From 507dc2b7ec30cf94554b441d4fcb1ce113f98a16 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 13:20:46 +0530 Subject: Create README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000000..14f89c2a245 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +rust-clippy +=========== + +A collection of lints that give helpful tips to newbies. -- cgit 1.4.1-3-g733a5 From 3a6010f8df35d21b7bd3d2cb47346b0aa75a3589 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 13:22:58 +0530 Subject: Create .gitignore --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..37727f91cbe --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Compiled files +*.o +*.so +*.rlib +*.dll + +# Executables +*.exe + +# Generated by Cargo +/target/ -- cgit 1.4.1-3-g733a5 From 37226273a7a5b2119daaab06d253f93b6813b881 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 13:23:40 +0530 Subject: init cargo --- Cargo.toml | 5 +++++ src/lib.rs | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000..f5f544af5c7 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[package] + +name = "rust-clippy" +version = "0.0.1" +authors = ["Manish Goregaokar "] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000000..a93251b65da --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +#[test] +fn it_works() { +} -- cgit 1.4.1-3-g733a5 From 92f13d823138ce3a22acef0db7818627ad5dee27 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 14:27:34 +0530 Subject: boxvec --- examples/boxvec.rs | 12 +++++++++++ src/lib.rs | 24 +++++++++++++++++++--- src/types.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 examples/boxvec.rs create mode 100644 src/types.rs diff --git a/examples/boxvec.rs b/examples/boxvec.rs new file mode 100644 index 00000000000..468da46f028 --- /dev/null +++ b/examples/boxvec.rs @@ -0,0 +1,12 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; + +pub fn test(foo: Box>) { + println!("{}", foo) +} + +fn main(){ + test(box Vec::new()); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a93251b65da..934232dceec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,21 @@ -#[test] -fn it_works() { -} +#![feature(globs, phase, plugin_registrar)] + + +#[phase(plugin,link)] +extern crate syntax; +#[phase(plugin, link)] +extern crate rustc; + + + +use rustc::plugin::Registry; +use rustc::lint::LintPassObject; + +pub mod types; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + //reg.register_syntax_extension(intern("jstraceable"), base::ItemDecorator(box expand_jstraceable)); + //reg.register_macro("factorial", expand) + reg.register_lint_pass(box types::TypePass as LintPassObject); +} \ No newline at end of file diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 00000000000..ffea017ec00 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,59 @@ + + +use syntax::ptr::P; +use syntax::ast; +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use syntax::codemap::Span; + + +pub struct TypePass; + +declare_lint!(CLIPPY_BOX_VEC, Warn, + "Warn on usage of Box>") + + +pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { + match ty.node { + TyPath(Path {segments: ref seg, ..}, _, _) => { + // So ast::Path isn't the full path, just the tokens that were provided. + // I could muck around with the maps and find the full path + // however the more efficient way is to simply reverse the iterators and zip them + // which will compare them in reverse until one of them runs out of segments + if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.as_str() == *b) { + match seg.as_slice().last() { + Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => { + Some(a.types.as_slice()) + } + _ => None + } + } else { + None + } + }, + _ => None + } +} + + +fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) { + cx.span_lint(lint, span, msg); + if cx.current_level(lint) != Level::Allow { + cx.sess().span_note(span, note); + } +} +impl LintPass for TypePass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_BOX_VEC) + } + + fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) { + match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.head()) + .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) + .map(|_| { + span_note_and_lint(cx, CLIPPY_BOX_VEC, ty.span, + "Detected Box>. Did you mean to use Vec?", + "Vec is already on the heap, Box> makes an extra allocation"); + }); + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 9341427b0ac71253395c8c177002a0c4e0bb274e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 14:32:47 +0530 Subject: docs --- src/types.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/types.rs b/src/types.rs index ffea017ec00..930223de770 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,13 +6,13 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use syntax::codemap::Span; - +/// Handles all the linting of funky types pub struct TypePass; declare_lint!(CLIPPY_BOX_VEC, Warn, "Warn on usage of Box>") - +/// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { match ty.node { TyPath(Path {segments: ref seg, ..}, _, _) => { @@ -35,13 +35,14 @@ pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> } } - -fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) { +/// Lets me span a note only if the lint is shown +pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) { cx.span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { cx.sess().span_note(span, note); } } + impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(CLIPPY_BOX_VEC) -- cgit 1.4.1-3-g733a5 From 767bd168c19b261ee0952a5ae9c2b0858234cf0a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Nov 2014 14:34:18 +0530 Subject: moar clippylike --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 930223de770..1b3c4f73c77 100644 --- a/src/types.rs +++ b/src/types.rs @@ -53,7 +53,7 @@ impl LintPass for TypePass { .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { span_note_and_lint(cx, CLIPPY_BOX_VEC, ty.span, - "Detected Box>. Did you mean to use Vec?", + "You seem to be trying to use Box>. Did you mean to use Vec?", "Vec is already on the heap, Box> makes an extra allocation"); }); } -- cgit 1.4.1-3-g733a5 From 871641030e7256f310a85c5ac41dd5c8959d74d3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 00:17:42 +0530 Subject: rn box_vec --- examples/box_vec.rs | 12 ++++++++++++ examples/boxvec.rs | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 examples/box_vec.rs delete mode 100644 examples/boxvec.rs diff --git a/examples/box_vec.rs b/examples/box_vec.rs new file mode 100644 index 00000000000..468da46f028 --- /dev/null +++ b/examples/box_vec.rs @@ -0,0 +1,12 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; + +pub fn test(foo: Box>) { + println!("{}", foo) +} + +fn main(){ + test(box Vec::new()); +} \ No newline at end of file diff --git a/examples/boxvec.rs b/examples/boxvec.rs deleted file mode 100644 index 468da46f028..00000000000 --- a/examples/boxvec.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(phase)] - -#[phase(plugin)] -extern crate rust_clippy; - -pub fn test(foo: Box>) { - println!("{}", foo) -} - -fn main(){ - test(box Vec::new()); -} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 542bfe357015e24504377c7347a8811797126ee3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 00:18:31 +0530 Subject: +match_if_let --- src/lib.rs | 7 ++++--- src/misc.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/misc.rs diff --git a/src/lib.rs b/src/lib.rs index 934232dceec..4528585c82c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ -#![feature(globs, phase, plugin_registrar)] +#![feature(globs, phase, plugin_registrar, if_let)] +#![allow(unused_imports)] #[phase(plugin,link)] extern crate syntax; @@ -12,10 +13,10 @@ use rustc::plugin::Registry; use rustc::lint::LintPassObject; pub mod types; +pub mod misc; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - //reg.register_syntax_extension(intern("jstraceable"), base::ItemDecorator(box expand_jstraceable)); - //reg.register_macro("factorial", expand) reg.register_lint_pass(box types::TypePass as LintPassObject); + reg.register_lint_pass(box misc::MiscPass as LintPassObject); } \ No newline at end of file diff --git a/src/misc.rs b/src/misc.rs new file mode 100644 index 00000000000..c70d4b48c1c --- /dev/null +++ b/src/misc.rs @@ -0,0 +1,46 @@ +use syntax::ptr::P; +use syntax::ast; +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use syntax::codemap::Span; + +use types::span_note_and_lint; + +/// Handles uncategorized lints +/// Currently handles linting of if-let-able matches +pub struct MiscPass; + + +declare_lint!(CLIPPY_SINGLE_MATCH, Warn, + "Warn on usage of matches with a single nontrivial arm") + +impl LintPass for MiscPass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_SINGLE_MATCH) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprMatch(ref ex, ref arms, MatchNormal) = expr.node { + if arms.len() == 2 { + if arms[0].guard.is_none() && arms[1].pats.len() == 1 { + match arms[1].body.node { + ExprTup(ref v) if v.len() == 0 && arms[1].guard.is_none() => (), + ExprBlock(ref b) if b.stmts.len() == 0 && arms[1].guard.is_none() => (), + _ => return + } + // In some cases, an exhaustive match is preferred to catch situations when + // an enum is extended. So we only consider cases where a `_` wildcard is used + if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { + let map = cx.sess().codemap(); + span_note_and_lint(cx, CLIPPY_SINGLE_MATCH, expr.span, + "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", + format!("Try if let {} = {} {{ ... }}", + map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), + map.span_to_snippet(ex.span).unwrap_or("..".to_string())).as_slice() + ); + } + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 883b8340683461d67b4653a83e8add6062246f91 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 00:18:41 +0530 Subject: Example for match_if_let --- examples/match_if_let.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 examples/match_if_let.rs diff --git a/examples/match_if_let.rs b/examples/match_if_let.rs new file mode 100644 index 00000000000..bdb6cc8ecfd --- /dev/null +++ b/examples/match_if_let.rs @@ -0,0 +1,23 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; + + +fn main(){ + let x = Some(1u); + match x { + Some(y) => println!("{}", y), + _ => () + } + // Not linted + match x { + Some(y) => println!("{}", y), + None => () + } + let z = (1u,1u); + match z { + (2...3, 7...9) => println!("{}", z), + _ => {} + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 7cf7e4368f689ac197c02cbf7e8014e122c5756e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 00:49:03 +0530 Subject: readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 14f89c2a245..7119c613166 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,11 @@ rust-clippy =========== A collection of lints that give helpful tips to newbies. + + +Lints included in this crate: + + - `clippy_single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. + - `clippy_box_vec`: Warns on usage of `Box>` + +More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! \ No newline at end of file -- cgit 1.4.1-3-g733a5 From ca7ad5fa805ee3e2ddd7181734ed0166fe168713 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 12:37:37 +0530 Subject: Add DList lint (fixes #2) --- src/lib.rs | 3 ++- src/types.rs | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4528585c82c..6166767378a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,8 @@ extern crate syntax; #[phase(plugin, link)] extern crate rustc; - +// Only for the compile time checking of paths +extern crate collections; use rustc::plugin::Registry; use rustc::lint::LintPassObject; diff --git a/src/types.rs b/src/types.rs index 1b3c4f73c77..625baec78fe 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,6 +11,8 @@ pub struct TypePass; declare_lint!(CLIPPY_BOX_VEC, Warn, "Warn on usage of Box>") +declare_lint!(CLIPPY_DLIST, Warn, + "Warn on usage of DList") /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { @@ -45,10 +47,15 @@ pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &s impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_BOX_VEC) + lint_array!(CLIPPY_BOX_VEC, CLIPPY_DLIST) } fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) { + { + // In case stuff gets moved around + use std::boxed::Box; + use std::vec::Vec; + } match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.head()) .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { @@ -56,5 +63,22 @@ impl LintPass for TypePass { "You seem to be trying to use Box>. Did you mean to use Vec?", "Vec is already on the heap, Box> makes an extra allocation"); }); + { + // In case stuff gets moved around + use collections::dlist::DList as DL1; + use std::collections::dlist::DList as DL2; + use std::collections::DList as DL3; + } + let dlists = [vec!["std","collections","dlist","DList"], + vec!["std","collections","DList"], + vec!["collections","dlist","DList"]]; + for path in dlists.iter() { + if match_ty_unwrap(ty, path.as_slice()).is_some() { + span_note_and_lint(cx, CLIPPY_DLIST, ty.span, + "You seem to be trying to use a DList. Perhaps you meant some other data structure?", + "A RingBuf might work."); + return; + } + } } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From ae635a60e64dcb7ba17be9c99693872d82dd8bb3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 12:37:45 +0530 Subject: add DList example --- examples/dlist.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/dlist.rs diff --git a/examples/dlist.rs b/examples/dlist.rs new file mode 100644 index 00000000000..91f3423fb44 --- /dev/null +++ b/examples/dlist.rs @@ -0,0 +1,14 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; +extern crate collections; +use collections::dlist::DList; + +pub fn test(foo: DList) { + println!("{}", foo) +} + +fn main(){ + test(DList::new()); +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 7bb411c239b219a063c065b744eec00dac11c6a4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 12:38:27 +0530 Subject: more clippylike (from issue title) --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 625baec78fe..36513339f74 100644 --- a/src/types.rs +++ b/src/types.rs @@ -75,7 +75,7 @@ impl LintPass for TypePass { for path in dlists.iter() { if match_ty_unwrap(ty, path.as_slice()).is_some() { span_note_and_lint(cx, CLIPPY_DLIST, ty.span, - "You seem to be trying to use a DList. Perhaps you meant some other data structure?", + "I see you're using a DList! Perhaps you meant some other data structure?", "A RingBuf might work."); return; } -- cgit 1.4.1-3-g733a5 From e9c08c4b12b715a2d680fd35d294227e373ed52d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 13:44:22 +0530 Subject: dlist readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7119c613166..cab6174ca30 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,6 @@ Lints included in this crate: - `clippy_single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. - `clippy_box_vec`: Warns on usage of `Box>` + - `clippy_dlist`: Warns on usage of `DList` More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 3a9fda7c7b0ef888298bffb71018e2a4dc26e877 Mon Sep 17 00:00:00 2001 From: Rohan Prinja Date: Thu, 4 Dec 2014 18:05:49 +0530 Subject: Path has only 2 fields now See also: https://github.com/phildawes/racer/pull/72 --- src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types.rs b/src/types.rs index 36513339f74..c3fd333a5b8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ declare_lint!(CLIPPY_DLIST, Warn, /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { match ty.node { - TyPath(Path {segments: ref seg, ..}, _, _) => { + TyPath(Path {segments: ref seg, ..}, _) => { // So ast::Path isn't the full path, just the tokens that were provided. // I could muck around with the maps and find the full path // however the more efficient way is to simply reverse the iterators and zip them @@ -81,4 +81,4 @@ impl LintPass for TypePass { } } } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 1e182b36fbe6c03482b07b94416d0e2045340c18 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 10 Dec 2014 12:21:55 +0530 Subject: Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cab6174ca30..0e04459bbd1 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,6 @@ Lints included in this crate: - `clippy_box_vec`: Warns on usage of `Box>` - `clippy_dlist`: Warns on usage of `DList` -More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! \ No newline at end of file +More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! + +Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 98d88e7eb415000160b9c3f9c96b1b1907f638cb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 11 Dec 2014 03:04:58 +0530 Subject: rm if_let gate --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6166767378a..380a530283c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(globs, phase, plugin_registrar, if_let)] +#![feature(globs, phase, plugin_registrar)] #![allow(unused_imports)] @@ -20,4 +20,4 @@ pub mod misc; pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 2703038f937f169090754c4b19ce7a3ddd457f05 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 15 Dec 2014 20:23:45 +0530 Subject: Add seanmonstar's StrToString lint --- README.md | 1 + src/lib.rs | 1 + src/misc.rs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/README.md b/README.md index 0e04459bbd1..91caaeba41a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Lints included in this crate: - `clippy_single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. - `clippy_box_vec`: Warns on usage of `Box>` - `clippy_dlist`: Warns on usage of `DList` + - `clippy_str_to_string`: Warns on usage of `str::to_string()` More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/lib.rs b/src/lib.rs index 380a530283c..386e8180c22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,4 +20,5 @@ pub mod misc; pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); + reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); } diff --git a/src/misc.rs b/src/misc.rs index c70d4b48c1c..2a77ecc3467 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -2,6 +2,7 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use rustc::middle::ty::{mod, expr_ty, ty_str, ty_ptr, ty_rptr}; use syntax::codemap::Span; use types::span_note_and_lint; @@ -44,3 +45,39 @@ impl LintPass for MiscPass { } } } + + +declare_lint!(CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()") + +pub struct StrToStringPass; + +impl LintPass for StrToStringPass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_STR_TO_STRING) + } + + fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { + match expr.node { + ast::ExprMethodCall(ref method, _, ref args) + if method.node.as_str() == "to_string" + && is_str(cx, &*args[0]) => { + cx.span_lint(CLIPPY_STR_TO_STRING, expr.span, "str.into_string() is faster"); + }, + _ => () + } + + fn is_str(cx: &Context, expr: &ast::Expr) -> bool { + fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { + //println!("{}: -> {}", depth, ty); + match ty.sty { + ty_ptr(ref tm) | ty_rptr(_, ref tm) => walk_ty(tm.ty), + _ => ty + } + } + match walk_ty(expr_ty(cx.tcx, expr)).sty { + ty_str => true, + _ => false + } + } + } +} -- cgit 1.4.1-3-g733a5 From 467b1ad9a44146e98fd86f6b0450c16d7b42468f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 19 Dec 2014 14:41:00 +0530 Subject: rustup --- src/misc.rs | 4 ++-- src/types.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 2a77ecc3467..68195994907 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -13,7 +13,7 @@ pub struct MiscPass; declare_lint!(CLIPPY_SINGLE_MATCH, Warn, - "Warn on usage of matches with a single nontrivial arm") + "Warn on usage of matches with a single nontrivial arm"); impl LintPass for MiscPass { fn get_lints(&self) -> LintArray { @@ -47,7 +47,7 @@ impl LintPass for MiscPass { } -declare_lint!(CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()") +declare_lint!(CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); pub struct StrToStringPass; diff --git a/src/types.rs b/src/types.rs index c3fd333a5b8..c418fdb7fe8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,9 +10,9 @@ use syntax::codemap::Span; pub struct TypePass; declare_lint!(CLIPPY_BOX_VEC, Warn, - "Warn on usage of Box>") + "Warn on usage of Box>"); declare_lint!(CLIPPY_DLIST, Warn, - "Warn on usage of DList") + "Warn on usage of DList"); /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { -- cgit 1.4.1-3-g733a5 From 2af7596f033cfd846bf4c73bea1f8a9adc62c511 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Dec 2014 04:43:56 +0530 Subject: dylib --- Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f5f544af5c7..e670b8f65a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,3 +3,8 @@ name = "rust-clippy" version = "0.0.1" authors = ["Manish Goregaokar "] + +[lib] +name = "rust_clippy" +crate_type = ["dylib"] + -- cgit 1.4.1-3-g733a5 From 1431fc04afe4e7cc2110fc9e9a59b0976b5e64ff Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 15:15:22 -0800 Subject: Implement a lint to check for args like `fn foo(ref x: u8)`, as the `ref` is effectively ignored by rustc. --- src/lib.rs | 5 +++-- src/misc.rs | 26 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 386e8180c22..9ac74eb2320 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ -#![feature(globs, phase, plugin_registrar)] +#![feature(globs, phase, plugin_registrar)] #![allow(unused_imports)] -#[phase(plugin,link)] +#[phase(plugin, link)] extern crate syntax; #[phase(plugin, link)] extern crate rustc; @@ -21,4 +21,5 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); + reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); } diff --git a/src/misc.rs b/src/misc.rs index 68195994907..47e8733abfb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,6 +1,7 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; +use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty::{mod, expr_ty, ty_str, ty_ptr, ty_rptr}; use syntax::codemap::Span; @@ -38,7 +39,7 @@ impl LintPass for MiscPass { format!("Try if let {} = {} {{ ... }}", map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), map.span_to_snippet(ex.span).unwrap_or("..".to_string())).as_slice() - ); + ); } } } @@ -81,3 +82,26 @@ impl LintPass for StrToStringPass { } } } + + +declare_lint!(CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); + +pub struct TopLevelRefPass; + +impl LintPass for TopLevelRefPass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_TOPLEVEL_REF_ARG) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + for ref arg in decl.inputs.iter() { + if let PatIdent(BindByRef(_), _, _) = arg.pat.node { + cx.span_lint( + CLIPPY_TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" + ); + } + } + } +} -- cgit 1.4.1-3-g733a5 From 8770f794674dd2af61159b4fef889e6257bfdd8b Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 17:48:03 -0800 Subject: Add an example of the toplevel_ref_arg lint. --- examples/toplevel_ref_arg.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/toplevel_ref_arg.rs diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs new file mode 100644 index 00000000000..0be737f9028 --- /dev/null +++ b/examples/toplevel_ref_arg.rs @@ -0,0 +1,14 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; + +fn the_answer(ref mut x: u8) { + *x = 42; +} + +fn main() { + let mut x = 0; + the_answer(x); + println!("The answer is {}.", x); +} -- cgit 1.4.1-3-g733a5 From a7d5048d48d54f691a10552a49e4b9bef89e89b0 Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 18:37:50 -0800 Subject: Update README.md for `clippy_toplevel_ref_arg`. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 91caaeba41a..3d5e366f56d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Lints included in this crate: - `clippy_box_vec`: Warns on usage of `Box>` - `clippy_dlist`: Warns on usage of `DList` - `clippy_str_to_string`: Warns on usage of `str::to_string()` + - `clippy_toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! -- cgit 1.4.1-3-g733a5 From 39481a521c626148b88385dca5197af8b07358e3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 26 Dec 2014 04:34:49 +0530 Subject: rustup (MatchSource rename, missing copy) --- src/misc.rs | 4 +++- src/types.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 68195994907..8c4fbe0597c 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -9,6 +9,7 @@ use types::span_note_and_lint; /// Handles uncategorized lints /// Currently handles linting of if-let-able matches +#[allow(missing_copy_implementations)] pub struct MiscPass; @@ -21,7 +22,7 @@ impl LintPass for MiscPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprMatch(ref ex, ref arms, MatchNormal) = expr.node { + if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { if arms.len() == 2 { if arms[0].guard.is_none() && arms[1].pats.len() == 1 { match arms[1].body.node { @@ -49,6 +50,7 @@ impl LintPass for MiscPass { declare_lint!(CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); +#[allow(missing_copy_implementations)] pub struct StrToStringPass; impl LintPass for StrToStringPass { diff --git a/src/types.rs b/src/types.rs index c418fdb7fe8..f2bedad56a2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,6 +7,7 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use syntax::codemap::Span; /// Handles all the linting of funky types +#[allow(missing_copy_implementations)] pub struct TypePass; declare_lint!(CLIPPY_BOX_VEC, Warn, -- cgit 1.4.1-3-g733a5 From 32d060ae1134d05738824019dc79c29225b32308 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 26 Dec 2014 04:52:18 +0530 Subject: more rustup --- src/misc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/misc.rs b/src/misc.rs index c72f39ba315..4fb0a159a8b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -88,6 +88,7 @@ impl LintPass for StrToStringPass { declare_lint!(CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); +#[allow(missing_copy_implementations)] pub struct TopLevelRefPass; impl LintPass for TopLevelRefPass { -- cgit 1.4.1-3-g733a5 From ccf996c348a9b591aad7f0b484dd02ac15a37b43 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 26 Dec 2014 05:12:05 +0530 Subject: clippy lint group --- src/lib.rs | 3 +++ src/misc.rs | 6 +++--- src/types.rs | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9ac74eb2320..a70327c468b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,4 +22,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); + reg.register_lint_group("clippy", vec![types::CLIPPY_BOX_VEC, types::CLIPPY_DLIST, + misc::CLIPPY_SINGLE_MATCH, misc::CLIPPY_STR_TO_STRING, + misc::CLIPPY_TOPLEVEL_REF_ARG]); } diff --git a/src/misc.rs b/src/misc.rs index 4fb0a159a8b..77520e02da7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -14,7 +14,7 @@ use types::span_note_and_lint; pub struct MiscPass; -declare_lint!(CLIPPY_SINGLE_MATCH, Warn, +declare_lint!(pub CLIPPY_SINGLE_MATCH, Warn, "Warn on usage of matches with a single nontrivial arm"); impl LintPass for MiscPass { @@ -49,7 +49,7 @@ impl LintPass for MiscPass { } -declare_lint!(CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); +declare_lint!(pub CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); #[allow(missing_copy_implementations)] pub struct StrToStringPass; @@ -86,7 +86,7 @@ impl LintPass for StrToStringPass { } -declare_lint!(CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); +declare_lint!(pub CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); #[allow(missing_copy_implementations)] pub struct TopLevelRefPass; diff --git a/src/types.rs b/src/types.rs index f2bedad56a2..c189e1c389c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,9 +10,9 @@ use syntax::codemap::Span; #[allow(missing_copy_implementations)] pub struct TypePass; -declare_lint!(CLIPPY_BOX_VEC, Warn, +declare_lint!(pub CLIPPY_BOX_VEC, Warn, "Warn on usage of Box>"); -declare_lint!(CLIPPY_DLIST, Warn, +declare_lint!(pub CLIPPY_DLIST, Warn, "Warn on usage of DList"); /// Matches a type with a provided string, and returns its type parameters if successful -- cgit 1.4.1-3-g733a5 From e57396bc5212137b95e29664917f4383f8ca123f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 26 Dec 2014 05:24:44 +0530 Subject: Remove namespacing --- src/lib.rs | 6 +++--- src/misc.rs | 18 +++++++++--------- src/types.rs | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a70327c468b..3b556ff2c63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); - reg.register_lint_group("clippy", vec![types::CLIPPY_BOX_VEC, types::CLIPPY_DLIST, - misc::CLIPPY_SINGLE_MATCH, misc::CLIPPY_STR_TO_STRING, - misc::CLIPPY_TOPLEVEL_REF_ARG]); + reg.register_lint_group("clippy", vec![types::BOX_VEC, types::DLIST, + misc::SINGLE_MATCH, misc::STR_TO_STRING, + misc::TOPLEVEL_REF_ARG]); } diff --git a/src/misc.rs b/src/misc.rs index 77520e02da7..d69a7db0f55 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -14,12 +14,12 @@ use types::span_note_and_lint; pub struct MiscPass; -declare_lint!(pub CLIPPY_SINGLE_MATCH, Warn, +declare_lint!(pub SINGLE_MATCH, Warn, "Warn on usage of matches with a single nontrivial arm"); impl LintPass for MiscPass { fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_SINGLE_MATCH) + lint_array!(SINGLE_MATCH) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -35,7 +35,7 @@ impl LintPass for MiscPass { // an enum is extended. So we only consider cases where a `_` wildcard is used if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { let map = cx.sess().codemap(); - span_note_and_lint(cx, CLIPPY_SINGLE_MATCH, expr.span, + span_note_and_lint(cx, SINGLE_MATCH, expr.span, "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", format!("Try if let {} = {} {{ ... }}", map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), @@ -49,14 +49,14 @@ impl LintPass for MiscPass { } -declare_lint!(pub CLIPPY_STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); +declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); #[allow(missing_copy_implementations)] pub struct StrToStringPass; impl LintPass for StrToStringPass { fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_STR_TO_STRING) + lint_array!(STR_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { @@ -64,7 +64,7 @@ impl LintPass for StrToStringPass { ast::ExprMethodCall(ref method, _, ref args) if method.node.as_str() == "to_string" && is_str(cx, &*args[0]) => { - cx.span_lint(CLIPPY_STR_TO_STRING, expr.span, "str.into_string() is faster"); + cx.span_lint(STR_TO_STRING, expr.span, "str.into_string() is faster"); }, _ => () } @@ -86,21 +86,21 @@ impl LintPass for StrToStringPass { } -declare_lint!(pub CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); +declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); #[allow(missing_copy_implementations)] pub struct TopLevelRefPass; impl LintPass for TopLevelRefPass { fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_TOPLEVEL_REF_ARG) + lint_array!(TOPLEVEL_REF_ARG) } fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { for ref arg in decl.inputs.iter() { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { cx.span_lint( - CLIPPY_TOPLEVEL_REF_ARG, + TOPLEVEL_REF_ARG, arg.pat.span, "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" ); diff --git a/src/types.rs b/src/types.rs index c189e1c389c..8754c1348b1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,9 +10,9 @@ use syntax::codemap::Span; #[allow(missing_copy_implementations)] pub struct TypePass; -declare_lint!(pub CLIPPY_BOX_VEC, Warn, +declare_lint!(pub BOX_VEC, Warn, "Warn on usage of Box>"); -declare_lint!(pub CLIPPY_DLIST, Warn, +declare_lint!(pub DLIST, Warn, "Warn on usage of DList"); /// Matches a type with a provided string, and returns its type parameters if successful @@ -48,7 +48,7 @@ pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &s impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_BOX_VEC, CLIPPY_DLIST) + lint_array!(BOX_VEC, DLIST) } fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) { @@ -60,7 +60,7 @@ impl LintPass for TypePass { match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.head()) .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { - span_note_and_lint(cx, CLIPPY_BOX_VEC, ty.span, + span_note_and_lint(cx, BOX_VEC, ty.span, "You seem to be trying to use Box>. Did you mean to use Vec?", "Vec is already on the heap, Box> makes an extra allocation"); }); @@ -75,7 +75,7 @@ impl LintPass for TypePass { vec!["collections","dlist","DList"]]; for path in dlists.iter() { if match_ty_unwrap(ty, path.as_slice()).is_some() { - span_note_and_lint(cx, CLIPPY_DLIST, ty.span, + span_note_and_lint(cx, DLIST, ty.span, "I see you're using a DList! Perhaps you meant some other data structure?", "A RingBuf might work."); return; -- cgit 1.4.1-3-g733a5 From a8aadc7376186d181bbed1bfaefc0307e02c158e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 26 Dec 2014 05:30:03 +0530 Subject: rust_clippy -> clippy --- Cargo.toml | 4 ++-- examples/box_vec.rs | 2 +- examples/dlist.rs | 2 +- examples/match_if_let.rs | 2 +- examples/toplevel_ref_arg.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e670b8f65a4..57133c142c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "rust-clippy" +name = "clippy" version = "0.0.1" authors = ["Manish Goregaokar "] [lib] -name = "rust_clippy" +name = "clippy" crate_type = ["dylib"] diff --git a/examples/box_vec.rs b/examples/box_vec.rs index 468da46f028..acc47dd0fb5 100644 --- a/examples/box_vec.rs +++ b/examples/box_vec.rs @@ -1,7 +1,7 @@ #![feature(phase)] #[phase(plugin)] -extern crate rust_clippy; +extern crate clippy; pub fn test(foo: Box>) { println!("{}", foo) diff --git a/examples/dlist.rs b/examples/dlist.rs index 91f3423fb44..9efa92fd63a 100644 --- a/examples/dlist.rs +++ b/examples/dlist.rs @@ -1,7 +1,7 @@ #![feature(phase)] #[phase(plugin)] -extern crate rust_clippy; +extern crate clippy; extern crate collections; use collections::dlist::DList; diff --git a/examples/match_if_let.rs b/examples/match_if_let.rs index bdb6cc8ecfd..b437424101d 100644 --- a/examples/match_if_let.rs +++ b/examples/match_if_let.rs @@ -1,7 +1,7 @@ #![feature(phase)] #[phase(plugin)] -extern crate rust_clippy; +extern crate clippy; fn main(){ diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs index 0be737f9028..4180ccce9aa 100644 --- a/examples/toplevel_ref_arg.rs +++ b/examples/toplevel_ref_arg.rs @@ -1,7 +1,7 @@ #![feature(phase)] #[phase(plugin)] -extern crate rust_clippy; +extern crate clippy; fn the_answer(ref mut x: u8) { *x = 42; -- cgit 1.4.1-3-g733a5 From 433c834897c1e10f074060ac768ca5bd377138b2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 28 Dec 2014 20:12:48 +0530 Subject: more readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3d5e366f56d..12f7557a8d4 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ Lints included in this crate: - `clippy_str_to_string`: Warns on usage of `str::to_string()` - `clippy_toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). +You can allow/warn/deny the whole set using the `clippy` lint group (`#[allow(clippy)]`, etc) + + More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From b7ecb6e7c72e00fe377560baf3c971b7457219d4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 7 Jan 2015 09:35:34 +0530 Subject: rustup --- src/misc.rs | 2 +- src/types.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index d69a7db0f55..763c78bf278 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax::ast::*; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{mod, expr_ty, ty_str, ty_ptr, ty_rptr}; +use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr}; use syntax::codemap::Span; use types::span_note_and_lint; diff --git a/src/types.rs b/src/types.rs index 8754c1348b1..17f030c950f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -57,7 +57,7 @@ impl LintPass for TypePass { use std::boxed::Box; use std::vec::Vec; } - match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.head()) + match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first()) .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { span_note_and_lint(cx, BOX_VEC, ty.span, -- cgit 1.4.1-3-g733a5 From 538db34e6028b89425a9d59e55d65d7ac6f1c556 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 10 Jan 2015 10:52:03 +0530 Subject: into_string() -> to_owned() (fix #27) --- src/misc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 763c78bf278..3fb88e431da 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -49,7 +49,7 @@ impl LintPass for MiscPass { } -declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use into_string() instead of to_string()"); +declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use to_owned() instead of to_string()"); #[allow(missing_copy_implementations)] pub struct StrToStringPass; @@ -64,7 +64,7 @@ impl LintPass for StrToStringPass { ast::ExprMethodCall(ref method, _, ref args) if method.node.as_str() == "to_string" && is_str(cx, &*args[0]) => { - cx.span_lint(STR_TO_STRING, expr.span, "str.into_string() is faster"); + cx.span_lint(STR_TO_STRING, expr.span, "str.to_owned() is faster"); }, _ => () } -- cgit 1.4.1-3-g733a5 From f428b18c47b1bf5385fd5178081df8abc4a2abe8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 10 Jan 2015 11:56:58 +0530 Subject: rustup (fixes #28) --- examples/box_vec.rs | 10 +++++----- examples/dlist.rs | 7 ++++--- examples/match_if_let.rs | 11 +++++------ examples/toplevel_ref_arg.rs | 4 ++-- src/lib.rs | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/box_vec.rs b/examples/box_vec.rs index acc47dd0fb5..874b9e8663c 100644 --- a/examples/box_vec.rs +++ b/examples/box_vec.rs @@ -1,12 +1,12 @@ -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] extern crate clippy; -pub fn test(foo: Box>) { - println!("{}", foo) +pub fn test(foo: Box>) { + println!("{:?}", foo.get(0)) } fn main(){ - test(box Vec::new()); + test(Box::new(Vec::new())); } \ No newline at end of file diff --git a/examples/dlist.rs b/examples/dlist.rs index 9efa92fd63a..05b71eabdcc 100644 --- a/examples/dlist.rs +++ b/examples/dlist.rs @@ -1,12 +1,13 @@ -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] extern crate clippy; + extern crate collections; use collections::dlist::DList; pub fn test(foo: DList) { - println!("{}", foo) + println!("{:?}", foo) } fn main(){ diff --git a/examples/match_if_let.rs b/examples/match_if_let.rs index b437424101d..5de96dd9951 100644 --- a/examples/match_if_let.rs +++ b/examples/match_if_let.rs @@ -1,23 +1,22 @@ -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] extern crate clippy; - fn main(){ let x = Some(1u); match x { - Some(y) => println!("{}", y), + Some(y) => println!("{:?}", y), _ => () } // Not linted match x { - Some(y) => println!("{}", y), + Some(y) => println!("{:?}", y), None => () } let z = (1u,1u); match z { - (2...3, 7...9) => println!("{}", z), + (2...3, 7...9) => println!("{:?}", z), _ => {} } } \ No newline at end of file diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs index 4180ccce9aa..538e377c74f 100644 --- a/examples/toplevel_ref_arg.rs +++ b/examples/toplevel_ref_arg.rs @@ -1,6 +1,6 @@ -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] extern crate clippy; fn the_answer(ref mut x: u8) { diff --git a/src/lib.rs b/src/lib.rs index 3b556ff2c63..da79e5ce9e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,10 @@ -#![feature(globs, phase, plugin_registrar)] +#![feature(plugin_registrar, box_syntax)] -#![allow(unused_imports)] +#![allow(unused_imports, unstable)] -#[phase(plugin, link)] +#[macro_use] extern crate syntax; -#[phase(plugin, link)] +#[macro_use] extern crate rustc; // Only for the compile time checking of paths -- cgit 1.4.1-3-g733a5 From 67701e00629ff2a0bb5a3b75628d23e102a95348 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 18 Feb 2015 17:54:22 +0530 Subject: -warnings --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index da79e5ce9e5..36802d1a329 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![feature(plugin_registrar, box_syntax)] +#![feature(rustc_private, core, collections)] -#![allow(unused_imports, unstable)] +#![allow(unused_imports)] #[macro_use] extern crate syntax; -- cgit 1.4.1-3-g733a5 From 426a3ee1e7a9832d9f3cd1ac0aba0bcf5a3caa0d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 2 Mar 2015 16:13:44 +0530 Subject: Rustup --- examples/box_vec.rs | 3 +-- examples/dlist.rs | 9 ++++----- examples/match_if_let.rs | 5 ++--- examples/toplevel_ref_arg.rs | 3 +-- src/lib.rs | 2 +- src/types.rs | 22 +++++++++++----------- 6 files changed, 20 insertions(+), 24 deletions(-) diff --git a/examples/box_vec.rs b/examples/box_vec.rs index 874b9e8663c..a93b53270bd 100644 --- a/examples/box_vec.rs +++ b/examples/box_vec.rs @@ -1,7 +1,6 @@ #![feature(plugin)] -#[plugin] -extern crate clippy; +#![plugin(clippy)] pub fn test(foo: Box>) { println!("{:?}", foo.get(0)) diff --git a/examples/dlist.rs b/examples/dlist.rs index 05b71eabdcc..d4c543b8e9f 100644 --- a/examples/dlist.rs +++ b/examples/dlist.rs @@ -1,15 +1,14 @@ #![feature(plugin)] -#[plugin] -extern crate clippy; +#![plugin(clippy)] extern crate collections; -use collections::dlist::DList; +use collections::linked_list::LinkedList; -pub fn test(foo: DList) { +pub fn test(foo: LinkedList) { println!("{:?}", foo) } fn main(){ - test(DList::new()); + test(LinkedList::new()); } \ No newline at end of file diff --git a/examples/match_if_let.rs b/examples/match_if_let.rs index 5de96dd9951..255bea7d73f 100644 --- a/examples/match_if_let.rs +++ b/examples/match_if_let.rs @@ -1,7 +1,6 @@ #![feature(plugin)] -#[plugin] -extern crate clippy; +#![plugin(clippy)] fn main(){ let x = Some(1u); @@ -19,4 +18,4 @@ fn main(){ (2...3, 7...9) => println!("{:?}", z), _ => {} } -} \ No newline at end of file +} diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs index 538e377c74f..3ebb354142a 100644 --- a/examples/toplevel_ref_arg.rs +++ b/examples/toplevel_ref_arg.rs @@ -1,7 +1,6 @@ #![feature(plugin)] -#[plugin] -extern crate clippy; +#![plugin(clippy)] fn the_answer(ref mut x: u8) { *x = 42; diff --git a/src/lib.rs b/src/lib.rs index 36802d1a329..b3f395e5a13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); - reg.register_lint_group("clippy", vec![types::BOX_VEC, types::DLIST, + reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG]); } diff --git a/src/types.rs b/src/types.rs index 17f030c950f..dceae401a2e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -12,8 +12,8 @@ pub struct TypePass; declare_lint!(pub BOX_VEC, Warn, "Warn on usage of Box>"); -declare_lint!(pub DLIST, Warn, - "Warn on usage of DList"); +declare_lint!(pub LINKEDLIST, Warn, + "Warn on usage of LinkedList"); /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { @@ -48,7 +48,7 @@ pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &s impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, DLIST) + lint_array!(BOX_VEC, LINKEDLIST) } fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) { @@ -66,17 +66,17 @@ impl LintPass for TypePass { }); { // In case stuff gets moved around - use collections::dlist::DList as DL1; - use std::collections::dlist::DList as DL2; - use std::collections::DList as DL3; + use collections::linked_list::LinkedList as DL1; + use std::collections::linked_list::LinkedList as DL2; + use std::collections::linked_list::LinkedList as DL3; } - let dlists = [vec!["std","collections","dlist","DList"], - vec!["std","collections","DList"], - vec!["collections","dlist","DList"]]; + let dlists = [vec!["std","collections","linked_list","LinkedList"], + vec!["std","collections","linked_list","LinkedList"], + vec!["collections","linked_list","LinkedList"]]; for path in dlists.iter() { if match_ty_unwrap(ty, path.as_slice()).is_some() { - span_note_and_lint(cx, DLIST, ty.span, - "I see you're using a DList! Perhaps you meant some other data structure?", + span_note_and_lint(cx, LINKEDLIST, ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", "A RingBuf might work."); return; } -- cgit 1.4.1-3-g733a5 From 2756ebe056e03aa38ef6048d800d035d13e61c5c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 13 Apr 2015 23:14:45 +0530 Subject: rustup --- src/types.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/types.rs b/src/types.rs index dceae401a2e..c966c49be85 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,15 +18,15 @@ declare_lint!(pub LINKEDLIST, Warn, /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P]> { match ty.node { - TyPath(Path {segments: ref seg, ..}, _) => { + TyPath(_, Path {segments: ref seg, ..}) => { // So ast::Path isn't the full path, just the tokens that were provided. // I could muck around with the maps and find the full path // however the more efficient way is to simply reverse the iterators and zip them // which will compare them in reverse until one of them runs out of segments if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.as_str() == *b) { - match seg.as_slice().last() { + match seg[..].last() { Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => { - Some(a.types.as_slice()) + Some(&a.types[..]) } _ => None } @@ -74,7 +74,7 @@ impl LintPass for TypePass { vec!["std","collections","linked_list","LinkedList"], vec!["collections","linked_list","LinkedList"]]; for path in dlists.iter() { - if match_ty_unwrap(ty, path.as_slice()).is_some() { + if match_ty_unwrap(ty, &path[..]).is_some() { span_note_and_lint(cx, LINKEDLIST, ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", "A RingBuf might work."); -- cgit 1.4.1-3-g733a5 From a5c31025940c8323495fbbdb5f690dcacd227458 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 13 Apr 2015 23:28:18 +0530 Subject: Use compiletest --- Cargo.toml | 4 ++++ examples/box_vec.rs | 11 ----------- examples/dlist.rs | 14 -------------- examples/match_if_let.rs | 21 --------------------- examples/toplevel_ref_arg.rs | 13 ------------- tests/compile-fail/box_vec.rs | 12 ++++++++++++ tests/compile-fail/dlist.rs | 15 +++++++++++++++ tests/compile-fail/match_if_let.rs | 24 ++++++++++++++++++++++++ tests/compile-fail/toplevel_ref_arg.rs | 15 +++++++++++++++ tests/compile-test.rs | 23 +++++++++++++++++++++++ 10 files changed, 93 insertions(+), 59 deletions(-) delete mode 100644 examples/box_vec.rs delete mode 100644 examples/dlist.rs delete mode 100644 examples/match_if_let.rs delete mode 100644 examples/toplevel_ref_arg.rs create mode 100644 tests/compile-fail/box_vec.rs create mode 100644 tests/compile-fail/dlist.rs create mode 100644 tests/compile-fail/match_if_let.rs create mode 100644 tests/compile-fail/toplevel_ref_arg.rs create mode 100644 tests/compile-test.rs diff --git a/Cargo.toml b/Cargo.toml index 57133c142c8..6a599adcc46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,7 @@ authors = ["Manish Goregaokar "] name = "clippy" crate_type = ["dylib"] + + +[dev-dependencies.compiletest] +git = "https://github.com/laumann/compiletest-rs.git" diff --git a/examples/box_vec.rs b/examples/box_vec.rs deleted file mode 100644 index a93b53270bd..00000000000 --- a/examples/box_vec.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(plugin)] - -#![plugin(clippy)] - -pub fn test(foo: Box>) { - println!("{:?}", foo.get(0)) -} - -fn main(){ - test(Box::new(Vec::new())); -} \ No newline at end of file diff --git a/examples/dlist.rs b/examples/dlist.rs deleted file mode 100644 index d4c543b8e9f..00000000000 --- a/examples/dlist.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(plugin)] - -#![plugin(clippy)] - -extern crate collections; -use collections::linked_list::LinkedList; - -pub fn test(foo: LinkedList) { - println!("{:?}", foo) -} - -fn main(){ - test(LinkedList::new()); -} \ No newline at end of file diff --git a/examples/match_if_let.rs b/examples/match_if_let.rs deleted file mode 100644 index 255bea7d73f..00000000000 --- a/examples/match_if_let.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(plugin)] - -#![plugin(clippy)] - -fn main(){ - let x = Some(1u); - match x { - Some(y) => println!("{:?}", y), - _ => () - } - // Not linted - match x { - Some(y) => println!("{:?}", y), - None => () - } - let z = (1u,1u); - match z { - (2...3, 7...9) => println!("{:?}", z), - _ => {} - } -} diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs deleted file mode 100644 index 3ebb354142a..00000000000 --- a/examples/toplevel_ref_arg.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(plugin)] - -#![plugin(clippy)] - -fn the_answer(ref mut x: u8) { - *x = 42; -} - -fn main() { - let mut x = 0; - the_answer(x); - println!("The answer is {}.", x); -} diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs new file mode 100644 index 00000000000..cd1270b2373 --- /dev/null +++ b/tests/compile-fail/box_vec.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] + +pub fn test(foo: Box>) { //~ ERROR You seem to be trying to use Box> + println!("{:?}", foo.get(0)) +} + +fn main(){ + test(Box::new(Vec::new())); +} \ No newline at end of file diff --git a/tests/compile-fail/dlist.rs b/tests/compile-fail/dlist.rs new file mode 100644 index 00000000000..a2343c339ad --- /dev/null +++ b/tests/compile-fail/dlist.rs @@ -0,0 +1,15 @@ +#![feature(plugin, collections)] + +#![plugin(clippy)] +#![deny(clippy)] + +extern crate collections; +use collections::linked_list::LinkedList; + +pub fn test(foo: LinkedList) { //~ ERROR I see you're using a LinkedList! + println!("{:?}", foo) +} + +fn main(){ + test(LinkedList::new()); +} \ No newline at end of file diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs new file mode 100644 index 00000000000..b03c6e1140a --- /dev/null +++ b/tests/compile-fail/match_if_let.rs @@ -0,0 +1,24 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] + +fn main(){ + let x = Some(1u8); + match x { //~ ERROR You seem to be trying to use match + //~^ NOTE Try if let Some(y) = x { ... } + Some(y) => println!("{:?}", y), + _ => () + } + // Not linted + match x { + Some(y) => println!("{:?}", y), + None => () + } + let z = (1u8,1u8); + match z { //~ ERROR You seem to be trying to use match + //~^ NOTE Try if let (2...3, 7...9) = z { ... } + (2...3, 7...9) => println!("{:?}", z), + _ => {} + } +} diff --git a/tests/compile-fail/toplevel_ref_arg.rs b/tests/compile-fail/toplevel_ref_arg.rs new file mode 100644 index 00000000000..cd4d46ee327 --- /dev/null +++ b/tests/compile-fail/toplevel_ref_arg.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] +#![allow(unused)] + +fn the_answer(ref mut x: u8) { //~ ERROR `ref` directly on a function argument is ignored + *x = 42; +} + +fn main() { + let mut x = 0; + the_answer(x); + println!("The answer is {}.", x); +} diff --git a/tests/compile-test.rs b/tests/compile-test.rs new file mode 100644 index 00000000000..3fd219dfb44 --- /dev/null +++ b/tests/compile-test.rs @@ -0,0 +1,23 @@ +extern crate compiletest; + +use std::env; +use std::process::Command; +use std::path::PathBuf; + +fn run_mode(mode: &'static str) { + + let mut config = compiletest::default_config(); + let cfg_mode = mode.parse().ok().expect("Invalid mode"); + config.target_rustcflags = Some("-L target/debug/".to_string()); + + config.mode = cfg_mode; + config.src_base = PathBuf::from(format!("tests/{}", mode)); + + compiletest::run_tests(&config); +} + +#[test] +fn compile_test() { + run_mode("compile-fail"); + // run_mode("run-pass"); +} -- cgit 1.4.1-3-g733a5 From ab65383f64e3318fdf54516e3b55ccd16881d23c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 14 Apr 2015 00:21:16 +0530 Subject: travisify --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..4b9789d2618 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: rust +sudo: false + +script: + - cargo build + - cargo test -- cgit 1.4.1-3-g733a5 From 2935c31692b49e5b2ffde2d33427a90be336eba6 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 20 Apr 2015 16:18:35 +0530 Subject: rustup (rustc 1.0.0-nightly (00978a987 2015-04-18) (built 2015-04-19)) --- src/lib.rs | 2 +- src/misc.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b3f395e5a13..ee137230f5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![feature(plugin_registrar, box_syntax)] -#![feature(rustc_private, core, collections)] +#![feature(rustc_private, collections)] #![allow(unused_imports)] diff --git a/src/misc.rs b/src/misc.rs index 3fb88e431da..04accaaa8bc 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -37,9 +37,9 @@ impl LintPass for MiscPass { let map = cx.sess().codemap(); span_note_and_lint(cx, SINGLE_MATCH, expr.span, "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", - format!("Try if let {} = {} {{ ... }}", - map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), - map.span_to_snippet(ex.span).unwrap_or("..".to_string())).as_slice() + &*format!("Try if let {} = {} {{ ... }}", + &*map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), + &*map.span_to_snippet(ex.span).unwrap_or("..".to_string())) ); } } -- cgit 1.4.1-3-g733a5 From 441b55b328220cf02b0f7b2cb7a6e0f3e752aa56 Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 30 Apr 2015 11:48:43 +0200 Subject: Added eq_op and bad_bit_mask from the extra_lints project (mostly plain copy, need to refactor to integrate better) --- Cargo.toml | 8 +- README.md | 14 +-- src/bit_mask.rs | 111 +++++++++++++++++++++ src/eq_op.rs | 214 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 7 +- tests/compile-fail/bit_masks.rs | 19 ++++ tests/compile-fail/eq_op.rs | 36 +++++++ tests/compile-test.rs | 4 - 8 files changed, 398 insertions(+), 15 deletions(-) create mode 100644 src/bit_mask.rs create mode 100644 src/eq_op.rs create mode 100644 tests/compile-fail/bit_masks.rs create mode 100644 tests/compile-fail/eq_op.rs diff --git a/Cargo.toml b/Cargo.toml index 6a599adcc46..27ff93982b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,14 @@ [package] - name = "clippy" version = "0.0.1" -authors = ["Manish Goregaokar "] +authors = [ + "Manish Goregaokar ", + "Andre Bogus " +] [lib] name = "clippy" crate_type = ["dylib"] - - [dev-dependencies.compiletest] git = "https://github.com/laumann/compiletest-rs.git" diff --git a/README.md b/README.md index 12f7557a8d4..577de498dab 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ rust-clippy =========== -A collection of lints that give helpful tips to newbies. +A collection of lints that give helpful tips to newbies and catch oversights. Lints included in this crate: - - `clippy_single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. - - `clippy_box_vec`: Warns on usage of `Box>` - - `clippy_dlist`: Warns on usage of `DList` - - `clippy_str_to_string`: Warns on usage of `str::to_string()` - - `clippy_toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). + - `single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. + - `box_vec`: Warns on usage of `Box>` + - `dlist`: Warns on usage of `DList` + - `str_to_string`: Warns on usage of `str::to_string()` + - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). + - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination + - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) You can allow/warn/deny the whole set using the `clippy` lint group (`#[allow(clippy)]`, etc) diff --git a/src/bit_mask.rs b/src/bit_mask.rs new file mode 100644 index 00000000000..313bfb1ac0b --- /dev/null +++ b/src/bit_mask.rs @@ -0,0 +1,111 @@ +//! Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. This cannot work because the bit that makes up +//! the value two was zeroed out by the bit-and with 1. So the formula for detecting if an expression of the type +//! `_ m c` (where `` is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` ,`!=`, `>=`, +//! `>`}) can be determined from the following table: +//! +//! |Comparison |Bit-Op|Example |is always|Formula | +//! |------------|------|------------|---------|----------------------| +//! |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +//! |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +//! |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +//! |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +//! |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +//! |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +//! +//! *TODO*: There is the open question if things like `x | 1 > 1` should be caught by this lint, because it is basically +//! an obfuscated version of `x > 1`. +//! +//! This lint is **deny** by default + +use rustc::plugin::Registry; +use rustc::lint::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; + +declare_lint! { + pub BAD_BIT_MASK, + Deny, + "Deny the use of incompatible bit masks in comparisons, e.g. '(a & 1) == 2'" +} + +#[derive(Copy,Clone)] +pub struct BitMask; + +impl LintPass for BitMask { + fn get_lints(&self) -> LintArray { + lint_array!(BAD_BIT_MASK) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + if is_comparison_binop(cmp.node) { + fetch_int_literal(&right.node).map(|cmp_value| check_compare(cx, left, cmp.node, cmp_value, &e.span)); + } + } + } +} + +fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { + match &bit_op.node { + &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), + &ExprBinary(ref op, ref left, ref right) => { + if op.node != BiBitAnd && op.node != BiBitOr { return; } + if let Some(mask_value) = fetch_int_literal(&right.node) { + check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); + } else if let Some(mask_value) = fetch_int_literal(&left.node) { + check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); + } + }, + _ => () + } +} + +fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { + match cmp_op { + BiEq | BiNe => match bit_op { + BiBitAnd => if mask_value & cmp_value != mask_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} can never be equal to {}", mask_value, + cmp_value)); + }, + BiBitOr => if mask_value | cmp_value != cmp_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} can never be equal to {}", mask_value, + cmp_value)); + }, + _ => () + }, + BiLt | BiGe => match bit_op { + BiBitAnd => if mask_value < cmp_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will always be lower than {}", mask_value, + cmp_value)); + }, + BiBitOr => if mask_value >= cmp_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will never be lower than {}", mask_value, + cmp_value)); + }, + _ => () + }, + BiLe | BiGt => match bit_op { + BiBitAnd => if mask_value <= cmp_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will never be higher than {}", mask_value, + cmp_value)); + }, + BiBitOr => if mask_value > cmp_value { + cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will always be higher than {}", mask_value, + cmp_value)); + }, + _ => () + }, + _ => () + } +} + +fn fetch_int_literal(lit : &Expr_) -> Option { + if let &ExprLit(ref lit_ptr) = lit { + if let &LitInt(value, _) = &lit_ptr.node { + return Option::Some(value); //TODO: Handle sign + } + } + Option::None +} diff --git a/src/eq_op.rs b/src/eq_op.rs new file mode 100644 index 00000000000..e0b722a0a18 --- /dev/null +++ b/src/eq_op.rs @@ -0,0 +1,214 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::ast_util as ast_util; +use syntax::ptr::P; +use syntax::codemap as code; + +declare_lint! { + pub EQ_OP, + Warn, + "warn about comparing equal expressions (e.g. x == x)" +} + +#[derive(Copy,Clone)] +pub struct EqOp; + +impl LintPass for EqOp { + fn get_lints(&self) -> LintArray { + lint_array!(EQ_OP) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let ExprBinary(ref op, ref left, ref right) = e.node { + if is_cmp_or_bit(op) && is_exp_equal(left, right) { + cx.span_lint(EQ_OP, e.span, &format!("equal expressions as operands to {}", ast_util::binop_to_string(op.node))); + } + } + } +} + +fn is_exp_equal(left : &Expr, right : &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => + lop.node == rop.node && is_exp_equal(ll, rl) && is_exp_equal(lr, rr), + (&ExprBox(ref lpl, ref lboxedpl), &ExprBox(ref rpl, ref rboxedpl)) => + both(lpl, rpl, |l, r| is_exp_equal(l, r)) && is_exp_equal(lboxedpl, rboxedpl), + (&ExprCall(ref lcallee, ref largs), &ExprCall(ref rcallee, ref rargs)) => + is_exp_equal(lcallee, rcallee) && is_exp_vec_equal(largs, rargs), + (&ExprCast(ref lcast, ref lty), &ExprCast(ref rcast, ref rty)) => + is_ty_equal(lty, rty) && is_exp_equal(lcast, rcast), + (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => + lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), + (&ExprLit(ref llit), &ExprLit(ref rlit)) => llit.node == rlit.node, + (&ExprMethodCall(ref lident, ref lcty, ref lmargs), &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => + lident.node == rident.node && is_ty_vec_equal(lcty, rcty) && is_exp_vec_equal(lmargs, rmargs), + (&ExprParen(ref lparen), &ExprParen(ref rparen)) => is_exp_equal(lparen, rparen), + (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), + (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), + (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, |l, r| is_qself_equal(l, r)) && is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exp_vec_equal(ltup, rtup), + (&ExprUnary(lunop, ref lparam), &ExprUnary(runop, ref rparam)) => lunop == runop && is_exp_equal(lparam, rparam), + (&ExprVec(ref lvec), &ExprVec(ref rvec)) => is_exp_vec_equal(lvec, rvec), + _ => false + } +} + +fn is_exp_vec_equal(left : &Vec>, right : &Vec>) -> bool { + over(left, right, |l, r| is_exp_equal(l, r)) +} + +fn is_path_equal(left : &Path, right : &Path) -> bool { + left.global == right.global && left.segments == right.segments +} + +fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { + left.ty.node == right.ty.node && left.position == right.position +} + +fn is_ty_equal(left : &Ty, right : &Ty) -> bool { + match (&left.node, &right.node) { + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), + (&TyFixedLengthVec(ref lfvty, ref lfvexp), &TyFixedLengthVec(ref rfvty, ref rfvexp)) => + is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), + (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => + both(ltime, rtime, is_lifetime_equal) && is_mut_ty_equal(lrmut, rrmut), + (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => is_bare_fn_ty_equal(lbare, rbare), + (&TyTup(ref ltup), &TyTup(ref rtup)) => is_ty_vec_equal(ltup, rtup), + (&TyPath(Option::None, ref lpath), &TyPath(Option::None, ref rpath)) => is_path_equal(lpath, rpath), + (&TyPath(Option::Some(ref lqself), ref lsubpath), &TyPath(Option::Some(ref rqself), ref rsubpath)) => + is_qself_equal(lqself, rqself) && is_path_equal(lsubpath, rsubpath), + (&TyObjectSum(ref lsumty, ref lobounds), &TyObjectSum(ref rsumty, ref robounds)) => + is_ty_equal(lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), + (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), + (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), + (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), + (&TyInfer, &TyInfer) => true, + _ => false + } +} + +fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { + match(left, right) { + (&TraitTyParamBound(ref lpoly, ref lmod), &TraitTyParamBound(ref rpoly, ref rmod)) => + lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), + (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => is_lifetime_equal(ltime, rtime), + _ => false + } +} + +fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) -> bool { + is_lifetimedef_vec_equal(&left.bound_lifetimes, &right.bound_lifetimes) && + is_path_equal(&left.trait_ref.path, &right.trait_ref.path) +} + +fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) -> bool { + over(left, right, is_param_bound_equal) +} + +fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { + left.mutbl == right.mutbl && is_ty_equal(&left.ty, &right.ty) +} + +fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { + left.unsafety == right.unsafety && left.abi == right.abi && + is_lifetimedef_vec_equal(&left.lifetimes, &right.lifetimes) && is_fndecl_equal(&left.decl, &right.decl) +} + +fn is_fndecl_equal(left : &P, right : &P) -> bool { + left.variadic == right.variadic && is_arg_vec_equal(&left.inputs, &right.inputs) && + is_fnret_ty_equal(&left.output, &right.output) +} + +fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) -> bool { + match (left, right) { + (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, + (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), + _ => false + } +} + +fn is_arg_equal(left : &Arg, right : &Arg) -> bool { + is_ty_equal(&left.ty, &right.ty) && is_pat_equal(&left.pat, &right.pat) +} + +fn is_arg_vec_equal(left : &Vec, right : &Vec) -> bool { + over(left, right, is_arg_equal) +} + +fn is_pat_equal(left : &Pat, right : &Pat) -> bool { + match(&left.node, &right.node) { + (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, + (&PatIdent(ref lmode, ref lident, Option::None), &PatIdent(ref rmode, ref rident, Option::None)) => + lmode == rmode && is_ident_equal(&lident.node, &rident.node), + (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), + &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => + lmode == rmode && is_ident_equal(&lident.node, &rident.node) && is_pat_equal(lpat, rpat), + (&PatEnum(ref lpath, Option::None), &PatEnum(ref rpath, Option::None)) => is_path_equal(lpath, rpath), + (&PatEnum(ref lpath, Option::Some(ref lenum)), &PatEnum(ref rpath, Option::Some(ref renum))) => + is_path_equal(lpath, rpath) && is_pat_vec_equal(lenum, renum), + (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => + lbool == rbool && is_path_equal(lpath, rpath) && is_spanned_fieldpat_vec_equal(lfieldpat, rfieldpat), + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pat_vec_equal(ltup, rtup), + (&PatBox(ref lboxed), &PatBox(ref rboxed)) => is_pat_equal(lboxed, rboxed), + (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => is_pat_equal(lpat, rpat) && lmut == rmut, + (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), + (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => + is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), + (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => + is_pat_vec_equal(lfirst, rfirst) && is_pat_vec_equal(llast, rlast), + (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => + is_pat_vec_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && is_pat_vec_equal(llast, rlast), + // I don't match macros for now, the code is slow enough as is ;-) + _ => false + } +} + +fn is_spanned_fieldpat_vec_equal(left : &Vec>, right : &Vec>) -> bool { + over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) +} + +fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { + left.is_shorthand == right.is_shorthand && is_ident_equal(&left.ident, &right.ident) && + is_pat_equal(&left.pat, &right.pat) +} + +fn is_ident_equal(left : &Ident, right : &Ident) -> bool { + &left.name == &right.name && left.ctxt == right.ctxt +} + +fn is_pat_vec_equal(left : &Vec>, right : &Vec>) -> bool { + over(left, right, |l, r| is_pat_equal(l, r)) +} + +fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) -> bool { + is_lifetime_equal(&left.lifetime, &right.lifetime) && over(&left.bounds, &right.bounds, is_lifetime_equal) +} + +fn is_lifetimedef_vec_equal(left : &Vec, right : &Vec) -> bool { + over(left, right, is_lifetimedef_equal) +} + +fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { + left.name == right.name +} + +fn is_ty_vec_equal(left : &Vec>, right : &Vec>) -> bool { + over(left, right, |l, r| is_ty_equal(l, r)) +} + +fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) +} + +fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool where F: FnMut(&X, &X) -> bool { + if l.is_none() { r.is_none() } else { r.is_some() && eq_fn(l.as_ref().unwrap(), &r.as_ref().unwrap()) } +} + +fn is_cmp_or_bit(op : &BinOp) -> bool { + match op.node { + BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, + _ => false + } +} diff --git a/src/lib.rs b/src/lib.rs index ee137230f5c..ad477a21042 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ use rustc::lint::LintPassObject; pub mod types; pub mod misc; +pub mod eq_op; +pub mod bit_mask; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -23,7 +25,10 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); + reg.register_lint_pass(box eq_op::EqOp as LintPassObject); + reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, - misc::TOPLEVEL_REF_ARG]); + misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, + bit_mask::BAD_BIT_MASK]); } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs new file mode 100644 index 00000000000..0c1fd348234 --- /dev/null +++ b/tests/compile-fail/bit_masks.rs @@ -0,0 +1,19 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(bad_bit_mask)] +fn main() { + let x = 5; + x & 1 == 1; //ok, distinguishes bit 0 + x & 2 == 1; //~ERROR + x | 1 == 3; //ok, equals x == 2 || x == 3 + x | 3 == 3; //ok, equals x <= 3 + x | 3 == 2; //~ERROR + + x & 1 > 1; //~ERROR + x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x | 1 > 1; // ok (if a bit silly), equals x > 1 + x | 2 > 1; //~ERROR + x | 2 <= 2; // ok (if a bit silly), equals x <= 2 +} diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs new file mode 100644 index 00000000000..910b5e84816 --- /dev/null +++ b/tests/compile-fail/eq_op.rs @@ -0,0 +1,36 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn id(x: X) -> X { + x +} + +#[deny(eq_op)] +fn main() { + // simple values and comparisons + 1 == 1; //~ERROR + "no" == "no"; //~ERROR + // even though I agree that no means no ;-) + false != false; //~ERROR + 1.5 < 1.5; //~ERROR + 1u64 >= 1u64; //~ERROR + + // casts, methods, parenthesis + (1 as u64) & (1 as u64); //~ERROR + 1 ^ ((((((1)))))); //~ERROR + id((1)) | id(1); //~ERROR + + // unary and binary operators + (-(2) < -(2)); //~ERROR + ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR + + // various other things + ([1] != [1]); //~ERROR + ((1, 2) != (1, 2)); //~ERROR + [1].len() == [1].len(); //~ERROR + vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros +} diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 3fd219dfb44..5008c2aa704 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,11 +1,8 @@ extern crate compiletest; -use std::env; -use std::process::Command; use std::path::PathBuf; fn run_mode(mode: &'static str) { - let mut config = compiletest::default_config(); let cfg_mode = mode.parse().ok().expect("Invalid mode"); config.target_rustcflags = Some("-L target/debug/".to_string()); @@ -19,5 +16,4 @@ fn run_mode(mode: &'static str) { #[test] fn compile_test() { run_mode("compile-fail"); - // run_mode("run-pass"); } -- cgit 1.4.1-3-g733a5 From 3a9bf24bb3d0fbcc8cabfecb03bb60c3cfa8babe Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 30 Apr 2015 15:17:06 +0200 Subject: Added constant lookup (with help from Manish) to bad_bit_mask --- src/bit_mask.rs | 31 ++++++++++++++++++++++--------- tests/compile-fail/bit_masks.rs | 9 ++++++++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 313bfb1ac0b..881eafa310e 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -19,6 +19,8 @@ use rustc::plugin::Registry; use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; @@ -41,7 +43,7 @@ impl LintPass for BitMask { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { - fetch_int_literal(&right.node).map(|cmp_value| check_compare(cx, left, cmp.node, cmp_value, &e.span)); + fetch_int_literal(cx, right).map(|cmp_value| check_compare(cx, left, cmp.node, cmp_value, &e.span)); } } } @@ -52,9 +54,9 @@ fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, sp &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), &ExprBinary(ref op, ref left, ref right) => { if op.node != BiBitAnd && op.node != BiBitOr { return; } - if let Some(mask_value) = fetch_int_literal(&right.node) { + if let Some(mask_value) = fetch_int_literal(cx, right) { check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); - } else if let Some(mask_value) = fetch_int_literal(&left.node) { + } else if let Some(mask_value) = fetch_int_literal(cx, left) { check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); } }, @@ -101,11 +103,22 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, } } -fn fetch_int_literal(lit : &Expr_) -> Option { - if let &ExprLit(ref lit_ptr) = lit { - if let &LitInt(value, _) = &lit_ptr.node { - return Option::Some(value); //TODO: Handle sign - } +fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option { + match &lit.node { + &ExprLit(ref lit_ptr) => { + if let &LitInt(value, _) = &lit_ptr.node { + Option::Some(value) //TODO: Handle sign + } else { Option::None } + }, + &ExprPath(_, _) => { + let def_map = cx.tcx.def_map.borrow(); + let path_res_op = def_map.get(&lit.id); + path_res_op.as_ref().and_then(|x| { + if let &DefConst(def_id) = &x.base_def { + lookup_const_by_id(cx.tcx, def_id, Option::None).and_then(|l| fetch_int_literal(cx, l)) + } else { Option::None } + }) + }, + _ => Option::None } - Option::None } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index 0c1fd348234..7cf8709c575 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -1,7 +1,10 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(bad_bit_mask)] +const THREE_BITS : i64 = 7; +const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; + +#[deny(bad_bit_mask)] fn main() { let x = 5; x & 1 == 1; //ok, distinguishes bit 0 @@ -16,4 +19,8 @@ fn main() { x | 1 > 1; // ok (if a bit silly), equals x > 1 x | 2 > 1; //~ERROR x | 2 <= 2; // ok (if a bit silly), equals x <= 2 + + // this also now works with constants + x & THREE_BITS == 8; //~ERROR + x | EVEN_MORE_REDIRECTION < 7; //~ERROR } -- cgit 1.4.1-3-g733a5 From 53fa76dff968787fc39e7a6b96059f151bab6b2e Mon Sep 17 00:00:00 2001 From: llogiq Date: Sat, 2 May 2015 00:35:49 +0200 Subject: new lint: needless_bool (TODO: The warnings could give more specific directions) --- README.md | 4 +-- src/lib.rs | 5 +++- src/needless_bool.rs | 51 +++++++++++++++++++++++++++++++++++++ tests/compile-fail/needless_bool.rs | 12 +++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/needless_bool.rs create mode 100644 tests/compile-fail/needless_bool.rs diff --git a/README.md b/README.md index 577de498dab..0fc9a6c8869 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ Lints included in this crate: - `box_vec`: Warns on usage of `Box>` - `dlist`: Warns on usage of `DList` - `str_to_string`: Warns on usage of `str::to_string()` - - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). + - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) + - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` You can allow/warn/deny the whole set using the `clippy` lint group (`#[allow(clippy)]`, etc) - More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. diff --git a/src/lib.rs b/src/lib.rs index ad477a21042..ea8a3962810 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,7 @@ pub mod types; pub mod misc; pub mod eq_op; pub mod bit_mask; +pub mod needless_bool; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -27,8 +28,10 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); + reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, - bit_mask::BAD_BIT_MASK]); + bit_mask::BAD_BIT_MASK, + needless_bool::NEEDLESS_BOOL]); } diff --git a/src/needless_bool.rs b/src/needless_bool.rs new file mode 100644 index 00000000000..5b14e2fe1f3 --- /dev/null +++ b/src/needless_bool.rs @@ -0,0 +1,51 @@ +//! Checks for needless boolean results of if-else expressions +//! +//! This lint is **deny** by default + +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; + +declare_lint! { + pub NEEDLESS_BOOL, + Warn, + "Warn on needless use of if x { true } else { false } (or vice versa)" +} + +#[derive(Copy,Clone)] +pub struct NeedlessBool; + +impl LintPass for NeedlessBool { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_BOOL) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { + match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { + (Option::Some(true), Option::Some(true)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "your if-then-else expression will always return true"); }, + (Option::Some(true), Option::Some(false)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "you can reduce your if-statement to its predicate"); }, + (Option::Some(false), Option::Some(true)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "you can reduce your if-statement to '!' + your predicate"); }, + (Option::Some(false), Option::Some(false)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "your if-then-else expression will always return false"); }, + _ => () + } + } + } +} + +fn fetch_bool_block(block: &Block) -> Option { + if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) } else { Option::None } +} + +fn fetch_bool_expr(expr: &Expr) -> Option { + match &expr.node { + &ExprBlock(ref block) => fetch_bool_block(block), + &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { Option::Some(value) } else { Option::None }, + _ => Option::None + } +} diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs new file mode 100644 index 00000000000..97a478ee410 --- /dev/null +++ b/tests/compile-fail/needless_bool.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(needless_bool)] +fn main() { + let x = true; + if x { true } else { true }; //~ERROR + if x { false } else { false }; //~ERROR + if x { true } else { false }; //~ERROR + if x { false } else { true }; //~ERROR + if x { x } else { false }; // would also be questionable, but we don't catch this yet +} -- cgit 1.4.1-3-g733a5 From 07adeee6e942a639af81f7cd4c035e066433cef0 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 4 May 2015 07:17:15 +0200 Subject: Added check for zero bitmask and uncommon directions, wrong comment in needless_bool corrected, added new lint vec_ptr_arg + test --- src/bit_mask.rs | 33 +++++++++++++++++++- src/lib.rs | 7 ++++- src/needless_bool.rs | 2 +- src/vec_ptr_arg.rs | 65 +++++++++++++++++++++++++++++++++++++++ tests/compile-fail/bit_masks.rs | 13 +++++++- tests/compile-fail/vec_ptr_arg.rs | 14 +++++++++ 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 src/vec_ptr_arg.rs create mode 100644 tests/compile-fail/vec_ptr_arg.rs diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 881eafa310e..d4cdc952661 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -43,12 +43,31 @@ impl LintPass for BitMask { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { - fetch_int_literal(cx, right).map(|cmp_value| check_compare(cx, left, cmp.node, cmp_value, &e.span)); + let cmp_opt = fetch_int_literal(cx, right); + if cmp_opt.is_some() { + check_compare(cx, left, cmp.node, cmp_opt.unwrap(), &e.span); + } else { + fetch_int_literal(cx, left).map(|cmp_val| + check_compare(cx, right, invert_cmp(cmp.node), cmp_val, &e.span)); + } } } } } +fn invert_cmp(cmp : BinOp_) -> BinOp_ { + match cmp { + BiEq => BiEq, + BiNe => BiNe, + BiLt => BiGt, + BiGt => BiLt, + BiLe => BiGe, + BiGe => BiLe, + _ => BiOr // Dummy + } +} + + fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { match &bit_op.node { &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), @@ -70,6 +89,10 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, BiBitAnd => if mask_value & cmp_value != mask_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} can never be equal to {}", mask_value, cmp_value)); + } else { + if mask_value == 0 { + cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + } }, BiBitOr => if mask_value | cmp_value != cmp_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} can never be equal to {}", mask_value, @@ -81,6 +104,10 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, BiBitAnd => if mask_value < cmp_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will always be lower than {}", mask_value, cmp_value)); + } else { + if mask_value == 0 { + cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + } }, BiBitOr => if mask_value >= cmp_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will never be lower than {}", mask_value, @@ -92,6 +119,10 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, BiBitAnd => if mask_value <= cmp_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will never be higher than {}", mask_value, cmp_value)); + } else { + if mask_value == 0 { + cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + } }, BiBitOr => if mask_value > cmp_value { cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will always be higher than {}", mask_value, diff --git a/src/lib.rs b/src/lib.rs index ea8a3962810..a9faf199863 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ pub mod misc; pub mod eq_op; pub mod bit_mask; pub mod needless_bool; +pub mod vec_ptr_arg; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -29,9 +30,13 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box eq_op::EqOp as LintPassObject); reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); + reg.register_lint_pass(box vec_ptr_arg::VecPtrArg as LintPassObject); + reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, - needless_bool::NEEDLESS_BOOL]); + needless_bool::NEEDLESS_BOOL, + vec_ptr_arg::VEC_PTR_ARG + ]); } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 5b14e2fe1f3..fe35e6ee3bd 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -1,6 +1,6 @@ //! Checks for needless boolean results of if-else expressions //! -//! This lint is **deny** by default +//! This lint is **warn** by default use rustc::plugin::Registry; use rustc::lint::*; diff --git a/src/vec_ptr_arg.rs b/src/vec_ptr_arg.rs new file mode 100644 index 00000000000..88fdc5cf065 --- /dev/null +++ b/src/vec_ptr_arg.rs @@ -0,0 +1,65 @@ +//! Checks for usage of &Vec[_] and &String +//! +//! This lint is **warn** by default + +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; +use types::match_ty_unwrap; + +declare_lint! { + pub VEC_PTR_ARG, + Allow, + "Warn on declaration of a &Vec-typed method argument" +} + + +#[derive(Copy,Clone)] +pub struct VecPtrArg; + +impl LintPass for VecPtrArg { + fn get_lints(&self) -> LintArray { + lint_array!(VEC_PTR_ARG) + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + if let &ItemFn(ref decl, _, _, _, _) = &item.node { + check_fn(cx, decl); + } + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if let &MethodImplItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if let &MethodTraitItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } +} + +fn check_fn(cx: &Context, decl: &FnDecl) { + for arg in &decl.inputs { + let ty = &arg.ty; + match ty.node { + TyPtr(ref pty) => check_ptr_subtype(cx, ty.span, &pty.ty), + TyRptr(_, ref rpty) => check_ptr_subtype(cx, ty.span, &rpty.ty), + _ => () + } + } +} + +fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { + if match_ty_unwrap(ty, &["Vec"]).is_some() { + cx.span_lint(VEC_PTR_ARG, span, + "Writing '&Vec<_>' instead of '&[_]' involves one more reference and cannot be used with non-vec-based slices. Consider changing the type to &[...]"); + } +} diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index 7cf8709c575..b575dbc4e25 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -7,12 +7,15 @@ const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] fn main() { let x = 5; + + x & 0 == 0; //~ERROR &-masking with zero x & 1 == 1; //ok, distinguishes bit 0 x & 2 == 1; //~ERROR + x | 0 == 0; //ok, equals x == 0 (maybe warn?) x | 1 == 3; //ok, equals x == 2 || x == 3 x | 3 == 3; //ok, equals x <= 3 x | 3 == 2; //~ERROR - + x & 1 > 1; //~ERROR x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 @@ -23,4 +26,12 @@ fn main() { // this also now works with constants x & THREE_BITS == 8; //~ERROR x | EVEN_MORE_REDIRECTION < 7; //~ERROR + + 0 & x == 0; //~ERROR + 1 | x > 1; + + // and should now also match uncommon usage + 1 < 2 | x; //~ERROR + 2 == 3 | x; //~ERROR + 1 == x & 2; //~ERROR } diff --git a/tests/compile-fail/vec_ptr_arg.rs b/tests/compile-fail/vec_ptr_arg.rs new file mode 100644 index 00000000000..5c4338e356f --- /dev/null +++ b/tests/compile-fail/vec_ptr_arg.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(vec_ptr_arg)] +#[allow(unused)] +fn go(x: &Vec) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' + //Nothing here +} + + +fn main() { + let x = vec![1i64, 2, 3]; + go(&x); +} -- cgit 1.4.1-3-g733a5 From 8d2328d9a5ed45bf20739b0164dfad2bc97da9a7 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 4 May 2015 08:15:24 +0200 Subject: Added &String matching and renamed to vec_ptr_arg to ptr_arg, also added README section --- README.md | 3 ++ src/lib.rs | 9 +++-- src/ptr_arg.rs | 69 +++++++++++++++++++++++++++++++++++++++ src/vec_ptr_arg.rs | 65 ------------------------------------ tests/compile-fail/ptr_arg.rs | 20 ++++++++++++ tests/compile-fail/vec_ptr_arg.rs | 14 -------- 6 files changed, 96 insertions(+), 84 deletions(-) create mode 100644 src/ptr_arg.rs delete mode 100644 src/vec_ptr_arg.rs create mode 100644 tests/compile-fail/ptr_arg.rs delete mode 100644 tests/compile-fail/vec_ptr_arg.rs diff --git a/README.md b/README.md index 0fc9a6c8869..32249163211 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ Lints included in this crate: - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` + - `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively + +In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) You can allow/warn/deny the whole set using the `clippy` lint group (`#[allow(clippy)]`, etc) diff --git a/src/lib.rs b/src/lib.rs index a9faf199863..8cf8650c80a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,8 +18,8 @@ pub mod types; pub mod misc; pub mod eq_op; pub mod bit_mask; +pub mod ptr_arg; pub mod needless_bool; -pub mod vec_ptr_arg; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -29,14 +29,13 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); + reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); - reg.register_lint_pass(box vec_ptr_arg::VecPtrArg as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, - bit_mask::BAD_BIT_MASK, - needless_bool::NEEDLESS_BOOL, - vec_ptr_arg::VEC_PTR_ARG + bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, + needless_bool::NEEDLESS_BOOL ]); } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs new file mode 100644 index 00000000000..378d30de57a --- /dev/null +++ b/src/ptr_arg.rs @@ -0,0 +1,69 @@ +//! Checks for usage of &Vec[_] and &String +//! +//! This lint is **warn** by default + +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; +use types::match_ty_unwrap; + +declare_lint! { + pub PTR_ARG, + Allow, + "Warn on declaration of a &Vec- or &String-typed method argument" +} + + +#[derive(Copy,Clone)] +pub struct PtrArg; + +impl LintPass for PtrArg { + fn get_lints(&self) -> LintArray { + lint_array!(PTR_ARG) + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + if let &ItemFn(ref decl, _, _, _, _) = &item.node { + check_fn(cx, decl); + } + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if let &MethodImplItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if let &MethodTraitItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } +} + +fn check_fn(cx: &Context, decl: &FnDecl) { + for arg in &decl.inputs { + let ty = &arg.ty; + match ty.node { + TyPtr(ref pty) => check_ptr_subtype(cx, ty.span, &pty.ty), + TyRptr(_, ref rpty) => check_ptr_subtype(cx, ty.span, &rpty.ty), + _ => () + } + } +} + +fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { + if match_ty_unwrap(ty, &["Vec"]).is_some() { + cx.span_lint(PTR_ARG, span, + "Writing '&Vec<_>' instead of '&[_]' involves one more reference and cannot be used with non-vec-based slices. Consider changing the type to &[...]"); + } else { if match_ty_unwrap(ty, &["String"]).is_some() { + cx.span_lint(PTR_ARG, span, + "Writing '&String' instead of '&str' involves a new Object where a slices will do. Consider changing the type to &str"); + } + } +} diff --git a/src/vec_ptr_arg.rs b/src/vec_ptr_arg.rs deleted file mode 100644 index 88fdc5cf065..00000000000 --- a/src/vec_ptr_arg.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Checks for usage of &Vec[_] and &String -//! -//! This lint is **warn** by default - -use rustc::plugin::Registry; -use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; -use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; -use syntax::codemap::Span; -use types::match_ty_unwrap; - -declare_lint! { - pub VEC_PTR_ARG, - Allow, - "Warn on declaration of a &Vec-typed method argument" -} - - -#[derive(Copy,Clone)] -pub struct VecPtrArg; - -impl LintPass for VecPtrArg { - fn get_lints(&self) -> LintArray { - lint_array!(VEC_PTR_ARG) - } - - fn check_item(&mut self, cx: &Context, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _) = &item.node { - check_fn(cx, decl); - } - } - - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - if let &MethodImplItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } - - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - if let &MethodTraitItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } -} - -fn check_fn(cx: &Context, decl: &FnDecl) { - for arg in &decl.inputs { - let ty = &arg.ty; - match ty.node { - TyPtr(ref pty) => check_ptr_subtype(cx, ty.span, &pty.ty), - TyRptr(_, ref rpty) => check_ptr_subtype(cx, ty.span, &rpty.ty), - _ => () - } - } -} - -fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - if match_ty_unwrap(ty, &["Vec"]).is_some() { - cx.span_lint(VEC_PTR_ARG, span, - "Writing '&Vec<_>' instead of '&[_]' involves one more reference and cannot be used with non-vec-based slices. Consider changing the type to &[...]"); - } -} diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs new file mode 100644 index 00000000000..2fe36eafa6c --- /dev/null +++ b/tests/compile-fail/ptr_arg.rs @@ -0,0 +1,20 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(ptr_arg)] +#[allow(unused)] +fn do_vec(x: &Vec) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' + //Nothing here +} + +#[deny(ptr_arg)] +#[allow(unused)] +fn do_str(x: &String) { //~ERROR + //Nothing here either +} + +fn main() { + let x = vec![1i64, 2, 3]; + do_vec(&x); + do_str(&"hello".to_owned()); +} diff --git a/tests/compile-fail/vec_ptr_arg.rs b/tests/compile-fail/vec_ptr_arg.rs deleted file mode 100644 index 5c4338e356f..00000000000 --- a/tests/compile-fail/vec_ptr_arg.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#[deny(vec_ptr_arg)] -#[allow(unused)] -fn go(x: &Vec) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' - //Nothing here -} - - -fn main() { - let x = vec![1i64, 2, 3]; - go(&x); -} -- cgit 1.4.1-3-g733a5 From 2cb84b9d15b0cf821fc6ad0b90fb7d731f4a1910 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 4 May 2015 12:01:34 +0200 Subject: New lint: approx_const --- README.md | 1 + src/approx_const.rs | 63 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++- tests/compile-fail/approx_const.rs | 56 +++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/approx_const.rs create mode 100644 tests/compile-fail/approx_const.rs diff --git a/README.md b/README.md index 32249163211..211833bacce 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Lints included in this crate: - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` - `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively + - `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) diff --git a/src/approx_const.rs b/src/approx_const.rs new file mode 100644 index 00000000000..8a93bbfa933 --- /dev/null +++ b/src/approx_const.rs @@ -0,0 +1,63 @@ +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; +use std::f64::consts as f64; + +declare_lint! { + pub APPROX_CONSTANT, + Warn, + "Warn if a user writes an approximate known constant in their code" +} + +const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), + (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), + (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), + (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; + +const EPSILON_DIVISOR : f64 = 8192f64; //TODO: test to find a good value + +#[derive(Copy,Clone)] +pub struct ApproxConstant; + +impl LintPass for ApproxConstant { + fn get_lints(&self) -> LintArray { + lint_array!(APPROX_CONSTANT) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let &ExprLit(ref lit) = &e.node { + check_lit(cx, lit, e.span); + } + } +} + +fn check_lit(cx: &Context, lit: &Lit, span: Span) { + match &lit.node { + &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), + &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), + &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), + _ => () + } +} + +fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { + if let Ok(value) = str.parse::() { + for &(constant, name) in KNOWN_CONSTS { + if within_epsilon(constant, value) { + cx.span_lint(APPROX_CONSTANT, span, &format!( + "Approximate value of {}::{} found, consider using it directly.", module, &name)); + } + } + } +} + +fn within_epsilon(target: f64, value: f64) -> bool { + f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR +} diff --git a/src/lib.rs b/src/lib.rs index 8cf8650c80a..b2a750f5cc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub mod eq_op; pub mod bit_mask; pub mod ptr_arg; pub mod needless_bool; +pub mod approx_const; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -31,11 +32,13 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); + reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, - needless_bool::NEEDLESS_BOOL + needless_bool::NEEDLESS_BOOL, + approx_const::APPROX_CONSTANT ]); } diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs new file mode 100644 index 00000000000..488c8f16f5b --- /dev/null +++ b/tests/compile-fail/approx_const.rs @@ -0,0 +1,56 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(approx_constant)] +#[allow(unused)] +fn main() { + let my_e = 2.7182; //~ERROR + let almost_e = 2.718; //~ERROR + let no_e = 2.71; + + let my_1_frac_pi = 0.3183; //~ERROR + let no_1_frac_pi = 0.31; + + let my_frac_1_sqrt_2 = 0.70710678; //~ERROR + let almost_frac_1_sqrt_2 = 0.70711; //~ERROR + let my_frac_1_sqrt_2 = 0.707; + + let my_frac_2_pi = 0.63661977; //~ERROR + let no_frac_2_pi = 0.636; + + let my_frac_2_sq_pi = 1.128379; //~ERROR + let no_frac_2_sq_pi = 1.128; + + let my_frac_2_pi = 1.57079632679; //~ERROR + let no_frac_2_pi = 1.5705; + + let my_frac_3_pi = 1.04719755119; //~ERROR + let no_frac_3_pi = 1.047; + + let my_frac_4_pi = 0.785398163397; //~ERROR + let no_frac_4_pi = 0.785; + + let my_frac_6_pi = 0.523598775598; //~ERROR + let no_frac_6_pi = 0.523; + + let my_frac_8_pi = 0.3926990816987; //~ERROR + let no_frac_8_pi = 0.392; + + let my_ln_10 = 2.302585092994046; //~ERROR + let no_ln_10 = 2.303; + + let my_ln_2 = 0.6931471805599453; //~ERROR + let no_ln_2 = 0.693; + + let my_log10_e = 0.43429448190325176; //~ERROR + let no_log10_e = 0.434; + + let my_log2_e = 1.4426950408889634; //~ERROR + let no_log2_e = 1.442; + + let my_pi = 3.1415; //~ERROR + let almost_pi = 3.141; + + let my_sq2 = 1.4142; //~ERROR + let no_sq2 = 1.414; +} -- cgit 1.4.1-3-g733a5 From 0936e0617a38727b78a76f7671fd382b128b5218 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 4 May 2015 14:11:15 +0200 Subject: new lint to check for doomed comparisons to NAN --- src/lib.rs | 4 +++- src/misc.rs | 31 +++++++++++++++++++++++++++++++ tests/compile-fail/cmp_nan.rs | 21 +++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/compile-fail/cmp_nan.rs diff --git a/src/lib.rs b/src/lib.rs index b2a750f5cc1..8137eccf13f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); + reg.register_lint_pass(box misc::CmpNan as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); @@ -39,6 +40,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, needless_bool::NEEDLESS_BOOL, - approx_const::APPROX_CONSTANT + approx_const::APPROX_CONSTANT, + misc::CMP_NAN ]); } diff --git a/src/misc.rs b/src/misc.rs index 04accaaa8bc..17de26807c2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,6 +1,7 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; +use syntax::ast_util::is_comparison_binop; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr}; @@ -108,3 +109,33 @@ impl LintPass for TopLevelRefPass { } } } + +declare_lint!(pub CMP_NAN, Allow, "Deny comparisons to std::f32::NAN or std::f64::NAN"); + +#[derive(Copy,Clone)] +pub struct CmpNan; + +impl LintPass for CmpNan { + fn get_lints(&self) -> LintArray { + lint_array!(CMP_NAN) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if is_comparison_binop(cmp.node) { + if let &ExprPath(_, ref path) = &left.node { + check_nan(cx, path, expr.span); + } + if let &ExprPath(_, ref path) = &right.node { + check_nan(cx, path, expr.span); + } + } + } + } +} + +fn check_nan(cx: &Context, path: &Path, span: Span) { + path.segments.last().map(|seg| if seg.identifier.as_str() == "NAN" { + cx.span_lint(CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); + }); +} diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs new file mode 100644 index 00000000000..b876bfcc63c --- /dev/null +++ b/tests/compile-fail/cmp_nan.rs @@ -0,0 +1,21 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(cmp_nan)] +fn main() { + let x = 5f32; + x == std::f32::NAN; //~ERROR + x != std::f32::NAN; //~ERROR + x < std::f32::NAN; //~ERROR + x > std::f32::NAN; //~ERROR + x <= std::f32::NAN; //~ERROR + x >= std::f32::NAN; //~ERROR + + let y = 0f64; + y == std::f64::NAN; //~ERROR + y != std::f64::NAN; //~ERROR + y < std::f64::NAN; //~ERROR + y > std::f64::NAN; //~ERROR + y <= std::f64::NAN; //~ERROR + y >= std::f64::NAN; //~ERROR +} -- cgit 1.4.1-3-g733a5 From ac151bb1f0f5069e36a10c8ff6dbf0f81601b317 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 6 May 2015 10:01:49 +0200 Subject: Added new 'float_cmp' lint (see issue #46) --- README.md | 9 ++++++++ src/lib.rs | 3 ++- src/misc.rs | 50 ++++++++++++++++++++++++++++++++--------- tests/compile-fail/cmp_nan.rs | 1 + tests/compile-fail/float_cmp.rs | 35 +++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 tests/compile-fail/float_cmp.rs diff --git a/README.md b/README.md index 211833bacce..3014a1a3ecd 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,15 @@ Lints included in this crate: - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` - `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively - `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant + - `cmp_nan`: Denies comparisons to NAN (which will always return false, which is probably not intended) + - `float_cmp`: Warns on `==` or `!=` comparisons of floaty typed values. As floating-point operations usually involve rounding errors, it is always better to check for approximate equality within some small bounds + +To use, add the following lines to your Cargo.toml: + +``` +[dev-dependencies.rust-clippy] +git = "https://github.com/Manishearth/rust-clippy" +``` In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) diff --git a/src/lib.rs b/src/lib.rs index 8137eccf13f..5b2f71bb4fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); + reg.register_lint_pass(box misc::FloatCmp as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -41,6 +42,6 @@ pub fn plugin_registrar(reg: &mut Registry) { bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, needless_bool::NEEDLESS_BOOL, approx_const::APPROX_CONSTANT, - misc::CMP_NAN + misc::CMP_NAN, misc::FLOAT_CMP, ]); } diff --git a/src/misc.rs b/src/misc.rs index 17de26807c2..cdc39a4b819 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,14 +1,22 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; -use syntax::ast_util::is_comparison_binop; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr}; +use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; use syntax::codemap::Span; + use types::span_note_and_lint; +fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { + match ty.sty { + ty_ptr(ref tm) | ty_rptr(_, ref tm) => walk_ty(tm.ty), + _ => ty + } +} + /// Handles uncategorized lints /// Currently handles linting of if-let-able matches #[allow(missing_copy_implementations)] @@ -71,13 +79,6 @@ impl LintPass for StrToStringPass { } fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { - //println!("{}: -> {}", depth, ty); - match ty.sty { - ty_ptr(ref tm) | ty_rptr(_, ref tm) => walk_ty(tm.ty), - _ => ty - } - } match walk_ty(expr_ty(cx.tcx, expr)).sty { ty_str => true, _ => false @@ -110,7 +111,7 @@ impl LintPass for TopLevelRefPass { } } -declare_lint!(pub CMP_NAN, Allow, "Deny comparisons to std::f32::NAN or std::f64::NAN"); +declare_lint!(pub CMP_NAN, Deny, "Deny comparisons to std::f32::NAN or std::f64::NAN"); #[derive(Copy,Clone)] pub struct CmpNan; @@ -139,3 +140,32 @@ fn check_nan(cx: &Context, path: &Path, span: Span) { cx.span_lint(CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); }); } + +declare_lint!(pub FLOAT_CMP, Warn, + "Warn on ==/!= comparison of floaty values"); + +#[derive(Copy,Clone)] +pub struct FloatCmp; + +impl LintPass for FloatCmp { + fn get_lints(&self) -> LintArray { + lint_array!(FLOAT_CMP) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + let op = cmp.node; + if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { + let map = cx.sess().codemap(); + cx.span_lint(FLOAT_CMP, expr.span, &format!( + "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", + binop_to_string(op), &*map.span_to_snippet(left.span).unwrap_or("..".to_string()), + &*map.span_to_snippet(right.span).unwrap_or("..".to_string()))); + } + } + } +} + +fn is_float(cx: &Context, expr: &Expr) -> bool { + if let ty_float(_) = walk_ty(expr_ty(cx.tcx, expr)).sty { true } else { false } +} diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs index b876bfcc63c..69631331467 100644 --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #[deny(cmp_nan)] +#[allow(float_cmp)] fn main() { let x = 5f32; x == std::f32::NAN; //~ERROR diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs new file mode 100644 index 00000000000..dce8dba1ebe --- /dev/null +++ b/tests/compile-fail/float_cmp.rs @@ -0,0 +1,35 @@ +#![feature(plugin)] +#![plugin(clippy)] + +use std::ops::Add; + +const ZERO : f32 = 0.0; +const ONE : f32 = ZERO + 1.0; + +fn twice(x : T) -> T where T : Add, T : Copy { + x + x +} + +#[deny(float_cmp)] +#[allow(unused)] +fn main() { + ZERO == 0f32; //~ERROR + ZERO == 0.0; //~ERROR + ZERO + ZERO != 1.0; //~ERROR + + ONE != 0.0; //~ERROR + twice(ONE) != ONE; //~ERROR + ONE as f64 != 0.0; //~ERROR + + let x : f64 = 1.0; + + x == 1.0; //~ERROR + x != 0f64; //~ERROR + + twice(x) != twice(ONE as f64); //~ERROR + + x < 0.0; + x > 0.0; + x <= 0.0; + x >= 0.0; +} -- cgit 1.4.1-3-g733a5 From 17bcf0e86519fa6147dec7271660e278cda98404 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 6 May 2015 12:59:08 +0200 Subject: New lint: precedence, see issue #41 --- README.md | 1 + src/lib.rs | 2 ++ src/misc.rs | 46 +++++++++++++++++++++++++++++++++++++++- tests/compile-fail/precedence.rs | 15 +++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/compile-fail/precedence.rs diff --git a/README.md b/README.md index 3014a1a3ecd..7d3e3fd8c65 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Lints included in this crate: - `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant - `cmp_nan`: Denies comparisons to NAN (which will always return false, which is probably not intended) - `float_cmp`: Warns on `==` or `!=` comparisons of floaty typed values. As floating-point operations usually involve rounding errors, it is always better to check for approximate equality within some small bounds + - `precedence`: Warns on expressions where precedence may trip up the unwary reader of the source and suggests adding parenthesis, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` To use, add the following lines to your Cargo.toml: diff --git a/src/lib.rs b/src/lib.rs index 5b2f71bb4fb..ffee122f776 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); reg.register_lint_pass(box misc::FloatCmp as LintPassObject); + reg.register_lint_pass(box misc::Precedence as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -43,5 +44,6 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_bool::NEEDLESS_BOOL, approx_const::APPROX_CONSTANT, misc::CMP_NAN, misc::FLOAT_CMP, + misc::PRECEDENCE, ]); } diff --git a/src/misc.rs b/src/misc.rs index cdc39a4b819..eae6d518950 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -5,7 +5,7 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; -use syntax::codemap::Span; +use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; @@ -169,3 +169,47 @@ impl LintPass for FloatCmp { fn is_float(cx: &Context, expr: &Expr) -> bool { if let ty_float(_) = walk_ty(expr_ty(cx.tcx, expr)).sty { true } else { false } } + +declare_lint!(pub PRECEDENCE, Warn, + "Warn on mixing bit ops with integer arithmetic without parenthesis"); + +#[derive(Copy,Clone)] +pub struct Precedence; + +impl LintPass for Precedence { + fn get_lints(&self) -> LintArray { + lint_array!(PRECEDENCE) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { + if is_bit_op(op) { + if let ExprBinary(Spanned { node: lop, ..}, _, _) = left.node { + if is_arith_op(lop) { + cx.span_lint(PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Please consider adding parenthesis to the subexpression to make the meaning more clear."); + } + } else { + if let ExprBinary(Spanned { node: rop, ..}, _, _) = right.node { + if is_arith_op(rop) { + cx.span_lint(PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Please consider adding parenthesis to the subexpression to make the meaning more clear."); + } + } + } + } + } + } +} + +fn is_bit_op(op : BinOp_) -> bool { + match op { + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, + _ => false + } +} + +fn is_arith_op(op : BinOp_) -> bool { + match op { + BiAdd | BiSub | BiMul | BiDiv | BiRem => true, + _ => false + } +} diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs new file mode 100644 index 00000000000..7969be0f371 --- /dev/null +++ b/tests/compile-fail/precedence.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(precedence)] +#[allow(eq_op)] +fn main() { + format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR + format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR + format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR + format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR + format!("{} vs. {}", 1 ^ 1 - 1, (1 ^ 1) - 1); //~ERROR + format!("{} vs. {}", 3 | 2 - 1, (3 | 2) - 1); //~ERROR + format!("{} vs. {}", 3 & 5 - 2, (3 & 5) - 2); //~ERROR + +} -- cgit 1.4.1-3-g733a5 From 7a8de35abc32478fa84406b0939137333fe9a6b5 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 6 May 2015 13:20:47 +0200 Subject: refactored precedence lint --- src/misc.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index eae6d518950..5059a87bccf 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -183,23 +183,21 @@ impl LintPass for Precedence { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { - if is_bit_op(op) { - if let ExprBinary(Spanned { node: lop, ..}, _, _) = left.node { - if is_arith_op(lop) { - cx.span_lint(PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Please consider adding parenthesis to the subexpression to make the meaning more clear."); - } - } else { - if let ExprBinary(Spanned { node: rop, ..}, _, _) = right.node { - if is_arith_op(rop) { - cx.span_lint(PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Please consider adding parenthesis to the subexpression to make the meaning more clear."); - } - } - } + if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { + cx.span_lint(PRECEDENCE, expr.span, + "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); } } } } +fn is_arith_expr(expr : &Expr) -> bool { + match expr.node { + ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(lop), + _ => false + } +} + fn is_bit_op(op : BinOp_) -> bool { match op { BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, -- cgit 1.4.1-3-g733a5 From 23525081f951c92e4c8ad0b0bfed7a2b03c0531e Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 6 May 2015 14:19:02 +0200 Subject: fixed typo from last commit --- src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 5059a87bccf..8cde5104ff7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -193,7 +193,7 @@ impl LintPass for Precedence { fn is_arith_expr(expr : &Expr) -> bool { match expr.node { - ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(lop), + ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), _ => false } } -- cgit 1.4.1-3-g733a5 From a175463acce7dde5c65d6919d4d2e3ebc9edded0 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Wed, 6 May 2015 21:41:54 -0700 Subject: Fix panic during constant lookup. --- src/bit_mask.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index d4cdc952661..6aece62420e 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -142,14 +142,16 @@ fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option { } else { Option::None } }, &ExprPath(_, _) => { - let def_map = cx.tcx.def_map.borrow(); - let path_res_op = def_map.get(&lit.id); - path_res_op.as_ref().and_then(|x| { - if let &DefConst(def_id) = &x.base_def { - lookup_const_by_id(cx.tcx, def_id, Option::None).and_then(|l| fetch_int_literal(cx, l)) - } else { Option::None } - }) - }, + // Important to let the borrow expire before the const lookup to avoid double + // borrowing. + let def_map = cx.tcx.def_map.borrow(); + match def_map.get(&lit.id) { + Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), + _ => None + } + } + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) + .and_then(|l| fetch_int_literal(cx, l)), _ => Option::None } } -- cgit 1.4.1-3-g733a5 From 11dea785955881b3f5461e7e22f96af151aa4fc0 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Wed, 6 May 2015 22:52:16 -0700 Subject: Fix Box> test. --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index c966c49be85..f0c91dc18b5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -58,7 +58,7 @@ impl LintPass for TypePass { use std::vec::Vec; } match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first()) - .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) + .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { span_note_and_lint(cx, BOX_VEC, ty.span, "You seem to be trying to use Box>. Did you mean to use Vec?", -- cgit 1.4.1-3-g733a5 From b24433f36dbc6ac8540e5b961fafdbb4fa155298 Mon Sep 17 00:00:00 2001 From: llogiq Date: Fri, 8 May 2015 06:01:41 +0200 Subject: added test for issue #31 --- tests/compile-fail/box_vec.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs index cd1270b2373..51d21f5537a 100644 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -7,6 +7,11 @@ pub fn test(foo: Box>) { //~ ERROR You seem to be trying to use Box)>) { // pass if #31 is fixed + foo(vec![1, 2, 3]) +} + fn main(){ test(Box::new(Vec::new())); -} \ No newline at end of file + test2(Box::new(|v| println!("{:?}", v))); +} -- cgit 1.4.1-3-g733a5 From 068e215728cbf388767d97a81464669cfb27eae7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 9 May 2015 15:19:12 +0530 Subject: move to compiletest on crates --- Cargo.toml | 4 ++-- tests/compile-test.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27ff93982b2..22565ccb76b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,5 @@ authors = [ name = "clippy" crate_type = ["dylib"] -[dev-dependencies.compiletest] -git = "https://github.com/laumann/compiletest-rs.git" +[dev-dependencies] +compiletest_rs = "*" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5008c2aa704..04f3fc16b1b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,4 +1,4 @@ -extern crate compiletest; +extern crate compiletest_rs as compiletest; use std::path::PathBuf; -- cgit 1.4.1-3-g733a5 From 5b1cda74c6cd22fefc2a0d74601adccf3ab16aaf Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 9 May 2015 15:22:22 +0530 Subject: Add info --- Cargo.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 22565ccb76b..01151894867 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,15 @@ [package] name = "clippy" -version = "0.0.1" +version = "0.0.2" authors = [ "Manish Goregaokar ", "Andre Bogus " ] +description = "A bunch of helpful lints to avoid common pitfalls in Rust" +repository = "https://github.com/Manishearth/rust-clippy" +readme = "README.md" +license = "MPL-2.0" +keywords = ["clippy", "lint", "plugin"] [lib] name = "clippy" -- cgit 1.4.1-3-g733a5 From 709dfe1cea8af02566d0c002dd48547a0d6537ac Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 9 May 2015 15:24:54 +0530 Subject: plugin --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 01151894867..3c3e700eea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.2" +version = "0.0.3" authors = [ "Manish Goregaokar ", "Andre Bogus " @@ -13,7 +13,7 @@ keywords = ["clippy", "lint", "plugin"] [lib] name = "clippy" -crate_type = ["dylib"] +plugin = true [dev-dependencies] compiletest_rs = "*" -- cgit 1.4.1-3-g733a5 From 2447e1d5bef3ea762a2e91dc7c121a3d7092fce5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 10 May 2015 10:39:04 +0530 Subject: Add eta reduction (fixes #29) --- .gitignore | 3 +++ Cargo.toml | 2 +- README.md | 1 + src/eta_reduction.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ tests/compile-fail/eta.rs | 21 +++++++++++++++++ 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/eta_reduction.rs create mode 100644 tests/compile-fail/eta.rs diff --git a/.gitignore b/.gitignore index 37727f91cbe..ac98a7d842f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ # Generated by Cargo /target/ + +# We don't pin yet +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 3c3e700eea5..95de98e8ee5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.3" +version = "0.0.4" authors = [ "Manish Goregaokar ", "Andre Bogus " diff --git a/README.md b/README.md index 7d3e3fd8c65..004520f5bd7 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Lints included in this crate: - `cmp_nan`: Denies comparisons to NAN (which will always return false, which is probably not intended) - `float_cmp`: Warns on `==` or `!=` comparisons of floaty typed values. As floating-point operations usually involve rounding errors, it is always better to check for approximate equality within some small bounds - `precedence`: Warns on expressions where precedence may trip up the unwary reader of the source and suggests adding parenthesis, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` + - `redundant_closure`: Warns on usage of eta-reducible closures like `|a| foo(a)` (which can be written as just `foo`) To use, add the following lines to your Cargo.toml: diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs new file mode 100644 index 00000000000..b89eef8c8bb --- /dev/null +++ b/src/eta_reduction.rs @@ -0,0 +1,59 @@ +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use syntax::codemap::{Span, Spanned}; +use syntax::print::pprust::expr_to_string; + + +#[allow(missing_copy_implementations)] +pub struct EtaPass; + + +declare_lint!(pub REDUNDANT_CLOSURE, Warn, + "Warn on usage of redundant closures, i.e. `|a| foo(a)`"); + +impl LintPass for EtaPass { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_CLOSURE) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprClosure(_, ref decl, ref blk) = expr.node { + if blk.stmts.len() != 0 { + // || {foo(); bar()}; can't be reduced here + return; + } + if let Some(ref ex) = blk.expr { + if let ExprCall(ref caller, ref args) = ex.node { + if args.len() != decl.inputs.len() { + // Not the same number of arguments, there + // is no way the closure is the same as the function + return; + } + for (ref a1, ref a2) in decl.inputs.iter().zip(args) { + if let PatIdent(_, ident, _) = a1.pat.node { + // XXXManishearth Should I be checking the binding mode here? + if let ExprPath(None, ref p) = a2.node { + if p.segments.len() != 1 { + // If it's a proper path, it can't be a local variable + return; + } + if p.segments[0].identifier != ident.node { + // The two idents should be the same + return + } + } else { + return + } + } else { + return + } + } + cx.span_lint(REDUNDANT_CLOSURE, expr.span, + &format!("Redundant closure found, consider using `{}` in its place", + expr_to_string(caller))[..]) + } + } + } + } +} + diff --git a/src/lib.rs b/src/lib.rs index ffee122f776..7e21a72dcf2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ pub mod bit_mask; pub mod ptr_arg; pub mod needless_bool; pub mod approx_const; +pub mod eta_reduction; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -36,6 +37,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); reg.register_lint_pass(box misc::FloatCmp as LintPassObject); reg.register_lint_pass(box misc::Precedence as LintPassObject); + reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -45,5 +47,6 @@ pub fn plugin_registrar(reg: &mut Registry) { approx_const::APPROX_CONSTANT, misc::CMP_NAN, misc::FLOAT_CMP, misc::PRECEDENCE, + eta_reduction::REDUNDANT_CLOSURE, ]); } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs new file mode 100644 index 00000000000..8ca88eecbd2 --- /dev/null +++ b/tests/compile-fail/eta.rs @@ -0,0 +1,21 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unknown_lints, unused)] +#![deny(redundant_closure)] + +fn main() { + let a = |a, b| foo(a, b); + //~^ ERROR Redundant closure found, consider using `foo` in its place + let c = |a, b| {1+2; foo}(a, b); + //~^ ERROR Redundant closure found, consider using `{ 1 + 2; foo }` in its place + let d = |a, b| foo((|c, d| foo2(c,d))(a,b), b); + //~^ ERROR Redundant closure found, consider using `foo2` in its place +} + +fn foo(_: u8, _: u8) { + +} + +fn foo2(_: u8, _: u8) -> u8 { + 1u8 +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 4eb47abde7dbb9b6c3506bb3ce0e783e21607190 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 10 May 2015 16:10:05 +0530 Subject: crates --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 004520f5bd7..bdda47fcc43 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Lints included in this crate: To use, add the following lines to your Cargo.toml: ``` -[dev-dependencies.rust-clippy] -git = "https://github.com/Manishearth/rust-clippy" +[dev-dependencies] +rust-clippy = "*" ``` In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) -- cgit 1.4.1-3-g733a5 From 2ffbdfdcd08751d48beeeea1cca0dcecf12d164d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 10 May 2015 16:13:02 +0530 Subject: oops --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bdda47fcc43..4859e0a8ad7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To use, add the following lines to your Cargo.toml: ``` [dev-dependencies] -rust-clippy = "*" +clippy = "*" ``` In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) -- cgit 1.4.1-3-g733a5 From 905509083c73a0d5f98f6dbfe4b82679dae1c8d2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 14 May 2015 14:41:33 +0530 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4859e0a8ad7..96d615d7b96 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Lints included in this crate: To use, add the following lines to your Cargo.toml: ``` -[dev-dependencies] +[dependencies] clippy = "*" ``` -- cgit 1.4.1-3-g733a5 From 6bec4f35dff0d0fe58d4bfdeeb63ed4695d62c5a Mon Sep 17 00:00:00 2001 From: llogiq Date: Fri, 15 May 2015 14:09:29 +0200 Subject: Added 'ineffective bit mask' lint --- README.md | 1 + src/bit_mask.rs | 40 +++++++++++++++++++++++++++++++--------- src/lib.rs | 4 +++- tests/compile-fail/bit_masks.rs | 15 +++++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 96d615d7b96..3ea3659dd1d 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Lints included in this crate: - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) + - `ineffective_bit_mask`: Warns on expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` - `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively - `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 6aece62420e..42e3003d336 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -32,12 +32,18 @@ declare_lint! { "Deny the use of incompatible bit masks in comparisons, e.g. '(a & 1) == 2'" } +declare_lint! { + pub INEFFECTIVE_BIT_MASK, + Warn, + "Warn on the use of an ineffective bit mask in comparisons, e.g. '(a & 1) > 2'" +} + #[derive(Copy,Clone)] pub struct BitMask; impl LintPass for BitMask { fn get_lints(&self) -> LintArray { - lint_array!(BAD_BIT_MASK) + lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) } fn check_expr(&mut self, cx: &Context, e: &Expr) { @@ -102,31 +108,47 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, }, BiLt | BiGe => match bit_op { BiBitAnd => if mask_value < cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will always be lower than {}", mask_value, - cmp_value)); + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} will always be lower than {}", + mask_value, cmp_value)); } else { if mask_value == 0 { cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); } }, BiBitOr => if mask_value >= cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will never be lower than {}", mask_value, - cmp_value)); + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} will never be lower than {}", + mask_value, cmp_value)); + } else { + if mask_value < cmp_value { + cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + mask_value, cmp_value)); + } }, _ => () }, BiLe | BiGt => match bit_op { BiBitAnd => if mask_value <= cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will never be higher than {}", mask_value, - cmp_value)); + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} will never be higher than {}", + mask_value, cmp_value)); } else { if mask_value == 0 { cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); } }, BiBitOr => if mask_value > cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will always be higher than {}", mask_value, - cmp_value)); + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} will always be higher than {}", + mask_value, cmp_value)); + } else { + if mask_value < cmp_value { + cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + mask_value, cmp_value)); + } }, _ => () }, diff --git a/src/lib.rs b/src/lib.rs index 7e21a72dcf2..1655faaf8b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, - bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + ptr_arg::PTR_ARG, needless_bool::NEEDLESS_BOOL, approx_const::APPROX_CONSTANT, misc::CMP_NAN, misc::FLOAT_CMP, diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index b575dbc4e25..d2646d2589e 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -5,6 +5,7 @@ const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] +#[allow(ineffective_bit_mask)] fn main() { let x = 5; @@ -34,4 +35,18 @@ fn main() { 1 < 2 | x; //~ERROR 2 == 3 | x; //~ERROR 1 == x & 2; //~ERROR + + x | 1 > 2; // no error, because we allowed ineffective bit masks + ineffective(); +} + +#[deny(ineffective_bit_mask)] +#[allow(bad_bit_mask)] +fn ineffective() { + let x = 5; + + x | 1 > 2; //~ERROR + x | 1 < 3; //~ERROR + x | 1 <= 3; //~ERROR + x | 1 >= 2; //~ERROR } -- cgit 1.4.1-3-g733a5 From edf747ab7617c38381e791f56c0376f0f8fea559 Mon Sep 17 00:00:00 2001 From: llogiq Date: Fri, 15 May 2015 18:46:43 +0200 Subject: new lint: identity_op, refactored bit_masks a bit --- README.md | 1 + src/identity_op.rs | 82 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ tests/compile-fail/bit_masks.rs | 2 +- tests/compile-fail/eq_op.rs | 1 + tests/compile-fail/identity_op.rs | 24 ++++++++++++ 6 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/identity_op.rs create mode 100644 tests/compile-fail/identity_op.rs diff --git a/README.md b/README.md index 3ea3659dd1d..47747d86e26 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Lints included in this crate: - `float_cmp`: Warns on `==` or `!=` comparisons of floaty typed values. As floating-point operations usually involve rounding errors, it is always better to check for approximate equality within some small bounds - `precedence`: Warns on expressions where precedence may trip up the unwary reader of the source and suggests adding parenthesis, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` - `redundant_closure`: Warns on usage of eta-reducible closures like `|a| foo(a)` (which can be written as just `foo`) + - `identity_op`: Warns on identity operations like `x + 0` or `y / 1` (which can be reduced to `x` and `y`, respectively) To use, add the following lines to your Cargo.toml: diff --git a/src/identity_op.rs b/src/identity_op.rs new file mode 100644 index 00000000000..ec4495539d2 --- /dev/null +++ b/src/identity_op.rs @@ -0,0 +1,82 @@ +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::ptr::P; +use syntax::codemap::Span; + +declare_lint! { pub IDENTITY_OP, Warn, + "Warn on identity operations, e.g. '_ + 0'"} + +#[derive(Copy,Clone)] +pub struct IdentityOp; + +impl LintPass for IdentityOp { + fn get_lints(&self) -> LintArray { + lint_array!(IDENTITY_OP) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + match cmp.node { + BiAdd | BiBitOr | BiBitXor => { + check(cx, left, 0, e.span, right.span); + check(cx, right, 0, e.span, left.span); + }, + BiShl | BiShr | BiSub => + check(cx, right, 0, e.span, left.span), + BiMul => { + check(cx, left, 1, e.span, right.span); + check(cx, right, 1, e.span, left.span); + }, + BiDiv => + check(cx, right, 1, e.span, left.span), + BiBitAnd => { + check(cx, left, -1, e.span, right.span); + check(cx, right, -1, e.span, left.span); + }, + _ => () + } + } + } +} + + +fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { + if have_lit(cx, e, m) { + let map = cx.sess().codemap(); + cx.span_lint(IDENTITY_OP, span, &format!( + "The operation is ineffective. Consider reducing it to '{}'", + &*map.span_to_snippet(arg).unwrap_or("..".to_string()))); + } +} + +fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { + match &e.node { + &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), + &ExprLit(ref lit) => { + match (&lit.node, m) { + (&LitInt(0, _), 0) => true, + (&LitInt(1, SignedIntLit(_, Plus)), 1) => true, + (&LitInt(1, UnsuffixedIntLit(Plus)), 1) => true, + (&LitInt(1, SignedIntLit(_, Minus)), -1) => true, + (&LitInt(1, UnsuffixedIntLit(Minus)), -1) => true, + _ => false + } + }, + &ExprParen(ref p) => have_lit(cx, p, m), + &ExprPath(_, _) => { + match cx.tcx.def_map.borrow().get(&e.id) { + Some(&PathResolution { base_def: DefConst(def_id), ..}) => + match lookup_const_by_id(cx.tcx, def_id, Option::None) { + Some(l) => have_lit(cx, l, m), + None => false + }, + _ => false + } + } + _ => false + } +} diff --git a/src/lib.rs b/src/lib.rs index 1655faaf8b0..c9585d2ebba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ pub mod ptr_arg; pub mod needless_bool; pub mod approx_const; pub mod eta_reduction; +pub mod identity_op; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -38,6 +39,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::FloatCmp as LintPassObject); reg.register_lint_pass(box misc::Precedence as LintPassObject); reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); + reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -50,5 +52,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::CMP_NAN, misc::FLOAT_CMP, misc::PRECEDENCE, eta_reduction::REDUNDANT_CLOSURE, + identity_op::IDENTITY_OP, ]); } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index d2646d2589e..e45b789800e 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -5,7 +5,7 @@ const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] -#[allow(ineffective_bit_mask)] +#[allow(ineffective_bit_mask, identity_op)] fn main() { let x = 5; diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 910b5e84816..07b15625b2c 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -6,6 +6,7 @@ fn id(x: X) -> X { } #[deny(eq_op)] +#[allow(identity_op)] fn main() { // simple values and comparisons 1 == 1; //~ERROR diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs new file mode 100644 index 00000000000..6c17d30fac4 --- /dev/null +++ b/tests/compile-fail/identity_op.rs @@ -0,0 +1,24 @@ +#![feature(plugin)] +#![plugin(clippy)] + +const ONE : i64 = 1; +const NEG_ONE : i64 = -1; +const ZERO : i64 = 0; + +#[deny(identity_op)] +fn main() { + let x = 0; + + x + 0; //~ERROR + 0 + x; //~ERROR + x - ZERO; //~ERROR + x | (0); //~ERROR + ((ZERO)) | x; //~ERROR + + x * 1; //~ERROR + 1 * x; //~ERROR + x / ONE; //~ERROR + + x & NEG_ONE; //~ERROR + -1 & x; //~ERROR +} -- cgit 1.4.1-3-g733a5 From 96bfade4f13af23f95c7381a3b08168f9e852f99 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 18 May 2015 09:02:24 +0200 Subject: New lint: mut_mut (closes issue #9) --- README.md | 1 + src/lib.rs | 3 +++ src/mut_mut.rs | 51 +++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/mut_mut.rs | 20 +++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/mut_mut.rs create mode 100644 tests/compile-fail/mut_mut.rs diff --git a/README.md b/README.md index 47747d86e26..ddc28a95f03 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Lints included in this crate: - `precedence`: Warns on expressions where precedence may trip up the unwary reader of the source and suggests adding parenthesis, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` - `redundant_closure`: Warns on usage of eta-reducible closures like `|a| foo(a)` (which can be written as just `foo`) - `identity_op`: Warns on identity operations like `x + 0` or `y / 1` (which can be reduced to `x` and `y`, respectively) + - `mut_mut`: Warns on `&mut &mut` which is either a copy'n'paste error, or shows a fundamental misunderstanding of references To use, add the following lines to your Cargo.toml: diff --git a/src/lib.rs b/src/lib.rs index c9585d2ebba..cd918bff459 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ pub mod needless_bool; pub mod approx_const; pub mod eta_reduction; pub mod identity_op; +pub mod mut_mut; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -40,6 +41,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::Precedence as LintPassObject); reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); + reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -53,5 +55,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::PRECEDENCE, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, + mut_mut::MUT_MUT, ]); } diff --git a/src/mut_mut.rs b/src/mut_mut.rs new file mode 100644 index 00000000000..0a58e293915 --- /dev/null +++ b/src/mut_mut.rs @@ -0,0 +1,51 @@ +use syntax::ptr::P; +use syntax::ast; +use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::visit::{FnKind}; +use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; +use syntax::codemap::{Span, Spanned}; + +declare_lint!(pub MUT_MUT, Warn, + "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); + +#[derive(Copy,Clone)] +pub struct MutMut; + +impl LintPass for MutMut { + fn get_lints(&self) -> LintArray { + lint_array!(MUT_MUT) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + + fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + match expr.node { + ExprAddrOf(MutMutable, ref e) => Option::Some(e), + _ => Option::None + } + } + + if unwrap_addr(expr).and_then(unwrap_addr).is_some() { + cx.span_lint(MUT_MUT, expr.span, + "We're not sure what this means, so if you know, please tell us.") + } + } + + fn check_ty(&mut self, cx: &Context, ty: &Ty) { + + fn unwrap_mut(ty : &Ty) -> Option<&Ty> { + match ty.node { + TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + _ => Option::None + } + } + + if unwrap_mut(ty).and_then(unwrap_mut).is_some() { + cx.span_lint(MUT_MUT, ty.span, + "We're not sure what this means, so if you know, please tell us.") + } + } +} diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs new file mode 100644 index 00000000000..7d1dad44a90 --- /dev/null +++ b/tests/compile-fail/mut_mut.rs @@ -0,0 +1,20 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(mut_mut)] +fn fun(x : &mut &mut u32) -> bool { //~ERROR + **x > 0 +} + +#[deny(mut_mut)] +fn main() { + let mut x = &mut &mut 1u32; //~ERROR + if fun(x) { + let y : &mut &mut &mut u32 = &mut &mut &mut 2; + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + //~^^^^ ERROR + ***y + **x; + } +} -- cgit 1.4.1-3-g733a5 From 1f8453ab73ef40a33e04c95349c6d3c638e576ae Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 18 May 2015 10:41:15 +0200 Subject: mut_mut now more robust (thanks to Manishearth, see issue #9) --- src/mut_mut.rs | 43 ++++++++++++++++++++++++------------------- tests/compile-fail/mut_mut.rs | 5 +++++ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 0a58e293915..d77a40a4ea5 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,11 +1,7 @@ use syntax::ptr::P; -use syntax::ast; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::visit::{FnKind}; -use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; -use syntax::codemap::{Span, Spanned}; +use rustc::lint::{Context, LintPass, LintArray, Lint}; +use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -27,25 +23,34 @@ impl LintPass for MutMut { } } - if unwrap_addr(expr).and_then(unwrap_addr).is_some() { - cx.span_lint(MUT_MUT, expr.span, - "We're not sure what this means, so if you know, please tell us.") - } + unwrap_addr(expr).map(|e| { + if unwrap_addr(e).is_some() { + cx.span_lint(MUT_MUT, expr.span, + "We're not sure what this means, so if you know, please tell us.") + } else { + match expr_ty(cx.tcx, e).sty { + ty_ptr(mt{ty: _, mutbl: MutMutable}) | + ty_rptr(_, mt{ty: _, mutbl: MutMutable}) => + cx.span_lint(MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. Consider direct reborrowing"), + _ => () + } + } + }); } fn check_ty(&mut self, cx: &Context, ty: &Ty) { - - fn unwrap_mut(ty : &Ty) -> Option<&Ty> { - match ty.node { - TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - _ => Option::None - } - } - if unwrap_mut(ty).and_then(unwrap_mut).is_some() { cx.span_lint(MUT_MUT, ty.span, "We're not sure what this means, so if you know, please tell us.") } } } + +fn unwrap_mut(ty : &Ty) -> Option<&Ty> { + match ty.node { + TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + _ => Option::None + } +} diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 7d1dad44a90..65e3762e2c4 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -7,8 +7,13 @@ fn fun(x : &mut &mut u32) -> bool { //~ERROR } #[deny(mut_mut)] +#[allow(unused_mut, unused_variables)] fn main() { let mut x = &mut &mut 1u32; //~ERROR + { + let mut y = &mut x; //~ERROR + } + if fun(x) { let y : &mut &mut &mut u32 = &mut &mut &mut 2; //~^ ERROR -- cgit 1.4.1-3-g733a5 From b9414637e238c94048b0f752c6c4f32953806ce1 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 18 May 2015 10:52:43 +0200 Subject: better messages --- src/mut_mut.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index d77a40a4ea5..5d50e351353 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -26,13 +26,13 @@ impl LintPass for MutMut { unwrap_addr(expr).map(|e| { if unwrap_addr(e).is_some() { cx.span_lint(MUT_MUT, expr.span, - "We're not sure what this means, so if you know, please tell us.") + "Generally you want to avoid &mut &mut _ if possible.") } else { match expr_ty(cx.tcx, e).sty { ty_ptr(mt{ty: _, mutbl: MutMutable}) | ty_rptr(_, mt{ty: _, mutbl: MutMutable}) => cx.span_lint(MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. Consider direct reborrowing"), + "This expression mutably borrows a mutable reference. Consider reborrowing"), _ => () } } @@ -42,7 +42,7 @@ impl LintPass for MutMut { fn check_ty(&mut self, cx: &Context, ty: &Ty) { if unwrap_mut(ty).and_then(unwrap_mut).is_some() { cx.span_lint(MUT_MUT, ty.span, - "We're not sure what this means, so if you know, please tell us.") + "Generally you want to avoid &mut &mut _ if possible.") } } } -- cgit 1.4.1-3-g733a5 From 5556d89f560ae2948f2bb3ce5415ba6aff6aca4f Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 18 May 2015 11:36:56 +0200 Subject: removed ty_ptr match --- src/mut_mut.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 5d50e351353..2a71b938d71 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -28,12 +28,9 @@ impl LintPass for MutMut { cx.span_lint(MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") } else { - match expr_ty(cx.tcx, e).sty { - ty_ptr(mt{ty: _, mutbl: MutMutable}) | - ty_rptr(_, mt{ty: _, mutbl: MutMutable}) => - cx.span_lint(MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. Consider reborrowing"), - _ => () + if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = expr_ty(cx.tcx, e).sty { + cx.span_lint(MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. Consider reborrowing") } } }); -- cgit 1.4.1-3-g733a5 From bac950b4d63a3f04bbb6502d6d2f832e4d64dc77 Mon Sep 17 00:00:00 2001 From: Camille TJHOA Date: Tue, 28 Apr 2015 21:50:04 +0200 Subject: Fix and improve README --- README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ddc28a95f03..4190005175a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -rust-clippy -=========== +#rust-clippy +[![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) A collection of lints that give helpful tips to newbies and catch oversights. - +##Lints Lints included in this crate: - `single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. - `box_vec`: Warns on usage of `Box>` - - `dlist`: Warns on usage of `DList` + - `linkedlist`: Warns on usage of `LinkedList` - `str_to_string`: Warns on usage of `str::to_string()` - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination @@ -31,10 +31,50 @@ To use, add the following lines to your Cargo.toml: clippy = "*" ``` -In your code, you may add `#![plugin(clippy)]` to use it (you may also need to include a `#![feature(plugin)]` line) +More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! -You can allow/warn/deny the whole set using the `clippy` lint group (`#[allow(clippy)]`, etc) +##Usage +Add in your `Cargo.toml`: +``` +[dependencies.clippy] +git = "https://github.com/Manishearth/rust-clippy" +``` -More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! +Sample `main.rs`: +``` +#![feature(plugin)] + +#![plugin(clippy)] +// OPTIONS GO HERE + +fn main(){ + let x = Some(1u8); + match x { + Some(y) => println!("{:?}", y), + _ => () + } +} +``` + +Produce this warning: +``` +src/main.rs:8:5: 11:6 warning: You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?, #[warn(single_match)] on by default +src/main.rs:8 match x { +src/main.rs:9 Some(y) => println!("{:?}", y), +src/main.rs:10 _ => () +src/main.rs:11 } +src/main.rs:8:5: 11:6 note: Try if let Some(y) = x { ... } +src/main.rs:8 match x { +src/main.rs:9 Some(y) => println!("{:?}", y), +src/main.rs:10 _ => () +src/main.rs:11 } +``` + +You can add `OPTIONS` to `allow`/`warn`/`deny`: +- the whole set using the `clippy` lint group (`#[deny(clippy)]`, etc) +- only some lints (`#[deny(single_match, box_vec)]`, etc) + +*`deny` produce error instead of warnings* +##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From b533b084f3abeabe6949cdaaff80f74ac22f7200 Mon Sep 17 00:00:00 2001 From: Camille TJHOA Date: Wed, 29 Apr 2015 14:18:02 +0200 Subject: Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4190005175a..de37d5e59f8 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ You can add `OPTIONS` to `allow`/`warn`/`deny`: - the whole set using the `clippy` lint group (`#[deny(clippy)]`, etc) - only some lints (`#[deny(single_match, box_vec)]`, etc) -*`deny` produce error instead of warnings* +*`deny` produces error instead of warnings* ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 04f48455e5906c32e826d751f07fd6f635bc68e6 Mon Sep 17 00:00:00 2001 From: Camille TJHOA Date: Wed, 29 Apr 2015 16:17:30 +0200 Subject: Specify languages for examples --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de37d5e59f8..48289f04216 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ##Usage Add in your `Cargo.toml`: -``` +```toml [dependencies.clippy] git = "https://github.com/Manishearth/rust-clippy" ``` Sample `main.rs`: -``` +```rust #![feature(plugin)] #![plugin(clippy)] -- cgit 1.4.1-3-g733a5 From 303c8f7b5e82174af94d43482b4bebff0306e287 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 May 2015 16:02:25 +0530 Subject: Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 48289f04216..633b2ed08c4 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Sample `main.rs`: #![feature(plugin)] #![plugin(clippy)] -// OPTIONS GO HERE + fn main(){ let x = Some(1u8); @@ -70,9 +70,10 @@ src/main.rs:10 _ => () src/main.rs:11 } ``` -You can add `OPTIONS` to `allow`/`warn`/`deny`: -- the whole set using the `clippy` lint group (`#[deny(clippy)]`, etc) -- only some lints (`#[deny(single_match, box_vec)]`, etc) +You can add options to `allow`/`warn`/`deny`: +- the whole set using the `clippy` lint group (`#![deny(clippy)]`, etc) +- only some lints (`#![deny(single_match, box_vec)]`, etc) +- `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc *`deny` produces error instead of warnings* -- cgit 1.4.1-3-g733a5 From e8ca3c6eae160310c310b15002587b1f2579d4e5 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 20 May 2015 08:52:19 +0200 Subject: new lints len_zero and len_without_is_empty --- README.md | 2 + src/len_zero.rs | 101 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 ++ tests/compile-fail/len_zero.rs | 56 +++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 src/len_zero.rs create mode 100644 tests/compile-fail/len_zero.rs diff --git a/README.md b/README.md index ddc28a95f03..e081630326f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Lints included in this crate: - `redundant_closure`: Warns on usage of eta-reducible closures like `|a| foo(a)` (which can be written as just `foo`) - `identity_op`: Warns on identity operations like `x + 0` or `y / 1` (which can be reduced to `x` and `y`, respectively) - `mut_mut`: Warns on `&mut &mut` which is either a copy'n'paste error, or shows a fundamental misunderstanding of references + - `len_zero`: Warns on `_.len() == 0` and suggests using `_.is_empty()` (or similar comparisons with `>` or `!=`) + - `len_without_is_empty`: Warns on traits or impls that have a `.len()` but no `.is_empty()` method To use, add the following lines to your Cargo.toml: diff --git a/src/len_zero.rs b/src/len_zero.rs new file mode 100644 index 00000000000..18ddbccc9a2 --- /dev/null +++ b/src/len_zero.rs @@ -0,0 +1,101 @@ +extern crate rustc_typeck as typeck; + +use syntax::ptr::P; +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint}; +use rustc::middle::ty::{self, node_id_to_type, sty, ty_ptr, ty_rptr, mt, MethodTraitItemId}; +use rustc::middle::def::{DefTy, DefStruct, DefTrait}; +use syntax::codemap::{Span, Spanned}; + +declare_lint!(pub LEN_ZERO, Warn, + "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); + +declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, + "Warn on traits and impls that have .len() but not .is_empty()"); + +#[derive(Copy,Clone)] +pub struct LenZero; + +impl LintPass for LenZero { + fn get_lints(&self) -> LintArray { + lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + match &item.node { + &ItemTrait(_, _, _, ref trait_items) => + check_trait_items(cx, item, trait_items), + &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait + check_impl_items(cx, item, impl_items), + _ => () + } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = + &expr.node { + match cmp { + BiEq => check_cmp(cx, expr.span, left, right, ""), + BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + _ => () + } + } + } +} + +fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P]) { + fn is_named_self(item: &TraitItem, name: &str) -> bool { + item.ident.as_str() == name && item.attrs.len() == 0 + } + + if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { + //cx.span_lint(LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); + for i in trait_items { + if is_named_self(i, "len") { + cx.span_lint(LEN_WITHOUT_IS_EMPTY, i.span, + &format!("Trait '{}' has a '.len()' method, but no \ + '.is_empty()' method. Consider adding one.", + item.ident.as_str())); + } + }; + } +} + +fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P]) { + fn is_named_self(item: &ImplItem, name: &str) -> bool { + item.ident.as_str() == name && item.attrs.len() == 0 + } + + if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { + for i in impl_items { + if is_named_self(i, "len") { + cx.span_lint(LEN_WITHOUT_IS_EMPTY, i.span, + &format!("Item '{}' has a '.len()' method, but no \ + '.is_empty()' method. Consider adding one.", + item.ident.as_str())); + return; + } + } + } +} + +fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { + match (&left.node, &right.node) { + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => + check_len_zero(cx, span, method, args, lit, empty), + (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => + check_len_zero(cx, span, method, args, lit, empty), + _ => () + } +} + +fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, + args: &[P], lit: &Lit, empty: &str) { + if let &Spanned{node: LitInt(0, _), ..} = lit { + if method.node.as_str() == "len" && args.len() == 1 { + cx.span_lint(LEN_ZERO, span, &format!( + "Consider replacing the len comparison with '{}_.is_empty()' if available", + empty)) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index cd918bff459..e22ee28e77e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub mod approx_const; pub mod eta_reduction; pub mod identity_op; pub mod mut_mut; +pub mod len_zero; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -42,6 +43,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); + reg.register_lint_pass(box len_zero::LenZero as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -56,5 +58,7 @@ pub fn plugin_registrar(reg: &mut Registry) { eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, mut_mut::MUT_MUT, + len_zero::LEN_ZERO, + len_zero::LEN_WITHOUT_IS_EMPTY, ]); } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs new file mode 100644 index 00000000000..7b1aafd409d --- /dev/null +++ b/tests/compile-fail/len_zero.rs @@ -0,0 +1,56 @@ +#![feature(plugin)] +#![plugin(clippy)] + +struct One; + +#[deny(len_without_is_empty)] +impl One { + fn len(self: &Self) -> isize { //~ERROR + 1 + } +} + +#[deny(len_without_is_empty)] +trait TraitsToo { + fn len(self: &Self) -> isize; //~ERROR +} + +impl TraitsToo for One { + fn len(self: &Self) -> isize { + 0 + } +} + +#[allow(dead_code)] +struct HasIsEmpty; + +#[deny(len_without_is_empty)] +#[allow(dead_code)] +impl HasIsEmpty { + fn len(self: &Self) -> isize { + 1 + } + + fn is_empty() -> bool { + false + } +} + +#[deny(len_zero)] +fn main() { + let x = [1, 2]; + if x.len() == 0 { //~ERROR + println!("This should not happen!"); + } + + let y = One; + // false positives here + if y.len() == 0 { //~ERROR + println!("This should not happen either!"); + } + + let z : &TraitsToo = &y; + if z.len() > 0 { //~ERROR + println!("Nor should this!"); + } +} -- cgit 1.4.1-3-g733a5 From 4a7cd0772effbb4e060db86a9bb9937f57155126 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 20 May 2015 12:34:45 +0530 Subject: Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4b9789d2618..0f9d6128eb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: rust +rust: nightly sudo: false script: -- cgit 1.4.1-3-g733a5 From 483a546e74a55ddae9769475e794ee55d62cfc17 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 20 May 2015 09:34:02 +0200 Subject: added messages to test error comments --- tests/compile-fail/len_zero.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 7b1aafd409d..14f2506ec8b 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -5,14 +5,14 @@ struct One; #[deny(len_without_is_empty)] impl One { - fn len(self: &Self) -> isize { //~ERROR + fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len()' method 1 } } #[deny(len_without_is_empty)] trait TraitsToo { - fn len(self: &Self) -> isize; //~ERROR + fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len()' method, } impl TraitsToo for One { @@ -39,18 +39,18 @@ impl HasIsEmpty { #[deny(len_zero)] fn main() { let x = [1, 2]; - if x.len() == 0 { //~ERROR + if x.len() == 0 { //~ERROR Consider replacing the len comparison println!("This should not happen!"); } let y = One; // false positives here - if y.len() == 0 { //~ERROR + if y.len() == 0 { //~ERROR Consider replacing the len comparison println!("This should not happen either!"); } let z : &TraitsToo = &y; - if z.len() > 0 { //~ERROR + if z.len() > 0 { //~ERROR Consider replacing the len comparison println!("Nor should this!"); } } -- cgit 1.4.1-3-g733a5 From 4292dc77a737c4f8f8210f4448ec2ef94c2b03f3 Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 21 May 2015 14:51:43 +0200 Subject: new lint: cmp_owned --- src/lib.rs | 3 ++- src/misc.rs | 49 +++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/cmp_owned.rs | 17 ++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/compile-fail/cmp_owned.rs diff --git a/src/lib.rs b/src/lib.rs index e22ee28e77e..cf5def800a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); reg.register_lint_pass(box len_zero::LenZero as LintPassObject); + reg.register_lint_pass(box misc::CmpOwned as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -54,7 +55,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_bool::NEEDLESS_BOOL, approx_const::APPROX_CONSTANT, misc::CMP_NAN, misc::FLOAT_CMP, - misc::PRECEDENCE, + misc::PRECEDENCE, misc::CMP_OWNED, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, mut_mut::MUT_MUT, diff --git a/src/misc.rs b/src/misc.rs index 8cde5104ff7..5f5b07a15b7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -211,3 +211,52 @@ fn is_arith_op(op : BinOp_) -> bool { _ => false } } + +declare_lint!(pub CMP_OWNED, Warn, + "Warn on creating an owned string just for comparison"); + +#[derive(Copy,Clone)] +pub struct CmpOwned; + +impl LintPass for CmpOwned { + fn get_lints(&self) -> LintArray { + lint_array!(CMP_OWNED) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if is_comparison_binop(cmp.node) { + check_to_owned(cx, left, right.span); + check_to_owned(cx, right, left.span) + } + } + } +} + +fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { + match &expr.node { + &ExprMethodCall(Spanned{node: ref ident, ..}, _, _) => { + let name = ident.as_str(); + if name == "to_string" || name == "to_owned" { + cx.span_lint(CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. + Consider using {}.as_slice() to compare without allocation", + cx.sess().codemap().span_to_snippet(other_span).unwrap_or( + "..".to_string()))) + } + }, + &ExprCall(ref path, _) => { + if let &ExprPath(None, ref path) = &path.node { + if path.segments.iter().zip(["String", "from_str"].iter()).all( + |(seg, name)| &seg.identifier.as_str() == name) { + cx.span_lint(CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. + Consider using {}.as_slice() to compare without allocation", + cx.sess().codemap().span_to_snippet(other_span).unwrap_or( + "..".to_string()))) + } + } + }, + _ => () + } +} diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs new file mode 100644 index 00000000000..a8b0cb32f6f --- /dev/null +++ b/tests/compile-fail/cmp_owned.rs @@ -0,0 +1,17 @@ +#![feature(plugin, collections)] +#![plugin(clippy)] + +#[deny(cmp_owned)] +fn main() { + let x = "oh"; + + #[allow(str_to_string)] + fn with_to_string(x : &str) { + x != "foo".to_string(); //~ERROR this creates an owned instance + } + with_to_string(x); + + x != "foo".to_owned(); //~ERROR this creates an owned instance + + x != String::from_str("foo"); //~ERROR this creates an owned instance +} -- cgit 1.4.1-3-g733a5 From 5b1287f017beac4609486a24fb0cc8c02d63c8ed Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 21 May 2015 14:57:20 +0200 Subject: added description to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5a5369fc9c1..0bea2fad1d6 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Lints included in this crate: - `mut_mut`: Warns on `&mut &mut` which is either a copy'n'paste error, or shows a fundamental misunderstanding of references - `len_zero`: Warns on `_.len() == 0` and suggests using `_.is_empty()` (or similar comparisons with `>` or `!=`) - `len_without_is_empty`: Warns on traits or impls that have a `.len()` but no `.is_empty()` method + - `cmp_owned`: Warns on creating owned instances for comparing with others, e.g. `x == "foo".to_string()` To use, add the following lines to your Cargo.toml: -- cgit 1.4.1-3-g733a5 From 158935a38d043a90e8f67ab3ae9363c65543d157 Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 21 May 2015 15:59:38 +0200 Subject: refactored Option usage and fn argument types, improved formatting --- src/bit_mask.rs | 12 +++-- src/eq_op.rs | 135 +++++++++++++++++++++++++++++++++++--------------------- src/misc.rs | 4 +- src/mut_mut.rs | 21 ++++----- src/ptr_arg.rs | 18 ++++---- 5 files changed, 112 insertions(+), 78 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 42e3003d336..d84da654eb4 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -49,13 +49,11 @@ impl LintPass for BitMask { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { - let cmp_opt = fetch_int_literal(cx, right); - if cmp_opt.is_some() { - check_compare(cx, left, cmp.node, cmp_opt.unwrap(), &e.span); - } else { - fetch_int_literal(cx, left).map(|cmp_val| - check_compare(cx, right, invert_cmp(cmp.node), cmp_val, &e.span)); - } + fetch_int_literal(cx, right).map(|cmp_opt| + check_compare(cx, left, cmp.node, cmp_opt, &e.span)) + .unwrap_or_else(|| fetch_int_literal(cx, left).map(|cmp_val| + check_compare(cx, right, invert_cmp(cmp.node), cmp_val, + &e.span)).unwrap_or(())) } } } diff --git a/src/eq_op.rs b/src/eq_op.rs index e0b722a0a18..0223820447d 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -21,7 +21,9 @@ impl LintPass for EqOp { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(left, right) { - cx.span_lint(EQ_OP, e.span, &format!("equal expressions as operands to {}", ast_util::binop_to_string(op.node))); + cx.span_lint(EQ_OP, e.span, &format!( + "equal expressions as operands to {}", + ast_util::binop_to_string(op.node))); } } } @@ -29,32 +31,39 @@ impl LintPass for EqOp { fn is_exp_equal(left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { - (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => + (&ExprBinary(ref lop, ref ll, ref lr), + &ExprBinary(ref rop, ref rl, ref rr)) => lop.node == rop.node && is_exp_equal(ll, rl) && is_exp_equal(lr, rr), (&ExprBox(ref lpl, ref lboxedpl), &ExprBox(ref rpl, ref rboxedpl)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && is_exp_equal(lboxedpl, rboxedpl), + both(lpl, rpl, |l, r| is_exp_equal(l, r)) && + is_exp_equal(lboxedpl, rboxedpl), (&ExprCall(ref lcallee, ref largs), &ExprCall(ref rcallee, ref rargs)) => - is_exp_equal(lcallee, rcallee) && is_exp_vec_equal(largs, rargs), + is_exp_equal(lcallee, rcallee) && is_exps_equal(largs, rargs), (&ExprCast(ref lcast, ref lty), &ExprCast(ref rcast, ref rty)) => is_ty_equal(lty, rty) && is_exp_equal(lcast, rcast), - (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => + (&ExprField(ref lfexp, ref lfident), + &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), (&ExprLit(ref llit), &ExprLit(ref rlit)) => llit.node == rlit.node, - (&ExprMethodCall(ref lident, ref lcty, ref lmargs), &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_ty_vec_equal(lcty, rcty) && is_exp_vec_equal(lmargs, rmargs), - (&ExprParen(ref lparen), &ExprParen(ref rparen)) => is_exp_equal(lparen, rparen), + (&ExprMethodCall(ref lident, ref lcty, ref lmargs), + &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => + lident.node == rident.node && is_tys_equal(lcty, rcty) && + is_exps_equal(lmargs, rmargs), (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), - (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, |l, r| is_qself_equal(l, r)) && is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exp_vec_equal(ltup, rtup), - (&ExprUnary(lunop, ref lparam), &ExprUnary(runop, ref rparam)) => lunop == runop && is_exp_equal(lparam, rparam), - (&ExprVec(ref lvec), &ExprVec(ref rvec)) => is_exp_vec_equal(lvec, rvec), + (&ExprPath(ref lqself, ref lsubpath), + &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, |l, r| is_qself_equal(l, r)) && + is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(ltup, rtup), + (&ExprUnary(lunop, ref lparam), &ExprUnary(runop, ref rparam)) => + lunop == runop && is_exp_equal(lparam, rparam), + (&ExprVec(ref lvec), &ExprVec(ref rvec)) => is_exps_equal(lvec, rvec), _ => false } } -fn is_exp_vec_equal(left : &Vec>, right : &Vec>) -> bool { +fn is_exps_equal(left : &[P], right : &[P]) -> bool { over(left, right, |l, r| is_exp_equal(l, r)) } @@ -69,19 +78,25 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { fn is_ty_equal(left : &Ty, right : &Ty) -> bool { match (&left.node, &right.node) { (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), - (&TyFixedLengthVec(ref lfvty, ref lfvexp), &TyFixedLengthVec(ref rfvty, ref rfvexp)) => + (&TyFixedLengthVec(ref lfvty, ref lfvexp), + &TyFixedLengthVec(ref rfvty, ref rfvexp)) => is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => both(ltime, rtime, is_lifetime_equal) && is_mut_ty_equal(lrmut, rrmut), - (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => is_bare_fn_ty_equal(lbare, rbare), - (&TyTup(ref ltup), &TyTup(ref rtup)) => is_ty_vec_equal(ltup, rtup), - (&TyPath(Option::None, ref lpath), &TyPath(Option::None, ref rpath)) => is_path_equal(lpath, rpath), - (&TyPath(Option::Some(ref lqself), ref lsubpath), &TyPath(Option::Some(ref rqself), ref rsubpath)) => + (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => + is_bare_fn_ty_equal(lbare, rbare), + (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), + (&TyPath(Option::None, ref lpath), &TyPath(Option::None, ref rpath)) => + is_path_equal(lpath, rpath), + (&TyPath(Option::Some(ref lqself), ref lsubpath), + &TyPath(Option::Some(ref rqself), ref rsubpath)) => is_qself_equal(lqself, rqself) && is_path_equal(lsubpath, rsubpath), - (&TyObjectSum(ref lsumty, ref lobounds), &TyObjectSum(ref rsumty, ref robounds)) => + (&TyObjectSum(ref lsumty, ref lobounds), + &TyObjectSum(ref rsumty, ref robounds)) => is_ty_equal(lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), - (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), + (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => + is_param_bounds_equal(ltbounds, rtbounds), (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), (&TyInfer, &TyInfer) => true, @@ -91,15 +106,17 @@ fn is_ty_equal(left : &Ty, right : &Ty) -> bool { fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { match(left, right) { - (&TraitTyParamBound(ref lpoly, ref lmod), &TraitTyParamBound(ref rpoly, ref rmod)) => + (&TraitTyParamBound(ref lpoly, ref lmod), + &TraitTyParamBound(ref rpoly, ref rmod)) => lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), - (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => is_lifetime_equal(ltime, rtime), + (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => + is_lifetime_equal(ltime, rtime), _ => false } } fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) -> bool { - is_lifetimedef_vec_equal(&left.bound_lifetimes, &right.bound_lifetimes) && + is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) && is_path_equal(&left.trait_ref.path, &right.trait_ref.path) } @@ -113,11 +130,12 @@ fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { left.unsafety == right.unsafety && left.abi == right.abi && - is_lifetimedef_vec_equal(&left.lifetimes, &right.lifetimes) && is_fndecl_equal(&left.decl, &right.decl) + is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && + is_fndecl_equal(&left.decl, &right.decl) } fn is_fndecl_equal(left : &P, right : &P) -> bool { - left.variadic == right.variadic && is_arg_vec_equal(&left.inputs, &right.inputs) && + left.variadic == right.variadic && is_args_equal(&left.inputs, &right.inputs) && is_fnret_ty_equal(&left.output, &right.output) } @@ -133,44 +151,56 @@ fn is_arg_equal(left : &Arg, right : &Arg) -> bool { is_ty_equal(&left.ty, &right.ty) && is_pat_equal(&left.pat, &right.pat) } -fn is_arg_vec_equal(left : &Vec, right : &Vec) -> bool { +fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { over(left, right, is_arg_equal) } fn is_pat_equal(left : &Pat, right : &Pat) -> bool { match(&left.node, &right.node) { (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, - (&PatIdent(ref lmode, ref lident, Option::None), &PatIdent(ref rmode, ref rident, Option::None)) => + (&PatIdent(ref lmode, ref lident, Option::None), + &PatIdent(ref rmode, ref rident, Option::None)) => lmode == rmode && is_ident_equal(&lident.node, &rident.node), (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node) && is_pat_equal(lpat, rpat), - (&PatEnum(ref lpath, Option::None), &PatEnum(ref rpath, Option::None)) => is_path_equal(lpath, rpath), - (&PatEnum(ref lpath, Option::Some(ref lenum)), &PatEnum(ref rpath, Option::Some(ref renum))) => - is_path_equal(lpath, rpath) && is_pat_vec_equal(lenum, renum), - (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => - lbool == rbool && is_path_equal(lpath, rpath) && is_spanned_fieldpat_vec_equal(lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pat_vec_equal(ltup, rtup), + lmode == rmode && is_ident_equal(&lident.node, &rident.node) && + is_pat_equal(lpat, rpat), + (&PatEnum(ref lpath, Option::None), &PatEnum(ref rpath, Option::None)) => + is_path_equal(lpath, rpath), + (&PatEnum(ref lpath, Option::Some(ref lenum)), + &PatEnum(ref rpath, Option::Some(ref renum))) => + is_path_equal(lpath, rpath) && is_pats_equal(lenum, renum), + (&PatStruct(ref lpath, ref lfieldpat, lbool), + &PatStruct(ref rpath, ref rfieldpat, rbool)) => + lbool == rbool && is_path_equal(lpath, rpath) && + is_spanned_fieldpats_equal(lfieldpat, rfieldpat), + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), (&PatBox(ref lboxed), &PatBox(ref rboxed)) => is_pat_equal(lboxed, rboxed), - (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => is_pat_equal(lpat, rpat) && lmut == rmut, + (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => + is_pat_equal(lpat, rpat) && lmut == rmut, (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), - (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => - is_pat_vec_equal(lfirst, rfirst) && is_pat_vec_equal(llast, rlast), - (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pat_vec_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && is_pat_vec_equal(llast, rlast), + (&PatVec(ref lfirst, Option::None, ref llast), + &PatVec(ref rfirst, Option::None, ref rlast)) => + is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), + (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), + &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => + is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && + is_pats_equal(llast, rlast), // I don't match macros for now, the code is slow enough as is ;-) _ => false } } -fn is_spanned_fieldpat_vec_equal(left : &Vec>, right : &Vec>) -> bool { +fn is_spanned_fieldpats_equal(left : &[code::Spanned], + right : &[code::Spanned]) -> bool { over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) } fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { - left.is_shorthand == right.is_shorthand && is_ident_equal(&left.ident, &right.ident) && + left.is_shorthand == right.is_shorthand && + is_ident_equal(&left.ident, &right.ident) && is_pat_equal(&left.pat, &right.pat) } @@ -178,15 +208,16 @@ fn is_ident_equal(left : &Ident, right : &Ident) -> bool { &left.name == &right.name && left.ctxt == right.ctxt } -fn is_pat_vec_equal(left : &Vec>, right : &Vec>) -> bool { +fn is_pats_equal(left : &[P], right : &[P]) -> bool { over(left, right, |l, r| is_pat_equal(l, r)) } fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) -> bool { - is_lifetime_equal(&left.lifetime, &right.lifetime) && over(&left.bounds, &right.bounds, is_lifetime_equal) + is_lifetime_equal(&left.lifetime, &right.lifetime) && + over(&left.bounds, &right.bounds, is_lifetime_equal) } -fn is_lifetimedef_vec_equal(left : &Vec, right : &Vec) -> bool { +fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) -> bool { over(left, right, is_lifetimedef_equal) } @@ -194,21 +225,25 @@ fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { left.name == right.name } -fn is_ty_vec_equal(left : &Vec>, right : &Vec>) -> bool { +fn is_tys_equal(left : &[P], right : &[P]) -> bool { over(left, right, |l, r| is_ty_equal(l, r)) } -fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { +fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool where F: FnMut(&X, &X) -> bool { - if l.is_none() { r.is_none() } else { r.is_some() && eq_fn(l.as_ref().unwrap(), &r.as_ref().unwrap()) } +fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool + where F: FnMut(&X, &X) -> bool { + l.as_ref().map(|x| r.as_ref().map(|y| eq_fn(x, y)).unwrap_or(false)) + .unwrap_or_else(|| r.is_none()) } fn is_cmp_or_bit(op : &BinOp) -> bool { match op.node { - BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, + BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | + BiBitAnd | BiBitOr => true, _ => false } } diff --git a/src/misc.rs b/src/misc.rs index 5f5b07a15b7..c225c83bae2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -239,7 +239,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { let name = ident.as_str(); if name == "to_string" || name == "to_owned" { cx.span_lint(CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. + "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", cx.sess().codemap().span_to_snippet(other_span).unwrap_or( "..".to_string()))) @@ -250,7 +250,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { if path.segments.iter().zip(["String", "from_str"].iter()).all( |(seg, name)| &seg.identifier.as_str() == name) { cx.span_lint(CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. + "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", cx.sess().codemap().span_to_snippet(other_span).unwrap_or( "..".to_string()))) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 2a71b938d71..569f7b81344 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -24,23 +24,24 @@ impl LintPass for MutMut { } unwrap_addr(expr).map(|e| { - if unwrap_addr(e).is_some() { + unwrap_addr(e).map(|_| { cx.span_lint(MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") - } else { - if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = expr_ty(cx.tcx, e).sty { + }).unwrap_or_else(|| { + if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = + expr_ty(cx.tcx, e).sty { cx.span_lint(MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. Consider reborrowing") + "This expression mutably borrows a mutable reference. \ + Consider reborrowing") } - } - }); + }) + }).unwrap_or(()) } fn check_ty(&mut self, cx: &Context, ty: &Ty) { - if unwrap_mut(ty).and_then(unwrap_mut).is_some() { - cx.span_lint(MUT_MUT, ty.span, - "Generally you want to avoid &mut &mut _ if possible.") - } + unwrap_mut(ty).and_then(unwrap_mut).map(|_| cx.span_lint(MUT_MUT, + ty.span, "Generally you want to avoid &mut &mut _ if possible.")). + unwrap_or(()) } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 378d30de57a..f8f056e7928 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -18,7 +18,6 @@ declare_lint! { "Warn on declaration of a &Vec- or &String-typed method argument" } - #[derive(Copy,Clone)] pub struct PtrArg; @@ -58,12 +57,13 @@ fn check_fn(cx: &Context, decl: &FnDecl) { } fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - if match_ty_unwrap(ty, &["Vec"]).is_some() { - cx.span_lint(PTR_ARG, span, - "Writing '&Vec<_>' instead of '&[_]' involves one more reference and cannot be used with non-vec-based slices. Consider changing the type to &[...]"); - } else { if match_ty_unwrap(ty, &["String"]).is_some() { - cx.span_lint(PTR_ARG, span, - "Writing '&String' instead of '&str' involves a new Object where a slices will do. Consider changing the type to &str"); - } - } + match_ty_unwrap(ty, &["Vec"]).map(|_| { + cx.span_lint(PTR_ARG, span, "Writing '&Vec<_>' instead of '&[_]' \ + involves one more reference and cannot be used with non-vec-based \ + slices. Consider changing the type to &[...]") + }).unwrap_or_else(|| match_ty_unwrap(ty, &["String"]).map(|_| { + cx.span_lint(PTR_ARG, span, + "Writing '&String' instead of '&str' involves a new Object \ + where a slices will do. Consider changing the type to &str") + }).unwrap_or(())); } -- cgit 1.4.1-3-g733a5 From 4b1c72c949328fb12d8eb72579b4ab9fa6243078 Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 21 May 2015 16:37:38 +0200 Subject: check for str type of .to_owned() callee --- src/misc.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 5f5b07a15b7..b8ce6d725f4 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -235,11 +235,12 @@ impl LintPass for CmpOwned { fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { match &expr.node { - &ExprMethodCall(Spanned{node: ref ident, ..}, _, _) => { + &ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { let name = ident.as_str(); - if name == "to_string" || name == "to_owned" { + if name == "to_string" || + name == "to_owned" && is_str_arg(cx, args) { cx.span_lint(CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. + "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", cx.sess().codemap().span_to_snippet(other_span).unwrap_or( "..".to_string()))) @@ -250,7 +251,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { if path.segments.iter().zip(["String", "from_str"].iter()).all( |(seg, name)| &seg.identifier.as_str() == name) { cx.span_lint(CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. + "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", cx.sess().codemap().span_to_snippet(other_span).unwrap_or( "..".to_string()))) @@ -260,3 +261,8 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { _ => () } } + +fn is_str_arg(cx: &Context, args: &[P]) -> bool { + args.len() == 1 && if let ty_str = + walk_ty(expr_ty(cx.tcx, &*args[0])).sty { true } else { false } +} -- cgit 1.4.1-3-g733a5 From 0ed8e4e9683a7900b71f055d9460f42b8baa468e Mon Sep 17 00:00:00 2001 From: llogiq Date: Sat, 23 May 2015 00:49:13 +0200 Subject: another refactoring, using more fitting Option methods, improving formatting, etc. --- src/bit_mask.rs | 64 +++++++++++++++++---------------- src/eq_op.rs | 94 ++++++++++++++++++++++++++---------------------- src/identity_op.rs | 102 ++++++++++++++++++++++++++--------------------------- src/mut_mut.rs | 9 +++-- src/ptr_arg.rs | 19 +++++----- 5 files changed, 148 insertions(+), 140 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index d84da654eb4..fcf8b6cb462 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,22 +1,3 @@ -//! Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. This cannot work because the bit that makes up -//! the value two was zeroed out by the bit-and with 1. So the formula for detecting if an expression of the type -//! `_ m c` (where `` is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` ,`!=`, `>=`, -//! `>`}) can be determined from the following table: -//! -//! |Comparison |Bit-Op|Example |is always|Formula | -//! |------------|------|------------|---------|----------------------| -//! |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -//! |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -//! |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -//! |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -//! |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -//! |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | -//! -//! *TODO*: There is the open question if things like `x | 1 > 1` should be caught by this lint, because it is basically -//! an obfuscated version of `x > 1`. -//! -//! This lint is **deny** by default - use rustc::plugin::Registry; use rustc::lint::*; use rustc::middle::const_eval::lookup_const_by_id; @@ -29,15 +10,37 @@ use syntax::codemap::Span; declare_lint! { pub BAD_BIT_MASK, Deny, - "Deny the use of incompatible bit masks in comparisons, e.g. '(a & 1) == 2'" + "Deny the use of incompatible bit masks in comparisons, e.g. \ + '(a & 1) == 2'" } declare_lint! { pub INEFFECTIVE_BIT_MASK, Warn, - "Warn on the use of an ineffective bit mask in comparisons, e.g. '(a & 1) > 2'" + "Warn on the use of an ineffective bit mask in comparisons, e.g. \ + '(a & 1) > 2'" } +/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. +/// This cannot work because the bit that makes up the value two was +/// zeroed out by the bit-and with 1. So the formula for detecting if an +/// expression of the type `_ m c` (where `` +/// is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` , +/// `!=`, `>=`, `>`}) can be determined from the following table: +/// +/// |Comparison |Bit-Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// +/// This lint is **deny** by default +/// +/// There is also a lint that warns on ineffective masks that is *warn* +/// by default #[derive(Copy,Clone)] pub struct BitMask; @@ -49,11 +52,12 @@ impl LintPass for BitMask { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { - fetch_int_literal(cx, right).map(|cmp_opt| - check_compare(cx, left, cmp.node, cmp_opt, &e.span)) - .unwrap_or_else(|| fetch_int_literal(cx, left).map(|cmp_val| - check_compare(cx, right, invert_cmp(cmp.node), cmp_val, - &e.span)).unwrap_or(())) + fetch_int_literal(cx, right).map_or_else(|| + fetch_int_literal(cx, left).map_or((), |cmp_val| + check_compare(cx, right, invert_cmp(cmp.node), + cmp_val, &e.span)), + |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, + &e.span)) } } } @@ -77,11 +81,9 @@ fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, sp &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), &ExprBinary(ref op, ref left, ref right) => { if op.node != BiBitAnd && op.node != BiBitOr { return; } - if let Some(mask_value) = fetch_int_literal(cx, right) { - check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); - } else if let Some(mask_value) = fetch_int_literal(cx, left) { - check_bit_mask(cx, op.node, cmp_op, mask_value, cmp_value, span); - } + fetch_int_literal(cx, right).or_else(|| fetch_int_literal( + cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, + cmp_op, mask, cmp_value, span)) }, _ => () } diff --git a/src/eq_op.rs b/src/eq_op.rs index 0223820447d..94a49e748e2 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -33,18 +33,20 @@ fn is_exp_equal(left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => - lop.node == rop.node && is_exp_equal(ll, rl) && is_exp_equal(lr, rr), - (&ExprBox(ref lpl, ref lboxedpl), &ExprBox(ref rpl, ref rboxedpl)) => + lop.node == rop.node && + is_exp_equal(ll, rl) && is_exp_equal(lr, rr), + (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => both(lpl, rpl, |l, r| is_exp_equal(l, r)) && - is_exp_equal(lboxedpl, rboxedpl), - (&ExprCall(ref lcallee, ref largs), &ExprCall(ref rcallee, ref rargs)) => - is_exp_equal(lcallee, rcallee) && is_exps_equal(largs, rargs), - (&ExprCast(ref lcast, ref lty), &ExprCast(ref rcast, ref rty)) => - is_ty_equal(lty, rty) && is_exp_equal(lcast, rcast), + is_exp_equal(lbox, rbox), + (&ExprCall(ref lcallee, ref largs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, + rcallee) && is_exps_equal(largs, rargs), + (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => + is_ty_equal(lty, rty) && is_exp_equal(lc, rc), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), - (&ExprLit(ref llit), &ExprLit(ref rlit)) => llit.node == rlit.node, + (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprMethodCall(ref lident, ref lcty, ref lmargs), &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => lident.node == rident.node && is_tys_equal(lcty, rcty) && @@ -55,10 +57,11 @@ fn is_exp_equal(left : &Expr, right : &Expr) -> bool { &ExprPath(ref rqself, ref rsubpath)) => both(lqself, rqself, |l, r| is_qself_equal(l, r)) && is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(ltup, rtup), - (&ExprUnary(lunop, ref lparam), &ExprUnary(runop, ref rparam)) => - lunop == runop && is_exp_equal(lparam, rparam), - (&ExprVec(ref lvec), &ExprVec(ref rvec)) => is_exps_equal(lvec, rvec), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => + is_exps_equal(ltup, rtup), + (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => + lunop == runop && is_exp_equal(l, r), + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), _ => false } } @@ -83,18 +86,17 @@ fn is_ty_equal(left : &Ty, right : &Ty) -> bool { is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => - both(ltime, rtime, is_lifetime_equal) && is_mut_ty_equal(lrmut, rrmut), + both(ltime, rtime, is_lifetime_equal) && + is_mut_ty_equal(lrmut, rrmut), (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => is_bare_fn_ty_equal(lbare, rbare), (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), - (&TyPath(Option::None, ref lpath), &TyPath(Option::None, ref rpath)) => - is_path_equal(lpath, rpath), - (&TyPath(Option::Some(ref lqself), ref lsubpath), - &TyPath(Option::Some(ref rqself), ref rsubpath)) => - is_qself_equal(lqself, rqself) && is_path_equal(lsubpath, rsubpath), + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), (&TyObjectSum(ref lsumty, ref lobounds), &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), + is_ty_equal(lsumty, rsumty) && + is_param_bounds_equal(lobounds, robounds), (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), @@ -104,7 +106,8 @@ fn is_ty_equal(left : &Ty, right : &Ty) -> bool { } } -fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { +fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) + -> bool { match(left, right) { (&TraitTyParamBound(ref lpoly, ref lmod), &TraitTyParamBound(ref rpoly, ref rmod)) => @@ -115,12 +118,14 @@ fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { } } -fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) -> bool { - is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) && - is_path_equal(&left.trait_ref.path, &right.trait_ref.path) +fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) + -> bool { + is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) + && is_path_equal(&left.trait_ref.path, &right.trait_ref.path) } -fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) -> bool { +fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) + -> bool { over(left, right, is_param_bound_equal) } @@ -135,20 +140,23 @@ fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { } fn is_fndecl_equal(left : &P, right : &P) -> bool { - left.variadic == right.variadic && is_args_equal(&left.inputs, &right.inputs) && + left.variadic == right.variadic && + is_args_equal(&left.inputs, &right.inputs) && is_fnret_ty_equal(&left.output, &right.output) } -fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) -> bool { +fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) + -> bool { match (left, right) { - (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, + (&NoReturn(_), &NoReturn(_)) | + (&DefaultReturn(_), &DefaultReturn(_)) => true, (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), _ => false } } -fn is_arg_equal(left : &Arg, right : &Arg) -> bool { - is_ty_equal(&left.ty, &right.ty) && is_pat_equal(&left.pat, &right.pat) +fn is_arg_equal(l: &Arg, r : &Arg) -> bool { + is_ty_equal(&l.ty, &r.ty) && is_pat_equal(&l.pat, &r.pat) } fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { @@ -165,17 +173,16 @@ fn is_pat_equal(left : &Pat, right : &Pat) -> bool { &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => lmode == rmode && is_ident_equal(&lident.node, &rident.node) && is_pat_equal(lpat, rpat), - (&PatEnum(ref lpath, Option::None), &PatEnum(ref rpath, Option::None)) => - is_path_equal(lpath, rpath), - (&PatEnum(ref lpath, Option::Some(ref lenum)), - &PatEnum(ref rpath, Option::Some(ref renum))) => - is_path_equal(lpath, rpath) && is_pats_equal(lenum, renum), + (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => + is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| + is_pats_equal(l, r)), (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => lbool == rbool && is_path_equal(lpath, rpath) && is_spanned_fieldpats_equal(lfieldpat, rfieldpat), (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), - (&PatBox(ref lboxed), &PatBox(ref rboxed)) => is_pat_equal(lboxed, rboxed), + (&PatBox(ref lboxed), &PatBox(ref rboxed)) => + is_pat_equal(lboxed, rboxed), (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => is_pat_equal(lpat, rpat) && lmut == rmut, (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), @@ -212,12 +219,14 @@ fn is_pats_equal(left : &[P], right : &[P]) -> bool { over(left, right, |l, r| is_pat_equal(l, r)) } -fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) -> bool { +fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) + -> bool { is_lifetime_equal(&left.lifetime, &right.lifetime) && over(&left.bounds, &right.bounds, is_lifetime_equal) } -fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) -> bool { +fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) + -> bool { over(left, right, is_lifetimedef_equal) } @@ -231,19 +240,20 @@ fn is_tys_equal(left : &[P], right : &[P]) -> bool { fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| + eq_fn(x, y)) } fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool where F: FnMut(&X, &X) -> bool { - l.as_ref().map(|x| r.as_ref().map(|y| eq_fn(x, y)).unwrap_or(false)) - .unwrap_or_else(|| r.is_none()) + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, + |y| eq_fn(x, y))) } fn is_cmp_or_bit(op : &BinOp) -> bool { match op.node { - BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | - BiBitAnd | BiBitOr => true, + BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | + BiBitXor | BiBitAnd | BiBitOr => true, _ => false } } diff --git a/src/identity_op.rs b/src/identity_op.rs index ec4495539d2..25697199dc3 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -17,66 +17,64 @@ impl LintPass for IdentityOp { fn get_lints(&self) -> LintArray { lint_array!(IDENTITY_OP) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = e.node { - match cmp.node { - BiAdd | BiBitOr | BiBitXor => { - check(cx, left, 0, e.span, right.span); - check(cx, right, 0, e.span, left.span); - }, - BiShl | BiShr | BiSub => - check(cx, right, 0, e.span, left.span), - BiMul => { - check(cx, left, 1, e.span, right.span); - check(cx, right, 1, e.span, left.span); - }, - BiDiv => - check(cx, right, 1, e.span, left.span), - BiBitAnd => { - check(cx, left, -1, e.span, right.span); - check(cx, right, -1, e.span, left.span); - }, - _ => () - } - } + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + match cmp.node { + BiAdd | BiBitOr | BiBitXor => { + check(cx, left, 0, e.span, right.span); + check(cx, right, 0, e.span, left.span); + }, + BiShl | BiShr | BiSub => + check(cx, right, 0, e.span, left.span), + BiMul => { + check(cx, left, 1, e.span, right.span); + check(cx, right, 1, e.span, left.span); + }, + BiDiv => + check(cx, right, 1, e.span, left.span), + BiBitAnd => { + check(cx, left, -1, e.span, right.span); + check(cx, right, -1, e.span, left.span); + }, + _ => () + } + } } } fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { - if have_lit(cx, e, m) { - let map = cx.sess().codemap(); - cx.span_lint(IDENTITY_OP, span, &format!( - "The operation is ineffective. Consider reducing it to '{}'", - &*map.span_to_snippet(arg).unwrap_or("..".to_string()))); - } + if have_lit(cx, e, m) { + let map = cx.sess().codemap(); + cx.span_lint(IDENTITY_OP, span, &format!( + "The operation is ineffective. Consider reducing it to '{}'", + &*map.span_to_snippet(arg).unwrap_or("..".to_string()))); + } } fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { - match &e.node { - &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), - &ExprLit(ref lit) => { - match (&lit.node, m) { - (&LitInt(0, _), 0) => true, - (&LitInt(1, SignedIntLit(_, Plus)), 1) => true, - (&LitInt(1, UnsuffixedIntLit(Plus)), 1) => true, - (&LitInt(1, SignedIntLit(_, Minus)), -1) => true, - (&LitInt(1, UnsuffixedIntLit(Minus)), -1) => true, - _ => false - } - }, - &ExprParen(ref p) => have_lit(cx, p, m), - &ExprPath(_, _) => { - match cx.tcx.def_map.borrow().get(&e.id) { - Some(&PathResolution { base_def: DefConst(def_id), ..}) => - match lookup_const_by_id(cx.tcx, def_id, Option::None) { - Some(l) => have_lit(cx, l, m), - None => false - }, - _ => false - } + match &e.node { + &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), + &ExprLit(ref lit) => { + match (&lit.node, m) { + (&LitInt(0, _), 0) => true, + (&LitInt(1, SignedIntLit(_, Plus)), 1) => true, + (&LitInt(1, UnsuffixedIntLit(Plus)), 1) => true, + (&LitInt(1, SignedIntLit(_, Minus)), -1) => true, + (&LitInt(1, UnsuffixedIntLit(Minus)), -1) => true, + _ => false + } + }, + &ExprParen(ref p) => have_lit(cx, p, m), + &ExprPath(_, _) => { + match cx.tcx.def_map.borrow().get(&e.id) { + Some(&PathResolution { base_def: DefConst(id), ..}) => + lookup_const_by_id(cx.tcx, id, Option::None) + .map_or(false, |l| have_lit(cx, l, m)), + _ => false } - _ => false - } + }, + _ => false + } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 569f7b81344..bf8155b5c3c 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -23,7 +23,7 @@ impl LintPass for MutMut { } } - unwrap_addr(expr).map(|e| { + unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map(|_| { cx.span_lint(MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") @@ -35,13 +35,12 @@ impl LintPass for MutMut { Consider reborrowing") } }) - }).unwrap_or(()) + }) } fn check_ty(&mut self, cx: &Context, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map(|_| cx.span_lint(MUT_MUT, - ty.span, "Generally you want to avoid &mut &mut _ if possible.")). - unwrap_or(()) + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| cx.span_lint(MUT_MUT, + ty.span, "Generally you want to avoid &mut &mut _ if possible.")) } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index f8f056e7928..86b87a942be 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -47,23 +47,22 @@ impl LintPass for PtrArg { fn check_fn(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - let ty = &arg.ty; - match ty.node { - TyPtr(ref pty) => check_ptr_subtype(cx, ty.span, &pty.ty), - TyRptr(_, ref rpty) => check_ptr_subtype(cx, ty.span, &rpty.ty), + match &arg.ty.node { + &TyPtr(ref p) | &TyRptr(_, ref p) => + check_ptr_subtype(cx, arg.ty.span, &p.ty), _ => () } } } fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - match_ty_unwrap(ty, &["Vec"]).map(|_| { - cx.span_lint(PTR_ARG, span, "Writing '&Vec<_>' instead of '&[_]' \ - involves one more reference and cannot be used with non-vec-based \ - slices. Consider changing the type to &[...]") - }).unwrap_or_else(|| match_ty_unwrap(ty, &["String"]).map(|_| { + match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, + &["String"]).map_or((), |_| { cx.span_lint(PTR_ARG, span, "Writing '&String' instead of '&str' involves a new Object \ where a slices will do. Consider changing the type to &str") - }).unwrap_or(())); + }), |_| cx.span_lint(PTR_ARG, span, "Writing '&Vec<_>' instead of \ + '&[_]' involves one more reference and cannot be used with \ + non-vec-based slices. Consider changing the type to &[...]") + ) } -- cgit 1.4.1-3-g733a5 From b51ca1c3db2c4d2195f325c28bdff83c771705ca Mon Sep 17 00:00:00 2001 From: llogiq Date: Sat, 23 May 2015 12:32:29 +0200 Subject: Formatting fixed --- src/bit_mask.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index fcf8b6cb462..352826dffae 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -34,7 +34,7 @@ declare_lint! { /// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | /// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | /// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | /// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | /// /// This lint is **deny** by default -- cgit 1.4.1-3-g733a5 From a133dc445164438b86f9d89f012839820ea0bdb7 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sun, 24 May 2015 19:06:54 +0100 Subject: Fix copy+paste in description of LEN_ZERO --- src/len_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 18ddbccc9a2..2ed0a6a9fab 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -8,7 +8,7 @@ use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; declare_lint!(pub LEN_ZERO, Warn, - "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); + "Warn when .is_empty() could be used instead of checking .len()"); declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, "Warn on traits and impls that have .len() but not .is_empty()"); -- cgit 1.4.1-3-g733a5 From a67e0f6e2f088f930c2f7447b9a8f407cc830c94 Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 25 May 2015 07:22:41 +0200 Subject: first prototype of macro expn detection in mut_mut.rs --- src/mut_mut.rs | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index bf8155b5c3c..b1e21def574 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -2,6 +2,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; +use syntax::codemap::ExpnInfo; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -15,27 +16,8 @@ impl LintPass for MutMut { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - - fn unwrap_addr(expr : &Expr) -> Option<&Expr> { - match expr.node { - ExprAddrOf(MutMutable, ref e) => Option::Some(e), - _ => Option::None - } - } - - unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map(|_| { - cx.span_lint(MUT_MUT, expr.span, - "Generally you want to avoid &mut &mut _ if possible.") - }).unwrap_or_else(|| { - if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = - expr_ty(cx.tcx, e).sty { - cx.span_lint(MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. \ - Consider reborrowing") - } - }) - }) + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) } fn check_ty(&mut self, cx: &Context, ty: &Ty) { @@ -44,6 +26,35 @@ impl LintPass for MutMut { } } +fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { + if in_external_macro(info) { return; } + + fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + match expr.node { + ExprAddrOf(MutMutable, ref e) => Option::Some(e), + _ => Option::None + } + } + + unwrap_addr(expr).map_or((), |e| { + unwrap_addr(e).map(|_| { + cx.span_lint(MUT_MUT, expr.span, + "Generally you want to avoid &mut &mut _ if possible.") + }).unwrap_or_else(|| { + if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = + expr_ty(cx.tcx, e).sty { + cx.span_lint(MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. \ + Consider reborrowing") + } + }) + }) +} + +fn in_external_macro(info: Option<&ExpnInfo>) -> bool { + info.map_or(false, |i| i.callee.span.is_some()) +} + fn unwrap_mut(ty : &Ty) -> Option<&Ty> { match ty.node { TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), -- cgit 1.4.1-3-g733a5 From 73e3ef6d0e2c1da8b5eb8b5b13bdd6d2929bfa5f Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 25 May 2015 22:50:41 +0200 Subject: fixed issue #69 --- src/ptr_arg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 86b87a942be..64c3c84c7b6 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -27,7 +27,7 @@ impl LintPass for PtrArg { } fn check_item(&mut self, cx: &Context, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _) = &item.node { + if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { check_fn(cx, decl); } } -- cgit 1.4.1-3-g733a5 From 0d651c72ff4c8833046dbdad0049893fbc57bef2 Mon Sep 17 00:00:00 2001 From: llogiq Date: Tue, 26 May 2015 01:45:15 +0200 Subject: made macro test even simpler, added a few tests --- Cargo.toml | 2 ++ src/lib.rs | 1 - src/mut_mut.rs | 6 +++--- src/ptr_arg.rs | 2 +- tests/compile-fail/mut_mut.rs | 9 +++++++++ tests/compile-test.rs | 2 +- tests/run-pass.rs | 11 +++++++++++ 7 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 tests/run-pass.rs diff --git a/Cargo.toml b/Cargo.toml index 95de98e8ee5..3c7d9be64e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,5 @@ plugin = true [dev-dependencies] compiletest_rs = "*" +regex = "*" +regex_macros = "*" diff --git a/src/lib.rs b/src/lib.rs index cf5def800a2..92cc7ef254c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] - #![allow(unused_imports)] #[macro_use] diff --git a/src/mut_mut.rs b/src/mut_mut.rs index b1e21def574..160b99a1d15 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -27,7 +27,7 @@ impl LintPass for MutMut { } fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { - if in_external_macro(info) { return; } + if in_macro(info) { return; } fn unwrap_addr(expr : &Expr) -> Option<&Expr> { match expr.node { @@ -51,8 +51,8 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { }) } -fn in_external_macro(info: Option<&ExpnInfo>) -> bool { - info.map_or(false, |i| i.callee.span.is_some()) +fn in_macro(info: Option<&ExpnInfo>) -> bool { + info.is_some() } fn unwrap_mut(ty : &Ty) -> Option<&Ty> { diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 86b87a942be..64c3c84c7b6 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -27,7 +27,7 @@ impl LintPass for PtrArg { } fn check_item(&mut self, cx: &Context, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _) = &item.node { + if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { check_fn(cx, decl); } } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 65e3762e2c4..d7adc067740 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -1,11 +1,18 @@ #![feature(plugin)] #![plugin(clippy)] +//#![plugin(regex_macros)] +//extern crate regex; + #[deny(mut_mut)] fn fun(x : &mut &mut u32) -> bool { //~ERROR **x > 0 } +macro_rules! mut_ptr { + ($p:expr) => { &mut $p } +} + #[deny(mut_mut)] #[allow(unused_mut, unused_variables)] fn main() { @@ -22,4 +29,6 @@ fn main() { //~^^^^ ERROR ***y + **x; } + + let mut z = mut_ptr!(&mut 3u32); //~ERROR } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 04f3fc16b1b..6fcf71d38ad 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); let cfg_mode = mode.parse().ok().expect("Invalid mode"); - config.target_rustcflags = Some("-L target/debug/".to_string()); + config.target_rustcflags = Some("-l regex_macros -L target/debug/".to_string()); config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); diff --git a/tests/run-pass.rs b/tests/run-pass.rs new file mode 100644 index 00000000000..bc39278606c --- /dev/null +++ b/tests/run-pass.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy, regex_macros)] + +extern crate regex; + +#[test] +#[deny(mut_mut)] +fn test_regex() { + let pattern = regex!(r"^(?P[#]+)\s(?P.+)$"); + assert!(pattern.is_match("# headline")); +} -- cgit 1.4.1-3-g733a5 From cd2e621c60b897a2f37fab36bc357da30aa9cc54 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 26 May 2015 13:52:40 +0200 Subject: made in_macro distinguish intra-crate and extra-crate macros, as the latter have no working source (note: may fail in the face of compiler plugins doing whatever they like with spans), also one more run-pass test --- Cargo.toml | 1 + src/mut_mut.rs | 14 ++++++++++---- tests/run-pass.rs | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3c7d9be64e3..e1308fb9cb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ plugin = true compiletest_rs = "*" regex = "*" regex_macros = "*" +lazy_static = "*" diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 160b99a1d15..a4c2d3932a3 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -2,7 +2,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; -use syntax::codemap::ExpnInfo; +use syntax::codemap::{BytePos, ExpnInfo, MacroFormat, Span}; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -27,7 +27,7 @@ impl LintPass for MutMut { } fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { - if in_macro(info) { return; } + if in_macro(cx, info) { return; } fn unwrap_addr(expr : &Expr) -> Option<&Expr> { match expr.node { @@ -51,8 +51,14 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { }) } -fn in_macro(info: Option<&ExpnInfo>) -> bool { - info.is_some() +fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + opt_info.map_or(false, |info| { + info.callee.span.map_or(true, |span| { + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + !code.starts_with("macro_rules") + ) + }) + }) } fn unwrap_mut(ty : &Ty) -> Option<&Ty> { diff --git a/tests/run-pass.rs b/tests/run-pass.rs index bc39278606c..32fdea3a340 100644 --- a/tests/run-pass.rs +++ b/tests/run-pass.rs @@ -1,11 +1,31 @@ #![feature(plugin)] #![plugin(clippy, regex_macros)] +#[macro_use] +extern crate lazy_static; extern crate regex; +use std::collections::HashMap; + #[test] #[deny(mut_mut)] fn test_regex() { let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); assert!(pattern.is_match("# headline")); } + +#[test] +#[deny(mut_mut)] +#[allow(unused_variables, unused_mut)] +fn test_lazy_static() { + lazy_static! { + static ref MUT_MAP : HashMap<usize, &'static str> = { + let mut m = HashMap::new(); + let mut zero = &mut &mut "zero"; + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert!(*MUT_COUNT == 1); +} -- cgit 1.4.1-3-g733a5 From 7e16822925380d4c4236caec116c8076b8ca150a Mon Sep 17 00:00:00 2001 From: Matthew Hall <matthew@quickbeam.me.uk> Date: Fri, 29 May 2015 15:07:34 +0100 Subject: Add lint for ifs that could be collapsed "Collapsible" ifs are ones which contain only a then block, and the then block consists of an if that only has a then block. --- src/collapsible_if.rs | 80 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ tests/compile-fail/collapsible_if.rs | 37 +++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/collapsible_if.rs create mode 100644 tests/compile-fail/collapsible_if.rs diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs new file mode 100644 index 00000000000..31ac1e62be6 --- /dev/null +++ b/src/collapsible_if.rs @@ -0,0 +1,80 @@ +//! Checks for if expressions that contain only an if expression. +//! +//! For example, the lint would catch: +//! +//! ``` +//! if x { +//! if y { +//! println!("Hello world"); +//! } +//! } +//! ``` +//! +//! This lint is **warn** by default + +use rustc::plugin::Registry; +use rustc::lint::*; +use rustc::middle::def::*; +use syntax::ast::*; +use syntax::ptr::P; +use syntax::codemap::{Span, Spanned}; +use syntax::print::pprust::expr_to_string; + +declare_lint! { + pub COLLAPSIBLE_IF, + Warn, + "Warn on if expressions that can be collapsed" +} + +#[derive(Copy,Clone)] +pub struct CollapsibleIf; + +impl LintPass for CollapsibleIf { + fn get_lints(&self) -> LintArray { + lint_array!(COLLAPSIBLE_IF) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let ExprIf(ref check, ref then_block, None) = e.node { + let expr = check_block(then_block); + let expr = match expr { + Some(e) => e, + None => return + }; + if let ExprIf(ref check_inner, _, None) = expr.node { + let (check, check_inner) = (check_to_string(check), check_to_string(check_inner)); + cx.span_lint(COLLAPSIBLE_IF, e.span, + &format!("This if statement can be collapsed. Try: if {} && {}", check, check_inner)); + } + } + } +} + +fn requires_brackets(e: &Expr) -> bool { + match e.node { + ExprBinary(Spanned {node: n, ..}, _, _) if n == BiEq => false, + _ => true + } +} + +fn check_to_string(e: &Expr) -> String { + if requires_brackets(e) { + format!("({})", expr_to_string(e)) + } else { + format!("{}", expr_to_string(e)) + } +} + +fn check_block(b: &Block) -> Option<&P<Expr>> { + if b.stmts.len() == 1 && b.expr.is_none() { + let stmt = &b.stmts[0]; + return match stmt.node { + StmtExpr(ref e, _) => Some(e), + _ => None + }; + } + if let Some(ref e) = b.expr { + return Some(e); + } + None +} diff --git a/src/lib.rs b/src/lib.rs index cf5def800a2..00d28deeed9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ pub mod eta_reduction; pub mod identity_op; pub mod mut_mut; pub mod len_zero; +pub mod collapsible_if; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -45,6 +46,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); reg.register_lint_pass(box len_zero::LenZero as LintPassObject); reg.register_lint_pass(box misc::CmpOwned as LintPassObject); + reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -61,5 +63,6 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_mut::MUT_MUT, len_zero::LEN_ZERO, len_zero::LEN_WITHOUT_IS_EMPTY, + collapsible_if::COLLAPSIBLE_IF, ]); } diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs new file mode 100644 index 00000000000..3aa86c893c6 --- /dev/null +++ b/tests/compile-fail/collapsible_if.rs @@ -0,0 +1,37 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(collapsible_if)] +fn main() { + let x = "hello"; + let y = "world"; + if x == "hello" { //~ERROR This if statement can be collapsed + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" || x == "world" { //~ERROR This if statement can be collapsed + if y == "world" || y == "hello" { + println!("Hello world!"); + } + } + + // Works because any if with an else statement cannot be collapsed. + if x == "hello" { + if y == "world" { + println!("Hello world!"); + } + } else { + println!("Not Hello world"); + } + + if x == "hello" { + if y == "world" { + println!("Hello world!"); + } else { + println!("Hello something else"); + } + } + +} -- cgit 1.4.1-3-g733a5 From 77838d6ba78c23fdc337da7ece974beda95280df Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 30 May 2015 15:10:19 +0200 Subject: New lint for issue #72 --- src/attrs.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ tests/compile-fail/attrs.rs | 12 ++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/attrs.rs create mode 100644 tests/compile-fail/attrs.rs diff --git a/src/attrs.rs b/src/attrs.rs new file mode 100644 index 00000000000..3ad3889f9db --- /dev/null +++ b/src/attrs.rs @@ -0,0 +1,48 @@ +/// checks for attributes + +use rustc::plugin::Registry; +use rustc::lint::*; +use syntax::ast::*; +use syntax::ptr::P; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; + +declare_lint! { pub INLINE_ALWAYS, Warn, + "#[inline(always)] is usually a bad idea."} + + +#[derive(Copy,Clone)] +pub struct AttrPass; + +impl LintPass for AttrPass { + fn get_lints(&self) -> LintArray { + lint_array!(INLINE_ALWAYS) + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + check_attrs(cx, &item.ident, &item.attrs) + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + check_attrs(cx, &item.ident, &item.attrs) + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + check_attrs(cx, &item.ident, &item.attrs) + } +} + +fn check_attrs(cx: &Context, ident: &Ident, attrs: &[Attribute]) { + for attr in attrs { + if let MetaList(ref inline, ref values) = attr.node.value.node { + if values.len() != 1 || inline != &"inline" { continue; } + if let MetaWord(ref always) = values[0].node { + if always != &"always" { continue; } + cx.span_lint(INLINE_ALWAYS, attr.span, &format!( + "You have declared #[inline(always)] on {}. This \ + is usually a bad idea. Are you sure?", + ident.as_str())); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 92cc7ef254c..918f8813cd2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub mod eta_reduction; pub mod identity_op; pub mod mut_mut; pub mod len_zero; +pub mod attrs; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -44,6 +45,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); reg.register_lint_pass(box len_zero::LenZero as LintPassObject); reg.register_lint_pass(box misc::CmpOwned as LintPassObject); + reg.register_lint_pass(box attrs::AttrPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -60,5 +62,6 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_mut::MUT_MUT, len_zero::LEN_ZERO, len_zero::LEN_WITHOUT_IS_EMPTY, + attrs::INLINE_ALWAYS, ]); } diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs new file mode 100644 index 00000000000..30ce191d3db --- /dev/null +++ b/tests/compile-fail/attrs.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(inline_always)] +#[inline(always)] //~ERROR You have declared #[inline(always)] on test_attr_lint. +fn test_attr_lint() { + assert!(true) +} + +fn main() { + test_attr_lint() +} -- cgit 1.4.1-3-g733a5 From 423a9666ca5c688dfd333cc7e6a93944b23a9f6f Mon Sep 17 00:00:00 2001 From: Matthew Hall <matthew@quickbeam.me.uk> Date: Sun, 31 May 2015 13:17:31 +0100 Subject: Implements #45 - any number mod 1 will be 0 --- src/lib.rs | 2 ++ src/misc.rs | 31 +++++++++++++++++++++++++++++++ tests/compile-fail/modulo_one.rs | 8 ++++++++ 3 files changed, 41 insertions(+) create mode 100644 tests/compile-fail/modulo_one.rs diff --git a/src/lib.rs b/src/lib.rs index 00d28deeed9..1d760bde99a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box len_zero::LenZero as LintPassObject); reg.register_lint_pass(box misc::CmpOwned as LintPassObject); reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); + reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -64,5 +65,6 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_ZERO, len_zero::LEN_WITHOUT_IS_EMPTY, collapsible_if::COLLAPSIBLE_IF, + misc::MODULO_ONE, ]); } diff --git a/src/misc.rs b/src/misc.rs index b8ce6d725f4..590ebbc3f9f 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -266,3 +266,34 @@ fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty_str = walk_ty(expr_ty(cx.tcx, &*args[0])).sty { true } else { false } } + + +declare_lint!(pub MODULO_ONE, Warn, "Warn on expressions that include % 1, which is always 0"); + +#[derive(Copy,Clone)] +pub struct ModuloOne; + +impl LintPass for ModuloOne { + fn get_lints(&self) -> LintArray { + lint_array!(MODULO_ONE) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, _, ref right) = expr.node { + if let &Spanned {node: BinOp_::BiRem, ..} = cmp { + if is_lit_one(right) { + cx.span_lint(MODULO_ONE, expr.span, "Any number modulo 1 will be 0"); + } + } + } + } +} + +fn is_lit_one(expr: &Expr) -> bool { + if let ExprLit(ref spanned) = expr.node { + if let LitInt(1, _) = spanned.node { + return true; + } + } + false +} diff --git a/tests/compile-fail/modulo_one.rs b/tests/compile-fail/modulo_one.rs new file mode 100644 index 00000000000..26c7de855e5 --- /dev/null +++ b/tests/compile-fail/modulo_one.rs @@ -0,0 +1,8 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(modulo_one)] + +fn main() { + 10 % 1; //~ERROR Any number modulo 1 will be 0 + 10 % 2; +} -- cgit 1.4.1-3-g733a5 From 21cd0c7e703c1303930f1b6735384ae806fd7c01 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Jun 2015 07:40:33 +0200 Subject: check for is_empty() method to get rid of false positives --- src/len_zero.rs | 36 +++++++++++++++++++++++++++++++----- tests/compile-fail/len_zero.rs | 3 +-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 18ddbccc9a2..621cee57328 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,11 +1,15 @@ extern crate rustc_typeck as typeck; +use std::rc::Rc; +use std::cell::RefCell; use syntax::ptr::P; -use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::middle::ty::{self, node_id_to_type, sty, ty_ptr, ty_rptr, mt, MethodTraitItemId}; +use rustc::util::nodemap::DefIdMap; +use rustc::middle::ty::{self, node_id_to_type, sty, ty_ptr, ty_rptr, expr_ty, + mt, ty_to_def_id, impl_or_trait_item, MethodTraitItemId, ImplOrTraitItemId}; use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; +use syntax::ast::*; declare_lint!(pub LEN_ZERO, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -69,7 +73,9 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { for i in impl_items { if is_named_self(i, "len") { - cx.span_lint(LEN_WITHOUT_IS_EMPTY, i.span, + let s = i.span; + cx.span_lint(LEN_WITHOUT_IS_EMPTY, + Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, &format!("Item '{}' has a '.len()' method, but no \ '.is_empty()' method. Consider adding one.", item.ident.as_str())); @@ -92,10 +98,30 @@ fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, empty: &str) { if let &Spanned{node: LitInt(0, _), ..} = lit { - if method.node.as_str() == "len" && args.len() == 1 { + if method.node.as_str() == "len" && args.len() == 1 && + has_is_empty(cx, &expr_ty(cx.tcx, &*args[0])) { cx.span_lint(LEN_ZERO, span, &format!( - "Consider replacing the len comparison with '{}_.is_empty()' if available", + "Consider replacing the len comparison with \ + '{}_.is_empty()' if available", empty)) } } } + +fn has_is_empty(cx: &Context, ty: &::rustc::middle::ty::Ty) -> bool { + fn check_item(cx: &Context, id: &ImplOrTraitItemId) -> bool { + if let &MethodTraitItemId(ref def_id) = id { + if let ty::MethodTraitItem(ref method) = ty::impl_or_trait_item( + cx.tcx, *def_id) { + method.name.as_str() == "is_empty" + } else { false } + } else { false } + } + + ::rustc::middle::ty::ty_to_def_id(ty).map_or(true, |id| { + cx.tcx.impl_items.borrow().get(&id).map_or(false, |item_ids| { + item_ids.iter().any(|i| check_item(cx, i)) + }) || cx.tcx.trait_item_def_ids.borrow().get(&id).map_or(false, + |item_ids| { item_ids.iter().any(|i| check_item(cx, i)) }) + }) +} diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 14f2506ec8b..39fcb3c1804 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -44,8 +44,7 @@ fn main() { } let y = One; - // false positives here - if y.len() == 0 { //~ERROR Consider replacing the len comparison + if y.len() == 0 { //no error because One does not have .is_empty() println!("This should not happen either!"); } -- cgit 1.4.1-3-g733a5 From cdca2c93c1949fcb9a4e3dd696fff01f3ff3dcf1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Jun 2015 12:49:36 +0200 Subject: now the method lookup actually works (and I understand why! :smile:), reduces unnecessary loops, and has a few comments --- src/len_zero.rs | 64 +++++++++++++++++++++++++++++------------- src/misc.rs | 2 +- tests/compile-fail/len_zero.rs | 59 ++++++++++++++++++++++++++++++++++---- tests/mut_mut_macro.rs | 11 ++++++++ tests/run-pass.rs | 11 -------- 5 files changed, 109 insertions(+), 38 deletions(-) create mode 100644 tests/mut_mut_macro.rs delete mode 100644 tests/run-pass.rs diff --git a/src/len_zero.rs b/src/len_zero.rs index 621cee57328..fef280199bd 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -10,6 +10,7 @@ use rustc::middle::ty::{self, node_id_to_type, sty, ty_ptr, ty_rptr, expr_ty, use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; +use misc::walk_ty; declare_lint!(pub LEN_ZERO, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -49,7 +50,8 @@ impl LintPass for LenZero { fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.ident.as_str() == name && item.attrs.len() == 0 + item.ident.as_str() == name && if let MethodTraitItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { @@ -57,8 +59,8 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { for i in trait_items { if is_named_self(i, "len") { cx.span_lint(LEN_WITHOUT_IS_EMPTY, i.span, - &format!("Trait '{}' has a '.len()' method, but no \ - '.is_empty()' method. Consider adding one.", + &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", item.ident.as_str())); } }; @@ -67,7 +69,8 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.ident.as_str() == name && item.attrs.len() == 0 + item.ident.as_str() == name && if let MethodImplItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } } if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { @@ -76,8 +79,8 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { let s = i.span; cx.span_lint(LEN_WITHOUT_IS_EMPTY, Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, - &format!("Item '{}' has a '.len()' method, but no \ - '.is_empty()' method. Consider adding one.", + &format!("Item '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", item.ident.as_str())); return; } @@ -85,6 +88,11 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { } } +fn is_self_sig(sig: &MethodSig) -> bool { + if let SelfStatic = sig.explicit_self.node { + false } else { sig.decl.inputs.len() == 1 } +} + fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => @@ -99,29 +107,45 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, empty: &str) { if let &Spanned{node: LitInt(0, _), ..} = lit { if method.node.as_str() == "len" && args.len() == 1 && - has_is_empty(cx, &expr_ty(cx.tcx, &*args[0])) { + has_is_empty(cx, &*args[0]) { cx.span_lint(LEN_ZERO, span, &format!( - "Consider replacing the len comparison with \ - '{}_.is_empty()' if available", + "Consider replacing the len comparison with '{}_.is_empty()'", empty)) } } } -fn has_is_empty(cx: &Context, ty: &::rustc::middle::ty::Ty) -> bool { - fn check_item(cx: &Context, id: &ImplOrTraitItemId) -> bool { - if let &MethodTraitItemId(ref def_id) = id { - if let ty::MethodTraitItem(ref method) = ty::impl_or_trait_item( - cx.tcx, *def_id) { +/// check if this type has an is_empty method +fn has_is_empty(cx: &Context, expr: &Expr) -> bool { + /// get a ImplOrTraitItem and return true if it matches is_empty(self) + fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { + if let &MethodTraitItemId(def_id) = id { + if let ty::MethodTraitItem(ref method) = + ty::impl_or_trait_item(cx.tcx, def_id) { method.name.as_str() == "is_empty" + && method.fty.sig.skip_binder().inputs.len() == 1 } else { false } } else { false } } - ::rustc::middle::ty::ty_to_def_id(ty).map_or(true, |id| { - cx.tcx.impl_items.borrow().get(&id).map_or(false, |item_ids| { - item_ids.iter().any(|i| check_item(cx, i)) - }) || cx.tcx.trait_item_def_ids.borrow().get(&id).map_or(false, - |item_ids| { item_ids.iter().any(|i| check_item(cx, i)) }) - }) + /// check the inherent impl's items for an is_empty(self) method + fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { + let impl_items = cx.tcx.impl_items.borrow(); + cx.tcx.inherent_impls.borrow().get(id).map_or(false, + |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, + |iids| iids.iter().any(|i| is_is_empty(cx, i))))) + } + + let ty = &walk_ty(&expr_ty(cx.tcx, expr)); + match ty.sty { + ty::ty_trait(_) => cx.tcx.trait_item_def_ids.borrow().get( + &ty::ty_to_def_id(ty).expect("trait impl not found")).map_or(false, + |ids| ids.iter().any(|i| is_is_empty(cx, i))), + ty::ty_projection(_) => ty::ty_to_def_id(ty).map_or(false, + |id| has_is_empty_impl(cx, &id)), + ty::ty_enum(ref id, _) | ty::ty_struct(ref id, _) => + has_is_empty_impl(cx, id), + ty::ty_vec(..) => true, + _ => false, + } } diff --git a/src/misc.rs b/src/misc.rs index b8ce6d725f4..5d0d79544e9 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -10,7 +10,7 @@ use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; -fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { +pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { match ty.sty { ty_ptr(ref tm) | ty_rptr(_, ref tm) => walk_ty(tm.ty), _ => ty diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 39fcb3c1804..e64010d334d 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -5,14 +5,14 @@ struct One; #[deny(len_without_is_empty)] impl One { - fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len()' method + fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' 1 } } #[deny(len_without_is_empty)] trait TraitsToo { - fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len()' method, + fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: } impl TraitsToo for One { @@ -21,17 +21,47 @@ impl TraitsToo for One { } } -#[allow(dead_code)] struct HasIsEmpty; #[deny(len_without_is_empty)] -#[allow(dead_code)] impl HasIsEmpty { fn len(self: &Self) -> isize { 1 } + + fn is_empty(self: &Self) -> bool { + false + } +} + +struct Wither; + +#[deny(len_without_is_empty)] +trait WithIsEmpty { + fn len(self: &Self) -> isize; + fn is_empty(self: &Self) -> bool; +} + +impl WithIsEmpty for Wither { + fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +struct HasWrongIsEmpty; + +#[deny(len_without_is_empty)] +impl HasWrongIsEmpty { + fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' + 1 + } - fn is_empty() -> bool { + #[allow(dead_code, unused)] + fn is_empty(self: &Self, x : u32) -> bool { false } } @@ -49,7 +79,24 @@ fn main() { } let z : &TraitsToo = &y; - if z.len() > 0 { //~ERROR Consider replacing the len comparison + if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method println!("Nor should this!"); } + + let hie = HasIsEmpty; + if hie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!hie.is_empty()); + + let wie : &WithIsEmpty = &Wither; + if wie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!wie.is_empty()); + + let hwie = HasWrongIsEmpty; + if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() + println!("Or this!"); + } } diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs new file mode 100644 index 00000000000..bc39278606c --- /dev/null +++ b/tests/mut_mut_macro.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy, regex_macros)] + +extern crate regex; + +#[test] +#[deny(mut_mut)] +fn test_regex() { + let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); + assert!(pattern.is_match("# headline")); +} diff --git a/tests/run-pass.rs b/tests/run-pass.rs deleted file mode 100644 index bc39278606c..00000000000 --- a/tests/run-pass.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy, regex_macros)] - -extern crate regex; - -#[test] -#[deny(mut_mut)] -fn test_regex() { - let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); - assert!(pattern.is_match("# headline")); -} -- cgit 1.4.1-3-g733a5 From 1ee2e4ffe8a4ca40676fe6b372570d4e51c2f375 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Jun 2015 15:09:17 +0200 Subject: Fixed block check, also added macro test to collapsible_if and inline_always --- src/attrs.rs | 17 +++++++--- src/collapsible_if.rs | 60 ++++++++++++++++++++---------------- src/mut_mut.rs | 2 +- tests/compile-fail/collapsible_if.rs | 6 ++++ tests/compile-test.rs | 2 +- 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 3ad3889f9db..f056ac6ee8c 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -4,8 +4,9 @@ use rustc::plugin::Registry; use rustc::lint::*; use syntax::ast::*; use syntax::ptr::P; -use syntax::codemap::Span; +use syntax::codemap::{Span, ExpnInfo}; use syntax::parse::token::InternedString; +use mut_mut::in_macro; declare_lint! { pub INLINE_ALWAYS, Warn, "#[inline(always)] is usually a bad idea."} @@ -20,19 +21,25 @@ impl LintPass for AttrPass { } fn check_item(&mut self, cx: &Context, item: &Item) { - check_attrs(cx, &item.ident, &item.attrs) + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) } fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - check_attrs(cx, &item.ident, &item.attrs) + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - check_attrs(cx, &item.ident, &item.attrs) + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) } } -fn check_attrs(cx: &Context, ident: &Ident, attrs: &[Attribute]) { +fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, + attrs: &[Attribute]) { + if in_macro(cx, info) { return; } + for attr in attrs { if let MetaList(ref inline, ref values) = attr.node.value.node { if values.len() != 1 || inline != &"inline" { continue; } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 31ac1e62be6..b9ebeed01de 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -17,8 +17,9 @@ use rustc::lint::*; use rustc::middle::def::*; use syntax::ast::*; use syntax::ptr::P; -use syntax::codemap::{Span, Spanned}; +use syntax::codemap::{Span, Spanned, ExpnInfo}; use syntax::print::pprust::expr_to_string; +use mut_mut::in_macro; declare_lint! { pub COLLAPSIBLE_IF, @@ -34,20 +35,23 @@ impl LintPass for CollapsibleIf { lint_array!(COLLAPSIBLE_IF) } - fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let ExprIf(ref check, ref then_block, None) = e.node { - let expr = check_block(then_block); - let expr = match expr { - Some(e) => e, - None => return - }; - if let ExprIf(ref check_inner, _, None) = expr.node { - let (check, check_inner) = (check_to_string(check), check_to_string(check_inner)); - cx.span_lint(COLLAPSIBLE_IF, e.span, - &format!("This if statement can be collapsed. Try: if {} && {}", check, check_inner)); - } - } - } + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) + } +} + +fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { + if in_macro(cx, info) { return; } + + if let ExprIf(ref check, ref then, None) = e.node { + if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = + single_stmt_of_block(then) { + cx.span_lint(COLLAPSIBLE_IF, e.span, &format!( + "This if statement can be collapsed. Try: if {} && {}\n{:?}", + check_to_string(check), check_to_string(check_inner), e)); + } + } } fn requires_brackets(e: &Expr) -> bool { @@ -65,16 +69,20 @@ fn check_to_string(e: &Expr) -> String { } } -fn check_block(b: &Block) -> Option<&P<Expr>> { - if b.stmts.len() == 1 && b.expr.is_none() { - let stmt = &b.stmts[0]; - return match stmt.node { - StmtExpr(ref e, _) => Some(e), - _ => None - }; - } - if let Some(ref e) = b.expr { - return Some(e); +fn single_stmt_of_block(block: &Block) -> Option<&Expr> { + if block.stmts.len() == 1 && block.expr.is_none() { + if let StmtExpr(ref expr, _) = block.stmts[0].node { + single_stmt_of_expr(expr) + } else { None } + } else { + if block.stmts.is_empty() { + if let Some(ref p) = block.expr { Some(&*p) } else { None } + } else { None } } - None +} + +fn single_stmt_of_expr(expr: &Expr) -> Option<&Expr> { + if let ExprBlock(ref block) = expr.node { + single_stmt_of_block(block) + } else { Some(expr) } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index a4c2d3932a3..3ba9c47e7fe 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -51,7 +51,7 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { }) } -fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { +pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { opt_info.map_or(false, |info| { info.callee.span.map_or(true, |span| { cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index 3aa86c893c6..7b7ff13f24b 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -34,4 +34,10 @@ fn main() { } } + if x == "hello" { + print!("Hello "); + if y == "world" { + println!("world!") + } + } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 6fcf71d38ad..04f3fc16b1b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); let cfg_mode = mode.parse().ok().expect("Invalid mode"); - config.target_rustcflags = Some("-l regex_macros -L target/debug/".to_string()); + config.target_rustcflags = Some("-L target/debug/".to_string()); config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); -- cgit 1.4.1-3-g733a5 From 30de91d3e9e724c8ebc5d3df342aa4e66a88dd47 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Jun 2015 22:30:34 +0200 Subject: moved in_macro to (new) utils.rs --- src/attrs.rs | 2 +- src/collapsible_if.rs | 2 +- src/mut_mut.rs | 11 +---------- src/utils.rs | 12 ++++++++++++ 4 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 src/utils.rs diff --git a/src/attrs.rs b/src/attrs.rs index f056ac6ee8c..5ee8745c33e 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -6,7 +6,7 @@ use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, ExpnInfo}; use syntax::parse::token::InternedString; -use mut_mut::in_macro; +use utils::in_macro; declare_lint! { pub INLINE_ALWAYS, Warn, "#[inline(always)] is usually a bad idea."} diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index b9ebeed01de..85c1b25a673 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -19,7 +19,7 @@ use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned, ExpnInfo}; use syntax::print::pprust::expr_to_string; -use mut_mut::in_macro; +use utils::in_macro; declare_lint! { pub COLLAPSIBLE_IF, diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 3ba9c47e7fe..202b5600dbe 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -3,6 +3,7 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; use syntax::codemap::{BytePos, ExpnInfo, MacroFormat, Span}; +use utils::in_macro; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -51,16 +52,6 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { }) } -pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { - opt_info.map_or(false, |info| { - info.callee.span.map_or(true, |span| { - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| - !code.starts_with("macro_rules") - ) - }) - }) -} - fn unwrap_mut(ty : &Ty) -> Option<&Ty> { match ty.node { TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000000..e6e0c0e4868 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,12 @@ +use rustc::lint::Context; +use syntax::codemap::ExpnInfo; + +fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + opt_info.map_or(false, |info| { + info.callee.span.map_or(true, |span| { + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + !code.starts_with("macro_rules") + ) + }) + }) +} -- cgit 1.4.1-3-g733a5 From e8ca19da244e2dce17c599fd35565f6e47ff19e9 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Jun 2015 22:36:56 +0200 Subject: fixed modules/visibility --- src/lib.rs | 1 + src/utils.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 37cdf6a9c58..06922ef5674 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ pub mod mut_mut; pub mod len_zero; pub mod attrs; pub mod collapsible_if; +pub mod utils; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/utils.rs b/src/utils.rs index e6e0c0e4868..c67ded3d93d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use rustc::lint::Context; use syntax::codemap::ExpnInfo; -fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { +pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { opt_info.map_or(false, |info| { info.callee.span.map_or(true, |span| { cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| -- cgit 1.4.1-3-g733a5 From 87047c3223434f38c4012f4fac71b5dedf0ba169 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 2 Jun 2015 09:23:22 +0200 Subject: explained recently added lints --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0bea2fad1d6..4a85a319bf0 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ Lints included in this crate: - `len_zero`: Warns on `_.len() == 0` and suggests using `_.is_empty()` (or similar comparisons with `>` or `!=`) - `len_without_is_empty`: Warns on traits or impls that have a `.len()` but no `.is_empty()` method - `cmp_owned`: Warns on creating owned instances for comparing with others, e.g. `x == "foo".to_string()` + - `redundant_closure` warns on creating a closure where none is needed, e.g. `|x| foo(x)`, where `foo` can be used directly + - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea + - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` To use, add the following lines to your Cargo.toml: -- cgit 1.4.1-3-g733a5 From 240d9716d89df4dcf7247b6fa6a6b1976ef78fb2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 4 Jun 2015 09:15:56 +0530 Subject: Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4a85a319bf0..e80af039f57 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,9 @@ clippy = "*" More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! ##Usage + +Compiler plugins are highly unstable and will only work with a nightly Rust for now. Since stable Rust is backwards compatible you hsould be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this. + Add in your `Cargo.toml`: ```toml [dependencies.clippy] -- cgit 1.4.1-3-g733a5 From b44435ef2843f7ec35684d2cfe37535efc82f360 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 6 Jun 2015 02:07:48 +0200 Subject: extended compile-test.rs to actually observe TESTNAME environment variable and filter tests if available --- tests/compile-test.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 04f3fc16b1b..4af4ea7673a 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,11 +1,17 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; +use std::env::var; fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); + let cfg_mode = mode.parse().ok().expect("Invalid mode"); - config.target_rustcflags = Some("-L target/debug/".to_string()); + config.target_rustcflags = Some("-L target/debug/".to_owned()); + if let Ok(name) = var::<&str>("TESTNAME") { + let s : String = name.to_owned(); + config.filter = Some(s) + } config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); -- cgit 1.4.1-3-g733a5 From 8563ee60ecf02be54c39dad0c063763c9dce4e91 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 6 Jun 2015 02:27:48 +0200 Subject: fixed issue #88 in bit_mask --- src/bit_mask.rs | 24 ++++++++++++++++-------- tests/compile-fail/bit_masks.rs | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 352826dffae..f3f95f92d9a 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -89,20 +89,26 @@ fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, sp } } -fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { +fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, + mask_value: u64, cmp_value: u64, span: &Span) { match cmp_op { BiEq | BiNe => match bit_op { BiBitAnd => if mask_value & cmp_value != mask_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} can never be equal to {}", mask_value, - cmp_value)); + if cmp_value != 0 { + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} can never be equal to {}", + mask_value, cmp_value)); + } } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + cx.span_lint(BAD_BIT_MASK, *span, + &format!("&-masking with zero")); } }, BiBitOr => if mask_value | cmp_value != cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} can never be equal to {}", mask_value, - cmp_value)); + cx.span_lint(BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} can never be equal to {}", + mask_value, cmp_value)); }, _ => () }, @@ -113,7 +119,8 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, mask_value, cmp_value)); } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + cx.span_lint(BAD_BIT_MASK, *span, + &format!("&-masking with zero")); } }, BiBitOr => if mask_value >= cmp_value { @@ -136,7 +143,8 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, mask_value, cmp_value)); } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero")); + cx.span_lint(BAD_BIT_MASK, *span, + &format!("&-masking with zero")); } }, BiBitOr => if mask_value > cmp_value { diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index e45b789800e..e6b89b98564 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -11,6 +11,7 @@ fn main() { x & 0 == 0; //~ERROR &-masking with zero x & 1 == 1; //ok, distinguishes bit 0 + x & 1 == 0; //ok, compared with zero x & 2 == 1; //~ERROR x | 0 == 0; //ok, equals x == 0 (maybe warn?) x | 1 == 3; //ok, equals x == 2 || x == 3 -- cgit 1.4.1-3-g733a5 From a275d99628bea790166fd53256202182b049a8df Mon Sep 17 00:00:00 2001 From: Michael Rutherford <michaellogan.rutherford@gmail.com> Date: Sat, 6 Jun 2015 13:28:58 -0500 Subject: Fixed spelling error Fixed a spelling error and added a comma in the README.md file. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e80af039f57..3efeb748b9e 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ##Usage -Compiler plugins are highly unstable and will only work with a nightly Rust for now. Since stable Rust is backwards compatible you hsould be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this. +Compiler plugins are highly unstable and will only work with a nightly Rust for now. Since stable Rust is backwards compatible, you should be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this. Add in your `Cargo.toml`: ```toml -- cgit 1.4.1-3-g733a5 From 1f74c4b3597d9062f3e6d8f908758598b3f904db Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 7 Jun 2015 12:03:56 +0200 Subject: removed false positives from inline_always (issue #84) --- src/attrs.rs | 71 ++++++++++++++++++++++++++++++++++++++++----- tests/compile-fail/attrs.rs | 25 ++++++++++++++-- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 5ee8745c33e..d5a56b1547f 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -6,7 +6,7 @@ use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, ExpnInfo}; use syntax::parse::token::InternedString; -use utils::in_macro; +use utils::{in_macro, match_path}; declare_lint! { pub INLINE_ALWAYS, Warn, "#[inline(always)] is usually a bad idea."} @@ -21,18 +21,73 @@ impl LintPass for AttrPass { } fn check_item(&mut self, cx: &Context, item: &Item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + if is_relevant_item(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } } - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if is_relevant_impl(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + if is_relevant_trait(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } +} + +fn is_relevant_item(item: &Item) -> bool { + if let &ItemFn(_, _, _, _, _, ref block) = &item.node { + is_relevant_block(block) + } else { false } +} + +fn is_relevant_impl(item: &ImplItem) -> bool { + match item.node { + MethodImplItem(_, ref block) => is_relevant_block(block), + _ => false + } +} + +fn is_relevant_trait(item: &TraitItem) -> bool { + match item.node { + MethodTraitItem(_, None) => true, + MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), + _ => false + } +} + +fn is_relevant_block(block: &Block) -> bool { + for stmt in block.stmts.iter() { + match stmt.node { + StmtDecl(_, _) => return true, + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { + return is_relevant_expr(expr); + } + _ => () + } + } + block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) +} + +fn is_relevant_expr(expr: &Expr) -> bool { + match expr.node { + ExprBlock(ref block) => is_relevant_block(block), + ExprRet(Some(ref e)) | ExprParen(ref e) => + is_relevant_expr(&*e), + ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, + ExprCall(ref path_expr, _) => { + if let ExprPath(_, ref path) = path_expr.node { + !match_path(path, &["std", "rt", "begin_unwind"]) + } else { true } + } + _ => true } } diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs index 30ce191d3db..9b648a517e0 100644 --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -1,12 +1,33 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(inline_always)] +#![deny(inline_always)] + #[inline(always)] //~ERROR You have declared #[inline(always)] on test_attr_lint. fn test_attr_lint() { assert!(true) } +#[inline(always)] +fn false_positive_expr() { + unreachable!() +} + +#[inline(always)] +fn false_positive_stmt() { + unreachable!(); +} + +#[inline(always)] +fn empty_and_false_positive_stmt() { + ; + unreachable!(); +} + + fn main() { - test_attr_lint() + test_attr_lint(); + if false { false_positive_expr() } + if false { false_positive_stmt() } + if false { empty_and_false_positive_stmt() } } -- cgit 1.4.1-3-g733a5 From 19e718966d0d3660df374f60022f219f5bf48469 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 7 Jun 2015 12:05:14 +0200 Subject: forgot to update utils, there are a few new s --- src/utils.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index c67ded3d93d..b99ed45b3c3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,12 +1,42 @@ use rustc::lint::Context; -use syntax::codemap::ExpnInfo; +use syntax::ast::{DefId, Name, Path}; +use syntax::codemap::{ExpnInfo, Span}; +use rustc::middle::ty; +/// returns true if the macro that expanded the crate was outside of +/// the current crate or was a compiler plugin pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + // no ExpnInfo = no macro opt_info.map_or(false, |info| { + // no span for the callee = external macro info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + // macro doesn't start with "macro_rules" + // = compiler plugin !code.starts_with("macro_rules") ) }) }) } + +/// invokes in_macro with the expansion info of the given span +pub fn in_external_macro(cx: &Context, span: Span) -> bool { + cx.sess().codemap().with_expn_info(span.expn_id, + |info| in_macro(cx, info)) +} + +/// check if a DefId's path matches the given absolute type path +/// usage e.g. with +/// `match_def_path(cx, id, &["core", "option", "Option"])` +pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { + ty::with_path(cx.tcx, def_id, |iter| iter.map(|elem| elem.name()) + .zip(path.iter()).all(|(nm, p)| &nm.as_str() == p)) +} + +/// match a Path against a slice of segment string literals, e.g. +/// `match_path(path, &["std", "rt", "begin_unwind"])` +pub fn match_path(path: &Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all( + |(a,b)| a.identifier.as_str() == *b) +} -- cgit 1.4.1-3-g733a5 From 23caf3cccc598dbe3228e407cc5864e9c5b6d5b8 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 11 Jun 2015 11:35:00 +0200 Subject: first unicode lint: zero_width_space --- README.md | 1 + src/lib.rs | 3 +++ src/unicode.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/unicode.rs | 25 ++++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 src/unicode.rs create mode 100644 tests/compile-fail/unicode.rs diff --git a/README.md b/README.md index 3efeb748b9e..979fb47985a 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Lints included in this crate: - `redundant_closure` warns on creating a closure where none is needed, e.g. `|x| foo(x)`, where `foo` can be used directly - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` + - `zero_width_space`: Warns on encountering a unicode zero-width space To use, add the following lines to your Cargo.toml: diff --git a/src/lib.rs b/src/lib.rs index 06922ef5674..647128e0f0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ pub mod mut_mut; pub mod len_zero; pub mod attrs; pub mod collapsible_if; +pub mod unicode; pub mod utils; #[plugin_registrar] @@ -49,6 +50,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::CmpOwned as LintPassObject); reg.register_lint_pass(box attrs::AttrPass as LintPassObject); reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); + reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -67,5 +69,6 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, attrs::INLINE_ALWAYS, collapsible_if::COLLAPSIBLE_IF, + unicode::ZERO_WIDTH_SPACE, ]); } diff --git a/src/unicode.rs b/src/unicode.rs new file mode 100644 index 00000000000..3ffcf699c26 --- /dev/null +++ b/src/unicode.rs @@ -0,0 +1,45 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::codemap::{BytePos, Span}; + +declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } + +#[derive(Copy, Clone)] +pub struct Unicode; + +impl LintPass for Unicode { + fn get_lints(&self) -> LintArray { + lint_array!(ZERO_WIDTH_SPACE) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprLit(ref lit) = expr.node { + if let LitStr(ref string, _) = lit.node { + check_str(cx, string, lit.span) + } + } + } +} + +fn check_str(cx: &Context, string: &str, span: Span) { + let mut start: Option<usize> = None; + for (i, c) in string.char_indices() { + if c == '\u{200B}' { + if start.is_none() { start = Some(i); } + } else { + lint_zero_width(cx, span, start); + start = None; + } + } + lint_zero_width(cx, span, start); +} + +fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) { + start.map(|index| { + cx.span_lint(ZERO_WIDTH_SPACE, Span { + lo: span.lo + BytePos(index as u32), + hi: span.lo + BytePos(index as u32), + expn_id: span.expn_id, + }, "Zero-width space detected. Consider using \\u{200B}") + }); +} diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs new file mode 100644 index 00000000000..0385f45cc5e --- /dev/null +++ b/tests/compile-fail/unicode.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(zero_width_space)] +fn zero() { + print!("Here >​< is a ZWS, and ​another"); + //~^ ERROR Zero-width space detected. Consider using \u{200B} + //~^^ ERROR Zero-width space detected. Consider using \u{200B} +} + +//#[deny(unicode_canon)] +fn canon() { + print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à +} + +//#[deny(ascii_only)] +fn uni() { + println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} +} + +fn main() { + zero(); + uni(); + canon(); +} -- cgit 1.4.1-3-g733a5 From 0e5b62c8d83046595f1be9231af3564644c4cfc1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 11 Jun 2015 16:53:23 +0200 Subject: also included String::from in cmp_owned and fixed deprecation in test --- src/misc.rs | 6 +++--- tests/compile-fail/cmp_owned.rs | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 5d0d79544e9..ec609fd2618 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,8 +7,8 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; use syntax::codemap::{Span, Spanned}; - use types::span_note_and_lint; +use utils::match_path; pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { match ty.sty { @@ -248,8 +248,8 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { }, &ExprCall(ref path, _) => { if let &ExprPath(None, ref path) = &path.node { - if path.segments.iter().zip(["String", "from_str"].iter()).all( - |(seg, name)| &seg.identifier.as_str() == name) { + if match_path(path, &["String", "from_str"]) || + match_path(path, &["String", "from"]) { cx.span_lint(CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index a8b0cb32f6f..d7399e6d3aa 100644 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -13,5 +13,11 @@ fn main() { x != "foo".to_owned(); //~ERROR this creates an owned instance - x != String::from_str("foo"); //~ERROR this creates an owned instance + #[allow(deprecated)] // for from_str + fn old_timey(x : &str) { + x != String::from_str("foo"); //~ERROR this creates an owned instance + } + old_timey(x); + + x != String::from("foo"); //~ERROR this creates an owned instance } -- cgit 1.4.1-3-g733a5 From be8cb319d8889b2ca10202b465fd5f20fec3b1ab Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Jun 2015 22:36:06 +0530 Subject: bump crates --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e1308fb9cb8..7240341dcab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.4" +version = "0.0.5" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" -- cgit 1.4.1-3-g733a5 From 9a3dcaabe8753ba7bdc687c4937d3ccb58d5d42f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 15 Jun 2015 13:27:24 +0200 Subject: fixed renaming of rustc::middle::ty enums --- src/len_zero.rs | 10 +++++----- src/misc.rs | 20 ++++++++++++-------- src/mut_mut.rs | 4 ++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 5d97efdf02c..0974e8f21e2 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use syntax::ptr::P; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::util::nodemap::DefIdMap; -use rustc::middle::ty::{self, node_id_to_type, sty, ty_ptr, ty_rptr, expr_ty, +use rustc::middle::ty::{self, node_id_to_type, TypeVariants, expr_ty, mt, ty_to_def_id, impl_or_trait_item, MethodTraitItemId, ImplOrTraitItemId}; use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; @@ -138,14 +138,14 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { let ty = &walk_ty(&expr_ty(cx.tcx, expr)); match ty.sty { - ty::ty_trait(_) => cx.tcx.trait_item_def_ids.borrow().get( + ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( &ty::ty_to_def_id(ty).expect("trait impl not found")).map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))), - ty::ty_projection(_) => ty::ty_to_def_id(ty).map_or(false, + ty::TyProjection(_) => ty::ty_to_def_id(ty).map_or(false, |id| has_is_empty_impl(cx, &id)), - ty::ty_enum(ref id, _) | ty::ty_struct(ref id, _) => + ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => has_is_empty_impl(cx, id), - ty::ty_vec(..) => true, + ty::TyArray(..) => true, _ => false, } } diff --git a/src/misc.rs b/src/misc.rs index ec609fd2618..f2492cf187d 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; +use rustc::middle::ty::{self, expr_ty}; use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; @@ -12,7 +12,7 @@ use utils::match_path; pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { match ty.sty { - ty_ptr(ref tm) | ty_rptr(_, ref tm) => walk_ty(tm.ty), + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ty(tm.ty), _ => ty } } @@ -79,10 +79,10 @@ impl LintPass for StrToStringPass { } fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ty(expr_ty(cx.tcx, expr)).sty { - ty_str => true, - _ => false - } + match walk_ty(expr_ty(cx.tcx, expr)).sty { + ty::TyStr => true, + _ => false + } } } } @@ -167,7 +167,11 @@ impl LintPass for FloatCmp { } fn is_float(cx: &Context, expr: &Expr) -> bool { - if let ty_float(_) = walk_ty(expr_ty(cx.tcx, expr)).sty { true } else { false } + if let ty::TyFloat(_) = walk_ty(expr_ty(cx.tcx, expr)).sty { + true + } else { + false + } } declare_lint!(pub PRECEDENCE, Warn, @@ -263,6 +267,6 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { } fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { - args.len() == 1 && if let ty_str = + args.len() == 1 && if let ty::TyStr = walk_ty(expr_ty(cx.tcx, &*args[0])).sty { true } else { false } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 202b5600dbe..fc5de44542f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,7 +1,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; +use rustc::middle::ty::{expr_ty, TypeVariants, mt, TyRef}; use syntax::codemap::{BytePos, ExpnInfo, MacroFormat, Span}; use utils::in_macro; @@ -42,7 +42,7 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { cx.span_lint(MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") }).unwrap_or_else(|| { - if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = + if let TyRef(_, mt{ty: _, mutbl: MutMutable}) = expr_ty(cx.tcx, e).sty { cx.span_lint(MUT_MUT, expr.span, "This expression mutably borrows a mutable reference. \ -- cgit 1.4.1-3-g733a5 From e774fd1650c40935f45cd3aacbd13a99c256cbe5 Mon Sep 17 00:00:00 2001 From: Ben S <ogham@users.noreply.github.com> Date: Wed, 17 Jun 2015 18:24:31 +0100 Subject: Remove redundant 'redundant_closure' description There were two of them in the README, now there are one. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 979fb47985a..271b19a18cf 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ Lints included in this crate: - `len_zero`: Warns on `_.len() == 0` and suggests using `_.is_empty()` (or similar comparisons with `>` or `!=`) - `len_without_is_empty`: Warns on traits or impls that have a `.len()` but no `.is_empty()` method - `cmp_owned`: Warns on creating owned instances for comparing with others, e.g. `x == "foo".to_string()` - - `redundant_closure` warns on creating a closure where none is needed, e.g. `|x| foo(x)`, where `foo` can be used directly - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space -- cgit 1.4.1-3-g733a5 From 0ffbdf2f8adc4d355dee96c4f2b462bc0e7ba255 Mon Sep 17 00:00:00 2001 From: Zachary Bush <zachary.bush@meraki.net> Date: Thu, 18 Jun 2015 15:29:13 -0700 Subject: Fix build with rustc 1.2.0-nightly (20d23d8e5 2015-06-18) In https://github.com/rust-lang/rust/pull/26347, MacroFormat was renamed to ExpnFormat. MacroFormat wasn't being used in src/mut_mut.rs, so I removed it. --- src/mut_mut.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index fc5de44542f..d2baded73ac 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -2,7 +2,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{expr_ty, TypeVariants, mt, TyRef}; -use syntax::codemap::{BytePos, ExpnInfo, MacroFormat, Span}; +use syntax::codemap::{BytePos, ExpnInfo, Span}; use utils::in_macro; declare_lint!(pub MUT_MUT, Warn, -- cgit 1.4.1-3-g733a5 From 038d540ab1f7ae3ab4be0118bc4517d186f54ec6 Mon Sep 17 00:00:00 2001 From: Zachary Bush <zachary.bush@meraki.net> Date: Wed, 1 Jul 2015 09:21:46 -0700 Subject: Fix build for rustc 1.3.0-nightly (bf3c979ec 2015-06-30) --- src/len_zero.rs | 11 +++++------ src/misc.rs | 8 ++++---- src/mut_mut.rs | 4 ++-- src/utils.rs | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 0974e8f21e2..f2fe21f88ff 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,8 +5,7 @@ use std::cell::RefCell; use syntax::ptr::P; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::util::nodemap::DefIdMap; -use rustc::middle::ty::{self, node_id_to_type, TypeVariants, expr_ty, - mt, ty_to_def_id, impl_or_trait_item, MethodTraitItemId, ImplOrTraitItemId}; +use rustc::middle::ty::{self, TypeVariants, mt, MethodTraitItemId, ImplOrTraitItemId}; use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; @@ -121,7 +120,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { if let &MethodTraitItemId(def_id) = id { if let ty::MethodTraitItem(ref method) = - ty::impl_or_trait_item(cx.tcx, def_id) { + cx.tcx.impl_or_trait_item(def_id) { method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 } else { false } @@ -136,12 +135,12 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { |iids| iids.iter().any(|i| is_is_empty(cx, i))))) } - let ty = &walk_ty(&expr_ty(cx.tcx, expr)); + let ty = &walk_ty(&cx.tcx.expr_ty(expr)); match ty.sty { ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( - &ty::ty_to_def_id(ty).expect("trait impl not found")).map_or(false, + &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))), - ty::TyProjection(_) => ty::ty_to_def_id(ty).map_or(false, + ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => has_is_empty_impl(cx, id), diff --git a/src/misc.rs b/src/misc.rs index f2492cf187d..646b6308e4a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{self, expr_ty}; +use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; @@ -79,7 +79,7 @@ impl LintPass for StrToStringPass { } fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ty(expr_ty(cx.tcx, expr)).sty { + match walk_ty(cx.tcx.expr_ty(expr)).sty { ty::TyStr => true, _ => false } @@ -167,7 +167,7 @@ impl LintPass for FloatCmp { } fn is_float(cx: &Context, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ty(expr_ty(cx.tcx, expr)).sty { + if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { true } else { false @@ -268,5 +268,5 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = - walk_ty(expr_ty(cx.tcx, &*args[0])).sty { true } else { false } + walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index d2baded73ac..10888d99075 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,7 +1,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::middle::ty::{expr_ty, TypeVariants, mt, TyRef}; +use rustc::middle::ty::{TypeVariants, mt, TyRef}; use syntax::codemap::{BytePos, ExpnInfo, Span}; use utils::in_macro; @@ -43,7 +43,7 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { "Generally you want to avoid &mut &mut _ if possible.") }).unwrap_or_else(|| { if let TyRef(_, mt{ty: _, mutbl: MutMutable}) = - expr_ty(cx.tcx, e).sty { + cx.tcx.expr_ty(e).sty { cx.span_lint(MUT_MUT, expr.span, "This expression mutably borrows a mutable reference. \ Consider reborrowing") diff --git a/src/utils.rs b/src/utils.rs index b99ed45b3c3..d754c85f7b5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -30,7 +30,7 @@ pub fn in_external_macro(cx: &Context, span: Span) -> bool { /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { - ty::with_path(cx.tcx, def_id, |iter| iter.map(|elem| elem.name()) + cx.tcx.with_path(def_id, |iter| iter.map(|elem| elem.name()) .zip(path.iter()).all(|(nm, p)| &nm.as_str() == p)) } -- cgit 1.4.1-3-g733a5 From a24475093954141168d30ef510f20171db4843ac Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 9 Jul 2015 17:02:21 +0200 Subject: new 'snippet' utils method, used where applicable --- src/identity_op.rs | 5 +++-- src/misc.rs | 18 +++++++----------- src/utils.rs | 8 ++++++++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/identity_op.rs b/src/identity_op.rs index 25697199dc3..9511bcdee8d 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -7,6 +7,8 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; +use utils::snippet; + declare_lint! { pub IDENTITY_OP, Warn, "Warn on identity operations, e.g. '_ + 0'"} @@ -46,10 +48,9 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { - let map = cx.sess().codemap(); cx.span_lint(IDENTITY_OP, span, &format!( "The operation is ineffective. Consider reducing it to '{}'", - &*map.span_to_snippet(arg).unwrap_or("..".to_string()))); + snippet(cx, arg, ".."))); } } diff --git a/src/misc.rs b/src/misc.rs index 646b6308e4a..ffa16543f25 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -8,7 +8,7 @@ use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; -use utils::match_path; +use utils::{match_path, snippet}; pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { match ty.sty { @@ -43,12 +43,11 @@ impl LintPass for MiscPass { // In some cases, an exhaustive match is preferred to catch situations when // an enum is extended. So we only consider cases where a `_` wildcard is used if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { - let map = cx.sess().codemap(); span_note_and_lint(cx, SINGLE_MATCH, expr.span, "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", &*format!("Try if let {} = {} {{ ... }}", - &*map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), - &*map.span_to_snippet(ex.span).unwrap_or("..".to_string())) + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, "..")) ); } } @@ -156,11 +155,10 @@ impl LintPass for FloatCmp { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - let map = cx.sess().codemap(); cx.span_lint(FLOAT_CMP, expr.span, &format!( "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", - binop_to_string(op), &*map.span_to_snippet(left.span).unwrap_or("..".to_string()), - &*map.span_to_snippet(right.span).unwrap_or("..".to_string()))); + binop_to_string(op), snippet(cx, left.span, ".."), + snippet(cx, right.span, ".."))); } } } @@ -246,8 +244,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { cx.span_lint(CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", - cx.sess().codemap().span_to_snippet(other_span).unwrap_or( - "..".to_string()))) + snippet(cx, other_span, ".."))) } }, &ExprCall(ref path, _) => { @@ -257,8 +254,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { cx.span_lint(CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", - cx.sess().codemap().span_to_snippet(other_span).unwrap_or( - "..".to_string()))) + snippet(cx, other_span, ".."))) } } }, diff --git a/src/utils.rs b/src/utils.rs index d754c85f7b5..7d61316367b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,6 +2,8 @@ use rustc::lint::Context; use syntax::ast::{DefId, Name, Path}; use syntax::codemap::{ExpnInfo, Span}; use rustc::middle::ty; +use std::borrow::{Cow, IntoCow}; +use std::convert::From; /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin @@ -40,3 +42,9 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( |(a,b)| a.identifier.as_str() == *b) } + +/// convert a span to a code snippet if available, otherwise use default, e.g. +/// `snippet(cx, expr.span, "..")` +pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { + cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) +} -- cgit 1.4.1-3-g733a5 From ad3d36dc7259fd49f5e6f57af88292b830f41073 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 10 Jul 2015 20:22:15 +0530 Subject: bump to 0.0.6 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7240341dcab..2d00f863e29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.5" +version = "0.0.6" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" -- cgit 1.4.1-3-g733a5 From 251c5cfffdc04e91bb421334a2a8117db66027f6 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 16 Jul 2015 08:53:02 +0200 Subject: rustup, also first time clippy was used on itself, which led to a small refactoring --- README.md | 7 +++++++ src/eta_reduction.rs | 2 +- src/len_zero.rs | 2 +- src/misc.rs | 4 ++-- src/mut_mut.rs | 4 ++-- src/needless_bool.rs | 21 ++++++++++++++++----- src/utils.rs | 4 ++++ 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 271b19a18cf..87339f46464 100644 --- a/README.md +++ b/README.md @@ -86,5 +86,12 @@ You can add options to `allow`/`warn`/`deny`: *`deny` produces error instead of warnings* +To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` +in your code, you can use: + +``` +cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy +``` + ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index b89eef8c8bb..17dac5930c4 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -18,7 +18,7 @@ impl LintPass for EtaPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprClosure(_, ref decl, ref blk) = expr.node { - if blk.stmts.len() != 0 { + if !blk.stmts.is_empty() { // || {foo(); bar()}; can't be reduced here return; } diff --git a/src/len_zero.rs b/src/len_zero.rs index f2fe21f88ff..35e11dfdcb9 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use syntax::ptr::P; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::util::nodemap::DefIdMap; -use rustc::middle::ty::{self, TypeVariants, mt, MethodTraitItemId, ImplOrTraitItemId}; +use rustc::middle::ty::{self, TypeVariants, TypeAndMut, MethodTraitItemId, ImplOrTraitItemId}; use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; diff --git a/src/misc.rs b/src/misc.rs index ffa16543f25..da2df2cc820 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -36,8 +36,8 @@ impl LintPass for MiscPass { if arms.len() == 2 { if arms[0].guard.is_none() && arms[1].pats.len() == 1 { match arms[1].body.node { - ExprTup(ref v) if v.len() == 0 && arms[1].guard.is_none() => (), - ExprBlock(ref b) if b.stmts.len() == 0 && arms[1].guard.is_none() => (), + ExprTup(ref v) if v.is_empty() && arms[1].guard.is_none() => (), + ExprBlock(ref b) if b.stmts.is_empty() && arms[1].guard.is_none() => (), _ => return } // In some cases, an exhaustive match is preferred to catch situations when diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 10888d99075..cfa040ddb04 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,7 +1,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::middle::ty::{TypeVariants, mt, TyRef}; +use rustc::middle::ty::{TypeVariants, TypeAndMut, TyRef}; use syntax::codemap::{BytePos, ExpnInfo, Span}; use utils::in_macro; @@ -42,7 +42,7 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { cx.span_lint(MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") }).unwrap_or_else(|| { - if let TyRef(_, mt{ty: _, mutbl: MutMutable}) = + if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = cx.tcx.expr_ty(e).sty { cx.span_lint(MUT_MUT, expr.span, "This expression mutably borrows a mutable reference. \ diff --git a/src/needless_bool.rs b/src/needless_bool.rs index fe35e6ee3bd..9b52771d8af 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -10,6 +10,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; +use utils::de_p; declare_lint! { pub NEEDLESS_BOOL, @@ -28,10 +29,18 @@ impl LintPass for NeedlessBool { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (Option::Some(true), Option::Some(true)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "your if-then-else expression will always return true"); }, - (Option::Some(true), Option::Some(false)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "you can reduce your if-statement to its predicate"); }, - (Option::Some(false), Option::Some(true)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "you can reduce your if-statement to '!' + your predicate"); }, - (Option::Some(false), Option::Some(false)) => { cx.span_lint(NEEDLESS_BOOL, e.span, "your if-then-else expression will always return false"); }, + (Option::Some(true), Option::Some(true)) => { + cx.span_lint(NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return true"); }, + (Option::Some(true), Option::Some(false)) => { + cx.span_lint(NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to its predicate"); }, + (Option::Some(false), Option::Some(true)) => { + cx.span_lint(NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to '!' + your predicate"); }, + (Option::Some(false), Option::Some(false)) => { + cx.span_lint(NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return false"); }, _ => () } } @@ -39,7 +48,9 @@ impl LintPass for NeedlessBool { } fn fetch_bool_block(block: &Block) -> Option<bool> { - if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) } else { Option::None } + if block.stmts.is_empty() { + block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) + } else { Option::None } } fn fetch_bool_expr(expr: &Expr) -> Option<bool> { diff --git a/src/utils.rs b/src/utils.rs index 7d61316367b..065c20717a1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,7 @@ use rustc::lint::Context; use syntax::ast::{DefId, Name, Path}; use syntax::codemap::{ExpnInfo, Span}; +use syntax::ptr::P; use rustc::middle::ty; use std::borrow::{Cow, IntoCow}; use std::convert::From; @@ -48,3 +49,6 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) } + +/// dereference a P<T> and return a ref on the result +pub fn de_p<T>(p: &P<T>) -> &T { &*p } -- cgit 1.4.1-3-g733a5 From 0e8e8cfc9be642311be9995934bb864560b8c553 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 26 Jul 2015 20:23:11 +0530 Subject: Basic framework for structured logging --- Cargo.toml | 4 ++++ src/approx_const.rs | 3 ++- src/attrs.rs | 4 ++-- src/bit_mask.rs | 23 ++++++++++++----------- src/collapsible_if.rs | 4 ++-- src/eq_op.rs | 3 ++- src/eta_reduction.rs | 4 +++- src/identity_op.rs | 4 ++-- src/len_zero.rs | 9 +++++---- src/misc.rs | 16 ++++++++-------- src/mut_mut.rs | 8 ++++---- src/needless_bool.rs | 10 +++++----- src/ptr_arg.rs | 5 +++-- src/types.rs | 4 +++- src/unicode.rs | 3 ++- src/utils.rs | 15 ++++++++++++++- 16 files changed, 73 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2d00f863e29..bd4be213b91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,7 @@ compiletest_rs = "*" regex = "*" regex_macros = "*" lazy_static = "*" + +[features] + +structured_logging = [] \ No newline at end of file diff --git a/src/approx_const.rs b/src/approx_const.rs index 8a93bbfa933..03d4da1ab7f 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -7,6 +7,7 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; use std::f64::consts as f64; +use utils::span_lint; declare_lint! { pub APPROX_CONSTANT, @@ -51,7 +52,7 @@ fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { if let Ok(value) = str.parse::<f64>() { for &(constant, name) in KNOWN_CONSTS { if within_epsilon(constant, value) { - cx.span_lint(APPROX_CONSTANT, span, &format!( + span_lint(cx, APPROX_CONSTANT, span, &format!( "Approximate value of {}::{} found, consider using it directly.", module, &name)); } } diff --git a/src/attrs.rs b/src/attrs.rs index d5a56b1547f..647e471c45e 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -6,7 +6,7 @@ use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, ExpnInfo}; use syntax::parse::token::InternedString; -use utils::{in_macro, match_path}; +use utils::{in_macro, match_path, span_lint}; declare_lint! { pub INLINE_ALWAYS, Warn, "#[inline(always)] is usually a bad idea."} @@ -100,7 +100,7 @@ fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, if values.len() != 1 || inline != &"inline" { continue; } if let MetaWord(ref always) = values[0].node { if always != &"always" { continue; } - cx.span_lint(INLINE_ALWAYS, attr.span, &format!( + span_lint(cx, INLINE_ALWAYS, attr.span, &format!( "You have declared #[inline(always)] on {}. This \ is usually a bad idea. Are you sure?", ident.as_str())); diff --git a/src/bit_mask.rs b/src/bit_mask.rs index f3f95f92d9a..5ce574007bc 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -6,6 +6,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; +use utils::span_lint; declare_lint! { pub BAD_BIT_MASK, @@ -95,18 +96,18 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, BiEq | BiNe => match bit_op { BiBitAnd => if mask_value & cmp_value != mask_value { if cmp_value != 0 { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ & {} can never be equal to {}", mask_value, cmp_value)); } } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, + span_lint(cx, BAD_BIT_MASK, *span, &format!("&-masking with zero")); } }, BiBitOr => if mask_value | cmp_value != cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ | {} can never be equal to {}", mask_value, cmp_value)); }, @@ -114,22 +115,22 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiLt | BiGe => match bit_op { BiBitAnd => if mask_value < cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ & {} will always be lower than {}", mask_value, cmp_value)); } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, + span_lint(cx, BAD_BIT_MASK, *span, &format!("&-masking with zero")); } }, BiBitOr => if mask_value >= cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ | {} will never be lower than {}", mask_value, cmp_value)); } else { if mask_value < cmp_value { - cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!( + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( "ineffective bit mask: x | {} compared to {} is the same as x compared directly", mask_value, cmp_value)); } @@ -138,22 +139,22 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiLe | BiGt => match bit_op { BiBitAnd => if mask_value <= cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ & {} will never be higher than {}", mask_value, cmp_value)); } else { if mask_value == 0 { - cx.span_lint(BAD_BIT_MASK, *span, + span_lint(cx, BAD_BIT_MASK, *span, &format!("&-masking with zero")); } }, BiBitOr => if mask_value > cmp_value { - cx.span_lint(BAD_BIT_MASK, *span, &format!( + span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: _ | {} will always be higher than {}", mask_value, cmp_value)); } else { if mask_value < cmp_value { - cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!( + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( "ineffective bit mask: x | {} compared to {} is the same as x compared directly", mask_value, cmp_value)); } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 85c1b25a673..dc2d3852237 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -19,7 +19,7 @@ use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned, ExpnInfo}; use syntax::print::pprust::expr_to_string; -use utils::in_macro; +use utils::{in_macro, span_lint}; declare_lint! { pub COLLAPSIBLE_IF, @@ -47,7 +47,7 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if let ExprIf(ref check, ref then, None) = e.node { if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = single_stmt_of_block(then) { - cx.span_lint(COLLAPSIBLE_IF, e.span, &format!( + span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( "This if statement can be collapsed. Try: if {} && {}\n{:?}", check_to_string(check), check_to_string(check_inner), e)); } diff --git a/src/eq_op.rs b/src/eq_op.rs index 94a49e748e2..10dbca2cf3c 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -3,6 +3,7 @@ use syntax::ast::*; use syntax::ast_util as ast_util; use syntax::ptr::P; use syntax::codemap as code; +use utils::span_lint; declare_lint! { pub EQ_OP, @@ -21,7 +22,7 @@ impl LintPass for EqOp { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(left, right) { - cx.span_lint(EQ_OP, e.span, &format!( + span_lint(cx, EQ_OP, e.span, &format!( "equal expressions as operands to {}", ast_util::binop_to_string(op.node))); } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 17dac5930c4..18011c61831 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -3,6 +3,8 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use syntax::codemap::{Span, Spanned}; use syntax::print::pprust::expr_to_string; +use utils::span_lint; + #[allow(missing_copy_implementations)] pub struct EtaPass; @@ -48,7 +50,7 @@ impl LintPass for EtaPass { return } } - cx.span_lint(REDUNDANT_CLOSURE, expr.span, + span_lint(cx, REDUNDANT_CLOSURE, expr.span, &format!("Redundant closure found, consider using `{}` in its place", expr_to_string(caller))[..]) } diff --git a/src/identity_op.rs b/src/identity_op.rs index 9511bcdee8d..b3fb3e05447 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -7,7 +7,7 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; -use utils::snippet; +use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, "Warn on identity operations, e.g. '_ + 0'"} @@ -48,7 +48,7 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { - cx.span_lint(IDENTITY_OP, span, &format!( + span_lint(cx, IDENTITY_OP, span, &format!( "The operation is ineffective. Consider reducing it to '{}'", snippet(cx, arg, ".."))); } diff --git a/src/len_zero.rs b/src/len_zero.rs index 35e11dfdcb9..7e71df2dd79 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -10,6 +10,7 @@ use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; use misc::walk_ty; +use utils::span_lint; declare_lint!(pub LEN_ZERO, Warn, "Warn when .is_empty() could be used instead of checking .len()"); @@ -54,10 +55,10 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - //cx.span_lint(LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); + //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); for i in trait_items { if is_named_self(i, "len") { - cx.span_lint(LEN_WITHOUT_IS_EMPTY, i.span, + span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ '.is_empty(_: &Self)' method. Consider adding one.", item.ident.as_str())); @@ -76,7 +77,7 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { for i in impl_items { if is_named_self(i, "len") { let s = i.span; - cx.span_lint(LEN_WITHOUT_IS_EMPTY, + span_lint(cx, LEN_WITHOUT_IS_EMPTY, Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, &format!("Item '{}' has a '.len(_: &Self)' method, but no \ '.is_empty(_: &Self)' method. Consider adding one.", @@ -107,7 +108,7 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, if let &Spanned{node: LitInt(0, _), ..} = lit { if method.node.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &*args[0]) { - cx.span_lint(LEN_ZERO, span, &format!( + span_lint(cx, LEN_ZERO, span, &format!( "Consider replacing the len comparison with '{}_.is_empty()'", empty)) } diff --git a/src/misc.rs b/src/misc.rs index da2df2cc820..a140671b1bb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -8,7 +8,7 @@ use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; use types::span_note_and_lint; -use utils::{match_path, snippet}; +use utils::{match_path, snippet, span_lint}; pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { match ty.sty { @@ -72,7 +72,7 @@ impl LintPass for StrToStringPass { ast::ExprMethodCall(ref method, _, ref args) if method.node.as_str() == "to_string" && is_str(cx, &*args[0]) => { - cx.span_lint(STR_TO_STRING, expr.span, "str.to_owned() is faster"); + span_lint(cx, STR_TO_STRING, expr.span, "str.to_owned() is faster"); }, _ => () } @@ -100,7 +100,7 @@ impl LintPass for TopLevelRefPass { fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { for ref arg in decl.inputs.iter() { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { - cx.span_lint( + span_lint(cx, TOPLEVEL_REF_ARG, arg.pat.span, "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" @@ -136,7 +136,7 @@ impl LintPass for CmpNan { fn check_nan(cx: &Context, path: &Path, span: Span) { path.segments.last().map(|seg| if seg.identifier.as_str() == "NAN" { - cx.span_lint(CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); + span_lint(cx, CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); }); } @@ -155,7 +155,7 @@ impl LintPass for FloatCmp { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - cx.span_lint(FLOAT_CMP, expr.span, &format!( + span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", binop_to_string(op), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); @@ -186,7 +186,7 @@ impl LintPass for Precedence { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - cx.span_lint(PRECEDENCE, expr.span, + span_lint(cx, PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); } } @@ -241,7 +241,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { let name = ident.as_str(); if name == "to_string" || name == "to_owned" && is_str_arg(cx, args) { - cx.span_lint(CMP_OWNED, expr.span, &format!( + span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", snippet(cx, other_span, ".."))) @@ -251,7 +251,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { if let &ExprPath(None, ref path) = &path.node { if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { - cx.span_lint(CMP_OWNED, expr.span, &format!( + span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using {}.as_slice() to compare without allocation", snippet(cx, other_span, ".."))) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index cfa040ddb04..73e97ae31f4 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -3,7 +3,7 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{TypeVariants, TypeAndMut, TyRef}; use syntax::codemap::{BytePos, ExpnInfo, Span}; -use utils::in_macro; +use utils::{in_macro, span_lint}; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -22,7 +22,7 @@ impl LintPass for MutMut { } fn check_ty(&mut self, cx: &Context, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| cx.span_lint(MUT_MUT, + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, ty.span, "Generally you want to avoid &mut &mut _ if possible.")) } } @@ -39,12 +39,12 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map(|_| { - cx.span_lint(MUT_MUT, expr.span, + span_lint(cx, MUT_MUT, expr.span, "Generally you want to avoid &mut &mut _ if possible.") }).unwrap_or_else(|| { if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = cx.tcx.expr_ty(e).sty { - cx.span_lint(MUT_MUT, expr.span, + span_lint(cx, MUT_MUT, expr.span, "This expression mutably borrows a mutable reference. \ Consider reborrowing") } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 9b52771d8af..35d921e8fa1 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -10,7 +10,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; -use utils::de_p; +use utils::{de_p, span_lint}; declare_lint! { pub NEEDLESS_BOOL, @@ -30,16 +30,16 @@ impl LintPass for NeedlessBool { if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (Option::Some(true), Option::Some(true)) => { - cx.span_lint(NEEDLESS_BOOL, e.span, + span_lint(cx, NEEDLESS_BOOL, e.span, "your if-then-else expression will always return true"); }, (Option::Some(true), Option::Some(false)) => { - cx.span_lint(NEEDLESS_BOOL, e.span, + span_lint(cx, NEEDLESS_BOOL, e.span, "you can reduce your if-statement to its predicate"); }, (Option::Some(false), Option::Some(true)) => { - cx.span_lint(NEEDLESS_BOOL, e.span, + span_lint(cx, NEEDLESS_BOOL, e.span, "you can reduce your if-statement to '!' + your predicate"); }, (Option::Some(false), Option::Some(false)) => { - cx.span_lint(NEEDLESS_BOOL, e.span, + span_lint(cx, NEEDLESS_BOOL, e.span, "your if-then-else expression will always return false"); }, _ => () } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 64c3c84c7b6..dad4e48c832 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -11,6 +11,7 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; use types::match_ty_unwrap; +use utils::span_lint; declare_lint! { pub PTR_ARG, @@ -58,10 +59,10 @@ fn check_fn(cx: &Context, decl: &FnDecl) { fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, &["String"]).map_or((), |_| { - cx.span_lint(PTR_ARG, span, + span_lint(cx, PTR_ARG, span, "Writing '&String' instead of '&str' involves a new Object \ where a slices will do. Consider changing the type to &str") - }), |_| cx.span_lint(PTR_ARG, span, "Writing '&Vec<_>' instead of \ + }), |_| span_lint(cx, PTR_ARG, span, "Writing '&Vec<_>' instead of \ '&[_]' involves one more reference and cannot be used with \ non-vec-based slices. Consider changing the type to &[...]") ) diff --git a/src/types.rs b/src/types.rs index f0c91dc18b5..8c46fed2c1f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,6 +6,8 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use syntax::codemap::Span; +use utils::span_lint; + /// Handles all the linting of funky types #[allow(missing_copy_implementations)] pub struct TypePass; @@ -40,7 +42,7 @@ pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> /// Lets me span a note only if the lint is shown pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) { - cx.span_lint(lint, span, msg); + span_lint(cx, lint, span, msg); if cx.current_level(lint) != Level::Allow { cx.sess().span_note(span, note); } diff --git a/src/unicode.rs b/src/unicode.rs index 3ffcf699c26..9b908c3f94f 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,6 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{BytePos, Span}; +use utils::span_lint; declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } @@ -36,7 +37,7 @@ fn check_str(cx: &Context, string: &str, span: Span) { fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) { start.map(|index| { - cx.span_lint(ZERO_WIDTH_SPACE, Span { + span_lint(cx, ZERO_WIDTH_SPACE, Span { lo: span.lo + BytePos(index as u32), hi: span.lo + BytePos(index as u32), expn_id: span.expn_id, diff --git a/src/utils.rs b/src/utils.rs index 065c20717a1..e3cafc700a5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use rustc::lint::Context; +use rustc::lint::{Context, Lint}; use syntax::ast::{DefId, Name, Path}; use syntax::codemap::{ExpnInfo, Span}; use syntax::ptr::P; @@ -52,3 +52,16 @@ pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { /// dereference a P<T> and return a ref on the result pub fn de_p<T>(p: &P<T>) -> &T { &*p } + +#[cfg(not(feature="structured_logging"))] +pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { + cx.span_lint(lint, sp, msg); +} + +#[cfg(feature="structured_logging")] +pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { + // lint.name / lint.desc is can give details of the lint + // cx.sess().codemap() has all these nice functions for line/column/snippet details + // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string + cx.span_lint(lint, sp, msg); +} -- cgit 1.4.1-3-g733a5 From de5ccdfab68a5e37689f3c950ed1532ba9d652a0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 31 Jul 2015 12:00:06 +0530 Subject: Upgrade to rustc 1.3.0-nightly (4d52d7c85 2015-07-30) --- Cargo.toml | 4 ++-- src/attrs.rs | 2 +- src/len_zero.rs | 10 +++++----- src/misc.rs | 6 +++--- src/types.rs | 2 +- src/utils.rs | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bd4be213b91..d0955c313e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.6" +version = "0.0.7" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" @@ -23,4 +23,4 @@ lazy_static = "*" [features] -structured_logging = [] \ No newline at end of file +structured_logging = [] diff --git a/src/attrs.rs b/src/attrs.rs index 647e471c45e..8d9e289fada 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -103,7 +103,7 @@ fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, span_lint(cx, INLINE_ALWAYS, attr.span, &format!( "You have declared #[inline(always)] on {}. This \ is usually a bad idea. Are you sure?", - ident.as_str())); + ident.name.as_str())); } } } diff --git a/src/len_zero.rs b/src/len_zero.rs index 7e71df2dd79..0e139983bbf 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -50,7 +50,7 @@ impl LintPass for LenZero { fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.ident.as_str() == name && if let MethodTraitItem(ref sig, _) = + item.ident.name == name && if let MethodTraitItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -61,7 +61,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.as_str())); + item.ident.name)); } }; } @@ -69,7 +69,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.ident.as_str() == name && if let MethodImplItem(ref sig, _) = + item.ident.name == name && if let MethodImplItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -81,7 +81,7 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, &format!("Item '{}' has a '.len(_: &Self)' method, but no \ '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.as_str())); + item.ident.name)); return; } } @@ -106,7 +106,7 @@ fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, empty: &str) { if let &Spanned{node: LitInt(0, _), ..} = lit { - if method.node.as_str() == "len" && args.len() == 1 && + if method.node.name == "len" && args.len() == 1 && has_is_empty(cx, &*args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "Consider replacing the len comparison with '{}_.is_empty()'", diff --git a/src/misc.rs b/src/misc.rs index a140671b1bb..73b94875b30 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -70,7 +70,7 @@ impl LintPass for StrToStringPass { fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { match expr.node { ast::ExprMethodCall(ref method, _, ref args) - if method.node.as_str() == "to_string" + if method.node.name == "to_string" && is_str(cx, &*args[0]) => { span_lint(cx, STR_TO_STRING, expr.span, "str.to_owned() is faster"); }, @@ -135,7 +135,7 @@ impl LintPass for CmpNan { } fn check_nan(cx: &Context, path: &Path, span: Span) { - path.segments.last().map(|seg| if seg.identifier.as_str() == "NAN" { + path.segments.last().map(|seg| if seg.identifier.name == "NAN" { span_lint(cx, CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); }); } @@ -238,7 +238,7 @@ impl LintPass for CmpOwned { fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { match &expr.node { &ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { - let name = ident.as_str(); + let name = ident.name; if name == "to_string" || name == "to_owned" && is_str_arg(cx, args) { span_lint(cx, CMP_OWNED, expr.span, &format!( diff --git a/src/types.rs b/src/types.rs index 8c46fed2c1f..d138239b5a7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -25,7 +25,7 @@ pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> // I could muck around with the maps and find the full path // however the more efficient way is to simply reverse the iterators and zip them // which will compare them in reverse until one of them runs out of segments - if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.as_str() == *b) { + if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.name == b) { match seg[..].last() { Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => { Some(&a.types[..]) diff --git a/src/utils.rs b/src/utils.rs index e3cafc700a5..d62e082c1fc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -41,7 +41,7 @@ pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a,b)| a.identifier.as_str() == *b) + |(a,b)| a.identifier.name == b) } /// convert a span to a code snippet if available, otherwise use default, e.g. -- cgit 1.4.1-3-g733a5 From 6ebb9b1551de419369e0272623ca5763d54ccc81 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 2 Aug 2015 20:59:12 +0530 Subject: Fix crash with idents from different contexts --- Cargo.toml | 2 +- src/eq_op.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0955c313e9..c94e1b38526 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.7" +version = "0.0.8" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" diff --git a/src/eq_op.rs b/src/eq_op.rs index 10dbca2cf3c..bd9787bd51c 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -72,7 +72,13 @@ fn is_exps_equal(left : &[P<Expr>], right : &[P<Expr>]) -> bool { } fn is_path_equal(left : &Path, right : &Path) -> bool { - left.global == right.global && left.segments == right.segments + // The == of idents doesn't work with different contexts, + // we have to be explicit about hygeine + left.global == right.global + && left.segments.iter().zip(right.segments.iter()) + .all( |(l,r)| l.identifier.name == r.identifier.name + && l.identifier.ctxt == r.identifier.ctxt + && l.parameters == r.parameters) } fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { -- cgit 1.4.1-3-g733a5 From b393752814e55726932a281249e5380643685986 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 5 Aug 2015 15:10:45 +0200 Subject: New string_add_assign lint (first part of #121), also formatting & refactoring --- README.md | 1 + src/eq_op.rs | 277 +++++++++++++++++++++--------------------- src/lib.rs | 3 + src/strings.rs | 55 +++++++++ src/utils.rs | 2 +- tests/compile-fail/strings.rs | 12 ++ 6 files changed, 210 insertions(+), 140 deletions(-) create mode 100644 src/strings.rs create mode 100644 tests/compile-fail/strings.rs diff --git a/README.md b/README.md index 87339f46464..fcd8d38a3b3 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Lints included in this crate: - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space + - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. To use, add the following lines to your Cargo.toml: diff --git a/src/eq_op.rs b/src/eq_op.rs index bd9787bd51c..1000d310e39 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -23,238 +23,237 @@ impl LintPass for EqOp { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(left, right) { span_lint(cx, EQ_OP, e.span, &format!( - "equal expressions as operands to {}", - ast_util::binop_to_string(op.node))); + "equal expressions as operands to {}", + ast_util::binop_to_string(op.node))); } } } } -fn is_exp_equal(left : &Expr, right : &Expr) -> bool { - match (&left.node, &right.node) { - (&ExprBinary(ref lop, ref ll, ref lr), - &ExprBinary(ref rop, ref rl, ref rr)) => - lop.node == rop.node && - is_exp_equal(ll, rl) && is_exp_equal(lr, rr), - (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && - is_exp_equal(lbox, rbox), - (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, - rcallee) && is_exps_equal(largs, rargs), - (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => - is_ty_equal(lty, rty) && is_exp_equal(lc, rc), - (&ExprField(ref lfexp, ref lfident), - &ExprField(ref rfexp, ref rfident)) => - lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), - (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprMethodCall(ref lident, ref lcty, ref lmargs), - &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(lcty, rcty) && - is_exps_equal(lmargs, rmargs), - (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), - (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), - (&ExprPath(ref lqself, ref lsubpath), - &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, |l, r| is_qself_equal(l, r)) && - is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => - is_exps_equal(ltup, rtup), - (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(l, r), - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), - _ => false - } +pub fn is_exp_equal(left : &Expr, right : &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(ref lop, ref ll, ref lr), + &ExprBinary(ref rop, ref rl, ref rr)) => + lop.node == rop.node && + is_exp_equal(ll, rl) && is_exp_equal(lr, rr), + (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => + both(lpl, rpl, |l, r| is_exp_equal(l, r)) && + is_exp_equal(lbox, rbox), + (&ExprCall(ref lcallee, ref largs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, + rcallee) && is_exps_equal(largs, rargs), + (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => + is_ty_equal(lty, rty) && is_exp_equal(lc, rc), + (&ExprField(ref lfexp, ref lfident), + &ExprField(ref rfexp, ref rfident)) => + lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), + (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprMethodCall(ref lident, ref lcty, ref lmargs), + &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => + lident.node == rident.node && is_tys_equal(lcty, rcty) && + is_exps_equal(lmargs, rmargs), + (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), + (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), + (&ExprPath(ref lqself, ref lsubpath), + &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, |l, r| is_qself_equal(l, r)) && + is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => + is_exps_equal(ltup, rtup), + (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => + lunop == runop && is_exp_equal(l, r), + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), + _ => false + } } fn is_exps_equal(left : &[P<Expr>], right : &[P<Expr>]) -> bool { - over(left, right, |l, r| is_exp_equal(l, r)) + over(left, right, |l, r| is_exp_equal(l, r)) } fn is_path_equal(left : &Path, right : &Path) -> bool { // The == of idents doesn't work with different contexts, - // we have to be explicit about hygeine - left.global == right.global - && left.segments.iter().zip(right.segments.iter()) - .all( |(l,r)| l.identifier.name == r.identifier.name - && l.identifier.ctxt == r.identifier.ctxt - && l.parameters == r.parameters) + // we have to be explicit about hygiene + left.global == right.global && over(&left.segments, &right.segments, + |l, r| l.identifier.name == r.identifier.name + && l.identifier.ctxt == r.identifier.ctxt + && l.parameters == r.parameters) } fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { - left.ty.node == right.ty.node && left.position == right.position + left.ty.node == right.ty.node && left.position == right.position } fn is_ty_equal(left : &Ty, right : &Ty) -> bool { - match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), - (&TyFixedLengthVec(ref lfvty, ref lfvexp), - &TyFixedLengthVec(ref rfvty, ref rfvexp)) => - is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), - (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => - both(ltime, rtime, is_lifetime_equal) && - is_mut_ty_equal(lrmut, rrmut), - (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => - is_bare_fn_ty_equal(lbare, rbare), + match (&left.node, &right.node) { + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), + (&TyFixedLengthVec(ref lfvty, ref lfvexp), + &TyFixedLengthVec(ref rfvty, ref rfvexp)) => + is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), + (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => + both(ltime, rtime, is_lifetime_equal) && + is_mut_ty_equal(lrmut, rrmut), + (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => + is_bare_fn_ty_equal(lbare, rbare), (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => - both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), (&TyObjectSum(ref lsumty, ref lobounds), - &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && - is_param_bounds_equal(lobounds, robounds), - (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => - is_param_bounds_equal(ltbounds, rtbounds), + &TyObjectSum(ref rsumty, ref robounds)) => + is_ty_equal(lsumty, rsumty) && + is_param_bounds_equal(lobounds, robounds), + (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => + is_param_bounds_equal(ltbounds, rtbounds), (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), - (&TyInfer, &TyInfer) => true, - _ => false - } + (&TyInfer, &TyInfer) => true, + _ => false + } } fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) - -> bool { - match(left, right) { - (&TraitTyParamBound(ref lpoly, ref lmod), - &TraitTyParamBound(ref rpoly, ref rmod)) => - lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), + -> bool { + match(left, right) { + (&TraitTyParamBound(ref lpoly, ref lmod), + &TraitTyParamBound(ref rpoly, ref rmod)) => + lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => - is_lifetime_equal(ltime, rtime), + is_lifetime_equal(ltime, rtime), _ => false - } + } } fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) - -> bool { - is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) - && is_path_equal(&left.trait_ref.path, &right.trait_ref.path) + -> bool { + is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) + && is_path_equal(&left.trait_ref.path, &right.trait_ref.path) } fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) - -> bool { - over(left, right, is_param_bound_equal) + -> bool { + over(left, right, is_param_bound_equal) } fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { - left.mutbl == right.mutbl && is_ty_equal(&left.ty, &right.ty) + left.mutbl == right.mutbl && is_ty_equal(&left.ty, &right.ty) } fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { - left.unsafety == right.unsafety && left.abi == right.abi && - is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && - is_fndecl_equal(&left.decl, &right.decl) + left.unsafety == right.unsafety && left.abi == right.abi && + is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && + is_fndecl_equal(&left.decl, &right.decl) } fn is_fndecl_equal(left : &P<FnDecl>, right : &P<FnDecl>) -> bool { - left.variadic == right.variadic && - is_args_equal(&left.inputs, &right.inputs) && - is_fnret_ty_equal(&left.output, &right.output) + left.variadic == right.variadic && + is_args_equal(&left.inputs, &right.inputs) && + is_fnret_ty_equal(&left.output, &right.output) } fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) - -> bool { - match (left, right) { - (&NoReturn(_), &NoReturn(_)) | - (&DefaultReturn(_), &DefaultReturn(_)) => true, - (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), - _ => false - } + -> bool { + match (left, right) { + (&NoReturn(_), &NoReturn(_)) | + (&DefaultReturn(_), &DefaultReturn(_)) => true, + (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), + _ => false + } } fn is_arg_equal(l: &Arg, r : &Arg) -> bool { - is_ty_equal(&l.ty, &r.ty) && is_pat_equal(&l.pat, &r.pat) + is_ty_equal(&l.ty, &r.ty) && is_pat_equal(&l.pat, &r.pat) } fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { - over(left, right, is_arg_equal) + over(left, right, is_arg_equal) } fn is_pat_equal(left : &Pat, right : &Pat) -> bool { - match(&left.node, &right.node) { - (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, - (&PatIdent(ref lmode, ref lident, Option::None), - &PatIdent(ref rmode, ref rident, Option::None)) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node), - (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), - &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node) && - is_pat_equal(lpat, rpat), + match(&left.node, &right.node) { + (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, + (&PatIdent(ref lmode, ref lident, Option::None), + &PatIdent(ref rmode, ref rident, Option::None)) => + lmode == rmode && is_ident_equal(&lident.node, &rident.node), + (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), + &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => + lmode == rmode && is_ident_equal(&lident.node, &rident.node) && + is_pat_equal(lpat, rpat), (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => - is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| - is_pats_equal(l, r)), + is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| + is_pats_equal(l, r)), (&PatStruct(ref lpath, ref lfieldpat, lbool), - &PatStruct(ref rpath, ref rfieldpat, rbool)) => - lbool == rbool && is_path_equal(lpath, rpath) && - is_spanned_fieldpats_equal(lfieldpat, rfieldpat), + &PatStruct(ref rpath, ref rfieldpat, rbool)) => + lbool == rbool && is_path_equal(lpath, rpath) && + is_spanned_fieldpats_equal(lfieldpat, rfieldpat), (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), (&PatBox(ref lboxed), &PatBox(ref rboxed)) => - is_pat_equal(lboxed, rboxed), + is_pat_equal(lboxed, rboxed), (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => - is_pat_equal(lpat, rpat) && lmut == rmut, - (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), + is_pat_equal(lpat, rpat) && lmut == rmut, + (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => - is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), + is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), (&PatVec(ref lfirst, Option::None, ref llast), - &PatVec(ref rfirst, Option::None, ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), + &PatVec(ref rfirst, Option::None, ref rlast)) => + is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), - &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && - is_pats_equal(llast, rlast), - // I don't match macros for now, the code is slow enough as is ;-) - _ => false - } + &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => + is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && + is_pats_equal(llast, rlast), + // I don't match macros for now, the code is slow enough as is ;-) + _ => false + } } fn is_spanned_fieldpats_equal(left : &[code::Spanned<FieldPat>], - right : &[code::Spanned<FieldPat>]) -> bool { - over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) + right : &[code::Spanned<FieldPat>]) -> bool { + over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) } fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { - left.is_shorthand == right.is_shorthand && - is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(&left.pat, &right.pat) + left.is_shorthand == right.is_shorthand && + is_ident_equal(&left.ident, &right.ident) && + is_pat_equal(&left.pat, &right.pat) } fn is_ident_equal(left : &Ident, right : &Ident) -> bool { - &left.name == &right.name && left.ctxt == right.ctxt + &left.name == &right.name && left.ctxt == right.ctxt } fn is_pats_equal(left : &[P<Pat>], right : &[P<Pat>]) -> bool { - over(left, right, |l, r| is_pat_equal(l, r)) + over(left, right, |l, r| is_pat_equal(l, r)) } fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) - -> bool { - is_lifetime_equal(&left.lifetime, &right.lifetime) && - over(&left.bounds, &right.bounds, is_lifetime_equal) + -> bool { + is_lifetime_equal(&left.lifetime, &right.lifetime) && + over(&left.bounds, &right.bounds, is_lifetime_equal) } fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) - -> bool { - over(left, right, is_lifetimedef_equal) + -> bool { + over(left, right, is_lifetimedef_equal) } fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { - left.name == right.name + left.name == right.name } fn is_tys_equal(left : &[P<Ty>], right : &[P<Ty>]) -> bool { - over(left, right, |l, r| is_ty_equal(l, r)) + over(left, right, |l, r| is_ty_equal(l, r)) } fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool { + where F: FnMut(&X, &X) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| - eq_fn(x, y)) + eq_fn(x, y)) } fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool - where F: FnMut(&X, &X) -> bool { - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, - |y| eq_fn(x, y))) + where F: FnMut(&X, &X) -> bool { + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, + |y| eq_fn(x, y))) } fn is_cmp_or_bit(op : &BinOp) -> bool { diff --git a/src/lib.rs b/src/lib.rs index 647128e0f0c..d0d0b637468 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,7 @@ pub mod attrs; pub mod collapsible_if; pub mod unicode; pub mod utils; +pub mod strings; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -51,6 +52,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box attrs::AttrPass as LintPassObject); reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); + reg.register_lint_pass(box strings::StringAdd as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -70,5 +72,6 @@ pub fn plugin_registrar(reg: &mut Registry) { attrs::INLINE_ALWAYS, collapsible_if::COLLAPSIBLE_IF, unicode::ZERO_WIDTH_SPACE, + strings::STRING_ADD_ASSIGN, ]); } diff --git a/src/strings.rs b/src/strings.rs new file mode 100644 index 00000000000..8bd882cada2 --- /dev/null +++ b/src/strings.rs @@ -0,0 +1,55 @@ +//! This LintPass catches both string addition and string addition + assignment +//! +//! Note that since we have two lints where one subsumes the other, we try to +//! disable the subsumed lint unless it has a higher level + +use rustc::lint::*; +use rustc::middle::ty::TypeVariants::TyStruct; +use syntax::ast::*; +use syntax::codemap::{Span, Spanned}; +use eq_op::is_exp_equal; +use misc::walk_ty; +use types::match_ty_unwrap; +use utils::{match_def_path, span_lint}; + +declare_lint! { + pub STRING_ADD_ASSIGN, + Warn, + "Warn on `x = x + ..` where x is a `String`" +} + +#[derive(Copy,Clone)] +pub struct StringAdd; + +impl LintPass for StringAdd { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_ADD_ASSIGN) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let &ExprAssign(ref target, ref src) =&e.node { + if is_string(cx, target) && is_add(src, target) { + span_lint(cx, STRING_ADD_ASSIGN, e.span, + "You assign the result of adding something to this string. \ + Consider using `String::push_str(..) instead.") + } + } + } +} + +fn is_string(cx: &Context, e: &Expr) -> bool { + if let TyStruct(def_id, _) = walk_ty(cx.tcx.expr_ty(e)).sty { + match_def_path(cx, def_id, &["std", "string", "String"]) + } else { false } +} + +fn is_add(src: &Expr, target: &Expr) -> bool { + match &src.node { + &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => + is_exp_equal(target, left), + &ExprBlock(ref block) => block.stmts.is_empty() && + block.expr.as_ref().map_or(false, |expr| is_add(&*expr, target)), + &ExprParen(ref expr) => is_add(&*expr, target), + _ => false + } +} diff --git a/src/utils.rs b/src/utils.rs index d62e082c1fc..4a87f4b3a2e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -41,7 +41,7 @@ pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a,b)| a.identifier.name == b) + |(a,b)| &a.identifier.name.as_str() == b) } /// convert a span to a code snippet if available, otherwise use default, e.g. diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs new file mode 100644 index 00000000000..2b200f1d07e --- /dev/null +++ b/tests/compile-fail/strings.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(string_add_assign)] + +fn main() { + let x = "".to_owned(); + + for i in (1..3) { + x = x + "."; //~ERROR + } +} -- cgit 1.4.1-3-g733a5 From 27f8fa75e19a5f821776aa06e40c03652ff28d86 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 7 Aug 2015 09:33:54 +0200 Subject: whitespace --- src/strings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings.rs b/src/strings.rs index 8bd882cada2..75133ec1254 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -27,7 +27,7 @@ impl LintPass for StringAdd { } fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprAssign(ref target, ref src) =&e.node { + if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "You assign the result of adding something to this string. \ -- cgit 1.4.1-3-g733a5 From 228f06a960d761e62f55b432b910642d31e8e26a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 9 Aug 2015 22:13:56 +0530 Subject: Upgrade Rust to rustc 1.4.0-nightly (a5d33d891 2015-08-08) (fixes #123) --- Cargo.toml | 2 +- src/len_zero.rs | 2 +- src/strings.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c94e1b38526..ce9ea2b3ed3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.8" +version = "0.0.9" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" diff --git a/src/len_zero.rs b/src/len_zero.rs index 0e139983bbf..37683bbfa53 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -144,7 +144,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => - has_is_empty_impl(cx, id), + has_is_empty_impl(cx, &id.did), ty::TyArray(..) => true, _ => false, } diff --git a/src/strings.rs b/src/strings.rs index 75133ec1254..511d123b58d 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -38,8 +38,8 @@ impl LintPass for StringAdd { } fn is_string(cx: &Context, e: &Expr) -> bool { - if let TyStruct(def_id, _) = walk_ty(cx.tcx.expr_ty(e)).sty { - match_def_path(cx, def_id, &["std", "string", "String"]) + if let TyStruct(did, _) = walk_ty(cx.tcx.expr_ty(e)).sty { + match_def_path(cx, did.did, &["std", "string", "String"]) } else { false } } -- cgit 1.4.1-3-g733a5 From 678a79d45a58d20953b07ecfc0587e6448238d0c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 11 Aug 2015 18:33:56 +0530 Subject: CONTRIBUTING --- CONTRIBUTING.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..86a2f624118 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing to rust-clippy + +Hello fellow Rustacean! Great to see your interest in compiler internals and lints! + +## Getting started + +All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth or @llogiq. + +Some issues are easier than others. The [E-easy](https://github.com/Manishearth/rust-clippy/labels/E-easy) +label can be used to find the easy issues. If you want to work on an issue, please leave a comment +so that we can assign it to you! + +Issues marked [T-AST](https://github.com/Manishearth/rust-clippy/labels/T-AST) involve simple +matching of the syntax tree structure, and are generally easier than +[T-middle](https://github.com/Manishearth/rust-clippy/labels/T-middle) issues, which involve types +and resolved paths. + +Issues marked [E-medium](https://github.com/Manishearth/rust-clippy/labels/E-medium) are generally +pretty easy too, though it's recommended you work on an E-easy issue first. + +[Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer +to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of +`LintPass` with one or more of its default methods overridden. See the existing lints for examples +of this. + +T-AST issues will generally need you to match against a predefined syntax structure. To figure out +how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an +example of the structure and compare with the +[nodes in the AST docs](http://manishearth.github.io/rust-internals-docs/syntax/ast/). Usually +the lint will end up to be a nested series of matches and ifs, +[like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34) + +T-middle issues can be more involved and require verifying types. The +[`middle::ty`](http://manishearth.github.io/rust-internals-docs/rustc/middle/ty) module contains a +lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of +an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. + +## Contributions + +Clippy welcomes contributions from everyone. + +Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will +be reviewed by a core contributor (someone with permission to land patches) and either landed in the +main tree or given feedback for changes that would be required. + +## Conduct + +We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). + + +<! -- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md --> \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 940c713f66ea565f6dab9223a2c1953a9707cbf3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 11 Aug 2015 18:35:05 +0530 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86a2f624118..d32b0ce8a31 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,4 +48,4 @@ main tree or given feedback for changes that would be required. We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). -<! -- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md --> \ No newline at end of file +<!-- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md --> -- cgit 1.4.1-3-g733a5 From f0eb36c2af5cd6b92fafb7ed386f75618958f857 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 11 Aug 2015 15:07:21 +0200 Subject: added parent method, also changed match-if-let note to help --- src/misc.rs | 181 +++++++++++++++++++------------------ src/utils.rs | 71 +++++++++------ tests/compile-fail/match_if_let.rs | 4 +- 3 files changed, 139 insertions(+), 117 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 73b94875b30..0f0405a835a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,14 +7,13 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; -use types::span_note_and_lint; -use utils::{match_path, snippet, span_lint}; +use utils::{match_path, snippet, span_lint, span_help_and_lint}; pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { - match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ty(tm.ty), - _ => ty - } + match ty.sty { + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ty(tm.ty), + _ => ty + } } /// Handles uncategorized lints @@ -42,9 +41,12 @@ impl LintPass for MiscPass { } // In some cases, an exhaustive match is preferred to catch situations when // an enum is extended. So we only consider cases where a `_` wildcard is used - if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { - span_note_and_lint(cx, SINGLE_MATCH, expr.span, - "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", + if arms[1].pats[0].node == PatWild(PatWildSingle) && + arms[0].pats.len() == 1 { + span_help_and_lint(cx, SINGLE_MATCH, expr.span, + "You seem to be trying to use match for \ + destructuring a single type. Did you mean to \ + use `if let`?", &*format!("Try if let {} = {} {{ ... }}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, "..")) @@ -79,9 +81,9 @@ impl LintPass for StrToStringPass { fn is_str(cx: &Context, expr: &ast::Expr) -> bool { match walk_ty(cx.tcx.expr_ty(expr)).sty { - ty::TyStr => true, - _ => false - } + ty::TyStr => true, + _ => false + } } } } @@ -116,123 +118,124 @@ declare_lint!(pub CMP_NAN, Deny, "Deny comparisons to std::f32::NAN or std::f64: pub struct CmpNan; impl LintPass for CmpNan { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(CMP_NAN) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if is_comparison_binop(cmp.node) { - if let &ExprPath(_, ref path) = &left.node { - check_nan(cx, path, expr.span); - } - if let &ExprPath(_, ref path) = &right.node { - check_nan(cx, path, expr.span); - } - } - } - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if is_comparison_binop(cmp.node) { + if let &ExprPath(_, ref path) = &left.node { + check_nan(cx, path, expr.span); + } + if let &ExprPath(_, ref path) = &right.node { + check_nan(cx, path, expr.span); + } + } + } + } } fn check_nan(cx: &Context, path: &Path, span: Span) { path.segments.last().map(|seg| if seg.identifier.name == "NAN" { - span_lint(cx, CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); + span_lint(cx, CMP_NAN, span, + "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); }); } declare_lint!(pub FLOAT_CMP, Warn, - "Warn on ==/!= comparison of floaty values"); - + "Warn on ==/!= comparison of floaty values"); + #[derive(Copy,Clone)] pub struct FloatCmp; impl LintPass for FloatCmp { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(FLOAT_CMP) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - let op = cmp.node; - if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - span_lint(cx, FLOAT_CMP, expr.span, &format!( - "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", - binop_to_string(op), snippet(cx, left.span, ".."), - snippet(cx, right.span, ".."))); - } - } - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + let op = cmp.node; + if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { + span_lint(cx, FLOAT_CMP, expr.span, &format!( + "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", + binop_to_string(op), snippet(cx, left.span, ".."), + snippet(cx, right.span, ".."))); + } + } + } } fn is_float(cx: &Context, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { - true - } else { - false - } + if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { + true + } else { + false + } } declare_lint!(pub PRECEDENCE, Warn, - "Warn on mixing bit ops with integer arithmetic without parenthesis"); - + "Warn on mixing bit ops with integer arithmetic without parenthesis"); + #[derive(Copy,Clone)] pub struct Precedence; impl LintPass for Precedence { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(PRECEDENCE) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { - if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - span_lint(cx, PRECEDENCE, expr.span, - "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); - } - } - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { + if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { + span_lint(cx, PRECEDENCE, expr.span, + "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); + } + } + } } fn is_arith_expr(expr : &Expr) -> bool { - match expr.node { - ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), - _ => false - } + match expr.node { + ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), + _ => false + } } fn is_bit_op(op : BinOp_) -> bool { - match op { - BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, - _ => false - } + match op { + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, + _ => false + } } fn is_arith_op(op : BinOp_) -> bool { - match op { - BiAdd | BiSub | BiMul | BiDiv | BiRem => true, - _ => false - } + match op { + BiAdd | BiSub | BiMul | BiDiv | BiRem => true, + _ => false + } } declare_lint!(pub CMP_OWNED, Warn, - "Warn on creating an owned string just for comparison"); - + "Warn on creating an owned string just for comparison"); + #[derive(Copy,Clone)] pub struct CmpOwned; impl LintPass for CmpOwned { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(CMP_OWNED) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if is_comparison_binop(cmp.node) { - check_to_owned(cx, left, right.span); - check_to_owned(cx, right, left.span) - } - } - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if is_comparison_binop(cmp.node) { + check_to_owned(cx, left, right.span); + check_to_owned(cx, right, left.span) + } + } + } } fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { @@ -263,6 +266,6 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { } fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { - args.len() == 1 && if let ty::TyStr = - walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } + args.len() == 1 && if let ty::TyStr = + walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } diff --git a/src/utils.rs b/src/utils.rs index 4a87f4b3a2e..a231171aee5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,8 @@ -use rustc::lint::{Context, Lint}; -use syntax::ast::{DefId, Name, Path}; +use rustc::lint::{Context, Lint, Level}; +use syntax::ast::{DefId, Expr, Name, NodeId, Path}; use syntax::codemap::{ExpnInfo, Span}; use syntax::ptr::P; +use rustc::ast_map::Node::NodeExpr; use rustc::middle::ty; use std::borrow::{Cow, IntoCow}; use std::convert::From; @@ -9,45 +10,55 @@ use std::convert::From; /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { - // no ExpnInfo = no macro - opt_info.map_or(false, |info| { - // no span for the callee = external macro - info.callee.span.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| - // macro doesn't start with "macro_rules" - // = compiler plugin - !code.starts_with("macro_rules") - ) - }) - }) + // no ExpnInfo = no macro + opt_info.map_or(false, |info| { + // no span for the callee = external macro + info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + // macro doesn't start with "macro_rules" + // = compiler plugin + !code.starts_with("macro_rules") + ) + }) + }) } /// invokes in_macro with the expansion info of the given span pub fn in_external_macro(cx: &Context, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, - |info| in_macro(cx, info)) + cx.sess().codemap().with_expn_info(span.expn_id, + |info| in_macro(cx, info)) } /// check if a DefId's path matches the given absolute type path /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| iter.map(|elem| elem.name()) - .zip(path.iter()).all(|(nm, p)| &nm.as_str() == p)) + cx.tcx.with_path(def_id, |iter| iter.map(|elem| elem.name()) + .zip(path.iter()).all(|(nm, p)| &nm.as_str() == p)) } /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a,b)| &a.identifier.name.as_str() == b) + path.segments.iter().rev().zip(segments.iter().rev()).all( + |(a,b)| &a.identifier.name.as_str() == b) } /// convert a span to a code snippet if available, otherwise use default, e.g. /// `snippet(cx, expr.span, "..")` pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { - cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) + cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) +} + +/// get a parent expr if any – this is useful to constrain a lint +pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { + let map = &cx.tcx.map; + let node_id : NodeId = e.id; + let parent_id : NodeId = map.get_parent_node(node_id); + if node_id == parent_id { return None; } + map.find(parent_id).and_then(|node| + if let NodeExpr(parent) = node { Some(parent) } else { None } ) } /// dereference a P<T> and return a ref on the result @@ -55,13 +66,21 @@ pub fn de_p<T>(p: &P<T>) -> &T { &*p } #[cfg(not(feature="structured_logging"))] pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { - cx.span_lint(lint, sp, msg); + cx.span_lint(lint, sp, msg); } #[cfg(feature="structured_logging")] pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { - // lint.name / lint.desc is can give details of the lint - // cx.sess().codemap() has all these nice functions for line/column/snippet details - // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string - cx.span_lint(lint, sp, msg); + // lint.name / lint.desc is can give details of the lint + // cx.sess().codemap() has all these nice functions for line/column/snippet details + // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string + cx.span_lint(lint, sp, msg); +} + +pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, + msg: &str, help: &str) { + span_lint(cx, lint, span, msg); + if cx.current_level(lint) != Level::Allow { + cx.sess().span_help(span, help); + } } diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs index b03c6e1140a..f1864f9d7f7 100644 --- a/tests/compile-fail/match_if_let.rs +++ b/tests/compile-fail/match_if_let.rs @@ -6,7 +6,7 @@ fn main(){ let x = Some(1u8); match x { //~ ERROR You seem to be trying to use match - //~^ NOTE Try if let Some(y) = x { ... } + //~^ HELP Try if let Some(y) = x { ... } Some(y) => println!("{:?}", y), _ => () } @@ -17,7 +17,7 @@ fn main(){ } let z = (1u8,1u8); match z { //~ ERROR You seem to be trying to use match - //~^ NOTE Try if let (2...3, 7...9) = z { ... } + //~^ HELP Try if let (2...3, 7...9) = z { ... } (2...3, 7...9) => println!("{:?}", z), _ => {} } -- cgit 1.4.1-3-g733a5 From 7b074d3ac7118a3f30c1f8782f15bfb081fbcaba Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 17:02:04 +0200 Subject: Remove tabs and trailing whitespace from lib and misc. --- src/lib.rs | 4 +-- src/misc.rs | 88 ++++++++++++++++++++++++++++++------------------------------- 2 files changed, 46 insertions(+), 46 deletions(-) mode change 100644 => 100755 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs old mode 100644 new mode 100755 index d0d0b637468..54f3bb11d26 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,11 +53,11 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); - + reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, - bit_mask::BAD_BIT_MASK, + bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, ptr_arg::PTR_ARG, needless_bool::NEEDLESS_BOOL, diff --git a/src/misc.rs b/src/misc.rs index 0f0405a835a..ff0594b2b5a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -41,7 +41,7 @@ impl LintPass for MiscPass { } // In some cases, an exhaustive match is preferred to catch situations when // an enum is extended. So we only consider cases where a `_` wildcard is used - if arms[1].pats[0].node == PatWild(PatWildSingle) && + if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { span_help_and_lint(cx, SINGLE_MATCH, expr.span, "You seem to be trying to use match for \ @@ -80,7 +80,7 @@ impl LintPass for StrToStringPass { } fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ty(cx.tcx.expr_ty(expr)).sty { + match walk_ty(cx.tcx.expr_ty(expr)).sty { ty::TyStr => true, _ => false } @@ -102,7 +102,7 @@ impl LintPass for TopLevelRefPass { fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { for ref arg in decl.inputs.iter() { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { - span_lint(cx, + span_lint(cx, TOPLEVEL_REF_ARG, arg.pat.span, "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" @@ -121,7 +121,7 @@ impl LintPass for CmpNan { fn get_lints(&self) -> LintArray { lint_array!(CMP_NAN) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { @@ -137,15 +137,15 @@ impl LintPass for CmpNan { } fn check_nan(cx: &Context, path: &Path, span: Span) { - path.segments.last().map(|seg| if seg.identifier.name == "NAN" { - span_lint(cx, CMP_NAN, span, - "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); - }); + path.segments.last().map(|seg| if seg.identifier.name == "NAN" { + span_lint(cx, CMP_NAN, span, + "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); + }); } declare_lint!(pub FLOAT_CMP, Warn, "Warn on ==/!= comparison of floaty values"); - + #[derive(Copy,Clone)] pub struct FloatCmp; @@ -153,14 +153,14 @@ impl LintPass for FloatCmp { fn get_lints(&self) -> LintArray { lint_array!(FLOAT_CMP) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", - binop_to_string(op), snippet(cx, left.span, ".."), + binop_to_string(op), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); } } @@ -168,16 +168,16 @@ impl LintPass for FloatCmp { } fn is_float(cx: &Context, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { + if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { true - } else { - false + } else { + false } } declare_lint!(pub PRECEDENCE, Warn, "Warn on mixing bit ops with integer arithmetic without parenthesis"); - + #[derive(Copy,Clone)] pub struct Precedence; @@ -185,11 +185,11 @@ impl LintPass for Precedence { fn get_lints(&self) -> LintArray { lint_array!(PRECEDENCE) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - span_lint(cx, PRECEDENCE, expr.span, + span_lint(cx, PRECEDENCE, expr.span, "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); } } @@ -219,7 +219,7 @@ fn is_arith_op(op : BinOp_) -> bool { declare_lint!(pub CMP_OWNED, Warn, "Warn on creating an owned string just for comparison"); - + #[derive(Copy,Clone)] pub struct CmpOwned; @@ -227,7 +227,7 @@ impl LintPass for CmpOwned { fn get_lints(&self) -> LintArray { lint_array!(CMP_OWNED) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { @@ -239,33 +239,33 @@ impl LintPass for CmpOwned { } fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { - match &expr.node { - &ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { - let name = ident.name; - if name == "to_string" || - name == "to_owned" && is_str_arg(cx, args) { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. \ - Consider using {}.as_slice() to compare without allocation", - snippet(cx, other_span, ".."))) - } - }, - &ExprCall(ref path, _) => { - if let &ExprPath(None, ref path) = &path.node { - if match_path(path, &["String", "from_str"]) || - match_path(path, &["String", "from"]) { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. \ - Consider using {}.as_slice() to compare without allocation", - snippet(cx, other_span, ".."))) - } - } - }, - _ => () - } + match &expr.node { + &ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { + let name = ident.name; + if name == "to_string" || + name == "to_owned" && is_str_arg(cx, args) { + span_lint(cx, CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. \ + Consider using {}.as_slice() to compare without allocation", + snippet(cx, other_span, ".."))) + } + }, + &ExprCall(ref path, _) => { + if let &ExprPath(None, ref path) = &path.node { + if match_path(path, &["String", "from_str"]) || + match_path(path, &["String", "from"]) { + span_lint(cx, CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. \ + Consider using {}.as_slice() to compare without allocation", + snippet(cx, other_span, ".."))) + } + } + }, + _ => () + } } fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { - args.len() == 1 && if let ty::TyStr = + args.len() == 1 && if let ty::TyStr = walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } -- cgit 1.4.1-3-g733a5 From 0ff476b529aa0ba11135aa2f3cf7c7779b5da2de Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 18:55:07 +0200 Subject: new lint for unneeded return stmts --- src/lib.rs | 2 ++ src/misc.rs | 68 +++++++++++++++++++++++++++++++++++ tests/compile-fail/needless_return.rs | 49 +++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100755 tests/compile-fail/needless_return.rs diff --git a/src/lib.rs b/src/lib.rs index 54f3bb11d26..7d29d96637d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); + reg.register_lint_pass(box misc::NeedlessReturn as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -73,5 +74,6 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, unicode::ZERO_WIDTH_SPACE, strings::STRING_ADD_ASSIGN, + misc::NEEDLESS_RETURN, ]); } diff --git a/src/misc.rs b/src/misc.rs index ff0594b2b5a..305a11abe23 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -269,3 +269,71 @@ fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } + +declare_lint!(pub NEEDLESS_RETURN, Warn, + "Warn on using a return statement where an expression would be enough"); + +#[derive(Copy,Clone)] +pub struct NeedlessReturn; + +impl NeedlessReturn { + // Check the final stmt or expr in a block for unnecessary return. + fn check_block_return(&mut self, cx: &Context, block: &Block) { + if let Some(ref expr) = block.expr { + self.check_final_expr(cx, expr); + } else if let Some(stmt) = block.stmts.last() { + if let StmtSemi(ref expr, _) = stmt.node { + if let ExprRet(Some(ref inner)) = expr.node { + self.emit_lint(cx, (expr.span, inner.span)); + } + } + } + } + + // Check a the final expression in a block if it's a return. + fn check_final_expr(&mut self, cx: &Context, expr: &Expr) { + match expr.node { + // simple return is always "bad" + ExprRet(Some(ref inner)) => { + self.emit_lint(cx, (expr.span, inner.span)); + } + // a whole block? check it! + ExprBlock(ref block) => { + self.check_block_return(cx, block); + } + // an if/if let expr, check both exprs + // note, if without else is going to be a type checking error anyways + // (except for unit type functions) so we don't match it + ExprIf(_, ref ifblock, Some(ref elsexpr)) | + ExprIfLet(_, _, ref ifblock, Some(ref elsexpr)) => { + self.check_block_return(cx, ifblock); + self.check_final_expr(cx, elsexpr); + } + // a match expr, check all arms + ExprMatch(_, ref arms, _) => { + for arm in arms { + self.check_final_expr(cx, &*arm.body); + } + } + _ => { } + } + } + + fn emit_lint(&mut self, cx: &Context, spans: (Span, Span)) { + span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( + "unneeded return statement. Consider using {} \ + without trailing semicolon", + snippet(cx, spans.1, ".."))) + } +} + +impl LintPass for NeedlessReturn { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_RETURN) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, + block: &Block, _: Span, _: ast::NodeId) { + self.check_block_return(cx, block); + } +} diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs new file mode 100755 index 00000000000..34d57127996 --- /dev/null +++ b/tests/compile-fail/needless_return.rs @@ -0,0 +1,49 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(needless_return)] + +fn test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + return true; //~ERROR +} + +fn test_no_semicolon() -> bool { + return true //~ERROR +} + +fn test_if_block() -> bool { + if true { + return true; //~ERROR + } else { + return false; //~ERROR + } +} + +fn test_match(x: bool) -> bool { + match x { + true => { + return false; //~ERROR + } + false => { + return true //~ERROR + } + } +} + +fn test_closure() { + let _ = || { + return true; //~ERROR + }; +} + +fn main() { + let _ = test_end_of_fn(); + let _ = test_no_semicolon(); + let _ = test_if_block(); + let _ = test_match(true); + test_closure(); +} -- cgit 1.4.1-3-g733a5 From cab9905705a56df245cce9e0f71ebeddf9daad89 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 19:26:33 +0200 Subject: better help text for "match -> if let" lint Implements the suggestion from #87. Changes span_help_and_lint(), which is only used for this lint, to use fileline_help() instead of span_help() to avoid printing the span twice. Also adds complete suggested new code. I had to distinguish between blocks, which need no additionals braces, and other exprs. --- src/misc.rs | 15 +++++++++++---- src/utils.rs | 4 ++-- tests/compile-fail/match_if_let.rs | 8 +++++--- 3 files changed, 18 insertions(+), 9 deletions(-) mode change 100644 => 100755 tests/compile-fail/match_if_let.rs diff --git a/src/misc.rs b/src/misc.rs index 0f0405a835a..24f0d8afeb6 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -43,13 +43,20 @@ impl LintPass for MiscPass { // an enum is extended. So we only consider cases where a `_` wildcard is used if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { + let body_code = snippet(cx, arms[0].body.span, ".."); + let suggestion = if let ExprBlock(_) = arms[0].body.node { + body_code.into_owned() + } else { + format!("{{ {} }}", body_code) + }; span_help_and_lint(cx, SINGLE_MATCH, expr.span, "You seem to be trying to use match for \ - destructuring a single type. Did you mean to \ + destructuring a single pattern. Did you mean to \ use `if let`?", - &*format!("Try if let {} = {} {{ ... }}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, "..")) + &*format!("Try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + suggestion) ); } } diff --git a/src/utils.rs b/src/utils.rs index a231171aee5..5ec1033b8ea 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -77,10 +77,10 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); } -pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, +pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, help: &str) { span_lint(cx, lint, span, msg); if cx.current_level(lint) != Level::Allow { - cx.sess().span_help(span, help); + cx.sess().fileline_help(span, help); } } diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs old mode 100644 new mode 100755 index f1864f9d7f7..47b8b18a5ec --- a/tests/compile-fail/match_if_let.rs +++ b/tests/compile-fail/match_if_let.rs @@ -6,8 +6,10 @@ fn main(){ let x = Some(1u8); match x { //~ ERROR You seem to be trying to use match - //~^ HELP Try if let Some(y) = x { ... } - Some(y) => println!("{:?}", y), + //~^ HELP Try + Some(y) => { + println!("{:?}", y); + } _ => () } // Not linted @@ -17,7 +19,7 @@ fn main(){ } let z = (1u8,1u8); match z { //~ ERROR You seem to be trying to use match - //~^ HELP Try if let (2...3, 7...9) = z { ... } + //~^ HELP Try (2...3, 7...9) => println!("{:?}", z), _ => {} } -- cgit 1.4.1-3-g733a5 From efdbfe0d3126b953eece0843e1177e086c594555 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 11 Aug 2015 23:11:20 +0530 Subject: nit --- src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 305a11abe23..b3a74194552 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -322,7 +322,7 @@ impl NeedlessReturn { fn emit_lint(&mut self, cx: &Context, spans: (Span, Span)) { span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using {} \ - without trailing semicolon", + without the trailing semicolon", snippet(cx, spans.1, ".."))) } } -- cgit 1.4.1-3-g733a5 From e318328d63e122b5b3e516a0592367eaa2b6ea93 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 20:22:20 +0200 Subject: all: whitespace cleanup * 4-space indentation * no trailing whitespace * no tabs --- README.md | 2 +- src/approx_const.rs | 50 +++---- src/attrs.rs | 138 +++++++++---------- src/bit_mask.rs | 260 +++++++++++++++++------------------ src/collapsible_if.rs | 30 ++-- src/eq_op.rs | 136 +++++++++--------- src/eta_reduction.rs | 1 - src/identity_op.rs | 12 +- src/len_zero.rs | 214 ++++++++++++++-------------- src/mut_mut.rs | 78 +++++------ src/needless_bool.rs | 53 +++---- src/ptr_arg.rs | 66 ++++----- src/strings.rs | 10 +- src/unicode.rs | 50 +++---- src/utils.rs | 8 +- tests/compile-fail/approx_const.rs | 98 ++++++------- tests/compile-fail/attrs.rs | 18 +-- tests/compile-fail/bit_masks.rs | 76 +++++----- tests/compile-fail/box_vec.rs | 2 +- tests/compile-fail/cmp_nan.rs | 28 ++-- tests/compile-fail/cmp_owned.rs | 34 ++--- tests/compile-fail/collapsible_if.rs | 12 +- tests/compile-fail/eq_op.rs | 40 +++--- tests/compile-fail/float_cmp.rs | 40 +++--- tests/compile-fail/identity_op.rs | 28 ++-- tests/compile-fail/len_zero.rs | 120 ++++++++-------- tests/compile-fail/mut_mut.rs | 36 ++--- tests/compile-fail/needless_bool.rs | 12 +- tests/compile-fail/precedence.rs | 2 +- tests/compile-fail/ptr_arg.rs | 10 +- tests/compile-fail/strings.rs | 10 +- tests/compile-fail/unicode.rs | 16 +-- tests/compile-test.rs | 10 +- tests/mut_mut_macro.rs | 24 ++-- 34 files changed, 862 insertions(+), 862 deletions(-) mode change 100644 => 100755 tests/compile-fail/approx_const.rs mode change 100644 => 100755 tests/compile-fail/attrs.rs mode change 100644 => 100755 tests/compile-fail/bit_masks.rs mode change 100644 => 100755 tests/compile-fail/box_vec.rs mode change 100644 => 100755 tests/compile-fail/cmp_nan.rs mode change 100644 => 100755 tests/compile-fail/cmp_owned.rs mode change 100644 => 100755 tests/compile-fail/collapsible_if.rs mode change 100644 => 100755 tests/compile-fail/eq_op.rs mode change 100644 => 100755 tests/compile-fail/float_cmp.rs mode change 100644 => 100755 tests/compile-fail/identity_op.rs mode change 100644 => 100755 tests/compile-fail/len_zero.rs mode change 100644 => 100755 tests/compile-fail/mut_mut.rs mode change 100644 => 100755 tests/compile-fail/needless_bool.rs mode change 100644 => 100755 tests/compile-fail/precedence.rs mode change 100644 => 100755 tests/compile-fail/ptr_arg.rs mode change 100644 => 100755 tests/compile-fail/strings.rs mode change 100644 => 100755 tests/compile-fail/unicode.rs mode change 100644 => 100755 tests/mut_mut_macro.rs diff --git a/README.md b/README.md index fcd8d38a3b3..62367b8a26e 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ You can add options to `allow`/`warn`/`deny`: *`deny` produces error instead of warnings* -To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` +To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` in your code, you can use: ``` diff --git a/src/approx_const.rs b/src/approx_const.rs index 03d4da1ab7f..3ae579a74b9 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -15,12 +15,12 @@ declare_lint! { "Warn if a user writes an approximate known constant in their code" } -const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), - (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), - (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), - (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; +const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), + (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), + (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), + (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; const EPSILON_DIVISOR : f64 = 8192f64; //TODO: test to find a good value @@ -31,34 +31,34 @@ impl LintPass for ApproxConstant { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprLit(ref lit) = &e.node { - check_lit(cx, lit, e.span); - } + if let &ExprLit(ref lit) = &e.node { + check_lit(cx, lit, e.span); + } } } fn check_lit(cx: &Context, lit: &Lit, span: Span) { - match &lit.node { - &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), - &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), - &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), - _ => () - } + match &lit.node { + &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), + &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), + &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), + _ => () + } } fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { - if let Ok(value) = str.parse::<f64>() { - for &(constant, name) in KNOWN_CONSTS { - if within_epsilon(constant, value) { - span_lint(cx, APPROX_CONSTANT, span, &format!( - "Approximate value of {}::{} found, consider using it directly.", module, &name)); - } - } - } + if let Ok(value) = str.parse::<f64>() { + for &(constant, name) in KNOWN_CONSTS { + if within_epsilon(constant, value) { + span_lint(cx, APPROX_CONSTANT, span, &format!( + "Approximate value of {}::{} found, consider using it directly.", module, &name)); + } + } + } } fn within_epsilon(target: f64, value: f64) -> bool { - f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR + f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR } diff --git a/src/attrs.rs b/src/attrs.rs index 8d9e289fada..6d73f1de964 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -19,92 +19,92 @@ impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { lint_array!(INLINE_ALWAYS) } - + fn check_item(&mut self, cx: &Context, item: &Item) { - if is_relevant_item(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } - + if is_relevant_item(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - if is_relevant_impl(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } - - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - if is_relevant_trait(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } + if is_relevant_impl(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if is_relevant_trait(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } } fn is_relevant_item(item: &Item) -> bool { - if let &ItemFn(_, _, _, _, _, ref block) = &item.node { - is_relevant_block(block) - } else { false } + if let &ItemFn(_, _, _, _, _, ref block) = &item.node { + is_relevant_block(block) + } else { false } } fn is_relevant_impl(item: &ImplItem) -> bool { - match item.node { - MethodImplItem(_, ref block) => is_relevant_block(block), - _ => false - } + match item.node { + MethodImplItem(_, ref block) => is_relevant_block(block), + _ => false + } } fn is_relevant_trait(item: &TraitItem) -> bool { - match item.node { - MethodTraitItem(_, None) => true, - MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), - _ => false - } + match item.node { + MethodTraitItem(_, None) => true, + MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), + _ => false + } } fn is_relevant_block(block: &Block) -> bool { - for stmt in block.stmts.iter() { - match stmt.node { - StmtDecl(_, _) => return true, - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { - return is_relevant_expr(expr); - } - _ => () - } - } - block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) + for stmt in block.stmts.iter() { + match stmt.node { + StmtDecl(_, _) => return true, + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { + return is_relevant_expr(expr); + } + _ => () + } + } + block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) } fn is_relevant_expr(expr: &Expr) -> bool { - match expr.node { - ExprBlock(ref block) => is_relevant_block(block), - ExprRet(Some(ref e)) | ExprParen(ref e) => - is_relevant_expr(&*e), - ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, - ExprCall(ref path_expr, _) => { - if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &["std", "rt", "begin_unwind"]) - } else { true } - } - _ => true - } + match expr.node { + ExprBlock(ref block) => is_relevant_block(block), + ExprRet(Some(ref e)) | ExprParen(ref e) => + is_relevant_expr(&*e), + ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, + ExprCall(ref path_expr, _) => { + if let ExprPath(_, ref path) = path_expr.node { + !match_path(path, &["std", "rt", "begin_unwind"]) + } else { true } + } + _ => true + } } -fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, - attrs: &[Attribute]) { - if in_macro(cx, info) { return; } - - for attr in attrs { - if let MetaList(ref inline, ref values) = attr.node.value.node { - if values.len() != 1 || inline != &"inline" { continue; } - if let MetaWord(ref always) = values[0].node { - if always != &"always" { continue; } - span_lint(cx, INLINE_ALWAYS, attr.span, &format!( - "You have declared #[inline(always)] on {}. This \ - is usually a bad idea. Are you sure?", - ident.name.as_str())); - } - } - } +fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, + attrs: &[Attribute]) { + if in_macro(cx, info) { return; } + + for attr in attrs { + if let MetaList(ref inline, ref values) = attr.node.value.node { + if values.len() != 1 || inline != &"inline" { continue; } + if let MetaWord(ref always) = values[0].node { + if always != &"always" { continue; } + span_lint(cx, INLINE_ALWAYS, attr.span, &format!( + "You have declared #[inline(always)] on {}. This \ + is usually a bad idea. Are you sure?", + ident.name.as_str())); + } + } + } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 5ce574007bc..ad6facfb199 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -12,23 +12,23 @@ declare_lint! { pub BAD_BIT_MASK, Deny, "Deny the use of incompatible bit masks in comparisons, e.g. \ - '(a & 1) == 2'" + '(a & 1) == 2'" } declare_lint! { - pub INEFFECTIVE_BIT_MASK, - Warn, - "Warn on the use of an ineffective bit mask in comparisons, e.g. \ - '(a & 1) > 2'" + pub INEFFECTIVE_BIT_MASK, + Warn, + "Warn on the use of an ineffective bit mask in comparisons, e.g. \ + '(a & 1) > 2'" } -/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. +/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. /// This cannot work because the bit that makes up the value two was /// zeroed out by the bit-and with 1. So the formula for detecting if an -/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` -/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , +/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , /// `!=`, `>=`, `>`}) can be determined from the following table: -/// +/// /// |Comparison |Bit-Op|Example |is always|Formula | /// |------------|------|------------|---------|----------------------| /// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | @@ -37,7 +37,7 @@ declare_lint! { /// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | /// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | /// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | -/// +/// /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* @@ -49,140 +49,140 @@ impl LintPass for BitMask { fn get_lints(&self) -> LintArray { lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { - if is_comparison_binop(cmp.node) { - fetch_int_literal(cx, right).map_or_else(|| - fetch_int_literal(cx, left).map_or((), |cmp_val| - check_compare(cx, right, invert_cmp(cmp.node), - cmp_val, &e.span)), - |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, - &e.span)) - } - } + if is_comparison_binop(cmp.node) { + fetch_int_literal(cx, right).map_or_else(|| + fetch_int_literal(cx, left).map_or((), |cmp_val| + check_compare(cx, right, invert_cmp(cmp.node), + cmp_val, &e.span)), + |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, + &e.span)) + } + } } } fn invert_cmp(cmp : BinOp_) -> BinOp_ { - match cmp { - BiEq => BiEq, - BiNe => BiNe, - BiLt => BiGt, - BiGt => BiLt, - BiLe => BiGe, - BiGe => BiLe, - _ => BiOr // Dummy - } + match cmp { + BiEq => BiEq, + BiNe => BiNe, + BiLt => BiGt, + BiGt => BiLt, + BiLe => BiGe, + BiGe => BiLe, + _ => BiOr // Dummy + } } fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { - match &bit_op.node { - &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), - &ExprBinary(ref op, ref left, ref right) => { - if op.node != BiBitAnd && op.node != BiBitOr { return; } - fetch_int_literal(cx, right).or_else(|| fetch_int_literal( - cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, - cmp_op, mask, cmp_value, span)) - }, - _ => () - } + match &bit_op.node { + &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), + &ExprBinary(ref op, ref left, ref right) => { + if op.node != BiBitAnd && op.node != BiBitOr { return; } + fetch_int_literal(cx, right).or_else(|| fetch_int_literal( + cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, + cmp_op, mask, cmp_value, span)) + }, + _ => () + } } -fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, - mask_value: u64, cmp_value: u64, span: &Span) { - match cmp_op { - BiEq | BiNe => match bit_op { - BiBitAnd => if mask_value & cmp_value != mask_value { - if cmp_value != 0 { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} can never be equal to {}", - mask_value, cmp_value)); - } - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); - } - }, - BiBitOr => if mask_value | cmp_value != cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} can never be equal to {}", - mask_value, cmp_value)); - }, - _ => () - }, - BiLt | BiGe => match bit_op { - BiBitAnd => if mask_value < cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} will always be lower than {}", - mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); - } - }, - BiBitOr => if mask_value >= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} will never be lower than {}", - mask_value, cmp_value)); - } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", - mask_value, cmp_value)); - } - }, - _ => () - }, - BiLe | BiGt => match bit_op { - BiBitAnd => if mask_value <= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} will never be higher than {}", - mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); - } - }, - BiBitOr => if mask_value > cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} will always be higher than {}", - mask_value, cmp_value)); - } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", - mask_value, cmp_value)); - } - }, - _ => () - }, - _ => () - } +fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, + mask_value: u64, cmp_value: u64, span: &Span) { + match cmp_op { + BiEq | BiNe => match bit_op { + BiBitAnd => if mask_value & cmp_value != mask_value { + if cmp_value != 0 { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} can never be equal to {}", + mask_value, cmp_value)); + } + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, + &format!("&-masking with zero")); + } + }, + BiBitOr => if mask_value | cmp_value != cmp_value { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} can never be equal to {}", + mask_value, cmp_value)); + }, + _ => () + }, + BiLt | BiGe => match bit_op { + BiBitAnd => if mask_value < cmp_value { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} will always be lower than {}", + mask_value, cmp_value)); + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, + &format!("&-masking with zero")); + } + }, + BiBitOr => if mask_value >= cmp_value { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} will never be lower than {}", + mask_value, cmp_value)); + } else { + if mask_value < cmp_value { + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + mask_value, cmp_value)); + } + }, + _ => () + }, + BiLe | BiGt => match bit_op { + BiBitAnd => if mask_value <= cmp_value { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ & {} will never be higher than {}", + mask_value, cmp_value)); + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, + &format!("&-masking with zero")); + } + }, + BiBitOr => if mask_value > cmp_value { + span_lint(cx, BAD_BIT_MASK, *span, &format!( + "incompatible bit mask: _ | {} will always be higher than {}", + mask_value, cmp_value)); + } else { + if mask_value < cmp_value { + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + mask_value, cmp_value)); + } + }, + _ => () + }, + _ => () + } } fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option<u64> { - match &lit.node { - &ExprLit(ref lit_ptr) => { - if let &LitInt(value, _) = &lit_ptr.node { - Option::Some(value) //TODO: Handle sign - } else { Option::None } - }, - &ExprPath(_, _) => { - // Important to let the borrow expire before the const lookup to avoid double - // borrowing. - let def_map = cx.tcx.def_map.borrow(); - match def_map.get(&lit.id) { - Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), - _ => None - } + match &lit.node { + &ExprLit(ref lit_ptr) => { + if let &LitInt(value, _) = &lit_ptr.node { + Option::Some(value) //TODO: Handle sign + } else { Option::None } + }, + &ExprPath(_, _) => { + // Important to let the borrow expire before the const lookup to avoid double + // borrowing. + let def_map = cx.tcx.def_map.borrow(); + match def_map.get(&lit.id) { + Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), + _ => None } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) - .and_then(|l| fetch_int_literal(cx, l)), - _ => Option::None - } + } + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) + .and_then(|l| fetch_int_literal(cx, l)), + _ => Option::None + } } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index dc2d3852237..eae3222945c 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -34,24 +34,24 @@ impl LintPass for CollapsibleIf { fn get_lints(&self) -> LintArray { lint_array!(COLLAPSIBLE_IF) } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) - } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) + } } fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } - - if let ExprIf(ref check, ref then, None) = e.node { - if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = - single_stmt_of_block(then) { - span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( - "This if statement can be collapsed. Try: if {} && {}\n{:?}", - check_to_string(check), check_to_string(check_inner), e)); - } - } + if in_macro(cx, info) { return; } + + if let ExprIf(ref check, ref then, None) = e.node { + if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = + single_stmt_of_block(then) { + span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( + "This if statement can be collapsed. Try: if {} && {}\n{:?}", + check_to_string(check), check_to_string(check_inner), e)); + } + } } fn requires_brackets(e: &Expr) -> bool { diff --git a/src/eq_op.rs b/src/eq_op.rs index 1000d310e39..6ad0e0658df 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -18,12 +18,12 @@ impl LintPass for EqOp { fn get_lints(&self) -> LintArray { lint_array!(EQ_OP) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(left, right) { span_lint(cx, EQ_OP, e.span, &format!( - "equal expressions as operands to {}", + "equal expressions as operands to {}", ast_util::binop_to_string(op.node))); } } @@ -32,36 +32,36 @@ impl LintPass for EqOp { pub fn is_exp_equal(left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { - (&ExprBinary(ref lop, ref ll, ref lr), - &ExprBinary(ref rop, ref rl, ref rr)) => - lop.node == rop.node && + (&ExprBinary(ref lop, ref ll, ref lr), + &ExprBinary(ref rop, ref rl, ref rr)) => + lop.node == rop.node && is_exp_equal(ll, rl) && is_exp_equal(lr, rr), - (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && + (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => + both(lpl, rpl, |l, r| is_exp_equal(l, r)) && is_exp_equal(lbox, rbox), - (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, + (&ExprCall(ref lcallee, ref largs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, rcallee) && is_exps_equal(largs, rargs), - (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => + (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => is_ty_equal(lty, rty) && is_exp_equal(lc, rc), - (&ExprField(ref lfexp, ref lfident), - &ExprField(ref rfexp, ref rfident)) => + (&ExprField(ref lfexp, ref lfident), + &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprMethodCall(ref lident, ref lcty, ref lmargs), - &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(lcty, rcty) && + (&ExprMethodCall(ref lident, ref lcty, ref lmargs), + &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => + lident.node == rident.node && is_tys_equal(lcty, rcty) && is_exps_equal(lmargs, rmargs), (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), - (&ExprPath(ref lqself, ref lsubpath), - &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, |l, r| is_qself_equal(l, r)) && - is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => + (&ExprPath(ref lqself, ref lsubpath), + &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, |l, r| is_qself_equal(l, r)) && + is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(ltup, rtup), - (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(l, r), + (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => + lunop == runop && is_exp_equal(l, r), (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), _ => false } @@ -74,7 +74,7 @@ fn is_exps_equal(left : &[P<Expr>], right : &[P<Expr>]) -> bool { fn is_path_equal(left : &Path, right : &Path) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene - left.global == right.global && over(&left.segments, &right.segments, + left.global == right.global && over(&left.segments, &right.segments, |l, r| l.identifier.name == r.identifier.name && l.identifier.ctxt == r.identifier.ctxt && l.parameters == r.parameters) @@ -87,23 +87,23 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { fn is_ty_equal(left : &Ty, right : &Ty) -> bool { match (&left.node, &right.node) { (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), - (&TyFixedLengthVec(ref lfvty, ref lfvexp), - &TyFixedLengthVec(ref rfvty, ref rfvexp)) => + (&TyFixedLengthVec(ref lfvty, ref lfvexp), + &TyFixedLengthVec(ref rfvty, ref rfvexp)) => is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), - (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => - both(ltime, rtime, is_lifetime_equal) && + (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => + both(ltime, rtime, is_lifetime_equal) && is_mut_ty_equal(lrmut, rrmut), - (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => + (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => is_bare_fn_ty_equal(lbare, rbare), (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), - (&TyObjectSum(ref lsumty, ref lobounds), - &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && + (&TyObjectSum(ref lsumty, ref lobounds), + &TyObjectSum(ref rsumty, ref robounds)) => + is_ty_equal(lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), - (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => + (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), @@ -112,13 +112,13 @@ fn is_ty_equal(left : &Ty, right : &Ty) -> bool { } } -fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) +fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { match(left, right) { - (&TraitTyParamBound(ref lpoly, ref lmod), - &TraitTyParamBound(ref rpoly, ref rmod)) => + (&TraitTyParamBound(ref lpoly, ref lmod), + &TraitTyParamBound(ref rpoly, ref rmod)) => lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), - (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => + (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => is_lifetime_equal(ltime, rtime), _ => false } @@ -140,24 +140,24 @@ fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { } fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { - left.unsafety == right.unsafety && left.abi == right.abi && - is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && + left.unsafety == right.unsafety && left.abi == right.abi && + is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && is_fndecl_equal(&left.decl, &right.decl) -} +} fn is_fndecl_equal(left : &P<FnDecl>, right : &P<FnDecl>) -> bool { - left.variadic == right.variadic && - is_args_equal(&left.inputs, &right.inputs) && + left.variadic == right.variadic && + is_args_equal(&left.inputs, &right.inputs) && is_fnret_ty_equal(&left.output, &right.output) } -fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) +fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) -> bool { match (left, right) { - (&NoReturn(_), &NoReturn(_)) | + (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), - _ => false + _ => false } } @@ -172,49 +172,49 @@ fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { fn is_pat_equal(left : &Pat, right : &Pat) -> bool { match(&left.node, &right.node) { (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, - (&PatIdent(ref lmode, ref lident, Option::None), + (&PatIdent(ref lmode, ref lident, Option::None), &PatIdent(ref rmode, ref rident, Option::None)) => lmode == rmode && is_ident_equal(&lident.node, &rident.node), - (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), + (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node) && + lmode == rmode && is_ident_equal(&lident.node, &rident.node) && is_pat_equal(lpat, rpat), - (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => - is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| + (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => + is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| is_pats_equal(l, r)), - (&PatStruct(ref lpath, ref lfieldpat, lbool), + (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => - lbool == rbool && is_path_equal(lpath, rpath) && + lbool == rbool && is_path_equal(lpath, rpath) && is_spanned_fieldpats_equal(lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), - (&PatBox(ref lboxed), &PatBox(ref rboxed)) => + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), + (&PatBox(ref lboxed), &PatBox(ref rboxed)) => is_pat_equal(lboxed, rboxed), - (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => + (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => is_pat_equal(lpat, rpat) && lmut == rmut, (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), - (&PatVec(ref lfirst, Option::None, ref llast), + (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), - (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), + (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && + is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && is_pats_equal(llast, rlast), // I don't match macros for now, the code is slow enough as is ;-) _ => false } } -fn is_spanned_fieldpats_equal(left : &[code::Spanned<FieldPat>], +fn is_spanned_fieldpats_equal(left : &[code::Spanned<FieldPat>], right : &[code::Spanned<FieldPat>]) -> bool { over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) } fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { - left.is_shorthand == right.is_shorthand && - is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(&left.pat, &right.pat) + left.is_shorthand == right.is_shorthand && + is_ident_equal(&left.ident, &right.ident) && + is_pat_equal(&left.pat, &right.pat) } fn is_ident_equal(left : &Ident, right : &Ident) -> bool { @@ -227,11 +227,11 @@ fn is_pats_equal(left : &[P<Pat>], right : &[P<Pat>]) -> bool { fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) -> bool { - is_lifetime_equal(&left.lifetime, &right.lifetime) && + is_lifetime_equal(&left.lifetime, &right.lifetime) && over(&left.bounds, &right.bounds, is_lifetime_equal) } -fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) +fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) -> bool { over(left, right, is_lifetimedef_equal) } @@ -244,13 +244,13 @@ fn is_tys_equal(left : &[P<Ty>], right : &[P<Ty>]) -> bool { over(left, right, |l, r| is_ty_equal(l, r)) } -fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool +fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool +fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool where F: FnMut(&X, &X) -> bool { l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) @@ -258,7 +258,7 @@ fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool fn is_cmp_or_bit(op : &BinOp) -> bool { match op.node { - BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | + BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, _ => false } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 18011c61831..6948c1b22ab 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -58,4 +58,3 @@ impl LintPass for EtaPass { } } } - diff --git a/src/identity_op.rs b/src/identity_op.rs index b3fb3e05447..56d01c52b1d 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -11,7 +11,7 @@ use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, "Warn on identity operations, e.g. '_ + 0'"} - + #[derive(Copy,Clone)] pub struct IdentityOp; @@ -27,7 +27,7 @@ impl LintPass for IdentityOp { check(cx, left, 0, e.span, right.span); check(cx, right, 0, e.span, left.span); }, - BiShl | BiShr | BiSub => + BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), BiMul => { check(cx, left, 1, e.span, right.span); @@ -49,14 +49,14 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { span_lint(cx, IDENTITY_OP, span, &format!( - "The operation is ineffective. Consider reducing it to '{}'", + "The operation is ineffective. Consider reducing it to '{}'", snippet(cx, arg, ".."))); } } fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { match &e.node { - &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), + &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), &ExprLit(ref lit) => { match (&lit.node, m) { (&LitInt(0, _), 0) => true, @@ -68,9 +68,9 @@ fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { } }, &ExprParen(ref p) => have_lit(cx, p, m), - &ExprPath(_, _) => { + &ExprPath(_, _) => { match cx.tcx.def_map.borrow().get(&e.id) { - Some(&PathResolution { base_def: DefConst(id), ..}) => + Some(&PathResolution { base_def: DefConst(id), ..}) => lookup_const_by_id(cx.tcx, id, Option::None) .map_or(false, |l| have_lit(cx, l, m)), _ => false diff --git a/src/len_zero.rs b/src/len_zero.rs index 37683bbfa53..0877fa95238 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -22,130 +22,130 @@ declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, pub struct LenZero; impl LintPass for LenZero { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) - } - - fn check_item(&mut self, cx: &Context, item: &Item) { - match &item.node { - &ItemTrait(_, _, _, ref trait_items) => - check_trait_items(cx, item, trait_items), - &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait - check_impl_items(cx, item, impl_items), - _ => () - } - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = - &expr.node { - match cmp { - BiEq => check_cmp(cx, expr.span, left, right, ""), - BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), - _ => () - } - } - } + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + match &item.node { + &ItemTrait(_, _, _, ref trait_items) => + check_trait_items(cx, item, trait_items), + &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait + check_impl_items(cx, item, impl_items), + _ => () + } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = + &expr.node { + match cmp { + BiEq => check_cmp(cx, expr.span, left, right, ""), + BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + _ => () + } + } + } } fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { - fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.ident.name == name && if let MethodTraitItem(ref sig, _) = - item.node { is_self_sig(sig) } else { false } - } - - if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); - for i in trait_items { - if is_named_self(i, "len") { - span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, - &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.name)); - } - }; - } + fn is_named_self(item: &TraitItem, name: &str) -> bool { + item.ident.name == name && if let MethodTraitItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } + } + + if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { + //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); + for i in trait_items { + if is_named_self(i, "len") { + span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, + &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", + item.ident.name)); + } + }; + } } fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { - fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.ident.name == name && if let MethodImplItem(ref sig, _) = - item.node { is_self_sig(sig) } else { false } - } - - if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { - for i in impl_items { - if is_named_self(i, "len") { - let s = i.span; - span_lint(cx, LEN_WITHOUT_IS_EMPTY, - Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, - &format!("Item '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.name)); - return; - } - } - } + fn is_named_self(item: &ImplItem, name: &str) -> bool { + item.ident.name == name && if let MethodImplItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } + } + + if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { + for i in impl_items { + if is_named_self(i, "len") { + let s = i.span; + span_lint(cx, LEN_WITHOUT_IS_EMPTY, + Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, + &format!("Item '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", + item.ident.name)); + return; + } + } + } } fn is_self_sig(sig: &MethodSig) -> bool { - if let SelfStatic = sig.explicit_self.node { - false } else { sig.decl.inputs.len() == 1 } + if let SelfStatic = sig.explicit_self.node { + false } else { sig.decl.inputs.len() == 1 } } fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { - match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => - check_len_zero(cx, span, method, args, lit, empty), - (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => - check_len_zero(cx, span, method, args, lit, empty), - _ => () - } + match (&left.node, &right.node) { + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => + check_len_zero(cx, span, method, args, lit, empty), + (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => + check_len_zero(cx, span, method, args, lit, empty), + _ => () + } } -fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, - args: &[P<Expr>], lit: &Lit, empty: &str) { - if let &Spanned{node: LitInt(0, _), ..} = lit { - if method.node.name == "len" && args.len() == 1 && - has_is_empty(cx, &*args[0]) { - span_lint(cx, LEN_ZERO, span, &format!( - "Consider replacing the len comparison with '{}_.is_empty()'", - empty)) - } - } +fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, + args: &[P<Expr>], lit: &Lit, empty: &str) { + if let &Spanned{node: LitInt(0, _), ..} = lit { + if method.node.name == "len" && args.len() == 1 && + has_is_empty(cx, &*args[0]) { + span_lint(cx, LEN_ZERO, span, &format!( + "Consider replacing the len comparison with '{}_.is_empty()'", + empty)) + } + } } /// check if this type has an is_empty method fn has_is_empty(cx: &Context, expr: &Expr) -> bool { - /// get a ImplOrTraitItem and return true if it matches is_empty(self) - fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { - if let &MethodTraitItemId(def_id) = id { - if let ty::MethodTraitItem(ref method) = - cx.tcx.impl_or_trait_item(def_id) { - method.name.as_str() == "is_empty" - && method.fty.sig.skip_binder().inputs.len() == 1 - } else { false } - } else { false } - } - - /// check the inherent impl's items for an is_empty(self) method - fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { - let impl_items = cx.tcx.impl_items.borrow(); - cx.tcx.inherent_impls.borrow().get(id).map_or(false, - |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, - |iids| iids.iter().any(|i| is_is_empty(cx, i))))) - } - - let ty = &walk_ty(&cx.tcx.expr_ty(expr)); - match ty.sty { - ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( - &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, - |ids| ids.iter().any(|i| is_is_empty(cx, i))), - ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, - |id| has_is_empty_impl(cx, &id)), - ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => - has_is_empty_impl(cx, &id.did), - ty::TyArray(..) => true, - _ => false, - } + /// get a ImplOrTraitItem and return true if it matches is_empty(self) + fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { + if let &MethodTraitItemId(def_id) = id { + if let ty::MethodTraitItem(ref method) = + cx.tcx.impl_or_trait_item(def_id) { + method.name.as_str() == "is_empty" + && method.fty.sig.skip_binder().inputs.len() == 1 + } else { false } + } else { false } + } + + /// check the inherent impl's items for an is_empty(self) method + fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { + let impl_items = cx.tcx.impl_items.borrow(); + cx.tcx.inherent_impls.borrow().get(id).map_or(false, + |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, + |iids| iids.iter().any(|i| is_is_empty(cx, i))))) + } + + let ty = &walk_ty(&cx.tcx.expr_ty(expr)); + match ty.sty { + ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( + &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, + |ids| ids.iter().any(|i| is_is_empty(cx, i))), + ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, + |id| has_is_empty_impl(cx, &id)), + ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => + has_is_empty_impl(cx, &id.did), + ty::TyArray(..) => true, + _ => false, + } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 73e97ae31f4..16ea422f77f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -12,50 +12,50 @@ declare_lint!(pub MUT_MUT, Warn, pub struct MutMut; impl LintPass for MutMut { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(MUT_MUT) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) - } - - fn check_ty(&mut self, cx: &Context, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, - ty.span, "Generally you want to avoid &mut &mut _ if possible.")) - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) + } + + fn check_ty(&mut self, cx: &Context, ty: &Ty) { + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, + ty.span, "Generally you want to avoid &mut &mut _ if possible.")) + } } fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } - - fn unwrap_addr(expr : &Expr) -> Option<&Expr> { - match expr.node { - ExprAddrOf(MutMutable, ref e) => Option::Some(e), - _ => Option::None - } - } - - unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map(|_| { - span_lint(cx, MUT_MUT, expr.span, - "Generally you want to avoid &mut &mut _ if possible.") - }).unwrap_or_else(|| { - if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = - cx.tcx.expr_ty(e).sty { - span_lint(cx, MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. \ - Consider reborrowing") - } - }) - }) + if in_macro(cx, info) { return; } + + fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + match expr.node { + ExprAddrOf(MutMutable, ref e) => Option::Some(e), + _ => Option::None + } + } + + unwrap_addr(expr).map_or((), |e| { + unwrap_addr(e).map(|_| { + span_lint(cx, MUT_MUT, expr.span, + "Generally you want to avoid &mut &mut _ if possible.") + }).unwrap_or_else(|| { + if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = + cx.tcx.expr_ty(e).sty { + span_lint(cx, MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. \ + Consider reborrowing") + } + }) + }) } fn unwrap_mut(ty : &Ty) -> Option<&Ty> { - match ty.node { - TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - _ => Option::None - } + match ty.node { + TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + _ => Option::None + } } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 35d921e8fa1..3296bdeca87 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -25,38 +25,39 @@ impl LintPass for NeedlessBool { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BOOL) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { - match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (Option::Some(true), Option::Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return true"); }, - (Option::Some(true), Option::Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to its predicate"); }, - (Option::Some(false), Option::Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to '!' + your predicate"); }, - (Option::Some(false), Option::Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return false"); }, - _ => () - } - } + match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { + (Option::Some(true), Option::Some(true)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return true"); }, + (Option::Some(true), Option::Some(false)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to its predicate"); }, + (Option::Some(false), Option::Some(true)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to '!' + your predicate"); }, + (Option::Some(false), Option::Some(false)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return false"); }, + _ => () + } + } } } fn fetch_bool_block(block: &Block) -> Option<bool> { - if block.stmts.is_empty() { - block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) - } else { Option::None } + if block.stmts.is_empty() { + block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) + } else { Option::None } } - + fn fetch_bool_expr(expr: &Expr) -> Option<bool> { - match &expr.node { - &ExprBlock(ref block) => fetch_bool_block(block), - &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { Option::Some(value) } else { Option::None }, - _ => Option::None - } + match &expr.node { + &ExprBlock(ref block) => fetch_bool_block(block), + &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { + Option::Some(value) } else { Option::None }, + _ => Option::None + } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index dad4e48c832..939277fe66c 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -26,44 +26,44 @@ impl LintPass for PtrArg { fn get_lints(&self) -> LintArray { lint_array!(PTR_ARG) } - + fn check_item(&mut self, cx: &Context, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { - check_fn(cx, decl); - } - } - - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - if let &MethodImplItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } - - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - if let &MethodTraitItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } + if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { + check_fn(cx, decl); + } + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if let &MethodImplItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if let &MethodTraitItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } } fn check_fn(cx: &Context, decl: &FnDecl) { - for arg in &decl.inputs { - match &arg.ty.node { - &TyPtr(ref p) | &TyRptr(_, ref p) => - check_ptr_subtype(cx, arg.ty.span, &p.ty), - _ => () - } - } + for arg in &decl.inputs { + match &arg.ty.node { + &TyPtr(ref p) | &TyRptr(_, ref p) => + check_ptr_subtype(cx, arg.ty.span, &p.ty), + _ => () + } + } } fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, - &["String"]).map_or((), |_| { - span_lint(cx, PTR_ARG, span, - "Writing '&String' instead of '&str' involves a new Object \ - where a slices will do. Consider changing the type to &str") - }), |_| span_lint(cx, PTR_ARG, span, "Writing '&Vec<_>' instead of \ - '&[_]' involves one more reference and cannot be used with \ - non-vec-based slices. Consider changing the type to &[...]") - ) + match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, + &["String"]).map_or((), |_| { + span_lint(cx, PTR_ARG, span, + "Writing '&String' instead of '&str' involves a new Object \ + where a slices will do. Consider changing the type to &str") + }), |_| span_lint(cx, PTR_ARG, span, + "Writing '&Vec<_>' instead of \ + '&[_]' involves one more reference and cannot be used with \ + non-vec-based slices. Consider changing the type to &[...]")) } diff --git a/src/strings.rs b/src/strings.rs index 511d123b58d..3384eed8da5 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -1,5 +1,5 @@ //! This LintPass catches both string addition and string addition + assignment -//! +//! //! Note that since we have two lints where one subsumes the other, we try to //! disable the subsumed lint unless it has a higher level @@ -25,11 +25,11 @@ impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD_ASSIGN) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let &ExprAssign(ref target, ref src) = &e.node { - if is_string(cx, target) && is_add(src, target) { - span_lint(cx, STRING_ADD_ASSIGN, e.span, + if is_string(cx, target) && is_add(src, target) { + span_lint(cx, STRING_ADD_ASSIGN, e.span, "You assign the result of adding something to this string. \ Consider using `String::push_str(..) instead.") } @@ -47,7 +47,7 @@ fn is_add(src: &Expr, target: &Expr) -> bool { match &src.node { &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(target, left), - &ExprBlock(ref block) => block.stmts.is_empty() && + &ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(&*expr, target)), &ExprParen(ref expr) => is_add(&*expr, target), _ => false diff --git a/src/unicode.rs b/src/unicode.rs index 9b908c3f94f..1854d5be7ff 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -9,38 +9,38 @@ declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } pub struct Unicode; impl LintPass for Unicode { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(ZERO_WIDTH_SPACE) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprLit(ref lit) = expr.node { - if let LitStr(ref string, _) = lit.node { - check_str(cx, string, lit.span) - } - } - } + if let ExprLit(ref lit) = expr.node { + if let LitStr(ref string, _) = lit.node { + check_str(cx, string, lit.span) + } + } + } } fn check_str(cx: &Context, string: &str, span: Span) { - let mut start: Option<usize> = None; - for (i, c) in string.char_indices() { - if c == '\u{200B}' { - if start.is_none() { start = Some(i); } - } else { - lint_zero_width(cx, span, start); - start = None; - } - } - lint_zero_width(cx, span, start); + let mut start: Option<usize> = None; + for (i, c) in string.char_indices() { + if c == '\u{200B}' { + if start.is_none() { start = Some(i); } + } else { + lint_zero_width(cx, span, start); + start = None; + } + } + lint_zero_width(cx, span, start); } fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) { - start.map(|index| { - span_lint(cx, ZERO_WIDTH_SPACE, Span { - lo: span.lo + BytePos(index as u32), - hi: span.lo + BytePos(index as u32), - expn_id: span.expn_id, - }, "Zero-width space detected. Consider using \\u{200B}") - }); + start.map(|index| { + span_lint(cx, ZERO_WIDTH_SPACE, Span { + lo: span.lo + BytePos(index as u32), + hi: span.lo + BytePos(index as u32), + expn_id: span.expn_id, + }, "Zero-width space detected. Consider using \\u{200B}") + }); } diff --git a/src/utils.rs b/src/utils.rs index a231171aee5..4f5763b1491 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,7 +15,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| // macro doesn't start with "macro_rules" // = compiler plugin !code.starts_with("macro_rules") @@ -26,7 +26,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { /// invokes in_macro with the expansion info of the given span pub fn in_external_macro(cx: &Context, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, + cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) } @@ -57,7 +57,7 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { let node_id : NodeId = e.id; let parent_id : NodeId = map.get_parent_node(node_id); if node_id == parent_id { return None; } - map.find(parent_id).and_then(|node| + map.find(parent_id).and_then(|node| if let NodeExpr(parent) = node { Some(parent) } else { None } ) } @@ -77,7 +77,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); } -pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, +pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, help: &str) { span_lint(cx, lint, span, msg); if cx.current_level(lint) != Level::Allow { diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs old mode 100644 new mode 100755 index 488c8f16f5b..3eb170b295b --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -4,53 +4,53 @@ #[deny(approx_constant)] #[allow(unused)] fn main() { - let my_e = 2.7182; //~ERROR - let almost_e = 2.718; //~ERROR - let no_e = 2.71; - - let my_1_frac_pi = 0.3183; //~ERROR - let no_1_frac_pi = 0.31; - - let my_frac_1_sqrt_2 = 0.70710678; //~ERROR - let almost_frac_1_sqrt_2 = 0.70711; //~ERROR - let my_frac_1_sqrt_2 = 0.707; - - let my_frac_2_pi = 0.63661977; //~ERROR - let no_frac_2_pi = 0.636; - - let my_frac_2_sq_pi = 1.128379; //~ERROR - let no_frac_2_sq_pi = 1.128; - - let my_frac_2_pi = 1.57079632679; //~ERROR - let no_frac_2_pi = 1.5705; - - let my_frac_3_pi = 1.04719755119; //~ERROR - let no_frac_3_pi = 1.047; - - let my_frac_4_pi = 0.785398163397; //~ERROR - let no_frac_4_pi = 0.785; - - let my_frac_6_pi = 0.523598775598; //~ERROR - let no_frac_6_pi = 0.523; - - let my_frac_8_pi = 0.3926990816987; //~ERROR - let no_frac_8_pi = 0.392; - - let my_ln_10 = 2.302585092994046; //~ERROR - let no_ln_10 = 2.303; - - let my_ln_2 = 0.6931471805599453; //~ERROR - let no_ln_2 = 0.693; - - let my_log10_e = 0.43429448190325176; //~ERROR - let no_log10_e = 0.434; - - let my_log2_e = 1.4426950408889634; //~ERROR - let no_log2_e = 1.442; - - let my_pi = 3.1415; //~ERROR - let almost_pi = 3.141; - - let my_sq2 = 1.4142; //~ERROR - let no_sq2 = 1.414; + let my_e = 2.7182; //~ERROR + let almost_e = 2.718; //~ERROR + let no_e = 2.71; + + let my_1_frac_pi = 0.3183; //~ERROR + let no_1_frac_pi = 0.31; + + let my_frac_1_sqrt_2 = 0.70710678; //~ERROR + let almost_frac_1_sqrt_2 = 0.70711; //~ERROR + let my_frac_1_sqrt_2 = 0.707; + + let my_frac_2_pi = 0.63661977; //~ERROR + let no_frac_2_pi = 0.636; + + let my_frac_2_sq_pi = 1.128379; //~ERROR + let no_frac_2_sq_pi = 1.128; + + let my_frac_2_pi = 1.57079632679; //~ERROR + let no_frac_2_pi = 1.5705; + + let my_frac_3_pi = 1.04719755119; //~ERROR + let no_frac_3_pi = 1.047; + + let my_frac_4_pi = 0.785398163397; //~ERROR + let no_frac_4_pi = 0.785; + + let my_frac_6_pi = 0.523598775598; //~ERROR + let no_frac_6_pi = 0.523; + + let my_frac_8_pi = 0.3926990816987; //~ERROR + let no_frac_8_pi = 0.392; + + let my_ln_10 = 2.302585092994046; //~ERROR + let no_ln_10 = 2.303; + + let my_ln_2 = 0.6931471805599453; //~ERROR + let no_ln_2 = 0.693; + + let my_log10_e = 0.43429448190325176; //~ERROR + let no_log10_e = 0.434; + + let my_log2_e = 1.4426950408889634; //~ERROR + let no_log2_e = 1.442; + + let my_pi = 3.1415; //~ERROR + let almost_pi = 3.141; + + let my_sq2 = 1.4142; //~ERROR + let no_sq2 = 1.414; } diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs old mode 100644 new mode 100755 index 9b648a517e0..42bb0fca6dc --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -5,29 +5,29 @@ #[inline(always)] //~ERROR You have declared #[inline(always)] on test_attr_lint. fn test_attr_lint() { - assert!(true) + assert!(true) } #[inline(always)] fn false_positive_expr() { - unreachable!() + unreachable!() } #[inline(always)] fn false_positive_stmt() { - unreachable!(); + unreachable!(); } #[inline(always)] fn empty_and_false_positive_stmt() { - ; - unreachable!(); + ; + unreachable!(); } fn main() { - test_attr_lint(); - if false { false_positive_expr() } - if false { false_positive_stmt() } - if false { empty_and_false_positive_stmt() } + test_attr_lint(); + if false { false_positive_expr() } + if false { false_positive_stmt() } + if false { empty_and_false_positive_stmt() } } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs old mode 100644 new mode 100755 index e6b89b98564..c2a82483005 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -7,47 +7,47 @@ const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] #[allow(ineffective_bit_mask, identity_op)] fn main() { - let x = 5; - - x & 0 == 0; //~ERROR &-masking with zero - x & 1 == 1; //ok, distinguishes bit 0 - x & 1 == 0; //ok, compared with zero - x & 2 == 1; //~ERROR - x | 0 == 0; //ok, equals x == 0 (maybe warn?) - x | 1 == 3; //ok, equals x == 2 || x == 3 - x | 3 == 3; //ok, equals x <= 3 - x | 3 == 2; //~ERROR - - x & 1 > 1; //~ERROR - x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 - x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 - x | 1 > 1; // ok (if a bit silly), equals x > 1 - x | 2 > 1; //~ERROR - x | 2 <= 2; // ok (if a bit silly), equals x <= 2 - - // this also now works with constants - x & THREE_BITS == 8; //~ERROR - x | EVEN_MORE_REDIRECTION < 7; //~ERROR - - 0 & x == 0; //~ERROR - 1 | x > 1; - - // and should now also match uncommon usage - 1 < 2 | x; //~ERROR - 2 == 3 | x; //~ERROR - 1 == x & 2; //~ERROR - - x | 1 > 2; // no error, because we allowed ineffective bit masks - ineffective(); + let x = 5; + + x & 0 == 0; //~ERROR &-masking with zero + x & 1 == 1; //ok, distinguishes bit 0 + x & 1 == 0; //ok, compared with zero + x & 2 == 1; //~ERROR + x | 0 == 0; //ok, equals x == 0 (maybe warn?) + x | 1 == 3; //ok, equals x == 2 || x == 3 + x | 3 == 3; //ok, equals x <= 3 + x | 3 == 2; //~ERROR + + x & 1 > 1; //~ERROR + x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x | 1 > 1; // ok (if a bit silly), equals x > 1 + x | 2 > 1; //~ERROR + x | 2 <= 2; // ok (if a bit silly), equals x <= 2 + + // this also now works with constants + x & THREE_BITS == 8; //~ERROR + x | EVEN_MORE_REDIRECTION < 7; //~ERROR + + 0 & x == 0; //~ERROR + 1 | x > 1; + + // and should now also match uncommon usage + 1 < 2 | x; //~ERROR + 2 == 3 | x; //~ERROR + 1 == x & 2; //~ERROR + + x | 1 > 2; // no error, because we allowed ineffective bit masks + ineffective(); } #[deny(ineffective_bit_mask)] #[allow(bad_bit_mask)] fn ineffective() { - let x = 5; - - x | 1 > 2; //~ERROR - x | 1 < 3; //~ERROR - x | 1 <= 3; //~ERROR - x | 1 >= 2; //~ERROR + let x = 5; + + x | 1 > 2; //~ERROR + x | 1 < 3; //~ERROR + x | 1 <= 3; //~ERROR + x | 1 >= 2; //~ERROR } diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs old mode 100644 new mode 100755 index 51d21f5537a..7d80dd86d22 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -8,7 +8,7 @@ pub fn test(foo: Box<Vec<bool>>) { //~ ERROR You seem to be trying to use Box<Ve } pub fn test2(foo: Box<Fn(Vec<u32>)>) { // pass if #31 is fixed - foo(vec![1, 2, 3]) + foo(vec![1, 2, 3]) } fn main(){ diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs old mode 100644 new mode 100755 index 69631331467..b6549c2c1fb --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -4,19 +4,19 @@ #[deny(cmp_nan)] #[allow(float_cmp)] fn main() { - let x = 5f32; - x == std::f32::NAN; //~ERROR - x != std::f32::NAN; //~ERROR - x < std::f32::NAN; //~ERROR - x > std::f32::NAN; //~ERROR - x <= std::f32::NAN; //~ERROR - x >= std::f32::NAN; //~ERROR + let x = 5f32; + x == std::f32::NAN; //~ERROR + x != std::f32::NAN; //~ERROR + x < std::f32::NAN; //~ERROR + x > std::f32::NAN; //~ERROR + x <= std::f32::NAN; //~ERROR + x >= std::f32::NAN; //~ERROR - let y = 0f64; - y == std::f64::NAN; //~ERROR - y != std::f64::NAN; //~ERROR - y < std::f64::NAN; //~ERROR - y > std::f64::NAN; //~ERROR - y <= std::f64::NAN; //~ERROR - y >= std::f64::NAN; //~ERROR + let y = 0f64; + y == std::f64::NAN; //~ERROR + y != std::f64::NAN; //~ERROR + y < std::f64::NAN; //~ERROR + y > std::f64::NAN; //~ERROR + y <= std::f64::NAN; //~ERROR + y >= std::f64::NAN; //~ERROR } diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs old mode 100644 new mode 100755 index d7399e6d3aa..5951dc1bbd7 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -3,21 +3,21 @@ #[deny(cmp_owned)] fn main() { - let x = "oh"; - - #[allow(str_to_string)] - fn with_to_string(x : &str) { - x != "foo".to_string(); //~ERROR this creates an owned instance - } - with_to_string(x); - - x != "foo".to_owned(); //~ERROR this creates an owned instance - - #[allow(deprecated)] // for from_str - fn old_timey(x : &str) { - x != String::from_str("foo"); //~ERROR this creates an owned instance - } - old_timey(x); - - x != String::from("foo"); //~ERROR this creates an owned instance + let x = "oh"; + + #[allow(str_to_string)] + fn with_to_string(x : &str) { + x != "foo".to_string(); //~ERROR this creates an owned instance + } + with_to_string(x); + + x != "foo".to_owned(); //~ERROR this creates an owned instance + + #[allow(deprecated)] // for from_str + fn old_timey(x : &str) { + x != String::from_str("foo"); //~ERROR this creates an owned instance + } + old_timey(x); + + x != String::from("foo"); //~ERROR this creates an owned instance } diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs old mode 100644 new mode 100755 index 7b7ff13f24b..280744b5b45 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -34,10 +34,10 @@ fn main() { } } - if x == "hello" { - print!("Hello "); - if y == "world" { - println!("world!") - } - } + if x == "hello" { + print!("Hello "); + if y == "world" { + println!("world!") + } + } } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs old mode 100644 new mode 100755 index 07b15625b2c..45fce0c0bb3 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -2,35 +2,35 @@ #![plugin(clippy)] fn id<X>(x: X) -> X { - x + x } #[deny(eq_op)] #[allow(identity_op)] fn main() { - // simple values and comparisons - 1 == 1; //~ERROR - "no" == "no"; //~ERROR - // even though I agree that no means no ;-) - false != false; //~ERROR - 1.5 < 1.5; //~ERROR - 1u64 >= 1u64; //~ERROR - - // casts, methods, parenthesis - (1 as u64) & (1 as u64); //~ERROR - 1 ^ ((((((1)))))); //~ERROR - id((1)) | id(1); //~ERROR - - // unary and binary operators - (-(2) < -(2)); //~ERROR + // simple values and comparisons + 1 == 1; //~ERROR + "no" == "no"; //~ERROR + // even though I agree that no means no ;-) + false != false; //~ERROR + 1.5 < 1.5; //~ERROR + 1u64 >= 1u64; //~ERROR + + // casts, methods, parenthesis + (1 as u64) & (1 as u64); //~ERROR + 1 ^ ((((((1)))))); //~ERROR + id((1)) | id(1); //~ERROR + + // unary and binary operators + (-(2) < -(2)); //~ERROR ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); //~^ ERROR //~^^ ERROR //~^^^ ERROR - (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR - - // various other things - ([1] != [1]); //~ERROR + (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR + + // various other things + ([1] != [1]); //~ERROR ((1, 2) != (1, 2)); //~ERROR [1].len() == [1].len(); //~ERROR vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs old mode 100644 new mode 100755 index dce8dba1ebe..2305e42161a --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -7,29 +7,29 @@ const ZERO : f32 = 0.0; const ONE : f32 = ZERO + 1.0; fn twice<T>(x : T) -> T where T : Add<T, Output = T>, T : Copy { - x + x + x + x } #[deny(float_cmp)] #[allow(unused)] fn main() { - ZERO == 0f32; //~ERROR - ZERO == 0.0; //~ERROR - ZERO + ZERO != 1.0; //~ERROR - - ONE != 0.0; //~ERROR - twice(ONE) != ONE; //~ERROR - ONE as f64 != 0.0; //~ERROR - - let x : f64 = 1.0; - - x == 1.0; //~ERROR - x != 0f64; //~ERROR - - twice(x) != twice(ONE as f64); //~ERROR - - x < 0.0; - x > 0.0; - x <= 0.0; - x >= 0.0; + ZERO == 0f32; //~ERROR + ZERO == 0.0; //~ERROR + ZERO + ZERO != 1.0; //~ERROR + + ONE != 0.0; //~ERROR + twice(ONE) != ONE; //~ERROR + ONE as f64 != 0.0; //~ERROR + + let x : f64 = 1.0; + + x == 1.0; //~ERROR + x != 0f64; //~ERROR + + twice(x) != twice(ONE as f64); //~ERROR + + x < 0.0; + x > 0.0; + x <= 0.0; + x >= 0.0; } diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs old mode 100644 new mode 100755 index 6c17d30fac4..cde4a615b25 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -7,18 +7,18 @@ const ZERO : i64 = 0; #[deny(identity_op)] fn main() { - let x = 0; - - x + 0; //~ERROR - 0 + x; //~ERROR - x - ZERO; //~ERROR - x | (0); //~ERROR - ((ZERO)) | x; //~ERROR - - x * 1; //~ERROR - 1 * x; //~ERROR - x / ONE; //~ERROR - - x & NEG_ONE; //~ERROR - -1 & x; //~ERROR + let x = 0; + + x + 0; //~ERROR + 0 + x; //~ERROR + x - ZERO; //~ERROR + x | (0); //~ERROR + ((ZERO)) | x; //~ERROR + + x * 1; //~ERROR + 1 * x; //~ERROR + x / ONE; //~ERROR + + x & NEG_ONE; //~ERROR + -1 & x; //~ERROR } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs old mode 100644 new mode 100755 index e64010d334d..48a10042658 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -5,98 +5,98 @@ struct One; #[deny(len_without_is_empty)] impl One { - fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' - 1 - } + fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' + 1 + } } #[deny(len_without_is_empty)] trait TraitsToo { - fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: + fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: } impl TraitsToo for One { - fn len(self: &Self) -> isize { - 0 - } + fn len(self: &Self) -> isize { + 0 + } } struct HasIsEmpty; #[deny(len_without_is_empty)] impl HasIsEmpty { - fn len(self: &Self) -> isize { - 1 - } + fn len(self: &Self) -> isize { + 1 + } - fn is_empty(self: &Self) -> bool { - false - } + fn is_empty(self: &Self) -> bool { + false + } } struct Wither; #[deny(len_without_is_empty)] trait WithIsEmpty { - fn len(self: &Self) -> isize; - fn is_empty(self: &Self) -> bool; + fn len(self: &Self) -> isize; + fn is_empty(self: &Self) -> bool; } impl WithIsEmpty for Wither { - fn len(self: &Self) -> isize { - 1 - } + fn len(self: &Self) -> isize { + 1 + } - fn is_empty(self: &Self) -> bool { - false - } + fn is_empty(self: &Self) -> bool { + false + } } struct HasWrongIsEmpty; #[deny(len_without_is_empty)] impl HasWrongIsEmpty { - fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' - 1 - } - - #[allow(dead_code, unused)] - fn is_empty(self: &Self, x : u32) -> bool { - false - } + fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' + 1 + } + + #[allow(dead_code, unused)] + fn is_empty(self: &Self, x : u32) -> bool { + false + } } #[deny(len_zero)] fn main() { - let x = [1, 2]; - if x.len() == 0 { //~ERROR Consider replacing the len comparison - println!("This should not happen!"); - } - - let y = One; - if y.len() == 0 { //no error because One does not have .is_empty() - println!("This should not happen either!"); - } - - let z : &TraitsToo = &y; - if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method - println!("Nor should this!"); - } - - let hie = HasIsEmpty; - if hie.len() == 0 { //~ERROR Consider replacing the len comparison - println!("Or this!"); - } - assert!(!hie.is_empty()); - - let wie : &WithIsEmpty = &Wither; - if wie.len() == 0 { //~ERROR Consider replacing the len comparison - println!("Or this!"); - } - assert!(!wie.is_empty()); - - let hwie = HasWrongIsEmpty; - if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() - println!("Or this!"); - } + let x = [1, 2]; + if x.len() == 0 { //~ERROR Consider replacing the len comparison + println!("This should not happen!"); + } + + let y = One; + if y.len() == 0 { //no error because One does not have .is_empty() + println!("This should not happen either!"); + } + + let z : &TraitsToo = &y; + if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method + println!("Nor should this!"); + } + + let hie = HasIsEmpty; + if hie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!hie.is_empty()); + + let wie : &WithIsEmpty = &Wither; + if wie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!wie.is_empty()); + + let hwie = HasWrongIsEmpty; + if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() + println!("Or this!"); + } } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs old mode 100644 new mode 100755 index d7adc067740..2a3f7e3958c --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -6,29 +6,29 @@ #[deny(mut_mut)] fn fun(x : &mut &mut u32) -> bool { //~ERROR - **x > 0 + **x > 0 } macro_rules! mut_ptr { - ($p:expr) => { &mut $p } -} + ($p:expr) => { &mut $p } +} #[deny(mut_mut)] #[allow(unused_mut, unused_variables)] fn main() { - let mut x = &mut &mut 1u32; //~ERROR - { - let mut y = &mut x; //~ERROR - } - - if fun(x) { - let y : &mut &mut &mut u32 = &mut &mut &mut 2; - //~^ ERROR - //~^^ ERROR - //~^^^ ERROR - //~^^^^ ERROR - ***y + **x; - } - - let mut z = mut_ptr!(&mut 3u32); //~ERROR + let mut x = &mut &mut 1u32; //~ERROR + { + let mut y = &mut x; //~ERROR + } + + if fun(x) { + let y : &mut &mut &mut u32 = &mut &mut &mut 2; + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + //~^^^^ ERROR + ***y + **x; + } + + let mut z = mut_ptr!(&mut 3u32); //~ERROR } diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs old mode 100644 new mode 100755 index 97a478ee410..88919f39d6d --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -3,10 +3,10 @@ #[deny(needless_bool)] fn main() { - let x = true; - if x { true } else { true }; //~ERROR - if x { false } else { false }; //~ERROR - if x { true } else { false }; //~ERROR - if x { false } else { true }; //~ERROR - if x { x } else { false }; // would also be questionable, but we don't catch this yet + let x = true; + if x { true } else { true }; //~ERROR + if x { false } else { false }; //~ERROR + if x { true } else { false }; //~ERROR + if x { false } else { true }; //~ERROR + if x { x } else { false }; // would also be questionable, but we don't catch this yet } diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs old mode 100644 new mode 100755 index 7969be0f371..fb7d06214a2 --- a/tests/compile-fail/precedence.rs +++ b/tests/compile-fail/precedence.rs @@ -4,7 +4,7 @@ #[deny(precedence)] #[allow(eq_op)] fn main() { - format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR + format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs old mode 100644 new mode 100755 index 2fe36eafa6c..7ba291b1439 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -4,17 +4,17 @@ #[deny(ptr_arg)] #[allow(unused)] fn do_vec(x: &Vec<i64>) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' - //Nothing here + //Nothing here } #[deny(ptr_arg)] #[allow(unused)] fn do_str(x: &String) { //~ERROR - //Nothing here either + //Nothing here either } fn main() { - let x = vec![1i64, 2, 3]; - do_vec(&x); - do_str(&"hello".to_owned()); + let x = vec![1i64, 2, 3]; + do_vec(&x); + do_str(&"hello".to_owned()); } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs old mode 100644 new mode 100755 index 2b200f1d07e..4b6f0bc884f --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -4,9 +4,9 @@ #![deny(string_add_assign)] fn main() { - let x = "".to_owned(); - - for i in (1..3) { - x = x + "."; //~ERROR - } + let x = "".to_owned(); + + for i in (1..3) { + x = x + "."; //~ERROR + } } diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs old mode 100644 new mode 100755 index 0385f45cc5e..a121b985f09 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -3,23 +3,23 @@ #[deny(zero_width_space)] fn zero() { - print!("Here >​< is a ZWS, and ​another"); - //~^ ERROR Zero-width space detected. Consider using \u{200B} - //~^^ ERROR Zero-width space detected. Consider using \u{200B} + print!("Here >​< is a ZWS, and ​another"); + //~^ ERROR Zero-width space detected. Consider using \u{200B} + //~^^ ERROR Zero-width space detected. Consider using \u{200B} } //#[deny(unicode_canon)] fn canon() { - print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à + print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à } //#[deny(ascii_only)] fn uni() { - println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} + println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} } fn main() { - zero(); - uni(); - canon(); + zero(); + uni(); + canon(); } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 4af4ea7673a..602937a40af 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,13 +5,13 @@ use std::env::var; fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); - + let cfg_mode = mode.parse().ok().expect("Invalid mode"); config.target_rustcflags = Some("-L target/debug/".to_owned()); - if let Ok(name) = var::<&str>("TESTNAME") { - let s : String = name.to_owned(); - config.filter = Some(s) - } + if let Ok(name) = var::<&str>("TESTNAME") { + let s : String = name.to_owned(); + config.filter = Some(s) + } config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs old mode 100644 new mode 100755 index 32fdea3a340..ebfd3ed2e1f --- a/tests/mut_mut_macro.rs +++ b/tests/mut_mut_macro.rs @@ -10,22 +10,22 @@ use std::collections::HashMap; #[test] #[deny(mut_mut)] fn test_regex() { - let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); - assert!(pattern.is_match("# headline")); + let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); + assert!(pattern.is_match("# headline")); } #[test] #[deny(mut_mut)] #[allow(unused_variables, unused_mut)] fn test_lazy_static() { - lazy_static! { - static ref MUT_MAP : HashMap<usize, &'static str> = { - let mut m = HashMap::new(); - let mut zero = &mut &mut "zero"; - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert!(*MUT_COUNT == 1); + lazy_static! { + static ref MUT_MAP : HashMap<usize, &'static str> = { + let mut m = HashMap::new(); + let mut zero = &mut &mut "zero"; + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert!(*MUT_COUNT == 1); } -- cgit 1.4.1-3-g733a5 From 5060e9e685e97106ee2e98547afc989db8ae7c91 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 00:28:46 +0530 Subject: Bump to 0.0.10 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ce9ea2b3ed3..f5c76132f8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.9" +version = "0.0.10" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" -- cgit 1.4.1-3-g733a5 From cf96042c65b4c232d0a73f6a8514e59e0358719b Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 20:57:21 +0200 Subject: move walk_ty() to utils module and rename to walk_ptrs_ty --- src/len_zero.rs | 5 ++--- src/misc.rs | 15 ++++----------- src/strings.rs | 5 ++--- src/utils.rs | 8 ++++++++ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 0877fa95238..8aa4c626760 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -9,8 +9,7 @@ use rustc::middle::ty::{self, TypeVariants, TypeAndMut, MethodTraitItemId, ImplO use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; -use misc::walk_ty; -use utils::span_lint; +use utils::{span_lint, walk_ptrs_ty}; declare_lint!(pub LEN_ZERO, Warn, "Warn when .is_empty() could be used instead of checking .len()"); @@ -136,7 +135,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { |iids| iids.iter().any(|i| is_is_empty(cx, i))))) } - let ty = &walk_ty(&cx.tcx.expr_ty(expr)); + let ty = &walk_ptrs_ty(&cx.tcx.expr_ty(expr)); match ty.sty { ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, diff --git a/src/misc.rs b/src/misc.rs index 444062a5919..a1b3dcb32b8 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,14 +7,7 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; -use utils::{match_path, snippet, span_lint, span_help_and_lint}; - -pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { - match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ty(tm.ty), - _ => ty - } -} +use utils::{match_path, snippet, span_lint, span_help_and_lint, walk_ptrs_ty}; /// Handles uncategorized lints /// Currently handles linting of if-let-able matches @@ -87,7 +80,7 @@ impl LintPass for StrToStringPass { } fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ty(cx.tcx.expr_ty(expr)).sty { + match walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { ty::TyStr => true, _ => false } @@ -175,7 +168,7 @@ impl LintPass for FloatCmp { } fn is_float(cx: &Context, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ty(cx.tcx.expr_ty(expr)).sty { + if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { true } else { false @@ -274,7 +267,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = - walk_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } + walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } declare_lint!(pub NEEDLESS_RETURN, Warn, diff --git a/src/strings.rs b/src/strings.rs index 3384eed8da5..b6bc7654e47 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -8,9 +8,8 @@ use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use eq_op::is_exp_equal; -use misc::walk_ty; use types::match_ty_unwrap; -use utils::{match_def_path, span_lint}; +use utils::{match_def_path, span_lint, walk_ptrs_ty}; declare_lint! { pub STRING_ADD_ASSIGN, @@ -38,7 +37,7 @@ impl LintPass for StringAdd { } fn is_string(cx: &Context, e: &Expr) -> bool { - if let TyStruct(did, _) = walk_ty(cx.tcx.expr_ty(e)).sty { + if let TyStruct(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(e)).sty { match_def_path(cx, did.did, &["std", "string", "String"]) } else { false } } diff --git a/src/utils.rs b/src/utils.rs index 9b3b94e113e..107f5c6f99b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -84,3 +84,11 @@ pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, cx.sess().fileline_help(span, help); } } + +/// return the base type for references and raw pointers +pub fn walk_ptrs_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { + match ty.sty { + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), + _ => ty + } +} -- cgit 1.4.1-3-g733a5 From 2bcc15188854ff184c85426b5aa60535ed1bd8a8 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 20:53:50 +0200 Subject: new lint for Option.unwrap() and Result.unwrap() The latter is set to Allow by default (fixes #24) --- src/lib.rs | 4 ++++ src/methods.rs | 39 +++++++++++++++++++++++++++++++++++++++ tests/compile-fail/methods.rs | 11 +++++++++++ 3 files changed, 54 insertions(+) create mode 100644 src/methods.rs create mode 100755 tests/compile-fail/methods.rs diff --git a/src/lib.rs b/src/lib.rs index 80ba04031fa..4009aa1cf8d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ pub mod collapsible_if; pub mod unicode; pub mod utils; pub mod strings; +pub mod methods; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -55,6 +56,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); reg.register_lint_pass(box misc::NeedlessReturn as LintPassObject); + reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -77,5 +79,7 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_ADD_ASSIGN, misc::NEEDLESS_RETURN, misc::MODULO_ONE, + methods::OPTION_UNWRAP_USED, + methods::RESULT_UNWRAP_USED, ]); } diff --git a/src/methods.rs b/src/methods.rs new file mode 100644 index 00000000000..3d9aa8c6ffc --- /dev/null +++ b/src/methods.rs @@ -0,0 +1,39 @@ +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray}; +use rustc::middle::ty; + +use utils::{span_lint, match_def_path, walk_ptrs_ty}; + +#[derive(Copy,Clone)] +pub struct MethodsPass; + +declare_lint!(pub OPTION_UNWRAP_USED, Warn, + "Warn on using unwrap() on an Option value"); +declare_lint!(pub RESULT_UNWRAP_USED, Allow, + "Warn on using unwrap() on a Result value"); + +impl LintPass for MethodsPass { + fn get_lints(&self) -> LintArray { + lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprMethodCall(ref ident, _, ref args) = expr.node { + if ident.node.name == "unwrap" { + if let ty::TyEnum(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { + if match_def_path(cx, did.did, &["core", "option", "Option"]) { + span_lint(cx, OPTION_UNWRAP_USED, expr.span, + "used unwrap() on an Option value. If you don't want \ + to handle the None case gracefully, consider using + expect() to provide a better panic message."); + } + else if match_def_path(cx, did.did, &["core", "result", "Result"]) { + span_lint(cx, RESULT_UNWRAP_USED, expr.span, + "used unwrap() on a Result value. Graceful handling \ + of Err values is preferred."); + } + } + } + } + } +} diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs new file mode 100755 index 00000000000..e989dffe5a7 --- /dev/null +++ b/tests/compile-fail/methods.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(option_unwrap_used, result_unwrap_used)] +fn main() { + let opt = Some(0); + let _ = opt.unwrap(); //~ERROR + + let res: Result<i32, ()> = Ok(0); + let _ = res.unwrap(); //~ERROR +} -- cgit 1.4.1-3-g733a5 From 4350dab7618bfdd58ea6eca45dca8151434dc4a4 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 21:25:24 +0200 Subject: types: remove almost duplicate helper function I guess "help" instead of "note" is fine as well, so we can get rid of the extra function. --- src/types.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/types.rs b/src/types.rs index d138239b5a7..f6d7749f160 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,7 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use syntax::codemap::Span; -use utils::span_lint; +use utils::{span_lint, span_help_and_lint}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -40,14 +40,6 @@ pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> } } -/// Lets me span a note only if the lint is shown -pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) { - span_lint(cx, lint, span, msg); - if cx.current_level(lint) != Level::Allow { - cx.sess().span_note(span, note); - } -} - impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, LINKEDLIST) @@ -62,7 +54,7 @@ impl LintPass for TypePass { match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first()) .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { - span_note_and_lint(cx, BOX_VEC, ty.span, + span_help_and_lint(cx, BOX_VEC, ty.span, "You seem to be trying to use Box<Vec<T>>. Did you mean to use Vec<T>?", "Vec<T> is already on the heap, Box<Vec<T>> makes an extra allocation"); }); @@ -77,7 +69,7 @@ impl LintPass for TypePass { vec!["collections","linked_list","LinkedList"]]; for path in dlists.iter() { if match_ty_unwrap(ty, &path[..]).is_some() { - span_note_and_lint(cx, LINKEDLIST, ty.span, + span_help_and_lint(cx, LINKEDLIST, ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", "A RingBuf might work."); return; -- cgit 1.4.1-3-g733a5 From dfd1f42dd211ee77d2b5934357b8f414401c53b9 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 21:30:55 +0200 Subject: README: update with recently added lints --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 62367b8a26e..f0d282e450a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,10 @@ Lints included in this crate: - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. + - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. + - `option_unwrap_used`: Warns when `Option.unwrap()` is used, and suggests `.expect()`. + - `result_unwrap_used`: Warns when `Result.unwrap()` is used (silent by default). + - `modulo_one`: Warns on taking a number modulo 1, which always has a result of 0. To use, add the following lines to your Cargo.toml: -- cgit 1.4.1-3-g733a5 From 02c0cafa146759f908201467d0a758f8f3d75325 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 21:47:34 +0200 Subject: move NeedlessReturn pass out to its own module and rename to ReturnPass --- src/lib.rs | 5 ++-- src/misc.rs | 69 ----------------------------------------------------- src/returns.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 71 deletions(-) create mode 100644 src/returns.rs diff --git a/src/lib.rs b/src/lib.rs index 4009aa1cf8d..c5469c19858 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ pub mod unicode; pub mod utils; pub mod strings; pub mod methods; +pub mod returns; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -55,7 +56,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); - reg.register_lint_pass(box misc::NeedlessReturn as LintPassObject); + reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, @@ -77,7 +78,7 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, unicode::ZERO_WIDTH_SPACE, strings::STRING_ADD_ASSIGN, - misc::NEEDLESS_RETURN, + returns::NEEDLESS_RETURN, misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, diff --git a/src/misc.rs b/src/misc.rs index a1b3dcb32b8..934e8a7fb77 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -270,75 +270,6 @@ fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } -declare_lint!(pub NEEDLESS_RETURN, Warn, - "Warn on using a return statement where an expression would be enough"); - -#[derive(Copy,Clone)] -pub struct NeedlessReturn; - -impl NeedlessReturn { - // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &Context, block: &Block) { - if let Some(ref expr) = block.expr { - self.check_final_expr(cx, expr); - } else if let Some(stmt) = block.stmts.last() { - if let StmtSemi(ref expr, _) = stmt.node { - if let ExprRet(Some(ref inner)) = expr.node { - self.emit_lint(cx, (expr.span, inner.span)); - } - } - } - } - - // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &Context, expr: &Expr) { - match expr.node { - // simple return is always "bad" - ExprRet(Some(ref inner)) => { - self.emit_lint(cx, (expr.span, inner.span)); - } - // a whole block? check it! - ExprBlock(ref block) => { - self.check_block_return(cx, block); - } - // an if/if let expr, check both exprs - // note, if without else is going to be a type checking error anyways - // (except for unit type functions) so we don't match it - ExprIf(_, ref ifblock, Some(ref elsexpr)) | - ExprIfLet(_, _, ref ifblock, Some(ref elsexpr)) => { - self.check_block_return(cx, ifblock); - self.check_final_expr(cx, elsexpr); - } - // a match expr, check all arms - ExprMatch(_, ref arms, _) => { - for arm in arms { - self.check_final_expr(cx, &*arm.body); - } - } - _ => { } - } - } - - fn emit_lint(&mut self, cx: &Context, spans: (Span, Span)) { - span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( - "unneeded return statement. Consider using {} \ - without the trailing semicolon", - snippet(cx, spans.1, ".."))) - } -} - -impl LintPass for NeedlessReturn { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RETURN) - } - - fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, - block: &Block, _: Span, _: ast::NodeId) { - self.check_block_return(cx, block); - } -} - - declare_lint!(pub MODULO_ONE, Warn, "Warn on expressions that include % 1, which is always 0"); #[derive(Copy,Clone)] diff --git a/src/returns.rs b/src/returns.rs new file mode 100644 index 00000000000..d6a4b33b6d1 --- /dev/null +++ b/src/returns.rs @@ -0,0 +1,75 @@ +use syntax::ast; +use syntax::ast::*; +use syntax::codemap::Span; +use syntax::visit::FnKind; +use rustc::lint::{Context, LintPass, LintArray}; + +use utils::{span_lint, snippet}; + +declare_lint!(pub NEEDLESS_RETURN, Warn, + "Warn on using a return statement where an expression would be enough"); + +#[derive(Copy,Clone)] +pub struct ReturnPass; + +impl ReturnPass { + // Check the final stmt or expr in a block for unnecessary return. + fn check_block_return(&mut self, cx: &Context, block: &Block) { + if let Some(ref expr) = block.expr { + self.check_final_expr(cx, expr); + } else if let Some(stmt) = block.stmts.last() { + if let StmtSemi(ref expr, _) = stmt.node { + if let ExprRet(Some(ref inner)) = expr.node { + self.emit_lint(cx, (expr.span, inner.span)); + } + } + } + } + + // Check a the final expression in a block if it's a return. + fn check_final_expr(&mut self, cx: &Context, expr: &Expr) { + match expr.node { + // simple return is always "bad" + ExprRet(Some(ref inner)) => { + self.emit_lint(cx, (expr.span, inner.span)); + } + // a whole block? check it! + ExprBlock(ref block) => { + self.check_block_return(cx, block); + } + // an if/if let expr, check both exprs + // note, if without else is going to be a type checking error anyways + // (except for unit type functions) so we don't match it + ExprIf(_, ref ifblock, Some(ref elsexpr)) | + ExprIfLet(_, _, ref ifblock, Some(ref elsexpr)) => { + self.check_block_return(cx, ifblock); + self.check_final_expr(cx, elsexpr); + } + // a match expr, check all arms + ExprMatch(_, ref arms, _) => { + for arm in arms { + self.check_final_expr(cx, &*arm.body); + } + } + _ => { } + } + } + + fn emit_lint(&mut self, cx: &Context, spans: (Span, Span)) { + span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( + "unneeded return statement. Consider using {} \ + without the trailing semicolon", + snippet(cx, spans.1, ".."))) + } +} + +impl LintPass for ReturnPass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_RETURN) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, + block: &Block, _: Span, _: ast::NodeId) { + self.check_block_return(cx, block); + } +} -- cgit 1.4.1-3-g733a5 From f6dc48fe3a0ec30b6db132b6848f6908f987af14 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 11 Aug 2015 22:06:30 +0200 Subject: new lint for "let x = EXPR; x" at the end of functions (fixes #104) --- README.md | 1 + src/returns.rs | 49 ++++++++++++++++++++++++++++++++++------ tests/compile-fail/let_return.rs | 34 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100755 tests/compile-fail/let_return.rs diff --git a/README.md b/README.md index f0d282e450a..1176841ca20 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Lints included in this crate: - `zero_width_space`: Warns on encountering a unicode zero-width space - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. + - `let_and_return`: Warns on doing `let x = expr; x` at the end of a function. - `option_unwrap_used`: Warns when `Option.unwrap()` is used, and suggests `.expect()`. - `result_unwrap_used`: Warns when `Result.unwrap()` is used (silent by default). - `modulo_one`: Warns on taking a number modulo 1, which always has a result of 0. diff --git a/src/returns.rs b/src/returns.rs index d6a4b33b6d1..9bfc99972c9 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,13 +1,15 @@ use syntax::ast; use syntax::ast::*; -use syntax::codemap::Span; +use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use rustc::lint::{Context, LintPass, LintArray}; +use rustc::lint::{Context, LintPass, LintArray, Level}; -use utils::{span_lint, snippet}; +use utils::{span_lint, snippet, match_path}; declare_lint!(pub NEEDLESS_RETURN, Warn, "Warn on using a return statement where an expression would be enough"); +declare_lint!(pub LET_AND_RETURN, Warn, + "Warn on creating a let-binding and then immediately returning it"); #[derive(Copy,Clone)] pub struct ReturnPass; @@ -20,7 +22,7 @@ impl ReturnPass { } else if let Some(stmt) = block.stmts.last() { if let StmtSemi(ref expr, _) = stmt.node { if let ExprRet(Some(ref inner)) = expr.node { - self.emit_lint(cx, (expr.span, inner.span)); + self.emit_return_lint(cx, (expr.span, inner.span)); } } } @@ -31,7 +33,7 @@ impl ReturnPass { match expr.node { // simple return is always "bad" ExprRet(Some(ref inner)) => { - self.emit_lint(cx, (expr.span, inner.span)); + self.emit_return_lint(cx, (expr.span, inner.span)); } // a whole block? check it! ExprBlock(ref block) => { @@ -55,21 +57,54 @@ impl ReturnPass { } } - fn emit_lint(&mut self, cx: &Context, spans: (Span, Span)) { + fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using {} \ without the trailing semicolon", snippet(cx, spans.1, ".."))) } + + // Check for "let x = EXPR; x" + fn check_let_return(&mut self, cx: &Context, block: &Block) { + // we need both a let-binding stmt and an expr + if let Some(stmt) = block.stmts.last() { + if let StmtDecl(ref decl, _) = stmt.node { + if let DeclLocal(ref local) = decl.node { + if let Some(ref initexpr) = local.init { + if let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node { + if let Some(ref retexpr) = block.expr { + if let ExprPath(_, ref path) = retexpr.node { + if match_path(path, &[&*id.name.as_str()]) { + self.emit_let_lint(cx, retexpr.span, initexpr.span); + } + } + } + } + } + } + } + } + } + + fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) { + span_lint(cx, LET_AND_RETURN, lint_span, + "returning the result of a let binding. \ + Consider returning the expression directly."); + if cx.current_level(LET_AND_RETURN) != Level::Allow { + cx.sess().span_note(note_span, + "this expression can be directly returned"); + } + } } impl LintPass for ReturnPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RETURN) + lint_array!(NEEDLESS_RETURN, LET_AND_RETURN) } fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: ast::NodeId) { self.check_block_return(cx, block); + self.check_let_return(cx, block); } } diff --git a/tests/compile-fail/let_return.rs b/tests/compile-fail/let_return.rs new file mode 100755 index 00000000000..8ea4653ef0f --- /dev/null +++ b/tests/compile-fail/let_return.rs @@ -0,0 +1,34 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(let_and_return)] + +fn test() -> i32 { + let _y = 0; // no warning + let x = 5; //~NOTE + x //~ERROR: +} + +fn test_nowarn_1() -> i32 { + let mut x = 5; + x += 1; + x +} + +fn test_nowarn_2() -> i32 { + let x = 5; + x + 1 +} + +fn test_nowarn_3() -> (i32, i32) { + // this should technically warn, but we do not compare complex patterns + let (x, y) = (5, 9); + (x, y) +} + +fn main() { + test(); + test_nowarn_1(); + test_nowarn_2(); + test_nowarn_3(); +} -- cgit 1.4.1-3-g733a5 From 854212ce852a421f0ef0ba056ea3d77911380fc7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 03:32:20 +0530 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d32b0ce8a31..8bac03d9447 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,6 +43,8 @@ Contributions to Clippy should be made in the form of GitHub pull requests. Each be reviewed by a core contributor (someone with permission to land patches) and either landed in the main tree or given feedback for changes that would be required. +All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/) + ## Conduct We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). -- cgit 1.4.1-3-g733a5 From 6d5f9478b22da27dc59d204cf94060bf949b6746 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 07:48:00 +0200 Subject: utils: implement if_let_chain macro as suggested by isHavvy --- src/lib.rs | 3 ++- src/returns.rs | 26 ++++++++++++-------------- src/utils.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c5469c19858..fef678f668d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ extern crate collections; use rustc::plugin::Registry; use rustc::lint::LintPassObject; +#[macro_use] +pub mod utils; pub mod types; pub mod misc; pub mod eq_op; @@ -27,7 +29,6 @@ pub mod len_zero; pub mod attrs; pub mod collapsible_if; pub mod unicode; -pub mod utils; pub mod strings; pub mod methods; pub mod returns; diff --git a/src/returns.rs b/src/returns.rs index 9bfc99972c9..5a361d3a7dc 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -67,20 +67,18 @@ impl ReturnPass { // Check for "let x = EXPR; x" fn check_let_return(&mut self, cx: &Context, block: &Block) { // we need both a let-binding stmt and an expr - if let Some(stmt) = block.stmts.last() { - if let StmtDecl(ref decl, _) = stmt.node { - if let DeclLocal(ref local) = decl.node { - if let Some(ref initexpr) = local.init { - if let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node { - if let Some(ref retexpr) = block.expr { - if let ExprPath(_, ref path) = retexpr.node { - if match_path(path, &[&*id.name.as_str()]) { - self.emit_let_lint(cx, retexpr.span, initexpr.span); - } - } - } - } - } + if_let_chain! { + [ + Some(stmt) = block.stmts.last(), + StmtDecl(ref decl, _) = stmt.node, + DeclLocal(ref local) = decl.node, + Some(ref initexpr) = local.init, + PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, + Some(ref retexpr) = block.expr, + ExprPath(_, ref path) = retexpr.node + ], { + if match_path(path, &[&*id.name.as_str()]) { + self.emit_let_lint(cx, retexpr.span, initexpr.span); } } } diff --git a/src/utils.rs b/src/utils.rs index 107f5c6f99b..575d39b0c23 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -92,3 +92,32 @@ pub fn walk_ptrs_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { _ => ty } } + +/// Produce a nested chain of if-lets from the patterns: +/// +/// if_let_chain! {[Some(y) = x, Some(z) = y], +/// { +/// block +/// } +/// } +/// +/// becomes +/// +/// if let Some(y) = x { +/// if let Some(z) = y { +/// block +/// } +/// } +#[macro_export] +macro_rules! if_let_chain { + ([$pat:pat = $expr:expr, $($p2:pat = $e2:expr),+], $block:block) => { + if let $pat = $expr { + if_let_chain!{ [$($p2 = $e2),+], $block } + } + }; + ([$pat:pat = $expr:expr], $block:block) => { + if let $pat = $expr { + $block + } + }; +} -- cgit 1.4.1-3-g733a5 From 2eacb3c146b7975ecad7c51079ac1b8b0f2803b1 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 07:47:21 +0200 Subject: README: update lint output --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1176841ca20..0a947e12ecf 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,8 @@ src/main.rs:8 match x { src/main.rs:9 Some(y) => println!("{:?}", y), src/main.rs:10 _ => () src/main.rs:11 } -src/main.rs:8:5: 11:6 note: Try if let Some(y) = x { ... } -src/main.rs:8 match x { -src/main.rs:9 Some(y) => println!("{:?}", y), -src/main.rs:10 _ => () -src/main.rs:11 } +src/main.rs:8:5: 11:6 help: Try +if let Some(y) = x { println!("{:?}", y) } ``` You can add options to `allow`/`warn`/`deny`: -- cgit 1.4.1-3-g733a5 From bcd95aec1ce4f2a328a2b1d4b2a1e44d36e02436 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 10:46:49 +0200 Subject: all: make style of lint messages consistent * start first sentence lowercased * use backticks to delimit code snippets * use "this is wrong. Consider doing X." consistently --- src/approx_const.rs | 2 +- src/attrs.rs | 2 +- src/bit_mask.rs | 16 ++++++++-------- src/collapsible_if.rs | 2 +- src/eta_reduction.rs | 2 +- src/identity_op.rs | 2 +- src/len_zero.rs | 10 +++++----- src/misc.rs | 20 ++++++++++---------- src/mut_mut.rs | 8 ++++---- src/needless_bool.rs | 4 ++-- src/ptr_arg.rs | 10 +++++----- src/returns.rs | 2 +- src/strings.rs | 4 ++-- src/types.rs | 8 +++----- src/unicode.rs | 2 +- tests/compile-fail/attrs.rs | 2 +- tests/compile-fail/box_vec.rs | 2 +- tests/compile-fail/collapsible_if.rs | 4 ++-- tests/compile-fail/eta.rs | 8 ++++---- tests/compile-fail/len_zero.rs | 12 ++++++------ tests/compile-fail/match_if_let.rs | 8 ++++---- tests/compile-fail/modulo_one.rs | 2 +- tests/compile-fail/ptr_arg.rs | 2 +- tests/compile-fail/unicode.rs | 6 +++--- 24 files changed, 69 insertions(+), 71 deletions(-) mode change 100644 => 100755 tests/compile-fail/eta.rs mode change 100644 => 100755 tests/compile-fail/modulo_one.rs diff --git a/src/approx_const.rs b/src/approx_const.rs index 3ae579a74b9..594348bf93f 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -53,7 +53,7 @@ fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { for &(constant, name) in KNOWN_CONSTS { if within_epsilon(constant, value) { span_lint(cx, APPROX_CONSTANT, span, &format!( - "Approximate value of {}::{} found, consider using it directly.", module, &name)); + "approximate value of `{}::{}` found. Consider using it directly.", module, &name)); } } } diff --git a/src/attrs.rs b/src/attrs.rs index 6d73f1de964..789a992e3a5 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -101,7 +101,7 @@ fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, if let MetaWord(ref always) = values[0].node { if always != &"always" { continue; } span_lint(cx, INLINE_ALWAYS, attr.span, &format!( - "You have declared #[inline(always)] on {}. This \ + "you have declared `#[inline(always)]` on `{}`. This \ is usually a bad idea. Are you sure?", ident.name.as_str())); } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index ad6facfb199..b5f088c23ef 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -97,7 +97,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, BiBitAnd => if mask_value & cmp_value != mask_value { if cmp_value != 0 { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} can never be equal to {}", + "incompatible bit mask: `_ & {}` can never be equal to `{}`", mask_value, cmp_value)); } } else { @@ -108,7 +108,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiBitOr => if mask_value | cmp_value != cmp_value { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} can never be equal to {}", + "incompatible bit mask: `_ | {}` can never be equal to `{}`", mask_value, cmp_value)); }, _ => () @@ -116,7 +116,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, BiLt | BiGe => match bit_op { BiBitAnd => if mask_value < cmp_value { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} will always be lower than {}", + "incompatible bit mask: `_ & {}` will always be lower than `{}`", mask_value, cmp_value)); } else { if mask_value == 0 { @@ -126,12 +126,12 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiBitOr => if mask_value >= cmp_value { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} will never be lower than {}", + "incompatible bit mask: `_ | {}` will never be lower than `{}`", mask_value, cmp_value)); } else { if mask_value < cmp_value { span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", mask_value, cmp_value)); } }, @@ -140,7 +140,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, BiLe | BiGt => match bit_op { BiBitAnd => if mask_value <= cmp_value { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ & {} will never be higher than {}", + "incompatible bit mask: `_ & {}` will never be higher than `{}`", mask_value, cmp_value)); } else { if mask_value == 0 { @@ -150,12 +150,12 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiBitOr => if mask_value > cmp_value { span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: _ | {} will always be higher than {}", + "incompatible bit mask: `_ | {}` will always be higher than `{}`", mask_value, cmp_value)); } else { if mask_value < cmp_value { span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", mask_value, cmp_value)); } }, diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index eae3222945c..f1c82f3eef8 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -48,7 +48,7 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = single_stmt_of_block(then) { span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( - "This if statement can be collapsed. Try: if {} && {}\n{:?}", + "this if statement can be collapsed. Try: `if {} && {}`\n{:?}", check_to_string(check), check_to_string(check_inner), e)); } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 6948c1b22ab..00c5a523981 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -51,7 +51,7 @@ impl LintPass for EtaPass { } } span_lint(cx, REDUNDANT_CLOSURE, expr.span, - &format!("Redundant closure found, consider using `{}` in its place", + &format!("redundant closure found. Consider using `{}` in its place.", expr_to_string(caller))[..]) } } diff --git a/src/identity_op.rs b/src/identity_op.rs index 56d01c52b1d..e043ac63026 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -49,7 +49,7 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { span_lint(cx, IDENTITY_OP, span, &format!( - "The operation is ineffective. Consider reducing it to '{}'", + "the operation is ineffective. Consider reducing it to `{}`.", snippet(cx, arg, ".."))); } } diff --git a/src/len_zero.rs b/src/len_zero.rs index 8aa4c626760..dea713180f5 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -58,8 +58,8 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { for i in trait_items { if is_named_self(i, "len") { span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, - &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", + &format!("trait `{}` has a `.len(_: &Self)` method, but no \ + `.is_empty(_: &Self)` method. Consider adding one.", item.ident.name)); } }; @@ -78,8 +78,8 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { let s = i.span; span_lint(cx, LEN_WITHOUT_IS_EMPTY, Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, - &format!("Item '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", + &format!("item `{}` has a `.len(_: &Self)` method, but no \ + `.is_empty(_: &Self)` method. Consider adding one.", item.ident.name)); return; } @@ -108,7 +108,7 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, if method.node.name == "len" && args.len() == 1 && has_is_empty(cx, &*args[0]) { span_lint(cx, LEN_ZERO, span, &format!( - "Consider replacing the len comparison with '{}_.is_empty()'", + "consider replacing the len comparison with `{}_.is_empty()`", empty)) } } diff --git a/src/misc.rs b/src/misc.rs index 934e8a7fb77..fa1847aad9a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -43,10 +43,10 @@ impl LintPass for MiscPass { format!("{{ {} }}", body_code) }; span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "You seem to be trying to use match for \ + "you seem to be trying to use match for \ destructuring a single pattern. Did you mean to \ use `if let`?", - &*format!("Try\nif let {} = {} {}", + &*format!("try\nif let {} = {} {}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), suggestion) @@ -74,7 +74,7 @@ impl LintPass for StrToStringPass { ast::ExprMethodCall(ref method, _, ref args) if method.node.name == "to_string" && is_str(cx, &*args[0]) => { - span_lint(cx, STR_TO_STRING, expr.span, "str.to_owned() is faster"); + span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); }, _ => () } @@ -105,7 +105,7 @@ impl LintPass for TopLevelRefPass { span_lint(cx, TOPLEVEL_REF_ARG, arg.pat.span, - "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" + "`ref` directly on a function argument is ignored. Consider using a reference type instead." ); } } @@ -139,7 +139,7 @@ impl LintPass for CmpNan { fn check_nan(cx: &Context, path: &Path, span: Span) { path.segments.last().map(|seg| if seg.identifier.name == "NAN" { span_lint(cx, CMP_NAN, span, - "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); }); } @@ -159,7 +159,7 @@ impl LintPass for FloatCmp { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { span_lint(cx, FLOAT_CMP, expr.span, &format!( - "{}-Comparison of f32 or f64 detected. You may want to change this to 'abs({} - {}) < epsilon' for some suitable value of epsilon", + "{}-comparison of f32 or f64 detected. Consider changing this to `abs({} - {}) < epsilon` for some suitable value of epsilon.", binop_to_string(op), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); } @@ -190,7 +190,7 @@ impl LintPass for Precedence { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { span_lint(cx, PRECEDENCE, expr.span, - "Operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); + "operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); } } } @@ -246,7 +246,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { name == "to_owned" && is_str_arg(cx, args) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ - Consider using {}.as_slice() to compare without allocation", + Consider using `{}.as_slice()` to compare without allocation.", snippet(cx, other_span, ".."))) } }, @@ -256,7 +256,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { match_path(path, &["String", "from"]) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ - Consider using {}.as_slice() to compare without allocation", + Consider using `{}.as_slice()` to compare without allocation.", snippet(cx, other_span, ".."))) } } @@ -284,7 +284,7 @@ impl LintPass for ModuloOne { if let ExprBinary(ref cmp, _, ref right) = expr.node { if let &Spanned {node: BinOp_::BiRem, ..} = cmp { if is_lit_one(right) { - cx.span_lint(MODULO_ONE, expr.span, "Any number modulo 1 will be 0"); + cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 16ea422f77f..469a14a9452 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -23,7 +23,7 @@ impl LintPass for MutMut { fn check_ty(&mut self, cx: &Context, ty: &Ty) { unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, - ty.span, "Generally you want to avoid &mut &mut _ if possible.")) + ty.span, "generally you want to avoid `&mut &mut _` if possible")) } } @@ -40,13 +40,13 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map(|_| { span_lint(cx, MUT_MUT, expr.span, - "Generally you want to avoid &mut &mut _ if possible.") + "generally you want to avoid `&mut &mut _` if possible") }).unwrap_or_else(|| { if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. \ - Consider reborrowing") + "this expression mutably borrows a mutable reference. \ + Consider reborrowing.") } }) }) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 3296bdeca87..fcbc287e30f 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -34,10 +34,10 @@ impl LintPass for NeedlessBool { "your if-then-else expression will always return true"); }, (Option::Some(true), Option::Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to its predicate"); }, + "you can reduce your if statement to its predicate"); }, (Option::Some(false), Option::Some(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to '!' + your predicate"); }, + "you can reduce your if statement to `!` + your predicate"); }, (Option::Some(false), Option::Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, "your if-then-else expression will always return false"); }, diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 939277fe66c..ed37c112040 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -60,10 +60,10 @@ fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, &["String"]).map_or((), |_| { span_lint(cx, PTR_ARG, span, - "Writing '&String' instead of '&str' involves a new Object \ - where a slices will do. Consider changing the type to &str") + "writing `&String` instead of `&str` involves a new object \ + where a slice will do. Consider changing the type to `&str`.") }), |_| span_lint(cx, PTR_ARG, span, - "Writing '&Vec<_>' instead of \ - '&[_]' involves one more reference and cannot be used with \ - non-vec-based slices. Consider changing the type to &[...]")) + "writing `&Vec<_>` instead of \ + `&[_]` involves one more reference and cannot be used with \ + non-Vec-based slices. Consider changing the type to `&[...]`.")) } diff --git a/src/returns.rs b/src/returns.rs index 5a361d3a7dc..70af37d5181 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -59,7 +59,7 @@ impl ReturnPass { fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( - "unneeded return statement. Consider using {} \ + "unneeded return statement. Consider using `{}` \ without the trailing semicolon", snippet(cx, spans.1, ".."))) } diff --git a/src/strings.rs b/src/strings.rs index b6bc7654e47..97016f36268 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -29,8 +29,8 @@ impl LintPass for StringAdd { if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, - "You assign the result of adding something to this string. \ - Consider using `String::push_str(..) instead.") + "you assign the result of adding something to this string. \ + Consider using `String::push_str()` instead.") } } } diff --git a/src/types.rs b/src/types.rs index f6d7749f160..b03829660dc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,3 @@ - - use syntax::ptr::P; use syntax::ast; use syntax::ast::*; @@ -55,8 +53,8 @@ impl LintPass for TypePass { .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) .map(|_| { span_help_and_lint(cx, BOX_VEC, ty.span, - "You seem to be trying to use Box<Vec<T>>. Did you mean to use Vec<T>?", - "Vec<T> is already on the heap, Box<Vec<T>> makes an extra allocation"); + "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); }); { // In case stuff gets moved around @@ -71,7 +69,7 @@ impl LintPass for TypePass { if match_ty_unwrap(ty, &path[..]).is_some() { span_help_and_lint(cx, LINKEDLIST, ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "A RingBuf might work."); + "a RingBuf might work"); return; } } diff --git a/src/unicode.rs b/src/unicode.rs index 1854d5be7ff..af48c9b99ad 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -41,6 +41,6 @@ fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) { lo: span.lo + BytePos(index as u32), hi: span.lo + BytePos(index as u32), expn_id: span.expn_id, - }, "Zero-width space detected. Consider using \\u{200B}") + }, "zero-width space detected. Consider using `\\u{200B}`.") }); } diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs index 42bb0fca6dc..ca7a0d5c07b 100755 --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -3,7 +3,7 @@ #![deny(inline_always)] -#[inline(always)] //~ERROR You have declared #[inline(always)] on test_attr_lint. +#[inline(always)] //~ERROR you have declared `#[inline(always)]` on `test_attr_lint`. fn test_attr_lint() { assert!(true) } diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs index 7d80dd86d22..58e780f190c 100755 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -3,7 +3,7 @@ #![plugin(clippy)] #![deny(clippy)] -pub fn test(foo: Box<Vec<bool>>) { //~ ERROR You seem to be trying to use Box<Vec<T>> +pub fn test(foo: Box<Vec<bool>>) { //~ ERROR you seem to be trying to use `Box<Vec<T>>` println!("{:?}", foo.get(0)) } diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index 280744b5b45..cc63e895f1c 100755 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -5,13 +5,13 @@ fn main() { let x = "hello"; let y = "world"; - if x == "hello" { //~ERROR This if statement can be collapsed + if x == "hello" { //~ERROR this if statement can be collapsed if y == "world" { println!("Hello world!"); } } - if x == "hello" || x == "world" { //~ERROR This if statement can be collapsed + if x == "hello" || x == "world" { //~ERROR this if statement can be collapsed if y == "world" || y == "hello" { println!("Hello world!"); } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs old mode 100644 new mode 100755 index 8ca88eecbd2..9e48ec1c3a5 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -5,11 +5,11 @@ fn main() { let a = |a, b| foo(a, b); - //~^ ERROR Redundant closure found, consider using `foo` in its place + //~^ ERROR redundant closure found. Consider using `foo` in its place let c = |a, b| {1+2; foo}(a, b); - //~^ ERROR Redundant closure found, consider using `{ 1 + 2; foo }` in its place + //~^ ERROR redundant closure found. Consider using `{ 1 + 2; foo }` in its place let d = |a, b| foo((|c, d| foo2(c,d))(a,b), b); - //~^ ERROR Redundant closure found, consider using `foo2` in its place + //~^ ERROR redundant closure found. Consider using `foo2` in its place } fn foo(_: u8, _: u8) { @@ -18,4 +18,4 @@ fn foo(_: u8, _: u8) { fn foo2(_: u8, _: u8) -> u8 { 1u8 -} \ No newline at end of file +} diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 48a10042658..3785a518e2b 100755 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -5,14 +5,14 @@ struct One; #[deny(len_without_is_empty)] impl One { - fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' + fn len(self: &Self) -> isize { //~ERROR item `One` has a `.len(_: &Self)` 1 } } #[deny(len_without_is_empty)] trait TraitsToo { - fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: + fn len(self: &Self) -> isize; //~ERROR trait `TraitsToo` has a `.len(_: } impl TraitsToo for One { @@ -56,7 +56,7 @@ struct HasWrongIsEmpty; #[deny(len_without_is_empty)] impl HasWrongIsEmpty { - fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' + fn len(self: &Self) -> isize { //~ERROR item `HasWrongIsEmpty` has a `.len(_: &Self)` 1 } @@ -69,7 +69,7 @@ impl HasWrongIsEmpty { #[deny(len_zero)] fn main() { let x = [1, 2]; - if x.len() == 0 { //~ERROR Consider replacing the len comparison + if x.len() == 0 { //~ERROR consider replacing the len comparison println!("This should not happen!"); } @@ -84,13 +84,13 @@ fn main() { } let hie = HasIsEmpty; - if hie.len() == 0 { //~ERROR Consider replacing the len comparison + if hie.len() == 0 { //~ERROR consider replacing the len comparison println!("Or this!"); } assert!(!hie.is_empty()); let wie : &WithIsEmpty = &Wither; - if wie.len() == 0 { //~ERROR Consider replacing the len comparison + if wie.len() == 0 { //~ERROR consider replacing the len comparison println!("Or this!"); } assert!(!wie.is_empty()); diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs index 47b8b18a5ec..01bfe744713 100755 --- a/tests/compile-fail/match_if_let.rs +++ b/tests/compile-fail/match_if_let.rs @@ -5,8 +5,8 @@ fn main(){ let x = Some(1u8); - match x { //~ ERROR You seem to be trying to use match - //~^ HELP Try + match x { //~ ERROR you seem to be trying to use match + //~^ HELP try Some(y) => { println!("{:?}", y); } @@ -18,8 +18,8 @@ fn main(){ None => () } let z = (1u8,1u8); - match z { //~ ERROR You seem to be trying to use match - //~^ HELP Try + match z { //~ ERROR you seem to be trying to use match + //~^ HELP try (2...3, 7...9) => println!("{:?}", z), _ => {} } diff --git a/tests/compile-fail/modulo_one.rs b/tests/compile-fail/modulo_one.rs old mode 100644 new mode 100755 index 26c7de855e5..1301b4e499c --- a/tests/compile-fail/modulo_one.rs +++ b/tests/compile-fail/modulo_one.rs @@ -3,6 +3,6 @@ #![deny(modulo_one)] fn main() { - 10 % 1; //~ERROR Any number modulo 1 will be 0 + 10 % 1; //~ERROR any number modulo 1 will be 0 10 % 2; } diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs index 7ba291b1439..d56ea735a1d 100755 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -3,7 +3,7 @@ #[deny(ptr_arg)] #[allow(unused)] -fn do_vec(x: &Vec<i64>) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' +fn do_vec(x: &Vec<i64>) { //~ERROR: writing `&Vec<_>` instead of `&[_]` //Nothing here } diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs index a121b985f09..60edf2577e7 100755 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -4,13 +4,13 @@ #[deny(zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); - //~^ ERROR Zero-width space detected. Consider using \u{200B} - //~^^ ERROR Zero-width space detected. Consider using \u{200B} + //~^ ERROR zero-width space detected. Consider using `\u{200B}` + //~^^ ERROR zero-width space detected. Consider using `\u{200B}` } //#[deny(unicode_canon)] fn canon() { - print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à + print!("̀ah?"); //not yet ~ERROR non-canonical unicode sequence detected. Consider using à } //#[deny(ascii_only)] -- cgit 1.4.1-3-g733a5 From b831bd1d1d16c2733b2c26196163f68c74f3c271 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 10:53:14 +0200 Subject: len_zero: display full suggested expr in message --- src/len_zero.rs | 14 +++++++------- tests/compile-fail/len_zero.rs | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index dea713180f5..298522ed24c 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -9,7 +9,7 @@ use rustc::middle::ty::{self, TypeVariants, TypeAndMut, MethodTraitItemId, ImplO use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; use syntax::ast::*; -use utils::{span_lint, walk_ptrs_ty}; +use utils::{span_lint, walk_ptrs_ty, snippet}; declare_lint!(pub LEN_ZERO, Warn, "Warn when .is_empty() could be used instead of checking .len()"); @@ -92,24 +92,24 @@ fn is_self_sig(sig: &MethodSig) -> bool { false } else { sig.decl.inputs.len() == 1 } } -fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { +fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => - check_len_zero(cx, span, method, args, lit, empty), + check_len_zero(cx, span, method, args, lit, op), (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => - check_len_zero(cx, span, method, args, lit, empty), + check_len_zero(cx, span, method, args, lit, op), _ => () } } fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, - args: &[P<Expr>], lit: &Lit, empty: &str) { + args: &[P<Expr>], lit: &Lit, op: &str) { if let &Spanned{node: LitInt(0, _), ..} = lit { if method.node.name == "len" && args.len() == 1 && has_is_empty(cx, &*args[0]) { span_lint(cx, LEN_ZERO, span, &format!( - "consider replacing the len comparison with `{}_.is_empty()`", - empty)) + "consider replacing the len comparison with `{}{}.is_empty()`", + op, snippet(cx, args[0].span, "_"))) } } } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 3785a518e2b..626e5557fb6 100755 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -87,6 +87,12 @@ fn main() { if hie.len() == 0 { //~ERROR consider replacing the len comparison println!("Or this!"); } + if hie.len() != 0 { //~ERROR consider replacing the len comparison + println!("Or this!"); + } + if hie.len() > 0 { //~ERROR consider replacing the len comparison + println!("Or this!"); + } assert!(!hie.is_empty()); let wie : &WithIsEmpty = &Wither; -- cgit 1.4.1-3-g733a5 From 7b3299e0094cdf407a3b745894a3949383c700f3 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 11:00:08 +0200 Subject: collapsible_if: do not show Debug display of expression Instead, pretty-print the inner block and use the same style as for the "single match => if let" lint. --- src/collapsible_if.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index f1c82f3eef8..c30acc02a4e 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -18,8 +18,8 @@ use rustc::middle::def::*; use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned, ExpnInfo}; -use syntax::print::pprust::expr_to_string; -use utils::{in_macro, span_lint}; +use syntax::print::pprust::{block_to_string, expr_to_string}; +use utils::{in_macro, span_help_and_lint}; declare_lint! { pub COLLAPSIBLE_IF, @@ -45,11 +45,13 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if in_macro(cx, info) { return; } if let ExprIf(ref check, ref then, None) = e.node { - if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = + if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), ..}) = single_stmt_of_block(then) { - span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( - "this if statement can be collapsed. Try: `if {} && {}`\n{:?}", - check_to_string(check), check_to_string(check_inner), e)); + span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, + "this if statement can be collapsed", + &format!("try\nif {} && {} {}", + check_to_string(check), check_to_string(check_inner), + block_to_string(&*content))); } } } -- cgit 1.4.1-3-g733a5 From ca3b4330f1c033033ea876a1074168071239f81d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 15:19:57 +0530 Subject: Use snippet, pprust methods expand AST --- src/collapsible_if.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index c30acc02a4e..0350db8163a 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -18,8 +18,7 @@ use rustc::middle::def::*; use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned, ExpnInfo}; -use syntax::print::pprust::{block_to_string, expr_to_string}; -use utils::{in_macro, span_help_and_lint}; +use utils::{in_macro, span_help_and_lint, snippet}; declare_lint! { pub COLLAPSIBLE_IF, @@ -50,8 +49,8 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", &format!("try\nif {} && {} {}", - check_to_string(check), check_to_string(check_inner), - block_to_string(&*content))); + check_to_string(cx, check), check_to_string(cx, check_inner), + snippet(cx, content.span, ".."))); } } } @@ -63,11 +62,11 @@ fn requires_brackets(e: &Expr) -> bool { } } -fn check_to_string(e: &Expr) -> String { +fn check_to_string(cx: &Context, e: &Expr) -> String { if requires_brackets(e) { - format!("({})", expr_to_string(e)) + format!("({})", snippet(cx, e.span, "..")) } else { - format!("{}", expr_to_string(e)) + format!("{}", snippet(cx, e.span, "..")) } } -- cgit 1.4.1-3-g733a5 From 8bcd01ff47a24253eccbd722d1566537a5576e52 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 15:20:18 +0530 Subject: Bump to 0.0.11 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f5c76132f8b..8433ead92bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.10" +version = "0.0.11" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>" -- cgit 1.4.1-3-g733a5 From e8fed074cfd8623dfe070f86f0cc3040ac33b9b4 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 11:31:09 +0200 Subject: new lint: warn if let-binding has unit value (fixes #74) --- src/lib.rs | 2 ++ src/types.rs | 36 ++++++++++++++++++++++++++++++++++-- tests/compile-fail/let_unit.rs | 13 +++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100755 tests/compile-fail/let_unit.rs diff --git a/src/lib.rs b/src/lib.rs index fef678f668d..27302b51bbd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box strings::StringAdd as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); + reg.register_lint_pass(box types::LetPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, misc::STR_TO_STRING, @@ -83,5 +84,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + types::LET_UNIT_VALUE, ]); } diff --git a/src/types.rs b/src/types.rs index b03829660dc..4980046e01b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,10 +1,11 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; +use rustc::middle::ty; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use syntax::codemap::Span; +use syntax::codemap::{ExpnInfo, Span}; -use utils::{span_lint, span_help_and_lint}; +use utils::{in_macro, snippet, span_lint, span_help_and_lint}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -75,3 +76,34 @@ impl LintPass for TypePass { } } } + +#[allow(missing_copy_implementations)] +pub struct LetPass; + +declare_lint!(pub LET_UNIT_VALUE, Warn, + "Warn on let-binding a value of unit type"); + + +fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { + if in_macro(cx, info) { return; } + if let DeclLocal(ref local) = decl.node { + let bindtype = &cx.tcx.pat_ty(&*local.pat).sty; + if *bindtype == ty::TyTuple(vec![]) { + span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( + "this let-binding has unit value. Consider omitting `let {} =`.", + snippet(cx, local.pat.span, ".."))); + } + } +} + +impl LintPass for LetPass { + fn get_lints(&self) -> LintArray { + lint_array!(LET_UNIT_VALUE) + } + + fn check_decl(&mut self, cx: &Context, decl: &Decl) { + cx.sess().codemap().with_expn_info( + decl.span.expn_id, + |info| check_let_unit(cx, decl, info)); + } +} diff --git a/tests/compile-fail/let_unit.rs b/tests/compile-fail/let_unit.rs new file mode 100755 index 00000000000..e8620f862a2 --- /dev/null +++ b/tests/compile-fail/let_unit.rs @@ -0,0 +1,13 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(let_unit_value)] + +fn main() { + let _x = println!("x"); //~ERROR this let-binding has unit value + let _y = 1; // this is fine + let _z = ((), 1); // this as well + if true { + let _a = (); //~ERROR + } +} -- cgit 1.4.1-3-g733a5 From a7527adf0855002dcbd1cb12309d4f7fbfd93e16 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 13:49:28 +0200 Subject: First (incomplete) const folding --- src/const.rs | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/const.rs diff --git a/src/const.rs b/src/const.rs new file mode 100644 index 00000000000..924a47f2e5a --- /dev/null +++ b/src/const.rs @@ -0,0 +1,131 @@ +use rustc::lint::Context; +use rustc::middle::const_eval::lookup_const_by_id; +use syntax::ast::*; +use syntax::ptr::P; + +/// a Lit_-like enum to fold constant `Expr`s into +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum Constant { + ConstantStr(&'static str, StrStyle), + ConstantBinary(Rc<Vec<u8>>), + ConstantByte(u8), + ConstantChar(char), + ConstantInt(u64, LitIntType), + ConstantFloat(Cow<'static, str>, FloatTy), + ConstantFloatUnsuffixed(Cow<'static, str>), + ConstantBool(bool), + ConstantVec(Vec<Constant>), + ConstantTuple(Vec<Constant>), +} + +/// simple constant folding +pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { + match e { + &ExprParen(ref inner) => constant(cx, inner), + &ExprPath(_, _) => fetch_path(cx, e), + &ExprBlock(ref block) => constant_block(cx, inner), + &ExprIf(ref cond, ref then, ref otherwise) => + match constant(cx, cond) { + Some(LitBool(true)) => constant(cx, then), + Some(LitBool(false)) => constant(cx, otherwise), + _ => None, + }, + &ExprLit(ref lit) => Some(lit_to_constant(lit)), + &ExprVec(ref vec) => constant_vec(cx, vec), + &ExprTup(ref tup) => constant_tup(cx, tup), + &ExprUnary(op, ref operand) => constant(cx, operand).and_then( + |o| match op { + UnNot => + if let ConstantBool(b) = o { + Some(ConstantBool(!b)) + } else { None }, + UnNeg => + match o { + &ConstantInt(value, ty) => + Some(ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => + UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + })), + &LitFloat(ref is, ref ty) => + Some(ConstantFloat(neg_float_str(is), ty)), + &LitFloatUnsuffixed(ref is) => + Some(ConstantFloatUnsuffixed(neg_float_str(is))), + _ => None, + }, + UnUniq | UnDeref => o, + }), + //TODO: add other expressions + _ => None, + } +} + +fn lit_to_constant(lit: &Lit_) -> Constant { + match lit { + &LitStr(ref is, style) => ConstantStr(&*is, style), + &LitBinary(ref blob) => ConstantBinary(blob.clone()), + &LitByte(b) => ConstantByte(b), + &LitChar(c) => ConstantChar(c), + &LitInt(value, ty) => ConstantInt(value, ty), + &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty), + &LitFloatUnsuffixed(InternedString) => + ConstantFloatUnsuffixed(Cow::Borrowed(&*is)), + &LitBool(b) => ConstantBool(b), + } +} + +/// create `Some(ConstantVec(..))` of all constants, unless there is any +/// non-constant part +fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { + Vec<Constant> parts = Vec::new(); + for opt_part in vec { + match constant(cx, opt_part) { + Some(ref p) => parts.push(p), + None => { return None; }, + } + } + Some(ConstantVec(parts)) +} + +fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> { + Vec<Constant> parts = Vec::new(); + for opt_part in vec { + match constant(cx, opt_part) { + Some(ref p) => parts.push(p), + None => { return None; }, + } + } + Some(ConstantTuple(parts)) +} + +/// lookup a possibly constant expression from a ExprPath +fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { + if let Some(&PathResolution { base_def: DefConst(id), ..}) = + cx.tcx.def_map.borrow().get(&e.id) { + lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l)) + } else { None } +} + +/// A block can only yield a constant if it only has one constant expression +fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { + if block.stmts.is_empty() { + block.expr.map(|b| constant(cx, b)) + } else { None } +} + +fn neg_sign(s: Sign) -> Sign { + match s: + Sign::Plus => Sign::Minus, + Sign::Minus => Sign::Plus, + } +} + +fn neg_float_str(s: &InternedString) -> Cow<'static, str> { + if s.startsWith('-') { + Cow::Borrowed(s[1..]) + } else { + Cow::Owned(format!("-{}", &*s)) + } +} -- cgit 1.4.1-3-g733a5 From 225969e8a3b8025dac6d577f6b23af85485be7d0 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 13:58:55 +0200 Subject: methods: move misc.StrToStringPass to MethodsPass --- src/lib.rs | 4 ++-- src/methods.rs | 12 ++++++++++-- src/misc.rs | 30 ------------------------------ 3 files changed, 12 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fef678f668d..7b47edaa496 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ pub mod returns; pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); - reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box misc::CmpNan as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); @@ -61,7 +60,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, - misc::SINGLE_MATCH, misc::STR_TO_STRING, + misc::SINGLE_MATCH, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, @@ -83,5 +82,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + methods::STR_TO_STRING, ]); } diff --git a/src/methods.rs b/src/methods.rs index 3d9aa8c6ffc..f02e0664092 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -11,16 +11,19 @@ declare_lint!(pub OPTION_UNWRAP_USED, Warn, "Warn on using unwrap() on an Option value"); declare_lint!(pub RESULT_UNWRAP_USED, Allow, "Warn on using unwrap() on a Result value"); +declare_lint!(pub STR_TO_STRING, Warn, + "Warn when a String could use to_owned() instead of to_string()"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED) + lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { + let ref obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty; if ident.node.name == "unwrap" { - if let ty::TyEnum(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { + if let ty::TyEnum(did, _) = *obj_ty { if match_def_path(cx, did.did, &["core", "option", "Option"]) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ @@ -34,6 +37,11 @@ impl LintPass for MethodsPass { } } } + else if ident.node.name == "to_string" { + if let ty::TyStr = *obj_ty { + span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); + } + } } } } diff --git a/src/misc.rs b/src/misc.rs index fa1847aad9a..d5e1efe2cc3 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -59,36 +59,6 @@ impl LintPass for MiscPass { } -declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use to_owned() instead of to_string()"); - -#[allow(missing_copy_implementations)] -pub struct StrToStringPass; - -impl LintPass for StrToStringPass { - fn get_lints(&self) -> LintArray { - lint_array!(STR_TO_STRING) - } - - fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { - match expr.node { - ast::ExprMethodCall(ref method, _, ref args) - if method.node.name == "to_string" - && is_str(cx, &*args[0]) => { - span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); - }, - _ => () - } - - fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { - ty::TyStr => true, - _ => false - } - } - } -} - - declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); #[allow(missing_copy_implementations)] -- cgit 1.4.1-3-g733a5 From fc6dfafc306568def3b58a6a91fe56289b53242f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 14:02:13 +0200 Subject: fixed if-condition match --- src/const.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/const.rs b/src/const.rs index 924a47f2e5a..a353de218f4 100644 --- a/src/const.rs +++ b/src/const.rs @@ -26,8 +26,8 @@ pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { &ExprBlock(ref block) => constant_block(cx, inner), &ExprIf(ref cond, ref then, ref otherwise) => match constant(cx, cond) { - Some(LitBool(true)) => constant(cx, then), - Some(LitBool(false)) => constant(cx, otherwise), + Some(ConstantBool(true)) => constant(cx, then), + Some(ConstantBool(false)) => constant(cx, otherwise), _ => None, }, &ExprLit(ref lit) => Some(lit_to_constant(lit)), -- cgit 1.4.1-3-g733a5 From 2d55381a9698694fe74438ff7ab28f9f99a45ecd Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 15:50:56 +0200 Subject: added string_add lint and fixed string_add_assign + test --- README.md | 1 + src/lib.rs | 1 + src/strings.rs | 47 +++++++++++++++++++++++++++++++++++++++---- tests/compile-fail/strings.rs | 13 ++++++++---- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0a947e12ecf..4644bac94cd 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Lints included in this crate: - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. + - `string_add`: Matches `x + ..` where `x` is a `String` and where `string_add_assign` doesn't warn. Allowed by default. - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. - `let_and_return`: Warns on doing `let x = expr; x` at the end of a function. - `option_unwrap_used`: Warns when `Option.unwrap()` is used, and suggests `.expect()`. diff --git a/src/lib.rs b/src/lib.rs index 7b47edaa496..f2872a17b56 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); + reg.register_lint_pass(box strings::StringAddAssign as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); diff --git a/src/strings.rs b/src/strings.rs index 97016f36268..60ea23556ac 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -9,7 +9,7 @@ use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use eq_op::is_exp_equal; use types::match_ty_unwrap; -use utils::{match_def_path, span_lint, walk_ptrs_ty}; +use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, @@ -17,10 +17,48 @@ declare_lint! { "Warn on `x = x + ..` where x is a `String`" } -#[derive(Copy,Clone)] +declare_lint! { + pub STRING_ADD, + Allow, + "Warn on `x + ..` where x is a `String`" +} + +#[derive(Copy, Clone)] pub struct StringAdd; impl LintPass for StringAdd { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_ADD) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { + if is_string(cx, left) { + if let Allow = cx.current_level(STRING_ADD_ASSIGN) { + // the string_add_assign is allow, so no duplicates + } else { + let parent = get_parent_expr(cx, e); + if let Some(ref p) = parent { + if let &ExprAssign(ref target, _) = &p.node { + // avoid duplicate matches + if is_exp_equal(target, left) { return; } + } + } + } + //TODO check for duplicates + span_lint(cx, STRING_ADD, e.span, + "you add something to a string. \ + Consider using `String::push_str()` instead.") + } + } + } +} + + +#[derive(Copy, Clone)] +pub struct StringAddAssign; + +impl LintPass for StringAddAssign { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD_ASSIGN) } @@ -37,8 +75,9 @@ impl LintPass for StringAdd { } fn is_string(cx: &Context, e: &Expr) -> bool { - if let TyStruct(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(e)).sty { - match_def_path(cx, did.did, &["std", "string", "String"]) + let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + if let TyStruct(did, _) = ty.sty { + match_def_path(cx, did.did, &["collections", "string", "String"]) } else { false } } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 4b6f0bc884f..e898a087d08 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -2,11 +2,16 @@ #![plugin(clippy)] #![deny(string_add_assign)] - +#![deny(string_add)] fn main() { - let x = "".to_owned(); + let mut x = "".to_owned(); - for i in (1..3) { - x = x + "."; //~ERROR + for _ in (1..3) { + x = x + "."; //~ERROR you assign the result of adding something to this string. } + + let y = "".to_owned(); + let z = y + "..."; //~ERROR you add something to a string. + + assert_eq!(&x, &z); } -- cgit 1.4.1-3-g733a5 From f0182ca6c809279843784d9669159157eedd2954 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 15:57:50 +0200 Subject: fixed formatting --- src/strings.rs | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index 60ea23556ac..47af63e6dea 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -18,9 +18,9 @@ declare_lint! { } declare_lint! { - pub STRING_ADD, - Allow, - "Warn on `x + ..` where x is a `String`" + pub STRING_ADD, + Allow, + "Warn on `x + ..` where x is a `String`" } #[derive(Copy, Clone)] @@ -32,26 +32,26 @@ impl LintPass for StringAdd { } fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { - if is_string(cx, left) { - if let Allow = cx.current_level(STRING_ADD_ASSIGN) { - // the string_add_assign is allow, so no duplicates - } else { - let parent = get_parent_expr(cx, e); - if let Some(ref p) = parent { - if let &ExprAssign(ref target, _) = &p.node { - // avoid duplicate matches - if is_exp_equal(target, left) { return; } - } - } - } - //TODO check for duplicates - span_lint(cx, STRING_ADD, e.span, - "you add something to a string. \ - Consider using `String::push_str()` instead.") - } - } - } + if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { + if is_string(cx, left) { + if let Allow = cx.current_level(STRING_ADD_ASSIGN) { + // the string_add_assign is allow, so no duplicates + } else { + let parent = get_parent_expr(cx, e); + if let Some(ref p) = parent { + if let &ExprAssign(ref target, _) = &p.node { + // avoid duplicate matches + if is_exp_equal(target, left) { return; } + } + } + } + //TODO check for duplicates + span_lint(cx, STRING_ADD, e.span, + "you add something to a string. \ + Consider using `String::push_str()` instead.") + } + } + } } @@ -75,7 +75,7 @@ impl LintPass for StringAddAssign { } fn is_string(cx: &Context, e: &Expr) -> bool { - let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); if let TyStruct(did, _) = ty.sty { match_def_path(cx, did.did, &["collections", "string", "String"]) } else { false } -- cgit 1.4.1-3-g733a5 From e6e036ec20d2646c5682e4a7e18039b8925ce575 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 16:42:42 +0200 Subject: pulled strings passes together, added more tests --- src/lib.rs | 1 - src/strings.rs | 18 ++--------------- tests/compile-fail/strings.rs | 45 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f2872a17b56..7b47edaa496 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,6 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); - reg.register_lint_pass(box strings::StringAddAssign as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); diff --git a/src/strings.rs b/src/strings.rs index 47af63e6dea..aa0e8499f3e 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -28,7 +28,7 @@ pub struct StringAdd; impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD) + lint_array!(STRING_ADD, STRING_ADD_ASSIGN) } fn check_expr(&mut self, cx: &Context, e: &Expr) { @@ -50,21 +50,7 @@ impl LintPass for StringAdd { "you add something to a string. \ Consider using `String::push_str()` instead.") } - } - } -} - - -#[derive(Copy, Clone)] -pub struct StringAddAssign; - -impl LintPass for StringAddAssign { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD_ASSIGN) - } - - fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprAssign(ref target, ref src) = &e.node { + } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assign the result of adding something to this string. \ diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index e898a087d08..02ebca2fe07 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -1,9 +1,37 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(string_add_assign)] -#![deny(string_add)] -fn main() { +#[deny(string_add)] +#[allow(string_add_assign)] +fn add_only() { // ignores assignment distinction + let mut x = "".to_owned(); + + for _ in (1..3) { + x = x + "."; //~ERROR you add something to a string. + } + + let y = "".to_owned(); + let z = y + "..."; //~ERROR you add something to a string. + + assert_eq!(&x, &z); +} + +#[deny(string_add_assign)] +fn add_assign_only() { + let mut x = "".to_owned(); + + for _ in (1..3) { + x = x + "."; //~ERROR you assign the result of adding something to this string. + } + + let y = "".to_owned(); + let z = y + "..."; + + assert_eq!(&x, &z); +} + +#[deny(string_add, string_add_assign)] +fn both() { let mut x = "".to_owned(); for _ in (1..3) { @@ -15,3 +43,14 @@ fn main() { assert_eq!(&x, &z); } + +fn main() { + add_only(); + add_assign_only(); + both(); + + // the add is only caught for String + let mut x = 1; + x = x + 1; + assert_eq!(2, x); +} -- cgit 1.4.1-3-g733a5 From 801f01d0012d48873050c27cf9876b3fc56509c5 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 16:50:43 +0200 Subject: added `string_add` to `clippy` lint group --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 7b47edaa496..46cc85e8559 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, unicode::ZERO_WIDTH_SPACE, strings::STRING_ADD_ASSIGN, + strings::STRING_ADD, returns::NEEDLESS_RETURN, misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, -- cgit 1.4.1-3-g733a5 From 4074c1f968d5bd37b3dec36bc21cbf656de65907 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 17:02:49 +0200 Subject: methods: lint against String.to_string (fixes #100) --- src/lib.rs | 1 + src/methods.rs | 10 +++++++++- tests/compile-fail/methods.rs | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 7b47edaa496..3299debbe0d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,5 +83,6 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::STR_TO_STRING, + methods::STRING_TO_STRING, ]); } diff --git a/src/methods.rs b/src/methods.rs index f02e0664092..a5b12e52bdf 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -13,10 +13,12 @@ declare_lint!(pub RESULT_UNWRAP_USED, Allow, "Warn on using unwrap() on a Result value"); declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use to_owned() instead of to_string()"); +declare_lint!(pub STRING_TO_STRING, Warn, + "Warn when calling String.to_string()"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING) + lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -41,6 +43,12 @@ impl LintPass for MethodsPass { if let ty::TyStr = *obj_ty { span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); } + else if let ty::TyStruct(did, _) = *obj_ty { + if match_def_path(cx, did.did, &["collections", "string", "String"]) { + span_lint(cx, STRING_TO_STRING, expr.span, + "`String.to_string()` is a no-op") + } + } } } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index e989dffe5a7..facf0378392 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -2,10 +2,14 @@ #![plugin(clippy)] #[deny(option_unwrap_used, result_unwrap_used)] +#[deny(str_to_string, string_to_string)] fn main() { let opt = Some(0); let _ = opt.unwrap(); //~ERROR let res: Result<i32, ()> = Ok(0); let _ = res.unwrap(); //~ERROR + + let string = "str".to_string(); //~ERROR + let _again = string.to_string(); //~ERROR } -- cgit 1.4.1-3-g733a5 From 79bf774e9b552862041b8dc2a49ac5ddcc91bffa Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 21:25:26 +0530 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a947e12ecf..b61f3561302 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ You can add options to `allow`/`warn`/`deny`: - only some lints (`#![deny(single_match, box_vec)]`, etc) - `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc -*`deny` produces error instead of warnings* +Note: `deny` produces errors instead of warnings To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` in your code, you can use: -- cgit 1.4.1-3-g733a5 From 3044d3d6333f92a9958b64420d9893403d4aea97 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 20:36:10 +0200 Subject: unicode: add lint against non-ascii chars in literals (Allow by default), #85 --- src/lib.rs | 1 + src/unicode.rs | 28 +++++++++++++--------------- tests/compile-fail/unicode.rs | 8 ++++---- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a7ed0320da8..7d7eff35545 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ pub fn plugin_registrar(reg: &mut Registry) { attrs::INLINE_ALWAYS, collapsible_if::COLLAPSIBLE_IF, unicode::ZERO_WIDTH_SPACE, + unicode::NON_ASCII_LITERAL, strings::STRING_ADD_ASSIGN, returns::NEEDLESS_RETURN, misc::MODULO_ONE, diff --git a/src/unicode.rs b/src/unicode.rs index af48c9b99ad..ca6abaf01b4 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -4,13 +4,14 @@ use syntax::codemap::{BytePos, Span}; use utils::span_lint; declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } +declare_lint!{ pub NON_ASCII_LITERAL, Allow, "Lint literal non-ASCII chars in literals" } #[derive(Copy, Clone)] pub struct Unicode; impl LintPass for Unicode { fn get_lints(&self) -> LintArray { - lint_array!(ZERO_WIDTH_SPACE) + lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -23,24 +24,21 @@ impl LintPass for Unicode { } fn check_str(cx: &Context, string: &str, span: Span) { - let mut start: Option<usize> = None; for (i, c) in string.char_indices() { if c == '\u{200B}' { - if start.is_none() { start = Some(i); } - } else { - lint_zero_width(cx, span, start); - start = None; + str_pos_lint(cx, ZERO_WIDTH_SPACE, span, i, + "zero-width space detected. Consider using `\\u{200B}`."); + } + if c as u32 > 0x7F { + str_pos_lint(cx, NON_ASCII_LITERAL, span, i, &format!( + "literal non-ASCII character detected. Consider using `\\u{{{:X}}}`.", c as u32)); } } - lint_zero_width(cx, span, start); } -fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) { - start.map(|index| { - span_lint(cx, ZERO_WIDTH_SPACE, Span { - lo: span.lo + BytePos(index as u32), - hi: span.lo + BytePos(index as u32), - expn_id: span.expn_id, - }, "zero-width space detected. Consider using `\\u{200B}`.") - }); +fn str_pos_lint(cx: &Context, lint: &'static Lint, span: Span, index: usize, msg: &str) { + span_lint(cx, lint, Span { lo: span.lo + BytePos((1 + index) as u32), + hi: span.lo + BytePos((1 + index) as u32), + expn_id: span.expn_id }, msg); + } diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs index 60edf2577e7..e4730f60de8 100755 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -4,8 +4,8 @@ #[deny(zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); - //~^ ERROR zero-width space detected. Consider using `\u{200B}` - //~^^ ERROR zero-width space detected. Consider using `\u{200B}` + //~^ ERROR zero-width space detected. Consider using `\u{200B}` + //~^^ ERROR zero-width space detected. Consider using `\u{200B}` } //#[deny(unicode_canon)] @@ -13,9 +13,9 @@ fn canon() { print!("̀ah?"); //not yet ~ERROR non-canonical unicode sequence detected. Consider using à } -//#[deny(ascii_only)] +#[deny(non_ascii_literal)] fn uni() { - println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} + print!("Üben!"); //~ERROR literal non-ASCII character detected. Consider using `\u{DC}` } fn main() { -- cgit 1.4.1-3-g733a5 From 30a6764adb44ac93b389128aa10089546c3c65c1 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 21:17:21 +0200 Subject: grammar --- src/strings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index aa0e8499f3e..33db980c065 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -47,13 +47,13 @@ impl LintPass for StringAdd { } //TODO check for duplicates span_lint(cx, STRING_ADD, e.span, - "you add something to a string. \ + "you added something to a string. \ Consider using `String::push_str()` instead.") } } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, - "you assign the result of adding something to this string. \ + "you assigned the result of adding something to this string. \ Consider using `String::push_str()` instead.") } } -- cgit 1.4.1-3-g733a5 From 1f8c29c6ade779f322adcc6900d2e615a583e59a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 21:39:42 +0200 Subject: fixed error messages in compile-fail test --- tests/compile-fail/strings.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 02ebca2fe07..680ebb73dea 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -7,11 +7,11 @@ fn add_only() { // ignores assignment distinction let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you add something to a string. + x = x + "."; //~ERROR you added something to a string. } let y = "".to_owned(); - let z = y + "..."; //~ERROR you add something to a string. + let z = y + "..."; //~ERROR you added something to a string. assert_eq!(&x, &z); } @@ -21,7 +21,7 @@ fn add_assign_only() { let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you assign the result of adding something to this string. + x = x + "."; //~ERROR you assigned the result of adding something to this string. } let y = "".to_owned(); @@ -35,11 +35,11 @@ fn both() { let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you assign the result of adding something to this string. + x = x + "."; //~ERROR you assigned the result of adding something to this string. } let y = "".to_owned(); - let z = y + "..."; //~ERROR you add something to a string. + let z = y + "..."; //~ERROR you added something to a string. assert_eq!(&x, &z); } -- cgit 1.4.1-3-g733a5 From 4400aaed4363e7955f4d45770c4add7b147c1022 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 21:11:32 +0200 Subject: if_let_chain: allow mixing in normal ifs as well --- src/returns.rs | 19 +++++++++---------- src/utils.rs | 31 ++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/returns.rs b/src/returns.rs index 70af37d5181..be28e14001c 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -69,17 +69,16 @@ impl ReturnPass { // we need both a let-binding stmt and an expr if_let_chain! { [ - Some(stmt) = block.stmts.last(), - StmtDecl(ref decl, _) = stmt.node, - DeclLocal(ref local) = decl.node, - Some(ref initexpr) = local.init, - PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, - Some(ref retexpr) = block.expr, - ExprPath(_, ref path) = retexpr.node + let Some(stmt) = block.stmts.last(), + let StmtDecl(ref decl, _) = stmt.node, + let DeclLocal(ref local) = decl.node, + let Some(ref initexpr) = local.init, + let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, + let Some(ref retexpr) = block.expr, + let ExprPath(_, ref path) = retexpr.node, + match_path(path, &[&*id.name.as_str()]) ], { - if match_path(path, &[&*id.name.as_str()]) { - self.emit_let_lint(cx, retexpr.span, initexpr.span); - } + self.emit_let_lint(cx, retexpr.span, initexpr.span); } } } diff --git a/src/utils.rs b/src/utils.rs index 575d39b0c23..220dc6215fd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -93,9 +93,14 @@ pub fn walk_ptrs_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { } } -/// Produce a nested chain of if-lets from the patterns: +/// Produce a nested chain of if-lets and ifs from the patterns: /// -/// if_let_chain! {[Some(y) = x, Some(z) = y], +/// if_let_chain! { +/// [ +/// Some(y) = x, +/// y.len() == 2, +/// Some(z) = y, +/// ], /// { /// block /// } @@ -104,20 +109,32 @@ pub fn walk_ptrs_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { /// becomes /// /// if let Some(y) = x { -/// if let Some(z) = y { -/// block +/// if y.len() == 2 { +/// if let Some(z) = y { +/// block +/// } /// } /// } #[macro_export] macro_rules! if_let_chain { - ([$pat:pat = $expr:expr, $($p2:pat = $e2:expr),+], $block:block) => { + ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { if let $pat = $expr { - if_let_chain!{ [$($p2 = $e2),+], $block } + if_let_chain!{ [$($tt)+], $block } } }; - ([$pat:pat = $expr:expr], $block:block) => { + ([let $pat:pat = $expr:expr], $block:block) => { if let $pat = $expr { $block } }; + ([$expr:expr, $($tt:tt)+], $block:block) => { + if $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([$expr:expr], $block:block) => { + if $expr { + $block + } + }; } -- cgit 1.4.1-3-g733a5 From f6090909d3e7654b9244fff937d78e3e17b5f3e2 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 21:56:27 +0200 Subject: new lint: using `for i in 0..x { .. vec[i] .. }` instead of iterator (fixes #3) --- src/lib.rs | 3 ++ src/loops.rs | 105 +++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/for_loop.rs | 17 +++++++ 3 files changed, 125 insertions(+) create mode 100644 src/loops.rs create mode 100755 tests/compile-fail/for_loop.rs diff --git a/src/lib.rs b/src/lib.rs index 7d7eff35545..33ce163a326 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub mod unicode; pub mod strings; pub mod methods; pub mod returns; +pub mod loops; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -59,6 +60,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); + reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, @@ -87,5 +89,6 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::STR_TO_STRING, methods::STRING_TO_STRING, types::LET_UNIT_VALUE, + loops::NEEDLESS_RANGE_LOOP, ]); } diff --git a/src/loops.rs b/src/loops.rs new file mode 100644 index 00000000000..83d7ca4eccb --- /dev/null +++ b/src/loops.rs @@ -0,0 +1,105 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::visit::{Visitor, walk_expr}; +use std::collections::HashSet; + +use utils::{span_lint, get_parent_expr}; + +declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, + "Warn about looping over a range of indices if a normal iterator would do" } + +#[derive(Copy, Clone)] +pub struct LoopsPass; + +impl LintPass for LoopsPass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_RANGE_LOOP) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let Some((pat, arg, body)) = recover_for_loop(expr) { + // the var must be a single name + if let PatIdent(_, ref ident, _) = pat.node { + // the iteratee must be a range literal + if let ExprRange(_, _) = arg.node { + let mut visitor = VarVisitor { cx: cx, var: ident.node.name, + indexed: HashSet::new(), nonindex: false }; + walk_expr(&mut visitor, body); + // linting condition: we only indexed one variable + if visitor.indexed.len() == 1 { + let indexed = visitor.indexed.into_iter().next().unwrap(); + if visitor.nonindex { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is used to index `{}`. Consider using \ + `for ({}, item) in {}.iter().enumerate()` or similar iterators.", + ident.node.name.as_str(), indexed.as_str(), + ident.node.name.as_str(), indexed.as_str())); + } else { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is only used to index `{}`. \ + Consider using `for item in &{}` or similar iterators.", + ident.node.name.as_str(), indexed.as_str(), indexed.as_str())); + } + } + } + } + } + } +} + +/// Recover the essential nodes of a desugared for loop: +/// `for pat in arg { body }` becomes `(pat, arg, body)`. +fn recover_for_loop<'a>(expr: &'a Expr) -> Option<(&'a Pat, &'a Expr, &'a Expr)> { + if_let_chain! { + [ + let ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1, + arms.len() == 1 && arms[0].guard.is_none(), + let ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let PatEnum(_, Some(ref somepats)) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&*somepats[0], + &*iterargs[0], + &*innerarms[0].body)); + } + } + None +} + +struct VarVisitor<'v, 't: 'v> { + cx: &'v Context<'v, 't>, // context reference + var: Name, // var name to look for as index + indexed: HashSet<Name>, // indexed variables + nonindex: bool, // has the var been used otherwise? +} + +impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if let ExprPath(None, ref path) = expr.node { + if path.segments.len() == 1 && path.segments[0].identifier.name == self.var { + // we are referencing our variable! now check if it's as an index + if_let_chain! { + [ + let Some(parexpr) = get_parent_expr(self.cx, expr), + let ExprIndex(ref seqexpr, _) = parexpr.node, + let ExprPath(None, ref seqvar) = seqexpr.node, + seqvar.segments.len() == 1 + ], { + self.indexed.insert(seqvar.segments[0].identifier.name); + return; // no need to walk further + } + } + // we are not indexing anything, record that + self.nonindex = true; + return; + } + } + walk_expr(self, expr); + } +} diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs new file mode 100755 index 00000000000..318e6fc8588 --- /dev/null +++ b/tests/compile-fail/for_loop.rs @@ -0,0 +1,17 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(needless_range_loop)] +fn main() { + let vec = vec![1, 2, 3, 4]; + let vec2 = vec![1, 2, 3, 4]; + for i in 0..vec.len() { //~ERROR the loop variable `i` is only used to index `vec`. + println!("{}", vec[i]); + } + for i in 0..vec.len() { //~ERROR the loop variable `i` is used to index `vec`. + println!("{} {}", vec[i], i); + } + for i in 0..vec.len() { // not an error, indexing more than one variable + println!("{} {}", vec[i], vec2[i]); + } +} -- cgit 1.4.1-3-g733a5 From b349f9e88dfd5269af69ef3096dabb71742a9737 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 13:16:09 +0200 Subject: new lint for needless lifetimes (fixes #115) --- src/lib.rs | 3 + src/lifetimes.rs | 126 ++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/lifetimes.rs | 62 ++++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 src/lifetimes.rs create mode 100755 tests/compile-fail/lifetimes.rs diff --git a/src/lib.rs b/src/lib.rs index 7d7eff35545..69a373b21bb 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub mod unicode; pub mod strings; pub mod methods; pub mod returns; +pub mod lifetimes; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -59,6 +60,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); + reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, misc::SINGLE_MATCH, @@ -87,5 +89,6 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::STR_TO_STRING, methods::STRING_TO_STRING, types::LET_UNIT_VALUE, + lifetimes::NEEDLESS_LIFETIMES, ]); } diff --git a/src/lifetimes.rs b/src/lifetimes.rs new file mode 100644 index 00000000000..602eea1ae5e --- /dev/null +++ b/src/lifetimes.rs @@ -0,0 +1,126 @@ +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint}; +use syntax::codemap::Span; +use syntax::visit::{Visitor, FnKind, walk_ty}; +use utils::{in_macro, span_lint}; +use std::collections::HashSet; +use std::iter::FromIterator; + +declare_lint!(pub NEEDLESS_LIFETIMES, Warn, + "Warn on explicit lifetimes when elision rules would apply"); + +#[derive(Copy,Clone)] +pub struct LifetimePass; + +impl LintPass for LifetimePass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_LIFETIMES) + } + + fn check_fn(&mut self, cx: &Context, kind: FnKind, decl: &FnDecl, + _: &Block, span: Span, _: NodeId) { + if cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) { + return; + } + if could_use_elision(kind, decl) { + span_lint(cx, NEEDLESS_LIFETIMES, span, + "explicit lifetimes given where they could be inferred"); + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug)] +enum RefLt { + Unnamed, + Static, + Named(Name), +} +use self::RefLt::*; + +fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { + // There are two scenarios where elision works: + // * no output references, all input references have different LT + // * output references, exactly one input reference with same LT + + let mut input_visitor = RefVisitor(Vec::new()); + let mut output_visitor = RefVisitor(Vec::new()); + + // extract lifetimes of input argument types + for arg in &func.inputs { + walk_ty(&mut input_visitor, &*arg.ty); + } + // extract lifetime of "self" argument for methods + if let FnKind::FkMethod(_, sig, _) = kind { + match sig.explicit_self.node { + SelfRegion(ref lt_opt, _, _) => + input_visitor.visit_opt_lifetime_ref(sig.explicit_self.span, lt_opt), + SelfExplicit(ref ty, _) => + walk_ty(&mut input_visitor, ty), + _ => { } + } + } + // extract lifetimes of output type + if let Return(ref ty) = func.output { + walk_ty(&mut output_visitor, ty); + } + + let input_lts = input_visitor.into_vec(); + let output_lts = output_visitor.into_vec(); + + // no input lifetimes? easy case! + if input_lts.is_empty() { + return false; + } else if output_lts.is_empty() { + // no output lifetimes, check distinctness of input lifetimes + + // only one reference with unnamed lifetime, ok + if input_lts.len() == 1 && input_lts[0] == Unnamed { + return false; + } + // we have no output reference, so we only need all distinct lifetimes + if input_lts.len() == unique_lifetimes(&input_lts) { + return true; + } + } else { + // we have output references, so we need one input reference, + // and all output lifetimes must be the same + if unique_lifetimes(&output_lts) > 1 { + return false; + } + if input_lts.len() == 1 { + match (&input_lts[0], &output_lts[0]) { + (&Named(n1), &Named(n2)) if n1 == n2 => { return true; } + (&Named(_), &Unnamed) => { return true; } + (&Unnamed, &Named(_)) => { return true; } + _ => { } // already elided, different named lifetimes + // or something static going on + } + } + } + false +} + +fn unique_lifetimes(lts: &Vec<RefLt>) -> usize { + let set: HashSet<&RefLt> = HashSet::from_iter(lts.iter()); + set.len() +} + +struct RefVisitor(Vec<RefLt>); + +impl RefVisitor { + fn into_vec(self) -> Vec<RefLt> { self.0 } +} + +impl<'v> Visitor<'v> for RefVisitor { + fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { + if let &Some(ref lt) = lifetime { + if lt.name.as_str() == "'static" { + self.0.push(Static); + } else { + self.0.push(Named(lt.name)); + } + } else { + self.0.push(Unnamed); + } + } +} diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs new file mode 100755 index 00000000000..9f2a3ee99af --- /dev/null +++ b/tests/compile-fail/lifetimes.rs @@ -0,0 +1,62 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(needless_lifetimes)] + +fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~ERROR + +fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } //~ERROR + +fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same lifetime on two params + +fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved + +fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } //~ERROR + +fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { x } // no error, multiple input refs + +fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { x } // no error, multiple input refs + +fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { x } // no error, static involved + +fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { Ok(x) } // no error + +fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // no error, two input refs + +fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } //~ERROR + +struct X { + x: u8, +} + +impl X { + fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } //~ERROR + + fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { &self.x } // no error, multiple input refs + + fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } //~ERROR + + fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params +} + +static STATIC: u8 = 1; + +fn main() { + distinct_lifetimes(&1, &2, 3); + distinct_and_static(&1, &2, &STATIC); + same_lifetime_on_input(&1, &2); + only_static_on_input(&1, &2, &STATIC); + in_and_out(&1, 2); + multiple_in_and_out_1(&1, &2); + multiple_in_and_out_2(&1, &2); + in_static_and_out(&1, &STATIC); + let _ = deep_reference_1(&1, &2); + let _ = deep_reference_2(Ok(&1)); + let _ = deep_reference_3(&1, 2); + + let foo = X { x: 1 }; + foo.self_and_out(); + foo.self_and_in_out(&1); + foo.distinct_self_and_in(&1); + foo.self_and_same_in(&1); +} -- cgit 1.4.1-3-g733a5 From 6603299f3f9f7fccde7dacbfd93e3cedd7e30e75 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 20:13:14 +0200 Subject: lifetimes lint: straighten some code, add a few comments --- src/lifetimes.rs | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 602eea1ae5e..83f6d0eecdb 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -2,7 +2,7 @@ use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use syntax::codemap::Span; use syntax::visit::{Visitor, FnKind, walk_ty}; -use utils::{in_macro, span_lint}; +use utils::{in_external_macro, span_lint}; use std::collections::HashSet; use std::iter::FromIterator; @@ -19,16 +19,17 @@ impl LintPass for LifetimePass { fn check_fn(&mut self, cx: &Context, kind: FnKind, decl: &FnDecl, _: &Block, span: Span, _: NodeId) { - if cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) { + if in_external_macro(cx, span) { return; } if could_use_elision(kind, decl) { span_lint(cx, NEEDLESS_LIFETIMES, span, - "explicit lifetimes given where they could be inferred"); + "explicit lifetimes given in parameter types where they could be elided"); } } } +/// The lifetime of a &-reference. #[derive(PartialEq, Eq, Hash, Debug)] enum RefLt { Unnamed, @@ -42,24 +43,24 @@ fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { // * no output references, all input references have different LT // * output references, exactly one input reference with same LT + // these will collect all the lifetimes for references in arg/return types let mut input_visitor = RefVisitor(Vec::new()); let mut output_visitor = RefVisitor(Vec::new()); - // extract lifetimes of input argument types - for arg in &func.inputs { - walk_ty(&mut input_visitor, &*arg.ty); - } - // extract lifetime of "self" argument for methods + // extract lifetime in "self" argument for methods (there is a "self" argument + // in func.inputs, but its type is TyInfer) if let FnKind::FkMethod(_, sig, _) = kind { match sig.explicit_self.node { - SelfRegion(ref lt_opt, _, _) => - input_visitor.visit_opt_lifetime_ref(sig.explicit_self.span, lt_opt), - SelfExplicit(ref ty, _) => - walk_ty(&mut input_visitor, ty), + SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), + SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), _ => { } } } - // extract lifetimes of output type + // extract lifetimes in input argument types + for arg in &func.inputs { + walk_ty(&mut input_visitor, &*arg.ty); + } + // extract lifetimes in output type if let Return(ref ty) = func.output { walk_ty(&mut output_visitor, ty); } @@ -100,19 +101,16 @@ fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { false } +/// Number of unique lifetimes in the given vector. fn unique_lifetimes(lts: &Vec<RefLt>) -> usize { - let set: HashSet<&RefLt> = HashSet::from_iter(lts.iter()); - set.len() + lts.iter().collect::<HashSet<_>>().len() } +/// A visitor usable for syntax::visit::walk_ty(). struct RefVisitor(Vec<RefLt>); impl RefVisitor { - fn into_vec(self) -> Vec<RefLt> { self.0 } -} - -impl<'v> Visitor<'v> for RefVisitor { - fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { + fn record(&mut self, lifetime: &Option<Lifetime>) { if let &Some(ref lt) = lifetime { if lt.name.as_str() == "'static" { self.0.push(Static); @@ -123,4 +121,14 @@ impl<'v> Visitor<'v> for RefVisitor { self.0.push(Unnamed); } } + + fn into_vec(self) -> Vec<RefLt> { + self.0 + } +} + +impl<'v> Visitor<'v> for RefVisitor { + fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { + self.record(lifetime); + } } -- cgit 1.4.1-3-g733a5 From 2f7693094f5c112174ae5e3aa7e9525bb35ac469 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 06:43:25 +0200 Subject: lifetimes lint: include support for lifetimes as generic params --- src/lifetimes.rs | 9 +++++++++ tests/compile-fail/lifetimes.rs | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 83f6d0eecdb..b510173e753 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -128,7 +128,16 @@ impl RefVisitor { } impl<'v> Visitor<'v> for RefVisitor { + // for lifetimes of references fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { self.record(lifetime); } + + // for lifetimes as parameters of generics + fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + self.record(&Some(*lifetime)); + } + + // for lifetime bounds; the default impl calls visit_lifetime_ref + fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { } } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 9f2a3ee99af..0f0f95ac5f5 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -25,6 +25,12 @@ fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // n fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } //~ERROR +type Ref<'r> = &'r u8; + +fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } + +fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } //~ERROR + struct X { x: u8, } @@ -53,6 +59,8 @@ fn main() { let _ = deep_reference_1(&1, &2); let _ = deep_reference_2(Ok(&1)); let _ = deep_reference_3(&1, 2); + lifetime_param_1(&1, &2); + lifetime_param_2(&1, &2); let foo = X { x: 1 }; foo.self_and_out(); -- cgit 1.4.1-3-g733a5 From 5952a2954376d6086672f5c166a24b87d93ddbb4 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 07:51:24 +0200 Subject: lifetimes test: use explicit message prefix --- tests/compile-fail/lifetimes.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 0f0f95ac5f5..36daa69fb31 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -3,15 +3,18 @@ #![deny(needless_lifetimes)] -fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~ERROR +fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } +//~^ERROR explicit lifetimes given -fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } //~ERROR +fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } +//~^ERROR explicit lifetimes given fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same lifetime on two params fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved -fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } //~ERROR +fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } +//~^ERROR explicit lifetimes given fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { x } // no error, multiple input refs @@ -23,24 +26,28 @@ fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { Ok(x) fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // no error, two input refs -fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } //~ERROR +fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } +//~^ERROR explicit lifetimes given type Ref<'r> = &'r u8; fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } -fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } //~ERROR +fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } +//~^ERROR explicit lifetimes given struct X { x: u8, } impl X { - fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } //~ERROR + fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } + //~^ERROR explicit lifetimes given fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { &self.x } // no error, multiple input refs - fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } //~ERROR + fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } + //~^ERROR explicit lifetimes given fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params } -- cgit 1.4.1-3-g733a5 From 38e8d2bc060607ebf9a37919752e1de15f1794fa Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 12 Aug 2015 13:58:55 +0200 Subject: methods: move misc.StrToStringPass to MethodsPass --- src/lib.rs | 4 ++-- src/methods.rs | 12 ++++++++++-- src/misc.rs | 30 ------------------------------ 3 files changed, 12 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fef678f668d..7b47edaa496 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ pub mod returns; pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); - reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box misc::CmpNan as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); @@ -61,7 +60,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, - misc::SINGLE_MATCH, misc::STR_TO_STRING, + misc::SINGLE_MATCH, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, @@ -83,5 +82,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + methods::STR_TO_STRING, ]); } diff --git a/src/methods.rs b/src/methods.rs index 3d9aa8c6ffc..f02e0664092 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -11,16 +11,19 @@ declare_lint!(pub OPTION_UNWRAP_USED, Warn, "Warn on using unwrap() on an Option value"); declare_lint!(pub RESULT_UNWRAP_USED, Allow, "Warn on using unwrap() on a Result value"); +declare_lint!(pub STR_TO_STRING, Warn, + "Warn when a String could use to_owned() instead of to_string()"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED) + lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { + let ref obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty; if ident.node.name == "unwrap" { - if let ty::TyEnum(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { + if let ty::TyEnum(did, _) = *obj_ty { if match_def_path(cx, did.did, &["core", "option", "Option"]) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ @@ -34,6 +37,11 @@ impl LintPass for MethodsPass { } } } + else if ident.node.name == "to_string" { + if let ty::TyStr = *obj_ty { + span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); + } + } } } } diff --git a/src/misc.rs b/src/misc.rs index fa1847aad9a..d5e1efe2cc3 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -59,36 +59,6 @@ impl LintPass for MiscPass { } -declare_lint!(pub STR_TO_STRING, Warn, "Warn when a String could use to_owned() instead of to_string()"); - -#[allow(missing_copy_implementations)] -pub struct StrToStringPass; - -impl LintPass for StrToStringPass { - fn get_lints(&self) -> LintArray { - lint_array!(STR_TO_STRING) - } - - fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { - match expr.node { - ast::ExprMethodCall(ref method, _, ref args) - if method.node.name == "to_string" - && is_str(cx, &*args[0]) => { - span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); - }, - _ => () - } - - fn is_str(cx: &Context, expr: &ast::Expr) -> bool { - match walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { - ty::TyStr => true, - _ => false - } - } - } -} - - declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); #[allow(missing_copy_implementations)] -- cgit 1.4.1-3-g733a5 From 7aee04878f5228f15d94b04addadfa9fe5ccc307 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 08:12:07 +0200 Subject: tests: use fragment of lint text for error checking (Did not touch strings.rs, which is fixed by @llogiq's PR) --- src/needless_bool.rs | 2 +- tests/compile-fail/approx_const.rs | 46 +++++++++++++++++------------------ tests/compile-fail/bit_masks.rs | 28 ++++++++++----------- tests/compile-fail/cmp_nan.rs | 24 +++++++++--------- tests/compile-fail/eq_op.rs | 32 ++++++++++++------------ tests/compile-fail/float_cmp.rs | 16 ++++++------ tests/compile-fail/identity_op.rs | 20 +++++++-------- tests/compile-fail/let_return.rs | 2 +- tests/compile-fail/let_unit.rs | 2 +- tests/compile-fail/methods.rs | 8 +++--- tests/compile-fail/mut_mut.rs | 16 ++++++------ tests/compile-fail/needless_bool.rs | 8 +++--- tests/compile-fail/needless_return.rs | 14 +++++------ tests/compile-fail/precedence.rs | 14 +++++------ tests/compile-fail/ptr_arg.rs | 4 +-- 15 files changed, 118 insertions(+), 118 deletions(-) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index fcbc287e30f..d97e819077a 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -37,7 +37,7 @@ impl LintPass for NeedlessBool { "you can reduce your if statement to its predicate"); }, (Option::Some(false), Option::Some(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if statement to `!` + your predicate"); }, + "you can reduce your if statement to `!` + its predicate"); }, (Option::Some(false), Option::Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, "your if-then-else expression will always return false"); }, diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index 3eb170b295b..799795becbd 100755 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -4,53 +4,53 @@ #[deny(approx_constant)] #[allow(unused)] fn main() { - let my_e = 2.7182; //~ERROR - let almost_e = 2.718; //~ERROR + let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::E` found + let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::E` found let no_e = 2.71; - let my_1_frac_pi = 0.3183; //~ERROR + let my_1_frac_pi = 0.3183; //~ERROR approximate value of `f{32, 64}::FRAC_1_PI` found let no_1_frac_pi = 0.31; - let my_frac_1_sqrt_2 = 0.70710678; //~ERROR - let almost_frac_1_sqrt_2 = 0.70711; //~ERROR + let my_frac_1_sqrt_2 = 0.70710678; //~ERROR approximate value of `f{32, 64}::FRAC_1_SQRT_2` found + let almost_frac_1_sqrt_2 = 0.70711; //~ERROR approximate value of `f{32, 64}::FRAC_1_SQRT_2` found let my_frac_1_sqrt_2 = 0.707; - let my_frac_2_pi = 0.63661977; //~ERROR + let my_frac_2_pi = 0.63661977; //~ERROR approximate value of `f{32, 64}::FRAC_2_PI` found let no_frac_2_pi = 0.636; - let my_frac_2_sq_pi = 1.128379; //~ERROR + let my_frac_2_sq_pi = 1.128379; //~ERROR approximate value of `f{32, 64}::FRAC_2_SQRT_PI` found let no_frac_2_sq_pi = 1.128; - let my_frac_2_pi = 1.57079632679; //~ERROR - let no_frac_2_pi = 1.5705; + let my_frac_pi_2 = 1.57079632679; //~ERROR approximate value of `f{32, 64}::FRAC_PI_2` found + let no_frac_pi_2 = 1.5705; - let my_frac_3_pi = 1.04719755119; //~ERROR - let no_frac_3_pi = 1.047; + let my_frac_pi_3 = 1.04719755119; //~ERROR approximate value of `f{32, 64}::FRAC_PI_3` found + let no_frac_pi_3 = 1.047; - let my_frac_4_pi = 0.785398163397; //~ERROR - let no_frac_4_pi = 0.785; + let my_frac_pi_4 = 0.785398163397; //~ERROR approximate value of `f{32, 64}::FRAC_PI_4` found + let no_frac_pi_4 = 0.785; - let my_frac_6_pi = 0.523598775598; //~ERROR - let no_frac_6_pi = 0.523; + let my_frac_pi_6 = 0.523598775598; //~ERROR approximate value of `f{32, 64}::FRAC_PI_6` found + let no_frac_pi_6 = 0.523; - let my_frac_8_pi = 0.3926990816987; //~ERROR - let no_frac_8_pi = 0.392; + let my_frac_pi_8 = 0.3926990816987; //~ERROR approximate value of `f{32, 64}::FRAC_PI_8` found + let no_frac_pi_8 = 0.392; - let my_ln_10 = 2.302585092994046; //~ERROR + let my_ln_10 = 2.302585092994046; //~ERROR approximate value of `f{32, 64}::LN_10` found let no_ln_10 = 2.303; - let my_ln_2 = 0.6931471805599453; //~ERROR + let my_ln_2 = 0.6931471805599453; //~ERROR approximate value of `f{32, 64}::LN_2` found let no_ln_2 = 0.693; - let my_log10_e = 0.43429448190325176; //~ERROR + let my_log10_e = 0.43429448190325176; //~ERROR approximate value of `f{32, 64}::LOG10_E` found let no_log10_e = 0.434; - let my_log2_e = 1.4426950408889634; //~ERROR + let my_log2_e = 1.4426950408889634; //~ERROR approximate value of `f{32, 64}::LOG2_E` found let no_log2_e = 1.442; - let my_pi = 3.1415; //~ERROR + let my_pi = 3.1415; //~ERROR approximate value of `f{32, 64}::PI` found let almost_pi = 3.141; - let my_sq2 = 1.4142; //~ERROR + let my_sq2 = 1.4142; //~ERROR approximate value of `f{32, 64}::SQRT_2` found let no_sq2 = 1.414; } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index c2a82483005..bcbfe99e42e 100755 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -12,30 +12,30 @@ fn main() { x & 0 == 0; //~ERROR &-masking with zero x & 1 == 1; //ok, distinguishes bit 0 x & 1 == 0; //ok, compared with zero - x & 2 == 1; //~ERROR + x & 2 == 1; //~ERROR incompatible bit mask x | 0 == 0; //ok, equals x == 0 (maybe warn?) x | 1 == 3; //ok, equals x == 2 || x == 3 x | 3 == 3; //ok, equals x <= 3 - x | 3 == 2; //~ERROR + x | 3 == 2; //~ERROR incompatible bit mask - x & 1 > 1; //~ERROR + x & 1 > 1; //~ERROR incompatible bit mask x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 x | 1 > 1; // ok (if a bit silly), equals x > 1 - x | 2 > 1; //~ERROR + x | 2 > 1; //~ERROR incompatible bit mask x | 2 <= 2; // ok (if a bit silly), equals x <= 2 // this also now works with constants - x & THREE_BITS == 8; //~ERROR - x | EVEN_MORE_REDIRECTION < 7; //~ERROR + x & THREE_BITS == 8; //~ERROR incompatible bit mask + x | EVEN_MORE_REDIRECTION < 7; //~ERROR incompatible bit mask - 0 & x == 0; //~ERROR + 0 & x == 0; //~ERROR &-masking with zero 1 | x > 1; // and should now also match uncommon usage - 1 < 2 | x; //~ERROR - 2 == 3 | x; //~ERROR - 1 == x & 2; //~ERROR + 1 < 2 | x; //~ERROR incompatible bit mask + 2 == 3 | x; //~ERROR incompatible bit mask + 1 == x & 2; //~ERROR incompatible bit mask x | 1 > 2; // no error, because we allowed ineffective bit masks ineffective(); @@ -46,8 +46,8 @@ fn main() { fn ineffective() { let x = 5; - x | 1 > 2; //~ERROR - x | 1 < 3; //~ERROR - x | 1 <= 3; //~ERROR - x | 1 >= 2; //~ERROR + x | 1 > 2; //~ERROR ineffective bit mask + x | 1 < 3; //~ERROR ineffective bit mask + x | 1 <= 3; //~ERROR ineffective bit mask + x | 1 >= 2; //~ERROR ineffective bit mask } diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs index b6549c2c1fb..b2369e164ff 100755 --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -5,18 +5,18 @@ #[allow(float_cmp)] fn main() { let x = 5f32; - x == std::f32::NAN; //~ERROR - x != std::f32::NAN; //~ERROR - x < std::f32::NAN; //~ERROR - x > std::f32::NAN; //~ERROR - x <= std::f32::NAN; //~ERROR - x >= std::f32::NAN; //~ERROR + x == std::f32::NAN; //~ERROR doomed comparison with NAN + x != std::f32::NAN; //~ERROR doomed comparison with NAN + x < std::f32::NAN; //~ERROR doomed comparison with NAN + x > std::f32::NAN; //~ERROR doomed comparison with NAN + x <= std::f32::NAN; //~ERROR doomed comparison with NAN + x >= std::f32::NAN; //~ERROR doomed comparison with NAN let y = 0f64; - y == std::f64::NAN; //~ERROR - y != std::f64::NAN; //~ERROR - y < std::f64::NAN; //~ERROR - y > std::f64::NAN; //~ERROR - y <= std::f64::NAN; //~ERROR - y >= std::f64::NAN; //~ERROR + y == std::f64::NAN; //~ERROR doomed comparison with NAN + y != std::f64::NAN; //~ERROR doomed comparison with NAN + y < std::f64::NAN; //~ERROR doomed comparison with NAN + y > std::f64::NAN; //~ERROR doomed comparison with NAN + y <= std::f64::NAN; //~ERROR doomed comparison with NAN + y >= std::f64::NAN; //~ERROR doomed comparison with NAN } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 45fce0c0bb3..298132013a9 100755 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -9,29 +9,29 @@ fn id<X>(x: X) -> X { #[allow(identity_op)] fn main() { // simple values and comparisons - 1 == 1; //~ERROR - "no" == "no"; //~ERROR + 1 == 1; //~ERROR equal expressions + "no" == "no"; //~ERROR equal expressions // even though I agree that no means no ;-) - false != false; //~ERROR - 1.5 < 1.5; //~ERROR - 1u64 >= 1u64; //~ERROR + false != false; //~ERROR equal expressions + 1.5 < 1.5; //~ERROR equal expressions + 1u64 >= 1u64; //~ERROR equal expressions // casts, methods, parenthesis - (1 as u64) & (1 as u64); //~ERROR - 1 ^ ((((((1)))))); //~ERROR - id((1)) | id(1); //~ERROR + (1 as u64) & (1 as u64); //~ERROR equal expressions + 1 ^ ((((((1)))))); //~ERROR equal expressions + id((1)) | id(1); //~ERROR equal expressions // unary and binary operators - (-(2) < -(2)); //~ERROR + (-(2) < -(2)); //~ERROR equal expressions ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); - //~^ ERROR - //~^^ ERROR - //~^^^ ERROR - (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR + //~^ ERROR equal expressions + //~^^ ERROR equal expressions + //~^^^ ERROR equal expressions + (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR equal expressions // various other things - ([1] != [1]); //~ERROR - ((1, 2) != (1, 2)); //~ERROR - [1].len() == [1].len(); //~ERROR + ([1] != [1]); //~ERROR equal expressions + ((1, 2) != (1, 2)); //~ERROR equal expressions + [1].len() == [1].len(); //~ERROR equal expressions vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros } diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 2305e42161a..419e500d0fc 100755 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -13,20 +13,20 @@ fn twice<T>(x : T) -> T where T : Add<T, Output = T>, T : Copy { #[deny(float_cmp)] #[allow(unused)] fn main() { - ZERO == 0f32; //~ERROR - ZERO == 0.0; //~ERROR - ZERO + ZERO != 1.0; //~ERROR + ZERO == 0f32; //~ERROR ==-comparison of f32 or f64 + ZERO == 0.0; //~ERROR ==-comparison of f32 or f64 + ZERO + ZERO != 1.0; //~ERROR !=-comparison of f32 or f64 ONE != 0.0; //~ERROR - twice(ONE) != ONE; //~ERROR - ONE as f64 != 0.0; //~ERROR + twice(ONE) != ONE; //~ERROR !=-comparison of f32 or f64 + ONE as f64 != 0.0; //~ERROR !=-comparison of f32 or f64 let x : f64 = 1.0; - x == 1.0; //~ERROR - x != 0f64; //~ERROR + x == 1.0; //~ERROR ==-comparison of f32 or f64 + x != 0f64; //~ERROR !=-comparison of f32 or f64 - twice(x) != twice(ONE as f64); //~ERROR + twice(x) != twice(ONE as f64); //~ERROR !=-comparison of f32 or f64 x < 0.0; x > 0.0; diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index cde4a615b25..987bada2ece 100755 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -9,16 +9,16 @@ const ZERO : i64 = 0; fn main() { let x = 0; - x + 0; //~ERROR - 0 + x; //~ERROR - x - ZERO; //~ERROR - x | (0); //~ERROR - ((ZERO)) | x; //~ERROR + x + 0; //~ERROR the operation is ineffective + 0 + x; //~ERROR the operation is ineffective + x - ZERO; //~ERROR the operation is ineffective + x | (0); //~ERROR the operation is ineffective + ((ZERO)) | x; //~ERROR the operation is ineffective - x * 1; //~ERROR - 1 * x; //~ERROR - x / ONE; //~ERROR + x * 1; //~ERROR the operation is ineffective + 1 * x; //~ERROR the operation is ineffective + x / ONE; //~ERROR the operation is ineffective - x & NEG_ONE; //~ERROR - -1 & x; //~ERROR + x & NEG_ONE; //~ERROR the operation is ineffective + -1 & x; //~ERROR the operation is ineffective } diff --git a/tests/compile-fail/let_return.rs b/tests/compile-fail/let_return.rs index 8ea4653ef0f..082378d21e2 100755 --- a/tests/compile-fail/let_return.rs +++ b/tests/compile-fail/let_return.rs @@ -6,7 +6,7 @@ fn test() -> i32 { let _y = 0; // no warning let x = 5; //~NOTE - x //~ERROR: + x //~ERROR returning the result of a let binding } fn test_nowarn_1() -> i32 { diff --git a/tests/compile-fail/let_unit.rs b/tests/compile-fail/let_unit.rs index e8620f862a2..f06a10bfe13 100755 --- a/tests/compile-fail/let_unit.rs +++ b/tests/compile-fail/let_unit.rs @@ -8,6 +8,6 @@ fn main() { let _y = 1; // this is fine let _z = ((), 1); // this as well if true { - let _a = (); //~ERROR + let _a = (); //~ERROR this let-binding has unit value } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index facf0378392..91d3b72de84 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -5,11 +5,11 @@ #[deny(str_to_string, string_to_string)] fn main() { let opt = Some(0); - let _ = opt.unwrap(); //~ERROR + let _ = opt.unwrap(); //~ERROR used unwrap() on an Option let res: Result<i32, ()> = Ok(0); - let _ = res.unwrap(); //~ERROR + let _ = res.unwrap(); //~ERROR used unwrap() on a Result - let string = "str".to_string(); //~ERROR - let _again = string.to_string(); //~ERROR + let string = "str".to_string(); //~ERROR `str.to_owned()` is faster + let _again = string.to_string(); //~ERROR `String.to_string()` is a no-op } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 2a3f7e3958c..8aa47769539 100755 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -5,7 +5,7 @@ //extern crate regex; #[deny(mut_mut)] -fn fun(x : &mut &mut u32) -> bool { //~ERROR +fn fun(x : &mut &mut u32) -> bool { //~ERROR generally you want to avoid `&mut &mut **x > 0 } @@ -16,19 +16,19 @@ macro_rules! mut_ptr { #[deny(mut_mut)] #[allow(unused_mut, unused_variables)] fn main() { - let mut x = &mut &mut 1u32; //~ERROR + let mut x = &mut &mut 1u32; //~ERROR generally you want to avoid `&mut &mut { - let mut y = &mut x; //~ERROR + let mut y = &mut x; //~ERROR this expression mutably borrows a mutable reference } if fun(x) { let y : &mut &mut &mut u32 = &mut &mut &mut 2; - //~^ ERROR - //~^^ ERROR - //~^^^ ERROR - //~^^^^ ERROR + //~^ ERROR generally you want to avoid `&mut &mut + //~^^ ERROR generally you want to avoid `&mut &mut + //~^^^ ERROR generally you want to avoid `&mut &mut + //~^^^^ ERROR generally you want to avoid `&mut &mut ***y + **x; } - let mut z = mut_ptr!(&mut 3u32); //~ERROR + let mut z = mut_ptr!(&mut 3u32); //~ERROR generally you want to avoid `&mut &mut } diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index 88919f39d6d..6016f79ab03 100755 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -4,9 +4,9 @@ #[deny(needless_bool)] fn main() { let x = true; - if x { true } else { true }; //~ERROR - if x { false } else { false }; //~ERROR - if x { true } else { false }; //~ERROR - if x { false } else { true }; //~ERROR + if x { true } else { true }; //~ERROR your if-then-else expression will always return true + if x { false } else { false }; //~ERROR your if-then-else expression will always return false + if x { true } else { false }; //~ERROR you can reduce your if statement to its predicate + if x { false } else { true }; //~ERROR you can reduce your if statement to `!` + its predicate if x { x } else { false }; // would also be questionable, but we don't catch this yet } diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs index 34d57127996..e0012942906 100755 --- a/tests/compile-fail/needless_return.rs +++ b/tests/compile-fail/needless_return.rs @@ -8,35 +8,35 @@ fn test_end_of_fn() -> bool { // no error! return true; } - return true; //~ERROR + return true; //~ERROR unneeded return statement } fn test_no_semicolon() -> bool { - return true //~ERROR + return true //~ERROR unneeded return statement } fn test_if_block() -> bool { if true { - return true; //~ERROR + return true; //~ERROR unneeded return statement } else { - return false; //~ERROR + return false; //~ERROR unneeded return statement } } fn test_match(x: bool) -> bool { match x { true => { - return false; //~ERROR + return false; //~ERROR unneeded return statement } false => { - return true //~ERROR + return true //~ERROR unneeded return statement } } } fn test_closure() { let _ = || { - return true; //~ERROR + return true; //~ERROR unneeded return statement }; } diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs index fb7d06214a2..4d57f119479 100755 --- a/tests/compile-fail/precedence.rs +++ b/tests/compile-fail/precedence.rs @@ -4,12 +4,12 @@ #[deny(precedence)] #[allow(eq_op)] fn main() { - format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR - format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR - format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR - format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR - format!("{} vs. {}", 1 ^ 1 - 1, (1 ^ 1) - 1); //~ERROR - format!("{} vs. {}", 3 | 2 - 1, (3 | 2) - 1); //~ERROR - format!("{} vs. {}", 3 & 5 - 2, (3 & 5) - 2); //~ERROR + format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR operator precedence can trip + format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR operator precedence can trip + format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR operator precedence can trip + format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR operator precedence can trip + format!("{} vs. {}", 1 ^ 1 - 1, (1 ^ 1) - 1); //~ERROR operator precedence can trip + format!("{} vs. {}", 3 | 2 - 1, (3 | 2) - 1); //~ERROR operator precedence can trip + format!("{} vs. {}", 3 & 5 - 2, (3 & 5) - 2); //~ERROR operator precedence can trip } diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs index d56ea735a1d..d4b6d22608f 100755 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -3,13 +3,13 @@ #[deny(ptr_arg)] #[allow(unused)] -fn do_vec(x: &Vec<i64>) { //~ERROR: writing `&Vec<_>` instead of `&[_]` +fn do_vec(x: &Vec<i64>) { //~ERROR writing `&Vec<_>` instead of `&[_]` //Nothing here } #[deny(ptr_arg)] #[allow(unused)] -fn do_str(x: &String) { //~ERROR +fn do_str(x: &String) { //~ERROR writing `&String` instead of `&str` //Nothing here either } -- cgit 1.4.1-3-g733a5 From a67e55f3f07d552233248a63d256535e095c7975 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 08:15:42 +0200 Subject: lint messages: remove trailing period Since lint messages often are suffixed by ", #[warn(xxx)] on by default" this trailing period produces an ugly clash with the comma. --- src/approx_const.rs | 2 +- src/eta_reduction.rs | 2 +- src/identity_op.rs | 2 +- src/len_zero.rs | 4 ++-- src/methods.rs | 4 ++-- src/misc.rs | 10 ++++++---- src/mut_mut.rs | 2 +- src/ptr_arg.rs | 4 ++-- src/strings.rs | 2 +- src/types.rs | 2 +- src/unicode.rs | 4 ++-- 11 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 594348bf93f..377c7e66ebd 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -53,7 +53,7 @@ fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { for &(constant, name) in KNOWN_CONSTS { if within_epsilon(constant, value) { span_lint(cx, APPROX_CONSTANT, span, &format!( - "approximate value of `{}::{}` found. Consider using it directly.", module, &name)); + "approximate value of `{}::{}` found. Consider using it directly", module, &name)); } } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 00c5a523981..eda38419d4d 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -51,7 +51,7 @@ impl LintPass for EtaPass { } } span_lint(cx, REDUNDANT_CLOSURE, expr.span, - &format!("redundant closure found. Consider using `{}` in its place.", + &format!("redundant closure found. Consider using `{}` in its place", expr_to_string(caller))[..]) } } diff --git a/src/identity_op.rs b/src/identity_op.rs index e043ac63026..8c6940e3df4 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -49,7 +49,7 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { span_lint(cx, IDENTITY_OP, span, &format!( - "the operation is ineffective. Consider reducing it to `{}`.", + "the operation is ineffective. Consider reducing it to `{}`", snippet(cx, arg, ".."))); } } diff --git a/src/len_zero.rs b/src/len_zero.rs index 298522ed24c..da230c1d28a 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -59,7 +59,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { if is_named_self(i, "len") { span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, &format!("trait `{}` has a `.len(_: &Self)` method, but no \ - `.is_empty(_: &Self)` method. Consider adding one.", + `.is_empty(_: &Self)` method. Consider adding one", item.ident.name)); } }; @@ -79,7 +79,7 @@ fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { span_lint(cx, LEN_WITHOUT_IS_EMPTY, Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, &format!("item `{}` has a `.len(_: &Self)` method, but no \ - `.is_empty(_: &Self)` method. Consider adding one.", + `.is_empty(_: &Self)` method. Consider adding one", item.ident.name)); return; } diff --git a/src/methods.rs b/src/methods.rs index a5b12e52bdf..403845771a9 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -30,12 +30,12 @@ impl LintPass for MethodsPass { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ to handle the None case gracefully, consider using - expect() to provide a better panic message."); + expect() to provide a better panic message"); } else if match_def_path(cx, did.did, &["core", "result", "Result"]) { span_lint(cx, RESULT_UNWRAP_USED, expr.span, "used unwrap() on a Result value. Graceful handling \ - of Err values is preferred."); + of Err values is preferred"); } } } diff --git a/src/misc.rs b/src/misc.rs index d5e1efe2cc3..82754820f8b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -129,7 +129,8 @@ impl LintPass for FloatCmp { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { span_lint(cx, FLOAT_CMP, expr.span, &format!( - "{}-comparison of f32 or f64 detected. Consider changing this to `abs({} - {}) < epsilon` for some suitable value of epsilon.", + "{}-comparison of f32 or f64 detected. Consider changing this to \ + `abs({} - {}) < epsilon` for some suitable value of epsilon", binop_to_string(op), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); } @@ -160,7 +161,8 @@ impl LintPass for Precedence { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { span_lint(cx, PRECEDENCE, expr.span, - "operator precedence can trip the unwary. Consider adding parenthesis to the subexpression."); + "operator precedence can trip the unwary. Consider adding parenthesis \ + to the subexpression"); } } } @@ -216,7 +218,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { name == "to_owned" && is_str_arg(cx, args) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ - Consider using `{}.as_slice()` to compare without allocation.", + Consider using `{}.as_slice()` to compare without allocation", snippet(cx, other_span, ".."))) } }, @@ -226,7 +228,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { match_path(path, &["String", "from"]) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ - Consider using `{}.as_slice()` to compare without allocation.", + Consider using `{}.as_slice()` to compare without allocation", snippet(cx, other_span, ".."))) } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 469a14a9452..a2055bb655f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -46,7 +46,7 @@ fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, "this expression mutably borrows a mutable reference. \ - Consider reborrowing.") + Consider reborrowing") } }) }) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index ed37c112040..3868854c7a1 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -61,9 +61,9 @@ fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { &["String"]).map_or((), |_| { span_lint(cx, PTR_ARG, span, "writing `&String` instead of `&str` involves a new object \ - where a slice will do. Consider changing the type to `&str`.") + where a slice will do. Consider changing the type to `&str`") }), |_| span_lint(cx, PTR_ARG, span, "writing `&Vec<_>` instead of \ `&[_]` involves one more reference and cannot be used with \ - non-Vec-based slices. Consider changing the type to `&[...]`.")) + non-Vec-based slices. Consider changing the type to `&[...]`")) } diff --git a/src/strings.rs b/src/strings.rs index 97016f36268..afc444dd67f 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -30,7 +30,7 @@ impl LintPass for StringAdd { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assign the result of adding something to this string. \ - Consider using `String::push_str()` instead.") + Consider using `String::push_str()` instead") } } } diff --git a/src/types.rs b/src/types.rs index 4980046e01b..c22d088ce5b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -90,7 +90,7 @@ fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { let bindtype = &cx.tcx.pat_ty(&*local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( - "this let-binding has unit value. Consider omitting `let {} =`.", + "this let-binding has unit value. Consider omitting `let {} =`", snippet(cx, local.pat.span, ".."))); } } diff --git a/src/unicode.rs b/src/unicode.rs index ca6abaf01b4..161e90d0f64 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -27,11 +27,11 @@ fn check_str(cx: &Context, string: &str, span: Span) { for (i, c) in string.char_indices() { if c == '\u{200B}' { str_pos_lint(cx, ZERO_WIDTH_SPACE, span, i, - "zero-width space detected. Consider using `\\u{200B}`."); + "zero-width space detected. Consider using `\\u{200B}`"); } if c as u32 > 0x7F { str_pos_lint(cx, NON_ASCII_LITERAL, span, i, &format!( - "literal non-ASCII character detected. Consider using `\\u{{{:X}}}`.", c as u32)); + "literal non-ASCII character detected. Consider using `\\u{{{:X}}}`", c as u32)); } } } -- cgit 1.4.1-3-g733a5 From 45b95537574182be0b7ef6301cdbafe11891ec95 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 09:25:44 +0200 Subject: added follow flag --- src/const.rs | 154 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 41 deletions(-) diff --git a/src/const.rs b/src/const.rs index a353de218f4..38044bbea5c 100644 --- a/src/const.rs +++ b/src/const.rs @@ -3,60 +3,74 @@ use rustc::middle::const_eval::lookup_const_by_id; use syntax::ast::*; use syntax::ptr::P; +pub enum FloatWidth { + Fw32, + Fw64, + FwAny +} + +impl From<FloatTy> for FloatWidth { + fn from(ty: FloatTy) -> FloatWidth { + match ty { + TyF32 => Fw32, + TyF64 => Fw64, + } + } +} + /// a Lit_-like enum to fold constant `Expr`s into #[derive(PartialEq, Eq, Debug, Clone)] pub enum Constant { + /// a String "abc" ConstantStr(&'static str, StrStyle), + /// a Binary String b"abc" ConstantBinary(Rc<Vec<u8>>), + /// a single byte b'a' ConstantByte(u8), + /// a single char 'a' ConstantChar(char), + /// an integer ConstantInt(u64, LitIntType), - ConstantFloat(Cow<'static, str>, FloatTy), - ConstantFloatUnsuffixed(Cow<'static, str>), + /// a float with given type + ConstantFloat(Cow<'static, str>, FloatWidth), + /// true or false ConstantBool(bool), + /// an array of constants ConstantVec(Vec<Constant>), + /// also an array, but with only one constant, repeated N times + ConstantRepeat(Constant, usize), + /// a tuple of constants ConstantTuple(Vec<Constant>), } /// simple constant folding -pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { +pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { match e { - &ExprParen(ref inner) => constant(cx, inner), - &ExprPath(_, _) => fetch_path(cx, e), - &ExprBlock(ref block) => constant_block(cx, inner), - &ExprIf(ref cond, ref then, ref otherwise) => + &ExprParen(ref inner) => constant(cx, inner, follow), + &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None }, + &ExprBlock(ref block) => constant_block(cx, inner, follow), + &ExprIf(ref cond, ref then, ref otherwise) => match constant(cx, cond) { - Some(ConstantBool(true)) => constant(cx, then), - Some(ConstantBool(false)) => constant(cx, otherwise), + Some(ConstantBool(true)) => constant(cx, then, follow), + Some(ConstantBool(false)) => constant(cx, otherwise, follow), _ => None, }, &ExprLit(ref lit) => Some(lit_to_constant(lit)), - &ExprVec(ref vec) => constant_vec(cx, vec), - &ExprTup(ref tup) => constant_tup(cx, tup), - &ExprUnary(op, ref operand) => constant(cx, operand).and_then( + &ExprVec(ref vec) => constant_vec(cx, vec, follow), + &ExprTup(ref tup) => constant_tup(cx, tup, follow), + &ExprRepeat(ref value, ref number) => + constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)), + &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then( |o| match op { UnNot => if let ConstantBool(b) = o { Some(ConstantBool(!b)) } else { None }, - UnNeg => - match o { - &ConstantInt(value, ty) => - Some(ConstantInt(value, match ty { - SignedIntLit(ity, sign) => - SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => - UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - })), - &LitFloat(ref is, ref ty) => - Some(ConstantFloat(neg_float_str(is), ty)), - &LitFloatUnsuffixed(ref is) => - Some(ConstantFloatUnsuffixed(neg_float_str(is))), - _ => None, - }, + UnNeg => constant_negate(o), UnUniq | UnDeref => o, }), + &ExprBinary(op, ref left, ref right) => + constant_binop(cx, op, left, right, follow), //TODO: add other expressions _ => None, } @@ -69,19 +83,19 @@ fn lit_to_constant(lit: &Lit_) -> Constant { &LitByte(b) => ConstantByte(b), &LitChar(c) => ConstantChar(c), &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty), - &LitFloatUnsuffixed(InternedString) => - ConstantFloatUnsuffixed(Cow::Borrowed(&*is)), + &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()), + &LitFloatUnsuffixed(InternedString) => + ConstantFloat(Cow::Borrowed(&*is), FwAny), &LitBool(b) => ConstantBool(b), } } /// create `Some(ConstantVec(..))` of all constants, unless there is any /// non-constant part -fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { - Vec<Constant> parts = Vec::new(); +fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> { + parts = Vec::new(); for opt_part in vec { - match constant(cx, opt_part) { + match constant(cx, opt_part, follow) { Some(ref p) => parts.push(p), None => { return None; }, } @@ -89,10 +103,10 @@ fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { Some(ConstantVec(parts)) } -fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> { - Vec<Constant> parts = Vec::new(); +fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> { + parts = Vec::new(); for opt_part in vec { - match constant(cx, opt_part) { + match constant(cx, opt_part, follow) { Some(ref p) => parts.push(p), None => { return None; }, } @@ -109,23 +123,81 @@ fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { } /// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { +fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> { if block.stmts.is_empty() { - block.expr.map(|b| constant(cx, b)) + block.expr.map(|b| constant(cx, b, follow)) } else { None } } +fn constant_negate(o: Constant) -> Option<Constant> { + match o { + &ConstantInt(value, ty) => + Some(ConstantInt(value, match ty { + SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + })), + &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)), + _ => None, + } +} + fn neg_sign(s: Sign) -> Sign { - match s: + match s { Sign::Plus => Sign::Minus, Sign::Minus => Sign::Plus, } } fn neg_float_str(s: &InternedString) -> Cow<'static, str> { - if s.startsWith('-') { + if s.startsWith('-') { Cow::Borrowed(s[1..]) } else { Cow::Owned(format!("-{}", &*s)) } } + +fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, + follow: bool) -> Option<Constant> { + match op.node { + //BiAdd, + //BiSub, + //BiMul, + //BiDiv, + //BiRem, + BiAnd => constant_short_circuit(cx, left, right, false, follow), + BiOr => constant_short_circuit(cx, left, right, true, follow), + //BiBitXor, + //BiBitAnd, + //BiBitOr, + //BiShl, + //BiShr, + //BiEq, + //BiLt, + //BiLe, + //BiNe, + //BiGe, + //BiGt, + _ => None, + } +} + +fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F, + follow: bool) -> Option<Constant> +where F: FnMut(Constant, Constant) -> Option<Constant> { + constant(cx, left, follow).and_then(|l| constant(cx, right, follow) + .and_then(|r| op(l, r))) +} + +fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool, + follow: bool) -> Option<Constant> { + if let ConstantBool(lbool) = constant(cx, left, follow) { + if l == b { + Some(ConstantBool(b)) + } else { + if let ConstantBool(rbool) = constant(cx, right, follow) { + Some(ConstantBool(rbool)) + } else { None } + } + } else { None } +} -- cgit 1.4.1-3-g733a5 From 12c974e21abc70689c59027adcf42ff3f4b29e84 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 10:45:30 +0200 Subject: changed Constant to a struct with 'needed_resolution' bool --- src/const.rs | 202 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 138 insertions(+), 64 deletions(-) diff --git a/src/const.rs b/src/const.rs index 38044bbea5c..cef2cd7f9fc 100644 --- a/src/const.rs +++ b/src/const.rs @@ -18,9 +18,25 @@ impl From<FloatTy> for FloatWidth { } } +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Constant { + constant: ConstantVariant, + needed_resolution: bool +} + +impl Constant { + fn new(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: false } + } + + fn new_resolved(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: true } + } +} + /// a Lit_-like enum to fold constant `Expr`s into #[derive(PartialEq, Eq, Debug, Clone)] -pub enum Constant { +pub enum ConstantVariant { /// a String "abc" ConstantStr(&'static str, StrStyle), /// a Binary String b"abc" @@ -43,34 +59,51 @@ pub enum Constant { ConstantTuple(Vec<Constant>), } -/// simple constant folding -pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { +impl ConstantVariant { + /// convert to u64 if possible + /// + /// # panics + /// + /// if the constant could not be converted to u64 losslessly + fn as_u64(&self) -> u64 { + if let &ConstantInt(val, _) = self { + val // TODO we may want to check the sign if any + } else { + panic!("Could not convert a {:?} to u64"); + } + } +} + +/// simple constant folding: Insert an expression, get a constant or none. +pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { match e { - &ExprParen(ref inner) => constant(cx, inner, follow), - &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None }, - &ExprBlock(ref block) => constant_block(cx, inner, follow), + &ExprParen(ref inner) => constant(cx, inner), + &ExprPath(_, _) => fetch_path(cx, e), + &ExprBlock(ref block) => constant_block(cx, inner), &ExprIf(ref cond, ref then, ref otherwise) => - match constant(cx, cond) { - Some(ConstantBool(true)) => constant(cx, then, follow), - Some(ConstantBool(false)) => constant(cx, otherwise, follow), - _ => None, - }, + constant_if(cx, cond, then, otherwise), &ExprLit(ref lit) => Some(lit_to_constant(lit)), - &ExprVec(ref vec) => constant_vec(cx, vec, follow), - &ExprTup(ref tup) => constant_tup(cx, tup, follow), + &ExprVec(ref vec) => constant_vec(cx, vec), + &ExprTup(ref tup) => constant_tup(cx, tup), &ExprRepeat(ref value, ref number) => - constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)), - &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then( + constant_binop_apply(cx, value, number,|v, n| Constant { + constant: ConstantRepeat(v, n.constant.as_u64()), + needed_resolution: v.needed_resolution || n.needed_resolution + }), + &ExprUnary(op, ref operand) => constant(cx, operand).and_then( |o| match op { UnNot => - if let ConstantBool(b) = o { - Some(ConstantBool(!b)) + if let ConstantBool(b) = o.variant { + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: ConstantBool(!b), + }) } else { None }, UnNeg => constant_negate(o), UnUniq | UnDeref => o, }), &ExprBinary(op, ref left, ref right) => - constant_binop(cx, op, left, right, follow), + constant_binop(op, left, right), //TODO: add other expressions _ => None, } @@ -78,68 +111,100 @@ pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { fn lit_to_constant(lit: &Lit_) -> Constant { match lit { - &LitStr(ref is, style) => ConstantStr(&*is, style), - &LitBinary(ref blob) => ConstantBinary(blob.clone()), - &LitByte(b) => ConstantByte(b), - &LitChar(c) => ConstantChar(c), - &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()), + &LitStr(ref is, style) => Constant::new(ConstantStr(&*is, style)), + &LitBinary(ref blob) => Constant::new(ConstantBinary(blob.clone())), + &LitByte(b) => Constant::new(ConstantByte(b)), + &LitChar(c) => Constant::new(ConstantChar(c)), + &LitInt(value, ty) => Constant::new(ConstantInt(value, ty)), + &LitFloat(ref is, ty) => + Constant::new(ConstantFloat(Cow::Borrowed(&*is), ty.into())), &LitFloatUnsuffixed(InternedString) => - ConstantFloat(Cow::Borrowed(&*is), FwAny), - &LitBool(b) => ConstantBool(b), + Constant::new(ConstantFloat(Cow::Borrowed(&*is), FwAny)), + &LitBool(b) => Constant::new(ConstantBool(b)), } } /// create `Some(ConstantVec(..))` of all constants, unless there is any /// non-constant part -fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> { - parts = Vec::new(); +fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; for opt_part in vec { - match constant(cx, opt_part, follow) { - Some(ref p) => parts.push(p), + match constant(cx, opt_part) { + Some(ref p) => { + resolved |= p.needed_resolution; + parts.push(p) + }, None => { return None; }, } } - Some(ConstantVec(parts)) + Some(Constant { + constant: ConstantVec(parts), + needed_resolution: resolved + }) } -fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> { - parts = Vec::new(); +fn constant_tup(cx: &Context, tup: &[&Expr]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; for opt_part in vec { - match constant(cx, opt_part, follow) { - Some(ref p) => parts.push(p), + match constant(cx, opt_part) { + Some(ref p) => { + resolved |= p.needed_resolution; + parts.push(p) + }, None => { return None; }, } } - Some(ConstantTuple(parts)) + Some(Constant { + constant: ConstantTuple(parts), + needed_resolution: resolved + }) } /// lookup a possibly constant expression from a ExprPath fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { if let Some(&PathResolution { base_def: DefConst(id), ..}) = cx.tcx.def_map.borrow().get(&e.id) { - lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l)) + lookup_const_by_id(cx.tcx, id, None).map( + |l| Constant::new_resolved(constant(cx, l).constant)) } else { None } } /// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> { +fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { if block.stmts.is_empty() { - block.expr.map(|b| constant(cx, b, follow)) + block.expr.map(|b| constant(cx, b)) + } else { None } +} + +fn constant_if(cx: &Context, cond: &Expr, then: &Expr, otherwise: &Expr) -> + Option<Constant> { + if let Some(Constant{ constant: ConstantBool(b), needed_resolution: res }) = + constant(cx, cond) { + let part = constant(cx, if b { then } else { otherwise }); + Some(Constant { + constant: part.constant, + needed_resolution: res || part.needed_resolution, + }) } else { None } } fn constant_negate(o: Constant) -> Option<Constant> { - match o { - &ConstantInt(value, ty) => - Some(ConstantInt(value, match ty { - SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - })), - &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)), - _ => None, - } + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: match o.constant { + &ConstantInt(value, ty) => + ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + }), + &LitFloat(ref is, ref ty) => ConstantFloat(neg_float_str(is), ty), + _ => { return None; }, + } + }) } fn neg_sign(s: Sign) -> Sign { @@ -157,16 +222,16 @@ fn neg_float_str(s: &InternedString) -> Cow<'static, str> { } } -fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, - follow: bool) -> Option<Constant> { +fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) + -> Option<Constant> { match op.node { //BiAdd, //BiSub, //BiMul, //BiDiv, //BiRem, - BiAnd => constant_short_circuit(cx, left, right, false, follow), - BiOr => constant_short_circuit(cx, left, right, true, follow), + BiAnd => constant_short_circuit(cx, left, right, false), + BiOr => constant_short_circuit(cx, left, right, true), //BiBitXor, //BiBitAnd, //BiBitOr, @@ -182,21 +247,30 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, } } -fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F, - follow: bool) -> Option<Constant> -where F: FnMut(Constant, Constant) -> Option<Constant> { - constant(cx, left, follow).and_then(|l| constant(cx, right, follow) - .and_then(|r| op(l, r))) +fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) + -> Option<Constant> +where F: FnMut(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { + constant(cx, left).and_then(|l| constant(cx, right).and_then( + |r| Constant { + needed_resolution: l.needed_resolution || r.needed_resolution, + constant: op(l.constant, r.constant) + })) } -fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool, - follow: bool) -> Option<Constant> { - if let ConstantBool(lbool) = constant(cx, left, follow) { +fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool) -> + Option<Constant> { + let leftconst = constant(cx, left); + if let ConstantBool(lbool) = leftconst.constant { if l == b { - Some(ConstantBool(b)) + Some(leftconst) } else { - if let ConstantBool(rbool) = constant(cx, right, follow) { - Some(ConstantBool(rbool)) + let rightconst = constant(cx, right); + if let ConstantBool(rbool) = rightconst.constant { + Some(Constant { + constant: rightconst.constant, + needed_resolution: leftconst.needed_resolution || + rightconst.needed_resolution, + }) } else { None } } } else { None } -- cgit 1.4.1-3-g733a5 From 8b9c2a79ed9bf4d25f61513017e9a254d0b02d93 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 13:49:28 +0200 Subject: First (incomplete) const folding --- src/const.rs | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/const.rs diff --git a/src/const.rs b/src/const.rs new file mode 100644 index 00000000000..924a47f2e5a --- /dev/null +++ b/src/const.rs @@ -0,0 +1,131 @@ +use rustc::lint::Context; +use rustc::middle::const_eval::lookup_const_by_id; +use syntax::ast::*; +use syntax::ptr::P; + +/// a Lit_-like enum to fold constant `Expr`s into +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum Constant { + ConstantStr(&'static str, StrStyle), + ConstantBinary(Rc<Vec<u8>>), + ConstantByte(u8), + ConstantChar(char), + ConstantInt(u64, LitIntType), + ConstantFloat(Cow<'static, str>, FloatTy), + ConstantFloatUnsuffixed(Cow<'static, str>), + ConstantBool(bool), + ConstantVec(Vec<Constant>), + ConstantTuple(Vec<Constant>), +} + +/// simple constant folding +pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { + match e { + &ExprParen(ref inner) => constant(cx, inner), + &ExprPath(_, _) => fetch_path(cx, e), + &ExprBlock(ref block) => constant_block(cx, inner), + &ExprIf(ref cond, ref then, ref otherwise) => + match constant(cx, cond) { + Some(LitBool(true)) => constant(cx, then), + Some(LitBool(false)) => constant(cx, otherwise), + _ => None, + }, + &ExprLit(ref lit) => Some(lit_to_constant(lit)), + &ExprVec(ref vec) => constant_vec(cx, vec), + &ExprTup(ref tup) => constant_tup(cx, tup), + &ExprUnary(op, ref operand) => constant(cx, operand).and_then( + |o| match op { + UnNot => + if let ConstantBool(b) = o { + Some(ConstantBool(!b)) + } else { None }, + UnNeg => + match o { + &ConstantInt(value, ty) => + Some(ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => + UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + })), + &LitFloat(ref is, ref ty) => + Some(ConstantFloat(neg_float_str(is), ty)), + &LitFloatUnsuffixed(ref is) => + Some(ConstantFloatUnsuffixed(neg_float_str(is))), + _ => None, + }, + UnUniq | UnDeref => o, + }), + //TODO: add other expressions + _ => None, + } +} + +fn lit_to_constant(lit: &Lit_) -> Constant { + match lit { + &LitStr(ref is, style) => ConstantStr(&*is, style), + &LitBinary(ref blob) => ConstantBinary(blob.clone()), + &LitByte(b) => ConstantByte(b), + &LitChar(c) => ConstantChar(c), + &LitInt(value, ty) => ConstantInt(value, ty), + &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty), + &LitFloatUnsuffixed(InternedString) => + ConstantFloatUnsuffixed(Cow::Borrowed(&*is)), + &LitBool(b) => ConstantBool(b), + } +} + +/// create `Some(ConstantVec(..))` of all constants, unless there is any +/// non-constant part +fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { + Vec<Constant> parts = Vec::new(); + for opt_part in vec { + match constant(cx, opt_part) { + Some(ref p) => parts.push(p), + None => { return None; }, + } + } + Some(ConstantVec(parts)) +} + +fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> { + Vec<Constant> parts = Vec::new(); + for opt_part in vec { + match constant(cx, opt_part) { + Some(ref p) => parts.push(p), + None => { return None; }, + } + } + Some(ConstantTuple(parts)) +} + +/// lookup a possibly constant expression from a ExprPath +fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { + if let Some(&PathResolution { base_def: DefConst(id), ..}) = + cx.tcx.def_map.borrow().get(&e.id) { + lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l)) + } else { None } +} + +/// A block can only yield a constant if it only has one constant expression +fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { + if block.stmts.is_empty() { + block.expr.map(|b| constant(cx, b)) + } else { None } +} + +fn neg_sign(s: Sign) -> Sign { + match s: + Sign::Plus => Sign::Minus, + Sign::Minus => Sign::Plus, + } +} + +fn neg_float_str(s: &InternedString) -> Cow<'static, str> { + if s.startsWith('-') { + Cow::Borrowed(s[1..]) + } else { + Cow::Owned(format!("-{}", &*s)) + } +} -- cgit 1.4.1-3-g733a5 From 6aeb9552148315641e49d7ab791ef6ffa638fcbe Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 14:02:13 +0200 Subject: fixed if-condition match --- src/const.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/const.rs b/src/const.rs index 924a47f2e5a..a353de218f4 100644 --- a/src/const.rs +++ b/src/const.rs @@ -26,8 +26,8 @@ pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { &ExprBlock(ref block) => constant_block(cx, inner), &ExprIf(ref cond, ref then, ref otherwise) => match constant(cx, cond) { - Some(LitBool(true)) => constant(cx, then), - Some(LitBool(false)) => constant(cx, otherwise), + Some(ConstantBool(true)) => constant(cx, then), + Some(ConstantBool(false)) => constant(cx, otherwise), _ => None, }, &ExprLit(ref lit) => Some(lit_to_constant(lit)), -- cgit 1.4.1-3-g733a5 From a2f19f2a380d1027436c30edc52992edfcd50cb1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 09:25:44 +0200 Subject: added follow flag --- src/const.rs | 154 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 41 deletions(-) diff --git a/src/const.rs b/src/const.rs index a353de218f4..38044bbea5c 100644 --- a/src/const.rs +++ b/src/const.rs @@ -3,60 +3,74 @@ use rustc::middle::const_eval::lookup_const_by_id; use syntax::ast::*; use syntax::ptr::P; +pub enum FloatWidth { + Fw32, + Fw64, + FwAny +} + +impl From<FloatTy> for FloatWidth { + fn from(ty: FloatTy) -> FloatWidth { + match ty { + TyF32 => Fw32, + TyF64 => Fw64, + } + } +} + /// a Lit_-like enum to fold constant `Expr`s into #[derive(PartialEq, Eq, Debug, Clone)] pub enum Constant { + /// a String "abc" ConstantStr(&'static str, StrStyle), + /// a Binary String b"abc" ConstantBinary(Rc<Vec<u8>>), + /// a single byte b'a' ConstantByte(u8), + /// a single char 'a' ConstantChar(char), + /// an integer ConstantInt(u64, LitIntType), - ConstantFloat(Cow<'static, str>, FloatTy), - ConstantFloatUnsuffixed(Cow<'static, str>), + /// a float with given type + ConstantFloat(Cow<'static, str>, FloatWidth), + /// true or false ConstantBool(bool), + /// an array of constants ConstantVec(Vec<Constant>), + /// also an array, but with only one constant, repeated N times + ConstantRepeat(Constant, usize), + /// a tuple of constants ConstantTuple(Vec<Constant>), } /// simple constant folding -pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { +pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { match e { - &ExprParen(ref inner) => constant(cx, inner), - &ExprPath(_, _) => fetch_path(cx, e), - &ExprBlock(ref block) => constant_block(cx, inner), - &ExprIf(ref cond, ref then, ref otherwise) => + &ExprParen(ref inner) => constant(cx, inner, follow), + &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None }, + &ExprBlock(ref block) => constant_block(cx, inner, follow), + &ExprIf(ref cond, ref then, ref otherwise) => match constant(cx, cond) { - Some(ConstantBool(true)) => constant(cx, then), - Some(ConstantBool(false)) => constant(cx, otherwise), + Some(ConstantBool(true)) => constant(cx, then, follow), + Some(ConstantBool(false)) => constant(cx, otherwise, follow), _ => None, }, &ExprLit(ref lit) => Some(lit_to_constant(lit)), - &ExprVec(ref vec) => constant_vec(cx, vec), - &ExprTup(ref tup) => constant_tup(cx, tup), - &ExprUnary(op, ref operand) => constant(cx, operand).and_then( + &ExprVec(ref vec) => constant_vec(cx, vec, follow), + &ExprTup(ref tup) => constant_tup(cx, tup, follow), + &ExprRepeat(ref value, ref number) => + constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)), + &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then( |o| match op { UnNot => if let ConstantBool(b) = o { Some(ConstantBool(!b)) } else { None }, - UnNeg => - match o { - &ConstantInt(value, ty) => - Some(ConstantInt(value, match ty { - SignedIntLit(ity, sign) => - SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => - UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - })), - &LitFloat(ref is, ref ty) => - Some(ConstantFloat(neg_float_str(is), ty)), - &LitFloatUnsuffixed(ref is) => - Some(ConstantFloatUnsuffixed(neg_float_str(is))), - _ => None, - }, + UnNeg => constant_negate(o), UnUniq | UnDeref => o, }), + &ExprBinary(op, ref left, ref right) => + constant_binop(cx, op, left, right, follow), //TODO: add other expressions _ => None, } @@ -69,19 +83,19 @@ fn lit_to_constant(lit: &Lit_) -> Constant { &LitByte(b) => ConstantByte(b), &LitChar(c) => ConstantChar(c), &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty), - &LitFloatUnsuffixed(InternedString) => - ConstantFloatUnsuffixed(Cow::Borrowed(&*is)), + &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()), + &LitFloatUnsuffixed(InternedString) => + ConstantFloat(Cow::Borrowed(&*is), FwAny), &LitBool(b) => ConstantBool(b), } } /// create `Some(ConstantVec(..))` of all constants, unless there is any /// non-constant part -fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { - Vec<Constant> parts = Vec::new(); +fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> { + parts = Vec::new(); for opt_part in vec { - match constant(cx, opt_part) { + match constant(cx, opt_part, follow) { Some(ref p) => parts.push(p), None => { return None; }, } @@ -89,10 +103,10 @@ fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { Some(ConstantVec(parts)) } -fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> { - Vec<Constant> parts = Vec::new(); +fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> { + parts = Vec::new(); for opt_part in vec { - match constant(cx, opt_part) { + match constant(cx, opt_part, follow) { Some(ref p) => parts.push(p), None => { return None; }, } @@ -109,23 +123,81 @@ fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { } /// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { +fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> { if block.stmts.is_empty() { - block.expr.map(|b| constant(cx, b)) + block.expr.map(|b| constant(cx, b, follow)) } else { None } } +fn constant_negate(o: Constant) -> Option<Constant> { + match o { + &ConstantInt(value, ty) => + Some(ConstantInt(value, match ty { + SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + })), + &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)), + _ => None, + } +} + fn neg_sign(s: Sign) -> Sign { - match s: + match s { Sign::Plus => Sign::Minus, Sign::Minus => Sign::Plus, } } fn neg_float_str(s: &InternedString) -> Cow<'static, str> { - if s.startsWith('-') { + if s.startsWith('-') { Cow::Borrowed(s[1..]) } else { Cow::Owned(format!("-{}", &*s)) } } + +fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, + follow: bool) -> Option<Constant> { + match op.node { + //BiAdd, + //BiSub, + //BiMul, + //BiDiv, + //BiRem, + BiAnd => constant_short_circuit(cx, left, right, false, follow), + BiOr => constant_short_circuit(cx, left, right, true, follow), + //BiBitXor, + //BiBitAnd, + //BiBitOr, + //BiShl, + //BiShr, + //BiEq, + //BiLt, + //BiLe, + //BiNe, + //BiGe, + //BiGt, + _ => None, + } +} + +fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F, + follow: bool) -> Option<Constant> +where F: FnMut(Constant, Constant) -> Option<Constant> { + constant(cx, left, follow).and_then(|l| constant(cx, right, follow) + .and_then(|r| op(l, r))) +} + +fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool, + follow: bool) -> Option<Constant> { + if let ConstantBool(lbool) = constant(cx, left, follow) { + if l == b { + Some(ConstantBool(b)) + } else { + if let ConstantBool(rbool) = constant(cx, right, follow) { + Some(ConstantBool(rbool)) + } else { None } + } + } else { None } +} -- cgit 1.4.1-3-g733a5 From 1a19d5ef65061338b90336626999eef3497ecbb7 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 10:45:30 +0200 Subject: changed Constant to a struct with 'needed_resolution' bool --- src/const.rs | 202 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 138 insertions(+), 64 deletions(-) diff --git a/src/const.rs b/src/const.rs index 38044bbea5c..cef2cd7f9fc 100644 --- a/src/const.rs +++ b/src/const.rs @@ -18,9 +18,25 @@ impl From<FloatTy> for FloatWidth { } } +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Constant { + constant: ConstantVariant, + needed_resolution: bool +} + +impl Constant { + fn new(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: false } + } + + fn new_resolved(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: true } + } +} + /// a Lit_-like enum to fold constant `Expr`s into #[derive(PartialEq, Eq, Debug, Clone)] -pub enum Constant { +pub enum ConstantVariant { /// a String "abc" ConstantStr(&'static str, StrStyle), /// a Binary String b"abc" @@ -43,34 +59,51 @@ pub enum Constant { ConstantTuple(Vec<Constant>), } -/// simple constant folding -pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { +impl ConstantVariant { + /// convert to u64 if possible + /// + /// # panics + /// + /// if the constant could not be converted to u64 losslessly + fn as_u64(&self) -> u64 { + if let &ConstantInt(val, _) = self { + val // TODO we may want to check the sign if any + } else { + panic!("Could not convert a {:?} to u64"); + } + } +} + +/// simple constant folding: Insert an expression, get a constant or none. +pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { match e { - &ExprParen(ref inner) => constant(cx, inner, follow), - &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None }, - &ExprBlock(ref block) => constant_block(cx, inner, follow), + &ExprParen(ref inner) => constant(cx, inner), + &ExprPath(_, _) => fetch_path(cx, e), + &ExprBlock(ref block) => constant_block(cx, inner), &ExprIf(ref cond, ref then, ref otherwise) => - match constant(cx, cond) { - Some(ConstantBool(true)) => constant(cx, then, follow), - Some(ConstantBool(false)) => constant(cx, otherwise, follow), - _ => None, - }, + constant_if(cx, cond, then, otherwise), &ExprLit(ref lit) => Some(lit_to_constant(lit)), - &ExprVec(ref vec) => constant_vec(cx, vec, follow), - &ExprTup(ref tup) => constant_tup(cx, tup, follow), + &ExprVec(ref vec) => constant_vec(cx, vec), + &ExprTup(ref tup) => constant_tup(cx, tup), &ExprRepeat(ref value, ref number) => - constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)), - &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then( + constant_binop_apply(cx, value, number,|v, n| Constant { + constant: ConstantRepeat(v, n.constant.as_u64()), + needed_resolution: v.needed_resolution || n.needed_resolution + }), + &ExprUnary(op, ref operand) => constant(cx, operand).and_then( |o| match op { UnNot => - if let ConstantBool(b) = o { - Some(ConstantBool(!b)) + if let ConstantBool(b) = o.variant { + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: ConstantBool(!b), + }) } else { None }, UnNeg => constant_negate(o), UnUniq | UnDeref => o, }), &ExprBinary(op, ref left, ref right) => - constant_binop(cx, op, left, right, follow), + constant_binop(op, left, right), //TODO: add other expressions _ => None, } @@ -78,68 +111,100 @@ pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> { fn lit_to_constant(lit: &Lit_) -> Constant { match lit { - &LitStr(ref is, style) => ConstantStr(&*is, style), - &LitBinary(ref blob) => ConstantBinary(blob.clone()), - &LitByte(b) => ConstantByte(b), - &LitChar(c) => ConstantChar(c), - &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()), + &LitStr(ref is, style) => Constant::new(ConstantStr(&*is, style)), + &LitBinary(ref blob) => Constant::new(ConstantBinary(blob.clone())), + &LitByte(b) => Constant::new(ConstantByte(b)), + &LitChar(c) => Constant::new(ConstantChar(c)), + &LitInt(value, ty) => Constant::new(ConstantInt(value, ty)), + &LitFloat(ref is, ty) => + Constant::new(ConstantFloat(Cow::Borrowed(&*is), ty.into())), &LitFloatUnsuffixed(InternedString) => - ConstantFloat(Cow::Borrowed(&*is), FwAny), - &LitBool(b) => ConstantBool(b), + Constant::new(ConstantFloat(Cow::Borrowed(&*is), FwAny)), + &LitBool(b) => Constant::new(ConstantBool(b)), } } /// create `Some(ConstantVec(..))` of all constants, unless there is any /// non-constant part -fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> { - parts = Vec::new(); +fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; for opt_part in vec { - match constant(cx, opt_part, follow) { - Some(ref p) => parts.push(p), + match constant(cx, opt_part) { + Some(ref p) => { + resolved |= p.needed_resolution; + parts.push(p) + }, None => { return None; }, } } - Some(ConstantVec(parts)) + Some(Constant { + constant: ConstantVec(parts), + needed_resolution: resolved + }) } -fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> { - parts = Vec::new(); +fn constant_tup(cx: &Context, tup: &[&Expr]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; for opt_part in vec { - match constant(cx, opt_part, follow) { - Some(ref p) => parts.push(p), + match constant(cx, opt_part) { + Some(ref p) => { + resolved |= p.needed_resolution; + parts.push(p) + }, None => { return None; }, } } - Some(ConstantTuple(parts)) + Some(Constant { + constant: ConstantTuple(parts), + needed_resolution: resolved + }) } /// lookup a possibly constant expression from a ExprPath fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { if let Some(&PathResolution { base_def: DefConst(id), ..}) = cx.tcx.def_map.borrow().get(&e.id) { - lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l)) + lookup_const_by_id(cx.tcx, id, None).map( + |l| Constant::new_resolved(constant(cx, l).constant)) } else { None } } /// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> { +fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { if block.stmts.is_empty() { - block.expr.map(|b| constant(cx, b, follow)) + block.expr.map(|b| constant(cx, b)) + } else { None } +} + +fn constant_if(cx: &Context, cond: &Expr, then: &Expr, otherwise: &Expr) -> + Option<Constant> { + if let Some(Constant{ constant: ConstantBool(b), needed_resolution: res }) = + constant(cx, cond) { + let part = constant(cx, if b { then } else { otherwise }); + Some(Constant { + constant: part.constant, + needed_resolution: res || part.needed_resolution, + }) } else { None } } fn constant_negate(o: Constant) -> Option<Constant> { - match o { - &ConstantInt(value, ty) => - Some(ConstantInt(value, match ty { - SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - })), - &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)), - _ => None, - } + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: match o.constant { + &ConstantInt(value, ty) => + ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + }), + &LitFloat(ref is, ref ty) => ConstantFloat(neg_float_str(is), ty), + _ => { return None; }, + } + }) } fn neg_sign(s: Sign) -> Sign { @@ -157,16 +222,16 @@ fn neg_float_str(s: &InternedString) -> Cow<'static, str> { } } -fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, - follow: bool) -> Option<Constant> { +fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) + -> Option<Constant> { match op.node { //BiAdd, //BiSub, //BiMul, //BiDiv, //BiRem, - BiAnd => constant_short_circuit(cx, left, right, false, follow), - BiOr => constant_short_circuit(cx, left, right, true, follow), + BiAnd => constant_short_circuit(cx, left, right, false), + BiOr => constant_short_circuit(cx, left, right, true), //BiBitXor, //BiBitAnd, //BiBitOr, @@ -182,21 +247,30 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr, } } -fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F, - follow: bool) -> Option<Constant> -where F: FnMut(Constant, Constant) -> Option<Constant> { - constant(cx, left, follow).and_then(|l| constant(cx, right, follow) - .and_then(|r| op(l, r))) +fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) + -> Option<Constant> +where F: FnMut(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { + constant(cx, left).and_then(|l| constant(cx, right).and_then( + |r| Constant { + needed_resolution: l.needed_resolution || r.needed_resolution, + constant: op(l.constant, r.constant) + })) } -fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool, - follow: bool) -> Option<Constant> { - if let ConstantBool(lbool) = constant(cx, left, follow) { +fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool) -> + Option<Constant> { + let leftconst = constant(cx, left); + if let ConstantBool(lbool) = leftconst.constant { if l == b { - Some(ConstantBool(b)) + Some(leftconst) } else { - if let ConstantBool(rbool) = constant(cx, right, follow) { - Some(ConstantBool(rbool)) + let rightconst = constant(cx, right); + if let ConstantBool(rbool) = rightconst.constant { + Some(Constant { + constant: rightconst.constant, + needed_resolution: leftconst.needed_resolution || + rightconst.needed_resolution, + }) } else { None } } } else { None } -- cgit 1.4.1-3-g733a5 From 2c2716f04587eb379bf7715f1dd7d7a46c8f7eab Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 10:32:35 +0200 Subject: all: DRY for lint descriptions * use the rustc style for lint descriptions * add a script to parse all lint descriptions and put the generated table into README --- README.md | 65 ++++++++++++++++++++++------------------- src/approx_const.rs | 3 +- src/attrs.rs | 2 +- src/bit_mask.rs | 7 ++--- src/collapsible_if.rs | 3 +- src/eq_op.rs | 2 +- src/eta_reduction.rs | 2 +- src/identity_op.rs | 2 +- src/len_zero.rs | 5 ++-- src/lib.rs | 15 ++++++---- src/lifetimes.rs | 3 +- src/loops.rs | 2 +- src/methods.rs | 8 +++--- src/misc.rs | 21 +++++++++----- src/mut_mut.rs | 3 +- src/needless_bool.rs | 3 +- src/ptr_arg.rs | 3 +- src/returns.rs | 5 ++-- src/strings.rs | 2 +- src/types.rs | 7 +++-- src/unicode.rs | 7 +++-- util/update_readme.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 180 insertions(+), 70 deletions(-) create mode 100644 util/update_readme.py diff --git a/README.md b/README.md index b61f3561302..193d759ff90 100644 --- a/README.md +++ b/README.md @@ -6,35 +6,42 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints Lints included in this crate: - - `single_match`: Warns when a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used, and recommends `if let` instead. - - `box_vec`: Warns on usage of `Box<Vec<T>>` - - `linkedlist`: Warns on usage of `LinkedList` - - `str_to_string`: Warns on usage of `str::to_string()` - - `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) - - `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination - - `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) - - `ineffective_bit_mask`: Warns on expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` - - `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` - - `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively - - `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant - - `cmp_nan`: Denies comparisons to NAN (which will always return false, which is probably not intended) - - `float_cmp`: Warns on `==` or `!=` comparisons of floaty typed values. As floating-point operations usually involve rounding errors, it is always better to check for approximate equality within some small bounds - - `precedence`: Warns on expressions where precedence may trip up the unwary reader of the source and suggests adding parenthesis, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` - - `redundant_closure`: Warns on usage of eta-reducible closures like `|a| foo(a)` (which can be written as just `foo`) - - `identity_op`: Warns on identity operations like `x + 0` or `y / 1` (which can be reduced to `x` and `y`, respectively) - - `mut_mut`: Warns on `&mut &mut` which is either a copy'n'paste error, or shows a fundamental misunderstanding of references - - `len_zero`: Warns on `_.len() == 0` and suggests using `_.is_empty()` (or similar comparisons with `>` or `!=`) - - `len_without_is_empty`: Warns on traits or impls that have a `.len()` but no `.is_empty()` method - - `cmp_owned`: Warns on creating owned instances for comparing with others, e.g. `x == "foo".to_string()` - - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea - - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - - `zero_width_space`: Warns on encountering a unicode zero-width space - - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. - - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. - - `let_and_return`: Warns on doing `let x = expr; x` at the end of a function. - - `option_unwrap_used`: Warns when `Option.unwrap()` is used, and suggests `.expect()`. - - `result_unwrap_used`: Warns when `Result.unwrap()` is used (silent by default). - - `modulo_one`: Warns on taking a number modulo 1, which always has a result of 0. +name | default | meaning +---------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) +cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` +ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +inline_always | warn | `#[inline(always)]` is a bad idea in most cases +len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` +len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +modulo_one | warn | taking a number modulo 1, which always returns 0 +mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do +needless_return | warn | using a return statement like `return expr;` where an expression would suffice +non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +option_unwrap_used | warn | using `Option.unwrap()`, which should at least get a better message using `expect()` +precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` +ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled +single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` +string_add_assign | warn | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +string_to_string | warn | calling `String.to_string()` which is a no-op +toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +zero_width_space | deny | using a zero-width space in a string literal, which is confusing To use, add the following lines to your Cargo.toml: diff --git a/src/approx_const.rs b/src/approx_const.rs index 377c7e66ebd..3c39b79885c 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -12,7 +12,8 @@ use utils::span_lint; declare_lint! { pub APPROX_CONSTANT, Warn, - "Warn if a user writes an approximate known constant in their code" + "the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) \ + is found; suggests to use the constant" } const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), diff --git a/src/attrs.rs b/src/attrs.rs index 789a992e3a5..ca5b6c55ced 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -9,7 +9,7 @@ use syntax::parse::token::InternedString; use utils::{in_macro, match_path, span_lint}; declare_lint! { pub INLINE_ALWAYS, Warn, - "#[inline(always)] is usually a bad idea."} + "`#[inline(always)]` is a bad idea in most cases" } #[derive(Copy,Clone)] diff --git a/src/bit_mask.rs b/src/bit_mask.rs index b5f088c23ef..169975001b9 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -11,15 +11,14 @@ use utils::span_lint; declare_lint! { pub BAD_BIT_MASK, Deny, - "Deny the use of incompatible bit masks in comparisons, e.g. \ - '(a & 1) == 2'" + "expressions of the form `_ & mask == select` that will only ever return `true` or `false` \ + (because in the example `select` containing bits that `mask` doesn't have)" } declare_lint! { pub INEFFECTIVE_BIT_MASK, Warn, - "Warn on the use of an ineffective bit mask in comparisons, e.g. \ - '(a & 1) > 2'" + "expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`" } /// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 0350db8163a..f0f53622c47 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -23,7 +23,8 @@ use utils::{in_macro, span_help_and_lint, snippet}; declare_lint! { pub COLLAPSIBLE_IF, Warn, - "Warn on if expressions that can be collapsed" + "two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` \ + can be written as `if x && y { foo() }`" } #[derive(Copy,Clone)] diff --git a/src/eq_op.rs b/src/eq_op.rs index 6ad0e0658df..495696b810c 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -8,7 +8,7 @@ use utils::span_lint; declare_lint! { pub EQ_OP, Warn, - "warn about comparing equal expressions (e.g. x == x)" + "equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" } #[derive(Copy,Clone)] diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index eda38419d4d..484d46ddc21 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -11,7 +11,7 @@ pub struct EtaPass; declare_lint!(pub REDUNDANT_CLOSURE, Warn, - "Warn on usage of redundant closures, i.e. `|a| foo(a)`"); + "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"); impl LintPass for EtaPass { fn get_lints(&self) -> LintArray { diff --git a/src/identity_op.rs b/src/identity_op.rs index 8c6940e3df4..964675b765e 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -10,7 +10,7 @@ use syntax::codemap::Span; use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, - "Warn on identity operations, e.g. '_ + 0'"} + "using identity operations, e.g. `x + 0` or `y / 1`" } #[derive(Copy,Clone)] pub struct IdentityOp; diff --git a/src/len_zero.rs b/src/len_zero.rs index da230c1d28a..d5f3d1ad810 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -12,10 +12,11 @@ use syntax::ast::*; use utils::{span_lint, walk_ptrs_ty, snippet}; declare_lint!(pub LEN_ZERO, Warn, - "Warn when .is_empty() could be used instead of checking .len()"); + "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ + could be used instead"); declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, - "Warn on traits and impls that have .len() but not .is_empty()"); + "traits and impls that have `.len()` but not `.is_empty()`"); #[derive(Copy,Clone)] pub struct LenZero; diff --git a/src/lib.rs b/src/lib.rs index f788c72db3c..eb2704cd4bd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,16 +64,21 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); - reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST, + reg.register_lint_group("clippy", vec![types::BOX_VEC, + types::LINKEDLIST, + types::LET_UNIT_VALUE, misc::SINGLE_MATCH, - misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, + misc::TOPLEVEL_REF_ARG, + misc::CMP_NAN, + misc::FLOAT_CMP, + misc::PRECEDENCE, + misc::CMP_OWNED, + eq_op::EQ_OP, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, ptr_arg::PTR_ARG, needless_bool::NEEDLESS_BOOL, approx_const::APPROX_CONSTANT, - misc::CMP_NAN, misc::FLOAT_CMP, - misc::PRECEDENCE, misc::CMP_OWNED, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, mut_mut::MUT_MUT, @@ -85,12 +90,12 @@ pub fn plugin_registrar(reg: &mut Registry) { unicode::NON_ASCII_LITERAL, strings::STRING_ADD_ASSIGN, returns::NEEDLESS_RETURN, + returns::LET_AND_RETURN, misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::STR_TO_STRING, methods::STRING_TO_STRING, - types::LET_UNIT_VALUE, lifetimes::NEEDLESS_LIFETIMES, loops::NEEDLESS_RANGE_LOOP, ]); diff --git a/src/lifetimes.rs b/src/lifetimes.rs index b510173e753..644537f9be1 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -7,7 +7,8 @@ use std::collections::HashSet; use std::iter::FromIterator; declare_lint!(pub NEEDLESS_LIFETIMES, Warn, - "Warn on explicit lifetimes when elision rules would apply"); + "using explicit lifetimes for references in function arguments when elision rules \ + would allow omitting them"); #[derive(Copy,Clone)] pub struct LifetimePass; diff --git a/src/loops.rs b/src/loops.rs index 83d7ca4eccb..b406bc67961 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use utils::{span_lint, get_parent_expr}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, - "Warn about looping over a range of indices if a normal iterator would do" } + "for-looping over a range of indices where an iterator over items would do" } #[derive(Copy, Clone)] pub struct LoopsPass; diff --git a/src/methods.rs b/src/methods.rs index 403845771a9..07b0fdf70e2 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -8,13 +8,13 @@ use utils::{span_lint, match_def_path, walk_ptrs_ty}; pub struct MethodsPass; declare_lint!(pub OPTION_UNWRAP_USED, Warn, - "Warn on using unwrap() on an Option value"); + "using `Option.unwrap()`, which should at least get a better message using `expect()`"); declare_lint!(pub RESULT_UNWRAP_USED, Allow, - "Warn on using unwrap() on a Result value"); + "using `Result.unwrap()`, which might be better handled"); declare_lint!(pub STR_TO_STRING, Warn, - "Warn when a String could use to_owned() instead of to_string()"); + "using `to_string()` on a str, which should be `to_owned()`"); declare_lint!(pub STRING_TO_STRING, Warn, - "Warn when calling String.to_string()"); + "calling `String.to_string()` which is a no-op"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { diff --git a/src/misc.rs b/src/misc.rs index 925843a7046..6c9a7d92ce8 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -16,7 +16,8 @@ pub struct MiscPass; declare_lint!(pub SINGLE_MATCH, Warn, - "Warn on usage of matches with a single nontrivial arm"); + "a match statement with a single nontrivial arm (i.e, where the other arm \ + is `_ => {}`) is used; recommends `if let` instead"); impl LintPass for MiscPass { fn get_lints(&self) -> LintArray { @@ -59,7 +60,9 @@ impl LintPass for MiscPass { } -declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); +declare_lint!(pub TOPLEVEL_REF_ARG, Warn, + "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \ + `fn foo((ref x, ref y): (u8, u8))`)"); #[allow(missing_copy_implementations)] pub struct TopLevelRefPass; @@ -82,7 +85,8 @@ impl LintPass for TopLevelRefPass { } } -declare_lint!(pub CMP_NAN, Deny, "Deny comparisons to std::f32::NAN or std::f64::NAN"); +declare_lint!(pub CMP_NAN, Deny, + "comparisons to NAN (which will always return false, which is probably not intended)"); #[derive(Copy,Clone)] pub struct CmpNan; @@ -114,7 +118,9 @@ fn check_nan(cx: &Context, path: &Path, span: Span) { } declare_lint!(pub FLOAT_CMP, Warn, - "Warn on ==/!= comparison of floaty values"); + "using `==` or `!=` on float values (as floating-point operations \ + usually involve rounding errors, it is always better to check for approximate \ + equality within small bounds)"); #[derive(Copy,Clone)] pub struct FloatCmp; @@ -147,7 +153,8 @@ fn is_float(cx: &Context, expr: &Expr) -> bool { } declare_lint!(pub PRECEDENCE, Warn, - "Warn on mixing bit ops with integer arithmetic without parentheses"); + "expressions where precedence may trip up the unwary reader of the source; \ + suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)`"); #[derive(Copy,Clone)] pub struct Precedence; @@ -190,7 +197,7 @@ fn is_arith_op(op : BinOp_) -> bool { } declare_lint!(pub CMP_OWNED, Warn, - "Warn on creating an owned string just for comparison"); + "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`"); #[derive(Copy,Clone)] pub struct CmpOwned; @@ -242,7 +249,7 @@ fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } } -declare_lint!(pub MODULO_ONE, Warn, "Warn on expressions that include % 1, which is always 0"); +declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); #[derive(Copy,Clone)] pub struct ModuloOne; diff --git a/src/mut_mut.rs b/src/mut_mut.rs index a2055bb655f..a3c40d06f90 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -6,7 +6,8 @@ use syntax::codemap::{BytePos, ExpnInfo, Span}; use utils::{in_macro, span_lint}; declare_lint!(pub MUT_MUT, Warn, - "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); + "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ + or shows a fundamental misunderstanding of references)"); #[derive(Copy,Clone)] pub struct MutMut; diff --git a/src/needless_bool.rs b/src/needless_bool.rs index d97e819077a..6a4a55aeda5 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -15,7 +15,8 @@ use utils::{de_p, span_lint}; declare_lint! { pub NEEDLESS_BOOL, Warn, - "Warn on needless use of if x { true } else { false } (or vice versa)" + "if-statements with plain booleans in the then- and else-clause, e.g. \ + `if p { true } else { false }`" } #[derive(Copy,Clone)] diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 3868854c7a1..85db4aa7b21 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -16,7 +16,8 @@ use utils::span_lint; declare_lint! { pub PTR_ARG, Allow, - "Warn on declaration of a &Vec- or &String-typed method argument" + "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ + instead, respectively" } #[derive(Copy,Clone)] diff --git a/src/returns.rs b/src/returns.rs index be28e14001c..94b9ec9650f 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -7,9 +7,10 @@ use rustc::lint::{Context, LintPass, LintArray, Level}; use utils::{span_lint, snippet, match_path}; declare_lint!(pub NEEDLESS_RETURN, Warn, - "Warn on using a return statement where an expression would be enough"); + "using a return statement like `return expr;` where an expression would suffice"); declare_lint!(pub LET_AND_RETURN, Warn, - "Warn on creating a let-binding and then immediately returning it"); + "creating a let-binding and then immediately returning it like `let x = expr; x` at \ + the end of a function"); #[derive(Copy,Clone)] pub struct ReturnPass; diff --git a/src/strings.rs b/src/strings.rs index afc444dd67f..20844be318b 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -14,7 +14,7 @@ use utils::{match_def_path, span_lint, walk_ptrs_ty}; declare_lint! { pub STRING_ADD_ASSIGN, Warn, - "Warn on `x = x + ..` where x is a `String`" + "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" } #[derive(Copy,Clone)] diff --git a/src/types.rs b/src/types.rs index c22d088ce5b..ad7b767d95e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -12,9 +12,10 @@ use utils::{in_macro, snippet, span_lint, span_help_and_lint}; pub struct TypePass; declare_lint!(pub BOX_VEC, Warn, - "Warn on usage of Box<Vec<T>>"); + "usage of `Box<Vec<T>>`, vector elements are already on the heap"); declare_lint!(pub LINKEDLIST, Warn, - "Warn on usage of LinkedList"); + "usage of LinkedList, usually a vector is faster, or a more specialized data \ + structure like a RingBuf"); /// Matches a type with a provided string, and returns its type parameters if successful pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> { @@ -81,7 +82,7 @@ impl LintPass for TypePass { pub struct LetPass; declare_lint!(pub LET_UNIT_VALUE, Warn, - "Warn on let-binding a value of unit type"); + "creating a let binding to a value of unit type, which usually can't be used afterwards"); fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { diff --git a/src/unicode.rs b/src/unicode.rs index 161e90d0f64..62b4a9dadf5 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -3,8 +3,11 @@ use syntax::ast::*; use syntax::codemap::{BytePos, Span}; use utils::span_lint; -declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } -declare_lint!{ pub NON_ASCII_LITERAL, Allow, "Lint literal non-ASCII chars in literals" } +declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, + "using a zero-width space in a string literal, which is confusing" } +declare_lint!{ pub NON_ASCII_LITERAL, Allow, + "using any literal non-ASCII chars in a string literal; suggests \ + using the \\u escape instead" } #[derive(Copy, Clone)] pub struct Unicode; diff --git a/util/update_readme.py b/util/update_readme.py new file mode 100644 index 00000000000..0b54afa83ea --- /dev/null +++ b/util/update_readme.py @@ -0,0 +1,80 @@ +# Generate a Markdown table of all lints, and put it in README.md. +# With -n option, only print the new table to stdout. + +import os +import re +import sys + +declare_lint_re = re.compile(r''' + declare_lint! \s* [{(] \s* + pub \s+ (?P<name>[A-Z_]+) \s*,\s* + (?P<level>Forbid|Deny|Warn|Allow) \s*,\s* + " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] +''', re.X | re.S) + +nl_escape_re = re.compile(r'\\\n\s*') + + +def collect(lints, fp): + code = fp.read() + for match in declare_lint_re.finditer(code): + # remove \-newline escapes from description string + desc = nl_escape_re.sub('', match.group('desc')) + lints.append((match.group('name').lower(), + match.group('level').lower(), + desc.replace('\\"', '"'))) + + +def write_tbl(lints, fp): + # first and third column widths + w_name = max(len(l[0]) for l in lints) + w_desc = max(len(l[2]) for l in lints) + # header and underline + fp.write('%-*s | default | meaning\n' % (w_name, 'name')) + fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) + # one table row per lint + for (name, default, meaning) in sorted(lints): + fp.write('%-*s | %-7s | %s\n' % (w_name, name, default, meaning)) + + +def main(print_only=False): + lints = [] + + # check directory + if not os.path.isfile('src/lib.rs'): + print('Error: call this script from clippy checkout directory!') + return + + # collect all lints from source files + for root, dirs, files in os.walk('src'): + for fn in files: + if fn.endswith('.rs'): + with open(os.path.join(root, fn)) as fp: + collect(lints, fp) + + if print_only: + write_tbl(lints, sys.stdout) + return + + # read current README.md content + with open('README.md') as fp: + lines = list(fp) + + # replace old table with new table + with open('README.md', 'w') as fp: + in_old_tbl = False + for line in lines: + if line.replace(' ', '').strip() == 'name|default|meaning': + # old table starts here + write_tbl(lints, fp) + in_old_tbl = True + if in_old_tbl: + # the old table is finished by an empty line + if line.strip(): + continue + in_old_tbl = False + fp.write(line) + + +if __name__ == '__main__': + main(print_only='-n' in sys.argv) -- cgit 1.4.1-3-g733a5 From ea0cf2a29685a0939c4ad0a04ea1aada608b8731 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 11:31:09 +0200 Subject: update script: also generate lint list in lib.rs --- src/lib.rs | 71 ++++++++++++++++---------------- util/update_lints.py | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ util/update_readme.py | 80 ------------------------------------ 3 files changed, 146 insertions(+), 115 deletions(-) create mode 100644 util/update_lints.py delete mode 100644 util/update_readme.py diff --git a/src/lib.rs b/src/lib.rs index eb2704cd4bd..9fc5def88c4 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,39 +64,40 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); - reg.register_lint_group("clippy", vec![types::BOX_VEC, - types::LINKEDLIST, - types::LET_UNIT_VALUE, - misc::SINGLE_MATCH, - misc::TOPLEVEL_REF_ARG, - misc::CMP_NAN, - misc::FLOAT_CMP, - misc::PRECEDENCE, - misc::CMP_OWNED, - eq_op::EQ_OP, - bit_mask::BAD_BIT_MASK, - bit_mask::INEFFECTIVE_BIT_MASK, - ptr_arg::PTR_ARG, - needless_bool::NEEDLESS_BOOL, - approx_const::APPROX_CONSTANT, - eta_reduction::REDUNDANT_CLOSURE, - identity_op::IDENTITY_OP, - mut_mut::MUT_MUT, - len_zero::LEN_ZERO, - len_zero::LEN_WITHOUT_IS_EMPTY, - attrs::INLINE_ALWAYS, - collapsible_if::COLLAPSIBLE_IF, - unicode::ZERO_WIDTH_SPACE, - unicode::NON_ASCII_LITERAL, - strings::STRING_ADD_ASSIGN, - returns::NEEDLESS_RETURN, - returns::LET_AND_RETURN, - misc::MODULO_ONE, - methods::OPTION_UNWRAP_USED, - methods::RESULT_UNWRAP_USED, - methods::STR_TO_STRING, - methods::STRING_TO_STRING, - lifetimes::NEEDLESS_LIFETIMES, - loops::NEEDLESS_RANGE_LOOP, - ]); + reg.register_lint_group("clippy", vec![ + approx_const::APPROX_CONSTANT, + attrs::INLINE_ALWAYS, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + collapsible_if::COLLAPSIBLE_IF, + eq_op::EQ_OP, + eta_reduction::REDUNDANT_CLOSURE, + identity_op::IDENTITY_OP, + len_zero::LEN_WITHOUT_IS_EMPTY, + len_zero::LEN_ZERO, + lifetimes::NEEDLESS_LIFETIMES, + loops::NEEDLESS_RANGE_LOOP, + methods::OPTION_UNWRAP_USED, + methods::RESULT_UNWRAP_USED, + methods::STR_TO_STRING, + methods::STRING_TO_STRING, + misc::CMP_NAN, + misc::CMP_OWNED, + misc::FLOAT_CMP, + misc::MODULO_ONE, + misc::PRECEDENCE, + misc::SINGLE_MATCH, + misc::TOPLEVEL_REF_ARG, + mut_mut::MUT_MUT, + needless_bool::NEEDLESS_BOOL, + ptr_arg::PTR_ARG, + returns::LET_AND_RETURN, + returns::NEEDLESS_RETURN, + strings::STRING_ADD_ASSIGN, + types::BOX_VEC, + types::LET_UNIT_VALUE, + types::LINKEDLIST, + unicode::NON_ASCII_LITERAL, + unicode::ZERO_WIDTH_SPACE, + ]); } diff --git a/util/update_lints.py b/util/update_lints.py new file mode 100644 index 00000000000..c2a9e08c993 --- /dev/null +++ b/util/update_lints.py @@ -0,0 +1,110 @@ +# Generate a Markdown table of all lints, and put it in README.md. +# With -n option, only print the new table to stdout. + +import os +import re +import sys + +declare_lint_re = re.compile(r''' + declare_lint! \s* [{(] \s* + pub \s+ (?P<name>[A-Z_]+) \s*,\s* + (?P<level>Forbid|Deny|Warn|Allow) \s*,\s* + " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] +''', re.X | re.S) + +nl_escape_re = re.compile(r'\\\n\s*') + + +def collect(lints, fn): + """Collect all lints from a file. + + Adds entries to the lints list as `(module, name, level, desc)`. + """ + with open(fn) as fp: + code = fp.read() + for match in declare_lint_re.finditer(code): + # remove \-newline escapes from description string + desc = nl_escape_re.sub('', match.group('desc')) + lints.append((os.path.splitext(os.path.basename(fn))[0], + match.group('name').lower(), + match.group('level').lower(), + desc.replace('\\"', '"'))) + + +def write_tbl(lints, fp): + """Write lint table in Markdown format.""" + # first and third column widths + w_name = max(len(l[1]) for l in lints) + w_desc = max(len(l[3]) for l in lints) + # header and underline + fp.write('%-*s | default | meaning\n' % (w_name, 'name')) + fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) + # one table row per lint + for (_, name, default, meaning) in sorted(lints, key=lambda l: l[1]): + fp.write('%-*s | %-7s | %s\n' % (w_name, name, default, meaning)) + + +def write_group(lints, fp): + """Write lint group (list of all lints in the form module::NAME).""" + for (module, name, _, _) in sorted(lints): + fp.write(' %s::%s,\n' % (module, name.upper())) + + +def replace_region(fn, region_start, region_end, callback, + replace_start=True): + """Replace a region in a file delimited by two lines matching regexes. + + A callback is called to write the new region. If `replace_start` is true, + the start delimiter line is replaced as well. The end delimiter line is + never replaced. + """ + # read current content + with open(fn) as fp: + lines = list(fp) + + # replace old region with new region + with open(fn, 'w') as fp: + in_old_region = False + for line in lines: + if in_old_region: + if re.search(region_end, line): + in_old_region = False + fp.write(line) + elif re.search(region_start, line): + if not replace_start: + fp.write(line) + # old region starts here + in_old_region = True + callback(fp) + else: + fp.write(line) + + +def main(print_only=False): + lints = [] + + # check directory + if not os.path.isfile('src/lib.rs'): + print('Error: call this script from clippy checkout directory!') + return + + # collect all lints from source files + for root, dirs, files in os.walk('src'): + for fn in files: + if fn.endswith('.rs'): + collect(lints, os.path.join(root, fn)) + + if print_only: + write_tbl(lints, sys.stdout) + return + + # replace table in README.md + replace_region('README.md', r'^name +\|', '^$', lambda fp: write_tbl(lints, fp)) + + # same for "clippy" lint collection + replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + lambda fp: write_group(lints, fp), replace_start=False) + + +if __name__ == '__main__': + main(print_only='-n' in sys.argv) diff --git a/util/update_readme.py b/util/update_readme.py deleted file mode 100644 index 0b54afa83ea..00000000000 --- a/util/update_readme.py +++ /dev/null @@ -1,80 +0,0 @@ -# Generate a Markdown table of all lints, and put it in README.md. -# With -n option, only print the new table to stdout. - -import os -import re -import sys - -declare_lint_re = re.compile(r''' - declare_lint! \s* [{(] \s* - pub \s+ (?P<name>[A-Z_]+) \s*,\s* - (?P<level>Forbid|Deny|Warn|Allow) \s*,\s* - " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] -''', re.X | re.S) - -nl_escape_re = re.compile(r'\\\n\s*') - - -def collect(lints, fp): - code = fp.read() - for match in declare_lint_re.finditer(code): - # remove \-newline escapes from description string - desc = nl_escape_re.sub('', match.group('desc')) - lints.append((match.group('name').lower(), - match.group('level').lower(), - desc.replace('\\"', '"'))) - - -def write_tbl(lints, fp): - # first and third column widths - w_name = max(len(l[0]) for l in lints) - w_desc = max(len(l[2]) for l in lints) - # header and underline - fp.write('%-*s | default | meaning\n' % (w_name, 'name')) - fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) - # one table row per lint - for (name, default, meaning) in sorted(lints): - fp.write('%-*s | %-7s | %s\n' % (w_name, name, default, meaning)) - - -def main(print_only=False): - lints = [] - - # check directory - if not os.path.isfile('src/lib.rs'): - print('Error: call this script from clippy checkout directory!') - return - - # collect all lints from source files - for root, dirs, files in os.walk('src'): - for fn in files: - if fn.endswith('.rs'): - with open(os.path.join(root, fn)) as fp: - collect(lints, fp) - - if print_only: - write_tbl(lints, sys.stdout) - return - - # read current README.md content - with open('README.md') as fp: - lines = list(fp) - - # replace old table with new table - with open('README.md', 'w') as fp: - in_old_tbl = False - for line in lines: - if line.replace(' ', '').strip() == 'name|default|meaning': - # old table starts here - write_tbl(lints, fp) - in_old_tbl = True - if in_old_tbl: - # the old table is finished by an empty line - if line.strip(): - continue - in_old_tbl = False - fp.write(line) - - -if __name__ == '__main__': - main(print_only='-n' in sys.argv) -- cgit 1.4.1-3-g733a5 From 71b46d9ecdd4adac122199669596370b14a4bb02 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 11:35:30 +0200 Subject: improved string_add/string_add_assign messages, Allow-by-default string_add_assign --- README.md | 2 +- src/strings.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4644bac94cd..d2e5049f8e1 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Lints included in this crate: - `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space - - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. + - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. Allowed by default. - `string_add`: Matches `x + ..` where `x` is a `String` and where `string_add_assign` doesn't warn. Allowed by default. - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. - `let_and_return`: Warns on doing `let x = expr; x` at the end of a function. diff --git a/src/strings.rs b/src/strings.rs index 33db980c065..226b851e991 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -13,14 +13,15 @@ use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, - Warn, - "Warn on `x = x + ..` where x is a `String`" + Allow, + "expressions of the form `x = x + ..` where x is a `String`" } declare_lint! { pub STRING_ADD, Allow, - "Warn on `x + ..` where x is a `String`" + "expressions of the form `x + ..` where x is a `String` \ + unless `string_add_assign` matches" } #[derive(Copy, Clone)] -- cgit 1.4.1-3-g733a5 From 0b08e9e83eb155188a5129f0d01bb09c7306d3b5 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 15:50:56 +0200 Subject: added string_add lint and fixed string_add_assign + test --- README.md | 1 + src/lib.rs | 1 + src/strings.rs | 47 +++++++++++++++++++++++++++++++++++++++---- tests/compile-fail/strings.rs | 13 ++++++++---- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b61f3561302..1dd8f5eaec6 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Lints included in this crate: - `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` - `zero_width_space`: Warns on encountering a unicode zero-width space - `string_add_assign`: Warns on `x = x + ..` where `x` is a `String` and suggests using `push_str(..)` instead. + - `string_add`: Matches `x + ..` where `x` is a `String` and where `string_add_assign` doesn't warn. Allowed by default. - `needless_return`: Warns on using `return expr;` when a simple `expr` would suffice. - `let_and_return`: Warns on doing `let x = expr; x` at the end of a function. - `option_unwrap_used`: Warns when `Option.unwrap()` is used, and suggests `.expect()`. diff --git a/src/lib.rs b/src/lib.rs index f788c72db3c..e6703e6bb28 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,6 +58,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); + reg.register_lint_pass(box strings::StringAddAssign as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); diff --git a/src/strings.rs b/src/strings.rs index afc444dd67f..89fc18fd0c5 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -9,7 +9,7 @@ use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use eq_op::is_exp_equal; use types::match_ty_unwrap; -use utils::{match_def_path, span_lint, walk_ptrs_ty}; +use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, @@ -17,10 +17,48 @@ declare_lint! { "Warn on `x = x + ..` where x is a `String`" } -#[derive(Copy,Clone)] +declare_lint! { + pub STRING_ADD, + Allow, + "Warn on `x + ..` where x is a `String`" +} + +#[derive(Copy, Clone)] pub struct StringAdd; impl LintPass for StringAdd { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_ADD) + } + + fn check_expr(&mut self, cx: &Context, e: &Expr) { + if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { + if is_string(cx, left) { + if let Allow = cx.current_level(STRING_ADD_ASSIGN) { + // the string_add_assign is allow, so no duplicates + } else { + let parent = get_parent_expr(cx, e); + if let Some(ref p) = parent { + if let &ExprAssign(ref target, _) = &p.node { + // avoid duplicate matches + if is_exp_equal(target, left) { return; } + } + } + } + //TODO check for duplicates + span_lint(cx, STRING_ADD, e.span, + "you add something to a string. \ + Consider using `String::push_str()` instead.") + } + } + } +} + + +#[derive(Copy, Clone)] +pub struct StringAddAssign; + +impl LintPass for StringAddAssign { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD_ASSIGN) } @@ -37,8 +75,9 @@ impl LintPass for StringAdd { } fn is_string(cx: &Context, e: &Expr) -> bool { - if let TyStruct(did, _) = walk_ptrs_ty(cx.tcx.expr_ty(e)).sty { - match_def_path(cx, did.did, &["std", "string", "String"]) + let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + if let TyStruct(did, _) = ty.sty { + match_def_path(cx, did.did, &["collections", "string", "String"]) } else { false } } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 4b6f0bc884f..e898a087d08 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -2,11 +2,16 @@ #![plugin(clippy)] #![deny(string_add_assign)] - +#![deny(string_add)] fn main() { - let x = "".to_owned(); + let mut x = "".to_owned(); - for i in (1..3) { - x = x + "."; //~ERROR + for _ in (1..3) { + x = x + "."; //~ERROR you assign the result of adding something to this string. } + + let y = "".to_owned(); + let z = y + "..."; //~ERROR you add something to a string. + + assert_eq!(&x, &z); } -- cgit 1.4.1-3-g733a5 From 52c0cf5a9d4076dfe827f33f409e0a4da5069b8b Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 15:57:50 +0200 Subject: fixed formatting --- src/strings.rs | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index 89fc18fd0c5..568b27bd355 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -18,9 +18,9 @@ declare_lint! { } declare_lint! { - pub STRING_ADD, - Allow, - "Warn on `x + ..` where x is a `String`" + pub STRING_ADD, + Allow, + "Warn on `x + ..` where x is a `String`" } #[derive(Copy, Clone)] @@ -32,26 +32,26 @@ impl LintPass for StringAdd { } fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { - if is_string(cx, left) { - if let Allow = cx.current_level(STRING_ADD_ASSIGN) { - // the string_add_assign is allow, so no duplicates - } else { - let parent = get_parent_expr(cx, e); - if let Some(ref p) = parent { - if let &ExprAssign(ref target, _) = &p.node { - // avoid duplicate matches - if is_exp_equal(target, left) { return; } - } - } - } - //TODO check for duplicates - span_lint(cx, STRING_ADD, e.span, - "you add something to a string. \ - Consider using `String::push_str()` instead.") - } - } - } + if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { + if is_string(cx, left) { + if let Allow = cx.current_level(STRING_ADD_ASSIGN) { + // the string_add_assign is allow, so no duplicates + } else { + let parent = get_parent_expr(cx, e); + if let Some(ref p) = parent { + if let &ExprAssign(ref target, _) = &p.node { + // avoid duplicate matches + if is_exp_equal(target, left) { return; } + } + } + } + //TODO check for duplicates + span_lint(cx, STRING_ADD, e.span, + "you add something to a string. \ + Consider using `String::push_str()` instead.") + } + } + } } @@ -75,7 +75,7 @@ impl LintPass for StringAddAssign { } fn is_string(cx: &Context, e: &Expr) -> bool { - let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); if let TyStruct(did, _) = ty.sty { match_def_path(cx, did.did, &["collections", "string", "String"]) } else { false } -- cgit 1.4.1-3-g733a5 From f9e851e212e08174917aa724b5e56a92d9584cdf Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 16:42:42 +0200 Subject: pulled strings passes together, added more tests --- src/lib.rs | 1 - src/strings.rs | 18 ++--------------- tests/compile-fail/strings.rs | 45 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e6703e6bb28..f788c72db3c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,7 +58,6 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box misc::ModuloOne as LintPassObject); reg.register_lint_pass(box unicode::Unicode as LintPassObject); reg.register_lint_pass(box strings::StringAdd as LintPassObject); - reg.register_lint_pass(box strings::StringAddAssign as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); diff --git a/src/strings.rs b/src/strings.rs index 568b27bd355..85e6501d336 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -28,7 +28,7 @@ pub struct StringAdd; impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD) + lint_array!(STRING_ADD, STRING_ADD_ASSIGN) } fn check_expr(&mut self, cx: &Context, e: &Expr) { @@ -50,21 +50,7 @@ impl LintPass for StringAdd { "you add something to a string. \ Consider using `String::push_str()` instead.") } - } - } -} - - -#[derive(Copy, Clone)] -pub struct StringAddAssign; - -impl LintPass for StringAddAssign { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD_ASSIGN) - } - - fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprAssign(ref target, ref src) = &e.node { + } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assign the result of adding something to this string. \ diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index e898a087d08..02ebca2fe07 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -1,9 +1,37 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(string_add_assign)] -#![deny(string_add)] -fn main() { +#[deny(string_add)] +#[allow(string_add_assign)] +fn add_only() { // ignores assignment distinction + let mut x = "".to_owned(); + + for _ in (1..3) { + x = x + "."; //~ERROR you add something to a string. + } + + let y = "".to_owned(); + let z = y + "..."; //~ERROR you add something to a string. + + assert_eq!(&x, &z); +} + +#[deny(string_add_assign)] +fn add_assign_only() { + let mut x = "".to_owned(); + + for _ in (1..3) { + x = x + "."; //~ERROR you assign the result of adding something to this string. + } + + let y = "".to_owned(); + let z = y + "..."; + + assert_eq!(&x, &z); +} + +#[deny(string_add, string_add_assign)] +fn both() { let mut x = "".to_owned(); for _ in (1..3) { @@ -15,3 +43,14 @@ fn main() { assert_eq!(&x, &z); } + +fn main() { + add_only(); + add_assign_only(); + both(); + + // the add is only caught for String + let mut x = 1; + x = x + 1; + assert_eq!(2, x); +} -- cgit 1.4.1-3-g733a5 From 9e786d3956c5500af94c9ae3eddb5fc7e58b0c67 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 16:50:43 +0200 Subject: added `string_add` to `clippy` lint group --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index f788c72db3c..436ba6cbf80 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,6 +84,7 @@ pub fn plugin_registrar(reg: &mut Registry) { unicode::ZERO_WIDTH_SPACE, unicode::NON_ASCII_LITERAL, strings::STRING_ADD_ASSIGN, + strings::STRING_ADD, returns::NEEDLESS_RETURN, misc::MODULO_ONE, methods::OPTION_UNWRAP_USED, -- cgit 1.4.1-3-g733a5 From a00270c5b14013c4129fedfe076d4fea227f6102 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 21:17:21 +0200 Subject: grammar --- src/strings.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index 85e6501d336..50971962f90 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -13,14 +13,14 @@ use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, - Warn, - "Warn on `x = x + ..` where x is a `String`" + Allow, + "expressions of the form `x = x + ..` where x is a `String`" } declare_lint! { pub STRING_ADD, Allow, - "Warn on `x + ..` where x is a `String`" + "expressions of the form on `x + ..` where x is a `String`" } #[derive(Copy, Clone)] @@ -47,14 +47,14 @@ impl LintPass for StringAdd { } //TODO check for duplicates span_lint(cx, STRING_ADD, e.span, - "you add something to a string. \ + "you added something to a string. \ Consider using `String::push_str()` instead.") } } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, - "you assign the result of adding something to this string. \ - Consider using `String::push_str()` instead") + "you assigned the result of adding something to this string. \ + Consider using `String::push_str()` instead.") } } } -- cgit 1.4.1-3-g733a5 From f67175b4cd4c10366950fc0af7b46c85967e51d7 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 12 Aug 2015 21:39:42 +0200 Subject: fixed error messages in compile-fail test --- tests/compile-fail/strings.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 02ebca2fe07..680ebb73dea 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -7,11 +7,11 @@ fn add_only() { // ignores assignment distinction let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you add something to a string. + x = x + "."; //~ERROR you added something to a string. } let y = "".to_owned(); - let z = y + "..."; //~ERROR you add something to a string. + let z = y + "..."; //~ERROR you added something to a string. assert_eq!(&x, &z); } @@ -21,7 +21,7 @@ fn add_assign_only() { let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you assign the result of adding something to this string. + x = x + "."; //~ERROR you assigned the result of adding something to this string. } let y = "".to_owned(); @@ -35,11 +35,11 @@ fn both() { let mut x = "".to_owned(); for _ in (1..3) { - x = x + "."; //~ERROR you assign the result of adding something to this string. + x = x + "."; //~ERROR you assigned the result of adding something to this string. } let y = "".to_owned(); - let z = y + "..."; //~ERROR you add something to a string. + let z = y + "..."; //~ERROR you added something to a string. assert_eq!(&x, &z); } -- cgit 1.4.1-3-g733a5 From 6aa36e9deb9191ae8414b433d49c71ac37475cea Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 14:22:05 +0200 Subject: initial addition and subtraction for bytes and ints --- src/const.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/const.rs b/src/const.rs index cef2cd7f9fc..bc53c1062dc 100644 --- a/src/const.rs +++ b/src/const.rs @@ -222,11 +222,75 @@ fn neg_float_str(s: &InternedString) -> Cow<'static, str> { } } +fn is_negative(ty: LitIntType) -> bool { + match ty { + SignedIntLit(_, sign) | UnsuffixedIntLit(sign) => sign == Minus, + UnsignedIntLit(_) => false, + } +} + +fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option(LitIntType) { + match (l, r) { + (SignedIntLit(lty, _), SignedIntLit(rty, _)) => if lty == rty { + Some(SignedIntLit(lty, s)) } else { None }, + (UnsignedIntLit(lty), UnsignedIntLit(rty)) => + if Sign == Plus && lty == rty { + Some(UnsignedIntLit(lty)) + } else { None }, + (UnsuffixedIntLit(_), UnsuffixedIntLit(_)) => UnsuffixedIntLit(s), + (SignedIntLit(lty, _), UnsuffixedIntLit(_)) => SignedIntLit(lty, s), + (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => if rs == Plus { + Some(UnsignedIntLit(lty)) } else { None }, + (UnsuffixedIntLit(_), SignedIntLit(rty, _)) => SignedIntLit(rty, s), + (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => if ls == Plus { + Some(UnsignedIntLit(rty)) } else { None }, + _ => None, + } +} + fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { match op.node { - //BiAdd, - //BiSub, + BiAdd => constant_binop_apply(cx, left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => + l8.checked_add(r8).map(|v| ConstantByte(v)), + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + if ln == rn { + unify_int_type(lty, rty, if ln { Minus } else { Plus }) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))) + } else { + if ln { + add_neg_int(r64, rty, l64, lty) + } else { + add_neg_int(l64, lty, r64, rty) + } + } + }, + // TODO: float + _ => None + }), + BiSub => constant_binop_apply(cx, left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { + None } else { Some(ConstantByte(l8 - r8)) }, + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + match (ln, rn) { + (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), + (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), + (true, false) => unify_int_type(lty, rty, Minus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + (false, true) => unify_int_type(lty, rty, Plus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + } + }, + _ => None, + }), //BiMul, //BiDiv, //BiRem, @@ -247,6 +311,21 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) } } +fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> + Some(Constant) { + if neg > pos { + unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) + } else { + unify_int_type(nty, pty, Plus).map(|ty| ConstantInt(pos - neg, ty)) + } +} + +fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: Bool) -> + Option<Constant> { + unify_int_type(lty, rty, if neg { Minus } else { Plus }).and_then( + |ty| l64.checked_sub(r64).map(|v| ConstantInt(v, ty))) +} + fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) -> Option<Constant> where F: FnMut(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { -- cgit 1.4.1-3-g733a5 From e03b71606ba7682e46603302a679ecdc30ce8373 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 10:32:35 +0200 Subject: update_lints: add a check mode for travis runs --- .travis.yml | 1 + README.md | 4 +-- src/strings.rs | 8 +++--- util/update_lints.py | 77 ++++++++++++++++++++++++++++++++-------------------- 4 files changed, 54 insertions(+), 36 deletions(-) mode change 100644 => 100755 util/update_lints.py diff --git a/.travis.yml b/.travis.yml index 0f9d6128eb8..e14785c9211 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ rust: nightly sudo: false script: + - python util/update_lints.py -c - cargo build - cargo test diff --git a/README.md b/README.md index 5f9f59c31e5..f6b65b952d4 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (wh result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` -string_add | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -string_add_assign | allow | expressions of the form `x = x + ..` where x is a `String` +string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead string_to_string | warn | calling `String.to_string()` which is a no-op toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) zero_width_space | deny | using a zero-width space in a string literal, which is confusing diff --git a/src/strings.rs b/src/strings.rs index 84512dfe7f8..7b7bab49b5d 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -14,13 +14,13 @@ use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, Allow, - "expressions of the form `x = x + ..` where x is a `String`" + "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" } declare_lint! { pub STRING_ADD, Allow, - "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" + "using `x + ..` where x is a `String`; suggests using `push_str()` instead" } #[derive(Copy, Clone)] @@ -48,13 +48,13 @@ impl LintPass for StringAdd { //TODO check for duplicates span_lint(cx, STRING_ADD, e.span, "you added something to a string. \ - Consider using `String::push_str()` instead.") + Consider using `String::push_str()` instead") } } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ - Consider using `String::push_str()` instead.") + Consider using `String::push_str()` instead") } } } diff --git a/util/update_lints.py b/util/update_lints.py old mode 100644 new mode 100755 index c2a9e08c993..ed26637059f --- a/util/update_lints.py +++ b/util/update_lints.py @@ -1,5 +1,7 @@ +#!/usr/bin/env python # Generate a Markdown table of all lints, and put it in README.md. # With -n option, only print the new table to stdout. +# With -c option, print a warning and set exit status to 1 if a file would be changed. import os import re @@ -31,27 +33,27 @@ def collect(lints, fn): desc.replace('\\"', '"'))) -def write_tbl(lints, fp): +def gen_table(lints): """Write lint table in Markdown format.""" # first and third column widths w_name = max(len(l[1]) for l in lints) w_desc = max(len(l[3]) for l in lints) # header and underline - fp.write('%-*s | default | meaning\n' % (w_name, 'name')) - fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) + yield '%-*s | default | meaning\n' % (w_name, 'name') + yield '%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc) # one table row per lint for (_, name, default, meaning) in sorted(lints, key=lambda l: l[1]): - fp.write('%-*s | %-7s | %s\n' % (w_name, name, default, meaning)) + yield '%-*s | %-7s | %s\n' % (w_name, name, default, meaning) -def write_group(lints, fp): +def gen_group(lints): """Write lint group (list of all lints in the form module::NAME).""" for (module, name, _, _) in sorted(lints): - fp.write(' %s::%s,\n' % (module, name.upper())) + yield ' %s::%s,\n' % (module, name.upper()) def replace_region(fn, region_start, region_end, callback, - replace_start=True): + replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. A callback is called to write the new region. If `replace_start` is true, @@ -63,24 +65,32 @@ def replace_region(fn, region_start, region_end, callback, lines = list(fp) # replace old region with new region - with open(fn, 'w') as fp: - in_old_region = False - for line in lines: - if in_old_region: - if re.search(region_end, line): - in_old_region = False - fp.write(line) - elif re.search(region_start, line): - if not replace_start: - fp.write(line) - # old region starts here - in_old_region = True - callback(fp) - else: - fp.write(line) - - -def main(print_only=False): + new_lines = [] + in_old_region = False + for line in lines: + if in_old_region: + if re.search(region_end, line): + in_old_region = False + new_lines.extend(callback()) + new_lines.append(line) + elif re.search(region_start, line): + if not replace_start: + new_lines.append(line) + # old region starts here + in_old_region = True + else: + new_lines.append(line) + + # write back to file + if write_back: + with open(fn, 'w') as fp: + fp.writelines(new_lines) + + # if something changed, return true + return lines != new_lines + + +def main(print_only=False, check=False): lints = [] # check directory @@ -95,16 +105,23 @@ def main(print_only=False): collect(lints, os.path.join(root, fn)) if print_only: - write_tbl(lints, sys.stdout) + sys.stdout.writelines(gen_table(lints)) return # replace table in README.md - replace_region('README.md', r'^name +\|', '^$', lambda fp: write_tbl(lints, fp)) + changed = replace_region('README.md', r'^name +\|', '^$', + lambda: gen_table(lints), + write_back=not check) # same for "clippy" lint collection - replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', - lambda fp: write_group(lints, fp), replace_start=False) + changed |= replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + lambda: gen_group(lints), replace_start=False, + write_back=not check) + + if check and changed: + print('Please run util/update_lints.py to regenerate lints lists.') + return 1 if __name__ == '__main__': - main(print_only='-n' in sys.argv) + sys.exit(main(print_only='-n' in sys.argv, check='-c' in sys.argv)) -- cgit 1.4.1-3-g733a5 From 8a98736f51249befe9d4a4412619490f6cecfa54 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 09:44:03 +0200 Subject: spelling fix, rework needless_bool with snippet (fixes #150) --- src/needless_bool.rs | 40 +++++++++++++++++++++++-------------- tests/compile-fail/eq_op.rs | 2 +- tests/compile-fail/needless_bool.rs | 8 ++++---- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 6a4a55aeda5..2a4ed50b93d 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -10,7 +10,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; -use utils::{de_p, span_lint}; +use utils::{de_p, span_lint, snippet}; declare_lint! { pub NEEDLESS_BOOL, @@ -28,20 +28,30 @@ impl LintPass for NeedlessBool { } fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { + if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (Option::Some(true), Option::Some(true)) => { + (Some(true), Some(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return true"); }, - (Option::Some(true), Option::Some(false)) => { + "this if-then-else expression will always return true"); }, + (Some(false), Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if statement to its predicate"); }, - (Option::Some(false), Option::Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if statement to `!` + its predicate"); }, - (Option::Some(false), Option::Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return false"); }, + "this if-then-else expression will always return false"); }, + (Some(true), Some(false)) => { + let pred_snip = snippet(cx, pred.span, ".."); + let hint = if pred_snip == ".." { "its predicate".into() } else { + format!("`{}`", pred_snip) + }; + span_lint(cx, NEEDLESS_BOOL, e.span, &format!( + "you can reduce this if-then-else expression to just {}", hint)); + }, + (Some(false), Some(true)) => { + let pred_snip = snippet(cx, pred.span, ".."); + let hint = if pred_snip == ".." { "`!` and its predicate".into() } else { + format!("`!{}`", pred_snip) + }; + span_lint(cx, NEEDLESS_BOOL, e.span, &format!( + "you can reduce this if-then-else expression to just {}", hint)); + }, _ => () } } @@ -51,14 +61,14 @@ impl LintPass for NeedlessBool { fn fetch_bool_block(block: &Block) -> Option<bool> { if block.stmts.is_empty() { block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) - } else { Option::None } + } else { None } } fn fetch_bool_expr(expr: &Expr) -> Option<bool> { match &expr.node { &ExprBlock(ref block) => fetch_bool_block(block), &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { - Option::Some(value) } else { Option::None }, - _ => Option::None + Some(value) } else { None }, + _ => None } } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 298132013a9..8f61a11aa08 100755 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -16,7 +16,7 @@ fn main() { 1.5 < 1.5; //~ERROR equal expressions 1u64 >= 1u64; //~ERROR equal expressions - // casts, methods, parenthesis + // casts, methods, parentheses (1 as u64) & (1 as u64); //~ERROR equal expressions 1 ^ ((((((1)))))); //~ERROR equal expressions id((1)) | id(1); //~ERROR equal expressions diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index 6016f79ab03..39fdf6353fd 100755 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -4,9 +4,9 @@ #[deny(needless_bool)] fn main() { let x = true; - if x { true } else { true }; //~ERROR your if-then-else expression will always return true - if x { false } else { false }; //~ERROR your if-then-else expression will always return false - if x { true } else { false }; //~ERROR you can reduce your if statement to its predicate - if x { false } else { true }; //~ERROR you can reduce your if statement to `!` + its predicate + if x { true } else { true }; //~ERROR this if-then-else expression will always return true + if x { false } else { false }; //~ERROR this if-then-else expression will always return false + if x { true } else { false }; //~ERROR you can reduce this if-then-else expression to just `x` + if x { false } else { true }; //~ERROR you can reduce this if-then-else expression to just `!x` if x { x } else { false }; // would also be questionable, but we don't catch this yet } -- cgit 1.4.1-3-g733a5 From b456e5fbd22e76ea064abad1e4ce9ed62b3454c6 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 19:30:33 +0530 Subject: Don't run `cargo build` (fixes #156) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e14785c9211..bd997a0c22e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,4 @@ sudo: false script: - python util/update_lints.py -c - - cargo build - cargo test -- cgit 1.4.1-3-g733a5 From 957840363802eb817e1285f0879c8474caff465d Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 15:36:31 +0200 Subject: new lint: looping over x.iter() or x.iter_mut() (fixes #157) --- README.md | 1 + src/attrs.rs | 2 +- src/lib.rs | 1 + src/loops.rs | 35 +++++++++++++++++++++++++++++------ src/types.rs | 2 +- tests/compile-fail/for_loop.rs | 10 ++++++++-- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f6b65b952d4..dd7d0158f03 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ cmp_nan | deny | comparisons to NAN (which will always return fa cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` diff --git a/src/attrs.rs b/src/attrs.rs index ca5b6c55ced..ef3320d2543 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -64,7 +64,7 @@ fn is_relevant_trait(item: &TraitItem) -> bool { } fn is_relevant_block(block: &Block) -> bool { - for stmt in block.stmts.iter() { + for stmt in &block.stmts { match stmt.node { StmtDecl(_, _) => return true, StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { diff --git a/src/lib.rs b/src/lib.rs index 4c29b8f1b79..7cb2877b2fd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,7 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, + loops::EXPLICIT_ITER_LOOP, loops::NEEDLESS_RANGE_LOOP, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, diff --git a/src/loops.rs b/src/loops.rs index b406bc67961..bfb5ad6861d 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -3,25 +3,29 @@ use syntax::ast::*; use syntax::visit::{Visitor, walk_expr}; use std::collections::HashSet; -use utils::{span_lint, get_parent_expr}; +use utils::{snippet, span_lint, get_parent_expr}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, "for-looping over a range of indices where an iterator over items would do" } +declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, + "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP) + lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) { - // the var must be a single name - if let PatIdent(_, ref ident, _) = pat.node { - // the iteratee must be a range literal - if let ExprRange(_, _) = arg.node { + // check for looping over a range and then indexing a sequence with it + // -> the iteratee must be a range literal + if let ExprRange(_, _) = arg.node { + // the var must be a single name + if let PatIdent(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, var: ident.node.name, indexed: HashSet::new(), nonindex: false }; walk_expr(&mut visitor, body); @@ -43,6 +47,25 @@ impl LintPass for LoopsPass { } } } + + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x + if let ExprMethodCall(ref method, _, ref args) = arg.node { + // just the receiver, no arguments to iter() or iter_mut() + if args.len() == 1 { + let method_name = method.node.name.as_str(); + if method_name == "iter" { + let object = snippet(cx, args[0].span, "_"); + span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( + "it is more idiomatic to loop over `&{}` instead of `{}.iter()`", + object, object)); + } else if method_name == "iter_mut" { + let object = snippet(cx, args[0].span, "_"); + span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( + "it is more idiomatic to loop over `&mut {}` instead of `{}.iter_mut()`", + object, object)); + } + } + } } } } diff --git a/src/types.rs b/src/types.rs index ad7b767d95e..53d8850c59d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -67,7 +67,7 @@ impl LintPass for TypePass { let dlists = [vec!["std","collections","linked_list","LinkedList"], vec!["std","collections","linked_list","LinkedList"], vec!["collections","linked_list","LinkedList"]]; - for path in dlists.iter() { + for path in &dlists { if match_ty_unwrap(ty, &path[..]).is_some() { span_help_and_lint(cx, LINKEDLIST, ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 318e6fc8588..550f9869291 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -1,9 +1,9 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(needless_range_loop)] +#[deny(needless_range_loop, explicit_iter_loop)] fn main() { - let vec = vec![1, 2, 3, 4]; + let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; for i in 0..vec.len() { //~ERROR the loop variable `i` is only used to index `vec`. println!("{}", vec[i]); @@ -14,4 +14,10 @@ fn main() { for i in 0..vec.len() { // not an error, indexing more than one variable println!("{} {}", vec[i], vec2[i]); } + + for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec` + for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec` + + for _v in &vec { } // these are fine + for _v in &mut vec { } // these are fine } -- cgit 1.4.1-3-g733a5 From 5eab397e7c9840bd01f9ca165428e8eb4156cdc4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 19:58:11 +0530 Subject: Some fixes from dogfooding clippy --- src/eq_op.rs | 1 + src/lib.rs | 2 +- src/lifetimes.rs | 2 +- src/loops.rs | 4 ++-- src/utils.rs | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 495696b810c..0b7511e7dbd 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,3 +1,4 @@ +#![allow(redundant_closure)] // FIXME (#116) use rustc::lint::*; use syntax::ast::*; use syntax::ast_util as ast_util; diff --git a/src/lib.rs b/src/lib.rs index 7cb2877b2fd..9135ecaca6c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] -#![allow(unused_imports)] +#![allow(unused_imports, unknown_lints)] #[macro_use] extern crate syntax; diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 644537f9be1..25be8874691 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -103,7 +103,7 @@ fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { } /// Number of unique lifetimes in the given vector. -fn unique_lifetimes(lts: &Vec<RefLt>) -> usize { +fn unique_lifetimes(lts: &[RefLt]) -> usize { lts.iter().collect::<HashSet<_>>().len() } diff --git a/src/loops.rs b/src/loops.rs index bfb5ad6861d..937e95970ef 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -31,7 +31,7 @@ impl LintPass for LoopsPass { walk_expr(&mut visitor, body); // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let indexed = visitor.indexed.into_iter().next().unwrap(); + let indexed = visitor.indexed.into_iter().next().expect("Len was nonzero, but no contents found"); if visitor.nonindex { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is used to index `{}`. Consider using \ @@ -72,7 +72,7 @@ impl LintPass for LoopsPass { /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. -fn recover_for_loop<'a>(expr: &'a Expr) -> Option<(&'a Pat, &'a Expr, &'a Expr)> { +fn recover_for_loop<'a>(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { if_let_chain! { [ let ExprMatch(ref iterexpr, ref arms, _) = expr.node, diff --git a/src/utils.rs b/src/utils.rs index 220dc6215fd..c54a7f56f7e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -86,7 +86,7 @@ pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, } /// return the base type for references and raw pointers -pub fn walk_ptrs_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { +pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), _ => ty -- cgit 1.4.1-3-g733a5 From c2bdc8571552ad74af18f71e8d026846947615e4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 19:59:14 +0530 Subject: oh the irony --- src/lifetimes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 25be8874691..03b4de6c948 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -130,15 +130,15 @@ impl RefVisitor { impl<'v> Visitor<'v> for RefVisitor { // for lifetimes of references - fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { + fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &Option<Lifetime>) { self.record(lifetime); } // for lifetimes as parameters of generics - fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) { self.record(&Some(*lifetime)); } // for lifetime bounds; the default impl calls visit_lifetime_ref - fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { } + fn visit_lifetime_bound(&mut self, _: &Lifetime) { } } -- cgit 1.4.1-3-g733a5 From 09db7f3fee25684ab0783ae80595fcc227ad0074 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 20:11:51 +0530 Subject: fix --- src/collapsible_if.rs | 6 +++++- src/loops.rs | 5 ++--- src/misc.rs | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index f0f53622c47..be34458e0dc 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -45,8 +45,12 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if in_macro(cx, info) { return; } if let ExprIf(ref check, ref then, None) = e.node { - if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), ..}) = + if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = single_stmt_of_block(then) { + if e.span.expn_id != sp.expn_id { + return; + } + cx.sess().note(&format!("{:?} -- {:?}", e.span, sp)); span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", &format!("try\nif {} && {} {}", diff --git a/src/loops.rs b/src/loops.rs index 937e95970ef..74015bdc6be 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -72,13 +72,12 @@ impl LintPass for LoopsPass { /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. -fn recover_for_loop<'a>(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { +fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { if_let_chain! { [ let ExprMatch(ref iterexpr, ref arms, _) = expr.node, let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1, - arms.len() == 1 && arms[0].guard.is_none(), + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), let ExprLoop(ref block, _) = arms[0].body.node, block.stmts.is_empty(), let Some(ref loopexpr) = block.expr, diff --git a/src/misc.rs b/src/misc.rs index 6c9a7d92ce8..7372bfed6c5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -73,7 +73,7 @@ impl LintPass for TopLevelRefPass { } fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - for ref arg in decl.inputs.iter() { + for ref arg in &decl.inputs { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { span_lint(cx, TOPLEVEL_REF_ARG, -- cgit 1.4.1-3-g733a5 From 49e51fe65a7762841aa7421b4c643b042c4fe4c6 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 13 Aug 2015 17:24:47 +0200 Subject: lifetimes: try to fix w.r.t. lifetimes from parent scopes (fixes #162) --- src/lifetimes.rs | 60 ++++++++++++++++++++++++++++++++++------- tests/compile-fail/lifetimes.rs | 7 +++-- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 03b4de6c948..c333f04ab44 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -18,14 +18,23 @@ impl LintPass for LifetimePass { lint_array!(NEEDLESS_LIFETIMES) } - fn check_fn(&mut self, cx: &Context, kind: FnKind, decl: &FnDecl, - _: &Block, span: Span, _: NodeId) { - if in_external_macro(cx, span) { - return; + fn check_item(&mut self, cx: &Context, item: &Item) { + if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { + check_fn_inner(cx, decl, None, &generics.lifetimes, item.span); } - if could_use_elision(kind, decl) { - span_lint(cx, NEEDLESS_LIFETIMES, span, - "explicit lifetimes given in parameter types where they could be elided"); + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if let MethodImplItem(ref sig, _) = item.node { + check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + &sig.generics.lifetimes, item.span); + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if let MethodTraitItem(ref sig, _) = item.node { + check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + &sig.generics.lifetimes, item.span); } } } @@ -39,10 +48,34 @@ enum RefLt { } use self::RefLt::*; -fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { +fn check_fn_inner(cx: &Context, decl: &FnDecl, slf: Option<&ExplicitSelf>, + named_lts: &[LifetimeDef], span: Span) { + if in_external_macro(cx, span) { + return; + } + if could_use_elision(decl, slf, named_lts) { + span_lint(cx, NEEDLESS_LIFETIMES, span, + "explicit lifetimes given in parameter types where they could be elided"); + } +} + +fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, + named_lts: &[LifetimeDef]) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT // * output references, exactly one input reference with same LT + // All lifetimes must be unnamed, 'static or defined without bounds on the + // level of the current item. + + // check named LTs + let mut allowed_lts = HashSet::new(); + for lt in named_lts { + if lt.bounds.is_empty() { + allowed_lts.insert(Named(lt.lifetime.name)); + } + } + allowed_lts.insert(Unnamed); + allowed_lts.insert(Static); // these will collect all the lifetimes for references in arg/return types let mut input_visitor = RefVisitor(Vec::new()); @@ -50,8 +83,8 @@ fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { // extract lifetime in "self" argument for methods (there is a "self" argument // in func.inputs, but its type is TyInfer) - if let FnKind::FkMethod(_, sig, _) = kind { - match sig.explicit_self.node { + if let Some(slf) = slf { + match slf.node { SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), _ => { } @@ -69,6 +102,13 @@ fn could_use_elision(kind: FnKind, func: &FnDecl) -> bool { let input_lts = input_visitor.into_vec(); let output_lts = output_visitor.into_vec(); + // check for lifetimes from higher scopes + for lt in input_lts.iter().chain(output_lts.iter()) { + if !allowed_lts.contains(lt) { + return false; + } + } + // no input lifetimes? easy case! if input_lts.is_empty() { return false; diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 36daa69fb31..7f463ec70b4 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -31,11 +31,13 @@ fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } type Ref<'r> = &'r u8; -fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } +fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } // no error, same lifetime on two params -fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } +fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } //~^ERROR explicit lifetimes given +fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounded lifetime + struct X { x: u8, } @@ -68,6 +70,7 @@ fn main() { let _ = deep_reference_3(&1, 2); lifetime_param_1(&1, &2); lifetime_param_2(&1, &2); + lifetime_param_3(&1, &2); let foo = X { x: 1 }; foo.self_and_out(); -- cgit 1.4.1-3-g733a5 From 485960a00cba610dd0d00d6cd1a104f0797759b7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 21:07:19 +0530 Subject: Add dogfood script --- util/dogfood.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 util/dogfood.sh diff --git a/util/dogfood.sh b/util/dogfood.sh new file mode 100644 index 00000000000..1fa091c9f39 --- /dev/null +++ b/util/dogfood.sh @@ -0,0 +1 @@ +rm -rf target* && cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 3cf5c36296d3f6b2203109c6b1757c83a55f09f0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 21:10:45 +0530 Subject: Address review comments, move to travis --- .travis.yml | 1 + src/lifetimes.rs | 6 +++--- tests/compile-fail/lifetimes.rs | 28 +++++++--------------------- util/dogfood.sh | 5 ++++- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index bd997a0c22e..7eaa61c5572 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,4 @@ sudo: false script: - python util/update_lints.py -c - cargo test + - bash util/dogfood.sh diff --git a/src/lifetimes.rs b/src/lifetimes.rs index c333f04ab44..c3c915ea777 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -170,15 +170,15 @@ impl RefVisitor { impl<'v> Visitor<'v> for RefVisitor { // for lifetimes of references - fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &Option<Lifetime>) { + fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { self.record(lifetime); } // for lifetimes as parameters of generics - fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) { + fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { self.record(&Some(*lifetime)); } // for lifetime bounds; the default impl calls visit_lifetime_ref - fn visit_lifetime_bound(&mut self, _: &Lifetime) { } + fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { } } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 7f463ec70b4..287a8199d2c 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(needless_lifetimes)] - +#![allow(dead_code)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~^ERROR explicit lifetimes given @@ -54,27 +54,13 @@ impl X { fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params } +struct Foo<'a>(&'a u8); + +impl<'a> Foo<'a> { + fn self_shared_lifetime(&self, _: &'a u8) {} // no error, lifetime 'a not defined in method + fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {} // no error, bounds exist +} static STATIC: u8 = 1; fn main() { - distinct_lifetimes(&1, &2, 3); - distinct_and_static(&1, &2, &STATIC); - same_lifetime_on_input(&1, &2); - only_static_on_input(&1, &2, &STATIC); - in_and_out(&1, 2); - multiple_in_and_out_1(&1, &2); - multiple_in_and_out_2(&1, &2); - in_static_and_out(&1, &STATIC); - let _ = deep_reference_1(&1, &2); - let _ = deep_reference_2(Ok(&1)); - let _ = deep_reference_3(&1, 2); - lifetime_param_1(&1, &2); - lifetime_param_2(&1, &2); - lifetime_param_3(&1, &2); - - let foo = X { x: 1 }; - foo.self_and_out(); - foo.self_and_in_out(&1); - foo.distinct_self_and_in(&1); - foo.self_and_same_in(&1); } diff --git a/util/dogfood.sh b/util/dogfood.sh index 1fa091c9f39..51dd465a25d 100644 --- a/util/dogfood.sh +++ b/util/dogfood.sh @@ -1 +1,4 @@ -rm -rf target* && cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy \ No newline at end of file +rm -rf target*/*so +cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy || exit 1 +rm -rf target_recur + -- cgit 1.4.1-3-g733a5 From 83487c060ff64498fb9a3eb472ce71af1d26fe89 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 12 Aug 2015 16:44:14 +0530 Subject: Add trim_multiline utility (fixes #139) --- src/collapsible_if.rs | 4 ++-- src/lib.rs | 1 + src/misc.rs | 4 ++-- src/utils.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index be34458e0dc..8a41f208938 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -18,7 +18,7 @@ use rustc::middle::def::*; use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned, ExpnInfo}; -use utils::{in_macro, span_help_and_lint, snippet}; +use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; declare_lint! { pub COLLAPSIBLE_IF, @@ -55,7 +55,7 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { "this if statement can be collapsed", &format!("try\nif {} && {} {}", check_to_string(cx, check), check_to_string(cx, check_inner), - snippet(cx, content.span, ".."))); + snippet_block(cx, content.span, ".."))); } } } diff --git a/src/lib.rs b/src/lib.rs index 9135ecaca6c..01a2d65606c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] +#![feature(str_split_at)] #![allow(unused_imports, unknown_lints)] #[macro_use] diff --git a/src/misc.rs b/src/misc.rs index 7372bfed6c5..861e4a73dd2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,7 +7,7 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; -use utils::{match_path, snippet, span_lint, span_help_and_lint, walk_ptrs_ty}; +use utils::{match_path, snippet, snippet_block, span_lint, span_help_and_lint, walk_ptrs_ty}; /// Handles uncategorized lints /// Currently handles linting of if-let-able matches @@ -37,7 +37,7 @@ impl LintPass for MiscPass { // an enum is extended. So we only consider cases where a `_` wildcard is used if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { - let body_code = snippet(cx, arms[0].body.span, ".."); + let body_code = snippet_block(cx, arms[0].body.span, ".."); let suggestion = if let ExprBlock(_) = arms[0].body.node { body_code.into_owned() } else { diff --git a/src/utils.rs b/src/utils.rs index c54a7f56f7e..5b9c995589b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -51,6 +51,35 @@ pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) } +/// convert a span (from a block) to a code snippet if available, otherwise use default, e.g. +/// `snippet(cx, expr.span, "..")` +/// This trims the code of indentation, except for the first line +/// Use it for blocks or block-like things which need to be printed as such +pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { + let snip = snippet(cx, span, default); + trim_multiline(snip, true) +} + +/// Trim indentation from a multiline string +/// with possibility of ignoring the first line +pub fn trim_multiline<'a>(s: Cow<'a, str>, ignore_first: bool) -> Cow<'a, str> { + let x = s.lines().skip(ignore_first as usize) + .map(|l| l.char_indices() + .find(|&(_,x)| x != ' ') + .unwrap_or((l.len(),' ')).0) + .min().unwrap_or(0); + if x > 0 { + Cow::Owned(s.lines().enumerate().map(|(i,l)| if ignore_first && i==0 { + l + } else { + l.split_at(x).1 + }).collect::<Vec<_>>() + .join("\n")) + } else { + s + } +} + /// get a parent expr if any – this is useful to constrain a lint pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { let map = &cx.tcx.map; -- cgit 1.4.1-3-g733a5 From fbbb44d93bb566d5b3346b180a659ebdcd815fe5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 13:27:30 +0530 Subject: Handle tabs --- src/utils.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 5b9c995589b..3be6993b759 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -63,10 +63,16 @@ pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, /// Trim indentation from a multiline string /// with possibility of ignoring the first line pub fn trim_multiline<'a>(s: Cow<'a, str>, ignore_first: bool) -> Cow<'a, str> { + let s = trim_multiline_inner(s, ignore_first, ' '); + let s = trim_multiline_inner(s, ignore_first, '\t'); + trim_multiline_inner(s, ignore_first, ' ') +} + +fn trim_multiline_inner<'a>(s: Cow<'a, str>, ignore_first: bool, ch: char) -> Cow<'a, str> { let x = s.lines().skip(ignore_first as usize) .map(|l| l.char_indices() - .find(|&(_,x)| x != ' ') - .unwrap_or((l.len(),' ')).0) + .find(|&(_,x)| x != ch) + .unwrap_or((l.len(), ch)).0) .min().unwrap_or(0); if x > 0 { Cow::Owned(s.lines().enumerate().map(|(i,l)| if ignore_first && i==0 { -- cgit 1.4.1-3-g733a5 From f4b5d215332da92256bcc4d0c4b9f8b7ef6d6f72 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 15:46:00 +0200 Subject: added a few unit tests to trim_multiline --- tests/trim_multiline.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/trim_multiline.rs diff --git a/tests/trim_multiline.rs b/tests/trim_multiline.rs new file mode 100644 index 00000000000..988e5d1012f --- /dev/null +++ b/tests/trim_multiline.rs @@ -0,0 +1,38 @@ +/// test the multiline-trim function +#[allow(plugin_as_library)] +extern crate clippy; + +use clippy::utils::trim_multiline; + +#[test] +fn test_single_line() { + assert_eq!("", trim_multiline("".into(), false)); + assert_eq!("...", trim_multiline("...".into(), false)); + assert_eq!("...", trim_multiline(" ...".into(), false)); + assert_eq!("...", trim_multiline("\t...".into(), false)); + assert_eq!("...", trim_multiline("\t\t...".into(), false)); +} + +#[test] +fn test_block() { + assert_eq!("\ +if x { + y +} else { + z +}", trim_multiline(" if x { + y + } else { + z + }".into(), false)); + assert_eq!("\ +if x { +\ty +} else { +\tz +}", trim_multiline(" if x { + \ty + } else { + \tz + }".into(), false)); +} -- cgit 1.4.1-3-g733a5 From dece5a6cb53248d67a761b8bd94e47cef776fcd6 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 13 Aug 2015 15:48:48 +0200 Subject: added empty line test --- tests/trim_multiline.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/trim_multiline.rs b/tests/trim_multiline.rs index 988e5d1012f..e29ee4922cd 100644 --- a/tests/trim_multiline.rs +++ b/tests/trim_multiline.rs @@ -36,3 +36,19 @@ if x { \tz }".into(), false)); } + +#[test] +fn test_empty_line() { + assert_eq!("\ +if x { + y + +} else { + z +}", trim_multiline(" if x { + y + + } else { + z + }".into(), false)); +} -- cgit 1.4.1-3-g733a5 From 5ce8e7ba85fa50e067a5262fccd130e071b679fb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 19:29:12 +0530 Subject: trim_multiline: ignore empty lines --- src/utils.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 3be6993b759..490d2f6d1f6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -70,12 +70,15 @@ pub fn trim_multiline<'a>(s: Cow<'a, str>, ignore_first: bool) -> Cow<'a, str> { fn trim_multiline_inner<'a>(s: Cow<'a, str>, ignore_first: bool, ch: char) -> Cow<'a, str> { let x = s.lines().skip(ignore_first as usize) - .map(|l| l.char_indices() - .find(|&(_,x)| x != ch) - .unwrap_or((l.len(), ch)).0) + .filter_map(|l| { if l.len() > 0 { // ignore empty lines + Some(l.char_indices() + .find(|&(_,x)| x != ch) + .unwrap_or((l.len(), ch)).0) + } else {None}}) .min().unwrap_or(0); if x > 0 { - Cow::Owned(s.lines().enumerate().map(|(i,l)| if ignore_first && i==0 { + Cow::Owned(s.lines().enumerate().map(|(i,l)| if (ignore_first && i == 0) || + l.len() == 0 { l } else { l.split_at(x).1 -- cgit 1.4.1-3-g733a5 From 763ae1f3ae9644110f0af893c79719be00288311 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 13 Aug 2015 23:20:00 +0530 Subject: Fix dogfood --- src/utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 490d2f6d1f6..67a89b067e6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -62,13 +62,13 @@ pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, /// Trim indentation from a multiline string /// with possibility of ignoring the first line -pub fn trim_multiline<'a>(s: Cow<'a, str>, ignore_first: bool) -> Cow<'a, str> { +pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { let s = trim_multiline_inner(s, ignore_first, ' '); let s = trim_multiline_inner(s, ignore_first, '\t'); trim_multiline_inner(s, ignore_first, ' ') } -fn trim_multiline_inner<'a>(s: Cow<'a, str>, ignore_first: bool, ch: char) -> Cow<'a, str> { +fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { let x = s.lines().skip(ignore_first as usize) .filter_map(|l| { if l.len() > 0 { // ignore empty lines Some(l.char_indices() -- cgit 1.4.1-3-g733a5 From 6f8d47b411ac9c8f92e2b95251805ab6b9ec9c01 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 11:30:39 +0200 Subject: add a few words on dogfood + update_lints --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8bac03d9447..eebea413f0d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,11 @@ T-middle issues can be more involved and require verifying types. The lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. +Should you add a lint, try it on clippy itself using `util/dogfood.sh`. You may find that clippy +contains some questionable code itself! Also before making a pull request, please run +`util/update_lints.py`, which will update `lib.rs` and `README.md` with the lint declarations. Our +travis build actually checks for this. + ## Contributions Clippy welcomes contributions from everyone. -- cgit 1.4.1-3-g733a5 From 49f6eb88d32d70057cc50e259f9bd59a81aebd5f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 14:21:05 +0200 Subject: fixed false positives (at the cost of some false negatives) --- src/eta_reduction.rs | 73 +++++++++++++++++++++++++++++------------------ tests/compile-fail/eta.rs | 25 ++++++++++++---- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 484d46ddc21..e0d4182081f 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -19,41 +19,58 @@ impl LintPass for EtaPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprClosure(_, ref decl, ref blk) = expr.node { - if !blk.stmts.is_empty() { - // || {foo(); bar()}; can't be reduced here - return; - } - if let Some(ref ex) = blk.expr { - if let ExprCall(ref caller, ref args) = ex.node { - if args.len() != decl.inputs.len() { - // Not the same number of arguments, there - // is no way the closure is the same as the function - return; - } - for (ref a1, ref a2) in decl.inputs.iter().zip(args) { - if let PatIdent(_, ident, _) = a1.pat.node { - // XXXManishearth Should I be checking the binding mode here? - if let ExprPath(None, ref p) = a2.node { - if p.segments.len() != 1 { - // If it's a proper path, it can't be a local variable - return; - } - if p.segments[0].identifier != ident.node { - // The two idents should be the same - return - } - } else { + match &expr.node { + &ExprCall(_, ref args) | + &ExprMethodCall(_, _, ref args) => { + for arg in args { + check_closure(cx, &*arg) + } + }, + _ => (), + } + } +} + +fn is_adjusted(cx: &Context, e: &Expr) -> bool { + cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() +} + +fn check_closure(cx: &Context, expr: &Expr) { + if let ExprClosure(_, ref decl, ref blk) = expr.node { + if !blk.stmts.is_empty() { + // || {foo(); bar()}; can't be reduced here + return; + } + if let Some(ref ex) = blk.expr { + if let ExprCall(ref caller, ref args) = ex.node { + if args.len() != decl.inputs.len() { + // Not the same number of arguments, there + // is no way the closure is the same as the function + return; + } + if args.iter().any(|arg| is_adjusted(cx, arg)) { return; } + for (ref a1, ref a2) in decl.inputs.iter().zip(args) { + if let PatIdent(_, ident, _) = a1.pat.node { + // XXXManishearth Should I be checking the binding mode here? + if let ExprPath(None, ref p) = a2.node { + if p.segments.len() != 1 { + // If it's a proper path, it can't be a local variable + return; + } + if p.segments[0].identifier != ident.node { + // The two idents should be the same return } } else { return } + } else { + return } - span_lint(cx, REDUNDANT_CLOSURE, expr.span, - &format!("redundant closure found. Consider using `{}` in its place", - expr_to_string(caller))[..]) } + span_lint(cx, REDUNDANT_CLOSURE, expr.span, + &format!("redundant closure found. Consider using `{}` in its place", + expr_to_string(caller))[..]) } } } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 9e48ec1c3a5..bf6ecd79617 100755 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -4,18 +4,31 @@ #![deny(redundant_closure)] fn main() { - let a = |a, b| foo(a, b); + let a = Some(1u8).map(|a| foo(a)); //~^ ERROR redundant closure found. Consider using `foo` in its place - let c = |a, b| {1+2; foo}(a, b); + meta(|a| foo(a)); + //~^ ERROR redundant closure found. Consider using `foo` in its place + let c = Some(1u8).map(|a| {1+2; foo}(a)); //~^ ERROR redundant closure found. Consider using `{ 1 + 2; foo }` in its place - let d = |a, b| foo((|c, d| foo2(c,d))(a,b), b); - //~^ ERROR redundant closure found. Consider using `foo2` in its place + let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? + all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted +} + +fn meta<F>(f: F) where F: Fn(u8) { + f(1u8) } -fn foo(_: u8, _: u8) { +fn foo(_: u8) { } -fn foo2(_: u8, _: u8) -> u8 { +fn foo2(_: u8) -> u8 { 1u8 } + +fn all<X, F>(x: &[X], y: &X, f: F) -> bool +where F: Fn(&X, &X) -> bool { + x.iter().all(|e| f(e, y)) +} + +fn below(x: &u8, y: &u8) -> bool { x < y } -- cgit 1.4.1-3-g733a5 From ffda91a8c7e7fbfd3c42b57302ac04e6119d7eeb Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 14:26:57 +0200 Subject: removed String::from_str(..) to fix build with 1.4.0-nightly/2015-08-14 --- tests/compile-fail/cmp_owned.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index 5951dc1bbd7..2765da5cf23 100755 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -1,4 +1,4 @@ -#![feature(plugin, collections)] +#![feature(plugin)] #![plugin(clippy)] #[deny(cmp_owned)] @@ -13,11 +13,8 @@ fn main() { x != "foo".to_owned(); //~ERROR this creates an owned instance - #[allow(deprecated)] // for from_str - fn old_timey(x : &str) { - x != String::from_str("foo"); //~ERROR this creates an owned instance - } - old_timey(x); + // removed String::from_str(..), as it has finally been removed in 1.4.0 + // as of 2015-08-14 x != String::from("foo"); //~ERROR this creates an owned instance } -- cgit 1.4.1-3-g733a5 From 811d89a01b241c695f4a4f280fc0c959fb2712dc Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 14:26:57 +0200 Subject: removed String::from_str(..) to fix build with 1.4.0-nightly/2015-08-14 --- tests/compile-fail/cmp_owned.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index 5951dc1bbd7..2765da5cf23 100755 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -1,4 +1,4 @@ -#![feature(plugin, collections)] +#![feature(plugin)] #![plugin(clippy)] #[deny(cmp_owned)] @@ -13,11 +13,8 @@ fn main() { x != "foo".to_owned(); //~ERROR this creates an owned instance - #[allow(deprecated)] // for from_str - fn old_timey(x : &str) { - x != String::from_str("foo"); //~ERROR this creates an owned instance - } - old_timey(x); + // removed String::from_str(..), as it has finally been removed in 1.4.0 + // as of 2015-08-14 x != String::from("foo"); //~ERROR this creates an owned instance } -- cgit 1.4.1-3-g733a5 From 5d99ebec72cdedc0e76103b9a93bd9199f9be0ef Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 14:21:05 +0200 Subject: fixed false positives (at the cost of some false negatives) --- src/eta_reduction.rs | 73 +++++++++++++++++++++++++++++------------------ tests/compile-fail/eta.rs | 25 ++++++++++++---- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 484d46ddc21..e0d4182081f 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -19,41 +19,58 @@ impl LintPass for EtaPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprClosure(_, ref decl, ref blk) = expr.node { - if !blk.stmts.is_empty() { - // || {foo(); bar()}; can't be reduced here - return; - } - if let Some(ref ex) = blk.expr { - if let ExprCall(ref caller, ref args) = ex.node { - if args.len() != decl.inputs.len() { - // Not the same number of arguments, there - // is no way the closure is the same as the function - return; - } - for (ref a1, ref a2) in decl.inputs.iter().zip(args) { - if let PatIdent(_, ident, _) = a1.pat.node { - // XXXManishearth Should I be checking the binding mode here? - if let ExprPath(None, ref p) = a2.node { - if p.segments.len() != 1 { - // If it's a proper path, it can't be a local variable - return; - } - if p.segments[0].identifier != ident.node { - // The two idents should be the same - return - } - } else { + match &expr.node { + &ExprCall(_, ref args) | + &ExprMethodCall(_, _, ref args) => { + for arg in args { + check_closure(cx, &*arg) + } + }, + _ => (), + } + } +} + +fn is_adjusted(cx: &Context, e: &Expr) -> bool { + cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() +} + +fn check_closure(cx: &Context, expr: &Expr) { + if let ExprClosure(_, ref decl, ref blk) = expr.node { + if !blk.stmts.is_empty() { + // || {foo(); bar()}; can't be reduced here + return; + } + if let Some(ref ex) = blk.expr { + if let ExprCall(ref caller, ref args) = ex.node { + if args.len() != decl.inputs.len() { + // Not the same number of arguments, there + // is no way the closure is the same as the function + return; + } + if args.iter().any(|arg| is_adjusted(cx, arg)) { return; } + for (ref a1, ref a2) in decl.inputs.iter().zip(args) { + if let PatIdent(_, ident, _) = a1.pat.node { + // XXXManishearth Should I be checking the binding mode here? + if let ExprPath(None, ref p) = a2.node { + if p.segments.len() != 1 { + // If it's a proper path, it can't be a local variable + return; + } + if p.segments[0].identifier != ident.node { + // The two idents should be the same return } } else { return } + } else { + return } - span_lint(cx, REDUNDANT_CLOSURE, expr.span, - &format!("redundant closure found. Consider using `{}` in its place", - expr_to_string(caller))[..]) } + span_lint(cx, REDUNDANT_CLOSURE, expr.span, + &format!("redundant closure found. Consider using `{}` in its place", + expr_to_string(caller))[..]) } } } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 9e48ec1c3a5..bf6ecd79617 100755 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -4,18 +4,31 @@ #![deny(redundant_closure)] fn main() { - let a = |a, b| foo(a, b); + let a = Some(1u8).map(|a| foo(a)); //~^ ERROR redundant closure found. Consider using `foo` in its place - let c = |a, b| {1+2; foo}(a, b); + meta(|a| foo(a)); + //~^ ERROR redundant closure found. Consider using `foo` in its place + let c = Some(1u8).map(|a| {1+2; foo}(a)); //~^ ERROR redundant closure found. Consider using `{ 1 + 2; foo }` in its place - let d = |a, b| foo((|c, d| foo2(c,d))(a,b), b); - //~^ ERROR redundant closure found. Consider using `foo2` in its place + let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? + all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted +} + +fn meta<F>(f: F) where F: Fn(u8) { + f(1u8) } -fn foo(_: u8, _: u8) { +fn foo(_: u8) { } -fn foo2(_: u8, _: u8) -> u8 { +fn foo2(_: u8) -> u8 { 1u8 } + +fn all<X, F>(x: &[X], y: &X, f: F) -> bool +where F: Fn(&X, &X) -> bool { + x.iter().all(|e| f(e, y)) +} + +fn below(x: &u8, y: &u8) -> bool { x < y } -- cgit 1.4.1-3-g733a5 From b6ac44d5b2ba3a7d20371dd5bc65bbc53c0e2f8b Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 15:00:04 +0200 Subject: Removed #![allow(redundant_closure)] on eq_op --- src/eq_op.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 0b7511e7dbd..495696b810c 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,4 +1,3 @@ -#![allow(redundant_closure)] // FIXME (#116) use rustc::lint::*; use syntax::ast::*; use syntax::ast_util as ast_util; -- cgit 1.4.1-3-g733a5 From f23af0cfd5cb25b1988d628fc41ad4515693c91d Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 14 Aug 2015 17:14:54 +0200 Subject: changed const to consts to avoid keyword, added test, fixed a lot of bugs --- src/const.rs | 356 -------------------------------------------------- src/consts.rs | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + tests/consts.rs | 11 ++ 4 files changed, 408 insertions(+), 356 deletions(-) delete mode 100644 src/const.rs create mode 100644 src/consts.rs create mode 100644 tests/consts.rs diff --git a/src/const.rs b/src/const.rs deleted file mode 100644 index bc53c1062dc..00000000000 --- a/src/const.rs +++ /dev/null @@ -1,356 +0,0 @@ -use rustc::lint::Context; -use rustc::middle::const_eval::lookup_const_by_id; -use syntax::ast::*; -use syntax::ptr::P; - -pub enum FloatWidth { - Fw32, - Fw64, - FwAny -} - -impl From<FloatTy> for FloatWidth { - fn from(ty: FloatTy) -> FloatWidth { - match ty { - TyF32 => Fw32, - TyF64 => Fw64, - } - } -} - -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct Constant { - constant: ConstantVariant, - needed_resolution: bool -} - -impl Constant { - fn new(variant: ConstantVariant) -> Constant { - Constant { constant: variant, needed_resolution: false } - } - - fn new_resolved(variant: ConstantVariant) -> Constant { - Constant { constant: variant, needed_resolution: true } - } -} - -/// a Lit_-like enum to fold constant `Expr`s into -#[derive(PartialEq, Eq, Debug, Clone)] -pub enum ConstantVariant { - /// a String "abc" - ConstantStr(&'static str, StrStyle), - /// a Binary String b"abc" - ConstantBinary(Rc<Vec<u8>>), - /// a single byte b'a' - ConstantByte(u8), - /// a single char 'a' - ConstantChar(char), - /// an integer - ConstantInt(u64, LitIntType), - /// a float with given type - ConstantFloat(Cow<'static, str>, FloatWidth), - /// true or false - ConstantBool(bool), - /// an array of constants - ConstantVec(Vec<Constant>), - /// also an array, but with only one constant, repeated N times - ConstantRepeat(Constant, usize), - /// a tuple of constants - ConstantTuple(Vec<Constant>), -} - -impl ConstantVariant { - /// convert to u64 if possible - /// - /// # panics - /// - /// if the constant could not be converted to u64 losslessly - fn as_u64(&self) -> u64 { - if let &ConstantInt(val, _) = self { - val // TODO we may want to check the sign if any - } else { - panic!("Could not convert a {:?} to u64"); - } - } -} - -/// simple constant folding: Insert an expression, get a constant or none. -pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { - match e { - &ExprParen(ref inner) => constant(cx, inner), - &ExprPath(_, _) => fetch_path(cx, e), - &ExprBlock(ref block) => constant_block(cx, inner), - &ExprIf(ref cond, ref then, ref otherwise) => - constant_if(cx, cond, then, otherwise), - &ExprLit(ref lit) => Some(lit_to_constant(lit)), - &ExprVec(ref vec) => constant_vec(cx, vec), - &ExprTup(ref tup) => constant_tup(cx, tup), - &ExprRepeat(ref value, ref number) => - constant_binop_apply(cx, value, number,|v, n| Constant { - constant: ConstantRepeat(v, n.constant.as_u64()), - needed_resolution: v.needed_resolution || n.needed_resolution - }), - &ExprUnary(op, ref operand) => constant(cx, operand).and_then( - |o| match op { - UnNot => - if let ConstantBool(b) = o.variant { - Some(Constant{ - needed_resolution: o.needed_resolution, - constant: ConstantBool(!b), - }) - } else { None }, - UnNeg => constant_negate(o), - UnUniq | UnDeref => o, - }), - &ExprBinary(op, ref left, ref right) => - constant_binop(op, left, right), - //TODO: add other expressions - _ => None, - } -} - -fn lit_to_constant(lit: &Lit_) -> Constant { - match lit { - &LitStr(ref is, style) => Constant::new(ConstantStr(&*is, style)), - &LitBinary(ref blob) => Constant::new(ConstantBinary(blob.clone())), - &LitByte(b) => Constant::new(ConstantByte(b)), - &LitChar(c) => Constant::new(ConstantChar(c)), - &LitInt(value, ty) => Constant::new(ConstantInt(value, ty)), - &LitFloat(ref is, ty) => - Constant::new(ConstantFloat(Cow::Borrowed(&*is), ty.into())), - &LitFloatUnsuffixed(InternedString) => - Constant::new(ConstantFloat(Cow::Borrowed(&*is), FwAny)), - &LitBool(b) => Constant::new(ConstantBool(b)), - } -} - -/// create `Some(ConstantVec(..))` of all constants, unless there is any -/// non-constant part -fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> { - let mut parts = Vec::new(); - let mut resolved = false; - for opt_part in vec { - match constant(cx, opt_part) { - Some(ref p) => { - resolved |= p.needed_resolution; - parts.push(p) - }, - None => { return None; }, - } - } - Some(Constant { - constant: ConstantVec(parts), - needed_resolution: resolved - }) -} - -fn constant_tup(cx: &Context, tup: &[&Expr]) -> Option<Constant> { - let mut parts = Vec::new(); - let mut resolved = false; - for opt_part in vec { - match constant(cx, opt_part) { - Some(ref p) => { - resolved |= p.needed_resolution; - parts.push(p) - }, - None => { return None; }, - } - } - Some(Constant { - constant: ConstantTuple(parts), - needed_resolution: resolved - }) -} - -/// lookup a possibly constant expression from a ExprPath -fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { - if let Some(&PathResolution { base_def: DefConst(id), ..}) = - cx.tcx.def_map.borrow().get(&e.id) { - lookup_const_by_id(cx.tcx, id, None).map( - |l| Constant::new_resolved(constant(cx, l).constant)) - } else { None } -} - -/// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { - if block.stmts.is_empty() { - block.expr.map(|b| constant(cx, b)) - } else { None } -} - -fn constant_if(cx: &Context, cond: &Expr, then: &Expr, otherwise: &Expr) -> - Option<Constant> { - if let Some(Constant{ constant: ConstantBool(b), needed_resolution: res }) = - constant(cx, cond) { - let part = constant(cx, if b { then } else { otherwise }); - Some(Constant { - constant: part.constant, - needed_resolution: res || part.needed_resolution, - }) - } else { None } -} - -fn constant_negate(o: Constant) -> Option<Constant> { - Some(Constant{ - needed_resolution: o.needed_resolution, - constant: match o.constant { - &ConstantInt(value, ty) => - ConstantInt(value, match ty { - SignedIntLit(ity, sign) => - SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - }), - &LitFloat(ref is, ref ty) => ConstantFloat(neg_float_str(is), ty), - _ => { return None; }, - } - }) -} - -fn neg_sign(s: Sign) -> Sign { - match s { - Sign::Plus => Sign::Minus, - Sign::Minus => Sign::Plus, - } -} - -fn neg_float_str(s: &InternedString) -> Cow<'static, str> { - if s.startsWith('-') { - Cow::Borrowed(s[1..]) - } else { - Cow::Owned(format!("-{}", &*s)) - } -} - -fn is_negative(ty: LitIntType) -> bool { - match ty { - SignedIntLit(_, sign) | UnsuffixedIntLit(sign) => sign == Minus, - UnsignedIntLit(_) => false, - } -} - -fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option(LitIntType) { - match (l, r) { - (SignedIntLit(lty, _), SignedIntLit(rty, _)) => if lty == rty { - Some(SignedIntLit(lty, s)) } else { None }, - (UnsignedIntLit(lty), UnsignedIntLit(rty)) => - if Sign == Plus && lty == rty { - Some(UnsignedIntLit(lty)) - } else { None }, - (UnsuffixedIntLit(_), UnsuffixedIntLit(_)) => UnsuffixedIntLit(s), - (SignedIntLit(lty, _), UnsuffixedIntLit(_)) => SignedIntLit(lty, s), - (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => if rs == Plus { - Some(UnsignedIntLit(lty)) } else { None }, - (UnsuffixedIntLit(_), SignedIntLit(rty, _)) => SignedIntLit(rty, s), - (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => if ls == Plus { - Some(UnsignedIntLit(rty)) } else { None }, - _ => None, - } -} - -fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) - -> Option<Constant> { - match op.node { - BiAdd => constant_binop_apply(cx, left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => - l8.checked_add(r8).map(|v| ConstantByte(v)), - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - if ln == rn { - unify_int_type(lty, rty, if ln { Minus } else { Plus }) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))) - } else { - if ln { - add_neg_int(r64, rty, l64, lty) - } else { - add_neg_int(l64, lty, r64, rty) - } - } - }, - // TODO: float - _ => None - }), - BiSub => constant_binop_apply(cx, left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { - None } else { Some(ConstantByte(l8 - r8)) }, - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - match (ln, rn) { - (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), - (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), - (true, false) => unify_int_type(lty, rty, Minus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - (false, true) => unify_int_type(lty, rty, Plus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - } - }, - _ => None, - }), - //BiMul, - //BiDiv, - //BiRem, - BiAnd => constant_short_circuit(cx, left, right, false), - BiOr => constant_short_circuit(cx, left, right, true), - //BiBitXor, - //BiBitAnd, - //BiBitOr, - //BiShl, - //BiShr, - //BiEq, - //BiLt, - //BiLe, - //BiNe, - //BiGe, - //BiGt, - _ => None, - } -} - -fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> - Some(Constant) { - if neg > pos { - unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) - } else { - unify_int_type(nty, pty, Plus).map(|ty| ConstantInt(pos - neg, ty)) - } -} - -fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: Bool) -> - Option<Constant> { - unify_int_type(lty, rty, if neg { Minus } else { Plus }).and_then( - |ty| l64.checked_sub(r64).map(|v| ConstantInt(v, ty))) -} - -fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) - -> Option<Constant> -where F: FnMut(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { - constant(cx, left).and_then(|l| constant(cx, right).and_then( - |r| Constant { - needed_resolution: l.needed_resolution || r.needed_resolution, - constant: op(l.constant, r.constant) - })) -} - -fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool) -> - Option<Constant> { - let leftconst = constant(cx, left); - if let ConstantBool(lbool) = leftconst.constant { - if l == b { - Some(leftconst) - } else { - let rightconst = constant(cx, right); - if let ConstantBool(rbool) = rightconst.constant { - Some(Constant { - constant: rightconst.constant, - needed_resolution: leftconst.needed_resolution || - rightconst.needed_resolution, - }) - } else { None } - } - } else { None } -} diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 00000000000..c8d5262abab --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,396 @@ +#[cfg(test)] +use rustc::lint::Context; + +use rustc::middle::const_eval::lookup_const_by_id; +use rustc::middle::def::PathResolution; +use rustc::middle::def::Def::*; +use syntax::ast::*; +use syntax::parse::token::InternedString; +use syntax::ptr::P; +use std::rc::Rc; +use std::ops::Deref; +use self::ConstantVariant::*; +use self::FloatWidth::*; + +#[cfg(not(test))] +pub struct Context; + +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub enum FloatWidth { + Fw32, + Fw64, + FwAny +} + +impl From<FloatTy> for FloatWidth { + fn from(ty: FloatTy) -> FloatWidth { + match ty { + TyF32 => Fw32, + TyF64 => Fw64, + } + } +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Constant { + constant: ConstantVariant, + needed_resolution: bool +} + +impl Constant { + pub fn new(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: false } + } + + pub fn new_resolved(variant: ConstantVariant) -> Constant { + Constant { constant: variant, needed_resolution: true } + } + + // convert this constant to a f64, if possible + pub fn as_float(&self) -> Option<f64> { + match &self.constant { + &ConstantByte(b) => Some(b as f64), + &ConstantFloat(ref s, _) => s.parse().ok(), + &ConstantInt(i, ty) => Some(if is_negative(ty) { + -(i as f64) } else { i as f64 }), + _ => None + } + } +} + +/// a Lit_-like enum to fold constant `Expr`s into +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum ConstantVariant { + /// a String "abc" + ConstantStr(String, StrStyle), + /// a Binary String b"abc" + ConstantBinary(Rc<Vec<u8>>), + /// a single byte b'a' + ConstantByte(u8), + /// a single char 'a' + ConstantChar(char), + /// an integer + ConstantInt(u64, LitIntType), + /// a float with given type + ConstantFloat(String, FloatWidth), + /// true or false + ConstantBool(bool), + /// an array of constants + ConstantVec(Box<Vec<Constant>>), + /// also an array, but with only one constant, repeated N times + ConstantRepeat(Box<ConstantVariant>, usize), + /// a tuple of constants + ConstantTuple(Box<Vec<Constant>>), +} + +impl ConstantVariant { + /// convert to u64 if possible + /// + /// # panics + /// + /// if the constant could not be converted to u64 losslessly + fn as_u64(&self) -> u64 { + if let &ConstantInt(val, _) = self { + val // TODO we may want to check the sign if any + } else { + panic!("Could not convert a {:?} to u64"); + } + } +} + +/// simple constant folding: Insert an expression, get a constant or none. +pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { + match &e.node { + &ExprParen(ref inner) => constant(cx, inner), + &ExprPath(_, _) => fetch_path(cx, e), + &ExprBlock(ref block) => constant_block(cx, block), + &ExprIf(ref cond, ref then, ref otherwise) => + constant_if(cx, &*cond, &*then, &*otherwise), + &ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), + &ExprVec(ref vec) => constant_vec(cx, &vec[..]), + &ExprTup(ref tup) => constant_tup(cx, &tup[..]), + &ExprRepeat(ref value, ref number) => + constant_binop_apply(cx, value, number,|v, n| + Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), + &ExprUnary(op, ref operand) => constant(cx, operand).and_then( + |o| match op { + UnNot => + if let ConstantBool(b) = o.constant { + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: ConstantBool(!b), + }) + } else { None }, + UnNeg => constant_negate(o), + UnUniq | UnDeref => Some(o), + }), + &ExprBinary(op, ref left, ref right) => + constant_binop(cx, op, left, right), + //TODO: add other expressions + _ => None, + } +} + +fn lit_to_constant(lit: &Lit_) -> Constant { + match lit { + &LitStr(ref is, style) => + Constant::new(ConstantStr(is.to_string(), style)), + &LitBinary(ref blob) => Constant::new(ConstantBinary(blob.clone())), + &LitByte(b) => Constant::new(ConstantByte(b)), + &LitChar(c) => Constant::new(ConstantChar(c)), + &LitInt(value, ty) => Constant::new(ConstantInt(value, ty)), + &LitFloat(ref is, ty) => { + Constant::new(ConstantFloat(is.to_string(), ty.into())) + }, + &LitFloatUnsuffixed(ref is) => { + Constant::new(ConstantFloat(is.to_string(), FwAny)) + }, + &LitBool(b) => Constant::new(ConstantBool(b)), + } +} + +/// create `Some(ConstantVec(..))` of all constants, unless there is any +/// non-constant part +fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; + for opt_part in vec.iter() { + match constant(cx, opt_part) { + Some(p) => { + resolved |= (&p).needed_resolution; + parts.push(p) + }, + None => { return None; }, + } + } + Some(Constant { + constant: ConstantVec(Box::new(parts)), + needed_resolution: resolved + }) +} + +fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Option<Constant> { + let mut parts = Vec::new(); + let mut resolved = false; + for opt_part in tup.iter() { + match constant(cx, opt_part) { + Some(p) => { + resolved |= (&p).needed_resolution; + parts.push(p) + }, + None => { return None; }, + } + } + Some(Constant { + constant: ConstantTuple(Box::new(parts)), + needed_resolution: resolved + }) +} + +#[cfg(test)] +fn fetch_path(_cx: &Context, _expr: &Expr) -> Option<Constant> { None } + +/// lookup a possibly constant expression from a ExprPath +#[cfg(not(test))] +fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { + if let Some(&PathResolution { base_def: DefConst(id), ..}) = + cx.tcx.def_map.borrow().get(&e.id) { + lookup_const_by_id(cx.tcx, id, None).and_then( + |l| constant(cx, l).map(|c| Constant::new_resolved(c.constant))) + } else { None } +} + +/// A block can only yield a constant if it only has one constant expression +fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { + if block.stmts.is_empty() { + block.expr.as_ref().and_then(|b| constant(cx, &*b)) + } else { None } +} + +fn constant_if(cx: &Context, cond: &Expr, then: &Block, otherwise: + &Option<P<Expr>>) -> Option<Constant> { + if let Some(Constant{ constant: ConstantBool(b), needed_resolution: res }) = + constant(cx, cond) { + if b { + constant_block(cx, then) + } else { + otherwise.as_ref().and_then(|expr| constant(cx, &*expr)) + }.map(|part| + Constant { + constant: part.constant, + needed_resolution: res || part.needed_resolution, + }) + } else { None } +} + +fn constant_negate(o: Constant) -> Option<Constant> { + Some(Constant{ + needed_resolution: o.needed_resolution, + constant: match o.constant { + ConstantInt(value, ty) => + ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + }), + ConstantFloat(ref is, ty) => + ConstantFloat(neg_float_str(is.to_string()), ty), + _ => { return None; }, + } + }) +} + +fn neg_sign(s: Sign) -> Sign { + match s { + Sign::Plus => Sign::Minus, + Sign::Minus => Sign::Plus, + } +} + +fn neg_float_str(s: String) -> String { + if s.starts_with('-') { + s[1..].to_owned() + } else { + format!("-{}", &*s) + } +} + +fn is_negative(ty: LitIntType) -> bool { + match ty { + SignedIntLit(_, sign) | UnsuffixedIntLit(sign) => sign == Minus, + UnsignedIntLit(_) => false, + } +} + +fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { + match (l, r) { + (SignedIntLit(lty, _), SignedIntLit(rty, _)) => if lty == rty { + Some(SignedIntLit(lty, s)) } else { None }, + (UnsignedIntLit(lty), UnsignedIntLit(rty)) => + if s == Plus && lty == rty { + Some(UnsignedIntLit(lty)) + } else { None }, + (UnsuffixedIntLit(_), UnsuffixedIntLit(_)) => Some(UnsuffixedIntLit(s)), + (SignedIntLit(lty, _), UnsuffixedIntLit(_)) => Some(SignedIntLit(lty, s)), + (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => if rs == Plus { + Some(UnsignedIntLit(lty)) } else { None }, + (UnsuffixedIntLit(_), SignedIntLit(rty, _)) => Some(SignedIntLit(rty, s)), + (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => if ls == Plus { + Some(UnsignedIntLit(rty)) } else { None }, + _ => None, + } +} + +fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) + -> Option<Constant> { + match op.node { + BiAdd => constant_binop_apply(cx, left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => + l8.checked_add(r8).map(|v| ConstantByte(v)), + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + if ln == rn { + unify_int_type(lty, rty, if ln { Minus } else { Plus }) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))) + } else { + if ln { + add_neg_int(r64, rty, l64, lty) + } else { + add_neg_int(l64, lty, r64, rty) + } + } + }, + // TODO: float + _ => None + }), + BiSub => constant_binop_apply(cx, left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { + None } else { Some(ConstantByte(l8 - r8)) }, + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + match (ln, rn) { + (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), + (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), + (true, false) => unify_int_type(lty, rty, Minus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + (false, true) => unify_int_type(lty, rty, Plus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + } + }, + _ => None, + }), + //BiMul, + //BiDiv, + //BiRem, + BiAnd => constant_short_circuit(cx, left, right, false), + BiOr => constant_short_circuit(cx, left, right, true), + //BiBitXor, + //BiBitAnd, + //BiBitOr, + //BiShl, + //BiShr, + //BiEq, + //BiLt, + //BiLe, + //BiNe, + //BiGe, + //BiGt, + _ => None, + } +} + +fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> + Option<ConstantVariant> { + if neg > pos { + unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) + } else { + unify_int_type(nty, pty, Plus).map(|ty| ConstantInt(pos - neg, ty)) + } +} + +fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> + Option<ConstantVariant> { + unify_int_type(lty, rty, if neg { Minus } else { Plus }).and_then( + |ty| l.checked_sub(r).map(|v| ConstantInt(v, ty))) +} + +fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) + -> Option<Constant> +where F: Fn(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { + if let (Some(Constant { constant: lc, needed_resolution: ln }), + Some(Constant { constant: rc, needed_resolution: rn })) = + (constant(cx, left), constant(cx, right)) { + op(lc, rc).map(|c| + Constant { + needed_resolution: ln || rn, + constant: c, + }) + } else { None } +} + +fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool) -> + Option<Constant> { + constant(cx, left).and_then(|left| + if let &ConstantBool(lbool) = &left.constant { + if lbool == b { + Some(left) + } else { + constant(cx, right).and_then(|right| + if let ConstantBool(_) = right.constant { + Some(Constant { + constant: right.constant, + needed_resolution: left.needed_resolution || + right.needed_resolution, + }) + } else { None } + ) + } + } else { None } + ) +} diff --git a/src/lib.rs b/src/lib.rs index f788c72db3c..8e7cc096c5e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ use rustc::lint::LintPassObject; #[macro_use] pub mod utils; +pub mod consts; pub mod types; pub mod misc; pub mod eq_op; diff --git a/tests/consts.rs b/tests/consts.rs new file mode 100644 index 00000000000..edbbfa1e2db --- /dev/null +++ b/tests/consts.rs @@ -0,0 +1,11 @@ + +extern crate clippy; + +use clippy::consts; +use syntax::ast::*; + +#[test] +fn test_lit() { + assert_eq!(ConstantBool(true), constant(&Context, + Expr{ node_id: 1, node: ExprLit(LitBool(true)), span: default() })); +} -- cgit 1.4.1-3-g733a5 From 137a9f3def7d4d420e9359d36efe52f8d3e42c9e Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 14 Aug 2015 07:17:10 +0200 Subject: methods: allow Option.unwrap by default --- README.md | 2 +- src/methods.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd7d0158f03..d9dea816318 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ needless_lifetimes | warn | using explicit lifetimes for references in func needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do needless_return | warn | using a return statement like `return expr;` where an expression would suffice non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -option_unwrap_used | warn | using `Option.unwrap()`, which should at least get a better message using `expect()` +option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) diff --git a/src/methods.rs b/src/methods.rs index 07b0fdf70e2..02b181a46e7 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -7,7 +7,7 @@ use utils::{span_lint, match_def_path, walk_ptrs_ty}; #[derive(Copy,Clone)] pub struct MethodsPass; -declare_lint!(pub OPTION_UNWRAP_USED, Warn, +declare_lint!(pub OPTION_UNWRAP_USED, Allow, "using `Option.unwrap()`, which should at least get a better message using `expect()`"); declare_lint!(pub RESULT_UNWRAP_USED, Allow, "using `Result.unwrap()`, which might be better handled"); -- cgit 1.4.1-3-g733a5 From b299433de3f3344ab97f426aea8a0bf7d396723a Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 15 Aug 2015 09:36:02 +0200 Subject: lifetimes: fix case with one unnamed and one static ref (fixes #171) --- src/lifetimes.rs | 4 ++-- tests/compile-fail/lifetimes.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index c3c915ea777..0127822dbde 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -115,8 +115,8 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, } else if output_lts.is_empty() { // no output lifetimes, check distinctness of input lifetimes - // only one reference with unnamed lifetime, ok - if input_lts.len() == 1 && input_lts[0] == Unnamed { + // only unnamed and static, ok + if input_lts.iter().all(|lt| *lt == Unnamed || *lt == Static) { return false; } // we have no output reference, so we only need all distinct lifetimes diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 287a8199d2c..a5597e6478f 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -13,6 +13,8 @@ fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same life fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved +fn mut_and_static_input(_x: &mut u8, _y: &'static str) { } + fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } //~^ERROR explicit lifetimes given @@ -60,7 +62,6 @@ impl<'a> Foo<'a> { fn self_shared_lifetime(&self, _: &'a u8) {} // no error, lifetime 'a not defined in method fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {} // no error, bounds exist } -static STATIC: u8 = 1; fn main() { } -- cgit 1.4.1-3-g733a5 From 542bf8d50ee9edc7754b3977407880640fc0bd68 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 15 Aug 2015 09:22:50 +0200 Subject: misc: fix check for unit body in "match -> if let" lint (fixes #172) --- src/misc.rs | 65 ++++++++++++++++++++++---------------- tests/compile-fail/match_if_let.rs | 12 +++++++ 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 861e4a73dd2..091ea36f2f5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -6,6 +6,7 @@ use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; +use std::borrow::Cow; use utils::{match_path, snippet, snippet_block, span_lint, span_help_and_lint, walk_ptrs_ty}; @@ -26,39 +27,47 @@ impl LintPass for MiscPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { - if arms.len() == 2 { - if arms[0].guard.is_none() && arms[1].pats.len() == 1 { - match arms[1].body.node { - ExprTup(ref v) if v.is_empty() && arms[1].guard.is_none() => (), - ExprBlock(ref b) if b.stmts.is_empty() && arms[1].guard.is_none() => (), - _ => return - } - // In some cases, an exhaustive match is preferred to catch situations when - // an enum is extended. So we only consider cases where a `_` wildcard is used - if arms[1].pats[0].node == PatWild(PatWildSingle) && - arms[0].pats.len() == 1 { - let body_code = snippet_block(cx, arms[0].body.span, ".."); - let suggestion = if let ExprBlock(_) = arms[0].body.node { - body_code.into_owned() - } else { - format!("{{ {} }}", body_code) - }; - span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for \ - destructuring a single pattern. Did you mean to \ - use `if let`?", - &*format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - suggestion) - ); - } - } + // check preconditions: only two arms + if arms.len() == 2 && + // both of the arms have a single pattern and no guard + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + // and the second pattern is a `_` wildcard: this is not strictly necessary, + // since the exhaustiveness check will ensure the last one is a catch-all, + // but in some cases, an explicit match is preferred to catch situations + // when an enum is extended, so we don't consider these cases + arms[1].pats[0].node == PatWild(PatWildSingle) && + // finally, we don't want any content in the second arm (unit or empty block) + is_unit_expr(&*arms[1].body) + { + let body_code = snippet_block(cx, arms[0].body.span, ".."); + let body_code = if let ExprBlock(_) = arms[0].body.node { + body_code + } else { + Cow::Owned(format!("{{ {} }}", body_code)) + }; + span_help_and_lint(cx, SINGLE_MATCH, expr.span, + "you seem to be trying to use match for \ + destructuring a single pattern. Did you mean to \ + use `if let`?", + &*format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + body_code) + ); } } } } +fn is_unit_expr(expr: &Expr) -> bool { + match expr.node { + ExprTup(ref v) if v.is_empty() => true, + ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, + _ => false, + } +} + declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \ diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs index 01bfe744713..bf2e7e43a52 100755 --- a/tests/compile-fail/match_if_let.rs +++ b/tests/compile-fail/match_if_let.rs @@ -23,4 +23,16 @@ fn main(){ (2...3, 7...9) => println!("{:?}", z), _ => {} } + + // Not linted (pattern guards used) + match x { + Some(y) if y == 0 => println!("{:?}", y), + _ => () + } + + // Not linted (content in the else) + match z { + (2...3, 7...9) => println!("{:?}", z), + _ => println!("nope"), + } } -- cgit 1.4.1-3-g733a5 From c64e373c9ebbf02a5f416972c6b292877e13f1d4 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 15 Aug 2015 09:58:26 +0200 Subject: util: make dogfood executable and give it a shebang --- util/dogfood.sh | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 util/dogfood.sh diff --git a/util/dogfood.sh b/util/dogfood.sh old mode 100644 new mode 100755 index 51dd465a25d..e98d18c40d5 --- a/util/dogfood.sh +++ b/util/dogfood.sh @@ -1,3 +1,4 @@ +#!/bin/sh rm -rf target*/*so cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy || exit 1 rm -rf target_recur -- cgit 1.4.1-3-g733a5 From 997f34504685085da149221c5fda4e4cd941ae53 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 16 Aug 2015 08:33:10 +0200 Subject: all: remove unneeded as_str() calls for ast::Name Name has PartialEq and Display impls that do what we want. --- src/attrs.rs | 2 +- src/len_zero.rs | 4 ++-- src/lifetimes.rs | 2 +- src/loops.rs | 7 +++---- src/utils.rs | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index ef3320d2543..850155b28b6 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -103,7 +103,7 @@ fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, span_lint(cx, INLINE_ALWAYS, attr.span, &format!( "you have declared `#[inline(always)]` on `{}`. This \ is usually a bad idea. Are you sure?", - ident.name.as_str())); + ident.name)); } } } diff --git a/src/len_zero.rs b/src/len_zero.rs index d5f3d1ad810..94f8d5873ec 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -55,7 +55,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); + //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident)); for i in trait_items { if is_named_self(i, "len") { span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, @@ -122,7 +122,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { if let &MethodTraitItemId(def_id) = id { if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { - method.name.as_str() == "is_empty" + method.name == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 } else { false } } else { false } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 0127822dbde..37204f03603 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -153,7 +153,7 @@ struct RefVisitor(Vec<RefLt>); impl RefVisitor { fn record(&mut self, lifetime: &Option<Lifetime>) { if let &Some(ref lt) = lifetime { - if lt.name.as_str() == "'static" { + if lt.name == "'static" { self.0.push(Static); } else { self.0.push(Named(lt.name)); diff --git a/src/loops.rs b/src/loops.rs index 74015bdc6be..092b5ce1196 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -36,13 +36,12 @@ impl LintPass for LoopsPass { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is used to index `{}`. Consider using \ `for ({}, item) in {}.iter().enumerate()` or similar iterators.", - ident.node.name.as_str(), indexed.as_str(), - ident.node.name.as_str(), indexed.as_str())); + ident.node.name, indexed, ident.node.name, indexed)); } else { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is only used to index `{}`. \ Consider using `for item in &{}` or similar iterators.", - ident.node.name.as_str(), indexed.as_str(), indexed.as_str())); + ident.node.name, indexed, indexed)); } } } @@ -52,7 +51,7 @@ impl LintPass for LoopsPass { if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments to iter() or iter_mut() if args.len() == 1 { - let method_name = method.node.name.as_str(); + let method_name = method.node.name; if method_name == "iter" { let object = snippet(cx, args[0].span, "_"); span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( diff --git a/src/utils.rs b/src/utils.rs index 67a89b067e6..a9378da415a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -35,14 +35,14 @@ pub fn in_external_macro(cx: &Context, span: Span) -> bool { /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { cx.tcx.with_path(def_id, |iter| iter.map(|elem| elem.name()) - .zip(path.iter()).all(|(nm, p)| &nm.as_str() == p)) + .zip(path.iter()).all(|(nm, p)| nm == p)) } /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a,b)| &a.identifier.name.as_str() == b) + |(a, b)| &a.identifier.name == b) } /// convert a span to a code snippet if available, otherwise use default, e.g. -- cgit 1.4.1-3-g733a5 From 47b605304db5e1bf3cac3879e11d0ceae9ba9959 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 16 Aug 2015 08:54:43 +0200 Subject: all: organize imports * remove unused imports * separate external and internal imports * consistent import of rustc::lint * move #[allow(unused_imports)] to local impl --- src/approx_const.rs | 6 +----- src/attrs.rs | 8 +++----- src/bit_mask.rs | 5 ++--- src/collapsible_if.rs | 6 ++---- src/eq_op.rs | 1 + src/eta_reduction.rs | 3 +-- src/identity_op.rs | 3 --- src/len_zero.rs | 13 ++++--------- src/lib.rs | 1 - src/lifetimes.rs | 8 ++++---- src/methods.rs | 2 +- src/misc.rs | 6 +++--- src/mut_mut.rs | 8 ++++---- src/needless_bool.rs | 7 +------ src/ptr_arg.rs | 6 +----- src/returns.rs | 5 ++--- src/strings.rs | 4 ++-- src/types.rs | 7 ++++--- src/unicode.rs | 1 + src/utils.rs | 7 +++---- 20 files changed, 40 insertions(+), 67 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 3c39b79885c..cfd646765c9 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,12 +1,8 @@ -use rustc::plugin::Registry; use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; use syntax::codemap::Span; use std::f64::consts as f64; + use utils::span_lint; declare_lint! { diff --git a/src/attrs.rs b/src/attrs.rs index 850155b28b6..3e451ac5eda 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -1,11 +1,9 @@ -/// checks for attributes +//! checks for attributes -use rustc::plugin::Registry; use rustc::lint::*; use syntax::ast::*; -use syntax::ptr::P; -use syntax::codemap::{Span, ExpnInfo}; -use syntax::parse::token::InternedString; +use syntax::codemap::ExpnInfo; + use utils::{in_macro, match_path, span_lint}; declare_lint! { pub INLINE_ALWAYS, Warn, diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 169975001b9..ec937dbab6c 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,11 +1,10 @@ -use rustc::plugin::Registry; use rustc::lint::*; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::*; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; +use syntax::ast_util::is_comparison_binop; use syntax::codemap::Span; + use utils::span_lint; declare_lint! { diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 8a41f208938..0b6dfc19e6b 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -12,12 +12,10 @@ //! //! This lint is **warn** by default -use rustc::plugin::Registry; use rustc::lint::*; -use rustc::middle::def::*; use syntax::ast::*; -use syntax::ptr::P; -use syntax::codemap::{Span, Spanned, ExpnInfo}; +use syntax::codemap::{Spanned, ExpnInfo}; + use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; declare_lint! { diff --git a/src/eq_op.rs b/src/eq_op.rs index 495696b810c..50b61e23356 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -3,6 +3,7 @@ use syntax::ast::*; use syntax::ast_util as ast_util; use syntax::ptr::P; use syntax::codemap as code; + use utils::span_lint; declare_lint! { diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index e0d4182081f..6712e787278 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,6 +1,5 @@ +use rustc::lint::*; use syntax::ast::*; -use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use syntax::codemap::{Span, Spanned}; use syntax::print::pprust::expr_to_string; use utils::span_lint; diff --git a/src/identity_op.rs b/src/identity_op.rs index 964675b765e..18a475bb737 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,10 +1,7 @@ -use rustc::plugin::Registry; use rustc::lint::*; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::*; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; use syntax::codemap::Span; use utils::{span_lint, snippet}; diff --git a/src/len_zero.rs b/src/len_zero.rs index 94f8d5873ec..073dcea582d 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,14 +1,9 @@ -extern crate rustc_typeck as typeck; - -use std::rc::Rc; -use std::cell::RefCell; +use rustc::lint::*; +use syntax::ast::*; use syntax::ptr::P; -use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::util::nodemap::DefIdMap; -use rustc::middle::ty::{self, TypeVariants, TypeAndMut, MethodTraitItemId, ImplOrTraitItemId}; -use rustc::middle::def::{DefTy, DefStruct, DefTrait}; use syntax::codemap::{Span, Spanned}; -use syntax::ast::*; +use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; + use utils::{span_lint, walk_ptrs_ty, snippet}; declare_lint!(pub LEN_ZERO, Warn, diff --git a/src/lib.rs b/src/lib.rs index 01a2d65606c..3ce5c1f9f3c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] #![feature(str_split_at)] -#![allow(unused_imports, unknown_lints)] #[macro_use] extern crate syntax; diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 37204f03603..9d07df4a3ed 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -1,10 +1,10 @@ use syntax::ast::*; -use rustc::lint::{Context, LintPass, LintArray, Lint}; +use rustc::lint::*; use syntax::codemap::Span; -use syntax::visit::{Visitor, FnKind, walk_ty}; -use utils::{in_external_macro, span_lint}; +use syntax::visit::{Visitor, walk_ty}; use std::collections::HashSet; -use std::iter::FromIterator; + +use utils::{in_external_macro, span_lint}; declare_lint!(pub NEEDLESS_LIFETIMES, Warn, "using explicit lifetimes for references in function arguments when elision rules \ diff --git a/src/methods.rs b/src/methods.rs index 02b181a46e7..6d0707ccbee 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,5 +1,5 @@ use syntax::ast::*; -use rustc::lint::{Context, LintPass, LintArray}; +use rustc::lint::*; use rustc::middle::ty; use utils::{span_lint, match_def_path, walk_ptrs_ty}; diff --git a/src/misc.rs b/src/misc.rs index 091ea36f2f5..1fc41cf4862 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,11 +1,11 @@ +use rustc::lint::*; use syntax::ptr::P; use syntax::ast; use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::visit::{FnKind}; -use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty; use syntax::codemap::{Span, Spanned}; +use syntax::visit::FnKind; +use rustc::middle::ty; use std::borrow::Cow; use utils::{match_path, snippet, snippet_block, span_lint, span_help_and_lint, walk_ptrs_ty}; diff --git a/src/mut_mut.rs b/src/mut_mut.rs index a3c40d06f90..fbcb70e17d3 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,8 +1,8 @@ -use syntax::ptr::P; +use rustc::lint::*; use syntax::ast::*; -use rustc::lint::{Context, LintPass, LintArray, Lint}; -use rustc::middle::ty::{TypeVariants, TypeAndMut, TyRef}; -use syntax::codemap::{BytePos, ExpnInfo, Span}; +use syntax::codemap::ExpnInfo; +use rustc::middle::ty::{TypeAndMut, TyRef}; + use utils::{in_macro, span_lint}; declare_lint!(pub MUT_MUT, Warn, diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 2a4ed50b93d..18d98f1f063 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -2,14 +2,9 @@ //! //! This lint is **warn** by default -use rustc::plugin::Registry; use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; -use syntax::codemap::Span; + use utils::{de_p, span_lint, snippet}; declare_lint! { diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 85db4aa7b21..2748d187a4e 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -2,14 +2,10 @@ //! //! This lint is **warn** by default -use rustc::plugin::Registry; use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; use syntax::codemap::Span; + use types::match_ty_unwrap; use utils::span_lint; diff --git a/src/returns.rs b/src/returns.rs index 94b9ec9650f..df0b93f301e 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,8 +1,7 @@ -use syntax::ast; +use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use rustc::lint::{Context, LintPass, LintArray, Level}; use utils::{span_lint, snippet, match_path}; @@ -101,7 +100,7 @@ impl LintPass for ReturnPass { } fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, - block: &Block, _: Span, _: ast::NodeId) { + block: &Block, _: Span, _: NodeId) { self.check_block_return(cx, block); self.check_let_return(cx, block); } diff --git a/src/strings.rs b/src/strings.rs index 7b7bab49b5d..7981b785850 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -6,9 +6,9 @@ use rustc::lint::*; use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; -use syntax::codemap::{Span, Spanned}; +use syntax::codemap::Spanned; + use eq_op::is_exp_equal; -use types::match_ty_unwrap; use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { diff --git a/src/types.rs b/src/types.rs index 53d8850c59d..25af398a0b4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,9 +1,9 @@ -use syntax::ptr::P; +use rustc::lint::*; use syntax::ast; use syntax::ast::*; +use syntax::ptr::P; use rustc::middle::ty; -use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use syntax::codemap::{ExpnInfo, Span}; +use syntax::codemap::ExpnInfo; use utils::{in_macro, snippet, span_lint, span_help_and_lint}; @@ -40,6 +40,7 @@ pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> } } +#[allow(unused_imports)] impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, LINKEDLIST) diff --git a/src/unicode.rs b/src/unicode.rs index 62b4a9dadf5..ab48fd1bef2 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,6 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{BytePos, Span}; + use utils::span_lint; declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, diff --git a/src/utils.rs b/src/utils.rs index a9378da415a..47e3a3456d6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,10 @@ -use rustc::lint::{Context, Lint, Level}; -use syntax::ast::{DefId, Expr, Name, NodeId, Path}; +use rustc::lint::*; +use syntax::ast::*; use syntax::codemap::{ExpnInfo, Span}; use syntax::ptr::P; use rustc::ast_map::Node::NodeExpr; use rustc::middle::ty; -use std::borrow::{Cow, IntoCow}; -use std::convert::From; +use std::borrow::Cow; /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin -- cgit 1.4.1-3-g733a5 From 64954283c12a5c0701fcd805454ca9282cafca51 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 16 Aug 2015 09:03:06 +0200 Subject: add some imports to guard against crate moves --- src/lib.rs | 3 ++- src/methods.rs | 7 +++++++ src/types.rs | 2 -- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3ce5c1f9f3c..c45227f88f2 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![feature(plugin_registrar, box_syntax)] -#![feature(rustc_private, collections)] +#![feature(rustc_private, core, collections)] #![feature(str_split_at)] #[macro_use] @@ -8,6 +8,7 @@ extern crate syntax; extern crate rustc; // Only for the compile time checking of paths +extern crate core; extern crate collections; use rustc::plugin::Registry; diff --git a/src/methods.rs b/src/methods.rs index 6d0707ccbee..f2df736bebc 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -16,12 +16,19 @@ declare_lint!(pub STR_TO_STRING, Warn, declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); +#[allow(unused_imports)] impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { + { + // In case stuff gets moved around + use core::option::Option; + use core::result::Result; + use collections::string::String; + } if let ExprMethodCall(ref ident, _, ref args) = expr.node { let ref obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty; if ident.node.name == "unwrap" { diff --git a/src/types.rs b/src/types.rs index 25af398a0b4..aa5f1d13471 100644 --- a/src/types.rs +++ b/src/types.rs @@ -63,10 +63,8 @@ impl LintPass for TypePass { // In case stuff gets moved around use collections::linked_list::LinkedList as DL1; use std::collections::linked_list::LinkedList as DL2; - use std::collections::linked_list::LinkedList as DL3; } let dlists = [vec!["std","collections","linked_list","LinkedList"], - vec!["std","collections","linked_list","LinkedList"], vec!["collections","linked_list","LinkedList"]]; for path in &dlists { if match_ty_unwrap(ty, &path[..]).is_some() { -- cgit 1.4.1-3-g733a5 From 164907ece2beef1bc067ac1f2753706b65b09f98 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 16 Aug 2015 17:24:03 +0530 Subject: restrict toplevel_ref_arg to only functions (fixes #170) --- src/misc.rs | 6 +++++- tests/compile-fail/toplevel_ref_arg.rs | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 1fc41cf4862..82ea78d97e1 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -81,7 +81,11 @@ impl LintPass for TopLevelRefPass { lint_array!(TOPLEVEL_REF_ARG) } - fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + if let FnKind::FkFnBlock = k { + // Does not apply to closures + return + } for ref arg in &decl.inputs { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { span_lint(cx, diff --git a/tests/compile-fail/toplevel_ref_arg.rs b/tests/compile-fail/toplevel_ref_arg.rs index cd4d46ee327..ea69a8cfa15 100644 --- a/tests/compile-fail/toplevel_ref_arg.rs +++ b/tests/compile-fail/toplevel_ref_arg.rs @@ -11,5 +11,8 @@ fn the_answer(ref mut x: u8) { //~ ERROR `ref` directly on a function argument fn main() { let mut x = 0; the_answer(x); + // Closures should not warn + let y = |ref x| { println!("{:?}", x) }; + y(1u8); println!("The answer is {}.", x); } -- cgit 1.4.1-3-g733a5 From 03c7d7074d4870588769707a1a8775489d29280a Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 16 Aug 2015 15:56:09 +0200 Subject: With working test now --- src/consts.rs | 13 ++----------- tests/consts.rs | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index c8d5262abab..fd6479df299 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,4 @@ -#[cfg(test)] use rustc::lint::Context; - use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; @@ -12,9 +10,6 @@ use std::ops::Deref; use self::ConstantVariant::*; use self::FloatWidth::*; -#[cfg(not(test))] -pub struct Context; - #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum FloatWidth { Fw32, @@ -33,8 +28,8 @@ impl From<FloatTy> for FloatWidth { #[derive(PartialEq, Eq, Debug, Clone)] pub struct Constant { - constant: ConstantVariant, - needed_resolution: bool + pub constant: ConstantVariant, + pub needed_resolution: bool } impl Constant { @@ -187,11 +182,7 @@ fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Optio }) } -#[cfg(test)] -fn fetch_path(_cx: &Context, _expr: &Expr) -> Option<Constant> { None } - /// lookup a possibly constant expression from a ExprPath -#[cfg(not(test))] fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { if let Some(&PathResolution { base_def: DefConst(id), ..}) = cx.tcx.def_map.borrow().get(&e.id) { diff --git a/tests/consts.rs b/tests/consts.rs index edbbfa1e2db..db309952be4 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -1,11 +1,34 @@ +#![allow(plugin_as_library)] +#![feature(rustc_private)] extern crate clippy; +extern crate syntax; +extern crate rustc; -use clippy::consts; +use clippy::consts::constant; +use clippy::consts::ConstantVariant::*; use syntax::ast::*; +use syntax::ptr::P; +use syntax::codemap::{Spanned, COMMAND_LINE_SP}; +use std::mem; +use rustc::lint::Context; + +fn ctx() -> &'static Context<'static, 'static> { + unsafe { + let x : *const Context<'static, 'static> = std::ptr::null(); + mem::transmute(x) + } +} #[test] fn test_lit() { - assert_eq!(ConstantBool(true), constant(&Context, - Expr{ node_id: 1, node: ExprLit(LitBool(true)), span: default() })); + assert_eq!(Some(ConstantBool(true)), constant(ctx(), + &Expr{ + id: 1, + node: ExprLit(P(Spanned{ + node: LitBool(true), + span: COMMAND_LINE_SP, + })), + span: COMMAND_LINE_SP, + }).map(|x| x.constant)); } -- cgit 1.4.1-3-g733a5 From fe0de07b28e2e9c1adcb126eea15ff4de14efb5b Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 16 Aug 2015 16:05:51 +0200 Subject: dogfooded --- src/consts.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index fd6479df299..b636fe1e2a8 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -3,7 +3,6 @@ use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; use syntax::ast::*; -use syntax::parse::token::InternedString; use syntax::ptr::P; use std::rc::Rc; use std::ops::Deref; @@ -71,11 +70,11 @@ pub enum ConstantVariant { /// true or false ConstantBool(bool), /// an array of constants - ConstantVec(Box<Vec<Constant>>), + ConstantVec(Vec<Constant>), /// also an array, but with only one constant, repeated N times ConstantRepeat(Box<ConstantVariant>, usize), /// a tuple of constants - ConstantTuple(Box<Vec<Constant>>), + ConstantTuple(Vec<Constant>), } impl ConstantVariant { @@ -159,7 +158,7 @@ fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Optio } } Some(Constant { - constant: ConstantVec(Box::new(parts)), + constant: ConstantVec(parts), needed_resolution: resolved }) } @@ -177,7 +176,7 @@ fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Optio } } Some(Constant { - constant: ConstantTuple(Box::new(parts)), + constant: ConstantTuple(parts), needed_resolution: resolved }) } -- cgit 1.4.1-3-g733a5 From 4244f2479f5959118fa90d99fc098f3c3fc897c3 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 16 Aug 2015 16:09:00 +0200 Subject: dogfooding, part 2 --- src/consts.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index b636fe1e2a8..95232cd8b73 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -148,7 +148,7 @@ fn lit_to_constant(lit: &Lit_) -> Constant { fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Option<Constant> { let mut parts = Vec::new(); let mut resolved = false; - for opt_part in vec.iter() { + for opt_part in vec { match constant(cx, opt_part) { Some(p) => { resolved |= (&p).needed_resolution; @@ -166,7 +166,7 @@ fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Optio fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Option<Constant> { let mut parts = Vec::new(); let mut resolved = false; - for opt_part in tup.iter() { + for opt_part in tup { match constant(cx, opt_part) { Some(p) => { resolved |= (&p).needed_resolution; @@ -224,8 +224,8 @@ fn constant_negate(o: Constant) -> Option<Constant> { UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), _ => { return None; }, }), - ConstantFloat(ref is, ty) => - ConstantFloat(neg_float_str(is.to_string()), ty), + ConstantFloat(is, ty) => + ConstantFloat(neg_float_str(is), ty), _ => { return None; }, } }) @@ -278,7 +278,7 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) BiAdd => constant_binop_apply(cx, left, right, |l, r| match (l, r) { (ConstantByte(l8), ConstantByte(r8)) => - l8.checked_add(r8).map(|v| ConstantByte(v)), + l8.checked_add(r8).map(ConstantByte), (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { let (ln, rn) = (is_negative(lty), is_negative(rty)); if ln == rn { -- cgit 1.4.1-3-g733a5 From e1438e701069a6dbb6e71e1ea90f8e45aba865c4 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 16 Aug 2015 16:13:44 +0200 Subject: copied over cmp_owned fix from master --- tests/compile-fail/cmp_owned.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index 5951dc1bbd7..2e1a8cfd819 100755 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -1,4 +1,4 @@ -#![feature(plugin, collections)] +#![feature(plugin)] #![plugin(clippy)] #[deny(cmp_owned)] @@ -13,11 +13,5 @@ fn main() { x != "foo".to_owned(); //~ERROR this creates an owned instance - #[allow(deprecated)] // for from_str - fn old_timey(x : &str) { - x != String::from_str("foo"); //~ERROR this creates an owned instance - } - old_timey(x); - x != String::from("foo"); //~ERROR this creates an owned instance } -- cgit 1.4.1-3-g733a5 From 23a38c4170887401b3c75f9ad4443ab1f6beae11 Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Sat, 15 Aug 2015 12:55:25 -0400 Subject: New lint: Range::step_by(0) (fixes #95) Uses type information so it can detect non-literal ranges as well (Range or RangeFrom -- the other range types don't have step_by). --- README.md | 1 + src/lib.rs | 3 +++ src/ranges.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/range.rs | 24 +++++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 src/ranges.rs create mode 100644 tests/compile-fail/range.rs diff --git a/README.md b/README.md index d9dea816318..bc82b2ee533 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ non_ascii_literal | allow | using any literal non-ASCII chars in a string l option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead diff --git a/src/lib.rs b/src/lib.rs index 01a2d65606c..91859005bf3 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ pub mod methods; pub mod returns; pub mod lifetimes; pub mod loops; +pub mod ranges; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -64,6 +65,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::LetPass as LintPassObject); reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); + reg.register_lint_pass(box ranges::StepByZero as LintPassObject); reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, @@ -93,6 +95,7 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, ptr_arg::PTR_ARG, + ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_ADD, diff --git a/src/ranges.rs b/src/ranges.rs new file mode 100644 index 00000000000..2981574e502 --- /dev/null +++ b/src/ranges.rs @@ -0,0 +1,52 @@ +use rustc::lint::{Context, LintArray, LintPass}; +use rustc::middle::ty::TypeVariants::TyStruct; +use syntax::ast::*; +use syntax::codemap::Spanned; +use utils::{match_def_path, walk_ptrs_ty}; + +declare_lint! { + pub RANGE_STEP_BY_ZERO, Warn, + "using Range::step_by(0), which produces an infinite iterator" +} + +#[derive(Copy,Clone)] +pub struct StepByZero; + +impl LintPass for StepByZero { + fn get_lints(&self) -> LintArray { + lint_array!(RANGE_STEP_BY_ZERO) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprMethodCall(Spanned { node: ref ident, .. }, _, + ref args) = expr.node { + // Only warn on literal ranges. + if ident.name.as_str() == "step_by" && args.len() == 2 && + is_range(cx, &args[0]) && is_lit_zero(&args[1]) { + cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, + "Range::step_by(0) produces an infinite iterator. \ + Consider using `std::iter::repeat()` instead") + } + } + } +} + +fn is_range(cx: &Context, expr: &Expr) -> bool { + // No need for walk_ptrs_ty here because step_by moves self, so it + // can't be called on a borrowed range. + if let TyStruct(did, _) = cx.tcx.expr_ty(expr).sty { + // Note: RangeTo and RangeFull don't have step_by + match_def_path(cx, did.did, &["core", "ops", "Range"]) || + match_def_path(cx, did.did, &["core", "ops", "RangeFrom"]) + } else { false } +} + +fn is_lit_zero(expr: &Expr) -> bool { + // FIXME: use constant folding + if let ExprLit(ref spanned) = expr.node { + if let LitInt(0, _) = spanned.node { + return true; + } + } + false +} diff --git a/tests/compile-fail/range.rs b/tests/compile-fail/range.rs new file mode 100644 index 00000000000..324f129fafa --- /dev/null +++ b/tests/compile-fail/range.rs @@ -0,0 +1,24 @@ +#![feature(step_by)] +#![feature(plugin)] +#![plugin(clippy)] + +struct NotARange; +impl NotARange { + fn step_by(&self, _: u32) {} +} + +#[deny(range_step_by_zero)] +fn main() { + (0..1).step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator + // No warning for non-zero step + (0..1).step_by(1); + + (1..).step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator + + let x = 0..1; + x.step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator + + // No error, not a range. + let y = NotARange; + y.step_by(0); +} -- cgit 1.4.1-3-g733a5 From 759b45a46d299f19a10477cc226e70002ac91340 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 16 Aug 2015 23:09:56 +0200 Subject: made is_negative(..) public (+doctest), fixed identity_op and precedence --- src/consts.rs | 9 +++++++- src/identity_op.rs | 44 +++++++++++++-------------------------- tests/compile-fail/cmp_owned.rs | 3 +++ tests/compile-fail/identity_op.rs | 8 +++---- tests/compile-fail/precedence.rs | 1 + 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 95232cd8b73..bb74b3c71d1 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -246,7 +246,14 @@ fn neg_float_str(s: String) -> String { } } -fn is_negative(ty: LitIntType) -> bool { +/// is the given LitIntType negative? +/// +/// Examples +/// +/// ``` +/// assert!(is_negative(UnsuffixedIntLit(Minus))); +/// ``` +pub fn is_negative(ty: LitIntType) -> bool { match ty { SignedIntLit(_, sign) | UnsuffixedIntLit(sign) => sign == Minus, UnsignedIntLit(_) => false, diff --git a/src/identity_op.rs b/src/identity_op.rs index 8c6940e3df4..445bef0125b 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -7,6 +7,8 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use syntax::codemap::Span; +use consts::{constant, Constant, is_negative}; +use consts::ConstantVariant::ConstantInt; use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, @@ -47,35 +49,19 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { - if have_lit(cx, e, m) { - span_lint(cx, IDENTITY_OP, span, &format!( - "the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, ".."))); - } -} - -fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { - match &e.node { - &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), - &ExprLit(ref lit) => { - match (&lit.node, m) { - (&LitInt(0, _), 0) => true, - (&LitInt(1, SignedIntLit(_, Plus)), 1) => true, - (&LitInt(1, UnsuffixedIntLit(Plus)), 1) => true, - (&LitInt(1, SignedIntLit(_, Minus)), -1) => true, - (&LitInt(1, UnsuffixedIntLit(Minus)), -1) => true, - _ => false + if let Some(c) = constant(cx, e) { + if c.needed_resolution { return; } // skip linting w/ lookup for now + if let ConstantInt(v, ty) = c.constant { + if match m { + 0 => v == 0, + -1 => is_negative(ty), + 1 => !is_negative(ty), + _ => unreachable!(), + } { + span_lint(cx, IDENTITY_OP, span, &format!( + "the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, ".."))); } - }, - &ExprParen(ref p) => have_lit(cx, p, m), - &ExprPath(_, _) => { - match cx.tcx.def_map.borrow().get(&e.id) { - Some(&PathResolution { base_def: DefConst(id), ..}) => - lookup_const_by_id(cx.tcx, id, Option::None) - .map_or(false, |l| have_lit(cx, l, m)), - _ => false - } - }, - _ => false + } } } diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index 2e1a8cfd819..2765da5cf23 100755 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -13,5 +13,8 @@ fn main() { x != "foo".to_owned(); //~ERROR this creates an owned instance + // removed String::from_str(..), as it has finally been removed in 1.4.0 + // as of 2015-08-14 + x != String::from("foo"); //~ERROR this creates an owned instance } diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index 987bada2ece..18e683e8a9e 100755 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -11,14 +11,14 @@ fn main() { x + 0; //~ERROR the operation is ineffective 0 + x; //~ERROR the operation is ineffective - x - ZERO; //~ERROR the operation is ineffective + x - ZERO; //no error, as we skip lookups (for now) x | (0); //~ERROR the operation is ineffective - ((ZERO)) | x; //~ERROR the operation is ineffective + ((ZERO)) | x; //no error, as we skip lookups (for now) x * 1; //~ERROR the operation is ineffective 1 * x; //~ERROR the operation is ineffective - x / ONE; //~ERROR the operation is ineffective + x / ONE; //no error, as we skip lookups (for now) - x & NEG_ONE; //~ERROR the operation is ineffective + x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; //~ERROR the operation is ineffective } diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs index 4d57f119479..ebb25f61b75 100755 --- a/tests/compile-fail/precedence.rs +++ b/tests/compile-fail/precedence.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #[deny(precedence)] +#[allow(identity_op)] #[allow(eq_op)] fn main() { format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR operator precedence can trip -- cgit 1.4.1-3-g733a5 From e9a41e2374878d8537fab4f607f8f1c1401b0389 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 17 Aug 2015 07:23:57 +0200 Subject: new lint: lint when iterating over any Iterator::next() result (fixes #182) --- README.md | 1 + src/lib.rs | 1 + src/loops.rs | 25 +++++++++++++++++++++---- tests/compile-fail/for_loop.rs | 14 +++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bc82b2ee533..5ec1040b2c4 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ float_cmp | warn | using `==` or `!=` on float values (as floating identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` inline_always | warn | `#[inline(always)]` is a bad idea in most cases +iter_next_loop | warn | for-looping over `_.next()` which is probably not intended len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function diff --git a/src/lib.rs b/src/lib.rs index 967865b2c0c..4c0617b1696 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,7 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, loops::EXPLICIT_ITER_LOOP, + loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, diff --git a/src/loops.rs b/src/loops.rs index 092b5ce1196..44827d08bcd 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,9 +1,10 @@ use rustc::lint::*; use syntax::ast::*; use syntax::visit::{Visitor, walk_expr}; +use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr}; +use utils::{snippet, span_lint, get_parent_expr, match_def_path}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, "for-looping over a range of indices where an iterator over items would do" } @@ -11,12 +12,15 @@ declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } +declare_lint!{ pub ITER_NEXT_LOOP, Warn, + "for-looping over `_.next()` which is probably not intended" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP) + lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -47,11 +51,11 @@ impl LintPass for LoopsPass { } } - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x if let ExprMethodCall(ref method, _, ref args) = arg.node { - // just the receiver, no arguments to iter() or iter_mut() + // just the receiver, no arguments if args.len() == 1 { let method_name = method.node.name; + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x if method_name == "iter" { let object = snippet(cx, args[0].span, "_"); span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( @@ -62,6 +66,19 @@ impl LintPass for LoopsPass { span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( "it is more idiomatic to loop over `&mut {}` instead of `{}.iter_mut()`", object, object)); + // check for looping over Iterator::next() which is not what you want + } else if method_name == "next" { + let method_call = ty::MethodCall::expr(arg.id); + let trt_id = cx.tcx.tables + .borrow().method_map.get(&method_call) + .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + if let Some(trt_id) = trt_id { + if match_def_path(cx, trt_id, &["core", "iter", "Iterator"]) { + span_lint(cx, ITER_NEXT_LOOP, expr.span, + "you are iterating over `Iterator::next()` which is an Option; \ + this will compile but is probably not what you want"); + } + } } } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 550f9869291..a4e3cc31a88 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -1,7 +1,14 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(needless_range_loop, explicit_iter_loop)] +struct Unrelated(Vec<u8>); +impl Unrelated { + fn next(&self) -> std::slice::Iter<u8> { + self.0.iter() + } +} + +#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; @@ -20,4 +27,9 @@ fn main() { for _v in &vec { } // these are fine for _v in &mut vec { } // these are fine + + for _v in vec.iter().next() { } //~ERROR you are iterating over `Iterator::next()` + + let u = Unrelated(vec![]); + for _v in u.next() { } // no error } -- cgit 1.4.1-3-g733a5 From caeb72c47bacfcc9e8be07470d682a562482f502 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 17 Aug 2015 07:30:33 +0200 Subject: loops: fix two trailing periods in lint msgs --- src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 092b5ce1196..064d1eb3932 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -35,12 +35,12 @@ impl LintPass for LoopsPass { if visitor.nonindex { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is used to index `{}`. Consider using \ - `for ({}, item) in {}.iter().enumerate()` or similar iterators.", + `for ({}, item) in {}.iter().enumerate()` or similar iterators", ident.node.name, indexed, ident.node.name, indexed)); } else { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in &{}` or similar iterators.", + Consider using `for item in &{}` or similar iterators", ident.node.name, indexed, indexed)); } } -- cgit 1.4.1-3-g733a5 From 84abfcd22d84431519c029e87c5914389ef008cb Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 11:43:36 +0200 Subject: fix 189, fixed a few warnings, ==/!= for consts, refactored consts test --- src/consts.rs | 8 +++++--- src/identity_op.rs | 8 +++----- src/ranges.rs | 2 +- tests/consts.rs | 37 +++++++++++++++++++++++-------------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index bb74b3c71d1..c931fb15bb8 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -53,7 +53,7 @@ impl Constant { } /// a Lit_-like enum to fold constant `Expr`s into -#[derive(PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] //TODO: A better PartialEq, remove Eq pub enum ConstantVariant { /// a String "abc" ConstantStr(String, StrStyle), @@ -332,10 +332,12 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) //BiBitOr, //BiShl, //BiShr, - //BiEq, + BiEq => constant_binop_apply(cx, left, right, + |l, r| Some(ConstantBool(l == r))), //BiLt, //BiLe, - //BiNe, + BiNe => constant_binop_apply(cx, left, right, + |l, r| Some(ConstantBool(l != r))), //BiGe, //BiGt, _ => None, diff --git a/src/identity_op.rs b/src/identity_op.rs index a429d42c4cc..9f415e5decb 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,10 +1,8 @@ use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; use syntax::ast::*; use syntax::codemap::Span; -use consts::{constant, Constant, is_negative}; +use consts::{constant, is_negative}; use consts::ConstantVariant::ConstantInt; use utils::{span_lint, snippet}; @@ -51,8 +49,8 @@ fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if let ConstantInt(v, ty) = c.constant { if match m { 0 => v == 0, - -1 => is_negative(ty), - 1 => !is_negative(ty), + -1 => is_negative(ty) && v == 1, + 1 => !is_negative(ty) && v == 1, _ => unreachable!(), } { span_lint(cx, IDENTITY_OP, span, &format!( diff --git a/src/ranges.rs b/src/ranges.rs index 2981574e502..bbe65285d58 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -2,7 +2,7 @@ use rustc::lint::{Context, LintArray, LintPass}; use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{match_def_path, walk_ptrs_ty}; +use utils::{match_def_path}; declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, diff --git a/tests/consts.rs b/tests/consts.rs index db309952be4..4f7b87d5e02 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -5,7 +5,7 @@ extern crate clippy; extern crate syntax; extern crate rustc; -use clippy::consts::constant; +use clippy::consts::{constant, ConstantVariant}; use clippy::consts::ConstantVariant::*; use syntax::ast::*; use syntax::ptr::P; @@ -14,21 +14,30 @@ use std::mem; use rustc::lint::Context; fn ctx() -> &'static Context<'static, 'static> { - unsafe { - let x : *const Context<'static, 'static> = std::ptr::null(); - mem::transmute(x) - } + unsafe { + let x : *const Context<'static, 'static> = std::ptr::null(); + mem::transmute(x) + } +} + +fn lit(l: Lit_) -> Expr { + Expr{ + id: 1, + node: ExprLit(P(Spanned{ + node: l, + span: COMMAND_LINE_SP, + })), + span: COMMAND_LINE_SP, + } +} + +fn check(expect: ConstantVariant, expr: &Expr) { + assert_eq!(Some(expect), constant(ctx(), expr).map(|x| x.constant)) } #[test] fn test_lit() { - assert_eq!(Some(ConstantBool(true)), constant(ctx(), - &Expr{ - id: 1, - node: ExprLit(P(Spanned{ - node: LitBool(true), - span: COMMAND_LINE_SP, - })), - span: COMMAND_LINE_SP, - }).map(|x| x.constant)); + check(ConstantBool(true), &lit(LitBool(true))); + check(ConstantBool(false), &lit(LitBool(false))); + } -- cgit 1.4.1-3-g733a5 From f7677b03e1624bc478614d34034c4c59d784cf09 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 11:46:45 +0200 Subject: added regression test for #189 --- tests/compile-fail/identity_op.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index 18e683e8a9e..54551852d5e 100755 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -10,7 +10,10 @@ fn main() { let x = 0; x + 0; //~ERROR the operation is ineffective + x + (1 - 1); //~ERROR the operation is ineffective + x + 1; 0 + x; //~ERROR the operation is ineffective + 1 + x; x - ZERO; //no error, as we skip lookups (for now) x | (0); //~ERROR the operation is ineffective ((ZERO)) | x; //no error, as we skip lookups (for now) @@ -19,6 +22,8 @@ fn main() { 1 * x; //~ERROR the operation is ineffective x / ONE; //no error, as we skip lookups (for now) + x / 2; //no false positive + x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; //~ERROR the operation is ineffective } -- cgit 1.4.1-3-g733a5 From fb715ce45dfb1fbaab94387332bee13f12336a43 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 11:43:36 +0200 Subject: fix 189, fixed a few warnings, ==/!= for consts, refactored consts test --- src/consts.rs | 8 +++++--- src/identity_op.rs | 8 +++----- src/ranges.rs | 2 +- tests/consts.rs | 37 +++++++++++++++++++++++-------------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index bb74b3c71d1..c931fb15bb8 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -53,7 +53,7 @@ impl Constant { } /// a Lit_-like enum to fold constant `Expr`s into -#[derive(PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] //TODO: A better PartialEq, remove Eq pub enum ConstantVariant { /// a String "abc" ConstantStr(String, StrStyle), @@ -332,10 +332,12 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) //BiBitOr, //BiShl, //BiShr, - //BiEq, + BiEq => constant_binop_apply(cx, left, right, + |l, r| Some(ConstantBool(l == r))), //BiLt, //BiLe, - //BiNe, + BiNe => constant_binop_apply(cx, left, right, + |l, r| Some(ConstantBool(l != r))), //BiGe, //BiGt, _ => None, diff --git a/src/identity_op.rs b/src/identity_op.rs index a429d42c4cc..9f415e5decb 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,10 +1,8 @@ use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; use syntax::ast::*; use syntax::codemap::Span; -use consts::{constant, Constant, is_negative}; +use consts::{constant, is_negative}; use consts::ConstantVariant::ConstantInt; use utils::{span_lint, snippet}; @@ -51,8 +49,8 @@ fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if let ConstantInt(v, ty) = c.constant { if match m { 0 => v == 0, - -1 => is_negative(ty), - 1 => !is_negative(ty), + -1 => is_negative(ty) && v == 1, + 1 => !is_negative(ty) && v == 1, _ => unreachable!(), } { span_lint(cx, IDENTITY_OP, span, &format!( diff --git a/src/ranges.rs b/src/ranges.rs index 2981574e502..bbe65285d58 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -2,7 +2,7 @@ use rustc::lint::{Context, LintArray, LintPass}; use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{match_def_path, walk_ptrs_ty}; +use utils::{match_def_path}; declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, diff --git a/tests/consts.rs b/tests/consts.rs index db309952be4..4f7b87d5e02 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -5,7 +5,7 @@ extern crate clippy; extern crate syntax; extern crate rustc; -use clippy::consts::constant; +use clippy::consts::{constant, ConstantVariant}; use clippy::consts::ConstantVariant::*; use syntax::ast::*; use syntax::ptr::P; @@ -14,21 +14,30 @@ use std::mem; use rustc::lint::Context; fn ctx() -> &'static Context<'static, 'static> { - unsafe { - let x : *const Context<'static, 'static> = std::ptr::null(); - mem::transmute(x) - } + unsafe { + let x : *const Context<'static, 'static> = std::ptr::null(); + mem::transmute(x) + } +} + +fn lit(l: Lit_) -> Expr { + Expr{ + id: 1, + node: ExprLit(P(Spanned{ + node: l, + span: COMMAND_LINE_SP, + })), + span: COMMAND_LINE_SP, + } +} + +fn check(expect: ConstantVariant, expr: &Expr) { + assert_eq!(Some(expect), constant(ctx(), expr).map(|x| x.constant)) } #[test] fn test_lit() { - assert_eq!(Some(ConstantBool(true)), constant(ctx(), - &Expr{ - id: 1, - node: ExprLit(P(Spanned{ - node: LitBool(true), - span: COMMAND_LINE_SP, - })), - span: COMMAND_LINE_SP, - }).map(|x| x.constant)); + check(ConstantBool(true), &lit(LitBool(true))); + check(ConstantBool(false), &lit(LitBool(false))); + } -- cgit 1.4.1-3-g733a5 From e354fdc3e8b5dbf8692ead6760ff36903cf952f8 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 11:46:45 +0200 Subject: added regression test for #189 --- tests/compile-fail/identity_op.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index 18e683e8a9e..54551852d5e 100755 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -10,7 +10,10 @@ fn main() { let x = 0; x + 0; //~ERROR the operation is ineffective + x + (1 - 1); //~ERROR the operation is ineffective + x + 1; 0 + x; //~ERROR the operation is ineffective + 1 + x; x - ZERO; //no error, as we skip lookups (for now) x | (0); //~ERROR the operation is ineffective ((ZERO)) | x; //no error, as we skip lookups (for now) @@ -19,6 +22,8 @@ fn main() { 1 * x; //~ERROR the operation is ineffective x / ONE; //no error, as we skip lookups (for now) + x / 2; //no false positive + x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; //~ERROR the operation is ineffective } -- cgit 1.4.1-3-g733a5 From 0e67c0134fbb7764ed7bd1532b0e15f1bfd17044 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 12:06:56 +0200 Subject: make float_cmp check for zero --- src/misc.rs | 5 +++++ tests/compile-fail/float_cmp.rs | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 82ea78d97e1..33c34eb9b84 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -9,6 +9,7 @@ use rustc::middle::ty; use std::borrow::Cow; use utils::{match_path, snippet, snippet_block, span_lint, span_help_and_lint, walk_ptrs_ty}; +use consts::constant; /// Handles uncategorized lints /// Currently handles linting of if-let-able matches @@ -147,6 +148,10 @@ impl LintPass for FloatCmp { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { + if constant(cx, left).or_else(|| constant(cx, right)).map_or( + false, |c| c.as_float().map_or(false, |f| f == 0.0)) { + return; + } span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-comparison of f32 or f64 detected. Consider changing this to \ `abs({} - {}) < epsilon` for some suitable value of epsilon", diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 419e500d0fc..067ec2818bf 100755 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -13,22 +13,30 @@ fn twice<T>(x : T) -> T where T : Add<T, Output = T>, T : Copy { #[deny(float_cmp)] #[allow(unused)] fn main() { - ZERO == 0f32; //~ERROR ==-comparison of f32 or f64 - ZERO == 0.0; //~ERROR ==-comparison of f32 or f64 + ZERO == 0f32; //no error, comparison with zero is ok + ZERO == 0.0; //no error, comparison with zero is ok ZERO + ZERO != 1.0; //~ERROR !=-comparison of f32 or f64 - ONE != 0.0; //~ERROR + ONE == 1f32; //~ERROR ==-comparison of f32 or f64 + ONE == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64 + + ONE + ONE == (ZERO + ONE + ONE); //~ERROR ==-comparison of f32 or f64 + + ONE != 2.0; //~ERROR !=-comparison of f32 or f64 + ONE != 0.0; // no error, comparison with zero is ok twice(ONE) != ONE; //~ERROR !=-comparison of f32 or f64 - ONE as f64 != 0.0; //~ERROR !=-comparison of f32 or f64 + ONE as f64 != 2.0; //~ERROR !=-comparison of f32 or f64 + ONE as f64 != 0.0; // no error, comparison with zero is ok let x : f64 = 1.0; x == 1.0; //~ERROR ==-comparison of f32 or f64 - x != 0f64; //~ERROR !=-comparison of f32 or f64 + x != 0f64; // no error, comparison with zero is ok twice(x) != twice(ONE as f64); //~ERROR !=-comparison of f32 or f64 - x < 0.0; + + x < 0.0; // no errors, lower or greater comparisons need no fuzzyness x > 0.0; x <= 0.0; x >= 0.0; -- cgit 1.4.1-3-g733a5 From 9f134f8e9559a339d5d98f3d3ef9ba3d15ae9b18 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 13:18:14 +0200 Subject: added PartialEq/PartialOrd to ConstantVariant, used to implement comparing binops --- src/consts.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- tests/consts.rs | 6 +++- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index c931fb15bb8..7cbbec1c451 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -4,6 +4,8 @@ use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; use syntax::ast::*; use syntax::ptr::P; +use std::cmp::PartialOrd; +use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; use self::ConstantVariant::*; @@ -52,8 +54,14 @@ impl Constant { } } +impl PartialOrd for Constant { + fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { + self.constant.partial_cmp(&other.constant) + } +} + /// a Lit_-like enum to fold constant `Expr`s into -#[derive(PartialEq, Eq, Debug, Clone)] //TODO: A better PartialEq, remove Eq +#[derive(Eq, Debug, Clone)] pub enum ConstantVariant { /// a String "abc" ConstantStr(String, StrStyle), @@ -92,6 +100,73 @@ impl ConstantVariant { } } +impl PartialEq for ConstantVariant { + fn eq(&self, other: &ConstantVariant) -> bool { + match (self, other) { + (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => + ls == rs && lsty == rsty, + (&ConstantBinary(ref l),&ConstantBinary(ref r)) => l == r, + (&ConstantByte(l), &ConstantByte(r)) => l == r, + (&ConstantChar(l), &ConstantChar(r)) => l == r, + (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => lv == rv && + is_negative(lty) == is_negative(rty), + (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => + if match (lw, rw) { + (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, + _ => false, + } { + match (ls.parse::<f64>(), rs.parse()) { + (Ok(l), Ok(r)) => l == r, + _ => false, + } + } else { false }, + (&ConstantBool(l), &ConstantBool(r)) => l == r, + (&ConstantVec(ref l), &ConstantVec(ref r)) => l == r, + (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => + ls == rs && lv == rv, + (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l == r, + _ => false, //TODO: Are there inter-type equalities? + } + } +} + +impl PartialOrd for ConstantVariant { + fn partial_cmp(&self, other: &ConstantVariant) -> Option<Ordering> { + match (self, other) { + (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => + if lsty != rsty { None } else { Some(ls.cmp(rs)) }, + (&ConstantByte(ref l), &ConstantByte(ref r)) => Some(l.cmp(r)), + (&ConstantChar(ref l), &ConstantChar(ref r)) => Some(l.cmp(r)), + (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => + Some(match (is_negative(lty), is_negative(rty)) { + (true, true) => lv.cmp(rv), + (false, false) => rv.cmp(lv), + (true, false) => Greater, + (false, true) => Less, + }), + (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => + if match (lw, rw) { + (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, + _ => false, + } { + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), + _ => None, + } + } else { None }, + (&ConstantBool(ref l), &ConstantBool(ref r)) => Some(l.cmp(r)), + (&ConstantVec(ref l), &ConstantVec(ref r)) => l.partial_cmp(&r), + (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => + match lv.partial_cmp(rv) { + Some(Equal) => Some(ls.cmp(rs)), + x => x, + }, + (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l.partial_cmp(r), + _ => None, //TODO: Are there any useful inter-type orderings? + } + } +} + /// simple constant folding: Insert an expression, get a constant or none. pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { match &e.node { @@ -300,7 +375,7 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) } } }, - // TODO: float + // TODO: float (would need bignum library?) _ => None }), BiSub => constant_binop_apply(cx, left, right, |l, r| @@ -334,16 +409,22 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) //BiShr, BiEq => constant_binop_apply(cx, left, right, |l, r| Some(ConstantBool(l == r))), - //BiLt, - //BiLe, BiNe => constant_binop_apply(cx, left, right, |l, r| Some(ConstantBool(l != r))), - //BiGe, - //BiGt, + BiLt => constant_cmp(cx, left, right, Less, true), + BiLe => constant_cmp(cx, left, right, Greater, false), + BiGe => constant_cmp(cx, left, right, Less, false), + BiGt => constant_cmp(cx, left, right, Greater, true), _ => None, } } +fn constant_cmp(cx: &Context, left: &Expr, right: &Expr, ordering: Ordering, + b: bool) -> Option<Constant> { + constant_binop_apply(cx, left, right, |l, r| l.partial_cmp(&r).map(|o| + ConstantBool(b == (o == ordering)))) +} + fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> Option<ConstantVariant> { if neg > pos { diff --git a/tests/consts.rs b/tests/consts.rs index 4f7b87d5e02..a7d84ee0ae9 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -8,6 +8,7 @@ extern crate rustc; use clippy::consts::{constant, ConstantVariant}; use clippy::consts::ConstantVariant::*; use syntax::ast::*; +use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; use std::mem; @@ -39,5 +40,8 @@ fn check(expect: ConstantVariant, expr: &Expr) { fn test_lit() { check(ConstantBool(true), &lit(LitBool(true))); check(ConstantBool(false), &lit(LitBool(false))); - + check(ConstantInt(0, UnsuffixedIntLit(Plus)), + &lit(LitInt(0, UnsuffixedIntLit(Plus)))); + check(ConstantStr("cool!".into(), CookedStr), &lit(LitStr( + InternedString::new("cool!"), CookedStr))); } -- cgit 1.4.1-3-g733a5 From 4394362836a2fb8ba0b8c225eb5ef0b441272897 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 13:23:17 +0200 Subject: dogfooding --- src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 7cbbec1c451..e39faf9e39a 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -115,8 +115,8 @@ impl PartialEq for ConstantVariant { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, } { - match (ls.parse::<f64>(), rs.parse()) { - (Ok(l), Ok(r)) => l == r, + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(l), Ok(r)) => l.eq(&r), _ => false, } } else { false }, -- cgit 1.4.1-3-g733a5 From c47402416bf611fa2b7742abfa94ddcef8e5501a Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 15:11:36 +0200 Subject: Added bit operations to const folding --- src/consts.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index e39faf9e39a..01fb3520f2c 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -402,11 +402,11 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) //BiRem, BiAnd => constant_short_circuit(cx, left, right, false), BiOr => constant_short_circuit(cx, left, right, true), - //BiBitXor, - //BiBitAnd, - //BiBitOr, - //BiShl, - //BiShr, + BiBitXor => constant_bitop(cx, left, right, |x, y| x ^ y), + BiBitAnd => constant_bitop(cx, left, right, |x, y| x & y), + BiBitOr => constant_bitop(cx, left, right, |x, y| (x | y)), + BiShl => constant_bitop(cx, left, right, |x, y| x << y), + BiShr => constant_bitop(cx, left, right, |x, y| x >> y), BiEq => constant_binop_apply(cx, left, right, |l, r| Some(ConstantBool(l == r))), BiNe => constant_binop_apply(cx, left, right, @@ -415,10 +415,23 @@ fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) BiLe => constant_cmp(cx, left, right, Greater, false), BiGe => constant_cmp(cx, left, right, Less, false), BiGt => constant_cmp(cx, left, right, Greater, true), - _ => None, + _ => None } } +fn constant_bitop<F>(cx: &Context, left: &Expr, right: &Expr, f: F) + -> Option<Constant> where F: Fn(u64, u64) -> u64 { + constant_binop_apply(cx, left, right, |l, r| match (l, r) { + (ConstantBool(l), ConstantBool(r)) => + Some(ConstantBool(f(l as u64, r as u64) != 0)), + (ConstantByte(l8), ConstantByte(r8)) => + Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), + (ConstantInt(l, lty), ConstantInt(r, rty)) => + unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)), + _ => None + }) +} + fn constant_cmp(cx: &Context, left: &Expr, right: &Expr, ordering: Ordering, b: bool) -> Option<Constant> { constant_binop_apply(cx, left, right, |l, r| l.partial_cmp(&r).map(|o| -- cgit 1.4.1-3-g733a5 From a2ee637be61ef1848e2f5c47a6d3a202057e992f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 17 Aug 2015 16:24:57 +0200 Subject: added test and fixed negativity check in Partial{Eq, Ord} impl --- src/consts.rs | 5 +++-- tests/consts.rs | 44 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 01fb3520f2c..0f212e3b8ef 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -109,7 +109,7 @@ impl PartialEq for ConstantVariant { (&ConstantByte(l), &ConstantByte(r)) => l == r, (&ConstantChar(l), &ConstantChar(r)) => l == r, (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => lv == rv && - is_negative(lty) == is_negative(rty), + (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)), (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, @@ -138,7 +138,8 @@ impl PartialOrd for ConstantVariant { (&ConstantByte(ref l), &ConstantByte(ref r)) => Some(l.cmp(r)), (&ConstantChar(ref l), &ConstantChar(ref r)) => Some(l.cmp(r)), (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => - Some(match (is_negative(lty), is_negative(rty)) { + Some(match (is_negative(lty) && *lv != 0, + is_negative(rty) && *rv != 0) { (true, true) => lv.cmp(rv), (false, false) => rv.cmp(lv), (true, false) => Greater, diff --git a/tests/consts.rs b/tests/consts.rs index a7d84ee0ae9..3b05dd67ad5 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -21,27 +21,53 @@ fn ctx() -> &'static Context<'static, 'static> { } } -fn lit(l: Lit_) -> Expr { +fn spanned<T>(t: T) -> Spanned<T> { + Spanned{ node: t, span: COMMAND_LINE_SP } +} + +fn expr(n: Expr_) -> Expr { Expr{ id: 1, - node: ExprLit(P(Spanned{ - node: l, - span: COMMAND_LINE_SP, - })), + node: n, span: COMMAND_LINE_SP, } } +fn lit(l: Lit_) -> Expr { + expr(ExprLit(P(spanned(l)))) +} + +fn binop(op: BinOp_, l: Expr, r: Expr) -> Expr { + expr(ExprBinary(spanned(op), P(l), P(r))) +} + fn check(expect: ConstantVariant, expr: &Expr) { assert_eq!(Some(expect), constant(ctx(), expr).map(|x| x.constant)) } +const TRUE : ConstantVariant = ConstantBool(true); +const FALSE : ConstantVariant = ConstantBool(false); +const ZERO : ConstantVariant = ConstantInt(0, UnsuffixedIntLit(Plus)); + #[test] fn test_lit() { - check(ConstantBool(true), &lit(LitBool(true))); - check(ConstantBool(false), &lit(LitBool(false))); - check(ConstantInt(0, UnsuffixedIntLit(Plus)), - &lit(LitInt(0, UnsuffixedIntLit(Plus)))); + check(TRUE, &lit(LitBool(true))); + check(FALSE, &lit(LitBool(false))); + check(ZERO, &lit(LitInt(0, UnsuffixedIntLit(Plus)))); check(ConstantStr("cool!".into(), CookedStr), &lit(LitStr( InternedString::new("cool!"), CookedStr))); } + +#[test] +fn test_ops() { + check(TRUE, &binop(BiOr, lit(LitBool(false)), lit(LitBool(true)))); + check(FALSE, &binop(BiAnd, lit(LitBool(false)), lit(LitBool(true)))); + + let litzero = lit(LitInt(0, UnsuffixedIntLit(Plus))); + check(TRUE, &binop(BiEq, litzero.clone(), litzero.clone())); + check(TRUE, &binop(BiGe, litzero.clone(), litzero.clone())); + check(TRUE, &binop(BiLe, litzero.clone(), litzero.clone())); + check(FALSE, &binop(BiNe, litzero.clone(), litzero.clone())); + check(FALSE, &binop(BiGt, litzero.clone(), litzero.clone())); + check(FALSE, &binop(BiLt, litzero.clone(), litzero.clone())); +} -- cgit 1.4.1-3-g733a5 From a2dcbfea65d87a8431a739d38d2a022bc68de15d Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 17 Aug 2015 16:45:50 +0200 Subject: const eval: implement ! for integers --- src/consts.rs | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 0f212e3b8ef..239f72e8774 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -105,7 +105,7 @@ impl PartialEq for ConstantVariant { match (self, other) { (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => ls == rs && lsty == rsty, - (&ConstantBinary(ref l),&ConstantBinary(ref r)) => l == r, + (&ConstantBinary(ref l), &ConstantBinary(ref r)) => l == r, (&ConstantByte(l), &ConstantByte(r)) => l == r, (&ConstantChar(l), &ConstantChar(r)) => l == r, (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => lv == rv && @@ -184,13 +184,7 @@ pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), &ExprUnary(op, ref operand) => constant(cx, operand).and_then( |o| match op { - UnNot => - if let ConstantBool(b) = o.constant { - Some(Constant{ - needed_resolution: o.needed_resolution, - constant: ConstantBool(!b), - }) - } else { None }, + UnNot => constant_not(o), UnNeg => constant_negate(o), UnUniq | UnDeref => Some(o), }), @@ -227,7 +221,7 @@ fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Optio for opt_part in vec { match constant(cx, opt_part) { Some(p) => { - resolved |= (&p).needed_resolution; + resolved |= p.needed_resolution; parts.push(p) }, None => { return None; }, @@ -245,7 +239,7 @@ fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Optio for opt_part in tup { match constant(cx, opt_part) { Some(p) => { - resolved |= (&p).needed_resolution; + resolved |= p.needed_resolution; parts.push(p) }, None => { return None; }, @@ -289,6 +283,43 @@ fn constant_if(cx: &Context, cond: &Expr, then: &Block, otherwise: } else { None } } +fn constant_not(o: Constant) -> Option<Constant> { + Some(Constant { + needed_resolution: o.needed_resolution, + constant: match o.constant { + ConstantBool(b) => ConstantBool(!b), + ConstantInt(value, ty) => { + let (nvalue, nty) = match ty { + SignedIntLit(ity, Plus) => { + if value == ::std::u64::MAX { return None; } + (value + 1, SignedIntLit(ity, Minus)) + }, + SignedIntLit(ity, Minus) => { + if value == 0 { + (1, SignedIntLit(ity, Minus)) + } else { + (value - 1, SignedIntLit(ity, Plus)) + } + } + UnsignedIntLit(ity) => { + let mask = match ity { + UintTy::TyU8 => ::std::u8::MAX as u64, + UintTy::TyU16 => ::std::u16::MAX as u64, + UintTy::TyU32 => ::std::u32::MAX as u64, + UintTy::TyU64 => ::std::u64::MAX, + UintTy::TyUs => { return None; } // refuse to guess + }; + (!value & mask, UnsignedIntLit(ity)) + } + UnsuffixedIntLit(_) => { return None; } // refuse to guess + }; + ConstantInt(nvalue, nty) + }, + _ => { return None; } + } + }) +} + fn constant_negate(o: Constant) -> Option<Constant> { Some(Constant{ needed_resolution: o.needed_resolution, -- cgit 1.4.1-3-g733a5 From 7f52239cab61f58c46f89c1a83616186a873c921 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 17 Aug 2015 17:51:30 +0200 Subject: consts: convert to using a struct with state Struct has the context reference (as an Option) and the needed_resolution flag. --- src/consts.rs | 587 +++++++++++++++++++++++++---------------------------- src/identity_op.rs | 8 +- src/misc.rs | 2 +- tests/consts.rs | 22 +- 4 files changed, 289 insertions(+), 330 deletions(-) mode change 100644 => 100755 tests/consts.rs diff --git a/src/consts.rs b/src/consts.rs index 239f72e8774..df669007b1e 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -8,7 +8,7 @@ use std::cmp::PartialOrd; use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; -use self::ConstantVariant::*; +use self::Constant::*; use self::FloatWidth::*; #[derive(PartialEq, Eq, Debug, Copy, Clone)] @@ -27,42 +27,9 @@ impl From<FloatTy> for FloatWidth { } } -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct Constant { - pub constant: ConstantVariant, - pub needed_resolution: bool -} - -impl Constant { - pub fn new(variant: ConstantVariant) -> Constant { - Constant { constant: variant, needed_resolution: false } - } - - pub fn new_resolved(variant: ConstantVariant) -> Constant { - Constant { constant: variant, needed_resolution: true } - } - - // convert this constant to a f64, if possible - pub fn as_float(&self) -> Option<f64> { - match &self.constant { - &ConstantByte(b) => Some(b as f64), - &ConstantFloat(ref s, _) => s.parse().ok(), - &ConstantInt(i, ty) => Some(if is_negative(ty) { - -(i as f64) } else { i as f64 }), - _ => None - } - } -} - -impl PartialOrd for Constant { - fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { - self.constant.partial_cmp(&other.constant) - } -} - /// a Lit_-like enum to fold constant `Expr`s into #[derive(Eq, Debug, Clone)] -pub enum ConstantVariant { +pub enum Constant { /// a String "abc" ConstantStr(String, StrStyle), /// a Binary String b"abc" @@ -80,12 +47,12 @@ pub enum ConstantVariant { /// an array of constants ConstantVec(Vec<Constant>), /// also an array, but with only one constant, repeated N times - ConstantRepeat(Box<ConstantVariant>, usize), + ConstantRepeat(Box<Constant>, usize), /// a tuple of constants ConstantTuple(Vec<Constant>), } -impl ConstantVariant { +impl Constant { /// convert to u64 if possible /// /// # panics @@ -98,10 +65,21 @@ impl ConstantVariant { panic!("Could not convert a {:?} to u64"); } } + + /// convert this constant to a f64, if possible + pub fn as_float(&self) -> Option<f64> { + match *self { + ConstantByte(b) => Some(b as f64), + ConstantFloat(ref s, _) => s.parse().ok(), + ConstantInt(i, ty) => Some(if is_negative(ty) { + -(i as f64) } else { i as f64 }), + _ => None + } + } } -impl PartialEq for ConstantVariant { - fn eq(&self, other: &ConstantVariant) -> bool { +impl PartialEq for Constant { + fn eq(&self, other: &Constant) -> bool { match (self, other) { (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => ls == rs && lsty == rsty, @@ -130,8 +108,8 @@ impl PartialEq for ConstantVariant { } } -impl PartialOrd for ConstantVariant { - fn partial_cmp(&self, other: &ConstantVariant) -> Option<Ordering> { +impl PartialOrd for Constant { + fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => if lsty != rsty { None } else { Some(ls.cmp(rs)) }, @@ -168,173 +146,67 @@ impl PartialOrd for ConstantVariant { } } -/// simple constant folding: Insert an expression, get a constant or none. -pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> { - match &e.node { - &ExprParen(ref inner) => constant(cx, inner), - &ExprPath(_, _) => fetch_path(cx, e), - &ExprBlock(ref block) => constant_block(cx, block), - &ExprIf(ref cond, ref then, ref otherwise) => - constant_if(cx, &*cond, &*then, &*otherwise), - &ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - &ExprVec(ref vec) => constant_vec(cx, &vec[..]), - &ExprTup(ref tup) => constant_tup(cx, &tup[..]), - &ExprRepeat(ref value, ref number) => - constant_binop_apply(cx, value, number,|v, n| - Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), - &ExprUnary(op, ref operand) => constant(cx, operand).and_then( - |o| match op { - UnNot => constant_not(o), - UnNeg => constant_negate(o), - UnUniq | UnDeref => Some(o), - }), - &ExprBinary(op, ref left, ref right) => - constant_binop(cx, op, left, right), - //TODO: add other expressions - _ => None, - } -} + fn lit_to_constant(lit: &Lit_) -> Constant { match lit { - &LitStr(ref is, style) => - Constant::new(ConstantStr(is.to_string(), style)), - &LitBinary(ref blob) => Constant::new(ConstantBinary(blob.clone())), - &LitByte(b) => Constant::new(ConstantByte(b)), - &LitChar(c) => Constant::new(ConstantChar(c)), - &LitInt(value, ty) => Constant::new(ConstantInt(value, ty)), - &LitFloat(ref is, ty) => { - Constant::new(ConstantFloat(is.to_string(), ty.into())) - }, - &LitFloatUnsuffixed(ref is) => { - Constant::new(ConstantFloat(is.to_string(), FwAny)) - }, - &LitBool(b) => Constant::new(ConstantBool(b)), + &LitStr(ref is, style) => ConstantStr(is.to_string(), style), + &LitBinary(ref blob) => ConstantBinary(blob.clone()), + &LitByte(b) => ConstantByte(b), + &LitChar(c) => ConstantChar(c), + &LitInt(value, ty) => ConstantInt(value, ty), + &LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), + &LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), + &LitBool(b) => ConstantBool(b), } } -/// create `Some(ConstantVec(..))` of all constants, unless there is any -/// non-constant part -fn constant_vec<E: Deref<Target=Expr> + Sized>(cx: &Context, vec: &[E]) -> Option<Constant> { - let mut parts = Vec::new(); - let mut resolved = false; - for opt_part in vec { - match constant(cx, opt_part) { - Some(p) => { - resolved |= p.needed_resolution; - parts.push(p) - }, - None => { return None; }, - } - } - Some(Constant { - constant: ConstantVec(parts), - needed_resolution: resolved - }) -} - -fn constant_tup<E: Deref<Target=Expr> + Sized>(cx: &Context, tup: &[E]) -> Option<Constant> { - let mut parts = Vec::new(); - let mut resolved = false; - for opt_part in tup { - match constant(cx, opt_part) { - Some(p) => { - resolved |= p.needed_resolution; - parts.push(p) - }, - None => { return None; }, - } - } - Some(Constant { - constant: ConstantTuple(parts), - needed_resolution: resolved - }) -} - -/// lookup a possibly constant expression from a ExprPath -fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> { - if let Some(&PathResolution { base_def: DefConst(id), ..}) = - cx.tcx.def_map.borrow().get(&e.id) { - lookup_const_by_id(cx.tcx, id, None).and_then( - |l| constant(cx, l).map(|c| Constant::new_resolved(c.constant))) - } else { None } -} - -/// A block can only yield a constant if it only has one constant expression -fn constant_block(cx: &Context, block: &Block) -> Option<Constant> { - if block.stmts.is_empty() { - block.expr.as_ref().and_then(|b| constant(cx, &*b)) - } else { None } -} - -fn constant_if(cx: &Context, cond: &Expr, then: &Block, otherwise: - &Option<P<Expr>>) -> Option<Constant> { - if let Some(Constant{ constant: ConstantBool(b), needed_resolution: res }) = - constant(cx, cond) { - if b { - constant_block(cx, then) - } else { - otherwise.as_ref().and_then(|expr| constant(cx, &*expr)) - }.map(|part| - Constant { - constant: part.constant, - needed_resolution: res || part.needed_resolution, - }) - } else { None } -} - fn constant_not(o: Constant) -> Option<Constant> { - Some(Constant { - needed_resolution: o.needed_resolution, - constant: match o.constant { - ConstantBool(b) => ConstantBool(!b), - ConstantInt(value, ty) => { - let (nvalue, nty) = match ty { - SignedIntLit(ity, Plus) => { - if value == ::std::u64::MAX { return None; } - (value + 1, SignedIntLit(ity, Minus)) - }, - SignedIntLit(ity, Minus) => { - if value == 0 { - (1, SignedIntLit(ity, Minus)) - } else { - (value - 1, SignedIntLit(ity, Plus)) - } - } - UnsignedIntLit(ity) => { - let mask = match ity { - UintTy::TyU8 => ::std::u8::MAX as u64, - UintTy::TyU16 => ::std::u16::MAX as u64, - UintTy::TyU32 => ::std::u32::MAX as u64, - UintTy::TyU64 => ::std::u64::MAX, - UintTy::TyUs => { return None; } // refuse to guess - }; - (!value & mask, UnsignedIntLit(ity)) + Some(match o { + ConstantBool(b) => ConstantBool(!b), + ConstantInt(value, ty) => { + let (nvalue, nty) = match ty { + SignedIntLit(ity, Plus) => { + if value == ::std::u64::MAX { return None; } + (value + 1, SignedIntLit(ity, Minus)) + }, + SignedIntLit(ity, Minus) => { + if value == 0 { + (1, SignedIntLit(ity, Minus)) + } else { + (value - 1, SignedIntLit(ity, Plus)) } - UnsuffixedIntLit(_) => { return None; } // refuse to guess - }; - ConstantInt(nvalue, nty) - }, - _ => { return None; } - } + } + UnsignedIntLit(ity) => { + let mask = match ity { + UintTy::TyU8 => ::std::u8::MAX as u64, + UintTy::TyU16 => ::std::u16::MAX as u64, + UintTy::TyU32 => ::std::u32::MAX as u64, + UintTy::TyU64 => ::std::u64::MAX, + UintTy::TyUs => { return None; } // refuse to guess + }; + (!value & mask, UnsignedIntLit(ity)) + } + UnsuffixedIntLit(_) => { return None; } // refuse to guess + }; + ConstantInt(nvalue, nty) + }, + _ => { return None; } }) } fn constant_negate(o: Constant) -> Option<Constant> { - Some(Constant{ - needed_resolution: o.needed_resolution, - constant: match o.constant { - ConstantInt(value, ty) => - ConstantInt(value, match ty { - SignedIntLit(ity, sign) => - SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, - }), - ConstantFloat(is, ty) => - ConstantFloat(neg_float_str(is), ty), - _ => { return None; }, - } + Some(match o { + ConstantInt(value, ty) => + ConstantInt(value, match ty { + SignedIntLit(ity, sign) => + SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { return None; }, + }), + ConstantFloat(is, ty) => + ConstantFloat(neg_float_str(is), ty), + _ => { return None; }, }) } @@ -386,92 +258,8 @@ fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { } } -fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr) - -> Option<Constant> { - match op.node { - BiAdd => constant_binop_apply(cx, left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => - l8.checked_add(r8).map(ConstantByte), - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - if ln == rn { - unify_int_type(lty, rty, if ln { Minus } else { Plus }) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))) - } else { - if ln { - add_neg_int(r64, rty, l64, lty) - } else { - add_neg_int(l64, lty, r64, rty) - } - } - }, - // TODO: float (would need bignum library?) - _ => None - }), - BiSub => constant_binop_apply(cx, left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { - None } else { Some(ConstantByte(l8 - r8)) }, - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - match (ln, rn) { - (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), - (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), - (true, false) => unify_int_type(lty, rty, Minus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - (false, true) => unify_int_type(lty, rty, Plus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - } - }, - _ => None, - }), - //BiMul, - //BiDiv, - //BiRem, - BiAnd => constant_short_circuit(cx, left, right, false), - BiOr => constant_short_circuit(cx, left, right, true), - BiBitXor => constant_bitop(cx, left, right, |x, y| x ^ y), - BiBitAnd => constant_bitop(cx, left, right, |x, y| x & y), - BiBitOr => constant_bitop(cx, left, right, |x, y| (x | y)), - BiShl => constant_bitop(cx, left, right, |x, y| x << y), - BiShr => constant_bitop(cx, left, right, |x, y| x >> y), - BiEq => constant_binop_apply(cx, left, right, - |l, r| Some(ConstantBool(l == r))), - BiNe => constant_binop_apply(cx, left, right, - |l, r| Some(ConstantBool(l != r))), - BiLt => constant_cmp(cx, left, right, Less, true), - BiLe => constant_cmp(cx, left, right, Greater, false), - BiGe => constant_cmp(cx, left, right, Less, false), - BiGt => constant_cmp(cx, left, right, Greater, true), - _ => None - } -} - -fn constant_bitop<F>(cx: &Context, left: &Expr, right: &Expr, f: F) - -> Option<Constant> where F: Fn(u64, u64) -> u64 { - constant_binop_apply(cx, left, right, |l, r| match (l, r) { - (ConstantBool(l), ConstantBool(r)) => - Some(ConstantBool(f(l as u64, r as u64) != 0)), - (ConstantByte(l8), ConstantByte(r8)) => - Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), - (ConstantInt(l, lty), ConstantInt(r, rty)) => - unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)), - _ => None - }) -} - -fn constant_cmp(cx: &Context, left: &Expr, right: &Expr, ordering: Ordering, - b: bool) -> Option<Constant> { - constant_binop_apply(cx, left, right, |l, r| l.partial_cmp(&r).map(|o| - ConstantBool(b == (o == ordering)))) -} - fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> - Option<ConstantVariant> { + Option<Constant> { if neg > pos { unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) } else { @@ -480,42 +268,221 @@ fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> } fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> - Option<ConstantVariant> { + Option<Constant> { unify_int_type(lty, rty, if neg { Minus } else { Plus }).and_then( |ty| l.checked_sub(r).map(|v| ConstantInt(v, ty))) } -fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F) - -> Option<Constant> -where F: Fn(ConstantVariant, ConstantVariant) -> Option<ConstantVariant> { - if let (Some(Constant { constant: lc, needed_resolution: ln }), - Some(Constant { constant: rc, needed_resolution: rn })) = - (constant(cx, left), constant(cx, right)) { - op(lc, rc).map(|c| - Constant { - needed_resolution: ln || rn, - constant: c, - }) - } else { None } + +pub fn constant(lcx: &Context, e: &Expr) -> Option<(Constant, bool)> { + let mut cx = ConstEvalContext { lcx: Some(lcx), needed_resolution: false }; + cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } -fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool) -> - Option<Constant> { - constant(cx, left).and_then(|left| - if let &ConstantBool(lbool) = &left.constant { - if lbool == b { - Some(left) +pub fn constant_simple(e: &Expr) -> Option<Constant> { + let mut cx = ConstEvalContext { lcx: None, needed_resolution: false }; + cx.expr(e) +} + +struct ConstEvalContext<'c, 'cc: 'c> { + lcx: Option<&'c Context<'c, 'cc>>, + needed_resolution: bool +} + +impl<'c, 'cc> ConstEvalContext<'c, 'cc> { + + /// simple constant folding: Insert an expression, get a constant or none. + fn expr(&mut self, e: &Expr) -> Option<Constant> { + match &e.node { + &ExprParen(ref inner) => self.expr(inner), + &ExprPath(_, _) => self.fetch_path(e), + &ExprBlock(ref block) => self.block(block), + &ExprIf(ref cond, ref then, ref otherwise) => + self.ifthenelse(&*cond, &*then, &*otherwise), + &ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), + &ExprVec(ref vec) => self.vec(&vec[..]), + &ExprTup(ref tup) => self.tup(&tup[..]), + &ExprRepeat(ref value, ref number) => + self.binop_apply(value, number,|v, n| + Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), + &ExprUnary(op, ref operand) => self.expr(operand).and_then( + |o| match op { + UnNot => constant_not(o), + UnNeg => constant_negate(o), + UnUniq | UnDeref => Some(o), + }), + &ExprBinary(op, ref left, ref right) => + self.binop(op, left, right), + //TODO: add other expressions + _ => None, + } + } + + /// create `Some(ConstantVec(..))` of all constants, unless there is any + /// non-constant part + fn vec<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> Option<Constant> { + let mut parts = Vec::new(); + for opt_part in vec { + match self.expr(opt_part) { + Some(p) => { + parts.push(p) + }, + None => { return None; }, + } + } + Some(ConstantVec(parts)) + } + + fn tup<E: Deref<Target=Expr> + Sized>(&mut self, tup: &[E]) -> Option<Constant> { + let mut parts = Vec::new(); + for opt_part in tup { + match self.expr(opt_part) { + Some(p) => { + parts.push(p) + }, + None => { return None; }, + } + } + Some(ConstantTuple(parts),) + } + + /// lookup a possibly constant expression from a ExprPath + fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { + if let Some(lcx) = self.lcx { + if let Some(&PathResolution { base_def: DefConst(id), ..}) = + lcx.tcx.def_map.borrow().get(&e.id) { + if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None) { + let ret = self.expr(const_expr); + if ret.is_some() { + self.needed_resolution = true; + } + return ret; + } + } + } + None + } + + /// A block can only yield a constant if it only has one constant expression + fn block(&mut self, block: &Block) -> Option<Constant> { + if block.stmts.is_empty() { + block.expr.as_ref().and_then(|b| self.expr(&*b)) + } else { None } + } + + fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) + -> Option<Constant> { + if let Some(ConstantBool(b)) = self.expr(cond) { + if b { + self.block(then) } else { - constant(cx, right).and_then(|right| - if let ConstantBool(_) = right.constant { - Some(Constant { - constant: right.constant, - needed_resolution: left.needed_resolution || - right.needed_resolution, - }) - } else { None } - ) + otherwise.as_ref().and_then(|expr| self.expr(&*expr)) } } else { None } - ) + } + + fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { + match op.node { + BiAdd => self.binop_apply(left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => + l8.checked_add(r8).map(ConstantByte), + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + if ln == rn { + unify_int_type(lty, rty, if ln { Minus } else { Plus }) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))) + } else { + if ln { + add_neg_int(r64, rty, l64, lty) + } else { + add_neg_int(l64, lty, r64, rty) + } + } + }, + // TODO: float (would need bignum library?) + _ => None + }), + BiSub => self.binop_apply(left, right, |l, r| + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { + None } else { Some(ConstantByte(l8 - r8)) }, + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + match (ln, rn) { + (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), + (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), + (true, false) => unify_int_type(lty, rty, Minus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + (false, true) => unify_int_type(lty, rty, Plus) + .and_then(|ty| l64.checked_add(r64).map( + |v| ConstantInt(v, ty))), + } + }, + _ => None, + }), + //BiMul, + //BiDiv, + //BiRem, + BiAnd => self.short_circuit(left, right, false), + BiOr => self.short_circuit(left, right, true), + BiBitXor => self.bitop(left, right, |x, y| x ^ y), + BiBitAnd => self.bitop(left, right, |x, y| x & y), + BiBitOr => self.bitop(left, right, |x, y| (x | y)), + BiShl => self.bitop(left, right, |x, y| x << y), + BiShr => self.bitop(left, right, |x, y| x >> y), + BiEq => self.binop_apply(left, right, + |l, r| Some(ConstantBool(l == r))), + BiNe => self.binop_apply(left, right, + |l, r| Some(ConstantBool(l != r))), + BiLt => self.cmp(left, right, Less, true), + BiLe => self.cmp(left, right, Greater, false), + BiGe => self.cmp(left, right, Less, false), + BiGt => self.cmp(left, right, Greater, true), + _ => None + } + } + + fn bitop<F>(&mut self, left: &Expr, right: &Expr, f: F) + -> Option<Constant> where F: Fn(u64, u64) -> u64 { + self.binop_apply(left, right, |l, r| match (l, r) { + (ConstantBool(l), ConstantBool(r)) => + Some(ConstantBool(f(l as u64, r as u64) != 0)), + (ConstantByte(l8), ConstantByte(r8)) => + Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), + (ConstantInt(l, lty), ConstantInt(r, rty)) => + unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)), + _ => None + }) + } + + fn cmp(&mut self, left: &Expr, right: &Expr, ordering: Ordering, b: bool) -> Option<Constant> { + self.binop_apply(left, right, |l, r| l.partial_cmp(&r).map(|o| + ConstantBool(b == (o == ordering)))) + } + + fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> + where F: Fn(Constant, Constant) -> Option<Constant> { + if let (Some(lc), Some(rc)) = (self.expr(left), self.expr(right)) { + op(lc, rc) + } else { None } + } + + fn short_circuit(&mut self, left: &Expr, right: &Expr, b: bool) -> Option<Constant> { + self.expr(left).and_then(|left| + if let &ConstantBool(lbool) = &left { + if lbool == b { + Some(left) + } else { + self.expr(right).and_then(|right| + if let ConstantBool(_) = right { + Some(right) + } else { None } + ) + } + } else { None } + ) + } } diff --git a/src/identity_op.rs b/src/identity_op.rs index 9f415e5decb..cd7d6351c80 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -3,7 +3,7 @@ use syntax::ast::*; use syntax::codemap::Span; use consts::{constant, is_negative}; -use consts::ConstantVariant::ConstantInt; +use consts::Constant::ConstantInt; use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, @@ -44,9 +44,9 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(c) = constant(cx, e) { - if c.needed_resolution { return; } // skip linting w/ lookup for now - if let ConstantInt(v, ty) = c.constant { + if let Some((c, needed_resolution)) = constant(cx, e) { + if needed_resolution { return; } // skip linting w/ lookup for now + if let ConstantInt(v, ty) = c { if match m { 0 => v == 0, -1 => is_negative(ty) && v == 1, diff --git a/src/misc.rs b/src/misc.rs index 33c34eb9b84..aca849931bb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -149,7 +149,7 @@ impl LintPass for FloatCmp { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { if constant(cx, left).or_else(|| constant(cx, right)).map_or( - false, |c| c.as_float().map_or(false, |f| f == 0.0)) { + false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { return; } span_lint(cx, FLOAT_CMP, expr.span, &format!( diff --git a/tests/consts.rs b/tests/consts.rs old mode 100644 new mode 100755 index 3b05dd67ad5..bcc5aa4c30a --- a/tests/consts.rs +++ b/tests/consts.rs @@ -5,21 +5,13 @@ extern crate clippy; extern crate syntax; extern crate rustc; -use clippy::consts::{constant, ConstantVariant}; -use clippy::consts::ConstantVariant::*; use syntax::ast::*; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; -use std::mem; -use rustc::lint::Context; -fn ctx() -> &'static Context<'static, 'static> { - unsafe { - let x : *const Context<'static, 'static> = std::ptr::null(); - mem::transmute(x) - } -} +use clippy::consts::{constant_simple, Constant}; +use clippy::consts::Constant::*; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } @@ -41,13 +33,13 @@ fn binop(op: BinOp_, l: Expr, r: Expr) -> Expr { expr(ExprBinary(spanned(op), P(l), P(r))) } -fn check(expect: ConstantVariant, expr: &Expr) { - assert_eq!(Some(expect), constant(ctx(), expr).map(|x| x.constant)) +fn check(expect: Constant, expr: &Expr) { + assert_eq!(Some(expect), constant_simple(expr)) } -const TRUE : ConstantVariant = ConstantBool(true); -const FALSE : ConstantVariant = ConstantBool(false); -const ZERO : ConstantVariant = ConstantInt(0, UnsuffixedIntLit(Plus)); +const TRUE : Constant = ConstantBool(true); +const FALSE : Constant = ConstantBool(false); +const ZERO : Constant = ConstantInt(0, UnsuffixedIntLit(Plus)); #[test] fn test_lit() { -- cgit 1.4.1-3-g733a5 From 49ad73f6e46b5ac400e1c7dd117646146e1ef722 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 17 Aug 2015 19:55:59 +0200 Subject: consts: minor improvements --- src/consts.rs | 76 ++++++++++++++++++++++++----------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index df669007b1e..07bde1d0b08 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -59,7 +59,7 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let &ConstantInt(val, _) = self { + if let ConstantInt(val, _) = *self { val // TODO we may want to check the sign if any } else { panic!("Could not convert a {:?} to u64"); @@ -149,15 +149,15 @@ impl PartialOrd for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { - match lit { - &LitStr(ref is, style) => ConstantStr(is.to_string(), style), - &LitBinary(ref blob) => ConstantBinary(blob.clone()), - &LitByte(b) => ConstantByte(b), - &LitChar(c) => ConstantChar(c), - &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), - &LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), - &LitBool(b) => ConstantBool(b), + match *lit { + LitStr(ref is, style) => ConstantStr(is.to_string(), style), + LitBinary(ref blob) => ConstantBinary(blob.clone()), + LitByte(b) => ConstantByte(b), + LitChar(c) => ConstantChar(c), + LitInt(value, ty) => ConstantInt(value, ty), + LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), + LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), + LitBool(b) => ConstantBool(b), } } @@ -293,25 +293,25 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// simple constant folding: Insert an expression, get a constant or none. fn expr(&mut self, e: &Expr) -> Option<Constant> { - match &e.node { - &ExprParen(ref inner) => self.expr(inner), - &ExprPath(_, _) => self.fetch_path(e), - &ExprBlock(ref block) => self.block(block), - &ExprIf(ref cond, ref then, ref otherwise) => + match e.node { + ExprParen(ref inner) => self.expr(inner), + ExprPath(_, _) => self.fetch_path(e), + ExprBlock(ref block) => self.block(block), + ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(&*cond, &*then, &*otherwise), - &ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - &ExprVec(ref vec) => self.vec(&vec[..]), - &ExprTup(ref tup) => self.tup(&tup[..]), - &ExprRepeat(ref value, ref number) => - self.binop_apply(value, number,|v, n| + ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), + ExprVec(ref vec) => self.vec(&vec), + ExprTup(ref tup) => self.tup(&tup), + ExprRepeat(ref value, ref number) => + self.binop_apply(value, number, |v, n| Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), - &ExprUnary(op, ref operand) => self.expr(operand).and_then( + ExprUnary(op, ref operand) => self.expr(operand).and_then( |o| match op { UnNot => constant_not(o), UnNeg => constant_negate(o), UnUniq | UnDeref => Some(o), }), - &ExprBinary(op, ref left, ref right) => + ExprBinary(op, ref left, ref right) => self.binop(op, left, right), //TODO: add other expressions _ => None, @@ -321,29 +321,15 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// create `Some(ConstantVec(..))` of all constants, unless there is any /// non-constant part fn vec<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> Option<Constant> { - let mut parts = Vec::new(); - for opt_part in vec { - match self.expr(opt_part) { - Some(p) => { - parts.push(p) - }, - None => { return None; }, - } - } - Some(ConstantVec(parts)) + vec.iter().map(|elem| self.expr(elem)) + .collect::<Option<_>>() + .map(ConstantVec) } fn tup<E: Deref<Target=Expr> + Sized>(&mut self, tup: &[E]) -> Option<Constant> { - let mut parts = Vec::new(); - for opt_part in tup { - match self.expr(opt_part) { - Some(p) => { - parts.push(p) - }, - None => { return None; }, - } - } - Some(ConstantTuple(parts),) + tup.iter().map(|elem| self.expr(elem)) + .collect::<Option<_>>() + .map(ConstantTuple) } /// lookup a possibly constant expression from a ExprPath @@ -366,7 +352,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// A block can only yield a constant if it only has one constant expression fn block(&mut self, block: &Block) -> Option<Constant> { if block.stmts.is_empty() { - block.expr.as_ref().and_then(|b| self.expr(&*b)) + block.expr.as_ref().and_then(|ref b| self.expr(b)) } else { None } } @@ -376,7 +362,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { if b { self.block(then) } else { - otherwise.as_ref().and_then(|expr| self.expr(&*expr)) + otherwise.as_ref().and_then(|ref expr| self.expr(expr)) } } else { None } } @@ -472,7 +458,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { fn short_circuit(&mut self, left: &Expr, right: &Expr, b: bool) -> Option<Constant> { self.expr(left).and_then(|left| - if let &ConstantBool(lbool) = &left { + if let ConstantBool(lbool) = left { if lbool == b { Some(left) } else { -- cgit 1.4.1-3-g733a5 From 6e0c103133b14fbad4803c87da71fd13aec2269f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 18 Aug 2015 12:26:01 +0200 Subject: more small const improvements --- src/consts.rs | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 07bde1d0b08..4d23ce07df2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -59,7 +59,7 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let ConstantInt(val, _) = *self { + if let &ConstantInt(val, _) = self { val // TODO we may want to check the sign if any } else { panic!("Could not convert a {:?} to u64"); @@ -149,15 +149,15 @@ impl PartialOrd for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { - match *lit { - LitStr(ref is, style) => ConstantStr(is.to_string(), style), - LitBinary(ref blob) => ConstantBinary(blob.clone()), - LitByte(b) => ConstantByte(b), - LitChar(c) => ConstantChar(c), - LitInt(value, ty) => ConstantInt(value, ty), - LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), - LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), - LitBool(b) => ConstantBool(b), + match lit { + &LitStr(ref is, style) => ConstantStr(is.to_string(), style), + &LitBinary(ref blob) => ConstantBinary(blob.clone()), + &LitByte(b) => ConstantByte(b), + &LitChar(c) => ConstantChar(c), + &LitInt(value, ty) => ConstantInt(value, ty), + &LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), + &LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), + &LitBool(b) => ConstantBool(b), } } @@ -300,8 +300,8 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(&*cond, &*then, &*otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - ExprVec(ref vec) => self.vec(&vec), - ExprTup(ref tup) => self.tup(&tup), + ExprVec(ref vec) => self.multi(&vec[..]).map(ConstantVec), + ExprTup(ref tup) => self.multi(&tup[..]).map(ConstantTuple), ExprRepeat(ref value, ref number) => self.binop_apply(value, number, |v, n| Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), @@ -318,18 +318,12 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { } } - /// create `Some(ConstantVec(..))` of all constants, unless there is any + /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part - fn vec<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> Option<Constant> { + fn multi<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> + Option<Vec<Constant>> { vec.iter().map(|elem| self.expr(elem)) .collect::<Option<_>>() - .map(ConstantVec) - } - - fn tup<E: Deref<Target=Expr> + Sized>(&mut self, tup: &[E]) -> Option<Constant> { - tup.iter().map(|elem| self.expr(elem)) - .collect::<Option<_>>() - .map(ConstantTuple) } /// lookup a possibly constant expression from a ExprPath -- cgit 1.4.1-3-g733a5 From 9f67ba7f8d588f1d7a39d1b34fa7e2a7e6209bda Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 18 Aug 2015 14:18:36 +0200 Subject: re-applied birkenfeld's improvements --- src/consts.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 4d23ce07df2..c069539a077 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -59,7 +59,7 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let &ConstantInt(val, _) = self { + if let ConstantInt(val, _) = *self { val // TODO we may want to check the sign if any } else { panic!("Could not convert a {:?} to u64"); @@ -149,15 +149,15 @@ impl PartialOrd for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { - match lit { - &LitStr(ref is, style) => ConstantStr(is.to_string(), style), - &LitBinary(ref blob) => ConstantBinary(blob.clone()), - &LitByte(b) => ConstantByte(b), - &LitChar(c) => ConstantChar(c), - &LitInt(value, ty) => ConstantInt(value, ty), - &LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), - &LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), - &LitBool(b) => ConstantBool(b), + match *lit { + LitStr(ref is, style) => ConstantStr(is.to_string(), style), + LitBinary(ref blob) => ConstantBinary(blob.clone()), + LitByte(b) => ConstantByte(b), + LitChar(c) => ConstantChar(c), + LitInt(value, ty) => ConstantInt(value, ty), + LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), + LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), + LitBool(b) => ConstantBool(b), } } @@ -300,8 +300,8 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(&*cond, &*then, &*otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - ExprVec(ref vec) => self.multi(&vec[..]).map(ConstantVec), - ExprTup(ref tup) => self.multi(&tup[..]).map(ConstantTuple), + ExprVec(ref vec) => self.multi(vec).map(ConstantVec), + ExprTup(ref tup) => self.multi(tup).map(ConstantTuple), ExprRepeat(ref value, ref number) => self.binop_apply(value, number, |v, n| Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), -- cgit 1.4.1-3-g733a5 From 8f4499f3aedd9fabb624318210bd69f0a8de1757 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 19 Aug 2015 06:54:20 +0200 Subject: new lint: comparing unit types (fixes #201) --- README.md | 1 + src/lib.rs | 2 ++ src/types.rs | 29 +++++++++++++++++++++++++++++ tests/compile-fail/unit_cmp.rs | 17 +++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100755 tests/compile-fail/unit_cmp.rs diff --git a/README.md b/README.md index 5ec1040b2c4..e6a4d1be514 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ string_add | allow | using `x + ..` where x is a `String`; suggests string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead string_to_string | warn | calling `String.to_string()` which is a no-op toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) zero_width_space | deny | using a zero-width space in a string literal, which is confusing To use, add the following lines to your Cargo.toml: diff --git a/src/lib.rs b/src/lib.rs index d7a10562df1..50ebbd6d9fd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); + reg.register_lint_pass(box types::UnitCmp as LintPassObject); reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); reg.register_lint_pass(box ranges::StepByZero as LintPassObject); @@ -105,6 +106,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::BOX_VEC, types::LET_UNIT_VALUE, types::LINKEDLIST, + types::UNIT_CMP, unicode::NON_ASCII_LITERAL, unicode::ZERO_WIDTH_SPACE, ]); diff --git a/src/types.rs b/src/types.rs index aa5f1d13471..617c51fd961 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,7 @@ use rustc::lint::*; use syntax::ast; use syntax::ast::*; +use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::ptr::P; use rustc::middle::ty; use syntax::codemap::ExpnInfo; @@ -107,3 +108,31 @@ impl LintPass for LetPass { |info| check_let_unit(cx, decl, info)); } } + +declare_lint!(pub UNIT_CMP, Warn, + "comparing unit values (which is always `true` or `false`, respectively)"); + +#[allow(missing_copy_implementations)] +pub struct UnitCmp; + +impl LintPass for UnitCmp { + fn get_lints(&self) -> LintArray { + lint_array!(UNIT_CMP) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, _) = expr.node { + let op = cmp.node; + let sty = &cx.tcx.expr_ty(left).sty; + if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) { + let result = match op { + BiEq | BiLe | BiGe => "true", + _ => "false" + }; + span_lint(cx, UNIT_CMP, expr.span, &format!( + "{}-comparison of unit values detected. This will always be {}", + binop_to_string(op), result)); + } + } + } +} diff --git a/tests/compile-fail/unit_cmp.rs b/tests/compile-fail/unit_cmp.rs new file mode 100755 index 00000000000..e246d9f3909 --- /dev/null +++ b/tests/compile-fail/unit_cmp.rs @@ -0,0 +1,17 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(unit_cmp)] + +fn main() { + // this is fine + if true == false { + } + + // this warns + if { true; } == { false; } { //~ERROR ==-comparison of unit values detected. This will always be true + } + + if { true; } > { false; } { //~ERROR >-comparison of unit values detected. This will always be false + } +} -- cgit 1.4.1-3-g733a5 From 98d24b5b5601d60f113ea14232416ce545f0cf73 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 19 Aug 2015 09:07:50 +0200 Subject: fixed #203 and #197 --- src/bit_mask.rs | 40 +++++++++++++++++++++++++++++----------- tests/compile-fail/bit_masks.rs | 11 ++++++++--- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index ec937dbab6c..7789381da23 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -39,7 +39,13 @@ declare_lint! { /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* -/// by default +/// by default. +/// +/// |Comparison|Bit-Op |Example |equals |Formula| +/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| +/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | +/// +/// `¹ power_of_two(c + 1)` #[derive(Copy,Clone)] pub struct BitMask; @@ -127,12 +133,10 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, "incompatible bit mask: `_ | {}` will never be lower than `{}`", mask_value, cmp_value)); } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", - mask_value, cmp_value)); - } + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); }, + BiBitXor => + check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), _ => () }, BiLe | BiGt => match bit_op { @@ -151,18 +155,32 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, "incompatible bit mask: `_ | {}` will always be higher than `{}`", mask_value, cmp_value)); } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", - mask_value, cmp_value)); - } + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); }, + BiBitXor => + check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), _ => () }, _ => () } } +fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { + if c.is_power_of_two() && m < c { + span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, m, c)); + } +} + +fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { + if (c + 1).is_power_of_two() && m <= c { + span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, m, c)); + } +} + fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option<u64> { match &lit.node { &ExprLit(ref lit_ptr) => { diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index bcbfe99e42e..47e9c11138a 100755 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -46,8 +46,13 @@ fn main() { fn ineffective() { let x = 5; - x | 1 > 2; //~ERROR ineffective bit mask - x | 1 < 3; //~ERROR ineffective bit mask + x | 1 > 3; //~ERROR ineffective bit mask + x | 1 < 4; //~ERROR ineffective bit mask x | 1 <= 3; //~ERROR ineffective bit mask - x | 1 >= 2; //~ERROR ineffective bit mask + x | 1 >= 8; //~ERROR ineffective bit mask + + x | 1 > 2; // not an error (yet), better written as x >= 2 + x | 1 >= 7; // not an error (yet), better written as x >= 6 + x | 3 > 4; // not an error (yet), better written as x >= 4 + x | 4 <= 19; } -- cgit 1.4.1-3-g733a5 From 973d5e5c6b58d7b2404f52bbb8b5eb5918defd9c Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 19 Aug 2015 11:58:59 +0200 Subject: Mul and Div for integers --- src/consts.rs | 28 ++++++++++++++++++++-------- tests/consts.rs | 9 +++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index c069539a077..5056cc27a54 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -320,7 +320,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part - fn multi<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> + fn multi<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> Option<Vec<Constant>> { vec.iter().map(|elem| self.expr(elem)) .collect::<Option<_>>() @@ -388,9 +388,8 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { match (l, r) { (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { None } else { Some(ConstantByte(l8 - r8)) }, - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - match (ln, rn) { + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => + match (is_negative(lty), is_negative(rty)) { (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), (true, false) => unify_int_type(lty, rty, Minus) @@ -399,12 +398,11 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { (false, true) => unify_int_type(lty, rty, Plus) .and_then(|ty| l64.checked_add(r64).map( |v| ConstantInt(v, ty))), - } - }, + }, _ => None, }), - //BiMul, - //BiDiv, + BiMul => self.divmul(left, right, u64::checked_mul), + BiDiv => self.divmul(left, right, u64::checked_div), //BiRem, BiAnd => self.short_circuit(left, right, false), BiOr => self.short_circuit(left, right, true), @@ -425,6 +423,20 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { } } + fn divmul<F>(&mut self, left: &Expr, right: &Expr, f: F) + -> Option<Constant> where F: Fn(u64, u64) -> Option<u64> { + self.binop_apply(left, right, |l, r| + match (l, r) { + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + f(l64, r64).and_then(|value| + unify_int_type(lty, rty, if is_negative(lty) == + is_negative(rty) { Plus } else { Minus }) + .map(|ty| ConstantInt(value, ty))) + }, + _ => None, + }) + } + fn bitop<F>(&mut self, left: &Expr, right: &Expr, f: F) -> Option<Constant> where F: Fn(u64, u64) -> u64 { self.binop_apply(left, right, |l, r| match (l, r) { diff --git a/tests/consts.rs b/tests/consts.rs index bcc5aa4c30a..55270cc6b51 100755 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -40,6 +40,8 @@ fn check(expect: Constant, expr: &Expr) { const TRUE : Constant = ConstantBool(true); const FALSE : Constant = ConstantBool(false); const ZERO : Constant = ConstantInt(0, UnsuffixedIntLit(Plus)); +const ONE : Constant = ConstantInt(1, UnsuffixedIntLit(Plus)); +const TWO : Constant = ConstantInt(2, UnsuffixedIntLit(Plus)); #[test] fn test_lit() { @@ -56,10 +58,17 @@ fn test_ops() { check(FALSE, &binop(BiAnd, lit(LitBool(false)), lit(LitBool(true)))); let litzero = lit(LitInt(0, UnsuffixedIntLit(Plus))); + let litone = lit(LitInt(1, UnsuffixedIntLit(Plus))); check(TRUE, &binop(BiEq, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiGe, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiLe, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiNe, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiGt, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiLt, litzero.clone(), litzero.clone())); + + check(ZERO, &binop(BiAdd, litzero.clone(), litzero.clone())); + check(TWO, &binop(BiAdd, litone.clone(), litone.clone())); + check(ONE, &binop(BiSub, litone.clone(), litzero.clone())); + check(ONE, &binop(BiMul, litone.clone(), litone.clone())); + check(ONE, &binop(BiDiv, litone.clone(), litone.clone())); } -- cgit 1.4.1-3-g733a5 From 993239d33af2b91fcd5e6dbec30f3810c8178ae3 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 00:04:01 +0200 Subject: Initial implementation of lossy cast lints. Introduces 3 lints : cast_possible_overflow cast_precision_loss cast_sign_loss Add a compile-test test case. Fix errors spotted by dogfood script. --- README.md | 85 ++++++++++++++-------------- src/consts.rs | 19 ++++--- src/lib.rs | 4 ++ src/types.rs | 135 ++++++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/cast.rs | 31 +++++++++++ 5 files changed, 223 insertions(+), 51 deletions(-) create mode 100644 tests/compile-fail/cast.rs diff --git a/README.md b/README.md index e6a4d1be514..df097ca9e3f 100644 --- a/README.md +++ b/README.md @@ -6,47 +6,50 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints Lints included in this crate: -name | default | meaning ----------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) -cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` -ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -inline_always | warn | `#[inline(always)]` is a bad idea in most cases -iter_next_loop | warn | for-looping over `_.next()` which is probably not intended -len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` -len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function -let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf -modulo_one | warn | taking a number modulo 1, which always returns 0 -mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do -needless_return | warn | using a return statement like `return expr;` where an expression would suffice -non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` -ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator -redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled -single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` -string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -string_to_string | warn | calling `String.to_string()` which is a no-op -toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) -unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) -zero_width_space | deny | using a zero-width space in a string literal, which is confusing +name | default | meaning +-----------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +cast_possible_overflow | allow | casts that may cause overflow +cast_precision_loss | allow | casts that cause loss of precision +cast_sign_loss | allow | casts from signed types to unsigned types +cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) +cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` +ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +inline_always | warn | `#[inline(always)]` is a bad idea in most cases +iter_next_loop | warn | for-looping over `_.next()` which is probably not intended +len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` +len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +modulo_one | warn | taking a number modulo 1, which always returns 0 +mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do +needless_return | warn | using a return statement like `return expr;` where an expression would suffice +non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` +ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator +redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled +single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` +string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +string_to_string | warn | calling `String.to_string()` which is a no-op +toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) +zero_width_space | deny | using a zero-width space in a string literal, which is confusing To use, add the following lines to your Cargo.toml: diff --git a/src/consts.rs b/src/consts.rs index 5056cc27a54..c033888e360 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -67,15 +67,16 @@ impl Constant { } /// convert this constant to a f64, if possible - pub fn as_float(&self) -> Option<f64> { - match *self { - ConstantByte(b) => Some(b as f64), - ConstantFloat(ref s, _) => s.parse().ok(), - ConstantInt(i, ty) => Some(if is_negative(ty) { - -(i as f64) } else { i as f64 }), - _ => None - } - } + #[allow(unknown_lints,cast_precision_loss)] + pub fn as_float(&self) -> Option<f64> { + match *self { + ConstantByte(b) => Some(b as f64), + ConstantFloat(ref s, _) => s.parse().ok(), + ConstantInt(i, ty) => Some(if is_negative(ty) { + -(i as f64) } else { i as f64 }), + _ => None + } + } } impl PartialEq for Constant { diff --git a/src/lib.rs b/src/lib.rs index 50ebbd6d9fd..1b4d77dacca 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,6 +68,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box loops::LoopsPass as LintPassObject); reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); reg.register_lint_pass(box ranges::StepByZero as LintPassObject); + reg.register_lint_pass(box types::CastPass as LintPassObject); reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, @@ -104,6 +105,9 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::BOX_VEC, + types::CAST_POSSIBLE_OVERFLOW, + types::CAST_PRECISION_LOSS, + types::CAST_SIGN_LOSS, types::LET_UNIT_VALUE, types::LINKEDLIST, types::UNIT_CMP, diff --git a/src/types.rs b/src/types.rs index 617c51fd961..17ebb791c3c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,7 @@ use syntax::ptr::P; use rustc::middle::ty; use syntax::codemap::ExpnInfo; -use utils::{in_macro, snippet, span_lint, span_help_and_lint}; +use utils::{in_macro, snippet, span_lint, span_help_and_lint, in_external_macro}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -136,3 +136,136 @@ impl LintPass for UnitCmp { } } } + +pub struct CastPass; + +declare_lint!(pub CAST_PRECISION_LOSS, Allow, + "casts that cause loss of precision"); +declare_lint!(pub CAST_SIGN_LOSS, Allow, + "casts from signed types to unsigned types"); +declare_lint!(pub CAST_POSSIBLE_OVERFLOW, Allow, + "casts that may cause overflow"); + +impl LintPass for CastPass { + fn get_lints(&self) -> LintArray { + lint_array!(CAST_PRECISION_LOSS, + CAST_SIGN_LOSS, + CAST_POSSIBLE_OVERFLOW) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprCast(ref ex, _) = expr.node { + let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr)); + if cast_from.is_numeric() && !in_external_macro(cx, expr.span) { + match (cast_from.is_integral(), cast_to.is_integral()) { + (true, false) => { + match (&cast_from.sty, &cast_to.sty) { + (&ty::TypeVariants::TyInt(i), &ty::TypeVariants::TyFloat(f)) => { + match (i, f) { + (ast::IntTy::TyI32, ast::FloatTy::TyF32) | + (ast::IntTy::TyI64, ast::FloatTy::TyF32) | + (ast::IntTy::TyI64, ast::FloatTy::TyF64) => { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("converting from {} to {}, which causes a loss of precision", + i, f)); + }, + _ => () + } + } + (&ty::TypeVariants::TyUint(u), &ty::TypeVariants::TyFloat(f)) => { + match (u, f) { + (ast::UintTy::TyU32, ast::FloatTy::TyF32) | + (ast::UintTy::TyU64, ast::FloatTy::TyF32) | + (ast::UintTy::TyU64, ast::FloatTy::TyF64) => { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("converting from {} to {}, which causes a loss of precision", + u, f)); + }, + _ => () + } + }, + _ => () + } + }, + (false, true) => { + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); + if !cx.tcx.expr_ty(expr).is_signed() { + span_lint(cx, CAST_SIGN_LOSS, expr.span, + &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); + } + }, + (true, true) => { + match (&cast_from.sty, &cast_to.sty) { + (&ty::TypeVariants::TyInt(i1), &ty::TypeVariants::TyInt(i2)) => { + match (i1, i2) { + (ast::IntTy::TyI64, ast::IntTy::TyI32) | + (ast::IntTy::TyI64, ast::IntTy::TyI16) | + (ast::IntTy::TyI64, ast::IntTy::TyI8) | + (ast::IntTy::TyI32, ast::IntTy::TyI16) | + (ast::IntTy::TyI32, ast::IntTy::TyI8) | + (ast::IntTy::TyI16, ast::IntTy::TyI8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", i1, i2)), + _ => () + } + }, + (&ty::TypeVariants::TyInt(i), &ty::TypeVariants::TyUint(u)) => { + span_lint(cx, CAST_SIGN_LOSS, expr.span, + &format!("casting from {} to {} loses the sign of the value", i, u)); + match (i, u) { + (ast::IntTy::TyI64, ast::UintTy::TyU32) | + (ast::IntTy::TyI64, ast::UintTy::TyU16) | + (ast::IntTy::TyI64, ast::UintTy::TyU8) | + (ast::IntTy::TyI32, ast::UintTy::TyU16) | + (ast::IntTy::TyI32, ast::UintTy::TyU8) | + (ast::IntTy::TyI16, ast::UintTy::TyU8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", i, u)), + _ => () + } + }, + (&ty::TypeVariants::TyUint(u), &ty::TypeVariants::TyInt(i)) => { + match (u, i) { + (ast::UintTy::TyU64, ast::IntTy::TyI32) | + (ast::UintTy::TyU64, ast::IntTy::TyI64) | + (ast::UintTy::TyU64, ast::IntTy::TyI16) | + (ast::UintTy::TyU64, ast::IntTy::TyI8) | + (ast::UintTy::TyU32, ast::IntTy::TyI32) | + (ast::UintTy::TyU32, ast::IntTy::TyI16) | + (ast::UintTy::TyU32, ast::IntTy::TyI8) | + (ast::UintTy::TyU16, ast::IntTy::TyI16) | + (ast::UintTy::TyU16, ast::IntTy::TyI8) | + (ast::UintTy::TyU8, ast::IntTy::TyI8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", u, i)), + _ => () + } + }, + (&ty::TypeVariants::TyUint(u1), &ty::TypeVariants::TyUint(u2)) => { + match (u1, u2) { + (ast::UintTy::TyU64, ast::UintTy::TyU32) | + (ast::UintTy::TyU64, ast::UintTy::TyU16) | + (ast::UintTy::TyU64, ast::UintTy::TyU8) | + (ast::UintTy::TyU32, ast::UintTy::TyU16) | + (ast::UintTy::TyU32, ast::UintTy::TyU8) | + (ast::UintTy::TyU16, ast::UintTy::TyU8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", u1, u2)), + _ => () + } + }, + _ => () + } + } + (false, false) => { + if let (&ty::TypeVariants::TyFloat(ast::FloatTy::TyF64), + &ty::TypeVariants::TyFloat(ast::FloatTy::TyF32)) = (&cast_from.sty, &cast_to.sty) { + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, "the contents of a f64 may overflow a f32"); + } + } + } + } + } + } +} diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs new file mode 100644 index 00000000000..a51ea62a7b8 --- /dev/null +++ b/tests/compile-fail/cast.rs @@ -0,0 +1,31 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(cast_precision_loss, cast_possible_overflow, cast_sign_loss)] +fn main() { + let i : i32 = 42; + let u : u32 = 42; + let f : f32 = 42.0; + + // Test cast_precision_loss + i as f32; //~ERROR converting from i32 to f32, which causes a loss of precision + (i as i64) as f32; //~ERROR converting from i64 to f32, which causes a loss of precision + (i as i64) as f64; //~ERROR converting from i64 to f64, which causes a loss of precision + u as f32; //~ERROR converting from u32 to f32, which causes a loss of precision + (u as u64) as f32; //~ERROR converting from u64 to f32, which causes a loss of precision + (u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision + i as f64; // Should not trigger the lint + u as f64; // Should not trigger the lint + + // Test cast_possible_overflow + f as i32; //~ERROR the contents of a f32 may overflow a i32 + f as u32; //~ERROR the contents of a f32 may overflow a u32 + //~^ERROR casting from f32 to u32 loses the sign of the value + i as u8; //~ERROR the contents of a i32 may overflow a u8 + //~^ERROR casting from i32 to u8 loses the sign of the value + (f as f64) as f32; //~ERROR the contents of a f64 may overflow a f32 + i as i8; //~ERROR the contents of a i32 may overflow a i8 + + // Test cast_sign_loss + i as u32; //~ERROR casting from i32 to u32 loses the sign of the value +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 36ef03158f968cee21e4e1891a99c6b8627ffda0 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 20 Aug 2015 08:59:07 +0200 Subject: give credit where credit is due --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8433ead92bd..4b890fc7b06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,8 @@ name = "clippy" version = "0.0.11" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", - "Andre Bogus <bogusandre@gmail.com>" + "Andre Bogus <bogusandre@gmail.com>", + "Georg Brandl <georg@python.org>" ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/Manishearth/rust-clippy" -- cgit 1.4.1-3-g733a5 From af1340e4fe55affdb0a3ad89788ff1e05d37d5fd Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 20 Aug 2015 12:49:49 +0530 Subject: bump crates to 0.0.12 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4b890fc7b06..28fd03e5d6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.11" +version = "0.0.12" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 1846581baace12af85dfda3fffc219b9ceadc7e8 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 14:24:26 +0200 Subject: Added examples to lint descriptions. --- README.md | 6 +++--- src/types.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index df097ca9e3f..6a264034773 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ name | default | meaning approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -cast_possible_overflow | allow | casts that may cause overflow -cast_precision_loss | allow | casts that cause loss of precision -cast_sign_loss | allow | casts from signed types to unsigned types +cast_possible_overflow | allow | casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +cast_precision_loss | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +cast_sign_loss | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` diff --git a/src/types.rs b/src/types.rs index 17ebb791c3c..d6081153f01 100644 --- a/src/types.rs +++ b/src/types.rs @@ -140,11 +140,11 @@ impl LintPass for UnitCmp { pub struct CastPass; declare_lint!(pub CAST_PRECISION_LOSS, Allow, - "casts that cause loss of precision"); + "casts that cause loss of precision, e.g `x as f32` where `x: u64`"); declare_lint!(pub CAST_SIGN_LOSS, Allow, - "casts from signed types to unsigned types"); + "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"); declare_lint!(pub CAST_POSSIBLE_OVERFLOW, Allow, - "casts that may cause overflow"); + "casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); impl LintPass for CastPass { fn get_lints(&self) -> LintArray { -- cgit 1.4.1-3-g733a5 From 93d9249f769f27e2864d5b2d53dfc94a933412a4 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 14:25:08 +0200 Subject: Moved allow(unknown_lints) to crate level. --- src/consts.rs | 2 +- src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index c033888e360..70d5ff4bc17 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -67,7 +67,7 @@ impl Constant { } /// convert this constant to a f64, if possible - #[allow(unknown_lints,cast_precision_loss)] + #[allow(cast_precision_loss)] pub fn as_float(&self) -> Option<f64> { match *self { ConstantByte(b) => Some(b as f64), diff --git a/src/lib.rs b/src/lib.rs index 1b4d77dacca..f4e3ed54c60 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, core, collections)] #![feature(str_split_at)] +#![allow(unknown_lints)] #[macro_use] extern crate syntax; -- cgit 1.4.1-3-g733a5 From b417f01ed82332cd81954ac6d9f5bad615db2bfc Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 14:36:26 +0200 Subject: Also test that the CastExpr's right arm is numeric. --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index d6081153f01..3f7012f6ca8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -156,7 +156,7 @@ impl LintPass for CastPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprCast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr)); - if cast_from.is_numeric() && !in_external_macro(cx, expr.span) { + if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { match (&cast_from.sty, &cast_to.sty) { -- cgit 1.4.1-3-g733a5 From 14528d433af176f36aab475318691676c3de4464 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 14:37:35 +0200 Subject: Simplified reexported ast::* type paths. Also removed trailing whitespaces. --- src/types.rs | 100 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/types.rs b/src/types.rs index 3f7012f6ca8..2c4d81e361d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -160,11 +160,11 @@ impl LintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { match (&cast_from.sty, &cast_to.sty) { - (&ty::TypeVariants::TyInt(i), &ty::TypeVariants::TyFloat(f)) => { + (&ty::TyInt(i), &ty::TyFloat(f)) => { match (i, f) { - (ast::IntTy::TyI32, ast::FloatTy::TyF32) | - (ast::IntTy::TyI64, ast::FloatTy::TyF32) | - (ast::IntTy::TyI64, ast::FloatTy::TyF64) => { + (ast::TyI32, ast::TyF32) | + (ast::TyI64, ast::TyF32) | + (ast::TyI64, ast::TyF64) => { span_lint(cx, CAST_PRECISION_LOSS, expr.span, &format!("converting from {} to {}, which causes a loss of precision", i, f)); @@ -172,11 +172,11 @@ impl LintPass for CastPass { _ => () } } - (&ty::TypeVariants::TyUint(u), &ty::TypeVariants::TyFloat(f)) => { + (&ty::TyUint(u), &ty::TyFloat(f)) => { match (u, f) { - (ast::UintTy::TyU32, ast::FloatTy::TyF32) | - (ast::UintTy::TyU64, ast::FloatTy::TyF32) | - (ast::UintTy::TyU64, ast::FloatTy::TyF64) => { + (ast::TyU32, ast::TyF32) | + (ast::TyU64, ast::TyF32) | + (ast::TyU64, ast::TyF64) => { span_lint(cx, CAST_PRECISION_LOSS, expr.span, &format!("converting from {} to {}, which causes a loss of precision", u, f)); @@ -188,69 +188,69 @@ impl LintPass for CastPass { } }, (false, true) => { - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); if !cx.tcx.expr_ty(expr).is_signed() { - span_lint(cx, CAST_SIGN_LOSS, expr.span, + span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); } }, (true, true) => { match (&cast_from.sty, &cast_to.sty) { - (&ty::TypeVariants::TyInt(i1), &ty::TypeVariants::TyInt(i2)) => { + (&ty::TyInt(i1), &ty::TyInt(i2)) => { match (i1, i2) { - (ast::IntTy::TyI64, ast::IntTy::TyI32) | - (ast::IntTy::TyI64, ast::IntTy::TyI16) | - (ast::IntTy::TyI64, ast::IntTy::TyI8) | - (ast::IntTy::TyI32, ast::IntTy::TyI16) | - (ast::IntTy::TyI32, ast::IntTy::TyI8) | - (ast::IntTy::TyI16, ast::IntTy::TyI8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + (ast::TyI64, ast::TyI32) | + (ast::TyI64, ast::TyI16) | + (ast::TyI64, ast::TyI8) | + (ast::TyI32, ast::TyI16) | + (ast::TyI32, ast::TyI8) | + (ast::TyI16, ast::TyI8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", i1, i2)), _ => () } }, - (&ty::TypeVariants::TyInt(i), &ty::TypeVariants::TyUint(u)) => { - span_lint(cx, CAST_SIGN_LOSS, expr.span, + (&ty::TyInt(i), &ty::TyUint(u)) => { + span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting from {} to {} loses the sign of the value", i, u)); match (i, u) { - (ast::IntTy::TyI64, ast::UintTy::TyU32) | - (ast::IntTy::TyI64, ast::UintTy::TyU16) | - (ast::IntTy::TyI64, ast::UintTy::TyU8) | - (ast::IntTy::TyI32, ast::UintTy::TyU16) | - (ast::IntTy::TyI32, ast::UintTy::TyU8) | - (ast::IntTy::TyI16, ast::UintTy::TyU8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + (ast::TyI64, ast::TyU32) | + (ast::TyI64, ast::TyU16) | + (ast::TyI64, ast::TyU8) | + (ast::TyI32, ast::TyU16) | + (ast::TyI32, ast::TyU8) | + (ast::TyI16, ast::TyU8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", i, u)), _ => () } }, - (&ty::TypeVariants::TyUint(u), &ty::TypeVariants::TyInt(i)) => { + (&ty::TyUint(u), &ty::TyInt(i)) => { match (u, i) { - (ast::UintTy::TyU64, ast::IntTy::TyI32) | - (ast::UintTy::TyU64, ast::IntTy::TyI64) | - (ast::UintTy::TyU64, ast::IntTy::TyI16) | - (ast::UintTy::TyU64, ast::IntTy::TyI8) | - (ast::UintTy::TyU32, ast::IntTy::TyI32) | - (ast::UintTy::TyU32, ast::IntTy::TyI16) | - (ast::UintTy::TyU32, ast::IntTy::TyI8) | - (ast::UintTy::TyU16, ast::IntTy::TyI16) | - (ast::UintTy::TyU16, ast::IntTy::TyI8) | - (ast::UintTy::TyU8, ast::IntTy::TyI8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + (ast::TyU64, ast::TyI32) | + (ast::TyU64, ast::TyI64) | + (ast::TyU64, ast::TyI16) | + (ast::TyU64, ast::TyI8) | + (ast::TyU32, ast::TyI32) | + (ast::TyU32, ast::TyI16) | + (ast::TyU32, ast::TyI8) | + (ast::TyU16, ast::TyI16) | + (ast::TyU16, ast::TyI8) | + (ast::TyU8, ast::TyI8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", u, i)), _ => () } }, - (&ty::TypeVariants::TyUint(u1), &ty::TypeVariants::TyUint(u2)) => { + (&ty::TyUint(u1), &ty::TyUint(u2)) => { match (u1, u2) { - (ast::UintTy::TyU64, ast::UintTy::TyU32) | - (ast::UintTy::TyU64, ast::UintTy::TyU16) | - (ast::UintTy::TyU64, ast::UintTy::TyU8) | - (ast::UintTy::TyU32, ast::UintTy::TyU16) | - (ast::UintTy::TyU32, ast::UintTy::TyU8) | - (ast::UintTy::TyU16, ast::UintTy::TyU8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + (ast::TyU64, ast::TyU32) | + (ast::TyU64, ast::TyU16) | + (ast::TyU64, ast::TyU8) | + (ast::TyU32, ast::TyU16) | + (ast::TyU32, ast::TyU8) | + (ast::TyU16, ast::TyU8) => + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", u1, u2)), _ => () } @@ -259,13 +259,13 @@ impl LintPass for CastPass { } } (false, false) => { - if let (&ty::TypeVariants::TyFloat(ast::FloatTy::TyF64), - &ty::TypeVariants::TyFloat(ast::FloatTy::TyF32)) = (&cast_from.sty, &cast_to.sty) { + if let (&ty::TyFloat(ast::TyF64), + &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) { span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, "the contents of a f64 may overflow a f32"); } } } } } - } + } } -- cgit 1.4.1-3-g733a5 From ff28dd324ec404285dc61c6a29ceadbf3985d7e0 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 14:50:26 +0200 Subject: Fixed a little oversight. --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 2c4d81e361d..2950a03a036 100644 --- a/src/types.rs +++ b/src/types.rs @@ -190,7 +190,7 @@ impl LintPass for CastPass { (false, true) => { span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); - if !cx.tcx.expr_ty(expr).is_signed() { + if !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); } -- cgit 1.4.1-3-g733a5 From ab481e5cb1cb54005a19044709ac9bebabd74aae Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 21:37:37 +0200 Subject: Refactored the CastPass lints. --- src/types.rs | 121 +++++++++++++++++------------------------------------------ 1 file changed, 35 insertions(+), 86 deletions(-) diff --git a/src/types.rs b/src/types.rs index 2950a03a036..ea0416e512c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -158,33 +158,24 @@ impl LintPass for CastPass { let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr)); if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { - (true, false) => { - match (&cast_from.sty, &cast_to.sty) { - (&ty::TyInt(i), &ty::TyFloat(f)) => { - match (i, f) { - (ast::TyI32, ast::TyF32) | - (ast::TyI64, ast::TyF32) | - (ast::TyI64, ast::TyF64) => { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("converting from {} to {}, which causes a loss of precision", - i, f)); - }, - _ => () - } + (true, false) => { + let from_nbits = match &cast_from.sty { + &ty::TyInt(i) => 4 << (i as usize), + &ty::TyUint(u) => 4 << (u as usize), + _ => 0 + }; + let to_nbits : usize = match &cast_to.sty { + &ty::TyFloat(ast::TyF32) => 32, + &ty::TyFloat(ast::TyF64) => 64, + _ => 0 + }; + if from_nbits != 4 { + // Handle TyIs/TyUs separately (size is arch dependant) + if from_nbits >= to_nbits { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("converting from {} to {}, which causes a loss of precision", + cast_from, cast_to)); } - (&ty::TyUint(u), &ty::TyFloat(f)) => { - match (u, f) { - (ast::TyU32, ast::TyF32) | - (ast::TyU64, ast::TyF32) | - (ast::TyU64, ast::TyF64) => { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("converting from {} to {}, which causes a loss of precision", - u, f)); - }, - _ => () - } - }, - _ => () } }, (false, true) => { @@ -196,66 +187,24 @@ impl LintPass for CastPass { } }, (true, true) => { - match (&cast_from.sty, &cast_to.sty) { - (&ty::TyInt(i1), &ty::TyInt(i2)) => { - match (i1, i2) { - (ast::TyI64, ast::TyI32) | - (ast::TyI64, ast::TyI16) | - (ast::TyI64, ast::TyI8) | - (ast::TyI32, ast::TyI16) | - (ast::TyI32, ast::TyI8) | - (ast::TyI16, ast::TyI8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", i1, i2)), - _ => () - } - }, - (&ty::TyInt(i), &ty::TyUint(u)) => { - span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting from {} to {} loses the sign of the value", i, u)); - match (i, u) { - (ast::TyI64, ast::TyU32) | - (ast::TyI64, ast::TyU16) | - (ast::TyI64, ast::TyU8) | - (ast::TyI32, ast::TyU16) | - (ast::TyI32, ast::TyU8) | - (ast::TyI16, ast::TyU8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", i, u)), - _ => () - } - }, - (&ty::TyUint(u), &ty::TyInt(i)) => { - match (u, i) { - (ast::TyU64, ast::TyI32) | - (ast::TyU64, ast::TyI64) | - (ast::TyU64, ast::TyI16) | - (ast::TyU64, ast::TyI8) | - (ast::TyU32, ast::TyI32) | - (ast::TyU32, ast::TyI16) | - (ast::TyU32, ast::TyI8) | - (ast::TyU16, ast::TyI16) | - (ast::TyU16, ast::TyI8) | - (ast::TyU8, ast::TyI8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", u, i)), - _ => () - } - }, - (&ty::TyUint(u1), &ty::TyUint(u2)) => { - match (u1, u2) { - (ast::TyU64, ast::TyU32) | - (ast::TyU64, ast::TyU16) | - (ast::TyU64, ast::TyU8) | - (ast::TyU32, ast::TyU16) | - (ast::TyU32, ast::TyU8) | - (ast::TyU16, ast::TyU8) => - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", u1, u2)), - _ => () - } - }, - _ => () + if cast_from.is_signed() && !cast_to.is_signed() { + span_lint(cx, CAST_SIGN_LOSS, expr.span, + &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); + } + let from_nbits = match &cast_from.sty { + &ty::TyInt(i) => 4 << (i as usize), + &ty::TyUint(u) => 4 << (u as usize), + _ => 0 + }; + let to_nbits = match &cast_to.sty { + &ty::TyInt(i) => 4 << (i as usize), + &ty::TyUint(u) => 4 << (u as usize), + _ => 0 + }; + if to_nbits < from_nbits || + (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { + span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, + &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); } } (false, false) => { -- cgit 1.4.1-3-g733a5 From dbc9b7f46eb95d2583fc60c09220c0803ba541ee Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Thu, 20 Aug 2015 22:44:40 +0200 Subject: Reworked the error messages for more heplfulness. Renamed the cast_possible_overflow lint to cast_possible_truncation, and updated the error message, readme and crate root accordingly. Added some more information to the message for the cast_precision_loss lint. Updated the test case to reflect changes. --- README.md | 88 +++++++++++++++++++++++----------------------- src/lib.rs | 2 +- src/types.rs | 23 ++++++------ tests/compile-fail/cast.rs | 26 +++++++------- 4 files changed, 70 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 6a264034773..fbb16fcb170 100644 --- a/README.md +++ b/README.md @@ -6,50 +6,50 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints Lints included in this crate: -name | default | meaning ------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -cast_possible_overflow | allow | casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -cast_precision_loss | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -cast_sign_loss | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) -cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` -ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -inline_always | warn | `#[inline(always)]` is a bad idea in most cases -iter_next_loop | warn | for-looping over `_.next()` which is probably not intended -len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` -len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function -let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf -modulo_one | warn | taking a number modulo 1, which always returns 0 -mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do -needless_return | warn | using a return statement like `return expr;` where an expression would suffice -non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` -ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator -redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled -single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` -string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -string_to_string | warn | calling `String.to_string()` which is a no-op -toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) -unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) -zero_width_space | deny | using a zero-width space in a string literal, which is confusing +name | default | meaning +-------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +cast_possible_truncation | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +cast_precision_loss | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +cast_sign_loss | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) +cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` +ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +inline_always | warn | `#[inline(always)]` is a bad idea in most cases +iter_next_loop | warn | for-looping over `_.next()` which is probably not intended +len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` +len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +modulo_one | warn | taking a number modulo 1, which always returns 0 +mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do +needless_return | warn | using a return statement like `return expr;` where an expression would suffice +non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` +ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator +redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled +single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` +string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +string_to_string | warn | calling `String.to_string()` which is a no-op +toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) +zero_width_space | deny | using a zero-width space in a string literal, which is confusing To use, add the following lines to your Cargo.toml: diff --git a/src/lib.rs b/src/lib.rs index f4e3ed54c60..bdb3cb3471a 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,7 +106,7 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::BOX_VEC, - types::CAST_POSSIBLE_OVERFLOW, + types::CAST_POSSIBLE_TRUNCATION, types::CAST_PRECISION_LOSS, types::CAST_SIGN_LOSS, types::LET_UNIT_VALUE, diff --git a/src/types.rs b/src/types.rs index ea0416e512c..f9949a7b563 100644 --- a/src/types.rs +++ b/src/types.rs @@ -143,14 +143,14 @@ declare_lint!(pub CAST_PRECISION_LOSS, Allow, "casts that cause loss of precision, e.g `x as f32` where `x: u64`"); declare_lint!(pub CAST_SIGN_LOSS, Allow, "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"); -declare_lint!(pub CAST_POSSIBLE_OVERFLOW, Allow, - "casts that may cause overflow, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); +declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, + "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!(CAST_PRECISION_LOSS, CAST_SIGN_LOSS, - CAST_POSSIBLE_OVERFLOW) + CAST_POSSIBLE_TRUNCATION) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -170,17 +170,18 @@ impl LintPass for CastPass { _ => 0 }; if from_nbits != 4 { - // Handle TyIs/TyUs separately (size is arch dependant) + // Handle TyIs/TyUs separately (pointer size is arch dependant) if from_nbits >= to_nbits { span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("converting from {} to {}, which causes a loss of precision", - cast_from, cast_to)); + &format!("converting from {0} to {1}, which causes a loss of precision \ + ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", + cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} )); } } }, (false, true) => { - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); if !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); @@ -203,14 +204,14 @@ impl LintPass for CastPass { }; if to_nbits < from_nbits || (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, - &format!("the contents of a {} may overflow a {}", cast_from, cast_to)); + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); } } (false, false) => { if let (&ty::TyFloat(ast::TyF64), &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) { - span_lint(cx, CAST_POSSIBLE_OVERFLOW, expr.span, "the contents of a f64 may overflow a f32"); + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may cause truncation of the value"); } } } diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index a51ea62a7b8..af6e6089fbf 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -1,30 +1,30 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(cast_precision_loss, cast_possible_overflow, cast_sign_loss)] +#[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss)] fn main() { let i : i32 = 42; let u : u32 = 42; let f : f32 = 42.0; // Test cast_precision_loss - i as f32; //~ERROR converting from i32 to f32, which causes a loss of precision - (i as i64) as f32; //~ERROR converting from i64 to f32, which causes a loss of precision - (i as i64) as f64; //~ERROR converting from i64 to f64, which causes a loss of precision - u as f32; //~ERROR converting from u32 to f32, which causes a loss of precision - (u as u64) as f32; //~ERROR converting from u64 to f32, which causes a loss of precision - (u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision + i as f32; //~ERROR converting from i32 to f32, which causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) + (i as i64) as f32; //~ERROR converting from i64 to f32, which causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) + (i as i64) as f64; //~ERROR converting from i64 to f64, which causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) + u as f32; //~ERROR converting from u32 to f32, which causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) + (u as u64) as f32; //~ERROR converting from u64 to f32, which causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) + (u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) i as f64; // Should not trigger the lint u as f64; // Should not trigger the lint - // Test cast_possible_overflow - f as i32; //~ERROR the contents of a f32 may overflow a i32 - f as u32; //~ERROR the contents of a f32 may overflow a u32 + // Test cast_possible_truncation + f as i32; //~ERROR casting f32 to i32 may cause truncation of the value + f as u32; //~ERROR casting f32 to u32 may cause truncation of the value //~^ERROR casting from f32 to u32 loses the sign of the value - i as u8; //~ERROR the contents of a i32 may overflow a u8 + i as u8; //~ERROR casting i32 to u8 may cause truncation of the value //~^ERROR casting from i32 to u8 loses the sign of the value - (f as f64) as f32; //~ERROR the contents of a f64 may overflow a f32 - i as i8; //~ERROR the contents of a i32 may overflow a i8 + (f as f64) as f32; //~ERROR casting f64 to f32 may cause truncation of the value + i as i8; //~ERROR casting i32 to i8 may cause truncation of the value // Test cast_sign_loss i as u32; //~ERROR casting from i32 to u32 loses the sign of the value -- cgit 1.4.1-3-g733a5 From ad0bc66402eb528aedb1d14235fed9a70bcc0a34 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Fri, 21 Aug 2015 03:03:37 +0200 Subject: Added support for isize/usize in the CastPass lint pass. Extracted the match that determines an integer types's size in a utility function and implemented support for usize/isize. Added a needed feature to the crate root. Added some tests to cover those cases, and a test I previously forgot. Silenced two errors signaled by dogfood.sh in unicode.rs. --- src/lib.rs | 2 +- src/types.rs | 33 ++++++++++++++++----------------- src/unicode.rs | 1 + tests/compile-fail/cast.rs | 30 ++++++++++++++++++++++++++++-- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bdb3cb3471a..9ea1efeed5f 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, core, collections)] -#![feature(str_split_at)] +#![feature(str_split_at, num_bits_bytes)] #![allow(unknown_lints)] #[macro_use] diff --git a/src/types.rs b/src/types.rs index f9949a7b563..915ffb15fe5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -146,6 +146,18 @@ declare_lint!(pub CAST_SIGN_LOSS, Allow, declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); +/// Returns the size in bits of an integral type. +/// Will return 0 if the type is not an int or uint variant +fn int_ty_to_nbits(typ: &ty::TyS) -> usize { + let n = match &typ.sty { + &ty::TyInt(i) => 4 << (i as usize), + &ty::TyUint(u) => 4 << (u as usize), + _ => 0 + }; + // n == 4 is the usize/isize case + if n == 4 { ::std::usize::BITS } else { n } +} + impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!(CAST_PRECISION_LOSS, @@ -159,18 +171,13 @@ impl LintPass for CastPass { if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { - let from_nbits = match &cast_from.sty { - &ty::TyInt(i) => 4 << (i as usize), - &ty::TyUint(u) => 4 << (u as usize), - _ => 0 - }; + let from_nbits = int_ty_to_nbits(cast_from); let to_nbits : usize = match &cast_to.sty { &ty::TyFloat(ast::TyF32) => 32, &ty::TyFloat(ast::TyF64) => 64, _ => 0 }; - if from_nbits != 4 { - // Handle TyIs/TyUs separately (pointer size is arch dependant) + if from_nbits != 0 { if from_nbits >= to_nbits { span_lint(cx, CAST_PRECISION_LOSS, expr.span, &format!("converting from {0} to {1}, which causes a loss of precision \ @@ -192,16 +199,8 @@ impl LintPass for CastPass { span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); } - let from_nbits = match &cast_from.sty { - &ty::TyInt(i) => 4 << (i as usize), - &ty::TyUint(u) => 4 << (u as usize), - _ => 0 - }; - let to_nbits = match &cast_to.sty { - &ty::TyInt(i) => 4 << (i as usize), - &ty::TyUint(u) => 4 << (u as usize), - _ => 0 - }; + let from_nbits = int_ty_to_nbits(cast_from); + let to_nbits = int_ty_to_nbits(cast_to); if to_nbits < from_nbits || (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, diff --git a/src/unicode.rs b/src/unicode.rs index ab48fd1bef2..8a64f612666 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -40,6 +40,7 @@ fn check_str(cx: &Context, string: &str, span: Span) { } } +#[allow(cast_possible_truncation)] fn str_pos_lint(cx: &Context, lint: &'static Lint, span: Span, index: usize, msg: &str) { span_lint(cx, lint, Span { lo: span.lo + BytePos((1 + index) as u32), hi: span.lo + BytePos((1 + index) as u32), diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index af6e6089fbf..0fa402b3bf7 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss)] +#[allow(dead_code)] fn main() { let i : i32 = 42; let u : u32 = 42; @@ -16,7 +17,7 @@ fn main() { (u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) i as f64; // Should not trigger the lint u as f64; // Should not trigger the lint - + // Test cast_possible_truncation f as i32; //~ERROR casting f32 to i32 may cause truncation of the value f as u32; //~ERROR casting f32 to u32 may cause truncation of the value @@ -25,7 +26,32 @@ fn main() { //~^ERROR casting from i32 to u8 loses the sign of the value (f as f64) as f32; //~ERROR casting f64 to f32 may cause truncation of the value i as i8; //~ERROR casting i32 to i8 may cause truncation of the value - + u as i32; //~ERROR casting u32 to i32 may cause truncation of the value + // Test cast_sign_loss i as u32; //~ERROR casting from i32 to u32 loses the sign of the value + + // Extra checks for usize/isize + let is : isize = -42; + is as usize; //~ERROR casting from isize to usize loses the sign of the value + is as i8; //~ERROR casting isize to i8 may cause truncation of the value + + // FIXME : enable these checks when we figure out a way to make compiletest deal with conditional compilation + /* + #[cfg(target_pointer_width = "64")] + fn check_64() { + let is : isize = -42; + let us : usize = 42; + is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 64 bits wide, but f32's mantissa is only 23 bits wide) + us as u32; //ERROR casting usize to u32 may cause truncation of the value + us as u64; // Should not trigger any lint + } + #[cfg(target_pointer_width = "32")] + fn check_32() { + let is : isize = -42; + let us : usize = 42; + is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 32 bits wide, but f32's mantissa is only 23 bits wide) + us as u32; // Should not trigger any lint + us as u64; // Should not trigger any lint + }*/ } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 4dcbad1b086368beb97dc9d20b154a634c5c84af Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 12:19:07 +0200 Subject: const folding for eq_op --- src/eq_op.rs | 128 +++++++++++++++++++++++++++++---------------------------- src/strings.rs | 13 +++--- 2 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 50b61e23356..6202dcc3670 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -4,6 +4,7 @@ use syntax::ast_util as ast_util; use syntax::ptr::P; use syntax::codemap as code; +use consts::constant; use utils::span_lint; declare_lint! { @@ -22,7 +23,7 @@ impl LintPass for EqOp { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_cmp_or_bit(op) && is_exp_equal(left, right) { + if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) { span_lint(cx, EQ_OP, e.span, &format!( "equal expressions as operands to {}", ast_util::binop_to_string(op.node))); @@ -31,45 +32,48 @@ impl LintPass for EqOp { } } -pub fn is_exp_equal(left : &Expr, right : &Expr) -> bool { +pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => lop.node == rop.node && - is_exp_equal(ll, rl) && is_exp_equal(lr, rr), + is_exp_equal(cx, ll, rl) && is_exp_equal(cx, lr, rr), (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && - is_exp_equal(lbox, rbox), + both(lpl, rpl, |l, r| is_exp_equal(cx, l, r)) && + is_exp_equal(cx, lbox, rbox), (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, - rcallee) && is_exps_equal(largs, rargs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(cx, lcallee, + rcallee) && is_exps_equal(cx, largs, rargs), (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => - is_ty_equal(lty, rty) && is_exp_equal(lc, rc), + is_ty_equal(cx, lty, rty) && is_exp_equal(cx, lc, rc), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => - lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), + lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprMethodCall(ref lident, ref lcty, ref lmargs), &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(lcty, rcty) && - is_exps_equal(lmargs, rmargs), - (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), - (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), + lident.node == rident.node && is_tys_equal(cx, lcty, rcty) && + is_exps_equal(cx, lmargs, rmargs), + (&ExprParen(ref lparen), _) => is_exp_equal(cx, lparen, right), + (_, &ExprParen(ref rparen)) => is_exp_equal(cx, left, rparen), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => both(lqself, rqself, |l, r| is_qself_equal(l, r)) && is_path_equal(lsubpath, rsubpath), (&ExprTup(ref ltup), &ExprTup(ref rtup)) => - is_exps_equal(ltup, rtup), + is_exps_equal(cx, ltup, rtup), (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(l, r), - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), + lunop == runop && is_exp_equal(cx, l, r), + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), + _ => false + } || match (constant(cx, left), constant(cx, right)) { + (Some(l), Some(r)) => l == r, _ => false } } -fn is_exps_equal(left : &[P<Expr>], right : &[P<Expr>]) -> bool { - over(left, right, |l, r| is_exp_equal(l, r)) +fn is_exps_equal(cx: &Context, left : &[P<Expr>], right : &[P<Expr>]) -> bool { + over(left, right, |l, r| is_exp_equal(cx, l, r)) } fn is_path_equal(left : &Path, right : &Path) -> bool { @@ -85,29 +89,29 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } -fn is_ty_equal(left : &Ty, right : &Ty) -> bool { +fn is_ty_equal(cx: &Context, left : &Ty, right : &Ty) -> bool { match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(cx, lvec, rvec), (&TyFixedLengthVec(ref lfvty, ref lfvexp), &TyFixedLengthVec(ref rfvty, ref rfvexp)) => - is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), + is_ty_equal(cx, lfvty, rfvty) && is_exp_equal(cx, lfvexp, rfvexp), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(cx, lmut, rmut), (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => both(ltime, rtime, is_lifetime_equal) && - is_mut_ty_equal(lrmut, rrmut), + is_mut_ty_equal(cx, lrmut, rrmut), (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => - is_bare_fn_ty_equal(lbare, rbare), - (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), + is_bare_fn_ty_equal(cx, lbare, rbare), + (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(cx, ltup, rtup), (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), (&TyObjectSum(ref lsumty, ref lobounds), &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && + is_ty_equal(cx, lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), - (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), - (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), + (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(cx, lty, rty), + (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(cx, lof, rof), (&TyInfer, &TyInfer) => true, _ => false } @@ -136,41 +140,41 @@ fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) over(left, right, is_param_bound_equal) } -fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { - left.mutbl == right.mutbl && is_ty_equal(&left.ty, &right.ty) +fn is_mut_ty_equal(cx: &Context, left : &MutTy, right : &MutTy) -> bool { + left.mutbl == right.mutbl && is_ty_equal(cx, &left.ty, &right.ty) } -fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { +fn is_bare_fn_ty_equal(cx: &Context, left : &BareFnTy, right : &BareFnTy) -> bool { left.unsafety == right.unsafety && left.abi == right.abi && is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && - is_fndecl_equal(&left.decl, &right.decl) + is_fndecl_equal(cx, &left.decl, &right.decl) } -fn is_fndecl_equal(left : &P<FnDecl>, right : &P<FnDecl>) -> bool { +fn is_fndecl_equal(cx: &Context, left : &P<FnDecl>, right : &P<FnDecl>) -> bool { left.variadic == right.variadic && - is_args_equal(&left.inputs, &right.inputs) && - is_fnret_ty_equal(&left.output, &right.output) + is_args_equal(cx, &left.inputs, &right.inputs) && + is_fnret_ty_equal(cx, &left.output, &right.output) } -fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) - -> bool { +fn is_fnret_ty_equal(cx: &Context, left : &FunctionRetTy, + right : &FunctionRetTy) -> bool { match (left, right) { (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, - (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), + (&Return(ref lty), &Return(ref rty)) => is_ty_equal(cx, lty, rty), _ => false } } -fn is_arg_equal(l: &Arg, r : &Arg) -> bool { - is_ty_equal(&l.ty, &r.ty) && is_pat_equal(&l.pat, &r.pat) +fn is_arg_equal(cx: &Context, l: &Arg, r : &Arg) -> bool { + is_ty_equal(cx, &l.ty, &r.ty) && is_pat_equal(cx, &l.pat, &r.pat) } -fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { - over(left, right, is_arg_equal) +fn is_args_equal(cx: &Context, left : &[Arg], right : &[Arg]) -> bool { + over(left, right, |l, r| is_arg_equal(cx, l, r)) } -fn is_pat_equal(left : &Pat, right : &Pat) -> bool { +fn is_pat_equal(cx: &Context, left : &Pat, right : &Pat) -> bool { match(&left.node, &right.node) { (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, (&PatIdent(ref lmode, ref lident, Option::None), @@ -179,51 +183,51 @@ fn is_pat_equal(left : &Pat, right : &Pat) -> bool { (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => lmode == rmode && is_ident_equal(&lident.node, &rident.node) && - is_pat_equal(lpat, rpat), + is_pat_equal(cx, lpat, rpat), (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| - is_pats_equal(l, r)), + is_pats_equal(cx, l, r)), (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => lbool == rbool && is_path_equal(lpath, rpath) && - is_spanned_fieldpats_equal(lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), + is_spanned_fieldpats_equal(cx, lfieldpat, rfieldpat), + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(cx, ltup, rtup), (&PatBox(ref lboxed), &PatBox(ref rboxed)) => - is_pat_equal(lboxed, rboxed), + is_pat_equal(cx, lboxed, rboxed), (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => - is_pat_equal(lpat, rpat) && lmut == rmut, - (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), + is_pat_equal(cx, lpat, rpat) && lmut == rmut, + (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(cx, llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => - is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), + is_exp_equal(cx, lfrom, rfrom) && is_exp_equal(cx, lto, rto), (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), + is_pats_equal(cx, lfirst, rfirst) && is_pats_equal(cx, llast, rlast), (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && - is_pats_equal(llast, rlast), + is_pats_equal(cx, lfirst, rfirst) && is_pat_equal(cx, lpat, rpat) && + is_pats_equal(cx, llast, rlast), // I don't match macros for now, the code is slow enough as is ;-) _ => false } } -fn is_spanned_fieldpats_equal(left : &[code::Spanned<FieldPat>], +fn is_spanned_fieldpats_equal(cx: &Context, left : &[code::Spanned<FieldPat>], right : &[code::Spanned<FieldPat>]) -> bool { - over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) + over(left, right, |l, r| is_fieldpat_equal(cx, &l.node, &r.node)) } -fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { +fn is_fieldpat_equal(cx: &Context, left : &FieldPat, right : &FieldPat) -> bool { left.is_shorthand == right.is_shorthand && is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(&left.pat, &right.pat) + is_pat_equal(cx, &left.pat, &right.pat) } fn is_ident_equal(left : &Ident, right : &Ident) -> bool { &left.name == &right.name && left.ctxt == right.ctxt } -fn is_pats_equal(left : &[P<Pat>], right : &[P<Pat>]) -> bool { - over(left, right, |l, r| is_pat_equal(l, r)) +fn is_pats_equal(cx: &Context, left : &[P<Pat>], right : &[P<Pat>]) -> bool { + over(left, right, |l, r| is_pat_equal(cx, l, r)) } fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) @@ -241,8 +245,8 @@ fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { left.name == right.name } -fn is_tys_equal(left : &[P<Ty>], right : &[P<Ty>]) -> bool { - over(left, right, |l, r| is_ty_equal(l, r)) +fn is_tys_equal(cx: &Context, left : &[P<Ty>], right : &[P<Ty>]) -> bool { + over(left, right, |l, r| is_ty_equal(cx, l, r)) } fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool diff --git a/src/strings.rs b/src/strings.rs index 7981b785850..b1da93d71e3 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -41,7 +41,7 @@ impl LintPass for StringAdd { if let Some(ref p) = parent { if let &ExprAssign(ref target, _) = &p.node { // avoid duplicate matches - if is_exp_equal(target, left) { return; } + if is_exp_equal(cx, target, left) { return; } } } } @@ -51,7 +51,7 @@ impl LintPass for StringAdd { Consider using `String::push_str()` instead") } } else if let &ExprAssign(ref target, ref src) = &e.node { - if is_string(cx, target) && is_add(src, target) { + if is_string(cx, target) && is_add(cx, src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ Consider using `String::push_str()` instead") @@ -67,13 +67,14 @@ fn is_string(cx: &Context, e: &Expr) -> bool { } else { false } } -fn is_add(src: &Expr, target: &Expr) -> bool { +fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { match &src.node { &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => - is_exp_equal(target, left), + is_exp_equal(cx, target, left), &ExprBlock(ref block) => block.stmts.is_empty() && - block.expr.as_ref().map_or(false, |expr| is_add(&*expr, target)), - &ExprParen(ref expr) => is_add(&*expr, target), + block.expr.as_ref().map_or(false, + |expr| is_add(cx, &*expr, target)), + &ExprParen(ref expr) => is_add(cx, &*expr, target), _ => false } } -- cgit 1.4.1-3-g733a5 From a22b3cdceecb85bf55a21e15959d639d98f6da5e Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 12:26:03 +0200 Subject: const folding for eq_op --- src/eq_op.rs | 5 +++-- tests/compile-fail/eq_op.rs | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 6202dcc3670..ebc6aa17100 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -33,7 +33,7 @@ impl LintPass for EqOp { } pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { - match (&left.node, &right.node) { + if match (&left.node, &right.node) { (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => lop.node == rop.node && @@ -66,7 +66,8 @@ pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { lunop == runop && is_exp_equal(cx, l, r), (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), _ => false - } || match (constant(cx, left), constant(cx, right)) { + } { return true; } + match (constant(cx, left), constant(cx, right)) { (Some(l), Some(r)) => l == r, _ => false } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 8f61a11aa08..a1183629344 100755 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -34,4 +34,8 @@ fn main() { ((1, 2) != (1, 2)); //~ERROR equal expressions [1].len() == [1].len(); //~ERROR equal expressions vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros + + // const folding + 1 + 1 == 2; //~ERROR equal expressions + 1 - 1 == 0; //~ERROR equal expressions } -- cgit 1.4.1-3-g733a5 From b2df15d65a7baf1f8d9b8b776027a34dd6e1db10 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 18:28:17 +0200 Subject: ptr_arg improvements (fixes #214) * do not trigger on mutable references * use "real" type from ty, not AST type --- src/ptr_arg.rs | 45 +++++++++++++++++++++++++------------------ tests/compile-fail/ptr_arg.rs | 17 +++++++++------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 2748d187a4e..35c61b10266 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -4,10 +4,9 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::codemap::Span; +use rustc::middle::ty; -use types::match_ty_unwrap; -use utils::span_lint; +use utils::{span_lint, match_def_path}; declare_lint! { pub PTR_ARG, @@ -43,24 +42,32 @@ impl LintPass for PtrArg { } } +#[allow(unused_imports)] fn check_fn(cx: &Context, decl: &FnDecl) { + { + // In case stuff gets moved around + use collections::vec::Vec; + use collections::string::String; + } for arg in &decl.inputs { - match &arg.ty.node { - &TyPtr(ref p) | &TyRptr(_, ref p) => - check_ptr_subtype(cx, arg.ty.span, &p.ty), - _ => () + if arg.ty.node == TyInfer { // "self" arguments + continue; + } + let ref sty = cx.tcx.pat_ty(&*arg.pat).sty; + if let &ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = sty { + if let ty::TyStruct(did, _) = ty.sty { + if match_def_path(cx, did.did, &["collections", "vec", "Vec"]) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference \ + and cannot be used with non-Vec-based slices. Consider changing \ + the type to `&[...]`"); + } + else if match_def_path(cx, did.did, &["collections", "string", "String"]) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&String` instead of `&str` involves a new object \ + where a slice will do. Consider changing the type to `&str`"); + } + } } } } - -fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, - &["String"]).map_or((), |_| { - span_lint(cx, PTR_ARG, span, - "writing `&String` instead of `&str` involves a new object \ - where a slice will do. Consider changing the type to `&str`") - }), |_| span_lint(cx, PTR_ARG, span, - "writing `&Vec<_>` instead of \ - `&[_]` involves one more reference and cannot be used with \ - non-Vec-based slices. Consider changing the type to `&[...]`")) -} diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs index d4b6d22608f..d0615be492b 100755 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -1,20 +1,23 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(unused)] +#![deny(ptr_arg)] -#[deny(ptr_arg)] -#[allow(unused)] fn do_vec(x: &Vec<i64>) { //~ERROR writing `&Vec<_>` instead of `&[_]` //Nothing here } -#[deny(ptr_arg)] -#[allow(unused)] +fn do_vec_mut(x: &mut Vec<i64>) { // no error here + //Nothing here +} + fn do_str(x: &String) { //~ERROR writing `&String` instead of `&str` //Nothing here either } +fn do_str_mut(x: &mut String) { // no error here + //Nothing here either +} + fn main() { - let x = vec![1i64, 2, 3]; - do_vec(&x); - do_str(&"hello".to_owned()); } -- cgit 1.4.1-3-g733a5 From 707e95f2e5b9f6e20998508d99959dd1642d26ec Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 18:40:36 +0200 Subject: types: use middle::ty types instead of ast types This gets rid of the match_ty_unwrap function. --- src/types.rs | 71 +++++++++++++++------------------------------ tests/compile-fail/dlist.rs | 2 +- 2 files changed, 24 insertions(+), 49 deletions(-) mode change 100644 => 100755 tests/compile-fail/dlist.rs diff --git a/src/types.rs b/src/types.rs index 915ffb15fe5..986fb1016ed 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,11 +2,10 @@ use rustc::lint::*; use syntax::ast; use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::ptr::P; use rustc::middle::ty; use syntax::codemap::ExpnInfo; -use utils::{in_macro, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{in_macro, match_def_path, snippet, span_lint, span_help_and_lint, in_external_macro}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -18,61 +17,37 @@ declare_lint!(pub LINKEDLIST, Warn, "usage of LinkedList, usually a vector is faster, or a more specialized data \ structure like a RingBuf"); -/// Matches a type with a provided string, and returns its type parameters if successful -pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> { - match ty.node { - TyPath(_, Path {segments: ref seg, ..}) => { - // So ast::Path isn't the full path, just the tokens that were provided. - // I could muck around with the maps and find the full path - // however the more efficient way is to simply reverse the iterators and zip them - // which will compare them in reverse until one of them runs out of segments - if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.name == b) { - match seg[..].last() { - Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => { - Some(&a.types[..]) - } - _ => None - } - } else { - None - } - }, - _ => None - } -} - #[allow(unused_imports)] impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, LINKEDLIST) } - fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) { + fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) { { // In case stuff gets moved around - use std::boxed::Box; - use std::vec::Vec; + use collections::vec::Vec; + use collections::linked_list::LinkedList; } - match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first()) - .and_then(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"])) - .map(|_| { - span_help_and_lint(cx, BOX_VEC, ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); - }); - { - // In case stuff gets moved around - use collections::linked_list::LinkedList as DL1; - use std::collections::linked_list::LinkedList as DL2; - } - let dlists = [vec!["std","collections","linked_list","LinkedList"], - vec!["collections","linked_list","LinkedList"]]; - for path in &dlists { - if match_ty_unwrap(ty, &path[..]).is_some() { - span_help_and_lint(cx, LINKEDLIST, ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a RingBuf might work"); - return; + if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { + if let ty::TyBox(ref inner) = ty.sty { + if let ty::TyStruct(did, _) = inner.sty { + if match_def_path(cx, did.did, &["collections", "vec", "Vec"]) { + span_help_and_lint( + cx, BOX_VEC, ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); + } + } + } + if let ty::TyStruct(did, _) = ty.sty { + if match_def_path(cx, did.did, &["collections", "linked_list", "LinkedList"]) { + span_help_and_lint( + cx, LINKEDLIST, ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a RingBuf might work"); + return; + } } } } diff --git a/tests/compile-fail/dlist.rs b/tests/compile-fail/dlist.rs old mode 100644 new mode 100755 index a2343c339ad..a800c045a50 --- a/tests/compile-fail/dlist.rs +++ b/tests/compile-fail/dlist.rs @@ -12,4 +12,4 @@ pub fn test(foo: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList! fn main(){ test(LinkedList::new()); -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From a437936d49081faa82227c7d216ff3b0d6363ed3 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 18:48:36 +0200 Subject: all: put often used DefPaths into utils as consts Also remove the "use xxx;" blocks to ensure import paths don't change. They don't work anyway since stuff may still be re-exported at the old location, while we need the "canonical" location for the type checks. Plus, the test suite catches all these cases. --- src/methods.rs | 14 ++++---------- src/ptr_arg.rs | 11 +++-------- src/strings.rs | 3 ++- src/types.rs | 11 +++-------- src/utils.rs | 7 +++++++ 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index f2df736bebc..70cf32e5093 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -3,6 +3,7 @@ use rustc::lint::*; use rustc::middle::ty; use utils::{span_lint, match_def_path, walk_ptrs_ty}; +use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; #[derive(Copy,Clone)] pub struct MethodsPass; @@ -16,30 +17,23 @@ declare_lint!(pub STR_TO_STRING, Warn, declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); -#[allow(unused_imports)] impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - { - // In case stuff gets moved around - use core::option::Option; - use core::result::Result; - use collections::string::String; - } if let ExprMethodCall(ref ident, _, ref args) = expr.node { let ref obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty; if ident.node.name == "unwrap" { if let ty::TyEnum(did, _) = *obj_ty { - if match_def_path(cx, did.did, &["core", "option", "Option"]) { + if match_def_path(cx, did.did, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ to handle the None case gracefully, consider using expect() to provide a better panic message"); } - else if match_def_path(cx, did.did, &["core", "result", "Result"]) { + else if match_def_path(cx, did.did, &RESULT_PATH) { span_lint(cx, RESULT_UNWRAP_USED, expr.span, "used unwrap() on a Result value. Graceful handling \ of Err values is preferred"); @@ -51,7 +45,7 @@ impl LintPass for MethodsPass { span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); } else if let ty::TyStruct(did, _) = *obj_ty { - if match_def_path(cx, did.did, &["collections", "string", "String"]) { + if match_def_path(cx, did.did, &STRING_PATH) { span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op") } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 35c61b10266..cdf4ecb48e5 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -7,6 +7,7 @@ use syntax::ast::*; use rustc::middle::ty; use utils::{span_lint, match_def_path}; +use utils::{STRING_PATH, VEC_PATH}; declare_lint! { pub PTR_ARG, @@ -42,13 +43,7 @@ impl LintPass for PtrArg { } } -#[allow(unused_imports)] fn check_fn(cx: &Context, decl: &FnDecl) { - { - // In case stuff gets moved around - use collections::vec::Vec; - use collections::string::String; - } for arg in &decl.inputs { if arg.ty.node == TyInfer { // "self" arguments continue; @@ -56,13 +51,13 @@ fn check_fn(cx: &Context, decl: &FnDecl) { let ref sty = cx.tcx.pat_ty(&*arg.pat).sty; if let &ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = sty { if let ty::TyStruct(did, _) = ty.sty { - if match_def_path(cx, did.did, &["collections", "vec", "Vec"]) { + if match_def_path(cx, did.did, &VEC_PATH) { span_lint(cx, PTR_ARG, arg.ty.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference \ and cannot be used with non-Vec-based slices. Consider changing \ the type to `&[...]`"); } - else if match_def_path(cx, did.did, &["collections", "string", "String"]) { + else if match_def_path(cx, did.did, &STRING_PATH) { span_lint(cx, PTR_ARG, arg.ty.span, "writing `&String` instead of `&str` involves a new object \ where a slice will do. Consider changing the type to `&str`"); diff --git a/src/strings.rs b/src/strings.rs index b1da93d71e3..c4fbca9344f 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -10,6 +10,7 @@ use syntax::codemap::Spanned; use eq_op::is_exp_equal; use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::STRING_PATH; declare_lint! { pub STRING_ADD_ASSIGN, @@ -63,7 +64,7 @@ impl LintPass for StringAdd { fn is_string(cx: &Context, e: &Expr) -> bool { let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); if let TyStruct(did, _) = ty.sty { - match_def_path(cx, did.did, &["collections", "string", "String"]) + match_def_path(cx, did.did, &STRING_PATH) } else { false } } diff --git a/src/types.rs b/src/types.rs index 986fb1016ed..57649adee8b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,6 +6,7 @@ use rustc::middle::ty; use syntax::codemap::ExpnInfo; use utils::{in_macro, match_def_path, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -17,22 +18,16 @@ declare_lint!(pub LINKEDLIST, Warn, "usage of LinkedList, usually a vector is faster, or a more specialized data \ structure like a RingBuf"); -#[allow(unused_imports)] impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, LINKEDLIST) } fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) { - { - // In case stuff gets moved around - use collections::vec::Vec; - use collections::linked_list::LinkedList; - } if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { if let ty::TyStruct(did, _) = inner.sty { - if match_def_path(cx, did.did, &["collections", "vec", "Vec"]) { + if match_def_path(cx, did.did, &VEC_PATH) { span_help_and_lint( cx, BOX_VEC, ast_ty.span, "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", @@ -41,7 +36,7 @@ impl LintPass for TypePass { } } if let ty::TyStruct(did, _) = ty.sty { - if match_def_path(cx, did.did, &["collections", "linked_list", "LinkedList"]) { + if match_def_path(cx, did.did, &LL_PATH) { span_help_and_lint( cx, LINKEDLIST, ast_ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", diff --git a/src/utils.rs b/src/utils.rs index 47e3a3456d6..fe5c1433c84 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,6 +6,13 @@ use rustc::ast_map::Node::NodeExpr; use rustc::middle::ty; use std::borrow::Cow; +// module DefPaths for certain structs/enums we check for +pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; + /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { -- cgit 1.4.1-3-g733a5 From 8a10440641f7ec89236b1f40129738426ad4d702 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 19:00:33 +0200 Subject: utils: add match_type() helper function which saves one level of matching when checking for type paths --- src/methods.rs | 35 ++++++++++++++--------------------- src/ptr_arg.rs | 23 ++++++++++------------- src/ranges.rs | 11 ++++------- src/strings.rs | 8 ++------ src/types.rs | 27 +++++++++++---------------- src/utils.rs | 12 ++++++++++++ 6 files changed, 53 insertions(+), 63 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 70cf32e5093..df8e35d98fb 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -2,7 +2,7 @@ use syntax::ast::*; use rustc::lint::*; use rustc::middle::ty; -use utils::{span_lint, match_def_path, walk_ptrs_ty}; +use utils::{span_lint, match_type, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; #[derive(Copy,Clone)] @@ -24,31 +24,24 @@ impl LintPass for MethodsPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { - let ref obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty; + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])); if ident.node.name == "unwrap" { - if let ty::TyEnum(did, _) = *obj_ty { - if match_def_path(cx, did.did, &OPTION_PATH) { - span_lint(cx, OPTION_UNWRAP_USED, expr.span, - "used unwrap() on an Option value. If you don't want \ - to handle the None case gracefully, consider using - expect() to provide a better panic message"); - } - else if match_def_path(cx, did.did, &RESULT_PATH) { - span_lint(cx, RESULT_UNWRAP_USED, expr.span, - "used unwrap() on a Result value. Graceful handling \ - of Err values is preferred"); - } + if match_type(cx, obj_ty, &OPTION_PATH) { + span_lint(cx, OPTION_UNWRAP_USED, expr.span, + "used unwrap() on an Option value. If you don't want \ + to handle the None case gracefully, consider using \ + expect() to provide a better panic message"); + } else if match_type(cx, obj_ty, &RESULT_PATH) { + span_lint(cx, RESULT_UNWRAP_USED, expr.span, + "used unwrap() on a Result value. Graceful handling \ + of Err values is preferred"); } } else if ident.node.name == "to_string" { - if let ty::TyStr = *obj_ty { + if obj_ty.sty == ty::TyStr { span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); - } - else if let ty::TyStruct(did, _) = *obj_ty { - if match_def_path(cx, did.did, &STRING_PATH) { - span_lint(cx, STRING_TO_STRING, expr.span, - "`String.to_string()` is a no-op") - } + } else if match_type(cx, obj_ty, &STRING_PATH) { + span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op"); } } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index cdf4ecb48e5..f0a0592f5e2 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use syntax::ast::*; use rustc::middle::ty; -use utils::{span_lint, match_def_path}; +use utils::{span_lint, match_type}; use utils::{STRING_PATH, VEC_PATH}; declare_lint! { @@ -50,18 +50,15 @@ fn check_fn(cx: &Context, decl: &FnDecl) { } let ref sty = cx.tcx.pat_ty(&*arg.pat).sty; if let &ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = sty { - if let ty::TyStruct(did, _) = ty.sty { - if match_def_path(cx, did.did, &VEC_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference \ - and cannot be used with non-Vec-based slices. Consider changing \ - the type to `&[...]`"); - } - else if match_def_path(cx, did.did, &STRING_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&String` instead of `&str` involves a new object \ - where a slice will do. Consider changing the type to `&str`"); - } + if match_type(cx, ty, &VEC_PATH) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference \ + and cannot be used with non-Vec-based slices. Consider changing \ + the type to `&[...]`"); + } else if match_type(cx, ty, &STRING_PATH) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&String` instead of `&str` involves a new object \ + where a slice will do. Consider changing the type to `&str`"); } } } diff --git a/src/ranges.rs b/src/ranges.rs index bbe65285d58..d1a0a7e702e 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,8 +1,7 @@ use rustc::lint::{Context, LintArray, LintPass}; -use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{match_def_path}; +use utils::match_type; declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, @@ -34,11 +33,9 @@ impl LintPass for StepByZero { fn is_range(cx: &Context, expr: &Expr) -> bool { // No need for walk_ptrs_ty here because step_by moves self, so it // can't be called on a borrowed range. - if let TyStruct(did, _) = cx.tcx.expr_ty(expr).sty { - // Note: RangeTo and RangeFull don't have step_by - match_def_path(cx, did.did, &["core", "ops", "Range"]) || - match_def_path(cx, did.did, &["core", "ops", "RangeFrom"]) - } else { false } + let ty = cx.tcx.expr_ty(expr); + // Note: RangeTo and RangeFull don't have step_by + match_type(cx, ty, &["core", "ops", "Range"]) || match_type(cx, ty, &["core", "ops", "RangeFrom"]) } fn is_lit_zero(expr: &Expr) -> bool { diff --git a/src/strings.rs b/src/strings.rs index c4fbca9344f..64d18eeb26d 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -4,12 +4,11 @@ //! disable the subsumed lint unless it has a higher level use rustc::lint::*; -use rustc::middle::ty::TypeVariants::TyStruct; use syntax::ast::*; use syntax::codemap::Spanned; use eq_op::is_exp_equal; -use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; declare_lint! { @@ -62,10 +61,7 @@ impl LintPass for StringAdd { } fn is_string(cx: &Context, e: &Expr) -> bool { - let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); - if let TyStruct(did, _) = ty.sty { - match_def_path(cx, did.did, &STRING_PATH) - } else { false } + match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &STRING_PATH) } fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { diff --git a/src/types.rs b/src/types.rs index 57649adee8b..622f733f812 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,7 +5,7 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use rustc::middle::ty; use syntax::codemap::ExpnInfo; -use utils::{in_macro, match_def_path, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types @@ -26,24 +26,19 @@ impl LintPass for TypePass { fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) { if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { - if let ty::TyStruct(did, _) = inner.sty { - if match_def_path(cx, did.did, &VEC_PATH) { - span_help_and_lint( - cx, BOX_VEC, ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); - } - } - } - if let ty::TyStruct(did, _) = ty.sty { - if match_def_path(cx, did.did, &LL_PATH) { + if match_type(cx, inner, &VEC_PATH) { span_help_and_lint( - cx, LINKEDLIST, ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a RingBuf might work"); - return; + cx, BOX_VEC, ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); } } + else if match_type(cx, ty, &LL_PATH) { + span_help_and_lint( + cx, LINKEDLIST, ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a RingBuf might work"); + } } } } diff --git a/src/utils.rs b/src/utils.rs index fe5c1433c84..4fd36fb91d4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,6 +44,18 @@ pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { .zip(path.iter()).all(|(nm, p)| nm == p)) } +/// check if type is struct or enum type with given def path +pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool { + match ty.sty { + ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => { + match_def_path(cx, adt.did, path) + } + _ => { + false + } + } +} + /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { -- cgit 1.4.1-3-g733a5 From f1255d5f5d9c9d23d039ee3798af4e164563226f Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Sat, 22 Aug 2015 02:44:05 +0200 Subject: Casts : work in progress handling *size separately --- src/types.rs | 37 ++++++++++++++++++++++++++++--------- tests/compile-fail/cast.rs | 28 +++++++--------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/types.rs b/src/types.rs index 915ffb15fe5..e8da11ecbe0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -150,14 +150,21 @@ declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: &ty::TyS) -> usize { let n = match &typ.sty { - &ty::TyInt(i) => 4 << (i as usize), - &ty::TyUint(u) => 4 << (u as usize), - _ => 0 + &ty::TyInt(i) => 4 << (i as usize), + &ty::TyUint(u) => 4 << (u as usize), + _ => 0 }; // n == 4 is the usize/isize case if n == 4 { ::std::usize::BITS } else { n } } +fn is_isize_or_usize(typ: &ty::TyS) -> bool { + match &typ.sty { + &ty::TyInt(ast::TyIs) | &ty::TyUint(ast::TyUs) => true, + _ => false + } +} + impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!(CAST_PRECISION_LOSS, @@ -178,7 +185,14 @@ impl LintPass for CastPass { _ => 0 }; if from_nbits != 0 { - if from_nbits >= to_nbits { + // When casting to f32, precision loss would occur regardless of the arch + if is_isize_or_usize(cast_from) && to_nbits == 64 { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("converting from {0} to f64, which causes a loss of precision on 64-bit architectures \ + ({0} is 64 bits wide, but f64's mantissa is only 52 bits wide)", + cast_from)); + } + else if from_nbits >= to_nbits { span_lint(cx, CAST_PRECISION_LOSS, expr.span, &format!("converting from {0} to {1}, which causes a loss of precision \ ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", @@ -186,7 +200,7 @@ impl LintPass for CastPass { } } }, - (false, true) => { + (false, true) => { // Nothing to add there span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); if !cast_to.is_signed() { @@ -201,10 +215,15 @@ impl LintPass for CastPass { } let from_nbits = int_ty_to_nbits(cast_from); let to_nbits = int_ty_to_nbits(cast_to); - if to_nbits < from_nbits || - (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); + match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { + (true, true) | (false, false) => + if to_nbits < from_nbits || + (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); + }, + (true, false) => (), // TODO + (false, true) => () // TODO } } (false, false) => { diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index 0fa402b3bf7..8e854fb21f9 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -32,26 +32,12 @@ fn main() { i as u32; //~ERROR casting from i32 to u32 loses the sign of the value // Extra checks for usize/isize - let is : isize = -42; - is as usize; //~ERROR casting from isize to usize loses the sign of the value - is as i8; //~ERROR casting isize to i8 may cause truncation of the value - - // FIXME : enable these checks when we figure out a way to make compiletest deal with conditional compilation /* - #[cfg(target_pointer_width = "64")] - fn check_64() { - let is : isize = -42; - let us : usize = 42; - is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 64 bits wide, but f32's mantissa is only 23 bits wide) - us as u32; //ERROR casting usize to u32 may cause truncation of the value - us as u64; // Should not trigger any lint - } - #[cfg(target_pointer_width = "32")] - fn check_32() { - let is : isize = -42; - let us : usize = 42; - is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 32 bits wide, but f32's mantissa is only 23 bits wide) - us as u32; // Should not trigger any lint - us as u64; // Should not trigger any lint - }*/ + let is : isize = -42; + let us : usize = 42; + is as usize; //ERROR casting from isize to usize loses the sign of the value + is as i8; //ERROR casting isize to i8 may cause truncation of the value + is as f64; //ERROR converting from isize to f64, which causes a loss of precision on 64-bit architectures (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) + us as f64; //ERROR converting from usize to f64, which causes a loss of precision on 64-bit architectures (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) + */ } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From e92bf84a535b77c65127fadc2b82d762cff8ab66 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 22 Aug 2015 08:57:05 +0200 Subject: ptr_arg: fix panic when pattern type is not in tcx --- src/ptr_arg.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index f0a0592f5e2..2d09fcbcca9 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -45,20 +45,18 @@ impl LintPass for PtrArg { fn check_fn(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - if arg.ty.node == TyInfer { // "self" arguments - continue; - } - let ref sty = cx.tcx.pat_ty(&*arg.pat).sty; - if let &ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = sty { - if match_type(cx, ty, &VEC_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference \ - and cannot be used with non-Vec-based slices. Consider changing \ - the type to `&[...]`"); - } else if match_type(cx, ty, &STRING_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&String` instead of `&str` involves a new object \ - where a slice will do. Consider changing the type to `&str`"); + if let Some(pat_ty) = cx.tcx.pat_ty_opt(&*arg.pat) { + if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty { + if match_type(cx, ty, &VEC_PATH) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference \ + and cannot be used with non-Vec-based slices. Consider changing \ + the type to `&[...]`"); + } else if match_type(cx, ty, &STRING_PATH) { + span_lint(cx, PTR_ARG, arg.ty.span, + "writing `&String` instead of `&str` involves a new object \ + where a slice will do. Consider changing the type to `&str`"); + } } } } -- cgit 1.4.1-3-g733a5 From 630bb76f960c49d559efde55030b9a3ccb8b5704 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 22:53:47 +0200 Subject: new lint: type complexity (fixes #93) Still very naive, but it's a start. --- README.md | 1 + src/lib.rs | 2 + src/types.rs | 125 ++++++++++++++++++++++++++++++++++++ tests/compile-fail/complex_types.rs | 44 +++++++++++++ 4 files changed, 172 insertions(+) create mode 100755 tests/compile-fail/complex_types.rs diff --git a/README.md b/README.md index fbb16fcb170..55976104058 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ string_add | allow | using `x + ..` where x is a `String`; sugge string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead string_to_string | warn | calling `String.to_string()` which is a no-op toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +type_complexity | warn | usage of very complex types; recommends factoring out parts into `type` definitions unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) zero_width_space | deny | using a zero-width space in a string literal, which is confusing diff --git a/src/lib.rs b/src/lib.rs index 9ea1efeed5f..b0f46ae45ab 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); reg.register_lint_pass(box ranges::StepByZero as LintPassObject); reg.register_lint_pass(box types::CastPass as LintPassObject); + reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, @@ -111,6 +112,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::CAST_SIGN_LOSS, types::LET_UNIT_VALUE, types::LINKEDLIST, + types::TYPE_COMPLEXITY, types::UNIT_CMP, unicode::NON_ASCII_LITERAL, unicode::ZERO_WIDTH_SPACE, diff --git a/src/types.rs b/src/types.rs index 622f733f812..54c36535286 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,6 +2,8 @@ use rustc::lint::*; use syntax::ast; use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use syntax::codemap::Span; +use syntax::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; use syntax::codemap::ExpnInfo; @@ -183,3 +185,126 @@ impl LintPass for CastPass { } } } + +declare_lint!(pub TYPE_COMPLEXITY, Warn, + "usage of very complex types; recommends factoring out parts into `type` definitions"); + +#[allow(missing_copy_implementations)] +pub struct TypeComplexityPass; + +impl LintPass for TypeComplexityPass { + fn get_lints(&self) -> LintArray { + lint_array!(TYPE_COMPLEXITY) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + check_fndecl(cx, decl); + } + + fn check_struct_field(&mut self, cx: &Context, field: &StructField) { + check_type(cx, &*field.node.ty); + } + + fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) { + // StructVariant is covered by check_struct_field + if let TupleVariantKind(ref args) = var.node.kind { + for arg in args { + check_type(cx, &*arg.ty); + } + } + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + match item.node { + ItemStatic(ref ty, _, _) | + ItemConst(ref ty, _) => check_type(cx, ty), + // functions, enums, structs, impls and traits are covered + _ => () + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + match item.node { + ConstTraitItem(ref ty, _) | + TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty), + MethodTraitItem(MethodSig { ref decl, .. }, None) => check_fndecl(cx, decl), + // methods with default impl are covered by check_fn + _ => () + } + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + match item.node { + ConstImplItem(ref ty, _) | + TypeImplItem(ref ty) => check_type(cx, ty), + // methods are covered by check_fn + _ => () + } + } + + fn check_local(&mut self, cx: &Context, local: &Local) { + if let Some(ref ty) = local.ty { + check_type(cx, ty); + } + } +} + +fn check_fndecl(cx: &Context, decl: &FnDecl) { + for arg in &decl.inputs { + check_type(cx, &*arg.ty); + } + if let Return(ref ty) = decl.output { + check_type(cx, ty); + } +} + +fn check_type(cx: &Context, ty: &ast::Ty) { + let score = { + let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; + visitor.visit_ty(ty); + visitor.score + }; + // println!("{:?} --> {}", ty, score); + if score > 250 { + span_lint(cx, TYPE_COMPLEXITY, ty.span, &format!( + "very complex type used. Consider factoring parts into `type` definitions")); + } +} + +/// Walks a type and assigns a complexity score to it. +struct TypeComplexityVisitor { + /// total complexity score of the type + score: u32, + /// current nesting level + nest: u32, +} + +impl<'v> Visitor<'v> for TypeComplexityVisitor { + fn visit_ty(&mut self, ty: &'v ast::Ty) { + let (add_score, sub_nest) = match ty.node { + // _, &x and *x have only small overhead; don't mess with nesting level + TyInfer | + TyPtr(..) | + TyRptr(..) => (1, 0), + + // the "normal" components of a type: named types, arrays/tuples + TyPath(..) | + TyVec(..) | + TyTup(..) | + TyFixedLengthVec(..) => (10 * self.nest, 1), + + // "Sum" of trait bounds + TyObjectSum(..) => (20 * self.nest, 0), + + // function types and "for<...>" bring a lot of overhead + TyBareFn(..) | + TyPolyTraitRef(..) => (50 * self.nest, 1), + + _ => (0, 0) + }; + self.score += add_score; + self.nest += sub_nest; + walk_ty(self, ty); + self.nest -= sub_nest; + } +} diff --git a/tests/compile-fail/complex_types.rs b/tests/compile-fail/complex_types.rs new file mode 100755 index 00000000000..995132ba88c --- /dev/null +++ b/tests/compile-fail/complex_types.rs @@ -0,0 +1,44 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy)] +#![allow(unused)] +#![feature(associated_consts, associated_type_defaults)] + +type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here + +const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); //~ERROR very complex type +static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); //~ERROR very complex type + +struct S { + f: Vec<Vec<Box<(u32, u32, u32, u32)>>>, //~ERROR very complex type +} + +struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>); //~ERROR very complex type + +enum E { + V1(Vec<Vec<Box<(u32, u32, u32, u32)>>>), //~ERROR very complex type + V2 { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, //~ERROR very complex type +} + +impl S { + const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); //~ERROR very complex type + fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) { } //~ERROR very complex type +} + +trait T { + const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>; //~ERROR very complex type + type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>; //~ERROR very complex type + fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>); //~ERROR very complex type + fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) { } //~ERROR very complex type +} + +fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> { vec![] } //~ERROR very complex type + +fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) { } //~ERROR very complex type + +fn test3() { + let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![]; //~ERROR very complex type +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 1334f2ceaea5e012bba02b6afc0371bf92e976e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 22 Aug 2015 13:01:54 +0530 Subject: Fix doubleborrow of refcell in consts.rs --- src/consts.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/consts.rs b/src/consts.rs index 70d5ff4bc17..e54ac77b599 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -330,8 +330,13 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// lookup a possibly constant expression from a ExprPath fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { if let Some(lcx) = self.lcx { + let mut maybe_id = None; if let Some(&PathResolution { base_def: DefConst(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { + maybe_id = Some(id); + } + // separate if lets to avoid doubleborrowing the defmap + if let Some(id) = maybe_id { if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None) { let ret = self.expr(const_expr); if ret.is_some() { -- cgit 1.4.1-3-g733a5 From 1587256dc4651bbc53793fb461f1a22c6f65fc5c Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 22 Aug 2015 14:30:53 +0200 Subject: types: check for macros in type complexity check --- src/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.rs b/src/types.rs index 54c36535286..cd7a5dc3729 100644 --- a/src/types.rs +++ b/src/types.rs @@ -259,6 +259,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) { } fn check_type(cx: &Context, ty: &ast::Ty) { + if in_external_macro(cx, ty.span) { return; } let score = { let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; visitor.visit_ty(ty); -- cgit 1.4.1-3-g733a5 From 5403e826818a3c669f476909b24b4470e6e3749c Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 19:32:21 +0200 Subject: matches: new module, move single_match lint there --- src/lib.rs | 5 +++-- src/matches.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/misc.rs | 63 +--------------------------------------------------------- 3 files changed, 65 insertions(+), 64 deletions(-) create mode 100644 src/matches.rs diff --git a/src/lib.rs b/src/lib.rs index b0f46ae45ab..fbeebb210fe 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,11 +38,11 @@ pub mod returns; pub mod lifetimes; pub mod loops; pub mod ranges; +pub mod matches; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); - reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box misc::CmpNan as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject); @@ -71,6 +71,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box ranges::StepByZero as LintPassObject); reg.register_lint_pass(box types::CastPass as LintPassObject); reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); + reg.register_lint_pass(box matches::MatchPass as LintPassObject); reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, @@ -87,6 +88,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, + matches::SINGLE_MATCH, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::STR_TO_STRING, @@ -96,7 +98,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::FLOAT_CMP, misc::MODULO_ONE, misc::PRECEDENCE, - misc::SINGLE_MATCH, misc::TOPLEVEL_REF_ARG, mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, diff --git a/src/matches.rs b/src/matches.rs new file mode 100644 index 00000000000..b9f6cbc4326 --- /dev/null +++ b/src/matches.rs @@ -0,0 +1,61 @@ +use rustc::lint::*; +use syntax::ast; +use syntax::ast::*; +use std::borrow::Cow; + +use utils::{snippet, snippet_block, span_help_and_lint}; + +declare_lint!(pub SINGLE_MATCH, Warn, + "a match statement with a single nontrivial arm (i.e, where the other arm \ + is `_ => {}`) is used; recommends `if let` instead"); + +#[allow(missing_copy_implementations)] +pub struct MatchPass; + +impl LintPass for MatchPass { + fn get_lints(&self) -> LintArray { + lint_array!(SINGLE_MATCH) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { + // check preconditions: only two arms + if arms.len() == 2 && + // both of the arms have a single pattern and no guard + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + // and the second pattern is a `_` wildcard: this is not strictly necessary, + // since the exhaustiveness check will ensure the last one is a catch-all, + // but in some cases, an explicit match is preferred to catch situations + // when an enum is extended, so we don't consider these cases + arms[1].pats[0].node == PatWild(PatWildSingle) && + // finally, we don't want any content in the second arm (unit or empty block) + is_unit_expr(&*arms[1].body) + { + let body_code = snippet_block(cx, arms[0].body.span, ".."); + let body_code = if let ExprBlock(_) = arms[0].body.node { + body_code + } else { + Cow::Owned(format!("{{ {} }}", body_code)) + }; + span_help_and_lint(cx, SINGLE_MATCH, expr.span, + "you seem to be trying to use match for \ + destructuring a single pattern. Did you mean to \ + use `if let`?", + &*format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + body_code) + ); + } + } + } +} + +fn is_unit_expr(expr: &Expr) -> bool { + match expr.node { + ExprTup(ref v) if v.is_empty() => true, + ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, + _ => false, + } +} diff --git a/src/misc.rs b/src/misc.rs index aca849931bb..49324de8de9 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,75 +1,14 @@ use rustc::lint::*; use syntax::ptr::P; -use syntax::ast; use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; use rustc::middle::ty; -use std::borrow::Cow; -use utils::{match_path, snippet, snippet_block, span_lint, span_help_and_lint, walk_ptrs_ty}; +use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; use consts::constant; -/// Handles uncategorized lints -/// Currently handles linting of if-let-able matches -#[allow(missing_copy_implementations)] -pub struct MiscPass; - - -declare_lint!(pub SINGLE_MATCH, Warn, - "a match statement with a single nontrivial arm (i.e, where the other arm \ - is `_ => {}`) is used; recommends `if let` instead"); - -impl LintPass for MiscPass { - fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { - // check preconditions: only two arms - if arms.len() == 2 && - // both of the arms have a single pattern and no guard - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - // and the second pattern is a `_` wildcard: this is not strictly necessary, - // since the exhaustiveness check will ensure the last one is a catch-all, - // but in some cases, an explicit match is preferred to catch situations - // when an enum is extended, so we don't consider these cases - arms[1].pats[0].node == PatWild(PatWildSingle) && - // finally, we don't want any content in the second arm (unit or empty block) - is_unit_expr(&*arms[1].body) - { - let body_code = snippet_block(cx, arms[0].body.span, ".."); - let body_code = if let ExprBlock(_) = arms[0].body.node { - body_code - } else { - Cow::Owned(format!("{{ {} }}", body_code)) - }; - span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for \ - destructuring a single pattern. Did you mean to \ - use `if let`?", - &*format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - body_code) - ); - } - } - } -} - -fn is_unit_expr(expr: &Expr) -> bool { - match expr.node { - ExprTup(ref v) if v.is_empty() => true, - ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, - _ => false, - } -} - - declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \ `fn foo((ref x, ref y): (u8, u8))`)"); -- cgit 1.4.1-3-g733a5 From 017dac23017e2dcf8fe350b66821a9e50d39bbd1 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 19:49:00 +0200 Subject: new lint: using &Ref patterns instead of matching on *expr (fixes #187) --- README.md | 1 + src/lib.rs | 1 + src/matches.rs | 30 +++++++++++++++++-- tests/compile-fail/match_if_let.rs | 38 ------------------------ tests/compile-fail/matches.rs | 59 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 41 deletions(-) delete mode 100755 tests/compile-fail/match_if_let.rs create mode 100755 tests/compile-fail/matches.rs diff --git a/README.md b/README.md index 55976104058..72ce27392a7 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ len_zero | warn | checking `.len() == 0` or `.len() > 0` (or let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +match_ref_pats | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead modulo_one | warn | taking a number modulo 1, which always returns 0 mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` diff --git a/src/lib.rs b/src/lib.rs index fbeebb210fe..26af063c9a5 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, + matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, diff --git a/src/matches.rs b/src/matches.rs index b9f6cbc4326..b704a2b47bb 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -3,23 +3,27 @@ use syntax::ast; use syntax::ast::*; use std::borrow::Cow; -use utils::{snippet, snippet_block, span_help_and_lint}; +use utils::{snippet, snippet_block, span_lint, span_help_and_lint}; declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ is `_ => {}`) is used; recommends `if let` instead"); +declare_lint!(pub MATCH_REF_PATS, Warn, + "a match has all arms prefixed with `&`; the match expression can be \ + dereferenced instead"); #[allow(missing_copy_implementations)] pub struct MatchPass; impl LintPass for MatchPass { fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH) + lint_array!(SINGLE_MATCH, MATCH_REF_PATS) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { - // check preconditions: only two arms + // check preconditions for SINGLE_MATCH + // only two arms if arms.len() == 2 && // both of the arms have a single pattern and no guard arms[0].pats.len() == 1 && arms[0].guard.is_none() && @@ -48,6 +52,13 @@ impl LintPass for MatchPass { body_code) ); } + + // check preconditions for MATCH_REF_PATS + if has_only_ref_pats(arms) { + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "instead of prefixing all patterns with `&`, you can dereference the \ + expression to match: `match *{} {{ ...`", snippet(cx, ex.span, ".."))); + } } } } @@ -59,3 +70,16 @@ fn is_unit_expr(expr: &Expr) -> bool { _ => false, } } + +fn has_only_ref_pats(arms: &[Arm]) -> bool { + for arm in arms { + for pat in &arm.pats { + match pat.node { + PatRegion(..) => (), // &-patterns + PatWild(..) => (), // an "anything" wildcard is also fine + _ => return false, + } + } + } + true +} diff --git a/tests/compile-fail/match_if_let.rs b/tests/compile-fail/match_if_let.rs deleted file mode 100755 index bf2e7e43a52..00000000000 --- a/tests/compile-fail/match_if_let.rs +++ /dev/null @@ -1,38 +0,0 @@ -#![feature(plugin)] - -#![plugin(clippy)] -#![deny(clippy)] - -fn main(){ - let x = Some(1u8); - match x { //~ ERROR you seem to be trying to use match - //~^ HELP try - Some(y) => { - println!("{:?}", y); - } - _ => () - } - // Not linted - match x { - Some(y) => println!("{:?}", y), - None => () - } - let z = (1u8,1u8); - match z { //~ ERROR you seem to be trying to use match - //~^ HELP try - (2...3, 7...9) => println!("{:?}", z), - _ => {} - } - - // Not linted (pattern guards used) - match x { - Some(y) if y == 0 => println!("{:?}", y), - _ => () - } - - // Not linted (content in the else) - match z { - (2...3, 7...9) => println!("{:?}", z), - _ => println!("nope"), - } -} diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs new file mode 100755 index 00000000000..43cf43b68df --- /dev/null +++ b/tests/compile-fail/matches.rs @@ -0,0 +1,59 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] +#![allow(unused)] + +fn single_match(){ + let x = Some(1u8); + match x { //~ ERROR you seem to be trying to use match + //~^ HELP try + Some(y) => { + println!("{:?}", y); + } + _ => () + } + // Not linted + match x { + Some(y) => println!("{:?}", y), + None => () + } + let z = (1u8,1u8); + match z { //~ ERROR you seem to be trying to use match + //~^ HELP try + (2...3, 7...9) => println!("{:?}", z), + _ => {} + } + + // Not linted (pattern guards used) + match x { + Some(y) if y == 0 => println!("{:?}", y), + _ => () + } + + // Not linted (content in the else) + match z { + (2...3, 7...9) => println!("{:?}", z), + _ => println!("nope"), + } +} + +fn ref_pats() { + let ref v = Some(0); + match v { //~ERROR instead of prefixing all patterns with `&` + &Some(v) => println!("{:?}", v), + &None => println!("none"), + } + match v { // this doesn't trigger, we have a different pattern + &Some(v) => println!("some"), + other => println!("other"), + } + let ref tup = (1, 2); + match tup { //~ERROR instead of prefixing all patterns with `&` + &(v, 1) => println!("{}", v), + _ => println!("none"), + } +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 8f1a2374938d77e3ecb713d57241d8209578ed0d Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 20:44:48 +0200 Subject: &-matches: dogfood fixes! --- src/approx_const.rs | 8 ++++---- src/bit_mask.rs | 12 ++++++------ src/eta_reduction.rs | 6 +++--- src/len_zero.rs | 8 ++++---- src/misc.rs | 6 +++--- src/needless_bool.rs | 6 +++--- src/strings.rs | 8 ++++---- src/types.rs | 16 ++++++++-------- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index cfd646765c9..3e0ba4eb669 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -37,10 +37,10 @@ impl LintPass for ApproxConstant { } fn check_lit(cx: &Context, lit: &Lit, span: Span) { - match &lit.node { - &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), - &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), - &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), + match lit.node { + LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), + LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), + LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), _ => () } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 7789381da23..6537fcf4c1a 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -82,9 +82,9 @@ fn invert_cmp(cmp : BinOp_) -> BinOp_ { fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { - match &bit_op.node { - &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), - &ExprBinary(ref op, ref left, ref right) => { + match bit_op.node { + ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), + ExprBinary(ref op, ref left, ref right) => { if op.node != BiBitAnd && op.node != BiBitOr { return; } fetch_int_literal(cx, right).or_else(|| fetch_int_literal( cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, @@ -182,13 +182,13 @@ fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { } fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option<u64> { - match &lit.node { - &ExprLit(ref lit_ptr) => { + match lit.node { + ExprLit(ref lit_ptr) => { if let &LitInt(value, _) = &lit_ptr.node { Option::Some(value) //TODO: Handle sign } else { Option::None } }, - &ExprPath(_, _) => { + ExprPath(_, _) => { // Important to let the borrow expire before the const lookup to avoid double // borrowing. let def_map = cx.tcx.def_map.borrow(); diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 6712e787278..25e967b07e5 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -18,9 +18,9 @@ impl LintPass for EtaPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - match &expr.node { - &ExprCall(_, ref args) | - &ExprMethodCall(_, _, ref args) => { + match expr.node { + ExprCall(_, ref args) | + ExprMethodCall(_, _, ref args) => { for arg in args { check_closure(cx, &*arg) } diff --git a/src/len_zero.rs b/src/len_zero.rs index 073dcea582d..5eaa0256402 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -22,10 +22,10 @@ impl LintPass for LenZero { } fn check_item(&mut self, cx: &Context, item: &Item) { - match &item.node { - &ItemTrait(_, _, _, ref trait_items) => + match item.node { + ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), - &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait + ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait check_impl_items(cx, item, impl_items), _ => () } @@ -100,7 +100,7 @@ fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, op: &str) { - if let &Spanned{node: LitInt(0, _), ..} = lit { + if let Spanned{node: LitInt(0, _), ..} = *lit { if method.node.name == "len" && args.len() == 1 && has_is_empty(cx, &*args[0]) { span_lint(cx, LEN_ZERO, span, &format!( diff --git a/src/misc.rs b/src/misc.rs index 49324de8de9..81b03db5e14 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -175,8 +175,8 @@ impl LintPass for CmpOwned { } fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { - match &expr.node { - &ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { + match expr.node { + ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { let name = ident.name; if name == "to_string" || name == "to_owned" && is_str_arg(cx, args) { @@ -186,7 +186,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { snippet(cx, other_span, ".."))) } }, - &ExprCall(ref path, _) => { + ExprCall(ref path, _) => { if let &ExprPath(None, ref path) = &path.node { if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 18d98f1f063..7671d63a35d 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -60,9 +60,9 @@ fn fetch_bool_block(block: &Block) -> Option<bool> { } fn fetch_bool_expr(expr: &Expr) -> Option<bool> { - match &expr.node { - &ExprBlock(ref block) => fetch_bool_block(block), - &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { + match expr.node { + ExprBlock(ref block) => fetch_bool_block(block), + ExprLit(ref lit_ptr) => if let LitBool(value) = lit_ptr.node { Some(value) } else { None }, _ => None } diff --git a/src/strings.rs b/src/strings.rs index 64d18eeb26d..b24ea345244 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -65,13 +65,13 @@ fn is_string(cx: &Context, e: &Expr) -> bool { } fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { - match &src.node { - &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => + match src.node { + ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left), - &ExprBlock(ref block) => block.stmts.is_empty() && + ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, &*expr, target)), - &ExprParen(ref expr) => is_add(cx, &*expr, target), + ExprParen(ref expr) => is_add(cx, &*expr, target), _ => false } } diff --git a/src/types.rs b/src/types.rs index 54c36535286..cb85fd6e0c6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -116,10 +116,10 @@ declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: &ty::TyS) -> usize { - let n = match &typ.sty { - &ty::TyInt(i) => 4 << (i as usize), - &ty::TyUint(u) => 4 << (u as usize), - _ => 0 + let n = match typ.sty { + ty::TyInt(i) => 4 << (i as usize), + ty::TyUint(u) => 4 << (u as usize), + _ => 0 }; // n == 4 is the usize/isize case if n == 4 { ::std::usize::BITS } else { n } @@ -139,16 +139,16 @@ impl LintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits : usize = match &cast_to.sty { - &ty::TyFloat(ast::TyF32) => 32, - &ty::TyFloat(ast::TyF64) => 64, + let to_nbits : usize = match cast_to.sty { + ty::TyFloat(ast::TyF32) => 32, + ty::TyFloat(ast::TyF64) => 64, _ => 0 }; if from_nbits != 0 { if from_nbits >= to_nbits { span_lint(cx, CAST_PRECISION_LOSS, expr.span, &format!("converting from {0} to {1}, which causes a loss of precision \ - ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", + ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} )); } } -- cgit 1.4.1-3-g733a5 From 7580da306e338089b1cffedb09a71cb11debddf5 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 21 Aug 2015 20:49:59 +0200 Subject: matches: special message for this case match &e { &Pat1 => {}, &Pat2 => {}, ... } (inspired by dogfood fixes) --- src/matches.rs | 27 ++++++++++++++------------- tests/compile-fail/matches.rs | 6 ++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index b704a2b47bb..002da07f50b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -55,9 +55,15 @@ impl LintPass for MatchPass { // check preconditions for MATCH_REF_PATS if has_only_ref_pats(arms) { - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "instead of prefixing all patterns with `&`, you can dereference the \ - expression to match: `match *{} {{ ...`", snippet(cx, ex.span, ".."))); + if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "you don't need to add `&` to both the expression to match \ + and the patterns: use `match {} {{ ...`", snippet(cx, inner.span, ".."))); + } else { + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "instead of prefixing all patterns with `&`, you can dereference the \ + expression to match: `match *{} {{ ...`", snippet(cx, ex.span, ".."))); + } } } } @@ -72,14 +78,9 @@ fn is_unit_expr(expr: &Expr) -> bool { } fn has_only_ref_pats(arms: &[Arm]) -> bool { - for arm in arms { - for pat in &arm.pats { - match pat.node { - PatRegion(..) => (), // &-patterns - PatWild(..) => (), // an "anything" wildcard is also fine - _ => return false, - } - } - } - true + arms.iter().flat_map(|a| &a.pats).all(|p| match p.node { + PatRegion(..) => true, // &-patterns + PatWild(..) => true, // an "anything" wildcard is also fine + _ => false, + }) } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 43cf43b68df..3cc540992c9 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -53,6 +53,12 @@ fn ref_pats() { &(v, 1) => println!("{}", v), _ => println!("none"), } + // special case: using & both in expr and pats + let w = Some(0); + match &w { //~ERROR you don't need to add `&` to both + &Some(v) => println!("{:?}", v), + &None => println!("none"), + } } fn main() { -- cgit 1.4.1-3-g733a5 From 807dab943bc35b8f579cc082f385bdd5a6a98c63 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Sat, 22 Aug 2015 21:36:54 +0200 Subject: Updated test case for cast lints. Also improved readability and reworded the messages. --- tests/compile-fail/cast.rs | 78 +++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index 8e854fb21f9..9be0d501198 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -1,43 +1,57 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss)] -#[allow(dead_code)] +#[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap)] fn main() { - let i : i32 = 42; - let u : u32 = 42; - let f : f32 = 42.0; - // Test cast_precision_loss - i as f32; //~ERROR converting from i32 to f32, which causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - (i as i64) as f32; //~ERROR converting from i64 to f32, which causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - (i as i64) as f64; //~ERROR converting from i64 to f64, which causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - u as f32; //~ERROR converting from u32 to f32, which causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - (u as u64) as f32; //~ERROR converting from u64 to f32, which causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - (u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - i as f64; // Should not trigger the lint - u as f64; // Should not trigger the lint + 1i32 as f32; //~ERROR casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) + 1i64 as f32; //~ERROR casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) + 1i64 as f64; //~ERROR casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) + 1u32 as f32; //~ERROR casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) + 1u64 as f32; //~ERROR casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) + 1u64 as f64; //~ERROR casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) + 1i32 as f64; // Should not trigger the lint + 1u32 as f64; // Should not trigger the lint // Test cast_possible_truncation - f as i32; //~ERROR casting f32 to i32 may cause truncation of the value - f as u32; //~ERROR casting f32 to u32 may cause truncation of the value - //~^ERROR casting from f32 to u32 loses the sign of the value - i as u8; //~ERROR casting i32 to u8 may cause truncation of the value - //~^ERROR casting from i32 to u8 loses the sign of the value - (f as f64) as f32; //~ERROR casting f64 to f32 may cause truncation of the value - i as i8; //~ERROR casting i32 to i8 may cause truncation of the value - u as i32; //~ERROR casting u32 to i32 may cause truncation of the value + 1f32 as i32; //~ERROR casting f32 to i32 may truncate the value + 1f32 as u32; //~ERROR casting f32 to u32 may truncate the value + //~^ERROR casting f32 to u32 may lose the sign of the value + 1f64 as f32; //~ERROR casting f64 to f32 may truncate the value + 1i32 as i8; //~ERROR casting i32 to i8 may truncate the value + 1i32 as u8; //~ERROR casting i32 to u8 may truncate the value + //~^ERROR casting i32 to u8 may lose the sign of the value + 1f64 as isize; //~ERROR casting f64 to isize may truncate the value + 1f64 as usize; //~ERROR casting f64 to usize may truncate the value + //~^ERROR casting f64 to usize may lose the sign of the value + + // Test cast_possible_wrap + 1u8 as i8; //~ERROR casting u8 to i8 may wrap around the value + 1u16 as i16; //~ERROR casting u16 to i16 may wrap around the value + 1u32 as i32; //~ERROR casting u32 to i32 may wrap around the value + 1u64 as i64; //~ERROR casting u64 to i64 may wrap around the value + 1usize as isize; //~ERROR casting usize to isize may wrap around the value // Test cast_sign_loss - i as u32; //~ERROR casting from i32 to u32 loses the sign of the value + 1i32 as u32; //~ERROR casting i32 to u32 may lose the sign of the value + 1isize as usize; //~ERROR casting isize to usize may lose the sign of the value - // Extra checks for usize/isize - /* - let is : isize = -42; - let us : usize = 42; - is as usize; //ERROR casting from isize to usize loses the sign of the value - is as i8; //ERROR casting isize to i8 may cause truncation of the value - is as f64; //ERROR converting from isize to f64, which causes a loss of precision on 64-bit architectures (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - us as f64; //ERROR converting from usize to f64, which causes a loss of precision on 64-bit architectures (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - */ + // Extra checks for *size + // Casting from *size + 1isize as i8; //~ERROR casting isize to i8 may truncate the value + 1isize as f64; //~ERROR casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) + 1usize as f64; //~ERROR casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) + 1isize as f32; //~ERROR casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + 1usize as f32; //~ERROR casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + 1isize as i32; //~ERROR casting isize to i32 may truncate the value on targets with 64-bit wide pointers + 1isize as u32; //~ERROR casting isize to u32 may lose the sign of the value + //~^ERROR casting isize to u32 may truncate the value on targets with 64-bit wide pointers + 1usize as u32; //~ERROR casting usize to u32 may truncate the value on targets with 64-bit wide pointers + // Casting to *size + 1i64 as isize; //~ERROR casting i64 to isize may truncate the value on targets with 32-bit wide pointers + 1i64 as usize; //~ERROR casting i64 to usize may truncate the value on targets with 32-bit wide pointers + //~^ERROR casting i64 to usize may lose the sign of the value + 1u64 as isize; //~ERROR casting u64 to isize may truncate the value on targets with 32-bit wide pointers + //~^ERROR casting u64 to isize may wrap around the value on targets with 64-bit wide pointers + 1u64 as usize; //~ERROR casting u64 to usize may truncate the value on targets with 32-bit wide pointers } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 79ef13592e617e58b84146ba568c43bad81e77bf Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Sat, 22 Aug 2015 23:49:03 +0200 Subject: Completed the implementation of *size handling. Added some more cases to the test, and implemented a new lint, cast_possible_wrap, triggered when casting from an unsigned type to a signed type of the same size. --- README.md | 1 + src/lib.rs | 1 + src/types.rs | 86 +++++++++++++++++++++++++++++++++++----------- tests/compile-fail/cast.rs | 8 ++++- 4 files changed, 75 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index fbb16fcb170..7ac5388e0fe 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ approx_constant | warn | the approximate of a known float constant ( bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap cast_possible_truncation | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +cast_possible_wrap | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` cast_precision_loss | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` cast_sign_loss | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) diff --git a/src/lib.rs b/src/lib.rs index 9ea1efeed5f..19a62dd214b 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_ADD_ASSIGN, types::BOX_VEC, types::CAST_POSSIBLE_TRUNCATION, + types::CAST_POSSIBLE_WRAP, types::CAST_PRECISION_LOSS, types::CAST_SIGN_LOSS, types::LET_UNIT_VALUE, diff --git a/src/types.rs b/src/types.rs index e8da11ecbe0..579527cfff4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -145,6 +145,8 @@ declare_lint!(pub CAST_SIGN_LOSS, Allow, "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"); declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); +declare_lint!(pub CAST_POSSIBLE_WRAP, Allow, + "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`"); /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant @@ -169,7 +171,8 @@ impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!(CAST_PRECISION_LOSS, CAST_SIGN_LOSS, - CAST_POSSIBLE_TRUNCATION) + CAST_POSSIBLE_TRUNCATION, + CAST_POSSIBLE_WRAP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -186,50 +189,93 @@ impl LintPass for CastPass { }; if from_nbits != 0 { // When casting to f32, precision loss would occur regardless of the arch - if is_isize_or_usize(cast_from) && to_nbits == 64 { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("converting from {0} to f64, which causes a loss of precision on 64-bit architectures \ - ({0} is 64 bits wide, but f64's mantissa is only 52 bits wide)", - cast_from)); + if is_isize_or_usize(cast_from) { + if to_nbits == 64 { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("casting {0} to f64 causes a loss of precision on targets with 64-bit wide pointers \ + ({0} is 64 bits wide, but f64's mantissa is only 52 bits wide)", + cast_from)); + } + else { + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("casting {0} to f32 causes a loss of precision \ + ({0} is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)", + cast_from)); + } } else if from_nbits >= to_nbits { span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("converting from {0} to {1}, which causes a loss of precision \ + &format!("casting {0} to {1} causes a loss of precision \ ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} )); } } }, - (false, true) => { // Nothing to add there + (false, true) => { + // Nothing to add there as long as UB in involved when the cast overflows span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); + &format!("casting {} to {} may truncate the value", cast_from, cast_to)); if !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } }, (true, true) => { + let from_nbits = int_ty_to_nbits(cast_from); + let to_nbits = int_ty_to_nbits(cast_to); if cast_from.is_signed() && !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to)); + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } - let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = int_ty_to_nbits(cast_to); match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { (true, true) | (false, false) => - if to_nbits < from_nbits || - (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to)); + if to_nbits < from_nbits { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value", cast_from, cast_to)); + } + else if !cast_from.is_signed() && cast_to.is_signed() && to_nbits == from_nbits { + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value", cast_from, cast_to)); + }, + (true, false) => + if to_nbits == 32 { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value on targets with 64-bit wide pointers", + cast_from, cast_to)); + if !cast_from.is_signed() && cast_to.is_signed() { + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value on targets with 32-bit wide pointers", + cast_from, cast_to)); + } + } + else if to_nbits < 32 { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value", cast_from, cast_to)); }, - (true, false) => (), // TODO - (false, true) => () // TODO + (false, true) => + if from_nbits == 64 { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value on targets with 32-bit wide pointers", + cast_from, cast_to)); + if !cast_from.is_signed() && cast_to.is_signed() { + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value on targets with 64-bit wide pointers", + cast_from, cast_to)); + } + } + else { + if !cast_from.is_signed() && cast_to.is_signed() { + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value on targets with 32-bit wide pointers", + cast_from, cast_to)); + } + } } } (false, false) => { if let (&ty::TyFloat(ast::TyF64), &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may cause truncation of the value"); + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may truncate the value"); } } } diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index 9be0d501198..b17f5de841b 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -45,8 +45,10 @@ fn main() { 1usize as f32; //~ERROR casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) 1isize as i32; //~ERROR casting isize to i32 may truncate the value on targets with 64-bit wide pointers 1isize as u32; //~ERROR casting isize to u32 may lose the sign of the value - //~^ERROR casting isize to u32 may truncate the value on targets with 64-bit wide pointers + //~^ERROR casting isize to u32 may truncate the value on targets with 64-bit wide pointers 1usize as u32; //~ERROR casting usize to u32 may truncate the value on targets with 64-bit wide pointers + 1usize as i32; //~ERROR casting usize to i32 may truncate the value on targets with 64-bit wide pointers + //~^ERROR casting usize to i32 may wrap around the value on targets with 32-bit wide pointers // Casting to *size 1i64 as isize; //~ERROR casting i64 to isize may truncate the value on targets with 32-bit wide pointers 1i64 as usize; //~ERROR casting i64 to usize may truncate the value on targets with 32-bit wide pointers @@ -54,4 +56,8 @@ fn main() { 1u64 as isize; //~ERROR casting u64 to isize may truncate the value on targets with 32-bit wide pointers //~^ERROR casting u64 to isize may wrap around the value on targets with 64-bit wide pointers 1u64 as usize; //~ERROR casting u64 to usize may truncate the value on targets with 32-bit wide pointers + 1u32 as isize; //~ERROR casting u32 to isize may wrap around the value on targets with 32-bit wide pointers + 1u32 as usize; // Should not trigger any lint + 1i32 as isize; // Neither should this + 1i32 as usize; //~ERROR casting i32 to usize may lose the sign of the value } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 3af2e3ba857630214d9bc81756be1c07ae305fc4 Mon Sep 17 00:00:00 2001 From: "R.Chavignat" <r.chavignat@gmail.com> Date: Sun, 23 Aug 2015 01:06:31 +0200 Subject: Refactored CastPass. --- src/types.rs | 143 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 70 insertions(+), 73 deletions(-) diff --git a/src/types.rs b/src/types.rs index 47ee51e98ef..4e9dd133ac8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -134,6 +134,72 @@ fn is_isize_or_usize(typ: &ty::TyS) -> bool { } } +fn span_precision_loss_lint(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { + let mantissa_nbits = if cast_to_f64 {52} else {23}; + let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; + let arch_dependent_str = "on targets with 64-bit wide pointers "; + let from_nbits_str = if arch_dependent {"64".to_owned()} + else if is_isize_or_usize(cast_from) {"32 or 64".to_owned()} + else {int_ty_to_nbits(cast_from).to_string()}; + span_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("casting {0} to {1} causes a loss of precision {2}\ + ({0} is {3} bits wide, but {1}'s mantissa is only {4} bits wide)", + cast_from, if cast_to_f64 {"f64"} else {"f32"}, + if arch_dependent {arch_dependent_str} else {""}, + from_nbits_str, + mantissa_nbits)); +} + +enum ArchSuffix { + _32, _64, None +} + +fn check_truncation_and_wrapping(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { + let arch_64_suffix = " on targets with 64-bit wide pointers"; + let arch_32_suffix = " on targets with 32-bit wide pointers"; + let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); + let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); + let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = + match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { + (true, true) | (false, false) => ( + to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None + ), + (true, false) => ( + to_nbits <= 32, + if to_nbits == 32 {ArchSuffix::_64} else {ArchSuffix::None}, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32 + ), + (false, true) => ( + from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 {ArchSuffix::_64} else {ArchSuffix::_32} + ), + }; + if span_truncation { + span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value{}", + cast_from, cast_to, + match suffix_truncation { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "" })); + } + if span_wrap { + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value{}", + cast_from, cast_to, + match suffix_wrap { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "" })); + } +} + impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!(CAST_PRECISION_LOSS, @@ -149,33 +215,9 @@ impl LintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits : usize = match cast_to.sty { - ty::TyFloat(ast::TyF32) => 32, - ty::TyFloat(ast::TyF64) => 64, - _ => 0 - }; - if from_nbits != 0 { - // When casting to f32, precision loss would occur regardless of the arch - if is_isize_or_usize(cast_from) { - if to_nbits == 64 { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("casting {0} to f64 causes a loss of precision on targets with 64-bit wide pointers \ - ({0} is 64 bits wide, but f64's mantissa is only 52 bits wide)", - cast_from)); - } - else { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("casting {0} to f32 causes a loss of precision \ - ({0} is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)", - cast_from)); - } - } - else if from_nbits >= to_nbits { - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("casting {0} to {1} causes a loss of precision \ - ({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)", - cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} )); - } + let to_nbits = if let ty::TyFloat(ast::TyF32) = cast_to.sty {32} else {64}; + if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { + span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); } }, (false, true) => { @@ -187,56 +229,11 @@ impl LintPass for CastPass { } }, (true, true) => { - let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = int_ty_to_nbits(cast_to); if cast_from.is_signed() && !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } - match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => - if to_nbits < from_nbits { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value", cast_from, cast_to)); - } - else if !cast_from.is_signed() && cast_to.is_signed() && to_nbits == from_nbits { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value", cast_from, cast_to)); - }, - (true, false) => - if to_nbits == 32 { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value on targets with 64-bit wide pointers", - cast_from, cast_to)); - if !cast_from.is_signed() && cast_to.is_signed() { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value on targets with 32-bit wide pointers", - cast_from, cast_to)); - } - } - else if to_nbits < 32 { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value", cast_from, cast_to)); - }, - (false, true) => - if from_nbits == 64 { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value on targets with 32-bit wide pointers", - cast_from, cast_to)); - if !cast_from.is_signed() && cast_to.is_signed() { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value on targets with 64-bit wide pointers", - cast_from, cast_to)); - } - } - else { - if !cast_from.is_signed() && cast_to.is_signed() { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value on targets with 32-bit wide pointers", - cast_from, cast_to)); - } - } - } + check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { if let (&ty::TyFloat(ast::TyF64), -- cgit 1.4.1-3-g733a5 From c8a2e848ab249758f79ca048a5b06b8fef56cd87 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 23 Aug 2015 16:32:50 +0200 Subject: utils: extract utility method for matching trait method calls from loops --- src/loops.rs | 17 +++++------------ src/utils.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 36bab550b67..5f18439eafe 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,10 +1,9 @@ use rustc::lint::*; use syntax::ast::*; use syntax::visit::{Visitor, walk_expr}; -use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr, match_def_path}; +use utils::{snippet, span_lint, get_parent_expr, match_trait_method}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, "for-looping over a range of indices where an iterator over items would do" } @@ -68,16 +67,10 @@ impl LintPass for LoopsPass { object, object)); // check for looping over Iterator::next() which is not what you want } else if method_name == "next" { - let method_call = ty::MethodCall::expr(arg.id); - let trt_id = cx.tcx.tables - .borrow().method_map.get(&method_call) - .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); - if let Some(trt_id) = trt_id { - if match_def_path(cx, trt_id, &["core", "iter", "Iterator"]) { - span_lint(cx, ITER_NEXT_LOOP, expr.span, - "you are iterating over `Iterator::next()` which is an Option; \ - this will compile but is probably not what you want"); - } + if match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { + span_lint(cx, ITER_NEXT_LOOP, expr.span, + "you are iterating over `Iterator::next()` which is an Option; \ + this will compile but is probably not what you want"); } } } diff --git a/src/utils.rs b/src/utils.rs index 4fd36fb91d4..5e7c63e85d9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -56,6 +56,19 @@ pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool { } } +/// check if method call given in "expr" belongs to given trait +pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + let trt_id = cx.tcx.tables + .borrow().method_map.get(&method_call) + .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} + /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { -- cgit 1.4.1-3-g733a5 From cc8f33d9152c38ca59cb79ccb89aca70fb3a7420 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 23 Aug 2015 16:34:23 +0200 Subject: ranges: remove unneeded as_str() --- src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ranges.rs b/src/ranges.rs index d1a0a7e702e..914b4daa6be 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -20,7 +20,7 @@ impl LintPass for StepByZero { if let ExprMethodCall(Spanned { node: ref ident, .. }, _, ref args) = expr.node { // Only warn on literal ranges. - if ident.name.as_str() == "step_by" && args.len() == 2 && + if ident.name == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && is_lit_zero(&args[1]) { cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, "Range::step_by(0) produces an infinite iterator. \ -- cgit 1.4.1-3-g733a5 From 380e41a914133f8e1c527e1f18db835dc4feb3f1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 24 Aug 2015 16:23:05 +0200 Subject: improved README, added lint counter --- README.md | 13 +++---------- util/update_lints.py | 5 +++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 66881b52290..be7154c8c62 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -Lints included in this crate: +There are 45 lints included in this crate: name | default | meaning -------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -54,13 +54,6 @@ type_complexity | warn | usage of very complex types; recommends fac unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) zero_width_space | deny | using a zero-width space in a string literal, which is confusing -To use, add the following lines to your Cargo.toml: - -``` -[dependencies] -clippy = "*" -``` - More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! ##Usage @@ -69,8 +62,8 @@ Compiler plugins are highly unstable and will only work with a nightly Rust for Add in your `Cargo.toml`: ```toml -[dependencies.clippy] -git = "https://github.com/Manishearth/rust-clippy" +[dependencies] +clippy = "*" ``` Sample `main.rs`: diff --git a/util/update_lints.py b/util/update_lints.py index ed26637059f..940899d4ebb 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -113,6 +113,11 @@ def main(print_only=False, check=False): lambda: gen_table(lints), write_back=not check) + changed |= replace_region('README.md', + r'^There are \d+ lints included in this crate:', "", + lambda: ['There are %d lints included in this crate:\n' % len(lints)], + write_back=not check) + # same for "clippy" lint collection changed |= replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', lambda: gen_group(lints), replace_start=False, -- cgit 1.4.1-3-g733a5 From 209e6981a3ec67ddc8d94cb46d876550948f6238 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 17:11:34 +0200 Subject: shadowing detection --- README.md | 5 +- src/lib.rs | 11 ++ src/returns.rs | 2 +- src/shadow.rs | 224 +++++++++++++++++++++++++++++++++++++ src/utils.rs | 6 +- tests/compile-fail/approx_const.rs | 2 +- tests/compile-fail/shadow.rs | 22 ++++ 7 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 src/shadow.rs create mode 100644 tests/compile-fail/shadow.rs diff --git a/README.md b/README.md index be7154c8c62..71ca256fb9a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 45 lints included in this crate: +There are 48 lints included in this crate: name | default | meaning -------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -44,6 +44,9 @@ ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&S range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled +shadow_foreign | warn | The name is re-bound without even using the original value +shadow_reuse | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +shadow_same | allow | rebinding a name to itself, e.g. `let mut x = &mut x` single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead diff --git a/src/lib.rs b/src/lib.rs index 863ba2624dd..e65311133d2 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub mod len_zero; pub mod attrs; pub mod collapsible_if; pub mod unicode; +pub mod shadow; pub mod strings; pub mod methods; pub mod returns; @@ -64,6 +65,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box strings::StringAdd as LintPassObject); reg.register_lint_pass(box returns::ReturnPass as LintPassObject); reg.register_lint_pass(box methods::MethodsPass as LintPassObject); + reg.register_lint_pass(box shadow::ShadowPass as LintPassObject); reg.register_lint_pass(box types::LetPass as LintPassObject); reg.register_lint_pass(box types::UnitCmp as LintPassObject); reg.register_lint_pass(box loops::LoopsPass as LintPassObject); @@ -73,6 +75,12 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); reg.register_lint_pass(box matches::MatchPass as LintPassObject); + reg.register_lint_group("shadow", vec![ + shadow::SHADOW_FOREIGN, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, + ]); + reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, attrs::INLINE_ALWAYS, @@ -106,6 +114,9 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + shadow::SHADOW_FOREIGN, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::BOX_VEC, diff --git a/src/returns.rs b/src/returns.rs index df0b93f301e..a5779984334 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -11,7 +11,7 @@ declare_lint!(pub LET_AND_RETURN, Warn, "creating a let-binding and then immediately returning it like `let x = expr; x` at \ the end of a function"); -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct ReturnPass; impl ReturnPass { diff --git a/src/shadow.rs b/src/shadow.rs new file mode 100644 index 00000000000..bae05c17d7b --- /dev/null +++ b/src/shadow.rs @@ -0,0 +1,224 @@ +use syntax::ast::*; +use syntax::codemap::Span; +use syntax::visit::FnKind; + +use rustc::lint::{Context, LintArray, LintPass}; +use utils::{in_external_macro, snippet, span_lint}; + +declare_lint!(pub SHADOW_SAME, Allow, + "rebinding a name to itself, e.g. `let mut x = &mut x`"); +declare_lint!(pub SHADOW_REUSE, Allow, + "rebinding a name to an expression that re-uses the original value, e.g. \ + `let x = x + 1`"); +declare_lint!(pub SHADOW_FOREIGN, Warn, + "The name is re-bound without even using the original value"); + +#[derive(Copy, Clone)] +pub struct ShadowPass; + +impl LintPass for ShadowPass { + fn get_lints(&self) -> LintArray { + lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_FOREIGN) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, + block: &Block, _: Span, _: NodeId) { + if in_external_macro(cx, block.span) { return; } + check_fn(cx, decl, block); + } +} + +fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { + let mut bindings = Vec::new(); + for arg in &decl.inputs { + if let PatIdent(_, ident, _) = arg.pat.node { + bindings.push(ident.node.name) + } + } + check_block(cx, block, &mut bindings); +} + +fn named(pat: &Pat) -> Option<Name> { + if let PatIdent(_, ident, _) = pat.node { + Some(ident.node.name) + } else { None } +} + +fn add(bindings: &mut Vec<Name>, pat: &Pat) { + named(pat).map(|name| bindings.push(name)); +} + +fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { + let len = bindings.len(); + for stmt in &block.stmts { + match stmt.node { + StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), + StmtExpr(ref e, _) | StmtSemi(ref e, _) => + check_expr(cx, e, bindings), + _ => () + } + } + if let Some(ref o) = block.expr { check_expr(cx, o, bindings); } + bindings.truncate(len); +} + +fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { + if in_external_macro(cx, decl.span) { return; } + if let DeclLocal(ref local) = decl.node { + let Local{ ref pat, ref ty, ref init, id: _, span: _ } = **local; + if let &Some(ref t) = ty { check_ty(cx, t, bindings); } + named(pat).map(|name| if bindings.contains(&name) { + if let &Some(ref o) = init { + if in_external_macro(cx, o.span) { return; } + check_expr(cx, o, bindings); + bindings.push(name); + lint_shadow(cx, name, decl.span, pat.span, o); + } + }); + add(bindings, pat); + if let &Some(ref o) = init { + check_expr(cx, o, bindings) + } + } +} + +fn lint_shadow(cx: &Context, name: Name, span: Span, lspan: Span, init: &Expr) { + if is_self_shadow(name, init) { + span_lint(cx, SHADOW_SAME, span, &format!( + "{} is shadowed by itself in {}", + snippet(cx, lspan, "_"), + snippet(cx, init.span, ".."))); + } else { + if contains_self(name, init) { + span_lint(cx, SHADOW_REUSE, span, &format!( + "{} is shadowed by {} which reuses the original value", + snippet(cx, lspan, "_"), + snippet(cx, init.span, ".."))); + } else { + span_lint(cx, SHADOW_FOREIGN, span, &format!( + "{} is shadowed by {} in this declaration", + snippet(cx, lspan, "_"), + snippet(cx, init.span, ".."))); + } + } +} + +fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { + if in_external_macro(cx, expr.span) { return; } + match expr.node { + ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | + ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e) + => { check_expr(cx, e, bindings) }, + ExprBox(Some(ref place), ref e) => { + check_expr(cx, place, bindings); check_expr(cx, e, bindings) } + ExprBlock(ref block) | ExprLoop(ref block, _) => + { check_block(cx, block, bindings) }, + ExprVec(ref v) | ExprTup(ref v) => + for ref e in v { check_expr(cx, e, bindings) }, + ExprIf(ref cond, ref then, ref otherwise) => { + check_expr(cx, cond, bindings); + check_block(cx, then, bindings); + if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } + }, + ExprIfLet(ref pat, ref e, ref block, ref otherwise) => { + check_expr(cx, e, bindings); + let len = bindings.len(); + add(bindings, pat); + check_block(cx, block, bindings); + if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } + bindings.truncate(len); + }, + ExprWhile(ref cond, ref block, _) => { + check_expr(cx, cond, bindings); + check_block(cx, block, bindings); + }, + ExprWhileLet(ref pat, ref e, ref block, _) | + ExprForLoop(ref pat, ref e, ref block, _) => { + check_expr(cx, e, bindings); + let len = bindings.len(); + add(bindings, pat); + check_block(cx, block, bindings); + bindings.truncate(len); + }, + _ => () + } +} + +fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<Name>) { + match ty.node { + TyParen(ref sty) | TyObjectSum(ref sty, _) | + TyVec(ref sty) => check_ty(cx, sty, bindings), + TyFixedLengthVec(ref fty, ref expr) => { + check_ty(cx, fty, bindings); + check_expr(cx, expr, bindings); + }, + TyPtr(MutTy{ ty: ref mty, .. }) | + TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } }, + TyTypeof(ref expr) => check_expr(cx, expr, bindings), + _ => (), + } +} + +fn is_self_shadow(name: Name, expr: &Expr) -> bool { + match expr.node { + ExprBox(_, ref inner) | + ExprParen(ref inner) | + ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), + ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref(). + map_or(false, |ref e| is_self_shadow(name, e)), + ExprUnary(op, ref inner) => (UnUniq == op || UnDeref == op) && + is_self_shadow(name, inner), + ExprPath(_, ref path) => path.segments.len() == 1 && + path.segments[0].identifier.name == name, + _ => false, + } +} + +fn contains_self(name: Name, expr: &Expr) -> bool { + match expr.node { + ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | + ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) + => contains_self(name, e), + ExprBinary(_, ref l, ref r) => + contains_self(name, l) || contains_self(name, r), + ExprBlock(ref block) | ExprLoop(ref block, _) => + contains_block_self(name, block), + ExprCall(ref fun, ref args) => contains_self(name, fun) || + args.iter().any(|ref a| contains_self(name, a)), + ExprMethodCall(_, _, ref args) => + args.iter().any(|ref a| contains_self(name, a)), + ExprVec(ref v) | ExprTup(ref v) => + v.iter().any(|ref e| contains_self(name, e)), + ExprIf(ref cond, ref then, ref otherwise) => + contains_self(name, cond) || contains_block_self(name, then) || + otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)), + ExprIfLet(_, ref e, ref block, ref otherwise) => + contains_self(name, e) || contains_block_self(name, block) || + otherwise.as_ref().map_or(false, |ref o| contains_self(name, o)), + ExprWhile(ref e, ref block, _) | + ExprWhileLet(_, ref e, ref block, _) | + ExprForLoop(_, ref e, ref block, _) => + contains_self(name, e) || contains_block_self(name, block), + ExprPath(_, ref path) => path.segments.len() == 1 && + path.segments[0].identifier.name == name, + _ => false + } +} + +fn contains_block_self(name: Name, block: &Block) -> bool { + for stmt in &block.stmts { + match stmt.node { + StmtDecl(ref decl, _) => + if let DeclLocal(ref local) = decl.node { + if let Some(ref init) = local.init { + if contains_self(name, init) { return true; } + } + }, + StmtExpr(ref e, _) | StmtSemi(ref e, _) => + if contains_self(name, e) { return true }, + _ => () + } + } + if let Some(ref e) = block.expr { contains_self(name, e) } else { false } +} diff --git a/src/utils.rs b/src/utils.rs index 5e7c63e85d9..6cb21148356 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -94,9 +94,9 @@ pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, /// Trim indentation from a multiline string /// with possibility of ignoring the first line pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { - let s = trim_multiline_inner(s, ignore_first, ' '); - let s = trim_multiline_inner(s, ignore_first, '\t'); - trim_multiline_inner(s, ignore_first, ' ') + let s_space = trim_multiline_inner(s, ignore_first, ' '); + let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); + trim_multiline_inner(s_tab, ignore_first, ' ') } fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index 799795becbd..4c289b474f7 100755 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(approx_constant)] -#[allow(unused)] +#[allow(unused, shadow_foreign)] fn main() { let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::E` found let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::E` found diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs new file mode 100644 index 00000000000..e3213717213 --- /dev/null +++ b/tests/compile-fail/shadow.rs @@ -0,0 +1,22 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused_parens, unused_variables)] +#![deny(shadow)] + +fn id<T>(x: T) -> T { x } + +fn first(x: (isize, isize)) -> isize { x.0 } + +fn main() { + let mut x = 1; + let x = &mut x; //~ERROR: x is shadowed by itself in &mut x + let x = { x }; //~ERROR: x is shadowed by itself in { x } + let x = (&*x); //~ERROR: x is shadowed by itself in (&*x) + let x = { *x + 1 }; //~ERROR: x is shadowed by { *x + 1 } which reuses + let x = id(x); //~ERROR: x is shadowed by id(x) which reuses + let x = (1, x); //~ERROR: x is shadowed by (1, x) which reuses + let x = first(x); //~ERROR: x is shadowed by first(x) which reuses + let y = 1; + let x = y; //~ERROR: x is shadowed by y in this declaration +} -- cgit 1.4.1-3-g733a5 From 56e8db476c437590f21be041c0e751ee185d8dd0 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 24 Aug 2015 18:13:02 +0200 Subject: new lint: inherent methods that should be trait impls (fixes #218) --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 118 +++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/methods.rs | 23 +++++++- 4 files changed, 140 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index be7154c8c62..9d86ece99d6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 45 lints included in this crate: +There are 46 lints included in this crate: name | default | meaning -------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -44,6 +44,7 @@ ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&S range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled +should_implement_trait | warn | defining a method that should be implementing a std trait single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead diff --git a/src/lib.rs b/src/lib.rs index 863ba2624dd..bacff19addc 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::SINGLE_MATCH, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, misc::CMP_NAN, diff --git a/src/methods.rs b/src/methods.rs index df8e35d98fb..73cf81fbdae 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -2,9 +2,12 @@ use syntax::ast::*; use rustc::lint::*; use rustc::middle::ty; -use utils::{span_lint, match_type, walk_ptrs_ty}; +use utils::{span_lint, match_path, match_type, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; +use self::SelfKind::*; +use self::OutType::*; + #[derive(Copy,Clone)] pub struct MethodsPass; @@ -16,10 +19,13 @@ declare_lint!(pub STR_TO_STRING, Warn, "using `to_string()` on a str, which should be `to_owned()`"); declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); +declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, + "defining a method that should be implementing a std trait"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING) + lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, + SHOULD_IMPLEMENT_TRAIT) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -46,4 +52,112 @@ impl LintPass for MethodsPass { } } } + + fn check_item(&mut self, cx: &Context, item: &Item) { + if let ItemImpl(_, _, _, None, _, ref items) = item.node { + for item in items { + let name = item.ident.name; + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if_let_chain! { + [ + name == method_name, + let MethodImplItem(ref sig, _) = item.node, + sig.decl.inputs.len() == n_args, + out_type.matches(&sig.decl.output), + self_kind.matches(&sig.explicit_self.node) + ], { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, item.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } + } + } + } + } + } +} + +const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ + ("add", 2, ValueSelf, AnyType, "std::ops::Add`"), + ("sub", 2, ValueSelf, AnyType, "std::ops::Sub"), + ("mul", 2, ValueSelf, AnyType, "std::ops::Mul"), + ("div", 2, ValueSelf, AnyType, "std::ops::Div"), + ("rem", 2, ValueSelf, AnyType, "std::ops::Rem"), + ("shl", 2, ValueSelf, AnyType, "std::ops::Shl"), + ("shr", 2, ValueSelf, AnyType, "std::ops::Shr"), + ("bitand", 2, ValueSelf, AnyType, "std::ops::BitAnd"), + ("bitor", 2, ValueSelf, AnyType, "std::ops::BitOr"), + ("bitxor", 2, ValueSelf, AnyType, "std::ops::BitXor"), + ("neg", 1, ValueSelf, AnyType, "std::ops::Neg"), + ("not", 1, ValueSelf, AnyType, "std::ops::Not"), + ("drop", 1, RefMutSelf, UnitType, "std::ops::Drop"), + ("index", 2, RefSelf, RefType, "std::ops::Index"), + ("index_mut", 2, RefMutSelf, RefType, "std::ops::IndexMut"), + ("deref", 1, RefSelf, RefType, "std::ops::Deref"), + ("deref_mut", 1, RefMutSelf, RefType, "std::ops::DerefMut"), + ("clone", 1, RefSelf, AnyType, "std::clone::Clone"), + ("borrow", 1, RefSelf, RefType, "std::borrow::Borrow"), + ("borrow_mut", 1, RefMutSelf, RefType, "std::borrow::BorrowMut"), + ("as_ref", 1, RefSelf, RefType, "std::convert::AsRef"), + ("as_mut", 1, RefMutSelf, RefType, "std::convert::AsMut"), + ("eq", 2, RefSelf, BoolType, "std::cmp::PartialEq"), + ("cmp", 2, RefSelf, AnyType, "std::cmp::Ord"), + ("default", 0, NoSelf, AnyType, "std::default::Default"), + ("hash", 2, RefSelf, UnitType, "std::hash::Hash"), + ("next", 1, RefMutSelf, AnyType, "std::iter::Iterator"), + ("into_iter", 1, ValueSelf, AnyType, "std::iter::IntoIterator"), + ("from_iter", 1, NoSelf, AnyType, "std::iter::FromIterator"), + ("from_str", 1, NoSelf, AnyType, "std::str::FromStr"), +]; + +#[derive(Clone, Copy)] +enum SelfKind { + ValueSelf, + RefSelf, + RefMutSelf, + NoSelf +} + +impl SelfKind { + fn matches(&self, slf: &ExplicitSelf_) -> bool { + match (self, slf) { + (&ValueSelf, &SelfValue(_)) => true, + (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true, + (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true, + (&NoSelf, &SelfStatic) => true, + _ => false + } + } +} + +#[derive(Clone, Copy)] +enum OutType { + UnitType, + BoolType, + AnyType, + RefType, +} + +impl OutType { + fn matches(&self, ty: &FunctionRetTy) -> bool { + match (self, ty) { + (&UnitType, &DefaultReturn(_)) => true, + (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![]) => true, + (&BoolType, &Return(ref ty)) if is_bool(ty) => true, + (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![]) => true, + (&RefType, &Return(ref ty)) => { + if let TyRptr(_, _) = ty.node { true } else { false } + } + _ => false + } + } +} + +fn is_bool(ty: &Ty) -> bool { + if let TyPath(None, ref p) = ty.node { + if match_path(p, &["bool"]) { + return true; + } + } + false } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 91d3b72de84..cb77d79f0ff 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -1,8 +1,27 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(option_unwrap_used, result_unwrap_used)] -#[deny(str_to_string, string_to_string)] +#![allow(unused)] +#![deny(clippy)] + +use std::ops::Mul; + +struct T; + +impl T { + fn add(self, other: T) -> T { self } //~ERROR defining a method called `add` + fn drop(&mut self) { } //~ERROR defining a method called `drop` + + fn sub(&self, other: T) -> &T { self } // no error, self is a ref + fn div(self) -> T { self } // no error, different #arguments + fn rem(self, other: T) { } // no error, wrong return type +} + +impl Mul<T> for T { + type Output = T; + fn mul(self, other: T) -> T { self } // no error, obviously +} + fn main() { let opt = Some(0); let _ = opt.unwrap(); //~ERROR used unwrap() on an Option -- cgit 1.4.1-3-g733a5 From 64cd1fc6ba266fdcfe96415a293a732df5741a04 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 12:34:27 +0200 Subject: eq_op: cut back to expressions that are guaranteed side effect free fixes #229 --- src/eq_op.rs | 211 ++++++-------------------------------------- tests/compile-fail/eq_op.rs | 6 -- 2 files changed, 26 insertions(+), 191 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index ebc6aa17100..3b4f47b5562 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -2,7 +2,6 @@ use rustc::lint::*; use syntax::ast::*; use syntax::ast_util as ast_util; use syntax::ptr::P; -use syntax::codemap as code; use consts::constant; use utils::span_lint; @@ -33,42 +32,27 @@ impl LintPass for EqOp { } pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { - if match (&left.node, &right.node) { - (&ExprBinary(ref lop, ref ll, ref lr), - &ExprBinary(ref rop, ref rl, ref rr)) => - lop.node == rop.node && - is_exp_equal(cx, ll, rl) && is_exp_equal(cx, lr, rr), - (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(cx, l, r)) && - is_exp_equal(cx, lbox, rbox), - (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(cx, lcallee, - rcallee) && is_exps_equal(cx, largs, rargs), - (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => - is_ty_equal(cx, lty, rty) && is_exp_equal(cx, lc, rc), + if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { + if l == r { + return true; + } + } + match (&left.node, &right.node) { (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprMethodCall(ref lident, ref lcty, ref lmargs), - &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(cx, lcty, rcty) && - is_exps_equal(cx, lmargs, rmargs), (&ExprParen(ref lparen), _) => is_exp_equal(cx, lparen, right), (_, &ExprParen(ref rparen)) => is_exp_equal(cx, left, rparen), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, |l, r| is_qself_equal(l, r)) && + both(lqself, rqself, is_qself_equal) && is_path_equal(lsubpath, rsubpath), (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup), - (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(cx, l, r), (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), - _ => false - } { return true; } - match (constant(cx, left), constant(cx, right)) { - (Some(l), Some(r)) => l == r, + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => + is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), _ => false } } @@ -90,166 +74,6 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } -fn is_ty_equal(cx: &Context, left : &Ty, right : &Ty) -> bool { - match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(cx, lvec, rvec), - (&TyFixedLengthVec(ref lfvty, ref lfvexp), - &TyFixedLengthVec(ref rfvty, ref rfvexp)) => - is_ty_equal(cx, lfvty, rfvty) && is_exp_equal(cx, lfvexp, rfvexp), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(cx, lmut, rmut), - (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => - both(ltime, rtime, is_lifetime_equal) && - is_mut_ty_equal(cx, lrmut, rrmut), - (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => - is_bare_fn_ty_equal(cx, lbare, rbare), - (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(cx, ltup, rtup), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => - both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), - (&TyObjectSum(ref lsumty, ref lobounds), - &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(cx, lsumty, rsumty) && - is_param_bounds_equal(lobounds, robounds), - (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => - is_param_bounds_equal(ltbounds, rtbounds), - (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(cx, lty, rty), - (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(cx, lof, rof), - (&TyInfer, &TyInfer) => true, - _ => false - } -} - -fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) - -> bool { - match(left, right) { - (&TraitTyParamBound(ref lpoly, ref lmod), - &TraitTyParamBound(ref rpoly, ref rmod)) => - lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), - (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => - is_lifetime_equal(ltime, rtime), - _ => false - } -} - -fn is_poly_traitref_equal(left : &PolyTraitRef, right : &PolyTraitRef) - -> bool { - is_lifetimedefs_equal(&left.bound_lifetimes, &right.bound_lifetimes) - && is_path_equal(&left.trait_ref.path, &right.trait_ref.path) -} - -fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) - -> bool { - over(left, right, is_param_bound_equal) -} - -fn is_mut_ty_equal(cx: &Context, left : &MutTy, right : &MutTy) -> bool { - left.mutbl == right.mutbl && is_ty_equal(cx, &left.ty, &right.ty) -} - -fn is_bare_fn_ty_equal(cx: &Context, left : &BareFnTy, right : &BareFnTy) -> bool { - left.unsafety == right.unsafety && left.abi == right.abi && - is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && - is_fndecl_equal(cx, &left.decl, &right.decl) -} - -fn is_fndecl_equal(cx: &Context, left : &P<FnDecl>, right : &P<FnDecl>) -> bool { - left.variadic == right.variadic && - is_args_equal(cx, &left.inputs, &right.inputs) && - is_fnret_ty_equal(cx, &left.output, &right.output) -} - -fn is_fnret_ty_equal(cx: &Context, left : &FunctionRetTy, - right : &FunctionRetTy) -> bool { - match (left, right) { - (&NoReturn(_), &NoReturn(_)) | - (&DefaultReturn(_), &DefaultReturn(_)) => true, - (&Return(ref lty), &Return(ref rty)) => is_ty_equal(cx, lty, rty), - _ => false - } -} - -fn is_arg_equal(cx: &Context, l: &Arg, r : &Arg) -> bool { - is_ty_equal(cx, &l.ty, &r.ty) && is_pat_equal(cx, &l.pat, &r.pat) -} - -fn is_args_equal(cx: &Context, left : &[Arg], right : &[Arg]) -> bool { - over(left, right, |l, r| is_arg_equal(cx, l, r)) -} - -fn is_pat_equal(cx: &Context, left : &Pat, right : &Pat) -> bool { - match(&left.node, &right.node) { - (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, - (&PatIdent(ref lmode, ref lident, Option::None), - &PatIdent(ref rmode, ref rident, Option::None)) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node), - (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), - &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node) && - is_pat_equal(cx, lpat, rpat), - (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => - is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| - is_pats_equal(cx, l, r)), - (&PatStruct(ref lpath, ref lfieldpat, lbool), - &PatStruct(ref rpath, ref rfieldpat, rbool)) => - lbool == rbool && is_path_equal(lpath, rpath) && - is_spanned_fieldpats_equal(cx, lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(cx, ltup, rtup), - (&PatBox(ref lboxed), &PatBox(ref rboxed)) => - is_pat_equal(cx, lboxed, rboxed), - (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => - is_pat_equal(cx, lpat, rpat) && lmut == rmut, - (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(cx, llit, rlit), - (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => - is_exp_equal(cx, lfrom, rfrom) && is_exp_equal(cx, lto, rto), - (&PatVec(ref lfirst, Option::None, ref llast), - &PatVec(ref rfirst, Option::None, ref rlast)) => - is_pats_equal(cx, lfirst, rfirst) && is_pats_equal(cx, llast, rlast), - (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), - &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(cx, lfirst, rfirst) && is_pat_equal(cx, lpat, rpat) && - is_pats_equal(cx, llast, rlast), - // I don't match macros for now, the code is slow enough as is ;-) - _ => false - } -} - -fn is_spanned_fieldpats_equal(cx: &Context, left : &[code::Spanned<FieldPat>], - right : &[code::Spanned<FieldPat>]) -> bool { - over(left, right, |l, r| is_fieldpat_equal(cx, &l.node, &r.node)) -} - -fn is_fieldpat_equal(cx: &Context, left : &FieldPat, right : &FieldPat) -> bool { - left.is_shorthand == right.is_shorthand && - is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(cx, &left.pat, &right.pat) -} - -fn is_ident_equal(left : &Ident, right : &Ident) -> bool { - &left.name == &right.name && left.ctxt == right.ctxt -} - -fn is_pats_equal(cx: &Context, left : &[P<Pat>], right : &[P<Pat>]) -> bool { - over(left, right, |l, r| is_pat_equal(cx, l, r)) -} - -fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) - -> bool { - is_lifetime_equal(&left.lifetime, &right.lifetime) && - over(&left.bounds, &right.bounds, is_lifetime_equal) -} - -fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) - -> bool { - over(left, right, is_lifetimedef_equal) -} - -fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { - left.name == right.name -} - -fn is_tys_equal(cx: &Context, left : &[P<Ty>], right : &[P<Ty>]) -> bool { - over(left, right, |l, r| is_ty_equal(cx, l, r)) -} - fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| @@ -269,3 +93,20 @@ fn is_cmp_or_bit(op : &BinOp) -> bool { _ => false } } + +fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { + match (&left.node, &right.node) { + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => + lmut.mutbl == rmut.mutbl && + is_cast_ty_equal(&*lmut.ty, &*rmut.ty), + (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => + lrmut.mutbl == rrmut.mutbl && + is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty), + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), + (&TyParen(ref lty), &TyParen(ref rty)) => is_cast_ty_equal(lty, rty), + (&TyInfer, &TyInfer) => true, + _ => false + } +} diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index a1183629344..fc59c2739a2 100755 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -1,10 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -fn id<X>(x: X) -> X { - x -} - #[deny(eq_op)] #[allow(identity_op)] fn main() { @@ -19,7 +15,6 @@ fn main() { // casts, methods, parentheses (1 as u64) & (1 as u64); //~ERROR equal expressions 1 ^ ((((((1)))))); //~ERROR equal expressions - id((1)) | id(1); //~ERROR equal expressions // unary and binary operators (-(2) < -(2)); //~ERROR equal expressions @@ -32,7 +27,6 @@ fn main() { // various other things ([1] != [1]); //~ERROR equal expressions ((1, 2) != (1, 2)); //~ERROR equal expressions - [1].len() == [1].len(); //~ERROR equal expressions vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros // const folding -- cgit 1.4.1-3-g733a5 From 81ef3da03cfb00eb16bd01d884fdc38835d9dfe0 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 12:45:52 +0200 Subject: methods: people might be using to_string() to make a copy; add a hint for that --- src/methods.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index df8e35d98fb..40043be109a 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -41,7 +41,8 @@ impl LintPass for MethodsPass { if obj_ty.sty == ty::TyStr { span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); } else if match_type(cx, obj_ty, &STRING_PATH) { - span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op"); + span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \ + `clone()` to make a copy"); } } } -- cgit 1.4.1-3-g733a5 From d5c808acd05d5f91b2358984b0c4c97c33cfc1f9 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 13:26:20 +0200 Subject: collapsible_if: remove extraneous note output This was probably a debug addition. --- src/collapsible_if.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 0b6dfc19e6b..7d654b43f2f 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -48,7 +48,6 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if e.span.expn_id != sp.expn_id { return; } - cx.sess().note(&format!("{:?} -- {:?}", e.span, sp)); span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", &format!("try\nif {} && {} {}", -- cgit 1.4.1-3-g733a5 From 5225feceaa345e55bdd3b45007555f6d477faf55 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 17:11:34 +0200 Subject: shadowing detection --- README.md | 2 +- src/lib.rs | 4 +- src/methods.rs | 3 +- src/shadow.rs | 144 ++++++++++++++++++++++--------------- tests/compile-fail/approx_const.rs | 2 +- 5 files changed, 93 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 71ca256fb9a..66411e432c9 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&S range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled -shadow_foreign | warn | The name is re-bound without even using the original value shadow_reuse | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` shadow_same | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +shadow_unrelated | warn | The name is re-bound without even using the original value single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead diff --git a/src/lib.rs b/src/lib.rs index e65311133d2..33788190fd3 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,9 +76,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box matches::MatchPass as LintPassObject); reg.register_lint_group("shadow", vec![ - shadow::SHADOW_FOREIGN, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, ]); reg.register_lint_group("clippy", vec![ @@ -114,9 +114,9 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, - shadow::SHADOW_FOREIGN, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::BOX_VEC, diff --git a/src/methods.rs b/src/methods.rs index df8e35d98fb..40043be109a 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -41,7 +41,8 @@ impl LintPass for MethodsPass { if obj_ty.sty == ty::TyStr { span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); } else if match_type(cx, obj_ty, &STRING_PATH) { - span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op"); + span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \ + `clone()` to make a copy"); } } } diff --git a/src/shadow.rs b/src/shadow.rs index bae05c17d7b..bbd146f77a5 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -1,3 +1,4 @@ +use std::ops::Deref; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; @@ -10,7 +11,7 @@ declare_lint!(pub SHADOW_SAME, Allow, declare_lint!(pub SHADOW_REUSE, Allow, "rebinding a name to an expression that re-uses the original value, e.g. \ `let x = x + 1`"); -declare_lint!(pub SHADOW_FOREIGN, Warn, +declare_lint!(pub SHADOW_UNRELATED, Warn, "The name is re-bound without even using the original value"); #[derive(Copy, Clone)] @@ -18,7 +19,7 @@ pub struct ShadowPass; impl LintPass for ShadowPass { fn get_lints(&self) -> LintArray { - lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_FOREIGN) + lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, @@ -44,10 +45,6 @@ fn named(pat: &Pat) -> Option<Name> { } else { None } } -fn add(bindings: &mut Vec<Name>, pat: &Pat) { - named(pat).map(|name| bindings.push(name)); -} - fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { let len = bindings.len(); for stmt in &block.stmts { @@ -65,41 +62,53 @@ fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { if in_external_macro(cx, decl.span) { return; } if let DeclLocal(ref local) = decl.node { - let Local{ ref pat, ref ty, ref init, id: _, span: _ } = **local; - if let &Some(ref t) = ty { check_ty(cx, t, bindings); } - named(pat).map(|name| if bindings.contains(&name) { - if let &Some(ref o) = init { - if in_external_macro(cx, o.span) { return; } + let Local{ ref pat, ref ty, ref init, id: _, span } = **local; + if let &Some(ref t) = ty { check_ty(cx, t, bindings) } + check_pat(cx, pat, init, span, bindings); + if let &Some(ref o) = init { check_expr(cx, o, bindings) } + } +} + +fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, + bindings: &mut Vec<Name>) where T: Deref<Target=Expr> { + //TODO: match more stuff / destructuring + named(pat).map(|name| { + if let &Some(ref o) = init { + if !in_external_macro(cx, o.span) { check_expr(cx, o, bindings); - bindings.push(name); - lint_shadow(cx, name, decl.span, pat.span, o); } - }); - add(bindings, pat); - if let &Some(ref o) = init { - check_expr(cx, o, bindings) } - } + if bindings.contains(&name) { + lint_shadow(cx, name, span, pat.span, init); + } + bindings.push(name); + }); } -fn lint_shadow(cx: &Context, name: Name, span: Span, lspan: Span, init: &Expr) { - if is_self_shadow(name, init) { - span_lint(cx, SHADOW_SAME, span, &format!( - "{} is shadowed by itself in {}", - snippet(cx, lspan, "_"), - snippet(cx, init.span, ".."))); - } else { - if contains_self(name, init) { - span_lint(cx, SHADOW_REUSE, span, &format!( - "{} is shadowed by {} which reuses the original value", +fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: + &Option<T>) where T: Deref<Target=Expr> { + if let &Some(ref expr) = init { + if is_self_shadow(name, expr) { + span_lint(cx, SHADOW_SAME, span, &format!( + "{} is shadowed by itself in {}", snippet(cx, lspan, "_"), - snippet(cx, init.span, ".."))); + snippet(cx, expr.span, ".."))); } else { - span_lint(cx, SHADOW_FOREIGN, span, &format!( - "{} is shadowed by {} in this declaration", - snippet(cx, lspan, "_"), - snippet(cx, init.span, ".."))); + if contains_self(name, expr) { + span_lint(cx, SHADOW_REUSE, span, &format!( + "{} is shadowed by {} which reuses the original value", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, ".."))); + } else { + span_lint(cx, SHADOW_UNRELATED, span, &format!( + "{} is shadowed by {} in this declaration", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, ".."))); + } } + } else { + span_lint(cx, SHADOW_UNRELATED, span, &format!( + "{} is shadowed in this declaration", snippet(cx, lspan, "_"))); } } @@ -120,26 +129,21 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { check_block(cx, then, bindings); if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } }, - ExprIfLet(ref pat, ref e, ref block, ref otherwise) => { - check_expr(cx, e, bindings); - let len = bindings.len(); - add(bindings, pat); - check_block(cx, block, bindings); - if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } - bindings.truncate(len); - }, ExprWhile(ref cond, ref block, _) => { check_expr(cx, cond, bindings); check_block(cx, block, bindings); }, - ExprWhileLet(ref pat, ref e, ref block, _) | - ExprForLoop(ref pat, ref e, ref block, _) => { - check_expr(cx, e, bindings); - let len = bindings.len(); - add(bindings, pat); - check_block(cx, block, bindings); - bindings.truncate(len); - }, + ExprMatch(ref init, ref arms, _) => + for ref arm in arms { + for ref pat in &arm.pats { + //TODO: This is ugly, but needed to get the right type + check_pat(cx, pat, &Some(&**init), pat.span, bindings); + } + if let Some(ref guard) = arm.guard { + check_expr(cx, guard, bindings); + } + check_expr(cx, &*arm.body, bindings); + }, _ => () } } @@ -169,12 +173,15 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { map_or(false, |ref e| is_self_shadow(name, e)), ExprUnary(op, ref inner) => (UnUniq == op || UnDeref == op) && is_self_shadow(name, inner), - ExprPath(_, ref path) => path.segments.len() == 1 && - path.segments[0].identifier.name == name, + ExprPath(_, ref path) => path_eq_name(name, path), _ => false, } } +fn path_eq_name(name: Name, path: &Path) -> bool { + path.segments.len() == 1 && path.segments[0].identifier.name == name +} + fn contains_self(name: Name, expr: &Expr) -> bool { match expr.node { ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | @@ -193,13 +200,11 @@ fn contains_self(name: Name, expr: &Expr) -> bool { ExprIf(ref cond, ref then, ref otherwise) => contains_self(name, cond) || contains_block_self(name, then) || otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)), - ExprIfLet(_, ref e, ref block, ref otherwise) => - contains_self(name, e) || contains_block_self(name, block) || - otherwise.as_ref().map_or(false, |ref o| contains_self(name, o)), - ExprWhile(ref e, ref block, _) | - ExprWhileLet(_, ref e, ref block, _) | - ExprForLoop(_, ref e, ref block, _) => + ExprWhile(ref e, ref block, _) => contains_self(name, e) || contains_block_self(name, block), + ExprMatch(ref e, ref arms, _) => + arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat| + contains_pat_self(name, pat))) || contains_self(name, e), ExprPath(_, ref path) => path.segments.len() == 1 && path.segments[0].identifier.name == name, _ => false @@ -211,6 +216,9 @@ fn contains_block_self(name: Name, block: &Block) -> bool { match stmt.node { StmtDecl(ref decl, _) => if let DeclLocal(ref local) = decl.node { + //TODO: We don't currently handle the case where the name + //is shadowed wiithin the block; this means code including this + //degenerate pattern will get the wrong warning. if let Some(ref init) = local.init { if contains_self(name, init) { return true; } } @@ -222,3 +230,25 @@ fn contains_block_self(name: Name, block: &Block) -> bool { } if let Some(ref e) = block.expr { contains_self(name, e) } else { false } } + +fn contains_pat_self(name: Name, pat: &Pat) -> bool { + match pat.node { + PatIdent(_, ref ident, ref inner) => name == ident.node.name || + inner.as_ref().map_or(false, |ref p| contains_pat_self(name, p)), + PatEnum(_, ref opats) => opats.as_ref().map_or(false, + |pats| pats.iter().any(|p| contains_pat_self(name, p))), + PatQPath(_, ref path) => path_eq_name(name, path), + PatStruct(_, ref fieldpats, _) => fieldpats.iter().any( + |ref fp| contains_pat_self(name, &fp.node.pat)), + PatTup(ref ps) => ps.iter().any(|ref p| contains_pat_self(name, p)), + PatBox(ref p) | + PatRegion(ref p, _) => contains_pat_self(name, p), + PatRange(ref from, ref until) => + contains_self(name, from) || contains_self(name, until), + PatVec(ref pre, ref opt, ref post) => + pre.iter().any(|ref p| contains_pat_self(name, p)) || + opt.as_ref().map_or(false, |ref p| contains_pat_self(name, p)) || + post.iter().any(|ref p| contains_pat_self(name, p)), + _ => false, + } +} diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index 4c289b474f7..a75cd0bf3f2 100755 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(approx_constant)] -#[allow(unused, shadow_foreign)] +#[allow(unused, shadow_unrelated)] fn main() { let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::E` found let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::E` found -- cgit 1.4.1-3-g733a5 From 92a3394065e601f6f4ace7f374f5ce782d7b211d Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 14:41:35 +0200 Subject: all: remove unneeded deref and/or ref operations --- src/attrs.rs | 4 ++-- src/collapsible_if.rs | 2 +- src/consts.rs | 6 +++--- src/eta_reduction.rs | 2 +- src/len_zero.rs | 2 +- src/lifetimes.rs | 6 +++--- src/loops.rs | 6 +++--- src/matches.rs | 10 +++++----- src/methods.rs | 2 +- src/misc.rs | 2 +- src/needless_bool.rs | 4 ++-- src/ptr_arg.rs | 2 +- src/returns.rs | 4 ++-- src/strings.rs | 4 ++-- src/types.rs | 10 +++++----- src/utils.rs | 4 ---- 16 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 3e451ac5eda..ad021f28a4d 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -71,14 +71,14 @@ fn is_relevant_block(block: &Block) -> bool { _ => () } } - block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) + block.expr.as_ref().map_or(false, |e| is_relevant_expr(e)) } fn is_relevant_expr(expr: &Expr) -> bool { match expr.node { ExprBlock(ref block) => is_relevant_block(block), ExprRet(Some(ref e)) | ExprParen(ref e) => - is_relevant_expr(&*e), + is_relevant_expr(e), ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 7d654b43f2f..e0b25b7283b 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -79,7 +79,7 @@ fn single_stmt_of_block(block: &Block) -> Option<&Expr> { } else { None } } else { if block.stmts.is_empty() { - if let Some(ref p) = block.expr { Some(&*p) } else { None } + if let Some(ref p) = block.expr { Some(p) } else { None } } else { None } } } diff --git a/src/consts.rs b/src/consts.rs index e54ac77b599..1a828317fc2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -222,7 +222,7 @@ fn neg_float_str(s: String) -> String { if s.starts_with('-') { s[1..].to_owned() } else { - format!("-{}", &*s) + format!("-{}", s) } } @@ -299,7 +299,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { ExprPath(_, _) => self.fetch_path(e), ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => - self.ifthenelse(&*cond, &*then, &*otherwise), + self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), ExprVec(ref vec) => self.multi(vec).map(ConstantVec), ExprTup(ref tup) => self.multi(tup).map(ConstantTuple), @@ -362,7 +362,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { if b { self.block(then) } else { - otherwise.as_ref().and_then(|ref expr| self.expr(expr)) + otherwise.as_ref().and_then(|expr| self.expr(expr)) } } else { None } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 25e967b07e5..481512abc62 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -22,7 +22,7 @@ impl LintPass for EtaPass { ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => { for arg in args { - check_closure(cx, &*arg) + check_closure(cx, arg) } }, _ => (), diff --git a/src/len_zero.rs b/src/len_zero.rs index 5eaa0256402..ca3ce51bf7c 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -102,7 +102,7 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { if method.node.name == "len" && args.len() == 1 && - has_is_empty(cx, &*args[0]) { + has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "consider replacing the len comparison with `{}{}.is_empty()`", op, snippet(cx, args[0].span, "_"))) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 9d07df4a3ed..660d68535bd 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -26,14 +26,14 @@ impl LintPass for LifetimePass { fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { if let MethodImplItem(ref sig, _) = item.node { - check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics.lifetimes, item.span); } } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { - check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics.lifetimes, item.span); } } @@ -92,7 +92,7 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, } // extract lifetimes in input argument types for arg in &func.inputs { - walk_ty(&mut input_visitor, &*arg.ty); + walk_ty(&mut input_visitor, &arg.ty); } // extract lifetimes in output type if let Return(ref ty) = func.output { diff --git a/src/loops.rs b/src/loops.rs index 5f18439eafe..ca8d3990fc5 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -95,9 +95,9 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { let PatEnum(_, Some(ref somepats)) = innerarms[0].pats[0].node, somepats.len() == 1 ], { - return Some((&*somepats[0], - &*iterargs[0], - &*innerarms[0].body)); + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); } } None diff --git a/src/matches.rs b/src/matches.rs index 002da07f50b..d1c74daf2cd 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -34,7 +34,7 @@ impl LintPass for MatchPass { // when an enum is extended, so we don't consider these cases arms[1].pats[0].node == PatWild(PatWildSingle) && // finally, we don't want any content in the second arm (unit or empty block) - is_unit_expr(&*arms[1].body) + is_unit_expr(&arms[1].body) { let body_code = snippet_block(cx, arms[0].body.span, ".."); let body_code = if let ExprBlock(_) = arms[0].body.node { @@ -46,10 +46,10 @@ impl LintPass for MatchPass { "you seem to be trying to use match for \ destructuring a single pattern. Did you mean to \ use `if let`?", - &*format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - body_code) + &format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + body_code) ); } diff --git a/src/methods.rs b/src/methods.rs index 40043be109a..07693e11d99 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -24,7 +24,7 @@ impl LintPass for MethodsPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])); + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])); if ident.node.name == "unwrap" { if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, diff --git a/src/misc.rs b/src/misc.rs index 81b03db5e14..2290af38bb5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -203,7 +203,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = - walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } + walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false } } declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 7671d63a35d..0fe52c44189 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{de_p, span_lint, snippet}; +use utils::{span_lint, snippet}; declare_lint! { pub NEEDLESS_BOOL, @@ -55,7 +55,7 @@ impl LintPass for NeedlessBool { fn fetch_bool_block(block: &Block) -> Option<bool> { if block.stmts.is_empty() { - block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) + block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) } else { None } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 2d09fcbcca9..bcbd8dad68a 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -45,7 +45,7 @@ impl LintPass for PtrArg { fn check_fn(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - if let Some(pat_ty) = cx.tcx.pat_ty_opt(&*arg.pat) { + if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty { if match_type(cx, ty, &VEC_PATH) { span_lint(cx, PTR_ARG, arg.ty.span, diff --git a/src/returns.rs b/src/returns.rs index df0b93f301e..301072f7912 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -50,7 +50,7 @@ impl ReturnPass { // a match expr, check all arms ExprMatch(_, ref arms, _) => { for arm in arms { - self.check_final_expr(cx, &*arm.body); + self.check_final_expr(cx, &arm.body); } } _ => { } @@ -76,7 +76,7 @@ impl ReturnPass { let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, let Some(ref retexpr) = block.expr, let ExprPath(_, ref path) = retexpr.node, - match_path(path, &[&*id.name.as_str()]) + match_path(path, &[&id.name.as_str()]) ], { self.emit_let_lint(cx, retexpr.span, initexpr.span); } diff --git a/src/strings.rs b/src/strings.rs index b24ea345244..d03f4d53c60 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -70,8 +70,8 @@ fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { is_exp_equal(cx, target, left), ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, - |expr| is_add(cx, &*expr, target)), - ExprParen(ref expr) => is_add(cx, &*expr, target), + |expr| is_add(cx, expr, target)), + ExprParen(ref expr) => is_add(cx, expr, target), _ => false } } diff --git a/src/types.rs b/src/types.rs index 4e9dd133ac8..7479a65b6ee 100644 --- a/src/types.rs +++ b/src/types.rs @@ -55,7 +55,7 @@ declare_lint!(pub LET_UNIT_VALUE, Warn, fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { if in_macro(cx, info) { return; } if let DeclLocal(ref local) = decl.node { - let bindtype = &cx.tcx.pat_ty(&*local.pat).sty; + let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( "this let-binding has unit value. Consider omitting `let {} =`", @@ -210,7 +210,7 @@ impl LintPass for CastPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprCast(ref ex, _) = expr.node { - let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr)); + let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr)); if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { @@ -263,14 +263,14 @@ impl LintPass for TypeComplexityPass { } fn check_struct_field(&mut self, cx: &Context, field: &StructField) { - check_type(cx, &*field.node.ty); + check_type(cx, &field.node.ty); } fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) { // StructVariant is covered by check_struct_field if let TupleVariantKind(ref args) = var.node.kind { for arg in args { - check_type(cx, &*arg.ty); + check_type(cx, &arg.ty); } } } @@ -312,7 +312,7 @@ impl LintPass for TypeComplexityPass { fn check_fndecl(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - check_type(cx, &*arg.ty); + check_type(cx, &arg.ty); } if let Return(ref ty) = decl.output { check_type(cx, ty); diff --git a/src/utils.rs b/src/utils.rs index 5e7c63e85d9..394204bedfc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{ExpnInfo, Span}; -use syntax::ptr::P; use rustc::ast_map::Node::NodeExpr; use rustc::middle::ty; use std::borrow::Cow; @@ -130,9 +129,6 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { if let NodeExpr(parent) = node { Some(parent) } else { None } ) } -/// dereference a P<T> and return a ref on the result -pub fn de_p<T>(p: &P<T>) -> &T { &*p } - #[cfg(not(feature="structured_logging"))] pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); -- cgit 1.4.1-3-g733a5 From 88047a0953d8032db9021a38e60d5c088d8318b0 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 13:26:20 +0200 Subject: collapsible_if: remove extraneous note output This was probably a debug addition. --- src/collapsible_if.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 0b6dfc19e6b..7d654b43f2f 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -48,7 +48,6 @@ fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { if e.span.expn_id != sp.expn_id { return; } - cx.sess().note(&format!("{:?} -- {:?}", e.span, sp)); span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", &format!("try\nif {} && {} {}", -- cgit 1.4.1-3-g733a5 From b13d318f48f181292e8efbdd4fe2d0353e1f51d2 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 14:41:35 +0200 Subject: all: remove unneeded deref and/or ref operations --- src/attrs.rs | 4 ++-- src/collapsible_if.rs | 2 +- src/consts.rs | 6 +++--- src/eta_reduction.rs | 2 +- src/len_zero.rs | 2 +- src/lifetimes.rs | 6 +++--- src/loops.rs | 6 +++--- src/matches.rs | 10 +++++----- src/methods.rs | 2 +- src/misc.rs | 2 +- src/needless_bool.rs | 4 ++-- src/ptr_arg.rs | 2 +- src/returns.rs | 4 ++-- src/strings.rs | 4 ++-- src/types.rs | 10 +++++----- src/utils.rs | 4 ---- 16 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 3e451ac5eda..ad021f28a4d 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -71,14 +71,14 @@ fn is_relevant_block(block: &Block) -> bool { _ => () } } - block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) + block.expr.as_ref().map_or(false, |e| is_relevant_expr(e)) } fn is_relevant_expr(expr: &Expr) -> bool { match expr.node { ExprBlock(ref block) => is_relevant_block(block), ExprRet(Some(ref e)) | ExprParen(ref e) => - is_relevant_expr(&*e), + is_relevant_expr(e), ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 7d654b43f2f..e0b25b7283b 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -79,7 +79,7 @@ fn single_stmt_of_block(block: &Block) -> Option<&Expr> { } else { None } } else { if block.stmts.is_empty() { - if let Some(ref p) = block.expr { Some(&*p) } else { None } + if let Some(ref p) = block.expr { Some(p) } else { None } } else { None } } } diff --git a/src/consts.rs b/src/consts.rs index e54ac77b599..1a828317fc2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -222,7 +222,7 @@ fn neg_float_str(s: String) -> String { if s.starts_with('-') { s[1..].to_owned() } else { - format!("-{}", &*s) + format!("-{}", s) } } @@ -299,7 +299,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { ExprPath(_, _) => self.fetch_path(e), ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => - self.ifthenelse(&*cond, &*then, &*otherwise), + self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), ExprVec(ref vec) => self.multi(vec).map(ConstantVec), ExprTup(ref tup) => self.multi(tup).map(ConstantTuple), @@ -362,7 +362,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { if b { self.block(then) } else { - otherwise.as_ref().and_then(|ref expr| self.expr(expr)) + otherwise.as_ref().and_then(|expr| self.expr(expr)) } } else { None } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 25e967b07e5..481512abc62 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -22,7 +22,7 @@ impl LintPass for EtaPass { ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => { for arg in args { - check_closure(cx, &*arg) + check_closure(cx, arg) } }, _ => (), diff --git a/src/len_zero.rs b/src/len_zero.rs index 5eaa0256402..ca3ce51bf7c 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -102,7 +102,7 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { if method.node.name == "len" && args.len() == 1 && - has_is_empty(cx, &*args[0]) { + has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "consider replacing the len comparison with `{}{}.is_empty()`", op, snippet(cx, args[0].span, "_"))) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 9d07df4a3ed..660d68535bd 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -26,14 +26,14 @@ impl LintPass for LifetimePass { fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { if let MethodImplItem(ref sig, _) = item.node { - check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics.lifetimes, item.span); } } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { - check_fn_inner(cx, &*sig.decl, Some(&sig.explicit_self), + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics.lifetimes, item.span); } } @@ -92,7 +92,7 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, } // extract lifetimes in input argument types for arg in &func.inputs { - walk_ty(&mut input_visitor, &*arg.ty); + walk_ty(&mut input_visitor, &arg.ty); } // extract lifetimes in output type if let Return(ref ty) = func.output { diff --git a/src/loops.rs b/src/loops.rs index 5f18439eafe..ca8d3990fc5 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -95,9 +95,9 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { let PatEnum(_, Some(ref somepats)) = innerarms[0].pats[0].node, somepats.len() == 1 ], { - return Some((&*somepats[0], - &*iterargs[0], - &*innerarms[0].body)); + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); } } None diff --git a/src/matches.rs b/src/matches.rs index 002da07f50b..d1c74daf2cd 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -34,7 +34,7 @@ impl LintPass for MatchPass { // when an enum is extended, so we don't consider these cases arms[1].pats[0].node == PatWild(PatWildSingle) && // finally, we don't want any content in the second arm (unit or empty block) - is_unit_expr(&*arms[1].body) + is_unit_expr(&arms[1].body) { let body_code = snippet_block(cx, arms[0].body.span, ".."); let body_code = if let ExprBlock(_) = arms[0].body.node { @@ -46,10 +46,10 @@ impl LintPass for MatchPass { "you seem to be trying to use match for \ destructuring a single pattern. Did you mean to \ use `if let`?", - &*format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - body_code) + &format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + body_code) ); } diff --git a/src/methods.rs b/src/methods.rs index 40043be109a..07693e11d99 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -24,7 +24,7 @@ impl LintPass for MethodsPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])); + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])); if ident.node.name == "unwrap" { if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, diff --git a/src/misc.rs b/src/misc.rs index 81b03db5e14..2290af38bb5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -203,7 +203,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = - walk_ptrs_ty(cx.tcx.expr_ty(&*args[0])).sty { true } else { false } + walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false } } declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 7671d63a35d..0fe52c44189 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{de_p, span_lint, snippet}; +use utils::{span_lint, snippet}; declare_lint! { pub NEEDLESS_BOOL, @@ -55,7 +55,7 @@ impl LintPass for NeedlessBool { fn fetch_bool_block(block: &Block) -> Option<bool> { if block.stmts.is_empty() { - block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) + block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) } else { None } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 2d09fcbcca9..bcbd8dad68a 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -45,7 +45,7 @@ impl LintPass for PtrArg { fn check_fn(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - if let Some(pat_ty) = cx.tcx.pat_ty_opt(&*arg.pat) { + if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty { if match_type(cx, ty, &VEC_PATH) { span_lint(cx, PTR_ARG, arg.ty.span, diff --git a/src/returns.rs b/src/returns.rs index a5779984334..889688cb0c7 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -50,7 +50,7 @@ impl ReturnPass { // a match expr, check all arms ExprMatch(_, ref arms, _) => { for arm in arms { - self.check_final_expr(cx, &*arm.body); + self.check_final_expr(cx, &arm.body); } } _ => { } @@ -76,7 +76,7 @@ impl ReturnPass { let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, let Some(ref retexpr) = block.expr, let ExprPath(_, ref path) = retexpr.node, - match_path(path, &[&*id.name.as_str()]) + match_path(path, &[&id.name.as_str()]) ], { self.emit_let_lint(cx, retexpr.span, initexpr.span); } diff --git a/src/strings.rs b/src/strings.rs index b24ea345244..d03f4d53c60 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -70,8 +70,8 @@ fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { is_exp_equal(cx, target, left), ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, - |expr| is_add(cx, &*expr, target)), - ExprParen(ref expr) => is_add(cx, &*expr, target), + |expr| is_add(cx, expr, target)), + ExprParen(ref expr) => is_add(cx, expr, target), _ => false } } diff --git a/src/types.rs b/src/types.rs index 4e9dd133ac8..7479a65b6ee 100644 --- a/src/types.rs +++ b/src/types.rs @@ -55,7 +55,7 @@ declare_lint!(pub LET_UNIT_VALUE, Warn, fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { if in_macro(cx, info) { return; } if let DeclLocal(ref local) = decl.node { - let bindtype = &cx.tcx.pat_ty(&*local.pat).sty; + let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( "this let-binding has unit value. Consider omitting `let {} =`", @@ -210,7 +210,7 @@ impl LintPass for CastPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprCast(ref ex, _) = expr.node { - let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr)); + let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr)); if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { @@ -263,14 +263,14 @@ impl LintPass for TypeComplexityPass { } fn check_struct_field(&mut self, cx: &Context, field: &StructField) { - check_type(cx, &*field.node.ty); + check_type(cx, &field.node.ty); } fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) { // StructVariant is covered by check_struct_field if let TupleVariantKind(ref args) = var.node.kind { for arg in args { - check_type(cx, &*arg.ty); + check_type(cx, &arg.ty); } } } @@ -312,7 +312,7 @@ impl LintPass for TypeComplexityPass { fn check_fndecl(cx: &Context, decl: &FnDecl) { for arg in &decl.inputs { - check_type(cx, &*arg.ty); + check_type(cx, &arg.ty); } if let Return(ref ty) = decl.output { check_type(cx, ty); diff --git a/src/utils.rs b/src/utils.rs index 6cb21148356..c71d61f81e7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{ExpnInfo, Span}; -use syntax::ptr::P; use rustc::ast_map::Node::NodeExpr; use rustc::middle::ty; use std::borrow::Cow; @@ -130,9 +129,6 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { if let NodeExpr(parent) = node { Some(parent) } else { None } ) } -/// dereference a P<T> and return a ref on the result -pub fn de_p<T>(p: &P<T>) -> &T { &*p } - #[cfg(not(feature="structured_logging"))] pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); -- cgit 1.4.1-3-g733a5 From bd22521af2313bc3e68b228077373a51bc3dda23 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 17:11:34 +0200 Subject: shadowing detection --- src/shadow.rs | 67 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index bbd146f77a5..1c09bffd9e6 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -39,12 +39,6 @@ fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { check_block(cx, block, &mut bindings); } -fn named(pat: &Pat) -> Option<Name> { - if let PatIdent(_, ident, _) = pat.node { - Some(ident.node.name) - } else { None } -} - fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { let len = bindings.len(); for stmt in &block.stmts { @@ -64,25 +58,46 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - check_pat(cx, pat, init, span, bindings); if let &Some(ref o) = init { check_expr(cx, o, bindings) } + check_pat(cx, pat, init, span, bindings); } } fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, bindings: &mut Vec<Name>) where T: Deref<Target=Expr> { //TODO: match more stuff / destructuring - named(pat).map(|name| { - if let &Some(ref o) = init { - if !in_external_macro(cx, o.span) { - check_expr(cx, o, bindings); + match pat.node { + PatIdent(_, ref ident, ref inner) => { + let name = ident.node.name; + if pat_is_binding(&cx.tcx.def_map, pat) { + if bindings.contains(&name) { + lint_shadow(cx, name, span, pat.span, init); + } + bindings.push(name); } - } - if bindings.contains(&name) { - lint_shadow(cx, name, span, pat.span, init); - } - bindings.push(name); - }); + if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } + }, + //PatEnum(Path, Option<Vec<P<Pat>>>), + //PatQPath(QSelf, Path), + //PatStruct(Path, Vec<Spanned<FieldPat>>, bool), + //PatTup(Vec<P<Pat>>), + PatBox(ref inner) => { + if let Some(ref initp) = *init { + match initp.node { + ExprBox(_, ref inner_init) => + check_pat(cx, inner, &Some(&**inner_init), span, bindings), + //TODO: ExprCall on Box::new + _ => check_pat(cx, inner, init, span, bindings), + } + } else { + check_pat(cx, inner, init, span, bindings); + } + }, + //PatRegion(P<Pat>, Mutability), + //PatRange(P<Expr>, P<Expr>), + //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), + _ => (), + } } fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: @@ -122,6 +137,8 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { check_expr(cx, place, bindings); check_expr(cx, e, bindings) } ExprBlock(ref block) | ExprLoop(ref block, _) => { check_block(cx, block, bindings) }, + //ExprCall + //ExprMethodCall ExprVec(ref v) | ExprTup(ref v) => for ref e in v { check_expr(cx, e, bindings) }, ExprIf(ref cond, ref then, ref otherwise) => { @@ -133,17 +150,19 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { check_expr(cx, cond, bindings); check_block(cx, block, bindings); }, - ExprMatch(ref init, ref arms, _) => + ExprMatch(ref init, ref arms, _) => { + check_expr(cx, init, bindings); for ref arm in arms { for ref pat in &arm.pats { + check_pat(cx, &pat, &Some(&**init), pat.span, bindings); //TODO: This is ugly, but needed to get the right type - check_pat(cx, pat, &Some(&**init), pat.span, bindings); } if let Some(ref guard) = arm.guard { check_expr(cx, guard, bindings); } - check_expr(cx, &*arm.body, bindings); - }, + check_expr(cx, &arm.body, bindings); + } + }, _ => () } } @@ -179,7 +198,8 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - path.segments.len() == 1 && path.segments[0].identifier.name == name + !path.global && path.segments.len() == 1 && + path.segments[0].identifier.name == name } fn contains_self(name: Name, expr: &Expr) -> bool { @@ -205,8 +225,7 @@ fn contains_self(name: Name, expr: &Expr) -> bool { ExprMatch(ref e, ref arms, _) => arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat| contains_pat_self(name, pat))) || contains_self(name, e), - ExprPath(_, ref path) => path.segments.len() == 1 && - path.segments[0].identifier.name == name, + ExprPath(_, ref path) => path_eq_name(name, path), _ => false } } -- cgit 1.4.1-3-g733a5 From ffed5b0b23ff8b3602a23227ecbfe7c9998d210b Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 18:26:20 +0200 Subject: loops: use a whitelist for the "x.iter() -> &x" lint (fixes #236) --- src/loops.rs | 48 +++++++++++++++++++++++++++++++----------- src/utils.rs | 3 +-- tests/compile-fail/for_loop.rs | 24 +++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index ca8d3990fc5..d12393dba68 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,9 +1,11 @@ use rustc::lint::*; use syntax::ast::*; use syntax::visit::{Visitor, walk_expr}; +use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method}; +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, walk_ptrs_ty}; +use utils::{VEC_PATH, LL_PATH}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, "for-looping over a range of indices where an iterator over items would do" } @@ -55,18 +57,17 @@ impl LintPass for LoopsPass { if args.len() == 1 { let method_name = method.node.name; // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - if method_name == "iter" { - let object = snippet(cx, args[0].span, "_"); - span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( - "it is more idiomatic to loop over `&{}` instead of `{}.iter()`", - object, object)); - } else if method_name == "iter_mut" { - let object = snippet(cx, args[0].span, "_"); - span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( - "it is more idiomatic to loop over `&mut {}` instead of `{}.iter_mut()`", - object, object)); + if method_name == "iter" || method_name == "iter_mut" { + if is_ref_iterable_type(cx, &args[0]) { + let object = snippet(cx, args[0].span, "_"); + span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( + "it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", + if method_name == "iter_mut" { "mut " } else { "" }, + object, object, method_name)); + } + } // check for looping over Iterator::next() which is not what you want - } else if method_name == "next" { + else if method_name == "next" { if match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { span_lint(cx, ITER_NEXT_LOOP, expr.span, "you are iterating over `Iterator::next()` which is an Option; \ @@ -134,3 +135,26 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { walk_expr(self, expr); } } + +/// Return true if the type of expr is one that provides IntoIterator impls +/// for &T and &mut T, such as Vec. +fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { + let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + println!("mt {:?} {:?}", e, ty); + is_array(ty) || + match_type(cx, ty, &VEC_PATH) || + match_type(cx, ty, &LL_PATH) || + match_type(cx, ty, &["std", "collections", "hash", "map", "HashMap"]) || + match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || + match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || + match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || + match_type(cx, ty, &["collections", "btree", "map", "BTreeMap"]) || + match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) +} + +fn is_array(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyArray(..) => true, + _ => false + } +} diff --git a/src/utils.rs b/src/utils.rs index 394204bedfc..d3ab2a586ea 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,8 +39,7 @@ pub fn in_external_macro(cx: &Context, span: Span) -> bool { /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| iter.map(|elem| elem.name()) - .zip(path.iter()).all(|(nm, p)| nm == p)) + cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p)) } /// check if type is struct or enum type with given def path diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index a4e3cc31a88..eb7667b7fbd 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -1,14 +1,21 @@ #![feature(plugin)] #![plugin(clippy)] +use std::collections::*; + struct Unrelated(Vec<u8>); impl Unrelated { fn next(&self) -> std::slice::Iter<u8> { self.0.iter() } + + fn iter(&self) -> std::slice::Iter<u8> { + self.0.iter() + } } #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop)] +#[allow(linkedlist)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; @@ -28,8 +35,25 @@ fn main() { for _v in &vec { } // these are fine for _v in &mut vec { } // these are fine + for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[ + let ll: LinkedList<()> = LinkedList::new(); + for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll` + let vd: VecDeque<()> = VecDeque::new(); + for _v in vd.iter() { } //~ERROR it is more idiomatic to loop over `&vd` + let bh: BinaryHeap<()> = BinaryHeap::new(); + for _v in bh.iter() { } //~ERROR it is more idiomatic to loop over `&bh` + let hm: HashMap<(), ()> = HashMap::new(); + for _v in hm.iter() { } //~ERROR it is more idiomatic to loop over `&hm` + let bt: BTreeMap<(), ()> = BTreeMap::new(); + for _v in bt.iter() { } //~ERROR it is more idiomatic to loop over `&bt` + let hs: HashSet<()> = HashSet::new(); + for _v in hs.iter() { } //~ERROR it is more idiomatic to loop over `&hs` + let bs: BTreeSet<()> = BTreeSet::new(); + for _v in bs.iter() { } //~ERROR it is more idiomatic to loop over `&bs` + for _v in vec.iter().next() { } //~ERROR you are iterating over `Iterator::next()` let u = Unrelated(vec![]); for _v in u.next() { } // no error + for _v in u.iter() { } // no error } -- cgit 1.4.1-3-g733a5 From 6fa34cca291995df922af6c822d0078db88504d5 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 25 Aug 2015 18:38:08 +0200 Subject: methods: suggest correct replacement for `to_string()` (fixes #232) --- src/methods.rs | 16 +++++++++++++--- src/utils.rs | 11 +++++++++++ tests/compile-fail/methods.rs | 5 ++++- tests/compile-fail/strings.rs | 32 ++++++++++++++++---------------- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 07693e11d99..bfe2f7984a9 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,8 +1,10 @@ use syntax::ast::*; use rustc::lint::*; use rustc::middle::ty; +use std::iter; +use std::borrow::Cow; -use utils::{span_lint, match_type, walk_ptrs_ty}; +use utils::{snippet, span_lint, match_type, walk_ptrs_ty_depth}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; #[derive(Copy,Clone)] @@ -24,7 +26,7 @@ impl LintPass for MethodsPass { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])); + let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); if ident.node.name == "unwrap" { if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, @@ -39,7 +41,15 @@ impl LintPass for MethodsPass { } else if ident.node.name == "to_string" { if obj_ty.sty == ty::TyStr { - span_lint(cx, STR_TO_STRING, expr.span, "`str.to_owned()` is faster"); + let mut arg_str = snippet(cx, args[0].span, "_"); + if ptr_depth > 1 { + arg_str = Cow::Owned(format!( + "({}{})", + iter::repeat('*').take(ptr_depth - 1).collect::<String>(), + arg_str)); + } + span_lint(cx, STR_TO_STRING, expr.span, &format!( + "`{}.to_owned()` is faster", arg_str)); } else if match_type(cx, obj_ty, &STRING_PATH) { span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \ `clone()` to make a copy"); diff --git a/src/utils.rs b/src/utils.rs index 394204bedfc..1b01d558094 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -158,6 +158,17 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { } } +/// return the base type for references and raw pointers, and count reference depth +pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { + fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { + match ty.sty { + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), + _ => (ty, depth) + } + } + inner(ty, 0) +} + /// Produce a nested chain of if-lets and ifs from the patterns: /// /// if_let_chain! { diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 91d3b72de84..811c44ef85c 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -10,6 +10,9 @@ fn main() { let res: Result<i32, ()> = Ok(0); let _ = res.unwrap(); //~ERROR used unwrap() on a Result - let string = "str".to_string(); //~ERROR `str.to_owned()` is faster + let _ = "str".to_string(); //~ERROR `"str".to_owned()` is faster + + let v = &"str"; + let string = v.to_string(); //~ERROR `(*v).to_owned()` is faster let _again = string.to_string(); //~ERROR `String.to_string()` is a no-op } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 680ebb73dea..7e21294a3d1 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -4,29 +4,29 @@ #[deny(string_add)] #[allow(string_add_assign)] fn add_only() { // ignores assignment distinction - let mut x = "".to_owned(); + let mut x = "".to_owned(); for _ in (1..3) { x = x + "."; //~ERROR you added something to a string. } - + let y = "".to_owned(); let z = y + "..."; //~ERROR you added something to a string. - + assert_eq!(&x, &z); } #[deny(string_add_assign)] fn add_assign_only() { - let mut x = "".to_owned(); + let mut x = "".to_owned(); for _ in (1..3) { x = x + "."; //~ERROR you assigned the result of adding something to this string. } - + let y = "".to_owned(); let z = y + "..."; - + assert_eq!(&x, &z); } @@ -37,20 +37,20 @@ fn both() { for _ in (1..3) { x = x + "."; //~ERROR you assigned the result of adding something to this string. } - + let y = "".to_owned(); let z = y + "..."; //~ERROR you added something to a string. - + assert_eq!(&x, &z); } fn main() { - add_only(); - add_assign_only(); - both(); - - // the add is only caught for String - let mut x = 1; - x = x + 1; - assert_eq!(2, x); + add_only(); + add_assign_only(); + both(); + + // the add is only caught for String + let mut x = 1; + x = x + 1; + assert_eq!(2, x); } -- cgit 1.4.1-3-g733a5 From 974ceefc1e18221b1c01961a34d8866750d7690c Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 21 Aug 2015 17:11:34 +0200 Subject: shadowing detection --- src/shadow.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shadow.rs b/src/shadow.rs index 1c09bffd9e6..c4f636ae112 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -4,6 +4,8 @@ use syntax::codemap::Span; use syntax::visit::FnKind; use rustc::lint::{Context, LintArray, LintPass}; +use rustc::middle::def::Def::{DefVariant, DefStruct}; + use utils::{in_external_macro, snippet, span_lint}; declare_lint!(pub SHADOW_SAME, Allow, -- cgit 1.4.1-3-g733a5 From 9012d8f1975829a1440fde6f6fd6158a239595c4 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 25 Aug 2015 20:11:03 +0200 Subject: fixed false positives on structs/enum variants --- src/shadow.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shadow.rs b/src/shadow.rs index c4f636ae112..2c16d9d78f4 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -65,13 +65,20 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { } } +fn is_binding(cx: &Context, pat: &Pat) -> bool { + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefVariant(..)) | Some(DefStruct(..)) => false, + _ => true + } +} + fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, bindings: &mut Vec<Name>) where T: Deref<Target=Expr> { //TODO: match more stuff / destructuring match pat.node { PatIdent(_, ref ident, ref inner) => { let name = ident.node.name; - if pat_is_binding(&cx.tcx.def_map, pat) { + if is_binding(cx, pat) { if bindings.contains(&name) { lint_shadow(cx, name, span, pat.span, init); } -- cgit 1.4.1-3-g733a5 From 92db00863f8940a2a53db159c8c730d881fd902c Mon Sep 17 00:00:00 2001 From: Frank Denis <github@pureftpd.org> Date: Tue, 25 Aug 2015 23:21:38 +0200 Subject: Changes for rust-nightly after #27856 --- src/len_zero.rs | 1 + src/misc.rs | 2 +- src/utils.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index ca3ce51bf7c..068568cb392 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -2,6 +2,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned}; +use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; use utils::{span_lint, walk_ptrs_ty, snippet}; diff --git a/src/misc.rs b/src/misc.rs index 2290af38bb5..b4385e298f7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -22,7 +22,7 @@ impl LintPass for TopLevelRefPass { } fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - if let FnKind::FkFnBlock = k { + if let FnKind::FkClosure = k { // Does not apply to closures return } diff --git a/src/utils.rs b/src/utils.rs index e4f3cc078de..ca704ebfd58 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,6 +2,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::{ExpnInfo, Span}; use rustc::ast_map::Node::NodeExpr; +use rustc::middle::def_id::DefId; use rustc::middle::ty; use std::borrow::Cow; -- cgit 1.4.1-3-g733a5 From 51a211503d5e62e7abf71a7824871ff5ef81dcab Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 25 Aug 2015 23:48:22 +0200 Subject: correct scoping for shadow lints --- src/shadow.rs | 5 ++++- tests/compile-fail/shadow.rs | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/shadow.rs b/src/shadow.rs index 2c16d9d78f4..fb840fd3258 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -81,8 +81,9 @@ fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, if is_binding(cx, pat) { if bindings.contains(&name) { lint_shadow(cx, name, span, pat.span, init); + } else { + bindings.push(name); } - bindings.push(name); } if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } }, @@ -161,6 +162,7 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { }, ExprMatch(ref init, ref arms, _) => { check_expr(cx, init, bindings); + let len = bindings.len(); for ref arm in arms { for ref pat in &arm.pats { check_pat(cx, &pat, &Some(&**init), pat.span, bindings); @@ -170,6 +172,7 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { check_expr(cx, guard, bindings); } check_expr(cx, &arm.body, bindings); + bindings.truncate(len); } }, _ => () diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index e3213717213..7098cb38877 100644 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -19,4 +19,12 @@ fn main() { let x = first(x); //~ERROR: x is shadowed by first(x) which reuses let y = 1; let x = y; //~ERROR: x is shadowed by y in this declaration + + let o = Some(1u8); + + if let Some(p) = o { assert_eq!(1, p); } + match o { + Some(p) => p, // no error, because the p above is in its own scope + None => 0, + }; } -- cgit 1.4.1-3-g733a5 From 6984d2bc09b790e762ca4e82f9070dc0fe65c515 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 26 Aug 2015 14:26:43 +0200 Subject: added helpful links to lints that have wiki entries --- src/approx_const.rs | 16 +++++++---- src/attrs.rs | 8 ++++-- src/bit_mask.rs | 68 +++++++++++++++++++++++++++++--------------- src/misc.rs | 14 +++++---- src/returns.rs | 2 +- src/shadow.rs | 26 +++++++++++------ src/strings.rs | 17 ++++++----- src/types.rs | 82 +++++++++++++++++++++++++++++++++-------------------- 8 files changed, 150 insertions(+), 83 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 3e0ba4eb669..0ec2f94cab8 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -3,7 +3,7 @@ use syntax::ast::*; use syntax::codemap::Span; use std::f64::consts as f64; -use utils::span_lint; +use utils::span_help_and_lint; declare_lint! { pub APPROX_CONSTANT, @@ -40,7 +40,8 @@ fn check_lit(cx: &Context, lit: &Lit, span: Span) { match lit.node { LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), - LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), + LitFloatUnsuffixed(ref str) => + check_known_consts(cx, span, str, "f{32, 64}"), _ => () } } @@ -49,13 +50,18 @@ fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { if let Ok(value) = str.parse::<f64>() { for &(constant, name) in KNOWN_CONSTS { if within_epsilon(constant, value) { - span_lint(cx, APPROX_CONSTANT, span, &format!( - "approximate value of `{}::{}` found. Consider using it directly", module, &name)); + span_help_and_lint(cx, APPROX_CONSTANT, span, &format!( + "approximate value of `{}::{}` found. \ + Consider using it directly", module, &name), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#approx_constant"); } } } } fn within_epsilon(target: f64, value: f64) -> bool { - f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR + f64::abs(value - target) < f64::abs(if target > value { + target + } else { value }) / EPSILON_DIVISOR } diff --git a/src/attrs.rs b/src/attrs.rs index ad021f28a4d..a9ee9402e28 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::ExpnInfo; -use utils::{in_macro, match_path, span_lint}; +use utils::{in_macro, match_path, span_help_and_lint}; declare_lint! { pub INLINE_ALWAYS, Warn, "`#[inline(always)]` is a bad idea in most cases" } @@ -98,10 +98,12 @@ fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, if values.len() != 1 || inline != &"inline" { continue; } if let MetaWord(ref always) = values[0].node { if always != &"always" { continue; } - span_lint(cx, INLINE_ALWAYS, attr.span, &format!( + span_help_and_lint(cx, INLINE_ALWAYS, attr.span, &format!( "you have declared `#[inline(always)]` on `{}`. This \ is usually a bad idea. Are you sure?", - ident.name)); + ident.name), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#inline_always"); } } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 6537fcf4c1a..6817dd3d97b 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -5,7 +5,7 @@ use syntax::ast::*; use syntax::ast_util::is_comparison_binop; use syntax::codemap::Span; -use utils::span_lint; +use utils::span_help_and_lint; declare_lint! { pub BAD_BIT_MASK, @@ -100,38 +100,50 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, BiEq | BiNe => match bit_op { BiBitAnd => if mask_value & cmp_value != mask_value { if cmp_value != 0 { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } } else { if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); + span_help_and_lint(cx, BAD_BIT_MASK, *span, + "&-masking with zero", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } }, BiBitOr => if mask_value | cmp_value != cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); }, _ => () }, BiLt | BiGe => match bit_op { BiBitAnd => if mask_value < cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } else { if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); + span_help_and_lint(cx, BAD_BIT_MASK, *span, + "&-masking with zero", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } }, BiBitOr => if mask_value >= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } else { check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); }, @@ -141,19 +153,25 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, }, BiLe | BiGt => match bit_op { BiBitAnd => if mask_value <= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } else { if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, - &format!("&-masking with zero")); + span_help_and_lint(cx, BAD_BIT_MASK, *span, + "&-masking with zero", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } }, BiBitOr => if mask_value > cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( + span_help_and_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, cmp_value)); + mask_value, cmp_value), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#bad_bit_mask"); } else { check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); }, @@ -167,17 +185,21 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { if c.is_power_of_two() && m < c { - span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + span_help_and_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, m, c)); + op, m, c), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#ineffective_bit_mask"); } } fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { if (c + 1).is_power_of_two() && m <= c { - span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + span_help_and_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, m, c)); + op, m, c), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#ineffective_bit_mask"); } } diff --git a/src/misc.rs b/src/misc.rs index 2290af38bb5..d3d99e93b0b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -6,7 +6,7 @@ use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; use rustc::middle::ty; -use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; +use utils::{match_path, snippet, span_lint, span_help_and_lint, walk_ptrs_ty}; use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, @@ -65,8 +65,10 @@ impl LintPass for CmpNan { fn check_nan(cx: &Context, path: &Path, span: Span) { path.segments.last().map(|seg| if seg.identifier.name == "NAN" { - span_lint(cx, CMP_NAN, span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); + span_help_and_lint(cx, CMP_NAN, span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cmp_nan"); }); } @@ -124,9 +126,11 @@ impl LintPass for Precedence { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - span_lint(cx, PRECEDENCE, expr.span, + span_help_and_lint(cx, PRECEDENCE, expr.span, "operator precedence can trip the unwary. Consider adding parentheses \ - to the subexpression"); + to the subexpression", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#precedence"); } } } diff --git a/src/returns.rs b/src/returns.rs index 889688cb0c7..e4b14c22115 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -60,7 +60,7 @@ impl ReturnPass { fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using `{}` \ - without the trailing semicolon", + without the return and trailing semicolon", snippet(cx, spans.1, ".."))) } diff --git a/src/shadow.rs b/src/shadow.rs index fb840fd3258..717c06a4c14 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -6,7 +6,7 @@ use syntax::visit::FnKind; use rustc::lint::{Context, LintArray, LintPass}; use rustc::middle::def::Def::{DefVariant, DefStruct}; -use utils::{in_external_macro, snippet, span_lint}; +use utils::{in_external_macro, snippet, span_help_and_lint}; declare_lint!(pub SHADOW_SAME, Allow, "rebinding a name to itself, e.g. `let mut x = &mut x`"); @@ -114,26 +114,34 @@ fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: &Option<T>) where T: Deref<Target=Expr> { if let &Some(ref expr) = init { if is_self_shadow(name, expr) { - span_lint(cx, SHADOW_SAME, span, &format!( + span_help_and_lint(cx, SHADOW_SAME, span, &format!( "{} is shadowed by itself in {}", snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); + snippet(cx, expr.span, "..")), + "for further information see \ + https://github.com/Manishearth/rust-clippy/wiki#shadow_same"); } else { if contains_self(name, expr) { - span_lint(cx, SHADOW_REUSE, span, &format!( + span_help_and_lint(cx, SHADOW_REUSE, span, &format!( "{} is shadowed by {} which reuses the original value", snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); + snippet(cx, expr.span, "..")), + "for further information see https://\ + github.com/Manishearth/rust-clippy/wiki#shadow_reuse"); } else { - span_lint(cx, SHADOW_UNRELATED, span, &format!( + span_help_and_lint(cx, SHADOW_UNRELATED, span, &format!( "{} is shadowed by {} in this declaration", snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); + snippet(cx, expr.span, "..")), + "for further information see https://github.com\ + /Manishearth/rust-clippy/wiki#shadow_unrelated"); } } } else { - span_lint(cx, SHADOW_UNRELATED, span, &format!( - "{} is shadowed in this declaration", snippet(cx, lspan, "_"))); + span_help_and_lint(cx, SHADOW_UNRELATED, span, &format!( + "{} is shadowed in this declaration", snippet(cx, lspan, "_")), + "for further information see \ + https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated"); } } diff --git a/src/strings.rs b/src/strings.rs index d03f4d53c60..8e10cfaa72c 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -8,7 +8,7 @@ use syntax::ast::*; use syntax::codemap::Spanned; use eq_op::is_exp_equal; -use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, span_help_and_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; declare_lint! { @@ -45,16 +45,19 @@ impl LintPass for StringAdd { } } } - //TODO check for duplicates - span_lint(cx, STRING_ADD, e.span, - "you added something to a string. \ - Consider using `String::push_str()` instead") + span_help_and_lint(cx, STRING_ADD, e.span, + "you added something to a string. \ + Consider using `String::push_str()` instead", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#string_add") } } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(cx, src, target) { - span_lint(cx, STRING_ADD_ASSIGN, e.span, + span_help_and_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ - Consider using `String::push_str()` instead") + Consider using `String::push_str()` instead", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#string_add_assign") } } } diff --git a/src/types.rs b/src/types.rs index 7479a65b6ee..700666d0542 100644 --- a/src/types.rs +++ b/src/types.rs @@ -32,14 +32,17 @@ impl LintPass for TypePass { span_help_and_lint( cx, BOX_VEC, ast_ty.span, "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation"); + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation. \ + for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#box_vec"); } } else if match_type(cx, ty, &LL_PATH) { span_help_and_lint( cx, LINKEDLIST, ast_ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a RingBuf might work"); + "a RingBuf might work; for further information see \ + https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask"); } } } @@ -141,13 +144,15 @@ fn span_precision_loss_lint(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast let from_nbits_str = if arch_dependent {"64".to_owned()} else if is_isize_or_usize(cast_from) {"32 or 64".to_owned()} else {int_ty_to_nbits(cast_from).to_string()}; - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("casting {0} to {1} causes a loss of precision {2}\ - ({0} is {3} bits wide, but {1}'s mantissa is only {4} bits wide)", - cast_from, if cast_to_f64 {"f64"} else {"f32"}, - if arch_dependent {arch_dependent_str} else {""}, - from_nbits_str, - mantissa_nbits)); + span_help_and_lint(cx, CAST_PRECISION_LOSS, expr.span, + &format!("casting {0} to {1} causes a loss of precision {2}\ + ({0} is {3} bits wide, but {1}'s mantissa is only {4} bits wide)", + cast_from, if cast_to_f64 {"f64"} else {"f32"}, + if arch_dependent {arch_dependent_str} else {""}, + from_nbits_str, + mantissa_nbits), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_precision_loss"); } enum ArchSuffix { @@ -181,22 +186,26 @@ fn check_truncation_and_wrapping(cx: &Context, expr: &Expr, cast_from: &ty::TyS, ), }; if span_truncation { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value{}", - cast_from, cast_to, - match suffix_truncation { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "" })); + span_help_and_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value{}", + cast_from, cast_to, + match suffix_truncation { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "" }), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_possible_truncation"); } if span_wrap { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value{}", - cast_from, cast_to, - match suffix_wrap { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "" })); + span_help_and_lint(cx, CAST_POSSIBLE_WRAP, expr.span, + &format!("casting {} to {} may wrap around the value{}", + cast_from, cast_to, + match suffix_wrap { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "" }), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_possible_wrap"); } } @@ -221,24 +230,37 @@ impl LintPass for CastPass { } }, (false, true) => { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value", cast_from, cast_to)); + span_help_and_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, + &format!("casting {} to {} may truncate the value", + cast_from, cast_to), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_possible_truncation"); if !cast_to.is_signed() { - span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + span_help_and_lint(cx, CAST_SIGN_LOSS, expr.span, + &format!("casting {} to {} may lose the sign of the value", + cast_from, cast_to), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_sign_loss"); } }, (true, true) => { if cast_from.is_signed() && !cast_to.is_signed() { - span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + span_help_and_lint(cx, CAST_SIGN_LOSS, expr.span, + &format!("casting {} to {} may lose the sign of the value", + cast_from, cast_to), + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_sign_loss"); } check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { if let (&ty::TyFloat(ast::TyF64), &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may truncate the value"); + span_help_and_lint(cx, CAST_POSSIBLE_TRUNCATION, + expr.span, + "casting f64 to f32 may truncate the value", + "for further information see https://github.com/\ + Manishearth/rust-clippy/wiki#cast_possible_truncation"); } } } -- cgit 1.4.1-3-g733a5 From 9461a480bd2c48bad8f50a3835d411da30c8b45a Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 26 Aug 2015 16:04:50 +0200 Subject: Added automatic links to wiki for all lints. --- README.md | 100 +++++++++++++++++++++++++-------------------------- util/update_lints.py | 8 +++-- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 66411e432c9..012b81c1d19 100644 --- a/README.md +++ b/README.md @@ -6,56 +6,56 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints There are 48 lints included in this crate: -name | default | meaning --------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -approx_constant | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -bad_bit_mask | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -box_vec | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -cast_possible_truncation | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -cast_possible_wrap | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` -cast_precision_loss | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -cast_sign_loss | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -cmp_nan | deny | comparisons to NAN (which will always return false, which is probably not intended) -cmp_owned | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -collapsible_if | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -eq_op | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -explicit_iter_loop | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -float_cmp | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -identity_op | warn | using identity operations, e.g. `x + 0` or `y / 1` -ineffective_bit_mask | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -inline_always | warn | `#[inline(always)]` is a bad idea in most cases -iter_next_loop | warn | for-looping over `_.next()` which is probably not intended -len_without_is_empty | warn | traits and impls that have `.len()` but not `.is_empty()` -len_zero | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -let_and_return | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function -let_unit_value | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -linkedlist | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf -match_ref_pats | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead -modulo_one | warn | taking a number modulo 1, which always returns 0 -mut_mut | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -needless_bool | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -needless_lifetimes | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -needless_range_loop | warn | for-looping over a range of indices where an iterator over items would do -needless_return | warn | using a return statement like `return expr;` where an expression would suffice -non_ascii_literal | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -option_unwrap_used | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -precedence | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` -ptr_arg | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -range_step_by_zero | warn | using Range::step_by(0), which produces an infinite iterator -redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled -shadow_reuse | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -shadow_same | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -shadow_unrelated | warn | The name is re-bound without even using the original value -single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` -string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -string_to_string | warn | calling `String.to_string()` which is a no-op -toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) -type_complexity | warn | usage of very complex types; recommends factoring out parts into `type` definitions -unit_cmp | warn | comparing unit values (which is always `true` or `false`, respectively) -zero_width_space | deny | using a zero-width space in a string literal, which is confusing +name | default | meaning +-----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) +[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` +[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead +[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | warn | The name is re-bound without even using the original value +[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` +[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/util/update_lints.py b/util/update_lints.py index 940899d4ebb..8c00f1b4f13 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -16,6 +16,7 @@ declare_lint_re = re.compile(r''' nl_escape_re = re.compile(r'\\\n\s*') +wiki_link = 'https://github.com/Manishearth/rust-clippy/wiki' def collect(lints, fn): """Collect all lints from a file. @@ -33,8 +34,11 @@ def collect(lints, fn): desc.replace('\\"', '"'))) -def gen_table(lints): +def gen_table(lints, link=None): """Write lint table in Markdown format.""" + if link: + lints = [(p, '[%s](%s#%s)' % (l, link, l), lvl, d) + for (p, l, lvl, d) in lints] # first and third column widths w_name = max(len(l[1]) for l in lints) w_desc = max(len(l[3]) for l in lints) @@ -110,7 +114,7 @@ def main(print_only=False, check=False): # replace table in README.md changed = replace_region('README.md', r'^name +\|', '^$', - lambda: gen_table(lints), + lambda: gen_table(lints, link=wiki_link), write_back=not check) changed |= replace_region('README.md', -- cgit 1.4.1-3-g733a5 From bb552dc96fc46ff0b33bc48f7c3c48f3acf2a306 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 26 Aug 2015 17:09:37 +0200 Subject: eta_reduction: fix false positive for unsafe fns (fixes #243) --- src/eta_reduction.rs | 22 ++++++++++++++++------ tests/compile-fail/eta.rs | 7 ++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 481512abc62..da2149f0539 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::print::pprust::expr_to_string; +use rustc::middle::ty; -use utils::span_lint; +use utils::{snippet, span_lint}; #[allow(missing_copy_implementations)] @@ -47,7 +47,17 @@ fn check_closure(cx: &Context, expr: &Expr) { // is no way the closure is the same as the function return; } - if args.iter().any(|arg| is_adjusted(cx, arg)) { return; } + if args.iter().any(|arg| is_adjusted(cx, arg)) { + // Are the arguments type-adjusted? Then we need the closure + return; + } + let fn_ty = cx.tcx.expr_ty(caller); + if let ty::TyBareFn(_, fn_ty) = fn_ty.sty { + // Is it an unsafe function? They don't implement the closure traits + if fn_ty.unsafety == Unsafety::Unsafe { + return; + } + } for (ref a1, ref a2) in decl.inputs.iter().zip(args) { if let PatIdent(_, ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? @@ -67,9 +77,9 @@ fn check_closure(cx: &Context, expr: &Expr) { return } } - span_lint(cx, REDUNDANT_CLOSURE, expr.span, - &format!("redundant closure found. Consider using `{}` in its place", - expr_to_string(caller))[..]) + span_lint(cx, REDUNDANT_CLOSURE, expr.span, &format!( + "redundant closure found. Consider using `{}` in its place", + snippet(cx, caller.span, ".."))); } } } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index bf6ecd79617..d53ea4e97d7 100755 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -9,9 +9,12 @@ fn main() { meta(|a| foo(a)); //~^ ERROR redundant closure found. Consider using `foo` in its place let c = Some(1u8).map(|a| {1+2; foo}(a)); - //~^ ERROR redundant closure found. Consider using `{ 1 + 2; foo }` in its place + //~^ ERROR redundant closure found. Consider using `{1+2; foo}` in its place let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted + unsafe { + Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn + } } fn meta<F>(f: F) where F: Fn(u8) { @@ -32,3 +35,5 @@ where F: Fn(&X, &X) -> bool { } fn below(x: &u8, y: &u8) -> bool { x < y } + +unsafe fn unsafe_fn(_: u8) { } -- cgit 1.4.1-3-g733a5 From 9ebcd0bf29b00226d83a1bb8b48ee9872cb67848 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 27 Aug 2015 04:01:35 +0530 Subject: More macro checks --- src/identity_op.rs | 3 ++- src/matches.rs | 4 +++- src/returns.rs | 4 +++- src/types.rs | 11 ++++------- src/utils.rs | 11 ++++++++++- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/identity_op.rs b/src/identity_op.rs index cd7d6351c80..bcdd527e407 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -4,7 +4,7 @@ use syntax::codemap::Span; use consts::{constant, is_negative}; use consts::Constant::ConstantInt; -use utils::{span_lint, snippet}; +use utils::{span_lint, snippet, in_external_macro}; declare_lint! { pub IDENTITY_OP, Warn, "using identity operations, e.g. `x + 0` or `y / 1`" } @@ -53,6 +53,7 @@ fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { 1 => !is_negative(ty) && v == 1, _ => unreachable!(), } { + if in_external_macro(cx, e.span) {return;} span_lint(cx, IDENTITY_OP, span, &format!( "the operation is ineffective. Consider reducing it to `{}`", snippet(cx, arg, ".."))); diff --git a/src/matches.rs b/src/matches.rs index d1c74daf2cd..1afb61e9b9e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -3,7 +3,8 @@ use syntax::ast; use syntax::ast::*; use std::borrow::Cow; -use utils::{snippet, snippet_block, span_lint, span_help_and_lint}; +use utils::{snippet, snippet_block}; +use utils::{span_lint, span_help_and_lint, in_external_macro}; declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ @@ -36,6 +37,7 @@ impl LintPass for MatchPass { // finally, we don't want any content in the second arm (unit or empty block) is_unit_expr(&arms[1].body) { + if in_external_macro(cx, expr.span) {return;} let body_code = snippet_block(cx, arms[0].body.span, ".."); let body_code = if let ExprBlock(_) = arms[0].body.node { body_code diff --git a/src/returns.rs b/src/returns.rs index e4b14c22115..29749b29435 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -3,7 +3,7 @@ use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_lint, snippet, match_path}; +use utils::{span_lint, snippet, match_path, in_external_macro}; declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); @@ -58,6 +58,7 @@ impl ReturnPass { } fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { + if in_external_macro(cx, spans.1) {return;} span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using `{}` \ without the return and trailing semicolon", @@ -84,6 +85,7 @@ impl ReturnPass { } fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) { + if in_external_macro(cx, note_span) {return;} span_lint(cx, LET_AND_RETURN, lint_span, "returning the result of a let binding. \ Consider returning the expression directly."); diff --git a/src/types.rs b/src/types.rs index 700666d0542..12f31ae89dd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,9 +5,8 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; use syntax::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; -use syntax::codemap::ExpnInfo; -use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types @@ -55,11 +54,11 @@ declare_lint!(pub LET_UNIT_VALUE, Warn, "creating a let binding to a value of unit type, which usually can't be used afterwards"); -fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } +fn check_let_unit(cx: &Context, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { + if in_external_macro(cx, decl.span) { return; } span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( "this let-binding has unit value. Consider omitting `let {} =`", snippet(cx, local.pat.span, ".."))); @@ -73,9 +72,7 @@ impl LintPass for LetPass { } fn check_decl(&mut self, cx: &Context, decl: &Decl) { - cx.sess().codemap().with_expn_info( - decl.span.expn_id, - |info| check_let_unit(cx, decl, info)); + check_let_unit(cx, decl) } } diff --git a/src/utils.rs b/src/utils.rs index b7bb14bd2f0..ece1eee9050 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::codemap::{ExpnInfo, Span}; +use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use rustc::ast_map::Node::NodeExpr; use rustc::middle::def_id::DefId; use rustc::middle::ty; @@ -18,6 +18,14 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "Linke pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { + if info.callee.format == ExpnFormat::CompilerExpansion { + if info.callee.name == "closure expansion" { + return false; + } + } else if info.callee.format == ExpnFormat::MacroAttribute { + // these are all plugins + return true; + } // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion @@ -31,6 +39,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { } /// invokes in_macro with the expansion info of the given span +/// slightly heavy, try to use this after other checks have already happened pub fn in_external_macro(cx: &Context, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) -- cgit 1.4.1-3-g733a5 From 5159e034a67587bfecfd3368a9cb9691ab20e440 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 27 Aug 2015 04:40:01 +0530 Subject: appease the dogfood gods --- src/consts.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/consts.rs b/src/consts.rs index 1a828317fc2..29b96146db2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,3 +1,5 @@ +#![allow(cast_possible_truncation)] + use rustc::lint::Context; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; -- cgit 1.4.1-3-g733a5 From 621818e6061e693c57a494742ba4094029a855c0 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 28 Aug 2015 14:35:20 +0200 Subject: rustup, the ExpnInfo stuff changed --- src/utils.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 69f5e22c48f..b6fae89fc31 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,13 +18,17 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "Linke pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { - if info.callee.format == ExpnFormat::CompilerExpansion { - if info.callee.name == "closure expansion" { - return false; - } - } else if info.callee.format == ExpnFormat::MacroAttribute { - // these are all plugins - return true; + match info.callee.format { + ExpnFormat::CompilerExpansion(..) => { + if info.callee.name() == "closure expansion" { + return false; + } + }, + ExpnFormat::MacroAttribute(..) => { + // these are all plugins + return true; + }, + _ => (), } // no span for the callee = external macro info.callee.span.map_or(true, |span| { -- cgit 1.4.1-3-g733a5 From 6461fb3308ee52a04b4856896909fb6974ae4a81 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 30 Aug 2015 09:57:52 +0200 Subject: lifetimes lint: take "where" clauses into account (fixes #253) If a where clause is present and has lifetimes mentioned, just bail out. --- src/lifetimes.rs | 30 ++++++++++++++++++++++++------ tests/compile-fail/lifetimes.rs | 6 ++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 660d68535bd..bff0db14f7b 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -20,21 +20,21 @@ impl LintPass for LifetimePass { fn check_item(&mut self, cx: &Context, item: &Item) { if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { - check_fn_inner(cx, decl, None, &generics.lifetimes, item.span); + check_fn_inner(cx, decl, None, &generics, item.span); } } fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { if let MethodImplItem(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), - &sig.generics.lifetimes, item.span); + &sig.generics, item.span); } } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), - &sig.generics.lifetimes, item.span); + &sig.generics, item.span); } } } @@ -49,11 +49,11 @@ enum RefLt { use self::RefLt::*; fn check_fn_inner(cx: &Context, decl: &FnDecl, slf: Option<&ExplicitSelf>, - named_lts: &[LifetimeDef], span: Span) { - if in_external_macro(cx, span) { + generics: &Generics, span: Span) { + if in_external_macro(cx, span) || has_where_lifetimes(&generics.where_clause) { return; } - if could_use_elision(decl, slf, named_lts) { + if could_use_elision(decl, slf, &generics.lifetimes) { span_lint(cx, NEEDLESS_LIFETIMES, span, "explicit lifetimes given in parameter types where they could be elided"); } @@ -182,3 +182,21 @@ impl<'v> Visitor<'v> for RefVisitor { // for lifetime bounds; the default impl calls visit_lifetime_ref fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { } } + +/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to +/// reason about elision. +fn has_where_lifetimes(where_clause: &WhereClause) -> bool { + let mut where_visitor = RefVisitor(Vec::new()); + for predicate in &where_clause.predicates { + match *predicate { + WherePredicate::RegionPredicate(..) => return true, + WherePredicate::BoundPredicate(ref pred) => { + walk_ty(&mut where_visitor, &pred.bounded_ty); + } + WherePredicate::EqPredicate(ref pred) => { + walk_ty(&mut where_visitor, &pred.ty); + } + } + } + !where_visitor.into_vec().is_empty() +} diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index a5597e6478f..ae115efec04 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -31,6 +31,10 @@ fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // n fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } //~^ERROR explicit lifetimes given +// where clause, but without lifetimes +fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } +//~^ERROR explicit lifetimes given + type Ref<'r> = &'r u8; fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } // no error, same lifetime on two params @@ -40,6 +44,8 @@ fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounded lifetime +fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) where 'b: 'a { } // no error, bounded lifetime + struct X { x: u8, } -- cgit 1.4.1-3-g733a5 From b72ef5a1731490778cb8ad7fb42e170a4e46ae13 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 29 Aug 2015 11:41:06 +0200 Subject: new lint: loop-match-break, which could be while-let (fixes #118) --- README.md | 3 +- src/lib.rs | 1 + src/loops.rs | 65 ++++++++++++++++++++++++++++++++++++++-- src/matches.rs | 13 ++------ src/utils.rs | 10 +++++++ tests/compile-fail/while_loop.rs | 52 ++++++++++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 15 deletions(-) create mode 100755 tests/compile-fail/while_loop.rs diff --git a/README.md b/README.md index 478bb25272f..92a03b31530 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 49 lints included in this crate: +There are 50 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -56,6 +56,7 @@ name [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/lib.rs b/src/lib.rs index 32fc953d1c3..d69d352abc6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, + loops::WHILE_LET_LOOP, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::OPTION_UNWRAP_USED, diff --git a/src/loops.rs b/src/loops.rs index d12393dba68..eba706ed7e1 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -4,7 +4,8 @@ use syntax::visit::{Visitor, walk_expr}; use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, walk_ptrs_ty}; +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, walk_ptrs_ty, + in_external_macro, expr_block, span_help_and_lint}; use utils::{VEC_PATH, LL_PATH}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, @@ -16,12 +17,16 @@ declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, declare_lint!{ pub ITER_NEXT_LOOP, Warn, "for-looping over `_.next()` which is probably not intended" } +declare_lint!{ pub WHILE_LET_LOOP, Warn, + "`loop { if let { ... } else break }` can be written as a `while let` loop" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP) + lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, + WHILE_LET_LOOP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -36,7 +41,8 @@ impl LintPass for LoopsPass { walk_expr(&mut visitor, body); // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let indexed = visitor.indexed.into_iter().next().expect("Len was nonzero, but no contents found"); + let indexed = visitor.indexed.into_iter().next().expect( + "Len was nonzero, but no contents found"); if visitor.nonindex { span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( "the loop variable `{}` is used to index `{}`. Consider using \ @@ -77,6 +83,34 @@ impl LintPass for LoopsPass { } } } + // check for `loop { if let {} else break }` that could be `while let` + // (also matches explicit "match" instead of "if let") + if let ExprLoop(ref block, _) = expr.node { + // extract a single expression + if let Some(inner) = extract_single_expr(block) { + if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { + // ensure "if let" compatible match structure + match *source { + MatchSource::Normal | MatchSource::IfLetDesugar{..} => if + arms.len() == 2 && + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + // finally, check for "break" in the second clause + is_break_expr(&arms[1].body) + { + if in_external_macro(cx, expr.span) { return; } + span_help_and_lint(cx, WHILE_LET_LOOP, expr.span, + "this loop could be written as a `while let` loop", + &format!("try\nwhile let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, matchexpr.span, ".."), + expr_block(cx, &arms[0].body, ".."))); + }, + _ => () + } + } + } + } } } @@ -158,3 +192,28 @@ fn is_array(ty: ty::Ty) -> bool { _ => false } } + +/// If block consists of a single expression (with or without semicolon), return it. +fn extract_single_expr(block: &Block) -> Option<&Expr> { + match (&block.stmts.len(), &block.expr) { + (&1, &None) => match block.stmts[0].node { + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => Some(expr), + _ => None, + }, + (&0, &Some(ref expr)) => Some(expr), + _ => None + } +} + +/// Return true if expr contains a single break expr (maybe within a block). +fn is_break_expr(expr: &Expr) -> bool { + match expr.node { + ExprBreak(None) => true, + ExprBlock(ref b) => match extract_single_expr(b) { + Some(ref subexpr) => is_break_expr(subexpr), + None => false, + }, + _ => false, + } +} diff --git a/src/matches.rs b/src/matches.rs index 1afb61e9b9e..3d04c9210ce 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,10 +1,8 @@ use rustc::lint::*; use syntax::ast; use syntax::ast::*; -use std::borrow::Cow; -use utils::{snippet, snippet_block}; -use utils::{span_lint, span_help_and_lint, in_external_macro}; +use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ @@ -38,12 +36,6 @@ impl LintPass for MatchPass { is_unit_expr(&arms[1].body) { if in_external_macro(cx, expr.span) {return;} - let body_code = snippet_block(cx, arms[0].body.span, ".."); - let body_code = if let ExprBlock(_) = arms[0].body.node { - body_code - } else { - Cow::Owned(format!("{{ {} }}", body_code)) - }; span_help_and_lint(cx, SINGLE_MATCH, expr.span, "you seem to be trying to use match for \ destructuring a single pattern. Did you mean to \ @@ -51,8 +43,7 @@ impl LintPass for MatchPass { &format!("try\nif let {} = {} {}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), - body_code) - ); + expr_block(cx, &arms[0].body, ".."))); } // check preconditions for MATCH_REF_PATS diff --git a/src/utils.rs b/src/utils.rs index b6fae89fc31..f16387f606d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -103,6 +103,16 @@ pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, trim_multiline(snip, true) } +/// Like snippet_block, but add braces if the expr is not an ExprBlock +pub fn expr_block<'a>(cx: &Context, expr: &Expr, default: &'a str) -> Cow<'a, str> { + let code = snippet_block(cx, expr.span, default); + if let ExprBlock(_) = expr.node { + code + } else { + Cow::Owned(format!("{{ {} }}", code)) + } +} + /// Trim indentation from a multiline string /// with possibility of ignoring the first line pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs new file mode 100755 index 00000000000..bc09168fad0 --- /dev/null +++ b/tests/compile-fail/while_loop.rs @@ -0,0 +1,52 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(while_let_loop)] +fn main() { + let y = Some(true); + loop { //~ERROR + if let Some(_x) = y { + let _v = 1; + } else { + break; + } + } + loop { //~ERROR + if let Some(_x) = y { + let _v = 1; + } else { + break + } + } + loop { // no error, break is not in else clause + if let Some(_x) = y { + let _v = 1; + } + break; + } + loop { //~ERROR + match y { + Some(_x) => true, + None => break + }; + } + loop { // no error, match is not the only statement + match y { + Some(_x) => true, + None => break + }; + let _x = 1; + } + loop { // no error, else branch does something other than break + match y { + Some(_x) => true, + _ => { + let _z = 1; + break; + } + }; + } + while let Some(x) = y { // no error, obviously + println!("{}", x); + } +} -- cgit 1.4.1-3-g733a5 From 16df79a0549ba44afdfcecfbb3cbb210d2a7863f Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 30 Aug 2015 13:10:59 +0200 Subject: new lint: using collect() to just exhaust an iterator Should use a for loop instead. --- README.md | 3 ++- src/lib.rs | 1 + src/loops.rs | 20 +++++++++++++++++++- tests/compile-fail/for_loop.rs | 5 +++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92a03b31530..4d5c59f2aef 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 50 lints included in this crate: +There are 51 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -56,6 +56,7 @@ name [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing diff --git a/src/lib.rs b/src/lib.rs index d69d352abc6..5e9205e32f9 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, + loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, diff --git a/src/loops.rs b/src/loops.rs index eba706ed7e1..fe901794d6c 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -20,13 +20,17 @@ declare_lint!{ pub ITER_NEXT_LOOP, Warn, declare_lint!{ pub WHILE_LET_LOOP, Warn, "`loop { if let { ... } else break }` can be written as a `while let` loop" } +declare_lint!{ pub UNUSED_COLLECT, Warn, + "`collect()`ing an iterator without using the result; this is usually better \ + written as a for loop" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP) + WHILE_LET_LOOP, UNUSED_COLLECT) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -112,6 +116,20 @@ impl LintPass for LoopsPass { } } } + + fn check_stmt(&mut self, cx: &Context, stmt: &Stmt) { + if let StmtSemi(ref expr, _) = stmt.node { + if let ExprMethodCall(ref method, _, ref args) = expr.node { + if args.len() == 1 && method.node.name == "collect" { + if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + span_lint(cx, UNUSED_COLLECT, expr.span, &format!( + "you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator")); + } + } + } + } + } } /// Recover the essential nodes of a desugared for loop: diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index eb7667b7fbd..66838651356 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -15,6 +15,7 @@ impl Unrelated { } #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop)] +#[deny(unused_collect)] #[allow(linkedlist)] fn main() { let mut vec = vec![1, 2, 3, 4]; @@ -56,4 +57,8 @@ fn main() { let u = Unrelated(vec![]); for _v in u.next() { } // no error for _v in u.iter() { } // no error + + let mut out = vec![]; + vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); //~ERROR you are collect()ing an iterator + let _y = vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine } -- cgit 1.4.1-3-g733a5 From ef0c933550937ed0db47fb9da9f0aa32e75c865b Mon Sep 17 00:00:00 2001 From: Tim Neumann <mail@timnn.me> Date: Sun, 30 Aug 2015 17:32:35 +0200 Subject: add precedence_negative_literal lint --- README.md | 2 +- src/lib.rs | 5 ++-- src/misc.rs | 44 --------------------------- src/precedence.rs | 65 ++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/precedence.rs | 10 +++++++ 5 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 src/precedence.rs diff --git a/README.md b/README.md index 4d5c59f2aef..1a1b6fe5956 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ name [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | expressions where precedence may trip up the unwary reader of the source; suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) diff --git a/src/lib.rs b/src/lib.rs index 5e9205e32f9..c72c5b1d7a7 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ pub mod lifetimes; pub mod loops; pub mod ranges; pub mod matches; +pub mod precedence; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { @@ -52,7 +53,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); reg.register_lint_pass(box misc::FloatCmp as LintPassObject); - reg.register_lint_pass(box misc::Precedence as LintPassObject); + reg.register_lint_pass(box precedence::Precedence as LintPassObject); reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); @@ -109,10 +110,10 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::CMP_OWNED, misc::FLOAT_CMP, misc::MODULO_ONE, - misc::PRECEDENCE, misc::TOPLEVEL_REF_ARG, mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, + precedence::PRECEDENCE, ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, diff --git a/src/misc.rs b/src/misc.rs index 6e438407216..ef9f4248c0c 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -109,50 +109,6 @@ fn is_float(cx: &Context, expr: &Expr) -> bool { } } -declare_lint!(pub PRECEDENCE, Warn, - "expressions where precedence may trip up the unwary reader of the source; \ - suggests adding parentheses, e.g. `x << 2 + y` will be parsed as `x << (2 + y)`"); - -#[derive(Copy,Clone)] -pub struct Precedence; - -impl LintPass for Precedence { - fn get_lints(&self) -> LintArray { - lint_array!(PRECEDENCE) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { - if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - span_lint(cx, PRECEDENCE, expr.span, - "operator precedence can trip the unwary. Consider adding parentheses \ - to the subexpression"); - } - } - } -} - -fn is_arith_expr(expr : &Expr) -> bool { - match expr.node { - ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), - _ => false - } -} - -fn is_bit_op(op : BinOp_) -> bool { - match op { - BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, - _ => false - } -} - -fn is_arith_op(op : BinOp_) -> bool { - match op { - BiAdd | BiSub | BiMul | BiDiv | BiRem => true, - _ => false - } -} - declare_lint!(pub CMP_OWNED, Warn, "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`"); diff --git a/src/precedence.rs b/src/precedence.rs new file mode 100644 index 00000000000..1d89adf9df8 --- /dev/null +++ b/src/precedence.rs @@ -0,0 +1,65 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::codemap::Spanned; + +use utils::span_lint; + +declare_lint!(pub PRECEDENCE, Warn, + "catches operations where precedence may be unclear. See the wiki for a \ + list of cases caught"); + +#[derive(Copy,Clone)] +pub struct Precedence; + +impl LintPass for Precedence { + fn get_lints(&self) -> LintArray { + lint_array!(PRECEDENCE) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { + if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { + span_lint(cx, PRECEDENCE, expr.span, + "operator precedence can trip the unwary. Consider adding parentheses \ + to the subexpression"); + } + } + + if let ExprUnary(UnNeg, ref rhs) = expr.node { + if let ExprMethodCall(_, _, ref args) = rhs.node { + if let Some(slf) = args.first() { + if let ExprLit(ref lit) = slf.node { + match lit.node { + LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => + span_lint(cx, PRECEDENCE, expr.span, + "unary minus has lower precedence than method call. Consider \ + adding parentheses to clarify your intent"), + _ => () + } + } + } + } + } + } +} + +fn is_arith_expr(expr : &Expr) -> bool { + match expr.node { + ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), + _ => false + } +} + +fn is_bit_op(op : BinOp_) -> bool { + match op { + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, + _ => false + } +} + +fn is_arith_op(op : BinOp_) -> bool { + match op { + BiAdd | BiSub | BiMul | BiDiv | BiRem => true, + _ => false + } +} diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs index ebb25f61b75..71dcd493008 100755 --- a/tests/compile-fail/precedence.rs +++ b/tests/compile-fail/precedence.rs @@ -13,4 +13,14 @@ fn main() { format!("{} vs. {}", 3 | 2 - 1, (3 | 2) - 1); //~ERROR operator precedence can trip format!("{} vs. {}", 3 & 5 - 2, (3 & 5) - 2); //~ERROR operator precedence can trip + format!("{} vs. {}", -1i32.abs(), (-1i32).abs()); //~ERROR unary minus has lower precedence + format!("{} vs. {}", -1f32.abs(), (-1f32).abs()); //~ERROR unary minus has lower precedence + + // These should not trigger an error + let _ = (-1i32).abs(); + let _ = (-1f32).abs(); + let _ = -(1i32).abs(); + let _ = -(1f32).abs(); + let _ = -(1i32.abs()); + let _ = -(1f32.abs()); } -- cgit 1.4.1-3-g733a5 From 03abe275b212890416b3015da8c2b323e946f424 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 30 Aug 2015 19:02:30 +0200 Subject: new lint: unnecessary patterns (x@_ -> x) --- README.md | 3 ++- src/lib.rs | 2 ++ src/misc.rs | 21 +++++++++++++++++++++ tests/compile-fail/patterns.rs | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100755 tests/compile-fail/patterns.rs diff --git a/README.md b/README.md index 4d5c59f2aef..cb9ee6671f3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 51 lints included in this crate: +There are 52 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -43,6 +43,7 @@ name [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` diff --git a/src/lib.rs b/src/lib.rs index 5e9205e32f9..d3f45af0754 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::CastPass as LintPassObject); reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); reg.register_lint_pass(box matches::MatchPass as LintPassObject); + reg.register_lint_pass(box misc::PatternPass as LintPassObject); reg.register_lint_group("shadow", vec![ shadow::SHADOW_REUSE, @@ -110,6 +111,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::FLOAT_CMP, misc::MODULO_ONE, misc::PRECEDENCE, + misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, diff --git a/src/misc.rs b/src/misc.rs index 6e438407216..ccf67b0fae0 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -235,3 +235,24 @@ fn is_lit_one(expr: &Expr) -> bool { } false } + +declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern"); + +#[derive(Copy,Clone)] +pub struct PatternPass; + +impl LintPass for PatternPass { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_PATTERN) + } + + fn check_pat(&mut self, cx: &Context, pat: &Pat) { + if let PatIdent(_, ref ident, Some(ref right)) = pat.node { + if right.node == PatWild(PatWildSingle) { + cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!( + "the `{} @ _` pattern can be written as just `{}`", + ident.node.name, ident.node.name)); + } + } + } +} diff --git a/tests/compile-fail/patterns.rs b/tests/compile-fail/patterns.rs new file mode 100755 index 00000000000..62bd2c43cc1 --- /dev/null +++ b/tests/compile-fail/patterns.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unused)] +#![deny(clippy)] + +fn main() { + let v = Some(true); + match v { + Some(x) => (), + y @ _ => (), //~ERROR the `y @ _` pattern can be written as just `y` + } + match v { + Some(x) => (), + y @ None => (), // no error + } +} -- cgit 1.4.1-3-g733a5 From d499d2a9a7c481a233fec1bf37245d20a44e7af5 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 31 Aug 2015 08:19:11 +0200 Subject: loops: remove debugging print --- src/loops.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/loops.rs b/src/loops.rs index fe901794d6c..f6247dd8419 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -192,7 +192,6 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { /// for &T and &mut T, such as Vec. fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); - println!("mt {:?} {:?}", e, ty); is_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || -- cgit 1.4.1-3-g733a5 From 0217fb81ee80776899440f997a8b71212dbfe17a Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 31 Aug 2015 08:29:34 +0200 Subject: loops: fix false positives with explicit_iter_loop and references (fixes #261) --- src/loops.rs | 6 ++++-- tests/compile-fail/for_loop.rs | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index f6247dd8419..33401dc67e1 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -4,7 +4,7 @@ use syntax::visit::{Visitor, walk_expr}; use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, walk_ptrs_ty, +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint}; use utils::{VEC_PATH, LL_PATH}; @@ -191,7 +191,9 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { - let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + // no walk_ptrs_ty: calling iter() on a reference can make sense because it + // will allow further borrows afterwards + let ty = cx.tcx.expr_ty(e); is_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 66838651356..f2540bfd595 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -37,6 +37,7 @@ fn main() { for _v in &mut vec { } // these are fine for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[ + for _v in (&mut [1, 2, 3]).iter() { } // no error let ll: LinkedList<()> = LinkedList::new(); for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll` let vd: VecDeque<()> = VecDeque::new(); -- cgit 1.4.1-3-g733a5 From e33bef685ef43cdefad624e73536927e766dec1e Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 31 Aug 2015 11:11:51 +0200 Subject: lifetimes lint: walk type bounds as well as types (fixes #253, again) --- src/lifetimes.rs | 48 ++++++++++++++++++++++++++++++----------- tests/compile-fail/lifetimes.rs | 12 +++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index bff0db14f7b..de7a39fdb3b 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -1,7 +1,7 @@ use syntax::ast::*; use rustc::lint::*; use syntax::codemap::Span; -use syntax::visit::{Visitor, walk_ty}; +use syntax::visit::{Visitor, walk_ty, walk_ty_param_bound}; use std::collections::HashSet; use utils::{in_external_macro, span_lint}; @@ -68,14 +68,7 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, // level of the current item. // check named LTs - let mut allowed_lts = HashSet::new(); - for lt in named_lts { - if lt.bounds.is_empty() { - allowed_lts.insert(Named(lt.lifetime.name)); - } - } - allowed_lts.insert(Unnamed); - allowed_lts.insert(Static); + let allowed_lts = allowed_lts_from(named_lts); // these will collect all the lifetimes for references in arg/return types let mut input_visitor = RefVisitor(Vec::new()); @@ -142,6 +135,18 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, false } +fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { + let mut allowed_lts = HashSet::new(); + for lt in named_lts { + if lt.bounds.is_empty() { + allowed_lts.insert(Named(lt.lifetime.name)); + } + } + allowed_lts.insert(Unnamed); + allowed_lts.insert(Static); + allowed_lts +} + /// Number of unique lifetimes in the given vector. fn unique_lifetimes(lts: &[RefLt]) -> usize { lts.iter().collect::<HashSet<_>>().len() @@ -186,17 +191,34 @@ impl<'v> Visitor<'v> for RefVisitor { /// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to /// reason about elision. fn has_where_lifetimes(where_clause: &WhereClause) -> bool { - let mut where_visitor = RefVisitor(Vec::new()); for predicate in &where_clause.predicates { match *predicate { WherePredicate::RegionPredicate(..) => return true, WherePredicate::BoundPredicate(ref pred) => { - walk_ty(&mut where_visitor, &pred.bounded_ty); + // a predicate like F: Trait or F: for<'a> Trait<'a> + let mut visitor = RefVisitor(Vec::new()); + // walk the type F, it may not contain LT refs + walk_ty(&mut visitor, &pred.bounded_ty); + if !visitor.0.is_empty() { return true; } + // if the bounds define new lifetimes, they are fine to occur + let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); + // now walk the bounds + for bound in pred.bounds.iter() { + walk_ty_param_bound(&mut visitor, bound); + } + // and check that all lifetimes are allowed + for lt in visitor.into_vec() { + if !allowed_lts.contains(<) { + return true; + } + } } WherePredicate::EqPredicate(ref pred) => { - walk_ty(&mut where_visitor, &pred.ty); + let mut visitor = RefVisitor(Vec::new()); + walk_ty(&mut visitor, &pred.ty); + if !visitor.0.is_empty() { return true; } } } } - !where_visitor.into_vec().is_empty() + false } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index ae115efec04..0b24ca65241 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -46,6 +46,18 @@ fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounde fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) where 'b: 'a { } // no error, bounded lifetime +struct Lt<'a, I: 'static> { + x: &'a I +} + +fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> + where F: Fn(Lt<'a, I>) -> Lt<'a, I> // no error, fn bound references 'a +{ unreachable!() } + +fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> //~ERROR explicit lifetimes given + where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> +{ unreachable!() } + struct X { x: u8, } -- cgit 1.4.1-3-g733a5 From 833493cf0711f7ca9ac778c4ea8d1410777be85d Mon Sep 17 00:00:00 2001 From: Frank Denis <github@pureftpd.org> Date: Tue, 1 Sep 2015 14:28:23 +0200 Subject: FnKind::FkClosure -> FnKind::Closure --- src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 26493080d87..b9d74c645b7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -22,7 +22,7 @@ impl LintPass for TopLevelRefPass { } fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - if let FnKind::FkClosure = k { + if let FnKind::Closure = k { // Does not apply to closures return } -- cgit 1.4.1-3-g733a5 From 88dd38de8771069b44b5ea52917c749d35bbc9b8 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 1 Sep 2015 17:53:56 +0200 Subject: lib: add clippy_pedantic group with all Allow by default lints (fixes #265) --- src/lib.rs | 25 +++++++++++-------------- tests/compile-fail/methods.rs | 2 +- tests/compile-fail/shadow.rs | 6 +++--- util/dogfood.sh | 2 +- util/update_lints.py | 29 ++++++++++++++++++++--------- 5 files changed, 36 insertions(+), 28 deletions(-) mode change 100644 => 100755 tests/compile-fail/shadow.rs diff --git a/src/lib.rs b/src/lib.rs index 7d6876ad839..f4da8b03bc2 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,10 +77,19 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box matches::MatchPass as LintPassObject); reg.register_lint_pass(box misc::PatternPass as LintPassObject); - reg.register_lint_group("shadow", vec![ + reg.register_lint_group("clippy_pedantic", vec![ + methods::OPTION_UNWRAP_USED, + methods::RESULT_UNWRAP_USED, + ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, - shadow::SHADOW_UNRELATED, + strings::STRING_ADD, + strings::STRING_ADD_ASSIGN, + types::CAST_POSSIBLE_TRUNCATION, + types::CAST_POSSIBLE_WRAP, + types::CAST_PRECISION_LOSS, + types::CAST_SIGN_LOSS, + unicode::NON_ASCII_LITERAL, ]); reg.register_lint_group("clippy", vec![ @@ -102,8 +111,6 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::WHILE_LET_LOOP, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, - methods::OPTION_UNWRAP_USED, - methods::RESULT_UNWRAP_USED, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, @@ -116,25 +123,15 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, precedence::PRECEDENCE, - ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, - shadow::SHADOW_REUSE, - shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, - strings::STRING_ADD, - strings::STRING_ADD_ASSIGN, types::BOX_VEC, - types::CAST_POSSIBLE_TRUNCATION, - types::CAST_POSSIBLE_WRAP, - types::CAST_PRECISION_LOSS, - types::CAST_SIGN_LOSS, types::LET_UNIT_VALUE, types::LINKEDLIST, types::TYPE_COMPLEXITY, types::UNIT_CMP, - unicode::NON_ASCII_LITERAL, unicode::ZERO_WIDTH_SPACE, ]); } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 05f77c1511e..1c81fefc4e5 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![allow(unused)] -#![deny(clippy)] +#![deny(clippy, clippy_pedantic)] use std::ops::Mul; diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs old mode 100644 new mode 100755 index 7098cb38877..8ac9a93b140 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![allow(unused_parens, unused_variables)] -#![deny(shadow)] +#![deny(clippy, clippy_pedantic)] fn id<T>(x: T) -> T { x } @@ -19,9 +19,9 @@ fn main() { let x = first(x); //~ERROR: x is shadowed by first(x) which reuses let y = 1; let x = y; //~ERROR: x is shadowed by y in this declaration - + let o = Some(1u8); - + if let Some(p) = o { assert_eq!(1, p); } match o { Some(p) => p, // no error, because the p above is in its own scope diff --git a/util/dogfood.sh b/util/dogfood.sh index e98d18c40d5..5ba8b4efa17 100755 --- a/util/dogfood.sh +++ b/util/dogfood.sh @@ -1,5 +1,5 @@ #!/bin/sh rm -rf target*/*so -cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy || exit 1 +cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy || exit 1 rm -rf target_recur diff --git a/util/update_lints.py b/util/update_lints.py index 8c00f1b4f13..94b2a3a57ba 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -38,7 +38,7 @@ def gen_table(lints, link=None): """Write lint table in Markdown format.""" if link: lints = [(p, '[%s](%s#%s)' % (l, link, l), lvl, d) - for (p, l, lvl, d) in lints] + for (p, l, lvl, d) in lints] # first and third column widths w_name = max(len(l[1]) for l in lints) w_desc = max(len(l[3]) for l in lints) @@ -50,8 +50,10 @@ def gen_table(lints, link=None): yield '%-*s | %-7s | %s\n' % (w_name, name, default, meaning) -def gen_group(lints): +def gen_group(lints, levels=None): """Write lint group (list of all lints in the form module::NAME).""" + if levels: + lints = [tup for tup in lints if tup[2] in levels] for (module, name, _, _) in sorted(lints): yield ' %s::%s,\n' % (module, name.upper()) @@ -113,19 +115,28 @@ def main(print_only=False, check=False): return # replace table in README.md - changed = replace_region('README.md', r'^name +\|', '^$', - lambda: gen_table(lints, link=wiki_link), - write_back=not check) + changed = replace_region( + 'README.md', r'^name +\|', '^$', + lambda: gen_table(lints, link=wiki_link), + write_back=not check) - changed |= replace_region('README.md', + changed |= replace_region( + 'README.md', r'^There are \d+ lints included in this crate:', "", lambda: ['There are %d lints included in this crate:\n' % len(lints)], write_back=not check) # same for "clippy" lint collection - changed |= replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', - lambda: gen_group(lints), replace_start=False, - write_back=not check) + changed |= replace_region( + 'src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + lambda: gen_group(lints, levels=('warn', 'deny')), + replace_start=False, write_back=not check) + + # same for "clippy_pedantic" lint collection + changed |= replace_region( + 'src/lib.rs', r'reg.register_lint_group\("clippy_pedantic"', r'\]\);', + lambda: gen_group(lints, levels=('allow',)), + replace_start=False, write_back=not check) if check and changed: print('Please run util/update_lints.py to regenerate lints lists.') -- cgit 1.4.1-3-g733a5 From 100786419807ac5365185b659d46acc67f5b1ccf Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 1 Sep 2015 18:52:48 +0200 Subject: new lint: self conventions for certain method names (fixes #267) --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 68 ++++++++++++++++++++++++++++++++++--------- tests/compile-fail/methods.rs | 3 ++ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 27be09c6127..1232f526875 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 52 lints included in this crate: +There are 53 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -59,6 +59,7 @@ name [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/lib.rs b/src/lib.rs index f4da8b03bc2..e51732818ba 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,6 +114,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, + methods::WRONG_SELF_CONVENTION, misc::CMP_NAN, misc::CMP_OWNED, misc::FLOAT_CMP, diff --git a/src/methods.rs b/src/methods.rs index 50f3512b4f0..5a20ba06831 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -23,11 +23,14 @@ declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, "defining a method that should be implementing a std trait"); +declare_lint!(pub WRONG_SELF_CONVENTION, Warn, + "defining a method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, - SHOULD_IMPLEMENT_TRAIT) + SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -68,18 +71,28 @@ impl LintPass for MethodsPass { if let ItemImpl(_, _, _, None, _, ref items) = item.node { for item in items { let name = item.ident.name; - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if_let_chain! { - [ - name == method_name, - let MethodImplItem(ref sig, _) = item.node, - sig.decl.inputs.len() == n_args, - out_type.matches(&sig.decl.output), - self_kind.matches(&sig.explicit_self.node) - ], { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, item.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); + if let MethodImplItem(ref sig, _) = item.node { + // check missing trait implementations + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if_let_chain! { + [ + name == method_name, + sig.decl.inputs.len() == n_args, + out_type.matches(&sig.decl.output), + self_kind.matches(&sig.explicit_self.node) + ], { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, item.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } + } + } + // check conventions w.r.t. conversion method names and predicates + for &(prefix, self_kind) in &CONVENTIONS { + if name.as_str().starts_with(prefix) && !self_kind.matches(&sig.explicit_self.node) { + span_lint(cx, WRONG_SELF_CONVENTION, sig.explicit_self.span, &format!( + "methods called `{}*` usually take {}; consider choosing a less \ + ambiguous name", prefix, self_kind.description())); } } } @@ -88,6 +101,14 @@ impl LintPass for MethodsPass { } } +const CONVENTIONS: [(&'static str, SelfKind); 5] = [ + ("into_", ValueSelf), + ("to_", RefSelf), + ("as_", RefSelf), + ("is_", RefSelf), + ("from_", NoSelf), +]; + const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ ("add", 2, ValueSelf, AnyType, "std::ops::Add`"), ("sub", 2, ValueSelf, AnyType, "std::ops::Sub"), @@ -126,7 +147,7 @@ enum SelfKind { ValueSelf, RefSelf, RefMutSelf, - NoSelf + NoSelf, } impl SelfKind { @@ -136,9 +157,28 @@ impl SelfKind { (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true, (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true, (&NoSelf, &SelfStatic) => true, + (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty), _ => false } } + + fn matches_explicit_type(&self, ty: &Ty) -> bool { + match (self, &ty.node) { + (&ValueSelf, &TyPath(..)) => true, + (&RefSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true, + (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, + _ => false + } + } + + fn description(&self) -> &'static str { + match *self { + ValueSelf => "self by value", + RefSelf => "self by reference", + RefMutSelf => "self by mutable reference", + NoSelf => "no self", + } + } } #[derive(Clone, Copy)] diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 1c81fefc4e5..560f36a9d5d 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -15,6 +15,9 @@ impl T { fn sub(&self, other: T) -> &T { self } // no error, self is a ref fn div(self) -> T { self } // no error, different #arguments fn rem(self, other: T) { } // no error, wrong return type + + fn into_u32(self) -> u32 { 0 } // fine + fn into_u16(&self) -> u16 { 0 } //~ERROR methods called `into_*` usually take self by value } impl Mul<T> for T { -- cgit 1.4.1-3-g733a5 From 5264196538a36d21d2666b9e5f1584c3806111ba Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Tue, 1 Sep 2015 21:08:49 +0200 Subject: methods: try to allow value self when type is Copy (fixes #273) --- src/methods.rs | 35 +++++++++++++++++++++++++---------- tests/compile-fail/methods.rs | 9 +++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 5a20ba06831..d55cf49daab 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -68,10 +68,10 @@ impl LintPass for MethodsPass { } fn check_item(&mut self, cx: &Context, item: &Item) { - if let ItemImpl(_, _, _, None, _, ref items) = item.node { - for item in items { - let name = item.ident.name; - if let MethodImplItem(ref sig, _) = item.node { + if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { + for implitem in items { + let name = implitem.ident.name; + if let MethodImplItem(ref sig, _) = implitem.node { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if_let_chain! { @@ -79,9 +79,9 @@ impl LintPass for MethodsPass { name == method_name, sig.decl.inputs.len() == n_args, out_type.matches(&sig.decl.output), - self_kind.matches(&sig.explicit_self.node) + self_kind.matches(&sig.explicit_self.node, false) ], { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, item.span, &format!( + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); } @@ -89,7 +89,8 @@ impl LintPass for MethodsPass { } // check conventions w.r.t. conversion method names and predicates for &(prefix, self_kind) in &CONVENTIONS { - if name.as_str().starts_with(prefix) && !self_kind.matches(&sig.explicit_self.node) { + if name.as_str().starts_with(prefix) && + !self_kind.matches(&sig.explicit_self.node, is_copy(cx, &ty, &item)) { span_lint(cx, WRONG_SELF_CONVENTION, sig.explicit_self.span, &format!( "methods called `{}*` usually take {}; consider choosing a less \ ambiguous name", prefix, self_kind.description())); @@ -151,22 +152,26 @@ enum SelfKind { } impl SelfKind { - fn matches(&self, slf: &ExplicitSelf_) -> bool { + fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool { match (self, slf) { (&ValueSelf, &SelfValue(_)) => true, (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true, (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true, + (&RefSelf, &SelfValue(_)) => allow_value_for_ref, + (&RefMutSelf, &SelfValue(_)) => allow_value_for_ref, (&NoSelf, &SelfStatic) => true, - (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty), + (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), _ => false } } - fn matches_explicit_type(&self, ty: &Ty) -> bool { + fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool { match (self, &ty.node) { (&ValueSelf, &TyPath(..)) => true, (&RefSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true, (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, + (&RefSelf, &TyPath(..)) => allow_value_for_ref, + (&RefMutSelf, &TyPath(..)) => allow_value_for_ref, _ => false } } @@ -212,3 +217,13 @@ fn is_bool(ty: &Ty) -> bool { } false } + +fn is_copy(cx: &Context, ast_ty: &Ty, item: &Item) -> bool { + match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { + None => false, + Some(ty) => { + let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); + !ty.moves_by_default(&env, ast_ty.span) + } + } +} diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 560f36a9d5d..314601f6dbd 100755 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -18,6 +18,15 @@ impl T { fn into_u32(self) -> u32 { 0 } // fine fn into_u16(&self) -> u16 { 0 } //~ERROR methods called `into_*` usually take self by value + + fn to_something(self) -> u32 { 0 } //~ERROR methods called `to_*` usually take self by reference +} + +#[derive(Clone,Copy)] +struct U; + +impl U { + fn to_something(self) -> u32 { 0 } // ok because U is Copy } impl Mul<T> for T { -- cgit 1.4.1-3-g733a5 From 08fb953e1a9ac43720db6cf1d75bd19f5aa3cff5 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 01:36:37 +0200 Subject: extended pattern matching --- src/shadow.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index eba7a9da187..e7097f9daf6 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -60,8 +60,12 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - if let &Some(ref o) = init { check_expr(cx, o, bindings) } - check_pat(cx, pat, init, span, bindings); + if let &Some(ref o) = init { + check_expr(cx, o, bindings); + check_pat(cx, pat, &Some(o), span, bindings); + } else { + check_pat(cx, pat, &None, span, bindings); + } } } @@ -72,8 +76,8 @@ fn is_binding(cx: &Context, pat: &Pat) -> bool { } } -fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, - bindings: &mut Vec<Name>) where T: Deref<Target=Expr> { +fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, + bindings: &mut Vec<Name>) { //TODO: match more stuff / destructuring match pat.node { PatIdent(_, ref ident, ref inner) => { @@ -88,9 +92,43 @@ fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span, if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } }, //PatEnum(Path, Option<Vec<P<Pat>>>), - //PatQPath(QSelf, Path), - //PatStruct(Path, Vec<Spanned<FieldPat>>, bool), - //PatTup(Vec<P<Pat>>), + PatStruct(_, ref pfields, _) => + if let Some(ref init_struct) = *init { // TODO follow + if let ExprStruct(_, ref efields, ref _base) = init_struct.node { + // TODO: follow base + for field in pfields { + let ident = field.node.ident; + let efield = efields.iter() + .find(|ref f| f.ident.node == ident) + .map(|f| &*f.expr); + check_pat(cx, &field.node.pat, &efield, span, bindings); + } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, &None, span, bindings); + } + } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, &None, span, bindings); + } + }, + PatTup(ref inner) => + if let Some(ref init_tup) = *init { //TODO: follow + if let ExprTup(ref tup) = init_tup.node { + for (i, p) in inner.iter().enumerate() { + check_pat(cx, p, &Some(&tup[i]), p.span, bindings); + } + } else { + for p in inner { + check_pat(cx, p, &None, span, bindings); + } + } + } else { + for p in inner { + check_pat(cx, p, &None, span, bindings); + } + }, PatBox(ref inner) => { if let Some(ref initp) = *init { match initp.node { -- cgit 1.4.1-3-g733a5 From e2e89bf800b263e7a7ba5639d62b402ce5dd3bba Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 01:36:37 +0200 Subject: extended pattern matching --- src/shadow.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index e7097f9daf6..2276fb1da5d 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -60,7 +60,7 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - if let &Some(ref o) = init { + if let &Some(ref o) = init { check_expr(cx, o, bindings); check_pat(cx, pat, &Some(o), span, bindings); } else { @@ -92,10 +92,9 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } }, //PatEnum(Path, Option<Vec<P<Pat>>>), - PatStruct(_, ref pfields, _) => - if let Some(ref init_struct) = *init { // TODO follow - if let ExprStruct(_, ref efields, ref _base) = init_struct.node { - // TODO: follow base + PatStruct(_, ref pfields, _) => + if let Some(ref init_struct) = *init { + if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { let ident = field.node.ident; let efield = efields.iter() @@ -105,7 +104,7 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, } } else { for field in pfields { - check_pat(cx, &field.node.pat, &None, span, bindings); + check_pat(cx, &field.node.pat, init, span, bindings); } } } else { @@ -114,14 +113,14 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, } }, PatTup(ref inner) => - if let Some(ref init_tup) = *init { //TODO: follow + if let Some(ref init_tup) = *init { if let ExprTup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { + for (i, p) in inner.iter().enumerate() { check_pat(cx, p, &Some(&tup[i]), p.span, bindings); } } else { for p in inner { - check_pat(cx, p, &None, span, bindings); + check_pat(cx, p, init, span, bindings); } } } else { -- cgit 1.4.1-3-g733a5 From 1ab733cfa1b8ccad239aaa1a9e9a0fbf69a5ee18 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 01:36:37 +0200 Subject: extended pattern matching --- src/shadow.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index e7097f9daf6..2276fb1da5d 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -60,7 +60,7 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - if let &Some(ref o) = init { + if let &Some(ref o) = init { check_expr(cx, o, bindings); check_pat(cx, pat, &Some(o), span, bindings); } else { @@ -92,10 +92,9 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } }, //PatEnum(Path, Option<Vec<P<Pat>>>), - PatStruct(_, ref pfields, _) => - if let Some(ref init_struct) = *init { // TODO follow - if let ExprStruct(_, ref efields, ref _base) = init_struct.node { - // TODO: follow base + PatStruct(_, ref pfields, _) => + if let Some(ref init_struct) = *init { + if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { let ident = field.node.ident; let efield = efields.iter() @@ -105,7 +104,7 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, } } else { for field in pfields { - check_pat(cx, &field.node.pat, &None, span, bindings); + check_pat(cx, &field.node.pat, init, span, bindings); } } } else { @@ -114,14 +113,14 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, } }, PatTup(ref inner) => - if let Some(ref init_tup) = *init { //TODO: follow + if let Some(ref init_tup) = *init { if let ExprTup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { + for (i, p) in inner.iter().enumerate() { check_pat(cx, p, &Some(&tup[i]), p.span, bindings); } } else { for p in inner { - check_pat(cx, p, &None, span, bindings); + check_pat(cx, p, init, span, bindings); } } } else { -- cgit 1.4.1-3-g733a5 From bc1eb8481029856d41df3ae2a404cbfe51b80016 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 07:56:13 +0200 Subject: match region patterns --- src/shadow.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index 2276fb1da5d..d64f6840db8 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -130,17 +130,17 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, }, PatBox(ref inner) => { if let Some(ref initp) = *init { - match initp.node { - ExprBox(_, ref inner_init) => - check_pat(cx, inner, &Some(&**inner_init), span, bindings), - //TODO: ExprCall on Box::new - _ => check_pat(cx, inner, init, span, bindings), + if let ExprBox(_, ref inner_init) = initp.node { + check_pat(cx, inner, &Some(&**inner_init), span, bindings), + } else { + check_pat(cx, inner, init, span, bindings), } } else { check_pat(cx, inner, init, span, bindings); } }, - //PatRegion(P<Pat>, Mutability), + PatRegion(ref inner, _) => + check_pat(cx, inner, init, span, bindings), //PatRange(P<Expr>, P<Expr>), //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), _ => (), -- cgit 1.4.1-3-g733a5 From 0fb7d1d2d98016b496c36606ab003fd5d0b7e994 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 08:19:47 +0200 Subject: reporting improvements --- src/shadow.rs | 22 ++++++++++++---------- src/utils.rs | 19 +++++++++++++++++-- tests/compile-fail/matches.rs | 18 ++++++++++-------- tests/compile-fail/shadow.rs | 2 +- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index d64f6840db8..751077ec1d9 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -6,7 +6,7 @@ use syntax::visit::FnKind; use rustc::lint::{Context, LintArray, LintPass}; use rustc::middle::def::Def::{DefVariant, DefStruct}; -use utils::{in_external_macro, snippet, span_lint}; +use utils::{in_external_macro, snippet, span_lint, span_note_and_lint}; declare_lint!(pub SHADOW_SAME, Allow, "rebinding a name to itself, e.g. `let mut x = &mut x`"); @@ -131,9 +131,9 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, PatBox(ref inner) => { if let Some(ref initp) = *init { if let ExprBox(_, ref inner_init) = initp.node { - check_pat(cx, inner, &Some(&**inner_init), span, bindings), + check_pat(cx, inner, &Some(&**inner_init), span, bindings); } else { - check_pat(cx, inner, init, span, bindings), + check_pat(cx, inner, init, span, bindings); } } else { check_pat(cx, inner, init, span, bindings); @@ -149,7 +149,7 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: &Option<T>) where T: Deref<Target=Expr> { - if let &Some(ref expr) = init { + if let Some(ref expr) = *init { if is_self_shadow(name, expr) { span_lint(cx, SHADOW_SAME, span, &format!( "{} is shadowed by itself in {}", @@ -157,20 +157,22 @@ fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: snippet(cx, expr.span, ".."))); } else { if contains_self(name, expr) { - span_lint(cx, SHADOW_REUSE, span, &format!( + span_note_and_lint(cx, SHADOW_REUSE, lspan, &format!( "{} is shadowed by {} which reuses the original value", snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); + snippet(cx, expr.span, "..")), + expr.span, "initialization happens here"); } else { - span_lint(cx, SHADOW_UNRELATED, span, &format!( - "{} is shadowed by {} in this declaration", + span_note_and_lint(cx, SHADOW_UNRELATED, lspan, &format!( + "{} is shadowed by {}", snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); + snippet(cx, expr.span, "..")), + expr.span, "initialization happens here"); } } } else { span_lint(cx, SHADOW_UNRELATED, span, &format!( - "{} is shadowed in this declaration", snippet(cx, lspan, "_"))); + "{} shadows a previous declaration", snippet(cx, lspan, "_"))); } } diff --git a/src/utils.rs b/src/utils.rs index f16387f606d..2f9b86964c2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -23,7 +23,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { if info.callee.name() == "closure expansion" { return false; } - }, + }, ExpnFormat::MacroAttribute(..) => { // these are all plugins return true; @@ -177,7 +177,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, help: &str) { - span_lint(cx, lint, span, msg); + cx.span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { cx.sess().fileline_help(span, &format!("{}\nfor further information \ visit https://github.com/Manishearth/rust-clippy/wiki#{}", @@ -185,6 +185,21 @@ pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, } } +pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, + msg: &str, note_span: Span, note: &str) { + cx.span_lint(lint, span, msg); + if cx.current_level(lint) != Level::Allow { + if note_span == span { + cx.sess().fileline_note(note_span, note) + } else { + cx.sess().span_note(note_span, note) + } + cx.sess().fileline_help(span, &format!("for further information visit \ + https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())) + } +} + /// return the base type for references and raw pointers pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 3cc540992c9..07dc7c9ef83 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -39,14 +39,16 @@ fn single_match(){ } fn ref_pats() { - let ref v = Some(0); - match v { //~ERROR instead of prefixing all patterns with `&` - &Some(v) => println!("{:?}", v), - &None => println!("none"), - } - match v { // this doesn't trigger, we have a different pattern - &Some(v) => println!("some"), - other => println!("other"), + { + let ref v = Some(0); + match v { //~ERROR instead of prefixing all patterns with `&` + &Some(v) => println!("{:?}", v), + &None => println!("none"), + } + match v { // this doesn't trigger, we have a different pattern + &Some(v) => println!("some"), + other => println!("other"), + } } let ref tup = (1, 2); match tup { //~ERROR instead of prefixing all patterns with `&` diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index 8ac9a93b140..80d48f84163 100755 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -18,7 +18,7 @@ fn main() { let x = (1, x); //~ERROR: x is shadowed by (1, x) which reuses let x = first(x); //~ERROR: x is shadowed by first(x) which reuses let y = 1; - let x = y; //~ERROR: x is shadowed by y in this declaration + let x = y; //~ERROR: x is shadowed by y let o = Some(1u8); -- cgit 1.4.1-3-g733a5 From 0c7f05dd760b7d1ad329d62268236184e2210c3f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 2 Sep 2015 10:30:11 +0200 Subject: check item name for eq, fixes #268 --- src/misc.rs | 12 ++++++++++++ tests/compile-fail/float_cmp.rs | 25 +++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index b9d74c645b7..5f32a93d3dd 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -4,6 +4,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; +use rustc::ast_map::Node::*; use rustc::middle::ty; use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; @@ -91,6 +92,17 @@ impl LintPass for FloatCmp { false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { return; } + let parent_id = cx.tcx.map.get_parent(expr.id); + match cx.tcx.map.find(parent_id) { + Some(NodeItem(&Item{ ref ident, .. })) | + Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | + Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { + let name = ident.name.as_str(); + if &*name == "eq" || name.starts_with("eq_") || + name.ends_with("_eq") { return; } + }, + _ => (), + } span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-comparison of f32 or f64 detected. Consider changing this to \ `abs({} - {}) < epsilon` for some suitable value of epsilon", diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 067ec2818bf..da3dba5e4d4 100755 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -1,6 +1,9 @@ #![feature(plugin)] #![plugin(clippy)] +#![deny(float_cmp)] +#![allow(unused)] + use std::ops::Add; const ZERO : f32 = 0.0; @@ -10,8 +13,26 @@ fn twice<T>(x : T) -> T where T : Add<T, Output = T>, T : Copy { x + x } -#[deny(float_cmp)] -#[allow(unused)] +fn eq_fl(x: f32, y: f32) -> bool { + if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn +} + +fn fl_eq(x: f32, y: f32) -> bool { + if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn +} + +struct X { val: f32 } + +impl PartialEq for X { + fn eq(&self, o: &X) -> bool { + if self.val.is_nan() { + o.val.is_nan() + } else { + self.val == o.val // no error, inside "eq" fn + } + } +} + fn main() { ZERO == 0f32; //no error, comparison with zero is ok ZERO == 0.0; //no error, comparison with zero is ok -- cgit 1.4.1-3-g733a5 From 73c34e12b324038e3c501faf63de1a3d618f22b5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 2 Sep 2015 16:11:51 +0530 Subject: Only handle ranges starting with 0 for needless_range_loop (fixes #279) --- src/loops.rs | 46 ++++++++++++++++++++++++------------------ tests/compile-fail/for_loop.rs | 4 ++++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 33401dc67e1..3e1e669ea48 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -37,26 +37,32 @@ impl LintPass for LoopsPass { if let Some((pat, arg, body)) = recover_for_loop(expr) { // check for looping over a range and then indexing a sequence with it // -> the iteratee must be a range literal - if let ExprRange(_, _) = arg.node { - // the var must be a single name - if let PatIdent(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { cx: cx, var: ident.node.name, - indexed: HashSet::new(), nonindex: false }; - walk_expr(&mut visitor, body); - // linting condition: we only indexed one variable - if visitor.indexed.len() == 1 { - let indexed = visitor.indexed.into_iter().next().expect( - "Len was nonzero, but no contents found"); - if visitor.nonindex { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is used to index `{}`. Consider using \ - `for ({}, item) in {}.iter().enumerate()` or similar iterators", - ident.node.name, indexed, ident.node.name, indexed)); - } else { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in &{}` or similar iterators", - ident.node.name, indexed, indexed)); + if let ExprRange(Some(ref l), _) = arg.node { + // Range should start with `0` + if let ExprLit(ref lit) = l.node { + if let LitInt(0, _) = lit.node { + + // the var must be a single name + if let PatIdent(_, ref ident, _) = pat.node { + let mut visitor = VarVisitor { cx: cx, var: ident.node.name, + indexed: HashSet::new(), nonindex: false }; + walk_expr(&mut visitor, body); + // linting condition: we only indexed one variable + if visitor.indexed.len() == 1 { + let indexed = visitor.indexed.into_iter().next().expect( + "Len was nonzero, but no contents found"); + if visitor.nonindex { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is used to index `{}`. Consider using \ + `for ({}, item) in {}.iter().enumerate()` or similar iterators", + ident.node.name, indexed, ident.node.name, indexed)); + } else { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is only used to index `{}`. \ + Consider using `for item in &{}` or similar iterators", + ident.node.name, indexed, indexed)); + } + } } } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index f2540bfd595..4d0c22fff0b 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -30,6 +30,10 @@ fn main() { println!("{} {}", vec[i], vec2[i]); } + for i in 5..vec.len() { // not an error, not starting with 0 + println!("{}", vec[i]); + } + for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec` for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec` -- cgit 1.4.1-3-g733a5 From 846c164709dac20fd16e30e8366c2b0dadd55787 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 2 Sep 2015 16:46:12 +0200 Subject: don't say "did you mean to" - use the standard "consider..." "Did you mean to ..." sounds a bit condescending to me, since if I meant to write "if let" I probably wouldn't have written "match" :) --- README.md | 2 +- src/matches.rs | 13 ++++++------- src/types.rs | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1232f526875..8c00c9f901b 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ fn main(){ Produce this warning: ``` -src/main.rs:8:5: 11:6 warning: You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?, #[warn(single_match)] on by default +src/main.rs:8:5: 11:6 warning: you seem to be trying to use match for destructuring a single type. Consider using `if let`, #[warn(single_match)] on by default src/main.rs:8 match x { src/main.rs:9 Some(y) => println!("{:?}", y), src/main.rs:10 _ => () diff --git a/src/matches.rs b/src/matches.rs index 3d04c9210ce..fdc3ca5e907 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -37,13 +37,12 @@ impl LintPass for MatchPass { { if in_external_macro(cx, expr.span) {return;} span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for \ - destructuring a single pattern. Did you mean to \ - use `if let`?", - &format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, ".."))); + "you seem to be trying to use match for destructuring a \ + single pattern. Consider using `if let`", + &format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, ".."))); } // check preconditions for MATCH_REF_PATS diff --git a/src/types.rs b/src/types.rs index 3c4d1441f17..4a3c183462d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -30,7 +30,7 @@ impl LintPass for TypePass { if match_type(cx, inner, &VEC_PATH) { span_help_and_lint( cx, BOX_VEC, ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?", + "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); } } -- cgit 1.4.1-3-g733a5 From 6b589681c9855a4802308423242976414d414b17 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 2 Sep 2015 17:14:23 +0200 Subject: methods: allow multiple self kinds for "is_" methods These can be static method predicates. (Found one in rust-copperline, called Term::is_unsupported_term().) --- src/methods.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index d55cf49daab..4a144734a94 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -88,12 +88,14 @@ impl LintPass for MethodsPass { } } // check conventions w.r.t. conversion method names and predicates - for &(prefix, self_kind) in &CONVENTIONS { + let is_copy = is_copy(cx, &ty, &item); + for &(prefix, self_kinds) in &CONVENTIONS { if name.as_str().starts_with(prefix) && - !self_kind.matches(&sig.explicit_self.node, is_copy(cx, &ty, &item)) { + !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { span_lint(cx, WRONG_SELF_CONVENTION, sig.explicit_self.span, &format!( "methods called `{}*` usually take {}; consider choosing a less \ - ambiguous name", prefix, self_kind.description())); + ambiguous name", prefix, + &self_kinds.iter().map(|k| k.description()).collect::<Vec<_>>().join(" or "))); } } } @@ -102,12 +104,12 @@ impl LintPass for MethodsPass { } } -const CONVENTIONS: [(&'static str, SelfKind); 5] = [ - ("into_", ValueSelf), - ("to_", RefSelf), - ("as_", RefSelf), - ("is_", RefSelf), - ("from_", NoSelf), +const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ + ("into_", &[ValueSelf]), + ("to_", &[RefSelf]), + ("as_", &[RefSelf]), + ("is_", &[RefSelf, NoSelf]), + ("from_", &[NoSelf]), ]; const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ -- cgit 1.4.1-3-g733a5 From 7649d1c2a8d53dc5928450d6d7befd602bc966cd Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 2 Sep 2015 18:17:38 +0200 Subject: shadow: complete coverage of "contains_self" checker --- src/shadow.rs | 52 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index 751077ec1d9..7f555d4be85 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -255,29 +255,55 @@ fn path_eq_name(name: Name, path: &Path) -> bool { fn contains_self(name: Name, expr: &Expr) -> bool { match expr.node { + // the "self" name itself (maybe) + ExprPath(_, ref path) => path_eq_name(name, path), + // no subexprs + ExprLit(_) => false, + // one subexpr ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) - => contains_self(name, e), - ExprBinary(_, ref l, ref r) => + ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) | + ExprCast(ref e, _) => + contains_self(name, e), + // two subexprs + ExprBinary(_, ref l, ref r) | ExprIndex(ref l, ref r) | + ExprAssign(ref l, ref r) | ExprAssignOp(_, ref l, ref r) | + ExprRepeat(ref l, ref r) => contains_self(name, l) || contains_self(name, r), - ExprBlock(ref block) | ExprLoop(ref block, _) => + // one optional subexpr + ExprRet(ref oe) => + oe.as_ref().map_or(false, |ref e| contains_self(name, e)), + // two optional subexprs + ExprRange(ref ol, ref or) => + ol.as_ref().map_or(false, |ref e| contains_self(name, e)) || + or.as_ref().map_or(false, |ref e| contains_self(name, e)), + // one subblock + ExprBlock(ref block) | ExprLoop(ref block, _) | + ExprClosure(_, _, ref block) => contains_block_self(name, block), - ExprCall(ref fun, ref args) => contains_self(name, fun) || - args.iter().any(|ref a| contains_self(name, a)), - ExprMethodCall(_, _, ref args) => + // one vec + ExprMethodCall(_, _, ref v) | ExprVec(ref v) | ExprTup(ref v) => + v.iter().any(|ref a| contains_self(name, a)), + // one expr, one vec + ExprCall(ref fun, ref args) => + contains_self(name, fun) || args.iter().any(|ref a| contains_self(name, a)), - ExprVec(ref v) | ExprTup(ref v) => - v.iter().any(|ref e| contains_self(name, e)), + // special ones ExprIf(ref cond, ref then, ref otherwise) => contains_self(name, cond) || contains_block_self(name, then) || otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)), ExprWhile(ref e, ref block, _) => contains_self(name, e) || contains_block_self(name, block), ExprMatch(ref e, ref arms, _) => - arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat| - contains_pat_self(name, pat))) || contains_self(name, e), - ExprPath(_, ref path) => path_eq_name(name, path), - _ => false + contains_self(name, e) || + arms.iter().any( + |ref arm| + arm.pats.iter().any(|ref pat| contains_pat_self(name, pat)) || + arm.guard.as_ref().map_or(false, |ref g| contains_self(name, g)) || + contains_self(name, &arm.body)), + ExprStruct(_, ref fields, ref other) => + fields.iter().any(|ref f| contains_self(name, &f.expr)) || + other.as_ref().map_or(false, |ref e| contains_self(name, e)), + _ => false, } } -- cgit 1.4.1-3-g733a5 From fbdba7f915cae7689b4afb6ef7580d8274f09d22 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 3 Sep 2015 02:14:05 +0530 Subject: Fix ICE --- src/methods.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index 4a144734a94..c6f0b1c2e59 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,6 +1,7 @@ use syntax::ast::*; use rustc::lint::*; use rustc::middle::ty; +use rustc::middle::subst::Subst; use std::iter; use std::borrow::Cow; @@ -225,7 +226,7 @@ fn is_copy(cx: &Context, ast_ty: &Ty, item: &Item) -> bool { None => false, Some(ty) => { let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - !ty.moves_by_default(&env, ast_ty.span) + !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, ast_ty.span) } } } -- cgit 1.4.1-3-g733a5 From cb571bf2e2b3b4f9696a9ed4d93f599a2b044fd6 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 3 Sep 2015 10:57:11 +0200 Subject: also ignore functions --- src/misc.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 5f32a93d3dd..1376bf41b38 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -98,8 +98,11 @@ impl LintPass for FloatCmp { Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { let name = ident.name.as_str(); - if &*name == "eq" || name.starts_with("eq_") || - name.ends_with("_eq") { return; } + if &*name == "eq" || &*name == "ne" || + name.starts_with("eq_") || + name.ends_with("_eq") { + return; + } }, _ => (), } -- cgit 1.4.1-3-g733a5 From eca185438b52ae4645f5aa78b6076adeec49707d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 3 Sep 2015 20:12:17 +0530 Subject: Update rust to 0efb9dab8c7c07fa28e9df0eccc5c07ea3c17fbb (HIR+lints, Thu Sep 3 18:59:56 2015 +0530) fixes #294 --- src/approx_const.rs | 2 +- src/attrs.rs | 6 +++--- src/bit_mask.rs | 4 ++-- src/collapsible_if.rs | 2 +- src/consts.rs | 2 +- src/eq_op.rs | 4 ++-- src/eta_reduction.rs | 2 +- src/identity_op.rs | 2 +- src/len_zero.rs | 2 +- src/lib.rs | 6 ++++++ src/lifetimes.rs | 7 ++++--- src/loops.rs | 5 +++-- src/matches.rs | 5 ++--- src/methods.rs | 2 +- src/misc.rs | 9 +++++---- src/mut_mut.rs | 2 +- src/needless_bool.rs | 2 +- src/precedence.rs | 2 +- src/ptr_arg.rs | 2 +- src/ranges.rs | 2 +- src/returns.rs | 8 ++++---- src/shadow.rs | 11 +++++------ src/strings.rs | 2 +- src/types.rs | 22 +++++++++++----------- src/unicode.rs | 2 +- src/utils.rs | 5 +++-- tests/consts.rs | 3 ++- 27 files changed, 66 insertions(+), 57 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index d307c7dd056..a132bc90361 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::Span; use std::f64::consts as f64; diff --git a/src/attrs.rs b/src/attrs.rs index ad021f28a4d..05362c706f0 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -1,7 +1,8 @@ //! checks for attributes use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; +use reexport::*; use syntax::codemap::ExpnInfo; use utils::{in_macro, match_path, span_lint}; @@ -68,7 +69,6 @@ fn is_relevant_block(block: &Block) -> bool { StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { return is_relevant_expr(expr); } - _ => () } } block.expr.as_ref().map_or(false, |e| is_relevant_expr(e)) @@ -79,7 +79,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { ExprBlock(ref block) => is_relevant_block(block), ExprRet(Some(ref e)) | ExprParen(ref e) => is_relevant_expr(e), - ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, + ExprRet(None) | ExprBreak(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { !match_path(path, &["std", "rt", "begin_unwind"]) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 465b772da5c..b1b8a735455 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::*; -use syntax::ast::*; -use syntax::ast_util::is_comparison_binop; +use rustc_front::hir::*; +use rustc_front::util::is_comparison_binop; use syntax::codemap::Span; use utils::span_lint; diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index e0b25b7283b..9301aafbace 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -13,7 +13,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::{Spanned, ExpnInfo}; use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; diff --git a/src/consts.rs b/src/consts.rs index 29b96146db2..a8a446a703f 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -4,7 +4,7 @@ use rustc::lint::Context; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::ptr::P; use std::cmp::PartialOrd; use std::cmp::Ordering::{self, Greater, Less, Equal}; diff --git a/src/eq_op.rs b/src/eq_op.rs index 3b4f47b5562..c5953201436 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::lint::*; -use syntax::ast::*; -use syntax::ast_util as ast_util; +use rustc_front::hir::*; +use rustc_front::util as ast_util; use syntax::ptr::P; use consts::constant; diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index da2149f0539..f3359ad0c37 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use rustc::middle::ty; use utils::{snippet, span_lint}; diff --git a/src/identity_op.rs b/src/identity_op.rs index bcdd527e407..0225c9b4d69 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::Span; use consts::{constant, is_negative}; diff --git a/src/len_zero.rs b/src/len_zero.rs index 068568cb392..c30a98d8537 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::ptr::P; use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; diff --git a/src/lib.rs b/src/lib.rs index e51732818ba..e0556972a7d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ extern crate syntax; #[macro_use] extern crate rustc; +#[macro_use] +extern crate rustc_front; // Only for the compile time checking of paths extern crate core; @@ -42,6 +44,10 @@ pub mod ranges; pub mod matches; pub mod precedence; +mod reexport { + pub use syntax::ast::{Name, Ident, NodeId}; +} + #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); diff --git a/src/lifetimes.rs b/src/lifetimes.rs index de7a39fdb3b..dccad1ffbe7 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -1,7 +1,8 @@ -use syntax::ast::*; +use rustc_front::hir::*; +use reexport::*; use rustc::lint::*; use syntax::codemap::Span; -use syntax::visit::{Visitor, walk_ty, walk_ty_param_bound}; +use rustc_front::visit::{Visitor, walk_ty, walk_ty_param_bound}; use std::collections::HashSet; use utils::{in_external_macro, span_lint}; @@ -152,7 +153,7 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize { lts.iter().collect::<HashSet<_>>().len() } -/// A visitor usable for syntax::visit::walk_ty(). +/// A visitor usable for rustc_front::visit::walk_ty(). struct RefVisitor(Vec<RefLt>); impl RefVisitor { diff --git a/src/loops.rs b/src/loops.rs index 3e1e669ea48..d40eca8c0f3 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,6 +1,7 @@ use rustc::lint::*; -use syntax::ast::*; -use syntax::visit::{Visitor, walk_expr}; +use rustc_front::hir::*; +use reexport::*; +use rustc_front::visit::{Visitor, walk_expr}; use rustc::middle::ty; use std::collections::HashSet; diff --git a/src/matches.rs b/src/matches.rs index fdc3ca5e907..5947469cd90 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,6 +1,5 @@ use rustc::lint::*; -use syntax::ast; -use syntax::ast::*; +use rustc_front::hir::*; use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; @@ -20,7 +19,7 @@ impl LintPass for MatchPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprMatch(ref ex, ref arms, ast::MatchSource::Normal) = expr.node { + if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { // check preconditions for SINGLE_MATCH // only two arms if arms.len() == 2 && diff --git a/src/methods.rs b/src/methods.rs index c6f0b1c2e59..25435274313 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,4 +1,4 @@ -use syntax::ast::*; +use rustc_front::hir::*; use rustc::lint::*; use rustc::middle::ty; use rustc::middle::subst::Subst; diff --git a/src/misc.rs b/src/misc.rs index 1376bf41b38..eb3a93941be 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,10 +1,11 @@ use rustc::lint::*; use syntax::ptr::P; -use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use rustc_front::hir::*; +use reexport::*; +use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; -use syntax::visit::FnKind; -use rustc::ast_map::Node::*; +use rustc_front::visit::FnKind; +use rustc::front::map::Node::*; use rustc::middle::ty; use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; diff --git a/src/mut_mut.rs b/src/mut_mut.rs index fbcb70e17d3..236d9b6a5a2 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::ExpnInfo; use rustc::middle::ty::{TypeAndMut, TyRef}; diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 0fe52c44189..0e8276bfafa 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use utils::{span_lint, snippet}; diff --git a/src/precedence.rs b/src/precedence.rs index 1d89adf9df8..31c28146e1e 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::span_lint; diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index bcbd8dad68a..b0d9757e6c5 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use rustc::middle::ty; use utils::{span_lint, match_type}; diff --git a/src/ranges.rs b/src/ranges.rs index 914b4daa6be..197afaf1163 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,5 +1,5 @@ use rustc::lint::{Context, LintArray, LintPass}; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::match_type; diff --git a/src/returns.rs b/src/returns.rs index 29749b29435..ea75cf562bf 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,7 +1,8 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; +use reexport::*; use syntax::codemap::{Span, Spanned}; -use syntax::visit::FnKind; +use rustc_front::visit::FnKind; use utils::{span_lint, snippet, match_path, in_external_macro}; @@ -42,8 +43,7 @@ impl ReturnPass { // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it - ExprIf(_, ref ifblock, Some(ref elsexpr)) | - ExprIfLet(_, _, ref ifblock, Some(ref elsexpr)) => { + ExprIf(_, ref ifblock, Some(ref elsexpr)) => { self.check_block_return(cx, ifblock); self.check_final_expr(cx, elsexpr); } diff --git a/src/shadow.rs b/src/shadow.rs index 7f555d4be85..aaa2c91a036 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -1,7 +1,8 @@ use std::ops::Deref; -use syntax::ast::*; +use rustc_front::hir::*; +use reexport::*; use syntax::codemap::Span; -use syntax::visit::FnKind; +use rustc_front::visit::FnKind; use rustc::lint::{Context, LintArray, LintPass}; use rustc::middle::def::Def::{DefVariant, DefStruct}; @@ -47,8 +48,7 @@ fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { match stmt.node { StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), StmtExpr(ref e, _) | StmtSemi(ref e, _) => - check_expr(cx, e, bindings), - _ => () + check_expr(cx, e, bindings) } } if let Some(ref o) = block.expr { check_expr(cx, o, bindings); } @@ -320,8 +320,7 @@ fn contains_block_self(name: Name, block: &Block) -> bool { } }, StmtExpr(ref e, _) | StmtSemi(ref e, _) => - if contains_self(name, e) { return true }, - _ => () + if contains_self(name, e) { return true } } } if let Some(ref e) = block.expr { contains_self(name, e) } else { false } diff --git a/src/strings.rs b/src/strings.rs index fc8a2d238bb..3c9c1086a12 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -4,7 +4,7 @@ //! disable the subsumed lint unless it has a higher level use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::Spanned; use eq_op::is_exp_equal; diff --git a/src/types.rs b/src/types.rs index 4a3c183462d..9fa63f1986c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,9 +1,9 @@ use rustc::lint::*; -use syntax::ast; -use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; +use rustc_front::hir::*; +use reexport::*; +use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; -use syntax::visit::{FnKind, Visitor, walk_ty}; +use rustc_front::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; @@ -24,7 +24,7 @@ impl LintPass for TypePass { lint_array!(BOX_VEC, LINKEDLIST) } - fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) { + fn check_ty(&mut self, cx: &Context, ast_ty: &Ty) { if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { if match_type(cx, inner, &VEC_PATH) { @@ -126,7 +126,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { fn is_isize_or_usize(typ: &ty::TyS) -> bool { match typ.sty { - ty::TyInt(ast::TyIs) | ty::TyUint(ast::TyUs) => true, + ty::TyInt(TyIs) | ty::TyUint(TyUs) => true, _ => false } } @@ -211,7 +211,7 @@ impl LintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = if let ty::TyFloat(ast::TyF32) = cast_to.sty {32} else {64}; + let to_nbits = if let ty::TyFloat(TyF32) = cast_to.sty {32} else {64}; if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); } @@ -235,8 +235,8 @@ impl LintPass for CastPass { check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { - if let (&ty::TyFloat(ast::TyF64), - &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) { + if let (&ty::TyFloat(TyF64), + &ty::TyFloat(TyF32)) = (&cast_from.sty, &cast_to.sty) { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may truncate the value"); @@ -320,7 +320,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) { } } -fn check_type(cx: &Context, ty: &ast::Ty) { +fn check_type(cx: &Context, ty: &Ty) { if in_external_macro(cx, ty.span) { return; } let score = { let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; @@ -343,7 +343,7 @@ struct TypeComplexityVisitor { } impl<'v> Visitor<'v> for TypeComplexityVisitor { - fn visit_ty(&mut self, ty: &'v ast::Ty) { + fn visit_ty(&mut self, ty: &'v Ty) { let (add_score, sub_nest) = match ty.node { // _, &x and *x have only small overhead; don't mess with nesting level TyInfer | diff --git a/src/unicode.rs b/src/unicode.rs index 8a64f612666..a993da1782a 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::codemap::{BytePos, Span}; use utils::span_lint; diff --git a/src/utils.rs b/src/utils.rs index 2f9b86964c2..860ad85aab9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,8 @@ use rustc::lint::*; -use syntax::ast::*; +use rustc_front::hir::*; +use reexport::*; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; -use rustc::ast_map::Node::NodeExpr; +use rustc::front::map::Node::NodeExpr; use rustc::middle::def_id::DefId; use rustc::middle::ty; use std::borrow::Cow; diff --git a/tests/consts.rs b/tests/consts.rs index 55270cc6b51..7aa42545074 100755 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -4,8 +4,9 @@ extern crate clippy; extern crate syntax; extern crate rustc; +extern crate rustc_front; -use syntax::ast::*; +use rustc_front::hir::*; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; -- cgit 1.4.1-3-g733a5 From d659d039b6b6e3c5c858baf7e2be82dfee4c35d3 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 4 Sep 2015 07:56:52 +0200 Subject: methods: allow &mut self for as_ methods --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index c6f0b1c2e59..1d0ac662c50 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -108,7 +108,7 @@ impl LintPass for MethodsPass { const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ("into_", &[ValueSelf]), ("to_", &[RefSelf]), - ("as_", &[RefSelf]), + ("as_", &[RefSelf, RefMutSelf]), ("is_", &[RefSelf, NoSelf]), ("from_", &[NoSelf]), ]; -- cgit 1.4.1-3-g733a5 From e11fd49b1cc333a4fedbe1f948e6203208edd17b Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 4 Sep 2015 09:08:07 +0200 Subject: Unicode lints, second attempt: Lint whole strings, help with replacement --- Cargo.toml | 3 +++ README.md | 3 ++- src/lib.rs | 4 +++ src/unicode.rs | 58 ++++++++++++++++++++++++++++++------------- tests/compile-fail/unicode.rs | 9 +++---- 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28fd03e5d6f..656efd312b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ keywords = ["clippy", "lint", "plugin"] name = "clippy" plugin = true +[dependencies] +unicode-normalization = "*" + [dev-dependencies] compiletest_rs = "*" regex = "*" diff --git a/README.md b/README.md index 8c00c9f901b..0046d891129 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 53 lints included in this crate: +There are 54 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -56,6 +56,7 @@ name [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop diff --git a/src/lib.rs b/src/lib.rs index e0556972a7d..a4aee0c27fd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,9 @@ extern crate rustc_front; extern crate core; extern crate collections; +// for unicode nfc normalization +extern crate unicode_normalization; + use rustc::plugin::Registry; use rustc::lint::LintPassObject; @@ -96,6 +99,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::CAST_PRECISION_LOSS, types::CAST_SIGN_LOSS, unicode::NON_ASCII_LITERAL, + unicode::UNICODE_NOT_NFC, ]); reg.register_lint_group("clippy", vec![ diff --git a/src/unicode.rs b/src/unicode.rs index a993da1782a..5e1af6f9818 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,21 +1,27 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::codemap::{BytePos, Span}; +use syntax::codemap::Span; -use utils::span_lint; +use unicode_normalization::UnicodeNormalization; + +use utils::span_help_and_lint; declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "using a zero-width space in a string literal, which is confusing" } declare_lint!{ pub NON_ASCII_LITERAL, Allow, "using any literal non-ASCII chars in a string literal; suggests \ using the \\u escape instead" } +declare_lint!{ pub UNICODE_NOT_NFC, Allow, + "using a unicode literal not in NFC normal form (see \ + http://www.unicode.org/reports/tr15/ for further information)" } + #[derive(Copy, Clone)] pub struct Unicode; impl LintPass for Unicode { fn get_lints(&self) -> LintArray { - lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL) + lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -27,23 +33,41 @@ impl LintPass for Unicode { } } -fn check_str(cx: &Context, string: &str, span: Span) { - for (i, c) in string.char_indices() { - if c == '\u{200B}' { - str_pos_lint(cx, ZERO_WIDTH_SPACE, span, i, - "zero-width space detected. Consider using `\\u{200B}`"); - } +fn escape<T: Iterator<Item=char>>(s: T) -> String { + let mut result = String::new(); + for c in s { if c as u32 > 0x7F { - str_pos_lint(cx, NON_ASCII_LITERAL, span, i, &format!( - "literal non-ASCII character detected. Consider using `\\u{{{:X}}}`", c as u32)); + for d in c.escape_unicode() { result.push(d) }; + } else { + result.push(c); } } + result } -#[allow(cast_possible_truncation)] -fn str_pos_lint(cx: &Context, lint: &'static Lint, span: Span, index: usize, msg: &str) { - span_lint(cx, lint, Span { lo: span.lo + BytePos((1 + index) as u32), - hi: span.lo + BytePos((1 + index) as u32), - expn_id: span.expn_id }, msg); - +fn check_str(cx: &Context, string: &str, span: Span) { + if string.contains('\u{200B}') { + span_help_and_lint(cx, ZERO_WIDTH_SPACE, span, + "zero-width space detected", + &format!("Consider replacing the string with:\n\"{}\"", + string.replace("\u{200B}", "\\u{200B}"))); + } + if string.chars().any(|c| c as u32 > 0x7F) { + span_help_and_lint(cx, NON_ASCII_LITERAL, span, + "literal non-ASCII character detected", + &format!("Consider replacing the string with:\n\"{}\"", + if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { + escape(string.chars()) + } else { + escape(string.nfc()) + })); + } + if string.chars().zip(string.nfc()).any(|(a, b)| a != b) { + if cx.current_level(NON_ASCII_LITERAL) == Level::Allow { + span_help_and_lint(cx, UNICODE_NOT_NFC, span, + "non-nfc unicode sequence detected", + &format!("Consider replacing the string with:\n\"{}\"", + string.nfc().collect::<String>())); + } + } } diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs index e4730f60de8..066825fc686 100755 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -4,18 +4,17 @@ #[deny(zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); - //~^ ERROR zero-width space detected. Consider using `\u{200B}` - //~^^ ERROR zero-width space detected. Consider using `\u{200B}` + //~^ ERROR zero-width space detected } -//#[deny(unicode_canon)] +#[deny(unicode_not_nfc)] fn canon() { - print!("̀ah?"); //not yet ~ERROR non-canonical unicode sequence detected. Consider using à + print!("̀àh?"); //~ERROR non-nfc unicode sequence detected } #[deny(non_ascii_literal)] fn uni() { - print!("Üben!"); //~ERROR literal non-ASCII character detected. Consider using `\u{DC}` + print!("Üben!"); //~ERROR literal non-ASCII character detected } fn main() { -- cgit 1.4.1-3-g733a5 From fb148a50b2766d1baf2a7e75474939d0f02e27ac Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 4 Sep 2015 16:27:53 +0530 Subject: Add false positive checks to unicode test --- tests/compile-fail/unicode.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs index 066825fc686..44bc9f1b199 100755 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -5,16 +5,19 @@ fn zero() { print!("Here >​< is a ZWS, and ​another"); //~^ ERROR zero-width space detected + print!("This\u{200B}is\u{200B}fine"); } #[deny(unicode_not_nfc)] fn canon() { print!("̀àh?"); //~ERROR non-nfc unicode sequence detected + print!("a\u{0300}h?"); // also okay } #[deny(non_ascii_literal)] fn uni() { print!("Üben!"); //~ERROR literal non-ASCII character detected + print!("\u{DC}ben!"); // this is okay } fn main() { -- cgit 1.4.1-3-g733a5 From 28212e4981f9a3f9eb187ed88cfdc4efbd90463f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 4 Sep 2015 14:24:49 +0200 Subject: fixed dogfood by using snippet instead of the (escaped) literal string --- src/unicode.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/unicode.rs b/src/unicode.rs index 5e1af6f9818..e745c0960ea 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -4,7 +4,7 @@ use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; -use utils::span_help_and_lint; +use utils::{snippet, span_help_and_lint}; declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "using a zero-width space in a string literal, which is confusing" } @@ -26,8 +26,8 @@ impl LintPass for Unicode { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprLit(ref lit) = expr.node { - if let LitStr(ref string, _) = lit.node { - check_str(cx, string, lit.span) + if let LitStr(_, _) = lit.node { + check_str(cx, lit.span) } } } @@ -45,7 +45,8 @@ fn escape<T: Iterator<Item=char>>(s: T) -> String { result } -fn check_str(cx: &Context, string: &str, span: Span) { +fn check_str(cx: &Context, span: Span) { + let string = snippet(cx, span, ""); if string.contains('\u{200B}') { span_help_and_lint(cx, ZERO_WIDTH_SPACE, span, "zero-width space detected", @@ -62,12 +63,11 @@ fn check_str(cx: &Context, string: &str, span: Span) { escape(string.nfc()) })); } - if string.chars().zip(string.nfc()).any(|(a, b)| a != b) { - if cx.current_level(NON_ASCII_LITERAL) == Level::Allow { - span_help_and_lint(cx, UNICODE_NOT_NFC, span, - "non-nfc unicode sequence detected", - &format!("Consider replacing the string with:\n\"{}\"", - string.nfc().collect::<String>())); - } + if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && + string.chars().zip(string.nfc()).any(|(a, b)| a != b) { + span_help_and_lint(cx, UNICODE_NOT_NFC, span, + "non-nfc unicode sequence detected", + &format!("Consider replacing the string with:\n\"{}\"", + string.nfc().collect::<String>())); } } -- cgit 1.4.1-3-g733a5 From cd91110ec0ca4f823145a13033cfd45f74ce72c6 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 5 Sep 2015 12:46:34 +0200 Subject: new lint: min_max --- README.md | 3 +- src/consts.rs | 8 ++-- src/lib.rs | 3 ++ src/minmax.rs | 90 +++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/min_max.rs | 25 ++++++++++++ 5 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 src/minmax.rs create mode 100644 tests/compile-fail/min_max.rs diff --git a/README.md b/README.md index 0046d891129..590ba60d552 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 54 lints included in this crate: +There are 55 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -31,6 +31,7 @@ name [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | deny | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` diff --git a/src/consts.rs b/src/consts.rs index a8a446a703f..5e7cd200d0f 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -121,10 +121,10 @@ impl PartialOrd for Constant { (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => Some(match (is_negative(lty) && *lv != 0, is_negative(rty) && *rv != 0) { - (true, true) => lv.cmp(rv), - (false, false) => rv.cmp(lv), - (true, false) => Greater, - (false, true) => Less, + (true, true) => rv.cmp(lv), + (false, false) => lv.cmp(rv), + (true, false) => Less, + (false, true) => Greater, }), (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => if match (lw, rw) { diff --git a/src/lib.rs b/src/lib.rs index a4aee0c27fd..7665d06b193 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub mod needless_bool; pub mod approx_const; pub mod eta_reduction; pub mod identity_op; +pub mod minmax; pub mod mut_mut; pub mod len_zero; pub mod attrs; @@ -85,6 +86,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); reg.register_lint_pass(box matches::MatchPass as LintPassObject); reg.register_lint_pass(box misc::PatternPass as LintPassObject); + reg.register_lint_pass(box minmax::MinMaxPass as LintPassObject); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -125,6 +127,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::STR_TO_STRING, methods::STRING_TO_STRING, methods::WRONG_SELF_CONVENTION, + minmax::MIN_MAX, misc::CMP_NAN, misc::CMP_OWNED, misc::FLOAT_CMP, diff --git a/src/minmax.rs b/src/minmax.rs new file mode 100644 index 00000000000..2e4c9256657 --- /dev/null +++ b/src/minmax.rs @@ -0,0 +1,90 @@ +use rustc::lint::{Context, LintPass, LintArray}; +use rustc_front::hir::*; +use syntax::codemap::Spanned; +use syntax::ptr::P; +use std::cmp::PartialOrd; +use std::cmp::Ordering::*; + +use consts::{Constant, constant}; +use utils::{match_path, span_lint}; +use self::MinMax::{Min, Max}; + +declare_lint!(pub MIN_MAX, Deny, + "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \ + to a constant"); + +#[allow(missing_copy_implementations)] +pub struct MinMaxPass; + +impl LintPass for MinMaxPass { + fn get_lints(&self) -> LintArray { + lint_array!(MIN_MAX) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { + if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { + if outer_max == inner_max { return; } + match (outer_max, outer_c.partial_cmp(&inner_c)) { + (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), + _ => { + span_lint(cx, MIN_MAX, expr.span, + "this min/max combination leads to constant result") + }, + } + } + } + } +} + +#[derive(PartialEq, Eq, Debug)] +enum MinMax { + Min, + Max, +} + +fn min_max<'e>(cx: &Context, expr: &'e Expr) -> + Option<(MinMax, Constant, &'e Expr)> { + match expr.node { + ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { + let name = ident.name; + if name == "min" { + fetch_const(cx, args, Min) + } else { + if name == "max" { + fetch_const(cx, args, Max) + } else { + None + } + } + }, + ExprCall(ref path, ref args) => { + if let &ExprPath(None, ref path) = &path.node { + if match_path(path, &["min"]) { + fetch_const(cx, args, Min) + } else { + if match_path(path, &["max"]) { + fetch_const(cx, args, Max) + } else { + None + } + } + } else { None } + }, + _ => None, + } + } + +fn fetch_const<'e>(cx: &Context, args: &'e Vec<P<Expr>>, m: MinMax) -> + Option<(MinMax, Constant, &'e Expr)> { + if args.len() != 2 { return None } + if let Some((c, _)) = constant(cx, &args[0]) { + if let None = constant(cx, &args[1]) { // otherwise ignore + Some((m, c, &args[1])) + } else { None } + } else { + if let Some((c, _)) = constant(cx, &args[1]) { + Some((m, c, &args[0])) + } else { None } + } +} diff --git a/tests/compile-fail/min_max.rs b/tests/compile-fail/min_max.rs new file mode 100644 index 00000000000..18f415ddc0b --- /dev/null +++ b/tests/compile-fail/min_max.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] + +use std::cmp::{min, max}; + +fn main() { + let x; + x = 2usize; + min(1, max(3, x)); //~ERROR this min/max combination leads to constant result + min(max(3, x), 1); //~ERROR this min/max combination leads to constant result + max(min(x, 1), 3); //~ERROR this min/max combination leads to constant result + max(3, min(x, 1)); //~ERROR this min/max combination leads to constant result + + min(3, max(1, x)); // ok, could be 1, 2 or 3 depending on x + + let s; + s = "Hello"; + + min("Apple", max("Zoo", s)); //~ERROR this min/max combination leads to constant result + max(min(s, "Apple"), "Zoo"); //~ERROR this min/max combination leads to constant result + + max("Apple", min(s, "Zoo")); // ok +} -- cgit 1.4.1-3-g733a5 From b90e4c7bd51e3193504d7acf8cfc3220933cd5ee Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 5 Sep 2015 13:15:18 +0200 Subject: hir naming, removed lookup, match full path --- src/consts.rs | 2 +- src/minmax.rs | 51 +++++++++++++++++---------------------------------- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 5e7cd200d0f..0c32dc5efad 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -154,8 +154,8 @@ impl PartialOrd for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { match *lit { LitStr(ref is, style) => ConstantStr(is.to_string(), style), - LitBinary(ref blob) => ConstantBinary(blob.clone()), LitByte(b) => ConstantByte(b), + LitByteStr(ref s) => ConstantBinary(s.clone()), LitChar(c) => ConstantChar(c), LitInt(value, ty) => ConstantInt(value, ty), LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), diff --git a/src/minmax.rs b/src/minmax.rs index 2e4c9256657..d7a74aa8c8b 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -1,11 +1,10 @@ use rustc::lint::{Context, LintPass, LintArray}; use rustc_front::hir::*; -use syntax::codemap::Spanned; use syntax::ptr::P; use std::cmp::PartialOrd; use std::cmp::Ordering::*; -use consts::{Constant, constant}; +use consts::{Constant, constant_simple}; use utils::{match_path, span_lint}; use self::MinMax::{Min, Max}; @@ -22,8 +21,8 @@ impl LintPass for MinMaxPass { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { - if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { + if let Some((outer_max, outer_c, oe)) = min_max(expr) { + if let Some((inner_max, inner_c, _)) = min_max(oe) { if outer_max == inner_max { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), @@ -43,47 +42,31 @@ enum MinMax { Max, } -fn min_max<'e>(cx: &Context, expr: &'e Expr) -> - Option<(MinMax, Constant, &'e Expr)> { - match expr.node { - ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { - let name = ident.name; - if name == "min" { - fetch_const(cx, args, Min) +fn min_max(expr: &Expr) -> Option<(MinMax, Constant, &Expr)> { + if let ExprCall(ref path, ref args) = expr.node { + if let ExprPath(None, ref path) = path.node { + if match_path(path, &["std", "cmp", "min"]) { + fetch_const(args, Min) } else { - if name == "max" { - fetch_const(cx, args, Max) + if match_path(path, &["std", "cmp", "max"]) { + fetch_const(args, Max) } else { None } } - }, - ExprCall(ref path, ref args) => { - if let &ExprPath(None, ref path) = &path.node { - if match_path(path, &["min"]) { - fetch_const(cx, args, Min) - } else { - if match_path(path, &["max"]) { - fetch_const(cx, args, Max) - } else { - None - } - } - } else { None } - }, - _ => None, - } + } else { None } + } else { None } } -fn fetch_const<'e>(cx: &Context, args: &'e Vec<P<Expr>>, m: MinMax) -> - Option<(MinMax, Constant, &'e Expr)> { +fn fetch_const(args: &[P<Expr>], m: MinMax) -> + Option<(MinMax, Constant, &Expr)> { if args.len() != 2 { return None } - if let Some((c, _)) = constant(cx, &args[0]) { - if let None = constant(cx, &args[1]) { // otherwise ignore + if let Some(c) = constant_simple(&args[0]) { + if let None = constant_simple(&args[1]) { // otherwise ignore Some((m, c, &args[1])) } else { None } } else { - if let Some((c, _)) = constant(cx, &args[1]) { + if let Some(c) = constant_simple(&args[1]) { Some((m, c, &args[0])) } else { None } } -- cgit 1.4.1-3-g733a5 From 3848756be09744d0947f7472a340764e7ecd2249 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 5 Sep 2015 14:20:35 +0200 Subject: Made min_max `Warn` by default --- src/minmax.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minmax.rs b/src/minmax.rs index d7a74aa8c8b..72190d70e2e 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -8,7 +8,7 @@ use consts::{Constant, constant_simple}; use utils::{match_path, span_lint}; use self::MinMax::{Min, Max}; -declare_lint!(pub MIN_MAX, Deny, +declare_lint!(pub MIN_MAX, Warn, "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \ to a constant"); -- cgit 1.4.1-3-g733a5 From b66bccc45a750169dadf9e93396791e32126e7c8 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 5 Sep 2015 14:22:33 +0200 Subject: update_lints --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 590ba60d552..c7071688e10 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ name [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | deny | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -- cgit 1.4.1-3-g733a5 From 79bf820170faf257e68540d43cdf40112822a87d Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 5 Sep 2015 16:24:41 +0200 Subject: added test against const lookup --- tests/compile-fail/min_max.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/compile-fail/min_max.rs b/tests/compile-fail/min_max.rs index 18f415ddc0b..5a5fae4930d 100644 --- a/tests/compile-fail/min_max.rs +++ b/tests/compile-fail/min_max.rs @@ -5,6 +5,8 @@ use std::cmp::{min, max}; +const LARGE : usize = 3; + fn main() { let x; x = 2usize; @@ -15,6 +17,8 @@ fn main() { min(3, max(1, x)); // ok, could be 1, 2 or 3 depending on x + min(1, max(LARGE, x)); // no error, we don't lookup consts here + let s; s = "Hello"; -- cgit 1.4.1-3-g733a5 From d9ecd0b9652fee465da0de13792156e1feaa0378 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 6 Sep 2015 05:47:51 +0530 Subject: bump --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 656efd312b2..9dea1c0d453 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.12" +version = "0.0.13" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 54393f0ef5ecabf43da2f4749d16eb1145ad0455 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 10:53:55 +0200 Subject: More strict macro check --- src/attrs.rs | 17 ++++++------- src/collapsible_if.rs | 11 ++++---- src/identity_op.rs | 29 ++++++++++------------ src/mut_mut.rs | 10 +++----- src/types.rs | 4 +-- src/utils.rs | 69 +++++++++++++++++++++++++++++---------------------- 6 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 05362c706f0..e6185d8b400 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; -use syntax::codemap::ExpnInfo; +use syntax::codemap::Span; use utils::{in_macro, match_path, span_lint}; @@ -21,22 +21,19 @@ impl LintPass for AttrPass { fn check_item(&mut self, cx: &Context, item: &Item) { if is_relevant_item(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + check_attrs(cx, item.span, &item.ident, &item.attrs) } } fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { if is_relevant_impl(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + check_attrs(cx, item.span, &item.ident, &item.attrs) } } fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { if is_relevant_trait(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) + check_attrs(cx, item.span, &item.ident, &item.attrs) } } } @@ -89,9 +86,9 @@ fn is_relevant_expr(expr: &Expr) -> bool { } } -fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, - attrs: &[Attribute]) { - if in_macro(cx, info) { return; } +fn check_attrs(cx: &Context, span: Span, ident: &Ident, + attrs: &[Attribute]) { + if in_macro(cx, span) { return; } for attr in attrs { if let MetaList(ref inline, ref values) = attr.node.value.node { diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 9301aafbace..7326bd20c7c 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -14,7 +14,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::codemap::{Spanned, ExpnInfo}; +use syntax::codemap::Spanned; use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; @@ -34,14 +34,13 @@ impl LintPass for CollapsibleIf { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) + if !in_macro(cx, expr.span) { + check_if(cx, expr) + } } } -fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } - +fn check_if(cx: &Context, e: &Expr) { if let ExprIf(ref check, ref then, None) = e.node { if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = single_stmt_of_block(then) { diff --git a/src/identity_op.rs b/src/identity_op.rs index 0225c9b4d69..9601a685690 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -2,9 +2,9 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use consts::{constant, is_negative}; +use consts::{constant_simple, is_negative}; use consts::Constant::ConstantInt; -use utils::{span_lint, snippet, in_external_macro}; +use utils::{span_lint, snippet, in_macro}; declare_lint! { pub IDENTITY_OP, Warn, "using identity operations, e.g. `x + 0` or `y / 1`" } @@ -18,6 +18,7 @@ impl LintPass for IdentityOp { } fn check_expr(&mut self, cx: &Context, e: &Expr) { + if in_macro(cx, e.span) { return; } if let ExprBinary(ref cmp, ref left, ref right) = e.node { match cmp.node { BiAdd | BiBitOr | BiBitXor => { @@ -44,20 +45,16 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some((c, needed_resolution)) = constant(cx, e) { - if needed_resolution { return; } // skip linting w/ lookup for now - if let ConstantInt(v, ty) = c { - if match m { - 0 => v == 0, - -1 => is_negative(ty) && v == 1, - 1 => !is_negative(ty) && v == 1, - _ => unreachable!(), - } { - if in_external_macro(cx, e.span) {return;} - span_lint(cx, IDENTITY_OP, span, &format!( - "the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, ".."))); - } + if let Some(ConstantInt(v, ty)) = constant_simple(e) { + if match m { + 0 => v == 0, + -1 => is_negative(ty) && v == 1, + 1 => !is_negative(ty) && v == 1, + _ => unreachable!(), + } { + span_lint(cx, IDENTITY_OP, span, &format!( + "the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, ".."))); } } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 236d9b6a5a2..b6260bb8ecc 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,9 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::codemap::ExpnInfo; use rustc::middle::ty::{TypeAndMut, TyRef}; -use utils::{in_macro, span_lint}; +use utils::{in_external_macro, span_lint}; declare_lint!(pub MUT_MUT, Warn, "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ @@ -18,8 +17,7 @@ impl LintPass for MutMut { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) + check_expr_mut(cx, expr) } fn check_ty(&mut self, cx: &Context, ty: &Ty) { @@ -28,8 +26,8 @@ impl LintPass for MutMut { } } -fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } +fn check_expr_mut(cx: &Context, expr: &Expr) { + if in_external_macro(cx, expr.span) { return; } fn unwrap_addr(expr : &Expr) -> Option<&Expr> { match expr.node { diff --git a/src/types.rs b/src/types.rs index 9fa63f1986c..44c0cd78148 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,7 @@ use syntax::codemap::Span; use rustc_front::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; -use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{match_type, snippet, span_lint, span_help_and_lint, in_macro, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types @@ -321,7 +321,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) { } fn check_type(cx: &Context, ty: &Ty) { - if in_external_macro(cx, ty.span) { return; } + if in_macro(cx, ty.span) { return; } let score = { let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; visitor.visit_ty(ty); diff --git a/src/utils.rs b/src/utils.rs index 860ad85aab9..33e53710df3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -14,40 +14,51 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; -/// returns true if the macro that expanded the crate was outside of -/// the current crate or was a compiler plugin -pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { - // no ExpnInfo = no macro - opt_info.map_or(false, |info| { - match info.callee.format { - ExpnFormat::CompilerExpansion(..) => { - if info.callee.name() == "closure expansion" { - return false; - } - }, - ExpnFormat::MacroAttribute(..) => { - // these are all plugins - return true; - }, - _ => (), +/// returns true this expn_info was expanded by any macro +pub fn in_macro(cx: &Context, span: Span) -> bool { + cx.sess().codemap().with_expn_info(span.expn_id, + |info| info.map_or(false, |i| { + match i.callee.format { + ExpnFormat::CompilerExpansion(..) => false, + _ => true, } - // no span for the callee = external macro - info.callee.span.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| - // macro doesn't start with "macro_rules" - // = compiler plugin - !code.starts_with("macro_rules") - ) - }) - }) + })) } -/// invokes in_macro with the expansion info of the given span -/// slightly heavy, try to use this after other checks have already happened +/// returns true if the macro that expanded the crate was outside of +/// the current crate or was a compiler plugin pub fn in_external_macro(cx: &Context, span: Span) -> bool { + /// invokes in_macro with the expansion info of the given span + /// slightly heavy, try to use this after other checks have already happened + fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + // no ExpnInfo = no macro + opt_info.map_or(false, |info| { + match info.callee.format { + ExpnFormat::CompilerExpansion(..) => { + if info.callee.name() == "closure expansion" { + return false; + } + }, + ExpnFormat::MacroAttribute(..) => { + // these are all plugins + return true; + }, + _ => (), + } + // no span for the callee = external macro + info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + // macro doesn't start with "macro_rules" + // = compiler plugin + !code.starts_with("macro_rules") + ) + }) + }) + } + cx.sess().codemap().with_expn_info(span.expn_id, - |info| in_macro(cx, info)) + |info| in_macro_ext(cx, info)) } /// check if a DefId's path matches the given absolute type path -- cgit 1.4.1-3-g733a5 From 55729b7caabca9ceac7a920ff09f0c80dc081d0a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 10:59:06 +0200 Subject: dogfooding a newly caught problem --- src/loops.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index d40eca8c0f3..099ff7910ac 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -84,12 +84,11 @@ impl LintPass for LoopsPass { } } // check for looping over Iterator::next() which is not what you want - else if method_name == "next" { - if match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { - span_lint(cx, ITER_NEXT_LOOP, expr.span, - "you are iterating over `Iterator::next()` which is an Option; \ - this will compile but is probably not what you want"); - } + else if method_name == "next" && + match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { + span_lint(cx, ITER_NEXT_LOOP, expr.span, + "you are iterating over `Iterator::next()` which is an Option; \ + this will compile but is probably not what you want"); } } } @@ -127,12 +126,11 @@ impl LintPass for LoopsPass { fn check_stmt(&mut self, cx: &Context, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.node.name == "collect" { - if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { - span_lint(cx, UNUSED_COLLECT, expr.span, &format!( - "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator")); - } + if args.len() == 1 && method.node.name == "collect" && + match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + span_lint(cx, UNUSED_COLLECT, expr.span, &format!( + "you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator")); } } } -- cgit 1.4.1-3-g733a5 From efd553c8a98ebe1799218aa05cf773f2ac57852c Mon Sep 17 00:00:00 2001 From: inrustwetrust <inrustwetrust@users.noreply.github.com> Date: Sun, 6 Sep 2015 13:36:21 +0200 Subject: Don't show the explicit_iter_loop lint for arrays with more than 32 elements The IntoIterator trait is currently not implemented for arrays with more than 32 elements, so for longer arrays, the iter() or iter_mut() methods must be used. --- src/loops.rs | 7 ++++--- tests/compile-fail/for_loop.rs | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 099ff7910ac..d1a3e4ac7ab 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -199,7 +199,7 @@ fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tcx.expr_ty(e); - is_array(ty) || + is_iterable_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || match_type(cx, ty, &["std", "collections", "hash", "map", "HashMap"]) || @@ -210,9 +210,10 @@ fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) } -fn is_array(ty: ty::Ty) -> bool { +fn is_iterable_array(ty: ty::Ty) -> bool { + //IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(..) => true, + ty::TyArray(_, 0...32) => true, _ => false } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 4d0c22fff0b..c8d1d383c78 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -42,6 +42,8 @@ fn main() { for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[ for _v in (&mut [1, 2, 3]).iter() { } // no error + for _v in [0; 32].iter() {} //~ERROR it is more idiomatic to loop over `&[ + for _v in [0; 33].iter() {} // no error let ll: LinkedList<()> = LinkedList::new(); for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll` let vd: VecDeque<()> = VecDeque::new(); -- cgit 1.4.1-3-g733a5 From b76ad366abbd8085ed1f59ed09e95886de8c1ae1 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 16:09:35 +0200 Subject: fixed bad_bit_mask false positive --- README.md | 2 +- src/bit_mask.rs | 4 ++-- tests/compile-fail/bit_masks.rs | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c7071688e10..0da19cbd620 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ There are 55 lints included in this crate: name | default | meaning -----------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | deny | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` diff --git a/src/bit_mask.rs b/src/bit_mask.rs index b1b8a735455..97d33b5e699 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -9,7 +9,7 @@ use utils::span_lint; declare_lint! { pub BAD_BIT_MASK, - Deny, + Warn, "expressions of the form `_ & mask == select` that will only ever return `true` or `false` \ (because in the example `select` containing bits that `mask` doesn't have)" } @@ -98,7 +98,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { match cmp_op { BiEq | BiNe => match bit_op { - BiBitAnd => if mask_value & cmp_value != mask_value { + BiBitAnd => if mask_value & cmp_value != cmp_value { if cmp_value != 0 { span_lint(cx, BAD_BIT_MASK, *span, &format!( "incompatible bit mask: `_ & {}` can never be equal to `{}`", diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index 47e9c11138a..0b7b31b64a5 100755 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -25,6 +25,9 @@ fn main() { x | 2 > 1; //~ERROR incompatible bit mask x | 2 <= 2; // ok (if a bit silly), equals x <= 2 + x & 192 == 128; // ok, tests for bit 7 and not bit 6 + x & 0xffc0 == 0xfe80; // ok + // this also now works with constants x & THREE_BITS == 8; //~ERROR incompatible bit mask x | EVEN_MORE_REDIRECTION < 7; //~ERROR incompatible bit mask -- cgit 1.4.1-3-g733a5 From 0c74304f7b4351d6fb27b9c206ec25476c0228f3 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 19:41:09 +0200 Subject: macro check for unit_cmp --- src/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.rs b/src/types.rs index 44c0cd78148..6586ce2c703 100644 --- a/src/types.rs +++ b/src/types.rs @@ -85,6 +85,7 @@ impl LintPass for UnitCmp { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if in_macro(expr) { return; } if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; let sty = &cx.tcx.expr_ty(left).sty; -- cgit 1.4.1-3-g733a5 From 391a5135e88afe2e6f86319db45b96262f350c4d Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 19:44:54 +0200 Subject: fixed build --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 6586ce2c703..6d096e18b88 100644 --- a/src/types.rs +++ b/src/types.rs @@ -85,7 +85,7 @@ impl LintPass for UnitCmp { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if in_macro(expr) { return; } + if in_macro(cx, expr.span) { return; } if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; let sty = &cx.tcx.expr_ty(left).sty; -- cgit 1.4.1-3-g733a5 From 87e6099ad7eb145c8fb2704d267eeaa3fdba2a2f Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 20:57:06 +0200 Subject: fix false positive len_zero in is_empty() --- src/len_zero.rs | 22 +++++++++++++--------- src/misc.rs | 21 ++++++--------------- src/utils.rs | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index c30a98d8537..206f18217d1 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,7 +5,7 @@ use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use utils::{span_lint, walk_ptrs_ty, snippet}; +use utils::{snippet, span_lint, walk_ptrs_ty, with_item_name}; declare_lint!(pub LEN_ZERO, Warn, "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ @@ -33,14 +33,14 @@ impl LintPass for LenZero { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = - &expr.node { - match cmp { - BiEq => check_cmp(cx, expr.span, left, right, ""), - BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), - _ => () - } + if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = + expr.node { + match cmp { + BiEq => check_cmp(cx, expr.span, left, right, ""), + BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + _ => () } + } } } @@ -89,7 +89,11 @@ fn is_self_sig(sig: &MethodSig) -> bool { false } else { sig.decl.inputs.len() == 1 } } -fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { +fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { + // check if we are in an is_empty() method + if let Some(true) = with_item_name(cx, left, |n| n == "is_empty") { + return; + } match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => check_len_zero(cx, span, method, args, lit, op), diff --git a/src/misc.rs b/src/misc.rs index eb3a93941be..87cc512f819 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -5,10 +5,9 @@ use reexport::*; use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; use rustc_front::visit::FnKind; -use rustc::front::map::Node::*; use rustc::middle::ty; -use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; +use utils::{match_path, snippet, span_lint, walk_ptrs_ty, with_item_name}; use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, @@ -93,19 +92,11 @@ impl LintPass for FloatCmp { false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { return; } - let parent_id = cx.tcx.map.get_parent(expr.id); - match cx.tcx.map.find(parent_id) { - Some(NodeItem(&Item{ ref ident, .. })) | - Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | - Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { - let name = ident.name.as_str(); - if &*name == "eq" || &*name == "ne" || - name.starts_with("eq_") || - name.ends_with("_eq") { - return; - } - }, - _ => (), + if let Some(true) = with_item_name(cx, expr, |name| + name == "eq" || name == "ne" || + name.as_str().starts_with("eq_") || + name.as_str().ends_with("_eq")) { + return; } span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-comparison of f32 or f64 detected. Consider changing this to \ diff --git a/src/utils.rs b/src/utils.rs index 33e53710df3..c781b74b359 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; -use rustc::front::map::Node::NodeExpr; +use rustc::front::map::Node::*; use rustc::middle::def_id::DefId; use rustc::middle::ty; use std::borrow::Cow; @@ -100,6 +100,19 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { |(a, b)| &a.identifier.name == b) } +pub fn with_item_name<T, F>(cx: &Context, expr: &Expr, f: F) -> Option<T> +where F: FnOnce(Name) -> T { + let parent_id = cx.tcx.map.get_parent(expr.id); + match cx.tcx.map.find(parent_id) { + Some(NodeItem(&Item{ ref ident, .. })) | + Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | + Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { + Some(f(ident.name)) + }, + _ => None, + } +} + /// convert a span to a code snippet if available, otherwise use default, e.g. /// `snippet(cx, expr.span, "..")` pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { -- cgit 1.4.1-3-g733a5 From 468b410d04a486bf9208be5136feee93d3818c21 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 6 Sep 2015 21:03:09 +0200 Subject: de-closured the item name getter --- src/len_zero.rs | 6 +++--- src/misc.rs | 13 +++++++------ src/utils.rs | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 206f18217d1..45b9c844af3 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,7 +5,7 @@ use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use utils::{snippet, span_lint, walk_ptrs_ty, with_item_name}; +use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; declare_lint!(pub LEN_ZERO, Warn, "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ @@ -91,8 +91,8 @@ fn is_self_sig(sig: &MethodSig) -> bool { fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { // check if we are in an is_empty() method - if let Some(true) = with_item_name(cx, left, |n| n == "is_empty") { - return; + if let Some(name) = get_item_name(cx, left) { + if name == "is_empty" { return; } } match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => diff --git a/src/misc.rs b/src/misc.rs index 87cc512f819..8891b000b59 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,7 +7,7 @@ use syntax::codemap::{Span, Spanned}; use rustc_front::visit::FnKind; use rustc::middle::ty; -use utils::{match_path, snippet, span_lint, walk_ptrs_ty, with_item_name}; +use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty}; use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, @@ -92,11 +92,12 @@ impl LintPass for FloatCmp { false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { return; } - if let Some(true) = with_item_name(cx, expr, |name| - name == "eq" || name == "ne" || - name.as_str().starts_with("eq_") || - name.as_str().ends_with("_eq")) { - return; + if let Some(name) = get_item_name(cx, expr) { + if name == "eq" || name == "ne" || + name.as_str().starts_with("eq_") || + name.as_str().ends_with("_eq") { + return; + } } span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-comparison of f32 or f64 detected. Consider changing this to \ diff --git a/src/utils.rs b/src/utils.rs index c781b74b359..d6e529048c9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -100,14 +100,14 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { |(a, b)| &a.identifier.name == b) } -pub fn with_item_name<T, F>(cx: &Context, expr: &Expr, f: F) -> Option<T> -where F: FnOnce(Name) -> T { +/// get the name of the item the expression is in, if available +pub fn get_item_name(cx: &Context, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { Some(NodeItem(&Item{ ref ident, .. })) | Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { - Some(f(ident.name)) + Some(ident.name) }, _ => None, } -- cgit 1.4.1-3-g733a5 From 92b04cd75db905dcb21ffabf10c005560c4e0f80 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 7 Sep 2015 09:17:45 +0200 Subject: split wrong_self_convention in pub/default visibility part --- README.md | 119 +++++++++++++++++++++++++++++---------------------------- src/lib.rs | 1 + src/methods.rs | 10 ++++- 3 files changed, 70 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 0da19cbd620..060eac942ba 100644 --- a/README.md +++ b/README.md @@ -4,65 +4,66 @@ A collection of lints that give helpful tips to newbies and catch oversights. ##Lints -There are 55 lints included in this crate: - -name | default | meaning ------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) -[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases -[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` -[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function -[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator -[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | warn | The name is re-bound without even using the original value -[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` -[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) -[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) -[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) -[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop -[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing +There are 56 lints included in this crate: + +name | default | meaning +-------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) +[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` +[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | warn | The name is re-bound without even using the original value +[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` +[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) +[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/lib.rs b/src/lib.rs index 7665d06b193..fdb0f975109 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, + methods::WRONG_PUB_SELF_CONVENTION, ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, diff --git a/src/methods.rs b/src/methods.rs index 4f64f0f7a94..c3ad4762873 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -27,6 +27,9 @@ declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, declare_lint!(pub WRONG_SELF_CONVENTION, Warn, "defining a method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); +declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, + "defining a public method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { @@ -93,7 +96,12 @@ impl LintPass for MethodsPass { for &(prefix, self_kinds) in &CONVENTIONS { if name.as_str().starts_with(prefix) && !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { - span_lint(cx, WRONG_SELF_CONVENTION, sig.explicit_self.span, &format!( + let lint = if let Visibility::Public = item.vis { + WRONG_PUB_SELF_CONVENTION + } else { + WRONG_SELF_CONVENTION + }; + span_lint(cx, lint, sig.explicit_self.span, &format!( "methods called `{}*` usually take {}; consider choosing a less \ ambiguous name", prefix, &self_kinds.iter().map(|k| k.description()).collect::<Vec<_>>().join(" or "))); -- cgit 1.4.1-3-g733a5 From c79d8844501e7fe92bcabbf2da2024b35d1682f7 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 7 Sep 2015 11:46:04 +0200 Subject: replace if let by equality check --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index c3ad4762873..b9132399652 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -96,7 +96,7 @@ impl LintPass for MethodsPass { for &(prefix, self_kinds) in &CONVENTIONS { if name.as_str().starts_with(prefix) && !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { - let lint = if let Visibility::Public = item.vis { + let lint = if item.VI's == Visibility::Public { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION -- cgit 1.4.1-3-g733a5 From e43f2d7e5480272e75b7583ffbfab4293715cda1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 7 Sep 2015 11:49:35 +0200 Subject: damn autocorrect --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index b9132399652..b110d92e7f8 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -96,7 +96,7 @@ impl LintPass for MethodsPass { for &(prefix, self_kinds) in &CONVENTIONS { if name.as_str().starts_with(prefix) && !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { - let lint = if item.VI's == Visibility::Public { + let lint = if item.vis == Visibility::Public { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION -- cgit 1.4.1-3-g733a5 From 0e658afc1bd3447e1f10a5cb67002512ea45ba3c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 8 Sep 2015 02:28:15 +0530 Subject: Fix mut_mut false positive, make Allow (fixes #309) --- README.md | 2 +- src/lib.rs | 2 +- src/mut_mut.rs | 3 +-- tests/compile-fail/mut_mut.rs | 7 +++++++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 060eac942ba..ca96e496bfe 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ name [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | warn | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do diff --git a/src/lib.rs b/src/lib.rs index fdb0f975109..7ce2be97358 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, + mut_mut::MUT_MUT, ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, @@ -135,7 +136,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, - mut_mut::MUT_MUT, needless_bool::NEEDLESS_BOOL, precedence::PRECEDENCE, ranges::RANGE_STEP_BY_ZERO, diff --git a/src/mut_mut.rs b/src/mut_mut.rs index b6260bb8ecc..d3270861870 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -4,7 +4,7 @@ use rustc::middle::ty::{TypeAndMut, TyRef}; use utils::{in_external_macro, span_lint}; -declare_lint!(pub MUT_MUT, Warn, +declare_lint!(pub MUT_MUT, Allow, "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ or shows a fundamental misunderstanding of references)"); @@ -53,7 +53,6 @@ fn check_expr_mut(cx: &Context, expr: &Expr) { fn unwrap_mut(ty : &Ty) -> Option<&Ty> { match ty.node { - TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), _ => Option::None } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 8aa47769539..2560a54c0ef 100755 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -1,6 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(unused)] + //#![plugin(regex_macros)] //extern crate regex; @@ -9,6 +11,11 @@ fn fun(x : &mut &mut u32) -> bool { //~ERROR generally you want to avoid `&mut & **x > 0 } +#[deny(mut_mut)] +fn less_fun(x : *mut *mut u32) { + let y = x; +} + macro_rules! mut_ptr { ($p:expr) => { &mut $p } } -- cgit 1.4.1-3-g733a5 From 4835372df559ff2e14edcdba409f5a6566a779bc Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 8 Sep 2015 11:50:04 +0200 Subject: made shadow_unrelated allow, added previous binding span note, fixed #319 --- README.md | 2 +- src/lib.rs | 2 +- src/shadow.rs | 55 ++++++++++++++++++++++++++++---------------- tests/compile-fail/shadow.rs | 5 ++++ 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ca96e496bfe..fdd341efa45 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ name [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | warn | The name is re-bound without even using the original value +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value [should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` diff --git a/src/lib.rs b/src/lib.rs index 7ce2be97358..ddaa3bf490c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::CAST_POSSIBLE_TRUNCATION, @@ -141,7 +142,6 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, - shadow::SHADOW_UNRELATED, types::BOX_VEC, types::LET_UNIT_VALUE, types::LINKEDLIST, diff --git a/src/shadow.rs b/src/shadow.rs index aaa2c91a036..ae1eeee2401 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -4,7 +4,7 @@ use reexport::*; use syntax::codemap::Span; use rustc_front::visit::FnKind; -use rustc::lint::{Context, LintArray, LintPass}; +use rustc::lint::{Context, Level, Lint, LintArray, LintPass}; use rustc::middle::def::Def::{DefVariant, DefStruct}; use utils::{in_external_macro, snippet, span_lint, span_note_and_lint}; @@ -14,7 +14,7 @@ declare_lint!(pub SHADOW_SAME, Allow, declare_lint!(pub SHADOW_REUSE, Allow, "rebinding a name to an expression that re-uses the original value, e.g. \ `let x = x + 1`"); -declare_lint!(pub SHADOW_UNRELATED, Warn, +declare_lint!(pub SHADOW_UNRELATED, Allow, "The name is re-bound without even using the original value"); #[derive(Copy, Clone)] @@ -36,13 +36,13 @@ fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { if let PatIdent(_, ident, _) = arg.pat.node { - bindings.push(ident.node.name) + bindings.push((ident.node.name, ident.span)) } } check_block(cx, block, &mut bindings); } -fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { +fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<(Name, Span)>) { let len = bindings.len(); for stmt in &block.stmts { match stmt.node { @@ -55,7 +55,7 @@ fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) { bindings.truncate(len); } -fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) { +fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; @@ -77,16 +77,23 @@ fn is_binding(cx: &Context, pat: &Pat) -> bool { } fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, - bindings: &mut Vec<Name>) { + bindings: &mut Vec<(Name, Span)>) { //TODO: match more stuff / destructuring match pat.node { PatIdent(_, ref ident, ref inner) => { let name = ident.node.name; if is_binding(cx, pat) { - if bindings.contains(&name) { - lint_shadow(cx, name, span, pat.span, init); - } else { - bindings.push(name); + let mut new_binding = true; + for tup in bindings.iter_mut() { + if tup.0 == name { + lint_shadow(cx, name, span, pat.span, init, tup.1); + tup.1 = ident.span; + new_binding = false; + break; + } + } + if new_binding { + bindings.push((name, ident.span)); } } if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } @@ -141,20 +148,25 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, }, PatRegion(ref inner, _) => check_pat(cx, inner, init, span, bindings), - //PatRange(P<Expr>, P<Expr>), //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), _ => (), } } fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: - &Option<T>) where T: Deref<Target=Expr> { + &Option<T>, prev_span: Span) where T: Deref<Target=Expr> { + fn note_orig(cx: &Context, lint: &'static Lint, span: Span) { + if cx.current_level(lint) != Level::Allow { + cx.sess().span_note(span, "previous binding is here"); + } + } if let Some(ref expr) = *init { if is_self_shadow(name, expr) { span_lint(cx, SHADOW_SAME, span, &format!( "{} is shadowed by itself in {}", snippet(cx, lspan, "_"), snippet(cx, expr.span, ".."))); + note_orig(cx, SHADOW_SAME, prev_span); } else { if contains_self(name, expr) { span_note_and_lint(cx, SHADOW_REUSE, lspan, &format!( @@ -162,21 +174,24 @@ fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); + note_orig(cx, SHADOW_REUSE, prev_span); } else { span_note_and_lint(cx, SHADOW_UNRELATED, lspan, &format!( "{} is shadowed by {}", snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); + note_orig(cx, SHADOW_UNRELATED, prev_span); } } } else { span_lint(cx, SHADOW_UNRELATED, span, &format!( "{} shadows a previous declaration", snippet(cx, lspan, "_"))); + note_orig(cx, SHADOW_UNRELATED, prev_span); } } -fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { +fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, expr.span) { return; } match expr.node { ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | @@ -205,20 +220,20 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) { for ref arm in arms { for ref pat in &arm.pats { check_pat(cx, &pat, &Some(&**init), pat.span, bindings); - //TODO: This is ugly, but needed to get the right type - } - if let Some(ref guard) = arm.guard { - check_expr(cx, guard, bindings); + //This is ugly, but needed to get the right type + if let Some(ref guard) = arm.guard { + check_expr(cx, guard, bindings); + } + check_expr(cx, &arm.body, bindings); + bindings.truncate(len); } - check_expr(cx, &arm.body, bindings); - bindings.truncate(len); } }, _ => () } } -fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<Name>) { +fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { match ty.node { TyParen(ref sty) | TyObjectSum(ref sty, _) | TyVec(ref sty) => check_ty(cx, sty, bindings), diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index 80d48f84163..293d97a42fa 100755 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -27,4 +27,9 @@ fn main() { Some(p) => p, // no error, because the p above is in its own scope None => 0, }; + + match (x, o) { + (1, Some(a)) | (a, Some(1)) => (), // no error though `a` appears twice + _ => (), + } } -- cgit 1.4.1-3-g733a5 From ce6ea58de0991df4e3144ccdd5659018ea5d4ead Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 10 Sep 2015 07:01:28 +0530 Subject: add cargo clippy link --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fdd341efa45..3e048c7ed07 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ A collection of lints that give helpful tips to newbies and catch oversights. +[Jump to usage instructions](#usage) + ##Lints There are 56 lints included in this crate: @@ -77,6 +79,8 @@ Add in your `Cargo.toml`: clippy = "*" ``` +You may also use [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), a custom cargo subcommand that runs clippy on a given project. + Sample `main.rs`: ```rust #![feature(plugin)] @@ -93,7 +97,7 @@ fn main(){ } ``` -Produce this warning: +Produces this warning: ``` src/main.rs:8:5: 11:6 warning: you seem to be trying to use match for destructuring a single type. Consider using `if let`, #[warn(single_match)] on by default src/main.rs:8 match x { -- cgit 1.4.1-3-g733a5 From f7ec0ef16c69ce29749a9b95e8e1b8fcc7292471 Mon Sep 17 00:00:00 2001 From: Alex Burka <durka42+github@gmail.com> Date: Thu, 10 Sep 2015 02:06:52 -0400 Subject: add warning about different rustc versions Ref #322. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3e048c7ed07..316ed8e2372 100644 --- a/README.md +++ b/README.md @@ -122,5 +122,7 @@ in your code, you can use: cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy ``` +Be sure that clippy was compiled with the same version of rustc that cargo invokes here! + ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 7b13a7b5e68118b6fc956e62a40d86a05df2a5da Mon Sep 17 00:00:00 2001 From: Alex Burka <durka42+github@gmail.com> Date: Thu, 10 Sep 2015 02:26:15 -0400 Subject: link to wiki --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 316ed8e2372..813d18683d5 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ in your code, you can use: cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy ``` -Be sure that clippy was compiled with the same version of rustc that cargo invokes here! +*[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 0e1bc74683c7901f8432499eccb890f9f6b29ad9 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 10 Sep 2015 08:51:14 +0200 Subject: additional macro check + more tests --- src/types.rs | 4 ++-- tests/compile-fail/let_unit.rs | 12 ++++++++++++ tests/compile-fail/unit_cmp.rs | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/types.rs b/src/types.rs index 6d096e18b88..08a8560fcd6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -50,12 +50,12 @@ pub struct LetPass; declare_lint!(pub LET_UNIT_VALUE, Warn, "creating a let binding to a value of unit type, which usually can't be used afterwards"); - fn check_let_unit(cx: &Context, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { - if in_external_macro(cx, decl.span) { return; } + if in_external_macro(cx, decl.span) || + in_macro(cx, local.pat.span) { return; } span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( "this let-binding has unit value. Consider omitting `let {} =`", snippet(cx, local.pat.span, ".."))); diff --git a/tests/compile-fail/let_unit.rs b/tests/compile-fail/let_unit.rs index f06a10bfe13..a0143406e52 100755 --- a/tests/compile-fail/let_unit.rs +++ b/tests/compile-fail/let_unit.rs @@ -2,6 +2,13 @@ #![plugin(clippy)] #![deny(let_unit_value)] +#![allow(unused_variables)] + +macro_rules! let_and_return { + ($n:expr) => {{ + let ret = $n; + }} +} fn main() { let _x = println!("x"); //~ERROR this let-binding has unit value @@ -10,4 +17,9 @@ fn main() { if true { let _a = (); //~ERROR this let-binding has unit value } + + let_and_return!(()) // should be fine } + +#[derive(Copy, Clone)] +pub struct ContainsUnit(()); // should be fine diff --git a/tests/compile-fail/unit_cmp.rs b/tests/compile-fail/unit_cmp.rs index e246d9f3909..af28f849e8c 100755 --- a/tests/compile-fail/unit_cmp.rs +++ b/tests/compile-fail/unit_cmp.rs @@ -3,6 +3,9 @@ #![deny(unit_cmp)] +#[derive(PartialEq)] +pub struct ContainsUnit(()); // should be fine + fn main() { // this is fine if true == false { -- cgit 1.4.1-3-g733a5 From 681bce925f92eaebc5ae3fc40a6a4a8720e46790 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 11 Sep 2015 15:30:08 +0200 Subject: less false positives for approx_const and float_cmp --- src/approx_const.rs | 10 +++++++++- src/misc.rs | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index a132bc90361..9a3d46c14bb 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,8 +1,9 @@ use rustc::lint::*; +use rustc::metadata::cstore::crate_metadata; use rustc_front::hir::*; use syntax::codemap::Span; +use std::borrow::Borrow; use std::f64::consts as f64; - use utils::span_lint; declare_lint! { @@ -31,6 +32,13 @@ impl LintPass for ApproxConstant { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let &ExprLit(ref lit) = &e.node { + if let Some(res) = cx.tcx.def_map.borrow().get(&e.id) { + let krate = res.def_id().krate; + let cdata = &cx.sess().cstore.get_crate_data(krate); + let crate_data : &crate_metadata = cdata.borrow(); + let name = &crate_data.name; + if name == "f32" || name == "f64" { return; } + } check_lit(cx, lit, e.span); } } diff --git a/src/misc.rs b/src/misc.rs index 8891b000b59..2cd6babb9c5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -93,7 +93,7 @@ impl LintPass for FloatCmp { return; } if let Some(name) = get_item_name(cx, expr) { - if name == "eq" || name == "ne" || + if name == "eq" || name == "ne" || name == "is_nan" || name.as_str().starts_with("eq_") || name.as_str().ends_with("_eq") { return; -- cgit 1.4.1-3-g733a5 From 03af82afd162a7516796097710ab5dc4dd48acf3 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 11 Sep 2015 15:59:19 +0200 Subject: removed expensive crate check from approx_const --- src/approx_const.rs | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 9a3d46c14bb..29631b6852f 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,8 +1,5 @@ use rustc::lint::*; -use rustc::metadata::cstore::crate_metadata; use rustc_front::hir::*; -use syntax::codemap::Span; -use std::borrow::Borrow; use std::f64::consts as f64; use utils::span_lint; @@ -32,36 +29,28 @@ impl LintPass for ApproxConstant { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let &ExprLit(ref lit) = &e.node { - if let Some(res) = cx.tcx.def_map.borrow().get(&e.id) { - let krate = res.def_id().krate; - let cdata = &cx.sess().cstore.get_crate_data(krate); - let crate_data : &crate_metadata = cdata.borrow(); - let name = &crate_data.name; - if name == "f32" || name == "f64" { return; } - } - check_lit(cx, lit, e.span); + check_lit(cx, lit, e); } } } -fn check_lit(cx: &Context, lit: &Lit, span: Span) { +fn check_lit(cx: &Context, lit: &Lit, e: &Expr) { match lit.node { - LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), - LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), + LitFloat(ref str, TyF32) => check_known_consts(cx, e, str, "f32"), + LitFloat(ref str, TyF64) => check_known_consts(cx, e, str, "f64"), LitFloatUnsuffixed(ref str) => - check_known_consts(cx, span, str, "f{32, 64}"), + check_known_consts(cx, e, str, "f{32, 64}"), _ => () } } -fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { +fn check_known_consts(cx: &Context, e: &Expr, str: &str, module: &str) { if let Ok(value) = str.parse::<f64>() { for &(constant, name) in KNOWN_CONSTS { - if within_epsilon(constant, value) { - span_lint(cx, APPROX_CONSTANT, span, &format!( - "approximate value of `{}::{}` found. \ - Consider using it directly", module, &name)); - } + if !within_epsilon(constant, value) { continue; } + span_lint(cx, APPROX_CONSTANT, e.span, &format!( + "approximate value of `{}::{}` found. \ + Consider using it directly", module, &name)); } } } -- cgit 1.4.1-3-g733a5 From 82c524b7747d0df2e92a088708795771872ca8ff Mon Sep 17 00:00:00 2001 From: swgillespie <sean.william.g@gmail.com> Date: Mon, 14 Sep 2015 17:19:05 -0700 Subject: implement empty range lint as described in #330 --- README.md | 3 ++- src/lib.rs | 1 + src/loops.rs | 38 ++++++++++++++++++++++++++++++++++++-- tests/compile-fail/for_loop.rs | 14 +++++++++++++- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 813d18683d5..ae711357901 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. [Jump to usage instructions](#usage) ##Lints -There are 56 lints included in this crate: +There are 57 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -48,6 +48,7 @@ name [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` [shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value diff --git a/src/lib.rs b/src/lib.rs index ddaa3bf490c..9cb9eb30561 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, + loops::REVERSE_RANGE_LOOP, loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, matches::MATCH_REF_PATS, diff --git a/src/loops.rs b/src/loops.rs index d1a3e4ac7ab..3b719481217 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -25,13 +25,16 @@ declare_lint!{ pub UNUSED_COLLECT, Warn, "`collect()`ing an iterator without using the result; this is usually better \ written as a for loop" } +declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, + "Iterating over an empty range, such as `10..0` or `5..5`" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP, UNUSED_COLLECT) + WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -69,6 +72,37 @@ impl LintPass for LoopsPass { } } + // if this for-loop is iterating over a two-sided range... + if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { + // and both sides are literals... + if let ExprLit(ref start_lit) = start_expr.node { + if let ExprLit(ref stop_lit) = stop_expr.node { + // and they are both integers... + if let LitInt(start_idx, _) = start_lit.node { + if let LitInt(stop_idx, _) = stop_lit.node { + // and the start index is greater than the stop index, + // this loop will never run. This is often confusing for developers + // who think that this will iterate from the larger value to the + // smaller value. + if start_idx > stop_idx { + span_lint(cx, REVERSE_RANGE_LOOP, expr.span, &format!( + "this range is empty and this for loop will never run. \ + Consider using `({}..{}).rev()` if you are attempting to \ + iterate over this range in reverse", stop_idx, start_idx)); + } + + // if they are equal, it's also problematic - this loop + // will never run. + if start_idx == stop_idx { + span_lint(cx, REVERSE_RANGE_LOOP, expr.span, + "this range is empty and this for loop will never run"); + } + } + } + } + } + } + if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { @@ -126,7 +160,7 @@ impl LintPass for LoopsPass { fn check_stmt(&mut self, cx: &Context, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.node.name == "collect" && + if args.len() == 1 && method.node.name == "collect" && match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { span_lint(cx, UNUSED_COLLECT, expr.span, &format!( "you are collect()ing an iterator and throwing away the result. \ diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index c8d1d383c78..d84b70025b8 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -14,7 +14,7 @@ impl Unrelated { } } -#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop)] +#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop)] #[deny(unused_collect)] #[allow(linkedlist)] fn main() { @@ -34,6 +34,18 @@ fn main() { println!("{}", vec[i]); } + for i in 10..0 { //~ERROR this range is empty and this for loop will never run. Consider using `(0..10).rev()` + println!("{}", i); + } + + for i in 5..5 { //~ERROR this range is empty and this for loop will never run + println!("{}", i); + } + + for i in 0..10 { // not an error, the start index is less than the end index + println!("{}", i); + } + for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec` for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec` -- cgit 1.4.1-3-g733a5 From bc7d25285600f497206d0b1f911534eb038ca81d Mon Sep 17 00:00:00 2001 From: swgillespie <sean.william.g@gmail.com> Date: Mon, 14 Sep 2015 22:20:56 -0700 Subject: use the constant folder to generalize the lint a little bit and clean up the code. Add additional tests for things that should not be linted --- src/loops.rs | 44 ++++++++++++++++++------------------------ tests/compile-fail/for_loop.rs | 39 +++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 3b719481217..286b51ab04e 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -3,6 +3,7 @@ use rustc_front::hir::*; use reexport::*; use rustc_front::visit::{Visitor, walk_expr}; use rustc::middle::ty; +use consts::{constant_simple, Constant}; use std::collections::HashSet; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, @@ -72,32 +73,25 @@ impl LintPass for LoopsPass { } } - // if this for-loop is iterating over a two-sided range... + // if this for loop is iterating over a two-sided range... if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { - // and both sides are literals... - if let ExprLit(ref start_lit) = start_expr.node { - if let ExprLit(ref stop_lit) = stop_expr.node { - // and they are both integers... - if let LitInt(start_idx, _) = start_lit.node { - if let LitInt(stop_idx, _) = stop_lit.node { - // and the start index is greater than the stop index, - // this loop will never run. This is often confusing for developers - // who think that this will iterate from the larger value to the - // smaller value. - if start_idx > stop_idx { - span_lint(cx, REVERSE_RANGE_LOOP, expr.span, &format!( - "this range is empty and this for loop will never run. \ - Consider using `({}..{}).rev()` if you are attempting to \ - iterate over this range in reverse", stop_idx, start_idx)); - } - - // if they are equal, it's also problematic - this loop - // will never run. - if start_idx == stop_idx { - span_lint(cx, REVERSE_RANGE_LOOP, expr.span, - "this range is empty and this for loop will never run"); - } - } + // ...and both sides are compile-time constant integers... + if let Some(Constant::ConstantInt(start_idx, _)) = constant_simple(start_expr) { + if let Some(Constant::ConstantInt(stop_idx, _)) = constant_simple(stop_expr) { + // ...and the start index is greater than the stop index, + // this loop will never run. This is often confusing for developers + // who think that this will iterate from the larger value to the + // smaller value. + if start_idx > stop_idx { + span_help_and_lint(cx, REVERSE_RANGE_LOOP, expr.span, + "this range is empty so this for loop will never run", + &format!("Consider using `({}..{}).rev()` if you are attempting to \ + iterate over this range in reverse", stop_idx, start_idx)); + } else if start_idx == stop_idx { + // if they are equal, it's also problematic - this loop + // will never run. + span_lint(cx, REVERSE_RANGE_LOOP, expr.span, + "this range is empty so this for loop will never run"); } } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index d84b70025b8..882373e0216 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -34,11 +34,11 @@ fn main() { println!("{}", vec[i]); } - for i in 10..0 { //~ERROR this range is empty and this for loop will never run. Consider using `(0..10).rev()` + for i in 10..0 { //~ERROR this range is empty so this for loop will never run println!("{}", i); } - for i in 5..5 { //~ERROR this range is empty and this for loop will never run + for i in 5..5 { //~ERROR this range is empty so this for loop will never run println!("{}", i); } @@ -46,6 +46,41 @@ fn main() { println!("{}", i); } + for i in (10..0).rev() { // not an error, this is an established idiom for looping backwards on a range + println!("{}", i); + } + + for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range + println!("{}", i); + } + + // testing that the empty range lint folds constants + for i in 10..5+4 { //~ERROR this range is empty so this for loop will never run + println!("{}", i); + } + + for i in (5+2)..(3-1) { //~ERROR this range is empty so this for loop will never run + println!("{}", i); + } + + for i in (5+2)..(8-1) { //~ERROR this range is empty so this for loop will never run + println!("{}", i); + } + + for i in (2*2)..(2*3) { // no error, 4..6 is fine + println!("{}", i); + } + + let x = 42; + for i in x..10 { // no error, not constant-foldable + println!("{}", i); + } + + /* + for i in (10..0).map(|x| x * 2) { + println!("{}", i); + }*/ + for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec` for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec` -- cgit 1.4.1-3-g733a5 From 5c5d10340573bbddd6447322eacd18f2e3d49207 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 15 Sep 2015 09:12:58 +0200 Subject: added fp test against negative .step_by(_) --- tests/compile-fail/for_loop.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 882373e0216..a43ed7faa23 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin)] +#![feature(plugin, step_by)] #![plugin(clippy)] use std::collections::*; @@ -71,6 +71,10 @@ fn main() { println!("{}", i); } + for i in (10..8).step_by(-1) { + println!("{}", i); + } + let x = 42; for i in x..10 { // no error, not constant-foldable println!("{}", i); -- cgit 1.4.1-3-g733a5 From f87dd31f30c2e5f731a2408b0da18f43fbc34c6f Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Sun, 23 Aug 2015 13:25:45 -0400 Subject: New lint: loop with explicit counter variable (fixes #159) Avoiding false positives here turns out to be fairly complicated. --- README.md | 3 +- src/lib.rs | 1 + src/loops.rs | 229 ++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/for_loop.rs | 64 +++++++++++- 4 files changed, 291 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ae711357901..011078c5407 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. [Jump to usage instructions](#usage) ##Lints -There are 57 lints included in this crate: +There are 58 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -21,6 +21,7 @@ name [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` diff --git a/src/lib.rs b/src/lib.rs index 9cb9eb30561..b88d2c844b0 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,7 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, + loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, diff --git a/src/loops.rs b/src/loops.rs index 286b51ab04e..a381737fe3b 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,10 +1,12 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; -use rustc_front::visit::{Visitor, walk_expr}; +use rustc_front::visit::{Visitor, walk_expr, walk_block, walk_decl}; use rustc::middle::ty; +use rustc::middle::def::DefLocal; use consts::{constant_simple, Constant}; -use std::collections::HashSet; +use rustc::front::map::Node::{NodeBlock}; +use std::collections::{HashSet,HashMap}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint}; @@ -29,13 +31,16 @@ declare_lint!{ pub UNUSED_COLLECT, Warn, declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, "Iterating over an empty range, such as `10..0` or `5..5`" } +declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, + "for-looping with an explicit counter when `_.enumerate()` would do" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP) + WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP) } fn check_expr(&mut self, cx: &Context, expr: &Expr) { @@ -120,6 +125,35 @@ impl LintPass for LoopsPass { } } } + + // Look for variables that are incremented once per loop iteration. + let mut visitor = IncrementVisitor { cx: cx, states: HashMap::new(), depth: 0, done: false }; + walk_expr(&mut visitor, body); + + // For each candidate, check the parent block to see if + // it's initialized to zero at the start of the loop. + let map = &cx.tcx.map; + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id) ); + if let Some(parent_id) = parent_scope { + if let NodeBlock(block) = map.get(parent_id) { + for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) { + let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(), + state: VarState::IncrOnce, name: None, + depth: 0, done: false }; + walk_block(&mut visitor2, block); + + if visitor2.state == VarState::Warn { + if let Some(name) = visitor2.name { + span_lint(cx, EXPLICIT_COUNTER_LOOP, expr.span, + &format!("the variable `{0}` is used as a loop counter. Consider \ + using `for ({0}, item) in _.iter().enumerate()` \ + or similar iterators.", + name)); + } + } + } + } + } } // check for `loop { if let {} else break }` that could be `while let` // (also matches explicit "match" instead of "if let") @@ -270,3 +304,192 @@ fn is_break_expr(expr: &Expr) -> bool { _ => false, } } + +// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be +// incremented exactly once in the loop body, and initialized to zero +// at the start of the loop. +#[derive(PartialEq)] +enum VarState { + Initial, // Not examined yet + IncrOnce, // Incremented exactly once, may be a loop counter + Declared, // Declared but not (yet) initialized to zero + Warn, + DontWarn +} + +// Scan a for loop for variables that are incremented exactly once. +struct IncrementVisitor<'v, 't: 'v> { + cx: &'v Context<'v, 't>, // context reference + states: HashMap<NodeId, VarState>, // incremented variables + depth: u32, // depth of conditional expressions + done: bool +} + +impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if self.done { + return; + } + + // If node is a variable + if let Some(def_id) = var_def_id(self.cx, expr) { + if let Some(parent) = get_parent_expr(self.cx, expr) { + let state = self.states.entry(def_id).or_insert(VarState::Initial); + + match parent.node { + ExprAssignOp(op, ref lhs, ref rhs) => + if lhs.id == expr.id { + if op.node == BiAdd && is_lit_one(rhs) { + *state = match *state { + VarState::Initial if self.depth == 0 => VarState::IncrOnce, + _ => VarState::DontWarn + }; + } + else { + // Assigned some other value + *state = VarState::DontWarn; + } + }, + ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, + _ => () + } + } + } + // Give up if there are nested loops + else if is_loop(expr) { + self.states.clear(); + self.done = true; + return; + } + // Keep track of whether we're inside a conditional expression + else if is_conditional(expr) { + self.depth += 1; + walk_expr(self, expr); + self.depth -= 1; + return; + } + walk_expr(self, expr); + } +} + +// Check whether a variable is initialized to zero at the start of a loop. +struct InitializeVisitor<'v, 't: 'v> { + cx: &'v Context<'v, 't>, // context reference + end_expr: &'v Expr, // the for loop. Stop scanning here. + var_id: NodeId, + state: VarState, + name: Option<Name>, + depth: u32, // depth of conditional expressions + done: bool +} + +impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { + fn visit_decl(&mut self, decl: &'v Decl) { + // Look for declarations of the variable + if let DeclLocal(ref local) = decl.node { + if local.pat.id == self.var_id { + if let PatIdent(_, ref ident, _) = local.pat.node { + self.name = Some(ident.node.name); + + self.state = if let Some(ref init) = local.init { + if is_lit_zero(init) { + VarState::Warn + } else { + VarState::Declared + } + } + else { + VarState::Declared + } + } + } + } + walk_decl(self, decl); + } + + fn visit_expr(&mut self, expr: &'v Expr) { + if self.state == VarState::DontWarn || expr == self.end_expr { + self.done = true; + } + // No need to visit expressions before the variable is + // declared or after we've rejected it. + if self.state == VarState::IncrOnce || self.done { + return; + } + + // If node is the desired variable, see how it's used + if var_def_id(self.cx, expr) == Some(self.var_id) { + if let Some(parent) = get_parent_expr(self.cx, expr) { + match parent.node { + ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => { + self.state = VarState::DontWarn; + }, + ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { + self.state = if is_lit_zero(rhs) && self.depth == 0 { + VarState::Warn + } else { + VarState::DontWarn + }}, + _ => () + } + } + } + // If there are other loops between the declaration and the target loop, give up + else if is_loop(expr) { + self.state = VarState::DontWarn; + self.done = true; + return; + } + // Keep track of whether we're inside a conditional expression + else if is_conditional(expr) { + self.depth += 1; + walk_expr(self, expr); + self.depth -= 1; + return; + } + walk_expr(self, expr); + } +} + +fn var_def_id(cx: &Context, expr: &Expr) -> Option<NodeId> { + if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { + if let DefLocal(node_id) = path_res.base_def { + return Some(node_id) + } + } + None +} + +fn is_loop(expr: &Expr) -> bool { + match expr.node { + ExprLoop(..) | ExprWhile(..) => true, + _ => false + } +} + +fn is_conditional(expr: &Expr) -> bool { + match expr.node { + ExprIf(..) | ExprMatch(..) => true, + _ => false + } +} + +// FIXME: copy/paste from misc.rs +fn is_lit_one(expr: &Expr) -> bool { + if let ExprLit(ref spanned) = expr.node { + if let LitInt(1, _) = spanned.node { + return true; + } + } + false +} + +// FIXME: copy/paste from ranges.rs +fn is_lit_zero(expr: &Expr) -> bool { + if let ExprLit(ref spanned) = expr.node { + if let LitInt(0, _) = spanned.node { + return true; + } + } + false +} diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index a43ed7faa23..3320e9acc1d 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -14,9 +14,9 @@ impl Unrelated { } } -#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop)] +#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist)] +#[allow(linkedlist,shadow_unrelated)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; @@ -119,4 +119,64 @@ fn main() { let mut out = vec![]; vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); //~ERROR you are collect()ing an iterator let _y = vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine + + // Loop with explicit counter variable + let mut _index = 0; + for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter + + let mut _index = 1; + _index = 0; + for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter + + let mut _index; + _index = 0; + for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter + for _v in &vec { _index += 1 } // But this does not warn + + // Potential false positives + let mut _index = 0; + _index = 1; + for _v in &vec { _index += 1 } + + let mut _index = 0; + _index += 1; + for _v in &vec { _index += 1 } + + let mut _index = 0; + if true { _index = 1 } + for _v in &vec { _index += 1 } + + let mut _index = 0; + let mut _index = 1; + for _v in &vec { _index += 1 } + + let mut _index = 0; + for _v in &vec { _index += 1; _index += 1 } + + let mut _index = 0; + for _v in &vec { _index *= 2; _index += 1 } + + let mut _index = 0; + for _v in &vec { _index = 1; _index += 1 } + + let mut _index = 0; + + for _v in &vec { let mut _index = 0; _index += 1 } + + let mut _index = 0; + for _v in &vec { _index += 1; _index = 0; } + + let mut _index = 0; + for _v in &vec { for _x in 0..1 { _index += 1; }; _index += 1 } + + let mut _index = 0; + for x in &vec { if *x == 1 { _index += 1 } } + + let mut _index = 0; + if true { _index = 1 }; + for _v in &vec { _index += 1 } + + let mut _index = 1; + if false { _index = 0 }; + for _v in &vec { _index += 1 } } -- cgit 1.4.1-3-g733a5 From 1e320b38c18165964916829a990bff1b663bf718 Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Fri, 4 Sep 2015 09:26:58 -0400 Subject: Add is_integer_literal utility function Replaces is_lit_zero and is_lit_one which were used in a couple of places. --- src/loops.rs | 28 ++++------------------------ src/misc.rs | 13 ++----------- src/ranges.rs | 14 ++------------ src/utils.rs | 11 +++++++++++ 4 files changed, 19 insertions(+), 47 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index a381737fe3b..ade4f46b4a0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -9,7 +9,7 @@ use rustc::front::map::Node::{NodeBlock}; use std::collections::{HashSet,HashMap}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, - in_external_macro, expr_block, span_help_and_lint}; + in_external_macro, expr_block, span_help_and_lint, is_integer_literal}; use utils::{VEC_PATH, LL_PATH}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, @@ -339,7 +339,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { match parent.node { ExprAssignOp(op, ref lhs, ref rhs) => if lhs.id == expr.id { - if op.node == BiAdd && is_lit_one(rhs) { + if op.node == BiAdd && is_integer_literal(rhs, 1) { *state = match *state { VarState::Initial if self.depth == 0 => VarState::IncrOnce, _ => VarState::DontWarn @@ -392,7 +392,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { self.name = Some(ident.node.name); self.state = if let Some(ref init) = local.init { - if is_lit_zero(init) { + if is_integer_literal(init, 0) { VarState::Warn } else { VarState::Declared @@ -425,7 +425,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { self.state = VarState::DontWarn; }, ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { - self.state = if is_lit_zero(rhs) && self.depth == 0 { + self.state = if is_integer_literal(rhs, 0) && self.depth == 0 { VarState::Warn } else { VarState::DontWarn @@ -473,23 +473,3 @@ fn is_conditional(expr: &Expr) -> bool { _ => false } } - -// FIXME: copy/paste from misc.rs -fn is_lit_one(expr: &Expr) -> bool { - if let ExprLit(ref spanned) = expr.node { - if let LitInt(1, _) = spanned.node { - return true; - } - } - false -} - -// FIXME: copy/paste from ranges.rs -fn is_lit_zero(expr: &Expr) -> bool { - if let ExprLit(ref spanned) = expr.node { - if let LitInt(0, _) = spanned.node { - return true; - } - } - false -} diff --git a/src/misc.rs b/src/misc.rs index 2cd6babb9c5..63c2082abde 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -7,7 +7,7 @@ use syntax::codemap::{Span, Spanned}; use rustc_front::visit::FnKind; use rustc::middle::ty; -use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty}; +use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, @@ -183,7 +183,7 @@ impl LintPass for ModuloOne { fn check_expr(&mut self, cx: &Context, expr: &Expr) { if let ExprBinary(ref cmp, _, ref right) = expr.node { if let &Spanned {node: BinOp_::BiRem, ..} = cmp { - if is_lit_one(right) { + if is_integer_literal(right, 1) { cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } } @@ -191,15 +191,6 @@ impl LintPass for ModuloOne { } } -fn is_lit_one(expr: &Expr) -> bool { - if let ExprLit(ref spanned) = expr.node { - if let LitInt(1, _) = spanned.node { - return true; - } - } - false -} - declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern"); #[derive(Copy,Clone)] diff --git a/src/ranges.rs b/src/ranges.rs index 197afaf1163..97f59a3aadd 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::{Context, LintArray, LintPass}; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::match_type; +use utils::{match_type, is_integer_literal}; declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, @@ -21,7 +21,7 @@ impl LintPass for StepByZero { ref args) = expr.node { // Only warn on literal ranges. if ident.name == "step_by" && args.len() == 2 && - is_range(cx, &args[0]) && is_lit_zero(&args[1]) { + is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, "Range::step_by(0) produces an infinite iterator. \ Consider using `std::iter::repeat()` instead") @@ -37,13 +37,3 @@ fn is_range(cx: &Context, expr: &Expr) -> bool { // Note: RangeTo and RangeFull don't have step_by match_type(cx, ty, &["core", "ops", "Range"]) || match_type(cx, ty, &["core", "ops", "RangeFrom"]) } - -fn is_lit_zero(expr: &Expr) -> bool { - // FIXME: use constant folding - if let ExprLit(ref spanned) = expr.node { - if let LitInt(0, _) = spanned.node { - return true; - } - } - false -} diff --git a/src/utils.rs b/src/utils.rs index d6e529048c9..01c9adf866c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -244,6 +244,17 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { inner(ty, 0) } +pub fn is_integer_literal(expr: &Expr, value: u64) -> bool +{ + // FIXME: use constant folding + if let ExprLit(ref spanned) = expr.node { + if let LitInt(v, _) = spanned.node { + return v == value; + } + } + false +} + /// Produce a nested chain of if-lets and ifs from the patterns: /// /// if_let_chain! { -- cgit 1.4.1-3-g733a5 From 6b57924e816af4543fc6b3214ccc4d472f5c9434 Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Thu, 10 Sep 2015 08:26:31 -0400 Subject: Improve lint message Remove trailing period and include snippet of loop argument. --- src/loops.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index ade4f46b4a0..06892f6a74e 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -146,9 +146,9 @@ impl LintPass for LoopsPass { if let Some(name) = visitor2.name { span_lint(cx, EXPLICIT_COUNTER_LOOP, expr.span, &format!("the variable `{0}` is used as a loop counter. Consider \ - using `for ({0}, item) in _.iter().enumerate()` \ - or similar iterators.", - name)); + using `for ({0}, item) in {1}.enumerate()` \ + or similar iterators", + name, snippet(cx, arg.span, "_"))); } } } -- cgit 1.4.1-3-g733a5 From 8a5b4f19fd6cec7b3ef583afa592fde99dabe58e Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Thu, 10 Sep 2015 08:33:29 -0400 Subject: Check for mutable borrow of counter variable --- src/loops.rs | 2 ++ tests/compile-fail/for_loop.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/loops.rs b/src/loops.rs index 06892f6a74e..406fbee0b7c 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -351,6 +351,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { } }, ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, + ExprAddrOf(mutability,_) if mutability == MutMutable => *state = VarState::DontWarn, _ => () } } @@ -430,6 +431,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { } else { VarState::DontWarn }}, + ExprAddrOf(mutability,_) if mutability == MutMutable => self.state = VarState::DontWarn, _ => () } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 3320e9acc1d..d6d73db3c18 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -179,4 +179,8 @@ fn main() { let mut _index = 1; if false { _index = 0 }; for _v in &vec { _index += 1 } + + let mut _index = 0; + { let mut _x = &mut _index; } + for _v in &vec { _index += 1 } } -- cgit 1.4.1-3-g733a5 From 3124d2b8df3f9a2f265778555f67a6eb54f81834 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 17 Sep 2015 05:31:41 +0530 Subject: Rustup to rustc 1.5.0-nightly (fc4d566b4 2015-09-16) fixes #334 --- Cargo.toml | 2 +- src/approx_const.rs | 3 +++ src/attrs.rs | 3 ++- src/bit_mask.rs | 1 + src/consts.rs | 10 ++++++++++ src/len_zero.rs | 3 +++ src/lib.rs | 2 +- src/loops.rs | 1 + src/needless_bool.rs | 2 ++ src/precedence.rs | 2 +- src/types.rs | 3 +++ src/unicode.rs | 2 ++ src/utils.rs | 1 + tests/consts.rs | 6 ++++++ 14 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9dea1c0d453..0ac40f29cb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.13" +version = "0.0.14" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/approx_const.rs b/src/approx_const.rs index 29631b6852f..b357c2dc40a 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -2,6 +2,9 @@ use rustc::lint::*; use rustc_front::hir::*; use std::f64::consts as f64; use utils::span_lint; +use syntax::ast::Lit_::*; +use syntax::ast::Lit; +use syntax::ast::FloatTy::*; declare_lint! { pub APPROX_CONSTANT, diff --git a/src/attrs.rs b/src/attrs.rs index e6185d8b400..a80d19d32a1 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -4,7 +4,8 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; use syntax::codemap::Span; - +use syntax::attr::*; +use syntax::ast::{Attribute, MetaList, MetaWord}; use utils::{in_macro, match_path, span_lint}; declare_lint! { pub INLINE_ALWAYS, Warn, diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 97d33b5e699..58d0f3f6085 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -4,6 +4,7 @@ use rustc::middle::def::*; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; use syntax::codemap::Span; +use syntax::ast::Lit_::*; use utils::span_lint; diff --git a/src/consts.rs b/src/consts.rs index 0c32dc5efad..5a97a5d3f7a 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -13,6 +13,16 @@ use std::ops::Deref; use self::Constant::*; use self::FloatWidth::*; +use syntax::ast::Lit_::*; +use syntax::ast::Lit_; +use syntax::ast::LitIntType::*; +use syntax::ast::LitIntType; +use syntax::ast::{UintTy, FloatTy, StrStyle}; +use syntax::ast::UintTy::*; +use syntax::ast::FloatTy::*; +use syntax::ast::Sign::{self, Plus, Minus}; + + #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum FloatWidth { Fw32, diff --git a/src/len_zero.rs b/src/len_zero.rs index 45b9c844af3..22aa75f8c9d 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -5,6 +5,9 @@ use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; +use syntax::ast::Lit_::*; +use syntax::ast::Lit; + use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; declare_lint!(pub LEN_ZERO, Warn, diff --git a/src/lib.rs b/src/lib.rs index b88d2c844b0..5995b4be8af 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, core, collections)] -#![feature(str_split_at, num_bits_bytes)] +#![feature(num_bits_bytes)] #![allow(unknown_lints)] #[macro_use] diff --git a/src/loops.rs b/src/loops.rs index 406fbee0b7c..bcb9744b3f2 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -7,6 +7,7 @@ use rustc::middle::def::DefLocal; use consts::{constant_simple, Constant}; use rustc::front::map::Node::{NodeBlock}; use std::collections::{HashSet,HashMap}; +use syntax::ast::Lit_::*; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal}; diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 0e8276bfafa..7947839426d 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -5,6 +5,8 @@ use rustc::lint::*; use rustc_front::hir::*; +use syntax::ast::Lit_::*; + use utils::{span_lint, snippet}; declare_lint! { diff --git a/src/precedence.rs b/src/precedence.rs index 31c28146e1e..c55e65b3a6b 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; - +use syntax::ast::Lit_::*; use utils::span_lint; declare_lint!(pub PRECEDENCE, Warn, diff --git a/src/types.rs b/src/types.rs index 08a8560fcd6..d8d2c7a9438 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,6 +5,9 @@ use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; use rustc_front::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; +use syntax::ast::IntTy::*; +use syntax::ast::UintTy::*; +use syntax::ast::FloatTy::*; use utils::{match_type, snippet, span_lint, span_help_and_lint, in_macro, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; diff --git a/src/unicode.rs b/src/unicode.rs index e745c0960ea..16f2653429f 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -2,6 +2,8 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; +use syntax::ast::Lit_::*; + use unicode_normalization::UnicodeNormalization; use utils::{snippet, span_help_and_lint}; diff --git a/src/utils.rs b/src/utils.rs index 01c9adf866c..da288db60ca 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,6 +6,7 @@ use rustc::front::map::Node::*; use rustc::middle::def_id::DefId; use rustc::middle::ty; use std::borrow::Cow; +use syntax::ast::Lit_::*; // module DefPaths for certain structs/enums we check for pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; diff --git a/tests/consts.rs b/tests/consts.rs index 7aa42545074..66a7953994b 100755 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -11,6 +11,12 @@ use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; +use syntax::ast::Lit_::*; +use syntax::ast::Lit_; +use syntax::ast::LitIntType::*; +use syntax::ast::StrStyle::*; +use syntax::ast::Sign::*; + use clippy::consts::{constant_simple, Constant}; use clippy::consts::Constant::*; -- cgit 1.4.1-3-g733a5 From e3ee87965e577a6520c2596c3a1b9dc16794427e Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 17 Sep 2015 07:24:11 +0200 Subject: ref matches: false positive with only wildcard pattern match (fixes #335) --- src/matches.rs | 13 ++++++++----- tests/compile-fail/matches.rs | 5 +++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 5947469cd90..8e5a7f51577 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -46,6 +46,7 @@ impl LintPass for MatchPass { // check preconditions for MATCH_REF_PATS if has_only_ref_pats(arms) { + if in_external_macro(cx, expr.span) { return; } if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { span_lint(cx, MATCH_REF_PATS, expr.span, &format!( "you don't need to add `&` to both the expression to match \ @@ -69,9 +70,11 @@ fn is_unit_expr(expr: &Expr) -> bool { } fn has_only_ref_pats(arms: &[Arm]) -> bool { - arms.iter().flat_map(|a| &a.pats).all(|p| match p.node { - PatRegion(..) => true, // &-patterns - PatWild(..) => true, // an "anything" wildcard is also fine - _ => false, - }) + let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node { + PatRegion(..) => Some(true), // &-patterns + PatWild(..) => Some(false), // an "anything" wildcard is also fine + _ => None, // any other pattern is not fine + }).collect::<Option<Vec<bool>>>(); + // look for Some(v) where there's at least one true element + mapped.map_or(false, |v| v.iter().any(|el| *el)) } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 07dc7c9ef83..2fd9df33ef5 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -61,6 +61,11 @@ fn ref_pats() { &Some(v) => println!("{:?}", v), &None => println!("none"), } + // false positive: only wildcard pattern + let w = Some(0); + match w { + _ => println!("none"), + } } fn main() { -- cgit 1.4.1-3-g733a5 From 58fee220a9ec3bd904aa7c8e84b6643b51e88f76 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Thu, 17 Sep 2015 07:27:18 +0200 Subject: fix indentation --- src/collapsible_if.rs | 6 +++--- src/utils.rs | 56 +++++++++++++++++++++++++-------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 7326bd20c7c..d22fc4817f3 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -34,9 +34,9 @@ impl LintPass for CollapsibleIf { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if !in_macro(cx, expr.span) { - check_if(cx, expr) - } + if !in_macro(cx, expr.span) { + check_if(cx, expr) + } } } diff --git a/src/utils.rs b/src/utils.rs index 01c9adf866c..a49a7b2b7a3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -28,34 +28,34 @@ pub fn in_macro(cx: &Context, span: Span) -> bool { /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin pub fn in_external_macro(cx: &Context, span: Span) -> bool { - /// invokes in_macro with the expansion info of the given span - /// slightly heavy, try to use this after other checks have already happened - fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { - // no ExpnInfo = no macro - opt_info.map_or(false, |info| { - match info.callee.format { - ExpnFormat::CompilerExpansion(..) => { - if info.callee.name() == "closure expansion" { - return false; - } - }, - ExpnFormat::MacroAttribute(..) => { - // these are all plugins - return true; - }, - _ => (), - } - // no span for the callee = external macro - info.callee.span.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| - // macro doesn't start with "macro_rules" - // = compiler plugin - !code.starts_with("macro_rules") - ) - }) - }) - } + /// invokes in_macro with the expansion info of the given span + /// slightly heavy, try to use this after other checks have already happened + fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + // no ExpnInfo = no macro + opt_info.map_or(false, |info| { + match info.callee.format { + ExpnFormat::CompilerExpansion(..) => { + if info.callee.name() == "closure expansion" { + return false; + } + }, + ExpnFormat::MacroAttribute(..) => { + // these are all plugins + return true; + }, + _ => (), + } + // no span for the callee = external macro + info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| + // macro doesn't start with "macro_rules" + // = compiler plugin + !code.starts_with("macro_rules") + ) + }) + }) + } cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) -- cgit 1.4.1-3-g733a5 From f4da7d09d278b39d66590d85f48938243372782d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 19 Sep 2015 08:23:04 +0530 Subject: Upgrade Rust to rustc 1.5.0-nightly (cff041170 2015-09-17) LintPass was split and ExprParen was removed from the HIR Fixes #338 --- Cargo.toml | 2 +- src/approx_const.rs | 8 ++++-- src/attrs.rs | 13 +++++---- src/bit_mask.rs | 15 +++++----- src/collapsible_if.rs | 8 ++++-- src/consts.rs | 15 +++++----- src/eq_op.rs | 10 +++---- src/eta_reduction.rs | 8 ++++-- src/identity_op.rs | 6 ++-- src/len_zero.rs | 20 +++++++------ src/lib.rs | 67 ++++++++++++++++++++++---------------------- src/lifetimes.rs | 10 ++++--- src/loops.rs | 16 ++++++----- src/matches.rs | 4 ++- src/methods.rs | 8 ++++-- src/minmax.rs | 6 ++-- src/misc.rs | 32 ++++++++++++++------- src/mut_mut.rs | 8 ++++-- src/needless_bool.rs | 4 ++- src/precedence.rs | 7 +++-- src/ptr_arg.rs | 10 ++++--- src/ranges.rs | 8 ++++-- src/returns.rs | 14 +++++---- src/shadow.rs | 30 +++++++++++--------- src/strings.rs | 9 +++--- src/types.rs | 42 ++++++++++++++++----------- src/unicode.rs | 6 ++-- src/utils.rs | 30 ++++++++++---------- tests/compile-fail/shadow.rs | 2 +- 29 files changed, 238 insertions(+), 180 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0ac40f29cb6..4ff702de4a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.14" +version = "0.0.15" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/approx_const.rs b/src/approx_const.rs index b357c2dc40a..9a186a4f8cd 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -29,15 +29,17 @@ impl LintPass for ApproxConstant { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for ApproxConstant { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let &ExprLit(ref lit) = &e.node { check_lit(cx, lit, e); } } } -fn check_lit(cx: &Context, lit: &Lit, e: &Expr) { +fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { LitFloat(ref str, TyF32) => check_known_consts(cx, e, str, "f32"), LitFloat(ref str, TyF64) => check_known_consts(cx, e, str, "f64"), @@ -47,7 +49,7 @@ fn check_lit(cx: &Context, lit: &Lit, e: &Expr) { } } -fn check_known_consts(cx: &Context, e: &Expr, str: &str, module: &str) { +fn check_known_consts(cx: &LateContext, e: &Expr, str: &str, module: &str) { if let Ok(value) = str.parse::<f64>() { for &(constant, name) in KNOWN_CONSTS { if !within_epsilon(constant, value) { continue; } diff --git a/src/attrs.rs b/src/attrs.rs index a80d19d32a1..6450cc16195 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -19,20 +19,22 @@ impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { lint_array!(INLINE_ALWAYS) } +} - fn check_item(&mut self, cx: &Context, item: &Item) { +impl LateLintPass for AttrPass { + fn check_item(&mut self, cx: &LateContext, item: &Item) { if is_relevant_item(item) { check_attrs(cx, item.span, &item.ident, &item.attrs) } } - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if is_relevant_impl(item) { check_attrs(cx, item.span, &item.ident, &item.attrs) } } - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if is_relevant_trait(item) { check_attrs(cx, item.span, &item.ident, &item.attrs) } @@ -75,8 +77,7 @@ fn is_relevant_block(block: &Block) -> bool { fn is_relevant_expr(expr: &Expr) -> bool { match expr.node { ExprBlock(ref block) => is_relevant_block(block), - ExprRet(Some(ref e)) | ExprParen(ref e) => - is_relevant_expr(e), + ExprRet(Some(ref e)) => is_relevant_expr(e), ExprRet(None) | ExprBreak(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { @@ -87,7 +88,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { } } -fn check_attrs(cx: &Context, span: Span, ident: &Ident, +fn check_attrs(cx: &LateContext, span: Span, ident: &Ident, attrs: &[Attribute]) { if in_macro(cx, span) { return; } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 58d0f3f6085..d99497aafe9 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -54,8 +54,10 @@ impl LintPass for BitMask { fn get_lints(&self) -> LintArray { lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for BitMask { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { fetch_int_literal(cx, right).map_or_else(|| @@ -82,9 +84,8 @@ fn invert_cmp(cmp : BinOp_) -> BinOp_ { } -fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { +fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { match bit_op.node { - ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), ExprBinary(ref op, ref left, ref right) => { if op.node != BiBitAnd && op.node != BiBitOr { return; } fetch_int_literal(cx, right).or_else(|| fetch_int_literal( @@ -95,7 +96,7 @@ fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, sp } } -fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, +fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { match cmp_op { BiEq | BiNe => match bit_op { @@ -163,7 +164,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, } } -fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { +fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { if c.is_power_of_two() && m < c { span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", @@ -171,7 +172,7 @@ fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { } } -fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { +fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { if (c + 1).is_power_of_two() && m <= c { span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", @@ -179,7 +180,7 @@ fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { } } -fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option<u64> { +fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { if let &LitInt(value, _) = &lit_ptr.node { diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index d22fc4817f3..78e3ec5e35f 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -32,15 +32,17 @@ impl LintPass for CollapsibleIf { fn get_lints(&self) -> LintArray { lint_array!(COLLAPSIBLE_IF) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for CollapsibleIf { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if !in_macro(cx, expr.span) { check_if(cx, expr) } } } -fn check_if(cx: &Context, e: &Expr) { +fn check_if(cx: &LateContext, e: &Expr) { if let ExprIf(ref check, ref then, None) = e.node { if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = single_stmt_of_block(then) { @@ -63,7 +65,7 @@ fn requires_brackets(e: &Expr) -> bool { } } -fn check_to_string(cx: &Context, e: &Expr) -> String { +fn check_to_string(cx: &LateContext, e: &Expr) -> String { if requires_brackets(e) { format!("({})", snippet(cx, e.span, "..")) } else { diff --git a/src/consts.rs b/src/consts.rs index 5a97a5d3f7a..d66bfb5b4fc 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,6 @@ #![allow(cast_possible_truncation)] -use rustc::lint::Context; +use rustc::lint::LateContext; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; @@ -287,27 +287,26 @@ fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> } -pub fn constant(lcx: &Context, e: &Expr) -> Option<(Constant, bool)> { - let mut cx = ConstEvalContext { lcx: Some(lcx), needed_resolution: false }; +pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { + let mut cx = ConstEvalLateContext { lcx: Some(lcx), needed_resolution: false }; cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } pub fn constant_simple(e: &Expr) -> Option<Constant> { - let mut cx = ConstEvalContext { lcx: None, needed_resolution: false }; + let mut cx = ConstEvalLateContext { lcx: None, needed_resolution: false }; cx.expr(e) } -struct ConstEvalContext<'c, 'cc: 'c> { - lcx: Option<&'c Context<'c, 'cc>>, +struct ConstEvalLateContext<'c, 'cc: 'c> { + lcx: Option<&'c LateContext<'c, 'cc>>, needed_resolution: bool } -impl<'c, 'cc> ConstEvalContext<'c, 'cc> { +impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// simple constant folding: Insert an expression, get a constant or none. fn expr(&mut self, e: &Expr) -> Option<Constant> { match e.node { - ExprParen(ref inner) => self.expr(inner), ExprPath(_, _) => self.fetch_path(e), ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => diff --git a/src/eq_op.rs b/src/eq_op.rs index c5953201436..6f305b6adf8 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -19,8 +19,10 @@ impl LintPass for EqOp { fn get_lints(&self) -> LintArray { lint_array!(EQ_OP) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for EqOp { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) { span_lint(cx, EQ_OP, e.span, &format!( @@ -31,7 +33,7 @@ impl LintPass for EqOp { } } -pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { +pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool { if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { if l == r { return true; @@ -42,8 +44,6 @@ pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprParen(ref lparen), _) => is_exp_equal(cx, lparen, right), - (_, &ExprParen(ref rparen)) => is_exp_equal(cx, left, rparen), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => both(lqself, rqself, is_qself_equal) && @@ -57,7 +57,7 @@ pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { } } -fn is_exps_equal(cx: &Context, left : &[P<Expr>], right : &[P<Expr>]) -> bool { +fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool { over(left, right, |l, r| is_exp_equal(cx, l, r)) } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index f3359ad0c37..7226a4bad05 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -16,8 +16,10 @@ impl LintPass for EtaPass { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_CLOSURE) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for EtaPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { match expr.node { ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => { @@ -30,11 +32,11 @@ impl LintPass for EtaPass { } } -fn is_adjusted(cx: &Context, e: &Expr) -> bool { +fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() } -fn check_closure(cx: &Context, expr: &Expr) { +fn check_closure(cx: &LateContext, expr: &Expr) { if let ExprClosure(_, ref decl, ref blk) = expr.node { if !blk.stmts.is_empty() { // || {foo(); bar()}; can't be reduced here diff --git a/src/identity_op.rs b/src/identity_op.rs index 9601a685690..aee208d624e 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -16,8 +16,10 @@ impl LintPass for IdentityOp { fn get_lints(&self) -> LintArray { lint_array!(IDENTITY_OP) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for IdentityOp { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if in_macro(cx, e.span) { return; } if let ExprBinary(ref cmp, ref left, ref right) = e.node { match cmp.node { @@ -44,7 +46,7 @@ impl LintPass for IdentityOp { } -fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { +fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(ConstantInt(v, ty)) = constant_simple(e) { if match m { 0 => v == 0, diff --git a/src/len_zero.rs b/src/len_zero.rs index 22aa75f8c9d..dfd340ef5ea 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -24,8 +24,10 @@ impl LintPass for LenZero { fn get_lints(&self) -> LintArray { lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) } +} - fn check_item(&mut self, cx: &Context, item: &Item) { +impl LateLintPass for LenZero { + fn check_item(&mut self, cx: &LateContext, item: &Item) { match item.node { ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), @@ -35,7 +37,7 @@ impl LintPass for LenZero { } } - fn check_expr(&mut self, cx: &Context, expr: &Expr) { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = expr.node { match cmp { @@ -47,7 +49,7 @@ impl LintPass for LenZero { } } -fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { +fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { item.ident.name == name && if let MethodTraitItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } @@ -66,7 +68,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) { } } -fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) { +fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { item.ident.name == name && if let MethodImplItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } @@ -92,7 +94,7 @@ fn is_self_sig(sig: &MethodSig) -> bool { false } else { sig.decl.inputs.len() == 1 } } -fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { +fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, left) { if name == "is_empty" { return; } @@ -106,7 +108,7 @@ fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) { } } -fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, +fn check_len_zero(cx: &LateContext, span: Span, method: &SpannedIdent, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { if method.node.name == "len" && args.len() == 1 && @@ -119,9 +121,9 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, } /// check if this type has an is_empty method -fn has_is_empty(cx: &Context, expr: &Expr) -> bool { +fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// get a ImplOrTraitItem and return true if it matches is_empty(self) - fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { + fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { if let &MethodTraitItemId(def_id) = id { if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { @@ -132,7 +134,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool { } /// check the inherent impl's items for an is_empty(self) method - fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { + fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool { let impl_items = cx.tcx.impl_items.borrow(); cx.tcx.inherent_impls.borrow().get(id).map_or(false, |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, diff --git a/src/lib.rs b/src/lib.rs index 5995b4be8af..3c2d870aee2 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ extern crate collections; extern crate unicode_normalization; use rustc::plugin::Registry; -use rustc::lint::LintPassObject; #[macro_use] pub mod utils; @@ -54,39 +53,39 @@ mod reexport { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box types::TypePass as LintPassObject); - reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); - reg.register_lint_pass(box misc::CmpNan as LintPassObject); - reg.register_lint_pass(box eq_op::EqOp as LintPassObject); - reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); - reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); - reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject); - reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject); - reg.register_lint_pass(box misc::FloatCmp as LintPassObject); - reg.register_lint_pass(box precedence::Precedence as LintPassObject); - reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject); - reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject); - reg.register_lint_pass(box mut_mut::MutMut as LintPassObject); - reg.register_lint_pass(box len_zero::LenZero as LintPassObject); - reg.register_lint_pass(box misc::CmpOwned as LintPassObject); - reg.register_lint_pass(box attrs::AttrPass as LintPassObject); - reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject); - reg.register_lint_pass(box misc::ModuloOne as LintPassObject); - reg.register_lint_pass(box unicode::Unicode as LintPassObject); - reg.register_lint_pass(box strings::StringAdd as LintPassObject); - reg.register_lint_pass(box returns::ReturnPass as LintPassObject); - reg.register_lint_pass(box methods::MethodsPass as LintPassObject); - reg.register_lint_pass(box shadow::ShadowPass as LintPassObject); - reg.register_lint_pass(box types::LetPass as LintPassObject); - reg.register_lint_pass(box types::UnitCmp as LintPassObject); - reg.register_lint_pass(box loops::LoopsPass as LintPassObject); - reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject); - reg.register_lint_pass(box ranges::StepByZero as LintPassObject); - reg.register_lint_pass(box types::CastPass as LintPassObject); - reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject); - reg.register_lint_pass(box matches::MatchPass as LintPassObject); - reg.register_lint_pass(box misc::PatternPass as LintPassObject); - reg.register_lint_pass(box minmax::MinMaxPass as LintPassObject); + reg.register_late_lint_pass(box types::TypePass); + reg.register_late_lint_pass(box misc::TopLevelRefPass); + reg.register_late_lint_pass(box misc::CmpNan); + reg.register_late_lint_pass(box eq_op::EqOp); + reg.register_late_lint_pass(box bit_mask::BitMask); + reg.register_late_lint_pass(box ptr_arg::PtrArg); + reg.register_late_lint_pass(box needless_bool::NeedlessBool); + reg.register_late_lint_pass(box approx_const::ApproxConstant); + reg.register_late_lint_pass(box misc::FloatCmp); + reg.register_early_lint_pass(box precedence::Precedence); + reg.register_late_lint_pass(box eta_reduction::EtaPass); + reg.register_late_lint_pass(box identity_op::IdentityOp); + reg.register_late_lint_pass(box mut_mut::MutMut); + reg.register_late_lint_pass(box len_zero::LenZero); + reg.register_late_lint_pass(box misc::CmpOwned); + reg.register_late_lint_pass(box attrs::AttrPass); + reg.register_late_lint_pass(box collapsible_if::CollapsibleIf); + reg.register_late_lint_pass(box misc::ModuloOne); + reg.register_late_lint_pass(box unicode::Unicode); + reg.register_late_lint_pass(box strings::StringAdd); + reg.register_late_lint_pass(box returns::ReturnPass); + reg.register_late_lint_pass(box methods::MethodsPass); + reg.register_late_lint_pass(box shadow::ShadowPass); + reg.register_late_lint_pass(box types::LetPass); + reg.register_late_lint_pass(box types::UnitCmp); + reg.register_late_lint_pass(box loops::LoopsPass); + reg.register_late_lint_pass(box lifetimes::LifetimePass); + reg.register_late_lint_pass(box ranges::StepByZero); + reg.register_late_lint_pass(box types::CastPass); + reg.register_late_lint_pass(box types::TypeComplexityPass); + reg.register_late_lint_pass(box matches::MatchPass); + reg.register_late_lint_pass(box misc::PatternPass); + reg.register_late_lint_pass(box minmax::MinMaxPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, diff --git a/src/lifetimes.rs b/src/lifetimes.rs index dccad1ffbe7..bfd7125aa4e 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -18,21 +18,23 @@ impl LintPass for LifetimePass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_LIFETIMES) } +} - fn check_item(&mut self, cx: &Context, item: &Item) { +impl LateLintPass for LifetimePass { + fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { check_fn_inner(cx, decl, None, &generics, item.span); } } - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let MethodImplItem(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); } } - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); @@ -49,7 +51,7 @@ enum RefLt { } use self::RefLt::*; -fn check_fn_inner(cx: &Context, decl: &FnDecl, slf: Option<&ExplicitSelf>, +fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, generics: &Generics, span: Span) { if in_external_macro(cx, span) || has_where_lifetimes(&generics.where_clause) { return; diff --git a/src/loops.rs b/src/loops.rs index bcb9744b3f2..497ea8d46c4 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -43,8 +43,10 @@ impl LintPass for LoopsPass { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for LoopsPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) { // check for looping over a range and then indexing a sequence with it // -> the iteratee must be a range literal @@ -186,7 +188,7 @@ impl LintPass for LoopsPass { } } - fn check_stmt(&mut self, cx: &Context, stmt: &Stmt) { + fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.node.name == "collect" && @@ -225,7 +227,7 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { } struct VarVisitor<'v, 't: 'v> { - cx: &'v Context<'v, 't>, // context reference + cx: &'v LateContext<'v, 't>, // context reference var: Name, // var name to look for as index indexed: HashSet<Name>, // indexed variables nonindex: bool, // has the var been used otherwise? @@ -258,7 +260,7 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. -fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { +fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tcx.expr_ty(e); @@ -320,7 +322,7 @@ enum VarState { // Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'v, 't: 'v> { - cx: &'v Context<'v, 't>, // context reference + cx: &'v LateContext<'v, 't>, // context reference states: HashMap<NodeId, VarState>, // incremented variables depth: u32, // depth of conditional expressions done: bool @@ -376,7 +378,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { // Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'v, 't: 'v> { - cx: &'v Context<'v, 't>, // context reference + cx: &'v LateContext<'v, 't>, // context reference end_expr: &'v Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, @@ -454,7 +456,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { } } -fn var_def_id(cx: &Context, expr: &Expr) -> Option<NodeId> { +fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { if let DefLocal(node_id) = path_res.base_def { return Some(node_id) diff --git a/src/matches.rs b/src/matches.rs index 8e5a7f51577..4e49cd3ff73 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -17,8 +17,10 @@ impl LintPass for MatchPass { fn get_lints(&self) -> LintArray { lint_array!(SINGLE_MATCH, MATCH_REF_PATS) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for MatchPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { // check preconditions for SINGLE_MATCH // only two arms diff --git a/src/methods.rs b/src/methods.rs index b110d92e7f8..facedaa3867 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -36,8 +36,10 @@ impl LintPass for MethodsPass { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for MethodsPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(ref ident, _, ref args) = expr.node { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); if ident.node.name == "unwrap" { @@ -71,7 +73,7 @@ impl LintPass for MethodsPass { } } - fn check_item(&mut self, cx: &Context, item: &Item) { + fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { for implitem in items { let name = implitem.ident.name; @@ -229,7 +231,7 @@ fn is_bool(ty: &Ty) -> bool { false } -fn is_copy(cx: &Context, ast_ty: &Ty, item: &Item) -> bool { +fn is_copy(cx: &LateContext, ast_ty: &Ty, item: &Item) -> bool { match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { None => false, Some(ty) => { diff --git a/src/minmax.rs b/src/minmax.rs index 72190d70e2e..a94b0b42ec1 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -1,4 +1,4 @@ -use rustc::lint::{Context, LintPass, LintArray}; +use rustc::lint::*; use rustc_front::hir::*; use syntax::ptr::P; use std::cmp::PartialOrd; @@ -19,8 +19,10 @@ impl LintPass for MinMaxPass { fn get_lints(&self) -> LintArray { lint_array!(MIN_MAX) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for MinMaxPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((outer_max, outer_c, oe)) = min_max(expr) { if let Some((inner_max, inner_c, _)) = min_max(oe) { if outer_max == inner_max { return; } diff --git a/src/misc.rs b/src/misc.rs index 63c2082abde..20f5d16bbc1 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -21,8 +21,10 @@ impl LintPass for TopLevelRefPass { fn get_lints(&self) -> LintArray { lint_array!(TOPLEVEL_REF_ARG) } +} - fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { +impl LateLintPass for TopLevelRefPass { + fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { if let FnKind::Closure = k { // Does not apply to closures return @@ -49,8 +51,10 @@ impl LintPass for CmpNan { fn get_lints(&self) -> LintArray { lint_array!(CMP_NAN) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for CmpNan { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { if let &ExprPath(_, ref path) = &left.node { @@ -64,7 +68,7 @@ impl LintPass for CmpNan { } } -fn check_nan(cx: &Context, path: &Path, span: Span) { +fn check_nan(cx: &LateContext, path: &Path, span: Span) { path.segments.last().map(|seg| if seg.identifier.name == "NAN" { span_lint(cx, CMP_NAN, span, "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); @@ -83,8 +87,10 @@ impl LintPass for FloatCmp { fn get_lints(&self) -> LintArray { lint_array!(FLOAT_CMP) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for FloatCmp { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { @@ -109,7 +115,7 @@ impl LintPass for FloatCmp { } } -fn is_float(cx: &Context, expr: &Expr) -> bool { +fn is_float(cx: &LateContext, expr: &Expr) -> bool { if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { true } else { @@ -127,8 +133,10 @@ impl LintPass for CmpOwned { fn get_lints(&self) -> LintArray { lint_array!(CMP_OWNED) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for CmpOwned { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { check_to_owned(cx, left, right.span); @@ -138,7 +146,7 @@ impl LintPass for CmpOwned { } } -fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { +fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span) { match expr.node { ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { let name = ident.name; @@ -165,7 +173,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) { } } -fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool { +fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { args.len() == 1 && if let ty::TyStr = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false } } @@ -179,8 +187,10 @@ impl LintPass for ModuloOne { fn get_lints(&self) -> LintArray { lint_array!(MODULO_ONE) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for ModuloOne { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, _, ref right) = expr.node { if let &Spanned {node: BinOp_::BiRem, ..} = cmp { if is_integer_literal(right, 1) { @@ -200,8 +210,10 @@ impl LintPass for PatternPass { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_PATTERN) } +} - fn check_pat(&mut self, cx: &Context, pat: &Pat) { +impl LateLintPass for PatternPass { + fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatIdent(_, ref ident, Some(ref right)) = pat.node { if right.node == PatWild(PatWildSingle) { cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!( diff --git a/src/mut_mut.rs b/src/mut_mut.rs index d3270861870..9b6a5d9ddcc 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -15,18 +15,20 @@ impl LintPass for MutMut { fn get_lints(&self) -> LintArray { lint_array!(MUT_MUT) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for MutMut { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { check_expr_mut(cx, expr) } - fn check_ty(&mut self, cx: &Context, ty: &Ty) { + fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible")) } } -fn check_expr_mut(cx: &Context, expr: &Expr) { +fn check_expr_mut(cx: &LateContext, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } fn unwrap_addr(expr : &Expr) -> Option<&Expr> { diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 7947839426d..c0a99acb71d 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -23,8 +23,10 @@ impl LintPass for NeedlessBool { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BOOL) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for NeedlessBool { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (Some(true), Some(true)) => { diff --git a/src/precedence.rs b/src/precedence.rs index c55e65b3a6b..ce06278b782 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,7 +1,6 @@ use rustc::lint::*; -use rustc_front::hir::*; use syntax::codemap::Spanned; -use syntax::ast::Lit_::*; +use syntax::ast::*; use utils::span_lint; declare_lint!(pub PRECEDENCE, Warn, @@ -15,8 +14,10 @@ impl LintPass for Precedence { fn get_lints(&self) -> LintArray { lint_array!(PRECEDENCE) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl EarlyLintPass for Precedence { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { span_lint(cx, PRECEDENCE, expr.span, diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index b0d9757e6c5..7c369469ea2 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -23,27 +23,29 @@ impl LintPass for PtrArg { fn get_lints(&self) -> LintArray { lint_array!(PTR_ARG) } +} - fn check_item(&mut self, cx: &Context, item: &Item) { +impl LateLintPass for PtrArg { + fn check_item(&mut self, cx: &LateContext, item: &Item) { if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { check_fn(cx, decl); } } - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let &MethodImplItem(ref sig, _) = &item.node { check_fn(cx, &sig.decl); } } - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if let &MethodTraitItem(ref sig, _) = &item.node { check_fn(cx, &sig.decl); } } } -fn check_fn(cx: &Context, decl: &FnDecl) { +fn check_fn(cx: &LateContext, decl: &FnDecl) { for arg in &decl.inputs { if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty { diff --git a/src/ranges.rs b/src/ranges.rs index 97f59a3aadd..8ba2440d361 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,4 +1,4 @@ -use rustc::lint::{Context, LintArray, LintPass}; +use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::{match_type, is_integer_literal}; @@ -15,8 +15,10 @@ impl LintPass for StepByZero { fn get_lints(&self) -> LintArray { lint_array!(RANGE_STEP_BY_ZERO) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for StepByZero { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(Spanned { node: ref ident, .. }, _, ref args) = expr.node { // Only warn on literal ranges. @@ -30,7 +32,7 @@ impl LintPass for StepByZero { } } -fn is_range(cx: &Context, expr: &Expr) -> bool { +fn is_range(cx: &LateContext, expr: &Expr) -> bool { // No need for walk_ptrs_ty here because step_by moves self, so it // can't be called on a borrowed range. let ty = cx.tcx.expr_ty(expr); diff --git a/src/returns.rs b/src/returns.rs index ea75cf562bf..7ab5f3364ac 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -17,7 +17,7 @@ pub struct ReturnPass; impl ReturnPass { // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &Context, block: &Block) { + fn check_block_return(&mut self, cx: &LateContext, block: &Block) { if let Some(ref expr) = block.expr { self.check_final_expr(cx, expr); } else if let Some(stmt) = block.stmts.last() { @@ -30,7 +30,7 @@ impl ReturnPass { } // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &Context, expr: &Expr) { + fn check_final_expr(&mut self, cx: &LateContext, expr: &Expr) { match expr.node { // simple return is always "bad" ExprRet(Some(ref inner)) => { @@ -57,7 +57,7 @@ impl ReturnPass { } } - fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { + fn emit_return_lint(&mut self, cx: &LateContext, spans: (Span, Span)) { if in_external_macro(cx, spans.1) {return;} span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using `{}` \ @@ -66,7 +66,7 @@ impl ReturnPass { } // Check for "let x = EXPR; x" - fn check_let_return(&mut self, cx: &Context, block: &Block) { + fn check_let_return(&mut self, cx: &LateContext, block: &Block) { // we need both a let-binding stmt and an expr if_let_chain! { [ @@ -84,7 +84,7 @@ impl ReturnPass { } } - fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) { + fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) { if in_external_macro(cx, note_span) {return;} span_lint(cx, LET_AND_RETURN, lint_span, "returning the result of a let binding. \ @@ -100,8 +100,10 @@ impl LintPass for ReturnPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RETURN, LET_AND_RETURN) } +} - fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl, +impl LateLintPass for ReturnPass { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { self.check_block_return(cx, block); self.check_let_return(cx, block); diff --git a/src/shadow.rs b/src/shadow.rs index ae1eeee2401..f1c09b802c3 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -4,7 +4,7 @@ use reexport::*; use syntax::codemap::Span; use rustc_front::visit::FnKind; -use rustc::lint::{Context, Level, Lint, LintArray, LintPass}; +use rustc::lint::*; use rustc::middle::def::Def::{DefVariant, DefStruct}; use utils::{in_external_macro, snippet, span_lint, span_note_and_lint}; @@ -25,14 +25,17 @@ impl LintPass for ShadowPass { lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } - fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, +} + +impl LateLintPass for ShadowPass { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { if in_external_macro(cx, block.span) { return; } check_fn(cx, decl, block); } } -fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { +fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { if let PatIdent(_, ident, _) = arg.pat.node { @@ -42,7 +45,7 @@ fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { check_block(cx, block, &mut bindings); } -fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<(Name, Span)>) { +fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) { let len = bindings.len(); for stmt in &block.stmts { match stmt.node { @@ -55,7 +58,7 @@ fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<(Name, Span)>) { bindings.truncate(len); } -fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { +fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; @@ -69,14 +72,14 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { } } -fn is_binding(cx: &Context, pat: &Pat) -> bool { +fn is_binding(cx: &LateContext, pat: &Pat) -> bool { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { Some(DefVariant(..)) | Some(DefStruct(..)) => false, _ => true } } -fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, +fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { //TODO: match more stuff / destructuring match pat.node { @@ -153,9 +156,9 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span, } } -fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: +fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: &Option<T>, prev_span: Span) where T: Deref<Target=Expr> { - fn note_orig(cx: &Context, lint: &'static Lint, span: Span) { + fn note_orig(cx: &LateContext, lint: &'static Lint, span: Span) { if cx.current_level(lint) != Level::Allow { cx.sess().span_note(span, "previous binding is here"); } @@ -191,10 +194,10 @@ fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init: } } -fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { +fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, expr.span) { return; } match expr.node { - ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | + ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e) => { check_expr(cx, e, bindings) }, ExprBox(Some(ref place), ref e) => { @@ -233,7 +236,7 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { } } -fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { +fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { match ty.node { TyParen(ref sty) | TyObjectSum(ref sty, _) | TyVec(ref sty) => check_ty(cx, sty, bindings), @@ -252,7 +255,6 @@ fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { ExprBox(_, ref inner) | - ExprParen(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref(). map_or(false, |ref e| is_self_shadow(name, e)), @@ -275,7 +277,7 @@ fn contains_self(name: Name, expr: &Expr) -> bool { // no subexprs ExprLit(_) => false, // one subexpr - ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) | + ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) | ExprCast(ref e, _) => contains_self(name, e), diff --git a/src/strings.rs b/src/strings.rs index 3c9c1086a12..6bbf94004b0 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -30,8 +30,10 @@ impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD, STRING_ADD_ASSIGN) } +} - fn check_expr(&mut self, cx: &Context, e: &Expr) { +impl LateLintPass for StringAdd { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { if is_string(cx, left) { if let Allow = cx.current_level(STRING_ADD_ASSIGN) { @@ -59,18 +61,17 @@ impl LintPass for StringAdd { } } -fn is_string(cx: &Context, e: &Expr) -> bool { +fn is_string(cx: &LateContext, e: &Expr) -> bool { match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &STRING_PATH) } -fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { +fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left), ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)), - ExprParen(ref expr) => is_add(cx, expr, target), _ => false } } diff --git a/src/types.rs b/src/types.rs index d8d2c7a9438..dd41b4f2239 100644 --- a/src/types.rs +++ b/src/types.rs @@ -26,8 +26,10 @@ impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, LINKEDLIST) } +} - fn check_ty(&mut self, cx: &Context, ast_ty: &Ty) { +impl LateLintPass for TypePass { + fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) { if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { if match_type(cx, inner, &VEC_PATH) { @@ -53,7 +55,7 @@ pub struct LetPass; declare_lint!(pub LET_UNIT_VALUE, Warn, "creating a let binding to a value of unit type, which usually can't be used afterwards"); -fn check_let_unit(cx: &Context, decl: &Decl) { +fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { @@ -70,8 +72,10 @@ impl LintPass for LetPass { fn get_lints(&self) -> LintArray { lint_array!(LET_UNIT_VALUE) } +} - fn check_decl(&mut self, cx: &Context, decl: &Decl) { +impl LateLintPass for LetPass { + fn check_decl(&mut self, cx: &LateContext, decl: &Decl) { check_let_unit(cx, decl) } } @@ -86,8 +90,10 @@ impl LintPass for UnitCmp { fn get_lints(&self) -> LintArray { lint_array!(UNIT_CMP) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for UnitCmp { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_macro(cx, expr.span) { return; } if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; @@ -135,7 +141,7 @@ fn is_isize_or_usize(typ: &ty::TyS) -> bool { } } -fn span_precision_loss_lint(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { +fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { let mantissa_nbits = if cast_to_f64 {52} else {23}; let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; let arch_dependent_str = "on targets with 64-bit wide pointers "; @@ -154,7 +160,7 @@ enum ArchSuffix { _32, _64, None } -fn check_truncation_and_wrapping(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { +fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); @@ -207,8 +213,10 @@ impl LintPass for CastPass { CAST_POSSIBLE_TRUNCATION, CAST_POSSIBLE_WRAP) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for CastPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr)); if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { @@ -262,16 +270,18 @@ impl LintPass for TypeComplexityPass { fn get_lints(&self) -> LintArray { lint_array!(TYPE_COMPLEXITY) } +} - fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { +impl LateLintPass for TypeComplexityPass { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { check_fndecl(cx, decl); } - fn check_struct_field(&mut self, cx: &Context, field: &StructField) { + fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { check_type(cx, &field.node.ty); } - fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) { + fn check_variant(&mut self, cx: &LateContext, var: &Variant, _: &Generics) { // StructVariant is covered by check_struct_field if let TupleVariantKind(ref args) = var.node.kind { for arg in args { @@ -280,7 +290,7 @@ impl LintPass for TypeComplexityPass { } } - fn check_item(&mut self, cx: &Context, item: &Item) { + fn check_item(&mut self, cx: &LateContext, item: &Item) { match item.node { ItemStatic(ref ty, _, _) | ItemConst(ref ty, _) => check_type(cx, ty), @@ -289,7 +299,7 @@ impl LintPass for TypeComplexityPass { } } - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { match item.node { ConstTraitItem(ref ty, _) | TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty), @@ -299,7 +309,7 @@ impl LintPass for TypeComplexityPass { } } - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { match item.node { ConstImplItem(ref ty, _) | TypeImplItem(ref ty) => check_type(cx, ty), @@ -308,14 +318,14 @@ impl LintPass for TypeComplexityPass { } } - fn check_local(&mut self, cx: &Context, local: &Local) { + fn check_local(&mut self, cx: &LateContext, local: &Local) { if let Some(ref ty) = local.ty { check_type(cx, ty); } } } -fn check_fndecl(cx: &Context, decl: &FnDecl) { +fn check_fndecl(cx: &LateContext, decl: &FnDecl) { for arg in &decl.inputs { check_type(cx, &arg.ty); } @@ -324,7 +334,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) { } } -fn check_type(cx: &Context, ty: &Ty) { +fn check_type(cx: &LateContext, ty: &Ty) { if in_macro(cx, ty.span) { return; } let score = { let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; diff --git a/src/unicode.rs b/src/unicode.rs index 16f2653429f..3855fafe7be 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -25,8 +25,10 @@ impl LintPass for Unicode { fn get_lints(&self) -> LintArray { lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) } +} - fn check_expr(&mut self, cx: &Context, expr: &Expr) { +impl LateLintPass for Unicode { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprLit(ref lit) = expr.node { if let LitStr(_, _) = lit.node { check_str(cx, lit.span) @@ -47,7 +49,7 @@ fn escape<T: Iterator<Item=char>>(s: T) -> String { result } -fn check_str(cx: &Context, span: Span) { +fn check_str(cx: &LateContext, span: Span) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { span_help_and_lint(cx, ZERO_WIDTH_SPACE, span, diff --git a/src/utils.rs b/src/utils.rs index 6c0fe97c983..d5566c3a691 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -16,7 +16,7 @@ pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; /// returns true this expn_info was expanded by any macro -pub fn in_macro(cx: &Context, span: Span) -> bool { +pub fn in_macro(cx: &LateContext, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| info.map_or(false, |i| { match i.callee.format { @@ -28,10 +28,10 @@ pub fn in_macro(cx: &Context, span: Span) -> bool { /// returns true if the macro that expanded the crate was outside of /// the current crate or was a compiler plugin -pub fn in_external_macro(cx: &Context, span: Span) -> bool { +pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// invokes in_macro with the expansion info of the given span /// slightly heavy, try to use this after other checks have already happened - fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { + fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { match info.callee.format { @@ -65,12 +65,12 @@ pub fn in_external_macro(cx: &Context, span: Span) -> bool { /// check if a DefId's path matches the given absolute type path /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` -pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool { +pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p)) } /// check if type is struct or enum type with given def path -pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool { +pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { match ty.sty { ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => { match_def_path(cx, adt.did, path) @@ -82,7 +82,7 @@ pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool { } /// check if method call given in "expr" belongs to given trait -pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool { +pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); let trt_id = cx.tcx.tables .borrow().method_map.get(&method_call) @@ -102,7 +102,7 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { } /// get the name of the item the expression is in, if available -pub fn get_item_name(cx: &Context, expr: &Expr) -> Option<Name> { +pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { Some(NodeItem(&Item{ ref ident, .. })) | @@ -116,7 +116,7 @@ pub fn get_item_name(cx: &Context, expr: &Expr) -> Option<Name> { /// convert a span to a code snippet if available, otherwise use default, e.g. /// `snippet(cx, expr.span, "..")` -pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { +pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) } @@ -124,13 +124,13 @@ pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { /// `snippet(cx, expr.span, "..")` /// This trims the code of indentation, except for the first line /// Use it for blocks or block-like things which need to be printed as such -pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> { +pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { let snip = snippet(cx, span, default); trim_multiline(snip, true) } /// Like snippet_block, but add braces if the expr is not an ExprBlock -pub fn expr_block<'a>(cx: &Context, expr: &Expr, default: &'a str) -> Cow<'a, str> { +pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, default: &'a str) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); if let ExprBlock(_) = expr.node { code @@ -169,7 +169,7 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { } /// get a parent expr if any – this is useful to constrain a lint -pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { +pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { let map = &cx.tcx.map; let node_id : NodeId = e.id; let parent_id : NodeId = map.get_parent_node(node_id); @@ -179,7 +179,7 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { } #[cfg(not(feature="structured_logging"))] -pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { +pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { cx.sess().fileline_help(sp, &format!("for further information visit \ @@ -189,7 +189,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { } #[cfg(feature="structured_logging")] -pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { +pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { // lint.name / lint.desc is can give details of the lint // cx.sess().codemap() has all these nice functions for line/column/snippet details // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string @@ -201,7 +201,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { } } -pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, +pub fn span_help_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, msg: &str, help: &str) { cx.span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { @@ -211,7 +211,7 @@ pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, } } -pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, +pub fn span_note_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, note: &str) { cx.span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index 293d97a42fa..d70f26ed090 100755 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -12,7 +12,7 @@ fn main() { let mut x = 1; let x = &mut x; //~ERROR: x is shadowed by itself in &mut x let x = { x }; //~ERROR: x is shadowed by itself in { x } - let x = (&*x); //~ERROR: x is shadowed by itself in (&*x) + let x = (&*x); //~ERROR: x is shadowed by itself in &*x let x = { *x + 1 }; //~ERROR: x is shadowed by { *x + 1 } which reuses let x = id(x); //~ERROR: x is shadowed by id(x) which reuses let x = (1, x); //~ERROR: x is shadowed by (1, x) which reuses -- cgit 1.4.1-3-g733a5 From b56ff4319eb341ce3393eadba4ff200efe32a4e9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 19 Sep 2015 08:32:56 +0530 Subject: fix dogfood --- src/bit_mask.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index d99497aafe9..e6665bbbb4d 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -85,14 +85,13 @@ fn invert_cmp(cmp : BinOp_) -> BinOp_ { fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { - match bit_op.node { - ExprBinary(ref op, ref left, ref right) => { - if op.node != BiBitAnd && op.node != BiBitOr { return; } - fetch_int_literal(cx, right).or_else(|| fetch_int_literal( - cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, - cmp_op, mask, cmp_value, span)) - }, - _ => () + if let ExprBinary(ref op, ref left, ref right) = bit_op.node { + if op.node != BiBitAnd && op.node != BiBitOr { + return; + } + fetch_int_literal(cx, right).or_else(|| fetch_int_literal( + cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, + cmp_op, mask, cmp_value, span)) } } -- cgit 1.4.1-3-g733a5 From 7fdf52270b504f4e8e680cc7ae2dc2f8b1eaae3b Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sat, 19 Sep 2015 08:49:01 +0200 Subject: Fix stray backquote. --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index facedaa3867..f5361f255c7 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -124,7 +124,7 @@ const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ]; const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ - ("add", 2, ValueSelf, AnyType, "std::ops::Add`"), + ("add", 2, ValueSelf, AnyType, "std::ops::Add"), ("sub", 2, ValueSelf, AnyType, "std::ops::Sub"), ("mul", 2, ValueSelf, AnyType, "std::ops::Mul"), ("div", 2, ValueSelf, AnyType, "std::ops::Div"), -- cgit 1.4.1-3-g733a5 From 56b9682624cfad6c48d1cb7b16d659630622ed19 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 19 Sep 2015 19:16:59 +0530 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 011078c5407..b1481eea5bf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ #rust-clippy [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) -A collection of lints that give helpful tips to newbies and catch oversights. +A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) -- cgit 1.4.1-3-g733a5 From 7cc291d02eba4b513461d697ee89971d0a0fb2cd Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 20 Sep 2015 13:57:27 +0200 Subject: generalize let_and_return for any block (closes #340) --- src/returns.rs | 9 ++++++--- tests/compile-fail/let_return.rs | 14 ++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/returns.rs b/src/returns.rs index 7ab5f3364ac..d04307ffd5d 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -10,7 +10,7 @@ declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); declare_lint!(pub LET_AND_RETURN, Warn, "creating a let-binding and then immediately returning it like `let x = expr; x` at \ - the end of a function"); + the end of a block"); #[derive(Copy, Clone)] pub struct ReturnPass; @@ -71,11 +71,11 @@ impl ReturnPass { if_let_chain! { [ let Some(stmt) = block.stmts.last(), + let Some(ref retexpr) = block.expr, let StmtDecl(ref decl, _) = stmt.node, let DeclLocal(ref local) = decl.node, let Some(ref initexpr) = local.init, let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, - let Some(ref retexpr) = block.expr, let ExprPath(_, ref path) = retexpr.node, match_path(path, &[&id.name.as_str()]) ], { @@ -87,7 +87,7 @@ impl ReturnPass { fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) { if in_external_macro(cx, note_span) {return;} span_lint(cx, LET_AND_RETURN, lint_span, - "returning the result of a let binding. \ + "returning the result of a let binding from a block. \ Consider returning the expression directly."); if cx.current_level(LET_AND_RETURN) != Level::Allow { cx.sess().span_note(note_span, @@ -106,6 +106,9 @@ impl LateLintPass for ReturnPass { fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { self.check_block_return(cx, block); + } + + fn check_block(&mut self, cx: &LateContext, block: &Block) { self.check_let_return(cx, block); } } diff --git a/tests/compile-fail/let_return.rs b/tests/compile-fail/let_return.rs index 082378d21e2..33d2d6a823a 100755 --- a/tests/compile-fail/let_return.rs +++ b/tests/compile-fail/let_return.rs @@ -1,5 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(unused)] #![deny(let_and_return)] @@ -9,6 +10,15 @@ fn test() -> i32 { x //~ERROR returning the result of a let binding } +fn test_inner() -> i32 { + if true { + let x = 5; + x //~ERROR returning the result of a let binding + } else { + 0 + } +} + fn test_nowarn_1() -> i32 { let mut x = 5; x += 1; @@ -27,8 +37,4 @@ fn test_nowarn_3() -> (i32, i32) { } fn main() { - test(); - test_nowarn_1(); - test_nowarn_2(); - test_nowarn_3(); } -- cgit 1.4.1-3-g733a5 From cf4e48d148812e4d84b93e5149e1a3a928f3d637 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 21 Sep 2015 06:24:46 +0200 Subject: update lints --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1481eea5bf..3ebc230e717 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ name [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a function +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead -- cgit 1.4.1-3-g733a5 From 3609a2211a1cdb27c77f139108b25f9c9d3613f9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 22 Sep 2015 12:38:42 +0530 Subject: Handle let ref in toplevel_ref_arg as well --- README.md | 4 ++-- src/misc.rs | 29 +++++++++++++++++++++++++++-- tests/compile-fail/matches.rs | 4 ++-- tests/compile-fail/toplevel_ref_arg.rs | 8 ++++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 011078c5407..902667f31c5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A collection of lints that give helpful tips to newbies and catch oversights. There are 58 lints included in this crate: name | default | meaning --------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap @@ -59,7 +59,7 @@ name [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) diff --git a/src/misc.rs b/src/misc.rs index 20f5d16bbc1..c18c483bcba 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -8,11 +8,13 @@ use rustc_front::visit::FnKind; use rustc::middle::ty; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; +use utils::span_help_and_lint; use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, - "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \ - `fn foo((ref x, ref y): (u8, u8))`)"); + "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ + or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ + references with `&`."); #[allow(missing_copy_implementations)] pub struct TopLevelRefPass; @@ -39,6 +41,29 @@ impl LateLintPass for TopLevelRefPass { } } } + fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) { + if_let_chain! { + [ + let StmtDecl(ref d, _) = s.node, + let DeclLocal(ref l) = d.node, + let PatIdent(BindByRef(_), i, None) = l.pat.node, + let Some(ref init) = l.init + ], { + let tyopt = if let Some(ref ty) = l.ty { + format!(": {:?} ", ty) + } else { + "".to_owned() + }; + span_help_and_lint(cx, + TOPLEVEL_REF_ARG, + l.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", + &format!("try `let {} {}= &{};`", snippet(cx, i.span, "_"), + tyopt, snippet(cx, init.span, "_")) + ); + } + }; + } } declare_lint!(pub CMP_NAN, Deny, diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 2fd9df33ef5..f25a5fa3fa4 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -40,7 +40,7 @@ fn single_match(){ fn ref_pats() { { - let ref v = Some(0); + let v = &Some(0); match v { //~ERROR instead of prefixing all patterns with `&` &Some(v) => println!("{:?}", v), &None => println!("none"), @@ -50,7 +50,7 @@ fn ref_pats() { other => println!("other"), } } - let ref tup = (1, 2); + let tup =& (1, 2); match tup { //~ERROR instead of prefixing all patterns with `&` &(v, 1) => println!("{}", v), _ => println!("none"), diff --git a/tests/compile-fail/toplevel_ref_arg.rs b/tests/compile-fail/toplevel_ref_arg.rs index ea69a8cfa15..05ad1af0034 100644 --- a/tests/compile-fail/toplevel_ref_arg.rs +++ b/tests/compile-fail/toplevel_ref_arg.rs @@ -14,5 +14,13 @@ fn main() { // Closures should not warn let y = |ref x| { println!("{:?}", x) }; y(1u8); + + let ref x = 1; //~ ERROR `ref` on an entire `let` pattern is discouraged + //~^ HELP try `let x = &1;` + + let ref y = (&1, 2); //~ ERROR `ref` on an entire `let` pattern is discouraged + //~^ HELP try `let y = &(&1, 2);` + + let (ref x, _) = (1,2); // okay, not top level println!("The answer is {}.", x); } -- cgit 1.4.1-3-g733a5 From b2c66d1a0eb77338dc6b421fd18903fca4d8975e Mon Sep 17 00:00:00 2001 From: Pietro Monteiro <pietro@riseup.net> Date: Wed, 23 Sep 2015 17:30:39 -0700 Subject: Upgrade Rust to rustc 1.5.0-nightly (b2f379cdc 2015-09-23) Ident was removed in many HIR structures in favor of Name. --- Cargo.toml | 2 +- src/attrs.rs | 10 +++++----- src/len_zero.rs | 17 +++++++++-------- src/loops.rs | 4 ++-- src/methods.rs | 8 ++++---- src/misc.rs | 7 +++---- src/ranges.rs | 4 ++-- src/shadow.rs | 4 ++-- src/utils.rs | 8 ++++---- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ff702de4a5..8a905ffac42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.15" +version = "0.0.16" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/attrs.rs b/src/attrs.rs index 6450cc16195..936548c04f8 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -24,19 +24,19 @@ impl LintPass for AttrPass { impl LateLintPass for AttrPass { fn check_item(&mut self, cx: &LateContext, item: &Item) { if is_relevant_item(item) { - check_attrs(cx, item.span, &item.ident, &item.attrs) + check_attrs(cx, item.span, &item.name, &item.attrs) } } fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if is_relevant_impl(item) { - check_attrs(cx, item.span, &item.ident, &item.attrs) + check_attrs(cx, item.span, &item.name, &item.attrs) } } fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if is_relevant_trait(item) { - check_attrs(cx, item.span, &item.ident, &item.attrs) + check_attrs(cx, item.span, &item.name, &item.attrs) } } } @@ -88,7 +88,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { } } -fn check_attrs(cx: &LateContext, span: Span, ident: &Ident, +fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { if in_macro(cx, span) { return; } @@ -100,7 +100,7 @@ fn check_attrs(cx: &LateContext, span: Span, ident: &Ident, span_lint(cx, INLINE_ALWAYS, attr.span, &format!( "you have declared `#[inline(always)]` on `{}`. This \ is usually a bad idea. Are you sure?", - ident.name)); + name)); } } } diff --git a/src/len_zero.rs b/src/len_zero.rs index dfd340ef5ea..d8886e43dca 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; +use syntax::ast::Name; use syntax::ptr::P; use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; @@ -51,7 +52,7 @@ impl LateLintPass for LenZero { fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.ident.name == name && if let MethodTraitItem(ref sig, _) = + item.name == name && if let MethodTraitItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -62,7 +63,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>] span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, &format!("trait `{}` has a `.len(_: &Self)` method, but no \ `.is_empty(_: &Self)` method. Consider adding one", - item.ident.name)); + item.name)); } }; } @@ -70,7 +71,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>] fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.ident.name == name && if let MethodImplItem(ref sig, _) = + item.name == name && if let MethodImplItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -82,7 +83,7 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, &format!("item `{}` has a `.len(_: &Self)` method, but no \ `.is_empty(_: &Self)` method. Consider adding one", - item.ident.name)); + item.name)); return; } } @@ -101,17 +102,17 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => - check_len_zero(cx, span, method, args, lit, op), + check_len_zero(cx, span, &method.node, args, lit, op), (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => - check_len_zero(cx, span, method, args, lit, op), + check_len_zero(cx, span, &method.node, args, lit, op), _ => () } } -fn check_len_zero(cx: &LateContext, span: Span, method: &SpannedIdent, +fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { - if method.node.name == "len" && args.len() == 1 && + if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "consider replacing the len comparison with `{}{}.is_empty()`", diff --git a/src/loops.rs b/src/loops.rs index 497ea8d46c4..4afa31ff515 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -108,7 +108,7 @@ impl LateLintPass for LoopsPass { if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { - let method_name = method.node.name; + let method_name = method.node; // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x if method_name == "iter" || method_name == "iter_mut" { if is_ref_iterable_type(cx, &args[0]) { @@ -191,7 +191,7 @@ impl LateLintPass for LoopsPass { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.node.name == "collect" && + if args.len() == 1 && method.node == "collect" && match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { span_lint(cx, UNUSED_COLLECT, expr.span, &format!( "you are collect()ing an iterator and throwing away the result. \ diff --git a/src/methods.rs b/src/methods.rs index f5361f255c7..1adf9c30e81 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -40,9 +40,9 @@ impl LintPass for MethodsPass { impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(ref ident, _, ref args) = expr.node { + if let ExprMethodCall(ref name, _, ref args) = expr.node { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - if ident.node.name == "unwrap" { + if name.node.as_str() == "unwrap" { if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ @@ -54,7 +54,7 @@ impl LateLintPass for MethodsPass { of Err values is preferred"); } } - else if ident.node.name == "to_string" { + else if name.node.as_str() == "to_string" { if obj_ty.sty == ty::TyStr { let mut arg_str = snippet(cx, args[0].span, "_"); if ptr_depth > 1 { @@ -76,7 +76,7 @@ impl LateLintPass for MethodsPass { fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { for implitem in items { - let name = implitem.ident.name; + let name = implitem.name; if let MethodImplItem(ref sig, _) = implitem.node { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { diff --git a/src/misc.rs b/src/misc.rs index c18c483bcba..c40fd0fa364 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -173,10 +173,9 @@ impl LateLintPass for CmpOwned { fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span) { match expr.node { - ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => { - let name = ident.name; - if name == "to_string" || - name == "to_owned" && is_str_arg(cx, args) { + ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) => { + if name.as_str() == "to_string" || + name.as_str() == "to_owned" && is_str_arg(cx, args) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using `{}.as_slice()` to compare without allocation", diff --git a/src/ranges.rs b/src/ranges.rs index 8ba2440d361..2ef272237d1 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -19,10 +19,10 @@ impl LintPass for StepByZero { impl LateLintPass for StepByZero { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(Spanned { node: ref ident, .. }, _, + if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { // Only warn on literal ranges. - if ident.name == "step_by" && args.len() == 2 && + if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, "Range::step_by(0) produces an infinite iterator. \ diff --git a/src/shadow.rs b/src/shadow.rs index f1c09b802c3..25970df399d 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -106,9 +106,9 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, if let Some(ref init_struct) = *init { if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { - let ident = field.node.ident; + let name = field.node.name; let efield = efields.iter() - .find(|ref f| f.ident.node == ident) + .find(|ref f| f.name.node == name) .map(|f| &*f.expr); check_pat(cx, &field.node.pat, &efield, span, bindings); } diff --git a/src/utils.rs b/src/utils.rs index d5566c3a691..250e24ac646 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -105,10 +105,10 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { - Some(NodeItem(&Item{ ref ident, .. })) | - Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | - Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { - Some(ident.name) + Some(NodeItem(&Item{ ref name, .. })) | + Some(NodeTraitItem(&TraitItem{ id: _, ref name, .. })) | + Some(NodeImplItem(&ImplItem{ id: _, ref name, .. })) => { + Some(*name) }, _ => None, } -- cgit 1.4.1-3-g733a5 From cd114880800069d5a79c5bfb5c146110b078160c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 25 Sep 2015 18:52:36 +0530 Subject: rustup 2015-09-24 --- Cargo.toml | 2 +- src/consts.rs | 2 +- src/shadow.rs | 12 +++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8a905ffac42..5ff911c8ced 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.16" +version = "0.0.17" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/consts.rs b/src/consts.rs index d66bfb5b4fc..be681efb257 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -321,7 +321,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { |o| match op { UnNot => constant_not(o), UnNeg => constant_negate(o), - UnUniq | UnDeref => Some(o), + UnDeref => Some(o), }), ExprBinary(op, ref left, ref right) => self.binop(op, left, right), diff --git a/src/shadow.rs b/src/shadow.rs index 25970df399d..8fd8d0d15ac 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -140,7 +140,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, }, PatBox(ref inner) => { if let Some(ref initp) = *init { - if let ExprBox(_, ref inner_init) = initp.node { + if let ExprBox(ref inner_init) = initp.node { check_pat(cx, inner, &Some(&**inner_init), span, bindings); } else { check_pat(cx, inner, init, span, bindings); @@ -198,10 +198,8 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, expr.span) { return; } match expr.node { ExprUnary(_, ref e) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e) + ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { check_expr(cx, e, bindings) }, - ExprBox(Some(ref place), ref e) => { - check_expr(cx, place, bindings); check_expr(cx, e, bindings) } ExprBlock(ref block) | ExprLoop(ref block, _) => { check_block(cx, block, bindings) }, //ExprCall @@ -254,11 +252,11 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { - ExprBox(_, ref inner) | + ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref(). map_or(false, |ref e| is_self_shadow(name, e)), - ExprUnary(op, ref inner) => (UnUniq == op || UnDeref == op) && + ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprPath(_, ref path) => path_eq_name(name, path), _ => false, @@ -278,7 +276,7 @@ fn contains_self(name: Name, expr: &Expr) -> bool { ExprLit(_) => false, // one subexpr ExprUnary(_, ref e) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) | + ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) | ExprCast(ref e, _) => contains_self(name, e), // two subexprs -- cgit 1.4.1-3-g733a5 From 15e3774cb4a6536cdb6c01edaa93315743b9f49a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 28 Sep 2015 10:34:06 +0530 Subject: rustup to 1.5.0-nightly (7bf4c885f 2015-09-26) fixes #348 --- src/len_zero.rs | 10 +++++----- src/lifetimes.rs | 2 +- src/loops.rs | 8 ++++---- src/methods.rs | 6 +++--- src/misc.rs | 11 ++++++----- src/ranges.rs | 2 +- src/utils.rs | 7 ++++--- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 620c6bfd7b8..2c85298201f 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -52,7 +52,7 @@ impl LateLintPass for LenZero { fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.name == name && if let MethodTraitItem(ref sig, _) = + item.name.as_str() == name && if let MethodTraitItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -71,7 +71,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>] fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.name == name && if let MethodImplItem(ref sig, _) = + item.name.as_str() == name && if let MethodImplItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } } @@ -98,7 +98,7 @@ fn is_self_sig(sig: &MethodSig) -> bool { fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, left) { - if name == "is_empty" { return; } + if name.as_str() == "is_empty" { return; } } match (&left.node, &right.node) { (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => @@ -112,7 +112,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { - if name == &"len" && args.len() == 1 && + if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "consider replacing the len comparison with `{}{}.is_empty()`", @@ -128,7 +128,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { if let &MethodTraitItemId(def_id) = id { if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { - method.name == "is_empty" + method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 } else { false } } else { false } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index bfd7125aa4e..b64fa148ef3 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -161,7 +161,7 @@ struct RefVisitor(Vec<RefLt>); impl RefVisitor { fn record(&mut self, lifetime: &Option<Lifetime>) { if let &Some(ref lt) = lifetime { - if lt.name == "'static" { + if lt.name.as_str() == "'static" { self.0.push(Static); } else { self.0.push(Named(lt.name)); diff --git a/src/loops.rs b/src/loops.rs index 4afa31ff515..9e7b0ee38d4 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -110,17 +110,17 @@ impl LateLintPass for LoopsPass { if args.len() == 1 { let method_name = method.node; // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - if method_name == "iter" || method_name == "iter_mut" { + if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { if is_ref_iterable_type(cx, &args[0]) { let object = snippet(cx, args[0].span, "_"); span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( "it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", - if method_name == "iter_mut" { "mut " } else { "" }, + if method_name.as_str() == "iter_mut" { "mut " } else { "" }, object, object, method_name)); } } // check for looping over Iterator::next() which is not what you want - else if method_name == "next" && + else if method_name.as_str() == "next" && match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { span_lint(cx, ITER_NEXT_LOOP, expr.span, "you are iterating over `Iterator::next()` which is an Option; \ @@ -191,7 +191,7 @@ impl LateLintPass for LoopsPass { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.node == "collect" && + if args.len() == 1 && method.node.as_str() == "collect" && match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { span_lint(cx, UNUSED_COLLECT, expr.span, &format!( "you are collect()ing an iterator and throwing away the result. \ diff --git a/src/methods.rs b/src/methods.rs index 946e0985823..18da7e977d6 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -42,7 +42,7 @@ impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(ref name, _, ref args) = expr.node { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - if name.node == "unwrap" { + if name.node.as_str() == "unwrap" { if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ @@ -54,7 +54,7 @@ impl LateLintPass for MethodsPass { of Err values is preferred"); } } - else if name.node == "to_string" { + else if name.node.as_str() == "to_string" { if obj_ty.sty == ty::TyStr { let mut arg_str = snippet(cx, args[0].span, "_"); if ptr_depth > 1 { @@ -82,7 +82,7 @@ impl LateLintPass for MethodsPass { for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if_let_chain! { [ - name == method_name, + name.as_str() == method_name, sig.decl.inputs.len() == n_args, out_type.matches(&sig.decl.output), self_kind.matches(&sig.explicit_self.node, false) diff --git a/src/misc.rs b/src/misc.rs index 2dd396cb1c5..cf4504d2f67 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -94,7 +94,7 @@ impl LateLintPass for CmpNan { } fn check_nan(cx: &LateContext, path: &Path, span: Span) { - path.segments.last().map(|seg| if seg.identifier.name == "NAN" { + path.segments.last().map(|seg| if seg.identifier.name.as_str() == "NAN" { span_lint(cx, CMP_NAN, span, "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); }); @@ -124,9 +124,10 @@ impl LateLintPass for FloatCmp { return; } if let Some(name) = get_item_name(cx, expr) { + let name = name.as_str(); if name == "eq" || name == "ne" || name == "is_nan" || - name.as_str().starts_with("eq_") || - name.as_str().ends_with("_eq") { + name.starts_with("eq_") || + name.ends_with("_eq") { return; } } @@ -174,8 +175,8 @@ impl LateLintPass for CmpOwned { fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span) { match expr.node { ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) => { - if name == &"to_string" || - name == &"to_owned" && is_str_arg(cx, args) { + if name.as_str() == "to_string" || + name.as_str() == "to_owned" && is_str_arg(cx, args) { span_lint(cx, CMP_OWNED, expr.span, &format!( "this creates an owned instance just for comparison. \ Consider using `{}.as_slice()` to compare without allocation", diff --git a/src/ranges.rs b/src/ranges.rs index 94bbb34a421..2ef272237d1 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -22,7 +22,7 @@ impl LateLintPass for StepByZero { if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { // Only warn on literal ranges. - if name == &"step_by" && args.len() == 2 && + if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, "Range::step_by(0) produces an infinite iterator. \ diff --git a/src/utils.rs b/src/utils.rs index 250e24ac646..0dfc10b390a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,7 +36,7 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { opt_info.map_or(false, |info| { match info.callee.format { ExpnFormat::CompilerExpansion(..) => { - if info.callee.name() == "closure expansion" { + if info.callee.name().as_str() == "closure expansion" { return false; } }, @@ -66,7 +66,8 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p)) + cx.tcx.with_path(def_id, |iter| iter.zip(path) + .all(|(nm, p)| nm.name().as_str() == *p)) } /// check if type is struct or enum type with given def path @@ -98,7 +99,7 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| &a.identifier.name == b) + |(a, b)| a.identifier.name.as_str() == *b) } /// get the name of the item the expression is in, if available -- cgit 1.4.1-3-g733a5 From e8f875813d75f5547c2e1e8b139c89a6275c0ccb Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 28 Sep 2015 07:11:03 +0200 Subject: all: remove trailing spaces --- src/len_zero.rs | 4 ++-- tests/compile-fail/bit_masks.rs | 2 +- tests/compile-fail/cast.rs | 4 ++-- tests/compile-fail/unicode.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) mode change 100644 => 100755 tests/compile-fail/cast.rs diff --git a/src/len_zero.rs b/src/len_zero.rs index 2c85298201f..f5ad37a71be 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -95,8 +95,8 @@ fn is_self_sig(sig: &MethodSig) -> bool { false } else { sig.decl.inputs.len() == 1 } } -fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { - // check if we are in an is_empty() method +fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { + // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, left) { if name.as_str() == "is_empty" { return; } } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index 0b7b31b64a5..f78012864a0 100755 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -27,7 +27,7 @@ fn main() { x & 192 == 128; // ok, tests for bit 7 and not bit 6 x & 0xffc0 == 0xfe80; // ok - + // this also now works with constants x & THREE_BITS == 8; //~ERROR incompatible bit mask x | EVEN_MORE_REDIRECTION < 7; //~ERROR incompatible bit mask diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs old mode 100644 new mode 100755 index b17f5de841b..70cc1919be4 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -45,7 +45,7 @@ fn main() { 1usize as f32; //~ERROR casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) 1isize as i32; //~ERROR casting isize to i32 may truncate the value on targets with 64-bit wide pointers 1isize as u32; //~ERROR casting isize to u32 may lose the sign of the value - //~^ERROR casting isize to u32 may truncate the value on targets with 64-bit wide pointers + //~^ERROR casting isize to u32 may truncate the value on targets with 64-bit wide pointers 1usize as u32; //~ERROR casting usize to u32 may truncate the value on targets with 64-bit wide pointers 1usize as i32; //~ERROR casting usize to i32 may truncate the value on targets with 64-bit wide pointers //~^ERROR casting usize to i32 may wrap around the value on targets with 32-bit wide pointers @@ -60,4 +60,4 @@ fn main() { 1u32 as usize; // Should not trigger any lint 1i32 as isize; // Neither should this 1i32 as usize; //~ERROR casting i32 to usize may lose the sign of the value -} \ No newline at end of file +} diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs index 44bc9f1b199..e55a0390ff3 100755 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -17,7 +17,7 @@ fn canon() { #[deny(non_ascii_literal)] fn uni() { print!("Üben!"); //~ERROR literal non-ASCII character detected - print!("\u{DC}ben!"); // this is okay + print!("\u{DC}ben!"); // this is okay } fn main() { -- cgit 1.4.1-3-g733a5 From b8cdefb6cfab11087943bb41824bb955c655daf1 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Tue, 29 Sep 2015 13:11:19 +0200 Subject: Add unnecessary mut passed lint --- README.md | 3 ++- src/lib.rs | 3 +++ src/mut_reference.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/mut_reference.rs diff --git a/README.md b/README.md index e15ed7e8fce..427f4181dea 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 58 lints included in this crate: +There are 59 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -63,6 +63,7 @@ name [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function only demands an immutable reference [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention diff --git a/src/lib.rs b/src/lib.rs index 3c2d870aee2..2f71d8cc9df 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ pub mod eta_reduction; pub mod identity_op; pub mod minmax; pub mod mut_mut; +pub mod mut_reference; pub mod len_zero; pub mod attrs; pub mod collapsible_if; @@ -66,6 +67,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); reg.register_late_lint_pass(box mut_mut::MutMut); + reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); reg.register_late_lint_pass(box len_zero::LenZero); reg.register_late_lint_pass(box misc::CmpOwned); reg.register_late_lint_pass(box attrs::AttrPass); @@ -138,6 +140,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + mut_reference::UNNECESSARY_MUT_PASSED, needless_bool::NEEDLESS_BOOL, precedence::PRECEDENCE, ranges::RANGE_STEP_BY_ZERO, diff --git a/src/mut_reference.rs b/src/mut_reference.rs new file mode 100644 index 00000000000..13cf1e1301e --- /dev/null +++ b/src/mut_reference.rs @@ -0,0 +1,53 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::span_lint; +use rustc::middle::ty::{TypeAndMut, TypeVariants}; + +declare_lint! { + pub UNNECESSARY_MUT_PASSED, + Warn, + "an argument is passed as a mutable reference although the function only demands an \ + immutable reference" +} + + +#[derive(Copy,Clone)] +pub struct UnnecessaryMutPassed; + +impl LintPass for UnnecessaryMutPassed { + fn get_lints(&self) -> LintArray { + lint_array!(UNNECESSARY_MUT_PASSED) + } +} + +impl LateLintPass for UnnecessaryMutPassed { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let &ExprCall(ref fn_expr, ref arguments) = &e.node { + let borrowed_table = cx.tcx.tables.borrow(); + let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { + Some(funtion_type) => funtion_type, + None => unreachable!(), // A function with unknown type is called. + // If this happened the compiler would have aborted the + // compilation long ago. + }; + if let TypeVariants::TyBareFn(_, ref b) = funtion_type.sty { + let parameters = b.sig.skip_binder().inputs.clone(); + for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | + TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { + if let ExprPath(_, path) = fn_expr.node.clone() { + span_lint(cx, UNNECESSARY_MUT_PASSED, + argument.span, &format!("This argument of the \ + function \"{}\" doesn't need to be mutable", path)); + } + } + }, + _ => {} + } + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 40e180d8c777a7689b20033b9c9eba982a9cebda Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Tue, 29 Sep 2015 13:16:53 +0200 Subject: Replace tabs by spaces --- src/mut_reference.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 13cf1e1301e..96e78256f4e 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -23,28 +23,28 @@ impl LintPass for UnnecessaryMutPassed { impl LateLintPass for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let &ExprCall(ref fn_expr, ref arguments) = &e.node { - let borrowed_table = cx.tcx.tables.borrow(); - let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { - Some(funtion_type) => funtion_type, - None => unreachable!(), // A function with unknown type is called. - // If this happened the compiler would have aborted the - // compilation long ago. - }; + let borrowed_table = cx.tcx.tables.borrow(); + let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { + Some(funtion_type) => funtion_type, + None => unreachable!(), // A function with unknown type is called. + // If this happened the compiler would have aborted the + // compilation long ago. + }; if let TypeVariants::TyBareFn(_, ref b) = funtion_type.sty { let parameters = b.sig.skip_binder().inputs.clone(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { - if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { - if let ExprPath(_, path) = fn_expr.node.clone() { - span_lint(cx, UNNECESSARY_MUT_PASSED, + TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | + TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { + if let ExprPath(_, path) = fn_expr.node.clone() { + span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("This argument of the \ function \"{}\" doesn't need to be mutable", path)); - } - } - }, - _ => {} + } + } + }, + _ => {} } } } -- cgit 1.4.1-3-g733a5 From 185da552635321d51be06e66115199f11a586289 Mon Sep 17 00:00:00 2001 From: Ravi Shankar <wafflespeanut@gmail.com> Date: Sun, 27 Sep 2015 13:09:42 +0530 Subject: extending while_let to warn for more statements --- src/loops.rs | 67 ++++++++++++++++++++++++++++++++-------- src/matches.rs | 2 +- src/utils.rs | 12 +++++-- tests/compile-fail/while_loop.rs | 16 +++------- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 4afa31ff515..b48ae13e73a 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -6,6 +6,7 @@ use rustc::middle::ty; use rustc::middle::def::DefLocal; use consts::{constant_simple, Constant}; use rustc::front::map::Node::{NodeBlock}; +use std::borrow::Cow; use std::collections::{HashSet,HashMap}; use syntax::ast::Lit_::*; @@ -159,10 +160,27 @@ impl LateLintPass for LoopsPass { } } // check for `loop { if let {} else break }` that could be `while let` - // (also matches explicit "match" instead of "if let") + // (also matches an explicit "match" instead of "if let") + // (even if the "match" or "if let" is used for declaration) if let ExprLoop(ref block, _) = expr.node { + // extract the first statement (if any) in a block + let inner_stmt = extract_expr_from_first_stmt(block); // extract a single expression - if let Some(inner) = extract_single_expr(block) { + let inner_expr = extract_first_expr(block); + let extracted = match inner_stmt { + Some(_) => inner_stmt, + None => inner_expr, + }; + + if let Some(inner) = extracted { + // collect remaining expressions below the match + let other_stuff = block.stmts + .iter() + .skip(1) + .map(|stmt| { + format!("{}", snippet(cx, stmt.span, "..")) + }).collect::<Vec<String>>(); + if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { @@ -174,12 +192,19 @@ impl LateLintPass for LoopsPass { is_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { return; } + let loop_body = match inner_stmt { + // FIXME: should probably be an ellipsis + // tabbing and newline is probably a bad idea, especially for large blocks + Some(_) => Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))), + None => expr_block(cx, &arms[0].body, + Some(other_stuff.join("\n ")), ".."), + }; span_help_and_lint(cx, WHILE_LET_LOOP, expr.span, "this loop could be written as a `while let` loop", &format!("try\nwhile let {} = {} {}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, matchexpr.span, ".."), - expr_block(cx, &arms[0].body, ".."))); + loop_body)); }, _ => () } @@ -276,23 +301,38 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { } fn is_iterable_array(ty: ty::Ty) -> bool { - //IntoIterator is currently only implemented for array sizes <= 32 in rustc + // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { ty::TyArray(_, 0...32) => true, _ => false } } -/// If block consists of a single expression (with or without semicolon), return it. -fn extract_single_expr(block: &Block) -> Option<&Expr> { - match (&block.stmts.len(), &block.expr) { - (&1, &None) => match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), +/// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. +fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { + match block.expr { + Some(_) => None, + None => match block.stmts[0].node { + StmtDecl(ref decl, _) => match decl.node { + DeclLocal(ref local) => match local.init { + Some(ref expr) => Some(expr), + None => None, + }, + _ => None, + }, + _ => None, + }, + } +} + +/// If a block begins with an expression (with or without semicolon), return it. +fn extract_first_expr(block: &Block) -> Option<&Expr> { + match block.expr { + Some(ref expr) => Some(expr), + None => match block.stmts[0].node { + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), _ => None, }, - (&0, &Some(ref expr)) => Some(expr), - _ => None } } @@ -300,7 +340,8 @@ fn extract_single_expr(block: &Block) -> Option<&Expr> { fn is_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(None) => true, - ExprBlock(ref b) => match extract_single_expr(b) { + // there won't be a `let <pat> = break` and so we can safely ignore the StmtDecl case + ExprBlock(ref b) => match extract_first_expr(b) { Some(ref subexpr) => is_break_expr(subexpr), None => false, }, diff --git a/src/matches.rs b/src/matches.rs index 4e49cd3ff73..e935a6aa6e1 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -43,7 +43,7 @@ impl LateLintPass for MatchPass { &format!("try\nif let {} = {} {}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, ".."))); + expr_block(cx, &arms[0].body, None, ".."))); } // check preconditions for MATCH_REF_PATS diff --git a/src/utils.rs b/src/utils.rs index 250e24ac646..09924d902d3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -130,12 +130,18 @@ pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) - } /// Like snippet_block, but add braces if the expr is not an ExprBlock -pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, default: &'a str) -> Cow<'a, str> { +/// Also takes an Option<String> which can be put inside the braces +pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, + option: Option<String>, + default: &'a str) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); + let string = option.map_or("".to_owned(), |s| s); if let ExprBlock(_) = expr.node { - code - } else { + Cow::Owned(format!("{}{}", code, string)) + } else if string.is_empty() { Cow::Owned(format!("{{ {} }}", code)) + } else { + Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) } } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index bc09168fad0..ef798b2a79e 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -4,13 +4,6 @@ #[deny(while_let_loop)] fn main() { let y = Some(true); - loop { //~ERROR - if let Some(_x) = y { - let _v = 1; - } else { - break; - } - } loop { //~ERROR if let Some(_x) = y { let _v = 1; @@ -30,12 +23,13 @@ fn main() { None => break }; } - loop { // no error, match is not the only statement - match y { - Some(_x) => true, + loop { //~ERROR + let x = match y { + Some(x) => x, None => break }; - let _x = 1; + let _x = x; + let _str = "foo"; } loop { // no error, else branch does something other than break match y { -- cgit 1.4.1-3-g733a5 From e2a6c9e375c1d160133aadb202a948245e73e750 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Tue, 29 Sep 2015 18:43:38 +0200 Subject: Add unnecessary mut passed lint for methods --- src/mut_reference.rs | 76 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 96e78256f4e..16973ea987a 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -1,12 +1,12 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::span_lint; -use rustc::middle::ty::{TypeAndMut, TypeVariants}; +use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall}; declare_lint! { pub UNNECESSARY_MUT_PASSED, Warn, - "an argument is passed as a mutable reference although the function only demands an \ + "an argument is passed as a mutable reference although the function/method only demands an \ immutable reference" } @@ -22,32 +22,62 @@ impl LintPass for UnnecessaryMutPassed { impl LateLintPass for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let &ExprCall(ref fn_expr, ref arguments) = &e.node { - let borrowed_table = cx.tcx.tables.borrow(); - let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { - Some(funtion_type) => funtion_type, - None => unreachable!(), // A function with unknown type is called. - // If this happened the compiler would have aborted the - // compilation long ago. - }; - if let TypeVariants::TyBareFn(_, ref b) = funtion_type.sty { - let parameters = b.sig.skip_binder().inputs.clone(); - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { - match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { - if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { - if let ExprPath(_, path) = fn_expr.node.clone() { + match e.node { + ExprCall(ref fn_expr, ref arguments) => { + let borrowed_table = cx.tcx.tables.borrow(); + let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { + Some(funtion_type) => funtion_type, + None => unreachable!(), // A function with unknown type is called. + // If this happened the compiler would have aborted the + // compilation long ago. + }; + if let TypeVariants::TyBareFn(_, ref b) = funtion_type.sty { + let parameters = b.sig.skip_binder().inputs.clone(); + for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | + TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { + if let ExprPath(_, path) = fn_expr.node.clone() { + span_lint(cx, UNNECESSARY_MUT_PASSED, + argument.span, &format!("This argument of the \ + function \"{}\" doesn't need to be mutable", path)); + } + } + }, + _ => {} + } + } + } + }, + ExprMethodCall(ref name, _, ref arguments) => { + let method_call = MethodCall::expr(e.id); + let borrowed_table = cx.tcx.tables.borrow(); + let method_type = match borrowed_table.method_map.get(&method_call) { + Some(method_type) => method_type, + None => unreachable!(), // Just like above, this should never happen. + }; + if let TypeVariants::TyBareFn(_, ref b) = method_type.ty.sty { + let parameters = b.sig.skip_binder().inputs.iter().clone(); + for (argument, parameter) in arguments.iter().zip(parameters).skip(1) { + // Skip the first argument and the first parameter because it is the + // struct the function is called on. + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | + TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("This argument of the \ - function \"{}\" doesn't need to be mutable", path)); + method \"{}\" doesn't need to be mutable", + name.node.as_str())); } - } - }, - _ => {} + }, + _ => {} + } } } - } + }, + _ => {} } } } -- cgit 1.4.1-3-g733a5 From e42f00e470b1f61b02f325f1ba0c7795c0725bfc Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Tue, 29 Sep 2015 18:52:19 +0200 Subject: Change description of unnecessary mut passed lint --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 427f4181dea..5d65143f366 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ name [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) -[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function only demands an immutable reference +[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -- cgit 1.4.1-3-g733a5 From 33a0799fa9777a4e2735faa8c4d6595db5cb6179 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 30 Sep 2015 13:08:29 +0200 Subject: Remove unnecessary clones and add helper function --- src/mut_reference.rs | 79 +++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 16973ea987a..1cc04e096ba 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -1,7 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::span_lint; -use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall}; +use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; +use syntax::ptr::P; declare_lint! { pub UNNECESSARY_MUT_PASSED, @@ -22,62 +23,52 @@ impl LintPass for UnnecessaryMutPassed { impl LateLintPass for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + let borrowed_table = cx.tcx.tables.borrow(); match e.node { ExprCall(ref fn_expr, ref arguments) => { - let borrowed_table = cx.tcx.tables.borrow(); - let funtion_type = match borrowed_table.node_types.get(&fn_expr.id) { - Some(funtion_type) => funtion_type, + match borrowed_table.node_types.get(&fn_expr.id) { + Some(function_type) => { + if let ExprPath(_, ref path) = fn_expr.node { + check_arguments(cx, &arguments, function_type, + &format!("{}", path)); + } + }, None => unreachable!(), // A function with unknown type is called. // If this happened the compiler would have aborted the // compilation long ago. }; - if let TypeVariants::TyBareFn(_, ref b) = funtion_type.sty { - let parameters = b.sig.skip_binder().inputs.clone(); - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { - match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { - if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { - if let ExprPath(_, path) = fn_expr.node.clone() { - span_lint(cx, UNNECESSARY_MUT_PASSED, - argument.span, &format!("This argument of the \ - function \"{}\" doesn't need to be mutable", path)); - } - } - }, - _ => {} - } - } - } + + }, ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); - let borrowed_table = cx.tcx.tables.borrow(); - let method_type = match borrowed_table.method_map.get(&method_call) { - Some(method_type) => method_type, + match borrowed_table.method_map.get(&method_call) { + Some(method_type) => check_arguments(cx, &arguments, method_type.ty, + &format!("{}", name.node.as_str())), None => unreachable!(), // Just like above, this should never happen. }; - if let TypeVariants::TyBareFn(_, ref b) = method_type.ty.sty { - let parameters = b.sig.skip_binder().inputs.iter().clone(); - for (argument, parameter) in arguments.iter().zip(parameters).skip(1) { - // Skip the first argument and the first parameter because it is the - // struct the function is called on. - match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { - if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, UNNECESSARY_MUT_PASSED, - argument.span, &format!("This argument of the \ - method \"{}\" doesn't need to be mutable", - name.node.as_str())); - } - }, - _ => {} - } - } - } }, _ => {} } } } + +fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { + if let TypeVariants::TyBareFn(_, ref fn_type) = type_definition.sty { + let parameters = &fn_type.sig.skip_binder().inputs; + for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | + TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { + span_lint(cx, UNNECESSARY_MUT_PASSED, + argument.span, &format!("The function/method \"{}\" \ + doesn't need a mutable reference", + name)); + } + }, + _ => {} + } + } + } +} -- cgit 1.4.1-3-g733a5 From 52aee99f6dcb2d7bb217c066d9b79d5fd61d1b45 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 30 Sep 2015 13:27:09 +0200 Subject: Add test for unnecessary mut passed lint --- tests/compile-fail/mut_reference.rs | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/compile-fail/mut_reference.rs diff --git a/tests/compile-fail/mut_reference.rs b/tests/compile-fail/mut_reference.rs new file mode 100644 index 00000000000..8d3723b1752 --- /dev/null +++ b/tests/compile-fail/mut_reference.rs @@ -0,0 +1,43 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn takes_an_immutable_reference(a: &i32) { +} + +fn takes_a_mutable_reference(a: &mut i32) { +} + +struct MyStruct; + +impl MyStruct { + fn takes_an_immutable_reference(&self, a: &i32) { + } + + fn takes_a_mutable_reference(&self, a: &mut i32) { + } +} + +#[deny(unnecessary_mut_passed)] +fn main() { + // Functions + takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference + + // Methods + let my_struct = MyStruct; + my_struct.takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference + + + // No error + + // Functions + takes_an_immutable_reference(&42); + takes_a_mutable_reference(&mut 42); + let mut a = &mut 42; + takes_an_immutable_reference(a); + + // Methods + my_struct.takes_an_immutable_reference(&42); + my_struct.takes_a_mutable_reference(&mut 42); + my_struct.takes_an_immutable_reference(a); + +} -- cgit 1.4.1-3-g733a5 From 4fc17e7fafcc59223fd9047b18829e052e074226 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 30 Sep 2015 19:54:41 +0530 Subject: rustup to rustc 1.5.0-nightly (65d5c0833 2015-09-29) --- src/lifetimes.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index b64fa148ef3..e39a41316a0 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -177,18 +177,10 @@ impl RefVisitor { } impl<'v> Visitor<'v> for RefVisitor { - // for lifetimes of references - fn visit_opt_lifetime_ref(&mut self, _: Span, lifetime: &'v Option<Lifetime>) { - self.record(lifetime); - } - // for lifetimes as parameters of generics - fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.record(&Some(*lifetime)); } - - // for lifetime bounds; the default impl calls visit_lifetime_ref - fn visit_lifetime_bound(&mut self, _: &'v Lifetime) { } } /// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to -- cgit 1.4.1-3-g733a5 From f76f4d52c261eaaa94028b2c864a405affeb2f6a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 30 Sep 2015 20:10:54 +0530 Subject: Fix rustup fallout: lifetimes false positives --- src/lifetimes.rs | 10 ++++++++++ tests/compile-fail/lifetimes.rs | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index e39a41316a0..206424de9b5 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -89,6 +89,9 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, // extract lifetimes in input argument types for arg in &func.inputs { walk_ty(&mut input_visitor, &arg.ty); + if let TyRptr(None, _) = arg.ty.node { + input_visitor.record(&None); + } } // extract lifetimes in output type if let Return(ref ty) = func.output { @@ -181,6 +184,13 @@ impl<'v> Visitor<'v> for RefVisitor { fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.record(&Some(*lifetime)); } + + fn visit_ty(&mut self, ty: &'v Ty) { + if let TyRptr(None, _) = ty.node { + self.record(&None); + } + walk_ty(self, ty); + } } /// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 0b24ca65241..a654c452379 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -81,5 +81,9 @@ impl<'a> Foo<'a> { fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {} // no error, bounds exist } +fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { + unimplemented!() +} + fn main() { } -- cgit 1.4.1-3-g733a5 From c5ab8d62e304e546ae685880272edd0ab949e69d Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 30 Sep 2015 18:00:14 +0200 Subject: Fix tests --- tests/compile-fail/for_loop.rs | 2 +- tests/compile-fail/mut_reference.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index d6d73db3c18..11810242a88 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -16,7 +16,7 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist,shadow_unrelated)] +#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; diff --git a/tests/compile-fail/mut_reference.rs b/tests/compile-fail/mut_reference.rs index 8d3723b1752..59c0aaf0c32 100644 --- a/tests/compile-fail/mut_reference.rs +++ b/tests/compile-fail/mut_reference.rs @@ -1,9 +1,12 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(unused_variable)] + fn takes_an_immutable_reference(a: &i32) { } + fn takes_a_mutable_reference(a: &mut i32) { } @@ -32,7 +35,7 @@ fn main() { // Functions takes_an_immutable_reference(&42); takes_a_mutable_reference(&mut 42); - let mut a = &mut 42; + let a = &mut 42; takes_an_immutable_reference(a); // Methods -- cgit 1.4.1-3-g733a5 From 390168cc0f8eae3f30a49decd690f667ff211773 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 30 Sep 2015 18:17:55 +0200 Subject: Well, fix them again --- tests/compile-fail/mut_reference.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/mut_reference.rs b/tests/compile-fail/mut_reference.rs index 59c0aaf0c32..7480add8e68 100644 --- a/tests/compile-fail/mut_reference.rs +++ b/tests/compile-fail/mut_reference.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused_variable)] +#![allow(unused_variables)] fn takes_an_immutable_reference(a: &i32) { } -- cgit 1.4.1-3-g733a5 From 431c3918189f845d3a57f0290857971ee03a7d33 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 2 Oct 2015 13:25:34 +0530 Subject: Fix a panic caused by while let --- src/loops.rs | 6 ++++-- tests/compile-fail/while_loop.rs | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 23be0ce728f..2069a56f78f 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -312,7 +312,7 @@ fn is_iterable_array(ty: ty::Ty) -> bool { fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { match block.expr { Some(_) => None, - None => match block.stmts[0].node { + None if !block.stmts.is_empty() => match block.stmts[0].node { StmtDecl(ref decl, _) => match decl.node { DeclLocal(ref local) => match local.init { Some(ref expr) => Some(expr), @@ -322,6 +322,7 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { }, _ => None, }, + _ => None, } } @@ -329,10 +330,11 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) => Some(expr), - None => match block.stmts[0].node { + None if !block.stmts.is_empty() => match block.stmts[0].node { StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), _ => None, }, + _ => None, } } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index ef798b2a79e..eca2c7e12ae 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -1,7 +1,9 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(while_let_loop)] +#![deny(while_let_loop)] +#![allow(dead_code, unused)] + fn main() { let y = Some(true); loop { //~ERROR @@ -44,3 +46,18 @@ fn main() { println!("{}", x); } } + +// regression test (#360) +// this should not panic +// it's okay if further iterations of the lint +// cause this function to trigger it +fn no_panic<T>(slice: &[T]) { + let mut iter = slice.iter(); + loop { + let _ = match iter.next() { + Some(ele) => ele, + None => break + }; + loop {} + } +} -- cgit 1.4.1-3-g733a5 From cd3b21907b256ce846169680239f61c336fd4edd Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 2 Oct 2015 13:26:04 +0530 Subject: bump --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5ff911c8ced..0946855e356 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.17" +version = "0.0.18" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 846602a87680089c0cda6e4c21d1181205b9d4aa Mon Sep 17 00:00:00 2001 From: Josh Stone <cuviper@gmail.com> Date: Fri, 2 Oct 2015 11:07:56 -0700 Subject: Update the DefLocal pattern DefLocal now contains a DefId too, since rust-lang/rust@a0dc2d9a29218. --- src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loops.rs b/src/loops.rs index 2069a56f78f..ee978932d09 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -501,7 +501,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { - if let DefLocal(node_id) = path_res.base_def { + if let DefLocal(_, node_id) = path_res.base_def { return Some(node_id) } } -- cgit 1.4.1-3-g733a5 From 7a129a1340d5f68c1f171370ba9407eef5198a59 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 6 Oct 2015 00:50:06 +0530 Subject: Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0946855e356..f8b70fd87b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.18" +version = "0.0.19" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 85ac8343431ef693ca07dcbce1e73f17f4c5ec7d Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 5 Oct 2015 22:02:05 +0200 Subject: RingBuf was renamed to VecDeque (fixes #363) --- README.md | 2 +- src/types.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e15ed7e8fce..2147530ff57 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ name [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a RingBuf +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 diff --git a/src/types.rs b/src/types.rs index dd41b4f2239..e9125085bb5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -20,7 +20,7 @@ declare_lint!(pub BOX_VEC, Warn, "usage of `Box<Vec<T>>`, vector elements are already on the heap"); declare_lint!(pub LINKEDLIST, Warn, "usage of LinkedList, usually a vector is faster, or a more specialized data \ - structure like a RingBuf"); + structure like a VecDeque"); impl LintPass for TypePass { fn get_lints(&self) -> LintArray { @@ -43,7 +43,7 @@ impl LateLintPass for TypePass { span_help_and_lint( cx, LINKEDLIST, ast_ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a RingBuf might work"); + "a VecDeque might work"); } } } -- cgit 1.4.1-3-g733a5 From f8aa0431bdea0b5adb8a53a7a8eb32b091759561 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 7 Oct 2015 01:17:57 +0200 Subject: Suggest using an atomic value instead of a Mutex where possible --- README.md | 3 ++- src/lib.rs | 3 +++ src/mutex_atomic.rs | 51 ++++++++++++++++++++++++++++++++++++++ src/utils.rs | 1 + tests/compile-fail/mutex_atomic.rs | 15 +++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/mutex_atomic.rs create mode 100644 tests/compile-fail/mutex_atomic.rs diff --git a/README.md b/README.md index a5ab856fc21..a09a9fefc35 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 59 lints included in this crate: +There are 60 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -37,6 +37,7 @@ name [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do diff --git a/src/lib.rs b/src/lib.rs index 2f71d8cc9df..0e560978979 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub mod loops; pub mod ranges; pub mod matches; pub mod precedence; +pub mod mutex_atomic; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -88,6 +89,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); + reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -141,6 +143,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, mut_reference::UNNECESSARY_MUT_PASSED, + mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, precedence::PRECEDENCE, ranges::RANGE_STEP_BY_ZERO, diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs new file mode 100644 index 00000000000..6cf71fe23bc --- /dev/null +++ b/src/mutex_atomic.rs @@ -0,0 +1,51 @@ +//! Checks for uses of Mutex where an atomic value could be used +//! +//! This lint is **warn** by default + +use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; +use rustc_front::hir::Expr; + +use syntax::ast; +use rustc::middle::ty; +use rustc::middle::subst::ParamSpace; + +use utils::{span_lint, MUTEX_PATH, match_type}; + +declare_lint! { + pub MUTEX_ATOMIC, + Warn, + "using a Mutex where an atomic value could be used instead" +} + +impl LintPass for MutexAtomic { + fn get_lints(&self) -> LintArray { + lint_array!(MUTEX_ATOMIC) + } +} +pub struct MutexAtomic; + +impl LateLintPass for MutexAtomic { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + let ty = cx.tcx.expr_ty(expr); + if let &ty::TyStruct(_, subst) = &ty.sty { + if match_type(cx, ty, &MUTEX_PATH) { + let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; + if let Some(atomic_name) = get_atomic_name(mutex_param) { + let msg = format!("Consider using an {} instead of a \ + Mutex here.", atomic_name); + span_lint(cx, MUTEX_ATOMIC, expr.span, &msg); + } + } + } + } +} + +fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { + match *ty { + ty::TyBool => Some("AtomicBool"), + ty::TyUint(ast::TyUs) => Some("AtomicUsize"), + ty::TyInt(ast::TyIs) => Some("AtomicIsize"), + ty::TyRawPtr(_) => Some("AtomicPtr"), + _ => None + } +} diff --git a/src/utils.rs b/src/utils.rs index ac155617011..4c9f1fb4b3e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -14,6 +14,7 @@ pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; /// returns true this expn_info was expanded by any macro pub fn in_macro(cx: &LateContext, span: Span) -> bool { diff --git a/tests/compile-fail/mutex_atomic.rs b/tests/compile-fail/mutex_atomic.rs new file mode 100644 index 00000000000..97e08d7ba36 --- /dev/null +++ b/tests/compile-fail/mutex_atomic.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(clippy)] + +fn main() { + use std::sync::Mutex; + Mutex::new(true); //~ERROR Consider using an AtomicBool instead of a Mutex here. + Mutex::new(5usize); //~ERROR Consider using an AtomicUsize instead of a Mutex here. + Mutex::new(9isize); //~ERROR Consider using an AtomicIsize instead of a Mutex here. + let mut x = 4u32; + Mutex::new(&x as *const u32); //~ERROR Consider using an AtomicPtr instead of a Mutex here. + Mutex::new(&mut x as *mut u32); //~ERROR Consider using an AtomicPtr instead of a Mutex here. + Mutex::new(0f32); // there are no float atomics, so this should not lint +} -- cgit 1.4.1-3-g733a5 From 7644f8e2a1774c426f520efc50fe3626b31e028c Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 7 Oct 2015 13:15:14 +0200 Subject: Add "nonsensical OpenOptions" lint --- README.md | 3 +- src/lib.rs | 3 + src/open_options.rs | 139 +++++++++++++++++++++++++++++++++++++ src/utils.rs | 11 +-- tests/compile-fail/open_options.rs | 16 +++++ 5 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 src/open_options.rs create mode 100644 tests/compile-fail/open_options.rs diff --git a/README.md b/README.md index a5ab856fc21..96465d9fd35 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 59 lints included in this crate: +There are 60 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -42,6 +42,7 @@ name [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | The options used for opening a file are nonsensical [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively diff --git a/src/lib.rs b/src/lib.rs index 2f71d8cc9df..44f8e9e5b98 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub mod loops; pub mod ranges; pub mod matches; pub mod precedence; +pub mod open_options; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -88,6 +89,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); + reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -142,6 +144,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::TOPLEVEL_REF_ARG, mut_reference::UNNECESSARY_MUT_PASSED, needless_bool::NEEDLESS_BOOL, + open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, diff --git a/src/open_options.rs b/src/open_options.rs new file mode 100644 index 00000000000..d91305c36c2 --- /dev/null +++ b/src/open_options.rs @@ -0,0 +1,139 @@ +use rustc::lint::*; +use rustc_front::hir::{Expr, ExprMethodCall, ExprLit}; +use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; +use syntax::codemap::{Span, Spanned}; +use syntax::ast::Lit_::LitBool; + +declare_lint! { + pub NONSENSICAL_OPEN_OPTIONS, + Warn, + "The options used for opening a file are nonsensical" +} + + +#[derive(Copy,Clone)] +pub struct NonSensicalOpenOptions; + +impl LintPass for NonSensicalOpenOptions { + fn get_lints(&self) -> LintArray { + lint_array!(NONSENSICAL_OPEN_OPTIONS) + } +} + +impl LateLintPass for NonSensicalOpenOptions { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprMethodCall(ref name, _, ref arguments) = e.node { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); + if name.node.as_str() == "open" && match_type(cx, obj_ty, &OPEN_OPTIONS_PATH){ + let mut options = Vec::new(); + get_open_options(cx, &arguments[0], &mut options); + check_open_options(cx, &options, e.span); + } + } + } +} + +#[derive(Debug)] +enum Argument { + True, + False, + Unknown +} + +#[derive(Debug)] +enum OpenOption { + Write(Argument), + Read(Argument), + Truncate(Argument), + Create(Argument), + Append(Argument) +} + +fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<OpenOption>) { + if let ExprMethodCall(ref name, _, ref arguments) = argument.node { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); + + // Only proceed if this is a call on some object of type std::fs::OpenOptions + if match_type(cx, obj_ty, &OPEN_OPTIONS_PATH) && arguments.len() >= 2 { + + let argument_option = match arguments[1].node { + ExprLit(ref span) => { + if let Spanned {node: LitBool(lit), span: _} = **span { + if lit {Argument::True} else {Argument::False} + } else { + return; // The function is called with a literal + // which is not a boolean literal. This is theoretically + // possible, but not very likely. + } + }, + _ => { + Argument::Unknown + } + }; + + match &*name.node.as_str() { + "create" => { + options.push(OpenOption::Create(argument_option)); + }, + "append" => { + options.push(OpenOption::Append(argument_option)); + }, + "truncate" => { + options.push(OpenOption::Truncate(argument_option)); + }, + "read" => { + options.push(OpenOption::Read(argument_option)); + }, + "write" => { + options.push(OpenOption::Write(argument_option)); + }, + _ => {} + } + + get_open_options(cx, &arguments[0], options); + } + } +} + +fn check_for_duplicates(cx: &LateContext, options: &[OpenOption], span: Span) { + // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. + if options.iter().filter(|o| if let OpenOption::Create(_) = **o {true} else {false}).count() > 1 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"create\" \ + is called more than once"); + } + if options.iter().filter(|o| if let OpenOption::Append(_) = **o {true} else {false}).count() > 1 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"append\" \ + is called more than once"); + } + if options.iter().filter(|o| if let OpenOption::Truncate(_) = **o {true} else {false}).count() > 1 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"truncate\" \ + is called more than once"); + } + if options.iter().filter(|o| if let OpenOption::Read(_) = **o {true} else {false}).count() > 1 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"read\" \ + is called more than once"); + } + if options.iter().filter(|o| if let OpenOption::Write(_) = **o {true} else {false}).count() > 1 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"write\" \ + is called more than once"); + } +} + +fn check_for_inconsistencies(cx: &LateContext, options: &[OpenOption], span: Span) { + // Truncate + read makes no sense. + if options.iter().filter(|o| if let OpenOption::Read(Argument::True) = **o {true} else {false}).count() > 0 && + options.iter().filter(|o| if let OpenOption::Truncate(Argument::True) = **o {true} else {false}).count() > 0 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\""); + } + + // Append + truncate makes no sense. + if options.iter().filter(|o| if let OpenOption::Append(Argument::True) = **o {true} else {false}).count() > 0 && + options.iter().filter(|o| if let OpenOption::Truncate(Argument::True) = **o {true} else {false}).count() > 0 { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"append\" and \"truncate\""); + } +} + +fn check_open_options(cx: &LateContext, options: &[OpenOption], span: Span) { + check_for_duplicates(cx, options, span); + check_for_inconsistencies(cx, options, span); +} diff --git a/src/utils.rs b/src/utils.rs index ac155617011..1f4fb2b251d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,11 +9,12 @@ use std::borrow::Cow; use syntax::ast::Lit_::*; // module DefPaths for certain structs/enums we check for -pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; -pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; /// returns true this expn_info was expanded by any macro pub fn in_macro(cx: &LateContext, span: Span) -> bool { diff --git a/tests/compile-fail/open_options.rs b/tests/compile-fail/open_options.rs new file mode 100644 index 00000000000..35cc91c9d0f --- /dev/null +++ b/tests/compile-fail/open_options.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] +use std::fs::OpenOptions; + +#[allow(unused_must_use)] +#[deny(nonsensical_open_options)] +fn main() { + OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~ERROR File opened with "truncate" and "read" + OpenOptions::new().append(true).truncate(true).open("foo.txt"); //~ERROR File opened with "append" and "truncate" + + OpenOptions::new().read(true).read(false).open("foo.txt"); //~ERROR The method "read" is called more than once + OpenOptions::new().create(true).create(false).open("foo.txt"); //~ERROR The method "create" is called more than once + OpenOptions::new().write(true).write(false).open("foo.txt"); //~ERROR The method "write" is called more than once + OpenOptions::new().append(true).append(false).open("foo.txt"); //~ERROR The method "append" is called more than once + OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); //~ERROR The method "truncate" is called more than once +} -- cgit 1.4.1-3-g733a5 From b7c6c30c8835254e2cb7c5fada886ffa7685bbd4 Mon Sep 17 00:00:00 2001 From: Pyriphlegethon <pyriphlegethon.github@gmail.com> Date: Wed, 7 Oct 2015 17:15:44 +0200 Subject: Change lint description --- README.md | 2 +- src/open_options.rs | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 96465d9fd35..6c6849ba105 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ name [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | The options used for opening a file are nonsensical +[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively diff --git a/src/open_options.rs b/src/open_options.rs index d91305c36c2..76a2eeef1ba 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -7,7 +7,7 @@ use syntax::ast::Lit_::LitBool; declare_lint! { pub NONSENSICAL_OPEN_OPTIONS, Warn, - "The options used for opening a file are nonsensical" + "nonsensical combination of options for opening a file" } @@ -42,14 +42,14 @@ enum Argument { #[derive(Debug)] enum OpenOption { - Write(Argument), - Read(Argument), - Truncate(Argument), - Create(Argument), - Append(Argument) + Write, + Read, + Truncate, + Create, + Append } -fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<OpenOption>) { +fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { if let ExprMethodCall(ref name, _, ref arguments) = argument.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); @@ -73,19 +73,19 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<OpenOpt match &*name.node.as_str() { "create" => { - options.push(OpenOption::Create(argument_option)); + options.push((OpenOption::Create, argument_option)); }, "append" => { - options.push(OpenOption::Append(argument_option)); + options.push((OpenOption::Append, argument_option)); }, "truncate" => { - options.push(OpenOption::Truncate(argument_option)); + options.push((OpenOption::Truncate, argument_option)); }, "read" => { - options.push(OpenOption::Read(argument_option)); + options.push((OpenOption::Read, argument_option)); }, "write" => { - options.push(OpenOption::Write(argument_option)); + options.push((OpenOption::Write, argument_option)); }, _ => {} } @@ -95,45 +95,45 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<OpenOpt } } -fn check_for_duplicates(cx: &LateContext, options: &[OpenOption], span: Span) { +fn check_for_duplicates(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. - if options.iter().filter(|o| if let OpenOption::Create(_) = **o {true} else {false}).count() > 1 { + if options.iter().filter(|o| if let (OpenOption::Create, _) = **o {true} else {false}).count() > 1 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"create\" \ is called more than once"); } - if options.iter().filter(|o| if let OpenOption::Append(_) = **o {true} else {false}).count() > 1 { + if options.iter().filter(|o| if let (OpenOption::Append, _) = **o {true} else {false}).count() > 1 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"append\" \ is called more than once"); } - if options.iter().filter(|o| if let OpenOption::Truncate(_) = **o {true} else {false}).count() > 1 { + if options.iter().filter(|o| if let (OpenOption::Truncate, _) = **o {true} else {false}).count() > 1 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"truncate\" \ is called more than once"); } - if options.iter().filter(|o| if let OpenOption::Read(_) = **o {true} else {false}).count() > 1 { + if options.iter().filter(|o| if let (OpenOption::Read, _) = **o {true} else {false}).count() > 1 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"read\" \ is called more than once"); } - if options.iter().filter(|o| if let OpenOption::Write(_) = **o {true} else {false}).count() > 1 { + if options.iter().filter(|o| if let (OpenOption::Write, _) = **o {true} else {false}).count() > 1 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"write\" \ is called more than once"); } } -fn check_for_inconsistencies(cx: &LateContext, options: &[OpenOption], span: Span) { +fn check_for_inconsistencies(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { // Truncate + read makes no sense. - if options.iter().filter(|o| if let OpenOption::Read(Argument::True) = **o {true} else {false}).count() > 0 && - options.iter().filter(|o| if let OpenOption::Truncate(Argument::True) = **o {true} else {false}).count() > 0 { + if options.iter().filter(|o| if let (OpenOption::Read, Argument::True) = **o {true} else {false}).count() > 0 && + options.iter().filter(|o| if let (OpenOption::Truncate, Argument::True) = **o {true} else {false}).count() > 0 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\""); } // Append + truncate makes no sense. - if options.iter().filter(|o| if let OpenOption::Append(Argument::True) = **o {true} else {false}).count() > 0 && - options.iter().filter(|o| if let OpenOption::Truncate(Argument::True) = **o {true} else {false}).count() > 0 { + if options.iter().filter(|o| if let (OpenOption::Append, Argument::True) = **o {true} else {false}).count() > 0 && + options.iter().filter(|o| if let (OpenOption::Truncate, Argument::True) = **o {true} else {false}).count() > 0 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"append\" and \"truncate\""); } } -fn check_open_options(cx: &LateContext, options: &[OpenOption], span: Span) { +fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { check_for_duplicates(cx, options, span); check_for_inconsistencies(cx, options, span); } -- cgit 1.4.1-3-g733a5 From 26b2733b15a0011ff1569e059ae7520d1a3a519d Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 7 Oct 2015 22:58:34 +0200 Subject: Add a lint for sized integer types in a mutex --- README.md | 3 ++- src/lib.rs | 1 + src/mutex_atomic.rs | 21 +++++++++++++++++---- tests/compile-fail/mutex_atomic.rs | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a09a9fefc35..50789cc3db2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 60 lints included in this crate: +There are 61 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -38,6 +38,7 @@ name [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) [mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead +[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do diff --git a/src/lib.rs b/src/lib.rs index 0e560978979..3483efea868 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, mut_mut::MUT_MUT, + mutex_atomic::MUTEX_INTEGER, ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 6cf71fe23bc..994e7937984 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -17,11 +17,18 @@ declare_lint! { "using a Mutex where an atomic value could be used instead" } +declare_lint! { + pub MUTEX_INTEGER, + Allow, + "using a Mutex for an integer type" +} + impl LintPass for MutexAtomic { fn get_lints(&self) -> LintArray { - lint_array!(MUTEX_ATOMIC) + lint_array!(MUTEX_ATOMIC, MUTEX_INTEGER) } } + pub struct MutexAtomic; impl LateLintPass for MutexAtomic { @@ -33,7 +40,13 @@ impl LateLintPass for MutexAtomic { if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!("Consider using an {} instead of a \ Mutex here.", atomic_name); - span_lint(cx, MUTEX_ATOMIC, expr.span, &msg); + match *mutex_param { + ty::TyUint(t) if t != ast::TyUs => + span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyInt(t) if t != ast::TyIs => + span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg) + } } } } @@ -43,8 +56,8 @@ impl LateLintPass for MutexAtomic { fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { match *ty { ty::TyBool => Some("AtomicBool"), - ty::TyUint(ast::TyUs) => Some("AtomicUsize"), - ty::TyInt(ast::TyIs) => Some("AtomicIsize"), + ty::TyUint(_) => Some("AtomicUsize"), + ty::TyInt(_) => Some("AtomicIsize"), ty::TyRawPtr(_) => Some("AtomicPtr"), _ => None } diff --git a/tests/compile-fail/mutex_atomic.rs b/tests/compile-fail/mutex_atomic.rs index 97e08d7ba36..20a34ba5547 100644 --- a/tests/compile-fail/mutex_atomic.rs +++ b/tests/compile-fail/mutex_atomic.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![deny(clippy)] +#![deny(mutex_integer)] fn main() { use std::sync::Mutex; @@ -11,5 +12,7 @@ fn main() { let mut x = 4u32; Mutex::new(&x as *const u32); //~ERROR Consider using an AtomicPtr instead of a Mutex here. Mutex::new(&mut x as *mut u32); //~ERROR Consider using an AtomicPtr instead of a Mutex here. + Mutex::new(0u32); //~ERROR Consider using an AtomicUsize instead of a Mutex here. + Mutex::new(0i32); //~ERROR Consider using an AtomicIsize instead of a Mutex here. Mutex::new(0f32); // there are no float atomics, so this should not lint } -- cgit 1.4.1-3-g733a5 From 6b7fff93bc343027b601d3abfe6e1435447ade23 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 8 Oct 2015 00:35:32 +0200 Subject: Fix documentation that disagrees with code --- src/ptr_arg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 7c369469ea2..be11ebce26a 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -1,6 +1,6 @@ //! Checks for usage of &Vec[_] and &String //! -//! This lint is **warn** by default +//! This lint is **allow** by default use rustc::lint::*; use rustc_front::hir::*; -- cgit 1.4.1-3-g733a5 From b48db27152caf31c892312bc8a8ea8db7418e157 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Sun, 11 Oct 2015 16:07:00 +0200 Subject: Recommend using Mutex<()> for locking --- src/mutex_atomic.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 994e7937984..9c10a062419 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -39,7 +39,10 @@ impl LateLintPass for MutexAtomic { let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!("Consider using an {} instead of a \ - Mutex here.", atomic_name); + Mutex here. If you just want the \ + locking behaviour and not the internal \ + type, consider using Mutex<()>.", + atomic_name); match *mutex_param { ty::TyUint(t) if t != ast::TyUs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), -- cgit 1.4.1-3-g733a5 From 4e2b09831bd67ad52954d5cfb48eae066b3d4c00 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 12 Oct 2015 02:42:21 +0530 Subject: Rust upgrade to rustc 1.5.0-nightly (9d3e79ad3 2015-10-10) --- src/lib.rs | 2 +- src/returns.rs | 28 ++++----- src/shadow.rs | 3 +- src/types.rs | 10 +-- src/utils.rs | 139 +++++++++++++++++++++++------------------- tests/compile-fail/strings.rs | 6 +- 6 files changed, 102 insertions(+), 86 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2f71d8cc9df..6503c5e1006 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box misc::ModuloOne); reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); - reg.register_late_lint_pass(box returns::ReturnPass); + reg.register_early_lint_pass(box returns::ReturnPass); reg.register_late_lint_pass(box methods::MethodsPass); reg.register_late_lint_pass(box shadow::ShadowPass); reg.register_late_lint_pass(box types::LetPass); diff --git a/src/returns.rs b/src/returns.rs index d04307ffd5d..3df4efd0889 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,10 +1,10 @@ use rustc::lint::*; -use rustc_front::hir::*; -use reexport::*; +use syntax::ast::*; +//use reexport::*; use syntax::codemap::{Span, Spanned}; -use rustc_front::visit::FnKind; +use syntax::visit::FnKind; -use utils::{span_lint, snippet, match_path, in_external_macro}; +use utils::{span_lint, snippet, match_path_ast, in_external_macro}; declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); @@ -17,7 +17,7 @@ pub struct ReturnPass; impl ReturnPass { // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &LateContext, block: &Block) { + fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) { if let Some(ref expr) = block.expr { self.check_final_expr(cx, expr); } else if let Some(stmt) = block.stmts.last() { @@ -30,7 +30,7 @@ impl ReturnPass { } // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &LateContext, expr: &Expr) { + fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) { match expr.node { // simple return is always "bad" ExprRet(Some(ref inner)) => { @@ -48,7 +48,7 @@ impl ReturnPass { self.check_final_expr(cx, elsexpr); } // a match expr, check all arms - ExprMatch(_, ref arms, _) => { + ExprMatch(_, ref arms) => { for arm in arms { self.check_final_expr(cx, &arm.body); } @@ -57,7 +57,7 @@ impl ReturnPass { } } - fn emit_return_lint(&mut self, cx: &LateContext, spans: (Span, Span)) { + fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { if in_external_macro(cx, spans.1) {return;} span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using `{}` \ @@ -66,7 +66,7 @@ impl ReturnPass { } // Check for "let x = EXPR; x" - fn check_let_return(&mut self, cx: &LateContext, block: &Block) { + fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { // we need both a let-binding stmt and an expr if_let_chain! { [ @@ -77,14 +77,14 @@ impl ReturnPass { let Some(ref initexpr) = local.init, let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, let ExprPath(_, ref path) = retexpr.node, - match_path(path, &[&id.name.as_str()]) + match_path_ast(path, &[&id.name.as_str()]) ], { self.emit_let_lint(cx, retexpr.span, initexpr.span); } } } - fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) { + fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { if in_external_macro(cx, note_span) {return;} span_lint(cx, LET_AND_RETURN, lint_span, "returning the result of a let binding from a block. \ @@ -102,13 +102,13 @@ impl LintPass for ReturnPass { } } -impl LateLintPass for ReturnPass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl, +impl EarlyLintPass for ReturnPass { + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { self.check_block_return(cx, block); } - fn check_block(&mut self, cx: &LateContext, block: &Block) { + fn check_block(&mut self, cx: &EarlyContext, block: &Block) { self.check_let_return(cx, block); } } diff --git a/src/shadow.rs b/src/shadow.rs index 8fd8d0d15ac..13df95bf8dd 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -7,7 +7,7 @@ use rustc_front::visit::FnKind; use rustc::lint::*; use rustc::middle::def::Def::{DefVariant, DefStruct}; -use utils::{in_external_macro, snippet, span_lint, span_note_and_lint}; +use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint}; declare_lint!(pub SHADOW_SAME, Allow, "rebinding a name to itself, e.g. `let mut x = &mut x`"); @@ -60,6 +60,7 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)> fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } + if is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } diff --git a/src/types.rs b/src/types.rs index e9125085bb5..584f9b34988 100644 --- a/src/types.rs +++ b/src/types.rs @@ -9,7 +9,8 @@ use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; use syntax::ast::FloatTy::*; -use utils::{match_type, snippet, span_lint, span_help_and_lint, in_macro, in_external_macro}; +use utils::{match_type, snippet, span_lint, span_help_and_lint}; +use utils::{is_from_for_desugar, in_macro, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types @@ -61,9 +62,10 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) { if *bindtype == ty::TyTuple(vec![]) { if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { return; } - span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( - "this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, ".."))); + if is_from_for_desugar(decl) { return; } + span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( + "this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, ".."))); } } } diff --git a/src/utils.rs b/src/utils.rs index ac155617011..34a6d25af25 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -7,6 +7,7 @@ use rustc::middle::def_id::DefId; use rustc::middle::ty; use std::borrow::Cow; use syntax::ast::Lit_::*; +use syntax::ast; // module DefPaths for certain structs/enums we check for pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; @@ -15,15 +16,56 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +/// Produce a nested chain of if-lets and ifs from the patterns: +/// +/// if_let_chain! { +/// [ +/// Some(y) = x, +/// y.len() == 2, +/// Some(z) = y, +/// ], +/// { +/// block +/// } +/// } +/// +/// becomes +/// +/// if let Some(y) = x { +/// if y.len() == 2 { +/// if let Some(z) = y { +/// block +/// } +/// } +/// } +#[macro_export] +macro_rules! if_let_chain { + ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { + if let $pat = $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([let $pat:pat = $expr:expr], $block:block) => { + if let $pat = $expr { + $block + } + }; + ([$expr:expr, $($tt:tt)+], $block:block) => { + if $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([$expr:expr], $block:block) => { + if $expr { + $block + } + }; +} + /// returns true this expn_info was expanded by any macro pub fn in_macro(cx: &LateContext, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, - |info| info.map_or(false, |i| { - match i.callee.format { - ExpnFormat::CompilerExpansion(..) => false, - _ => true, - } - })) + |info| info.is_some()) } /// returns true if the macro that expanded the crate was outside of @@ -34,17 +76,9 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { - match info.callee.format { - ExpnFormat::CompilerExpansion(..) => { - if info.callee.name().as_str() == "closure expansion" { - return false; - } - }, - ExpnFormat::MacroAttribute(..) => { - // these are all plugins - return true; - }, - _ => (), + if let ExpnFormat::MacroAttribute(..) = info.callee.format { + // these are all plugins + return true; } // no span for the callee = external macro info.callee.span.map_or(true, |span| { @@ -102,6 +136,13 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { |(a, b)| a.identifier.name.as_str() == *b) } +/// match a Path against a slice of segment string literals, e.g. +/// `match_path(path, &["std", "rt", "begin_unwind"])` +pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all( + |(a, b)| a.identifier.name.as_str() == *b) +} + /// get the name of the item the expression is in, if available pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); @@ -115,6 +156,24 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { } } +/// checks if a `let` decl is from a for loop desugaring +pub fn is_from_for_desugar(decl: &Decl) -> bool { + if_let_chain! { + [ + let DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + // FIXME: This should check for MatchSource::ForLoop + // but right now there's a bug where the match source isn't + // set during lowering + // https://github.com/rust-lang/rust/pull/28973 + let ExprMatch(_, _, _) = expr.node + ], + { return true; } + }; + false +} + + /// convert a span to a code snippet if available, otherwise use default, e.g. /// `snippet(cx, expr.span, "..")` pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { @@ -262,49 +321,3 @@ pub fn is_integer_literal(expr: &Expr, value: u64) -> bool } false } - -/// Produce a nested chain of if-lets and ifs from the patterns: -/// -/// if_let_chain! { -/// [ -/// Some(y) = x, -/// y.len() == 2, -/// Some(z) = y, -/// ], -/// { -/// block -/// } -/// } -/// -/// becomes -/// -/// if let Some(y) = x { -/// if y.len() == 2 { -/// if let Some(z) = y { -/// block -/// } -/// } -/// } -#[macro_export] -macro_rules! if_let_chain { - ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { - if let $pat = $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([let $pat:pat = $expr:expr], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([$expr:expr, $($tt:tt)+], $block:block) => { - if $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([$expr:expr], $block:block) => { - if $expr { - $block - } - }; -} diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 7e21294a3d1..1ba8616ed29 100755 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -6,7 +6,7 @@ fn add_only() { // ignores assignment distinction let mut x = "".to_owned(); - for _ in (1..3) { + for _ in 1..3 { x = x + "."; //~ERROR you added something to a string. } @@ -20,7 +20,7 @@ fn add_only() { // ignores assignment distinction fn add_assign_only() { let mut x = "".to_owned(); - for _ in (1..3) { + for _ in 1..3 { x = x + "."; //~ERROR you assigned the result of adding something to this string. } @@ -34,7 +34,7 @@ fn add_assign_only() { fn both() { let mut x = "".to_owned(); - for _ in (1..3) { + for _ in 1..3 { x = x + "."; //~ERROR you assigned the result of adding something to this string. } -- cgit 1.4.1-3-g733a5 From b02e80c0124ad356f5b5be4f8ae4e23c0bf33efc Mon Sep 17 00:00:00 2001 From: swgillespie <sean.william.g@gmail.com> Date: Sun, 11 Oct 2015 19:22:13 -0700 Subject: implement 0.0/0.0 -> NaN lint as described in #370 casing of NaN --- README.md | 3 ++- src/lib.rs | 3 +++ src/zero_div_zero.rs | 50 +++++++++++++++++++++++++++++++++++++ tests/compile-fail/zero_div_zero.rs | 16 ++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/zero_div_zero.rs create mode 100644 tests/compile-fail/zero_div_zero.rs diff --git a/README.md b/README.md index a5ab856fc21..44262eba8a1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 59 lints included in this crate: +There are 60 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -68,6 +68,7 @@ name [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention [wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/lib.rs b/src/lib.rs index 6503c5e1006..8675eb01527 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub mod loops; pub mod ranges; pub mod matches; pub mod precedence; +pub mod zero_div_zero; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -88,6 +89,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); + reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -152,5 +154,6 @@ pub fn plugin_registrar(reg: &mut Registry) { types::TYPE_COMPLEXITY, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, + zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); } diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs new file mode 100644 index 00000000000..37d5d8904e1 --- /dev/null +++ b/src/zero_div_zero.rs @@ -0,0 +1,50 @@ +use rustc::lint::*; +use rustc_front::hir::*; + +use utils::{span_help_and_lint}; +use consts::{Constant, constant_simple, FloatWidth}; + +/// ZeroDivZeroPass is a pass that checks for a binary expression that consists +/// of 0.0/0.0, which is always NaN. It is more clear to replace instances of +/// 0.0/0.0 with std::f32::NaN or std::f64::NaN, depending on the precision. +pub struct ZeroDivZeroPass; + +declare_lint!(pub ZERO_DIVIDED_BY_ZERO, Warn, + "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN"); + +impl LintPass for ZeroDivZeroPass { + fn get_lints(&self) -> LintArray { + lint_array!(ZERO_DIVIDED_BY_ZERO) + } +} + +impl LateLintPass for ZeroDivZeroPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // check for instances of 0.0/0.0 + if_let_chain! { + [ + let ExprBinary(ref op, ref left, ref right) = expr.node, + let BinOp_::BiDiv = op.node, + // TODO - constant_simple does not fold many operations involving floats. + // That's probably fine for this lint - it's pretty unlikely that someone would + // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. + let Some(Constant::ConstantFloat(ref lhs_value, lhs_width)) = constant_simple(left), + let Some(Constant::ConstantFloat(ref rhs_value, rhs_width)) = constant_simple(right), + let Some(0.0) = lhs_value.parse().ok(), + let Some(0.0) = rhs_value.parse().ok() + ], + { + // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, + // match the precision of the literals that are given. + let float_type = match (lhs_width, rhs_width) { + (FloatWidth::Fw64, _) + | (_, FloatWidth::Fw64) => "f64", + _ => "f32" + }; + span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, + "constant division of 0.0 with 0.0 will always result in NaN", + &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); + } + } + } +} diff --git a/tests/compile-fail/zero_div_zero.rs b/tests/compile-fail/zero_div_zero.rs new file mode 100644 index 00000000000..8c40923d3ed --- /dev/null +++ b/tests/compile-fail/zero_div_zero.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[allow(unused_variables)] +#[deny(zero_divided_by_zero)] +fn main() { + let nan = 0.0 / 0.0; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + let f64_nan = 0.0 / 0.0f64; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + let other_f64_nan = 0.0f64 / 0.0; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + let one_more_f64_nan = 0.0f64/0.0f64; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + let zero = 0.0; + let other_zero = 0.0; + let other_nan = zero / other_zero; // fine - this lint doesn't propegate constants. + let not_nan = 2.0/0.0; // not an error: 2/0 = inf + let also_not_nan = 0.0/2.0; // not an error: 0/2 = 0 +} -- cgit 1.4.1-3-g733a5 From 3632b93d7afe5af15c9daa7e86b775c54ccfbd29 Mon Sep 17 00:00:00 2001 From: Alex Burka <durka42+github@gmail.com> Date: Mon, 12 Oct 2015 01:54:44 -0400 Subject: fix doc comment for if_let_chain! --- src/utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 34a6d25af25..df730a4c021 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,9 +20,9 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "Linke /// /// if_let_chain! { /// [ -/// Some(y) = x, +/// let Some(y) = x, /// y.len() == 2, -/// Some(z) = y, +/// let Some(z) = y, /// ], /// { /// block -- cgit 1.4.1-3-g733a5 From be2fb9ba113125c0ad3c156b3bcedb036eac60c2 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 12 Oct 2015 07:59:08 +0200 Subject: Remove "are you sure?" from lint msg. No added value, and leads to punctuation clash. --- src/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attrs.rs b/src/attrs.rs index 936548c04f8..79cec664adc 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -99,7 +99,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, if always != &"always" { continue; } span_lint(cx, INLINE_ALWAYS, attr.span, &format!( "you have declared `#[inline(always)]` on `{}`. This \ - is usually a bad idea. Are you sure?", + is usually a bad idea", name)); } } -- cgit 1.4.1-3-g733a5 From fb5fdb61fab3b08a39aeb6713aeadd14f309f376 Mon Sep 17 00:00:00 2001 From: Ravi Shankar <wafflespeanut@gmail.com> Date: Sun, 11 Oct 2015 22:19:01 +0530 Subject: whup the while_let_loop for ignoring expressions! --- src/loops.rs | 43 ++++++++++++++++++++++------------------ tests/compile-fail/while_loop.rs | 10 +++++++++- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index ee978932d09..5657f08fdef 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -163,25 +163,31 @@ impl LateLintPass for LoopsPass { // (also matches an explicit "match" instead of "if let") // (even if the "match" or "if let" is used for declaration) if let ExprLoop(ref block, _) = expr.node { - // extract the first statement (if any) in a block - let inner_stmt = extract_expr_from_first_stmt(block); - // extract a single expression + // extract the expression from the first statement (if any) in a block + let inner_stmt_expr = extract_expr_from_first_stmt(block); + // extract the first expression (if any) from the block let inner_expr = extract_first_expr(block); - let extracted = match inner_stmt { - Some(_) => inner_stmt, - None => inner_expr, + let (extracted, collect_expr) = match inner_stmt_expr { + Some(_) => (inner_stmt_expr, true), // check if an expression exists in the first statement + None => (inner_expr, false), // if not, let's go for the first expression in the block }; if let Some(inner) = extracted { - // collect remaining expressions below the match - let other_stuff = block.stmts - .iter() - .skip(1) - .map(|stmt| { - format!("{}", snippet(cx, stmt.span, "..")) - }).collect::<Vec<String>>(); - if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { + // collect the remaining statements below the match + let mut other_stuff = block.stmts + .iter() + .skip(1) + .map(|stmt| { + format!("{}", snippet(cx, stmt.span, "..")) + }).collect::<Vec<String>>(); + if collect_expr { // if we have a statement which has a match, + match block.expr { // then collect the expression (without semicolon) below it + Some(ref expr) => other_stuff.push(format!("{}", snippet(cx, expr.span, ".."))), + None => (), + } + } + // ensure "if let" compatible match structure match *source { MatchSource::Normal | MatchSource::IfLetDesugar{..} => if @@ -192,7 +198,7 @@ impl LateLintPass for LoopsPass { is_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { return; } - let loop_body = match inner_stmt { + let loop_body = match inner_stmt_expr { // FIXME: should probably be an ellipsis // tabbing and newline is probably a bad idea, especially for large blocks Some(_) => Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))), @@ -310,9 +316,9 @@ fn is_iterable_array(ty: ty::Ty) -> bool { /// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { - match block.expr { - Some(_) => None, - None if !block.stmts.is_empty() => match block.stmts[0].node { + match block.stmts.is_empty() { + true => None, + false => match block.stmts[0].node { StmtDecl(ref decl, _) => match decl.node { DeclLocal(ref local) => match local.init { Some(ref expr) => Some(expr), @@ -322,7 +328,6 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { }, _ => None, }, - _ => None, } } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index eca2c7e12ae..c8444ee0a57 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -33,6 +33,14 @@ fn main() { let _x = x; let _str = "foo"; } + loop { //~ERROR + let x = match y { + Some(x) => x, + None => break, + }; + { let _a = "bar"; }; + { let _b = "foobar"; } + } loop { // no error, else branch does something other than break match y { Some(_x) => true, @@ -53,7 +61,7 @@ fn main() { // cause this function to trigger it fn no_panic<T>(slice: &[T]) { let mut iter = slice.iter(); - loop { + loop { //~ERROR let _ = match iter.next() { Some(ele) => ele, None => break -- cgit 1.4.1-3-g733a5 From 567d5a7293f2a3ab6672919fb0ce8f94c28a6136 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 13 Oct 2015 04:16:05 +0530 Subject: Improve cmp_owned suggestions (fixes #386) --- src/misc.rs | 42 ++++++++++++++++++++++++++--------------- tests/compile-fail/cmp_owned.rs | 6 +++++- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index cf4504d2f67..497bb6692c7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -165,37 +165,49 @@ impl LateLintPass for CmpOwned { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { - check_to_owned(cx, left, right.span); - check_to_owned(cx, right, left.span) + check_to_owned(cx, left, right.span, true, cmp.span); + check_to_owned(cx, right, left.span, false, cmp.span) } } } } -fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span) { - match expr.node { - ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) => { +fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, op: Span) { + let snip = match expr.node { + ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) if args.len() == 1 => { if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. \ - Consider using `{}.as_slice()` to compare without allocation", - snippet(cx, other_span, ".."))) + snippet(cx, args[0].span, "..") + } else { + return } }, - ExprCall(ref path, _) => { + ExprCall(ref path, ref v) if v.len() == 1 => { if let &ExprPath(None, ref path) = &path.node { if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. \ - Consider using `{}.as_slice()` to compare without allocation", - snippet(cx, other_span, ".."))) + snippet(cx, v[0].span, "..") + } else { + return } + } else { + return } }, - _ => () + _ => return + }; + if left { + span_lint(cx, CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. Consider using \ + `{} {} {}` to compare without allocation", snip, + snippet(cx, op, "=="), snippet(cx, other_span, ".."))); + } else { + span_lint(cx, CMP_OWNED, expr.span, &format!( + "this creates an owned instance just for comparison. Consider using \ + `{} {} {}` to compare without allocation", + snippet(cx, other_span, ".."), snippet(cx, op, "=="), snip)); } + } fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index 2765da5cf23..afca83e1d32 100755 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -7,7 +7,11 @@ fn main() { #[allow(str_to_string)] fn with_to_string(x : &str) { - x != "foo".to_string(); //~ERROR this creates an owned instance + x != "foo".to_string(); + //~^ ERROR this creates an owned instance just for comparison. Consider using `x != "foo"` to compare without allocation + + "foo".to_string() != x; + //~^ ERROR this creates an owned instance just for comparison. Consider using `"foo" != x` to compare without allocation } with_to_string(x); -- cgit 1.4.1-3-g733a5 From b2f1940f6f76c78771a2793b97e0cf2c5b459d1f Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 13 Oct 2015 13:48:48 +0200 Subject: improved precedence messages (fixes #389) --- src/precedence.rs | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/precedence.rs b/src/precedence.rs index ce06278b782..b7dbe268557 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,7 +1,9 @@ use rustc::lint::*; use syntax::codemap::Spanned; use syntax::ast::*; -use utils::span_lint; +use syntax::ast_util::binop_to_string; + +use utils::{span_lint, snippet}; declare_lint!(pub PRECEDENCE, Warn, "catches operations where precedence may be unclear. See the wiki for a \ @@ -19,10 +21,24 @@ impl LintPass for Precedence { impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { - if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) { - span_lint(cx, PRECEDENCE, expr.span, - "operator precedence can trip the unwary. Consider adding parentheses \ - to the subexpression"); + if !is_bit_op(op) { return; } + match (is_arith_expr(left), is_arith_expr(right)) { + (true, true) => span_lint(cx, PRECEDENCE, expr.span, + &format!("operator precedence can trip the unwary. \ + Consider parenthesizing your expression:\ + `({}) {} ({})`", snippet(cx, left.span, ".."), + binop_to_string(op), snippet(cx, right.span, ".."))), + (true, false) => span_lint(cx, PRECEDENCE, expr.span, + &format!("operator precedence can trip the unwary. \ + Consider parenthesizing your expression:\ + `({}) {} {}`", snippet(cx, left.span, ".."), + binop_to_string(op), snippet(cx, right.span, ".."))), + (false, true) => span_lint(cx, PRECEDENCE, expr.span, + &format!("operator precedence can trip the unwary. \ + Consider parenthesizing your expression:\ + `{} {} ({})`", snippet(cx, left.span, ".."), + binop_to_string(op), snippet(cx, right.span, ".."))), + _ => (), } } @@ -32,9 +48,11 @@ impl EarlyLintPass for Precedence { if let ExprLit(ref lit) = slf.node { match lit.node { LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => - span_lint(cx, PRECEDENCE, expr.span, - "unary minus has lower precedence than method call. Consider \ - adding parentheses to clarify your intent"), + span_lint(cx, PRECEDENCE, expr.span, &format!( + "unary minus has lower precedence than \ + method call. Consider adding parentheses \ + to clarify your intent: -({})", + snippet(cx, rhs.span, ".."))), _ => () } } -- cgit 1.4.1-3-g733a5 From bed29a017b6c998b671cfd7821111ed550d5ad98 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Mon, 12 Oct 2015 13:38:18 +0200 Subject: new lint to detect --- README.md | 1 + src/lib.rs | 1 + src/loops.rs | 13 ++++++++++++- tests/compile-fail/while_loop.rs | 4 ++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 44262eba8a1..138900937f7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ name [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do diff --git a/src/lib.rs b/src/lib.rs index 8675eb01527..fd7adbed16d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, + loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, loops::ITER_NEXT_LOOP, diff --git a/src/loops.rs b/src/loops.rs index ee978932d09..10f58716dc7 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -36,13 +36,16 @@ declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, "for-looping with an explicit counter when `_.enumerate()` would do" } +declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } + #[derive(Copy, Clone)] pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP) + WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, + EXPLICIT_COUNTER_LOOP, EMPTY_LOOP) } } @@ -163,6 +166,14 @@ impl LateLintPass for LoopsPass { // (also matches an explicit "match" instead of "if let") // (even if the "match" or "if let" is used for declaration) if let ExprLoop(ref block, _) = expr.node { + // also check for empty `loop {}` statements + if block.stmts.is_empty() && block.expr.is_none() { + span_lint(cx, EMPTY_LOOP, expr.span, + "empty `loop {}` detected. You may want to either \ + use `panic!()` or add `std::thread::sleep(..);` to \ + the loop body."); + } + // extract the first statement (if any) in a block let inner_stmt = extract_expr_from_first_stmt(block); // extract a single expression diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index eca2c7e12ae..8e51bf84887 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(while_let_loop)] +#![deny(while_let_loop, empty_loop)] #![allow(dead_code, unused)] fn main() { @@ -58,6 +58,6 @@ fn no_panic<T>(slice: &[T]) { Some(ele) => ele, None => break }; - loop {} + loop {} //~ERROR empty `loop {}` detected. } } -- cgit 1.4.1-3-g733a5 From 6f17e2e3a0fae42cf72e7bbbfe96dd5a96e2e3b7 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 13 Oct 2015 14:45:35 +0200 Subject: update lints --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 138900937f7..c5e6aae7041 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 60 lints included in this crate: +There are 61 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- cgit 1.4.1-3-g733a5 From 871d9fc27c54159bf7ad9dbff5a0fe52a6d84645 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 14 Oct 2015 19:51:54 +0200 Subject: Make ptr_arg lint warn by default --- README.md | 2 +- src/lib.rs | 2 +- src/ptr_arg.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e57ca8d1e02..a0131583597 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ name [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | allow | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern diff --git a/src/lib.rs b/src/lib.rs index 5276ad711c0..8bf199bff47 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,6 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::WRONG_PUB_SELF_CONVENTION, mut_mut::MUT_MUT, mutex_atomic::MUTEX_INTEGER, - ptr_arg::PTR_ARG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, @@ -153,6 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_bool::NEEDLESS_BOOL, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, + ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index be11ebce26a..4baba711886 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -1,6 +1,6 @@ //! Checks for usage of &Vec[_] and &String //! -//! This lint is **allow** by default +//! This lint is **warn** by default use rustc::lint::*; use rustc_front::hir::*; @@ -11,7 +11,7 @@ use utils::{STRING_PATH, VEC_PATH}; declare_lint! { pub PTR_ARG, - Allow, + Warn, "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ instead, respectively" } -- cgit 1.4.1-3-g733a5 From 1f4136dc0844a06ed08d47fb95d3c2bb097bfc5e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 15 Oct 2015 19:22:36 +0530 Subject: bump crates --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f8b70fd87b8..ec205b4a378 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.19" +version = "0.0.20" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 657afc1157fa316a1f1b311e8d54d733e6f50be2 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Thu, 15 Oct 2015 16:02:19 +0200 Subject: rustup --- src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types.rs b/src/types.rs index 584f9b34988..af2deb9aa97 100644 --- a/src/types.rs +++ b/src/types.rs @@ -285,9 +285,9 @@ impl LateLintPass for TypeComplexityPass { fn check_variant(&mut self, cx: &LateContext, var: &Variant, _: &Generics) { // StructVariant is covered by check_struct_field - if let TupleVariantKind(ref args) = var.node.kind { + if let VariantData::Tuple(ref args, _) = *var.node.data { for arg in args { - check_type(cx, &arg.ty); + check_type(cx, &arg.node.ty); } } } -- cgit 1.4.1-3-g733a5 From 7db7559fa57140f1825fd22bbfc9b5cfce3df1d3 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Thu, 15 Oct 2015 16:04:19 +0200 Subject: bump crate version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f8b70fd87b8..ec205b4a378 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.19" +version = "0.0.20" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From be66322886c8fd529733aaef0d3774a80e45b701 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Thu, 15 Oct 2015 16:18:40 +0200 Subject: workaround for failing test --- tests/compile-fail/complex_types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/compile-fail/complex_types.rs b/tests/compile-fail/complex_types.rs index 995132ba88c..f5b21c6df4b 100755 --- a/tests/compile-fail/complex_types.rs +++ b/tests/compile-fail/complex_types.rs @@ -17,6 +17,7 @@ struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>); //~ERROR very complex type enum E { V1(Vec<Vec<Box<(u32, u32, u32, u32)>>>), //~ERROR very complex type + //~^ERROR very complex type V2 { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, //~ERROR very complex type } -- cgit 1.4.1-3-g733a5 From b2f455065401eeb65250815e8ce566239ca69217 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 15 Oct 2015 19:55:14 +0530 Subject: Fix type complexity lint --- src/types.rs | 10 +--------- tests/compile-fail/complex_types.rs | 1 - 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/types.rs b/src/types.rs index af2deb9aa97..93962586bc6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -280,18 +280,10 @@ impl LateLintPass for TypeComplexityPass { } fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { + // enum variants are also struct fields now check_type(cx, &field.node.ty); } - fn check_variant(&mut self, cx: &LateContext, var: &Variant, _: &Generics) { - // StructVariant is covered by check_struct_field - if let VariantData::Tuple(ref args, _) = *var.node.data { - for arg in args { - check_type(cx, &arg.node.ty); - } - } - } - fn check_item(&mut self, cx: &LateContext, item: &Item) { match item.node { ItemStatic(ref ty, _, _) | diff --git a/tests/compile-fail/complex_types.rs b/tests/compile-fail/complex_types.rs index f5b21c6df4b..995132ba88c 100755 --- a/tests/compile-fail/complex_types.rs +++ b/tests/compile-fail/complex_types.rs @@ -17,7 +17,6 @@ struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>); //~ERROR very complex type enum E { V1(Vec<Vec<Box<(u32, u32, u32, u32)>>>), //~ERROR very complex type - //~^ERROR very complex type V2 { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, //~ERROR very complex type } -- cgit 1.4.1-3-g733a5 From e24d4698497b2e86f9a1a1b5d4d72c9ebd2ad659 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 15 Oct 2015 19:56:27 +0530 Subject: bump again --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ec205b4a378..5a553ca77e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.20" +version = "0.0.21" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 1bd023d3e01857b6fff86efb8da7159c84d0be5d Mon Sep 17 00:00:00 2001 From: Florian Gilcher <florian.gilcher@asquera.de> Date: Thu, 15 Oct 2015 11:13:01 +0200 Subject: New lint for needless use of nightly features --- src/lib.rs | 4 +++ src/needless_features.rs | 49 +++++++++++++++++++++++++++++++++ tests/compile-fail/needless_features.rs | 17 ++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/needless_features.rs create mode 100644 tests/compile-fail/needless_features.rs diff --git a/src/lib.rs b/src/lib.rs index 8bf199bff47..31ce6738fd1 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,6 +50,7 @@ pub mod precedence; pub mod mutex_atomic; pub mod zero_div_zero; pub mod open_options; +pub mod needless_features; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -94,6 +95,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); + reg.register_late_lint_pass(box needless_features::NeedlessFeaturesPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -150,6 +152,8 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, + needless_features::AS_SLICE, + needless_features::AS_MUT_SLICE, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, diff --git a/src/needless_features.rs b/src/needless_features.rs new file mode 100644 index 00000000000..950057da26c --- /dev/null +++ b/src/needless_features.rs @@ -0,0 +1,49 @@ +//! Checks for usage of nightly features that have simple stable equivalents +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc_front::hir::*; + +use utils::{span_lint}; + +declare_lint! { + pub AS_SLICE, + Warn, + "as_slice is not stable and can be replaced by & v[..]\ +see https://github.com/rust-lang/rust/issues/27729" +} + +declare_lint! { + pub AS_MUT_SLICE, + Warn, + "as_mut_slice is not stable and can be replaced by &mut v[..]\ +see https://github.com/rust-lang/rust/issues/27729" +} + + +#[derive(Copy,Clone)] +pub struct NeedlessFeaturesPass; + +impl LintPass for NeedlessFeaturesPass { + fn get_lints(&self) -> LintArray { + lint_array!(AS_SLICE,AS_MUT_SLICE) + } +} + +impl LateLintPass for NeedlessFeaturesPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprMethodCall(ref name, _, _) = expr.node { + if name.node.as_str() == "as_slice" { + span_lint(cx, AS_SLICE, expr.span, + "used as_slice() from the 'convert' nightly feature. Use &[..] \ + instead"); + } + if name.node.as_str() == "as_mut_slice" { + span_lint(cx, AS_MUT_SLICE, expr.span, + "used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] \ + instead"); + } + } + } +} \ No newline at end of file diff --git a/tests/compile-fail/needless_features.rs b/tests/compile-fail/needless_features.rs new file mode 100644 index 00000000000..02639aea66f --- /dev/null +++ b/tests/compile-fail/needless_features.rs @@ -0,0 +1,17 @@ +#![feature(plugin)] +#![feature(convert)] +#![plugin(clippy)] + +#![deny(clippy)] + +fn test_as_slice() { + let v = vec![1]; + v.as_slice(); //~ERROR used as_slice() from the 'convert' nightly feature. Use &[..] + + let mut v2 = vec![1]; + v2.as_mut_slice(); //~ERROR used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] +} + +fn main() { + test_as_slice(); +} -- cgit 1.4.1-3-g733a5 From 39e93d572b4fa85a71bbe04a2a1c15bcb445e26c Mon Sep 17 00:00:00 2001 From: Florian Gilcher <florian.gilcher@asquera.de> Date: Thu, 15 Oct 2015 12:53:21 +0200 Subject: Regnerate README.md --- README.md | 4 +++- src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0131583597..5125f6d4e00 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,13 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 64 lints included in this crate: +There are 66 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 +[as_slice](https://github.com/Manishearth/rust-clippy/wiki#as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` diff --git a/src/lib.rs b/src/lib.rs index 31ce6738fd1..3175b92be4e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,8 +152,8 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, - needless_features::AS_SLICE, needless_features::AS_MUT_SLICE, + needless_features::AS_SLICE, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, -- cgit 1.4.1-3-g733a5 From 853368c1d3c92fa699ba5d1bd1cca2cd2703d4d1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 17 Oct 2015 04:33:05 +0530 Subject: Make is_from_for_desugar sound (rust/28973 got fixed) --- src/utils.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 1ba6029ebe6..caf77332b62 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -164,11 +164,7 @@ pub fn is_from_for_desugar(decl: &Decl) -> bool { [ let DeclLocal(ref loc) = decl.node, let Some(ref expr) = loc.init, - // FIXME: This should check for MatchSource::ForLoop - // but right now there's a bug where the match source isn't - // set during lowering - // https://github.com/rust-lang/rust/pull/28973 - let ExprMatch(_, _, _) = expr.node + let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node ], { return true; } }; -- cgit 1.4.1-3-g733a5 From 80639164770bd5755443b52073d358c7496a030a Mon Sep 17 00:00:00 2001 From: Florian Gilcher <florian.gilcher@asquera.de> Date: Sat, 17 Oct 2015 20:16:54 +0200 Subject: Cleanup as discussed in PR --- src/lib.rs | 4 ++-- src/needless_features.rs | 22 +++++++++++++--------- src/utils.rs | 13 +++++++++++++ tests/compile-fail/needless_features.rs | 12 ++++++++++++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3175b92be4e..a3657460fe9 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,8 +152,8 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, - needless_features::AS_MUT_SLICE, - needless_features::AS_SLICE, + needless_features::UNSTABLE_AS_MUT_SLICE, + needless_features::UNSTABLE_AS_SLICE, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, diff --git a/src/needless_features.rs b/src/needless_features.rs index 950057da26c..b1d38df7311 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -6,44 +6,48 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::{span_lint}; +use utils; declare_lint! { - pub AS_SLICE, + pub UNSTABLE_AS_SLICE, Warn, "as_slice is not stable and can be replaced by & v[..]\ see https://github.com/rust-lang/rust/issues/27729" } declare_lint! { - pub AS_MUT_SLICE, + pub UNSTABLE_AS_MUT_SLICE, Warn, "as_mut_slice is not stable and can be replaced by &mut v[..]\ see https://github.com/rust-lang/rust/issues/27729" } - #[derive(Copy,Clone)] pub struct NeedlessFeaturesPass; impl LintPass for NeedlessFeaturesPass { fn get_lints(&self) -> LintArray { - lint_array!(AS_SLICE,AS_MUT_SLICE) + lint_array!(UNSTABLE_AS_SLICE,UNSTABLE_AS_MUT_SLICE) } } impl LateLintPass for NeedlessFeaturesPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(ref name, _, _) = expr.node { - if name.node.as_str() == "as_slice" { - span_lint(cx, AS_SLICE, expr.span, + if name.node.as_str() == "as_slice" && check_paths(cx, expr) { + span_lint(cx, UNSTABLE_AS_SLICE, expr.span, "used as_slice() from the 'convert' nightly feature. Use &[..] \ instead"); } - if name.node.as_str() == "as_mut_slice" { - span_lint(cx, AS_MUT_SLICE, expr.span, + if name.node.as_str() == "as_mut_slice" && check_paths(cx, expr) { + span_lint(cx, UNSTABLE_AS_MUT_SLICE, expr.span, "used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] \ instead"); } } } -} \ No newline at end of file +} + +fn check_paths(cx: &LateContext, expr: &Expr) -> bool { + utils::match_impl_method(cx, expr, &["collections", "vec", "Vec<T>"]) +} diff --git a/src/utils.rs b/src/utils.rs index 1ba6029ebe6..c3ebfd8147d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -118,6 +118,19 @@ pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { } } +/// check if method call given in "expr" belongs to given trait +pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + + let trt_id = cx.tcx.tables + .borrow().method_map.get(&method_call) + .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} /// check if method call given in "expr" belongs to given trait pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); diff --git a/tests/compile-fail/needless_features.rs b/tests/compile-fail/needless_features.rs index 02639aea66f..dee2a19d5d0 100644 --- a/tests/compile-fail/needless_features.rs +++ b/tests/compile-fail/needless_features.rs @@ -12,6 +12,18 @@ fn test_as_slice() { v2.as_mut_slice(); //~ERROR used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] } +struct ShouldWork; + +impl ShouldWork { + fn as_slice(&self) -> &ShouldWork { self } +} + +fn test_should_work() { + let sw = ShouldWork; + sw.as_slice(); +} + fn main() { test_as_slice(); + test_should_work(); } -- cgit 1.4.1-3-g733a5 From 2951b70d1575f62771ac2da007ef426f9ac600c6 Mon Sep 17 00:00:00 2001 From: Vikas Kumar <kr.vikas@gmail.com> Date: Tue, 20 Oct 2015 10:18:48 -0700 Subject: Match on bool should be replaced with if..else block 1. Added another conditional in `check_expr` impl to lint if match expr is a bool. 2. Test cases. --- src/lib.rs | 1 + src/matches.rs | 19 ++++++++++++++++++- tests/compile-fail/matches.rs | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a3657460fe9..6d6c6dfeeb0 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,6 +138,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::WHILE_LET_LOOP, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, + matches::MATCH_BOOL, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, diff --git a/src/matches.rs b/src/matches.rs index e935a6aa6e1..0606c244747 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; +use rustc::middle::ty; use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; @@ -9,13 +10,15 @@ declare_lint!(pub SINGLE_MATCH, Warn, declare_lint!(pub MATCH_REF_PATS, Warn, "a match has all arms prefixed with `&`; the match expression can be \ dereferenced instead"); +declare_lint!(pub MATCH_BOOL, Warn, + "a match on boolean expression; recommends `if..else` block instead"); #[allow(missing_copy_implementations)] pub struct MatchPass; impl LintPass for MatchPass { fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH, MATCH_REF_PATS) + lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL) } } @@ -59,6 +62,16 @@ impl LateLintPass for MatchPass { expression to match: `match *{} {{ ...`", snippet(cx, ex.span, ".."))); } } + + // check preconditions for MATCH_BOOL + // type of expression == bool + if is_bool_expr(cx, ex) { + if in_external_macro(cx, expr.span) { return; } + + span_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using if..else block"); + } } } } @@ -71,6 +84,10 @@ fn is_unit_expr(expr: &Expr) -> bool { } } +fn is_bool_expr(cx: &LateContext, ex: &Expr ) -> bool { + cx.tcx.expr_ty(ex).sty == ty::TyBool +} + fn has_only_ref_pats(arms: &[Arm]) -> bool { let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node { PatRegion(..) => Some(true), // &-patterns diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index f25a5fa3fa4..1cdf813bc00 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -38,6 +38,28 @@ fn single_match(){ } } +fn match_bool() { + let test: bool = true; + + match test { //~ ERROR you seem to be trying to match on a boolean expression + true => (), + false => (), + }; + + let option = 1; + match option == 1 { //~ ERROR you seem to be trying to match on a boolean expression + true => (), + false => (), + }; + + // Not linted + match option { + 1 ... 10 => (), + 10 ... 20 => (), + _ => (), + }; +} + fn ref_pats() { { let v = &Some(0); -- cgit 1.4.1-3-g733a5 From 675c532eabadeb5e203e71336a50fbf70f7decde Mon Sep 17 00:00:00 2001 From: Vikas Kumar <kr.vikas@gmail.com> Date: Tue, 20 Oct 2015 10:25:37 -0700 Subject: Ran util/update_lints.py to auto gen doc and lib.rs --- README.md | 3 ++- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e50407eaaaa..990db2e5460 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 66 lints included in this crate: +There are 67 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -34,6 +34,7 @@ name [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 diff --git a/src/lib.rs b/src/lib.rs index 6d6c6dfeeb0..6f06641ef45 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,9 +136,9 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::REVERSE_RANGE_LOOP, loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, + matches::MATCH_BOOL, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, - matches::MATCH_BOOL, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, -- cgit 1.4.1-3-g733a5 From 5e78fbbf57e5bf5891c116a3c1bf287212744efa Mon Sep 17 00:00:00 2001 From: Vikas Kumar <kr.vikas@gmail.com> Date: Tue, 20 Oct 2015 11:26:54 -0700 Subject: Fixups from review comments 1. Moved common check `in_external_macro` to the top of function from inside each conditionals. 2. Inlined `is_bool_expr` call --- src/matches.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 0606c244747..da770c6f484 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -25,6 +25,8 @@ impl LintPass for MatchPass { impl LateLintPass for MatchPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { + if in_external_macro(cx, expr.span) { return; } + // check preconditions for SINGLE_MATCH // only two arms if arms.len() == 2 && @@ -39,7 +41,6 @@ impl LateLintPass for MatchPass { // finally, we don't want any content in the second arm (unit or empty block) is_unit_expr(&arms[1].body) { - if in_external_macro(cx, expr.span) {return;} span_help_and_lint(cx, SINGLE_MATCH, expr.span, "you seem to be trying to use match for destructuring a \ single pattern. Consider using `if let`", @@ -51,7 +52,6 @@ impl LateLintPass for MatchPass { // check preconditions for MATCH_REF_PATS if has_only_ref_pats(arms) { - if in_external_macro(cx, expr.span) { return; } if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { span_lint(cx, MATCH_REF_PATS, expr.span, &format!( "you don't need to add `&` to both the expression to match \ @@ -65,12 +65,11 @@ impl LateLintPass for MatchPass { // check preconditions for MATCH_BOOL // type of expression == bool - if is_bool_expr(cx, ex) { - if in_external_macro(cx, expr.span) { return; } + if cx.tcx.expr_ty(ex).sty == ty::TyBool { span_lint(cx, MATCH_BOOL, expr.span, "you seem to be trying to match on a boolean expression. \ - Consider using if..else block"); + Consider using an if..else block"); } } } @@ -84,10 +83,6 @@ fn is_unit_expr(expr: &Expr) -> bool { } } -fn is_bool_expr(cx: &LateContext, ex: &Expr ) -> bool { - cx.tcx.expr_ty(ex).sty == ty::TyBool -} - fn has_only_ref_pats(arms: &[Arm]) -> bool { let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node { PatRegion(..) => Some(true), // &-patterns -- cgit 1.4.1-3-g733a5 From da82e2d3baee6061ca28894ac053cd5e3f332927 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 21 Oct 2015 08:24:56 +0200 Subject: added code snippet help to match_bool --- src/matches.rs | 53 +++++++++++++++++++++++++++++++++++++++++-- tests/compile-fail/matches.rs | 19 +++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index da770c6f484..a7cfefd7af5 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,6 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; +use syntax::ast::Lit_::LitBool; use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; @@ -66,10 +67,58 @@ impl LateLintPass for MatchPass { // check preconditions for MATCH_BOOL // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { - - span_lint(cx, MATCH_BOOL, expr.span, + if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards + let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { + if let ExprLit(ref lit) = arm_bool.node { + if let LitBool(val) = lit.node { + if val { + Some((&*arms[0].body, &*arms[1].body)) + } else { + Some((&*arms[1].body, &*arms[0].body)) + } + } else { None } + } else { None } + } else { None }; + if let Some((ref true_expr, ref false_expr)) = exprs { + if !is_unit_expr(true_expr) { + if !is_unit_expr(false_expr) { + span_help_and_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block:", + &format!("try\nif {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))); + } else { + span_help_and_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block:", + &format!("try\nif {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."))); + } + } else if !is_unit_expr(false_expr) { + span_help_and_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block:", + &format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))); + } else { + span_lint(cx, MATCH_BOOL, expr.span, "you seem to be trying to match on a boolean expression. \ Consider using an if..else block"); + } + } else { + span_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block"); + } + } else { + span_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block"); + } } } } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 1cdf813bc00..f0cc650f753 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -48,8 +48,25 @@ fn match_bool() { let option = 1; match option == 1 { //~ ERROR you seem to be trying to match on a boolean expression + true => 1, + false => 0, + }; + + match test { //~ ERROR you seem to be trying to match on a boolean expression true => (), - false => (), + false => { println!("Noooo!"); }, + }; + + match test { //~ ERROR you seem to be trying to match on a boolean expression + //~^ERROR you seem to be trying to use match + //TODO: Remove duplicate warning + false => { println!("Noooo!"); }, + _ => (), + }; + + match test { //~ ERROR you seem to be trying to match on a boolean expression + false => { println!("Noooo!"); }, + true => { println!("Yes!"); }, }; // Not linted -- cgit 1.4.1-3-g733a5 From d843257643637facfa7308c2c85e677442298738 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Thu, 22 Oct 2015 00:25:16 +0900 Subject: New lint for struct update that has no effect --- README.md | 3 ++- src/lib.rs | 3 +++ src/needless_update.rs | 35 +++++++++++++++++++++++++++++++++++ tests/compile-fail/needless_update.rs | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/needless_update.rs create mode 100644 tests/compile-fail/needless_update.rs diff --git a/README.md b/README.md index 990db2e5460..3e56e863287 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 67 lints included in this crate: +There are 68 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -45,6 +45,7 @@ name [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` diff --git a/src/lib.rs b/src/lib.rs index 6f06641ef45..d5d27e5e2af 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ pub mod mutex_atomic; pub mod zero_div_zero; pub mod open_options; pub mod needless_features; +pub mod needless_update; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -96,6 +97,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_features::NeedlessFeaturesPass); + reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -155,6 +157,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_bool::NEEDLESS_BOOL, needless_features::UNSTABLE_AS_MUT_SLICE, needless_features::UNSTABLE_AS_SLICE, + needless_update::NEEDLESS_UPDATE, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, diff --git a/src/needless_update.rs b/src/needless_update.rs new file mode 100644 index 00000000000..c65d0c9e7d3 --- /dev/null +++ b/src/needless_update.rs @@ -0,0 +1,35 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::middle::ty::TyStruct; +use rustc_front::hir::{Expr, ExprStruct}; + +use utils::span_lint; + +declare_lint! { + pub NEEDLESS_UPDATE, + Warn, + "using `{ ..base }` when there are no missing fields" +} + +#[derive(Copy, Clone)] +pub struct NeedlessUpdatePass; + +impl LintPass for NeedlessUpdatePass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_UPDATE) + } +} + +impl LateLintPass for NeedlessUpdatePass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { + let ty = cx.tcx.expr_ty(expr); + if let TyStruct(def, _) = ty.sty { + if fields.len() == def.struct_variant().fields.len() { + span_lint(cx, NEEDLESS_UPDATE, base.span, + "struct update has no effect, all the fields \ + in the struct have already been specified"); + } + } + } + } +} diff --git a/tests/compile-fail/needless_update.rs b/tests/compile-fail/needless_update.rs new file mode 100644 index 00000000000..55438d9d90a --- /dev/null +++ b/tests/compile-fail/needless_update.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(needless_update)] + +struct S { + pub a: i32, + pub b: i32, +} + +fn main() { + let base = S { a: 0, b: 0 }; + S { ..base }; // no error + S { a: 1, ..base }; // no error + S { a: 1, b: 1, ..base }; //~ERROR struct update has no effect +} -- cgit 1.4.1-3-g733a5 From 546eb14b7ef847545d91c10e48b564a30b51fc60 Mon Sep 17 00:00:00 2001 From: Kevin Yap <me@kevinyap.ca> Date: Thu, 22 Oct 2015 15:19:03 -0700 Subject: Change implementation of approx_const lint - Replace epsilon with lower and upper bounds for each constant. - Warn on use of "3.14", and update tests accordingly. --- src/approx_const.rs | 50 +++++++++++++++++++++----------------- tests/compile-fail/approx_const.rs | 3 ++- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 9a186a4f8cd..19753aaf844 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use rustc_front::hir::*; -use std::f64::consts as f64; use utils::span_lint; use syntax::ast::Lit_::*; use syntax::ast::Lit; @@ -13,14 +12,26 @@ declare_lint! { is found; suggests to use the constant" } -const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), - (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), - (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), - (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; - -const EPSILON_DIVISOR : f64 = 8192f64; //TODO: test to find a good value +// Tuples are of the form (name, lower_bound, upper_bound) +#[allow(approx_constant)] +const KNOWN_CONSTS : &'static [(&'static str, f64, f64)] = &[ + ("E", 2.7101, 2.7200), + ("FRAC_1_PI", 0.31829, 0.31840), + ("FRAC_1_SQRT_2", 0.7071, 0.7072), + ("FRAC_2_PI", 0.6366, 0.6370), + ("FRAC_2_SQRT_PI", 1.1283, 1.1284), + ("FRAC_PI_2", 1.5707, 1.5708), + ("FRAC_PI_3", 1.0471, 1.0472), + ("FRAC_PI_4", 0.7853, 0.7854), + ("FRAC_PI_6", 0.5235, 0.5236), + ("FRAC_PI_8", 0.3926, 0.3927), + ("LN_10", 2.302, 2.303), + ("LN_2", 0.6931, 0.6932), + ("LOG10_E", 0.4342, 0.4343), + ("LOG2_E", 1.4426, 1.4427), + ("PI", 3.140, 3.142), + ("SQRT_2", 1.4142, 1.4143), +]; #[derive(Copy,Clone)] pub struct ApproxConstant; @@ -49,19 +60,14 @@ fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { } } -fn check_known_consts(cx: &LateContext, e: &Expr, str: &str, module: &str) { - if let Ok(value) = str.parse::<f64>() { - for &(constant, name) in KNOWN_CONSTS { - if !within_epsilon(constant, value) { continue; } - span_lint(cx, APPROX_CONSTANT, e.span, &format!( - "approximate value of `{}::{}` found. \ - Consider using it directly", module, &name)); +fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { + if let Ok(value) = s.parse::<f64>() { + for &(name, lower_bound, upper_bound) in KNOWN_CONSTS { + if (value >= lower_bound) && (value < upper_bound) { + span_lint(cx, APPROX_CONSTANT, e.span, &format!( + "approximate value of `{}::{}` found. \ + Consider using it directly", module, &name)); + } } } } - -fn within_epsilon(target: f64, value: f64) -> bool { - f64::abs(value - target) < f64::abs(if target > value { - target - } else { value }) / EPSILON_DIVISOR -} diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index a75cd0bf3f2..ebd5d3ea139 100755 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -49,7 +49,8 @@ fn main() { let no_log2_e = 1.442; let my_pi = 3.1415; //~ERROR approximate value of `f{32, 64}::PI` found - let almost_pi = 3.141; + let almost_pi = 3.14; //~ERROR approximate value of `f{32, 64}::PI` found + let no_pi = 3.15; let my_sq2 = 1.4142; //~ERROR approximate value of `f{32, 64}::SQRT_2` found let no_sq2 = 1.414; -- cgit 1.4.1-3-g733a5 From 70e3277bf960be55c529fcfaf4beb713620dd19d Mon Sep 17 00:00:00 2001 From: Kevin Yap <me@kevinyap.ca> Date: Fri, 23 Oct 2015 21:30:57 -0700 Subject: Compare float literals to stringified constants - Convert constants to strings and compare directly with float literal. - Return immediately after positive match for constant. - Fix value of `my_log10_e` in `approx_const` tests. --- src/approx_const.rs | 71 ++++++++++++++++++++++++-------------- tests/compile-fail/approx_const.rs | 2 +- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 19753aaf844..89cb5204a8c 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; +use std::f64::consts as f64; use utils::span_lint; use syntax::ast::Lit_::*; use syntax::ast::Lit; @@ -12,25 +13,24 @@ declare_lint! { is found; suggests to use the constant" } -// Tuples are of the form (name, lower_bound, upper_bound) -#[allow(approx_constant)] -const KNOWN_CONSTS : &'static [(&'static str, f64, f64)] = &[ - ("E", 2.7101, 2.7200), - ("FRAC_1_PI", 0.31829, 0.31840), - ("FRAC_1_SQRT_2", 0.7071, 0.7072), - ("FRAC_2_PI", 0.6366, 0.6370), - ("FRAC_2_SQRT_PI", 1.1283, 1.1284), - ("FRAC_PI_2", 1.5707, 1.5708), - ("FRAC_PI_3", 1.0471, 1.0472), - ("FRAC_PI_4", 0.7853, 0.7854), - ("FRAC_PI_6", 0.5235, 0.5236), - ("FRAC_PI_8", 0.3926, 0.3927), - ("LN_10", 2.302, 2.303), - ("LN_2", 0.6931, 0.6932), - ("LOG10_E", 0.4342, 0.4343), - ("LOG2_E", 1.4426, 1.4427), - ("PI", 3.140, 3.142), - ("SQRT_2", 1.4142, 1.4143), +// Tuples are of the form (constant, name, min_digits) +const KNOWN_CONSTS : &'static [(f64, &'static str, usize)] = &[ + (f64::E, "E", 4), + (f64::FRAC_1_PI, "FRAC_1_PI", 4), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), + (f64::FRAC_2_PI, "FRAC_2_PI", 5), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), + (f64::FRAC_PI_2, "FRAC_PI_2", 5), + (f64::FRAC_PI_3, "FRAC_PI_3", 5), + (f64::FRAC_PI_4, "FRAC_PI_4", 5), + (f64::FRAC_PI_6, "FRAC_PI_6", 5), + (f64::FRAC_PI_8, "FRAC_PI_8", 5), + (f64::LN_10, "LN_10", 5), + (f64::LN_2, "LN_2", 5), + (f64::LOG10_E, "LOG10_E", 5), + (f64::LOG2_E, "LOG2_E", 5), + (f64::PI, "PI", 3), + (f64::SQRT_2, "SQRT_2", 5), ]; #[derive(Copy,Clone)] @@ -52,22 +52,41 @@ impl LateLintPass for ApproxConstant { fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { - LitFloat(ref str, TyF32) => check_known_consts(cx, e, str, "f32"), - LitFloat(ref str, TyF64) => check_known_consts(cx, e, str, "f64"), - LitFloatUnsuffixed(ref str) => - check_known_consts(cx, e, str, "f{32, 64}"), + LitFloat(ref s, TyF32) => check_known_consts(cx, e, s, "f32"), + LitFloat(ref s, TyF64) => check_known_consts(cx, e, s, "f64"), + LitFloatUnsuffixed(ref s) => + check_known_consts(cx, e, s, "f{32, 64}"), _ => () } } fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { - if let Ok(value) = s.parse::<f64>() { - for &(name, lower_bound, upper_bound) in KNOWN_CONSTS { - if (value >= lower_bound) && (value < upper_bound) { + if let Ok(_) = s.parse::<f64>() { + for &(constant, name, min_digits) in KNOWN_CONSTS { + if is_approx_const(constant, s, min_digits) { span_lint(cx, APPROX_CONSTANT, e.span, &format!( "approximate value of `{}::{}` found. \ Consider using it directly", module, &name)); + return; } } } } + +/// Returns false if the number of significant figures in `value` are +/// less than `min_digits`; otherwise, returns true if `value` is equal +/// to `constant`, rounded to the number of digits present in `value`. +fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool { + if value.len() <= min_digits { + false + } else { + let round_const = format!("{:.*}", value.len() - 2, constant); + + let mut trunc_const = constant.to_string(); + if trunc_const.len() > value.len() { + trunc_const.truncate(value.len()); + } + + (value == round_const) || (value == trunc_const) + } +} diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index ebd5d3ea139..148746bfa94 100755 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -42,7 +42,7 @@ fn main() { let my_ln_2 = 0.6931471805599453; //~ERROR approximate value of `f{32, 64}::LN_2` found let no_ln_2 = 0.693; - let my_log10_e = 0.43429448190325176; //~ERROR approximate value of `f{32, 64}::LOG10_E` found + let my_log10_e = 0.43429448190325182; //~ERROR approximate value of `f{32, 64}::LOG10_E` found let no_log10_e = 0.434; let my_log2_e = 1.4426950408889634; //~ERROR approximate value of `f{32, 64}::LOG2_E` found -- cgit 1.4.1-3-g733a5 From 5d3f627f47d1784b2d8bf52b864656c7c6b69d3a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 25 Oct 2015 23:43:27 +0530 Subject: bump version, add optional dep info --- Cargo.toml | 2 +- README.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5a553ca77e5..4091a6b1caf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.21" +version = "0.0.22" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/README.md b/README.md index 3e56e863287..32e8b77d6d8 100644 --- a/README.md +++ b/README.md @@ -136,5 +136,24 @@ cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy *[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! +If you want to make clippy an optional dependency, you can do the following: + +In your `Cargo.toml`: +```toml +[dependencies] +clippy = {version = "*", optional = true} + +[features] +default=[] +``` + +And, in your `main.rs` or `lib.rs`: + +```rust +#![cfg_attr(feature=clippy, feature(plugin))] + +#![cfg_attr(feature=clippy, plugin(clippy))] +``` + ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 2b65473ac537e87edc570e9ae0ddb06578a1b38a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 25 Oct 2015 23:49:53 +0530 Subject: fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32e8b77d6d8..b37695f2f69 100644 --- a/README.md +++ b/README.md @@ -150,9 +150,9 @@ default=[] And, in your `main.rs` or `lib.rs`: ```rust -#![cfg_attr(feature=clippy, feature(plugin))] +#![cfg_attr(feature="clippy", feature(plugin))] -#![cfg_attr(feature=clippy, plugin(clippy))] +#![cfg_attr(feature="clippy", plugin(clippy))] ``` ##License -- cgit 1.4.1-3-g733a5 From a91c618fed0ffdc0651768d148985c1594dc9de5 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Mon, 26 Oct 2015 07:43:38 +0100 Subject: Fix reverse_range_loop not taking sign into account (fixes #409) Adds a Display impl for Constant, because that might come in handy elsewhere as well. --- src/consts.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ src/loops.rs | 6 ++-- tests/compile-fail/for_loop.rs | 4 +++ 3 files changed, 71 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/consts.rs diff --git a/src/consts.rs b/src/consts.rs old mode 100644 new mode 100755 index be681efb257..766d998c256 --- a/src/consts.rs +++ b/src/consts.rs @@ -6,10 +6,12 @@ use rustc::middle::def::PathResolution; use rustc::middle::def::Def::*; use rustc_front::hir::*; use syntax::ptr::P; +use std::char; use std::cmp::PartialOrd; use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; +use std::fmt; use self::Constant::*; use self::FloatWidth::*; @@ -21,6 +23,7 @@ use syntax::ast::{UintTy, FloatTy, StrStyle}; use syntax::ast::UintTy::*; use syntax::ast::FloatTy::*; use syntax::ast::Sign::{self, Plus, Minus}; +use syntax::ast_util; #[derive(PartialEq, Eq, Debug, Copy, Clone)] @@ -159,6 +162,67 @@ impl PartialOrd for Constant { } } +fn format_byte(fmt: &mut fmt::Formatter, b: u8) -> fmt::Result { + if b == b'\\' { + write!(fmt, "\\\\") + } else if 0x20 <= b && b <= 0x7e { + write!(fmt, "{}", char::from_u32(b as u32).expect("all u8 are valid char")) + } else if b == 0x0a { + write!(fmt, "\\n") + } else if b == 0x0d { + write!(fmt, "\\r") + } else { + write!(fmt, "\\x{:02x}", b) + } +} + +impl fmt::Display for Constant { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + ConstantStr(ref s, _) => write!(fmt, "{:?}", s), + ConstantByte(ref b) => + write!(fmt, "b'").and_then(|_| format_byte(fmt, *b)) + .and_then(|_| write!(fmt, "'")), + ConstantBinary(ref bs) => { + try!(write!(fmt, "b\"")); + for b in bs.iter() { + try!(format_byte(fmt, *b)); + } + write!(fmt, "\"") + } + ConstantChar(ref c) => write!(fmt, "'{}'", c), + ConstantInt(ref i, ref ity) => { + let (sign, suffix) = match *ity { + LitIntType::SignedIntLit(ref sity, ref sign) => + (if let Sign::Minus = *sign { "-" } else { "" }, + ast_util::int_ty_to_string(*sity, None)), + LitIntType::UnsignedIntLit(ref uity) => + ("", ast_util::uint_ty_to_string(*uity, None)), + LitIntType::UnsuffixedIntLit(ref sign) => + (if let Sign::Minus = *sign { "-" } else { "" }, + "".into()), + }; + write!(fmt, "{}{}{}", sign, i, suffix) + } + ConstantFloat(ref s, ref fw) => { + let suffix = match *fw { + FloatWidth::Fw32 => "f32", + FloatWidth::Fw64 => "f64", + FloatWidth::FwAny => "", + }; + write!(fmt, "{}{}", s, suffix) + } + ConstantBool(ref b) => write!(fmt, "{}", b), + ConstantRepeat(ref c, ref n) => write!(fmt, "[{}; {}]", c, n), + ConstantVec(ref v) => write!(fmt, "[{}]", + v.iter().map(|i| format!("{}", i)) + .collect::<Vec<_>>().join(", ")), + ConstantTuple(ref t) => write!(fmt, "({})", + t.iter().map(|i| format!("{}", i)) + .collect::<Vec<_>>().join(", ")), + } + } +} fn lit_to_constant(lit: &Lit_) -> Constant { diff --git a/src/loops.rs b/src/loops.rs index 7d7c97f1bb1..95289cf347c 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -44,7 +44,7 @@ pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, + WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP, EMPTY_LOOP) } } @@ -88,8 +88,8 @@ impl LateLintPass for LoopsPass { // if this for loop is iterating over a two-sided range... if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { // ...and both sides are compile-time constant integers... - if let Some(Constant::ConstantInt(start_idx, _)) = constant_simple(start_expr) { - if let Some(Constant::ConstantInt(stop_idx, _)) = constant_simple(stop_expr) { + if let Some(start_idx @ Constant::ConstantInt(..)) = constant_simple(start_expr) { + if let Some(stop_idx @ Constant::ConstantInt(..)) = constant_simple(stop_expr) { // ...and the start index is greater than the stop index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 11810242a88..02c8cc56083 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -46,6 +46,10 @@ fn main() { println!("{}", i); } + for i in -10..0 { // not an error + println!("{}", i); + } + for i in (10..0).rev() { // not an error, this is an established idiom for looping backwards on a range println!("{}", i); } -- cgit 1.4.1-3-g733a5 From f6163fce6120b6bde902d1fd8f862d80e67c0721 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Fri, 16 Oct 2015 20:27:13 +0200 Subject: Suggest for loop instead of while-let when looping over iterators --- README.md | 4 +++- src/lib.rs | 1 + src/loops.rs | 16 +++++++++++++++- tests/compile-fail/while_loop.rs | 19 ++++++++++++++++++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b37695f2f69..664fc0359bf 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 68 lints included in this crate: +There are 69 lints included in this crate: +There are 65 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -74,6 +75,7 @@ name [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention [wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention [zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN diff --git a/src/lib.rs b/src/lib.rs index d5d27e5e2af..b84c1e2aab6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,6 +138,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::REVERSE_RANGE_LOOP, loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, + loops::WHILE_LET_ON_ITERATOR, matches::MATCH_BOOL, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, diff --git a/src/loops.rs b/src/loops.rs index 95289cf347c..6b6fbf60c4c 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -38,6 +38,8 @@ declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } +declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" } + #[derive(Copy, Clone)] pub struct LoopsPass; @@ -45,7 +47,8 @@ impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, - EXPLICIT_COUNTER_LOOP, EMPTY_LOOP) + EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, + WHILE_LET_ON_ITERATOR) } } @@ -228,6 +231,17 @@ impl LateLintPass for LoopsPass { } } } + if let ExprMatch(ref expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { + let pat = &arms[0].pats[0].node; + if let (&PatEnum(ref path, _), &ExprMethodCall(method_name, _, _)) = (pat, &expr.node) { + if method_name.node.as_str() == "next" && + match_trait_method(cx, expr, &["core", "iter", "Iterator"]) && + path.segments.last().unwrap().identifier.name.as_str() == "Some" { + span_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, + "this loop could be written as a `for` loop"); + } + } + } } fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index a056fe249b5..efd77a6d9c3 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(while_let_loop, empty_loop)] +#![deny(while_let_loop, empty_loop, while_let_on_iterator)] #![allow(dead_code, unused)] fn main() { @@ -53,6 +53,23 @@ fn main() { while let Some(x) = y { // no error, obviously println!("{}", x); } + + + while let Option::Some(x) = (1..20).next() { //~ERROR this loop could be written as a `for` loop + println!("{}", x); + } + + while let Some(x) = (1..20).next() { //~ERROR this loop could be written as a `for` loop + println!("{}", x); + } + + while let Some(_) = (1..20).next() {} //~ERROR this loop could be written as a `for` loop + + while let None = (1..20).next() {} // this is fine (if nonsensical) + + if let Some(x) = (1..20).next() { // also fine + println!("{}", x) + } } // regression test (#360) -- cgit 1.4.1-3-g733a5 From 659e7c1d5efa79394695c62375ef6860ab37aa67 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Tue, 20 Oct 2015 01:04:21 +0200 Subject: Don't suggest using a for loop if the iterator is used in the loop body Due to https://github.com/rust-lang/rust/issues/8372, we have to use while-let in these cases. --- src/loops.rs | 33 +++++++++++++++++++++++++++++++-- tests/compile-fail/while_loop.rs | 10 ++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 6b6fbf60c4c..04a2350db6b 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -232,11 +232,14 @@ impl LateLintPass for LoopsPass { } } if let ExprMatch(ref expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { + let body = &arms[0].body; let pat = &arms[0].pats[0].node; - if let (&PatEnum(ref path, _), &ExprMethodCall(method_name, _, _)) = (pat, &expr.node) { + if let (&PatEnum(ref path, _), &ExprMethodCall(method_name, _, ref args)) = (pat, &expr.node) { + let iterator_def_id = var_def_id(cx, &args[0]); if method_name.node.as_str() == "next" && match_trait_method(cx, expr, &["core", "iter", "Iterator"]) && - path.segments.last().unwrap().identifier.name.as_str() == "Some" { + path.segments.last().unwrap().identifier.name.as_str() == "Some" && + !var_used(body, iterator_def_id, cx) { span_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, "this loop could be written as a `for` loop"); } @@ -314,6 +317,32 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { } } +fn var_used(expr: &Expr, def_id: Option<NodeId>, cx: &LateContext) -> bool { + match def_id { + None => false, + Some(def_id) => { + let mut visitor = VarUsedVisitor{ def_id: def_id, found: false, cx: cx }; + walk_expr(&mut visitor, expr); + visitor.found + } + } +} + +struct VarUsedVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, + def_id: NodeId, + found: bool +} + +impl<'v, 't> Visitor<'v> for VarUsedVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if Some(self.def_id) == var_def_id(self.cx, expr) { + self.found = true; + } + walk_expr(self, expr); + } +} + /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index efd77a6d9c3..ae2f6995061 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -70,6 +70,16 @@ fn main() { if let Some(x) = (1..20).next() { // also fine println!("{}", x) } + + // the following shouldn't warn because it can't be written with a for loop + let mut iter = 1u32..20; + while let Some(x) = iter.next() { + println!("next: {:?}", iter.next()) + } + + // but this should: + let mut iter2 = 1u32..20; + while let Some(x) = iter2.next() { } //~ERROR this loop could be written as a `for` loop } // regression test (#360) -- cgit 1.4.1-3-g733a5 From 8626ac1fd40f70e18857b4b8c143c522def544f1 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 22 Oct 2015 23:16:58 +0200 Subject: Fixes for code review comments * remove weird infinite loops from compile-tests * remove call to Option::unwrap * in the lint message, show while-let loop rewritten as for loop --- src/loops.rs | 27 ++++++++++++++++++--------- tests/compile-fail/while_loop.rs | 20 ++++++++++---------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 04a2350db6b..bf64ec5b132 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -231,17 +231,26 @@ impl LateLintPass for LoopsPass { } } } - if let ExprMatch(ref expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { + if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let body = &arms[0].body; let pat = &arms[0].pats[0].node; - if let (&PatEnum(ref path, _), &ExprMethodCall(method_name, _, ref args)) = (pat, &expr.node) { - let iterator_def_id = var_def_id(cx, &args[0]); - if method_name.node.as_str() == "next" && - match_trait_method(cx, expr, &["core", "iter", "Iterator"]) && - path.segments.last().unwrap().identifier.name.as_str() == "Some" && - !var_used(body, iterator_def_id, cx) { - span_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, - "this loop could be written as a `for` loop"); + if let (&PatEnum(ref path, Some(ref pat_args)), + &ExprMethodCall(method_name, _, ref method_args)) = + (pat, &match_expr.node) { + let iterator_def_id = var_def_id(cx, &method_args[0]); + if let Some(lhs_constructor) = path.segments.last() { + if method_name.node.as_str() == "next" && + match_trait_method(cx, match_expr, &["core", "iter", "Iterator"]) && + lhs_constructor.identifier.name.as_str() == "Some" && + !var_used(body, iterator_def_id, cx) { + let iterator = snippet(cx, method_args[0].span, "_"); + let loop_var = snippet(cx, pat_args[0].span, "_"); + span_help_and_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, + "this loop could be written as a `for` loop", + &format!("try\nfor {} in {} {{...}}", + loop_var, + iterator)); + } } } } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index ae2f6995061..334ddd346a2 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -54,20 +54,24 @@ fn main() { println!("{}", x); } - - while let Option::Some(x) = (1..20).next() { //~ERROR this loop could be written as a `for` loop + let mut iter = 1..20; + while let Option::Some(x) = iter.next() { //~ERROR this loop could be written as a `for` loop println!("{}", x); } - while let Some(x) = (1..20).next() { //~ERROR this loop could be written as a `for` loop + let mut iter = 1..20; + while let Some(x) = iter.next() { //~ERROR this loop could be written as a `for` loop println!("{}", x); } - while let Some(_) = (1..20).next() {} //~ERROR this loop could be written as a `for` loop + let mut iter = 1..20; + while let Some(_) = iter.next() {} //~ERROR this loop could be written as a `for` loop - while let None = (1..20).next() {} // this is fine (if nonsensical) + let mut iter = 1..20; + while let None = iter.next() {} // this is fine (if nonsensical) - if let Some(x) = (1..20).next() { // also fine + let mut iter = 1..20; + if let Some(x) = iter.next() { // also fine println!("{}", x) } @@ -76,10 +80,6 @@ fn main() { while let Some(x) = iter.next() { println!("next: {:?}", iter.next()) } - - // but this should: - let mut iter2 = 1u32..20; - while let Some(x) = iter2.next() { } //~ERROR this loop could be written as a `for` loop } // regression test (#360) -- cgit 1.4.1-3-g733a5 From 66419582b5dde68e3219ed1686babc0c9e9df4d5 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Fri, 23 Oct 2015 10:50:18 +0200 Subject: Fix error in README --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 664fc0359bf..c602edca7df 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ A collection of lints to catch common mistakes and improve your Rust code. ##Lints There are 69 lints included in this crate: -There are 65 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- cgit 1.4.1-3-g733a5 From 5ca7ebb6d271c593605e03046abbd3a3849036b3 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Mon, 26 Oct 2015 23:49:37 +0100 Subject: Fix false positives when iterator variable is used after the loop --- src/loops.rs | 48 ++++++++++++++++++++++++++-------------- src/utils.rs | 13 +++++++++++ tests/compile-fail/while_loop.rs | 17 ++++++++++++++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index bf64ec5b132..d056c67c541 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -11,7 +11,8 @@ use std::collections::{HashSet,HashMap}; use syntax::ast::Lit_::*; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, - in_external_macro, expr_block, span_help_and_lint, is_integer_literal}; + in_external_macro, expr_block, span_help_and_lint, is_integer_literal, + get_enclosing_block}; use utils::{VEC_PATH, LL_PATH}; declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, @@ -232,17 +233,16 @@ impl LateLintPass for LoopsPass { } } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { - let body = &arms[0].body; let pat = &arms[0].pats[0].node; if let (&PatEnum(ref path, Some(ref pat_args)), &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { - let iterator_def_id = var_def_id(cx, &method_args[0]); + let iter_expr = &method_args[0]; if let Some(lhs_constructor) = path.segments.last() { if method_name.node.as_str() == "next" && match_trait_method(cx, match_expr, &["core", "iter", "Iterator"]) && lhs_constructor.identifier.name.as_str() == "Some" && - !var_used(body, iterator_def_id, cx) { + !is_iterator_used_after_while_let(cx, iter_expr) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); span_help_and_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, @@ -326,32 +326,46 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { } } -fn var_used(expr: &Expr, def_id: Option<NodeId>, cx: &LateContext) -> bool { - match def_id { - None => false, - Some(def_id) => { - let mut visitor = VarUsedVisitor{ def_id: def_id, found: false, cx: cx }; - walk_expr(&mut visitor, expr); - visitor.found - } +fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool { + let def_id = match var_def_id(cx, iter_expr) { + Some(id) => id, + None => return false + }; + let mut visitor = VarUsedAfterLoopVisitor { + cx: cx, + def_id: def_id, + iter_expr_id: iter_expr.id, + past_while_let: false, + var_used_after_while_let: false + }; + if let Some(enclosing_block) = get_enclosing_block(cx, def_id) { + walk_block(&mut visitor, enclosing_block); } + visitor.var_used_after_while_let } -struct VarUsedVisitor<'v, 't: 'v> { +struct VarUsedAfterLoopVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, def_id: NodeId, - found: bool + iter_expr_id: NodeId, + past_while_let: bool, + var_used_after_while_let: bool } -impl<'v, 't> Visitor<'v> for VarUsedVisitor<'v, 't> { +impl <'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { fn visit_expr(&mut self, expr: &'v Expr) { - if Some(self.def_id) == var_def_id(self.cx, expr) { - self.found = true; + if self.past_while_let { + if Some(self.def_id) == var_def_id(self.cx, expr) { + self.var_used_after_while_let = true; + } + } else if self.iter_expr_id == expr.id { + self.past_while_let = true; } walk_expr(self, expr); } } + /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { diff --git a/src/utils.rs b/src/utils.rs index 80b8c88361a..73b641b644e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -255,6 +255,19 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if let NodeExpr(parent) = node { Some(parent) } else { None } ) } +pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { + let map = &cx.tcx.map; + let enclosing_node = map.get_enclosing_scope(node) + .and_then(|enclosing_id| map.find(enclosing_id)); + if let Some(node) = enclosing_node { + match node { + NodeBlock(ref block) => Some(block), + NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), + _ => None + } + } else { None } +} + #[cfg(not(feature="structured_logging"))] pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index 334ddd346a2..7d1904ad446 100755 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -80,6 +80,23 @@ fn main() { while let Some(x) = iter.next() { println!("next: {:?}", iter.next()) } + + // neither can this + let mut iter = 1u32..20; + while let Some(x) = iter.next() { + println!("next: {:?}", iter.next()); + } + + // or this + let mut iter = 1u32..20; + while let Some(x) = iter.next() {break;} + println!("Remaining iter {:?}", iter); + + // or this + let mut iter = 1u32..20; + while let Some(x) = iter.next() { + iter = 1..20; + } } // regression test (#360) -- cgit 1.4.1-3-g733a5 From c5b6fda399644147c9a002109a4be1ac9508e9ec Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Tue, 27 Oct 2015 18:28:36 +0100 Subject: Allow needless_lifetime to pass dogfood.sh --- src/utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.rs b/src/utils.rs index 73b641b644e..7cbb532cf22 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -255,6 +255,7 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if let NodeExpr(parent) = node { Some(parent) } else { None } ) } +#[allow(needless_lifetimes)] // workaround for https://github.com/Manishearth/rust-clippy/issues/417 pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { let map = &cx.tcx.map; let enclosing_node = map.get_enclosing_scope(node) -- cgit 1.4.1-3-g733a5 From 8e4c2171d24a3f43a5f6d7af3c15efb6d1d56803 Mon Sep 17 00:00:00 2001 From: wartman4404 <wartman4404@my.mstc.edu> Date: Wed, 28 Oct 2015 22:26:48 -0500 Subject: Don't show single_match if match_bool also applies --- src/matches.rs | 6 ++++-- tests/compile-fail/matches.rs | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index a7cfefd7af5..fb000c24364 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -39,8 +39,10 @@ impl LateLintPass for MatchPass { // but in some cases, an explicit match is preferred to catch situations // when an enum is extended, so we don't consider these cases arms[1].pats[0].node == PatWild(PatWildSingle) && - // finally, we don't want any content in the second arm (unit or empty block) - is_unit_expr(&arms[1].body) + // we don't want any content in the second arm (unit or empty block) + is_unit_expr(&arms[1].body) && + // finally, MATCH_BOOL doesn't apply here + (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) { span_help_and_lint(cx, SINGLE_MATCH, expr.span, "you seem to be trying to use match for destructuring a \ diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index f0cc650f753..ff92a67271b 100755 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -58,8 +58,6 @@ fn match_bool() { }; match test { //~ ERROR you seem to be trying to match on a boolean expression - //~^ERROR you seem to be trying to use match - //TODO: Remove duplicate warning false => { println!("Noooo!"); }, _ => (), }; -- cgit 1.4.1-3-g733a5 From 0fe5981870b4588d3412a31acec18cd5a12269fe Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Thu, 29 Oct 2015 01:50:00 +0900 Subject: New lint for statement with no effect --- README.md | 3 +- src/lib.rs | 3 ++ src/no_effect.rs | 61 +++++++++++++++++++++++++++++++++++ tests/compile-fail/needless_update.rs | 1 + tests/compile-fail/no_effect.rs | 39 ++++++++++++++++++++++ tests/compile-fail/unit_cmp.rs | 1 + 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/no_effect.rs create mode 100644 tests/compile-fail/no_effect.rs diff --git a/README.md b/README.md index c602edca7df..29eb6750d16 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 69 lints included in this crate: +There are 70 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -46,6 +46,7 @@ name [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` diff --git a/src/lib.rs b/src/lib.rs index b84c1e2aab6..60ab18566b8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,7 @@ pub mod zero_div_zero; pub mod open_options; pub mod needless_features; pub mod needless_update; +pub mod no_effect; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -98,6 +99,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_features::NeedlessFeaturesPass); reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); + reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -159,6 +161,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_features::UNSTABLE_AS_MUT_SLICE, needless_features::UNSTABLE_AS_SLICE, needless_update::NEEDLESS_UPDATE, + no_effect::NO_EFFECT, open_options::NONSENSICAL_OPEN_OPTIONS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, diff --git a/src/no_effect.rs b/src/no_effect.rs new file mode 100644 index 00000000000..82fcf92fd4c --- /dev/null +++ b/src/no_effect.rs @@ -0,0 +1,61 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::middle::def::{DefStruct, DefVariant}; +use rustc_front::hir::{Expr, ExprCall, ExprLit, ExprPath, ExprStruct}; +use rustc_front::hir::{Stmt, StmtSemi}; + +use utils::in_macro; +use utils::span_lint; + +declare_lint! { + pub NO_EFFECT, + Warn, + "statements with no effect" +} + +fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { + if in_macro(cx, expr.span) { + return false; + } + match expr.node { + ExprLit(..) | + ExprPath(..) => true, + ExprStruct(_, ref fields, ref base) => { + fields.iter().all(|field| has_no_effect(cx, &field.expr)) && + match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } + } + ExprCall(ref callee, ref args) => { + let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); + match def { + Some(DefStruct(..)) | + Some(DefVariant(..)) => { + args.iter().all(|arg| has_no_effect(cx, arg)) + } + _ => false, + } + } + _ => false, + } +} + +#[derive(Copy, Clone)] +pub struct NoEffectPass; + +impl LintPass for NoEffectPass { + fn get_lints(&self) -> LintArray { + lint_array!(NO_EFFECT) + } +} + +impl LateLintPass for NoEffectPass { + fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { + if let StmtSemi(ref expr, _) = stmt.node { + if has_no_effect(cx, expr) { + span_lint(cx, NO_EFFECT, stmt.span, + "statement with no effect"); + } + } + } +} diff --git a/tests/compile-fail/needless_update.rs b/tests/compile-fail/needless_update.rs index 55438d9d90a..55cfed76d5d 100644 --- a/tests/compile-fail/needless_update.rs +++ b/tests/compile-fail/needless_update.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![deny(needless_update)] +#![allow(no_effect)] struct S { pub a: i32, diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs new file mode 100644 index 00000000000..8da119eb16d --- /dev/null +++ b/tests/compile-fail/no_effect.rs @@ -0,0 +1,39 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(no_effect)] +#![allow(dead_code)] +#![allow(path_statements)] + +struct Unit; +struct Tuple(i32); +struct Struct { + field: i32 +} +enum Enum { + TupleVariant(i32), + StructVariant { field: i32 }, +} + +fn get_number() -> i32 { 0 } +fn get_struct() -> Struct { Struct { field: 0 } } + +fn main() { + let s = get_struct(); + + 0; //~ERROR statement with no effect + Unit; //~ERROR statement with no effect + Tuple(0); //~ERROR statement with no effect + Struct { field: 0 }; //~ERROR statement with no effect + Struct { ..s }; //~ERROR statement with no effect + Enum::TupleVariant(0); //~ERROR statement with no effect + Enum::StructVariant { field: 0 }; //~ERROR statement with no effect + + // Do not warn + get_number(); + Tuple(get_number()); + Struct { field: get_number() }; + Struct { ..get_struct() }; + Enum::TupleVariant(get_number()); + Enum::StructVariant { field: get_number() }; +} diff --git a/tests/compile-fail/unit_cmp.rs b/tests/compile-fail/unit_cmp.rs index af28f849e8c..1a28953ace1 100755 --- a/tests/compile-fail/unit_cmp.rs +++ b/tests/compile-fail/unit_cmp.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![deny(unit_cmp)] +#![allow(no_effect)] #[derive(PartialEq)] pub struct ContainsUnit(()); // should be fine -- cgit 1.4.1-3-g733a5 From dbb8a872a3aea4bb9510d109f5f7dbe5273446da Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 31 Oct 2015 05:18:05 +0530 Subject: Fix ptr-arg false positive for trait impls Fixes #425 --- src/ptr_arg.rs | 10 ++++++++-- tests/compile-fail/ptr_arg.rs | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 4baba711886..78a3c146c0f 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -5,6 +5,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; +use rustc::front::map::Node; use utils::{span_lint, match_type}; use utils::{STRING_PATH, VEC_PATH}; @@ -34,6 +35,11 @@ impl LateLintPass for PtrArg { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let &MethodImplItem(ref sig, _) = &item.node { + if let Some(Node::NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { + if let ItemImpl(_, _, _, Some(_), _, _) = it.node { + return; // ignore trait impls + } + } check_fn(cx, &sig.decl); } } @@ -47,8 +53,8 @@ impl LateLintPass for PtrArg { fn check_fn(cx: &LateContext, decl: &FnDecl) { for arg in &decl.inputs { - if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) { - if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty { + if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&arg.ty.id) { + if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { if match_type(cx, ty, &VEC_PATH) { span_lint(cx, PTR_ARG, arg.ty.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference \ diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs index d0615be492b..e4971208747 100755 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -21,3 +21,18 @@ fn do_str_mut(x: &mut String) { // no error here fn main() { } + +trait Foo { + type Item; + fn do_vec(x: &Vec<i64>); //~ERROR writing `&Vec<_>` + fn do_item(x: &Self::Item); +} + +struct Bar; + +// no error, in trait impl (#425) +impl Foo for Bar { + type Item = Vec<u8>; + fn do_vec(x: &Vec<i64>) {} + fn do_item(x: &Vec<u8>) {} +} -- cgit 1.4.1-3-g733a5 From d28b8e169fc9f722aa32dc16a21be137587316ef Mon Sep 17 00:00:00 2001 From: Nathan Weston <nweston@fastmail.com> Date: Tue, 3 Nov 2015 09:42:52 -0500 Subject: New lint for zip with array length instead of enumerate() Fixes #11. --- README.md | 3 ++- src/lib.rs | 1 + src/ranges.rs | 37 ++++++++++++++++++++++++++++++++++--- tests/compile-fail/range.rs | 7 ++++++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 29eb6750d16..0da037e7b16 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 70 lints included in this crate: +There are 71 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -53,6 +53,7 @@ name [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled diff --git a/src/lib.rs b/src/lib.rs index 60ab18566b8..525603dc2b8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,6 +166,7 @@ pub fn plugin_registrar(reg: &mut Registry) { precedence::PRECEDENCE, ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, + ranges::RANGE_ZIP_WITH_LEN, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, types::BOX_VEC, diff --git a/src/ranges.rs b/src/ranges.rs index 2ef272237d1..39ff7d3cd31 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,19 +1,23 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::{match_type, is_integer_literal}; +use utils::{is_integer_literal, match_type, snippet}; declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, "using Range::step_by(0), which produces an infinite iterator" } +declare_lint! { + pub RANGE_ZIP_WITH_LEN, Warn, + "zipping iterator with a range when enumerate() would do" +} #[derive(Copy,Clone)] pub struct StepByZero; impl LintPass for StepByZero { fn get_lints(&self) -> LintArray { - lint_array!(RANGE_STEP_BY_ZERO) + lint_array!(RANGE_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN) } } @@ -21,13 +25,40 @@ impl LateLintPass for StepByZero { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { - // Only warn on literal ranges. + // Range with step_by(0). if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, "Range::step_by(0) produces an infinite iterator. \ Consider using `std::iter::repeat()` instead") } + + // x.iter().zip(0..x.len()) + else if name.as_str() == "zip" && args.len() == 2 { + let iter = &args[0].node; + let zip_arg = &args[1].node; + if_let_chain! { + [ + // .iter() call + let &ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = iter, + iter_name.as_str() == "iter", + // range expression in .zip() call: 0..x.len() + let &ExprRange(Some(ref from), Some(ref to)) = zip_arg, + is_integer_literal(from, 0), + // .len() call + let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = to.node, + len_name.as_str() == "len" && len_args.len() == 1, + // .iter() and .len() called on same Path + let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, + let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, + iter_path == len_path + ], { + cx.span_lint(RANGE_ZIP_WITH_LEN, expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); + } + } + } } } } diff --git a/tests/compile-fail/range.rs b/tests/compile-fail/range.rs index 324f129fafa..2d731670cbe 100644 --- a/tests/compile-fail/range.rs +++ b/tests/compile-fail/range.rs @@ -7,7 +7,7 @@ impl NotARange { fn step_by(&self, _: u32) {} } -#[deny(range_step_by_zero)] +#[deny(range_step_by_zero, range_zip_with_len)] fn main() { (0..1).step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator // No warning for non-zero step @@ -21,4 +21,9 @@ fn main() { // No error, not a range. let y = NotARange; y.step_by(0); + + let _v1 = vec![1,2,3]; + let _v2 = vec![4,5]; + let _x = _v1.iter().zip(0.._v1.len()); //~ERROR It is more idiomatic to use _v1.iter().enumerate() + let _y = _v1.iter().zip(0.._v2.len()); // No error } -- cgit 1.4.1-3-g733a5 From 414c0d20f746c2e3852c8a5356b8831176c915f6 Mon Sep 17 00:00:00 2001 From: wartman4404 <wartman4404@my.mstc.edu> Date: Fri, 30 Oct 2015 23:58:37 -0500 Subject: New lint for using `.cloned()` --- README.md | 1 + src/lib.rs | 3 ++ src/map_clone.rs | 102 ++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/map_clone.rs | 69 +++++++++++++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 src/map_clone.rs create mode 100644 tests/compile-fail/map_clone.rs diff --git a/README.md b/README.md index 0da037e7b16..fcfeca1509e 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ name [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant diff --git a/src/lib.rs b/src/lib.rs index 525603dc2b8..37e1ace61de 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,6 +45,7 @@ pub mod returns; pub mod lifetimes; pub mod loops; pub mod ranges; +pub mod map_clone; pub mod matches; pub mod precedence; pub mod mutex_atomic; @@ -100,6 +101,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box needless_features::NeedlessFeaturesPass); reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); reg.register_late_lint_pass(box no_effect::NoEffectPass); + reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -141,6 +143,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, diff --git a/src/map_clone.rs b/src/map_clone.rs new file mode 100644 index 00000000000..570ee91dd7b --- /dev/null +++ b/src/map_clone.rs @@ -0,0 +1,102 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::ast::Ident; +use utils::OPTION_PATH; +use utils::{match_trait_method, match_type, snippet, span_help_and_lint}; +use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; + +declare_lint!(pub MAP_CLONE, Warn, + "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ + `.cloned()` instead)"); + +#[derive(Copy, Clone)] +pub struct MapClonePass; + +impl LateLintPass for MapClonePass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! { + [ + // call to .map() + let ExprMethodCall(name, _, ref args) = expr.node, + name.node.as_str() == "map" && args.len() == 2, + let ExprClosure(_, ref decl, ref blk) = args[1].node, + // just one expression in the closure + blk.stmts.is_empty(), + let Some(ref closure_expr) = blk.expr, + // nothing special in the argument, besides reference bindings + // (e.g. .map(|&x| x) ) + let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), + // the method is being called on a known type (option or iterator) + let Some(type_name) = get_type_name(cx, expr, &args[0]) + ], { + // look for derefs, for .map(|x| *x) + if only_derefs(&*closure_expr, arg_ident) && + // .cloned() only removes one level of indirection, don't lint on more + walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + // explicit clone() calls ( .map(|x| x.clone()) ) + else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { + if clone_call.node.as_str() == "clone" && + clone_args.len() == 1 && + match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) && + expr_eq_ident(&clone_args[0], arg_ident) + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } + } + } + } +} + +fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { + match expr.node { + ExprPath(None, ref path) => { + let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }]; + !path.global && path.segments == arg_segment + }, + _ => false, + } +} + +fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { + if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + Some("iterator") + } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &OPTION_PATH) { + Some("Option") + } else { + None + } +} + +fn get_arg_name(pat: &Pat) -> Option<Ident> { + match pat.node { + PatIdent(_, ident, None) => Some(ident.node), + PatRegion(ref subpat, _) => get_arg_name(subpat), + _ => None, + } +} + +fn only_derefs(expr: &Expr, id: Ident) -> bool { + if expr_eq_ident(expr, id) { + true + } else if let ExprUnary(UnDeref, ref subexpr) = expr.node { + only_derefs(subexpr, id) + } else { + false + } +} + +impl LintPass for MapClonePass { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_CLONE) + } +} diff --git a/tests/compile-fail/map_clone.rs b/tests/compile-fail/map_clone.rs new file mode 100644 index 00000000000..9d9f253defe --- /dev/null +++ b/tests/compile-fail/map_clone.rs @@ -0,0 +1,69 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(map_clone)] + +#![allow(unused)] + +fn map_clone_iter() { + let x = [1,2,3]; + x.iter().map(|y| y.clone()); //~ ERROR you seem to be using .map() + //~^ HELP try + x.iter().map(|&y| y); //~ ERROR you seem to be using .map() + //~^ HELP try + x.iter().map(|y| *y); //~ ERROR you seem to be using .map() + //~^ HELP try +} + +fn map_clone_option() { + let x = Some(4); + x.as_ref().map(|y| y.clone()); //~ ERROR you seem to be using .map() + //~^ HELP try + x.as_ref().map(|&y| y); //~ ERROR you seem to be using .map() + //~^ HELP try + x.as_ref().map(|y| *y); //~ ERROR you seem to be using .map() + //~^ HELP try +} + +fn not_linted_option() { + let x = Some(5); + + // Not linted: other statements + x.as_ref().map(|y| { + println!("y: {}", y); + y.clone() + }); + + // Not linted: argument bindings + let x = Some((6, 7)); + x.map(|(y, _)| y.clone()); + + // Not linted: cloning something else + x.map(|y| y.0.clone()); + + // Not linted: no dereferences + x.map(|y| y); + + // Not linted: multiple dereferences + let _: Option<(i32, i32)> = x.as_ref().as_ref().map(|&&x| x); +} + +#[derive(Copy, Clone)] +struct Wrapper<T>(T); +impl<T> Wrapper<T> { + fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Wrapper<U> { + Wrapper(f(self.0)) + } +} + +fn map_clone_other() { + let eight = 8; + let x = Wrapper(&eight); + + // Not linted: not a linted type + x.map(|y| y.clone()); + x.map(|&y| y); + x.map(|y| *y); +} + +fn main() { } -- cgit 1.4.1-3-g733a5 From 764eedd0508a53b5184741bd05b8d20ea1034c42 Mon Sep 17 00:00:00 2001 From: wartman4404 <wartman4404@my.mstc.edu> Date: Tue, 3 Nov 2015 21:11:40 -0600 Subject: check for Deref conversions --- README.md | 2 +- src/eta_reduction.rs | 6 +----- src/map_clone.rs | 17 ++++++++--------- src/utils.rs | 4 ++++ tests/compile-fail/map_clone.rs | 23 +++++++++++++++++++++++ 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fcfeca1509e..4c23d6994d2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 71 lints included in this crate: +There are 72 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 7226a4bad05..855ea51ee8e 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; -use utils::{snippet, span_lint}; +use utils::{snippet, span_lint, is_adjusted}; #[allow(missing_copy_implementations)] @@ -32,10 +32,6 @@ impl LateLintPass for EtaPass { } } -fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { - cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() -} - fn check_closure(cx: &LateContext, expr: &Expr) { if let ExprClosure(_, ref decl, ref blk) = expr.node { if !blk.stmts.is_empty() { diff --git a/src/map_clone.rs b/src/map_clone.rs index 570ee91dd7b..e93a8221145 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::Ident; use utils::OPTION_PATH; -use utils::{match_trait_method, match_type, snippet, span_help_and_lint}; +use utils::{is_adjusted, match_trait_method, match_type, snippet, span_help_and_lint}; use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; declare_lint!(pub MAP_CLONE, Warn, @@ -30,7 +30,7 @@ impl LateLintPass for MapClonePass { let Some(type_name) = get_type_name(cx, expr, &args[0]) ], { // look for derefs, for .map(|x| *x) - if only_derefs(&*closure_expr, arg_ident) && + if only_derefs(cx, &*closure_expr, arg_ident) && // .cloned() only removes one level of indirection, don't lint on more walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 { @@ -85,13 +85,12 @@ fn get_arg_name(pat: &Pat) -> Option<Ident> { } } -fn only_derefs(expr: &Expr, id: Ident) -> bool { - if expr_eq_ident(expr, id) { - true - } else if let ExprUnary(UnDeref, ref subexpr) = expr.node { - only_derefs(subexpr, id) - } else { - false +fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool { + match expr.node { + ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => { + only_derefs(cx, subexpr, id) + }, + _ => expr_eq_ident(expr, id), } } diff --git a/src/utils.rs b/src/utils.rs index 7cbb532cf22..757d7bc379d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -347,6 +347,10 @@ pub fn is_integer_literal(expr: &Expr, value: u64) -> bool false } +pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { + cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() +} + /// Produce a nested chain of if-lets and ifs from the patterns: /// /// if_let_chain! { diff --git a/tests/compile-fail/map_clone.rs b/tests/compile-fail/map_clone.rs index 9d9f253defe..f6241114a83 100644 --- a/tests/compile-fail/map_clone.rs +++ b/tests/compile-fail/map_clone.rs @@ -5,6 +5,8 @@ #![allow(unused)] +use std::ops::Deref; + fn map_clone_iter() { let x = [1,2,3]; x.iter().map(|y| y.clone()); //~ ERROR you seem to be using .map() @@ -66,4 +68,25 @@ fn map_clone_other() { x.map(|y| *y); } +#[derive(Copy, Clone)] +struct UnusualDeref; +static NINE: i32 = 9; + +impl Deref for UnusualDeref { + type Target = i32; + fn deref(&self) -> &i32 { &NINE } +} + +fn map_clone_deref() { + let x = Some(UnusualDeref); + let _: Option<UnusualDeref> = x.as_ref().map(|y| *y); //~ ERROR you seem to be using .map() + //~^ HELP try + + // Not linted: using deref conversion + let _: Option<i32> = x.map(|y| *y); + + // Not linted: using regular deref but also deref conversion + let _: Option<i32> = x.as_ref().map(|y| **y); +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 3322ffa8a048ef5369d3cdd914869fdf383473a4 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 4 Nov 2015 18:55:14 +0900 Subject: New lint for assignment to temporary --- README.md | 3 +- src/lib.rs | 3 ++ src/temporary_assignment.rs | 44 ++++++++++++++++++++++++++++++ tests/compile-fail/temporary_assignment.rs | 36 ++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/temporary_assignment.rs create mode 100644 tests/compile-fail/temporary_assignment.rs diff --git a/README.md b/README.md index 4c23d6994d2..5a2ea945349 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 72 lints included in this crate: +There are 73 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -68,6 +68,7 @@ name [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) diff --git a/src/lib.rs b/src/lib.rs index 37e1ace61de..970a244e2cd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,7 @@ pub mod open_options; pub mod needless_features; pub mod needless_update; pub mod no_effect; +pub mod temporary_assignment; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -102,6 +103,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); + reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -172,6 +174,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_ZIP_WITH_LEN, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + temporary_assignment::TEMPORARY_ASSIGNMENT, types::BOX_VEC, types::LET_UNIT_VALUE, types::LINKEDLIST, diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs new file mode 100644 index 00000000000..6cfcb711ff7 --- /dev/null +++ b/src/temporary_assignment.rs @@ -0,0 +1,44 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; + +use utils::is_adjusted; +use utils::span_lint; + +declare_lint! { + pub TEMPORARY_ASSIGNMENT, + Warn, + "assignments to temporaries" +} + +fn is_temporary(expr: &Expr) -> bool { + match expr.node { + ExprStruct(..) | + ExprTup(..) => true, + _ => false, + } +} + +#[derive(Copy, Clone)] +pub struct TemporaryAssignmentPass; + +impl LintPass for TemporaryAssignmentPass { + fn get_lints(&self) -> LintArray { + lint_array!(TEMPORARY_ASSIGNMENT) + } +} + +impl LateLintPass for TemporaryAssignmentPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprAssign(ref target, _) = expr.node { + match target.node { + ExprField(ref base, _) | ExprTupField(ref base, _) => { + if is_temporary(base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, + "assignment to temporary"); + } + } + _ => () + } + } + } +} diff --git a/tests/compile-fail/temporary_assignment.rs b/tests/compile-fail/temporary_assignment.rs new file mode 100644 index 00000000000..b1c2b990024 --- /dev/null +++ b/tests/compile-fail/temporary_assignment.rs @@ -0,0 +1,36 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(temporary_assignment)] + +use std::ops::{Deref, DerefMut}; + +struct Struct { + field: i32 +} + +struct Wrapper<'a> { + inner: &'a mut Struct +} + +impl<'a> Deref for Wrapper<'a> { + type Target = Struct; + fn deref(&self) -> &Struct { self.inner } +} + +impl<'a> DerefMut for Wrapper<'a> { + fn deref_mut(&mut self) -> &mut Struct { self.inner } +} + +fn main() { + let mut s = Struct { field: 0 }; + let mut t = (0, 0); + + Struct { field: 0 }.field = 1; //~ERROR assignment to temporary + (0, 0).0 = 1; //~ERROR assignment to temporary + + // no error + s.field = 1; + t.0 = 1; + Wrapper { inner: &mut s }.field = 1; +} -- cgit 1.4.1-3-g733a5 From c7df4bd0008bb8aad4373457995f56dde861fb8a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 5 Nov 2015 08:20:28 +0530 Subject: Rustup to rustc 1.6.0-nightly (effcd2965 2015-11-04) fixes #437 --- Cargo.toml | 2 +- src/matches.rs | 2 +- src/misc.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4091a6b1caf..f9eceabfc85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.22" +version = "0.0.23" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/matches.rs b/src/matches.rs index fb000c24364..eaa3e0026a3 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -38,7 +38,7 @@ impl LateLintPass for MatchPass { // since the exhaustiveness check will ensure the last one is a catch-all, // but in some cases, an explicit match is preferred to catch situations // when an enum is extended, so we don't consider these cases - arms[1].pats[0].node == PatWild(PatWildSingle) && + arms[1].pats[0].node == PatWild && // we don't want any content in the second arm (unit or empty block) is_unit_expr(&arms[1].body) && // finally, MATCH_BOOL doesn't apply here diff --git a/src/misc.rs b/src/misc.rs index 497bb6692c7..01ecb2c2cf8 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -252,7 +252,7 @@ impl LintPass for PatternPass { impl LateLintPass for PatternPass { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatIdent(_, ref ident, Some(ref right)) = pat.node { - if right.node == PatWild(PatWildSingle) { + if right.node == PatWild { cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!( "the `{} @ _` pattern can be written as just `{}`", ident.node.name, ident.node.name)); -- cgit 1.4.1-3-g733a5 From a0cd8fc9437a9cc1ccb2a8d27f7c00c9fc9575c7 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 5 Nov 2015 17:11:41 +0100 Subject: match .map(Clone::clone) --- src/map_clone.rs | 91 ++++++++++++++++++++++++----------------- src/utils.rs | 1 + tests/compile-fail/map_clone.rs | 2 + 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/map_clone.rs b/src/map_clone.rs index e93a8221145..b9f677dd03d 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::Ident; -use utils::OPTION_PATH; -use utils::{is_adjusted, match_trait_method, match_type, snippet, span_help_and_lint}; +use utils::{CLONE_PATH, OPTION_PATH}; +use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint}; use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; declare_lint!(pub MAP_CLONE, Warn, @@ -14,43 +14,58 @@ pub struct MapClonePass; impl LateLintPass for MapClonePass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain! { - [ - // call to .map() - let ExprMethodCall(name, _, ref args) = expr.node, - name.node.as_str() == "map" && args.len() == 2, - let ExprClosure(_, ref decl, ref blk) = args[1].node, - // just one expression in the closure - blk.stmts.is_empty(), - let Some(ref closure_expr) = blk.expr, - // nothing special in the argument, besides reference bindings - // (e.g. .map(|&x| x) ) - let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), - // the method is being called on a known type (option or iterator) - let Some(type_name) = get_type_name(cx, expr, &args[0]) - ], { - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.node.as_str() == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) && - expr_eq_ident(&clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + // call to .map() + if let ExprMethodCall(name, _, ref args) = expr.node { + if name.node.as_str() == "map" && args.len() == 2 { + match args[1].node { + ExprClosure(_, ref decl, ref blk) => { + if_let_chain! { + [ + // just one expression in the closure + blk.stmts.is_empty(), + let Some(ref closure_expr) = blk.expr, + // nothing special in the argument, besides reference bindings + // (e.g. .map(|&x| x) ) + let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), + // the method is being called on a known type (option or iterator) + let Some(type_name) = get_type_name(cx, expr, &args[0]) + ], { + // look for derefs, for .map(|x| *x) + if only_derefs(cx, &*closure_expr, arg_ident) && + // .cloned() only removes one level of indirection, don't lint on more + walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + // explicit clone() calls ( .map(|x| x.clone()) ) + else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { + if clone_call.node.as_str() == "clone" && + clone_args.len() == 1 && + match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) && + expr_eq_ident(&clone_args[0], arg_ident) + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } + } + } + }, + ExprPath(_, ref path) => { + if match_path(path, &CLONE_PATH) { + let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } } + _ => (), } } } diff --git a/src/utils.rs b/src/utils.rs index 757d7bc379d..e56eab5ad28 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -17,6 +17,7 @@ pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/map_clone.rs b/tests/compile-fail/map_clone.rs index f6241114a83..2e60300afda 100644 --- a/tests/compile-fail/map_clone.rs +++ b/tests/compile-fail/map_clone.rs @@ -15,6 +15,8 @@ fn map_clone_iter() { //~^ HELP try x.iter().map(|y| *y); //~ ERROR you seem to be using .map() //~^ HELP try + x.iter().map(Clone::clone); //~ ERROR you seem to be using .map() + //~^ HELP try } fn map_clone_option() { -- cgit 1.4.1-3-g733a5 From 140c34f85e2df99cbd06c6fc8e71fa4234c25acd Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 9 Nov 2015 08:49:20 +0530 Subject: Tests shouldn't be executable (fixes #444) --- tests/compile-fail/approx_const.rs | 0 tests/compile-fail/attrs.rs | 0 tests/compile-fail/bit_masks.rs | 0 tests/compile-fail/box_vec.rs | 0 tests/compile-fail/cast.rs | 0 tests/compile-fail/cmp_nan.rs | 0 tests/compile-fail/cmp_owned.rs | 0 tests/compile-fail/collapsible_if.rs | 0 tests/compile-fail/complex_types.rs | 0 tests/compile-fail/dlist.rs | 0 tests/compile-fail/eq_op.rs | 0 tests/compile-fail/eta.rs | 0 tests/compile-fail/float_cmp.rs | 0 tests/compile-fail/for_loop.rs | 0 tests/compile-fail/identity_op.rs | 0 tests/compile-fail/len_zero.rs | 0 tests/compile-fail/let_return.rs | 0 tests/compile-fail/let_unit.rs | 0 tests/compile-fail/lifetimes.rs | 0 tests/compile-fail/matches.rs | 0 tests/compile-fail/methods.rs | 0 tests/compile-fail/modulo_one.rs | 0 tests/compile-fail/mut_mut.rs | 0 tests/compile-fail/needless_bool.rs | 0 tests/compile-fail/needless_return.rs | 0 tests/compile-fail/patterns.rs | 0 tests/compile-fail/precedence.rs | 0 tests/compile-fail/ptr_arg.rs | 0 tests/compile-fail/shadow.rs | 0 tests/compile-fail/strings.rs | 0 tests/compile-fail/unicode.rs | 0 tests/compile-fail/unit_cmp.rs | 0 tests/compile-fail/while_loop.rs | 0 33 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/compile-fail/approx_const.rs mode change 100755 => 100644 tests/compile-fail/attrs.rs mode change 100755 => 100644 tests/compile-fail/bit_masks.rs mode change 100755 => 100644 tests/compile-fail/box_vec.rs mode change 100755 => 100644 tests/compile-fail/cast.rs mode change 100755 => 100644 tests/compile-fail/cmp_nan.rs mode change 100755 => 100644 tests/compile-fail/cmp_owned.rs mode change 100755 => 100644 tests/compile-fail/collapsible_if.rs mode change 100755 => 100644 tests/compile-fail/complex_types.rs mode change 100755 => 100644 tests/compile-fail/dlist.rs mode change 100755 => 100644 tests/compile-fail/eq_op.rs mode change 100755 => 100644 tests/compile-fail/eta.rs mode change 100755 => 100644 tests/compile-fail/float_cmp.rs mode change 100755 => 100644 tests/compile-fail/for_loop.rs mode change 100755 => 100644 tests/compile-fail/identity_op.rs mode change 100755 => 100644 tests/compile-fail/len_zero.rs mode change 100755 => 100644 tests/compile-fail/let_return.rs mode change 100755 => 100644 tests/compile-fail/let_unit.rs mode change 100755 => 100644 tests/compile-fail/lifetimes.rs mode change 100755 => 100644 tests/compile-fail/matches.rs mode change 100755 => 100644 tests/compile-fail/methods.rs mode change 100755 => 100644 tests/compile-fail/modulo_one.rs mode change 100755 => 100644 tests/compile-fail/mut_mut.rs mode change 100755 => 100644 tests/compile-fail/needless_bool.rs mode change 100755 => 100644 tests/compile-fail/needless_return.rs mode change 100755 => 100644 tests/compile-fail/patterns.rs mode change 100755 => 100644 tests/compile-fail/precedence.rs mode change 100755 => 100644 tests/compile-fail/ptr_arg.rs mode change 100755 => 100644 tests/compile-fail/shadow.rs mode change 100755 => 100644 tests/compile-fail/strings.rs mode change 100755 => 100644 tests/compile-fail/unicode.rs mode change 100755 => 100644 tests/compile-fail/unit_cmp.rs mode change 100755 => 100644 tests/compile-fail/while_loop.rs diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/complex_types.rs b/tests/compile-fail/complex_types.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/dlist.rs b/tests/compile-fail/dlist.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/let_return.rs b/tests/compile-fail/let_return.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/let_unit.rs b/tests/compile-fail/let_unit.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/modulo_one.rs b/tests/compile-fail/modulo_one.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/patterns.rs b/tests/compile-fail/patterns.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/unit_cmp.rs b/tests/compile-fail/unit_cmp.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs old mode 100755 new mode 100644 -- cgit 1.4.1-3-g733a5 From 44b2b264466c112c148142e6b3233d3c6f1b1b76 Mon Sep 17 00:00:00 2001 From: Emanuel Czirai <zazdxscf@gmail.com> Date: Mon, 9 Nov 2015 06:49:44 +0100 Subject: update readme to specify both lint groups are needed for the whole set As a new user and newbie to rust, after reading this part of the readme("whole set"), I thought I was seeing a bug when I used `#![deny(clippy)]` but also had to add `#![deny(shadow_unrelated)]`. But this explained it: https://github.com/Manishearth/rust-clippy/blob/3322ffa8a048ef5369d3cdd914869fdf383473a4/src/lib.rs#L108 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a2ea945349..6a9a213af48 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ if let Some(y) = x { println!("{:?}", y) } ``` You can add options to `allow`/`warn`/`deny`: -- the whole set using the `clippy` lint group (`#![deny(clippy)]`, etc) +- the whole set using the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, `#![deny(clippy_pedantic)]`, etc) - only some lints (`#![deny(single_match, box_vec)]`, etc) - `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc -- cgit 1.4.1-3-g733a5 From 2801c1031d41d9d2399c4aff9653e078d54e98c4 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner <apaseltiner@gmail.com> Date: Mon, 9 Nov 2015 08:04:41 -0500 Subject: Remove executable permission from remaining source files --- src/consts.rs | 0 src/lib.rs | 0 tests/consts.rs | 0 tests/mut_mut_macro.rs | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/consts.rs mode change 100755 => 100644 src/lib.rs mode change 100755 => 100644 tests/consts.rs mode change 100755 => 100644 tests/mut_mut_macro.rs diff --git a/src/consts.rs b/src/consts.rs old mode 100755 new mode 100644 diff --git a/src/lib.rs b/src/lib.rs old mode 100755 new mode 100644 diff --git a/tests/consts.rs b/tests/consts.rs old mode 100755 new mode 100644 diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs old mode 100755 new mode 100644 -- cgit 1.4.1-3-g733a5 From aea2eb7da7ef9db34ee225abd3b625f428c00202 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 10 Nov 2015 10:25:21 +0100 Subject: use visitor for contains_self --- src/shadow.rs | 100 +++++++--------------------------------------------------- 1 file changed, 12 insertions(+), 88 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index 13df95bf8dd..ca45ed11ab8 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use rustc_front::hir::*; use reexport::*; use syntax::codemap::Span; -use rustc_front::visit::FnKind; +use rustc_front::visit::{Visitor, FnKind}; use rustc::lint::*; use rustc::middle::def::Def::{DefVariant, DefStruct}; @@ -269,97 +269,21 @@ fn path_eq_name(name: Name, path: &Path) -> bool { path.segments[0].identifier.name == name } -fn contains_self(name: Name, expr: &Expr) -> bool { - match expr.node { - // the "self" name itself (maybe) - ExprPath(_, ref path) => path_eq_name(name, path), - // no subexprs - ExprLit(_) => false, - // one subexpr - ExprUnary(_, ref e) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) | - ExprCast(ref e, _) => - contains_self(name, e), - // two subexprs - ExprBinary(_, ref l, ref r) | ExprIndex(ref l, ref r) | - ExprAssign(ref l, ref r) | ExprAssignOp(_, ref l, ref r) | - ExprRepeat(ref l, ref r) => - contains_self(name, l) || contains_self(name, r), - // one optional subexpr - ExprRet(ref oe) => - oe.as_ref().map_or(false, |ref e| contains_self(name, e)), - // two optional subexprs - ExprRange(ref ol, ref or) => - ol.as_ref().map_or(false, |ref e| contains_self(name, e)) || - or.as_ref().map_or(false, |ref e| contains_self(name, e)), - // one subblock - ExprBlock(ref block) | ExprLoop(ref block, _) | - ExprClosure(_, _, ref block) => - contains_block_self(name, block), - // one vec - ExprMethodCall(_, _, ref v) | ExprVec(ref v) | ExprTup(ref v) => - v.iter().any(|ref a| contains_self(name, a)), - // one expr, one vec - ExprCall(ref fun, ref args) => - contains_self(name, fun) || - args.iter().any(|ref a| contains_self(name, a)), - // special ones - ExprIf(ref cond, ref then, ref otherwise) => - contains_self(name, cond) || contains_block_self(name, then) || - otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)), - ExprWhile(ref e, ref block, _) => - contains_self(name, e) || contains_block_self(name, block), - ExprMatch(ref e, ref arms, _) => - contains_self(name, e) || - arms.iter().any( - |ref arm| - arm.pats.iter().any(|ref pat| contains_pat_self(name, pat)) || - arm.guard.as_ref().map_or(false, |ref g| contains_self(name, g)) || - contains_self(name, &arm.body)), - ExprStruct(_, ref fields, ref other) => - fields.iter().any(|ref f| contains_self(name, &f.expr)) || - other.as_ref().map_or(false, |ref e| contains_self(name, e)), - _ => false, - } +struct ContainsSelf { + name: Name, + result: bool } -fn contains_block_self(name: Name, block: &Block) -> bool { - for stmt in &block.stmts { - match stmt.node { - StmtDecl(ref decl, _) => - if let DeclLocal(ref local) = decl.node { - //TODO: We don't currently handle the case where the name - //is shadowed wiithin the block; this means code including this - //degenerate pattern will get the wrong warning. - if let Some(ref init) = local.init { - if contains_self(name, init) { return true; } - } - }, - StmtExpr(ref e, _) | StmtSemi(ref e, _) => - if contains_self(name, e) { return true } +impl<'v> Visitor<'v> for ContainsSelf { + fn visit_name(&mut self, _: Span, name: Name) { + if self.name == name { + self.result = true; } } - if let Some(ref e) = block.expr { contains_self(name, e) } else { false } } -fn contains_pat_self(name: Name, pat: &Pat) -> bool { - match pat.node { - PatIdent(_, ref ident, ref inner) => name == ident.node.name || - inner.as_ref().map_or(false, |ref p| contains_pat_self(name, p)), - PatEnum(_, ref opats) => opats.as_ref().map_or(false, - |pats| pats.iter().any(|p| contains_pat_self(name, p))), - PatQPath(_, ref path) => path_eq_name(name, path), - PatStruct(_, ref fieldpats, _) => fieldpats.iter().any( - |ref fp| contains_pat_self(name, &fp.node.pat)), - PatTup(ref ps) => ps.iter().any(|ref p| contains_pat_self(name, p)), - PatBox(ref p) | - PatRegion(ref p, _) => contains_pat_self(name, p), - PatRange(ref from, ref until) => - contains_self(name, from) || contains_self(name, until), - PatVec(ref pre, ref opt, ref post) => - pre.iter().any(|ref p| contains_pat_self(name, p)) || - opt.as_ref().map_or(false, |ref p| contains_pat_self(name, p)) || - post.iter().any(|ref p| contains_pat_self(name, p)), - _ => false, - } +fn contains_self(name: Name, expr: &Expr) -> bool { + let mut cs = ContainsSelf { name: name, result: false }; + cs.visit_expr(expr); + cs.result } -- cgit 1.4.1-3-g733a5 From 42ae1e69182577aa33a378e82362ca78be458bd2 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 10 Nov 2015 11:19:33 +0100 Subject: use rustc's eval_const, bail on (negative) infinity --- src/misc.rs | 16 +++++++++++----- tests/compile-fail/float_cmp.rs | 4 +++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 01ecb2c2cf8..85fd03079fe 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -6,10 +6,12 @@ use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; use rustc_front::visit::FnKind; use rustc::middle::ty; +use rustc::middle::const_eval::ConstVal::Float; +use rustc::middle::const_eval::eval_const_expr_partial; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use utils::span_help_and_lint; -use consts::constant; declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ @@ -119,10 +121,7 @@ impl LateLintPass for FloatCmp { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - if constant(cx, left).or_else(|| constant(cx, right)).map_or( - false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { - return; - } + if is_allowed(cx, left) || is_allowed(cx, right) { return; } if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); if name == "eq" || name == "ne" || name == "is_nan" || @@ -141,6 +140,13 @@ impl LateLintPass for FloatCmp { } } +fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { + let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); + if let Ok(Float(val)) = res { + val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY + } else { false } +} + fn is_float(cx: &LateContext, expr: &Expr) -> bool { if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { true diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index da3dba5e4d4..27cde245f68 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -35,8 +35,10 @@ impl PartialEq for X { fn main() { ZERO == 0f32; //no error, comparison with zero is ok + 1.0f32 != ::std::f32::INFINITY; // also comparison with infinity + 1.0f32 != ::std::f32::NEG_INFINITY; // and negative infinity ZERO == 0.0; //no error, comparison with zero is ok - ZERO + ZERO != 1.0; //~ERROR !=-comparison of f32 or f64 + ZERO + ZERO != 1.0; //no error, comparison with zero is ok ONE == 1f32; //~ERROR ==-comparison of f32 or f64 ONE == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64 -- cgit 1.4.1-3-g733a5 From e48973eb9faa1043de3c1dc5a5a86d709180c992 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 11 Nov 2015 00:12:45 +0100 Subject: Track elided lifetimes in types and trait objects --- src/lifetimes.rs | 86 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 206424de9b5..229d13401c6 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -3,6 +3,7 @@ use reexport::*; use rustc::lint::*; use syntax::codemap::Span; use rustc_front::visit::{Visitor, walk_ty, walk_ty_param_bound}; +use rustc::middle::def::Def::{DefTy, DefTrait}; use std::collections::HashSet; use utils::{in_external_macro, span_lint}; @@ -53,16 +54,16 @@ use self::RefLt::*; fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, generics: &Generics, span: Span) { - if in_external_macro(cx, span) || has_where_lifetimes(&generics.where_clause) { + if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; } - if could_use_elision(decl, slf, &generics.lifetimes) { + if could_use_elision(cx, decl, slf, &generics.lifetimes) { span_lint(cx, NEEDLESS_LIFETIMES, span, "explicit lifetimes given in parameter types where they could be elided"); } } -fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, +fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, named_lts: &[LifetimeDef]) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT @@ -74,8 +75,8 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, let allowed_lts = allowed_lts_from(named_lts); // these will collect all the lifetimes for references in arg/return types - let mut input_visitor = RefVisitor(Vec::new()); - let mut output_visitor = RefVisitor(Vec::new()); + let mut input_visitor = RefVisitor::new(cx); + let mut output_visitor = RefVisitor::new(cx); // extract lifetime in "self" argument for methods (there is a "self" argument // in func.inputs, but its type is TyInfer) @@ -88,14 +89,11 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>, } // extract lifetimes in input argument types for arg in &func.inputs { - walk_ty(&mut input_visitor, &arg.ty); - if let TyRptr(None, _) = arg.ty.node { - input_visitor.record(&None); - } + input_visitor.visit_ty(&arg.ty); } // extract lifetimes in output type if let Return(ref ty) = func.output { - walk_ty(&mut output_visitor, ty); + output_visitor.visit_ty(ty); } let input_lts = input_visitor.into_vec(); @@ -159,35 +157,75 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize { } /// A visitor usable for rustc_front::visit::walk_ty(). -struct RefVisitor(Vec<RefLt>); +struct RefVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, // context reference + lts: Vec<RefLt> +} + +impl <'v, 't> RefVisitor<'v, 't> { + fn new(cx: &'v LateContext<'v, 't>) -> RefVisitor<'v, 't> { + RefVisitor { cx: cx, lts: Vec::new() } + } -impl RefVisitor { fn record(&mut self, lifetime: &Option<Lifetime>) { if let &Some(ref lt) = lifetime { if lt.name.as_str() == "'static" { - self.0.push(Static); + self.lts.push(Static); } else { - self.0.push(Named(lt.name)); + self.lts.push(Named(lt.name)); } } else { - self.0.push(Unnamed); + self.lts.push(Unnamed); } } fn into_vec(self) -> Vec<RefLt> { - self.0 + self.lts + } + + fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) { + let last_path_segment = path.segments.last().map(|s| &s.parameters); + if let Some(&AngleBracketedParameters(ref params)) = last_path_segment { + if params.lifetimes.is_empty() { + let def = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()); + match def { + Some(DefTy(def_id, _)) => { + if let Some(ty_def) = self.cx.tcx.adt_defs.borrow().get(&def_id) { + let scheme = ty_def.type_scheme(self.cx.tcx); + for _ in scheme.generics.regions.as_slice() { + self.record(&None); + } + } + }, + Some(DefTrait(def_id)) => { + let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; + for _ in &trait_def.generics.regions { + self.record(&None); + } + }, + _ => {} + } + } + } } } -impl<'v> Visitor<'v> for RefVisitor { +impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { + // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.record(&Some(*lifetime)); } fn visit_ty(&mut self, ty: &'v Ty) { - if let TyRptr(None, _) = ty.node { - self.record(&None); + match ty.node { + TyRptr(None, _) => { + self.record(&None); + }, + TyPath(_, ref path) => { + self.collect_anonymous_lifetimes(path, ty); + }, + _ => {} } walk_ty(self, ty); } @@ -195,16 +233,16 @@ impl<'v> Visitor<'v> for RefVisitor { /// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to /// reason about elision. -fn has_where_lifetimes(where_clause: &WhereClause) -> bool { +fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { for predicate in &where_clause.predicates { match *predicate { WherePredicate::RegionPredicate(..) => return true, WherePredicate::BoundPredicate(ref pred) => { // a predicate like F: Trait or F: for<'a> Trait<'a> - let mut visitor = RefVisitor(Vec::new()); + let mut visitor = RefVisitor::new(cx); // walk the type F, it may not contain LT refs walk_ty(&mut visitor, &pred.bounded_ty); - if !visitor.0.is_empty() { return true; } + if !visitor.lts.is_empty() { return true; } // if the bounds define new lifetimes, they are fine to occur let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); // now walk the bounds @@ -219,9 +257,9 @@ fn has_where_lifetimes(where_clause: &WhereClause) -> bool { } } WherePredicate::EqPredicate(ref pred) => { - let mut visitor = RefVisitor(Vec::new()); + let mut visitor = RefVisitor::new(cx); walk_ty(&mut visitor, &pred.ty); - if !visitor.0.is_empty() { return true; } + if !visitor.lts.is_empty() { return true; } } } } -- cgit 1.4.1-3-g733a5 From 6046edbc234272dd2eeb7a98028e499e57f2a255 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 11 Nov 2015 00:26:22 +0100 Subject: Add some tests for lifetime elision lint with types and traits with lifetimes --- tests/compile-fail/lifetimes.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index a654c452379..f5d95aacc9a 100755 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -85,5 +85,26 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { unimplemented!() } +fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } //~ERROR explicit lifetimes given + +// no warning, two input lifetimes (named on the reference, anonymous on Foo) +fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { unimplemented!() } + +// no warning, two input lifetimes (anonymous on the reference, named on Foo) +fn struct_with_lt3<'a>(_foo: &Foo<'a> ) -> &'a str { unimplemented!() } + +// no warning, two input lifetimes +fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b> ) -> &'a str { unimplemented!() } + +trait WithLifetime<'a> {} +type WithLifetimeAlias<'a> = WithLifetime<'a>; + +// should not warn because it won't build without the lifetime +fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str { unimplemented!() } + +// this should warn because there is no lifetime on Drop, so this would be +// unambiguous if we elided the lifetime +fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } //~ERROR explicit lifetimes given + fn main() { } -- cgit 1.4.1-3-g733a5 From e8a239a1a2ec9e0da86a8553f9dff62431f8bd0e Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner <apaseltiner@gmail.com> Date: Wed, 11 Nov 2015 09:28:31 -0500 Subject: Add lint for useless transmutes Closes #441. --- README.md | 3 ++- src/lib.rs | 3 +++ src/transmute.rs | 37 +++++++++++++++++++++++++++++++++ tests/compile-fail/transmute.rs | 46 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/transmute.rs create mode 100644 tests/compile-fail/transmute.rs diff --git a/README.md b/README.md index 6727707717f..b893c4e7a17 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 73 lints included in this crate: +There are 74 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -77,6 +77,7 @@ name [unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention diff --git a/src/lib.rs b/src/lib.rs index 970a244e2cd..afbf3d2a92c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,7 @@ pub mod needless_features; pub mod needless_update; pub mod no_effect; pub mod temporary_assignment; +pub mod transmute; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -104,6 +105,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); + reg.register_late_lint_pass(box transmute::UselessTransmute); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -175,6 +177,7 @@ pub fn plugin_registrar(reg: &mut Registry) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, temporary_assignment::TEMPORARY_ASSIGNMENT, + transmute::USELESS_TRANSMUTE, types::BOX_VEC, types::LET_UNIT_VALUE, types::LINKEDLIST, diff --git a/src/transmute.rs b/src/transmute.rs new file mode 100644 index 00000000000..ab1397ea7fe --- /dev/null +++ b/src/transmute.rs @@ -0,0 +1,37 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils; + +declare_lint! { + pub USELESS_TRANSMUTE, + Warn, + "transmutes that have the same to and from types" +} + +pub struct UselessTransmute; + +impl LintPass for UselessTransmute { + fn get_lints(&self) -> LintArray { + lint_array!(USELESS_TRANSMUTE) + } +} + +impl LateLintPass for UselessTransmute { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprCall(ref path_expr, ref args) = e.node { + if let ExprPath(None, _) = path_expr.node { + let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + + if utils::match_def_path(cx, def_id, &["core", "intrinsics", "transmute"]) { + let from_ty = cx.tcx.expr_ty(&args[0]); + let to_ty = cx.tcx.expr_ty(e); + + if from_ty == to_ty { + cx.span_lint(USELESS_TRANSMUTE, e.span, + &format!("transmute from a type (`{}`) to itself", from_ty)); + } + } + } + } + } +} diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs new file mode 100644 index 00000000000..0a2d09d9431 --- /dev/null +++ b/tests/compile-fail/transmute.rs @@ -0,0 +1,46 @@ +#![feature(core)] +#![feature(plugin)] +#![plugin(clippy)] +#![deny(useless_transmute)] + +extern crate core; + +use std::mem::transmute as my_transmute; +use std::vec::Vec as MyVec; + +fn my_vec() -> MyVec<i32> { + vec![] +} + +#[allow(needless_lifetimes)] +unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { + let _: &'a T = core::intrinsics::transmute(t); + //~^ ERROR transmute from a type (`&'a T`) to itself + + let _: &'a U = core::intrinsics::transmute(t); +} + +fn main() { + unsafe { + let _: Vec<i32> = core::intrinsics::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + + let _: Vec<i32> = core::mem::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + + let _: Vec<i32> = std::intrinsics::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + + let _: Vec<i32> = std::mem::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + + let _: Vec<i32> = my_transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + + let _: Vec<u32> = core::intrinsics::transmute(my_vec()); + let _: Vec<u32> = core::mem::transmute(my_vec()); + let _: Vec<u32> = std::intrinsics::transmute(my_vec()); + let _: Vec<u32> = std::mem::transmute(my_vec()); + let _: Vec<u32> = my_transmute(my_vec()); + } +} -- cgit 1.4.1-3-g733a5 From 91763d77251f7f84529b6802fe6172854641a520 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner <apaseltiner@gmail.com> Date: Wed, 11 Nov 2015 11:08:33 -0500 Subject: Match `min` and `max` functions using `DefId` Closes #446. --- src/minmax.rs | 16 +++++++++------- tests/compile-fail/min_max.rs | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/minmax.rs b/src/minmax.rs index a94b0b42ec1..3171a951422 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -5,7 +5,7 @@ use std::cmp::PartialOrd; use std::cmp::Ordering::*; use consts::{Constant, constant_simple}; -use utils::{match_path, span_lint}; +use utils::{match_def_path, span_lint}; use self::MinMax::{Min, Max}; declare_lint!(pub MIN_MAX, Warn, @@ -23,8 +23,8 @@ impl LintPass for MinMaxPass { impl LateLintPass for MinMaxPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some((outer_max, outer_c, oe)) = min_max(expr) { - if let Some((inner_max, inner_c, _)) = min_max(oe) { + if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { + if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { if outer_max == inner_max { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), @@ -44,13 +44,15 @@ enum MinMax { Max, } -fn min_max(expr: &Expr) -> Option<(MinMax, Constant, &Expr)> { +fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { if let ExprCall(ref path, ref args) = expr.node { - if let ExprPath(None, ref path) = path.node { - if match_path(path, &["std", "cmp", "min"]) { + if let ExprPath(None, _) = path.node { + let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + + if match_def_path(cx, def_id, &["core", "cmp", "min"]) { fetch_const(args, Min) } else { - if match_path(path, &["std", "cmp", "max"]) { + if match_def_path(cx, def_id, &["core", "cmp", "max"]) { fetch_const(args, Max) } else { None diff --git a/tests/compile-fail/min_max.rs b/tests/compile-fail/min_max.rs index 5a5fae4930d..9a6794afebf 100644 --- a/tests/compile-fail/min_max.rs +++ b/tests/compile-fail/min_max.rs @@ -4,6 +4,8 @@ #![deny(clippy)] use std::cmp::{min, max}; +use std::cmp::min as my_min; +use std::cmp::max as my_max; const LARGE : usize = 3; @@ -15,6 +17,8 @@ fn main() { max(min(x, 1), 3); //~ERROR this min/max combination leads to constant result max(3, min(x, 1)); //~ERROR this min/max combination leads to constant result + my_max(3, my_min(x, 1)); //~ERROR this min/max combination leads to constant result + min(3, max(1, x)); // ok, could be 1, 2 or 3 depending on x min(1, max(LARGE, x)); // no error, we don't lookup consts here -- cgit 1.4.1-3-g733a5 From b17e38782e4cf4313c7ce21c27f00a98dcf823c1 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Tue, 17 Nov 2015 13:39:42 +0900 Subject: Remove trailing commas in match arms with blocks --- src/bit_mask.rs | 2 +- src/consts.rs | 12 ++++++------ src/eta_reduction.rs | 2 +- src/identity_op.rs | 6 +++--- src/lifetimes.rs | 8 ++++---- src/loops.rs | 4 ++-- src/map_clone.rs | 6 +++--- src/minmax.rs | 2 +- src/misc.rs | 4 ++-- src/mut_reference.rs | 8 ++++---- src/needless_bool.rs | 8 ++++---- src/open_options.rs | 12 ++++++------ src/shadow.rs | 18 +++++++++--------- src/types.rs | 4 ++-- src/utils.rs | 2 +- tests/compile-fail/matches.rs | 8 ++++---- 16 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index e6665bbbb4d..c8530b92d48 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -185,7 +185,7 @@ fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { if let &LitInt(value, _) = &lit_ptr.node { Option::Some(value) //TODO: Handle sign } else { Option::None } - }, + } ExprPath(_, _) => { // Important to let the borrow expire before the const lookup to avoid double // borrowing. diff --git a/src/consts.rs b/src/consts.rs index 766d998c256..1750495d1f3 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -246,7 +246,7 @@ fn constant_not(o: Constant) -> Option<Constant> { SignedIntLit(ity, Plus) => { if value == ::std::u64::MAX { return None; } (value + 1, SignedIntLit(ity, Minus)) - }, + } SignedIntLit(ity, Minus) => { if value == 0 { (1, SignedIntLit(ity, Minus)) @@ -267,7 +267,7 @@ fn constant_not(o: Constant) -> Option<Constant> { UnsuffixedIntLit(_) => { return None; } // refuse to guess }; ConstantInt(nvalue, nty) - }, + } _ => { return None; } }) } @@ -279,11 +279,11 @@ fn constant_negate(o: Constant) -> Option<Constant> { SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; }, + _ => { return None; } }), ConstantFloat(is, ty) => ConstantFloat(neg_float_str(is), ty), - _ => { return None; }, + _ => { return None; } }) } @@ -461,7 +461,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { add_neg_int(l64, lty, r64, rty) } } - }, + } // TODO: float (would need bignum library?) _ => None }), @@ -513,7 +513,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { unify_int_type(lty, rty, if is_negative(lty) == is_negative(rty) { Plus } else { Minus }) .map(|ty| ConstantInt(value, ty))) - }, + } _ => None, }) } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 855ea51ee8e..c4c0912464c 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -26,7 +26,7 @@ impl LateLintPass for EtaPass { for arg in args { check_closure(cx, arg) } - }, + } _ => (), } } diff --git a/src/identity_op.rs b/src/identity_op.rs index aee208d624e..7ed784f00fc 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -26,19 +26,19 @@ impl LateLintPass for IdentityOp { BiAdd | BiBitOr | BiBitXor => { check(cx, left, 0, e.span, right.span); check(cx, right, 0, e.span, left.span); - }, + } BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), BiMul => { check(cx, left, 1, e.span, right.span); check(cx, right, 1, e.span, left.span); - }, + } BiDiv => check(cx, right, 1, e.span, left.span), BiBitAnd => { check(cx, left, -1, e.span, right.span); check(cx, right, -1, e.span, left.span); - }, + } _ => () } } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 229d13401c6..09c5821dd49 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -196,13 +196,13 @@ impl <'v, 't> RefVisitor<'v, 't> { self.record(&None); } } - }, + } Some(DefTrait(def_id)) => { let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; for _ in &trait_def.generics.regions { self.record(&None); } - }, + } _ => {} } } @@ -221,10 +221,10 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { match ty.node { TyRptr(None, _) => { self.record(&None); - }, + } TyPath(_, ref path) => { self.collect_anonymous_lifetimes(path, ty); - }, + } _ => {} } walk_ty(self, ty); diff --git a/src/loops.rs b/src/loops.rs index d056c67c541..60ae2c23f0a 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -545,13 +545,13 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { match parent.node { ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => { self.state = VarState::DontWarn; - }, + } ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { self.state = if is_integer_literal(rhs, 0) && self.depth == 0 { VarState::Warn } else { VarState::DontWarn - }}, + }} ExprAddrOf(mutability,_) if mutability == MutMutable => self.state = VarState::DontWarn, _ => () } diff --git a/src/map_clone.rs b/src/map_clone.rs index b9f677dd03d..ba561fbb167 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -55,7 +55,7 @@ impl LateLintPass for MapClonePass { } } } - }, + } ExprPath(_, ref path) => { if match_path(path, &CLONE_PATH) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); @@ -77,7 +77,7 @@ fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { ExprPath(None, ref path) => { let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }]; !path.global && path.segments == arg_segment - }, + } _ => false, } } @@ -104,7 +104,7 @@ fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool { match expr.node { ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => { only_derefs(cx, subexpr, id) - }, + } _ => expr_eq_ident(expr, id), } } diff --git a/src/minmax.rs b/src/minmax.rs index 3171a951422..7ed65184727 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -31,7 +31,7 @@ impl LateLintPass for MinMaxPass { _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result") - }, + } } } } diff --git a/src/misc.rs b/src/misc.rs index 85fd03079fe..857ae1cc0c3 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -187,7 +187,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o } else { return } - }, + } ExprCall(ref path, ref v) if v.len() == 1 => { if let &ExprPath(None, ref path) = &path.node { if match_path(path, &["String", "from_str"]) || @@ -199,7 +199,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o } else { return } - }, + } _ => return }; if left { diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 1cc04e096ba..86c272affb7 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -32,14 +32,14 @@ impl LateLintPass for UnnecessaryMutPassed { check_arguments(cx, &arguments, function_type, &format!("{}", path)); } - }, + } None => unreachable!(), // A function with unknown type is called. // If this happened the compiler would have aborted the // compilation long ago. }; - }, + } ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); match borrowed_table.method_map.get(&method_call) { @@ -47,7 +47,7 @@ impl LateLintPass for UnnecessaryMutPassed { &format!("{}", name.node.as_str())), None => unreachable!(), // Just like above, this should never happen. }; - }, + } _ => {} } } @@ -66,7 +66,7 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty doesn't need a mutable reference", name)); } - }, + } _ => {} } } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index c0a99acb71d..52f23c7518a 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -31,10 +31,10 @@ impl LateLintPass for NeedlessBool { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (Some(true), Some(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "this if-then-else expression will always return true"); }, + "this if-then-else expression will always return true"); } (Some(false), Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "this if-then-else expression will always return false"); }, + "this if-then-else expression will always return false"); } (Some(true), Some(false)) => { let pred_snip = snippet(cx, pred.span, ".."); let hint = if pred_snip == ".." { "its predicate".into() } else { @@ -42,7 +42,7 @@ impl LateLintPass for NeedlessBool { }; span_lint(cx, NEEDLESS_BOOL, e.span, &format!( "you can reduce this if-then-else expression to just {}", hint)); - }, + } (Some(false), Some(true)) => { let pred_snip = snippet(cx, pred.span, ".."); let hint = if pred_snip == ".." { "`!` and its predicate".into() } else { @@ -50,7 +50,7 @@ impl LateLintPass for NeedlessBool { }; span_lint(cx, NEEDLESS_BOOL, e.span, &format!( "you can reduce this if-then-else expression to just {}", hint)); - }, + } _ => () } } diff --git a/src/open_options.rs b/src/open_options.rs index 76a2eeef1ba..732852e1686 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -65,7 +65,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp // which is not a boolean literal. This is theoretically // possible, but not very likely. } - }, + } _ => { Argument::Unknown } @@ -74,19 +74,19 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp match &*name.node.as_str() { "create" => { options.push((OpenOption::Create, argument_option)); - }, + } "append" => { options.push((OpenOption::Append, argument_option)); - }, + } "truncate" => { options.push((OpenOption::Truncate, argument_option)); - }, + } "read" => { options.push((OpenOption::Read, argument_option)); - }, + } "write" => { options.push((OpenOption::Write, argument_option)); - }, + } _ => {} } diff --git a/src/shadow.rs b/src/shadow.rs index ca45ed11ab8..a1e86028752 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -101,7 +101,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, } } if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } - }, + } //PatEnum(Path, Option<Vec<P<Pat>>>), PatStruct(_, ref pfields, _) => if let Some(ref init_struct) = *init { @@ -149,7 +149,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, } else { check_pat(cx, inner, init, span, bindings); } - }, + } PatRegion(ref inner, _) => check_pat(cx, inner, init, span, bindings), //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), @@ -200,9 +200,9 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { match expr.node { ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) - => { check_expr(cx, e, bindings) }, + => { check_expr(cx, e, bindings) } ExprBlock(ref block) | ExprLoop(ref block, _) => - { check_block(cx, block, bindings) }, + { check_block(cx, block, bindings) } //ExprCall //ExprMethodCall ExprVec(ref v) | ExprTup(ref v) => @@ -211,11 +211,11 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { check_expr(cx, cond, bindings); check_block(cx, then, bindings); if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } - }, + } ExprWhile(ref cond, ref block, _) => { check_expr(cx, cond, bindings); check_block(cx, block, bindings); - }, + } ExprMatch(ref init, ref arms, _) => { check_expr(cx, init, bindings); let len = bindings.len(); @@ -230,7 +230,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { bindings.truncate(len); } } - }, + } _ => () } } @@ -242,10 +242,10 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { TyFixedLengthVec(ref fty, ref expr) => { check_ty(cx, fty, bindings); check_expr(cx, expr, bindings); - }, + } TyPtr(MutTy{ ty: ref mty, .. }) | TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } }, + TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } } TyTypeof(ref expr) => check_expr(cx, expr, bindings), _ => (), } diff --git a/src/types.rs b/src/types.rs index 93962586bc6..68120f65e1f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -229,7 +229,7 @@ impl LateLintPass for CastPass { if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); } - }, + } (false, true) => { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &format!("casting {} to {} may truncate the value", @@ -239,7 +239,7 @@ impl LateLintPass for CastPass { &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } - }, + } (true, true) => { if cast_from.is_signed() && !cast_to.is_signed() { span_lint(cx, CAST_SIGN_LOSS, expr.span, diff --git a/src/utils.rs b/src/utils.rs index e56eab5ad28..3fcfa66259c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -167,7 +167,7 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { Some(NodeTraitItem(&TraitItem{ id: _, ref name, .. })) | Some(NodeImplItem(&ImplItem{ id: _, ref name, .. })) => { Some(*name) - }, + } _ => None, } } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index ff92a67271b..20d7552d77a 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -54,17 +54,17 @@ fn match_bool() { match test { //~ ERROR you seem to be trying to match on a boolean expression true => (), - false => { println!("Noooo!"); }, + false => { println!("Noooo!"); } }; match test { //~ ERROR you seem to be trying to match on a boolean expression - false => { println!("Noooo!"); }, + false => { println!("Noooo!"); } _ => (), }; match test { //~ ERROR you seem to be trying to match on a boolean expression - false => { println!("Noooo!"); }, - true => { println!("Yes!"); }, + false => { println!("Noooo!"); } + true => { println!("Yes!"); } }; // Not linted -- cgit 1.4.1-3-g733a5 From 1d602d0f124904f91d6d934e83a8a687f314e110 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Tue, 17 Nov 2015 14:22:57 +0900 Subject: rustfmt a little --- src/minmax.rs | 2 +- src/mut_mut.rs | 6 +++--- src/needless_bool.rs | 6 ++++-- src/needless_features.rs | 4 ++-- src/precedence.rs | 8 ++++---- src/strings.rs | 2 +- src/zero_div_zero.rs | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/minmax.rs b/src/minmax.rs index 7ed65184727..9eb8a030e15 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -17,7 +17,7 @@ pub struct MinMaxPass; impl LintPass for MinMaxPass { fn get_lints(&self) -> LintArray { - lint_array!(MIN_MAX) + lint_array!(MIN_MAX) } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 9b6a5d9ddcc..a92338165dd 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -19,7 +19,7 @@ impl LintPass for MutMut { impl LateLintPass for MutMut { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - check_expr_mut(cx, expr) + check_expr_mut(cx, expr) } fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { @@ -31,7 +31,7 @@ impl LateLintPass for MutMut { fn check_expr_mut(cx: &LateContext, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } - fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + fn unwrap_addr(expr: &Expr) -> Option<&Expr> { match expr.node { ExprAddrOf(MutMutable, ref e) => Option::Some(e), _ => Option::None @@ -53,7 +53,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { }) } -fn unwrap_mut(ty : &Ty) -> Option<&Ty> { +fn unwrap_mut(ty: &Ty) -> Option<&Ty> { match ty.node { TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), _ => Option::None diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 52f23c7518a..e4d3b00218e 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -31,10 +31,12 @@ impl LateLintPass for NeedlessBool { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (Some(true), Some(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "this if-then-else expression will always return true"); } + "this if-then-else expression will always return true"); + } (Some(false), Some(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, - "this if-then-else expression will always return false"); } + "this if-then-else expression will always return false"); + } (Some(true), Some(false)) => { let pred_snip = snippet(cx, pred.span, ".."); let hint = if pred_snip == ".." { "its predicate".into() } else { diff --git a/src/needless_features.rs b/src/needless_features.rs index b1d38df7311..44db5e92221 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{span_lint}; +use utils::span_lint; use utils; declare_lint! { @@ -27,7 +27,7 @@ pub struct NeedlessFeaturesPass; impl LintPass for NeedlessFeaturesPass { fn get_lints(&self) -> LintArray { - lint_array!(UNSTABLE_AS_SLICE,UNSTABLE_AS_MUT_SLICE) + lint_array!(UNSTABLE_AS_SLICE, UNSTABLE_AS_MUT_SLICE) } } diff --git a/src/precedence.rs b/src/precedence.rs index b7dbe268557..b659bd647a7 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -53,7 +53,7 @@ impl EarlyLintPass for Precedence { method call. Consider adding parentheses \ to clarify your intent: -({})", snippet(cx, rhs.span, ".."))), - _ => () + _ => () } } } @@ -62,21 +62,21 @@ impl EarlyLintPass for Precedence { } } -fn is_arith_expr(expr : &Expr) -> bool { +fn is_arith_expr(expr: &Expr) -> bool { match expr.node { ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), _ => false } } -fn is_bit_op(op : BinOp_) -> bool { +fn is_bit_op(op: BinOp_) -> bool { match op { BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, _ => false } } -fn is_arith_op(op : BinOp_) -> bool { +fn is_arith_op(op: BinOp_) -> bool { match op { BiAdd | BiSub | BiMul | BiDiv | BiRem => true, _ => false diff --git a/src/strings.rs b/src/strings.rs index 6bbf94004b0..08274657538 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -51,7 +51,7 @@ impl LateLintPass for StringAdd { "you added something to a string. \ Consider using `String::push_str()` instead") } - } else if let &ExprAssign(ref target, ref src) = &e.node { + } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(cx, src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 37d5d8904e1..484348c5a37 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{span_help_and_lint}; +use utils::span_help_and_lint; use consts::{Constant, constant_simple, FloatWidth}; /// ZeroDivZeroPass is a pass that checks for a binary expression that consists -- cgit 1.4.1-3-g733a5 From 9511e6739dad2874aa39350cb74fcbcc28fe087d Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 19 Nov 2015 15:51:30 +0100 Subject: Update to latest rust nightly --- src/attrs.rs | 2 +- src/eq_op.rs | 1 - src/len_zero.rs | 2 +- src/lifetimes.rs | 4 ++-- src/loops.rs | 2 +- src/methods.rs | 2 +- src/misc.rs | 2 +- src/ptr_arg.rs | 2 +- src/shadow.rs | 4 ++-- src/types.rs | 6 +++--- 10 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 79cec664adc..a0101688668 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -49,7 +49,7 @@ fn is_relevant_item(item: &Item) -> bool { fn is_relevant_impl(item: &ImplItem) -> bool { match item.node { - MethodImplItem(_, ref block) => is_relevant_block(block), + ImplItemKind::Method(_, ref block) => is_relevant_block(block), _ => false } } diff --git a/src/eq_op.rs b/src/eq_op.rs index 6f305b6adf8..1d2146537c9 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -105,7 +105,6 @@ fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty), (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), - (&TyParen(ref lty), &TyParen(ref rty)) => is_cast_ty_equal(lty, rty), (&TyInfer, &TyInfer) => true, _ => false } diff --git a/src/len_zero.rs b/src/len_zero.rs index f5ad37a71be..25645ea8742 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -71,7 +71,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>] fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.name.as_str() == name && if let MethodImplItem(ref sig, _) = + item.name.as_str() == name && if let ImplItemKind::Method(ref sig, _) = item.node { is_self_sig(sig) } else { false } } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 09c5821dd49..9b47a4d830f 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -2,7 +2,7 @@ use rustc_front::hir::*; use reexport::*; use rustc::lint::*; use syntax::codemap::Span; -use rustc_front::visit::{Visitor, walk_ty, walk_ty_param_bound}; +use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound}; use rustc::middle::def::Def::{DefTy, DefTrait}; use std::collections::HashSet; @@ -29,7 +29,7 @@ impl LateLintPass for LifetimePass { } fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let MethodImplItem(ref sig, _) = item.node { + if let ImplItemKind::Method(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); } diff --git a/src/loops.rs b/src/loops.rs index 60ae2c23f0a..92dff3a7d93 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; -use rustc_front::visit::{Visitor, walk_expr, walk_block, walk_decl}; +use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use rustc::middle::ty; use rustc::middle::def::DefLocal; use consts::{constant_simple, Constant}; diff --git a/src/methods.rs b/src/methods.rs index 18da7e977d6..275de8d8ebd 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -77,7 +77,7 @@ impl LateLintPass for MethodsPass { if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { for implitem in items { let name = implitem.name; - if let MethodImplItem(ref sig, _) = implitem.node { + if let ImplItemKind::Method(ref sig, _) = implitem.node { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if_let_chain! { diff --git a/src/misc.rs b/src/misc.rs index 857ae1cc0c3..9a8ce74e997 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -4,7 +4,7 @@ use rustc_front::hir::*; use reexport::*; use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; -use rustc_front::visit::FnKind; +use rustc_front::intravisit::FnKind; use rustc::middle::ty; use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::eval_const_expr_partial; diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 78a3c146c0f..78be2af1217 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -34,7 +34,7 @@ impl LateLintPass for PtrArg { } fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let &MethodImplItem(ref sig, _) = &item.node { + if let &ImplItemKind::Method(ref sig, _) = &item.node { if let Some(Node::NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { if let ItemImpl(_, _, _, Some(_), _, _) = it.node { return; // ignore trait impls diff --git a/src/shadow.rs b/src/shadow.rs index a1e86028752..3f72722333b 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use rustc_front::hir::*; use reexport::*; use syntax::codemap::Span; -use rustc_front::visit::{Visitor, FnKind}; +use rustc_front::intravisit::{Visitor, FnKind}; use rustc::lint::*; use rustc::middle::def::Def::{DefVariant, DefStruct}; @@ -237,7 +237,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { match ty.node { - TyParen(ref sty) | TyObjectSum(ref sty, _) | + TyObjectSum(ref sty, _) | TyVec(ref sty) => check_ty(cx, sty, bindings), TyFixedLengthVec(ref fty, ref expr) => { check_ty(cx, fty, bindings); diff --git a/src/types.rs b/src/types.rs index 68120f65e1f..506509cdfed 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,7 +3,7 @@ use rustc_front::hir::*; use reexport::*; use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; -use rustc_front::visit::{FnKind, Visitor, walk_ty}; +use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; @@ -305,8 +305,8 @@ impl LateLintPass for TypeComplexityPass { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { match item.node { - ConstImplItem(ref ty, _) | - TypeImplItem(ref ty) => check_type(cx, ty), + ImplItemKind::Const(ref ty, _) | + ImplItemKind::Type(ref ty) => check_type(cx, ty), // methods are covered by check_fn _ => () } -- cgit 1.4.1-3-g733a5 From cad88a91371a988a0078016c44b1d6f3c24dec57 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 19 Nov 2015 14:39:27 +0100 Subject: warn on use of ok().expect() --- src/lib.rs | 3 +- src/methods.rs | 108 ++++++++++++++++++++++++++++++++++++++++-- tests/compile-fail/methods.rs | 23 +++++++++ 3 files changed, 128 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index afbf3d2a92c..35e303b749b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,7 +85,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box methods::MethodsPass); + reg.register_late_lint_pass(box methods::MethodsPass::new()); reg.register_late_lint_pass(box shadow::ShadowPass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); @@ -151,6 +151,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_BOOL, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, + methods::OK_EXPECT, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, diff --git a/src/methods.rs b/src/methods.rs index 275de8d8ebd..dbc18fdfe33 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,18 +1,81 @@ use rustc_front::hir::*; use rustc::lint::*; use rustc::middle::ty; -use rustc::middle::subst::Subst; +use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; +use std::collections::HashSet; -use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth}; +use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth, + walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; use self::SelfKind::*; use self::OutType::*; -#[derive(Copy,Clone)] -pub struct MethodsPass; +use rustc::middle::def_id::DefId; + +use rustc::middle::ty::TypeFlags; + +#[derive(Clone)] +pub struct MethodsPass { types_implementing_debug: Option<HashSet<DefId>> } + +impl MethodsPass { + pub fn new() -> MethodsPass { + MethodsPass { types_implementing_debug: None } + } + + fn get_debug_impls(&mut self, cx: &LateContext) -> Option<&HashSet<DefId>> { + if self.types_implementing_debug.is_none() { + let debug = match cx.tcx.lang_items.debug_trait() { + Some(debug) => debug, + None => return None + }; + let debug_def = cx.tcx.lookup_trait_def(debug); + let mut impls = HashSet::new(); + debug_def.for_each_impl(cx.tcx, |d| { + let o_self_ty = &cx.tcx.impl_trait_ref(d) + .map(|x| x.substs) + .and_then(|x| x.self_ty()); + let self_ty = match *o_self_ty { + Some(self_type) => self_type, + None => return + }; + let self_ty_def_id = self_ty.ty_to_def_id(); + if let Some(self_ty_def_id) = self_ty_def_id { + let has_params = self_ty.flags.get().contains(TypeFlags::HAS_PARAMS); + if !has_params { + impls.insert(self_ty_def_id); + } + } + }); + self.types_implementing_debug = Some(impls); + } + self.types_implementing_debug.as_ref() + } + + // This checks whether a given type is known to implement Debug. It's + // conservative, i.e. it should not return false positives, but will return + // false negatives. + fn has_debug_impl(&mut self, ty: ty::Ty, cx: &LateContext) -> bool { + let debug_impls = match self.get_debug_impls(cx) { + Some(debug_impls) => debug_impls, + None => return false + }; + match walk_ptrs_ty(ty).sty { + ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) + | ty::TyFloat(..) | ty::TyStr => true, + ty::TyTuple(ref v) if v.is_empty() => true, + ty::TyStruct(..) | ty::TyEnum(..) => { + match ty.ty_to_def_id() { + Some(ref ty_def_id) => debug_impls.contains(ty_def_id), + None => false + } + }, + _ => false + } + } +} declare_lint!(pub OPTION_UNWRAP_USED, Allow, "using `Option.unwrap()`, which should at least get a better message using `expect()`"); @@ -30,16 +93,21 @@ declare_lint!(pub WRONG_SELF_CONVENTION, Warn, declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, "defining a public method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); +declare_lint!(pub OK_EXPECT, Warn, + "using `ok().expect()`, which gives worse error messages than \ + calling `expect` directly on the Result"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, - SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION) + SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, OK_EXPECT) } } impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprMethodCall(ref name, _, ref args) = expr.node { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); if name.node.as_str() == "unwrap" { @@ -70,6 +138,22 @@ impl LateLintPass for MethodsPass { `clone()` to make a copy"); } } + else if name.node.as_str() == "expect" { + if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + if inner_name.node.as_str() == "ok" + && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &RESULT_PATH) { + let result_type = cx.tcx.expr_ty(&inner_args[0]); + if let Some(error_type) = get_error_type(cx, result_type) { + if self.has_debug_impl(error_type, cx) { + span_lint(cx, OK_EXPECT, expr.span, + "called `ok().expect()` on a Result \ + value. You can call `expect` directly + on the `Result`"); + } + } + } + } + } } } @@ -115,6 +199,20 @@ impl LateLintPass for MethodsPass { } } +// Given a `Result<T, E>` type, return its error type (`E`) +fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { + if !match_type(cx, ty, &RESULT_PATH) { + return None; + } + if let ty::TyEnum(_, substs) = ty.sty { + if let Some(err_ty) = substs.types.opt_get(TypeSpace, 1) { + return Some(err_ty); + } + } + None +} + + const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ("into_", &[ValueSelf]), ("to_", &[RefSelf]), diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 314601f6dbd..aeb79503504 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -35,6 +35,8 @@ impl Mul<T> for T { } fn main() { + use std::io; + let opt = Some(0); let _ = opt.unwrap(); //~ERROR used unwrap() on an Option @@ -46,4 +48,25 @@ fn main() { let v = &"str"; let string = v.to_string(); //~ERROR `(*v).to_owned()` is faster let _again = string.to_string(); //~ERROR `String.to_string()` is a no-op + + res.ok().expect("disaster!"); //~ERROR called `ok().expect()` + // the following should not warn, since `expect` isn't implemented unless + // the error type implements `Debug` + let res2: Result<i32, MyError> = Ok(0); + res2.ok().expect("oh noes!"); + // we're currently don't warn if the error type has a type parameter + // (but it would be nice if we did) + let res3: Result<u32, MyErrorWithParam<u8>>= Ok(0); + res3.ok().expect("whoof"); + let res4: Result<u32, io::Error> = Ok(0); + res4.ok().expect("argh"); //~ERROR called `ok().expect()` + let res5: io::Result<u32> = Ok(0); + res5.ok().expect("oops"); //~ERROR called `ok().expect()` +} + +struct MyError(()); // doesn't implement Debug + +#[derive(Debug)] +struct MyErrorWithParam<T> { + x: T } -- cgit 1.4.1-3-g733a5 From 516f6484607166f062d723544f335d7d5e5c2fb5 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 19 Nov 2015 14:40:51 +0100 Subject: Run update_lints --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b893c4e7a17..64585cfcc02 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 74 lints included in this crate: +There are 75 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -50,6 +50,7 @@ name [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -- cgit 1.4.1-3-g733a5 From 096c064d4374daf6292cb54f7cf4fac4a8eda718 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 19 Nov 2015 20:13:36 +0100 Subject: Simplify has_debug_impl --- src/lib.rs | 2 +- src/methods.rs | 87 ++++++++++++------------------------------- tests/compile-fail/methods.rs | 4 +- 3 files changed, 27 insertions(+), 66 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 35e303b749b..d977ed07bfd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,7 +85,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box methods::MethodsPass::new()); + reg.register_late_lint_pass(box methods::MethodsPass); reg.register_late_lint_pass(box shadow::ShadowPass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); diff --git a/src/methods.rs b/src/methods.rs index dbc18fdfe33..858a5a3dca0 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -4,7 +4,6 @@ use rustc::middle::ty; use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; -use std::collections::HashSet; use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth, walk_ptrs_ty}; @@ -13,69 +12,8 @@ use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; use self::SelfKind::*; use self::OutType::*; -use rustc::middle::def_id::DefId; - -use rustc::middle::ty::TypeFlags; - #[derive(Clone)] -pub struct MethodsPass { types_implementing_debug: Option<HashSet<DefId>> } - -impl MethodsPass { - pub fn new() -> MethodsPass { - MethodsPass { types_implementing_debug: None } - } - - fn get_debug_impls(&mut self, cx: &LateContext) -> Option<&HashSet<DefId>> { - if self.types_implementing_debug.is_none() { - let debug = match cx.tcx.lang_items.debug_trait() { - Some(debug) => debug, - None => return None - }; - let debug_def = cx.tcx.lookup_trait_def(debug); - let mut impls = HashSet::new(); - debug_def.for_each_impl(cx.tcx, |d| { - let o_self_ty = &cx.tcx.impl_trait_ref(d) - .map(|x| x.substs) - .and_then(|x| x.self_ty()); - let self_ty = match *o_self_ty { - Some(self_type) => self_type, - None => return - }; - let self_ty_def_id = self_ty.ty_to_def_id(); - if let Some(self_ty_def_id) = self_ty_def_id { - let has_params = self_ty.flags.get().contains(TypeFlags::HAS_PARAMS); - if !has_params { - impls.insert(self_ty_def_id); - } - } - }); - self.types_implementing_debug = Some(impls); - } - self.types_implementing_debug.as_ref() - } - - // This checks whether a given type is known to implement Debug. It's - // conservative, i.e. it should not return false positives, but will return - // false negatives. - fn has_debug_impl(&mut self, ty: ty::Ty, cx: &LateContext) -> bool { - let debug_impls = match self.get_debug_impls(cx) { - Some(debug_impls) => debug_impls, - None => return false - }; - match walk_ptrs_ty(ty).sty { - ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) - | ty::TyFloat(..) | ty::TyStr => true, - ty::TyTuple(ref v) if v.is_empty() => true, - ty::TyStruct(..) | ty::TyEnum(..) => { - match ty.ty_to_def_id() { - Some(ref ty_def_id) => debug_impls.contains(ty_def_id), - None => false - } - }, - _ => false - } - } -} +pub struct MethodsPass; declare_lint!(pub OPTION_UNWRAP_USED, Allow, "using `Option.unwrap()`, which should at least get a better message using `expect()`"); @@ -144,7 +82,7 @@ impl LateLintPass for MethodsPass { && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &RESULT_PATH) { let result_type = cx.tcx.expr_ty(&inner_args[0]); if let Some(error_type) = get_error_type(cx, result_type) { - if self.has_debug_impl(error_type, cx) { + if has_debug_impl(error_type, cx) { span_lint(cx, OK_EXPECT, expr.span, "called `ok().expect()` on a Result \ value. You can call `expect` directly @@ -212,6 +150,27 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { None } +// This checks whether a given type is known to implement Debug. It's +// conservative, i.e. it should not return false positives, but will return +// false negatives. +fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { + let ty = walk_ptrs_ty(ty); + let debug = match cx.tcx.lang_items.debug_trait() { + Some(debug) => debug, + None => return false + }; + let debug_def = cx.tcx.lookup_trait_def(debug); + let mut debug_impl_exists = false; + debug_def.for_each_relevant_impl(cx.tcx, ty, |d| { + let self_ty = &cx.tcx.impl_trait_ref(d).and_then(|im| im.substs.self_ty()); + if let Some(self_ty) = *self_ty { + if !self_ty.flags.get().contains(ty::TypeFlags::HAS_PARAMS) { + debug_impl_exists = true; + } + } + }); + debug_impl_exists +} const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ("into_", &[ValueSelf]), diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index aeb79503504..6d543596cf5 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -54,7 +54,7 @@ fn main() { // the error type implements `Debug` let res2: Result<i32, MyError> = Ok(0); res2.ok().expect("oh noes!"); - // we're currently don't warn if the error type has a type parameter + // we currently don't warn if the error type has a type parameter // (but it would be nice if we did) let res3: Result<u32, MyErrorWithParam<u8>>= Ok(0); res3.ok().expect("whoof"); @@ -62,6 +62,8 @@ fn main() { res4.ok().expect("argh"); //~ERROR called `ok().expect()` let res5: io::Result<u32> = Ok(0); res5.ok().expect("oops"); //~ERROR called `ok().expect()` + let res6: Result<u32, &str> = Ok(0); + res6.ok().expect("meh"); //~ERROR called `ok().expect()` } struct MyError(()); // doesn't implement Debug -- cgit 1.4.1-3-g733a5 From a36707bffd41d5197cf7b081c7594b5663106586 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 19 Nov 2015 20:19:19 +0100 Subject: Appease clippy by not shadowing variables --- src/methods.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 858a5a3dca0..b8c6402544d 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -154,14 +154,14 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { // conservative, i.e. it should not return false positives, but will return // false negatives. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { - let ty = walk_ptrs_ty(ty); + let no_ref_ty = walk_ptrs_ty(ty); let debug = match cx.tcx.lang_items.debug_trait() { Some(debug) => debug, None => return false }; let debug_def = cx.tcx.lookup_trait_def(debug); let mut debug_impl_exists = false; - debug_def.for_each_relevant_impl(cx.tcx, ty, |d| { + debug_def.for_each_relevant_impl(cx.tcx, no_ref_ty, |d| { let self_ty = &cx.tcx.impl_trait_ref(d).and_then(|im| im.substs.self_ty()); if let Some(self_ty) = *self_ty { if !self_ty.flags.get().contains(ty::TypeFlags::HAS_PARAMS) { -- cgit 1.4.1-3-g733a5 From 1b41a4515e1aa71702550a933e801694efcc1f13 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 20 Nov 2015 16:21:14 +0530 Subject: Crates bump --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f9eceabfc85..3eb848fe51f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.23" +version = "0.0.24" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From d4cf288b385b9c58cfa0d4c97b3b548bc21b4923 Mon Sep 17 00:00:00 2001 From: John Quigley <jmquigs@gmail.com> Date: Fri, 20 Nov 2015 00:22:52 -0500 Subject: Add block_in_if lint, #434 --- README.md | 158 ++++++++++++++-------------- src/block_in_if_condition.rs | 91 ++++++++++++++++ src/lib.rs | 4 + tests/compile-fail/block_in_if_condition.rs | 64 +++++++++++ 4 files changed, 239 insertions(+), 78 deletions(-) create mode 100644 src/block_in_if_condition.rs create mode 100644 tests/compile-fail/block_in_if_condition.rs diff --git a/README.md b/README.md index b893c4e7a17..696836f417d 100644 --- a/README.md +++ b/README.md @@ -6,84 +6,86 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 74 lints included in this crate: - -name | default | meaning --------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) -[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected -[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do -[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases -[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` -[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block -[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque -[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) -[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead -[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type -[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields -[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect -[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file -[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator -[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do -[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` -[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value -[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` -[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op -[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. -[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) -[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) -[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference -[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 -[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 -[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types -[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop -[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator -[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN -[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing +There are 76 lints included in this crate: + +name | default | meaning +---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` +[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` +[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) +[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do +[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` +[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block +[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) +[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead +[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type +[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect +[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do +[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` +[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value +[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` +[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. +[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) +[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 +[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 +[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types +[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator +[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN +[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs new file mode 100644 index 00000000000..39196ed175f --- /dev/null +++ b/src/block_in_if_condition.rs @@ -0,0 +1,91 @@ +use rustc_front::hir::*; +use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; +use rustc_front::intravisit::{Visitor, walk_expr}; +use utils::*; + +declare_lint! { + pub BLOCK_IN_IF_CONDITION_EXPR, Warn, + "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" +} + +declare_lint! { + pub BLOCK_IN_IF_CONDITION_STMT, Warn, + "avoid complex blocks in conditions, instead move the block higher and bind it \ + with 'let'; e.g: `if { let x = true; x } ...`" +} + +#[derive(Copy,Clone)] +pub struct BlockInIfCondition; + +impl LintPass for BlockInIfCondition { + fn get_lints(&self) -> LintArray { + lint_array!(BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT) + } +} + +struct ExVisitor<'v> { + found_block: Option<&'v Expr> +} + +impl<'v> Visitor<'v> for ExVisitor<'v> { + fn visit_expr(&mut self, expr: &'v Expr) { + if let ExprClosure(_, _, ref block) = expr.node { + let complex = { + if !block.stmts.is_empty() { + true + } else { + if let Some(ref ex) = block.expr { + match ex.node { + ExprBlock(_) => true, + _ => false + } + } else { + false + } + } + }; + if complex { + self.found_block = Some(& expr); + return; + } + } + walk_expr(self, expr); + } +} + +const BRACED_EXPR_MESSAGE:&'static str = "omit braces around single expression condition"; +const COMPLEX_BLOCK_MESSAGE:&'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let'"; + +impl LateLintPass for BlockInIfCondition { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprIf(ref check, ref then, _) = expr.node { + if let ExprBlock(ref block) = check.node { + if block.stmts.is_empty() { + if let Some(ref ex) = block.expr { + // don't dig into the expression here, just suggest that they remove + // the block + + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_EXPR, check.span, + BRACED_EXPR_MESSAGE, + &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, ".."))); + } + } else { + // move block higher + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, check.span, + COMPLEX_BLOCK_MESSAGE, + &format!("try\nlet res = {};\nif res {} ... ", + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, ".."))); + } + } else { + let mut visitor = ExVisitor { found_block: None }; + walk_expr(&mut visitor, check); + if let Some(ref block) = visitor.found_block { + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, + COMPLEX_BLOCK_MESSAGE, ""); + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index afbf3d2a92c..9507b1d86f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ pub mod mut_reference; pub mod len_zero; pub mod attrs; pub mod collapsible_if; +pub mod block_in_if_condition; pub mod unicode; pub mod shadow; pub mod strings; @@ -81,6 +82,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box misc::CmpOwned); reg.register_late_lint_pass(box attrs::AttrPass); reg.register_late_lint_pass(box collapsible_if::CollapsibleIf); + reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition); reg.register_late_lint_pass(box misc::ModuloOne); reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); @@ -131,6 +133,8 @@ pub fn plugin_registrar(reg: &mut Registry) { attrs::INLINE_ALWAYS, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, + block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, + block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, eq_op::EQ_OP, eta_reduction::REDUNDANT_CLOSURE, diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs new file mode 100644 index 00000000000..c075d48297e --- /dev/null +++ b/tests/compile-fail/block_in_if_condition.rs @@ -0,0 +1,64 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(block_in_if_condition_expr)] +#![deny(block_in_if_condition_stmt)] +#![allow(unused)] + +fn condition_has_block() -> i32 { + + if { //~ERROR in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' + let x = 3; + x == 3 + } { + 6 + } else { + 10 + } +} + +fn condition_has_block_with_single_expression() -> i32 { + if { true } { //~ERROR omit braces around single expression condition + 6 + } else { + 10 + } +} + +fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val:T) -> bool { + pfn(val) +} + +fn pred_test() { + let v = 3; + let sky = "blue"; + // this is a sneaky case, where the block isn't directly in the condition, but is actually + // inside a closure that the condition is using. same principle applies. add some extra + // expressions to make sure linter isn't confused by them. + if v == 3 && sky == "blue" && predicate(|x| { let target = 3; x == target }, v) { //~ERROR in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' + + } + + if predicate(|x| { let target = 3; x == target }, v) { //~ERROR in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' + + } + +} + +fn condition_is_normal() -> i32 { + let x = 3; + if true && x == 3 { + 6 + } else { + 10 + } +} + +fn closure_without_block() { + if predicate(|x| x == 3, 6) { + + } +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From b40e80f039afb01fefca508e7f7c5d31fa280a6a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 23 Nov 2015 16:34:23 +0530 Subject: spurious newline --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index b8c6402544d..e40531a4d66 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -85,7 +85,7 @@ impl LateLintPass for MethodsPass { if has_debug_impl(error_type, cx) { span_lint(cx, OK_EXPECT, expr.span, "called `ok().expect()` on a Result \ - value. You can call `expect` directly + value. You can call `expect` directly \ on the `Result`"); } } -- cgit 1.4.1-3-g733a5 From a3e8091e875a34aa288f675f90c657fa0a86f0e6 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 25 Nov 2015 02:44:40 +0900 Subject: Dogfood match_ref_pats for `if let` --- src/approx_const.rs | 2 +- src/attrs.rs | 2 +- src/bit_mask.rs | 2 +- src/len_zero.rs | 2 +- src/lifetimes.rs | 2 +- src/misc.rs | 8 ++++---- src/mutex_atomic.rs | 2 +- src/ptr_arg.rs | 6 +++--- src/ranges.rs | 4 ++-- src/shadow.rs | 6 +++--- src/strings.rs | 6 +++--- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 89cb5204a8c..9d1d51444fa 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -44,7 +44,7 @@ impl LintPass for ApproxConstant { impl LateLintPass for ApproxConstant { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let &ExprLit(ref lit) = &e.node { + if let ExprLit(ref lit) = e.node { check_lit(cx, lit, e); } } diff --git a/src/attrs.rs b/src/attrs.rs index a0101688668..f4a5b4c1517 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -42,7 +42,7 @@ impl LateLintPass for AttrPass { } fn is_relevant_item(item: &Item) -> bool { - if let &ItemFn(_, _, _, _, _, ref block) = &item.node { + if let ItemFn(_, _, _, _, _, ref block) = item.node { is_relevant_block(block) } else { false } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index c8530b92d48..ab73086d07b 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -182,7 +182,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { - if let &LitInt(value, _) = &lit_ptr.node { + if let LitInt(value, _) = lit_ptr.node { Option::Some(value) //TODO: Handle sign } else { Option::None } } diff --git a/src/len_zero.rs b/src/len_zero.rs index 25645ea8742..9ac4ab1e0e0 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -125,7 +125,7 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name, fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// get a ImplOrTraitItem and return true if it matches is_empty(self) fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { - if let &MethodTraitItemId(def_id) = id { + if let MethodTraitItemId(def_id) = *id { if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { method.name.as_str() == "is_empty" diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 9b47a4d830f..acc7b014052 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -168,7 +168,7 @@ impl <'v, 't> RefVisitor<'v, 't> { } fn record(&mut self, lifetime: &Option<Lifetime>) { - if let &Some(ref lt) = lifetime { + if let Some(ref lt) = *lifetime { if lt.name.as_str() == "'static" { self.lts.push(Static); } else { diff --git a/src/misc.rs b/src/misc.rs index 9a8ce74e997..9df751d49b7 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -84,10 +84,10 @@ impl LateLintPass for CmpNan { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { - if let &ExprPath(_, ref path) = &left.node { + if let ExprPath(_, ref path) = left.node { check_nan(cx, path, expr.span); } - if let &ExprPath(_, ref path) = &right.node { + if let ExprPath(_, ref path) = right.node { check_nan(cx, path, expr.span); } } @@ -189,7 +189,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o } } ExprCall(ref path, ref v) if v.len() == 1 => { - if let &ExprPath(None, ref path) = &path.node { + if let ExprPath(None, ref path) = path.node { if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { snippet(cx, v[0].span, "..") @@ -235,7 +235,7 @@ impl LintPass for ModuloOne { impl LateLintPass for ModuloOne { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, _, ref right) = expr.node { - if let &Spanned {node: BinOp_::BiRem, ..} = cmp { + if let Spanned {node: BinOp_::BiRem, ..} = *cmp { if is_integer_literal(right, 1) { cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 9c10a062419..e6d1fc8a888 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -34,7 +34,7 @@ pub struct MutexAtomic; impl LateLintPass for MutexAtomic { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { let ty = cx.tcx.expr_ty(expr); - if let &ty::TyStruct(_, subst) = &ty.sty { + if let ty::TyStruct(_, subst) = ty.sty { if match_type(cx, ty, &MUTEX_PATH) { let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; if let Some(atomic_name) = get_atomic_name(mutex_param) { diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 78be2af1217..6946d0549d0 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -28,13 +28,13 @@ impl LintPass for PtrArg { impl LateLintPass for PtrArg { fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { + if let ItemFn(ref decl, _, _, _, _, _) = item.node { check_fn(cx, decl); } } fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let &ImplItemKind::Method(ref sig, _) = &item.node { + if let ImplItemKind::Method(ref sig, _) = item.node { if let Some(Node::NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { if let ItemImpl(_, _, _, Some(_), _, _) = it.node { return; // ignore trait impls @@ -45,7 +45,7 @@ impl LateLintPass for PtrArg { } fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - if let &MethodTraitItem(ref sig, _) = &item.node { + if let MethodTraitItem(ref sig, _) = item.node { check_fn(cx, &sig.decl); } } diff --git a/src/ranges.rs b/src/ranges.rs index 39ff7d3cd31..31bb985230d 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -40,10 +40,10 @@ impl LateLintPass for StepByZero { if_let_chain! { [ // .iter() call - let &ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = iter, + let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, iter_name.as_str() == "iter", // range expression in .zip() call: 0..x.len() - let &ExprRange(Some(ref from), Some(ref to)) = zip_arg, + let ExprRange(Some(ref from), Some(ref to)) = *zip_arg, is_integer_literal(from, 0), // .len() call let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = to.node, diff --git a/src/shadow.rs b/src/shadow.rs index 3f72722333b..5fb27f75c3c 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -63,8 +63,8 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; - if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - if let &Some(ref o) = init { + if let Some(ref t) = *ty { check_ty(cx, t, bindings) } + if let Some(ref o) = *init { check_expr(cx, o, bindings); check_pat(cx, pat, &Some(o), span, bindings); } else { @@ -210,7 +210,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { ExprIf(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); check_block(cx, then, bindings); - if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); } + if let Some(ref o) = *otherwise { check_expr(cx, o, bindings); } } ExprWhile(ref cond, ref block, _) => { check_expr(cx, cond, bindings); diff --git a/src/strings.rs b/src/strings.rs index 08274657538..3c34e188d11 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -34,14 +34,14 @@ impl LintPass for StringAdd { impl LateLintPass for StringAdd { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node { + if let ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = e.node { if is_string(cx, left) { if let Allow = cx.current_level(STRING_ADD_ASSIGN) { // the string_add_assign is allow, so no duplicates } else { let parent = get_parent_expr(cx, e); if let Some(ref p) = parent { - if let &ExprAssign(ref target, _) = &p.node { + if let ExprAssign(ref target, _) = p.node { // avoid duplicate matches if is_exp_equal(cx, target, left) { return; } } @@ -51,7 +51,7 @@ impl LateLintPass for StringAdd { "you added something to a string. \ Consider using `String::push_str()` instead") } - } else if let &ExprAssign(ref target, ref src) = &e.node { + } else if let ExprAssign(ref target, ref src) = e.node { if is_string(cx, target) && is_add(cx, src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ -- cgit 1.4.1-3-g733a5 From 746991572fac33ba29c4d1a83574d3b7c2776998 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 25 Nov 2015 02:47:17 +0900 Subject: Extend match_ref_pats to desugared matches --- src/matches.rs | 49 ++++++++++++++++++++++++++++++------------- tests/compile-fail/matches.rs | 16 +++++++++++--- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index eaa3e0026a3..55eb4fe381b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -25,9 +25,8 @@ impl LintPass for MatchPass { impl LateLintPass for MatchPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_external_macro(cx, expr.span) { return; } if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { - if in_external_macro(cx, expr.span) { return; } - // check preconditions for SINGLE_MATCH // only two arms if arms.len() == 2 && @@ -53,19 +52,6 @@ impl LateLintPass for MatchPass { expr_block(cx, &arms[0].body, None, ".."))); } - // check preconditions for MATCH_REF_PATS - if has_only_ref_pats(arms) { - if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "you don't need to add `&` to both the expression to match \ - and the patterns: use `match {} {{ ...`", snippet(cx, inner.span, ".."))); - } else { - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "instead of prefixing all patterns with `&`, you can dereference the \ - expression to match: `match *{} {{ ...`", snippet(cx, ex.span, ".."))); - } - } - // check preconditions for MATCH_BOOL // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { @@ -123,6 +109,22 @@ impl LateLintPass for MatchPass { } } } + if let ExprMatch(ref ex, ref arms, source) = expr.node { + // check preconditions for MATCH_REF_PATS + if has_only_ref_pats(arms) { + if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + let template = match_template(source, "", &snippet(cx, inner.span, "..")); + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "you don't need to add `&` to both the expression \ + and the patterns: use `{}`", template)); + } else { + let template = match_template(source, "*", &snippet(cx, ex.span, "..")); + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "instead of prefixing all patterns with `&`, you can dereference the \ + expression: `{}`", template)); + } + } + } } } @@ -143,3 +145,20 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { // look for Some(v) where there's at least one true element mapped.map_or(false, |v| v.iter().any(|el| *el)) } + +fn match_template(source: MatchSource, op: &str, expr: &str) -> String { + match source { + MatchSource::Normal => { + format!("match {}{} {{ ...", op, expr) + } + MatchSource::IfLetDesugar { .. } => { + format!("if let ... = {}{} {{", op, expr) + } + MatchSource::WhileLetDesugar => { + format!("while let ... = {}{} {{", op, expr) + } + MatchSource::ForLoopDesugar => { + panic!("for loop desugared to match with &-patterns!") + } + } +} diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 20d7552d77a..ea3a48a94f5 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -78,7 +78,7 @@ fn match_bool() { fn ref_pats() { { let v = &Some(0); - match v { //~ERROR instead of prefixing all patterns with `&` + match v { //~ERROR dereference the expression: `match *v { ...` &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -88,13 +88,13 @@ fn ref_pats() { } } let tup =& (1, 2); - match tup { //~ERROR instead of prefixing all patterns with `&` + match tup { //~ERROR dereference the expression: `match *tup { ...` &(v, 1) => println!("{}", v), _ => println!("none"), } // special case: using & both in expr and pats let w = Some(0); - match &w { //~ERROR you don't need to add `&` to both + match &w { //~ERROR use `match w { ...` &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -103,6 +103,16 @@ fn ref_pats() { match w { _ => println!("none"), } + + let a = &Some(0); + if let &None = a { //~ERROR dereference the expression: `if let ... = *a {` + println!("none"); + } + + let b = Some(0); + if let &None = &b { //~ERROR use `if let ... = b {` + println!("none"); + } } fn main() { -- cgit 1.4.1-3-g733a5 From b1a0abe404740e1425a8586c7519114578d20372 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 25 Nov 2015 13:57:50 +0900 Subject: Don't panic --- src/matches.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 55eb4fe381b..ec118052fbc 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,6 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; use syntax::ast::Lit_::LitBool; +use syntax::codemap::Span; use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; @@ -113,12 +114,12 @@ impl LateLintPass for MatchPass { // check preconditions for MATCH_REF_PATS if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - let template = match_template(source, "", &snippet(cx, inner.span, "..")); + let template = match_template(cx, expr.span, source, "", inner); span_lint(cx, MATCH_REF_PATS, expr.span, &format!( "you don't need to add `&` to both the expression \ and the patterns: use `{}`", template)); } else { - let template = match_template(source, "*", &snippet(cx, ex.span, "..")); + let template = match_template(cx, expr.span, source, "*", ex); span_lint(cx, MATCH_REF_PATS, expr.span, &format!( "instead of prefixing all patterns with `&`, you can dereference the \ expression: `{}`", template)); @@ -146,19 +147,24 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { mapped.map_or(false, |v| v.iter().any(|el| *el)) } -fn match_template(source: MatchSource, op: &str, expr: &str) -> String { +fn match_template(cx: &LateContext, + span: Span, + source: MatchSource, + op: &str, + expr: &Expr) -> String { + let expr_snippet = snippet(cx, expr.span, ".."); match source { MatchSource::Normal => { - format!("match {}{} {{ ...", op, expr) + format!("match {}{} {{ ...", op, expr_snippet) } MatchSource::IfLetDesugar { .. } => { - format!("if let ... = {}{} {{", op, expr) + format!("if let ... = {}{} {{", op, expr_snippet) } MatchSource::WhileLetDesugar => { - format!("while let ... = {}{} {{", op, expr) + format!("while let ... = {}{} {{", op, expr_snippet) } MatchSource::ForLoopDesugar => { - panic!("for loop desugared to match with &-patterns!") + cx.sess().span_bug(span, "for loop desugared to match with &-patterns!") } } } -- cgit 1.4.1-3-g733a5 From cf540064492a724bcaa155a2a484eadb26e3e66c Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 25 Nov 2015 16:28:29 +0100 Subject: Fixes to build with current rust nightly --- src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 1750495d1f3..791bf587bb5 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -195,9 +195,9 @@ impl fmt::Display for Constant { let (sign, suffix) = match *ity { LitIntType::SignedIntLit(ref sity, ref sign) => (if let Sign::Minus = *sign { "-" } else { "" }, - ast_util::int_ty_to_string(*sity, None)), + ast_util::int_ty_to_string(*sity)), LitIntType::UnsignedIntLit(ref uity) => - ("", ast_util::uint_ty_to_string(*uity, None)), + ("", ast_util::uint_ty_to_string(*uity)), LitIntType::UnsuffixedIntLit(ref sign) => (if let Sign::Minus = *sign { "-" } else { "" }, "".into()), -- cgit 1.4.1-3-g733a5 From 94dc2f567ab7cd84a1d200749ca376eb7a5d96ec Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 26 Nov 2015 00:09:01 +0100 Subject: Suppress explicit_counter_loop lint if loop variable is used after the loop --- src/loops.rs | 25 +++++++++++++++++-------- tests/compile-fail/for_loop.rs | 9 ++++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 92dff3a7d93..cfde1741715 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -150,7 +150,8 @@ impl LateLintPass for LoopsPass { for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(), state: VarState::IncrOnce, name: None, - depth: 0, done: false }; + depth: 0, + past_loop: false }; walk_block(&mut visitor2, block); if visitor2.state == VarState::Warn { @@ -502,7 +503,7 @@ struct InitializeVisitor<'v, 't: 'v> { state: VarState, name: Option<Name>, depth: u32, // depth of conditional expressions - done: bool + past_loop: bool } impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { @@ -530,12 +531,16 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { } fn visit_expr(&mut self, expr: &'v Expr) { - if self.state == VarState::DontWarn || expr == self.end_expr { - self.done = true; + if self.state == VarState::DontWarn { + return; + } + if expr == self.end_expr { + self.past_loop = true; + return; } // No need to visit expressions before the variable is - // declared or after we've rejected it. - if self.state == VarState::IncrOnce || self.done { + // declared + if self.state == VarState::IncrOnce { return; } @@ -556,11 +561,15 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { _ => () } } + + if self.past_loop { + self.state = VarState::DontWarn; + return; + } } // If there are other loops between the declaration and the target loop, give up - else if is_loop(expr) { + else if !self.past_loop && is_loop(expr) { self.state = VarState::DontWarn; - self.done = true; return; } // Keep track of whether we're inside a conditional expression diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 02c8cc56083..3d19bd66094 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -132,11 +132,6 @@ fn main() { _index = 0; for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter - let mut _index; - _index = 0; - for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter - for _v in &vec { _index += 1 } // But this does not warn - // Potential false positives let mut _index = 0; _index = 1; @@ -187,4 +182,8 @@ fn main() { let mut _index = 0; { let mut _x = &mut _index; } for _v in &vec { _index += 1 } + + let mut index = 0; + for _v in &vec { index += 1 } + println!("index: {}", index); } -- cgit 1.4.1-3-g733a5 From 5b6c2b7938fdde68fd262b5265df22ee0ace88ae Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 26 Nov 2015 04:57:23 +0530 Subject: Publish 0.0.25 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3eb848fe51f..353f4c78534 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.24" +version = "0.0.25" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 443e4556c2fec853cea4fb93f1c3e309ff5c98a4 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sun, 22 Nov 2015 21:48:19 -0800 Subject: Add lints suggesting map_or() and map_or_else() In accordance with the latter lint, replace map().unwrap_or_else() in src/mut_mut.rs with map_or_else() --- README.md | 4 ++- src/lib.rs | 2 ++ src/methods.rs | 72 +++++++++++++++++++++++++++++++++++++++++-- src/mut_mut.rs | 23 ++++++++------ tests/compile-fail/methods.rs | 49 +++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ae19f6ff9d7..0a10c849ca7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 77 lints included in this crate: +There are 79 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -53,6 +53,8 @@ name [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result +[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`) +[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`) [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively diff --git a/src/lib.rs b/src/lib.rs index 3664803d022..12cb14f7355 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,6 +156,8 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::OK_EXPECT, + methods::OPTION_MAP_UNWRAP_OR, + methods::OPTION_MAP_UNWRAP_OR_ELSE, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, diff --git a/src/methods.rs b/src/methods.rs index b8c6402544d..f1b610c6211 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -5,7 +5,7 @@ use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; -use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth, +use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, walk_ptrs_ty_depth, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; @@ -34,12 +34,18 @@ declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, declare_lint!(pub OK_EXPECT, Warn, "using `ok().expect()`, which gives worse error messages than \ calling `expect` directly on the Result"); - +declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, + "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ + `map_or(a, f)`)"); +declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, + "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `map_or_else(g, f)`)"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, - SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, OK_EXPECT) + SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, OK_EXPECT, OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE) } } @@ -92,6 +98,66 @@ impl LateLintPass for MethodsPass { } } } + // check Option.map(_).unwrap_or(_) + else if name.node.as_str() == "unwrap_or" { + if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + if inner_name.node.as_str() == "map" + && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { + // lint message + let msg = + "called `map(f).unwrap_or(a)` on an Option value. This can be done \ + more directly by calling `map_or(a, f)` instead"; + // get args to map() and unwrap_or() + let map_arg = snippet(cx, inner_args[1].span, ".."); + let unwrap_arg = snippet(cx, args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or() have the same span + let multiline = map_arg.lines().count() > 1 + || unwrap_arg.lines().count() > 1; + let same_span = inner_args[1].span.expn_id == args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint( + cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, + &format!("replace this with map_or({1}, {0})", + map_arg, unwrap_arg) + ); + } + else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); + }; + } + } + } + // check Option.map(_).unwrap_or_else(_) + else if name.node.as_str() == "unwrap_or_else" { + if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + if inner_name.node.as_str() == "map" + && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { + // lint message + let msg = + "called `map(f).unwrap_or_else(g)` on an Option value. This can be \ + done more directly by calling `map_or_else(g, f)` instead"; + // get args to map() and unwrap_or_else() + let map_arg = snippet(cx, inner_args[1].span, ".."); + let unwrap_arg = snippet(cx, args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or_else() have the same span + let multiline = map_arg.lines().count() > 1 + || unwrap_arg.lines().count() > 1; + let same_span = inner_args[1].span.expn_id == args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint( + cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg, expr.span, + &format!("replace this with map_or_else({1}, {0})", + map_arg, unwrap_arg) + ); + } + else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); + }; + } + } + } } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index a92338165dd..09ba7d781a2 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -39,17 +39,20 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { } unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map(|_| { - span_lint(cx, MUT_MUT, expr.span, - "generally you want to avoid `&mut &mut _` if possible") - }).unwrap_or_else(|| { - if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = - cx.tcx.expr_ty(e).sty { - span_lint(cx, MUT_MUT, expr.span, - "this expression mutably borrows a mutable reference. \ - Consider reborrowing") + unwrap_addr(e).map_or_else( + || { + if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = + cx.tcx.expr_ty(e).sty { + span_lint(cx, MUT_MUT, expr.span, + "this expression mutably borrows a mutable reference. \ + Consider reborrowing") } - }) + }, + |_| { + span_lint(cx, MUT_MUT, expr.span, + "generally you want to avoid `&mut &mut _` if possible") + } + ) }) } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 6d543596cf5..9078a78d6fe 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -34,6 +34,55 @@ impl Mul<T> for T { fn mul(self, other: T) -> T { self } // no error, obviously } +/// Utility macro to test linting behavior in `option_methods()` +/// The lints included in `option_methods()` should not lint if the call to map is partially +/// within a macro +macro_rules! opt_map { + ($opt:expr, $map:expr) => {($opt).map($map)}; +} + +/// Checks implementation of the following lints: +/// OPTION_MAP_UNWRAP_OR +/// OPTION_MAP_UNWRAP_OR_ELSE +fn option_methods() { + let opt = Some(1); + + // Check OPTION_MAP_UNWRAP_OR + // single line case + let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or(a)` + //~| NOTE replace this + .unwrap_or(0); // should lint even though this call is on a separate line + // multi line cases + let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or(a)` + x + 1 + } + ).unwrap_or(0); + let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or(a)` + .unwrap_or({ + 0 + }); + // macro case + let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint + + // Check OPTION_MAP_UNWRAP_OR_ELSE + // single line case + let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or_else(g)` + //~| NOTE replace this + .unwrap_or_else(|| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or_else(g)` + x + 1 + } + ).unwrap_or_else(|| 0); + let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or_else(g)` + .unwrap_or_else(|| + 0 + ); + // macro case + let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); // should not lint + +} + fn main() { use std::io; -- cgit 1.4.1-3-g733a5 From 7d583dab80d7cadaa8283e59e7e5ce9f657b8a20 Mon Sep 17 00:00:00 2001 From: Hobofan <goisser94@gmail.com> Date: Fri, 27 Nov 2015 14:47:00 +0100 Subject: fix for latest nightly Fixes breakage introduced by rust-lang/rust#30043 --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 12cb14f7355..7f3f9009411 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,9 @@ extern crate collections; // for unicode nfc normalization extern crate unicode_normalization; -use rustc::plugin::Registry; +extern crate rustc_plugin; + +use rustc_plugin::Registry; #[macro_use] pub mod utils; -- cgit 1.4.1-3-g733a5 From 2ce2bc3345c9309404efa6b67bce402fa9583800 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 30 Nov 2015 15:52:17 +0530 Subject: Bump to 26 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 353f4c78534..b69b49f208c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.25" +version = "0.0.26" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From ba59ed05e334d70b50fca18befa1790f509dbee1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 30 Nov 2015 23:16:28 +0530 Subject: Rust upgrade to rustc 1.6.0-nightly (52d95e644 2015-11-30) --- src/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matches.rs b/src/matches.rs index ec118052fbc..b6a7fc7fa5b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -140,7 +140,7 @@ fn is_unit_expr(expr: &Expr) -> bool { fn has_only_ref_pats(arms: &[Arm]) -> bool { let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node { PatRegion(..) => Some(true), // &-patterns - PatWild(..) => Some(false), // an "anything" wildcard is also fine + PatWild => Some(false), // an "anything" wildcard is also fine _ => None, // any other pattern is not fine }).collect::<Option<Vec<bool>>>(); // look for Some(v) where there's at least one true element -- cgit 1.4.1-3-g733a5 From b45745e9052f46eece3c0f8688ff5849ffd3a464 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 30 Nov 2015 23:17:14 +0530 Subject: bump 27 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b69b49f208c..b9ade2ac28f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.26" +version = "0.0.27" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 26f539eaa379675b7736a652705e1fdde1c7bc9f Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Sat, 28 Nov 2015 00:47:24 +0900 Subject: Remove unused qualifications --- src/bit_mask.rs | 8 ++++---- src/mut_mut.rs | 8 ++++---- src/mut_reference.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index ab73086d07b..bee99b0f783 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -183,8 +183,8 @@ fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { if let LitInt(value, _) = lit_ptr.node { - Option::Some(value) //TODO: Handle sign - } else { Option::None } + Some(value) //TODO: Handle sign + } else { None } } ExprPath(_, _) => { // Important to let the borrow expire before the const lookup to avoid double @@ -195,8 +195,8 @@ fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { _ => None } } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) .and_then(|l| fetch_int_literal(cx, l)), - _ => Option::None + _ => None } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 09ba7d781a2..c361ab24831 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -33,8 +33,8 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { fn unwrap_addr(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprAddrOf(MutMutable, ref e) => Option::Some(e), - _ => Option::None + ExprAddrOf(MutMutable, ref e) => Some(e), + _ => None } } @@ -58,7 +58,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { fn unwrap_mut(ty: &Ty) -> Option<&Ty> { match ty.node { - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - _ => Option::None + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Some(pty), + _ => None } } diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 86c272affb7..e9601e8650f 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -60,7 +60,7 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty match parameter.sty { TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { - if let Expr_::ExprAddrOf(MutMutable, _) = argument.node { + if let ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("The function/method \"{}\" \ doesn't need a mutable reference", -- cgit 1.4.1-3-g733a5 From 617c820e6b0edebacdf5295cfa8333af023f98e1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 18 Nov 2015 12:35:18 +0100 Subject: compute cyclomatic complexity (adjusted to not punish Rust's `match`) --- .gitignore | 3 + README.md | 3 +- src/cyclomatic_complexity.rs | 105 +++++++++++++ src/lib.rs | 5 +- src/lifetimes.rs | 19 ++- src/loops.rs | 224 ++++++++++++++-------------- src/matches.rs | 2 +- src/utils.rs | 66 +++++++- tests/compile-fail/cyclomatic_complexity.rs | 181 ++++++++++++++++++++++ tests/compile-fail/for_loop.rs | 2 +- tests/compile-fail/while_loop.rs | 2 +- 11 files changed, 485 insertions(+), 127 deletions(-) create mode 100644 src/cyclomatic_complexity.rs create mode 100644 tests/compile-fail/cyclomatic_complexity.rs diff --git a/.gitignore b/.gitignore index ac98a7d842f..acb3c020fe7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ # We don't pin yet Cargo.lock + +# Generated by dogfood +/target_recur/ diff --git a/README.md b/README.md index 0a10c849ca7..206d86ec1ee 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 79 lints included in this crate: +There are 80 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -22,6 +22,7 @@ name [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs new file mode 100644 index 00000000000..678ebe866cb --- /dev/null +++ b/src/cyclomatic_complexity.rs @@ -0,0 +1,105 @@ +//! calculate cyclomatic complexity and warn about overly complex functions + +use rustc::lint::*; +use rustc_front::hir::*; +use rustc::middle::cfg::CFG; +use syntax::codemap::Span; +use syntax::attr::*; +use syntax::ast::Attribute; +use rustc_front::intravisit::{Visitor, walk_expr}; + +use utils::{in_macro, LimitStack}; + +declare_lint! { pub CYCLOMATIC_COMPLEXITY, Warn, + "finds functions that should be split up into multiple functions" } + +pub struct CyclomaticComplexity { + limit: LimitStack, +} + +impl CyclomaticComplexity { + pub fn new(limit: u64) -> Self { + CyclomaticComplexity { + limit: LimitStack::new(limit), + } + } +} + +impl LintPass for CyclomaticComplexity { + fn get_lints(&self) -> LintArray { + lint_array!(CYCLOMATIC_COMPLEXITY) + } +} + +impl CyclomaticComplexity { + fn check(&mut self, cx: &LateContext, block: &Block, span: Span) { + if in_macro(cx, span) { return; } + let cfg = CFG::new(cx.tcx, block); + let n = cfg.graph.len_nodes() as u64; + let e = cfg.graph.len_edges() as u64; + let cc = e + 2 - n; + let mut arm_counter = MatchArmCounter(0); + arm_counter.visit_block(block); + let mut narms = arm_counter.0; + if narms > 0 { + narms = narms - 1; + } + if cc < narms { + println!("cc = {}, arms = {}", cc, narms); + println!("{:?}", block); + println!("{:?}", span); + panic!("cc = {}, arms = {}", cc, narms); + } + let rust_cc = cc - narms; + if rust_cc > self.limit.limit() { + cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, + &format!("The function has a cyclomatic complexity of {}.", rust_cc), + "You could split it up into multiple smaller functions"); + } + } +} + +impl LateLintPass for CyclomaticComplexity { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemFn(_, _, _, _, _, ref block) = item.node { + self.check(cx, block, item.span); + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + if let ImplItemKind::Method(_, ref block) = item.node { + self.check(cx, block, item.span); + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + if let MethodTraitItem(_, Some(ref block)) = item.node { + self.check(cx, block, item.span); + } + } + + fn enter_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { + self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + } + fn exit_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { + self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + } +} + +struct MatchArmCounter(u64); + +impl<'a> Visitor<'a> for MatchArmCounter { + fn visit_expr(&mut self, e: &'a Expr) { + match e.node { + ExprMatch(_, ref arms, _) => { + walk_expr(self, e); + let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); + if arms_n > 0 { + self.0 += arms_n - 1; + } + }, + ExprClosure(..) => {}, + _ => walk_expr(self, e), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 7f3f9009411..33ae07b7ad8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, core, collections)] -#![feature(num_bits_bytes)] +#![feature(num_bits_bytes, iter_arith)] #![allow(unknown_lints)] #[macro_use] @@ -59,6 +59,7 @@ pub mod needless_update; pub mod no_effect; pub mod temporary_assignment; pub mod transmute; +pub mod cyclomatic_complexity; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -110,6 +111,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); reg.register_late_lint_pass(box transmute::UselessTransmute); + reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -138,6 +140,7 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, + cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, eq_op::EQ_OP, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, diff --git a/src/lifetimes.rs b/src/lifetimes.rs index acc7b014052..97eb7fa67a3 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -108,7 +108,7 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> // no input lifetimes? easy case! if input_lts.is_empty() { - return false; + false } else if output_lts.is_empty() { // no output lifetimes, check distinctness of input lifetimes @@ -117,9 +117,7 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> return false; } // we have no output reference, so we only need all distinct lifetimes - if input_lts.len() == unique_lifetimes(&input_lts) { - return true; - } + input_lts.len() == unique_lifetimes(&input_lts) } else { // we have output references, so we need one input reference, // and all output lifetimes must be the same @@ -128,15 +126,16 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> } if input_lts.len() == 1 { match (&input_lts[0], &output_lts[0]) { - (&Named(n1), &Named(n2)) if n1 == n2 => { return true; } - (&Named(_), &Unnamed) => { return true; } - (&Unnamed, &Named(_)) => { return true; } - _ => { } // already elided, different named lifetimes - // or something static going on + (&Named(n1), &Named(n2)) if n1 == n2 => true, + (&Named(_), &Unnamed) => true, + (&Unnamed, &Named(_)) => true, + _ => false // already elided, different named lifetimes + // or something static going on } + } else { + false } } - false } fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { diff --git a/src/loops.rs b/src/loops.rs index cfde1741715..393c92b16ef 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -56,116 +56,7 @@ impl LintPass for LoopsPass { impl LateLintPass for LoopsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) { - // check for looping over a range and then indexing a sequence with it - // -> the iteratee must be a range literal - if let ExprRange(Some(ref l), _) = arg.node { - // Range should start with `0` - if let ExprLit(ref lit) = l.node { - if let LitInt(0, _) = lit.node { - - // the var must be a single name - if let PatIdent(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { cx: cx, var: ident.node.name, - indexed: HashSet::new(), nonindex: false }; - walk_expr(&mut visitor, body); - // linting condition: we only indexed one variable - if visitor.indexed.len() == 1 { - let indexed = visitor.indexed.into_iter().next().expect( - "Len was nonzero, but no contents found"); - if visitor.nonindex { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is used to index `{}`. Consider using \ - `for ({}, item) in {}.iter().enumerate()` or similar iterators", - ident.node.name, indexed, ident.node.name, indexed)); - } else { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in &{}` or similar iterators", - ident.node.name, indexed, indexed)); - } - } - } - } - } - } - - // if this for loop is iterating over a two-sided range... - if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { - // ...and both sides are compile-time constant integers... - if let Some(start_idx @ Constant::ConstantInt(..)) = constant_simple(start_expr) { - if let Some(stop_idx @ Constant::ConstantInt(..)) = constant_simple(stop_expr) { - // ...and the start index is greater than the stop index, - // this loop will never run. This is often confusing for developers - // who think that this will iterate from the larger value to the - // smaller value. - if start_idx > stop_idx { - span_help_and_lint(cx, REVERSE_RANGE_LOOP, expr.span, - "this range is empty so this for loop will never run", - &format!("Consider using `({}..{}).rev()` if you are attempting to \ - iterate over this range in reverse", stop_idx, start_idx)); - } else if start_idx == stop_idx { - // if they are equal, it's also problematic - this loop - // will never run. - span_lint(cx, REVERSE_RANGE_LOOP, expr.span, - "this range is empty so this for loop will never run"); - } - } - } - } - - if let ExprMethodCall(ref method, _, ref args) = arg.node { - // just the receiver, no arguments - if args.len() == 1 { - let method_name = method.node; - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { - if is_ref_iterable_type(cx, &args[0]) { - let object = snippet(cx, args[0].span, "_"); - span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( - "it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", - if method_name.as_str() == "iter_mut" { "mut " } else { "" }, - object, object, method_name)); - } - } - // check for looping over Iterator::next() which is not what you want - else if method_name.as_str() == "next" && - match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { - span_lint(cx, ITER_NEXT_LOOP, expr.span, - "you are iterating over `Iterator::next()` which is an Option; \ - this will compile but is probably not what you want"); - } - } - } - - // Look for variables that are incremented once per loop iteration. - let mut visitor = IncrementVisitor { cx: cx, states: HashMap::new(), depth: 0, done: false }; - walk_expr(&mut visitor, body); - - // For each candidate, check the parent block to see if - // it's initialized to zero at the start of the loop. - let map = &cx.tcx.map; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id) ); - if let Some(parent_id) = parent_scope { - if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) { - let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(), - state: VarState::IncrOnce, name: None, - depth: 0, - past_loop: false }; - walk_block(&mut visitor2, block); - - if visitor2.state == VarState::Warn { - if let Some(name) = visitor2.name { - span_lint(cx, EXPLICIT_COUNTER_LOOP, expr.span, - &format!("the variable `{0}` is used as a loop counter. Consider \ - using `for ({0}, item) in {1}.enumerate()` \ - or similar iterators", - name, snippet(cx, arg.span, "_"))); - } - } - } - } - } + check_for_loop(cx, pat, arg, body, expr); } // check for `loop { if let {} else break }` that could be `while let` // (also matches an explicit "match" instead of "if let") @@ -271,6 +162,119 @@ impl LateLintPass for LoopsPass { } } +fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + // check for looping over a range and then indexing a sequence with it + // -> the iteratee must be a range literal + if let ExprRange(Some(ref l), _) = arg.node { + // Range should start with `0` + if let ExprLit(ref lit) = l.node { + if let LitInt(0, _) = lit.node { + + // the var must be a single name + if let PatIdent(_, ref ident, _) = pat.node { + let mut visitor = VarVisitor { cx: cx, var: ident.node.name, + indexed: HashSet::new(), nonindex: false }; + walk_expr(&mut visitor, body); + // linting condition: we only indexed one variable + if visitor.indexed.len() == 1 { + let indexed = visitor.indexed.into_iter().next().expect( + "Len was nonzero, but no contents found"); + if visitor.nonindex { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is used to index `{}`. Consider using \ + `for ({}, item) in {}.iter().enumerate()` or similar iterators", + ident.node.name, indexed, ident.node.name, indexed)); + } else { + span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( + "the loop variable `{}` is only used to index `{}`. \ + Consider using `for item in &{}` or similar iterators", + ident.node.name, indexed, indexed)); + } + } + } + } + } + } + + // if this for loop is iterating over a two-sided range... + if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { + // ...and both sides are compile-time constant integers... + if let Some(start_idx @ Constant::ConstantInt(..)) = constant_simple(start_expr) { + if let Some(stop_idx @ Constant::ConstantInt(..)) = constant_simple(stop_expr) { + // ...and the start index is greater than the stop index, + // this loop will never run. This is often confusing for developers + // who think that this will iterate from the larger value to the + // smaller value. + if start_idx > stop_idx { + span_help_and_lint(cx, REVERSE_RANGE_LOOP, expr.span, + "this range is empty so this for loop will never run", + &format!("Consider using `({}..{}).rev()` if you are attempting to \ + iterate over this range in reverse", stop_idx, start_idx)); + } else if start_idx == stop_idx { + // if they are equal, it's also problematic - this loop + // will never run. + span_lint(cx, REVERSE_RANGE_LOOP, expr.span, + "this range is empty so this for loop will never run"); + } + } + } + } + + if let ExprMethodCall(ref method, _, ref args) = arg.node { + // just the receiver, no arguments + if args.len() == 1 { + let method_name = method.node; + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x + if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { + if is_ref_iterable_type(cx, &args[0]) { + let object = snippet(cx, args[0].span, "_"); + span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( + "it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", + if method_name.as_str() == "iter_mut" { "mut " } else { "" }, + object, object, method_name)); + } + } + // check for looping over Iterator::next() which is not what you want + else if method_name.as_str() == "next" && + match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { + span_lint(cx, ITER_NEXT_LOOP, expr.span, + "you are iterating over `Iterator::next()` which is an Option; \ + this will compile but is probably not what you want"); + } + } + } + + // Look for variables that are incremented once per loop iteration. + let mut visitor = IncrementVisitor { cx: cx, states: HashMap::new(), depth: 0, done: false }; + walk_expr(&mut visitor, body); + + // For each candidate, check the parent block to see if + // it's initialized to zero at the start of the loop. + let map = &cx.tcx.map; + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id) ); + if let Some(parent_id) = parent_scope { + if let NodeBlock(block) = map.get(parent_id) { + for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) { + let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(), + state: VarState::IncrOnce, name: None, + depth: 0, + past_loop: false }; + walk_block(&mut visitor2, block); + + if visitor2.state == VarState::Warn { + if let Some(name) = visitor2.name { + span_lint(cx, EXPLICIT_COUNTER_LOOP, expr.span, + &format!("the variable `{0}` is used as a loop counter. Consider \ + using `for ({0}, item) in {1}.enumerate()` \ + or similar iterators", + name, snippet(cx, arg.span, "_"))); + } + } + } + } + } +} + /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { diff --git a/src/matches.rs b/src/matches.rs index b6a7fc7fa5b..2c7f0830a53 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -59,7 +59,7 @@ impl LateLintPass for MatchPass { if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { - if let LitBool(val) = lit.node { + if let LitBool(val) = lit.node { if val { Some((&*arms[0].body, &*arms[1].body)) } else { diff --git a/src/utils.rs b/src/utils.rs index 3fcfa66259c..365fc1bf99d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,6 +9,9 @@ use std::borrow::Cow; use syntax::ast::Lit_::*; use syntax::ast; +use rustc::session::Session; +use std::str::FromStr; + // module DefPaths for certain structs/enums we check for pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; @@ -65,8 +68,8 @@ macro_rules! if_let_chain { }; } -/// returns true this expn_info was expanded by any macro -pub fn in_macro(cx: &LateContext, span: Span) -> bool { +/// returns true if this expn_info was expanded by any macro +pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) } @@ -397,3 +400,62 @@ macro_rules! if_let_chain { } }; } + +pub struct LimitStack { + stack: Vec<u64>, +} + +impl Drop for LimitStack { + fn drop(&mut self) { + assert_eq!(self.stack.len(), 1); + } +} + +impl LimitStack { + pub fn new(limit: u64) -> LimitStack { + LimitStack { + stack: vec![limit], + } + } + pub fn limit(&self) -> u64 { + *self.stack.last().expect("there should always be a value in the stack") + } + pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs( + sess, + attrs, + name, + |val| stack.push(val), + ); + } + pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs( + sess, + attrs, + name, + |val| assert_eq!(stack.pop(), Some(val)), + ); + } +} + +fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { + for attr in attrs { + let attr = &attr.node; + if attr.is_sugared_doc { continue; } + if let ast::MetaNameValue(ref key, ref value) = attr.value.node { + if *key == name { + if let LitStr(ref s, _) = value.node { + if let Ok(value) = FromStr::from_str(s) { + f(value) + } else { + sess.span_err(value.span, "not a number"); + } + } else { + unreachable!() + } + } + } + } +} diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs new file mode 100644 index 00000000000..8e3bf123c26 --- /dev/null +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -0,0 +1,181 @@ +#![feature(plugin, custom_attribute)] +#![plugin(clippy)] +#![deny(clippy)] +#![deny(cyclomatic_complexity)] +#![allow(unused)] + +fn main() { //~ ERROR: The function has a cyclomatic complexity of 28. + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } + if true { + println!("a"); + } +} + +#[cyclomatic_complexity = "0"] +fn kaboom() { //~ ERROR: The function has a cyclomatic complexity of 6 + let n = 0; + 'a: for i in 0..20 { + 'b: for j in i..20 { + for k in j..20 { + if k == 5 { + break 'b; + } + if j == 3 && k == 6 { + continue 'a; + } + if k == j { + continue; + } + println!("bake"); + } + } + println!("cake"); + } +} + +fn bloo() { + match 42 { + 0 => println!("hi"), + 1 => println!("hai"), + 2 => println!("hey"), + 3 => println!("hallo"), + 4 => println!("hello"), + 5 => println!("salut"), + 6 => println!("good morning"), + 7 => println!("good evening"), + 8 => println!("good afternoon"), + 9 => println!("good night"), + 10 => println!("bonjour"), + 11 => println!("hej"), + 12 => println!("hej hej"), + 13 => println!("greetings earthling"), + 14 => println!("take us to you leader"), + 15 | 17 | 19 | 21 | 23 | 25 | 27 | 29 | 31 | 33 => println!("take us to you leader"), + 35 | 37 | 39 | 41 | 43 | 45 | 47 | 49 | 51 | 53 => println!("there is no undefined behavior"), + 55 | 57 | 59 | 61 | 63 | 65 | 67 | 69 | 71 | 73 => println!("I know borrow-fu"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn baa() { //~ ERROR: The function has a cyclomatic complexity of 2 + let x = || match 99 { + 0 => true, + 1 => false, + 2 => true, + 4 => true, + 6 => true, + 9 => true, + _ => false, + }; + if x() { + println!("x"); + } else { + println!("not x"); + } +} + +#[cyclomatic_complexity = "0"] +fn bar() { //~ ERROR: The function has a cyclomatic complexity of 2 + match 99 { + 0 => println!("hi"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn barr() { //~ ERROR: The function has a cyclomatic complexity of 2 + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } +} + +enum Void {} + +#[cyclomatic_complexity = "0"] +fn void(void: Void) { //~ ERROR: The function has a cyclomatic complexity of 1 + if true { + match void { + } + } +} diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 3d19bd66094..7a18c210d0c 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -16,7 +16,7 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed)] +#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index 7d1904ad446..ee8e4622e0e 100644 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(while_let_loop, empty_loop, while_let_on_iterator)] -#![allow(dead_code, unused)] +#![allow(dead_code, unused, cyclomatic_complexity)] fn main() { let y = Some(true); -- cgit 1.4.1-3-g733a5 From 3d1b7e1957b647ae17eb26d1e1258c4ca2ba4a16 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 18 Nov 2015 17:09:48 +0100 Subject: high-speed-dogfood --- src/lib.rs | 4 ++++ tests/dogfood.rs | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/dogfood.rs diff --git a/src/lib.rs b/src/lib.rs index 33ae07b7ad8..57a92f99900 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,10 @@ #![feature(num_bits_bytes, iter_arith)] #![allow(unknown_lints)] +// this only exists to allow the "dogfood" integration test to work +#[allow(dead_code)] +fn main() { println!("What are you doing? Don't run clippy as an executable"); } + #[macro_use] extern crate syntax; #[macro_use] diff --git a/tests/dogfood.rs b/tests/dogfood.rs new file mode 100644 index 00000000000..61e37c28c94 --- /dev/null +++ b/tests/dogfood.rs @@ -0,0 +1,24 @@ +extern crate compiletest_rs as compiletest; + +use std::path::Path; +use std::env::var; + +#[test] +fn dogfood() { + let mut config = compiletest::default_config(); + + let cfg_mode = "run-pass".parse().ok().expect("Invalid mode"); + let mut s = String::new(); + s.push_str(" -L target/debug/"); + s.push_str(" -L target/debug/deps"); + s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy"); + config.target_rustcflags = Some(s); + if let Ok(name) = var::<&str>("TESTNAME") { + let s : String = name.to_owned(); + config.filter = Some(s) + } + + config.mode = cfg_mode; + + compiletest::runtest::run(config, &Path::new("src/lib.rs")); +} -- cgit 1.4.1-3-g733a5 From 04524c549eaa96a437e7ffd4c509b9de79370e3c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 3 Dec 2015 12:43:50 +0100 Subject: improve cc of function --- src/methods.rs | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index b0758bc6937..f1c868bec07 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -54,20 +54,19 @@ impl LateLintPass for MethodsPass { if let ExprMethodCall(ref name, _, ref args) = expr.node { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - if name.node.as_str() == "unwrap" { - if match_type(cx, obj_ty, &OPTION_PATH) { + match &*name.node.as_str() { + "unwrap" if match_type(cx, obj_ty, &OPTION_PATH) => { span_lint(cx, OPTION_UNWRAP_USED, expr.span, "used unwrap() on an Option value. If you don't want \ to handle the None case gracefully, consider using \ expect() to provide a better panic message"); - } else if match_type(cx, obj_ty, &RESULT_PATH) { + }, + "unwrap" if match_type(cx, obj_ty, &RESULT_PATH) => { span_lint(cx, RESULT_UNWRAP_USED, expr.span, "used unwrap() on a Result value. Graceful handling \ of Err values is preferred"); - } - } - else if name.node.as_str() == "to_string" { - if obj_ty.sty == ty::TyStr { + }, + "to_string" if obj_ty.sty == ty::TyStr => { let mut arg_str = snippet(cx, args[0].span, "_"); if ptr_depth > 1 { arg_str = Cow::Owned(format!( @@ -77,13 +76,12 @@ impl LateLintPass for MethodsPass { } span_lint(cx, STR_TO_STRING, expr.span, &format!( "`{}.to_owned()` is faster", arg_str)); - } else if match_type(cx, obj_ty, &STRING_PATH) { + }, + "to_string" if match_type(cx, obj_ty, &STRING_PATH) => { span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \ `clone()` to make a copy"); - } - } - else if name.node.as_str() == "expect" { - if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + }, + "expect" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { if inner_name.node.as_str() == "ok" && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &RESULT_PATH) { let result_type = cx.tcx.expr_ty(&inner_args[0]); @@ -96,11 +94,9 @@ impl LateLintPass for MethodsPass { } } } - } - } - // check Option.map(_).unwrap_or(_) - else if name.node.as_str() == "unwrap_or" { - if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + }, + // check Option.map(_).unwrap_or(_) + "unwrap_or" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { if inner_name.node.as_str() == "map" && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { // lint message @@ -126,11 +122,9 @@ impl LateLintPass for MethodsPass { span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); }; } - } - } - // check Option.map(_).unwrap_or_else(_) - else if name.node.as_str() == "unwrap_or_else" { - if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { + }, + // check Option.map(_).unwrap_or_else(_) + "unwrap_or_else" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { if inner_name.node.as_str() == "map" && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { // lint message @@ -156,7 +150,8 @@ impl LateLintPass for MethodsPass { span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); }; } - } + }, + _ => {}, } } } -- cgit 1.4.1-3-g733a5 From 18e81c1b59cd908bf3a1c14463533de64df74f5c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 4 Dec 2015 15:42:53 +0530 Subject: Rudimentary escape analysis for Box<T> --- README.md | 3 +- src/escape.rs | 156 ++++++++++++++++++++++++++++++++++ src/lib.rs | 3 + tests/compile-fail/escape_analysis.rs | 81 ++++++++++++++++++ 4 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 src/escape.rs create mode 100644 tests/compile-fail/escape_analysis.rs diff --git a/README.md b/README.md index 206d86ec1ee..e19ab474c5e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 80 lints included in this crate: +There are 81 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -15,6 +15,7 @@ name [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` [block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` diff --git a/src/escape.rs b/src/escape.rs new file mode 100644 index 00000000000..fbd545acc96 --- /dev/null +++ b/src/escape.rs @@ -0,0 +1,156 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use rustc_front::intravisit as visit; +use rustc::front::map::Node; +use rustc::middle::ty; +use rustc::middle::ty::adjustment::AutoAdjustment; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::infer; +use rustc::middle::mem_categorization::{cmt, Categorization}; +use rustc::util::nodemap::NodeSet; +use syntax::ast::NodeId; +use syntax::codemap::Span; +use utils::span_lint; + +pub struct EscapePass; + +declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); + +struct EscapeDelegate<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + set: NodeSet, +} + +impl LintPass for EscapePass { + fn get_lints(&self) -> LintArray { + lint_array!(BOXED_LOCAL) + } +} + +impl LateLintPass for EscapePass { + fn check_fn(&mut self, + cx: &LateContext, + _: visit::FnKind, + decl: &FnDecl, + body: &Block, + _: Span, + id: NodeId) { + let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env), false); + let mut v = EscapeDelegate { + cx: cx, + set: NodeSet(), + }; + { + let mut vis = ExprUseVisitor::new(&mut v, &infcx); + vis.walk_fn(decl, body); + } + for node in v.set { + span_lint(cx, + BOXED_LOCAL, + cx.tcx.map.span(node), + "local variable doesn't need to be boxed here"); + } + } +} + +impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { + fn consume(&mut self, + _: NodeId, + _: Span, + cmt: cmt<'tcx>, + mode: ConsumeMode) { + + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + if let Move(DirectRefMove) = mode { + // moved out or in. clearly can't be localized + self.set.remove(&lid); + } + } + } + } + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} + fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { + if let Categorization::Rvalue(..) = cmt.cat { + if let Some(Node::NodeStmt(st)) = self.cx + .tcx + .map + .find(self.cx.tcx.map.get_parent_node(cmt.id)) { + if let StmtDecl(ref decl, _) = st.node { + if let DeclLocal(ref loc) = decl.node { + if let Some(ref ex) = loc.init { + if let ExprBox(..) = ex.node { + if let ty::TyBox(..) = cmt.ty.sty { + // let x = box (...) + self.set.insert(consume_pat.id); + } + // TODO Box::new + // TODO vec![] + // TODO "foo".to_owned() and friends + } + } + } + } + } + } + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + // let y = x where x is known + // remove x, insert y + self.set.insert(consume_pat.id); + self.set.remove(&lid); + } + } + + } + fn borrow(&mut self, + borrow_id: NodeId, + _: Span, + cmt: cmt<'tcx>, + _: ty::Region, + _: ty::BorrowKind, + loan_cause: LoanCause) { + + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.cx + .tcx + .tables + .borrow() + .adjustments + .get(&borrow_id) { + if LoanCause::AutoRef == loan_cause { + // x.foo() + if adj.autoderefs <= 0 { + self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) + } + } else { + self.cx.sess().span_bug(cmt.span, "Unknown adjusted AutoRef"); + } + } else if LoanCause::AddrOf == loan_cause { + // &x + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = + self.cx.tcx.tables.borrow().adjustments + .get(&self.cx.tcx.map.get_parent_node(borrow_id)) { + if adj.autoderefs <= 1 { + // foo(&x) where no extra autoreffing is happening + self.set.remove(&lid); + } + } + + } else if LoanCause::MatchDiscriminant == loan_cause { + self.set.remove(&lid); // `match x` can move + } + // do nothing for matches, etc. These can't escape + } + } + } + fn decl_without_init(&mut self, _: NodeId, _: Span) {} + fn mutate(&mut self, + _: NodeId, + _: Span, + _: cmt<'tcx>, + _: MutateMode) { + } +} diff --git a/src/lib.rs b/src/lib.rs index 57a92f99900..9ead05b93b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,7 @@ pub mod no_effect; pub mod temporary_assignment; pub mod transmute; pub mod cyclomatic_complexity; +pub mod escape; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -116,6 +117,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); reg.register_late_lint_pass(box transmute::UselessTransmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); + reg.register_late_lint_pass(box escape::EscapePass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -146,6 +148,7 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, eq_op::EQ_OP, + escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, len_zero::LEN_WITHOUT_IS_EMPTY, diff --git a/tests/compile-fail/escape_analysis.rs b/tests/compile-fail/escape_analysis.rs new file mode 100644 index 00000000000..3782cb96da5 --- /dev/null +++ b/tests/compile-fail/escape_analysis.rs @@ -0,0 +1,81 @@ +#![feature(plugin, box_syntax)] +#![plugin(clippy)] +#![allow(warnings, clippy)] + +#![deny(boxed_local)] + +#[derive(Clone)] +struct A; + +impl A { + fn foo(&self){} +} + +fn main() { +} + +fn warn_call() { + let x = box A; //~ ERROR local variable + x.foo(); +} + +fn warn_rename_call() { + let x = box A; + + let y = x; //~ ERROR local variable + y.foo(); // via autoderef +} + +fn warn_notuse() { + let bz = box A; //~ ERROR local variable +} + +fn warn_pass() { + let bz = box A; //~ ERROR local variable + take_ref(&bz); // via deref coercion +} + +fn nowarn_return() -> Box<A> { + let fx = box A; + fx // moved out, "escapes" +} + +fn nowarn_move() { + let bx = box A; + drop(bx) // moved in, "escapes" +} +fn nowarn_call() { + let bx = box A; + bx.clone(); // method only available to Box, not via autoderef +} + +fn nowarn_pass() { + let bx = box A; + take_box(&bx); // fn needs &Box +} + + +fn take_box(x: &Box<A>) {} +fn take_ref(x: &A) {} + + +fn nowarn_ref_take() { + // false positive, should actually warn + let x = box A; //~ ERROR local variable + let y = &x; + take_box(y); +} + +fn nowarn_match() { + let x = box A; // moved into a match + match x { + y => drop(y) + } +} + +fn warn_match() { + let x = box A; //~ ERROR local variable + match &x { // not moved + ref y => () + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From dc414e6c02cde7092b89cccd470a5b58fac736bd Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 5 Dec 2015 14:23:00 +0530 Subject: Make panic in CC silencable (partial #478) --- .travis.yml | 2 +- Cargo.toml | 3 ++- src/cyclomatic_complexity.rs | 33 +++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7eaa61c5572..920aaf981f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,5 @@ sudo: false script: - python util/update_lints.py -c - - cargo test + - cargo test --features debugging - bash util/dogfood.sh diff --git a/Cargo.toml b/Cargo.toml index b9ade2ac28f..c86b7b7d522 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.27" +version = "0.0.28" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -28,3 +28,4 @@ lazy_static = "*" [features] structured_logging = [] +debugging = [] diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 678ebe866cb..1379a8db15d 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -44,17 +44,16 @@ impl CyclomaticComplexity { if narms > 0 { narms = narms - 1; } + if cc < narms { - println!("cc = {}, arms = {}", cc, narms); - println!("{:?}", block); - println!("{:?}", span); - panic!("cc = {}, arms = {}", cc, narms); - } - let rust_cc = cc - narms; - if rust_cc > self.limit.limit() { - cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, - &format!("The function has a cyclomatic complexity of {}.", rust_cc), - "You could split it up into multiple smaller functions"); + report_cc_bug(cx, cc, narms, span); + } else { + let rust_cc = cc - narms; + if rust_cc > self.limit.limit() { + cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, + &format!("The function has a cyclomatic complexity of {}.", rust_cc), + "You could split it up into multiple smaller functions"); + } } } } @@ -103,3 +102,17 @@ impl<'a> Visitor<'a> for MatchArmCounter { } } } + +#[cfg(feature="debugging")] +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, span: Span) { + cx.sess().span_bug(span, &format!("Clippy encountered a bug calculating cyclomatic complexity: \ + cc = {}, arms = {}. Please file a bug report.", cc, narms));; +} +#[cfg(not(feature="debugging"))] +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, span: Span) { + if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { + cx.sess().span_note(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ + (hide this message with `#[allow(cyclomatic_complexity)]`): \ + cc = {}, arms = {}. Please file a bug report.", cc, narms)); + } +} -- cgit 1.4.1-3-g733a5 From 978c41584f9d1337ad2d6cf5d5ec0ff1a40a30c4 Mon Sep 17 00:00:00 2001 From: Robert Clipsham <robert@octarineparrot.com> Date: Sat, 5 Dec 2015 12:25:04 +0000 Subject: Fix clippy with latest Rust nightly. --- Cargo.toml | 2 +- src/shadow.rs | 2 +- tests/consts.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c86b7b7d522..4ae56d791f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.28" +version = "0.0.29" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/shadow.rs b/src/shadow.rs index 5fb27f75c3c..2c68667fc32 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -62,7 +62,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } if is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { - let Local{ ref pat, ref ty, ref init, id: _, span } = **local; + let Local{ ref pat, ref ty, ref init, id: _, span, attrs: _ } = **local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } if let Some(ref o) = *init { check_expr(cx, o, bindings); diff --git a/tests/consts.rs b/tests/consts.rs index 66a7953994b..5ddcd6df7b8 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -29,6 +29,7 @@ fn expr(n: Expr_) -> Expr { id: 1, node: n, span: COMMAND_LINE_SP, + attrs: None } } -- cgit 1.4.1-3-g733a5 From 62db39273088f216ba95e1853b982a489051c152 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Fri, 4 Dec 2015 15:56:25 +0100 Subject: Make lifetimes lint work with type aliases and non-locally-defined structs --- src/lifetimes.rs | 29 ++++++++++++++--------------- tests/compile-fail/lifetimes.rs | 13 +++++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index acc7b014052..0003c50d843 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -3,7 +3,7 @@ use reexport::*; use rustc::lint::*; use syntax::codemap::Span; use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound}; -use rustc::middle::def::Def::{DefTy, DefTrait}; +use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct}; use std::collections::HashSet; use utils::{in_external_macro, span_lint}; @@ -187,23 +187,22 @@ impl <'v, 't> RefVisitor<'v, 't> { let last_path_segment = path.segments.last().map(|s| &s.parameters); if let Some(&AngleBracketedParameters(ref params)) = last_path_segment { if params.lifetimes.is_empty() { - let def = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()); - match def { - Some(DefTy(def_id, _)) => { - if let Some(ty_def) = self.cx.tcx.adt_defs.borrow().get(&def_id) { - let scheme = ty_def.type_scheme(self.cx.tcx); - for _ in scheme.generics.regions.as_slice() { + if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { + match def { + DefTy(def_id, _) | DefStruct(def_id) => { + let type_scheme = self.cx.tcx.lookup_item_type(def_id); + for _ in type_scheme.generics.regions.as_slice() { self.record(&None); } - } - } - Some(DefTrait(def_id)) => { - let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; - for _ in &trait_def.generics.regions { - self.record(&None); - } + }, + DefTrait(def_id) => { + let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; + for _ in &trait_def.generics.regions { + self.record(&None); + } + }, + _ => {} } - _ => {} } } } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index f5d95aacc9a..040c3554e89 100644 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -106,5 +106,18 @@ fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str { unimplemented!() } // unambiguous if we elided the lifetime fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } //~ERROR explicit lifetimes given +type FooAlias<'a> = Foo<'a>; + +fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } //~ERROR explicit lifetimes given + +// no warning, two input lifetimes (named on the reference, anonymous on Foo) +fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { unimplemented!() } + +// no warning, two input lifetimes (anonymous on the reference, named on Foo) +fn alias_with_lt3<'a>(_foo: &FooAlias<'a> ) -> &'a str { unimplemented!() } + +// no warning, two input lifetimes +fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b> ) -> &'a str { unimplemented!() } + fn main() { } -- cgit 1.4.1-3-g733a5 From ac39dc290b7a2319a5bba61314bf1ee288e36057 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Sun, 6 Dec 2015 02:05:32 +0100 Subject: Remove obsolete workaround --- src/utils.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index 3fcfa66259c..8be5a12ae07 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -256,7 +256,6 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if let NodeExpr(parent) = node { Some(parent) } else { None } ) } -#[allow(needless_lifetimes)] // workaround for https://github.com/Manishearth/rust-clippy/issues/417 pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { let map = &cx.tcx.map; let enclosing_node = map.get_enclosing_scope(node) -- cgit 1.4.1-3-g733a5 From c7b87a06d20a13e9fdf86d34f200ad4e444cb5b8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 7 Dec 2015 03:06:22 +0530 Subject: Add lint for unused lifetimes (fixes #459) --- README.md | 3 ++- src/lib.rs | 1 + src/lifetimes.rs | 31 +++++++++++++++++++++++--- tests/compile-fail/lifetimes.rs | 2 +- tests/compile-fail/unused_lt.rs | 48 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 tests/compile-fail/unused_lt.rs diff --git a/README.md b/README.md index e19ab474c5e..8fdaf1206f9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 81 lints included in this crate: +There are 82 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -84,6 +84,7 @@ name [unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator diff --git a/src/lib.rs b/src/lib.rs index 9ead05b93b2..3faa0427c39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,6 +154,7 @@ pub fn plugin_registrar(reg: &mut Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, + lifetimes::UNUSED_LIFETIMES, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 16ba43766e0..e9591ab6ddc 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -2,9 +2,9 @@ use rustc_front::hir::*; use reexport::*; use rustc::lint::*; use syntax::codemap::Span; -use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound}; +use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl}; use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct}; -use std::collections::HashSet; +use std::collections::{HashSet, HashMap}; use utils::{in_external_macro, span_lint}; @@ -12,12 +12,15 @@ declare_lint!(pub NEEDLESS_LIFETIMES, Warn, "using explicit lifetimes for references in function arguments when elision rules \ would allow omitting them"); +declare_lint!(pub UNUSED_LIFETIMES, Warn, + "unused lifetimes in function definitions"); + #[derive(Copy,Clone)] pub struct LifetimePass; impl LintPass for LifetimePass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_LIFETIMES) + lint_array!(NEEDLESS_LIFETIMES, UNUSED_LIFETIMES) } } @@ -61,6 +64,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, span_lint(cx, NEEDLESS_LIFETIMES, span, "explicit lifetimes given in parameter types where they could be elided"); } + report_extra_lifetimes(cx, decl, &generics.lifetimes); } fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, @@ -263,3 +267,24 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { } false } + +struct LifetimeChecker(HashMap<Name, Span>); + +impl<'v> Visitor<'v> for LifetimeChecker { + + // for lifetimes as parameters of generics + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { + self.0.remove(&lifetime.name); + } +} + +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, + named_lts: &[LifetimeDef]) { + let hs = named_lts.iter().map(|lt| (lt.lifetime.name, lt.lifetime.span)).collect(); + let mut checker = LifetimeChecker(hs); + walk_fn_decl(&mut checker, func); + for (_, v) in checker.0 { + span_lint(cx, UNUSED_LIFETIMES, v, + "this lifetime isn't used in the function definition"); + } +} diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 040c3554e89..4d454a738d9 100644 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(needless_lifetimes)] -#![allow(dead_code)] +#![allow(dead_code, unused_lifetimes)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~^ERROR explicit lifetimes given diff --git a/tests/compile-fail/unused_lt.rs b/tests/compile-fail/unused_lt.rs new file mode 100644 index 00000000000..d4babdfc4fd --- /dev/null +++ b/tests/compile-fail/unused_lt.rs @@ -0,0 +1,48 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unused, dead_code, needless_lifetimes)] +#![deny(unused_lifetimes)] + +fn empty() { + +} + + +fn used_lt<'a>(x: &'a u8) { + +} + + +fn unused_lt<'a>(x: u8) { //~ ERROR this lifetime + +} + +fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { //~ ERROR this lifetime + // 'a is useless here since it's not directly bound +} + +fn lt_return<'a, 'b: 'a>(x: &'b u8) -> &'a u8 { + panic!() +} + +fn lt_return_only<'a>() -> &'a u8 { + panic!() +} + +fn unused_lt_blergh<'a>(x: Option<Box<Send+'a>>) { + +} + + +trait Foo<'a> { + fn x(&self, a: &'a u8); +} + +impl<'a> Foo<'a> for u8 { + fn x(&self, a: &'a u8) { + + } +} +fn main() { + +} -- cgit 1.4.1-3-g733a5 From 72117836f17a1c68946be433d1467001af7bb8af Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Sun, 6 Dec 2015 03:21:34 +0100 Subject: Add check on redundant _ bindings in structs --- README.md | 3 ++- src/lib.rs | 3 +++ src/misc_early.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/mut_mut.rs | 2 +- src/mut_reference.rs | 4 ++-- src/open_options.rs | 2 +- src/shadow.rs | 2 +- src/utils.rs | 4 ++-- 8 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 src/misc_early.rs diff --git a/README.md b/README.md index e19ab474c5e..af4c3e80437 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 81 lints included in this crate: +There are 82 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -81,6 +81,7 @@ name [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unneeded_binding](https://github.com/Manishearth/rust-clippy/wiki#unneeded_binding) | warn | Type fields are bound when not necessary [unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop diff --git a/src/lib.rs b/src/lib.rs index 9ead05b93b2..abb3f0425df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ pub mod temporary_assignment; pub mod transmute; pub mod cyclomatic_complexity; pub mod escape; +pub mod misc_early; mod reexport { pub use syntax::ast::{Name, Ident, NodeId}; @@ -118,6 +119,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box transmute::UselessTransmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); reg.register_late_lint_pass(box escape::EscapePass); + reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -181,6 +183,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + misc_early::UNNEEDED_BINDING, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, diff --git a/src/misc_early.rs b/src/misc_early.rs new file mode 100644 index 00000000000..5bec753d3eb --- /dev/null +++ b/src/misc_early.rs @@ -0,0 +1,48 @@ +//use rustc_front::hir::*; + +use rustc::lint::*; + +use syntax::ast::*; + +use utils::span_lint; + +declare_lint!(pub UNNEEDED_BINDING, Warn, + "Type fields are bound when not necessary"); + +#[derive(Copy, Clone)] +pub struct MiscEarly; + +impl LintPass for MiscEarly { + fn get_lints(&self) -> LintArray { + lint_array!(UNNEEDED_BINDING) + } +} + +impl EarlyLintPass for MiscEarly { + fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { + if let PatStruct(_, ref pfields, _) = pat.node { + let mut wilds = 0; + + for field in pfields { + if field.node.pat.node == PatWild { + wilds += 1; + } + } + if !pfields.is_empty() && wilds == pfields.len() { + span_lint(cx, UNNEEDED_BINDING, pat.span, + "All the struct fields are matched to a wildcard pattern, \ + consider using `..`."); + return; + } + if wilds > 0 { + for field in pfields { + if field.node.pat.node == PatWild { + span_lint(cx, UNNEEDED_BINDING, field.span, + "You matched a field with a wildcard pattern. \ + Consider using `..` instead"); + } + } + } + } + } +} diff --git a/src/mut_mut.rs b/src/mut_mut.rs index c361ab24831..06f76479c59 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -41,7 +41,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map_or_else( || { - if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = + if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, "this expression mutably borrows a mutable reference. \ diff --git a/src/mut_reference.rs b/src/mut_reference.rs index e9601e8650f..8e089378929 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -58,8 +58,8 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty let parameters = &fn_type.sig.skip_binder().inputs; for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {ty: _, mutbl: MutImmutable}) | - TypeVariants::TyRawPtr(TypeAndMut {ty: _, mutbl: MutImmutable}) => { + TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | + TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { if let ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("The function/method \"{}\" \ diff --git a/src/open_options.rs b/src/open_options.rs index 732852e1686..dd375d58a60 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -58,7 +58,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned {node: LitBool(lit), span: _} = **span { + if let Spanned {node: LitBool(lit), ..} = **span { if lit {Argument::True} else {Argument::False} } else { return; // The function is called with a literal diff --git a/src/shadow.rs b/src/shadow.rs index 2c68667fc32..60197fcf9df 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -62,7 +62,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } if is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { - let Local{ ref pat, ref ty, ref init, id: _, span, attrs: _ } = **local; + let Local{ ref pat, ref ty, ref init, span, .. } = **local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } if let Some(ref o) = *init { check_expr(cx, o, bindings); diff --git a/src/utils.rs b/src/utils.rs index 365fc1bf99d..a602902d45f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -167,8 +167,8 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { Some(NodeItem(&Item{ ref name, .. })) | - Some(NodeTraitItem(&TraitItem{ id: _, ref name, .. })) | - Some(NodeImplItem(&ImplItem{ id: _, ref name, .. })) => { + Some(NodeTraitItem(&TraitItem{ ref name, .. })) | + Some(NodeImplItem(&ImplItem{ ref name, .. })) => { Some(*name) } _ => None, -- cgit 1.4.1-3-g733a5 From 98c4dc185c5bdd688dcf3631b840ca7d12047f94 Mon Sep 17 00:00:00 2001 From: Andre Bogus <andre.bogus@ankordata.de> Date: Tue, 8 Dec 2015 06:32:55 +0100 Subject: updated lints --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cae2ec1a4a..4e410002852 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 82 lints included in this crate: +There are 83 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- cgit 1.4.1-3-g733a5 From 35b5c3efdd4785a72d54104aa4a2580eaa15dfa9 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Tue, 8 Dec 2015 15:03:01 +0900 Subject: Use suggestion for redundant_closure --- src/eta_reduction.rs | 11 +++++++---- src/utils.rs | 5 +++++ tests/compile-fail/eta.rs | 12 +++++++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index c4c0912464c..5ade158200c 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; -use utils::{snippet, span_lint, is_adjusted}; +use utils::{snippet_opt, span_lint, is_adjusted}; #[allow(missing_copy_implementations)] @@ -75,9 +75,12 @@ fn check_closure(cx: &LateContext, expr: &Expr) { return } } - span_lint(cx, REDUNDANT_CLOSURE, expr.span, &format!( - "redundant closure found. Consider using `{}` in its place", - snippet(cx, caller.span, ".."))); + span_lint(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found"); + if let Some(snippet) = snippet_opt(cx, caller.span) { + cx.sess().span_suggestion(expr.span, + "remove closure as shown:", + snippet); + } } } } diff --git a/src/utils.rs b/src/utils.rs index 2b38403b63a..21d1f9d16ec 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -195,6 +195,11 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow< cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) } +/// Converts a span to a code snippet. Returns None if not available. +pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { + cx.sess().codemap().span_to_snippet(span).ok() +} + /// convert a span (from a block) to a code snippet if available, otherwise use default, e.g. /// `snippet(cx, expr.span, "..")` /// This trims the code of indentation, except for the first line diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index d53ea4e97d7..a51d116d9cc 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -5,11 +5,17 @@ fn main() { let a = Some(1u8).map(|a| foo(a)); - //~^ ERROR redundant closure found. Consider using `foo` in its place + //~^ ERROR redundant closure found + //~| HELP remove closure as shown + //~| SUGGESTION let a = Some(1u8).map(foo); meta(|a| foo(a)); - //~^ ERROR redundant closure found. Consider using `foo` in its place + //~^ ERROR redundant closure found + //~| HELP remove closure as shown + //~| SUGGESTION meta(foo); let c = Some(1u8).map(|a| {1+2; foo}(a)); - //~^ ERROR redundant closure found. Consider using `{1+2; foo}` in its place + //~^ ERROR redundant closure found + //~| HELP remove closure as shown + //~| SUGGESTION let c = Some(1u8).map({1+2; foo}); let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted unsafe { -- cgit 1.4.1-3-g733a5 From 213c15cd66c2291bcb95c8f9bd421c5181cb68d3 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 9 Dec 2015 01:28:35 +0900 Subject: Add span_lint_and_then and use it --- src/eta_reduction.rs | 17 ++++++++++------- src/utils.rs | 11 +++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 5ade158200c..4957c2e21bc 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::ty; -use utils::{snippet_opt, span_lint, is_adjusted}; +use utils::{snippet_opt, span_lint_and_then, is_adjusted}; #[allow(missing_copy_implementations)] @@ -75,12 +75,15 @@ fn check_closure(cx: &LateContext, expr: &Expr) { return } } - span_lint(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found"); - if let Some(snippet) = snippet_opt(cx, caller.span) { - cx.sess().span_suggestion(expr.span, - "remove closure as shown:", - snippet); - } + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, + "redundant closure found", + || { + if let Some(snippet) = snippet_opt(cx, caller.span) { + cx.sess().span_suggestion(expr.span, + "remove closure as shown:", + snippet); + } + }); } } } diff --git a/src/utils.rs b/src/utils.rs index 21d1f9d16ec..5e1671b709c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -325,6 +325,17 @@ pub fn span_note_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Spa } } +pub fn span_lint_and_then<T: LintContext, F>(cx: &T, lint: &'static Lint, sp: Span, + msg: &str, f: F) where F: Fn() { + cx.span_lint(lint, sp, msg); + if cx.current_level(lint) != Level::Allow { + f(); + cx.sess().fileline_help(sp, &format!("for further information visit \ + https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())) + } +} + /// return the base type for references and raw pointers pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { -- cgit 1.4.1-3-g733a5 From b865e30b49f3f0fb914ab82d152fae0f608ed540 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 9 Dec 2015 15:56:49 -0500 Subject: Upgrade rust to rustc 1.6.0-nightly (462ec0576 2015-12-09) --- Cargo.toml | 2 +- src/eq_op.rs | 1 - src/len_zero.rs | 4 ++-- src/lib.rs | 4 ++-- src/map_clone.rs | 1 - src/shadow.rs | 10 +++++----- tests/compile-fail/shadow.rs | 16 ++++++++-------- tests/compile-fail/transmute.rs | 1 - 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ae56d791f5..c70e43ed78d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.29" +version = "0.0.30" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/eq_op.rs b/src/eq_op.rs index 1d2146537c9..7636267bcd8 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -66,7 +66,6 @@ fn is_path_equal(left : &Path, right : &Path) -> bool { // we have to be explicit about hygiene left.global == right.global && over(&left.segments, &right.segments, |l, r| l.identifier.name == r.identifier.name - && l.identifier.ctxt == r.identifier.ctxt && l.parameters == r.parameters) } diff --git a/src/len_zero.rs b/src/len_zero.rs index 9ac4ab1e0e0..c501ceb66fa 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -50,7 +50,7 @@ impl LateLintPass for LenZero { } } -fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>]) { +fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { item.name.as_str() == name && if let MethodTraitItem(ref sig, _) = item.node { is_self_sig(sig) } else { false } @@ -69,7 +69,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>] } } -fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) { +fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { item.name.as_str() == name && if let ImplItemKind::Method(ref sig, _) = item.node { is_self_sig(sig) } else { false } diff --git a/src/lib.rs b/src/lib.rs index be0db936e6b..03e0cbea19c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![feature(plugin_registrar, box_syntax)] -#![feature(rustc_private, core, collections)] +#![feature(rustc_private, collections)] #![feature(num_bits_bytes, iter_arith)] #![allow(unknown_lints)] @@ -68,7 +68,7 @@ pub mod escape; pub mod misc_early; mod reexport { - pub use syntax::ast::{Name, Ident, NodeId}; + pub use syntax::ast::{Name, NodeId}; } #[plugin_registrar] diff --git a/src/map_clone.rs b/src/map_clone.rs index ba561fbb167..d9719df0b6f 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::ast::Ident; use utils::{CLONE_PATH, OPTION_PATH}; use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint}; use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; diff --git a/src/shadow.rs b/src/shadow.rs index 60197fcf9df..b9f60e0e01a 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -39,7 +39,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { if let PatIdent(_, ident, _) = arg.pat.node { - bindings.push((ident.node.name, ident.span)) + bindings.push((ident.node.unhygienic_name, ident.span)) } } check_block(cx, block, &mut bindings); @@ -85,7 +85,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, //TODO: match more stuff / destructuring match pat.node { PatIdent(_, ref ident, ref inner) => { - let name = ident.node.name; + let name = ident.node.unhygienic_name; if is_binding(cx, pat) { let mut new_binding = true; for tup in bindings.iter_mut() { @@ -266,7 +266,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { fn path_eq_name(name: Name, path: &Path) -> bool { !path.global && path.segments.len() == 1 && - path.segments[0].identifier.name == name + path.segments[0].identifier.unhygienic_name == name } struct ContainsSelf { @@ -275,8 +275,8 @@ struct ContainsSelf { } impl<'v> Visitor<'v> for ContainsSelf { - fn visit_name(&mut self, _: Span, name: Name) { - if self.name == name { + fn visit_ident(&mut self, _: Span, ident: Ident) { + if self.name == ident.unhygienic_name { self.result = true; } } diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index d70f26ed090..0a52a9829ae 100644 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -10,15 +10,15 @@ fn first(x: (isize, isize)) -> isize { x.0 } fn main() { let mut x = 1; - let x = &mut x; //~ERROR: x is shadowed by itself in &mut x - let x = { x }; //~ERROR: x is shadowed by itself in { x } - let x = (&*x); //~ERROR: x is shadowed by itself in &*x - let x = { *x + 1 }; //~ERROR: x is shadowed by { *x + 1 } which reuses - let x = id(x); //~ERROR: x is shadowed by id(x) which reuses - let x = (1, x); //~ERROR: x is shadowed by (1, x) which reuses - let x = first(x); //~ERROR: x is shadowed by first(x) which reuses + let x = &mut x; //~ERROR x is shadowed by itself in &mut x + let x = { x }; //~ERROR x is shadowed by itself in { x } + let x = (&*x); //~ERROR x is shadowed by itself in &*x + let x = { *x + 1 }; //~ERROR x is shadowed by { *x + 1 } which reuses + let x = id(x); //~ERROR x is shadowed by id(x) which reuses + let x = (1, x); //~ERROR x is shadowed by (1, x) which reuses + let x = first(x); //~ERROR x is shadowed by first(x) which reuses let y = 1; - let x = y; //~ERROR: x is shadowed by y + let x = y; //~ERROR x is shadowed by y let o = Some(1u8); diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 0a2d09d9431..94dd3a18549 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -1,4 +1,3 @@ -#![feature(core)] #![feature(plugin)] #![plugin(clippy)] #![deny(useless_transmute)] -- cgit 1.4.1-3-g733a5 From b9546599e31cb8f1b3ce5124d67f1f664e89b9c0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 10 Dec 2015 11:44:12 -0500 Subject: Check for unused lifetimes in bounds (fixes #489) --- src/lifetimes.rs | 19 +++++++++++++++---- tests/compile-fail/unused_lt.rs | 9 +++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index e9591ab6ddc..3edffc3bee3 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -2,7 +2,7 @@ use rustc_front::hir::*; use reexport::*; use rustc::lint::*; use syntax::codemap::Span; -use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl}; +use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct}; use std::collections::{HashSet, HashMap}; @@ -64,7 +64,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, span_lint(cx, NEEDLESS_LIFETIMES, span, "explicit lifetimes given in parameter types where they could be elided"); } - report_extra_lifetimes(cx, decl, &generics.lifetimes); + report_extra_lifetimes(cx, decl, &generics); } fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, @@ -276,12 +276,23 @@ impl<'v> Visitor<'v> for LifetimeChecker { fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.0.remove(&lifetime.name); } + + fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) { + // don't actually visit `<'a>` or `<'a: 'b>` + // we've already visited the `'a` declarations and + // don't want to spuriously remove them + // `'b` in `'a: 'b` is useless unless used elsewhere in + // a non-lifetime bound + } } fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, - named_lts: &[LifetimeDef]) { - let hs = named_lts.iter().map(|lt| (lt.lifetime.name, lt.lifetime.span)).collect(); + generics: &Generics) { + let hs = generics.lifetimes.iter() + .map(|lt| (lt.lifetime.name, lt.lifetime.span)) + .collect(); let mut checker = LifetimeChecker(hs); + walk_generics(&mut checker, generics); walk_fn_decl(&mut checker, func); for (_, v) in checker.0 { span_lint(cx, UNUSED_LIFETIMES, v, diff --git a/tests/compile-fail/unused_lt.rs b/tests/compile-fail/unused_lt.rs index d4babdfc4fd..85667174509 100644 --- a/tests/compile-fail/unused_lt.rs +++ b/tests/compile-fail/unused_lt.rs @@ -43,6 +43,15 @@ impl<'a> Foo<'a> for u8 { } } + +// test for #489 (used lifetimes in bounds) +pub fn parse<'a, I: Iterator<Item=&'a str>>(_it: &mut I) { + unimplemented!() +} +pub fn parse2<'a, I>(_it: &mut I) where I: Iterator<Item=&'a str>{ + unimplemented!() +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 5bbc1427fde4152d42e6159d5a3ca3eec167b02f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 11 Dec 2015 01:22:27 +0100 Subject: added wiki comments + wiki-generating python script --- src/approx_const.rs | 7 ++++ src/attrs.rs | 13 ++++++++ src/bit_mask.rs | 35 ++++++++++++++++++++ src/collapsible_if.rs | 7 ++++ src/eq_op.rs | 7 ++++ src/eta_reduction.rs | 7 ++++ src/identity_op.rs | 7 ++++ src/len_zero.rs | 19 +++++++++++ src/lifetimes.rs | 7 ++++ src/loops.rs | 75 ++++++++++++++++++++++++++++++++++++++++++ src/matches.rs | 43 ++++++++++++++++++++++++ src/methods.rs | 76 +++++++++++++++++++++++++++++++++++++++++++ src/minmax.rs | 7 ++++ src/misc.rs | 50 ++++++++++++++++++++++++++++ src/mut_mut.rs | 7 ++++ src/mut_reference.rs | 7 ++++ src/needless_bool.rs | 7 ++++ src/open_options.rs | 7 ++++ src/precedence.rs | 11 +++++++ src/ptr_arg.rs | 7 ++++ src/ranges.rs | 14 ++++++++ src/returns.rs | 14 ++++++++ src/shadow.rs | 21 ++++++++++++ src/strings.rs | 26 +++++++++++++++ src/types.rs | 69 +++++++++++++++++++++++++++++++++++++++ src/unicode.rs | 21 ++++++++++++ src/zero_div_zero.rs | 7 ++++ util/update_wiki.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 28 files changed, 668 insertions(+) create mode 100755 util/update_wiki.py diff --git a/src/approx_const.rs b/src/approx_const.rs index 9d1d51444fa..05829838903 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -6,6 +6,13 @@ use syntax::ast::Lit_::*; use syntax::ast::Lit; use syntax::ast::FloatTy::*; +/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. This lint is `Warn` by default. +/// +/// **Why is this bad?** Usually, the definition in the standard library is more precise than what people come up with. If you find that your definition is actually more precise, please [file a Rust issue](https://github.com/rust-lang/rust/issues). +/// +/// **Known problems:** If you happen to have a value that is within 1/8192 of a known constant, but is not *and should not* be the same, this lint will report your value anyway. We have not yet noticed any false positives in code we tested clippy with (this includes servo), but YMMV. +/// +/// **Example:** `let x = 3.14;` declare_lint! { pub APPROX_CONSTANT, Warn, diff --git a/src/attrs.rs b/src/attrs.rs index f4a5b4c1517..10db4a551f9 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -8,6 +8,19 @@ use syntax::attr::*; use syntax::ast::{Attribute, MetaList, MetaWord}; use utils::{in_macro, match_path, span_lint}; +/// **What it does:** This lint warns on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. +/// +/// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it. +/// +/// As a rule of thumb, before slapping `#[inline(always)]` on a function, measure if that additional function call really affects your runtime profile sufficiently to make up for the increase in compile time. +/// +/// **Known problems:** False positives, big time. This lint is meant to be deactivated by everyone doing serious performance work. This means having done the measurement. +/// +/// **Example:** +/// ``` +/// #[inline(always)] +/// fn not_quite_hot_code(..) { ... } +/// ``` declare_lint! { pub INLINE_ALWAYS, Warn, "`#[inline(always)]` is a bad idea in most cases" } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index bee99b0f783..3d428aa0da7 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -8,6 +8,27 @@ use syntax::ast::Lit_::*; use utils::span_lint; +/// **What it does:** This lint checks for incompatible bit masks in comparisons. It is `Warn` by default. +/// +/// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: +/// +/// |Comparison |Bit-Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// +/// **Why is this bad?** If the bits that the comparison cares about are always set to zero or one by the bit mask, the comparison is constant `true` or `false` (depending on mask, compared value, and operators). +/// +/// So the code is actively misleading, and the only reason someone would write this intentionally is to win an underhanded Rust contest or create a test-case for this lint. +/// +/// **Known problems:** None +/// +/// **Example:** `x & 1 == 2` (also see table above) declare_lint! { pub BAD_BIT_MASK, Warn, @@ -15,6 +36,20 @@ declare_lint! { (because in the example `select` containing bits that `mask` doesn't have)" } +/// **What it does:** This lint checks for bit masks in comparisons which can be removed without changing the outcome. The basic structure can be seen in the following table: +/// +/// |Comparison|Bit-Op |Example |equals | +/// |----------|---------|-----------|-------| +/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| +/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`| +/// +/// This lint is `Warn` by default. +/// +/// **Why is this bad?** Not equally evil as [`bad_bit_mask`](#bad_bit_mask), but still a bit misleading, because the bit mask is ineffective. +/// +/// **Known problems:** False negatives: This lint will only match instances where we have figured out the math (which is for a power-of-two compared value). This means things like `x | 1 >= 7` (which would be better written as `x >= 6`) will not be reported (but bit masks like this are fairly uncommon). +/// +/// **Example:** `x | 1 > 3` (also see table above) declare_lint! { pub INEFFECTIVE_BIT_MASK, Warn, diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 78e3ec5e35f..775e9ec95fc 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -18,6 +18,13 @@ use syntax::codemap::Spanned; use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; +/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by `&&`-combining their conditions. It is `Warn` by default. +/// +/// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. +/// +/// **Known problems:** None +/// +/// **Example:** `if x { if y { .. } }` declare_lint! { pub COLLAPSIBLE_IF, Warn, diff --git a/src/eq_op.rs b/src/eq_op.rs index 1d2146537c9..282056e4eb4 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -6,6 +6,13 @@ use syntax::ptr::P; use consts::constant; use utils::span_lint; +/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). It is `Warn` by default. +/// +/// **Why is this bad?** This is usually just a typo. +/// +/// **Known problems:** False negatives: We had some false positives regarding calls (notably [racer](https://github.com/phildawes/racer) had one instance of `x.pop() && x.pop()`), so we removed matching any function or method calls. We may introduce a whitelist of known pure functions in the future. +/// +/// **Example:** `x + 1 == x + 1` declare_lint! { pub EQ_OP, Warn, diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 4957c2e21bc..c25228793e6 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -9,6 +9,13 @@ use utils::{snippet_opt, span_lint_and_then, is_adjusted}; pub struct EtaPass; +/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. It is `Warn` by default. +/// +/// **Why is this bad?** Needlessly creating a closure just costs heap space and adds code for no benefit. +/// +/// **Known problems:** None +/// +/// **Example:** `xs.map(|x| foo(x))` where `foo(_)` is a plain function that takes the exact argument type of `x`. declare_lint!(pub REDUNDANT_CLOSURE, Warn, "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"); diff --git a/src/identity_op.rs b/src/identity_op.rs index 7ed784f00fc..88a03e050be 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -6,6 +6,13 @@ use consts::{constant_simple, is_negative}; use consts::Constant::ConstantInt; use utils::{span_lint, snippet, in_macro}; +/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. It is `Warn` by default. +/// +/// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly. +/// +/// **Known problems:** None +/// +/// **Example:** `x / 1 + 0 * 1 - 0 | 0` declare_lint! { pub IDENTITY_OP, Warn, "using identity operations, e.g. `x + 0` or `y / 1`" } diff --git a/src/len_zero.rs b/src/len_zero.rs index 9ac4ab1e0e0..cff2281985c 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -11,10 +11,29 @@ use syntax::ast::Lit; use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; +/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. It is `Warn` by default. +/// +/// **Why is this bad?** Some structures can answer `.is_empty()` much faster than calculating their length. So it is good to get into the habit of using `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer than a comparison. +/// +/// **Known problems:** None +/// +/// **Example:** `if x.len() == 0 { .. }` declare_lint!(pub LEN_ZERO, Warn, "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ could be used instead"); +/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. It is `Warn` by default. +/// +/// **Why is this bad?** It is good custom to have both methods, because for some data structures, asking about the length will be a costly operation, whereas `.is_empty()` can usually answer in constant time. Also it used to lead to false positives on the [`len_zero`](#len_zero) lint – currently that lint will ignore such entities. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// impl X { +/// fn len(&self) -> usize { .. } +/// } +/// ``` declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, "traits and impls that have `.len()` but not `.is_empty()`"); diff --git a/src/lifetimes.rs b/src/lifetimes.rs index e9591ab6ddc..39ef7857b08 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -8,6 +8,13 @@ use std::collections::{HashSet, HashMap}; use utils::{in_external_macro, span_lint}; +/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. It is `Warn` by default. +/// +/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. +/// +/// **Known problems:** Potential false negatives: we bail out if the function has a `where` clause where lifetimes are mentioned. +/// +/// **Example:** `fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }` declare_lint!(pub NEEDLESS_LIFETIMES, Warn, "using explicit lifetimes for references in function arguments when elision rules \ would allow omitting them"); diff --git a/src/loops.rs b/src/loops.rs index 393c92b16ef..3c4e023b98e 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -15,28 +15,103 @@ use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, get_enclosing_block}; use utils::{VEC_PATH, LL_PATH}; +/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. +/// +/// **Why is this bad?** Just iterating the collection itself makes the intent more clear and is probably faster. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// for i in 0..vec.len() { +/// println!("{}", vec[i]); +/// } +/// ``` declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, "for-looping over a range of indices where an iterator over items would do" } +/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. It is `Warn` by default. +/// +/// **Why is this bad?** Readability. +/// +/// **Known problems:** False negatives. We currently only warn on some known types. +/// +/// **Example:** `for x in y.iter() { .. }` (where y is a `Vec` or slice) declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } +/// **What it does:** This lint checks for loops on `x.next()`. It is `Warn` by default. +/// +/// **Why is this bad?** `next()` returns either `Some(value)` if there was a value, or `None` otherwise. The insidious thing is that `Option<_>` implements `IntoIterator`, so that possibly one value will be iterated, leading to some hard to find bugs. No one will want to write such code [except to win an Underhanded Rust Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). +/// +/// **Known problems:** None +/// +/// **Example:** `for x in y.next() { .. }` declare_lint!{ pub ITER_NEXT_LOOP, Warn, "for-looping over `_.next()` which is probably not intended" } +/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. +/// +/// **Why is this bad?** The `while let` loop is usually shorter and more readable +/// +/// **Known problems:** Sometimes the wrong binding is displayed (#383) +/// +/// **Example:** +/// +/// ``` +/// loop { +/// let x = match y { +/// Some(x) => x, +/// None => break, +/// } +/// // .. do something with x +/// } +/// // is easier written as +/// while let Some(x) = y { +/// // .. do something with x +/// } +/// ``` declare_lint!{ pub WHILE_LET_LOOP, Warn, "`loop { if let { ... } else break }` can be written as a `while let` loop" } +/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. It is `Warn` by default. +/// +/// **Why is this bad?** It is more idiomatic to use a `for` loop over the iterator instead. +/// +/// **Known problems:** None +/// +/// **Example:** `vec.iter().map(|x| /* some operation returning () */).collect::<Vec<_>>();` declare_lint!{ pub UNUSED_COLLECT, Warn, "`collect()`ing an iterator without using the result; this is usually better \ written as a for loop" } +/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. +/// +/// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended. +/// +/// **Known problems:** The lint cannot catch loops over dynamically defined ranges. Doing this would require simulating all possible inputs and code paths through the program, which would be complex and error-prone. +/// +/// **Examples**: `for x in 5..10-5 { .. }` (oops, stray `-`) declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, "Iterating over an empty range, such as `10..0` or `5..5`" } +/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. It is `Warn` by default. +/// +/// **Why is it bad?** Not only is the version using `.enumerate()` more readable, the compiler is able to remove bounds checks which can lead to faster code in some instances. +/// +/// **Known problems:** None. +/// +/// **Example:** `for i in 0..v.len() { foo(v[i]); }` or `for i in 0..v.len() { bar(i, v[i]); }` declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, "for-looping with an explicit counter when `_.enumerate()` would do" } +/// **What it does:** This lint checks for empty `loop` expressions. It is `Warn` by default. +/// +/// **Why is this bad?** Those busy loops burn CPU cycles without doing anything. Think of the environment and either block on something or at least make the thread sleep for some microseconds. +/// +/// **Known problems:** None +/// +/// **Example:** `loop {}` declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" } diff --git a/src/matches.rs b/src/matches.rs index 2c7f0830a53..39459bafba7 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -6,12 +6,55 @@ use syntax::codemap::Span; use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; +/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default. +/// +/// **Why is this bad?** Just readability – `if let` nests less than a `match`. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// match x { +/// Some(ref foo) -> bar(foo), +/// _ => () +/// } +/// ``` declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ is `_ => {}`) is used; recommends `if let` instead"); +/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It is `Warn` by default. +/// +/// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// match x { +/// &A(ref y) => foo(y), +/// &B => bar(), +/// _ => frob(&x), +/// } +/// ``` declare_lint!(pub MATCH_REF_PATS, Warn, "a match has all arms prefixed with `&`; the match expression can be \ dereferenced instead"); +/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default. +/// +/// **Why is this bad?** It makes the code less readable. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let condition: bool = true; +/// match condition { +/// true => foo(), +/// false => bar(), +/// } +/// ``` declare_lint!(pub MATCH_BOOL, Warn, "a match on boolean expression; recommends `if..else` block instead"); diff --git a/src/methods.rs b/src/methods.rs index f1c868bec07..6c629f29c41 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -15,19 +15,95 @@ use self::OutType::*; #[derive(Clone)] pub struct MethodsPass; +/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. It is `Allow` by default. +/// +/// **Why is this bad?** Usually it is better to handle the `None` case, or to at least call `.expect(_)` with a more helpful message. Still, for a lot of quick-and-dirty code, `unwrap` is a good choice, which is why this lint is `Allow` by default. +/// +/// **Known problems:** None +/// +/// **Example:** `x.unwrap()` declare_lint!(pub OPTION_UNWRAP_USED, Allow, "using `Option.unwrap()`, which should at least get a better message using `expect()`"); +/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. It is `Allow` by default. +/// +/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`. +/// +/// Even if you want to panic on errors, not all `Error`s implement good messages on display. Therefore it may be beneficial to look at the places where they may get displayed. Activate this lint to do just that. +/// +/// **Known problems:** None +/// +/// **Example:** `x.unwrap()` declare_lint!(pub RESULT_UNWRAP_USED, Allow, "using `Result.unwrap()`, which might be better handled"); +/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. It is `Warn` by default. +/// +/// **Why is this bad?** This uses the whole formatting machinery just to clone a string. Using `.to_owned()` is lighter on resources. You can also consider using a [`Cow<'a, str>`](http://doc.rust-lang.org/std/borrow/enum.Cow.html) instead in some cases. +/// +/// **Known problems:** None +/// +/// **Example:** `s.to_string()` where `s: &str` declare_lint!(pub STR_TO_STRING, Warn, "using `to_string()` on a str, which should be `to_owned()`"); +/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default. +/// +/// **Why is this bad?** As our string is already owned, this whole operation is basically a no-op, but still creates a clone of the string (which, if really wanted, should be done with `.clone()`). +/// +/// **Known problems:** None +/// +/// **Example:** `s.to_string()` where `s: String` declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); +/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default. +/// +/// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// struct X; +/// impl X { +/// fn add(&self, other: &X) -> X { .. } +/// } +/// ``` declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, "defining a method that should be implementing a std trait"); +/// **What it does:** This lint checks for methods with certain name prefixes and `Warn`s (by default) if the prefix doesn't match how self is taken. The actual rules are: +/// +/// |Prefix |`self` taken | +/// |-------|--------------------| +/// |`as_` |`&self` or &mut self| +/// |`from_`| none | +/// |`into_`|`self` | +/// |`is_` |`&self` or none | +/// |`to_` |`&self` | +/// +/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_`.. function. +/// +/// **Known problems:** None +/// +/// **Example** +/// +/// ``` +/// impl X { +/// fn as_str(self) -> &str { .. } +/// } +/// ``` declare_lint!(pub WRONG_SELF_CONVENTION, Warn, "defining a method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); +/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. This lint is `Allow` by default. +/// +/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). +/// +/// **Known problems:** Actually *renaming* the function may break clients if the function is part of the public interface. In that case, be mindful of the stability guarantees you've given your users. +/// +/// **Example:** +/// ``` +/// impl X { +/// pub fn as_str(self) -> &str { .. } +/// } +/// ``` declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, "defining a public method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); diff --git a/src/minmax.rs b/src/minmax.rs index 9eb8a030e15..ac8d6f05272 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -8,6 +8,13 @@ use consts::{Constant, constant_simple}; use utils::{match_def_path, span_lint}; use self::MinMax::{Min, Max}; +/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. +/// +/// **Why is this bad?** This is in all probability not the intended outcome. At the least it hurts readability of the code. +/// +/// **Known problems:** None +/// +/// **Example:** `min(0, max(100, x))` will always be equal to `0`. Probably the author meant to clamp the value between 0 and 100, but has erroneously swapped `min` and `max`. declare_lint!(pub MIN_MAX, Warn, "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \ to a constant"); diff --git a/src/misc.rs b/src/misc.rs index 9df751d49b7..b5c3d0c514f 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -13,6 +13,15 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use utils::span_help_and_lint; +/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. +/// +/// **Why is this bad?** The `ref` declaration makes the function take an owned value, but turns the argument into a reference (which means that the value is destroyed when exiting the function). This adds not much value: either take a reference type, or take an owned value and create references in the body. +/// +/// For let bindings, `let x = &foo;` is preferred over `let ref x = foo`. The type of `x` is more obvious with the former. +/// +/// **Known problems:** If the argument is dereferenced within the function, removing the `ref` will lead to errors. This can be fixed by removing the dereferences, e.g. changing `*x` to `x` within the function. +/// +/// **Example:** `fn foo(ref x: u8) -> bool { .. }` declare_lint!(pub TOPLEVEL_REF_ARG, Warn, "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ @@ -68,6 +77,13 @@ impl LateLintPass for TopLevelRefPass { } } +/// **What it does:** This lint checks for comparisons to NAN. It is `Deny` by default. +/// +/// **Why is this bad?** NAN does not compare meaningfully to anything – not even itself – so those comparisons are simply wrong. +/// +/// **Known problems:** None +/// +/// **Example:** `x == NAN` declare_lint!(pub CMP_NAN, Deny, "comparisons to NAN (which will always return false, which is probably not intended)"); @@ -102,6 +118,13 @@ fn check_nan(cx: &LateContext, path: &Path, span: Span) { }); } +/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). It is `Warn` by default. +/// +/// **Why is this bad?** Floating point calculations are usually imprecise, so asking if two values are *exactly* equal is asking for trouble. For a good guide on what to do, see [the floating point guide](http://www.floating-point-gui.de/errors/comparison). +/// +/// **Known problems:** None +/// +/// **Example:** `y == 1.23f64` declare_lint!(pub FLOAT_CMP, Warn, "using `==` or `!=` on float values (as floating-point operations \ usually involve rounding errors, it is always better to check for approximate \ @@ -155,6 +178,13 @@ fn is_float(cx: &LateContext, expr: &Expr) -> bool { } } +/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. It is `Warn` by default. +/// +/// **Why is this bad?** The comparison can operate on a reference, so creating an owned value effectively throws it away directly afterwards, which is needlessly consuming code and heap space. +/// +/// **Known problems:** None +/// +/// **Example:** `x.to_owned() == y` declare_lint!(pub CMP_OWNED, Warn, "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`"); @@ -221,6 +251,13 @@ fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false } } +/// **What it does:** This lint checks for getting the remainder of a division by one. It is `Warn` by default. +/// +/// **Why is this bad?** The result can only ever be zero. No one will write such code deliberately, unless trying to win an Underhanded Rust Contest. Even for that contest, it's probably a bad idea. Use something more underhanded. +/// +/// **Known problems:** None +/// +/// **Example:** `x % 1` declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); #[derive(Copy,Clone)] @@ -244,6 +281,19 @@ impl LateLintPass for ModuloOne { } } +/// **What it does:** This lint checks for patterns in the form `name @ _`. +/// +/// **Why is this bad?** It's almost always more readable to just use direct bindings. +/// +/// **Known problems:** None +/// +/// **Example**: +/// ``` +/// match v { +/// Some(x) => (), +/// y @ _ => (), // easier written as `y`, +/// } +/// ``` declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern"); #[derive(Copy,Clone)] diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 06f76479c59..ade688d377f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -4,6 +4,13 @@ use rustc::middle::ty::{TypeAndMut, TyRef}; use utils::{in_external_macro, span_lint}; +/// **What it does:** This lint checks for instances of `mut mut` references. It is `Warn` by default. +/// +/// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = &mut &mut y;` declare_lint!(pub MUT_MUT, Allow, "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ or shows a fundamental misunderstanding of references)"); diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 8e089378929..9ba9782336a 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -4,6 +4,13 @@ use utils::span_lint; use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; use syntax::ptr::P; +/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. +/// +/// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site. +/// +/// **Known problems:** None +/// +/// **Example** `my_vec.push(&mut value)` declare_lint! { pub UNNECESSARY_MUT_PASSED, Warn, diff --git a/src/needless_bool.rs b/src/needless_bool.rs index e4d3b00218e..bd2e4116fd0 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -9,6 +9,13 @@ use syntax::ast::Lit_::*; use utils::{span_lint, snippet}; +/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. It is `Warn` by default. +/// +/// **Why is this bad?** Redundant code. +/// +/// **Known problems:** Maybe false positives: Sometimes, the two branches are painstakingly documented (which we of course do not detect), so they *may* have some value. Even then, the documentation can be rewritten to match the shorter code. +/// +/// **Example:** `if x { false } else { true }` declare_lint! { pub NEEDLESS_BOOL, Warn, diff --git a/src/open_options.rs b/src/open_options.rs index dd375d58a60..31ca0d72939 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -4,6 +4,13 @@ use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; use syntax::codemap::{Span, Spanned}; use syntax::ast::Lit_::LitBool; +/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. It is `Warn` by default. +/// +/// **Why is this bad?** In the best case, the code will be harder to read than necessary. I don't know the worst case. +/// +/// **Known problems:** None +/// +/// **Example:** `OpenOptions::new().read(true).truncate(true)` declare_lint! { pub NONSENSICAL_OPEN_OPTIONS, Warn, diff --git a/src/precedence.rs b/src/precedence.rs index b659bd647a7..be5f44c823a 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -5,6 +5,17 @@ use syntax::ast_util::binop_to_string; use utils::{span_lint, snippet}; +/// **What it does:** This lint checks for operations where precedence may be unclear and `Warn`'s about them by default, suggesting to add parentheses. Currently it catches the following: +/// * mixed usage of arithmetic and bit shifting/combining operators without parentheses +/// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call +/// +/// **Why is this bad?** Because not everyone knows the precedence of those operators by heart, so expressions like these may trip others trying to reason about the code. +/// +/// **Known problems:** None +/// +/// **Examples:** +/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 +/// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 declare_lint!(pub PRECEDENCE, Warn, "catches operations where precedence may be unclear. See the wiki for a \ list of cases caught"); diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 6946d0549d0..f748dbd9cfa 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -10,6 +10,13 @@ use rustc::front::map::Node; use utils::{span_lint, match_type}; use utils::{STRING_PATH, VEC_PATH}; +/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. It is `Warn` by default. +/// +/// **Why is this bad?** Requiring the argument to be of the specific size makes the function less useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be obtained from other types, too. +/// +/// **Known problems:** None +/// +/// **Example:** `fn foo(&Vec<u32>) { .. }` declare_lint! { pub PTR_ARG, Warn, diff --git a/src/ranges.rs b/src/ranges.rs index 31bb985230d..48bbba734ff 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -3,10 +3,24 @@ use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::{is_integer_literal, match_type, snippet}; +/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. It is `Warn` by default. +/// +/// **Why is this bad?** This very much looks like an oversight, since with `loop { .. }` there is an obvious better way to endlessly loop. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in (5..5).step_by(0) { .. }` declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, "using Range::step_by(0), which produces an infinite iterator" } +/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. It is `Warn` by default. +/// +/// **Why is this bad?** The code is better expressed with `.enumerate()`. +/// +/// **Known problems:** None +/// +/// **Example:** `x.iter().zip(0..x.len())` declare_lint! { pub RANGE_ZIP_WITH_LEN, Warn, "zipping iterator with a range when enumerate() would do" diff --git a/src/returns.rs b/src/returns.rs index 3df4efd0889..cf27b117ac4 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -6,8 +6,22 @@ use syntax::visit::FnKind; use utils::{span_lint, snippet, match_path_ast, in_external_macro}; +/// **What it does:** This lint checks for return statements at the end of a block. It is `Warn` by default. +/// +/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty. +/// +/// **Known problems:** None +/// +/// **Example:** `fn foo(x: usize) { return x; }` declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); +/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. It is `Warn` by default. +/// +/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. +/// +/// **Known problems:** None +/// +/// **Example:** `{ let x = ..; x }` declare_lint!(pub LET_AND_RETURN, Warn, "creating a let-binding and then immediately returning it like `let x = expr; x` at \ the end of a block"); diff --git a/src/shadow.rs b/src/shadow.rs index 60197fcf9df..b38435656c6 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -9,11 +9,32 @@ use rustc::middle::def::Def::{DefVariant, DefStruct}; use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint}; +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. It is `Allow` by default. +/// +/// **Why is this bad?** Not much, in fact it's a very common pattern in Rust code. Still, some may opt to avoid it in their code base, they can set this lint to `Warn`. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = &x;` declare_lint!(pub SHADOW_SAME, Allow, "rebinding a name to itself, e.g. `let mut x = &mut x`"); +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. It is `Allow` by default. +/// +/// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = x + 1;` declare_lint!(pub SHADOW_REUSE, Allow, "rebinding a name to an expression that re-uses the original value, e.g. \ `let x = x + 1`"); +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. This lint is `Warn` by default. +/// +/// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = y; let x = z; // shadows the earlier binding` declare_lint!(pub SHADOW_UNRELATED, Allow, "The name is re-bound without even using the original value"); diff --git a/src/strings.rs b/src/strings.rs index 3c34e188d11..b567d949330 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -11,12 +11,38 @@ use eq_op::is_exp_equal; use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; +/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!) +/// +/// **Why is this bad?** Because this expression needs another copy as opposed to `x.push_str(y)` (in practice LLVM will usually elide it, though). Despite [llogiq](https://github.com/llogiq)'s reservations, this lint also is `allow` by default, as some people opine that it's more readable. +/// +/// **Known problems:** None. Well apart from the lint being `allow` by default. :smile: +/// +/// **Example:** +/// +/// ``` +/// let mut x = "Hello".to_owned(); +/// x = x + ", World"; +/// ``` declare_lint! { pub STRING_ADD_ASSIGN, Allow, "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" } +/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. It is `Allow` by default. +/// +/// **Why is this bad?** It's not bad in and of itself. However, this particular `Add` implementation is asymmetric (the other operand need not be `String`, but `x` does), while addition as mathematically defined is symmetric, also the `String::push_str(_)` function is a perfectly good replacement. Therefore some dislike it and wish not to have it in their code. +/// +/// That said, other people think that String addition, having a long tradition in other languages is actually fine, which is why we decided to make this particular lint `allow` by default. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let x = "Hello".to_owned(); +/// x + ", World" +/// ``` declare_lint! { pub STRING_ADD, Allow, diff --git a/src/types.rs b/src/types.rs index 506509cdfed..c505b612a8c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,8 +17,26 @@ use utils::{LL_PATH, VEC_PATH}; #[allow(missing_copy_implementations)] pub struct TypePass; +/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. +/// +/// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever. +/// +/// **Known problems:** None +/// +/// **Example:** `struct X { values: Box<Vec<Foo>> }` declare_lint!(pub BOX_VEC, Warn, "usage of `Box<Vec<T>>`, vector elements are already on the heap"); +/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or `RingBuf`. +/// +/// **Why is this bad?** Gankro says: +/// +/// >The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection. It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while "only" amortized for push/pop, should be faster in the general case for almost every possible workload, and isn't even amortized at all if you can predict the capacity you need. +/// > +/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists. This is because they can just mangle some pointers instead of actually copying the data. Even if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better because of how expensive it is to seek to the middle of a `LinkedList`. +/// +/// **Known problems:** False positives – the instances where using a `LinkedList` makes sense are few and far between, but they can still happen. +/// +/// **Example:** `let x = LinkedList::new();` declare_lint!(pub LINKEDLIST, Warn, "usage of LinkedList, usually a vector is faster, or a more specialized data \ structure like a VecDeque"); @@ -53,6 +71,13 @@ impl LateLintPass for TypePass { #[allow(missing_copy_implementations)] pub struct LetPass; +/// **What it does:** This lint checks for binding a unit value. It is `Warn` by default. +/// +/// **Why is this bad?** A unit value cannot usefully be used anywhere. So binding one is kind of pointless. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = { 1; };` declare_lint!(pub LET_UNIT_VALUE, Warn, "creating a let binding to a value of unit type, which usually can't be used afterwards"); @@ -82,6 +107,13 @@ impl LateLintPass for LetPass { } } +/// **What it does:** This lint checks for comparisons to unit. It is `Warn` by default. +/// +/// **Why is this bad?** Unit is always equal to itself, and thus is just a clumsily written constant. Mostly this happens when someone accidentally adds semicolons at the end of the operands. +/// +/// **Known problems:** None +/// +/// **Example:** `if { foo(); } == { bar(); } { baz(); }` is equal to `{ foo(); bar(); baz(); }` declare_lint!(pub UNIT_CMP, Warn, "comparing unit values (which is always `true` or `false`, respectively)"); @@ -115,12 +147,42 @@ impl LateLintPass for UnitCmp { pub struct CastPass; +/// **What it does:** This lint checks for casts from any numerical to a float type where the receiving type cannot store all values from the original type without rounding errors. This possible rounding is to be expected, so this lint is `Allow` by default. +/// +/// Basically, this warns on casting any integer with 32 or more bits to `f32` or any 64-bit integer to `f64`. +/// +/// **Why is this bad?** It's not bad at all. But in some applications it can be helpful to know where precision loss can take place. This lint can help find those places in the code. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = u64::MAX; x as f64` declare_lint!(pub CAST_PRECISION_LOSS, Allow, "casts that cause loss of precision, e.g `x as f32` where `x: u64`"); +/// **What it does:** This lint checks for casts from a signed to an unsigned numerical type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default. +/// +/// **Why is this bad?** Possibly surprising results. You can activate this lint as a one-time check to see where numerical wrapping can arise. +/// +/// **Known problems:** None +/// +/// **Example:** `let y : i8 = -1; y as u64` will return 18446744073709551615 declare_lint!(pub CAST_SIGN_LOSS, Allow, "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"); +/// **What it does:** This lint checks for on casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by default. +/// +/// **Why is this bad?** In some problem domains, it is good practice to avoid truncation. This lint can be activated to help assess where additional checks could be beneficial. +/// +/// **Known problems:** None +/// +/// **Example:** `fn as_u8(x: u64) -> u8 { x as u8 }` declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); +/// **What it does:** This lint checks for casts from an unsigned type to a signed type of the same size. Performing such a cast is a 'no-op' for the compiler, i.e. nothing is changed at the bit level, and the binary representation of the value is reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default. +/// +/// **Why is this bad?** While such a cast is not bad in itself, the results can be surprising when this is not the intended behavior, as demonstrated by the example below. +/// +/// **Known problems:** None +/// +/// **Example:** `u32::MAX as i32` will yield a value of `-1`. declare_lint!(pub CAST_POSSIBLE_WRAP, Allow, "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`"); @@ -262,6 +324,13 @@ impl LateLintPass for CastPass { } } +/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. It is `Warn` by default. +/// +/// **Why is this bad?** Too complex types make the code less readable. Consider using a `type` definition to simplify them. +/// +/// **Known problems:** None +/// +/// **Example:** `struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }` declare_lint!(pub TYPE_COMPLEXITY, Warn, "usage of very complex types; recommends factoring out parts into `type` definitions"); diff --git a/src/unicode.rs b/src/unicode.rs index 3855fafe7be..a5b03087604 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -8,11 +8,32 @@ use unicode_normalization::UnicodeNormalization; use utils::{snippet, span_help_and_lint}; +/// **What it does:** This lint checks for the unicode zero-width space in the code. It is `Warn` by default. +/// +/// **Why is this bad?** Having an invisible character in the code makes for all sorts of April fools, but otherwise is very much frowned upon. +/// +/// **Known problems:** None +/// +/// **Example:** You don't see it, but there may be a zero-width space somewhere in this text. declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "using a zero-width space in a string literal, which is confusing" } +/// **What it does:** This lint checks for non-ascii characters in string literals. It is `Allow` by default. +/// +/// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = "Hä?"` declare_lint!{ pub NON_ASCII_LITERAL, Allow, "using any literal non-ASCII chars in a string literal; suggests \ using the \\u escape instead" } +/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). This lint is `Allow` by default. +/// +/// **Why is this bad?** If such a string is compared to another, the results may be surprising. +/// +/// **Known problems** None +/// +/// **Example:** You may not see it, but "à" and "à" aren't the same string. The former when escaped is actually "a\u{300}" while the latter is "\u{e0}". declare_lint!{ pub UNICODE_NOT_NFC, Allow, "using a unicode literal not in NFC normal form (see \ http://www.unicode.org/reports/tr15/ for further information)" } diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 484348c5a37..c4d7cf4a589 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -9,6 +9,13 @@ use consts::{Constant, constant_simple, FloatWidth}; /// 0.0/0.0 with std::f32::NaN or std::f64::NaN, depending on the precision. pub struct ZeroDivZeroPass; +/// **What it does:** This lint checks for `0.0 / 0.0` +/// +/// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN` +/// +/// **Known problems:** None +/// +/// **Example** `0.0f32 / 0.0` declare_lint!(pub ZERO_DIVIDED_BY_ZERO, Warn, "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN"); diff --git a/util/update_wiki.py b/util/update_wiki.py new file mode 100755 index 00000000000..96333c1e4b3 --- /dev/null +++ b/util/update_wiki.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# Generate the wiki Home.md page from the contained doc comments +# requires the checked out wiki in ../rust-clippy.wiki/ +# with -c option, print a warning and set exit status 1 if the file would be changed. +import os, re, sys + +def parse_path(p="src"): + d = {} + for f in os.listdir(p): + if f.endswith(".rs"): + parse_file(d, os.path.join(p, f)) + return d + +START = 0 +LINT = 1 + +def parse_file(d, f): + last_comment = [] + comment = True + lint = None + + with open(f) as rs: + for line in rs: + if comment: + if line.startswith("///"): + if line.startswith("/// "): + last_comment.append(line[4:]) + else: + last_comment.append(line[3:]) + elif line.startswith("declare_lint!"): + comment = False + else: + last_comment = [] + if not comment: + l = line.strip() + m = re.search(r"pub\s+([A-Z_]+)", l) + if m: + print "found %s in %s" % (m.group(1).lower(), f) + d[m.group(1).lower()] = last_comment + last_comment = [] + comment = True + if "}" in l: + print "Warning: Missing Lint-Name in", f + comment = True + +PREFIX = """Welcome to the rust-clippy wiki! + +Here we aim to collect further explanations on the lints clippy provides. So without further ado: + +""" + +WARNING = """ +# A word of warning + +Clippy works as a *plugin* to the compiler, which means using an unstable internal API. We have gotten quite good at keeping pace with the API evolution, but the consequence is that clippy absolutely needs to be compiled with the version of `rustc` it will run on, otherwise you will get strange errors of missing symbols.""" + +def write_wiki_page(d, f): + keys = d.keys() + keys.sort() + with open(f, "w") as w: + w.write(PREFIX) + for k in keys: + w.write("[`%s`](#%s)\n" % (k, k)) + w.write(WARNING) + for k in keys: + w.write("\n# `%s`\n\n%s" % (k, "".join(d[k]))) + +def check_wiki_page(d, f): + errors = [] + with open(f) as w: + for line in w: + m = re.match("# `([a-z_]+)`", line) + if m: + v = d.pop(m.group(1), "()") + if v == "()": + errors.append("Missing wiki entry: " + m.group(1)) + keys = d.keys() + keys.sort() + for k in keys: + errors.append("Spurious wiki entry: " + k) + if errors: + print "\n".join(errors) + sys.exit(1) + +if __name__ == "__main__": + d = parse_path() + if "-c" in sys.argv: + check_wiki_page(d, "../rust-clippy.wiki/Home.md") + else: + write_wiki_page(d, "../rust-clippy.wiki/Home.md") -- cgit 1.4.1-3-g733a5 From 974ab43453514d85bc0bb3ffa4ee44f0b0e6204e Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Fri, 11 Dec 2015 16:28:05 +0900 Subject: Use suggestion for needless_return --- src/returns.rs | 17 +++++++++++------ tests/compile-fail/needless_return.rs | 12 +++++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/returns.rs b/src/returns.rs index 3df4efd0889..7347558b3a7 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_lint, snippet, match_path_ast, in_external_macro}; +use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); @@ -23,7 +23,7 @@ impl ReturnPass { } else if let Some(stmt) = block.stmts.last() { if let StmtSemi(ref expr, _) = stmt.node { if let ExprRet(Some(ref inner)) = expr.node { - self.emit_return_lint(cx, (expr.span, inner.span)); + self.emit_return_lint(cx, (stmt.span, inner.span)); } } } @@ -59,10 +59,15 @@ impl ReturnPass { fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { if in_external_macro(cx, spans.1) {return;} - span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( - "unneeded return statement. Consider using `{}` \ - without the return and trailing semicolon", - snippet(cx, spans.1, ".."))) + span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, + "unneeded return statement", + || { + if let Some(snippet) = snippet_opt(cx, spans.1) { + cx.sess().span_suggestion(spans.0, + "remove `return` as shown:", + snippet); + } + }); } // Check for "let x = EXPR; x" diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs index e0012942906..fe29d991661 100644 --- a/tests/compile-fail/needless_return.rs +++ b/tests/compile-fail/needless_return.rs @@ -8,11 +8,17 @@ fn test_end_of_fn() -> bool { // no error! return true; } - return true; //~ERROR unneeded return statement + return true; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION true } fn test_no_semicolon() -> bool { - return true //~ERROR unneeded return statement + return true + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION true } fn test_if_block() -> bool { @@ -29,7 +35,7 @@ fn test_match(x: bool) -> bool { return false; //~ERROR unneeded return statement } false => { - return true //~ERROR unneeded return statement + return true; //~ERROR unneeded return statement } } } -- cgit 1.4.1-3-g733a5 From 8e59be318c73d33adf99a76a48ebd0f655b97968 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros <cesarb@cesarb.eti.br> Date: Sat, 12 Dec 2015 20:05:06 -0200 Subject: Mention VecDeque in linkedlist lint I couldn't find anything named RingBuf in the standard library. Some search revealed that it had been renamed to VecDeque before the first stable Rust release. --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index c505b612a8c..9bc50643259 100644 --- a/src/types.rs +++ b/src/types.rs @@ -26,7 +26,7 @@ pub struct TypePass; /// **Example:** `struct X { values: Box<Vec<Foo>> }` declare_lint!(pub BOX_VEC, Warn, "usage of `Box<Vec<T>>`, vector elements are already on the heap"); -/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or `RingBuf`. +/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). /// /// **Why is this bad?** Gankro says: /// -- cgit 1.4.1-3-g733a5 From 4ae43b10f0b48bca95efa6dd830bb7281f52f05e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 13 Dec 2015 09:08:58 +0530 Subject: Add wiki note for escape analysis --- src/escape.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/escape.rs b/src/escape.rs index fbd545acc96..1df19bcf548 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -14,6 +14,20 @@ use utils::span_lint; pub struct EscapePass; +/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine +/// +/// **Why is this bad?** This is an unnecessary allocation, and bad for performance +/// +/// It is only necessary to allocate if you wish to move the box into something. +/// +/// **Example:** +/// +/// ```rust +/// fn main() { +/// let x = Box::new(1); +/// foo(*x); +/// println!("{}", *x); +/// } declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); struct EscapeDelegate<'a, 'tcx: 'a> { -- cgit 1.4.1-3-g733a5 From 6482840bc55055bc1597ae2aa7ed0f6abdad30fa Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 10 Dec 2015 12:54:43 -0800 Subject: Add tests --- tests/compile-fail/used_underscore_binding.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/compile-fail/used_underscore_binding.rs diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs new file mode 100644 index 00000000000..8c7fe4e0069 --- /dev/null +++ b/tests/compile-fail/used_underscore_binding.rs @@ -0,0 +1,22 @@ +#![feature(plugin)] +#![plugin(clippy)] +#[deny(used_underscore_binding)] + +fn main() { + let foo = 0u32; + prefix_underscore(foo); //should fail + non_prefix_underscore(foo); //should pass + unused_underscore(foo); //should pass +} + +fn prefix_underscore(_x: u32){ + println!("{}", _x + 1); //~Error: Used binding which is prefixed with an underscore +} + +fn non_prefix_underscore(some_foo: u32) { + println!("{}", some_foo + 1); +} + +fn unused_underscore(_foo: u32) { + println!("{}", 1); +} -- cgit 1.4.1-3-g733a5 From 9de308ee1538ed35988dc6bcb0fd2faf43129133 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 11 Dec 2015 14:02:02 -0800 Subject: Add used_underscore_binding lint --- src/misc.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/misc.rs b/src/misc.rs index b5c3d0c514f..7068aac781e 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -9,6 +9,7 @@ use rustc::middle::ty; use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::def::Def; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use utils::span_help_and_lint; @@ -316,3 +317,36 @@ impl LateLintPass for PatternPass { } } } + +declare_lint!(pub USED_UNDERSCORE_BINDING, Warn, + "using a binding which is prefixed with an underscore"); + +#[derive(Copy, Clone)] +pub struct UsedUnderscoreBinding; + +impl LintPass for UsedUnderscoreBinding { + fn get_lints(&self) -> LintArray { + lint_array!(USED_UNDERSCORE_BINDING) + } +} + +impl LateLintPass for UsedUnderscoreBinding { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + let needs_lint = match expr.node { + ExprPath(_, ref path) => { + path.segments.last().unwrap().identifier.name.as_str().chars().next() == Some('_') && + (cx.tcx.def_map.borrow()).values().any(|res| match res.base_def { + Def::DefLocal(_, _) => true, + _ => false + }) + }, + ExprField(_, spanned) => spanned.node.as_str().chars().next() == Some('_'), + _ => false + }; + if needs_lint { + cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, &format!( + "Used binding which is prefixed with an underscore. A leading underscore signals\ + that a binding will not be used.")); + } + } +} -- cgit 1.4.1-3-g733a5 From 43b96d59ade2321bf55f2ee0f082b8f0b7080bfe Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 11 Dec 2015 15:08:59 -0800 Subject: Run update_lints.py --- README.md | 3 ++- src/lib.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e410002852..015a7d9adf2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 83 lints included in this crate: +There are 84 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -86,6 +86,7 @@ name [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions +[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator diff --git a/src/lib.rs b/src/lib.rs index 03e0cbea19c..05181e69b2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,6 +120,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); reg.register_late_lint_pass(box escape::EscapePass); reg.register_early_lint_pass(box misc_early::MiscEarly); + reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -184,6 +185,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + misc::USED_UNDERSCORE_BINDING, misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, -- cgit 1.4.1-3-g733a5 From 609111269818f99918980c85753d0d1bcea488c3 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sat, 12 Dec 2015 16:31:34 -0800 Subject: Update tests --- src/misc.rs | 2 +- tests/compile-fail/used_underscore_binding.rs | 32 +++++++++++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 7068aac781e..5c3aeeb7899 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -345,7 +345,7 @@ impl LateLintPass for UsedUnderscoreBinding { }; if needs_lint { cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, &format!( - "Used binding which is prefixed with an underscore. A leading underscore signals\ + "used binding which is prefixed with an underscore. A leading underscore signals\ that a binding will not be used.")); } } diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 8c7fe4e0069..adc20d67841 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -1,22 +1,30 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(used_underscore_binding)] +#![deny(clippy)] -fn main() { - let foo = 0u32; - prefix_underscore(foo); //should fail - non_prefix_underscore(foo); //should pass - unused_underscore(foo); //should pass +fn prefix_underscore(_x: u32) -> u32{ + _x + 1 //~ ERROR used binding which is prefixed with an underscore } -fn prefix_underscore(_x: u32){ - println!("{}", _x + 1); //~Error: Used binding which is prefixed with an underscore +fn in_macro(_x: u32) { + println!("{}", _x); //~ ERROR used binding which is prefixed with an underscore } -fn non_prefix_underscore(some_foo: u32) { - println!("{}", some_foo + 1); +fn non_prefix_underscore(some_foo: u32) -> u32 { + some_foo + 1 } -fn unused_underscore(_foo: u32) { - println!("{}", 1); +fn unused_underscore(_foo: u32) -> u32 { + 1 } + +fn main() { + let foo = 0u32; + // tests of unused_underscore lint + let _ = prefix_underscore(foo); + in_macro(foo); + // possible false positives + let _ = non_prefix_underscore(foo); + let _ = unused_underscore(foo); +} + -- cgit 1.4.1-3-g733a5 From aeb5a0e60cc7b61253fa486b4e3af4d537af7322 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sat, 12 Dec 2015 17:51:58 -0800 Subject: Reduce false positives Add macro checking, and only lint for single leading underscores --- src/misc.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 5c3aeeb7899..f46a26c10e1 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -334,19 +334,24 @@ impl LateLintPass for UsedUnderscoreBinding { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { let needs_lint = match expr.node { ExprPath(_, ref path) => { - path.segments.last().unwrap().identifier.name.as_str().chars().next() == Some('_') && - (cx.tcx.def_map.borrow()).values().any(|res| match res.base_def { + let ident = path.segments.last() + .expect("path should always have at least one segment") + .identifier; + ident.name.as_str().chars().next() == Some('_') //starts with '_' + && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" + && ident.name != ident.unhygienic_name //not in macro + && cx.tcx.def_map.borrow().values().any(|res| match res.base_def { Def::DefLocal(_, _) => true, _ => false - }) + }) //local variable }, ExprField(_, spanned) => spanned.node.as_str().chars().next() == Some('_'), _ => false }; if needs_lint { - cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, &format!( - "used binding which is prefixed with an underscore. A leading underscore signals\ - that a binding will not be used.")); + cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, + "used binding which is prefixed with an underscore. A leading underscore\ + signals that a binding will not be used."); } } } -- cgit 1.4.1-3-g733a5 From 92fba6bd2c7c5b1a08ff1399ae8357e51399a1c0 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sat, 12 Dec 2015 21:35:35 -0800 Subject: Make clippy tests compatible with new lint --- tests/compile-fail/for_loop.rs | 3 ++- tests/compile-fail/range.rs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 7a18c210d0c..59b77f6421b 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -16,7 +16,8 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity)] +#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity, + used_underscore_binding)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; diff --git a/tests/compile-fail/range.rs b/tests/compile-fail/range.rs index 2d731670cbe..064d9f55173 100644 --- a/tests/compile-fail/range.rs +++ b/tests/compile-fail/range.rs @@ -22,8 +22,8 @@ fn main() { let y = NotARange; y.step_by(0); - let _v1 = vec![1,2,3]; - let _v2 = vec![4,5]; - let _x = _v1.iter().zip(0.._v1.len()); //~ERROR It is more idiomatic to use _v1.iter().enumerate() - let _y = _v1.iter().zip(0.._v2.len()); // No error + let v1 = vec![1,2,3]; + let v2 = vec![4,5]; + let _x = v1.iter().zip(0..v1.len()); //~ERROR It is more idiomatic to use v1.iter().enumerate() + let _y = v1.iter().zip(0..v2.len()); // No error } -- cgit 1.4.1-3-g733a5 From b24e3aeea038cb207f28f868a6af1e36897d0e5b Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sat, 12 Dec 2015 21:50:36 -0800 Subject: Add wiki docs, in line with #492 --- src/misc.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/misc.rs b/src/misc.rs index f46a26c10e1..2558d6bb4bb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -318,6 +318,29 @@ impl LateLintPass for PatternPass { } } + +/// **What it does:** This lint checks for the use of bindings with a single leading underscore +/// +/// **Why is this bad?** A single leading underscore is usually used to indicate that a binding +/// will not be used. Using such a binding breaks this expectation. +/// +/// **Known problems:** This lint's idea of a "used" variable is not quite the same as in the +/// built-in `unused_variables` lint. For example, in the following code +/// ``` +/// fn foo(_y: u32) -> u32) { +/// let _x = 1; +/// _x +=1; +/// y +/// } +/// ``` +/// _x will trigger both the `unused_variables` lint and the `used_underscore_binding` lint. +/// +/// **Example**: +/// ``` +/// let _x = 0; +/// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore. +/// // We should rename `_x` to `x` +/// ``` declare_lint!(pub USED_UNDERSCORE_BINDING, Warn, "using a binding which is prefixed with an underscore"); -- cgit 1.4.1-3-g733a5 From 6960bf2ebc711385048834863eda081bae2633db Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sat, 12 Dec 2015 21:59:25 -0800 Subject: Make ExprField follow single-underscore rules --- src/misc.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 2558d6bb4bb..89b4dbb4de6 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -368,7 +368,11 @@ impl LateLintPass for UsedUnderscoreBinding { _ => false }) //local variable }, - ExprField(_, spanned) => spanned.node.as_str().chars().next() == Some('_'), + ExprField(_, spanned) => { + let name = spanned.node.as_str(); + name.chars().next() == Some('_') + && name.chars().skip(1).next() != Some('_') + }, _ => false }; if needs_lint { -- cgit 1.4.1-3-g733a5 From d7292fe235bc9d72c9c528e2c2bfc5d07ad7baa2 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 14 Dec 2015 08:03:01 +0100 Subject: more docs --- src/mutex_atomic.rs | 14 ++++++++++++++ src/transmute.rs | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index e6d1fc8a888..40f7d21f43c 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -11,12 +11,26 @@ use rustc::middle::subst::ParamSpace; use utils::{span_lint, MUTEX_PATH, match_type}; +/// **What it does:** It `Warn`s on usages of `Mutex<X>` where an atomic will do +/// +/// **Why is this bad?** Using a Mutex just to make access to a plain bool or reference sequential is shooting flies with cannons. `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and faster. +/// +/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. +/// +/// **Example:** `let x = Mutex::new(&y);` declare_lint! { pub MUTEX_ATOMIC, Warn, "using a Mutex where an atomic value could be used instead" } +/// **What it does:** It `Warn`s on usages of `Mutex<X>` where `X` is an integral type. +/// +/// **Why is this bad?** Using a Mutex just to make access to a plain integer sequential is shooting flies with cannons. `std::atomic::usize` is leaner and faster. +/// +/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. +/// +/// **Example:** `let x = Mutex::new(0usize);` declare_lint! { pub MUTEX_INTEGER, Allow, diff --git a/src/transmute.rs b/src/transmute.rs index ab1397ea7fe..c71468bf5a0 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -2,6 +2,13 @@ use rustc::lint::*; use rustc_front::hir::*; use utils; +/// **What it does:** This lint checks for transmutes to the original type of the object. It is `Warn` by default. +/// +/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type. +/// +/// **Known problems:** None. +/// +/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `t`'s. declare_lint! { pub USELESS_TRANSMUTE, Warn, -- cgit 1.4.1-3-g733a5 From ecb97866b6be1e3ff22a5ced3b8d573314dc795e Mon Sep 17 00:00:00 2001 From: Oliver Schneider <github333195615777966@oli-obk.de> Date: Mon, 14 Dec 2015 11:28:22 +0100 Subject: compiletest_rs needs to be at least 0.0.11 otherwise tests using `SUGGESTION` will fail (see `compile-fail/eta.rs`) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c70e43ed78d..832a6dff401 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ plugin = true unicode-normalization = "*" [dev-dependencies] -compiletest_rs = "*" +compiletest_rs = "0.0.11" regex = "*" regex_macros = "*" lazy_static = "*" -- cgit 1.4.1-3-g733a5 From c0bccc95670fc3891c1991f22815ef9a6f043850 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 14 Dec 2015 13:31:28 +0100 Subject: more doc comments --- src/block_in_if_condition.rs | 14 ++++++++++++++ src/map_clone.rs | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 39196ed175f..b4e81ac6a2b 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -3,11 +3,25 @@ use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; use rustc_front::intravisit::{Visitor, walk_expr}; use utils::*; +/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. +/// +/// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions. +/// +/// **Known problems:** None +/// +/// **Example:** `if { true } ..` declare_lint! { pub BLOCK_IN_IF_CONDITION_EXPR, Warn, "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" } +/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. +/// +/// **Why is this bad?** Using blocks in the condition makes it hard to read. +/// +/// **Known problems:** None +/// +/// **Example:** `if { let x = somefunc(); x } ..` or `if somefunc(|x| { x == 47 }) ..` declare_lint! { pub BLOCK_IN_IF_CONDITION_STMT, Warn, "avoid complex blocks in conditions, instead move the block higher and bind it \ diff --git a/src/map_clone.rs b/src/map_clone.rs index d9719df0b6f..f5e8d20a745 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -4,6 +4,13 @@ use utils::{CLONE_PATH, OPTION_PATH}; use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint}; use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; +/// **What it does:** This lint checks for mapping clone() over an iterator. It is `Warn` by default and suggests to use `.cloned()` instead. +/// +/// **Why is this bad?** It makes the code less readable. +/// +/// **Known problems:** False negative: The lint currently misses mapping `Clone::clone` directly. Issue #436 is tracking this. +/// +/// **Example:** `x.map(|e| e.clone());` declare_lint!(pub MAP_CLONE, Warn, "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ `.cloned()` instead)"); -- cgit 1.4.1-3-g733a5 From 902c7d832b6f355414632ca55dc7c7017fde5250 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Dec 2015 14:29:20 +0100 Subject: fix cc computation in the presence of diverging calls CFG treats diverging calls as its completely own path out of the function. While this makes sense, it should also mean that a panic should increase the cyclomatic complexity. Instead it decreases it. Minimal example: ```rust if a { b } else { panic!("cake"); } d ``` creates the following graph ```dot digraph G { "if a" -> "b" "if a" -> "panic!(\"cake\")" "b" -> c } ``` which has a CC of 1 (3 - 4 + 2). A CC of 1 means there is one path through the program. Obviously that is wrong. There are two paths. One returning normally, and one panicking. --- src/cyclomatic_complexity.rs | 52 +++++++++---- tests/cc_seme.rs | 25 +++++++ tests/compile-fail/cyclomatic_complexity.rs | 110 +++++++++++++++++++++++++++- 3 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 tests/cc_seme.rs diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 1379a8db15d..cb391769279 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -3,6 +3,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc::middle::cfg::CFG; +use rustc::middle::ty; use syntax::codemap::Span; use syntax::attr::*; use syntax::ast::Attribute; @@ -32,7 +33,7 @@ impl LintPass for CyclomaticComplexity { } impl CyclomaticComplexity { - fn check(&mut self, cx: &LateContext, block: &Block, span: Span) { + fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) { if in_macro(cx, span) { return; } let cfg = CFG::new(cx.tcx, block); let n = cfg.graph.len_nodes() as u64; @@ -40,15 +41,16 @@ impl CyclomaticComplexity { let cc = e + 2 - n; let mut arm_counter = MatchArmCounter(0); arm_counter.visit_block(block); - let mut narms = arm_counter.0; - if narms > 0 { - narms = narms - 1; - } - - if cc < narms { - report_cc_bug(cx, cc, narms, span); + let narms = arm_counter.0; + + let mut diverge_counter = DivergenceCounter(0, &cx.tcx); + diverge_counter.visit_block(block); + let divergence = diverge_counter.0; + + if cc + divergence < narms { + report_cc_bug(cx, cc, narms, divergence, span); } else { - let rust_cc = cc - narms; + let rust_cc = cc + divergence - narms; if rust_cc > self.limit.limit() { cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, &format!("The function has a cyclomatic complexity of {}.", rust_cc), @@ -93,8 +95,28 @@ impl<'a> Visitor<'a> for MatchArmCounter { ExprMatch(_, ref arms, _) => { walk_expr(self, e); let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); - if arms_n > 0 { - self.0 += arms_n - 1; + if arms_n > 1 { + self.0 += arms_n - 2; + } + }, + ExprClosure(..) => {}, + _ => walk_expr(self, e), + } + } +} + +struct DivergenceCounter<'a, 'tcx: 'a>(u64, &'a ty::ctxt<'tcx>); + +impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> { + fn visit_expr(&mut self, e: &'a Expr) { + match e.node { + ExprCall(ref callee, _) => { + walk_expr(self, e); + let ty = self.1.node_id_to_type(callee.id); + if let ty::TyBareFn(_, ty) = ty.sty { + if ty.sig.skip_binder().output.diverges() { + self.0 += 1; + } } }, ExprClosure(..) => {}, @@ -104,15 +126,15 @@ impl<'a> Visitor<'a> for MatchArmCounter { } #[cfg(feature="debugging")] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, span: Span) { +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { cx.sess().span_bug(span, &format!("Clippy encountered a bug calculating cyclomatic complexity: \ - cc = {}, arms = {}. Please file a bug report.", cc, narms));; + cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div));; } #[cfg(not(feature="debugging"))] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, span: Span) { +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { cx.sess().span_note(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ (hide this message with `#[allow(cyclomatic_complexity)]`): \ - cc = {}, arms = {}. Please file a bug report.", cc, narms)); + cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div)); } } diff --git a/tests/cc_seme.rs b/tests/cc_seme.rs new file mode 100644 index 00000000000..a26731c396a --- /dev/null +++ b/tests/cc_seme.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[allow(dead_code)] +enum Baz { + Baz1, + Baz2, +} + +struct Test { + t: Option<usize>, + b: Baz, +} + +fn main() { + use Baz::*; + let x = Test { t: Some(0), b: Baz1 }; + + match x { + Test { t: Some(_), b: Baz1 } => unreachable!(), + Test { t: Some(42), b: Baz2 } => unreachable!(), + Test { t: None, .. } => unreachable!(), + Test { .. } => unreachable!(), + } +} diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 8e3bf123c26..1a6dfd28728 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -89,7 +89,7 @@ fn main() { //~ ERROR: The function has a cyclomatic complexity of 28. } #[cyclomatic_complexity = "0"] -fn kaboom() { //~ ERROR: The function has a cyclomatic complexity of 6 +fn kaboom() { //~ ERROR: The function has a cyclomatic complexity of 8 let n = 0; 'a: for i in 0..20 { 'b: for j in i..20 { @@ -170,6 +170,114 @@ fn barr() { //~ ERROR: The function has a cyclomatic complexity of 2 } } +#[cyclomatic_complexity = "0"] +fn barr2() { //~ ERROR: The function has a cyclomatic complexity of 3 + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn barrr() { //~ ERROR: The function has a cyclomatic complexity of 2 + match 99 { + 0 => println!("hi"), + 1 => panic!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn barrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 + match 99 { + 0 => println!("hi"), + 1 => panic!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } + match 99 { + 0 => println!("hi"), + 1 => panic!("bla"), + 2 | 3 => println!("blub"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn barrrr() { //~ ERROR: The function has a cyclomatic complexity of 2 + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => panic!("blub"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn barrrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => panic!("blub"), + _ => println!("bye"), + } + match 99 { + 0 => println!("hi"), + 1 => println!("bla"), + 2 | 3 => panic!("blub"), + _ => println!("bye"), + } +} + +#[cyclomatic_complexity = "0"] +fn cake() { //~ ERROR: The function has a cyclomatic complexity of 2 + if 4 == 5 { + println!("yea"); + } else { + panic!("meh"); + } + println!("whee"); +} + + +#[cyclomatic_complexity = "0"] +pub fn read_file(input_path: &str) -> String { //~ ERROR: The function has a cyclomatic complexity of 4 + use std::fs::File; + use std::io::{Read, Write}; + use std::path::Path; + let mut file = match File::open(&Path::new(input_path)) { + Ok(f) => f, + Err(err) => { + panic!("Can't open {}: {}", input_path, err); + } + }; + + let mut bytes = Vec::new(); + + match file.read_to_end(&mut bytes) { + Ok(..) => {}, + Err(_) => { + panic!("Can't read {}", input_path); + } + }; + + match String::from_utf8(bytes) { + Ok(contents) => contents, + Err(_) => { + panic!("{} is not UTF-8 encoded", input_path); + } + } +} + enum Void {} #[cyclomatic_complexity = "0"] -- cgit 1.4.1-3-g733a5 From cc1d696cb9df64b1da9aeebcc47717d84ec649f8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Dec 2015 14:30:09 +0100 Subject: fix fallout from CC improvements --- src/loops.rs | 27 +++++++++++---------------- src/matches.rs | 12 +++++------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 3c4e023b98e..8295e186172 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -147,14 +147,8 @@ impl LateLintPass for LoopsPass { // extract the expression from the first statement (if any) in a block let inner_stmt_expr = extract_expr_from_first_stmt(block); - // extract the first expression (if any) from the block - let inner_expr = extract_first_expr(block); - let (extracted, collect_expr) = match inner_stmt_expr { - Some(_) => (inner_stmt_expr, true), // check if an expression exists in the first statement - None => (inner_expr, false), // if not, let's go for the first expression in the block - }; - - if let Some(inner) = extracted { + // or extract the first expression (if any) from the block + if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // collect the remaining statements below the match let mut other_stuff = block.stmts @@ -163,10 +157,11 @@ impl LateLintPass for LoopsPass { .map(|stmt| { format!("{}", snippet(cx, stmt.span, "..")) }).collect::<Vec<String>>(); - if collect_expr { // if we have a statement which has a match, - match block.expr { // then collect the expression (without semicolon) below it - Some(ref expr) => other_stuff.push(format!("{}", snippet(cx, expr.span, ".."))), - None => (), + if inner_stmt_expr.is_some() { + // if we have a statement which has a match, + if let Some(ref expr) = block.expr { + // then collect the expression (without semicolon) below it + other_stuff.push(format!("{}", snippet(cx, expr.span, ".."))); } } @@ -180,12 +175,12 @@ impl LateLintPass for LoopsPass { is_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { return; } - let loop_body = match inner_stmt_expr { + let loop_body = if inner_stmt_expr.is_some() { // FIXME: should probably be an ellipsis // tabbing and newline is probably a bad idea, especially for large blocks - Some(_) => Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))), - None => expr_block(cx, &arms[0].body, - Some(other_stuff.join("\n ")), ".."), + Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))) + } else { + expr_block(cx, &arms[0].body, Some(other_stuff.join("\n ")), "..") }; span_help_and_lint(cx, WHILE_LET_LOOP, expr.span, "this loop could be written as a `while let` loop", diff --git a/src/matches.rs b/src/matches.rs index 39459bafba7..460893d93ab 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -102,13 +102,11 @@ impl LateLintPass for MatchPass { if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { - if let LitBool(val) = lit.node { - if val { - Some((&*arms[0].body, &*arms[1].body)) - } else { - Some((&*arms[1].body, &*arms[0].body)) - } - } else { None } + match lit.node { + LitBool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitBool(false) => Some((&*arms[1].body, &*arms[0].body)), + _ => None, + } } else { None } } else { None }; if let Some((ref true_expr, ref false_expr)) = exprs { -- cgit 1.4.1-3-g733a5 From 827082ac41a7f05fe6b974523a54977100fda6b6 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 14 Dec 2015 21:17:11 +0100 Subject: fix boxed_local example --- src/escape.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/escape.rs b/src/escape.rs index 1df19bcf548..63894cda9be 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -28,6 +28,7 @@ pub struct EscapePass; /// foo(*x); /// println!("{}", *x); /// } +/// ``` declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); struct EscapeDelegate<'a, 'tcx: 'a> { -- cgit 1.4.1-3-g733a5 From c645a9febe4451bec13eda67fb808f3471d5d00f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 14 Dec 2015 22:16:56 +0100 Subject: adding missing doc comments --- src/cyclomatic_complexity.rs | 7 +++++++ src/lifetimes.rs | 7 +++++++ src/loops.rs | 7 +++++++ src/methods.rs | 30 ++++++++++++++++++++++++++++++ src/misc_early.rs | 7 +++++++ src/needless_features.rs | 14 ++++++++++++++ src/needless_update.rs | 7 +++++++ src/no_effect.rs | 7 +++++++ src/temporary_assignment.rs | 7 +++++++ 9 files changed, 93 insertions(+) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index cb391769279..c2cc6a8c4ab 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -11,6 +11,13 @@ use rustc_front::intravisit::{Visitor, walk_expr}; use utils::{in_macro, LimitStack}; +/// **What it does:** It `Warn`s on methods with high cyclomatic complexity +/// +/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better. +/// +/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity +/// +/// **Example:** No. You'll see it when you get the warning. declare_lint! { pub CYCLOMATIC_COMPLEXITY, Warn, "finds functions that should be split up into multiple functions" } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 743dc366e44..6ae10c09455 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -19,6 +19,13 @@ declare_lint!(pub NEEDLESS_LIFETIMES, Warn, "using explicit lifetimes for references in function arguments when elision rules \ would allow omitting them"); +/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. It is `Warn` by default. +/// +/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. +/// +/// **Known problems:** None +/// +/// **Example:** `fn unused_lifetime<'a>(x: u8) { .. }` declare_lint!(pub UNUSED_LIFETIMES, Warn, "unused lifetimes in function definitions"); diff --git a/src/loops.rs b/src/loops.rs index 8295e186172..5c552d2ce42 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -114,6 +114,13 @@ declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, /// **Example:** `loop {}` declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } +/// **What it does:** This lint checks for `while let` expressions on iterators. It is `Warn` by default. +/// +/// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys the intent better. +/// +/// **Known problems:** None +/// +/// **Example:** `while let Some(val) = iter() { .. }` declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" } #[derive(Copy, Clone)] diff --git a/src/methods.rs b/src/methods.rs index 6c629f29c41..ef7a58959ac 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -24,6 +24,7 @@ pub struct MethodsPass; /// **Example:** `x.unwrap()` declare_lint!(pub OPTION_UNWRAP_USED, Allow, "using `Option.unwrap()`, which should at least get a better message using `expect()`"); + /// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. It is `Allow` by default. /// /// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`. @@ -35,6 +36,7 @@ declare_lint!(pub OPTION_UNWRAP_USED, Allow, /// **Example:** `x.unwrap()` declare_lint!(pub RESULT_UNWRAP_USED, Allow, "using `Result.unwrap()`, which might be better handled"); + /// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. It is `Warn` by default. /// /// **Why is this bad?** This uses the whole formatting machinery just to clone a string. Using `.to_owned()` is lighter on resources. You can also consider using a [`Cow<'a, str>`](http://doc.rust-lang.org/std/borrow/enum.Cow.html) instead in some cases. @@ -44,6 +46,7 @@ declare_lint!(pub RESULT_UNWRAP_USED, Allow, /// **Example:** `s.to_string()` where `s: &str` declare_lint!(pub STR_TO_STRING, Warn, "using `to_string()` on a str, which should be `to_owned()`"); + /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default. /// /// **Why is this bad?** As our string is already owned, this whole operation is basically a no-op, but still creates a clone of the string (which, if really wanted, should be done with `.clone()`). @@ -53,6 +56,7 @@ declare_lint!(pub STR_TO_STRING, Warn, /// **Example:** `s.to_string()` where `s: String` declare_lint!(pub STRING_TO_STRING, Warn, "calling `String.to_string()` which is a no-op"); + /// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default. /// /// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. @@ -68,6 +72,7 @@ declare_lint!(pub STRING_TO_STRING, Warn, /// ``` declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, "defining a method that should be implementing a std trait"); + /// **What it does:** This lint checks for methods with certain name prefixes and `Warn`s (by default) if the prefix doesn't match how self is taken. The actual rules are: /// /// |Prefix |`self` taken | @@ -92,6 +97,7 @@ declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, declare_lint!(pub WRONG_SELF_CONVENTION, Warn, "defining a method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); + /// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. This lint is `Allow` by default. /// /// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). @@ -107,12 +113,36 @@ declare_lint!(pub WRONG_SELF_CONVENTION, Warn, declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, "defining a public method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention"); + +/// **What it does:** This lint `Warn`s on using `ok().expect(..)`. +/// +/// **Why is this bad?** Because you usually call `expect()` on the `Result` directly to get a good error message. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.ok().expect("why did I do this again?")` declare_lint!(pub OK_EXPECT, Warn, "using `ok().expect()`, which gives worse error messages than \ calling `expect` directly on the Result"); + +/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.map(|a| a + 1).unwrap_or(0)` declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ `map_or(a, f)`)"); + +/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or_else(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)` declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ `map_or_else(g, f)`)"); diff --git a/src/misc_early.rs b/src/misc_early.rs index 8adff752337..1520e9c0e58 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -6,6 +6,13 @@ use syntax::ast::*; use utils::span_lint; +/// **What it does:** This lint `Warn`s on struct field patterns bound to wildcards. +/// +/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound. +/// +/// **Known problems:** None. +/// +/// **Example:** `let { a: _, b: ref b, c: _ } = ..` declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn, "Struct fields are bound to a wildcard instead of using `..`"); diff --git a/src/needless_features.rs b/src/needless_features.rs index 44db5e92221..2dd53c2d783 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -8,6 +8,13 @@ use rustc_front::hir::*; use utils::span_lint; use utils; +/// **What it does:** This lint `Warn`s on use of the `as_slice(..)` function, which is unstable. +/// +/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.as_slice(..)` declare_lint! { pub UNSTABLE_AS_SLICE, Warn, @@ -15,6 +22,13 @@ declare_lint! { see https://github.com/rust-lang/rust/issues/27729" } +/// **What it does:** This lint `Warn`s on use of the `as_mut_slice(..)` function, which is unstable. +/// +/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.as_mut_slice(..)` declare_lint! { pub UNSTABLE_AS_MUT_SLICE, Warn, diff --git a/src/needless_update.rs b/src/needless_update.rs index c65d0c9e7d3..e1e0f481848 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -4,6 +4,13 @@ use rustc_front::hir::{Expr, ExprStruct}; use utils::span_lint; +/// **What it does:** This lint `Warn`s on needlessly including a base struct on update when all fields are changed anyway. +/// +/// **Why is this bad?** This will cost resources (because the base has to be somewhere), and make the code less readable. +/// +/// **Known problems:** None. +/// +/// **Example:** `Point { x: 1, y: 0, ..zero_point }`` declare_lint! { pub NEEDLESS_UPDATE, Warn, diff --git a/src/no_effect.rs b/src/no_effect.rs index 82fcf92fd4c..b51b4235d54 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -6,6 +6,13 @@ use rustc_front::hir::{Stmt, StmtSemi}; use utils::in_macro; use utils::span_lint; +/// **What it does:** This lint `Warn`s on statements which have no effect. +/// +/// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable. +/// +/// **Known problems:** None. +/// +/// **Example:** `0;` declare_lint! { pub NO_EFFECT, Warn, diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index 6cfcb711ff7..622bf5bc25e 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -4,6 +4,13 @@ use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTup use utils::is_adjusted; use utils::span_lint; +/// **What it does:** This lint `Warn`s on creating a struct or tuple just to assign a value in it. +/// +/// **Why is this bad?** Readability. If the struct is only created to be updated, why not write the struct you want in the first place? +/// +/// **Known problems:** None. +/// +/// **Example:** `(0, 0).0 = 1` declare_lint! { pub TEMPORARY_ASSIGNMENT, Warn, -- cgit 1.4.1-3-g733a5 From dc9a08fc78147cdd3c08bcb843162945c1708536 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 14 Dec 2015 22:23:33 +0100 Subject: Add short section on lint docs --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eebea413f0d..5147595ab54 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,19 @@ contains some questionable code itself! Also before making a pull request, pleas `util/update_lints.py`, which will update `lib.rs` and `README.md` with the lint declarations. Our travis build actually checks for this. +Also please document your lint with a doc comment akin to the following: +``` +/// **What it does:** Describe what the lint matches. +/// +/// **Why is this bad?** Write the reason for linting the code. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** Insert a short example if you have one +``` + +Our `util/update_wiki.py` script can then add your ilnt docs to the wiki. + ## Contributions Clippy welcomes contributions from everyone. -- cgit 1.4.1-3-g733a5 From f3f5e3cb2512eda534788d849b93b760006c6332 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Wed, 16 Dec 2015 23:13:01 +0900 Subject: Don't dogfood twice --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 920aaf981f9..1029c67ee6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,3 @@ sudo: false script: - python util/update_lints.py -c - cargo test --features debugging - - bash util/dogfood.sh -- cgit 1.4.1-3-g733a5 From e620a1d57cb1a49b1c6e7e45c19f9102dc0876d3 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Wed, 16 Dec 2015 15:28:06 -0800 Subject: Make suggested changes --- src/misc.rs | 8 ++------ tests/compile-fail/used_underscore_binding.rs | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 89b4dbb4de6..3b093027f48 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -9,7 +9,6 @@ use rustc::middle::ty; use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::def::Def; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use utils::span_help_and_lint; @@ -327,7 +326,7 @@ impl LateLintPass for PatternPass { /// **Known problems:** This lint's idea of a "used" variable is not quite the same as in the /// built-in `unused_variables` lint. For example, in the following code /// ``` -/// fn foo(_y: u32) -> u32) { +/// fn foo(y: u32) -> u32) { /// let _x = 1; /// _x +=1; /// y @@ -363,10 +362,7 @@ impl LateLintPass for UsedUnderscoreBinding { ident.name.as_str().chars().next() == Some('_') //starts with '_' && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" && ident.name != ident.unhygienic_name //not in macro - && cx.tcx.def_map.borrow().values().any(|res| match res.base_def { - Def::DefLocal(_, _) => true, - _ => false - }) //local variable + && cx.tcx.def_map.borrow().contains_key(&expr.id) //local variable }, ExprField(_, spanned) => { let name = spanned.node.as_str(); diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index adc20d67841..5567f23a9ff 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(clippy)] -fn prefix_underscore(_x: u32) -> u32{ +fn prefix_underscore(_x: u32) -> u32 { _x + 1 //~ ERROR used binding which is prefixed with an underscore } -- cgit 1.4.1-3-g733a5 From 3533d3a22302269b90796a09f8baf292f6849c5d Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 17 Dec 2015 13:52:30 -0800 Subject: Add more tests --- tests/compile-fail/used_underscore_binding.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 5567f23a9ff..bc6b32807f3 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -2,22 +2,46 @@ #![plugin(clippy)] #![deny(clippy)] +/// Test that we lint if we use a binding with a single leading underscore fn prefix_underscore(_x: u32) -> u32 { _x + 1 //~ ERROR used binding which is prefixed with an underscore } +/// Test that we lint even if the use is within a macro expansion fn in_macro(_x: u32) { println!("{}", _x); //~ ERROR used binding which is prefixed with an underscore } +/// Test that we do not lint if the underscore is not a prefix fn non_prefix_underscore(some_foo: u32) -> u32 { some_foo + 1 } +/// Test that we do not lint if we do not use the binding fn unused_underscore(_foo: u32) -> u32 { 1 } +// Non-variable bindings with preceding underscore +fn _fn_test() {} +struct _StructTest; +enum _EnumTest { + _FieldA, + _FieldB(_StructTest) +} + +/// Test that we do not lint for non-variable bindings +fn non_variables() { + _fn_test(); + let _s = _StructTest; + let _e = match _EnumTest::_FieldB(_StructTest) { + _EnumTest::_FieldA => 0, + _EnumTest::_FieldB(_st) => 1, + }; + let f = _fn_test; + f(); +} + fn main() { let foo = 0u32; // tests of unused_underscore lint @@ -26,5 +50,6 @@ fn main() { // possible false positives let _ = non_prefix_underscore(foo); let _ = unused_underscore(foo); + non_variables(); } -- cgit 1.4.1-3-g733a5 From 02cb24de82e7dda49e7ae612a968de548c67b8f0 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 18 Dec 2015 13:45:03 -0800 Subject: Remove local variable check --- src/misc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/misc.rs b/src/misc.rs index 3b093027f48..9954e358232 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -362,7 +362,6 @@ impl LateLintPass for UsedUnderscoreBinding { ident.name.as_str().chars().next() == Some('_') //starts with '_' && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" && ident.name != ident.unhygienic_name //not in macro - && cx.tcx.def_map.borrow().contains_key(&expr.id) //local variable }, ExprField(_, spanned) => { let name = spanned.node.as_str(); -- cgit 1.4.1-3-g733a5 From c8d78a70b3acbf255a7dfb9472361691e1e0f6cf Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 18 Dec 2015 13:47:12 -0800 Subject: Test that we do not lint for multiple underscores --- tests/compile-fail/used_underscore_binding.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index bc6b32807f3..0d822a29cee 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -22,6 +22,11 @@ fn unused_underscore(_foo: u32) -> u32 { 1 } +///Test that we do not lint for multiple underscores +fn multiple_underscores(__x: u32) -> u32 { + __x + 1 +} + // Non-variable bindings with preceding underscore fn _fn_test() {} struct _StructTest; @@ -50,6 +55,7 @@ fn main() { // possible false positives let _ = non_prefix_underscore(foo); let _ = unused_underscore(foo); + let _ = multiple_underscores(foo); non_variables(); } -- cgit 1.4.1-3-g733a5 From 98d21f9fc5f5dfb4391452b506d4a27ac1d452a4 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 18 Dec 2015 16:04:33 -0800 Subject: Make compatible with `unused_variables` lint --- src/misc.rs | 30 ++++++++++++++++----------- tests/compile-fail/for_loop.rs | 7 +++---- tests/compile-fail/used_underscore_binding.rs | 29 +++++++++++++++++--------- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 9954e358232..44d044a4384 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -10,7 +10,8 @@ use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; +use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint, walk_ptrs_ty, + is_integer_literal}; use utils::span_help_and_lint; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. @@ -323,16 +324,7 @@ impl LateLintPass for PatternPass { /// **Why is this bad?** A single leading underscore is usually used to indicate that a binding /// will not be used. Using such a binding breaks this expectation. /// -/// **Known problems:** This lint's idea of a "used" variable is not quite the same as in the -/// built-in `unused_variables` lint. For example, in the following code -/// ``` -/// fn foo(y: u32) -> u32) { -/// let _x = 1; -/// _x +=1; -/// y -/// } -/// ``` -/// _x will trigger both the `unused_variables` lint and the `used_underscore_binding` lint. +/// **Known problems:** None /// /// **Example**: /// ``` @@ -362,6 +354,7 @@ impl LateLintPass for UsedUnderscoreBinding { ident.name.as_str().chars().next() == Some('_') //starts with '_' && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" && ident.name != ident.unhygienic_name //not in macro + && is_used(cx, expr) }, ExprField(_, spanned) => { let name = spanned.node.as_str(); @@ -372,8 +365,21 @@ impl LateLintPass for UsedUnderscoreBinding { }; if needs_lint { cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, - "used binding which is prefixed with an underscore. A leading underscore\ + "used binding which is prefixed with an underscore. A leading underscore \ signals that a binding will not be used."); } } } + +fn is_used(cx: &LateContext, expr: &Expr) -> bool { + if let Some(ref parent) = get_parent_expr(cx, expr) { + match parent.node { + ExprAssign(_, ref rhs) => **rhs == *expr, + ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + _ => is_used(cx, &parent) + } + } + else { + true + } +} diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 59b77f6421b..f1c1adf6cc8 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -16,8 +16,7 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity, - used_underscore_binding)] +#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity)] fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; @@ -180,8 +179,8 @@ fn main() { if false { _index = 0 }; for _v in &vec { _index += 1 } - let mut _index = 0; - { let mut _x = &mut _index; } + let mut index = 0; + { let mut _x = &mut index; } for _v in &vec { _index += 1 } let mut index = 0; diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 0d822a29cee..e787124dce7 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -3,13 +3,13 @@ #![deny(clippy)] /// Test that we lint if we use a binding with a single leading underscore -fn prefix_underscore(_x: u32) -> u32 { - _x + 1 //~ ERROR used binding which is prefixed with an underscore +fn prefix_underscore(_foo: u32) -> u32 { + _foo + 1 //~ ERROR used binding which is prefixed with an underscore } /// Test that we lint even if the use is within a macro expansion -fn in_macro(_x: u32) { - println!("{}", _x); //~ ERROR used binding which is prefixed with an underscore +fn in_macro(_foo: u32) { + println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore } /// Test that we do not lint if the underscore is not a prefix @@ -17,14 +17,23 @@ fn non_prefix_underscore(some_foo: u32) -> u32 { some_foo + 1 } -/// Test that we do not lint if we do not use the binding -fn unused_underscore(_foo: u32) -> u32 { +/// Test that we do not lint if we do not use the binding (simple case) +fn unused_underscore_simple(_foo: u32) -> u32 { + 1 +} + +#[deny(unused_variables)] +/// Test that we do not lint if we do not use the binding (complex case). This checks for +/// compatibility with the built-in `unused_variables` lint. +fn unused_underscore_complex(mut _foo: u32) -> u32 { + _foo += 1; + _foo = 2; 1 } ///Test that we do not lint for multiple underscores -fn multiple_underscores(__x: u32) -> u32 { - __x + 1 +fn multiple_underscores(__foo: u32) -> u32 { + __foo + 1 } // Non-variable bindings with preceding underscore @@ -54,8 +63,8 @@ fn main() { in_macro(foo); // possible false positives let _ = non_prefix_underscore(foo); - let _ = unused_underscore(foo); + let _ = unused_underscore_simple(foo); + let _ = unused_underscore_complex(foo); let _ = multiple_underscores(foo); non_variables(); } - -- cgit 1.4.1-3-g733a5 From bd82c082cb7734f037116d38f949ca354b597a29 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 18 Dec 2015 16:29:22 -0800 Subject: Add test for struct fields --- tests/compile-fail/used_underscore_binding.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index e787124dce7..39a33c96876 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -12,6 +12,17 @@ fn in_macro(_foo: u32) { println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore } +// Struct for testing use of fields prefixed with an underscore +struct StructFieldTest { + _underscore_field: u32, +} + +/// Test that we lint the use of a struct field which is prefixed with an underscore +fn in_struct_field() { + let mut s = StructFieldTest { _underscore_field: 0 }; + s._underscore_field += 1; //~ Error used binding which is prefixed with an underscore +} + /// Test that we do not lint if the underscore is not a prefix fn non_prefix_underscore(some_foo: u32) -> u32 { some_foo + 1 @@ -22,7 +33,6 @@ fn unused_underscore_simple(_foo: u32) -> u32 { 1 } -#[deny(unused_variables)] /// Test that we do not lint if we do not use the binding (complex case). This checks for /// compatibility with the built-in `unused_variables` lint. fn unused_underscore_complex(mut _foo: u32) -> u32 { @@ -61,6 +71,7 @@ fn main() { // tests of unused_underscore lint let _ = prefix_underscore(foo); in_macro(foo); + in_struct_field(); // possible false positives let _ = non_prefix_underscore(foo); let _ = unused_underscore_simple(foo); -- cgit 1.4.1-3-g733a5 From a65a7770b3e16fbe5e350c670d852c2696ce2907 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 19 Dec 2015 19:08:22 +0530 Subject: Rust upgrade to rustc 1.7.0-nightly (8ad12c3e2 2015-12-19) --- Cargo.toml | 2 +- src/consts.rs | 6 ++---- src/precedence.rs | 7 +++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 832a6dff401..5306de9b8d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.30" +version = "0.0.31" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/consts.rs b/src/consts.rs index 791bf587bb5..f7069476546 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -20,10 +20,8 @@ use syntax::ast::Lit_; use syntax::ast::LitIntType::*; use syntax::ast::LitIntType; use syntax::ast::{UintTy, FloatTy, StrStyle}; -use syntax::ast::UintTy::*; use syntax::ast::FloatTy::*; use syntax::ast::Sign::{self, Plus, Minus}; -use syntax::ast_util; #[derive(PartialEq, Eq, Debug, Copy, Clone)] @@ -195,9 +193,9 @@ impl fmt::Display for Constant { let (sign, suffix) = match *ity { LitIntType::SignedIntLit(ref sity, ref sign) => (if let Sign::Minus = *sign { "-" } else { "" }, - ast_util::int_ty_to_string(*sity)), + sity.ty_to_string()), LitIntType::UnsignedIntLit(ref uity) => - ("", ast_util::uint_ty_to_string(*uity)), + ("", uity.ty_to_string()), LitIntType::UnsuffixedIntLit(ref sign) => (if let Sign::Minus = *sign { "-" } else { "" }, "".into()), diff --git a/src/precedence.rs b/src/precedence.rs index be5f44c823a..39a3e9e56c2 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use syntax::codemap::Spanned; use syntax::ast::*; -use syntax::ast_util::binop_to_string; use utils::{span_lint, snippet}; @@ -38,17 +37,17 @@ impl EarlyLintPass for Precedence { &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} ({})`", snippet(cx, left.span, ".."), - binop_to_string(op), snippet(cx, right.span, ".."))), + op.to_string(), snippet(cx, right.span, ".."))), (true, false) => span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} {}`", snippet(cx, left.span, ".."), - binop_to_string(op), snippet(cx, right.span, ".."))), + op.to_string(), snippet(cx, right.span, ".."))), (false, true) => span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `{} {} ({})`", snippet(cx, left.span, ".."), - binop_to_string(op), snippet(cx, right.span, ".."))), + op.to_string(), snippet(cx, right.span, ".."))), _ => (), } } -- cgit 1.4.1-3-g733a5 From 4a32445aa7fdc7d38fdfeb23e07536ff11c860bc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 20 Dec 2015 04:45:31 +0530 Subject: Add macro check to used_underscore --- Cargo.toml | 2 +- src/misc.rs | 8 +++++--- tests/compile-fail/used_underscore_binding.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5306de9b8d0..5b1332b18f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.31" +version = "0.0.32" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/misc.rs b/src/misc.rs index 44d044a4384..3a17ff0f0cb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -10,9 +10,8 @@ use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint, walk_ptrs_ty, - is_integer_literal}; -use utils::span_help_and_lint; +use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; +use utils::{span_help_and_lint, in_external_macro, walk_ptrs_ty, is_integer_literal}; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. /// @@ -363,6 +362,9 @@ impl LateLintPass for UsedUnderscoreBinding { }, _ => false }; + if in_external_macro(cx, expr.span) { + return + } if needs_lint { cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, "used binding which is prefixed with an underscore. A leading underscore \ diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 39a33c96876..49e1aa99cc0 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -9,7 +9,7 @@ fn prefix_underscore(_foo: u32) -> u32 { /// Test that we lint even if the use is within a macro expansion fn in_macro(_foo: u32) { - println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore + println!("{}", _foo); // doesn't warn, nut should #507 } // Struct for testing use of fields prefixed with an underscore -- cgit 1.4.1-3-g733a5 From b190aa7debabc5b9d81b73b3f72701ece99d5ff0 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Mon, 21 Dec 2015 01:03:12 -0800 Subject: Implement #507 Make `used_underscore_binding` lint compatible with MacroAttributes expansions. TODO: Add a good test for this. --- src/misc.rs | 27 +++++++++++++++++++++------ tests/compile-fail/used_underscore_binding.rs | 11 ++++++++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 3a17ff0f0cb..139dfde3681 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -3,7 +3,7 @@ use syntax::ptr::P; use rustc_front::hir::*; use reexport::*; use rustc_front::util::{is_comparison_binop, binop_to_string}; -use syntax::codemap::{Span, Spanned}; +use syntax::codemap::{Span, Spanned, ExpnFormat}; use rustc_front::intravisit::FnKind; use rustc::middle::ty; use rustc::middle::const_eval::ConstVal::Float; @@ -11,7 +11,7 @@ use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; -use utils::{span_help_and_lint, in_external_macro, walk_ptrs_ty, is_integer_literal}; +use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal}; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. /// @@ -345,6 +345,9 @@ impl LintPass for UsedUnderscoreBinding { impl LateLintPass for UsedUnderscoreBinding { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_attributes_expansion(cx, expr) { // Don't lint things expanded by #[derive(...)], etc + return; + } let needs_lint = match expr.node { ExprPath(_, ref path) => { let ident = path.segments.last() @@ -352,7 +355,7 @@ impl LateLintPass for UsedUnderscoreBinding { .identifier; ident.name.as_str().chars().next() == Some('_') //starts with '_' && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" - && ident.name != ident.unhygienic_name //not in macro + && ident.name != ident.unhygienic_name //not in bang macro && is_used(cx, expr) }, ExprField(_, spanned) => { @@ -362,9 +365,6 @@ impl LateLintPass for UsedUnderscoreBinding { }, _ => false }; - if in_external_macro(cx, expr.span) { - return - } if needs_lint { cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, "used binding which is prefixed with an underscore. A leading underscore \ @@ -373,6 +373,8 @@ impl LateLintPass for UsedUnderscoreBinding { } } +/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea +/// of what it means for an expression to be "used". fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(ref parent) = get_parent_expr(cx, expr) { match parent.node { @@ -385,3 +387,16 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { true } } + +/// Test whether an expression is in a macro expansion (e.g. something generated by #[derive(...)] +/// or the like) +fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { + cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| { + info_opt.map_or(false, |info| { + match info.callee.format { + ExpnFormat::MacroAttribute(_) => true, + _ => false, + } + }) + }) +} diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 49e1aa99cc0..fd1b3bfc162 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -9,7 +9,15 @@ fn prefix_underscore(_foo: u32) -> u32 { /// Test that we lint even if the use is within a macro expansion fn in_macro(_foo: u32) { - println!("{}", _foo); // doesn't warn, nut should #507 + println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore +} + +// TODO: This doesn't actually correctly test this. Need to find a #[derive(...)] which sets off +// the lint if the `in_attributes_expansion` test isn't there +/// Test that we do not lint for unused underscores in a MacroAttribute expansion +#[derive(Clone)] +struct MacroAttributesTest { + _foo: u32, } // Struct for testing use of fields prefixed with an underscore @@ -68,6 +76,7 @@ fn non_variables() { fn main() { let foo = 0u32; + let _ = MacroAttributesTest{_foo: 0}; // tests of unused_underscore lint let _ = prefix_underscore(foo); in_macro(foo); -- cgit 1.4.1-3-g733a5 From b6766a0dcf66650a24820929c20be237e37230bc Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Mon, 21 Dec 2015 01:40:19 -0800 Subject: Add RustcEncodable test --- Cargo.toml | 1 + tests/compile-fail/used_underscore_binding.rs | 9 --------- tests/used_underscore_binding_macro.rs | 16 ++++++++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 tests/used_underscore_binding_macro.rs diff --git a/Cargo.toml b/Cargo.toml index 5b1332b18f5..609f847b4a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ compiletest_rs = "0.0.11" regex = "*" regex_macros = "*" lazy_static = "*" +rustc-serialize = "0.3" [features] diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index fd1b3bfc162..39a33c96876 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -12,14 +12,6 @@ fn in_macro(_foo: u32) { println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore } -// TODO: This doesn't actually correctly test this. Need to find a #[derive(...)] which sets off -// the lint if the `in_attributes_expansion` test isn't there -/// Test that we do not lint for unused underscores in a MacroAttribute expansion -#[derive(Clone)] -struct MacroAttributesTest { - _foo: u32, -} - // Struct for testing use of fields prefixed with an underscore struct StructFieldTest { _underscore_field: u32, @@ -76,7 +68,6 @@ fn non_variables() { fn main() { let foo = 0u32; - let _ = MacroAttributesTest{_foo: 0}; // tests of unused_underscore lint let _ = prefix_underscore(foo); in_macro(foo); diff --git a/tests/used_underscore_binding_macro.rs b/tests/used_underscore_binding_macro.rs new file mode 100644 index 00000000000..4170f907b0a --- /dev/null +++ b/tests/used_underscore_binding_macro.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] + +extern crate rustc_serialize; + +/// Test that we do not lint for unused underscores in a MacroAttribute expansion +#[deny(used_underscore_binding)] +#[derive(RustcEncodable)] +struct MacroAttributesTest { + _foo: u32, +} + +#[test] +fn macro_attributes_test() { + let _ = MacroAttributesTest{_foo: 0}; +} -- cgit 1.4.1-3-g733a5 From 3abdcd470901ef8cec81314558f11571c75911dd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 21 Dec 2015 19:22:29 +0100 Subject: Implement #364 --- README.md | 3 ++- src/array_indexing.rs | 52 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ tests/compile-fail/array_indexing.rs | 12 +++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/array_indexing.rs create mode 100755 tests/compile-fail/array_indexing.rs diff --git a/README.md b/README.md index 015a7d9adf2..dc8fd37dfc9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 84 lints included in this crate: +There are 85 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -58,6 +58,7 @@ name [option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`) [option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`) [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator diff --git a/src/array_indexing.rs b/src/array_indexing.rs new file mode 100644 index 00000000000..d72adac943f --- /dev/null +++ b/src/array_indexing.rs @@ -0,0 +1,52 @@ +use rustc::lint::*; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc::middle::ty::TyArray; +use rustc_front::hir::*; +use utils::span_lint; + +/// **What it does:** Check for out of bounds array indexing with a constant index. +/// +/// **Why is this bad?** This will always panic at runtime. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ``` +/// let x = [1,2,3,4]; +/// ... +/// x[9]; +/// ``` +declare_lint! { + pub OUT_OF_BOUNDS_INDEXING, + Deny, + "out of bound constant indexing" +} + +#[derive(Copy,Clone)] +pub struct ArrayIndexing; + +impl LintPass for ArrayIndexing { + fn get_lints(&self) -> LintArray { + lint_array!(OUT_OF_BOUNDS_INDEXING) + } +} + +impl LateLintPass for ArrayIndexing { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprIndex(ref array, ref index) = e.node { + let ty = cx.tcx.expr_ty(array); + + if let TyArray(_, size) = ty.sty { + let index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); + if let Ok(ConstVal::Uint(index)) = index { + if size as u64 <= index { + span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, + "const index-expr is out of bounds"); + } + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 05181e69b2c..29b911a0cb2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ pub mod transmute; pub mod cyclomatic_complexity; pub mod escape; pub mod misc_early; +pub mod array_indexing; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -121,6 +122,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box escape::EscapePass); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); + reg.register_late_lint_pass(box array_indexing::ArrayIndexing); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -143,6 +145,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, + array_indexing::OUT_OF_BOUNDS_INDEXING, attrs::INLINE_ALWAYS, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs new file mode 100755 index 00000000000..68ab71da586 --- /dev/null +++ b/tests/compile-fail/array_indexing.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(out_of_bounds_indexing)] + +fn main() { + let x = [1,2,3,4]; + x[0]; + x[3]; + x[4]; //~ERROR: const index-expr is out of bounds + x[1 << 3]; //~ERROR: const index-expr is out of bounds +} -- cgit 1.4.1-3-g733a5 From 826827fe9422446ac6084a21f69542fe97626ea6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 21 Dec 2015 20:47:19 +0100 Subject: Fix some typos --- CONTRIBUTING.md | 2 +- src/bit_mask.rs | 2 +- src/needless_update.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5147595ab54..53caba6615c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,7 @@ Also please document your lint with a doc comment akin to the following: /// **Example:** Insert a short example if you have one ``` -Our `util/update_wiki.py` script can then add your ilnt docs to the wiki. +Our `util/update_wiki.py` script can then add your lint docs to the wiki. ## Contributions diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 3d428aa0da7..f4310db0fcb 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -11,7 +11,7 @@ use utils::span_lint; /// **What it does:** This lint checks for incompatible bit masks in comparisons. It is `Warn` by default. /// /// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` -/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: +/// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: /// /// |Comparison |Bit-Op|Example |is always|Formula | /// |------------|------|------------|---------|----------------------| diff --git a/src/needless_update.rs b/src/needless_update.rs index e1e0f481848..9a314616cdc 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -10,7 +10,7 @@ use utils::span_lint; /// /// **Known problems:** None. /// -/// **Example:** `Point { x: 1, y: 0, ..zero_point }`` +/// **Example:** `Point { x: 1, y: 0, ..zero_point }` declare_lint! { pub NEEDLESS_UPDATE, Warn, -- cgit 1.4.1-3-g733a5 From acc47a3bd5aa474bbf970d3e5a9e50522408a32b Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer <markus@unterwaditzer.net> Date: Tue, 22 Dec 2015 00:22:35 +0100 Subject: Nightly fixes As of https://github.com/rust-lang/rust/commit/e3da2a90033d233bf6d77e3c725880c12cfc8728#diff-12e06f1e9ca371a11bdc4615f50a4071L59 HirVec is syntax::ptr::P instead of Vec. --- src/map_clone.rs | 2 +- src/methods.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/map_clone.rs b/src/map_clone.rs index f5e8d20a745..b1ba47a9b54 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -82,7 +82,7 @@ fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { match expr.node { ExprPath(None, ref path) => { let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }]; - !path.global && path.segments == arg_segment + !path.global && path.segments[..] == arg_segment } _ => false, } diff --git a/src/methods.rs b/src/methods.rs index ef7a58959ac..35207cb746c 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -435,9 +435,9 @@ impl OutType { fn matches(&self, ty: &FunctionRetTy) -> bool { match (self, ty) { (&UnitType, &DefaultReturn(_)) => true, - (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![]) => true, + (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![].into()) => true, (&BoolType, &Return(ref ty)) if is_bool(ty) => true, - (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![]) => true, + (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, (&RefType, &Return(ref ty)) => { if let TyRptr(_, _) = ty.node { true } else { false } } -- cgit 1.4.1-3-g733a5 From 0e4259a827787b5e9f50e2b5e78dbdff510b8e2a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 22 Dec 2015 00:48:50 +0100 Subject: Remove duplicated if_let_chain! macro definition --- src/utils.rs | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 5e1671b709c..92b1cb1cd3a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -370,52 +370,6 @@ pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() } -/// Produce a nested chain of if-lets and ifs from the patterns: -/// -/// if_let_chain! { -/// [ -/// Some(y) = x, -/// y.len() == 2, -/// Some(z) = y, -/// ], -/// { -/// block -/// } -/// } -/// -/// becomes -/// -/// if let Some(y) = x { -/// if y.len() == 2 { -/// if let Some(z) = y { -/// block -/// } -/// } -/// } -#[macro_export] -macro_rules! if_let_chain { - ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { - if let $pat = $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([let $pat:pat = $expr:expr], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([$expr:expr, $($tt:tt)+], $block:block) => { - if $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([$expr:expr], $block:block) => { - if $expr { - $block - } - }; -} - pub struct LimitStack { stack: Vec<u64>, } -- cgit 1.4.1-3-g733a5 From 934ead14b566a80785ea1e647b2a3c5f747cf92e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 22 Dec 2015 00:51:15 +0100 Subject: Fix typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5147595ab54..7d52e10f867 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ how this syntax structure is encoded in the AST, it is recommended to run `rustc example of the structure and compare with the [nodes in the AST docs](http://manishearth.github.io/rust-internals-docs/syntax/ast/). Usually the lint will end up to be a nested series of matches and ifs, -[like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34) +[like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). T-middle issues can be more involved and require verifying types. The [`middle::ty`](http://manishearth.github.io/rust-internals-docs/rustc/middle/ty) module contains a -- cgit 1.4.1-3-g733a5 From e4fbeb49470818d6528ea9a36f245bd9d80b3297 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 23 Dec 2015 02:12:08 +0100 Subject: Don't trigger block_in_if_condition_expr lint if the block is unsafe --- src/block_in_if_condition.rs | 30 +++++++++++++++-------------- tests/compile-fail/block_in_if_condition.rs | 9 +++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index b4e81ac6a2b..f7c181f5fd8 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -74,23 +74,25 @@ impl LateLintPass for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprIf(ref check, ref then, _) = expr.node { if let ExprBlock(ref block) = check.node { - if block.stmts.is_empty() { - if let Some(ref ex) = block.expr { - // don't dig into the expression here, just suggest that they remove - // the block + if block.rules == DefaultBlock { + if block.stmts.is_empty() { + if let Some(ref ex) = block.expr { + // don't dig into the expression here, just suggest that they remove + // the block - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_EXPR, check.span, - BRACED_EXPR_MESSAGE, - &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_EXPR, check.span, + BRACED_EXPR_MESSAGE, + &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, ".."))); + } + } else { + // move block higher + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, check.span, + COMPLEX_BLOCK_MESSAGE, + &format!("try\nlet res = {};\nif res {} ... ", + snippet_block(cx, block.span, ".."), snippet_block(cx, then.span, ".."))); } - } else { - // move block higher - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, check.span, - COMPLEX_BLOCK_MESSAGE, - &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, ".."))); } } else { let mut visitor = ExVisitor { found_block: None }; diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs index c075d48297e..cd95fbd202c 100644 --- a/tests/compile-fail/block_in_if_condition.rs +++ b/tests/compile-fail/block_in_if_condition.rs @@ -60,5 +60,14 @@ fn closure_without_block() { } } +fn condition_is_unsafe_block() { + let a: i32 = 1; + + // this should not warn because the condition is an unsafe block + if unsafe { 1u32 == std::mem::transmute(a) } { + println!("1u32 == a"); + } +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 7216e83189e2458fd5d3a311f9d1a487cfee51d9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 01:14:10 +0100 Subject: Implement #471 --- src/lib.rs | 1 + src/matches.rs | 184 +++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/matches.rs | 31 ++++++- 3 files changed, 210 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 29b911a0cb2..2e05fd1fc43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -172,6 +172,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::WHILE_LET_ON_ITERATOR, map_clone::MAP_CLONE, matches::MATCH_BOOL, + matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::OK_EXPECT, diff --git a/src/matches.rs b/src/matches.rs index 460893d93ab..69a6fdf6016 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,10 +1,14 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::middle::const_eval::ConstVal::{Int, Uint}; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty; +use rustc_front::hir::*; +use std::cmp::Ordering; use syntax::ast::Lit_::LitBool; use syntax::codemap::Span; -use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_block}; +use utils::{snippet, span_lint, span_note_and_lint, span_help_and_lint, in_external_macro, expr_block}; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default. /// @@ -22,6 +26,7 @@ use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_bloc declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ is `_ => {}`) is used; recommends `if let` instead"); + /// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It is `Warn` by default. /// /// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. @@ -40,6 +45,7 @@ declare_lint!(pub SINGLE_MATCH, Warn, declare_lint!(pub MATCH_REF_PATS, Warn, "a match has all arms prefixed with `&`; the match expression can be \ dereferenced instead"); + /// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default. /// /// **Why is this bad?** It makes the code less readable. @@ -58,6 +64,25 @@ declare_lint!(pub MATCH_REF_PATS, Warn, declare_lint!(pub MATCH_BOOL, Warn, "a match on boolean expression; recommends `if..else` block instead"); +/// **What it does:** This lint checks for overlapping match arms. It is `Warn` by default. +/// +/// **Why is this bad?** It is likely to be an error and if not, makes the code less obvious. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let x = 5; +/// match x { +/// 1 ... 10 => println!("1 ... 10"), +/// 5 ... 15 => println!("5 ... 15"), +/// _ => (), +/// } +/// ``` +declare_lint!(pub MATCH_OVERLAPPING_ARM, Warn, + "overlapping match arms"); + #[allow(missing_copy_implementations)] pub struct MatchPass; @@ -150,6 +175,22 @@ impl LateLintPass for MatchPass { Consider using an if..else block"); } } + + // MATCH_OVERLAPPING_ARM + if arms.len() >= 2 { + let ranges = all_ranges(cx, arms); + let overlap = match type_ranges(&ranges) { + TypedRanges::IntRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::UintRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::None => None, + }; + + if let Some((start, end)) = overlap { + span_note_and_lint(cx, MATCH_OVERLAPPING_ARM, start, + "some ranges overlap", + end, "overlaps with this"); + } + } } if let ExprMatch(ref ex, ref arms, source) = expr.node { // check preconditions for MATCH_REF_PATS @@ -170,6 +211,77 @@ impl LateLintPass for MatchPass { } } +/// Get all arms that are unbounded PatRange-s. +fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { + arms.iter() + .filter_map(|arm| { + if let Arm { ref pats, guard: None, .. } = *arm { + Some(pats.iter().filter_map(|pat| { + if_let_chain! {[ + let PatRange(ref lhs, ref rhs) = pat.node, + let Ok(lhs) = eval_const_expr_partial(cx.tcx, &lhs, ExprTypeChecked, None), + let Ok(rhs) = eval_const_expr_partial(cx.tcx, &rhs, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); + }} + + None + })) + } + else { + None + } + }) + .flat_map(IntoIterator::into_iter) + .collect() +} + +#[derive(Debug, Eq, PartialEq)] +struct SpannedRange<T> { + span: Span, + node: (T, T), +} + +#[derive(Debug)] +enum TypedRanges { + IntRanges(Vec<SpannedRange<i64>>), + UintRanges(Vec<SpannedRange<u64>>), + None, +} + +/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than +/// `Uint` and `Int` probably don't make sense. +fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { + if ranges.is_empty() { + TypedRanges::None + } + else { + match ranges[0].node { + (Int(_), Int(_)) => { + TypedRanges::IntRanges(ranges.iter().filter_map(|range| { + if let (Int(start), Int(end)) = range.node { + Some(SpannedRange { span: range.span, node: (start, end) }) + } + else { + None + } + }).collect()) + }, + (Uint(_), Uint(_)) => { + TypedRanges::UintRanges(ranges.iter().filter_map(|range| { + if let (Uint(start), Uint(end)) = range.node { + Some(SpannedRange { span: range.span, node: (start, end) }) + } + else { + None + } + }).collect()) + }, + _ => TypedRanges::None, + } + } +} + fn is_unit_expr(expr: &Expr) -> bool { match expr.node { ExprTup(ref v) if v.is_empty() => true, @@ -209,3 +321,71 @@ fn match_template(cx: &LateContext, } } } + +fn overlaping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> + where T: Copy + Ord { + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + enum Kind<'a, T: 'a> { + Start(T, &'a SpannedRange<T>), + End(T, &'a SpannedRange<T>), + } + + impl<'a, T: Copy> Kind<'a, T> { + fn range(&self) -> &'a SpannedRange<T> { + match *self { + Kind::Start(_, r) | Kind::End(_, r) => r + } + } + + fn value(self) -> T { + match self { + Kind::Start(t, _) | Kind::End(t, _) => t + } + } + } + + impl<'a, T: Copy + Ord> PartialOrd for Kind<'a, T> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } + } + + impl<'a, T: Copy + Ord> Ord for Kind<'a, T> { + fn cmp(&self, other: &Self) -> Ordering { + self.value().cmp(&other.value()) + } + } + + let mut values = Vec::with_capacity(2*ranges.len()); + + for r in ranges { + values.push(Kind::Start(r.node.0, &r)); + values.push(Kind::End(r.node.1, &r)); + } + + values.sort(); + + for (a, b) in values.iter().zip(values.iter().skip(1)) { + match (a, b) { + (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node { return Some((ra, rb)) }, + (&Kind::End(a, _), &Kind::Start(b, _)) if a != b => (), + _ => return Some((&a.range(), &b.range())), + } + } + + None +} + +#[test] +fn test_overlapping() { + use syntax::codemap::DUMMY_SP; + + let sp = |s, e| SpannedRange { span: DUMMY_SP, node: (s, e) }; + + assert_eq!(None, overlaping::<u8>(&[])); + assert_eq!(None, overlaping(&[sp(1, 4)])); + assert_eq!(None, overlaping(&[sp(1, 4), sp(5, 6)])); + assert_eq!(None, overlaping(&[sp(1, 4), sp(5, 6), sp(10, 11)])); + assert_eq!(Some((&sp(1, 4), &sp(3, 6))), overlaping(&[sp(1, 4), sp(3, 6)])); + assert_eq!(Some((&sp(5, 6), &sp(6, 11))), overlaping(&[sp(1, 4), sp(5, 6), sp(6, 11)])); +} diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index ea3a48a94f5..ab181901c9c 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -51,17 +51,17 @@ fn match_bool() { true => 1, false => 0, }; - + match test { //~ ERROR you seem to be trying to match on a boolean expression true => (), false => { println!("Noooo!"); } }; - + match test { //~ ERROR you seem to be trying to match on a boolean expression false => { println!("Noooo!"); } _ => (), }; - + match test { //~ ERROR you seem to be trying to match on a boolean expression false => { println!("Noooo!"); } true => { println!("Yes!"); } @@ -70,7 +70,7 @@ fn match_bool() { // Not linted match option { 1 ... 10 => (), - 10 ... 20 => (), + 11 ... 20 => (), _ => (), }; } @@ -115,5 +115,28 @@ fn ref_pats() { } } +fn overlapping() { + const FOO : u64 = 2; + + match 42 { + 0 ... 10 => println!("0 ... 10"), //~ERROR + 0 ... 11 => println!("0 ... 10"), + _ => (), + } + + match 42 { + 0 ... 5 => println!("0 ... 10"), //~ERROR + 6 ... 7 => println!("6 ... 7"), + FOO ... 11 => println!("0 ... 10"), + _ => (), + } + + match 42 { + 0 ... 10 => println!("0 ... 10"), + 11 ... 50 => println!("0 ... 10"), + _ => (), + } +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 3373ea43c0ba0f226bc0a5e9bd578118fa564547 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 02:06:18 +0100 Subject: Consider literal patterns in MATCH_OVERLAPPING_ARM --- src/matches.rs | 7 +++++++ tests/compile-fail/matches.rs | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/matches.rs b/src/matches.rs index 69a6fdf6016..227a5bdb2df 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -225,6 +225,13 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); }} + if_let_chain! {[ + let PatLit(ref value) = pat.node, + let Ok(value) = eval_const_expr_partial(cx.tcx, &value, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); + }} + None })) } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index ab181901c9c..94d24746e4d 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -125,12 +125,18 @@ fn overlapping() { } match 42 { - 0 ... 5 => println!("0 ... 10"), //~ERROR + 0 ... 5 => println!("0 ... 5"), //~ERROR 6 ... 7 => println!("6 ... 7"), FOO ... 11 => println!("0 ... 10"), _ => (), } + match 42 { + 2 => println!("2"), + 0 ... 5 => println!("0 ... 5"), //~ERROR + _ => (), + } + match 42 { 0 ... 10 => println!("0 ... 10"), 11 ... 50 => println!("0 ... 10"), -- cgit 1.4.1-3-g733a5 From 0c8de9ed52ddc14e3797f89ab260a4e45be62418 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 02:19:32 +0100 Subject: Split MatchPass::check_expr for dogfood --- src/matches.rs | 211 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 110 insertions(+), 101 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 227a5bdb2df..78b39ac1791 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -96,117 +96,126 @@ impl LateLintPass for MatchPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { - // check preconditions for SINGLE_MATCH - // only two arms - if arms.len() == 2 && - // both of the arms have a single pattern and no guard - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - // and the second pattern is a `_` wildcard: this is not strictly necessary, - // since the exhaustiveness check will ensure the last one is a catch-all, - // but in some cases, an explicit match is preferred to catch situations - // when an enum is extended, so we don't consider these cases - arms[1].pats[0].node == PatWild && - // we don't want any content in the second arm (unit or empty block) - is_unit_expr(&arms[1].body) && - // finally, MATCH_BOOL doesn't apply here - (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) - { - span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for destructuring a \ - single pattern. Consider using `if let`", - &format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."))); - } + check_single_match(cx, ex, arms, expr); + check_match_bool(cx, ex, arms, expr); + check_overlapping_arms(cx, arms); + } + if let ExprMatch(ref ex, ref arms, source) = expr.node { + check_match_ref_pats(cx, ex, arms, source, expr); + } + } +} - // check preconditions for MATCH_BOOL - // type of expression == bool - if cx.tcx.expr_ty(ex).sty == ty::TyBool { - if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards - let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { - if let ExprLit(ref lit) = arm_bool.node { - match lit.node { - LitBool(true) => Some((&*arms[0].body, &*arms[1].body)), - LitBool(false) => Some((&*arms[1].body, &*arms[0].body)), - _ => None, - } - } else { None } - } else { None }; - if let Some((ref true_expr, ref false_expr)) = exprs { - if !is_unit_expr(true_expr) { - if !is_unit_expr(false_expr) { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))); - } else { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."))); - } - } else if !is_unit_expr(false_expr) { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))); - } else { - span_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); - } +fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + if arms.len() == 2 && + // both of the arms have a single pattern and no guard + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + // and the second pattern is a `_` wildcard: this is not strictly necessary, + // since the exhaustiveness check will ensure the last one is a catch-all, + // but in some cases, an explicit match is preferred to catch situations + // when an enum is extended, so we don't consider these cases + arms[1].pats[0].node == PatWild && + // we don't want any content in the second arm (unit or empty block) + is_unit_expr(&arms[1].body) && + // finally, MATCH_BOOL doesn't apply here + (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) + { + span_help_and_lint(cx, SINGLE_MATCH, expr.span, + "you seem to be trying to use match for destructuring a \ + single pattern. Consider using `if let`", + &format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."))); + } +} + +fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + // type of expression == bool + if cx.tcx.expr_ty(ex).sty == ty::TyBool { + if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards + let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { + if let ExprLit(ref lit) = arm_bool.node { + match lit.node { + LitBool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitBool(false) => Some((&*arms[1].body, &*arms[0].body)), + _ => None, + } + } else { None } + } else { None }; + if let Some((ref true_expr, ref false_expr)) = exprs { + if !is_unit_expr(true_expr) { + if !is_unit_expr(false_expr) { + span_help_and_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block:", + &format!("try\nif {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))); } else { - span_lint(cx, MATCH_BOOL, expr.span, + span_help_and_lint(cx, MATCH_BOOL, expr.span, "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); + Consider using an if..else block:", + &format!("try\nif {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."))); } + } else if !is_unit_expr(false_expr) { + span_help_and_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block:", + &format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))); } else { span_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block"); } + } else { + span_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block"); } + } else { + span_lint(cx, MATCH_BOOL, expr.span, + "you seem to be trying to match on a boolean expression. \ + Consider using an if..else block"); + } + } +} - // MATCH_OVERLAPPING_ARM - if arms.len() >= 2 { - let ranges = all_ranges(cx, arms); - let overlap = match type_ranges(&ranges) { - TypedRanges::IntRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::UintRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::None => None, - }; - - if let Some((start, end)) = overlap { - span_note_and_lint(cx, MATCH_OVERLAPPING_ARM, start, - "some ranges overlap", - end, "overlaps with this"); - } - } +fn check_overlapping_arms(cx: &LateContext, arms: &[Arm]) { + if arms.len() >= 2 { + let ranges = all_ranges(cx, arms); + let overlap = match type_ranges(&ranges) { + TypedRanges::IntRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::UintRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::None => None, + }; + + if let Some((start, end)) = overlap { + span_note_and_lint(cx, MATCH_OVERLAPPING_ARM, start, + "some ranges overlap", + end, "overlaps with this"); } - if let ExprMatch(ref ex, ref arms, source) = expr.node { - // check preconditions for MATCH_REF_PATS - if has_only_ref_pats(arms) { - if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - let template = match_template(cx, expr.span, source, "", inner); - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "you don't need to add `&` to both the expression \ - and the patterns: use `{}`", template)); - } else { - let template = match_template(cx, expr.span, source, "*", ex); - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "instead of prefixing all patterns with `&`, you can dereference the \ - expression: `{}`", template)); - } - } + } +} + +fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { + if has_only_ref_pats(arms) { + if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + let template = match_template(cx, expr.span, source, "", inner); + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "you don't need to add `&` to both the expression \ + and the patterns: use `{}`", template)); + } else { + let template = match_template(cx, expr.span, source, "*", ex); + span_lint(cx, MATCH_REF_PATS, expr.span, &format!( + "instead of prefixing all patterns with `&`, you can dereference the \ + expression: `{}`", template)); } } } -- cgit 1.4.1-3-g733a5 From 1aa3956b8a84de9e2e81e9f10ad1f72a0a935918 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 02:41:20 +0100 Subject: Update README --- README.md | 3 ++- src/matches.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc8fd37dfc9..6d1b88688c1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 85 lints included in this crate: +There are 86 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -40,6 +40,7 @@ name [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead +[match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 diff --git a/src/matches.rs b/src/matches.rs index 78b39ac1791..1cdf76db663 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -81,7 +81,7 @@ declare_lint!(pub MATCH_BOOL, Warn, /// } /// ``` declare_lint!(pub MATCH_OVERLAPPING_ARM, Warn, - "overlapping match arms"); + "a match has overlapping arms"); #[allow(missing_copy_implementations)] pub struct MatchPass; -- cgit 1.4.1-3-g733a5 From a2b842dff33abc90258c60cfaffb18443a225362 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 23 Dec 2015 07:53:01 +0530 Subject: Bump cargo (fixes #517) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 609f847b4a9..5c35f9f4271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.32" +version = "0.0.33" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 90efb7b76d401995eb054799dc55058aa66887c7 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 11:25:32 +0100 Subject: Fix typo --- src/matches.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 1cdf76db663..3ece02c0374 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -191,8 +191,8 @@ fn check_overlapping_arms(cx: &LateContext, arms: &[Arm]) { if arms.len() >= 2 { let ranges = all_ranges(cx, arms); let overlap = match type_ranges(&ranges) { - TypedRanges::IntRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::UintRanges(ranges) => overlaping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), + TypedRanges::UintRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), TypedRanges::None => None, }; @@ -338,7 +338,7 @@ fn match_template(cx: &LateContext, } } -fn overlaping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> +fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> where T: Copy + Ord { #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Kind<'a, T: 'a> { @@ -398,10 +398,10 @@ fn test_overlapping() { let sp = |s, e| SpannedRange { span: DUMMY_SP, node: (s, e) }; - assert_eq!(None, overlaping::<u8>(&[])); - assert_eq!(None, overlaping(&[sp(1, 4)])); - assert_eq!(None, overlaping(&[sp(1, 4), sp(5, 6)])); - assert_eq!(None, overlaping(&[sp(1, 4), sp(5, 6), sp(10, 11)])); - assert_eq!(Some((&sp(1, 4), &sp(3, 6))), overlaping(&[sp(1, 4), sp(3, 6)])); - assert_eq!(Some((&sp(5, 6), &sp(6, 11))), overlaping(&[sp(1, 4), sp(5, 6), sp(6, 11)])); + assert_eq!(None, overlapping::<u8>(&[])); + assert_eq!(None, overlapping(&[sp(1, 4)])); + assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6)])); + assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6), sp(10, 11)])); + assert_eq!(Some((&sp(1, 4), &sp(3, 6))), overlapping(&[sp(1, 4), sp(3, 6)])); + assert_eq!(Some((&sp(5, 6), &sp(6, 11))), overlapping(&[sp(1, 4), sp(5, 6), sp(6, 11)])); } -- cgit 1.4.1-3-g733a5 From 2fd3093395d989bb8ada55440fb4101264e676e5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 11:25:44 +0100 Subject: Only run MATCH_OVERLAPPING_ARM on integral matches --- src/matches.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 3ece02c0374..053b6b072b5 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -98,7 +98,7 @@ impl LateLintPass for MatchPass { if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { check_single_match(cx, ex, arms, expr); check_match_bool(cx, ex, arms, expr); - check_overlapping_arms(cx, arms); + check_overlapping_arms(cx, ex, arms); } if let ExprMatch(ref ex, ref arms, source) = expr.node { check_match_ref_pats(cx, ex, arms, source, expr); @@ -187,8 +187,9 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } -fn check_overlapping_arms(cx: &LateContext, arms: &[Arm]) { - if arms.len() >= 2 { +fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { + if arms.len() >= 2 && + cx.tcx.expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms); let overlap = match type_ranges(&ranges) { TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), -- cgit 1.4.1-3-g733a5 From d01987a40bea852260f5d1442bb0631c0a893ec0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 11:26:35 +0100 Subject: Include error message in tests --- tests/compile-fail/matches.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 94d24746e4d..b569f9566ef 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -119,13 +119,13 @@ fn overlapping() { const FOO : u64 = 2; match 42 { - 0 ... 10 => println!("0 ... 10"), //~ERROR + 0 ... 10 => println!("0 ... 10"), //~ERROR: some ranges overlap 0 ... 11 => println!("0 ... 10"), _ => (), } match 42 { - 0 ... 5 => println!("0 ... 5"), //~ERROR + 0 ... 5 => println!("0 ... 5"), //~ERROR: some ranges overlap 6 ... 7 => println!("6 ... 7"), FOO ... 11 => println!("0 ... 10"), _ => (), @@ -133,7 +133,7 @@ fn overlapping() { match 42 { 2 => println!("2"), - 0 ... 5 => println!("0 ... 5"), //~ERROR + 0 ... 5 => println!("0 ... 5"), //~ERROR: some ranges overlap _ => (), } -- cgit 1.4.1-3-g733a5 From 0fa8481ba390dc9b860123950717acbb34bd39fd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 17:48:30 +0100 Subject: Put tests in tests folder --- src/matches.rs | 22 ++++------------------ tests/matches.rs | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 tests/matches.rs diff --git a/src/matches.rs b/src/matches.rs index 053b6b072b5..e4172b40932 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -254,9 +254,9 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { } #[derive(Debug, Eq, PartialEq)] -struct SpannedRange<T> { - span: Span, - node: (T, T), +pub struct SpannedRange<T> { + pub span: Span, + pub node: (T, T), } #[derive(Debug)] @@ -339,7 +339,7 @@ fn match_template(cx: &LateContext, } } -fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> +pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> where T: Copy + Ord { #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Kind<'a, T: 'a> { @@ -392,17 +392,3 @@ fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &Span None } - -#[test] -fn test_overlapping() { - use syntax::codemap::DUMMY_SP; - - let sp = |s, e| SpannedRange { span: DUMMY_SP, node: (s, e) }; - - assert_eq!(None, overlapping::<u8>(&[])); - assert_eq!(None, overlapping(&[sp(1, 4)])); - assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6)])); - assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6), sp(10, 11)])); - assert_eq!(Some((&sp(1, 4), &sp(3, 6))), overlapping(&[sp(1, 4), sp(3, 6)])); - assert_eq!(Some((&sp(5, 6), &sp(6, 11))), overlapping(&[sp(1, 4), sp(5, 6), sp(6, 11)])); -} diff --git a/tests/matches.rs b/tests/matches.rs new file mode 100644 index 00000000000..03cc5281741 --- /dev/null +++ b/tests/matches.rs @@ -0,0 +1,20 @@ +#![allow(plugin_as_library)] +#![feature(rustc_private)] + +extern crate clippy; +extern crate syntax; + +#[test] +fn test_overlapping() { + use clippy::matches::overlapping; + use syntax::codemap::DUMMY_SP; + + let sp = |s, e| clippy::matches::SpannedRange { span: DUMMY_SP, node: (s, e) }; + + assert_eq!(None, overlapping::<u8>(&[])); + assert_eq!(None, overlapping(&[sp(1, 4)])); + assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6)])); + assert_eq!(None, overlapping(&[sp(1, 4), sp(5, 6), sp(10, 11)])); + assert_eq!(Some((&sp(1, 4), &sp(3, 6))), overlapping(&[sp(1, 4), sp(3, 6)])); + assert_eq!(Some((&sp(5, 6), &sp(6, 11))), overlapping(&[sp(1, 4), sp(5, 6), sp(6, 11)])); +} -- cgit 1.4.1-3-g733a5 From 4958878ad219d570388a1866d13761e35122cc0a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 22:36:37 +0100 Subject: Fix missing parameter in `panic!` --- src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index f7069476546..9d3a9e7d7c2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -75,7 +75,7 @@ impl Constant { if let ConstantInt(val, _) = *self { val // TODO we may want to check the sign if any } else { - panic!("Could not convert a {:?} to u64"); + panic!("Could not convert a {:?} to u64", self); } } -- cgit 1.4.1-3-g733a5 From 592ca26e902bfa9ed3648db4ef0eeb53a5d598fe Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 23 Dec 2015 22:37:52 +0100 Subject: Fix #518 --- README.md | 3 ++- src/attrs.rs | 4 ++-- src/lib.rs | 3 +++ src/panic.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 1 + tests/compile-fail/panic.rs | 22 ++++++++++++++++++++++ 6 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/panic.rs create mode 100644 tests/compile-fail/panic.rs diff --git a/README.md b/README.md index dc8fd37dfc9..2c8b20f83a9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 85 lints included in this crate: +There are 86 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -59,6 +59,7 @@ name [option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`) [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing +[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator diff --git a/src/attrs.rs b/src/attrs.rs index 10db4a551f9..0882f3af41f 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -6,7 +6,7 @@ use reexport::*; use syntax::codemap::Span; use syntax::attr::*; use syntax::ast::{Attribute, MetaList, MetaWord}; -use utils::{in_macro, match_path, span_lint}; +use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; /// **What it does:** This lint warns on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. /// @@ -94,7 +94,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { ExprRet(None) | ExprBreak(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &["std", "rt", "begin_unwind"]) + !match_path(path, &BEGIN_UNWIND) } else { true } } _ => true diff --git a/src/lib.rs b/src/lib.rs index 29b911a0cb2..adc1d402e92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,7 @@ pub mod cyclomatic_complexity; pub mod escape; pub mod misc_early; pub mod array_indexing; +pub mod panic; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -123,6 +124,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); + reg.register_late_lint_pass(box panic::PanicPass); reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, @@ -198,6 +200,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_update::NEEDLESS_UPDATE, no_effect::NO_EFFECT, open_options::NONSENSICAL_OPEN_OPTIONS, + panic::PANIC_PARAMS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, diff --git a/src/panic.rs b/src/panic.rs new file mode 100644 index 00000000000..6f713804e8c --- /dev/null +++ b/src/panic.rs @@ -0,0 +1,42 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::ast::Lit_::LitStr; + +use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; + +/// **What it does:** Warn about missing parameters in `panic!`. +/// +/// **Known problems:** Should you want to use curly brackets in `panic!` without any parameter, +/// this lint will warn. +/// +/// **Example:** +/// ``` +/// panic!("This panic! is probably missing a parameter there: {}"); +/// ``` +declare_lint!(pub PANIC_PARAMS, Warn, "missing parameters in `panic!`"); + +#[allow(missing_copy_implementations)] +pub struct PanicPass; + +impl LintPass for PanicPass { + fn get_lints(&self) -> LintArray { + lint_array!(PANIC_PARAMS) + } +} + +impl LateLintPass for PanicPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! {[ + in_external_macro(cx, expr.span), + let ExprCall(ref fun, ref params) = expr.node, + params.len() == 2, + let ExprPath(None, ref path) = fun.node, + match_path(path, &BEGIN_UNWIND), + let ExprLit(ref lit) = params[0].node, + let LitStr(ref string, _) = lit.node, + string.contains('{') + ], { + span_lint(cx, PANIC_PARAMS, expr.span, "You probably are missing some parameter in your `panic!` call"); + }} + } +} diff --git a/src/utils.rs b/src/utils.rs index 92b1cb1cd3a..1ce97ccea4e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -21,6 +21,7 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "Linke pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; +pub const BEGIN_UNWIND:[&'static str; 3] = ["std", "rt", "begin_unwind"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/panic.rs b/tests/compile-fail/panic.rs new file mode 100644 index 00000000000..36427f4330b --- /dev/null +++ b/tests/compile-fail/panic.rs @@ -0,0 +1,22 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(panic_params)] + +fn missing() { + panic!("{}"); //~ERROR: You probably are missing some parameter +} + +fn ok_sigle() { + panic!("foo bar"); +} + +fn ok_multiple() { + panic!("{}", "This is {ok}"); +} + +fn main() { + missing(); + ok_sigle(); + ok_multiple(); +} -- cgit 1.4.1-3-g733a5 From dbf1cdf34aa89cdaba1bb9993e6aed221dfceb90 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 24 Dec 2015 15:27:31 +0530 Subject: Fix panic lint --- src/panic.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/panic.rs b/src/panic.rs index 6f713804e8c..40d6e7d4dff 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -28,15 +28,22 @@ impl LateLintPass for PanicPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ in_external_macro(cx, expr.span), - let ExprCall(ref fun, ref params) = expr.node, + let ExprBlock(ref block) = expr.node, + let Some(ref ex) = block.expr, + let ExprCall(ref fun, ref params) = ex.node, params.len() == 2, let ExprPath(None, ref path) = fun.node, match_path(path, &BEGIN_UNWIND), let ExprLit(ref lit) = params[0].node, let LitStr(ref string, _) = lit.node, - string.contains('{') + string.contains('{'), + let Some(sp) = cx.sess().codemap() + .with_expn_info(expr.span.expn_id, + |info| info.map(|i| i.call_site)) ], { - span_lint(cx, PANIC_PARAMS, expr.span, "You probably are missing some parameter in your `panic!` call"); + + span_lint(cx, PANIC_PARAMS, sp, + "You probably are missing some parameter in your `panic!` call"); }} } } -- cgit 1.4.1-3-g733a5 From f1aac931bdb687c12b77980e52458ae921f90f21 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sun, 27 Dec 2015 01:22:53 -0800 Subject: Refactor `check_expr()` impl for `MethodsPass` --- src/methods.rs | 269 +++++++++++++++++++++++++++++++++++---------------------- src/utils.rs | 22 +++++ 2 files changed, 188 insertions(+), 103 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 35207cb746c..31e3bfb8f4a 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -5,8 +5,8 @@ use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; -use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, walk_ptrs_ty_depth, - walk_ptrs_ty}; +use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, match_method_chain, + walk_ptrs_ty_depth, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; use self::SelfKind::*; @@ -157,107 +157,21 @@ impl LintPass for MethodsPass { impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - - if let ExprMethodCall(ref name, _, ref args) = expr.node { - let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - match &*name.node.as_str() { - "unwrap" if match_type(cx, obj_ty, &OPTION_PATH) => { - span_lint(cx, OPTION_UNWRAP_USED, expr.span, - "used unwrap() on an Option value. If you don't want \ - to handle the None case gracefully, consider using \ - expect() to provide a better panic message"); - }, - "unwrap" if match_type(cx, obj_ty, &RESULT_PATH) => { - span_lint(cx, RESULT_UNWRAP_USED, expr.span, - "used unwrap() on a Result value. Graceful handling \ - of Err values is preferred"); - }, - "to_string" if obj_ty.sty == ty::TyStr => { - let mut arg_str = snippet(cx, args[0].span, "_"); - if ptr_depth > 1 { - arg_str = Cow::Owned(format!( - "({}{})", - iter::repeat('*').take(ptr_depth - 1).collect::<String>(), - arg_str)); - } - span_lint(cx, STR_TO_STRING, expr.span, &format!( - "`{}.to_owned()` is faster", arg_str)); - }, - "to_string" if match_type(cx, obj_ty, &STRING_PATH) => { - span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \ - `clone()` to make a copy"); - }, - "expect" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { - if inner_name.node.as_str() == "ok" - && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &RESULT_PATH) { - let result_type = cx.tcx.expr_ty(&inner_args[0]); - if let Some(error_type) = get_error_type(cx, result_type) { - if has_debug_impl(error_type, cx) { - span_lint(cx, OK_EXPECT, expr.span, - "called `ok().expect()` on a Result \ - value. You can call `expect` directly \ - on the `Result`"); - } - } - } - }, - // check Option.map(_).unwrap_or(_) - "unwrap_or" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { - if inner_name.node.as_str() == "map" - && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { - // lint message - let msg = - "called `map(f).unwrap_or(a)` on an Option value. This can be done \ - more directly by calling `map_or(a, f)` instead"; - // get args to map() and unwrap_or() - let map_arg = snippet(cx, inner_args[1].span, ".."); - let unwrap_arg = snippet(cx, args[1].span, ".."); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or() have the same span - let multiline = map_arg.lines().count() > 1 - || unwrap_arg.lines().count() > 1; - let same_span = inner_args[1].span.expn_id == args[1].span.expn_id; - if same_span && !multiline { - span_note_and_lint( - cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, - &format!("replace this with map_or({1}, {0})", - map_arg, unwrap_arg) - ); - } - else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); - }; - } - }, - // check Option.map(_).unwrap_or_else(_) - "unwrap_or_else" => if let ExprMethodCall(ref inner_name, _, ref inner_args) = args[0].node { - if inner_name.node.as_str() == "map" - && match_type(cx, cx.tcx.expr_ty(&inner_args[0]), &OPTION_PATH) { - // lint message - let msg = - "called `map(f).unwrap_or_else(g)` on an Option value. This can be \ - done more directly by calling `map_or_else(g, f)` instead"; - // get args to map() and unwrap_or_else() - let map_arg = snippet(cx, inner_args[1].span, ".."); - let unwrap_arg = snippet(cx, args[1].span, ".."); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or_else() have the same span - let multiline = map_arg.lines().count() > 1 - || unwrap_arg.lines().count() > 1; - let same_span = inner_args[1].span.expn_id == args[1].span.expn_id; - if same_span && !multiline { - span_note_and_lint( - cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg, expr.span, - &format!("replace this with map_or_else({1}, {0})", - map_arg, unwrap_arg) - ); - } - else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); - }; - } - }, - _ => {}, + if let ExprMethodCall(_, _, _) = expr.node { + if match_method_chain(expr, &["unwrap"]) { + lint_unwrap(cx, expr); + } + else if match_method_chain(expr, &["to_string"]) { + lint_to_string(cx, expr); + } + else if match_method_chain(expr, &["ok", "expect"]) { + lint_ok_expect(cx, expr); + } + else if match_method_chain(expr, &["map", "unwrap_or"]) { + lint_map_unwrap_or(cx, expr); + } + else if match_method_chain(expr, &["map", "unwrap_or_else"]) { + lint_map_unwrap_or_else(cx, expr); } } } @@ -304,6 +218,155 @@ impl LateLintPass for MethodsPass { } } +/// lint use of `unwrap()` for `Option`s and `Result`s +fn lint_unwrap(cx: &LateContext, expr: &Expr) { + let args = match expr.node { + ExprMethodCall(_, _, ref args) => args, + _ => panic!("clippy methods.rs: should not have called `lint_unwrap()` on a non-matching \ + expression!"), + }; + + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); + + if match_type(cx, obj_ty, &OPTION_PATH) { + span_lint(cx, OPTION_UNWRAP_USED, expr.span, + "used unwrap() on an Option value. If you don't want to handle the None case \ + gracefully, consider using expect() to provide a better panic message"); + } + else if match_type(cx, obj_ty, &RESULT_PATH) { + span_lint(cx, RESULT_UNWRAP_USED, expr.span, + "used unwrap() on a Result value. Graceful handling of Err values is preferred"); + } +} + +/// lint use of `to_string()` for `&str`s and `String`s +fn lint_to_string(cx: &LateContext, expr: &Expr) { + let args = match expr.node { + ExprMethodCall(_, _, ref args) => args, + _ => panic!("clippy methods.rs: should not have called `lint_to_string()` on a \ + non-matching expression!"), + }; + + let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); + + if obj_ty.sty == ty::TyStr { + let mut arg_str = snippet(cx, args[0].span, "_"); + if ptr_depth > 1 { + arg_str = Cow::Owned(format!( + "({}{})", + iter::repeat('*').take(ptr_depth - 1).collect::<String>(), + arg_str)); + } + span_lint(cx, STR_TO_STRING, expr.span, + &format!("`{}.to_owned()` is faster", arg_str)); + } + else if match_type(cx, obj_ty, &STRING_PATH) { + span_lint(cx, STRING_TO_STRING, expr.span, + "`String.to_string()` is a no-op; use `clone()` to make a copy"); + } +} + +/// lint use of `ok().expect()` for `Result`s +fn lint_ok_expect(cx: &LateContext, expr: &Expr) { + let expect_args = match expr.node { + ExprMethodCall(_, _, ref expect_args) => expect_args, + _ => panic!("clippy methods.rs: Should not have called `lint_ok_expect()` on a \ + non-matching expression!") + }; + let ok_args = match expect_args[0].node { + ExprMethodCall(_, _, ref ok_args) => ok_args, + _ => panic!("clippy methods.rs: Should not have called `lint_ok_expect()` on a \ + non-matching expression!") + }; + + // lint if the caller of `ok()` is a `Result` + if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &RESULT_PATH) { + let result_type = cx.tcx.expr_ty(&ok_args[0]); + if let Some(error_type) = get_error_type(cx, result_type) { + if has_debug_impl(error_type, cx) { + span_lint(cx, OK_EXPECT, expr.span, + "called `ok().expect()` on a Result value. You can call `expect` \ + directly on the `Result`"); + } + } + } +} + +/// lint use of `map().unwrap_or()` for `Option`s +fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr) { + let unwrap_args = match expr.node { + ExprMethodCall(_, _, ref unwrap_args) => unwrap_args, + _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or()` on a \ + non-matching expression!") + }; + let map_args = match unwrap_args[0].node { + ExprMethodCall(_, _, ref map_args) => map_args, + _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or()` on a \ + non-matching expression!") + }; + + // lint if the caller of `map()` is an `Option` + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { + // lint message + let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more \ + directly by calling `map_or(a, f)` instead"; + // get snippets for args to map() and unwrap_or() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or() have the same span + let multiline = map_snippet.lines().count() > 1 + || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint( + cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, + &format!("replace this with map_or({1}, {0})", map_snippet, unwrap_snippet) + ); + } + else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); + }; + } +} + +/// lint use of `map().unwrap_or_else()` for `Option`s +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr) { + let unwrap_args = match expr.node { + ExprMethodCall(_, _, ref unwrap_args) => unwrap_args, + _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or_else()` on a \ + non-matching expression!") + }; + let map_args = match unwrap_args[0].node { + ExprMethodCall(_, _, ref map_args) => map_args, + _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or_else()` on a \ + non-matching expression!") + }; + + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { + // lint message + let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more \ + directly by calling `map_or_else(g, f)` instead"; + // get snippets for args to map() and unwrap_or_else() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or_else() have the same span + let multiline = map_snippet.lines().count() > 1 + || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint( + cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg, expr.span, + &format!("replace this with map_or_else({1}, {0})", map_snippet, unwrap_snippet) + ); + } + else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); + }; + } +} + // Given a `Result<T, E>` type, return its error type (`E`) fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { diff --git a/src/utils.rs b/src/utils.rs index 1ce97ccea4e..479ee142514 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -136,6 +136,7 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { false } } + /// check if method call given in "expr" belongs to given trait pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); @@ -163,6 +164,27 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { |(a, b)| a.identifier.name.as_str() == *b) } +/// match an Expr against a chain of methods. For example, if `expr` represents the `.baz()` in +/// `foo.bar().baz()`, `matched_method_chain(expr, &["bar", "baz"])` will return true. +pub fn match_method_chain(expr: &Expr, methods: &[&str]) -> bool { + let mut current = &expr.node ; + for method_name in methods.iter().rev() { // method chains are stored last -> first + if let ExprMethodCall(ref name, _, ref args) = *current { + if name.node.as_str() == *method_name { + current = &args[0].node + } + else { + return false; + } + } + else { + return false; + } + } + true +} + + /// get the name of the item the expression is in, if available pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); -- cgit 1.4.1-3-g733a5 From 29b53d600f63b998eaf3d723ee0da90379b7a8b8 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Sun, 27 Dec 2015 14:15:09 -0800 Subject: Replace `match_method_chain()` with `method_chain_args()` --- src/methods.rs | 92 ++++++++++++++++++---------------------------------------- src/utils.rs | 25 ++++++++++------ 2 files changed, 44 insertions(+), 73 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 31e3bfb8f4a..d4809d374a3 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -5,9 +5,10 @@ use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; -use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, match_method_chain, +use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, walk_ptrs_ty_depth, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; +use utils::MethodArgs; use self::SelfKind::*; use self::OutType::*; @@ -158,20 +159,20 @@ impl LintPass for MethodsPass { impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(_, _, _) = expr.node { - if match_method_chain(expr, &["unwrap"]) { - lint_unwrap(cx, expr); + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + lint_unwrap(cx, expr, arglists[0]); } - else if match_method_chain(expr, &["to_string"]) { - lint_to_string(cx, expr); + else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { + lint_to_string(cx, expr, arglists[0]); } - else if match_method_chain(expr, &["ok", "expect"]) { - lint_ok_expect(cx, expr); + else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { + lint_ok_expect(cx, expr, arglists[0]); } - else if match_method_chain(expr, &["map", "unwrap_or"]) { - lint_map_unwrap_or(cx, expr); + else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { + lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); } - else if match_method_chain(expr, &["map", "unwrap_or_else"]) { - lint_map_unwrap_or_else(cx, expr); + else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { + lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); } } } @@ -218,15 +219,10 @@ impl LateLintPass for MethodsPass { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `unwrap()` for `Option`s and `Result`s -fn lint_unwrap(cx: &LateContext, expr: &Expr) { - let args = match expr.node { - ExprMethodCall(_, _, ref args) => args, - _ => panic!("clippy methods.rs: should not have called `lint_unwrap()` on a non-matching \ - expression!"), - }; - - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); +fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); if match_type(cx, obj_ty, &OPTION_PATH) { span_lint(cx, OPTION_UNWRAP_USED, expr.span, @@ -239,18 +235,13 @@ fn lint_unwrap(cx: &LateContext, expr: &Expr) { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `to_string()` for `&str`s and `String`s -fn lint_to_string(cx: &LateContext, expr: &Expr) { - let args = match expr.node { - ExprMethodCall(_, _, ref args) => args, - _ => panic!("clippy methods.rs: should not have called `lint_to_string()` on a \ - non-matching expression!"), - }; - - let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); +fn lint_to_string(cx: &LateContext, expr: &Expr, to_string_args: &MethodArgs) { + let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&to_string_args[0])); if obj_ty.sty == ty::TyStr { - let mut arg_str = snippet(cx, args[0].span, "_"); + let mut arg_str = snippet(cx, to_string_args[0].span, "_"); if ptr_depth > 1 { arg_str = Cow::Owned(format!( "({}{})", @@ -266,19 +257,9 @@ fn lint_to_string(cx: &LateContext, expr: &Expr) { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext, expr: &Expr) { - let expect_args = match expr.node { - ExprMethodCall(_, _, ref expect_args) => expect_args, - _ => panic!("clippy methods.rs: Should not have called `lint_ok_expect()` on a \ - non-matching expression!") - }; - let ok_args = match expect_args[0].node { - ExprMethodCall(_, _, ref ok_args) => ok_args, - _ => panic!("clippy methods.rs: Should not have called `lint_ok_expect()` on a \ - non-matching expression!") - }; - +fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { // lint if the caller of `ok()` is a `Result` if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &RESULT_PATH) { let result_type = cx.tcx.expr_ty(&ok_args[0]); @@ -292,19 +273,10 @@ fn lint_ok_expect(cx: &LateContext, expr: &Expr) { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr) { - let unwrap_args = match expr.node { - ExprMethodCall(_, _, ref unwrap_args) => unwrap_args, - _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or()` on a \ - non-matching expression!") - }; - let map_args = match unwrap_args[0].node { - ExprMethodCall(_, _, ref map_args) => map_args, - _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or()` on a \ - non-matching expression!") - }; - +fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs, + map_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message @@ -330,19 +302,11 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr) { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr) { - let unwrap_args = match expr.node { - ExprMethodCall(_, _, ref unwrap_args) => unwrap_args, - _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or_else()` on a \ - non-matching expression!") - }; - let map_args = match unwrap_args[0].node { - ExprMethodCall(_, _, ref map_args) => map_args, - _ => panic!("clippy methods.rs: Should not have called `lint_map_unwrap_or_else()` on a \ - non-matching expression!") - }; - +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs, + map_args: &MethodArgs) { + // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more \ diff --git a/src/utils.rs b/src/utils.rs index 479ee142514..2ff498b5646 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,10 +8,13 @@ use rustc::middle::ty; use std::borrow::Cow; use syntax::ast::Lit_::*; use syntax::ast; +use syntax::ptr::P; use rustc::session::Session; use std::str::FromStr; +pub type MethodArgs = HirVec<P<Expr>>; + // module DefPaths for certain structs/enums we check for pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; @@ -164,24 +167,28 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { |(a, b)| a.identifier.name.as_str() == *b) } -/// match an Expr against a chain of methods. For example, if `expr` represents the `.baz()` in -/// `foo.bar().baz()`, `matched_method_chain(expr, &["bar", "baz"])` will return true. -pub fn match_method_chain(expr: &Expr, methods: &[&str]) -> bool { - let mut current = &expr.node ; +/// match an Expr against a chain of methods, and return the matched Exprs. For example, if `expr` +/// represents the `.baz()` in `foo.bar().baz()`, `matched_method_chain(expr, &["bar", "baz"])` +/// will return a Vec containing the Exprs for `.bar()` and `.baz()` +pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { + let mut current = expr; + let mut matched = Vec::with_capacity(methods.len()); for method_name in methods.iter().rev() { // method chains are stored last -> first - if let ExprMethodCall(ref name, _, ref args) = *current { + if let ExprMethodCall(ref name, _, ref args) = current.node { if name.node.as_str() == *method_name { - current = &args[0].node + matched.push(args); // build up `matched` backwards + current = &args[0] // go to parent expression } else { - return false; + return None; } } else { - return false; + return None; } } - true + matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` + Some(matched) } -- cgit 1.4.1-3-g733a5 From 07830c44af2bc95332b36b51434bd73300c33fc1 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Mon, 28 Dec 2015 23:12:57 +0900 Subject: Extend escape analysis to arguments --- src/escape.rs | 15 ++++++++++++++- tests/compile-fail/box_vec.rs | 3 ++- tests/compile-fail/escape_analysis.rs | 6 +++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index 63894cda9be..9ee9d7ff344 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -31,6 +31,13 @@ pub struct EscapePass; /// ``` declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); +fn is_box(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyBox(..) => true, + _ => false + } +} + struct EscapeDelegate<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, set: NodeSet, @@ -87,6 +94,12 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { + if self.cx.tcx.map.is_argument(consume_pat.id) { + if is_box(cmt.ty) { + self.set.insert(consume_pat.id); + } + return; + } if let Categorization::Rvalue(..) = cmt.cat { if let Some(Node::NodeStmt(st)) = self.cx .tcx @@ -96,7 +109,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { if let ExprBox(..) = ex.node { - if let ty::TyBox(..) = cmt.ty.sty { + if is_box(cmt.ty) { // let x = box (...) self.set.insert(consume_pat.id); } diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs index 58e780f190c..65275923dc5 100644 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -1,7 +1,8 @@ #![feature(plugin)] - #![plugin(clippy)] + #![deny(clippy)] +#![allow(boxed_local)] pub fn test(foo: Box<Vec<bool>>) { //~ ERROR you seem to be trying to use `Box<Vec<T>>` println!("{:?}", foo.get(0)) diff --git a/tests/compile-fail/escape_analysis.rs b/tests/compile-fail/escape_analysis.rs index 3782cb96da5..28154d9414e 100644 --- a/tests/compile-fail/escape_analysis.rs +++ b/tests/compile-fail/escape_analysis.rs @@ -19,6 +19,10 @@ fn warn_call() { x.foo(); } +fn warn_arg(x: Box<A>) { //~ ERROR local variable + x.foo(); +} + fn warn_rename_call() { let x = box A; @@ -78,4 +82,4 @@ fn warn_match() { match &x { // not moved ref y => () } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From bbd439ec9ea3ef20edefa319b479cb06739ba52d Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Mon, 28 Dec 2015 16:56:58 -0800 Subject: Add FILTER_NEXT lint --- README.md | 7 ++++--- src/lib.rs | 1 + src/methods.rs | 37 ++++++++++++++++++++++++++++++++++--- tests/compile-fail/methods.rs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2c8b20f83a9..9840eda8d39 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 86 lints included in this crate: +There are 87 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -28,6 +28,7 @@ name [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` @@ -55,8 +56,8 @@ name [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result -[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`) -[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`) +[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` +[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing [panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` diff --git a/src/lib.rs b/src/lib.rs index adc1d402e92..4caf008e330 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,6 +176,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_BOOL, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, + methods::FILTER_NEXT, methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, diff --git a/src/methods.rs b/src/methods.rs index d4809d374a3..f2f7dbdea9c 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -6,7 +6,7 @@ use std::iter; use std::borrow::Cow; use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, - walk_ptrs_ty_depth, walk_ptrs_ty}; + match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; use utils::MethodArgs; @@ -135,7 +135,7 @@ declare_lint!(pub OK_EXPECT, Warn, /// **Example:** `x.map(|a| a + 1).unwrap_or(0)` declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ - `map_or(a, f)`)"); + `map_or(a, f)`"); /// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`. /// @@ -146,7 +146,17 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, /// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)` declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`)"); + `map_or_else(g, f)`"); + +/// **What it does:** This lint `Warn`s on `_.filter(_).next()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.find(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `iter.filter(|x| x == 0).next()` +declare_lint!(pub FILTER_NEXT, Warn, + "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"); impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { @@ -174,6 +184,9 @@ impl LateLintPass for MethodsPass { else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); } + else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { + lint_filter_next(cx, expr, arglists[0]); + } } } @@ -331,6 +344,24 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, unwrap_args: &MethodAr } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +/// lint use of `filter().next() for Iterators` +fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { + // lint if caller of `.filter().next()` is an Iterator + if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by \ + calling `.find(p)` instead."; + let filter_snippet = snippet(cx, filter_args[1].span, ".."); + if filter_snippet.lines().count() <= 1 { // add note if not multi-line + span_note_and_lint(cx, FILTER_NEXT, expr.span, msg, expr.span, + &format!("replace this with `find({})`)", filter_snippet)); + } + else { + span_lint(cx, FILTER_NEXT, expr.span, msg); + } + } +} + // Given a `Result<T, E>` type, return its error type (`E`) fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 9078a78d6fe..d2fed0f907b 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -83,6 +83,39 @@ fn option_methods() { } +/// Struct to generate false positive for FILTER_NEXT lint +struct FilterNextTest { + _foo: u32, +} + +impl FilterNextTest { + fn filter(self) -> FilterNextTest { + self + } + fn next(self) -> FilterNextTest { + self + } +} + +/// Checks implementation of FILTER_NEXT lint +fn filter_next() { + let v = vec![3, 2, 1, 0, -1, -2, -3]; + + // check single-line case + let _ = v.iter().filter(|&x| *x < 0).next(); //~ERROR called `filter(p).next()` on an Iterator. + //~| NOTE replace this + + // check multi-line case + let _ = v.iter().filter(|&x| { //~ERROR called `filter(p).next()` on an Iterator. + *x < 0 + } + ).next(); + + // check that we don't lint if the caller is not an Iterator + let foo = FilterNextTest { _foo: 0 }; + let _ = foo.filter().next(); +} + fn main() { use std::io; -- cgit 1.4.1-3-g733a5 From e7f3fa6713c24882c5a8affe506e2c17dc50f1fa Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 29 Dec 2015 10:25:53 +0530 Subject: Remove * dep --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5c35f9f4271..4bae9f5aa22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ name = "clippy" plugin = true [dependencies] -unicode-normalization = "*" +unicode-normalization = "0.1" [dev-dependencies] compiletest_rs = "0.0.11" -- cgit 1.4.1-3-g733a5 From a6bd2d06227fa315c7a404d61dee9ded4a1e45bc Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Wed, 30 Dec 2015 00:38:03 -0800 Subject: Add SEARCH_IS_SOME lint --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 40 ++++++++++++++++++++++++++ tests/compile-fail/methods.rs | 66 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9840eda8d39..9fe59d4fdaf 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 87 lints included in this crate: +There are 88 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -69,6 +69,7 @@ name [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` +[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` [shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value diff --git a/src/lib.rs b/src/lib.rs index 4caf008e330..6d39cad20cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -180,6 +180,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, + methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, methods::STRING_TO_STRING, diff --git a/src/methods.rs b/src/methods.rs index f2f7dbdea9c..081e64b53ea 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -158,6 +158,18 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, declare_lint!(pub FILTER_NEXT, Warn, "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"); +/// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or +/// `rposition()`) followed by a call to `is_some()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.any(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `iter.find(|x| x == 0).is_some()` +declare_lint!(pub SEARCH_IS_SOME, Warn, + "using an iterator search followed by `is_some()`, which is more succinctly \ + expressed as a call to `any()`"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, @@ -187,6 +199,15 @@ impl LateLintPass for MethodsPass { else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { lint_filter_next(cx, expr, arglists[0]); } + else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { + lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); + } + else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { + lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); + } + else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { + lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); + } } } @@ -362,6 +383,25 @@ fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { } } +#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +/// lint searching an Iterator followed by `is_some()` +fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, search_args: &MethodArgs, + is_some_args: &MethodArgs) { + // lint if caller of search is an Iterator + if match_trait_method(cx, &*is_some_args[0], &["core", "iter", "Iterator"]) { + let msg = format!("called `is_some()` after searching an iterator with {}. This is more \ + succinctly expressed by calling `any()`.", search_method); + let search_snippet = snippet(cx, search_args[1].span, ".."); + if search_snippet.lines().count() <= 1 { // add note if not multi-line + span_note_and_lint(cx, SEARCH_IS_SOME, expr.span, &msg, expr.span, + &format!("replace this with `any({})`)", search_snippet)); + } + else { + span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); + } + } +} + // Given a `Result<T, E>` type, return its error type (`E`) fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index d2fed0f907b..1878ae15b75 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -83,18 +83,32 @@ fn option_methods() { } -/// Struct to generate false positive for FILTER_NEXT lint -struct FilterNextTest { - _foo: u32, +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +struct IteratorFalsePositives { + foo: u32, } -impl FilterNextTest { - fn filter(self) -> FilterNextTest { +impl IteratorFalsePositives { + fn filter(self) -> IteratorFalsePositives { self } - fn next(self) -> FilterNextTest { + + fn next(self) -> IteratorFalsePositives { self } + + fn find(self) -> Option<u32> { + Some(self.foo) + } + + fn position(self) -> Option<u32> { + Some(self.foo) + } + + fn rposition(self) -> Option<u32> { + Some(self.foo) + } } /// Checks implementation of FILTER_NEXT lint @@ -112,10 +126,48 @@ fn filter_next() { ).next(); // check that we don't lint if the caller is not an Iterator - let foo = FilterNextTest { _foo: 0 }; + let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.filter().next(); } +/// Checks implementation of SEARCH_IS_SOME lint +fn search_is_some() { + let v = vec![3, 2, 1, 0, -1, -2, -3]; + + // check `find().is_some()`, single-line + let _ = v.iter().find(|&x| *x < 0).is_some(); //~ERROR called `is_some()` after searching + //~| NOTE replace this + // check `find().is_some()`, multi-line + let _ = v.iter().find(|&x| { //~ERROR called `is_some()` after searching + *x < 0 + } + ).is_some(); + + // check `position().is_some()`, single-line + let _ = v.iter().position(|&x| x < 0).is_some(); //~ERROR called `is_some()` after searching + //~| NOTE replace this + // check `position().is_some()`, multi-line + let _ = v.iter().position(|&x| { //~ERROR called `is_some()` after searching + x < 0 + } + ).is_some(); + + // check `rposition().is_some()`, single-line + let _ = v.iter().rposition(|&x| x < 0).is_some(); //~ERROR called `is_some()` after searching + //~| NOTE replace this + // check `rposition().is_some()`, multi-line + let _ = v.iter().rposition(|&x| { //~ERROR called `is_some()` after searching + x < 0 + } + ).is_some(); + + // check that we don't lint if the caller is not an Iterator + let foo = IteratorFalsePositives { foo: 0 }; + let _ = foo.find().is_some(); + let _ = foo.position().is_some(); + let _ = foo.rposition().is_some(); +} + fn main() { use std::io; -- cgit 1.4.1-3-g733a5 From 2c42d46468e7a047841c89d1ebdd517917bb12a2 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Wed, 30 Dec 2015 00:55:38 -0800 Subject: Bug fix --- src/methods.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 081e64b53ea..5515ba17bf0 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -309,8 +309,8 @@ fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs, - map_args: &MethodArgs) { +fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, + unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message @@ -338,8 +338,8 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs, #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs, - map_args: &MethodArgs) { +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, + unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message -- cgit 1.4.1-3-g733a5 From 093582c102b4ca983e9b6ef620860a75f6a1d812 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Wed, 30 Dec 2015 01:07:40 -0800 Subject: Make MethodsPass lint notes clearer --- src/methods.rs | 11 +++++++---- tests/compile-fail/methods.rs | 27 +++++++++++++++++---------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 5515ba17bf0..a6200534e30 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -327,7 +327,8 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, if same_span && !multiline { span_note_and_lint( cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, - &format!("replace this with map_or({1}, {0})", map_snippet, unwrap_snippet) + &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", map_snippet, + unwrap_snippet) ); } else if same_span && multiline { @@ -356,7 +357,8 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, if same_span && !multiline { span_note_and_lint( cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg, expr.span, - &format!("replace this with map_or_else({1}, {0})", map_snippet, unwrap_snippet) + &format!("replace `map({0}).unwrap_or_else({1})` with `with map_or_else({1}, {0})`", + map_snippet, unwrap_snippet) ); } else if same_span && multiline { @@ -375,7 +377,7 @@ fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { let filter_snippet = snippet(cx, filter_args[1].span, ".."); if filter_snippet.lines().count() <= 1 { // add note if not multi-line span_note_and_lint(cx, FILTER_NEXT, expr.span, msg, expr.span, - &format!("replace this with `find({})`)", filter_snippet)); + &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); } else { span_lint(cx, FILTER_NEXT, expr.span, msg); @@ -394,7 +396,8 @@ fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, searc let search_snippet = snippet(cx, search_args[1].span, ".."); if search_snippet.lines().count() <= 1 { // add note if not multi-line span_note_and_lint(cx, SEARCH_IS_SOME, expr.span, &msg, expr.span, - &format!("replace this with `any({})`)", search_snippet)); + &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, + search_snippet)); } else { span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 1878ae15b75..b41b28dc11e 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -50,7 +50,7 @@ fn option_methods() { // Check OPTION_MAP_UNWRAP_OR // single line case let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or(a)` - //~| NOTE replace this + //~| NOTE replace `map(|x| x + 1).unwrap_or(0)` .unwrap_or(0); // should lint even though this call is on a separate line // multi line cases let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or(a)` @@ -67,7 +67,7 @@ fn option_methods() { // Check OPTION_MAP_UNWRAP_OR_ELSE // single line case let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or_else(g)` - //~| NOTE replace this + //~| NOTE replace `map(|x| x + 1).unwrap_or_else(|| 0)` .unwrap_or_else(|| 0); // should lint even though this call is on a separate line // multi line cases let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or_else(g)` @@ -116,8 +116,9 @@ fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; // check single-line case - let _ = v.iter().filter(|&x| *x < 0).next(); //~ERROR called `filter(p).next()` on an Iterator. - //~| NOTE replace this + let _ = v.iter().filter(|&x| *x < 0).next(); + //~^ ERROR called `filter(p).next()` on an Iterator. + //~| NOTE replace `filter(|&x| *x < 0).next()` // check multi-line case let _ = v.iter().filter(|&x| { //~ERROR called `filter(p).next()` on an Iterator. @@ -135,8 +136,10 @@ fn search_is_some() { let v = vec![3, 2, 1, 0, -1, -2, -3]; // check `find().is_some()`, single-line - let _ = v.iter().find(|&x| *x < 0).is_some(); //~ERROR called `is_some()` after searching - //~| NOTE replace this + let _ = v.iter().find(|&x| *x < 0).is_some(); + //~^ ERROR called `is_some()` after searching + //~| NOTE replace `find(|&x| *x < 0).is_some()` + // check `find().is_some()`, multi-line let _ = v.iter().find(|&x| { //~ERROR called `is_some()` after searching *x < 0 @@ -144,8 +147,10 @@ fn search_is_some() { ).is_some(); // check `position().is_some()`, single-line - let _ = v.iter().position(|&x| x < 0).is_some(); //~ERROR called `is_some()` after searching - //~| NOTE replace this + let _ = v.iter().position(|&x| x < 0).is_some(); + //~^ ERROR called `is_some()` after searching + //~| NOTE replace `position(|&x| x < 0).is_some()` + // check `position().is_some()`, multi-line let _ = v.iter().position(|&x| { //~ERROR called `is_some()` after searching x < 0 @@ -153,8 +158,10 @@ fn search_is_some() { ).is_some(); // check `rposition().is_some()`, single-line - let _ = v.iter().rposition(|&x| x < 0).is_some(); //~ERROR called `is_some()` after searching - //~| NOTE replace this + let _ = v.iter().rposition(|&x| x < 0).is_some(); + //~^ ERROR called `is_some()` after searching + //~| NOTE replace `rposition(|&x| x < 0).is_some()` + // check `rposition().is_some()`, multi-line let _ = v.iter().rposition(|&x| { //~ERROR called `is_some()` after searching x < 0 -- cgit 1.4.1-3-g733a5 From 06f30a61dd2a948c58907ef9ebb80b040e930450 Mon Sep 17 00:00:00 2001 From: Johannes Linke <johannes.linke@posteo.de> Date: Fri, 1 Jan 2016 17:48:19 +0100 Subject: Add "warn/allow by default" to lint descriptions where it was missing. --- src/attrs.rs | 2 +- src/block_in_if_condition.rs | 4 ++-- src/escape.rs | 2 +- src/loops.rs | 4 ++-- src/minmax.rs | 2 +- src/misc.rs | 2 +- src/mut_reference.rs | 2 +- src/strings.rs | 2 +- src/types.rs | 5 +++-- src/zero_div_zero.rs | 2 +- 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 0882f3af41f..f0dbf390ebb 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -8,7 +8,7 @@ use syntax::attr::*; use syntax::ast::{Attribute, MetaList, MetaWord}; use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; -/// **What it does:** This lint warns on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. +/// **What it does:** This lint `Warn`s on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. /// /// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it. /// diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index f7c181f5fd8..03265635b1d 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -3,7 +3,7 @@ use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; use rustc_front::intravisit::{Visitor, walk_expr}; use utils::*; -/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. +/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. It is `Warn` by default. /// /// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions. /// @@ -15,7 +15,7 @@ declare_lint! { "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" } -/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. +/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. It is `Warn` by default. /// /// **Why is this bad?** Using blocks in the condition makes it hard to read. /// diff --git a/src/escape.rs b/src/escape.rs index 63894cda9be..21bf30e131c 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -14,7 +14,7 @@ use utils::span_lint; pub struct EscapePass; -/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine +/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. It is `Warn` by default. /// /// **Why is this bad?** This is an unnecessary allocation, and bad for performance /// diff --git a/src/loops.rs b/src/loops.rs index 5c552d2ce42..9f103f4e7a8 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -50,7 +50,7 @@ declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, declare_lint!{ pub ITER_NEXT_LOOP, Warn, "for-looping over `_.next()` which is probably not intended" } -/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. +/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default. /// /// **Why is this bad?** The `while let` loop is usually shorter and more readable /// @@ -85,7 +85,7 @@ declare_lint!{ pub UNUSED_COLLECT, Warn, "`collect()`ing an iterator without using the result; this is usually better \ written as a for loop" } -/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. +/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. It is `Warn` by default. /// /// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended. /// diff --git a/src/minmax.rs b/src/minmax.rs index ac8d6f05272..b63e839612c 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -8,7 +8,7 @@ use consts::{Constant, constant_simple}; use utils::{match_def_path, span_lint}; use self::MinMax::{Min, Max}; -/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. +/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. It is `Warn` by default. /// /// **Why is this bad?** This is in all probability not the intended outcome. At the least it hurts readability of the code. /// diff --git a/src/misc.rs b/src/misc.rs index 139dfde3681..92276961d11 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -281,7 +281,7 @@ impl LateLintPass for ModuloOne { } } -/// **What it does:** This lint checks for patterns in the form `name @ _`. +/// **What it does:** This lint checks for patterns in the form `name @ _`. It is `Warn` by default. /// /// **Why is this bad?** It's almost always more readable to just use direct bindings. /// diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 9ba9782336a..133462071e4 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -4,7 +4,7 @@ use utils::span_lint; use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; use syntax::ptr::P; -/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. +/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. It is `Warn` by default. /// /// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site. /// diff --git a/src/strings.rs b/src/strings.rs index b567d949330..d60a045aa75 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -11,7 +11,7 @@ use eq_op::is_exp_equal; use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; -/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!) +/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). It is `Allow` by default. /// /// **Why is this bad?** Because this expression needs another copy as opposed to `x.push_str(y)` (in practice LLVM will usually elide it, though). Despite [llogiq](https://github.com/llogiq)'s reservations, this lint also is `allow` by default, as some people opine that it's more readable. /// diff --git a/src/types.rs b/src/types.rs index 9bc50643259..f332659188b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ use utils::{LL_PATH, VEC_PATH}; #[allow(missing_copy_implementations)] pub struct TypePass; -/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. +/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. It is `Warn` by default. /// /// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever. /// @@ -26,7 +26,8 @@ pub struct TypePass; /// **Example:** `struct X { values: Box<Vec<Foo>> }` declare_lint!(pub BOX_VEC, Warn, "usage of `Box<Vec<T>>`, vector elements are already on the heap"); -/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). + +/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). It is `Warn` by default. /// /// **Why is this bad?** Gankro says: /// diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index c4d7cf4a589..5a4d3931606 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -9,7 +9,7 @@ use consts::{Constant, constant_simple, FloatWidth}; /// 0.0/0.0 with std::f32::NaN or std::f64::NaN, depending on the precision. pub struct ZeroDivZeroPass; -/// **What it does:** This lint checks for `0.0 / 0.0` +/// **What it does:** This lint checks for `0.0 / 0.0`. It is `Warn` by default. /// /// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN` /// -- cgit 1.4.1-3-g733a5 From b287739c0b2e4d6202d94eb2a20a385a69c74d63 Mon Sep 17 00:00:00 2001 From: Johannes Linke <johannes.linke@posteo.de> Date: Fri, 1 Jan 2016 17:48:46 +0100 Subject: Remove reference to a fixed issue --- src/map_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map_clone.rs b/src/map_clone.rs index b1ba47a9b54..ef992ad086c 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -8,7 +8,7 @@ use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; /// /// **Why is this bad?** It makes the code less readable. /// -/// **Known problems:** False negative: The lint currently misses mapping `Clone::clone` directly. Issue #436 is tracking this. +/// **Known problems:** None /// /// **Example:** `x.map(|e| e.clone());` declare_lint!(pub MAP_CLONE, Warn, -- cgit 1.4.1-3-g733a5 From f89e4005784abfe0b71a2c24fbd2fa007e57a61a Mon Sep 17 00:00:00 2001 From: Johannes Linke <johannes.linke@posteo.de> Date: Fri, 1 Jan 2016 17:49:01 +0100 Subject: Minor documentation cleanups --- src/escape.rs | 4 ++-- src/mut_reference.rs | 8 ++++---- src/precedence.rs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index 21bf30e131c..4b6a8258dbe 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -16,9 +16,9 @@ pub struct EscapePass; /// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. It is `Warn` by default. /// -/// **Why is this bad?** This is an unnecessary allocation, and bad for performance +/// **Why is this bad?** This is an unnecessary allocation, and bad for performance. It is only necessary to allocate if you wish to move the box into something. /// -/// It is only necessary to allocate if you wish to move the box into something. +/// **Known problems:** None /// /// **Example:** /// diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 133462071e4..ddfd9ddcc13 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -36,7 +36,7 @@ impl LateLintPass for UnnecessaryMutPassed { match borrowed_table.node_types.get(&fn_expr.id) { Some(function_type) => { if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, &arguments, function_type, + check_arguments(cx, &arguments, function_type, &format!("{}", path)); } } @@ -50,7 +50,7 @@ impl LateLintPass for UnnecessaryMutPassed { ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); match borrowed_table.method_map.get(&method_call) { - Some(method_type) => check_arguments(cx, &arguments, method_type.ty, + Some(method_type) => check_arguments(cx, &arguments, method_type.ty, &format!("{}", name.node.as_str())), None => unreachable!(), // Just like above, this should never happen. }; @@ -68,9 +68,9 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, UNNECESSARY_MUT_PASSED, + span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, &format!("The function/method \"{}\" \ - doesn't need a mutable reference", + doesn't need a mutable reference", name)); } } diff --git a/src/precedence.rs b/src/precedence.rs index 39a3e9e56c2..3aae9fd0d6c 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use utils::{span_lint, snippet}; -/// **What it does:** This lint checks for operations where precedence may be unclear and `Warn`'s about them by default, suggesting to add parentheses. Currently it catches the following: +/// **What it does:** This lint checks for operations where precedence may be unclear and `Warn`s about them by default, suggesting to add parentheses. Currently it catches the following: /// * mixed usage of arithmetic and bit shifting/combining operators without parentheses /// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call /// @@ -33,17 +33,17 @@ impl EarlyLintPass for Precedence { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if !is_bit_op(op) { return; } match (is_arith_expr(left), is_arith_expr(right)) { - (true, true) => span_lint(cx, PRECEDENCE, expr.span, + (true, true) => span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} ({})`", snippet(cx, left.span, ".."), op.to_string(), snippet(cx, right.span, ".."))), - (true, false) => span_lint(cx, PRECEDENCE, expr.span, + (true, false) => span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} {}`", snippet(cx, left.span, ".."), op.to_string(), snippet(cx, right.span, ".."))), - (false, true) => span_lint(cx, PRECEDENCE, expr.span, + (false, true) => span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `{} {} ({})`", snippet(cx, left.span, ".."), -- cgit 1.4.1-3-g733a5 From bd8a265000a25b5cb06fd12a5201d6e347163279 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Sat, 2 Jan 2016 05:52:13 +0100 Subject: Add help on field binding --- src/misc_early.rs | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/misc_early.rs b/src/misc_early.rs index 1520e9c0e58..dafe7816fe4 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::span_lint; +use utils::{span_lint, span_help_and_lint}; /// **What it does:** This lint `Warn`s on struct field patterns bound to wildcards. /// @@ -27,8 +27,12 @@ impl LintPass for MiscEarly { impl EarlyLintPass for MiscEarly { fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { - if let PatStruct(_, ref pfields, _) = pat.node { + if let PatStruct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; + let type_name = match npat.segments.last() { + Some(elem) => format!("{}", elem.identifier.name), + None => String::new(), + }; for field in pfields { if field.node.pat.node == PatWild { @@ -36,17 +40,38 @@ impl EarlyLintPass for MiscEarly { } } if !pfields.is_empty() && wilds == pfields.len() { - span_lint(cx, UNNEEDED_FIELD_PATTERN, pat.span, - "All the struct fields are matched to a wildcard pattern, \ - consider using `..`."); + span_help_and_lint(cx, UNNEEDED_FIELD_PATTERN, pat.span, + "All the struct fields are matched to a wildcard pattern, \ + consider using `..`.", + &format!("Try with `{} {{ .. }}` instead", + type_name)); return; } if wilds > 0 { + let mut normal = vec!(); + + for field in pfields { + if field.node.pat.node != PatWild { + if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { + normal.push(n); + } + } + } for field in pfields { if field.node.pat.node == PatWild { - span_lint(cx, UNNEEDED_FIELD_PATTERN, field.span, - "You matched a field with a wildcard pattern. \ - Consider using `..` instead"); + wilds -= 1; + if wilds > 0 { + span_lint(cx, UNNEEDED_FIELD_PATTERN, field.span, + "You matched a field with a wildcard pattern. \ + Consider using `..` instead"); + } else { + span_help_and_lint(cx, UNNEEDED_FIELD_PATTERN, field.span, + "You matched a field with a wildcard pattern. \ + Consider using `..` instead", + &format!("Try with `{} {{ {}, .. }}`", + type_name, + normal[..].join(", "))); + } } } } -- cgit 1.4.1-3-g733a5 From 1605ef6ed48fded84b7b8556c9b65809c5aba1ad Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 1 Jan 2016 02:09:03 +0530 Subject: Rustup to syntax::errors changes --- Cargo.toml | 2 +- src/cyclomatic_complexity.rs | 13 ++--- src/eta_reduction.rs | 4 +- src/len_zero.rs | 2 +- src/minmax.rs | 2 +- src/mut_mut.rs | 8 +-- src/mutex_atomic.rs | 2 +- src/precedence.rs | 23 +++++--- src/returns.rs | 8 +-- src/shadow.rs | 22 ++++---- src/strings.rs | 4 +- src/utils.rs | 82 ++++++++++++++++++++--------- tests/compile-fail/cyclomatic_complexity.rs | 3 +- 13 files changed, 107 insertions(+), 68 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4bae9f5aa22..3ab2c9ef6e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.33" +version = "0.0.34" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index c2cc6a8c4ab..7beb3296aac 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -9,7 +9,7 @@ use syntax::attr::*; use syntax::ast::Attribute; use rustc_front::intravisit::{Visitor, walk_expr}; -use utils::{in_macro, LimitStack}; +use utils::{in_macro, LimitStack, span_help_and_lint}; /// **What it does:** It `Warn`s on methods with high cyclomatic complexity /// @@ -59,8 +59,8 @@ impl CyclomaticComplexity { } else { let rust_cc = cc + divergence - narms; if rust_cc > self.limit.limit() { - cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, - &format!("The function has a cyclomatic complexity of {}.", rust_cc), + span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, span, + &format!("The function has a cyclomatic complexity of {}", rust_cc), "You could split it up into multiple smaller functions"); } } @@ -140,8 +140,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { #[cfg(not(feature="debugging"))] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { - cx.sess().span_note(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): \ - cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div)); + cx.sess().span_note_without_error(span, + &format!("Clippy encountered a bug calculating cyclomatic complexity \ + (hide this message with `#[allow(cyclomatic_complexity)]`): \ + cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div)); } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index c25228793e6..6b561ff7a05 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -84,9 +84,9 @@ fn check_closure(cx: &LateContext, expr: &Expr) { } span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", - || { + |db| { if let Some(snippet) = snippet_opt(cx, caller.span) { - cx.sess().span_suggestion(expr.span, + db.span_suggestion(expr.span, "remove closure as shown:", snippet); } diff --git a/src/len_zero.rs b/src/len_zero.rs index 589b4f6ebb1..d574fa2c336 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -135,7 +135,7 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name, has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, span, &format!( "consider replacing the len comparison with `{}{}.is_empty()`", - op, snippet(cx, args[0].span, "_"))) + op, snippet(cx, args[0].span, "_"))); } } } diff --git a/src/minmax.rs b/src/minmax.rs index b63e839612c..2a8e064f9f4 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -37,7 +37,7 @@ impl LateLintPass for MinMaxPass { (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, - "this min/max combination leads to constant result") + "this min/max combination leads to constant result"); } } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index ade688d377f..db6f0e0320b 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -30,8 +30,8 @@ impl LateLintPass for MutMut { } fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, - ty.span, "generally you want to avoid `&mut &mut _` if possible")) + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| { span_lint(cx, MUT_MUT, + ty.span, "generally you want to avoid `&mut &mut _` if possible"); }); } } @@ -52,12 +52,12 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, "this expression mutably borrows a mutable reference. \ - Consider reborrowing") + Consider reborrowing"); } }, |_| { span_lint(cx, MUT_MUT, expr.span, - "generally you want to avoid `&mut &mut _` if possible") + "generally you want to avoid `&mut &mut _` if possible"); } ) }) diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 40f7d21f43c..8899eb56d42 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -63,7 +63,7 @@ impl LateLintPass for MutexAtomic { ty::TyInt(t) if t != ast::TyIs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg) - } + }; } } } diff --git a/src/precedence.rs b/src/precedence.rs index 3aae9fd0d6c..91ff0680b3e 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -33,21 +33,27 @@ impl EarlyLintPass for Precedence { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if !is_bit_op(op) { return; } match (is_arith_expr(left), is_arith_expr(right)) { - (true, true) => span_lint(cx, PRECEDENCE, expr.span, + (true, true) => { + span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} ({})`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))), - (true, false) => span_lint(cx, PRECEDENCE, expr.span, + op.to_string(), snippet(cx, right.span, ".."))); + }, + (true, false) => { + span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `({}) {} {}`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))), - (false, true) => span_lint(cx, PRECEDENCE, expr.span, + op.to_string(), snippet(cx, right.span, ".."))); + }, + (false, true) => { + span_lint(cx, PRECEDENCE, expr.span, &format!("operator precedence can trip the unwary. \ Consider parenthesizing your expression:\ `{} {} ({})`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))), + op.to_string(), snippet(cx, right.span, ".."))); + }, _ => (), } } @@ -57,12 +63,13 @@ impl EarlyLintPass for Precedence { if let Some(slf) = args.first() { if let ExprLit(ref lit) = slf.node { match lit.node { - LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => + LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => { span_lint(cx, PRECEDENCE, expr.span, &format!( "unary minus has lower precedence than \ method call. Consider adding parentheses \ to clarify your intent: -({})", - snippet(cx, rhs.span, ".."))), + snippet(cx, rhs.span, ".."))); + } _ => () } } diff --git a/src/returns.rs b/src/returns.rs index 3ef94a4c926..15f9bb80d95 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -75,9 +75,9 @@ impl ReturnPass { if in_external_macro(cx, spans.1) {return;} span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", - || { + |db| { if let Some(snippet) = snippet_opt(cx, spans.1) { - cx.sess().span_suggestion(spans.0, + db.span_suggestion(spans.0, "remove `return` as shown:", snippet); } @@ -105,11 +105,11 @@ impl ReturnPass { fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { if in_external_macro(cx, note_span) {return;} - span_lint(cx, LET_AND_RETURN, lint_span, + let mut db = span_lint(cx, LET_AND_RETURN, lint_span, "returning the result of a let binding from a block. \ Consider returning the expression directly."); if cx.current_level(LET_AND_RETURN) != Level::Allow { - cx.sess().span_note(note_span, + db.span_note(note_span, "this expression can be directly returned"); } } diff --git a/src/shadow.rs b/src/shadow.rs index 27bed50c263..1210590bbcb 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -7,7 +7,7 @@ use rustc_front::intravisit::{Visitor, FnKind}; use rustc::lint::*; use rustc::middle::def::Def::{DefVariant, DefStruct}; -use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint}; +use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. It is `Allow` by default. /// @@ -180,39 +180,39 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: &Option<T>, prev_span: Span) where T: Deref<Target=Expr> { - fn note_orig(cx: &LateContext, lint: &'static Lint, span: Span) { + fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { if cx.current_level(lint) != Level::Allow { - cx.sess().span_note(span, "previous binding is here"); + db.span_note(span, "previous binding is here"); } } if let Some(ref expr) = *init { if is_self_shadow(name, expr) { - span_lint(cx, SHADOW_SAME, span, &format!( + let db = span_lint(cx, SHADOW_SAME, span, &format!( "{} is shadowed by itself in {}", snippet(cx, lspan, "_"), snippet(cx, expr.span, ".."))); - note_orig(cx, SHADOW_SAME, prev_span); + note_orig(cx, db, SHADOW_SAME, prev_span); } else { if contains_self(name, expr) { - span_note_and_lint(cx, SHADOW_REUSE, lspan, &format!( + let db = span_note_and_lint(cx, SHADOW_REUSE, lspan, &format!( "{} is shadowed by {} which reuses the original value", snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); - note_orig(cx, SHADOW_REUSE, prev_span); + note_orig(cx, db, SHADOW_REUSE, prev_span); } else { - span_note_and_lint(cx, SHADOW_UNRELATED, lspan, &format!( + let db = span_note_and_lint(cx, SHADOW_UNRELATED, lspan, &format!( "{} is shadowed by {}", snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); - note_orig(cx, SHADOW_UNRELATED, prev_span); + note_orig(cx, db, SHADOW_UNRELATED, prev_span); } } } else { - span_lint(cx, SHADOW_UNRELATED, span, &format!( + let db = span_lint(cx, SHADOW_UNRELATED, span, &format!( "{} shadows a previous declaration", snippet(cx, lspan, "_"))); - note_orig(cx, SHADOW_UNRELATED, prev_span); + note_orig(cx, db, SHADOW_UNRELATED, prev_span); } } diff --git a/src/strings.rs b/src/strings.rs index d60a045aa75..861ae0bb012 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -75,13 +75,13 @@ impl LateLintPass for StringAdd { } span_lint(cx, STRING_ADD, e.span, "you added something to a string. \ - Consider using `String::push_str()` instead") + Consider using `String::push_str()` instead"); } } else if let ExprAssign(ref target, ref src) = e.node { if is_string(cx, target) && is_add(cx, src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ - Consider using `String::push_str()` instead") + Consider using `String::push_str()` instead"); } } } diff --git a/src/utils.rs b/src/utils.rs index 2ff498b5646..7c0ee09b3cd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,10 +8,12 @@ use rustc::middle::ty; use std::borrow::Cow; use syntax::ast::Lit_::*; use syntax::ast; +use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; use rustc::session::Session; use std::str::FromStr; +use std::ops::{Deref, DerefMut}; pub type MethodArgs = HirVec<P<Expr>>; @@ -307,63 +309,91 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c } else { None } } +pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); + +impl<'a> Drop for DiagnosticWrapper<'a> { + fn drop(&mut self) { + self.0.emit(); + } +} + +impl<'a> DerefMut for DiagnosticWrapper<'a> { + fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { + &mut self.0 + } +} + +impl<'a> Deref for DiagnosticWrapper<'a> { + type Target = DiagnosticBuilder<'a>; + fn deref(&self) -> &DiagnosticBuilder<'a> { + &self.0 + } +} + #[cfg(not(feature="structured_logging"))] -pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { - cx.span_lint(lint, sp, msg); +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, + sp: Span, msg: &str) -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { - cx.sess().fileline_help(sp, &format!("for further information visit \ + db.fileline_help(sp, &format!("for further information visit \ https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())) + lint.name_lower())); } + DiagnosticWrapper(db) } #[cfg(feature="structured_logging")] -pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, + sp: Span, msg: &str) -> DiagnosticWrapper<'a> { // lint.name / lint.desc is can give details of the lint // cx.sess().codemap() has all these nice functions for line/column/snippet details // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string - cx.span_lint(lint, sp, msg); + let mut db = cx.struct_span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { - cx.sess().fileline_help(sp, &format!("for further information visit \ + db.fileline_help(sp, &format!("for further information visit \ https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())) + lint.name_lower())); } + DiagnosticWrapper(db) } -pub fn span_help_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, - msg: &str, help: &str) { - cx.span_lint(lint, span, msg); +pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, + msg: &str, help: &str) -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { - cx.sess().fileline_help(span, &format!("{}\nfor further information \ + db.fileline_help(span, &format!("{}\nfor further information \ visit https://github.com/Manishearth/rust-clippy/wiki#{}", - help, lint.name_lower())) + help, lint.name_lower())); } + DiagnosticWrapper(db) } -pub fn span_note_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, - msg: &str, note_span: Span, note: &str) { - cx.span_lint(lint, span, msg); +pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, + msg: &str, note_span: Span, note: &str) -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { if note_span == span { - cx.sess().fileline_note(note_span, note) + db.fileline_note(note_span, note); } else { - cx.sess().span_note(note_span, note) + db.span_note(note_span, note); } - cx.sess().fileline_help(span, &format!("for further information visit \ + db.fileline_help(span, &format!("for further information visit \ https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())) + lint.name_lower())); } + DiagnosticWrapper(db) } -pub fn span_lint_and_then<T: LintContext, F>(cx: &T, lint: &'static Lint, sp: Span, - msg: &str, f: F) where F: Fn() { - cx.span_lint(lint, sp, msg); +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, + msg: &str, f: F) -> DiagnosticWrapper<'a> where F: Fn(&mut DiagnosticWrapper) { + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { - f(); - cx.sess().fileline_help(sp, &format!("for further information visit \ + f(&mut db); + db.fileline_help(sp, &format!("for further information visit \ https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())) + lint.name_lower())); } + db } /// return the base type for references and raw pointers diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 1a6dfd28728..f79440af121 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -4,7 +4,8 @@ #![deny(cyclomatic_complexity)] #![allow(unused)] -fn main() { //~ ERROR: The function has a cyclomatic complexity of 28. + +fn main() { //~ERROR The function has a cyclomatic complexity of 28 if true { println!("a"); } -- cgit 1.4.1-3-g733a5 From c11d140ebf1f4027868a52aa5d67e28e567ef844 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 2 Jan 2016 16:10:31 +0530 Subject: Bump to 35 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3ab2c9ef6e8..2b203e8b796 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.34" +version = "0.0.35" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 32cf6e32f66980cea7630edacaa66d1bd0497b2e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 2 Jan 2016 16:33:44 +0530 Subject: Improve documentation on match_ref_pats (fixes #532) --- README.md | 2 +- src/matches.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9fe59d4fdaf..0e0a60537b4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ name [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match has all arms prefixed with `&`; the match expression can be dereferenced instead +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) diff --git a/src/matches.rs b/src/matches.rs index 460893d93ab..aaf41a391cb 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -22,7 +22,7 @@ use utils::{snippet, span_lint, span_help_and_lint, in_external_macro, expr_bloc declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ is `_ => {}`) is used; recommends `if let` instead"); -/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It is `Warn` by default. +/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. It is `Warn` by default. /// /// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. /// @@ -38,7 +38,7 @@ declare_lint!(pub SINGLE_MATCH, Warn, /// } /// ``` declare_lint!(pub MATCH_REF_PATS, Warn, - "a match has all arms prefixed with `&`; the match expression can be \ + "a match or `if let` has all arms prefixed with `&`; the match expression can be \ dereferenced instead"); /// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default. /// -- cgit 1.4.1-3-g733a5 From a745efd5665b1c9a0d7e6af3f34493093896b701 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 2 Jan 2016 21:41:48 +0530 Subject: Add smarter macro check for block_in_if (fixes #528) --- src/block_in_if_condition.rs | 7 ++++++- src/utils.rs | 4 ++++ tests/compile-fail/block_in_if_condition.rs | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 03265635b1d..ce01f591c59 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -79,13 +79,18 @@ impl LateLintPass for BlockInIfCondition { if let Some(ref ex) = block.expr { // don't dig into the expression here, just suggest that they remove // the block - + if differing_macro_contexts(expr.span, ex.span) { + return; + } span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_EXPR, check.span, BRACED_EXPR_MESSAGE, &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), snippet_block(cx, then.span, ".."))); } } else { + if differing_macro_contexts(expr.span, block.stmts[0].span) { + return; + } // move block higher span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, check.span, COMPLEX_BLOCK_MESSAGE, diff --git a/src/utils.rs b/src/utils.rs index 7c0ee09b3cd..90e8e27b4f0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -74,6 +74,10 @@ macro_rules! if_let_chain { }; } +/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one isn't) +pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { + sp1.expn_id != sp2.expn_id +} /// returns true if this expn_info was expanded by any macro pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs index cd95fbd202c..0a68d80c339 100644 --- a/tests/compile-fail/block_in_if_condition.rs +++ b/tests/compile-fail/block_in_if_condition.rs @@ -5,6 +5,15 @@ #![deny(block_in_if_condition_stmt)] #![allow(unused)] + +macro_rules! blocky { + () => {{true}} +} + +fn macro_if() { + if blocky!() { + } +} fn condition_has_block() -> i32 { if { //~ERROR in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' -- cgit 1.4.1-3-g733a5 From d8d3ee907bafc690f466e34ab790f568dbeeea36 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 2 Jan 2016 21:49:53 +0530 Subject: Add macro check for box vec (fixes #529) --- src/types.rs | 7 ++++--- tests/compile-fail/box_vec.rs | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index f332659188b..e119ef63436 100644 --- a/src/types.rs +++ b/src/types.rs @@ -9,9 +9,7 @@ use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; use syntax::ast::FloatTy::*; -use utils::{match_type, snippet, span_lint, span_help_and_lint}; -use utils::{is_from_for_desugar, in_macro, in_external_macro}; -use utils::{LL_PATH, VEC_PATH}; +use utils::*; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -50,6 +48,9 @@ impl LintPass for TypePass { impl LateLintPass for TypePass { fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) { + if in_macro(cx, ast_ty.span) { + return + } if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { if match_type(cx, inner, &VEC_PATH) { diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs index 58e780f190c..4fd98cd52ff 100644 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -3,6 +3,15 @@ #![plugin(clippy)] #![deny(clippy)] +macro_rules! boxit { + ($init:expr, $x:ty) => { + let _: Box<$x> = Box::new($init); + } +} + +fn test_macro() { + boxit!(Vec::new(), Vec<u8>); +} pub fn test(foo: Box<Vec<bool>>) { //~ ERROR you seem to be trying to use `Box<Vec<T>>` println!("{:?}", foo.get(0)) } @@ -14,4 +23,5 @@ pub fn test2(foo: Box<Fn(Vec<u32>)>) { // pass if #31 is fixed fn main(){ test(Box::new(Vec::new())); test2(Box::new(|v| println!("{:?}", v))); + test_macro(); } -- cgit 1.4.1-3-g733a5 From 4b9912c2b00a047c6c19aa62ba90bb7d252f07d4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Sat, 2 Jan 2016 23:13:15 +0100 Subject: Add test for wild fields --- tests/compile-fail/unneeded_field_pattern.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/compile-fail/unneeded_field_pattern.rs diff --git a/tests/compile-fail/unneeded_field_pattern.rs b/tests/compile-fail/unneeded_field_pattern.rs new file mode 100644 index 00000000000..bbe72a7133e --- /dev/null +++ b/tests/compile-fail/unneeded_field_pattern.rs @@ -0,0 +1,26 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(unneeded_field_pattern)] +#[allow(dead_code, unused)] + +struct Foo { + a: i32, + b: i32, + c: i32, +} + +fn main() { + let f = Foo { a: 0, b: 0, c: 0 }; + + match f { + Foo { a: _, b: 0, .. } => {} //~ERROR You matched a field with a wildcard pattern + //~^ HELP Try with `Foo { b: 0, .. }` + Foo { a: _, b: _, c: _ } => {} //~ERROR All the struct fields are matched to a + //~^ HELP Try with `Foo { .. }` + } + match f { + Foo { b: 0, .. } => {} // should be OK + Foo { .. } => {} // and the Force might be with this one + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 52fbf1989df18ba669f1542bb6706a42bb5db6f1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 14:22:27 +0100 Subject: Add missing WRONG_PUB_SELF_CONVENTION in lint_array! and corresponding test --- src/methods.rs | 4 +-- tests/compile-fail/wrong_self_convention.rs | 45 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/compile-fail/wrong_self_convention.rs diff --git a/src/methods.rs b/src/methods.rs index a6200534e30..e70d26820b1 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -173,8 +173,8 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, - SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, OK_EXPECT, OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE) + SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE) } } diff --git a/tests/compile-fail/wrong_self_convention.rs b/tests/compile-fail/wrong_self_convention.rs new file mode 100644 index 00000000000..ca896a6b94b --- /dev/null +++ b/tests/compile-fail/wrong_self_convention.rs @@ -0,0 +1,45 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(wrong_self_convention)] +#![deny(wrong_pub_self_convention)] +#![allow(dead_code)] + +fn main() {} + +#[derive(Clone, Copy)] +struct Foo; + +impl Foo { + + fn as_i32(self) {} + fn into_i32(self) {} + fn is_i32(self) {} + fn to_i32(self) {} + fn from_i32(self) {} //~ERROR: methods called `from_*` usually take no self + + pub fn as_i64(self) {} + pub fn into_i64(self) {} + pub fn is_i64(self) {} + pub fn to_i64(self) {} + pub fn from_i64(self) {} //~ERROR: methods called `from_*` usually take no self + +} + +struct Bar; + +impl Bar { + + fn as_i32(self) {} //~ERROR: methods called `as_*` usually take self by reference + fn into_i32(&self) {} //~ERROR: methods called `into_*` usually take self by value + fn is_i32(self) {} //~ERROR: methods called `is_*` usually take self by reference + fn to_i32(self) {} //~ERROR: methods called `to_*` usually take self by reference + fn from_i32(self) {} //~ERROR: methods called `from_*` usually take no self + + pub fn as_i64(self) {} //~ERROR: methods called `as_*` usually take self by reference + pub fn into_i64(&self) {} //~ERROR: methods called `into_*` usually take self by value + pub fn is_i64(self) {} //~ERROR: methods called `is_*` usually take self by reference + pub fn to_i64(self) {} //~ERROR: methods called `to_*` usually take self by reference + pub fn from_i64(self) {} //~ERROR: methods called `from_*` usually take no self + +} -- cgit 1.4.1-3-g733a5 From abfb1d3ca1469d09b2c17e881f85e3f06b2357c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Sun, 3 Jan 2016 14:00:42 +0100 Subject: Add new lint on function naming check (the '_') --- README.md | 3 +- src/lib.rs | 1 + src/misc_early.rs | 38 ++++++++++++++++++++-- .../compile-fail/duplicate_underscore_argument.rs | 13 ++++++++ tests/compile-fail/unneeded_field_pattern.rs | 2 +- 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 tests/compile-fail/duplicate_underscore_argument.rs diff --git a/README.md b/README.md index 0e0a60537b4..2cd93274952 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 88 lints included in this crate: +There are 89 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -24,6 +24,7 @@ name [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions +[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument)| warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do diff --git a/src/lib.rs b/src/lib.rs index 6d39cad20cd..6610173f2dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -193,6 +193,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, misc::USED_UNDERSCORE_BINDING, + misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, diff --git a/src/misc_early.rs b/src/misc_early.rs index dafe7816fe4..77114ccb493 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -1,8 +1,11 @@ -//use rustc_front::hir::*; - use rustc::lint::*; +use std::collections::HashMap; + use syntax::ast::*; +use syntax::codemap::Span; +use syntax::print::pprust; +use syntax::visit::FnKind; use utils::{span_lint, span_help_and_lint}; @@ -16,12 +19,22 @@ use utils::{span_lint, span_help_and_lint}; declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn, "Struct fields are bound to a wildcard instead of using `..`"); +/// **What it does:** This lint `Warn`s on function arguments having the same name except one starts with '_' +/// +/// **Why is this bad?** It makes source code documentation more difficult +/// +/// **Known problems:** None. +/// +/// **Example:** `fn foo(a: i32, _a: i32) {}` +declare_lint!(pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn, + "Function arguments having names which only differ by an underscore"); + #[derive(Copy, Clone)] pub struct MiscEarly; impl LintPass for MiscEarly { fn get_lints(&self) -> LintArray { - lint_array!(UNNEEDED_FIELD_PATTERN) + lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT) } } @@ -77,4 +90,23 @@ impl EarlyLintPass for MiscEarly { } } } + + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + let mut registered_names : HashMap<String, Span> = HashMap::new(); + + for ref arg in &decl.inputs { + let arg_name = pprust::pat_to_string(&arg.pat); + + if arg_name.starts_with("_") { + if let Some(correspondance) = registered_names.get(&arg_name[1..].to_owned()) { + span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, *correspondance, + &format!("`{}` already exists, having another argument having almost \ + the same name makes code comprehension and documentation \ + more difficult", arg_name[1..].to_owned())); + } + } else { + registered_names.insert(arg_name.to_owned(), arg.pat.span.clone()); + } + } + } } diff --git a/tests/compile-fail/duplicate_underscore_argument.rs b/tests/compile-fail/duplicate_underscore_argument.rs new file mode 100644 index 00000000000..4d908e7f02b --- /dev/null +++ b/tests/compile-fail/duplicate_underscore_argument.rs @@ -0,0 +1,13 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(duplicate_underscore_argument)] +#[allow(dead_code, unused)] + +fn join_the_dark_side(darth: i32, _darth: i32) {} //~ERROR `darth` already exists +fn join_the_light_side(knight: i32, _master: i32) {} // the Force is strong with this one + +fn main() { + join_the_dark_side(0, 0); + join_the_light_side(0, 0); +} \ No newline at end of file diff --git a/tests/compile-fail/unneeded_field_pattern.rs b/tests/compile-fail/unneeded_field_pattern.rs index bbe72a7133e..9c7623d85b7 100644 --- a/tests/compile-fail/unneeded_field_pattern.rs +++ b/tests/compile-fail/unneeded_field_pattern.rs @@ -23,4 +23,4 @@ fn main() { Foo { b: 0, .. } => {} // should be OK Foo { .. } => {} // and the Force might be with this one } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 7a4d6aa8b7fbbcf1ff44bafb4cc82745c8cefee9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 14:36:24 +0100 Subject: Use same error message for OPTION_UNWRAP_USED and RESULT_UNWRAP_USED IIRC, Result::expect wasn't stable until quite recently, which might be why there was 2 different error messages. --- src/methods.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index e70d26820b1..2aa3b040e55 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -258,14 +258,21 @@ impl LateLintPass for MethodsPass { fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); - if match_type(cx, obj_ty, &OPTION_PATH) { - span_lint(cx, OPTION_UNWRAP_USED, expr.span, - "used unwrap() on an Option value. If you don't want to handle the None case \ - gracefully, consider using expect() to provide a better panic message"); + let mess = if match_type(cx, obj_ty, &OPTION_PATH) { + Some((OPTION_UNWRAP_USED, "an Option", "None")) } else if match_type(cx, obj_ty, &RESULT_PATH) { - span_lint(cx, RESULT_UNWRAP_USED, expr.span, - "used unwrap() on a Result value. Graceful handling of Err values is preferred"); + Some((RESULT_UNWRAP_USED, "a Result", "Err")) + } + else { + None + }; + + if let Some((lint, kind, none_value)) = mess { + span_lint(cx, lint, expr.span, + &format!("used unwrap() on {} value. If you don't want to handle the {} \ + case gracefully, consider using expect() to provide a better panic + message", kind, none_value)); } } -- cgit 1.4.1-3-g733a5 From bb597179158d8a2d36ac9f5cf0083b5a680c9d85 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 14:43:29 +0100 Subject: Remove x rights on a test file --- tests/compile-fail/array_indexing.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/compile-fail/array_indexing.rs diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs old mode 100755 new mode 100644 -- cgit 1.4.1-3-g733a5 From 780dedc500f9472d726a68bde8590c12ea54c187 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 3 Jan 2016 21:25:09 +0530 Subject: fixups --- README.md | 182 +++++++++++++++++++++++++++--------------------------- src/misc_early.rs | 25 ++++---- 2 files changed, 104 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 2cd93274952..3281adc5b51 100644 --- a/README.md +++ b/README.md @@ -8,97 +8,97 @@ A collection of lints to catch common mistakes and improve your Rust code. ##Lints There are 89 lints included in this crate: -name | default | meaning ----------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` -[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` -[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary -[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) -[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` -[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions -[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument)| warn | Function arguments having names which only differ by an underscore -[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected -[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do -[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` -[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases -[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` -[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block -[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque -[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) -[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead -[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type -[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields -[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect -[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file -[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result -[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` -[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` -[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing -[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator -[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do -[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` -[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` -[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value -[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` -[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op -[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. -[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) -[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) -[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference -[unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` -[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 -[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 -[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions -[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore -[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types -[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop -[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator -[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN -[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing +name | default | meaning +---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` +[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` +[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary +[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) +[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions +[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore +[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do +[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` +[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` +[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block +[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) +[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead +[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type +[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect +[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result +[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` +[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` +[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing +[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do +[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` +[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` +[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value +[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` +[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. +[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) +[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` +[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 +[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 +[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions +[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore +[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types +[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator +[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN +[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/misc_early.rs b/src/misc_early.rs index 77114ccb493..7a59c15275f 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -4,7 +4,6 @@ use std::collections::HashMap; use syntax::ast::*; use syntax::codemap::Span; -use syntax::print::pprust; use syntax::visit::FnKind; use utils::{span_lint, span_help_and_lint}; @@ -19,9 +18,9 @@ use utils::{span_lint, span_help_and_lint}; declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn, "Struct fields are bound to a wildcard instead of using `..`"); -/// **What it does:** This lint `Warn`s on function arguments having the same name except one starts with '_' +/// **What it does:** This lint `Warn`s on function arguments having the similar names differing by an underscore /// -/// **Why is this bad?** It makes source code documentation more difficult +/// **Why is this bad?** It affects code readability /// /// **Known problems:** None. /// @@ -95,17 +94,19 @@ impl EarlyLintPass for MiscEarly { let mut registered_names : HashMap<String, Span> = HashMap::new(); for ref arg in &decl.inputs { - let arg_name = pprust::pat_to_string(&arg.pat); + if let PatIdent(_, sp_ident, None) = arg.pat.node { + let arg_name = sp_ident.node.to_string(); - if arg_name.starts_with("_") { - if let Some(correspondance) = registered_names.get(&arg_name[1..].to_owned()) { - span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, *correspondance, - &format!("`{}` already exists, having another argument having almost \ - the same name makes code comprehension and documentation \ - more difficult", arg_name[1..].to_owned())); + if arg_name.starts_with("_") { + if let Some(correspondance) = registered_names.get(&arg_name[1..]) { + span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, *correspondance, + &format!("`{}` already exists, having another argument having almost \ + the same name makes code comprehension and documentation \ + more difficult", arg_name[1..].to_owned())); + } + } else { + registered_names.insert(arg_name, arg.pat.span.clone()); } - } else { - registered_names.insert(arg_name.to_owned(), arg.pat.span.clone()); } } } -- cgit 1.4.1-3-g733a5 From 0c6e385493407815068b9ca618a0baa09ad20d08 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 22 Dec 2015 00:35:56 +0100 Subject: Implement a HashMapLint --- README.md | 3 +- src/hashmap.rs | 73 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/loops.rs | 4 +-- src/utils.rs | 17 +++++----- tests/compile-fail/hashmap.rs | 25 +++++++++++++++ 6 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 src/hashmap.rs create mode 100644 tests/compile-fail/hashmap.rs diff --git a/README.md b/README.md index 0d854b384fe..f1c28888636 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 90 lints included in this crate: +There are 91 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -31,6 +31,7 @@ name [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[hashmap_entry](https://github.com/Manishearth/rust-clippy/wiki#hashmap_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases diff --git a/src/hashmap.rs b/src/hashmap.rs new file mode 100644 index 00000000000..6448847ee2f --- /dev/null +++ b/src/hashmap.rs @@ -0,0 +1,73 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::codemap::Span; +use utils::{get_item_name, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; +use utils::HASHMAP_PATH; + +/// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap`. +/// +/// **Why is this bad?** Using `HashMap::entry` is more efficient. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** `if !m.contains_key(&k) { m.insert(k, v) }` +declare_lint! { + pub HASHMAP_ENTRY, + Warn, + "use of `contains_key` followed by `insert` on a `HashMap`" +} + +#[derive(Copy,Clone)] +pub struct HashMapLint; + +impl LintPass for HashMapLint { + fn get_lints(&self) -> LintArray { + lint_array!(HASHMAP_ENTRY) + } +} + +impl LateLintPass for HashMapLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! { + [ + let ExprIf(ref check, ref then, _) = expr.node, + let ExprUnary(UnOp::UnNot, ref check) = check.node, + let ExprMethodCall(ref name, _, ref params) = check.node, + params.len() >= 2, + name.node.as_str() == "contains_key" + ], { + let map = ¶ms[0]; + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); + + if match_type(cx, obj_ty, &HASHMAP_PATH) { + if let Some(ref then) = then.expr { + check_for_insert(cx, expr.span, map, then); + } + else if then.stmts.len() == 1 { + if let StmtSemi(ref stmt, _) = then.stmts[0].node { + check_for_insert(cx, expr.span, map, stmt); + } + } + } + } + } + } +} + +fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, expr: &Expr) { + if_let_chain! { + [ + let ExprMethodCall(ref name, _, ref params) = expr.node, + params.len() >= 3, + name.node.as_str() == "insert", + get_item_name(cx, map) == get_item_name(cx, &*params[0]) + ], { + span_help_and_lint(cx, HASHMAP_ENTRY, span, + "usage of `contains_key` followed by `insert` on `HashMap`", + &format!("Consider using `{}.entry({}).or_insert({})`", + snippet(cx, map.span, ".."), + snippet(cx, params[1].span, ".."), + snippet(cx, params[2].span, ".."))); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index e79f0f6ca22..76c04d53a0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ pub mod temporary_assignment; pub mod transmute; pub mod cyclomatic_complexity; pub mod escape; +pub mod hashmap; pub mod misc_early; pub mod array_indexing; pub mod panic; @@ -104,6 +105,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::UnitCmp); reg.register_late_lint_pass(box loops::LoopsPass); reg.register_late_lint_pass(box lifetimes::LifetimePass); + reg.register_late_lint_pass(box hashmap::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); reg.register_late_lint_pass(box types::CastPass); reg.register_late_lint_pass(box types::TypeComplexityPass); @@ -158,6 +160,7 @@ pub fn plugin_registrar(reg: &mut Registry) { eq_op::EQ_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, + hashmap::HASHMAP_ENTRY, identity_op::IDENTITY_OP, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, diff --git a/src/loops.rs b/src/loops.rs index 9f103f4e7a8..a0454a325e4 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -13,7 +13,7 @@ use syntax::ast::Lit_::*; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal, get_enclosing_block}; -use utils::{VEC_PATH, LL_PATH}; +use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH}; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. /// @@ -457,7 +457,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { is_iterable_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || - match_type(cx, ty, &["std", "collections", "hash", "map", "HashMap"]) || + match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || diff --git a/src/utils.rs b/src/utils.rs index 90e8e27b4f0..76b57317c31 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,15 +18,16 @@ use std::ops::{Deref, DerefMut}; pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for -pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; -pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; -pub const BEGIN_UNWIND:[&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; +pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/hashmap.rs b/tests/compile-fail/hashmap.rs new file mode 100644 index 00000000000..9b15acf4072 --- /dev/null +++ b/tests/compile-fail/hashmap.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unused)] + +#![deny(hashmap_entry)] + +use std::collections::HashMap; +use std::hash::Hash; + +fn insert_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { m.insert(k, v); } //~ERROR: usage of `contains_key` followed by `insert` on `HashMap` +} + +fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { m.insert(k, v) } else { None }; //~ERROR: usage of `contains_key` followed by `insert` on `HashMap` +} + +/* TODO +fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { + if !m.contains_key(&k) { m.insert(o, v) } else { None }; +} +*/ + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 54b70ed8e1ead333c0e45d21ff3daa89061a8b05 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 15:49:25 +0100 Subject: Move eq_op::is_exp_equal to utils --- src/eq_op.rs | 71 +--------------------------------------------------------- src/strings.rs | 3 +-- src/utils.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 72 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 4865596b630..3d2f32e6c7f 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,10 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc_front::util as ast_util; -use syntax::ptr::P; -use consts::constant; -use utils::span_lint; +use utils::{is_exp_equal, span_lint}; /// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). It is `Warn` by default. /// @@ -40,57 +38,6 @@ impl LateLintPass for EqOp { } } -pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool { - if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { - if l == r { - return true; - } - } - match (&left.node, &right.node) { - (&ExprField(ref lfexp, ref lfident), - &ExprField(ref rfexp, ref rfident)) => - lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), - (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprPath(ref lqself, ref lsubpath), - &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, is_qself_equal) && - is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => - is_exps_equal(cx, ltup, rtup), - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => - is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), - _ => false - } -} - -fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool { - over(left, right, |l, r| is_exp_equal(cx, l, r)) -} - -fn is_path_equal(left : &Path, right : &Path) -> bool { - // The == of idents doesn't work with different contexts, - // we have to be explicit about hygiene - left.global == right.global && over(&left.segments, &right.segments, - |l, r| l.identifier.name == r.identifier.name - && l.parameters == r.parameters) -} - -fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { - left.ty.node == right.ty.node && left.position == right.position -} - -fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool { - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| - eq_fn(x, y)) -} - -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool - where F: FnMut(&X, &X) -> bool { - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, - |y| eq_fn(x, y))) -} fn is_cmp_or_bit(op : &BinOp) -> bool { match op.node { @@ -99,19 +46,3 @@ fn is_cmp_or_bit(op : &BinOp) -> bool { _ => false } } - -fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { - match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => - lmut.mutbl == rmut.mutbl && - is_cast_ty_equal(&*lmut.ty, &*rmut.ty), - (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => - lrmut.mutbl == rrmut.mutbl && - is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => - both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), - (&TyInfer, &TyInfer) => true, - _ => false - } -} diff --git a/src/strings.rs b/src/strings.rs index 861ae0bb012..2baf26095b7 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -7,8 +7,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use eq_op::is_exp_equal; -use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::{is_exp_equal, match_type, span_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). It is `Allow` by default. diff --git a/src/utils.rs b/src/utils.rs index 76b57317c31..1b6c75a3b78 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,6 +10,7 @@ use syntax::ast::Lit_::*; use syntax::ast; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +use consts::constant; use rustc::session::Session; use std::str::FromStr; @@ -493,3 +494,71 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } } } + +pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool { + if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { + if l == r { + return true; + } + } + match (&left.node, &right.node) { + (&ExprField(ref lfexp, ref lfident), + &ExprField(ref rfexp, ref rfident)) => + lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), + (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprPath(ref lqself, ref lsubpath), + &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, is_qself_equal) && + is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => + is_exps_equal(cx, ltup, rtup), + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => + is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), + _ => false + } +} + +fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool { + over(left, right, |l, r| is_exp_equal(cx, l, r)) +} + +fn is_path_equal(left : &Path, right : &Path) -> bool { + // The == of idents doesn't work with different contexts, + // we have to be explicit about hygiene + left.global == right.global && over(&left.segments, &right.segments, + |l, r| l.identifier.name == r.identifier.name + && l.parameters == r.parameters) +} + +fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { + left.ty.node == right.ty.node && left.position == right.position +} + +fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool { + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| + eq_fn(x, y)) +} + +fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool + where F: FnMut(&X, &X) -> bool { + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, + |y| eq_fn(x, y))) +} + +fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { + match (&left.node, &right.node) { + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => + lmut.mutbl == rmut.mutbl && + is_cast_ty_equal(&*lmut.ty, &*rmut.ty), + (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => + lrmut.mutbl == rrmut.mutbl && + is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty), + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), + (&TyInfer, &TyInfer) => true, + _ => false + } +} -- cgit 1.4.1-3-g733a5 From d0bb71e6a23d45b4e367007da1099df9db424b8d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 16:31:28 +0100 Subject: Finish the HashMapLint --- src/hashmap.rs | 34 ++++++++++++++++++++++------------ tests/compile-fail/hashmap.rs | 4 +--- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/hashmap.rs b/src/hashmap.rs index 6448847ee2f..14f535b3820 100644 --- a/src/hashmap.rs +++ b/src/hashmap.rs @@ -1,14 +1,18 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use utils::{get_item_name, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; +use utils::{get_item_name, is_exp_equal, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; use utils::HASHMAP_PATH; /// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap`. /// /// **Why is this bad?** Using `HashMap::entry` is more efficient. /// -/// **Known problems:** Hopefully none. +/// **Known problems:** Some false negatives, eg.: +/// ``` +/// let k = &key; +/// if !m.contains_key(k) { m.insert(k.clone(), v); } +/// ``` /// /// **Example:** `if !m.contains_key(&k) { m.insert(k, v) }` declare_lint! { @@ -36,16 +40,22 @@ impl LateLintPass for HashMapLint { params.len() >= 2, name.node.as_str() == "contains_key" ], { + let key = match params[1].node { + ExprAddrOf(_, ref key) => key, + _ => return + }; + let map = ¶ms[0]; let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); if match_type(cx, obj_ty, &HASHMAP_PATH) { if let Some(ref then) = then.expr { - check_for_insert(cx, expr.span, map, then); + check_for_insert(cx, expr.span, map, key, then); } - else if then.stmts.len() == 1 { - if let StmtSemi(ref stmt, _) = then.stmts[0].node { - check_for_insert(cx, expr.span, map, stmt); + + for stmt in &then.stmts { + if let StmtSemi(ref stmt, _) = stmt.node { + check_for_insert(cx, expr.span, map, key, stmt); } } } @@ -54,20 +64,20 @@ impl LateLintPass for HashMapLint { } } -fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, expr: &Expr) { +fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr) { if_let_chain! { [ let ExprMethodCall(ref name, _, ref params) = expr.node, - params.len() >= 3, + params.len() == 3, name.node.as_str() == "insert", - get_item_name(cx, map) == get_item_name(cx, &*params[0]) + get_item_name(cx, map) == get_item_name(cx, &*params[0]), + is_exp_equal(cx, key, ¶ms[1]) ], { span_help_and_lint(cx, HASHMAP_ENTRY, span, "usage of `contains_key` followed by `insert` on `HashMap`", - &format!("Consider using `{}.entry({}).or_insert({})`", + &format!("Consider using `{}.entry({})`", snippet(cx, map.span, ".."), - snippet(cx, params[1].span, ".."), - snippet(cx, params[2].span, ".."))); + snippet(cx, params[1].span, ".."))); } } } diff --git a/tests/compile-fail/hashmap.rs b/tests/compile-fail/hashmap.rs index 9b15acf4072..9aeacac0e14 100644 --- a/tests/compile-fail/hashmap.rs +++ b/tests/compile-fail/hashmap.rs @@ -15,11 +15,9 @@ fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v) } else { None }; //~ERROR: usage of `contains_key` followed by `insert` on `HashMap` } -/* TODO fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { - if !m.contains_key(&k) { m.insert(o, v) } else { None }; + if !m.contains_key(&k) { m.insert(o, v); } } -*/ fn main() { } -- cgit 1.4.1-3-g733a5 From 9945bd82a8273f9c5506e9c26d51b312188d620f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jan 2016 17:19:49 +0100 Subject: Add better error messages for HashMapLint --- src/hashmap.rs | 37 ++++++++++++++++++++++++++++--------- tests/compile-fail/hashmap.rs | 24 +++++++++++++++++++++--- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/hashmap.rs b/src/hashmap.rs index 14f535b3820..095a00e3777 100644 --- a/src/hashmap.rs +++ b/src/hashmap.rs @@ -14,7 +14,14 @@ use utils::HASHMAP_PATH; /// if !m.contains_key(k) { m.insert(k.clone(), v); } /// ``` /// -/// **Example:** `if !m.contains_key(&k) { m.insert(k, v) }` +/// **Example:** +/// ```rust +/// if !m.contains_key(&k) { m.insert(k, v) } +/// ``` +/// can be rewritten as: +/// ```rust +/// m.entry(k).or_insert(v); +/// ``` declare_lint! { pub HASHMAP_ENTRY, Warn, @@ -49,13 +56,15 @@ impl LateLintPass for HashMapLint { let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); if match_type(cx, obj_ty, &HASHMAP_PATH) { + let sole_expr = if then.expr.is_some() { 1 } else { 0 } + then.stmts.len() == 1; + if let Some(ref then) = then.expr { - check_for_insert(cx, expr.span, map, key, then); + check_for_insert(cx, expr.span, map, key, then, sole_expr); } for stmt in &then.stmts { if let StmtSemi(ref stmt, _) = stmt.node { - check_for_insert(cx, expr.span, map, key, stmt); + check_for_insert(cx, expr.span, map, key, stmt, sole_expr); } } } @@ -64,7 +73,7 @@ impl LateLintPass for HashMapLint { } } -fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr) { +fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr, sole_expr: bool) { if_let_chain! { [ let ExprMethodCall(ref name, _, ref params) = expr.node, @@ -73,11 +82,21 @@ fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: get_item_name(cx, map) == get_item_name(cx, &*params[0]), is_exp_equal(cx, key, ¶ms[1]) ], { - span_help_and_lint(cx, HASHMAP_ENTRY, span, - "usage of `contains_key` followed by `insert` on `HashMap`", - &format!("Consider using `{}.entry({})`", - snippet(cx, map.span, ".."), - snippet(cx, params[1].span, ".."))); + if sole_expr { + span_help_and_lint(cx, HASHMAP_ENTRY, span, + "usage of `contains_key` followed by `insert` on `HashMap`", + &format!("Consider using `{}.entry({}).or_insert({})`", + snippet(cx, map.span, ".."), + snippet(cx, params[1].span, ".."), + snippet(cx, params[2].span, ".."))); + } + else { + span_help_and_lint(cx, HASHMAP_ENTRY, span, + "usage of `contains_key` followed by `insert` on `HashMap`", + &format!("Consider using `{}.entry({})`", + snippet(cx, map.span, ".."), + snippet(cx, params[1].span, ".."))); + } } } } diff --git a/tests/compile-fail/hashmap.rs b/tests/compile-fail/hashmap.rs index 9aeacac0e14..a53566a794e 100644 --- a/tests/compile-fail/hashmap.rs +++ b/tests/compile-fail/hashmap.rs @@ -7,12 +7,30 @@ use std::collections::HashMap; use std::hash::Hash; -fn insert_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v); } //~ERROR: usage of `contains_key` followed by `insert` on `HashMap` +fn foo() {} + +fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { m.insert(k, v); } + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k).or_insert(v)` +} + +fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { foo(); m.insert(k, v); } + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k)` } fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v) } else { None }; //~ERROR: usage of `contains_key` followed by `insert` on `HashMap` + if !m.contains_key(&k) { m.insert(k, v) } else { None }; + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k).or_insert(v)` +} + +fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k)` } fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { -- cgit 1.4.1-3-g733a5 From 839ad09689e417d1d9e84eb24c627226765f8322 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 4 Jan 2016 09:55:29 +0530 Subject: Rustfmt config --- rustfmt.toml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000000..c0695c04126 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +max_width = 120 +ideal_width = 100 +fn_args_density = "Compressed" +fn_call_width = 80 +fn_args_paren_newline = false \ No newline at end of file -- cgit 1.4.1-3-g733a5 From c9342d01213ca1663d2cdf23289bae024823ae6a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 4 Jan 2016 09:56:12 +0530 Subject: fmt clippy --- src/approx_const.rs | 46 +++-- src/array_indexing.rs | 3 +- src/attrs.rs | 38 ++-- src/bit_mask.rs | 225 +++++++++++++--------- src/block_in_if_condition.rs | 37 ++-- src/collapsible_if.rs | 41 ++-- src/consts.rs | 443 +++++++++++++++++++++++++++---------------- src/cyclomatic_complexity.rs | 39 ++-- src/eq_op.rs | 24 ++- src/escape.rs | 40 ++-- src/eta_reduction.rs | 14 +- src/identity_op.rs | 20 +- src/len_zero.rs | 128 ++++++++----- src/lib.rs | 10 +- src/lifetimes.rs | 54 +++--- src/loops.rs | 374 ++++++++++++++++++++---------------- src/map_clone.rs | 20 +- src/matches.rs | 234 ++++++++++++----------- src/methods.rs | 420 ++++++++++++++++++++++++++-------------- src/minmax.rs | 35 ++-- src/misc.rs | 145 ++++++++------ src/misc_early.rs | 39 ++-- src/mut_mut.rs | 42 ++-- src/mut_reference.rs | 20 +- src/mutex_atomic.rs | 16 +- src/needless_bool.rs | 45 +++-- src/needless_features.rs | 14 +- src/needless_update.rs | 7 +- src/no_effect.rs | 7 +- src/open_options.rs | 151 +++++++++++---- src/precedence.rs | 68 ++++--- src/ptr_arg.rs | 17 +- src/ranges.rs | 19 +- src/returns.rs | 34 ++-- src/shadow.rs | 166 +++++++++------- src/strings.rs | 30 +-- src/temporary_assignment.rs | 5 +- src/transmute.rs | 3 +- src/types.rs | 253 +++++++++++++++--------- src/unicode.rs | 46 +++-- src/utils.rs | 301 ++++++++++++++--------------- 41 files changed, 2186 insertions(+), 1487 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 05829838903..2c8779ae737 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -21,24 +21,22 @@ declare_lint! { } // Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS : &'static [(f64, &'static str, usize)] = &[ - (f64::E, "E", 4), - (f64::FRAC_1_PI, "FRAC_1_PI", 4), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), - (f64::FRAC_2_PI, "FRAC_2_PI", 5), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), - (f64::FRAC_PI_2, "FRAC_PI_2", 5), - (f64::FRAC_PI_3, "FRAC_PI_3", 5), - (f64::FRAC_PI_4, "FRAC_PI_4", 5), - (f64::FRAC_PI_6, "FRAC_PI_6", 5), - (f64::FRAC_PI_8, "FRAC_PI_8", 5), - (f64::LN_10, "LN_10", 5), - (f64::LN_2, "LN_2", 5), - (f64::LOG10_E, "LOG10_E", 5), - (f64::LOG2_E, "LOG2_E", 5), - (f64::PI, "PI", 3), - (f64::SQRT_2, "SQRT_2", 5), -]; +const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), + (f64::FRAC_1_PI, "FRAC_1_PI", 4), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), + (f64::FRAC_2_PI, "FRAC_2_PI", 5), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), + (f64::FRAC_PI_2, "FRAC_PI_2", 5), + (f64::FRAC_PI_3, "FRAC_PI_3", 5), + (f64::FRAC_PI_4, "FRAC_PI_4", 5), + (f64::FRAC_PI_6, "FRAC_PI_6", 5), + (f64::FRAC_PI_8, "FRAC_PI_8", 5), + (f64::LN_10, "LN_10", 5), + (f64::LN_2, "LN_2", 5), + (f64::LOG10_E, "LOG10_E", 5), + (f64::LOG2_E, "LOG2_E", 5), + (f64::PI, "PI", 3), + (f64::SQRT_2, "SQRT_2", 5)]; #[derive(Copy,Clone)] pub struct ApproxConstant; @@ -61,9 +59,8 @@ fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { LitFloat(ref s, TyF32) => check_known_consts(cx, e, s, "f32"), LitFloat(ref s, TyF64) => check_known_consts(cx, e, s, "f64"), - LitFloatUnsuffixed(ref s) => - check_known_consts(cx, e, s, "f{32, 64}"), - _ => () + LitFloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), + _ => (), } } @@ -71,9 +68,10 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { if let Ok(_) = s.parse::<f64>() { for &(constant, name, min_digits) in KNOWN_CONSTS { if is_approx_const(constant, s, min_digits) { - span_lint(cx, APPROX_CONSTANT, e.span, &format!( - "approximate value of `{}::{}` found. \ - Consider using it directly", module, &name)); + span_lint(cx, + APPROX_CONSTANT, + e.span, + &format!("approximate value of `{}::{}` found. Consider using it directly", module, &name)); return; } } diff --git a/src/array_indexing.rs b/src/array_indexing.rs index d72adac943f..cfa52f390d2 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -42,8 +42,7 @@ impl LateLintPass for ArrayIndexing { let index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); if let Ok(ConstVal::Uint(index)) = index { if size as u64 <= index { - span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, - "const index-expr is out of bounds"); + span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index-expr is out of bounds"); } } } diff --git a/src/attrs.rs b/src/attrs.rs index f0dbf390ebb..ec2cfcb0efc 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -57,13 +57,15 @@ impl LateLintPass for AttrPass { fn is_relevant_item(item: &Item) -> bool { if let ItemFn(_, _, _, _, _, ref block) = item.node { is_relevant_block(block) - } else { false } + } else { + false + } } fn is_relevant_impl(item: &ImplItem) -> bool { match item.node { ImplItemKind::Method(_, ref block) => is_relevant_block(block), - _ => false + _ => false, } } @@ -71,7 +73,7 @@ fn is_relevant_trait(item: &TraitItem) -> bool { match item.node { MethodTraitItem(_, None) => true, MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), - _ => false + _ => false, } } @@ -95,25 +97,33 @@ fn is_relevant_expr(expr: &Expr) -> bool { ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { !match_path(path, &BEGIN_UNWIND) - } else { true } + } else { + true + } } - _ => true + _ => true, } } -fn check_attrs(cx: &LateContext, span: Span, name: &Name, - attrs: &[Attribute]) { - if in_macro(cx, span) { return; } +fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { + if in_macro(cx, span) { + return; + } for attr in attrs { if let MetaList(ref inline, ref values) = attr.node.value.node { - if values.len() != 1 || inline != &"inline" { continue; } + if values.len() != 1 || inline != &"inline" { + continue; + } if let MetaWord(ref always) = values[0].node { - if always != &"always" { continue; } - span_lint(cx, INLINE_ALWAYS, attr.span, &format!( - "you have declared `#[inline(always)]` on `{}`. This \ - is usually a bad idea", - name)); + if always != &"always" { + continue; + } + span_lint(cx, + INLINE_ALWAYS, + attr.span, + &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea", + name)); } } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index f4310db0fcb..c2fd3742066 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -95,18 +95,22 @@ impl LateLintPass for BitMask { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if is_comparison_binop(cmp.node) { - fetch_int_literal(cx, right).map_or_else(|| - fetch_int_literal(cx, left).map_or((), |cmp_val| - check_compare(cx, right, invert_cmp(cmp.node), - cmp_val, &e.span)), - |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, - &e.span)) + fetch_int_literal(cx, right).map_or_else(|| { + fetch_int_literal(cx, left).map_or((), |cmp_val| { + check_compare(cx, + right, + invert_cmp(cmp.node), + cmp_val, + &e.span) + }) + }, + |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, &e.span)) } } } } -fn invert_cmp(cmp : BinOp_) -> BinOp_ { +fn invert_cmp(cmp: BinOp_) -> BinOp_ { match cmp { BiEq => BiEq, BiNe => BiNe, @@ -114,7 +118,7 @@ fn invert_cmp(cmp : BinOp_) -> BinOp_ { BiGt => BiLt, BiLe => BiGe, BiGe => BiLe, - _ => BiOr // Dummy + _ => BiOr, // Dummy } } @@ -124,114 +128,159 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64 if op.node != BiBitAnd && op.node != BiBitOr { return; } - fetch_int_literal(cx, right).or_else(|| fetch_int_literal( - cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, - cmp_op, mask, cmp_value, span)) + fetch_int_literal(cx, right) + .or_else(|| fetch_int_literal(cx, left)) + .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span)) } } -fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, - mask_value: u64, cmp_value: u64, span: &Span) { +fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { match cmp_op { - BiEq | BiNe => match bit_op { - BiBitAnd => if mask_value & cmp_value != cmp_value { - if cmp_value != 0 { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, cmp_value)); + BiEq | BiNe => { + match bit_op { + BiBitAnd => { + if mask_value & cmp_value != cmp_value { + if cmp_value != 0 { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, + cmp_value)); + } + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } } - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + BiBitOr => { + if mask_value | cmp_value != cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, + cmp_value)); + } } - }, - BiBitOr => if mask_value | cmp_value != cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, cmp_value)); - }, - _ => () - }, - BiLt | BiGe => match bit_op { - BiBitAnd => if mask_value < cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + _ => (), + } + } + BiLt | BiGe => { + match bit_op { + BiBitAnd => { + if mask_value < cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, + cmp_value)); + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } } - }, - BiBitOr => if mask_value >= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, cmp_value)); - } else { - check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); - }, - BiBitXor => - check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), - _ => () - }, - BiLe | BiGt => match bit_op { - BiBitAnd => if mask_value <= cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + BiBitOr => { + if mask_value >= cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, + cmp_value)); + } else { + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); + } } - }, - BiBitOr => if mask_value > cmp_value { - span_lint(cx, BAD_BIT_MASK, *span, &format!( - "incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, cmp_value)); - } else { - check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); - }, - BiBitXor => - check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), - _ => () - }, - _ => () + BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), + _ => (), + } + } + BiLe | BiGt => { + match bit_op { + BiBitAnd => { + if mask_value <= cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, + cmp_value)); + } else { + if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } + } + BiBitOr => { + if mask_value > cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, + cmp_value)); + } else { + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); + } + } + BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), + _ => (), + } + } + _ => (), } } fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { if c.is_power_of_two() && m < c { - span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( - "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, m, c)); + span_lint(cx, + INEFFECTIVE_BIT_MASK, + span, + &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c)); } } fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { if (c + 1).is_power_of_two() && m <= c { - span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( - "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, m, c)); + span_lint(cx, + INEFFECTIVE_BIT_MASK, + span, + &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c)); } } -fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> { +fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { if let LitInt(value, _) = lit_ptr.node { Some(value) //TODO: Handle sign - } else { None } + } else { + None + } } ExprPath(_, _) => { - // Important to let the borrow expire before the const lookup to avoid double - // borrowing. - let def_map = cx.tcx.def_map.borrow(); - match def_map.get(&lit.id) { - Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), - _ => None + { + // Important to let the borrow expire before the const lookup to avoid double + // borrowing. + let def_map = cx.tcx.def_map.borrow(); + match def_map.get(&lit.id) { + Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), + _ => None, + } } + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) + .and_then(|l| fetch_int_literal(cx, l)) } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) - .and_then(|l| fetch_int_literal(cx, l)), - _ => None + _ => None, } } diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index ce01f591c59..f7d8c95ee76 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -38,7 +38,7 @@ impl LintPass for BlockInIfCondition { } struct ExVisitor<'v> { - found_block: Option<&'v Expr> + found_block: Option<&'v Expr>, } impl<'v> Visitor<'v> for ExVisitor<'v> { @@ -51,7 +51,7 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { if let Some(ref ex) = block.expr { match ex.node { ExprBlock(_) => true, - _ => false + _ => false, } } else { false @@ -59,7 +59,7 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { } }; if complex { - self.found_block = Some(& expr); + self.found_block = Some(&expr); return; } } @@ -67,8 +67,9 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { } } -const BRACED_EXPR_MESSAGE:&'static str = "omit braces around single expression condition"; -const COMPLEX_BLOCK_MESSAGE:&'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let'"; +const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition"; +const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ + instead, move the block or closure higher and bind it with a 'let'"; impl LateLintPass for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { @@ -82,29 +83,33 @@ impl LateLintPass for BlockInIfCondition { if differing_macro_contexts(expr.span, ex.span) { return; } - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_EXPR, check.span, - BRACED_EXPR_MESSAGE, - &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, ".."))); + span_help_and_lint(cx, + BLOCK_IN_IF_CONDITION_EXPR, + check.span, + BRACED_EXPR_MESSAGE, + &format!("try\nif {} {} ... ", + snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, ".."))); } } else { if differing_macro_contexts(expr.span, block.stmts[0].span) { return; } // move block higher - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, check.span, - COMPLEX_BLOCK_MESSAGE, - &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, ".."))); + span_help_and_lint(cx, + BLOCK_IN_IF_CONDITION_STMT, + check.span, + COMPLEX_BLOCK_MESSAGE, + &format!("try\nlet res = {};\nif res {} ... ", + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, ".."))); } } } else { let mut visitor = ExVisitor { found_block: None }; walk_expr(&mut visitor, check); if let Some(ref block) = visitor.found_block { - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, - COMPLEX_BLOCK_MESSAGE, ""); + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE, ""); } } } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 775e9ec95fc..4a17d3a4608 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -52,23 +52,26 @@ impl LateLintPass for CollapsibleIf { fn check_if(cx: &LateContext, e: &Expr) { if let ExprIf(ref check, ref then, None) = e.node { if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = - single_stmt_of_block(then) { - if e.span.expn_id != sp.expn_id { - return; - } - span_help_and_lint(cx, COLLAPSIBLE_IF, e.span, - "this if statement can be collapsed", - &format!("try\nif {} && {} {}", - check_to_string(cx, check), check_to_string(cx, check_inner), - snippet_block(cx, content.span, ".."))); + single_stmt_of_block(then) { + if e.span.expn_id != sp.expn_id { + return; } + span_help_and_lint(cx, + COLLAPSIBLE_IF, + e.span, + "this if statement can be collapsed", + &format!("try\nif {} && {} {}", + check_to_string(cx, check), + check_to_string(cx, check_inner), + snippet_block(cx, content.span, ".."))); + } } } fn requires_brackets(e: &Expr) -> bool { match e.node { ExprBinary(Spanned {node: n, ..}, _, _) if n == BiEq => false, - _ => true + _ => true, } } @@ -84,16 +87,26 @@ fn single_stmt_of_block(block: &Block) -> Option<&Expr> { if block.stmts.len() == 1 && block.expr.is_none() { if let StmtExpr(ref expr, _) = block.stmts[0].node { single_stmt_of_expr(expr) - } else { None } + } else { + None + } } else { if block.stmts.is_empty() { - if let Some(ref p) = block.expr { Some(p) } else { None } - } else { None } + if let Some(ref p) = block.expr { + Some(p) + } else { + None + } + } else { + None + } } } fn single_stmt_of_expr(expr: &Expr) -> Option<&Expr> { if let ExprBlock(ref block) = expr.node { single_stmt_of_block(block) - } else { Some(expr) } + } else { + Some(expr) + } } diff --git a/src/consts.rs b/src/consts.rs index 9d3a9e7d7c2..171ba6f27f0 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -28,7 +28,7 @@ use syntax::ast::Sign::{self, Plus, Minus}; pub enum FloatWidth { Fw32, Fw64, - FwAny + FwAny, } impl From<FloatTy> for FloatWidth { @@ -85,9 +85,14 @@ impl Constant { match *self { ConstantByte(b) => Some(b as f64), ConstantFloat(ref s, _) => s.parse().ok(), - ConstantInt(i, ty) => Some(if is_negative(ty) { - -(i as f64) } else { i as f64 }), - _ => None + ConstantInt(i, ty) => { + Some(if is_negative(ty) { + -(i as f64) + } else { + i as f64 + }) + } + _ => None, } } } @@ -95,14 +100,14 @@ impl Constant { impl PartialEq for Constant { fn eq(&self, other: &Constant) -> bool { match (self, other) { - (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => - ls == rs && lsty == rsty, + (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => ls == rs && lsty == rsty, (&ConstantBinary(ref l), &ConstantBinary(ref r)) => l == r, (&ConstantByte(l), &ConstantByte(r)) => l == r, (&ConstantChar(l), &ConstantChar(r)) => l == r, - (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => lv == rv && - (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)), - (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => + (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => { + lv == rv && (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)) + } + (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => { if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -111,11 +116,13 @@ impl PartialEq for Constant { (Ok(l), Ok(r)) => l.eq(&r), _ => false, } - } else { false }, + } else { + false + } + } (&ConstantBool(l), &ConstantBool(r)) => l == r, (&ConstantVec(ref l), &ConstantVec(ref r)) => l == r, - (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => - ls == rs && lv == rv, + (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => ls == rs && lv == rv, (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l == r, _ => false, //TODO: Are there inter-type equalities? } @@ -125,19 +132,24 @@ impl PartialEq for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { - (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => - if lsty != rsty { None } else { Some(ls.cmp(rs)) }, + (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => { + if lsty != rsty { + None + } else { + Some(ls.cmp(rs)) + } + } (&ConstantByte(ref l), &ConstantByte(ref r)) => Some(l.cmp(r)), (&ConstantChar(ref l), &ConstantChar(ref r)) => Some(l.cmp(r)), - (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => - Some(match (is_negative(lty) && *lv != 0, - is_negative(rty) && *rv != 0) { + (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => { + Some(match (is_negative(lty) && *lv != 0, is_negative(rty) && *rv != 0) { (true, true) => rv.cmp(lv), (false, false) => lv.cmp(rv), (true, false) => Less, (false, true) => Greater, - }), - (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => + }) + } + (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => { if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -146,17 +158,21 @@ impl PartialOrd for Constant { (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), _ => None, } - } else { None }, + } else { + None + } + } (&ConstantBool(ref l), &ConstantBool(ref r)) => Some(l.cmp(r)), (&ConstantVec(ref l), &ConstantVec(ref r)) => l.partial_cmp(&r), - (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => + (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => { match lv.partial_cmp(rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, - }, + } + } (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l.partial_cmp(r), - _ => None, //TODO: Are there any useful inter-type orderings? - } + _ => None, //TODO: Are there any useful inter-type orderings? + } } } @@ -178,9 +194,11 @@ impl fmt::Display for Constant { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { ConstantStr(ref s, _) => write!(fmt, "{:?}", s), - ConstantByte(ref b) => - write!(fmt, "b'").and_then(|_| format_byte(fmt, *b)) - .and_then(|_| write!(fmt, "'")), + ConstantByte(ref b) => { + write!(fmt, "b'") + .and_then(|_| format_byte(fmt, *b)) + .and_then(|_| write!(fmt, "'")) + } ConstantBinary(ref bs) => { try!(write!(fmt, "b\"")); for b in bs.iter() { @@ -191,14 +209,23 @@ impl fmt::Display for Constant { ConstantChar(ref c) => write!(fmt, "'{}'", c), ConstantInt(ref i, ref ity) => { let (sign, suffix) = match *ity { - LitIntType::SignedIntLit(ref sity, ref sign) => - (if let Sign::Minus = *sign { "-" } else { "" }, - sity.ty_to_string()), - LitIntType::UnsignedIntLit(ref uity) => - ("", uity.ty_to_string()), - LitIntType::UnsuffixedIntLit(ref sign) => - (if let Sign::Minus = *sign { "-" } else { "" }, - "".into()), + LitIntType::SignedIntLit(ref sity, ref sign) => { + (if let Sign::Minus = *sign { + "-" + } else { + "" + }, + sity.ty_to_string()) + } + LitIntType::UnsignedIntLit(ref uity) => ("", uity.ty_to_string()), + LitIntType::UnsuffixedIntLit(ref sign) => { + (if let Sign::Minus = *sign { + "-" + } else { + "" + }, + "".into()) + } }; write!(fmt, "{}{}{}", sign, i, suffix) } @@ -212,12 +239,22 @@ impl fmt::Display for Constant { } ConstantBool(ref b) => write!(fmt, "{}", b), ConstantRepeat(ref c, ref n) => write!(fmt, "[{}; {}]", c, n), - ConstantVec(ref v) => write!(fmt, "[{}]", - v.iter().map(|i| format!("{}", i)) - .collect::<Vec<_>>().join(", ")), - ConstantTuple(ref t) => write!(fmt, "({})", - t.iter().map(|i| format!("{}", i)) - .collect::<Vec<_>>().join(", ")), + ConstantVec(ref v) => { + write!(fmt, + "[{}]", + v.iter() + .map(|i| format!("{}", i)) + .collect::<Vec<_>>() + .join(", ")) + } + ConstantTuple(ref t) => { + write!(fmt, + "({})", + t.iter() + .map(|i| format!("{}", i)) + .collect::<Vec<_>>() + .join(", ")) + } } } } @@ -242,7 +279,9 @@ fn constant_not(o: Constant) -> Option<Constant> { ConstantInt(value, ty) => { let (nvalue, nty) = match ty { SignedIntLit(ity, Plus) => { - if value == ::std::u64::MAX { return None; } + if value == ::std::u64::MAX { + return None; + } (value + 1, SignedIntLit(ity, Minus)) } SignedIntLit(ity, Minus) => { @@ -258,30 +297,40 @@ fn constant_not(o: Constant) -> Option<Constant> { UintTy::TyU16 => ::std::u16::MAX as u64, UintTy::TyU32 => ::std::u32::MAX as u64, UintTy::TyU64 => ::std::u64::MAX, - UintTy::TyUs => { return None; } // refuse to guess + UintTy::TyUs => { + return None; + } // refuse to guess }; (!value & mask, UnsignedIntLit(ity)) } - UnsuffixedIntLit(_) => { return None; } // refuse to guess + UnsuffixedIntLit(_) => { + return None; + } // refuse to guess }; ConstantInt(nvalue, nty) } - _ => { return None; } + _ => { + return None; + } }) } fn constant_negate(o: Constant) -> Option<Constant> { Some(match o { - ConstantInt(value, ty) => - ConstantInt(value, match ty { - SignedIntLit(ity, sign) => - SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { return None; } - }), - ConstantFloat(is, ty) => - ConstantFloat(neg_float_str(is), ty), - _ => { return None; } + ConstantInt(value, ty) => { + ConstantInt(value, + match ty { + SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), + UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), + _ => { + return None; + } + }) + } + ConstantFloat(is, ty) => ConstantFloat(neg_float_str(is), ty), + _ => { + return None; + } }) } @@ -316,25 +365,42 @@ pub fn is_negative(ty: LitIntType) -> bool { fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { match (l, r) { - (SignedIntLit(lty, _), SignedIntLit(rty, _)) => if lty == rty { - Some(SignedIntLit(lty, s)) } else { None }, - (UnsignedIntLit(lty), UnsignedIntLit(rty)) => + (SignedIntLit(lty, _), SignedIntLit(rty, _)) => { + if lty == rty { + Some(SignedIntLit(lty, s)) + } else { + None + } + } + (UnsignedIntLit(lty), UnsignedIntLit(rty)) => { if s == Plus && lty == rty { Some(UnsignedIntLit(lty)) - } else { None }, + } else { + None + } + } (UnsuffixedIntLit(_), UnsuffixedIntLit(_)) => Some(UnsuffixedIntLit(s)), (SignedIntLit(lty, _), UnsuffixedIntLit(_)) => Some(SignedIntLit(lty, s)), - (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => if rs == Plus { - Some(UnsignedIntLit(lty)) } else { None }, + (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => { + if rs == Plus { + Some(UnsignedIntLit(lty)) + } else { + None + } + } (UnsuffixedIntLit(_), SignedIntLit(rty, _)) => Some(SignedIntLit(rty, s)), - (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => if ls == Plus { - Some(UnsignedIntLit(rty)) } else { None }, + (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => { + if ls == Plus { + Some(UnsignedIntLit(rty)) + } else { + None + } + } _ => None, } } -fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> - Option<Constant> { +fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> Option<Constant> { if neg > pos { unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) } else { @@ -342,70 +408,80 @@ fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> } } -fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> - Option<Constant> { - unify_int_type(lty, rty, if neg { Minus } else { Plus }).and_then( - |ty| l.checked_sub(r).map(|v| ConstantInt(v, ty))) +fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> Option<Constant> { + unify_int_type(lty, + rty, + if neg { + Minus + } else { + Plus + }) + .and_then(|ty| l.checked_sub(r).map(|v| ConstantInt(v, ty))) } pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { - let mut cx = ConstEvalLateContext { lcx: Some(lcx), needed_resolution: false }; + let mut cx = ConstEvalLateContext { + lcx: Some(lcx), + needed_resolution: false, + }; cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } pub fn constant_simple(e: &Expr) -> Option<Constant> { - let mut cx = ConstEvalLateContext { lcx: None, needed_resolution: false }; + let mut cx = ConstEvalLateContext { + lcx: None, + needed_resolution: false, + }; cx.expr(e) } struct ConstEvalLateContext<'c, 'cc: 'c> { lcx: Option<&'c LateContext<'c, 'cc>>, - needed_resolution: bool + needed_resolution: bool, } impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { - /// simple constant folding: Insert an expression, get a constant or none. fn expr(&mut self, e: &Expr) -> Option<Constant> { match e.node { ExprPath(_, _) => self.fetch_path(e), ExprBlock(ref block) => self.block(block), - ExprIf(ref cond, ref then, ref otherwise) => - self.ifthenelse(cond, then, otherwise), + ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), ExprVec(ref vec) => self.multi(vec).map(ConstantVec), ExprTup(ref tup) => self.multi(tup).map(ConstantTuple), - ExprRepeat(ref value, ref number) => - self.binop_apply(value, number, |v, n| - Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))), - ExprUnary(op, ref operand) => self.expr(operand).and_then( - |o| match op { - UnNot => constant_not(o), - UnNeg => constant_negate(o), - UnDeref => Some(o), - }), - ExprBinary(op, ref left, ref right) => - self.binop(op, left, right), - //TODO: add other expressions + ExprRepeat(ref value, ref number) => { + self.binop_apply(value, number, |v, n| Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))) + } + ExprUnary(op, ref operand) => { + self.expr(operand).and_then(|o| { + match op { + UnNot => constant_not(o), + UnNeg => constant_negate(o), + UnDeref => Some(o), + } + }) + } + ExprBinary(op, ref left, ref right) => self.binop(op, left, right), + // TODO: add other expressions _ => None, } } /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part - fn multi<E: Deref<Target=Expr> + Sized>(&mut self, vec: &[E]) -> - Option<Vec<Constant>> { - vec.iter().map(|elem| self.expr(elem)) - .collect::<Option<_>>() + fn multi<E: Deref<Target = Expr> + Sized>(&mut self, vec: &[E]) -> Option<Vec<Constant>> { + vec.iter() + .map(|elem| self.expr(elem)) + .collect::<Option<_>>() } /// lookup a possibly constant expression from a ExprPath fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { if let Some(lcx) = self.lcx { let mut maybe_id = None; - if let Some(&PathResolution { base_def: DefConst(id), ..}) = - lcx.tcx.def_map.borrow().get(&e.id) { + if let Some(&PathResolution { base_def: DefConst(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { maybe_id = Some(id); } // separate if lets to avoid doubleborrowing the defmap @@ -426,63 +502,84 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn block(&mut self, block: &Block) -> Option<Constant> { if block.stmts.is_empty() { block.expr.as_ref().and_then(|ref b| self.expr(b)) - } else { None } + } else { + None + } } - fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) - -> Option<Constant> { + fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) -> Option<Constant> { if let Some(ConstantBool(b)) = self.expr(cond) { if b { self.block(then) } else { otherwise.as_ref().and_then(|expr| self.expr(expr)) } - } else { None } + } else { + None + } } fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { match op.node { - BiAdd => self.binop_apply(left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => - l8.checked_add(r8).map(ConstantByte), - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - if ln == rn { - unify_int_type(lty, rty, if ln { Minus } else { Plus }) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))) - } else { - if ln { - add_neg_int(r64, rty, l64, lty) + BiAdd => { + self.binop_apply(left, right, |l, r| { + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => l8.checked_add(r8).map(ConstantByte), + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + let (ln, rn) = (is_negative(lty), is_negative(rty)); + if ln == rn { + unify_int_type(lty, + rty, + if ln { + Minus + } else { + Plus + }) + .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) } else { - add_neg_int(l64, lty, r64, rty) + if ln { + add_neg_int(r64, rty, l64, lty) + } else { + add_neg_int(l64, lty, r64, rty) + } } } + // TODO: float (would need bignum library?) + _ => None, } - // TODO: float (would need bignum library?) - _ => None - }), - BiSub => self.binop_apply(left, right, |l, r| - match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { - None } else { Some(ConstantByte(l8 - r8)) }, - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => - match (is_negative(lty), is_negative(rty)) { - (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), - (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), - (true, false) => unify_int_type(lty, rty, Minus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - (false, true) => unify_int_type(lty, rty, Plus) - .and_then(|ty| l64.checked_add(r64).map( - |v| ConstantInt(v, ty))), - }, - _ => None, - }), + }) + } + BiSub => { + self.binop_apply(left, right, |l, r| { + match (l, r) { + (ConstantByte(l8), ConstantByte(r8)) => { + if r8 > l8 { + None + } else { + Some(ConstantByte(l8 - r8)) + } + } + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + match (is_negative(lty), is_negative(rty)) { + (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), + (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), + (true, false) => { + unify_int_type(lty, rty, Minus) + .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + } + (false, true) => { + unify_int_type(lty, rty, Plus) + .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + } + } + } + _ => None, + } + }) + } BiMul => self.divmul(left, right, u64::checked_mul), BiDiv => self.divmul(left, right, u64::checked_div), - //BiRem, + // BiRem, BiAnd => self.short_circuit(left, right, false), BiOr => self.short_circuit(left, right, true), BiBitXor => self.bitop(left, right, |x, y| x ^ y), @@ -490,70 +587,86 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiBitOr => self.bitop(left, right, |x, y| (x | y)), BiShl => self.bitop(left, right, |x, y| x << y), BiShr => self.bitop(left, right, |x, y| x >> y), - BiEq => self.binop_apply(left, right, - |l, r| Some(ConstantBool(l == r))), - BiNe => self.binop_apply(left, right, - |l, r| Some(ConstantBool(l != r))), + BiEq => self.binop_apply(left, right, |l, r| Some(ConstantBool(l == r))), + BiNe => self.binop_apply(left, right, |l, r| Some(ConstantBool(l != r))), BiLt => self.cmp(left, right, Less, true), BiLe => self.cmp(left, right, Greater, false), BiGe => self.cmp(left, right, Less, false), BiGt => self.cmp(left, right, Greater, true), - _ => None + _ => None, } } - fn divmul<F>(&mut self, left: &Expr, right: &Expr, f: F) - -> Option<Constant> where F: Fn(u64, u64) -> Option<u64> { - self.binop_apply(left, right, |l, r| + fn divmul<F>(&mut self, left: &Expr, right: &Expr, f: F) -> Option<Constant> + where F: Fn(u64, u64) -> Option<u64> + { + self.binop_apply(left, right, |l, r| { match (l, r) { (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - f(l64, r64).and_then(|value| - unify_int_type(lty, rty, if is_negative(lty) == - is_negative(rty) { Plus } else { Minus }) - .map(|ty| ConstantInt(value, ty))) + f(l64, r64).and_then(|value| { + unify_int_type(lty, + rty, + if is_negative(lty) == is_negative(rty) { + Plus + } else { + Minus + }) + .map(|ty| ConstantInt(value, ty)) + }) } _ => None, - }) + } + }) } - fn bitop<F>(&mut self, left: &Expr, right: &Expr, f: F) - -> Option<Constant> where F: Fn(u64, u64) -> u64 { - self.binop_apply(left, right, |l, r| match (l, r) { - (ConstantBool(l), ConstantBool(r)) => - Some(ConstantBool(f(l as u64, r as u64) != 0)), - (ConstantByte(l8), ConstantByte(r8)) => - Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), - (ConstantInt(l, lty), ConstantInt(r, rty)) => - unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)), - _ => None + fn bitop<F>(&mut self, left: &Expr, right: &Expr, f: F) -> Option<Constant> + where F: Fn(u64, u64) -> u64 + { + self.binop_apply(left, right, |l, r| { + match (l, r) { + (ConstantBool(l), ConstantBool(r)) => Some(ConstantBool(f(l as u64, r as u64) != 0)), + (ConstantByte(l8), ConstantByte(r8)) => Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), + (ConstantInt(l, lty), ConstantInt(r, rty)) => { + unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)) + } + _ => None, + } }) } fn cmp(&mut self, left: &Expr, right: &Expr, ordering: Ordering, b: bool) -> Option<Constant> { - self.binop_apply(left, right, |l, r| l.partial_cmp(&r).map(|o| - ConstantBool(b == (o == ordering)))) + self.binop_apply(left, + right, + |l, r| l.partial_cmp(&r).map(|o| ConstantBool(b == (o == ordering)))) } fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> - where F: Fn(Constant, Constant) -> Option<Constant> { + where F: Fn(Constant, Constant) -> Option<Constant> + { if let (Some(lc), Some(rc)) = (self.expr(left), self.expr(right)) { op(lc, rc) - } else { None } + } else { + None + } } fn short_circuit(&mut self, left: &Expr, right: &Expr, b: bool) -> Option<Constant> { - self.expr(left).and_then(|left| + self.expr(left).and_then(|left| { if let ConstantBool(lbool) = left { if lbool == b { Some(left) } else { - self.expr(right).and_then(|right| + self.expr(right).and_then(|right| { if let ConstantBool(_) = right { Some(right) - } else { None } - ) + } else { + None + } + }) } - } else { None } - ) + } else { + None + } + }) } } diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 7beb3296aac..d4375abcd05 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -27,9 +27,7 @@ pub struct CyclomaticComplexity { impl CyclomaticComplexity { pub fn new(limit: u64) -> Self { - CyclomaticComplexity { - limit: LimitStack::new(limit), - } + CyclomaticComplexity { limit: LimitStack::new(limit) } } } @@ -41,7 +39,9 @@ impl LintPass for CyclomaticComplexity { impl CyclomaticComplexity { fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) { - if in_macro(cx, span) { return; } + if in_macro(cx, span) { + return; + } let cfg = CFG::new(cx.tcx, block); let n = cfg.graph.len_nodes() as u64; let e = cfg.graph.len_edges() as u64; @@ -59,9 +59,11 @@ impl CyclomaticComplexity { } else { let rust_cc = cc + divergence - narms; if rust_cc > self.limit.limit() { - span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, span, - &format!("The function has a cyclomatic complexity of {}", rust_cc), - "You could split it up into multiple smaller functions"); + span_help_and_lint(cx, + CYCLOMATIC_COMPLEXITY, + span, + &format!("The function has a cyclomatic complexity of {}", rust_cc), + "You could split it up into multiple smaller functions"); } } } @@ -105,8 +107,8 @@ impl<'a> Visitor<'a> for MatchArmCounter { if arms_n > 1 { self.0 += arms_n - 2; } - }, - ExprClosure(..) => {}, + } + ExprClosure(..) => {} _ => walk_expr(self, e), } } @@ -125,8 +127,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> { self.0 += 1; } } - }, - ExprClosure(..) => {}, + } + ExprClosure(..) => {} _ => walk_expr(self, e), } } @@ -134,15 +136,22 @@ impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> { #[cfg(feature="debugging")] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { - cx.sess().span_bug(span, &format!("Clippy encountered a bug calculating cyclomatic complexity: \ - cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div));; + cx.sess().span_bug(span, + &format!("Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ + div = {}. Please file a bug report.", + cc, + narms, + div));; } #[cfg(not(feature="debugging"))] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { cx.sess().span_note_without_error(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): \ - cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div)); + (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ + = {}, arms = {}, div = {}. Please file a bug report.", + cc, + narms, + div)); } } diff --git a/src/eq_op.rs b/src/eq_op.rs index 3d2f32e6c7f..31dc094385f 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -30,19 +30,29 @@ impl LateLintPass for EqOp { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) { - span_lint(cx, EQ_OP, e.span, &format!( - "equal expressions as operands to {}", - ast_util::binop_to_string(op.node))); + span_lint(cx, + EQ_OP, + e.span, + &format!("equal expressions as operands to {}", ast_util::binop_to_string(op.node))); } } } } -fn is_cmp_or_bit(op : &BinOp) -> bool { +fn is_cmp_or_bit(op: &BinOp) -> bool { match op.node { - BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | - BiBitXor | BiBitAnd | BiBitOr => true, - _ => false + BiEq | + BiLt | + BiLe | + BiGt | + BiGe | + BiNe | + BiAnd | + BiOr | + BiBitXor | + BiBitAnd | + BiBitOr => true, + _ => false, } } diff --git a/src/escape.rs b/src/escape.rs index 4b6a8258dbe..079fdcf09a0 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -43,13 +43,7 @@ impl LintPass for EscapePass { } impl LateLintPass for EscapePass { - fn check_fn(&mut self, - cx: &LateContext, - _: visit::FnKind, - decl: &FnDecl, - body: &Block, - _: Span, - id: NodeId) { + fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env), false); let mut v = EscapeDelegate { @@ -70,11 +64,7 @@ impl LateLintPass for EscapePass { } impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, - _: NodeId, - _: Span, - cmt: cmt<'tcx>, - mode: ConsumeMode) { + fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { @@ -119,12 +109,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn borrow(&mut self, - borrow_id: NodeId, - _: Span, - cmt: cmt<'tcx>, - _: ty::Region, - _: ty::BorrowKind, + fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { @@ -145,9 +130,15 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } else if LoanCause::AddrOf == loan_cause { // &x - if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = - self.cx.tcx.tables.borrow().adjustments - .get(&self.cx.tcx.map.get_parent_node(borrow_id)) { + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.cx + .tcx + .tables + .borrow() + .adjustments + .get(&self.cx + .tcx + .map + .get_parent_node(borrow_id)) { if adj.autoderefs <= 1 { // foo(&x) where no extra autoreffing is happening self.set.remove(&lid); @@ -162,10 +153,5 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } fn decl_without_init(&mut self, _: NodeId, _: Span) {} - fn mutate(&mut self, - _: NodeId, - _: Span, - _: cmt<'tcx>, - _: MutateMode) { - } + fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 6b561ff7a05..46c458c6bcb 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -73,22 +73,18 @@ fn check_closure(cx: &LateContext, expr: &Expr) { } if p.segments[0].identifier != ident.node { // The two idents should be the same - return + return; } } else { - return + return; } } else { - return + return; } } - span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, - "redundant closure found", - |db| { + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { if let Some(snippet) = snippet_opt(cx, caller.span) { - db.span_suggestion(expr.span, - "remove closure as shown:", - snippet); + db.span_suggestion(expr.span, "remove closure as shown:", snippet); } }); } diff --git a/src/identity_op.rs b/src/identity_op.rs index 88a03e050be..fd5071d4013 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -27,26 +27,26 @@ impl LintPass for IdentityOp { impl LateLintPass for IdentityOp { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if in_macro(cx, e.span) { return; } + if in_macro(cx, e.span) { + return; + } if let ExprBinary(ref cmp, ref left, ref right) = e.node { match cmp.node { BiAdd | BiBitOr | BiBitXor => { check(cx, left, 0, e.span, right.span); check(cx, right, 0, e.span, left.span); } - BiShl | BiShr | BiSub => - check(cx, right, 0, e.span, left.span), + BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), BiMul => { check(cx, left, 1, e.span, right.span); check(cx, right, 1, e.span, left.span); } - BiDiv => - check(cx, right, 1, e.span, left.span), + BiDiv => check(cx, right, 1, e.span, left.span), BiBitAnd => { check(cx, left, -1, e.span, right.span); check(cx, right, -1, e.span, left.span); } - _ => () + _ => (), } } } @@ -61,9 +61,11 @@ fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { 1 => !is_negative(ty) && v == 1, _ => unreachable!(), } { - span_lint(cx, IDENTITY_OP, span, &format!( - "the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, ".."))); + span_lint(cx, + IDENTITY_OP, + span, + &format!("the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, ".."))); } } } diff --git a/src/len_zero.rs b/src/len_zero.rs index d574fa2c336..6bc5bc4bf01 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -49,21 +49,18 @@ impl LintPass for LenZero { impl LateLintPass for LenZero { fn check_item(&mut self, cx: &LateContext, item: &Item) { match item.node { - ItemTrait(_, _, _, ref trait_items) => - check_trait_items(cx, item, trait_items), - ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait - check_impl_items(cx, item, impl_items), - _ => () + ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), + ItemImpl(_, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), + _ => (), } } fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = - expr.node { + if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = expr.node { match cmp { BiEq => check_cmp(cx, expr.span, left, right, ""), BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), - _ => () + _ => (), } } } @@ -71,37 +68,52 @@ impl LateLintPass for LenZero { fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.name.as_str() == name && if let MethodTraitItem(ref sig, _) = - item.node { is_self_sig(sig) } else { false } + item.name.as_str() == name && + if let MethodTraitItem(ref sig, _) = item.node { + is_self_sig(sig) + } else { + false + } } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident)); + // span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident)); for i in trait_items { if is_named_self(i, "len") { - span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, - &format!("trait `{}` has a `.len(_: &Self)` method, but no \ - `.is_empty(_: &Self)` method. Consider adding one", + span_lint(cx, + LEN_WITHOUT_IS_EMPTY, + i.span, + &format!("trait `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ + Consider adding one", item.name)); } - }; + } } } fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.name.as_str() == name && if let ImplItemKind::Method(ref sig, _) = - item.node { is_self_sig(sig) } else { false } + item.name.as_str() == name && + if let ImplItemKind::Method(ref sig, _) = item.node { + is_self_sig(sig) + } else { + false + } } if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { for i in impl_items { if is_named_self(i, "len") { let s = i.span; - span_lint(cx, LEN_WITHOUT_IS_EMPTY, - Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, - &format!("item `{}` has a `.len(_: &Self)` method, but no \ - `.is_empty(_: &Self)` method. Consider adding one", + span_lint(cx, + LEN_WITHOUT_IS_EMPTY, + Span { + lo: s.lo, + hi: s.lo, + expn_id: s.expn_id, + }, + &format!("item `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ + Consider adding one", item.name)); return; } @@ -111,32 +123,40 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { fn is_self_sig(sig: &MethodSig) -> bool { if let SelfStatic = sig.explicit_self.node { - false } else { sig.decl.inputs.len() == 1 } + false + } else { + sig.decl.inputs.len() == 1 + } } fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, left) { - if name.as_str() == "is_empty" { return; } + if name.as_str() == "is_empty" { + return; + } } match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => - check_len_zero(cx, span, &method.node, args, lit, op), - (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => - check_len_zero(cx, span, &method.node, args, lit, op), - _ => () + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => { + check_len_zero(cx, span, &method.node, args, lit, op) + } + (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => { + check_len_zero(cx, span, &method.node, args, lit, op) + } + _ => (), } } -fn check_len_zero(cx: &LateContext, span: Span, name: &Name, - args: &[P<Expr>], lit: &Lit, op: &str) { +fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitInt(0, _), ..} = *lit { - if name.as_str() == "len" && args.len() == 1 && - has_is_empty(cx, &args[0]) { - span_lint(cx, LEN_ZERO, span, &format!( - "consider replacing the len comparison with `{}{}.is_empty()`", - op, snippet(cx, args[0].span, "_"))); - } + if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { + span_lint(cx, + LEN_ZERO, + span, + &format!("consider replacing the len comparison with `{}{}.is_empty()`", + op, + snippet(cx, args[0].span, "_"))); + } } } @@ -145,31 +165,35 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// get a ImplOrTraitItem and return true if it matches is_empty(self) fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { if let MethodTraitItemId(def_id) = *id { - if let ty::MethodTraitItem(ref method) = - cx.tcx.impl_or_trait_item(def_id) { - method.name.as_str() == "is_empty" - && method.fty.sig.skip_binder().inputs.len() == 1 - } else { false } - } else { false } + if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { + method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 + } else { + false + } + } else { + false + } } /// check the inherent impl's items for an is_empty(self) method fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool { let impl_items = cx.tcx.impl_items.borrow(); - cx.tcx.inherent_impls.borrow().get(id).map_or(false, - |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, - |iids| iids.iter().any(|i| is_is_empty(cx, i))))) + cx.tcx.inherent_impls.borrow().get(id).map_or(false, |ids| { + ids.iter().any(|iid| impl_items.get(iid).map_or(false, |iids| iids.iter().any(|i| is_is_empty(cx, i)))) + }) } let ty = &walk_ptrs_ty(&cx.tcx.expr_ty(expr)); match ty.sty { - ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( - &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, - |ids| ids.iter().any(|i| is_is_empty(cx, i))), - ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, - |id| has_is_empty_impl(cx, &id)), - ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => - has_is_empty_impl(cx, &id.did), + ty::TyTrait(_) => { + cx.tcx + .trait_item_def_ids + .borrow() + .get(&ty.ty_to_def_id().expect("trait impl not found")) + .map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))) + } + ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), + ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), ty::TyArray(..) => true, _ => false, } diff --git a/src/lib.rs b/src/lib.rs index 76c04d53a0b..2ac8e9044db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,9 @@ // this only exists to allow the "dogfood" integration test to work #[allow(dead_code)] -fn main() { println!("What are you doing? Don't run clippy as an executable"); } +fn main() { + println!("What are you doing? Don't run clippy as an executable"); +} #[macro_use] extern crate syntax; @@ -128,7 +130,8 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box array_indexing::ArrayIndexing); reg.register_late_lint_pass(box panic::PanicPass); - reg.register_lint_group("clippy_pedantic", vec![ + reg.register_lint_group("clippy_pedantic", + vec![ methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, @@ -147,7 +150,8 @@ pub fn plugin_registrar(reg: &mut Registry) { unicode::UNICODE_NOT_NFC, ]); - reg.register_lint_group("clippy", vec![ + reg.register_lint_group("clippy", + vec![ approx_const::APPROX_CONSTANT, array_indexing::OUT_OF_BOUNDS_INDEXING, attrs::INLINE_ALWAYS, diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 6ae10c09455..2de916cfebc 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -47,15 +47,13 @@ impl LateLintPass for LifetimePass { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let ImplItemKind::Method(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), - &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); } } fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), - &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); } } } @@ -69,20 +67,20 @@ enum RefLt { } use self::RefLt::*; -fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, - generics: &Generics, span: Span) { +fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, generics: &Generics, span: Span) { if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; } if could_use_elision(cx, decl, slf, &generics.lifetimes) { - span_lint(cx, NEEDLESS_LIFETIMES, span, + span_lint(cx, + NEEDLESS_LIFETIMES, + span, "explicit lifetimes given in parameter types where they could be elided"); } report_extra_lifetimes(cx, decl, &generics); } -fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, - named_lts: &[LifetimeDef]) -> bool { +fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, named_lts: &[LifetimeDef]) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT // * output references, exactly one input reference with same LT @@ -102,7 +100,7 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> match slf.node { SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), - _ => { } + _ => {} } } // extract lifetimes in input argument types @@ -147,8 +145,8 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> (&Named(n1), &Named(n2)) if n1 == n2 => true, (&Named(_), &Unnamed) => true, (&Unnamed, &Named(_)) => true, - _ => false // already elided, different named lifetimes - // or something static going on + _ => false, // already elided, different named lifetimes + // or something static going on } } else { false @@ -176,12 +174,15 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize { /// A visitor usable for rustc_front::visit::walk_ty(). struct RefVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference - lts: Vec<RefLt> + lts: Vec<RefLt>, } -impl <'v, 't> RefVisitor<'v, 't> { +impl<'v, 't> RefVisitor<'v, 't> { fn new(cx: &'v LateContext<'v, 't>) -> RefVisitor<'v, 't> { - RefVisitor { cx: cx, lts: Vec::new() } + RefVisitor { + cx: cx, + lts: Vec::new(), + } } fn record(&mut self, lifetime: &Option<Lifetime>) { @@ -211,13 +212,13 @@ impl <'v, 't> RefVisitor<'v, 't> { for _ in type_scheme.generics.regions.as_slice() { self.record(&None); } - }, + } DefTrait(def_id) => { let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; for _ in &trait_def.generics.regions { self.record(&None); } - }, + } _ => {} } } @@ -227,7 +228,6 @@ impl <'v, 't> RefVisitor<'v, 't> { } impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { - // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.record(&Some(*lifetime)); @@ -258,7 +258,9 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { let mut visitor = RefVisitor::new(cx); // walk the type F, it may not contain LT refs walk_ty(&mut visitor, &pred.bounded_ty); - if !visitor.lts.is_empty() { return true; } + if !visitor.lts.is_empty() { + return true; + } // if the bounds define new lifetimes, they are fine to occur let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); // now walk the bounds @@ -275,7 +277,9 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { WherePredicate::EqPredicate(ref pred) => { let mut visitor = RefVisitor::new(cx); walk_ty(&mut visitor, &pred.ty); - if !visitor.lts.is_empty() { return true; } + if !visitor.lts.is_empty() { + return true; + } } } } @@ -285,7 +289,6 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { struct LifetimeChecker(HashMap<Name, Span>); impl<'v> Visitor<'v> for LifetimeChecker { - // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { self.0.remove(&lifetime.name); @@ -300,16 +303,15 @@ impl<'v> Visitor<'v> for LifetimeChecker { } } -fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, - generics: &Generics) { - let hs = generics.lifetimes.iter() +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) { + let hs = generics.lifetimes + .iter() .map(|lt| (lt.lifetime.name, lt.lifetime.span)) .collect(); let mut checker = LifetimeChecker(hs); walk_generics(&mut checker, generics); walk_fn_decl(&mut checker, func); for (_, v) in checker.0 { - span_lint(cx, UNUSED_LIFETIMES, v, - "this lifetime isn't used in the function definition"); + span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); } } diff --git a/src/loops.rs b/src/loops.rs index a0454a325e4..91bb898629f 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -5,14 +5,13 @@ use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use rustc::middle::ty; use rustc::middle::def::DefLocal; use consts::{constant_simple, Constant}; -use rustc::front::map::Node::{NodeBlock}; +use rustc::front::map::Node::NodeBlock; use std::borrow::Cow; -use std::collections::{HashSet,HashMap}; +use std::collections::{HashSet, HashMap}; use syntax::ast::Lit_::*; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, - in_external_macro, expr_block, span_help_and_lint, is_integer_literal, - get_enclosing_block}; +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, + span_help_and_lint, is_integer_literal, get_enclosing_block}; use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH}; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. @@ -128,9 +127,14 @@ pub struct LoopsPass; impl LintPass for LoopsPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP, - WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, - EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, + lint_array!(NEEDLESS_RANGE_LOOP, + EXPLICIT_ITER_LOOP, + ITER_NEXT_LOOP, + WHILE_LET_LOOP, + UNUSED_COLLECT, + REVERSE_RANGE_LOOP, + EXPLICIT_COUNTER_LOOP, + EMPTY_LOOP, WHILE_LET_ON_ITERATOR) } } @@ -146,10 +150,11 @@ impl LateLintPass for LoopsPass { if let ExprLoop(ref block, _) = expr.node { // also check for empty `loop {}` statements if block.stmts.is_empty() && block.expr.is_none() { - span_lint(cx, EMPTY_LOOP, expr.span, - "empty `loop {}` detected. You may want to either \ - use `panic!()` or add `std::thread::sleep(..);` to \ - the loop body."); + span_lint(cx, + EMPTY_LOOP, + expr.span, + "empty `loop {}` detected. You may want to either use `panic!()` or add \ + `std::thread::sleep(..);` to the loop body."); } // extract the expression from the first statement (if any) in a block @@ -159,11 +164,10 @@ impl LateLintPass for LoopsPass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // collect the remaining statements below the match let mut other_stuff = block.stmts - .iter() - .skip(1) - .map(|stmt| { - format!("{}", snippet(cx, stmt.span, "..")) - }).collect::<Vec<String>>(); + .iter() + .skip(1) + .map(|stmt| format!("{}", snippet(cx, stmt.span, ".."))) + .collect::<Vec<String>>(); if inner_stmt_expr.is_some() { // if we have a statement which has a match, if let Some(ref expr) = block.expr { @@ -174,29 +178,31 @@ impl LateLintPass for LoopsPass { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | MatchSource::IfLetDesugar{..} => if - arms.len() == 2 && - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - // finally, check for "break" in the second clause - is_break_expr(&arms[1].body) - { - if in_external_macro(cx, expr.span) { return; } - let loop_body = if inner_stmt_expr.is_some() { - // FIXME: should probably be an ellipsis - // tabbing and newline is probably a bad idea, especially for large blocks - Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))) - } else { - expr_block(cx, &arms[0].body, Some(other_stuff.join("\n ")), "..") - }; - span_help_and_lint(cx, WHILE_LET_LOOP, expr.span, - "this loop could be written as a `while let` loop", - &format!("try\nwhile let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, ".."), - loop_body)); - }, - _ => () + MatchSource::Normal | MatchSource::IfLetDesugar{..} => { + if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + is_break_expr(&arms[1].body) { + if in_external_macro(cx, expr.span) { + return; + } + let loop_body = if inner_stmt_expr.is_some() { + // FIXME: should probably be an ellipsis + // tabbing and newline is probably a bad idea, especially for large blocks + Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))) + } else { + expr_block(cx, &arms[0].body, Some(other_stuff.join("\n ")), "..") + }; + span_help_and_lint(cx, + WHILE_LET_LOOP, + expr.span, + "this loop could be written as a `while let` loop", + &format!("try\nwhile let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, matchexpr.span, ".."), + loop_body)); + } + } + _ => (), } } } @@ -204,21 +210,20 @@ impl LateLintPass for LoopsPass { if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; if let (&PatEnum(ref path, Some(ref pat_args)), - &ExprMethodCall(method_name, _, ref method_args)) = - (pat, &match_expr.node) { + &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; if let Some(lhs_constructor) = path.segments.last() { if method_name.node.as_str() == "next" && - match_trait_method(cx, match_expr, &["core", "iter", "Iterator"]) && - lhs_constructor.identifier.name.as_str() == "Some" && - !is_iterator_used_after_while_let(cx, iter_expr) { + match_trait_method(cx, match_expr, &["core", "iter", "Iterator"]) && + lhs_constructor.identifier.name.as_str() == "Some" && + !is_iterator_used_after_while_let(cx, iter_expr) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); - span_help_and_lint(cx, WHILE_LET_ON_ITERATOR, expr.span, + span_help_and_lint(cx, + WHILE_LET_ON_ITERATOR, + expr.span, "this loop could be written as a `for` loop", - &format!("try\nfor {} in {} {{...}}", - loop_var, - iterator)); + &format!("try\nfor {} in {} {{...}}", loop_var, iterator)); } } } @@ -229,10 +234,12 @@ impl LateLintPass for LoopsPass { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.node.as_str() == "collect" && - match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { - span_lint(cx, UNUSED_COLLECT, expr.span, &format!( - "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator")); + match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + span_lint(cx, + UNUSED_COLLECT, + expr.span, + &format!("you are collect()ing an iterator and throwing away the result. Consider \ + using an explicit for loop to exhaust the iterator")); } } } @@ -249,23 +256,38 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E // the var must be a single name if let PatIdent(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { cx: cx, var: ident.node.name, - indexed: HashSet::new(), nonindex: false }; + let mut visitor = VarVisitor { + cx: cx, + var: ident.node.name, + indexed: HashSet::new(), + nonindex: false, + }; walk_expr(&mut visitor, body); // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let indexed = visitor.indexed.into_iter().next().expect( - "Len was nonzero, but no contents found"); + let indexed = visitor.indexed + .into_iter() + .next() + .expect("Len was nonzero, but no contents found"); if visitor.nonindex { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is used to index `{}`. Consider using \ - `for ({}, item) in {}.iter().enumerate()` or similar iterators", - ident.node.name, indexed, ident.node.name, indexed)); + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`. Consider using `for \ + ({}, item) in {}.iter().enumerate()` or similar iterators", + ident.node.name, + indexed, + ident.node.name, + indexed)); } else { - span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, &format!( - "the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in &{}` or similar iterators", - ident.node.name, indexed, indexed)); + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`. Consider using \ + `for item in &{}` or similar iterators", + ident.node.name, + indexed, + indexed)); } } } @@ -283,15 +305,21 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E // who think that this will iterate from the larger value to the // smaller value. if start_idx > stop_idx { - span_help_and_lint(cx, REVERSE_RANGE_LOOP, expr.span, - "this range is empty so this for loop will never run", - &format!("Consider using `({}..{}).rev()` if you are attempting to \ - iterate over this range in reverse", stop_idx, start_idx)); + span_help_and_lint(cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run", + &format!("Consider using `({}..{}).rev()` if you are attempting to iterate \ + over this range in reverse", + stop_idx, + start_idx)); } else if start_idx == stop_idx { // if they are equal, it's also problematic - this loop // will never run. - span_lint(cx, REVERSE_RANGE_LOOP, expr.span, - "this range is empty so this for loop will never run"); + span_lint(cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run"); } } } @@ -305,46 +333,65 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { if is_ref_iterable_type(cx, &args[0]) { let object = snippet(cx, args[0].span, "_"); - span_lint(cx, EXPLICIT_ITER_LOOP, expr.span, &format!( - "it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", - if method_name.as_str() == "iter_mut" { "mut " } else { "" }, - object, object, method_name)); + span_lint(cx, + EXPLICIT_ITER_LOOP, + expr.span, + &format!("it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", + if method_name.as_str() == "iter_mut" { + "mut " + } else { + "" + }, + object, + object, + method_name)); } - } - // check for looping over Iterator::next() which is not what you want - else if method_name.as_str() == "next" && - match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { - span_lint(cx, ITER_NEXT_LOOP, expr.span, - "you are iterating over `Iterator::next()` which is an Option; \ - this will compile but is probably not what you want"); + } else if method_name.as_str() == "next" && match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { + span_lint(cx, + ITER_NEXT_LOOP, + expr.span, + "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ + probably not what you want"); } } } // Look for variables that are incremented once per loop iteration. - let mut visitor = IncrementVisitor { cx: cx, states: HashMap::new(), depth: 0, done: false }; + let mut visitor = IncrementVisitor { + cx: cx, + states: HashMap::new(), + depth: 0, + done: false, + }; walk_expr(&mut visitor, body); // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.map; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id) ); + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) { - let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(), - state: VarState::IncrOnce, name: None, - depth: 0, - past_loop: false }; + for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { + let mut visitor2 = InitializeVisitor { + cx: cx, + end_expr: expr, + var_id: id.clone(), + state: VarState::IncrOnce, + name: None, + depth: 0, + past_loop: false, + }; walk_block(&mut visitor2, block); if visitor2.state == VarState::Warn { if let Some(name) = visitor2.name { - span_lint(cx, EXPLICIT_COUNTER_LOOP, expr.span, - &format!("the variable `{0}` is used as a loop counter. Consider \ - using `for ({0}, item) in {1}.enumerate()` \ - or similar iterators", - name, snippet(cx, arg.span, "_"))); + span_lint(cx, + EXPLICIT_COUNTER_LOOP, + expr.span, + &format!("the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ + item) in {1}.enumerate()` or similar iterators", + name, + snippet(cx, arg.span, "_"))); } } } @@ -378,9 +425,9 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { struct VarVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference - var: Name, // var name to look for as index - indexed: HashSet<Name>, // indexed variables - nonindex: bool, // has the var been used otherwise? + var: Name, // var name to look for as index + indexed: HashSet<Name>, // indexed variables + nonindex: bool, // has the var been used otherwise? } impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { @@ -411,14 +458,14 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool { let def_id = match var_def_id(cx, iter_expr) { Some(id) => id, - None => return false + None => return false, }; let mut visitor = VarUsedAfterLoopVisitor { cx: cx, def_id: def_id, iter_expr_id: iter_expr.id, past_while_let: false, - var_used_after_while_let: false + var_used_after_while_let: false, }; if let Some(enclosing_block) = get_enclosing_block(cx, def_id) { walk_block(&mut visitor, enclosing_block); @@ -431,10 +478,10 @@ struct VarUsedAfterLoopVisitor<'v, 't: 'v> { def_id: NodeId, iter_expr_id: NodeId, past_while_let: bool, - var_used_after_while_let: bool + var_used_after_while_let: bool, } -impl <'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { +impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { fn visit_expr(&mut self, expr: &'v Expr) { if self.past_while_let { if Some(self.def_id) == var_def_id(self.cx, expr) { @@ -454,43 +501,52 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tcx.expr_ty(e); - is_iterable_array(ty) || - match_type(cx, ty, &VEC_PATH) || - match_type(cx, ty, &LL_PATH) || - match_type(cx, ty, &HASHMAP_PATH) || - match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || - match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || - match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || - match_type(cx, ty, &["collections", "btree", "map", "BTreeMap"]) || - match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) + is_iterable_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || + match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || + match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || + match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || + match_type(cx, ty, &["collections", "btree", "map", "BTreeMap"]) || + match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) } fn is_iterable_array(ty: ty::Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { ty::TyArray(_, 0...32) => true, - _ => false + _ => false, } } /// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { - if block.stmts.is_empty() { return None; } + if block.stmts.is_empty() { + return None; + } if let StmtDecl(ref decl, _) = block.stmts[0].node { if let DeclLocal(ref local) = decl.node { - if let Some(ref expr) = local.init { Some(expr) } else { None } - } else { None } - } else { None } + if let Some(ref expr) = local.init { + Some(expr) + } else { + None + } + } else { + None + } + } else { + None + } } /// If a block begins with an expression (with or without semicolon), return it. fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) => Some(expr), - None if !block.stmts.is_empty() => match block.stmts[0].node { - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), - _ => None, - }, + None if !block.stmts.is_empty() => { + match block.stmts[0].node { + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + _ => None, + } + } _ => None, } } @@ -500,10 +556,12 @@ fn is_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(None) => true, // there won't be a `let <pat> = break` and so we can safely ignore the StmtDecl case - ExprBlock(ref b) => match extract_first_expr(b) { - Some(ref subexpr) => is_break_expr(subexpr), - None => false, - }, + ExprBlock(ref b) => { + match extract_first_expr(b) { + Some(ref subexpr) => is_break_expr(subexpr), + None => false, + } + } _ => false, } } @@ -513,19 +571,19 @@ fn is_break_expr(expr: &Expr) -> bool { // at the start of the loop. #[derive(PartialEq)] enum VarState { - Initial, // Not examined yet - IncrOnce, // Incremented exactly once, may be a loop counter - Declared, // Declared but not (yet) initialized to zero + Initial, // Not examined yet + IncrOnce, // Incremented exactly once, may be a loop counter + Declared, // Declared but not (yet) initialized to zero Warn, - DontWarn + DontWarn, } // Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, // context reference - states: HashMap<NodeId, VarState>, // incremented variables - depth: u32, // depth of conditional expressions - done: bool + cx: &'v LateContext<'v, 't>, // context reference + states: HashMap<NodeId, VarState>, // incremented variables + depth: u32, // depth of conditional expressions + done: bool, } impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { @@ -540,33 +598,29 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { let state = self.states.entry(def_id).or_insert(VarState::Initial); match parent.node { - ExprAssignOp(op, ref lhs, ref rhs) => + ExprAssignOp(op, ref lhs, ref rhs) => { if lhs.id == expr.id { if op.node == BiAdd && is_integer_literal(rhs, 1) { *state = match *state { VarState::Initial if self.depth == 0 => VarState::IncrOnce, - _ => VarState::DontWarn + _ => VarState::DontWarn, }; - } - else { + } else { // Assigned some other value *state = VarState::DontWarn; } - }, + } + } ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, - ExprAddrOf(mutability,_) if mutability == MutMutable => *state = VarState::DontWarn, - _ => () + ExprAddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn, + _ => (), } } - } - // Give up if there are nested loops - else if is_loop(expr) { + } else if is_loop(expr) { self.states.clear(); self.done = true; return; - } - // Keep track of whether we're inside a conditional expression - else if is_conditional(expr) { + } else if is_conditional(expr) { self.depth += 1; walk_expr(self, expr); self.depth -= 1; @@ -579,12 +633,12 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { // Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference - end_expr: &'v Expr, // the for loop. Stop scanning here. + end_expr: &'v Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, name: Option<Name>, - depth: u32, // depth of conditional expressions - past_loop: bool + depth: u32, // depth of conditional expressions + past_loop: bool, } impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { @@ -601,8 +655,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { } else { VarState::Declared } - } - else { + } else { VarState::Declared } } @@ -637,9 +690,10 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { VarState::Warn } else { VarState::DontWarn - }} - ExprAddrOf(mutability,_) if mutability == MutMutable => self.state = VarState::DontWarn, - _ => () + } + } + ExprAddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn, + _ => (), } } @@ -647,14 +701,10 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { self.state = VarState::DontWarn; return; } - } - // If there are other loops between the declaration and the target loop, give up - else if !self.past_loop && is_loop(expr) { + } else if !self.past_loop && is_loop(expr) { self.state = VarState::DontWarn; return; - } - // Keep track of whether we're inside a conditional expression - else if is_conditional(expr) { + } else if is_conditional(expr) { self.depth += 1; walk_expr(self, expr); self.depth -= 1; @@ -667,7 +717,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { if let DefLocal(_, node_id) = path_res.base_def { - return Some(node_id) + return Some(node_id); } } None @@ -675,14 +725,14 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { fn is_loop(expr: &Expr) -> bool { match expr.node { - ExprLoop(..) | ExprWhile(..) => true, - _ => false + ExprLoop(..) | ExprWhile(..) => true, + _ => false, } } fn is_conditional(expr: &Expr) -> bool { match expr.node { ExprIf(..) | ExprMatch(..) => true, - _ => false + _ => false, } } diff --git a/src/map_clone.rs b/src/map_clone.rs index ef992ad086c..9db97a1b9f2 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -65,10 +65,13 @@ impl LateLintPass for MapClonePass { ExprPath(_, ref path) => { if match_path(path, &CLONE_PATH) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + span_help_and_lint(cx, + MAP_CLONE, + expr.span, + &format!("you seem to be using .map() to clone the contents of an \ + {}, consider using `.cloned()`", + type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); } } _ => (), @@ -81,7 +84,10 @@ impl LateLintPass for MapClonePass { fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { match expr.node { ExprPath(None, ref path) => { - let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }]; + let arg_segment = [PathSegment { + identifier: id, + parameters: PathParameters::none(), + }]; !path.global && path.segments[..] == arg_segment } _ => false, @@ -108,9 +114,7 @@ fn get_arg_name(pat: &Pat) -> Option<Ident> { fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool { match expr.node { - ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => { - only_derefs(cx, subexpr, id) - } + ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), _ => expr_eq_ident(expr, id), } } diff --git a/src/matches.rs b/src/matches.rs index 8564c36e617..5e207093c15 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -94,7 +94,9 @@ impl LintPass for MatchPass { impl LateLintPass for MatchPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { return; } + if in_external_macro(cx, expr.span) { + return; + } if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { check_single_match(cx, ex, arms, expr); check_match_bool(cx, ex, arms, expr); @@ -107,23 +109,14 @@ impl LateLintPass for MatchPass { } fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { - if arms.len() == 2 && - // both of the arms have a single pattern and no guard - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - // and the second pattern is a `_` wildcard: this is not strictly necessary, - // since the exhaustiveness check will ensure the last one is a catch-all, - // but in some cases, an explicit match is preferred to catch situations - // when an enum is extended, so we don't consider these cases - arms[1].pats[0].node == PatWild && - // we don't want any content in the second arm (unit or empty block) - is_unit_expr(&arms[1].body) && - // finally, MATCH_BOOL doesn't apply here - (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) - { - span_help_and_lint(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for destructuring a \ - single pattern. Consider using `if let`", + if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && + arms[1].guard.is_none() && arms[1].pats[0].node == PatWild && is_unit_expr(&arms[1].body) && + (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) { + span_help_and_lint(cx, + SINGLE_MATCH, + expr.span, + "you seem to be trying to use match for destructuring a single pattern. Consider using \ + `if let`", &format!("try\nif let {} = {} {}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), @@ -134,7 +127,8 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { - if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards + if arms.len() == 2 && arms[0].pats.len() == 1 { + // no guards let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { match lit.node { @@ -142,54 +136,67 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { LitBool(false) => Some((&*arms[1].body, &*arms[0].body)), _ => None, } - } else { None } - } else { None }; + } else { + None + } + } else { + None + }; if let Some((ref true_expr, ref false_expr)) = exprs { if !is_unit_expr(true_expr) { if !is_unit_expr(false_expr) { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))); + span_help_and_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using \ + an if..else block:", + &format!("try\nif {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))); } else { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."))); + span_help_and_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using \ + an if..else block:", + &format!("try\nif {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."))); } } else if !is_unit_expr(false_expr) { - span_help_and_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block:", - &format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))); + span_help_and_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using an \ + if..else block:", + &format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))); } else { - span_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); + span_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using an if..else \ + block"); } } else { - span_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); + span_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using an if..else block"); } } else { - span_lint(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. \ - Consider using an if..else block"); + span_lint(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using an if..else block"); } } } fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { - if arms.len() >= 2 && - cx.tcx.expr_ty(ex).is_integral() { + if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms); let overlap = match type_ranges(&ranges) { TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), @@ -198,9 +205,12 @@ fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { }; if let Some((start, end)) = overlap { - span_note_and_lint(cx, MATCH_OVERLAPPING_ARM, start, + span_note_and_lint(cx, + MATCH_OVERLAPPING_ARM, + start, "some ranges overlap", - end, "overlaps with this"); + end, + "overlaps with this"); } } } @@ -209,14 +219,18 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { let template = match_template(cx, expr.span, source, "", inner); - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "you don't need to add `&` to both the expression \ - and the patterns: use `{}`", template)); + span_lint(cx, + MATCH_REF_PATS, + expr.span, + &format!("you don't need to add `&` to both the expression and the patterns: use `{}`", + template)); } else { let template = match_template(cx, expr.span, source, "*", ex); - span_lint(cx, MATCH_REF_PATS, expr.span, &format!( - "instead of prefixing all patterns with `&`, you can dereference the \ - expression: `{}`", template)); + span_lint(cx, + MATCH_REF_PATS, + expr.span, + &format!("instead of prefixing all patterns with `&`, you can dereference the expression: `{}`", + template)); } } } @@ -244,8 +258,7 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { None })) - } - else { + } else { None } }) @@ -271,29 +284,36 @@ enum TypedRanges { fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { if ranges.is_empty() { TypedRanges::None - } - else { + } else { match ranges[0].node { (Int(_), Int(_)) => { - TypedRanges::IntRanges(ranges.iter().filter_map(|range| { - if let (Int(start), Int(end)) = range.node { - Some(SpannedRange { span: range.span, node: (start, end) }) - } - else { - None - } - }).collect()) - }, + TypedRanges::IntRanges(ranges.iter() + .filter_map(|range| { + if let (Int(start), Int(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None + } + }) + .collect()) + } (Uint(_), Uint(_)) => { - TypedRanges::UintRanges(ranges.iter().filter_map(|range| { - if let (Uint(start), Uint(end)) = range.node { - Some(SpannedRange { span: range.span, node: (start, end) }) - } - else { - None - } - }).collect()) - }, + TypedRanges::UintRanges(ranges.iter() + .filter_map(|range| { + if let (Uint(start), Uint(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None + } + }) + .collect()) + } _ => TypedRanges::None, } } @@ -308,39 +328,33 @@ fn is_unit_expr(expr: &Expr) -> bool { } fn has_only_ref_pats(arms: &[Arm]) -> bool { - let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node { - PatRegion(..) => Some(true), // &-patterns - PatWild => Some(false), // an "anything" wildcard is also fine - _ => None, // any other pattern is not fine - }).collect::<Option<Vec<bool>>>(); + let mapped = arms.iter() + .flat_map(|a| &a.pats) + .map(|p| { + match p.node { + PatRegion(..) => Some(true), // &-patterns + PatWild => Some(false), // an "anything" wildcard is also fine + _ => None, // any other pattern is not fine + } + }) + .collect::<Option<Vec<bool>>>(); // look for Some(v) where there's at least one true element mapped.map_or(false, |v| v.iter().any(|el| *el)) } -fn match_template(cx: &LateContext, - span: Span, - source: MatchSource, - op: &str, - expr: &Expr) -> String { +fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, expr: &Expr) -> String { let expr_snippet = snippet(cx, expr.span, ".."); match source { - MatchSource::Normal => { - format!("match {}{} {{ ...", op, expr_snippet) - } - MatchSource::IfLetDesugar { .. } => { - format!("if let ... = {}{} {{", op, expr_snippet) - } - MatchSource::WhileLetDesugar => { - format!("while let ... = {}{} {{", op, expr_snippet) - } - MatchSource::ForLoopDesugar => { - cx.sess().span_bug(span, "for loop desugared to match with &-patterns!") - } + MatchSource::Normal => format!("match {}{} {{ ...", op, expr_snippet), + MatchSource::IfLetDesugar { .. } => format!("if let ... = {}{} {{", op, expr_snippet), + MatchSource::WhileLetDesugar => format!("while let ... = {}{} {{", op, expr_snippet), + MatchSource::ForLoopDesugar => cx.sess().span_bug(span, "for loop desugared to match with &-patterns!"), } } pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> - where T: Copy + Ord { + where T: Copy + Ord +{ #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Kind<'a, T: 'a> { Start(T, &'a SpannedRange<T>), @@ -350,13 +364,13 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & impl<'a, T: Copy> Kind<'a, T> { fn range(&self) -> &'a SpannedRange<T> { match *self { - Kind::Start(_, r) | Kind::End(_, r) => r + Kind::Start(_, r) | Kind::End(_, r) => r, } } fn value(self) -> T { match self { - Kind::Start(t, _) | Kind::End(t, _) => t + Kind::Start(t, _) | Kind::End(t, _) => t, } } } @@ -373,7 +387,7 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & } } - let mut values = Vec::with_capacity(2*ranges.len()); + let mut values = Vec::with_capacity(2 * ranges.len()); for r in ranges { values.push(Kind::Start(r.node.0, &r)); @@ -384,7 +398,11 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & for (a, b) in values.iter().zip(values.iter().skip(1)) { match (a, b) { - (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node { return Some((ra, rb)) }, + (&Kind::Start(_, ra), &Kind::End(_, rb)) => { + if ra.node != rb.node { + return Some((ra, rb)); + } + } (&Kind::End(a, _), &Kind::Start(b, _)) if a != b => (), _ => return Some((&a.range(), &b.range())), } diff --git a/src/methods.rs b/src/methods.rs index 2aa3b040e55..83b9e60f4be 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -5,8 +5,8 @@ use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; -use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, - match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty}; +use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, match_trait_method, + walk_ptrs_ty_depth, walk_ptrs_ty}; use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; use utils::MethodArgs; @@ -172,9 +172,16 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, - SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, - OK_EXPECT, OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE) + lint_array!(OPTION_UNWRAP_USED, + RESULT_UNWRAP_USED, + STR_TO_STRING, + STRING_TO_STRING, + SHOULD_IMPLEMENT_TRAIT, + WRONG_SELF_CONVENTION, + WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, + OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE) } } @@ -183,29 +190,21 @@ impl LateLintPass for MethodsPass { if let ExprMethodCall(_, _, _) = expr.node { if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { lint_unwrap(cx, expr, arglists[0]); - } - else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { + } else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { lint_to_string(cx, expr, arglists[0]); - } - else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { + } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { lint_ok_expect(cx, expr, arglists[0]); - } - else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); - } - else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); - } - else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { + } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { lint_filter_next(cx, expr, arglists[0]); - } - else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { + } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); - } - else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { + } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); - } - else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { + } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); } } @@ -235,16 +234,22 @@ impl LateLintPass for MethodsPass { let is_copy = is_copy(cx, &ty, &item); for &(prefix, self_kinds) in &CONVENTIONS { if name.as_str().starts_with(prefix) && - !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { + !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { let lint = if item.vis == Visibility::Public { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION }; - span_lint(cx, lint, sig.explicit_self.span, &format!( - "methods called `{}*` usually take {}; consider choosing a less \ - ambiguous name", prefix, - &self_kinds.iter().map(|k| k.description()).collect::<Vec<_>>().join(" or "))); + span_lint(cx, + lint, + sig.explicit_self.span, + &format!("methods called `{}*` usually take {}; consider choosing a less \ + ambiguous name", + prefix, + &self_kinds.iter() + .map(|k| k.description()) + .collect::<Vec<_>>() + .join(" or "))); } } } @@ -253,30 +258,34 @@ impl LateLintPass for MethodsPass { } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `unwrap()` for `Option`s and `Result`s fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); let mess = if match_type(cx, obj_ty, &OPTION_PATH) { Some((OPTION_UNWRAP_USED, "an Option", "None")) - } - else if match_type(cx, obj_ty, &RESULT_PATH) { + } else if match_type(cx, obj_ty, &RESULT_PATH) { Some((RESULT_UNWRAP_USED, "a Result", "Err")) - } - else { + } else { None }; if let Some((lint, kind, none_value)) = mess { - span_lint(cx, lint, expr.span, - &format!("used unwrap() on {} value. If you don't want to handle the {} \ - case gracefully, consider using expect() to provide a better panic - message", kind, none_value)); + span_lint(cx, + lint, + expr.span, + &format!("used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ + using expect() to provide a better panic + message", + kind, + none_value)); } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `to_string()` for `&str`s and `String`s fn lint_to_string(cx: &LateContext, expr: &Expr, to_string_args: &MethodArgs) { let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&to_string_args[0])); @@ -284,21 +293,19 @@ fn lint_to_string(cx: &LateContext, expr: &Expr, to_string_args: &MethodArgs) { if obj_ty.sty == ty::TyStr { let mut arg_str = snippet(cx, to_string_args[0].span, "_"); if ptr_depth > 1 { - arg_str = Cow::Owned(format!( - "({}{})", - iter::repeat('*').take(ptr_depth - 1).collect::<String>(), - arg_str)); + arg_str = Cow::Owned(format!("({}{})", iter::repeat('*').take(ptr_depth - 1).collect::<String>(), arg_str)); } - span_lint(cx, STR_TO_STRING, expr.span, - &format!("`{}.to_owned()` is faster", arg_str)); - } - else if match_type(cx, obj_ty, &STRING_PATH) { - span_lint(cx, STRING_TO_STRING, expr.span, + span_lint(cx, STR_TO_STRING, expr.span, &format!("`{}.to_owned()` is faster", arg_str)); + } else if match_type(cx, obj_ty, &STRING_PATH) { + span_lint(cx, + STRING_TO_STRING, + expr.span, "`String.to_string()` is a no-op; use `clone()` to make a copy"); } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `ok().expect()` for `Result`s fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { // lint if the caller of `ok()` is a `Result` @@ -306,107 +313,120 @@ fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { let result_type = cx.tcx.expr_ty(&ok_args[0]); if let Some(error_type) = get_error_type(cx, result_type) { if has_debug_impl(error_type, cx) { - span_lint(cx, OK_EXPECT, expr.span, - "called `ok().expect()` on a Result value. You can call `expect` \ - directly on the `Result`"); + span_lint(cx, + OK_EXPECT, + expr.span, + "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`"); } } } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, - unwrap_args: &MethodArgs) { +fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message - let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more \ - directly by calling `map_or(a, f)` instead"; + let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ + `map_or(a, f)` instead"; // get snippets for args to map() and unwrap_or() let map_snippet = snippet(cx, map_args[1].span, ".."); let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); // lint, with note if neither arg is > 1 line and both map() and // unwrap_or() have the same span - let multiline = map_snippet.lines().count() > 1 - || unwrap_snippet.lines().count() > 1; + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; if same_span && !multiline { - span_note_and_lint( - cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, - &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", map_snippet, - unwrap_snippet) - ); - } - else if same_span && multiline { + span_note_and_lint(cx, + OPTION_MAP_UNWRAP_OR, + expr.span, + msg, + expr.span, + &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", + map_snippet, + unwrap_snippet)); + } else if same_span && multiline { span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); }; } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, - unwrap_args: &MethodArgs) { +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { // lint message - let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more \ - directly by calling `map_or_else(g, f)` instead"; + let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ + `map_or_else(g, f)` instead"; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_args[1].span, ".."); let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); // lint, with note if neither arg is > 1 line and both map() and // unwrap_or_else() have the same span - let multiline = map_snippet.lines().count() > 1 - || unwrap_snippet.lines().count() > 1; + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; if same_span && !multiline { - span_note_and_lint( - cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg, expr.span, - &format!("replace `map({0}).unwrap_or_else({1})` with `with map_or_else({1}, {0})`", - map_snippet, unwrap_snippet) - ); - } - else if same_span && multiline { + span_note_and_lint(cx, + OPTION_MAP_UNWRAP_OR_ELSE, + expr.span, + msg, + expr.span, + &format!("replace `map({0}).unwrap_or_else({1})` with `with map_or_else({1}, {0})`", + map_snippet, + unwrap_snippet)); + } else if same_span && multiline { span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); }; } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint use of `filter().next() for Iterators` fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { - let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by \ - calling `.find(p)` instead."; + let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ + instead."; let filter_snippet = snippet(cx, filter_args[1].span, ".."); - if filter_snippet.lines().count() <= 1 { // add note if not multi-line - span_note_and_lint(cx, FILTER_NEXT, expr.span, msg, expr.span, - &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); - } - else { + if filter_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint(cx, + FILTER_NEXT, + expr.span, + msg, + expr.span, + &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); + } else { span_lint(cx, FILTER_NEXT, expr.span, msg); } } } -#[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec /// lint searching an Iterator followed by `is_some()` fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, search_args: &MethodArgs, is_some_args: &MethodArgs) { // lint if caller of search is an Iterator if match_trait_method(cx, &*is_some_args[0], &["core", "iter", "Iterator"]) { - let msg = format!("called `is_some()` after searching an iterator with {}. This is more \ - succinctly expressed by calling `any()`.", search_method); + let msg = format!("called `is_some()` after searching an iterator with {}. This is more succinctly expressed \ + by calling `any()`.", + search_method); let search_snippet = snippet(cx, search_args[1].span, ".."); - if search_snippet.lines().count() <= 1 { // add note if not multi-line - span_note_and_lint(cx, SEARCH_IS_SOME, expr.span, &msg, expr.span, - &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, - search_snippet)); - } - else { + if search_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint(cx, + SEARCH_IS_SOME, + expr.span, + &msg, + expr.span, + &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet)); + } else { span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); } } @@ -432,7 +452,7 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { let no_ref_ty = walk_ptrs_ty(ty); let debug = match cx.tcx.lang_items.debug_trait() { Some(debug) => debug, - None => return false + None => return false, }; let debug_def = cx.tcx.lookup_trait_def(debug); let mut debug_impl_exists = false; @@ -447,46 +467,162 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { debug_impl_exists } -const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ - ("into_", &[ValueSelf]), - ("to_", &[RefSelf]), - ("as_", &[RefSelf, RefMutSelf]), - ("is_", &[RefSelf, NoSelf]), - ("from_", &[NoSelf]), -]; - -const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ - ("add", 2, ValueSelf, AnyType, "std::ops::Add"), - ("sub", 2, ValueSelf, AnyType, "std::ops::Sub"), - ("mul", 2, ValueSelf, AnyType, "std::ops::Mul"), - ("div", 2, ValueSelf, AnyType, "std::ops::Div"), - ("rem", 2, ValueSelf, AnyType, "std::ops::Rem"), - ("shl", 2, ValueSelf, AnyType, "std::ops::Shl"), - ("shr", 2, ValueSelf, AnyType, "std::ops::Shr"), - ("bitand", 2, ValueSelf, AnyType, "std::ops::BitAnd"), - ("bitor", 2, ValueSelf, AnyType, "std::ops::BitOr"), - ("bitxor", 2, ValueSelf, AnyType, "std::ops::BitXor"), - ("neg", 1, ValueSelf, AnyType, "std::ops::Neg"), - ("not", 1, ValueSelf, AnyType, "std::ops::Not"), - ("drop", 1, RefMutSelf, UnitType, "std::ops::Drop"), - ("index", 2, RefSelf, RefType, "std::ops::Index"), - ("index_mut", 2, RefMutSelf, RefType, "std::ops::IndexMut"), - ("deref", 1, RefSelf, RefType, "std::ops::Deref"), - ("deref_mut", 1, RefMutSelf, RefType, "std::ops::DerefMut"), - ("clone", 1, RefSelf, AnyType, "std::clone::Clone"), - ("borrow", 1, RefSelf, RefType, "std::borrow::Borrow"), - ("borrow_mut", 1, RefMutSelf, RefType, "std::borrow::BorrowMut"), - ("as_ref", 1, RefSelf, RefType, "std::convert::AsRef"), - ("as_mut", 1, RefMutSelf, RefType, "std::convert::AsMut"), - ("eq", 2, RefSelf, BoolType, "std::cmp::PartialEq"), - ("cmp", 2, RefSelf, AnyType, "std::cmp::Ord"), - ("default", 0, NoSelf, AnyType, "std::default::Default"), - ("hash", 2, RefSelf, UnitType, "std::hash::Hash"), - ("next", 1, RefMutSelf, AnyType, "std::iter::Iterator"), - ("into_iter", 1, ValueSelf, AnyType, "std::iter::IntoIterator"), - ("from_iter", 1, NoSelf, AnyType, "std::iter::FromIterator"), - ("from_str", 1, NoSelf, AnyType, "std::str::FromStr"), -]; +const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [("into_", &[ValueSelf]), + ("to_", &[RefSelf]), + ("as_", &[RefSelf, RefMutSelf]), + ("is_", &[RefSelf, NoSelf]), + ("from_", &[NoSelf])]; + +const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [("add", + 2, + ValueSelf, + AnyType, + "std::ops::Add"), + ("sub", + 2, + ValueSelf, + AnyType, + "std::ops::Sub"), + ("mul", + 2, + ValueSelf, + AnyType, + "std::ops::Mul"), + ("div", + 2, + ValueSelf, + AnyType, + "std::ops::Div"), + ("rem", + 2, + ValueSelf, + AnyType, + "std::ops::Rem"), + ("shl", + 2, + ValueSelf, + AnyType, + "std::ops::Shl"), + ("shr", + 2, + ValueSelf, + AnyType, + "std::ops::Shr"), + ("bitand", + 2, + ValueSelf, + AnyType, + "std::ops::BitAnd"), + ("bitor", + 2, + ValueSelf, + AnyType, + "std::ops::BitOr"), + ("bitxor", + 2, + ValueSelf, + AnyType, + "std::ops::BitXor"), + ("neg", + 1, + ValueSelf, + AnyType, + "std::ops::Neg"), + ("not", + 1, + ValueSelf, + AnyType, + "std::ops::Not"), + ("drop", + 1, + RefMutSelf, + UnitType, + "std::ops::Drop"), + ("index", + 2, + RefSelf, + RefType, + "std::ops::Index"), + ("index_mut", + 2, + RefMutSelf, + RefType, + "std::ops::IndexMut"), + ("deref", + 1, + RefSelf, + RefType, + "std::ops::Deref"), + ("deref_mut", + 1, + RefMutSelf, + RefType, + "std::ops::DerefMut"), + ("clone", + 1, + RefSelf, + AnyType, + "std::clone::Clone"), + ("borrow", + 1, + RefSelf, + RefType, + "std::borrow::Borrow"), + ("borrow_mut", + 1, + RefMutSelf, + RefType, + "std::borrow::BorrowMut"), + ("as_ref", + 1, + RefSelf, + RefType, + "std::convert::AsRef"), + ("as_mut", + 1, + RefMutSelf, + RefType, + "std::convert::AsMut"), + ("eq", + 2, + RefSelf, + BoolType, + "std::cmp::PartialEq"), + ("cmp", + 2, + RefSelf, + AnyType, + "std::cmp::Ord"), + ("default", + 0, + NoSelf, + AnyType, + "std::default::Default"), + ("hash", + 2, + RefSelf, + UnitType, + "std::hash::Hash"), + ("next", + 1, + RefMutSelf, + AnyType, + "std::iter::Iterator"), + ("into_iter", + 1, + ValueSelf, + AnyType, + "std::iter::IntoIterator"), + ("from_iter", + 1, + NoSelf, + AnyType, + "std::iter::FromIterator"), + ("from_str", + 1, + NoSelf, + AnyType, + "std::str::FromStr")]; #[derive(Clone, Copy)] enum SelfKind { @@ -506,7 +642,7 @@ impl SelfKind { (&RefMutSelf, &SelfValue(_)) => allow_value_for_ref, (&NoSelf, &SelfStatic) => true, (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), - _ => false + _ => false, } } @@ -517,7 +653,7 @@ impl SelfKind { (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, (&RefSelf, &TyPath(..)) => allow_value_for_ref, (&RefMutSelf, &TyPath(..)) => allow_value_for_ref, - _ => false + _ => false, } } @@ -545,11 +681,15 @@ impl OutType { (&UnitType, &DefaultReturn(_)) => true, (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![].into()) => true, (&BoolType, &Return(ref ty)) if is_bool(ty) => true, - (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, + (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, (&RefType, &Return(ref ty)) => { - if let TyRptr(_, _) = ty.node { true } else { false } + if let TyRptr(_, _) = ty.node { + true + } else { + false + } } - _ => false + _ => false, } } } diff --git a/src/minmax.rs b/src/minmax.rs index 2a8e064f9f4..2cce36f2a9c 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -32,12 +32,13 @@ impl LateLintPass for MinMaxPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { - if outer_max == inner_max { return; } + if outer_max == inner_max { + return; + } match (outer_max, outer_c.partial_cmp(&inner_c)) { (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), _ => { - span_lint(cx, MIN_MAX, expr.span, - "this min/max combination leads to constant result"); + span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); } } } @@ -65,20 +66,30 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' None } } - } else { None } - } else { None } - } + } else { + None + } + } else { + None + } +} -fn fetch_const(args: &[P<Expr>], m: MinMax) -> - Option<(MinMax, Constant, &Expr)> { - if args.len() != 2 { return None } +fn fetch_const(args: &[P<Expr>], m: MinMax) -> Option<(MinMax, Constant, &Expr)> { + if args.len() != 2 { + return None; + } if let Some(c) = constant_simple(&args[0]) { - if let None = constant_simple(&args[1]) { // otherwise ignore + if let None = constant_simple(&args[1]) { + // otherwise ignore Some((m, c, &args[1])) - } else { None } + } else { + None + } } else { if let Some(c) = constant_simple(&args[1]) { Some((m, c, &args[0])) - } else { None } + } else { + None + } } } diff --git a/src/misc.rs b/src/misc.rs index 92276961d11..1b7f2a921b9 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -40,15 +40,14 @@ impl LateLintPass for TopLevelRefPass { fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { if let FnKind::Closure = k { // Does not apply to closures - return + return; } for ref arg in &decl.inputs { if let PatIdent(BindByRef(_), _, _) = arg.pat.node { span_lint(cx, - TOPLEVEL_REF_ARG, - arg.pat.span, - "`ref` directly on a function argument is ignored. Consider using a reference type instead." - ); + TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. Consider using a reference type instead."); } } } @@ -112,9 +111,13 @@ impl LateLintPass for CmpNan { } fn check_nan(cx: &LateContext, path: &Path, span: Span) { - path.segments.last().map(|seg| if seg.identifier.name.as_str() == "NAN" { - span_lint(cx, CMP_NAN, span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); + path.segments.last().map(|seg| { + if seg.identifier.name.as_str() == "NAN" { + span_lint(cx, + CMP_NAN, + span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); + } }); } @@ -144,20 +147,24 @@ impl LateLintPass for FloatCmp { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { let op = cmp.node; if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - if is_allowed(cx, left) || is_allowed(cx, right) { return; } + if is_allowed(cx, left) || is_allowed(cx, right) { + return; + } if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); - if name == "eq" || name == "ne" || name == "is_nan" || - name.starts_with("eq_") || - name.ends_with("_eq") { + if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || + name.ends_with("_eq") { return; } } - span_lint(cx, FLOAT_CMP, expr.span, &format!( - "{}-comparison of f32 or f64 detected. Consider changing this to \ - `abs({} - {}) < epsilon` for some suitable value of epsilon", - binop_to_string(op), snippet(cx, left.span, ".."), - snippet(cx, right.span, ".."))); + span_lint(cx, + FLOAT_CMP, + expr.span, + &format!("{}-comparison of f32 or f64 detected. Consider changing this to `abs({} - {}) < \ + epsilon` for some suitable value of epsilon", + binop_to_string(op), + snippet(cx, left.span, ".."), + snippet(cx, right.span, ".."))); } } } @@ -167,7 +174,9 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); if let Ok(Float(val)) = res { val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY - } else { false } + } else { + false + } } fn is_float(cx: &LateContext, expr: &Expr) -> bool { @@ -211,44 +220,54 @@ impl LateLintPass for CmpOwned { fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, op: Span) { let snip = match expr.node { ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) if args.len() == 1 => { - if name.as_str() == "to_string" || - name.as_str() == "to_owned" && is_str_arg(cx, args) { - snippet(cx, args[0].span, "..") - } else { - return - } + if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { + snippet(cx, args[0].span, "..") + } else { + return; + } } ExprCall(ref path, ref v) if v.len() == 1 => { if let ExprPath(None, ref path) = path.node { - if match_path(path, &["String", "from_str"]) || - match_path(path, &["String", "from"]) { - snippet(cx, v[0].span, "..") - } else { - return - } + if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { + snippet(cx, v[0].span, "..") + } else { + return; + } } else { - return + return; } } - _ => return + _ => return, }; if left { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. Consider using \ - `{} {} {}` to compare without allocation", snip, - snippet(cx, op, "=="), snippet(cx, other_span, ".."))); + span_lint(cx, + CMP_OWNED, + expr.span, + &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ + compare without allocation", + snip, + snippet(cx, op, "=="), + snippet(cx, other_span, ".."))); } else { - span_lint(cx, CMP_OWNED, expr.span, &format!( - "this creates an owned instance just for comparison. Consider using \ - `{} {} {}` to compare without allocation", - snippet(cx, other_span, ".."), snippet(cx, op, "=="), snip)); + span_lint(cx, + CMP_OWNED, + expr.span, + &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ + compare without allocation", + snippet(cx, other_span, ".."), + snippet(cx, op, "=="), + snip)); } } fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { - args.len() == 1 && if let ty::TyStr = - walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false } + args.len() == 1 && + if let ty::TyStr = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { + true + } else { + false + } } /// **What it does:** This lint checks for getting the remainder of a division by one. It is `Warn` by default. @@ -309,9 +328,11 @@ impl LateLintPass for PatternPass { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatIdent(_, ref ident, Some(ref right)) = pat.node { if right.node == PatWild { - cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!( - "the `{} @ _` pattern can be written as just `{}`", - ident.node.name, ident.node.name)); + cx.span_lint(REDUNDANT_PATTERN, + pat.span, + &format!("the `{} @ _` pattern can be written as just `{}`", + ident.node.name, + ident.node.name)); } } } @@ -345,30 +366,31 @@ impl LintPass for UsedUnderscoreBinding { impl LateLintPass for UsedUnderscoreBinding { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_attributes_expansion(cx, expr) { // Don't lint things expanded by #[derive(...)], etc + if in_attributes_expansion(cx, expr) { + // Don't lint things expanded by #[derive(...)], etc return; } let needs_lint = match expr.node { ExprPath(_, ref path) => { - let ident = path.segments.last() + let ident = path.segments + .last() .expect("path should always have at least one segment") .identifier; - ident.name.as_str().chars().next() == Some('_') //starts with '_' - && ident.name.as_str().chars().skip(1).next() != Some('_') //doesn't start with "__" - && ident.name != ident.unhygienic_name //not in bang macro - && is_used(cx, expr) - }, + ident.name.as_str().chars().next() == Some('_') && + ident.name.as_str().chars().skip(1).next() != Some('_') && + ident.name != ident.unhygienic_name && is_used(cx, expr) + } ExprField(_, spanned) => { let name = spanned.node.as_str(); - name.chars().next() == Some('_') - && name.chars().skip(1).next() != Some('_') - }, - _ => false + name.chars().next() == Some('_') && name.chars().skip(1).next() != Some('_') + } + _ => false, }; if needs_lint { - cx.span_lint(USED_UNDERSCORE_BINDING, expr.span, - "used binding which is prefixed with an underscore. A leading underscore \ - signals that a binding will not be used."); + cx.span_lint(USED_UNDERSCORE_BINDING, + expr.span, + "used binding which is prefixed with an underscore. A leading underscore signals that a \ + binding will not be used."); } } } @@ -380,10 +402,9 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { match parent.node { ExprAssign(_, ref rhs) => **rhs == *expr, ExprAssignOp(_, _, ref rhs) => **rhs == *expr, - _ => is_used(cx, &parent) + _ => is_used(cx, &parent), } - } - else { + } else { true } } diff --git a/src/misc_early.rs b/src/misc_early.rs index 7a59c15275f..a90c901df8f 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -52,15 +52,15 @@ impl EarlyLintPass for MiscEarly { } } if !pfields.is_empty() && wilds == pfields.len() { - span_help_and_lint(cx, UNNEEDED_FIELD_PATTERN, pat.span, - "All the struct fields are matched to a wildcard pattern, \ - consider using `..`.", - &format!("Try with `{} {{ .. }}` instead", - type_name)); + span_help_and_lint(cx, + UNNEEDED_FIELD_PATTERN, + pat.span, + "All the struct fields are matched to a wildcard pattern, consider using `..`.", + &format!("Try with `{} {{ .. }}` instead", type_name)); return; } if wilds > 0 { - let mut normal = vec!(); + let mut normal = vec![]; for field in pfields { if field.node.pat.node != PatWild { @@ -73,13 +73,16 @@ impl EarlyLintPass for MiscEarly { if field.node.pat.node == PatWild { wilds -= 1; if wilds > 0 { - span_lint(cx, UNNEEDED_FIELD_PATTERN, field.span, - "You matched a field with a wildcard pattern. \ - Consider using `..` instead"); + span_lint(cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` instead"); } else { - span_help_and_lint(cx, UNNEEDED_FIELD_PATTERN, field.span, - "You matched a field with a wildcard pattern. \ - Consider using `..` instead", + span_help_and_lint(cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` \ + instead", &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", "))); @@ -91,7 +94,7 @@ impl EarlyLintPass for MiscEarly { } fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - let mut registered_names : HashMap<String, Span> = HashMap::new(); + let mut registered_names: HashMap<String, Span> = HashMap::new(); for ref arg in &decl.inputs { if let PatIdent(_, sp_ident, None) = arg.pat.node { @@ -99,10 +102,12 @@ impl EarlyLintPass for MiscEarly { if arg_name.starts_with("_") { if let Some(correspondance) = registered_names.get(&arg_name[1..]) { - span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, *correspondance, - &format!("`{}` already exists, having another argument having almost \ - the same name makes code comprehension and documentation \ - more difficult", arg_name[1..].to_owned())); + span_lint(cx, + DUPLICATE_UNDERSCORE_ARGUMENT, + *correspondance, + &format!("`{}` already exists, having another argument having almost the same \ + name makes code comprehension and documentation more difficult", + arg_name[1..].to_owned())); } } else { registered_names.insert(arg_name, arg.pat.span.clone()); diff --git a/src/mut_mut.rs b/src/mut_mut.rs index db6f0e0320b..1bdb4e9a3d6 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -30,42 +30,46 @@ impl LateLintPass for MutMut { } fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| { span_lint(cx, MUT_MUT, - ty.span, "generally you want to avoid `&mut &mut _` if possible"); }); + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| { + span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); + }); } } fn check_expr_mut(cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { return; } + if in_external_macro(cx, expr.span) { + return; + } fn unwrap_addr(expr: &Expr) -> Option<&Expr> { match expr.node { ExprAddrOf(MutMutable, ref e) => Some(e), - _ => None + _ => None, } } unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map_or_else( - || { - if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = - cx.tcx.expr_ty(e).sty { - span_lint(cx, MUT_MUT, expr.span, - "this expression mutably borrows a mutable reference. \ - Consider reborrowing"); - } - }, - |_| { - span_lint(cx, MUT_MUT, expr.span, - "generally you want to avoid `&mut &mut _` if possible"); - } - ) + unwrap_addr(e).map_or_else(|| { + if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = cx.tcx.expr_ty(e).sty { + span_lint(cx, + MUT_MUT, + expr.span, + "this expression mutably borrows a mutable reference. Consider \ + reborrowing"); + } + }, + |_| { + span_lint(cx, + MUT_MUT, + expr.span, + "generally you want to avoid `&mut &mut _` if possible"); + }) }) } fn unwrap_mut(ty: &Ty) -> Option<&Ty> { match ty.node { TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Some(pty), - _ => None + _ => None, } } diff --git a/src/mut_reference.rs b/src/mut_reference.rs index ddfd9ddcc13..d92e449e7f2 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -36,13 +36,12 @@ impl LateLintPass for UnnecessaryMutPassed { match borrowed_table.node_types.get(&fn_expr.id) { Some(function_type) => { if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, &arguments, function_type, - &format!("{}", path)); + check_arguments(cx, &arguments, function_type, &format!("{}", path)); } } None => unreachable!(), // A function with unknown type is called. - // If this happened the compiler would have aborted the - // compilation long ago. + // If this happened the compiler would have aborted the + // compilation long ago. }; @@ -50,8 +49,9 @@ impl LateLintPass for UnnecessaryMutPassed { ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); match borrowed_table.method_map.get(&method_call) { - Some(method_type) => check_arguments(cx, &arguments, method_type.ty, - &format!("{}", name.node.as_str())), + Some(method_type) => { + check_arguments(cx, &arguments, method_type.ty, &format!("{}", name.node.as_str())) + } None => unreachable!(), // Just like above, this should never happen. }; } @@ -68,10 +68,10 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, UNNECESSARY_MUT_PASSED, - argument.span, &format!("The function/method \"{}\" \ - doesn't need a mutable reference", - name)); + span_lint(cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method \"{}\" doesn't need a mutable reference", name)); } } _ => {} diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 8899eb56d42..7b75bd747bb 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -52,17 +52,13 @@ impl LateLintPass for MutexAtomic { if match_type(cx, ty, &MUTEX_PATH) { let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; if let Some(atomic_name) = get_atomic_name(mutex_param) { - let msg = format!("Consider using an {} instead of a \ - Mutex here. If you just want the \ - locking behaviour and not the internal \ - type, consider using Mutex<()>.", + let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ + behaviour and not the internal type, consider using Mutex<()>.", atomic_name); match *mutex_param { - ty::TyUint(t) if t != ast::TyUs => - span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::TyInt(t) if t != ast::TyIs => - span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg) + ty::TyUint(t) if t != ast::TyUs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyInt(t) if t != ast::TyIs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } } @@ -76,6 +72,6 @@ fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { ty::TyUint(_) => Some("AtomicUsize"), ty::TyInt(_) => Some("AtomicIsize"), ty::TyRawPtr(_) => Some("AtomicPtr"), - _ => None + _ => None, } } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index bd2e4116fd0..22edbc272bd 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -37,30 +37,42 @@ impl LateLintPass for NeedlessBool { if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (Some(true), Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, + span_lint(cx, + NEEDLESS_BOOL, + e.span, "this if-then-else expression will always return true"); } (Some(false), Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, + span_lint(cx, + NEEDLESS_BOOL, + e.span, "this if-then-else expression will always return false"); } (Some(true), Some(false)) => { let pred_snip = snippet(cx, pred.span, ".."); - let hint = if pred_snip == ".." { "its predicate".into() } else { + let hint = if pred_snip == ".." { + "its predicate".into() + } else { format!("`{}`", pred_snip) }; - span_lint(cx, NEEDLESS_BOOL, e.span, &format!( - "you can reduce this if-then-else expression to just {}", hint)); + span_lint(cx, + NEEDLESS_BOOL, + e.span, + &format!("you can reduce this if-then-else expression to just {}", hint)); } (Some(false), Some(true)) => { let pred_snip = snippet(cx, pred.span, ".."); - let hint = if pred_snip == ".." { "`!` and its predicate".into() } else { + let hint = if pred_snip == ".." { + "`!` and its predicate".into() + } else { format!("`!{}`", pred_snip) }; - span_lint(cx, NEEDLESS_BOOL, e.span, &format!( - "you can reduce this if-then-else expression to just {}", hint)); + span_lint(cx, + NEEDLESS_BOOL, + e.span, + &format!("you can reduce this if-then-else expression to just {}", hint)); } - _ => () + _ => (), } } } @@ -69,14 +81,21 @@ impl LateLintPass for NeedlessBool { fn fetch_bool_block(block: &Block) -> Option<bool> { if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) - } else { None } + } else { + None + } } fn fetch_bool_expr(expr: &Expr) -> Option<bool> { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), - ExprLit(ref lit_ptr) => if let LitBool(value) = lit_ptr.node { - Some(value) } else { None }, - _ => None + ExprLit(ref lit_ptr) => { + if let LitBool(value) = lit_ptr.node { + Some(value) + } else { + None + } + } + _ => None, } } diff --git a/src/needless_features.rs b/src/needless_features.rs index 2dd53c2d783..2c293d04600 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -49,14 +49,16 @@ impl LateLintPass for NeedlessFeaturesPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(ref name, _, _) = expr.node { if name.node.as_str() == "as_slice" && check_paths(cx, expr) { - span_lint(cx, UNSTABLE_AS_SLICE, expr.span, - "used as_slice() from the 'convert' nightly feature. Use &[..] \ - instead"); + span_lint(cx, + UNSTABLE_AS_SLICE, + expr.span, + "used as_slice() from the 'convert' nightly feature. Use &[..] instead"); } if name.node.as_str() == "as_mut_slice" && check_paths(cx, expr) { - span_lint(cx, UNSTABLE_AS_MUT_SLICE, expr.span, - "used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] \ - instead"); + span_lint(cx, + UNSTABLE_AS_MUT_SLICE, + expr.span, + "used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] instead"); } } } diff --git a/src/needless_update.rs b/src/needless_update.rs index 9a314616cdc..1b306df8eed 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -32,9 +32,10 @@ impl LateLintPass for NeedlessUpdatePass { let ty = cx.tcx.expr_ty(expr); if let TyStruct(def, _) = ty.sty { if fields.len() == def.struct_variant().fields.len() { - span_lint(cx, NEEDLESS_UPDATE, base.span, - "struct update has no effect, all the fields \ - in the struct have already been specified"); + span_lint(cx, + NEEDLESS_UPDATE, + base.span, + "struct update has no effect, all the fields in the struct have already been specified"); } } } diff --git a/src/no_effect.rs b/src/no_effect.rs index b51b4235d54..3b2d91fc78e 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -37,9 +37,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); match def { Some(DefStruct(..)) | - Some(DefVariant(..)) => { - args.iter().all(|arg| has_no_effect(cx, arg)) - } + Some(DefVariant(..)) => args.iter().all(|arg| has_no_effect(cx, arg)), _ => false, } } @@ -60,8 +58,7 @@ impl LateLintPass for NoEffectPass { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if has_no_effect(cx, expr) { - span_lint(cx, NO_EFFECT, stmt.span, - "statement with no effect"); + span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); } } } diff --git a/src/open_options.rs b/src/open_options.rs index 31ca0d72939..26784cb6008 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -31,7 +31,7 @@ impl LateLintPass for NonSensicalOpenOptions { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprMethodCall(ref name, _, ref arguments) = e.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); - if name.node.as_str() == "open" && match_type(cx, obj_ty, &OPEN_OPTIONS_PATH){ + if name.node.as_str() == "open" && match_type(cx, obj_ty, &OPEN_OPTIONS_PATH) { let mut options = Vec::new(); get_open_options(cx, &arguments[0], &mut options); check_open_options(cx, &options, e.span); @@ -44,7 +44,7 @@ impl LateLintPass for NonSensicalOpenOptions { enum Argument { True, False, - Unknown + Unknown, } #[derive(Debug)] @@ -53,31 +53,33 @@ enum OpenOption { Read, Truncate, Create, - Append + Append, } fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { if let ExprMethodCall(ref name, _, ref arguments) = argument.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); - + // Only proceed if this is a call on some object of type std::fs::OpenOptions if match_type(cx, obj_ty, &OPEN_OPTIONS_PATH) && arguments.len() >= 2 { - + let argument_option = match arguments[1].node { ExprLit(ref span) => { if let Spanned {node: LitBool(lit), ..} = **span { - if lit {Argument::True} else {Argument::False} + if lit { + Argument::True + } else { + Argument::False + } } else { return; // The function is called with a literal // which is not a boolean literal. This is theoretically // possible, but not very likely. } } - _ => { - Argument::Unknown - } + _ => Argument::Unknown, }; - + match &*name.node.as_str() { "create" => { options.push((OpenOption::Create, argument_option)); @@ -96,7 +98,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp } _ => {} } - + get_open_options(cx, &arguments[0], options); } } @@ -104,39 +106,124 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp fn check_for_duplicates(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. - if options.iter().filter(|o| if let (OpenOption::Create, _) = **o {true} else {false}).count() > 1 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"create\" \ - is called more than once"); + if options.iter() + .filter(|o| { + if let (OpenOption::Create, _) = **o { + true + } else { + false + } + }) + .count() > 1 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"create\" is called more than once"); } - if options.iter().filter(|o| if let (OpenOption::Append, _) = **o {true} else {false}).count() > 1 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"append\" \ - is called more than once"); + if options.iter() + .filter(|o| { + if let (OpenOption::Append, _) = **o { + true + } else { + false + } + }) + .count() > 1 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"append\" is called more than once"); } - if options.iter().filter(|o| if let (OpenOption::Truncate, _) = **o {true} else {false}).count() > 1 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"truncate\" \ - is called more than once"); + if options.iter() + .filter(|o| { + if let (OpenOption::Truncate, _) = **o { + true + } else { + false + } + }) + .count() > 1 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"truncate\" is called more than once"); } - if options.iter().filter(|o| if let (OpenOption::Read, _) = **o {true} else {false}).count() > 1 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"read\" \ - is called more than once"); + if options.iter() + .filter(|o| { + if let (OpenOption::Read, _) = **o { + true + } else { + false + } + }) + .count() > 1 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"read\" is called more than once"); } - if options.iter().filter(|o| if let (OpenOption::Write, _) = **o {true} else {false}).count() > 1 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "The method \"write\" \ - is called more than once"); + if options.iter() + .filter(|o| { + if let (OpenOption::Write, _) = **o { + true + } else { + false + } + }) + .count() > 1 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"write\" is called more than once"); } } fn check_for_inconsistencies(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { // Truncate + read makes no sense. - if options.iter().filter(|o| if let (OpenOption::Read, Argument::True) = **o {true} else {false}).count() > 0 && - options.iter().filter(|o| if let (OpenOption::Truncate, Argument::True) = **o {true} else {false}).count() > 0 { + if options.iter() + .filter(|o| { + if let (OpenOption::Read, Argument::True) = **o { + true + } else { + false + } + }) + .count() > 0 && + options.iter() + .filter(|o| { + if let (OpenOption::Truncate, Argument::True) = **o { + true + } else { + false + } + }) + .count() > 0 { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\""); } - + // Append + truncate makes no sense. - if options.iter().filter(|o| if let (OpenOption::Append, Argument::True) = **o {true} else {false}).count() > 0 && - options.iter().filter(|o| if let (OpenOption::Truncate, Argument::True) = **o {true} else {false}).count() > 0 { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"append\" and \"truncate\""); + if options.iter() + .filter(|o| { + if let (OpenOption::Append, Argument::True) = **o { + true + } else { + false + } + }) + .count() > 0 && + options.iter() + .filter(|o| { + if let (OpenOption::Truncate, Argument::True) = **o { + true + } else { + false + } + }) + .count() > 0 { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "File opened with \"append\" and \"truncate\""); } } diff --git a/src/precedence.rs b/src/precedence.rs index 91ff0680b3e..8253471f8b0 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -31,29 +31,40 @@ impl LintPass for Precedence { impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { - if !is_bit_op(op) { return; } + if !is_bit_op(op) { + return; + } match (is_arith_expr(left), is_arith_expr(right)) { (true, true) => { - span_lint(cx, PRECEDENCE, expr.span, - &format!("operator precedence can trip the unwary. \ - Consider parenthesizing your expression:\ - `({}) {} ({})`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))); - }, + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`({}) {} ({})`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } (true, false) => { - span_lint(cx, PRECEDENCE, expr.span, - &format!("operator precedence can trip the unwary. \ - Consider parenthesizing your expression:\ - `({}) {} {}`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))); - }, + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`({}) {} {}`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } (false, true) => { - span_lint(cx, PRECEDENCE, expr.span, - &format!("operator precedence can trip the unwary. \ - Consider parenthesizing your expression:\ - `{} {} ({})`", snippet(cx, left.span, ".."), - op.to_string(), snippet(cx, right.span, ".."))); - }, + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`{} {} ({})`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } _ => (), } } @@ -64,13 +75,14 @@ impl EarlyLintPass for Precedence { if let ExprLit(ref lit) = slf.node { match lit.node { LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => { - span_lint(cx, PRECEDENCE, expr.span, &format!( - "unary minus has lower precedence than \ - method call. Consider adding parentheses \ - to clarify your intent: -({})", - snippet(cx, rhs.span, ".."))); + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("unary minus has lower precedence than method call. Consider \ + adding parentheses to clarify your intent: -({})", + snippet(cx, rhs.span, ".."))); } - _ => () + _ => (), } } } @@ -82,20 +94,20 @@ impl EarlyLintPass for Precedence { fn is_arith_expr(expr: &Expr) -> bool { match expr.node { ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), - _ => false + _ => false, } } fn is_bit_op(op: BinOp_) -> bool { match op { BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, - _ => false + _ => false, } } fn is_arith_op(op: BinOp_) -> bool { match op { BiAdd | BiSub | BiMul | BiDiv | BiRem => true, - _ => false + _ => false, } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index f748dbd9cfa..2e1e16cf22b 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -63,14 +63,17 @@ fn check_fn(cx: &LateContext, decl: &FnDecl) { if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&arg.ty.id) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { if match_type(cx, ty, &VEC_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference \ - and cannot be used with non-Vec-based slices. Consider changing \ - the type to `&[...]`"); + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ + with non-Vec-based slices. Consider changing the type to `&[...]`"); } else if match_type(cx, ty, &STRING_PATH) { - span_lint(cx, PTR_ARG, arg.ty.span, - "writing `&String` instead of `&str` involves a new object \ - where a slice will do. Consider changing the type to `&str`"); + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&String` instead of `&str` involves a new object where a slice will do. \ + Consider changing the type to `&str`"); } } } diff --git a/src/ranges.rs b/src/ranges.rs index 48bbba734ff..692a5a2da1d 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -37,18 +37,15 @@ impl LintPass for StepByZero { impl LateLintPass for StepByZero { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(Spanned { node: ref name, .. }, _, - ref args) = expr.node { + if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { // Range with step_by(0). - if name.as_str() == "step_by" && args.len() == 2 && - is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { - cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, - "Range::step_by(0) produces an infinite iterator. \ - Consider using `std::iter::repeat()` instead") - } - - // x.iter().zip(0..x.len()) - else if name.as_str() == "zip" && args.len() == 2 { + if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && + is_integer_literal(&args[1], 0) { + cx.span_lint(RANGE_STEP_BY_ZERO, + expr.span, + "Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \ + instead") + } else if name.as_str() == "zip" && args.len() == 2 { let iter = &args[0].node; let zip_arg = &args[1].node; if_let_chain! { diff --git a/src/returns.rs b/src/returns.rs index 15f9bb80d95..e4745b8766f 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::ast::*; -//use reexport::*; +// use reexport::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; @@ -67,19 +67,17 @@ impl ReturnPass { self.check_final_expr(cx, &arm.body); } } - _ => { } + _ => {} } } fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { - if in_external_macro(cx, spans.1) {return;} - span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, - "unneeded return statement", - |db| { + if in_external_macro(cx, spans.1) { + return; + } + span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| { if let Some(snippet) = snippet_opt(cx, spans.1) { - db.span_suggestion(spans.0, - "remove `return` as shown:", - snippet); + db.span_suggestion(spans.0, "remove `return` as shown:", snippet); } }); } @@ -104,13 +102,16 @@ impl ReturnPass { } fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { - if in_external_macro(cx, note_span) {return;} - let mut db = span_lint(cx, LET_AND_RETURN, lint_span, - "returning the result of a let binding from a block. \ - Consider returning the expression directly."); + if in_external_macro(cx, note_span) { + return; + } + let mut db = span_lint(cx, + LET_AND_RETURN, + lint_span, + "returning the result of a let binding from a block. Consider returning the \ + expression directly."); if cx.current_level(LET_AND_RETURN) != Level::Allow { - db.span_note(note_span, - "this expression can be directly returned"); + db.span_note(note_span, "this expression can be directly returned"); } } } @@ -122,8 +123,7 @@ impl LintPass for ReturnPass { } impl EarlyLintPass for ReturnPass { - fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, - block: &Block, _: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { self.check_block_return(cx, block); } diff --git a/src/shadow.rs b/src/shadow.rs index 1210590bbcb..2d3e423eacb 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -45,13 +45,13 @@ impl LintPass for ShadowPass { fn get_lints(&self) -> LintArray { lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } - } impl LateLintPass for ShadowPass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, - block: &Block, _: Span, _: NodeId) { - if in_external_macro(cx, block.span) { return; } + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { + if in_external_macro(cx, block.span) { + return; + } check_fn(cx, decl, block); } } @@ -71,20 +71,27 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)> for stmt in &block.stmts { match stmt.node { StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | StmtSemi(ref e, _) => - check_expr(cx, e, bindings) + StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), } } - if let Some(ref o) = block.expr { check_expr(cx, o, bindings); } + if let Some(ref o) = block.expr { + check_expr(cx, o, bindings); + } bindings.truncate(len); } fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, decl.span) { return; } - if is_from_for_desugar(decl) { return; } + if in_external_macro(cx, decl.span) { + return; + } + if is_from_for_desugar(decl) { + return; + } if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, span, .. } = **local; - if let Some(ref t) = *ty { check_ty(cx, t, bindings) } + if let Some(ref t) = *ty { + check_ty(cx, t, bindings) + } if let Some(ref o) = *init { check_expr(cx, o, bindings); check_pat(cx, pat, &Some(o), span, bindings); @@ -97,13 +104,12 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { fn is_binding(cx: &LateContext, pat: &Pat) -> bool { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { Some(DefVariant(..)) | Some(DefStruct(..)) => false, - _ => true + _ => true, } } -fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, - bindings: &mut Vec<(Name, Span)>) { - //TODO: match more stuff / destructuring +fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { + // TODO: match more stuff / destructuring match pat.node { PatIdent(_, ref ident, ref inner) => { let name = ident.node.unhygienic_name; @@ -121,17 +127,19 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings.push((name, ident.span)); } } - if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } + if let Some(ref p) = *inner { + check_pat(cx, p, init, span, bindings); + } } - //PatEnum(Path, Option<Vec<P<Pat>>>), - PatStruct(_, ref pfields, _) => + // PatEnum(Path, Option<Vec<P<Pat>>>), + PatStruct(_, ref pfields, _) => { if let Some(ref init_struct) = *init { if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { let name = field.node.name; let efield = efields.iter() - .find(|ref f| f.name.node == name) - .map(|f| &*f.expr); + .find(|ref f| f.name.node == name) + .map(|f| &*f.expr); check_pat(cx, &field.node.pat, &efield, span, bindings); } } else { @@ -143,8 +151,9 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, for field in pfields { check_pat(cx, &field.node.pat, &None, span, bindings); } - }, - PatTup(ref inner) => + } + } + PatTup(ref inner) => { if let Some(ref init_tup) = *init { if let ExprTup(ref tup) = init_tup.node { for (i, p) in inner.iter().enumerate() { @@ -159,7 +168,8 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, for p in inner { check_pat(cx, p, &None, span, bindings); } - }, + } + } PatBox(ref inner) => { if let Some(ref initp) = *init { if let ExprBox(ref inner_init) = initp.node { @@ -171,15 +181,15 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, check_pat(cx, inner, init, span, bindings); } } - PatRegion(ref inner, _) => - check_pat(cx, inner, init, span, bindings), - //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), + PatRegion(ref inner, _) => check_pat(cx, inner, init, span, bindings), + // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), _ => (), } } -fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: - &Option<T>, prev_span: Span) where T: Deref<Target=Expr> { +fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: &Option<T>, prev_span: Span) + where T: Deref<Target = Expr> +{ fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { if cx.current_level(lint) != Level::Allow { db.span_note(span, "previous binding is here"); @@ -187,51 +197,69 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: } if let Some(ref expr) = *init { if is_self_shadow(name, expr) { - let db = span_lint(cx, SHADOW_SAME, span, &format!( - "{} is shadowed by itself in {}", - snippet(cx, lspan, "_"), - snippet(cx, expr.span, ".."))); - note_orig(cx, db, SHADOW_SAME, prev_span); + let db = span_lint(cx, + SHADOW_SAME, + span, + &format!("{} is shadowed by itself in {}", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, ".."))); + note_orig(cx, db, SHADOW_SAME, prev_span); } else { if contains_self(name, expr) { - let db = span_note_and_lint(cx, SHADOW_REUSE, lspan, &format!( - "{} is shadowed by {} which reuses the original value", - snippet(cx, lspan, "_"), - snippet(cx, expr.span, "..")), - expr.span, "initialization happens here"); + let db = span_note_and_lint(cx, + SHADOW_REUSE, + lspan, + &format!("{} is shadowed by {} which reuses the original value", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); note_orig(cx, db, SHADOW_REUSE, prev_span); } else { - let db = span_note_and_lint(cx, SHADOW_UNRELATED, lspan, &format!( - "{} is shadowed by {}", - snippet(cx, lspan, "_"), - snippet(cx, expr.span, "..")), - expr.span, "initialization happens here"); + let db = span_note_and_lint(cx, + SHADOW_UNRELATED, + lspan, + &format!("{} is shadowed by {}", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); note_orig(cx, db, SHADOW_UNRELATED, prev_span); } } } else { - let db = span_lint(cx, SHADOW_UNRELATED, span, &format!( - "{} shadows a previous declaration", snippet(cx, lspan, "_"))); + let db = span_lint(cx, + SHADOW_UNRELATED, + span, + &format!("{} shadows a previous declaration", snippet(cx, lspan, "_"))); note_orig(cx, db, SHADOW_UNRELATED, prev_span); } } fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, expr.span) { return; } + if in_external_macro(cx, expr.span) { + return; + } match expr.node { - ExprUnary(_, ref e) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) - => { check_expr(cx, e, bindings) } - ExprBlock(ref block) | ExprLoop(ref block, _) => - { check_block(cx, block, bindings) } - //ExprCall - //ExprMethodCall - ExprVec(ref v) | ExprTup(ref v) => - for ref e in v { check_expr(cx, e, bindings) }, + ExprUnary(_, ref e) | + ExprField(ref e, _) | + ExprTupField(ref e, _) | + ExprAddrOf(_, ref e) | + ExprBox(ref e) => check_expr(cx, e, bindings), + ExprBlock(ref block) | ExprLoop(ref block, _) => check_block(cx, block, bindings), + // ExprCall + // ExprMethodCall + ExprVec(ref v) | ExprTup(ref v) => { + for ref e in v { + check_expr(cx, e, bindings) + } + } ExprIf(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); check_block(cx, then, bindings); - if let Some(ref o) = *otherwise { check_expr(cx, o, bindings); } + if let Some(ref o) = *otherwise { + check_expr(cx, o, bindings); + } } ExprWhile(ref cond, ref block, _) => { check_expr(cx, cond, bindings); @@ -243,7 +271,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { for ref arm in arms { for ref pat in &arm.pats { check_pat(cx, &pat, &Some(&**init), pat.span, bindings); - //This is ugly, but needed to get the right type + // This is ugly, but needed to get the right type if let Some(ref guard) = arm.guard { check_expr(cx, guard, bindings); } @@ -252,7 +280,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { } } } - _ => () + _ => (), } } @@ -266,7 +294,11 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { } TyPtr(MutTy{ ty: ref mty, .. }) | TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } } + TyTup(ref tup) => { + for ref t in tup { + check_ty(cx, t, bindings) + } + } TyTypeof(ref expr) => check_expr(cx, expr, bindings), _ => (), } @@ -276,23 +308,22 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), - ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref(). - map_or(false, |ref e| is_self_shadow(name, e)), - ExprUnary(op, ref inner) => (UnDeref == op) && - is_self_shadow(name, inner), + ExprBlock(ref block) => { + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |ref e| is_self_shadow(name, e)) + } + ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprPath(_, ref path) => path_eq_name(name, path), _ => false, } } fn path_eq_name(name: Name, path: &Path) -> bool { - !path.global && path.segments.len() == 1 && - path.segments[0].identifier.unhygienic_name == name + !path.global && path.segments.len() == 1 && path.segments[0].identifier.unhygienic_name == name } struct ContainsSelf { name: Name, - result: bool + result: bool, } impl<'v> Visitor<'v> for ContainsSelf { @@ -304,7 +335,10 @@ impl<'v> Visitor<'v> for ContainsSelf { } fn contains_self(name: Name, expr: &Expr) -> bool { - let mut cs = ContainsSelf { name: name, result: false }; + let mut cs = ContainsSelf { + name: name, + result: false, + }; cs.visit_expr(expr); cs.result } diff --git a/src/strings.rs b/src/strings.rs index 2baf26095b7..55d1a0acf68 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -68,19 +68,24 @@ impl LateLintPass for StringAdd { if let Some(ref p) = parent { if let ExprAssign(ref target, _) = p.node { // avoid duplicate matches - if is_exp_equal(cx, target, left) { return; } + if is_exp_equal(cx, target, left) { + return; + } } } } - span_lint(cx, STRING_ADD, e.span, - "you added something to a string. \ - Consider using `String::push_str()` instead"); + span_lint(cx, + STRING_ADD, + e.span, + "you added something to a string. Consider using `String::push_str()` instead"); } } else if let ExprAssign(ref target, ref src) = e.node { if is_string(cx, target) && is_add(cx, src, target) { - span_lint(cx, STRING_ADD_ASSIGN, e.span, - "you assigned the result of adding something to this string. \ - Consider using `String::push_str()` instead"); + span_lint(cx, + STRING_ADD_ASSIGN, + e.span, + "you assigned the result of adding something to this string. Consider using \ + `String::push_str()` instead"); } } } @@ -92,11 +97,10 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => - is_exp_equal(cx, target, left), - ExprBlock(ref block) => block.stmts.is_empty() && - block.expr.as_ref().map_or(false, - |expr| is_add(cx, expr, target)), - _ => false + ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left), + ExprBlock(ref block) => { + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) + } + _ => false, } } diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index 622bf5bc25e..7d5057d8377 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -40,11 +40,10 @@ impl LateLintPass for TemporaryAssignmentPass { match target.node { ExprField(ref base, _) | ExprTupField(ref base, _) => { if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, - "assignment to temporary"); + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); } } - _ => () + _ => (), } } } diff --git a/src/transmute.rs b/src/transmute.rs index c71468bf5a0..24af45bc68d 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -34,7 +34,8 @@ impl LateLintPass for UselessTransmute { let to_ty = cx.tcx.expr_ty(e); if from_ty == to_ty { - cx.span_lint(USELESS_TRANSMUTE, e.span, + cx.span_lint(USELESS_TRANSMUTE, + e.span, &format!("transmute from a type (`{}`) to itself", from_ty)); } } diff --git a/src/types.rs b/src/types.rs index e119ef63436..6289e13c85a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -49,22 +49,23 @@ impl LintPass for TypePass { impl LateLintPass for TypePass { fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) { if in_macro(cx, ast_ty.span) { - return + return; } if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { if let ty::TyBox(ref inner) = ty.sty { if match_type(cx, inner, &VEC_PATH) { - span_help_and_lint( - cx, BOX_VEC, ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); + span_help_and_lint(cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); } - } - else if match_type(cx, ty, &LL_PATH) { - span_help_and_lint( - cx, LINKEDLIST, ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a VecDeque might work"); + } else if match_type(cx, ty, &LL_PATH) { + span_help_and_lint(cx, + LINKEDLIST, + ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a VecDeque might work"); } } } @@ -87,12 +88,17 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { - if in_external_macro(cx, decl.span) || - in_macro(cx, local.pat.span) { return; } - if is_from_for_desugar(decl) { return; } - span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( - "this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, ".."))); + if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { + return; + } + if is_from_for_desugar(decl) { + return; + } + span_lint(cx, + LET_UNIT_VALUE, + decl.span, + &format!("this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, ".."))); } } } @@ -130,18 +136,23 @@ impl LintPass for UnitCmp { impl LateLintPass for UnitCmp { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_macro(cx, expr.span) { return; } + if in_macro(cx, expr.span) { + return; + } if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; let sty = &cx.tcx.expr_ty(left).sty; if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) { let result = match op { BiEq | BiLe | BiGe => "true", - _ => "false" + _ => "false", }; - span_lint(cx, UNIT_CMP, expr.span, &format!( - "{}-comparison of unit values detected. This will always be {}", - binop_to_string(op), result)); + span_lint(cx, + UNIT_CMP, + expr.span, + &format!("{}-comparison of unit values detected. This will always be {}", + binop_to_string(op), + result)); } } } @@ -192,38 +203,64 @@ declare_lint!(pub CAST_POSSIBLE_WRAP, Allow, /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: &ty::TyS) -> usize { let n = match typ.sty { - ty::TyInt(i) => 4 << (i as usize), + ty::TyInt(i) => 4 << (i as usize), ty::TyUint(u) => 4 << (u as usize), - _ => 0 + _ => 0, }; // n == 4 is the usize/isize case - if n == 4 { ::std::usize::BITS } else { n } + if n == 4 { + ::std::usize::BITS + } else { + n + } } fn is_isize_or_usize(typ: &ty::TyS) -> bool { match typ.sty { ty::TyInt(TyIs) | ty::TyUint(TyUs) => true, - _ => false + _ => false, } } fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { - let mantissa_nbits = if cast_to_f64 {52} else {23}; + let mantissa_nbits = if cast_to_f64 { + 52 + } else { + 23 + }; let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; let arch_dependent_str = "on targets with 64-bit wide pointers "; - let from_nbits_str = if arch_dependent {"64".to_owned()} - else if is_isize_or_usize(cast_from) {"32 or 64".to_owned()} - else {int_ty_to_nbits(cast_from).to_string()}; - span_lint(cx, CAST_PRECISION_LOSS, expr.span, - &format!("casting {0} to {1} causes a loss of precision {2}\ - ({0} is {3} bits wide, but {1}'s mantissa is only {4} bits wide)", - cast_from, if cast_to_f64 {"f64"} else {"f32"}, - if arch_dependent {arch_dependent_str} else {""}, - from_nbits_str, mantissa_nbits)); + let from_nbits_str = if arch_dependent { + "64".to_owned() + } else if is_isize_or_usize(cast_from) { + "32 or 64".to_owned() + } else { + int_ty_to_nbits(cast_from).to_string() + }; + span_lint(cx, + CAST_PRECISION_LOSS, + expr.span, + &format!("casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ + is only {4} bits wide)", + cast_from, + if cast_to_f64 { + "f64" + } else { + "f32" + }, + if arch_dependent { + arch_dependent_str + } else { + "" + }, + from_nbits_str, + mantissa_nbits)); } enum ArchSuffix { - _32, _64, None + _32, + _64, + None, } fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { @@ -231,44 +268,60 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty:: let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); - let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = - match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => ( - to_nbits < from_nbits, - ArchSuffix::None, - to_nbits == from_nbits && cast_unsigned_to_signed, + let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), + is_isize_or_usize(cast_to)) { + (true, true) | (false, false) => { + (to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None) + } + (true, false) => { + (to_nbits <= 32, + if to_nbits == 32 { + ArchSuffix::_64 + } else { ArchSuffix::None - ), - (true, false) => ( - to_nbits <= 32, - if to_nbits == 32 {ArchSuffix::_64} else {ArchSuffix::None}, - to_nbits <= 32 && cast_unsigned_to_signed, + }, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32) + } + (false, true) => { + (from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 { + ArchSuffix::_64 + } else { ArchSuffix::_32 - ), - (false, true) => ( - from_nbits == 64, - ArchSuffix::_32, - cast_unsigned_to_signed, - if from_nbits == 64 {ArchSuffix::_64} else {ArchSuffix::_32} - ), - }; + }) + } + }; if span_truncation { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value{}", - cast_from, cast_to, - match suffix_truncation { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "" })); + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!("casting {} to {} may truncate the value{}", + cast_from, + cast_to, + match suffix_truncation { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + })); } if span_wrap { - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, - &format!("casting {} to {} may wrap around the value{}", - cast_from, cast_to, - match suffix_wrap { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "" })); + span_lint(cx, + CAST_POSSIBLE_WRAP, + expr.span, + &format!("casting {} to {} may wrap around the value{}", + cast_from, + cast_to, + match suffix_wrap { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + })); } } @@ -289,35 +342,42 @@ impl LateLintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = if let ty::TyFloat(TyF32) = cast_to.sty {32} else {64}; + let to_nbits = if let ty::TyFloat(TyF32) = cast_to.sty { + 32 + } else { + 64 + }; if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); } } (false, true) => { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, - &format!("casting {} to {} may truncate the value", - cast_from, cast_to)); + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!("casting {} to {} may truncate the value", cast_from, cast_to)); if !cast_to.is_signed() { - span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting {} to {} may lose the sign of the value", - cast_from, cast_to)); + span_lint(cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } } (true, true) => { if cast_from.is_signed() && !cast_to.is_signed() { - span_lint(cx, CAST_SIGN_LOSS, expr.span, - &format!("casting {} to {} may lose the sign of the value", - cast_from, cast_to)); + span_lint(cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); } check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { - if let (&ty::TyFloat(TyF64), - &ty::TyFloat(TyF32)) = (&cast_from.sty, &cast_to.sty) { - span_lint(cx, CAST_POSSIBLE_TRUNCATION, - expr.span, - "casting f64 to f32 may truncate the value"); + if let (&ty::TyFloat(TyF64), &ty::TyFloat(TyF32)) = (&cast_from.sty, &cast_to.sty) { + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + "casting f64 to f32 may truncate the value"); } } } @@ -360,7 +420,7 @@ impl LateLintPass for TypeComplexityPass { ItemStatic(ref ty, _, _) | ItemConst(ref ty, _) => check_type(cx, ty), // functions, enums, structs, impls and traits are covered - _ => () + _ => (), } } @@ -370,7 +430,7 @@ impl LateLintPass for TypeComplexityPass { TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty), MethodTraitItem(MethodSig { ref decl, .. }, None) => check_fndecl(cx, decl), // methods with default impl are covered by check_fn - _ => () + _ => (), } } @@ -379,7 +439,7 @@ impl LateLintPass for TypeComplexityPass { ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => check_type(cx, ty), // methods are covered by check_fn - _ => () + _ => (), } } @@ -400,16 +460,23 @@ fn check_fndecl(cx: &LateContext, decl: &FnDecl) { } fn check_type(cx: &LateContext, ty: &Ty) { - if in_macro(cx, ty.span) { return; } + if in_macro(cx, ty.span) { + return; + } let score = { - let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; + let mut visitor = TypeComplexityVisitor { + score: 0, + nest: 1, + }; visitor.visit_ty(ty); visitor.score }; // println!("{:?} --> {}", ty, score); if score > 250 { - span_lint(cx, TYPE_COMPLEXITY, ty.span, &format!( - "very complex type used. Consider factoring parts into `type` definitions")); + span_lint(cx, + TYPE_COMPLEXITY, + ty.span, + &format!("very complex type used. Consider factoring parts into `type` definitions")); } } @@ -442,7 +509,7 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { TyBareFn(..) | TyPolyTraitRef(..) => (50 * self.nest, 1), - _ => (0, 0) + _ => (0, 0), }; self.score += add_score; self.nest += sub_nest; diff --git a/src/unicode.rs b/src/unicode.rs index a5b03087604..d5ea7199e10 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -58,11 +58,13 @@ impl LateLintPass for Unicode { } } -fn escape<T: Iterator<Item=char>>(s: T) -> String { +fn escape<T: Iterator<Item = char>>(s: T) -> String { let mut result = String::new(); for c in s { if c as u32 > 0x7F { - for d in c.escape_unicode() { result.push(d) }; + for d in c.escape_unicode() { + result.push(d) + } } else { result.push(c); } @@ -73,26 +75,30 @@ fn escape<T: Iterator<Item=char>>(s: T) -> String { fn check_str(cx: &LateContext, span: Span) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { - span_help_and_lint(cx, ZERO_WIDTH_SPACE, span, - "zero-width space detected", - &format!("Consider replacing the string with:\n\"{}\"", - string.replace("\u{200B}", "\\u{200B}"))); + span_help_and_lint(cx, + ZERO_WIDTH_SPACE, + span, + "zero-width space detected", + &format!("Consider replacing the string with:\n\"{}\"", + string.replace("\u{200B}", "\\u{200B}"))); } if string.chars().any(|c| c as u32 > 0x7F) { - span_help_and_lint(cx, NON_ASCII_LITERAL, span, - "literal non-ASCII character detected", - &format!("Consider replacing the string with:\n\"{}\"", - if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { - escape(string.chars()) - } else { - escape(string.nfc()) - })); + span_help_and_lint(cx, + NON_ASCII_LITERAL, + span, + "literal non-ASCII character detected", + &format!("Consider replacing the string with:\n\"{}\"", + if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { + escape(string.chars()) + } else { + escape(string.nfc()) + })); } - if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && - string.chars().zip(string.nfc()).any(|(a, b)| a != b) { - span_help_and_lint(cx, UNICODE_NOT_NFC, span, - "non-nfc unicode sequence detected", - &format!("Consider replacing the string with:\n\"{}\"", - string.nfc().collect::<String>())); + if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { + span_help_and_lint(cx, + UNICODE_NOT_NFC, + span, + "non-nfc unicode sequence detected", + &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::<String>())); } } diff --git a/src/utils.rs b/src/utils.rs index 1b6c75a3b78..74a15927ad1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,15 +19,15 @@ use std::ops::{Deref, DerefMut}; pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for -pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; -pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; +pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; /// Produce a nested chain of if-lets and ifs from the patterns: @@ -82,8 +82,7 @@ pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { } /// returns true if this expn_info was expanded by any macro pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, - |info| info.is_some()) + cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) } /// returns true if the macro that expanded the crate was outside of @@ -95,42 +94,35 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { if let ExpnFormat::MacroAttribute(..) = info.callee.format { - // these are all plugins - return true; + // these are all plugins + return true; } // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| - // macro doesn't start with "macro_rules" - // = compiler plugin - !code.starts_with("macro_rules") - ) + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) }) }) } - cx.sess().codemap().with_expn_info(span.expn_id, - |info| in_macro_ext(cx, info)) + cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) } /// check if a DefId's path matches the given absolute type path /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| iter.zip(path) - .all(|(nm, p)| nm.name().as_str() == *p)) + cx.tcx.with_path(def_id, |iter| { + iter.zip(path) + .all(|(nm, p)| nm.name().as_str() == *p) + }) } /// check if type is struct or enum type with given def path pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { match ty.sty { - ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => { - match_def_path(cx, adt.did, path) - } - _ => { - false - } + ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), + _ => false, } } @@ -138,9 +130,12 @@ pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); - let trt_id = cx.tcx.tables - .borrow().method_map.get(&method_call) - .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); if let Some(trt_id) = trt_id { match_def_path(cx, trt_id, path) } else { @@ -151,9 +146,12 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { /// check if method call given in "expr" belongs to given trait pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); - let trt_id = cx.tcx.tables - .borrow().method_map.get(&method_call) - .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); if let Some(trt_id) = trt_id { match_def_path(cx, trt_id, path) } else { @@ -164,15 +162,13 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.identifier.name.as_str() == *b) + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) } /// match a Path against a slice of segment string literals, e.g. /// `match_path(path, &["std", "rt", "begin_unwind"])` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.identifier.name.as_str() == *b) + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) } /// match an Expr against a chain of methods, and return the matched Exprs. For example, if `expr` @@ -181,17 +177,16 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { let mut current = expr; let mut matched = Vec::with_capacity(methods.len()); - for method_name in methods.iter().rev() { // method chains are stored last -> first + for method_name in methods.iter().rev() { + // method chains are stored last -> first if let ExprMethodCall(ref name, _, ref args) = current.node { if name.node.as_str() == *method_name { matched.push(args); // build up `matched` backwards current = &args[0] // go to parent expression - } - else { + } else { return None; } - } - else { + } else { return None; } } @@ -206,9 +201,7 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { match cx.tcx.map.find(parent_id) { Some(NodeItem(&Item{ ref name, .. })) | Some(NodeTraitItem(&TraitItem{ ref name, .. })) | - Some(NodeImplItem(&ImplItem{ ref name, .. })) => { - Some(*name) - } + Some(NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), _ => None, } } @@ -249,9 +242,7 @@ pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) - /// Like snippet_block, but add braces if the expr is not an ExprBlock /// Also takes an Option<String> which can be put inside the braces -pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, - option: Option<String>, - default: &'a str) -> Cow<'a, str> { +pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); let string = option.map_or("".to_owned(), |s| s); if let ExprBlock(_) = expr.node { @@ -272,21 +263,33 @@ pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { } fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { - let x = s.lines().skip(ignore_first as usize) - .filter_map(|l| { if l.len() > 0 { // ignore empty lines - Some(l.char_indices() - .find(|&(_,x)| x != ch) - .unwrap_or((l.len(), ch)).0) - } else {None}}) - .min().unwrap_or(0); + let x = s.lines() + .skip(ignore_first as usize) + .filter_map(|l| { + if l.len() > 0 { + // ignore empty lines + Some(l.char_indices() + .find(|&(_, x)| x != ch) + .unwrap_or((l.len(), ch)) + .0) + } else { + None + } + }) + .min() + .unwrap_or(0); if x > 0 { - Cow::Owned(s.lines().enumerate().map(|(i,l)| if (ignore_first && i == 0) || - l.len() == 0 { - l - } else { - l.split_at(x).1 - }).collect::<Vec<_>>() - .join("\n")) + Cow::Owned(s.lines() + .enumerate() + .map(|(i, l)| { + if (ignore_first && i == 0) || l.len() == 0 { + l + } else { + l.split_at(x).1 + } + }) + .collect::<Vec<_>>() + .join("\n")) } else { s } @@ -295,11 +298,18 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { /// get a parent expr if any – this is useful to constrain a lint pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { let map = &cx.tcx.map; - let node_id : NodeId = e.id; - let parent_id : NodeId = map.get_parent_node(node_id); - if node_id == parent_id { return None; } - map.find(parent_id).and_then(|node| - if let NodeExpr(parent) = node { Some(parent) } else { None } ) + let node_id: NodeId = e.id; + let parent_id: NodeId = map.get_parent_node(node_id); + if node_id == parent_id { + return None; + } + map.find(parent_id).and_then(|node| { + if let NodeExpr(parent) = node { + Some(parent) + } else { + None + } + }) } pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { @@ -310,9 +320,11 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c match node { NodeBlock(ref block) => Some(block), NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), - _ => None + _ => None, } - } else { None } + } else { + None + } } pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); @@ -326,56 +338,57 @@ impl<'a> Drop for DiagnosticWrapper<'a> { impl<'a> DerefMut for DiagnosticWrapper<'a> { fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { &mut self.0 - } + } } impl<'a> Deref for DiagnosticWrapper<'a> { type Target = DiagnosticBuilder<'a>; fn deref(&self) -> &DiagnosticBuilder<'a> { &self.0 - } + } } #[cfg(not(feature="structured_logging"))] -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, - sp: Span, msg: &str) -> DiagnosticWrapper<'a> { +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { let mut db = cx.struct_span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { - db.fileline_help(sp, &format!("for further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.fileline_help(sp, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); } DiagnosticWrapper(db) } #[cfg(feature="structured_logging")] -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, - sp: Span, msg: &str) -> DiagnosticWrapper<'a> { +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { // lint.name / lint.desc is can give details of the lint // cx.sess().codemap() has all these nice functions for line/column/snippet details // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string let mut db = cx.struct_span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { - db.fileline_help(sp, &format!("for further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.fileline_help(sp, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); } DiagnosticWrapper(db) } -pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, - msg: &str, help: &str) -> DiagnosticWrapper<'a> { +pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) + -> DiagnosticWrapper<'a> { let mut db = cx.struct_span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { - db.fileline_help(span, &format!("{}\nfor further information \ - visit https://github.com/Manishearth/rust-clippy/wiki#{}", - help, lint.name_lower())); + db.fileline_help(span, + &format!("{}\nfor further information visit \ + https://github.com/Manishearth/rust-clippy/wiki#{}", + help, + lint.name_lower())); } DiagnosticWrapper(db) } -pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, - msg: &str, note_span: Span, note: &str) -> DiagnosticWrapper<'a> { +pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, + note: &str) + -> DiagnosticWrapper<'a> { let mut db = cx.struct_span_lint(lint, span, msg); if cx.current_level(lint) != Level::Allow { if note_span == span { @@ -383,21 +396,23 @@ pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp } else { db.span_note(note_span, note); } - db.fileline_help(span, &format!("for further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.fileline_help(span, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); } DiagnosticWrapper(db) } -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, - msg: &str, f: F) -> DiagnosticWrapper<'a> where F: Fn(&mut DiagnosticWrapper) { +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) + -> DiagnosticWrapper<'a> + where F: Fn(&mut DiagnosticWrapper) +{ let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { f(&mut db); - db.fileline_help(sp, &format!("for further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.fileline_help(sp, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); } db } @@ -406,7 +421,7 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), - _ => ty + _ => ty, } } @@ -415,14 +430,13 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { match ty.sty { ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), - _ => (ty, depth) + _ => (ty, depth), } } inner(ty, 0) } -pub fn is_integer_literal(expr: &Expr, value: u64) -> bool -{ +pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { // FIXME: use constant folding if let ExprLit(ref spanned) = expr.node { if let LitInt(v, _) = spanned.node { @@ -448,37 +462,27 @@ impl Drop for LimitStack { impl LimitStack { pub fn new(limit: u64) -> LimitStack { - LimitStack { - stack: vec![limit], - } + LimitStack { stack: vec![limit] } } pub fn limit(&self) -> u64 { *self.stack.last().expect("there should always be a value in the stack") } pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; - parse_attrs( - sess, - attrs, - name, - |val| stack.push(val), - ); + parse_attrs(sess, attrs, name, |val| stack.push(val)); } pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; - parse_attrs( - sess, - attrs, - name, - |val| assert_eq!(stack.pop(), Some(val)), - ); + parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); } } fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { for attr in attrs { let attr = &attr.node; - if attr.is_sugared_doc { continue; } + if attr.is_sugared_doc { + continue; + } if let ast::MetaNameValue(ref key, ref value) = attr.value.node { if *key == name { if let LitStr(ref s, _) = value.node { @@ -495,70 +499,67 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } } -pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool { +pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr) -> bool { if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { if l == r { return true; } } match (&left.node, &right.node) { - (&ExprField(ref lfexp, ref lfident), - &ExprField(ref rfexp, ref rfident)) => - lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), + (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { + lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp) + } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprPath(ref lqself, ref lsubpath), - &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, is_qself_equal) && - is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => - is_exps_equal(cx, ltup, rtup), + (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { + both(lqself, rqself, is_qself_equal) && is_path_equal(lsubpath, rsubpath) + } + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup), (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => - is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), - _ => false + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), + _ => false, } } -fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool { +fn is_exps_equal(cx: &LateContext, left: &[P<Expr>], right: &[P<Expr>]) -> bool { over(left, right, |l, r| is_exp_equal(cx, l, r)) } -fn is_path_equal(left : &Path, right : &Path) -> bool { +fn is_path_equal(left: &Path, right: &Path) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene - left.global == right.global && over(&left.segments, &right.segments, - |l, r| l.identifier.name == r.identifier.name - && l.parameters == r.parameters) + left.global == right.global && + over(&left.segments, + &right.segments, + |l, r| l.identifier.name == r.identifier.name && l.parameters == r.parameters) } -fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { +fn is_qself_equal(left: &QSelf, right: &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool { - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| - eq_fn(x, y)) + where F: FnMut(&X, &X) -> bool +{ + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool - where F: FnMut(&X, &X) -> bool { - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, - |y| eq_fn(x, y))) +fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool +{ + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) } fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { (&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => - lmut.mutbl == rmut.mutbl && - is_cast_ty_equal(&*lmut.ty, &*rmut.ty), - (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => - lrmut.mutbl == rrmut.mutbl && - is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => - both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => lmut.mutbl == rmut.mutbl && is_cast_ty_equal(&*lmut.ty, &*rmut.ty), + (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => { + lrmut.mutbl == rrmut.mutbl && is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty) + } + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => { + both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath) + } (&TyInfer, &TyInfer) => true, - _ => false + _ => false, } } -- cgit 1.4.1-3-g733a5 From c1a99fdd90df92d5cb9a1b5b5f6ee66aad627766 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 4 Jan 2016 10:13:56 +0530 Subject: Fix dogfood failures by refactoring open_options --- src/lib.rs | 9 +-- src/open_options.rs | 186 +++++++++++++++++++--------------------------------- 2 files changed, 74 insertions(+), 121 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2ac8e9044db..8227be92543 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] #![feature(num_bits_bytes, iter_arith)] +#![feature(custom_attribute)] #![allow(unknown_lints)] // this only exists to allow the "dogfood" integration test to work @@ -77,6 +78,7 @@ mod reexport { } #[plugin_registrar] +#[rustfmt_skip] pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box misc::TopLevelRefPass); @@ -130,8 +132,8 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box array_indexing::ArrayIndexing); reg.register_late_lint_pass(box panic::PanicPass); - reg.register_lint_group("clippy_pedantic", - vec![ + + reg.register_lint_group("clippy_pedantic", vec![ methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, @@ -150,8 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) { unicode::UNICODE_NOT_NFC, ]); - reg.register_lint_group("clippy", - vec![ + reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, array_indexing::OUT_OF_BOUNDS_INDEXING, attrs::INLINE_ALWAYS, diff --git a/src/open_options.rs b/src/open_options.rs index 26784cb6008..541ed2444f4 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -40,7 +40,7 @@ impl LateLintPass for NonSensicalOpenOptions { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] enum Argument { True, False, @@ -104,130 +104,82 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp } } -fn check_for_duplicates(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { +fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { + let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); + let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, + false, + false, + false, + false); // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. - if options.iter() - .filter(|o| { - if let (OpenOption::Create, _) = **o { - true - } else { - false - } - }) - .count() > 1 { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "The method \"create\" is called more than once"); - } - if options.iter() - .filter(|o| { - if let (OpenOption::Append, _) = **o { - true - } else { - false - } - }) - .count() > 1 { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "The method \"append\" is called more than once"); - } - if options.iter() - .filter(|o| { - if let (OpenOption::Truncate, _) = **o { - true - } else { - false - } - }) - .count() > 1 { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "The method \"truncate\" is called more than once"); - } - if options.iter() - .filter(|o| { - if let (OpenOption::Read, _) = **o { - true - } else { - false - } - }) - .count() > 1 { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "The method \"read\" is called more than once"); - } - if options.iter() - .filter(|o| { - if let (OpenOption::Write, _) = **o { - true - } else { - false - } - }) - .count() > 1 { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "The method \"write\" is called more than once"); + + for option in options { + match *option { + (OpenOption::Create, arg) => { + if create { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"create\" is called more than once"); + } else { + create = true + } + create_arg = create_arg || (arg == Argument::True);; + } + (OpenOption::Append, arg) => { + if append { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"append\" is called more than once"); + } else { + append = true + } + append_arg = append_arg || (arg == Argument::True);; + } + (OpenOption::Truncate, arg) => { + if truncate { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"truncate\" is called more than once"); + } else { + truncate = true + } + truncate_arg = truncate_arg || (arg == Argument::True); + } + (OpenOption::Read, arg) => { + if read { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"read\" is called more than once"); + } else { + read = true + } + read_arg = read_arg || (arg == Argument::True);; + } + (OpenOption::Write, arg) => { + if write { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "The method \"write\" is called more than once"); + } else { + write = true + } + write_arg = write_arg || (arg == Argument::True);; + } + } } -} -fn check_for_inconsistencies(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { - // Truncate + read makes no sense. - if options.iter() - .filter(|o| { - if let (OpenOption::Read, Argument::True) = **o { - true - } else { - false - } - }) - .count() > 0 && - options.iter() - .filter(|o| { - if let (OpenOption::Truncate, Argument::True) = **o { - true - } else { - false - } - }) - .count() > 0 { + if read && truncate && read_arg && truncate_arg { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\""); } - - // Append + truncate makes no sense. - if options.iter() - .filter(|o| { - if let (OpenOption::Append, Argument::True) = **o { - true - } else { - false - } - }) - .count() > 0 && - options.iter() - .filter(|o| { - if let (OpenOption::Truncate, Argument::True) = **o { - true - } else { - false - } - }) - .count() > 0 { + if append && truncate && append_arg && truncate_arg { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"append\" and \"truncate\""); } } - -fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { - check_for_duplicates(cx, options, span); - check_for_inconsistencies(cx, options, span); -} -- cgit 1.4.1-3-g733a5 From 002c8c34f8be15c35e2fc8fd640a250f5227d95b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 4 Jan 2016 20:01:08 +0530 Subject: re-add missing comments --- src/misc.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 1b7f2a921b9..4cee123909b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -365,9 +365,10 @@ impl LintPass for UsedUnderscoreBinding { } impl LateLintPass for UsedUnderscoreBinding { + #[rustfmt_skip] fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_attributes_expansion(cx, expr) { - // Don't lint things expanded by #[derive(...)], etc + // Don't lint things expanded by #[derive(...)], etc return; } let needs_lint = match expr.node { @@ -376,9 +377,9 @@ impl LateLintPass for UsedUnderscoreBinding { .last() .expect("path should always have at least one segment") .identifier; - ident.name.as_str().chars().next() == Some('_') && - ident.name.as_str().chars().skip(1).next() != Some('_') && - ident.name != ident.unhygienic_name && is_used(cx, expr) + ident.name.as_str().chars().next() == Some('_') && // starts with '_' + ident.name.as_str().chars().skip(1).next() != Some('_') && // doesn't start with "__" + ident.name != ident.unhygienic_name && is_used(cx, expr) // not in bang macro } ExprField(_, spanned) => { let name = spanned.node.as_str(); -- cgit 1.4.1-3-g733a5 From f27cfdb51a50c92031f3432ed98eb0ba54cb740e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 7 Jan 2016 12:06:16 +0530 Subject: Fix warnings for unused attributes --- src/lib.rs | 1 + src/misc.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 8227be92543..45f47fe3d63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,6 +77,7 @@ mod reexport { pub use syntax::ast::{Name, NodeId}; } +#[allow(unused_attributes)] #[plugin_registrar] #[rustfmt_skip] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/misc.rs b/src/misc.rs index 4cee123909b..a8fabaa3fcf 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -365,6 +365,7 @@ impl LintPass for UsedUnderscoreBinding { } impl LateLintPass for UsedUnderscoreBinding { + #[allow(unused_attributes)] #[rustfmt_skip] fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_attributes_expansion(cx, expr) { -- cgit 1.4.1-3-g733a5 From a21108a2963c63310d9c5b452e7faf3e622c47de Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 8 Jan 2016 21:21:12 +0530 Subject: Stronger macro check --- src/block_in_if_condition.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index f7d8c95ee76..53f11366cae 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -80,7 +80,7 @@ impl LateLintPass for BlockInIfCondition { if let Some(ref ex) = block.expr { // don't dig into the expression here, just suggest that they remove // the block - if differing_macro_contexts(expr.span, ex.span) { + if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, ex.span) { return; } span_help_and_lint(cx, @@ -92,7 +92,7 @@ impl LateLintPass for BlockInIfCondition { snippet_block(cx, then.span, ".."))); } } else { - if differing_macro_contexts(expr.span, block.stmts[0].span) { + if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, block.stmts[0].span) { return; } // move block higher -- cgit 1.4.1-3-g733a5 From 37707b5a34752e950ee09e9d0e5effb1f481fff1 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sat, 9 Jan 2016 02:05:43 +0100 Subject: added semver lint --- Cargo.toml | 1 + README.md | 3 ++- src/attrs.rs | 45 +++++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 4 ++++ tests/compile-fail/attrs.rs | 12 ++++++++++-- 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b203e8b796..792326d6c1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ plugin = true [dependencies] unicode-normalization = "0.1" +semver = "0.2.1" [dev-dependencies] compiletest_rs = "0.0.11" diff --git a/README.md b/README.md index f1c28888636..13105087706 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 91 lints included in this crate: +There are 92 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -24,6 +24,7 @@ name [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions +[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) diff --git a/src/attrs.rs b/src/attrs.rs index ec2cfcb0efc..853e2ab5910 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -3,9 +3,10 @@ use rustc::lint::*; use rustc_front::hir::*; use reexport::*; +use semver::Version; use syntax::codemap::Span; use syntax::attr::*; -use syntax::ast::{Attribute, MetaList, MetaWord}; +use syntax::ast::{Attribute, Lit, Lit_, MetaList, MetaWord, MetaNameValue}; use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; /// **What it does:** This lint `Warn`s on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. @@ -24,17 +25,45 @@ use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; declare_lint! { pub INLINE_ALWAYS, Warn, "`#[inline(always)]` is a bad idea in most cases" } +/// **What it does:** This lint `Warn`s on `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. +/// +/// **Why is this bad?** For checking the version of the deprecation, it must be valid semver. Failing that, the contained information is useless. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// #[deprecated(since = "forever")] +/// fn something_else(..) { ... } +/// ``` +declare_lint! { pub DEPRECATED_SEMVER, Warn, + "`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" } #[derive(Copy,Clone)] pub struct AttrPass; impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { - lint_array!(INLINE_ALWAYS) + lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER) } } impl LateLintPass for AttrPass { + fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) { + if let MetaList(ref name, ref items) = attr.node.value.node { + if items.is_empty() || name != &"deprecated" { + return; + } + for ref item in items { + if let MetaNameValue(ref name, ref lit) = item.node { + if name == &"since" { + check_semver(cx, item.span, lit); + } + } + } + } + } + fn check_item(&mut self, cx: &LateContext, item: &Item) { if is_relevant_item(item) { check_attrs(cx, item.span, &item.name, &item.attrs) @@ -128,3 +157,15 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } } } + +fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { + if let Lit_::LitStr(ref is, _) = lit.node { + if Version::parse(&*is).is_ok() { + return; + } + } + span_lint(cx, + DEPRECATED_SEMVER, + span, + "the since field must contain a semver-compliant version"); +} diff --git a/src/lib.rs b/src/lib.rs index 45f47fe3d63..f8db15605ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,9 @@ extern crate collections; // for unicode nfc normalization extern crate unicode_normalization; +// for semver check in attrs.rs +extern crate semver; + extern crate rustc_plugin; use rustc_plugin::Registry; @@ -156,6 +159,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, array_indexing::OUT_OF_BOUNDS_INDEXING, + attrs::DEPRECATED_SEMVER, attrs::INLINE_ALWAYS, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs index ca7a0d5c07b..c7a4af60982 100644 --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -1,7 +1,7 @@ -#![feature(plugin)] +#![feature(plugin, deprecated)] #![plugin(clippy)] -#![deny(inline_always)] +#![deny(inline_always, deprecated_semver)] #[inline(always)] //~ERROR you have declared `#[inline(always)]` on `test_attr_lint`. fn test_attr_lint() { @@ -24,6 +24,14 @@ fn empty_and_false_positive_stmt() { unreachable!(); } +#[deprecated(since = "forever")] //~ERROR the since field must contain a semver-compliant version +pub const SOME_CONST : u8 = 42; + +#[deprecated(since = "1")] //~ERROR the since field must contain a semver-compliant version +pub const ANOTHER_CONST : u8 = 23; + +#[deprecated(since = "0.1.1")] +pub const YET_ANOTHER_CONST : u8 = 0; fn main() { test_attr_lint(); -- cgit 1.4.1-3-g733a5 From 9f641a1009e92431b4a49a835c4e80c51ce44c88 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Jan 2016 01:19:27 +0100 Subject: Add known enums to SINGLE_MATCH --- src/matches.rs | 53 +++++++++++++++++++++++++++++++++++++++---- src/utils.rs | 1 + tests/compile-fail/matches.rs | 49 +++++++++++++++++++++++++++++++++++---- 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 5e207093c15..217c4abf45b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -8,7 +8,8 @@ use std::cmp::Ordering; use syntax::ast::Lit_::LitBool; use syntax::codemap::Span; -use utils::{snippet, span_lint, span_note_and_lint, span_help_and_lint, in_external_macro, expr_block}; +use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; +use utils::{match_type, snippet, span_lint, span_note_and_lint, span_help_and_lint, in_external_macro, expr_block}; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default. /// @@ -109,9 +110,20 @@ impl LateLintPass for MatchPass { } fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { - if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && - arms[1].guard.is_none() && arms[1].pats[0].node == PatWild && is_unit_expr(&arms[1].body) && - (cx.tcx.expr_ty(ex).sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow) { + if arms.len() == 2 && + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + is_unit_expr(&arms[1].body) { + let ty = cx.tcx.expr_ty(ex); + if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { + check_single_match_single_pattern(cx, ex, arms, expr); + check_single_match_opt_like(cx, ex, arms, expr, ty); + } + } +} + +fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + if arms[1].pats[0].node == PatWild { span_help_and_lint(cx, SINGLE_MATCH, expr.span, @@ -124,6 +136,39 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } +fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty) { + // list of candidate Enums we know will never get any more membre + let candidates = &[ + (&COW_PATH, "Borrowed"), + (&COW_PATH, "Cow::Borrowed"), + (&COW_PATH, "Cow::Owned"), + (&COW_PATH, "Owned"), + (&OPTION_PATH, "None"), + (&RESULT_PATH, "Err"), + (&RESULT_PATH, "Ok"), + ]; + + let path = match arms[1].pats[0].node { + PatEnum(ref path, _) => path.to_string(), + PatIdent(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), + _ => return + }; + + for &(ty_path, pat_path) in candidates { + if &path == pat_path && match_type(cx, ty, ty_path) { + span_help_and_lint(cx, + SINGLE_MATCH, + expr.span, + "you seem to be trying to use match for destructuring a single pattern. Consider using \ + `if let`", + &format!("try\nif let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."))); + } + } +} + fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { diff --git a/src/utils.rs b/src/utils.rs index 74a15927ad1..77e63fe4458 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -29,6 +29,7 @@ pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index b569f9566ef..c58e62419c6 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -4,8 +4,14 @@ #![deny(clippy)] #![allow(unused)] +use std::borrow::Cow; + +enum Foo { Bar, Baz(u8) } +use Foo::*; + fn single_match(){ let x = Some(1u8); + match x { //~ ERROR you seem to be trying to use match //~^ HELP try Some(y) => { @@ -13,11 +19,7 @@ fn single_match(){ } _ => () } - // Not linted - match x { - Some(y) => println!("{:?}", y), - None => () - } + let z = (1u8,1u8); match z { //~ ERROR you seem to be trying to use match //~^ HELP try @@ -38,6 +40,43 @@ fn single_match(){ } } +fn single_match_know_enum() { + let x = Some(1u8); + let y : Result<_, i8> = Ok(1i8); + + match x { //~ ERROR you seem to be trying to use match + //~^ HELP try + Some(y) => println!("{:?}", y), + None => () + } + + match y { //~ ERROR you seem to be trying to use match + //~^ HELP try + Ok(y) => println!("{:?}", y), + Err(..) => () + } + + let c = Cow::Borrowed(""); + + match c { //~ ERROR you seem to be trying to use match + //~^ HELP try + Cow::Borrowed(..) => println!("42"), + Cow::Owned(..) => (), + } + + let z = Foo::Bar; + // no warning + match z { + Bar => println!("42"), + Baz(_) => (), + } + + match z { + Baz(_) => println!("42"), + Bar => (), + } +} + fn match_bool() { let test: bool = true; -- cgit 1.4.1-3-g733a5 From 44daa8bd72d29b281741a6fc11e07faa03d5fb1e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Jan 2016 12:57:44 +0100 Subject: Use span_suggestion in matches lints Ref #442 --- src/matches.rs | 100 ++++++++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 55 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 217c4abf45b..4cb4df19bf8 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -9,7 +9,7 @@ use syntax::ast::Lit_::LitBool; use syntax::codemap::Span; use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; -use utils::{match_type, snippet, span_lint, span_note_and_lint, span_help_and_lint, in_external_macro, expr_block}; +use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default. /// @@ -124,15 +124,17 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms[1].pats[0].node == PatWild { - span_help_and_lint(cx, + span_lint_and_then(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for destructuring a single pattern. Consider using \ - `if let`", - &format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."))); + "you seem to be trying to use match for destructuring a single pattern. \ + Consider using `if let`", |db| { + db.span_suggestion(expr.span, "try this", + format!("if let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."))); + }); } } @@ -156,15 +158,17 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: for &(ty_path, pat_path) in candidates { if &path == pat_path && match_type(cx, ty, ty_path) { - span_help_and_lint(cx, + span_lint_and_then(cx, SINGLE_MATCH, expr.span, - "you seem to be trying to use match for destructuring a single pattern. Consider using \ - `if let`", - &format!("try\nif let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."))); + "you seem to be trying to use match for destructuring a single pattern. \ + Consider using `if let`", |db| { + db.span_suggestion(expr.span, "try this", + format!("if let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."))); + }); } } } @@ -172,7 +176,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { - if arms.len() == 2 && arms[0].pats.len() == 1 { + let sugg = if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { @@ -187,56 +191,42 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } else { None }; + if let Some((ref true_expr, ref false_expr)) = exprs { if !is_unit_expr(true_expr) { if !is_unit_expr(false_expr) { - span_help_and_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using \ - an if..else block:", - &format!("try\nif {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))); + Some(format!("if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))) } else { - span_help_and_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using \ - an if..else block:", - &format!("try\nif {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."))); + Some(format!("if {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."))) } } else if !is_unit_expr(false_expr) { - span_help_and_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an \ - if..else block:", - &format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))); + Some(format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))) } else { - span_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an if..else \ - block"); + None } } else { - span_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an if..else block"); + None } } else { - span_lint(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an if..else block"); - } + None + }; + + span_lint_and_then(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using \ + an if..else block:", move |db| { + if let Some(ref sugg) = sugg { + db.span_suggestion(expr.span, "try this", sugg.clone()); + } + }); } } -- cgit 1.4.1-3-g733a5 From 09129c1b416cf0101b75e72e6a3ffdfbbef78542 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 12 Jan 2016 20:23:28 +0100 Subject: Add BTreeMap to the HASHMAP_ENTRY rule Fixes #433 --- README.md | 2 +- src/entry.rs | 111 ++++++++++++++++++++++++++++++++++++++++++ src/hashmap.rs | 102 -------------------------------------- src/lib.rs | 6 +-- src/utils.rs | 15 +++--- tests/compile-fail/entry.rs | 47 ++++++++++++++++++ tests/compile-fail/hashmap.rs | 41 ---------------- 7 files changed, 170 insertions(+), 154 deletions(-) create mode 100644 src/entry.rs delete mode 100644 src/hashmap.rs create mode 100644 tests/compile-fail/entry.rs delete mode 100644 tests/compile-fail/hashmap.rs diff --git a/README.md b/README.md index 13105087706..631c1d7f1d2 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ name [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[hashmap_entry](https://github.com/Manishearth/rust-clippy/wiki#hashmap_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases @@ -43,6 +42,7 @@ name [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) +[map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead diff --git a/src/entry.rs b/src/entry.rs new file mode 100644 index 00000000000..1885bea164b --- /dev/null +++ b/src/entry.rs @@ -0,0 +1,111 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::codemap::Span; +use utils::{get_item_name, is_exp_equal, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; +use utils::{BTREEMAP_PATH, HASHMAP_PATH}; + +/// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or +/// `BTreeMap`. +/// +/// **Why is this bad?** Using `entry` is more efficient. +/// +/// **Known problems:** Some false negatives, eg.: +/// ``` +/// let k = &key; +/// if !m.contains_key(k) { m.insert(k.clone(), v); } +/// ``` +/// +/// **Example:** +/// ```rust +/// if !m.contains_key(&k) { m.insert(k, v) } +/// ``` +/// can be rewritten as: +/// ```rust +/// m.entry(k).or_insert(v); +/// ``` +declare_lint! { + pub MAP_ENTRY, + Warn, + "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" +} + +#[derive(Copy,Clone)] +pub struct HashMapLint; + +impl LintPass for HashMapLint { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_ENTRY) + } +} + +impl LateLintPass for HashMapLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! { + [ + let ExprIf(ref check, ref then, _) = expr.node, + let ExprUnary(UnOp::UnNot, ref check) = check.node, + let ExprMethodCall(ref name, _, ref params) = check.node, + params.len() >= 2, + name.node.as_str() == "contains_key" + ], { + let key = match params[1].node { + ExprAddrOf(_, ref key) => key, + _ => return + }; + + let map = ¶ms[0]; + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); + + let kind = if match_type(cx, obj_ty, &BTREEMAP_PATH) { + "BTreeMap" + } + else if match_type(cx, obj_ty, &HASHMAP_PATH) { + "HashMap" + } + else { + return + }; + + let sole_expr = if then.expr.is_some() { 1 } else { 0 } + then.stmts.len() == 1; + + if let Some(ref then) = then.expr { + check_for_insert(cx, expr.span, map, key, then, sole_expr, kind); + } + + for stmt in &then.stmts { + if let StmtSemi(ref stmt, _) = stmt.node { + check_for_insert(cx, expr.span, map, key, stmt, sole_expr, kind); + } + } + } + } + } +} + +fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr, sole_expr: bool, kind: &str) { + if_let_chain! { + [ + let ExprMethodCall(ref name, _, ref params) = expr.node, + params.len() == 3, + name.node.as_str() == "insert", + get_item_name(cx, map) == get_item_name(cx, &*params[0]), + is_exp_equal(cx, key, ¶ms[1]) + ], { + let help = if sole_expr { + format!("Consider using `{}.entry({}).or_insert({})`", + snippet(cx, map.span, ".."), + snippet(cx, params[1].span, ".."), + snippet(cx, params[2].span, "..")) + } + else { + format!("Consider using `{}.entry({})`", + snippet(cx, map.span, ".."), + snippet(cx, params[1].span, "..")) + }; + + span_help_and_lint(cx, MAP_ENTRY, span, + &format!("usage of `contains_key` followed by `insert` on `{}`", kind), + &help); + } + } +} diff --git a/src/hashmap.rs b/src/hashmap.rs deleted file mode 100644 index 095a00e3777..00000000000 --- a/src/hashmap.rs +++ /dev/null @@ -1,102 +0,0 @@ -use rustc::lint::*; -use rustc_front::hir::*; -use syntax::codemap::Span; -use utils::{get_item_name, is_exp_equal, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; -use utils::HASHMAP_PATH; - -/// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap`. -/// -/// **Why is this bad?** Using `HashMap::entry` is more efficient. -/// -/// **Known problems:** Some false negatives, eg.: -/// ``` -/// let k = &key; -/// if !m.contains_key(k) { m.insert(k.clone(), v); } -/// ``` -/// -/// **Example:** -/// ```rust -/// if !m.contains_key(&k) { m.insert(k, v) } -/// ``` -/// can be rewritten as: -/// ```rust -/// m.entry(k).or_insert(v); -/// ``` -declare_lint! { - pub HASHMAP_ENTRY, - Warn, - "use of `contains_key` followed by `insert` on a `HashMap`" -} - -#[derive(Copy,Clone)] -pub struct HashMapLint; - -impl LintPass for HashMapLint { - fn get_lints(&self) -> LintArray { - lint_array!(HASHMAP_ENTRY) - } -} - -impl LateLintPass for HashMapLint { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain! { - [ - let ExprIf(ref check, ref then, _) = expr.node, - let ExprUnary(UnOp::UnNot, ref check) = check.node, - let ExprMethodCall(ref name, _, ref params) = check.node, - params.len() >= 2, - name.node.as_str() == "contains_key" - ], { - let key = match params[1].node { - ExprAddrOf(_, ref key) => key, - _ => return - }; - - let map = ¶ms[0]; - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); - - if match_type(cx, obj_ty, &HASHMAP_PATH) { - let sole_expr = if then.expr.is_some() { 1 } else { 0 } + then.stmts.len() == 1; - - if let Some(ref then) = then.expr { - check_for_insert(cx, expr.span, map, key, then, sole_expr); - } - - for stmt in &then.stmts { - if let StmtSemi(ref stmt, _) = stmt.node { - check_for_insert(cx, expr.span, map, key, stmt, sole_expr); - } - } - } - } - } - } -} - -fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr, sole_expr: bool) { - if_let_chain! { - [ - let ExprMethodCall(ref name, _, ref params) = expr.node, - params.len() == 3, - name.node.as_str() == "insert", - get_item_name(cx, map) == get_item_name(cx, &*params[0]), - is_exp_equal(cx, key, ¶ms[1]) - ], { - if sole_expr { - span_help_and_lint(cx, HASHMAP_ENTRY, span, - "usage of `contains_key` followed by `insert` on `HashMap`", - &format!("Consider using `{}.entry({}).or_insert({})`", - snippet(cx, map.span, ".."), - snippet(cx, params[1].span, ".."), - snippet(cx, params[2].span, ".."))); - } - else { - span_help_and_lint(cx, HASHMAP_ENTRY, span, - "usage of `contains_key` followed by `insert` on `HashMap`", - &format!("Consider using `{}.entry({})`", - snippet(cx, map.span, ".."), - snippet(cx, params[1].span, ".."))); - } - } - } -} diff --git a/src/lib.rs b/src/lib.rs index f8db15605ff..9bb59693795 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,7 @@ pub mod temporary_assignment; pub mod transmute; pub mod cyclomatic_complexity; pub mod escape; -pub mod hashmap; +pub mod entry; pub mod misc_early; pub mod array_indexing; pub mod panic; @@ -113,7 +113,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::UnitCmp); reg.register_late_lint_pass(box loops::LoopsPass); reg.register_late_lint_pass(box lifetimes::LifetimePass); - reg.register_late_lint_pass(box hashmap::HashMapLint); + reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); reg.register_late_lint_pass(box types::CastPass); reg.register_late_lint_pass(box types::TypeComplexityPass); @@ -167,10 +167,10 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + entry::MAP_ENTRY, eq_op::EQ_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, - hashmap::HASHMAP_ENTRY, identity_op::IDENTITY_OP, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, diff --git a/src/utils.rs b/src/utils.rs index 77e63fe4458..d3ebe809ac9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,17 +19,18 @@ use std::ops::{Deref, DerefMut}; pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for +pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; +pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; +pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; -pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; -pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; -pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; -pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs new file mode 100644 index 00000000000..7ea0e3952b0 --- /dev/null +++ b/tests/compile-fail/entry.rs @@ -0,0 +1,47 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unused)] + +#![deny(map_entry)] + +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; + +fn foo() {} + +fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { m.insert(k, v); } + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k).or_insert(v)` +} + +fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { foo(); m.insert(k, v); } + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k)` +} + +fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { m.insert(k, v) } else { None }; + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k).or_insert(v)` +} + +fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; + //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` + //~^^HELP: Consider using `m.entry(k)` +} + +fn insert_in_btreemap<K: Ord, V>(m: &mut BTreeMap<K, V>, k: K, v: V) { + if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; + //~^ERROR: usage of `contains_key` followed by `insert` on `BTreeMap` + //~^^HELP: Consider using `m.entry(k)` +} + +fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { + if !m.contains_key(&k) { m.insert(o, v); } +} + +fn main() { +} diff --git a/tests/compile-fail/hashmap.rs b/tests/compile-fail/hashmap.rs deleted file mode 100644 index a53566a794e..00000000000 --- a/tests/compile-fail/hashmap.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] -#![allow(unused)] - -#![deny(hashmap_entry)] - -use std::collections::HashMap; -use std::hash::Hash; - -fn foo() {} - -fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v); } - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k).or_insert(v)` -} - -fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { foo(); m.insert(k, v); } - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k)` -} - -fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v) } else { None }; - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k).or_insert(v)` -} - -fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k)` -} - -fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { - if !m.contains_key(&k) { m.insert(o, v); } -} - -fn main() { -} -- cgit 1.4.1-3-g733a5 From f63329761fe66395acb17ccd89a6202c2b5dadab Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 12 Jan 2016 23:17:54 +0100 Subject: Cleanup utils, mostly doc --- Cargo.toml | 1 - src/utils.rs | 109 +++++++++++++++++++++++++++++++---------------------------- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 792326d6c1d..db5944ab9b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,5 +29,4 @@ rustc-serialize = "0.3" [features] -structured_logging = [] debugging = [] diff --git a/src/utils.rs b/src/utils.rs index d3ebe809ac9..53f83d6921a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -78,20 +78,21 @@ macro_rules! if_let_chain { }; } -/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one isn't) +/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one +/// isn't). pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { sp1.expn_id != sp2.expn_id } -/// returns true if this expn_info was expanded by any macro +/// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) } -/// returns true if the macro that expanded the crate was outside of -/// the current crate or was a compiler plugin +/// Returns true if the macro that expanded the crate was outside of the current crate or was a +/// compiler plugin. pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { - /// invokes in_macro with the expansion info of the given span - /// slightly heavy, try to use this after other checks have already happened + /// Invokes in_macro with the expansion info of the given span slightly heavy, try to use this + /// after other checks have already happened. fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { @@ -110,9 +111,12 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) } -/// check if a DefId's path matches the given absolute type path -/// usage e.g. with -/// `match_def_path(cx, id, &["core", "option", "Option"])` +/// Check if a `DefId`'s path matches the given absolute type path usage. +/// +/// # Examples +/// ``` +/// match_def_path(cx, id, &["core", "option", "Option"]) +/// ``` pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { cx.tcx.with_path(def_id, |iter| { iter.zip(path) @@ -120,7 +124,7 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { }) } -/// check if type is struct or enum type with given def path +/// Check if type is struct or enum type with given def path. pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { match ty.sty { ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), @@ -128,7 +132,7 @@ pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { } } -/// check if method call given in "expr" belongs to given trait +/// Check if the method call given in `expr` belongs to given trait. pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); @@ -145,9 +149,10 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { } } -/// check if method call given in "expr" belongs to given trait +/// Check if the method call given in `expr` belongs to given trait. pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); + let trt_id = cx.tcx .tables .borrow() @@ -161,21 +166,31 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool } } -/// match a Path against a slice of segment string literals, e.g. -/// `match_path(path, &["std", "rt", "begin_unwind"])` +/// Match a `Path` against a slice of segment string literals. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) } -/// match a Path against a slice of segment string literals, e.g. -/// `match_path(path, &["std", "rt", "begin_unwind"])` +/// Match a `Path` against a slice of segment string literals, e.g. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) } -/// match an Expr against a chain of methods, and return the matched Exprs. For example, if `expr` -/// represents the `.baz()` in `foo.bar().baz()`, `matched_method_chain(expr, &["bar", "baz"])` -/// will return a Vec containing the Exprs for `.bar()` and `.baz()` +/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. +/// +/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, +/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for +/// `.bar()` and `.baz()` pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { let mut current = expr; let mut matched = Vec::with_capacity(methods.len()); @@ -197,7 +212,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a } -/// get the name of the item the expression is in, if available +/// Get the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { @@ -208,7 +223,7 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { } } -/// checks if a `let` decl is from a for loop desugaring +/// Checks if a `let` decl is from a `for` loop desugaring. pub fn is_from_for_desugar(decl: &Decl) -> bool { if_let_chain! { [ @@ -222,31 +237,39 @@ pub fn is_from_for_desugar(decl: &Decl) -> bool { } -/// convert a span to a code snippet if available, otherwise use default, e.g. -/// `snippet(cx, expr.span, "..")` +/// Convert a span to a code snippet if available, otherwise use default. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) } -/// Converts a span to a code snippet. Returns None if not available. +/// Convert a span to a code snippet. Returns `None` if not available. pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { cx.sess().codemap().span_to_snippet(span).ok() } -/// convert a span (from a block) to a code snippet if available, otherwise use default, e.g. -/// `snippet(cx, expr.span, "..")` -/// This trims the code of indentation, except for the first line -/// Use it for blocks or block-like things which need to be printed as such +/// Convert a span (from a block) to a code snippet if available, otherwise use default. +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like +/// things which need to be printed as such. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { let snip = snippet(cx, span, default); trim_multiline(snip, true) } -/// Like snippet_block, but add braces if the expr is not an ExprBlock -/// Also takes an Option<String> which can be put inside the braces +/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. +/// Also takes an `Option<String>` which can be put inside the braces. pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); - let string = option.map_or("".to_owned(), |s| s); + let string = option.unwrap_or_default(); if let ExprBlock(_) = expr.node { Cow::Owned(format!("{}{}", code, string)) } else if string.is_empty() { @@ -256,8 +279,7 @@ pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String } } -/// Trim indentation from a multiline string -/// with possibility of ignoring the first line +/// Trim indentation from a multiline string with possibility of ignoring the first line. pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { let s_space = trim_multiline_inner(s, ignore_first, ' '); let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); @@ -297,7 +319,7 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { } } -/// get a parent expr if any – this is useful to constrain a lint +/// Get a parent expressions if any – this is useful to constrain a lint. pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { let map = &cx.tcx.map; let node_id: NodeId = e.id; @@ -350,22 +372,7 @@ impl<'a> Deref for DiagnosticWrapper<'a> { } } -#[cfg(not(feature="structured_logging"))] -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, sp, msg); - if cx.current_level(lint) != Level::Allow { - db.fileline_help(sp, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); - } - DiagnosticWrapper(db) -} - -#[cfg(feature="structured_logging")] pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { - // lint.name / lint.desc is can give details of the lint - // cx.sess().codemap() has all these nice functions for line/column/snippet details - // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string let mut db = cx.struct_span_lint(lint, sp, msg); if cx.current_level(lint) != Level::Allow { db.fileline_help(sp, @@ -419,7 +426,7 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, db } -/// return the base type for references and raw pointers +/// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), @@ -427,7 +434,7 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { } } -/// return the base type for references and raw pointers, and count reference depth +/// Return the base type for references and raw pointers, and count reference depth. pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { match ty.sty { -- cgit 1.4.1-3-g733a5 From 6fa9bf64d73d90ec35f30dcbb7d77f7418fff071 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Jan 2016 17:17:19 +0100 Subject: Use span_suggestion in ENTRY lint --- src/entry.rs | 13 +++++++------ tests/compile-fail/entry.rs | 25 +++++++++++++++---------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index 1885bea164b..d9fb7269be6 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use utils::{get_item_name, is_exp_equal, match_type, snippet, span_help_and_lint, walk_ptrs_ty}; +use utils::{get_item_name, is_exp_equal, match_type, snippet, span_lint_and_then, walk_ptrs_ty}; use utils::{BTREEMAP_PATH, HASHMAP_PATH}; /// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or @@ -92,20 +92,21 @@ fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: is_exp_equal(cx, key, ¶ms[1]) ], { let help = if sole_expr { - format!("Consider using `{}.entry({}).or_insert({})`", + format!("{}.entry({}).or_insert({})", snippet(cx, map.span, ".."), snippet(cx, params[1].span, ".."), snippet(cx, params[2].span, "..")) } else { - format!("Consider using `{}.entry({})`", + format!("{}.entry({})", snippet(cx, map.span, ".."), snippet(cx, params[1].span, "..")) }; - span_help_and_lint(cx, MAP_ENTRY, span, - &format!("usage of `contains_key` followed by `insert` on `{}`", kind), - &help); + span_lint_and_then(cx, MAP_ENTRY, span, + &format!("usage of `contains_key` followed by `insert` on `{}`", kind), |db| { + db.span_suggestion(span, "Consider using", help.clone()); + }); } } } diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs index 7ea0e3952b0..a7460282007 100644 --- a/tests/compile-fail/entry.rs +++ b/tests/compile-fail/entry.rs @@ -11,32 +11,37 @@ fn foo() {} fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v); } - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k).or_insert(v)` + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| HELP Consider + //~| SUGGESTION m.entry(k).or_insert(v) } fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v); } - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| HELP Consider + //~| SUGGESTION m.entry(k) } fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v) } else { None }; - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k).or_insert(v)` + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| HELP Consider + //~| SUGGESTION m.entry(k).or_insert(v) } fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - //~^ERROR: usage of `contains_key` followed by `insert` on `HashMap` - //~^^HELP: Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| HELP Consider + //~| SUGGESTION m.entry(k) } fn insert_in_btreemap<K: Ord, V>(m: &mut BTreeMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - //~^ERROR: usage of `contains_key` followed by `insert` on `BTreeMap` - //~^^HELP: Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on `BTreeMap` + //~| HELP Consider + //~| SUGGESTION m.entry(k) } fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { -- cgit 1.4.1-3-g733a5 From 375b8168e48f7af89c754a41581f3a7102fae066 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Jan 2016 18:32:05 +0100 Subject: Remove useless curly braces in else { if .. } --- src/bit_mask.rs | 19 +++++++------------ src/consts.rs | 8 +++----- src/minmax.rs | 8 +++----- src/shadow.rs | 41 ++++++++++++++++++++--------------------- 4 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index c2fd3742066..133212daf14 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -148,11 +148,10 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: mask_value, cmp_value)); } - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } + } BiBitOr => { if mask_value | cmp_value != cmp_value { @@ -177,10 +176,8 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: &format!("incompatible bit mask: `_ & {}` will always be lower than `{}`", mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } } BiBitOr => { @@ -209,10 +206,8 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: &format!("incompatible bit mask: `_ & {}` will never be higher than `{}`", mask_value, cmp_value)); - } else { - if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } } BiBitOr => { diff --git a/src/consts.rs b/src/consts.rs index 171ba6f27f0..68320705fb6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -536,12 +536,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { Plus }) .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + } else if ln { + add_neg_int(r64, rty, l64, lty) } else { - if ln { - add_neg_int(r64, rty, l64, lty) - } else { - add_neg_int(l64, lty, r64, rty) - } + add_neg_int(l64, lty, r64, rty) } } // TODO: float (would need bignum library?) diff --git a/src/minmax.rs b/src/minmax.rs index 2cce36f2a9c..e72f2392054 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -59,12 +59,10 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' if match_def_path(cx, def_id, &["core", "cmp", "min"]) { fetch_const(args, Min) + } else if match_def_path(cx, def_id, &["core", "cmp", "max"]) { + fetch_const(args, Max) } else { - if match_def_path(cx, def_id, &["core", "cmp", "max"]) { - fetch_const(args, Max) - } else { - None - } + None } } else { None diff --git a/src/shadow.rs b/src/shadow.rs index 2d3e423eacb..bcf3ce7116a 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -204,29 +204,28 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & snippet(cx, lspan, "_"), snippet(cx, expr.span, ".."))); note_orig(cx, db, SHADOW_SAME, prev_span); + } else if contains_self(name, expr) { + let db = span_note_and_lint(cx, + SHADOW_REUSE, + lspan, + &format!("{} is shadowed by {} which reuses the original value", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); + note_orig(cx, db, SHADOW_REUSE, prev_span); } else { - if contains_self(name, expr) { - let db = span_note_and_lint(cx, - SHADOW_REUSE, - lspan, - &format!("{} is shadowed by {} which reuses the original value", - snippet(cx, lspan, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_REUSE, prev_span); - } else { - let db = span_note_and_lint(cx, - SHADOW_UNRELATED, - lspan, - &format!("{} is shadowed by {}", - snippet(cx, lspan, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_UNRELATED, prev_span); - } + let db = span_note_and_lint(cx, + SHADOW_UNRELATED, + lspan, + &format!("{} is shadowed by {}", + snippet(cx, lspan, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); + note_orig(cx, db, SHADOW_UNRELATED, prev_span); } + } else { let db = span_lint(cx, SHADOW_UNRELATED, -- cgit 1.4.1-3-g733a5 From c2444c604388f96a6949bb39bcf3730c6ef78c0f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Jan 2016 18:32:55 +0100 Subject: Lint about `else { if .. }` with useless braces --- README.md | 2 +- src/collapsible_if.rs | 71 ++++++++++++++++++++++++------------ tests/compile-fail/collapsible_if.rs | 24 ++++++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 631c1d7f1d2..33bca7f871f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ name [cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 4a17d3a4608..fb1d7f696d1 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -16,9 +16,11 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::{in_macro, span_help_and_lint, snippet, snippet_block}; +use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; -/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by `&&`-combining their conditions. It is `Warn` by default. +/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by +/// `&&`-combining their conditions and for `else { if .. } expressions that can be collapsed to +/// `else if ..`. It is `Warn` by default. /// /// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. /// @@ -29,7 +31,8 @@ declare_lint! { pub COLLAPSIBLE_IF, Warn, "two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` \ - can be written as `if x && y { foo() }`" + can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to \ + `else if`" } #[derive(Copy,Clone)] @@ -50,20 +53,44 @@ impl LateLintPass for CollapsibleIf { } fn check_if(cx: &LateContext, e: &Expr) { - if let ExprIf(ref check, ref then, None) = e.node { - if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = - single_stmt_of_block(then) { - if e.span.expn_id != sp.expn_id { - return; + if let ExprIf(ref check, ref then, ref else_) = e.node { + match *else_ { + Some(ref else_) => { + if_let_chain! {[ + let ExprBlock(ref block) = else_.node, + block.stmts.is_empty(), + block.rules == BlockCheckMode::DefaultBlock, + let Some(ref else_) = block.expr, + let ExprIf(_, _, _) = else_.node + ], { + span_lint_and_then(cx, + COLLAPSIBLE_IF, + block.span, + "this `else { if .. }` block can be collapsed", |db| { + db.span_suggestion(block.span, "try", + format!("else {}", + snippet_block(cx, else_.span, ".."))); + }); + }} + } + None => { + if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = + single_stmt_of_block(then) { + if e.span.expn_id != sp.expn_id { + return; + } + span_lint_and_then(cx, + COLLAPSIBLE_IF, + e.span, + "this if statement can be collapsed", |db| { + db.span_suggestion(e.span, "try", + format!("if {} && {} {}", + check_to_string(cx, check), + check_to_string(cx, check_inner), + snippet_block(cx, content.span, ".."))); + }); + } } - span_help_and_lint(cx, - COLLAPSIBLE_IF, - e.span, - "this if statement can be collapsed", - &format!("try\nif {} && {} {}", - check_to_string(cx, check), - check_to_string(cx, check_inner), - snippet_block(cx, content.span, ".."))); } } } @@ -90,16 +117,14 @@ fn single_stmt_of_block(block: &Block) -> Option<&Expr> { } else { None } - } else { - if block.stmts.is_empty() { - if let Some(ref p) = block.expr { - Some(p) - } else { - None - } + } else if block.stmts.is_empty() { + if let Some(ref p) = block.expr { + Some(p) } else { None } + } else { + None } } diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index cc63e895f1c..85eac28dc38 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -17,6 +17,30 @@ fn main() { } } + // Collaspe `else { if .. }` to `else if ..` + if x == "hello" { + print!("Hello "); + } else { //~ERROR: this `else { if .. }` + //~| HELP try + //~| SUGGESTION else if y == "world" + if y == "world" { + println!("world!") + } + } + + if x == "hello" { + print!("Hello "); + } else { //~ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION else if y == "world" + if y == "world" { + println!("world") + } + else { + println!("!") + } + } + // Works because any if with an else statement cannot be collapsed. if x == "hello" { if y == "world" { -- cgit 1.4.1-3-g733a5 From 7499f3c7a945f7dc32c3b9a7fd553874a2adff43 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Thu, 14 Jan 2016 19:27:24 +0100 Subject: Consider lifetime in self paramter in unused_lifetime lint --- src/lifetimes.rs | 15 +++++++++++++-- tests/compile-fail/lifetimes.rs | 4 ++-- tests/compile-fail/unused_lt.rs | 7 +++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 2de916cfebc..1edd75a45aa 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -77,7 +77,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g span, "explicit lifetimes given in parameter types where they could be elided"); } - report_extra_lifetimes(cx, decl, &generics); + report_extra_lifetimes(cx, decl, &generics, slf); } fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, named_lts: &[LifetimeDef]) -> bool { @@ -303,14 +303,25 @@ impl<'v> Visitor<'v> for LifetimeChecker { } } -fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) { +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, + generics: &Generics, slf: Option<&ExplicitSelf>) { let hs = generics.lifetimes .iter() .map(|lt| (lt.lifetime.name, lt.lifetime.span)) .collect(); let mut checker = LifetimeChecker(hs); + walk_generics(&mut checker, generics); walk_fn_decl(&mut checker, func); + + if let Some(slf) = slf { + match slf.node { + SelfRegion(Some(ref lt), _, _) => checker.visit_lifetime(lt), + SelfExplicit(ref t, _) => walk_ty(&mut checker, t), + _ => {} + } + } + for (_, v) in checker.0 { span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 4d454a738d9..99c16917426 100644 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -1,8 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(needless_lifetimes)] -#![allow(dead_code, unused_lifetimes)] +#![deny(needless_lifetimes, unused_lifetimes)] +#![allow(dead_code)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~^ERROR explicit lifetimes given diff --git a/tests/compile-fail/unused_lt.rs b/tests/compile-fail/unused_lt.rs index 85667174509..a35718b5848 100644 --- a/tests/compile-fail/unused_lt.rs +++ b/tests/compile-fail/unused_lt.rs @@ -52,6 +52,13 @@ pub fn parse2<'a, I>(_it: &mut I) where I: Iterator<Item=&'a str>{ unimplemented!() } +struct X { x: u32 } + +impl X { + fn self_ref_with_lifetime<'a>(&'a self) {} + fn explicit_self_with_lifetime<'a>(self: &'a Self) {} +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 387e0991e3be528ab85fce8f57c489949a7a41a5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Jan 2016 20:58:32 +0100 Subject: Handle more iterator adapter cases in for loops --- src/loops.rs | 138 ++++++++++++++++++++++++++++------------- src/utils.rs | 1 + tests/compile-fail/for_loop.rs | 24 ++++++- 3 files changed, 117 insertions(+), 46 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 91bb898629f..614b561749f 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -8,7 +8,6 @@ use consts::{constant_simple, Constant}; use rustc::front::map::Node::NodeBlock; use std::borrow::Cow; use std::collections::{HashSet, HashMap}; -use syntax::ast::Lit_::*; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal, get_enclosing_block}; @@ -247,54 +246,102 @@ impl LateLintPass for LoopsPass { } fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - // check for looping over a range and then indexing a sequence with it - // -> the iteratee must be a range literal - if let ExprRange(Some(ref l), _) = arg.node { - // Range should start with `0` - if let ExprLit(ref lit) = l.node { - if let LitInt(0, _) = lit.node { - - // the var must be a single name - if let PatIdent(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { - cx: cx, - var: ident.node.name, - indexed: HashSet::new(), - nonindex: false, - }; - walk_expr(&mut visitor, body); - // linting condition: we only indexed one variable - if visitor.indexed.len() == 1 { - let indexed = visitor.indexed - .into_iter() - .next() - .expect("Len was nonzero, but no contents found"); - if visitor.nonindex { - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is used to index `{}`. Consider using `for \ - ({}, item) in {}.iter().enumerate()` or similar iterators", - ident.node.name, - indexed, - ident.node.name, - indexed)); - } else { - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is only used to index `{}`. Consider using \ - `for item in &{}` or similar iterators", - ident.node.name, - indexed, - indexed)); - } + check_for_loop_range(cx, pat, arg, body, expr); + check_for_loop_reverse_range(cx, arg, expr); + check_for_loop_explicit_iter(cx, arg, expr); + check_for_loop_explicit_counter(cx, arg, body, expr); +} + +/// Check for looping over a range and then indexing a sequence with it. +/// The iteratee must be a range literal. +fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + if let ExprRange(Some(ref l), ref r) = arg.node { + // the var must be a single name + if let PatIdent(_, ref ident, _) = pat.node { + let mut visitor = VarVisitor { + cx: cx, + var: ident.node.name, + indexed: HashSet::new(), + nonindex: false, + }; + walk_expr(&mut visitor, body); + // linting condition: we only indexed one variable + if visitor.indexed.len() == 1 { + let indexed = visitor.indexed + .into_iter() + .next() + .expect("Len was nonzero, but no contents found"); + + let starts_at_zero = is_integer_literal(l, 0); + + let skip: Cow<_> = if starts_at_zero { + "".into() + } + else { + format!(".skip({})", snippet(cx, l.span, "..")).into() + }; + + let take: Cow<_> = if let Some(ref r) = *r { + if !is_len_call(&r, &indexed) { + format!(".take({})", snippet(cx, r.span, "..")).into() + } + else { + "".into() + } + } else { + "".into() + }; + + if visitor.nonindex { + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`. \ + Consider using `for ({}, item) in {}.iter().enumerate(){}{}` or similar iterators", + ident.node.name, + indexed, + ident.node.name, + indexed, + take, + skip)); + } else { + let repl = if starts_at_zero && take.is_empty() { + format!("&{}", indexed) } + else { + format!("{}.iter(){}{}", indexed, take, skip) + }; + + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`. \ + Consider using `for item in {}` or similar iterators", + ident.node.name, + indexed, + repl)); } } } } +} + +fn is_len_call(expr: &Expr, var: &Name) -> bool { + if_let_chain! {[ + let ExprMethodCall(method, _, ref len_args) = expr.node, + len_args.len() == 1, + method.node.as_str() == "len", + let ExprPath(_, ref path) = len_args[0].node, + path.segments.len() == 1, + &path.segments[0].identifier.name == var + ], { + return true; + }} + + false +} +fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { // ...and both sides are compile-time constant integers... @@ -324,7 +371,9 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E } } } +} +fn check_for_loop_explicit_iter(cx: &LateContext, arg: &Expr, expr: &Expr) { if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { @@ -356,6 +405,9 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E } } +} + +fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { // Look for variables that are incremented once per loop iteration. let mut visitor = IncrementVisitor { cx: cx, diff --git a/src/utils.rs b/src/utils.rs index 53f83d6921a..312cf77d068 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -445,6 +445,7 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { inner(ty, 0) } +/// Check whether the given expression is a constant literal of the given value. pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { // FIXME: use constant folding if let ExprLit(ref spanned) = expr.node { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index f1c1adf6cc8..6791d71ca36 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -20,20 +20,38 @@ impl Unrelated { fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; - for i in 0..vec.len() { //~ERROR the loop variable `i` is only used to index `vec`. + for i in 0..vec.len() { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in &vec` println!("{}", vec[i]); } - for i in 0..vec.len() { //~ERROR the loop variable `i` is used to index `vec`. + for i in 0..vec.len() { + //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate()` println!("{} {}", vec[i], i); } for i in 0..vec.len() { // not an error, indexing more than one variable println!("{} {}", vec[i], vec2[i]); } - for i in 5..vec.len() { // not an error, not starting with 0 + for i in 5..vec.len() { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().skip(5)` println!("{}", vec[i]); } + for i in 5..10 { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` + println!("{}", vec[i]); + } + + for i in 5..vec.len() { + //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().skip(5)` + println!("{} {}", vec[i], i); + } + + for i in 5..10 { + //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().take(10).skip(5)` + println!("{} {}", vec[i], i); + } + for i in 10..0 { //~ERROR this range is empty so this for loop will never run println!("{}", i); } -- cgit 1.4.1-3-g733a5 From e6b905d92529eb50de7073d34a6f9db7f2c6ab10 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Jan 2016 21:04:34 +0100 Subject: Add a test for #398 --- tests/compile-fail/for_loop.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 6791d71ca36..37ecd290175 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -32,6 +32,11 @@ fn main() { println!("{} {}", vec[i], vec2[i]); } + for i in 0..vec.len() { + //~^ ERROR `i` is only used to index `vec2`. Consider using `for item in vec2.iter().take(vec.len())` + println!("{}", vec2[i]); + } + for i in 5..vec.len() { //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().skip(5)` println!("{}", vec[i]); -- cgit 1.4.1-3-g733a5 From c6604bb281d6f8ca77c33f15e67a26e0ceeb95a3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 16 Jan 2016 18:47:45 +0100 Subject: Add a lint to warn about call to `.*or(foo(..))` --- README.md | 3 ++- src/lib.rs | 1 + src/methods.rs | 61 +++++++++++++++++++++++++++++++++++++++++-- src/utils.rs | 2 +- tests/compile-fail/methods.rs | 27 +++++++++++++++++++ 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 631c1d7f1d2..29644a14fc4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 92 lints included in this crate: +There are 93 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -63,6 +63,7 @@ name [option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` [option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[or_fun_call](https://github.com/Manishearth/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method when the `*or_else` would do [out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing [panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught diff --git a/src/lib.rs b/src/lib.rs index 9bb59693795..4e13ba5c458 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -194,6 +194,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, + methods::OR_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::STR_TO_STRING, diff --git a/src/methods.rs b/src/methods.rs index 83b9e60f4be..ff91759be23 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -4,6 +4,7 @@ use rustc::middle::ty; use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; +use syntax::ptr::P; use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty}; @@ -170,6 +171,25 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, "using an iterator search followed by `is_some()`, which is more succinctly \ expressed as a call to `any()`"); +/// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and +/// suggests to use `or_else`, `unwrap_or_else`, etc., instead. +/// +/// **Why is this bad?** The function will always be called and potentially allocate an object +/// in expressions such as: +/// ```rust +/// foo.unwrap_or(String::new()) +/// ``` +/// this can instead be written: +/// ```rust +/// foo.unwrap_or_else(String::new) +/// ``` +/// +/// **Known problems:** If the function as side-effects, not calling it will change the semantic of +/// the program, but you shouldn't rely on that anyway. The will won't catch +/// `foo.unwrap_or(vec![])`. +declare_lint!(pub OR_FUN_CALL, Warn, + "using any `*or` method when the `*or_else` would do"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_UNWRAP_USED, @@ -181,13 +201,15 @@ impl LintPass for MethodsPass { WRONG_PUB_SELF_CONVENTION, OK_EXPECT, OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE) + OPTION_MAP_UNWRAP_OR_ELSE, + OR_FUN_CALL) } } impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(_, _, _) = expr.node { + if let ExprMethodCall(name, _, ref args) = expr.node { + // Chain calls if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { lint_unwrap(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { @@ -207,6 +229,8 @@ impl LateLintPass for MethodsPass { } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); } + + lint_or_fun_call(cx, expr, &name.node.as_str(), &args); } } @@ -258,6 +282,39 @@ impl LateLintPass for MethodsPass { } } +/// Checks for the `OR_FUN_CALL` lint. +fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { + if args.len() == 2 && ["map_or", "ok_or", "or", "unwrap_or"].contains(&name) { + let self_ty = cx.tcx.expr_ty(&args[0]); + + let is_result = if match_type(cx, self_ty, &RESULT_PATH) { + true + } + else if match_type(cx, self_ty, &OPTION_PATH) { + false + } + else { + return; + }; + + if let ExprCall(ref fun, ref or_args) = args[1].node { + let sugg = match (is_result, or_args.is_empty()) { + (true, _) => format!("|_| {}", snippet(cx, args[1].span, "..")), + (false, false) => format!("|| {}", snippet(cx, args[1].span, "..")), + (false, true) => format!("{}", snippet(cx, fun.span, "..")), + }; + + span_lint(cx, OR_FUN_CALL, expr.span, + &format!("use of `{}` followed by a function call", name)) + .span_suggestion(expr.span, "try this", + format!("{}.{}_else({})", + snippet(cx, args[0].span, "_"), + name, + sugg)); + } + } +} + #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `unwrap()` for `Option`s and `Result`s diff --git a/src/utils.rs b/src/utils.rs index 312cf77d068..4b144452063 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -244,7 +244,7 @@ pub fn is_from_for_desugar(decl: &Decl) -> bool { /// snippet(cx, expr.span, "..") /// ``` pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) + cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default)) } /// Convert a span to a code snippet. Returns `None` if not available. diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index b41b28dc11e..570715db6af 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -175,6 +175,33 @@ fn search_is_some() { let _ = foo.rposition().is_some(); } +/// Checks implementation of the OR_FUN_CALL lint +fn or_fun_call() { + let foo = Some(vec![1]); + foo.unwrap_or(Vec::new()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION foo.unwrap_or_else(Vec::new); + + let bar = Some(vec![1]); + bar.unwrap_or(Vec::with_capacity(12)); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION bar.unwrap_or_else(|| Vec::with_capacity(12)); + + let baz : Result<_, ()> = Ok(vec![1]); + baz.unwrap_or(Vec::new()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION baz.unwrap_or_else(|_| Vec::new()); + + let qux : Result<_, ()> = Ok(vec![1]); + qux.unwrap_or(Vec::with_capacity(12)); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION qux.unwrap_or_else(|_| Vec::with_capacity(12)); +} + fn main() { use std::io; -- cgit 1.4.1-3-g733a5 From 7e85db645e35061d11897c049715c845fb4cf073 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Sun, 17 Jan 2016 17:53:41 +0100 Subject: Fix another false positive in lifetime elision lint The false positive occurred when we have an anonymous input lifetime and a named output lifetime. This is not elidable, because if we elided the output lifetime, it would be inferred to be the same as the input. --- src/lifetimes.rs | 1 - tests/compile-fail/lifetimes.rs | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 1edd75a45aa..83da3d8644a 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -144,7 +144,6 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> match (&input_lts[0], &output_lts[0]) { (&Named(n1), &Named(n2)) if n1 == n2 => true, (&Named(_), &Unnamed) => true, - (&Unnamed, &Named(_)) => true, _ => false, // already elided, different named lifetimes // or something static going on } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index 99c16917426..eb161af9dc3 100644 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -119,5 +119,9 @@ fn alias_with_lt3<'a>(_foo: &FooAlias<'a> ) -> &'a str { unimplemented!() } // no warning, two input lifetimes fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b> ) -> &'a str { unimplemented!() } +fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } //~ERROR explicit lifetimes given + +fn elided_input_named_output<'a>(_arg: &str) -> &'a str { unimplemented!() } + fn main() { } -- cgit 1.4.1-3-g733a5 From 90cbc858e983e302d97f2bd72be7af9a94def51a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 13:09:46 +0100 Subject: Fix spelling mistake --- src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index 171ba6f27f0..36191993474 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -484,7 +484,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { if let Some(&PathResolution { base_def: DefConst(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { maybe_id = Some(id); } - // separate if lets to avoid doubleborrowing the defmap + // separate if lets to avoid double borrowing the def_map if let Some(id) = maybe_id { if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None) { let ret = self.expr(const_expr); -- cgit 1.4.1-3-g733a5 From fb6b3bed0fc5701287035fc9c445a202e492a0d8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 13:10:13 +0100 Subject: Add utility functions to check for trait impl --- src/utils.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 4b144452063..c41c0a8681b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,20 +1,20 @@ -use rustc::lint::*; -use rustc_front::hir::*; +use consts::constant; use reexport::*; -use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use rustc::front::map::Node::*; +use rustc::lint::*; use rustc::middle::def_id::DefId; -use rustc::middle::ty; +use rustc::middle::{cstore, def, infer, ty, traits}; +use rustc::session::Session; +use rustc_front::hir::*; use std::borrow::Cow; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::str::FromStr; use syntax::ast::Lit_::*; use syntax::ast; +use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; -use consts::constant; - -use rustc::session::Session; -use std::str::FromStr; -use std::ops::{Deref, DerefMut}; pub type MethodArgs = HirVec<P<Expr>>; @@ -23,6 +23,7 @@ pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; @@ -132,7 +133,7 @@ pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { } } -/// Check if the method call given in `expr` belongs to given trait. +/// Check if the method call given in `expr` belongs to given type. pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { let method_call = ty::MethodCall::expr(expr.id); @@ -186,6 +187,73 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) } +/// Get the definition associated to a path. +/// TODO: investigate if there is something more efficient for that. +pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { + let cstore = &cx.tcx.sess.cstore; + + let crates = cstore.crates(); + let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); + if let Some(krate) = krate { + let mut items = cstore.crate_top_level_items(*krate); + let mut path_it = path.iter().skip(1).peekable(); + + loop { + let segment = match path_it.next() { + Some(segment) => segment, + None => return None + }; + + for item in &mem::replace(&mut items, vec![]) { + if item.name.as_str() == *segment { + if path_it.peek().is_none() { + return Some(item.def); + } + + let def_id = match item.def { + cstore::DefLike::DlDef(def) => def.def_id(), + cstore::DefLike::DlImpl(def_id) => def_id, + _ => panic!("Unexpected {:?}", item.def), + }; + + items = cstore.item_children(def_id); + break; + } + } + } + } + else { + None + } +} + +/// Convenience function to get the `DefId` of a trait by path. +pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { + let def = match path_to_def(cx, path) { + Some(def) => def, + None => return None, + }; + + match def { + cstore::DlDef(def::DefTrait(trait_id)) => Some(trait_id), + _ => None, + } +} + +/// Check whether a type implements a trait. +/// See also `get_trait_def_id`. +pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId) -> bool { + cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); + + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, true); + let obligation = traits::predicate_for_trait_def(cx.tcx, + traits::ObligationCause::dummy(), + trait_id, 0, ty, + vec![]); + + traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) +} + /// Match an `Expr` against a chain of methods, and return the matched `Expr`s. /// /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -- cgit 1.4.1-3-g733a5 From b5f65ec699c8a89155c4aa214cf2510030a88a6d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 13:11:07 +0100 Subject: Improve OR_FUN_CALL to suggest unwrap_or_default --- src/methods.rs | 105 ++++++++++++++++++++++++++++++++++-------- tests/compile-fail/methods.rs | 50 +++++++++++++++----- 2 files changed, 123 insertions(+), 32 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index ff91759be23..b5ce82f1a43 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -5,11 +5,13 @@ use rustc::middle::subst::{Subst, TypeSpace}; use std::iter; use std::borrow::Cow; use syntax::ptr::P; +use syntax::codemap::Span; use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, match_trait_method, - walk_ptrs_ty_depth, walk_ptrs_ty}; -use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH}; + walk_ptrs_ty_depth, walk_ptrs_ty, get_trait_def_id, implements_trait}; +use utils::{DEFAULT_TRAIT_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH}; use utils::MethodArgs; +use rustc::middle::cstore::CrateStore; use self::SelfKind::*; use self::OutType::*; @@ -172,7 +174,7 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, expressed as a call to `any()`"); /// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and -/// suggests to use `or_else`, `unwrap_or_else`, etc., instead. +/// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead. /// /// **Why is this bad?** The function will always be called and potentially allocate an object /// in expressions such as: @@ -183,10 +185,13 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, /// ```rust /// foo.unwrap_or_else(String::new) /// ``` +/// or +/// ```rust +/// foo.unwrap_or_default() +/// ``` /// /// **Known problems:** If the function as side-effects, not calling it will change the semantic of -/// the program, but you shouldn't rely on that anyway. The will won't catch -/// `foo.unwrap_or(vec![])`. +/// the program, but you shouldn't rely on that anyway. declare_lint!(pub OR_FUN_CALL, Warn, "using any `*or` method when the `*or_else` would do"); @@ -284,8 +289,61 @@ impl LateLintPass for MethodsPass { /// Checks for the `OR_FUN_CALL` lint. fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { - if args.len() == 2 && ["map_or", "ok_or", "or", "unwrap_or"].contains(&name) { - let self_ty = cx.tcx.expr_ty(&args[0]); + /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. + fn check_unwrap_or_default( + cx: &LateContext, + name: &str, + fun: &Expr, + self_expr: &Expr, + arg: &Expr, + or_has_args: bool, + span: Span + ) -> bool { + if or_has_args { + return false; + } + + if name == "unwrap_or" { + if let ExprPath(_, ref path) = fun.node { + let path : &str = &path.segments.last() + .expect("A path must have at least one segment") + .identifier.name.as_str(); + + if ["default", "new"].contains(&path) { + let arg_ty = cx.tcx.expr_ty(arg); + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { + default_trait_id + } + else { + return false; + }; + + if implements_trait(cx, arg_ty, default_trait_id) { + span_lint(cx, OR_FUN_CALL, span, + &format!("use of `{}` followed by a call to `{}`", name, path)) + .span_suggestion(span, "try this", + format!("{}.unwrap_or_default()", + snippet(cx, self_expr.span, "_"))); + return true; + } + } + } + } + + false + } + + /// Check for `*or(foo())`. + fn check_general_case( + cx: &LateContext, + name: &str, + fun: &Expr, + self_expr: &Expr, + arg: &Expr, + or_has_args: bool, + span: Span + ) { + let self_ty = cx.tcx.expr_ty(self_expr); let is_result = if match_type(cx, self_ty, &RESULT_PATH) { true @@ -297,20 +355,27 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) return; }; + let sugg = match (is_result, !or_has_args) { + (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")), + (false, false) => format!("|| {}", snippet(cx, arg.span, "..")), + (false, true) => format!("{}", snippet(cx, fun.span, "..")), + }; + + span_lint(cx, OR_FUN_CALL, span, + &format!("use of `{}` followed by a function call", name)) + .span_suggestion(span, "try this", + format!("{}.{}_else({})", + snippet(cx, self_expr.span, "_"), + name, + sugg)); + } + + if args.len() == 2 && ["map_or", "ok_or", "or", "unwrap_or"].contains(&name) { if let ExprCall(ref fun, ref or_args) = args[1].node { - let sugg = match (is_result, or_args.is_empty()) { - (true, _) => format!("|_| {}", snippet(cx, args[1].span, "..")), - (false, false) => format!("|| {}", snippet(cx, args[1].span, "..")), - (false, true) => format!("{}", snippet(cx, fun.span, "..")), - }; - - span_lint(cx, OR_FUN_CALL, expr.span, - &format!("use of `{}` followed by a function call", name)) - .span_suggestion(expr.span, "try this", - format!("{}.{}_else({})", - snippet(cx, args[0].span, "_"), - name, - sugg)); + let or_has_args = !or_args.is_empty(); + if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { + check_general_case(cx, name, fun, &args[0], &args[1], or_has_args, expr.span); + } } } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 570715db6af..d357fb0a54a 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -177,29 +177,55 @@ fn search_is_some() { /// Checks implementation of the OR_FUN_CALL lint fn or_fun_call() { - let foo = Some(vec![1]); - foo.unwrap_or(Vec::new()); + fn make<T>() -> T { unimplemented!(); } + + let with_constructor = Some(vec![1]); + with_constructor.unwrap_or(make()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION with_constructor.unwrap_or_else(make) + + let with_new = Some(vec![1]); + with_new.unwrap_or(Vec::new()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION with_new.unwrap_or_default(); + + let with_const_args = Some(vec![1]); + with_const_args.unwrap_or(Vec::with_capacity(12)); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION with_const_args.unwrap_or_else(|| Vec::with_capacity(12)); + + let with_err : Result<_, ()> = Ok(vec![1]); + with_err.unwrap_or(make()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION with_err.unwrap_or_else(|_| make()); + + let with_err_args : Result<_, ()> = Ok(vec![1]); + with_err_args.unwrap_or(Vec::with_capacity(12)); //~^ERROR use of `unwrap_or` //~|HELP try this - //~|SUGGESTION foo.unwrap_or_else(Vec::new); + //~|SUGGESTION with_err_args.unwrap_or_else(|_| Vec::with_capacity(12)); - let bar = Some(vec![1]); - bar.unwrap_or(Vec::with_capacity(12)); + let with_default_trait = Some(1); + with_default_trait.unwrap_or(Default::default()); //~^ERROR use of `unwrap_or` //~|HELP try this - //~|SUGGESTION bar.unwrap_or_else(|| Vec::with_capacity(12)); + //~|SUGGESTION with_default_trait.unwrap_or_default(); - let baz : Result<_, ()> = Ok(vec![1]); - baz.unwrap_or(Vec::new()); + let with_default_type = Some(1); + with_default_type.unwrap_or(u64::default()); //~^ERROR use of `unwrap_or` //~|HELP try this - //~|SUGGESTION baz.unwrap_or_else(|_| Vec::new()); + //~|SUGGESTION with_default_type.unwrap_or_default(); - let qux : Result<_, ()> = Ok(vec![1]); - qux.unwrap_or(Vec::with_capacity(12)); + let with_vec = Some(vec![1]); + with_vec.unwrap_or(vec![]); //~^ERROR use of `unwrap_or` //~|HELP try this - //~|SUGGESTION qux.unwrap_or_else(|_| Vec::with_capacity(12)); + //~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); } fn main() { -- cgit 1.4.1-3-g733a5 From 21ba3151025c4438a16ee110d99b9d6a525c695f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 13:27:42 +0100 Subject: Update to rustc 1.7.0-nightly (d0bac3f14 2016-01-18) --- src/bit_mask.rs | 2 +- src/consts.rs | 2 +- src/escape.rs | 2 +- src/utils.rs | 2 +- tests/compile-fail/needless_features.rs | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index c2fd3742066..0e98f5a93a9 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -278,7 +278,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { _ => None, } } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None, None)) .and_then(|l| fetch_int_literal(cx, l)) } _ => None, diff --git a/src/consts.rs b/src/consts.rs index 36191993474..7b022947719 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -486,7 +486,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } // separate if lets to avoid double borrowing the def_map if let Some(id) = maybe_id { - if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None) { + if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None, None) { let ret = self.expr(const_expr); if ret.is_some() { self.needed_resolution = true; diff --git a/src/escape.rs b/src/escape.rs index 079fdcf09a0..3e59a801f68 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -45,7 +45,7 @@ impl LintPass for EscapePass { impl LateLintPass for EscapePass { fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env), false); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env)); let mut v = EscapeDelegate { cx: cx, set: NodeSet(), diff --git a/src/utils.rs b/src/utils.rs index c41c0a8681b..446303f8bb1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -245,7 +245,7 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId) -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, true); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); let obligation = traits::predicate_for_trait_def(cx.tcx, traits::ObligationCause::dummy(), trait_id, 0, ty, diff --git a/tests/compile-fail/needless_features.rs b/tests/compile-fail/needless_features.rs index dee2a19d5d0..c5c82c7072b 100644 --- a/tests/compile-fail/needless_features.rs +++ b/tests/compile-fail/needless_features.rs @@ -1,5 +1,4 @@ #![feature(plugin)] -#![feature(convert)] #![plugin(clippy)] #![deny(clippy)] -- cgit 1.4.1-3-g733a5 From 8642306f090f2f91c89d5cb992b3085ec0f39699 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 13:36:58 +0100 Subject: Add a test for the OR_FUN_CALL lint --- tests/compile-fail/methods.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index d357fb0a54a..f8642cb3ed8 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -177,6 +177,12 @@ fn search_is_some() { /// Checks implementation of the OR_FUN_CALL lint fn or_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Foo { Foo } + } + fn make<T>() -> T { unimplemented!(); } let with_constructor = Some(vec![1]); @@ -226,6 +232,12 @@ fn or_fun_call() { //~^ERROR use of `unwrap_or` //~|HELP try this //~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); + + let without_default = Some(Foo); + without_default.unwrap_or(Foo::new()); + //~^ERROR use of `unwrap_or` + //~|HELP try this + //~|SUGGESTION without_default.unwrap_or_else(Foo::new); } fn main() { -- cgit 1.4.1-3-g733a5 From 28b043735468936cc23b4cc7a4ce5ed3246524c8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 18 Jan 2016 18:58:00 +0530 Subject: bump cargo --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index db5944ab9b4..4cdc1bd9be4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.35" +version = "0.0.36" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 3713fd3dce39e94fb5903554300df1db63a5c422 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 15:35:50 +0100 Subject: Check types in the CMP_OWNED lint --- src/methods.rs | 2 +- src/misc.rs | 29 ++++++++++++++++++++--------- src/utils.rs | 4 ++-- tests/compile-fail/cmp_owned.rs | 2 ++ 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index b5ce82f1a43..254b68deb11 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -318,7 +318,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) return false; }; - if implements_trait(cx, arg_ty, default_trait_id) { + if implements_trait(cx, arg_ty, default_trait_id, None) { span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a call to `{}`", name, path)) .span_suggestion(span, "try this", diff --git a/src/misc.rs b/src/misc.rs index a8fabaa3fcf..52234fd61af 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -11,7 +11,7 @@ use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; -use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal}; +use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_trait}; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. /// @@ -210,18 +210,18 @@ impl LateLintPass for CmpOwned { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if is_comparison_binop(cmp.node) { - check_to_owned(cx, left, right.span, true, cmp.span); - check_to_owned(cx, right, left.span, false, cmp.span) + check_to_owned(cx, left, right, true, cmp.span); + check_to_owned(cx, right, left, false, cmp.span) } } } } -fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, op: Span) { - let snip = match expr.node { +fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) { + let (arg_ty, snip) = match expr.node { ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) if args.len() == 1 => { if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { - snippet(cx, args[0].span, "..") + (cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) } else { return; } @@ -229,7 +229,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o ExprCall(ref path, ref v) if v.len() == 1 => { if let ExprPath(None, ref path) = path.node { if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { - snippet(cx, v[0].span, "..") + (cx.tcx.expr_ty(&v[0]), snippet(cx, v[0].span, "..")) } else { return; } @@ -239,6 +239,17 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o } _ => return, }; + + let other_ty = cx.tcx.expr_ty(other); + let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() { + Some(id) => id, + None => return, + }; + + if !implements_trait(cx, arg_ty, partial_eq_trait_id, Some(vec![other_ty])) { + return; + } + if left { span_lint(cx, CMP_OWNED, @@ -247,14 +258,14 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span, left: bool, o compare without allocation", snip, snippet(cx, op, "=="), - snippet(cx, other_span, ".."))); + snippet(cx, other.span, ".."))); } else { span_lint(cx, CMP_OWNED, expr.span, &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ compare without allocation", - snippet(cx, other_span, ".."), + snippet(cx, other.span, ".."), snippet(cx, op, "=="), snip)); } diff --git a/src/utils.rs b/src/utils.rs index 446303f8bb1..65a7bc86031 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -242,14 +242,14 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { /// Check whether a type implements a trait. /// See also `get_trait_def_id`. -pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId) -> bool { +pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, ty_params: Option<Vec<ty::Ty<'tcx>>>) -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); let obligation = traits::predicate_for_trait_def(cx.tcx, traits::ObligationCause::dummy(), trait_id, 0, ty, - vec![]); + ty_params.unwrap_or_default()); traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) } diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index afca83e1d32..c4c9ee60fab 100644 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -21,4 +21,6 @@ fn main() { // as of 2015-08-14 x != String::from("foo"); //~ERROR this creates an owned instance + + 42.to_string() == "42"; } -- cgit 1.4.1-3-g733a5 From 9d5e9cfd97e69ddef1e25562ecd4d351e655ae17 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 18 Jan 2016 19:28:06 +0100 Subject: Fix redundant_closure false positive --- src/eta_reduction.rs | 5 +++-- tests/compile-fail/eta.rs | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 46c458c6bcb..fcc1a6893b2 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -45,6 +45,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { // || {foo(); bar()}; can't be reduced here return; } + if let Some(ref ex) = blk.expr { if let ExprCall(ref caller, ref args) = ex.node { if args.len() != decl.inputs.len() { @@ -52,8 +53,8 @@ fn check_closure(cx: &LateContext, expr: &Expr) { // is no way the closure is the same as the function return; } - if args.iter().any(|arg| is_adjusted(cx, arg)) { - // Are the arguments type-adjusted? Then we need the closure + if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { + // Are the expression or the arguments type-adjusted? Then we need the closure return; } let fn_ty = cx.tcx.expr_ty(caller); diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index a51d116d9cc..1ffca9ac5ce 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -21,6 +21,10 @@ fn main() { unsafe { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } + + // See #515 + let a: Option<Box<::std::ops::Deref<Target = [i32]>>> = + Some(vec![1i32, 2]).map(|v| -> Box<::std::ops::Deref<Target = [i32]>> { Box::new(v) }); } fn meta<F>(f: F) where F: Fn(u8) { -- cgit 1.4.1-3-g733a5 From 6a4d77aa32a5a0c80264fa7d385707c4e1e45ffd Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Tue, 19 Jan 2016 13:53:49 +0100 Subject: Fix deprecation warning on latest nightly --- src/lib.rs | 2 +- src/types.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4e13ba5c458..6c60d403e1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] -#![feature(num_bits_bytes, iter_arith)] +#![feature(iter_arith)] #![feature(custom_attribute)] #![allow(unknown_lints)] diff --git a/src/types.rs b/src/types.rs index 6289e13c85a..427b695d385 100644 --- a/src/types.rs +++ b/src/types.rs @@ -209,7 +209,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { }; // n == 4 is the usize/isize case if n == 4 { - ::std::usize::BITS + ::std::mem::size_of::<usize>() * 8 } else { n } -- cgit 1.4.1-3-g733a5 From 01eda52cb5c2d3a787b2c6e81f3c699370525387 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Tue, 19 Jan 2016 19:14:49 +0100 Subject: Add lint for "string literal".as_bytes() --- README.md | 3 ++- src/lib.rs | 2 ++ src/strings.rs | 49 +++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/strings.rs | 8 +++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 29644a14fc4..f76157a249d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 93 lints included in this crate: +There are 94 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -83,6 +83,7 @@ name [str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. diff --git a/src/lib.rs b/src/lib.rs index 6c60d403e1c..76d9426b25a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,6 +135,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); reg.register_late_lint_pass(box panic::PanicPass); + reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_lint_group("clippy_pedantic", vec![ @@ -225,6 +226,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_ZIP_WITH_LEN, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + strings::STRING_LIT_AS_BYTES, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, types::BOX_VEC, diff --git a/src/strings.rs b/src/strings.rs index 55d1a0acf68..c32289f84fd 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -48,6 +48,22 @@ declare_lint! { "using `x + ..` where x is a `String`; suggests using `push_str()` instead" } +/// **What it does:** This lint matches the `as_bytes` method called on string +/// literals that contain only ascii characters. It is `Warn` by default. +/// +/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used instead. They are shorter but less discoverable than `as_bytes()`. +/// +/// **Example:** +/// +/// ``` +/// let bs = "a byte string".as_bytes(); +/// ``` +declare_lint! { + pub STRING_LIT_AS_BYTES, + Warn, + "calling `as_bytes` on a string literal; suggests using a byte string literal instead" +} + #[derive(Copy, Clone)] pub struct StringAdd; @@ -104,3 +120,36 @@ fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { _ => false, } } + +#[derive(Copy, Clone)] +pub struct StringLitAsBytes; + +impl LintPass for StringLitAsBytes { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_LIT_AS_BYTES) + } +} + +impl LateLintPass for StringLitAsBytes { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use std::ascii::AsciiExt; + use syntax::ast::Lit_::LitStr; + use utils::snippet; + + if let ExprMethodCall(ref name, _, ref args) = e.node { + if name.node.as_str() == "as_bytes" { + if let ExprLit(ref lit) = args[0].node { + if let LitStr(ref lit_content, _) = lit.node { + if lit_content.chars().all(|c| c.is_ascii()) { + let msg = format!("calling `as_bytes()` on a string literal. \ + Consider using a byte string literal instead: \ + `b{}`", + snippet(cx, args[0].span, r#""foo""#)); + span_lint(cx, STRING_LIT_AS_BYTES, e.span, &msg); + } + } + } + } + } + } +} diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 1ba8616ed29..7ed93737ffa 100644 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -44,6 +44,14 @@ fn both() { assert_eq!(&x, &z); } +#[allow(dead_code, unused_variables)] +#[deny(string_lit_as_bytes)] +fn str_lit_as_bytes() { + let bs = "hello there".as_bytes(); //~ERROR calling `as_bytes()` + // no warning, because this cannot be written as a byte string literal: + let ubs = "☃".as_bytes(); +} + fn main() { add_only(); add_assign_only(); -- cgit 1.4.1-3-g733a5 From ea26ae3888bd10046e723ef0c2939605cd57bb6c Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Tue, 19 Jan 2016 19:43:29 +0100 Subject: Add macro check --- src/strings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index c32289f84fd..16ee08b1894 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -134,13 +134,13 @@ impl LateLintPass for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { use std::ascii::AsciiExt; use syntax::ast::Lit_::LitStr; - use utils::snippet; + use utils::{snippet, in_macro}; if let ExprMethodCall(ref name, _, ref args) = e.node { if name.node.as_str() == "as_bytes" { if let ExprLit(ref lit) = args[0].node { if let LitStr(ref lit_content, _) = lit.node { - if lit_content.chars().all(|c| c.is_ascii()) { + if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, e.span) { let msg = format!("calling `as_bytes()` on a string literal. \ Consider using a byte string literal instead: \ `b{}`", -- cgit 1.4.1-3-g733a5 From 5ac6659814f6605628618ef79cc994df7c6a049b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 20 Jan 2016 00:53:26 +0100 Subject: Handle Entry types in OR_FUN_CALL lint --- src/methods.rs | 40 ++++++++++++++++++++++++++++------------ src/utils.rs | 2 ++ tests/compile-fail/methods.rs | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 254b68deb11..7be2e0ee1d8 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -9,7 +9,10 @@ use syntax::codemap::Span; use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty, get_trait_def_id, implements_trait}; -use utils::{DEFAULT_TRAIT_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH}; +use utils::{ + BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, + RESULT_PATH, STRING_PATH +}; use utils::MethodArgs; use rustc::middle::cstore::CrateStore; @@ -343,19 +346,31 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) or_has_args: bool, span: Span ) { + // (path, fn_has_argument, methods) + let know_types : &[(&[_], _, &[_], _)] = &[ + (&BTREEMAP_ENTRY_PATH, false, &["or_insert"], "with"), + (&HASHMAP_ENTRY_PATH, false, &["or_insert"], "with"), + (&OPTION_PATH, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), + (&RESULT_PATH, true, &["or", "unwrap_or"], "else"), + ]; + let self_ty = cx.tcx.expr_ty(self_expr); - let is_result = if match_type(cx, self_ty, &RESULT_PATH) { - true - } - else if match_type(cx, self_ty, &OPTION_PATH) { - false + let (fn_has_arguments, poss, suffix) = + if let Some(&(_, fn_has_arguments, poss, suffix)) = know_types.iter().find(|&&i| { + match_type(cx, self_ty, i.0) + }) { + (fn_has_arguments, poss, suffix) + } + else { + return + }; + + if !poss.contains(&name) { + return } - else { - return; - }; - let sugg = match (is_result, !or_has_args) { + let sugg = match (fn_has_arguments, !or_has_args) { (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")), (false, false) => format!("|| {}", snippet(cx, arg.span, "..")), (false, true) => format!("{}", snippet(cx, fun.span, "..")), @@ -364,13 +379,14 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) .span_suggestion(span, "try this", - format!("{}.{}_else({})", + format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, + suffix, sugg)); } - if args.len() == 2 && ["map_or", "ok_or", "or", "unwrap_or"].contains(&name) { + if args.len() == 2 { if let ExprCall(ref fun, ref or_args) = args[1].node { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { diff --git a/src/utils.rs b/src/utils.rs index 65a7bc86031..97d0d2ecf11 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,10 +20,12 @@ pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; +pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index f8642cb3ed8..1e2e881c308 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -4,6 +4,8 @@ #![allow(unused)] #![deny(clippy, clippy_pedantic)] +use std::collections::BTreeMap; +use std::collections::HashMap; use std::ops::Mul; struct T; @@ -238,6 +240,18 @@ fn or_fun_call() { //~^ERROR use of `unwrap_or` //~|HELP try this //~|SUGGESTION without_default.unwrap_or_else(Foo::new); + + let mut map = HashMap::<u64, String>::new(); + map.entry(42).or_insert(String::new()); + //~^ERROR use of `or_insert` followed by a function call + //~|HELP try this + //~|SUGGESTION map.entry(42).or_insert_with(String::new); + + let mut btree = BTreeMap::<u64, String>::new(); + btree.entry(42).or_insert(String::new()); + //~^ERROR use of `or_insert` followed by a function call + //~|HELP try this + //~|SUGGESTION btree.entry(42).or_insert_with(String::new); } fn main() { -- cgit 1.4.1-3-g733a5 From 91ff1db5bc51c8513038ce510b182b7cd75de9d4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 20 Jan 2016 02:23:39 +0100 Subject: Add a lint for starts_with --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 112 ++++++++++++++++++++++++++++++++---------- src/misc.rs | 9 ++-- tests/compile-fail/methods.rs | 12 +++++ 5 files changed, 105 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index f76157a249d..ba257ce43a1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 94 lints included in this crate: +There are 95 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -20,6 +20,7 @@ name [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` [cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` diff --git a/src/lib.rs b/src/lib.rs index 76d9426b25a..1a4501ffce6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -191,6 +191,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, matches::SINGLE_MATCH, + methods::CHARS_NEXT_CMP, methods::FILTER_NEXT, methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, diff --git a/src/methods.rs b/src/methods.rs index 7be2e0ee1d8..3f57f8189c3 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -7,11 +7,14 @@ use std::borrow::Cow; use syntax::ptr::P; use syntax::codemap::Span; -use utils::{snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, match_trait_method, - walk_ptrs_ty_depth, walk_ptrs_ty, get_trait_def_id, implements_trait}; use utils::{ - BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, - RESULT_PATH, STRING_PATH + snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, + match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty, get_trait_def_id, implements_trait, + span_lint_and_then +}; +use utils::{ + BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, + STRING_PATH }; use utils::MethodArgs; use rustc::middle::cstore::CrateStore; @@ -176,6 +179,17 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, "using an iterator search followed by `is_some()`, which is more succinctly \ expressed as a call to `any()`"); +/// **What it does:** This lint `Warn`s on using `.chars().next()` on a `str` to check if it +/// starts with a given char. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.starts_with(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `name.chars().next() == Some('_')` +declare_lint!(pub CHARS_NEXT_CMP, Warn, + "using `.chars().next()` to check if a string starts with a char"); + /// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and /// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead. /// @@ -210,35 +224,44 @@ impl LintPass for MethodsPass { OK_EXPECT, OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE, - OR_FUN_CALL) + OR_FUN_CALL, + CHARS_NEXT_CMP) } } impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(name, _, ref args) = expr.node { - // Chain calls - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - lint_unwrap(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { - lint_to_string(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { - lint_ok_expect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { - lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { - lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { - lint_filter_next(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { - lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { - lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { - lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); - } + match expr.node { + ExprMethodCall(name, _, ref args) => { + // Chain calls + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + lint_unwrap(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { + lint_to_string(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { + lint_ok_expect(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { + lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { + lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { + lint_filter_next(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { + lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { + lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { + lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); + } - lint_or_fun_call(cx, expr, &name.node.as_str(), &args); + lint_or_fun_call(cx, expr, &name.node.as_str(), &args); + } + ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { + if !lint_chars_next(cx, expr, lhs, rhs, op.node == BiEq) { + lint_chars_next(cx, expr, rhs, lhs, op.node == BiEq); + } + } + _ => (), } } @@ -570,6 +593,41 @@ fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, searc } } +/// Checks for the `CHARS_NEXT_CMP` lint. +fn lint_chars_next(cx: &LateContext, expr: &Expr, chain: &Expr, other: &Expr, eq: bool) -> bool { + if_let_chain! {[ + let Some(args) = method_chain_args(chain, &["chars", "next"]), + let ExprCall(ref fun, ref arg_char) = other.node, + arg_char.len() == 1, + let ExprPath(None, ref path) = fun.node, + path.segments.len() == 1 && path.segments[0].identifier.name.as_str() == "Some" + ], { + let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0])); + + if self_ty.sty != ty::TyStr { + return false; + } + + span_lint_and_then(cx, + CHARS_NEXT_CMP, + expr.span, + "you should use the `starts_with` method", + |db| { + let sugg = format!("{}{}.starts_with({})", + if eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + snippet(cx, arg_char[0].span, "_") + ); + + db.span_suggestion(expr.span, "like this", sugg); + }); + + return true; + }} + + false +} + // Given a `Result<T, E>` type, return its error type (`E`) fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { diff --git a/src/misc.rs b/src/misc.rs index 52234fd61af..4b6170cf164 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -389,13 +389,14 @@ impl LateLintPass for UsedUnderscoreBinding { .last() .expect("path should always have at least one segment") .identifier; - ident.name.as_str().chars().next() == Some('_') && // starts with '_' - ident.name.as_str().chars().skip(1).next() != Some('_') && // doesn't start with "__" - ident.name != ident.unhygienic_name && is_used(cx, expr) // not in bang macro + ident.name.as_str().starts_with('_') && + !ident.name.as_str().starts_with("__") && + ident.name != ident.unhygienic_name && + is_used(cx, expr) // not in bang macro } ExprField(_, spanned) => { let name = spanned.node.as_str(); - name.chars().next() == Some('_') && name.chars().skip(1).next() != Some('_') + name.starts_with('_') && !name.starts_with("__") } _ => false, }; diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 1e2e881c308..535e8cc4a26 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -292,3 +292,15 @@ struct MyError(()); // doesn't implement Debug struct MyErrorWithParam<T> { x: T } + +fn starts_with() { + "".chars().next() == Some(' '); + //~^ ERROR starts_with + //~| HELP like this + //~| SUGGESTION "".starts_with(' ') + + Some(' ') != "".chars().next(); + //~^ ERROR starts_with + //~| HELP like this + //~| SUGGESTION !"".starts_with(' ') +} -- cgit 1.4.1-3-g733a5 From 7a26cfc991c1d8e60def820d133df39e30e105fd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 20 Jan 2016 18:32:17 +0100 Subject: Add macro checks in src/methods.rs lints --- src/methods.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 3f57f8189c3..6338961b56b 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -8,9 +8,9 @@ use syntax::ptr::P; use syntax::codemap::Span; use utils::{ - snippet, span_lint, span_note_and_lint, match_path, match_type, method_chain_args, - match_trait_method, walk_ptrs_ty_depth, walk_ptrs_ty, get_trait_def_id, implements_trait, - span_lint_and_then + get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, + match_trait_method, match_type, method_chain_args, snippet, span_lint, span_lint_and_then, + span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, }; use utils::{ BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, @@ -231,6 +231,10 @@ impl LintPass for MethodsPass { impl LateLintPass for MethodsPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_macro(cx, expr.span) { + return; + } + match expr.node { ExprMethodCall(name, _, ref args) => { // Chain calls @@ -266,6 +270,10 @@ impl LateLintPass for MethodsPass { } fn check_item(&mut self, cx: &LateContext, item: &Item) { + if in_external_macro(cx, item.span) { + return; + } + if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { for implitem in items { let name = implitem.name; -- cgit 1.4.1-3-g733a5 From c6c0edb19b755aeeb7ab37aba4e43d0fbd28a916 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 21 Jan 2016 18:19:02 +0100 Subject: Add a lint about deriving Hash and implementing PartialEq --- README.md | 3 +- src/derive.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/utils.rs | 1 + tests/compile-fail/derive.rs | 29 +++++++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/derive.rs create mode 100755 tests/compile-fail/derive.rs diff --git a/README.md b/README.md index ba257ce43a1..c45acf4af77 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 95 lints included in this crate: +There are 96 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -26,6 +26,7 @@ name [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver +[derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) diff --git a/src/derive.rs b/src/derive.rs new file mode 100644 index 00000000000..6306bb8f09d --- /dev/null +++ b/src/derive.rs @@ -0,0 +1,98 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::ast::{Attribute, MetaItem_}; +use utils::{match_path, span_lint_and_then}; +use utils::HASH_PATH; + +use rustc::middle::ty::fast_reject::simplify_type; + +/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` +/// explicitely. +/// +/// **Why is this bad?** The implementation of these traits must agree (for example for use with +/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation with +/// an explicitely defined `PartialEq`. In particular, the following must hold for any type: +/// +/// ```rust +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// #[derive(Hash)] +/// struct Foo; +/// +/// impl PartialEq for Foo { +/// .. +/// } +declare_lint! { + pub DERIVE_HASH_NOT_EQ, + Warn, + "deriving `Hash` but implementing `PartialEq` explicitly" +} + +pub struct Derive; + +impl LintPass for Derive { + fn get_lints(&self) -> LintArray { + lint_array!(DERIVE_HASH_NOT_EQ) + } +} + +impl LateLintPass for Derive { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + /// A `#[derive]`d implementation has a `#[automatically_derived]` attribute. + fn is_automatically_derived(attr: &Attribute) -> bool { + if let MetaItem_::MetaWord(ref word) = attr.node.value.node { + word == &"automatically_derived" + } + else { + false + } + } + + // If `item` is an automatically derived `Hash` implementation + if_let_chain! {[ + let ItemImpl(_, _, _, Some(ref trait_ref), ref ast_ty, _) = item.node, + match_path(&trait_ref.path, &HASH_PATH), + item.attrs.iter().any(is_automatically_derived), + let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() + ], { + let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); + + cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id); + let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1; + let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + + + // Look for the PartialEq implementations for `ty` + if_let_chain! {[ + let Some(ty) = ast_ty_to_ty_cache.get(&ast_ty.id), + let Some(simpl_ty) = simplify_type(cx.tcx, ty, false), + let Some(impl_ids) = peq_impls.get(&simpl_ty) + ], { + for &impl_id in impl_ids { + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialEq<Foo> for Foo` + if trait_ref.input_types()[0] == *ty && + !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) { + span_lint_and_then( + cx, DERIVE_HASH_NOT_EQ, item.span, + &format!("you are deriving `Hash` but have implemented \ + `PartialEq` explicitely"), |db| { + if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { + db.span_note( + cx.tcx.map.span(node_id), + "`PartialEq` implemented here" + ); + } + }); + } + } + }} + }} + } +} diff --git a/src/lib.rs b/src/lib.rs index 1a4501ffce6..4a832cc7b89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,7 @@ pub mod entry; pub mod misc_early; pub mod array_indexing; pub mod panic; +pub mod derive; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -136,6 +137,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box array_indexing::ArrayIndexing); reg.register_late_lint_pass(box panic::PanicPass); reg.register_late_lint_pass(box strings::StringLitAsBytes); + reg.register_late_lint_pass(box derive::Derive); reg.register_lint_group("clippy_pedantic", vec![ @@ -168,6 +170,7 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + derive::DERIVE_HASH_NOT_EQ, entry::MAP_ENTRY, eq_op::EQ_OP, escape::BOXED_LOCAL, diff --git a/src/utils.rs b/src/utils.rs index 97d0d2ecf11..c5483997f90 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,6 +27,7 @@ pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs new file mode 100755 index 00000000000..a879be28292 --- /dev/null +++ b/tests/compile-fail/derive.rs @@ -0,0 +1,29 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(warnings)] + +#[derive(PartialEq, Hash)] +struct Foo; + +impl PartialEq<u64> for Foo { + fn eq(&self, _: &u64) -> bool { true } +} + +#[derive(Hash)] +//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitely +struct Bar; + +impl PartialEq for Bar { + fn eq(&self, _: &Bar) -> bool { true } +} + +#[derive(Hash)] +//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitely +struct Baz; + +impl PartialEq<Baz> for Baz { + fn eq(&self, _: &Baz) -> bool { true } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From c86a5ccd2ee3165690386faad06ffdb4f4b59187 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 22 Jan 2016 17:54:44 +0530 Subject: Upgrade Rust to rustc 1.8.0-nightly (18b851bc5 2016-01-22) fixes #573 --- Cargo.toml | 2 +- src/bit_mask.rs | 4 ++-- src/consts.rs | 4 ++-- src/escape.rs | 4 ++-- src/lifetimes.rs | 6 +++--- src/loops.rs | 4 ++-- src/no_effect.rs | 6 +++--- src/ptr_arg.rs | 4 ++-- src/shadow.rs | 4 ++-- src/utils.rs | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4cdc1bd9be4..36b95ebe30f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.36" +version = "0.0.37" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 0e98f5a93a9..6c6d277e25b 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::*; +use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; use syntax::codemap::Span; @@ -274,7 +274,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { // borrowing. let def_map = cx.tcx.def_map.borrow(); match def_map.get(&lit.id) { - Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), + Some(&PathResolution { base_def: Def::Const(def_id), ..}) => Some(def_id), _ => None, } } diff --git a/src/consts.rs b/src/consts.rs index 7b022947719..34f7e924de7 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -3,7 +3,7 @@ use rustc::lint::LateContext; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution; -use rustc::middle::def::Def::*; +use rustc::middle::def::Def; use rustc_front::hir::*; use syntax::ptr::P; use std::char; @@ -481,7 +481,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { if let Some(lcx) = self.lcx { let mut maybe_id = None; - if let Some(&PathResolution { base_def: DefConst(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { + if let Some(&PathResolution { base_def: Def::Const(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { maybe_id = Some(id); } // separate if lets to avoid double borrowing the def_map diff --git a/src/escape.rs b/src/escape.rs index 70151054e95..32dbbb99226 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,7 +1,7 @@ use rustc::lint::*; +use rustc::front::map::Node::NodeStmt; use rustc_front::hir::*; use rustc_front::intravisit as visit; -use rustc::front::map::Node; use rustc::middle::ty; use rustc::middle::ty::adjustment::AutoAdjustment; use rustc::middle::expr_use_visitor::*; @@ -91,7 +91,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { return; } if let Categorization::Rvalue(..) = cmt.cat { - if let Some(Node::NodeStmt(st)) = self.cx + if let Some(NodeStmt(st)) = self.cx .tcx .map .find(self.cx.tcx.map.get_parent_node(cmt.id)) { diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 83da3d8644a..b83ac390edf 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -3,7 +3,7 @@ use reexport::*; use rustc::lint::*; use syntax::codemap::Span; use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; -use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct}; +use rustc::middle::def::Def; use std::collections::{HashSet, HashMap}; use utils::{in_external_macro, span_lint}; @@ -206,13 +206,13 @@ impl<'v, 't> RefVisitor<'v, 't> { if params.lifetimes.is_empty() { if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { match def { - DefTy(def_id, _) | DefStruct(def_id) => { + Def::TyAlias(def_id) | Def::Struct(def_id) => { let type_scheme = self.cx.tcx.lookup_item_type(def_id); for _ in type_scheme.generics.regions.as_slice() { self.record(&None); } } - DefTrait(def_id) => { + Def::Trait(def_id) => { let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; for _ in &trait_def.generics.regions { self.record(&None); diff --git a/src/loops.rs b/src/loops.rs index 614b561749f..699e6e525da 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -3,7 +3,7 @@ use rustc_front::hir::*; use reexport::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use rustc::middle::ty; -use rustc::middle::def::DefLocal; +use rustc::middle::def::Def; use consts::{constant_simple, Constant}; use rustc::front::map::Node::NodeBlock; use std::borrow::Cow; @@ -768,7 +768,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { - if let DefLocal(_, node_id) = path_res.base_def { + if let Def::Local(_, node_id) = path_res.base_def { return Some(node_id); } } diff --git a/src/no_effect.rs b/src/no_effect.rs index 3b2d91fc78e..075b9b62800 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::middle::def::{DefStruct, DefVariant}; +use rustc::middle::def::Def; use rustc_front::hir::{Expr, ExprCall, ExprLit, ExprPath, ExprStruct}; use rustc_front::hir::{Stmt, StmtSemi}; @@ -36,8 +36,8 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { ExprCall(ref callee, ref args) => { let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); match def { - Some(DefStruct(..)) | - Some(DefVariant(..)) => args.iter().all(|arg| has_no_effect(cx, arg)), + Some(Def::Struct(..)) | + Some(Def::Variant(..)) => args.iter().all(|arg| has_no_effect(cx, arg)), _ => false, } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 2e1e16cf22b..75ce96f6350 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -4,8 +4,8 @@ use rustc::lint::*; use rustc_front::hir::*; +use rustc::front::map::NodeItem; use rustc::middle::ty; -use rustc::front::map::Node; use utils::{span_lint, match_type}; use utils::{STRING_PATH, VEC_PATH}; @@ -42,7 +42,7 @@ impl LateLintPass for PtrArg { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let ImplItemKind::Method(ref sig, _) = item.node { - if let Some(Node::NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { + if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { if let ItemImpl(_, _, _, Some(_), _, _) = it.node { return; // ignore trait impls } diff --git a/src/shadow.rs b/src/shadow.rs index 2d3e423eacb..1c445f42b55 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -5,7 +5,7 @@ use syntax::codemap::Span; use rustc_front::intravisit::{Visitor, FnKind}; use rustc::lint::*; -use rustc::middle::def::Def::{DefVariant, DefStruct}; +use rustc::middle::def::Def; use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; @@ -103,7 +103,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { fn is_binding(cx: &LateContext, pat: &Pat) -> bool { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { - Some(DefVariant(..)) | Some(DefStruct(..)) => false, + Some(Def::Variant(..)) | Some(Def::Struct(..)) => false, _ => true, } } diff --git a/src/utils.rs b/src/utils.rs index 446303f8bb1..323f0592d97 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -235,7 +235,7 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { }; match def { - cstore::DlDef(def::DefTrait(trait_id)) => Some(trait_id), + cstore::DlDef(def::Def::Trait(trait_id)) => Some(trait_id), _ => None, } } -- cgit 1.4.1-3-g733a5 From 5dd042487749d9c2f2adaa6ae84d930fdee6c46a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 22 Jan 2016 18:39:40 +0530 Subject: un-wildcard stuff --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 36b95ebe30f..b74db8f95ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ semver = "0.2.1" [dev-dependencies] compiletest_rs = "0.0.11" -regex = "*" -regex_macros = "*" -lazy_static = "*" +regex = "0.1.47" +regex_macros = "0.1.27" +lazy_static = "0.1.15" rustc-serialize = "0.3" [features] -- cgit 1.4.1-3-g733a5 From 2a51f8d2becadffee4eeb96937d14060889178cc Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <rust19446194516@oli-obk.de> Date: Sun, 24 Jan 2016 10:16:56 +0100 Subject: lint on items following statements --- README.md | 3 +- src/items_after_statements.rs | 62 ++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/mut_mut.rs | 8 ++-- tests/compile-fail/cmp_owned.rs | 5 ++- tests/compile-fail/item_after_statement.rs | 9 +++++ 6 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 src/items_after_statements.rs create mode 100644 tests/compile-fail/item_after_statement.rs diff --git a/README.md b/README.md index c45acf4af77..5848759c2b8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 96 lints included in this crate: +There are 97 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -37,6 +37,7 @@ name [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs new file mode 100644 index 00000000000..5f109dac058 --- /dev/null +++ b/src/items_after_statements.rs @@ -0,0 +1,62 @@ +//! lint when items are used after statements + +use rustc::lint::*; +use syntax::attr::*; +use syntax::ast::*; +use utils::in_macro; + +/// **What it does:** It `Warn`s on blocks where there are items that are declared in the middle of or after the statements +/// +/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are processed in order. This might cause confusion as it's hard to figure out which item is meant in a statement. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// fn foo() { +/// println!("cake"); +/// } +/// fn main() { +/// foo(); // prints "foo" +/// fn foo() { +/// println!("foo"); +/// } +/// foo(); // prints "foo" +/// } +declare_lint! { pub ITEMS_AFTER_STATEMENTS, Warn, "finds blocks where an item comes after a statement" } + +pub struct ItemsAfterStatemets; + +impl LintPass for ItemsAfterStatemets { + fn get_lints(&self) -> LintArray { + lint_array!(ITEMS_AFTER_STATEMENTS) + } +} + +impl EarlyLintPass for ItemsAfterStatemets { + fn check_block(&mut self, cx: &EarlyContext, item: &Block) { + if in_macro(cx, item.span) { + return; + } + let mut stmts = item.stmts.iter().map(|stmt| &stmt.node); + // skip initial items + while let Some(&StmtDecl(ref decl, _)) = stmts.next() { + if let DeclLocal(_) = decl.node { + break; + } + } + // lint on all further items + for stmt in stmts { + if let StmtDecl(ref decl, _) = *stmt { + if let DeclItem(ref it) = decl.node { + if in_macro(cx, it.span) { + return; + } + cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, it.span, + "adding items after statements is confusing, since items exist from the start of the scope") + .emit(); + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 4a832cc7b89..cd69ac23c19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,7 @@ pub mod needless_bool; pub mod approx_const; pub mod eta_reduction; pub mod identity_op; +pub mod items_after_statements; pub mod minmax; pub mod mut_mut; pub mod mut_reference; @@ -97,6 +98,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box precedence::Precedence); reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); + reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatemets); reg.register_late_lint_pass(box mut_mut::MutMut); reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); reg.register_late_lint_pass(box len_zero::LenZero); @@ -176,6 +178,7 @@ pub fn plugin_registrar(reg: &mut Registry) { escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, identity_op::IDENTITY_OP, + items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 1bdb4e9a3d6..4623ca38533 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -37,10 +37,6 @@ impl LateLintPass for MutMut { } fn check_expr_mut(cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { - return; - } - fn unwrap_addr(expr: &Expr) -> Option<&Expr> { match expr.node { ExprAddrOf(MutMutable, ref e) => Some(e), @@ -48,6 +44,10 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { } } + if in_external_macro(cx, expr.span) { + return; + } + unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map_or_else(|| { if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = cx.tcx.expr_ty(e).sty { diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index c4c9ee60fab..c06949eb01a 100644 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -3,8 +3,6 @@ #[deny(cmp_owned)] fn main() { - let x = "oh"; - #[allow(str_to_string)] fn with_to_string(x : &str) { x != "foo".to_string(); @@ -13,6 +11,9 @@ fn main() { "foo".to_string() != x; //~^ ERROR this creates an owned instance just for comparison. Consider using `"foo" != x` to compare without allocation } + + let x = "oh"; + with_to_string(x); x != "foo".to_owned(); //~ERROR this creates an owned instance diff --git a/tests/compile-fail/item_after_statement.rs b/tests/compile-fail/item_after_statement.rs new file mode 100644 index 00000000000..f104081faa9 --- /dev/null +++ b/tests/compile-fail/item_after_statement.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(items_after_statements)] + +fn main() { + foo(); + fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing + foo(); +} -- cgit 1.4.1-3-g733a5 From 8ef0b86fab63cb548eb640f6fcebd8c5c9e451f0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 24 Jan 2016 13:56:23 +0100 Subject: Lint explicit Clone implementations on Copy type --- README.md | 3 +- src/derive.rs | 167 ++++++++++++++++++++++++++++++++----------- src/lib.rs | 1 + src/utils.rs | 3 +- tests/compile-fail/derive.rs | 43 ++++++++++- 5 files changed, 170 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 5848759c2b8..83ff6daa9f5 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 97 lints included in this crate: +There are 98 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -30,6 +30,7 @@ name [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` diff --git a/src/derive.rs b/src/derive.rs index 6306bb8f09d..b1c0bde40a2 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,13 +1,15 @@ use rustc::lint::*; +use rustc::middle::ty::fast_reject::simplify_type; +use rustc::middle::ty; use rustc_front::hir::*; use syntax::ast::{Attribute, MetaItem_}; +use syntax::codemap::Span; +use utils::{CLONE_TRAIT_PATH, HASH_PATH}; use utils::{match_path, span_lint_and_then}; -use utils::HASH_PATH; - -use rustc::middle::ty::fast_reject::simplify_type; +use rustc::middle::ty::TypeVariants; /// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` -/// explicitely. +/// explicitly. /// /// **Why is this bad?** The implementation of these traits must agree (for example for use with /// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation with @@ -33,66 +35,145 @@ declare_lint! { "deriving `Hash` but implementing `PartialEq` explicitly" } +/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types. +/// +/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour +/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone` +/// implementation that does nothing more than copy the object, which is what +/// `#[derive(Copy, Clone)]` gets you. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// #[derive(Copy)] +/// struct Foo; +/// +/// impl Clone for Foo { +/// .. +/// } +declare_lint! { + pub EXPL_IMPL_CLONE_ON_COPY, + Warn, + "implementing `Clone` explicitly on `Copy` types" +} + pub struct Derive; impl LintPass for Derive { fn get_lints(&self) -> LintArray { - lint_array!(DERIVE_HASH_NOT_EQ) + lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_NOT_EQ) } } impl LateLintPass for Derive { fn check_item(&mut self, cx: &LateContext, item: &Item) { - /// A `#[derive]`d implementation has a `#[automatically_derived]` attribute. - fn is_automatically_derived(attr: &Attribute) -> bool { - if let MetaItem_::MetaWord(ref word) = attr.node.value.node { - word == &"automatically_derived" + let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + + if_let_chain! {[ + let ItemImpl(_, _, _, Some(ref trait_ref), ref ast_ty, _) = item.node, + let Some(&ty) = ast_ty_to_ty_cache.get(&ast_ty.id) + ], { + if item.attrs.iter().any(is_automatically_derived) { + check_hash_peq(cx, item.span, trait_ref, ty); } else { - false + check_copy_clone(cx, item.span, trait_ref, ty); } - } + }} + } +} - // If `item` is an automatically derived `Hash` implementation +/// Implementation of the `DERIVE_HASH_NOT_EQ` lint. +fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty) { + // If `item` is an automatically derived `Hash` implementation + if_let_chain! {[ + match_path(&trait_ref.path, &HASH_PATH), + let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() + ], { + let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); + + cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id); + let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1; + + // Look for the PartialEq implementations for `ty` if_let_chain! {[ - let ItemImpl(_, _, _, Some(ref trait_ref), ref ast_ty, _) = item.node, - match_path(&trait_ref.path, &HASH_PATH), - item.attrs.iter().any(is_automatically_derived), - let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() + let Some(simpl_ty) = simplify_type(cx.tcx, ty, false), + let Some(impl_ids) = peq_impls.get(&simpl_ty) ], { - let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); + for &impl_id in impl_ids { + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id); - let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1; - let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + // Only care about `impl PartialEq<Foo> for Foo` + if trait_ref.input_types()[0] == ty && + !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) { + span_lint_and_then( + cx, DERIVE_HASH_NOT_EQ, span, + "you are deriving `Hash` but have implemented `PartialEq` explicitly", + |db| { + if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { + db.span_note( + cx.tcx.map.span(node_id), + "`PartialEq` implemented here" + ); + } + }); + } + } + }} + }} +} +/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { + if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) { + let parameter_environment = cx.tcx.empty_parameter_environment(); - // Look for the PartialEq implementations for `ty` - if_let_chain! {[ - let Some(ty) = ast_ty_to_ty_cache.get(&ast_ty.id), - let Some(simpl_ty) = simplify_type(cx.tcx, ty, false), - let Some(impl_ids) = peq_impls.get(&simpl_ty) - ], { - for &impl_id in impl_ids { - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + if ty.moves_by_default(¶meter_environment, span) { + return; // ty is not Copy + } - // Only care about `impl PartialEq<Foo> for Foo` - if trait_ref.input_types()[0] == *ty && - !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) { - span_lint_and_then( - cx, DERIVE_HASH_NOT_EQ, item.span, - &format!("you are deriving `Hash` but have implemented \ - `PartialEq` explicitely"), |db| { - if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { - db.span_note( - cx.tcx.map.span(node_id), - "`PartialEq` implemented here" - ); + // Some types are not Clone by default but could be cloned `by hand` if necessary + match ty.sty { + TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => { + for variant in &def.variants { + for field in &variant.fields { + match field.ty(cx.tcx, substs).sty { + TypeVariants::TyArray(_, size) if size > 32 => { + return; } - }); + TypeVariants::TyBareFn(..) => { + return; + } + TypeVariants::TyTuple(ref tys) if tys.len() > 12 => { + return; + } + _ => (), + } } } - }} - }} + } + _ => (), + } + + span_lint_and_then( + cx, DERIVE_HASH_NOT_EQ, span, + "you are implementing `Clone` explicitly on a `Copy` type", + |db| { + db.span_note( + span, + "consider deriving `Clone` or removing `Copy`" + ); + }); + } +} + +/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have. +fn is_automatically_derived(attr: &Attribute) -> bool { + if let MetaItem_::MetaWord(ref word) = attr.node.value.node { + word == &"automatically_derived" + } + else { + false } } diff --git a/src/lib.rs b/src/lib.rs index cd69ac23c19..c43c01268fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -173,6 +173,7 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_NOT_EQ, + derive::EXPL_IMPL_CLONE_ON_COPY, entry::MAP_ENTRY, eq_op::EQ_OP, escape::BOXED_LOCAL, diff --git a/src/utils.rs b/src/utils.rs index 7b9866d8530..139e94dbc91 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -22,7 +22,8 @@ pub type MethodArgs = HirVec<P<Expr>>; pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; -pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"]; +pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; +pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs index a879be28292..66b04a66d0f 100755 --- a/tests/compile-fail/derive.rs +++ b/tests/compile-fail/derive.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![deny(warnings)] +#![allow(dead_code)] #[derive(PartialEq, Hash)] struct Foo; @@ -11,7 +12,7 @@ impl PartialEq<u64> for Foo { } #[derive(Hash)] -//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitely +//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitly struct Bar; impl PartialEq for Bar { @@ -19,11 +20,49 @@ impl PartialEq for Bar { } #[derive(Hash)] -//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitely +//~^ ERROR you are deriving `Hash` but have implemented `PartialEq` explicitly struct Baz; impl PartialEq<Baz> for Baz { fn eq(&self, _: &Baz) -> bool { true } } +#[derive(Copy)] +struct Qux; + +impl Clone for Qux { +//~^ ERROR you are implementing `Clone` explicitly on a `Copy` type + fn clone(&self) -> Self { Qux } +} + +// Ok, `Clone` cannot be derived because of the big array +#[derive(Copy)] +struct BigArray { + a: [u8; 65], +} + +impl Clone for BigArray { + fn clone(&self) -> Self { unimplemented!() } +} + +// Ok, function pointers are not always Clone +#[derive(Copy)] +struct FnPtr { + a: fn() -> !, +} + +impl Clone for FnPtr { + fn clone(&self) -> Self { unimplemented!() } +} + +// Ok, generics +#[derive(Copy)] +struct Generic<T> { + a: T, +} + +impl<T> Clone for Generic<T> { + fn clone(&self) -> Self { unimplemented!() } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From ed96583677a955e4dcd935e35031e434ac9ea5e5 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 25 Jan 2016 14:02:47 +0100 Subject: extend_from_slice lint --- README.md | 3 ++- src/lib.rs | 1 + src/methods.rs | 46 +++++++++++++++++++++++++++++++++++++++++-- tests/compile-fail/methods.rs | 7 +++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 83ff6daa9f5..290684d3bad 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 98 lints included in this crate: +There are 99 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -33,6 +33,7 @@ name [expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` diff --git a/src/lib.rs b/src/lib.rs index c43c01268fe..f44191b562d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,6 +199,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::CHARS_NEXT_CMP, + methods::EXTEND_FROM_SLICE, methods::FILTER_NEXT, methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, diff --git a/src/methods.rs b/src/methods.rs index 6338961b56b..0f09d67485a 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -14,7 +14,7 @@ use utils::{ }; use utils::{ BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, - STRING_PATH + STRING_PATH, VEC_PATH, }; use utils::MethodArgs; use rustc::middle::cstore::CrateStore; @@ -212,9 +212,20 @@ declare_lint!(pub CHARS_NEXT_CMP, Warn, declare_lint!(pub OR_FUN_CALL, Warn, "using any `*or` method when the `*or_else` would do"); +/// **What it does:** This lint `Warn`s on using `.extend(s)` on a `vec` to extend the vec by a slice. +/// +/// **Why is this bad?** Since Rust 1.6, the `extend_from_slice(_)` method is stable and at least for now faster. +/// +/// **Known problems:** None. +/// +/// **Example:** `my_vec.extend(&xs)` +declare_lint!(pub EXTEND_FROM_SLICE, Warn, + "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, + lint_array!(EXTEND_FROM_SLICE, + OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING, @@ -256,6 +267,8 @@ impl LateLintPass for MethodsPass { lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { + lint_extend(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &name.node.as_str(), &args); @@ -427,6 +440,35 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } } +fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); + let arg_ty = cx.tcx.expr_ty(&args[1]); + + if !match_type(cx, obj_ty, &VEC_PATH) { + return; // for your Vecs only + } + + if derefs_to_slice(&arg_ty) { + span_lint(cx, EXTEND_FROM_SLICE, expr.span, + &format!("use of `extend` to extend a Vec by a slice")) + .span_suggestion(expr.span, "try this", + format!("{}.extend_from_slice({})", + snippet(cx, args[0].span, "_"), + snippet(cx, args[1].span, "_"))); + } +} + +fn derefs_to_slice(ty: &ty::Ty) -> bool { + match ty.sty { + ty::TySlice(_) | + ty::TyStr => true, + ty::TyBox(ref inner) => derefs_to_slice(inner), + ty::TyArray(_, size) => size < 32, + ty::TyRef(_, ty::TypeAndMut { ty: ref t, .. }) => derefs_to_slice(t), + _ => false + } +} + #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `unwrap()` for `Option`s and `Result`s diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 535e8cc4a26..64b31b75597 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -304,3 +304,10 @@ fn starts_with() { //~| HELP like this //~| SUGGESTION !"".starts_with(' ') } + +fn use_extend_from_slice() { + let mut v : Vec<&'static str> = vec![]; + v.extend(&["Hello", "World"]); //~ERROR use of `extend` + + +} -- cgit 1.4.1-3-g733a5 From 2d97f916ebdcb53f22b65e8142382c9624079297 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 25 Jan 2016 19:46:56 +0100 Subject: added more test, now works with vecs and iter --- src/methods.rs | 16 ++++++++++------ tests/compile-fail/methods.rs | 7 +++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 0f09d67485a..5377dd1bc52 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -448,7 +448,7 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { return; // for your Vecs only } - if derefs_to_slice(&arg_ty) { + if derefs_to_slice(cx, &args[1], &arg_ty) { span_lint(cx, EXTEND_FROM_SLICE, expr.span, &format!("use of `extend` to extend a Vec by a slice")) .span_suggestion(expr.span, "try this", @@ -458,13 +458,17 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } } -fn derefs_to_slice(ty: &ty::Ty) -> bool { +fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> bool { + if let ExprMethodCall(name, _, ref args) = expr.node { + return &name.node.as_str() == &"iter" && + derefs_to_slice(cx, &args[0], &cx.tcx.expr_ty(&args[0])) + } match ty.sty { - ty::TySlice(_) | - ty::TyStr => true, - ty::TyBox(ref inner) => derefs_to_slice(inner), + ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), + ty::TySlice(_) => true, ty::TyArray(_, size) => size < 32, - ty::TyRef(_, ty::TypeAndMut { ty: ref t, .. }) => derefs_to_slice(t), + ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | + ty::TyBox(ref inner) => derefs_to_slice(cx, expr, inner), _ => false } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 64b31b75597..752427847f3 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -308,6 +308,9 @@ fn starts_with() { fn use_extend_from_slice() { let mut v : Vec<&'static str> = vec![]; v.extend(&["Hello", "World"]); //~ERROR use of `extend` - - + v.extend(vec!["Some", "more"]); //~ERROR use of `extend` + v.extend(vec!["And", "even", "more"].iter()); //~ERROR use of `extend` + let o : Option<&'static str> = None; + v.extend(o); + v.extend(Some("Bye")); } -- cgit 1.4.1-3-g733a5 From d152e5c683165b9ba43de1e65aadd08f137d999d Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 26 Jan 2016 23:51:06 +0100 Subject: fixed argument check --- src/methods.rs | 22 ++++++++++++++-------- tests/compile-fail/methods.rs | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 5377dd1bc52..f1021c839cd 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -442,12 +442,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - let arg_ty = cx.tcx.expr_ty(&args[1]); - if !match_type(cx, obj_ty, &VEC_PATH) { - return; // for your Vecs only + return; } - + let arg_ty = cx.tcx.expr_ty(&args[1]); if derefs_to_slice(cx, &args[1], &arg_ty) { span_lint(cx, EXTEND_FROM_SLICE, expr.span, &format!("use of `extend` to extend a Vec by a slice")) @@ -459,16 +457,24 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> bool { + fn may_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> bool { + match ty.sty { + ty::TySlice(_) => true, + ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), + ty::TyArray(_, size) => size < 32, + ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | + ty::TyBox(ref inner) => may_slice(cx, expr, inner), + _ => false + } + } if let ExprMethodCall(name, _, ref args) = expr.node { return &name.node.as_str() == &"iter" && - derefs_to_slice(cx, &args[0], &cx.tcx.expr_ty(&args[0])) + may_slice(cx, &args[0], &cx.tcx.expr_ty(&args[0])) } match ty.sty { - ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), ty::TySlice(_) => true, - ty::TyArray(_, size) => size < 32, ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => derefs_to_slice(cx, expr, inner), + ty::TyBox(ref inner) => may_slice(cx, expr, inner), _ => false } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 752427847f3..3156a38cdeb 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -308,9 +308,10 @@ fn starts_with() { fn use_extend_from_slice() { let mut v : Vec<&'static str> = vec![]; v.extend(&["Hello", "World"]); //~ERROR use of `extend` - v.extend(vec!["Some", "more"]); //~ERROR use of `extend` + v.extend(&vec!["Some", "more"]); //~ERROR use of `extend` v.extend(vec!["And", "even", "more"].iter()); //~ERROR use of `extend` let o : Option<&'static str> = None; v.extend(o); v.extend(Some("Bye")); + v.extend(vec!["Not", "like", "this"]); } -- cgit 1.4.1-3-g733a5 From 5d5e50d67edd071aa82035435d522577bd03b2d8 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 27 Jan 2016 14:51:30 +0100 Subject: fixed suggestion for iter case --- src/methods.rs | 36 ++++++++++++++++++++++-------------- tests/compile-fail/methods.rs | 1 + 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index f1021c839cd..a5f27440f94 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -446,36 +446,44 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { return; } let arg_ty = cx.tcx.expr_ty(&args[1]); - if derefs_to_slice(cx, &args[1], &arg_ty) { + if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { span_lint(cx, EXTEND_FROM_SLICE, expr.span, &format!("use of `extend` to extend a Vec by a slice")) .span_suggestion(expr.span, "try this", - format!("{}.extend_from_slice({})", + format!("{}.extend_from_slice({}{})", snippet(cx, args[0].span, "_"), - snippet(cx, args[1].span, "_"))); + r, snippet(cx, span, "_"))); } } -fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> bool { - fn may_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> bool { +fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) + -> Option<(Span, &'static str)> { + fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { ty::TySlice(_) => true, ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), ty::TyArray(_, size) => size < 32, ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => may_slice(cx, expr, inner), + ty::TyBox(ref inner) => may_slice(cx, inner), _ => false } } if let ExprMethodCall(name, _, ref args) = expr.node { - return &name.node.as_str() == &"iter" && - may_slice(cx, &args[0], &cx.tcx.expr_ty(&args[0])) - } - match ty.sty { - ty::TySlice(_) => true, - ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => may_slice(cx, expr, inner), - _ => false + if &name.node.as_str() == &"iter" && + may_slice(cx, &cx.tcx.expr_ty(&args[0])) { + Some((args[0].span, "&")) + } else { + None + } + } else { + match ty.sty { + ty::TySlice(_) => Some((expr.span, "")), + ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | + ty::TyBox(ref inner) => if may_slice(cx, inner) { + Some((expr.span, "")) + } else { None }, + _ => None + } } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 3156a38cdeb..5172aa9e9df 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -314,4 +314,5 @@ fn use_extend_from_slice() { v.extend(o); v.extend(Some("Bye")); v.extend(vec!["Not", "like", "this"]); + v.extend(["Nor", "this"].iter()); } -- cgit 1.4.1-3-g733a5 From a1ac3125de6ae7cb0ffffd845df28b3ba3872a19 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Wed, 27 Jan 2016 20:13:15 +0100 Subject: fixed and extended tests --- tests/compile-fail/methods.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 5172aa9e9df..c72e602ac2b 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -308,11 +308,18 @@ fn starts_with() { fn use_extend_from_slice() { let mut v : Vec<&'static str> = vec![]; v.extend(&["Hello", "World"]); //~ERROR use of `extend` - v.extend(&vec!["Some", "more"]); //~ERROR use of `extend` + v.extend(&vec!["Some", "more"]); + //~^ERROR use of `extend` + //~| HELP try this + //~| SUGGESTION v.extend_from_slice(&vec!["Some", "more"]); + v.extend(vec!["And", "even", "more"].iter()); //~ERROR use of `extend` let o : Option<&'static str> = None; v.extend(o); v.extend(Some("Bye")); v.extend(vec!["Not", "like", "this"]); - v.extend(["Nor", "this"].iter()); + v.extend(["But", "this"].iter()); + //~^ERROR use of `extend + //~| HELP try this + //~| SUGGESTION v.extend_from_slice(&["But", "this"]); } -- cgit 1.4.1-3-g733a5 From 04f9d35f64b0a08a6ea2ff6ce8ceab358526cade Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 27 Jan 2016 20:23:59 +0100 Subject: Add a lint for casts from char literals to u8 --- src/lib.rs | 1 + src/types.rs | 38 ++++++++++++++++++++++++++++++++++++ tests/compile-fail/char_lit_as_u8.rs | 8 ++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/compile-fail/char_lit_as_u8.rs diff --git a/src/lib.rs b/src/lib.rs index c43c01268fe..731778db606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box panic::PanicPass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); + reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_lint_group("clippy_pedantic", vec![ diff --git a/src/types.rs b/src/types.rs index 427b695d385..42824c36ec6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -517,3 +517,41 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { self.nest -= sub_nest; } } + +/// **What it does:** This lint points out expressions where a character literal is casted to u8 and suggests using a byte literal instead. +/// +/// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`. +/// +/// **Known problems:** None +/// +/// **Example:** `'x' as u8` +declare_lint!(pub CHAR_LIT_AS_U8, Warn, + "Casting a character literal to u8"); + +pub struct CharLitAsU8; + +impl LintPass for CharLitAsU8 { + fn get_lints(&self) -> LintArray { + lint_array!(CHAR_LIT_AS_U8) + } +} + +impl LateLintPass for CharLitAsU8 { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + use syntax::ast::{Lit_, UintTy}; + + if let ExprCast(ref e, _) = expr.node { + if let ExprLit(ref l) = e.node { + if let Lit_::LitChar(_) = l.node { + if ty::TyUint(UintTy::TyU8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { + let msg = "casting character literal to u8."; + let help = format!("Consider using a byte literal \ + instead:\nb{}", + snippet(cx, e.span, "'x'")); + span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help); + } + } + } + } + } +} diff --git a/tests/compile-fail/char_lit_as_u8.rs b/tests/compile-fail/char_lit_as_u8.rs new file mode 100644 index 00000000000..4fca878c4da --- /dev/null +++ b/tests/compile-fail/char_lit_as_u8.rs @@ -0,0 +1,8 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(char_lit_as_u8)] +#![allow(unused_variables)] +fn main() { + let c = 'a' as u8; //~ERROR casting character literal +} -- cgit 1.4.1-3-g733a5 From 23dfb2fbc0e10150ec00053406d372321a09bbd6 Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 27 Jan 2016 20:59:19 +0100 Subject: Make update_lints script accept digits in lint names --- README.md | 3 ++- src/lib.rs | 1 + util/update_lints.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83ff6daa9f5..63ecbf11fcf 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 98 lints included in this crate: +There are 99 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -20,6 +20,7 @@ name [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` [cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8 [chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` diff --git a/src/lib.rs b/src/lib.rs index 731778db606..b0cf4d46972 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -239,6 +239,7 @@ pub fn plugin_registrar(reg: &mut Registry) { temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, types::BOX_VEC, + types::CHAR_LIT_AS_U8, types::LET_UNIT_VALUE, types::LINKEDLIST, types::TYPE_COMPLEXITY, diff --git a/util/update_lints.py b/util/update_lints.py index 94b2a3a57ba..6a59abcdc15 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -9,7 +9,7 @@ import sys declare_lint_re = re.compile(r''' declare_lint! \s* [{(] \s* - pub \s+ (?P<name>[A-Z_]+) \s*,\s* + pub \s+ (?P<name>[A-Z_][A-Z_0-9]*) \s*,\s* (?P<level>Forbid|Deny|Warn|Allow) \s*,\s* " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] ''', re.X | re.S) -- cgit 1.4.1-3-g733a5 From cee96fab39299449f877c3db997d1cf421abc8af Mon Sep 17 00:00:00 2001 From: Florian Hartwig <florian.j.hartwig@gmail.com> Date: Wed, 27 Jan 2016 21:10:35 +0100 Subject: Point out that char is 32 bit value --- src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 42824c36ec6..d41896cd490 100644 --- a/src/types.rs +++ b/src/types.rs @@ -544,7 +544,9 @@ impl LateLintPass for CharLitAsU8 { if let ExprLit(ref l) = e.node { if let Lit_::LitChar(_) = l.node { if ty::TyUint(UintTy::TyU8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { - let msg = "casting character literal to u8."; + let msg = "casting character literal to u8. `char`s \ + are 4 bytes wide in rust, so casting to u8 \ + truncates them"; let help = format!("Consider using a byte literal \ instead:\nb{}", snippet(cx, e.span, "'x'")); -- cgit 1.4.1-3-g733a5 From da93643357128faf432d2d03c29d87e81084dce2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 28 Jan 2016 19:29:59 +0100 Subject: Add a lint to warn about use of `print{,ln}!` --- README.md | 3 ++- src/lib.rs | 4 ++++ src/print.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 27 +++++++++++++++++++++++++ tests/compile-fail/print.rs | 11 ++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/print.rs create mode 100755 tests/compile-fail/print.rs diff --git a/README.md b/README.md index 04b0bd0e384..2673d81f808 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 100 lints included in this crate: +There are 101 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -73,6 +73,7 @@ name [out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing [panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught +[print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout [ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator [range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do diff --git a/src/lib.rs b/src/lib.rs index 6d706888fc3..8b115a304e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ // this only exists to allow the "dogfood" integration test to work #[allow(dead_code)] +#[allow(print_stdout)] fn main() { println!("What are you doing? Don't run clippy as an executable"); } @@ -77,6 +78,7 @@ pub mod misc_early; pub mod array_indexing; pub mod panic; pub mod derive; +pub mod print; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -141,6 +143,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); + reg.register_late_lint_pass(box print::PrintLint); reg.register_lint_group("clippy_pedantic", vec![ @@ -149,6 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::WRONG_PUB_SELF_CONVENTION, mut_mut::MUT_MUT, mutex_atomic::MUTEX_INTEGER, + print::PRINT_STDOUT, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, diff --git a/src/print.rs b/src/print.rs new file mode 100644 index 00000000000..a47fa69b2e8 --- /dev/null +++ b/src/print.rs @@ -0,0 +1,49 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::{IO_PRINT_PATH, is_expn_of, match_path, span_lint}; + +/// **What it does:** This lint warns whenever you print on *stdout*. This lint is `Allow` by +/// default, the purpose is to catch debugging remnants. +/// +/// **Why is this bad?** People often print on *stdout* while debugging an application and might +/// forget to remove those prints afterward. +/// +/// **Known problems:** Only catches `print!` and `println!` calls. +/// +/// **Example:** `println!("Hello world!");` +declare_lint! { + pub PRINT_STDOUT, + Allow, + "printing on stdout" +} + +#[derive(Copy, Clone, Debug)] +pub struct PrintLint; + +impl LintPass for PrintLint { + fn get_lints(&self) -> LintArray { + lint_array!(PRINT_STDOUT) + } +} + +impl LateLintPass for PrintLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprCall(ref fun, _) = expr.node { + if let ExprPath(_, ref path) = fun.node { + if match_path(path, &IO_PRINT_PATH) { + if let Some(span) = is_expn_of(cx, expr.span, "print") { + let (span, name) = match is_expn_of(cx, span, "println") { + Some(span) => (span, "println"), + None => (span, "print"), + }; + + span_lint(cx, + PRINT_STDOUT, + span, + &format!("use of `{}!`", name)); + } + } + } + } + } +} diff --git a/src/utils.rs b/src/utils.rs index 139e94dbc91..c59e35c5c5b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -29,6 +29,7 @@ pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"] pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; +pub const IO_PRINT_PATH: [&'static str; 3] = ["std", "io", "_print"]; pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; @@ -645,3 +646,29 @@ fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { _ => false, } } + +/// Return the pre-expansion span is this comes from a expansion of the macro `name`. +pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { + loop { + let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| { + expn.map(|ei| { + (ei.callee.name(), ei.call_site) + }) + }); + + return match span_name_span { + Some((mac_name, new_span)) => { + if mac_name.as_str() == name { + Some(new_span) + } + else { + span = new_span; + continue; + } + } + None => { + None + } + }; + } +} diff --git a/tests/compile-fail/print.rs b/tests/compile-fail/print.rs new file mode 100755 index 00000000000..8141cdd2645 --- /dev/null +++ b/tests/compile-fail/print.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(print_stdout)] + +fn main() { + println!("Hello"); //~ERROR use of `println!` + print!("Hello"); //~ERROR use of `print!` + + vec![1, 2]; +} -- cgit 1.4.1-3-g733a5 From f5cc94c96a1f00d4ed7360df13b3ce78721c623d Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 28 Jan 2016 23:34:09 -0800 Subject: Add for_loop_over_option lint --- README.md | 3 ++- src/lib.rs | 1 + src/loops.rs | 36 +++++++++++++++++++++++++++++++++--- tests/compile-fail/for_loop.rs | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2673d81f808..b58d2f67ac2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 101 lints included in this crate: +There are 102 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -37,6 +37,7 @@ name [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an Option, which is more clear as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases diff --git a/src/lib.rs b/src/lib.rs index 8b115a304e9..b955a337076 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -192,6 +192,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, + loops::FOR_LOOP_OVER_OPTION, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, loops::REVERSE_RANGE_LOOP, diff --git a/src/loops.rs b/src/loops.rs index 699e6e525da..dd7f7cbe3eb 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -11,7 +11,7 @@ use std::collections::{HashSet, HashMap}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal, get_enclosing_block}; -use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH}; +use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH, OPTION_PATH}; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. /// @@ -48,6 +48,16 @@ declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, declare_lint!{ pub ITER_NEXT_LOOP, Warn, "for-looping over `_.next()` which is probably not intended" } +/// **What it does:** This lint checks for `for` loops over Option values. It is `Warn` by default. +/// +/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`. +declare_lint!{ pub FOR_LOOP_OVER_OPTION, Warn, + "for-looping over an Option, which is more clear as an `if let`" } + /// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default. /// /// **Why is this bad?** The `while let` loop is usually shorter and more readable @@ -248,7 +258,7 @@ impl LateLintPass for LoopsPass { fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { check_for_loop_range(cx, pat, arg, body, expr); check_for_loop_reverse_range(cx, arg, expr); - check_for_loop_explicit_iter(cx, arg, expr); + check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); } @@ -373,7 +383,8 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { } } -fn check_for_loop_explicit_iter(cx: &LateContext, arg: &Expr, expr: &Expr) { +fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { + let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { @@ -401,10 +412,29 @@ fn check_for_loop_explicit_iter(cx: &LateContext, arg: &Expr, expr: &Expr) { expr.span, "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ probably not what you want"); + next_loop_linted = true; } } } + if !next_loop_linted { + check_option_looping(cx, pat, arg); + } +} +/// Check for `for` loops over `Option`s +fn check_option_looping(cx: &LateContext, pat: &Pat, arg: &Expr) { + let ty = cx.tcx.expr_ty(arg); + if match_type(cx, ty, &OPTION_PATH) { + span_help_and_lint( + cx, + FOR_LOOP_OVER_OPTION, + arg.span, + &format!("for loop over `{0}`, which is an Option. This is more readably written as \ + an `if let` statement.", snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", + snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_")) + ); + } } fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 37ecd290175..a45dc4bbb35 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -3,6 +3,39 @@ use std::collections::*; +#[deny(clippy)] +fn for_loop_over_option() { + let option = Some(1); + let v = vec![0,1,2]; + + // check FOR_LOOP_OVER_OPTION lint + for x in option { + //~^ ERROR for loop over `option`, which is an Option. + //~| HELP consider replacing `for x in option` with `if let Some(x) = option` + println!("{}", x); + } + + // make sure LOOP_OVER_NEXT lint takes precedence + for x in v.iter().next() { + //~^ ERROR you are iterating over `Iterator::next()` which is an Option + // TODO: make sure we don't lint twice + println!("{}", x); + } + + // check for false positives + + // for loop false positive + for x in v { + println!("{}", x); + } + + // while let false positive + while let Some(x) = option { + println!("{}", x); + break; + } +} + struct Unrelated(Vec<u8>); impl Unrelated { fn next(&self) -> std::slice::Iter<u8> { @@ -209,4 +242,6 @@ fn main() { let mut index = 0; for _v in &vec { index += 1 } println!("index: {}", index); + + for_loop_over_option(); } -- cgit 1.4.1-3-g733a5 From afb7e6721797484c704a01ed94ae67c086cdc007 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 01:54:10 +0100 Subject: Add a lint to warn about &vec![_] if &[_] would do --- README.md | 3 +- src/lib.rs | 3 ++ src/utils.rs | 4 +- src/vec.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/vec.rs | 44 ++++++++++++++++++ 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 src/vec.rs create mode 100755 tests/compile-fail/vec.rs diff --git a/README.md b/README.md index fbd6f4ebfe6..212d868c698 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 101 lints included in this crate: +There are 102 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -105,6 +105,7 @@ name [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types +[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention diff --git a/src/lib.rs b/src/lib.rs index 8b115a304e9..90625e4bb5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ pub mod array_indexing; pub mod panic; pub mod derive; pub mod print; +pub mod vec; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -144,6 +145,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box print::PrintLint); + reg.register_late_lint_pass(box vec::UselessVec); reg.register_lint_group("clippy_pedantic", vec![ @@ -250,6 +252,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::TYPE_COMPLEXITY, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, + vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); } diff --git a/src/utils.rs b/src/utils.rs index c59e35c5c5b..a6dbcfd9e2f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,6 +20,7 @@ pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BOX_NEW_PATH: [&'static str; 4] = ["std", "boxed", "Box", "new"]; pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; @@ -36,6 +37,7 @@ pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; /// Produce a nested chain of if-lets and ifs from the patterns: @@ -487,7 +489,7 @@ pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) -> DiagnosticWrapper<'a> - where F: Fn(&mut DiagnosticWrapper) + where F: FnOnce(&mut DiagnosticWrapper) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { diff --git a/src/vec.rs b/src/vec.rs new file mode 100644 index 00000000000..b46795a3cdd --- /dev/null +++ b/src/vec.rs @@ -0,0 +1,111 @@ +use rustc::lint::*; +use rustc::middle::ty::TypeVariants; +use rustc_front::hir::*; +use syntax::codemap::Span; +use syntax::ptr::P; +use utils::{BOX_NEW_PATH, VEC_FROM_ELEM_PATH}; +use utils::{is_expn_of, match_path, snippet, span_lint_and_then}; + +/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. +/// It is `Warn` by default. +/// +/// **Why is this bad?** This is less efficient. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust, ignore +/// foo(&vec![1, 2]) +/// ``` +declare_lint! { + pub USELESS_VEC, + Warn, + "useless `vec!`" +} + +#[derive(Copy, Clone, Debug)] +pub struct UselessVec; + +impl LintPass for UselessVec { + fn get_lints(&self) -> LintArray { + lint_array!(USELESS_VEC) + } +} + +impl LateLintPass for UselessVec { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + unexpand_vec(cx, expr); + + // search for `&!vec[_]` expressions where the adjusted type is `&[_]` + if_let_chain!{[ + let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, + let TypeVariants::TySlice(..) = ty.ty.sty, + let ExprAddrOf(_, ref addressee) = expr.node, + let Some(vec_args) = unexpand_vec(cx, addressee) + ], { + let snippet = match vec_args { + VecArgs::Repeat(elem, len) => { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } + VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = Span { + lo: args[0].span.lo, + hi: last.span.hi, + expn_id: args[0].span.expn_id, + }; + + format!("&[{}]", snippet(cx, span, "..")).into() + } + else { + "&[]".into() + } + } + }; + + span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| { + db.span_suggestion(expr.span, "you can use a slice directly", snippet); + }); + }} + } +} + +/// Represent the pre-expansion arguments of a `vec!` invocation. +pub enum VecArgs<'a> { + /// `vec![elem, len]` + Repeat(&'a P<Expr>, &'a P<Expr>), + /// `vec![a, b, c]` + Vec(&'a [P<Expr>]), +} + +/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. +pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> { + if_let_chain!{[ + let ExprCall(ref fun, ref args) = expr.node, + let ExprPath(_, ref path) = fun.node, + is_expn_of(cx, fun.span, "vec").is_some() + ], { + return if match_path(path, &VEC_FROM_ELEM_PATH) && args.len() == 2 { + // `vec![elem; size]` case + Some(VecArgs::Repeat(&args[0], &args[1])) + } + else if match_path(path, &["into_vec"]) && args.len() == 1 { + // `vec![a, b, c]` case + if_let_chain!{[ + let ExprCall(ref fun, ref args) = args[0].node, + let ExprPath(_, ref path) = fun.node, + match_path(path, &BOX_NEW_PATH) && args.len() == 1, + let ExprVec(ref args) = args[0].node + ], { + return Some(VecArgs::Vec(&*args)); + }} + + None + } + else { + None + }; + }} + + None +} diff --git a/tests/compile-fail/vec.rs b/tests/compile-fail/vec.rs new file mode 100755 index 00000000000..b4f52ecadc5 --- /dev/null +++ b/tests/compile-fail/vec.rs @@ -0,0 +1,44 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(useless_vec)] + +fn on_slice(_: &[u8]) {} +#[allow(ptr_arg)] +fn on_vec(_: &Vec<u8>) {} + +fn main() { + on_slice(&vec![]); + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION on_slice(&[]) + on_slice(&[]); + + on_slice(&vec![1, 2]); + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION on_slice(&[1, 2]) + on_slice(&[1, 2]); + + on_slice(&vec ![1, 2]); + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION on_slice(&[1, 2]) + on_slice(&[1, 2]); + + on_slice(&vec!(1, 2)); + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION on_slice(&[1, 2]) + on_slice(&[1, 2]); + + on_slice(&vec![1; 2]); + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION on_slice(&[1; 2]) + on_slice(&[1; 2]); + + on_vec(&vec![]); + on_vec(&vec![1, 2]); + on_vec(&vec![1; 2]); +} -- cgit 1.4.1-3-g733a5 From 1b9fbd8801019b9235c08e09acb92d21ac0c8c74 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 22:18:14 +0100 Subject: Fix false positive in NEEDLESS_LIFETIMES --- src/lifetimes.rs | 60 ++++++++++++++++++++++++++++++----------- tests/compile-fail/lifetimes.rs | 5 ++++ 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/lifetimes.rs b/src/lifetimes.rs index b83ac390edf..1441015eb0e 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -65,13 +65,30 @@ enum RefLt { Static, Named(Name), } -use self::RefLt::*; + +fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { + if let TraitTyParamBound(ref trait_ref, _) = *bound { + let lt = trait_ref.trait_ref.path.segments + .last().expect("a path must have at least one segment") + .parameters.lifetimes(); + + Some(lt) + } else { + None + } +} fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, generics: &Generics, span: Span) { if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; } - if could_use_elision(cx, decl, slf, &generics.lifetimes) { + + let bounds_lts = + generics.ty_params + .iter() + .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); + + if could_use_elision(cx, decl, slf, &generics.lifetimes, bounds_lts) { span_lint(cx, NEEDLESS_LIFETIMES, span, @@ -80,7 +97,10 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g report_extra_lifetimes(cx, decl, &generics, slf); } -fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, named_lts: &[LifetimeDef]) -> bool { +fn could_use_elision<'a, T: Iterator<Item=&'a Lifetime>>( + cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, + named_lts: &[LifetimeDef], bounds_lts: T +) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT // * output references, exactly one input reference with same LT @@ -112,7 +132,7 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> output_visitor.visit_ty(ty); } - let input_lts = input_visitor.into_vec(); + let input_lts = lts_from_bounds(input_visitor.into_vec(), bounds_lts); let output_lts = output_visitor.into_vec(); // check for lifetimes from higher scopes @@ -129,7 +149,7 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - if input_lts.iter().all(|lt| *lt == Unnamed || *lt == Static) { + if input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static) { return false; } // we have no output reference, so we only need all distinct lifetimes @@ -142,8 +162,8 @@ fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf> } if input_lts.len() == 1 { match (&input_lts[0], &output_lts[0]) { - (&Named(n1), &Named(n2)) if n1 == n2 => true, - (&Named(_), &Unnamed) => true, + (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true, + (&RefLt::Named(_), &RefLt::Unnamed) => true, _ => false, // already elided, different named lifetimes // or something static going on } @@ -157,22 +177,32 @@ fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { let mut allowed_lts = HashSet::new(); for lt in named_lts { if lt.bounds.is_empty() { - allowed_lts.insert(Named(lt.lifetime.name)); + allowed_lts.insert(RefLt::Named(lt.lifetime.name)); } } - allowed_lts.insert(Unnamed); - allowed_lts.insert(Static); + allowed_lts.insert(RefLt::Unnamed); + allowed_lts.insert(RefLt::Static); allowed_lts } +fn lts_from_bounds<'a, T: Iterator<Item=&'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> { + for lt in bounds_lts { + if lt.name.as_str() != "'static" { + vec.push(RefLt::Named(lt.name)); + } + } + + vec +} + /// Number of unique lifetimes in the given vector. fn unique_lifetimes(lts: &[RefLt]) -> usize { lts.iter().collect::<HashSet<_>>().len() } -/// A visitor usable for rustc_front::visit::walk_ty(). +/// A visitor usable for `rustc_front::visit::walk_ty()`. struct RefVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, // context reference + cx: &'v LateContext<'v, 't>, lts: Vec<RefLt>, } @@ -187,12 +217,12 @@ impl<'v, 't> RefVisitor<'v, 't> { fn record(&mut self, lifetime: &Option<Lifetime>) { if let Some(ref lt) = *lifetime { if lt.name.as_str() == "'static" { - self.lts.push(Static); + self.lts.push(RefLt::Static); } else { - self.lts.push(Named(lt.name)); + self.lts.push(RefLt::Named(lt.name)); } } else { - self.lts.push(Unnamed); + self.lts.push(RefLt::Unnamed); } } diff --git a/tests/compile-fail/lifetimes.rs b/tests/compile-fail/lifetimes.rs index eb161af9dc3..408b6762df6 100644 --- a/tests/compile-fail/lifetimes.rs +++ b/tests/compile-fail/lifetimes.rs @@ -3,6 +3,7 @@ #![deny(needless_lifetimes, unused_lifetimes)] #![allow(dead_code)] + fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~^ERROR explicit lifetimes given @@ -97,6 +98,7 @@ fn struct_with_lt3<'a>(_foo: &Foo<'a> ) -> &'a str { unimplemented!() } fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b> ) -> &'a str { unimplemented!() } trait WithLifetime<'a> {} + type WithLifetimeAlias<'a> = WithLifetime<'a>; // should not warn because it won't build without the lifetime @@ -123,5 +125,8 @@ fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } //~ fn elided_input_named_output<'a>(_arg: &str) -> &'a str { unimplemented!() } +fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } //~ERROR explicit lifetimes given +fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { unimplemented!() } + fn main() { } -- cgit 1.4.1-3-g733a5 From 3a39bbaf741f74342c694e59a3e0b1888279131c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 22:19:14 +0100 Subject: Small cleanup --- src/entry.rs | 6 +++--- src/matches.rs | 4 ++-- src/utils.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index d9fb7269be6..64d6fa7be38 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -93,19 +93,19 @@ fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: ], { let help = if sole_expr { format!("{}.entry({}).or_insert({})", - snippet(cx, map.span, ".."), + snippet(cx, map.span, "map"), snippet(cx, params[1].span, ".."), snippet(cx, params[2].span, "..")) } else { format!("{}.entry({})", - snippet(cx, map.span, ".."), + snippet(cx, map.span, "map"), snippet(cx, params[1].span, "..")) }; span_lint_and_then(cx, MAP_ENTRY, span, &format!("usage of `contains_key` followed by `insert` on `{}`", kind), |db| { - db.span_suggestion(span, "Consider using", help.clone()); + db.span_suggestion(span, "Consider using", help); }); } } diff --git a/src/matches.rs b/src/matches.rs index 4cb4df19bf8..0c18d35fa12 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -223,8 +223,8 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { expr.span, "you seem to be trying to match on a boolean expression. Consider using \ an if..else block:", move |db| { - if let Some(ref sugg) = sugg { - db.span_suggestion(expr.span, "try this", sugg.clone()); + if let Some(sugg) = sugg { + db.span_suggestion(expr.span, "try this", sugg); } }); } diff --git a/src/utils.rs b/src/utils.rs index a6dbcfd9e2f..b5355919496 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -649,7 +649,7 @@ fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { } } -/// Return the pre-expansion span is this comes from a expansion of the macro `name`. +/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { loop { let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| { -- cgit 1.4.1-3-g733a5 From 997a565aeb92f01342d4e35075be609b292befcd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 22:24:08 +0100 Subject: Make the python scripts py3 and pep8 compatible --- util/update_lints.py | 4 +++- util/update_wiki.py | 37 ++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/util/update_lints.py b/util/update_lints.py index 6a59abcdc15..9f105a2699c 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -1,7 +1,8 @@ #!/usr/bin/env python # Generate a Markdown table of all lints, and put it in README.md. # With -n option, only print the new table to stdout. -# With -c option, print a warning and set exit status to 1 if a file would be changed. +# With -c option, print a warning and set exit status to 1 if a file would be +# changed. import os import re @@ -18,6 +19,7 @@ nl_escape_re = re.compile(r'\\\n\s*') wiki_link = 'https://github.com/Manishearth/rust-clippy/wiki' + def collect(lints, fn): """Collect all lints from a file. diff --git a/util/update_wiki.py b/util/update_wiki.py index 96333c1e4b3..842f0ed6d8e 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -1,8 +1,12 @@ #!/usr/bin/env python # Generate the wiki Home.md page from the contained doc comments # requires the checked out wiki in ../rust-clippy.wiki/ -# with -c option, print a warning and set exit status 1 if the file would be changed. -import os, re, sys +# with -c option, print a warning and set exit status 1 if the file would be +# changed. +import os +import re +import sys + def parse_path(p="src"): d = {} @@ -14,10 +18,10 @@ def parse_path(p="src"): START = 0 LINT = 1 + def parse_file(d, f): last_comment = [] comment = True - lint = None with open(f) as rs: for line in rs: @@ -35,27 +39,33 @@ def parse_file(d, f): l = line.strip() m = re.search(r"pub\s+([A-Z_]+)", l) if m: - print "found %s in %s" % (m.group(1).lower(), f) + print("found %s in %s" % (m.group(1).lower(), f)) d[m.group(1).lower()] = last_comment last_comment = [] comment = True if "}" in l: - print "Warning: Missing Lint-Name in", f + print("Warning: Missing Lint-Name in", f) comment = True PREFIX = """Welcome to the rust-clippy wiki! -Here we aim to collect further explanations on the lints clippy provides. So without further ado: +Here we aim to collect further explanations on the lints clippy provides. So \ +without further ado: """ WARNING = """ # A word of warning -Clippy works as a *plugin* to the compiler, which means using an unstable internal API. We have gotten quite good at keeping pace with the API evolution, but the consequence is that clippy absolutely needs to be compiled with the version of `rustc` it will run on, otherwise you will get strange errors of missing symbols.""" +Clippy works as a *plugin* to the compiler, which means using an unstable \ +internal API. We have gotten quite good at keeping pace with the API \ +evolution, but the consequence is that clippy absolutely needs to be compiled \ +with the version of `rustc` it will run on, otherwise you will get strange \ +errors of missing symbols.""" + def write_wiki_page(d, f): - keys = d.keys() + keys = list(d.keys()) keys.sort() with open(f, "w") as w: w.write(PREFIX) @@ -65,6 +75,7 @@ def write_wiki_page(d, f): for k in keys: w.write("\n# `%s`\n\n%s" % (k, "".join(d[k]))) + def check_wiki_page(d, f): errors = [] with open(f) as w: @@ -74,17 +85,21 @@ def check_wiki_page(d, f): v = d.pop(m.group(1), "()") if v == "()": errors.append("Missing wiki entry: " + m.group(1)) - keys = d.keys() + keys = list(d.keys()) keys.sort() for k in keys: errors.append("Spurious wiki entry: " + k) if errors: - print "\n".join(errors) + print("\n".join(errors)) sys.exit(1) -if __name__ == "__main__": + +def main(): d = parse_path() if "-c" in sys.argv: check_wiki_page(d, "../rust-clippy.wiki/Home.md") else: write_wiki_page(d, "../rust-clippy.wiki/Home.md") + +if __name__ == "__main__": + main() -- cgit 1.4.1-3-g733a5 From 95599c6a620efcb39f130be5a77c46900a71ad0e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 22:42:19 +0100 Subject: Synchronise comments with wiki Wiki commits bfa439b and 9b8ced8. --- src/collapsible_if.rs | 2 +- src/derive.rs | 2 ++ src/items_after_statements.rs | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index fb1d7f696d1..dd89b22a40f 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -19,7 +19,7 @@ use syntax::codemap::Spanned; use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; /// **What it does:** This lint checks for nested `if`-statements which can be collapsed by -/// `&&`-combining their conditions and for `else { if .. } expressions that can be collapsed to +/// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to /// `else if ..`. It is `Warn` by default. /// /// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. diff --git a/src/derive.rs b/src/derive.rs index b1c0bde40a2..ca7649f75b3 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -29,6 +29,7 @@ use rustc::middle::ty::TypeVariants; /// impl PartialEq for Foo { /// .. /// } +/// ``` declare_lint! { pub DERIVE_HASH_NOT_EQ, Warn, @@ -52,6 +53,7 @@ declare_lint! { /// impl Clone for Foo { /// .. /// } +/// ``` declare_lint! { pub EXPL_IMPL_CLONE_ON_COPY, Warn, diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 5f109dac058..8eb3364b2bd 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -5,9 +5,12 @@ use syntax::attr::*; use syntax::ast::*; use utils::in_macro; -/// **What it does:** It `Warn`s on blocks where there are items that are declared in the middle of or after the statements +/// **What it does:** It `Warn`s on blocks where there are items that are declared in the middle of +/// or after the statements /// -/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are processed in order. This might cause confusion as it's hard to figure out which item is meant in a statement. +/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are +/// processed in order. This might cause confusion as it's hard to figure out which item is meant +/// in a statement. /// /// **Known problems:** None /// @@ -23,6 +26,7 @@ use utils::in_macro; /// } /// foo(); // prints "foo" /// } +/// ``` declare_lint! { pub ITEMS_AFTER_STATEMENTS, Warn, "finds blocks where an item comes after a statement" } pub struct ItemsAfterStatemets; -- cgit 1.4.1-3-g733a5 From f7bab322f65c3cbc5a312ea02fb6f4781c167e1e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 29 Jan 2016 22:49:48 +0100 Subject: Fix formatting on wiki --- src/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vec.rs b/src/vec.rs index b46795a3cdd..41a477c34ff 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -14,7 +14,7 @@ use utils::{is_expn_of, match_path, snippet, span_lint_and_then}; /// **Known problems:** None. /// /// **Example:** -/// ```rust, ignore +/// ```rust,ignore /// foo(&vec![1, 2]) /// ``` declare_lint! { -- cgit 1.4.1-3-g733a5 From 405d7c691e2ad6b21e044b39c736b1e1a7db99cf Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Fri, 29 Jan 2016 15:15:57 -0800 Subject: Add for_loop_over_result lint --- README.md | 5 +++-- src/lib.rs | 1 + src/loops.rs | 35 ++++++++++++++++++++++++------ tests/compile-fail/for_loop.rs | 48 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b58d2f67ac2..39b848d036b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 102 lints included in this crate: +There are 103 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -37,7 +37,8 @@ name [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an Option, which is more clear as an `if let` +[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` +[for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases diff --git a/src/lib.rs b/src/lib.rs index b955a337076..a6f5aa97485 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -193,6 +193,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, loops::FOR_LOOP_OVER_OPTION, + loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, loops::NEEDLESS_RANGE_LOOP, loops::REVERSE_RANGE_LOOP, diff --git a/src/loops.rs b/src/loops.rs index dd7f7cbe3eb..74ff9edcb6b 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -11,7 +11,7 @@ use std::collections::{HashSet, HashMap}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal, get_enclosing_block}; -use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH, OPTION_PATH}; +use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH, OPTION_PATH, RESULT_PATH}; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. /// @@ -48,7 +48,7 @@ declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, declare_lint!{ pub ITER_NEXT_LOOP, Warn, "for-looping over `_.next()` which is probably not intended" } -/// **What it does:** This lint checks for `for` loops over Option values. It is `Warn` by default. +/// **What it does:** This lint checks for `for` loops over `Option` values. It is `Warn` by default. /// /// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. /// @@ -56,7 +56,17 @@ declare_lint!{ pub ITER_NEXT_LOOP, Warn, /// /// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`. declare_lint!{ pub FOR_LOOP_OVER_OPTION, Warn, - "for-looping over an Option, which is more clear as an `if let`" } + "for-looping over an `Option`, which is more clearly expressed as an `if let`" } + +/// **What it does:** This lint checks for `for` loops over `Result` values. It is `Warn` by default. +/// +/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in result { .. }`. This should be `if let Ok(x) = result { .. }`. +declare_lint!{ pub FOR_LOOP_OVER_RESULT, Warn, + "for-looping over a `Result`, which is more clearly expressed as an `if let`" } /// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default. /// @@ -417,24 +427,35 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { } } if !next_loop_linted { - check_option_looping(cx, pat, arg); + check_arg_type(cx, pat, arg); } } -/// Check for `for` loops over `Option`s -fn check_option_looping(cx: &LateContext, pat: &Pat, arg: &Expr) { +/// Check for `for` loops over `Option`s and `Results` +fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { let ty = cx.tcx.expr_ty(arg); if match_type(cx, ty, &OPTION_PATH) { span_help_and_lint( cx, FOR_LOOP_OVER_OPTION, arg.span, - &format!("for loop over `{0}`, which is an Option. This is more readably written as \ + &format!("for loop over `{0}`, which is an `Option`. This is more readably written as \ an `if let` statement.", snippet(cx, arg.span, "_")), &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_")) ); } + else if match_type(cx, ty, &RESULT_PATH) { + span_help_and_lint( + cx, + FOR_LOOP_OVER_RESULT, + arg.span, + &format!("for loop over `{0}`, which is a `Result`. This is more readably written as \ + an `if let` statement.", snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", + snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_")) + ); + } } fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index a45dc4bbb35..1fcbbf54d1f 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -4,21 +4,51 @@ use std::collections::*; #[deny(clippy)] -fn for_loop_over_option() { +fn for_loop_over_option_and_result() { let option = Some(1); + let result = option.ok_or("x not found"); let v = vec![0,1,2]; // check FOR_LOOP_OVER_OPTION lint + for x in option { - //~^ ERROR for loop over `option`, which is an Option. + //~^ ERROR for loop over `option`, which is an `Option`. //~| HELP consider replacing `for x in option` with `if let Some(x) = option` println!("{}", x); } - // make sure LOOP_OVER_NEXT lint takes precedence + // check FOR_LOOP_OVER_RESULT lint + + for x in result { + //~^ ERROR for loop over `result`, which is a `Result`. + //~| HELP consider replacing `for x in result` with `if let Ok(x) = result` + println!("{}", x); + } + + for x in option.ok_or("x not found") { + //~^ ERROR for loop over `option.ok_or("x not found")`, which is a `Result`. + //~| HELP consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` + println!("{}", x); + } + + // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call in the chain + for x in v.iter().next() { //~^ ERROR you are iterating over `Iterator::next()` which is an Option - // TODO: make sure we don't lint twice + println!("{}", x); + } + + // make sure we lint when next() is not the last call in the chain + + for x in v.iter().next().and(Some(0)) { + //~^ ERROR for loop over `v.iter().next().and(Some(0))`, which is an `Option` + //~| HELP consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` + println!("{}", x); + } + + for x in v.iter().next().ok_or("x not found") { + //~^ ERROR for loop over `v.iter().next().ok_or("x not found")`, which is a `Result` + //~| HELP consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` println!("{}", x); } @@ -29,11 +59,17 @@ fn for_loop_over_option() { println!("{}", x); } - // while let false positive + // while let false positive for Option while let Some(x) = option { println!("{}", x); break; } + + // while let false positive for Option + while let Ok(x) = result { + println!("{}", x); + break; + } } struct Unrelated(Vec<u8>); @@ -243,5 +279,5 @@ fn main() { for _v in &vec { index += 1 } println!("index: {}", index); - for_loop_over_option(); + for_loop_over_option_and_result(); } -- cgit 1.4.1-3-g733a5 From e48fbba864dad14bb554bc60b445da41c8dd72d5 Mon Sep 17 00:00:00 2001 From: scurest <scurest@users.noreply.github.com> Date: Fri, 29 Jan 2016 00:39:13 -0600 Subject: Add a lint to suggest uint == 0 over uint <= 0 --- README.md | 3 +- src/escape.rs | 2 +- src/lib.rs | 2 + src/types.rs | 52 +++++++++++++++++++++++ tests/compile-fail/absurd_unsigned_comparisons.rs | 14 ++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/compile-fail/absurd_unsigned_comparisons.rs diff --git a/README.md b/README.md index ec1dd7f6dbb..0c94fb3383e 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,11 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 104 lints included in this crate: +There are 105 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +[absurd_unsigned_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_unsigned_comparisons) | warn | testing whether an unsigned integer is non-positive [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` diff --git a/src/escape.rs b/src/escape.rs index 32dbbb99226..c54c4395335 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { .get(&borrow_id) { if LoanCause::AutoRef == loan_cause { // x.foo() - if adj.autoderefs <= 0 { + if adj.autoderefs == 0 { self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) } } else { diff --git a/src/lib.rs b/src/lib.rs index 82bd2d39a12..3519fb9ee88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -146,6 +146,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); + reg.register_late_lint_pass(box types::AbsurdUnsignedComparisons); reg.register_lint_group("clippy_pedantic", vec![ @@ -247,6 +248,7 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_LIT_AS_BYTES, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, + types::ABSURD_UNSIGNED_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, types::LET_UNIT_VALUE, diff --git a/src/types.rs b/src/types.rs index d41896cd490..0ab373bfa35 100644 --- a/src/types.rs +++ b/src/types.rs @@ -557,3 +557,55 @@ impl LateLintPass for CharLitAsU8 { } } } + +/// **What it does:** This lint checks for expressions where an unsigned integer is tested to be non-positive and suggests testing for equality with zero instead. +/// +/// **Why is this bad?** `x <= 0` may mislead the reader into thinking `x` can be negative. `x == 0` makes explicit that zero is the only possibility. +/// +/// **Known problems:** None +/// +/// **Example:** `vec.len() <= 0` +declare_lint!(pub ABSURD_UNSIGNED_COMPARISONS, Warn, + "testing whether an unsigned integer is non-positive"); + +pub struct AbsurdUnsignedComparisons; + +impl LintPass for AbsurdUnsignedComparisons { + fn get_lints(&self) -> LintArray { + lint_array!(ABSURD_UNSIGNED_COMPARISONS) + } +} + +fn is_zero_lit(expr: &Expr) -> bool { + use syntax::ast::Lit_; + + if let ExprLit(ref l) = expr.node { + if let Lit_::LitInt(val, _) = l.node { + return val == 0; + } + } + false +} + +impl LateLintPass for AbsurdUnsignedComparisons { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + let op = cmp.node; + + let comparee = match op { + BiLe if is_zero_lit(rhs) => lhs, // x <= 0 + BiGe if is_zero_lit(lhs) => rhs, // 0 >= x + _ => return, + }; + + if let ty::TyUint(_) = cx.tcx.expr_ty(comparee).sty { + if !in_macro(cx, expr.span) { + let msg = "testing whether an unsigned integer is non-positive"; + let help = format!("consider using {} == 0 instead", + snippet(cx, comparee.span, "x")); + span_help_and_lint(cx, ABSURD_UNSIGNED_COMPARISONS, expr.span, msg, &help); + } + } + } + } +} diff --git a/tests/compile-fail/absurd_unsigned_comparisons.rs b/tests/compile-fail/absurd_unsigned_comparisons.rs new file mode 100644 index 00000000000..d7817daf204 --- /dev/null +++ b/tests/compile-fail/absurd_unsigned_comparisons.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused)] + +#[deny(absurd_unsigned_comparisons)] +fn main() { + 1u32 <= 0; //~ERROR testing whether an unsigned integer is non-positive + 1u8 <= 0; //~ERROR testing whether an unsigned integer is non-positive + 1i32 <= 0; + 0 >= 1u32; //~ERROR testing whether an unsigned integer is non-positive + 0 >= 1; + 1u32 > 0; +} -- cgit 1.4.1-3-g733a5 From a2ad0c66953cae54d43773fa51fa98e2d68d10d7 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 31 Jan 2016 23:25:10 +0100 Subject: fixed #528 --- src/block_in_if_condition.rs | 4 +++- tests/compile-fail/block_in_if_condition.rs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 53f11366cae..0162ef92dd6 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -92,7 +92,9 @@ impl LateLintPass for BlockInIfCondition { snippet_block(cx, then.span, ".."))); } } else { - if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, block.stmts[0].span) { + let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, + |e| e.span); + if in_macro(cx, span) || differing_macro_contexts(expr.span, span) { return; } // move block higher diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs index 0a68d80c339..5158e74c1e0 100644 --- a/tests/compile-fail/block_in_if_condition.rs +++ b/tests/compile-fail/block_in_if_condition.rs @@ -3,17 +3,28 @@ #![deny(block_in_if_condition_expr)] #![deny(block_in_if_condition_stmt)] -#![allow(unused)] +#![allow(unused, let_and_return)] macro_rules! blocky { () => {{true}} } +macro_rules! blocky_too { + () => {{ + let r = true; + r + }} +} + fn macro_if() { if blocky!() { } + + if blocky_too!() { + } } + fn condition_has_block() -> i32 { if { //~ERROR in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' -- cgit 1.4.1-3-g733a5 From d6c0435c81c594c9fb3d563d0306ac24c25cc2ca Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <rust19446194516@oli-obk.de> Date: Sun, 24 Jan 2016 12:24:16 +0100 Subject: lint on single match expressions with a value in the else path --- README.md | 3 +- src/lib.rs | 1 + src/matches.rs | 76 ++++++++++++++++++++++++++++++++++--------- tests/compile-fail/matches.rs | 22 ++++++++++++- 4 files changed, 85 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index ec1dd7f6dbb..36037036147 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 104 lints included in this crate: +There are 105 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -89,6 +89,7 @@ name [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value [should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead [str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead diff --git a/src/lib.rs b/src/lib.rs index 82bd2d39a12..6d8ea99ebcc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,6 +149,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy_pedantic", vec![ + matches::SINGLE_MATCH_ELSE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, diff --git a/src/matches.rs b/src/matches.rs index 0c18d35fa12..c866a48d223 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -28,6 +28,23 @@ declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ is `_ => {}`) is used; recommends `if let` instead"); +/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. It is `Allow` by default. +/// +/// **Why is this bad?** Just readability – `if let` nests less than a `match`. +/// +/// **Known problems:** Personal style preferences may differ +/// +/// **Example:** +/// ``` +/// match x { +/// Some(ref foo) -> bar(foo), +/// _ => bar(other_ref), +/// } +/// ``` +declare_lint!(pub SINGLE_MATCH_ELSE, Allow, + "a match statement with a two arms where the second arm's pattern is a wildcard; \ + recommends `if let` instead"); + /// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. It is `Warn` by default. /// /// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. @@ -89,7 +106,7 @@ pub struct MatchPass; impl LintPass for MatchPass { fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL) + lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL, SINGLE_MATCH_ELSE) } } @@ -112,34 +129,49 @@ impl LateLintPass for MatchPass { fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - is_unit_expr(&arms[1].body) { + arms[1].pats.len() == 1 && arms[1].guard.is_none() { + let els = if is_unit_expr(&arms[1].body) { + None + } else if let ExprBlock(_) = arms[1].body.node { + // matches with blocks that contain statements are prettier as `if let + else` + Some(&*arms[1].body) + } else { + // allow match arms with just expressions + return; + }; let ty = cx.tcx.expr_ty(ex); if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { - check_single_match_single_pattern(cx, ex, arms, expr); - check_single_match_opt_like(cx, ex, arms, expr, ty); + check_single_match_single_pattern(cx, ex, arms, expr, els); + check_single_match_opt_like(cx, ex, arms, expr, ty, els); } } } -fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { +fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { if arms[1].pats[0].node == PatWild { + let lint = if els.is_some() { + SINGLE_MATCH_ELSE + } else { + SINGLE_MATCH + }; + let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); span_lint_and_then(cx, - SINGLE_MATCH, + lint, expr.span, "you seem to be trying to use match for destructuring a single pattern. \ Consider using `if let`", |db| { db.span_suggestion(expr.span, "try this", - format!("if let {} = {} {}", + format!("if let {} = {} {}{}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."))); + expr_block(cx, &arms[0].body, None, ".."), + els_str)); }); } } -fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty) { - // list of candidate Enums we know will never get any more membre +fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) { + // list of candidate Enums we know will never get any more members let candidates = &[ (&COW_PATH, "Borrowed"), (&COW_PATH, "Cow::Borrowed"), @@ -151,23 +183,37 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: ]; let path = match arms[1].pats[0].node { - PatEnum(ref path, _) => path.to_string(), + PatEnum(ref path, Some(ref inner)) => { + // contains any non wildcard patterns? e.g. Err(err) + if inner.iter().any(|pat| if let PatWild = pat.node { false } else { true }) { + return; + } + path.to_string() + }, + PatEnum(ref path, None) => path.to_string(), PatIdent(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), _ => return }; for &(ty_path, pat_path) in candidates { if &path == pat_path && match_type(cx, ty, ty_path) { + let lint = if els.is_some() { + SINGLE_MATCH_ELSE + } else { + SINGLE_MATCH + }; + let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); span_lint_and_then(cx, - SINGLE_MATCH, + lint, expr.span, "you seem to be trying to use match for destructuring a single pattern. \ Consider using `if let`", |db| { db.span_suggestion(expr.span, "try this", - format!("if let {} = {} {}", + format!("if let {} = {} {}{}", snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."))); + expr_block(cx, &arms[0].body, None, ".."), + els_str)); }); } } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index c58e62419c6..71cc7c59f8f 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -3,12 +3,32 @@ #![plugin(clippy)] #![deny(clippy)] #![allow(unused)] +#![deny(single_match_else)] use std::borrow::Cow; enum Foo { Bar, Baz(u8) } use Foo::*; +enum ExprNode { + ExprAddrOf, + Butterflies, + Unicorns, +} + +static NODE: ExprNode = ExprNode::Unicorns; + +fn unwrap_addr() -> Option<&'static ExprNode> { + match ExprNode::Butterflies { //~ ERROR you seem to be trying to use match + //~^ HELP try + ExprNode::ExprAddrOf => Some(&NODE), + _ => { + let x = 5; + None + }, + } +} + fn single_match(){ let x = Some(1u8); @@ -33,7 +53,7 @@ fn single_match(){ _ => () } - // Not linted (content in the else) + // Not linted (no block with statements in the single arm) match z { (2...3, 7...9) => println!("{:?}", z), _ => println!("nope"), -- cgit 1.4.1-3-g733a5 From 07ace32ac91875be65c40a8957eb0982c027bd16 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 1 Feb 2016 11:28:39 +0100 Subject: fallout --- src/collapsible_if.rs | 65 ++++++++++++++++++++++++--------------------------- src/mut_reference.rs | 28 ++++++++-------------- src/utils.rs | 20 ++++------------ 3 files changed, 45 insertions(+), 68 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index dd89b22a40f..4b3c4174df7 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -54,43 +54,38 @@ impl LateLintPass for CollapsibleIf { fn check_if(cx: &LateContext, e: &Expr) { if let ExprIf(ref check, ref then, ref else_) = e.node { - match *else_ { - Some(ref else_) => { - if_let_chain! {[ - let ExprBlock(ref block) = else_.node, - block.stmts.is_empty(), - block.rules == BlockCheckMode::DefaultBlock, - let Some(ref else_) = block.expr, - let ExprIf(_, _, _) = else_.node - ], { - span_lint_and_then(cx, - COLLAPSIBLE_IF, - block.span, - "this `else { if .. }` block can be collapsed", |db| { - db.span_suggestion(block.span, "try", - format!("else {}", - snippet_block(cx, else_.span, ".."))); - }); - }} - } - None => { - if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = + if let Some(ref else_) = *else_ { + if_let_chain! {[ + let ExprBlock(ref block) = else_.node, + block.stmts.is_empty(), + block.rules == BlockCheckMode::DefaultBlock, + let Some(ref else_) = block.expr, + let ExprIf(_, _, _) = else_.node + ], { + span_lint_and_then(cx, + COLLAPSIBLE_IF, + block.span, + "this `else { if .. }` block can be collapsed", |db| { + db.span_suggestion(block.span, "try", + format!("else {}", + snippet_block(cx, else_.span, ".."))); + }); + }} + } else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = single_stmt_of_block(then) { - if e.span.expn_id != sp.expn_id { - return; - } - span_lint_and_then(cx, - COLLAPSIBLE_IF, - e.span, - "this if statement can be collapsed", |db| { - db.span_suggestion(e.span, "try", - format!("if {} && {} {}", - check_to_string(cx, check), - check_to_string(cx, check_inner), - snippet_block(cx, content.span, ".."))); - }); - } + if e.span.expn_id != sp.expn_id { + return; } + span_lint_and_then(cx, + COLLAPSIBLE_IF, + e.span, + "this if statement can be collapsed", |db| { + db.span_suggestion(e.span, "try", + format!("if {} && {} {}", + check_to_string(cx, check), + check_to_string(cx, check_inner), + snippet_block(cx, content.span, ".."))); + }); } } } diff --git a/src/mut_reference.rs b/src/mut_reference.rs index d92e449e7f2..15e8d310cd6 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -33,27 +33,19 @@ impl LateLintPass for UnnecessaryMutPassed { let borrowed_table = cx.tcx.tables.borrow(); match e.node { ExprCall(ref fn_expr, ref arguments) => { - match borrowed_table.node_types.get(&fn_expr.id) { - Some(function_type) => { - if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, &arguments, function_type, &format!("{}", path)); - } - } - None => unreachable!(), // A function with unknown type is called. - // If this happened the compiler would have aborted the - // compilation long ago. - }; - - + let function_type = borrowed_table.node_types + .get(&fn_expr.id) + .expect("A function with an unknown type is called. \ + If this happened, the compiler would have \ + aborted the compilation long ago"); + if let ExprPath(_, ref path) = fn_expr.node { + check_arguments(cx, &arguments, function_type, &format!("{}", path)); + } } ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); - match borrowed_table.method_map.get(&method_call) { - Some(method_type) => { - check_arguments(cx, &arguments, method_type.ty, &format!("{}", name.node.as_str())) - } - None => unreachable!(), // Just like above, this should never happen. - }; + let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); + check_arguments(cx, &arguments, method_type.ty, &format!("{}", name.node.as_str())) } _ => {} } diff --git a/src/utils.rs b/src/utils.rs index b5355919496..ff0c59ab290 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -657,20 +657,10 @@ pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> (ei.callee.name(), ei.call_site) }) }); - - return match span_name_span { - Some((mac_name, new_span)) => { - if mac_name.as_str() == name { - Some(new_span) - } - else { - span = new_span; - continue; - } - } - None => { - None - } - }; + match span_name_span { + Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), + None => return None, + Some((_, new_span)) => span = new_span, + } } } -- cgit 1.4.1-3-g733a5 From 35ec57c116ed4a37c6858b682542f9677835fae5 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Mon, 1 Feb 2016 20:35:01 +0900 Subject: Skip escape analysis for closure arguments --- src/escape.rs | 14 ++++++++------ tests/compile-fail/escape_analysis.rs | 5 +++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index 32dbbb99226..edc7b5c6fbb 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::front::map::Node::NodeStmt; +use rustc::front::map::Node::{NodeExpr, NodeStmt}; use rustc_front::hir::*; use rustc_front::intravisit as visit; use rustc::middle::ty; @@ -84,17 +84,19 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { - if self.cx.tcx.map.is_argument(consume_pat.id) { + let map = &self.cx.tcx.map; + if map.is_argument(consume_pat.id) { + // Skip closure arguments + if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { + return; + } if is_box(cmt.ty) { self.set.insert(consume_pat.id); } return; } if let Categorization::Rvalue(..) = cmt.cat { - if let Some(NodeStmt(st)) = self.cx - .tcx - .map - .find(self.cx.tcx.map.get_parent_node(cmt.id)) { + if let Some(NodeStmt(st)) = map.find(map.get_parent_node(cmt.id)) { if let StmtDecl(ref decl, _) = st.node { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { diff --git a/tests/compile-fail/escape_analysis.rs b/tests/compile-fail/escape_analysis.rs index 28154d9414e..f3aa8bff41c 100644 --- a/tests/compile-fail/escape_analysis.rs +++ b/tests/compile-fail/escape_analysis.rs @@ -23,6 +23,11 @@ fn warn_arg(x: Box<A>) { //~ ERROR local variable x.foo(); } +fn nowarn_closure_arg() { + let x = Some(box A); + x.map_or((), |x| take_ref(&x)); +} + fn warn_rename_call() { let x = box A; -- cgit 1.4.1-3-g733a5 From 328d2c76260631aa8da7d0c64eeb95f2592630d1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 1 Feb 2016 12:47:31 +0100 Subject: add lint to check for enums where all variants have the same pre-/postfix --- README.md | 3 +- src/enum_variants.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/enum_variants.rs diff --git a/README.md b/README.md index 36037036147..9b249636c66 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 105 lints included in this crate: +There are 106 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -30,6 +30,7 @@ name [derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do diff --git a/src/enum_variants.rs b/src/enum_variants.rs new file mode 100644 index 00000000000..bf0025e021c --- /dev/null +++ b/src/enum_variants.rs @@ -0,0 +1,90 @@ +//! lint on enum variants that are prefixed or suffixed by the same characters + +use rustc::lint::*; +use syntax::attr::*; +use syntax::ast::*; +use syntax::parse::token::InternedString; + +use utils::span_help_and_lint; + +/// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters +/// +/// **Why is this bad?** Enum variant names should specify their variant, not the enum, too. +/// +/// **Known problems:** None +/// +/// **Example:** enum Cake { BlackForestCake, HummingbirdCake } +declare_lint! { pub ENUM_VARIANT_NAMES, Warn, + "finds enums where all variants share a prefix/postfix" } + +pub struct EnumVariantNames; + +impl LintPass for EnumVariantNames { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_VARIANT_NAMES) + } +} + +fn var2str(var: &Variant) -> InternedString { + var.node.name.name.as_str() +} + +fn partial_match(left: &str, right: &str) -> usize { + left.chars().zip(right.chars()).take_while(|&(l, r)| l == r).count() +} + +fn partial_rmatch(left: &str, right: &str) -> usize { + left.chars().rev().zip(right.chars().rev()).take_while(|&(l, r)| l == r).count() +} + +impl EarlyLintPass for EnumVariantNames { + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemEnum(ref def, _) = item.node { + if def.variants.len() < 2 { + return; + } + let first = var2str(&*def.variants[0]); + let mut pre = first.to_string(); + let mut post = pre.clone(); + for var in &def.variants[1..] { + let name = var2str(var); + let pre_match = partial_match(&pre, &name); + let post_match = partial_rmatch(&post, &name); + pre.truncate(pre_match); + let post_end = post.len() - post_match; + post.drain(..post_end); + } + if let Some(c) = first[pre.len()..].chars().next() { + if !c.is_uppercase() { + // non camel case prefix + pre.clear() + } + } + if let Some(c) = first[..(first.len() - post.len())].chars().rev().next() { + if let Some(c1) = post.chars().next() { + if !c.is_lowercase() || !c1.is_uppercase() { + // non camel case postfix + post.clear() + } + } + } + if pre == "_" { + // don't lint on underscores which are meant to allow dead code + pre.clear(); + } + let (what, value) = if !pre.is_empty() { + ("pre", pre) + } else if !post.is_empty() { + ("post", post) + } else { + return + }; + span_help_and_lint(cx, + ENUM_VARIANT_NAMES, + item.span, + &format!("All variants have the same {}fix: `{}`", what, value), + &format!("remove the {}fixes and use full paths to \ + the variants instead of glob imports", what)); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6d8ea99ebcc..15d1db19d97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,7 @@ pub mod ptr_arg; pub mod needless_bool; pub mod approx_const; pub mod eta_reduction; +pub mod enum_variants; pub mod identity_op; pub mod items_after_statements; pub mod minmax; @@ -93,6 +94,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); + reg.register_early_lint_pass(box enum_variants::EnumVariantNames); reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); @@ -183,6 +185,7 @@ pub fn plugin_registrar(reg: &mut Registry) { derive::DERIVE_HASH_NOT_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, entry::MAP_ENTRY, + enum_variants::ENUM_VARIANT_NAMES, eq_op::EQ_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, -- cgit 1.4.1-3-g733a5 From 3b1df8d3814752b704fb741af2b10ebb2fd98243 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 1 Feb 2016 12:51:33 +0100 Subject: fallout --- src/consts.rs | 167 +++++++++++----------- src/identity_op.rs | 5 +- src/loops.rs | 4 +- src/methods.rs | 197 +++++++++++++------------- src/zero_div_zero.rs | 4 +- tests/cc_seme.rs | 10 +- tests/compile-fail/complex_types.rs | 4 +- tests/compile-fail/no_effect.rs | 12 +- tests/compile-fail/used_underscore_binding.rs | 10 +- tests/consts.rs | 13 +- 10 files changed, 210 insertions(+), 216 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 31094e5b6c6..f590095d9f2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -12,7 +12,6 @@ use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; use std::fmt; -use self::Constant::*; use self::FloatWidth::*; use syntax::ast::Lit_::*; @@ -44,25 +43,25 @@ impl From<FloatTy> for FloatWidth { #[derive(Eq, Debug, Clone)] pub enum Constant { /// a String "abc" - ConstantStr(String, StrStyle), + Str(String, StrStyle), /// a Binary String b"abc" - ConstantBinary(Rc<Vec<u8>>), + Binary(Rc<Vec<u8>>), /// a single byte b'a' - ConstantByte(u8), + Byte(u8), /// a single char 'a' - ConstantChar(char), + Char(char), /// an integer - ConstantInt(u64, LitIntType), + Int(u64, LitIntType), /// a float with given type - ConstantFloat(String, FloatWidth), + Float(String, FloatWidth), /// true or false - ConstantBool(bool), + Bool(bool), /// an array of constants - ConstantVec(Vec<Constant>), + Vec(Vec<Constant>), /// also an array, but with only one constant, repeated N times - ConstantRepeat(Box<Constant>, usize), + Repeat(Box<Constant>, usize), /// a tuple of constants - ConstantTuple(Vec<Constant>), + Tuple(Vec<Constant>), } impl Constant { @@ -72,7 +71,7 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let ConstantInt(val, _) = *self { + if let Constant::Int(val, _) = *self { val // TODO we may want to check the sign if any } else { panic!("Could not convert a {:?} to u64", self); @@ -83,9 +82,9 @@ impl Constant { #[allow(cast_precision_loss)] pub fn as_float(&self) -> Option<f64> { match *self { - ConstantByte(b) => Some(b as f64), - ConstantFloat(ref s, _) => s.parse().ok(), - ConstantInt(i, ty) => { + Constant::Byte(b) => Some(b as f64), + Constant::Float(ref s, _) => s.parse().ok(), + Constant::Int(i, ty) => { Some(if is_negative(ty) { -(i as f64) } else { @@ -100,14 +99,14 @@ impl Constant { impl PartialEq for Constant { fn eq(&self, other: &Constant) -> bool { match (self, other) { - (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => ls == rs && lsty == rsty, - (&ConstantBinary(ref l), &ConstantBinary(ref r)) => l == r, - (&ConstantByte(l), &ConstantByte(r)) => l == r, - (&ConstantChar(l), &ConstantChar(r)) => l == r, - (&ConstantInt(lv, lty), &ConstantInt(rv, rty)) => { + (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => ls == rs && lsty == rsty, + (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, + (&Constant::Byte(l), &Constant::Byte(r)) => l == r, + (&Constant::Char(l), &Constant::Char(r)) => l == r, + (&Constant::Int(lv, lty), &Constant::Int(rv, rty)) => { lv == rv && (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)) } - (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => { + (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -120,10 +119,10 @@ impl PartialEq for Constant { false } } - (&ConstantBool(l), &ConstantBool(r)) => l == r, - (&ConstantVec(ref l), &ConstantVec(ref r)) => l == r, - (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => ls == rs && lv == rv, - (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l == r, + (&Constant::Bool(l), &Constant::Bool(r)) => l == r, + (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, _ => false, //TODO: Are there inter-type equalities? } } @@ -132,16 +131,16 @@ impl PartialEq for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { - (&ConstantStr(ref ls, ref lsty), &ConstantStr(ref rs, ref rsty)) => { + (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => { if lsty != rsty { None } else { Some(ls.cmp(rs)) } } - (&ConstantByte(ref l), &ConstantByte(ref r)) => Some(l.cmp(r)), - (&ConstantChar(ref l), &ConstantChar(ref r)) => Some(l.cmp(r)), - (&ConstantInt(ref lv, lty), &ConstantInt(ref rv, rty)) => { + (&Constant::Byte(ref l), &Constant::Byte(ref r)) => Some(l.cmp(r)), + (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), + (&Constant::Int(ref lv, lty), &Constant::Int(ref rv, rty)) => { Some(match (is_negative(lty) && *lv != 0, is_negative(rty) && *rv != 0) { (true, true) => rv.cmp(lv), (false, false) => lv.cmp(rv), @@ -149,7 +148,7 @@ impl PartialOrd for Constant { (false, true) => Greater, }) } - (&ConstantFloat(ref ls, lw), &ConstantFloat(ref rs, rw)) => { + (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -162,15 +161,15 @@ impl PartialOrd for Constant { None } } - (&ConstantBool(ref l), &ConstantBool(ref r)) => Some(l.cmp(r)), - (&ConstantVec(ref l), &ConstantVec(ref r)) => l.partial_cmp(&r), - (&ConstantRepeat(ref lv, ref ls), &ConstantRepeat(ref rv, ref rs)) => { + (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), + (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(&r), + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { match lv.partial_cmp(rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, } } - (&ConstantTuple(ref l), &ConstantTuple(ref r)) => l.partial_cmp(r), + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l.partial_cmp(r), _ => None, //TODO: Are there any useful inter-type orderings? } } @@ -193,21 +192,21 @@ fn format_byte(fmt: &mut fmt::Formatter, b: u8) -> fmt::Result { impl fmt::Display for Constant { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { - ConstantStr(ref s, _) => write!(fmt, "{:?}", s), - ConstantByte(ref b) => { + Constant::Str(ref s, _) => write!(fmt, "{:?}", s), + Constant::Byte(ref b) => { write!(fmt, "b'") .and_then(|_| format_byte(fmt, *b)) .and_then(|_| write!(fmt, "'")) } - ConstantBinary(ref bs) => { + Constant::Binary(ref bs) => { try!(write!(fmt, "b\"")); for b in bs.iter() { try!(format_byte(fmt, *b)); } write!(fmt, "\"") } - ConstantChar(ref c) => write!(fmt, "'{}'", c), - ConstantInt(ref i, ref ity) => { + Constant::Char(ref c) => write!(fmt, "'{}'", c), + Constant::Int(ref i, ref ity) => { let (sign, suffix) = match *ity { LitIntType::SignedIntLit(ref sity, ref sign) => { (if let Sign::Minus = *sign { @@ -229,7 +228,7 @@ impl fmt::Display for Constant { }; write!(fmt, "{}{}{}", sign, i, suffix) } - ConstantFloat(ref s, ref fw) => { + Constant::Float(ref s, ref fw) => { let suffix = match *fw { FloatWidth::Fw32 => "f32", FloatWidth::Fw64 => "f64", @@ -237,9 +236,9 @@ impl fmt::Display for Constant { }; write!(fmt, "{}{}", s, suffix) } - ConstantBool(ref b) => write!(fmt, "{}", b), - ConstantRepeat(ref c, ref n) => write!(fmt, "[{}; {}]", c, n), - ConstantVec(ref v) => { + Constant::Bool(ref b) => write!(fmt, "{}", b), + Constant::Repeat(ref c, ref n) => write!(fmt, "[{}; {}]", c, n), + Constant::Vec(ref v) => { write!(fmt, "[{}]", v.iter() @@ -247,7 +246,7 @@ impl fmt::Display for Constant { .collect::<Vec<_>>() .join(", ")) } - ConstantTuple(ref t) => { + Constant::Tuple(ref t) => { write!(fmt, "({})", t.iter() @@ -262,21 +261,21 @@ impl fmt::Display for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { match *lit { - LitStr(ref is, style) => ConstantStr(is.to_string(), style), - LitByte(b) => ConstantByte(b), - LitByteStr(ref s) => ConstantBinary(s.clone()), - LitChar(c) => ConstantChar(c), - LitInt(value, ty) => ConstantInt(value, ty), - LitFloat(ref is, ty) => ConstantFloat(is.to_string(), ty.into()), - LitFloatUnsuffixed(ref is) => ConstantFloat(is.to_string(), FwAny), - LitBool(b) => ConstantBool(b), + LitStr(ref is, style) => Constant::Str(is.to_string(), style), + LitByte(b) => Constant::Byte(b), + LitByteStr(ref s) => Constant::Binary(s.clone()), + LitChar(c) => Constant::Char(c), + LitInt(value, ty) => Constant::Int(value, ty), + LitFloat(ref is, ty) => Constant::Float(is.to_string(), ty.into()), + LitFloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FwAny), + LitBool(b) => Constant::Bool(b), } } fn constant_not(o: Constant) -> Option<Constant> { Some(match o { - ConstantBool(b) => ConstantBool(!b), - ConstantInt(value, ty) => { + Constant::Bool(b) => Constant::Bool(!b), + Constant::Int(value, ty) => { let (nvalue, nty) = match ty { SignedIntLit(ity, Plus) => { if value == ::std::u64::MAX { @@ -307,7 +306,7 @@ fn constant_not(o: Constant) -> Option<Constant> { return None; } // refuse to guess }; - ConstantInt(nvalue, nty) + Constant::Int(nvalue, nty) } _ => { return None; @@ -317,8 +316,8 @@ fn constant_not(o: Constant) -> Option<Constant> { fn constant_negate(o: Constant) -> Option<Constant> { Some(match o { - ConstantInt(value, ty) => { - ConstantInt(value, + Constant::Int(value, ty) => { + Constant::Int(value, match ty { SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), @@ -327,7 +326,7 @@ fn constant_negate(o: Constant) -> Option<Constant> { } }) } - ConstantFloat(is, ty) => ConstantFloat(neg_float_str(is), ty), + Constant::Float(is, ty) => Constant::Float(neg_float_str(is), ty), _ => { return None; } @@ -402,9 +401,9 @@ fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> Option<Constant> { if neg > pos { - unify_int_type(nty, pty, Minus).map(|ty| ConstantInt(neg - pos, ty)) + unify_int_type(nty, pty, Minus).map(|ty| Constant::Int(neg - pos, ty)) } else { - unify_int_type(nty, pty, Plus).map(|ty| ConstantInt(pos - neg, ty)) + unify_int_type(nty, pty, Plus).map(|ty| Constant::Int(pos - neg, ty)) } } @@ -416,7 +415,7 @@ fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> Optio } else { Plus }) - .and_then(|ty| l.checked_sub(r).map(|v| ConstantInt(v, ty))) + .and_then(|ty| l.checked_sub(r).map(|v| Constant::Int(v, ty))) } @@ -449,10 +448,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - ExprVec(ref vec) => self.multi(vec).map(ConstantVec), - ExprTup(ref tup) => self.multi(tup).map(ConstantTuple), + ExprVec(ref vec) => self.multi(vec).map(Constant::Vec), + ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprRepeat(ref value, ref number) => { - self.binop_apply(value, number, |v, n| Some(ConstantRepeat(Box::new(v), n.as_u64() as usize))) + self.binop_apply(value, number, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) } ExprUnary(op, ref operand) => { self.expr(operand).and_then(|o| { @@ -508,7 +507,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) -> Option<Constant> { - if let Some(ConstantBool(b)) = self.expr(cond) { + if let Some(Constant::Bool(b)) = self.expr(cond) { if b { self.block(then) } else { @@ -524,8 +523,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiAdd => { self.binop_apply(left, right, |l, r| { match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => l8.checked_add(r8).map(ConstantByte), - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + (Constant::Byte(l8), Constant::Byte(r8)) => l8.checked_add(r8).map(Constant::Byte), + (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { let (ln, rn) = (is_negative(lty), is_negative(rty)); if ln == rn { unify_int_type(lty, @@ -535,7 +534,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } else { Plus }) - .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) } else if ln { add_neg_int(r64, rty, l64, lty) } else { @@ -550,24 +549,24 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiSub => { self.binop_apply(left, right, |l, r| { match (l, r) { - (ConstantByte(l8), ConstantByte(r8)) => { + (Constant::Byte(l8), Constant::Byte(r8)) => { if r8 > l8 { None } else { - Some(ConstantByte(l8 - r8)) + Some(Constant::Byte(l8 - r8)) } } - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { match (is_negative(lty), is_negative(rty)) { (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), (true, false) => { unify_int_type(lty, rty, Minus) - .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) } (false, true) => { unify_int_type(lty, rty, Plus) - .and_then(|ty| l64.checked_add(r64).map(|v| ConstantInt(v, ty))) + .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) } } } @@ -585,8 +584,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiBitOr => self.bitop(left, right, |x, y| (x | y)), BiShl => self.bitop(left, right, |x, y| x << y), BiShr => self.bitop(left, right, |x, y| x >> y), - BiEq => self.binop_apply(left, right, |l, r| Some(ConstantBool(l == r))), - BiNe => self.binop_apply(left, right, |l, r| Some(ConstantBool(l != r))), + BiEq => self.binop_apply(left, right, |l, r| Some(Constant::Bool(l == r))), + BiNe => self.binop_apply(left, right, |l, r| Some(Constant::Bool(l != r))), BiLt => self.cmp(left, right, Less, true), BiLe => self.cmp(left, right, Greater, false), BiGe => self.cmp(left, right, Less, false), @@ -600,7 +599,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { { self.binop_apply(left, right, |l, r| { match (l, r) { - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { f(l64, r64).and_then(|value| { unify_int_type(lty, rty, @@ -609,7 +608,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } else { Minus }) - .map(|ty| ConstantInt(value, ty)) + .map(|ty| Constant::Int(value, ty)) }) } _ => None, @@ -622,10 +621,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { { self.binop_apply(left, right, |l, r| { match (l, r) { - (ConstantBool(l), ConstantBool(r)) => Some(ConstantBool(f(l as u64, r as u64) != 0)), - (ConstantByte(l8), ConstantByte(r8)) => Some(ConstantByte(f(l8 as u64, r8 as u64) as u8)), - (ConstantInt(l, lty), ConstantInt(r, rty)) => { - unify_int_type(lty, rty, Plus).map(|ty| ConstantInt(f(l, r), ty)) + (Constant::Bool(l), Constant::Bool(r)) => Some(Constant::Bool(f(l as u64, r as u64) != 0)), + (Constant::Byte(l8), Constant::Byte(r8)) => Some(Constant::Byte(f(l8 as u64, r8 as u64) as u8)), + (Constant::Int(l, lty), Constant::Int(r, rty)) => { + unify_int_type(lty, rty, Plus).map(|ty| Constant::Int(f(l, r), ty)) } _ => None, } @@ -635,7 +634,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn cmp(&mut self, left: &Expr, right: &Expr, ordering: Ordering, b: bool) -> Option<Constant> { self.binop_apply(left, right, - |l, r| l.partial_cmp(&r).map(|o| ConstantBool(b == (o == ordering)))) + |l, r| l.partial_cmp(&r).map(|o| Constant::Bool(b == (o == ordering)))) } fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> @@ -650,12 +649,12 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn short_circuit(&mut self, left: &Expr, right: &Expr, b: bool) -> Option<Constant> { self.expr(left).and_then(|left| { - if let ConstantBool(lbool) = left { + if let Constant::Bool(lbool) = left { if lbool == b { Some(left) } else { self.expr(right).and_then(|right| { - if let ConstantBool(_) = right { + if let Constant::Bool(_) = right { Some(right) } else { None diff --git a/src/identity_op.rs b/src/identity_op.rs index fd5071d4013..5fa9c7588cd 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -2,8 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use consts::{constant_simple, is_negative}; -use consts::Constant::ConstantInt; +use consts::{constant_simple, is_negative, Constant}; use utils::{span_lint, snippet, in_macro}; /// **What it does:** This lint checks for identity operations, e.g. `x + 0`. It is `Warn` by default. @@ -54,7 +53,7 @@ impl LateLintPass for IdentityOp { fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(ConstantInt(v, ty)) = constant_simple(e) { + if let Some(Constant::Int(v, ty)) = constant_simple(e) { if match m { 0 => v == 0, -1 => is_negative(ty) && v == 1, diff --git a/src/loops.rs b/src/loops.rs index 74ff9edcb6b..1baaab6abc0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -365,8 +365,8 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { // ...and both sides are compile-time constant integers... - if let Some(start_idx @ Constant::ConstantInt(..)) = constant_simple(start_expr) { - if let Some(stop_idx @ Constant::ConstantInt(..)) = constant_simple(stop_expr) { + if let Some(start_idx @ Constant::Int(..)) = constant_simple(start_expr) { + if let Some(stop_idx @ Constant::Int(..)) = constant_simple(stop_expr) { // ...and the start index is greater than the stop index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the diff --git a/src/methods.rs b/src/methods.rs index a5f27440f94..111f4d56424 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -19,9 +19,6 @@ use utils::{ use utils::MethodArgs; use rustc::middle::cstore::CrateStore; -use self::SelfKind::*; -use self::OutType::*; - #[derive(Clone)] pub struct MethodsPass; @@ -456,11 +453,11 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } } -fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) +fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { - ty::TySlice(_) => true, + ty::TySlice(_) => true, ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), ty::TyArray(_, size) => size < 32, ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | @@ -469,7 +466,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) } } if let ExprMethodCall(name, _, ref args) = expr.node { - if &name.node.as_str() == &"iter" && + if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { Some((args[0].span, "&")) } else { @@ -479,7 +476,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) match ty.sty { ty::TySlice(_) => Some((expr.span, "")), ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => if may_slice(cx, inner) { + ty::TyBox(ref inner) => if may_slice(cx, inner) { Some((expr.span, "")) } else { None }, _ => None @@ -731,180 +728,180 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { debug_impl_exists } -const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [("into_", &[ValueSelf]), - ("to_", &[RefSelf]), - ("as_", &[RefSelf, RefMutSelf]), - ("is_", &[RefSelf, NoSelf]), - ("from_", &[NoSelf])]; +const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [("into_", &[SelfKind::Value]), + ("to_", &[SelfKind::Ref]), + ("as_", &[SelfKind::Ref, SelfKind::RefMut]), + ("is_", &[SelfKind::Ref, SelfKind::No]), + ("from_", &[SelfKind::No])]; const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [("add", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Add"), ("sub", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Sub"), ("mul", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Mul"), ("div", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Div"), ("rem", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Rem"), ("shl", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Shl"), ("shr", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Shr"), ("bitand", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::BitAnd"), ("bitor", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::BitOr"), ("bitxor", 2, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::BitXor"), ("neg", 1, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Neg"), ("not", 1, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::ops::Not"), ("drop", 1, - RefMutSelf, - UnitType, + SelfKind::RefMut, + OutType::Unit, "std::ops::Drop"), ("index", 2, - RefSelf, - RefType, + SelfKind::Ref, + OutType::Ref, "std::ops::Index"), ("index_mut", 2, - RefMutSelf, - RefType, + SelfKind::RefMut, + OutType::Ref, "std::ops::IndexMut"), ("deref", 1, - RefSelf, - RefType, + SelfKind::Ref, + OutType::Ref, "std::ops::Deref"), ("deref_mut", 1, - RefMutSelf, - RefType, + SelfKind::RefMut, + OutType::Ref, "std::ops::DerefMut"), ("clone", 1, - RefSelf, - AnyType, + SelfKind::Ref, + OutType::Any, "std::clone::Clone"), ("borrow", 1, - RefSelf, - RefType, + SelfKind::Ref, + OutType::Ref, "std::borrow::Borrow"), ("borrow_mut", 1, - RefMutSelf, - RefType, + SelfKind::RefMut, + OutType::Ref, "std::borrow::BorrowMut"), ("as_ref", 1, - RefSelf, - RefType, + SelfKind::Ref, + OutType::Ref, "std::convert::AsRef"), ("as_mut", 1, - RefMutSelf, - RefType, + SelfKind::RefMut, + OutType::Ref, "std::convert::AsMut"), ("eq", 2, - RefSelf, - BoolType, + SelfKind::Ref, + OutType::Bool, "std::cmp::PartialEq"), ("cmp", 2, - RefSelf, - AnyType, + SelfKind::Ref, + OutType::Any, "std::cmp::Ord"), ("default", 0, - NoSelf, - AnyType, + SelfKind::No, + OutType::Any, "std::default::Default"), ("hash", 2, - RefSelf, - UnitType, + SelfKind::Ref, + OutType::Unit, "std::hash::Hash"), ("next", 1, - RefMutSelf, - AnyType, + SelfKind::RefMut, + OutType::Any, "std::iter::Iterator"), ("into_iter", 1, - ValueSelf, - AnyType, + SelfKind::Value, + OutType::Any, "std::iter::IntoIterator"), ("from_iter", 1, - NoSelf, - AnyType, + SelfKind::No, + OutType::Any, "std::iter::FromIterator"), ("from_str", 1, - NoSelf, - AnyType, + SelfKind::No, + OutType::Any, "std::str::FromStr")]; #[derive(Clone, Copy)] enum SelfKind { - ValueSelf, - RefSelf, - RefMutSelf, - NoSelf, + Value, + Ref, + RefMut, + No, } impl SelfKind { fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool { match (self, slf) { - (&ValueSelf, &SelfValue(_)) => true, - (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true, - (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true, - (&RefSelf, &SelfValue(_)) => allow_value_for_ref, - (&RefMutSelf, &SelfValue(_)) => allow_value_for_ref, - (&NoSelf, &SelfStatic) => true, + (&SelfKind::Value, &SelfValue(_)) => true, + (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) => true, + (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) => true, + (&SelfKind::Ref, &SelfValue(_)) => allow_value_for_ref, + (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, + (&SelfKind::No, &SelfStatic) => true, (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), _ => false, } @@ -912,41 +909,41 @@ impl SelfKind { fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool { match (self, &ty.node) { - (&ValueSelf, &TyPath(..)) => true, - (&RefSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true, - (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, - (&RefSelf, &TyPath(..)) => allow_value_for_ref, - (&RefMutSelf, &TyPath(..)) => allow_value_for_ref, + (&SelfKind::Value, &TyPath(..)) => true, + (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true, + (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, + (&SelfKind::Ref, &TyPath(..)) => allow_value_for_ref, + (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, _ => false, } } fn description(&self) -> &'static str { match *self { - ValueSelf => "self by value", - RefSelf => "self by reference", - RefMutSelf => "self by mutable reference", - NoSelf => "no self", + SelfKind::Value => "self by value", + SelfKind::Ref => "self by reference", + SelfKind::RefMut => "self by mutable reference", + SelfKind::No => "no self", } } } #[derive(Clone, Copy)] enum OutType { - UnitType, - BoolType, - AnyType, - RefType, + Unit, + Bool, + Any, + Ref, } impl OutType { fn matches(&self, ty: &FunctionRetTy) -> bool { match (self, ty) { - (&UnitType, &DefaultReturn(_)) => true, - (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![].into()) => true, - (&BoolType, &Return(ref ty)) if is_bool(ty) => true, - (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, - (&RefType, &Return(ref ty)) => { + (&OutType::Unit, &DefaultReturn(_)) => true, + (&OutType::Unit, &Return(ref ty)) if ty.node == TyTup(vec![].into()) => true, + (&OutType::Bool, &Return(ref ty)) if is_bool(ty) => true, + (&OutType::Any, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, + (&OutType::Ref, &Return(ref ty)) => { if let TyRptr(_, _) = ty.node { true } else { diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 5a4d3931606..2c3ec86936c 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -35,8 +35,8 @@ impl LateLintPass for ZeroDivZeroPass { // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - let Some(Constant::ConstantFloat(ref lhs_value, lhs_width)) = constant_simple(left), - let Some(Constant::ConstantFloat(ref rhs_value, rhs_width)) = constant_simple(right), + let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), + let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), let Some(0.0) = lhs_value.parse().ok(), let Some(0.0) = rhs_value.parse().ok() ], diff --git a/tests/cc_seme.rs b/tests/cc_seme.rs index a26731c396a..cc02853c70a 100644 --- a/tests/cc_seme.rs +++ b/tests/cc_seme.rs @@ -3,8 +3,8 @@ #[allow(dead_code)] enum Baz { - Baz1, - Baz2, + One, + Two, } struct Test { @@ -14,11 +14,11 @@ struct Test { fn main() { use Baz::*; - let x = Test { t: Some(0), b: Baz1 }; + let x = Test { t: Some(0), b: One }; match x { - Test { t: Some(_), b: Baz1 } => unreachable!(), - Test { t: Some(42), b: Baz2 } => unreachable!(), + Test { t: Some(_), b: One } => unreachable!(), + Test { t: Some(42), b: Two } => unreachable!(), Test { t: None, .. } => unreachable!(), Test { .. } => unreachable!(), } diff --git a/tests/compile-fail/complex_types.rs b/tests/compile-fail/complex_types.rs index 995132ba88c..ad01e4fadd5 100644 --- a/tests/compile-fail/complex_types.rs +++ b/tests/compile-fail/complex_types.rs @@ -16,8 +16,8 @@ struct S { struct TS(Vec<Vec<Box<(u32, u32, u32, u32)>>>); //~ERROR very complex type enum E { - V1(Vec<Vec<Box<(u32, u32, u32, u32)>>>), //~ERROR very complex type - V2 { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, //~ERROR very complex type + Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>), //~ERROR very complex type + Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, //~ERROR very complex type } impl S { diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index 8da119eb16d..21118b82718 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -11,8 +11,8 @@ struct Struct { field: i32 } enum Enum { - TupleVariant(i32), - StructVariant { field: i32 }, + Tuple(i32), + Struct { field: i32 }, } fn get_number() -> i32 { 0 } @@ -26,14 +26,14 @@ fn main() { Tuple(0); //~ERROR statement with no effect Struct { field: 0 }; //~ERROR statement with no effect Struct { ..s }; //~ERROR statement with no effect - Enum::TupleVariant(0); //~ERROR statement with no effect - Enum::StructVariant { field: 0 }; //~ERROR statement with no effect + Enum::Tuple(0); //~ERROR statement with no effect + Enum::Struct { field: 0 }; //~ERROR statement with no effect // Do not warn get_number(); Tuple(get_number()); Struct { field: get_number() }; Struct { ..get_struct() }; - Enum::TupleVariant(get_number()); - Enum::StructVariant { field: get_number() }; + Enum::Tuple(get_number()); + Enum::Struct { field: get_number() }; } diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 39a33c96876..281d92c46df 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -50,17 +50,17 @@ fn multiple_underscores(__foo: u32) -> u32 { fn _fn_test() {} struct _StructTest; enum _EnumTest { - _FieldA, - _FieldB(_StructTest) + _Empty, + _Value(_StructTest) } /// Test that we do not lint for non-variable bindings fn non_variables() { _fn_test(); let _s = _StructTest; - let _e = match _EnumTest::_FieldB(_StructTest) { - _EnumTest::_FieldA => 0, - _EnumTest::_FieldB(_st) => 1, + let _e = match _EnumTest::_Value(_StructTest) { + _EnumTest::_Empty => 0, + _EnumTest::_Value(_st) => 1, }; let f = _fn_test; f(); diff --git a/tests/consts.rs b/tests/consts.rs index 5ddcd6df7b8..75082e646a0 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -18,7 +18,6 @@ use syntax::ast::StrStyle::*; use syntax::ast::Sign::*; use clippy::consts::{constant_simple, Constant}; -use clippy::consts::Constant::*; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } @@ -45,18 +44,18 @@ fn check(expect: Constant, expr: &Expr) { assert_eq!(Some(expect), constant_simple(expr)) } -const TRUE : Constant = ConstantBool(true); -const FALSE : Constant = ConstantBool(false); -const ZERO : Constant = ConstantInt(0, UnsuffixedIntLit(Plus)); -const ONE : Constant = ConstantInt(1, UnsuffixedIntLit(Plus)); -const TWO : Constant = ConstantInt(2, UnsuffixedIntLit(Plus)); +const TRUE : Constant = Constant::Bool(true); +const FALSE : Constant = Constant::Bool(false); +const ZERO : Constant = Constant::Int(0, UnsuffixedIntLit(Plus)); +const ONE : Constant = Constant::Int(1, UnsuffixedIntLit(Plus)); +const TWO : Constant = Constant::Int(2, UnsuffixedIntLit(Plus)); #[test] fn test_lit() { check(TRUE, &lit(LitBool(true))); check(FALSE, &lit(LitBool(false))); check(ZERO, &lit(LitInt(0, UnsuffixedIntLit(Plus)))); - check(ConstantStr("cool!".into(), CookedStr), &lit(LitStr( + check(Constant::Str("cool!".into(), CookedStr), &lit(LitStr( InternedString::new("cool!"), CookedStr))); } -- cgit 1.4.1-3-g733a5 From 3a31576d76f5cab4554da5b511f4a065bf5f92b5 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 1 Feb 2016 20:37:07 +0100 Subject: fixed #606 --- src/escape.rs | 8 ++++---- tests/compile-fail/escape_analysis.rs | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index edc7b5c6fbb..68dd2307e3f 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -31,9 +31,9 @@ pub struct EscapePass; /// ``` declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); -fn is_box(ty: ty::Ty) -> bool { +fn is_non_trait_box(ty: ty::Ty) -> bool { match ty.sty { - ty::TyBox(..) => true, + ty::TyBox(ref inner) => !inner.is_trait(), _ => false } } @@ -90,7 +90,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { return; } - if is_box(cmt.ty) { + if is_non_trait_box(cmt.ty) { self.set.insert(consume_pat.id); } return; @@ -101,7 +101,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { if let ExprBox(..) = ex.node { - if is_box(cmt.ty) { + if is_non_trait_box(cmt.ty) { // let x = box (...) self.set.insert(consume_pat.id); } diff --git a/tests/compile-fail/escape_analysis.rs b/tests/compile-fail/escape_analysis.rs index f3aa8bff41c..c0893bcd767 100644 --- a/tests/compile-fail/escape_analysis.rs +++ b/tests/compile-fail/escape_analysis.rs @@ -11,9 +11,24 @@ impl A { fn foo(&self){} } +trait Z { + fn bar(&self); +} + +impl Z for A { + fn bar(&self) { + //nothing + } +} + fn main() { } +fn ok_box_trait(boxed_trait: &Box<Z>) { + let boxed_local = boxed_trait; + // done +} + fn warn_call() { let x = box A; //~ ERROR local variable x.foo(); -- cgit 1.4.1-3-g733a5 From bd86922c4f33e2528bb87a7f693e57935970f1cf Mon Sep 17 00:00:00 2001 From: inrustwetrust <inrustwetrust@users.noreply.github.com> Date: Mon, 1 Feb 2016 19:53:03 +0100 Subject: Add lint to warn for calls to `std::mem::drop` with a reference argument --- README.md | 3 ++- src/drop_ref.rs | 61 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ src/utils.rs | 1 + tests/compile-fail/drop_ref.rs | 43 +++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/drop_ref.rs create mode 100644 tests/compile-fail/drop_ref.rs diff --git a/README.md b/README.md index 9b249636c66..d24dc3de1bd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 106 lints included in this crate: +There are 107 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -28,6 +28,7 @@ name [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly +[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix diff --git a/src/drop_ref.rs b/src/drop_ref.rs new file mode 100644 index 00000000000..fecb69f5c14 --- /dev/null +++ b/src/drop_ref.rs @@ -0,0 +1,61 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use rustc::middle::ty; +use syntax::codemap::Span; + +use utils::DROP_PATH; +use utils::{match_def_path, span_note_and_lint}; + +/// **What it does:** This lint checks for calls to `std::mem::drop` with a reference instead of an owned value. +/// +/// **Why is this bad?** Calling `drop` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` method (from the `Drop` trait implementation) on the underlying referenced value, which is likely what was intended. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let mut lock_guard = mutex.lock(); +/// std::mem::drop(&lock_guard) //Should have been drop(lock_guard), mutex still locked +/// operation_that_requires_mutex_to_be_unlocked(); +/// ``` +declare_lint!(pub DROP_REF, Warn, + "call to `std::mem::drop` with a reference instead of an owned value, \ + which will not not call the `Drop::drop` method on the underlying value"); + +#[allow(missing_copy_implementations)] +pub struct DropRefPass; + +impl LintPass for DropRefPass { + fn get_lints(&self) -> LintArray { + lint_array!(DROP_REF) + } +} + +impl LateLintPass for DropRefPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprCall(ref path, ref args) = expr.node { + if let ExprPath(None, _) = path.node { + let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + if match_def_path(cx, def_id, &DROP_PATH) { + if args.len() != 1 { + return; + } + check_drop_arg(cx, expr.span, &*args[0]); + } + } + } + } +} + +fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) { + let arg_ty = cx.tcx.expr_ty(arg); + if let ty::TyRef(..) = arg_ty.sty { + span_note_and_lint(cx, + DROP_REF, + call_span, + "call to `std::mem::drop` with a reference argument. \ + Dropping a reference does nothing", + arg.span, + &format!("argument has type {}", arg_ty.sty)); + } +} diff --git a/src/lib.rs b/src/lib.rs index 15d1db19d97..e2596dd58ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,7 @@ pub mod panic; pub mod derive; pub mod print; pub mod vec; +pub mod drop_ref; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -148,6 +149,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); + reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_lint_group("clippy_pedantic", vec![ @@ -184,6 +186,7 @@ pub fn plugin_registrar(reg: &mut Registry) { cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_NOT_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, + drop_ref::DROP_REF, entry::MAP_ENTRY, enum_variants::ENUM_VARIANT_NAMES, eq_op::EQ_OP, diff --git a/src/utils.rs b/src/utils.rs index ff0c59ab290..bc6fcd44891 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,6 +27,7 @@ pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; +pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; diff --git a/tests/compile-fail/drop_ref.rs b/tests/compile-fail/drop_ref.rs new file mode 100644 index 00000000000..3e4c0a9d8ec --- /dev/null +++ b/tests/compile-fail/drop_ref.rs @@ -0,0 +1,43 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(drop_ref)] +#![allow(toplevel_ref_arg)] + +use std::mem::drop; + +struct DroppableStruct; +impl Drop for DroppableStruct { fn drop(&mut self) {} } + +fn main() { + drop(&DroppableStruct); //~ERROR call to `std::mem::drop` with a reference argument + + let mut owned = DroppableStruct; + drop(&owned); //~ERROR call to `std::mem::drop` with a reference argument + drop(&&owned); //~ERROR call to `std::mem::drop` with a reference argument + drop(&mut owned); //~ERROR call to `std::mem::drop` with a reference argument + drop(owned); //OK + + let reference1 = &DroppableStruct; + drop(reference1); //~ERROR call to `std::mem::drop` with a reference argument + drop(&*reference1); //~ERROR call to `std::mem::drop` with a reference argument + + let reference2 = &mut DroppableStruct; + drop(reference2); //~ERROR call to `std::mem::drop` with a reference argument + + let ref reference3 = DroppableStruct; + drop(reference3); //~ERROR call to `std::mem::drop` with a reference argument +} + +#[allow(dead_code)] +fn test_generic_fn<T>(val: T) { + drop(&val); //~ERROR call to `std::mem::drop` with a reference argument + drop(val); //OK +} + +#[allow(dead_code)] +fn test_similarly_named_function() { + fn drop<T>(_val: T) {} + drop(&DroppableStruct); //OK; call to unrelated function which happens to have the same name + std::mem::drop(&DroppableStruct); //~ERROR call to `std::mem::drop` with a reference argument +} -- cgit 1.4.1-3-g733a5 From d93eca29fc5ca6bf127405f156c3bbf7b69611d2 Mon Sep 17 00:00:00 2001 From: inrustwetrust <inrustwetrust@users.noreply.github.com> Date: Tue, 2 Feb 2016 20:38:14 +0100 Subject: Fix typo in drop_ref lint description. --- README.md | 2 +- src/drop_ref.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d24dc3de1bd..0c5b12df8ae 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ name [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not not call the `Drop::drop` method on the underlying value +[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected [enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix diff --git a/src/drop_ref.rs b/src/drop_ref.rs index fecb69f5c14..c15689d8cd6 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -20,7 +20,7 @@ use utils::{match_def_path, span_note_and_lint}; /// ``` declare_lint!(pub DROP_REF, Warn, "call to `std::mem::drop` with a reference instead of an owned value, \ - which will not not call the `Drop::drop` method on the underlying value"); + which will not call the `Drop::drop` method on the underlying value"); #[allow(missing_copy_implementations)] pub struct DropRefPass; -- cgit 1.4.1-3-g733a5 From 0c726e8077f9effe36dfa1358f87e71c941961f0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 13:39:16 +0100 Subject: Restore some of rustfmt madness --- src/methods.rs | 198 ++++++++++++--------------------------------------------- 1 file changed, 42 insertions(+), 156 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 111f4d56424..dfa9a90d9cf 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -728,162 +728,48 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { debug_impl_exists } -const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [("into_", &[SelfKind::Value]), - ("to_", &[SelfKind::Ref]), - ("as_", &[SelfKind::Ref, SelfKind::RefMut]), - ("is_", &[SelfKind::Ref, SelfKind::No]), - ("from_", &[SelfKind::No])]; - -const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [("add", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Add"), - ("sub", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Sub"), - ("mul", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Mul"), - ("div", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Div"), - ("rem", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Rem"), - ("shl", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Shl"), - ("shr", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::Shr"), - ("bitand", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::BitAnd"), - ("bitor", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::BitOr"), - ("bitxor", - 2, - SelfKind::Value, - OutType::Any, - "std::ops::BitXor"), - ("neg", - 1, - SelfKind::Value, - OutType::Any, - "std::ops::Neg"), - ("not", - 1, - SelfKind::Value, - OutType::Any, - "std::ops::Not"), - ("drop", - 1, - SelfKind::RefMut, - OutType::Unit, - "std::ops::Drop"), - ("index", - 2, - SelfKind::Ref, - OutType::Ref, - "std::ops::Index"), - ("index_mut", - 2, - SelfKind::RefMut, - OutType::Ref, - "std::ops::IndexMut"), - ("deref", - 1, - SelfKind::Ref, - OutType::Ref, - "std::ops::Deref"), - ("deref_mut", - 1, - SelfKind::RefMut, - OutType::Ref, - "std::ops::DerefMut"), - ("clone", - 1, - SelfKind::Ref, - OutType::Any, - "std::clone::Clone"), - ("borrow", - 1, - SelfKind::Ref, - OutType::Ref, - "std::borrow::Borrow"), - ("borrow_mut", - 1, - SelfKind::RefMut, - OutType::Ref, - "std::borrow::BorrowMut"), - ("as_ref", - 1, - SelfKind::Ref, - OutType::Ref, - "std::convert::AsRef"), - ("as_mut", - 1, - SelfKind::RefMut, - OutType::Ref, - "std::convert::AsMut"), - ("eq", - 2, - SelfKind::Ref, - OutType::Bool, - "std::cmp::PartialEq"), - ("cmp", - 2, - SelfKind::Ref, - OutType::Any, - "std::cmp::Ord"), - ("default", - 0, - SelfKind::No, - OutType::Any, - "std::default::Default"), - ("hash", - 2, - SelfKind::Ref, - OutType::Unit, - "std::hash::Hash"), - ("next", - 1, - SelfKind::RefMut, - OutType::Any, - "std::iter::Iterator"), - ("into_iter", - 1, - SelfKind::Value, - OutType::Any, - "std::iter::IntoIterator"), - ("from_iter", - 1, - SelfKind::No, - OutType::Any, - "std::iter::FromIterator"), - ("from_str", - 1, - SelfKind::No, - OutType::Any, - "std::str::FromStr")]; +#[rustfmt_skip] +const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ + ("into_", &[SelfKind::Value]), + ("to_", &[SelfKind::Ref]), + ("as_", &[SelfKind::Ref, SelfKind::RefMut]), + ("is_", &[SelfKind::Ref, SelfKind::No]), + ("from_", &[SelfKind::No]), +]; + +#[rustfmt_skip] +const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ + ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), + ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), + ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), + ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), + ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), + ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), + ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), + ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), + ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), + ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), + ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), + ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), + ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), + ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), + ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), + ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), + ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), + ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), + ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), + ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), + ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), + ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), + ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), + ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), + ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), + ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), + ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), + ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), +]; #[derive(Clone, Copy)] enum SelfKind { -- cgit 1.4.1-3-g733a5 From c0d2fdc723bff9e271e00da4d24c125b1e19762a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 13:48:39 +0100 Subject: Partially apply rustfmt --- src/attrs.rs | 6 +++--- src/bit_mask.rs | 1 - src/derive.rs | 19 ++++++++----------- src/escape.rs | 2 +- src/items_after_statements.rs | 6 ++++-- src/lifetimes.rs | 29 ++++++++++++++-------------- src/loops.rs | 9 +++------ src/matches.rs | 34 +++++++++++++++++---------------- src/methods.rs | 44 +++++++++++++++++++++++++------------------ src/print.rs | 5 +---- src/shadow.rs | 8 ++++---- src/utils.rs | 14 +++++++++----- 12 files changed, 92 insertions(+), 85 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 853e2ab5910..012c4e502b4 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -60,10 +60,10 @@ impl LateLintPass for AttrPass { check_semver(cx, item.span, lit); } } - } + } } } - + fn check_item(&mut self, cx: &LateContext, item: &Item) { if is_relevant_item(item) { check_attrs(cx, item.span, &item.name, &item.attrs) @@ -164,7 +164,7 @@ fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { return; } } - span_lint(cx, + span_lint(cx, DEPRECATED_SEMVER, span, "the since field must contain a semver-compliant version"); diff --git a/src/bit_mask.rs b/src/bit_mask.rs index b0d3c3d3f78..0fce772010a 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -151,7 +151,6 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } - } BiBitOr => { if mask_value | cmp_value != cmp_value { diff --git a/src/derive.rs b/src/derive.rs index ca7649f75b3..d8f331ef5ff 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -158,15 +158,13 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: _ => (), } - span_lint_and_then( - cx, DERIVE_HASH_NOT_EQ, span, - "you are implementing `Clone` explicitly on a `Copy` type", - |db| { - db.span_note( - span, - "consider deriving `Clone` or removing `Copy`" - ); - }); + span_lint_and_then(cx, + DERIVE_HASH_NOT_EQ, + span, + "you are implementing `Clone` explicitly on a `Copy` type", + |db| { + db.span_note(span, "consider deriving `Clone` or removing `Copy`"); + }); } } @@ -174,8 +172,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: fn is_automatically_derived(attr: &Attribute) -> bool { if let MetaItem_::MetaWord(ref word) = attr.node.value.node { word == &"automatically_derived" - } - else { + } else { false } } diff --git a/src/escape.rs b/src/escape.rs index 68dd2307e3f..bd6687e3f0d 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -34,7 +34,7 @@ declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); fn is_non_trait_box(ty: ty::Ty) -> bool { match ty.sty { ty::TyBox(ref inner) => !inner.is_trait(), - _ => false + _ => false, } } diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 8eb3364b2bd..ad666a3bf3f 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -56,8 +56,10 @@ impl EarlyLintPass for ItemsAfterStatemets { if in_macro(cx, it.span) { return; } - cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, it.span, - "adding items after statements is confusing, since items exist from the start of the scope") + cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, + it.span, + "adding items after statements is confusing, since items exist from the \ + start of the scope") .emit(); } } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 1441015eb0e..b6f8ebe5fd8 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -68,9 +68,13 @@ enum RefLt { fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { if let TraitTyParamBound(ref trait_ref, _) = *bound { - let lt = trait_ref.trait_ref.path.segments - .last().expect("a path must have at least one segment") - .parameters.lifetimes(); + let lt = trait_ref.trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .parameters + .lifetimes(); Some(lt) } else { @@ -83,10 +87,9 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g return; } - let bounds_lts = - generics.ty_params - .iter() - .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); + let bounds_lts = generics.ty_params + .iter() + .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); if could_use_elision(cx, decl, slf, &generics.lifetimes, bounds_lts) { span_lint(cx, @@ -97,10 +100,9 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g report_extra_lifetimes(cx, decl, &generics, slf); } -fn could_use_elision<'a, T: Iterator<Item=&'a Lifetime>>( - cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, - named_lts: &[LifetimeDef], bounds_lts: T -) -> bool { +fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, + named_lts: &[LifetimeDef], bounds_lts: T) + -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT // * output references, exactly one input reference with same LT @@ -185,7 +187,7 @@ fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { allowed_lts } -fn lts_from_bounds<'a, T: Iterator<Item=&'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> { +fn lts_from_bounds<'a, T: Iterator<Item = &'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> { for lt in bounds_lts { if lt.name.as_str() != "'static" { vec.push(RefLt::Named(lt.name)); @@ -332,8 +334,7 @@ impl<'v> Visitor<'v> for LifetimeChecker { } } -fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, - generics: &Generics, slf: Option<&ExplicitSelf>) { +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics, slf: Option<&ExplicitSelf>) { let hs = generics.lifetimes .iter() .map(|lt| (lt.lifetime.name, lt.lifetime.span)) diff --git a/src/loops.rs b/src/loops.rs index 1baaab6abc0..20c75e08d23 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -296,16 +296,14 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex let skip: Cow<_> = if starts_at_zero { "".into() - } - else { + } else { format!(".skip({})", snippet(cx, l.span, "..")).into() }; let take: Cow<_> = if let Some(ref r) = *r { if !is_len_call(&r, &indexed) { format!(".take({})", snippet(cx, r.span, "..")).into() - } - else { + } else { "".into() } } else { @@ -327,8 +325,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex } else { let repl = if starts_at_zero && take.is_empty() { format!("&{}", indexed) - } - else { + } else { format!("{}.iter(){}{}", indexed, take, skip) }; diff --git a/src/matches.rs b/src/matches.rs index c866a48d223..e690f04bdb0 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -192,7 +192,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: }, PatEnum(ref path, None) => path.to_string(), PatIdent(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), - _ => return + _ => return, }; for &(ty_path, pat_path) in candidates { @@ -206,15 +206,17 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: span_lint_and_then(cx, lint, expr.span, - "you seem to be trying to use match for destructuring a single pattern. \ - Consider using `if let`", |db| { - db.span_suggestion(expr.span, "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); + "you seem to be trying to use match for destructuring a single pattern. Consider \ + using `if let`", + |db| { + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); } } } @@ -267,12 +269,12 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { span_lint_and_then(cx, MATCH_BOOL, expr.span, - "you seem to be trying to match on a boolean expression. Consider using \ - an if..else block:", move |db| { - if let Some(sugg) = sugg { - db.span_suggestion(expr.span, "try this", sugg); - } - }); + "you seem to be trying to match on a boolean expression. Consider using an if..else block:", + move |db| { + if let Some(sugg) = sugg { + db.span_suggestion(expr.span, "try this", sugg); + } + }); } } diff --git a/src/methods.rs b/src/methods.rs index dfa9a90d9cf..d40ab250a7f 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -349,16 +349,18 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) if name == "unwrap_or" { if let ExprPath(_, ref path) = fun.node { - let path : &str = &path.segments.last() - .expect("A path must have at least one segment") - .identifier.name.as_str(); + let path: &str = &path.segments + .last() + .expect("A path must have at least one segment") + .identifier + .name + .as_str(); if ["default", "new"].contains(&path) { let arg_ty = cx.tcx.expr_ty(arg); let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { default_trait_id - } - else { + } else { return false; }; @@ -408,7 +410,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) }; if !poss.contains(&name) { - return + return; } let sugg = match (fn_has_arguments, !or_has_args) { @@ -444,17 +446,20 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } let arg_ty = cx.tcx.expr_ty(&args[1]); if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { - span_lint(cx, EXTEND_FROM_SLICE, expr.span, + span_lint(cx, + EXTEND_FROM_SLICE, + expr.span, &format!("use of `extend` to extend a Vec by a slice")) - .span_suggestion(expr.span, "try this", + .span_suggestion(expr.span, + "try this", format!("{}.extend_from_slice({}{})", snippet(cx, args[0].span, "_"), - r, snippet(cx, span, "_"))); + r, + snippet(cx, span, "_"))); } } -fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) - -> Option<(Span, &'static str)> { +fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { ty::TySlice(_) => true, @@ -462,12 +467,11 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) ty::TyArray(_, size) => size < 32, ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | ty::TyBox(ref inner) => may_slice(cx, inner), - _ => false + _ => false, } } if let ExprMethodCall(name, _, ref args) = expr.node { - if &name.node.as_str() == &"iter" && - may_slice(cx, &cx.tcx.expr_ty(&args[0])) { + if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { Some((args[0].span, "&")) } else { None @@ -476,10 +480,14 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) match ty.sty { ty::TySlice(_) => Some((expr.span, "")), ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => if may_slice(cx, inner) { - Some((expr.span, "")) - } else { None }, - _ => None + ty::TyBox(ref inner) => { + if may_slice(cx, inner) { + Some((expr.span, "")) + } else { + None + } + } + _ => None, } } } diff --git a/src/print.rs b/src/print.rs index a47fa69b2e8..930952bdbaf 100644 --- a/src/print.rs +++ b/src/print.rs @@ -37,10 +37,7 @@ impl LateLintPass for PrintLint { None => (span, "print"), }; - span_lint(cx, - PRINT_STDOUT, - span, - &format!("use of `{}!`", name)); + span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); } } } diff --git a/src/shadow.rs b/src/shadow.rs index 5bd392abb3c..1beb00e9056 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -211,8 +211,8 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & &format!("{} is shadowed by {} which reuses the original value", snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); + expr.span, + "initialization happens here"); note_orig(cx, db, SHADOW_REUSE, prev_span); } else { let db = span_note_and_lint(cx, @@ -221,8 +221,8 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & &format!("{} is shadowed by {}", snippet(cx, lspan, "_"), snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); + expr.span, + "initialization happens here"); note_orig(cx, db, SHADOW_UNRELATED, prev_span); } diff --git a/src/utils.rs b/src/utils.rs index bc6fcd44891..78fb45cd6cf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -209,7 +209,7 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { loop { let segment = match path_it.next() { Some(segment) => segment, - None => return None + None => return None, }; for item in &mem::replace(&mut items, vec![]) { @@ -229,8 +229,7 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { } } } - } - else { + } else { None } } @@ -250,13 +249,17 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { /// Check whether a type implements a trait. /// See also `get_trait_def_id`. -pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, ty_params: Option<Vec<ty::Ty<'tcx>>>) -> bool { +pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, + ty_params: Option<Vec<ty::Ty<'tcx>>>) + -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); let obligation = traits::predicate_for_trait_def(cx.tcx, traits::ObligationCause::dummy(), - trait_id, 0, ty, + trait_id, + 0, + ty, ty_params.unwrap_or_default()); traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) @@ -658,6 +661,7 @@ pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> (ei.callee.name(), ei.call_site) }) }); + match span_name_span { Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), None => return None, -- cgit 1.4.1-3-g733a5 From 47e26ab287447c7321214f6b9451a5238d47e9cb Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 14:01:26 +0100 Subject: Fix warnings about the rustfmt_skip attribute --- src/lib.rs | 3 +-- src/methods.rs | 4 ++-- src/misc.rs | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e2596dd58ca..e7302ea5829 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,9 +87,8 @@ mod reexport { pub use syntax::ast::{Name, NodeId}; } -#[allow(unused_attributes)] #[plugin_registrar] -#[rustfmt_skip] +#[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box misc::TopLevelRefPass); diff --git a/src/methods.rs b/src/methods.rs index d40ab250a7f..5768a6e8f85 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -736,7 +736,7 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { debug_impl_exists } -#[rustfmt_skip] +#[cfg_attr(rustfmt, rustfmt_skip)] const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ("into_", &[SelfKind::Value]), ("to_", &[SelfKind::Ref]), @@ -745,7 +745,7 @@ const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ ("from_", &[SelfKind::No]), ]; -#[rustfmt_skip] +#[cfg_attr(rustfmt, rustfmt_skip)] const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), diff --git a/src/misc.rs b/src/misc.rs index 4b6170cf164..d436d98c981 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -376,8 +376,7 @@ impl LintPass for UsedUnderscoreBinding { } impl LateLintPass for UsedUnderscoreBinding { - #[allow(unused_attributes)] - #[rustfmt_skip] + #[cfg_attr(rustfmt, rustfmt_skip)] fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_attributes_expansion(cx, expr) { // Don't lint things expanded by #[derive(...)], etc -- cgit 1.4.1-3-g733a5 From db205c82a4125446d47296c3d3463c81efb0dd3d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 2 Feb 2016 22:35:01 +0100 Subject: Add a lint about using `clone` on `Copy` types --- README.md | 3 ++- src/lib.rs | 1 + src/loops.rs | 2 +- src/methods.rs | 36 +++++++++++++++++++++++++++++++----- src/misc_early.rs | 2 +- tests/compile-fail/map_clone.rs | 2 +- tests/compile-fail/methods.rs | 15 +++++++++++++-- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 0c5b12df8ae..d7086a6dac8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 107 lints included in this crate: +There are 108 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -22,6 +22,7 @@ name [cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` [char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8 [chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char +[clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` diff --git a/src/lib.rs b/src/lib.rs index e7302ea5829..36954284184 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -214,6 +214,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::CHARS_NEXT_CMP, + methods::CLONE_ON_COPY, methods::EXTEND_FROM_SLICE, methods::FILTER_NEXT, methods::OK_EXPECT, diff --git a/src/loops.rs b/src/loops.rs index 20c75e08d23..49e073aacd0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -475,7 +475,7 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, - var_id: id.clone(), + var_id: *id, state: VarState::IncrOnce, name: None, depth: 0, diff --git a/src/methods.rs b/src/methods.rs index 5768a6e8f85..0584d39330d 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -219,6 +219,17 @@ declare_lint!(pub OR_FUN_CALL, Warn, declare_lint!(pub EXTEND_FROM_SLICE, Warn, "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"); +/// **What it does:** This lint warns on using `.clone()` on a `Copy` type. +/// +/// **Why is this bad?** The only reason `Copy` types implement `Clone` is for generics, not for +/// using the `clone` method on a concrete type. +/// +/// **Known problems:** None. +/// +/// **Example:** `42u64.clone()` +declare_lint!(pub CLONE_ON_COPY, Warn, + "using `clone` on a `Copy` type"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -233,7 +244,8 @@ impl LintPass for MethodsPass { OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE, OR_FUN_CALL, - CHARS_NEXT_CMP) + CHARS_NEXT_CMP, + CLONE_ON_COPY) } } @@ -269,6 +281,7 @@ impl LateLintPass for MethodsPass { } lint_or_fun_call(cx, expr, &name.node.as_str(), &args); + lint_clone_on_copy(cx, expr, &name.node.as_str(), &args); } ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { if !lint_chars_next(cx, expr, lhs, rhs, op.node == BiEq) { @@ -439,6 +452,19 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } } +/// Checks for the `CLONE_ON_COPY` lint. +fn lint_clone_on_copy(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { + if args.len() == 1 && name == "clone" { + let ty = cx.tcx.expr_ty(expr); + let parent = cx.tcx.map.get_parent(expr.id); + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); + + if !ty.moves_by_default(¶meter_environment, expr.span) { + span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); + } + } +} + fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); if !match_type(cx, obj_ty, &VEC_PATH) { @@ -701,7 +727,7 @@ fn lint_chars_next(cx: &LateContext, expr: &Expr, chain: &Expr, other: &Expr, eq false } -// Given a `Result<T, E>` type, return its error type (`E`) +/// Given a `Result<T, E>` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { return None; @@ -714,9 +740,9 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { None } -// This checks whether a given type is known to implement Debug. It's -// conservative, i.e. it should not return false positives, but will return -// false negatives. +/// This checks whether a given type is known to implement Debug. It's +/// conservative, i.e. it should not return false positives, but will return +/// false negatives. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { let no_ref_ty = walk_ptrs_ty(ty); let debug = match cx.tcx.lang_items.debug_trait() { diff --git a/src/misc_early.rs b/src/misc_early.rs index a90c901df8f..1573aff2a4d 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -110,7 +110,7 @@ impl EarlyLintPass for MiscEarly { arg_name[1..].to_owned())); } } else { - registered_names.insert(arg_name, arg.pat.span.clone()); + registered_names.insert(arg_name, arg.pat.span); } } } diff --git a/tests/compile-fail/map_clone.rs b/tests/compile-fail/map_clone.rs index 2e60300afda..bd630211f19 100644 --- a/tests/compile-fail/map_clone.rs +++ b/tests/compile-fail/map_clone.rs @@ -3,7 +3,7 @@ #![plugin(clippy)] #![deny(map_clone)] -#![allow(unused)] +#![allow(clone_on_copy, unused)] use std::ops::Deref; diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index c72e602ac2b..f998a83e831 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -312,14 +312,25 @@ fn use_extend_from_slice() { //~^ERROR use of `extend` //~| HELP try this //~| SUGGESTION v.extend_from_slice(&vec!["Some", "more"]); - + v.extend(vec!["And", "even", "more"].iter()); //~ERROR use of `extend` let o : Option<&'static str> = None; v.extend(o); v.extend(Some("Bye")); v.extend(vec!["Not", "like", "this"]); - v.extend(["But", "this"].iter()); + v.extend(["But", "this"].iter()); //~^ERROR use of `extend //~| HELP try this //~| SUGGESTION v.extend_from_slice(&["But", "this"]); } + +fn clone_on_copy() { + 42.clone(); //~ERROR using `clone` on a `Copy` type + vec![1].clone(); // ok, not a Copy type + Some(vec![1]).clone(); // ok, not a Copy type +} + +fn clone_on_copy_generic<T: Copy>(t: T) { + t.clone(); //~ERROR using `clone` on a `Copy` type + Some(t).clone(); //~ERROR using `clone` on a `Copy` type +} -- cgit 1.4.1-3-g733a5 From 908fb143ef06cc50f759ef38053a41d190dc73d5 Mon Sep 17 00:00:00 2001 From: scurest <scurest@users.noreply.github.com> Date: Tue, 2 Feb 2016 21:48:52 -0600 Subject: Extend ABSURD_UNSIGNED_COMPARISONS to handle more types --- README.md | 2 +- src/lib.rs | 4 +- src/types.rs | 165 ++++++++++++++++++---- tests/compile-fail/absurd-extreme-comparisons.rs | 44 ++++++ tests/compile-fail/absurd_unsigned_comparisons.rs | 14 -- 5 files changed, 183 insertions(+), 46 deletions(-) create mode 100644 tests/compile-fail/absurd-extreme-comparisons.rs delete mode 100644 tests/compile-fail/absurd_unsigned_comparisons.rs diff --git a/README.md b/README.md index 006ddcd7a7f..75d3279f9c7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ There are 109 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -[absurd_unsigned_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_unsigned_comparisons) | warn | testing whether an unsigned integer is non-positive +[absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison involving a maximum or minimum value involves a case that is always true or always false [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` diff --git a/src/lib.rs b/src/lib.rs index 44dd9fa8c86..ec609bfe206 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,7 +149,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); reg.register_late_lint_pass(box drop_ref::DropRefPass); - reg.register_late_lint_pass(box types::AbsurdUnsignedComparisons); + reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_lint_group("clippy_pedantic", vec![ @@ -255,7 +255,7 @@ pub fn plugin_registrar(reg: &mut Registry) { strings::STRING_LIT_AS_BYTES, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, - types::ABSURD_UNSIGNED_COMPARISONS, + types::ABSURD_EXTREME_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, types::LET_UNIT_VALUE, diff --git a/src/types.rs b/src/types.rs index 0ab373bfa35..fb9b05da612 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,6 +5,7 @@ use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; +use rustc::middle::const_eval; use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; use syntax::ast::FloatTy::*; @@ -558,52 +559,158 @@ impl LateLintPass for CharLitAsU8 { } } -/// **What it does:** This lint checks for expressions where an unsigned integer is tested to be non-positive and suggests testing for equality with zero instead. +/// **What it does:** This lint checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked. /// -/// **Why is this bad?** `x <= 0` may mislead the reader into thinking `x` can be negative. `x == 0` makes explicit that zero is the only possibility. +/// **Why is this bad?** An expression like `min <= x` may misleadingly imply that is is possible for `x` to be less than the minimum. Expressions like `max < x` are probably mistakes. /// /// **Known problems:** None /// -/// **Example:** `vec.len() <= 0` -declare_lint!(pub ABSURD_UNSIGNED_COMPARISONS, Warn, - "testing whether an unsigned integer is non-positive"); +/// **Example:** `vec.len() <= 0`, `100 > std::i32::MAX` +declare_lint!(pub ABSURD_EXTREME_COMPARISONS, Warn, + "a comparison involving a maximum or minimum value involves a case that is always \ + true or always false"); -pub struct AbsurdUnsignedComparisons; +pub struct AbsurdExtremeComparisons; -impl LintPass for AbsurdUnsignedComparisons { +impl LintPass for AbsurdExtremeComparisons { fn get_lints(&self) -> LintArray { - lint_array!(ABSURD_UNSIGNED_COMPARISONS) + lint_array!(ABSURD_EXTREME_COMPARISONS) } } -fn is_zero_lit(expr: &Expr) -> bool { - use syntax::ast::Lit_; +enum ExtremeType { + Minimum, + Maximum, +} + +struct ExtremeExpr<'a> { + which: ExtremeType, + expr: &'a Expr, +} + +enum AbsurdComparisonResult { + AlwaysFalse, + AlwaysTrue, + InequalityImpossible, +} + +fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) + -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { + use types::ExtremeType::*; + use types::AbsurdComparisonResult::*; + type Extr<'a> = ExtremeExpr<'a>; + + // Put the expression in the form lhs < rhs or lhs <= rhs. + enum Rel { Lt, Le }; + let (rel, lhs2, rhs2) = match op { + BiLt => (Rel::Lt, lhs, rhs), + BiLe => (Rel::Le, lhs, rhs), + BiGt => (Rel::Lt, rhs, lhs), + BiGe => (Rel::Le, rhs, lhs), + _ => return None, + }; + + let lx = detect_extreme_expr(cx, lhs2); + let rx = detect_extreme_expr(cx, rhs2); - if let ExprLit(ref l) = expr.node { - if let Lit_::LitInt(val, _) = l.node { - return val == 0; + Some(match rel { + Rel::Lt => { + match (lx, rx) { + (Some(l @ Extr { which: Maximum, ..}), _) => (l, AlwaysFalse), // max < x + (_, Some(r @ Extr { which: Minimum, ..})) => (r, AlwaysFalse), // x < min + _ => return None, + } } - } - false + Rel::Le => { + match (lx, rx) { + (Some(l @ Extr { which: Minimum, ..}), _) => (l, AlwaysTrue), // min <= x + (Some(l @ Extr { which: Maximum, ..}), _) => (l, InequalityImpossible), //max <= x + (_, Some(r @ Extr { which: Minimum, ..})) => (r, InequalityImpossible), // x <= min + (_, Some(r @ Extr { which: Maximum, ..})) => (r, AlwaysTrue), // x <= max + _ => return None, + } + } + }) } -impl LateLintPass for AbsurdUnsignedComparisons { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - let op = cmp.node; +fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeExpr<'a>> { + use rustc::middle::const_eval::EvalHint::ExprTypeChecked; + use types::ExtremeType::*; + use rustc::middle::const_eval::ConstVal::*; - let comparee = match op { - BiLe if is_zero_lit(rhs) => lhs, // x <= 0 - BiGe if is_zero_lit(lhs) => rhs, // 0 >= x - _ => return, - }; + let ty = &cx.tcx.expr_ty(expr).sty; - if let ty::TyUint(_) = cx.tcx.expr_ty(comparee).sty { + match *ty { + ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (), + _ => return None, + }; + + let cv = match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + Ok(val) => val, + Err(_) => return None, + }; + + let which = match (ty, cv) { + (&ty::TyBool, Bool(false)) => Minimum, + + (&ty::TyInt(TyIs), Int(x)) if x == ::std::isize::MIN as i64 => Minimum, + (&ty::TyInt(TyI8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum, + (&ty::TyInt(TyI16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum, + (&ty::TyInt(TyI32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum, + (&ty::TyInt(TyI64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum, + + (&ty::TyUint(TyUs), Uint(x)) if x == ::std::usize::MIN as u64 => Minimum, + (&ty::TyUint(TyU8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum, + (&ty::TyUint(TyU16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum, + (&ty::TyUint(TyU32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum, + (&ty::TyUint(TyU64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum, + + (&ty::TyBool, Bool(true)) => Maximum, + + (&ty::TyInt(TyIs), Int(x)) if x == ::std::isize::MAX as i64 => Maximum, + (&ty::TyInt(TyI8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum, + (&ty::TyInt(TyI16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum, + (&ty::TyInt(TyI32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum, + (&ty::TyInt(TyI64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum, + + (&ty::TyUint(TyUs), Uint(x)) if x == ::std::usize::MAX as u64 => Maximum, + (&ty::TyUint(TyU8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum, + (&ty::TyUint(TyU16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum, + (&ty::TyUint(TyU32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum, + (&ty::TyUint(TyU64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum, + + _ => return None, + }; + Some(ExtremeExpr { which: which, expr: expr }) +} + +impl LateLintPass for AbsurdExtremeComparisons { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + use types::ExtremeType::*; + use types::AbsurdComparisonResult::*; + + if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { if !in_macro(cx, expr.span) { - let msg = "testing whether an unsigned integer is non-positive"; - let help = format!("consider using {} == 0 instead", - snippet(cx, comparee.span, "x")); - span_help_and_lint(cx, ABSURD_UNSIGNED_COMPARISONS, expr.span, msg, &help); + let msg = "this comparison involving the minimum or maximum element for this \ + type contains a case that is always true or always false"; + + let conclusion = match result { + AlwaysFalse => "this comparison is always false".to_owned(), + AlwaysTrue => "this comparison is always true".to_owned(), + InequalityImpossible => + format!("the case where the two sides are not equal never occurs, \ + consider using {} == {} instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs")), + }; + + let help = format!("because {} is the {} value for this type, {}", + snippet(cx, culprit.expr.span, "x"), + match culprit.which { Minimum => "minimum", Maximum => "maximum" }, + conclusion); + + span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help); } } } diff --git a/tests/compile-fail/absurd-extreme-comparisons.rs b/tests/compile-fail/absurd-extreme-comparisons.rs new file mode 100644 index 00000000000..fea5f24b63f --- /dev/null +++ b/tests/compile-fail/absurd-extreme-comparisons.rs @@ -0,0 +1,44 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(absurd_extreme_comparisons)] +#![allow(unused)] +fn main() { + const Z: u32 = 0; + + let u: u32 = 42; + + u <= 0; //~ERROR this comparison involving the minimum or maximum element for this type contains a case that is always true or always false + u <= Z; //~ERROR this comparison involving + u < Z; //~ERROR this comparison involving + Z >= u; //~ERROR this comparison involving + Z > u; //~ERROR this comparison involving + u > std::u32::MAX; //~ERROR this comparison involving + u >= std::u32::MAX; //~ERROR this comparison involving + std::u32::MAX < u; //~ERROR this comparison involving + std::u32::MAX <= u; //~ERROR this comparison involving + + 1-1 > u; + //~^ ERROR this comparison involving + //~| HELP because 1-1 is the minimum value for this type, this comparison is always false + u >= !0; + //~^ ERROR this comparison involving + //~| HELP because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead + u <= 12 - 2*6; + //~^ ERROR this comparison involving + //~| HELP because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead + + let i: i8 = 0; + i < -127 - 1; //~ERROR this comparison involving + std::i8::MAX >= i; //~ERROR this comparison involving + 3-7 < std::i32::MIN; //~ERROR this comparison involving + + let b = false; + b >= true; //~ERROR this comparison involving + false > b; //~ERROR this comparison involving + + u > 0; // ok + + // this is handled by unit_cmp + () < {}; //~WARNING <-comparison of unit values detected. +} diff --git a/tests/compile-fail/absurd_unsigned_comparisons.rs b/tests/compile-fail/absurd_unsigned_comparisons.rs deleted file mode 100644 index d7817daf204..00000000000 --- a/tests/compile-fail/absurd_unsigned_comparisons.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#![allow(unused)] - -#[deny(absurd_unsigned_comparisons)] -fn main() { - 1u32 <= 0; //~ERROR testing whether an unsigned integer is non-positive - 1u8 <= 0; //~ERROR testing whether an unsigned integer is non-positive - 1i32 <= 0; - 0 >= 1u32; //~ERROR testing whether an unsigned integer is non-positive - 0 >= 1; - 1u32 > 0; -} -- cgit 1.4.1-3-g733a5 From fab10c07e8012b1190550615173ba6e5bca45c5e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 3 Feb 2016 13:42:46 +0100 Subject: Fix confusing message for STRING_TO_STRING --- README.md | 2 +- src/methods.rs | 7 ++++--- tests/compile-fail/methods.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 006ddcd7a7f..3f99b73c4cb 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ name [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String.to_string()` which is a no-op +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions diff --git a/src/methods.rs b/src/methods.rs index 0584d39330d..0a06351afac 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -56,13 +56,14 @@ declare_lint!(pub STR_TO_STRING, Warn, /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default. /// -/// **Why is this bad?** As our string is already owned, this whole operation is basically a no-op, but still creates a clone of the string (which, if really wanted, should be done with `.clone()`). +/// **Why is this bad?** This is an non-efficient way to clone a `String`, `.clone()` should be used +/// instead. `String` implements `ToString` mostly for generics. /// /// **Known problems:** None /// /// **Example:** `s.to_string()` where `s: String` declare_lint!(pub STRING_TO_STRING, Warn, - "calling `String.to_string()` which is a no-op"); + "calling `String::to_string` which is inefficient"); /// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default. /// @@ -560,7 +561,7 @@ fn lint_to_string(cx: &LateContext, expr: &Expr, to_string_args: &MethodArgs) { span_lint(cx, STRING_TO_STRING, expr.span, - "`String.to_string()` is a no-op; use `clone()` to make a copy"); + "`String::to_string` is an inefficient way to clone a `String`; use `clone()` instead"); } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index f998a83e831..464a7c26e44 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -267,7 +267,7 @@ fn main() { let v = &"str"; let string = v.to_string(); //~ERROR `(*v).to_owned()` is faster - let _again = string.to_string(); //~ERROR `String.to_string()` is a no-op + let _again = string.to_string(); //~ERROR `String::to_string` is an inefficient way to clone a `String`; use `clone()` instead res.ok().expect("disaster!"); //~ERROR called `ok().expect()` // the following should not warn, since `expect` isn't implemented unless -- cgit 1.4.1-3-g733a5 From 3b8375d90b0e7d04c992b368bb7632ddab6841ff Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 3 Feb 2016 15:38:23 +0100 Subject: warn on `use`ing all variants of an enum --- README.md | 3 +- src/enum_glob_use.rs | 61 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ tests/compile-fail/enum_glob_use.rs | 20 ++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/enum_glob_use.rs create mode 100644 tests/compile-fail/enum_glob_use.rs diff --git a/README.md b/README.md index 006ddcd7a7f..424c89b28b8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 109 lints included in this crate: +There are 110 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -33,6 +33,7 @@ name [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[enum_glob_use](https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use) | allow | finds use items that import all variants of an enum [enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) [expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs new file mode 100644 index 00000000000..d6df307fec2 --- /dev/null +++ b/src/enum_glob_use.rs @@ -0,0 +1,61 @@ +//! lint on `use`ing all variants of an enum + +use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; +use rustc_front::hir::*; +use rustc::front::map::Node::NodeItem; +use rustc::front::map::PathElem::PathName; +use rustc::middle::ty::TyEnum; +use utils::span_lint; +use syntax::codemap::Span; +use syntax::ast::NodeId; + +/// **What it does:** Warns when `use`ing all variants of an enum +/// +/// **Why is this bad?** It is usually better style to use the prefixed name of an enum variant, rather than importing variants +/// +/// **Known problems:** Old-style enums that prefix the variants are still around +/// +/// **Example:** `use std::cmp::Ordering::*;` +declare_lint! { pub ENUM_GLOB_USE, Allow, + "finds use items that import all variants of an enum" } + +pub struct EnumGlobUse; + +impl LintPass for EnumGlobUse { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_GLOB_USE) + } +} + +impl LateLintPass for EnumGlobUse { + fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) { + // only check top level `use` statements + for item in &m.item_ids { + self.lint_item(cx, cx.krate.item(item.id)); + } + } +} + +impl EnumGlobUse { + fn lint_item(&self, cx: &LateContext, item: &Item) { + if item.vis == Visibility::Public { + return; // re-exports are fine + } + if let ItemUse(ref item_use) = item.node { + if let ViewPath_::ViewPathGlob(_) = item_use.node { + let def = cx.tcx.def_map.borrow()[&item.id]; + if let Some(NodeItem(it)) = cx.tcx.map.get_if_local(def.def_id()) { + if let ItemEnum(..) = it.node { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } + } else { + if let Some(&PathName(_)) = cx.sess().cstore.item_path(def.def_id()).last() { + if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } + } + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 44dd9fa8c86..4f3de70db4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ pub mod utils; pub mod consts; pub mod types; pub mod misc; +pub mod enum_glob_use; pub mod eq_op; pub mod bit_mask; pub mod ptr_arg; @@ -95,6 +96,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); reg.register_early_lint_pass(box enum_variants::EnumVariantNames); + reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); @@ -153,6 +155,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy_pedantic", vec![ + enum_glob_use::ENUM_GLOB_USE, matches::SINGLE_MATCH_ELSE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, diff --git a/tests/compile-fail/enum_glob_use.rs b/tests/compile-fail/enum_glob_use.rs new file mode 100644 index 00000000000..fc5f531ba90 --- /dev/null +++ b/tests/compile-fail/enum_glob_use.rs @@ -0,0 +1,20 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy, clippy_pedantic)] +#![allow(unused_imports, dead_code)] + +use std::cmp::Ordering::*; //~ ERROR: don't use glob imports for enum variants + +enum Enum {} + +use self::Enum::*; //~ ERROR: don't use glob imports for enum variants + +fn blarg() { + use self::Enum::*; // ok, just for a function +} + +mod blurg { + pub use std::cmp::Ordering::*; // ok, re-export +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From af07ccc16cbf9a736a5aba2759f296242636fecc Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 3 Feb 2016 15:39:22 +0100 Subject: fallout --- src/approx_const.rs | 10 ++--- src/bit_mask.rs | 4 +- src/consts.rs | 110 ++++++++++++++++++++------------------------------- src/len_zero.rs | 5 +-- src/minmax.rs | 5 +-- src/needless_bool.rs | 4 +- src/types.rs | 10 ++--- src/unicode.rs | 4 +- src/utils.rs | 22 +++++------ 9 files changed, 71 insertions(+), 103 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 2c8779ae737..f42c723e27a 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -2,9 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use std::f64::consts as f64; use utils::span_lint; -use syntax::ast::Lit_::*; -use syntax::ast::Lit; -use syntax::ast::FloatTy::*; +use syntax::ast::{Lit, Lit_, FloatTy}; /// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. This lint is `Warn` by default. /// @@ -57,9 +55,9 @@ impl LateLintPass for ApproxConstant { fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { - LitFloat(ref s, TyF32) => check_known_consts(cx, e, s, "f32"), - LitFloat(ref s, TyF64) => check_known_consts(cx, e, s, "f64"), - LitFloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), + Lit_::LitFloat(ref s, FloatTy::TyF32) => check_known_consts(cx, e, s, "f32"), + Lit_::LitFloat(ref s, FloatTy::TyF64) => check_known_consts(cx, e, s, "f64"), + Lit_::LitFloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), _ => (), } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 0fce772010a..5a8b00f8b1a 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -4,7 +4,7 @@ use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; use syntax::codemap::Span; -use syntax::ast::Lit_::*; +use syntax::ast::Lit_; use utils::span_lint; @@ -256,7 +256,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { - if let LitInt(value, _) = lit_ptr.node { + if let Lit_::LitInt(value, _) = lit_ptr.node { Some(value) //TODO: Handle sign } else { None diff --git a/src/consts.rs b/src/consts.rs index f590095d9f2..5f40aff92cc 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -12,14 +12,10 @@ use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; use std::fmt; -use self::FloatWidth::*; -use syntax::ast::Lit_::*; use syntax::ast::Lit_; -use syntax::ast::LitIntType::*; use syntax::ast::LitIntType; use syntax::ast::{UintTy, FloatTy, StrStyle}; -use syntax::ast::FloatTy::*; use syntax::ast::Sign::{self, Plus, Minus}; @@ -33,8 +29,8 @@ pub enum FloatWidth { impl From<FloatTy> for FloatWidth { fn from(ty: FloatTy) -> FloatWidth { match ty { - TyF32 => Fw32, - TyF64 => Fw64, + FloatTy::TyF32 => FloatWidth::Fw32, + FloatTy::TyF64 => FloatWidth::Fw64, } } } @@ -107,6 +103,7 @@ impl PartialEq for Constant { lv == rv && (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)) } (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { + use self::FloatWidth::*; if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -149,6 +146,7 @@ impl PartialOrd for Constant { }) } (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { + use self::FloatWidth::*; if match (lw, rw) { (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, _ => false, @@ -261,76 +259,51 @@ impl fmt::Display for Constant { fn lit_to_constant(lit: &Lit_) -> Constant { match *lit { - LitStr(ref is, style) => Constant::Str(is.to_string(), style), - LitByte(b) => Constant::Byte(b), - LitByteStr(ref s) => Constant::Binary(s.clone()), - LitChar(c) => Constant::Char(c), - LitInt(value, ty) => Constant::Int(value, ty), - LitFloat(ref is, ty) => Constant::Float(is.to_string(), ty.into()), - LitFloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FwAny), - LitBool(b) => Constant::Bool(b), + Lit_::LitStr(ref is, style) => Constant::Str(is.to_string(), style), + Lit_::LitByte(b) => Constant::Byte(b), + Lit_::LitByteStr(ref s) => Constant::Binary(s.clone()), + Lit_::LitChar(c) => Constant::Char(c), + Lit_::LitInt(value, ty) => Constant::Int(value, ty), + Lit_::LitFloat(ref is, ty) => Constant::Float(is.to_string(), ty.into()), + Lit_::LitFloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::FwAny), + Lit_::LitBool(b) => Constant::Bool(b), } } fn constant_not(o: Constant) -> Option<Constant> { - Some(match o { - Constant::Bool(b) => Constant::Bool(!b), - Constant::Int(value, ty) => { - let (nvalue, nty) = match ty { - SignedIntLit(ity, Plus) => { - if value == ::std::u64::MAX { - return None; - } - (value + 1, SignedIntLit(ity, Minus)) - } - SignedIntLit(ity, Minus) => { - if value == 0 { - (1, SignedIntLit(ity, Minus)) - } else { - (value - 1, SignedIntLit(ity, Plus)) - } - } - UnsignedIntLit(ity) => { - let mask = match ity { - UintTy::TyU8 => ::std::u8::MAX as u64, - UintTy::TyU16 => ::std::u16::MAX as u64, - UintTy::TyU32 => ::std::u32::MAX as u64, - UintTy::TyU64 => ::std::u64::MAX, - UintTy::TyUs => { - return None; - } // refuse to guess - }; - (!value & mask, UnsignedIntLit(ity)) - } - UnsuffixedIntLit(_) => { + use syntax::ast::LitIntType::*; + use self::Constant::*; + match o { + Bool(b) => Some(Bool(!b)), + Int(::std::u64::MAX, SignedIntLit(_, Plus)) => None, + Int(value, SignedIntLit(ity, Plus)) => Some(Int(value + 1, SignedIntLit(ity, Minus))), + Int(0, SignedIntLit(ity, Minus)) => Some(Int(1, SignedIntLit(ity, Minus))), + Int(value, SignedIntLit(ity, Minus)) => Some(Int(value - 1, SignedIntLit(ity, Plus))), + Int(value, UnsignedIntLit(ity)) => { + let mask = match ity { + UintTy::TyU8 => ::std::u8::MAX as u64, + UintTy::TyU16 => ::std::u16::MAX as u64, + UintTy::TyU32 => ::std::u32::MAX as u64, + UintTy::TyU64 => ::std::u64::MAX, + UintTy::TyUs => { return None; } // refuse to guess }; - Constant::Int(nvalue, nty) - } - _ => { - return None; - } - }) + Some(Int(!value & mask, UnsignedIntLit(ity))) + }, + _ => None, + } } fn constant_negate(o: Constant) -> Option<Constant> { - Some(match o { - Constant::Int(value, ty) => { - Constant::Int(value, - match ty { - SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)), - UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)), - _ => { - return None; - } - }) - } - Constant::Float(is, ty) => Constant::Float(neg_float_str(is), ty), - _ => { - return None; - } - }) + use syntax::ast::LitIntType::*; + use self::Constant::*; + match o { + Int(value, SignedIntLit(ity, sign)) => Some(Int(value, SignedIntLit(ity, neg_sign(sign)))), + Int(value, UnsuffixedIntLit(sign)) => Some(Int(value, UnsuffixedIntLit(neg_sign(sign)))), + Float(is, ty) => Some(Float(neg_float_str(is), ty)), + _ => None, + } } fn neg_sign(s: Sign) -> Sign { @@ -357,12 +330,13 @@ fn neg_float_str(s: String) -> String { /// ``` pub fn is_negative(ty: LitIntType) -> bool { match ty { - SignedIntLit(_, sign) | UnsuffixedIntLit(sign) => sign == Minus, - UnsignedIntLit(_) => false, + LitIntType::SignedIntLit(_, sign) | LitIntType::UnsuffixedIntLit(sign) => sign == Minus, + LitIntType::UnsignedIntLit(_) => false, } } fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { + use syntax::ast::LitIntType::*; match (l, r) { (SignedIntLit(lty, _), SignedIntLit(rty, _)) => { if lty == rty { diff --git a/src/len_zero.rs b/src/len_zero.rs index 6bc5bc4bf01..a79c488b778 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -6,8 +6,7 @@ use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use syntax::ast::Lit_::*; -use syntax::ast::Lit; +use syntax::ast::{Lit, Lit_}; use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; @@ -148,7 +147,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { - if let Spanned{node: LitInt(0, _), ..} = *lit { + if let Spanned{node: Lit_::LitInt(0, _), ..} = *lit { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, diff --git a/src/minmax.rs b/src/minmax.rs index e72f2392054..3a74105d0df 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -1,8 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ptr::P; -use std::cmp::PartialOrd; -use std::cmp::Ordering::*; +use std::cmp::{PartialOrd, Ordering}; use consts::{Constant, constant_simple}; use utils::{match_def_path, span_lint}; @@ -36,7 +35,7 @@ impl LateLintPass for MinMaxPass { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), + (_, None) | (Max, Some(Ordering::Less)) | (Min, Some(Ordering::Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 22edbc272bd..34fd2204dc0 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::ast::Lit_::*; +use syntax::ast::Lit_; use utils::{span_lint, snippet}; @@ -90,7 +90,7 @@ fn fetch_bool_expr(expr: &Expr) -> Option<bool> { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), ExprLit(ref lit_ptr) => { - if let LitBool(value) = lit_ptr.node { + if let Lit_::LitBool(value) = lit_ptr.node { Some(value) } else { None diff --git a/src/types.rs b/src/types.rs index 0ab373bfa35..329813fdc4e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,9 +5,7 @@ use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::Span; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; -use syntax::ast::IntTy::*; -use syntax::ast::UintTy::*; -use syntax::ast::FloatTy::*; +use syntax::ast::{IntTy, UintTy, FloatTy}; use utils::*; @@ -217,7 +215,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { fn is_isize_or_usize(typ: &ty::TyS) -> bool { match typ.sty { - ty::TyInt(TyIs) | ty::TyUint(TyUs) => true, + ty::TyInt(IntTy::TyIs) | ty::TyUint(UintTy::TyUs) => true, _ => false, } } @@ -342,7 +340,7 @@ impl LateLintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = if let ty::TyFloat(TyF32) = cast_to.sty { + let to_nbits = if let ty::TyFloat(FloatTy::TyF32) = cast_to.sty { 32 } else { 64 @@ -373,7 +371,7 @@ impl LateLintPass for CastPass { check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { - if let (&ty::TyFloat(TyF64), &ty::TyFloat(TyF32)) = (&cast_from.sty, &cast_to.sty) { + if let (&ty::TyFloat(FloatTy::TyF64), &ty::TyFloat(FloatTy::TyF32)) = (&cast_from.sty, &cast_to.sty) { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, diff --git a/src/unicode.rs b/src/unicode.rs index d5ea7199e10..1e4ebda5821 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use syntax::ast::Lit_::*; +use syntax::ast::Lit_; use unicode_normalization::UnicodeNormalization; @@ -51,7 +51,7 @@ impl LintPass for Unicode { impl LateLintPass for Unicode { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprLit(ref lit) = expr.node { - if let LitStr(_, _) = lit.node { + if let Lit_::LitStr(_, _) = lit.node { check_str(cx, lit.span) } } diff --git a/src/utils.rs b/src/utils.rs index 78fb45cd6cf..156d18cbe4c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use consts::constant; use reexport::*; -use rustc::front::map::Node::*; -use rustc::lint::*; +use rustc::front::map::Node; +use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::middle::def_id::DefId; use rustc::middle::{cstore, def, infer, ty, traits}; use rustc::session::Session; @@ -10,7 +10,7 @@ use std::borrow::Cow; use std::mem; use std::ops::{Deref, DerefMut}; use std::str::FromStr; -use syntax::ast::Lit_::*; +use syntax::ast::Lit_; use syntax::ast; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; @@ -295,9 +295,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { - Some(NodeItem(&Item{ ref name, .. })) | - Some(NodeTraitItem(&TraitItem{ ref name, .. })) | - Some(NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), + Some(Node::NodeItem(&Item{ ref name, .. })) | + Some(Node::NodeTraitItem(&TraitItem{ ref name, .. })) | + Some(Node::NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), _ => None, } } @@ -407,7 +407,7 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { return None; } map.find(parent_id).and_then(|node| { - if let NodeExpr(parent) = node { + if let Node::NodeExpr(parent) = node { Some(parent) } else { None @@ -421,8 +421,8 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c .and_then(|enclosing_id| map.find(enclosing_id)); if let Some(node) = enclosing_node { match node { - NodeBlock(ref block) => Some(block), - NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), + Node::NodeBlock(ref block) => Some(block), + Node::NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), _ => None, } } else { @@ -528,7 +528,7 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { // FIXME: use constant folding if let ExprLit(ref spanned) = expr.node { - if let LitInt(v, _) = spanned.node { + if let Lit_::LitInt(v, _) = spanned.node { return v == value; } } @@ -574,7 +574,7 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } if let ast::MetaNameValue(ref key, ref value) = attr.value.node { if *key == name { - if let LitStr(ref s, _) = value.node { + if let Lit_::LitStr(ref s, _) = value.node { if let Ok(value) = FromStr::from_str(s) { f(value) } else { -- cgit 1.4.1-3-g733a5 From 3d85cc24e7c9a62359ca837570d5e08105d22036 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 5 Feb 2016 00:36:06 +0100 Subject: new regex syntax lint, fixes #597 --- Cargo.toml | 1 + README.md | 4 +++- src/lib.rs | 8 +++++-- src/regex.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 1 + tests/compile-fail/regex.rs | 16 ++++++++++++++ tests/compile-test.rs | 2 +- 7 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 src/regex.rs create mode 100644 tests/compile-fail/regex.rs diff --git a/Cargo.toml b/Cargo.toml index b74db8f95ac..c0d600e418c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ plugin = true [dependencies] unicode-normalization = "0.1" semver = "0.2.1" +regex-syntax = "0.2.2" [dev-dependencies] compiletest_rs = "0.0.11" diff --git a/README.md b/README.md index 3f99b73c4cb..05cc5031fce 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 109 lints included in this crate: +There are 111 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -46,6 +46,7 @@ name [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` @@ -85,6 +86,7 @@ name [range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | allow | finds use of `regex!(_)`, suggests `Regex::new(_)` instead [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` [search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` diff --git a/src/lib.rs b/src/lib.rs index 44dd9fa8c86..87d23c96d36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,9 @@ extern crate unicode_normalization; // for semver check in attrs.rs extern crate semver; +// for regex checking +extern crate regex_syntax; + extern crate rustc_plugin; use rustc_plugin::Registry; @@ -82,6 +85,7 @@ pub mod derive; pub mod print; pub mod vec; pub mod drop_ref; +pub mod regex; mod reexport { pub use syntax::ast::{Name, NodeId}; @@ -150,7 +154,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box vec::UselessVec); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdUnsignedComparisons); - + reg.register_late_lint_pass(box regex::RegexPass); reg.register_lint_group("clippy_pedantic", vec![ matches::SINGLE_MATCH_ELSE, @@ -163,7 +167,6 @@ pub fn plugin_registrar(reg: &mut Registry) { shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, - strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, @@ -250,6 +253,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ptr_arg::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, ranges::RANGE_ZIP_WITH_LEN, + regex::INVALID_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, diff --git a/src/regex.rs b/src/regex.rs new file mode 100644 index 00000000000..e3363ad1df0 --- /dev/null +++ b/src/regex.rs @@ -0,0 +1,53 @@ +use regex_syntax; +use std::error::Error; +use syntax::codemap::{Span, BytePos, Pos}; +use rustc_front::hir::*; +use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::lint::*; + +use utils::{match_path, REGEX_NEW_PATH, span_lint}; + +/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. It is `deny` by default. +/// +/// **Why is this bad?** This will lead to a runtime panic. +/// +/// **Known problems:** None. +/// +/// **Example:** `Regex::new("|")` +declare_lint! { + pub INVALID_REGEX, + Deny, + "finds invalid regular expressions in `Regex::new(_)` invocations" +} + +#[derive(Copy,Clone)] +pub struct RegexPass; + +impl LintPass for RegexPass { + fn get_lints(&self) -> LintArray { + lint_array!(INVALID_REGEX) + } +} + +impl LateLintPass for RegexPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain!{[ + let ExprCall(ref fun, ref args) = expr.node, + let ExprPath(_, ref path) = fun.node, + match_path(path, ®EX_NEW_PATH) && args.len() == 1, + let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, + &*args[0], + ExprTypeChecked, + None), + let Err(e) = regex_syntax::Expr::parse(&r) + ], { + let lo = args[0].span.lo + BytePos::from_usize(e.position()); + let span = Span{ lo: lo, hi: lo, expn_id: args[0].span.expn_id }; + span_lint(cx, + INVALID_REGEX, + span, + &format!("Regex syntax error: {}", e.description())); + }} + } +} diff --git a/src/utils.rs b/src/utils.rs index 78fb45cd6cf..8f542431d64 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,6 +36,7 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedLis pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs new file mode 100644 index 00000000000..e2be26a999e --- /dev/null +++ b/tests/compile-fail/regex.rs @@ -0,0 +1,16 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused)] +#![deny(invalid_regex)] + +extern crate regex; + +use regex::Regex; + +fn main() { + let pipe_in_wrong_position = Regex::new("|"); + //~^ERROR: Regex syntax error: empty alternate + let wrong_char_range = Regex::new("[z-a]"); + //~^ERROR: Regex syntax error: invalid character class range +} diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 602937a40af..92d2671eaa7 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -7,7 +7,7 @@ fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); let cfg_mode = mode.parse().ok().expect("Invalid mode"); - config.target_rustcflags = Some("-L target/debug/".to_owned()); + config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps".to_owned()); if let Ok(name) = var::<&str>("TESTNAME") { let s : String = name.to_owned(); config.filter = Some(s) -- cgit 1.4.1-3-g733a5 From 4eb9a921d4a3658bb38f6831281a594ad6e3359f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 5 Feb 2016 16:04:15 +0530 Subject: Lint on cloning double pointer fixes #620 --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 146 ++++++++++++++++++++++++++++++++------------------------- 3 files changed, 84 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 3f99b73c4cb..d6daa49c521 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 109 lints included in this crate: +There are 110 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -23,6 +23,7 @@ name [cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` [char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8 [chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char +[clone_double_ref](https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` [clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` diff --git a/src/lib.rs b/src/lib.rs index 44dd9fa8c86..482472b6651 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,6 +215,7 @@ pub fn plugin_registrar(reg: &mut Registry) { matches::MATCH_REF_PATS, matches::SINGLE_MATCH, methods::CHARS_NEXT_CMP, + methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, methods::EXTEND_FROM_SLICE, methods::FILTER_NEXT, diff --git a/src/methods.rs b/src/methods.rs index 0a06351afac..61a910a65ab 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -7,15 +7,11 @@ use std::borrow::Cow; use syntax::ptr::P; use syntax::codemap::Span; -use utils::{ - get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, - match_trait_method, match_type, method_chain_args, snippet, span_lint, span_lint_and_then, - span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, -}; -use utils::{ - BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, - STRING_PATH, VEC_PATH, -}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, + match_type, method_chain_args, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, + walk_ptrs_ty, walk_ptrs_ty_depth}; +use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, + VEC_PATH,}; use utils::MethodArgs; use rustc::middle::cstore::CrateStore; @@ -231,6 +227,26 @@ declare_lint!(pub EXTEND_FROM_SLICE, Warn, declare_lint!(pub CLONE_ON_COPY, Warn, "using `clone` on a `Copy` type"); +/// **What it does:** This lint warns on using `.clone()` on an `&&T` +/// +/// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of cloning the underlying +/// `T` +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn main() { +/// let x = vec![1]; +/// let y = &&x; +/// let z = y.clone(); +/// println!("{:p} {:p}",*y, z); // prints out the same pointer +/// } +/// ``` +/// +declare_lint!(pub CLONE_DOUBLE_REF, Warn, + "using `clone` on `&&T`"); + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -246,7 +262,8 @@ impl LintPass for MethodsPass { OPTION_MAP_UNWRAP_OR_ELSE, OR_FUN_CALL, CHARS_NEXT_CMP, - CLONE_ON_COPY) + CLONE_ON_COPY, + CLONE_DOUBLE_REF) } } @@ -280,9 +297,11 @@ impl LateLintPass for MethodsPass { } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { lint_extend(cx, expr, arglists[0]); } - lint_or_fun_call(cx, expr, &name.node.as_str(), &args); - lint_clone_on_copy(cx, expr, &name.node.as_str(), &args); + if args.len() == 1 && name.node.as_str() == "clone" { + lint_clone_on_copy(cx, expr); + lint_clone_double_ref(cx, expr, &args[0]); + } } ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { if !lint_chars_next(cx, expr, lhs, rhs, op.node == BiEq) { @@ -348,15 +367,9 @@ impl LateLintPass for MethodsPass { /// Checks for the `OR_FUN_CALL` lint. fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. - fn check_unwrap_or_default( - cx: &LateContext, - name: &str, - fun: &Expr, - self_expr: &Expr, - arg: &Expr, - or_has_args: bool, - span: Span - ) -> bool { + fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, + or_has_args: bool, span: Span) + -> bool { if or_has_args { return false; } @@ -379,11 +392,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) }; if implements_trait(cx, arg_ty, default_trait_id, None) { - span_lint(cx, OR_FUN_CALL, span, + span_lint(cx, + OR_FUN_CALL, + span, &format!("use of `{}` followed by a call to `{}`", name, path)) - .span_suggestion(span, "try this", - format!("{}.unwrap_or_default()", - snippet(cx, self_expr.span, "_"))); + .span_suggestion(span, + "try this", + format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); return true; } } @@ -394,34 +409,25 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } /// Check for `*or(foo())`. - fn check_general_case( - cx: &LateContext, - name: &str, - fun: &Expr, - self_expr: &Expr, - arg: &Expr, - or_has_args: bool, - span: Span - ) { + fn check_general_case(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, or_has_args: bool, + span: Span) { // (path, fn_has_argument, methods) - let know_types : &[(&[_], _, &[_], _)] = &[ - (&BTREEMAP_ENTRY_PATH, false, &["or_insert"], "with"), - (&HASHMAP_ENTRY_PATH, false, &["or_insert"], "with"), - (&OPTION_PATH, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&RESULT_PATH, true, &["or", "unwrap_or"], "else"), - ]; + let know_types: &[(&[_], _, &[_], _)] = &[(&BTREEMAP_ENTRY_PATH, false, &["or_insert"], "with"), + (&HASHMAP_ENTRY_PATH, false, &["or_insert"], "with"), + (&OPTION_PATH, + false, + &["map_or", "ok_or", "or", "unwrap_or"], + "else"), + (&RESULT_PATH, true, &["or", "unwrap_or"], "else")]; let self_ty = cx.tcx.expr_ty(self_expr); - let (fn_has_arguments, poss, suffix) = - if let Some(&(_, fn_has_arguments, poss, suffix)) = know_types.iter().find(|&&i| { - match_type(cx, self_ty, i.0) - }) { - (fn_has_arguments, poss, suffix) - } - else { - return - }; + let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = + know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) { + (fn_has_arguments, poss, suffix) + } else { + return; + }; if !poss.contains(&name) { return; @@ -433,14 +439,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) (false, true) => format!("{}", snippet(cx, fun.span, "..")), }; - span_lint(cx, OR_FUN_CALL, span, - &format!("use of `{}` followed by a function call", name)) - .span_suggestion(span, "try this", - format!("{}.{}_{}({})", - snippet(cx, self_expr.span, "_"), - name, - suffix, - sugg)); + span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) + .span_suggestion(span, + "try this", + format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); } if args.len() == 2 { @@ -454,14 +456,28 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } /// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { - if args.len() == 1 && name == "clone" { - let ty = cx.tcx.expr_ty(expr); - let parent = cx.tcx.map.get_parent(expr.id); - let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); - - if !ty.moves_by_default(¶meter_environment, expr.span) { - span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); +fn lint_clone_on_copy(cx: &LateContext, expr: &Expr) { + let ty = cx.tcx.expr_ty(expr); + let parent = cx.tcx.map.get_parent(expr.id); + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); + + if !ty.moves_by_default(¶meter_environment, expr.span) { + span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); + } +} + +/// Checks for the `CLONE_DOUBLE_REF` lint. +fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr) { + let ty = cx.tcx.expr_ty(arg); + if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { + if let ty::TyRef(..) = inner.sty { + let mut db = span_lint(cx, CLONE_DOUBLE_REF, expr.span, + "using `clone` on a double-reference; \ + this will copy the reference instead of cloning \ + the inner type"); + if let Some(snip) = snippet_opt(cx, arg.span) { + db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); + } } } } -- cgit 1.4.1-3-g733a5 From 8f7b8524d3a0491f668cbe92e19e101fef6bd2d0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 5 Feb 2016 16:04:59 +0530 Subject: Test for double-ref lint --- tests/compile-fail/methods.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 464a7c26e44..4e515c2aa12 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -1,8 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused)] #![deny(clippy, clippy_pedantic)] +#![allow(unused, print_stdout)] use std::collections::BTreeMap; use std::collections::HashMap; @@ -334,3 +334,13 @@ fn clone_on_copy_generic<T: Copy>(t: T) { t.clone(); //~ERROR using `clone` on a `Copy` type Some(t).clone(); //~ERROR using `clone` on a `Copy` type } + +fn clone_on_double_ref() { + let x = vec![1]; + let y = &&x; + let z: &Vec<_> = y.clone(); //~ERROR using `clone` on a double + //~| HELP try dereferencing it + //~| SUGGESTION let z: &Vec<_> = (*y).clone(); + //~^^^ERROR using `clone` on a `Copy` type + println!("{:p} {:p}",*y, z); +} -- cgit 1.4.1-3-g733a5 From a14514f7c8a9a93ed09f6c1ee3e3a21560ab66b8 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 5 Feb 2016 16:48:35 +0100 Subject: fixed span position and README --- README.md | 3 +-- src/lib.rs | 1 + src/regex.rs | 56 ++++++++++++++++++++++++++++++++++----------- tests/compile-fail/regex.rs | 10 +++++++- 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 05cc5031fce..eb843daab20 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 111 lints included in this crate: +There are 110 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -86,7 +86,6 @@ name [range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | allow | finds use of `regex!(_)`, suggests `Regex::new(_)` instead [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` [search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` diff --git a/src/lib.rs b/src/lib.rs index 87d23c96d36..a77f6829b90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,6 +167,7 @@ pub fn plugin_registrar(reg: &mut Registry) { shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, + strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, diff --git a/src/regex.rs b/src/regex.rs index e3363ad1df0..259bbb1b64b 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,6 +1,8 @@ use regex_syntax; use std::error::Error; -use syntax::codemap::{Span, BytePos, Pos}; +use syntax::ast::Lit_::LitStr; +use syntax::codemap::{Span, BytePos}; +use syntax::parse::token::InternedString; use rustc_front::hir::*; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; @@ -35,19 +37,47 @@ impl LateLintPass for RegexPass { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, let ExprPath(_, ref path) = fun.node, - match_path(path, ®EX_NEW_PATH) && args.len() == 1, - let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, - &*args[0], - ExprTypeChecked, - None), - let Err(e) = regex_syntax::Expr::parse(&r) + match_path(path, ®EX_NEW_PATH) && args.len() == 1 ], { - let lo = args[0].span.lo + BytePos::from_usize(e.position()); - let span = Span{ lo: lo, hi: lo, expn_id: args[0].span.expn_id }; - span_lint(cx, - INVALID_REGEX, - span, - &format!("Regex syntax error: {}", e.description())); + if let ExprLit(ref lit) = args[0].node { + if let LitStr(ref r, _) = lit.node { + if let Err(e) = regex_syntax::Expr::parse(r) { + span_lint(cx, + INVALID_REGEX, + str_span(args[0].span, &r, e.position()), + &format!("Regex syntax error: {}", + e.description())); + } + } + } else { + if_let_chain!{[ + let Some(r) = const_str(cx, &*args[0]), + let Err(e) = regex_syntax::Expr::parse(&r) + ], { + span_lint(cx, + INVALID_REGEX, + args[0].span, + &format!("Regex syntax error on position {}: {}", + e.position(), + e.description())); + }} + } }} } } + +#[allow(cast_possible_truncation)] +fn str_span(base: Span, s: &str, c: usize) -> Span { + let lo = match s.char_indices().nth(c) { + Some((b, _)) => base.lo + BytePos(b as u32), + _ => base.hi + }; + Span{ lo: lo, hi: lo, ..base } +} + +fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { + match eval_const_expr_partial(cx.tcx, e, ExprTypeChecked, None) { + Ok(ConstVal::Str(r)) => Some(r), + _ => None + } +} diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index e2be26a999e..34dfc1ef25b 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -8,9 +8,17 @@ extern crate regex; use regex::Regex; +const OPENING_PAREN : &'static str = "("; + fn main() { let pipe_in_wrong_position = Regex::new("|"); //~^ERROR: Regex syntax error: empty alternate - let wrong_char_range = Regex::new("[z-a]"); + let wrong_char_ranice = Regex::new("[z-a]"); //~^ERROR: Regex syntax error: invalid character class range + + let some_regex = Regex::new(OPENING_PAREN); + //~^ERROR: Regex syntax error on position 0: unclosed + + let closing_paren = ")"; + let not_linted = Regex::new(closing_paren); } -- cgit 1.4.1-3-g733a5 From 431c446746a7893ca6c78048adebc55f2f308979 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 19 Jan 2016 21:10:00 +0100 Subject: Lint looping on maps ignoring the keys or values --- README.md | 3 +- src/lib.rs | 1 + src/lifetimes.rs | 2 +- src/loops.rs | 82 ++++++++++++++++++++++++++++++++++++++---- tests/compile-fail/for_loop.rs | 16 +++++++++ 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f7908ffdcab..59a12e09b17 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 111 lints included in this crate: +There are 112 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -42,6 +42,7 @@ name [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` diff --git a/src/lib.rs b/src/lib.rs index 56a2a072421..3f18bcb17ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,6 +205,7 @@ pub fn plugin_registrar(reg: &mut Registry) { loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_ITER_LOOP, + loops::FOR_KV_MAP, loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, diff --git a/src/lifetimes.rs b/src/lifetimes.rs index b6f8ebe5fd8..3e9880d5932 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -352,7 +352,7 @@ fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics, } } - for (_, v) in checker.0 { + for &v in checker.0.values() { span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); } } diff --git a/src/loops.rs b/src/loops.rs index 49e073aacd0..830fac94e46 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -10,8 +10,8 @@ use std::borrow::Cow; use std::collections::{HashSet, HashMap}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, - span_help_and_lint, is_integer_literal, get_enclosing_block}; -use utils::{HASHMAP_PATH, VEC_PATH, LL_PATH, OPTION_PATH, RESULT_PATH}; + span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty}; +use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. /// @@ -141,6 +141,24 @@ declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } /// **Example:** `while let Some(val) = iter() { .. }` declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" } +/// **What it does:** This warns when you iterate on a map (`HashMap` or `BTreeMap`) and ignore +/// either the keys or values. +/// +/// **Why is this bad?** Readability. There are `keys` and `values` methods that can be used to +/// express that don't need the values or keys. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// for (k, _) in &map { .. } +/// ``` +/// could be replaced by +/// ```rust +/// for k in map.keys() { .. } +/// ``` +declare_lint!{ pub FOR_KV_MAP, Warn, "looping on a map using `iter` when `keys` or `values` would do" } + #[derive(Copy, Clone)] pub struct LoopsPass; @@ -154,7 +172,8 @@ impl LintPass for LoopsPass { REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, - WHILE_LET_ON_ITERATOR) + WHILE_LET_ON_ITERATOR, + FOR_KV_MAP) } } @@ -270,6 +289,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E check_for_loop_reverse_range(cx, arg, expr); check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); + check_for_loop_over_map_kv(cx, pat, arg, expr); } /// Check for looping over a range and then indexing a sequence with it. @@ -499,6 +519,53 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex } } +// Check for the FOR_KV_MAP lint. +fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { + if let PatTup(ref pat) = pat.node { + if pat.len() == 2 { + let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key) => (&pat[1].span, "values"), + (_, value) if pat_is_wild(value) => (&pat[0].span, "keys"), + _ => return + }; + + let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); + let arg_span = if let ExprAddrOf(_, ref expr) = arg.node { + expr.span + } + else { + arg.span + }; + + if match_type(cx, ty, &HASHMAP_PATH) || + match_type(cx, ty, &BTREEMAP_PATH) { + span_lint_and_then(cx, + FOR_KV_MAP, + expr.span, + &format!("you seem to want to iterate on a map's {}", kind), + |db| { + db.span_suggestion(expr.span, + "use the corresponding method", + format!("for {} in {}.{}()", + snippet(cx, *pat_span, ".."), + snippet(cx, arg_span, ".."), + kind)); + }); + } + } + } + +} + +// Return true if the pattern is a `PatWild` or an ident prefixed with '_'. +fn pat_is_wild(pat: &Pat_) -> bool { + match *pat { + PatWild => true, + PatIdent(_, ident, None) if ident.node.name.as_str().starts_with('_') => true, + _ => false, + } +} + /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { @@ -601,11 +668,14 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tcx.expr_ty(e); - is_iterable_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || - match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || + is_iterable_array(ty) || + match_type(cx, ty, &VEC_PATH) || + match_type(cx, ty, &LL_PATH) || + match_type(cx, ty, &HASHMAP_PATH) || + match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || - match_type(cx, ty, &["collections", "btree", "map", "BTreeMap"]) || + match_type(cx, ty, &BTREEMAP_PATH) || match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 1fcbbf54d1f..7049a21b15e 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -280,4 +280,20 @@ fn main() { println!("index: {}", index); for_loop_over_option_and_result(); + + let m : HashMap<u64, u64> = HashMap::new(); + for (_, v) in &m { + //~^ you seem to want to iterate on a map's values + //~| HELP use the corresponding method + //~| SUGGESTION for v in &m.values() + let _v = v; + } + + let rm = &m; + for (k, _values) in rm { + //~^ you seem to want to iterate on a map's keys + //~| HELP use the corresponding method + //~| SUGGESTION for k in rm.keys() + let _k = k; + } } -- cgit 1.4.1-3-g733a5 From 0f50b0981d33c2fcb591e2aab46bd8bd0497daff Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 5 Feb 2016 19:14:02 +0100 Subject: Check for pattern use in FOR_KV_MAP --- src/loops.rs | 38 ++++++++++++++++++++++++++++++++------ tests/compile-fail/for_loop.rs | 15 ++++++++++++++- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 830fac94e46..22dfef55ec1 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -289,7 +289,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E check_for_loop_reverse_range(cx, arg, expr); check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); - check_for_loop_over_map_kv(cx, pat, arg, expr); + check_for_loop_over_map_kv(cx, pat, arg, body, expr); } /// Check for looping over a range and then indexing a sequence with it. @@ -520,12 +520,13 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex } // Check for the FOR_KV_MAP lint. -fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { +fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let PatTup(ref pat) = pat.node { if pat.len() == 2 { + let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key) => (&pat[1].span, "values"), - (_, value) if pat_is_wild(value) => (&pat[0].span, "keys"), + (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), + (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), _ => return }; @@ -558,14 +559,39 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Ex } // Return true if the pattern is a `PatWild` or an ident prefixed with '_'. -fn pat_is_wild(pat: &Pat_) -> bool { +fn pat_is_wild(pat: &Pat_, body: &Expr) -> bool { match *pat { PatWild => true, - PatIdent(_, ident, None) if ident.node.name.as_str().starts_with('_') => true, + PatIdent(_, ident, None) if ident.node.name.as_str().starts_with('_') => { + let mut visitor = UsedVisitor { + var: ident.node, + used: false, + }; + walk_expr(&mut visitor, body); + !visitor.used + }, _ => false, } } +struct UsedVisitor { + var: Ident, // var to look for + used: bool, // has the var been used otherwise? +} + +impl<'a> Visitor<'a> for UsedVisitor { + fn visit_expr(&mut self, expr: &Expr) { + if let ExprPath(None, ref path) = expr.node { + if path.segments.len() == 1 && path.segments[0].identifier == self.var { + self.used = true; + return + } + } + + walk_expr(self, expr); + } +} + /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 7049a21b15e..e361ebe777f 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -290,10 +290,23 @@ fn main() { } let rm = &m; - for (k, _values) in rm { + for (k, _value) in rm { //~^ you seem to want to iterate on a map's keys //~| HELP use the corresponding method //~| SUGGESTION for k in rm.keys() let _k = k; } + + test_for_kv_map(); +} + +#[allow(used_underscore_binding)] +fn test_for_kv_map() { + let m : HashMap<u64, u64> = HashMap::new(); + + // No error, _value is actually used + for (k, _value) in &m { + let _ = _value; + let _k = k; + } } -- cgit 1.4.1-3-g733a5 From c0063e172de4854b6da3f097e5eb1da43dd3bd7a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 5 Feb 2016 19:46:11 +0100 Subject: Improve error message --- src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loops.rs b/src/loops.rs index 22dfef55ec1..3f430a1aaf0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -547,7 +547,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex |db| { db.span_suggestion(expr.span, "use the corresponding method", - format!("for {} in {}.{}()", + format!("for {} in {}.{}() {{...}}", snippet(cx, *pat_span, ".."), snippet(cx, arg_span, ".."), kind)); -- cgit 1.4.1-3-g733a5 From 70124cf5917e0b9d6597c3e3f855687182a9d071 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 5 Feb 2016 21:54:29 +0100 Subject: Fix case conventions --- src/cyclomatic_complexity.rs | 4 ++-- src/open_options.rs | 14 +++++++------- src/regex.rs | 4 ++-- tests/compile-fail/cyclomatic_complexity.rs | 26 +++++++++++++------------- tests/compile-fail/open_options.rs | 16 ++++++++-------- tests/compile-fail/regex.rs | 10 +++++----- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index d4375abcd05..84fb9b874ff 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -62,8 +62,8 @@ impl CyclomaticComplexity { span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, span, - &format!("The function has a cyclomatic complexity of {}", rust_cc), - "You could split it up into multiple smaller functions"); + &format!("the function has a cyclomatic complexity of {}", rust_cc), + "you could split it up into multiple smaller functions"); } } } diff --git a/src/open_options.rs b/src/open_options.rs index 541ed2444f4..e0b51cdfa2a 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -120,7 +120,7 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "The method \"create\" is called more than once"); + "the method \"create\" is called more than once"); } else { create = true } @@ -131,7 +131,7 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "The method \"append\" is called more than once"); + "the method \"append\" is called more than once"); } else { append = true } @@ -142,7 +142,7 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "The method \"truncate\" is called more than once"); + "the method \"truncate\" is called more than once"); } else { truncate = true } @@ -153,7 +153,7 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "The method \"read\" is called more than once"); + "the method \"read\" is called more than once"); } else { read = true } @@ -164,7 +164,7 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "The method \"write\" is called more than once"); + "the method \"write\" is called more than once"); } else { write = true } @@ -174,12 +174,12 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span } if read && truncate && read_arg && truncate_arg { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\""); + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\""); } if append && truncate && append_arg && truncate_arg { span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, - "File opened with \"append\" and \"truncate\""); + "file opened with \"append\" and \"truncate\""); } } diff --git a/src/regex.rs b/src/regex.rs index 259bbb1b64b..c24edc564ae 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -45,7 +45,7 @@ impl LateLintPass for RegexPass { span_lint(cx, INVALID_REGEX, str_span(args[0].span, &r, e.position()), - &format!("Regex syntax error: {}", + &format!("regex syntax error: {}", e.description())); } } @@ -57,7 +57,7 @@ impl LateLintPass for RegexPass { span_lint(cx, INVALID_REGEX, args[0].span, - &format!("Regex syntax error on position {}: {}", + &format!("regex syntax error on position {}: {}", e.position(), e.description())); }} diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index f79440af121..5bdca7f3629 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -5,7 +5,7 @@ #![allow(unused)] -fn main() { //~ERROR The function has a cyclomatic complexity of 28 +fn main() { //~ERROR the function has a cyclomatic complexity of 28 if true { println!("a"); } @@ -90,7 +90,7 @@ fn main() { //~ERROR The function has a cyclomatic complexity of 28 } #[cyclomatic_complexity = "0"] -fn kaboom() { //~ ERROR: The function has a cyclomatic complexity of 8 +fn kaboom() { //~ ERROR: the function has a cyclomatic complexity of 8 let n = 0; 'a: for i in 0..20 { 'b: for j in i..20 { @@ -136,7 +136,7 @@ fn bloo() { } #[cyclomatic_complexity = "0"] -fn baa() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn baa() { //~ ERROR: the function has a cyclomatic complexity of 2 let x = || match 99 { 0 => true, 1 => false, @@ -154,7 +154,7 @@ fn baa() { //~ ERROR: The function has a cyclomatic complexity of 2 } #[cyclomatic_complexity = "0"] -fn bar() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn bar() { //~ ERROR: the function has a cyclomatic complexity of 2 match 99 { 0 => println!("hi"), _ => println!("bye"), @@ -162,7 +162,7 @@ fn bar() { //~ ERROR: The function has a cyclomatic complexity of 2 } #[cyclomatic_complexity = "0"] -fn barr() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn barr() { //~ ERROR: the function has a cyclomatic complexity of 2 match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -172,7 +172,7 @@ fn barr() { //~ ERROR: The function has a cyclomatic complexity of 2 } #[cyclomatic_complexity = "0"] -fn barr2() { //~ ERROR: The function has a cyclomatic complexity of 3 +fn barr2() { //~ ERROR: the function has a cyclomatic complexity of 3 match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -188,7 +188,7 @@ fn barr2() { //~ ERROR: The function has a cyclomatic complexity of 3 } #[cyclomatic_complexity = "0"] -fn barrr() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn barrr() { //~ ERROR: the function has a cyclomatic complexity of 2 match 99 { 0 => println!("hi"), 1 => panic!("bla"), @@ -198,7 +198,7 @@ fn barrr() { //~ ERROR: The function has a cyclomatic complexity of 2 } #[cyclomatic_complexity = "0"] -fn barrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 +fn barrr2() { //~ ERROR: the function has a cyclomatic complexity of 3 match 99 { 0 => println!("hi"), 1 => panic!("bla"), @@ -214,7 +214,7 @@ fn barrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 } #[cyclomatic_complexity = "0"] -fn barrrr() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn barrrr() { //~ ERROR: the function has a cyclomatic complexity of 2 match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -224,7 +224,7 @@ fn barrrr() { //~ ERROR: The function has a cyclomatic complexity of 2 } #[cyclomatic_complexity = "0"] -fn barrrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 +fn barrrr2() { //~ ERROR: the function has a cyclomatic complexity of 3 match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -240,7 +240,7 @@ fn barrrr2() { //~ ERROR: The function has a cyclomatic complexity of 3 } #[cyclomatic_complexity = "0"] -fn cake() { //~ ERROR: The function has a cyclomatic complexity of 2 +fn cake() { //~ ERROR: the function has a cyclomatic complexity of 2 if 4 == 5 { println!("yea"); } else { @@ -251,7 +251,7 @@ fn cake() { //~ ERROR: The function has a cyclomatic complexity of 2 #[cyclomatic_complexity = "0"] -pub fn read_file(input_path: &str) -> String { //~ ERROR: The function has a cyclomatic complexity of 4 +pub fn read_file(input_path: &str) -> String { //~ ERROR: the function has a cyclomatic complexity of 4 use std::fs::File; use std::io::{Read, Write}; use std::path::Path; @@ -282,7 +282,7 @@ pub fn read_file(input_path: &str) -> String { //~ ERROR: The function has a cyc enum Void {} #[cyclomatic_complexity = "0"] -fn void(void: Void) { //~ ERROR: The function has a cyclomatic complexity of 1 +fn void(void: Void) { //~ ERROR: the function has a cyclomatic complexity of 1 if true { match void { } diff --git a/tests/compile-fail/open_options.rs b/tests/compile-fail/open_options.rs index 35cc91c9d0f..08024e37d4a 100644 --- a/tests/compile-fail/open_options.rs +++ b/tests/compile-fail/open_options.rs @@ -5,12 +5,12 @@ use std::fs::OpenOptions; #[allow(unused_must_use)] #[deny(nonsensical_open_options)] fn main() { - OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~ERROR File opened with "truncate" and "read" - OpenOptions::new().append(true).truncate(true).open("foo.txt"); //~ERROR File opened with "append" and "truncate" - - OpenOptions::new().read(true).read(false).open("foo.txt"); //~ERROR The method "read" is called more than once - OpenOptions::new().create(true).create(false).open("foo.txt"); //~ERROR The method "create" is called more than once - OpenOptions::new().write(true).write(false).open("foo.txt"); //~ERROR The method "write" is called more than once - OpenOptions::new().append(true).append(false).open("foo.txt"); //~ERROR The method "append" is called more than once - OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); //~ERROR The method "truncate" is called more than once + OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~ERROR file opened with "truncate" and "read" + OpenOptions::new().append(true).truncate(true).open("foo.txt"); //~ERROR file opened with "append" and "truncate" + + OpenOptions::new().read(true).read(false).open("foo.txt"); //~ERROR the method "read" is called more than once + OpenOptions::new().create(true).create(false).open("foo.txt"); //~ERROR the method "create" is called more than once + OpenOptions::new().write(true).write(false).open("foo.txt"); //~ERROR the method "write" is called more than once + OpenOptions::new().append(true).append(false).open("foo.txt"); //~ERROR the method "append" is called more than once + OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); //~ERROR the method "truncate" is called more than once } diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index 34dfc1ef25b..5a3f8b1a368 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -12,12 +12,12 @@ const OPENING_PAREN : &'static str = "("; fn main() { let pipe_in_wrong_position = Regex::new("|"); - //~^ERROR: Regex syntax error: empty alternate - let wrong_char_ranice = Regex::new("[z-a]"); - //~^ERROR: Regex syntax error: invalid character class range - + //~^ERROR: regex syntax error: empty alternate + let wrong_char_ranice = Regex::new("[z-a]"); + //~^ERROR: regex syntax error: invalid character class range + let some_regex = Regex::new(OPENING_PAREN); - //~^ERROR: Regex syntax error on position 0: unclosed + //~^ERROR: regex syntax error on position 0: unclosed let closing_paren = ")"; let not_linted = Regex::new(closing_paren); -- cgit 1.4.1-3-g733a5 From a02b8124de9b778e822814608217ca774ec231fa Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 5 Feb 2016 23:10:48 +0100 Subject: Lint about trivial regexes --- README.md | 3 ++- src/lib.rs | 1 + src/regex.rs | 60 +++++++++++++++++++++++++++++++++++++++------ tests/compile-fail/regex.rs | 47 +++++++++++++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 59a12e09b17..08ad214e690 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 112 lints included in this crate: +There are 113 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -104,6 +104,7 @@ name [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. +[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) diff --git a/src/lib.rs b/src/lib.rs index 3f18bcb17ce..33de4d6fb79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -257,6 +257,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_STEP_BY_ZERO, ranges::RANGE_ZIP_WITH_LEN, regex::INVALID_REGEX, + regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, diff --git a/src/regex.rs b/src/regex.rs index c24edc564ae..0558b77acb0 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -8,7 +8,7 @@ use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::lint::*; -use utils::{match_path, REGEX_NEW_PATH, span_lint}; +use utils::{match_path, REGEX_NEW_PATH, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. It is `deny` by default. /// @@ -23,12 +23,26 @@ declare_lint! { "finds invalid regular expressions in `Regex::new(_)` invocations" } +/// **What it does:** This lint checks for `Regex::new(_)` invocations with trivial regex. +/// +/// **Why is this bad?** This can likely be replaced by `==` or `str::starts_with`, +/// `str::ends_with` or `std::contains` or other `str` methods. +/// +/// **Known problems:** None. +/// +/// **Example:** `Regex::new("^foobar")` +declare_lint! { + pub TRIVIAL_REGEX, + Warn, + "finds trivial regular expressions in `Regex::new(_)` invocations" +} + #[derive(Copy,Clone)] pub struct RegexPass; impl LintPass for RegexPass { fn get_lints(&self) -> LintArray { - lint_array!(INVALID_REGEX) + lint_array!(INVALID_REGEX, TRIVIAL_REGEX) } } @@ -48,19 +62,26 @@ impl LateLintPass for RegexPass { &format!("regex syntax error: {}", e.description())); } + else if let Some(repl) = is_trivial_regex(r) { + span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, + &"trivial regex", + &format!("consider using {}", repl)); + } } - } else { - if_let_chain!{[ - let Some(r) = const_str(cx, &*args[0]), - let Err(e) = regex_syntax::Expr::parse(&r) - ], { + } else if let Some(r) = const_str(cx, &*args[0]) { + if let Err(e) = regex_syntax::Expr::parse(&r) { span_lint(cx, INVALID_REGEX, args[0].span, &format!("regex syntax error on position {}: {}", e.position(), e.description())); - }} + } + else if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, + &"trivial regex", + &format!("{}", repl)); + } } }} } @@ -81,3 +102,26 @@ fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { _ => None } } + +fn is_trivial_regex(s: &str) -> Option<&'static str> { + // some unlikely but valid corner cases + match s { + "" | "^" | "$" => return Some("the regex is unlikely to be useful as it is"), + "^$" => return Some("consider using `str::is_empty`"), + _ => (), + } + + let (start, end, repl) = match (s.starts_with('^'), s.ends_with('$')) { + (true, true) => (1, s.len()-1, "consider using `==` on `str`s"), + (false, true) => (0, s.len()-1, "consider using `str::ends_with`"), + (true, false) => (1, s.len(), "consider using `str::starts_with`"), + (false, false) => (0, s.len(), "consider using `str::contains`"), + }; + + if !s.chars().take(end).skip(start).any(regex_syntax::is_punct) { + Some(repl) + } + else { + None + } +} diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index 5a3f8b1a368..cd10d47c1bb 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -2,15 +2,16 @@ #![plugin(clippy)] #![allow(unused)] -#![deny(invalid_regex)] +#![deny(invalid_regex, trivial_regex)] extern crate regex; use regex::Regex; const OPENING_PAREN : &'static str = "("; +const NOT_A_REAL_REGEX : &'static str = "foobar"; -fn main() { +fn syntax_error() { let pipe_in_wrong_position = Regex::new("|"); //~^ERROR: regex syntax error: empty alternate let wrong_char_ranice = Regex::new("[z-a]"); @@ -22,3 +23,45 @@ fn main() { let closing_paren = ")"; let not_linted = Regex::new(closing_paren); } + +fn trivial_regex() { + let trivial_eq = Regex::new("^foobar$"); + //~^ERROR: trivial regex + //~|HELP consider using `==` on `str`s + + let trivial_starts_with = Regex::new("^foobar"); + //~^ERROR: trivial regex + //~|HELP consider using `str::starts_with` + + let trivial_ends_with = Regex::new("foobar$"); + //~^ERROR: trivial regex + //~|HELP consider using `str::ends_with` + + let trivial_contains = Regex::new("foobar"); + //~^ERROR: trivial regex + //~|HELP consider using `str::contains` + + let trivial_contains = Regex::new(NOT_A_REAL_REGEX); + //~^ERROR: trivial regex + //~|HELP consider using `str::contains` + + // unlikely corner cases + let trivial_empty = Regex::new(""); + //~^ERROR: trivial regex + //~|HELP the regex is unlikely to be useful + + let trivial_empty = Regex::new("^$"); + //~^ERROR: trivial regex + //~|HELP consider using `str::is_empty` + + // non-trivial regexes + let non_trivial_eq = Regex::new("^foo|bar$"); + let non_trivial_starts_with = Regex::new("^foo|bar"); + let non_trivial_ends_with = Regex::new("^foo|bar"); + let non_trivial_ends_with = Regex::new("foo|bar"); +} + +fn main() { + syntax_error(); + trivial_regex(); +} -- cgit 1.4.1-3-g733a5 From 13f245f6c951e6dca16dd02851237e5f271a31d0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 00:13:29 +0100 Subject: Fix util/update_wiki.py warnings and be consistent in declare_lint! invocations --- src/attrs.rs | 12 +++-- src/cyclomatic_complexity.rs | 6 ++- src/drop_ref.rs | 6 ++- src/enum_variants.rs | 6 ++- src/escape.rs | 4 +- src/eta_reduction.rs | 6 ++- src/identity_op.rs | 6 ++- src/items_after_statements.rs | 6 ++- src/len_zero.rs | 14 ++++-- src/lifetimes.rs | 16 ++++-- src/loops.rs | 83 ++++++++++++++++++++++--------- src/map_clone.rs | 8 +-- src/matches.rs | 35 ++++++++----- src/methods.rs | 112 +++++++++++++++++++++++++++--------------- src/minmax.rs | 7 +-- src/misc.rs | 10 ++-- src/misc_early.rs | 12 +++-- src/mut_mut.rs | 9 ++-- src/panic.rs | 4 +- src/precedence.rs | 8 +-- src/returns.rs | 15 ++++-- src/shadow.rs | 20 +++++--- src/types.rs | 71 +++++++++++++++++--------- src/unicode.rs | 24 ++++++--- src/zero_div_zero.rs | 7 ++- 25 files changed, 341 insertions(+), 166 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 012c4e502b4..f224b7dff29 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -22,8 +22,10 @@ use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; /// #[inline(always)] /// fn not_quite_hot_code(..) { ... } /// ``` -declare_lint! { pub INLINE_ALWAYS, Warn, - "`#[inline(always)]` is a bad idea in most cases" } +declare_lint! { + pub INLINE_ALWAYS, Warn, + "`#[inline(always)]` is a bad idea in most cases" +} /// **What it does:** This lint `Warn`s on `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. /// @@ -36,8 +38,10 @@ declare_lint! { pub INLINE_ALWAYS, Warn, /// #[deprecated(since = "forever")] /// fn something_else(..) { ... } /// ``` -declare_lint! { pub DEPRECATED_SEMVER, Warn, - "`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" } +declare_lint! { + pub DEPRECATED_SEMVER, Warn, + "`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" +} #[derive(Copy,Clone)] pub struct AttrPass; diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index d4375abcd05..7eab7c1935f 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -18,8 +18,10 @@ use utils::{in_macro, LimitStack, span_help_and_lint}; /// **Known problems:** Sometimes it's hard to find a way to reduce the complexity /// /// **Example:** No. You'll see it when you get the warning. -declare_lint! { pub CYCLOMATIC_COMPLEXITY, Warn, - "finds functions that should be split up into multiple functions" } +declare_lint! { + pub CYCLOMATIC_COMPLEXITY, Warn, + "finds functions that should be split up into multiple functions" +} pub struct CyclomaticComplexity { limit: LimitStack, diff --git a/src/drop_ref.rs b/src/drop_ref.rs index c15689d8cd6..f7a0ca59f01 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -18,9 +18,11 @@ use utils::{match_def_path, span_note_and_lint}; /// std::mem::drop(&lock_guard) //Should have been drop(lock_guard), mutex still locked /// operation_that_requires_mutex_to_be_unlocked(); /// ``` -declare_lint!(pub DROP_REF, Warn, +declare_lint! { + pub DROP_REF, Warn, "call to `std::mem::drop` with a reference instead of an owned value, \ - which will not call the `Drop::drop` method on the underlying value"); + which will not call the `Drop::drop` method on the underlying value" +} #[allow(missing_copy_implementations)] pub struct DropRefPass; diff --git a/src/enum_variants.rs b/src/enum_variants.rs index bf0025e021c..8ceaca1bbf3 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -14,8 +14,10 @@ use utils::span_help_and_lint; /// **Known problems:** None /// /// **Example:** enum Cake { BlackForestCake, HummingbirdCake } -declare_lint! { pub ENUM_VARIANT_NAMES, Warn, - "finds enums where all variants share a prefix/postfix" } +declare_lint! { + pub ENUM_VARIANT_NAMES, Warn, + "finds enums where all variants share a prefix/postfix" +} pub struct EnumVariantNames; diff --git a/src/escape.rs b/src/escape.rs index 123b2b5c307..b7bec46c3fd 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -29,7 +29,9 @@ pub struct EscapePass; /// println!("{}", *x); /// } /// ``` -declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"); +declare_lint! { + pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary" +} fn is_non_trait_box(ty: ty::Ty) -> bool { match ty.sty { diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index fcc1a6893b2..39063f91ba3 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -16,8 +16,10 @@ pub struct EtaPass; /// **Known problems:** None /// /// **Example:** `xs.map(|x| foo(x))` where `foo(_)` is a plain function that takes the exact argument type of `x`. -declare_lint!(pub REDUNDANT_CLOSURE, Warn, - "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"); +declare_lint! { + pub REDUNDANT_CLOSURE, Warn, + "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)" +} impl LintPass for EtaPass { fn get_lints(&self) -> LintArray { diff --git a/src/identity_op.rs b/src/identity_op.rs index 5fa9c7588cd..093c37783eb 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -12,8 +12,10 @@ use utils::{span_lint, snippet, in_macro}; /// **Known problems:** None /// /// **Example:** `x / 1 + 0 * 1 - 0 | 0` -declare_lint! { pub IDENTITY_OP, Warn, - "using identity operations, e.g. `x + 0` or `y / 1`" } +declare_lint! { + pub IDENTITY_OP, Warn, + "using identity operations, e.g. `x + 0` or `y / 1`" +} #[derive(Copy,Clone)] pub struct IdentityOp; diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index ad666a3bf3f..2f061d32546 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -27,7 +27,11 @@ use utils::in_macro; /// foo(); // prints "foo" /// } /// ``` -declare_lint! { pub ITEMS_AFTER_STATEMENTS, Warn, "finds blocks where an item comes after a statement" } +declare_lint! { + pub ITEMS_AFTER_STATEMENTS, + Warn, + "finds blocks where an item comes after a statement" +} pub struct ItemsAfterStatemets; diff --git a/src/len_zero.rs b/src/len_zero.rs index 6bc5bc4bf01..48fc10ef236 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -18,9 +18,11 @@ use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; /// **Known problems:** None /// /// **Example:** `if x.len() == 0 { .. }` -declare_lint!(pub LEN_ZERO, Warn, - "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ - could be used instead"); +declare_lint! { + pub LEN_ZERO, Warn, + "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ + could be used instead" +} /// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. It is `Warn` by default. /// @@ -34,8 +36,10 @@ declare_lint!(pub LEN_ZERO, Warn, /// fn len(&self) -> usize { .. } /// } /// ``` -declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, - "traits and impls that have `.len()` but not `.is_empty()`"); +declare_lint! { + pub LEN_WITHOUT_IS_EMPTY, Warn, + "traits and impls that have `.len()` but not `.is_empty()`" +} #[derive(Copy,Clone)] pub struct LenZero; diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 3e9880d5932..f2f33a634bc 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -15,9 +15,12 @@ use utils::{in_external_macro, span_lint}; /// **Known problems:** Potential false negatives: we bail out if the function has a `where` clause where lifetimes are mentioned. /// /// **Example:** `fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }` -declare_lint!(pub NEEDLESS_LIFETIMES, Warn, - "using explicit lifetimes for references in function arguments when elision rules \ - would allow omitting them"); +declare_lint! { + pub NEEDLESS_LIFETIMES, + Warn, + "using explicit lifetimes for references in function arguments when elision rules \ + would allow omitting them" +} /// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. It is `Warn` by default. /// @@ -26,8 +29,11 @@ declare_lint!(pub NEEDLESS_LIFETIMES, Warn, /// **Known problems:** None /// /// **Example:** `fn unused_lifetime<'a>(x: u8) { .. }` -declare_lint!(pub UNUSED_LIFETIMES, Warn, - "unused lifetimes in function definitions"); +declare_lint! { + pub UNUSED_LIFETIMES, + Warn, + "unused lifetimes in function definitions" +} #[derive(Copy,Clone)] pub struct LifetimePass; diff --git a/src/loops.rs b/src/loops.rs index 3f430a1aaf0..bfd0e9895e5 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -25,8 +25,11 @@ use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_ /// println!("{}", vec[i]); /// } /// ``` -declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, - "for-looping over a range of indices where an iterator over items would do" } +declare_lint! { + pub NEEDLESS_RANGE_LOOP, + Warn, + "for-looping over a range of indices where an iterator over items would do" +} /// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. It is `Warn` by default. /// @@ -35,8 +38,11 @@ declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, /// **Known problems:** False negatives. We currently only warn on some known types. /// /// **Example:** `for x in y.iter() { .. }` (where y is a `Vec` or slice) -declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, - "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } +declare_lint! { + pub EXPLICIT_ITER_LOOP, + Warn, + "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" +} /// **What it does:** This lint checks for loops on `x.next()`. It is `Warn` by default. /// @@ -45,8 +51,11 @@ declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn, /// **Known problems:** None /// /// **Example:** `for x in y.next() { .. }` -declare_lint!{ pub ITER_NEXT_LOOP, Warn, - "for-looping over `_.next()` which is probably not intended" } +declare_lint! { + pub ITER_NEXT_LOOP, + Warn, + "for-looping over `_.next()` which is probably not intended" +} /// **What it does:** This lint checks for `for` loops over `Option` values. It is `Warn` by default. /// @@ -55,8 +64,11 @@ declare_lint!{ pub ITER_NEXT_LOOP, Warn, /// **Known problems:** None /// /// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`. -declare_lint!{ pub FOR_LOOP_OVER_OPTION, Warn, - "for-looping over an `Option`, which is more clearly expressed as an `if let`" } +declare_lint! { + pub FOR_LOOP_OVER_OPTION, + Warn, + "for-looping over an `Option`, which is more clearly expressed as an `if let`" +} /// **What it does:** This lint checks for `for` loops over `Result` values. It is `Warn` by default. /// @@ -65,8 +77,11 @@ declare_lint!{ pub FOR_LOOP_OVER_OPTION, Warn, /// **Known problems:** None /// /// **Example:** `for x in result { .. }`. This should be `if let Ok(x) = result { .. }`. -declare_lint!{ pub FOR_LOOP_OVER_RESULT, Warn, - "for-looping over a `Result`, which is more clearly expressed as an `if let`" } +declare_lint! { + pub FOR_LOOP_OVER_RESULT, + Warn, + "for-looping over a `Result`, which is more clearly expressed as an `if let`" +} /// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default. /// @@ -89,8 +104,11 @@ declare_lint!{ pub FOR_LOOP_OVER_RESULT, Warn, /// // .. do something with x /// } /// ``` -declare_lint!{ pub WHILE_LET_LOOP, Warn, - "`loop { if let { ... } else break }` can be written as a `while let` loop" } +declare_lint! { + pub WHILE_LET_LOOP, + Warn, + "`loop { if let { ... } else break }` can be written as a `while let` loop" +} /// **What it does:** This lint checks for using `collect()` on an iterator without using the result. It is `Warn` by default. /// @@ -99,9 +117,12 @@ declare_lint!{ pub WHILE_LET_LOOP, Warn, /// **Known problems:** None /// /// **Example:** `vec.iter().map(|x| /* some operation returning () */).collect::<Vec<_>>();` -declare_lint!{ pub UNUSED_COLLECT, Warn, - "`collect()`ing an iterator without using the result; this is usually better \ - written as a for loop" } +declare_lint! { + pub UNUSED_COLLECT, + Warn, + "`collect()`ing an iterator without using the result; this is usually better \ + written as a for loop" +} /// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. It is `Warn` by default. /// @@ -110,8 +131,11 @@ declare_lint!{ pub UNUSED_COLLECT, Warn, /// **Known problems:** The lint cannot catch loops over dynamically defined ranges. Doing this would require simulating all possible inputs and code paths through the program, which would be complex and error-prone. /// /// **Examples**: `for x in 5..10-5 { .. }` (oops, stray `-`) -declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, - "Iterating over an empty range, such as `10..0` or `5..5`" } +declare_lint! { + pub REVERSE_RANGE_LOOP, + Warn, + "Iterating over an empty range, such as `10..0` or `5..5`" +} /// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. It is `Warn` by default. /// @@ -120,8 +144,11 @@ declare_lint!{ pub REVERSE_RANGE_LOOP, Warn, /// **Known problems:** None. /// /// **Example:** `for i in 0..v.len() { foo(v[i]); }` or `for i in 0..v.len() { bar(i, v[i]); }` -declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, - "for-looping with an explicit counter when `_.enumerate()` would do" } +declare_lint! { + pub EXPLICIT_COUNTER_LOOP, + Warn, + "for-looping with an explicit counter when `_.enumerate()` would do" +} /// **What it does:** This lint checks for empty `loop` expressions. It is `Warn` by default. /// @@ -130,7 +157,11 @@ declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn, /// **Known problems:** None /// /// **Example:** `loop {}` -declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } +declare_lint! { + pub EMPTY_LOOP, + Warn, + "empty `loop {}` detected" +} /// **What it does:** This lint checks for `while let` expressions on iterators. It is `Warn` by default. /// @@ -139,7 +170,11 @@ declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" } /// **Known problems:** None /// /// **Example:** `while let Some(val) = iter() { .. }` -declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" } +declare_lint! { + pub WHILE_LET_ON_ITERATOR, + Warn, + "using a while-let loop instead of a for loop on an iterator" +} /// **What it does:** This warns when you iterate on a map (`HashMap` or `BTreeMap`) and ignore /// either the keys or values. @@ -157,7 +192,11 @@ declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead /// ```rust /// for k in map.keys() { .. } /// ``` -declare_lint!{ pub FOR_KV_MAP, Warn, "looping on a map using `iter` when `keys` or `values` would do" } +declare_lint! { + pub FOR_KV_MAP, + Warn, + "looping on a map using `iter` when `keys` or `values` would do" +} #[derive(Copy, Clone)] pub struct LoopsPass; diff --git a/src/map_clone.rs b/src/map_clone.rs index 9db97a1b9f2..d4773986399 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -11,9 +11,11 @@ use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; /// **Known problems:** None /// /// **Example:** `x.map(|e| e.clone());` -declare_lint!(pub MAP_CLONE, Warn, - "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ - `.cloned()` instead)"); +declare_lint! { + pub MAP_CLONE, Warn, + "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ + `.cloned()` instead)" +} #[derive(Copy, Clone)] pub struct MapClonePass; diff --git a/src/matches.rs b/src/matches.rs index e690f04bdb0..fb0663117fa 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -24,9 +24,11 @@ use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_th /// _ => () /// } /// ``` -declare_lint!(pub SINGLE_MATCH, Warn, - "a match statement with a single nontrivial arm (i.e, where the other arm \ - is `_ => {}`) is used; recommends `if let` instead"); +declare_lint! { + pub SINGLE_MATCH, Warn, + "a match statement with a single nontrivial arm (i.e, where the other arm \ + is `_ => {}`) is used; recommends `if let` instead" +} /// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. It is `Allow` by default. /// @@ -41,9 +43,11 @@ declare_lint!(pub SINGLE_MATCH, Warn, /// _ => bar(other_ref), /// } /// ``` -declare_lint!(pub SINGLE_MATCH_ELSE, Allow, - "a match statement with a two arms where the second arm's pattern is a wildcard; \ - recommends `if let` instead"); +declare_lint! { + pub SINGLE_MATCH_ELSE, Allow, + "a match statement with a two arms where the second arm's pattern is a wildcard; \ + recommends `if let` instead" +} /// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. It is `Warn` by default. /// @@ -60,9 +64,11 @@ declare_lint!(pub SINGLE_MATCH_ELSE, Allow, /// _ => frob(&x), /// } /// ``` -declare_lint!(pub MATCH_REF_PATS, Warn, - "a match or `if let` has all arms prefixed with `&`; the match expression can be \ - dereferenced instead"); +declare_lint! { + pub MATCH_REF_PATS, Warn, + "a match or `if let` has all arms prefixed with `&`; the match expression can be \ + dereferenced instead" +} /// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default. /// @@ -79,8 +85,10 @@ declare_lint!(pub MATCH_REF_PATS, Warn, /// false => bar(), /// } /// ``` -declare_lint!(pub MATCH_BOOL, Warn, - "a match on boolean expression; recommends `if..else` block instead"); +declare_lint! { + pub MATCH_BOOL, Warn, + "a match on boolean expression; recommends `if..else` block instead" +} /// **What it does:** This lint checks for overlapping match arms. It is `Warn` by default. /// @@ -98,8 +106,9 @@ declare_lint!(pub MATCH_BOOL, Warn, /// _ => (), /// } /// ``` -declare_lint!(pub MATCH_OVERLAPPING_ARM, Warn, - "a match has overlapping arms"); +declare_lint! { + pub MATCH_OVERLAPPING_ARM, Warn, "a match has overlapping arms" +} #[allow(missing_copy_implementations)] pub struct MatchPass; diff --git a/src/methods.rs b/src/methods.rs index 61a910a65ab..4cd957d0fe7 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -25,8 +25,10 @@ pub struct MethodsPass; /// **Known problems:** None /// /// **Example:** `x.unwrap()` -declare_lint!(pub OPTION_UNWRAP_USED, Allow, - "using `Option.unwrap()`, which should at least get a better message using `expect()`"); +declare_lint! { + pub OPTION_UNWRAP_USED, Allow, + "using `Option.unwrap()`, which should at least get a better message using `expect()`" +} /// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. It is `Allow` by default. /// @@ -37,8 +39,10 @@ declare_lint!(pub OPTION_UNWRAP_USED, Allow, /// **Known problems:** None /// /// **Example:** `x.unwrap()` -declare_lint!(pub RESULT_UNWRAP_USED, Allow, - "using `Result.unwrap()`, which might be better handled"); +declare_lint! { + pub RESULT_UNWRAP_USED, Allow, + "using `Result.unwrap()`, which might be better handled" +} /// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. It is `Warn` by default. /// @@ -47,8 +51,10 @@ declare_lint!(pub RESULT_UNWRAP_USED, Allow, /// **Known problems:** None /// /// **Example:** `s.to_string()` where `s: &str` -declare_lint!(pub STR_TO_STRING, Warn, - "using `to_string()` on a str, which should be `to_owned()`"); +declare_lint! { + pub STR_TO_STRING, Warn, + "using `to_string()` on a str, which should be `to_owned()`" +} /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default. /// @@ -58,8 +64,10 @@ declare_lint!(pub STR_TO_STRING, Warn, /// **Known problems:** None /// /// **Example:** `s.to_string()` where `s: String` -declare_lint!(pub STRING_TO_STRING, Warn, - "calling `String::to_string` which is inefficient"); +declare_lint! { + pub STRING_TO_STRING, Warn, + "calling `String::to_string` which is inefficient" +} /// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default. /// @@ -74,8 +82,10 @@ declare_lint!(pub STRING_TO_STRING, Warn, /// fn add(&self, other: &X) -> X { .. } /// } /// ``` -declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, - "defining a method that should be implementing a std trait"); +declare_lint! { + pub SHOULD_IMPLEMENT_TRAIT, Warn, + "defining a method that should be implementing a std trait" +} /// **What it does:** This lint checks for methods with certain name prefixes and `Warn`s (by default) if the prefix doesn't match how self is taken. The actual rules are: /// @@ -98,9 +108,11 @@ declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn, /// fn as_str(self) -> &str { .. } /// } /// ``` -declare_lint!(pub WRONG_SELF_CONVENTION, Warn, - "defining a method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention"); +declare_lint! { + pub WRONG_SELF_CONVENTION, Warn, + "defining a method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} /// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. This lint is `Allow` by default. /// @@ -114,9 +126,11 @@ declare_lint!(pub WRONG_SELF_CONVENTION, Warn, /// pub fn as_str(self) -> &str { .. } /// } /// ``` -declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, - "defining a public method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention"); +declare_lint! { + pub WRONG_PUB_SELF_CONVENTION, Allow, + "defining a public method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} /// **What it does:** This lint `Warn`s on using `ok().expect(..)`. /// @@ -125,9 +139,11 @@ declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow, /// **Known problems:** None. /// /// **Example:** `x.ok().expect("why did I do this again?")` -declare_lint!(pub OK_EXPECT, Warn, - "using `ok().expect()`, which gives worse error messages than \ - calling `expect` directly on the Result"); +declare_lint! { + pub OK_EXPECT, Warn, + "using `ok().expect()`, which gives worse error messages than \ + calling `expect` directly on the Result" +} /// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or(_)`. /// @@ -136,9 +152,11 @@ declare_lint!(pub OK_EXPECT, Warn, /// **Known problems:** None. /// /// **Example:** `x.map(|a| a + 1).unwrap_or(0)` -declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, - "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ - `map_or(a, f)`"); +declare_lint! { + pub OPTION_MAP_UNWRAP_OR, Warn, + "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ + `map_or(a, f)`" +} /// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`. /// @@ -147,9 +165,11 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn, /// **Known problems:** None. /// /// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)` -declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, - "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`"); +declare_lint! { + pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, + "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `map_or_else(g, f)`" +} /// **What it does:** This lint `Warn`s on `_.filter(_).next()`. /// @@ -158,8 +178,10 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, /// **Known problems:** None. /// /// **Example:** `iter.filter(|x| x == 0).next()` -declare_lint!(pub FILTER_NEXT, Warn, - "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"); +declare_lint! { + pub FILTER_NEXT, Warn, + "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" +} /// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or /// `rposition()`) followed by a call to `is_some()`. @@ -169,9 +191,11 @@ declare_lint!(pub FILTER_NEXT, Warn, /// **Known problems:** None. /// /// **Example:** `iter.find(|x| x == 0).is_some()` -declare_lint!(pub SEARCH_IS_SOME, Warn, - "using an iterator search followed by `is_some()`, which is more succinctly \ - expressed as a call to `any()`"); +declare_lint! { + pub SEARCH_IS_SOME, Warn, + "using an iterator search followed by `is_some()`, which is more succinctly \ + expressed as a call to `any()`" +} /// **What it does:** This lint `Warn`s on using `.chars().next()` on a `str` to check if it /// starts with a given char. @@ -181,8 +205,10 @@ declare_lint!(pub SEARCH_IS_SOME, Warn, /// **Known problems:** None. /// /// **Example:** `name.chars().next() == Some('_')` -declare_lint!(pub CHARS_NEXT_CMP, Warn, - "using `.chars().next()` to check if a string starts with a char"); +declare_lint! { + pub CHARS_NEXT_CMP, Warn, + "using `.chars().next()` to check if a string starts with a char" +} /// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and /// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead. @@ -203,8 +229,10 @@ declare_lint!(pub CHARS_NEXT_CMP, Warn, /// /// **Known problems:** If the function as side-effects, not calling it will change the semantic of /// the program, but you shouldn't rely on that anyway. -declare_lint!(pub OR_FUN_CALL, Warn, - "using any `*or` method when the `*or_else` would do"); +declare_lint! { + pub OR_FUN_CALL, Warn, + "using any `*or` method when the `*or_else` would do" +} /// **What it does:** This lint `Warn`s on using `.extend(s)` on a `vec` to extend the vec by a slice. /// @@ -213,8 +241,10 @@ declare_lint!(pub OR_FUN_CALL, Warn, /// **Known problems:** None. /// /// **Example:** `my_vec.extend(&xs)` -declare_lint!(pub EXTEND_FROM_SLICE, Warn, - "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"); +declare_lint! { + pub EXTEND_FROM_SLICE, Warn, + "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice" +} /// **What it does:** This lint warns on using `.clone()` on a `Copy` type. /// @@ -224,8 +254,9 @@ declare_lint!(pub EXTEND_FROM_SLICE, Warn, /// **Known problems:** None. /// /// **Example:** `42u64.clone()` -declare_lint!(pub CLONE_ON_COPY, Warn, - "using `clone` on a `Copy` type"); +declare_lint! { + pub CLONE_ON_COPY, Warn, "using `clone` on a `Copy` type" +} /// **What it does:** This lint warns on using `.clone()` on an `&&T` /// @@ -244,8 +275,9 @@ declare_lint!(pub CLONE_ON_COPY, Warn, /// } /// ``` /// -declare_lint!(pub CLONE_DOUBLE_REF, Warn, - "using `clone` on `&&T`"); +declare_lint! { + pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`" +} impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { diff --git a/src/minmax.rs b/src/minmax.rs index e72f2392054..2e199345579 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -15,9 +15,10 @@ use self::MinMax::{Min, Max}; /// **Known problems:** None /// /// **Example:** `min(0, max(100, x))` will always be equal to `0`. Probably the author meant to clamp the value between 0 and 100, but has erroneously swapped `min` and `max`. -declare_lint!(pub MIN_MAX, Warn, - "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \ - to a constant"); +declare_lint! { + pub MIN_MAX, Warn, + "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" +} #[allow(missing_copy_implementations)] pub struct MinMaxPass; diff --git a/src/misc.rs b/src/misc.rs index d436d98c981..099b1797e8e 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -22,10 +22,12 @@ use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_tra /// **Known problems:** If the argument is dereferenced within the function, removing the `ref` will lead to errors. This can be fixed by removing the dereferences, e.g. changing `*x` to `x` within the function. /// /// **Example:** `fn foo(ref x: u8) -> bool { .. }` -declare_lint!(pub TOPLEVEL_REF_ARG, Warn, - "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ - or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ - references with `&`."); +declare_lint! { + pub TOPLEVEL_REF_ARG, Warn, + "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ + or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ + references with `&`." +} #[allow(missing_copy_implementations)] pub struct TopLevelRefPass; diff --git a/src/misc_early.rs b/src/misc_early.rs index 1573aff2a4d..de3c4289353 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -15,8 +15,10 @@ use utils::{span_lint, span_help_and_lint}; /// **Known problems:** None. /// /// **Example:** `let { a: _, b: ref b, c: _ } = ..` -declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn, - "Struct fields are bound to a wildcard instead of using `..`"); +declare_lint! { + pub UNNEEDED_FIELD_PATTERN, Warn, + "Struct fields are bound to a wildcard instead of using `..`" +} /// **What it does:** This lint `Warn`s on function arguments having the similar names differing by an underscore /// @@ -25,8 +27,10 @@ declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn, /// **Known problems:** None. /// /// **Example:** `fn foo(a: i32, _a: i32) {}` -declare_lint!(pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn, - "Function arguments having names which only differ by an underscore"); +declare_lint! { + pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn, + "Function arguments having names which only differ by an underscore" +} #[derive(Copy, Clone)] pub struct MiscEarly; diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 4623ca38533..99c1d040fd2 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -11,9 +11,12 @@ use utils::{in_external_macro, span_lint}; /// **Known problems:** None /// /// **Example:** `let x = &mut &mut y;` -declare_lint!(pub MUT_MUT, Allow, - "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ - or shows a fundamental misunderstanding of references)"); +declare_lint! { + pub MUT_MUT, + Allow, + "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ + or shows a fundamental misunderstanding of references)" +} #[derive(Copy,Clone)] pub struct MutMut; diff --git a/src/panic.rs b/src/panic.rs index 40d6e7d4dff..dc30f710830 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -13,7 +13,9 @@ use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; /// ``` /// panic!("This panic! is probably missing a parameter there: {}"); /// ``` -declare_lint!(pub PANIC_PARAMS, Warn, "missing parameters in `panic!`"); +declare_lint! { + pub PANIC_PARAMS, Warn, "missing parameters in `panic!`" +} #[allow(missing_copy_implementations)] pub struct PanicPass; diff --git a/src/precedence.rs b/src/precedence.rs index 8253471f8b0..a316f183863 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -15,9 +15,11 @@ use utils::{span_lint, snippet}; /// **Examples:** /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 -declare_lint!(pub PRECEDENCE, Warn, - "catches operations where precedence may be unclear. See the wiki for a \ - list of cases caught"); +declare_lint! { + pub PRECEDENCE, Warn, + "catches operations where precedence may be unclear. See the wiki for a \ + list of cases caught" +} #[derive(Copy,Clone)] pub struct Precedence; diff --git a/src/returns.rs b/src/returns.rs index e4745b8766f..0b0c4d14bdf 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -13,8 +13,11 @@ use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_exter /// **Known problems:** None /// /// **Example:** `fn foo(x: usize) { return x; }` -declare_lint!(pub NEEDLESS_RETURN, Warn, - "using a return statement like `return expr;` where an expression would suffice"); +declare_lint! { + pub NEEDLESS_RETURN, Warn, + "using a return statement like `return expr;` where an expression would suffice" +} + /// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. It is `Warn` by default. /// /// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. @@ -22,9 +25,11 @@ declare_lint!(pub NEEDLESS_RETURN, Warn, /// **Known problems:** None /// /// **Example:** `{ let x = ..; x }` -declare_lint!(pub LET_AND_RETURN, Warn, - "creating a let-binding and then immediately returning it like `let x = expr; x` at \ - the end of a block"); +declare_lint! { + pub LET_AND_RETURN, Warn, + "creating a let-binding and then immediately returning it like `let x = expr; x` at \ + the end of a block" +} #[derive(Copy, Clone)] pub struct ReturnPass; diff --git a/src/shadow.rs b/src/shadow.rs index 1beb00e9056..f772f97c81e 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -16,8 +16,11 @@ use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_not /// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. /// /// **Example:** `let x = &x;` -declare_lint!(pub SHADOW_SAME, Allow, - "rebinding a name to itself, e.g. `let mut x = &mut x`"); +declare_lint! { + pub SHADOW_SAME, Allow, + "rebinding a name to itself, e.g. `let mut x = &mut x`" +} + /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. It is `Allow` by default. /// /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code. @@ -25,9 +28,12 @@ declare_lint!(pub SHADOW_SAME, Allow, /// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. /// /// **Example:** `let x = x + 1;` -declare_lint!(pub SHADOW_REUSE, Allow, +declare_lint! { + pub SHADOW_REUSE, Allow, "rebinding a name to an expression that re-uses the original value, e.g. \ - `let x = x + 1`"); + `let x = x + 1`" +} + /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. This lint is `Warn` by default. /// /// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings. @@ -35,8 +41,10 @@ declare_lint!(pub SHADOW_REUSE, Allow, /// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. /// /// **Example:** `let x = y; let x = z; // shadows the earlier binding` -declare_lint!(pub SHADOW_UNRELATED, Allow, - "The name is re-bound without even using the original value"); +declare_lint! { + pub SHADOW_UNRELATED, Allow, + "The name is re-bound without even using the original value" +} #[derive(Copy, Clone)] pub struct ShadowPass; diff --git a/src/types.rs b/src/types.rs index 0ab373bfa35..bb1201547b3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -22,8 +22,10 @@ pub struct TypePass; /// **Known problems:** None /// /// **Example:** `struct X { values: Box<Vec<Foo>> }` -declare_lint!(pub BOX_VEC, Warn, - "usage of `Box<Vec<T>>`, vector elements are already on the heap"); +declare_lint! { + pub BOX_VEC, Warn, + "usage of `Box<Vec<T>>`, vector elements are already on the heap" +} /// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). It is `Warn` by default. /// @@ -36,9 +38,11 @@ declare_lint!(pub BOX_VEC, Warn, /// **Known problems:** False positives – the instances where using a `LinkedList` makes sense are few and far between, but they can still happen. /// /// **Example:** `let x = LinkedList::new();` -declare_lint!(pub LINKEDLIST, Warn, - "usage of LinkedList, usually a vector is faster, or a more specialized data \ - structure like a VecDeque"); +declare_lint! { + pub LINKEDLIST, Warn, + "usage of LinkedList, usually a vector is faster, or a more specialized data \ + structure like a VecDeque" +} impl LintPass for TypePass { fn get_lints(&self) -> LintArray { @@ -81,8 +85,10 @@ pub struct LetPass; /// **Known problems:** None /// /// **Example:** `let x = { 1; };` -declare_lint!(pub LET_UNIT_VALUE, Warn, - "creating a let binding to a value of unit type, which usually can't be used afterwards"); +declare_lint! { + pub LET_UNIT_VALUE, Warn, + "creating a let binding to a value of unit type, which usually can't be used afterwards" +} fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { @@ -122,8 +128,10 @@ impl LateLintPass for LetPass { /// **Known problems:** None /// /// **Example:** `if { foo(); } == { bar(); } { baz(); }` is equal to `{ foo(); bar(); baz(); }` -declare_lint!(pub UNIT_CMP, Warn, - "comparing unit values (which is always `true` or `false`, respectively)"); +declare_lint! { + pub UNIT_CMP, Warn, + "comparing unit values (which is always `true` or `false`, respectively)" +} #[allow(missing_copy_implementations)] pub struct UnitCmp; @@ -169,8 +177,11 @@ pub struct CastPass; /// **Known problems:** None /// /// **Example:** `let x = u64::MAX; x as f64` -declare_lint!(pub CAST_PRECISION_LOSS, Allow, - "casts that cause loss of precision, e.g `x as f32` where `x: u64`"); +declare_lint! { + pub CAST_PRECISION_LOSS, Allow, + "casts that cause loss of precision, e.g `x as f32` where `x: u64`" +} + /// **What it does:** This lint checks for casts from a signed to an unsigned numerical type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default. /// /// **Why is this bad?** Possibly surprising results. You can activate this lint as a one-time check to see where numerical wrapping can arise. @@ -178,8 +189,11 @@ declare_lint!(pub CAST_PRECISION_LOSS, Allow, /// **Known problems:** None /// /// **Example:** `let y : i8 = -1; y as u64` will return 18446744073709551615 -declare_lint!(pub CAST_SIGN_LOSS, Allow, - "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"); +declare_lint! { + pub CAST_SIGN_LOSS, Allow, + "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`" +} + /// **What it does:** This lint checks for on casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by default. /// /// **Why is this bad?** In some problem domains, it is good practice to avoid truncation. This lint can be activated to help assess where additional checks could be beneficial. @@ -187,8 +201,11 @@ declare_lint!(pub CAST_SIGN_LOSS, Allow, /// **Known problems:** None /// /// **Example:** `fn as_u8(x: u64) -> u8 { x as u8 }` -declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, - "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`"); +declare_lint! { + pub CAST_POSSIBLE_TRUNCATION, Allow, + "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`" +} + /// **What it does:** This lint checks for casts from an unsigned type to a signed type of the same size. Performing such a cast is a 'no-op' for the compiler, i.e. nothing is changed at the bit level, and the binary representation of the value is reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default. /// /// **Why is this bad?** While such a cast is not bad in itself, the results can be surprising when this is not the intended behavior, as demonstrated by the example below. @@ -196,8 +213,10 @@ declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow, /// **Known problems:** None /// /// **Example:** `u32::MAX as i32` will yield a value of `-1`. -declare_lint!(pub CAST_POSSIBLE_WRAP, Allow, - "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`"); +declare_lint! { + pub CAST_POSSIBLE_WRAP, Allow, + "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`" +} /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant @@ -393,8 +412,10 @@ impl LateLintPass for CastPass { /// **Known problems:** None /// /// **Example:** `struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }` -declare_lint!(pub TYPE_COMPLEXITY, Warn, - "usage of very complex types; recommends factoring out parts into `type` definitions"); +declare_lint! { + pub TYPE_COMPLEXITY, Warn, + "usage of very complex types; recommends factoring out parts into `type` definitions" +} #[allow(missing_copy_implementations)] pub struct TypeComplexityPass; @@ -525,8 +546,10 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { /// **Known problems:** None /// /// **Example:** `'x' as u8` -declare_lint!(pub CHAR_LIT_AS_U8, Warn, - "Casting a character literal to u8"); +declare_lint! { + pub CHAR_LIT_AS_U8, Warn, + "Casting a character literal to u8" +} pub struct CharLitAsU8; @@ -565,8 +588,10 @@ impl LateLintPass for CharLitAsU8 { /// **Known problems:** None /// /// **Example:** `vec.len() <= 0` -declare_lint!(pub ABSURD_UNSIGNED_COMPARISONS, Warn, - "testing whether an unsigned integer is non-positive"); +declare_lint! { + pub ABSURD_UNSIGNED_COMPARISONS, Warn, + "testing whether an unsigned integer is non-positive" +} pub struct AbsurdUnsignedComparisons; diff --git a/src/unicode.rs b/src/unicode.rs index d5ea7199e10..92d365f0323 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -15,8 +15,11 @@ use utils::{snippet, span_help_and_lint}; /// **Known problems:** None /// /// **Example:** You don't see it, but there may be a zero-width space somewhere in this text. -declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, - "using a zero-width space in a string literal, which is confusing" } +declare_lint! { + pub ZERO_WIDTH_SPACE, Deny, + "using a zero-width space in a string literal, which is confusing" +} + /// **What it does:** This lint checks for non-ascii characters in string literals. It is `Allow` by default. /// /// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful. @@ -24,9 +27,12 @@ declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, /// **Known problems:** None /// /// **Example:** `let x = "Hä?"` -declare_lint!{ pub NON_ASCII_LITERAL, Allow, - "using any literal non-ASCII chars in a string literal; suggests \ - using the \\u escape instead" } +declare_lint! { + pub NON_ASCII_LITERAL, Allow, + "using any literal non-ASCII chars in a string literal; suggests \ + using the \\u escape instead" +} + /// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). This lint is `Allow` by default. /// /// **Why is this bad?** If such a string is compared to another, the results may be surprising. @@ -34,9 +40,11 @@ declare_lint!{ pub NON_ASCII_LITERAL, Allow, /// **Known problems** None /// /// **Example:** You may not see it, but "à" and "à" aren't the same string. The former when escaped is actually "a\u{300}" while the latter is "\u{e0}". -declare_lint!{ pub UNICODE_NOT_NFC, Allow, - "using a unicode literal not in NFC normal form (see \ - http://www.unicode.org/reports/tr15/ for further information)" } +declare_lint! { + pub UNICODE_NOT_NFC, Allow, + "using a unicode literal not in NFC normal form (see \ + http://www.unicode.org/reports/tr15/ for further information)" +} #[derive(Copy, Clone)] diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 2c3ec86936c..9c5c07cd678 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -16,8 +16,11 @@ pub struct ZeroDivZeroPass; /// **Known problems:** None /// /// **Example** `0.0f32 / 0.0` -declare_lint!(pub ZERO_DIVIDED_BY_ZERO, Warn, - "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN"); +declare_lint! { + pub ZERO_DIVIDED_BY_ZERO, + Warn, + "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" +} impl LintPass for ZeroDivZeroPass { fn get_lints(&self) -> LintArray { -- cgit 1.4.1-3-g733a5 From 83a82a1d86b0a5b9fe39ca7b33e7bca2687a733b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 00:41:54 +0100 Subject: Remove redundancy in lint documentation The default level is always given in the declare_lint! macro, no need to add it inconsistently in the documentation. --- src/approx_const.rs | 2 +- src/attrs.rs | 4 ++-- src/bit_mask.rs | 4 +--- src/block_in_if_condition.rs | 4 ++-- src/collapsible_if.rs | 2 +- src/cyclomatic_complexity.rs | 2 +- src/drop_ref.rs | 2 +- src/eq_op.rs | 2 +- src/escape.rs | 2 +- src/eta_reduction.rs | 2 +- src/identity_op.rs | 2 +- src/items_after_statements.rs | 3 +-- src/len_zero.rs | 4 ++-- src/lifetimes.rs | 4 ++-- src/loops.rs | 22 +++++++++++----------- src/map_clone.rs | 2 +- src/matches.rs | 10 +++++----- src/methods.rs | 22 +++++++++++----------- src/minmax.rs | 2 +- src/misc.rs | 12 ++++++------ src/misc_early.rs | 4 ++-- src/mut_mut.rs | 2 +- src/mut_reference.rs | 2 +- src/mutex_atomic.rs | 4 ++-- src/needless_bool.rs | 2 +- src/needless_features.rs | 4 ++-- src/needless_update.rs | 2 +- src/no_effect.rs | 2 +- src/open_options.rs | 2 +- src/panic.rs | 4 ++-- src/precedence.rs | 2 +- src/print.rs | 3 +-- src/ptr_arg.rs | 2 +- src/ranges.rs | 4 ++-- src/regex.rs | 2 +- src/returns.rs | 4 ++-- src/shadow.rs | 6 +++--- src/strings.rs | 6 +++--- src/temporary_assignment.rs | 4 ++-- src/transmute.rs | 2 +- src/types.rs | 12 ++++++------ src/unicode.rs | 6 +++--- src/vec.rs | 1 - src/zero_div_zero.rs | 8 ++++---- 44 files changed, 97 insertions(+), 102 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 2c8779ae737..98e2fa97eba 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -6,7 +6,7 @@ use syntax::ast::Lit_::*; use syntax::ast::Lit; use syntax::ast::FloatTy::*; -/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. This lint is `Warn` by default. +/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. /// /// **Why is this bad?** Usually, the definition in the standard library is more precise than what people come up with. If you find that your definition is actually more precise, please [file a Rust issue](https://github.com/rust-lang/rust/issues). /// diff --git a/src/attrs.rs b/src/attrs.rs index f224b7dff29..231a08779cc 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -9,7 +9,7 @@ use syntax::attr::*; use syntax::ast::{Attribute, Lit, Lit_, MetaList, MetaWord, MetaNameValue}; use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; -/// **What it does:** This lint `Warn`s on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. +/// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. /// /// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it. /// @@ -27,7 +27,7 @@ declare_lint! { "`#[inline(always)]` is a bad idea in most cases" } -/// **What it does:** This lint `Warn`s on `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. +/// **What it does:** This lint checks for `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. /// /// **Why is this bad?** For checking the version of the deprecation, it must be valid semver. Failing that, the contained information is useless. /// diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 0fce772010a..b9925f10fa2 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -8,7 +8,7 @@ use syntax::ast::Lit_::*; use utils::span_lint; -/// **What it does:** This lint checks for incompatible bit masks in comparisons. It is `Warn` by default. +/// **What it does:** This lint checks for incompatible bit masks in comparisons. /// /// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` /// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: @@ -43,8 +43,6 @@ declare_lint! { /// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| /// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`| /// -/// This lint is `Warn` by default. -/// /// **Why is this bad?** Not equally evil as [`bad_bit_mask`](#bad_bit_mask), but still a bit misleading, because the bit mask is ineffective. /// /// **Known problems:** False negatives: This lint will only match instances where we have figured out the math (which is for a power-of-two compared value). This means things like `x | 1 >= 7` (which would be better written as `x >= 6`) will not be reported (but bit masks like this are fairly uncommon). diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 0162ef92dd6..65fbce640cf 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -3,7 +3,7 @@ use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; use rustc_front::intravisit::{Visitor, walk_expr}; use utils::*; -/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. It is `Warn` by default. +/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. /// /// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions. /// @@ -15,7 +15,7 @@ declare_lint! { "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" } -/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. It is `Warn` by default. +/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. /// /// **Why is this bad?** Using blocks in the condition makes it hard to read. /// diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 4b3c4174df7..03c43ef5dc8 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -20,7 +20,7 @@ use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; /// **What it does:** This lint checks for nested `if`-statements which can be collapsed by /// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to -/// `else if ..`. It is `Warn` by default. +/// `else if ..`. /// /// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. /// diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 7eab7c1935f..b2be1dddbee 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -11,7 +11,7 @@ use rustc_front::intravisit::{Visitor, walk_expr}; use utils::{in_macro, LimitStack, span_help_and_lint}; -/// **What it does:** It `Warn`s on methods with high cyclomatic complexity +/// **What it does:** This lint checks for methods with high cyclomatic complexity /// /// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better. /// diff --git a/src/drop_ref.rs b/src/drop_ref.rs index f7a0ca59f01..6dc3d734196 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -15,7 +15,7 @@ use utils::{match_def_path, span_note_and_lint}; /// **Example:** /// ```rust /// let mut lock_guard = mutex.lock(); -/// std::mem::drop(&lock_guard) //Should have been drop(lock_guard), mutex still locked +/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked /// operation_that_requires_mutex_to_be_unlocked(); /// ``` declare_lint! { diff --git a/src/eq_op.rs b/src/eq_op.rs index 31dc094385f..49037cd9ae7 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -4,7 +4,7 @@ use rustc_front::util as ast_util; use utils::{is_exp_equal, span_lint}; -/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). It is `Warn` by default. +/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). /// /// **Why is this bad?** This is usually just a typo. /// diff --git a/src/escape.rs b/src/escape.rs index b7bec46c3fd..60bfbbc59c3 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -14,7 +14,7 @@ use utils::span_lint; pub struct EscapePass; -/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. It is `Warn` by default. +/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. /// /// **Why is this bad?** This is an unnecessary allocation, and bad for performance. It is only necessary to allocate if you wish to move the box into something. /// diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 39063f91ba3..280392a50b1 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -9,7 +9,7 @@ use utils::{snippet_opt, span_lint_and_then, is_adjusted}; pub struct EtaPass; -/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. It is `Warn` by default. +/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. /// /// **Why is this bad?** Needlessly creating a closure just costs heap space and adds code for no benefit. /// diff --git a/src/identity_op.rs b/src/identity_op.rs index 093c37783eb..1a62ffb4ae0 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -5,7 +5,7 @@ use syntax::codemap::Span; use consts::{constant_simple, is_negative, Constant}; use utils::{span_lint, snippet, in_macro}; -/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. It is `Warn` by default. +/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. /// /// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly. /// diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 2f061d32546..2aa2fc6da34 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -5,8 +5,7 @@ use syntax::attr::*; use syntax::ast::*; use utils::in_macro; -/// **What it does:** It `Warn`s on blocks where there are items that are declared in the middle of -/// or after the statements +/// **What it does:** This lints checks for items declared after some statement in a block /// /// **Why is this bad?** Items live for the entire scope they are declared in. But statements are /// processed in order. This might cause confusion as it's hard to figure out which item is meant diff --git a/src/len_zero.rs b/src/len_zero.rs index 48fc10ef236..120e880cde6 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -11,7 +11,7 @@ use syntax::ast::Lit; use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; -/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. It is `Warn` by default. +/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. /// /// **Why is this bad?** Some structures can answer `.is_empty()` much faster than calculating their length. So it is good to get into the habit of using `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer than a comparison. /// @@ -24,7 +24,7 @@ declare_lint! { could be used instead" } -/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. It is `Warn` by default. +/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. /// /// **Why is this bad?** It is good custom to have both methods, because for some data structures, asking about the length will be a costly operation, whereas `.is_empty()` can usually answer in constant time. Also it used to lead to false positives on the [`len_zero`](#len_zero) lint – currently that lint will ignore such entities. /// diff --git a/src/lifetimes.rs b/src/lifetimes.rs index f2f33a634bc..f30163f4656 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -8,7 +8,7 @@ use std::collections::{HashSet, HashMap}; use utils::{in_external_macro, span_lint}; -/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. It is `Warn` by default. +/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. /// /// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. /// @@ -22,7 +22,7 @@ declare_lint! { would allow omitting them" } -/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. It is `Warn` by default. +/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. /// /// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. /// diff --git a/src/loops.rs b/src/loops.rs index bfd0e9895e5..4620d6a3e81 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -13,7 +13,7 @@ use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty}; use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; -/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default. +/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. /// /// **Why is this bad?** Just iterating the collection itself makes the intent more clear and is probably faster. /// @@ -31,7 +31,7 @@ declare_lint! { "for-looping over a range of indices where an iterator over items would do" } -/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. It is `Warn` by default. +/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. /// /// **Why is this bad?** Readability. /// @@ -44,7 +44,7 @@ declare_lint! { "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } -/// **What it does:** This lint checks for loops on `x.next()`. It is `Warn` by default. +/// **What it does:** This lint checks for loops on `x.next()`. /// /// **Why is this bad?** `next()` returns either `Some(value)` if there was a value, or `None` otherwise. The insidious thing is that `Option<_>` implements `IntoIterator`, so that possibly one value will be iterated, leading to some hard to find bugs. No one will want to write such code [except to win an Underhanded Rust Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). /// @@ -57,7 +57,7 @@ declare_lint! { "for-looping over `_.next()` which is probably not intended" } -/// **What it does:** This lint checks for `for` loops over `Option` values. It is `Warn` by default. +/// **What it does:** This lint checks for `for` loops over `Option` values. /// /// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. /// @@ -70,7 +70,7 @@ declare_lint! { "for-looping over an `Option`, which is more clearly expressed as an `if let`" } -/// **What it does:** This lint checks for `for` loops over `Result` values. It is `Warn` by default. +/// **What it does:** This lint checks for `for` loops over `Result` values. /// /// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. /// @@ -83,7 +83,7 @@ declare_lint! { "for-looping over a `Result`, which is more clearly expressed as an `if let`" } -/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default. +/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. /// /// **Why is this bad?** The `while let` loop is usually shorter and more readable /// @@ -110,7 +110,7 @@ declare_lint! { "`loop { if let { ... } else break }` can be written as a `while let` loop" } -/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. It is `Warn` by default. +/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. /// /// **Why is this bad?** It is more idiomatic to use a `for` loop over the iterator instead. /// @@ -124,7 +124,7 @@ declare_lint! { written as a for loop" } -/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. It is `Warn` by default. +/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. /// /// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended. /// @@ -137,7 +137,7 @@ declare_lint! { "Iterating over an empty range, such as `10..0` or `5..5`" } -/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. It is `Warn` by default. +/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. /// /// **Why is it bad?** Not only is the version using `.enumerate()` more readable, the compiler is able to remove bounds checks which can lead to faster code in some instances. /// @@ -150,7 +150,7 @@ declare_lint! { "for-looping with an explicit counter when `_.enumerate()` would do" } -/// **What it does:** This lint checks for empty `loop` expressions. It is `Warn` by default. +/// **What it does:** This lint checks for empty `loop` expressions. /// /// **Why is this bad?** Those busy loops burn CPU cycles without doing anything. Think of the environment and either block on something or at least make the thread sleep for some microseconds. /// @@ -163,7 +163,7 @@ declare_lint! { "empty `loop {}` detected" } -/// **What it does:** This lint checks for `while let` expressions on iterators. It is `Warn` by default. +/// **What it does:** This lint checks for `while let` expressions on iterators. /// /// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys the intent better. /// diff --git a/src/map_clone.rs b/src/map_clone.rs index d4773986399..e0255c52fb5 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -4,7 +4,7 @@ use utils::{CLONE_PATH, OPTION_PATH}; use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint}; use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; -/// **What it does:** This lint checks for mapping clone() over an iterator. It is `Warn` by default and suggests to use `.cloned()` instead. +/// **What it does:** This lint checks for mapping clone() over an iterator. /// /// **Why is this bad?** It makes the code less readable. /// diff --git a/src/matches.rs b/src/matches.rs index fb0663117fa..6be5d0bf24f 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -11,7 +11,7 @@ use syntax::codemap::Span; use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; -/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default. +/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. /// /// **Why is this bad?** Just readability – `if let` nests less than a `match`. /// @@ -30,7 +30,7 @@ declare_lint! { is `_ => {}`) is used; recommends `if let` instead" } -/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. It is `Allow` by default. +/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. /// /// **Why is this bad?** Just readability – `if let` nests less than a `match`. /// @@ -49,7 +49,7 @@ declare_lint! { recommends `if let` instead" } -/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. It is `Warn` by default. +/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. /// /// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. /// @@ -70,7 +70,7 @@ declare_lint! { dereferenced instead" } -/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default. +/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. /// /// **Why is this bad?** It makes the code less readable. /// @@ -90,7 +90,7 @@ declare_lint! { "a match on boolean expression; recommends `if..else` block instead" } -/// **What it does:** This lint checks for overlapping match arms. It is `Warn` by default. +/// **What it does:** This lint checks for overlapping match arms. /// /// **Why is this bad?** It is likely to be an error and if not, makes the code less obvious. /// diff --git a/src/methods.rs b/src/methods.rs index 4cd957d0fe7..40d975545e9 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -18,7 +18,7 @@ use rustc::middle::cstore::CrateStore; #[derive(Clone)] pub struct MethodsPass; -/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. It is `Allow` by default. +/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. /// /// **Why is this bad?** Usually it is better to handle the `None` case, or to at least call `.expect(_)` with a more helpful message. Still, for a lot of quick-and-dirty code, `unwrap` is a good choice, which is why this lint is `Allow` by default. /// @@ -30,7 +30,7 @@ declare_lint! { "using `Option.unwrap()`, which should at least get a better message using `expect()`" } -/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. It is `Allow` by default. +/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. /// /// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`. /// @@ -44,7 +44,7 @@ declare_lint! { "using `Result.unwrap()`, which might be better handled" } -/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. It is `Warn` by default. +/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. /// /// **Why is this bad?** This uses the whole formatting machinery just to clone a string. Using `.to_owned()` is lighter on resources. You can also consider using a [`Cow<'a, str>`](http://doc.rust-lang.org/std/borrow/enum.Cow.html) instead in some cases. /// @@ -56,7 +56,7 @@ declare_lint! { "using `to_string()` on a str, which should be `to_owned()`" } -/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default. +/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. /// /// **Why is this bad?** This is an non-efficient way to clone a `String`, `.clone()` should be used /// instead. `String` implements `ToString` mostly for generics. @@ -69,7 +69,7 @@ declare_lint! { "calling `String::to_string` which is inefficient" } -/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default. +/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. /// /// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. /// @@ -87,7 +87,7 @@ declare_lint! { "defining a method that should be implementing a std trait" } -/// **What it does:** This lint checks for methods with certain name prefixes and `Warn`s (by default) if the prefix doesn't match how self is taken. The actual rules are: +/// **What it does:** This lint checks for methods with certain name prefixes and which doesn't match how self is taken. The actual rules are: /// /// |Prefix |`self` taken | /// |-------|--------------------| @@ -97,7 +97,7 @@ declare_lint! { /// |`is_` |`&self` or none | /// |`to_` |`&self` | /// -/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_`.. function. +/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_..` function. /// /// **Known problems:** None /// @@ -114,7 +114,7 @@ declare_lint! { `self` with the wrong convention" } -/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. This lint is `Allow` by default. +/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. /// /// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). /// @@ -132,7 +132,7 @@ declare_lint! { `self` with the wrong convention" } -/// **What it does:** This lint `Warn`s on using `ok().expect(..)`. +/// **What it does:** This lint checks for usage of `ok().expect(..)`. /// /// **Why is this bad?** Because you usually call `expect()` on the `Result` directly to get a good error message. /// @@ -145,7 +145,7 @@ declare_lint! { calling `expect` directly on the Result" } -/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or(_)`. +/// **What it does:** This lint checks for usage of `_.map(_).unwrap_or(_)`. /// /// **Why is this bad?** Readability, this can be written more concisely as `_.map_or(_, _)`. /// @@ -234,7 +234,7 @@ declare_lint! { "using any `*or` method when the `*or_else` would do" } -/// **What it does:** This lint `Warn`s on using `.extend(s)` on a `vec` to extend the vec by a slice. +/// **What it does:** This lint checks for usage of `.extend(s)` on a `Vec` to extend the vector by a slice. /// /// **Why is this bad?** Since Rust 1.6, the `extend_from_slice(_)` method is stable and at least for now faster. /// diff --git a/src/minmax.rs b/src/minmax.rs index 2e199345579..57ec9d91734 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -8,7 +8,7 @@ use consts::{Constant, constant_simple}; use utils::{match_def_path, span_lint}; use self::MinMax::{Min, Max}; -/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. It is `Warn` by default. +/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. /// /// **Why is this bad?** This is in all probability not the intended outcome. At the least it hurts readability of the code. /// diff --git a/src/misc.rs b/src/misc.rs index 099b1797e8e..c0aed78225a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -13,7 +13,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_trait}; -/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default. +/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. /// /// **Why is this bad?** The `ref` declaration makes the function take an owned value, but turns the argument into a reference (which means that the value is destroyed when exiting the function). This adds not much value: either take a reference type, or take an owned value and create references in the body. /// @@ -78,7 +78,7 @@ impl LateLintPass for TopLevelRefPass { } } -/// **What it does:** This lint checks for comparisons to NAN. It is `Deny` by default. +/// **What it does:** This lint checks for comparisons to NAN. /// /// **Why is this bad?** NAN does not compare meaningfully to anything – not even itself – so those comparisons are simply wrong. /// @@ -123,7 +123,7 @@ fn check_nan(cx: &LateContext, path: &Path, span: Span) { }); } -/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). It is `Warn` by default. +/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). /// /// **Why is this bad?** Floating point calculations are usually imprecise, so asking if two values are *exactly* equal is asking for trouble. For a good guide on what to do, see [the floating point guide](http://www.floating-point-gui.de/errors/comparison). /// @@ -189,7 +189,7 @@ fn is_float(cx: &LateContext, expr: &Expr) -> bool { } } -/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. It is `Warn` by default. +/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. /// /// **Why is this bad?** The comparison can operate on a reference, so creating an owned value effectively throws it away directly afterwards, which is needlessly consuming code and heap space. /// @@ -283,7 +283,7 @@ fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { } } -/// **What it does:** This lint checks for getting the remainder of a division by one. It is `Warn` by default. +/// **What it does:** This lint checks for getting the remainder of a division by one. /// /// **Why is this bad?** The result can only ever be zero. No one will write such code deliberately, unless trying to win an Underhanded Rust Contest. Even for that contest, it's probably a bad idea. Use something more underhanded. /// @@ -313,7 +313,7 @@ impl LateLintPass for ModuloOne { } } -/// **What it does:** This lint checks for patterns in the form `name @ _`. It is `Warn` by default. +/// **What it does:** This lint checks for patterns in the form `name @ _`. /// /// **Why is this bad?** It's almost always more readable to just use direct bindings. /// diff --git a/src/misc_early.rs b/src/misc_early.rs index de3c4289353..59a0102aacf 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -8,7 +8,7 @@ use syntax::visit::FnKind; use utils::{span_lint, span_help_and_lint}; -/// **What it does:** This lint `Warn`s on struct field patterns bound to wildcards. +/// **What it does:** This lint checks for structure field patterns bound to wildcards. /// /// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound. /// @@ -20,7 +20,7 @@ declare_lint! { "Struct fields are bound to a wildcard instead of using `..`" } -/// **What it does:** This lint `Warn`s on function arguments having the similar names differing by an underscore +/// **What it does:** This lint checks for function arguments having the similar names differing by an underscore /// /// **Why is this bad?** It affects code readability /// diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 99c1d040fd2..1759a89242b 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -4,7 +4,7 @@ use rustc::middle::ty::{TypeAndMut, TyRef}; use utils::{in_external_macro, span_lint}; -/// **What it does:** This lint checks for instances of `mut mut` references. It is `Warn` by default. +/// **What it does:** This lint checks for instances of `mut mut` references. /// /// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source. /// diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 15e8d310cd6..35904533719 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -4,7 +4,7 @@ use utils::span_lint; use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; use syntax::ptr::P; -/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. It is `Warn` by default. +/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. /// /// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site. /// diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 7b75bd747bb..cf1c347750c 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -11,7 +11,7 @@ use rustc::middle::subst::ParamSpace; use utils::{span_lint, MUTEX_PATH, match_type}; -/// **What it does:** It `Warn`s on usages of `Mutex<X>` where an atomic will do +/// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do. /// /// **Why is this bad?** Using a Mutex just to make access to a plain bool or reference sequential is shooting flies with cannons. `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and faster. /// @@ -24,7 +24,7 @@ declare_lint! { "using a Mutex where an atomic value could be used instead" } -/// **What it does:** It `Warn`s on usages of `Mutex<X>` where `X` is an integral type. +/// **What it does:** This lint checks for usages of `Mutex<X>` where `X` is an integral type. /// /// **Why is this bad?** Using a Mutex just to make access to a plain integer sequential is shooting flies with cannons. `std::atomic::usize` is leaner and faster. /// diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 22edbc272bd..52b3108f6fa 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -9,7 +9,7 @@ use syntax::ast::Lit_::*; use utils::{span_lint, snippet}; -/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. It is `Warn` by default. +/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. /// /// **Why is this bad?** Redundant code. /// diff --git a/src/needless_features.rs b/src/needless_features.rs index 2c293d04600..646ebbbd015 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -8,7 +8,7 @@ use rustc_front::hir::*; use utils::span_lint; use utils; -/// **What it does:** This lint `Warn`s on use of the `as_slice(..)` function, which is unstable. +/// **What it does:** This lint checks for usage of the `as_slice(..)` function, which is unstable. /// /// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. /// @@ -22,7 +22,7 @@ declare_lint! { see https://github.com/rust-lang/rust/issues/27729" } -/// **What it does:** This lint `Warn`s on use of the `as_mut_slice(..)` function, which is unstable. +/// **What it does:** This lint checks for usage of the `as_mut_slice(..)` function, which is unstable. /// /// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. /// diff --git a/src/needless_update.rs b/src/needless_update.rs index 1b306df8eed..d18930c8ccc 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -4,7 +4,7 @@ use rustc_front::hir::{Expr, ExprStruct}; use utils::span_lint; -/// **What it does:** This lint `Warn`s on needlessly including a base struct on update when all fields are changed anyway. +/// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway. /// /// **Why is this bad?** This will cost resources (because the base has to be somewhere), and make the code less readable. /// diff --git a/src/no_effect.rs b/src/no_effect.rs index 075b9b62800..e1067f27ab9 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -6,7 +6,7 @@ use rustc_front::hir::{Stmt, StmtSemi}; use utils::in_macro; use utils::span_lint; -/// **What it does:** This lint `Warn`s on statements which have no effect. +/// **What it does:** This lint checks for statements which have no effect. /// /// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable. /// diff --git a/src/open_options.rs b/src/open_options.rs index 541ed2444f4..a5766604cec 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -4,7 +4,7 @@ use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; use syntax::codemap::{Span, Spanned}; use syntax::ast::Lit_::LitBool; -/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. It is `Warn` by default. +/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. /// /// **Why is this bad?** In the best case, the code will be harder to read than necessary. I don't know the worst case. /// diff --git a/src/panic.rs b/src/panic.rs index dc30f710830..5337942b4e0 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -4,14 +4,14 @@ use syntax::ast::Lit_::LitStr; use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; -/// **What it does:** Warn about missing parameters in `panic!`. +/// **What it does:** This lint checks for missing parameters in `panic!`. /// /// **Known problems:** Should you want to use curly brackets in `panic!` without any parameter, /// this lint will warn. /// /// **Example:** /// ``` -/// panic!("This panic! is probably missing a parameter there: {}"); +/// panic!("This `panic!` is probably missing a parameter there: {}"); /// ``` declare_lint! { pub PANIC_PARAMS, Warn, "missing parameters in `panic!`" diff --git a/src/precedence.rs b/src/precedence.rs index a316f183863..009a79b1673 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use utils::{span_lint, snippet}; -/// **What it does:** This lint checks for operations where precedence may be unclear and `Warn`s about them by default, suggesting to add parentheses. Currently it catches the following: +/// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following: /// * mixed usage of arithmetic and bit shifting/combining operators without parentheses /// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call /// diff --git a/src/print.rs b/src/print.rs index 930952bdbaf..d8f5fd488aa 100644 --- a/src/print.rs +++ b/src/print.rs @@ -2,8 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::{IO_PRINT_PATH, is_expn_of, match_path, span_lint}; -/// **What it does:** This lint warns whenever you print on *stdout*. This lint is `Allow` by -/// default, the purpose is to catch debugging remnants. +/// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants. /// /// **Why is this bad?** People often print on *stdout* while debugging an application and might /// forget to remove those prints afterward. diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 75ce96f6350..707adcfeb07 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -10,7 +10,7 @@ use rustc::middle::ty; use utils::{span_lint, match_type}; use utils::{STRING_PATH, VEC_PATH}; -/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. It is `Warn` by default. +/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. /// /// **Why is this bad?** Requiring the argument to be of the specific size makes the function less useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be obtained from other types, too. /// diff --git a/src/ranges.rs b/src/ranges.rs index 692a5a2da1d..895bd180168 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -3,7 +3,7 @@ use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::{is_integer_literal, match_type, snippet}; -/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. It is `Warn` by default. +/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. /// /// **Why is this bad?** This very much looks like an oversight, since with `loop { .. }` there is an obvious better way to endlessly loop. /// @@ -14,7 +14,7 @@ declare_lint! { pub RANGE_STEP_BY_ZERO, Warn, "using Range::step_by(0), which produces an infinite iterator" } -/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. It is `Warn` by default. +/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. /// /// **Why is this bad?** The code is better expressed with `.enumerate()`. /// diff --git a/src/regex.rs b/src/regex.rs index 259bbb1b64b..81193793a23 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -10,7 +10,7 @@ use rustc::lint::*; use utils::{match_path, REGEX_NEW_PATH, span_lint}; -/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. It is `deny` by default. +/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// /// **Why is this bad?** This will lead to a runtime panic. /// diff --git a/src/returns.rs b/src/returns.rs index 0b0c4d14bdf..3d830e9e372 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -6,7 +6,7 @@ use syntax::visit::FnKind; use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; -/// **What it does:** This lint checks for return statements at the end of a block. It is `Warn` by default. +/// **What it does:** This lint checks for return statements at the end of a block. /// /// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty. /// @@ -18,7 +18,7 @@ declare_lint! { "using a return statement like `return expr;` where an expression would suffice" } -/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. It is `Warn` by default. +/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. /// /// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. /// diff --git a/src/shadow.rs b/src/shadow.rs index f772f97c81e..ff9ea47f065 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -9,7 +9,7 @@ use rustc::middle::def::Def; use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. It is `Allow` by default. +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. /// /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust code. Still, some may opt to avoid it in their code base, they can set this lint to `Warn`. /// @@ -21,7 +21,7 @@ declare_lint! { "rebinding a name to itself, e.g. `let mut x = &mut x`" } -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. It is `Allow` by default. +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. /// /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code. /// @@ -34,7 +34,7 @@ declare_lint! { `let x = x + 1`" } -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. This lint is `Warn` by default. +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. /// /// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings. /// diff --git a/src/strings.rs b/src/strings.rs index 16ee08b1894..f1a1341460e 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -10,7 +10,7 @@ use syntax::codemap::Spanned; use utils::{is_exp_equal, match_type, span_lint, walk_ptrs_ty, get_parent_expr}; use utils::STRING_PATH; -/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). It is `Allow` by default. +/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). /// /// **Why is this bad?** Because this expression needs another copy as opposed to `x.push_str(y)` (in practice LLVM will usually elide it, though). Despite [llogiq](https://github.com/llogiq)'s reservations, this lint also is `allow` by default, as some people opine that it's more readable. /// @@ -28,7 +28,7 @@ declare_lint! { "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" } -/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. It is `Allow` by default. +/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. /// /// **Why is this bad?** It's not bad in and of itself. However, this particular `Add` implementation is asymmetric (the other operand need not be `String`, but `x` does), while addition as mathematically defined is symmetric, also the `String::push_str(_)` function is a perfectly good replacement. Therefore some dislike it and wish not to have it in their code. /// @@ -49,7 +49,7 @@ declare_lint! { } /// **What it does:** This lint matches the `as_bytes` method called on string -/// literals that contain only ascii characters. It is `Warn` by default. +/// literals that contain only ascii characters. /// /// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used instead. They are shorter but less discoverable than `as_bytes()`. /// diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index 7d5057d8377..417ec540856 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -4,9 +4,9 @@ use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTup use utils::is_adjusted; use utils::span_lint; -/// **What it does:** This lint `Warn`s on creating a struct or tuple just to assign a value in it. +/// **What it does:** This lint checks for construction of a structure or tuple just to assign a value in it. /// -/// **Why is this bad?** Readability. If the struct is only created to be updated, why not write the struct you want in the first place? +/// **Why is this bad?** Readability. If the structure is only created to be updated, why not write the structure you want in the first place? /// /// **Known problems:** None. /// diff --git a/src/transmute.rs b/src/transmute.rs index 24af45bc68d..0dd5b60e77a 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use utils; -/// **What it does:** This lint checks for transmutes to the original type of the object. It is `Warn` by default. +/// **What it does:** This lint checks for transmutes to the original type of the object. /// /// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type. /// diff --git a/src/types.rs b/src/types.rs index bb1201547b3..498a084984f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -15,7 +15,7 @@ use utils::*; #[allow(missing_copy_implementations)] pub struct TypePass; -/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. It is `Warn` by default. +/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. /// /// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever. /// @@ -27,7 +27,7 @@ declare_lint! { "usage of `Box<Vec<T>>`, vector elements are already on the heap" } -/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). It is `Warn` by default. +/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). /// /// **Why is this bad?** Gankro says: /// @@ -78,7 +78,7 @@ impl LateLintPass for TypePass { #[allow(missing_copy_implementations)] pub struct LetPass; -/// **What it does:** This lint checks for binding a unit value. It is `Warn` by default. +/// **What it does:** This lint checks for binding a unit value. /// /// **Why is this bad?** A unit value cannot usefully be used anywhere. So binding one is kind of pointless. /// @@ -121,7 +121,7 @@ impl LateLintPass for LetPass { } } -/// **What it does:** This lint checks for comparisons to unit. It is `Warn` by default. +/// **What it does:** This lint checks for comparisons to unit. /// /// **Why is this bad?** Unit is always equal to itself, and thus is just a clumsily written constant. Mostly this happens when someone accidentally adds semicolons at the end of the operands. /// @@ -405,7 +405,7 @@ impl LateLintPass for CastPass { } } -/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. It is `Warn` by default. +/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. /// /// **Why is this bad?** Too complex types make the code less readable. Consider using a `type` definition to simplify them. /// @@ -539,7 +539,7 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { } } -/// **What it does:** This lint points out expressions where a character literal is casted to u8 and suggests using a byte literal instead. +/// **What it does:** This lint points out expressions where a character literal is casted to `u8` and suggests using a byte literal instead. /// /// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`. /// diff --git a/src/unicode.rs b/src/unicode.rs index 92d365f0323..63ffe219d9b 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -8,7 +8,7 @@ use unicode_normalization::UnicodeNormalization; use utils::{snippet, span_help_and_lint}; -/// **What it does:** This lint checks for the unicode zero-width space in the code. It is `Warn` by default. +/// **What it does:** This lint checks for the unicode zero-width space in the code. /// /// **Why is this bad?** Having an invisible character in the code makes for all sorts of April fools, but otherwise is very much frowned upon. /// @@ -20,7 +20,7 @@ declare_lint! { "using a zero-width space in a string literal, which is confusing" } -/// **What it does:** This lint checks for non-ascii characters in string literals. It is `Allow` by default. +/// **What it does:** This lint checks for non-ascii characters in string literals. /// /// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful. /// @@ -33,7 +33,7 @@ declare_lint! { using the \\u escape instead" } -/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). This lint is `Allow` by default. +/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). /// /// **Why is this bad?** If such a string is compared to another, the results may be surprising. /// diff --git a/src/vec.rs b/src/vec.rs index 41a477c34ff..fe3c1f90199 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -7,7 +7,6 @@ use utils::{BOX_NEW_PATH, VEC_FROM_ELEM_PATH}; use utils::{is_expn_of, match_path, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. -/// It is `Warn` by default. /// /// **Why is this bad?** This is less efficient. /// diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 9c5c07cd678..1576d699a4a 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -4,12 +4,12 @@ use rustc_front::hir::*; use utils::span_help_and_lint; use consts::{Constant, constant_simple, FloatWidth}; -/// ZeroDivZeroPass is a pass that checks for a binary expression that consists -/// of 0.0/0.0, which is always NaN. It is more clear to replace instances of -/// 0.0/0.0 with std::f32::NaN or std::f64::NaN, depending on the precision. +/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists +/// `of 0.0/0.0`, which is always NaN. It is more clear to replace instances of +/// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. pub struct ZeroDivZeroPass; -/// **What it does:** This lint checks for `0.0 / 0.0`. It is `Warn` by default. +/// **What it does:** This lint checks for `0.0 / 0.0`. /// /// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN` /// -- cgit 1.4.1-3-g733a5 From f2a7c8cca03aa817ff10654af6821cfd92746b1a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 00:42:55 +0100 Subject: Update `update_wiki.py` to extract default lint level --- util/update_wiki.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index 842f0ed6d8e..990b8860c01 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -8,6 +8,9 @@ import re import sys +level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''') + + def parse_path(p="src"): d = {} for f in os.listdir(p): @@ -38,9 +41,20 @@ def parse_file(d, f): if not comment: l = line.strip() m = re.search(r"pub\s+([A-Z_]+)", l) + if m: - print("found %s in %s" % (m.group(1).lower(), f)) - d[m.group(1).lower()] = last_comment + name = m.group(1).lower() + + while True: + m = re.search(level_re, line) + if m: + level = m.group(0) + break + + line = next(rs) + + print("found %s with level %s in %s" % (name, level, f)) + d[name] = (level, last_comment) last_comment = [] comment = True if "}" in l: @@ -51,7 +65,6 @@ PREFIX = """Welcome to the rust-clippy wiki! Here we aim to collect further explanations on the lints clippy provides. So \ without further ado: - """ WARNING = """ @@ -61,7 +74,16 @@ Clippy works as a *plugin* to the compiler, which means using an unstable \ internal API. We have gotten quite good at keeping pace with the API \ evolution, but the consequence is that clippy absolutely needs to be compiled \ with the version of `rustc` it will run on, otherwise you will get strange \ -errors of missing symbols.""" +errors of missing symbols. + +""" + + +template = """# `%s` + +**Default level:** %s + +%s""" def write_wiki_page(d, f): @@ -69,11 +91,16 @@ def write_wiki_page(d, f): keys.sort() with open(f, "w") as w: w.write(PREFIX) - for k in keys: - w.write("[`%s`](#%s)\n" % (k, k)) + + for level in ('Deny', 'Warn', 'Allow'): + w.write("\n**Those lints are %s by default**:\n\n" % level) + for k in keys: + if d[k][0] == level: + w.write("[`%s`](#%s)\n" % (k, k)) + w.write(WARNING) for k in keys: - w.write("\n# `%s`\n\n%s" % (k, "".join(d[k]))) + w.write(template % (k, d[k][0], "".join(d[k][1]))) def check_wiki_page(d, f): -- cgit 1.4.1-3-g733a5 From d9a2a7ac3c992f6093babb7770acfaac3a08833f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 18:06:39 +0100 Subject: Fix false negative in TRIVIAL_REGEX --- src/regex.rs | 96 ++++++++++++++++++++++++++------------------- tests/compile-fail/regex.rs | 9 +++++ 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/regex.rs b/src/regex.rs index 76412f17880..cf19c764361 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -55,32 +55,40 @@ impl LateLintPass for RegexPass { ], { if let ExprLit(ref lit) = args[0].node { if let LitStr(ref r, _) = lit.node { - if let Err(e) = regex_syntax::Expr::parse(r) { + match regex_syntax::Expr::parse(r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, + &"trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { + span_lint(cx, + INVALID_REGEX, + str_span(args[0].span, &r, e.position()), + &format!("regex syntax error: {}", + e.description())); + } + } + } + } else if let Some(r) = const_str(cx, &*args[0]) { + match regex_syntax::Expr::parse(&r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, + &"trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { span_lint(cx, INVALID_REGEX, - str_span(args[0].span, &r, e.position()), - &format!("regex syntax error: {}", + args[0].span, + &format!("regex syntax error on position {}: {}", + e.position(), e.description())); } - else if let Some(repl) = is_trivial_regex(r) { - span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - &"trivial regex", - &format!("consider using {}", repl)); - } - } - } else if let Some(r) = const_str(cx, &*args[0]) { - if let Err(e) = regex_syntax::Expr::parse(&r) { - span_lint(cx, - INVALID_REGEX, - args[0].span, - &format!("regex syntax error on position {}: {}", - e.position(), - e.description())); - } - else if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - &"trivial regex", - &format!("{}", repl)); } } }} @@ -103,25 +111,31 @@ fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { } } -fn is_trivial_regex(s: &str) -> Option<&'static str> { - // some unlikely but valid corner cases - match s { - "" | "^" | "$" => return Some("the regex is unlikely to be useful as it is"), - "^$" => return Some("consider using `str::is_empty`"), - _ => (), - } - - let (start, end, repl) = match (s.starts_with('^'), s.ends_with('$')) { - (true, true) => (1, s.len()-1, "consider using `==` on `str`s"), - (false, true) => (0, s.len()-1, "consider using `str::ends_with`"), - (true, false) => (1, s.len(), "consider using `str::starts_with`"), - (false, false) => (0, s.len(), "consider using `str::contains`"), - }; +fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { + use regex_syntax::Expr; - if !s.chars().take(end).skip(start).any(regex_syntax::is_punct) { - Some(repl) - } - else { - None + match *s { + Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), + Expr::Literal {..} => Some("consider using `str::contains`"), + Expr::Concat(ref exprs) => { + match exprs.len() { + 2 => match (&exprs[0], &exprs[1]) { + (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), + (&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"), + (&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"), + _ => None, + }, + 3 => { + if let (&Expr::StartText, &Expr::Literal {..}, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { + Some("consider using `==` on `str`s") + } + else { + None + } + }, + _ => None, + } + } + _ => None, } } diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index cd10d47c1bb..2e8228a823d 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -45,16 +45,25 @@ fn trivial_regex() { //~^ERROR: trivial regex //~|HELP consider using `str::contains` + let trivial_backslash = Regex::new("a\\.b"); + //~^ERROR: trivial regex + //~|HELP consider using `str::contains` + // unlikely corner cases let trivial_empty = Regex::new(""); //~^ERROR: trivial regex //~|HELP the regex is unlikely to be useful + let trivial_empty = Regex::new("^"); + //~^ERROR: trivial regex + //~|HELP the regex is unlikely to be useful + let trivial_empty = Regex::new("^$"); //~^ERROR: trivial regex //~|HELP consider using `str::is_empty` // non-trivial regexes + let non_trivial_dot = Regex::new("a.b"); let non_trivial_eq = Regex::new("^foo|bar$"); let non_trivial_starts_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("^foo|bar"); -- cgit 1.4.1-3-g733a5 From fe6f2a22ba48f8187ed69cd3d479d7a0dfa3b432 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 18:03:53 +0100 Subject: Lint about consecutive ifs with same condition --- README.md | 1 + src/copies.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/utils.rs | 24 +++++++++++++++- tests/compile-fail/copies.rs | 31 ++++++++++++++++++++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/copies.rs create mode 100755 tests/compile-fail/copies.rs diff --git a/README.md b/README.md index 20aaa03c51c..93921f01f6e 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ name [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations diff --git a/src/copies.rs b/src/copies.rs new file mode 100644 index 00000000000..33461a29670 --- /dev/null +++ b/src/copies.rs @@ -0,0 +1,68 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::{get_parent_expr, is_exp_equal, span_lint}; + +/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is +/// `Warn` by default. +/// +/// **Why is this bad?** This is probably a copy & paste error. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** `if a == b { .. } else if a == b { .. }` +declare_lint! { + pub IFS_SAME_COND, + Warn, + "consecutive `ifs` with the same condition" +} + +#[derive(Copy, Clone, Debug)] +pub struct CopyAndPaste; + +impl LintPass for CopyAndPaste { + fn get_lints(&self) -> LintArray { + lint_array![ + IFS_SAME_COND + ] + } +} + +impl LateLintPass for CopyAndPaste { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // skip ifs directly in else, it will be checked in the parent if + if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { + if else_expr.id == expr.id { + return; + } + } + + let conds = condition_sequence(expr); + + for (n, i) in conds.iter().enumerate() { + for j in conds.iter().skip(n+1) { + if is_exp_equal(cx, i, j) { + span_lint(cx, IFS_SAME_COND, j.span, "this if as the same condition as a previous if"); + } + } + } + } +} + +/// Return the list of conditions expression in a sequence of `if/else`. +/// Eg. would return `[a, b]` for the expression `if a {..} else if b {..}`. +fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> { + let mut result = vec![]; + + while let ExprIf(ref cond, _, ref else_expr) = expr.node { + result.push(&**cond); + + if let Some(ref else_expr) = *else_expr { + expr = else_expr; + } + else { + break; + } + } + + result +} diff --git a/src/lib.rs b/src/lib.rs index fa98beb8d74..6b2a43db795 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ use rustc_plugin::Registry; #[macro_use] pub mod utils; +pub mod copies; pub mod consts; pub mod types; pub mod misc; @@ -157,6 +158,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdUnsignedComparisons); reg.register_late_lint_pass(box regex::RegexPass); + reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -190,6 +192,7 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, + copies::IFS_SAME_COND, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_NOT_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, diff --git a/src/utils.rs b/src/utils.rs index 74c1de6976f..72c6fe94ce2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -596,16 +596,38 @@ pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr) -> bool { } } match (&left.node, &right.node) { + (&ExprAddrOf(ref lmut, ref le), &ExprAddrOf(ref rmut, ref re)) => { + lmut == rmut && is_exp_equal(cx, le, re) + } + (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { + lop.node == rop.node && is_exp_equal(cx, ll, rl) && is_exp_equal(cx, lr, rr) + } + (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { + is_exp_equal(cx, lfun, rfun) && is_exps_equal(cx, largs, rargs) + } + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp) } + (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { + is_exp_equal(cx, la, ra) && is_exp_equal(cx, li, ri) + } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { + // TODO: tys + lname.node == rname.node && ltys.is_empty() && rtys.is_empty() && is_exps_equal(cx, largs, rargs) + } (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { both(lqself, rqself, is_qself_equal) && is_path_equal(lsubpath, rsubpath) } (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup), + (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => { + li.node == ri.node && is_exp_equal(cx, le, re) + } + (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => { + lop == rop && is_exp_equal(cx, le, re) + } (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), _ => false, } } diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs new file mode 100755 index 00000000000..a29fd392c5e --- /dev/null +++ b/tests/compile-fail/copies.rs @@ -0,0 +1,31 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(clippy)] + +fn foo() -> bool { unimplemented!() } + +fn main() { + let a = 0; + + if a == 1 { + } + else if a == 1 { //~ERROR this if as the same condition as a previous if + } + + if 2*a == 1 { + } + else if 2*a == 2 { + } + else if 2*a == 1 { //~ERROR this if as the same condition as a previous if + } + else if a == 1 { + } + + // Ok, maybe `foo` isn’t pure and this actually makes sense. But you should probably refactor + // this to make the intention clearer anyway. + if foo() { + } + else if foo() { //~ERROR this if as the same condition as a previous if + } +} -- cgit 1.4.1-3-g733a5 From d862495d191dc432e92015a724780477f743152e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 19:16:49 +0100 Subject: Lint ifs with the same then and else blocks --- README.md | 1 + src/copies.rs | 72 ++++++++++++++++++++++++++++++------- src/lib.rs | 1 + src/utils.rs | 10 +++++- tests/compile-fail/copies.rs | 48 ++++++++++++++++++++++--- tests/compile-fail/needless_bool.rs | 1 + 6 files changed, 115 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 93921f01f6e..01999cce70b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ name [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks [ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases diff --git a/src/copies.rs b/src/copies.rs index 33461a29670..f8fe09c3133 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{get_parent_expr, is_exp_equal, span_lint}; +use utils::{get_parent_expr, in_macro, is_exp_equal, is_stmt_equal, over, span_lint, span_note_and_lint}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is /// `Warn` by default. @@ -16,33 +16,79 @@ declare_lint! { "consecutive `ifs` with the same condition" } +/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the +/// *else* part. This lint is `Warn` by default. +/// +/// **Why is this bad?** This is probably a copy & paste error. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** `if .. { 42 } else { 42 }` +declare_lint! { + pub IF_SAME_THEN_ELSE, + Warn, + "if with the same *then* and *else* blocks" +} + #[derive(Copy, Clone, Debug)] pub struct CopyAndPaste; impl LintPass for CopyAndPaste { fn get_lints(&self) -> LintArray { lint_array![ - IFS_SAME_COND + IFS_SAME_COND, + IF_SAME_THEN_ELSE ] } } impl LateLintPass for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { - if else_expr.id == expr.id { - return; - } + if !in_macro(cx, expr.span) { + lint_same_then_else(cx, expr); + lint_same_cond(cx, expr); } + } +} - let conds = condition_sequence(expr); - - for (n, i) in conds.iter().enumerate() { - for j in conds.iter().skip(n+1) { - if is_exp_equal(cx, i, j) { - span_lint(cx, IFS_SAME_COND, j.span, "this if as the same condition as a previous if"); +/// Implementation of `IF_SAME_THEN_ELSE`. +fn lint_same_then_else(cx: &LateContext, expr: &Expr) { + if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node { + let must_lint = if let ExprBlock(ref else_block) = else_expr.node { + over(&then_block.stmts, &else_block.stmts, |l, r| is_stmt_equal(cx, l, r)) && + match (&then_block.expr, &else_block.expr) { + (&Some(ref then_expr), &Some(ref else_expr)) => { + is_exp_equal(cx, &then_expr, &else_expr) + } + (&None, &None) => true, + _ => false, } + } + else { + false + }; + + if must_lint { + span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks"); + } + } +} + +/// Implementation of `IFS_SAME_COND`. +fn lint_same_cond(cx: &LateContext, expr: &Expr) { + // skip ifs directly in else, it will be checked in the parent if + if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { + if else_expr.id == expr.id { + return; + } + } + + let conds = condition_sequence(expr); + + for (n, i) in conds.iter().enumerate() { + for j in conds.iter().skip(n+1) { + if is_exp_equal(cx, i, j) { + span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); } } } diff --git a/src/lib.rs b/src/lib.rs index 6b2a43db795..35ec0e13c3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -192,6 +192,7 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, + copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_NOT_EQ, diff --git a/src/utils.rs b/src/utils.rs index 72c6fe94ce2..13fd849993f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -589,6 +589,14 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } } +pub fn is_stmt_equal(cx: &LateContext, left: &Stmt, right: &Stmt) -> bool { + match (&left.node, &right.node) { + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => is_exp_equal(cx, l, r), + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => is_exp_equal(cx, l, r), + _ => false, + } +} + pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr) -> bool { if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { if l == r { @@ -649,7 +657,7 @@ fn is_qself_equal(left: &QSelf, right: &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } -fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool +pub fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index a29fd392c5e..94c5c620f34 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -1,23 +1,61 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(dead_code)] #![deny(clippy)] fn foo() -> bool { unimplemented!() } -fn main() { +fn if_same_then_else() { + if true { //~ERROR this if has the same then and else blocks + foo(); + } + else { + foo(); + } + + if true { + foo(); + foo(); + } + else { + foo(); + } + + let _ = if true { //~ERROR this if has the same then and else blocks + foo(); + 42 + } + else { + foo(); + 42 + }; + + if true { + foo(); + } + + let _ = if true { //~ERROR this if has the same then and else blocks + 42 + } + else { + 42 + }; +} + +fn ifs_same_cond() { let a = 0; if a == 1 { } - else if a == 1 { //~ERROR this if as the same condition as a previous if + else if a == 1 { //~ERROR this if has the same condition as a previous if } if 2*a == 1 { } else if 2*a == 2 { } - else if 2*a == 1 { //~ERROR this if as the same condition as a previous if + else if 2*a == 1 { //~ERROR this if has the same condition as a previous if } else if a == 1 { } @@ -26,6 +64,8 @@ fn main() { // this to make the intention clearer anyway. if foo() { } - else if foo() { //~ERROR this if as the same condition as a previous if + else if foo() { //~ERROR this if has the same condition as a previous if } } + +fn main() {} diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index 39fdf6353fd..c2ad24bc4ee 100644 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] +#[allow(if_same_then_else)] #[deny(needless_bool)] fn main() { let x = true; -- cgit 1.4.1-3-g733a5 From 8e22d08129dc242cebcdb25b824fa4ffb57d4f7a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 20:10:14 +0100 Subject: Improve is_exp_equal --- src/copies.rs | 13 +--- src/entry.rs | 2 +- src/eq_op.rs | 2 +- src/strings.rs | 4 +- src/utils.rs | 164 ++++++++++++++++++++++++++++++++++++++----- tests/compile-fail/copies.rs | 76 ++++++++++++++++++-- tests/compile-fail/eq_op.rs | 5 ++ 7 files changed, 227 insertions(+), 39 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index f8fe09c3133..38f1be92d30 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{get_parent_expr, in_macro, is_exp_equal, is_stmt_equal, over, span_lint, span_note_and_lint}; +use utils::{get_parent_expr, in_macro, is_block_equal, is_exp_equal, span_lint, span_note_and_lint}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is /// `Warn` by default. @@ -55,14 +55,7 @@ impl LateLintPass for CopyAndPaste { fn lint_same_then_else(cx: &LateContext, expr: &Expr) { if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node { let must_lint = if let ExprBlock(ref else_block) = else_expr.node { - over(&then_block.stmts, &else_block.stmts, |l, r| is_stmt_equal(cx, l, r)) && - match (&then_block.expr, &else_block.expr) { - (&Some(ref then_expr), &Some(ref else_expr)) => { - is_exp_equal(cx, &then_expr, &else_expr) - } - (&None, &None) => true, - _ => false, - } + is_block_equal(cx, &then_block, &else_block, false) } else { false @@ -87,7 +80,7 @@ fn lint_same_cond(cx: &LateContext, expr: &Expr) { for (n, i) in conds.iter().enumerate() { for j in conds.iter().skip(n+1) { - if is_exp_equal(cx, i, j) { + if is_exp_equal(cx, i, j, true) { span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); } } diff --git a/src/entry.rs b/src/entry.rs index 64d6fa7be38..d5bb086fc21 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -89,7 +89,7 @@ fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: params.len() == 3, name.node.as_str() == "insert", get_item_name(cx, map) == get_item_name(cx, &*params[0]), - is_exp_equal(cx, key, ¶ms[1]) + is_exp_equal(cx, key, ¶ms[1], false) ], { let help = if sole_expr { format!("{}.entry({}).or_insert({})", diff --git a/src/eq_op.rs b/src/eq_op.rs index 49037cd9ae7..06e4fdc6cb7 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -29,7 +29,7 @@ impl LintPass for EqOp { impl LateLintPass for EqOp { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) { + if is_cmp_or_bit(op) && is_exp_equal(cx, left, right, true) { span_lint(cx, EQ_OP, e.span, diff --git a/src/strings.rs b/src/strings.rs index f1a1341460e..b78db7f4b77 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -84,7 +84,7 @@ impl LateLintPass for StringAdd { if let Some(ref p) = parent { if let ExprAssign(ref target, _) = p.node { // avoid duplicate matches - if is_exp_equal(cx, target, left) { + if is_exp_equal(cx, target, left, false) { return; } } @@ -113,7 +113,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left), + ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left, false), ExprBlock(ref block) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) } diff --git a/src/utils.rs b/src/utils.rs index 13fd849993f..a8890f31cb0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -589,59 +589,183 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } } -pub fn is_stmt_equal(cx: &LateContext, left: &Stmt, right: &Stmt) -> bool { +/// Check whether two statements are the same. +/// See also `is_exp_equal`. +pub fn is_stmt_equal(cx: &LateContext, left: &Stmt, right: &Stmt, ignore_fn: bool) -> bool { match (&left.node, &right.node) { - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => is_exp_equal(cx, l, r), - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => is_exp_equal(cx, l, r), + (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { + if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { + // TODO: tys + l.ty.is_none() && r.ty.is_none() && + both(&l.init, &r.init, |l, r| is_exp_equal(cx, l, r, ignore_fn)) + } + else { + false + } + } + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => is_exp_equal(cx, l, r, ignore_fn), + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => is_exp_equal(cx, l, r, ignore_fn), + _ => false, + } +} + +/// Check whether two blocks are the same. +/// See also `is_exp_equal`. +pub fn is_block_equal(cx: &LateContext, left: &Block, right: &Block, ignore_fn: bool) -> bool { + over(&left.stmts, &right.stmts, |l, r| is_stmt_equal(cx, l, r, ignore_fn)) && + both(&left.expr, &right.expr, |l, r| is_exp_equal(cx, l, r, ignore_fn)) +} + +/// Check whether two pattern are the same. +/// See also `is_exp_equal`. +pub fn is_pat_equal(cx: &LateContext, left: &Pat, right: &Pat, ignore_fn: bool) -> bool { + match (&left.node, &right.node) { + (&PatBox(ref l), &PatBox(ref r)) => { + is_pat_equal(cx, l, r, ignore_fn) + } + (&PatEnum(ref lp, ref la), &PatEnum(ref rp, ref ra)) => { + is_path_equal(lp, rp) && + both(la, ra, |l, r| { + over(l, r, |l, r| is_pat_equal(cx, l, r, ignore_fn)) + }) + } + (&PatIdent(ref lb, ref li, ref lp), &PatIdent(ref rb, ref ri, ref rp)) => { + lb == rb && li.node.name.as_str() == ri.node.name.as_str() && + both(lp, rp, |l, r| is_pat_equal(cx, l, r, ignore_fn)) + } + (&PatLit(ref l), &PatLit(ref r)) => { + is_exp_equal(cx, l, r, ignore_fn) + } + (&PatQPath(ref ls, ref lp), &PatQPath(ref rs, ref rp)) => { + is_qself_equal(ls, rs) && is_path_equal(lp, rp) + } + (&PatTup(ref l), &PatTup(ref r)) => { + over(l, r, |l, r| is_pat_equal(cx, l, r, ignore_fn)) + } + (&PatRange(ref ls, ref le), &PatRange(ref rs, ref re)) => { + is_exp_equal(cx, ls, rs, ignore_fn) && + is_exp_equal(cx, le, re, ignore_fn) + } + (&PatRegion(ref le, ref lm), &PatRegion(ref re, ref rm)) => { + lm == rm && is_pat_equal(cx, le, re, ignore_fn) + } + (&PatVec(ref ls, ref li, ref le), &PatVec(ref rs, ref ri, ref re)) => { + over(ls, rs, |l, r| is_pat_equal(cx, l, r, ignore_fn)) && + over(le, re, |l, r| is_pat_equal(cx, l, r, ignore_fn)) && + both(li, ri, |l, r| is_pat_equal(cx, l, r, ignore_fn)) + } + (&PatWild, &PatWild) => true, _ => false, } } -pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr) -> bool { +/// Check whether two expressions are the same. This is different from the operator `==` on +/// expression as this operator would compare true equality with ID and span. +/// If `ignore_fn` is true, never consider as equal fonction calls. +/// +/// Note that some expression kinds are not considered but could be added. +#[allow(cyclomatic_complexity)] // ok, it’s a big function, but mostly one big match with simples cases +pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr, ignore_fn: bool) -> bool { if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { if l == r { return true; } } + match (&left.node, &right.node) { (&ExprAddrOf(ref lmut, ref le), &ExprAddrOf(ref rmut, ref re)) => { - lmut == rmut && is_exp_equal(cx, le, re) + lmut == rmut && is_exp_equal(cx, le, re, ignore_fn) + } + (&ExprAgain(li), &ExprAgain(ri)) => { + both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) + } + (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => { + is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) + } + (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { + lo.node == ro.node && is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) + } + (&ExprBlock(ref l), &ExprBlock(ref r)) => { + is_block_equal(cx, l, r, ignore_fn) } (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { - lop.node == rop.node && is_exp_equal(cx, ll, rl) && is_exp_equal(cx, lr, rr) + lop.node == rop.node && is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) + } + (&ExprBreak(li), &ExprBreak(ri)) => { + both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) + } + (&ExprBox(ref l), &ExprBox(ref r)) => { + is_exp_equal(cx, l, r, ignore_fn) } (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { - is_exp_equal(cx, lfun, rfun) && is_exps_equal(cx, largs, rargs) + !ignore_fn && + is_exp_equal(cx, lfun, rfun, ignore_fn) && + is_exps_equal(cx, largs, rargs, ignore_fn) + } + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => { + is_exp_equal(cx, lx, rx, ignore_fn) && is_cast_ty_equal(lt, rt) } - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { - lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp) + lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp, ignore_fn) } (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { - is_exp_equal(cx, la, ra) && is_exp_equal(cx, li, ri) + is_exp_equal(cx, la, ra, ignore_fn) && is_exp_equal(cx, li, ri, ignore_fn) + } + (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { + is_exp_equal(cx, lc, rc, ignore_fn) && + is_block_equal(cx, lt, rt, ignore_fn) && + both(le, re, |l, r| is_exp_equal(cx, l, r, ignore_fn)) } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { + ls == rs && + is_exp_equal(cx, le, re, ignore_fn) && + over(la, ra, |l, r| { + is_exp_equal(cx, &l.body, &r.body, ignore_fn) && + both(&l.guard, &r.guard, |l, r| is_exp_equal(cx, l, r, ignore_fn)) && + over(&l.pats, &r.pats, |l, r| is_pat_equal(cx, l, r, ignore_fn)) + }) + } (&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { // TODO: tys - lname.node == rname.node && ltys.is_empty() && rtys.is_empty() && is_exps_equal(cx, largs, rargs) + !ignore_fn && + lname.node == rname.node && + ltys.is_empty() && + rtys.is_empty() && + is_exps_equal(cx, largs, rargs, ignore_fn) + } + (&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => { + both(lb, rb, |l, r| is_exp_equal(cx, l, r, ignore_fn)) && + both(le, re, |l, r| is_exp_equal(cx, l, r, ignore_fn)) + } + (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => { + is_exp_equal(cx, le, re, ignore_fn) && is_exp_equal(cx, ll, rl, ignore_fn) + } + (&ExprRet(ref l), &ExprRet(ref r)) => { + both(l, r, |l, r| is_exp_equal(cx, l, r, ignore_fn)) } (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { both(lqself, rqself, is_qself_equal) && is_path_equal(lsubpath, rsubpath) } - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup, ignore_fn), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => { - li.node == ri.node && is_exp_equal(cx, le, re) + li.node == ri.node && is_exp_equal(cx, le, re, ignore_fn) } (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => { - lop == rop && is_exp_equal(cx, le, re) + lop == rop && is_exp_equal(cx, le, re, ignore_fn) + } + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r, ignore_fn), + (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { + is_exp_equal(cx, lc, rc, ignore_fn) && + is_block_equal(cx, lb, rb, ignore_fn) && + both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) } - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), _ => false, } } -fn is_exps_equal(cx: &LateContext, left: &[P<Expr>], right: &[P<Expr>]) -> bool { - over(left, right, |l, r| is_exp_equal(cx, l, r)) +fn is_exps_equal(cx: &LateContext, left: &[P<Expr>], right: &[P<Expr>], ignore_fn: bool) -> bool { + over(left, right, |l, r| is_exp_equal(cx, l, r, ignore_fn)) } fn is_path_equal(left: &Path, right: &Path) -> bool { @@ -650,20 +774,22 @@ fn is_path_equal(left: &Path, right: &Path) -> bool { left.global == right.global && over(&left.segments, &right.segments, - |l, r| l.identifier.name == r.identifier.name && l.parameters == r.parameters) + |l, r| l.identifier.name.as_str() == r.identifier.name.as_str() && l.parameters == r.parameters) } fn is_qself_equal(left: &QSelf, right: &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } +/// Check if two slices are equal as per `eq_fn`. pub fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool +/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. +pub fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 94c5c620f34..0f57b619ccc 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -2,11 +2,15 @@ #![plugin(clippy)] #![allow(dead_code)] -#![deny(clippy)] +#![allow(let_and_return)] +#![allow(needless_return)] +#![allow(unused_variables)] +#![deny(if_same_then_else)] +#![deny(ifs_same_cond)] fn foo() -> bool { unimplemented!() } -fn if_same_then_else() { +fn if_same_then_else() -> &'static str { if true { //~ERROR this if has the same then and else blocks foo(); } @@ -41,6 +45,62 @@ fn if_same_then_else() { else { 42 }; + + if true { //~ERROR this if has the same then and else blocks + let bar = if true { + 42 + } + else { + 43 + }; + + while foo() { break; } + bar + 1; + } + else { + let bar = if true { + 42 + } + else { + 43 + }; + + while foo() { break; } + bar + 1; + } + + if true { //~ERROR this if has the same then and else blocks + match 42 { + 42 => (), + a if a > 0 => (), + 10...15 => (), + _ => (), + } + } + else { + match 42 { + 42 => (), + a if a > 0 => (), + 10...15 => (), + _ => (), + } + } + + if true { //~ERROR this if has the same then and else blocks + if let Some(a) = Some(42) {} + } + else { + if let Some(a) = Some(42) {} + } + + if true { //~ERROR this if has the same then and else blocks + let foo = ""; + return &foo[0..]; + } + else { + let foo = ""; + return &foo[0..]; + } } fn ifs_same_cond() { @@ -60,11 +120,15 @@ fn ifs_same_cond() { else if a == 1 { } - // Ok, maybe `foo` isn’t pure and this actually makes sense. But you should probably refactor - // this to make the intention clearer anyway. - if foo() { + let mut v = vec![1]; + if v.pop() == None { // ok, functions + } + else if v.pop() == None { + } + + if v.len() == 42 { // ok, functions } - else if foo() { //~ERROR this if has the same condition as a previous if + else if v.len() == 42 { } } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index fc59c2739a2..fe74d182da1 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -32,4 +32,9 @@ fn main() { // const folding 1 + 1 == 2; //~ERROR equal expressions 1 - 1 == 0; //~ERROR equal expressions + + let mut a = vec![1]; + a == a; //~ERROR equal expressions + 2*a.len() == 2*a.len(); // ok, functions + a.pop() == a.pop(); // ok, functions } -- cgit 1.4.1-3-g733a5 From cd7a9132001e0a6de7ee2f7420c63bdf98ca6eff Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 3 Feb 2016 20:42:05 +0100 Subject: Add `-` and `/` to EQ_OP --- src/eq_op.rs | 14 +++++++++----- tests/compile-fail/eq_op.rs | 14 ++++++++++---- tests/compile-fail/identity_op.rs | 1 + tests/compile-fail/zero_div_zero.rs | 4 ++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 06e4fdc6cb7..aecd0693ff1 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -4,9 +4,11 @@ use rustc_front::util as ast_util; use utils::{is_exp_equal, span_lint}; -/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). +/// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, +/// difference and division binary operators (`==`, `>`, etc., `&&`, `||`, `&`, `|`, `^`, `-` and +/// `/`). /// -/// **Why is this bad?** This is usually just a typo. +/// **Why is this bad?** This is usually just a typo or a copy and paste error. /// /// **Known problems:** False negatives: We had some false positives regarding calls (notably [racer](https://github.com/phildawes/racer) had one instance of `x.pop() && x.pop()`), so we removed matching any function or method calls. We may introduce a whitelist of known pure functions in the future. /// @@ -29,19 +31,21 @@ impl LintPass for EqOp { impl LateLintPass for EqOp { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_cmp_or_bit(op) && is_exp_equal(cx, left, right, true) { + if is_valid_operator(op) && is_exp_equal(cx, left, right, true) { span_lint(cx, EQ_OP, e.span, - &format!("equal expressions as operands to {}", ast_util::binop_to_string(op.node))); + &format!("equal expressions as operands to `{}`", ast_util::binop_to_string(op.node))); } } } } -fn is_cmp_or_bit(op: &BinOp) -> bool { +fn is_valid_operator(op: &BinOp) -> bool { match op.node { + BiSub | + BiDiv | BiEq | BiLt | BiLe | diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index fe74d182da1..7be5ef11ce6 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -19,9 +19,9 @@ fn main() { // unary and binary operators (-(2) < -(2)); //~ERROR equal expressions ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); - //~^ ERROR equal expressions - //~^^ ERROR equal expressions - //~^^^ ERROR equal expressions + //~^ ERROR equal expressions as operands to `==` + //~^^ ERROR equal expressions as operands to `&` + //~^^^ ERROR equal expressions as operands to `&` (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR equal expressions // various other things @@ -31,7 +31,13 @@ fn main() { // const folding 1 + 1 == 2; //~ERROR equal expressions - 1 - 1 == 0; //~ERROR equal expressions + 1 - 1 == 0; //~ERROR equal expressions as operands to `==` + //~^ ERROR equal expressions as operands to `-` + + 1 - 1; //~ERROR equal expressions + 1 / 1; //~ERROR equal expressions + true && true; //~ERROR equal expressions + true || true; //~ERROR equal expressions let mut a = vec![1]; a == a; //~ERROR equal expressions diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index 54551852d5e..c1141e0b460 100644 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -5,6 +5,7 @@ const ONE : i64 = 1; const NEG_ONE : i64 = -1; const ZERO : i64 = 0; +#[allow(eq_op)] #[deny(identity_op)] fn main() { let x = 0; diff --git a/tests/compile-fail/zero_div_zero.rs b/tests/compile-fail/zero_div_zero.rs index 8c40923d3ed..c422e83873b 100644 --- a/tests/compile-fail/zero_div_zero.rs +++ b/tests/compile-fail/zero_div_zero.rs @@ -5,9 +5,13 @@ #[deny(zero_divided_by_zero)] fn main() { let nan = 0.0 / 0.0; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + //~^ equal expressions as operands to `/` let f64_nan = 0.0 / 0.0f64; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + //~^ equal expressions as operands to `/` let other_f64_nan = 0.0f64 / 0.0; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + //~^ equal expressions as operands to `/` let one_more_f64_nan = 0.0f64/0.0f64; //~ERROR constant division of 0.0 with 0.0 will always result in NaN + //~^ equal expressions as operands to `/` let zero = 0.0; let other_zero = 0.0; let other_nan = zero / other_zero; // fine - this lint doesn't propegate constants. -- cgit 1.4.1-3-g733a5 From 344698377f04124a5df01e498e55c3e27eac294d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 5 Feb 2016 19:43:21 +0100 Subject: Fix typo --- README.md | 2 +- src/copies.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 01999cce70b..d134afe8a8e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 114 lints included in this crate: +There are 116 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/copies.rs b/src/copies.rs index 38f1be92d30..84324dffc85 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -87,7 +87,7 @@ fn lint_same_cond(cx: &LateContext, expr: &Expr) { } } -/// Return the list of conditions expression in a sequence of `if/else`. +/// Return the list of condition expressions in a sequence of `if/else`. /// Eg. would return `[a, b]` for the expression `if a {..} else if b {..}`. fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> { let mut result = vec![]; -- cgit 1.4.1-3-g733a5 From a9e1b1fba05ce94a65f511e2c07bd086c1b0f00f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 14:40:45 +0100 Subject: Small cleanup --- src/copies.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index 84324dffc85..525c7b7a6fd 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -54,15 +54,10 @@ impl LateLintPass for CopyAndPaste { /// Implementation of `IF_SAME_THEN_ELSE`. fn lint_same_then_else(cx: &LateContext, expr: &Expr) { if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node { - let must_lint = if let ExprBlock(ref else_block) = else_expr.node { - is_block_equal(cx, &then_block, &else_block, false) - } - else { - false - }; - - if must_lint { - span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks"); + if let ExprBlock(ref else_block) = else_expr.node { + if is_block_equal(cx, &then_block, &else_block, false) { + span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks"); + } } } } -- cgit 1.4.1-3-g733a5 From d14c4ea187e1874d21a6ddf38bc2b729b2486f24 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 15:14:12 +0100 Subject: Fix wiki Markdown is hell. --- util/update_wiki.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index 990b8860c01..d3467a41012 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -79,7 +79,7 @@ errors of missing symbols. """ -template = """# `%s` +template = """\n# `%s` **Default level:** %s -- cgit 1.4.1-3-g733a5 From ceb9a8bdd79e4c2081d88d40d3a8a2b6f080268f Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 7 Feb 2016 22:50:54 +0100 Subject: regex macro lint --- src/regex.rs | 56 +++++++++++++++++++++++++++++++++++++++++++-- tests/compile-fail/regex.rs | 11 +++++++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/regex.rs b/src/regex.rs index cf19c764361..e7abc9be876 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,14 +1,16 @@ use regex_syntax; use std::error::Error; use syntax::ast::Lit_::LitStr; +use syntax::ast::NodeId; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use rustc_front::hir::*; +use rustc_front::intravisit::{Visitor, walk_block, FnKind}; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::lint::*; -use utils::{match_path, REGEX_NEW_PATH, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_path, REGEX_NEW_PATH, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// @@ -37,16 +39,41 @@ declare_lint! { "finds trivial regular expressions in `Regex::new(_)` invocations" } +/// **What it does:** This lint checks for usage of `regex!(_)` which as of now is usually slower than `Regex::new(_)` unless called in a loop (which is a bad idea anyway). +/// +/// **Why is this bad?** Performance, at least for now. The macro version is likely to catch up long-term, but for now the dynamic version is faster. +/// +/// **Known problems:** None +/// +/// **Example:** `regex!("foo|bar")` +declare_lint! { + pub REGEX_MACRO, + Allow, + "finds use of `regex!(_)`, suggests `Regex::new(_)` instead" +} + #[derive(Copy,Clone)] pub struct RegexPass; impl LintPass for RegexPass { fn get_lints(&self) -> LintArray { - lint_array!(INVALID_REGEX, TRIVIAL_REGEX) + lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) } } impl LateLintPass for RegexPass { + fn check_fn(&mut self, + cx: &LateContext, + _: FnKind, + _: &FnDecl, + block: &Block, + _: Span, + _: NodeId) { + let mut visitor = RegexVisitor { cx: cx, last: BytePos(0) }; + visitor.visit_block(block); + } + + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, @@ -139,3 +166,28 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { _ => None, } } + +struct RegexVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, + last: BytePos +} + +impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { + fn visit_block(&mut self, block: &'v Block) { + if let Some(ref expr) = block.expr { + if let Some(span) = is_expn_of(self.cx, expr.span, "regex") { + if span.lo == BytePos(0) || span.lo == self.last { + return; + } + span_lint(self.cx, + REGEX_MACRO, + span, + &format!("regex!(_): {:?}, {:?}", self.last, span.lo)); + //"`regex!(_)` found. Use `Regex::new(_)`, which is faster for now."); + self.last = span.lo; + return; + } + } + walk_block(self, block); + } +} diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index 2e8228a823d..df52cc3dff0 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -1,8 +1,8 @@ #![feature(plugin)] -#![plugin(clippy)] +#![plugin(clippy, regex_macros)] #![allow(unused)] -#![deny(invalid_regex, trivial_regex)] +#![deny(invalid_regex, trivial_regex, regex_macro)] extern crate regex; @@ -70,7 +70,14 @@ fn trivial_regex() { let non_trivial_ends_with = Regex::new("foo|bar"); } +fn regex_macro() { + let some_regex = regex!("for real!"); //~ERROR `regex!(_)` + let other_regex = regex!("[a-z]_[A-Z]"); //~ERROR `regex!(_)` +} + + fn main() { + regex_macro(); syntax_error(); trivial_regex(); } -- cgit 1.4.1-3-g733a5 From 672beb4138011446ee55360e71a857197ae18d97 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 8 Feb 2016 11:28:18 +0100 Subject: prevent panic in enum glob import lint if a crate's elements are glob imported fixes #639 --- src/enum_glob_use.rs | 10 ++++++---- tests/compile-test.rs | 1 + tests/run-pass/enum-glob-import-crate.rs | 7 +++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tests/run-pass/enum-glob-import-crate.rs diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index d6df307fec2..c6561461e04 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -3,7 +3,7 @@ use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; use rustc_front::hir::*; use rustc::front::map::Node::NodeItem; -use rustc::front::map::PathElem::PathName; +use rustc::front::map::definitions::DefPathData; use rustc::middle::ty::TyEnum; use utils::span_lint; use syntax::codemap::Span; @@ -49,9 +49,11 @@ impl EnumGlobUse { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } else { - if let Some(&PathName(_)) = cx.sess().cstore.item_path(def.def_id()).last() { - if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + if let Some(dp) = cx.sess().cstore.def_path(def.def_id()).last() { + if let DefPathData::Type(_) = dp.data { + if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } } } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 92d2671eaa7..822d9339ba3 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -21,5 +21,6 @@ fn run_mode(mode: &'static str) { #[test] fn compile_test() { + run_mode("run-pass"); run_mode("compile-fail"); } diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs new file mode 100644 index 00000000000..5b54698605a --- /dev/null +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -0,0 +1,7 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy)] + +use std::*; + +fn main() { } -- cgit 1.4.1-3-g733a5 From 652547121490c642f033668043711ba7009b8169 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Mon, 8 Feb 2016 23:48:04 +0100 Subject: fix #595 --- src/lib.rs | 1 + src/regex.rs | 44 ++++++++++++++++++-------------------------- tests/mut_mut_macro.rs | 1 + 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 33de4d6fb79..6f47dfea2f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -257,6 +257,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ranges::RANGE_STEP_BY_ZERO, ranges::RANGE_ZIP_WITH_LEN, regex::INVALID_REGEX, + regex::REGEX_MACRO, regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, diff --git a/src/regex.rs b/src/regex.rs index e7abc9be876..1f5d7faba06 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,11 +1,11 @@ use regex_syntax; use std::error::Error; +use std::collections::HashSet; use syntax::ast::Lit_::LitStr; -use syntax::ast::NodeId; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_block, FnKind}; +use rustc_front::intravisit::{Visitor, walk_expr}; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::lint::*; @@ -48,7 +48,7 @@ declare_lint! { /// **Example:** `regex!("foo|bar")` declare_lint! { pub REGEX_MACRO, - Allow, + Warn, "finds use of `regex!(_)`, suggests `Regex::new(_)` instead" } @@ -62,15 +62,9 @@ impl LintPass for RegexPass { } impl LateLintPass for RegexPass { - fn check_fn(&mut self, - cx: &LateContext, - _: FnKind, - _: &FnDecl, - block: &Block, - _: Span, - _: NodeId) { - let mut visitor = RegexVisitor { cx: cx, last: BytePos(0) }; - visitor.visit_block(block); + fn check_crate(&mut self, cx: &LateContext, krate: &Crate) { + let mut visitor = RegexVisitor { cx: cx, spans: HashSet::new() }; + krate.visit_all_items(&mut visitor); } @@ -169,25 +163,23 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { struct RegexVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, - last: BytePos + spans: HashSet<Span>, } impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { - fn visit_block(&mut self, block: &'v Block) { - if let Some(ref expr) = block.expr { - if let Some(span) = is_expn_of(self.cx, expr.span, "regex") { - if span.lo == BytePos(0) || span.lo == self.last { - return; - } - span_lint(self.cx, - REGEX_MACRO, - span, - &format!("regex!(_): {:?}, {:?}", self.last, span.lo)); - //"`regex!(_)` found. Use `Regex::new(_)`, which is faster for now."); - self.last = span.lo; + fn visit_expr(&mut self, expr: &'v Expr) { + if let Some(span) = is_expn_of(self.cx, expr.span, "regex") { + if self.spans.contains(&span) { return; } + span_lint(self.cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now."); + self.spans.insert(span); + return; } - walk_block(self, block); + walk_expr(self, expr); } } diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs index ebfd3ed2e1f..67d73ce0ac4 100644 --- a/tests/mut_mut_macro.rs +++ b/tests/mut_mut_macro.rs @@ -9,6 +9,7 @@ use std::collections::HashMap; #[test] #[deny(mut_mut)] +#[allow(regex_macro)] fn test_regex() { let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); assert!(pattern.is_match("# headline")); -- cgit 1.4.1-3-g733a5 From 275795fab321d860cd9f01243f861bf804b1e53c Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Tue, 9 Feb 2016 06:18:08 +0100 Subject: speed up lint using blocks and types --- src/regex.rs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/regex.rs b/src/regex.rs index 1f5d7faba06..cf938dcf4b3 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -5,12 +5,12 @@ use syntax::ast::Lit_::LitStr; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_expr}; +use rustc_front::intravisit::{Visitor, walk_block}; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::lint::*; -use utils::{is_expn_of, match_path, REGEX_NEW_PATH, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_path, match_type, REGEX_NEW_PATH, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// @@ -167,19 +167,23 @@ struct RegexVisitor<'v, 't: 'v> { } impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { - fn visit_expr(&mut self, expr: &'v Expr) { - if let Some(span) = is_expn_of(self.cx, expr.span, "regex") { - if self.spans.contains(&span) { + fn visit_block(&mut self, block: &'v Block) { + if_let_chain!{[ + let Some(ref expr) = block.expr, + match_type(self.cx, self.cx.tcx.expr_ty(expr), &["regex", "re", "Regex"]), + let Some(span) = is_expn_of(self.cx, expr.span, "regex") + ], { + if self.spans.contains(&span) { + return; + } + span_lint(self.cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now."); + self.spans.insert(span); return; - } - span_lint(self.cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now."); - self.spans.insert(span); - return; - } - walk_expr(self, expr); + }} + walk_block(self, block); } } -- cgit 1.4.1-3-g733a5 From 56b3e7b4c2308be84ce4eed18f03743cc592b780 Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Tue, 9 Feb 2016 14:10:22 -0500 Subject: lint comparison to bool (e.g. `y == true`) Addresses #630 --- src/lib.rs | 2 ++ src/needless_bool.rs | 66 +++++++++++++++++++++++++++++++++++ tests/compile-fail/bool_comparison.rs | 12 +++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/compile-fail/bool_comparison.rs diff --git a/src/lib.rs b/src/lib.rs index 728aa124a18..c1e8c3c9f01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,6 +105,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); + reg.register_late_lint_pass(box needless_bool::BoolComparison); reg.register_late_lint_pass(box approx_const::ApproxConstant); reg.register_late_lint_pass(box misc::FloatCmp); reg.register_early_lint_pass(box precedence::Precedence); @@ -253,6 +254,7 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, needless_bool::NEEDLESS_BOOL, + needless_bool::BOOL_COMPARISON, needless_features::UNSTABLE_AS_MUT_SLICE, needless_features::UNSTABLE_AS_SLICE, needless_update::NEEDLESS_UPDATE, diff --git a/src/needless_bool.rs b/src/needless_bool.rs index bfd819edcb6..a2a0d13e17c 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -6,6 +6,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::Lit_; +use syntax::codemap::Spanned; use utils::{span_lint, snippet}; @@ -23,6 +24,20 @@ declare_lint! { `if p { true } else { false }`" } +/// **What it does:** This lint checks for expressions of the form `x == true` (or vice versa) and suggest using the variable directly. +/// +/// **Why is this bad?** Unnecessary code. +/// +/// **Known problems:** None. +/// +/// **Example:** `if x == true { }` could be `if x { }` +declare_lint! { + pub BOOL_COMPARISON, + Warn, + "comparing a variable to a boolean, e.g. \ + `if x == true`" +} + #[derive(Copy,Clone)] pub struct NeedlessBool; @@ -78,6 +93,57 @@ impl LateLintPass for NeedlessBool { } } +#[derive(Copy,Clone)] +pub struct BoolComparison; + +impl LintPass for BoolComparison { + fn get_lints(&self) -> LintArray { + lint_array!(BOOL_COMPARISON) + } +} + +impl LateLintPass for BoolComparison { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(Spanned{ node: BiEq, .. }, ref left_side, ref right_side) = e.node { + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { + (Some(true), None) => { + let side_snip = snippet(cx, right_side.span, ".."); + let hint = format!("`{}`", side_snip); + span_lint(cx, + BOOL_COMPARISON, + e.span, + &format!("you can simplify this boolean comparison to {}", hint)); + } + (None, Some(true)) => { + let side_snip = snippet(cx, left_side.span, ".."); + let hint = format!("`{}`", side_snip); + span_lint(cx, + BOOL_COMPARISON, + e.span, + &format!("you can simplify this boolean comparison to {}", hint)); + } + (Some(false), None) => { + let side_snip = snippet(cx, right_side.span, ".."); + let hint = format!("`!{}`", side_snip); + span_lint(cx, + BOOL_COMPARISON, + e.span, + &format!("you can simplify this boolean comparison to {}", hint)); + } + (None, Some(false)) => { + let side_snip = snippet(cx, left_side.span, ".."); + let hint = format!("`!{}`", side_snip); + span_lint(cx, + BOOL_COMPARISON, + e.span, + &format!("you can simplify this boolean comparison to {}", hint)); + } + _ => (), + } + } + } +} + fn fetch_bool_block(block: &Block) -> Option<bool> { if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) diff --git a/tests/compile-fail/bool_comparison.rs b/tests/compile-fail/bool_comparison.rs new file mode 100644 index 00000000000..d2a362af2f4 --- /dev/null +++ b/tests/compile-fail/bool_comparison.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[allow(needless_bool)] +#[deny(bool_comparison)] +fn main() { + let x = true; + if x == true { true } else { false }; //~ERROR you can simplify this boolean comparison to `x` + if x == false { true } else { false }; //~ERROR you can simplify this boolean comparison to `!x` + if true == x { true } else { false }; //~ERROR you can simplify this boolean comparison to `x` + if false == x { true } else { false }; //~ERROR you can simplify this boolean comparison to `!x` +} -- cgit 1.4.1-3-g733a5 From 14292674b0cc828ced88731d15c86035045fa206 Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Tue, 9 Feb 2016 14:44:42 -0500 Subject: display suggestion separately from lint --- src/needless_bool.rs | 46 ++++++++++++++++++++++------------- tests/compile-fail/bool_comparison.rs | 21 ++++++++++++---- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index a2a0d13e17c..a40b4b3a252 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -8,7 +8,7 @@ use rustc_front::hir::*; use syntax::ast::Lit_; use syntax::codemap::Spanned; -use utils::{span_lint, snippet}; +use utils::{span_lint, span_lint_and_then, snippet}; /// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. /// @@ -109,34 +109,46 @@ impl LateLintPass for BoolComparison { (Some(true), None) => { let side_snip = snippet(cx, right_side.span, ".."); let hint = format!("`{}`", side_snip); - span_lint(cx, - BOOL_COMPARISON, - e.span, - &format!("you can simplify this boolean comparison to {}", hint)); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against booleans are unnecesary", + |db| { + db.span_suggestion(e.span, "try simplifying it:", hint); + }); } (None, Some(true)) => { let side_snip = snippet(cx, left_side.span, ".."); let hint = format!("`{}`", side_snip); - span_lint(cx, - BOOL_COMPARISON, - e.span, - &format!("you can simplify this boolean comparison to {}", hint)); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against booleans are unnecesary", + |db| { + db.span_suggestion(e.span, "try simplifying it:", hint); + }); } (Some(false), None) => { let side_snip = snippet(cx, right_side.span, ".."); let hint = format!("`!{}`", side_snip); - span_lint(cx, - BOOL_COMPARISON, - e.span, - &format!("you can simplify this boolean comparison to {}", hint)); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against booleans are unnecesary", + |db| { + db.span_suggestion(e.span, "try simplifying it:", hint); + }); } (None, Some(false)) => { let side_snip = snippet(cx, left_side.span, ".."); let hint = format!("`!{}`", side_snip); - span_lint(cx, - BOOL_COMPARISON, - e.span, - &format!("you can simplify this boolean comparison to {}", hint)); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against booleans are unnecesary", + |db| { + db.span_suggestion(e.span, "try simplifying it:", hint); + }); } _ => (), } diff --git a/tests/compile-fail/bool_comparison.rs b/tests/compile-fail/bool_comparison.rs index d2a362af2f4..468b8382e94 100644 --- a/tests/compile-fail/bool_comparison.rs +++ b/tests/compile-fail/bool_comparison.rs @@ -1,12 +1,23 @@ #![feature(plugin)] #![plugin(clippy)] -#[allow(needless_bool)] #[deny(bool_comparison)] fn main() { let x = true; - if x == true { true } else { false }; //~ERROR you can simplify this boolean comparison to `x` - if x == false { true } else { false }; //~ERROR you can simplify this boolean comparison to `!x` - if true == x { true } else { false }; //~ERROR you can simplify this boolean comparison to `x` - if false == x { true } else { false }; //~ERROR you can simplify this boolean comparison to `!x` + if x == true { "yes" } else { "no" }; + //~^ ERROR equality checks against booleans are unnecesary + //~| HELP try simplifying it: + //~| SUGGESTION x + if x == false { "yes" } else { "no" }; + //~^ ERROR equality checks against booleans are unnecesary + //~| HELP try simplifying it: + //~| SUGGESTION !x + if true == x { "yes" } else { "no" }; + //~^ ERROR equality checks against booleans are unnecesary + //~| HELP try simplifying it: + //~| SUGGESTION x + if false == x { "yes" } else { "no" }; + //~^ ERROR equality checks against booleans are unnecesary + //~| HELP try simplifying it: + //~| SUGGESTION !x } -- cgit 1.4.1-3-g733a5 From 2687a3f6b590f7175d87a95dd49ccf2f11c9d2e3 Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Tue, 9 Feb 2016 14:52:20 -0500 Subject: Update lints --- README.md | 3 ++- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cbb8646c672..4f5cdf30606 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 117 lints included in this crate: +There are 118 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -15,6 +15,7 @@ name [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` [block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` +[bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap [boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` diff --git a/src/lib.rs b/src/lib.rs index c1e8c3c9f01..3485b83a18b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,8 +253,8 @@ pub fn plugin_registrar(reg: &mut Registry) { misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, - needless_bool::NEEDLESS_BOOL, needless_bool::BOOL_COMPARISON, + needless_bool::NEEDLESS_BOOL, needless_features::UNSTABLE_AS_MUT_SLICE, needless_features::UNSTABLE_AS_SLICE, needless_update::NEEDLESS_UPDATE, -- cgit 1.4.1-3-g733a5 From 34812e82d066dc1b3ef89df4272300662374f907 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 18:10:03 +0100 Subject: Use const_eval in loops --- src/loops.rs | 43 ++++++++++++++++++++++++++++-------------- tests/compile-fail/for_loop.rs | 22 ++++++++++++++++++--- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 4620d6a3e81..cecf47daf55 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,11 +1,12 @@ +use reexport::*; +use rustc::front::map::Node::NodeBlock; use rustc::lint::*; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; +use rustc::middle::def::Def; +use rustc::middle::ty; use rustc_front::hir::*; -use reexport::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; -use rustc::middle::ty; -use rustc::middle::def::Def; -use consts::{constant_simple, Constant}; -use rustc::front::map::Node::NodeBlock; use std::borrow::Cow; use std::collections::{HashSet, HashMap}; @@ -421,22 +422,36 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { // ...and both sides are compile-time constant integers... - if let Some(start_idx @ Constant::Int(..)) = constant_simple(start_expr) { - if let Some(stop_idx @ Constant::Int(..)) = constant_simple(stop_expr) { + if let Ok(start_idx) = eval_const_expr_partial(&cx.tcx, start_expr, ExprTypeChecked, None) { + if let Ok(stop_idx) = eval_const_expr_partial(&cx.tcx, stop_expr, ExprTypeChecked, None) { // ...and the start index is greater than the stop index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the // smaller value. - if start_idx > stop_idx { - span_help_and_lint(cx, + let (sup, eq) = match (start_idx, stop_idx) { + (ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx), + (ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx), + _ => (false, false), + }; + + if sup { + let start_snippet = snippet(cx, start_expr.span, "_"); + let stop_snippet = snippet(cx, stop_expr.span, "_"); + + span_lint_and_then(cx, REVERSE_RANGE_LOOP, expr.span, "this range is empty so this for loop will never run", - &format!("Consider using `({}..{}).rev()` if you are attempting to iterate \ - over this range in reverse", - stop_idx, - start_idx)); - } else if start_idx == stop_idx { + |db| { + db.span_suggestion(expr.span, + "consider using the following if \ + you are attempting to iterate \ + over this range in reverse", + format!("({}..{}).rev()` ", + stop_snippet, + start_snippet)); + }); + } else if eq { // if they are equal, it's also problematic - this loop // will never run. span_lint(cx, diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index e361ebe777f..4609c840836 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -65,7 +65,7 @@ fn for_loop_over_option_and_result() { break; } - // while let false positive for Option + // while let false positive for Result while let Ok(x) = result { println!("{}", x); break; @@ -85,8 +85,10 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist,shadow_unrelated,unnecessary_mut_passed, cyclomatic_complexity)] +#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity)] fn main() { + const MAX_LEN: usize = 42; + let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; for i in 0..vec.len() { @@ -111,6 +113,11 @@ fn main() { println!("{}", vec[i]); } + for i in 0..MAX_LEN { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)` + println!("{}", vec[i]); + } + for i in 5..10 { //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` println!("{}", vec[i]); @@ -126,7 +133,16 @@ fn main() { println!("{} {}", vec[i], i); } - for i in 10..0 { //~ERROR this range is empty so this for loop will never run + for i in 10..0 { + //~^ERROR this range is empty so this for loop will never run + //~|HELP consider + //~|SUGGESTION (0..10).rev() + println!("{}", i); + } + + for i in MAX_LEN..0 { //~ERROR this range is empty so this for loop will never run + //~|HELP consider + //~|SUGGESTION (0..MAX_LEN).rev() println!("{}", i); } -- cgit 1.4.1-3-g733a5 From d27aa960b605f69a22b83917ba3830bd2d5690ec Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 18:14:03 +0100 Subject: Remove unused Display implementation for consts --- src/consts.rs | 86 ----------------------------------------------------------- 1 file changed, 86 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 5f40aff92cc..ddc8560c9b3 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -6,12 +6,10 @@ use rustc::middle::def::PathResolution; use rustc::middle::def::Def; use rustc_front::hir::*; use syntax::ptr::P; -use std::char; use std::cmp::PartialOrd; use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; -use std::fmt; use syntax::ast::Lit_; use syntax::ast::LitIntType; @@ -173,90 +171,6 @@ impl PartialOrd for Constant { } } -fn format_byte(fmt: &mut fmt::Formatter, b: u8) -> fmt::Result { - if b == b'\\' { - write!(fmt, "\\\\") - } else if 0x20 <= b && b <= 0x7e { - write!(fmt, "{}", char::from_u32(b as u32).expect("all u8 are valid char")) - } else if b == 0x0a { - write!(fmt, "\\n") - } else if b == 0x0d { - write!(fmt, "\\r") - } else { - write!(fmt, "\\x{:02x}", b) - } -} - -impl fmt::Display for Constant { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - Constant::Str(ref s, _) => write!(fmt, "{:?}", s), - Constant::Byte(ref b) => { - write!(fmt, "b'") - .and_then(|_| format_byte(fmt, *b)) - .and_then(|_| write!(fmt, "'")) - } - Constant::Binary(ref bs) => { - try!(write!(fmt, "b\"")); - for b in bs.iter() { - try!(format_byte(fmt, *b)); - } - write!(fmt, "\"") - } - Constant::Char(ref c) => write!(fmt, "'{}'", c), - Constant::Int(ref i, ref ity) => { - let (sign, suffix) = match *ity { - LitIntType::SignedIntLit(ref sity, ref sign) => { - (if let Sign::Minus = *sign { - "-" - } else { - "" - }, - sity.ty_to_string()) - } - LitIntType::UnsignedIntLit(ref uity) => ("", uity.ty_to_string()), - LitIntType::UnsuffixedIntLit(ref sign) => { - (if let Sign::Minus = *sign { - "-" - } else { - "" - }, - "".into()) - } - }; - write!(fmt, "{}{}{}", sign, i, suffix) - } - Constant::Float(ref s, ref fw) => { - let suffix = match *fw { - FloatWidth::Fw32 => "f32", - FloatWidth::Fw64 => "f64", - FloatWidth::FwAny => "", - }; - write!(fmt, "{}{}", s, suffix) - } - Constant::Bool(ref b) => write!(fmt, "{}", b), - Constant::Repeat(ref c, ref n) => write!(fmt, "[{}; {}]", c, n), - Constant::Vec(ref v) => { - write!(fmt, - "[{}]", - v.iter() - .map(|i| format!("{}", i)) - .collect::<Vec<_>>() - .join(", ")) - } - Constant::Tuple(ref t) => { - write!(fmt, - "({})", - t.iter() - .map(|i| format!("{}", i)) - .collect::<Vec<_>>() - .join(", ")) - } - } - } -} - - fn lit_to_constant(lit: &Lit_) -> Constant { match *lit { Lit_::LitStr(ref is, style) => Constant::Str(is.to_string(), style), -- cgit 1.4.1-3-g733a5 From 1a8b8cd28f3e452a1c4bfc2208ada1a2f4a0ebda Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 18:28:37 +0100 Subject: Don’t use `{:?}` and use span_suggestion in TOPLEVEL_REF_ARG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/misc.rs | 16 +++++++++++----- tests/compile-fail/toplevel_ref_arg.rs | 12 ++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index c0aed78225a..f570c18b742 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -11,7 +11,7 @@ use rustc::middle::const_eval::eval_const_expr_partial; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; -use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_trait}; +use utils::{span_lint_and_then, walk_ptrs_ty, is_integer_literal, implements_trait}; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. /// @@ -62,16 +62,22 @@ impl LateLintPass for TopLevelRefPass { let Some(ref init) = l.init ], { let tyopt = if let Some(ref ty) = l.ty { - format!(": {:?} ", ty) + format!(": {}", snippet(cx, ty.span, "_")) } else { "".to_owned() }; - span_help_and_lint(cx, + span_lint_and_then(cx, TOPLEVEL_REF_ARG, l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", - &format!("try `let {} {}= &{};`", snippet(cx, i.span, "_"), - tyopt, snippet(cx, init.span, "_")) + |db| { + db.span_suggestion(s.span, + "try", + format!("let {}{} = &{};", + snippet(cx, i.span, "_"), + tyopt, + snippet(cx, init.span, "_"))); + } ); } }; diff --git a/tests/compile-fail/toplevel_ref_arg.rs b/tests/compile-fail/toplevel_ref_arg.rs index 05ad1af0034..de1556ed0e3 100644 --- a/tests/compile-fail/toplevel_ref_arg.rs +++ b/tests/compile-fail/toplevel_ref_arg.rs @@ -15,11 +15,15 @@ fn main() { let y = |ref x| { println!("{:?}", x) }; y(1u8); - let ref x = 1; //~ ERROR `ref` on an entire `let` pattern is discouraged - //~^ HELP try `let x = &1;` + let ref x = 1; + //~^ ERROR `ref` on an entire `let` pattern is discouraged + //~| HELP try + //~| SUGGESTION let x = &1; - let ref y = (&1, 2); //~ ERROR `ref` on an entire `let` pattern is discouraged - //~^ HELP try `let y = &(&1, 2);` + let ref y : (&_, u8) = (&1, 2); + //~^ ERROR `ref` on an entire `let` pattern is discouraged + //~| HELP try + //~| SUGGESTION let y: (&_, u8) = &(&1, 2); let (ref x, _) = (1,2); // okay, not top level println!("The answer is {}.", x); -- cgit 1.4.1-3-g733a5 From 2db6965c81ee9f01b12874c115ec2a593b5f2c5f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 7 Feb 2016 18:30:57 +0100 Subject: Lint usage of `Debug`-based formatting --- README.md | 3 ++- src/lib.rs | 1 + src/print.rs | 48 ++++++++++++++++++++++++++++++++++++++++++--- src/utils.rs | 2 ++ tests/compile-fail/print.rs | 32 +++++++++++++++++++++++++++++- 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4d655c85951..87b58b320ff 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 117 lints included in this crate: +There are 118 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -118,6 +118,7 @@ name [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions +[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` diff --git a/src/lib.rs b/src/lib.rs index cd9ac226321..ba9236012d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,7 @@ pub fn plugin_registrar(reg: &mut Registry) { mut_mut::MUT_MUT, mutex_atomic::MUTEX_INTEGER, print::PRINT_STDOUT, + print::USE_DEBUG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, diff --git a/src/print.rs b/src/print.rs index d8f5fd488aa..3c10b4bed13 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,6 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{IO_PRINT_PATH, is_expn_of, match_path, span_lint}; +use rustc::front::map::Node::{NodeItem, NodeImplItem}; +use utils::{FMT_ARGUMENTV1_NEW_PATH, DEBUG_FMT_METHOD_PATH, IO_PRINT_PATH}; +use utils::{is_expn_of, match_path, span_lint}; /// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants. /// @@ -16,21 +18,36 @@ declare_lint! { "printing on stdout" } +/// **What it does:** This lint warns whenever you use `Debug` formatting. The purpose of this lint is to catch debugging remnants. +/// +/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate debugging Rust code. It +/// should not be used in in user-facing output. +/// +/// **Example:** `println!("{:?}", foo);` +declare_lint! { + pub USE_DEBUG, + Allow, + "use `Debug`-based formatting" +} + #[derive(Copy, Clone, Debug)] pub struct PrintLint; impl LintPass for PrintLint { fn get_lints(&self) -> LintArray { - lint_array!(PRINT_STDOUT) + lint_array!(PRINT_STDOUT, USE_DEBUG) } } impl LateLintPass for PrintLint { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprCall(ref fun, _) = expr.node { + if let ExprCall(ref fun, ref args) = expr.node { if let ExprPath(_, ref path) = fun.node { + // Search for `std::io::_print(..)` which is unique in a + // `print!` expansion. if match_path(path, &IO_PRINT_PATH) { if let Some(span) = is_expn_of(cx, expr.span, "print") { + // `println!` uses `print!`. let (span, name) = match is_expn_of(cx, span, "println") { Some(span) => (span, "println"), None => (span, "print"), @@ -39,7 +56,32 @@ impl LateLintPass for PrintLint { span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); } } + // Search for something like + // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` + else if args.len() == 2 && match_path(path, &FMT_ARGUMENTV1_NEW_PATH) { + if let ExprPath(None, ref path) = args[1].node { + if match_path(path, &DEBUG_FMT_METHOD_PATH) && + !is_in_debug_impl(cx, expr) && + is_expn_of(cx, expr.span, "panic").is_none() { + span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } + } + } } } } } + +fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { + let map = &cx.tcx.map; + + if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { // `fmt` method + if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { // `Debug` impl + if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node { + return match_path(&tr.path, &["Debug"]); + } + } + } + + false +} diff --git a/src/utils.rs b/src/utils.rs index a8890f31cb0..4c89b7f113d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -26,8 +26,10 @@ pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BT pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTV1_NEW_PATH: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; diff --git a/tests/compile-fail/print.rs b/tests/compile-fail/print.rs index 8141cdd2645..34c38dca286 100755 --- a/tests/compile-fail/print.rs +++ b/tests/compile-fail/print.rs @@ -1,11 +1,41 @@ #![feature(plugin)] #![plugin(clippy)] +#![deny(print_stdout, use_debug)] -#[deny(print_stdout)] +use std::fmt::{Debug, Display, Formatter, Result}; + +#[allow(dead_code)] +struct Foo; + +impl Display for Foo { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "{:?}", 43.1415) + //~^ ERROR use of `Debug`-based formatting + } +} + +impl Debug for Foo { + fn fmt(&self, f: &mut Formatter) -> Result { + // ok, we can use `Debug` formatting in `Debug` implementations + write!(f, "{:?}", 42.718) + } +} fn main() { println!("Hello"); //~ERROR use of `println!` print!("Hello"); //~ERROR use of `print!` + print!("Hello {}", "World"); //~ERROR use of `print!` + + print!("Hello {:?}", "World"); + //~^ ERROR use of `print!` + //~| ERROR use of `Debug`-based formatting + + print!("Hello {:#?}", "#orld"); + //~^ ERROR use of `print!` + //~| ERROR use of `Debug`-based formatting + + assert_eq!(42, 1337); + vec![1, 2]; } -- cgit 1.4.1-3-g733a5 From 7e06737d6f54ed6ecae339c625a5a2e2d679ad7e Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Tue, 9 Feb 2016 15:44:07 -0500 Subject: Improve testing and suggestion messages on bool_comparison --- src/needless_bool.rs | 28 ++++++++++++---------------- tests/compile-fail/bool_comparison.rs | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index a40b4b3a252..5382b8f0f04 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -107,47 +107,43 @@ impl LateLintPass for BoolComparison { if let ExprBinary(Spanned{ node: BiEq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Some(true), None) => { - let side_snip = snippet(cx, right_side.span, ".."); - let hint = format!("`{}`", side_snip); + let hint = format!("{}", snippet(cx, right_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against booleans are unnecesary", + "equality checks against true are unnecesary", |db| { - db.span_suggestion(e.span, "try simplifying it:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } (None, Some(true)) => { - let side_snip = snippet(cx, left_side.span, ".."); - let hint = format!("`{}`", side_snip); + let hint = format!("{}", snippet(cx, left_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against booleans are unnecesary", + "equality checks against true are unnecesary", |db| { - db.span_suggestion(e.span, "try simplifying it:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } (Some(false), None) => { - let side_snip = snippet(cx, right_side.span, ".."); - let hint = format!("`!{}`", side_snip); + let hint = format!("!{}", snippet(cx, right_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against booleans are unnecesary", + "equality checks against false can be replaced by a negation", |db| { - db.span_suggestion(e.span, "try simplifying it:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } (None, Some(false)) => { - let side_snip = snippet(cx, left_side.span, ".."); - let hint = format!("`!{}`", side_snip); + let hint = format!("!{}", snippet(cx, left_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against booleans are unnecesary", + "equality checks against false can be replaced by a negation", |db| { - db.span_suggestion(e.span, "try simplifying it:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } _ => (), diff --git a/tests/compile-fail/bool_comparison.rs b/tests/compile-fail/bool_comparison.rs index 468b8382e94..8a792931d02 100644 --- a/tests/compile-fail/bool_comparison.rs +++ b/tests/compile-fail/bool_comparison.rs @@ -5,19 +5,19 @@ fn main() { let x = true; if x == true { "yes" } else { "no" }; - //~^ ERROR equality checks against booleans are unnecesary - //~| HELP try simplifying it: - //~| SUGGESTION x + //~^ ERROR equality checks against true are unnecesary + //~| HELP try simplifying it as shown: + //~| SUGGESTION if x { "yes" } else { "no" }; if x == false { "yes" } else { "no" }; - //~^ ERROR equality checks against booleans are unnecesary - //~| HELP try simplifying it: - //~| SUGGESTION !x + //~^ ERROR equality checks against false can be replaced by a negation + //~| HELP try simplifying it as shown: + //~| SUGGESTION if !x { "yes" } else { "no" }; if true == x { "yes" } else { "no" }; - //~^ ERROR equality checks against booleans are unnecesary - //~| HELP try simplifying it: - //~| SUGGESTION x + //~^ ERROR equality checks against true are unnecesary + //~| HELP try simplifying it as shown: + //~| SUGGESTION if x { "yes" } else { "no" }; if false == x { "yes" } else { "no" }; - //~^ ERROR equality checks against booleans are unnecesary - //~| HELP try simplifying it: - //~| SUGGESTION !x + //~^ ERROR equality checks against false can be replaced by a negation + //~| HELP try simplifying it as shown: + //~| SUGGESTION if !x { "yes" } else { "no" }; } -- cgit 1.4.1-3-g733a5 From eed9ec15fb2f38f4ea315f0a112f726d5623264f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 11 Feb 2016 13:50:41 +0100 Subject: improve the `no_effect` lint --- src/no_effect.rs | 27 +++++++++++++++---- tests/compile-fail/absurd-extreme-comparisons.rs | 2 +- tests/compile-fail/array_indexing.rs | 1 + tests/compile-fail/bit_masks.rs | 4 +-- tests/compile-fail/cast.rs | 1 + tests/compile-fail/cmp_nan.rs | 2 +- tests/compile-fail/copies.rs | 2 +- tests/compile-fail/eq_op.rs | 1 + tests/compile-fail/eta.rs | 2 +- tests/compile-fail/float_cmp.rs | 2 +- tests/compile-fail/identity_op.rs | 2 +- tests/compile-fail/modulo_one.rs | 1 + tests/compile-fail/mut_mut.rs | 2 +- tests/compile-fail/no_effect.rs | 33 +++++++++++++++++++++++- 14 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/no_effect.rs b/src/no_effect.rs index e1067f27ab9..0df5ede82da 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::middle::def::Def; -use rustc_front::hir::{Expr, ExprCall, ExprLit, ExprPath, ExprStruct}; +use rustc_front::hir::{Expr, Expr_}; use rustc_front::hir::{Stmt, StmtSemi}; use utils::in_macro; @@ -24,16 +24,33 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { return false; } match expr.node { - ExprLit(..) | - ExprPath(..) => true, - ExprStruct(_, ref fields, ref base) => { + Expr_::ExprLit(..) | + Expr_::ExprClosure(..) | + Expr_::ExprRange(None, None) | + Expr_::ExprPath(..) => true, + Expr_::ExprIndex(ref a, ref b) | + Expr_::ExprRange(Some(ref a), Some(ref b)) | + Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), + Expr_::ExprVec(ref v) | + Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), + Expr_::ExprRange(Some(ref inner), None) | + Expr_::ExprRange(None, Some(ref inner)) | + Expr_::ExprRepeat(ref inner, _) | + Expr_::ExprCast(ref inner, _) | + Expr_::ExprType(ref inner, _) | + Expr_::ExprUnary(_, ref inner) | + Expr_::ExprField(ref inner, _) | + Expr_::ExprTupField(ref inner, _) | + Expr_::ExprAddrOf(_, ref inner) | + Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), + Expr_::ExprStruct(_, ref fields, ref base) => { fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { Some(ref base) => has_no_effect(cx, base), None => true, } } - ExprCall(ref callee, ref args) => { + Expr_::ExprCall(ref callee, ref args) => { let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); match def { Some(Def::Struct(..)) | diff --git a/tests/compile-fail/absurd-extreme-comparisons.rs b/tests/compile-fail/absurd-extreme-comparisons.rs index 9718225d203..7e2ad1fede5 100644 --- a/tests/compile-fail/absurd-extreme-comparisons.rs +++ b/tests/compile-fail/absurd-extreme-comparisons.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(absurd_extreme_comparisons)] -#![allow(unused, eq_op)] +#![allow(unused, eq_op, no_effect)] fn main() { const Z: u32 = 0; diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs index 68ab71da586..1d9492bc0ab 100644 --- a/tests/compile-fail/array_indexing.rs +++ b/tests/compile-fail/array_indexing.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![deny(out_of_bounds_indexing)] +#![allow(no_effect)] fn main() { let x = [1,2,3,4]; diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index f78012864a0..98135295862 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -5,7 +5,7 @@ const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] -#[allow(ineffective_bit_mask, identity_op)] +#[allow(ineffective_bit_mask, identity_op, no_effect)] fn main() { let x = 5; @@ -45,7 +45,7 @@ fn main() { } #[deny(ineffective_bit_mask)] -#[allow(bad_bit_mask)] +#[allow(bad_bit_mask, no_effect)] fn ineffective() { let x = 5; diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index 70cc1919be4..0f44fa2c1fd 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap)] +#[allow(no_effect)] fn main() { // Test cast_precision_loss 1i32 as f32; //~ERROR casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs index b2369e164ff..d2188130a61 100644 --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(cmp_nan)] -#[allow(float_cmp)] +#[allow(float_cmp, no_effect)] fn main() { let x = 5f32; x == std::f32::NAN; //~ERROR doomed comparison with NAN diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 0f57b619ccc..d6e666f299b 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(dead_code)] +#![allow(dead_code, no_effect)] #![allow(let_and_return)] #![allow(needless_return)] #![allow(unused_variables)] diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 7be5ef11ce6..487185516bf 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -3,6 +3,7 @@ #[deny(eq_op)] #[allow(identity_op)] +#[allow(no_effect)] fn main() { // simple values and comparisons 1 == 1; //~ERROR equal expressions diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 1ffca9ac5ce..46680f2b8d8 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unknown_lints, unused)] +#![allow(unknown_lints, unused, no_effect)] #![deny(redundant_closure)] fn main() { diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 27cde245f68..d1ecb37cdd5 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(float_cmp)] -#![allow(unused)] +#![allow(unused, no_effect)] use std::ops::Add; diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index c1141e0b460..28873ee6b73 100644 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -5,7 +5,7 @@ const ONE : i64 = 1; const NEG_ONE : i64 = -1; const ZERO : i64 = 0; -#[allow(eq_op)] +#[allow(eq_op, no_effect)] #[deny(identity_op)] fn main() { let x = 0; diff --git a/tests/compile-fail/modulo_one.rs b/tests/compile-fail/modulo_one.rs index 1301b4e499c..e84209a6d1e 100644 --- a/tests/compile-fail/modulo_one.rs +++ b/tests/compile-fail/modulo_one.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] #![deny(modulo_one)] +#![allow(no_effect)] fn main() { 10 % 1; //~ERROR any number modulo 1 will be 0 diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 2560a54c0ef..0db9cb3bdef 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused)] +#![allow(unused, no_effect)] //#![plugin(regex_macros)] //extern crate regex; diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index 21118b82718..52ea423a57d 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -1,4 +1,4 @@ -#![feature(plugin)] +#![feature(plugin, box_syntax)] #![plugin(clippy)] #![deny(no_effect)] @@ -20,14 +20,32 @@ fn get_struct() -> Struct { Struct { field: 0 } } fn main() { let s = get_struct(); + let s2 = get_struct(); 0; //~ERROR statement with no effect + s2; //~ERROR statement with no effect Unit; //~ERROR statement with no effect Tuple(0); //~ERROR statement with no effect Struct { field: 0 }; //~ERROR statement with no effect Struct { ..s }; //~ERROR statement with no effect Enum::Tuple(0); //~ERROR statement with no effect Enum::Struct { field: 0 }; //~ERROR statement with no effect + 5 + 6; //~ERROR statement with no effect + *&42; //~ERROR statement with no effect + &6; //~ERROR statement with no effect + (5, 6, 7); //~ERROR statement with no effect + box 42; //~ERROR statement with no effect + ..; //~ERROR statement with no effect + 5..; //~ERROR statement with no effect + ..5; //~ERROR statement with no effect + 5..6; //~ERROR statement with no effect + [42, 55]; //~ERROR statement with no effect + [42, 55][1]; //~ERROR statement with no effect + (42, 55).1; //~ERROR statement with no effect + [42; 55]; //~ERROR statement with no effect + [42; 55][13]; //~ERROR statement with no effect + let mut x = 0; + || x += 5; //~ERROR statement with no effect // Do not warn get_number(); @@ -36,4 +54,17 @@ fn main() { Struct { ..get_struct() }; Enum::Tuple(get_number()); Enum::Struct { field: get_number() }; + 5 + get_number(); + *&get_number(); + &get_number(); + (5, 6, get_number()); + box get_number(); + get_number()..; + ..get_number(); + 5..get_number(); + [42, get_number()]; + [42, 55][get_number() as usize]; + (42, get_number()).1; + [get_number(); 55]; + [42; 55][get_number() as usize]; } -- cgit 1.4.1-3-g733a5 From d305bca25bf4c560faaa030c069364d46739e255 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Fri, 12 Feb 2016 12:31:13 +0100 Subject: fixed README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 39e2cf15a37..6bb7a2e230e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 118 lints included in this crate: +There are 119 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- cgit 1.4.1-3-g733a5 From e1c7914c2e1afe34073f01acb5638963029cb961 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 30 Jan 2016 18:03:53 +0100 Subject: Add missing ExprIndex to is_exp_equal --- src/utils.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils.rs b/src/utils.rs index 4c89b7f113d..9adbff90e66 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -718,6 +718,9 @@ pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr, ignore_fn: bool is_block_equal(cx, lt, rt, ignore_fn) && both(le, re, |l, r| is_exp_equal(cx, l, r, ignore_fn)) } + (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { + is_exp_equal(cx, la, ra) && is_exp_equal(cx, li, ri) + } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && -- cgit 1.4.1-3-g733a5 From 91c16fc8e605ddb7f0b4f967bd7fbf62ccd6a292 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 20:13:25 +0100 Subject: Refactor Expr comparisons --- src/copies.rs | 7 +- src/entry.rs | 5 +- src/eq_op.rs | 4 +- src/strings.rs | 7 +- src/utils.rs | 833 ------------------------------------------------------- src/utils/hir.rs | 239 ++++++++++++++++ src/utils/mod.rs | 610 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 862 insertions(+), 843 deletions(-) delete mode 100644 src/utils.rs create mode 100644 src/utils/hir.rs create mode 100644 src/utils/mod.rs diff --git a/src/copies.rs b/src/copies.rs index 525c7b7a6fd..b1ea8f0c347 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,6 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{get_parent_expr, in_macro, is_block_equal, is_exp_equal, span_lint, span_note_and_lint}; +use utils::SpanlessEq; +use utils::{get_parent_expr, in_macro, span_lint, span_note_and_lint}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is /// `Warn` by default. @@ -55,7 +56,7 @@ impl LateLintPass for CopyAndPaste { fn lint_same_then_else(cx: &LateContext, expr: &Expr) { if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node { if let ExprBlock(ref else_block) = else_expr.node { - if is_block_equal(cx, &then_block, &else_block, false) { + if SpanlessEq::new(cx).eq_block(&then_block, &else_block) { span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks"); } } @@ -75,7 +76,7 @@ fn lint_same_cond(cx: &LateContext, expr: &Expr) { for (n, i) in conds.iter().enumerate() { for j in conds.iter().skip(n+1) { - if is_exp_equal(cx, i, j, true) { + if SpanlessEq::new(cx).ignore_fn().eq_expr(i, j) { span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); } } diff --git a/src/entry.rs b/src/entry.rs index d5bb086fc21..c2f2e956e5e 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,8 +1,9 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use utils::{get_item_name, is_exp_equal, match_type, snippet, span_lint_and_then, walk_ptrs_ty}; +use utils::SpanlessEq; use utils::{BTREEMAP_PATH, HASHMAP_PATH}; +use utils::{get_item_name, match_type, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or /// `BTreeMap`. @@ -89,7 +90,7 @@ fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: params.len() == 3, name.node.as_str() == "insert", get_item_name(cx, map) == get_item_name(cx, &*params[0]), - is_exp_equal(cx, key, ¶ms[1], false) + SpanlessEq::new(cx).eq_expr(key, ¶ms[1]) ], { let help = if sole_expr { format!("{}.entry({}).or_insert({})", diff --git a/src/eq_op.rs b/src/eq_op.rs index aecd0693ff1..fc1cab2cd71 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc_front::util as ast_util; -use utils::{is_exp_equal, span_lint}; +use utils::{SpanlessEq, span_lint}; /// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, /// difference and division binary operators (`==`, `>`, etc., `&&`, `||`, `&`, `|`, `^`, `-` and @@ -31,7 +31,7 @@ impl LintPass for EqOp { impl LateLintPass for EqOp { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_valid_operator(op) && is_exp_equal(cx, left, right, true) { + if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { span_lint(cx, EQ_OP, e.span, diff --git a/src/strings.rs b/src/strings.rs index b78db7f4b77..40d137101a6 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -7,7 +7,8 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::{is_exp_equal, match_type, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::SpanlessEq; use utils::STRING_PATH; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). @@ -84,7 +85,7 @@ impl LateLintPass for StringAdd { if let Some(ref p) = parent { if let ExprAssign(ref target, _) = p.node { // avoid duplicate matches - if is_exp_equal(cx, target, left, false) { + if SpanlessEq::new(cx).eq_expr(target, left) { return; } } @@ -113,7 +114,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(cx, target, left, false), + ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) } diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 9adbff90e66..00000000000 --- a/src/utils.rs +++ /dev/null @@ -1,833 +0,0 @@ -use consts::constant; -use reexport::*; -use rustc::front::map::Node; -use rustc::lint::{LintContext, LateContext, Level, Lint}; -use rustc::middle::def_id::DefId; -use rustc::middle::{cstore, def, infer, ty, traits}; -use rustc::session::Session; -use rustc_front::hir::*; -use std::borrow::Cow; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::str::FromStr; -use syntax::ast::Lit_; -use syntax::ast; -use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; -use syntax::errors::DiagnosticBuilder; -use syntax::ptr::P; - -pub type MethodArgs = HirVec<P<Expr>>; - -// module DefPaths for certain structs/enums we check for -pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; -pub const BOX_NEW_PATH: [&'static str; 4] = ["std", "boxed", "Box", "new"]; -pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; -pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; -pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; -pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; -pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; -pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; -pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; -pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; -pub const FMT_ARGUMENTV1_NEW_PATH: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; -pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; -pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; -pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; -pub const IO_PRINT_PATH: [&'static str; 3] = ["std", "io", "_print"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; -pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; -pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; -pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; -pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; - -/// Produce a nested chain of if-lets and ifs from the patterns: -/// -/// if_let_chain! { -/// [ -/// let Some(y) = x, -/// y.len() == 2, -/// let Some(z) = y, -/// ], -/// { -/// block -/// } -/// } -/// -/// becomes -/// -/// if let Some(y) = x { -/// if y.len() == 2 { -/// if let Some(z) = y { -/// block -/// } -/// } -/// } -#[macro_export] -macro_rules! if_let_chain { - ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { - if let $pat = $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([let $pat:pat = $expr:expr], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([$expr:expr, $($tt:tt)+], $block:block) => { - if $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([$expr:expr], $block:block) => { - if $expr { - $block - } - }; -} - -/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one -/// isn't). -pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { - sp1.expn_id != sp2.expn_id -} -/// Returns true if this `expn_info` was expanded by any macro. -pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) -} - -/// Returns true if the macro that expanded the crate was outside of the current crate or was a -/// compiler plugin. -pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { - /// Invokes in_macro with the expansion info of the given span slightly heavy, try to use this - /// after other checks have already happened. - fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { - // no ExpnInfo = no macro - opt_info.map_or(false, |info| { - if let ExpnFormat::MacroAttribute(..) = info.callee.format { - // these are all plugins - return true; - } - // no span for the callee = external macro - info.callee.span.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) - }) - }) - } - - cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) -} - -/// Check if a `DefId`'s path matches the given absolute type path usage. -/// -/// # Examples -/// ``` -/// match_def_path(cx, id, &["core", "option", "Option"]) -/// ``` -pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| { - iter.zip(path) - .all(|(nm, p)| nm.name().as_str() == *p) - }) -} - -/// Check if type is struct or enum type with given def path. -pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { - match ty.sty { - ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), - _ => false, - } -} - -/// Check if the method call given in `expr` belongs to given type. -pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tcx - .tables - .borrow() - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); - if let Some(trt_id) = trt_id { - match_def_path(cx, trt_id, path) - } else { - false - } -} - -/// Check if the method call given in `expr` belongs to given trait. -pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tcx - .tables - .borrow() - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); - if let Some(trt_id) = trt_id { - match_def_path(cx, trt_id, path) - } else { - false - } -} - -/// Match a `Path` against a slice of segment string literals. -/// -/// # Examples -/// ``` -/// match_path(path, &["std", "rt", "begin_unwind"]) -/// ``` -pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) -} - -/// Match a `Path` against a slice of segment string literals, e.g. -/// -/// # Examples -/// ``` -/// match_path(path, &["std", "rt", "begin_unwind"]) -/// ``` -pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) -} - -/// Get the definition associated to a path. -/// TODO: investigate if there is something more efficient for that. -pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { - let cstore = &cx.tcx.sess.cstore; - - let crates = cstore.crates(); - let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); - if let Some(krate) = krate { - let mut items = cstore.crate_top_level_items(*krate); - let mut path_it = path.iter().skip(1).peekable(); - - loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; - - for item in &mem::replace(&mut items, vec![]) { - if item.name.as_str() == *segment { - if path_it.peek().is_none() { - return Some(item.def); - } - - let def_id = match item.def { - cstore::DefLike::DlDef(def) => def.def_id(), - cstore::DefLike::DlImpl(def_id) => def_id, - _ => panic!("Unexpected {:?}", item.def), - }; - - items = cstore.item_children(def_id); - break; - } - } - } - } else { - None - } -} - -/// Convenience function to get the `DefId` of a trait by path. -pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { - let def = match path_to_def(cx, path) { - Some(def) => def, - None => return None, - }; - - match def { - cstore::DlDef(def::Def::Trait(trait_id)) => Some(trait_id), - _ => None, - } -} - -/// Check whether a type implements a trait. -/// See also `get_trait_def_id`. -pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, - ty_params: Option<Vec<ty::Ty<'tcx>>>) - -> bool { - cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); - - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); - let obligation = traits::predicate_for_trait_def(cx.tcx, - traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params.unwrap_or_default()); - - traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) -} - -/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. -/// -/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for -/// `.bar()` and `.baz()` -pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { - let mut current = expr; - let mut matched = Vec::with_capacity(methods.len()); - for method_name in methods.iter().rev() { - // method chains are stored last -> first - if let ExprMethodCall(ref name, _, ref args) = current.node { - if name.node.as_str() == *method_name { - matched.push(args); // build up `matched` backwards - current = &args[0] // go to parent expression - } else { - return None; - } - } else { - return None; - } - } - matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` - Some(matched) -} - - -/// Get the name of the item the expression is in, if available. -pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { - let parent_id = cx.tcx.map.get_parent(expr.id); - match cx.tcx.map.find(parent_id) { - Some(Node::NodeItem(&Item{ ref name, .. })) | - Some(Node::NodeTraitItem(&TraitItem{ ref name, .. })) | - Some(Node::NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), - _ => None, - } -} - -/// Checks if a `let` decl is from a `for` loop desugaring. -pub fn is_from_for_desugar(decl: &Decl) -> bool { - if_let_chain! { - [ - let DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node - ], - { return true; } - }; - false -} - - -/// Convert a span to a code snippet if available, otherwise use default. -/// -/// # Example -/// ``` -/// snippet(cx, expr.span, "..") -/// ``` -pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default)) -} - -/// Convert a span to a code snippet. Returns `None` if not available. -pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { - cx.sess().codemap().span_to_snippet(span).ok() -} - -/// Convert a span (from a block) to a code snippet if available, otherwise use default. -/// This trims the code of indentation, except for the first line. Use it for blocks or block-like -/// things which need to be printed as such. -/// -/// # Example -/// ``` -/// snippet(cx, expr.span, "..") -/// ``` -pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - let snip = snippet(cx, span, default); - trim_multiline(snip, true) -} - -/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. -/// Also takes an `Option<String>` which can be put inside the braces. -pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { - let code = snippet_block(cx, expr.span, default); - let string = option.unwrap_or_default(); - if let ExprBlock(_) = expr.node { - Cow::Owned(format!("{}{}", code, string)) - } else if string.is_empty() { - Cow::Owned(format!("{{ {} }}", code)) - } else { - Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) - } -} - -/// Trim indentation from a multiline string with possibility of ignoring the first line. -pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { - let s_space = trim_multiline_inner(s, ignore_first, ' '); - let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); - trim_multiline_inner(s_tab, ignore_first, ' ') -} - -fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { - let x = s.lines() - .skip(ignore_first as usize) - .filter_map(|l| { - if l.len() > 0 { - // ignore empty lines - Some(l.char_indices() - .find(|&(_, x)| x != ch) - .unwrap_or((l.len(), ch)) - .0) - } else { - None - } - }) - .min() - .unwrap_or(0); - if x > 0 { - Cow::Owned(s.lines() - .enumerate() - .map(|(i, l)| { - if (ignore_first && i == 0) || l.len() == 0 { - l - } else { - l.split_at(x).1 - } - }) - .collect::<Vec<_>>() - .join("\n")) - } else { - s - } -} - -/// Get a parent expressions if any – this is useful to constrain a lint. -pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { - let map = &cx.tcx.map; - let node_id: NodeId = e.id; - let parent_id: NodeId = map.get_parent_node(node_id); - if node_id == parent_id { - return None; - } - map.find(parent_id).and_then(|node| { - if let Node::NodeExpr(parent) = node { - Some(parent) - } else { - None - } - }) -} - -pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { - let map = &cx.tcx.map; - let enclosing_node = map.get_enclosing_scope(node) - .and_then(|enclosing_id| map.find(enclosing_id)); - if let Some(node) = enclosing_node { - match node { - Node::NodeBlock(ref block) => Some(block), - Node::NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), - _ => None, - } - } else { - None - } -} - -pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); - -impl<'a> Drop for DiagnosticWrapper<'a> { - fn drop(&mut self) { - self.0.emit(); - } -} - -impl<'a> DerefMut for DiagnosticWrapper<'a> { - fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { - &mut self.0 - } -} - -impl<'a> Deref for DiagnosticWrapper<'a> { - type Target = DiagnosticBuilder<'a>; - fn deref(&self) -> &DiagnosticBuilder<'a> { - &self.0 - } -} - -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, sp, msg); - if cx.current_level(lint) != Level::Allow { - db.fileline_help(sp, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); - } - DiagnosticWrapper(db) -} - -pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) - -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, span, msg); - if cx.current_level(lint) != Level::Allow { - db.fileline_help(span, - &format!("{}\nfor further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - help, - lint.name_lower())); - } - DiagnosticWrapper(db) -} - -pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, - note: &str) - -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, span, msg); - if cx.current_level(lint) != Level::Allow { - if note_span == span { - db.fileline_note(note_span, note); - } else { - db.span_note(note_span, note); - } - db.fileline_help(span, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); - } - DiagnosticWrapper(db) -} - -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) - -> DiagnosticWrapper<'a> - where F: FnOnce(&mut DiagnosticWrapper) -{ - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - if cx.current_level(lint) != Level::Allow { - f(&mut db); - db.fileline_help(sp, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); - } - db -} - -/// Return the base type for references and raw pointers. -pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { - match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), - _ => ty, - } -} - -/// Return the base type for references and raw pointers, and count reference depth. -pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { - fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { - match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), - _ => (ty, depth), - } - } - inner(ty, 0) -} - -/// Check whether the given expression is a constant literal of the given value. -pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { - // FIXME: use constant folding - if let ExprLit(ref spanned) = expr.node { - if let Lit_::LitInt(v, _) = spanned.node { - return v == value; - } - } - false -} - -pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { - cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() -} - -pub struct LimitStack { - stack: Vec<u64>, -} - -impl Drop for LimitStack { - fn drop(&mut self) { - assert_eq!(self.stack.len(), 1); - } -} - -impl LimitStack { - pub fn new(limit: u64) -> LimitStack { - LimitStack { stack: vec![limit] } - } - pub fn limit(&self) -> u64 { - *self.stack.last().expect("there should always be a value in the stack") - } - pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { - let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| stack.push(val)); - } - pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { - let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); - } -} - -fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { - for attr in attrs { - let attr = &attr.node; - if attr.is_sugared_doc { - continue; - } - if let ast::MetaNameValue(ref key, ref value) = attr.value.node { - if *key == name { - if let Lit_::LitStr(ref s, _) = value.node { - if let Ok(value) = FromStr::from_str(s) { - f(value) - } else { - sess.span_err(value.span, "not a number"); - } - } else { - unreachable!() - } - } - } - } -} - -/// Check whether two statements are the same. -/// See also `is_exp_equal`. -pub fn is_stmt_equal(cx: &LateContext, left: &Stmt, right: &Stmt, ignore_fn: bool) -> bool { - match (&left.node, &right.node) { - (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { - if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { - // TODO: tys - l.ty.is_none() && r.ty.is_none() && - both(&l.init, &r.init, |l, r| is_exp_equal(cx, l, r, ignore_fn)) - } - else { - false - } - } - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => is_exp_equal(cx, l, r, ignore_fn), - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => is_exp_equal(cx, l, r, ignore_fn), - _ => false, - } -} - -/// Check whether two blocks are the same. -/// See also `is_exp_equal`. -pub fn is_block_equal(cx: &LateContext, left: &Block, right: &Block, ignore_fn: bool) -> bool { - over(&left.stmts, &right.stmts, |l, r| is_stmt_equal(cx, l, r, ignore_fn)) && - both(&left.expr, &right.expr, |l, r| is_exp_equal(cx, l, r, ignore_fn)) -} - -/// Check whether two pattern are the same. -/// See also `is_exp_equal`. -pub fn is_pat_equal(cx: &LateContext, left: &Pat, right: &Pat, ignore_fn: bool) -> bool { - match (&left.node, &right.node) { - (&PatBox(ref l), &PatBox(ref r)) => { - is_pat_equal(cx, l, r, ignore_fn) - } - (&PatEnum(ref lp, ref la), &PatEnum(ref rp, ref ra)) => { - is_path_equal(lp, rp) && - both(la, ra, |l, r| { - over(l, r, |l, r| is_pat_equal(cx, l, r, ignore_fn)) - }) - } - (&PatIdent(ref lb, ref li, ref lp), &PatIdent(ref rb, ref ri, ref rp)) => { - lb == rb && li.node.name.as_str() == ri.node.name.as_str() && - both(lp, rp, |l, r| is_pat_equal(cx, l, r, ignore_fn)) - } - (&PatLit(ref l), &PatLit(ref r)) => { - is_exp_equal(cx, l, r, ignore_fn) - } - (&PatQPath(ref ls, ref lp), &PatQPath(ref rs, ref rp)) => { - is_qself_equal(ls, rs) && is_path_equal(lp, rp) - } - (&PatTup(ref l), &PatTup(ref r)) => { - over(l, r, |l, r| is_pat_equal(cx, l, r, ignore_fn)) - } - (&PatRange(ref ls, ref le), &PatRange(ref rs, ref re)) => { - is_exp_equal(cx, ls, rs, ignore_fn) && - is_exp_equal(cx, le, re, ignore_fn) - } - (&PatRegion(ref le, ref lm), &PatRegion(ref re, ref rm)) => { - lm == rm && is_pat_equal(cx, le, re, ignore_fn) - } - (&PatVec(ref ls, ref li, ref le), &PatVec(ref rs, ref ri, ref re)) => { - over(ls, rs, |l, r| is_pat_equal(cx, l, r, ignore_fn)) && - over(le, re, |l, r| is_pat_equal(cx, l, r, ignore_fn)) && - both(li, ri, |l, r| is_pat_equal(cx, l, r, ignore_fn)) - } - (&PatWild, &PatWild) => true, - _ => false, - } -} - -/// Check whether two expressions are the same. This is different from the operator `==` on -/// expression as this operator would compare true equality with ID and span. -/// If `ignore_fn` is true, never consider as equal fonction calls. -/// -/// Note that some expression kinds are not considered but could be added. -#[allow(cyclomatic_complexity)] // ok, it’s a big function, but mostly one big match with simples cases -pub fn is_exp_equal(cx: &LateContext, left: &Expr, right: &Expr, ignore_fn: bool) -> bool { - if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) { - if l == r { - return true; - } - } - - match (&left.node, &right.node) { - (&ExprAddrOf(ref lmut, ref le), &ExprAddrOf(ref rmut, ref re)) => { - lmut == rmut && is_exp_equal(cx, le, re, ignore_fn) - } - (&ExprAgain(li), &ExprAgain(ri)) => { - both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) - } - (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => { - is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) - } - (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { - lo.node == ro.node && is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) - } - (&ExprBlock(ref l), &ExprBlock(ref r)) => { - is_block_equal(cx, l, r, ignore_fn) - } - (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { - lop.node == rop.node && is_exp_equal(cx, ll, rl, ignore_fn) && is_exp_equal(cx, lr, rr, ignore_fn) - } - (&ExprBreak(li), &ExprBreak(ri)) => { - both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) - } - (&ExprBox(ref l), &ExprBox(ref r)) => { - is_exp_equal(cx, l, r, ignore_fn) - } - (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { - !ignore_fn && - is_exp_equal(cx, lfun, rfun, ignore_fn) && - is_exps_equal(cx, largs, rargs, ignore_fn) - } - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => { - is_exp_equal(cx, lx, rx, ignore_fn) && is_cast_ty_equal(lt, rt) - } - (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { - lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp, ignore_fn) - } - (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { - is_exp_equal(cx, la, ra, ignore_fn) && is_exp_equal(cx, li, ri, ignore_fn) - } - (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { - is_exp_equal(cx, lc, rc, ignore_fn) && - is_block_equal(cx, lt, rt, ignore_fn) && - both(le, re, |l, r| is_exp_equal(cx, l, r, ignore_fn)) - } - (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { - is_exp_equal(cx, la, ra) && is_exp_equal(cx, li, ri) - } - (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { - ls == rs && - is_exp_equal(cx, le, re, ignore_fn) && - over(la, ra, |l, r| { - is_exp_equal(cx, &l.body, &r.body, ignore_fn) && - both(&l.guard, &r.guard, |l, r| is_exp_equal(cx, l, r, ignore_fn)) && - over(&l.pats, &r.pats, |l, r| is_pat_equal(cx, l, r, ignore_fn)) - }) - } - (&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { - // TODO: tys - !ignore_fn && - lname.node == rname.node && - ltys.is_empty() && - rtys.is_empty() && - is_exps_equal(cx, largs, rargs, ignore_fn) - } - (&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => { - both(lb, rb, |l, r| is_exp_equal(cx, l, r, ignore_fn)) && - both(le, re, |l, r| is_exp_equal(cx, l, r, ignore_fn)) - } - (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => { - is_exp_equal(cx, le, re, ignore_fn) && is_exp_equal(cx, ll, rl, ignore_fn) - } - (&ExprRet(ref l), &ExprRet(ref r)) => { - both(l, r, |l, r| is_exp_equal(cx, l, r, ignore_fn)) - } - (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { - both(lqself, rqself, is_qself_equal) && is_path_equal(lsubpath, rsubpath) - } - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(cx, ltup, rtup, ignore_fn), - (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => { - li.node == ri.node && is_exp_equal(cx, le, re, ignore_fn) - } - (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => { - lop == rop && is_exp_equal(cx, le, re, ignore_fn) - } - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r, ignore_fn), - (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - is_exp_equal(cx, lc, rc, ignore_fn) && - is_block_equal(cx, lb, rb, ignore_fn) && - both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) - } - _ => false, - } -} - -fn is_exps_equal(cx: &LateContext, left: &[P<Expr>], right: &[P<Expr>], ignore_fn: bool) -> bool { - over(left, right, |l, r| is_exp_equal(cx, l, r, ignore_fn)) -} - -fn is_path_equal(left: &Path, right: &Path) -> bool { - // The == of idents doesn't work with different contexts, - // we have to be explicit about hygiene - left.global == right.global && - over(&left.segments, - &right.segments, - |l, r| l.identifier.name.as_str() == r.identifier.name.as_str() && l.parameters == r.parameters) -} - -fn is_qself_equal(left: &QSelf, right: &QSelf) -> bool { - left.ty.node == right.ty.node && left.position == right.position -} - -/// Check if two slices are equal as per `eq_fn`. -pub fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool -{ - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) -} - -/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. -pub fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool -{ - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) -} - -fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool { - match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => lmut.mutbl == rmut.mutbl && is_cast_ty_equal(&*lmut.ty, &*rmut.ty), - (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => { - lrmut.mutbl == rrmut.mutbl && is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty) - } - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => { - both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath) - } - (&TyInfer, &TyInfer) => true, - _ => false, - } -} - -/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. -pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { - loop { - let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| { - expn.map(|ei| { - (ei.callee.name(), ei.call_site) - }) - }); - - match span_name_span { - Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), - None => return None, - Some((_, new_span)) => span = new_span, - } - } -} diff --git a/src/utils/hir.rs b/src/utils/hir.rs new file mode 100644 index 00000000000..95356772e60 --- /dev/null +++ b/src/utils/hir.rs @@ -0,0 +1,239 @@ +use consts::constant; +use rustc::lint::*; +use rustc_front::hir::*; +use syntax::ptr::P; + +/// Type used to check whether two ast are the same. This is different from the operator +/// `==` on ast types as this operator would compare true equality with ID and span. +/// +/// Note that some expressions kinds are not considered but could be added. +pub struct SpanlessEq<'a, 'tcx: 'a> { + /// Context used to evaluate constant expressions. + cx: &'a LateContext<'a, 'tcx>, + /// If is true, never consider as equal expressions containing fonction calls. + ignore_fn: bool, +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + SpanlessEq { cx: cx, ignore_fn: false } + } + + pub fn ignore_fn(self) -> Self { + SpanlessEq { cx: self.cx, ignore_fn: true } + } + + /// Check whether two statements are the same. + pub fn eq_stmt(&self, left: &Stmt, right: &Stmt) -> bool { + match (&left.node, &right.node) { + (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { + if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { + // TODO: tys + l.ty.is_none() && r.ty.is_none() && + both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + } + else { + false + } + } + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => self.eq_expr(l, r), + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + _ => false, + } + } + + /// Check whether two blocks are the same. + pub fn eq_block(&self, left: &Block, right: &Block) -> bool { + over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && + both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) + } + + // ok, it’s a big function, but mostly one big match with simples cases + #[allow(cyclomatic_complexity)] + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + if let (Some(l), Some(r)) = (constant(self.cx, left), constant(self.cx, right)) { + if l == r { + return true; + } + } + + match (&left.node, &right.node) { + (&ExprAddrOf(ref lmut, ref le), &ExprAddrOf(ref rmut, ref re)) => { + lmut == rmut && self.eq_expr(le, re) + } + (&ExprAgain(li), &ExprAgain(ri)) => { + both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) + } + (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => { + self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + } + (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { + lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + } + (&ExprBlock(ref l), &ExprBlock(ref r)) => { + self.eq_block(l, r) + } + (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { + lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + } + (&ExprBreak(li), &ExprBreak(ri)) => { + both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) + } + (&ExprBox(ref l), &ExprBox(ref r)) => { + self.eq_expr(l, r) + } + (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { + !self.ignore_fn && + self.eq_expr(lfun, rfun) && + self.eq_exprs(largs, rargs) + } + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => { + self.eq_expr(lx, rx) && self.eq_ty(lt, rt) + } + (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { + lfident.node == rfident.node && self.eq_expr(lfexp, rfexp) + } + (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { + self.eq_expr(la, ra) && self.eq_expr(li, ri) + } + (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { + self.eq_expr(lc, rc) && + self.eq_block(lt, rt) && + both(le, re, |l, r| self.eq_expr(l, r)) + } + (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { + ls == rs && + self.eq_expr(le, re) && + over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && + both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) + } + (&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { + // TODO: tys + !self.ignore_fn && + lname.node == rname.node && + ltys.is_empty() && + rtys.is_empty() && + self.eq_exprs(largs, rargs) + } + (&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => { + both(lb, rb, |l, r| self.eq_expr(l, r)) && + both(le, re, |l, r| self.eq_expr(l, r)) + } + (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => { + self.eq_expr(le, re) && self.eq_expr(ll, rl) + } + (&ExprRet(ref l), &ExprRet(ref r)) => { + both(l, r, |l, r| self.eq_expr(l, r)) + } + (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { + both(lqself, rqself, |l, r| self.eq_qself(l, r)) && self.eq_path(lsubpath, rsubpath) + } + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => self.eq_exprs(ltup, rtup), + (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => { + li.node == ri.node && self.eq_expr(le, re) + } + (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => { + lop == rop && self.eq_expr(le, re) + } + (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), + (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { + self.eq_expr(lc, rc) && + self.eq_block(lb, rb) && + both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + } + _ => false, + } + } + + fn eq_exprs(&self, left: &[P<Expr>], right: &[P<Expr>]) -> bool { + over(left, right, |l, r| self.eq_expr(l, r)) + } + + /// Check whether two patterns are the same. + pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { + match (&left.node, &right.node) { + (&PatBox(ref l), &PatBox(ref r)) => { + self.eq_pat(l, r) + } + (&PatEnum(ref lp, ref la), &PatEnum(ref rp, ref ra)) => { + self.eq_path(lp, rp) && + both(la, ra, |l, r| { + over(l, r, |l, r| self.eq_pat(l, r)) + }) + } + (&PatIdent(ref lb, ref li, ref lp), &PatIdent(ref rb, ref ri, ref rp)) => { + lb == rb && li.node.name.as_str() == ri.node.name.as_str() && + both(lp, rp, |l, r| self.eq_pat(l, r)) + } + (&PatLit(ref l), &PatLit(ref r)) => { + self.eq_expr(l, r) + } + (&PatQPath(ref ls, ref lp), &PatQPath(ref rs, ref rp)) => { + self.eq_qself(ls, rs) && self.eq_path(lp, rp) + } + (&PatTup(ref l), &PatTup(ref r)) => { + over(l, r, |l, r| self.eq_pat(l, r)) + } + (&PatRange(ref ls, ref le), &PatRange(ref rs, ref re)) => { + self.eq_expr(ls, rs) && + self.eq_expr(le, re) + } + (&PatRegion(ref le, ref lm), &PatRegion(ref re, ref rm)) => { + lm == rm && self.eq_pat(le, re) + } + (&PatVec(ref ls, ref li, ref le), &PatVec(ref rs, ref ri, ref re)) => { + over(ls, rs, |l, r| self.eq_pat(l, r)) && + over(le, re, |l, r| self.eq_pat(l, r)) && + both(li, ri, |l, r| self.eq_pat(l, r)) + } + (&PatWild, &PatWild) => true, + _ => false, + } + } + + fn eq_path(&self, left: &Path, right: &Path) -> bool { + // The == of idents doesn't work with different contexts, + // we have to be explicit about hygiene + left.global == right.global && + over(&left.segments, + &right.segments, + |l, r| l.identifier.name.as_str() == r.identifier.name.as_str() && l.parameters == r.parameters) + } + + fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool { + left.ty.node == right.ty.node && left.position == right.position + } + + fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { + match (&left.node, &right.node) { + (&TyVec(ref lvec), &TyVec(ref rvec)) => self.eq_ty(lvec, rvec), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => lmut.mutbl == rmut.mutbl && self.eq_ty(&*lmut.ty, &*rmut.ty), + (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => { + lrmut.mutbl == rrmut.mutbl && self.eq_ty(&*lrmut.ty, &*rrmut.ty) + } + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => { + both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(lpath, rpath) + } + (&TyInfer, &TyInfer) => true, + _ => false, + } + } +} + +/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. +fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool +{ + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) +} + +/// Check if two slices are equal as per `eq_fn`. +fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool +{ + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 00000000000..d666ee36bce --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,610 @@ +use reexport::*; +use rustc::front::map::Node; +use rustc::lint::{LintContext, LateContext, Level, Lint}; +use rustc::middle::def_id::DefId; +use rustc::middle::{cstore, def, infer, ty, traits}; +use rustc::session::Session; +use rustc_front::hir::*; +use std::borrow::Cow; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::str::FromStr; +use syntax::ast::Lit_; +use syntax::ast; +use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; +use syntax::errors::DiagnosticBuilder; +use syntax::ptr::P; + +mod hir; +pub use self::hir::SpanlessEq; +pub type MethodArgs = HirVec<P<Expr>>; + +// module DefPaths for certain structs/enums we check for +pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BOX_NEW_PATH: [&'static str; 4] = ["std", "boxed", "Box", "new"]; +pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; +pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; +pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; +pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; +pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; +pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; +pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTV1_NEW_PATH: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; +pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; +pub const IO_PRINT_PATH: [&'static str; 3] = ["std", "io", "_print"]; +pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; +pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; +pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; +pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; + +/// Produce a nested chain of if-lets and ifs from the patterns: +/// +/// if_let_chain! { +/// [ +/// let Some(y) = x, +/// y.len() == 2, +/// let Some(z) = y, +/// ], +/// { +/// block +/// } +/// } +/// +/// becomes +/// +/// if let Some(y) = x { +/// if y.len() == 2 { +/// if let Some(z) = y { +/// block +/// } +/// } +/// } +#[macro_export] +macro_rules! if_let_chain { + ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { + if let $pat = $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([let $pat:pat = $expr:expr], $block:block) => { + if let $pat = $expr { + $block + } + }; + ([$expr:expr, $($tt:tt)+], $block:block) => { + if $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([$expr:expr], $block:block) => { + if $expr { + $block + } + }; +} + +/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one +/// isn't). +pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { + sp1.expn_id != sp2.expn_id +} +/// Returns true if this `expn_info` was expanded by any macro. +pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { + cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) +} + +/// Returns true if the macro that expanded the crate was outside of the current crate or was a +/// compiler plugin. +pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { + /// Invokes in_macro with the expansion info of the given span slightly heavy, try to use this + /// after other checks have already happened. + fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { + // no ExpnInfo = no macro + opt_info.map_or(false, |info| { + if let ExpnFormat::MacroAttribute(..) = info.callee.format { + // these are all plugins + return true; + } + // no span for the callee = external macro + info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) + }) + }) + } + + cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) +} + +/// Check if a `DefId`'s path matches the given absolute type path usage. +/// +/// # Examples +/// ``` +/// match_def_path(cx, id, &["core", "option", "Option"]) +/// ``` +pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { + cx.tcx.with_path(def_id, |iter| { + iter.zip(path) + .all(|(nm, p)| nm.name().as_str() == *p) + }) +} + +/// Check if type is struct or enum type with given def path. +pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { + match ty.sty { + ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), + _ => false, + } +} + +/// Check if the method call given in `expr` belongs to given type. +pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} + +/// Check if the method call given in `expr` belongs to given trait. +pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} + +/// Match a `Path` against a slice of segment string literals. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` +pub fn match_path(path: &Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) +} + +/// Match a `Path` against a slice of segment string literals, e.g. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` +pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) +} + +/// Get the definition associated to a path. +/// TODO: investigate if there is something more efficient for that. +pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { + let cstore = &cx.tcx.sess.cstore; + + let crates = cstore.crates(); + let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); + if let Some(krate) = krate { + let mut items = cstore.crate_top_level_items(*krate); + let mut path_it = path.iter().skip(1).peekable(); + + loop { + let segment = match path_it.next() { + Some(segment) => segment, + None => return None, + }; + + for item in &mem::replace(&mut items, vec![]) { + if item.name.as_str() == *segment { + if path_it.peek().is_none() { + return Some(item.def); + } + + let def_id = match item.def { + cstore::DefLike::DlDef(def) => def.def_id(), + cstore::DefLike::DlImpl(def_id) => def_id, + _ => panic!("Unexpected {:?}", item.def), + }; + + items = cstore.item_children(def_id); + break; + } + } + } + } else { + None + } +} + +/// Convenience function to get the `DefId` of a trait by path. +pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { + let def = match path_to_def(cx, path) { + Some(def) => def, + None => return None, + }; + + match def { + cstore::DlDef(def::Def::Trait(trait_id)) => Some(trait_id), + _ => None, + } +} + +/// Check whether a type implements a trait. +/// See also `get_trait_def_id`. +pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, + ty_params: Option<Vec<ty::Ty<'tcx>>>) + -> bool { + cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); + + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); + let obligation = traits::predicate_for_trait_def(cx.tcx, + traits::ObligationCause::dummy(), + trait_id, + 0, + ty, + ty_params.unwrap_or_default()); + + traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) +} + +/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. +/// +/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, +/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for +/// `.bar()` and `.baz()` +pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { + let mut current = expr; + let mut matched = Vec::with_capacity(methods.len()); + for method_name in methods.iter().rev() { + // method chains are stored last -> first + if let ExprMethodCall(ref name, _, ref args) = current.node { + if name.node.as_str() == *method_name { + matched.push(args); // build up `matched` backwards + current = &args[0] // go to parent expression + } else { + return None; + } + } else { + return None; + } + } + matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` + Some(matched) +} + + +/// Get the name of the item the expression is in, if available. +pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { + let parent_id = cx.tcx.map.get_parent(expr.id); + match cx.tcx.map.find(parent_id) { + Some(Node::NodeItem(&Item{ ref name, .. })) | + Some(Node::NodeTraitItem(&TraitItem{ ref name, .. })) | + Some(Node::NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), + _ => None, + } +} + +/// Checks if a `let` decl is from a `for` loop desugaring. +pub fn is_from_for_desugar(decl: &Decl) -> bool { + if_let_chain! { + [ + let DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node + ], + { return true; } + }; + false +} + + +/// Convert a span to a code snippet if available, otherwise use default. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` +pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default)) +} + +/// Convert a span to a code snippet. Returns `None` if not available. +pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { + cx.sess().codemap().span_to_snippet(span).ok() +} + +/// Convert a span (from a block) to a code snippet if available, otherwise use default. +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like +/// things which need to be printed as such. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` +pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + let snip = snippet(cx, span, default); + trim_multiline(snip, true) +} + +/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. +/// Also takes an `Option<String>` which can be put inside the braces. +pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { + let code = snippet_block(cx, expr.span, default); + let string = option.unwrap_or_default(); + if let ExprBlock(_) = expr.node { + Cow::Owned(format!("{}{}", code, string)) + } else if string.is_empty() { + Cow::Owned(format!("{{ {} }}", code)) + } else { + Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) + } +} + +/// Trim indentation from a multiline string with possibility of ignoring the first line. +pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { + let s_space = trim_multiline_inner(s, ignore_first, ' '); + let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); + trim_multiline_inner(s_tab, ignore_first, ' ') +} + +fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { + let x = s.lines() + .skip(ignore_first as usize) + .filter_map(|l| { + if l.len() > 0 { + // ignore empty lines + Some(l.char_indices() + .find(|&(_, x)| x != ch) + .unwrap_or((l.len(), ch)) + .0) + } else { + None + } + }) + .min() + .unwrap_or(0); + if x > 0 { + Cow::Owned(s.lines() + .enumerate() + .map(|(i, l)| { + if (ignore_first && i == 0) || l.len() == 0 { + l + } else { + l.split_at(x).1 + } + }) + .collect::<Vec<_>>() + .join("\n")) + } else { + s + } +} + +/// Get a parent expressions if any – this is useful to constrain a lint. +pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { + let map = &cx.tcx.map; + let node_id: NodeId = e.id; + let parent_id: NodeId = map.get_parent_node(node_id); + if node_id == parent_id { + return None; + } + map.find(parent_id).and_then(|node| { + if let Node::NodeExpr(parent) = node { + Some(parent) + } else { + None + } + }) +} + +pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { + let map = &cx.tcx.map; + let enclosing_node = map.get_enclosing_scope(node) + .and_then(|enclosing_id| map.find(enclosing_id)); + if let Some(node) = enclosing_node { + match node { + Node::NodeBlock(ref block) => Some(block), + Node::NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), + _ => None, + } + } else { + None + } +} + +pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); + +impl<'a> Drop for DiagnosticWrapper<'a> { + fn drop(&mut self) { + self.0.emit(); + } +} + +impl<'a> DerefMut for DiagnosticWrapper<'a> { + fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { + &mut self.0 + } +} + +impl<'a> Deref for DiagnosticWrapper<'a> { + type Target = DiagnosticBuilder<'a>; + fn deref(&self) -> &DiagnosticBuilder<'a> { + &self.0 + } +} + +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, sp, msg); + if cx.current_level(lint) != Level::Allow { + db.fileline_help(sp, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } + DiagnosticWrapper(db) +} + +pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) + -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, span, msg); + if cx.current_level(lint) != Level::Allow { + db.fileline_help(span, + &format!("{}\nfor further information visit \ + https://github.com/Manishearth/rust-clippy/wiki#{}", + help, + lint.name_lower())); + } + DiagnosticWrapper(db) +} + +pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, + note: &str) + -> DiagnosticWrapper<'a> { + let mut db = cx.struct_span_lint(lint, span, msg); + if cx.current_level(lint) != Level::Allow { + if note_span == span { + db.fileline_note(note_span, note); + } else { + db.span_note(note_span, note); + } + db.fileline_help(span, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } + DiagnosticWrapper(db) +} + +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) + -> DiagnosticWrapper<'a> + where F: FnOnce(&mut DiagnosticWrapper) +{ + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); + if cx.current_level(lint) != Level::Allow { + f(&mut db); + db.fileline_help(sp, + &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } + db +} + +/// Return the base type for references and raw pointers. +pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { + match ty.sty { + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), + _ => ty, + } +} + +/// Return the base type for references and raw pointers, and count reference depth. +pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { + fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { + match ty.sty { + ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), + _ => (ty, depth), + } + } + inner(ty, 0) +} + +/// Check whether the given expression is a constant literal of the given value. +pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { + // FIXME: use constant folding + if let ExprLit(ref spanned) = expr.node { + if let Lit_::LitInt(v, _) = spanned.node { + return v == value; + } + } + false +} + +pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { + cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() +} + +pub struct LimitStack { + stack: Vec<u64>, +} + +impl Drop for LimitStack { + fn drop(&mut self) { + assert_eq!(self.stack.len(), 1); + } +} + +impl LimitStack { + pub fn new(limit: u64) -> LimitStack { + LimitStack { stack: vec![limit] } + } + pub fn limit(&self) -> u64 { + *self.stack.last().expect("there should always be a value in the stack") + } + pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs(sess, attrs, name, |val| stack.push(val)); + } + pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); + } +} + +fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { + for attr in attrs { + let attr = &attr.node; + if attr.is_sugared_doc { + continue; + } + if let ast::MetaNameValue(ref key, ref value) = attr.value.node { + if *key == name { + if let Lit_::LitStr(ref s, _) = value.node { + if let Ok(value) = FromStr::from_str(s) { + f(value) + } else { + sess.span_err(value.span, "not a number"); + } + } else { + unreachable!() + } + } + } + } +} + +/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. +pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { + loop { + let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| { + expn.map(|ei| { + (ei.callee.name(), ei.call_site) + }) + }); + + match span_name_span { + Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), + None => return None, + Some((_, new_span)) => span = new_span, + } + } +} -- cgit 1.4.1-3-g733a5 From afee209d5a85c41f02145869ca360f23a69344d1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 6 Feb 2016 22:41:12 +0100 Subject: Add missing ExprLoop to SpanlessEq --- src/utils/hir.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 95356772e60..457f11a0d26 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } match (&left.node, &right.node) { - (&ExprAddrOf(ref lmut, ref le), &ExprAddrOf(ref rmut, ref re)) => { + (&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => { lmut == rmut && self.eq_expr(le, re) } (&ExprAgain(li), &ExprAgain(ri)) => { @@ -102,6 +102,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { both(le, re, |l, r| self.eq_expr(l, r)) } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { + self.eq_block(lb, rb) && + both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + + } (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && -- cgit 1.4.1-3-g733a5 From 88beb351940e888932b30c555c273f18a0254aff Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 9 Feb 2016 15:18:27 +0100 Subject: Implement Expr spanless-hashing --- src/consts.rs | 4 +- src/copies.rs | 93 ++++++++++---- src/utils/hir.rs | 287 +++++++++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 2 +- tests/compile-fail/copies.rs | 6 + 5 files changed, 364 insertions(+), 28 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index ddc8560c9b3..4469853ddf9 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -17,7 +17,7 @@ use syntax::ast::{UintTy, FloatTy, StrStyle}; use syntax::ast::Sign::{self, Plus, Minus}; -#[derive(PartialEq, Eq, Debug, Copy, Clone)] +#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)] pub enum FloatWidth { Fw32, Fw64, @@ -34,7 +34,7 @@ impl From<FloatTy> for FloatWidth { } /// a Lit_-like enum to fold constant `Expr`s into -#[derive(Eq, Debug, Clone)] +#[derive(Eq, Debug, Clone, Hash)] pub enum Constant { /// a String "abc" Str(String, StrStyle), diff --git a/src/copies.rs b/src/copies.rs index b1ea8f0c347..1899b47accd 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,6 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::SpanlessEq; +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use utils::{SpanlessEq, SpanlessHash}; use utils::{get_parent_expr, in_macro, span_lint, span_note_and_lint}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is @@ -46,8 +48,16 @@ impl LintPass for CopyAndPaste { impl LateLintPass for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if !in_macro(cx, expr.span) { + // skip ifs directly in else, it will be checked in the parent if + if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { + if else_expr.id == expr.id { + return; + } + } + + let (conds, blocks) = if_sequence(expr); lint_same_then_else(cx, expr); - lint_same_cond(cx, expr); + lint_same_cond(cx, &conds); } } } @@ -64,32 +74,22 @@ fn lint_same_then_else(cx: &LateContext, expr: &Expr) { } /// Implementation of `IFS_SAME_COND`. -fn lint_same_cond(cx: &LateContext, expr: &Expr) { - // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { - if else_expr.id == expr.id { - return; - } - } - - let conds = condition_sequence(expr); - - for (n, i) in conds.iter().enumerate() { - for j in conds.iter().skip(n+1) { - if SpanlessEq::new(cx).ignore_fn().eq_expr(i, j) { - span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); - } - } +fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { + if let Some((i, j)) = search_same(cx, conds) { + span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); } } -/// Return the list of condition expressions in a sequence of `if/else`. -/// Eg. would return `[a, b]` for the expression `if a {..} else if b {..}`. -fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> { - let mut result = vec![]; +/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`. +/// Eg. would return `([a, b], [c, d, e])` for the expression +/// `if a { c } else if b { d } else { e }`. +fn if_sequence(mut expr: &Expr) -> (Vec<&Expr>, Vec<&Block>) { + let mut conds = vec![]; + let mut blocks = vec![]; - while let ExprIf(ref cond, _, ref else_expr) = expr.node { - result.push(&**cond); + while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node { + conds.push(&**cond); + blocks.push(&**then_block); if let Some(ref else_expr) = *else_expr { expr = else_expr; @@ -99,5 +99,48 @@ fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> { } } - result + // final `else {..}` + if !blocks.is_empty() { + if let ExprBlock(ref block) = expr.node { + blocks.push(&**block); + } + } + + (conds, blocks) +} + +fn search_same<'a>(cx: &LateContext, exprs: &[&'a Expr]) -> Option<(&'a Expr, &'a Expr)> { + // common cases + if exprs.len() < 2 { + return None; + } + else if exprs.len() == 2 { + return if SpanlessEq::new(cx).ignore_fn().eq_expr(&exprs[0], &exprs[1]) { + Some((&exprs[0], &exprs[1])) + } + else { + None + } + } + + let mut map : HashMap<_, Vec<&'a _>> = HashMap::with_capacity(exprs.len()); + + for &expr in exprs { + let mut h = SpanlessHash::new(cx); + h.hash_expr(expr); + let h = h.finish(); + + match map.entry(h) { + Entry::Occupied(o) => { + for o in o.get() { + if SpanlessEq::new(cx).ignore_fn().eq_expr(o, expr) { + return Some((o, expr)) + } + } + } + Entry::Vacant(v) => { v.insert(vec![expr]); } + } + } + + None } diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 457f11a0d26..bd2aebfd013 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -1,6 +1,8 @@ use consts::constant; use rustc::lint::*; use rustc_front::hir::*; +use std::hash::{Hash, Hasher, SipHasher}; +use syntax::ast::Name; use syntax::ptr::P; /// Type used to check whether two ast are the same. This is different from the operator @@ -242,3 +244,288 @@ fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } + + +pub struct SpanlessHash<'a, 'tcx: 'a> { + /// Context used to evaluate constant expressions. + cx: &'a LateContext<'a, 'tcx>, + s: SipHasher, +} + +impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { + pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + SpanlessHash { cx: cx, s: SipHasher::new() } + } + + pub fn finish(&self) -> u64 { + self.s.finish() + } + + pub fn hash_block(&mut self, b: &Block) { + for s in &b.stmts { + self.hash_stmt(s); + } + + if let Some(ref e) = b.expr { + self.hash_expr(e); + } + + b.rules.hash(&mut self.s); + } + + pub fn hash_expr(&mut self, e: &Expr) { + if let Some(e) = constant(self.cx, e) { + return e.hash(&mut self.s); + } + + match e.node { + ExprAddrOf(m, ref e) => { + let c: fn(_, _) -> _ = ExprAddrOf; + c.hash(&mut self.s); + m.hash(&mut self.s); + self.hash_expr(e); + } + ExprAgain(i) => { + let c: fn(_) -> _ = ExprAgain; + c.hash(&mut self.s); + if let Some(i) = i { + self.hash_name(&i.node.name); + } + } + ExprAssign(ref l, ref r) => { + let c: fn(_, _) -> _ = ExprAssign; + c.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprAssignOp(ref o, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprAssignOp; + c.hash(&mut self.s); + o.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprBlock(ref b) => { + let c: fn(_) -> _ = ExprBlock; + c.hash(&mut self.s); + self.hash_block(b); + } + ExprBinary(op, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprBinary; + c.hash(&mut self.s); + op.node.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprBreak(i) => { + let c: fn(_) -> _ = ExprBreak; + c.hash(&mut self.s); + if let Some(i) = i { + self.hash_name(&i.node.name); + } + } + ExprBox(ref e) => { + let c: fn(_) -> _ = ExprBox; + c.hash(&mut self.s); + self.hash_expr(e); + } + ExprCall(ref fun, ref args) => { + let c: fn(_, _) -> _ = ExprCall; + c.hash(&mut self.s); + self.hash_expr(fun); + self.hash_exprs(args); + } + ExprCast(ref e, ref _ty) => { + let c: fn(_, _) -> _ = ExprCast; + c.hash(&mut self.s); + self.hash_expr(e); + // TODO: _ty + } + ExprClosure(cap, _, ref b) => { + let c: fn(_, _, _) -> _ = ExprClosure; + c.hash(&mut self.s); + cap.hash(&mut self.s); + self.hash_block(b); + } + ExprField(ref e, ref f) => { + let c: fn(_, _) -> _ = ExprField; + c.hash(&mut self.s); + self.hash_expr(e); + self.hash_name(&f.node); + } + ExprIndex(ref a, ref i) => { + let c: fn(_, _) -> _ = ExprIndex; + c.hash(&mut self.s); + self.hash_expr(a); + self.hash_expr(i); + } + ExprInlineAsm(_) => { + let c: fn(_) -> _ = ExprInlineAsm; + c.hash(&mut self.s); + } + ExprIf(ref cond, ref t, ref e) => { + let c: fn(_, _, _) -> _ = ExprIf; + c.hash(&mut self.s); + self.hash_expr(cond); + self.hash_block(t); + if let Some(ref e) = *e { + self.hash_expr(e); + } + } + ExprLit(ref l) => { + let c: fn(_) -> _ = ExprLit; + c.hash(&mut self.s); + l.hash(&mut self.s); + }, + ExprLoop(ref b, ref i) => { + let c: fn(_, _) -> _ = ExprLoop; + c.hash(&mut self.s); + self.hash_block(b); + if let Some(i) = *i { + self.hash_name(&i.name); + } + } + ExprMatch(ref e, ref arms, ref s) => { + let c: fn(_, _, _) -> _ = ExprMatch; + c.hash(&mut self.s); + self.hash_expr(e); + + for arm in arms { + // TODO: arm.pat? + if let Some(ref e) = arm.guard { + self.hash_expr(e); + } + self.hash_expr(&arm.body); + } + + s.hash(&mut self.s); + } + ExprMethodCall(ref name, ref _tys, ref args) => { + let c: fn(_, _, _) -> _ = ExprMethodCall; + c.hash(&mut self.s); + self.hash_name(&name.node); + self.hash_exprs(args); + } + ExprRange(ref b, ref e) => { + let c: fn(_, _) -> _ = ExprRange; + c.hash(&mut self.s); + if let Some(ref b) = *b { + self.hash_expr(b); + } + if let Some(ref e) = *e { + self.hash_expr(e); + } + } + ExprRepeat(ref e, ref l) => { + let c: fn(_, _) -> _ = ExprRepeat; + c.hash(&mut self.s); + self.hash_expr(e); + self.hash_expr(l); + } + ExprRet(ref e) => { + let c: fn(_) -> _ = ExprRet; + c.hash(&mut self.s); + if let Some(ref e) = *e { + self.hash_expr(e); + } + } + ExprPath(ref _qself, ref subpath) => { + let c: fn(_, _) -> _ = ExprPath; + c.hash(&mut self.s); + self.hash_path(subpath); + } + ExprStruct(ref path, ref fields, ref expr) => { + let c: fn(_, _, _) -> _ = ExprStruct; + c.hash(&mut self.s); + + self.hash_path(path); + + for f in fields { + self.hash_name(&f.name.node); + self.hash_expr(&f.expr); + } + + if let Some(ref e) = *expr { + self.hash_expr(e); + } + } + ExprTup(ref tup) => { + let c: fn(_) -> _ = ExprTup; + c.hash(&mut self.s); + self.hash_exprs(tup); + }, + ExprTupField(ref le, li) => { + let c: fn(_, _) -> _ = ExprTupField; + c.hash(&mut self.s); + + self.hash_expr(le); + li.node.hash(&mut self.s); + } + ExprType(_, _) => { + let c: fn(_, _) -> _ = ExprType; + c.hash(&mut self.s); + // what’s an ExprType anyway? + } + ExprUnary(lop, ref le) => { + let c: fn(_, _) -> _ = ExprUnary; + c.hash(&mut self.s); + + lop.hash(&mut self.s); + self.hash_expr(le); + } + ExprVec(ref v) => { + let c: fn(_) -> _ = ExprVec; + c.hash(&mut self.s); + + self.hash_exprs(v); + }, + ExprWhile(ref cond, ref b, l) => { + let c: fn(_, _, _) -> _ = ExprWhile; + c.hash(&mut self.s); + + self.hash_expr(cond); + self.hash_block(b); + if let Some(l) = l { + self.hash_name(&l.name); + } + } + } + } + + pub fn hash_exprs(&mut self, e: &[P<Expr>]) { + for e in e { + self.hash_expr(e); + } + } + + pub fn hash_name(&mut self, n: &Name) { + n.as_str().hash(&mut self.s); + } + + pub fn hash_path(&mut self, p: &Path) { + p.global.hash(&mut self.s); + for p in &p.segments { + self.hash_name(&p.identifier.name); + } + } + + pub fn hash_stmt(&mut self, b: &Stmt) { + match b.node { + StmtDecl(ref _decl, _) => { + let c: fn(_, _) -> _ = StmtDecl; + c.hash(&mut self.s); + // TODO: decl + } + StmtExpr(ref expr, _) => { + let c: fn(_, _) -> _ = StmtExpr; + c.hash(&mut self.s); + self.hash_expr(expr); + } + StmtSemi(ref expr, _) => { + let c: fn(_, _) -> _ = StmtSemi; + c.hash(&mut self.s); + self.hash_expr(expr); + } + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d666ee36bce..f5a028219ed 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -16,7 +16,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; mod hir; -pub use self::hir::SpanlessEq; +pub use self::hir::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index d6e666f299b..9ae90043948 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -105,6 +105,12 @@ fn if_same_then_else() -> &'static str { fn ifs_same_cond() { let a = 0; + let b = false; + + if b { + } + else if b { //~ERROR this if has the same condition as a previous if + } if a == 1 { } -- cgit 1.4.1-3-g733a5 From ee830ba55e12b9f360b41768078db805332dbea4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 9 Feb 2016 16:45:47 +0100 Subject: Extend IF_SAME_THEN_ELSE to ifs sequences --- src/copies.rs | 50 ++++++++++++++++++++++++++++---------------- src/utils/hir.rs | 4 ++++ tests/compile-fail/copies.rs | 47 +++++++++++++++++++++++++++-------------- 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index 1899b47accd..5f7e7a2a643 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -3,7 +3,7 @@ use rustc_front::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, span_lint, span_note_and_lint}; +use utils::{get_parent_expr, in_macro, span_note_and_lint}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is /// `Warn` by default. @@ -56,26 +56,40 @@ impl LateLintPass for CopyAndPaste { } let (conds, blocks) = if_sequence(expr); - lint_same_then_else(cx, expr); + lint_same_then_else(cx, &blocks); lint_same_cond(cx, &conds); } } } /// Implementation of `IF_SAME_THEN_ELSE`. -fn lint_same_then_else(cx: &LateContext, expr: &Expr) { - if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node { - if let ExprBlock(ref else_block) = else_expr.node { - if SpanlessEq::new(cx).eq_block(&then_block, &else_block) { - span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks"); - } - } +fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { + let hash = |block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + let eq = |lhs, rhs| -> bool { + SpanlessEq::new(cx).eq_block(lhs, rhs) + }; + + if let Some((i, j)) = search_same(blocks, hash, eq) { + span_note_and_lint(cx, IF_SAME_THEN_ELSE, j.span, "this if has identical blocks", i.span, "same as this"); } } /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { - if let Some((i, j)) = search_same(cx, conds) { + let hash = |expr| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_expr(expr); + h.finish() + }; + let eq = |lhs, rhs| -> bool { + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) + }; + + if let Some((i, j)) = search_same(conds, hash, eq) { span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); } } @@ -109,13 +123,17 @@ fn if_sequence(mut expr: &Expr) -> (Vec<&Expr>, Vec<&Block>) { (conds, blocks) } -fn search_same<'a>(cx: &LateContext, exprs: &[&'a Expr]) -> Option<(&'a Expr, &'a Expr)> { +fn search_same<'a, T, Hash, Eq>(exprs: &[&'a T], + hash: Hash, + eq: Eq) -> Option<(&'a T, &'a T)> +where Hash: Fn(&'a T) -> u64, + Eq: Fn(&'a T, &'a T) -> bool { // common cases if exprs.len() < 2 { return None; } else if exprs.len() == 2 { - return if SpanlessEq::new(cx).ignore_fn().eq_expr(&exprs[0], &exprs[1]) { + return if eq(&exprs[0], &exprs[1]) { Some((&exprs[0], &exprs[1])) } else { @@ -126,14 +144,10 @@ fn search_same<'a>(cx: &LateContext, exprs: &[&'a Expr]) -> Option<(&'a Expr, &' let mut map : HashMap<_, Vec<&'a _>> = HashMap::with_capacity(exprs.len()); for &expr in exprs { - let mut h = SpanlessHash::new(cx); - h.hash_expr(expr); - let h = h.finish(); - - match map.entry(h) { + match map.entry(hash(expr)) { Entry::Occupied(o) => { for o in o.get() { - if SpanlessEq::new(cx).ignore_fn().eq_expr(o, expr) { + if eq(o, expr) { return Some((o, expr)) } } diff --git a/src/utils/hir.rs b/src/utils/hir.rs index bd2aebfd013..c982510b3c3 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -246,6 +246,10 @@ fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool } +/// Type used to hash an ast element. This is different from the `Hash` trait on ast types as this +/// trait would consider IDs and spans. +/// +/// All expressions kind are hashed, but some might have a weaker hash. pub struct SpanlessHash<'a, 'tcx: 'a> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'a, 'tcx>, diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 9ae90043948..f465141248a 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -5,16 +5,15 @@ #![allow(let_and_return)] #![allow(needless_return)] #![allow(unused_variables)] -#![deny(if_same_then_else)] -#![deny(ifs_same_cond)] fn foo() -> bool { unimplemented!() } +#[deny(if_same_then_else)] fn if_same_then_else() -> &'static str { - if true { //~ERROR this if has the same then and else blocks + if true { foo(); } - else { + else { //~ERROR this if has identical blocks foo(); } @@ -26,11 +25,11 @@ fn if_same_then_else() -> &'static str { foo(); } - let _ = if true { //~ERROR this if has the same then and else blocks + let _ = if true { foo(); 42 } - else { + else { //~ERROR this if has identical blocks foo(); 42 }; @@ -39,14 +38,14 @@ fn if_same_then_else() -> &'static str { foo(); } - let _ = if true { //~ERROR this if has the same then and else blocks + let _ = if true { 42 } - else { + else { //~ERROR this if has identical blocks 42 }; - if true { //~ERROR this if has the same then and else blocks + if true { let bar = if true { 42 } @@ -57,7 +56,7 @@ fn if_same_then_else() -> &'static str { while foo() { break; } bar + 1; } - else { + else { //~ERROR this if has identical blocks let bar = if true { 42 } @@ -69,7 +68,7 @@ fn if_same_then_else() -> &'static str { bar + 1; } - if true { //~ERROR this if has the same then and else blocks + if true { match 42 { 42 => (), a if a > 0 => (), @@ -77,7 +76,10 @@ fn if_same_then_else() -> &'static str { _ => (), } } - else { + else if false { + foo(); + } + else if foo() { //~ERROR this if has identical blocks match 42 { 42 => (), a if a > 0 => (), @@ -86,23 +88,36 @@ fn if_same_then_else() -> &'static str { } } - if true { //~ERROR this if has the same then and else blocks + if true { + if let Some(a) = Some(42) {} + } + else { //~ERROR this if has identical blocks + if let Some(a) = Some(42) {} + } + + if true { if let Some(a) = Some(42) {} } else { - if let Some(a) = Some(42) {} + if let Some(a) = Some(43) {} } - if true { //~ERROR this if has the same then and else blocks + if true { let foo = ""; return &foo[0..]; } - else { + else if false { + let foo = "bar"; + return &foo[0..]; + } + else { //~ERROR this if has identical blocks let foo = ""; return &foo[0..]; } } +#[deny(ifs_same_cond)] +#[allow(if_same_then_else)] // all empty blocks fn ifs_same_cond() { let a = 0; let b = false; -- cgit 1.4.1-3-g733a5 From 5ddc615a40d1f33ab23899a4fe63856be9f96435 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 9 Feb 2016 17:10:50 +0100 Subject: Add missing types to eq_ty --- src/utils/hir.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/hir.rs b/src/utils/hir.rs index c982510b3c3..1ccb411b775 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -218,6 +218,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { (&TyVec(ref lvec), &TyVec(ref rvec)) => self.eq_ty(lvec, rvec), + (&TyFixedLengthVec(ref lt, ref ll), &TyFixedLengthVec(ref rt, ref rl)) => { + self.eq_ty(lt, rt) && self.eq_expr(ll, rl) + } (&TyPtr(ref lmut), &TyPtr(ref rmut)) => lmut.mutbl == rmut.mutbl && self.eq_ty(&*lmut.ty, &*rmut.ty), (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => { lrmut.mutbl == rrmut.mutbl && self.eq_ty(&*lrmut.ty, &*rrmut.ty) @@ -225,6 +228,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => { both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(lpath, rpath) } + (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), (&TyInfer, &TyInfer) => true, _ => false, } -- cgit 1.4.1-3-g733a5 From cbbc667b1b77764949714285356f475159bd2491 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 10 Feb 2016 00:38:53 +0100 Subject: Dogfood for future MATCH_SAME_ARMS lint --- src/len_zero.rs | 4 +--- src/methods.rs | 21 ++++++++++----------- src/misc.rs | 3 +-- src/utils/hir.rs | 4 ++-- tests/compile-fail/cyclomatic_complexity.rs | 16 ++++++++-------- tests/compile-fail/matches.rs | 10 +++++----- 6 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index ea0c873cb54..125a7c0ae78 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -140,9 +140,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } } match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => { - check_len_zero(cx, span, &method.node, args, lit, op) - } + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) | (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => { check_len_zero(cx, span, &method.node, args, lit, op) } diff --git a/src/methods.rs b/src/methods.rs index 40d975545e9..9263d657371 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -865,12 +865,11 @@ enum SelfKind { impl SelfKind { fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool { match (self, slf) { - (&SelfKind::Value, &SelfValue(_)) => true, - (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) => true, - (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) => true, - (&SelfKind::Ref, &SelfValue(_)) => allow_value_for_ref, - (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, - (&SelfKind::No, &SelfStatic) => true, + (&SelfKind::Value, &SelfValue(_)) | + (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | + (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | + (&SelfKind::No, &SelfStatic) => true, + (&SelfKind::Ref, &SelfValue(_)) | (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), _ => false, } @@ -878,11 +877,11 @@ impl SelfKind { fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool { match (self, &ty.node) { - (&SelfKind::Value, &TyPath(..)) => true, - (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true, - (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, - (&SelfKind::Ref, &TyPath(..)) => allow_value_for_ref, - (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, + (&SelfKind::Value, &TyPath(..)) | + (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) | + (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, + (&SelfKind::Ref, &TyPath(..)) | + (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, _ => false, } } diff --git a/src/misc.rs b/src/misc.rs index f570c18b742..076e6e385c2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -421,8 +421,7 @@ impl LateLintPass for UsedUnderscoreBinding { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(ref parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) => **rhs == *expr, - ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, _ => is_used(cx, &parent), } } else { diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 1ccb411b775..f8695956f09 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -38,8 +38,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { false } } - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) => self.eq_expr(l, r), - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), _ => false, } } diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 5bdca7f3629..3a4a83af5c6 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -138,15 +138,15 @@ fn bloo() { #[cyclomatic_complexity = "0"] fn baa() { //~ ERROR: the function has a cyclomatic complexity of 2 let x = || match 99 { - 0 => true, - 1 => false, - 2 => true, - 4 => true, - 6 => true, - 9 => true, - _ => false, + 0 => 0, + 1 => 1, + 2 => 2, + 4 => 4, + 6 => 6, + 9 => 9, + _ => 42, }; - if x() { + if x() == 42 { println!("x"); } else { println!("not x"); diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 71cc7c59f8f..46d3ff8d5fb 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -101,8 +101,8 @@ fn match_bool() { let test: bool = true; match test { //~ ERROR you seem to be trying to match on a boolean expression - true => (), - false => (), + true => 0, + false => 42, }; let option = 1; @@ -128,9 +128,9 @@ fn match_bool() { // Not linted match option { - 1 ... 10 => (), - 11 ... 20 => (), - _ => (), + 1 ... 10 => 1, + 11 ... 20 => 2, + _ => 3, }; } -- cgit 1.4.1-3-g733a5 From f309dc3c0fae39b993f95058a619f8591e9935df Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 10 Feb 2016 01:22:53 +0100 Subject: Add the MATCH_SAME_ARMS lint --- README.md | 3 +- src/copies.rs | 126 +++++++++++++++++++++++++++++++++++++------ src/lib.rs | 1 + tests/compile-fail/copies.rs | 71 ++++++++++++++++-------- 4 files changed, 162 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 6bb7a2e230e..c2d3b16074c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 119 lints included in this crate: +There are 120 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -65,6 +65,7 @@ name [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead +[match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) diff --git a/src/copies.rs b/src/copies.rs index 5f7e7a2a643..aea17c3132d 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,7 +1,9 @@ use rustc::lint::*; +use rustc::middle::ty; use rustc_front::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; +use syntax::parse::token::InternedString; use utils::{SpanlessEq, SpanlessHash}; use utils::{get_parent_expr, in_macro, span_note_and_lint}; @@ -33,6 +35,25 @@ declare_lint! { "if with the same *then* and *else* blocks" } +/// **What it does:** This lint checks for `match` with identical arm bodies. +/// +/// **Why is this bad?** This is probably a copy & paste error. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust,ignore +/// match foo { +/// Bar => bar(), +/// Quz => quz(), +/// Baz => bar(), // <= oups +/// ``` +declare_lint! { + pub MATCH_SAME_ARMS, + Warn, + "`match` with identical arm bodies" +} + #[derive(Copy, Clone, Debug)] pub struct CopyAndPaste; @@ -40,7 +61,8 @@ impl LintPass for CopyAndPaste { fn get_lints(&self) -> LintArray { lint_array![ IFS_SAME_COND, - IF_SAME_THEN_ELSE + IF_SAME_THEN_ELSE, + MATCH_SAME_ARMS ] } } @@ -58,39 +80,63 @@ impl LateLintPass for CopyAndPaste { let (conds, blocks) = if_sequence(expr); lint_same_then_else(cx, &blocks); lint_same_cond(cx, &conds); + lint_match_arms(cx, expr); } } } /// Implementation of `IF_SAME_THEN_ELSE`. fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { - let hash = |block| -> u64 { + let hash : &Fn(&&Block) -> u64 = &|block| -> u64 { let mut h = SpanlessHash::new(cx); h.hash_block(block); h.finish() }; - let eq = |lhs, rhs| -> bool { + + let eq : &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same(blocks, hash, eq) { - span_note_and_lint(cx, IF_SAME_THEN_ELSE, j.span, "this if has identical blocks", i.span, "same as this"); + span_note_and_lint(cx, IF_SAME_THEN_ELSE, j.span, "this `if` has identical blocks", i.span, "same as this"); } } /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { - let hash = |expr| -> u64 { + let hash : &Fn(&&Expr) -> u64 = &|expr| -> u64 { let mut h = SpanlessHash::new(cx); h.hash_expr(expr); h.finish() }; - let eq = |lhs, rhs| -> bool { + + let eq : &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; if let Some((i, j)) = search_same(conds, hash, eq) { - span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this"); + span_note_and_lint(cx, IFS_SAME_COND, j.span, "this `if` has the same condition as a previous if", i.span, "same as this"); + } +} + +/// Implementation if `MATCH_SAME_ARMS`. +fn lint_match_arms(cx: &LateContext, expr: &Expr) { + let hash = |arm: &Arm| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_expr(&arm.body); + h.finish() + }; + + let eq = |lhs: &Arm, rhs: &Arm| -> bool { + SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && + // all patterns should have the same bindings + bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) + }; + + if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { + if let Some((i, j)) = search_same(&**arms, hash, eq) { + span_note_and_lint(cx, MATCH_SAME_ARMS, j.body.span, "this `match` has identical arm bodies", i.body.span, "same as this"); + } } } @@ -123,11 +169,59 @@ fn if_sequence(mut expr: &Expr) -> (Vec<&Expr>, Vec<&Block>) { (conds, blocks) } -fn search_same<'a, T, Hash, Eq>(exprs: &[&'a T], - hash: Hash, - eq: Eq) -> Option<(&'a T, &'a T)> -where Hash: Fn(&'a T) -> u64, - Eq: Fn(&'a T, &'a T) -> bool { +/// Return the list of bindings in a pattern. +fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { + fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { + match pat.node { + PatBox(ref pat) | PatRegion(ref pat, _) => bindings_impl(cx, pat, map), + PatEnum(_, Some(ref pats)) => { + for pat in pats { + bindings_impl(cx, pat, map); + } + } + PatIdent(_, ref ident, ref as_pat) => { + if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) { + v.insert(cx.tcx.pat_ty(pat)); + } + if let Some(ref as_pat) = *as_pat { + bindings_impl(cx, as_pat, map); + } + }, + PatStruct(_, ref fields, _) => { + for pat in fields { + bindings_impl(cx, &pat.node.pat, map); + } + } + PatTup(ref fields) => { + for pat in fields { + bindings_impl(cx, pat, map); + } + } + PatVec(ref lhs, ref mid, ref rhs) => { + for pat in lhs { + bindings_impl(cx, pat, map); + } + if let Some(ref mid) = *mid { + bindings_impl(cx, mid, map); + } + for pat in rhs { + bindings_impl(cx, pat, map); + } + } + PatEnum(..) | PatLit(..) | PatQPath(..) | PatRange(..) | PatWild => (), + } + } + + let mut result = HashMap::new(); + bindings_impl(cx, pat, &mut result); + result +} + +fn search_same<T, Hash, Eq>(exprs: &[T], + hash: Hash, + eq: Eq) -> Option<(&T, &T)> +where Hash: Fn(&T) -> u64, + Eq: Fn(&T, &T) -> bool { // common cases if exprs.len() < 2 { return None; @@ -141,14 +235,14 @@ where Hash: Fn(&'a T) -> u64, } } - let mut map : HashMap<_, Vec<&'a _>> = HashMap::with_capacity(exprs.len()); + let mut map : HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len()); - for &expr in exprs { + for expr in exprs { match map.entry(hash(expr)) { Entry::Occupied(o) => { for o in o.get() { - if eq(o, expr) { - return Some((o, expr)) + if eq(&o, expr) { + return Some((&o, expr)) } } } diff --git a/src/lib.rs b/src/lib.rs index 775b9830750..675dbdd2dd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -196,6 +196,7 @@ pub fn plugin_registrar(reg: &mut Registry) { collapsible_if::COLLAPSIBLE_IF, copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, + copies::MATCH_SAME_ARMS, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_NOT_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index f465141248a..623f9967bd4 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -5,15 +5,18 @@ #![allow(let_and_return)] #![allow(needless_return)] #![allow(unused_variables)] +#![allow(cyclomatic_complexity)] +fn bar<T>(_: T) {} fn foo() -> bool { unimplemented!() } #[deny(if_same_then_else)] +#[deny(match_same_arms)] fn if_same_then_else() -> &'static str { if true { foo(); } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks foo(); } @@ -29,7 +32,7 @@ fn if_same_then_else() -> &'static str { foo(); 42 } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks foo(); 42 }; @@ -41,7 +44,7 @@ fn if_same_then_else() -> &'static str { let _ = if true { 42 } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks 42 }; @@ -56,7 +59,7 @@ fn if_same_then_else() -> &'static str { while foo() { break; } bar + 1; } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks let bar = if true { 42 } @@ -69,29 +72,29 @@ fn if_same_then_else() -> &'static str { } if true { - match 42 { - 42 => (), - a if a > 0 => (), - 10...15 => (), - _ => (), - } + let _ = match 42 { + 42 => 1, + a if a > 0 => 2, + 10...15 => 3, + _ => 4, + }; } else if false { foo(); } - else if foo() { //~ERROR this if has identical blocks - match 42 { - 42 => (), - a if a > 0 => (), - 10...15 => (), - _ => (), - } + else if foo() { //~ERROR this `if` has identical blocks + let _ = match 42 { + 42 => 1, + a if a > 0 => 2, + 10...15 => 3, + _ => 4, + }; } if true { if let Some(a) = Some(42) {} } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks if let Some(a) = Some(42) {} } @@ -102,6 +105,30 @@ fn if_same_then_else() -> &'static str { if let Some(a) = Some(43) {} } + let _ = match 42 { + 42 => foo(), + 51 => foo(), //~ERROR this `match` has identical arm bodies + _ => true, + }; + + let _ = match Some(42) { + Some(42) => 24, + Some(a) => 24, // bindings are different + None => 0, + }; + + match (Some(42), Some(42)) { + (Some(a), None) => bar(a), + (None, Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies + _ => (), + } + + match (Some(42), Some("")) { + (Some(a), None) => bar(a), + (None, Some(a)) => bar(a), // bindings have different types + _ => (), + } + if true { let foo = ""; return &foo[0..]; @@ -110,7 +137,7 @@ fn if_same_then_else() -> &'static str { let foo = "bar"; return &foo[0..]; } - else { //~ERROR this if has identical blocks + else { //~ERROR this `if` has identical blocks let foo = ""; return &foo[0..]; } @@ -124,19 +151,19 @@ fn ifs_same_cond() { if b { } - else if b { //~ERROR this if has the same condition as a previous if + else if b { //~ERROR this `if` has the same condition as a previous if } if a == 1 { } - else if a == 1 { //~ERROR this if has the same condition as a previous if + else if a == 1 { //~ERROR this `if` has the same condition as a previous if } if 2*a == 1 { } else if 2*a == 2 { } - else if 2*a == 1 { //~ERROR this if has the same condition as a previous if + else if 2*a == 1 { //~ERROR this `if` has the same condition as a previous if } else if a == 1 { } -- cgit 1.4.1-3-g733a5 From 68ecd06f4cf67a996af348a5ccc90d6a0f25589f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 11 Feb 2016 23:49:35 +0100 Subject: Small optimisation of most common cases --- src/copies.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index aea17c3132d..e2defe8f364 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -4,6 +4,7 @@ use rustc_front::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; use syntax::parse::token::InternedString; +use syntax::util::small_vector::SmallVector; use utils::{SpanlessEq, SpanlessHash}; use utils::{get_parent_expr, in_macro, span_note_and_lint}; @@ -78,8 +79,8 @@ impl LateLintPass for CopyAndPaste { } let (conds, blocks) = if_sequence(expr); - lint_same_then_else(cx, &blocks); - lint_same_cond(cx, &conds); + lint_same_then_else(cx, blocks.as_slice()); + lint_same_cond(cx, conds.as_slice()); lint_match_arms(cx, expr); } } @@ -143,9 +144,9 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { /// Return the list of condition expressions and the list of blocks in a sequence of `if/else`. /// Eg. would return `([a, b], [c, d, e])` for the expression /// `if a { c } else if b { d } else { e }`. -fn if_sequence(mut expr: &Expr) -> (Vec<&Expr>, Vec<&Block>) { - let mut conds = vec![]; - let mut blocks = vec![]; +fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { + let mut conds = SmallVector::zero(); + let mut blocks = SmallVector::zero(); while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node { conds.push(&**cond); -- cgit 1.4.1-3-g733a5 From 07228a104109b00ad3ec553a33eb6b496fc97451 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 12 Feb 2016 15:51:55 +0100 Subject: Fix `Hash` implementation for `Constant` --- src/consts.rs | 93 ++++++++++++++++++++++++++++++++++++--------------------- tests/consts.rs | 10 ++++++- 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 4469853ddf9..416ec82799c 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -2,22 +2,21 @@ use rustc::lint::LateContext; use rustc::middle::const_eval::lookup_const_by_id; -use rustc::middle::def::PathResolution; -use rustc::middle::def::Def; +use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; -use syntax::ptr::P; -use std::cmp::PartialOrd; use std::cmp::Ordering::{self, Greater, Less, Equal}; -use std::rc::Rc; +use std::cmp::PartialOrd; +use std::hash::{Hash, Hasher}; +use std::mem; use std::ops::Deref; - -use syntax::ast::Lit_; -use syntax::ast::LitIntType; -use syntax::ast::{UintTy, FloatTy, StrStyle}; +use std::rc::Rc; +use syntax::ast::{LitIntType, Lit_}; use syntax::ast::Sign::{self, Plus, Minus}; +use syntax::ast::{UintTy, FloatTy, StrStyle}; +use syntax::ptr::P; -#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)] +#[derive(Debug, Copy, Clone)] pub enum FloatWidth { Fw32, Fw64, @@ -34,7 +33,7 @@ impl From<FloatTy> for FloatWidth { } /// a Lit_-like enum to fold constant `Expr`s into -#[derive(Eq, Debug, Clone, Hash)] +#[derive(Debug, Clone)] pub enum Constant { /// a String "abc" Str(String, StrStyle), @@ -100,18 +99,12 @@ impl PartialEq for Constant { (&Constant::Int(lv, lty), &Constant::Int(rv, rty)) => { lv == rv && (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)) } - (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { - use self::FloatWidth::*; - if match (lw, rw) { - (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, + (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { + // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have + // `Fw32 == Fw64` so don’t compare them + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(l), Ok(r)) => l.eq(&r), _ => false, - } { - match (ls.parse::<f64>(), rs.parse::<f64>()) { - (Ok(l), Ok(r)) => l.eq(&r), - _ => false, - } - } else { - false } } (&Constant::Bool(l), &Constant::Bool(r)) => l == r, @@ -123,6 +116,46 @@ impl PartialEq for Constant { } } +impl Hash for Constant { + fn hash<H>(&self, state: &mut H) where H: Hasher { + match *self { + Constant::Str(ref s, ref k) => { + s.hash(state); + k.hash(state); + } + Constant::Binary(ref b) => { + b.hash(state); + } + Constant::Byte(u) => { + u.hash(state); + } + Constant::Char(c) => { + c.hash(state); + } + Constant::Int(u, t) => { + u.hash(state); + t.hash(state); + } + Constant::Float(ref f, _) => { + // don’t use the width here because of PartialEq implementation + if let Ok(f) = f.parse::<f64>() { + unsafe { mem::transmute::<f64, u64>(f) }.hash(state); + } + } + Constant::Bool(b) => { + b.hash(state); + } + Constant::Vec(ref v) | Constant::Tuple(ref v)=> { + v.hash(state); + } + Constant::Repeat(ref c, l) => { + c.hash(state); + l.hash(state); + } + } + } +} + impl PartialOrd for Constant { fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { @@ -143,18 +176,10 @@ impl PartialOrd for Constant { (false, true) => Greater, }) } - (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { - use self::FloatWidth::*; - if match (lw, rw) { - (FwAny, _) | (_, FwAny) | (Fw32, Fw32) | (Fw64, Fw64) => true, - _ => false, - } { - match (ls.parse::<f64>(), rs.parse::<f64>()) { - (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), - _ => None, - } - } else { - None + (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), + _ => None, } } (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), diff --git a/tests/consts.rs b/tests/consts.rs index 75082e646a0..ab8636b8131 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -17,7 +17,7 @@ use syntax::ast::LitIntType::*; use syntax::ast::StrStyle::*; use syntax::ast::Sign::*; -use clippy::consts::{constant_simple, Constant}; +use clippy::consts::{constant_simple, Constant, FloatWidth}; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } @@ -78,4 +78,12 @@ fn test_ops() { check(ONE, &binop(BiSub, litone.clone(), litzero.clone())); check(ONE, &binop(BiMul, litone.clone(), litone.clone())); check(ONE, &binop(BiDiv, litone.clone(), litone.clone())); + + let half_any = Constant::Float("0.5".into(), FloatWidth::FwAny); + let half32 = Constant::Float("0.5".into(), FloatWidth::Fw32); + let half64 = Constant::Float("0.5".into(), FloatWidth::Fw64); + + assert_eq!(half_any, half32); + assert_eq!(half_any, half64); + assert_eq!(half32, half64); // for transitivity } -- cgit 1.4.1-3-g733a5 From 3f34b65747546aefeceb2edc4e8e4dc03c82e7f7 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 12 Feb 2016 18:35:44 +0100 Subject: fix nightly breakage --- Cargo.toml | 2 +- src/approx_const.rs | 8 +- src/attrs.rs | 12 +-- src/bit_mask.rs | 4 +- src/consts.rs | 233 ++++++++++++++++-------------------------- src/derive.rs | 4 +- src/enum_variants.rs | 2 +- src/identity_op.rs | 8 +- src/items_after_statements.rs | 8 +- src/len_zero.rs | 4 +- src/matches.rs | 6 +- src/mutex_atomic.rs | 4 +- src/needless_bool.rs | 4 +- src/open_options.rs | 4 +- src/panic.rs | 4 +- src/precedence.rs | 22 ++-- src/regex.rs | 8 +- src/returns.rs | 18 ++-- src/strings.rs | 4 +- src/types.rs | 54 +++++----- src/unicode.rs | 4 +- src/utils.rs | 9 +- tests/consts.rs | 36 +++---- 23 files changed, 202 insertions(+), 260 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c0d600e418c..9a0b0b37bae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ regex-syntax = "0.2.2" [dev-dependencies] compiletest_rs = "0.0.11" regex = "0.1.47" -regex_macros = "0.1.27" +regex_macros = "0.1.28" lazy_static = "0.1.15" rustc-serialize = "0.3" diff --git a/src/approx_const.rs b/src/approx_const.rs index d18785ab818..b1a33584442 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use std::f64::consts as f64; use utils::span_lint; -use syntax::ast::{Lit, Lit_, FloatTy}; +use syntax::ast::{Lit, LitKind, FloatTy}; /// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. /// @@ -55,9 +55,9 @@ impl LateLintPass for ApproxConstant { fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { - Lit_::LitFloat(ref s, FloatTy::TyF32) => check_known_consts(cx, e, s, "f32"), - Lit_::LitFloat(ref s, FloatTy::TyF64) => check_known_consts(cx, e, s, "f64"), - Lit_::LitFloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), + LitKind::Float(ref s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), + LitKind::Float(ref s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), + LitKind::FloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), _ => (), } } diff --git a/src/attrs.rs b/src/attrs.rs index 231a08779cc..fda46724862 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -6,7 +6,7 @@ use reexport::*; use semver::Version; use syntax::codemap::Span; use syntax::attr::*; -use syntax::ast::{Attribute, Lit, Lit_, MetaList, MetaWord, MetaNameValue}; +use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; /// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. @@ -54,12 +54,12 @@ impl LintPass for AttrPass { impl LateLintPass for AttrPass { fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) { - if let MetaList(ref name, ref items) = attr.node.value.node { + if let MetaItemKind::List(ref name, ref items) = attr.node.value.node { if items.is_empty() || name != &"deprecated" { return; } for ref item in items { - if let MetaNameValue(ref name, ref lit) = item.node { + if let MetaItemKind::NameValue(ref name, ref lit) = item.node { if name == &"since" { check_semver(cx, item.span, lit); } @@ -144,11 +144,11 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } for attr in attrs { - if let MetaList(ref inline, ref values) = attr.node.value.node { + if let MetaItemKind::List(ref inline, ref values) = attr.node.value.node { if values.len() != 1 || inline != &"inline" { continue; } - if let MetaWord(ref always) = values[0].node { + if let MetaItemKind::Word(ref always) = values[0].node { if always != &"always" { continue; } @@ -163,7 +163,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { - if let Lit_::LitStr(ref is, _) = lit.node { + if let LitKind::Str(ref is, _) = lit.node { if Version::parse(&*is).is_ok() { return; } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 6de00167571..e1366924e1d 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -4,7 +4,7 @@ use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; use syntax::codemap::Span; -use syntax::ast::Lit_; +use syntax::ast::LitKind; use utils::span_lint; @@ -254,7 +254,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { match lit.node { ExprLit(ref lit_ptr) => { - if let Lit_::LitInt(value, _) = lit_ptr.node { + if let LitKind::Int(value, _) = lit_ptr.node { Some(value) //TODO: Handle sign } else { None diff --git a/src/consts.rs b/src/consts.rs index ddc8560c9b3..5ff0591e02d 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -11,10 +11,9 @@ use std::cmp::Ordering::{self, Greater, Less, Equal}; use std::rc::Rc; use std::ops::Deref; -use syntax::ast::Lit_; +use syntax::ast::LitKind; use syntax::ast::LitIntType; use syntax::ast::{UintTy, FloatTy, StrStyle}; -use syntax::ast::Sign::{self, Plus, Minus}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] @@ -27,12 +26,18 @@ pub enum FloatWidth { impl From<FloatTy> for FloatWidth { fn from(ty: FloatTy) -> FloatWidth { match ty { - FloatTy::TyF32 => FloatWidth::Fw32, - FloatTy::TyF64 => FloatWidth::Fw64, + FloatTy::F32 => FloatWidth::Fw32, + FloatTy::F64 => FloatWidth::Fw64, } } } +#[derive(Copy, Eq, Debug, Clone, PartialEq)] +pub enum Sign { + Plus, + Minus, +} + /// a Lit_-like enum to fold constant `Expr`s into #[derive(Eq, Debug, Clone)] pub enum Constant { @@ -44,8 +49,8 @@ pub enum Constant { Byte(u8), /// a single char 'a' Char(char), - /// an integer - Int(u64, LitIntType), + /// an integer, third argument is whether the value is negated + Int(u64, LitIntType, Sign), /// a float with given type Float(String, FloatWidth), /// true or false @@ -65,7 +70,7 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let Constant::Int(val, _) = *self { + if let Constant::Int(val, _, _) = *self { val // TODO we may want to check the sign if any } else { panic!("Could not convert a {:?} to u64", self); @@ -78,13 +83,8 @@ impl Constant { match *self { Constant::Byte(b) => Some(b as f64), Constant::Float(ref s, _) => s.parse().ok(), - Constant::Int(i, ty) => { - Some(if is_negative(ty) { - -(i as f64) - } else { - i as f64 - }) - } + Constant::Int(i, _, Sign::Minus) => Some(-(i as f64)), + Constant::Int(i, _, Sign::Plus) => Some(i as f64), _ => None, } } @@ -97,8 +97,9 @@ impl PartialEq for Constant { (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Byte(l), &Constant::Byte(r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(lv, lty), &Constant::Int(rv, rty)) => { - lv == rv && (is_negative(lty) & (lv != 0)) == (is_negative(rty) & (rv != 0)) + (&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => true, + (&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => { + lv == rv && lneg == rneg } (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { use self::FloatWidth::*; @@ -135,14 +136,11 @@ impl PartialOrd for Constant { } (&Constant::Byte(ref l), &Constant::Byte(ref r)) => Some(l.cmp(r)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), - (&Constant::Int(ref lv, lty), &Constant::Int(ref rv, rty)) => { - Some(match (is_negative(lty) && *lv != 0, is_negative(rty) && *rv != 0) { - (true, true) => rv.cmp(lv), - (false, false) => lv.cmp(rv), - (true, false) => Less, - (false, true) => Greater, - }) - } + (&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => Some(Equal), + (&Constant::Int(ref lv, _, Sign::Plus), &Constant::Int(ref rv, _, Sign::Plus)) => Some(lv.cmp(rv)), + (&Constant::Int(ref lv, _, Sign::Minus), &Constant::Int(ref rv, _, Sign::Minus)) => Some(rv.cmp(lv)), + (&Constant::Int(_, _, Sign::Minus), &Constant::Int(_, _, Sign::Plus)) => Some(Less), + (&Constant::Int(_, _, Sign::Plus), &Constant::Int(_, _, Sign::Minus)) => Some(Greater), (&Constant::Float(ref ls, lw), &Constant::Float(ref rs, rw)) => { use self::FloatWidth::*; if match (lw, rw) { @@ -171,16 +169,16 @@ impl PartialOrd for Constant { } } -fn lit_to_constant(lit: &Lit_) -> Constant { +fn lit_to_constant(lit: &LitKind) -> Constant { match *lit { - Lit_::LitStr(ref is, style) => Constant::Str(is.to_string(), style), - Lit_::LitByte(b) => Constant::Byte(b), - Lit_::LitByteStr(ref s) => Constant::Binary(s.clone()), - Lit_::LitChar(c) => Constant::Char(c), - Lit_::LitInt(value, ty) => Constant::Int(value, ty), - Lit_::LitFloat(ref is, ty) => Constant::Float(is.to_string(), ty.into()), - Lit_::LitFloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::FwAny), - Lit_::LitBool(b) => Constant::Bool(b), + LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), + LitKind::Byte(b) => Constant::Byte(b), + LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), + LitKind::Char(c) => Constant::Char(c), + LitKind::Int(value, ty) => Constant::Int(value, ty, Sign::Plus), + LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), + LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::FwAny), + LitKind::Bool(b) => Constant::Bool(b), } } @@ -189,21 +187,21 @@ fn constant_not(o: Constant) -> Option<Constant> { use self::Constant::*; match o { Bool(b) => Some(Bool(!b)), - Int(::std::u64::MAX, SignedIntLit(_, Plus)) => None, - Int(value, SignedIntLit(ity, Plus)) => Some(Int(value + 1, SignedIntLit(ity, Minus))), - Int(0, SignedIntLit(ity, Minus)) => Some(Int(1, SignedIntLit(ity, Minus))), - Int(value, SignedIntLit(ity, Minus)) => Some(Int(value - 1, SignedIntLit(ity, Plus))), - Int(value, UnsignedIntLit(ity)) => { + Int(::std::u64::MAX, LitIntType::Signed(_), Sign::Plus) => None, + Int(value, LitIntType::Signed(ity), Sign::Plus) => Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus)), + Int(0, LitIntType::Signed(ity), Sign::Minus) => Some(Int(1, LitIntType::Signed(ity), Sign::Minus)), + Int(value, LitIntType::Signed(ity), Sign::Minus) => Some(Int(value - 1, LitIntType::Signed(ity), Sign::Plus)), + Int(value, LitIntType::Unsigned(ity), Sign::Plus) => { let mask = match ity { - UintTy::TyU8 => ::std::u8::MAX as u64, - UintTy::TyU16 => ::std::u16::MAX as u64, - UintTy::TyU32 => ::std::u32::MAX as u64, - UintTy::TyU64 => ::std::u64::MAX, - UintTy::TyUs => { + UintTy::U8 => ::std::u8::MAX as u64, + UintTy::U16 => ::std::u16::MAX as u64, + UintTy::U32 => ::std::u32::MAX as u64, + UintTy::U64 => ::std::u64::MAX, + UintTy::Us => { return None; } // refuse to guess }; - Some(Int(!value & mask, UnsignedIntLit(ity))) + Some(Int(!value & mask, LitIntType::Unsigned(ity), Sign::Plus)) }, _ => None, } @@ -213,8 +211,8 @@ fn constant_negate(o: Constant) -> Option<Constant> { use syntax::ast::LitIntType::*; use self::Constant::*; match o { - Int(value, SignedIntLit(ity, sign)) => Some(Int(value, SignedIntLit(ity, neg_sign(sign)))), - Int(value, UnsuffixedIntLit(sign)) => Some(Int(value, UnsuffixedIntLit(neg_sign(sign)))), + Int(value, LitIntType::Signed(ity), sign) => Some(Int(value, LitIntType::Signed(ity), neg_sign(sign))), + Int(value, LitIntType::Unsuffixed, sign) => Some(Int(value, LitIntType::Unsuffixed, neg_sign(sign))), Float(is, ty) => Some(Float(neg_float_str(is), ty)), _ => None, } @@ -235,78 +233,32 @@ fn neg_float_str(s: String) -> String { } } -/// is the given LitIntType negative? -/// -/// Examples -/// -/// ``` -/// assert!(is_negative(UnsuffixedIntLit(Minus))); -/// ``` -pub fn is_negative(ty: LitIntType) -> bool { - match ty { - LitIntType::SignedIntLit(_, sign) | LitIntType::UnsuffixedIntLit(sign) => sign == Minus, - LitIntType::UnsignedIntLit(_) => false, - } -} - -fn unify_int_type(l: LitIntType, r: LitIntType, s: Sign) -> Option<LitIntType> { +fn unify_int_type(l: LitIntType, r: LitIntType) -> Option<LitIntType> { use syntax::ast::LitIntType::*; match (l, r) { - (SignedIntLit(lty, _), SignedIntLit(rty, _)) => { + (Signed(lty), Signed(rty)) => { if lty == rty { - Some(SignedIntLit(lty, s)) + Some(LitIntType::Signed(lty)) } else { None } } - (UnsignedIntLit(lty), UnsignedIntLit(rty)) => { - if s == Plus && lty == rty { - Some(UnsignedIntLit(lty)) - } else { - None - } - } - (UnsuffixedIntLit(_), UnsuffixedIntLit(_)) => Some(UnsuffixedIntLit(s)), - (SignedIntLit(lty, _), UnsuffixedIntLit(_)) => Some(SignedIntLit(lty, s)), - (UnsignedIntLit(lty), UnsuffixedIntLit(rs)) => { - if rs == Plus { - Some(UnsignedIntLit(lty)) - } else { - None - } - } - (UnsuffixedIntLit(_), SignedIntLit(rty, _)) => Some(SignedIntLit(rty, s)), - (UnsuffixedIntLit(ls), UnsignedIntLit(rty)) => { - if ls == Plus { - Some(UnsignedIntLit(rty)) + (Unsigned(lty), Unsigned(rty)) => { + if lty == rty { + Some(LitIntType::Unsigned(lty)) } else { None } } + (Unsuffixed, Unsuffixed) => Some(Unsuffixed), + (Signed(lty), Unsuffixed) => Some(Signed(lty)), + (Unsigned(lty), Unsuffixed) => Some(Unsigned(lty)), + (Unsuffixed, Signed(rty)) => Some(Signed(rty)), + (Unsuffixed, Unsigned(rty)) => Some(Unsigned(rty)), _ => None, } } -fn add_neg_int(pos: u64, pty: LitIntType, neg: u64, nty: LitIntType) -> Option<Constant> { - if neg > pos { - unify_int_type(nty, pty, Minus).map(|ty| Constant::Int(neg - pos, ty)) - } else { - unify_int_type(nty, pty, Plus).map(|ty| Constant::Int(pos - neg, ty)) - } -} - -fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) -> Option<Constant> { - unify_int_type(lty, - rty, - if neg { - Minus - } else { - Plus - }) - .and_then(|ty| l.checked_sub(r).map(|v| Constant::Int(v, ty))) -} - - pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { lcx: Some(lcx), @@ -412,23 +364,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { self.binop_apply(left, right, |l, r| { match (l, r) { (Constant::Byte(l8), Constant::Byte(r8)) => l8.checked_add(r8).map(Constant::Byte), - (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - if ln == rn { - unify_int_type(lty, - rty, - if ln { - Minus - } else { - Plus - }) - .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) - } else if ln { - add_neg_int(r64, rty, l64, lty) - } else { - add_neg_int(l64, lty, r64, rty) - } - } + (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { + add_ints(l64, r64, lty, rty, lsign, rsign) + }, // TODO: float (would need bignum library?) _ => None, } @@ -444,20 +382,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { Some(Constant::Byte(l8 - r8)) } } - (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { - match (is_negative(lty), is_negative(rty)) { - (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), - (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), - (true, false) => { - unify_int_type(lty, rty, Minus) - .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) - } - (false, true) => { - unify_int_type(lty, rty, Plus) - .and_then(|ty| l64.checked_add(r64).map(|v| Constant::Int(v, ty))) - } - } - } + (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { + add_ints(l64, r64, lty, rty, lsign, neg_sign(rsign)) + }, _ => None, } }) @@ -487,16 +414,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { { self.binop_apply(left, right, |l, r| { match (l, r) { - (Constant::Int(l64, lty), Constant::Int(r64, rty)) => { + (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { f(l64, r64).and_then(|value| { - unify_int_type(lty, - rty, - if is_negative(lty) == is_negative(rty) { - Plus - } else { - Minus - }) - .map(|ty| Constant::Int(value, ty)) + let sign = if lsign == rsign { Sign::Plus } else { Sign::Minus }; + unify_int_type(lty, rty).map(|ty| Constant::Int(value, ty, sign)) }) } _ => None, @@ -511,8 +432,12 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match (l, r) { (Constant::Bool(l), Constant::Bool(r)) => Some(Constant::Bool(f(l as u64, r as u64) != 0)), (Constant::Byte(l8), Constant::Byte(r8)) => Some(Constant::Byte(f(l8 as u64, r8 as u64) as u8)), - (Constant::Int(l, lty), Constant::Int(r, rty)) => { - unify_int_type(lty, rty, Plus).map(|ty| Constant::Int(f(l, r), ty)) + (Constant::Int(l, lty, lsign), Constant::Int(r, rty, rsign)) => { + if lsign == Sign::Plus && rsign == Sign::Plus { + unify_int_type(lty, rty).map(|ty| Constant::Int(f(l, r), ty, Sign::Plus)) + } else { + None + } } _ => None, } @@ -555,3 +480,21 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }) } } + +fn add_ints(l64: u64, r64: u64, lty: LitIntType, rty: LitIntType, lsign: Sign, rsign: Sign) -> Option<Constant> { + let ty = if let Some(ty) = unify_int_type(lty, rty) { ty } else { return None; }; + match (lsign, rsign) { + (Sign::Plus, Sign::Plus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Plus)), + (Sign::Plus, Sign::Minus) => if r64 > l64 { + Some(Constant::Int(r64 - l64, ty, Sign::Minus)) + } else { + Some(Constant::Int(l64 - r64, ty, Sign::Plus)) + }, + (Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)), + (Sign::Minus, Sign::Plus) => if l64 > r64 { + Some(Constant::Int(l64 - r64, ty, Sign::Minus)) + } else { + Some(Constant::Int(r64 - l64, ty, Sign::Plus)) + }, + } +} diff --git a/src/derive.rs b/src/derive.rs index d8f331ef5ff..e9eef824713 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::middle::ty::fast_reject::simplify_type; use rustc::middle::ty; use rustc_front::hir::*; -use syntax::ast::{Attribute, MetaItem_}; +use syntax::ast::{Attribute, MetaItemKind}; use syntax::codemap::Span; use utils::{CLONE_TRAIT_PATH, HASH_PATH}; use utils::{match_path, span_lint_and_then}; @@ -170,7 +170,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have. fn is_automatically_derived(attr: &Attribute) -> bool { - if let MetaItem_::MetaWord(ref word) = attr.node.value.node { + if let MetaItemKind::Word(ref word) = attr.node.value.node { word == &"automatically_derived" } else { false diff --git a/src/enum_variants.rs b/src/enum_variants.rs index 8ceaca1bbf3..c77e42e69c9 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -41,7 +41,7 @@ fn partial_rmatch(left: &str, right: &str) -> usize { impl EarlyLintPass for EnumVariantNames { fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemEnum(ref def, _) = item.node { + if let ItemKind::Enum(ref def, _) = item.node { if def.variants.len() < 2 { return; } diff --git a/src/identity_op.rs b/src/identity_op.rs index 1a62ffb4ae0..b033b234122 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use consts::{constant_simple, is_negative, Constant}; +use consts::{constant_simple, Constant, Sign}; use utils::{span_lint, snippet, in_macro}; /// **What it does:** This lint checks for identity operations, e.g. `x + 0`. @@ -55,11 +55,11 @@ impl LateLintPass for IdentityOp { fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(Constant::Int(v, ty)) = constant_simple(e) { + if let Some(Constant::Int(v, _, sign)) = constant_simple(e) { if match m { 0 => v == 0, - -1 => is_negative(ty) && v == 1, - 1 => !is_negative(ty) && v == 1, + -1 => sign == Sign::Minus && v == 1, + 1 => sign == Sign::Plus && v == 1, _ => unreachable!(), } { span_lint(cx, diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 2aa2fc6da34..9bfb3b87ed1 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -47,15 +47,15 @@ impl EarlyLintPass for ItemsAfterStatemets { } let mut stmts = item.stmts.iter().map(|stmt| &stmt.node); // skip initial items - while let Some(&StmtDecl(ref decl, _)) = stmts.next() { - if let DeclLocal(_) = decl.node { + while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() { + if let DeclKind::Local(_) = decl.node { break; } } // lint on all further items for stmt in stmts { - if let StmtDecl(ref decl, _) = *stmt { - if let DeclItem(ref it) = decl.node { + if let StmtKind::Decl(ref decl, _) = *stmt { + if let DeclKind::Item(ref it) = decl.node { if in_macro(cx, it.span) { return; } diff --git a/src/len_zero.rs b/src/len_zero.rs index ea0c873cb54..4f3c2367370 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -6,7 +6,7 @@ use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use syntax::ast::{Lit, Lit_}; +use syntax::ast::{Lit, LitKind}; use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; @@ -151,7 +151,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { - if let Spanned{node: Lit_::LitInt(0, _), ..} = *lit { + if let Spanned{node: LitKind::Int(0, _), ..} = *lit { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint(cx, LEN_ZERO, diff --git a/src/matches.rs b/src/matches.rs index 6be5d0bf24f..ca410a413bd 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -5,7 +5,7 @@ use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty; use rustc_front::hir::*; use std::cmp::Ordering; -use syntax::ast::Lit_::LitBool; +use syntax::ast::LitKind; use syntax::codemap::Span; use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; @@ -238,8 +238,8 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { match lit.node { - LitBool(true) => Some((&*arms[0].body, &*arms[1].body)), - LitBool(false) => Some((&*arms[1].body, &*arms[0].body)), + LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), _ => None, } } else { diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index cf1c347750c..8a51ba27b8e 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -56,8 +56,8 @@ impl LateLintPass for MutexAtomic { behaviour and not the internal type, consider using Mutex<()>.", atomic_name); match *mutex_param { - ty::TyUint(t) if t != ast::TyUs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::TyInt(t) if t != ast::TyIs => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 4ddd8f2f3c5..fe46988dccb 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::ast::Lit_; +use syntax::ast::LitKind; use syntax::codemap::Spanned; use utils::{span_lint, span_lint_and_then, snippet}; @@ -164,7 +164,7 @@ fn fetch_bool_expr(expr: &Expr) -> Option<bool> { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), ExprLit(ref lit_ptr) => { - if let Lit_::LitBool(value) = lit_ptr.node { + if let LitKind::Bool(value) = lit_ptr.node { Some(value) } else { None diff --git a/src/open_options.rs b/src/open_options.rs index 77e9a300335..8b1c4a90fdf 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::{Expr, ExprMethodCall, ExprLit}; use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; use syntax::codemap::{Span, Spanned}; -use syntax::ast::Lit_::LitBool; +use syntax::ast::LitKind; /// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. /// @@ -65,7 +65,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned {node: LitBool(lit), ..} = **span { + if let Spanned {node: LitKind::Bool(lit), ..} = **span { if lit { Argument::True } else { diff --git a/src/panic.rs b/src/panic.rs index 5337942b4e0..b76def8d2f3 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::ast::Lit_::LitStr; +use syntax::ast::LitKind; use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; @@ -37,7 +37,7 @@ impl LateLintPass for PanicPass { let ExprPath(None, ref path) = fun.node, match_path(path, &BEGIN_UNWIND), let ExprLit(ref lit) = params[0].node, - let LitStr(ref string, _) = lit.node, + let LitKind::Str(ref string, _) = lit.node, string.contains('{'), let Some(sp) = cx.sess().codemap() .with_expn_info(expr.span.expn_id, diff --git a/src/precedence.rs b/src/precedence.rs index 009a79b1673..d498510f97a 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -32,7 +32,7 @@ impl LintPass for Precedence { impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { + if let ExprKind::Binary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if !is_bit_op(op) { return; } @@ -71,12 +71,12 @@ impl EarlyLintPass for Precedence { } } - if let ExprUnary(UnNeg, ref rhs) = expr.node { - if let ExprMethodCall(_, _, ref args) = rhs.node { + if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.node { + if let ExprKind::MethodCall(_, _, ref args) = rhs.node { if let Some(slf) = args.first() { - if let ExprLit(ref lit) = slf.node { + if let ExprKind::Lit(ref lit) = slf.node { match lit.node { - LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => { + LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { span_lint(cx, PRECEDENCE, expr.span, @@ -95,21 +95,23 @@ impl EarlyLintPass for Precedence { fn is_arith_expr(expr: &Expr) -> bool { match expr.node { - ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op), + ExprKind::Binary(Spanned { node: op, ..}, _, _) => is_arith_op(op), _ => false, } } -fn is_bit_op(op: BinOp_) -> bool { +fn is_bit_op(op: BinOpKind) -> bool { + use syntax::ast::BinOpKind::*; match op { - BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true, + BitXor | BitAnd | BitOr | Shl | Shr => true, _ => false, } } -fn is_arith_op(op: BinOp_) -> bool { +fn is_arith_op(op: BinOpKind) -> bool { + use syntax::ast::BinOpKind::*; match op { - BiAdd | BiSub | BiMul | BiDiv | BiRem => true, + Add | Sub | Mul | Div | Rem => true, _ => false, } } diff --git a/src/regex.rs b/src/regex.rs index cf938dcf4b3..5103391e9dd 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,7 +1,7 @@ use regex_syntax; use std::error::Error; use std::collections::HashSet; -use syntax::ast::Lit_::LitStr; +use syntax::ast::LitKind; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use rustc_front::hir::*; @@ -75,7 +75,7 @@ impl LateLintPass for RegexPass { match_path(path, ®EX_NEW_PATH) && args.len() == 1 ], { if let ExprLit(ref lit) = args[0].node { - if let LitStr(ref r, _) = lit.node { + if let LitKind::Str(ref r, _) = lit.node { match regex_syntax::Expr::parse(r) { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { @@ -176,8 +176,8 @@ impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { if self.spans.contains(&span) { return; } - span_lint(self.cx, - REGEX_MACRO, + span_lint(self.cx, + REGEX_MACRO, span, "`regex!(_)` found. \ Please use `Regex::new(_)`, which is faster for now."); diff --git a/src/returns.rs b/src/returns.rs index 3d830e9e372..63864eafcd2 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -40,8 +40,8 @@ impl ReturnPass { if let Some(ref expr) = block.expr { self.check_final_expr(cx, expr); } else if let Some(stmt) = block.stmts.last() { - if let StmtSemi(ref expr, _) = stmt.node { - if let ExprRet(Some(ref inner)) = expr.node { + if let StmtKind::Semi(ref expr, _) = stmt.node { + if let ExprKind::Ret(Some(ref inner)) = expr.node { self.emit_return_lint(cx, (stmt.span, inner.span)); } } @@ -52,22 +52,22 @@ impl ReturnPass { fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) { match expr.node { // simple return is always "bad" - ExprRet(Some(ref inner)) => { + ExprKind::Ret(Some(ref inner)) => { self.emit_return_lint(cx, (expr.span, inner.span)); } // a whole block? check it! - ExprBlock(ref block) => { + ExprKind::Block(ref block) => { self.check_block_return(cx, block); } // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it - ExprIf(_, ref ifblock, Some(ref elsexpr)) => { + ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => { self.check_block_return(cx, ifblock); self.check_final_expr(cx, elsexpr); } // a match expr, check all arms - ExprMatch(_, ref arms) => { + ExprKind::Match(_, ref arms) => { for arm in arms { self.check_final_expr(cx, &arm.body); } @@ -94,11 +94,11 @@ impl ReturnPass { [ let Some(stmt) = block.stmts.last(), let Some(ref retexpr) = block.expr, - let StmtDecl(ref decl, _) = stmt.node, - let DeclLocal(ref local) = decl.node, + let StmtKind::Decl(ref decl, _) = stmt.node, + let DeclKind::Local(ref local) = decl.node, let Some(ref initexpr) = local.init, let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, - let ExprPath(_, ref path) = retexpr.node, + let ExprKind::Path(_, ref path) = retexpr.node, match_path_ast(path, &[&id.name.as_str()]) ], { self.emit_let_lint(cx, retexpr.span, initexpr.span); diff --git a/src/strings.rs b/src/strings.rs index b78db7f4b77..7b4b2e2c5ec 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -133,13 +133,13 @@ impl LintPass for StringLitAsBytes { impl LateLintPass for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { use std::ascii::AsciiExt; - use syntax::ast::Lit_::LitStr; + use syntax::ast::LitKind; use utils::{snippet, in_macro}; if let ExprMethodCall(ref name, _, ref args) = e.node { if name.node.as_str() == "as_bytes" { if let ExprLit(ref lit) = args[0].node { - if let LitStr(ref lit_content, _) = lit.node { + if let LitKind::Str(ref lit_content, _) = lit.node { if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, e.span) { let msg = format!("calling `as_bytes()` on a string literal. \ Consider using a byte string literal instead: \ diff --git a/src/types.rs b/src/types.rs index a48172c5980..7cfcc76193d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -235,7 +235,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { fn is_isize_or_usize(typ: &ty::TyS) -> bool { match typ.sty { - ty::TyInt(IntTy::TyIs) | ty::TyUint(UintTy::TyUs) => true, + ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, _ => false, } } @@ -360,7 +360,7 @@ impl LateLintPass for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = if let ty::TyFloat(FloatTy::TyF32) = cast_to.sty { + let to_nbits = if let ty::TyFloat(FloatTy::F32) = cast_to.sty { 32 } else { 64 @@ -391,7 +391,7 @@ impl LateLintPass for CastPass { check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { - if let (&ty::TyFloat(FloatTy::TyF64), &ty::TyFloat(FloatTy::TyF32)) = (&cast_from.sty, &cast_to.sty) { + if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, @@ -560,12 +560,12 @@ impl LintPass for CharLitAsU8 { impl LateLintPass for CharLitAsU8 { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - use syntax::ast::{Lit_, UintTy}; + use syntax::ast::{LitKind, UintTy}; if let ExprCast(ref e, _) = expr.node { if let ExprLit(ref l) = e.node { - if let Lit_::LitChar(_) = l.node { - if ty::TyUint(UintTy::TyU8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { + if let LitKind::Char(_) = l.node { + if ty::TyUint(UintTy::U8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { let msg = "casting character literal to u8. `char`s \ are 4 bytes wide in rust, so casting to u8 \ truncates them"; @@ -676,31 +676,31 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx let which = match (ty, cv) { (&ty::TyBool, Bool(false)) => Minimum, - (&ty::TyInt(IntTy::TyIs), Int(x)) if x == ::std::isize::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::TyI8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::TyI16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::TyI32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::TyI64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum, - (&ty::TyUint(UintTy::TyUs), Uint(x)) if x == ::std::usize::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::TyU8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::TyU16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::TyU32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::TyU64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum, (&ty::TyBool, Bool(true)) => Maximum, - (&ty::TyInt(IntTy::TyIs), Int(x)) if x == ::std::isize::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::TyI8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::TyI16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::TyI32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::TyI64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum, - - (&ty::TyUint(UintTy::TyUs), Uint(x)) if x == ::std::usize::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::TyU8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::TyU16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::TyU32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::TyU64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum, + (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MAX as i64 => Maximum, + (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum, + (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum, + (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum, + (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum, + + (&ty::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MAX as u64 => Maximum, + (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum, + (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum, + (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum, + (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum, _ => return None, }; diff --git a/src/unicode.rs b/src/unicode.rs index f363eace713..c8d810b9e71 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; -use syntax::ast::Lit_; +use syntax::ast::LitKind; use unicode_normalization::UnicodeNormalization; @@ -59,7 +59,7 @@ impl LintPass for Unicode { impl LateLintPass for Unicode { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprLit(ref lit) = expr.node { - if let Lit_::LitStr(_, _) = lit.node { + if let LitKind::Str(_, _) = lit.node { check_str(cx, lit.span) } } diff --git a/src/utils.rs b/src/utils.rs index 4c89b7f113d..cd4a34d95b3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,8 +10,7 @@ use std::borrow::Cow; use std::mem; use std::ops::{Deref, DerefMut}; use std::str::FromStr; -use syntax::ast::Lit_; -use syntax::ast; +use syntax::ast::{LitKind, self}; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; @@ -531,7 +530,7 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { // FIXME: use constant folding if let ExprLit(ref spanned) = expr.node { - if let Lit_::LitInt(v, _) = spanned.node { + if let LitKind::Int(v, _) = spanned.node { return v == value; } } @@ -575,9 +574,9 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' if attr.is_sugared_doc { continue; } - if let ast::MetaNameValue(ref key, ref value) = attr.value.node { + if let ast::MetaItemKind::NameValue(ref key, ref value) = attr.value.node { if *key == name { - if let Lit_::LitStr(ref s, _) = value.node { + if let LitKind::Str(ref s, _) = value.node { if let Ok(value) = FromStr::from_str(s) { f(value) } else { diff --git a/tests/consts.rs b/tests/consts.rs index 75082e646a0..1d639c8092b 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -11,13 +11,11 @@ use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; -use syntax::ast::Lit_::*; -use syntax::ast::Lit_; -use syntax::ast::LitIntType::*; -use syntax::ast::StrStyle::*; -use syntax::ast::Sign::*; +use syntax::ast::LitKind; +use syntax::ast::LitIntType; +use syntax::ast::StrStyle; -use clippy::consts::{constant_simple, Constant}; +use clippy::consts::{constant_simple, Constant, Sign}; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } @@ -32,7 +30,7 @@ fn expr(n: Expr_) -> Expr { } } -fn lit(l: Lit_) -> Expr { +fn lit(l: LitKind) -> Expr { expr(ExprLit(P(spanned(l)))) } @@ -46,26 +44,26 @@ fn check(expect: Constant, expr: &Expr) { const TRUE : Constant = Constant::Bool(true); const FALSE : Constant = Constant::Bool(false); -const ZERO : Constant = Constant::Int(0, UnsuffixedIntLit(Plus)); -const ONE : Constant = Constant::Int(1, UnsuffixedIntLit(Plus)); -const TWO : Constant = Constant::Int(2, UnsuffixedIntLit(Plus)); +const ZERO : Constant = Constant::Int(0, LitIntType::Unsuffixed, Sign::Plus); +const ONE : Constant = Constant::Int(1, LitIntType::Unsuffixed, Sign::Plus); +const TWO : Constant = Constant::Int(2, LitIntType::Unsuffixed, Sign::Plus); #[test] fn test_lit() { - check(TRUE, &lit(LitBool(true))); - check(FALSE, &lit(LitBool(false))); - check(ZERO, &lit(LitInt(0, UnsuffixedIntLit(Plus)))); - check(Constant::Str("cool!".into(), CookedStr), &lit(LitStr( - InternedString::new("cool!"), CookedStr))); + check(TRUE, &lit(LitKind::Bool(true))); + check(FALSE, &lit(LitKind::Bool(false))); + check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed))); + check(Constant::Str("cool!".into(), StrStyle::Cooked), &lit(LitKind::Str( + InternedString::new("cool!"), StrStyle::Cooked))); } #[test] fn test_ops() { - check(TRUE, &binop(BiOr, lit(LitBool(false)), lit(LitBool(true)))); - check(FALSE, &binop(BiAnd, lit(LitBool(false)), lit(LitBool(true)))); + check(TRUE, &binop(BiOr, lit(LitKind::Bool(false)), lit(LitKind::Bool(true)))); + check(FALSE, &binop(BiAnd, lit(LitKind::Bool(false)), lit(LitKind::Bool(true)))); - let litzero = lit(LitInt(0, UnsuffixedIntLit(Plus))); - let litone = lit(LitInt(1, UnsuffixedIntLit(Plus))); + let litzero = lit(LitKind::Int(0, LitIntType::Unsuffixed)); + let litone = lit(LitKind::Int(1, LitIntType::Unsuffixed)); check(TRUE, &binop(BiEq, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiGe, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiLe, litzero.clone(), litzero.clone())); -- cgit 1.4.1-3-g733a5 From b5dac50c5c2e04545af1149192743b663e7636be Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 00:44:27 +0530 Subject: Bump to 0.0.38 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9a0b0b37bae..c4479e15d47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.37" +version = "0.0.38" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 17b7b413f7e89be6879ea99c3aefc76c41416e87 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 02:59:39 +0530 Subject: Add @mcarton as owner --- Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c4479e15d47..ba1198b9d88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "clippy" -version = "0.0.38" +version = "0.0.39" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", - "Georg Brandl <georg@python.org>" + "Georg Brandl <georg@python.org>", + "Martin Carton <cartonmartin@gmail.com>" ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/Manishearth/rust-clippy" -- cgit 1.4.1-3-g733a5 From 7f567ce1d18a3d4579567fae33bfceaa0b18a9ff Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 01:38:55 +0100 Subject: Fix false negative with OK_EXPECT --- src/methods.rs | 25 +++++-------------------- tests/compile-fail/methods.rs | 4 +--- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 9263d657371..175e3b5c033 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -274,7 +274,6 @@ declare_lint! { /// println!("{:p} {:p}",*y, z); // prints out the same pointer /// } /// ``` -/// declare_lint! { pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`" } @@ -789,26 +788,12 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { None } -/// This checks whether a given type is known to implement Debug. It's -/// conservative, i.e. it should not return false positives, but will return -/// false negatives. +/// This checks whether a given type is known to implement Debug. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { - let no_ref_ty = walk_ptrs_ty(ty); - let debug = match cx.tcx.lang_items.debug_trait() { - Some(debug) => debug, - None => return false, - }; - let debug_def = cx.tcx.lookup_trait_def(debug); - let mut debug_impl_exists = false; - debug_def.for_each_relevant_impl(cx.tcx, no_ref_ty, |d| { - let self_ty = &cx.tcx.impl_trait_ref(d).and_then(|im| im.substs.self_ty()); - if let Some(self_ty) = *self_ty { - if !self_ty.flags.get().contains(ty::TypeFlags::HAS_PARAMS) { - debug_impl_exists = true; - } - } - }); - debug_impl_exists + match cx.tcx.lang_items.debug_trait() { + Some(debug) => implements_trait(cx, ty, debug, Some(vec![])), + None => false, + } } #[cfg_attr(rustfmt, rustfmt_skip)] diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 4e515c2aa12..043f9e7bcac 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -274,10 +274,8 @@ fn main() { // the error type implements `Debug` let res2: Result<i32, MyError> = Ok(0); res2.ok().expect("oh noes!"); - // we currently don't warn if the error type has a type parameter - // (but it would be nice if we did) let res3: Result<u32, MyErrorWithParam<u8>>= Ok(0); - res3.ok().expect("whoof"); + res3.ok().expect("whoof"); //~ERROR called `ok().expect()` let res4: Result<u32, io::Error> = Ok(0); res4.ok().expect("argh"); //~ERROR called `ok().expect()` let res5: io::Result<u32> = Ok(0); -- cgit 1.4.1-3-g733a5 From edc0d19a3f1f32dc16dc307e30dd2637f5a5fb04 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 01:42:46 +0100 Subject: Add `new` to WRONG_SELF_CONVENTION --- src/methods.rs | 93 +++++++++++++++++++++++++++---------------- tests/compile-fail/methods.rs | 2 + 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 175e3b5c033..3787474e28c 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,11 +1,11 @@ -use rustc_front::hir::*; use rustc::lint::*; -use rustc::middle::ty; use rustc::middle::subst::{Subst, TypeSpace}; -use std::iter; +use rustc::middle::ty; +use rustc_front::hir::*; use std::borrow::Cow; -use syntax::ptr::P; +use std::{fmt, iter}; use syntax::codemap::Span; +use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, match_type, method_chain_args, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, @@ -367,10 +367,11 @@ impl LateLintPass for MethodsPass { } } } + // check conventions w.r.t. conversion method names and predicates let is_copy = is_copy(cx, &ty, &item); - for &(prefix, self_kinds) in &CONVENTIONS { - if name.as_str().starts_with(prefix) && + for &(ref conv, self_kinds) in &CONVENTIONS { + if conv.check(&name.as_str()) && !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { let lint = if item.vis == Visibility::Public { WRONG_PUB_SELF_CONVENTION @@ -380,9 +381,9 @@ impl LateLintPass for MethodsPass { span_lint(cx, lint, sig.explicit_self.span, - &format!("methods called `{}*` usually take {}; consider choosing a less \ + &format!("methods called `{}` usually take {}; consider choosing a less \ ambiguous name", - prefix, + conv, &self_kinds.iter() .map(|k| k.description()) .collect::<Vec<_>>() @@ -796,47 +797,53 @@ fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { } } +enum Convention { + Eq(&'static str), + StartsWith(&'static str), +} + #[cfg_attr(rustfmt, rustfmt_skip)] -const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [ - ("into_", &[SelfKind::Value]), - ("to_", &[SelfKind::Ref]), - ("as_", &[SelfKind::Ref, SelfKind::RefMut]), - ("is_", &[SelfKind::Ref, SelfKind::No]), - ("from_", &[SelfKind::No]), +const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [ + (Convention::Eq("new"), &[SelfKind::No]), + (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), + (Convention::StartsWith("from_"), &[SelfKind::No]), + (Convention::StartsWith("into_"), &[SelfKind::Value]), + (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), + (Convention::StartsWith("to_"), &[SelfKind::Ref]), ]; #[cfg_attr(rustfmt, rustfmt_skip)] const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), - ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), - ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), - ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), - ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), - ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), - ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), + ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), - ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), - ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), - ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), - ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), - ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), - ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), - ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), - ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), - ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), - ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), - ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), + ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), - ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), - ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), - ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), + ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), + ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), + ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), + ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), + ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), + ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), + ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), + ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), + ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), + ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), + ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), + ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), + ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), + ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), ]; #[derive(Clone, Copy)] @@ -881,6 +888,24 @@ impl SelfKind { } } +impl Convention { + fn check(&self, other: &str) -> bool { + match *self { + Convention::Eq(this) => this == other, + Convention::StartsWith(this) => other.starts_with(this), + } + } +} + +impl fmt::Display for Convention { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Convention::Eq(this) => this.fmt(f), + Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), + } + } +} + #[derive(Clone, Copy)] enum OutType { Unit, diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 043f9e7bcac..9a10b336e0e 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -22,6 +22,8 @@ impl T { fn into_u16(&self) -> u16 { 0 } //~ERROR methods called `into_*` usually take self by value fn to_something(self) -> u32 { 0 } //~ERROR methods called `to_*` usually take self by reference + + fn new(self) {} //~ERROR methods called `new` usually take no self } #[derive(Clone,Copy)] -- cgit 1.4.1-3-g733a5 From d4ebd68df2d1a4511ab26adc4850fd66f2343e37 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 08:45:36 +0530 Subject: Clarify readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c2d3b16074c..e42d3717e16 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ Add in your `Cargo.toml`: clippy = "*" ``` -You may also use [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), a custom cargo subcommand that runs clippy on a given project. +You then need to add `#![feature(plugin)]` and `#![plugin(clippy)]` to the top of your crate entry point (`main.rs` or `lib.rs`). Sample `main.rs`: ```rust @@ -172,6 +172,9 @@ src/main.rs:8:5: 11:6 help: Try if let Some(y) = x { println!("{:?}", y) } ``` + +An alternate way to use clippy is by compiling and using [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), a custom cargo subcommand that runs clippy on a given project. + You can add options to `allow`/`warn`/`deny`: - the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) - all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive lints prone to false positives. -- cgit 1.4.1-3-g733a5 From e8c2aa2997861c745c01c837aa14eec24627f584 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 02:20:22 +0100 Subject: Lint about `new` methods not returning `Self` --- README.md | 3 ++- src/lib.rs | 1 + src/methods.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/methods.rs | 13 ++++++++++++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c2d3b16074c..5a405c6d4ca 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 120 lints included in this crate: +There are 121 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -76,6 +76,7 @@ name [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file diff --git a/src/lib.rs b/src/lib.rs index 675dbdd2dd7..8d29d6ab68a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -234,6 +234,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::CLONE_ON_COPY, methods::EXTEND_FROM_SLICE, methods::FILTER_NEXT, + methods::NEW_RET_NO_SELF, methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, diff --git a/src/methods.rs b/src/methods.rs index 3787474e28c..ed3f61e4a72 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -278,6 +278,23 @@ declare_lint! { pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`" } +/// **What it does:** This lint warns about `new` not returning `Self`. +/// +/// **Why is this bad?** As a convention, `new` methods are used to make a new instance of a type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl Foo { +/// fn new(..) -> NotAFoo { +/// } +/// } +/// ``` +declare_lint! { + pub NEW_RET_NO_SELF, Warn, "not returning `Self` in a `new` method" +} + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -294,7 +311,8 @@ impl LintPass for MethodsPass { OR_FUN_CALL, CHARS_NEXT_CMP, CLONE_ON_COPY, - CLONE_DOUBLE_REF) + CLONE_DOUBLE_REF, + NEW_RET_NO_SELF) } } @@ -390,6 +408,29 @@ impl LateLintPass for MethodsPass { .join(" or "))); } } + + if &name.as_str() == &"new" { + let returns_self = if let FunctionRetTy::Return(ref ret_ty) = sig.decl.output { + let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + let ty = ast_ty_to_ty_cache.get(&ty.id); + let ret_ty = ast_ty_to_ty_cache.get(&ret_ty.id); + + match (ty, ret_ty) { + (Some(&ty), Some(&ret_ty)) => ret_ty.walk().any(|t| t == ty), + _ => false, + } + } + else { + false + }; + + if !returns_self { + span_lint(cx, + NEW_RET_NO_SELF, + sig.explicit_self.span, + "methods called `new` usually return `Self`"); + } + } } } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 9a10b336e0e..afe056e3d05 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -23,16 +23,27 @@ impl T { fn to_something(self) -> u32 { 0 } //~ERROR methods called `to_*` usually take self by reference - fn new(self) {} //~ERROR methods called `new` usually take no self + fn new(self) {} + //~^ ERROR methods called `new` usually take no self + //~| ERROR methods called `new` usually return `Self` } #[derive(Clone,Copy)] struct U; impl U { + fn new() -> Self { U } fn to_something(self) -> u32 { 0 } // ok because U is Copy } +struct V<T> { + _dummy: T +} + +impl<T> V<T> { + fn new() -> Option<V<T>> { None } +} + impl Mul<T> for T { type Output = T; fn mul(self, other: T) -> T { self } // no error, obviously -- cgit 1.4.1-3-g733a5 From 9fd1745db6d2fef9f1551824bdfa14cccf6f5fe0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 17:38:08 +0530 Subject: +license --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e42d3717e16..524a2d18ddd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ #rust-clippy [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) +[![Current Version](http://meritbadge.herokuapp.com/optional)](https://crates.io/crates/clippy) +[![License: MIT/Apache](https://img.shields.io/crates/l/clippy.svg)](#License) A collection of lints to catch common mistakes and improve your Rust code. -- cgit 1.4.1-3-g733a5 From d964e18b90722a56fa9035403920acb23ed88615 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 17:43:28 +0530 Subject: Wrong crate --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 524a2d18ddd..44c7cbc50d1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ #rust-clippy [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) -[![Current Version](http://meritbadge.herokuapp.com/optional)](https://crates.io/crates/clippy) +[![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MIT/Apache](https://img.shields.io/crates/l/clippy.svg)](#License) A collection of lints to catch common mistakes and improve your Rust code. -- cgit 1.4.1-3-g733a5 From 1efc88f10a182d263baa4f267be756b1fb01492a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 13:17:48 +0100 Subject: Rustup to 1.8.0-nightly (ce4b75f25 2016-02-12) --- src/enum_variants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enum_variants.rs b/src/enum_variants.rs index c77e42e69c9..1dab2c40891 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -45,7 +45,7 @@ impl EarlyLintPass for EnumVariantNames { if def.variants.len() < 2 { return; } - let first = var2str(&*def.variants[0]); + let first = var2str(&def.variants[0]); let mut pre = first.to_string(); let mut post = pre.clone(); for var in &def.variants[1..] { -- cgit 1.4.1-3-g733a5 From 1e176cae5da892c2920abeeaa84feeb12f3c5442 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sat, 13 Feb 2016 18:01:33 +0530 Subject: Bump twice --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ba1198b9d88..4797b7b37a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.39" +version = "0.0.41" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/README.md b/README.md index 44c7cbc50d1..a85d494e029 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ #rust-clippy [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) -[![License: MIT/Apache](https://img.shields.io/crates/l/clippy.svg)](#License) +[![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) A collection of lints to catch common mistakes and improve your Rust code. -- cgit 1.4.1-3-g733a5 From 49e2501c633d519d56352609afda8103dbe8a2e8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 15:36:57 +0100 Subject: Fix false positive for `ifs_same_cond` and `cfg!` --- src/utils/hir.rs | 5 +++++ tests/compile-fail/copies.rs | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/utils/hir.rs b/src/utils/hir.rs index f8695956f09..e527f63ebbd 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -4,6 +4,7 @@ use rustc_front::hir::*; use std::hash::{Hash, Hasher, SipHasher}; use syntax::ast::Name; use syntax::ptr::P; +use utils::differing_macro_contexts; /// Type used to check whether two ast are the same. This is different from the operator /// `==` on ast types as this operator would compare true equality with ID and span. @@ -53,6 +54,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { // ok, it’s a big function, but mostly one big match with simples cases #[allow(cyclomatic_complexity)] pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + if self.ignore_fn && differing_macro_contexts(left.span, right.span) { + return false; + } + if let (Some(l), Some(r)) = (constant(self.cx, left), constant(self.cx, right)) { if l == r { return true; diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 623f9967bd4..7a17b345fa8 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -12,7 +12,7 @@ fn foo() -> bool { unimplemented!() } #[deny(if_same_then_else)] #[deny(match_same_arms)] -fn if_same_then_else() -> &'static str { +fn if_same_then_else() -> Result<&'static str, ()> { if true { foo(); } @@ -129,17 +129,24 @@ fn if_same_then_else() -> &'static str { _ => (), } + if true { + try!(Ok("foo")); + } + else { //~ERROR this `if` has identical blocks + try!(Ok("foo")); + } + if true { let foo = ""; - return &foo[0..]; + return Ok(&foo[0..]); } else if false { let foo = "bar"; - return &foo[0..]; + return Ok(&foo[0..]); } else { //~ERROR this `if` has identical blocks let foo = ""; - return &foo[0..]; + return Ok(&foo[0..]); } } @@ -168,6 +175,15 @@ fn ifs_same_cond() { else if a == 1 { } + // See #659 + if cfg!(feature = "feature1-659") { + 1 + } else if cfg!(feature = "feature2-659") { + 2 + } else { + 3 + }; + let mut v = vec![1]; if v.pop() == None { // ok, functions } -- cgit 1.4.1-3-g733a5 From d589a2d516a4b35af22dee60f9e7ae57622cea00 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 22:08:15 +0100 Subject: Fix comment --- src/copies.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/copies.rs b/src/copies.rs index e2defe8f364..b975aefe125 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -48,6 +48,7 @@ declare_lint! { /// Bar => bar(), /// Quz => quz(), /// Baz => bar(), // <= oups +/// } /// ``` declare_lint! { pub MATCH_SAME_ARMS, -- cgit 1.4.1-3-g733a5 From 4562040d6b640fa448fedcb7db9124b6abcaba5b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 13 Feb 2016 22:09:17 +0100 Subject: Fix false positive in `NEEDLESS_RANGE_LOOP` --- src/loops.rs | 23 ++++++++++++++++++----- tests/compile-fail/for_loop.rs | 6 ++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index cecf47daf55..bbbff676350 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -4,6 +4,7 @@ use rustc::lint::*; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; use rustc::middle::def::Def; +use rustc::middle::region::CodeExtent; use rustc::middle::ty; use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; @@ -338,20 +339,28 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex if let ExprRange(Some(ref l), ref r) = arg.node { // the var must be a single name if let PatIdent(_, ref ident, _) = pat.node { + let mut visitor = VarVisitor { cx: cx, var: ident.node.name, - indexed: HashSet::new(), + indexed: HashMap::new(), nonindex: false, }; walk_expr(&mut visitor, body); + // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let indexed = visitor.indexed + let (indexed, indexed_extent) = visitor.indexed .into_iter() .next() .expect("Len was nonzero, but no contents found"); + // ensure that the indexed variable was declared before the loop, see #601 + let pat_extent = cx.tcx.region_maps.var_scope(pat.id); + if cx.tcx.region_maps.is_subscope_of(indexed_extent, pat_extent) { + return; + } + let starts_at_zero = is_integer_literal(l, 0); let skip: Cow<_> = if starts_at_zero { @@ -673,7 +682,7 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { struct VarVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference var: Name, // var name to look for as index - indexed: HashSet<Name>, // indexed variables + indexed: HashMap<Name, CodeExtent>, // indexed variables nonindex: bool, // has the var been used otherwise? } @@ -689,8 +698,12 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { let ExprPath(None, ref seqvar) = seqexpr.node, seqvar.segments.len() == 1 ], { - self.indexed.insert(seqvar.segments[0].identifier.name); - return; // no need to walk further + let def_map = self.cx.tcx.def_map.borrow(); + if let Some(def) = def_map.get(&seqexpr.id) { + let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); + self.indexed.insert(seqvar.segments[0].identifier.name, extent); + return; // no need to walk further + } } } // we are not indexing anything, record that diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 4609c840836..b805963a03a 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -192,6 +192,12 @@ fn main() { println!("{}", i); } + // See #601 + for i in 0..10 { // no error, id_col does not exist outside the loop + let mut id_col = vec![0f64; 10]; + id_col[i] = 1f64; + } + /* for i in (10..0).map(|x| x * 2) { println!("{}", i); -- cgit 1.4.1-3-g733a5 From cbe2de7fd273d25e6fc37abb4094a3ecfabbe359 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 14 Feb 2016 12:07:56 +0100 Subject: Address small nit --- src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index bbbff676350..2754f743caa 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -9,7 +9,7 @@ use rustc::middle::ty; use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; -use std::collections::{HashSet, HashMap}; +use std::collections::HashMap; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty}; @@ -353,7 +353,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex let (indexed, indexed_extent) = visitor.indexed .into_iter() .next() - .expect("Len was nonzero, but no contents found"); + .unwrap_or_else(|| unreachable!() /* len == 1 */); // ensure that the indexed variable was declared before the loop, see #601 let pat_extent = cx.tcx.region_maps.var_scope(pat.id); -- cgit 1.4.1-3-g733a5 From 30a8dfb31ae401a104bfbb870a528225b4d6b2e0 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 14 Feb 2016 16:55:02 +0100 Subject: remove Visitor from regex_macro --- src/lib.rs | 2 +- src/regex.rs | 66 +++++++++++++++++++++++++++++------------------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8d29d6ab68a..cb3d3d5392b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,7 +158,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box vec::UselessVec); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); - reg.register_late_lint_pass(box regex::RegexPass); + reg.register_late_lint_pass(box regex::RegexPass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_lint_group("clippy_pedantic", vec![ diff --git a/src/regex.rs b/src/regex.rs index 5103391e9dd..25c7260abec 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,11 +1,10 @@ use regex_syntax; use std::error::Error; use std::collections::HashSet; -use syntax::ast::LitKind; +use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_block}; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::lint::*; @@ -52,8 +51,11 @@ declare_lint! { "finds use of `regex!(_)`, suggests `Regex::new(_)` instead" } -#[derive(Copy,Clone)] -pub struct RegexPass; +#[derive(Clone, Default)] +pub struct RegexPass { + spans: HashSet<Span>, + last: Option<NodeId> +} impl LintPass for RegexPass { fn get_lints(&self) -> LintArray { @@ -62,11 +64,34 @@ impl LintPass for RegexPass { } impl LateLintPass for RegexPass { - fn check_crate(&mut self, cx: &LateContext, krate: &Crate) { - let mut visitor = RegexVisitor { cx: cx, spans: HashSet::new() }; - krate.visit_all_items(&mut visitor); + fn check_crate(&mut self, _: &LateContext, _: &Crate) { + self.spans.clear(); } + fn check_block(&mut self, cx: &LateContext, block: &Block) { + if_let_chain!{[ + self.last.is_none(), + let Some(ref expr) = block.expr, + match_type(cx, cx.tcx.expr_ty(expr), &["regex", "re", "Regex"]), + let Some(span) = is_expn_of(cx, expr.span, "regex") + ], { + if !self.spans.contains(&span) { + span_lint(cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now."); + self.spans.insert(span); + } + self.last = Some(block.id); + }} + } + + fn check_block_post(&mut self, _: &LateContext, block: &Block) { + if self.last.map_or(false, |id| block.id == id) { + self.last = None; + } + } fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain!{[ @@ -160,30 +185,3 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { _ => None, } } - -struct RegexVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, - spans: HashSet<Span>, -} - -impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { - fn visit_block(&mut self, block: &'v Block) { - if_let_chain!{[ - let Some(ref expr) = block.expr, - match_type(self.cx, self.cx.tcx.expr_ty(expr), &["regex", "re", "Regex"]), - let Some(span) = is_expn_of(self.cx, expr.span, "regex") - ], { - if self.spans.contains(&span) { - return; - } - span_lint(self.cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now."); - self.spans.insert(span); - return; - }} - walk_block(self, block); - } -} -- cgit 1.4.1-3-g733a5 From 1b93d716459346eb0c6de654c5771d95ecf6aaa4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 14 Feb 2016 20:29:32 +0100 Subject: Fix ICE in `EXPL_IMPL_CLONE_ON_COPY` --- src/derive.rs | 20 +++++++++++--------- tests/ice-666.rs | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 tests/ice-666.rs diff --git a/src/derive.rs b/src/derive.rs index e9eef824713..467d55feafd 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::middle::ty::TypeVariants; use rustc::middle::ty::fast_reject::simplify_type; use rustc::middle::ty; use rustc_front::hir::*; @@ -6,7 +7,6 @@ use syntax::ast::{Attribute, MetaItemKind}; use syntax::codemap::Span; use utils::{CLONE_TRAIT_PATH, HASH_PATH}; use utils::{match_path, span_lint_and_then}; -use rustc::middle::ty::TypeVariants; /// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` /// explicitly. @@ -73,14 +73,14 @@ impl LateLintPass for Derive { let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); if_let_chain! {[ - let ItemImpl(_, _, _, Some(ref trait_ref), ref ast_ty, _) = item.node, + let ItemImpl(_, _, ref ast_generics, Some(ref trait_ref), ref ast_ty, _) = item.node, let Some(&ty) = ast_ty_to_ty_cache.get(&ast_ty.id) ], { if item.attrs.iter().any(is_automatically_derived) { check_hash_peq(cx, item.span, trait_ref, ty); } - else { - check_copy_clone(cx, item.span, trait_ref, ty); + else if !ast_generics.is_lt_parameterized() { + check_copy_clone(cx, item, trait_ref, ty); } }} } @@ -127,11 +127,13 @@ fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, + item: &Item, + trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) { - let parameter_environment = cx.tcx.empty_parameter_environment(); + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - if ty.moves_by_default(¶meter_environment, span) { + if ty.moves_by_default(¶meter_environment, item.span) { return; // ty is not Copy } @@ -160,10 +162,10 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: span_lint_and_then(cx, DERIVE_HASH_NOT_EQ, - span, + item.span, "you are implementing `Clone` explicitly on a `Copy` type", |db| { - db.span_note(span, "consider deriving `Clone` or removing `Copy`"); + db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }); } } diff --git a/tests/ice-666.rs b/tests/ice-666.rs new file mode 100644 index 00000000000..b681f4b2c58 --- /dev/null +++ b/tests/ice-666.rs @@ -0,0 +1,24 @@ +#![feature(plugin)] +#![plugin(clippy)] + +pub struct Lt<'a> { + _foo: &'a u8, +} + +impl<'a> Copy for Lt<'a> {} +impl<'a> Clone for Lt<'a> { + fn clone(&self) -> Lt<'a> { + unimplemented!(); + } +} + +pub struct Ty<A> { + _foo: A, +} + +impl<A: Copy> Copy for Ty<A> {} +impl<A> Clone for Ty<A> { + fn clone(&self) -> Ty<A> { + unimplemented!(); + } +} -- cgit 1.4.1-3-g733a5 From 7eea67605a92864530600bde3776c80ce08e790e Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Sun, 14 Feb 2016 22:40:43 -0500 Subject: Lint single-character strings as P: Pattern args Fixes #650 --- README.md | 3 +- src/lib.rs | 1 + src/methods.rs | 62 ++++++++++++++++++++++++++++- src/misc_early.rs | 2 +- tests/compile-fail/methods.rs | 91 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 155 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 483182a68f6..ae5b42e45b3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 121 lints included in this crate: +There are 122 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -104,6 +104,7 @@ name [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value [should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead [str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` diff --git a/src/lib.rs b/src/lib.rs index 8d29d6ab68a..7233eab2921 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,6 +241,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OR_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, + methods::SINGLE_CHAR_PATTERN, methods::STR_TO_STRING, methods::STRING_TO_STRING, methods::WRONG_SELF_CONVENTION, diff --git a/src/methods.rs b/src/methods.rs index ed3f61e4a72..c8c3160ccaa 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,4 +1,6 @@ use rustc::lint::*; +use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::subst::{Subst, TypeSpace}; use rustc::middle::ty; use rustc_front::hir::*; @@ -295,6 +297,20 @@ declare_lint! { pub NEW_RET_NO_SELF, Warn, "not returning `Self` in a `new` method" } +/// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")` +/// +/// **Why is this bad?** Performing these methods using a `str` may be slower than using a `char` +/// +/// **Known problems:** Does not catch multi-byte unicode characters +/// +/// **Example:** `_.split("x")` could be `_.split('x')` +declare_lint! { + pub SINGLE_CHAR_PATTERN, + Warn, + "using a single-character str where a char could be used, e.g. \ + `_.split(\"x\")`" +} + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -312,7 +328,8 @@ impl LintPass for MethodsPass { CHARS_NEXT_CMP, CLONE_ON_COPY, CLONE_DOUBLE_REF, - NEW_RET_NO_SELF) + NEW_RET_NO_SELF, + SINGLE_CHAR_PATTERN) } } @@ -351,6 +368,11 @@ impl LateLintPass for MethodsPass { lint_clone_on_copy(cx, expr); lint_clone_double_ref(cx, expr, &args[0]); } + for &(method, pos) in &PATTERN_METHODS { + if name.node.as_str() == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); + } + } } ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { if !lint_chars_next(cx, expr, lhs, rhs, op.node == BiEq) { @@ -817,6 +839,22 @@ fn lint_chars_next(cx: &LateContext, expr: &Expr, chain: &Expr, other: &Expr, eq false } +/// lint for length-1 `str`s for methods in `PATTERN_METHODS` +fn lint_single_char_pattern(cx: &LateContext, expr: &Expr, arg: &Expr) { + if let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, arg, ExprTypeChecked, None) { + if r.len() == 1 { + let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); + span_lint_and_then(cx, + SINGLE_CHAR_PATTERN, + expr.span, + "single-character string constant used as pattern", + |db| { + db.span_suggestion(expr.span, "try using a char instead:", hint); + }); + } + } +} + /// Given a `Result<T, E>` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { if !match_type(cx, ty, &RESULT_PATH) { @@ -887,6 +925,28 @@ const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30 ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), ]; +#[cfg_attr(rustfmt, rustfmt_skip)] +const PATTERN_METHODS: [(&'static str, usize); 17] = [ + ("contains", 1), + ("starts_with", 1), + ("ends_with", 1), + ("find", 1), + ("rfind", 1), + ("split", 1), + ("rsplit", 1), + ("split_terminator", 1), + ("rsplit_terminator", 1), + ("splitn", 2), + ("rsplitn", 2), + ("matches", 1), + ("rmatches", 1), + ("match_indices", 1), + ("rmatch_indices", 1), + ("trim_left_matches", 1), + ("trim_right_matches", 1), +]; + + #[derive(Clone, Copy)] enum SelfKind { Value, diff --git a/src/misc_early.rs b/src/misc_early.rs index 59a0102aacf..1999d911804 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -104,7 +104,7 @@ impl EarlyLintPass for MiscEarly { if let PatIdent(_, sp_ident, None) = arg.pat.node { let arg_name = sp_ident.node.to_string(); - if arg_name.starts_with("_") { + if arg_name.starts_with('_') { if let Some(correspondance) = registered_names.get(&arg_name[1..]) { span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index afe056e3d05..06dd161ba9e 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(clippy, clippy_pedantic)] -#![allow(unused, print_stdout)] +#![allow(unused, print_stdout, non_ascii_literal)] use std::collections::BTreeMap; use std::collections::HashMap; @@ -355,3 +355,92 @@ fn clone_on_double_ref() { //~^^^ERROR using `clone` on a `Copy` type println!("{:p} {:p}",*y, z); } + +fn single_char_pattern() { + let x = "foo"; + x.split("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.split('x'); + + x.split("xx"); + + x.split('x'); + + let y = "x"; + x.split(y); + + // Not yet testing for multi-byte characters + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` + // should have done this but produced an ICE + x.split("ß"); + x.split("ℝ"); + x.split("💣"); + // Can't use this lint for unicode code points which don't fit in a char + x.split("❤️"); + + x.contains("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.contains('x'); + x.starts_with("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.starts_with('x'); + x.ends_with("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.ends_with('x'); + x.find("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.find('x'); + x.rfind("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rfind('x'); + x.rsplit("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rsplit('x'); + x.split_terminator("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.split_terminator('x'); + x.rsplit_terminator("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rsplit_terminator('x'); + x.splitn(0, "x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.splitn(0, 'x'); + x.rsplitn(0, "x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rsplitn(0, 'x'); + x.matches("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.matches('x'); + x.rmatches("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rmatches('x'); + x.match_indices("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.match_indices('x'); + x.rmatch_indices("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.rmatch_indices('x'); + x.trim_left_matches("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.trim_left_matches('x'); + x.trim_right_matches("x"); + //~^ ERROR single-character string constant used as pattern + //~| HELP try using a char instead: + //~| SUGGESTION x.trim_right_matches('x'); +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 1ca59031389ef3ebd029faf889c5eaae2a169438 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 15 Feb 2016 10:20:26 +0530 Subject: Make derive lint handle generics correctly --- src/derive.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/derive.rs b/src/derive.rs index 467d55feafd..7cb85b8c97b 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::middle::subst::Subst; use rustc::middle::ty::TypeVariants; use rustc::middle::ty::fast_reject::simplify_type; use rustc::middle::ty; @@ -70,16 +71,17 @@ impl LintPass for Derive { impl LateLintPass for Derive { fn check_item(&mut self, cx: &LateContext, item: &Item) { - let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + if_let_chain! {[ - let ItemImpl(_, _, ref ast_generics, Some(ref trait_ref), ref ast_ty, _) = item.node, - let Some(&ty) = ast_ty_to_ty_cache.get(&ast_ty.id) + let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node ], { + + let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; if item.attrs.iter().any(is_automatically_derived) { check_hash_peq(cx, item.span, trait_ref, ty); } - else if !ast_generics.is_lt_parameterized() { + else { check_copy_clone(cx, item, trait_ref, ty); } }} @@ -132,8 +134,9 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) { let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); + let subst_ty = ty.subst(cx.tcx, ¶meter_environment.free_substs); - if ty.moves_by_default(¶meter_environment, item.span) { + if subst_ty.moves_by_default(¶meter_environment, item.span) { return; // ty is not Copy } -- cgit 1.4.1-3-g733a5 From d755b1ebe2204b93c8ab82c6c04699a9e20921f5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 15 Feb 2016 13:25:29 +0100 Subject: Cleanup --- src/derive.rs | 3 --- tests/compile-fail/derive.rs | 11 +++++++++++ tests/ice-666.rs | 24 ------------------------ 3 files changed, 11 insertions(+), 27 deletions(-) delete mode 100644 tests/ice-666.rs diff --git a/src/derive.rs b/src/derive.rs index 7cb85b8c97b..7110cf71424 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -71,12 +71,9 @@ impl LintPass for Derive { impl LateLintPass for Derive { fn check_item(&mut self, cx: &LateContext, item: &Item) { - - if_let_chain! {[ let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node ], { - let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; if item.attrs.iter().any(is_automatically_derived) { check_hash_peq(cx, item.span, trait_ref, ty); diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs index 66b04a66d0f..14b1106add5 100755 --- a/tests/compile-fail/derive.rs +++ b/tests/compile-fail/derive.rs @@ -35,6 +35,17 @@ impl Clone for Qux { fn clone(&self) -> Self { Qux } } +// See #666 +#[derive(Copy)] +struct Lt<'a> { + a: &'a u8, +} + +impl<'a> Clone for Lt<'a> { +//~^ ERROR you are implementing `Clone` explicitly on a `Copy` type + fn clone(&self) -> Self { unimplemented!() } +} + // Ok, `Clone` cannot be derived because of the big array #[derive(Copy)] struct BigArray { diff --git a/tests/ice-666.rs b/tests/ice-666.rs deleted file mode 100644 index b681f4b2c58..00000000000 --- a/tests/ice-666.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -pub struct Lt<'a> { - _foo: &'a u8, -} - -impl<'a> Copy for Lt<'a> {} -impl<'a> Clone for Lt<'a> { - fn clone(&self) -> Lt<'a> { - unimplemented!(); - } -} - -pub struct Ty<A> { - _foo: A, -} - -impl<A: Copy> Copy for Ty<A> {} -impl<A> Clone for Ty<A> { - fn clone(&self) -> Ty<A> { - unimplemented!(); - } -} -- cgit 1.4.1-3-g733a5 From 570b9635354c8d41711f464bcaeb6a7128d1cc2a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 15 Feb 2016 13:44:59 +0100 Subject: Replace potentially ICEgen ast_ty_to_ty_cache --- src/methods.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index ed3f61e4a72..b71d2ffd7a2 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -366,7 +366,7 @@ impl LateLintPass for MethodsPass { return; } - if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node { + if let ItemImpl(_, _, _, None, _, ref items) = item.node { for implitem in items { let name = implitem.name; if let ImplItemKind::Method(ref sig, _) = implitem.node { @@ -387,6 +387,7 @@ impl LateLintPass for MethodsPass { } // check conventions w.r.t. conversion method names and predicates + let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; let is_copy = is_copy(cx, &ty, &item); for &(ref conv, self_kinds) in &CONVENTIONS { if conv.check(&name.as_str()) && @@ -412,12 +413,13 @@ impl LateLintPass for MethodsPass { if &name.as_str() == &"new" { let returns_self = if let FunctionRetTy::Return(ref ret_ty) = sig.decl.output { let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); - let ty = ast_ty_to_ty_cache.get(&ty.id); let ret_ty = ast_ty_to_ty_cache.get(&ret_ty.id); - match (ty, ret_ty) { - (Some(&ty), Some(&ret_ty)) => ret_ty.walk().any(|t| t == ty), - _ => false, + if let Some(&ret_ty) = ret_ty { + ret_ty.walk().any(|t| t == ty) + } + else { + false } } else { @@ -983,12 +985,7 @@ fn is_bool(ty: &Ty) -> bool { false } -fn is_copy(cx: &LateContext, ast_ty: &Ty, item: &Item) -> bool { - match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { - None => false, - Some(ty) => { - let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, ast_ty.span) - } - } +fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &Item) -> bool { + let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); + !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, item.span) } -- cgit 1.4.1-3-g733a5 From 643a223f7123ee832d67732370faffb023ab3ed9 Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Mon, 15 Feb 2016 09:10:31 -0500 Subject: Address nits --- src/methods.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index c8c3160ccaa..f1aaaf633dd 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -297,11 +297,11 @@ declare_lint! { pub NEW_RET_NO_SELF, Warn, "not returning `Self` in a `new` method" } -/// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")` +/// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")`. /// -/// **Why is this bad?** Performing these methods using a `str` may be slower than using a `char` +/// **Why is this bad?** Performing these methods using a `str` may be slower than using a `char`. /// -/// **Known problems:** Does not catch multi-byte unicode characters +/// **Known problems:** Does not catch multi-byte unicode characters. /// /// **Example:** `_.split("x")` could be `_.split('x')` declare_lint! { @@ -846,7 +846,7 @@ fn lint_single_char_pattern(cx: &LateContext, expr: &Expr, arg: &Expr) { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then(cx, SINGLE_CHAR_PATTERN, - expr.span, + arg.span, "single-character string constant used as pattern", |db| { db.span_suggestion(expr.span, "try using a char instead:", hint); -- cgit 1.4.1-3-g733a5 From c22ded11e57ece41455e18e11eba8f64606c8860 Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Mon, 15 Feb 2016 10:32:04 -0500 Subject: Reword lint documentation char is faster, proven by benchmark. --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index f1aaaf633dd..c8d5fa08ff1 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -299,7 +299,7 @@ declare_lint! { /// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")`. /// -/// **Why is this bad?** Performing these methods using a `str` may be slower than using a `char`. +/// **Why is this bad?** Performing these methods using a `char` is faster than using a `str`. /// /// **Known problems:** Does not catch multi-byte unicode characters. /// -- cgit 1.4.1-3-g733a5 From 00b27bf7becf26f3be918f2558e56f617fd716ec Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 15 Feb 2016 17:43:16 +0100 Subject: Fix suggestion in `COLLAPSIBLE_IF` lint --- src/collapsible_if.rs | 4 +--- tests/compile-fail/collapsible_if.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 03c43ef5dc8..e5ad94fc639 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -66,9 +66,7 @@ fn check_if(cx: &LateContext, e: &Expr) { COLLAPSIBLE_IF, block.span, "this `else { if .. }` block can be collapsed", |db| { - db.span_suggestion(block.span, "try", - format!("else {}", - snippet_block(cx, else_.span, ".."))); + db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); }); }} } else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index 85eac28dc38..3bf4128347a 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -22,7 +22,7 @@ fn main() { print!("Hello "); } else { //~ERROR: this `else { if .. }` //~| HELP try - //~| SUGGESTION else if y == "world" + //~| SUGGESTION } else if y == "world" if y == "world" { println!("world!") } @@ -32,7 +32,7 @@ fn main() { print!("Hello "); } else { //~ERROR this `else { if .. }` //~| HELP try - //~| SUGGESTION else if y == "world" + //~| SUGGESTION } else if y == "world" if y == "world" { println!("world") } -- cgit 1.4.1-3-g733a5 From b1e4b496e118b47be06e362286764f077c8d899d Mon Sep 17 00:00:00 2001 From: Joshua Holmer <holmerj@uindy.edu> Date: Mon, 15 Feb 2016 13:36:10 -0500 Subject: Address @ilogiq's nits --- tests/compile-fail/methods.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 06dd161ba9e..c450c953284 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -373,6 +373,9 @@ fn single_char_pattern() { // Not yet testing for multi-byte characters // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` // should have done this but produced an ICE + // + // We may not want to suggest changing these anyway + // See: https://github.com/Manishearth/rust-clippy/issues/650#issuecomment-184328984 x.split("ß"); x.split("ℝ"); x.split("💣"); @@ -443,4 +446,4 @@ fn single_char_pattern() { //~^ ERROR single-character string constant used as pattern //~| HELP try using a char instead: //~| SUGGESTION x.trim_right_matches('x'); -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From cd35b9e38d3520b59eb5ef219cec0f17f7d12f91 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 15 Feb 2016 22:26:20 +0100 Subject: Fix wrong reported lint for EXPL_IMPL_CLONE_ON_COPY --- src/derive.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/derive.rs b/src/derive.rs index 467d55feafd..30ef2be9384 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -16,7 +16,7 @@ use utils::{match_path, span_lint_and_then}; /// an explicitely defined `PartialEq`. In particular, the following must hold for any type: /// /// ```rust -/// k1 == k2 -> hash(k1) == hash(k2) +/// k1 == k2 ⇒ hash(k1) == hash(k2) /// ``` /// /// **Known problems:** None. @@ -161,7 +161,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, } span_lint_and_then(cx, - DERIVE_HASH_NOT_EQ, + EXPL_IMPL_CLONE_ON_COPY, item.span, "you are implementing `Clone` explicitly on a `Copy` type", |db| { -- cgit 1.4.1-3-g733a5 From b5ba621f61a07193d3f7b0e7bd04204cc0dec4b4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 15 Feb 2016 23:38:09 +0100 Subject: Make DERIVE_HASH_NOT_EQ symmetric --- README.md | 2 +- src/derive.rs | 43 ++++++++++++++++++++++++++++++------------- src/lib.rs | 2 +- tests/compile-fail/derive.rs | 10 ++++++++++ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 483182a68f6..05737f142fa 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ name [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver -[derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly +[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected diff --git a/src/derive.rs b/src/derive.rs index e8816731219..084d00d409f 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -32,7 +32,7 @@ use utils::{match_path, span_lint_and_then}; /// } /// ``` declare_lint! { - pub DERIVE_HASH_NOT_EQ, + pub DERIVE_HASH_XOR_EQ, Warn, "deriving `Hash` but implementing `PartialEq` explicitly" } @@ -65,7 +65,7 @@ pub struct Derive; impl LintPass for Derive { fn get_lints(&self) -> LintArray { - lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_NOT_EQ) + lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ) } } @@ -75,19 +75,25 @@ impl LateLintPass for Derive { let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node ], { let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; - if item.attrs.iter().any(is_automatically_derived) { - check_hash_peq(cx, item.span, trait_ref, ty); - } - else { + let is_automatically_derived = item.attrs.iter().any(is_automatically_derived); + + check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); + + if !is_automatically_derived { check_copy_clone(cx, item, trait_ref, ty); } }} } } -/// Implementation of the `DERIVE_HASH_NOT_EQ` lint. -fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty) { - // If `item` is an automatically derived `Hash` implementation +/// Implementation of the `DERIVE_HASH_XOR_EQ` lint. +fn check_hash_peq( + cx: &LateContext, + span: Span, + trait_ref: &TraitRef, + ty: ty::Ty, + hash_is_automatically_derived: bool +) { if_let_chain! {[ match_path(&trait_ref.path, &HASH_PATH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() @@ -103,14 +109,25 @@ fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty let Some(impl_ids) = peq_impls.get(&simpl_ty) ], { for &impl_id in impl_ids { + let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); + + if peq_is_automatically_derived == hash_is_automatically_derived { + return; + } + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); // Only care about `impl PartialEq<Foo> for Foo` - if trait_ref.input_types()[0] == ty && - !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) { + if trait_ref.input_types()[0] == ty { + let mess = if peq_is_automatically_derived { + "you are implementing `Hash` explicitly but have derived `PartialEq`" + } else { + "you are deriving `Hash` but have implemented `PartialEq` explicitly" + }; + span_lint_and_then( - cx, DERIVE_HASH_NOT_EQ, span, - "you are deriving `Hash` but have implemented `PartialEq` explicitly", + cx, DERIVE_HASH_XOR_EQ, span, + mess, |db| { if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { db.span_note( diff --git a/src/lib.rs b/src/lib.rs index 8d29d6ab68a..bd13190f859 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -198,7 +198,7 @@ pub fn plugin_registrar(reg: &mut Registry) { copies::IFS_SAME_COND, copies::MATCH_SAME_ARMS, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, - derive::DERIVE_HASH_NOT_EQ, + derive::DERIVE_HASH_XOR_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, drop_ref::DROP_REF, entry::MAP_ENTRY, diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs index 14b1106add5..06f1388dc05 100755 --- a/tests/compile-fail/derive.rs +++ b/tests/compile-fail/derive.rs @@ -4,6 +4,8 @@ #![deny(warnings)] #![allow(dead_code)] +use std::hash::{Hash, Hasher}; + #[derive(PartialEq, Hash)] struct Foo; @@ -27,6 +29,14 @@ impl PartialEq<Baz> for Baz { fn eq(&self, _: &Baz) -> bool { true } } +#[derive(PartialEq)] +struct Bah; + +impl Hash for Bah { +//~^ ERROR you are implementing `Hash` explicitly but have derived `PartialEq` + fn hash<H: Hasher>(&self, _: &mut H) {} +} + #[derive(Copy)] struct Qux; -- cgit 1.4.1-3-g733a5 From e809eb61d7b150dac9b9810b4d62f31b11db15d1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 15 Feb 2016 16:59:56 +0100 Subject: fix enum_variant_names linting on all caps enum variants --- src/enum_variants.rs | 70 ++++++++++++++++++++++-------------- src/utils/mod.rs | 62 ++++++++++++++++++++++++++++++++ tests/camel_case.rs | 51 ++++++++++++++++++++++++++ tests/compile-fail/enum_variants.rs | 71 +++++++++++++++++++++++++++++++++++++ 4 files changed, 227 insertions(+), 27 deletions(-) create mode 100644 tests/camel_case.rs create mode 100644 tests/compile-fail/enum_variants.rs diff --git a/src/enum_variants.rs b/src/enum_variants.rs index 1dab2c40891..8ad7adf0077 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -6,6 +6,7 @@ use syntax::ast::*; use syntax::parse::token::InternedString; use utils::span_help_and_lint; +use utils::{camel_case_from, camel_case_until}; /// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters /// @@ -31,48 +32,63 @@ fn var2str(var: &Variant) -> InternedString { var.node.name.name.as_str() } -fn partial_match(left: &str, right: &str) -> usize { - left.chars().zip(right.chars()).take_while(|&(l, r)| l == r).count() +/* +FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 +fn partial_match(pre: &str, name: &str) -> usize { + // skip(1) to ensure that the prefix never takes the whole variant name + pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() } -fn partial_rmatch(left: &str, right: &str) -> usize { - left.chars().rev().zip(right.chars().rev()).take_while(|&(l, r)| l == r).count() +fn partial_rmatch(post: &str, name: &str) -> usize { + // skip(1) to ensure that the postfix never takes the whole variant name + post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() +}*/ + +fn partial_match(pre: &str, name: &str) -> usize { + let mut name_iter = name.chars(); + let _ = name_iter.next_back(); // make sure the name is never fully matched + pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() +} + +fn partial_rmatch(post: &str, name: &str) -> usize { + let mut name_iter = name.chars(); + let _ = name_iter.next(); // make sure the name is never fully matched + post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() } impl EarlyLintPass for EnumVariantNames { + // FIXME: #600 + #[allow(while_let_on_iterator)] fn check_item(&mut self, cx: &EarlyContext, item: &Item) { if let ItemKind::Enum(ref def, _) = item.node { if def.variants.len() < 2 { return; } let first = var2str(&def.variants[0]); - let mut pre = first.to_string(); - let mut post = pre.clone(); - for var in &def.variants[1..] { + let mut pre = &first[..camel_case_until(&*first)]; + let mut post = &first[camel_case_from(&*first)..]; + for var in &def.variants { let name = var2str(var); + let pre_match = partial_match(&pre, &name); - let post_match = partial_rmatch(&post, &name); - pre.truncate(pre_match); - let post_end = post.len() - post_match; - post.drain(..post_end); - } - if let Some(c) = first[pre.len()..].chars().next() { - if !c.is_uppercase() { - // non camel case prefix - pre.clear() - } - } - if let Some(c) = first[..(first.len() - post.len())].chars().rev().next() { - if let Some(c1) = post.chars().next() { - if !c.is_lowercase() || !c1.is_uppercase() { - // non camel case postfix - post.clear() + pre = &pre[..pre_match]; + let pre_camel = camel_case_until(&pre); + pre = &pre[..pre_camel]; + while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { + if next.is_lowercase() { + let last = pre.len() - last.len_utf8(); + let last_camel = camel_case_until(&pre[..last]); + pre = &pre[..last_camel]; + } else { + break; } } - } - if pre == "_" { - // don't lint on underscores which are meant to allow dead code - pre.clear(); + + let post_match = partial_rmatch(&post, &name); + let post_end = post.len() - post_match; + post = &post[post_end..]; + let post_camel = camel_case_from(&post); + post = &post[post_camel..]; } let (what, value) = if !pre.is_empty() { ("pre", pre) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9fd52ff0e98..3a7c6c90d51 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -607,3 +607,65 @@ pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> } } } + +/// Returns index of character after first CamelCase component of `s` +pub fn camel_case_until(s: &str) -> usize { + let mut iter = s.char_indices(); + if let Some((_, first)) = iter.next() { + if !first.is_uppercase() { + return 0; + } + } else { + return 0; + } + let mut up = true; + let mut last_i = 0; + for (i, c) in iter { + if up { + if c.is_lowercase() { + up = false; + } else { + return last_i; + } + } else if c.is_uppercase() { + up = true; + last_i = i; + } else if !c.is_lowercase() { + return i; + } + } + if up { + last_i + } else { + s.len() + } +} + +/// Returns index of last CamelCase component of `s`. +pub fn camel_case_from(s: &str) -> usize { + let mut iter = s.char_indices().rev(); + if let Some((_, first)) = iter.next() { + if !first.is_lowercase() { + return s.len(); + } + } else { + return s.len(); + } + let mut down = true; + let mut last_i = s.len(); + for (i, c) in iter { + if down { + if c.is_uppercase() { + down = false; + last_i = i; + } else if !c.is_lowercase() { + return last_i; + } + } else if c.is_lowercase() { + down = true; + } else { + return last_i; + } + } + last_i +} diff --git a/tests/camel_case.rs b/tests/camel_case.rs new file mode 100644 index 00000000000..201b796af1c --- /dev/null +++ b/tests/camel_case.rs @@ -0,0 +1,51 @@ +#[allow(plugin_as_library)] +extern crate clippy; + +use clippy::utils::{camel_case_from, camel_case_until}; + +#[test] +fn from_full() { + assert_eq!(camel_case_from("AbcDef"), 0); + assert_eq!(camel_case_from("Abc"), 0); +} + +#[test] +fn from_partial() { + assert_eq!(camel_case_from("abcDef"), 3); + assert_eq!(camel_case_from("aDbc"), 1); +} + +#[test] +fn from_not() { + assert_eq!(camel_case_from("AbcDef_"), 7); + assert_eq!(camel_case_from("AbcDD"), 5); +} + +#[test] +fn from_caps() { + assert_eq!(camel_case_from("ABCD"), 4); +} + +#[test] +fn until_full() { + assert_eq!(camel_case_until("AbcDef"), 6); + assert_eq!(camel_case_until("Abc"), 3); +} + +#[test] +fn until_not() { + assert_eq!(camel_case_until("abcDef"), 0); + assert_eq!(camel_case_until("aDbc"), 0); +} + +#[test] +fn until_partial() { + assert_eq!(camel_case_until("AbcDef_"), 6); + assert_eq!(camel_case_until("CallTypeC"), 8); + assert_eq!(camel_case_until("AbcDD"), 3); +} + +#[test] +fn until_caps() { + assert_eq!(camel_case_until("ABCD"), 0); +} diff --git a/tests/compile-fail/enum_variants.rs b/tests/compile-fail/enum_variants.rs new file mode 100644 index 00000000000..6589bd35fd3 --- /dev/null +++ b/tests/compile-fail/enum_variants.rs @@ -0,0 +1,71 @@ +#![feature(plugin, non_ascii_idents)] +#![plugin(clippy)] +#![deny(clippy)] + +enum FakeCallType { + CALL, CREATE +} + +enum FakeCallType2 { + CALL, CREATELL +} + +enum Foo { + cFoo, cBar, +} + +enum BadCallType { //~ ERROR: All variants have the same prefix: `CallType` + CallTypeCall, + CallTypeCreate, + CallTypeDestroy, +} + +enum TwoCallType { //~ ERROR: All variants have the same prefix: `CallType` + CallTypeCall, + CallTypeCreate, +} + +enum Consts { //~ ERROR: All variants have the same prefix: `Constant` + ConstantInt, + ConstantCake, + ConstantLie, +} + +enum Two { //~ ERROR: All variants have the same prefix: `Constant` + ConstantInt, + ConstantInfer, +} + +enum Something { + CCall, + CCreate, + CCryogenize, +} + +enum Seal { + With, + Without, +} + +enum Seall { + With, + WithOut, + Withbroken, +} + +enum Sealll { + With, + WithOut, +} + +enum Seallll { //~ ERROR: All variants have the same prefix: `With` + WithOutCake, + WithOut, +} + +enum NonCaps { //~ ERROR: All variants have the same prefix: `Prefix` + Prefix的, + PrefixCake, +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From cf536d7a4fbb82595f439eb812d469eda766bf42 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 15 Feb 2016 17:00:06 +0100 Subject: fallout --- src/consts.rs | 12 ++++++------ src/zero_div_zero.rs | 4 ++-- tests/consts.rs | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 7cb0683711a..37322aeffc8 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -15,16 +15,16 @@ use syntax::ptr::P; #[derive(Debug, Copy, Clone)] pub enum FloatWidth { - Fw32, - Fw64, - FwAny, + F32, + F64, + Any, } impl From<FloatTy> for FloatWidth { fn from(ty: FloatTy) -> FloatWidth { match ty { - FloatTy::F32 => FloatWidth::Fw32, - FloatTy::F64 => FloatWidth::Fw64, + FloatTy::F32 => FloatWidth::F32, + FloatTy::F64 => FloatWidth::F64, } } } @@ -200,7 +200,7 @@ fn lit_to_constant(lit: &LitKind) -> Constant { LitKind::Char(c) => Constant::Char(c), LitKind::Int(value, ty) => Constant::Int(value, ty, Sign::Plus), LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), - LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::FwAny), + LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), LitKind::Bool(b) => Constant::Bool(b), } } diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 1576d699a4a..dbfa2744189 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -47,8 +47,8 @@ impl LateLintPass for ZeroDivZeroPass { // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, // match the precision of the literals that are given. let float_type = match (lhs_width, rhs_width) { - (FloatWidth::Fw64, _) - | (_, FloatWidth::Fw64) => "f64", + (FloatWidth::F64, _) + | (_, FloatWidth::F64) => "f64", _ => "f32" }; span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, diff --git a/tests/consts.rs b/tests/consts.rs index 67be4243335..5c6088d0554 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -77,9 +77,9 @@ fn test_ops() { check(ONE, &binop(BiMul, litone.clone(), litone.clone())); check(ONE, &binop(BiDiv, litone.clone(), litone.clone())); - let half_any = Constant::Float("0.5".into(), FloatWidth::FwAny); - let half32 = Constant::Float("0.5".into(), FloatWidth::Fw32); - let half64 = Constant::Float("0.5".into(), FloatWidth::Fw64); + let half_any = Constant::Float("0.5".into(), FloatWidth::Any); + let half32 = Constant::Float("0.5".into(), FloatWidth::F32); + let half64 = Constant::Float("0.5".into(), FloatWidth::F64); assert_eq!(half_any, half32); assert_eq!(half_any, half64); -- cgit 1.4.1-3-g733a5 From 227ff8c4ad881b99222d1f3feda559a8db95a8d3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 17 Feb 2016 13:38:44 +0100 Subject: Rustup to 1.8.0-nightly (57c357d89 2016-02-16) --- src/misc_early.rs | 10 +++++----- src/returns.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/misc_early.rs b/src/misc_early.rs index 59a0102aacf..cdc95c9924e 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -43,7 +43,7 @@ impl LintPass for MiscEarly { impl EarlyLintPass for MiscEarly { fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { - if let PatStruct(ref npat, ref pfields, _) = pat.node { + if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; let type_name = match npat.segments.last() { Some(elem) => format!("{}", elem.identifier.name), @@ -51,7 +51,7 @@ impl EarlyLintPass for MiscEarly { }; for field in pfields { - if field.node.pat.node == PatWild { + if field.node.pat.node == PatKind::Wild { wilds += 1; } } @@ -67,14 +67,14 @@ impl EarlyLintPass for MiscEarly { let mut normal = vec![]; for field in pfields { - if field.node.pat.node != PatWild { + if field.node.pat.node != PatKind::Wild { if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { normal.push(n); } } } for field in pfields { - if field.node.pat.node == PatWild { + if field.node.pat.node == PatKind::Wild { wilds -= 1; if wilds > 0 { span_lint(cx, @@ -101,7 +101,7 @@ impl EarlyLintPass for MiscEarly { let mut registered_names: HashMap<String, Span> = HashMap::new(); for ref arg in &decl.inputs { - if let PatIdent(_, sp_ident, None) = arg.pat.node { + if let PatKind::Ident(_, sp_ident, None) = arg.pat.node { let arg_name = sp_ident.node.to_string(); if arg_name.starts_with("_") { diff --git a/src/returns.rs b/src/returns.rs index 63864eafcd2..bfddee797b8 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -97,7 +97,7 @@ impl ReturnPass { let StmtKind::Decl(ref decl, _) = stmt.node, let DeclKind::Local(ref local) = decl.node, let Some(ref initexpr) = local.init, - let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, + let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, let ExprKind::Path(_, ref path) = retexpr.node, match_path_ast(path, &[&id.name.as_str()]) ], { -- cgit 1.4.1-3-g733a5 From 31db60ccc50b3d823f3b384b5830039738a76ec4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 18 Feb 2016 10:52:53 +0530 Subject: Bump and publish to 0.0.41 (fix #683) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4797b7b37a9..06fd32d8424 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.41" +version = "0.0.42" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From add483afedc86aa56913de6debadfa4f867675ad Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 18 Feb 2016 16:08:45 +0100 Subject: fix enum glob use (again) --- src/enum_glob_use.rs | 8 +++++--- tests/compile-fail/enum_glob_use.rs | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index c6561461e04..f8afdf627e2 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -44,9 +44,11 @@ impl EnumGlobUse { if let ItemUse(ref item_use) = item.node { if let ViewPath_::ViewPathGlob(_) = item_use.node { let def = cx.tcx.def_map.borrow()[&item.id]; - if let Some(NodeItem(it)) = cx.tcx.map.get_if_local(def.def_id()) { - if let ItemEnum(..) = it.node { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { + if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { + if let ItemEnum(..) = it.node { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } } } else { if let Some(dp) = cx.sess().cstore.def_path(def.def_id()).last() { diff --git a/tests/compile-fail/enum_glob_use.rs b/tests/compile-fail/enum_glob_use.rs index fc5f531ba90..27f0ff24579 100644 --- a/tests/compile-fail/enum_glob_use.rs +++ b/tests/compile-fail/enum_glob_use.rs @@ -17,4 +17,8 @@ mod blurg { pub use std::cmp::Ordering::*; // ok, re-export } +mod tests { + use super::*; +} + fn main() {} -- cgit 1.4.1-3-g733a5 From 1fd0676fa3c859ec9f0e83fc7266189ea62b4635 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Thu, 18 Feb 2016 20:12:33 +0100 Subject: improve str_add_assign lint description --- src/strings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index 14c2e877919..a7dca02c967 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -13,9 +13,9 @@ use utils::STRING_PATH; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). /// -/// **Why is this bad?** Because this expression needs another copy as opposed to `x.push_str(y)` (in practice LLVM will usually elide it, though). Despite [llogiq](https://github.com/llogiq)'s reservations, this lint also is `allow` by default, as some people opine that it's more readable. +/// **Why is this bad?** It's not really bad, but some people think that the `.push_str(_)` method is more readable. /// -/// **Known problems:** None. Well apart from the lint being `allow` by default. :smile: +/// **Known problems:** None. /// /// **Example:** /// -- cgit 1.4.1-3-g733a5 From aa1df8e9fff6db1aec49e1d01f5495fce1c653ac Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 18 Feb 2016 20:19:16 +0100 Subject: Improve the `MAP_ENTRY` lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t span a suggestion when not appropriate but use a note and don’t force it to be `if !cond`. --- src/entry.rs | 140 ++++++++++++++++++++++++++++---------------- tests/compile-fail/entry.rs | 24 +++++--- 2 files changed, 104 insertions(+), 60 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index c2f2e956e5e..6242b44dd6e 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; +use rustc_front::intravisit::{Visitor, walk_expr, walk_block}; use syntax::codemap::Span; use utils::SpanlessEq; use utils::{BTREEMAP_PATH, HASHMAP_PATH}; @@ -41,73 +42,108 @@ impl LintPass for HashMapLint { impl LateLintPass for HashMapLint { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain! { - [ - let ExprIf(ref check, ref then, _) = expr.node, - let ExprUnary(UnOp::UnNot, ref check) = check.node, - let ExprMethodCall(ref name, _, ref params) = check.node, - params.len() >= 2, - name.node.as_str() == "contains_key" - ], { - let key = match params[1].node { - ExprAddrOf(_, ref key) => key, - _ => return - }; - - let map = ¶ms[0]; - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); - - let kind = if match_type(cx, obj_ty, &BTREEMAP_PATH) { - "BTreeMap" - } - else if match_type(cx, obj_ty, &HASHMAP_PATH) { - "HashMap" - } - else { - return - }; + if let ExprIf(ref check, ref then_block, ref else_block) = expr.node { + if let ExprUnary(UnOp::UnNot, ref check) = check.node { + if let Some((ty, map, key)) = check_cond(cx, check) { + // in case of `if !m.contains_key(&k) { m.insert(k, v); }` + // we can give a better error message + let sole_expr = else_block.is_none() && + if then_block.expr.is_some() { 1 } else { 0 } + then_block.stmts.len() == 1; - let sole_expr = if then.expr.is_some() { 1 } else { 0 } + then.stmts.len() == 1; + let mut visitor = InsertVisitor { + cx: cx, + span: expr.span, + ty: ty, + map: map, + key: key, + sole_expr: sole_expr, + }; - if let Some(ref then) = then.expr { - check_for_insert(cx, expr.span, map, key, then, sole_expr, kind); + walk_block(&mut visitor, then_block); } + } else if let Some(ref else_block) = *else_block { + if let Some((ty, map, key)) = check_cond(cx, check) { + let mut visitor = InsertVisitor { + cx: cx, + span: expr.span, + ty: ty, + map: map, + key: key, + sole_expr: false, + }; - for stmt in &then.stmts { - if let StmtSemi(ref stmt, _) = stmt.node { - check_for_insert(cx, expr.span, map, key, stmt, sole_expr, kind); - } + walk_expr(&mut visitor, else_block); } } } } } -fn check_for_insert(cx: &LateContext, span: Span, map: &Expr, key: &Expr, expr: &Expr, sole_expr: bool, kind: &str) { - if_let_chain! { - [ +fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> Option<(&'static str, &'b Expr, &'b Expr)> { + if_let_chain! {[ + let ExprMethodCall(ref name, _, ref params) = check.node, + params.len() >= 2, + name.node.as_str() == "contains_key", + let ExprAddrOf(_, ref key) = params[1].node + ], { + let map = ¶ms[0]; + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); + + return if match_type(cx, obj_ty, &BTREEMAP_PATH) { + Some(("BTreeMap", map, key)) + } + else if match_type(cx, obj_ty, &HASHMAP_PATH) { + Some(("HashMap", map, key)) + } + else { + None + }; + }} + + None +} + +struct InsertVisitor<'a, 'tcx: 'a, 'b> { + cx: &'a LateContext<'a, 'tcx>, + span: Span, + ty: &'static str, + map: &'b Expr, + key: &'b Expr, + sole_expr: bool, +} + +impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> { + fn visit_expr(&mut self, expr: &'v Expr) { + if_let_chain! {[ let ExprMethodCall(ref name, _, ref params) = expr.node, params.len() == 3, name.node.as_str() == "insert", - get_item_name(cx, map) == get_item_name(cx, &*params[0]), - SpanlessEq::new(cx).eq_expr(key, ¶ms[1]) + get_item_name(self.cx, self.map) == get_item_name(self.cx, &*params[0]), + SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) ], { - let help = if sole_expr { - format!("{}.entry({}).or_insert({})", - snippet(cx, map.span, "map"), - snippet(cx, params[1].span, ".."), - snippet(cx, params[2].span, "..")) - } - else { - format!("{}.entry({})", - snippet(cx, map.span, "map"), - snippet(cx, params[1].span, "..")) - }; - - span_lint_and_then(cx, MAP_ENTRY, span, - &format!("usage of `contains_key` followed by `insert` on `{}`", kind), |db| { - db.span_suggestion(span, "Consider using", help); + + span_lint_and_then(self.cx, MAP_ENTRY, self.span, + &format!("usage of `contains_key` followed by `insert` on `{}`", self.ty), |db| { + if self.sole_expr { + let help = format!("{}.entry({}).or_insert({})", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, ".."), + snippet(self.cx, params[2].span, "..")); + + db.span_suggestion(self.span, "Consider using", help); + } + else { + let help = format!("Consider using `{}.entry({})`", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, "..")); + + db.span_note(self.span, &help); + } }); + }} + + if !self.sole_expr { + walk_expr(self, expr); } } } diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs index a7460282007..7dc4054ec5b 100644 --- a/tests/compile-fail/entry.rs +++ b/tests/compile-fail/entry.rs @@ -19,29 +19,37 @@ fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v); } //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| HELP Consider - //~| SUGGESTION m.entry(k) + //~| NOTE Consider using `m.entry(k)` } fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v) } else { None }; //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| HELP Consider - //~| SUGGESTION m.entry(k).or_insert(v) + //~| NOTE Consider using `m.entry(k)` +} + +fn insert_if_present2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if m.contains_key(&k) { None } else { m.insert(k, v) }; + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| NOTE Consider using `m.entry(k)` } fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| HELP Consider - //~| SUGGESTION m.entry(k) + //~| NOTE Consider using `m.entry(k)` +} + +fn insert_if_present3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { + if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; + //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` + //~| NOTE Consider using `m.entry(k)` } fn insert_in_btreemap<K: Ord, V>(m: &mut BTreeMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; //~^ ERROR usage of `contains_key` followed by `insert` on `BTreeMap` - //~| HELP Consider - //~| SUGGESTION m.entry(k) + //~| NOTE Consider using `m.entry(k)` } fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { -- cgit 1.4.1-3-g733a5 From 35a48bf5120d5a92723896982c16d793cd680e82 Mon Sep 17 00:00:00 2001 From: quininer kel <quininer@live.com> Date: Fri, 19 Feb 2016 04:16:39 +0800 Subject: fix nightly https://github.com/rust-lang/rust/commit/9b40e1e5b3d75c101b1ad78a1e2160962e955174 --- src/copies.rs | 14 +++++++------- src/eta_reduction.rs | 2 +- src/loops.rs | 16 ++++++++-------- src/map_clone.rs | 4 ++-- src/matches.rs | 20 ++++++++++---------- src/misc.rs | 8 ++++---- src/shadow.rs | 12 ++++++------ src/utils/hir.rs | 20 ++++++++++---------- 8 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index b975aefe125..d97745203f0 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -175,13 +175,13 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { match pat.node { - PatBox(ref pat) | PatRegion(ref pat, _) => bindings_impl(cx, pat, map), - PatEnum(_, Some(ref pats)) => { + PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), + PatKind::TupleStruct(_, Some(ref pats)) => { for pat in pats { bindings_impl(cx, pat, map); } } - PatIdent(_, ref ident, ref as_pat) => { + PatKind::Ident(_, ref ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) { v.insert(cx.tcx.pat_ty(pat)); } @@ -189,17 +189,17 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, as_pat, map); } }, - PatStruct(_, ref fields, _) => { + PatKind::Struct(_, ref fields, _) => { for pat in fields { bindings_impl(cx, &pat.node.pat, map); } } - PatTup(ref fields) => { + PatKind::Tup(ref fields) => { for pat in fields { bindings_impl(cx, pat, map); } } - PatVec(ref lhs, ref mid, ref rhs) => { + PatKind::Vec(ref lhs, ref mid, ref rhs) => { for pat in lhs { bindings_impl(cx, pat, map); } @@ -210,7 +210,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, pat, map); } } - PatEnum(..) | PatLit(..) | PatQPath(..) | PatRange(..) | PatWild => (), + PatKind::TupleStruct(..) | PatKind::Lit(..) | PatKind::QPath(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (), } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 280392a50b1..2522b1517a6 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -67,7 +67,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { } } for (ref a1, ref a2) in decl.inputs.iter().zip(args) { - if let PatIdent(_, ident, _) = a1.pat.node { + if let PatKind::Ident(_, ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? if let ExprPath(None, ref p) = a2.node { if p.segments.len() != 1 { diff --git a/src/loops.rs b/src/loops.rs index 2754f743caa..f88c12b4056 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -288,7 +288,7 @@ impl LateLintPass for LoopsPass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatEnum(ref path, Some(ref pat_args)), + if let (&PatKind::TupleStruct(ref path, Some(ref pat_args)), &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; if let Some(lhs_constructor) = path.segments.last() { @@ -338,7 +338,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let ExprRange(Some(ref l), ref r) = arg.node { // the var must be a single name - if let PatIdent(_, ref ident, _) = pat.node { + if let PatKind::Ident(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, @@ -584,7 +584,7 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex // Check for the FOR_KV_MAP lint. fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let PatTup(ref pat) = pat.node { + if let PatKind::Tup(ref pat) = pat.node { if pat.len() == 2 { let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { @@ -622,10 +622,10 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex } // Return true if the pattern is a `PatWild` or an ident prefixed with '_'. -fn pat_is_wild(pat: &Pat_, body: &Expr) -> bool { +fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { - PatWild => true, - PatIdent(_, ident, None) if ident.node.name.as_str().starts_with('_') => { + PatKind::Wild => true, + PatKind::Ident(_, ident, None) if ident.node.name.as_str().starts_with('_') => { let mut visitor = UsedVisitor { var: ident.node, used: false, @@ -668,7 +668,7 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { let Some(ref loopexpr) = block.expr, let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatEnum(_, Some(ref somepats)) = innerarms[0].pats[0].node, + let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, somepats.len() == 1 ], { return Some((&somepats[0], @@ -909,7 +909,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { // Look for declarations of the variable if let DeclLocal(ref local) = decl.node { if local.pat.id == self.var_id { - if let PatIdent(_, ref ident, _) = local.pat.node { + if let PatKind::Ident(_, ref ident, _) = local.pat.node { self.name = Some(ident.node.name); self.state = if let Some(ref init) = local.init { diff --git a/src/map_clone.rs b/src/map_clone.rs index e0255c52fb5..c83e4ca64ff 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -108,8 +108,8 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s fn get_arg_name(pat: &Pat) -> Option<Ident> { match pat.node { - PatIdent(_, ident, None) => Some(ident.node), - PatRegion(ref subpat, _) => get_arg_name(subpat), + PatKind::Ident(_, ident, None) => Some(ident.node), + PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } } diff --git a/src/matches.rs b/src/matches.rs index ca410a413bd..b8ea4f2b1b0 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -157,7 +157,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { - if arms[1].pats[0].node == PatWild { + if arms[1].pats[0].node == PatKind::Wild { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { @@ -192,15 +192,15 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: ]; let path = match arms[1].pats[0].node { - PatEnum(ref path, Some(ref inner)) => { + PatKind::TupleStruct(ref path, Some(ref inner)) => { // contains any non wildcard patterns? e.g. Err(err) - if inner.iter().any(|pat| if let PatWild = pat.node { false } else { true }) { + if inner.iter().any(|pat| if let PatKind::Wild = pat.node { false } else { true }) { return; } path.to_string() }, - PatEnum(ref path, None) => path.to_string(), - PatIdent(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), + PatKind::TupleStruct(ref path, None) => path.to_string(), + PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), _ => return, }; @@ -235,7 +235,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if cx.tcx.expr_ty(ex).sty == ty::TyBool { let sugg = if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards - let exprs = if let PatLit(ref arm_bool) = arms[0].pats[0].node { + let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { if let ExprLit(ref lit) = arm_bool.node { match lit.node { LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), @@ -334,7 +334,7 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { if let Arm { ref pats, guard: None, .. } = *arm { Some(pats.iter().filter_map(|pat| { if_let_chain! {[ - let PatRange(ref lhs, ref rhs) = pat.node, + let PatKind::Range(ref lhs, ref rhs) = pat.node, let Ok(lhs) = eval_const_expr_partial(cx.tcx, &lhs, ExprTypeChecked, None), let Ok(rhs) = eval_const_expr_partial(cx.tcx, &rhs, ExprTypeChecked, None) ], { @@ -342,7 +342,7 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { }} if_let_chain! {[ - let PatLit(ref value) = pat.node, + let PatKind::Lit(ref value) = pat.node, let Ok(value) = eval_const_expr_partial(cx.tcx, &value, ExprTypeChecked, None) ], { return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); @@ -424,8 +424,8 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { .flat_map(|a| &a.pats) .map(|p| { match p.node { - PatRegion(..) => Some(true), // &-patterns - PatWild => Some(false), // an "anything" wildcard is also fine + PatKind::Ref(..) => Some(true), // &-patterns + PatKind::Wild => Some(false), // an "anything" wildcard is also fine _ => None, // any other pattern is not fine } }) diff --git a/src/misc.rs b/src/misc.rs index 076e6e385c2..5c154dc59e2 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -45,7 +45,7 @@ impl LateLintPass for TopLevelRefPass { return; } for ref arg in &decl.inputs { - if let PatIdent(BindByRef(_), _, _) = arg.pat.node { + if let PatKind::Ident(BindByRef(_), _, _) = arg.pat.node { span_lint(cx, TOPLEVEL_REF_ARG, arg.pat.span, @@ -58,7 +58,7 @@ impl LateLintPass for TopLevelRefPass { [ let StmtDecl(ref d, _) = s.node, let DeclLocal(ref l) = d.node, - let PatIdent(BindByRef(_), i, None) = l.pat.node, + let PatKind::Ident(BindByRef(_), i, None) = l.pat.node, let Some(ref init) = l.init ], { let tyopt = if let Some(ref ty) = l.ty { @@ -345,8 +345,8 @@ impl LintPass for PatternPass { impl LateLintPass for PatternPass { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatIdent(_, ref ident, Some(ref right)) = pat.node { - if right.node == PatWild { + if let PatKind::Ident(_, ref ident, Some(ref right)) = pat.node { + if right.node == PatKind::Wild { cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!("the `{} @ _` pattern can be written as just `{}`", diff --git a/src/shadow.rs b/src/shadow.rs index ff9ea47f065..206fa492419 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -67,7 +67,7 @@ impl LateLintPass for ShadowPass { fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { - if let PatIdent(_, ident, _) = arg.pat.node { + if let PatKind::Ident(_, ident, _) = arg.pat.node { bindings.push((ident.node.unhygienic_name, ident.span)) } } @@ -119,7 +119,7 @@ fn is_binding(cx: &LateContext, pat: &Pat) -> bool { fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { // TODO: match more stuff / destructuring match pat.node { - PatIdent(_, ref ident, ref inner) => { + PatKind::Ident(_, ref ident, ref inner) => { let name = ident.node.unhygienic_name; if is_binding(cx, pat) { let mut new_binding = true; @@ -140,7 +140,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind } } // PatEnum(Path, Option<Vec<P<Pat>>>), - PatStruct(_, ref pfields, _) => { + PatKind::Struct(_, ref pfields, _) => { if let Some(ref init_struct) = *init { if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { @@ -161,7 +161,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind } } } - PatTup(ref inner) => { + PatKind::Tup(ref inner) => { if let Some(ref init_tup) = *init { if let ExprTup(ref tup) = init_tup.node { for (i, p) in inner.iter().enumerate() { @@ -178,7 +178,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind } } } - PatBox(ref inner) => { + PatKind::Box(ref inner) => { if let Some(ref initp) = *init { if let ExprBox(ref inner_init) = initp.node { check_pat(cx, inner, &Some(&**inner_init), span, bindings); @@ -189,7 +189,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind check_pat(cx, inner, init, span, bindings); } } - PatRegion(ref inner, _) => check_pat(cx, inner, init, span, bindings), + PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), _ => (), } diff --git a/src/utils/hir.rs b/src/utils/hir.rs index e527f63ebbd..631bcb1b100 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -168,41 +168,41 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two patterns are the same. pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { match (&left.node, &right.node) { - (&PatBox(ref l), &PatBox(ref r)) => { + (&PatKind::Box(ref l), &PatKind::Box(ref r)) => { self.eq_pat(l, r) } - (&PatEnum(ref lp, ref la), &PatEnum(ref rp, ref ra)) => { + (&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => { self.eq_path(lp, rp) && both(la, ra, |l, r| { over(l, r, |l, r| self.eq_pat(l, r)) }) } - (&PatIdent(ref lb, ref li, ref lp), &PatIdent(ref rb, ref ri, ref rp)) => { + (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { lb == rb && li.node.name.as_str() == ri.node.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } - (&PatLit(ref l), &PatLit(ref r)) => { + (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => { self.eq_expr(l, r) } - (&PatQPath(ref ls, ref lp), &PatQPath(ref rs, ref rp)) => { + (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { self.eq_qself(ls, rs) && self.eq_path(lp, rp) } - (&PatTup(ref l), &PatTup(ref r)) => { + (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => { over(l, r, |l, r| self.eq_pat(l, r)) } - (&PatRange(ref ls, ref le), &PatRange(ref rs, ref re)) => { + (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { self.eq_expr(ls, rs) && self.eq_expr(le, re) } - (&PatRegion(ref le, ref lm), &PatRegion(ref re, ref rm)) => { + (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => { lm == rm && self.eq_pat(le, re) } - (&PatVec(ref ls, ref li, ref le), &PatVec(ref rs, ref ri, ref re)) => { + (&PatKind::Vec(ref ls, ref li, ref le), &PatKind::Vec(ref rs, ref ri, ref re)) => { over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && both(li, ri, |l, r| self.eq_pat(l, r)) } - (&PatWild, &PatWild) => true, + (&PatKind::Wild, &PatKind::Wild) => true, _ => false, } } -- cgit 1.4.1-3-g733a5 From 5fe6e9f911f69cdef209c20b2024c33b19bf3993 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 17:00:36 +0100 Subject: Build the import lint in update_lints.py --- src/lib.rs | 69 +++++++++++++++++++++++++++------------------------- util/update_lints.py | 13 ++++++++++ 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 106d63aa0da..23accd2ebaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,59 +35,62 @@ extern crate rustc_plugin; use rustc_plugin::Registry; +pub mod consts; #[macro_use] pub mod utils; + +// begin lints modules, do not remove this comment, it’s used in `update_lints` +pub mod approx_const; +pub mod array_indexing; +pub mod attrs; +pub mod bit_mask; +pub mod block_in_if_condition; +pub mod collapsible_if; pub mod copies; -pub mod consts; -pub mod types; -pub mod misc; +pub mod cyclomatic_complexity; +pub mod derive; +pub mod drop_ref; +pub mod entry; pub mod enum_glob_use; +pub mod enum_variants; pub mod eq_op; -pub mod bit_mask; -pub mod ptr_arg; -pub mod needless_bool; -pub mod approx_const; +pub mod escape; pub mod eta_reduction; -pub mod enum_variants; pub mod identity_op; pub mod items_after_statements; -pub mod minmax; -pub mod mut_mut; -pub mod mut_reference; pub mod len_zero; -pub mod attrs; -pub mod collapsible_if; -pub mod block_in_if_condition; -pub mod unicode; -pub mod shadow; -pub mod strings; -pub mod methods; -pub mod returns; pub mod lifetimes; pub mod loops; -pub mod ranges; pub mod map_clone; pub mod matches; -pub mod precedence; +pub mod methods; +pub mod minmax; +pub mod misc; +pub mod misc_early; +pub mod mut_mut; +pub mod mut_reference; pub mod mutex_atomic; -pub mod zero_div_zero; -pub mod open_options; +pub mod needless_bool; pub mod needless_features; pub mod needless_update; pub mod no_effect; -pub mod temporary_assignment; -pub mod transmute; -pub mod cyclomatic_complexity; -pub mod escape; -pub mod entry; -pub mod misc_early; -pub mod array_indexing; +pub mod open_options; pub mod panic; -pub mod derive; +pub mod precedence; pub mod print; -pub mod vec; -pub mod drop_ref; +pub mod ptr_arg; +pub mod ranges; pub mod regex; +pub mod returns; +pub mod shadow; +pub mod strings; +pub mod temporary_assignment; +pub mod transmute; +pub mod types; +pub mod unicode; +pub mod vec; +pub mod zero_div_zero; +// end lints modules, do not remove this comment, it’s used in `update_lints` mod reexport { pub use syntax::ast::{Name, NodeId}; diff --git a/util/update_lints.py b/util/update_lints.py index 9f105a2699c..2eaa6ab6211 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -60,6 +60,13 @@ def gen_group(lints, levels=None): yield ' %s::%s,\n' % (module, name.upper()) +def gen_mods(lints): + """Declare modules""" + + for module in sorted(set(lint[0] for lint in lints)): + yield 'pub mod %s;\n' % module + + def replace_region(fn, region_start, region_end, callback, replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. @@ -128,6 +135,12 @@ def main(print_only=False, check=False): lambda: ['There are %d lints included in this crate:\n' % len(lints)], write_back=not check) + # update the `pub mod` list + changed |= replace_region( + 'src/lib.rs', r'begin lints modules', r'end lints modules', + lambda: gen_mods(lints), + replace_start=False, write_back=not check) + # same for "clippy" lint collection changed |= replace_region( 'src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', -- cgit 1.4.1-3-g733a5 From 222086d62b2c22e59eab82f03f4d08e3cb9bd6ae Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 17:33:53 +0100 Subject: Remove all use of `format!("string literal")` --- src/loops.rs | 4 ++-- src/methods.rs | 2 +- src/types.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 2754f743caa..9e5745950dd 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -317,8 +317,8 @@ impl LateLintPass for LoopsPass { span_lint(cx, UNUSED_COLLECT, expr.span, - &format!("you are collect()ing an iterator and throwing away the result. Consider \ - using an explicit for loop to exhaust the iterator")); + &"you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator"); } } } diff --git a/src/methods.rs b/src/methods.rs index 39f69f63d7b..f776d5890b7 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -589,7 +589,7 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { span_lint(cx, EXTEND_FROM_SLICE, expr.span, - &format!("use of `extend` to extend a Vec by a slice")) + &"use of `extend` to extend a Vec by a slice") .span_suggestion(expr.span, "try this", format!("{}.extend_from_slice({}{})", diff --git a/src/types.rs b/src/types.rs index 7cfcc76193d..7521bc48046 100644 --- a/src/types.rs +++ b/src/types.rs @@ -491,12 +491,12 @@ fn check_type(cx: &LateContext, ty: &Ty) { visitor.visit_ty(ty); visitor.score }; - // println!("{:?} --> {}", ty, score); + if score > 250 { span_lint(cx, TYPE_COMPLEXITY, ty.span, - &format!("very complex type used. Consider factoring parts into `type` definitions")); + &"very complex type used. Consider factoring parts into `type` definitions"); } } -- cgit 1.4.1-3-g733a5 From ef4401d4acf2eb1e125b9dd01d1baef195e2f53b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 17:35:07 +0100 Subject: Lint about usage of `format!("string literal")` --- README.md | 3 ++- src/format.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ tests/compile-fail/format.rs | 11 +++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/format.rs create mode 100755 tests/compile-fail/format.rs diff --git a/README.md b/README.md index 7fa0a15715f..62d6695b24d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 122 lints included in this crate: +There are 123 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -126,6 +126,7 @@ name [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore +[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop diff --git a/src/format.rs b/src/format.rs new file mode 100644 index 00000000000..ad72b38e110 --- /dev/null +++ b/src/format.rs @@ -0,0 +1,40 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::{is_expn_of, span_lint}; + +/// **What it does:** This lints about use of `format!("string literal with no argument")`. +/// +/// **Why is this bad?** There is no point of doing that. If you want a `String` you can use +/// `to_owned` on the string literal. The even worst `&format!("foo")` is often encountered in the +/// wild. +/// +/// **Known problems:** None. +/// +/// **Example:** `format!("foo")` +declare_lint! { + pub USELESS_FORMAT, + Warn, + "useless use of `format!`" +} + +#[derive(Copy, Clone, Debug)] +pub struct FormatMacLint; + +impl LintPass for FormatMacLint { + fn get_lints(&self) -> LintArray { + lint_array![USELESS_FORMAT] + } +} + +impl LateLintPass for FormatMacLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // `format!("foo")` expansion contains `match () { () => [], }` + if let ExprMatch(ref matchee, _, _) = expr.node { + if let ExprTup(ref tup) = matchee.node { + if tup.is_empty() && is_expn_of(cx, expr.span, "format").is_some() { + span_lint(cx, USELESS_FORMAT, expr.span, &"useless use of `format!`"); + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 23accd2ebaa..b690a5cf45e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -163,6 +163,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box regex::RegexPass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); + reg.register_late_lint_pass(box format::FormatMacLint); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -209,6 +210,7 @@ pub fn plugin_registrar(reg: &mut Registry) { eq_op::EQ_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, + format::USELESS_FORMAT, identity_op::IDENTITY_OP, items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, diff --git a/tests/compile-fail/format.rs b/tests/compile-fail/format.rs new file mode 100755 index 00000000000..6cdceefd063 --- /dev/null +++ b/tests/compile-fail/format.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(useless_format)] + +fn main() { + format!("foo"); //~ERROR useless use of `format!` + format!("foo {}", 42); + + println!("foo"); + println!("foo {}", 42); +} -- cgit 1.4.1-3-g733a5 From b6443b992898eebf465470c2dcdb93fdbd87d381 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 21:03:45 +0100 Subject: Replace all `format!("{}", foo)` calls --- src/collapsible_if.rs | 7 ++++--- src/loops.rs | 6 +++--- src/methods.rs | 8 ++++---- src/misc_early.rs | 5 +---- src/mut_reference.rs | 4 ++-- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index e5ad94fc639..663d39cdbb2 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -14,6 +14,7 @@ use rustc::lint::*; use rustc_front::hir::*; +use std::borrow::Cow; use syntax::codemap::Spanned; use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; @@ -95,11 +96,11 @@ fn requires_brackets(e: &Expr) -> bool { } } -fn check_to_string(cx: &LateContext, e: &Expr) -> String { +fn check_to_string(cx: &LateContext, e: &Expr) -> Cow<'static, str> { if requires_brackets(e) { - format!("({})", snippet(cx, e.span, "..")) + format!("({})", snippet(cx, e.span, "..")).into() } else { - format!("{}", snippet(cx, e.span, "..")) + snippet(cx, e.span, "..") } } diff --git a/src/loops.rs b/src/loops.rs index 9e5745950dd..fff73f907f0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -245,13 +245,13 @@ impl LateLintPass for LoopsPass { let mut other_stuff = block.stmts .iter() .skip(1) - .map(|stmt| format!("{}", snippet(cx, stmt.span, ".."))) - .collect::<Vec<String>>(); + .map(|stmt| snippet(cx, stmt.span, "..")) + .collect::<Vec<Cow<_>>>(); if inner_stmt_expr.is_some() { // if we have a statement which has a match, if let Some(ref expr) = block.expr { // then collect the expression (without semicolon) below it - other_stuff.push(format!("{}", snippet(cx, expr.span, ".."))); + other_stuff.push(snippet(cx, expr.span, "..")); } } diff --git a/src/methods.rs b/src/methods.rs index f776d5890b7..1d529e175db 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -530,10 +530,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) return; } - let sugg = match (fn_has_arguments, !or_has_args) { - (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")), - (false, false) => format!("|| {}", snippet(cx, arg.span, "..")), - (false, true) => format!("{}", snippet(cx, fun.span, "..")), + let sugg: Cow<_> = match (fn_has_arguments, !or_has_args) { + (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), + (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), + (false, true) => snippet(cx, fun.span, ".."), }; span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) diff --git a/src/misc_early.rs b/src/misc_early.rs index 28d5fb65f36..bbed9ad4996 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -45,10 +45,7 @@ impl EarlyLintPass for MiscEarly { fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; - let type_name = match npat.segments.last() { - Some(elem) => format!("{}", elem.identifier.name), - None => String::new(), - }; + let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name; for field in pfields { if field.node.pat.node == PatKind::Wild { diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 35904533719..ea2c00bab94 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -39,13 +39,13 @@ impl LateLintPass for UnnecessaryMutPassed { If this happened, the compiler would have \ aborted the compilation long ago"); if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, &arguments, function_type, &format!("{}", path)); + check_arguments(cx, &arguments, function_type, &path.to_string()); } } ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); - check_arguments(cx, &arguments, method_type.ty, &format!("{}", name.node.as_str())) + check_arguments(cx, &arguments, method_type.ty, &name.node.as_str()) } _ => {} } -- cgit 1.4.1-3-g733a5 From ba3be834881a5a62c00cb49ac09b2d1b9f35fe5f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 21:15:05 +0100 Subject: Lint about `format!("{}", foo)` --- src/format.rs | 86 ++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 1 + src/utils/mod.rs | 2 ++ tests/compile-fail/format.rs | 4 +++ 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/format.rs b/src/format.rs index ad72b38e110..704b4e8e8fa 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,11 +1,14 @@ +use rustc::front::map::Node::NodeItem; use rustc::lint::*; use rustc_front::hir::*; -use utils::{is_expn_of, span_lint}; +use syntax::ast::LitKind; +use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH}; +use utils::{is_expn_of, match_path, span_lint}; /// **What it does:** This lints about use of `format!("string literal with no argument")`. /// /// **Why is this bad?** There is no point of doing that. If you want a `String` you can use -/// `to_owned` on the string literal. The even worst `&format!("foo")` is often encountered in the +/// `to_owned` on the string literal. The even worse `&format!("foo")` is often encountered in the /// wild. /// /// **Known problems:** None. @@ -28,13 +31,82 @@ impl LintPass for FormatMacLint { impl LateLintPass for FormatMacLint { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - // `format!("foo")` expansion contains `match () { () => [], }` - if let ExprMatch(ref matchee, _, _) = expr.node { - if let ExprTup(ref tup) = matchee.node { - if tup.is_empty() && is_expn_of(cx, expr.span, "format").is_some() { - span_lint(cx, USELESS_FORMAT, expr.span, &"useless use of `format!`"); + if let Some(span) = is_expn_of(cx, expr.span, "format") { + match expr.node { + // `format!("{}", foo)` expansion + ExprCall(ref fun, ref args) => { + if_let_chain!{[ + let ExprPath(_, ref path) = fun.node, + args.len() == 2, + match_path(path, &FMT_ARGUMENTS_NEWV1_PATH), + // ensure the format string is `"{..}"` with only one argument and no text + check_static_str(cx, &args[0]), + // ensure the format argument is `{}` ie. Display with no fancy option + check_arg_is_display(&args[1]) + ], { + span_lint(cx, USELESS_FORMAT, span, &"useless use of `format!`"); + }} } + // `format!("foo")` expansion contains `match () { () => [], }` + ExprMatch(ref matchee, _, _) => { + if let ExprTup(ref tup) = matchee.node { + if tup.is_empty() { + span_lint(cx, USELESS_FORMAT, span, &"useless use of `format!`"); + } + } + } + _ => (), } } } } + +/// Checks if the expressions matches +/// ``` +/// { static __STATIC_FMTSTR: &[""] = _; __STATIC_FMTSTR } +/// ``` +fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { + if_let_chain! {[ + let ExprBlock(ref block) = expr.node, + block.stmts.len() == 1, + let StmtDecl(ref decl, _) = block.stmts[0].node, + let DeclItem(ref decl) = decl.node, + let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id), + decl.name.as_str() == "__STATIC_FMTSTR", + let ItemStatic(_, _, ref expr) = decl.node, + let ExprAddrOf(_, ref expr) = expr.node, // &[""] + let ExprVec(ref expr) = expr.node, + expr.len() == 1, + let ExprLit(ref lit) = expr[0].node, + let LitKind::Str(ref lit, _) = lit.node, + lit.is_empty() + ], { + return true; + }} + + false +} + +/// Checks if the expressions matches +/// ``` +/// &match (&42,) { +/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)], +/// }) +/// ``` +fn check_arg_is_display(expr: &Expr) -> bool { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, + let ExprMatch(_, ref arms, _) = expr.node, + arms.len() == 1, + let ExprVec(ref exprs) = arms[0].body.node, + exprs.len() == 1, + let ExprCall(_, ref args) = exprs[0].node, + args.len() == 2, + let ExprPath(None, ref path) = args[1].node, + match_path(path, &DISPLAY_FMT_METHOD_PATH) + ], { + return true; + }} + + false +} diff --git a/src/lib.rs b/src/lib.rs index b690a5cf45e..8348eb09834 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,7 @@ pub mod enum_variants; pub mod eq_op; pub mod escape; pub mod eta_reduction; +pub mod format; pub mod identity_op; pub mod items_after_statements; pub mod len_zero; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 3a7c6c90d51..68137fbbf2a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -28,7 +28,9 @@ pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; +pub const DISPLAY_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTS_NEWV1_PATH: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTV1_NEW_PATH: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; diff --git a/tests/compile-fail/format.rs b/tests/compile-fail/format.rs index 6cdceefd063..0219771e09e 100755 --- a/tests/compile-fail/format.rs +++ b/tests/compile-fail/format.rs @@ -4,7 +4,11 @@ fn main() { format!("foo"); //~ERROR useless use of `format!` + format!("{}", 42); //~ERROR useless use of `format!` + format!("{:?}", 42); // we only want to warn about `{}` + format!("{:+}", 42); // we only want to warn about `{}` format!("foo {}", 42); + format!("{} bar", 42); println!("foo"); println!("foo {}", 42); -- cgit 1.4.1-3-g733a5 From 1a64a4890c56f23039fbb5df3c643d6c060d7660 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 20 Feb 2016 21:20:56 +0100 Subject: Small cleanup --- src/format.rs | 4 ++-- src/loops.rs | 4 ++-- src/methods.rs | 2 +- src/regex.rs | 4 ++-- src/types.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/format.rs b/src/format.rs index 704b4e8e8fa..901cd3f7a9b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -44,14 +44,14 @@ impl LateLintPass for FormatMacLint { // ensure the format argument is `{}` ie. Display with no fancy option check_arg_is_display(&args[1]) ], { - span_lint(cx, USELESS_FORMAT, span, &"useless use of `format!`"); + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); }} } // `format!("foo")` expansion contains `match () { () => [], }` ExprMatch(ref matchee, _, _) => { if let ExprTup(ref tup) = matchee.node { if tup.is_empty() { - span_lint(cx, USELESS_FORMAT, span, &"useless use of `format!`"); + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); } } } diff --git a/src/loops.rs b/src/loops.rs index fff73f907f0..15f0e51f36c 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -317,8 +317,8 @@ impl LateLintPass for LoopsPass { span_lint(cx, UNUSED_COLLECT, expr.span, - &"you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator"); + "you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator"); } } } diff --git a/src/methods.rs b/src/methods.rs index 1d529e175db..c67e2eade14 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -589,7 +589,7 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { span_lint(cx, EXTEND_FROM_SLICE, expr.span, - &"use of `extend` to extend a Vec by a slice") + "use of `extend` to extend a Vec by a slice") .span_suggestion(expr.span, "try this", format!("{}.extend_from_slice({}{})", diff --git a/src/regex.rs b/src/regex.rs index 25c7260abec..745d685ec80 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -105,7 +105,7 @@ impl LateLintPass for RegexPass { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - &"trivial regex", + "trivial regex", &format!("consider using {}", repl)); } } @@ -123,7 +123,7 @@ impl LateLintPass for RegexPass { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - &"trivial regex", + "trivial regex", &format!("consider using {}", repl)); } } diff --git a/src/types.rs b/src/types.rs index 7521bc48046..eec8bd63eb7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -496,7 +496,7 @@ fn check_type(cx: &LateContext, ty: &Ty) { span_lint(cx, TYPE_COMPLEXITY, ty.span, - &"very complex type used. Consider factoring parts into `type` definitions"); + "very complex type used. Consider factoring parts into `type` definitions"); } } -- cgit 1.4.1-3-g733a5 From d77ccdc33870e89c7fba9a55aea876f14754b94d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 21 Feb 2016 13:21:04 +0100 Subject: Fix `USELESS_FORMAT` wiki --- src/format.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/format.rs b/src/format.rs index 901cd3f7a9b..e161d6fce3b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -5,15 +5,16 @@ use syntax::ast::LitKind; use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH}; use utils::{is_expn_of, match_path, span_lint}; -/// **What it does:** This lints about use of `format!("string literal with no argument")`. +/// **What it does:** This lints about use of `format!("string literal with no argument")` and +/// `format!("{}", foo)`. /// /// **Why is this bad?** There is no point of doing that. If you want a `String` you can use -/// `to_owned` on the string literal. The even worse `&format!("foo")` is often encountered in the -/// wild. +/// `to_owned` on the string literal or expression. The even worse `&format!("foo")` is often +/// encountered in the wild. /// /// **Known problems:** None. /// -/// **Example:** `format!("foo")` +/// **Examples:** `format!("foo")` and `format!("{}", foo)` declare_lint! { pub USELESS_FORMAT, Warn, -- cgit 1.4.1-3-g733a5 From 0e9ced5cb85793c4fe1765130a5ca0e01084f2c2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 21 Feb 2016 20:09:37 +0530 Subject: Bump to 0.0.43 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 06fd32d8424..d6a3e4915bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.42" +version = "0.0.43" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 2a0fb1fb440fda9267a7d57961d16da25b03005a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 17:54:46 +0100 Subject: Limit `USELESS_FORMAT` with args to string args --- src/format.rs | 24 +++++++++++++++--------- tests/compile-fail/format.rs | 25 ++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/format.rs b/src/format.rs index e161d6fce3b..f0b8485b4a4 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,16 +1,17 @@ use rustc::front::map::Node::NodeItem; use rustc::lint::*; +use rustc::middle::ty::TypeVariants; use rustc_front::hir::*; use syntax::ast::LitKind; -use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH}; -use utils::{is_expn_of, match_path, span_lint}; +use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH, STRING_PATH}; +use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty}; /// **What it does:** This lints about use of `format!("string literal with no argument")` and -/// `format!("{}", foo)`. +/// `format!("{}", foo)` where `foo` is a string. /// -/// **Why is this bad?** There is no point of doing that. If you want a `String` you can use -/// `to_owned` on the string literal or expression. The even worse `&format!("foo")` is often -/// encountered in the wild. +/// **Why is this bad?** There is no point of doing that. `format!("too")` can be replaced by `"foo".to_owned()` if you really need a `String`. The even worse `&format!("foo")` is often +/// encountered in the wild. `format!("{}", foo)` can be replaced by `foo.clone()` if `foo: String` +/// or `foo.to_owned()` is `foo: &str`. /// /// **Known problems:** None. /// @@ -43,7 +44,7 @@ impl LateLintPass for FormatMacLint { // ensure the format string is `"{..}"` with only one argument and no text check_static_str(cx, &args[0]), // ensure the format argument is `{}` ie. Display with no fancy option - check_arg_is_display(&args[1]) + check_arg_is_display(cx, &args[1]) ], { span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); }} @@ -94,11 +95,14 @@ fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { /// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)], /// }) /// ``` -fn check_arg_is_display(expr: &Expr) -> bool { +fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { if_let_chain! {[ let ExprAddrOf(_, ref expr) = expr.node, let ExprMatch(_, ref arms, _) = expr.node, arms.len() == 1, + arms[0].pats.len() == 1, + let PatKind::Tup(ref pat) = arms[0].pats[0].node, + pat.len() == 1, let ExprVec(ref exprs) = arms[0].body.node, exprs.len() == 1, let ExprCall(_, ref args) = exprs[0].node, @@ -106,7 +110,9 @@ fn check_arg_is_display(expr: &Expr) -> bool { let ExprPath(None, ref path) = args[1].node, match_path(path, &DISPLAY_FMT_METHOD_PATH) ], { - return true; + let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0])); + + return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &STRING_PATH); }} false diff --git a/tests/compile-fail/format.rs b/tests/compile-fail/format.rs index 0219771e09e..4fff131f6e7 100755 --- a/tests/compile-fail/format.rs +++ b/tests/compile-fail/format.rs @@ -4,12 +4,31 @@ fn main() { format!("foo"); //~ERROR useless use of `format!` - format!("{}", 42); //~ERROR useless use of `format!` - format!("{:?}", 42); // we only want to warn about `{}` - format!("{:+}", 42); // we only want to warn about `{}` + + format!("{}", "foo"); //~ERROR useless use of `format!` + format!("{:?}", "foo"); // we only want to warn about `{}` + format!("{:+}", "foo"); // we only want to warn about `{}` + format!("foo {}", "bar"); + format!("{} bar", "foo"); + + let arg: String = "".to_owned(); + format!("{}", arg); //~ERROR useless use of `format!` + format!("{:?}", arg); // we only want to warn about `{}` + format!("{:+}", arg); // we only want to warn about `{}` + format!("foo {}", arg); + format!("{} bar", arg); + + // we don’t want to warn for non-string args, see #697 + format!("{}", 42); + format!("{:?}", 42); + format!("{:+}", 42); format!("foo {}", 42); format!("{} bar", 42); + // we only want to warn about `format!` itself println!("foo"); + println!("{}", "foo"); + println!("foo {}", "foo"); + println!("{}", 42); println!("foo {}", 42); } -- cgit 1.4.1-3-g733a5 From 3b783152ccff54f3bf1e54db424dc476e36b1b31 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 20:00:51 +0100 Subject: Fix ICE with match_def_path --- src/utils/mod.rs | 6 +++++- tests/run-pass/ice-700.rs | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100755 tests/run-pass/ice-700.rs diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 68137fbbf2a..b9dd9359c66 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -133,8 +133,12 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// ``` pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { cx.tcx.with_path(def_id, |iter| { - iter.zip(path) + let mut len = 0; + + iter.inspect(|_| len += 1) + .zip(path) .all(|(nm, p)| nm.name().as_str() == *p) + && len == path.len() }) } diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs new file mode 100755 index 00000000000..a7ff78eac14 --- /dev/null +++ b/tests/run-pass/ice-700.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy)] + +fn core() {} + +fn main() { + core(); +} -- cgit 1.4.1-3-g733a5 From d299b5d4d9c6d66cfe7f9ba081a1de646b6dc310 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 20:06:59 +0100 Subject: Bump to 0.0.44 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d6a3e4915bc..d4134461685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.43" +version = "0.0.44" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From b753e77cbe175fc6e336387029290e9d19f1243a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 24 Feb 2016 17:38:57 +0100 Subject: Rustfmt and sort all `use` items --- src/approx_const.rs | 2 +- src/attrs.rs | 6 +-- src/bit_mask.rs | 2 +- src/block_in_if_condition.rs | 2 +- src/consts.rs | 59 ++++++++++++++++++----------- src/copies.rs | 74 +++++++++++++++++++++--------------- src/cyclomatic_complexity.rs | 8 ++-- src/drop_ref.rs | 3 +- src/enum_glob_use.rs | 8 ++-- src/enum_variants.rs | 5 +-- src/eq_op.rs | 1 - src/escape.rs | 10 ++--- src/eta_reduction.rs | 4 +- src/identity_op.rs | 3 +- src/items_after_statements.rs | 2 +- src/len_zero.rs | 11 ++---- src/lifetimes.rs | 7 ++-- src/loops.rs | 87 ++++++++++++++++++++++--------------------- src/map_clone.rs | 6 ++- src/matches.rs | 33 ++++++++-------- src/methods.rs | 25 ++++++------- src/minmax.rs | 12 +++--- src/misc.rs | 15 ++++---- src/misc_early.rs | 3 -- src/mut_mut.rs | 3 +- src/mut_reference.rs | 4 +- src/mutex_atomic.rs | 6 +-- src/needless_bool.rs | 2 - src/needless_features.rs | 1 - src/needless_update.rs | 1 - src/no_effect.rs | 7 +--- src/open_options.rs | 4 +- src/panic.rs | 1 - src/precedence.rs | 3 +- src/print.rs | 2 +- src/ptr_arg.rs | 7 ++-- src/regex.rs | 39 +++++++++---------- src/returns.rs | 1 - src/shadow.rs | 10 ++--- src/strings.rs | 5 +-- src/temporary_assignment.rs | 1 - src/types.rs | 32 +++++++++------- src/unicode.rs | 5 +-- src/utils/hir.rs | 29 +++++++++------ src/utils/mod.rs | 2 +- src/zero_div_zero.rs | 3 +- 46 files changed, 279 insertions(+), 277 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index b1a33584442..822fbd16c32 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; use std::f64::consts as f64; -use utils::span_lint; use syntax::ast::{Lit, LitKind, FloatTy}; +use utils::span_lint; /// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. /// diff --git a/src/attrs.rs b/src/attrs.rs index fda46724862..363809c37bb 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -1,12 +1,12 @@ //! checks for attributes +use reexport::*; use rustc::lint::*; use rustc_front::hir::*; -use reexport::*; use semver::Version; -use syntax::codemap::Span; -use syntax::attr::*; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; +use syntax::attr::*; +use syntax::codemap::Span; use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; /// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. diff --git a/src/bit_mask.rs b/src/bit_mask.rs index e1366924e1d..0e09122bcc6 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -3,8 +3,8 @@ use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; -use syntax::codemap::Span; use syntax::ast::LitKind; +use syntax::codemap::Span; use utils::span_lint; diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 65fbce640cf..6db77a5ce93 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -1,5 +1,5 @@ -use rustc_front::hir::*; use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; +use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr}; use utils::*; diff --git a/src/consts.rs b/src/consts.rs index 37322aeffc8..cf32a9a2c82 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -95,9 +95,7 @@ impl PartialEq for Constant { (&Constant::Byte(l), &Constant::Byte(r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, (&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => true, - (&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => { - lv == rv && lneg == rneg - } + (&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => lv == rv && lneg == rneg, (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them @@ -116,7 +114,9 @@ impl PartialEq for Constant { } impl Hash for Constant { - fn hash<H>(&self, state: &mut H) where H: Hasher { + fn hash<H>(&self, state: &mut H) + where H: Hasher + { match *self { Constant::Str(ref s, ref k) => { s.hash(state); @@ -144,7 +144,7 @@ impl Hash for Constant { Constant::Bool(b) => { b.hash(state); } - Constant::Vec(ref v) | Constant::Tuple(ref v)=> { + Constant::Vec(ref v) | Constant::Tuple(ref v) => { v.hash(state); } Constant::Repeat(ref c, l) => { @@ -210,7 +210,9 @@ fn constant_not(o: Constant) -> Option<Constant> { use self::Constant::*; match o { Bool(b) => Some(Bool(!b)), - Int(value, LitIntType::Signed(ity), Sign::Plus) if value != ::std::u64::MAX => Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus)), + Int(value, LitIntType::Signed(ity), Sign::Plus) if value != ::std::u64::MAX => { + Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus)) + } Int(0, LitIntType::Signed(ity), Sign::Minus) => Some(Int(1, LitIntType::Signed(ity), Sign::Minus)), Int(value, LitIntType::Signed(ity), Sign::Minus) => Some(Int(value - 1, LitIntType::Signed(ity), Sign::Plus)), Int(value, LitIntType::Unsigned(ity), Sign::Plus) => { @@ -224,7 +226,7 @@ fn constant_not(o: Constant) -> Option<Constant> { } // refuse to guess }; Some(Int(!value & mask, LitIntType::Unsigned(ity), Sign::Plus)) - }, + } _ => None, } } @@ -388,7 +390,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (Constant::Byte(l8), Constant::Byte(r8)) => l8.checked_add(r8).map(Constant::Byte), (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { add_ints(l64, r64, lty, rty, lsign, rsign) - }, + } // TODO: float (would need bignum library?) _ => None, } @@ -406,7 +408,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { add_ints(l64, r64, lty, rty, lsign, neg_sign(rsign)) - }, + } _ => None, } }) @@ -438,7 +440,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match (l, r) { (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { f(l64, r64).and_then(|value| { - let sign = if lsign == rsign { Sign::Plus } else { Sign::Minus }; + let sign = if lsign == rsign { + Sign::Plus + } else { + Sign::Minus + }; unify_int_type(lty, rty).map(|ty| Constant::Int(value, ty, sign)) }) } @@ -504,19 +510,28 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn add_ints(l64: u64, r64: u64, lty: LitIntType, rty: LitIntType, lsign: Sign, rsign: Sign) -> Option<Constant> { - let ty = if let Some(ty) = unify_int_type(lty, rty) { ty } else { return None; }; + let ty = if let Some(ty) = unify_int_type(lty, rty) { + ty + } else { + return None; + }; + match (lsign, rsign) { (Sign::Plus, Sign::Plus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Plus)), - (Sign::Plus, Sign::Minus) => if r64 > l64 { - Some(Constant::Int(r64 - l64, ty, Sign::Minus)) - } else { - Some(Constant::Int(l64 - r64, ty, Sign::Plus)) - }, - (Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)), - (Sign::Minus, Sign::Plus) => if l64 > r64 { - Some(Constant::Int(l64 - r64, ty, Sign::Minus)) - } else { - Some(Constant::Int(r64 - l64, ty, Sign::Plus)) - }, + (Sign::Plus, Sign::Minus) => { + if r64 > l64 { + Some(Constant::Int(r64 - l64, ty, Sign::Minus)) + } else { + Some(Constant::Int(l64 - r64, ty, Sign::Plus)) + } + } + (Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)), + (Sign::Minus, Sign::Plus) => { + if l64 > r64 { + Some(Constant::Int(l64 - r64, ty, Sign::Minus)) + } else { + Some(Constant::Int(r64 - l64, ty, Sign::Plus)) + } + } } } diff --git a/src/copies.rs b/src/copies.rs index d97745203f0..1995e2901ad 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -61,11 +61,7 @@ pub struct CopyAndPaste; impl LintPass for CopyAndPaste { fn get_lints(&self) -> LintArray { - lint_array![ - IFS_SAME_COND, - IF_SAME_THEN_ELSE, - MATCH_SAME_ARMS - ] + lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS] } } @@ -89,35 +85,43 @@ impl LateLintPass for CopyAndPaste { /// Implementation of `IF_SAME_THEN_ELSE`. fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { - let hash : &Fn(&&Block) -> u64 = &|block| -> u64 { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { let mut h = SpanlessHash::new(cx); h.hash_block(block); h.finish() }; - let eq : &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { + let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same(blocks, hash, eq) { - span_note_and_lint(cx, IF_SAME_THEN_ELSE, j.span, "this `if` has identical blocks", i.span, "same as this"); + span_note_and_lint(cx, + IF_SAME_THEN_ELSE, + j.span, + "this `if` has identical blocks", + i.span, + "same as this"); } } /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { - let hash : &Fn(&&Expr) -> u64 = &|expr| -> u64 { + let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 { let mut h = SpanlessHash::new(cx); h.hash_expr(expr); h.finish() }; - let eq : &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) - }; + let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; if let Some((i, j)) = search_same(conds, hash, eq) { - span_note_and_lint(cx, IFS_SAME_COND, j.span, "this `if` has the same condition as a previous if", i.span, "same as this"); + span_note_and_lint(cx, + IFS_SAME_COND, + j.span, + "this `if` has the same condition as a previous if", + i.span, + "same as this"); } } @@ -137,7 +141,12 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { if let Some((i, j)) = search_same(&**arms, hash, eq) { - span_note_and_lint(cx, MATCH_SAME_ARMS, j.body.span, "this `match` has identical arm bodies", i.body.span, "same as this"); + span_note_and_lint(cx, + MATCH_SAME_ARMS, + j.body.span, + "this `match` has identical arm bodies", + i.body.span, + "same as this"); } } } @@ -155,8 +164,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { if let Some(ref else_expr) = *else_expr { expr = else_expr; - } - else { + } else { break; } } @@ -188,7 +196,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned if let Some(ref as_pat) = *as_pat { bindings_impl(cx, as_pat, map); } - }, + } PatKind::Struct(_, ref fields, _) => { for pat in fields { bindings_impl(cx, &pat.node.pat, map); @@ -210,7 +218,12 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, pat, map); } } - PatKind::TupleStruct(..) | PatKind::Lit(..) | PatKind::QPath(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (), + PatKind::TupleStruct(..) | + PatKind::Lit(..) | + PatKind::QPath(..) | + PatKind::Range(..) | + PatKind::Wild | + PatKind::Path(..) => (), } } @@ -219,36 +232,35 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned result } -fn search_same<T, Hash, Eq>(exprs: &[T], - hash: Hash, - eq: Eq) -> Option<(&T, &T)> -where Hash: Fn(&T) -> u64, - Eq: Fn(&T, &T) -> bool { +fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> + where Hash: Fn(&T) -> u64, + Eq: Fn(&T, &T) -> bool +{ // common cases if exprs.len() < 2 { return None; - } - else if exprs.len() == 2 { + } else if exprs.len() == 2 { return if eq(&exprs[0], &exprs[1]) { Some((&exprs[0], &exprs[1])) - } - else { + } else { None - } + }; } - let mut map : HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len()); + let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len()); for expr in exprs { match map.entry(hash(expr)) { Entry::Occupied(o) => { for o in o.get() { if eq(&o, expr) { - return Some((&o, expr)) + return Some((&o, expr)); } } } - Entry::Vacant(v) => { v.insert(vec![expr]); } + Entry::Vacant(v) => { + v.insert(vec![expr]); + } } } diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 99157e76969..3f956f1fc41 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -1,13 +1,13 @@ //! calculate cyclomatic complexity and warn about overly complex functions use rustc::lint::*; -use rustc_front::hir::*; use rustc::middle::cfg::CFG; use rustc::middle::ty; -use syntax::codemap::Span; -use syntax::attr::*; -use syntax::ast::Attribute; +use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr}; +use syntax::ast::Attribute; +use syntax::attr::*; +use syntax::codemap::Span; use utils::{in_macro, LimitStack, span_help_and_lint}; diff --git a/src/drop_ref.rs b/src/drop_ref.rs index 6dc3d734196..5f7e67925bd 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -1,8 +1,7 @@ use rustc::lint::*; -use rustc_front::hir::*; use rustc::middle::ty; +use rustc_front::hir::*; use syntax::codemap::Span; - use utils::DROP_PATH; use utils::{match_def_path, span_note_and_lint}; diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index f8afdf627e2..5b542a7d67b 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -1,13 +1,13 @@ //! lint on `use`ing all variants of an enum -use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; -use rustc_front::hir::*; use rustc::front::map::Node::NodeItem; use rustc::front::map::definitions::DefPathData; +use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; use rustc::middle::ty::TyEnum; -use utils::span_lint; -use syntax::codemap::Span; +use rustc_front::hir::*; use syntax::ast::NodeId; +use syntax::codemap::Span; +use utils::span_lint; /// **What it does:** Warns when `use`ing all variants of an enum /// diff --git a/src/enum_variants.rs b/src/enum_variants.rs index 8ad7adf0077..a95fca8c6c4 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -1,10 +1,9 @@ //! lint on enum variants that are prefixed or suffixed by the same characters use rustc::lint::*; -use syntax::attr::*; use syntax::ast::*; +use syntax::attr::*; use syntax::parse::token::InternedString; - use utils::span_help_and_lint; use utils::{camel_case_from, camel_case_until}; @@ -95,7 +94,7 @@ impl EarlyLintPass for EnumVariantNames { } else if !post.is_empty() { ("post", post) } else { - return + return; }; span_help_and_lint(cx, ENUM_VARIANT_NAMES, diff --git a/src/eq_op.rs b/src/eq_op.rs index fc1cab2cd71..09ac6325f96 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc_front::util as ast_util; - use utils::{SpanlessEq, span_lint}; /// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, diff --git a/src/escape.rs b/src/escape.rs index 60bfbbc59c3..bcc1cb16870 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,13 +1,13 @@ -use rustc::lint::*; use rustc::front::map::Node::{NodeExpr, NodeStmt}; -use rustc_front::hir::*; -use rustc_front::intravisit as visit; -use rustc::middle::ty; -use rustc::middle::ty::adjustment::AutoAdjustment; +use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::infer; use rustc::middle::mem_categorization::{cmt, Categorization}; +use rustc::middle::ty::adjustment::AutoAdjustment; +use rustc::middle::ty; use rustc::util::nodemap::NodeSet; +use rustc_front::hir::*; +use rustc_front::intravisit as visit; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 2522b1517a6..e28411cc79c 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,10 +1,8 @@ use rustc::lint::*; -use rustc_front::hir::*; use rustc::middle::ty; - +use rustc_front::hir::*; use utils::{snippet_opt, span_lint_and_then, is_adjusted}; - #[allow(missing_copy_implementations)] pub struct EtaPass; diff --git a/src/identity_op.rs b/src/identity_op.rs index b033b234122..8a0da7bcd9f 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,8 +1,7 @@ +use consts::{constant_simple, Constant, Sign}; use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; - -use consts::{constant_simple, Constant, Sign}; use utils::{span_lint, snippet, in_macro}; /// **What it does:** This lint checks for identity operations, e.g. `x + 0`. diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 9bfb3b87ed1..a2ab7246942 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -1,8 +1,8 @@ //! lint when items are used after statements use rustc::lint::*; -use syntax::attr::*; use syntax::ast::*; +use syntax::attr::*; use utils::in_macro; /// **What it does:** This lints checks for items declared after some statement in a block diff --git a/src/len_zero.rs b/src/len_zero.rs index 222de03f006..6963592592d 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,13 +1,10 @@ use rustc::lint::*; -use rustc_front::hir::*; -use syntax::ast::Name; -use syntax::ptr::P; -use syntax::codemap::{Span, Spanned}; use rustc::middle::def_id::DefId; use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; - -use syntax::ast::{Lit, LitKind}; - +use rustc_front::hir::*; +use syntax::ast::{Lit, LitKind, Name}; +use syntax::codemap::{Span, Spanned}; +use syntax::ptr::P; use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; /// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. diff --git a/src/lifetimes.rs b/src/lifetimes.rs index f30163f4656..72fdba07d32 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -1,11 +1,10 @@ -use rustc_front::hir::*; use reexport::*; use rustc::lint::*; -use syntax::codemap::Span; -use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; use rustc::middle::def::Def; +use rustc_front::hir::*; +use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; use std::collections::{HashSet, HashMap}; - +use syntax::codemap::Span; use utils::{in_external_macro, span_lint}; /// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. diff --git a/src/loops.rs b/src/loops.rs index acfb6c150d5..ce2ae94cd30 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -351,9 +351,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { let (indexed, indexed_extent) = visitor.indexed - .into_iter() - .next() - .unwrap_or_else(|| unreachable!() /* len == 1 */); + .into_iter() + .next() + .unwrap_or_else(|| unreachable!() /* len == 1 */); // ensure that the indexed variable was declared before the loop, see #601 let pat_extent = cx.tcx.region_maps.var_scope(pat.id); @@ -438,8 +438,12 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, stop_idx) { - (ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx), - (ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx), + (ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => { + (start_idx > stop_idx, start_idx == stop_idx) + } + (ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => { + (start_idx > stop_idx, start_idx == stop_idx) + } _ => (false, false), }; @@ -515,26 +519,25 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { let ty = cx.tcx.expr_ty(arg); if match_type(cx, ty, &OPTION_PATH) { - span_help_and_lint( - cx, - FOR_LOOP_OVER_OPTION, - arg.span, - &format!("for loop over `{0}`, which is an `Option`. This is more readably written as \ - an `if let` statement.", snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", - snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_")) - ); - } - else if match_type(cx, ty, &RESULT_PATH) { - span_help_and_lint( - cx, - FOR_LOOP_OVER_RESULT, - arg.span, - &format!("for loop over `{0}`, which is a `Result`. This is more readably written as \ - an `if let` statement.", snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", - snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_")) - ); + span_help_and_lint(cx, + FOR_LOOP_OVER_OPTION, + arg.span, + &format!("for loop over `{0}`, which is an `Option`. This is more readably written as an \ + `if let` statement.", + snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_"))); + } else if match_type(cx, ty, &RESULT_PATH) { + span_help_and_lint(cx, + FOR_LOOP_OVER_RESULT, + arg.span, + &format!("for loop over `{0}`, which is a `Result`. This is more readably written as an \ + `if let` statement.", + snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_"))); } } @@ -590,31 +593,29 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), - _ => return + _ => return, }; let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); let arg_span = if let ExprAddrOf(_, ref expr) = arg.node { expr.span - } - else { + } else { arg.span }; - if match_type(cx, ty, &HASHMAP_PATH) || - match_type(cx, ty, &BTREEMAP_PATH) { + if match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &BTREEMAP_PATH) { span_lint_and_then(cx, - FOR_KV_MAP, - expr.span, - &format!("you seem to want to iterate on a map's {}", kind), - |db| { - db.span_suggestion(expr.span, - "use the corresponding method", - format!("for {} in {}.{}() {{...}}", - snippet(cx, *pat_span, ".."), - snippet(cx, arg_span, ".."), - kind)); - }); + FOR_KV_MAP, + expr.span, + &format!("you seem to want to iterate on a map's {}", kind), + |db| { + db.span_suggestion(expr.span, + "use the corresponding method", + format!("for {} in {}.{}() {{...}}", + snippet(cx, *pat_span, ".."), + snippet(cx, arg_span, ".."), + kind)); + }); } } } @@ -632,7 +633,7 @@ fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { }; walk_expr(&mut visitor, body); !visitor.used - }, + } _ => false, } } @@ -647,7 +648,7 @@ impl<'a> Visitor<'a> for UsedVisitor { if let ExprPath(None, ref path) = expr.node { if path.segments.len() == 1 && path.segments[0].identifier == self.var { self.used = true; - return + return; } } diff --git a/src/map_clone.rs b/src/map_clone.rs index c83e4ca64ff..8a4e1d770dc 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,8 +1,10 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::{CLONE_PATH, OPTION_PATH}; -use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint}; -use utils::{walk_ptrs_ty, walk_ptrs_ty_depth}; +use utils::{ + is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, + walk_ptrs_ty, walk_ptrs_ty_depth +}; /// **What it does:** This lint checks for mapping clone() over an iterator. /// diff --git a/src/matches.rs b/src/matches.rs index b8ea4f2b1b0..35c0dbb3950 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -7,7 +7,6 @@ use rustc_front::hir::*; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; - use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; @@ -139,20 +138,20 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() { - let els = if is_unit_expr(&arms[1].body) { - None - } else if let ExprBlock(_) = arms[1].body.node { - // matches with blocks that contain statements are prettier as `if let + else` - Some(&*arms[1].body) - } else { - // allow match arms with just expressions - return; - }; - let ty = cx.tcx.expr_ty(ex); - if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { - check_single_match_single_pattern(cx, ex, arms, expr, els); - check_single_match_opt_like(cx, ex, arms, expr, ty, els); - } + let els = if is_unit_expr(&arms[1].body) { + None + } else if let ExprBlock(_) = arms[1].body.node { + // matches with blocks that contain statements are prettier as `if let + else` + Some(&*arms[1].body) + } else { + // allow match arms with just expressions + return; + }; + let ty = cx.tcx.expr_ty(ex); + if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { + check_single_match_single_pattern(cx, ex, arms, expr, els); + check_single_match_opt_like(cx, ex, arms, expr, ty, els); + } } } @@ -194,11 +193,11 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: let path = match arms[1].pats[0].node { PatKind::TupleStruct(ref path, Some(ref inner)) => { // contains any non wildcard patterns? e.g. Err(err) - if inner.iter().any(|pat| if let PatKind::Wild = pat.node { false } else { true }) { + if inner.iter().any(|pat| pat.node != PatKind::Wild) { return; } path.to_string() - }, + } PatKind::TupleStruct(ref path, None) => path.to_string(), PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), _ => return, diff --git a/src/methods.rs b/src/methods.rs index c67e2eade14..6ef779cd79e 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,6 +1,7 @@ use rustc::lint::*; -use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; +use rustc::middle::cstore::CrateStore; use rustc::middle::subst::{Subst, TypeSpace}; use rustc::middle::ty; use rustc_front::hir::*; @@ -8,14 +9,12 @@ use std::borrow::Cow; use std::{fmt, iter}; use syntax::codemap::Span; use syntax::ptr::P; - use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, match_type, method_chain_args, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, - VEC_PATH,}; + VEC_PATH}; use utils::MethodArgs; -use rustc::middle::cstore::CrateStore; #[derive(Clone)] pub struct MethodsPass; @@ -439,12 +438,10 @@ impl LateLintPass for MethodsPass { if let Some(&ret_ty) = ret_ty { ret_ty.walk().any(|t| t == ty) - } - else { + } else { false } - } - else { + } else { false }; @@ -961,9 +958,9 @@ impl SelfKind { fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool { match (self, slf) { (&SelfKind::Value, &SelfValue(_)) | - (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | - (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | - (&SelfKind::No, &SelfStatic) => true, + (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | + (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | + (&SelfKind::No, &SelfStatic) => true, (&SelfKind::Ref, &SelfValue(_)) | (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), _ => false, @@ -973,10 +970,10 @@ impl SelfKind { fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool { match (self, &ty.node) { (&SelfKind::Value, &TyPath(..)) | - (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) | - (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, + (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) | + (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, (&SelfKind::Ref, &TyPath(..)) | - (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, + (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, _ => false, } } diff --git a/src/minmax.rs b/src/minmax.rs index 03e2d0a4ec3..0560bf15604 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -1,11 +1,9 @@ +use consts::{Constant, constant_simple}; use rustc::lint::*; use rustc_front::hir::*; -use syntax::ptr::P; use std::cmp::{PartialOrd, Ordering}; - -use consts::{Constant, constant_simple}; +use syntax::ptr::P; use utils::{match_def_path, span_lint}; -use self::MinMax::{Min, Max}; /// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. /// @@ -36,7 +34,7 @@ impl LateLintPass for MinMaxPass { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | (Max, Some(Ordering::Less)) | (Min, Some(Ordering::Greater)) => (), + (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); } @@ -58,9 +56,9 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); if match_def_path(cx, def_id, &["core", "cmp", "min"]) { - fetch_const(args, Min) + fetch_const(args, MinMax::Min) } else if match_def_path(cx, def_id, &["core", "cmp", "max"]) { - fetch_const(args, Max) + fetch_const(args, MinMax::Max) } else { None } diff --git a/src/misc.rs b/src/misc.rs index 5c154dc59e2..fae780e4ced 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,15 +1,14 @@ +use reexport::*; use rustc::lint::*; -use syntax::ptr::P; +use rustc::middle::const_eval::ConstVal::Float; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::eval_const_expr_partial; +use rustc::middle::ty; use rustc_front::hir::*; -use reexport::*; +use rustc_front::intravisit::FnKind; use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned, ExpnFormat}; -use rustc_front::intravisit::FnKind; -use rustc::middle::ty; -use rustc::middle::const_eval::ConstVal::Float; -use rustc::middle::const_eval::eval_const_expr_partial; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; - +use syntax::ptr::P; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; use utils::{span_lint_and_then, walk_ptrs_ty, is_integer_literal, implements_trait}; diff --git a/src/misc_early.rs b/src/misc_early.rs index bbed9ad4996..604e6002103 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -1,11 +1,8 @@ use rustc::lint::*; - use std::collections::HashMap; - use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; - use utils::{span_lint, span_help_and_lint}; /// **What it does:** This lint checks for structure field patterns bound to wildcards. diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 1759a89242b..c8f86330b93 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,7 +1,6 @@ use rustc::lint::*; -use rustc_front::hir::*; use rustc::middle::ty::{TypeAndMut, TyRef}; - +use rustc_front::hir::*; use utils::{in_external_macro, span_lint}; /// **What it does:** This lint checks for instances of `mut mut` references. diff --git a/src/mut_reference.rs b/src/mut_reference.rs index ea2c00bab94..0e5b038f27d 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -1,8 +1,8 @@ use rustc::lint::*; -use rustc_front::hir::*; -use utils::span_lint; use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; +use rustc_front::hir::*; use syntax::ptr::P; +use utils::span_lint; /// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. /// diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 8a51ba27b8e..c8f5e3c7919 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -3,12 +3,10 @@ //! This lint is **warn** by default use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; +use rustc::middle::subst::ParamSpace; +use rustc::middle::ty; use rustc_front::hir::Expr; - use syntax::ast; -use rustc::middle::ty; -use rustc::middle::subst::ParamSpace; - use utils::{span_lint, MUTEX_PATH, match_type}; /// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do. diff --git a/src/needless_bool.rs b/src/needless_bool.rs index fe46988dccb..625f8b0ca78 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -4,10 +4,8 @@ use rustc::lint::*; use rustc_front::hir::*; - use syntax::ast::LitKind; use syntax::codemap::Spanned; - use utils::{span_lint, span_lint_and_then, snippet}; /// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. diff --git a/src/needless_features.rs b/src/needless_features.rs index 646ebbbd015..f80ac48320e 100644 --- a/src/needless_features.rs +++ b/src/needless_features.rs @@ -4,7 +4,6 @@ use rustc::lint::*; use rustc_front::hir::*; - use utils::span_lint; use utils; diff --git a/src/needless_update.rs b/src/needless_update.rs index d18930c8ccc..e3359469150 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -1,7 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::middle::ty::TyStruct; use rustc_front::hir::{Expr, ExprStruct}; - use utils::span_lint; /// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway. diff --git a/src/no_effect.rs b/src/no_effect.rs index 0df5ede82da..65dfeb0d4be 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,10 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::middle::def::Def; -use rustc_front::hir::{Expr, Expr_}; -use rustc_front::hir::{Stmt, StmtSemi}; - -use utils::in_macro; -use utils::span_lint; +use rustc_front::hir::{Expr, Expr_, Stmt, StmtSemi}; +use utils::{in_macro, span_lint}; /// **What it does:** This lint checks for statements which have no effect. /// diff --git a/src/open_options.rs b/src/open_options.rs index 8b1c4a90fdf..e3f61afcf1c 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use rustc_front::hir::{Expr, ExprMethodCall, ExprLit}; -use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; -use syntax::codemap::{Span, Spanned}; use syntax::ast::LitKind; +use syntax::codemap::{Span, Spanned}; +use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; /// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. /// diff --git a/src/panic.rs b/src/panic.rs index b76def8d2f3..60a3ce1a461 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::LitKind; - use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; /// **What it does:** This lint checks for missing parameters in `panic!`. diff --git a/src/precedence.rs b/src/precedence.rs index d498510f97a..7e24f55d1b4 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -1,7 +1,6 @@ use rustc::lint::*; -use syntax::codemap::Spanned; use syntax::ast::*; - +use syntax::codemap::Spanned; use utils::{span_lint, snippet}; /// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following: diff --git a/src/print.rs b/src/print.rs index 3c10b4bed13..d7d83bfb437 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,6 +1,6 @@ +use rustc::front::map::Node::{NodeItem, NodeImplItem}; use rustc::lint::*; use rustc_front::hir::*; -use rustc::front::map::Node::{NodeItem, NodeImplItem}; use utils::{FMT_ARGUMENTV1_NEW_PATH, DEBUG_FMT_METHOD_PATH, IO_PRINT_PATH}; use utils::{is_expn_of, match_path, span_lint}; diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 707adcfeb07..c02e5609b8c 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -2,13 +2,12 @@ //! //! This lint is **warn** by default -use rustc::lint::*; -use rustc_front::hir::*; use rustc::front::map::NodeItem; +use rustc::lint::*; use rustc::middle::ty; - -use utils::{span_lint, match_type}; +use rustc_front::hir::*; use utils::{STRING_PATH, VEC_PATH}; +use utils::{span_lint, match_type}; /// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. /// diff --git a/src/regex.rs b/src/regex.rs index 745d685ec80..f58b6319d57 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,13 +1,13 @@ use regex_syntax; -use std::error::Error; +use rustc::lint::*; +use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc_front::hir::*; use std::collections::HashSet; +use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; -use rustc_front::hir::*; -use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::lint::*; use utils::{is_expn_of, match_path, match_type, REGEX_NEW_PATH, span_lint, span_help_and_lint}; @@ -54,7 +54,7 @@ declare_lint! { #[derive(Clone, Default)] pub struct RegexPass { spans: HashSet<Span>, - last: Option<NodeId> + last: Option<NodeId>, } impl LintPass for RegexPass { @@ -86,10 +86,10 @@ impl LateLintPass for RegexPass { self.last = Some(block.id); }} } - + fn check_block_post(&mut self, _: &LateContext, block: &Block) { if self.last.map_or(false, |id| block.id == id) { - self.last = None; + self.last = None; } } @@ -145,7 +145,7 @@ impl LateLintPass for RegexPass { fn str_span(base: Span, s: &str, c: usize) -> Span { let lo = match s.char_indices().nth(c) { Some((b, _)) => base.lo + BytePos(b as u32), - _ => base.hi + _ => base.hi, }; Span{ lo: lo, hi: lo, ..base } } @@ -153,7 +153,7 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { match eval_const_expr_partial(cx.tcx, e, ExprTypeChecked, None) { Ok(ConstVal::Str(r)) => Some(r), - _ => None + _ => None, } } @@ -165,20 +165,21 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { Expr::Literal {..} => Some("consider using `str::contains`"), Expr::Concat(ref exprs) => { match exprs.len() { - 2 => match (&exprs[0], &exprs[1]) { - (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"), - (&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"), - _ => None, - }, + 2 => { + match (&exprs[0], &exprs[1]) { + (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), + (&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"), + (&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"), + _ => None, + } + } 3 => { if let (&Expr::StartText, &Expr::Literal {..}, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { Some("consider using `==` on `str`s") - } - else { + } else { None } - }, + } _ => None, } } diff --git a/src/returns.rs b/src/returns.rs index bfddee797b8..43ea3780173 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use syntax::ast::*; -// use reexport::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; diff --git a/src/shadow.rs b/src/shadow.rs index 206fa492419..baf5c9b8872 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -1,12 +1,10 @@ -use std::ops::Deref; -use rustc_front::hir::*; use reexport::*; -use syntax::codemap::Span; -use rustc_front::intravisit::{Visitor, FnKind}; - use rustc::lint::*; use rustc::middle::def::Def; - +use rustc_front::hir::*; +use rustc_front::intravisit::{Visitor, FnKind}; +use std::ops::Deref; +use syntax::codemap::Span; use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. diff --git a/src/strings.rs b/src/strings.rs index a7dca02c967..fdba6302a46 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -6,10 +6,9 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; - -use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; -use utils::SpanlessEq; use utils::STRING_PATH; +use utils::SpanlessEq; +use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). /// diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index 417ec540856..c945fd7148e 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -1,6 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; - use utils::is_adjusted; use utils::span_lint; diff --git a/src/types.rs b/src/types.rs index eec8bd63eb7..248aab32baa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,13 +1,12 @@ +use reexport::*; use rustc::lint::*; +use rustc::middle::const_eval; +use rustc::middle::ty; use rustc_front::hir::*; -use reexport::*; -use rustc_front::util::{is_comparison_binop, binop_to_string}; -use syntax::codemap::Span; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; -use rustc::middle::ty; -use rustc::middle::const_eval; +use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::ast::{IntTy, UintTy, FloatTy}; - +use syntax::codemap::Span; use utils::*; /// Handles all the linting of funky types @@ -618,7 +617,7 @@ enum AbsurdComparisonResult { } fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) - -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { + -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { use types::ExtremeType::*; use types::AbsurdComparisonResult::*; type Extr<'a> = ExtremeExpr<'a>; @@ -704,7 +703,10 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx _ => return None, }; - Some(ExtremeExpr { which: which, expr: expr }) + Some(ExtremeExpr { + which: which, + expr: expr, + }) } impl LateLintPass for AbsurdExtremeComparisons { @@ -721,16 +723,20 @@ impl LateLintPass for AbsurdExtremeComparisons { let conclusion = match result { AlwaysFalse => "this comparison is always false".to_owned(), AlwaysTrue => "this comparison is always true".to_owned(), - InequalityImpossible => - format!("the case where the two sides are not equal never occurs, \ - consider using {} == {} instead", + InequalityImpossible => { + format!("the case where the two sides are not equal never occurs, consider using {} == {} \ + instead", snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs")), + snippet(cx, rhs.span, "rhs")) + } }; let help = format!("because {} is the {} value for this type, {}", snippet(cx, culprit.expr.span, "x"), - match culprit.which { Minimum => "minimum", Maximum => "maximum" }, + match culprit.which { + Minimum => "minimum", + Maximum => "maximum", + }, conclusion); span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help); diff --git a/src/unicode.rs b/src/unicode.rs index c8d810b9e71..0f21822ea08 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,11 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; -use syntax::codemap::Span; - use syntax::ast::LitKind; - +use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; - use utils::{snippet, span_help_and_lint}; /// **What it does:** This lint checks for the unicode zero-width space in the code. diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 631bcb1b100..faa2082b7d0 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -19,11 +19,17 @@ pub struct SpanlessEq<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessEq { cx: cx, ignore_fn: false } + SpanlessEq { + cx: cx, + ignore_fn: false, + } } pub fn ignore_fn(self) -> Self { - SpanlessEq { cx: self.cx, ignore_fn: true } + SpanlessEq { + cx: self.cx, + ignore_fn: true, + } } /// Check whether two statements are the same. @@ -40,7 +46,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), _ => false, } } @@ -48,7 +54,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two blocks are the same. pub fn eq_block(&self, left: &Block, right: &Block) -> bool { over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && - both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) + both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } // ok, it’s a big function, but mostly one big match with simples cases @@ -77,9 +83,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } - (&ExprBlock(ref l), &ExprBlock(ref r)) => { - self.eq_block(l, r) - } + (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } @@ -267,7 +271,10 @@ pub struct SpanlessHash<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessHash { cx: cx, s: SipHasher::new() } + SpanlessHash { + cx: cx, + s: SipHasher::new(), + } } pub fn finish(&self) -> u64 { @@ -389,7 +396,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprLit; c.hash(&mut self.s); l.hash(&mut self.s); - }, + } ExprLoop(ref b, ref i) => { let c: fn(_, _) -> _ = ExprLoop; c.hash(&mut self.s); @@ -466,7 +473,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprTup; c.hash(&mut self.s); self.hash_exprs(tup); - }, + } ExprTupField(ref le, li) => { let c: fn(_, _) -> _ = ExprTupField; c.hash(&mut self.s); @@ -491,7 +498,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_exprs(v); - }, + } ExprWhile(ref cond, ref b, l) => { let c: fn(_, _, _) -> _ = ExprWhile; c.hash(&mut self.s); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b9dd9359c66..a8708eb8f7f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,7 +9,7 @@ use std::borrow::Cow; use std::mem; use std::ops::{Deref, DerefMut}; use std::str::FromStr; -use syntax::ast::{LitKind, self}; +use syntax::ast::{self, LitKind}; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index dbfa2744189..1d119b05176 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -1,8 +1,7 @@ +use consts::{Constant, constant_simple, FloatWidth}; use rustc::lint::*; use rustc_front::hir::*; - use utils::span_help_and_lint; -use consts::{Constant, constant_simple, FloatWidth}; /// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists /// `of 0.0/0.0`, which is always NaN. It is more clear to replace instances of -- cgit 1.4.1-3-g733a5 From c1b2fe31b70e2b7293b3aea7cfb8b1ed084b9334 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 24 Feb 2016 20:52:47 +0100 Subject: Use `span_suggestion` in `len_zero` --- src/len_zero.rs | 20 ++++++++++++-------- tests/compile-fail/len_zero.rs | 25 ++++++++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 222de03f006..f99ea1e6fd5 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -8,7 +8,7 @@ use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; use syntax::ast::{Lit, LitKind}; -use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty}; +use utils::{get_item_name, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. /// @@ -80,7 +80,6 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - // span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident)); for i in trait_items { if is_named_self(i, "len") { span_lint(cx, @@ -151,12 +150,17 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitKind::Int(0, _), ..} = *lit { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { - span_lint(cx, - LEN_ZERO, - span, - &format!("consider replacing the len comparison with `{}{}.is_empty()`", - op, - snippet(cx, args[0].span, "_"))); + span_lint_and_then(cx, + LEN_ZERO, + span, + "length comparison to zero", + |db| { + db.span_suggestion(span, + "consider using `is_empty`", + format!("{}{}.is_empty()", + op, + snippet(cx, args[0].span, "_"))); + }); } } } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 626e5557fb6..9814a1c2d7d 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -69,7 +69,10 @@ impl HasWrongIsEmpty { #[deny(len_zero)] fn main() { let x = [1, 2]; - if x.len() == 0 { //~ERROR consider replacing the len comparison + if x.len() == 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION x.is_empty() println!("This should not happen!"); } @@ -84,19 +87,31 @@ fn main() { } let hie = HasIsEmpty; - if hie.len() == 0 { //~ERROR consider replacing the len comparison + if hie.len() == 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION hie.is_empty() println!("Or this!"); } - if hie.len() != 0 { //~ERROR consider replacing the len comparison + if hie.len() != 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION !hie.is_empty() println!("Or this!"); } - if hie.len() > 0 { //~ERROR consider replacing the len comparison + if hie.len() > 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION !hie.is_empty() println!("Or this!"); } assert!(!hie.is_empty()); let wie : &WithIsEmpty = &Wither; - if wie.len() == 0 { //~ERROR consider replacing the len comparison + if wie.len() == 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION wie.is_empty() println!("Or this!"); } assert!(!wie.is_empty()); -- cgit 1.4.1-3-g733a5 From 7b1a0a94348bd429b863ac16dfa0cc9c79e73c90 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 24 Feb 2016 20:53:15 +0100 Subject: Macro check `len_zero` --- src/len_zero.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index f99ea1e6fd5..f63e733d65b 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -8,7 +8,7 @@ use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; use syntax::ast::{Lit, LitKind}; -use utils::{get_item_name, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; +use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. /// @@ -51,6 +51,10 @@ impl LintPass for LenZero { impl LateLintPass for LenZero { fn check_item(&mut self, cx: &LateContext, item: &Item) { + if in_macro(cx, item.span) { + return; + } + match item.node { ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), ItemImpl(_, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), @@ -59,6 +63,10 @@ impl LateLintPass for LenZero { } fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_macro(cx, expr.span) { + return; + } + if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = expr.node { match cmp { BiEq => check_cmp(cx, expr.span, left, right, ""), -- cgit 1.4.1-3-g733a5 From 783437eef0380dff8e1a6a4d049366aa54011f48 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 24 Feb 2016 20:54:35 +0100 Subject: Use `span_suggestion` in loops lints --- src/loops.rs | 13 ++++++++----- tests/compile-fail/while_loop.rs | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index acfb6c150d5..602de0eebcb 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -271,14 +271,17 @@ impl LateLintPass for LoopsPass { } else { expr_block(cx, &arms[0].body, Some(other_stuff.join("\n ")), "..") }; - span_help_and_lint(cx, + span_lint_and_then(cx, WHILE_LET_LOOP, expr.span, "this loop could be written as a `while let` loop", - &format!("try\nwhile let {} = {} {}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, ".."), - loop_body)); + |db| { + let sug = format!("while let {} = {} {}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, matchexpr.span, ".."), + loop_body); + db.span_suggestion(expr.span, "try", sug); + }); } } _ => (), diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index ee8e4622e0e..bbb76cfbfaf 100644 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -6,7 +6,10 @@ fn main() { let y = Some(true); - loop { //~ERROR + loop { + //~^ERROR this loop could be written as a `while let` loop + //~|HELP try + //~|SUGGESTION while let Some(_x) = y { if let Some(_x) = y { let _v = 1; } else { @@ -19,13 +22,19 @@ fn main() { } break; } - loop { //~ERROR + loop { + //~^ERROR this loop could be written as a `while let` loop + //~|HELP try + //~|SUGGESTION while let Some(_x) = y { match y { Some(_x) => true, None => break }; } - loop { //~ERROR + loop { + //~^ERROR this loop could be written as a `while let` loop + //~|HELP try + //~|SUGGESTION while let Some(x) = y { let x = match y { Some(x) => x, None => break @@ -33,7 +42,10 @@ fn main() { let _x = x; let _str = "foo"; } - loop { //~ERROR + loop { + //~^ERROR this loop could be written as a `while let` loop + //~|HELP try + //~|SUGGESTION while let Some(x) = y { let x = match y { Some(x) => x, None => break, -- cgit 1.4.1-3-g733a5 From 62cbd877281a9d8dd8b4948dd73799319eb16846 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 26 Feb 2016 12:45:55 +0100 Subject: Fix false positive in `FOR_KV_MAP` and `&mut` refs --- src/loops.rs | 19 +++++++++---------- tests/compile-fail/for_loop.rs | 7 +++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index a4c0e349495..3eb013da6d9 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -588,24 +588,23 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex } } -// Check for the FOR_KV_MAP lint. +/// Check for the FOR_KV_MAP lint. fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let PatKind::Tup(ref pat) = pat.node { if pat.len() == 2 { - let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), _ => return, }; - let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); - let arg_span = if let ExprAddrOf(_, ref expr) = arg.node { - expr.span - } else { - arg.span + let arg_span = match arg.node { + ExprAddrOf(MutImmutable, ref expr) => expr.span, + ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method + _ => arg.span, }; + let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); if match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &BTREEMAP_PATH) { span_lint_and_then(cx, FOR_KV_MAP, @@ -625,7 +624,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex } -// Return true if the pattern is a `PatWild` or an ident prefixed with '_'. +/// Return true if the pattern is a `PatWild` or an ident prefixed with '_'. fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { PatKind::Wild => true, @@ -845,7 +844,7 @@ enum VarState { DontWarn, } -// Scan a for loop for variables that are incremented exactly once. +/// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference states: HashMap<NodeId, VarState>, // incremented variables @@ -897,7 +896,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { } } -// Check whether a variable is initialized to zero at the start of a loop. +/// Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference end_expr: &'v Expr, // the for loop. Stop scanning here. diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index b805963a03a..69ce68b17db 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -311,6 +311,13 @@ fn main() { let _v = v; } + let mut m : HashMap<u64, u64> = HashMap::new(); + for (_, v) in &mut m { + // Ok, there is no values_mut method or equivalent + let _v = v; + } + + let rm = &m; for (k, _value) in rm { //~^ you seem to want to iterate on a map's keys -- cgit 1.4.1-3-g733a5 From 810de56079b678caf72e9fa712798da61f11fe77 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 27 Feb 2016 17:57:36 +0100 Subject: Add a lint about suspiciously formatted `=@` ops For `@` in {`*`, `!`, `-`}. --- README.md | 255 ++++++++++++++++++++------------------- src/formatting.rs | 66 ++++++++++ src/lib.rs | 3 + tests/compile-fail/formatting.rs | 28 +++++ 4 files changed, 225 insertions(+), 127 deletions(-) create mode 100644 src/formatting.rs create mode 100755 tests/compile-fail/formatting.rs diff --git a/README.md b/README.md index 62d6695b24d..9156db1cbdb 100644 --- a/README.md +++ b/README.md @@ -8,133 +8,134 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 123 lints included in this crate: - -name | default | meaning ----------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -[absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison involving a maximum or minimum value involves a case that is always true or always false -[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) -[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` -[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` -[bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` -[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary -[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` -[char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8 -[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char -[clone_double_ref](https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` -[clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type -[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) -[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` -[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions -[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver -[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value -[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore -[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected -[enum_glob_use](https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use) | allow | finds use items that import all variants of an enum -[enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix -[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types -[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do -[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice -[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` -[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) -[for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do -[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` -[for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` -[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks -[ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition -[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases -[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations -[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement -[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` -[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block -[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque -[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) -[map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` -[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead -[match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead -[match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead -[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type -[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields -[new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method -[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect -[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file -[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result -[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` -[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` -[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[or_fun_call](https://github.com/Manishearth/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method when the `*or_else` would do -[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing -[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught -[print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator -[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do -[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | warn | finds use of `regex!(_)`, suggests `Regex::new(_)` instead -[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` -[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` -[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value -[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` -[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead -[single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead -[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` -[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead -[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -[string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient -[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. -[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations -[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) -[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) -[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference -[unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` -[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 -[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 -[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions -[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting -[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore -[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` -[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types -[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` -[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop -[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator -[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN -[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing +There are 125 lints included in this crate: + +name | default | meaning +---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +[absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison involving a maximum or minimum value involves a case that is always true or always false +[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` +[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` +[bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` +[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap +[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary +[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32` +[char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8 +[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char +[clone_double_ref](https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` +[clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type +[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) +[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` +[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions +[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver +[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly +[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value +[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore +[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[enum_glob_use](https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use) | allow | finds use items that import all variants of an enum +[enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix +[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types +[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do +[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice +[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` +[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) +[for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do +[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` +[for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` +[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks +[ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition +[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations +[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement +[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` +[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block +[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) +[map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` +[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead +[match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms +[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead +[match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies +[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) +[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead +[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type +[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method +[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect +[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result +[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` +[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` +[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[or_fun_call](https://github.com/Manishearth/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method when the `*or_else` would do +[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing +[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` +[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught +[print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout +[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator +[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do +[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | warn | finds use of `regex!(_)`, suggests `Regex::new(_)` instead +[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` +[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` +[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value +[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` +[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead +[single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead +[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` +[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead +[string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead +[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient +[suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` +[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. +[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations +[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) +[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) +[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` +[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 +[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 +[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions +[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting +[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore +[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` +[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types +[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` +[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop +[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator +[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN +[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! diff --git a/src/formatting.rs b/src/formatting.rs new file mode 100644 index 00000000000..ce3c6f45a22 --- /dev/null +++ b/src/formatting.rs @@ -0,0 +1,66 @@ +use rustc::lint::*; +use syntax::codemap::mk_sp; +use syntax::ast; +use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; +use syntax::ptr::P; + +/// **What it does:** This lint looks for use of the non-existent `=*`, `=!` and `=-` operators. +/// +/// **Why is this bad?** This either a typo of `*=`, `!=` or `-=` or confusing. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// a =- 42; // confusing, should it be `a -= 42` or `a = -42`? +/// ``` +declare_lint! { + pub SUSPICIOUS_ASSIGNMENT_FORMATTING, + Warn, + "suspicious formatting of `*=`, `-=` or `!=`" +} + +#[derive(Copy,Clone)] +pub struct Formatting; + +impl LintPass for Formatting { + fn get_lints(&self) -> LintArray { + lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING] + } +} + +impl EarlyLintPass for Formatting { + fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { + check_assign(cx, expr); + } +} + +/// Implementation of the SUSPICIOUS_ASSIGNMENT_FORMATTING lint. +fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { + if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { + if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) { + let eq_span = mk_sp(lhs.span.hi, rhs.span.lo); + + if let Some((sub_rhs, op)) = check_unop(rhs) { + if let Some(eq_snippet) = snippet_opt(cx, eq_span) { + let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo); + if eq_snippet.ends_with('=') { + span_note_and_lint(cx, + SUSPICIOUS_ASSIGNMENT_FORMATTING, + eqop_span, + &format!("this looks like you are trying to use `.. {op}= ..`, but you really are doing `.. = ({op} ..)`", op=op), + eqop_span, + &format!("to remove this lint, use either `{op}=` or `= {op}`", op=op)); + } + } + } + } + } +} + +fn check_unop(expr: &ast::Expr) -> Option<(&P<ast::Expr>, &'static str)> { + match expr.node { + ast::ExprKind::Unary(op, ref expr) => Some((expr, ast::UnOp::to_string(op))), + _ => None, + } +} diff --git a/src/lib.rs b/src/lib.rs index 8348eb09834..61029138fc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,7 @@ pub mod eq_op; pub mod escape; pub mod eta_reduction; pub mod format; +pub mod formatting; pub mod identity_op; pub mod items_after_statements; pub mod len_zero; @@ -165,6 +166,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box regex::RegexPass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_late_lint_pass(box format::FormatMacLint); + reg.register_early_lint_pass(box formatting::Formatting); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -212,6 +214,7 @@ pub fn plugin_registrar(reg: &mut Registry) { escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, format::USELESS_FORMAT, + formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, identity_op::IDENTITY_OP, items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, diff --git a/tests/compile-fail/formatting.rs b/tests/compile-fail/formatting.rs new file mode 100755 index 00000000000..c2d0f54f906 --- /dev/null +++ b/tests/compile-fail/formatting.rs @@ -0,0 +1,28 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(clippy)] +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(if_same_then_else)] + +fn main() { + // weird op_eq formatting: + let mut a = 42; + a =- 35; + //~^ ERROR this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` + //~| NOTE to remove this lint, use either `-=` or `= -` + a =* &191; + //~^ ERROR this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` + //~| NOTE to remove this lint, use either `*=` or `= *` + + let mut b = true; + b =! false; + //~^ ERROR this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` + //~| NOTE to remove this lint, use either `!=` or `= !` + + // those are ok: + a = -35; + a = *&191; + b = !false; +} -- cgit 1.4.1-3-g733a5 From 1c3cce8ba586c634d70a304d7e1a0da58b35bbea Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 27 Feb 2016 17:59:04 +0100 Subject: Add a lint about suspiciously formatted `else if` --- README.md | 1 + src/formatting.rs | 110 ++++++++++++++++++++++++++++++++++++++- src/lib.rs | 1 + tests/compile-fail/formatting.rs | 48 +++++++++++++++++ 4 files changed, 158 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9156db1cbdb..c9730c4c58b 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ name [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` +[suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations diff --git a/src/formatting.rs b/src/formatting.rs index ce3c6f45a22..f82aa7d8188 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -6,7 +6,7 @@ use syntax::ptr::P; /// **What it does:** This lint looks for use of the non-existent `=*`, `=!` and `=-` operators. /// -/// **Why is this bad?** This either a typo of `*=`, `!=` or `-=` or confusing. +/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing. /// /// **Known problems:** None. /// @@ -20,18 +20,65 @@ declare_lint! { "suspicious formatting of `*=`, `-=` or `!=`" } +/// **What it does:** This lint checks for formatting of `else if`. It lints if the `else` and `if` +/// are not on the same line or the `else` seems to be missing. +/// +/// **Why is this bad?** This is probably some refactoring remnant, even if the code is correct, it +/// might look confusing. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// if foo { +/// } if bar { // looks like an `else` is missing here +/// } +/// +/// if foo { +/// } else +/// +/// if bar { // this is the `else` block of the previous `if`, but should it be? +/// } +/// ``` +declare_lint! { + pub SUSPICIOUS_ELSE_FORMATTING, + Warn, + "suspicious formatting of `else if`" +} + #[derive(Copy,Clone)] pub struct Formatting; impl LintPass for Formatting { fn get_lints(&self) -> LintArray { - lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING] + lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING] } } impl EarlyLintPass for Formatting { + fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { + for w in block.stmts.windows(2) { + match (&w[0].node, &w[1].node) { + (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Expr(ref second, _)) | + (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Semi(ref second, _)) => { + check_consecutive_ifs(cx, first, second); + } + _ => (), + } + } + + if let Some(ref expr) = block.expr { + if let Some(ref stmt) = block.stmts.iter().last() { + if let ast::StmtKind::Expr(ref first, _) = stmt.node { + check_consecutive_ifs(cx, first, expr); + } + } + } + } + fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { check_assign(cx, expr); + check_else_if(cx, expr); } } @@ -64,3 +111,62 @@ fn check_unop(expr: &ast::Expr) -> Option<(&P<ast::Expr>, &'static str)> { _ => None, } } + +/// Implementation of the SUSPICIOUS_ELSE_FORMATTING lint for weird `else if`. +fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { + if let Some((then, &Some(ref else_))) = unsugar_if(expr) { + if unsugar_if(else_).is_some() && + !differing_macro_contexts(then.span, else_.span) && + !in_macro(cx, then.span) { + // this will be a span from the closing ‘}’ of the “then” block (excluding) to the + // “if” of the “else if” block (excluding) + let else_span = mk_sp(then.span.hi, else_.span.lo); + + // the snippet should look like " else \n " with maybe comments anywhere + // it’s bad when there is a ‘\n’ after the “else” + if let Some(else_snippet) = snippet_opt(cx, else_span) { + let else_pos = else_snippet.find("else").expect("there must be a `else` here"); + + if else_snippet[else_pos..].contains('\n') { + span_note_and_lint(cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this is an `else if` but the formatting might hide it", + else_span, + "to remove this lint, remove the `else` or remove the new line between `else` and `if`"); + } + } + } + } +} + +/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. +fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { + if !differing_macro_contexts(first.span, second.span) && + !in_macro(cx, first.span) && + unsugar_if(first).is_some() && + unsugar_if(second).is_some() { + // where the else would be + let else_span = mk_sp(first.span.hi, second.span.lo); + + if let Some(else_snippet) = snippet_opt(cx, else_span) { + if !else_snippet.contains('\n') { + span_note_and_lint(cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this looks like an `else if` but the `else` is missing", + else_span, + "to remove this lint, add the missing `else` or add a new line before the second `if`"); + } + } + } +} + +/// Match `if` or `else if` expressions and return the `then` and `else` block. +fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)>{ + match expr.node { + ast::ExprKind::If(_, ref then, ref else_) | + ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), + _ => None, + } +} diff --git a/src/lib.rs b/src/lib.rs index 61029138fc7..47d9fc6f24c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,6 +215,7 @@ pub fn plugin_registrar(reg: &mut Registry) { eta_reduction::REDUNDANT_CLOSURE, format::USELESS_FORMAT, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, + formatting::SUSPICIOUS_ELSE_FORMATTING, identity_op::IDENTITY_OP, items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, diff --git a/tests/compile-fail/formatting.rs b/tests/compile-fail/formatting.rs index c2d0f54f906..14a23111ec7 100755 --- a/tests/compile-fail/formatting.rs +++ b/tests/compile-fail/formatting.rs @@ -6,7 +6,55 @@ #![allow(unused_assignments)] #![allow(if_same_then_else)] +fn foo() -> bool { true } + fn main() { + // weird `else if` formatting: + if foo() { + } if foo() { //~ERROR this looks like an `else if` but the `else` is missing + } + + let _ = { + if foo() { + } if foo() { //~ERROR this looks like an `else if` but the `else` is missing + } + else { + } + }; + + if foo() { + } else //~ERROR this is an `else if` but the formatting might hide it + if foo() { // the span of the above error should continue here + } + + if foo() { + } //~ERROR this is an `else if` but the formatting might hide it + else + if foo() { // the span of the above error should continue here + } + + // those are ok: + if foo() { + } + if foo() { + } + + if foo() { + } else if foo() { + } + + if foo() { + } + else if foo() { + } + + if foo() { + } + + else if + + foo() {} + // weird op_eq formatting: let mut a = 42; a =- 35; -- cgit 1.4.1-3-g733a5 From 3a5b9a707c786bf02ed05d65ca8394d77df601fb Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 27 Feb 2016 18:05:50 +0100 Subject: Fix (new?) rustc warnings --- src/consts.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index cf32a9a2c82..64f45d72c12 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -206,7 +206,6 @@ fn lit_to_constant(lit: &LitKind) -> Constant { } fn constant_not(o: Constant) -> Option<Constant> { - use syntax::ast::LitIntType::*; use self::Constant::*; match o { Bool(b) => Some(Bool(!b)), @@ -232,7 +231,6 @@ fn constant_not(o: Constant) -> Option<Constant> { } fn constant_negate(o: Constant) -> Option<Constant> { - use syntax::ast::LitIntType::*; use self::Constant::*; match o { Int(value, LitIntType::Signed(ity), sign) => Some(Int(value, LitIntType::Signed(ity), neg_sign(sign))), -- cgit 1.4.1-3-g733a5 From 05178c92b900caeee17bfc4acbaf6baf6600f089 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 27 Feb 2016 18:14:37 +0100 Subject: Cleanup --- src/formatting.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index f82aa7d8188..efcb222ebed 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -88,8 +88,9 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) { let eq_span = mk_sp(lhs.span.hi, rhs.span.lo); - if let Some((sub_rhs, op)) = check_unop(rhs) { + if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node { if let Some(eq_snippet) = snippet_opt(cx, eq_span) { + let op = ast::UnOp::to_string(op); let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo); if eq_snippet.ends_with('=') { span_note_and_lint(cx, @@ -105,13 +106,6 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { } } -fn check_unop(expr: &ast::Expr) -> Option<(&P<ast::Expr>, &'static str)> { - match expr.node { - ast::ExprKind::Unary(op, ref expr) => Some((expr, ast::UnOp::to_string(op))), - _ => None, - } -} - /// Implementation of the SUSPICIOUS_ELSE_FORMATTING lint for weird `else if`. fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { -- cgit 1.4.1-3-g733a5 From 72ef26272d9718f5495b3a143010e031ba898e5a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 28 Feb 2016 00:01:15 +0100 Subject: Lint `foo = bar; bar = foo` sequences --- README.md | 3 ++- src/lib.rs | 3 +++ src/swap.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/swap.rs | 17 ++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/swap.rs create mode 100755 tests/compile-fail/swap.rs diff --git a/README.md b/README.md index c9730c4c58b..f7527372585 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 125 lints included in this crate: +There are 126 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -114,6 +114,7 @@ name [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` +[suspicious_swap](https://github.com/Manishearth/rust-clippy/wiki#suspicious_swap) | warn | `foo = bar; bar = foo` sequence [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations diff --git a/src/lib.rs b/src/lib.rs index 47d9fc6f24c..217110e2bd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ pub mod regex; pub mod returns; pub mod shadow; pub mod strings; +pub mod swap; pub mod temporary_assignment; pub mod transmute; pub mod types; @@ -167,6 +168,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_late_lint_pass(box format::FormatMacLint); reg.register_early_lint_pass(box formatting::Formatting); + reg.register_late_lint_pass(box swap::Swap); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -285,6 +287,7 @@ pub fn plugin_registrar(reg: &mut Registry) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, + swap::SUSPICIOUS_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, diff --git a/src/swap.rs b/src/swap.rs new file mode 100644 index 00000000000..8e1b1e781f4 --- /dev/null +++ b/src/swap.rs @@ -0,0 +1,66 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; +use syntax::codemap::mk_sp; + +/// **What it does:** This lints `foo = bar; bar = foo` sequences. +/// +/// **Why is this bad?** This looks like a failed attempt to swap. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// a = b; +/// b = a; +/// ``` +declare_lint! { + pub SUSPICIOUS_SWAP, + Warn, + "`foo = bar; bar = foo` sequence" +} + +#[derive(Copy,Clone)] +pub struct Swap; + +impl LintPass for Swap { + fn get_lints(&self) -> LintArray { + lint_array![SUSPICIOUS_SWAP] + } +} + +impl LateLintPass for Swap { + fn check_block(&mut self, cx: &LateContext, block: &Block) { + for w in block.stmts.windows(2) { + if_let_chain!{[ + let StmtSemi(ref first, _) = w[0].node, + let StmtSemi(ref second, _) = w[1].node, + !differing_macro_contexts(first.span, second.span), + let ExprAssign(ref lhs0, ref rhs0) = first.node, + let ExprAssign(ref lhs1, ref rhs1) = second.node, + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) + ], { + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { + (format!(" `{}` and `{}`", first, second), first, second) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; + + let span = mk_sp(first.span.lo, second.span.hi); + + span_lint_and_then(cx, + SUSPICIOUS_SWAP, + span, + &format!("this looks like you are trying to swap{}", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap({}, {})", lhs, rhs)); + db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); + } + }); + }} + } + } +} diff --git a/tests/compile-fail/swap.rs b/tests/compile-fail/swap.rs new file mode 100755 index 00000000000..be2c785eb41 --- /dev/null +++ b/tests/compile-fail/swap.rs @@ -0,0 +1,17 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(clippy)] +#![allow(unused_assignments)] + +fn main() { + let mut a = 42; + let mut b = 1337; + + a = b; + b = a; + //~^^ ERROR this looks like you are trying to swap `a` and `b` + //~| HELP try + //~| SUGGESTION std::mem::swap(a, b); + //~| NOTE or maybe you should use `std::mem::replace`? +} -- cgit 1.4.1-3-g733a5 From 5fadfb3ea6a89512959b0bfa1261ed92bcf47964 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 27 Feb 2016 22:59:15 +0100 Subject: Fix wrong suggestion in `WHILE_LET_LOOP` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ok, I lied in the title. This basically *removes* the problematic part but: 1) it was ugly with big bodies; 2) it was not indented properly; 3) it wasn’t very smart (see #675). --- src/loops.rs | 34 +++++++++------------------------- tests/compile-fail/while_loop.rs | 13 +++++++++++++ 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 3eb013da6d9..e6b28d20e83 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -11,7 +11,7 @@ use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; use std::collections::HashMap; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty}; use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; @@ -241,20 +241,6 @@ impl LateLintPass for LoopsPass { // or extract the first expression (if any) from the block if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { - // collect the remaining statements below the match - let mut other_stuff = block.stmts - .iter() - .skip(1) - .map(|stmt| snippet(cx, stmt.span, "..")) - .collect::<Vec<Cow<_>>>(); - if inner_stmt_expr.is_some() { - // if we have a statement which has a match, - if let Some(ref expr) = block.expr { - // then collect the expression (without semicolon) below it - other_stuff.push(snippet(cx, expr.span, "..")); - } - } - // ensure "if let" compatible match structure match *source { MatchSource::Normal | MatchSource::IfLetDesugar{..} => { @@ -264,22 +250,20 @@ impl LateLintPass for LoopsPass { if in_external_macro(cx, expr.span) { return; } - let loop_body = if inner_stmt_expr.is_some() { - // FIXME: should probably be an ellipsis - // tabbing and newline is probably a bad idea, especially for large blocks - Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))) - } else { - expr_block(cx, &arms[0].body, Some(other_stuff.join("\n ")), "..") - }; + + // NOTE: we used to make build a body here instead of using + // ellipsis, this was removed because: + // 1) it was ugly with big bodies; + // 2) it was not indented properly; + // 3) it wasn’t very smart (see #675). span_lint_and_then(cx, WHILE_LET_LOOP, expr.span, "this loop could be written as a `while let` loop", |db| { - let sug = format!("while let {} = {} {}", + let sug = format!("while let {} = {} {{ .. }}", snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, ".."), - loop_body); + snippet(cx, matchexpr.span, "..")); db.span_suggestion(expr.span, "try", sug); }); } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index bbb76cfbfaf..7c5582ba9bf 100644 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -66,6 +66,19 @@ fn main() { println!("{}", x); } + // #675, this used to have a wrong suggestion + loop { + //~^ERROR this loop could be written as a `while let` loop + //~|HELP try + //~|SUGGESTION while let Some(word) = "".split_whitespace().next() { .. } + let (e, l) = match "".split_whitespace().next() { + Some(word) => (word.is_empty(), word.len()), + None => break + }; + + let _ = (e, l); + } + let mut iter = 1..20; while let Option::Some(x) = iter.next() { //~ERROR this loop could be written as a `for` loop println!("{}", x); -- cgit 1.4.1-3-g733a5 From 76004306ccf3e3069bdf0928a70895916bea00ff Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 28 Feb 2016 00:46:02 +0100 Subject: Lint manual swaps --- README.md | 5 +- src/lib.rs | 3 +- src/swap.rs | 136 ++++++++++++++++++++++++++++++++++----------- tests/compile-fail/swap.rs | 29 +++++++++- 4 files changed, 137 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index f7527372585..f421cbdb7c9 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,12 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 126 lints included in this crate: +There are 127 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison involving a maximum or minimum value involves a case that is always true or always false +[almost_swapped](https://github.com/Manishearth/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` @@ -62,6 +63,7 @@ name [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[manual_swap](https://github.com/Manishearth/rust-clippy/wiki#manual_swap) | warn | manual swap [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) [map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead @@ -114,7 +116,6 @@ name [string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` -[suspicious_swap](https://github.com/Manishearth/rust-clippy/wiki#suspicious_swap) | warn | `foo = bar; bar = foo` sequence [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations diff --git a/src/lib.rs b/src/lib.rs index 217110e2bd8..5debe2ed50c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -287,7 +287,8 @@ pub fn plugin_registrar(reg: &mut Registry) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, - swap::SUSPICIOUS_SWAP, + swap::ALMOST_SWAPPED, + swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, diff --git a/src/swap.rs b/src/swap.rs index 8e1b1e781f4..6d7212233fb 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -1,7 +1,26 @@ use rustc::lint::*; use rustc_front::hir::*; -use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; use syntax::codemap::mk_sp; +use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; + +/// **What it does:** This lints manual swapping. +/// +/// **Why is this bad?** The `std::mem::swap` function exposes the intent better without +/// deinitializing or copying either variable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let t = b; +/// b = a; +/// a = t; +/// ``` +declare_lint! { + pub MANUAL_SWAP, + Warn, + "manual swap" +} /// **What it does:** This lints `foo = bar; bar = foo` sequences. /// @@ -15,7 +34,7 @@ use syntax::codemap::mk_sp; /// b = a; /// ``` declare_lint! { - pub SUSPICIOUS_SWAP, + pub ALMOST_SWAPPED, Warn, "`foo = bar; bar = foo` sequence" } @@ -25,42 +44,95 @@ pub struct Swap; impl LintPass for Swap { fn get_lints(&self) -> LintArray { - lint_array![SUSPICIOUS_SWAP] + lint_array![MANUAL_SWAP, ALMOST_SWAPPED] } } impl LateLintPass for Swap { fn check_block(&mut self, cx: &LateContext, block: &Block) { - for w in block.stmts.windows(2) { - if_let_chain!{[ - let StmtSemi(ref first, _) = w[0].node, - let StmtSemi(ref second, _) = w[1].node, - !differing_macro_contexts(first.span, second.span), - let ExprAssign(ref lhs0, ref rhs0) = first.node, - let ExprAssign(ref lhs1, ref rhs1) = second.node, - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) - ], { - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { - (format!(" `{}` and `{}`", first, second), first, second) - } else { - ("".to_owned(), "".to_owned(), "".to_owned()) - }; + check_manual_swap(cx, block); + check_suspicious_swap(cx, block); + } +} + +/// Implementation of the `MANUAL_SWAP` lint. +fn check_manual_swap(cx: &LateContext, block: &Block) { + for w in block.stmts.windows(3) { + if_let_chain!{[ + // let t = foo(); + let StmtDecl(ref tmp, _) = w[0].node, + let DeclLocal(ref tmp) = tmp.node, + let Some(ref tmp_init) = tmp.init, + let PatKind::Ident(_, ref tmp_name, None) = tmp.pat.node, + + // foo() = bar(); + let StmtSemi(ref first, _) = w[1].node, + let ExprAssign(ref lhs1, ref rhs1) = first.node, + + // bar() = t; + let StmtSemi(ref second, _) = w[2].node, + let ExprAssign(ref lhs2, ref rhs2) = second.node, + let ExprPath(None, ref rhs2) = rhs2.node, + rhs2.segments.len() == 1, + + tmp_name.node.name.as_str() == rhs2.segments[0].identifier.name.as_str(), + SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), + SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) + ], { + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { + (format!(" `{}` and `{}`", first, second), first, second) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; + + let span = mk_sp(tmp.span.lo, second.span.hi); + + span_lint_and_then(cx, + MANUAL_SWAP, + span, + &format!("this looks like you are swapping{} manually", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); + db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); + } + }); + }} + } +} + +/// Implementation of the `ALMOST_SWAPPED` lint. +fn check_suspicious_swap(cx: &LateContext, block: &Block) { + for w in block.stmts.windows(2) { + if_let_chain!{[ + let StmtSemi(ref first, _) = w[0].node, + let StmtSemi(ref second, _) = w[1].node, + !differing_macro_contexts(first.span, second.span), + let ExprAssign(ref lhs0, ref rhs0) = first.node, + let ExprAssign(ref lhs1, ref rhs1) = second.node, + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) + ], { + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { + (format!(" `{}` and `{}`", first, second), first, second) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; - let span = mk_sp(first.span.lo, second.span.hi); + let span = mk_sp(first.span.lo, second.span.hi); - span_lint_and_then(cx, - SUSPICIOUS_SWAP, - span, - &format!("this looks like you are trying to swap{}", what), - |db| { - if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap({}, {})", lhs, rhs)); - db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); - } - }); - }} - } + span_lint_and_then(cx, + ALMOST_SWAPPED, + span, + &format!("this looks like you are trying to swap{}", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); + db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); + } + }); + }} } } diff --git a/tests/compile-fail/swap.rs b/tests/compile-fail/swap.rs index be2c785eb41..cc0570e6c63 100755 --- a/tests/compile-fail/swap.rs +++ b/tests/compile-fail/swap.rs @@ -4,6 +4,8 @@ #![deny(clippy)] #![allow(unused_assignments)] +struct Foo(u32); + fn main() { let mut a = 42; let mut b = 1337; @@ -12,6 +14,31 @@ fn main() { b = a; //~^^ ERROR this looks like you are trying to swap `a` and `b` //~| HELP try - //~| SUGGESTION std::mem::swap(a, b); + //~| SUGGESTION std::mem::swap(&mut a, &mut b); + //~| NOTE or maybe you should use `std::mem::replace`? + + let t = a; + a = b; + b = t; + //~^^^ ERROR this looks like you are swapping `a` and `b` manually + //~| HELP try + //~| SUGGESTION std::mem::swap(&mut a, &mut b); + //~| NOTE or maybe you should use `std::mem::replace`? + + let mut c = Foo(42); + + c.0 = a; + a = c.0; + //~^^ ERROR this looks like you are trying to swap `c.0` and `a` + //~| HELP try + //~| SUGGESTION std::mem::swap(&mut c.0, &mut a); + //~| NOTE or maybe you should use `std::mem::replace`? + + let t = c.0; + c.0 = a; + a = t; + //~^^^ ERROR this looks like you are swapping `c.0` and `a` manually + //~| HELP try + //~| SUGGESTION std::mem::swap(&mut c.0, &mut a); //~| NOTE or maybe you should use `std::mem::replace`? } -- cgit 1.4.1-3-g733a5 From 67213c9be408fbfb8b1015d00b1b72a4f3742c75 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 29 Feb 2016 09:36:13 +0100 Subject: lint unportable clike enum discriminants --- README.md | 3 ++- src/enum_clike.rs | 56 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ tests/compile-fail/enums_clike.rs | 53 ++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/enum_clike.rs create mode 100644 tests/compile-fail/enums_clike.rs diff --git a/README.md b/README.md index f421cbdb7c9..d424aca9faa 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 127 lints included in this crate: +There are 128 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -38,6 +38,7 @@ name [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected +[enum_clike_unportable_variant](https://github.com/Manishearth/rust-clippy/wiki#enum_clike_unportable_variant) | warn | finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` [enum_glob_use](https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use) | allow | finds use items that import all variants of an enum [enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix [eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) diff --git a/src/enum_clike.rs b/src/enum_clike.rs new file mode 100644 index 00000000000..7ee71f41f29 --- /dev/null +++ b/src/enum_clike.rs @@ -0,0 +1,56 @@ +//! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` + +use rustc::lint::*; +use syntax::ast::{IntTy, UintTy}; +use syntax::attr::*; +use rustc_front::hir::*; +use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial}; +use rustc::middle::ty; +use utils::span_lint; + +/// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. +/// +/// **Why is this bad?** This will truncate the variant value on 32bit architectures, but works fine on 64 bit. +/// +/// **Known problems:** None +/// +/// **Example:** `#[repr(usize)] enum NonPortable { X = 0x1_0000_0000, Y = 0 }` +declare_lint! { + pub ENUM_CLIKE_UNPORTABLE_VARIANT, Warn, + "finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" +} + +pub struct EnumClikeUnportableVariant; + +impl LintPass for EnumClikeUnportableVariant { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) + } +} + +impl LateLintPass for EnumClikeUnportableVariant { + #[allow(cast_possible_truncation, cast_sign_loss)] + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemEnum(ref def, _) = item.node { + for var in &def.variants { + let variant = &var.node; + if let Some(ref disr) = variant.disr_expr { + let cv = eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None); + let bad = match (cv, &cx.tcx.expr_ty(&**disr).sty) { + (Ok(ConstVal::Int(i)), &ty::TyInt(IntTy::Is)) => i as i32 as i64 != i, + (Ok(ConstVal::Uint(i)), &ty::TyInt(IntTy::Is)) => i as i32 as u64 != i, + (Ok(ConstVal::Int(i)), &ty::TyUint(UintTy::Us)) => (i < 0) || (i as u32 as i64 != i), + (Ok(ConstVal::Uint(i)), &ty::TyUint(UintTy::Us)) => i as u32 as u64 != i, + _ => false, + }; + if bad { + span_lint(cx, + ENUM_CLIKE_UNPORTABLE_VARIANT, + var.span, + "Clike enum variant discriminant is not portable to 32-bit targets"); + } + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5debe2ed50c..50ea765f85d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ pub mod cyclomatic_complexity; pub mod derive; pub mod drop_ref; pub mod entry; +pub mod enum_clike; pub mod enum_glob_use; pub mod enum_variants; pub mod eq_op; @@ -108,6 +109,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box eq_op::EqOp); reg.register_early_lint_pass(box enum_variants::EnumVariantNames); reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); + reg.register_late_lint_pass(box enum_clike::EnumClikeUnportableVariant); reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); @@ -211,6 +213,7 @@ pub fn plugin_registrar(reg: &mut Registry) { derive::EXPL_IMPL_CLONE_ON_COPY, drop_ref::DROP_REF, entry::MAP_ENTRY, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES, eq_op::EQ_OP, escape::BOXED_LOCAL, diff --git a/tests/compile-fail/enums_clike.rs b/tests/compile-fail/enums_clike.rs new file mode 100644 index 00000000000..f48f9b13de4 --- /dev/null +++ b/tests/compile-fail/enums_clike.rs @@ -0,0 +1,53 @@ +#![feature(plugin, associated_consts)] +#![plugin(clippy)] +#![deny(clippy)] + +#![allow(unused)] + +#[repr(usize)] +enum NonPortable { + X = 0x1_0000_0000, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets + Y = 0, + Z = 0x7FFF_FFFF, + A = 0xFFFF_FFFF, +} + +enum NonPortableNoHint { + X = 0x1_0000_0000, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets + Y = 0, + Z = 0x7FFF_FFFF, + A = 0xFFFF_FFFF, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets +} + +#[repr(isize)] +enum NonPortableSigned { + X = -1, + Y = 0x7FFF_FFFF, + Z = 0xFFFF_FFFF, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets + A = 0x1_0000_0000, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets + B = std::i32::MIN as isize, + C = (std::i32::MIN as isize) - 1, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets +} + +enum NonPortableSignedNoHint { + X = -1, + Y = 0x7FFF_FFFF, + Z = 0xFFFF_FFFF, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets + A = 0x1_0000_0000, //~ ERROR: Clike enum variant discriminant is not portable to 32-bit targets +} + +/* +FIXME: uncomment once https://github.com/rust-lang/rust/issues/31910 is fixed +#[repr(usize)] +enum NonPortable2<T: Trait> { + X = Trait::Number, + Y = 0, +} + +trait Trait { + const Number: usize = 0x1_0000_0000; +} +*/ + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 3b7720f992a5bc03027e64450ba51a58a5a971ae Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 29 Feb 2016 09:45:36 +0100 Subject: lint ! and != in if expressions with else branches --- README.md | 3 ++- src/block_in_if_condition.rs | 6 ++--- src/consts.rs | 6 ++--- src/enum_variants.rs | 10 +++----- src/if_not_else.rs | 53 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ src/loops.rs | 6 ++--- src/matches.rs | 22 ++++++++-------- tests/compile-fail/entry.rs | 2 +- tests/compile-fail/if_not_else.rs | 18 +++++++++++++ 10 files changed, 100 insertions(+), 29 deletions(-) create mode 100644 src/if_not_else.rs create mode 100644 tests/compile-fail/if_not_else.rs diff --git a/README.md b/README.md index d424aca9faa..3a957a7e4c9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 128 lints included in this crate: +There are 129 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -52,6 +52,7 @@ name [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | warn | finds if branches that could be swapped so no negation operation is necessary on the condition [if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks [ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 6db77a5ce93..7004910dfc7 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -45,9 +45,7 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { fn visit_expr(&mut self, expr: &'v Expr) { if let ExprClosure(_, _, ref block) = expr.node { let complex = { - if !block.stmts.is_empty() { - true - } else { + if block.stmts.is_empty() { if let Some(ref ex) = block.expr { match ex.node { ExprBlock(_) => true, @@ -56,6 +54,8 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { } else { false } + } else { + true } }; if complex { diff --git a/src/consts.rs b/src/consts.rs index 64f45d72c12..6dd5651e7ef 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -159,10 +159,10 @@ impl PartialOrd for Constant { fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => { - if lsty != rsty { - None - } else { + if lsty == rsty { Some(ls.cmp(rs)) + } else { + None } } (&Constant::Byte(ref l), &Constant::Byte(ref r)) => Some(l.cmp(r)), diff --git a/src/enum_variants.rs b/src/enum_variants.rs index a95fca8c6c4..179ce24cfa7 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -89,12 +89,10 @@ impl EarlyLintPass for EnumVariantNames { let post_camel = camel_case_from(&post); post = &post[post_camel..]; } - let (what, value) = if !pre.is_empty() { - ("pre", pre) - } else if !post.is_empty() { - ("post", post) - } else { - return; + let (what, value) = match (pre.is_empty(), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre), + (true, false) => ("post", post), }; span_help_and_lint(cx, ENUM_VARIANT_NAMES, diff --git a/src/if_not_else.rs b/src/if_not_else.rs new file mode 100644 index 00000000000..1a074a723a9 --- /dev/null +++ b/src/if_not_else.rs @@ -0,0 +1,53 @@ +//! lint on if branches that could be swapped so no `!` operation is necessary on the condition + +use rustc::lint::*; +use syntax::attr::*; +use syntax::ast::*; + +use utils::span_help_and_lint; + +/// **What it does:** Warns on the use of `!` or `!=` in an if condition with an else branch +/// +/// **Why is this bad?** Negations reduce the readability of statements +/// +/// **Known problems:** None +/// +/// **Example:** if !v.is_empty() { a() } else { b() } +declare_lint! { + pub IF_NOT_ELSE, Warn, + "finds if branches that could be swapped so no negation operation is necessary on the condition" +} + +pub struct IfNotElse; + +impl LintPass for IfNotElse { + fn get_lints(&self) -> LintArray { + lint_array!(IF_NOT_ELSE) + } +} + +impl EarlyLintPass for IfNotElse { + fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + if let ExprKind::If(ref cond, _, Some(ref els)) = item.node { + if let ExprKind::Block(..) = els.node { + match cond.node { + ExprKind::Unary(UnOp::Not, _) => { + span_help_and_lint(cx, + IF_NOT_ELSE, + item.span, + "Unnecessary boolean `not` operation", + "remove the `!` and swap the blocks of the if/else"); + }, + ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { + span_help_and_lint(cx, + IF_NOT_ELSE, + item.span, + "Unnecessary `!=` operation", + "change to `==` and swap the blocks of the if/else"); + }, + _ => {}, + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 50ea765f85d..7436dada020 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,7 @@ pub mod eta_reduction; pub mod format; pub mod formatting; pub mod identity_op; +pub mod if_not_else; pub mod items_after_statements; pub mod len_zero; pub mod lifetimes; @@ -171,6 +172,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box format::FormatMacLint); reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); + reg.register_early_lint_pass(box if_not_else::IfNotElse); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -222,6 +224,7 @@ pub fn plugin_registrar(reg: &mut Registry) { formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, identity_op::IDENTITY_OP, + if_not_else::IF_NOT_ELSE, items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, diff --git a/src/loops.rs b/src/loops.rs index e6b28d20e83..5e862382742 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -357,10 +357,10 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex }; let take: Cow<_> = if let Some(ref r) = *r { - if !is_len_call(&r, &indexed) { - format!(".take({})", snippet(cx, r.span, "..")).into() - } else { + if is_len_call(&r, &indexed) { "".into() + } else { + format!(".take({})", snippet(cx, r.span, "..")).into() } } else { "".into() diff --git a/src/matches.rs b/src/matches.rs index 35c0dbb3950..d832888606a 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -249,23 +249,21 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { }; if let Some((ref true_expr, ref false_expr)) = exprs { - if !is_unit_expr(true_expr) { - if !is_unit_expr(false_expr) { + match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { + (false, false) => Some(format!("if {} {} else {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))) - } else { + expr_block(cx, false_expr, None, ".."))), + (false, true) => Some(format!("if {} {}", snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."))) - } - } else if !is_unit_expr(false_expr) { - Some(format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))) - } else { - None + expr_block(cx, true_expr, None, ".."))), + (true, false) => + Some(format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))), + (true, true) => None, } } else { None diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs index 7dc4054ec5b..e65ef503ba5 100644 --- a/tests/compile-fail/entry.rs +++ b/tests/compile-fail/entry.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused)] +#![allow(unused, if_not_else)] #![deny(map_entry)] diff --git a/tests/compile-fail/if_not_else.rs b/tests/compile-fail/if_not_else.rs new file mode 100644 index 00000000000..eb716e4599a --- /dev/null +++ b/tests/compile-fail/if_not_else.rs @@ -0,0 +1,18 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy)] + +fn bla() -> bool { unimplemented!() } + +fn main() { + if !bla() { //~ ERROR: Unnecessary boolean `not` operation + println!("Bugs"); + } else { + println!("Bunny"); + } + if 4 != 5 { //~ ERROR: Unnecessary `!=` operation + println!("Bugs"); + } else { + println!("Bunny"); + } +} -- cgit 1.4.1-3-g733a5 From bd45cfd2739babc9350760cc4b5989a729fe447e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 29 Feb 2016 16:49:32 +0530 Subject: rustfmt --- src/block_in_if_condition.rs | 3 +- src/collapsible_if.rs | 10 ++-- src/copies.rs | 4 +- src/derive.rs | 12 +---- src/entry.rs | 2 +- src/enum_variants.rs | 24 ++++----- src/formatting.rs | 24 ++++----- src/len_zero.rs | 16 ++---- src/loops.rs | 27 +++++----- src/map_clone.rs | 6 +-- src/matches.rs | 39 +++++++------- src/methods.rs | 9 ++-- src/print.rs | 11 ++-- src/regex.rs | 6 ++- src/strings.rs | 2 +- src/types.rs | 10 ++-- src/utils/hir.rs | 125 +++++++++++++------------------------------ src/utils/mod.rs | 12 ++--- 18 files changed, 138 insertions(+), 204 deletions(-) diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 7004910dfc7..9cb11968abc 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -92,8 +92,7 @@ impl LateLintPass for BlockInIfCondition { snippet_block(cx, then.span, ".."))); } } else { - let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, - |e| e.span); + let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); if in_macro(cx, span) || differing_macro_contexts(expr.span, span) { return; } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 663d39cdbb2..74397304eda 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -71,15 +71,13 @@ fn check_if(cx: &LateContext, e: &Expr) { }); }} } else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = - single_stmt_of_block(then) { + single_stmt_of_block(then) { if e.span.expn_id != sp.expn_id { return; } - span_lint_and_then(cx, - COLLAPSIBLE_IF, - e.span, - "this if statement can be collapsed", |db| { - db.span_suggestion(e.span, "try", + span_lint_and_then(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", |db| { + db.span_suggestion(e.span, + "try", format!("if {} && {} {}", check_to_string(cx, check), check_to_string(cx, check_inner), diff --git a/src/copies.rs b/src/copies.rs index 1995e2901ad..691acad6e92 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -91,9 +91,7 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { h.finish() }; - let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { - SpanlessEq::new(cx).eq_block(lhs, rhs) - }; + let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same(blocks, hash, eq) { span_note_and_lint(cx, diff --git a/src/derive.rs b/src/derive.rs index 084d00d409f..8bdcb4b0167 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -87,13 +87,7 @@ impl LateLintPass for Derive { } /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq( - cx: &LateContext, - span: Span, - trait_ref: &TraitRef, - ty: ty::Ty, - hash_is_automatically_derived: bool -) { +fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty, hash_is_automatically_derived: bool) { if_let_chain! {[ match_path(&trait_ref.path, &HASH_PATH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() @@ -143,9 +137,7 @@ fn check_hash_peq( } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, - item: &Item, - trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) { let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); let subst_ty = ty.subst(cx.tcx, ¶meter_environment.free_substs); diff --git a/src/entry.rs b/src/entry.rs index 6242b44dd6e..8a4cf37c0ac 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -48,7 +48,7 @@ impl LateLintPass for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = else_block.is_none() && - if then_block.expr.is_some() { 1 } else { 0 } + then_block.stmts.len() == 1; + ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); let mut visitor = InsertVisitor { cx: cx, diff --git a/src/enum_variants.rs b/src/enum_variants.rs index 179ce24cfa7..d7bd4742ebb 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -31,17 +31,16 @@ fn var2str(var: &Variant) -> InternedString { var.node.name.name.as_str() } -/* -FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 -fn partial_match(pre: &str, name: &str) -> usize { - // skip(1) to ensure that the prefix never takes the whole variant name - pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() -} - -fn partial_rmatch(post: &str, name: &str) -> usize { - // skip(1) to ensure that the postfix never takes the whole variant name - post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() -}*/ +// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 +// fn partial_match(pre: &str, name: &str) -> usize { +// // skip(1) to ensure that the prefix never takes the whole variant name +// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() +// } +// +// fn partial_rmatch(post: &str, name: &str) -> usize { +// // skip(1) to ensure that the postfix never takes the whole variant name +// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() +// } fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); @@ -99,7 +98,8 @@ impl EarlyLintPass for EnumVariantNames { item.span, &format!("All variants have the same {}fix: `{}`", what, value), &format!("remove the {}fixes and use full paths to \ - the variants instead of glob imports", what)); + the variants instead of glob imports", + what)); } } } diff --git a/src/formatting.rs b/src/formatting.rs index efcb222ebed..091280de28d 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -96,9 +96,11 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { span_note_and_lint(cx, SUSPICIOUS_ASSIGNMENT_FORMATTING, eqop_span, - &format!("this looks like you are trying to use `.. {op}= ..`, but you really are doing `.. = ({op} ..)`", op=op), + &format!("this looks like you are trying to use `.. {op}= ..`, but you \ + really are doing `.. = ({op} ..)`", + op = op), eqop_span, - &format!("to remove this lint, use either `{op}=` or `= {op}`", op=op)); + &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op)); } } } @@ -109,9 +111,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { /// Implementation of the SUSPICIOUS_ELSE_FORMATTING lint for weird `else if`. fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { - if unsugar_if(else_).is_some() && - !differing_macro_contexts(then.span, else_.span) && - !in_macro(cx, then.span) { + if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) { // this will be a span from the closing ‘}’ of the “then” block (excluding) to the // “if” of the “else if” block (excluding) let else_span = mk_sp(then.span.hi, else_.span.lo); @@ -127,7 +127,8 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { else_span, "this is an `else if` but the formatting might hide it", else_span, - "to remove this lint, remove the `else` or remove the new line between `else` and `if`"); + "to remove this lint, remove the `else` or remove the new line between `else` \ + and `if`"); } } } @@ -136,10 +137,8 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { - if !differing_macro_contexts(first.span, second.span) && - !in_macro(cx, first.span) && - unsugar_if(first).is_some() && - unsugar_if(second).is_some() { + if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) && + unsugar_if(first).is_some() && unsugar_if(second).is_some() { // where the else would be let else_span = mk_sp(first.span.hi, second.span.lo); @@ -150,14 +149,15 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp else_span, "this looks like an `else if` but the `else` is missing", else_span, - "to remove this lint, add the missing `else` or add a new line before the second `if`"); + "to remove this lint, add the missing `else` or add a new line before the second \ + `if`"); } } } } /// Match `if` or `else if` expressions and return the `then` and `else` block. -fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)>{ +fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> { match expr.node { ast::ExprKind::If(_, ref then, ref else_) | ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), diff --git a/src/len_zero.rs b/src/len_zero.rs index adf42b43383..548a3d92c2c 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -155,17 +155,11 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { if let Spanned{node: LitKind::Int(0, _), ..} = *lit { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { - span_lint_and_then(cx, - LEN_ZERO, - span, - "length comparison to zero", - |db| { - db.span_suggestion(span, - "consider using `is_empty`", - format!("{}{}.is_empty()", - op, - snippet(cx, args[0].span, "_"))); - }); + span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| { + db.span_suggestion(span, + "consider using `is_empty`", + format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_"))); + }); } } } diff --git a/src/loops.rs b/src/loops.rs index 5e862382742..600f22ea001 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -370,14 +370,14 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex span_lint(cx, NEEDLESS_RANGE_LOOP, expr.span, - &format!("the loop variable `{}` is used to index `{}`. \ - Consider using `for ({}, item) in {}.iter().enumerate(){}{}` or similar iterators", - ident.node.name, - indexed, - ident.node.name, - indexed, - take, - skip)); + &format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \ + item) in {}.iter().enumerate(){}{}` or similar iterators", + ident.node.name, + indexed, + ident.node.name, + indexed, + take, + skip)); } else { let repl = if starts_at_zero && take.is_empty() { format!("&{}", indexed) @@ -390,9 +390,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex expr.span, &format!("the loop variable `{}` is only used to index `{}`. \ Consider using `for item in {}` or similar iterators", - ident.node.name, - indexed, - repl)); + ident.node.name, + indexed, + repl)); } } } @@ -447,9 +447,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { "consider using the following if \ you are attempting to iterate \ over this range in reverse", - format!("({}..{}).rev()` ", - stop_snippet, - start_snippet)); + format!("({}..{}).rev()` ", stop_snippet, start_snippet)); }); } else if eq { // if they are equal, it's also problematic - this loop @@ -744,6 +742,7 @@ impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. +#[cfg_attr(rustfmt, rustfmt_skip)] fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards diff --git a/src/map_clone.rs b/src/map_clone.rs index 8a4e1d770dc..4eac4dc6113 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,10 +1,8 @@ use rustc::lint::*; use rustc_front::hir::*; use utils::{CLONE_PATH, OPTION_PATH}; -use utils::{ - is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, - walk_ptrs_ty, walk_ptrs_ty_depth -}; +use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, walk_ptrs_ty, + walk_ptrs_ty_depth}; /// **What it does:** This lint checks for mapping clone() over an iterator. /// diff --git a/src/matches.rs b/src/matches.rs index d832888606a..1b05162c86a 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -134,10 +134,11 @@ impl LateLintPass for MatchPass { } } +#[cfg_attr(rustfmt, rustfmt_skip)] fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() { + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() { let els = if is_unit_expr(&arms[1].body) { None } else if let ExprBlock(_) = arms[1].body.node { @@ -167,28 +168,28 @@ fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], lint, expr.span, "you seem to be trying to use match for destructuring a single pattern. \ - Consider using `if let`", |db| { - db.span_suggestion(expr.span, "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); + Consider using `if let`", + |db| { + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); } } fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) { // list of candidate Enums we know will never get any more members - let candidates = &[ - (&COW_PATH, "Borrowed"), - (&COW_PATH, "Cow::Borrowed"), - (&COW_PATH, "Cow::Owned"), - (&COW_PATH, "Owned"), - (&OPTION_PATH, "None"), - (&RESULT_PATH, "Err"), - (&RESULT_PATH, "Ok"), - ]; + let candidates = &[(&COW_PATH, "Borrowed"), + (&COW_PATH, "Cow::Borrowed"), + (&COW_PATH, "Cow::Owned"), + (&COW_PATH, "Owned"), + (&OPTION_PATH, "None"), + (&RESULT_PATH, "Err"), + (&RESULT_PATH, "Ok")]; let path = match arms[1].pats[0].node { PatKind::TupleStruct(ref path, Some(ref inner)) => { diff --git a/src/methods.rs b/src/methods.rs index 6ef779cd79e..94548cf9672 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -565,7 +565,9 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr) { let ty = cx.tcx.expr_ty(arg); if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { if let ty::TyRef(..) = inner.sty { - let mut db = span_lint(cx, CLONE_DOUBLE_REF, expr.span, + let mut db = span_lint(cx, + CLONE_DOUBLE_REF, + expr.span, "using `clone` on a double-reference; \ this will copy the reference instead of cloning \ the inner type"); @@ -583,10 +585,7 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } let arg_ty = cx.tcx.expr_ty(&args[1]); if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { - span_lint(cx, - EXTEND_FROM_SLICE, - expr.span, - "use of `extend` to extend a Vec by a slice") + span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice") .span_suggestion(expr.span, "try this", format!("{}.extend_from_slice({}{})", diff --git a/src/print.rs b/src/print.rs index d7d83bfb437..ffe20d13cea 100644 --- a/src/print.rs +++ b/src/print.rs @@ -60,9 +60,8 @@ impl LateLintPass for PrintLint { // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` else if args.len() == 2 && match_path(path, &FMT_ARGUMENTV1_NEW_PATH) { if let ExprPath(None, ref path) = args[1].node { - if match_path(path, &DEBUG_FMT_METHOD_PATH) && - !is_in_debug_impl(cx, expr) && - is_expn_of(cx, expr.span, "panic").is_none() { + if match_path(path, &DEBUG_FMT_METHOD_PATH) && !is_in_debug_impl(cx, expr) && + is_expn_of(cx, expr.span, "panic").is_none() { span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); } } @@ -75,8 +74,10 @@ impl LateLintPass for PrintLint { fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { let map = &cx.tcx.map; - if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { // `fmt` method - if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { // `Debug` impl + // `fmt` method + if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { + // `Debug` impl + if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node { return match_path(&tr.path, &["Debug"]); } diff --git a/src/regex.rs b/src/regex.rs index f58b6319d57..e8a71a2cb5a 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -147,7 +147,11 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { Some((b, _)) => base.lo + BytePos(b as u32), _ => base.hi, }; - Span{ lo: lo, hi: lo, ..base } + Span { + lo: lo, + hi: lo, + ..base + } } fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { diff --git a/src/strings.rs b/src/strings.rs index fdba6302a46..f4318fc261a 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -144,7 +144,7 @@ impl LateLintPass for StringLitAsBytes { let msg = format!("calling `as_bytes()` on a string literal. \ Consider using a byte string literal instead: \ `b{}`", - snippet(cx, args[0].span, r#""foo""#)); + snippet(cx, args[0].span, r#""foo""#)); span_lint(cx, STRING_LIT_AS_BYTES, e.span, &msg); } } diff --git a/src/types.rs b/src/types.rs index 248aab32baa..27c67e78e03 100644 --- a/src/types.rs +++ b/src/types.rs @@ -390,7 +390,8 @@ impl LateLintPass for CastPass { check_truncation_and_wrapping(cx, expr, cast_from, cast_to); } (false, false) => { - if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { + if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, + &cast_to.sty) { span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, @@ -570,7 +571,7 @@ impl LateLintPass for CharLitAsU8 { truncates them"; let help = format!("Consider using a byte literal \ instead:\nb{}", - snippet(cx, e.span, "'x'")); + snippet(cx, e.span, "'x'")); span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help); } } @@ -623,7 +624,10 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs type Extr<'a> = ExtremeExpr<'a>; // Put the expression in the form lhs < rhs or lhs <= rhs. - enum Rel { Lt, Le }; + enum Rel { + Lt, + Le, + }; let (rel, lhs2, rhs2) = match op { BiLt => (Rel::Lt, lhs, rhs), BiLe => (Rel::Le, lhs, rhs), diff --git a/src/utils/hir.rs b/src/utils/hir.rs index faa2082b7d0..6231970a0cc 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -38,10 +38,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { // TODO: tys - l.ty.is_none() && r.ty.is_none() && - both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) - } - else { + l.ty.is_none() && r.ty.is_none() && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + } else { false } } @@ -71,15 +69,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } match (&left.node, &right.node) { - (&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => { - lmut == rmut && self.eq_expr(le, re) - } - (&ExprAgain(li), &ExprAgain(ri)) => { - both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) - } - (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => { - self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - } + (&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => lmut == rmut && self.eq_expr(le, re), + (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), + (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } @@ -87,79 +79,50 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } - (&ExprBreak(li), &ExprBreak(ri)) => { - both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()) - } - (&ExprBox(ref l), &ExprBox(ref r)) => { - self.eq_expr(l, r) - } + (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), + (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { - !self.ignore_fn && - self.eq_expr(lfun, rfun) && - self.eq_exprs(largs, rargs) - } - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => { - self.eq_expr(lx, rx) && self.eq_ty(lt, rt) + !self.ignore_fn && self.eq_expr(lfun, rfun) && self.eq_exprs(largs, rargs) } + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { lfident.node == rfident.node && self.eq_expr(lfexp, rfexp) } - (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => { - self.eq_expr(la, ra) && self.eq_expr(li, ri) - } + (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { - self.eq_expr(lc, rc) && - self.eq_block(lt, rt) && - both(le, re, |l, r| self.eq_expr(l, r)) + self.eq_expr(lc, rc) && self.eq_block(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r)) } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { - self.eq_block(lb, rb) && - both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) - + self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) } (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { - ls == rs && - self.eq_expr(le, re) && - over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && - both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) - } - (&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { + ls == rs && self.eq_expr(le, re) && + over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) + } + (&ExprMethodCall(ref lname, ref ltys, ref largs), + &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { // TODO: tys - !self.ignore_fn && - lname.node == rname.node && - ltys.is_empty() && - rtys.is_empty() && - self.eq_exprs(largs, rargs) + !self.ignore_fn && lname.node == rname.node && ltys.is_empty() && rtys.is_empty() && + self.eq_exprs(largs, rargs) } (&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => { - both(lb, rb, |l, r| self.eq_expr(l, r)) && - both(le, re, |l, r| self.eq_expr(l, r)) - } - (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => { - self.eq_expr(le, re) && self.eq_expr(ll, rl) - } - (&ExprRet(ref l), &ExprRet(ref r)) => { - both(l, r, |l, r| self.eq_expr(l, r)) + both(lb, rb, |l, r| self.eq_expr(l, r)) && both(le, re, |l, r| self.eq_expr(l, r)) } + (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), + (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { both(lqself, rqself, |l, r| self.eq_qself(l, r)) && self.eq_path(lsubpath, rsubpath) } (&ExprTup(ref ltup), &ExprTup(ref rtup)) => self.eq_exprs(ltup, rtup), - (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => { - li.node == ri.node && self.eq_expr(le, re) - } - (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => { - lop == rop && self.eq_expr(le, re) - } + (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), + (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => lop == rop && self.eq_expr(le, re), (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && - self.eq_block(lb, rb) && - both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) } _ => false, } @@ -172,39 +135,25 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two patterns are the same. pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { match (&left.node, &right.node) { - (&PatKind::Box(ref l), &PatKind::Box(ref r)) => { - self.eq_pat(l, r) - } + (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), (&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => { - self.eq_path(lp, rp) && - both(la, ra, |l, r| { - over(l, r, |l, r| self.eq_pat(l, r)) - }) + self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r))) } (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { - lb == rb && li.node.name.as_str() == ri.node.name.as_str() && - both(lp, rp, |l, r| self.eq_pat(l, r)) - } - (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => { - self.eq_expr(l, r) + lb == rb && li.node.name.as_str() == ri.node.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } + (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { self.eq_qself(ls, rs) && self.eq_path(lp, rp) } - (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => { - over(l, r, |l, r| self.eq_pat(l, r)) - } + (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => over(l, r, |l, r| self.eq_pat(l, r)), (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { - self.eq_expr(ls, rs) && - self.eq_expr(le, re) - } - (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => { - lm == rm && self.eq_pat(le, re) + self.eq_expr(ls, rs) && self.eq_expr(le, re) } + (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), (&PatKind::Vec(ref ls, ref li, ref le), &PatKind::Vec(ref rs, ref ri, ref re)) => { - over(ls, rs, |l, r| self.eq_pat(l, r)) && - over(le, re, |l, r| self.eq_pat(l, r)) && - both(li, ri, |l, r| self.eq_pat(l, r)) + over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && + both(li, ri, |l, r| self.eq_pat(l, r)) } (&PatKind::Wild, &PatKind::Wild) => true, _ => false, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index a8708eb8f7f..f2b0c1f4db1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -137,8 +137,7 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { iter.inspect(|_| len += 1) .zip(path) - .all(|(nm, p)| nm.name().as_str() == *p) - && len == path.len() + .all(|(nm, p)| nm.name().as_str() == *p) && len == path.len() }) } @@ -600,11 +599,10 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' /// Return the pre-expansion span if is this comes from an expansion of the macro `name`. pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { loop { - let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| { - expn.map(|ei| { - (ei.callee.name(), ei.call_site) - }) - }); + let span_name_span = cx.tcx + .sess + .codemap() + .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); match span_name_span { Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), -- cgit 1.4.1-3-g733a5 From 100ca337421f57c4db57d5e3270c0ce1dbe86765 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 3 Mar 2016 01:24:20 +0530 Subject: Rust upgrade to 2016-03-02 nightly --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 27c67e78e03..cf90155b1fa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -432,7 +432,7 @@ impl LateLintPass for TypeComplexityPass { fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { // enum variants are also struct fields now - check_type(cx, &field.node.ty); + check_type(cx, &field.ty); } fn check_item(&mut self, cx: &LateContext, item: &Item) { -- cgit 1.4.1-3-g733a5 From 414396ab6583fe45995651f29e1effce5d508bb0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 3 Mar 2016 01:24:51 +0530 Subject: Bump to 0.0.45 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d4134461685..71d6d2864f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.44" +version = "0.0.45" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 79b0ad7441970dee66ebbdec9271ed8a6ea07944 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 3 Mar 2016 20:09:31 +0100 Subject: `vec!` now uses `box` --- src/vec.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/vec.rs b/src/vec.rs index fe3c1f90199..dda552bc8f9 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -3,7 +3,7 @@ use rustc::middle::ty::TypeVariants; use rustc_front::hir::*; use syntax::codemap::Span; use syntax::ptr::P; -use utils::{BOX_NEW_PATH, VEC_FROM_ELEM_PATH}; +use utils::VEC_FROM_ELEM_PATH; use utils::{is_expn_of, match_path, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. @@ -33,9 +33,7 @@ impl LintPass for UselessVec { impl LateLintPass for UselessVec { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - unexpand_vec(cx, expr); - - // search for `&!vec[_]` expressions where the adjusted type is `&[_]` + // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_let_chain!{[ let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, let TypeVariants::TySlice(..) = ty.ty.sty, @@ -71,7 +69,7 @@ impl LateLintPass for UselessVec { /// Represent the pre-expansion arguments of a `vec!` invocation. pub enum VecArgs<'a> { - /// `vec![elem, len]` + /// `vec![elem; len]` Repeat(&'a P<Expr>, &'a P<Expr>), /// `vec![a, b, c]` Vec(&'a [P<Expr>]), @@ -91,10 +89,8 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> else if match_path(path, &["into_vec"]) && args.len() == 1 { // `vec![a, b, c]` case if_let_chain!{[ - let ExprCall(ref fun, ref args) = args[0].node, - let ExprPath(_, ref path) = fun.node, - match_path(path, &BOX_NEW_PATH) && args.len() == 1, - let ExprVec(ref args) = args[0].node + let ExprBox(ref boxed) = args[0].node, + let ExprVec(ref args) = boxed.node ], { return Some(VecArgs::Vec(&*args)); }} -- cgit 1.4.1-3-g733a5 From c7bf0681210bdf2e504f08967568fc7d807afea1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 4 Mar 2016 14:25:34 +0100 Subject: s/ctxt/TyCtxt --- src/cyclomatic_complexity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 3f956f1fc41..7034f87f59f 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -116,7 +116,7 @@ impl<'a> Visitor<'a> for MatchArmCounter { } } -struct DivergenceCounter<'a, 'tcx: 'a>(u64, &'a ty::ctxt<'tcx>); +struct DivergenceCounter<'a, 'tcx: 'a>(u64, &'a ty::TyCtxt<'tcx>); impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> { fn visit_expr(&mut self, e: &'a Expr) { -- cgit 1.4.1-3-g733a5 From 026d443e1e091aee21b6f5fd4cfb13058427039a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 4 Mar 2016 14:25:53 +0100 Subject: Bump to 0.0.46 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 71d6d2864f2..bee10dccd6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.45" +version = "0.0.46" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From e7fa117ff8d9c9f6b82aa94dcfbef3ac05cbe68a Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 4 Mar 2016 16:27:03 +0100 Subject: simplify cyclomatic complexity auxiliarly value computation previously the HIR was unnecessarily traversed twice --- src/cyclomatic_complexity.rs | 51 +++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 7034f87f59f..05f633ee0e4 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -48,18 +48,22 @@ impl CyclomaticComplexity { let n = cfg.graph.len_nodes() as u64; let e = cfg.graph.len_edges() as u64; let cc = e + 2 - n; - let mut arm_counter = MatchArmCounter(0); - arm_counter.visit_block(block); - let narms = arm_counter.0; - - let mut diverge_counter = DivergenceCounter(0, &cx.tcx); - diverge_counter.visit_block(block); - let divergence = diverge_counter.0; - - if cc + divergence < narms { - report_cc_bug(cx, cc, narms, divergence, span); + let mut helper = CCHelper { + match_arms: 0, + divergence: 0, + tcx: &cx.tcx, + }; + helper.visit_block(block); + let CCHelper { + match_arms, + divergence, + .. + } = helper; + + if cc + divergence < match_arms { + report_cc_bug(cx, cc, match_arms, divergence, span); } else { - let rust_cc = cc + divergence - narms; + let rust_cc = cc + divergence - match_arms; if rust_cc > self.limit.limit() { span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, @@ -98,35 +102,28 @@ impl LateLintPass for CyclomaticComplexity { } } -struct MatchArmCounter(u64); +struct CCHelper<'a, 'tcx: 'a> { + match_arms: u64, + divergence: u64, + tcx: &'a ty::TyCtxt<'tcx>, +} -impl<'a> Visitor<'a> for MatchArmCounter { +impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { fn visit_expr(&mut self, e: &'a Expr) { match e.node { ExprMatch(_, ref arms, _) => { walk_expr(self, e); let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); if arms_n > 1 { - self.0 += arms_n - 2; + self.match_arms += arms_n - 2; } } - ExprClosure(..) => {} - _ => walk_expr(self, e), - } - } -} - -struct DivergenceCounter<'a, 'tcx: 'a>(u64, &'a ty::TyCtxt<'tcx>); - -impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> { - fn visit_expr(&mut self, e: &'a Expr) { - match e.node { ExprCall(ref callee, _) => { walk_expr(self, e); - let ty = self.1.node_id_to_type(callee.id); + let ty = self.tcx.node_id_to_type(callee.id); if let ty::TyBareFn(_, ty) = ty.sty { if ty.sig.skip_binder().output.diverges() { - self.0 += 1; + self.divergence += 1; } } } -- cgit 1.4.1-3-g733a5 From e421a0f8a3aa8a28ef06d5b8892c5c32e7d39f89 Mon Sep 17 00:00:00 2001 From: KALPESH KRISHNA <kalpeshk2011@gmail.com> Date: Fri, 4 Mar 2016 00:44:49 +0530 Subject: Warn about calling a closure in the same expression where it's defined. --- README.md | 3 +- src/lib.rs | 1 + src/misc_early.rs | 58 ++++++++++++++++++++++++++-- tests/compile-fail/eta.rs | 2 +- tests/compile-fail/redundant_closure_call.rs | 25 ++++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 tests/compile-fail/redundant_closure_call.rs diff --git a/README.md b/README.md index 3a957a7e4c9..ff875085da2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 129 lints included in this crate: +There are 130 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -99,6 +99,7 @@ name [range_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero) | warn | using Range::step_by(0), which produces an infinite iterator [range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when enumerate() would do [redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_closure_call](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call) | warn | Closures should not be called in the expression they are defined [redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern [regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | warn | finds use of `regex!(_)`, suggests `Regex::new(_)` instead [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled diff --git a/src/lib.rs b/src/lib.rs index 7436dada020..803a4c2345c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -272,6 +272,7 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::TOPLEVEL_REF_ARG, misc::USED_UNDERSCORE_BINDING, misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, + misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, mutex_atomic::MUTEX_ATOMIC, diff --git a/src/misc_early.rs b/src/misc_early.rs index 604e6002103..89a0763e2e3 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -3,8 +3,7 @@ use std::collections::HashMap; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{span_lint, span_help_and_lint}; - +use utils::{span_lint, span_help_and_lint, snippet, span_lint_and_then}; /// **What it does:** This lint checks for structure field patterns bound to wildcards. /// /// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound. @@ -29,12 +28,24 @@ declare_lint! { "Function arguments having names which only differ by an underscore" } +/// **What it does:** This lint detects closures called in the same expression where they are defined. +/// +/// **Why is this bad?** It is unnecessarily adding to the expression's complexity. +/// +/// **Known problems:** None. +/// +/// **Example:** `(|| 42)()` +declare_lint! { + pub REDUNDANT_CLOSURE_CALL, Warn, + "Closures should not be called in the expression they are defined" +} + #[derive(Copy, Clone)] pub struct MiscEarly; impl LintPass for MiscEarly { fn get_lints(&self) -> LintArray { - lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT) + lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL) } } @@ -105,7 +116,7 @@ impl EarlyLintPass for MiscEarly { *correspondance, &format!("`{}` already exists, having another argument having almost the same \ name makes code comprehension and documentation more difficult", - arg_name[1..].to_owned())); + arg_name[1..].to_owned()));; } } else { registered_names.insert(arg_name, arg.pat.span); @@ -113,4 +124,43 @@ impl EarlyLintPass for MiscEarly { } } } + + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if let ExprKind::Call(ref paren, _) = expr.node { + if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, ref decl, ref block) = closure.node { + span_lint_and_then(cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |db| { + if decl.inputs.len() == 0 { + let hint = format!("{}", snippet(cx, block.span, "..")); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + } + }); + } + } + } + } + + fn check_block(&mut self, cx: &EarlyContext, block: &Block) { + for w in block.stmts.windows(2) { + if_let_chain! {[ + let StmtKind::Decl(ref first, _) = w[0].node, + let DeclKind::Local(ref local) = first.node, + let Option::Some(ref t) = local.init, + let ExprKind::Closure(_,_,_) = t.node, + let PatKind::Ident(_,sp_ident,_) = local.pat.node, + let StmtKind::Semi(ref second,_) = w[1].node, + let ExprKind::Assign(_,ref call) = second.node, + let ExprKind::Call(ref closure,_) = call.node, + let ExprKind::Path(_,ref path) = closure.node + ], { + if sp_ident.node == (&path.segments[0]).identifier { + span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared"); + } + }} + } + } } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 46680f2b8d8..0e72efe654e 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unknown_lints, unused, no_effect)] +#![allow(unknown_lints, unused, no_effect, redundant_closure_call)] #![deny(redundant_closure)] fn main() { diff --git a/tests/compile-fail/redundant_closure_call.rs b/tests/compile-fail/redundant_closure_call.rs new file mode 100644 index 00000000000..73830ecc9f1 --- /dev/null +++ b/tests/compile-fail/redundant_closure_call.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(redundant_closure_call)] + +fn main() { + let a = (|| 42)(); + //~^ ERROR Try not to call a closure in the expression where it is declared. + //~| HELP Try doing something like: + //~| SUGGESTION let a = 42; + + let mut i = 1; + let k = (|m| m+1)(i); //~ERROR Try not to call a closure in the expression where it is declared. + + k = (|a,b| a*b)(1,5); //~ERROR Try not to call a closure in the expression where it is declared. + + let closure = || 32; + i = closure(); //~ERROR Closure called just once immediately after it was declared + + let closure = |i| i+1; + i = closure(3); //~ERROR Closure called just once immediately after it was declared + + i = closure(4); +} + -- cgit 1.4.1-3-g733a5 From 2abb775de5bed06722ef0d9d14488d6e8777842f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 6 Mar 2016 14:10:04 +0100 Subject: Fix dogfood --- src/misc_early.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc_early.rs b/src/misc_early.rs index 89a0763e2e3..60e175d6382 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -134,7 +134,7 @@ impl EarlyLintPass for MiscEarly { expr.span, "Try not to call a closure in the expression where it is declared.", |db| { - if decl.inputs.len() == 0 { + if decl.inputs.is_empty() { let hint = format!("{}", snippet(cx, block.span, "..")); db.span_suggestion(expr.span, "Try doing something like: ", hint); } -- cgit 1.4.1-3-g733a5 From 59f44eb17a1896518c171db34d9b7f1254b4ee24 Mon Sep 17 00:00:00 2001 From: Camille TJHOA <camille@contract-live.com> Date: Mon, 7 Mar 2016 00:12:06 +0100 Subject: add clippy service badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff875085da2..a61c9882c1b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ #rust-clippy [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) +[![Clippy Linting Result](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/badge.svg)](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/log) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) -- cgit 1.4.1-3-g733a5 From eb0a4934422941385a490ae9273ce8f6f05698e2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 16:30:02 +0100 Subject: Implement struct literal equality --- src/utils/hir.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 6231970a0cc..6b745c15e6f 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -117,6 +117,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { both(lqself, rqself, |l, r| self.eq_qself(l, r)) && self.eq_path(lsubpath, rsubpath) } + (&ExprStruct(ref lpath, ref lf, ref lo), &ExprStruct(ref rpath, ref rf, ref ro)) => { + self.eq_path(lpath, rpath) && + both(lo, ro, |l, r| self.eq_expr(l, r)) && + over(lf, rf, |l, r| self.eq_field(l, r)) + } (&ExprTup(ref ltup), &ExprTup(ref rtup)) => self.eq_exprs(ltup, rtup), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => lop == rop && self.eq_expr(le, re), @@ -132,6 +137,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { over(left, right, |l, r| self.eq_expr(l, r)) } + fn eq_field(&self, left: &Field, right: &Field) -> bool { + left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr) + } + /// Check whether two patterns are the same. pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { match (&left.node, &right.node) { -- cgit 1.4.1-3-g733a5 From 13bb22a68b1170a9e75fba0d1ded528fd7fe5139 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 16:31:38 +0100 Subject: Remove all ExprRange Rustup to rustc 1.9.0-nightly (998a6720b 2016-03-07) --- src/loops.rs | 41 ++++++++++++++-------------- src/no_effect.rs | 11 +++++--- src/ranges.rs | 10 +++---- src/utils/hir.rs | 13 --------- src/utils/mod.rs | 60 ++++++++++++++++++++++++++++++++++++++++- tests/compile-fail/copies.rs | 32 +++++++++++++++++++++- tests/compile-fail/no_effect.rs | 3 ++- 7 files changed, 125 insertions(+), 45 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 600f22ea001..723236c7ed7 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -12,8 +12,10 @@ use std::borrow::Cow; use std::collections::HashMap; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, - span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty}; + span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, + unsugar_range, walk_ptrs_ty}; use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; +use utils::UnsugaredRange; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. /// @@ -323,10 +325,9 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E /// Check for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let ExprRange(Some(ref l), ref r) = arg.node { + if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(&arg) { // the var must be a single name if let PatKind::Ident(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { cx: cx, var: ident.node.name, @@ -348,19 +349,19 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex return; } - let starts_at_zero = is_integer_literal(l, 0); + let starts_at_zero = is_integer_literal(start, 0); let skip: Cow<_> = if starts_at_zero { "".into() } else { - format!(".skip({})", snippet(cx, l.span, "..")).into() + format!(".skip({})", snippet(cx, start.span, "..")).into() }; - let take: Cow<_> = if let Some(ref r) = *r { - if is_len_call(&r, &indexed) { + let take: Cow<_> = if let Some(ref end) = *end { + if is_len_call(&end, &indexed) { "".into() } else { - format!(".take({})", snippet(cx, r.span, "..")).into() + format!(".take({})", snippet(cx, end.span, "..")).into() } } else { "".into() @@ -416,27 +417,27 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... - if let ExprRange(Some(ref start_expr), Some(ref stop_expr)) = arg.node { + if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(&arg) { // ...and both sides are compile-time constant integers... - if let Ok(start_idx) = eval_const_expr_partial(&cx.tcx, start_expr, ExprTypeChecked, None) { - if let Ok(stop_idx) = eval_const_expr_partial(&cx.tcx, stop_expr, ExprTypeChecked, None) { - // ...and the start index is greater than the stop index, + if let Ok(start_idx) = eval_const_expr_partial(&cx.tcx, start, ExprTypeChecked, None) { + if let Ok(end_idx) = eval_const_expr_partial(&cx.tcx, end, ExprTypeChecked, None) { + // ...and the start index is greater than the end index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the // smaller value. - let (sup, eq) = match (start_idx, stop_idx) { - (ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => { - (start_idx > stop_idx, start_idx == stop_idx) + let (sup, eq) = match (start_idx, end_idx) { + (ConstVal::Int(start_idx), ConstVal::Int(end_idx)) => { + (start_idx > end_idx, start_idx == end_idx) } - (ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => { - (start_idx > stop_idx, start_idx == stop_idx) + (ConstVal::Uint(start_idx), ConstVal::Uint(end_idx)) => { + (start_idx > end_idx, start_idx == end_idx) } _ => (false, false), }; if sup { - let start_snippet = snippet(cx, start_expr.span, "_"); - let stop_snippet = snippet(cx, stop_expr.span, "_"); + let start_snippet = snippet(cx, start.span, "_"); + let end_snippet = snippet(cx, end.span, "_"); span_lint_and_then(cx, REVERSE_RANGE_LOOP, @@ -447,7 +448,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { "consider using the following if \ you are attempting to iterate \ over this range in reverse", - format!("({}..{}).rev()` ", stop_snippet, start_snippet)); + format!("({}..{}).rev()` ", end_snippet, start_snippet)); }); } else if eq { // if they are equal, it's also problematic - this loop diff --git a/src/no_effect.rs b/src/no_effect.rs index 65dfeb0d4be..59f7be94c23 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -23,15 +23,11 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { match expr.node { Expr_::ExprLit(..) | Expr_::ExprClosure(..) | - Expr_::ExprRange(None, None) | Expr_::ExprPath(..) => true, Expr_::ExprIndex(ref a, ref b) | - Expr_::ExprRange(Some(ref a), Some(ref b)) | Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), Expr_::ExprVec(ref v) | Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), - Expr_::ExprRange(Some(ref inner), None) | - Expr_::ExprRange(None, Some(ref inner)) | Expr_::ExprRepeat(ref inner, _) | Expr_::ExprCast(ref inner, _) | Expr_::ExprType(ref inner, _) | @@ -55,6 +51,13 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { _ => false, } } + Expr_::ExprBlock(ref block) => { + block.stmts.is_empty() && if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) + } else { + false + } + } _ => false, } } diff --git a/src/ranges.rs b/src/ranges.rs index 895bd180168..766d98b4e0b 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::{is_integer_literal, match_type, snippet}; +use utils::{is_integer_literal, match_type, snippet, unsugar_range, UnsugaredRange}; /// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. /// @@ -47,17 +47,17 @@ impl LateLintPass for StepByZero { instead") } else if name.as_str() == "zip" && args.len() == 2 { let iter = &args[0].node; - let zip_arg = &args[1].node; + let zip_arg = &args[1]; if_let_chain! { [ // .iter() call let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, iter_name.as_str() == "iter", // range expression in .zip() call: 0..x.len() - let ExprRange(Some(ref from), Some(ref to)) = *zip_arg, - is_integer_literal(from, 0), + let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), + is_integer_literal(start, 0), // .len() call - let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = to.node, + let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, len_name.as_str() == "len" && len_args.len() == 1, // .iter() and .len() called on same Path let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 6b745c15e6f..0bd054a839a 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -109,9 +109,6 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { !self.ignore_fn && lname.node == rname.node && ltys.is_empty() && rtys.is_empty() && self.eq_exprs(largs, rargs) } - (&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => { - both(lb, rb, |l, r| self.eq_expr(l, r)) && both(le, re, |l, r| self.eq_expr(l, r)) - } (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { @@ -384,16 +381,6 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_name(&name.node); self.hash_exprs(args); } - ExprRange(ref b, ref e) => { - let c: fn(_, _) -> _ = ExprRange; - c.hash(&mut self.s); - if let Some(ref b) = *b { - self.hash_expr(b); - } - if let Some(ref e) = *e { - self.hash_expr(e); - } - } ExprRepeat(ref e, ref l) => { let c: fn(_, _) -> _ = ExprRepeat; c.hash(&mut self.s); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index f2b0c1f4db1..b001d9530ed 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,7 +9,7 @@ use std::borrow::Cow; use std::mem; use std::ops::{Deref, DerefMut}; use std::str::FromStr; -use syntax::ast::{self, LitKind}; +use syntax::ast::{self, LitKind, RangeLimits}; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; @@ -40,6 +40,12 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedLis pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; +pub const RANGE_FROM_PATH: [&'static str; 3] = ["std", "ops", "RangeFrom"]; +pub const RANGE_FULL_PATH: [&'static str; 3] = ["std", "ops", "RangeFull"]; +pub const RANGE_INCLUSIVE_NON_EMPTY_PATH: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE_PATH: [&'static str; 3] = ["std", "ops", "Range"]; +pub const RANGE_TO_INCLUSIVE_PATH: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; +pub const RANGE_TO_PATH: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; @@ -673,3 +679,55 @@ pub fn camel_case_from(s: &str) -> usize { } last_i } + +/// Represents a range akin to `ast::ExprKind::Range`. +pub struct UnsugaredRange<'a> { + pub start: Option<&'a Expr>, + pub end: Option<&'a Expr>, + pub limits: RangeLimits, +} + +/// Unsugar a `hir` range. +pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { + // To be removed when ranges get stable. + fn unwrap_unstable(expr: &Expr) -> &Expr { + if let ExprBlock(ref block) = expr.node { + if block.rules == BlockCheckMode::PushUnstableBlock || block.rules == BlockCheckMode::PopUnstableBlock { + if let Some(ref expr) = block.expr { + return expr; + } + } + } + + expr + } + + fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> { + let expr = &fields.iter() + .find(|field| field.name.node.as_str() == name) + .unwrap_or_else(|| panic!("missing {} field for range", name)) + .expr; + + Some(unwrap_unstable(expr)) + } + + if let ExprStruct(ref path, ref fields, None) = unwrap_unstable(&expr).node { + if match_path(path, &RANGE_FROM_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) + } else if match_path(path, &RANGE_FULL_PATH) { + Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) + } else if match_path(path, &RANGE_INCLUSIVE_NON_EMPTY_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) + } else if match_path(path, &RANGE_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + } else if match_path(path, &RANGE_TO_INCLUSIVE_PATH) { + Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) + } else if match_path(path, &RANGE_TO_PATH) { + Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + } else { + None + } + } else { + None + } +} diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 7a17b345fa8..c1e1ba68b3e 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -1,4 +1,4 @@ -#![feature(plugin)] +#![feature(plugin, inclusive_range_syntax)] #![plugin(clippy)] #![allow(dead_code, no_effect)] @@ -10,16 +10,46 @@ fn bar<T>(_: T) {} fn foo() -> bool { unimplemented!() } +struct Foo { + bar: u8, +} + #[deny(if_same_then_else)] #[deny(match_same_arms)] fn if_same_then_else() -> Result<&'static str, ()> { if true { + Foo { bar: 42 }; + 0..10; + ..; + 0..; + ..10; + 0...10; foo(); } else { //~ERROR this `if` has identical blocks + Foo { bar: 42 }; + 0..10; + ..; + 0..; + ..10; + 0...10; foo(); } + if true { + Foo { bar: 42 }; + } + else { + Foo { bar: 43 }; + } + + if true { + 0..10; + } + else { + 0...10; + } + if true { foo(); foo(); diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index 52ea423a57d..344c82f3307 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -1,4 +1,4 @@ -#![feature(plugin, box_syntax)] +#![feature(plugin, box_syntax, inclusive_range_syntax)] #![plugin(clippy)] #![deny(no_effect)] @@ -39,6 +39,7 @@ fn main() { 5..; //~ERROR statement with no effect ..5; //~ERROR statement with no effect 5..6; //~ERROR statement with no effect + 5...6; //~ERROR statement with no effect [42, 55]; //~ERROR statement with no effect [42, 55][1]; //~ERROR statement with no effect (42, 55).1; //~ERROR statement with no effect -- cgit 1.4.1-3-g733a5 From 7b135efa73b4d92f8ff8e6ed5d39a15d1c7a6c86 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 16:42:49 +0100 Subject: Remove bad test in for_loop --- tests/compile-fail/for_loop.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 69ce68b17db..8d483ccde7a 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -158,10 +158,6 @@ fn main() { println!("{}", i); } - for i in (10..0).rev() { // not an error, this is an established idiom for looping backwards on a range - println!("{}", i); - } - for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range println!("{}", i); } -- cgit 1.4.1-3-g733a5 From 3c3a4549a8df25e9fcdd2e41a50311124cc0906c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 16:55:12 +0100 Subject: Fix tests with inclusive ranges --- src/loops.rs | 5 +++-- tests/compile-fail/for_loop.rs | 23 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 723236c7ed7..e41402ef85a 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -10,6 +10,7 @@ use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; use std::collections::HashMap; +use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, @@ -417,7 +418,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... - if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(&arg) { + if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(&arg) { // ...and both sides are compile-time constant integers... if let Ok(start_idx) = eval_const_expr_partial(&cx.tcx, start, ExprTypeChecked, None) { if let Ok(end_idx) = eval_const_expr_partial(&cx.tcx, end, ExprTypeChecked, None) { @@ -450,7 +451,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { over this range in reverse", format!("({}..{}).rev()` ", end_snippet, start_snippet)); }); - } else if eq { + } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop // will never run. span_lint(cx, diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 8d483ccde7a..0853ae83cd7 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin, step_by)] +#![feature(plugin, step_by, inclusive_range_syntax)] #![plugin(clippy)] use std::collections::*; @@ -118,11 +118,21 @@ fn main() { println!("{}", vec[i]); } + for i in 0...MAX_LEN { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)` + println!("{}", vec[i]); + } + for i in 5..10 { //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` println!("{}", vec[i]); } + for i in 5...10 { + //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` + println!("{}", vec[i]); + } + for i in 5..vec.len() { //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().skip(5)` println!("{} {}", vec[i], i); @@ -140,6 +150,13 @@ fn main() { println!("{}", i); } + for i in 10...0 { + //~^ERROR this range is empty so this for loop will never run + //~|HELP consider + //~|SUGGESTION (0..10).rev() + println!("{}", i); + } + for i in MAX_LEN..0 { //~ERROR this range is empty so this for loop will never run //~|HELP consider //~|SUGGESTION (0..MAX_LEN).rev() @@ -150,6 +167,10 @@ fn main() { println!("{}", i); } + for i in 5...5 { // not an error, this is the range with only one element “5” + println!("{}", i); + } + for i in 0..10 { // not an error, the start index is less than the end index println!("{}", i); } -- cgit 1.4.1-3-g733a5 From 4683cb1af364374ad9e33a0bc2d7eda91f44a385 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 16:57:01 +0100 Subject: Bump to 0.0.47 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bee10dccd6f..97dcb20390b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.46" +version = "0.0.47" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 004fc4e09a0f85929af81812d829486d2c0775f9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 18:40:13 +0100 Subject: Split travis tests into build + test --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1029c67ee6b..6df1b49e484 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,5 @@ sudo: false script: - python util/update_lints.py -c + - cargo build --features debugging - cargo test --features debugging -- cgit 1.4.1-3-g733a5 From 6ad2f645be848f4c9e0be136a612271a6bf202f1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 19:08:46 +0100 Subject: Put regex_macros tests in a separate feature --- .travis.yml | 3 +++ Cargo.toml | 10 ++++----- tests/compile-fail-regex_macros/regex.rs | 12 +++++++++++ tests/compile-fail/regex.rs | 9 +------- tests/compile-test.rs | 8 +++++++ tests/mut_mut_macro.rs | 32 ---------------------------- tests/run-pass-regex_macros/mut_mut_macro.rs | 12 +++++++++++ tests/run-pass/mut_mut_macro.rs | 22 +++++++++++++++++++ 8 files changed, 63 insertions(+), 45 deletions(-) create mode 100644 tests/compile-fail-regex_macros/regex.rs delete mode 100644 tests/mut_mut_macro.rs create mode 100644 tests/run-pass-regex_macros/mut_mut_macro.rs create mode 100644 tests/run-pass/mut_mut_macro.rs diff --git a/.travis.yml b/.travis.yml index 6df1b49e484..d0c614aaae9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,6 @@ script: - python util/update_lints.py -c - cargo build --features debugging - cargo test --features debugging + + # only test regex_macros if it compiles + - if [[ "$(cargo build --features 'debugging test-regex_macros')" = 101 ]]; then cargo test --features 'debugging test-regex_macros'; fi diff --git a/Cargo.toml b/Cargo.toml index 97dcb20390b..5fede91ea2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,17 +18,17 @@ name = "clippy" plugin = true [dependencies] -unicode-normalization = "0.1" -semver = "0.2.1" regex-syntax = "0.2.2" +regex_macros = { version = "0.1.28", optional = true } +semver = "0.2.1" +unicode-normalization = "0.1" [dev-dependencies] compiletest_rs = "0.0.11" -regex = "0.1.47" -regex_macros = "0.1.28" lazy_static = "0.1.15" +regex = "0.1.47" rustc-serialize = "0.3" [features] - debugging = [] +test-regex_macros = ["regex_macros"] diff --git a/tests/compile-fail-regex_macros/regex.rs b/tests/compile-fail-regex_macros/regex.rs new file mode 100644 index 00000000000..aab196fb795 --- /dev/null +++ b/tests/compile-fail-regex_macros/regex.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy, regex_macros)] + +#![allow(unused)] +#![deny(invalid_regex, trivial_regex, regex_macro)] + +extern crate regex; + +fn main() { + let some_regex = regex!("for real!"); //~ERROR `regex!(_)` + let other_regex = regex!("[a-z]_[A-Z]"); //~ERROR `regex!(_)` +} diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index df52cc3dff0..606c3d513b2 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -1,5 +1,5 @@ #![feature(plugin)] -#![plugin(clippy, regex_macros)] +#![plugin(clippy)] #![allow(unused)] #![deny(invalid_regex, trivial_regex, regex_macro)] @@ -70,14 +70,7 @@ fn trivial_regex() { let non_trivial_ends_with = Regex::new("foo|bar"); } -fn regex_macro() { - let some_regex = regex!("for real!"); //~ERROR `regex!(_)` - let other_regex = regex!("[a-z]_[A-Z]"); //~ERROR `regex!(_)` -} - - fn main() { - regex_macro(); syntax_error(); trivial_regex(); } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 822d9339ba3..ff2d94d2777 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -20,7 +20,15 @@ fn run_mode(mode: &'static str) { } #[test] +#[cfg(not(feature = "test-regex_macros"))] fn compile_test() { run_mode("run-pass"); run_mode("compile-fail"); } + +#[test] +#[cfg(feature = "test-regex_macros")] +fn compile_test() { + run_mode("run-pass-regex_macros"); + run_mode("compile-fail-regex_macros"); +} diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs deleted file mode 100644 index 67d73ce0ac4..00000000000 --- a/tests/mut_mut_macro.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy, regex_macros)] - -#[macro_use] -extern crate lazy_static; -extern crate regex; - -use std::collections::HashMap; - -#[test] -#[deny(mut_mut)] -#[allow(regex_macro)] -fn test_regex() { - let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); - assert!(pattern.is_match("# headline")); -} - -#[test] -#[deny(mut_mut)] -#[allow(unused_variables, unused_mut)] -fn test_lazy_static() { - lazy_static! { - static ref MUT_MAP : HashMap<usize, &'static str> = { - let mut m = HashMap::new(); - let mut zero = &mut &mut "zero"; - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert!(*MUT_COUNT == 1); -} diff --git a/tests/run-pass-regex_macros/mut_mut_macro.rs b/tests/run-pass-regex_macros/mut_mut_macro.rs new file mode 100644 index 00000000000..92b44dbdd48 --- /dev/null +++ b/tests/run-pass-regex_macros/mut_mut_macro.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy, regex_macros)] + +#[macro_use] +extern crate regex; + +#[deny(mut_mut)] +#[allow(regex_macro)] +fn main() { + let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); + assert!(pattern.is_match("# headline")); +} diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs new file mode 100644 index 00000000000..e652862c4ff --- /dev/null +++ b/tests/run-pass/mut_mut_macro.rs @@ -0,0 +1,22 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[macro_use] +extern crate lazy_static; + +use std::collections::HashMap; + +#[deny(mut_mut)] +#[allow(unused_variables, unused_mut)] +fn main() { + lazy_static! { + static ref MUT_MAP : HashMap<usize, &'static str> = { + let mut m = HashMap::new(); + let mut zero = &mut &mut "zero"; + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert!(*MUT_COUNT == 1); +} -- cgit 1.4.1-3-g733a5 From 55fbf59f3bec1425e03b56516050912ed02147c9 Mon Sep 17 00:00:00 2001 From: KALPESH KRISHNA <kalpeshk2011@gmail.com> Date: Sun, 6 Mar 2016 20:31:17 +0530 Subject: Linting classical overflow checks. --- README.md | 3 +- src/lib.rs | 3 ++ src/overflow_check_conditional.rs | 41 ++++++++++++++++++++++++ tests/compile-fail/overflow_check_conditional.rs | 25 +++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/overflow_check_conditional.rs create mode 100644 tests/compile-fail/overflow_check_conditional.rs diff --git a/README.md b/README.md index ff875085da2..77518df6b39 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 130 lints included in this crate: +There are 131 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -92,6 +92,7 @@ name [option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` [or_fun_call](https://github.com/Manishearth/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method when the `*or_else` would do [out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bound constant indexing +[overflow_check_conditional](https://github.com/Manishearth/rust-clippy/wiki#overflow_check_conditional) | warn | Using overflow checks which are likely to panic [panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` [precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | catches operations where precedence may be unclear. See the wiki for a list of cases caught [print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout diff --git a/src/lib.rs b/src/lib.rs index 803a4c2345c..51292bea8b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ pub mod needless_features; pub mod needless_update; pub mod no_effect; pub mod open_options; +pub mod overflow_check_conditional; pub mod panic; pub mod precedence; pub mod print; @@ -173,6 +174,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); + reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -283,6 +285,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_update::NEEDLESS_UPDATE, no_effect::NO_EFFECT, open_options::NONSENSICAL_OPEN_OPTIONS, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic::PANIC_PARAMS, precedence::PRECEDENCE, ptr_arg::PTR_ARG, diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs new file mode 100644 index 00000000000..7f4f4b3597c --- /dev/null +++ b/src/overflow_check_conditional.rs @@ -0,0 +1,41 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::{span_lint}; + +/// **What it does:** This lint finds classic overflow checks. +/// +/// **Why is this bad?** Most classic C overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead. +/// +/// **Known problems:** None. +/// +/// **Example:** `a + b < a` +declare_lint!(pub OVERFLOW_CHECK_CONDITIONAL, Warn, + "Using overflow checks which are likely to panic"); + +#[derive(Copy, Clone)] +pub struct OverflowCheckConditional; + +impl LintPass for OverflowCheckConditional { + fn get_lints(&self) -> LintArray { + lint_array!(OVERFLOW_CHECK_CONDITIONAL) + } +} + +impl LateLintPass for OverflowCheckConditional { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! {[ + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let BinOp_::BiLt = op.node, + let Expr_::ExprBinary(ref op2, ref add1, ref add2) = first.node, + let BinOp_::BiAdd = op2.node, + let Expr_::ExprPath(_,ref path1) = add1.node, + let Expr_::ExprPath(_, ref path2) = add2.node, + let Expr_::ExprPath(_, ref path3) = second.node, + (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, + cx.tcx.expr_ty(add1).is_integral(), + cx.tcx.expr_ty(add2).is_integral() + ], { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + }} + } +} diff --git a/tests/compile-fail/overflow_check_conditional.rs b/tests/compile-fail/overflow_check_conditional.rs new file mode 100644 index 00000000000..0b5e486df46 --- /dev/null +++ b/tests/compile-fail/overflow_check_conditional.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(overflow_check_conditional)] + +fn main() { + let a: u32 = 1; + let b: u32 = 2; + let c: u32 = 3; + if a + b < a { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + + } + if a + b < b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + + } + if a + b < c { + + } + let i = 1.1; + let j = 2.2; + if i + j < i { + + } +} + -- cgit 1.4.1-3-g733a5 From d6d409414ea82866bac7f4c7698c16f9884a1b9b Mon Sep 17 00:00:00 2001 From: KALPESH KRISHNA <kalpeshk2011@gmail.com> Date: Tue, 8 Mar 2016 02:57:45 +0530 Subject: Adding underflow checks and tests --- src/overflow_check_conditional.rs | 15 +++++++++++++++ tests/compile-fail/overflow_check_conditional.rs | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index 7f4f4b3597c..c89a3dd2732 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -37,5 +37,20 @@ impl LateLintPass for OverflowCheckConditional { ], { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); }} + + if_let_chain! {[ + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let BinOp_::BiGt = op.node, + let Expr_::ExprBinary(ref op2, ref sub1, ref sub2) = first.node, + let BinOp_::BiSub = op2.node, + let Expr_::ExprPath(_,ref path1) = sub1.node, + let Expr_::ExprPath(_, ref path2) = sub2.node, + let Expr_::ExprPath(_, ref path3) = second.node, + (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, + cx.tcx.expr_ty(sub1).is_integral(), + cx.tcx.expr_ty(sub2).is_integral() + ], { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + }} } } diff --git a/tests/compile-fail/overflow_check_conditional.rs b/tests/compile-fail/overflow_check_conditional.rs index 0b5e486df46..a59fa2a444a 100644 --- a/tests/compile-fail/overflow_check_conditional.rs +++ b/tests/compile-fail/overflow_check_conditional.rs @@ -12,14 +12,26 @@ fn main() { } if a + b < b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + } + if a - b > b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + + } + if a - b > a { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + } if a + b < c { + } + if a - b < c { + } let i = 1.1; let j = 2.2; if i + j < i { + } + if i - j < i { + } } -- cgit 1.4.1-3-g733a5 From 8bbd8b0b9263718b4c0c6c86b5ab2fb038aa3f5b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 23:24:11 +0100 Subject: Fix ICE in for_loop with globals --- src/loops.rs | 25 ++++++++++++++++++------- tests/compile-fail/for_loop.rs | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index e41402ef85a..462ca7c49f6 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -345,9 +345,11 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex .unwrap_or_else(|| unreachable!() /* len == 1 */); // ensure that the indexed variable was declared before the loop, see #601 - let pat_extent = cx.tcx.region_maps.var_scope(pat.id); - if cx.tcx.region_maps.is_subscope_of(indexed_extent, pat_extent) { - return; + if let Some(indexed_extent) = indexed_extent { + let pat_extent = cx.tcx.region_maps.var_scope(pat.id); + if cx.tcx.region_maps.is_subscope_of(indexed_extent, pat_extent) { + return; + } } let starts_at_zero = is_integer_literal(start, 0); @@ -669,7 +671,7 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { struct VarVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference var: Name, // var name to look for as index - indexed: HashMap<Name, CodeExtent>, // indexed variables + indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global nonindex: bool, // has the var been used otherwise? } @@ -687,9 +689,18 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { ], { let def_map = self.cx.tcx.def_map.borrow(); if let Some(def) = def_map.get(&seqexpr.id) { - let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); - self.indexed.insert(seqvar.segments[0].identifier.name, extent); - return; // no need to walk further + match def.base_def { + Def::Local(..) | Def::Upvar(..) => { + let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); + self.indexed.insert(seqvar.segments[0].identifier.name, Some(extent)); + return; // no need to walk further + } + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].identifier.name, None); + return; // no need to walk further + } + _ => (), + } } } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 0853ae83cd7..bbdf9d8f1b5 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -3,6 +3,9 @@ use std::collections::*; +static STATIC: [usize; 4] = [ 0, 1, 8, 16 ]; +const CONST: [usize; 4] = [ 0, 1, 8, 16 ]; + #[deny(clippy)] fn for_loop_over_option_and_result() { let option = Some(1); @@ -95,6 +98,18 @@ fn main() { //~^ ERROR `i` is only used to index `vec`. Consider using `for item in &vec` println!("{}", vec[i]); } + + // ICE #746 + for j in 0..4 { + //~^ ERROR `j` is only used to index `STATIC` + println!("{:?}", STATIC[j]); + } + + for j in 0..4 { + //~^ ERROR `j` is only used to index `CONST` + println!("{:?}", CONST[j]); + } + for i in 0..vec.len() { //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate()` println!("{} {}", vec[i], i); -- cgit 1.4.1-3-g733a5 From 55a584ac84387cf56bf2a4af05ecd2643cce5980 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 7 Mar 2016 23:24:49 +0100 Subject: Bump to 0.0.48 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5fede91ea2f..7f19858fff4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.47" +version = "0.0.48" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 9faffd28705b39c37526f964b637bb405e348f35 Mon Sep 17 00:00:00 2001 From: KALPESH KRISHNA <kalpeshk2011@gmail.com> Date: Tue, 8 Mar 2016 11:03:30 +0530 Subject: Adding symmetric lints and test cases --- src/overflow_check_conditional.rs | 55 ++++++++++++++++-------- tests/compile-fail/overflow_check_conditional.rs | 24 +++++++++++ 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index c89a3dd2732..2dccbfdb26a 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -1,14 +1,16 @@ +#![allow(cyclomatic_complexity)] use rustc::lint::*; use rustc_front::hir::*; use utils::{span_lint}; -/// **What it does:** This lint finds classic overflow checks. +/// **What it does:** This lint finds classic underflow / overflow checks. /// -/// **Why is this bad?** Most classic C overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead. +/// **Why is this bad?** Most classic C underflow / overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead. /// /// **Known problems:** None. /// /// **Example:** `a + b < a` + declare_lint!(pub OVERFLOW_CHECK_CONDITIONAL, Warn, "Using overflow checks which are likely to panic"); @@ -22,35 +24,50 @@ impl LintPass for OverflowCheckConditional { } impl LateLintPass for OverflowCheckConditional { + // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let BinOp_::BiLt = op.node, - let Expr_::ExprBinary(ref op2, ref add1, ref add2) = first.node, - let BinOp_::BiAdd = op2.node, - let Expr_::ExprPath(_,ref path1) = add1.node, - let Expr_::ExprPath(_, ref path2) = add2.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, let Expr_::ExprPath(_, ref path3) = second.node, (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, - cx.tcx.expr_ty(add1).is_integral(), - cx.tcx.expr_ty(add2).is_integral() + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() ], { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + if let BinOp_::BiLt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + } + } + if let BinOp_::BiGt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + } + } }} if_let_chain! {[ let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let BinOp_::BiGt = op.node, - let Expr_::ExprBinary(ref op2, ref sub1, ref sub2) = first.node, - let BinOp_::BiSub = op2.node, - let Expr_::ExprPath(_,ref path1) = sub1.node, - let Expr_::ExprPath(_, ref path2) = sub2.node, - let Expr_::ExprPath(_, ref path3) = second.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, + let Expr_::ExprPath(_, ref path3) = first.node, (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, - cx.tcx.expr_ty(sub1).is_integral(), - cx.tcx.expr_ty(sub2).is_integral() + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() ], { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + if let BinOp_::BiGt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + } + } + if let BinOp_::BiLt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + } + } }} } } diff --git a/tests/compile-fail/overflow_check_conditional.rs b/tests/compile-fail/overflow_check_conditional.rs index a59fa2a444a..df629146dee 100644 --- a/tests/compile-fail/overflow_check_conditional.rs +++ b/tests/compile-fail/overflow_check_conditional.rs @@ -9,21 +9,39 @@ fn main() { let c: u32 = 3; if a + b < a { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + } + if a > a + b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + } if a + b < b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + } + if b > a + b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + } if a - b > b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + } + if b < a - b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + } if a - b > a { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + } + if a < a - b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + } if a + b < c { + } + if c > a + b { + } if a - b < c { + } + if c > a - b { + } let i = 1.1; let j = 2.2; @@ -32,6 +50,12 @@ fn main() { } if i - j < i { + } + if i > i + j { + + } + if i - j < i { + } } -- cgit 1.4.1-3-g733a5 From bf20b40664d699954599d4e7e333b756cec0ad59 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 8 Mar 2016 15:10:02 +0100 Subject: fix cyclomatic complexity lint triggering because of short circuit operations --- src/cyclomatic_complexity.rs | 30 +++++++++++++++++------- src/overflow_check_conditional.rs | 9 ++++--- src/utils/hir.rs | 2 -- tests/compile-fail/cyclomatic_complexity.rs | 14 +++++++++-- tests/compile-fail/overflow_check_conditional.rs | 17 +++++++------- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 05f633ee0e4..b1b578af759 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -51,19 +51,21 @@ impl CyclomaticComplexity { let mut helper = CCHelper { match_arms: 0, divergence: 0, + short_circuits: 0, tcx: &cx.tcx, }; helper.visit_block(block); let CCHelper { match_arms, divergence, + short_circuits, .. } = helper; - if cc + divergence < match_arms { - report_cc_bug(cx, cc, match_arms, divergence, span); + if cc + divergence < match_arms + short_circuits { + report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span); } else { - let rust_cc = cc + divergence - match_arms; + let rust_cc = cc + divergence - match_arms - short_circuits; if rust_cc > self.limit.limit() { span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, @@ -105,6 +107,7 @@ impl LateLintPass for CyclomaticComplexity { struct CCHelper<'a, 'tcx: 'a> { match_arms: u64, divergence: u64, + short_circuits: u64, // && and || tcx: &'a ty::TyCtxt<'tcx>, } @@ -128,29 +131,38 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { } } ExprClosure(..) => {} + ExprBinary(op, _, _) => { + walk_expr(self, e); + match op.node { + BiAnd | BiOr => self.short_circuits += 1, + _ => {}, + } + } _ => walk_expr(self, e), } } } #[cfg(feature="debugging")] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { cx.sess().span_bug(span, &format!("Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}. Please file a bug report.", + div = {}, shorts = {}. Please file a bug report.", cc, narms, - div));; + div, + shorts));; } #[cfg(not(feature="debugging"))] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { cx.sess().span_note_without_error(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ - = {}, arms = {}, div = {}. Please file a bug report.", + = {}, arms = {}, div = {}, shorts = {}. Please file a bug report.", cc, narms, - div)); + div, + shorts)); } } diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index 2dccbfdb26a..823cb696901 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -1,4 +1,3 @@ -#![allow(cyclomatic_complexity)] use rustc::lint::*; use rustc_front::hir::*; use utils::{span_lint}; @@ -38,12 +37,12 @@ impl LateLintPass for OverflowCheckConditional { ], { if let BinOp_::BiLt = op.node { if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } } if let BinOp_::BiGt = op.node { if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); } } }} @@ -60,12 +59,12 @@ impl LateLintPass for OverflowCheckConditional { ], { if let BinOp_::BiGt = op.node { if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditons that will fail in Rust."); + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } } if let BinOp_::BiLt = op.node { if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditons that will fail in Rust."); + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); } } }} diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 0bd054a839a..b4b786f9743 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -55,8 +55,6 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } - // ok, it’s a big function, but mostly one big match with simples cases - #[allow(cyclomatic_complexity)] pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { if self.ignore_fn && differing_macro_contexts(left.span, right.span) { return false; diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 3a4a83af5c6..30a05c3f87d 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -1,6 +1,6 @@ #![feature(plugin, custom_attribute)] #![plugin(clippy)] -#![deny(clippy)] +#![allow(clippy)] #![deny(cyclomatic_complexity)] #![allow(unused)] @@ -90,7 +90,7 @@ fn main() { //~ERROR the function has a cyclomatic complexity of 28 } #[cyclomatic_complexity = "0"] -fn kaboom() { //~ ERROR: the function has a cyclomatic complexity of 8 +fn kaboom() { //~ ERROR: the function has a cyclomatic complexity of 7 let n = 0; 'a: for i in 0..20 { 'b: for j in i..20 { @@ -135,6 +135,16 @@ fn bloo() { } } +#[cyclomatic_complexity = "0"] +fn lots_of_short_circuits() -> bool { //~ ERROR: the function has a cyclomatic complexity of 1 + true && false && true && false && true && false && true +} + +#[cyclomatic_complexity = "0"] +fn lots_of_short_circuits2() -> bool { //~ ERROR: the function has a cyclomatic complexity of 1 + true || false || true || false || true || false || true +} + #[cyclomatic_complexity = "0"] fn baa() { //~ ERROR: the function has a cyclomatic complexity of 2 let x = || match 99 { diff --git a/tests/compile-fail/overflow_check_conditional.rs b/tests/compile-fail/overflow_check_conditional.rs index df629146dee..db7b2792484 100644 --- a/tests/compile-fail/overflow_check_conditional.rs +++ b/tests/compile-fail/overflow_check_conditional.rs @@ -7,28 +7,28 @@ fn main() { let a: u32 = 1; let b: u32 = 2; let c: u32 = 3; - if a + b < a { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + if a + b < a { //~ERROR You are trying to use classic C overflow conditions that will fail in Rust. } - if a > a + b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + if a > a + b { //~ERROR You are trying to use classic C overflow conditions that will fail in Rust. } - if a + b < b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + if a + b < b { //~ERROR You are trying to use classic C overflow conditions that will fail in Rust. } - if b > a + b { //~ERROR You are trying to use classic C overflow conditons that will fail in Rust. + if b > a + b { //~ERROR You are trying to use classic C overflow conditions that will fail in Rust. } - if a - b > b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + if a - b > b { //~ERROR You are trying to use classic C underflow conditions that will fail in Rust. } - if b < a - b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + if b < a - b { //~ERROR You are trying to use classic C underflow conditions that will fail in Rust. } - if a - b > a { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + if a - b > a { //~ERROR You are trying to use classic C underflow conditions that will fail in Rust. } - if a < a - b { //~ERROR You are trying to use classic C underflow conditons that will fail in Rust. + if a < a - b { //~ERROR You are trying to use classic C underflow conditions that will fail in Rust. } if a + b < c { @@ -58,4 +58,3 @@ fn main() { } } - -- cgit 1.4.1-3-g733a5 From 204c12c99ea1d3266bf067700351e8e6468a35d2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 1 Mar 2016 15:15:39 +0100 Subject: Lint unused labels --- README.md | 3 +- src/lib.rs | 3 ++ src/unused_label.rs | 78 +++++++++++++++++++++++++++++++++++++ tests/compile-fail/unused_labels.rs | 35 +++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/unused_label.rs create mode 100755 tests/compile-fail/unused_labels.rs diff --git a/README.md b/README.md index 77518df6b39..3b0a4f8820c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 131 lints included in this crate: +There are 132 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -131,6 +131,7 @@ name [unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 [unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore diff --git a/src/lib.rs b/src/lib.rs index 51292bea8b2..bb9d9b620ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,6 +94,7 @@ pub mod temporary_assignment; pub mod transmute; pub mod types; pub mod unicode; +pub mod unused_label; pub mod vec; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -175,6 +176,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); + reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -309,6 +311,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::TYPE_COMPLEXITY, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, + unused_label::UNUSED_LABEL, vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); diff --git a/src/unused_label.rs b/src/unused_label.rs new file mode 100644 index 00000000000..f2ecad7cc82 --- /dev/null +++ b/src/unused_label.rs @@ -0,0 +1,78 @@ +use rustc::lint::*; +use rustc_front::hir; +use rustc_front::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; +use std::collections::HashMap; +use syntax::ast; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use utils::{in_macro, span_lint}; + +/// **What it does:** This lint checks for unused labels. +/// +/// **Why is this bad?** Maybe the label should be used in which case there is an error in the +/// code or it should be removed. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust,ignore +/// fn unused_label() { +/// 'label: for i in 1..2 { +/// if i > 4 { continue } +/// } +/// ``` +declare_lint! { + pub UNUSED_LABEL, + Warn, + "unused label" +} + +pub struct UnusedLabel; + +#[derive(Default)] +struct UnusedLabelVisitor { + labels: HashMap<InternedString, Span>, +} + +impl UnusedLabelVisitor { + pub fn new() -> UnusedLabelVisitor { + ::std::default::Default::default() + } +} + +impl LintPass for UnusedLabel { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_LABEL) + } +} + +impl LateLintPass for UnusedLabel { + fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, _: ast::NodeId) { + if in_macro(cx, span) { + return; + } + + let mut v = UnusedLabelVisitor::new(); + walk_fn(&mut v, kind, decl, body, span); + + for (label, span) in v.labels { + span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label)); + } + } +} + +impl<'v> Visitor<'v> for UnusedLabelVisitor { + fn visit_expr(&mut self, expr: &hir::Expr) { + match expr.node { + hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => { + self.labels.remove(&label.node.name.as_str()); + } + hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { + self.labels.insert(label.name.as_str(), expr.span); + } + _ => (), + } + + walk_expr(self, expr); + } +} diff --git a/tests/compile-fail/unused_labels.rs b/tests/compile-fail/unused_labels.rs new file mode 100755 index 00000000000..26b4d4a2f3b --- /dev/null +++ b/tests/compile-fail/unused_labels.rs @@ -0,0 +1,35 @@ +#![plugin(clippy)] +#![feature(plugin)] + +#![allow(dead_code, items_after_statements)] +#![deny(unused_label)] + +fn unused_label() { + 'label: for i in 1..2 { //~ERROR: unused label `'label` + if i > 4 { continue } + } +} + +fn foo() { + 'same_label_in_two_fns: loop { + break 'same_label_in_two_fns; + } +} + + +fn bla() { + 'a: loop { break } //~ERROR: unused label `'a` + fn blub() {} +} + +fn main() { + 'a: for _ in 0..10 { + while let Some(42) = None { + continue 'a; + } + } + + 'same_label_in_two_fns: loop { //~ERROR: unused label `'same_label_in_two_fns` + let _ = 1; + } +} -- cgit 1.4.1-3-g733a5 From d7129f560d4a47d95a0b2f84ebf3b15a9b9f79c6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 1 Mar 2016 16:25:15 +0100 Subject: Lint types with `fn new() -> Self` and no `Default` impl --- README.md | 3 +- src/lib.rs | 3 ++ src/methods.rs | 33 +++++----------- src/misc.rs | 2 +- src/new_without_default.rs | 63 +++++++++++++++++++++++++++++++ src/utils/mod.rs | 20 +++++++++- tests/compile-fail/methods.rs | 2 +- tests/compile-fail/new_without_default.rs | 35 +++++++++++++++++ 8 files changed, 132 insertions(+), 29 deletions(-) create mode 100644 src/new_without_default.rs create mode 100755 tests/compile-fail/new_without_default.rs diff --git a/README.md b/README.md index 3b0a4f8820c..9f3c30d39b3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) ##Lints -There are 132 lints included in this crate: +There are 133 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -83,6 +83,7 @@ name [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields [new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method +[new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file diff --git a/src/lib.rs b/src/lib.rs index bb9d9b620ab..8c619a1eaf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,6 +77,7 @@ pub mod mutex_atomic; pub mod needless_bool; pub mod needless_features; pub mod needless_update; +pub mod new_without_default; pub mod no_effect; pub mod open_options; pub mod overflow_check_conditional; @@ -177,6 +178,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box if_not_else::IfNotElse); reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); + reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); reg.register_lint_group("clippy_pedantic", vec![ enum_glob_use::ENUM_GLOB_USE, @@ -285,6 +287,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_features::UNSTABLE_AS_MUT_SLICE, needless_features::UNSTABLE_AS_SLICE, needless_update::NEEDLESS_UPDATE, + new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, diff --git a/src/methods.rs b/src/methods.rs index 94548cf9672..663c7dd1bc4 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -10,8 +10,8 @@ use std::{fmt, iter}; use syntax::codemap::Span; use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, - walk_ptrs_ty, walk_ptrs_ty_depth}; + match_type, method_chain_args, returns_self, snippet, snippet_opt, span_lint, + span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, VEC_PATH}; use utils::MethodArgs; @@ -431,26 +431,11 @@ impl LateLintPass for MethodsPass { } } - if &name.as_str() == &"new" { - let returns_self = if let FunctionRetTy::Return(ref ret_ty) = sig.decl.output { - let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); - let ret_ty = ast_ty_to_ty_cache.get(&ret_ty.id); - - if let Some(&ret_ty) = ret_ty { - ret_ty.walk().any(|t| t == ty) - } else { - false - } - } else { - false - }; - - if !returns_self { - span_lint(cx, - NEW_RET_NO_SELF, - sig.explicit_self.span, - "methods called `new` usually return `Self`"); - } + if &name.as_str() == &"new" && !returns_self(cx, &sig.decl.output, ty) { + span_lint(cx, + NEW_RET_NO_SELF, + sig.explicit_self.span, + "methods called `new` usually return `Self`"); } } } @@ -485,7 +470,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) return false; }; - if implements_trait(cx, arg_ty, default_trait_id, None) { + if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) { span_lint(cx, OR_FUN_CALL, span, @@ -869,7 +854,7 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { /// This checks whether a given type is known to implement Debug. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { match cx.tcx.lang_items.debug_trait() { - Some(debug) => implements_trait(cx, ty, debug, Some(vec![])), + Some(debug) => implements_trait(cx, ty, debug, Vec::new()), None => false, } } diff --git a/src/misc.rs b/src/misc.rs index fae780e4ced..c7aeb7f9a2f 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -253,7 +253,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S None => return, }; - if !implements_trait(cx, arg_ty, partial_eq_trait_id, Some(vec![other_ty])) { + if !implements_trait(cx, arg_ty, partial_eq_trait_id, vec![other_ty]) { return; } diff --git a/src/new_without_default.rs b/src/new_without_default.rs new file mode 100644 index 00000000000..4666336495c --- /dev/null +++ b/src/new_without_default.rs @@ -0,0 +1,63 @@ +use rustc::lint::*; +use rustc_front::hir; +use rustc_front::intravisit::FnKind; +use syntax::ast; +use syntax::codemap::Span; +use utils::{get_trait_def_id, implements_trait, in_external_macro, returns_self, span_lint, DEFAULT_TRAIT_PATH}; + +/// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` +/// implementation. +/// +/// **Why is this bad?** User might expect to be able to use `Default` is the type can be +/// constructed without arguments. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ```rust,ignore +/// struct Foo; +/// +/// impl Foo { +/// fn new() -> Self { +/// Foo +/// } +/// } +/// ``` +declare_lint! { + pub NEW_WITHOUT_DEFAULT, + Warn, + "`fn new() -> Self` method without `Default` implementation" +} + +#[derive(Copy,Clone)] +pub struct NewWithoutDefault; + +impl LintPass for NewWithoutDefault { + fn get_lints(&self) -> LintArray { + lint_array!(NEW_WITHOUT_DEFAULT) + } +} + +impl LateLintPass for NewWithoutDefault { + fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) { + if in_external_macro(cx, span) { + return; + } + + if let FnKind::Method(name, _, _) = kind { + if decl.inputs.is_empty() && name.as_str() == "new" { + let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; + + if returns_self(cx, &decl.output, ty) { + if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { + if !implements_trait(cx, ty, default_trait_id, Vec::new()) { + span_lint(cx, NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a `Default` implementation for `{}`", ty)); + } + } + } + } + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b001d9530ed..46feafb1de4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -264,7 +264,7 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { /// Check whether a type implements a trait. /// See also `get_trait_def_id`. pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, - ty_params: Option<Vec<ty::Ty<'tcx>>>) + ty_params: Vec<ty::Ty<'tcx>>) -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); @@ -274,7 +274,7 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id, 0, ty, - ty_params.unwrap_or_default()); + ty_params); traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) } @@ -731,3 +731,19 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { None } } + +/// Return whether a method returns `Self`. +pub fn returns_self(cx: &LateContext, ret: &FunctionRetTy, ty: ty::Ty) -> bool { + if let FunctionRetTy::Return(ref ret_ty) = *ret { + let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); + let ret_ty = ast_ty_to_ty_cache.get(&ret_ty.id); + + if let Some(&ret_ty) = ret_ty { + ret_ty.walk().any(|t| t == ty) + } else { + false + } + } else { + false + } +} diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index c450c953284..0acab8be4fb 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(clippy, clippy_pedantic)] -#![allow(unused, print_stdout, non_ascii_literal)] +#![allow(unused, print_stdout, non_ascii_literal, new_without_default)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs new file mode 100755 index 00000000000..5f00179a9a2 --- /dev/null +++ b/tests/compile-fail/new_without_default.rs @@ -0,0 +1,35 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(dead_code)] +#![deny(new_without_default)] + +struct Foo; + +impl Foo { + fn new() -> Foo { Foo } //~ERROR: you should consider adding a `Default` implementation for `Foo` +} + +struct Bar; + +impl Bar { + fn new() -> Self { Bar } //~ERROR: you should consider adding a `Default` implementation for `Bar` +} + +struct Ok; + +impl Ok { + fn new() -> Self { Ok } +} + +impl Default for Ok { + fn default() -> Self { Ok } +} + +struct Params; + +impl Params { + fn new(_: u32) -> Self { Params } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 8e9e858b786c262185b279be2d78e9eea0a81ed8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 1 Mar 2016 20:38:21 +0100 Subject: Remove uses of `ast_ty_to_ty_cache` --- src/methods.rs | 5 +++-- src/new_without_default.rs | 12 +++++++----- src/ptr_arg.rs | 41 +++++++++++++++++++++-------------------- src/utils/mod.rs | 17 +++++------------ 4 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 663c7dd1bc4..3ed75fdffeb 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -10,7 +10,7 @@ use std::{fmt, iter}; use syntax::codemap::Span; use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, returns_self, snippet, snippet_opt, span_lint, + match_type, method_chain_args, return_ty, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, VEC_PATH}; @@ -431,7 +431,8 @@ impl LateLintPass for MethodsPass { } } - if &name.as_str() == &"new" && !returns_self(cx, &sig.decl.output, ty) { + let ret_ty = return_ty(cx.tcx.node_id_to_type(implitem.id)); + if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| t == ty)) { span_lint(cx, NEW_RET_NO_SELF, sig.explicit_self.span, diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 4666336495c..89467f1dc55 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -3,7 +3,7 @@ use rustc_front::hir; use rustc_front::intravisit::FnKind; use syntax::ast; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, returns_self, span_lint, DEFAULT_TRAIT_PATH}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, span_lint, DEFAULT_TRAIT_PATH}; /// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` /// implementation. @@ -47,13 +47,15 @@ impl LateLintPass for NewWithoutDefault { if let FnKind::Method(name, _, _) = kind { if decl.inputs.is_empty() && name.as_str() == "new" { - let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; + let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; - if returns_self(cx, &decl.output, ty) { + let ret_ty = return_ty(cx.tcx.node_id_to_type(id)); + + if Some(self_ty) == ret_ty { if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { - if !implements_trait(cx, ty, default_trait_id, Vec::new()) { + if !implements_trait(cx, self_ty, default_trait_id, Vec::new()) { span_lint(cx, NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a `Default` implementation for `{}`", ty)); + &format!("you should consider adding a `Default` implementation for `{}`", self_ty)); } } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index c02e5609b8c..85baf3310c3 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -6,6 +6,7 @@ use rustc::front::map::NodeItem; use rustc::lint::*; use rustc::middle::ty; use rustc_front::hir::*; +use syntax::ast::NodeId; use utils::{STRING_PATH, VEC_PATH}; use utils::{span_lint, match_type}; @@ -35,7 +36,7 @@ impl LintPass for PtrArg { impl LateLintPass for PtrArg { fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemFn(ref decl, _, _, _, _, _) = item.node { - check_fn(cx, decl); + check_fn(cx, decl, item.id); } } @@ -46,34 +47,34 @@ impl LateLintPass for PtrArg { return; // ignore trait impls } } - check_fn(cx, &sig.decl); + check_fn(cx, &sig.decl, item.id); } } fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { - check_fn(cx, &sig.decl); + check_fn(cx, &sig.decl, item.id); } } } -fn check_fn(cx: &LateContext, decl: &FnDecl) { - for arg in &decl.inputs { - if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&arg.ty.id) { - if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { - if match_type(cx, ty, &VEC_PATH) { - span_lint(cx, - PTR_ARG, - arg.ty.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`"); - } else if match_type(cx, ty, &STRING_PATH) { - span_lint(cx, - PTR_ARG, - arg.ty.span, - "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`"); - } +fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { + let fn_ty = cx.tcx.node_id_to_type(fn_id).fn_sig().skip_binder(); + + for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) { + if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { + if match_type(cx, ty, &VEC_PATH) { + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ + with non-Vec-based slices. Consider changing the type to `&[...]`"); + } else if match_type(cx, ty, &STRING_PATH) { + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&String` instead of `&str` involves a new object where a slice will do. \ + Consider changing the type to `&str`"); } } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 46feafb1de4..bef4baea67e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -732,18 +732,11 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { } } -/// Return whether a method returns `Self`. -pub fn returns_self(cx: &LateContext, ret: &FunctionRetTy, ty: ty::Ty) -> bool { - if let FunctionRetTy::Return(ref ret_ty) = *ret { - let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow(); - let ret_ty = ast_ty_to_ty_cache.get(&ret_ty.id); - - if let Some(&ret_ty) = ret_ty { - ret_ty.walk().any(|t| t == ty) - } else { - false - } +/// Convenience function to get the return type of a function or `None` if the function diverges. +pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> { + if let ty::FnConverging(ret_ty) = fun.fn_sig().skip_binder().output { + Some(ret_ty) } else { - false + None } } -- cgit 1.4.1-3-g733a5 From 052f5984e772513654be815a1eac08997db6839c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 3 Mar 2016 19:46:10 +0100 Subject: Fix types comparison --- src/methods.rs | 4 ++-- src/new_without_default.rs | 22 +++++++++++----------- src/utils/mod.rs | 8 ++++++++ tests/compile-fail/methods.rs | 19 +++++++++++++++++++ tests/compile-fail/new_without_default.rs | 9 +++++++++ 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 3ed75fdffeb..6d33f31d45c 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -10,7 +10,7 @@ use std::{fmt, iter}; use syntax::codemap::Span; use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, return_ty, snippet, snippet_opt, span_lint, + match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, VEC_PATH}; @@ -432,7 +432,7 @@ impl LateLintPass for MethodsPass { } let ret_ty = return_ty(cx.tcx.node_id_to_type(implitem.id)); - if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| t == ty)) { + if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty))) { span_lint(cx, NEW_RET_NO_SELF, sig.explicit_self.span, diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 89467f1dc55..d341afb4d92 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -3,7 +3,8 @@ use rustc_front::hir; use rustc_front::intravisit::FnKind; use syntax::ast; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, span_lint, DEFAULT_TRAIT_PATH}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint, + DEFAULT_TRAIT_PATH}; /// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` /// implementation. @@ -49,16 +50,15 @@ impl LateLintPass for NewWithoutDefault { if decl.inputs.is_empty() && name.as_str() == "new" { let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; - let ret_ty = return_ty(cx.tcx.node_id_to_type(id)); - - if Some(self_ty) == ret_ty { - if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { - if !implements_trait(cx, self_ty, default_trait_id, Vec::new()) { - span_lint(cx, NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a `Default` implementation for `{}`", self_ty)); - } - } - } + if_let_chain!{[ + let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)), + same_tys(cx, self_ty, ret_ty), + let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH), + !implements_trait(cx, self_ty, default_trait_id, Vec::new()) + ], { + span_lint(cx, NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a `Default` implementation for `{}`", self_ty)); + }} } } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index bef4baea67e..c626fcb8930 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -740,3 +740,11 @@ pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> { None } } + +/// Check if two types are the same. +// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but +// not for type parameters. +pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>) -> bool { + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); + infcx.can_equate(&cx.tcx.erase_regions(&a), &cx.tcx.erase_regions(&b)).is_ok() +} diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 0acab8be4fb..46f14d5d921 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -28,6 +28,25 @@ impl T { //~| ERROR methods called `new` usually return `Self` } +struct Lt<'a> { + foo: &'a u32, +} + +impl<'a> Lt<'a> { + // The lifetime is different, but that’s irrelevant, see #734 + #[allow(needless_lifetimes)] + pub fn new<'b>(s: &'b str) -> Lt<'b> { unimplemented!() } +} + +struct Lt2<'a> { + foo: &'a u32, +} + +impl<'a> Lt2<'a> { + // The lifetime is different, but that’s irrelevant, see #734 + pub fn new(s: &str) -> Lt2 { unimplemented!() } +} + #[derive(Clone,Copy)] struct U; diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index 5f00179a9a2..cc033043bc5 100755 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -32,4 +32,13 @@ impl Params { fn new(_: u32) -> Self { Params } } +struct Generics<'a, T> { + foo: &'a bool, + bar: T, +} + +impl<'c, V> Generics<'c, V> { + fn new<'b>() -> Generics<'b, V> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for +} + fn main() {} -- cgit 1.4.1-3-g733a5 From 3ab4914a29a24684f0b384133b80e522fb95310b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 9 Mar 2016 16:10:24 +0100 Subject: Handle the new TryDesugar variant --- src/matches.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/matches.rs b/src/matches.rs index 1b05162c86a..85a8a4b005d 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -439,6 +439,7 @@ fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, e MatchSource::IfLetDesugar { .. } => format!("if let ... = {}{} {{", op, expr_snippet), MatchSource::WhileLetDesugar => format!("while let ... = {}{} {{", op, expr_snippet), MatchSource::ForLoopDesugar => cx.sess().span_bug(span, "for loop desugared to match with &-patterns!"), + MatchSource::TryDesugar => cx.sess().span_bug(span, "`?` operator desugared to match with &-patterns!") } } -- cgit 1.4.1-3-g733a5 From 9cfc6124a3e09276c75d8998b5a93a29e82213a4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 9 Mar 2016 16:22:31 +0100 Subject: Improve the MATCH_REF_PATS suggestions --- src/matches.rs | 36 ++++++++++++++++++++++-------------- tests/compile-fail/matches.rs | 25 ++++++++++++++++++++----- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/matches.rs b/src/matches.rs index 85a8a4b005d..4c60ea89b34 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -8,7 +8,7 @@ use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; -use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; +use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. /// @@ -309,18 +309,26 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { let template = match_template(cx, expr.span, source, "", inner); - span_lint(cx, - MATCH_REF_PATS, - expr.span, - &format!("you don't need to add `&` to both the expression and the patterns: use `{}`", - template)); + span_lint_and_then(cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to both the expression and the patterns", + |db| { + db.span_suggestion(expr.span, + "try", + template); + }); } else { let template = match_template(cx, expr.span, source, "*", ex); - span_lint(cx, - MATCH_REF_PATS, - expr.span, - &format!("instead of prefixing all patterns with `&`, you can dereference the expression: `{}`", - template)); + span_lint_and_then(cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to all patterns", + |db| { + db.span_suggestion(expr.span, + "instead of prefixing all patterns with `&`, you can dereference the expression", + template); + }); } } } @@ -435,9 +443,9 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, expr: &Expr) -> String { let expr_snippet = snippet(cx, expr.span, ".."); match source { - MatchSource::Normal => format!("match {}{} {{ ...", op, expr_snippet), - MatchSource::IfLetDesugar { .. } => format!("if let ... = {}{} {{", op, expr_snippet), - MatchSource::WhileLetDesugar => format!("while let ... = {}{} {{", op, expr_snippet), + MatchSource::Normal => format!("match {}{} {{ .. }}", op, expr_snippet), + MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), + MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::ForLoopDesugar => cx.sess().span_bug(span, "for loop desugared to match with &-patterns!"), MatchSource::TryDesugar => cx.sess().span_bug(span, "`?` operator desugared to match with &-patterns!") } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 46d3ff8d5fb..f5f830fed51 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -137,7 +137,10 @@ fn match_bool() { fn ref_pats() { { let v = &Some(0); - match v { //~ERROR dereference the expression: `match *v { ...` + match v { + //~^ERROR add `&` to all patterns + //~|HELP instead of + //~|SUGGESTION `match *v { .. }` &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -147,13 +150,19 @@ fn ref_pats() { } } let tup =& (1, 2); - match tup { //~ERROR dereference the expression: `match *tup { ...` + match tup { + //~^ERROR add `&` to all patterns + //~|HELP instead of + //~|SUGGESTION `match *tup { .. }` &(v, 1) => println!("{}", v), _ => println!("none"), } // special case: using & both in expr and pats let w = Some(0); - match &w { //~ERROR use `match w { ...` + match &w { + //~^ERROR add `&` to both + //~|HELP try + //~|SUGGESTION `match w { .. }` &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -164,12 +173,18 @@ fn ref_pats() { } let a = &Some(0); - if let &None = a { //~ERROR dereference the expression: `if let ... = *a {` + if let &None = a { + //~^ERROR add `&` to all patterns + //~|HELP instead of + //~|SUGGESTION `if let ... = *a { .. }` println!("none"); } let b = Some(0); - if let &None = &b { //~ERROR use `if let ... = b {` + if let &None = &b { + //~^ERROR add `&` to both + //~|HELP try + //~|SUGGESTION `if let ... = b { .. }` println!("none"); } } -- cgit 1.4.1-3-g733a5 From c95ae89387f022ec2bf396fba4c49cb4690c7bae Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 9 Mar 2016 16:22:53 +0100 Subject: Bump to 0.0.49 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7f19858fff4..8ee5e8ab346 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.48" +version = "0.0.49" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From e67e21ca5d9fc1ab85b20cb37b277a46781c4c9c Mon Sep 17 00:00:00 2001 From: Camille TJHOA <camille.tjhoa@outlook.com> Date: Thu, 10 Mar 2016 21:42:24 +0100 Subject: Add link with clippy service --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a61c9882c1b..d2dbb7940fc 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to usage instructions](#usage) +[Jump to link with clippy-service](#link-with-clippy-service) + ##Lints There are 130 lints included in this crate: @@ -224,5 +226,12 @@ And, in your `main.rs` or `lib.rs`: #![cfg_attr(feature="clippy", plugin(clippy))] ``` +##Link with clippy service +`clippy-service` is a rust web initiative providing `rust-clippy` as a web service. + +Both projects are independent and maintained by different people (even if some `clippy-service`'s contributions are authored by some `rust-clippy` members). + +You can check it out this great service at [clippy.bashy.io](https://clippy.bashy.io/) + ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From c6316df19f14702a16c7be3685547def9ff21b21 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 10 Mar 2016 18:13:49 +0100 Subject: Rustup to 1.9.0-nightly (c9629d61c 2016-03-10) --- src/cyclomatic_complexity.rs | 7 ++++--- src/derive.rs | 2 +- src/eta_reduction.rs | 9 ++++++--- src/mut_reference.rs | 27 +++++++++++++++------------ tests/compile-fail/mut_reference.rs | 25 ++++++++++++++----------- 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index b1b578af759..bc13576fe3b 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -124,13 +124,14 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { ExprCall(ref callee, _) => { walk_expr(self, e); let ty = self.tcx.node_id_to_type(callee.id); - if let ty::TyBareFn(_, ty) = ty.sty { - if ty.sig.skip_binder().output.diverges() { + match ty.sty { + ty::TyFnDef(_, _, ty) | ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { self.divergence += 1; } + _ => (), } } - ExprClosure(..) => {} + ExprClosure(..) => (), ExprBinary(op, _, _) => { walk_expr(self, e); match op.node { diff --git a/src/derive.rs b/src/derive.rs index 8bdcb4b0167..380ff0a30f9 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -155,7 +155,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref TypeVariants::TyArray(_, size) if size > 32 => { return; } - TypeVariants::TyBareFn(..) => { + TypeVariants::TyFnPtr(..) => { return; } TypeVariants::TyTuple(ref tys) if tys.len() > 12 => { diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index e28411cc79c..6335f3f1398 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -58,11 +58,14 @@ fn check_closure(cx: &LateContext, expr: &Expr) { return; } let fn_ty = cx.tcx.expr_ty(caller); - if let ty::TyBareFn(_, fn_ty) = fn_ty.sty { + match fn_ty.sty { // Is it an unsafe function? They don't implement the closure traits - if fn_ty.unsafety == Unsafety::Unsafe { - return; + ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { + if fn_ty.unsafety == Unsafety::Unsafe { + return; + } } + _ => (), } for (ref a1, ref a2) in decl.inputs.iter().zip(args) { if let PatKind::Ident(_, ident, _) = a1.pat.node { diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 0e5b038f27d..707ce8efaeb 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -53,21 +53,24 @@ impl LateLintPass for UnnecessaryMutPassed { } fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { - if let TypeVariants::TyBareFn(_, ref fn_type) = type_definition.sty { - let parameters = &fn_type.sig.skip_binder().inputs; - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { - match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | - TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { - if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method \"{}\" doesn't need a mutable reference", name)); + match type_definition.sty { + TypeVariants::TyFnDef(_, _, ref fn_type) | TypeVariants::TyFnPtr(ref fn_type) => { + let parameters = &fn_type.sig.skip_binder().inputs; + for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | + TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { + if let ExprAddrOf(MutMutable, _) = argument.node { + span_lint(cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method \"{}\" doesn't need a mutable reference", name)); + } } + _ => {} } - _ => {} } } + _ => (), } } diff --git a/tests/compile-fail/mut_reference.rs b/tests/compile-fail/mut_reference.rs index 7480add8e68..1d81ed14e4e 100644 --- a/tests/compile-fail/mut_reference.rs +++ b/tests/compile-fail/mut_reference.rs @@ -3,12 +3,8 @@ #![allow(unused_variables)] -fn takes_an_immutable_reference(a: &i32) { -} - - -fn takes_a_mutable_reference(a: &mut i32) { -} +fn takes_an_immutable_reference(a: &i32) {} +fn takes_a_mutable_reference(a: &mut i32) {} struct MyStruct; @@ -24,23 +20,30 @@ impl MyStruct { fn main() { // Functions takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference - + let foo: fn(&i32) = takes_an_immutable_reference; + foo(&mut 42); //~ERROR The function/method "foo" doesn't need a mutable reference + // Methods let my_struct = MyStruct; my_struct.takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference - + // No error - + // Functions takes_an_immutable_reference(&42); + let foo: fn(&i32) = takes_an_immutable_reference; + foo(&42); + takes_a_mutable_reference(&mut 42); + let foo: fn(&mut i32) = takes_a_mutable_reference; + foo(&mut 42); + let a = &mut 42; takes_an_immutable_reference(a); - + // Methods my_struct.takes_an_immutable_reference(&42); my_struct.takes_a_mutable_reference(&mut 42); my_struct.takes_an_immutable_reference(a); - } -- cgit 1.4.1-3-g733a5 From 74412d9574139e6e7fb41da4b21ae83413f5213f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 11 Mar 2016 14:19:28 +0100 Subject: Bump to 0.0.50 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8ee5e8ab346..853815e049f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.49" +version = "0.0.50" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 3f112b1b8a42f2ceacb373bbb09b29d55523f7fe Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 11 Mar 2016 13:19:51 +0100 Subject: Fix punctuation in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a74de7c6998..556bfcf7eb2 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,7 @@ And, in your `main.rs` or `lib.rs`: Both projects are independent and maintained by different people (even if some `clippy-service`'s contributions are authored by some `rust-clippy` members). -You can check it out this great service at [clippy.bashy.io](https://clippy.bashy.io/) +You can check it out this great service at [clippy.bashy.io](https://clippy.bashy.io/). ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From a38958b8d94984ef15f27d808ac82279191ca19e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 11 Mar 2016 20:27:33 +0100 Subject: Fix `unsugar_range` with `..` --- src/utils/mod.rs | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index c626fcb8930..625e8da197d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -681,6 +681,7 @@ pub fn camel_case_from(s: &str) -> usize { } /// Represents a range akin to `ast::ExprKind::Range`. +#[derive(Debug, Copy, Clone)] pub struct UnsugaredRange<'a> { pub start: Option<&'a Expr>, pub end: Option<&'a Expr>, @@ -711,24 +712,30 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { Some(unwrap_unstable(expr)) } - if let ExprStruct(ref path, ref fields, None) = unwrap_unstable(&expr).node { - if match_path(path, &RANGE_FROM_PATH) { - Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) - } else if match_path(path, &RANGE_FULL_PATH) { - Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) - } else if match_path(path, &RANGE_INCLUSIVE_NON_EMPTY_PATH) { - Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) - } else if match_path(path, &RANGE_PATH) { - Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) - } else if match_path(path, &RANGE_TO_INCLUSIVE_PATH) { - Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) - } else if match_path(path, &RANGE_TO_PATH) { - Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) - } else { - None + match unwrap_unstable(&expr).node { + ExprPath(None, ref path) => { + if match_path(path, &RANGE_FULL_PATH) { + Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) + } else { + None + } } - } else { - None + ExprStruct(ref path, ref fields, None) => { + if match_path(path, &RANGE_FROM_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) + } else if match_path(path, &RANGE_INCLUSIVE_NON_EMPTY_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) + } else if match_path(path, &RANGE_PATH) { + Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + } else if match_path(path, &RANGE_TO_INCLUSIVE_PATH) { + Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) + } else if match_path(path, &RANGE_TO_PATH) { + Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + } else { + None + } + } + _ => None, } } -- cgit 1.4.1-3-g733a5 From 87ef5f4d3b300c893cb404ab1f62816b34e0ea4d Mon Sep 17 00:00:00 2001 From: Adolfo Ochagavía <aochagavia92@gmail.com> Date: Fri, 11 Mar 2016 10:51:16 +0100 Subject: Lint against indexing and slicing This can be useful to prevent panics in a codebase. ATM it is a pedantic lint, but in the future it should be added to the restricions group. --- README.md | 3 +- src/array_indexing.rs | 110 ++++++++++++++++++++++++++++++++--- src/lib.rs | 1 + tests/compile-fail/array_indexing.rs | 25 +++++++- 4 files changed, 128 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 556bfcf7eb2..48a106e3591 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to link with clippy-service](#link-with-clippy-service) ##Lints -There are 133 lints included in this crate: +There are 134 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -58,6 +58,7 @@ name [if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | warn | finds if branches that could be swapped so no negation operation is necessary on the condition [if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks [ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition +[indexing_slicing](https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations diff --git a/src/array_indexing.rs b/src/array_indexing.rs index cfa52f390d2..abce04f0b77 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -3,7 +3,8 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty::TyArray; use rustc_front::hir::*; -use utils::span_lint; +use syntax::ast::RangeLimits; +use utils; /// **What it does:** Check for out of bounds array indexing with a constant index. /// @@ -17,6 +18,7 @@ use utils::span_lint; /// let x = [1,2,3,4]; /// ... /// x[9]; +/// &x[2..9]; /// ``` declare_lint! { pub OUT_OF_BOUNDS_INDEXING, @@ -24,28 +26,122 @@ declare_lint! { "out of bound constant indexing" } +/// **What it does:** Check for usage of indexing or slicing. +/// +/// **Why is this bad?** Usually, this can be safely allowed. However, +/// in some domains such as kernel development, a panic can cause the +/// whole operating system to crash. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ``` +/// ... +/// x[2]; +/// &x[0..2]; +/// ``` +declare_lint! { + pub INDEXING_SLICING, + Allow, + "indexing/slicing usage" +} + #[derive(Copy,Clone)] pub struct ArrayIndexing; impl LintPass for ArrayIndexing { fn get_lints(&self) -> LintArray { - lint_array!(OUT_OF_BOUNDS_INDEXING) + lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) } } impl LateLintPass for ArrayIndexing { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprIndex(ref array, ref index) = e.node { + // Array with known size can be checked statically let ty = cx.tcx.expr_ty(array); - if let TyArray(_, size) = ty.sty { - let index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); - if let Ok(ConstVal::Uint(index)) = index { - if size as u64 <= index { - span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index-expr is out of bounds"); + let size = size as u64; + + // Index is a constant uint + let const_index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); + if let Ok(ConstVal::Uint(const_index)) = const_index { + if size <= const_index { + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); + utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); + } else { + // Index is within bounds + return; } } + + // Index is a constant range + if let Some(range) = utils::unsugar_range(index) { + let start = range.start.map(|start| + eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)); + let end = range.end.map(|end| + eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)); + + if let Some((start, end)) = to_const_range(start, end, range.limits, size) { + if start >= size && end >= size { + utils::span_lint(cx, + OUT_OF_BOUNDS_INDEXING, + e.span, + "range is out of bounds"); + utils::span_lint(cx, + INDEXING_SLICING, + e.span, + "slicing may panic"); + } else { + // Range is within bounds + return; + } + } + } + } + + if let Some(range) = utils::unsugar_range(index) { + // Full ranges are always valid + if range.start.is_none() && range.end.is_none() { + return; + } + + // Impossible to know if indexing or slicing is correct + utils::span_lint(cx, INDEXING_SLICING, e.span, "slicing may panic"); + } else { + utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); } } } } + +/// Returns an option containing a tuple with the start and end (exclusive) of the range +/// +/// Note: we assume the start and the end of the range are unsigned, since array slicing +/// works only on usize +fn to_const_range<T>(start: Option<Result<ConstVal, T>>, + end: Option<Result<ConstVal, T>>, + limits: RangeLimits, + array_size: u64) + -> Option<(u64, u64)> { + let start = match start { + Some(Ok(ConstVal::Uint(x))) => x, + Some(_) => return None, + None => 0, + }; + + let end = match end { + Some(Ok(ConstVal::Uint(x))) => { + if limits == RangeLimits::Closed { + x + } else { + x - 1 + } + } + Some(_) => return None, + None => array_size - 1, + }; + + Some((start, end)) +} diff --git a/src/lib.rs b/src/lib.rs index 8c619a1eaf7..664819b97ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,6 +181,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); reg.register_lint_group("clippy_pedantic", vec![ + array_indexing::INDEXING_SLICING, enum_glob_use::ENUM_GLOB_USE, matches::SINGLE_MATCH_ELSE, methods::OPTION_UNWRAP_USED, diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs index 1d9492bc0ab..bcd25f5bf06 100644 --- a/tests/compile-fail/array_indexing.rs +++ b/tests/compile-fail/array_indexing.rs @@ -1,6 +1,7 @@ -#![feature(plugin)] +#![feature(inclusive_range_syntax, plugin)] #![plugin(clippy)] +#![deny(indexing_slicing)] #![deny(out_of_bounds_indexing)] #![allow(no_effect)] @@ -8,6 +9,24 @@ fn main() { let x = [1,2,3,4]; x[0]; x[3]; - x[4]; //~ERROR: const index-expr is out of bounds - x[1 << 3]; //~ERROR: const index-expr is out of bounds + x[4]; //~ERROR: indexing may panic + //~^ ERROR: const index is out of bounds + x[1 << 3]; //~ERROR: indexing may panic + //~^ ERROR: const index is out of bounds + &x[1..5]; //~ERROR: slicing may panic + //~^ ERROR: range is out of bounds + &x[0..3]; + &x[0...4]; //~ERROR: slicing may panic + //~^ ERROR: range is out of bounds + &x[..]; + &x[1..]; + &x[..4]; + &x[..5]; //~ERROR: slicing may panic + //~^ ERROR: range is out of bounds + + let y = &x; + y[0]; //~ERROR: indexing may panic + &y[1..2]; //~ERROR: slicing may panic + &y[..]; + &y[0...4]; //~ERROR: slicing may panic } -- cgit 1.4.1-3-g733a5 From 2f13c3bdefefb7947049ed51edde8db341994164 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 11 Mar 2016 22:10:40 +0100 Subject: Small nits on INDEXING_SLICING --- src/array_indexing.rs | 28 ++++++++++------------------ src/lib.rs | 2 +- tests/compile-fail/array_indexing.rs | 15 +++++---------- 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index abce04f0b77..274491b7c96 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -69,34 +69,26 @@ impl LateLintPass for ArrayIndexing { if let Ok(ConstVal::Uint(const_index)) = const_index { if size <= const_index { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); - utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); - } else { - // Index is within bounds - return; } + + return; } // Index is a constant range if let Some(range) = utils::unsugar_range(index) { let start = range.start.map(|start| - eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)); + eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)).map(|v| v.ok()); let end = range.end.map(|end| - eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)); + eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)).map(|v| v.ok()); if let Some((start, end)) = to_const_range(start, end, range.limits, size) { - if start >= size && end >= size { + if start >= size || end >= size { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); - utils::span_lint(cx, - INDEXING_SLICING, - e.span, - "slicing may panic"); - } else { - // Range is within bounds - return; } + return; } } } @@ -120,19 +112,19 @@ impl LateLintPass for ArrayIndexing { /// /// Note: we assume the start and the end of the range are unsigned, since array slicing /// works only on usize -fn to_const_range<T>(start: Option<Result<ConstVal, T>>, - end: Option<Result<ConstVal, T>>, +fn to_const_range(start: Option<Option<ConstVal>>, + end: Option<Option<ConstVal>>, limits: RangeLimits, array_size: u64) -> Option<(u64, u64)> { let start = match start { - Some(Ok(ConstVal::Uint(x))) => x, + Some(Some(ConstVal::Uint(x))) => x, Some(_) => return None, None => 0, }; let end = match end { - Some(Ok(ConstVal::Uint(x))) => { + Some(Some(ConstVal::Uint(x))) => { if limits == RangeLimits::Closed { x } else { diff --git a/src/lib.rs b/src/lib.rs index 664819b97ec..4b9d5d8c9c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ #![feature(rustc_private, collections)] #![feature(iter_arith)] #![feature(custom_attribute)] -#![allow(unknown_lints)] +#![allow(indexing_slicing, shadow_reuse, unknown_lints)] // this only exists to allow the "dogfood" integration test to work #[allow(dead_code)] diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs index bcd25f5bf06..14f3448a9f6 100644 --- a/tests/compile-fail/array_indexing.rs +++ b/tests/compile-fail/array_indexing.rs @@ -9,20 +9,15 @@ fn main() { let x = [1,2,3,4]; x[0]; x[3]; - x[4]; //~ERROR: indexing may panic - //~^ ERROR: const index is out of bounds - x[1 << 3]; //~ERROR: indexing may panic - //~^ ERROR: const index is out of bounds - &x[1..5]; //~ERROR: slicing may panic - //~^ ERROR: range is out of bounds + x[4]; //~ERROR: const index is out of bounds + x[1 << 3]; //~ERROR: const index is out of bounds + &x[1..5]; //~ERROR: range is out of bounds &x[0..3]; - &x[0...4]; //~ERROR: slicing may panic - //~^ ERROR: range is out of bounds + &x[0...4]; //~ERROR: range is out of bounds &x[..]; &x[1..]; &x[..4]; - &x[..5]; //~ERROR: slicing may panic - //~^ ERROR: range is out of bounds + &x[..5]; //~ERROR: range is out of bounds let y = &x; y[0]; //~ERROR: indexing may panic -- cgit 1.4.1-3-g733a5 From 29c0c2bb09b9b33f1e4e81db0e46bdd089dc2847 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 21 Feb 2016 20:11:32 +0100 Subject: Start implementing a configuration file --- Cargo.toml | 1 + src/conf.rs | 184 +++++++++++++++++++++++++++++++ src/lib.rs | 26 ++++- tests/compile-fail/conf_bad_arg.rs | 6 + tests/compile-fail/conf_non_existant.rs | 6 + tests/compile-fail/conf_unknown_key.rs | 6 + tests/compile-fail/conf_unknown_key.toml | 1 + 7 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 src/conf.rs create mode 100644 tests/compile-fail/conf_bad_arg.rs create mode 100644 tests/compile-fail/conf_non_existant.rs create mode 100644 tests/compile-fail/conf_unknown_key.rs create mode 100644 tests/compile-fail/conf_unknown_key.toml diff --git a/Cargo.toml b/Cargo.toml index 853815e049f..a10164b5fcf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ plugin = true regex-syntax = "0.2.2" regex_macros = { version = "0.1.28", optional = true } semver = "0.2.1" +toml = "0.1" unicode-normalization = "0.1" [dev-dependencies] diff --git a/src/conf.rs b/src/conf.rs new file mode 100644 index 00000000000..e275bd701bd --- /dev/null +++ b/src/conf.rs @@ -0,0 +1,184 @@ +use std::{fmt, fs, io}; +use std::io::Read; +use syntax::{ast, codemap, ptr}; +use syntax::parse::token; +use toml; + +/// Get the configuration file from arguments. +pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { + for arg in args { + match arg.node { + ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { + if name == &"conf_file" { + return Err(("`conf_file` must be a named value", arg.span)); + } + } + ast::MetaItemKind::NameValue(ref name, ref value) => { + if name == &"conf_file" { + return if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.clone())) + } else { + Err(("`conf_file` value must be a string", value.span)) + } + } + } + } + } + + Ok(None) +} + +/// Error from reading a configuration file. +#[derive(Debug)] +pub enum ConfError { + IoError(io::Error), + TomlError(Vec<toml::ParserError>), + TypeError(&'static str, &'static str, &'static str), + UnknownKey(String), +} + +impl fmt::Display for ConfError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ConfError::IoError(ref err) => { + err.fmt(f) + } + ConfError::TomlError(ref errs) => { + let mut first = true; + for err in errs { + if !first { + try!(", ".fmt(f)); + first = false; + } + + try!(err.fmt(f)); + } + + Ok(()) + } + ConfError::TypeError(ref key, ref expected, ref got) => { + write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) + } + ConfError::UnknownKey(ref key) => { + write!(f, "unknown key `{}`", key) + } + } + } +} + +impl From<io::Error> for ConfError { + fn from(e: io::Error) -> Self { + ConfError::IoError(e) + } +} + +macro_rules! define_Conf { + ($(($toml_name: tt, $rust_name: ident, $default: expr, $ty: ident),)+) => { + /// Type used to store lint configuration. + pub struct Conf { + $(pub $rust_name: $ty,)+ + } + + impl Default for Conf { + fn default() -> Conf { + Conf { + $($rust_name: $default,)+ + } + } + } + + impl Conf { + /// Set the property `name` (which must be the `toml` name) to the given value + #[allow(cast_sign_loss)] + fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + match name.as_str() { + $( + define_Conf!(PAT $toml_name) => { + if let Some(value) = define_Conf!(CONV $ty, value) { + self.$rust_name = value; + } + else { + return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), + stringify!($ty), + value.type_str())); + } + }, + )+ + _ => { + return Err(ConfError::UnknownKey(name)); + } + } + + Ok(()) + } + } + }; + + // hack to convert tts + (PAT $pat: pat) => { $pat }; + (EXPR $e: expr) => { $e }; + + // how to read the value? + (CONV i64, $value: expr) => { $value.as_integer() }; + (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; + (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; + (CONV StringVec, $value: expr) => {{ + let slice = $value.as_slice(); + + if let Some(slice) = slice { + if slice.iter().any(|v| v.as_str().is_none()) { + None + } + else { + Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) + } + } + else { + None + } + }}; +} + +/// To keep the `define_Conf!` macro simple +pub type StringVec = Vec<String>; + +define_Conf! { + ("blacklisted-names", blacklisted_names, vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()], StringVec), + ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25, u64), + ("too-many-arguments-threshold", too_many_arguments_threshold, 6, u64), + ("type-complexity-threshold", type_complexity_threshold, 250, u64), +} + +/// Read the `toml` configuration file. The function will ignore “File not found” errors iif +/// `!must_exist`, in which case, it will return the default configuration. +pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { + let mut conf = Conf::default(); + + let file = match fs::File::open(path) { + Ok(mut file) => { + let mut buf = String::new(); + try!(file.read_to_string(&mut buf)); + buf + } + Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { + return Ok(conf); + } + Err(err) => { + return Err(err.into()); + } + }; + + let mut parser = toml::Parser::new(&file); + let toml = if let Some(toml) = parser.parse() { + toml + } + else { + return Err(ConfError::TomlError(parser.errors)); + }; + + for (key, value) in toml { + try!(conf.set(key, value)); + } + + Ok(conf) +} diff --git a/src/lib.rs b/src/lib.rs index 4b9d5d8c9c4..f3c3564796a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,8 @@ extern crate rustc; #[macro_use] extern crate rustc_front; +extern crate toml; + // Only for the compile time checking of paths extern crate core; extern crate collections; @@ -35,6 +37,7 @@ extern crate rustc_plugin; use rustc_plugin::Registry; +mod conf; pub mod consts; #[macro_use] pub mod utils; @@ -107,6 +110,27 @@ mod reexport { #[plugin_registrar] #[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { + let conferr = match conf::conf_file(reg.args()) { + Ok(Some(file_name)) => { + conf::read_conf(&file_name, true) + } + Ok(None) => { + conf::read_conf("Clippy.toml", false) + } + Err((err, span)) => { + reg.sess.struct_span_err(span, err).emit(); + return; + } + }; + + let conf = match conferr { + Ok(conf) => conf, + Err(err) => { + reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", err)).emit(); + return; + } + }; + reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); @@ -157,7 +181,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); reg.register_late_lint_pass(box transmute::UselessTransmute); - reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(25)); + reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); reg.register_late_lint_pass(box escape::EscapePass); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); diff --git a/tests/compile-fail/conf_bad_arg.rs b/tests/compile-fail/conf_bad_arg.rs new file mode 100644 index 00000000000..68b902719f6 --- /dev/null +++ b/tests/compile-fail/conf_bad_arg.rs @@ -0,0 +1,6 @@ +// error-pattern: `conf_file` must be a named value + +#![feature(plugin)] +#![plugin(clippy(conf_file))] + +fn main() {} diff --git a/tests/compile-fail/conf_non_existant.rs b/tests/compile-fail/conf_non_existant.rs new file mode 100644 index 00000000000..13ab7f6cebf --- /dev/null +++ b/tests/compile-fail/conf_non_existant.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: No such file or directory + +#![feature(plugin)] +#![plugin(clippy(conf_file="./tests/compile-fail/non_existant_conf.toml"))] + +fn main() {} diff --git a/tests/compile-fail/conf_unknown_key.rs b/tests/compile-fail/conf_unknown_key.rs new file mode 100644 index 00000000000..02131d94d52 --- /dev/null +++ b/tests/compile-fail/conf_unknown_key.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: unknown key `foobar` + +#![feature(plugin)] +#![plugin(clippy(conf_file="./tests/compile-fail/conf_unknown_key.toml"))] + +fn main() {} diff --git a/tests/compile-fail/conf_unknown_key.toml b/tests/compile-fail/conf_unknown_key.toml new file mode 100644 index 00000000000..df298ea78d4 --- /dev/null +++ b/tests/compile-fail/conf_unknown_key.toml @@ -0,0 +1 @@ +foobar = 42 -- cgit 1.4.1-3-g733a5 From 1841804d43b1ef3e919a3e9cb7fdb4e166f8fd64 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 21 Feb 2016 21:01:30 +0100 Subject: Use configuration in the `TYPE_COMPLEXITY` lint --- src/lib.rs | 2 +- src/types.rs | 78 +++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f3c3564796a..4c0a069a090 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,7 +168,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); reg.register_late_lint_pass(box types::CastPass); - reg.register_late_lint_pass(box types::TypeComplexityPass); + reg.register_late_lint_pass(box types::TypeComplexityPass::new(conf.type_complexity_threshold)); reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); diff --git a/src/types.rs b/src/types.rs index cf90155b1fa..1aefe5a4d27 100644 --- a/src/types.rs +++ b/src/types.rs @@ -417,7 +417,17 @@ declare_lint! { } #[allow(missing_copy_implementations)] -pub struct TypeComplexityPass; +pub struct TypeComplexityPass { + threshold: u64, +} + +impl TypeComplexityPass { + pub fn new(threshold: u64) -> Self { + TypeComplexityPass { + threshold: threshold + } + } +} impl LintPass for TypeComplexityPass { fn get_lints(&self) -> LintArray { @@ -427,18 +437,18 @@ impl LintPass for TypeComplexityPass { impl LateLintPass for TypeComplexityPass { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - check_fndecl(cx, decl); + self.check_fndecl(cx, decl); } fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { // enum variants are also struct fields now - check_type(cx, &field.ty); + self.check_type(cx, &field.ty); } fn check_item(&mut self, cx: &LateContext, item: &Item) { match item.node { ItemStatic(ref ty, _, _) | - ItemConst(ref ty, _) => check_type(cx, ty), + ItemConst(ref ty, _) => self.check_type(cx, ty), // functions, enums, structs, impls and traits are covered _ => (), } @@ -447,8 +457,8 @@ impl LateLintPass for TypeComplexityPass { fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { match item.node { ConstTraitItem(ref ty, _) | - TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty), - MethodTraitItem(MethodSig { ref decl, .. }, None) => check_fndecl(cx, decl), + TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty), + MethodTraitItem(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), } @@ -457,7 +467,7 @@ impl LateLintPass for TypeComplexityPass { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { match item.node { ImplItemKind::Const(ref ty, _) | - ImplItemKind::Type(ref ty) => check_type(cx, ty), + ImplItemKind::Type(ref ty) => self.check_type(cx, ty), // methods are covered by check_fn _ => (), } @@ -465,47 +475,49 @@ impl LateLintPass for TypeComplexityPass { fn check_local(&mut self, cx: &LateContext, local: &Local) { if let Some(ref ty) = local.ty { - check_type(cx, ty); + self.check_type(cx, ty); } } } -fn check_fndecl(cx: &LateContext, decl: &FnDecl) { - for arg in &decl.inputs { - check_type(cx, &arg.ty); - } - if let Return(ref ty) = decl.output { - check_type(cx, ty); +impl TypeComplexityPass { + fn check_fndecl(&self, cx: &LateContext, decl: &FnDecl) { + for arg in &decl.inputs { + self.check_type(cx, &arg.ty); + } + if let Return(ref ty) = decl.output { + self.check_type(cx, ty); + } } -} -fn check_type(cx: &LateContext, ty: &Ty) { - if in_macro(cx, ty.span) { - return; - } - let score = { - let mut visitor = TypeComplexityVisitor { - score: 0, - nest: 1, + fn check_type(&self, cx: &LateContext, ty: &Ty) { + if in_macro(cx, ty.span) { + return; + } + let score = { + let mut visitor = TypeComplexityVisitor { + score: 0, + nest: 1, + }; + visitor.visit_ty(ty); + visitor.score }; - visitor.visit_ty(ty); - visitor.score - }; - if score > 250 { - span_lint(cx, - TYPE_COMPLEXITY, - ty.span, - "very complex type used. Consider factoring parts into `type` definitions"); + if score > self.threshold { + span_lint(cx, + TYPE_COMPLEXITY, + ty.span, + "very complex type used. Consider factoring parts into `type` definitions"); + } } } /// Walks a type and assigns a complexity score to it. struct TypeComplexityVisitor { /// total complexity score of the type - score: u32, + score: u64, /// current nesting level - nest: u32, + nest: u64, } impl<'v> Visitor<'v> for TypeComplexityVisitor { -- cgit 1.4.1-3-g733a5 From 232710cd4312abce7476de2baa21b943a9763eb4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 14:25:51 +0100 Subject: Add configuration variables to wiki --- src/conf.rs | 32 +++++++++++++++++++------------- src/lib.rs | 1 + util/update_wiki.py | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/conf.rs b/src/conf.rs index e275bd701bd..3b2a1dafad4 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -73,16 +73,16 @@ impl From<io::Error> for ConfError { } macro_rules! define_Conf { - ($(($toml_name: tt, $rust_name: ident, $default: expr, $ty: ident),)+) => { + ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { /// Type used to store lint configuration. pub struct Conf { - $(pub $rust_name: $ty,)+ + $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ } impl Default for Conf { fn default() -> Conf { Conf { - $($rust_name: $default,)+ + $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ } } } @@ -94,12 +94,12 @@ macro_rules! define_Conf { match name.as_str() { $( define_Conf!(PAT $toml_name) => { - if let Some(value) = define_Conf!(CONV $ty, value) { + if let Some(value) = define_Conf!(CONV $($ty)+, value) { self.$rust_name = value; } else { return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), - stringify!($ty), + stringify!($($ty)+), value.type_str())); } }, @@ -117,12 +117,13 @@ macro_rules! define_Conf { // hack to convert tts (PAT $pat: pat) => { $pat }; (EXPR $e: expr) => { $e }; + (TY $ty: ty) => { $ty }; // how to read the value? (CONV i64, $value: expr) => { $value.as_integer() }; (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; - (CONV StringVec, $value: expr) => {{ + (CONV Vec<String>, $value: expr) => {{ let slice = $value.as_slice(); if let Some(slice) = slice { @@ -137,16 +138,21 @@ macro_rules! define_Conf { None } }}; -} -/// To keep the `define_Conf!` macro simple -pub type StringVec = Vec<String>; + // provide a nicer syntax to declare the default value of `Vec<String>` variables + (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; + (DEFAULT $ty: ty, $e: expr) => { $e }; +} define_Conf! { - ("blacklisted-names", blacklisted_names, vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()], StringVec), - ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25, u64), - ("too-many-arguments-threshold", too_many_arguments_threshold, 6, u64), - ("type-complexity-threshold", type_complexity_threshold, 250, u64), + /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about + ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), + /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have + ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), + /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have + ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), + /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have + ("type-complexity-threshold", type_complexity_threshold, 250 => u64), } /// Read the `toml` configuration file. The function will ignore “File not found” errors iif diff --git a/src/lib.rs b/src/lib.rs index 4c0a069a090..b69fdf70c99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(type_macros)] #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] #![feature(iter_arith)] diff --git a/util/update_wiki.py b/util/update_wiki.py index d3467a41012..a10b3549a22 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -9,6 +9,8 @@ import sys level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''') +conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) +confvar_re = re.compile(r'''/// Lint: (\w+). (.*).*\n *\("([^"]*)", (?:[^,]*), (.*) => (.*)\),''') def parse_path(p="src"): @@ -16,10 +18,23 @@ def parse_path(p="src"): for f in os.listdir(p): if f.endswith(".rs"): parse_file(d, os.path.join(p, f)) - return d + return (d, parse_conf(p)) -START = 0 -LINT = 1 + +def parse_conf(p): + c = {} + with open(p + '/conf.rs') as f: + f = f.read() + + m = re.search(conf_re, f) + m = m.groups()[0] + + m = re.findall(confvar_re, m) + + for (lint, doc, name, default, ty) in m: + c[lint.lower()] = (name, ty, doc, default) + + return c def parse_file(d, f): @@ -85,8 +100,14 @@ template = """\n# `%s` %s""" +conf_template = """ +**Configuration:** This lint has the following configuration variables: -def write_wiki_page(d, f): +* `%s: %s`: %s (defaults to `%s`). +""" + + +def write_wiki_page(d, c, f): keys = list(d.keys()) keys.sort() with open(f, "w") as w: @@ -102,8 +123,11 @@ def write_wiki_page(d, f): for k in keys: w.write(template % (k, d[k][0], "".join(d[k][1]))) + if k in c: + w.write(conf_template % c[k]) + -def check_wiki_page(d, f): +def check_wiki_page(d, c, f): errors = [] with open(f) as w: for line in w: @@ -122,11 +146,11 @@ def check_wiki_page(d, f): def main(): - d = parse_path() + (d, c) = parse_path() if "-c" in sys.argv: - check_wiki_page(d, "../rust-clippy.wiki/Home.md") + check_wiki_page(d, c, "../rust-clippy.wiki/Home.md") else: - write_wiki_page(d, "../rust-clippy.wiki/Home.md") + write_wiki_page(d, c, "../rust-clippy.wiki/Home.md") if __name__ == "__main__": main() -- cgit 1.4.1-3-g733a5 From a3031e34f9db46f172d955cec607c6f4ef226ab4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 15:42:24 +0100 Subject: Add a `BLACKLISTED_NAME` lint --- README.md | 3 +- src/blacklisted_name.rs | 45 ++++++++++++++++++++++ src/lib.rs | 3 ++ tests/compile-fail/blacklisted_name.rs | 26 +++++++++++++ tests/compile-fail/box_vec.rs | 1 + tests/compile-fail/conf_french_blacklisted_name.rs | 26 +++++++++++++ .../compile-fail/conf_french_blacklisted_name.toml | 1 + tests/compile-fail/copies.rs | 1 + tests/compile-fail/dlist.rs | 3 +- tests/compile-fail/methods.rs | 2 +- tests/compile-fail/mut_reference.rs | 12 +++--- tests/compile-fail/used_underscore_binding.rs | 2 + 12 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 src/blacklisted_name.rs create mode 100755 tests/compile-fail/blacklisted_name.rs create mode 100755 tests/compile-fail/conf_french_blacklisted_name.rs create mode 100644 tests/compile-fail/conf_french_blacklisted_name.toml diff --git a/README.md b/README.md index 48a106e3591..1b18a62f7a4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A collection of lints to catch common mistakes and improve your Rust code. [Jump to link with clippy-service](#link-with-clippy-service) ##Lints -There are 134 lints included in this crate: +There are 135 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -19,6 +19,7 @@ name [almost_swapped](https://github.com/Manishearth/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) +[blacklisted_name](https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` [block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` [bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` diff --git a/src/blacklisted_name.rs b/src/blacklisted_name.rs new file mode 100644 index 00000000000..2d62cc44d26 --- /dev/null +++ b/src/blacklisted_name.rs @@ -0,0 +1,45 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use utils::span_lint; + +/// **What it does:** This lints about usage of blacklisted names. +/// +/// **Why is this bad?** These names are usually placeholder names and should be avoided. +/// +/// **Known problems:** None. +/// +/// **Example:** `let foo = 3.14;` +declare_lint! { + pub BLACKLISTED_NAME, + Warn, + "usage of a blacklisted/placeholder name" +} + +#[derive(Clone, Debug)] +pub struct BlackListedName { + blacklist: Vec<String>, +} + +impl BlackListedName { + pub fn new(blacklist: Vec<String>) -> BlackListedName { + BlackListedName { + blacklist: blacklist + } + } +} + +impl LintPass for BlackListedName { + fn get_lints(&self) -> LintArray { + lint_array!(BLACKLISTED_NAME) + } +} + +impl LateLintPass for BlackListedName { + fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { + if let PatKind::Ident(_, ref ident, _) = pat.node { + if self.blacklist.iter().any(|s| s == &*ident.node.name.as_str()) { + span_lint(cx, BLACKLISTED_NAME, pat.span, &format!("use of a blacklisted/placeholder name `{}`", ident.node.name)); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index b69fdf70c99..66ae815d7e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,7 @@ pub mod approx_const; pub mod array_indexing; pub mod attrs; pub mod bit_mask; +pub mod blacklisted_name; pub mod block_in_if_condition; pub mod collapsible_if; pub mod copies; @@ -204,6 +205,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); + reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -236,6 +238,7 @@ pub fn plugin_registrar(reg: &mut Registry) { attrs::INLINE_ALWAYS, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, + blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, diff --git a/tests/compile-fail/blacklisted_name.rs b/tests/compile-fail/blacklisted_name.rs new file mode 100755 index 00000000000..efcb810a30e --- /dev/null +++ b/tests/compile-fail/blacklisted_name.rs @@ -0,0 +1,26 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(dead_code)] +#![allow(single_match)] +#![allow(unused_variables)] +#![deny(blacklisted_name)] + +fn test(foo: ()) {} //~ERROR use of a blacklisted/placeholder name `foo` + +fn main() { + let foo = 42; //~ERROR use of a blacklisted/placeholder name `foo` + let bar = 42; //~ERROR use of a blacklisted/placeholder name `bar` + let baz = 42; //~ERROR use of a blacklisted/placeholder name `baz` + + let barb = 42; + let barbaric = 42; + + match (42, Some(1337), Some(0)) { + (foo, Some(bar), baz @ Some(_)) => (), + //~^ ERROR use of a blacklisted/placeholder name `foo` + //~| ERROR use of a blacklisted/placeholder name `bar` + //~| ERROR use of a blacklisted/placeholder name `baz` + _ => (), + } +} diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs index 044e7dffa79..071945a81b2 100644 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -3,6 +3,7 @@ #![deny(clippy)] #![allow(boxed_local)] +#![allow(blacklisted_name)] macro_rules! boxit { ($init:expr, $x:ty) => { diff --git a/tests/compile-fail/conf_french_blacklisted_name.rs b/tests/compile-fail/conf_french_blacklisted_name.rs new file mode 100755 index 00000000000..b7e29eeef1f --- /dev/null +++ b/tests/compile-fail/conf_french_blacklisted_name.rs @@ -0,0 +1,26 @@ +#![feature(plugin)] +#![plugin(clippy(conf_file="./tests/compile-fail/conf_french_blacklisted_name.toml"))] + +#![allow(dead_code)] +#![allow(single_match)] +#![allow(unused_variables)] +#![deny(blacklisted_name)] + +fn test(toto: ()) {} //~ERROR use of a blacklisted/placeholder name `toto` + +fn main() { + let toto = 42; //~ERROR use of a blacklisted/placeholder name `toto` + let tata = 42; //~ERROR use of a blacklisted/placeholder name `tata` + let titi = 42; //~ERROR use of a blacklisted/placeholder name `titi` + + let tatab = 42; + let tatatataic = 42; + + match (42, Some(1337), Some(0)) { + (toto, Some(tata), titi @ Some(_)) => (), + //~^ ERROR use of a blacklisted/placeholder name `toto` + //~| ERROR use of a blacklisted/placeholder name `tata` + //~| ERROR use of a blacklisted/placeholder name `titi` + _ => (), + } +} diff --git a/tests/compile-fail/conf_french_blacklisted_name.toml b/tests/compile-fail/conf_french_blacklisted_name.toml new file mode 100644 index 00000000000..6abe5a3bbc2 --- /dev/null +++ b/tests/compile-fail/conf_french_blacklisted_name.toml @@ -0,0 +1 @@ +blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index c1e1ba68b3e..66457e77f47 100755 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -6,6 +6,7 @@ #![allow(needless_return)] #![allow(unused_variables)] #![allow(cyclomatic_complexity)] +#![allow(blacklisted_name)] fn bar<T>(_: T) {} fn foo() -> bool { unimplemented!() } diff --git a/tests/compile-fail/dlist.rs b/tests/compile-fail/dlist.rs index a800c045a50..e7919619121 100644 --- a/tests/compile-fail/dlist.rs +++ b/tests/compile-fail/dlist.rs @@ -6,8 +6,7 @@ extern crate collections; use collections::linked_list::LinkedList; -pub fn test(foo: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList! - println!("{:?}", foo) +pub fn test(_: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList! } fn main(){ diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 46f14d5d921..344016a3b90 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(clippy, clippy_pedantic)] -#![allow(unused, print_stdout, non_ascii_literal, new_without_default)] +#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/compile-fail/mut_reference.rs b/tests/compile-fail/mut_reference.rs index 1d81ed14e4e..0bb59a318b8 100644 --- a/tests/compile-fail/mut_reference.rs +++ b/tests/compile-fail/mut_reference.rs @@ -20,8 +20,8 @@ impl MyStruct { fn main() { // Functions takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference - let foo: fn(&i32) = takes_an_immutable_reference; - foo(&mut 42); //~ERROR The function/method "foo" doesn't need a mutable reference + let as_ptr: fn(&i32) = takes_an_immutable_reference; + as_ptr(&mut 42); //~ERROR The function/method "as_ptr" doesn't need a mutable reference // Methods let my_struct = MyStruct; @@ -32,12 +32,12 @@ fn main() { // Functions takes_an_immutable_reference(&42); - let foo: fn(&i32) = takes_an_immutable_reference; - foo(&42); + let as_ptr: fn(&i32) = takes_an_immutable_reference; + as_ptr(&42); takes_a_mutable_reference(&mut 42); - let foo: fn(&mut i32) = takes_a_mutable_reference; - foo(&mut 42); + let as_ptr: fn(&mut i32) = takes_a_mutable_reference; + as_ptr(&mut 42); let a = &mut 42; takes_an_immutable_reference(a); diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 281d92c46df..6bf4324e623 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -2,6 +2,8 @@ #![plugin(clippy)] #![deny(clippy)] +#![allow(blacklisted_name)] + /// Test that we lint if we use a binding with a single leading underscore fn prefix_underscore(_foo: u32) -> u32 { _foo + 1 //~ ERROR used binding which is prefixed with an underscore -- cgit 1.4.1-3-g733a5 From 578750aae145c59ce7a175c42ee1a6a7a32831e9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 22 Feb 2016 15:50:40 +0100 Subject: Document the configuration file --- README.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b18a62f7a4..97e0a075dd2 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,12 @@ A collection of lints to catch common mistakes and improve your Rust code. -[Jump to usage instructions](#usage) - -[Jump to link with clippy-service](#link-with-clippy-service) +Table of contents: +* [Lint list](#lints) +* [Usage instructions](#usage) +* [Configuration](#configuration) +* [*clippy-service*](#link-with-clippy-service) +* [License](#license) ##Lints There are 135 lints included in this crate: @@ -231,6 +234,22 @@ And, in your `main.rs` or `lib.rs`: #![cfg_attr(feature="clippy", plugin(clippy))] ``` +## Configuration +Some lints can be configured in a `Clippy.toml` file. It contains basic `variable = value` mapping eg. + +```toml +blacklisted-names = ["toto", "tata", "titi"] +cyclomatic-complexity-threshold = 30 +``` + +See the wiki for more information about which lints can be configured and the +meaning of the variables. + +You can also specify the path to the configuration file with: +```rust +#![plugin(clippy(conf_file="path/to/clippy's/configuration"))] +``` + ##Link with clippy service `clippy-service` is a rust web initiative providing `rust-clippy` as a web service. -- cgit 1.4.1-3-g733a5 From c7db94aee6996b0b707cb8c0b912056c1ede6011 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 29 Feb 2016 17:48:20 +0100 Subject: Rustfmt --- src/blacklisted_name.rs | 9 +++++---- src/conf.rs | 13 ++++--------- src/types.rs | 4 +--- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/blacklisted_name.rs b/src/blacklisted_name.rs index 2d62cc44d26..25c0bac2c37 100644 --- a/src/blacklisted_name.rs +++ b/src/blacklisted_name.rs @@ -22,9 +22,7 @@ pub struct BlackListedName { impl BlackListedName { pub fn new(blacklist: Vec<String>) -> BlackListedName { - BlackListedName { - blacklist: blacklist - } + BlackListedName { blacklist: blacklist } } } @@ -38,7 +36,10 @@ impl LateLintPass for BlackListedName { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatKind::Ident(_, ref ident, _) = pat.node { if self.blacklist.iter().any(|s| s == &*ident.node.name.as_str()) { - span_lint(cx, BLACKLISTED_NAME, pat.span, &format!("use of a blacklisted/placeholder name `{}`", ident.node.name)); + span_lint(cx, + BLACKLISTED_NAME, + pat.span, + &format!("use of a blacklisted/placeholder name `{}`", ident.node.name)); } } } diff --git a/src/conf.rs b/src/conf.rs index 3b2a1dafad4..0ceede3b5b8 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -19,7 +19,7 @@ pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::Interne Ok(Some(file.clone())) } else { Err(("`conf_file` value must be a string", value.span)) - } + }; } } } @@ -40,9 +40,7 @@ pub enum ConfError { impl fmt::Display for ConfError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ConfError::IoError(ref err) => { - err.fmt(f) - } + ConfError::IoError(ref err) => err.fmt(f), ConfError::TomlError(ref errs) => { let mut first = true; for err in errs { @@ -59,9 +57,7 @@ impl fmt::Display for ConfError { ConfError::TypeError(ref key, ref expected, ref got) => { write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) } - ConfError::UnknownKey(ref key) => { - write!(f, "unknown key `{}`", key) - } + ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), } } } @@ -177,8 +173,7 @@ pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { let mut parser = toml::Parser::new(&file); let toml = if let Some(toml) = parser.parse() { toml - } - else { + } else { return Err(ConfError::TomlError(parser.errors)); }; diff --git a/src/types.rs b/src/types.rs index 1aefe5a4d27..e64bf010549 100644 --- a/src/types.rs +++ b/src/types.rs @@ -423,9 +423,7 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { - TypeComplexityPass { - threshold: threshold - } + TypeComplexityPass { threshold: threshold } } } -- cgit 1.4.1-3-g733a5 From 403c54ec5bfa6f2d944dff5a1b34fda3344dec66 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 6 Mar 2016 14:40:25 +0100 Subject: White-list `third-party` in conf files --- src/conf.rs | 4 ++++ tests/compile-fail/conf_unknown_key.toml | 5 +++++ tests/run-pass/conf_unknown_key.rs | 4 ++++ tests/run-pass/conf_unknown_key.toml | 3 +++ 4 files changed, 16 insertions(+) create mode 100644 tests/run-pass/conf_unknown_key.rs create mode 100644 tests/run-pass/conf_unknown_key.toml diff --git a/src/conf.rs b/src/conf.rs index 0ceede3b5b8..93caa1edca3 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -100,6 +100,10 @@ macro_rules! define_Conf { } }, )+ + "third-party" => { + // for external tools such as clippy-service + return Ok(()); + } _ => { return Err(ConfError::UnknownKey(name)); } diff --git a/tests/compile-fail/conf_unknown_key.toml b/tests/compile-fail/conf_unknown_key.toml index df298ea78d4..554b87cc50b 100644 --- a/tests/compile-fail/conf_unknown_key.toml +++ b/tests/compile-fail/conf_unknown_key.toml @@ -1 +1,6 @@ +# that one is an error foobar = 42 + +# that one is white-listed +[third-party] +clippy-feature = "nightly" diff --git a/tests/run-pass/conf_unknown_key.rs b/tests/run-pass/conf_unknown_key.rs new file mode 100644 index 00000000000..bb186d47630 --- /dev/null +++ b/tests/run-pass/conf_unknown_key.rs @@ -0,0 +1,4 @@ +#![feature(plugin)] +#![plugin(clippy(conf_file="./tests/run-pass/conf_unknown_key.toml"))] + +fn main() {} diff --git a/tests/run-pass/conf_unknown_key.toml b/tests/run-pass/conf_unknown_key.toml new file mode 100644 index 00000000000..9f87de20baf --- /dev/null +++ b/tests/run-pass/conf_unknown_key.toml @@ -0,0 +1,3 @@ +# this is ignored by Clippy, but allowed for other tools like clippy-service +[third-party] +clippy-feature = "nightly" -- cgit 1.4.1-3-g733a5 From d118b27abb50fef41f7a9510aa9e3741ac036370 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 6 Mar 2016 15:17:51 +0100 Subject: mv src/conf.rs src/utils --- src/conf.rs | 189 ------------------------------------------------------ src/lib.rs | 7 +- src/utils/conf.rs | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 1 + 4 files changed, 193 insertions(+), 193 deletions(-) delete mode 100644 src/conf.rs create mode 100644 src/utils/conf.rs diff --git a/src/conf.rs b/src/conf.rs deleted file mode 100644 index 93caa1edca3..00000000000 --- a/src/conf.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::{fmt, fs, io}; -use std::io::Read; -use syntax::{ast, codemap, ptr}; -use syntax::parse::token; -use toml; - -/// Get the configuration file from arguments. -pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { - for arg in args { - match arg.node { - ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { - if name == &"conf_file" { - return Err(("`conf_file` must be a named value", arg.span)); - } - } - ast::MetaItemKind::NameValue(ref name, ref value) => { - if name == &"conf_file" { - return if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.clone())) - } else { - Err(("`conf_file` value must be a string", value.span)) - }; - } - } - } - } - - Ok(None) -} - -/// Error from reading a configuration file. -#[derive(Debug)] -pub enum ConfError { - IoError(io::Error), - TomlError(Vec<toml::ParserError>), - TypeError(&'static str, &'static str, &'static str), - UnknownKey(String), -} - -impl fmt::Display for ConfError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ConfError::IoError(ref err) => err.fmt(f), - ConfError::TomlError(ref errs) => { - let mut first = true; - for err in errs { - if !first { - try!(", ".fmt(f)); - first = false; - } - - try!(err.fmt(f)); - } - - Ok(()) - } - ConfError::TypeError(ref key, ref expected, ref got) => { - write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) - } - ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), - } - } -} - -impl From<io::Error> for ConfError { - fn from(e: io::Error) -> Self { - ConfError::IoError(e) - } -} - -macro_rules! define_Conf { - ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { - /// Type used to store lint configuration. - pub struct Conf { - $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ - } - - impl Default for Conf { - fn default() -> Conf { - Conf { - $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ - } - } - } - - impl Conf { - /// Set the property `name` (which must be the `toml` name) to the given value - #[allow(cast_sign_loss)] - fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { - match name.as_str() { - $( - define_Conf!(PAT $toml_name) => { - if let Some(value) = define_Conf!(CONV $($ty)+, value) { - self.$rust_name = value; - } - else { - return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), - stringify!($($ty)+), - value.type_str())); - } - }, - )+ - "third-party" => { - // for external tools such as clippy-service - return Ok(()); - } - _ => { - return Err(ConfError::UnknownKey(name)); - } - } - - Ok(()) - } - } - }; - - // hack to convert tts - (PAT $pat: pat) => { $pat }; - (EXPR $e: expr) => { $e }; - (TY $ty: ty) => { $ty }; - - // how to read the value? - (CONV i64, $value: expr) => { $value.as_integer() }; - (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; - (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; - (CONV Vec<String>, $value: expr) => {{ - let slice = $value.as_slice(); - - if let Some(slice) = slice { - if slice.iter().any(|v| v.as_str().is_none()) { - None - } - else { - Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) - } - } - else { - None - } - }}; - - // provide a nicer syntax to declare the default value of `Vec<String>` variables - (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; - (DEFAULT $ty: ty, $e: expr) => { $e }; -} - -define_Conf! { - /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about - ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), - /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have - ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), - /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have - ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), - /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have - ("type-complexity-threshold", type_complexity_threshold, 250 => u64), -} - -/// Read the `toml` configuration file. The function will ignore “File not found” errors iif -/// `!must_exist`, in which case, it will return the default configuration. -pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { - let mut conf = Conf::default(); - - let file = match fs::File::open(path) { - Ok(mut file) => { - let mut buf = String::new(); - try!(file.read_to_string(&mut buf)); - buf - } - Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { - return Ok(conf); - } - Err(err) => { - return Err(err.into()); - } - }; - - let mut parser = toml::Parser::new(&file); - let toml = if let Some(toml) = parser.parse() { - toml - } else { - return Err(ConfError::TomlError(parser.errors)); - }; - - for (key, value) in toml { - try!(conf.set(key, value)); - } - - Ok(conf) -} diff --git a/src/lib.rs b/src/lib.rs index 66ae815d7e0..a7fe2c1aab3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,6 @@ extern crate rustc_plugin; use rustc_plugin::Registry; -mod conf; pub mod consts; #[macro_use] pub mod utils; @@ -112,12 +111,12 @@ mod reexport { #[plugin_registrar] #[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { - let conferr = match conf::conf_file(reg.args()) { + let conferr = match utils::conf::conf_file(reg.args()) { Ok(Some(file_name)) => { - conf::read_conf(&file_name, true) + utils::conf::read_conf(&file_name, true) } Ok(None) => { - conf::read_conf("Clippy.toml", false) + utils::conf::read_conf("Clippy.toml", false) } Err((err, span)) => { reg.sess.struct_span_err(span, err).emit(); diff --git a/src/utils/conf.rs b/src/utils/conf.rs new file mode 100644 index 00000000000..93caa1edca3 --- /dev/null +++ b/src/utils/conf.rs @@ -0,0 +1,189 @@ +use std::{fmt, fs, io}; +use std::io::Read; +use syntax::{ast, codemap, ptr}; +use syntax::parse::token; +use toml; + +/// Get the configuration file from arguments. +pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { + for arg in args { + match arg.node { + ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { + if name == &"conf_file" { + return Err(("`conf_file` must be a named value", arg.span)); + } + } + ast::MetaItemKind::NameValue(ref name, ref value) => { + if name == &"conf_file" { + return if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.clone())) + } else { + Err(("`conf_file` value must be a string", value.span)) + }; + } + } + } + } + + Ok(None) +} + +/// Error from reading a configuration file. +#[derive(Debug)] +pub enum ConfError { + IoError(io::Error), + TomlError(Vec<toml::ParserError>), + TypeError(&'static str, &'static str, &'static str), + UnknownKey(String), +} + +impl fmt::Display for ConfError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ConfError::IoError(ref err) => err.fmt(f), + ConfError::TomlError(ref errs) => { + let mut first = true; + for err in errs { + if !first { + try!(", ".fmt(f)); + first = false; + } + + try!(err.fmt(f)); + } + + Ok(()) + } + ConfError::TypeError(ref key, ref expected, ref got) => { + write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) + } + ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), + } + } +} + +impl From<io::Error> for ConfError { + fn from(e: io::Error) -> Self { + ConfError::IoError(e) + } +} + +macro_rules! define_Conf { + ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { + /// Type used to store lint configuration. + pub struct Conf { + $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ + } + + impl Default for Conf { + fn default() -> Conf { + Conf { + $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ + } + } + } + + impl Conf { + /// Set the property `name` (which must be the `toml` name) to the given value + #[allow(cast_sign_loss)] + fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + match name.as_str() { + $( + define_Conf!(PAT $toml_name) => { + if let Some(value) = define_Conf!(CONV $($ty)+, value) { + self.$rust_name = value; + } + else { + return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), + stringify!($($ty)+), + value.type_str())); + } + }, + )+ + "third-party" => { + // for external tools such as clippy-service + return Ok(()); + } + _ => { + return Err(ConfError::UnknownKey(name)); + } + } + + Ok(()) + } + } + }; + + // hack to convert tts + (PAT $pat: pat) => { $pat }; + (EXPR $e: expr) => { $e }; + (TY $ty: ty) => { $ty }; + + // how to read the value? + (CONV i64, $value: expr) => { $value.as_integer() }; + (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; + (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; + (CONV Vec<String>, $value: expr) => {{ + let slice = $value.as_slice(); + + if let Some(slice) = slice { + if slice.iter().any(|v| v.as_str().is_none()) { + None + } + else { + Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) + } + } + else { + None + } + }}; + + // provide a nicer syntax to declare the default value of `Vec<String>` variables + (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; + (DEFAULT $ty: ty, $e: expr) => { $e }; +} + +define_Conf! { + /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about + ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), + /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have + ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), + /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have + ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), + /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have + ("type-complexity-threshold", type_complexity_threshold, 250 => u64), +} + +/// Read the `toml` configuration file. The function will ignore “File not found” errors iif +/// `!must_exist`, in which case, it will return the default configuration. +pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { + let mut conf = Conf::default(); + + let file = match fs::File::open(path) { + Ok(mut file) => { + let mut buf = String::new(); + try!(file.read_to_string(&mut buf)); + buf + } + Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { + return Ok(conf); + } + Err(err) => { + return Err(err.into()); + } + }; + + let mut parser = toml::Parser::new(&file); + let toml = if let Some(toml) = parser.parse() { + toml + } else { + return Err(ConfError::TomlError(parser.errors)); + }; + + for (key, value) in toml { + try!(conf.set(key, value)); + } + + Ok(conf) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 625e8da197d..feeb70126ea 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -14,6 +14,7 @@ use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +pub mod conf; mod hir; pub use self::hir::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec<P<Expr>>; -- cgit 1.4.1-3-g733a5 From 95e582a338068a840d0d5a9be6ae4b2b9c93c053 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 6 Mar 2016 15:48:56 +0100 Subject: Don’t make conf errors fatal errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib.rs | 38 ++++++++++++++++++++++---------------- src/utils/conf.rs | 25 ++++++++++++++++++------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a7fe2c1aab3..1088e4bc139 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,24 +111,30 @@ mod reexport { #[plugin_registrar] #[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { - let conferr = match utils::conf::conf_file(reg.args()) { - Ok(Some(file_name)) => { - utils::conf::read_conf(&file_name, true) - } - Ok(None) => { - utils::conf::read_conf("Clippy.toml", false) + let conf = match utils::conf::conf_file(reg.args()) { + Ok(file_name) => { + // if the user specified a file, it must exist, otherwise default to `Clippy.toml` but + // do not require the file to exist + let (ref file_name, must_exist) = if let Some(ref file_name) = file_name { + (&**file_name, true) + } else { + ("Clippy.toml", false) + }; + + let (conf, errors) = utils::conf::read_conf(&file_name, must_exist); + + // all conf errors are non-fatal, we just use the default conf in case of error + for error in errors { + reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", error)).emit(); + } + + conf } Err((err, span)) => { - reg.sess.struct_span_err(span, err).emit(); - return; - } - }; - - let conf = match conferr { - Ok(conf) => conf, - Err(err) => { - reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", err)).emit(); - return; + reg.sess.struct_span_err(span, err) + .span_note(span, "Clippy will use defaulf configuration") + .emit(); + utils::conf::Conf::default() } }; diff --git a/src/utils/conf.rs b/src/utils/conf.rs index 93caa1edca3..8c36570c833 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -157,20 +157,28 @@ define_Conf! { /// Read the `toml` configuration file. The function will ignore “File not found” errors iif /// `!must_exist`, in which case, it will return the default configuration. -pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { +/// In case of error, the function tries to continue as much as possible. +pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { let mut conf = Conf::default(); + let mut errors = Vec::new(); let file = match fs::File::open(path) { Ok(mut file) => { let mut buf = String::new(); - try!(file.read_to_string(&mut buf)); + + if let Err(err) = file.read_to_string(&mut buf) { + errors.push(err.into()); + return (conf, errors); + } + buf } Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { - return Ok(conf); + return (conf, errors); } Err(err) => { - return Err(err.into()); + errors.push(err.into()); + return (conf, errors); } }; @@ -178,12 +186,15 @@ pub fn read_conf(path: &str, must_exist: bool) -> Result<Conf, ConfError> { let toml = if let Some(toml) = parser.parse() { toml } else { - return Err(ConfError::TomlError(parser.errors)); + errors.push(ConfError::TomlError(parser.errors)); + return (conf, errors); }; for (key, value) in toml { - try!(conf.set(key, value)); + if let Err(err) = conf.set(key, value) { + errors.push(err); + } } - Ok(conf) + (conf, errors) } -- cgit 1.4.1-3-g733a5 From aa4daea3646f1ff34362f6f52a6881fab91190a6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 9 Mar 2016 00:48:10 +0100 Subject: Lint function with too many arguments --- README.md | 3 +- src/functions.rs | 75 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/utils/conf.rs | 2 +- tests/compile-fail/functions.rs | 33 ++++++++++++++++++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/functions.rs create mode 100755 tests/compile-fail/functions.rs diff --git a/README.md b/README.md index 97e0a075dd2..93edf4a81fa 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 135 lints included in this crate: +There are 136 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -130,6 +130,7 @@ name [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[too_many_arguments](https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions diff --git a/src/functions.rs b/src/functions.rs new file mode 100644 index 00000000000..5ac5aae51a4 --- /dev/null +++ b/src/functions.rs @@ -0,0 +1,75 @@ +use rustc::lint::*; +use rustc_front::hir; +use rustc_front::intravisit; +use syntax::ast; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** Check for functions with too many parameters. +/// +/// **Why is this bad?** Functions with lots of parameters are considered bad style and reduce +/// readability (“what does the 5th parameter means?”). Consider grouping some parameters into a +/// new type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ``` +/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { .. } +/// ``` +declare_lint! { + pub TOO_MANY_ARGUMENTS, + Warn, + "functions with too many arguments" +} + +#[derive(Copy,Clone)] +pub struct Functions { + threshold: u64, +} + +impl Functions { + pub fn new(threshold: u64) -> Functions { + Functions { + threshold: threshold + } + } +} + +impl LintPass for Functions { + fn get_lints(&self) -> LintArray { + lint_array!(TOO_MANY_ARGUMENTS) + } +} + +impl LateLintPass for Functions { + fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) { + use rustc::front::map::Node::*; + + if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { + match item.node { + hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..) => return, + _ => (), + } + } + + self.check_arg_number(cx, decl, span); + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { + if let hir::MethodTraitItem(ref sig, _) = item.node { + self.check_arg_number(cx, &sig.decl, item.span); + } + } +} + +impl Functions { + fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { + let args = decl.inputs.len() as u64; + if args > self.threshold { + span_lint(cx, TOO_MANY_ARGUMENTS, span, + &format!("this function has to many arguments ({}/{})", args, self.threshold)); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 1088e4bc139..d65294b56b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,7 @@ pub mod escape; pub mod eta_reduction; pub mod format; pub mod formatting; +pub mod functions; pub mod identity_op; pub mod if_not_else; pub mod items_after_statements; @@ -211,6 +212,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); + reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -263,6 +265,7 @@ pub fn plugin_registrar(reg: &mut Registry) { format::USELESS_FORMAT, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, + functions::TOO_MANY_ARGUMENTS, identity_op::IDENTITY_OP, if_not_else::IF_NOT_ELSE, items_after_statements::ITEMS_AFTER_STATEMENTS, diff --git a/src/utils/conf.rs b/src/utils/conf.rs index 8c36570c833..6636e30ab38 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -150,7 +150,7 @@ define_Conf! { /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have - ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), + ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have ("type-complexity-threshold", type_complexity_threshold, 250 => u64), } diff --git a/tests/compile-fail/functions.rs b/tests/compile-fail/functions.rs new file mode 100755 index 00000000000..d3d5eee335a --- /dev/null +++ b/tests/compile-fail/functions.rs @@ -0,0 +1,33 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(clippy)] +#![allow(dead_code)] + +fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} + +fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { + //~^ ERROR: this function has to many arguments (8/7) +} + +trait Foo { + fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool); + fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); + //~^ ERROR: this function has to many arguments (8/7) +} + +struct Bar; + +impl Bar { + fn good_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} + fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} + //~^ ERROR: this function has to many arguments (8/7) +} + +// ok, we don’t want to warn implementations +impl Foo for Bar { + fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} + fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 14dcb60bf8c68dda34bb22894534f4d9b83e60df Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 9 Mar 2016 11:48:55 +0100 Subject: s/Clippy.toml/clippy.toml --- README.md | 2 +- src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 93edf4a81fa..52223ef097b 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ And, in your `main.rs` or `lib.rs`: ``` ## Configuration -Some lints can be configured in a `Clippy.toml` file. It contains basic `variable = value` mapping eg. +Some lints can be configured in a `clippy.toml` file. It contains basic `variable = value` mapping eg. ```toml blacklisted-names = ["toto", "tata", "titi"] diff --git a/src/lib.rs b/src/lib.rs index d65294b56b8..f5a3598a1ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,12 +114,12 @@ mod reexport { pub fn plugin_registrar(reg: &mut Registry) { let conf = match utils::conf::conf_file(reg.args()) { Ok(file_name) => { - // if the user specified a file, it must exist, otherwise default to `Clippy.toml` but + // if the user specified a file, it must exist, otherwise default to `clippy.toml` but // do not require the file to exist let (ref file_name, must_exist) = if let Some(ref file_name) = file_name { (&**file_name, true) } else { - ("Clippy.toml", false) + ("clippy.toml", false) }; let (conf, errors) = utils::conf::read_conf(&file_name, must_exist); -- cgit 1.4.1-3-g733a5 From 04d81799a22f7a3e8138fae806502b830b647628 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 12 Mar 2016 21:23:35 +0100 Subject: Dogfood --- src/utils/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 625e8da197d..ee2e2d7206f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -383,14 +383,14 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { let x = s.lines() .skip(ignore_first as usize) .filter_map(|l| { - if l.len() > 0 { + if l.is_empty() { + None + } else { // ignore empty lines Some(l.char_indices() .find(|&(_, x)| x != ch) .unwrap_or((l.len(), ch)) .0) - } else { - None } }) .min() @@ -399,7 +399,7 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { Cow::Owned(s.lines() .enumerate() .map(|(i, l)| { - if (ignore_first && i == 0) || l.len() == 0 { + if (ignore_first && i == 0) || l.is_empty() { l } else { l.split_at(x).1 -- cgit 1.4.1-3-g733a5 From 7eef989ff4859f9b551b3905f2bf30c6ff113872 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 12 Mar 2016 21:12:35 +0100 Subject: Add `str` to types considered by `len_zero` --- src/len_zero.rs | 2 +- tests/compile-fail/len_zero.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 548a3d92c2c..e61c77adf24 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -198,7 +198,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { } ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), - ty::TyArray(..) => true, + ty::TyArray(..) | ty::TyStr => true, _ => false, } } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 9814a1c2d7d..5168f80b856 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -76,6 +76,12 @@ fn main() { println!("This should not happen!"); } + if "".len() == 0 { + //~^ERROR length comparison to zero + //~|HELP consider using `is_empty` + //~|SUGGESTION "".is_empty() + } + let y = One; if y.len() == 0 { //no error because One does not have .is_empty() println!("This should not happen either!"); -- cgit 1.4.1-3-g733a5 From 0774b203f4a9a46d91ea4edfab89e7552382c2c6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 12 Mar 2016 21:23:01 +0100 Subject: Fix false-positive in `panic_params` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It might still have false positives, but it’s even less likely. --- src/panic.rs | 3 ++- tests/compile-fail/panic.rs | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/panic.rs b/src/panic.rs index 60a3ce1a461..7dbcf2a5b30 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -37,7 +37,8 @@ impl LateLintPass for PanicPass { match_path(path, &BEGIN_UNWIND), let ExprLit(ref lit) = params[0].node, let LitKind::Str(ref string, _) = lit.node, - string.contains('{'), + let Some(par) = string.find('{'), + string[par..].contains('}'), let Some(sp) = cx.sess().codemap() .with_expn_info(expr.span.expn_id, |info| info.map(|i| i.call_site)) diff --git a/tests/compile-fail/panic.rs b/tests/compile-fail/panic.rs index 36427f4330b..38fe5aa2c0f 100644 --- a/tests/compile-fail/panic.rs +++ b/tests/compile-fail/panic.rs @@ -4,10 +4,14 @@ #[deny(panic_params)] fn missing() { - panic!("{}"); //~ERROR: You probably are missing some parameter + if true { + panic!("{}"); //~ERROR: You probably are missing some parameter + } else { + panic!("{:?}"); //~ERROR: You probably are missing some parameter + } } -fn ok_sigle() { +fn ok_single() { panic!("foo bar"); } @@ -15,8 +19,18 @@ fn ok_multiple() { panic!("{}", "This is {ok}"); } +fn ok_bracket() { + // the match is just here because of #759, it serves no other purpose for the lint + match 42 { + 1337 => panic!("{so is this"), + 666 => panic!("so is this}"), + _ => panic!("}so is that{"), + } +} + fn main() { missing(); - ok_sigle(); + ok_single(); ok_multiple(); + ok_bracket(); } -- cgit 1.4.1-3-g733a5 From 34d57c5247a733129e1e2b00a31651700b369e68 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 13 Mar 2016 01:30:20 +0100 Subject: Bump to 0.0.51 It fixes a false positive in mustache. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 853815e049f..cb9ad5ffedc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.50" +version = "0.0.51" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From d5a01e8789ff46e4f35bf48273c274b5c5effd31 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 17:24:55 +0100 Subject: prevent cc lint from panicking on unreachable code --- src/cyclomatic_complexity.rs | 4 ++++ tests/compile-fail/cyclomatic_complexity.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index bc13576fe3b..a03a42f2bc0 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -47,6 +47,10 @@ impl CyclomaticComplexity { let cfg = CFG::new(cx.tcx, block); let n = cfg.graph.len_nodes() as u64; let e = cfg.graph.len_edges() as u64; + if e + 2 < n { + // the function has unreachable code, other lints should catch this + return; + } let cc = e + 2 - n; let mut helper = CCHelper { match_arms: 0, diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 30a05c3f87d..f744d60440f 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -298,3 +298,9 @@ fn void(void: Void) { //~ ERROR: the function has a cyclomatic complexity of 1 } } } + +#[cyclomatic_complexity = "0"] +fn mcarton_sees_all() { + panic!("meh"); + panic!("möh"); +} -- cgit 1.4.1-3-g733a5 From 6c7a2ffdb580701ad0971b43fd7ef0b1c53699d7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 15 Mar 2016 14:41:56 +0530 Subject: Rust upgrade to rustc 1.9.0-nightly (74b886ab1 2016-03-13), update compiletest --- .travis.yml | 1 + Cargo.toml | 8 ++++---- tests/dogfood.rs | 13 +++++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d0c614aaae9..a0893d9c1c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ sudo: false script: - python util/update_lints.py -c - cargo build --features debugging + - rm -rf target/ Cargo.lock - cargo test --features debugging # only test regex_macros if it compiles diff --git a/Cargo.toml b/Cargo.toml index 98f57cc08ca..0bf83ab872a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.51" +version = "0.0.52" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -18,16 +18,16 @@ name = "clippy" plugin = true [dependencies] -regex-syntax = "0.2.2" +regex-syntax = "0.3.0" regex_macros = { version = "0.1.28", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" [dev-dependencies] -compiletest_rs = "0.0.11" +compiletest_rs = "0.1.0" lazy_static = "0.1.15" -regex = "0.1.47" +regex = "0.1.56" rustc-serialize = "0.3" [features] diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 61e37c28c94..b5ae813ae51 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,7 +1,11 @@ +#![feature(test)] + extern crate compiletest_rs as compiletest; +extern crate test; -use std::path::Path; use std::env::var; +use std::path::PathBuf; +use test::TestPaths; #[test] fn dogfood() { @@ -20,5 +24,10 @@ fn dogfood() { config.mode = cfg_mode; - compiletest::runtest::run(config, &Path::new("src/lib.rs")); + let paths = TestPaths { + base: PathBuf::new(), + file: PathBuf::from("src/lib.rs"), + relative_dir: PathBuf::new(), + }; + compiletest::runtest::run(config, &paths); } -- cgit 1.4.1-3-g733a5 From 20123eef982d3bd26fb30df8ead2f386d0daad7b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 15 Mar 2016 21:03:08 +0530 Subject: Update to rustc 1.9.0-nightly (6d215fe04 2016-03-14) --- Cargo.toml | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0bf83ab872a..115ca4ede32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ plugin = true [dependencies] regex-syntax = "0.3.0" -regex_macros = { version = "0.1.28", optional = true } +regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" diff --git a/src/lib.rs b/src/lib.rs index f5a3598a1ba..17f35e07537 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,7 @@ extern crate semver; extern crate regex_syntax; extern crate rustc_plugin; - +extern crate rustc_const_eval; use rustc_plugin::Registry; pub mod consts; -- cgit 1.4.1-3-g733a5 From d65953330b45672b61a321add42056376b3c2342 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 15 Mar 2016 20:09:53 +0100 Subject: rustup const eval changes --- src/array_indexing.rs | 19 +++++++------ src/bit_mask.rs | 2 +- src/consts.rs | 2 +- src/enum_clike.rs | 12 +++----- src/loops.rs | 5 +--- src/matches.rs | 76 +++++++++++++++------------------------------------ src/types.rs | 59 +++++++++++++++++++++------------------ 7 files changed, 71 insertions(+), 104 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index 274491b7c96..3c6acb93284 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -3,6 +3,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty::TyArray; use rustc_front::hir::*; +use rustc_const_eval::ConstInt; use syntax::ast::RangeLimits; use utils; @@ -62,11 +63,11 @@ impl LateLintPass for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tcx.expr_ty(array); if let TyArray(_, size) = ty.sty { - let size = size as u64; + let size = ConstInt::Infer(size as u64); // Index is a constant uint let const_index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); - if let Ok(ConstVal::Uint(const_index)) = const_index { + if let Ok(ConstVal::Integral(const_index)) = const_index { if size <= const_index { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); } @@ -115,24 +116,24 @@ impl LateLintPass for ArrayIndexing { fn to_const_range(start: Option<Option<ConstVal>>, end: Option<Option<ConstVal>>, limits: RangeLimits, - array_size: u64) - -> Option<(u64, u64)> { + array_size: ConstInt) + -> Option<(ConstInt, ConstInt)> { let start = match start { - Some(Some(ConstVal::Uint(x))) => x, + Some(Some(ConstVal::Integral(x))) => x, Some(_) => return None, - None => 0, + None => ConstInt::Infer(0), }; let end = match end { - Some(Some(ConstVal::Uint(x))) => { + Some(Some(ConstVal::Integral(x))) => { if limits == RangeLimits::Closed { x } else { - x - 1 + (x - ConstInt::Infer(1)).expect("x > 0") } } Some(_) => return None, - None => array_size - 1, + None => (array_size - ConstInt::Infer(1)).expect("array_size > 0"), }; Some((start, end)) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 0e09122bcc6..02d428e834d 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -271,7 +271,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { } } .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None, None)) - .and_then(|l| fetch_int_literal(cx, l)) + .and_then(|(l, _ty)| fetch_int_literal(cx, l)) } _ => None, } diff --git a/src/consts.rs b/src/consts.rs index 6dd5651e7ef..eae9747d6e0 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -347,7 +347,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } // separate if lets to avoid double borrowing the def_map if let Some(id) = maybe_id { - if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None, None) { + if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None, None) { let ret = self.expr(const_expr); if ret.is_some() { self.needed_resolution = true; diff --git a/src/enum_clike.rs b/src/enum_clike.rs index 7ee71f41f29..85fa418f278 100644 --- a/src/enum_clike.rs +++ b/src/enum_clike.rs @@ -1,11 +1,9 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` use rustc::lint::*; -use syntax::ast::{IntTy, UintTy}; use syntax::attr::*; use rustc_front::hir::*; use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial}; -use rustc::middle::ty; use utils::span_lint; /// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. @@ -35,12 +33,10 @@ impl LateLintPass for EnumClikeUnportableVariant { for var in &def.variants { let variant = &var.node; if let Some(ref disr) = variant.disr_expr { - let cv = eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None); - let bad = match (cv, &cx.tcx.expr_ty(&**disr).sty) { - (Ok(ConstVal::Int(i)), &ty::TyInt(IntTy::Is)) => i as i32 as i64 != i, - (Ok(ConstVal::Uint(i)), &ty::TyInt(IntTy::Is)) => i as i32 as u64 != i, - (Ok(ConstVal::Int(i)), &ty::TyUint(UintTy::Us)) => (i < 0) || (i as u32 as i64 != i), - (Ok(ConstVal::Uint(i)), &ty::TyUint(UintTy::Us)) => i as u32 as u64 != i, + use rustc_const_eval::*; + let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) { + Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, + Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, _ => false, }; if bad { diff --git a/src/loops.rs b/src/loops.rs index 462ca7c49f6..7987c70d027 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -429,10 +429,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, end_idx) { - (ConstVal::Int(start_idx), ConstVal::Int(end_idx)) => { - (start_idx > end_idx, start_idx == end_idx) - } - (ConstVal::Uint(start_idx), ConstVal::Uint(end_idx)) => { + (ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => { (start_idx > end_idx, start_idx == end_idx) } _ => (false, false), diff --git a/src/matches.rs b/src/matches.rs index 4c60ea89b34..a456a816f62 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,9 +1,9 @@ use rustc::lint::*; -use rustc::middle::const_eval::ConstVal::{Int, Uint}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty; use rustc_front::hir::*; +use rustc_const_eval::ConstInt; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; @@ -288,19 +288,16 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms); - let overlap = match type_ranges(&ranges) { - TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::UintRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::None => None, - }; - - if let Some((start, end)) = overlap { - span_note_and_lint(cx, - MATCH_OVERLAPPING_ARM, - start, - "some ranges overlap", - end, - "overlaps with this"); + let type_ranges = type_ranges(&ranges); + if !type_ranges.is_empty() { + if let Some((start, end)) = overlapping(&type_ranges) { + span_note_and_lint(cx, + MATCH_OVERLAPPING_ARM, + start.span, + "some ranges overlap", + end.span, + "overlaps with this"); + } } } } @@ -370,51 +367,22 @@ pub struct SpannedRange<T> { pub node: (T, T), } -#[derive(Debug)] -enum TypedRanges { - IntRanges(Vec<SpannedRange<i64>>), - UintRanges(Vec<SpannedRange<u64>>), - None, -} +type TypedRanges = Vec<SpannedRange<ConstInt>>; /// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than /// `Uint` and `Int` probably don't make sense. fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { - if ranges.is_empty() { - TypedRanges::None - } else { - match ranges[0].node { - (Int(_), Int(_)) => { - TypedRanges::IntRanges(ranges.iter() - .filter_map(|range| { - if let (Int(start), Int(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect()) - } - (Uint(_), Uint(_)) => { - TypedRanges::UintRanges(ranges.iter() - .filter_map(|range| { - if let (Uint(start), Uint(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect()) - } - _ => TypedRanges::None, + ranges.iter().filter_map(|range| { + if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None } - } + }) + .collect() } fn is_unit_expr(expr: &Expr) -> bool { diff --git a/src/types.rs b/src/types.rs index e64bf010549..c5acbb41ea1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -673,6 +673,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use types::ExtremeType::*; use rustc::middle::const_eval::ConstVal::*; + use rustc_const_eval::*; let ty = &cx.tcx.expr_ty(expr).sty; @@ -687,33 +688,37 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx }; let which = match (ty, cv) { - (&ty::TyBool, Bool(false)) => Minimum, - - (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum, - - (&ty::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum, - - (&ty::TyBool, Bool(true)) => Maximum, - - (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum, - - (&ty::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum, + (&ty::TyBool, Bool(false)) | + + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | + (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | + (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | + (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | + (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | + + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | + (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | + (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | + (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum, + + (&ty::TyBool, Bool(true)) | + + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | + (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | + (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | + (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | + (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | + + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | + (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | + (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | + (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) => Maximum, _ => return None, }; -- cgit 1.4.1-3-g733a5 From 893d6e8bf2ef5c8cde1946a223471cfa061370ee Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 15 Mar 2016 20:26:01 +0100 Subject: Bump to 0.0.53 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 115ca4ede32..3f890f2116f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.52" +version = "0.0.53" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 1546cc47988129cd41b4531f4670f49937162b4c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 14 Mar 2016 21:48:24 +0100 Subject: Fix ICE in `OUT_OF_BOUNDS_INDEXING` with ranges --- src/array_indexing.rs | 19 ++++++++----------- tests/compile-fail/array_indexing.rs | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index 3c6acb93284..ece66ae20a2 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -83,7 +83,7 @@ impl LateLintPass for ArrayIndexing { eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)).map(|v| v.ok()); if let Some((start, end)) = to_const_range(start, end, range.limits, size) { - if start >= size || end >= size { + if start > size || end > size { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, @@ -109,14 +109,11 @@ impl LateLintPass for ArrayIndexing { } } -/// Returns an option containing a tuple with the start and end (exclusive) of the range -/// -/// Note: we assume the start and the end of the range are unsigned, since array slicing -/// works only on usize +/// Returns an option containing a tuple with the start and end (exclusive) of the range. fn to_const_range(start: Option<Option<ConstVal>>, - end: Option<Option<ConstVal>>, - limits: RangeLimits, - array_size: ConstInt) + end: Option<Option<ConstVal>>, + limits: RangeLimits, + array_size: ConstInt) -> Option<(ConstInt, ConstInt)> { let start = match start { Some(Some(ConstVal::Integral(x))) => x, @@ -127,13 +124,13 @@ fn to_const_range(start: Option<Option<ConstVal>>, let end = match end { Some(Some(ConstVal::Integral(x))) => { if limits == RangeLimits::Closed { - x + (x + ConstInt::Infer(1)).expect("such a big array is not realistic") } else { - (x - ConstInt::Infer(1)).expect("x > 0") + x } } Some(_) => return None, - None => (array_size - ConstInt::Infer(1)).expect("array_size > 0"), + None => array_size }; Some((start, end)) diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs index 14f3448a9f6..35fadf8c1e4 100644 --- a/tests/compile-fail/array_indexing.rs +++ b/tests/compile-fail/array_indexing.rs @@ -16,6 +16,8 @@ fn main() { &x[0...4]; //~ERROR: range is out of bounds &x[..]; &x[1..]; + &x[4..]; + &x[5..]; //~ERROR: range is out of bounds &x[..4]; &x[..5]; //~ERROR: range is out of bounds @@ -24,4 +26,16 @@ fn main() { &y[1..2]; //~ERROR: slicing may panic &y[..]; &y[0...4]; //~ERROR: slicing may panic + + let empty: [i8; 0] = []; + empty[0]; //~ERROR: const index is out of bounds + &empty[1..5]; //~ERROR: range is out of bounds + &empty[0...4]; //~ERROR: range is out of bounds + &empty[..]; + &empty[0..]; + &empty[0..0]; + &empty[0...0]; //~ERROR: range is out of bounds + &empty[..0]; + &empty[1..]; //~ERROR: range is out of bounds + &empty[..4]; //~ERROR: range is out of bounds } -- cgit 1.4.1-3-g733a5 From 6d4e1bd73d080476a371b904d99827f2a056c6d2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 14 Mar 2016 22:00:01 +0100 Subject: Fix false positive with STRING_LIT_AS_BYTES and stringify! --- src/strings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings.rs b/src/strings.rs index f4318fc261a..dac5ac9f6bd 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -140,7 +140,7 @@ impl LateLintPass for StringLitAsBytes { if name.node.as_str() == "as_bytes" { if let ExprLit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { - if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, e.span) { + if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, args[0].span) { let msg = format!("calling `as_bytes()` on a string literal. \ Consider using a byte string literal instead: \ `b{}`", -- cgit 1.4.1-3-g733a5 From 251c3eefd15bb35cad053e9526768ca949f6efea Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 14 Mar 2016 22:03:30 +0100 Subject: Use `span_suggestion` in `STRING_LIT_AS_BYTES` --- src/strings.rs | 19 +++++++++++++------ tests/compile-fail/strings.rs | 8 +++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/strings.rs b/src/strings.rs index dac5ac9f6bd..aa9cdcce50c 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -8,7 +8,7 @@ use rustc_front::hir::*; use syntax::codemap::Spanned; use utils::STRING_PATH; use utils::SpanlessEq; -use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, span_lint, span_lint_and_then, walk_ptrs_ty, get_parent_expr}; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). /// @@ -141,11 +141,18 @@ impl LateLintPass for StringLitAsBytes { if let ExprLit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, args[0].span) { - let msg = format!("calling `as_bytes()` on a string literal. \ - Consider using a byte string literal instead: \ - `b{}`", - snippet(cx, args[0].span, r#""foo""#)); - span_lint(cx, STRING_LIT_AS_BYTES, e.span, &msg); + span_lint_and_then(cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on a string literal", + |db| { + let sugg = format!("b{}", + snippet(cx, args[0].span, r#""foo""#)); + db.span_suggestion(e.span, + "consider using a byte string literal instead", + sugg); + }); + } } } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 7ed93737ffa..656349ba621 100644 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -47,9 +47,15 @@ fn both() { #[allow(dead_code, unused_variables)] #[deny(string_lit_as_bytes)] fn str_lit_as_bytes() { - let bs = "hello there".as_bytes(); //~ERROR calling `as_bytes()` + let bs = "hello there".as_bytes(); + //~^ERROR calling `as_bytes()` + //~|HELP byte string literal + //~|SUGGESTION b"hello there" + // no warning, because this cannot be written as a byte string literal: let ubs = "☃".as_bytes(); + + let strify = stringify!(foobar).as_bytes(); } fn main() { -- cgit 1.4.1-3-g733a5 From 8282a3a426690b8dddf7b275621090402b254444 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 15 Mar 2016 21:02:08 +0100 Subject: Fix problem in PANIC_PARAMS with inner `format!` --- src/panic.rs | 14 +++++--------- src/utils/mod.rs | 20 ++++++++++++++++++++ tests/compile-fail/panic.rs | 15 +++++++++++---- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/panic.rs b/src/panic.rs index 7dbcf2a5b30..8b9bf9f1f19 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::LitKind; -use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND}; +use utils::{span_lint, is_direct_expn_of, match_path, BEGIN_UNWIND}; /// **What it does:** This lint checks for missing parameters in `panic!`. /// @@ -28,7 +28,6 @@ impl LintPass for PanicPass { impl LateLintPass for PanicPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ - in_external_macro(cx, expr.span), let ExprBlock(ref block) = expr.node, let Some(ref ex) = block.expr, let ExprCall(ref fun, ref params) = ex.node, @@ -36,16 +35,13 @@ impl LateLintPass for PanicPass { let ExprPath(None, ref path) = fun.node, match_path(path, &BEGIN_UNWIND), let ExprLit(ref lit) = params[0].node, + is_direct_expn_of(cx, params[0].span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, let Some(par) = string.find('{'), - string[par..].contains('}'), - let Some(sp) = cx.sess().codemap() - .with_expn_info(expr.span.expn_id, - |info| info.map(|i| i.call_site)) + string[par..].contains('}') ], { - - span_lint(cx, PANIC_PARAMS, sp, - "You probably are missing some parameter in your `panic!` call"); + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); }} } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 86a5e24efc2..3fb52318b6f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -604,6 +604,7 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' } /// Return the pre-expansion span if is this comes from an expansion of the macro `name`. +/// See also `is_direct_expn_of`. pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { loop { let span_name_span = cx.tcx @@ -619,6 +620,25 @@ pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> } } +/// Return the pre-expansion span if is this directly comes from an expansion of the macro `name`. +/// The difference with `is_expn_of` is that in +/// ```rust,ignore +/// foo!(bar!(42)); +/// ``` +/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only `bar!` by +/// `is_direct_expn_of`. +pub fn is_direct_expn_of(cx: &LateContext, span: Span, name: &str) -> Option<Span> { + let span_name_span = cx.tcx + .sess + .codemap() + .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); + + match span_name_span { + Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span), + _ => None, + } +} + /// Returns index of character after first CamelCase component of `s` pub fn camel_case_until(s: &str) -> usize { let mut iter = s.char_indices(); diff --git a/tests/compile-fail/panic.rs b/tests/compile-fail/panic.rs index 38fe5aa2c0f..7e535d69b69 100644 --- a/tests/compile-fail/panic.rs +++ b/tests/compile-fail/panic.rs @@ -1,13 +1,15 @@ #![feature(plugin)] #![plugin(clippy)] -#[deny(panic_params)] +#![deny(panic_params)] fn missing() { if true { - panic!("{}"); //~ERROR: You probably are missing some parameter + panic!("{}"); //~ERROR: you probably are missing some parameter + } else if false { + panic!("{:?}"); //~ERROR: you probably are missing some parameter } else { - panic!("{:?}"); //~ERROR: You probably are missing some parameter + assert!(true, "here be missing values: {}"); //~ERROR you probably are missing some parameter } } @@ -15,12 +17,16 @@ fn ok_single() { panic!("foo bar"); } +fn ok_inner() { + // Test for #768 + assert!("foo bar".contains(&format!("foo {}", "bar"))); +} + fn ok_multiple() { panic!("{}", "This is {ok}"); } fn ok_bracket() { - // the match is just here because of #759, it serves no other purpose for the lint match 42 { 1337 => panic!("{so is this"), 666 => panic!("so is this}"), @@ -33,4 +39,5 @@ fn main() { ok_single(); ok_multiple(); ok_bracket(); + ok_inner(); } -- cgit 1.4.1-3-g733a5 From bd5af32cb1589a9c8b00f0be2a0e2c24dfdbfc6d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 15 Mar 2016 21:17:26 +0100 Subject: Fix `conf.rs` path in `update_wiki` --- util/update_wiki.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index a10b3549a22..cf3421a8228 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -23,7 +23,7 @@ def parse_path(p="src"): def parse_conf(p): c = {} - with open(p + '/conf.rs') as f: + with open(p + '/utils/conf.rs') as f: f = f.read() m = re.search(conf_re, f) -- cgit 1.4.1-3-g733a5 From 1ac6efedd1f462d02de09a3cea0f94037fbd162d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 16 Mar 2016 16:57:11 +0100 Subject: Rustup to *1.9.0-nightly (c66d2380a 2016-03-15)* --- src/escape.rs | 3 ++- src/utils/mod.rs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index bcc1cb16870..f81a05d43d5 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -3,6 +3,7 @@ use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::infer; use rustc::middle::mem_categorization::{cmt, Categorization}; +use rustc::middle::traits::ProjectionMode; use rustc::middle::ty::adjustment::AutoAdjustment; use rustc::middle::ty; use rustc::util::nodemap::NodeSet; @@ -54,7 +55,7 @@ impl LintPass for EscapePass { impl LateLintPass for EscapePass { fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env)); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env), ProjectionMode::Any); let mut v = EscapeDelegate { cx: cx, set: NodeSet(), diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 86a5e24efc2..cacc9f8e51b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,6 +2,7 @@ use reexport::*; use rustc::front::map::Node; use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::middle::def_id::DefId; +use rustc::middle::traits::ProjectionMode; use rustc::middle::{cstore, def, infer, ty, traits}; use rustc::session::Session; use rustc_front::hir::*; @@ -269,7 +270,7 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any); let obligation = traits::predicate_for_trait_def(cx.tcx, traits::ObligationCause::dummy(), trait_id, @@ -753,6 +754,6 @@ pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> { // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>) -> bool { - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any); infcx.can_equate(&cx.tcx.erase_regions(&a), &cx.tcx.erase_regions(&b)).is_ok() } -- cgit 1.4.1-3-g733a5 From 976d17785e5d71929d072a60f5729f7aaadda715 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 16 Mar 2016 19:26:14 +0100 Subject: Temporary fix for rustc warning false-positive? --- tests/compile-fail/derive.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs index 06f1388dc05..775669dcbd5 100755 --- a/tests/compile-fail/derive.rs +++ b/tests/compile-fail/derive.rs @@ -3,6 +3,7 @@ #![deny(warnings)] #![allow(dead_code)] +#![allow(unused_variables)] // Temporary fix for rustc false positive. To be removed. use std::hash::{Hash, Hasher}; -- cgit 1.4.1-3-g733a5 From 0323d0b05b377af7e27d21f2cefcdf7dd1ead611 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 16 Mar 2016 16:57:38 +0100 Subject: Bump to 0.0.54 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3f890f2116f..dd675981fae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.53" +version = "0.0.54" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 432d9fec38be7b8b5abe57f002dc3f71d84e63c3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 16 Mar 2016 12:38:26 +0100 Subject: refactor clippy-consts to use ConstInt --- src/consts.rs | 278 +++++++++++------------------------------------------ src/identity_op.rs | 11 ++- tests/consts.rs | 10 +- 3 files changed, 66 insertions(+), 233 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index eae9747d6e0..06f790d8308 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -4,13 +4,14 @@ use rustc::lint::LateContext; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::{Def, PathResolution}; use rustc_front::hir::*; -use std::cmp::Ordering::{self, Greater, Less, Equal}; +use rustc_const_eval::{ConstInt, ConstUsize, ConstIsize}; +use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; use std::rc::Rc; -use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy}; +use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy}; use syntax::ptr::P; #[derive(Debug, Copy, Clone)] @@ -29,12 +30,6 @@ impl From<FloatTy> for FloatWidth { } } -#[derive(Copy, Eq, Debug, Clone, PartialEq, Hash)] -pub enum Sign { - Plus, - Minus, -} - /// a Lit_-like enum to fold constant `Expr`s into #[derive(Debug, Clone)] pub enum Constant { @@ -42,12 +37,10 @@ pub enum Constant { Str(String, StrStyle), /// a Binary String b"abc" Binary(Rc<Vec<u8>>), - /// a single byte b'a' - Byte(u8), /// a single char 'a' Char(char), /// an integer, third argument is whether the value is negated - Int(u64, LitIntType, Sign), + Int(ConstInt), /// a float with given type Float(String, FloatWidth), /// true or false @@ -67,21 +60,20 @@ impl Constant { /// /// if the constant could not be converted to u64 losslessly fn as_u64(&self) -> u64 { - if let Constant::Int(val, _, _) = *self { - val // TODO we may want to check the sign if any + if let Constant::Int(val) = *self { + val.to_u64().expect("negative constant can't be casted to u64") } else { panic!("Could not convert a {:?} to u64", self); } } /// convert this constant to a f64, if possible - #[allow(cast_precision_loss)] + #[allow(cast_precision_loss, cast_possible_wrap)] pub fn as_float(&self) -> Option<f64> { match *self { - Constant::Byte(b) => Some(b as f64), Constant::Float(ref s, _) => s.parse().ok(), - Constant::Int(i, _, Sign::Minus) => Some(-(i as f64)), - Constant::Int(i, _, Sign::Plus) => Some(i as f64), + Constant::Int(i) if i.is_negative() => Some(i.to_u64_unchecked() as i64 as f64), + Constant::Int(i) => Some(i.to_u64_unchecked() as f64), _ => None, } } @@ -92,10 +84,8 @@ impl PartialEq for Constant { match (self, other) { (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => ls == rs && lsty == rsty, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, - (&Constant::Byte(l), &Constant::Byte(r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => true, - (&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => lv == rv && lneg == rneg, + (&Constant::Int(l), &Constant::Int(r)) => l == r, (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them @@ -125,15 +115,11 @@ impl Hash for Constant { Constant::Binary(ref b) => { b.hash(state); } - Constant::Byte(u) => { - u.hash(state); - } Constant::Char(c) => { c.hash(state); } - Constant::Int(u, _, t) => { - u.hash(state); - t.hash(state); + Constant::Int(i) => { + i.hash(state); } Constant::Float(ref f, _) => { // don’t use the width here because of PartialEq implementation @@ -165,13 +151,8 @@ impl PartialOrd for Constant { None } } - (&Constant::Byte(ref l), &Constant::Byte(ref r)) => Some(l.cmp(r)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), - (&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => Some(Equal), - (&Constant::Int(ref lv, _, Sign::Plus), &Constant::Int(ref rv, _, Sign::Plus)) => Some(lv.cmp(rv)), - (&Constant::Int(ref lv, _, Sign::Minus), &Constant::Int(ref rv, _, Sign::Minus)) => Some(rv.cmp(lv)), - (&Constant::Int(_, _, Sign::Minus), &Constant::Int(_, _, Sign::Plus)) => Some(Less), - (&Constant::Int(_, _, Sign::Plus), &Constant::Int(_, _, Sign::Minus)) => Some(Greater), + (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { match (ls.parse::<f64>(), rs.parse::<f64>()) { (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), @@ -192,13 +173,24 @@ impl PartialOrd for Constant { } } +#[allow(cast_possible_wrap)] fn lit_to_constant(lit: &LitKind) -> Constant { match *lit { LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), - LitKind::Byte(b) => Constant::Byte(b), + LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(value, ty) => Constant::Int(value, ty, Sign::Plus), + LitKind::Int(value, LitIntType::Unsuffixed) => Constant::Int(ConstInt::Infer(value)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U8)) => Constant::Int(ConstInt::U8(value as u8)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))), + LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), + LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), + LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), + LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), + LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))), LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), LitKind::Bool(b) => Constant::Bool(b), @@ -209,23 +201,7 @@ fn constant_not(o: Constant) -> Option<Constant> { use self::Constant::*; match o { Bool(b) => Some(Bool(!b)), - Int(value, LitIntType::Signed(ity), Sign::Plus) if value != ::std::u64::MAX => { - Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus)) - } - Int(0, LitIntType::Signed(ity), Sign::Minus) => Some(Int(1, LitIntType::Signed(ity), Sign::Minus)), - Int(value, LitIntType::Signed(ity), Sign::Minus) => Some(Int(value - 1, LitIntType::Signed(ity), Sign::Plus)), - Int(value, LitIntType::Unsigned(ity), Sign::Plus) => { - let mask = match ity { - UintTy::U8 => ::std::u8::MAX as u64, - UintTy::U16 => ::std::u16::MAX as u64, - UintTy::U32 => ::std::u32::MAX as u64, - UintTy::U64 => ::std::u64::MAX, - UintTy::Us => { - return None; - } // refuse to guess - }; - Some(Int(!value & mask, LitIntType::Unsigned(ity), Sign::Plus)) - } + Int(value) => (!value).ok().map(Int), _ => None, } } @@ -233,20 +209,12 @@ fn constant_not(o: Constant) -> Option<Constant> { fn constant_negate(o: Constant) -> Option<Constant> { use self::Constant::*; match o { - Int(value, LitIntType::Signed(ity), sign) => Some(Int(value, LitIntType::Signed(ity), neg_sign(sign))), - Int(value, LitIntType::Unsuffixed, sign) => Some(Int(value, LitIntType::Unsuffixed, neg_sign(sign))), + Int(value) => (-value).ok().map(Int), Float(is, ty) => Some(Float(neg_float_str(is), ty)), _ => None, } } -fn neg_sign(s: Sign) -> Sign { - match s { - Sign::Plus => Sign::Minus, - Sign::Minus => Sign::Plus, - } -} - fn neg_float_str(s: String) -> String { if s.starts_with('-') { s[1..].to_owned() @@ -255,32 +223,6 @@ fn neg_float_str(s: String) -> String { } } -fn unify_int_type(l: LitIntType, r: LitIntType) -> Option<LitIntType> { - use syntax::ast::LitIntType::*; - match (l, r) { - (Signed(lty), Signed(rty)) => { - if lty == rty { - Some(LitIntType::Signed(lty)) - } else { - None - } - } - (Unsigned(lty), Unsigned(rty)) => { - if lty == rty { - Some(LitIntType::Unsigned(lty)) - } else { - None - } - } - (Unsuffixed, Unsuffixed) => Some(Unsuffixed), - (Signed(lty), Unsuffixed) => Some(Signed(lty)), - (Unsigned(lty), Unsuffixed) => Some(Unsigned(lty)), - (Unsuffixed, Signed(rty)) => Some(Signed(rty)), - (Unsuffixed, Unsigned(rty)) => Some(Unsigned(rty)), - _ => None, - } -} - pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { lcx: Some(lcx), @@ -381,101 +323,36 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { - match op.node { - BiAdd => { - self.binop_apply(left, right, |l, r| { - match (l, r) { - (Constant::Byte(l8), Constant::Byte(r8)) => l8.checked_add(r8).map(Constant::Byte), - (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { - add_ints(l64, r64, lty, rty, lsign, rsign) - } - // TODO: float (would need bignum library?) - _ => None, - } - }) - } - BiSub => { - self.binop_apply(left, right, |l, r| { - match (l, r) { - (Constant::Byte(l8), Constant::Byte(r8)) => { - if r8 > l8 { - None - } else { - Some(Constant::Byte(l8 - r8)) - } - } - (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { - add_ints(l64, r64, lty, rty, lsign, neg_sign(rsign)) - } - _ => None, - } - }) - } - BiMul => self.divmul(left, right, u64::checked_mul), - BiDiv => self.divmul(left, right, u64::checked_div), - // BiRem, - BiAnd => self.short_circuit(left, right, false), - BiOr => self.short_circuit(left, right, true), - BiBitXor => self.bitop(left, right, |x, y| x ^ y), - BiBitAnd => self.bitop(left, right, |x, y| x & y), - BiBitOr => self.bitop(left, right, |x, y| (x | y)), - BiShl => self.bitop(left, right, |x, y| x << y), - BiShr => self.bitop(left, right, |x, y| x >> y), - BiEq => self.binop_apply(left, right, |l, r| Some(Constant::Bool(l == r))), - BiNe => self.binop_apply(left, right, |l, r| Some(Constant::Bool(l != r))), - BiLt => self.cmp(left, right, Less, true), - BiLe => self.cmp(left, right, Greater, false), - BiGe => self.cmp(left, right, Less, false), - BiGt => self.cmp(left, right, Greater, true), + let l = if let Some(l) = self.expr(left) { l } else { return None; }; + let r = self.expr(right); + match (op.node, l, r) { + (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), + (BiSub, Constant::Int(l), Some(Constant::Int(r))) => (l - r).ok().map(Constant::Int), + (BiMul, Constant::Int(l), Some(Constant::Int(r))) => (l * r).ok().map(Constant::Int), + (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int), + (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), + (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), + (BiAnd, Constant::Bool(true), Some(r)) => Some(r), + (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), + (BiOr, Constant::Bool(false), Some(r)) => Some(r), + (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), + (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), + (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), + (BiBitAnd, Constant::Int(l), Some(Constant::Int(r))) => (l & r).ok().map(Constant::Int), + (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), + (BiBitOr, Constant::Int(l), Some(Constant::Int(r))) => (l | r).ok().map(Constant::Int), + (BiShl, Constant::Int(l), Some(Constant::Int(r))) => (l << r).ok().map(Constant::Int), + (BiShr, Constant::Int(l), Some(Constant::Int(r))) => (l >> r).ok().map(Constant::Int), + (BiEq, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l == r)), + (BiNe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l != r)), + (BiLt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l < r)), + (BiLe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l <= r)), + (BiGe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l >= r)), + (BiGt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l > r)), _ => None, } } - fn divmul<F>(&mut self, left: &Expr, right: &Expr, f: F) -> Option<Constant> - where F: Fn(u64, u64) -> Option<u64> - { - self.binop_apply(left, right, |l, r| { - match (l, r) { - (Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => { - f(l64, r64).and_then(|value| { - let sign = if lsign == rsign { - Sign::Plus - } else { - Sign::Minus - }; - unify_int_type(lty, rty).map(|ty| Constant::Int(value, ty, sign)) - }) - } - _ => None, - } - }) - } - - fn bitop<F>(&mut self, left: &Expr, right: &Expr, f: F) -> Option<Constant> - where F: Fn(u64, u64) -> u64 - { - self.binop_apply(left, right, |l, r| { - match (l, r) { - (Constant::Bool(l), Constant::Bool(r)) => Some(Constant::Bool(f(l as u64, r as u64) != 0)), - (Constant::Byte(l8), Constant::Byte(r8)) => Some(Constant::Byte(f(l8 as u64, r8 as u64) as u8)), - (Constant::Int(l, lty, lsign), Constant::Int(r, rty, rsign)) => { - if lsign == Sign::Plus && rsign == Sign::Plus { - unify_int_type(lty, rty).map(|ty| Constant::Int(f(l, r), ty, Sign::Plus)) - } else { - None - } - } - _ => None, - } - }) - } - - fn cmp(&mut self, left: &Expr, right: &Expr, ordering: Ordering, b: bool) -> Option<Constant> { - self.binop_apply(left, - right, - |l, r| l.partial_cmp(&r).map(|o| Constant::Bool(b == (o == ordering)))) - } - fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> where F: Fn(Constant, Constant) -> Option<Constant> { @@ -485,51 +362,4 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { None } } - - fn short_circuit(&mut self, left: &Expr, right: &Expr, b: bool) -> Option<Constant> { - self.expr(left).and_then(|left| { - if let Constant::Bool(lbool) = left { - if lbool == b { - Some(left) - } else { - self.expr(right).and_then(|right| { - if let Constant::Bool(_) = right { - Some(right) - } else { - None - } - }) - } - } else { - None - } - }) - } -} - -fn add_ints(l64: u64, r64: u64, lty: LitIntType, rty: LitIntType, lsign: Sign, rsign: Sign) -> Option<Constant> { - let ty = if let Some(ty) = unify_int_type(lty, rty) { - ty - } else { - return None; - }; - - match (lsign, rsign) { - (Sign::Plus, Sign::Plus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Plus)), - (Sign::Plus, Sign::Minus) => { - if r64 > l64 { - Some(Constant::Int(r64 - l64, ty, Sign::Minus)) - } else { - Some(Constant::Int(l64 - r64, ty, Sign::Plus)) - } - } - (Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)), - (Sign::Minus, Sign::Plus) => { - if l64 > r64 { - Some(Constant::Int(l64 - r64, ty, Sign::Minus)) - } else { - Some(Constant::Int(r64 - l64, ty, Sign::Plus)) - } - } - } } diff --git a/src/identity_op.rs b/src/identity_op.rs index 8a0da7bcd9f..21167ce768d 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,8 +1,9 @@ -use consts::{constant_simple, Constant, Sign}; +use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; use utils::{span_lint, snippet, in_macro}; +use rustc_const_eval::ConstInt; /// **What it does:** This lint checks for identity operations, e.g. `x + 0`. /// @@ -54,11 +55,11 @@ impl LateLintPass for IdentityOp { fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(Constant::Int(v, _, sign)) = constant_simple(e) { + if let Some(Constant::Int(v)) = constant_simple(e) { if match m { - 0 => v == 0, - -1 => sign == Sign::Minus && v == 1, - 1 => sign == Sign::Plus && v == 1, + 0 => v == ConstInt::Infer(0), + -1 => v == ConstInt::InferSigned(-1), + 1 => v == ConstInt::Infer(1), _ => unreachable!(), } { span_lint(cx, diff --git a/tests/consts.rs b/tests/consts.rs index 5c6088d0554..78853f7c1e5 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -5,8 +5,10 @@ extern crate clippy; extern crate syntax; extern crate rustc; extern crate rustc_front; +extern crate rustc_const_eval; use rustc_front::hir::*; +use rustc_const_eval::ConstInt; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; @@ -15,7 +17,7 @@ use syntax::ast::LitKind; use syntax::ast::LitIntType; use syntax::ast::StrStyle; -use clippy::consts::{constant_simple, Constant, FloatWidth, Sign}; +use clippy::consts::{constant_simple, Constant, FloatWidth}; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } @@ -44,9 +46,9 @@ fn check(expect: Constant, expr: &Expr) { const TRUE : Constant = Constant::Bool(true); const FALSE : Constant = Constant::Bool(false); -const ZERO : Constant = Constant::Int(0, LitIntType::Unsuffixed, Sign::Plus); -const ONE : Constant = Constant::Int(1, LitIntType::Unsuffixed, Sign::Plus); -const TWO : Constant = Constant::Int(2, LitIntType::Unsuffixed, Sign::Plus); +const ZERO : Constant = Constant::Int(ConstInt::Infer(0)); +const ONE : Constant = Constant::Int(ConstInt::Infer(1)); +const TWO : Constant = Constant::Int(ConstInt::Infer(2)); #[test] fn test_lit() { -- cgit 1.4.1-3-g733a5 From 64110f16dd5fc8b28bcee3f4291f8c4ffb6162aa Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 16 Mar 2016 16:28:31 +0100 Subject: fix `Eq`+`Hash` for `Constant` --- src/consts.rs | 5 +++-- src/identity_op.rs | 8 ++++---- tests/consts.rs | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 06f790d8308..3e08f1b74ff 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -85,7 +85,7 @@ impl PartialEq for Constant { (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => ls == rs && lsty == rsty, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(l), &Constant::Int(r)) => l == r, + (&Constant::Int(l), &Constant::Int(r)) => l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked(), (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them @@ -119,7 +119,8 @@ impl Hash for Constant { c.hash(state); } Constant::Int(i) => { - i.hash(state); + i.to_u64_unchecked().hash(state); + i.is_negative().hash(state); } Constant::Float(ref f, _) => { // don’t use the width here because of PartialEq implementation diff --git a/src/identity_op.rs b/src/identity_op.rs index 21167ce768d..9ade801abb3 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -55,11 +55,11 @@ impl LateLintPass for IdentityOp { fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(Constant::Int(v)) = constant_simple(e) { + if let Some(v @ Constant::Int(_)) = constant_simple(e) { if match m { - 0 => v == ConstInt::Infer(0), - -1 => v == ConstInt::InferSigned(-1), - 1 => v == ConstInt::Infer(1), + 0 => v == Constant::Int(ConstInt::Infer(0)), + -1 => v == Constant::Int(ConstInt::InferSigned(-1)), + 1 => v == Constant::Int(ConstInt::Infer(1)), _ => unreachable!(), } { span_lint(cx, diff --git a/tests/consts.rs b/tests/consts.rs index 78853f7c1e5..3a774f67473 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -86,4 +86,8 @@ fn test_ops() { assert_eq!(half_any, half32); assert_eq!(half_any, half64); assert_eq!(half32, half64); // for transitivity + + assert_eq!(Constant::Int(ConstInt::Infer(0)), Constant::Int(ConstInt::U8(0))); + assert_eq!(Constant::Int(ConstInt::Infer(0)), Constant::Int(ConstInt::I8(0))); + assert_eq!(Constant::Int(ConstInt::InferSigned(-1)), Constant::Int(ConstInt::I8(-1))); } -- cgit 1.4.1-3-g733a5 From 06ca1fc0a6d88ff5fbe0dabcc595687861c8c9b1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 1 Mar 2016 10:13:54 +0100 Subject: lint on binding-names that are too similar --- Cargo.toml | 1 + README.md | 1 + src/consts.rs | 7 +- src/lib.rs | 6 ++ src/non_expressive_names.rs | 150 +++++++++++++++++++++++++++++ src/types.rs | 6 +- src/utils/hir.rs | 46 ++++----- src/utils/mod.rs | 4 +- tests/compile-fail/approx_const.rs | 2 +- tests/compile-fail/drop_ref.rs | 2 +- tests/compile-fail/for_loop.rs | 2 +- tests/compile-fail/len_zero.rs | 28 +++--- tests/compile-fail/methods.rs | 1 + tests/compile-fail/non_expressive_names.rs | 37 +++++++ 14 files changed, 245 insertions(+), 48 deletions(-) create mode 100644 src/non_expressive_names.rs create mode 100644 tests/compile-fail/non_expressive_names.rs diff --git a/Cargo.toml b/Cargo.toml index dd675981fae..844408df23c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" +strsim = "0.4.0" [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/README.md b/README.md index 52223ef097b..2ee4dfc5e6c 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ name [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value [should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[similar_names](https://github.com/Manishearth/rust-clippy/wiki#similar_names) | warn | similarly named items and bindings [single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead diff --git a/src/consts.rs b/src/consts.rs index 3e08f1b74ff..f04ad1d214a 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -82,7 +82,7 @@ impl Constant { impl PartialEq for Constant { fn eq(&self, other: &Constant) -> bool { match (self, other) { - (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => ls == rs && lsty == rsty, + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, (&Constant::Int(l), &Constant::Int(r)) => l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked(), @@ -145,8 +145,8 @@ impl Hash for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { match (self, other) { - (&Constant::Str(ref ls, ref lsty), &Constant::Str(ref rs, ref rsty)) => { - if lsty == rsty { + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { + if l_sty == r_sty { Some(ls.cmp(rs)) } else { None @@ -354,6 +354,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } + fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> where F: Fn(Constant, Constant) -> Option<Constant> { diff --git a/src/lib.rs b/src/lib.rs index 17f35e07537..ef6b1f3a2b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,9 @@ extern crate unicode_normalization; // for semver check in attrs.rs extern crate semver; +// for levensthein distance +extern crate strsim; + // for regex checking extern crate regex_syntax; @@ -84,6 +87,7 @@ pub mod needless_features; pub mod needless_update; pub mod new_without_default; pub mod no_effect; +pub mod non_expressive_names; pub mod open_options; pub mod overflow_check_conditional; pub mod panic; @@ -200,6 +204,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); + reg.register_early_lint_pass(box non_expressive_names::SimilarNames(1)); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box regex::RegexPass::default()); @@ -326,6 +331,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_update::NEEDLESS_UPDATE, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, + non_expressive_names::SIMILAR_NAMES, open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic::PANIC_PARAMS, diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs new file mode 100644 index 00000000000..944dcaeb006 --- /dev/null +++ b/src/non_expressive_names.rs @@ -0,0 +1,150 @@ +use rustc::lint::*; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use syntax::ast::*; +use syntax::visit::{self, FnKind}; +use utils::{span_note_and_lint, in_macro}; +use strsim::levenshtein; + +/// **What it does:** This lint warns about names that are very similar and thus confusing +/// +/// **Why is this bad?** It's hard to distinguish between names that differ only by a single character +/// +/// **Known problems:** None? +/// +/// **Example:** `checked_exp` and `checked_expr` +declare_lint! { + pub SIMILAR_NAMES, + Warn, + "similarly named items and bindings" +} + +pub struct SimilarNames(pub usize); + +impl LintPass for SimilarNames { + fn get_lints(&self) -> LintArray { + lint_array!(SIMILAR_NAMES) + } +} + +struct SimilarNamesLocalVisitor<'a, 'b: 'a> { + names: Vec<(InternedString, Span)>, + cx: &'a EarlyContext<'b>, + limit: usize, +} + +const WHITELIST: &'static [&'static str] = &[ + "lhs", "rhs", +]; + +struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); + +impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { + fn visit_pat(&mut self, pat: &'v Pat) { + if let PatKind::Ident(_, id, _) = pat.node { + self.check_name(id.span, id.node.name); + } + visit::walk_pat(self, pat); + } +} + +impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { + fn check_name(&mut self, span: Span, name: Name) { + if in_macro(self.0.cx, span) { + return; + } + let interned_name = name.as_str(); + if interned_name.chars().any(char::is_uppercase) { + return; + } + if interned_name.chars().count() < 3 { + return; + } + for &allow in WHITELIST { + if interned_name == allow { + return; + } + if interned_name.len() <= allow.len() { + continue; + } + // allow_* + let allow_start = allow.chars().chain(Some('_')); + if interned_name.chars().zip(allow_start).all(|(l, r)| l == r) { + return; + } + // *_allow + let allow_end = Some('_').into_iter().chain(allow.chars()); + if interned_name.chars().rev().zip(allow_end.rev()).all(|(l, r)| l == r) { + return; + } + } + for &(ref existing_name, sp) in &self.0.names { + let dist = levenshtein(&interned_name, &existing_name); + // equality is caught by shadow lints + if dist == 0 { + continue; + } + // if they differ enough it's all good + if dist > self.0.limit { + continue; + } + // are we doing stuff like `for item in items`? + if interned_name.starts_with(&**existing_name) || + existing_name.starts_with(&*interned_name) || + interned_name.ends_with(&**existing_name) || + existing_name.ends_with(&*interned_name) { + continue; + } + if dist == 1 { + // are we doing stuff like a_bar, b_bar, c_bar? + if interned_name.chars().next() != existing_name.chars().next() && interned_name.chars().nth(1) == Some('_') { + continue; + } + // are we doing stuff like foo_x, foo_y, foo_z? + if interned_name.chars().rev().next() != existing_name.chars().rev().next() && interned_name.chars().rev().nth(1) == Some('_') { + continue; + } + } + span_note_and_lint(self.0.cx, SIMILAR_NAMES, span, "binding's name is too similar to existing binding", sp, "existing binding defined here"); + return; + } + self.0.names.push((interned_name, span)); + } +} + +impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { + fn visit_local(&mut self, local: &'v Local) { + SimilarNamesNameVisitor(self).visit_local(local) + } + fn visit_block(&mut self, blk: &'v Block) { + // ensure scoping rules work + let n = self.names.len(); + visit::walk_block(self, blk); + self.names.truncate(n); + } + fn visit_arm(&mut self, arm: &'v Arm) { + let n = self.names.len(); + // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier + SimilarNamesNameVisitor(self).visit_pat(&arm.pats[0]); + self.names.truncate(n); + } + fn visit_item(&mut self, _: &'v Item) { + // do nothing + } +} + +impl EarlyLintPass for SimilarNames { + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, blk: &Block, _: Span, _: NodeId) { + let mut visitor = SimilarNamesLocalVisitor { + names: Vec::new(), + cx: cx, + limit: self.0, + }; + // initialize with function arguments + for arg in &decl.inputs { + visit::walk_pat(&mut SimilarNamesNameVisitor(&mut visitor), &arg.pat); + } + // walk all other bindings + visit::walk_block(&mut visitor, blk); + } +} diff --git a/src/types.rs b/src/types.rs index c5acbb41ea1..1dc1f55b773 100644 --- a/src/types.rs +++ b/src/types.rs @@ -638,7 +638,7 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs Lt, Le, }; - let (rel, lhs2, rhs2) = match op { + let (rel, normalized_lhs, normalized_rhs) = match op { BiLt => (Rel::Lt, lhs, rhs), BiLe => (Rel::Le, lhs, rhs), BiGt => (Rel::Lt, rhs, lhs), @@ -646,8 +646,8 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs _ => return None, }; - let lx = detect_extreme_expr(cx, lhs2); - let rx = detect_extreme_expr(cx, rhs2); + let lx = detect_extreme_expr(cx, normalized_lhs); + let rx = detect_extreme_expr(cx, normalized_rhs); Some(match rel { Rel::Lt => { diff --git a/src/utils/hir.rs b/src/utils/hir.rs index b4b786f9743..bc7bc358a9c 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -67,24 +67,24 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } match (&left.node, &right.node) { - (&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => lmut == rmut && self.eq_expr(le, re), + (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), - (&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => { - lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) } (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), - (&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => { - !self.ignore_fn && self.eq_expr(lfun, rfun) && self.eq_exprs(largs, rargs) + (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { + !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) } (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), - (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => { - lfident.node == rfident.node && self.eq_expr(lfexp, rfexp) + (&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => { + l_f_ident.node == r_f_ident.node && self.eq_expr(l_f_exp, r_f_exp) } (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { @@ -101,25 +101,25 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) }) } - (&ExprMethodCall(ref lname, ref ltys, ref largs), - &ExprMethodCall(ref rname, ref rtys, ref rargs)) => { + (&ExprMethodCall(ref l_name, ref l_tys, ref l_args), + &ExprMethodCall(ref r_name, ref r_tys, ref r_args)) => { // TODO: tys - !self.ignore_fn && lname.node == rname.node && ltys.is_empty() && rtys.is_empty() && - self.eq_exprs(largs, rargs) + !self.ignore_fn && l_name.node == r_name.node && l_tys.is_empty() && r_tys.is_empty() && + self.eq_exprs(l_args, r_args) } (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), - (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => { - both(lqself, rqself, |l, r| self.eq_qself(l, r)) && self.eq_path(lsubpath, rsubpath) + (&ExprPath(ref l_qself, ref l_subpath), &ExprPath(ref r_qself, ref r_subpath)) => { + both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) } - (&ExprStruct(ref lpath, ref lf, ref lo), &ExprStruct(ref rpath, ref rf, ref ro)) => { - self.eq_path(lpath, rpath) && + (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { + self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_field(l, r)) } - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => self.eq_exprs(ltup, rtup), + (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), - (&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => lop == rop && self.eq_expr(le, re), + (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) @@ -179,16 +179,16 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => self.eq_ty(lvec, rvec), + (&TyVec(ref l_vec), &TyVec(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyFixedLengthVec(ref lt, ref ll), &TyFixedLengthVec(ref rt, ref rl)) => { self.eq_ty(lt, rt) && self.eq_expr(ll, rl) } - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => lmut.mutbl == rmut.mutbl && self.eq_ty(&*lmut.ty, &*rmut.ty), - (&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) => { - lrmut.mutbl == rrmut.mutbl && self.eq_ty(&*lrmut.ty, &*rrmut.ty) + (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), + (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { + l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) } - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => { - both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(lpath, rpath) + (&TyPath(ref lq, ref l_path), &TyPath(ref rq, ref r_path)) => { + both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path) } (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), (&TyInfer, &TyInfer) => true, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 2934f1c4fba..de303a35f17 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -102,8 +102,8 @@ macro_rules! if_let_chain { /// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one /// isn't). -pub fn differing_macro_contexts(sp1: Span, sp2: Span) -> bool { - sp1.expn_id != sp2.expn_id +pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { + rhs.expn_id != lhs.expn_id } /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index 148746bfa94..3660fb41919 100644 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(approx_constant)] -#[allow(unused, shadow_unrelated)] +#[allow(unused, shadow_unrelated, similar_names)] fn main() { let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::E` found let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::E` found diff --git a/tests/compile-fail/drop_ref.rs b/tests/compile-fail/drop_ref.rs index 3e4c0a9d8ec..8454a471513 100644 --- a/tests/compile-fail/drop_ref.rs +++ b/tests/compile-fail/drop_ref.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(drop_ref)] -#![allow(toplevel_ref_arg)] +#![allow(toplevel_ref_arg, similar_names)] use std::mem::drop; diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index bbdf9d8f1b5..b111439ba51 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -88,7 +88,7 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] -#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity)] +#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] fn main() { const MAX_LEN: usize = 42; diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs index 5168f80b856..4fd0203b912 100644 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -92,38 +92,38 @@ fn main() { println!("Nor should this!"); } - let hie = HasIsEmpty; - if hie.len() == 0 { + let has_is_empty = HasIsEmpty; + if has_is_empty.len() == 0 { //~^ERROR length comparison to zero //~|HELP consider using `is_empty` - //~|SUGGESTION hie.is_empty() + //~|SUGGESTION has_is_empty.is_empty() println!("Or this!"); } - if hie.len() != 0 { + if has_is_empty.len() != 0 { //~^ERROR length comparison to zero //~|HELP consider using `is_empty` - //~|SUGGESTION !hie.is_empty() + //~|SUGGESTION !has_is_empty.is_empty() println!("Or this!"); } - if hie.len() > 0 { + if has_is_empty.len() > 0 { //~^ERROR length comparison to zero //~|HELP consider using `is_empty` - //~|SUGGESTION !hie.is_empty() + //~|SUGGESTION !has_is_empty.is_empty() println!("Or this!"); } - assert!(!hie.is_empty()); + assert!(!has_is_empty.is_empty()); - let wie : &WithIsEmpty = &Wither; - if wie.len() == 0 { + let with_is_empty: &WithIsEmpty = &Wither; + if with_is_empty.len() == 0 { //~^ERROR length comparison to zero //~|HELP consider using `is_empty` - //~|SUGGESTION wie.is_empty() + //~|SUGGESTION with_is_empty.is_empty() println!("Or this!"); } - assert!(!wie.is_empty()); + assert!(!with_is_empty.is_empty()); - let hwie = HasWrongIsEmpty; - if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() + let has_wrong_is_empty = HasWrongIsEmpty; + if has_wrong_is_empty.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() println!("Or this!"); } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 344016a3b90..b1a8f6cf776 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -286,6 +286,7 @@ fn or_fun_call() { //~|SUGGESTION btree.entry(42).or_insert_with(String::new); } +#[allow(similar_names)] fn main() { use std::io; diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs new file mode 100644 index 00000000000..a9a06f4234f --- /dev/null +++ b/tests/compile-fail/non_expressive_names.rs @@ -0,0 +1,37 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy)] +#![allow(unused)] + +fn main() { + let specter: i32; + let spectre: i32; + + let apple: i32; //~ NOTE: existing binding defined here + let bpple: i32; //~ ERROR: name is too similar + let cpple: i32; //~ ERROR: name is too similar + + let a_bar: i32; + let b_bar: i32; + let c_bar: i32; + + let foo_x: i32; + let foo_y: i32; + + let rhs: i32; + let lhs: i32; + + let bla_rhs: i32; + let bla_lhs: i32; + + let blubrhs: i32; //~ NOTE: existing binding defined here + let blublhs: i32; //~ ERROR: name is too similar + + let blubx: i32; //~ NOTE: existing binding defined here + let bluby: i32; //~ ERROR: name is too similar + + let cake: i32; //~ NOTE: existing binding defined here + let caked: i32; //~ NOTE: existing binding defined here + let cakes: i32; //~ ERROR: name is too similar + let coke: i32; //~ ERROR: name is too similar +} -- cgit 1.4.1-3-g733a5 From 5373ffdeb85d55b39671b31fc15a8183d86ff662 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 1 Mar 2016 10:34:45 +0100 Subject: suggest inserting underscores for simple cases --- src/non_expressive_names.rs | 30 ++++++++++++++++++++++++------ tests/compile-fail/non_expressive_names.rs | 4 ++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 944dcaeb006..fc8bb69c5bc 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -3,7 +3,7 @@ use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast::*; use syntax::visit::{self, FnKind}; -use utils::{span_note_and_lint, in_macro}; +use utils::{span_lint_and_then, in_macro}; use strsim::levenshtein; /// **What it does:** This lint warns about names that are very similar and thus confusing @@ -95,17 +95,35 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { existing_name.ends_with(&*interned_name) { continue; } + let mut split_at = None; if dist == 1 { // are we doing stuff like a_bar, b_bar, c_bar? - if interned_name.chars().next() != existing_name.chars().next() && interned_name.chars().nth(1) == Some('_') { - continue; + if interned_name.chars().next() != existing_name.chars().next() { + if interned_name.chars().nth(1) == Some('_') { + continue; + } + split_at = interned_name.chars().next().map(|c| c.len_utf8()); } // are we doing stuff like foo_x, foo_y, foo_z? - if interned_name.chars().rev().next() != existing_name.chars().rev().next() && interned_name.chars().rev().nth(1) == Some('_') { - continue; + if interned_name.chars().rev().next() != existing_name.chars().rev().next() { + if interned_name.chars().rev().nth(1) == Some('_') { + continue; + } + split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); } } - span_note_and_lint(self.0.cx, SIMILAR_NAMES, span, "binding's name is too similar to existing binding", sp, "existing binding defined here"); + span_lint_and_then(self.0.cx, + SIMILAR_NAMES, + span, + "binding's name is too similar to existing binding", + |diag| { + diag.span_note(sp, "existing binding defined here"); + if let Some(split) = split_at { + diag.span_help(span, &format!("separate the discriminating character by an underscore like: `{}_{}`", + &interned_name[..split], + &interned_name[split..])); + } + }); return; } self.0.names.push((interned_name, span)); diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index a9a06f4234f..35dba1a82ca 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -29,9 +29,9 @@ fn main() { let blubx: i32; //~ NOTE: existing binding defined here let bluby: i32; //~ ERROR: name is too similar + //~| HELP: separate the discriminating character by an underscore like: `blub_y` let cake: i32; //~ NOTE: existing binding defined here - let caked: i32; //~ NOTE: existing binding defined here - let cakes: i32; //~ ERROR: name is too similar + let cakes: i32; let coke: i32; //~ ERROR: name is too similar } -- cgit 1.4.1-3-g733a5 From 463897fd399482bd99fa80871269139f13d740c8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 1 Mar 2016 13:05:39 +0100 Subject: lint on too many single character bindings --- README.md | 1 + src/lib.rs | 6 ++- src/non_expressive_names.rs | 66 +++++++++++++++++++++++++----- tests/compile-fail/eta.rs | 2 +- tests/compile-fail/for_loop.rs | 1 + tests/compile-fail/non_expressive_names.rs | 27 ++++++++++++ 6 files changed, 91 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2ee4dfc5e6c..65fc097af71 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ name [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque [manual_swap](https://github.com/Manishearth/rust-clippy/wiki#manual_swap) | warn | manual swap +[many_single_char_names](https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names) | warn | too many single character bindings [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) [map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` [match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on boolean expression; recommends `if..else` block instead diff --git a/src/lib.rs b/src/lib.rs index ef6b1f3a2b9..82383e2b7a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,7 +204,10 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); - reg.register_early_lint_pass(box non_expressive_names::SimilarNames(1)); + reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { + similarity_threshold: 1, + max_single_char_names: 5, + }); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box regex::RegexPass::default()); @@ -331,6 +334,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_update::NEEDLESS_UPDATE, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, + non_expressive_names::MANY_SINGLE_CHAR_NAMES, non_expressive_names::SIMILAR_NAMES, open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index fc8bb69c5bc..7f2fc618ed6 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -3,7 +3,7 @@ use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast::*; use syntax::visit::{self, FnKind}; -use utils::{span_lint_and_then, in_macro}; +use utils::{span_lint_and_then, in_macro, span_lint}; use strsim::levenshtein; /// **What it does:** This lint warns about names that are very similar and thus confusing @@ -19,18 +19,35 @@ declare_lint! { "similarly named items and bindings" } -pub struct SimilarNames(pub usize); +/// **What it does:** This lint warns about having too many variables whose name consists of a single character +/// +/// **Why is this bad?** It's hard to memorize what a variable means without a descriptive name. +/// +/// **Known problems:** None? +/// +/// **Example:** let (a, b, c, d, e, f, g) = (...); +declare_lint! { + pub MANY_SINGLE_CHAR_NAMES, + Warn, + "too many single character bindings" +} + +pub struct NonExpressiveNames { + pub similarity_threshold: usize, + pub max_single_char_names: usize, +} -impl LintPass for SimilarNames { +impl LintPass for NonExpressiveNames { fn get_lints(&self) -> LintArray { - lint_array!(SIMILAR_NAMES) + lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES) } } struct SimilarNamesLocalVisitor<'a, 'b: 'a> { names: Vec<(InternedString, Span)>, cx: &'a EarlyContext<'b>, - limit: usize, + lint: &'a NonExpressiveNames, + single_char_names: Vec<char>, } const WHITELIST: &'static [&'static str] = &[ @@ -57,7 +74,15 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { if interned_name.chars().any(char::is_uppercase) { return; } - if interned_name.chars().count() < 3 { + let count = interned_name.chars().count(); + if count < 3 { + if count == 1 { + let c = interned_name.chars().next().expect("already checked"); + // make sure we ignore shadowing + if !self.0.single_char_names.contains(&c) { + self.0.single_char_names.push(c); + } + } return; } for &allow in WHITELIST { @@ -85,7 +110,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { continue; } // if they differ enough it's all good - if dist > self.0.limit { + if dist > self.0.lint.similarity_threshold { continue; } // are we doing stuff like `for item in items`? @@ -119,7 +144,8 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { |diag| { diag.span_note(sp, "existing binding defined here"); if let Some(split) = split_at { - diag.span_help(span, &format!("separate the discriminating character by an underscore like: `{}_{}`", + diag.span_help(span, &format!("separate the discriminating character \ + by an underscore like: `{}_{}`", &interned_name[..split], &interned_name[split..])); } @@ -130,6 +156,19 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } } +impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { + fn check_single_char_count(&self, span: Span) { + if self.single_char_names.len() < self.lint.max_single_char_names { + return; + } + span_lint(self.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("scope contains {} bindings whose name are just one char", + self.single_char_names.len())); + } +} + impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { fn visit_local(&mut self, local: &'v Local) { SimilarNamesNameVisitor(self).visit_local(local) @@ -137,26 +176,33 @@ impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { fn visit_block(&mut self, blk: &'v Block) { // ensure scoping rules work let n = self.names.len(); + let single_char_count = self.single_char_names.len(); visit::walk_block(self, blk); self.names.truncate(n); + self.check_single_char_count(blk.span); + self.single_char_names.truncate(single_char_count); } fn visit_arm(&mut self, arm: &'v Arm) { let n = self.names.len(); + let single_char_count = self.single_char_names.len(); // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier SimilarNamesNameVisitor(self).visit_pat(&arm.pats[0]); self.names.truncate(n); + self.check_single_char_count(arm.body.span); + self.single_char_names.truncate(single_char_count); } fn visit_item(&mut self, _: &'v Item) { // do nothing } } -impl EarlyLintPass for SimilarNames { +impl EarlyLintPass for NonExpressiveNames { fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, blk: &Block, _: Span, _: NodeId) { let mut visitor = SimilarNamesLocalVisitor { names: Vec::new(), cx: cx, - limit: self.0, + lint: &self, + single_char_names: Vec::new(), }; // initialize with function arguments for arg in &decl.inputs { diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 0e72efe654e..3fd089bf588 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unknown_lints, unused, no_effect, redundant_closure_call)] +#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names)] #![deny(redundant_closure)] fn main() { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index b111439ba51..064f66537eb 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -89,6 +89,7 @@ impl Unrelated { #[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)] #[deny(unused_collect)] #[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] +#[allow(many_single_char_names)] fn main() { const MAX_LEN: usize = 42; diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index 35dba1a82ca..9c75b07356e 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -35,3 +35,30 @@ fn main() { let cakes: i32; let coke: i32; //~ ERROR: name is too similar } + + +fn bla() { + let a: i32; + let (b, c, d): (i32, i64, i16); + { + { + let cdefg: i32; + let blar: i32; + } + { //~ ERROR: scope contains 5 bindings whose name are just one char + let e: i32; + } + { //~ ERROR: scope contains 6 bindings whose name are just one char + let e: i32; + let f: i32; + } + match 5 { + 1 => println!(""), + e => panic!(), //~ ERROR: scope contains 5 bindings whose name are just one char + } + match 5 { + 1 => println!(""), + _ => panic!(), + } + } +} -- cgit 1.4.1-3-g733a5 From 077481053cb28050d7c50e7db93d22eb332181cb Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 8 Mar 2016 14:36:21 +0100 Subject: refactoring and bugfix --- README.md | 2 +- src/non_expressive_names.rs | 64 +++++++++++++----------- tests/compile-fail/non_expressive_names.rs | 44 +++++++++++++--- tests/compile-fail/overflow_check_conditional.rs | 1 + 4 files changed, 74 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 65fc097af71..57dedbdb39e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 136 lints included in this crate: +There are 138 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 7f2fc618ed6..f8f2c4fb9a6 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -76,13 +76,23 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } let count = interned_name.chars().count(); if count < 3 { - if count == 1 { - let c = interned_name.chars().next().expect("already checked"); - // make sure we ignore shadowing - if !self.0.single_char_names.contains(&c) { - self.0.single_char_names.push(c); - } + if count != 1 { + return; + } + let c = interned_name.chars().next().expect("already checked"); + // make sure we ignore shadowing + if self.0.single_char_names.contains(&c) { + return; + } + self.0.single_char_names.push(c); + if self.0.single_char_names.len() < self.0.lint.max_single_char_names { + return; } + span_lint(self.0.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("{}th binding whose name is just one char", + self.0.single_char_names.len())); return; } for &allow in WHITELIST { @@ -157,39 +167,33 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { - fn check_single_char_count(&self, span: Span) { - if self.single_char_names.len() < self.lint.max_single_char_names { - return; - } - span_lint(self.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!("scope contains {} bindings whose name are just one char", - self.single_char_names.len())); + /// ensure scoping rules work + fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) { + let n = self.names.len(); + let single_char_count = self.single_char_names.len(); + f(self); + self.names.truncate(n); + self.single_char_names.truncate(single_char_count); } } impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { fn visit_local(&mut self, local: &'v Local) { - SimilarNamesNameVisitor(self).visit_local(local) + if let Some(ref init) = local.init { + self.apply(|this| visit::walk_expr(this, &**init)); + } + // add the pattern after the expression because the bindings aren't available yet in the init expression + SimilarNamesNameVisitor(self).visit_pat(&*local.pat); } fn visit_block(&mut self, blk: &'v Block) { - // ensure scoping rules work - let n = self.names.len(); - let single_char_count = self.single_char_names.len(); - visit::walk_block(self, blk); - self.names.truncate(n); - self.check_single_char_count(blk.span); - self.single_char_names.truncate(single_char_count); + self.apply(|this| visit::walk_block(this, blk)); } fn visit_arm(&mut self, arm: &'v Arm) { - let n = self.names.len(); - let single_char_count = self.single_char_names.len(); - // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier - SimilarNamesNameVisitor(self).visit_pat(&arm.pats[0]); - self.names.truncate(n); - self.check_single_char_count(arm.body.span); - self.single_char_names.truncate(single_char_count); + self.apply(|this| { + // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier + SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); + this.apply(|this| visit::walk_expr(this, &arm.body)); + }); } fn visit_item(&mut self, _: &'v Item) { // do nothing diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index 9c75b07356e..2e3c60cf66a 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -34,8 +34,40 @@ fn main() { let cake: i32; //~ NOTE: existing binding defined here let cakes: i32; let coke: i32; //~ ERROR: name is too similar + + match 5 { + cheese @ 1 => {}, + rabbit => panic!(), + } + let cheese: i32; + match (42, 43) { + (cheese1, 1) => {}, + (cheese2, 2) => panic!(), + _ => println!(""), + } } +#[derive(Clone, Debug)] +enum MaybeInst { + Split, + Split1(usize), + Split2(usize), +} + +struct InstSplit { + uiae: usize, +} + +impl MaybeInst { + fn fill(&mut self) { + let filled = match *self { + MaybeInst::Split1(goto1) => panic!(1), + MaybeInst::Split2(goto2) => panic!(2), + _ => unimplemented!(), + }; + unimplemented!() + } +} fn bla() { let a: i32; @@ -45,16 +77,16 @@ fn bla() { let cdefg: i32; let blar: i32; } - { //~ ERROR: scope contains 5 bindings whose name are just one char - let e: i32; + { + let e: i32; //~ ERROR: 5th binding whose name is just one char } - { //~ ERROR: scope contains 6 bindings whose name are just one char - let e: i32; - let f: i32; + { + let e: i32; //~ ERROR: 5th binding whose name is just one char + let f: i32; //~ ERROR: 6th binding whose name is just one char } match 5 { 1 => println!(""), - e => panic!(), //~ ERROR: scope contains 5 bindings whose name are just one char + e => panic!(), //~ ERROR: 5th binding whose name is just one char } match 5 { 1 => println!(""), diff --git a/tests/compile-fail/overflow_check_conditional.rs b/tests/compile-fail/overflow_check_conditional.rs index db7b2792484..24310eb81da 100644 --- a/tests/compile-fail/overflow_check_conditional.rs +++ b/tests/compile-fail/overflow_check_conditional.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(many_single_char_names)] #![deny(overflow_check_conditional)] fn main() { -- cgit 1.4.1-3-g733a5 From aa1ecb6fce5b6e44f5a7e8c8ca2e15391dd64489 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 10:18:09 +0100 Subject: fix and rebase --- src/non_expressive_names.rs | 13 ++++++------- tests/compile-fail/blacklisted_name.rs | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index f8f2c4fb9a6..294af274beb 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -85,14 +85,13 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { return; } self.0.single_char_names.push(c); - if self.0.single_char_names.len() < self.0.lint.max_single_char_names { - return; + if self.0.single_char_names.len() >= self.0.lint.max_single_char_names { + span_lint(self.0.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("{}th binding whose name is just one char", + self.0.single_char_names.len())); } - span_lint(self.0.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!("{}th binding whose name is just one char", - self.0.single_char_names.len())); return; } for &allow in WHITELIST { diff --git a/tests/compile-fail/blacklisted_name.rs b/tests/compile-fail/blacklisted_name.rs index efcb810a30e..1afcd94a0b1 100755 --- a/tests/compile-fail/blacklisted_name.rs +++ b/tests/compile-fail/blacklisted_name.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] #![allow(single_match)] -#![allow(unused_variables)] +#![allow(unused_variables, similar_names)] #![deny(blacklisted_name)] fn test(foo: ()) {} //~ERROR use of a blacklisted/placeholder name `foo` -- cgit 1.4.1-3-g733a5 From 24cdb14d5a99e3a12250f449b16d05cdd4a7d53c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 14:34:47 +0100 Subject: refactor for speed --- Cargo.toml | 1 - src/lib.rs | 4 - src/non_expressive_names.rs | 178 +++++++++++++++++++---------- tests/compile-fail/non_expressive_names.rs | 5 + 4 files changed, 125 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 844408df23c..dd675981fae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" -strsim = "0.4.0" [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/src/lib.rs b/src/lib.rs index 82383e2b7a9..a42db8d1fcb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,9 +31,6 @@ extern crate unicode_normalization; // for semver check in attrs.rs extern crate semver; -// for levensthein distance -extern crate strsim; - // for regex checking extern crate regex_syntax; @@ -205,7 +202,6 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { - similarity_threshold: 1, max_single_char_names: 5, }); reg.register_late_lint_pass(box drop_ref::DropRefPass); diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 294af274beb..0c7c97ce474 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -4,7 +4,6 @@ use syntax::parse::token::InternedString; use syntax::ast::*; use syntax::visit::{self, FnKind}; use utils::{span_lint_and_then, in_macro, span_lint}; -use strsim::levenshtein; /// **What it does:** This lint warns about names that are very similar and thus confusing /// @@ -33,7 +32,6 @@ declare_lint! { } pub struct NonExpressiveNames { - pub similarity_threshold: usize, pub max_single_char_names: usize, } @@ -44,7 +42,7 @@ impl LintPass for NonExpressiveNames { } struct SimilarNamesLocalVisitor<'a, 'b: 'a> { - names: Vec<(InternedString, Span)>, + names: Vec<(InternedString, Span, usize)>, cx: &'a EarlyContext<'b>, lint: &'a NonExpressiveNames, single_char_names: Vec<char>, @@ -65,7 +63,43 @@ impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> } } +fn whitelisted(interned_name: &str) -> bool { + for &allow in WHITELIST { + if interned_name == allow { + return true; + } + if interned_name.len() <= allow.len() { + continue; + } + // allow_* + let allow_start = allow.chars().chain(Some('_')); + if interned_name.chars().zip(allow_start).all(|(l, r)| l == r) { + return true; + } + // *_allow + let allow_end = Some('_').into_iter().chain(allow.chars()); + if interned_name.chars().rev().zip(allow_end.rev()).all(|(l, r)| l == r) { + return true; + } + } + false +} + impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { + fn check_short_name(&mut self, c: char, span: Span) { + // make sure we ignore shadowing + if self.0.single_char_names.contains(&c) { + return; + } + self.0.single_char_names.push(c); + if self.0.single_char_names.len() >= self.0.lint.max_single_char_names { + span_lint(self.0.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("{}th binding whose name is just one char", + self.0.single_char_names.len())); + } + } fn check_name(&mut self, span: Span, name: Name) { if in_macro(self.0.cx, span) { return; @@ -80,67 +114,68 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { return; } let c = interned_name.chars().next().expect("already checked"); - // make sure we ignore shadowing - if self.0.single_char_names.contains(&c) { - return; - } - self.0.single_char_names.push(c); - if self.0.single_char_names.len() >= self.0.lint.max_single_char_names { - span_lint(self.0.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!("{}th binding whose name is just one char", - self.0.single_char_names.len())); - } + self.check_short_name(c, span); return; } - for &allow in WHITELIST { - if interned_name == allow { - return; - } - if interned_name.len() <= allow.len() { - continue; - } - // allow_* - let allow_start = allow.chars().chain(Some('_')); - if interned_name.chars().zip(allow_start).all(|(l, r)| l == r) { - return; - } - // *_allow - let allow_end = Some('_').into_iter().chain(allow.chars()); - if interned_name.chars().rev().zip(allow_end.rev()).all(|(l, r)| l == r) { - return; - } + if whitelisted(&interned_name) { + return; } - for &(ref existing_name, sp) in &self.0.names { - let dist = levenshtein(&interned_name, &existing_name); - // equality is caught by shadow lints - if dist == 0 { - continue; - } - // if they differ enough it's all good - if dist > self.0.lint.similarity_threshold { - continue; - } - // are we doing stuff like `for item in items`? - if interned_name.starts_with(&**existing_name) || - existing_name.starts_with(&*interned_name) || - interned_name.ends_with(&**existing_name) || - existing_name.ends_with(&*interned_name) { - continue; - } + for &(ref existing_name, sp, existing_len) in &self.0.names { let mut split_at = None; - if dist == 1 { - // are we doing stuff like a_bar, b_bar, c_bar? - if interned_name.chars().next() != existing_name.chars().next() { - if interned_name.chars().nth(1) == Some('_') { + if existing_len > count { + if existing_len - count != 1 { + continue; + } + if levenstein_not_1(&interned_name, &existing_name) { + continue; + } + } else if existing_len < count { + if count - existing_len != 1 { + continue; + } + if levenstein_not_1(&existing_name, &interned_name) { + continue; + } + } else { + let mut interned_chars = interned_name.chars(); + let mut existing_chars = existing_name.chars(); + + if interned_chars.next() != existing_chars.next() { + let i = interned_chars.next().expect("we know we have more than 1 char"); + let e = existing_chars.next().expect("we know we have more than 1 char"); + if i == e { + if i == '_' { + // allowed similarity x_foo, y_foo + // or too many chars differ (x_foo, y_boo) + continue; + } else if interned_chars.ne(existing_chars) { + // too many chars differ + continue + } + } else { + // too many chars differ continue; } split_at = interned_name.chars().next().map(|c| c.len_utf8()); - } - // are we doing stuff like foo_x, foo_y, foo_z? - if interned_name.chars().rev().next() != existing_name.chars().rev().next() { - if interned_name.chars().rev().nth(1) == Some('_') { + } else if interned_chars.next_back() == existing_chars.next_back() { + if interned_chars.zip(existing_chars).filter(|&(i, e)| i != e).count() != 1 { + // too many chars differ, or none differ (aka shadowing) + continue; + } + } else { + let i = interned_chars.next_back().expect("we know we have more than 2 chars"); + let e = existing_chars.next_back().expect("we know we have more than 2 chars"); + if i == e { + if i == '_' { + // allowed similarity foo_x, foo_x + // or too many chars differ (foo_x, boo_x) + continue; + } else if interned_chars.ne(existing_chars) { + // too many chars differ + continue + } + } else { + // too many chars differ continue; } split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); @@ -161,7 +196,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { }); return; } - self.0.names.push((interned_name, span)); + self.0.names.push((interned_name, span, count)); } } @@ -215,3 +250,30 @@ impl EarlyLintPass for NonExpressiveNames { visit::walk_block(&mut visitor, blk); } } + +/// precondition: a_name.chars().count() < b_name.chars().count() +fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { + debug_assert!(a_name.chars().count() < b_name.chars().count()); + let mut a_chars = a_name.chars(); + let mut b_chars = b_name.chars(); + while let (Some(a), Some(b)) = (a_chars.next(), b_chars.next()) { + if a == b { + continue; + } + if let Some(b2) = b_chars.next() { + // check if there's just one character inserted + if a == b2 && a_chars.eq(b_chars) { + return false; + } else { + // two charaters don't match + return true; + } + } else { + // tuple + // ntuple + return true; + } + } + // for item in items + true +} diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index 2e3c60cf66a..c374c3c4331 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -15,6 +15,11 @@ fn main() { let b_bar: i32; let c_bar: i32; + let items = [5]; + for item in &items { + loop {} + } + let foo_x: i32; let foo_y: i32; -- cgit 1.4.1-3-g733a5 From ea1c2406cc2711ac19bc651b665ab081cfac987f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 14:56:44 +0100 Subject: make single char names threshold configurable --- src/lib.rs | 2 +- src/non_expressive_names.rs | 4 ++-- src/utils/conf.rs | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a42db8d1fcb..8bbaff65361 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,7 +202,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box vec::UselessVec); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { - max_single_char_names: 5, + max_single_char_names: conf.max_single_char_names, }); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 0c7c97ce474..9ad91b421dd 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -32,7 +32,7 @@ declare_lint! { } pub struct NonExpressiveNames { - pub max_single_char_names: usize, + pub max_single_char_names: u64, } impl LintPass for NonExpressiveNames { @@ -92,7 +92,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { return; } self.0.single_char_names.push(c); - if self.0.single_char_names.len() >= self.0.lint.max_single_char_names { + if self.0.single_char_names.len() as u64 >= self.0.lint.max_single_char_names { span_lint(self.0.cx, MANY_SINGLE_CHAR_NAMES, span, diff --git a/src/utils/conf.rs b/src/utils/conf.rs index 6636e30ab38..2411e48997b 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -153,6 +153,8 @@ define_Conf! { ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have ("type-complexity-threshold", type_complexity_threshold, 250 => u64), + /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have + ("single-char-binding-names-threshold", max_single_char_names, 5 => u64), } /// Read the `toml` configuration file. The function will ignore “File not found” errors iif -- cgit 1.4.1-3-g733a5 From 9dc282e31db5c70ca9583152557ebbf87df8ee95 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 16:41:41 +0100 Subject: improve needless_bool to catch odd construct in non_expressive_names --- src/lib.rs | 1 + src/needless_bool.rs | 94 +++++++++++++++++++++---------------- src/non_expressive_names.rs | 7 +-- tests/compile-fail/needless_bool.rs | 26 ++++++++++ 4 files changed, 82 insertions(+), 46 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8bbaff65361..f6179f4f993 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ #![feature(rustc_private, collections)] #![feature(iter_arith)] #![feature(custom_attribute)] +#![feature(slice_patterns)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] // this only exists to allow the "dogfood" integration test to work diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 625f8b0ca78..58afc86b82c 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -47,44 +47,39 @@ impl LintPass for NeedlessBool { impl LateLintPass for NeedlessBool { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use self::Expression::*; if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { + let reduce = |hint: &str, not| { + let pred_snip = snippet(cx, pred.span, ".."); + let hint = if pred_snip == ".." { + hint.into() + } else { + format!("`{}{}`", not, pred_snip) + }; + span_lint(cx, + NEEDLESS_BOOL, + e.span, + &format!("you can reduce this if-then-else expression to just {}", hint)); + }; match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (Some(true), Some(true)) => { + (RetBool(true), RetBool(true)) | + (Bool(true), Bool(true)) => { span_lint(cx, NEEDLESS_BOOL, e.span, "this if-then-else expression will always return true"); } - (Some(false), Some(false)) => { + (RetBool(false), RetBool(false)) | + (Bool(false), Bool(false)) => { span_lint(cx, NEEDLESS_BOOL, e.span, "this if-then-else expression will always return false"); } - (Some(true), Some(false)) => { - let pred_snip = snippet(cx, pred.span, ".."); - let hint = if pred_snip == ".." { - "its predicate".into() - } else { - format!("`{}`", pred_snip) - }; - span_lint(cx, - NEEDLESS_BOOL, - e.span, - &format!("you can reduce this if-then-else expression to just {}", hint)); - } - (Some(false), Some(true)) => { - let pred_snip = snippet(cx, pred.span, ".."); - let hint = if pred_snip == ".." { - "`!` and its predicate".into() - } else { - format!("`!{}`", pred_snip) - }; - span_lint(cx, - NEEDLESS_BOOL, - e.span, - &format!("you can reduce this if-then-else expression to just {}", hint)); - } + (RetBool(true), RetBool(false)) => reduce("its predicate", "return "), + (Bool(true), Bool(false)) => reduce("its predicate", ""), + (RetBool(false), RetBool(true)) => reduce("`!` and its predicate", "return !"), + (Bool(false), Bool(true)) => reduce("`!` and its predicate", "!"), _ => (), } } @@ -102,9 +97,10 @@ impl LintPass for BoolComparison { impl LateLintPass for BoolComparison { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use self::Expression::*; if let ExprBinary(Spanned{ node: BiEq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Some(true), None) => { + (Bool(true), Other) => { let hint = snippet(cx, right_side.span, "..").into_owned(); span_lint_and_then(cx, BOOL_COMPARISON, @@ -114,7 +110,7 @@ impl LateLintPass for BoolComparison { db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } - (None, Some(true)) => { + (Other, Bool(true)) => { let hint = snippet(cx, left_side.span, "..").into_owned(); span_lint_and_then(cx, BOOL_COMPARISON, @@ -124,7 +120,7 @@ impl LateLintPass for BoolComparison { db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } - (Some(false), None) => { + (Bool(false), Other) => { let hint = format!("!{}", snippet(cx, right_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, @@ -134,7 +130,7 @@ impl LateLintPass for BoolComparison { db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); } - (None, Some(false)) => { + (Other, Bool(false)) => { let hint = format!("!{}", snippet(cx, left_side.span, "..")); span_lint_and_then(cx, BOOL_COMPARISON, @@ -150,24 +146,42 @@ impl LateLintPass for BoolComparison { } } -fn fetch_bool_block(block: &Block) -> Option<bool> { - if block.stmts.is_empty() { - block.expr.as_ref().and_then(|e| fetch_bool_expr(e)) - } else { - None +enum Expression { + Bool(bool), + RetBool(bool), + Other, +} + +fn fetch_bool_block(block: &Block) -> Expression { + match (&*block.stmts, block.expr.as_ref()) { + ([], Some(e)) => fetch_bool_expr(&**e), + ([ref e], None) => if let StmtSemi(ref e, _) = e.node { + if let ExprRet(_) = e.node { + fetch_bool_expr(&**e) + } else { + Expression::Other + } + } else { + Expression::Other + }, + _ => Expression::Other, } } -fn fetch_bool_expr(expr: &Expr) -> Option<bool> { +fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), ExprLit(ref lit_ptr) => { if let LitKind::Bool(value) = lit_ptr.node { - Some(value) + Expression::Bool(value) } else { - None + Expression::Other } - } - _ => None, + }, + ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { + Expression::Bool(value) => Expression::RetBool(value), + _ => Expression::Other, + }, + _ => Expression::Other, } } diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 9ad91b421dd..b7d2ac80a10 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -262,12 +262,7 @@ fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { } if let Some(b2) = b_chars.next() { // check if there's just one character inserted - if a == b2 && a_chars.eq(b_chars) { - return false; - } else { - // two charaters don't match - return true; - } + return !(a == b2 && a_chars.eq(b_chars)); } else { // tuple // ntuple diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index c2ad24bc4ee..eff2bdc9b28 100644 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -10,4 +10,30 @@ fn main() { if x { true } else { false }; //~ERROR you can reduce this if-then-else expression to just `x` if x { false } else { true }; //~ERROR you can reduce this if-then-else expression to just `!x` if x { x } else { false }; // would also be questionable, but we don't catch this yet + bool_ret(x); + bool_ret2(x); + bool_ret3(x); + bool_ret4(x); +} + +#[deny(needless_bool)] +#[allow(if_same_then_else)] +fn bool_ret(x: bool) -> bool { + if x { return true } else { return true }; //~ERROR this if-then-else expression will always return true +} + +#[deny(needless_bool)] +#[allow(if_same_then_else)] +fn bool_ret2(x: bool) -> bool { + if x { return false } else { return false }; //~ERROR this if-then-else expression will always return false +} + +#[deny(needless_bool)] +fn bool_ret3(x: bool) -> bool { + if x { return true } else { return false }; //~ERROR you can reduce this if-then-else expression to just `return x` +} + +#[deny(needless_bool)] +fn bool_ret4(x: bool) -> bool { + if x { return false } else { return true }; //~ERROR you can reduce this if-then-else expression to just `return !x` } -- cgit 1.4.1-3-g733a5 From 6a566a1009fefdbfe30e8475836f6b06fed81b3c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 14 Mar 2016 17:13:10 +0100 Subject: use snippet_opt and span_suggestion --- src/needless_bool.rs | 20 ++++++++++---------- tests/compile-fail/needless_bool.rs | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 58afc86b82c..43e7cfddadd 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; -use utils::{span_lint, span_lint_and_then, snippet}; +use utils::{span_lint, span_lint_and_then, snippet, snippet_opt}; /// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. /// @@ -50,16 +50,16 @@ impl LateLintPass for NeedlessBool { use self::Expression::*; if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { let reduce = |hint: &str, not| { - let pred_snip = snippet(cx, pred.span, ".."); - let hint = if pred_snip == ".." { - hint.into() - } else { - format!("`{}{}`", not, pred_snip) + let hint = match snippet_opt(cx, pred.span) { + Some(pred_snip) => format!("`{}{}`", not, pred_snip), + None => hint.into(), }; - span_lint(cx, - NEEDLESS_BOOL, - e.span, - &format!("you can reduce this if-then-else expression to just {}", hint)); + span_lint_and_then(cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression returns a bool literal", |db| { + db.span_suggestion(e.span, "you can reduce it to", hint); + }); }; match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index eff2bdc9b28..7f2d7754bda 100644 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -7,8 +7,14 @@ fn main() { let x = true; if x { true } else { true }; //~ERROR this if-then-else expression will always return true if x { false } else { false }; //~ERROR this if-then-else expression will always return false - if x { true } else { false }; //~ERROR you can reduce this if-then-else expression to just `x` - if x { false } else { true }; //~ERROR you can reduce this if-then-else expression to just `!x` + if x { true } else { false }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION `x` + if x { false } else { true }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION `!x` if x { x } else { false }; // would also be questionable, but we don't catch this yet bool_ret(x); bool_ret2(x); @@ -30,10 +36,16 @@ fn bool_ret2(x: bool) -> bool { #[deny(needless_bool)] fn bool_ret3(x: bool) -> bool { - if x { return true } else { return false }; //~ERROR you can reduce this if-then-else expression to just `return x` + if x { return true } else { return false }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION `return x` } #[deny(needless_bool)] fn bool_ret4(x: bool) -> bool { - if x { return false } else { return true }; //~ERROR you can reduce this if-then-else expression to just `return !x` + if x { return false } else { return true }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION `return !x` } -- cgit 1.4.1-3-g733a5 From fa739e4a0b17f43f955416788120705001a82666 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 17 Mar 2016 13:04:33 +0100 Subject: update for compiletest update --- tests/compile-fail/non_expressive_names.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index c374c3c4331..ac412fb4475 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -1,6 +1,15 @@ #![feature(plugin)] #![plugin(clippy)] #![deny(clippy)] +//~^ NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here +//~| NOTE: lint level defined here #![allow(unused)] fn main() { @@ -8,8 +17,13 @@ fn main() { let spectre: i32; let apple: i32; //~ NOTE: existing binding defined here + //~^ NOTE: existing binding defined here let bpple: i32; //~ ERROR: name is too similar + //~| HELP: separate the discriminating character by an underscore like: `b_pple` + //~| HELP: for further information visit let cpple: i32; //~ ERROR: name is too similar + //~| HELP: separate the discriminating character by an underscore like: `c_pple` + //~| HELP: for further information visit let a_bar: i32; let b_bar: i32; @@ -31,14 +45,17 @@ fn main() { let blubrhs: i32; //~ NOTE: existing binding defined here let blublhs: i32; //~ ERROR: name is too similar + //~| HELP: for further information visit let blubx: i32; //~ NOTE: existing binding defined here let bluby: i32; //~ ERROR: name is too similar + //~| HELP: for further information visit //~| HELP: separate the discriminating character by an underscore like: `blub_y` let cake: i32; //~ NOTE: existing binding defined here let cakes: i32; let coke: i32; //~ ERROR: name is too similar + //~| HELP: for further information visit match 5 { cheese @ 1 => {}, @@ -84,14 +101,18 @@ fn bla() { } { let e: i32; //~ ERROR: 5th binding whose name is just one char + //~| HELP: for further information visit } { let e: i32; //~ ERROR: 5th binding whose name is just one char + //~| HELP: for further information visit let f: i32; //~ ERROR: 6th binding whose name is just one char + //~| HELP: for further information visit } match 5 { 1 => println!(""), e => panic!(), //~ ERROR: 5th binding whose name is just one char + //~| HELP: for further information visit } match 5 { 1 => println!(""), -- cgit 1.4.1-3-g733a5 From ef721106840325a1113225489ca3be2735a00d38 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 18 Mar 2016 19:12:32 +0100 Subject: Fix `new_without_default` with lts and generics --- src/new_without_default.rs | 1 + src/utils/mod.rs | 1 + tests/compile-fail/new_without_default.rs | 31 +++++++++++++++++++++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/new_without_default.rs b/src/new_without_default.rs index d341afb4d92..461d1f5bebd 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -51,6 +51,7 @@ impl LateLintPass for NewWithoutDefault { let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; if_let_chain!{[ + self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)), same_tys(cx, self_ty, ret_ty), let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH), diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 2934f1c4fba..16174e434d4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -270,6 +270,7 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, -> bool { cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); + let ty = cx.tcx.erase_regions(&ty); let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any); let obligation = traits::predicate_for_trait_def(cx.tcx, traits::ObligationCause::dummy(), diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index cc033043bc5..30015f6c9e8 100755 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -32,13 +32,36 @@ impl Params { fn new(_: u32) -> Self { Params } } -struct Generics<'a, T> { - foo: &'a bool, +struct GenericsOk<T> { bar: T, } -impl<'c, V> Generics<'c, V> { - fn new<'b>() -> Generics<'b, V> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for +impl<U> Default for GenericsOk<U> { + fn default() -> Self { unimplemented!(); } +} + +impl<'c, V> GenericsOk<V> { + fn new() -> GenericsOk<V> { unimplemented!() } +} + +struct LtOk<'a> { + foo: &'a bool, +} + +impl<'b> Default for LtOk<'b> { + fn default() -> Self { unimplemented!(); } +} + +impl<'c> LtOk<'c> { + fn new() -> LtOk<'c> { unimplemented!() } +} + +struct LtKo<'a> { + foo: &'a bool, +} + +impl<'c> LtKo<'c> { + fn new() -> LtKo<'c> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for } fn main() {} -- cgit 1.4.1-3-g733a5 From 7d3e6da3cba392e5c39fc37908bc0a635ca7c96d Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger <badboy@archlinux.us> Date: Sun, 20 Mar 2016 20:32:22 +0100 Subject: Fix typo in new_without_default docu --- src/new_without_default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 461d1f5bebd..ff5c09e3911 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -9,7 +9,7 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, sa /// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` /// implementation. /// -/// **Why is this bad?** User might expect to be able to use `Default` is the type can be +/// **Why is this bad?** User might expect to be able to use `Default` as the type can be /// constructed without arguments. /// /// **Known problems:** Hopefully none. -- cgit 1.4.1-3-g733a5 From 6164eabc3c17ab5094c5962c44b4bf7473240b19 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 20 Mar 2016 21:24:18 +0100 Subject: fixed the build --- src/bit_mask.rs | 2 +- src/consts.rs | 2 +- src/utils/hir.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 02d428e834d..f96927f1548 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -270,7 +270,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { _ => None, } } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None, None)) + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) .and_then(|(l, _ty)| fetch_int_literal(cx, l)) } _ => None, diff --git a/src/consts.rs b/src/consts.rs index 3e08f1b74ff..e6bda7df8de 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -290,7 +290,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } // separate if lets to avoid double borrowing the def_map if let Some(id) = maybe_id { - if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None, None) { + if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) { let ret = self.expr(const_expr); if ret.is_some() { self.needed_resolution = true; diff --git a/src/utils/hir.rs b/src/utils/hir.rs index b4b786f9743..fd8dc046eb5 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -332,8 +332,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(a); self.hash_expr(i); } - ExprInlineAsm(_) => { - let c: fn(_) -> _ = ExprInlineAsm; + ExprInlineAsm(..) => { + let c: fn(_, _, _) -> _ = ExprInlineAsm; c.hash(&mut self.s); } ExprIf(ref cond, ref t, ref e) => { -- cgit 1.4.1-3-g733a5 From e90a95016a10e0fe08634dbdb9b8d161ff258917 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 21 Mar 2016 01:21:39 +0100 Subject: Bump to 0.0.55 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dd675981fae..d8234cd0fb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.54" +version = "0.0.55" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From a7f662d8f291ebfdd5cbb46a9c96e28f49200d7f Mon Sep 17 00:00:00 2001 From: Jascha <Jascha-N@users.noreply.github.com> Date: Wed, 23 Mar 2016 16:11:24 +0100 Subject: Match attributes in FnKind patterns --- src/misc.rs | 2 +- src/new_without_default.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index c7aeb7f9a2f..66771e9a690 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -39,7 +39,7 @@ impl LintPass for TopLevelRefPass { impl LateLintPass for TopLevelRefPass { fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - if let FnKind::Closure = k { + if let FnKind::Closure(_) = k { // Does not apply to closures return; } diff --git a/src/new_without_default.rs b/src/new_without_default.rs index ff5c09e3911..d9b11cc49b6 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -46,7 +46,7 @@ impl LateLintPass for NewWithoutDefault { return; } - if let FnKind::Method(name, _, _) = kind { + if let FnKind::Method(name, _, _, _) = kind { if decl.inputs.is_empty() && name.as_str() == "new" { let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; -- cgit 1.4.1-3-g733a5 From 341b7d3f6b5c1b36d8fb3c12a808572b94ccae41 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet <vincent@wearewizards.io> Date: Thu, 24 Mar 2016 17:07:55 +0000 Subject: Update float_cmp message --- src/misc.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 66771e9a690..55439e6a78b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -167,8 +167,9 @@ impl LateLintPass for FloatCmp { span_lint(cx, FLOAT_CMP, expr.span, - &format!("{}-comparison of f32 or f64 detected. Consider changing this to `abs({} - {}) < \ - epsilon` for some suitable value of epsilon", + &format!("{}-comparison of f32 or f64 detected. Consider changing this to `({} - {}).abs() < \ + epsilon` for some suitable value of epsilon. \ + std::f32::EPSILON and std::f64::EPSILON are available.", binop_to_string(op), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); -- cgit 1.4.1-3-g733a5 From 15e55f5df5e13dd7867d86df6bc26c49b7d77944 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 24 Mar 2016 19:25:59 +0100 Subject: Deprecates 4 lints Namely STR_TO_STRING, STRING_TO_STRING, UNSTABLE_AS_SLICE and UNSTABLE_AS_MUT_SLICE. --- README.md | 6 +-- src/deprecated_lints.rs | 44 +++++++++++++++++++++ src/lib.rs | 13 ++++--- src/methods.rs | 53 +------------------------ src/needless_features.rs | 68 --------------------------------- tests/compile-fail/cmp_owned.rs | 1 - tests/compile-fail/methods.rs | 6 --- tests/compile-fail/needless_features.rs | 28 -------------- tests/run-pass/deprecated.rs | 12 ++++++ util/update_lints.py | 34 +++++++++++++++-- util/update_wiki.py | 21 ++++++++-- 11 files changed, 115 insertions(+), 171 deletions(-) create mode 100644 src/deprecated_lints.rs delete mode 100644 src/needless_features.rs delete mode 100644 tests/compile-fail/needless_features.rs create mode 100644 tests/run-pass/deprecated.rs diff --git a/README.md b/README.md index 57dedbdb39e..b3e6937604d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 138 lints included in this crate: +There are 134 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -124,11 +124,9 @@ name [single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead -[str_to_string](https://github.com/Manishearth/rust-clippy/wiki#str_to_string) | warn | using `to_string()` on a str, which should be `to_owned()` [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead -[string_to_string](https://github.com/Manishearth/rust-clippy/wiki#string_to_string) | warn | calling `String::to_string` which is inefficient [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries @@ -140,8 +138,6 @@ name [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference [unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` -[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729 -[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729 [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions diff --git a/src/deprecated_lints.rs b/src/deprecated_lints.rs new file mode 100644 index 00000000000..abdb6297b9e --- /dev/null +++ b/src/deprecated_lints.rs @@ -0,0 +1,44 @@ +macro_rules! declare_deprecated_lint { + (pub $name: ident, $_reason: expr) => { + declare_lint!(pub $name, Allow, "deprecated lint") + } +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `Vec::as_slice`, which was unstable with good +/// stable alternatives. `Vec::as_slice` has now been stabilized. +declare_deprecated_lint! { + pub UNSTABLE_AS_SLICE, + "`Vec::as_slice` has been stabilized in 1.7" +} + + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `Vec::as_mut_slice`, which was unstable with good +/// stable alternatives. `Vec::as_mut_slice` has now been stabilized. +declare_deprecated_lint! { + pub UNSTABLE_AS_MUT_SLICE, + "`Vec::as_mut_slice` has been stabilized in 1.7" +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `.to_string()` method calls on values +/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be +/// specialized to be as efficient as `to_owned`. +declare_deprecated_lint! { + pub STR_TO_STRING, + "using `str::to_string` is common even today and specialization will likely happen soon" +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `.to_string()` method calls on values +/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be +/// specialized to be as efficient as `clone`. +declare_deprecated_lint! { + pub STRING_TO_STRING, + "using `string::to_string` is common even today and specialization will likely happen soon" +} diff --git a/src/lib.rs b/src/lib.rs index f6179f4f993..ffa66fd581b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,7 +81,6 @@ pub mod mut_mut; pub mod mut_reference; pub mod mutex_atomic; pub mod needless_bool; -pub mod needless_features; pub mod needless_update; pub mod new_without_default; pub mod no_effect; @@ -141,6 +140,13 @@ pub fn plugin_registrar(reg: &mut Registry) { } }; + let mut store = reg.sess.lint_store.borrow_mut(); + store.register_removed("unstable_as_slice", "`Vec::as_slice` has been stabilized in 1.7"); + store.register_removed("unstable_as_mut_slice", "`Vec::as_mut_slice` has been stabilized in 1.7"); + store.register_removed("str_to_string", "using `str::to_string` is common even today and specialization will likely happen soon"); + store.register_removed("string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon"); + // end deprecated lints, do not remove this comment, it’s used in `update_lints` + reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); @@ -185,7 +191,6 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); - reg.register_late_lint_pass(box needless_features::NeedlessFeaturesPass); reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); @@ -308,8 +313,6 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, - methods::STR_TO_STRING, - methods::STRING_TO_STRING, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, misc::CMP_NAN, @@ -326,8 +329,6 @@ pub fn plugin_registrar(reg: &mut Registry) { mutex_atomic::MUTEX_ATOMIC, needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, - needless_features::UNSTABLE_AS_MUT_SLICE, - needless_features::UNSTABLE_AS_SLICE, needless_update::NEEDLESS_UPDATE, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, diff --git a/src/methods.rs b/src/methods.rs index 6d33f31d45c..95bbdd441c9 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -6,13 +6,13 @@ use rustc::middle::subst::{Subst, TypeSpace}; use rustc::middle::ty; use rustc_front::hir::*; use std::borrow::Cow; -use std::{fmt, iter}; +use std::fmt; use syntax::codemap::Span; use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; -use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH, +use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; use utils::MethodArgs; @@ -45,31 +45,6 @@ declare_lint! { "using `Result.unwrap()`, which might be better handled" } -/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. -/// -/// **Why is this bad?** This uses the whole formatting machinery just to clone a string. Using `.to_owned()` is lighter on resources. You can also consider using a [`Cow<'a, str>`](http://doc.rust-lang.org/std/borrow/enum.Cow.html) instead in some cases. -/// -/// **Known problems:** None -/// -/// **Example:** `s.to_string()` where `s: &str` -declare_lint! { - pub STR_TO_STRING, Warn, - "using `to_string()` on a str, which should be `to_owned()`" -} - -/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. -/// -/// **Why is this bad?** This is an non-efficient way to clone a `String`, `.clone()` should be used -/// instead. `String` implements `ToString` mostly for generics. -/// -/// **Known problems:** None -/// -/// **Example:** `s.to_string()` where `s: String` -declare_lint! { - pub STRING_TO_STRING, Warn, - "calling `String::to_string` which is inefficient" -} - /// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. /// /// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. @@ -315,8 +290,6 @@ impl LintPass for MethodsPass { lint_array!(EXTEND_FROM_SLICE, OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, - STR_TO_STRING, - STRING_TO_STRING, SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, @@ -343,8 +316,6 @@ impl LateLintPass for MethodsPass { // Chain calls if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { lint_unwrap(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["to_string"]) { - lint_to_string(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { lint_ok_expect(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { @@ -640,26 +611,6 @@ fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { } } -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `to_string()` for `&str`s and `String`s -fn lint_to_string(cx: &LateContext, expr: &Expr, to_string_args: &MethodArgs) { - let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&to_string_args[0])); - - if obj_ty.sty == ty::TyStr { - let mut arg_str = snippet(cx, to_string_args[0].span, "_"); - if ptr_depth > 1 { - arg_str = Cow::Owned(format!("({}{})", iter::repeat('*').take(ptr_depth - 1).collect::<String>(), arg_str)); - } - span_lint(cx, STR_TO_STRING, expr.span, &format!("`{}.to_owned()` is faster", arg_str)); - } else if match_type(cx, obj_ty, &STRING_PATH) { - span_lint(cx, - STRING_TO_STRING, - expr.span, - "`String::to_string` is an inefficient way to clone a `String`; use `clone()` instead"); - } -} - #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `ok().expect()` for `Result`s diff --git a/src/needless_features.rs b/src/needless_features.rs deleted file mode 100644 index f80ac48320e..00000000000 --- a/src/needless_features.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Checks for usage of nightly features that have simple stable equivalents -//! -//! This lint is **warn** by default - -use rustc::lint::*; -use rustc_front::hir::*; -use utils::span_lint; -use utils; - -/// **What it does:** This lint checks for usage of the `as_slice(..)` function, which is unstable. -/// -/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. -/// -/// **Known problems:** None. -/// -/// **Example:** `x.as_slice(..)` -declare_lint! { - pub UNSTABLE_AS_SLICE, - Warn, - "as_slice is not stable and can be replaced by & v[..]\ -see https://github.com/rust-lang/rust/issues/27729" -} - -/// **What it does:** This lint checks for usage of the `as_mut_slice(..)` function, which is unstable. -/// -/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust. -/// -/// **Known problems:** None. -/// -/// **Example:** `x.as_mut_slice(..)` -declare_lint! { - pub UNSTABLE_AS_MUT_SLICE, - Warn, - "as_mut_slice is not stable and can be replaced by &mut v[..]\ -see https://github.com/rust-lang/rust/issues/27729" -} - -#[derive(Copy,Clone)] -pub struct NeedlessFeaturesPass; - -impl LintPass for NeedlessFeaturesPass { - fn get_lints(&self) -> LintArray { - lint_array!(UNSTABLE_AS_SLICE, UNSTABLE_AS_MUT_SLICE) - } -} - -impl LateLintPass for NeedlessFeaturesPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(ref name, _, _) = expr.node { - if name.node.as_str() == "as_slice" && check_paths(cx, expr) { - span_lint(cx, - UNSTABLE_AS_SLICE, - expr.span, - "used as_slice() from the 'convert' nightly feature. Use &[..] instead"); - } - if name.node.as_str() == "as_mut_slice" && check_paths(cx, expr) { - span_lint(cx, - UNSTABLE_AS_MUT_SLICE, - expr.span, - "used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] instead"); - } - } - } -} - -fn check_paths(cx: &LateContext, expr: &Expr) -> bool { - utils::match_impl_method(cx, expr, &["collections", "vec", "Vec<T>"]) -} diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index c06949eb01a..eb4070d8fd6 100644 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -3,7 +3,6 @@ #[deny(cmp_owned)] fn main() { - #[allow(str_to_string)] fn with_to_string(x : &str) { x != "foo".to_string(); //~^ ERROR this creates an owned instance just for comparison. Consider using `x != "foo"` to compare without allocation diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index b1a8f6cf776..edbdeb2e55a 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -296,12 +296,6 @@ fn main() { let res: Result<i32, ()> = Ok(0); let _ = res.unwrap(); //~ERROR used unwrap() on a Result - let _ = "str".to_string(); //~ERROR `"str".to_owned()` is faster - - let v = &"str"; - let string = v.to_string(); //~ERROR `(*v).to_owned()` is faster - let _again = string.to_string(); //~ERROR `String::to_string` is an inefficient way to clone a `String`; use `clone()` instead - res.ok().expect("disaster!"); //~ERROR called `ok().expect()` // the following should not warn, since `expect` isn't implemented unless // the error type implements `Debug` diff --git a/tests/compile-fail/needless_features.rs b/tests/compile-fail/needless_features.rs deleted file mode 100644 index c5c82c7072b..00000000000 --- a/tests/compile-fail/needless_features.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#![deny(clippy)] - -fn test_as_slice() { - let v = vec![1]; - v.as_slice(); //~ERROR used as_slice() from the 'convert' nightly feature. Use &[..] - - let mut v2 = vec![1]; - v2.as_mut_slice(); //~ERROR used as_mut_slice() from the 'convert' nightly feature. Use &mut [..] -} - -struct ShouldWork; - -impl ShouldWork { - fn as_slice(&self) -> &ShouldWork { self } -} - -fn test_should_work() { - let sw = ShouldWork; - sw.as_slice(); -} - -fn main() { - test_as_slice(); - test_should_work(); -} diff --git a/tests/run-pass/deprecated.rs b/tests/run-pass/deprecated.rs new file mode 100644 index 00000000000..70223bfd867 --- /dev/null +++ b/tests/run-pass/deprecated.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[warn(str_to_string)] +//~^WARNING: warning: lint str_to_string has been removed: using `str::to_string` +#[warn(string_to_string)] +//~^WARNING: warning: lint string_to_string has been removed: using `string::to_string` +#[warn(unstable_as_slice)] +//~^WARNING: warning: lint unstable_as_slice has been removed: `Vec::as_slice` has been stabilized +#[warn(unstable_as_mut_slice)] +//~^WARNING: warning: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been stabilized +fn main() {} diff --git a/util/update_lints.py b/util/update_lints.py index 2eaa6ab6211..b16b4b67fad 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -13,14 +13,20 @@ declare_lint_re = re.compile(r''' pub \s+ (?P<name>[A-Z_][A-Z_0-9]*) \s*,\s* (?P<level>Forbid|Deny|Warn|Allow) \s*,\s* " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] -''', re.X | re.S) +''', re.VERBOSE | re.DOTALL) + +declare_deprecated_lint_re = re.compile(r''' + declare_deprecated_lint! \s* [{(] \s* + pub \s+ (?P<name>[A-Z_][A-Z_0-9]*) \s*,\s* + " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] +''', re.VERBOSE | re.DOTALL) nl_escape_re = re.compile(r'\\\n\s*') wiki_link = 'https://github.com/Manishearth/rust-clippy/wiki' -def collect(lints, fn): +def collect(lints, deprecated_lints, fn): """Collect all lints from a file. Adds entries to the lints list as `(module, name, level, desc)`. @@ -35,6 +41,13 @@ def collect(lints, fn): match.group('level').lower(), desc.replace('\\"', '"'))) + for match in declare_deprecated_lint_re.finditer(code): + # remove \-newline escapes from description string + desc = nl_escape_re.sub('', match.group('desc')) + deprecated_lints.append((os.path.splitext(os.path.basename(fn))[0], + match.group('name').lower(), + desc.replace('\\"', '"'))) + def gen_table(lints, link=None): """Write lint table in Markdown format.""" @@ -67,6 +80,13 @@ def gen_mods(lints): yield 'pub mod %s;\n' % module +def gen_deprecated(lints): + """Declare deprecated lints""" + + for lint in lints: + yield ' store.register_removed("%s", "%s");\n' % (lint[1], lint[2]) + + def replace_region(fn, region_start, region_end, callback, replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. @@ -107,6 +127,7 @@ def replace_region(fn, region_start, region_end, callback, def main(print_only=False, check=False): lints = [] + deprecated_lints = [] # check directory if not os.path.isfile('src/lib.rs'): @@ -117,7 +138,7 @@ def main(print_only=False, check=False): for root, dirs, files in os.walk('src'): for fn in files: if fn.endswith('.rs'): - collect(lints, os.path.join(root, fn)) + collect(lints, deprecated_lints, os.path.join(root, fn)) if print_only: sys.stdout.writelines(gen_table(lints)) @@ -147,6 +168,13 @@ def main(print_only=False, check=False): lambda: gen_group(lints, levels=('warn', 'deny')), replace_start=False, write_back=not check) + # same for "deprecated" lint collection + changed |= replace_region( + 'src/lib.rs', r'let mut store', r'end deprecated lints', + lambda: gen_deprecated(deprecated_lints), + replace_start=False, + write_back=not check) + # same for "clippy_pedantic" lint collection changed |= replace_region( 'src/lib.rs', r'reg.register_lint_group\("clippy_pedantic"', r'\]\);', diff --git a/util/update_wiki.py b/util/update_wiki.py index cf3421a8228..5040a28bca0 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -51,6 +51,10 @@ def parse_file(d, f): last_comment.append(line[3:]) elif line.startswith("declare_lint!"): comment = False + deprecated = False + elif line.startswith("declare_deprecated_lint!"): + comment = False + deprecated = True else: last_comment = [] if not comment: @@ -60,7 +64,8 @@ def parse_file(d, f): if m: name = m.group(1).lower() - while True: + # Intentionally either a never looping or infinite loop + while not deprecated: m = re.search(level_re, line) if m: level = m.group(0) @@ -68,6 +73,9 @@ def parse_file(d, f): line = next(rs) + if deprecated: + level = "Deprecated" + print("found %s with level %s in %s" % (name, level, f)) d[name] = (level, last_comment) last_comment = [] @@ -107,14 +115,21 @@ conf_template = """ """ +def level_message(level): + if level == "Deprecated": + return "\n**Those lints are deprecated**:\n\n" + else: + return "\n**Those lints are %s by default**:\n\n" % level + + def write_wiki_page(d, c, f): keys = list(d.keys()) keys.sort() with open(f, "w") as w: w.write(PREFIX) - for level in ('Deny', 'Warn', 'Allow'): - w.write("\n**Those lints are %s by default**:\n\n" % level) + for level in ('Deny', 'Warn', 'Allow', 'Deprecated'): + w.write(level_message(level)) for k in keys: if d[k][0] == level: w.write("[`%s`](#%s)\n" % (k, k)) -- cgit 1.4.1-3-g733a5 From e53babef8f3ea74eccea22d431a5d39f333fdbce Mon Sep 17 00:00:00 2001 From: Tim Neumann <mail@timnn.me> Date: Thu, 24 Mar 2016 23:03:51 +0100 Subject: Mention running optional clippy dependency with `cargo rustc` --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b3e6937604d..23b9c989d78 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,8 @@ And, in your `main.rs` or `lib.rs`: #![cfg_attr(feature="clippy", plugin(clippy))] ``` +Instead of adding the `cfg_attr` attributes you can also run clippy on demand: `cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` (the `-Z no trans`, while not neccessary, will stop the compilation process after typechecking (and lints) have completed, which can significantly reduce the runtime). + ## Configuration Some lints can be configured in a `clippy.toml` file. It contains basic `variable = value` mapping eg. -- cgit 1.4.1-3-g733a5 From 6adb9cb53f5d3ee899398603c6de628ec55f99fe Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Thu, 24 Mar 2016 15:48:38 -0700 Subject: Added crosspointer transmute error and tests --- src/lib.rs | 2 ++ src/transmute.rs | 58 +++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/transmute.rs | 31 ++++++++++++++++++++-- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ffa66fd581b..8a4a84f5dde 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,6 +195,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); + reg.register_late_lint_pass(box transmute::CrosspointerTransmute); reg.register_late_lint_pass(box transmute::UselessTransmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); reg.register_late_lint_pass(box escape::EscapePass); @@ -350,6 +351,7 @@ pub fn plugin_registrar(reg: &mut Registry) { swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, + transmute::CROSSPOINTER_TRANSMUTE, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BOX_VEC, diff --git a/src/transmute.rs b/src/transmute.rs index 0dd5b60e77a..daefbaf07ad 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -1,5 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; +use rustc::middle::ty::TyS; +use rustc::middle::ty::TypeVariants::TyRawPtr; use utils; /// **What it does:** This lint checks for transmutes to the original type of the object. @@ -15,6 +17,19 @@ declare_lint! { "transmutes that have the same to and from types" } +/// **What it does:*** This lint checks for transmutes between a type T and *T. +/// +/// **Why is this bad?** It's easy to mistakenly transmute between a type and a pointer to that type. +/// +/// **Known problems:** None. +/// +/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `*t` or `&t`'s. +declare_lint! { + pub CROSSPOINTER_TRANSMUTE, + Warn, + "transmutes that have to or from types that are a pointer to the other" +} + pub struct UselessTransmute; impl LintPass for UselessTransmute { @@ -43,3 +58,46 @@ impl LateLintPass for UselessTransmute { } } } + +pub struct CrosspointerTransmute; + +impl LintPass for CrosspointerTransmute { + fn get_lints(&self) -> LintArray { + lint_array!(CROSSPOINTER_TRANSMUTE) + } +} + +fn is_ptr_to(from: &TyS, to: &TyS) -> bool { + if let TyRawPtr(from_ptr) = from.sty { + from_ptr.ty == to + } else { + false + } +} + +impl LateLintPass for CrosspointerTransmute { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprCall(ref path_expr, ref args) = e.node { + if let ExprPath(None, _) = path_expr.node { + let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + + if utils::match_def_path(cx, def_id, &["core", "intrinsics", "transmute"]) { + let from_ty = cx.tcx.expr_ty(&args[0]); + let to_ty = cx.tcx.expr_ty(e); + + if is_ptr_to(to_ty, from_ty) { + cx.span_lint(CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); + } + + if is_ptr_to(from_ty, to_ty) { + cx.span_lint(CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); + } + } + } + } + } +} diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 94dd3a18549..b8755008086 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -1,6 +1,5 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(useless_transmute)] extern crate core; @@ -12,6 +11,7 @@ fn my_vec() -> MyVec<i32> { } #[allow(needless_lifetimes)] +#[deny(useless_transmute)] unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a T = core::intrinsics::transmute(t); //~^ ERROR transmute from a type (`&'a T`) to itself @@ -19,7 +19,8 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a U = core::intrinsics::transmute(t); } -fn main() { +#[deny(useless_transmute)] +fn useless() { unsafe { let _: Vec<i32> = core::intrinsics::transmute(my_vec()); //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself @@ -43,3 +44,29 @@ fn main() { let _: Vec<u32> = my_transmute(my_vec()); } } + +#[deny(crosspointer_transmute)] +fn crosspointer() { + let mut vec: Vec<i32> = vec![]; + let vec_const_ptr: *const Vec<i32> = &vec as *const Vec<i32>; + let vec_mut_ptr: *mut Vec<i32> = &mut vec as *mut Vec<i32>; + + unsafe { + let _: Vec<i32> = core::intrinsics::transmute(vec_const_ptr); + //~^ ERROR transmute from a type (`*const collections::vec::Vec<i32>`) to the type that it points to (`collections::vec::Vec<i32>`) + + let _: Vec<i32> = core::intrinsics::transmute(vec_mut_ptr); + //~^ ERROR transmute from a type (`*mut collections::vec::Vec<i32>`) to the type that it points to (`collections::vec::Vec<i32>`) + + let _: *const Vec<i32> = core::intrinsics::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to a pointer to that type (`*const collections::vec::Vec<i32>`) + + let _: *mut Vec<i32> = core::intrinsics::transmute(my_vec()); + //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to a pointer to that type (`*mut collections::vec::Vec<i32>`) + } +} + +fn main() { + useless(); + crosspointer(); +} -- cgit 1.4.1-3-g733a5 From b07360eb2852953fcb07da738da0e2266058b2c0 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Thu, 24 Mar 2016 16:38:16 -0700 Subject: Cleanup and added transmute to ugly path list --- src/transmute.rs | 11 +++++------ src/utils/mod.rs | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/transmute.rs b/src/transmute.rs index daefbaf07ad..488d214b21f 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -3,6 +3,7 @@ use rustc_front::hir::*; use rustc::middle::ty::TyS; use rustc::middle::ty::TypeVariants::TyRawPtr; use utils; +use utils::TRANSMUTE_PATH; /// **What it does:** This lint checks for transmutes to the original type of the object. /// @@ -17,7 +18,7 @@ declare_lint! { "transmutes that have the same to and from types" } -/// **What it does:*** This lint checks for transmutes between a type T and *T. +/// **What it does:*** This lint checks for transmutes between a type `T` and `*T`. /// /// **Why is this bad?** It's easy to mistakenly transmute between a type and a pointer to that type. /// @@ -44,7 +45,7 @@ impl LateLintPass for UselessTransmute { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if utils::match_def_path(cx, def_id, &["core", "intrinsics", "transmute"]) { + if utils::match_def_path(cx, def_id, &TRANSMUTE_PATH) { let from_ty = cx.tcx.expr_ty(&args[0]); let to_ty = cx.tcx.expr_ty(e); @@ -81,7 +82,7 @@ impl LateLintPass for CrosspointerTransmute { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if utils::match_def_path(cx, def_id, &["core", "intrinsics", "transmute"]) { + if utils::match_def_path(cx, def_id, &TRANSMUTE_PATH) { let from_ty = cx.tcx.expr_ty(&args[0]); let to_ty = cx.tcx.expr_ty(e); @@ -89,9 +90,7 @@ impl LateLintPass for CrosspointerTransmute { cx.span_lint(CROSSPOINTER_TRANSMUTE, e.span, &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); - } - - if is_ptr_to(from_ty, to_ty) { + } else if is_ptr_to(from_ty, to_ty) { cx.span_lint(CROSSPOINTER_TRANSMUTE, e.span, &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 050aec0e430..e7b2a9d5210 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -51,6 +51,7 @@ pub const RANGE_TO_PATH: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; +pub const TRANSMUTE_PATH: [&'static str; 3] = ["core", "intrinsics", "transmute"]; pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -- cgit 1.4.1-3-g733a5 From bafffbd624c25bdec62df6655ee6b1786da0e11d Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Thu, 24 Mar 2016 16:39:22 -0700 Subject: Ran python lint updater --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b3e6937604d..0ad56769c38 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 134 lints included in this crate: +There are 135 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -39,6 +39,7 @@ name [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` [collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` +[crosspointer_transmute](https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute) | warn | transmutes that have to or from types that are a pointer to the other [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -- cgit 1.4.1-3-g733a5 From e37ff5a5c739d4852761daa42272e0ff69772a4f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 02:44:25 +0530 Subject: Fix ICE with relating late bound regions --- src/methods.rs | 4 ++-- src/new_without_default.rs | 4 ++-- src/utils/mod.rs | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 95bbdd441c9..81761695eb8 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -402,8 +402,8 @@ impl LateLintPass for MethodsPass { } } - let ret_ty = return_ty(cx.tcx.node_id_to_type(implitem.id)); - if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty))) { + let ret_ty = return_ty(cx, implitem.id); + if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { span_lint(cx, NEW_RET_NO_SELF, sig.explicit_self.span, diff --git a/src/new_without_default.rs b/src/new_without_default.rs index d9b11cc49b6..395d69138e1 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -52,8 +52,8 @@ impl LateLintPass for NewWithoutDefault { if_let_chain!{[ self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics - let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)), - same_tys(cx, self_ty, ret_ty), + let Some(ret_ty) = return_ty(cx, id), + same_tys(cx, self_ty, ret_ty, id), let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH), !implements_trait(cx, self_ty, default_trait_id, Vec::new()) ], { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index e7b2a9d5210..09fb1475b0c 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -4,6 +4,7 @@ use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::middle::def_id::DefId; use rustc::middle::traits::ProjectionMode; use rustc::middle::{cstore, def, infer, ty, traits}; +use rustc::middle::subst::Subst; use rustc::session::Session; use rustc_front::hir::*; use std::borrow::Cow; @@ -764,8 +765,13 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { } /// Convenience function to get the return type of a function or `None` if the function diverges. -pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> { - if let ty::FnConverging(ret_ty) = fun.fn_sig().skip_binder().output { +pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { + let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any); + + let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(infcx.tcx, &infcx.parameter_environment.free_substs); + let fn_sig = infcx.tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive, &fn_sig); + if let ty::FnConverging(ret_ty) = fn_sig.output { Some(ret_ty) } else { None @@ -775,7 +781,10 @@ pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> { /// Check if two types are the same. // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but // not for type parameters. -pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>) -> bool { - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any); - infcx.can_equate(&cx.tcx.erase_regions(&a), &cx.tcx.erase_regions(&b)).is_ok() +pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>, parameter_item: NodeId) -> bool { + let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, parameter_item); + let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any); + let new_a = a.subst(infcx.tcx, &infcx.parameter_environment.free_substs); + let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs); + infcx.can_equate(&new_a, &new_b).is_ok() } -- cgit 1.4.1-3-g733a5 From 3d9a7d91405719d82496e882e22e3797f29d632f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 02:44:55 +0530 Subject: Add test for new() -> Self<'static> --- tests/compile-fail/methods.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index edbdeb2e55a..74f262b05a7 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -47,6 +47,15 @@ impl<'a> Lt2<'a> { pub fn new(s: &str) -> Lt2 { unimplemented!() } } +struct Lt3<'a> { + foo: &'a u32, +} + +impl<'a> Lt3<'a> { + // The lifetime is different, but that’s irrelevant, see #734 + pub fn new() -> Lt3<'static> { unimplemented!() } +} + #[derive(Clone,Copy)] struct U; -- cgit 1.4.1-3-g733a5 From f3fdbd0d89f2ce785c7dfb43b9776f1073dd4189 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 02:45:14 +0530 Subject: Fix ICE with unknown defids --- src/enum_glob_use.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index 5b542a7d67b..7924623c189 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -43,20 +43,21 @@ impl EnumGlobUse { } if let ItemUse(ref item_use) = item.node { if let ViewPath_::ViewPathGlob(_) = item_use.node { - let def = cx.tcx.def_map.borrow()[&item.id]; - if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { - if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { - if let ItemEnum(..) = it.node { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); - } - } - } else { - if let Some(dp) = cx.sess().cstore.def_path(def.def_id()).last() { - if let DefPathData::Type(_) = dp.data { - if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { + if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) { + if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { + if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { + if let ItemEnum(..) = it.node { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } + } else { + if let Some(dp) = cx.sess().cstore.def_path(def.def_id()).last() { + if let DefPathData::Type(_) = dp.data { + if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } + } + } } } } -- cgit 1.4.1-3-g733a5 From 07dc709ba4099bf0c6738f18c2d975c7b893435c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 04:24:42 +0530 Subject: Allow trailing commas in if_let_chain --- src/utils/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 09fb1475b0c..0389c3d56c0 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -55,6 +55,7 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const TRANSMUTE_PATH: [&'static str; 3] = ["core", "intrinsics", "transmute"]; pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const BOX_PATH: [&'static str; 3] = ["std", "boxed", "Box"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// @@ -90,6 +91,11 @@ macro_rules! if_let_chain { $block } }; + ([let $pat:pat = $expr:expr,], $block:block) => { + if let $pat = $expr { + $block + } + }; ([$expr:expr, $($tt:tt)+], $block:block) => { if $expr { if_let_chain!{ [$($tt)+], $block } @@ -100,6 +106,11 @@ macro_rules! if_let_chain { $block } }; + ([$expr:expr,], $block:block) => { + if $expr { + $block + } + }; } /// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one -- cgit 1.4.1-3-g733a5 From fcfda681e51ec538fd117d906b95606fd3c3198d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 04:24:55 +0530 Subject: Stop using ast_ty_to_ty_cache It's not reliable and gets cleared` --- src/types.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/types.rs b/src/types.rs index 1dc1f55b773..742298622fc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,7 +1,6 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::const_eval; -use rustc::middle::ty; +use rustc::middle::{const_eval, def, ty}; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc_front::util::{is_comparison_binop, binop_to_string}; @@ -53,21 +52,34 @@ impl LateLintPass for TypePass { if in_macro(cx, ast_ty.span) { return; } - if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { - if let ty::TyBox(ref inner) = ty.sty { - if match_type(cx, inner, &VEC_PATH) { + if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { + if let def::Def::Struct(..) = did.full_def() { + if Some(did.def_id()) == cx.tcx.lang_items.owned_box() { + if_let_chain! { + [ + let TyPath(_, ref path) = ast_ty.node, + let Some(ref last) = path.segments.last(), + let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, + let Some(ref vec) = ag.types.get(0), + let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), + let def::Def::Struct(..) = did.full_def(), + match_def_path(cx, did.def_id(), &VEC_PATH), + ], + { + span_help_and_lint(cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); + } + } + } else if match_def_path(cx, did.def_id(), &LL_PATH) { span_help_and_lint(cx, - BOX_VEC, + LINKEDLIST, ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a VecDeque might work"); } - } else if match_type(cx, ty, &LL_PATH) { - span_help_and_lint(cx, - LINKEDLIST, - ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a VecDeque might work"); } } } -- cgit 1.4.1-3-g733a5 From 45d41f7d6ad08dccd47bf49632f6706e5ac2a185 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 04:31:02 +0530 Subject: Bump 0.0.56 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d8234cd0fb2..ba4aa426967 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.55" +version = "0.0.57" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From f51293c399eda07678ea74cc6f5a83c557011c63 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 27 Mar 2016 04:57:25 +0530 Subject: Rm extraneous infcx --- src/utils/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0389c3d56c0..6ef0853fdd7 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -778,10 +778,8 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { /// Convenience function to get the return type of a function or `None` if the function diverges. pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any); - - let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(infcx.tcx, &infcx.parameter_environment.free_substs); - let fn_sig = infcx.tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive, &fn_sig); + let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, ¶meter_env.free_substs); + let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); if let ty::FnConverging(ret_ty) = fn_sig.output { Some(ret_ty) } else { -- cgit 1.4.1-3-g733a5 From aa819b7748b8aa6ae03ddcdc993b6dff1ba26912 Mon Sep 17 00:00:00 2001 From: josephDunne <jd@lambda.tech> Date: Sun, 27 Mar 2016 19:59:02 +0100 Subject: Update rust-clippy to rustc 1.9.0-nightly (d5a91e695 2016-03-26) move cfg, infer, traits and ty from middle to top-level move middle::subst into middle::ty track the extern-crate def-id rather than path (rustc ab9b844) --- CONTRIBUTING.md | 2 +- src/array_indexing.rs | 2 +- src/copies.rs | 2 +- src/cyclomatic_complexity.rs | 4 ++-- src/derive.rs | 8 ++++---- src/drop_ref.rs | 2 +- src/enum_glob_use.rs | 7 ++++--- src/escape.rs | 8 ++++---- src/eta_reduction.rs | 2 +- src/format.rs | 2 +- src/len_zero.rs | 2 +- src/loops.rs | 2 +- src/matches.rs | 2 +- src/methods.rs | 4 ++-- src/misc.rs | 2 +- src/mut_mut.rs | 2 +- src/mut_reference.rs | 2 +- src/mutex_atomic.rs | 4 ++-- src/needless_update.rs | 2 +- src/ptr_arg.rs | 2 +- src/transmute.rs | 4 ++-- src/types.rs | 3 ++- src/utils/mod.rs | 9 ++++++--- src/vec.rs | 2 +- 24 files changed, 43 insertions(+), 38 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac094d1c828..d7b181c8bdb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ the lint will end up to be a nested series of matches and ifs, [like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). T-middle issues can be more involved and require verifying types. The -[`middle::ty`](http://manishearth.github.io/rust-internals-docs/rustc/middle/ty) module contains a +[`ty`](http://manishearth.github.io/rust-internals-docs/rustc/middle/ty) module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. diff --git a/src/array_indexing.rs b/src/array_indexing.rs index ece66ae20a2..344a8b8c34e 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; -use rustc::middle::ty::TyArray; +use rustc::ty::TyArray; use rustc_front::hir::*; use rustc_const_eval::ConstInt; use syntax::ast::RangeLimits; diff --git a/src/copies.rs b/src/copies.rs index 691acad6e92..789f852c6c3 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index a03a42f2bc0..3db080f970e 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -1,8 +1,8 @@ //! calculate cyclomatic complexity and warn about overly complex functions use rustc::lint::*; -use rustc::middle::cfg::CFG; -use rustc::middle::ty; +use rustc::cfg::CFG; +use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr}; use syntax::ast::Attribute; diff --git a/src/derive.rs b/src/derive.rs index 380ff0a30f9..4a20d8018de 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,8 +1,8 @@ use rustc::lint::*; -use rustc::middle::subst::Subst; -use rustc::middle::ty::TypeVariants; -use rustc::middle::ty::fast_reject::simplify_type; -use rustc::middle::ty; +use rustc::ty::subst::Subst; +use rustc::ty::TypeVariants; +use rustc::ty::fast_reject::simplify_type; +use rustc::ty; use rustc_front::hir::*; use syntax::ast::{Attribute, MetaItemKind}; use syntax::codemap::Span; diff --git a/src/drop_ref.rs b/src/drop_ref.rs index 5f7e67925bd..7536fb1b63b 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use syntax::codemap::Span; use utils::DROP_PATH; diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index 7924623c189..63f5886fec8 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -3,7 +3,7 @@ use rustc::front::map::Node::NodeItem; use rustc::front::map::definitions::DefPathData; use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; -use rustc::middle::ty::TyEnum; +use rustc::ty::TyEnum; use rustc_front::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; @@ -51,8 +51,9 @@ impl EnumGlobUse { } } } else { - if let Some(dp) = cx.sess().cstore.def_path(def.def_id()).last() { - if let DefPathData::Type(_) = dp.data { + let dp = cx.sess().cstore.relative_def_path(def.def_id()); + if let Some(dpa) = dp.data.last() { + if let DefPathData::TypeNs(_) = dpa.data { if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } diff --git a/src/escape.rs b/src/escape.rs index f81a05d43d5..51c4c7b6f5d 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,11 +1,11 @@ use rustc::front::map::Node::{NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; -use rustc::middle::infer; +use rustc::infer; use rustc::middle::mem_categorization::{cmt, Categorization}; -use rustc::middle::traits::ProjectionMode; -use rustc::middle::ty::adjustment::AutoAdjustment; -use rustc::middle::ty; +use rustc::traits::ProjectionMode; +use rustc::ty::adjustment::AutoAdjustment; +use rustc::ty; use rustc::util::nodemap::NodeSet; use rustc_front::hir::*; use rustc_front::intravisit as visit; diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 6335f3f1398..bae971f46ac 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use utils::{snippet_opt, span_lint_and_then, is_adjusted}; diff --git a/src/format.rs b/src/format.rs index f0b8485b4a4..300b3d17b39 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,6 +1,6 @@ use rustc::front::map::Node::NodeItem; use rustc::lint::*; -use rustc::middle::ty::TypeVariants; +use rustc::ty::TypeVariants; use rustc_front::hir::*; use syntax::ast::LitKind; use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH, STRING_PATH}; diff --git a/src/len_zero.rs b/src/len_zero.rs index e61c77adf24..6dad8684354 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::middle::def_id::DefId; -use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; +use rustc::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; use rustc_front::hir::*; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; diff --git a/src/loops.rs b/src/loops.rs index 7987c70d027..c0d3993746a 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -5,7 +5,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; use rustc::middle::def::Def; use rustc::middle::region::CodeExtent; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; diff --git a/src/matches.rs b/src/matches.rs index a456a816f62..bc3b45b32ef 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use rustc_const_eval::ConstInt; use std::cmp::Ordering; diff --git a/src/methods.rs b/src/methods.rs index 81761695eb8..b8bbc0e9068 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; use rustc::middle::cstore::CrateStore; -use rustc::middle::subst::{Subst, TypeSpace}; -use rustc::middle::ty; +use rustc::ty::subst::{Subst, TypeSpace}; +use rustc::ty; use rustc_front::hir::*; use std::borrow::Cow; use std::fmt; diff --git a/src/misc.rs b/src/misc.rs index 55439e6a78b..49426d5d5de 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::middle::const_eval::ConstVal::Float; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::eval_const_expr_partial; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::FnKind; use rustc_front::util::{is_comparison_binop, binop_to_string}; diff --git a/src/mut_mut.rs b/src/mut_mut.rs index c8f86330b93..a5ed233241d 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty::{TypeAndMut, TyRef}; +use rustc::ty::{TypeAndMut, TyRef}; use rustc_front::hir::*; use utils::{in_external_macro, span_lint}; diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 707ce8efaeb..95ed1092eb5 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; +use rustc::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; use rustc_front::hir::*; use syntax::ptr::P; use utils::span_lint; diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index c8f5e3c7919..0593438cfc1 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -3,8 +3,8 @@ //! This lint is **warn** by default use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; -use rustc::middle::subst::ParamSpace; -use rustc::middle::ty; +use rustc::ty::subst::ParamSpace; +use rustc::ty; use rustc_front::hir::Expr; use syntax::ast; use utils::{span_lint, MUTEX_PATH, match_type}; diff --git a/src/needless_update.rs b/src/needless_update.rs index e3359469150..d25f66ca434 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::middle::ty::TyStruct; +use rustc::ty::TyStruct; use rustc_front::hir::{Expr, ExprStruct}; use utils::span_lint; diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 85baf3310c3..b7882bfda16 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -4,7 +4,7 @@ use rustc::front::map::NodeItem; use rustc::lint::*; -use rustc::middle::ty; +use rustc::ty; use rustc_front::hir::*; use syntax::ast::NodeId; use utils::{STRING_PATH, VEC_PATH}; diff --git a/src/transmute.rs b/src/transmute.rs index 488d214b21f..8689a7e3668 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; -use rustc::middle::ty::TyS; -use rustc::middle::ty::TypeVariants::TyRawPtr; +use rustc::ty::TyS; +use rustc::ty::TypeVariants::TyRawPtr; use utils; use utils::TRANSMUTE_PATH; diff --git a/src/types.rs b/src/types.rs index 742298622fc..c2fc242ec53 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,7 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::{const_eval, def, ty}; +use rustc::middle::{const_eval, def}; +use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc_front::util::{is_comparison_binop, binop_to_string}; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6ef0853fdd7..017890dc461 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,9 +2,12 @@ use reexport::*; use rustc::front::map::Node; use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::middle::def_id::DefId; -use rustc::middle::traits::ProjectionMode; -use rustc::middle::{cstore, def, infer, ty, traits}; -use rustc::middle::subst::Subst; +use rustc::traits; +use rustc::traits::ProjectionMode; +use rustc::middle::{cstore, def}; +use rustc::infer; +use rustc::ty; +use rustc::ty::subst::Subst; use rustc::session::Session; use rustc_front::hir::*; use std::borrow::Cow; diff --git a/src/vec.rs b/src/vec.rs index dda552bc8f9..481c84079f2 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::middle::ty::TypeVariants; +use rustc::ty::TypeVariants; use rustc_front::hir::*; use syntax::codemap::Span; use syntax::ptr::P; -- cgit 1.4.1-3-g733a5 From 204034e8fa32e488b14131302a77fb2c918d32f0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 28 Mar 2016 01:58:57 +0530 Subject: Fix ICE --- src/enum_glob_use.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index 63f5886fec8..5b29f84ef51 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -1,9 +1,9 @@ //! lint on `use`ing all variants of an enum use rustc::front::map::Node::NodeItem; -use rustc::front::map::definitions::DefPathData; use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; -use rustc::ty::TyEnum; +use rustc::middle::def::Def; +use rustc::middle::cstore::DefLike; use rustc_front::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; @@ -51,12 +51,10 @@ impl EnumGlobUse { } } } else { - let dp = cx.sess().cstore.relative_def_path(def.def_id()); - if let Some(dpa) = dp.data.last() { - if let DefPathData::TypeNs(_) = dpa.data { - if let TyEnum(..) = cx.sess().cstore.item_type(&cx.tcx, def.def_id()).ty.sty { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); - } + let child = cx.sess().cstore.item_children(def.def_id()); + if let Some(child) = child.first() { + if let DefLike::DlDef(Def::Variant(..)) = child.def { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } } -- cgit 1.4.1-3-g733a5 From d2eac3add595b820e5205332caf649017551c722 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 28 Mar 2016 01:59:25 +0530 Subject: Bump to 0.0.58 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ba4aa426967..3bb7a82f6e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.57" +version = "0.0.58" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From ae24929cd65ab2ab50a6ae7bba2a03e93e573c84 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 28 Mar 2016 02:00:35 +0530 Subject: Update contributing with new links --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7b181c8bdb..5e74cd9ef02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ the lint will end up to be a nested series of matches and ifs, [like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). T-middle issues can be more involved and require verifying types. The -[`ty`](http://manishearth.github.io/rust-internals-docs/rustc/middle/ty) module contains a +[`ty`](http://manishearth.github.io/rust-internals-docs/rustc/ty) module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. -- cgit 1.4.1-3-g733a5 From 2d5e3f311841617eba62089212c1b43120c13921 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 25 Mar 2016 23:22:17 +0100 Subject: Lint transmute from ptr to ref --- README.md | 3 +- src/lib.rs | 4 +- src/transmute.rs | 108 ++++++++++++++++++++++++++-------------- tests/compile-fail/transmute.rs | 39 +++++++++++++++ 4 files changed, 114 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 6199ccd8e8f..95ba6b08539 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 135 lints included in this crate: +There are 136 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -133,6 +133,7 @@ name [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries [too_many_arguments](https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. +[transmute_ptr_to_ref](https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) diff --git a/src/lib.rs b/src/lib.rs index 8a4a84f5dde..7d24b2c8924 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,8 +195,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); - reg.register_late_lint_pass(box transmute::CrosspointerTransmute); - reg.register_late_lint_pass(box transmute::UselessTransmute); + reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); reg.register_late_lint_pass(box escape::EscapePass); reg.register_early_lint_pass(box misc_early::MiscEarly); @@ -352,6 +351,7 @@ pub fn plugin_registrar(reg: &mut Registry) { swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BOX_VEC, diff --git a/src/transmute.rs b/src/transmute.rs index 8689a7e3668..ef049ba4a6d 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -1,9 +1,9 @@ use rustc::lint::*; +use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; +use rustc::ty; use rustc_front::hir::*; -use rustc::ty::TyS; -use rustc::ty::TypeVariants::TyRawPtr; -use utils; use utils::TRANSMUTE_PATH; +use utils::{match_def_path, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** This lint checks for transmutes to the original type of the object. /// @@ -31,28 +31,63 @@ declare_lint! { "transmutes that have to or from types that are a pointer to the other" } -pub struct UselessTransmute; +/// **What it does:*** This lint checks for transmutes from a pointer to a reference. +/// +/// **Why is this bad?** This can always be rewritten with `&` and `*`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: &T = std::mem::transmute(p); // where p: *const T +/// // can be written: +/// let _: &T = &*p; +/// ``` +declare_lint! { + pub TRANSMUTE_PTR_TO_REF, + Warn, + "transmutes from a pointer to a reference type" +} + +pub struct Transmute; -impl LintPass for UselessTransmute { +impl LintPass for Transmute { fn get_lints(&self) -> LintArray { - lint_array!(USELESS_TRANSMUTE) + lint_array! [ + CROSSPOINTER_TRANSMUTE, + TRANSMUTE_PTR_TO_REF, + USELESS_TRANSMUTE + ] } } -impl LateLintPass for UselessTransmute { +impl LateLintPass for Transmute { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if utils::match_def_path(cx, def_id, &TRANSMUTE_PATH) { + if match_def_path(cx, def_id, &TRANSMUTE_PATH) { let from_ty = cx.tcx.expr_ty(&args[0]); let to_ty = cx.tcx.expr_ty(e); if from_ty == to_ty { - cx.span_lint(USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty)); + span_lint(cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty)); + } else if is_ptr_to(to_ty, from_ty) { + span_lint(cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); + } else if is_ptr_to(from_ty, to_ty) { + span_lint(cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); + } else { + check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); } } } @@ -60,15 +95,7 @@ impl LateLintPass for UselessTransmute { } } -pub struct CrosspointerTransmute; - -impl LintPass for CrosspointerTransmute { - fn get_lints(&self) -> LintArray { - lint_array!(CROSSPOINTER_TRANSMUTE) - } -} - -fn is_ptr_to(from: &TyS, to: &TyS) -> bool { +fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { if let TyRawPtr(from_ptr) = from.sty { from_ptr.ty == to } else { @@ -76,27 +103,34 @@ fn is_ptr_to(from: &TyS, to: &TyS) -> bool { } } -impl LateLintPass for CrosspointerTransmute { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(None, _) = path_expr.node { - let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); +fn check_ptr_to_ref<'tcx>(cx: &LateContext, + from_ty: ty::Ty<'tcx>, + to_ty: ty::Ty<'tcx>, + e: &Expr, arg: &Expr) { + if let TyRawPtr(ref from_pty) = from_ty.sty { + if let TyRef(_, ref to_rty) = to_ty.sty { + let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", + from_ty, + to_ty); + span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| { + if let Some(arg) = snippet_opt(cx, arg.span) { + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - if utils::match_def_path(cx, def_id, &TRANSMUTE_PATH) { - let from_ty = cx.tcx.expr_ty(&args[0]); - let to_ty = cx.tcx.expr_ty(e); - if is_ptr_to(to_ty, from_ty) { - cx.span_lint(CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); - } else if is_ptr_to(from_ty, to_ty) { - cx.span_lint(CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); + let sugg = if from_pty.ty == to_rty.ty { + format!("{}{}", deref, arg) } + else { + format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + }; + + db.span_suggestion(e.span, "try", sugg); } - } + }); } } } diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index b8755008086..5bae2c72643 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -19,6 +19,45 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a U = core::intrinsics::transmute(t); } +#[deny(transmute_ptr_to_ref)] +unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { + let _: &T = std::mem::transmute(p); + //~^ ERROR transmute from a pointer type (`*const T`) to a reference type (`&T`) + //~| HELP try + //~| SUGGESTION = &*p; + let _: &T = &*p; + + let _: &mut T = std::mem::transmute(m); + //~^ ERROR transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) + //~| HELP try + //~| SUGGESTION = &mut *m; + let _: &mut T = &mut *m; + + let _: &T = std::mem::transmute(m); + //~^ ERROR transmute from a pointer type (`*mut T`) to a reference type (`&T`) + //~| HELP try + //~| SUGGESTION = &*m; + let _: &T = &*m; + + let _: &T = std::mem::transmute(o); + //~^ ERROR transmute from a pointer type (`*const U`) to a reference type (`&T`) + //~| HELP try + //~| SUGGESTION = &*(o as *const T); + let _: &T = &*(o as *const T); + + let _: &mut T = std::mem::transmute(om); + //~^ ERROR transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) + //~| HELP try + //~| SUGGESTION = &mut *(om as *mut T); + let _: &mut T = &mut *(om as *mut T); + + let _: &T = std::mem::transmute(om); + //~^ ERROR transmute from a pointer type (`*mut U`) to a reference type (`&T`) + //~| HELP try + //~| SUGGESTION = &*(om as *const T); + let _: &T = &*(om as *const T); +} + #[deny(useless_transmute)] fn useless() { unsafe { -- cgit 1.4.1-3-g733a5 From e7158dc8f174126780ac6caa864bccede5dda262 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 26 Mar 2016 01:49:45 +0100 Subject: s/cx.span_lint/span_lint(cx, / --- src/misc.rs | 22 ++++++++++++---------- src/ranges.rs | 19 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index 49426d5d5de..5a787ba6dba 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -312,7 +312,7 @@ impl LateLintPass for ModuloOne { if let ExprBinary(ref cmp, _, ref right) = expr.node { if let Spanned {node: BinOp_::BiRem, ..} = *cmp { if is_integer_literal(right, 1) { - cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0"); + span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } } } @@ -347,11 +347,12 @@ impl LateLintPass for PatternPass { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatKind::Ident(_, ref ident, Some(ref right)) = pat.node { if right.node == PatKind::Wild { - cx.span_lint(REDUNDANT_PATTERN, - pat.span, - &format!("the `{} @ _` pattern can be written as just `{}`", - ident.node.name, - ident.node.name)); + span_lint(cx, + REDUNDANT_PATTERN, + pat.span, + &format!("the `{} @ _` pattern can be written as just `{}`", + ident.node.name, + ident.node.name)); } } } @@ -408,10 +409,11 @@ impl LateLintPass for UsedUnderscoreBinding { _ => false, }; if needs_lint { - cx.span_lint(USED_UNDERSCORE_BINDING, - expr.span, - "used binding which is prefixed with an underscore. A leading underscore signals that a \ - binding will not be used."); + span_lint(cx, + USED_UNDERSCORE_BINDING, + expr.span, + "used binding which is prefixed with an underscore. A leading underscore signals that a \ + binding will not be used."); } } } diff --git a/src/ranges.rs b/src/ranges.rs index 766d98b4e0b..23bd3d1103c 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Spanned; -use utils::{is_integer_literal, match_type, snippet, unsugar_range, UnsugaredRange}; +use utils::{is_integer_literal, match_type, snippet, span_lint, unsugar_range, UnsugaredRange}; /// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. /// @@ -41,10 +41,11 @@ impl LateLintPass for StepByZero { // Range with step_by(0). if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) { - cx.span_lint(RANGE_STEP_BY_ZERO, - expr.span, - "Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \ - instead") + span_lint(cx, + RANGE_STEP_BY_ZERO, + expr.span, + "Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \ + instead"); } else if name.as_str() == "zip" && args.len() == 2 { let iter = &args[0].node; let zip_arg = &args[1]; @@ -64,9 +65,11 @@ impl LateLintPass for StepByZero { let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, iter_path == len_path ], { - cx.span_lint(RANGE_ZIP_WITH_LEN, expr.span, - &format!("It is more idiomatic to use {}.iter().enumerate()", - snippet(cx, iter_args[0].span, "_"))); + span_lint(cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); } } } -- cgit 1.4.1-3-g733a5 From 7877a42308a05597840f212d10d2abb27086669f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 19 Mar 2016 15:06:56 +0100 Subject: Fix some spelling mistakes here and there --- src/copies.rs | 2 +- src/derive.rs | 2 +- src/items_after_statements.rs | 6 +++--- src/lib.rs | 4 ++-- src/misc_early.rs | 4 ++-- src/needless_bool.rs | 4 ++-- src/utils/hir.rs | 2 +- tests/compile-fail/bool_comparison.rs | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index 789f852c6c3..04f8aaa37e7 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -47,7 +47,7 @@ declare_lint! { /// match foo { /// Bar => bar(), /// Quz => quz(), -/// Baz => bar(), // <= oups +/// Baz => bar(), // <= oops /// } /// ``` declare_lint! { diff --git a/src/derive.rs b/src/derive.rs index 4a20d8018de..ab4f73eafc0 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -14,7 +14,7 @@ use utils::{match_path, span_lint_and_then}; /// /// **Why is this bad?** The implementation of these traits must agree (for example for use with /// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation with -/// an explicitely defined `PartialEq`. In particular, the following must hold for any type: +/// an explicitly defined `PartialEq`. In particular, the following must hold for any type: /// /// ```rust /// k1 == k2 ⇒ hash(k1) == hash(k2) diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index a2ab7246942..952dcb7ed9c 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -32,15 +32,15 @@ declare_lint! { "finds blocks where an item comes after a statement" } -pub struct ItemsAfterStatemets; +pub struct ItemsAfterStatements; -impl LintPass for ItemsAfterStatemets { +impl LintPass for ItemsAfterStatements { fn get_lints(&self) -> LintArray { lint_array!(ITEMS_AFTER_STATEMENTS) } } -impl EarlyLintPass for ItemsAfterStatemets { +impl EarlyLintPass for ItemsAfterStatements { fn check_block(&mut self, cx: &EarlyContext, item: &Block) { if in_macro(cx, item.span) { return; diff --git a/src/lib.rs b/src/lib.rs index 7d24b2c8924..75b5ec4cc23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,7 +134,7 @@ pub fn plugin_registrar(reg: &mut Registry) { } Err((err, span)) => { reg.sess.struct_span_err(span, err) - .span_note(span, "Clippy will use defaulf configuration") + .span_note(span, "Clippy will use default configuration") .emit(); utils::conf::Conf::default() } @@ -163,7 +163,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box precedence::Precedence); reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); - reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatemets); + reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements); reg.register_late_lint_pass(box mut_mut::MutMut); reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); reg.register_late_lint_pass(box len_zero::LenZero); diff --git a/src/misc_early.rs b/src/misc_early.rs index 60e175d6382..b1c584a4b3e 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -110,10 +110,10 @@ impl EarlyLintPass for MiscEarly { let arg_name = sp_ident.node.to_string(); if arg_name.starts_with('_') { - if let Some(correspondance) = registered_names.get(&arg_name[1..]) { + if let Some(correspondence) = registered_names.get(&arg_name[1..]) { span_lint(cx, DUPLICATE_UNDERSCORE_ARGUMENT, - *correspondance, + *correspondence, &format!("`{}` already exists, having another argument having almost the same \ name makes code comprehension and documentation more difficult", arg_name[1..].to_owned()));; diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 43e7cfddadd..ab5a1e26b20 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -105,7 +105,7 @@ impl LateLintPass for BoolComparison { span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against true are unnecesary", + "equality checks against true are unnecessary", |db| { db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); @@ -115,7 +115,7 @@ impl LateLintPass for BoolComparison { span_lint_and_then(cx, BOOL_COMPARISON, e.span, - "equality checks against true are unnecesary", + "equality checks against true are unnecessary", |db| { db.span_suggestion(e.span, "try simplifying it as shown:", hint); }); diff --git a/src/utils/hir.rs b/src/utils/hir.rs index ed2a49b3caa..20c7e33fbb2 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -13,7 +13,7 @@ use utils::differing_macro_contexts; pub struct SpanlessEq<'a, 'tcx: 'a> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'a, 'tcx>, - /// If is true, never consider as equal expressions containing fonction calls. + /// If is true, never consider as equal expressions containing function calls. ignore_fn: bool, } diff --git a/tests/compile-fail/bool_comparison.rs b/tests/compile-fail/bool_comparison.rs index 8a792931d02..83675945519 100644 --- a/tests/compile-fail/bool_comparison.rs +++ b/tests/compile-fail/bool_comparison.rs @@ -5,7 +5,7 @@ fn main() { let x = true; if x == true { "yes" } else { "no" }; - //~^ ERROR equality checks against true are unnecesary + //~^ ERROR equality checks against true are unnecessary //~| HELP try simplifying it as shown: //~| SUGGESTION if x { "yes" } else { "no" }; if x == false { "yes" } else { "no" }; @@ -13,7 +13,7 @@ fn main() { //~| HELP try simplifying it as shown: //~| SUGGESTION if !x { "yes" } else { "no" }; if true == x { "yes" } else { "no" }; - //~^ ERROR equality checks against true are unnecesary + //~^ ERROR equality checks against true are unnecessary //~| HELP try simplifying it as shown: //~| SUGGESTION if x { "yes" } else { "no" }; if false == x { "yes" } else { "no" }; -- cgit 1.4.1-3-g733a5 From cfb1bc3723f42e98d08e24001696abc5a17bc8a6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 19 Mar 2016 15:09:24 +0100 Subject: `chmod -x` test files --- tests/compile-fail/blacklisted_name.rs | 0 tests/compile-fail/conf_french_blacklisted_name.rs | 0 tests/compile-fail/copies.rs | 0 tests/compile-fail/derive.rs | 0 tests/compile-fail/format.rs | 0 tests/compile-fail/formatting.rs | 0 tests/compile-fail/functions.rs | 0 tests/compile-fail/new_without_default.rs | 0 tests/compile-fail/print.rs | 0 tests/compile-fail/swap.rs | 0 tests/compile-fail/unused_labels.rs | 0 tests/compile-fail/vec.rs | 0 tests/run-pass/ice-700.rs | 0 13 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/compile-fail/blacklisted_name.rs mode change 100755 => 100644 tests/compile-fail/conf_french_blacklisted_name.rs mode change 100755 => 100644 tests/compile-fail/copies.rs mode change 100755 => 100644 tests/compile-fail/derive.rs mode change 100755 => 100644 tests/compile-fail/format.rs mode change 100755 => 100644 tests/compile-fail/formatting.rs mode change 100755 => 100644 tests/compile-fail/functions.rs mode change 100755 => 100644 tests/compile-fail/new_without_default.rs mode change 100755 => 100644 tests/compile-fail/print.rs mode change 100755 => 100644 tests/compile-fail/swap.rs mode change 100755 => 100644 tests/compile-fail/unused_labels.rs mode change 100755 => 100644 tests/compile-fail/vec.rs mode change 100755 => 100644 tests/run-pass/ice-700.rs diff --git a/tests/compile-fail/blacklisted_name.rs b/tests/compile-fail/blacklisted_name.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/conf_french_blacklisted_name.rs b/tests/compile-fail/conf_french_blacklisted_name.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/derive.rs b/tests/compile-fail/derive.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/format.rs b/tests/compile-fail/format.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/formatting.rs b/tests/compile-fail/formatting.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/functions.rs b/tests/compile-fail/functions.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/print.rs b/tests/compile-fail/print.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/swap.rs b/tests/compile-fail/swap.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/unused_labels.rs b/tests/compile-fail/unused_labels.rs old mode 100755 new mode 100644 diff --git a/tests/compile-fail/vec.rs b/tests/compile-fail/vec.rs old mode 100755 new mode 100644 diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs old mode 100755 new mode 100644 -- cgit 1.4.1-3-g733a5 From 941ec6e4f5cfc54078f5fe65702ec46b6c59b8d2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 19 Mar 2016 17:48:29 +0100 Subject: Beautify more docs --- src/bit_mask.rs | 36 +++++++++++++++++----------------- src/consts.rs | 2 +- src/formatting.rs | 4 ++-- src/len_zero.rs | 6 +++--- src/loops.rs | 8 ++++---- src/matches.rs | 2 +- src/non_expressive_names.rs | 2 +- src/ptr_arg.rs | 4 +--- src/strings.rs | 2 +- src/utils/mod.rs | 10 +++++----- src/zero_div_zero.rs | 2 +- tests/compile-fail/methods.rs | 10 +++++----- tests/used_underscore_binding_macro.rs | 2 +- 13 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index f96927f1548..15fbabf9f0b 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -13,14 +13,14 @@ use utils::span_lint; /// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` /// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: /// -/// |Comparison |Bit-Op|Example |is always|Formula | -/// |------------|------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// |Comparison |Bit Op |Example |is always|Formula | +/// |------------|-------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | /// /// **Why is this bad?** If the bits that the comparison cares about are always set to zero or one by the bit mask, the comparison is constant `true` or `false` (depending on mask, compared value, and operators). /// @@ -38,7 +38,7 @@ declare_lint! { /// **What it does:** This lint checks for bit masks in comparisons which can be removed without changing the outcome. The basic structure can be seen in the following table: /// -/// |Comparison|Bit-Op |Example |equals | +/// |Comparison| Bit Op |Example |equals | /// |----------|---------|-----------|-------| /// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| /// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`| @@ -61,21 +61,21 @@ declare_lint! { /// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , /// `!=`, `>=`, `>`}) can be determined from the following table: /// -/// |Comparison |Bit-Op|Example |is always|Formula | -/// |------------|------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// |Comparison |Bit Op |Example |is always|Formula | +/// |------------|-------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | /// /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* /// by default. /// -/// |Comparison|Bit-Op |Example |equals |Formula| +/// |Comparison| Bit Op |Example |equals |Formula| /// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| /// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | /// diff --git a/src/consts.rs b/src/consts.rs index 67da1216c42..97a99dda4b5 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -30,7 +30,7 @@ impl From<FloatTy> for FloatWidth { } } -/// a Lit_-like enum to fold constant `Expr`s into +/// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] pub enum Constant { /// a String "abc" diff --git a/src/formatting.rs b/src/formatting.rs index 091280de28d..aa6dd46cf0b 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -82,7 +82,7 @@ impl EarlyLintPass for Formatting { } } -/// Implementation of the SUSPICIOUS_ASSIGNMENT_FORMATTING lint. +/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint. fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) { @@ -108,7 +108,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { } } -/// Implementation of the SUSPICIOUS_ELSE_FORMATTING lint for weird `else if`. +/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`. fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) { diff --git a/src/len_zero.rs b/src/len_zero.rs index 6dad8684354..1a097820e1e 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -164,9 +164,9 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], l } } -/// check if this type has an is_empty method +/// Check if this type has an `is_empty` method. fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { - /// get a ImplOrTraitItem and return true if it matches is_empty(self) + /// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { if let MethodTraitItemId(def_id) = *id { if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { @@ -179,7 +179,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { } } - /// check the inherent impl's items for an is_empty(self) method + /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool { let impl_items = cx.tcx.impl_items.borrow(); cx.tcx.inherent_impls.borrow().get(id).map_or(false, |ids| { diff --git a/src/loops.rs b/src/loops.rs index c0d3993746a..546f07a6507 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -571,7 +571,7 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex } } -/// Check for the FOR_KV_MAP lint. +/// Check for the `FOR_KV_MAP` lint. fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let PatKind::Tup(ref pat) = pat.node { if pat.len() == 2 { @@ -607,7 +607,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex } -/// Return true if the pattern is a `PatWild` or an ident prefixed with '_'. +/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { PatKind::Wild => true, @@ -750,8 +750,8 @@ impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { } -/// Return true if the type of expr is one that provides IntoIterator impls -/// for &T and &mut T, such as Vec. +/// Return true if the type of expr is one that provides `IntoIterator` impls +/// for `&T` and `&mut T`, such as `Vec`. #[cfg_attr(rustfmt, rustfmt_skip)] fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it diff --git a/src/matches.rs b/src/matches.rs index bc3b45b32ef..7bffd445f6b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -330,7 +330,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match } } -/// Get all arms that are unbounded PatRange-s. +/// Get all arms that are unbounded `PatRange`s. fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { arms.iter() .filter_map(|arm| { diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index b7d2ac80a10..d7cb6fc5d28 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -251,7 +251,7 @@ impl EarlyLintPass for NonExpressiveNames { } } -/// precondition: a_name.chars().count() < b_name.chars().count() +/// Precondition: `a_name.chars().count() < b_name.chars().count()`. fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { debug_assert!(a_name.chars().count() < b_name.chars().count()); let mut a_chars = a_name.chars(); diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index b7882bfda16..6498db66e13 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -1,6 +1,4 @@ -//! Checks for usage of &Vec[_] and &String -//! -//! This lint is **warn** by default +//! Checks for usage of `&Vec[_]` and `&String`. use rustc::front::map::NodeItem; use rustc::lint::*; diff --git a/src/strings.rs b/src/strings.rs index aa9cdcce50c..9f68175b202 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -1,4 +1,4 @@ -//! This LintPass catches both string addition and string addition + assignment +//! This lint catches both string addition and string addition + assignment //! //! Note that since we have two lints where one subsumes the other, we try to //! disable the subsumed lint unless it has a higher level diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 017890dc461..34404f4c2e9 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -129,8 +129,8 @@ pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// Returns true if the macro that expanded the crate was outside of the current crate or was a /// compiler plugin. pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { - /// Invokes in_macro with the expansion info of the given span slightly heavy, try to use this - /// after other checks have already happened. + /// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use + /// this after other checks have already happened. fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { @@ -657,7 +657,7 @@ pub fn is_direct_expn_of(cx: &LateContext, span: Span, name: &str) -> Option<Spa } } -/// Returns index of character after first CamelCase component of `s` +/// Return the index of the character after the first camel-case component of `s`. pub fn camel_case_until(s: &str) -> usize { let mut iter = s.char_indices(); if let Some((_, first)) = iter.next() { @@ -690,7 +690,7 @@ pub fn camel_case_until(s: &str) -> usize { } } -/// Returns index of last CamelCase component of `s`. +/// Return index of the last camel-case component of `s`. pub fn camel_case_from(s: &str) -> usize { let mut iter = s.char_indices().rev(); if let Some((_, first)) = iter.next() { @@ -719,7 +719,7 @@ pub fn camel_case_from(s: &str) -> usize { last_i } -/// Represents a range akin to `ast::ExprKind::Range`. +/// Represent a range akin to `ast::ExprKind::Range`. #[derive(Debug, Copy, Clone)] pub struct UnsugaredRange<'a> { pub start: Option<&'a Expr>, diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index 1d119b05176..f58b0e695a9 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -4,7 +4,7 @@ use rustc_front::hir::*; use utils::span_help_and_lint; /// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists -/// `of 0.0/0.0`, which is always NaN. It is more clear to replace instances of +/// `of 0.0/0.0`, which is always `NaN`. It is more clear to replace instances of /// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. pub struct ZeroDivZeroPass; diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 74f262b05a7..9d938ebb19e 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -85,8 +85,8 @@ macro_rules! opt_map { } /// Checks implementation of the following lints: -/// OPTION_MAP_UNWRAP_OR -/// OPTION_MAP_UNWRAP_OR_ELSE +/// * `OPTION_MAP_UNWRAP_OR` +/// * `OPTION_MAP_UNWRAP_OR_ELSE` fn option_methods() { let opt = Some(1); @@ -154,7 +154,7 @@ impl IteratorFalsePositives { } } -/// Checks implementation of FILTER_NEXT lint +/// Checks implementation of `FILTER_NEXT` lint fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; @@ -174,7 +174,7 @@ fn filter_next() { let _ = foo.filter().next(); } -/// Checks implementation of SEARCH_IS_SOME lint +/// Checks implementation of `SEARCH_IS_SOME` lint fn search_is_some() { let v = vec![3, 2, 1, 0, -1, -2, -3]; @@ -218,7 +218,7 @@ fn search_is_some() { let _ = foo.rposition().is_some(); } -/// Checks implementation of the OR_FUN_CALL lint +/// Checks implementation of the `OR_FUN_CALL` lint fn or_fun_call() { struct Foo; diff --git a/tests/used_underscore_binding_macro.rs b/tests/used_underscore_binding_macro.rs index 4170f907b0a..7a8faa62742 100644 --- a/tests/used_underscore_binding_macro.rs +++ b/tests/used_underscore_binding_macro.rs @@ -3,7 +3,7 @@ extern crate rustc_serialize; -/// Test that we do not lint for unused underscores in a MacroAttribute expansion +/// Test that we do not lint for unused underscores in a `MacroAttribute` expansion #[deny(used_underscore_binding)] #[derive(RustcEncodable)] struct MacroAttributesTest { -- cgit 1.4.1-3-g733a5 From 42bf37f49f49829507be4f2dfd6c5db9b8234b66 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 19 Mar 2016 17:59:12 +0100 Subject: Add a lint for bad documentation formatting --- README.md | 1 + src/doc.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ tests/compile-fail/doc.rs | 26 +++++++++++ 4 files changed, 142 insertions(+) create mode 100644 src/doc.rs create mode 100755 tests/compile-fail/doc.rs diff --git a/README.md b/README.md index 95ba6b08539..e4d18c28bfe 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ name [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly +[doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | checks for the presence of the `_` character outside ticks in documentation [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected diff --git a/src/doc.rs b/src/doc.rs new file mode 100644 index 00000000000..610aa34ab2c --- /dev/null +++ b/src/doc.rs @@ -0,0 +1,112 @@ +use rustc::lint::*; +use std::borrow::Cow; +use syntax::ast; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** This lint checks for the presence of the `_` character outside ticks in +/// documentation. +/// +/// **Why is this bad?** *Rustdoc* supports markdown formatting, the `_` character probably +/// indicates some code which should be included between ticks. +/// +/// **Known problems:** Lots of bad docs won’t be fixed, the lint only checks for `_`. +/// +/// **Examples:** +/// ```rust +/// /// Do something with the foo_bar parameter. +/// fn doit(foo_bar) { .. } +/// ``` +declare_lint! { + pub DOC_MARKDOWN, Warn, + "checks for the presence of the `_` character outside ticks in documentation" +} + +#[derive(Copy,Clone)] +pub struct Doc; + +impl LintPass for Doc { + fn get_lints(&self) -> LintArray { + lint_array![DOC_MARKDOWN] + } +} + +impl EarlyLintPass for Doc { + fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { + check_attrs(cx, &krate.attrs, krate.span); + } + + fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { + check_attrs(cx, &item.attrs, item.span); + } +} + +/// Collect all doc attributes. Multiple `///` are represented in different attributes. `rustdoc` +/// has a pass to merge them, but we probably don’t want to invoke that here. +fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { + fn doc_and_span(attr: &ast::Attribute) -> Option<(&str, Span)> { + if attr.node.is_sugared_doc { + if let ast::MetaItemKind::NameValue(_, ref doc) = attr.node.value.node { + if let ast::LitKind::Str(ref doc, _) = doc.node { + return Some((&doc[..], attr.span)); + } + } + } + + None + } + let doc_and_span: fn(_) -> _ = doc_and_span; + + let mut doc_attrs = attrs.iter().filter_map(doc_and_span); + + let count = doc_attrs.clone().take(2).count(); + + match count { + 0 => ("".into(), None), + 1 => { + let (doc, span) = doc_attrs.next().unwrap_or_else(|| unreachable!()); + (doc.into(), Some(span)) + } + _ => (doc_attrs.map(|s| s.0).collect::<String>().into(), None), + } +} + +fn check_attrs<'a>(cx: &EarlyContext, attrs: &'a [ast::Attribute], default_span: Span) { + let (doc, span) = collect_doc(attrs); + let span = span.unwrap_or(default_span); + + let mut in_ticks = false; + for word in doc.split_whitespace() { + let ticks = word.bytes().filter(|&b| b == b'`').count(); + + if ticks == 2 { // likely to be “`foo`” + continue; + } else if ticks % 2 == 1 { + in_ticks = !in_ticks; + continue; // let’s assume no one will ever write something like “`foo`_bar” + } + + if !in_ticks { + check_word(cx, word, span); + } + } +} + +fn check_word(cx: &EarlyContext, word: &str, span: Span) { + /// Checks if a string a camel-case, ie. contains at least two uppercase letter (`Clippy` is + /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok). + fn is_camel_case(s: &str) -> bool { + let s = if s.ends_with('s') { + &s[..s.len()-1] + } else { + s + }; + + s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && + s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 + } + + if word.contains('_') || is_camel_case(word) { + span_lint(cx, DOC_MARKDOWN, span, &format!("you should put `{}` between ticks in the documentation", word)); + } +} diff --git a/src/lib.rs b/src/lib.rs index 75b5ec4cc23..0a51385f6f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,7 @@ pub mod collapsible_if; pub mod copies; pub mod cyclomatic_complexity; pub mod derive; +pub mod doc; pub mod drop_ref; pub mod entry; pub mod enum_clike; @@ -223,6 +224,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); + reg.register_early_lint_pass(box doc::Doc); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -265,6 +267,7 @@ pub fn plugin_registrar(reg: &mut Registry) { cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_XOR_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, + doc::DOC_MARKDOWN, drop_ref::DROP_REF, entry::MAP_ENTRY, enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs new file mode 100755 index 00000000000..9eb949a3b68 --- /dev/null +++ b/tests/compile-fail/doc.rs @@ -0,0 +1,26 @@ +//! This file tests for the DOC_MARKDOWN lint +//~^ ERROR: you should put `DOC_MARKDOWN` between ticks + +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(doc_markdown)] + +/// The foo_bar function does nothing. +//~^ ERROR: you should put `foo_bar` between ticks +fn foo_bar() { +} + +/// That one tests multiline ticks. +/// ```rust +/// foo_bar FOO_BAR +/// ``` +fn multiline_ticks() { +} + +/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and +/// `multiline_ticks` functions. +fn main() { + foo_bar(); + multiline_ticks(); +} -- cgit 1.4.1-3-g733a5 From b1d1f095f12d6640aac2ab7e8ad29fc36de90b39 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 28 Mar 2016 18:00:24 +0200 Subject: Improve the DOC_MARKDOWN lint `_` can be used for emphasize text. `::` is equality as bad outside ticks. --- README.md | 2 +- src/doc.rs | 37 +++++++++++++++++++++++++++++-------- tests/compile-fail/doc.rs | 8 ++++++-- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e4d18c28bfe..264bc6f010b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ name [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -[doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | checks for the presence of the `_` character outside ticks in documentation +[doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | checks for the presence of `_`, `::` or camel-case outside ticks in documentation [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected diff --git a/src/doc.rs b/src/doc.rs index 610aa34ab2c..a4a0448c102 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -4,22 +4,23 @@ use syntax::ast; use syntax::codemap::Span; use utils::span_lint; -/// **What it does:** This lint checks for the presence of the `_` character outside ticks in -/// documentation. +/// **What it does:** This lint checks for the presence of `_`, `::` or camel-case words outside +/// ticks in documentation. /// -/// **Why is this bad?** *Rustdoc* supports markdown formatting, the `_` character probably +/// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and camel-case probably /// indicates some code which should be included between ticks. /// -/// **Known problems:** Lots of bad docs won’t be fixed, the lint only checks for `_`. +/// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks for is limited. /// /// **Examples:** /// ```rust -/// /// Do something with the foo_bar parameter. +/// /// Do something with the foo_bar parameter. See also that::other::module::foo. +/// // ^ `foo_bar` and `that::other::module::foo` should be ticked. /// fn doit(foo_bar) { .. } /// ``` declare_lint! { pub DOC_MARKDOWN, Warn, - "checks for the presence of the `_` character outside ticks in documentation" + "checks for the presence of `_`, `::` or camel-case outside ticks in documentation" } #[derive(Copy,Clone)] @@ -71,10 +72,21 @@ fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { } } -fn check_attrs<'a>(cx: &EarlyContext, attrs: &'a [ast::Attribute], default_span: Span) { +pub fn check_attrs<'a>(cx: &EarlyContext, attrs: &'a [ast::Attribute], default_span: Span) { let (doc, span) = collect_doc(attrs); let span = span.unwrap_or(default_span); + // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. + // There really is no markdown specification that would disambiguate this properly. This is + // what GitHub and Rustdoc do: + // + // foo_bar test_quz → foo_bar test_quz + // foo_bar_baz → foo_bar_baz (note that the “official” spec says this should be emphasized) + // _foo bar_ test_quz_ → <em>foo bar</em> test_quz_ + // \_foo bar\_ → _foo bar_ + // (_baz_) → (<em>baz</em>) + // foo _ bar _ baz → foo _ bar _ baz + let mut in_ticks = false; for word in doc.split_whitespace() { let ticks = word.bytes().filter(|&b| b == b'`').count(); @@ -106,7 +118,16 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 } - if word.contains('_') || is_camel_case(word) { + fn has_underscore(s: &str) -> bool { + s != "_" && !s.contains("\\_") && s.contains('_') + } + + // Trim punctuation as in `some comment (see foo::bar).` + // ^^ + // Or even as `_foo bar_` which is emphasized. + let word = word.trim_matches(|c: char| !c.is_alphanumeric()); + + if has_underscore(word) || word.contains("::") || is_camel_case(word) { span_lint(cx, DOC_MARKDOWN, span, &format!("you should put `{}` between ticks in the documentation", word)); } } diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 9eb949a3b68..35b5857d937 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -6,9 +6,13 @@ #![deny(doc_markdown)] -/// The foo_bar function does nothing. -//~^ ERROR: you should put `foo_bar` between ticks +/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun +/// which should be reported only once despite being __doubly bad__. fn foo_bar() { +//~^ ERROR: you should put `foo_bar` between ticks +//~| ERROR: you should put `foo::bar` between ticks +//~| ERROR: you should put `Foo::some_fun` between ticks } /// That one tests multiline ticks. -- cgit 1.4.1-3-g733a5 From 371a5537eb0435fef43763d1bbbc21007ac707e4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 28 Mar 2016 21:23:21 +0200 Subject: Address nits in DOC_MARKDOWN --- README.md | 2 +- src/bit_mask.rs | 34 +++++++++++++++++----------------- src/doc.rs | 4 +++- tests/compile-fail/doc.rs | 8 ++++++++ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 264bc6f010b..43caa80543a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 136 lints included in this crate: +There are 137 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 15fbabf9f0b..28fc311507d 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -13,14 +13,14 @@ use utils::span_lint; /// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` /// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: /// -/// |Comparison |Bit Op |Example |is always|Formula | -/// |------------|-------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// |Comparison |Bit Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | /// /// **Why is this bad?** If the bits that the comparison cares about are always set to zero or one by the bit mask, the comparison is constant `true` or `false` (depending on mask, compared value, and operators). /// @@ -61,21 +61,21 @@ declare_lint! { /// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , /// `!=`, `>=`, `>`}) can be determined from the following table: /// -/// |Comparison |Bit Op |Example |is always|Formula | -/// |------------|-------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// |Comparison |Bit Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | /// /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* /// by default. /// -/// |Comparison| Bit Op |Example |equals |Formula| +/// |Comparison|Bit Op |Example |equals |Formula| /// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| /// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | /// diff --git a/src/doc.rs b/src/doc.rs index a4a0448c102..5637fb2cefb 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -8,7 +8,8 @@ use utils::span_lint; /// ticks in documentation. /// /// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and camel-case probably -/// indicates some code which should be included between ticks. +/// indicates some code which should be included between ticks. `_` can also be used for empasis in +/// markdown, this lint tries to consider that. /// /// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks for is limited. /// @@ -114,6 +115,7 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { s }; + s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 } diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 35b5857d937..eecf5e0b206 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -18,13 +18,21 @@ fn foo_bar() { /// That one tests multiline ticks. /// ```rust /// foo_bar FOO_BAR +/// _foo bar_ /// ``` fn multiline_ticks() { } +/// This _is a test for +/// multiline +/// emphasis_. +fn test_emphasis() { +} + /// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and /// `multiline_ticks` functions. fn main() { foo_bar(); multiline_ticks(); + test_emphasis(); } -- cgit 1.4.1-3-g733a5 From 777e810a394bdf8becc308704f7df5ade9321f79 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 28 Mar 2016 23:32:55 +0200 Subject: Add `for _ in vec![…]` to the `USELESS_VEC` lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/loops.rs | 26 +--------------------- src/utils/mod.rs | 24 ++++++++++++++++++++ src/vec.rs | 56 ++++++++++++++++++++++++++++------------------- tests/compile-fail/vec.rs | 7 ++++++ 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 546f07a6507..10a8a76d7ae 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -14,7 +14,7 @@ use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, - unsugar_range, walk_ptrs_ty}; + unsugar_range, walk_ptrs_ty, recover_for_loop}; use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; use utils::UnsugaredRange; @@ -641,30 +641,6 @@ impl<'a> Visitor<'a> for UsedVisitor { } } -/// Recover the essential nodes of a desugared for loop: -/// `for pat in arg { body }` becomes `(pat, arg, body)`. -fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { - if_let_chain! { - [ - let ExprMatch(ref iterexpr, ref arms, _) = expr.node, - let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let ExprLoop(ref block, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, - somepats.len() == 1 - ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); - } - } - None -} - struct VarVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference var: Name, // var name to look for as index diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 34404f4c2e9..300cb8df042 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -800,3 +800,27 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs); infcx.can_equate(&new_a, &new_b).is_ok() } + +/// Recover the essential nodes of a desugared for loop: +/// `for pat in arg { body }` becomes `(pat, arg, body)`. +pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { + if_let_chain! { + [ + let ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), + let ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); + } + } + None +} diff --git a/src/vec.rs b/src/vec.rs index 481c84079f2..412ebf396dd 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -4,7 +4,7 @@ use rustc_front::hir::*; use syntax::codemap::Span; use syntax::ptr::P; use utils::VEC_FROM_ELEM_PATH; -use utils::{is_expn_of, match_path, snippet, span_lint_and_then}; +use utils::{is_expn_of, match_path, recover_for_loop, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -38,32 +38,42 @@ impl LateLintPass for UselessVec { let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, let TypeVariants::TySlice(..) = ty.ty.sty, let ExprAddrOf(_, ref addressee) = expr.node, - let Some(vec_args) = unexpand_vec(cx, addressee) ], { - let snippet = match vec_args { - VecArgs::Repeat(elem, len) => { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() - } - VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = Span { - lo: args[0].span.lo, - hi: last.span.hi, - expn_id: args[0].span.expn_id, - }; + check_vec_macro(cx, expr, addressee); + }} + + // search for `for _ in vec![…]` + if let Some((_, arg, _)) = recover_for_loop(expr) { + check_vec_macro(cx, arg, arg); + } + } +} + +fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) { + if let Some(vec_args) = unexpand_vec(cx, vec) { + let snippet = match vec_args { + VecArgs::Repeat(elem, len) => { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } + VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = Span { + lo: args[0].span.lo, + hi: last.span.hi, + expn_id: args[0].span.expn_id, + }; - format!("&[{}]", snippet(cx, span, "..")).into() - } - else { - "&[]".into() - } + format!("&[{}]", snippet(cx, span, "..")).into() + } + else { + "&[]".into() } - }; + } + }; - span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| { - db.span_suggestion(expr.span, "you can use a slice directly", snippet); - }); - }} + span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| { + db.span_suggestion(expr.span, "you can use a slice directly", snippet); + }); } } diff --git a/tests/compile-fail/vec.rs b/tests/compile-fail/vec.rs index b4f52ecadc5..eda75a2fe8a 100644 --- a/tests/compile-fail/vec.rs +++ b/tests/compile-fail/vec.rs @@ -41,4 +41,11 @@ fn main() { on_vec(&vec![]); on_vec(&vec![1, 2]); on_vec(&vec![1; 2]); + + for a in vec![1, 2, 3] { + //~^ ERROR useless use of `vec!` + //~| HELP you can use + //~| SUGGESTION for a in &[1, 2, 3] { + println!("{}", a); + } } -- cgit 1.4.1-3-g733a5 From 0939f5a2ec9797c9277b2dabd578429264da0498 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 29 Mar 2016 01:39:35 +0200 Subject: Fix false positive in `MATCH_SAME_ARMS` and guards --- src/copies.rs | 6 ++++-- tests/compile-fail/copies.rs | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/copies.rs b/src/copies.rs index 04f8aaa37e7..2de034f83c2 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -132,13 +132,15 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { }; let eq = |lhs: &Arm, rhs: &Arm| -> bool { - SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && + // Arms with a guard are ignored, those can’t always be merged together + lhs.guard.is_none() && rhs.guard.is_none() && + SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && // all patterns should have the same bindings bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) }; if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { - if let Some((i, j)) = search_same(&**arms, hash, eq) { + if let Some((i, j)) = search_same(&arms, hash, eq) { span_note_and_lint(cx, MATCH_SAME_ARMS, j.body.span, diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 66457e77f47..68756a57cc7 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -142,12 +142,23 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => true, }; + let _ = match Some(42) { + Some(_) => 24, + None => 24, + }; + let _ = match Some(42) { Some(42) => 24, Some(a) => 24, // bindings are different None => 0, }; + let _ = match Some(42) { + Some(a) if a > 0 => 24, + Some(a) => 24, // one arm has a guard + None => 0, + }; + match (Some(42), Some(42)) { (Some(a), None) => bar(a), (None, Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies -- cgit 1.4.1-3-g733a5 From 54c8c23a74ffb770b30896e1ff5b194387a5cf0d Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann <ben@create-build-execute.com> Date: Tue, 29 Mar 2016 10:24:35 +0200 Subject: Add Post-Success script to build clippy-service --- .travis.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.travis.yml b/.travis.yml index a0893d9c1c6..322e03258d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,3 +10,25 @@ script: # only test regex_macros if it compiles - if [[ "$(cargo build --features 'debugging test-regex_macros')" = 101 ]]; then cargo test --features 'debugging test-regex_macros'; fi + +# trigger rebuild of the clippy-service +after_success: +- | + #!/bin/bash + set -e + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && + [ "$TRAVIS_REPO_SLUG" == "Manishearth/rust-clippy" ] && + [ "$TRAVIS_BRANCH" == "master" ] && + [ "$TRAVIS_TOKEN_CLIPPY_SERVICE" != "" ] ; then + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Travis-API-Version: 3" \ + -H "Authorization: token $TRAVIS_TOKEN_CLIPPY_SERVICE" \ + -d "{ \"request\": { \"branch\":\"master\" }}" \ + https://api.travis-ci.org/repo/ligthyear%2Fclippy-service/requests + + else + echo "Ignored" + fi -- cgit 1.4.1-3-g733a5 From 93d097eb12fc0b7e34187d2cac19b0059fa18ed4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 12:19:13 +0100 Subject: better simplification --- Cargo.toml | 1 + README.md | 3 +- src/booleans.rs | 155 ++++++++++++++++++++++++++++ src/lib.rs | 8 ++ tests/compile-fail/block_in_if_condition.rs | 2 +- tests/compile-fail/eq_op.rs | 2 + 6 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/booleans.rs diff --git a/Cargo.toml b/Cargo.toml index 3bb7a82f6e2..93886e214e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" +quine-mc_cluskey = "0.2" [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/README.md b/README.md index 43caa80543a..cd8b0257c6e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 137 lints included in this crate: +There are 138 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -97,6 +97,7 @@ name [new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead +[nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | warn | checks for boolean expressions that can be written more concisely [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result [option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` diff --git a/src/booleans.rs b/src/booleans.rs new file mode 100644 index 00000000000..90e4dee9769 --- /dev/null +++ b/src/booleans.rs @@ -0,0 +1,155 @@ +use rustc::lint::*; +use rustc_front::hir::*; +use rustc_front::intravisit::*; +use syntax::ast::LitKind; +use utils::{span_lint_and_then, in_macro, snippet_opt}; + +/// **What it does:** This lint checks for boolean expressions that can be written more concisely +/// +/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication +/// +/// **Known problems:** None +/// +/// **Example:** `if a && b || a` should be `if a` +declare_lint! { + pub NONMINIMAL_BOOL, Warn, + "checks for boolean expressions that can be written more concisely" +} + +#[derive(Copy,Clone)] +pub struct NonminimalBool; + +impl LintPass for NonminimalBool { + fn get_lints(&self) -> LintArray { + lint_array!(NONMINIMAL_BOOL) + } +} + +impl LateLintPass for NonminimalBool { + fn check_crate(&mut self, cx: &LateContext, krate: &Crate) { + krate.visit_all_items(&mut NonminimalBoolVisitor(cx)) + } +} + +struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); + +use quine_mc_cluskey::Bool; +struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>); + +impl<'tcx> Hir2Qmm<'tcx> { + fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> { + for a in a { + if let ExprBinary(binop, ref lhs, ref rhs) = a.node { + if binop.node == op { + v = self.extract(op, &[lhs, rhs], v)?; + continue; + } + } + v.push(self.run(a)?); + } + Ok(v) + } + + fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> { + match e.node { + ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), + ExprBinary(binop, ref lhs, ref rhs) => { + match binop.node { + BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), + BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + _ => {}, + } + }, + ExprLit(ref lit) => { + match lit.node { + LitKind::Bool(true) => return Ok(Bool::True), + LitKind::Bool(false) => return Ok(Bool::False), + _ => {}, + } + }, + _ => {}, + } + let n = self.0.len(); + self.0.push(e); + if n < 32 { + #[allow(cast_possible_truncation)] + Ok(Bool::Term(n as u8)) + } else { + Err("too many literals".to_owned()) + } + } +} + +fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { + fn recurse(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { + use quine_mc_cluskey::Bool::*; + match *suggestion { + True => { + s.extend("true".chars()); + s + }, + False => { + s.extend("false".chars()); + s + }, + Not(ref inner) => { + s.push('!'); + recurse(cx, inner, terminals, s) + }, + And(ref v) => { + s = recurse(cx, &v[0], terminals, s); + for inner in &v[1..] { + s.extend(" && ".chars()); + s = recurse(cx, inner, terminals, s); + } + s + }, + Or(ref v) => { + s = recurse(cx, &v[0], terminals, s); + for inner in &v[1..] { + s.extend(" || ".chars()); + s = recurse(cx, inner, terminals, s); + } + s + }, + Term(n) => { + s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars()); + s + } + } + } + recurse(cx, suggestion, terminals, String::new()) +} + +impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { + fn bool_expr(&self, e: &Expr) { + let mut h2q = Hir2Qmm(Vec::new()); + if let Ok(expr) = h2q.run(e) { + let simplified = expr.simplify(); + if !simplified.iter().any(|s| *s == expr) { + span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { + for suggestion in &simplified { + db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0)); + } + }); + } + } + } +} + +impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { + fn visit_expr(&mut self, e: &'v Expr) { + if in_macro(self.0, e.span) { return } + match e.node { + ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), + ExprUnary(UnNot, ref inner) => { + if self.0.tcx.node_types()[&inner.id].is_bool() { + self.bool_expr(e); + } else { + walk_expr(self, e); + } + }, + _ => walk_expr(self, e), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 0a51385f6f2..575e318e7ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,8 @@ #![feature(iter_arith)] #![feature(custom_attribute)] #![feature(slice_patterns)] +#![feature(question_mark)] +#![feature(stmt_expr_attributes)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] // this only exists to allow the "dogfood" integration test to work @@ -35,6 +37,9 @@ extern crate semver; // for regex checking extern crate regex_syntax; +// for finding minimal boolean expressions +extern crate quine_mc_cluskey; + extern crate rustc_plugin; extern crate rustc_const_eval; use rustc_plugin::Registry; @@ -50,6 +55,7 @@ pub mod attrs; pub mod bit_mask; pub mod blacklisted_name; pub mod block_in_if_condition; +pub mod booleans; pub mod collapsible_if; pub mod copies; pub mod cyclomatic_complexity; @@ -149,6 +155,7 @@ pub fn plugin_registrar(reg: &mut Registry) { // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box types::TypePass); + reg.register_late_lint_pass(box booleans::NonminimalBool); reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); @@ -260,6 +267,7 @@ pub fn plugin_registrar(reg: &mut Registry) { blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, + booleans::NONMINIMAL_BOOL, collapsible_if::COLLAPSIBLE_IF, copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs index 5158e74c1e0..19fa949fb84 100644 --- a/tests/compile-fail/block_in_if_condition.rs +++ b/tests/compile-fail/block_in_if_condition.rs @@ -67,7 +67,7 @@ fn pred_test() { fn condition_is_normal() -> i32 { let x = 3; - if true && x == 3 { + if true && x == 3 { //~ WARN this boolean expression can be simplified 6 } else { 10 diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 487185516bf..bd76695e6ad 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -38,7 +38,9 @@ fn main() { 1 - 1; //~ERROR equal expressions 1 / 1; //~ERROR equal expressions true && true; //~ERROR equal expressions + //~|WARN this boolean expression can be simplified true || true; //~ERROR equal expressions + //~|WARN this boolean expression can be simplified let mut a = vec![1]; a == a; //~ERROR equal expressions -- cgit 1.4.1-3-g733a5 From 57faa5a9f58026ab167c1024c5a3b924156522c3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 12:49:16 +0100 Subject: improve bracket display --- src/booleans.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 90e4dee9769..5b29d33e891 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -81,7 +81,7 @@ impl<'tcx> Hir2Qmm<'tcx> { } fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { - fn recurse(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { + fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { use quine_mc_cluskey::Bool::*; match *suggestion { True => { @@ -94,21 +94,33 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { }, Not(ref inner) => { s.push('!'); - recurse(cx, inner, terminals, s) + recurse(true, cx, inner, terminals, s) }, And(ref v) => { - s = recurse(cx, &v[0], terminals, s); + if brackets { + s.push('('); + } + s = recurse(true, cx, &v[0], terminals, s); for inner in &v[1..] { s.extend(" && ".chars()); - s = recurse(cx, inner, terminals, s); + s = recurse(true, cx, inner, terminals, s); + } + if brackets { + s.push(')'); } s }, Or(ref v) => { - s = recurse(cx, &v[0], terminals, s); + if brackets { + s.push('('); + } + s = recurse(true, cx, &v[0], terminals, s); for inner in &v[1..] { s.extend(" || ".chars()); - s = recurse(cx, inner, terminals, s); + s = recurse(true, cx, inner, terminals, s); + } + if brackets { + s.push(')'); } s }, @@ -118,7 +130,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { } } } - recurse(cx, suggestion, terminals, String::new()) + recurse(false, cx, suggestion, terminals, String::new()) } impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { -- cgit 1.4.1-3-g733a5 From 1f1f09ba92b997388d7a653c6515fb4ab4e4a888 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 12:52:17 +0100 Subject: also compute minimal product of sum form --- src/booleans.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/booleans.rs b/src/booleans.rs index 5b29d33e891..178cef3aada 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -133,11 +133,40 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { recurse(false, cx, suggestion, terminals, String::new()) } +fn simple_negate(b: Bool) -> Bool { + use quine_mc_cluskey::Bool::*; + match b { + True => False, + False => True, + t @ Term(_) => Not(Box::new(t)), + And(mut v) => { + for el in &mut v { + *el = simple_negate(::std::mem::replace(el, True)); + } + Or(v) + }, + Or(mut v) => { + for el in &mut v { + *el = simple_negate(::std::mem::replace(el, True)); + } + And(v) + }, + Not(inner) => *inner, + } +} + impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { fn bool_expr(&self, e: &Expr) { let mut h2q = Hir2Qmm(Vec::new()); if let Ok(expr) = h2q.run(e) { - let simplified = expr.simplify(); + let mut simplified = expr.simplify(); + for simple in Bool::Not(Box::new(expr.clone())).simplify() { + let simple_negated = simple_negate(simple); + if simplified.iter().any(|s| *s == simple_negated) { + continue; + } + simplified.push(simple_negated); + } if !simplified.iter().any(|s| *s == expr) { span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { for suggestion in &simplified { -- cgit 1.4.1-3-g733a5 From 25ed62ff23eca4b6757bbd18f53061feebb09ae4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 14:45:51 +0100 Subject: improve lint attribute detail --- src/booleans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 178cef3aada..12cec565271 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -26,8 +26,8 @@ impl LintPass for NonminimalBool { } impl LateLintPass for NonminimalBool { - fn check_crate(&mut self, cx: &LateContext, krate: &Crate) { - krate.visit_all_items(&mut NonminimalBoolVisitor(cx)) + fn check_item(&mut self, cx: &LateContext, item: &Item) { + NonminimalBoolVisitor(cx).visit_item(item) } } -- cgit 1.4.1-3-g733a5 From 5911ccaba8ff0a308660c83e4d307609f8236146 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 14:50:08 +0100 Subject: merge multiple equal terminals into one --- src/booleans.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 12cec565271..4369a05d2d8 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -34,10 +34,13 @@ impl LateLintPass for NonminimalBool { struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); use quine_mc_cluskey::Bool; -struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>); +struct Hir2Qmm<'a, 'tcx: 'a, 'v> { + terminals: Vec<&'v Expr>, + cx: &'a LateContext<'a, 'tcx> +} -impl<'tcx> Hir2Qmm<'tcx> { - fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> { +impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { + fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> { for a in a { if let ExprBinary(binop, ref lhs, ref rhs) = a.node { if binop.node == op { @@ -50,7 +53,7 @@ impl<'tcx> Hir2Qmm<'tcx> { Ok(v) } - fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> { + fn run(&mut self, e: &'v Expr) -> Result<Bool, String> { match e.node { ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), ExprBinary(binop, ref lhs, ref rhs) => { @@ -69,8 +72,15 @@ impl<'tcx> Hir2Qmm<'tcx> { }, _ => {}, } - let n = self.0.len(); - self.0.push(e); + if let Some((n, _)) = self.terminals + .iter() + .enumerate() + .find(|&(_, expr)| SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr)) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Term(n as u8)); + } + let n = self.terminals.len(); + self.terminals.push(e); if n < 32 { #[allow(cast_possible_truncation)] Ok(Bool::Term(n as u8)) @@ -157,7 +167,10 @@ fn simple_negate(b: Bool) -> Bool { impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { fn bool_expr(&self, e: &Expr) { - let mut h2q = Hir2Qmm(Vec::new()); + let mut h2q = Hir2Qmm { + terminals: Vec::new(), + cx: self.0, + }; if let Ok(expr) = h2q.run(e) { let mut simplified = expr.simplify(); for simple in Bool::Not(Box::new(expr.clone())).simplify() { @@ -170,7 +183,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { if !simplified.iter().any(|s| *s == expr) { span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { for suggestion in &simplified { - db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0)); + db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); } }); } -- cgit 1.4.1-3-g733a5 From 050d7fd30805dcc995cd99575af2ff4db3ae0b90 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 23 Mar 2016 14:50:47 +0100 Subject: fallout and tests --- src/booleans.rs | 6 +++--- src/non_expressive_names.rs | 2 +- tests/compile-fail/block_in_if_condition.rs | 1 + tests/compile-fail/booleans.rs | 24 ++++++++++++++++++++++++ tests/compile-fail/eq_op.rs | 5 +++-- 5 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 tests/compile-fail/booleans.rs diff --git a/src/booleans.rs b/src/booleans.rs index 4369a05d2d8..e9197cf85c6 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -2,17 +2,17 @@ use rustc::lint::*; use rustc_front::hir::*; use rustc_front::intravisit::*; use syntax::ast::LitKind; -use utils::{span_lint_and_then, in_macro, snippet_opt}; +use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// **What it does:** This lint checks for boolean expressions that can be written more concisely /// /// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication /// -/// **Known problems:** None +/// **Known problems:** Ignores short circuting behavior, bitwise and/or and xor. Ends up suggesting things like !(a == b) /// /// **Example:** `if a && b || a` should be `if a` declare_lint! { - pub NONMINIMAL_BOOL, Warn, + pub NONMINIMAL_BOOL, Allow, "checks for boolean expressions that can be written more concisely" } diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index d7cb6fc5d28..87373c7a0de 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -262,7 +262,7 @@ fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { } if let Some(b2) = b_chars.next() { // check if there's just one character inserted - return !(a == b2 && a_chars.eq(b_chars)); + return a != b2 || a_chars.ne(b_chars); } else { // tuple // ntuple diff --git a/tests/compile-fail/block_in_if_condition.rs b/tests/compile-fail/block_in_if_condition.rs index 19fa949fb84..3d47fc74a11 100644 --- a/tests/compile-fail/block_in_if_condition.rs +++ b/tests/compile-fail/block_in_if_condition.rs @@ -4,6 +4,7 @@ #![deny(block_in_if_condition_expr)] #![deny(block_in_if_condition_stmt)] #![allow(unused, let_and_return)] +#![warn(nonminimal_bool)] macro_rules! blocky { diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs new file mode 100644 index 00000000000..ed989c0e84b --- /dev/null +++ b/tests/compile-fail/booleans.rs @@ -0,0 +1,24 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(nonminimal_bool)] + +#[allow(unused)] +fn main() { + let a: bool = unimplemented!(); + let b: bool = unimplemented!(); + let _ = a && b || a; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = a; + let _ = !(a && b); //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = !b || !a; + let _ = !true; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = false; + let _ = !false; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = true; + let _ = !!a; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = a; +} diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index bd76695e6ad..d49dcc6f84b 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -4,6 +4,7 @@ #[deny(eq_op)] #[allow(identity_op)] #[allow(no_effect)] +#[deny(nonminimal_bool)] fn main() { // simple values and comparisons 1 == 1; //~ERROR equal expressions @@ -38,9 +39,9 @@ fn main() { 1 - 1; //~ERROR equal expressions 1 / 1; //~ERROR equal expressions true && true; //~ERROR equal expressions - //~|WARN this boolean expression can be simplified + //~|ERROR this boolean expression can be simplified true || true; //~ERROR equal expressions - //~|WARN this boolean expression can be simplified + //~|ERROR this boolean expression can be simplified let mut a = vec![1]; a == a; //~ERROR equal expressions -- cgit 1.4.1-3-g733a5 From 0a78a795ab8618267a8b692095c4579d6931e598 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 09:36:46 +0100 Subject: bugfix in quine-mc_cluskey 0.2.1 --- Cargo.toml | 2 +- tests/compile-fail/booleans.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 93886e214e0..c07a0bf5e24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" -quine-mc_cluskey = "0.2" +quine-mc_cluskey = "0.2.1" [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index ed989c0e84b..8130e535773 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -21,4 +21,12 @@ fn main() { let _ = !!a; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = a; + + let _ = false && a; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = false; + + let _ = false || a; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = a; } -- cgit 1.4.1-3-g733a5 From 288ea799637dee4b2250069af41b44a8facaa52f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 09:37:16 +0100 Subject: treat macros as terminals to prevent `cfg!` from giving platform specific hints --- src/booleans.rs | 37 ++++++++++++++++++++----------------- tests/compile-fail/booleans.rs | 3 +++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index e9197cf85c6..1b4d661da84 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -54,23 +54,26 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } fn run(&mut self, e: &'v Expr) -> Result<Bool, String> { - match e.node { - ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprBinary(binop, ref lhs, ref rhs) => { - match binop.node { - BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), - BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), - _ => {}, - } - }, - ExprLit(ref lit) => { - match lit.node { - LitKind::Bool(true) => return Ok(Bool::True), - LitKind::Bool(false) => return Ok(Bool::False), - _ => {}, - } - }, - _ => {}, + // prevent folding of `cfg!` macros and the like + if !in_macro(self.cx, e.span) { + match e.node { + ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), + ExprBinary(binop, ref lhs, ref rhs) => { + match binop.node { + BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), + BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + _ => {}, + } + }, + ExprLit(ref lit) => { + match lit.node { + LitKind::Bool(true) => return Ok(Bool::True), + LitKind::Bool(false) => return Ok(Bool::False), + _ => {}, + } + }, + _ => {}, + } } if let Some((n, _)) = self.terminals .iter() diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 8130e535773..f9bf1a15f18 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -29,4 +29,7 @@ fn main() { let _ = false || a; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = a; + + // don't lint on cfgs + let _ = cfg!(you_shall_not_not_pass) && a; } -- cgit 1.4.1-3-g733a5 From 03833f666fccad492746304d818a4afbe679ccf3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 10:45:24 +0100 Subject: differentiate between logic bugs and optimizable expressions --- src/booleans.rs | 71 ++++++++++++++++++++++++++++++++++++++---- tests/compile-fail/booleans.rs | 10 ++++-- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 1b4d661da84..49371de5c9d 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -10,18 +10,30 @@ use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// /// **Known problems:** Ignores short circuting behavior, bitwise and/or and xor. Ends up suggesting things like !(a == b) /// -/// **Example:** `if a && b || a` should be `if a` +/// **Example:** `if a && true` should be `if a` declare_lint! { pub NONMINIMAL_BOOL, Allow, "checks for boolean expressions that can be written more concisely" } +/// **What it does:** This lint checks for boolean expressions that contain terminals that can be eliminated +/// +/// **Why is this bad?** This is most likely a logic bug +/// +/// **Known problems:** Ignores short circuiting behavior +/// +/// **Example:** The `b` in `if a && b || a` is unnecessary because the expression is equivalent to `if a` +declare_lint! { + pub LOGIC_BUG, Warn, + "checks for boolean expressions that contain terminals which can be eliminated" +} + #[derive(Copy,Clone)] pub struct NonminimalBool; impl LintPass for NonminimalBool { fn get_lints(&self) -> LintArray { - lint_array!(NONMINIMAL_BOOL) + lint_array!(NONMINIMAL_BOOL, LOGIC_BUG) } } @@ -168,6 +180,23 @@ fn simple_negate(b: Bool) -> Bool { } } +fn terminal_stats(b: &Bool) -> [usize; 32] { + fn recurse(b: &Bool, stats: &mut [usize; 32]) { + match *b { + True | False => {}, + Not(ref inner) => recurse(inner, stats), + And(ref v) | Or(ref v) => for inner in v { + recurse(inner, stats) + }, + Term(n) => stats[n as usize] += 1, + } + } + use quine_mc_cluskey::Bool::*; + let mut stats = [0; 32]; + recurse(b, &mut stats); + stats +} + impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { fn bool_expr(&self, e: &Expr) { let mut h2q = Hir2Qmm { @@ -175,6 +204,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { cx: self.0, }; if let Ok(expr) = h2q.run(e) { + let stats = terminal_stats(&expr); let mut simplified = expr.simplify(); for simple in Bool::Not(Box::new(expr.clone())).simplify() { let simple_negated = simple_negate(simple); @@ -184,11 +214,40 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { simplified.push(simple_negated); } if !simplified.iter().any(|s| *s == expr) { - span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { - for suggestion in &simplified { - db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); + let mut improvements = Vec::new(); + 'simplified: for suggestion in &simplified { + let simplified_stats = terminal_stats(&suggestion); + let mut improvement = false; + for i in 0..32 { + // ignore any "simplifications" that end up requiring a terminal more often than in the original expression + if stats[i] < simplified_stats[i] { + continue 'simplified; + } + // if the number of occurrences of a terminal decreases, this expression is a candidate for improvement + if stats[i] >= simplified_stats[i] { + improvement = true; + } + if stats[i] != 0 && simplified_stats[i] == 0 { + span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { + db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); + db.span_suggestion(e.span, "it would look like the following", suggest(self.0, suggestion, &h2q.terminals)); + }); + // don't also lint `NONMINIMAL_BOOL` + improvements.clear(); + break 'simplified; + } } - }); + if improvement { + improvements.push(suggestion); + } + } + if !improvements.is_empty() { + span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { + for suggestion in &improvements { + db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); + } + }); + } } } } diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index f9bf1a15f18..31c160980fc 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -1,13 +1,15 @@ #![feature(plugin)] #![plugin(clippy)] -#![deny(nonminimal_bool)] +#![deny(nonminimal_bool, logic_bug)] #[allow(unused)] fn main() { let a: bool = unimplemented!(); let b: bool = unimplemented!(); - let _ = a && b || a; //~ ERROR this boolean expression can be simplified + let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following //|~ SUGGESTION let _ = a; let _ = !(a && b); //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit @@ -22,8 +24,10 @@ fn main() { //|~ HELP for further information visit //|~ SUGGESTION let _ = a; - let _ = false && a; //~ ERROR this boolean expression can be simplified + let _ = false && a; //~ ERROR this boolean expression contains a logic bug //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following //|~ SUGGESTION let _ = false; let _ = false || a; //~ ERROR this boolean expression can be simplified -- cgit 1.4.1-3-g733a5 From 37cee84c44ff2e020504f6ee6e762452b525b8c7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 10:54:48 +0100 Subject: negations around expressions can make things simpler --- src/booleans.rs | 4 ++++ tests/compile-fail/booleans.rs | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 49371de5c9d..e290b896b1d 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -207,6 +207,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { let stats = terminal_stats(&expr); let mut simplified = expr.simplify(); for simple in Bool::Not(Box::new(expr.clone())).simplify() { + match simple { + Bool::Not(_) | Bool::True | Bool::False => {}, + _ => simplified.push(Bool::Not(Box::new(simple.clone()))), + } let simple_negated = simple_negate(simple); if simplified.iter().any(|s| *s == simple_negated) { continue; diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 31c160980fc..4630a4635b4 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -6,14 +6,13 @@ fn main() { let a: bool = unimplemented!(); let b: bool = unimplemented!(); + let c: bool = unimplemented!(); let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug //|~ HELP for further information visit //|~ HELP this expression can be optimized out //|~ HELP it would look like the following //|~ SUGGESTION let _ = a; - let _ = !(a && b); //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = !b || !a; + let _ = !(a && b); let _ = !true; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = false; @@ -36,4 +35,6 @@ fn main() { // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; + + let _ = !(a && b || c); } -- cgit 1.4.1-3-g733a5 From 76ab80100177403a1a860ce4f01c5e791377afb0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 10:58:57 +0100 Subject: if a < b { ... } if a >= b { ... } what am I doing? --- src/booleans.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index e290b896b1d..f4437249b4c 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -227,10 +227,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { if stats[i] < simplified_stats[i] { continue 'simplified; } - // if the number of occurrences of a terminal decreases, this expression is a candidate for improvement - if stats[i] >= simplified_stats[i] { - improvement = true; - } + // if the number of occurrences of a terminal doesn't increase, this expression is a candidate for improvement + improvement = true; if stats[i] != 0 && simplified_stats[i] == 0 { span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); -- cgit 1.4.1-3-g733a5 From e7013a3e9c7e8b3cfe2825fe0d3c803b67001b20 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 11:02:28 +0100 Subject: update lints --- README.md | 3 ++- src/booleans.rs | 2 +- src/lib.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cd8b0257c6e..188e272dc4d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 138 lints included in this crate: +There are 139 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -75,6 +75,7 @@ name [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block [let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards [linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[logic_bug](https://github.com/Manishearth/rust-clippy/wiki#logic_bug) | warn | checks for boolean expressions that contain terminals which can be eliminated [manual_swap](https://github.com/Manishearth/rust-clippy/wiki#manual_swap) | warn | manual swap [many_single_char_names](https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names) | warn | too many single character bindings [map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends `.cloned()` instead) diff --git a/src/booleans.rs b/src/booleans.rs index f4437249b4c..c156a893c62 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -12,7 +12,7 @@ use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// /// **Example:** `if a && true` should be `if a` declare_lint! { - pub NONMINIMAL_BOOL, Allow, + pub NONMINIMAL_BOOL, Warn, "checks for boolean expressions that can be written more concisely" } diff --git a/src/lib.rs b/src/lib.rs index 575e318e7ad..617d2e24266 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -267,6 +267,7 @@ pub fn plugin_registrar(reg: &mut Registry) { blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, + booleans::LOGIC_BUG, booleans::NONMINIMAL_BOOL, collapsible_if::COLLAPSIBLE_IF, copies::IF_SAME_THEN_ELSE, -- cgit 1.4.1-3-g733a5 From 0f92f84f16778d6921f22079ffd5141cec2dbc6b Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 15:36:50 +0100 Subject: String::extend -> String::push_str --- src/booleans.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index c156a893c62..ea05d65ac9c 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; use rustc_front::hir::*; use rustc_front::intravisit::*; use syntax::ast::LitKind; @@ -110,11 +110,11 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { use quine_mc_cluskey::Bool::*; match *suggestion { True => { - s.extend("true".chars()); + s.push_str("true"); s }, False => { - s.extend("false".chars()); + s.push_str("false"); s }, Not(ref inner) => { @@ -127,7 +127,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { } s = recurse(true, cx, &v[0], terminals, s); for inner in &v[1..] { - s.extend(" && ".chars()); + s.push_str(" && "); s = recurse(true, cx, inner, terminals, s); } if brackets { @@ -141,7 +141,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { } s = recurse(true, cx, &v[0], terminals, s); for inner in &v[1..] { - s.extend(" || ".chars()); + s.push_str(" || "); s = recurse(true, cx, inner, terminals, s); } if brackets { @@ -150,7 +150,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s }, Term(n) => { - s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars()); + s.push_str(&snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros")); s } } -- cgit 1.4.1-3-g733a5 From dd6bee3b3f653d01415b9be3245654b036390718 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 15:37:17 +0100 Subject: collect stats on bool ops and negations in an expression --- src/booleans.rs | 89 ++++++++++++++++++++++++------------------ tests/compile-fail/booleans.rs | 10 ++++- 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index ea05d65ac9c..9da594424ff 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -180,19 +180,35 @@ fn simple_negate(b: Bool) -> Bool { } } -fn terminal_stats(b: &Bool) -> [usize; 32] { - fn recurse(b: &Bool, stats: &mut [usize; 32]) { +#[derive(Default)] +struct Stats { + terminals: [usize; 32], + negations: usize, + ops: usize, +} + +fn terminal_stats(b: &Bool) -> Stats { + fn recurse(b: &Bool, stats: &mut Stats) { match *b { - True | False => {}, - Not(ref inner) => recurse(inner, stats), - And(ref v) | Or(ref v) => for inner in v { - recurse(inner, stats) + True | False => stats.ops += 1, + Not(ref inner) => { + match **inner { + And(_) | Or(_) => stats.ops += 1, // brackets are also operations + _ => stats.negations += 1, + } + recurse(inner, stats); }, - Term(n) => stats[n as usize] += 1, + And(ref v) | Or(ref v) => { + stats.ops += v.len() - 1; + for inner in v { + recurse(inner, stats); + } + }, + Term(n) => stats.terminals[n as usize] += 1, } } use quine_mc_cluskey::Bool::*; - let mut stats = [0; 32]; + let mut stats = Stats::default(); recurse(b, &mut stats); stats } @@ -217,40 +233,39 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } simplified.push(simple_negated); } - if !simplified.iter().any(|s| *s == expr) { - let mut improvements = Vec::new(); - 'simplified: for suggestion in &simplified { - let simplified_stats = terminal_stats(&suggestion); - let mut improvement = false; - for i in 0..32 { - // ignore any "simplifications" that end up requiring a terminal more often than in the original expression - if stats[i] < simplified_stats[i] { - continue 'simplified; - } - // if the number of occurrences of a terminal doesn't increase, this expression is a candidate for improvement - improvement = true; - if stats[i] != 0 && simplified_stats[i] == 0 { - span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { - db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); - db.span_suggestion(e.span, "it would look like the following", suggest(self.0, suggestion, &h2q.terminals)); - }); - // don't also lint `NONMINIMAL_BOOL` - improvements.clear(); - break 'simplified; - } + let mut improvements = Vec::new(); + 'simplified: for suggestion in &simplified { + let simplified_stats = terminal_stats(&suggestion); + let mut improvement = false; + for i in 0..32 { + // ignore any "simplifications" that end up requiring a terminal more often than in the original expression + if stats.terminals[i] < simplified_stats.terminals[i] { + continue 'simplified; } - if improvement { - improvements.push(suggestion); + if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { + span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { + db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); + db.span_suggestion(e.span, "it would look like the following", suggest(self.0, suggestion, &h2q.terminals)); + }); + // don't also lint `NONMINIMAL_BOOL` + return; } + // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases + improvement = (stats.terminals[i] > simplified_stats.terminals[i]) || + (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || + (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); } - if !improvements.is_empty() { - span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { - for suggestion in &improvements { - db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); - } - }); + if improvement { + improvements.push(suggestion); } } + if !improvements.is_empty() { + span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { + for suggestion in &improvements { + db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); + } + }); + } } } } diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 4630a4635b4..5d39c44e7bf 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -2,11 +2,13 @@ #![plugin(clippy)] #![deny(nonminimal_bool, logic_bug)] -#[allow(unused)] +#[allow(unused, many_single_char_names)] fn main() { let a: bool = unimplemented!(); let b: bool = unimplemented!(); let c: bool = unimplemented!(); + let d: bool = unimplemented!(); + let e: bool = unimplemented!(); let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug //|~ HELP for further information visit //|~ HELP this expression can be optimized out @@ -36,5 +38,11 @@ fn main() { // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; + let _ = a || !b || !c || !d || !e; + let _ = !(a && b || c); + + let _ = !(!a && b); //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = !b || a; } -- cgit 1.4.1-3-g733a5 From 6904fd5a490572af615055d135686206018fe14b Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 15:44:08 +0100 Subject: add tests showing the current level of minimization with == --- tests/compile-fail/booleans.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 5d39c44e7bf..61a8edaabbd 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -46,3 +46,19 @@ fn main() { //|~ HELP for further information visit //|~ SUGGESTION let _ = !b || a; } + +#[allow(unused, many_single_char_names)] +fn equality_stuff() { + let a: i32 = unimplemented!(); + let b: i32 = unimplemented!(); + let c: i32 = unimplemented!(); + let d: i32 = unimplemented!(); + let e: i32 = unimplemented!(); + let _ = a == b && a != b; + let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = c == 5 && a == b; + let _ = a < b && a >= b; + let _ = a > b && a <= b; + let _ = a > b && a == b; +} -- cgit 1.4.1-3-g733a5 From 25bbde091a9cf1f903b9dc418de2920c1a099c1f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 16:02:26 +0100 Subject: a small refactoring for readability --- src/booleans.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 9da594424ff..2de59c9bc59 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -87,12 +87,11 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { _ => {}, } } - if let Some((n, _)) = self.terminals - .iter() - .enumerate() - .find(|&(_, expr)| SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr)) { - #[allow(cast_possible_truncation)] - return Ok(Bool::Term(n as u8)); + for (n, expr) in self.terminals.iter().enumerate() { + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Term(n as u8)); + } } let n = self.terminals.len(); self.terminals.push(e); -- cgit 1.4.1-3-g733a5 From 3a0791e68080297fe7b8d622f037037108e67148 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 16:11:38 +0100 Subject: make sure `a < b` and `a >= b` are considered equal by SpanlessEq --- src/utils/hir.rs | 20 +++++++++++++++++++- tests/compile-fail/booleans.rs | 3 +++ tests/compile-fail/eq_op.rs | 14 +++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 20c7e33fbb2..0659e26d0f2 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -75,7 +75,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) } (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), @@ -197,6 +198,23 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } +fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> { + match binop { + BiAdd | + BiMul | + BiBitXor | + BiBitAnd | + BiEq | + BiNe | + BiBitOr => Some((binop, rhs, lhs)), + BiLt => Some((BiGt, rhs, lhs)), + BiLe => Some((BiGe, rhs, lhs)), + BiGe => Some((BiLe, rhs, lhs)), + BiGt => Some((BiLt, rhs, lhs)), + BiShl | BiShr | BiRem | BiSub | BiDiv | BiAnd | BiOr => None, + } +} + /// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 61a8edaabbd..43528f5c5df 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -58,6 +58,9 @@ fn equality_stuff() { let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = c == 5 && a == b; + let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = c == 5 && a == b; let _ = a < b && a >= b; let _ = a > b && a <= b; let _ = a > b && a == b; diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index d49dcc6f84b..443bbbaacd3 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -3,7 +3,7 @@ #[deny(eq_op)] #[allow(identity_op)] -#[allow(no_effect)] +#[allow(no_effect, unused_variables)] #[deny(nonminimal_bool)] fn main() { // simple values and comparisons @@ -43,6 +43,18 @@ fn main() { true || true; //~ERROR equal expressions //~|ERROR this boolean expression can be simplified + let a: u32 = unimplemented!(); + let b: u32 = unimplemented!(); + + a == b && b == a; //~ERROR equal expressions + //~|ERROR this boolean expression can be simplified + a != b && b != a; //~ERROR equal expressions + //~|ERROR this boolean expression can be simplified + a < b && b > a; //~ERROR equal expressions + //~|ERROR this boolean expression can be simplified + a <= b && b >= a; //~ERROR equal expressions + //~|ERROR this boolean expression can be simplified + let mut a = vec![1]; a == a; //~ERROR equal expressions 2*a.len() == 2*a.len(); // ok, functions -- cgit 1.4.1-3-g733a5 From 96be287f12ff4199b3b1005a22a2dd7c1f01f5bf Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 24 Mar 2016 16:29:20 +0100 Subject: detect negations of terminals like a != b vs a == b --- src/booleans.rs | 27 ++++++++++++++++++++++++++- tests/compile-fail/booleans.rs | 18 +++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 2de59c9bc59..b43f2297311 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -1,7 +1,8 @@ use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; use rustc_front::hir::*; use rustc_front::intravisit::*; -use syntax::ast::LitKind; +use syntax::ast::{LitKind, DUMMY_NODE_ID}; +use syntax::codemap::{DUMMY_SP, dummy_spanned}; use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// **What it does:** This lint checks for boolean expressions that can be written more concisely @@ -92,6 +93,30 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { #[allow(cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } + let negated = match e.node { + ExprBinary(binop, ref lhs, ref rhs) => { + let mk_expr = |op| Expr { + id: DUMMY_NODE_ID, + span: DUMMY_SP, + attrs: None, + node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + }; + match binop.node { + BiEq => mk_expr(BiNe), + BiNe => mk_expr(BiEq), + BiGt => mk_expr(BiLe), + BiGe => mk_expr(BiLt), + BiLt => mk_expr(BiGe), + BiLe => mk_expr(BiGt), + _ => continue, + } + }, + _ => continue, + }; + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + } } let n = self.terminals.len(); self.terminals.push(e); diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 43528f5c5df..4ad51226d51 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -54,14 +54,26 @@ fn equality_stuff() { let c: i32 = unimplemented!(); let d: i32 = unimplemented!(); let e: i32 = unimplemented!(); - let _ = a == b && a != b; + let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = c == 5 && a == b; let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = c == 5 && a == b; - let _ = a < b && a >= b; - let _ = a > b && a <= b; + let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; + let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; let _ = a > b && a == b; } -- cgit 1.4.1-3-g733a5 From be7288303ae2ebb74b176f75ff567af4cace5d3b Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 29 Mar 2016 10:44:35 +0200 Subject: more tests --- tests/compile-fail/booleans.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 4ad51226d51..ecaa52019c6 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -76,4 +76,6 @@ fn equality_stuff() { //|~ HELP it would look like the following //|~ SUGGESTION let _ = false; let _ = a > b && a == b; + + let _ = a != b || !(a != b || c == d); } -- cgit 1.4.1-3-g733a5 From cf95374486bccf7f665aa695ad669256f3bbc8e2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 29 Mar 2016 18:45:58 +0530 Subject: Add token --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 322e03258d4..3f727555bd7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,11 @@ language: rust rust: nightly sudo: false +env: + global: + # TRAVIS_TOKEN_CLIPPY_SERVICE + secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI= + script: - python util/update_lints.py -c - cargo build --features debugging @@ -11,7 +16,7 @@ script: # only test regex_macros if it compiles - if [[ "$(cargo build --features 'debugging test-regex_macros')" = 101 ]]; then cargo test --features 'debugging test-regex_macros'; fi -# trigger rebuild of the clippy-service +# trigger rebuild of the clippy-service, to keep it up to date with clippy itself after_success: - | #!/bin/bash -- cgit 1.4.1-3-g733a5 From 216edbae59463538045f953c21d877b5f906caf2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 29 Mar 2016 16:27:06 +0200 Subject: accidentally forgot about improvements if there were multiplie candidates --- Cargo.toml | 2 +- src/booleans.rs | 2 +- tests/compile-fail/booleans.rs | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c07a0bf5e24..058dc012cfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ regex_macros = { version = "0.1.33", optional = true } semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" -quine-mc_cluskey = "0.2.1" +quine-mc_cluskey = "0.2.2" [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/src/booleans.rs b/src/booleans.rs index b43f2297311..b603d5188aa 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { return; } // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases - improvement = (stats.terminals[i] > simplified_stats.terminals[i]) || + improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); } diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index ecaa52019c6..008e6dcdda9 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -77,5 +77,8 @@ fn equality_stuff() { //|~ SUGGESTION let _ = false; let _ = a > b && a == b; - let _ = a != b || !(a != b || c == d); + let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified + //|~ HELP for further information visit + //|~ SUGGESTION let _ = !c == d || a != b; + //|~ SUGGESTION let _ = !(!a != b && c == d); } -- cgit 1.4.1-3-g733a5 From b05dd13f2c5199bc2e97a5b5e6910b1cde4be988 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 29 Mar 2016 16:55:38 +0200 Subject: added brackets and fixed compiler comments --- src/booleans.rs | 29 +++++++++++++--- tests/compile-fail/booleans.rs | 77 ++++++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index b603d5188aa..0cfab9a5357 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -129,6 +129,15 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } +macro_rules! brackets { + ($val:expr => $($name:ident),*) => { + match $val { + $($name(_) => true,)* + _ => false, + } + } +} + fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { use quine_mc_cluskey::Bool::*; @@ -143,16 +152,16 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { }, Not(ref inner) => { s.push('!'); - recurse(true, cx, inner, terminals, s) + recurse(brackets!(**inner => And, Or, Term), cx, inner, terminals, s) }, And(ref v) => { if brackets { s.push('('); } - s = recurse(true, cx, &v[0], terminals, s); + s = recurse(brackets!(v[0] => Or), cx, &v[0], terminals, s); for inner in &v[1..] { s.push_str(" && "); - s = recurse(true, cx, inner, terminals, s); + s = recurse(brackets!(*inner => Or), cx, inner, terminals, s); } if brackets { s.push(')'); @@ -163,10 +172,10 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { if brackets { s.push('('); } - s = recurse(true, cx, &v[0], terminals, s); + s = recurse(false, cx, &v[0], terminals, s); for inner in &v[1..] { s.push_str(" || "); - s = recurse(true, cx, inner, terminals, s); + s = recurse(false, cx, inner, terminals, s); } if brackets { s.push(')'); @@ -174,7 +183,17 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s }, Term(n) => { + if brackets { + if let ExprBinary(..) = terminals[n as usize].node { + s.push('('); + } + } s.push_str(&snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros")); + if brackets { + if let ExprBinary(..) = terminals[n as usize].node { + s.push(')'); + } + } s } } diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 008e6dcdda9..f4760a6fd46 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -10,30 +10,30 @@ fn main() { let d: bool = unimplemented!(); let e: bool = unimplemented!(); let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug - //|~ HELP for further information visit - //|~ HELP this expression can be optimized out - //|~ HELP it would look like the following - //|~ SUGGESTION let _ = a; + //~| HELP for further information visit + //~| HELP this expression can be optimized out + //~| HELP it would look like the following + //~| SUGGESTION let _ = a; let _ = !(a && b); let _ = !true; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = false; + //~| HELP for further information visit + //~| SUGGESTION let _ = false; let _ = !false; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = true; + //~| HELP for further information visit + //~| SUGGESTION let _ = true; let _ = !!a; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = a; + //~| HELP for further information visit + //~| SUGGESTION let _ = a; let _ = false && a; //~ ERROR this boolean expression contains a logic bug - //|~ HELP for further information visit - //|~ HELP this expression can be optimized out - //|~ HELP it would look like the following - //|~ SUGGESTION let _ = false; + //~| HELP for further information visit + //~| HELP this expression can be optimized out + //~| HELP it would look like the following + //~| SUGGESTION let _ = false; let _ = false || a; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = a; + //~| HELP for further information visit + //~| SUGGESTION let _ = a; // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; @@ -43,8 +43,8 @@ fn main() { let _ = !(a && b || c); let _ = !(!a && b); //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = !b || a; + //~| HELP for further information visit + //~| SUGGESTION let _ = !b || a; } #[allow(unused, many_single_char_names)] @@ -55,30 +55,33 @@ fn equality_stuff() { let d: i32 = unimplemented!(); let e: i32 = unimplemented!(); let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug - //|~ HELP for further information visit - //|~ HELP this expression can be optimized out - //|~ HELP it would look like the following - //|~ SUGGESTION let _ = false; + //~| HELP for further information visit + //~| HELP this expression can be optimized out + //~| HELP it would look like the following + //~| SUGGESTION let _ = false; let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = c == 5 && a == b; + //~| HELP for further information visit + //~| SUGGESTION let _ = a == b && c == 5; let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = c == 5 && a == b; + //~| HELP for further information visit + //~| SUGGESTION let _ = a == b && c == 5; + //~| HELP try + //~| SUGGESTION let _ = !(!(c == 5) || !(a == b)); let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug - //|~ HELP for further information visit - //|~ HELP this expression can be optimized out - //|~ HELP it would look like the following - //|~ SUGGESTION let _ = false; + //~| HELP for further information visit + //~| HELP this expression can be optimized out + //~| HELP it would look like the following + //~| SUGGESTION let _ = false; let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug - //|~ HELP for further information visit - //|~ HELP this expression can be optimized out - //|~ HELP it would look like the following - //|~ SUGGESTION let _ = false; + //~| HELP for further information visit + //~| HELP this expression can be optimized out + //~| HELP it would look like the following + //~| SUGGESTION let _ = false; let _ = a > b && a == b; let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified - //|~ HELP for further information visit - //|~ SUGGESTION let _ = !c == d || a != b; - //|~ SUGGESTION let _ = !(!a != b && c == d); + //~| HELP for further information visit + //~| SUGGESTION let _ = !(c == d) || a != b; + //~| HELP try + //~| SUGGESTION let _ = !(!(a != b) && c == d); } -- cgit 1.4.1-3-g733a5 From e9c87c777c88d36b7ce8aee1ef13d5744f90da3d Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 29 Mar 2016 17:18:47 +0200 Subject: `!(a == b)` --> `a != b` --- src/booleans.rs | 62 ++++++++++++++++++++++++++++++++---------- tests/compile-fail/booleans.rs | 6 ++-- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 0cfab9a5357..74a10faa070 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -129,18 +129,10 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } -macro_rules! brackets { - ($val:expr => $($name:ident),*) => { - match $val { - $($name(_) => true,)* - _ => false, - } - } -} - fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { use quine_mc_cluskey::Bool::*; + let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); match *suggestion { True => { s.push_str("true"); @@ -151,17 +143,59 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s }, Not(ref inner) => { - s.push('!'); - recurse(brackets!(**inner => And, Or, Term), cx, inner, terminals, s) + match **inner { + And(_) | Or(_) => { + s.push('!'); + recurse(true, cx, inner, terminals, s) + }, + Term(n) => { + match terminals[n as usize].node { + ExprBinary(binop, ref lhs, ref rhs) => { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { + s.push('!'); + return recurse(true, cx, inner, terminals, s) + }, + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + }, + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, + } + }, + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, + } }, And(ref v) => { if brackets { s.push('('); } - s = recurse(brackets!(v[0] => Or), cx, &v[0], terminals, s); + if let Or(_) = v[0] { + s = recurse(true, cx, &v[0], terminals, s); + } else { + s = recurse(false, cx, &v[0], terminals, s); + } for inner in &v[1..] { s.push_str(" && "); - s = recurse(brackets!(*inner => Or), cx, inner, terminals, s); + if let Or(_) = *inner { + s = recurse(true, cx, inner, terminals, s); + } else { + s = recurse(false, cx, inner, terminals, s); + } } if brackets { s.push(')'); @@ -188,7 +222,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push('('); } } - s.push_str(&snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros")); + s.push_str(&snip(&terminals[n as usize])); if brackets { if let ExprBinary(..) = terminals[n as usize].node { s.push(')'); diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index f4760a6fd46..aba55f0b8b4 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -66,7 +66,7 @@ fn equality_stuff() { //~| HELP for further information visit //~| SUGGESTION let _ = a == b && c == 5; //~| HELP try - //~| SUGGESTION let _ = !(!(c == 5) || !(a == b)); + //~| SUGGESTION let _ = !(c != 5 || a != b); let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug //~| HELP for further information visit //~| HELP this expression can be optimized out @@ -81,7 +81,7 @@ fn equality_stuff() { let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified //~| HELP for further information visit - //~| SUGGESTION let _ = !(c == d) || a != b; + //~| SUGGESTION let _ = c != d || a != b; //~| HELP try - //~| SUGGESTION let _ = !(!(a != b) && c == d); + //~| SUGGESTION let _ = !(a == b && c == d); } -- cgit 1.4.1-3-g733a5 From fa48ee678a8b647f339547d1111dd9064ea9bfbe Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 29 Mar 2016 17:20:30 +0200 Subject: dogfood --- src/booleans.rs | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 74a10faa070..35ea5fe4462 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -149,29 +149,26 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { recurse(true, cx, inner, terminals, s) }, Term(n) => { - match terminals[n as usize].node { - ExprBinary(binop, ref lhs, ref rhs) => { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { - s.push('!'); - return recurse(true, cx, inner, terminals, s) - }, - }; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - }, - _ => { - s.push('!'); - recurse(false, cx, inner, terminals, s) - }, + if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { + s.push('!'); + return recurse(true, cx, inner, terminals, s) + }, + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + } else { + s.push('!'); + recurse(false, cx, inner, terminals, s) } }, _ => { -- cgit 1.4.1-3-g733a5 From 2917484130db16c4533f0e241dd89352ec3b2ba6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 30 Mar 2016 12:55:59 +0200 Subject: make `nonminimal_bool` allow-by-default --- README.md | 2 +- src/booleans.rs | 6 +++--- src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 188e272dc4d..e59012c8165 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ name [new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead -[nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | warn | checks for boolean expressions that can be written more concisely +[nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | allow | checks for boolean expressions that can be written more concisely [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file [ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result [option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` diff --git a/src/booleans.rs b/src/booleans.rs index 35ea5fe4462..877a45a355a 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -9,11 +9,11 @@ use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// /// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication /// -/// **Known problems:** Ignores short circuting behavior, bitwise and/or and xor. Ends up suggesting things like !(a == b) +/// **Known problems:** Ignores short circuting behavior of `||` and `&&`. Ignores `|`, `&` and `^`. /// -/// **Example:** `if a && true` should be `if a` +/// **Example:** `if a && true` should be `if a` and `!(a == b)` should be `a != b` declare_lint! { - pub NONMINIMAL_BOOL, Warn, + pub NONMINIMAL_BOOL, Allow, "checks for boolean expressions that can be written more concisely" } diff --git a/src/lib.rs b/src/lib.rs index 617d2e24266..2d12532fcfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -235,6 +235,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, + booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, matches::SINGLE_MATCH_ELSE, methods::OPTION_UNWRAP_USED, @@ -268,7 +269,6 @@ pub fn plugin_registrar(reg: &mut Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, booleans::LOGIC_BUG, - booleans::NONMINIMAL_BOOL, collapsible_if::COLLAPSIBLE_IF, copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, -- cgit 1.4.1-3-g733a5 From 77652243aef0a5848ef2858b26443b9d3943ec83 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 30 Mar 2016 16:39:25 +0200 Subject: minor code readability improvements --- src/non_expressive_names.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 87373c7a0de..4e10d415b66 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -123,17 +123,11 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { for &(ref existing_name, sp, existing_len) in &self.0.names { let mut split_at = None; if existing_len > count { - if existing_len - count != 1 { - continue; - } - if levenstein_not_1(&interned_name, &existing_name) { + if existing_len - count != 1 || levenstein_not_1(&interned_name, &existing_name) { continue; } } else if existing_len < count { - if count - existing_len != 1 { - continue; - } - if levenstein_not_1(&existing_name, &interned_name) { + if count - existing_len != 1 || levenstein_not_1(&existing_name, &interned_name) { continue; } } else { -- cgit 1.4.1-3-g733a5 From d3362a2222481ce93c921bcc2781ffd401551628 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 30 Mar 2016 16:40:21 +0200 Subject: don't lint on binding names where only a numeric char changes to another numeric --- src/non_expressive_names.rs | 54 ++++++++++++------------------ tests/compile-fail/non_expressive_names.rs | 9 +++++ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 4e10d415b66..394812dc4cb 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -133,46 +133,36 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } else { let mut interned_chars = interned_name.chars(); let mut existing_chars = existing_name.chars(); + let first_i = interned_chars.next().expect("we know we have at least one char"); + let first_e = existing_chars.next().expect("we know we have at least one char"); + let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); - if interned_chars.next() != existing_chars.next() { - let i = interned_chars.next().expect("we know we have more than 1 char"); - let e = existing_chars.next().expect("we know we have more than 1 char"); - if i == e { - if i == '_' { - // allowed similarity x_foo, y_foo - // or too many chars differ (x_foo, y_boo) + if eq_or_numeric(first_i, first_e) { + let last_i = interned_chars.next_back().expect("we know we have at least two chars"); + let last_e = existing_chars.next_back().expect("we know we have at least two chars"); + if eq_or_numeric(last_i, last_e) { + if interned_chars.zip(existing_chars).filter(|&(i, e)| !eq_or_numeric(i, e)).count() != 1 { continue; - } else if interned_chars.ne(existing_chars) { - // too many chars differ - continue } } else { - // too many chars differ - continue; - } - split_at = interned_name.chars().next().map(|c| c.len_utf8()); - } else if interned_chars.next_back() == existing_chars.next_back() { - if interned_chars.zip(existing_chars).filter(|&(i, e)| i != e).count() != 1 { - // too many chars differ, or none differ (aka shadowing) - continue; - } - } else { - let i = interned_chars.next_back().expect("we know we have more than 2 chars"); - let e = existing_chars.next_back().expect("we know we have more than 2 chars"); - if i == e { - if i == '_' { - // allowed similarity foo_x, foo_x - // or too many chars differ (foo_x, boo_x) + let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); + let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); + if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + // allowed similarity foo_x, foo_y + // or too many chars differ (foo_x, boo_y) or (foox, booy) continue; - } else if interned_chars.ne(existing_chars) { - // too many chars differ - continue } - } else { - // too many chars differ + split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); + } + } else { + let second_i = interned_chars.next().expect("we know we have at least two chars"); + let second_e = existing_chars.next().expect("we know we have at least two chars"); + if !eq_or_numeric(second_i, second_e) || second_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + // allowed similarity x_foo, y_foo + // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) continue; } - split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); + split_at = interned_name.chars().next().map(|c| c.len_utf8()); } } span_lint_and_then(self.0.cx, diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index ac412fb4475..7d0cea70366 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -10,6 +10,7 @@ //~| NOTE: lint level defined here //~| NOTE: lint level defined here //~| NOTE: lint level defined here +//~| NOTE: lint level defined here #![allow(unused)] fn main() { @@ -67,6 +68,14 @@ fn main() { (cheese2, 2) => panic!(), _ => println!(""), } + let ipv4: i32; + let ipv6: i32; + let abcd1: i32; + let abdc2: i32; + let xyz1abc: i32; //~ NOTE: existing binding defined here + let xyz2abc: i32; + let xyzeabc: i32; //~ ERROR: name is too similar + //~| HELP: for further information visit } #[derive(Clone, Debug)] -- cgit 1.4.1-3-g733a5 From f03d93e05e5e2149a2ae0fd05666da7d18edc993 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 30 Mar 2016 17:05:15 +0200 Subject: better whitelisting of "confusable" binding names --- src/non_expressive_names.rs | 76 +++++++++++++++++++----------- tests/compile-fail/non_expressive_names.rs | 7 +++ 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 394812dc4cb..32118b11c4e 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -41,15 +41,25 @@ impl LintPass for NonExpressiveNames { } } +struct ExistingName { + interned: InternedString, + span: Span, + len: usize, + whitelist: &'static[&'static str], +} + struct SimilarNamesLocalVisitor<'a, 'b: 'a> { - names: Vec<(InternedString, Span, usize)>, + names: Vec<ExistingName>, cx: &'a EarlyContext<'b>, lint: &'a NonExpressiveNames, single_char_names: Vec<char>, } -const WHITELIST: &'static [&'static str] = &[ - "lhs", "rhs", +// this list contains lists of names that are allowed to be similar +// the assumption is that no name is ever contained in multiple lists. +const WHITELIST: &'static [&'static [&'static str]] = &[ + &["parsed", "parser"], + &["lhs", "rhs"], ]; struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); @@ -63,21 +73,27 @@ impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> } } -fn whitelisted(interned_name: &str) -> bool { +fn get_whitelist(interned_name: &str) -> Option<&'static[&'static str]> { for &allow in WHITELIST { - if interned_name == allow { - return true; + if whitelisted(interned_name, allow) { + return Some(allow); } - if interned_name.len() <= allow.len() { - continue; - } - // allow_* - let allow_start = allow.chars().chain(Some('_')); + } + None +} + +fn whitelisted(interned_name: &str, list: &[&str]) -> bool { + if list.iter().any(|&name| interned_name == name) { + return true; + } + for name in list { + // name_* + let allow_start = name.chars().chain(Some('_')); if interned_name.chars().zip(allow_start).all(|(l, r)| l == r) { return true; } - // *_allow - let allow_end = Some('_').into_iter().chain(allow.chars()); + // *_name + let allow_end = Some('_').into_iter().chain(name.chars()); if interned_name.chars().rev().zip(allow_end.rev()).all(|(l, r)| l == r) { return true; } @@ -110,29 +126,28 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } let count = interned_name.chars().count(); if count < 3 { - if count != 1 { - return; + if count == 1 { + let c = interned_name.chars().next().expect("already checked"); + self.check_short_name(c, span); } - let c = interned_name.chars().next().expect("already checked"); - self.check_short_name(c, span); - return; - } - if whitelisted(&interned_name) { return; } - for &(ref existing_name, sp, existing_len) in &self.0.names { + for existing_name in &self.0.names { + if whitelisted(&interned_name, existing_name.whitelist) { + continue; + } let mut split_at = None; - if existing_len > count { - if existing_len - count != 1 || levenstein_not_1(&interned_name, &existing_name) { + if existing_name.len > count { + if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned) { continue; } - } else if existing_len < count { - if count - existing_len != 1 || levenstein_not_1(&existing_name, &interned_name) { + } else if existing_name.len < count { + if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned, &interned_name) { continue; } } else { let mut interned_chars = interned_name.chars(); - let mut existing_chars = existing_name.chars(); + let mut existing_chars = existing_name.interned.chars(); let first_i = interned_chars.next().expect("we know we have at least one char"); let first_e = existing_chars.next().expect("we know we have at least one char"); let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); @@ -170,7 +185,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { span, "binding's name is too similar to existing binding", |diag| { - diag.span_note(sp, "existing binding defined here"); + diag.span_note(existing_name.span, "existing binding defined here"); if let Some(split) = split_at { diag.span_help(span, &format!("separate the discriminating character \ by an underscore like: `{}_{}`", @@ -180,7 +195,12 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { }); return; } - self.0.names.push((interned_name, span, count)); + self.0.names.push(ExistingName { + whitelist: get_whitelist(&interned_name).unwrap_or(&[]), + interned: interned_name, + span: span, + len: count, + }); } } diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index 7d0cea70366..aab88f742a6 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -11,6 +11,7 @@ //~| NOTE: lint level defined here //~| NOTE: lint level defined here //~| NOTE: lint level defined here +//~| NOTE: lint level defined here #![allow(unused)] fn main() { @@ -76,6 +77,12 @@ fn main() { let xyz2abc: i32; let xyzeabc: i32; //~ ERROR: name is too similar //~| HELP: for further information visit + + let parser: i32; //~ NOTE: existing binding defined here + let parsed: i32; + let parsee: i32; //~ ERROR: name is too similar + //~| HELP: for further information visit + //~| HELP: separate the discriminating character by an underscore like: `parse_e` } #[derive(Clone, Debug)] -- cgit 1.4.1-3-g733a5 From 7095b5df31dceb27b5ee1d344458cd6d1cd791d0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 30 Mar 2016 23:07:21 +0200 Subject: Fix FP in `REDUNDANT_CLOSURE` with divergent functions --- src/eta_reduction.rs | 3 ++- tests/compile-fail/eta.rs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index bae971f46ac..c080968ef84 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -61,7 +61,8 @@ fn check_closure(cx: &LateContext, expr: &Expr) { match fn_ty.sty { // Is it an unsafe function? They don't implement the closure traits ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { - if fn_ty.unsafety == Unsafety::Unsafe { + if fn_ty.unsafety == Unsafety::Unsafe || + fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { return; } } diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index 3fd089bf588..a744489fa9c 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -22,6 +22,14 @@ fn main() { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } + // See #815 + let e = Some(1u8).map(|a| divergent(a)); + let e = Some(1u8).map(|a| generic(a)); + //~^ ERROR redundant closure found + //~| HELP remove closure as shown + //~| SUGGESTION map(generic); + let e = Some(1u8).map(generic); + // See #515 let a: Option<Box<::std::ops::Deref<Target = [i32]>>> = Some(vec![1i32, 2]).map(|v| -> Box<::std::ops::Deref<Target = [i32]>> { Box::new(v) }); @@ -47,3 +55,11 @@ where F: Fn(&X, &X) -> bool { fn below(x: &u8, y: &u8) -> bool { x < y } unsafe fn unsafe_fn(_: u8) { } + +fn divergent(_: u8) -> ! { + unimplemented!() +} + +fn generic<T>(_: T) -> u8 { + 0 +} -- cgit 1.4.1-3-g733a5 From 9438f4f263e6fa8a53f766069e3522ca12b46ce7 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 31 Mar 2016 17:05:43 +0200 Subject: Rustup to 1.9.0-nightly (30a3849f2 2016-03-30) --- src/array_indexing.rs | 7 ++++--- src/bit_mask.rs | 3 +-- src/consts.rs | 4 ++-- src/enum_clike.rs | 5 +++-- src/identity_op.rs | 2 +- src/lib.rs | 1 + src/loops.rs | 5 +++-- src/matches.rs | 7 ++++--- src/methods.rs | 5 +++-- src/misc.rs | 8 ++++---- src/regex.rs | 5 +++-- src/types.rs | 11 ++++++----- tests/consts.rs | 17 +++++++---------- 13 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index 344a8b8c34e..e5f54c128ef 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -1,9 +1,10 @@ use rustc::lint::*; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc::middle::const_val::ConstVal; use rustc::ty::TyArray; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_math::ConstInt; use rustc_front::hir::*; -use rustc_const_eval::ConstInt; use syntax::ast::RangeLimits; use utils; diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 28fc311507d..cbe601ba1b4 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,11 +1,10 @@ use rustc::lint::*; -use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::{Def, PathResolution}; +use rustc_const_eval::lookup_const_by_id; use rustc_front::hir::*; use rustc_front::util::is_comparison_binop; use syntax::ast::LitKind; use syntax::codemap::Span; - use utils::span_lint; /// **What it does:** This lint checks for incompatible bit masks in comparisons. diff --git a/src/consts.rs b/src/consts.rs index 97a99dda4b5..73f2bc4653a 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,10 +1,10 @@ #![allow(cast_possible_truncation)] use rustc::lint::LateContext; -use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::{Def, PathResolution}; +use rustc_const_eval::lookup_const_by_id; +use rustc_const_math::{ConstInt, ConstUsize, ConstIsize}; use rustc_front::hir::*; -use rustc_const_eval::{ConstInt, ConstUsize, ConstIsize}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; diff --git a/src/enum_clike.rs b/src/enum_clike.rs index 85fa418f278..0e2a7a5304f 100644 --- a/src/enum_clike.rs +++ b/src/enum_clike.rs @@ -1,9 +1,10 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` use rustc::lint::*; -use syntax::attr::*; +use rustc::middle::const_val::ConstVal; +use rustc_const_math::*; use rustc_front::hir::*; -use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial}; +use syntax::attr::*; use utils::span_lint; /// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. diff --git a/src/identity_op.rs b/src/identity_op.rs index 9ade801abb3..c25047b87b4 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc_front::hir::*; use syntax::codemap::Span; use utils::{span_lint, snippet, in_macro}; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; /// **What it does:** This lint checks for identity operations, e.g. `x + 0`. /// diff --git a/src/lib.rs b/src/lib.rs index 2d12532fcfe..75970449582 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ extern crate quine_mc_cluskey; extern crate rustc_plugin; extern crate rustc_const_eval; +extern crate rustc_const_math; use rustc_plugin::Registry; pub mod consts; diff --git a/src/loops.rs b/src/loops.rs index 10a8a76d7ae..20d0fc026d1 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,11 +1,12 @@ use reexport::*; use rustc::front::map::Node::NodeBlock; use rustc::lint::*; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; +use rustc::middle::const_val::ConstVal; use rustc::middle::def::Def; use rustc::middle::region::CodeExtent; use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; use rustc_front::hir::*; use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; diff --git a/src/matches.rs b/src/matches.rs index 7bffd445f6b..40013209e57 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,9 +1,10 @@ use rustc::lint::*; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc::middle::const_val::ConstVal; use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_math::ConstInt; use rustc_front::hir::*; -use rustc_const_eval::ConstInt; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; diff --git a/src/methods.rs b/src/methods.rs index b8bbc0e9068..3ba6bfc9b41 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,9 +1,10 @@ use rustc::lint::*; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial}; +use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::CrateStore; use rustc::ty::subst::{Subst, TypeSpace}; use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; use rustc_front::hir::*; use std::borrow::Cow; use std::fmt; diff --git a/src/misc.rs b/src/misc.rs index 5a787ba6dba..a6cfec276e5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,9 +1,9 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::const_eval::ConstVal::Float; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::eval_const_expr_partial; +use rustc::middle::const_val::ConstVal; use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; use rustc_front::hir::*; use rustc_front::intravisit::FnKind; use rustc_front::util::{is_comparison_binop, binop_to_string}; @@ -180,7 +180,7 @@ impl LateLintPass for FloatCmp { fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); - if let Ok(Float(val)) = res { + if let Ok(ConstVal::Float(val)) = res { val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY } else { false diff --git a/src/regex.rs b/src/regex.rs index e8a71a2cb5a..46ee7776d66 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,7 +1,8 @@ use regex_syntax; use rustc::lint::*; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; -use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; +use rustc::middle::const_val::ConstVal; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; use rustc_front::hir::*; use std::collections::HashSet; use std::error::Error; diff --git a/src/types.rs b/src/types.rs index c2fc242ec53..8e9ac1217f0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,6 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::{const_eval, def}; +use rustc::middle::def; use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; @@ -683,10 +683,11 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs } fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeExpr<'a>> { - use rustc::middle::const_eval::EvalHint::ExprTypeChecked; - use types::ExtremeType::*; - use rustc::middle::const_eval::ConstVal::*; + use rustc::middle::const_val::ConstVal::*; + use rustc_const_math::*; + use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::*; + use types::ExtremeType::*; let ty = &cx.tcx.expr_ty(expr).sty; @@ -695,7 +696,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx _ => return None, }; - let cv = match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + let cv = match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { Ok(val) => val, Err(_) => return None, }; diff --git a/tests/consts.rs b/tests/consts.rs index 3a774f67473..b7b2f6a3f83 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -2,22 +2,19 @@ #![feature(rustc_private)] extern crate clippy; -extern crate syntax; extern crate rustc; -extern crate rustc_front; extern crate rustc_const_eval; +extern crate rustc_const_math; +extern crate rustc_front; +extern crate syntax; +use clippy::consts::{constant_simple, Constant, FloatWidth}; +use rustc_const_math::ConstInt; use rustc_front::hir::*; -use rustc_const_eval::ConstInt; +use syntax::ast::{LitIntType, LitKind, StrStyle}; +use syntax::codemap::{Spanned, COMMAND_LINE_SP}; use syntax::parse::token::InternedString; use syntax::ptr::P; -use syntax::codemap::{Spanned, COMMAND_LINE_SP}; - -use syntax::ast::LitKind; -use syntax::ast::LitIntType; -use syntax::ast::StrStyle; - -use clippy::consts::{constant_simple, Constant, FloatWidth}; fn spanned<T>(t: T) -> Spanned<T> { Spanned{ node: t, span: COMMAND_LINE_SP } -- cgit 1.4.1-3-g733a5 From 4a9a4fcb4d6d51dd4e18670d482353cd38815662 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 31 Mar 2016 17:07:35 +0200 Subject: Bump to 0.0.59 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 058dc012cfa..6dcadfca46b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.58" +version = "0.0.59" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 73ee3e6f36a73d149f9b7994b9c3c57fa14c93e2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 31 Mar 2016 15:38:43 +0200 Subject: whitelist more non-expressive-name false positives --- src/non_expressive_names.rs | 8 ++++---- tests/compile-fail/non_expressive_names.rs | 13 +++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 32118b11c4e..36fcc292bfc 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -60,6 +60,8 @@ struct SimilarNamesLocalVisitor<'a, 'b: 'a> { const WHITELIST: &'static [&'static [&'static str]] = &[ &["parsed", "parser"], &["lhs", "rhs"], + &["tx", "rx"], + &["set", "get"], ]; struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); @@ -88,13 +90,11 @@ fn whitelisted(interned_name: &str, list: &[&str]) -> bool { } for name in list { // name_* - let allow_start = name.chars().chain(Some('_')); - if interned_name.chars().zip(allow_start).all(|(l, r)| l == r) { + if interned_name.chars().zip(name.chars()).all(|(l, r)| l == r) { return true; } // *_name - let allow_end = Some('_').into_iter().chain(name.chars()); - if interned_name.chars().rev().zip(allow_end.rev()).all(|(l, r)| l == r) { + if interned_name.chars().rev().zip(name.chars().rev()).all(|(l, r)| l == r) { return true; } } diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index aab88f742a6..b756253e6ad 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -11,7 +11,6 @@ //~| NOTE: lint level defined here //~| NOTE: lint level defined here //~| NOTE: lint level defined here -//~| NOTE: lint level defined here #![allow(unused)] fn main() { @@ -45,9 +44,8 @@ fn main() { let bla_rhs: i32; let bla_lhs: i32; - let blubrhs: i32; //~ NOTE: existing binding defined here - let blublhs: i32; //~ ERROR: name is too similar - //~| HELP: for further information visit + let blubrhs: i32; + let blublhs: i32; let blubx: i32; //~ NOTE: existing binding defined here let bluby: i32; //~ ERROR: name is too similar @@ -83,6 +81,13 @@ fn main() { let parsee: i32; //~ ERROR: name is too similar //~| HELP: for further information visit //~| HELP: separate the discriminating character by an underscore like: `parse_e` + + let setter: i32; + let getter: i32; + let tx1: i32; + let rx1: i32; + let tx_cake: i32; + let rx_cake: i32; } #[derive(Clone, Debug)] -- cgit 1.4.1-3-g733a5 From 4c6c84e0a19539a4c5e742e02387ec17efe68d0a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Fri, 1 Apr 2016 10:33:17 +0200 Subject: fix #820 --- src/methods.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index 3ba6bfc9b41..646cd319a0c 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -302,7 +302,8 @@ impl LintPass for MethodsPass { CLONE_ON_COPY, CLONE_DOUBLE_REF, NEW_RET_NO_SELF, - SINGLE_CHAR_PATTERN) + SINGLE_CHAR_PATTERN, + SEARCH_IS_SOME) } } -- cgit 1.4.1-3-g733a5 From 8bfe38c432694677282f658b48b2a4c86d6a23a5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Apr 2016 13:14:39 +0200 Subject: Improve the `match_same_arms` doc --- src/copies.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/copies.rs b/src/copies.rs index 2de034f83c2..b8eb97cbeed 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -38,7 +38,9 @@ declare_lint! { /// **What it does:** This lint checks for `match` with identical arm bodies. /// -/// **Why is this bad?** This is probably a copy & paste error. +/// **Why is this bad?** This is probably a copy & paste error. If arm bodies are the same on +/// purpose, you can factor them +/// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). /// /// **Known problems:** Hopefully none. /// -- cgit 1.4.1-3-g733a5 From f16da4fddae85c73f088fdc38151eb69b1caffc3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Apr 2016 17:24:55 +0200 Subject: Fix false positive with `DOC_MARKDOWN` and links --- src/doc.rs | 9 +++++++-- tests/compile-fail/doc.rs | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 5637fb2cefb..9a6a86d4140 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -69,7 +69,7 @@ fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { let (doc, span) = doc_attrs.next().unwrap_or_else(|| unreachable!()); (doc.into(), Some(span)) } - _ => (doc_attrs.map(|s| s.0).collect::<String>().into(), None), + _ => (doc_attrs.map(|s| format!("{}\n", s.0)).collect::<String>().into(), None), } } @@ -124,9 +124,14 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { s != "_" && !s.contains("\\_") && s.contains('_') } + // Something with a `/` might be a link, don’t warn (see #823): + if word.contains('/') { + return; + } + // Trim punctuation as in `some comment (see foo::bar).` // ^^ - // Or even as `_foo bar_` which is emphasized. + // Or even as in `_foo bar_` which is emphasized. let word = word.trim_matches(|c: char| !c.is_alphanumeric()); if has_underscore(word) || word.contains("::") || is_camel_case(word) { diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index eecf5e0b206..a7b316e1f82 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -29,6 +29,11 @@ fn multiline_ticks() { fn test_emphasis() { } +/// This test has [a link with underscores][chunked-example] inside it. See #823. +/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues). +/// +/// [chunked-example]: http://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example + /// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and /// `multiline_ticks` functions. fn main() { -- cgit 1.4.1-3-g733a5 From f8acc8344933d2abab88f77c2b8d7cc7a6498ed9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Apr 2016 17:48:13 +0200 Subject: Rustup to 1.9.0-nightly (e1195c24b 2016-03-31) This does not require a version bump, it only affects tests. --- tests/compile-fail/transmute.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 5bae2c72643..cd86281d8f2 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -62,19 +62,19 @@ unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { fn useless() { unsafe { let _: Vec<i32> = core::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to itself let _: Vec<i32> = core::mem::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to itself let _: Vec<i32> = std::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to itself let _: Vec<i32> = std::mem::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to itself let _: Vec<i32> = my_transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to itself + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to itself let _: Vec<u32> = core::intrinsics::transmute(my_vec()); let _: Vec<u32> = core::mem::transmute(my_vec()); @@ -92,16 +92,16 @@ fn crosspointer() { unsafe { let _: Vec<i32> = core::intrinsics::transmute(vec_const_ptr); - //~^ ERROR transmute from a type (`*const collections::vec::Vec<i32>`) to the type that it points to (`collections::vec::Vec<i32>`) + //~^ ERROR transmute from a type (`*const std::vec::Vec<i32>`) to the type that it points to (`std::vec::Vec<i32>`) let _: Vec<i32> = core::intrinsics::transmute(vec_mut_ptr); - //~^ ERROR transmute from a type (`*mut collections::vec::Vec<i32>`) to the type that it points to (`collections::vec::Vec<i32>`) + //~^ ERROR transmute from a type (`*mut std::vec::Vec<i32>`) to the type that it points to (`std::vec::Vec<i32>`) let _: *const Vec<i32> = core::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to a pointer to that type (`*const collections::vec::Vec<i32>`) + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to a pointer to that type (`*const std::vec::Vec<i32>`) let _: *mut Vec<i32> = core::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`collections::vec::Vec<i32>`) to a pointer to that type (`*mut collections::vec::Vec<i32>`) + //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to a pointer to that type (`*mut std::vec::Vec<i32>`) } } -- cgit 1.4.1-3-g733a5 From 6b0eb107694aa07abf8a85e42b5991e9744b73eb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 1 Apr 2016 21:24:26 +0530 Subject: Ignore pathological cases in boolean lint (#825) --- src/booleans.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/booleans.rs b/src/booleans.rs index 877a45a355a..37ad927ef92 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -294,6 +294,14 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { cx: self.0, }; if let Ok(expr) = h2q.run(e) { + + if h2q.terminals.len() > 8 { + // QMC has exponentially slow behavior as the number of terminals increases + // 8 is reasonable, it takes approximately 0.2 seconds. + // See #825 + return; + } + let stats = terminal_stats(&expr); let mut simplified = expr.simplify(); for simple in Bool::Not(Box::new(expr.clone())).simplify() { -- cgit 1.4.1-3-g733a5 From a504ef488a719ef2dd7daecc1ad092b3bc454c32 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 1 Apr 2016 21:25:20 +0530 Subject: Add regression test for #825 --- tests/issue-825.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/issue-825.rs diff --git a/tests/issue-825.rs b/tests/issue-825.rs new file mode 100644 index 00000000000..f5c0725f812 --- /dev/null +++ b/tests/issue-825.rs @@ -0,0 +1,25 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(warnings)] + +// this should compile in a reasonable amount of time +fn rust_type_id(name: String) { + if "bool" == &name[..] || + "uint" == &name[..] || + "u8" == &name[..] || + "u16" == &name[..] || + "u32" == &name[..] || + "f32" == &name[..] || + "f64" == &name[..] || + "i8" == &name[..] || + "i16" == &name[..] || + "i32" == &name[..] || + "i64" == &name[..] || + "Self" == &name[..] || + "str" == &name[..] { + unreachable!(); + } +} + +fn main() {} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 9349ec597d54e125d740bfafca3dd381410f7243 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 1 Apr 2016 21:25:38 +0530 Subject: Bump to 0.0.60 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6dcadfca46b..febe1ab9c19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.59" +version = "0.0.60" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 498e0fba7f5d614c8165b41204e05c5ad461d25d Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Fri, 25 Mar 2016 02:42:27 -0700 Subject: Initial attempt at linting invalid upcast comparisons --- src/lib.rs | 2 + src/types.rs | 223 +++++++++++++++++++++-- tests/compile-fail/invalid_upcast_comparisons.rs | 15 ++ 3 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 tests/compile-fail/invalid_upcast_comparisons.rs diff --git a/src/lib.rs b/src/lib.rs index 75970449582..6834753adf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -221,6 +221,7 @@ pub fn plugin_registrar(reg: &mut Registry) { }); reg.register_late_lint_pass(box drop_ref::DropRefPass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); + reg.register_late_lint_pass(box types::InvalidUpcastComparisons); reg.register_late_lint_pass(box regex::RegexPass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_late_lint_pass(box format::FormatMacLint); @@ -367,6 +368,7 @@ pub fn plugin_registrar(reg: &mut Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, + types::INVALID_UPCAST_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, types::LET_UNIT_VALUE, diff --git a/src/types.rs b/src/types.rs index 8e9ac1217f0..6f08b57b55a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,7 +1,10 @@ use reexport::*; +use rustc_const_eval::*; use rustc::lint::*; use rustc::middle::def; use rustc::ty; +use rustc::middle::const_eval::ConstVal::Integral; +use rustc_const_eval; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc_front::util::{is_comparison_binop, binop_to_string}; @@ -9,6 +12,7 @@ use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; use utils::*; + /// Handles all the linting of funky types #[allow(missing_copy_implementations)] pub struct TypePass; @@ -640,24 +644,32 @@ enum AbsurdComparisonResult { InequalityImpossible, } +enum Rel { + Lt, + Le, +} + +// Put the expression in the form lhs < rhs or lhs <= rhs. +fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) + -> Option<(Rel, &'a Expr, &'a Expr)> { + match op { + BiLt => Some((Rel::Lt, lhs, rhs)), + BiLe => Some((Rel::Le, lhs, rhs)), + BiGt => Some((Rel::Lt, rhs, lhs)), + BiGe => Some((Rel::Le, rhs, lhs)), + _ => return None, + } +} + fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { use types::ExtremeType::*; use types::AbsurdComparisonResult::*; type Extr<'a> = ExtremeExpr<'a>; - // Put the expression in the form lhs < rhs or lhs <= rhs. - enum Rel { - Lt, - Le, - }; - let (rel, normalized_lhs, normalized_rhs) = match op { - BiLt => (Rel::Lt, lhs, rhs), - BiLe => (Rel::Le, lhs, rhs), - BiGt => (Rel::Lt, rhs, lhs), - BiGe => (Rel::Le, rhs, lhs), - _ => return None, - }; + let normalized = normalize_comparison(op, lhs, rhs); + if normalized.is_none() { return None; } // Could be an if let, but this prevents rightward drift + let (rel, normalized_lhs, normalized_rhs) = normalized.unwrap(); let lx = detect_extreme_expr(cx, normalized_lhs); let rx = detect_extreme_expr(cx, normalized_rhs); @@ -778,3 +790,190 @@ impl LateLintPass for AbsurdExtremeComparisons { } } } + +/// **What it does:** This lint checks for comparisons where the relation is always either true or false, but where one side has been upcast so that the comparison is necessary. Only integer types are checked. +/// +/// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` will mistakenly imply that it is possible for `x` to be outside the range of `u8`. +/// +/// **Known problems:** None +/// +/// **Example:** `let x : u8 = ...; (x as u32) > 300` +declare_lint! { + pub INVALID_UPCAST_COMPARISONS, Warn, + "a comparison involving an term's upcasting to be within the range of the other side of the \ + term is always true or false" +} + +pub struct InvalidUpcastComparisons; + +impl LintPass for InvalidUpcastComparisons { + fn get_lints(&self) -> LintArray { + lint_array!(INVALID_UPCAST_COMPARISONS) + } +} + +enum FullInt { + S(i64), + U(u64), +} + +use std; +use self::FullInt::*; +use std::cmp::Ordering::*; + +impl FullInt { + fn cmp_s_u(s: &i64, u: &u64) -> std::cmp::Ordering { + if *s < 0 { + Less + } else if *u > (i64::max_value() as u64) { + Greater + } else { + (*s as u64).cmp(u) + } + } +} + +impl PartialEq for FullInt { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Equal + } +} +impl Eq for FullInt {} + +impl PartialOrd for FullInt { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(match (self, other) { + (&S(ref s), &S(ref o)) => s.cmp(o), + (&U(ref s), &U(ref o)) => s.cmp(o), + (&S(ref s), &U(ref o)) => Self::cmp_s_u(s, o), + (&U(ref s), &S(ref o)) => Self::cmp_s_u(o, s).reverse(), + }) + } +} +impl Ord for FullInt { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.partial_cmp(other).unwrap() + } +} + + +fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { + use rustc::middle::const_eval::EvalHint::ExprTypeChecked; + + if let ExprCast(ref cast_exp,_) = expr.node { + let cv = match const_eval::eval_const_expr_partial(cx.tcx, cast_exp, ExprTypeChecked, None) { + Ok(val) => val, + Err(_) => return None, + }; + + if let Integral(const_int) = cv { + Some(match const_int { + I8(_) => (S(i8::min_value() as i64), S(i8::max_value() as i64)), + I16(_) => (S(i16::min_value() as i64), S(i16::max_value() as i64)), + I32(_) => (S(i32::min_value() as i64), S(i32::max_value() as i64)), + Isize(_) | + I64(_) | + InferSigned(_) => (S(i64::max_value()), S(i64::max_value())), + U8(_) => (U(u8::min_value() as u64), U(u8::max_value() as u64)), + U16(_) => (U(u16::min_value() as u64), U(u16::max_value() as u64)), + U32(_) => (U(u32::min_value() as u64), U(u32::max_value() as u64)), + Usize(_) | + U64(_) | + Infer(_) => (U(u64::max_value()), U(u64::max_value())), + }) + } else { + None + } + } else { + None + } +} + +fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { + use rustc::middle::const_eval::EvalHint::ExprTypeChecked; + + match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + Ok(val) => { + if let Integral(const_int) = val { + Some(match const_int { + I8(x) => S(x as i64), + I16(x) => S(x as i64), + I32(x) => S(x as i64), + Isize(x) => S(match x { + Is32(x_) => x_ as i64, + Is64(x_) => x_ + }), + I64(x) => S(x), + InferSigned(x) => S(x as i64), + U8(x) => U(x as u64), + U16(x) => U(x as u64), + U32(x) => U(x as u64), + Usize(x) => U(match x { + Us32(x_) => x_ as u64, + Us64(x_) => x_, + }), + U64(x) => U(x), + Infer(x) => U(x as u64), + }) + } else { + None + } + }, + Err(_) => return None, + } +} + +impl LateLintPass for InvalidUpcastComparisons { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + let normalized = normalize_comparison(cmp.node, lhs, rhs); + if normalized.is_none() { return; } + let (rel, normalized_lhs, normalized_rhs) = normalized.unwrap(); + + let norm_lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); + let norm_rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); + + if let Some(nlb) = norm_lhs_bounds { + if let Some(norm_rhs_val) = node_as_const_fullint(cx, normalized_rhs) { + if match rel { + Rel::Lt => nlb.1 < norm_rhs_val, + Rel::Le => nlb.1 <= norm_rhs_val, + } { + // Expression is always true + cx.span_lint(INVALID_UPCAST_COMPARISONS, + expr.span, + &format!("")); + } else if match rel { + Rel::Lt => nlb.0 >= norm_rhs_val, + Rel::Le => nlb.0 > norm_rhs_val, + } { + // Expression is always false + cx.span_lint(INVALID_UPCAST_COMPARISONS, + expr.span, + &format!("")); + } + } + } else if let Some(nrb) = norm_rhs_bounds { + if let Some(norm_lhs_val) = node_as_const_fullint(cx, normalized_lhs) { + if match rel { + Rel::Lt => norm_lhs_val < nrb.0, + Rel::Le => norm_lhs_val <= nrb.0, + } { + // Expression is always true + cx.span_lint(INVALID_UPCAST_COMPARISONS, + expr.span, + &format!("")); + } else if match rel { + Rel::Lt => norm_lhs_val >= nrb.1, + Rel::Le => norm_lhs_val > nrb.1, + } { + // Expression is always false + cx.span_lint(INVALID_UPCAST_COMPARISONS, + expr.span, + &format!("")); + } + } + } + } + } +} diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs new file mode 100644 index 00000000000..63ccb6efd9d --- /dev/null +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(invalid_upcast_comparisons)] +#![allow(unused, eq_op, no_effect)] +fn main() { + let zero: u32 = 0; + let u8_max: u8 = 255; + + (u8_max as u32) > 300; //~ERROR + (u8_max as u32) > 20; + + (zero as i32) < -5; //~ERROR + (zero as i32) < 10; +} -- cgit 1.4.1-3-g733a5 From c81edfc7b904ccab94073a5726fda27c439db010 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Fri, 25 Mar 2016 02:44:45 -0700 Subject: Updated lints with script --- README.md | 3 ++- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e59012c8165..c81fb9b52c1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 139 lints included in this crate: +There are 140 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -68,6 +68,7 @@ name [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations +[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an term's upcasting to be within the range of the other side of the term is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` diff --git a/src/lib.rs b/src/lib.rs index 6834753adf0..f3fc453cf69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -368,9 +368,9 @@ pub fn plugin_registrar(reg: &mut Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, - types::INVALID_UPCAST_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, + types::INVALID_UPCAST_COMPARISONS, types::LET_UNIT_VALUE, types::LINKEDLIST, types::TYPE_COMPLEXITY, -- cgit 1.4.1-3-g733a5 From 8687949a29aaf8e33718a33154f9d9b65d39a6be Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Fri, 25 Mar 2016 15:47:27 -0700 Subject: Tests passing for invalid_upcast_comparisons --- src/types.rs | 115 +++++++++++------------ tests/compile-fail/invalid_upcast_comparisons.rs | 8 +- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/src/types.rs b/src/types.rs index 6f08b57b55a..8fede2593ed 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,4 @@ use reexport::*; -use rustc_const_eval::*; use rustc::lint::*; use rustc::middle::def; use rustc::ty; @@ -657,7 +656,7 @@ fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) BiLe => Some((Rel::Le, lhs, rhs)), BiGt => Some((Rel::Lt, rhs, lhs)), BiGe => Some((Rel::Le, rhs, lhs)), - _ => return None, + _ => None, } } @@ -669,7 +668,7 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs let normalized = normalize_comparison(op, lhs, rhs); if normalized.is_none() { return None; } // Could be an if let, but this prevents rightward drift - let (rel, normalized_lhs, normalized_rhs) = normalized.unwrap(); + let (rel, normalized_lhs, normalized_rhs) = normalized.expect("Unreachable-- is none check above"); let lx = detect_extreme_expr(cx, normalized_lhs); let rx = detect_extreme_expr(cx, normalized_rhs); @@ -818,15 +817,15 @@ enum FullInt { } use std; -use self::FullInt::*; -use std::cmp::Ordering::*; +use std::cmp::Ordering; impl FullInt { + #[allow(cast_sign_loss)] fn cmp_s_u(s: &i64, u: &u64) -> std::cmp::Ordering { if *s < 0 { - Less + Ordering::Less } else if *u > (i64::max_value() as u64) { - Greater + Ordering::Greater } else { (*s as u64).cmp(u) } @@ -835,7 +834,7 @@ impl FullInt { impl PartialEq for FullInt { fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Equal + self.cmp(other) == Ordering::Equal } } impl Eq for FullInt {} @@ -843,46 +842,43 @@ impl Eq for FullInt {} impl PartialOrd for FullInt { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(match (self, other) { - (&S(ref s), &S(ref o)) => s.cmp(o), - (&U(ref s), &U(ref o)) => s.cmp(o), - (&S(ref s), &U(ref o)) => Self::cmp_s_u(s, o), - (&U(ref s), &S(ref o)) => Self::cmp_s_u(o, s).reverse(), + (&FullInt::S(ref s), &FullInt::S(ref o)) => s.cmp(o), + (&FullInt::U(ref s), &FullInt::U(ref o)) => s.cmp(o), + (&FullInt::S(ref s), &FullInt::U(ref o)) => Self::cmp_s_u(s, o), + (&FullInt::U(ref s), &FullInt::S(ref o)) => Self::cmp_s_u(o, s).reverse(), }) } } impl Ord for FullInt { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.partial_cmp(other).unwrap() + self.partial_cmp(other).expect("partial_cmp for FullInt can never return None") } } fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { - use rustc::middle::const_eval::EvalHint::ExprTypeChecked; + use rustc::middle::ty::TypeVariants::{TyInt, TyUint}; + use syntax::ast::UintTy; + use syntax::ast::IntTy; + use std::*; if let ExprCast(ref cast_exp,_) = expr.node { - let cv = match const_eval::eval_const_expr_partial(cx.tcx, cast_exp, ExprTypeChecked, None) { - Ok(val) => val, - Err(_) => return None, - }; - - if let Integral(const_int) = cv { - Some(match const_int { - I8(_) => (S(i8::min_value() as i64), S(i8::max_value() as i64)), - I16(_) => (S(i16::min_value() as i64), S(i16::max_value() as i64)), - I32(_) => (S(i32::min_value() as i64), S(i32::max_value() as i64)), - Isize(_) | - I64(_) | - InferSigned(_) => (S(i64::max_value()), S(i64::max_value())), - U8(_) => (U(u8::min_value() as u64), U(u8::max_value() as u64)), - U16(_) => (U(u16::min_value() as u64), U(u16::max_value() as u64)), - U32(_) => (U(u32::min_value() as u64), U(u32::max_value() as u64)), - Usize(_) | - U64(_) | - Infer(_) => (U(u64::max_value()), U(u64::max_value())), - }) - } else { - None + match cx.tcx.expr_ty(cast_exp).sty { + TyInt(int_ty) => Some(match int_ty { + IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), + IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), + IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), + IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), + IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), + }), + TyUint(uint_ty) => Some(match uint_ty { + UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), + UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), + UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), + UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), + UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), + }), + _ => None, } } else { None @@ -891,35 +887,36 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { use rustc::middle::const_eval::EvalHint::ExprTypeChecked; + use rustc_const_eval::*; match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { Ok(val) => { if let Integral(const_int) = val { Some(match const_int { - I8(x) => S(x as i64), - I16(x) => S(x as i64), - I32(x) => S(x as i64), - Isize(x) => S(match x { + I8(x) => FullInt::S(x as i64), + I16(x) => FullInt::S(x as i64), + I32(x) => FullInt::S(x as i64), + Isize(x) => FullInt::S(match x { Is32(x_) => x_ as i64, Is64(x_) => x_ }), - I64(x) => S(x), - InferSigned(x) => S(x as i64), - U8(x) => U(x as u64), - U16(x) => U(x as u64), - U32(x) => U(x as u64), - Usize(x) => U(match x { + I64(x) => FullInt::S(x), + InferSigned(x) => FullInt::S(x as i64), + U8(x) => FullInt::U(x as u64), + U16(x) => FullInt::U(x as u64), + U32(x) => FullInt::U(x as u64), + Usize(x) => FullInt::U(match x { Us32(x_) => x_ as u64, Us64(x_) => x_, }), - U64(x) => U(x), - Infer(x) => U(x as u64), + U64(x) => FullInt::U(x), + Infer(x) => FullInt::U(x as u64), }) } else { None } }, - Err(_) => return None, + Err(_) => None, } } @@ -928,12 +925,14 @@ impl LateLintPass for InvalidUpcastComparisons { if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { let normalized = normalize_comparison(cmp.node, lhs, rhs); if normalized.is_none() { return; } - let (rel, normalized_lhs, normalized_rhs) = normalized.unwrap(); + let (rel, normalized_lhs, normalized_rhs) = normalized.expect("Unreachable-- is none check above"); + + let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); + let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); - let norm_lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); - let norm_rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); + let msg = "Because of the numeric bounds prior to casting, this expression is always "; - if let Some(nlb) = norm_lhs_bounds { + if let Some(nlb) = lhs_bounds { if let Some(norm_rhs_val) = node_as_const_fullint(cx, normalized_rhs) { if match rel { Rel::Lt => nlb.1 < norm_rhs_val, @@ -942,7 +941,7 @@ impl LateLintPass for InvalidUpcastComparisons { // Expression is always true cx.span_lint(INVALID_UPCAST_COMPARISONS, expr.span, - &format!("")); + &format!("{}{}.", msg, "true")); } else if match rel { Rel::Lt => nlb.0 >= norm_rhs_val, Rel::Le => nlb.0 > norm_rhs_val, @@ -950,10 +949,10 @@ impl LateLintPass for InvalidUpcastComparisons { // Expression is always false cx.span_lint(INVALID_UPCAST_COMPARISONS, expr.span, - &format!("")); + &format!("{}{}.", msg, "false")); } } - } else if let Some(nrb) = norm_rhs_bounds { + } else if let Some(nrb) = rhs_bounds { if let Some(norm_lhs_val) = node_as_const_fullint(cx, normalized_lhs) { if match rel { Rel::Lt => norm_lhs_val < nrb.0, @@ -962,7 +961,7 @@ impl LateLintPass for InvalidUpcastComparisons { // Expression is always true cx.span_lint(INVALID_UPCAST_COMPARISONS, expr.span, - &format!("")); + &format!("{}{}.", msg, "true")); } else if match rel { Rel::Lt => norm_lhs_val >= nrb.1, Rel::Le => norm_lhs_val > nrb.1, @@ -970,7 +969,7 @@ impl LateLintPass for InvalidUpcastComparisons { // Expression is always false cx.span_lint(INVALID_UPCAST_COMPARISONS, expr.span, - &format!("")); + &format!("{}{}.", msg, "false")); } } } diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index 63ccb6efd9d..d5849420e38 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -7,9 +7,13 @@ fn main() { let zero: u32 = 0; let u8_max: u8 = 255; - (u8_max as u32) > 300; //~ERROR + (u8_max as u32) > 300; //~ERROR Because of the numeric bounds prior to casting, this expression is always false. (u8_max as u32) > 20; - (zero as i32) < -5; //~ERROR + (zero as i32) < -5; //~ERROR Because of the numeric bounds prior to casting, this expression is always false. (zero as i32) < 10; + + -5 < (zero as i32); //~ERROR Because of the numeric bounds prior to casting, this expression is always true. + 0 <= (zero as i32); //~ERROR Because of the numeric bounds prior to casting, this expression is always true. + 0 < (zero as i32); } -- cgit 1.4.1-3-g733a5 From 106ae7da441c075aa1b83f5c021ea47f25589d05 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Fri, 25 Mar 2016 22:57:03 -0700 Subject: Invalid upcast comparison cleanup --- README.md | 2 +- src/types.rs | 159 ++++++++++------------- src/utils/comparisons.rs | 19 +++ src/utils/mod.rs | 1 + tests/compile-fail/invalid_upcast_comparisons.rs | 8 +- 5 files changed, 93 insertions(+), 96 deletions(-) create mode 100644 src/utils/comparisons.rs diff --git a/README.md b/README.md index c81fb9b52c1..fee6d066e7c 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ name [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations -[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an term's upcasting to be within the range of the other side of the term is always true or false +[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` diff --git a/src/types.rs b/src/types.rs index 8fede2593ed..5e4b3e673cd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -643,32 +643,21 @@ enum AbsurdComparisonResult { InequalityImpossible, } -enum Rel { - Lt, - Le, -} -// Put the expression in the form lhs < rhs or lhs <= rhs. -fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) - -> Option<(Rel, &'a Expr, &'a Expr)> { - match op { - BiLt => Some((Rel::Lt, lhs, rhs)), - BiLe => Some((Rel::Le, lhs, rhs)), - BiGt => Some((Rel::Lt, rhs, lhs)), - BiGe => Some((Rel::Le, rhs, lhs)), - _ => None, - } -} fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { use types::ExtremeType::*; use types::AbsurdComparisonResult::*; + use utils::comparisons::*; type Extr<'a> = ExtremeExpr<'a>; let normalized = normalize_comparison(op, lhs, rhs); - if normalized.is_none() { return None; } // Could be an if let, but this prevents rightward drift - let (rel, normalized_lhs, normalized_rhs) = normalized.expect("Unreachable-- is none check above"); + let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { + val + } else { + return None; + }; let lx = detect_extreme_expr(cx, normalized_lhs); let rx = detect_extreme_expr(cx, normalized_rhs); @@ -799,8 +788,7 @@ impl LateLintPass for AbsurdExtremeComparisons { /// **Example:** `let x : u8 = ...; (x as u32) > 300` declare_lint! { pub INVALID_UPCAST_COMPARISONS, Warn, - "a comparison involving an term's upcasting to be within the range of the other side of the \ - term is always true or false" + "a comparison involving an upcast which is always true or false" } pub struct InvalidUpcastComparisons; @@ -811,46 +799,39 @@ impl LintPass for InvalidUpcastComparisons { } } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] enum FullInt { S(i64), U(u64), } -use std; use std::cmp::Ordering; impl FullInt { #[allow(cast_sign_loss)] - fn cmp_s_u(s: &i64, u: &u64) -> std::cmp::Ordering { - if *s < 0 { + fn cmp_s_u(s: i64, u: u64) -> Ordering { + if s < 0 { Ordering::Less - } else if *u > (i64::max_value() as u64) { + } else if u > (i64::max_value() as u64) { Ordering::Greater } else { - (*s as u64).cmp(u) + (s as u64).cmp(&u) } } } -impl PartialEq for FullInt { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} -impl Eq for FullInt {} - impl PartialOrd for FullInt { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(match (self, other) { - (&FullInt::S(ref s), &FullInt::S(ref o)) => s.cmp(o), - (&FullInt::U(ref s), &FullInt::U(ref o)) => s.cmp(o), - (&FullInt::S(ref s), &FullInt::U(ref o)) => Self::cmp_s_u(s, o), - (&FullInt::U(ref s), &FullInt::S(ref o)) => Self::cmp_s_u(o, s).reverse(), + (&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o), + (&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o), + (&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o), + (&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(), }) } } impl Ord for FullInt { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).expect("partial_cmp for FullInt can never return None") } } @@ -896,19 +877,15 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { I8(x) => FullInt::S(x as i64), I16(x) => FullInt::S(x as i64), I32(x) => FullInt::S(x as i64), - Isize(x) => FullInt::S(match x { - Is32(x_) => x_ as i64, - Is64(x_) => x_ - }), + Isize(Is32(x)) => FullInt::S(x as i64), + Isize(Is64(x)) | I64(x) => FullInt::S(x), InferSigned(x) => FullInt::S(x as i64), U8(x) => FullInt::U(x as u64), U16(x) => FullInt::U(x as u64), U32(x) => FullInt::U(x as u64), - Usize(x) => FullInt::U(match x { - Us32(x_) => x_ as u64, - Us64(x_) => x_, - }), + Usize(Us32(x)) => FullInt::U(x as u64), + Usize(Us64(x)) | U64(x) => FullInt::U(x), Infer(x) => FullInt::U(x as u64), }) @@ -920,59 +897,59 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { } } +fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { + if let ExprCast(ref cast_val, _) = expr.node { + span_lint( + cx, + INVALID_UPCAST_COMPARISONS, + *span, + &format!( + "because of the numeric bounds on `{}` prior to casting, this expression is always {}", + snippet(cx, cast_val.span, "the expression"), + if always { "true" } else { "false" }, + ) + ); + } +} + +fn upcast_comparison_bounds_err( + cx: &LateContext, span: &Span, rel: comparisons::Rel, + lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { + use utils::comparisons::*; + + if let Some(nlb) = lhs_bounds { + if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { + if match rel { + Rel::Lt => if invert { norm_rhs_val < nlb.0 } else { nlb.1 < norm_rhs_val }, + Rel::Le => if invert { norm_rhs_val <= nlb.0 } else { nlb.1 <= norm_rhs_val }, + } { + err_upcast_comparison(cx, &span, lhs, true) + } else if match rel { + Rel::Lt => if invert { norm_rhs_val >= nlb.1 } else { nlb.0 >= norm_rhs_val }, + Rel::Le => if invert { norm_rhs_val > nlb.1 } else { nlb.0 > norm_rhs_val }, + } { + err_upcast_comparison(cx, &span, lhs, false) + } + } + } +} + impl LateLintPass for InvalidUpcastComparisons { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - let normalized = normalize_comparison(cmp.node, lhs, rhs); - if normalized.is_none() { return; } - let (rel, normalized_lhs, normalized_rhs) = normalized.expect("Unreachable-- is none check above"); + + let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); + let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { + val + } else { + return; + }; let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); - let msg = "Because of the numeric bounds prior to casting, this expression is always "; - - if let Some(nlb) = lhs_bounds { - if let Some(norm_rhs_val) = node_as_const_fullint(cx, normalized_rhs) { - if match rel { - Rel::Lt => nlb.1 < norm_rhs_val, - Rel::Le => nlb.1 <= norm_rhs_val, - } { - // Expression is always true - cx.span_lint(INVALID_UPCAST_COMPARISONS, - expr.span, - &format!("{}{}.", msg, "true")); - } else if match rel { - Rel::Lt => nlb.0 >= norm_rhs_val, - Rel::Le => nlb.0 > norm_rhs_val, - } { - // Expression is always false - cx.span_lint(INVALID_UPCAST_COMPARISONS, - expr.span, - &format!("{}{}.", msg, "false")); - } - } - } else if let Some(nrb) = rhs_bounds { - if let Some(norm_lhs_val) = node_as_const_fullint(cx, normalized_lhs) { - if match rel { - Rel::Lt => norm_lhs_val < nrb.0, - Rel::Le => norm_lhs_val <= nrb.0, - } { - // Expression is always true - cx.span_lint(INVALID_UPCAST_COMPARISONS, - expr.span, - &format!("{}{}.", msg, "true")); - } else if match rel { - Rel::Lt => norm_lhs_val >= nrb.1, - Rel::Le => norm_lhs_val > nrb.1, - } { - // Expression is always false - cx.span_lint(INVALID_UPCAST_COMPARISONS, - expr.span, - &format!("{}{}.", msg, "false")); - } - } - } + upcast_comparison_bounds_err(cx, &expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); + upcast_comparison_bounds_err(cx, &expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); } } } diff --git a/src/utils/comparisons.rs b/src/utils/comparisons.rs new file mode 100644 index 00000000000..2222c31a4f9 --- /dev/null +++ b/src/utils/comparisons.rs @@ -0,0 +1,19 @@ +use rustc_front::hir::{BinOp_, Expr}; + +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub enum Rel { + Lt, + Le, +} + +/// Put the expression in the form `lhs < rhs` or `lhs <= rhs`. +pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) + -> Option<(Rel, &'a Expr, &'a Expr)> { + match op { + BinOp_::BiLt => Some((Rel::Lt, lhs, rhs)), + BinOp_::BiLe => Some((Rel::Le, lhs, rhs)), + BinOp_::BiGt => Some((Rel::Lt, rhs, lhs)), + BinOp_::BiGe => Some((Rel::Le, rhs, lhs)), + _ => None, + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 300cb8df042..7607ef31486 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -19,6 +19,7 @@ use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +pub mod comparisons; pub mod conf; mod hir; pub use self::hir::{SpanlessEq, SpanlessHash}; diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index d5849420e38..f94b4959287 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -7,13 +7,13 @@ fn main() { let zero: u32 = 0; let u8_max: u8 = 255; - (u8_max as u32) > 300; //~ERROR Because of the numeric bounds prior to casting, this expression is always false. + (u8_max as u32) > 300; //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always false (u8_max as u32) > 20; - (zero as i32) < -5; //~ERROR Because of the numeric bounds prior to casting, this expression is always false. + (zero as i32) < -5; //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false (zero as i32) < 10; - -5 < (zero as i32); //~ERROR Because of the numeric bounds prior to casting, this expression is always true. - 0 <= (zero as i32); //~ERROR Because of the numeric bounds prior to casting, this expression is always true. + -5 < (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always true + 0 <= (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always true 0 < (zero as i32); } -- cgit 1.4.1-3-g733a5 From d52d23d662683050939669609fd4257ef67cbb4c Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Mon, 28 Mar 2016 21:38:54 -0700 Subject: Erased numeric type to reduce branching --- src/types.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/types.rs b/src/types.rs index 5e4b3e673cd..e9b8e15303a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -873,21 +873,10 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { Ok(val) => { if let Integral(const_int) = val { - Some(match const_int { - I8(x) => FullInt::S(x as i64), - I16(x) => FullInt::S(x as i64), - I32(x) => FullInt::S(x as i64), - Isize(Is32(x)) => FullInt::S(x as i64), - Isize(Is64(x)) | - I64(x) => FullInt::S(x), + Some(match const_int.erase_type() { InferSigned(x) => FullInt::S(x as i64), - U8(x) => FullInt::U(x as u64), - U16(x) => FullInt::U(x as u64), - U32(x) => FullInt::U(x as u64), - Usize(Us32(x)) => FullInt::U(x as u64), - Usize(Us64(x)) | - U64(x) => FullInt::U(x), Infer(x) => FullInt::U(x as u64), + _ => unreachable!(), }) } else { None -- cgit 1.4.1-3-g733a5 From cf451d3bba438d465b847b0ade7960127cfe81c6 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Mon, 28 Mar 2016 21:44:18 -0700 Subject: Added > and >= tests for upcast comparisons --- tests/compile-fail/invalid_upcast_comparisons.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index f94b4959287..263e74e5f4a 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -16,4 +16,7 @@ fn main() { -5 < (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always true 0 <= (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always true 0 < (zero as i32); + + -5 > (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false + -5 >= (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always false } -- cgit 1.4.1-3-g733a5 From 90a61177298c9d73e2d3b842c199c36e1dfe77e3 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Mon, 28 Mar 2016 21:52:36 -0700 Subject: Reverted to manual implementation of PartialEq for FullInt --- src/types.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index e9b8e15303a..948e8fd063d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -799,7 +799,7 @@ impl LintPass for InvalidUpcastComparisons { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq)] enum FullInt { S(i64), U(u64), @@ -820,6 +820,12 @@ impl FullInt { } } +impl PartialEq for FullInt { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal + } +} + impl PartialOrd for FullInt { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(match (self, other) { -- cgit 1.4.1-3-g733a5 From d050d601fc1d27f486c8f5313330e75a0954a522 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Mon, 28 Mar 2016 22:06:57 -0700 Subject: Added eq and neq handling to invalid upcast comparisons --- src/types.rs | 9 ++++++++- src/utils/comparisons.rs | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 948e8fd063d..9adc2cc5680 100644 --- a/src/types.rs +++ b/src/types.rs @@ -679,6 +679,7 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs _ => return None, } } + Rel::Ne | Rel::Eq => return None, }) } @@ -914,14 +915,20 @@ fn upcast_comparison_bounds_err( if let Some(nlb) = lhs_bounds { if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { - if match rel { + if rel == Rel::Eq || rel == Rel::Ne { + if norm_rhs_val < nlb.0 || norm_rhs_val > nlb.0 { + err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne); + } + } else if match rel { Rel::Lt => if invert { norm_rhs_val < nlb.0 } else { nlb.1 < norm_rhs_val }, Rel::Le => if invert { norm_rhs_val <= nlb.0 } else { nlb.1 <= norm_rhs_val }, + Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, true) } else if match rel { Rel::Lt => if invert { norm_rhs_val >= nlb.1 } else { nlb.0 >= norm_rhs_val }, Rel::Le => if invert { norm_rhs_val > nlb.1 } else { nlb.0 > norm_rhs_val }, + Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, false) } diff --git a/src/utils/comparisons.rs b/src/utils/comparisons.rs index 2222c31a4f9..a9181b35b38 100644 --- a/src/utils/comparisons.rs +++ b/src/utils/comparisons.rs @@ -4,6 +4,8 @@ use rustc_front::hir::{BinOp_, Expr}; pub enum Rel { Lt, Le, + Eq, + Ne, } /// Put the expression in the form `lhs < rhs` or `lhs <= rhs`. @@ -14,6 +16,8 @@ pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) BinOp_::BiLe => Some((Rel::Le, lhs, rhs)), BinOp_::BiGt => Some((Rel::Lt, rhs, lhs)), BinOp_::BiGe => Some((Rel::Le, rhs, lhs)), + BinOp_::BiEq => Some((Rel::Eq, rhs, lhs)), + BinOp_::BiNe => Some((Rel::Ne, rhs, lhs)), _ => None, } } -- cgit 1.4.1-3-g733a5 From 44ab23703a1a6c4ff0e15a3b3e20284f6a9053fb Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Mon, 28 Mar 2016 22:08:58 -0700 Subject: Added tests for eq and neq invalid upcast comparisons --- tests/compile-fail/invalid_upcast_comparisons.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index 263e74e5f4a..6ccba368e62 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -19,4 +19,7 @@ fn main() { -5 > (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false -5 >= (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always false + + -5 == (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false + -5 != (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always true } -- cgit 1.4.1-3-g733a5 From 51e63a1ae2b39cf691340f557fdea6f5d50ace35 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 2 Apr 2016 15:43:58 +0200 Subject: Rustup PR #802 --- src/types.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/types.rs b/src/types.rs index 9adc2cc5680..7c893ef207c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,8 +2,6 @@ use reexport::*; use rustc::lint::*; use rustc::middle::def; use rustc::ty; -use rustc::middle::const_eval::ConstVal::Integral; -use rustc_const_eval; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc_front::util::{is_comparison_binop, binop_to_string}; @@ -11,7 +9,6 @@ use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; use utils::*; - /// Handles all the linting of funky types #[allow(missing_copy_implementations)] pub struct TypePass; @@ -845,7 +842,7 @@ impl Ord for FullInt { fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { - use rustc::middle::ty::TypeVariants::{TyInt, TyUint}; + use rustc::ty::TypeVariants::{TyInt, TyUint}; use syntax::ast::UintTy; use syntax::ast::IntTy; use std::*; @@ -874,15 +871,17 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( } fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { - use rustc::middle::const_eval::EvalHint::ExprTypeChecked; - use rustc_const_eval::*; + use rustc::middle::const_val::ConstVal::*; + use rustc_const_eval::EvalHint::ExprTypeChecked; + use rustc_const_eval::eval_const_expr_partial; + use rustc_const_math::ConstInt; - match const_eval::eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { Ok(val) => { if let Integral(const_int) = val { Some(match const_int.erase_type() { - InferSigned(x) => FullInt::S(x as i64), - Infer(x) => FullInt::U(x as u64), + ConstInt::InferSigned(x) => FullInt::S(x as i64), + ConstInt::Infer(x) => FullInt::U(x as u64), _ => unreachable!(), }) } else { -- cgit 1.4.1-3-g733a5 From eada860aa74f9b325342ac533c55593beabcc24c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 2 Apr 2016 15:51:28 +0200 Subject: Small fixes in #802 --- src/types.rs | 18 ++++++++---------- tests/compile-fail/invalid_upcast_comparisons.rs | 10 ++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/types.rs b/src/types.rs index 7c893ef207c..cc618453132 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,6 +5,7 @@ use rustc::ty; use rustc_front::hir::*; use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; use rustc_front::util::{is_comparison_binop, binop_to_string}; +use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; use utils::*; @@ -803,8 +804,6 @@ enum FullInt { U(u64), } -use std::cmp::Ordering; - impl FullInt { #[allow(cast_sign_loss)] fn cmp_s_u(s: i64, u: u64) -> Ordering { @@ -843,8 +842,7 @@ impl Ord for FullInt { fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { use rustc::ty::TypeVariants::{TyInt, TyUint}; - use syntax::ast::UintTy; - use syntax::ast::IntTy; + use syntax::ast::{IntTy, UintTy}; use std::*; if let ExprCast(ref cast_exp,_) = expr.node { @@ -912,21 +910,21 @@ fn upcast_comparison_bounds_err( lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { use utils::comparisons::*; - if let Some(nlb) = lhs_bounds { + if let Some((lb, ub)) = lhs_bounds { if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { if rel == Rel::Eq || rel == Rel::Ne { - if norm_rhs_val < nlb.0 || norm_rhs_val > nlb.0 { + if norm_rhs_val < lb || norm_rhs_val > ub { err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => if invert { norm_rhs_val < nlb.0 } else { nlb.1 < norm_rhs_val }, - Rel::Le => if invert { norm_rhs_val <= nlb.0 } else { nlb.1 <= norm_rhs_val }, + Rel::Lt => if invert { norm_rhs_val < lb } else { ub < norm_rhs_val }, + Rel::Le => if invert { norm_rhs_val <= lb } else { ub <= norm_rhs_val }, Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, true) } else if match rel { - Rel::Lt => if invert { norm_rhs_val >= nlb.1 } else { nlb.0 >= norm_rhs_val }, - Rel::Le => if invert { norm_rhs_val > nlb.1 } else { nlb.0 > norm_rhs_val }, + Rel::Lt => if invert { norm_rhs_val >= ub } else { lb >= norm_rhs_val }, + Rel::Le => if invert { norm_rhs_val > ub } else { lb > norm_rhs_val }, Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, false) diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index 6ccba368e62..443dd89aab9 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -19,7 +19,17 @@ fn main() { -5 > (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false -5 >= (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always false + 1337 == (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always false -5 == (zero as i32); //~ERROR because of the numeric bounds on `zero` prior to casting, this expression is always false -5 != (u8_max as i32); //~ERROR because of the numeric bounds on `u8_max` prior to casting, this expression is always true + + // Those are Ok: + 42 == (u8_max as i32); + 42 != (u8_max as i32); + 42 > (u8_max as i32); + (u8_max as i32) == 42; + (u8_max as i32) != 42; + (u8_max as i32) > 42; + (u8_max as i32) < 42; } -- cgit 1.4.1-3-g733a5 From f46e96405fe990ab15d51a8ee54d349f7e79e3b0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Apr 2016 17:16:53 +0200 Subject: Rustup to 1.9.0-nightly (5ab11d72c 2016-04-02) --- src/cyclomatic_complexity.rs | 16 ++++++++-------- src/escape.rs | 2 +- src/matches.rs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 3db080f970e..ca5acc6895f 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -149,14 +149,14 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { } #[cfg(feature="debugging")] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { - cx.sess().span_bug(span, - &format!("Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}. Please file a bug report.", - cc, - narms, - div, - shorts));; +fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { + span_bug!(span, + "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ + div = {}, shorts = {}. Please file a bug report.", + cc, + narms, + div, + shorts); } #[cfg(not(feature="debugging"))] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { diff --git a/src/escape.rs b/src/escape.rs index 51c4c7b6f5d..98500bf62f0 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) } } else { - self.cx.sess().span_bug(cmt.span, "Unknown adjusted AutoRef"); + span_bug!(cmt.span, "Unknown adjusted AutoRef"); } } else if LoanCause::AddrOf == loan_cause { // &x diff --git a/src/matches.rs b/src/matches.rs index 40013209e57..f1499f7fb94 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -415,8 +415,8 @@ fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, e MatchSource::Normal => format!("match {}{} {{ .. }}", op, expr_snippet), MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), - MatchSource::ForLoopDesugar => cx.sess().span_bug(span, "for loop desugared to match with &-patterns!"), - MatchSource::TryDesugar => cx.sess().span_bug(span, "`?` operator desugared to match with &-patterns!") + MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), + MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!") } } -- cgit 1.4.1-3-g733a5 From 67fb0e17c14ab42072b151c5b7af28bf338cd4e4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Apr 2016 17:17:55 +0200 Subject: Bump to 0.0.61 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index febe1ab9c19..dbdc233cc70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.60" +version = "0.0.61" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From ee907b73a4935140c547d3f794e31a13e4f6a75a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 4 Apr 2016 20:18:17 +0200 Subject: Fix false positive with `DOC_MARKDOWN` and `32MiB` --- src/doc.rs | 30 +++++++++++++++++++++++------- src/lib.rs | 2 +- src/utils/conf.rs | 2 ++ tests/compile-fail/doc.rs | 13 +++++++++++++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 9a6a86d4140..0ad238b5522 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -24,8 +24,16 @@ declare_lint! { "checks for the presence of `_`, `::` or camel-case outside ticks in documentation" } -#[derive(Copy,Clone)] -pub struct Doc; +#[derive(Clone)] +pub struct Doc { + valid_idents: Vec<String>, +} + +impl Doc { + pub fn new(valid_idents: Vec<String>) -> Self { + Doc { valid_idents: valid_idents } + } +} impl LintPass for Doc { fn get_lints(&self) -> LintArray { @@ -35,11 +43,11 @@ impl LintPass for Doc { impl EarlyLintPass for Doc { fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { - check_attrs(cx, &krate.attrs, krate.span); + check_attrs(cx, &self.valid_idents, &krate.attrs, krate.span); } fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { - check_attrs(cx, &item.attrs, item.span); + check_attrs(cx, &self.valid_idents, &item.attrs, item.span); } } @@ -73,7 +81,7 @@ fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { } } -pub fn check_attrs<'a>(cx: &EarlyContext, attrs: &'a [ast::Attribute], default_span: Span) { +pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute], default_span: Span) { let (doc, span) = collect_doc(attrs); let span = span.unwrap_or(default_span); @@ -100,15 +108,19 @@ pub fn check_attrs<'a>(cx: &EarlyContext, attrs: &'a [ast::Attribute], default_s } if !in_ticks { - check_word(cx, word, span); + check_word(cx, valid_idents, word, span); } } } -fn check_word(cx: &EarlyContext, word: &str, span: Span) { +fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span) { /// Checks if a string a camel-case, ie. contains at least two uppercase letter (`Clippy` is /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok). fn is_camel_case(s: &str) -> bool { + if s.starts_with(|c: char| c.is_digit(10)) { + return false; + } + let s = if s.ends_with('s') { &s[..s.len()-1] } else { @@ -134,6 +146,10 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { // Or even as in `_foo bar_` which is emphasized. let word = word.trim_matches(|c: char| !c.is_alphanumeric()); + if valid_idents.iter().any(|i| i == word) { + return; + } + if has_underscore(word) || word.contains("::") || is_camel_case(word) { span_lint(cx, DOC_MARKDOWN, span, &format!("you should put `{}` between ticks in the documentation", word)); } diff --git a/src/lib.rs b/src/lib.rs index f3fc453cf69..7ab48f46223 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -233,7 +233,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); - reg.register_early_lint_pass(box doc::Doc); + reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, diff --git a/src/utils/conf.rs b/src/utils/conf.rs index 2411e48997b..e11a6c0d9c7 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -149,6 +149,8 @@ define_Conf! { ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), + /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB"] => Vec<String>), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index a7b316e1f82..635b33be907 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -29,6 +29,18 @@ fn multiline_ticks() { fn test_emphasis() { } +/// This tests units. See also #835. +/// kiB MiB GiB TiB PiB EiB +/// kib Mib Gib Tib Pib Eib +/// kB MB GB TB PB EB +/// kb Mb Gb Tb Pb Eb +/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB +/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib +/// 32kB 32MB 32GB 32TB 32PB 32EB +/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb +fn test_units() { +} + /// This test has [a link with underscores][chunked-example] inside it. See #823. /// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues). /// @@ -40,4 +52,5 @@ fn main() { foo_bar(); multiline_ticks(); test_emphasis(); + test_units(); } -- cgit 1.4.1-3-g733a5 From c24ba91123b1a5413de1c9208c1fdf458e1ab8cd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 7 Apr 2016 17:46:48 +0200 Subject: Rustup to 1.9.0-nightly (bf5da36f1 2016-04-06) --- src/approx_const.rs | 2 +- src/array_indexing.rs | 2 +- src/attrs.rs | 2 +- src/bit_mask.rs | 7 +++---- src/blacklisted_name.rs | 2 +- src/block_in_if_condition.rs | 4 ++-- src/booleans.rs | 4 ++-- src/collapsible_if.rs | 2 +- src/consts.rs | 4 ++-- src/copies.rs | 2 +- src/cyclomatic_complexity.rs | 4 ++-- src/derive.rs | 2 +- src/drop_ref.rs | 2 +- src/entry.rs | 4 ++-- src/enum_clike.rs | 2 +- src/enum_glob_use.rs | 6 +++--- src/eq_op.rs | 5 ++--- src/escape.rs | 8 ++++---- src/eta_reduction.rs | 2 +- src/format.rs | 4 ++-- src/functions.rs | 6 +++--- src/identity_op.rs | 2 +- src/len_zero.rs | 8 +++++--- src/lib.rs | 2 -- src/lifetimes.rs | 6 +++--- src/loops.rs | 8 ++++---- src/map_clone.rs | 2 +- src/matches.rs | 2 +- src/methods.rs | 2 +- src/minmax.rs | 2 +- src/misc.rs | 11 +++++------ src/mut_mut.rs | 2 +- src/mut_reference.rs | 2 +- src/mutex_atomic.rs | 2 +- src/needless_bool.rs | 2 +- src/needless_update.rs | 2 +- src/new_without_default.rs | 4 ++-- src/no_effect.rs | 4 ++-- src/open_options.rs | 2 +- src/overflow_check_conditional.rs | 2 +- src/panic.rs | 2 +- src/print.rs | 4 ++-- src/ptr_arg.rs | 4 ++-- src/ranges.rs | 2 +- src/regex.rs | 3 +-- src/shadow.rs | 6 +++--- src/strings.rs | 2 +- src/swap.rs | 2 +- src/temporary_assignment.rs | 2 +- src/transmute.rs | 2 +- src/types.rs | 10 ++++------ src/unicode.rs | 2 +- src/unused_label.rs | 4 ++-- src/utils/comparisons.rs | 2 +- src/utils/hir.rs | 2 +- src/utils/mod.rs | 39 ++++++++++++++++++++++++--------------- src/vec.rs | 2 +- src/zero_div_zero.rs | 2 +- tests/compile-fail/transmute.rs | 26 +++++++++++++++----------- tests/consts.rs | 3 +-- 60 files changed, 135 insertions(+), 129 deletions(-) diff --git a/src/approx_const.rs b/src/approx_const.rs index 822fbd16c32..731f1a45d09 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use std::f64::consts as f64; use syntax::ast::{Lit, LitKind, FloatTy}; use utils::span_lint; diff --git a/src/array_indexing.rs b/src/array_indexing.rs index e5f54c128ef..ce5c85500bd 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -4,7 +4,7 @@ use rustc::ty::TyArray; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; use rustc_const_math::ConstInt; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::RangeLimits; use utils; diff --git a/src/attrs.rs b/src/attrs.rs index 363809c37bb..17b8a60bcb9 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -2,7 +2,7 @@ use reexport::*; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; use syntax::attr::*; diff --git a/src/bit_mask.rs b/src/bit_mask.rs index cbe601ba1b4..45f7e5bc938 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -1,8 +1,7 @@ +use rustc::hir::*; +use rustc::hir::def::{Def, PathResolution}; use rustc::lint::*; -use rustc::middle::def::{Def, PathResolution}; use rustc_const_eval::lookup_const_by_id; -use rustc_front::hir::*; -use rustc_front::util::is_comparison_binop; use syntax::ast::LitKind; use syntax::codemap::Span; use utils::span_lint; @@ -91,7 +90,7 @@ impl LintPass for BitMask { impl LateLintPass for BitMask { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { - if is_comparison_binop(cmp.node) { + if cmp.node.is_comparison() { fetch_int_literal(cx, right).map_or_else(|| { fetch_int_literal(cx, left).map_or((), |cmp_val| { check_compare(cx, diff --git a/src/blacklisted_name.rs b/src/blacklisted_name.rs index 25c0bac2c37..b515da000ee 100644 --- a/src/blacklisted_name.rs +++ b/src/blacklisted_name.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use utils::span_lint; /// **What it does:** This lints about usage of blacklisted names. diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 9cb11968abc..1a2123fe00a 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_expr}; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr}; use utils::*; /// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. diff --git a/src/booleans.rs b/src/booleans.rs index 37ad927ef92..213d12b42ef 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -1,6 +1,6 @@ use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; -use rustc_front::hir::*; -use rustc_front::intravisit::*; +use rustc::hir::*; +use rustc::hir::intravisit::*; use syntax::ast::{LitKind, DUMMY_NODE_ID}; use syntax::codemap::{DUMMY_SP, dummy_spanned}; use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 74397304eda..5674806b175 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -13,7 +13,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use std::borrow::Cow; use syntax::codemap::Spanned; diff --git a/src/consts.rs b/src/consts.rs index 73f2bc4653a..d30392e0586 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,10 +1,10 @@ #![allow(cast_possible_truncation)] use rustc::lint::LateContext; -use rustc::middle::def::{Def, PathResolution}; +use rustc::hir::def::{Def, PathResolution}; use rustc_const_eval::lookup_const_by_id; use rustc_const_math::{ConstInt, ConstUsize, ConstIsize}; -use rustc_front::hir::*; +use rustc::hir::*; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; diff --git a/src/copies.rs b/src/copies.rs index b8eb97cbeed..5b992cf38ae 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; use syntax::parse::token::InternedString; diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index ca5acc6895f..fcd89801ecc 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -3,8 +3,8 @@ use rustc::lint::*; use rustc::cfg::CFG; use rustc::ty; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_expr}; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr}; use syntax::ast::Attribute; use syntax::attr::*; use syntax::codemap::Span; diff --git a/src/derive.rs b/src/derive.rs index ab4f73eafc0..593118bef84 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -3,7 +3,7 @@ use rustc::ty::subst::Subst; use rustc::ty::TypeVariants; use rustc::ty::fast_reject::simplify_type; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::{Attribute, MetaItemKind}; use syntax::codemap::Span; use utils::{CLONE_TRAIT_PATH, HASH_PATH}; diff --git a/src/drop_ref.rs b/src/drop_ref.rs index 7536fb1b63b..3448e05dbac 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::Span; use utils::DROP_PATH; use utils::{match_def_path, span_note_and_lint}; diff --git a/src/entry.rs b/src/entry.rs index 8a4cf37c0ac..934400bc122 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,6 +1,6 @@ use rustc::lint::*; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_expr, walk_block}; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr, walk_block}; use syntax::codemap::Span; use utils::SpanlessEq; use utils::{BTREEMAP_PATH, HASHMAP_PATH}; diff --git a/src/enum_clike.rs b/src/enum_clike.rs index 0e2a7a5304f..e3e8f1e5eb6 100644 --- a/src/enum_clike.rs +++ b/src/enum_clike.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc_const_math::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::attr::*; use utils::span_lint; diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index 5b29f84ef51..671b9bb141c 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -1,10 +1,10 @@ //! lint on `use`ing all variants of an enum -use rustc::front::map::Node::NodeItem; +use rustc::hir::*; +use rustc::hir::def::Def; +use rustc::hir::map::Node::NodeItem; use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; -use rustc::middle::def::Def; use rustc::middle::cstore::DefLike; -use rustc_front::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; diff --git a/src/eq_op.rs b/src/eq_op.rs index 09ac6325f96..fb06639853c 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -1,6 +1,5 @@ +use rustc::hir::*; use rustc::lint::*; -use rustc_front::hir::*; -use rustc_front::util as ast_util; use utils::{SpanlessEq, span_lint}; /// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, @@ -34,7 +33,7 @@ impl LateLintPass for EqOp { span_lint(cx, EQ_OP, e.span, - &format!("equal expressions as operands to `{}`", ast_util::binop_to_string(op.node))); + &format!("equal expressions as operands to `{}`", op.node.as_str())); } } } diff --git a/src/escape.rs b/src/escape.rs index 98500bf62f0..fa235244884 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,14 +1,14 @@ -use rustc::front::map::Node::{NodeExpr, NodeStmt}; +use rustc::hir::*; +use rustc::hir::intravisit as visit; +use rustc::hir::map::Node::{NodeExpr, NodeStmt}; +use rustc::infer; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; -use rustc::infer; use rustc::middle::mem_categorization::{cmt, Categorization}; use rustc::traits::ProjectionMode; use rustc::ty::adjustment::AutoAdjustment; use rustc::ty; use rustc::util::nodemap::NodeSet; -use rustc_front::hir::*; -use rustc_front::intravisit as visit; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index c080968ef84..4519acc39de 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use utils::{snippet_opt, span_lint_and_then, is_adjusted}; #[allow(missing_copy_implementations)] diff --git a/src/format.rs b/src/format.rs index 300b3d17b39..0a349c98e07 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,7 +1,7 @@ -use rustc::front::map::Node::NodeItem; +use rustc::hir::map::Node::NodeItem; use rustc::lint::*; use rustc::ty::TypeVariants; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::LitKind; use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH, STRING_PATH}; use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty}; diff --git a/src/functions.rs b/src/functions.rs index 5ac5aae51a4..ed04473abc3 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -1,6 +1,6 @@ use rustc::lint::*; -use rustc_front::hir; -use rustc_front::intravisit; +use rustc::hir; +use rustc::hir::intravisit; use syntax::ast; use syntax::codemap::Span; use utils::span_lint; @@ -45,7 +45,7 @@ impl LintPass for Functions { impl LateLintPass for Functions { fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) { - use rustc::front::map::Node::*; + use rustc::hir::map::Node::*; if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { match item.node { diff --git a/src/identity_op.rs b/src/identity_op.rs index c25047b87b4..4c1f01b7385 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -1,6 +1,6 @@ use consts::{constant_simple, Constant}; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::Span; use utils::{span_lint, snippet, in_macro}; use rustc_const_math::ConstInt; diff --git a/src/len_zero.rs b/src/len_zero.rs index 1a097820e1e..3a376d91c92 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -1,7 +1,7 @@ use rustc::lint::*; -use rustc::middle::def_id::DefId; +use rustc::hir::def_id::DefId; use rustc::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; use syntax::ptr::P; @@ -111,6 +111,8 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { for i in impl_items { if is_named_self(i, "len") { + let ty = cx.tcx.node_id_to_type(item.id); + let s = i.span; span_lint(cx, LEN_WITHOUT_IS_EMPTY, @@ -121,7 +123,7 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { }, &format!("item `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ Consider adding one", - item.name)); + ty)); return; } } diff --git a/src/lib.rs b/src/lib.rs index 7ab48f46223..1b48c7b3dbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +19,6 @@ fn main() { extern crate syntax; #[macro_use] extern crate rustc; -#[macro_use] -extern crate rustc_front; extern crate toml; diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 72fdba07d32..ad42a8568e6 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -1,8 +1,8 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::def::Def; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; use std::collections::{HashSet, HashMap}; use syntax::codemap::Span; use utils::{in_external_macro, span_lint}; diff --git a/src/loops.rs b/src/loops.rs index 20d0fc026d1..4e7e4bf117d 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -1,14 +1,14 @@ use reexport::*; -use rustc::front::map::Node::NodeBlock; +use rustc::hir::*; +use rustc::hir::def::Def; +use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; +use rustc::hir::map::Node::NodeBlock; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::middle::def::Def; use rustc::middle::region::CodeExtent; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use std::borrow::Cow; use std::collections::HashMap; use syntax::ast; diff --git a/src/map_clone.rs b/src/map_clone.rs index 4eac4dc6113..eeb3aab4655 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use utils::{CLONE_PATH, OPTION_PATH}; use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; diff --git a/src/matches.rs b/src/matches.rs index f1499f7fb94..d82dad5b065 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,10 +1,10 @@ +use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; use rustc_const_math::ConstInt; -use rustc_front::hir::*; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; diff --git a/src/methods.rs b/src/methods.rs index 646cd319a0c..3fcd472faf5 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,3 +1,4 @@ +use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::CrateStore; @@ -5,7 +6,6 @@ use rustc::ty::subst::{Subst, TypeSpace}; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; -use rustc_front::hir::*; use std::borrow::Cow; use std::fmt; use syntax::codemap::Span; diff --git a/src/minmax.rs b/src/minmax.rs index 0560bf15604..67299bac998 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -1,6 +1,6 @@ use consts::{Constant, constant_simple}; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use std::cmp::{PartialOrd, Ordering}; use syntax::ptr::P; use utils::{match_def_path, span_lint}; diff --git a/src/misc.rs b/src/misc.rs index a6cfec276e5..654e6244c1b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,12 +1,11 @@ use reexport::*; +use rustc::hir::*; +use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; -use rustc_front::hir::*; -use rustc_front::intravisit::FnKind; -use rustc_front::util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned, ExpnFormat}; use syntax::ptr::P; use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; @@ -105,7 +104,7 @@ impl LintPass for CmpNan { impl LateLintPass for CmpNan { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if is_comparison_binop(cmp.node) { + if cmp.node.is_comparison() { if let ExprPath(_, ref path) = left.node { check_nan(cx, path, expr.span); } @@ -170,7 +169,7 @@ impl LateLintPass for FloatCmp { &format!("{}-comparison of f32 or f64 detected. Consider changing this to `({} - {}).abs() < \ epsilon` for some suitable value of epsilon. \ std::f32::EPSILON and std::f64::EPSILON are available.", - binop_to_string(op), + op.as_str(), snippet(cx, left.span, ".."), snippet(cx, right.span, ".."))); } @@ -217,7 +216,7 @@ impl LintPass for CmpOwned { impl LateLintPass for CmpOwned { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if is_comparison_binop(cmp.node) { + if cmp.node.is_comparison() { check_to_owned(cx, left, right, true, cmp.span); check_to_owned(cx, right, left, false, cmp.span) } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index a5ed233241d..65e2c3a46a9 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty::{TypeAndMut, TyRef}; -use rustc_front::hir::*; +use rustc::hir::*; use utils::{in_external_macro, span_lint}; /// **What it does:** This lint checks for instances of `mut mut` references. diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 95ed1092eb5..d74c2c41f23 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ptr::P; use utils::span_lint; diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index 0593438cfc1..bae1ae38168 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -5,7 +5,7 @@ use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; use rustc::ty::subst::ParamSpace; use rustc::ty; -use rustc_front::hir::Expr; +use rustc::hir::Expr; use syntax::ast; use utils::{span_lint, MUTEX_PATH, match_type}; diff --git a/src/needless_bool.rs b/src/needless_bool.rs index ab5a1e26b20..07da57c684b 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; use utils::{span_lint, span_lint_and_then, snippet, snippet_opt}; diff --git a/src/needless_update.rs b/src/needless_update.rs index d25f66ca434..d8ae9dc3471 100644 --- a/src/needless_update.rs +++ b/src/needless_update.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::TyStruct; -use rustc_front::hir::{Expr, ExprStruct}; +use rustc::hir::{Expr, ExprStruct}; use utils::span_lint; /// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway. diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 395d69138e1..2bcc345fd60 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -1,6 +1,6 @@ use rustc::lint::*; -use rustc_front::hir; -use rustc_front::intravisit::FnKind; +use rustc::hir; +use rustc::hir::intravisit::FnKind; use syntax::ast; use syntax::codemap::Span; use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint, diff --git a/src/no_effect.rs b/src/no_effect.rs index 59f7be94c23..afb49376b3f 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::middle::def::Def; -use rustc_front::hir::{Expr, Expr_, Stmt, StmtSemi}; +use rustc::hir::def::Def; +use rustc::hir::{Expr, Expr_, Stmt, StmtSemi}; use utils::{in_macro, span_lint}; /// **What it does:** This lint checks for statements which have no effect. diff --git a/src/open_options.rs b/src/open_options.rs index e3f61afcf1c..3c1e69a40ea 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::{Expr, ExprMethodCall, ExprLit}; +use rustc::hir::{Expr, ExprMethodCall, ExprLit}; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index 823cb696901..627028ad462 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use utils::{span_lint}; /// **What it does:** This lint finds classic underflow / overflow checks. diff --git a/src/panic.rs b/src/panic.rs index 8b9bf9f1f19..ab03181c2dd 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::LitKind; use utils::{span_lint, is_direct_expn_of, match_path, BEGIN_UNWIND}; diff --git a/src/print.rs b/src/print.rs index ffe20d13cea..a298d162c05 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,6 +1,6 @@ -use rustc::front::map::Node::{NodeItem, NodeImplItem}; +use rustc::hir::map::Node::{NodeItem, NodeImplItem}; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use utils::{FMT_ARGUMENTV1_NEW_PATH, DEBUG_FMT_METHOD_PATH, IO_PRINT_PATH}; use utils::{is_expn_of, match_path, span_lint}; diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 6498db66e13..8720424da86 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -1,9 +1,9 @@ //! Checks for usage of `&Vec[_]` and `&String`. -use rustc::front::map::NodeItem; +use rustc::hir::map::NodeItem; use rustc::lint::*; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::NodeId; use utils::{STRING_PATH, VEC_PATH}; use utils::{span_lint, match_type}; diff --git a/src/ranges.rs b/src/ranges.rs index 23bd3d1103c..c2555da1d0b 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::Spanned; use utils::{is_integer_literal, match_type, snippet, span_lint, unsugar_range, UnsugaredRange}; diff --git a/src/regex.rs b/src/regex.rs index 46ee7776d66..f24639312ed 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,15 +1,14 @@ use regex_syntax; +use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; -use rustc_front::hir::*; use std::collections::HashSet; use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; - use utils::{is_expn_of, match_path, match_type, REGEX_NEW_PATH, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. diff --git a/src/shadow.rs b/src/shadow.rs index baf5c9b8872..928d447974a 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -1,8 +1,8 @@ use reexport::*; use rustc::lint::*; -use rustc::middle::def::Def; -use rustc_front::hir::*; -use rustc_front::intravisit::{Visitor, FnKind}; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, FnKind}; use std::ops::Deref; use syntax::codemap::Span; use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; diff --git a/src/strings.rs b/src/strings.rs index 9f68175b202..da1456671fd 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -4,7 +4,7 @@ //! disable the subsumed lint unless it has a higher level use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::Spanned; use utils::STRING_PATH; use utils::SpanlessEq; diff --git a/src/swap.rs b/src/swap.rs index 6d7212233fb..29db0da5cf9 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::mk_sp; use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index c945fd7148e..44796410458 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; +use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; use utils::is_adjusted; use utils::span_lint; diff --git a/src/transmute.rs b/src/transmute.rs index ef049ba4a6d..41b92ca6113 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; use rustc::ty; -use rustc_front::hir::*; +use rustc::hir::*; use utils::TRANSMUTE_PATH; use utils::{match_def_path, snippet_opt, span_lint, span_lint_and_then}; diff --git a/src/types.rs b/src/types.rs index cc618453132..281af90736b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,10 +1,8 @@ use reexport::*; +use rustc::hir::*; +use rustc::hir::intravisit::{FnKind, Visitor, walk_ty}; use rustc::lint::*; -use rustc::middle::def; use rustc::ty; -use rustc_front::hir::*; -use rustc_front::intravisit::{FnKind, Visitor, walk_ty}; -use rustc_front::util::{is_comparison_binop, binop_to_string}; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; @@ -162,7 +160,7 @@ impl LateLintPass for UnitCmp { if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; let sty = &cx.tcx.expr_ty(left).sty; - if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) { + if *sty == ty::TyTuple(vec![]) && op.is_comparison() { let result = match op { BiEq | BiLe | BiGe => "true", _ => "false", @@ -171,7 +169,7 @@ impl LateLintPass for UnitCmp { UNIT_CMP, expr.span, &format!("{}-comparison of unit values detected. This will always be {}", - binop_to_string(op), + op.as_str(), result)); } } diff --git a/src/unicode.rs b/src/unicode.rs index 0f21822ea08..26521017ee5 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; diff --git a/src/unused_label.rs b/src/unused_label.rs index f2ecad7cc82..f6ff3c3d4b4 100644 --- a/src/unused_label.rs +++ b/src/unused_label.rs @@ -1,6 +1,6 @@ use rustc::lint::*; -use rustc_front::hir; -use rustc_front::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; +use rustc::hir; +use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; use std::collections::HashMap; use syntax::ast; use syntax::codemap::Span; diff --git a/src/utils/comparisons.rs b/src/utils/comparisons.rs index a9181b35b38..b890a363fb7 100644 --- a/src/utils/comparisons.rs +++ b/src/utils/comparisons.rs @@ -1,4 +1,4 @@ -use rustc_front::hir::{BinOp_, Expr}; +use rustc::hir::{BinOp_, Expr}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum Rel { diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 0659e26d0f2..f6fa2176941 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -1,6 +1,6 @@ use consts::constant; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use std::hash::{Hash, Hasher, SipHasher}; use syntax::ast::Name; use syntax::ptr::P; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 7607ef31486..761d5d3df9d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,15 +1,15 @@ use reexport::*; -use rustc::front::map::Node; +use rustc::hir::*; +use rustc::hir::def_id::DefId; +use rustc::hir::map::Node; +use rustc::infer; use rustc::lint::{LintContext, LateContext, Level, Lint}; -use rustc::middle::def_id::DefId; -use rustc::traits; +use rustc::middle::cstore; +use rustc::session::Session; use rustc::traits::ProjectionMode; -use rustc::middle::{cstore, def}; -use rustc::infer; -use rustc::ty; +use rustc::traits; use rustc::ty::subst::Subst; -use rustc::session::Session; -use rustc_front::hir::*; +use rustc::ty; use std::borrow::Cow; use std::mem; use std::ops::{Deref, DerefMut}; @@ -56,7 +56,7 @@ pub const RANGE_TO_PATH: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const TRANSMUTE_PATH: [&'static str; 3] = ["core", "intrinsics", "transmute"]; +pub const TRANSMUTE_PATH: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const BOX_PATH: [&'static str; 3] = ["std", "boxed", "Box"]; @@ -157,13 +157,22 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// match_def_path(cx, id, &["core", "option", "Option"]) /// ``` pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - cx.tcx.with_path(def_id, |iter| { - let mut len = 0; + let krate = &cx.tcx.crate_name(def_id.krate); + if krate != &path[0] { + return false; + } - iter.inspect(|_| len += 1) - .zip(path) - .all(|(nm, p)| nm.name().as_str() == *p) && len == path.len() - }) + let path = &path[1..]; + let other = cx.tcx.def_path(def_id).data; + + if other.len() != path.len() { + return false; + } + + other.into_iter() + .map(|e| e.data) + .zip(path) + .all(|(nm, p)| nm.as_interned_str() == *p) } /// Check if type is struct or enum type with given def path. diff --git a/src/vec.rs b/src/vec.rs index 412ebf396dd..d27a3320d96 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::ty::TypeVariants; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::codemap::Span; use syntax::ptr::P; use utils::VEC_FROM_ELEM_PATH; diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs index f58b0e695a9..902d84d4dd3 100644 --- a/src/zero_div_zero.rs +++ b/src/zero_div_zero.rs @@ -1,6 +1,6 @@ use consts::{Constant, constant_simple, FloatWidth}; use rustc::lint::*; -use rustc_front::hir::*; +use rustc::hir::*; use utils::span_help_and_lint; /// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index cd86281d8f2..ad97410cf65 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -6,6 +6,10 @@ extern crate core; use std::mem::transmute as my_transmute; use std::vec::Vec as MyVec; +fn my_int() -> usize { + 42 +} + fn my_vec() -> MyVec<i32> { vec![] } @@ -86,22 +90,22 @@ fn useless() { #[deny(crosspointer_transmute)] fn crosspointer() { - let mut vec: Vec<i32> = vec![]; - let vec_const_ptr: *const Vec<i32> = &vec as *const Vec<i32>; - let vec_mut_ptr: *mut Vec<i32> = &mut vec as *mut Vec<i32>; + let mut int: usize = 0; + let int_const_ptr: *const usize = &int as *const usize; + let int_mut_ptr: *mut usize = &mut int as *mut usize; unsafe { - let _: Vec<i32> = core::intrinsics::transmute(vec_const_ptr); - //~^ ERROR transmute from a type (`*const std::vec::Vec<i32>`) to the type that it points to (`std::vec::Vec<i32>`) + let _: usize = core::intrinsics::transmute(int_const_ptr); + //~^ ERROR transmute from a type (`*const usize`) to the type that it points to (`usize`) - let _: Vec<i32> = core::intrinsics::transmute(vec_mut_ptr); - //~^ ERROR transmute from a type (`*mut std::vec::Vec<i32>`) to the type that it points to (`std::vec::Vec<i32>`) + let _: usize = core::intrinsics::transmute(int_mut_ptr); + //~^ ERROR transmute from a type (`*mut usize`) to the type that it points to (`usize`) - let _: *const Vec<i32> = core::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to a pointer to that type (`*const std::vec::Vec<i32>`) + let _: *const usize = core::intrinsics::transmute(my_int()); + //~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*const usize`) - let _: *mut Vec<i32> = core::intrinsics::transmute(my_vec()); - //~^ ERROR transmute from a type (`std::vec::Vec<i32>`) to a pointer to that type (`*mut std::vec::Vec<i32>`) + let _: *mut usize = core::intrinsics::transmute(my_int()); + //~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*mut usize`) } } diff --git a/tests/consts.rs b/tests/consts.rs index b7b2f6a3f83..4b3aba3f6be 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -5,12 +5,11 @@ extern crate clippy; extern crate rustc; extern crate rustc_const_eval; extern crate rustc_const_math; -extern crate rustc_front; extern crate syntax; use clippy::consts::{constant_simple, Constant, FloatWidth}; use rustc_const_math::ConstInt; -use rustc_front::hir::*; +use rustc::hir::*; use syntax::ast::{LitIntType, LitKind, StrStyle}; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; use syntax::parse::token::InternedString; -- cgit 1.4.1-3-g733a5 From 76a831c60ff989446016ad0cfc519471661811f1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 7 Apr 2016 18:35:51 +0200 Subject: Bump to 0.0.62 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dbdc233cc70..97a3b4b84cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.61" +version = "0.0.62" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 532446d3f8cc5bb1c01d4cdcced86ef1f3529897 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 8 Apr 2016 17:31:47 +0200 Subject: Rustup to 1.9.0-nightly (7979dd608 2016-04-07) --- src/derive.rs | 65 +++++++++++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/src/derive.rs b/src/derive.rs index 593118bef84..4b8446e6201 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use rustc::ty::subst::Subst; use rustc::ty::TypeVariants; -use rustc::ty::fast_reject::simplify_type; use rustc::ty; use rustc::hir::*; use syntax::ast::{Attribute, MetaItemKind}; @@ -87,52 +86,44 @@ impl LateLintPass for Derive { } /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty, hash_is_automatically_derived: bool) { +fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { if_let_chain! {[ match_path(&trait_ref.path, &HASH_PATH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() ], { let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); - cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id); - let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1; - // Look for the PartialEq implementations for `ty` - if_let_chain! {[ - let Some(simpl_ty) = simplify_type(cx.tcx, ty, false), - let Some(impl_ids) = peq_impls.get(&simpl_ty) - ], { - for &impl_id in impl_ids { - let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); + peq_trait_def.for_each_relevant_impl(&cx.tcx, ty, |impl_id| { + let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); - if peq_is_automatically_derived == hash_is_automatically_derived { - return; - } + if peq_is_automatically_derived == hash_is_automatically_derived { + return; + } - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - - // Only care about `impl PartialEq<Foo> for Foo` - if trait_ref.input_types()[0] == ty { - let mess = if peq_is_automatically_derived { - "you are implementing `Hash` explicitly but have derived `PartialEq`" - } else { - "you are deriving `Hash` but have implemented `PartialEq` explicitly" - }; - - span_lint_and_then( - cx, DERIVE_HASH_XOR_EQ, span, - mess, - |db| { - if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { - db.span_note( - cx.tcx.map.span(node_id), - "`PartialEq` implemented here" - ); - } - }); - } + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialEq<Foo> for Foo` + if trait_ref.input_types()[0] == ty { + let mess = if peq_is_automatically_derived { + "you are implementing `Hash` explicitly but have derived `PartialEq`" + } else { + "you are deriving `Hash` but have implemented `PartialEq` explicitly" + }; + + span_lint_and_then( + cx, DERIVE_HASH_XOR_EQ, span, + mess, + |db| { + if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { + db.span_note( + cx.tcx.map.span(node_id), + "`PartialEq` implemented here" + ); + } + }); } - }} + }); }} } -- cgit 1.4.1-3-g733a5 From f665b5f1c2f780572082644118ea1897301fc960 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 8 Apr 2016 17:32:04 +0200 Subject: Bump to 0.0.63 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 97a3b4b84cc..b55ab8d2271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.62" +version = "0.0.63" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From a137ac92ac9f195cb64da7c84a67c816c5e3733a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 11 Apr 2016 21:37:21 +0200 Subject: Add a changelog file --- CHANGELOG.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000000..07750501b48 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,84 @@ +# Change Log +All notable changes to this project will be documented in this file. + +## 0.0.63 — 2016-04-08 +* Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)* + +## 0.0.62 — 2016-04-07 +* Rustup to *rustc 1.9.0-nightly (bf5da36f1 2016-04-06)* + +## 0.0.61 — 2016-04-03 +* Rustup to *rustc 1.9.0-nightly (5ab11d72c 2016-04-02)* +* New lint: [`invalid_upcast_comparisons`] + +## 0.0.60 — 2016-04-01 +* Rustup to *rustc 1.9.0-nightly (e1195c24b 2016-03-31)* + +## 0.0.59 — 2016-03-31 +* Rustup to *rustc 1.9.0-nightly (30a3849f2 2016-03-30)* +* New lints: [`logic_bug`], [`nonminimal_bool`] +* Fixed: [`match_same_arms`] now ignores arms with guards +* Improved: [`useless_vec`] now warns on `for … in vec![…]` + +## 0.0.58 — 2016-03-27 +* Rustup to *rustc 1.9.0-nightly (d5a91e695 2016-03-26)* +* New lint: [`doc_markdown`] + +## 0.0.57 — 2016-03-27 +* Update to *rustc 1.9.0-nightly (a1e29daf1 2016-03-25)* +* Deprecated lints: [`str_to_string`], [`string_to_string`], [`unstable_as_slice`], [`unstable_as_mut_slice`] +* New lint: [`crosspointer_transmute`] + +## 0.0.56 — 2016-03-23 +* Update to *rustc 1.9.0-nightly (0dcc413e4 2016-03-22)* +* New lint: [`non_expressive_names`] + +## 0.0.55 — 2016-03-21 +* Update to *rustc 1.9.0-nightly (02310fd31 2016-03-19)* + +## 0.0.54 — 2016-03-16 +* Update to *rustc 1.9.0-nightly (c66d2380a 2016-03-15)* + +## 0.0.53 — 2016-03-15 +* Add a [configuration file] + +## ~~0.0.52~~ + +## 0.0.51 — 2016-03-13 +* Add `str` to types considered by `len_zero` +* New lints: [`indexing_slicing`] + +## 0.0.50 — 2016-03-11 +* Update to *rustc 1.9.0-nightly (c9629d61c 2016-03-10)* + +## 0.0.49 — 2016-03-09 +* Update to *rustc 1.9.0-nightly (eabfc160f 2016-03-08)* +* New lints: [`overflow_check_conditional`], [`unused_label`], [`new_without_default`] + +## 0.0.48 — 2016-03-07 +* Fixed: ICE in [`needless_range_loop`] with globals + +## 0.0.47 — 2016-03-07 +* Update to *rustc 1.9.0-nightly (998a6720b 2016-03-07)* +* New lint: [`redundant_closure_call`] + +[configuration file]: ./rust-clippy#configuration + +[`crosspointer_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute +[`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown +[`indexing_slicing`]: https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing +[`invalid_upcast_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons +[`logic_bug`]: https://github.com/Manishearth/rust-clippy/wiki#logic_bug +[`match_same_arms`]: https://github.com/Manishearth/rust-clippy/wiki#match_same_arms +[`needless_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop +[`new_without_default`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default +[`non_expressive_names`]: https://github.com/Manishearth/rust-clippy/wiki#non_expressive_names +[`nonminimal_bool`]: https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool +[`overflow_check_conditional`]: https://github.com/Manishearth/rust-clippy/wiki#overflow_check_conditional +[`redundant_closure_call`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call +[`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string +[`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string +[`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice +[`unstable_as_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice +[`unused_label`]: https://github.com/Manishearth/rust-clippy/wiki#unused_label +[`useless_vec`]: https://github.com/Manishearth/rust-clippy/wiki#useless_vec -- cgit 1.4.1-3-g733a5 From 9c4ae9295dbcf16a1cabf351149df0d1c0d100ea Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 11 Apr 2016 23:23:49 +0200 Subject: Markdownify more doc --- src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/methods.rs b/src/methods.rs index 3fcd472faf5..45f87fba9dd 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -805,7 +805,7 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { None } -/// This checks whether a given type is known to implement Debug. +/// This checks whether a given type is known to implement `Debug`. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { match cx.tcx.lang_items.debug_trait() { Some(debug) => implements_trait(cx, ty, debug, Vec::new()), -- cgit 1.4.1-3-g733a5 From 29c058f0af1306e6c7d7a6b633a758d36dc89fef Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Mon, 11 Apr 2016 23:59:52 +0200 Subject: add a note of rust-lang/rust/#31439 to the wiki text --- src/returns.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/returns.rs b/src/returns.rs index 43ea3780173..bb94b59df7d 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -9,7 +9,7 @@ use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_exter /// /// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty. /// -/// **Known problems:** None +/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. /// /// **Example:** `fn foo(x: usize) { return x; }` declare_lint! { @@ -21,7 +21,7 @@ declare_lint! { /// /// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. /// -/// **Known problems:** None +/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. /// /// **Example:** `{ let x = ..; x }` declare_lint! { -- cgit 1.4.1-3-g733a5 From 6c0a486e8b3f9801a408b89946cb6c8245a88061 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 11 Apr 2016 23:22:30 +0200 Subject: Fix FP with `DOC_MARKDOWN` and reference links --- src/doc.rs | 101 ++++++++++++++++++++++++++++++++++++++-------- tests/compile-fail/doc.rs | 11 +++-- 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 0ad238b5522..da87b104341 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -84,7 +84,32 @@ fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute], default_span: Span) { let (doc, span) = collect_doc(attrs); let span = span.unwrap_or(default_span); + check_doc(cx, valid_idents, &doc, span); +} + +macro_rules! jump_to { + // Get the next character’s first byte UTF-8 friendlyly. + (@next_char, $chars: expr, $len: expr) => {{ + if let Some(&(pos, _)) = $chars.peek() { + pos + } else { + $len + } + }}; + + // Jump to the next `$c`. If no such character is found, give up. + ($chars: expr, $c: expr, $len: expr) => {{ + if $chars.find(|&(_, c)| c == $c).is_some() { + jump_to!(@next_char, $chars, $len) + } + else { + return; + } + }}; +} +#[allow(while_let_loop)] // #362 +pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) { // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. // There really is no markdown specification that would disambiguate this properly. This is // what GitHub and Rustdoc do: @@ -96,19 +121,68 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a // (_baz_) → (<em>baz</em>) // foo _ bar _ baz → foo _ bar _ baz - let mut in_ticks = false; - for word in doc.split_whitespace() { - let ticks = word.bytes().filter(|&b| b == b'`').count(); - - if ticks == 2 { // likely to be “`foo`” - continue; - } else if ticks % 2 == 1 { - in_ticks = !in_ticks; - continue; // let’s assume no one will ever write something like “`foo`_bar” + /// Character that can appear in a word + fn is_word_char(c: char) -> bool { + match c { + t if t.is_alphanumeric() => true, + ':' | '_' => true, + _ => false, } + } - if !in_ticks { - check_word(cx, valid_idents, word, span); + let len = doc.len(); + let mut chars = doc.char_indices().peekable(); + let mut current_word_begin = 0; + loop { + match chars.next() { + Some((_, c)) => { + match c { + c if c.is_whitespace() => { + current_word_begin = jump_to!(@next_char, chars, len); + } + '`' => { + current_word_begin = jump_to!(chars, '`', len); + }, + '[' => { + let end = jump_to!(chars, ']', len); + let link_text = &doc[current_word_begin+1..end]; + + match chars.peek() { + Some(&(_, c)) => { + // Trying to parse a link. Let’s ignore the link. + + // FIXME: how does markdown handles such link? + // https://en.wikipedia.org/w/index.php?title=) + match c { + '(' => { // inline link + current_word_begin = jump_to!(chars, ')', len); + check_doc(cx, valid_idents, link_text, span); + } + '[' => { // reference link + current_word_begin = jump_to!(chars, ']', len); + check_doc(cx, valid_idents, link_text, span); + } + ':' => { // reference link + current_word_begin = jump_to!(chars, '\n', len); + } + _ => continue, + } + } + None => return, + } + } + _ => { + let end = match chars.find(|&(_, c)| !is_word_char(c)) { + Some((end, _)) => end, + None => len, + }; + + check_word(cx, valid_idents, &doc[current_word_begin..end], span); + current_word_begin = jump_to!(@next_char, chars, len); + } + } + } + None => break, } } } @@ -136,11 +210,6 @@ fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span s != "_" && !s.contains("\\_") && s.contains('_') } - // Something with a `/` might be a link, don’t warn (see #823): - if word.contains('/') { - return; - } - // Trim punctuation as in `some comment (see foo::bar).` // ^^ // Or even as in `_foo bar_` which is emphasized. diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 635b33be907..81250b5485a 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -41,14 +41,19 @@ fn test_emphasis() { fn test_units() { } -/// This test has [a link with underscores][chunked-example] inside it. See #823. -/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues). +/// This test has [a link_with_underscores][chunked-example] inside it. See #823. +/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues). And here is another [inline link][inline_link]. /// -/// [chunked-example]: http://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example +/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example +/// [inline_link]: https://foobar /// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and /// `multiline_ticks` functions. +/// +/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , fn main() { +//~^ ERROR: you should put `link_with_underscores` between ticks foo_bar(); multiline_ticks(); test_emphasis(); -- cgit 1.4.1-3-g733a5 From fe6e8dac3592b3e73120ff5ce9569c0f2323dd74 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Apr 2016 16:02:44 +0200 Subject: More tests in `DOC_MARKDOWN` --- src/doc.rs | 5 ++++- src/utils/conf.rs | 2 +- tests/compile-fail/doc.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index da87b104341..f27b4d862f1 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -165,7 +165,10 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp ':' => { // reference link current_word_begin = jump_to!(chars, '\n', len); } - _ => continue, + _ => { // automatic reference link + current_word_begin = jump_to!(@next_char, chars, len); + check_doc(cx, valid_idents, link_text, span); + } } } None => return, diff --git a/src/utils/conf.rs b/src/utils/conf.rs index e11a6c0d9c7..74a68d2d730 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -150,7 +150,7 @@ define_Conf! { /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks - ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB"] => Vec<String>), + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub"] => Vec<String>), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 81250b5485a..16e460e5055 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -9,10 +9,12 @@ /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun /// which should be reported only once despite being __doubly bad__. +/// be_sure_we_got_to_the_end_of_it fn foo_bar() { //~^ ERROR: you should put `foo_bar` between ticks //~| ERROR: you should put `foo::bar` between ticks //~| ERROR: you should put `Foo::some_fun` between ticks +//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// That one tests multiline ticks. @@ -20,13 +22,17 @@ fn foo_bar() { /// foo_bar FOO_BAR /// _foo bar_ /// ``` +/// be_sure_we_got_to_the_end_of_it fn multiline_ticks() { +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// This _is a test for /// multiline /// emphasis_. +/// be_sure_we_got_to_the_end_of_it fn test_emphasis() { +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// This tests units. See also #835. @@ -38,22 +44,64 @@ fn test_emphasis() { /// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib /// 32kB 32MB 32GB 32TB 32PB 32EB /// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb +/// be_sure_we_got_to_the_end_of_it fn test_units() { +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +} + +/// This one checks we don’t try to split unicode codepoints +/// `ß` +/// `ℝ` +/// `💣` +/// `❤️` +/// ß_foo +/// ℝ_foo +/// 💣_foo +/// ❤️_foo +/// foo_ß +/// foo_ℝ +/// foo_💣 +/// foo_❤️ +/// [ßdummy textß][foo_ß] +/// [ℝdummy textℝ][foo_ℝ] +/// [💣dummy tex💣t][foo_💣] +/// [❤️dummy text❤️][foo_❤️] +/// [ßdummy textß](foo_ß) +/// [ℝdummy textℝ](foo_ℝ) +/// [💣dummy tex💣t](foo_💣) +/// [❤️dummy text❤️](foo_❤️) +/// [foo_ß]: dummy text +/// [foo_ℝ]: dummy text +/// [foo_💣]: dummy text +/// [foo_❤️]: dummy text +/// be_sure_we_got_to_the_end_of_it +fn test_unicode() { +//~^ ERROR: you should put `ß_foo` between ticks +//~| ERROR: you should put `ℝ_foo` between ticks +//~| ERROR: you should put `foo_ß` between ticks +//~| ERROR: you should put `foo_ℝ` between ticks +//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// This test has [a link_with_underscores][chunked-example] inside it. See #823. -/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues). And here is another [inline link][inline_link]. +/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues) +/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. +/// It can also be [inline_link2]. /// /// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example /// [inline_link]: https://foobar +/// [inline_link2]: https://foobar /// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and /// `multiline_ticks` functions. /// /// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` /// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , +/// be_sure_we_got_to_the_end_of_it fn main() { -//~^ ERROR: you should put `link_with_underscores` between ticks +//~^ ERROR: you should put `inline_link2` between ticks +//~| ERROR: you should put `link_with_underscores` between ticks +//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks foo_bar(); multiline_ticks(); test_emphasis(); -- cgit 1.4.1-3-g733a5 From 7ae8516bb3b44239131211425862502f4bfb5ecb Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 13 Apr 2016 16:07:45 +0200 Subject: Remove `#[feature(deprecated)]` Fixes `warning: this feature is stable. attribute no longer needed`. --- tests/compile-fail/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs index c7a4af60982..314602b2b0b 100644 --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -1,4 +1,4 @@ -#![feature(plugin, deprecated)] +#![feature(plugin)] #![plugin(clippy)] #![deny(inline_always, deprecated_semver)] -- cgit 1.4.1-3-g733a5 From 831b8fc1b5e78673a2dd855556c03b756819e5b3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 5 Apr 2016 17:29:14 +0200 Subject: Ignore `#[test]` fns in `cyclomatic_complexity` --- src/cyclomatic_complexity.rs | 9 ++++++--- tests/compile-fail/cyclomatic_complexity.rs | 11 +++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index fcd89801ecc..043504f5a28 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -1,12 +1,12 @@ //! calculate cyclomatic complexity and warn about overly complex functions -use rustc::lint::*; use rustc::cfg::CFG; +use rustc::lint::*; use rustc::ty; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, walk_expr}; use syntax::ast::Attribute; -use syntax::attr::*; +use syntax::attr; use syntax::codemap::Span; use utils::{in_macro, LimitStack, span_help_and_lint}; @@ -44,6 +44,7 @@ impl CyclomaticComplexity { if in_macro(cx, span) { return; } + let cfg = CFG::new(cx.tcx, block); let n = cfg.graph.len_nodes() as u64; let e = cfg.graph.len_edges() as u64; @@ -84,7 +85,9 @@ impl CyclomaticComplexity { impl LateLintPass for CyclomaticComplexity { fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemFn(_, _, _, _, _, ref block) = item.node { - self.check(cx, block, item.span); + if !attr::contains_name(&item.attrs, "test") { + self.check(cx, block, item.span); + } } } diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index f744d60440f..4b24f16eda7 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -171,6 +171,17 @@ fn bar() { //~ ERROR: the function has a cyclomatic complexity of 2 } } +#[test] +#[cyclomatic_complexity = "0"] +/// Tests are usually complex but simple at the same time. `cyclomatic_complexity` used to give +/// lots of false-positives in tests. +fn dont_warn_on_tests() { + match 99 { + 0 => println!("hi"), + _ => println!("bye"), + } +} + #[cyclomatic_complexity = "0"] fn barr() { //~ ERROR: the function has a cyclomatic complexity of 2 match 99 { -- cgit 1.4.1-3-g733a5 From 1789430a49d7ce0f59b76b4f07a2d8ba6be3d03e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 17:25:31 +0200 Subject: Add a `TEMPORARY_CSTRING_AS_PTR` lint --- README.md | 3 ++- src/lib.rs | 1 + src/methods.rs | 54 ++++++++++++++++++++++++++++++++++++++++--- src/utils/mod.rs | 3 ++- tests/compile-fail/methods.rs | 12 ++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fee6d066e7c..c7cee794db4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 140 lints included in this crate: +There are 141 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -135,6 +135,7 @@ name [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[temporary_cstring_as_ptr](https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr) | warn | getting the inner pointer of a temporary `CString` [too_many_arguments](https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [transmute_ptr_to_ref](https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type diff --git a/src/lib.rs b/src/lib.rs index 1b48c7b3dbb..c1a7732e3f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,6 +325,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, + methods::TEMPORARY_CSTRING_AS_PTR, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, misc::CMP_NAN, diff --git a/src/methods.rs b/src/methods.rs index 45f87fba9dd..8a51b576b3d 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -13,8 +13,8 @@ use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; -use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, - VEC_PATH}; +use utils::{CSTRING_NEW_PATH, BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, + OPTION_PATH, RESULT_PATH, VEC_PATH}; use utils::MethodArgs; #[derive(Clone)] @@ -286,6 +286,33 @@ declare_lint! { `_.split(\"x\")`" } +/// **What it does:** This lint checks for getting the inner pointer of a temporary `CString`. +/// +/// **Why is this bad?** The inner pointer of a `CString` is only valid as long as the `CString` is +/// alive. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap().as_ptr(); +/// unsafe { +/// call_some_ffi_func(c_str); +/// } +/// ``` +/// Here `c_str` point to a freed address. The correct use would be: +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap(); +/// unsafe { +/// call_some_ffi_func(c_str.as_ptr()); +/// } +/// ``` +declare_lint! { + pub TEMPORARY_CSTRING_AS_PTR, + Warn, + "getting the inner pointer of a temporary `CString`" +} + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -303,7 +330,8 @@ impl LintPass for MethodsPass { CLONE_DOUBLE_REF, NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, - SEARCH_IS_SOME) + SEARCH_IS_SOME, + TEMPORARY_CSTRING_AS_PTR) } } @@ -334,7 +362,11 @@ impl LateLintPass for MethodsPass { lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { lint_extend(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { + lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); } + + lint_or_fun_call(cx, expr, &name.node.as_str(), &args); if args.len() == 1 && name.node.as_str() == "clone" { lint_clone_on_copy(cx, expr); @@ -554,6 +586,22 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } } +fn lint_cstring_as_ptr(cx: &LateContext, expr: &Expr, new: &Expr, unwrap: &Expr) { + if_let_chain!{[ + let ExprCall(ref fun, ref args) = new.node, + args.len() == 1, + let ExprPath(None, ref path) = fun.node, + match_path(path, &CSTRING_NEW_PATH), + ], { + span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, + "you are getting the inner pointer of a temporary `CString`", + |db| { + db.fileline_note(expr.span, "that pointer will be invalid outside this expression"); + db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); + }); + }} +} + fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 761d5d3df9d..75637b67d9d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -28,11 +28,13 @@ pub type MethodArgs = HirVec<P<Expr>>; // module DefPaths for certain structs/enums we check for pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; pub const BOX_NEW_PATH: [&'static str; 4] = ["std", "boxed", "Box", "new"]; +pub const BOX_PATH: [&'static str; 3] = ["std", "boxed", "Box"]; pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const CSTRING_NEW_PATH: [&'static str; 4] = ["std", "ffi", "CString", "new"]; pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; pub const DISPLAY_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; @@ -59,7 +61,6 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; pub const TRANSMUTE_PATH: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const BOX_PATH: [&'static str; 3] = ["std", "boxed", "Box"]; /// Produce a nested chain of if-lets and ifs from the patterns: /// diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 9d938ebb19e..1869fd12a69 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -470,3 +470,15 @@ fn single_char_pattern() { //~| HELP try using a char instead: //~| SUGGESTION x.trim_right_matches('x'); } + +#[allow(result_unwrap_used)] +fn temporary_cstring() { + use std::ffi::CString; + + ( // extra parenthesis to better test spans + //~^ ERROR you are getting the inner pointer of a temporary `CString` + //~| NOTE that pointer will be invalid outside this expression + CString::new("foo").unwrap() + //~^ HELP assign the `CString` to a variable to extend its lifetime + ).as_ptr(); +} -- cgit 1.4.1-3-g733a5 From 3511297330be4ca9f697542ffdfafed9caa079e1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 17:27:57 +0200 Subject: Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07750501b48..4c53466a965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## Unreleased +* New lint: [`temporary_cstring_as_ptr`] + ## 0.0.63 — 2016-04-08 * Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)* @@ -78,6 +81,7 @@ All notable changes to this project will be documented in this file. [`redundant_closure_call`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call [`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string [`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string +[`temporary_cstring_as_ptr`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr [`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice [`unstable_as_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice [`unused_label`]: https://github.com/Manishearth/rust-clippy/wiki#unused_label -- cgit 1.4.1-3-g733a5 From d81481bd0d3ba9893b96c9a2dd5f31d96d115e0a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 17:56:46 +0200 Subject: Autogenerate CHANGELOG links to lints in wiki --- CHANGELOG.md | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++- util/update_lints.py | 11 ++++- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c53466a965..2493ae2502d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ All notable changes to this project will be documented in this file. ## 0.0.56 — 2016-03-23 * Update to *rustc 1.9.0-nightly (0dcc413e4 2016-03-22)* -* New lint: [`non_expressive_names`] +* New lints: [`many_single_char_names`] and [`similar_names`] ## 0.0.55 — 2016-03-21 * Update to *rustc 1.9.0-nightly (02310fd31 2016-03-19)* @@ -67,22 +67,150 @@ All notable changes to this project will be documented in this file. [configuration file]: ./rust-clippy#configuration +<!-- begin autogenerated links to wiki --> +[`absurd_extreme_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons +[`almost_swapped`]: https://github.com/Manishearth/rust-clippy/wiki#almost_swapped +[`approx_constant`]: https://github.com/Manishearth/rust-clippy/wiki#approx_constant +[`bad_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask +[`blacklisted_name`]: https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name +[`block_in_if_condition_expr`]: https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr +[`block_in_if_condition_stmt`]: https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt +[`bool_comparison`]: https://github.com/Manishearth/rust-clippy/wiki#bool_comparison +[`box_vec`]: https://github.com/Manishearth/rust-clippy/wiki#box_vec +[`boxed_local`]: https://github.com/Manishearth/rust-clippy/wiki#boxed_local +[`cast_possible_truncation`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation +[`cast_possible_wrap`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap +[`cast_precision_loss`]: https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss +[`cast_sign_loss`]: https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss +[`char_lit_as_u8`]: https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8 +[`chars_next_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp +[`clone_double_ref`]: https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref +[`clone_on_copy`]: https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy +[`cmp_nan`]: https://github.com/Manishearth/rust-clippy/wiki#cmp_nan +[`cmp_owned`]: https://github.com/Manishearth/rust-clippy/wiki#cmp_owned +[`collapsible_if`]: https://github.com/Manishearth/rust-clippy/wiki#collapsible_if [`crosspointer_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute +[`cyclomatic_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity +[`deprecated_semver`]: https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver +[`derive_hash_xor_eq`]: https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq [`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown +[`drop_ref`]: https://github.com/Manishearth/rust-clippy/wiki#drop_ref +[`duplicate_underscore_argument`]: https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument +[`empty_loop`]: https://github.com/Manishearth/rust-clippy/wiki#empty_loop +[`enum_clike_unportable_variant`]: https://github.com/Manishearth/rust-clippy/wiki#enum_clike_unportable_variant +[`enum_glob_use`]: https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use +[`enum_variant_names`]: https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names +[`eq_op`]: https://github.com/Manishearth/rust-clippy/wiki#eq_op +[`expl_impl_clone_on_copy`]: https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy +[`explicit_counter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop +[`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop +[`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice +[`filter_next`]: https://github.com/Manishearth/rust-clippy/wiki#filter_next +[`float_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#float_cmp +[`for_kv_map`]: https://github.com/Manishearth/rust-clippy/wiki#for_kv_map +[`for_loop_over_option`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option +[`for_loop_over_result`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result +[`identity_op`]: https://github.com/Manishearth/rust-clippy/wiki#identity_op +[`if_not_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_not_else +[`if_same_then_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else +[`ifs_same_cond`]: https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond [`indexing_slicing`]: https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing +[`ineffective_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask +[`inline_always`]: https://github.com/Manishearth/rust-clippy/wiki#inline_always +[`invalid_regex`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_regex [`invalid_upcast_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons +[`items_after_statements`]: https://github.com/Manishearth/rust-clippy/wiki#items_after_statements +[`iter_next_loop`]: https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop +[`len_without_is_empty`]: https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty +[`len_zero`]: https://github.com/Manishearth/rust-clippy/wiki#len_zero +[`let_and_return`]: https://github.com/Manishearth/rust-clippy/wiki#let_and_return +[`let_unit_value`]: https://github.com/Manishearth/rust-clippy/wiki#let_unit_value +[`linkedlist`]: https://github.com/Manishearth/rust-clippy/wiki#linkedlist [`logic_bug`]: https://github.com/Manishearth/rust-clippy/wiki#logic_bug +[`manual_swap`]: https://github.com/Manishearth/rust-clippy/wiki#manual_swap +[`many_single_char_names`]: https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names +[`map_clone`]: https://github.com/Manishearth/rust-clippy/wiki#map_clone +[`map_entry`]: https://github.com/Manishearth/rust-clippy/wiki#map_entry +[`match_bool`]: https://github.com/Manishearth/rust-clippy/wiki#match_bool +[`match_overlapping_arm`]: https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm +[`match_ref_pats`]: https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats [`match_same_arms`]: https://github.com/Manishearth/rust-clippy/wiki#match_same_arms +[`min_max`]: https://github.com/Manishearth/rust-clippy/wiki#min_max +[`modulo_one`]: https://github.com/Manishearth/rust-clippy/wiki#modulo_one +[`mut_mut`]: https://github.com/Manishearth/rust-clippy/wiki#mut_mut +[`mutex_atomic`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic +[`mutex_integer`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_integer +[`needless_bool`]: https://github.com/Manishearth/rust-clippy/wiki#needless_bool +[`needless_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes [`needless_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop +[`needless_return`]: https://github.com/Manishearth/rust-clippy/wiki#needless_return +[`needless_update`]: https://github.com/Manishearth/rust-clippy/wiki#needless_update +[`new_ret_no_self`]: https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self [`new_without_default`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default -[`non_expressive_names`]: https://github.com/Manishearth/rust-clippy/wiki#non_expressive_names +[`no_effect`]: https://github.com/Manishearth/rust-clippy/wiki#no_effect +[`non_ascii_literal`]: https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal [`nonminimal_bool`]: https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool +[`nonsensical_open_options`]: https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options +[`ok_expect`]: https://github.com/Manishearth/rust-clippy/wiki#ok_expect +[`option_map_unwrap_or`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or +[`option_map_unwrap_or_else`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else +[`option_unwrap_used`]: https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used +[`or_fun_call`]: https://github.com/Manishearth/rust-clippy/wiki#or_fun_call +[`out_of_bounds_indexing`]: https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing [`overflow_check_conditional`]: https://github.com/Manishearth/rust-clippy/wiki#overflow_check_conditional +[`panic_params`]: https://github.com/Manishearth/rust-clippy/wiki#panic_params +[`precedence`]: https://github.com/Manishearth/rust-clippy/wiki#precedence +[`print_stdout`]: https://github.com/Manishearth/rust-clippy/wiki#print_stdout +[`ptr_arg`]: https://github.com/Manishearth/rust-clippy/wiki#ptr_arg +[`range_step_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero +[`range_zip_with_len`]: https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len +[`redundant_closure`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure [`redundant_closure_call`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call +[`redundant_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern +[`regex_macro`]: https://github.com/Manishearth/rust-clippy/wiki#regex_macro +[`result_unwrap_used`]: https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used +[`reverse_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop +[`search_is_some`]: https://github.com/Manishearth/rust-clippy/wiki#search_is_some +[`shadow_reuse`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse +[`shadow_same`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_same +[`shadow_unrelated`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated +[`should_implement_trait`]: https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait +[`similar_names`]: https://github.com/Manishearth/rust-clippy/wiki#similar_names +[`single_char_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern +[`single_match`]: https://github.com/Manishearth/rust-clippy/wiki#single_match +[`single_match_else`]: https://github.com/Manishearth/rust-clippy/wiki#single_match_else [`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string +[`string_add`]: https://github.com/Manishearth/rust-clippy/wiki#string_add +[`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign +[`string_lit_as_bytes`]: https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes [`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string +[`suspicious_assignment_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting +[`suspicious_else_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting +[`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment [`temporary_cstring_as_ptr`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr +[`too_many_arguments`]: https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments +[`toplevel_ref_arg`]: https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg +[`transmute_ptr_to_ref`]: https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref +[`trivial_regex`]: https://github.com/Manishearth/rust-clippy/wiki#trivial_regex +[`type_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#type_complexity +[`unicode_not_nfc`]: https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc +[`unit_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#unit_cmp +[`unnecessary_mut_passed`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed +[`unneeded_field_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern [`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice [`unstable_as_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice +[`unused_collect`]: https://github.com/Manishearth/rust-clippy/wiki#unused_collect [`unused_label`]: https://github.com/Manishearth/rust-clippy/wiki#unused_label +[`unused_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes +[`use_debug`]: https://github.com/Manishearth/rust-clippy/wiki#use_debug +[`used_underscore_binding`]: https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding +[`useless_format`]: https://github.com/Manishearth/rust-clippy/wiki#useless_format +[`useless_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#useless_transmute [`useless_vec`]: https://github.com/Manishearth/rust-clippy/wiki#useless_vec +[`while_let_loop`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_loop +[`while_let_on_iterator`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator +[`wrong_pub_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention +[`wrong_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention +[`zero_divided_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero +[`zero_width_space`]: https://github.com/Manishearth/rust-clippy/wiki#zero_width_space +<!-- end autogenerated links to wiki --> diff --git a/util/update_lints.py b/util/update_lints.py index b16b4b67fad..bf9728d4f58 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -135,7 +135,7 @@ def main(print_only=False, check=False): return # collect all lints from source files - for root, dirs, files in os.walk('src'): + for root, _, files in os.walk('src'): for fn in files: if fn.endswith('.rs'): collect(lints, deprecated_lints, os.path.join(root, fn)) @@ -156,6 +156,15 @@ def main(print_only=False, check=False): lambda: ['There are %d lints included in this crate:\n' % len(lints)], write_back=not check) + # update the links in the CHANGELOG + changed |= replace_region( + 'CHANGELOG.md', + "<!-- begin autogenerated links to wiki -->", + "<!-- end autogenerated links to wiki -->", + lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], wiki_link) for l in + sorted(lints + deprecated_lints, key=lambda l: l[1])], + replace_start=False, write_back=not check) + # update the `pub mod` list changed |= replace_region( 'src/lib.rs', r'begin lints modules', r'end lints modules', -- cgit 1.4.1-3-g733a5 From 48a672b4eefa1cfe4dad62e37f8768e2f5a0c355 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 18:13:15 +0200 Subject: Move paths to their own module --- src/attrs.rs | 5 +++-- src/derive.rs | 6 +++--- src/drop_ref.rs | 5 ++--- src/entry.rs | 9 ++++---- src/format.rs | 10 ++++----- src/loops.rs | 16 +++++++-------- src/map_clone.rs | 9 ++++---- src/matches.rs | 16 +++++++-------- src/methods.rs | 33 +++++++++++++++--------------- src/mutex_atomic.rs | 4 ++-- src/new_without_default.rs | 10 ++++----- src/open_options.rs | 8 ++++---- src/panic.rs | 6 +++--- src/print.rs | 10 ++++----- src/ptr_arg.rs | 9 ++++---- src/regex.rs | 5 +++-- src/strings.rs | 7 +++---- src/transmute.rs | 5 ++--- src/types.rs | 8 +++++--- src/utils/mod.rs | 51 ++++++++-------------------------------------- src/utils/paths.rs | 37 +++++++++++++++++++++++++++++++++ src/vec.rs | 5 ++--- 22 files changed, 136 insertions(+), 138 deletions(-) create mode 100644 src/utils/paths.rs diff --git a/src/attrs.rs b/src/attrs.rs index 17b8a60bcb9..a41cd141a12 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -7,7 +7,8 @@ use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; use syntax::attr::*; use syntax::codemap::Span; -use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND}; +use utils::{in_macro, match_path, span_lint}; +use utils::paths; /// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. /// @@ -129,7 +130,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { ExprRet(None) | ExprBreak(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &BEGIN_UNWIND) + !match_path(path, &paths::BEGIN_UNWIND) } else { true } diff --git a/src/derive.rs b/src/derive.rs index 4b8446e6201..c9ac8f0a948 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -5,7 +5,7 @@ use rustc::ty; use rustc::hir::*; use syntax::ast::{Attribute, MetaItemKind}; use syntax::codemap::Span; -use utils::{CLONE_TRAIT_PATH, HASH_PATH}; +use utils::paths; use utils::{match_path, span_lint_and_then}; /// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` @@ -88,7 +88,7 @@ impl LateLintPass for Derive { /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { if_let_chain! {[ - match_path(&trait_ref.path, &HASH_PATH), + match_path(&trait_ref.path, &paths::HASH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() ], { let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); @@ -129,7 +129,7 @@ fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: & /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { - if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) { + if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); let subst_ty = ty.subst(cx.tcx, ¶meter_environment.free_substs); diff --git a/src/drop_ref.rs b/src/drop_ref.rs index 3448e05dbac..69156f15f31 100644 --- a/src/drop_ref.rs +++ b/src/drop_ref.rs @@ -2,8 +2,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; use syntax::codemap::Span; -use utils::DROP_PATH; -use utils::{match_def_path, span_note_and_lint}; +use utils::{match_def_path, paths, span_note_and_lint}; /// **What it does:** This lint checks for calls to `std::mem::drop` with a reference instead of an owned value. /// @@ -37,7 +36,7 @@ impl LateLintPass for DropRefPass { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(None, _) = path.node { let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); - if match_def_path(cx, def_id, &DROP_PATH) { + if match_def_path(cx, def_id, &paths::DROP) { if args.len() != 1 { return; } diff --git a/src/entry.rs b/src/entry.rs index 934400bc122..24810e242ad 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,10 +1,9 @@ -use rustc::lint::*; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, walk_expr, walk_block}; +use rustc::lint::*; use syntax::codemap::Span; use utils::SpanlessEq; -use utils::{BTREEMAP_PATH, HASHMAP_PATH}; -use utils::{get_item_name, match_type, snippet, span_lint_and_then, walk_ptrs_ty}; +use utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or /// `BTreeMap`. @@ -89,10 +88,10 @@ fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> O let map = ¶ms[0]; let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); - return if match_type(cx, obj_ty, &BTREEMAP_PATH) { + return if match_type(cx, obj_ty, &paths::BTREEMAP) { Some(("BTreeMap", map, key)) } - else if match_type(cx, obj_ty, &HASHMAP_PATH) { + else if match_type(cx, obj_ty, &paths::HASHMAP) { Some(("HashMap", map, key)) } else { diff --git a/src/format.rs b/src/format.rs index 0a349c98e07..0726fcaeab7 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,9 +1,9 @@ +use rustc::hir::*; use rustc::hir::map::Node::NodeItem; use rustc::lint::*; use rustc::ty::TypeVariants; -use rustc::hir::*; use syntax::ast::LitKind; -use utils::{DISPLAY_FMT_METHOD_PATH, FMT_ARGUMENTS_NEWV1_PATH, STRING_PATH}; +use utils::paths; use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty}; /// **What it does:** This lints about use of `format!("string literal with no argument")` and @@ -40,7 +40,7 @@ impl LateLintPass for FormatMacLint { if_let_chain!{[ let ExprPath(_, ref path) = fun.node, args.len() == 2, - match_path(path, &FMT_ARGUMENTS_NEWV1_PATH), + match_path(path, &paths::FMT_ARGUMENTS_NEWV1), // ensure the format string is `"{..}"` with only one argument and no text check_static_str(cx, &args[0]), // ensure the format argument is `{}` ie. Display with no fancy option @@ -108,11 +108,11 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { let ExprCall(_, ref args) = exprs[0].node, args.len() == 2, let ExprPath(None, ref path) = args[1].node, - match_path(path, &DISPLAY_FMT_METHOD_PATH) + match_path(path, &paths::DISPLAY_FMT_METHOD) ], { let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0])); - return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &STRING_PATH); + return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING); }} false diff --git a/src/loops.rs b/src/loops.rs index 4e7e4bf117d..4fb45e7c198 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -16,7 +16,7 @@ use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range, walk_ptrs_ty, recover_for_loop}; -use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH}; +use utils::paths; use utils::UnsugaredRange; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. @@ -505,7 +505,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { /// Check for `for` loops over `Option`s and `Results` fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { let ty = cx.tcx.expr_ty(arg); - if match_type(cx, ty, &OPTION_PATH) { + if match_type(cx, ty, &paths::OPTION) { span_help_and_lint(cx, FOR_LOOP_OVER_OPTION, arg.span, @@ -515,7 +515,7 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_"))); - } else if match_type(cx, ty, &RESULT_PATH) { + } else if match_type(cx, ty, &paths::RESULT) { span_help_and_lint(cx, FOR_LOOP_OVER_RESULT, arg.span, @@ -589,7 +589,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex }; let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); - if match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &BTREEMAP_PATH) { + if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) { span_lint_and_then(cx, FOR_KV_MAP, expr.span, @@ -735,13 +735,13 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // will allow further borrows afterwards let ty = cx.tcx.expr_ty(e); is_iterable_array(ty) || - match_type(cx, ty, &VEC_PATH) || - match_type(cx, ty, &LL_PATH) || - match_type(cx, ty, &HASHMAP_PATH) || + match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::LL) || + match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || - match_type(cx, ty, &BTREEMAP_PATH) || + match_type(cx, ty, &paths::BTREEMAP) || match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) } diff --git a/src/map_clone.rs b/src/map_clone.rs index eeb3aab4655..caefb64eb5f 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,8 +1,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{CLONE_PATH, OPTION_PATH}; -use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, walk_ptrs_ty, - walk_ptrs_ty_depth}; +use utils::{is_adjusted, match_path, match_trait_method, match_type, paths, snippet, + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** This lint checks for mapping clone() over an iterator. /// @@ -65,7 +64,7 @@ impl LateLintPass for MapClonePass { } } ExprPath(_, ref path) => { - if match_path(path, &CLONE_PATH) { + if match_path(path, &paths::CLONE) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); span_help_and_lint(cx, MAP_CLONE, @@ -99,7 +98,7 @@ fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { Some("iterator") - } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &OPTION_PATH) { + } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) { Some("Option") } else { None diff --git a/src/matches.rs b/src/matches.rs index d82dad5b065..c1692ee47d2 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -8,7 +8,7 @@ use rustc_const_math::ConstInt; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; -use utils::{COW_PATH, OPTION_PATH, RESULT_PATH}; +use utils::paths; use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. @@ -184,13 +184,13 @@ fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) { // list of candidate Enums we know will never get any more members - let candidates = &[(&COW_PATH, "Borrowed"), - (&COW_PATH, "Cow::Borrowed"), - (&COW_PATH, "Cow::Owned"), - (&COW_PATH, "Owned"), - (&OPTION_PATH, "None"), - (&RESULT_PATH, "Err"), - (&RESULT_PATH, "Ok")]; + let candidates = &[(&paths::COW, "Borrowed"), + (&paths::COW, "Cow::Borrowed"), + (&paths::COW, "Cow::Owned"), + (&paths::COW, "Owned"), + (&paths::OPTION, "None"), + (&paths::RESULT, "Err"), + (&paths::RESULT, "Ok")]; let path = match arms[1].pats[0].node { PatKind::TupleStruct(ref path, Some(ref inner)) => { diff --git a/src/methods.rs b/src/methods.rs index 8a51b576b3d..d2a91b615ae 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -13,9 +13,8 @@ use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; -use utils::{CSTRING_NEW_PATH, BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, - OPTION_PATH, RESULT_PATH, VEC_PATH}; use utils::MethodArgs; +use utils::paths; #[derive(Clone)] pub struct MethodsPass; @@ -470,7 +469,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) if ["default", "new"].contains(&path) { let arg_ty = cx.tcx.expr_ty(arg); - let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) { + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { default_trait_id } else { return false; @@ -497,13 +496,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) fn check_general_case(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, or_has_args: bool, span: Span) { // (path, fn_has_argument, methods) - let know_types: &[(&[_], _, &[_], _)] = &[(&BTREEMAP_ENTRY_PATH, false, &["or_insert"], "with"), - (&HASHMAP_ENTRY_PATH, false, &["or_insert"], "with"), - (&OPTION_PATH, + let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&RESULT_PATH, true, &["or", "unwrap_or"], "else")]; + (&paths::RESULT, true, &["or", "unwrap_or"], "else")]; let self_ty = cx.tcx.expr_ty(self_expr); @@ -571,7 +570,7 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr) { fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - if !match_type(cx, obj_ty, &VEC_PATH) { + if !match_type(cx, obj_ty, &paths::VEC) { return; } let arg_ty = cx.tcx.expr_ty(&args[1]); @@ -591,7 +590,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &Expr, new: &Expr, unwrap: &Expr) let ExprCall(ref fun, ref args) = new.node, args.len() == 1, let ExprPath(None, ref path) = fun.node, - match_path(path, &CSTRING_NEW_PATH), + match_path(path, &paths::CSTRING_NEW), ], { span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, "you are getting the inner pointer of a temporary `CString`", @@ -606,7 +605,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { ty::TySlice(_) => true, - ty::TyStruct(..) => match_type(cx, ty, &VEC_PATH), + ty::TyStruct(..) => match_type(cx, ty, &paths::VEC), ty::TyArray(_, size) => size < 32, ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | ty::TyBox(ref inner) => may_slice(cx, inner), @@ -641,9 +640,9 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); - let mess = if match_type(cx, obj_ty, &OPTION_PATH) { + let mess = if match_type(cx, obj_ty, &paths::OPTION) { Some((OPTION_UNWRAP_USED, "an Option", "None")) - } else if match_type(cx, obj_ty, &RESULT_PATH) { + } else if match_type(cx, obj_ty, &paths::RESULT) { Some((RESULT_UNWRAP_USED, "a Result", "Err")) } else { None @@ -666,7 +665,7 @@ fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { /// lint use of `ok().expect()` for `Result`s fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { // lint if the caller of `ok()` is a `Result` - if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &RESULT_PATH) { + if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) { let result_type = cx.tcx.expr_ty(&ok_args[0]); if let Some(error_type) = get_error_type(cx, result_type) { if has_debug_impl(error_type, cx) { @@ -684,7 +683,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { /// lint use of `map().unwrap_or()` for `Option`s fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { // lint message let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ `map_or(a, f)` instead"; @@ -715,7 +714,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwr /// lint use of `map().unwrap_or_else()` for `Option`s fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &OPTION_PATH) { + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { // lint message let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ `map_or_else(g, f)` instead"; @@ -842,7 +841,7 @@ fn lint_single_char_pattern(cx: &LateContext, expr: &Expr, arg: &Expr) { /// Given a `Result<T, E>` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { - if !match_type(cx, ty, &RESULT_PATH) { + if !match_type(cx, ty, &paths::RESULT) { return None; } if let ty::TyEnum(_, substs) = ty.sty { @@ -853,7 +852,7 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { None } -/// This checks whether a given type is known to implement `Debug`. +/// This checks whether a given type is known to implement Debug. fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { match cx.tcx.lang_items.debug_trait() { Some(debug) => implements_trait(cx, ty, debug, Vec::new()), diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs index bae1ae38168..7d637adb8b8 100644 --- a/src/mutex_atomic.rs +++ b/src/mutex_atomic.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::ParamSpace; use rustc::ty; use rustc::hir::Expr; use syntax::ast; -use utils::{span_lint, MUTEX_PATH, match_type}; +use utils::{match_type, paths, span_lint}; /// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do. /// @@ -47,7 +47,7 @@ impl LateLintPass for MutexAtomic { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { let ty = cx.tcx.expr_ty(expr); if let ty::TyStruct(_, subst) = ty.sty { - if match_type(cx, ty, &MUTEX_PATH) { + if match_type(cx, ty, &paths::MUTEX) { let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 2bcc345fd60..f42b1d0d74a 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -1,10 +1,10 @@ -use rustc::lint::*; -use rustc::hir; use rustc::hir::intravisit::FnKind; +use rustc::hir; +use rustc::lint::*; use syntax::ast; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint, - DEFAULT_TRAIT_PATH}; +use utils::paths; +use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint}; /// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` /// implementation. @@ -54,7 +54,7 @@ impl LateLintPass for NewWithoutDefault { self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics let Some(ret_ty) = return_ty(cx, id), same_tys(cx, self_ty, ret_ty, id), - let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH), + let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), !implements_trait(cx, self_ty, default_trait_id, Vec::new()) ], { span_lint(cx, NEW_WITHOUT_DEFAULT, span, diff --git a/src/open_options.rs b/src/open_options.rs index 3c1e69a40ea..aaaebe5b2f8 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -1,8 +1,8 @@ -use rustc::lint::*; use rustc::hir::{Expr, ExprMethodCall, ExprLit}; +use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; -use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH}; +use utils::{match_type, paths, span_lint, walk_ptrs_ty_depth}; /// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. /// @@ -31,7 +31,7 @@ impl LateLintPass for NonSensicalOpenOptions { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprMethodCall(ref name, _, ref arguments) = e.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); - if name.node.as_str() == "open" && match_type(cx, obj_ty, &OPEN_OPTIONS_PATH) { + if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); get_open_options(cx, &arguments[0], &mut options); check_open_options(cx, &options, e.span); @@ -61,7 +61,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); // Only proceed if this is a call on some object of type std::fs::OpenOptions - if match_type(cx, obj_ty, &OPEN_OPTIONS_PATH) && arguments.len() >= 2 { + if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { let argument_option = match arguments[1].node { ExprLit(ref span) => { diff --git a/src/panic.rs b/src/panic.rs index ab03181c2dd..78499fa1a1a 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,7 +1,7 @@ -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; use syntax::ast::LitKind; -use utils::{span_lint, is_direct_expn_of, match_path, BEGIN_UNWIND}; +use utils::{is_direct_expn_of, match_path, paths, span_lint}; /// **What it does:** This lint checks for missing parameters in `panic!`. /// @@ -33,7 +33,7 @@ impl LateLintPass for PanicPass { let ExprCall(ref fun, ref params) = ex.node, params.len() == 2, let ExprPath(None, ref path) = fun.node, - match_path(path, &BEGIN_UNWIND), + match_path(path, &paths::BEGIN_UNWIND), let ExprLit(ref lit) = params[0].node, is_direct_expn_of(cx, params[0].span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, diff --git a/src/print.rs b/src/print.rs index a298d162c05..d426286dba4 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,7 +1,7 @@ +use rustc::hir::*; use rustc::hir::map::Node::{NodeItem, NodeImplItem}; use rustc::lint::*; -use rustc::hir::*; -use utils::{FMT_ARGUMENTV1_NEW_PATH, DEBUG_FMT_METHOD_PATH, IO_PRINT_PATH}; +use utils::paths; use utils::{is_expn_of, match_path, span_lint}; /// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants. @@ -45,7 +45,7 @@ impl LateLintPass for PrintLint { if let ExprPath(_, ref path) = fun.node { // Search for `std::io::_print(..)` which is unique in a // `print!` expansion. - if match_path(path, &IO_PRINT_PATH) { + if match_path(path, &paths::IO_PRINT) { if let Some(span) = is_expn_of(cx, expr.span, "print") { // `println!` uses `print!`. let (span, name) = match is_expn_of(cx, span, "println") { @@ -58,9 +58,9 @@ impl LateLintPass for PrintLint { } // Search for something like // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` - else if args.len() == 2 && match_path(path, &FMT_ARGUMENTV1_NEW_PATH) { + else if args.len() == 2 && match_path(path, &paths::FMT_ARGUMENTV1_NEW) { if let ExprPath(None, ref path) = args[1].node { - if match_path(path, &DEBUG_FMT_METHOD_PATH) && !is_in_debug_impl(cx, expr) && + if match_path(path, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(cx, expr.span, "panic").is_none() { span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index 8720424da86..addcfc9e84d 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -1,12 +1,11 @@ //! Checks for usage of `&Vec[_]` and `&String`. +use rustc::hir::*; use rustc::hir::map::NodeItem; use rustc::lint::*; use rustc::ty; -use rustc::hir::*; use syntax::ast::NodeId; -use utils::{STRING_PATH, VEC_PATH}; -use utils::{span_lint, match_type}; +use utils::{match_type, paths, span_lint}; /// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. /// @@ -61,13 +60,13 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { - if match_type(cx, ty, &VEC_PATH) { + if match_type(cx, ty, &paths::VEC) { span_lint(cx, PTR_ARG, arg.ty.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ with non-Vec-based slices. Consider changing the type to `&[...]`"); - } else if match_type(cx, ty, &STRING_PATH) { + } else if match_type(cx, ty, &paths::STRING) { span_lint(cx, PTR_ARG, arg.ty.span, diff --git a/src/regex.rs b/src/regex.rs index f24639312ed..177f7a7b045 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -9,7 +9,8 @@ use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; -use utils::{is_expn_of, match_path, match_type, REGEX_NEW_PATH, span_lint, span_help_and_lint}; +use utils::paths; +use utils::{is_expn_of, match_path, match_type, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// @@ -97,7 +98,7 @@ impl LateLintPass for RegexPass { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, let ExprPath(_, ref path) = fun.node, - match_path(path, ®EX_NEW_PATH) && args.len() == 1 + match_path(path, &paths::REGEX_NEW) && args.len() == 1 ], { if let ExprLit(ref lit) = args[0].node { if let LitKind::Str(ref r, _) = lit.node { diff --git a/src/strings.rs b/src/strings.rs index da1456671fd..a6808d2dd42 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -3,12 +3,11 @@ //! Note that since we have two lints where one subsumes the other, we try to //! disable the subsumed lint unless it has a higher level -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; use syntax::codemap::Spanned; -use utils::STRING_PATH; use utils::SpanlessEq; -use utils::{match_type, span_lint, span_lint_and_then, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, paths, span_lint, span_lint_and_then, walk_ptrs_ty, get_parent_expr}; /// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). /// @@ -108,7 +107,7 @@ impl LateLintPass for StringAdd { } fn is_string(cx: &LateContext, e: &Expr) -> bool { - match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &STRING_PATH) + match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &paths::STRING) } fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { diff --git a/src/transmute.rs b/src/transmute.rs index 41b92ca6113..8b74b1989db 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -2,8 +2,7 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; use rustc::ty; use rustc::hir::*; -use utils::TRANSMUTE_PATH; -use utils::{match_def_path, snippet_opt, span_lint, span_lint_and_then}; +use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** This lint checks for transmutes to the original type of the object. /// @@ -67,7 +66,7 @@ impl LateLintPass for Transmute { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if match_def_path(cx, def_id, &TRANSMUTE_PATH) { + if match_def_path(cx, def_id, &paths::TRANSMUTE) { let from_ty = cx.tcx.expr_ty(&args[0]); let to_ty = cx.tcx.expr_ty(e); diff --git a/src/types.rs b/src/types.rs index 281af90736b..00b36f1f5d4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,9 @@ use rustc::ty; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; -use utils::*; +use utils::{comparisons, in_external_macro, in_macro, is_from_for_desugar, match_def_path, snippet, + span_help_and_lint, span_lint}; +use utils::paths; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -63,7 +65,7 @@ impl LateLintPass for TypePass { let Some(ref vec) = ag.types.get(0), let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), let def::Def::Struct(..) = did.full_def(), - match_def_path(cx, did.def_id(), &VEC_PATH), + match_def_path(cx, did.def_id(), &paths::VEC), ], { span_help_and_lint(cx, @@ -73,7 +75,7 @@ impl LateLintPass for TypePass { "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); } } - } else if match_def_path(cx, did.def_id(), &LL_PATH) { + } else if match_def_path(cx, did.def_id(), &paths::LL) { span_help_and_lint(cx, LINKEDLIST, ast_ty.span, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 75637b67d9d..d01b0698de8 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -22,45 +22,10 @@ use syntax::ptr::P; pub mod comparisons; pub mod conf; mod hir; +pub mod paths; pub use self::hir::{SpanlessEq, SpanlessHash}; -pub type MethodArgs = HirVec<P<Expr>>; -// module DefPaths for certain structs/enums we check for -pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; -pub const BOX_NEW_PATH: [&'static str; 4] = ["std", "boxed", "Box", "new"]; -pub const BOX_PATH: [&'static str; 3] = ["std", "boxed", "Box"]; -pub const BTREEMAP_ENTRY_PATH: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; -pub const BTREEMAP_PATH: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; -pub const CLONE_PATH: [&'static str; 3] = ["clone", "Clone", "clone"]; -pub const CLONE_TRAIT_PATH: [&'static str; 2] = ["clone", "Clone"]; -pub const COW_PATH: [&'static str; 3] = ["collections", "borrow", "Cow"]; -pub const CSTRING_NEW_PATH: [&'static str; 4] = ["std", "ffi", "CString", "new"]; -pub const DEBUG_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; -pub const DEFAULT_TRAIT_PATH: [&'static str; 3] = ["core", "default", "Default"]; -pub const DISPLAY_FMT_METHOD_PATH: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; -pub const DROP_PATH: [&'static str; 3] = ["core", "mem", "drop"]; -pub const FMT_ARGUMENTS_NEWV1_PATH: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; -pub const FMT_ARGUMENTV1_NEW_PATH: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; -pub const HASHMAP_ENTRY_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; -pub const HASHMAP_PATH: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; -pub const HASH_PATH: [&'static str; 2] = ["hash", "Hash"]; -pub const IO_PRINT_PATH: [&'static str; 3] = ["std", "io", "_print"]; -pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; -pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"]; -pub const RANGE_FROM_PATH: [&'static str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL_PATH: [&'static str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE_NON_EMPTY_PATH: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; -pub const RANGE_PATH: [&'static str; 3] = ["std", "ops", "Range"]; -pub const RANGE_TO_INCLUSIVE_PATH: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; -pub const RANGE_TO_PATH: [&'static str; 3] = ["std", "ops", "RangeTo"]; -pub const REGEX_NEW_PATH: [&'static str; 3] = ["regex", "Regex", "new"]; -pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"]; -pub const TRANSMUTE_PATH: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; -pub const VEC_FROM_ELEM_PATH: [&'static str; 3] = ["std", "vec", "from_elem"]; -pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub type MethodArgs = HirVec<P<Expr>>; /// Produce a nested chain of if-lets and ifs from the patterns: /// @@ -764,22 +729,22 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { match unwrap_unstable(&expr).node { ExprPath(None, ref path) => { - if match_path(path, &RANGE_FULL_PATH) { + if match_path(path, &paths::RANGE_FULL) { Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) } else { None } } ExprStruct(ref path, ref fields, None) => { - if match_path(path, &RANGE_FROM_PATH) { + if match_path(path, &paths::RANGE_FROM) { Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) - } else if match_path(path, &RANGE_INCLUSIVE_NON_EMPTY_PATH) { + } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) - } else if match_path(path, &RANGE_PATH) { + } else if match_path(path, &paths::RANGE) { Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) - } else if match_path(path, &RANGE_TO_INCLUSIVE_PATH) { + } else if match_path(path, &paths::RANGE_TO_INCLUSIVE) { Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) - } else if match_path(path, &RANGE_TO_PATH) { + } else if match_path(path, &paths::RANGE_TO) { Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) } else { None diff --git a/src/utils/paths.rs b/src/utils/paths.rs new file mode 100644 index 00000000000..94f1d17f27a --- /dev/null +++ b/src/utils/paths.rs @@ -0,0 +1,37 @@ +//! This module contains paths to types and functions Clippy needs to know about. + +pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; +pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; +pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; +pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; +pub const CLONE: [&'static str; 3] = ["clone", "Clone", "clone"]; +pub const CLONE_TRAIT: [&'static str; 2] = ["clone", "Clone"]; +pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const CSTRING_NEW: [&'static str; 4] = ["std", "ffi", "CString", "new"]; +pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; +pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"]; +pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; +pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; +pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; +pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASH: [&'static str; 2] = ["hash", "Hash"]; +pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; +pub const LL: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; +pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; +pub const RANGE_FROM: [&'static str; 3] = ["std", "ops", "RangeFrom"]; +pub const RANGE_FULL: [&'static str; 3] = ["std", "ops", "RangeFull"]; +pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE: [&'static str; 3] = ["std", "ops", "Range"]; +pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; +pub const RANGE_TO: [&'static str; 3] = ["std", "ops", "RangeTo"]; +pub const REGEX_NEW: [&'static str; 3] = ["regex", "Regex", "new"]; +pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; +pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; +pub const VEC_FROM_ELEM: [&'static str; 3] = ["std", "vec", "from_elem"]; +pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"]; diff --git a/src/vec.rs b/src/vec.rs index d27a3320d96..513efa1a2a4 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -3,8 +3,7 @@ use rustc::ty::TypeVariants; use rustc::hir::*; use syntax::codemap::Span; use syntax::ptr::P; -use utils::VEC_FROM_ELEM_PATH; -use utils::{is_expn_of, match_path, recover_for_loop, snippet, span_lint_and_then}; +use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -92,7 +91,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> let ExprPath(_, ref path) = fun.node, is_expn_of(cx, fun.span, "vec").is_some() ], { - return if match_path(path, &VEC_FROM_ELEM_PATH) && args.len() == 2 { + return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { // `vec![elem; size]` case Some(VecArgs::Repeat(&args[0], &args[1])) } -- cgit 1.4.1-3-g733a5 From cd12a2369a4c3a9b9719a14c7f3f53b6b58b9ebe Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 18:41:38 +0200 Subject: s/paths::LL/paths::LINKED_LIST All other paths had non-abbreviated names. --- src/loops.rs | 2 +- src/types.rs | 2 +- src/utils/paths.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 4fb45e7c198..f376e28c992 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -736,7 +736,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { let ty = cx.tcx.expr_ty(e); is_iterable_array(ty) || match_type(cx, ty, &paths::VEC) || - match_type(cx, ty, &paths::LL) || + match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || diff --git a/src/types.rs b/src/types.rs index 00b36f1f5d4..9d12d7970d1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -75,7 +75,7 @@ impl LateLintPass for TypePass { "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); } } - } else if match_def_path(cx, did.def_id(), &paths::LL) { + } else if match_def_path(cx, did.def_id(), &paths::LINKED_LIST) { span_help_and_lint(cx, LINKEDLIST, ast_ty.span, diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 94f1d17f27a..1777c31ef8c 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -19,7 +19,7 @@ pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASH: [&'static str; 2] = ["hash", "Hash"]; pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; -pub const LL: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; -- cgit 1.4.1-3-g733a5 From a878916ad54eba5e92a3e6f0906e5099b26815d1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 20:14:03 +0200 Subject: rustfmt all the things --- src/array_indexing.rs | 23 ++++---- src/attrs.rs | 3 +- src/bit_mask.rs | 2 +- src/booleans.rs | 99 ++++++++++++++++++++-------------- src/collapsible_if.rs | 4 +- src/consts.rs | 23 +++++--- src/copies.rs | 5 +- src/cyclomatic_complexity.rs | 20 +++---- src/doc.rs | 11 ++-- src/entry.rs | 2 +- src/enum_glob_use.rs | 2 +- src/eta_reduction.rs | 5 +- src/functions.rs | 11 ++-- src/if_not_else.rs | 6 +-- src/len_zero.rs | 7 +-- src/lifetimes.rs | 11 ++-- src/loops.rs | 10 ++-- src/matches.rs | 55 ++++++++++--------- src/methods.rs | 6 ++- src/minmax.rs | 4 +- src/misc.rs | 7 +-- src/misc_early.rs | 10 ++-- src/mut_mut.rs | 4 +- src/mut_reference.rs | 11 ++-- src/needless_bool.rs | 35 ++++++------ src/no_effect.rs | 3 +- src/non_expressive_names.rs | 23 ++++---- src/open_options.rs | 4 +- src/overflow_check_conditional.rs | 2 +- src/precedence.rs | 8 +-- src/regex.rs | 6 +-- src/returns.rs | 2 +- src/shadow.rs | 15 +++--- src/strings.rs | 7 ++- src/temporary_assignment.rs | 6 +-- src/transmute.rs | 22 ++++---- src/types.rs | 108 ++++++++++++++++++++++---------------- src/utils/conf.rs | 3 +- src/utils/hir.rs | 9 ++-- src/utils/mod.rs | 53 ++++++++++++++----- src/vec.rs | 3 +- 41 files changed, 375 insertions(+), 275 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index ce5c85500bd..2295bd7832a 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -78,17 +78,16 @@ impl LateLintPass for ArrayIndexing { // Index is a constant range if let Some(range) = utils::unsugar_range(index) { - let start = range.start.map(|start| - eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)).map(|v| v.ok()); - let end = range.end.map(|end| - eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)).map(|v| v.ok()); + let start = range.start + .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) + .map(|v| v.ok()); + let end = range.end + .map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)) + .map(|v| v.ok()); if let Some((start, end)) = to_const_range(start, end, range.limits, size) { if start > size || end > size { - utils::span_lint(cx, - OUT_OF_BOUNDS_INDEXING, - e.span, - "range is out of bounds"); + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); } return; } @@ -111,11 +110,9 @@ impl LateLintPass for ArrayIndexing { } /// Returns an option containing a tuple with the start and end (exclusive) of the range. -fn to_const_range(start: Option<Option<ConstVal>>, - end: Option<Option<ConstVal>>, - limits: RangeLimits, +fn to_const_range(start: Option<Option<ConstVal>>, end: Option<Option<ConstVal>>, limits: RangeLimits, array_size: ConstInt) - -> Option<(ConstInt, ConstInt)> { + -> Option<(ConstInt, ConstInt)> { let start = match start { Some(Some(ConstVal::Integral(x))) => x, Some(_) => return None, @@ -131,7 +128,7 @@ fn to_const_range(start: Option<Option<ConstVal>>, } } Some(_) => return None, - None => array_size + None => array_size, }; Some((start, end)) diff --git a/src/attrs.rs b/src/attrs.rs index a41cd141a12..6106486c71e 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -115,7 +115,8 @@ fn is_relevant_block(block: &Block) -> bool { for stmt in &block.stmts { match stmt.node { StmtDecl(_, _) => return true, - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => { return is_relevant_expr(expr); } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 45f7e5bc938..aec0990dcc6 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -264,7 +264,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { // borrowing. let def_map = cx.tcx.def_map.borrow(); match def_map.get(&lit.id) { - Some(&PathResolution { base_def: Def::Const(def_id), ..}) => Some(def_id), + Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id), _ => None, } } diff --git a/src/booleans.rs b/src/booleans.rs index 213d12b42ef..908415acc7b 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -49,7 +49,7 @@ struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); use quine_mc_cluskey::Bool; struct Hir2Qmm<'a, 'tcx: 'a, 'v> { terminals: Vec<&'v Expr>, - cx: &'a LateContext<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx>, } impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { @@ -75,17 +75,17 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { match binop.node { BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), - _ => {}, + _ => (), } - }, + } ExprLit(ref lit) => { match lit.node { LitKind::Bool(true) => return Ok(Bool::True), LitKind::Bool(false) => return Ok(Bool::False), - _ => {}, + _ => (), } - }, - _ => {}, + } + _ => (), } } for (n, expr) in self.terminals.iter().enumerate() { @@ -95,11 +95,13 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { - let mk_expr = |op| Expr { - id: DUMMY_NODE_ID, - span: DUMMY_SP, - attrs: None, - node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + let mk_expr = |op| { + Expr { + id: DUMMY_NODE_ID, + span: DUMMY_SP, + attrs: None, + node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + } }; match binop.node { BiEq => mk_expr(BiNe), @@ -110,7 +112,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { BiLe => mk_expr(BiGt), _ => continue, } - }, + } _ => continue, }; if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { @@ -137,17 +139,17 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { True => { s.push_str("true"); s - }, + } False => { s.push_str("false"); s - }, + } Not(ref inner) => { match **inner { And(_) | Or(_) => { s.push('!'); recurse(true, cx, inner, terminals, s) - }, + } Term(n) => { if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { let op = match binop.node { @@ -159,8 +161,8 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { BiGe => " < ", _ => { s.push('!'); - return recurse(true, cx, inner, terminals, s) - }, + return recurse(true, cx, inner, terminals, s); + } }; s.push_str(&snip(lhs)); s.push_str(op); @@ -170,13 +172,13 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push('!'); recurse(false, cx, inner, terminals, s) } - }, + } _ => { s.push('!'); recurse(false, cx, inner, terminals, s) - }, + } } - }, + } And(ref v) => { if brackets { s.push('('); @@ -198,7 +200,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push(')'); } s - }, + } Or(ref v) => { if brackets { s.push('('); @@ -212,7 +214,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push(')'); } s - }, + } Term(n) => { if brackets { if let ExprBinary(..) = terminals[n as usize].node { @@ -243,13 +245,13 @@ fn simple_negate(b: Bool) -> Bool { *el = simple_negate(::std::mem::replace(el, True)); } Or(v) - }, + } Or(mut v) => { for el in &mut v { *el = simple_negate(::std::mem::replace(el, True)); } And(v) - }, + } Not(inner) => *inner, } } @@ -271,13 +273,13 @@ fn terminal_stats(b: &Bool) -> Stats { _ => stats.negations += 1, } recurse(inner, stats); - }, + } And(ref v) | Or(ref v) => { stats.ops += v.len() - 1; for inner in v { recurse(inner, stats); } - }, + } Term(n) => stats.terminals[n as usize] += 1, } } @@ -306,7 +308,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { let mut simplified = expr.simplify(); for simple in Bool::Not(Box::new(expr.clone())).simplify() { match simple { - Bool::Not(_) | Bool::True | Bool::False => {}, + Bool::Not(_) | Bool::True | Bool::False => {} _ => simplified.push(Bool::Not(Box::new(simple.clone()))), } let simple_negated = simple_negate(simple); @@ -325,28 +327,43 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { continue 'simplified; } if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { - span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { - db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); - db.span_suggestion(e.span, "it would look like the following", suggest(self.0, suggestion, &h2q.terminals)); - }); + span_lint_and_then(self.0, + LOGIC_BUG, + e.span, + "this boolean expression contains a logic bug", + |db| { + db.span_help(h2q.terminals[i].span, + "this expression can be optimized out by applying \ + boolean operations to the outer expression"); + db.span_suggestion(e.span, + "it would look like the following", + suggest(self.0, suggestion, &h2q.terminals)); + }); // don't also lint `NONMINIMAL_BOOL` return; } // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || - (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || - (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); + (stats.negations > simplified_stats.negations && + stats.ops == simplified_stats.ops) || + (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); } if improvement { improvements.push(suggestion); } } if !improvements.is_empty() { - span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { - for suggestion in &improvements { - db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); - } - }); + span_lint_and_then(self.0, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + for suggestion in &improvements { + db.span_suggestion(e.span, + "try", + suggest(self.0, suggestion, &h2q.terminals)); + } + }); } } } @@ -354,7 +371,9 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'v Expr) { - if in_macro(self.0, e.span) { return } + if in_macro(self.0, e.span) { + return; + } match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprUnary(UnNot, ref inner) => { @@ -363,7 +382,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { } else { walk_expr(self, e); } - }, + } _ => walk_expr(self, e), } } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index 5674806b175..38e04723e53 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -70,7 +70,7 @@ fn check_if(cx: &LateContext, e: &Expr) { db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); }); }} - } else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = + } else if let Some(&Expr { node: ExprIf(ref check_inner, ref content, None), span: sp, .. }) = single_stmt_of_block(then) { if e.span.expn_id != sp.expn_id { return; @@ -89,7 +89,7 @@ fn check_if(cx: &LateContext, e: &Expr) { fn requires_brackets(e: &Expr) -> bool { match e.node { - ExprBinary(Spanned {node: n, ..}, _, _) if n == BiEq => false, + ExprBinary(Spanned { node: n, .. }, _, _) if n == BiEq => false, _ => true, } } diff --git a/src/consts.rs b/src/consts.rs index d30392e0586..0eed34a8055 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -85,7 +85,9 @@ impl PartialEq for Constant { (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(l), &Constant::Int(r)) => l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked(), + (&Constant::Int(l), &Constant::Int(r)) => { + l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked() + } (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them @@ -131,7 +133,8 @@ impl Hash for Constant { Constant::Bool(b) => { b.hash(state); } - Constant::Vec(ref v) | Constant::Tuple(ref v) => { + Constant::Vec(ref v) | + Constant::Tuple(ref v) => { v.hash(state); } Constant::Repeat(ref c, l) => { @@ -186,12 +189,16 @@ fn lit_to_constant(lit: &LitKind) -> Constant { LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))), + LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => { + Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))) + } LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), - LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))), + LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => { + Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))) + } LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), LitKind::Bool(b) => Constant::Bool(b), @@ -285,7 +292,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { if let Some(lcx) = self.lcx { let mut maybe_id = None; - if let Some(&PathResolution { base_def: Def::Const(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { + if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) { maybe_id = Some(id); } // separate if lets to avoid double borrowing the def_map @@ -324,7 +331,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { - let l = if let Some(l) = self.expr(left) { l } else { return None; }; + let l = if let Some(l) = self.expr(left) { + l + } else { + return None; + }; let r = self.expr(right); match (op.node, l, r) { (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), diff --git a/src/copies.rs b/src/copies.rs index 5b992cf38ae..aba4638ab8b 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -71,7 +71,7 @@ impl LateLintPass for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if !in_macro(cx, expr.span) { // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { + if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { if else_expr.id == expr.id { return; } @@ -185,7 +185,8 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { match pat.node { - PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), + PatKind::Box(ref pat) | + PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), PatKind::TupleStruct(_, Some(ref pats)) => { for pat in pats { bindings_impl(cx, pat, map); diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 043504f5a28..e8a3a569a14 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -60,12 +60,7 @@ impl CyclomaticComplexity { tcx: &cx.tcx, }; helper.visit_block(block); - let CCHelper { - match_arms, - divergence, - short_circuits, - .. - } = helper; + let CCHelper { match_arms, divergence, short_circuits, .. } = helper; if cc + divergence < match_arms + short_circuits { report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span); @@ -132,7 +127,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { walk_expr(self, e); let ty = self.tcx.node_id_to_type(callee.id); match ty.sty { - ty::TyFnDef(_, _, ty) | ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { + ty::TyFnDef(_, _, ty) | + ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { self.divergence += 1; } _ => (), @@ -143,7 +139,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { walk_expr(self, e); match op.node { BiAnd | BiOr => self.short_circuits += 1, - _ => {}, + _ => (), } } _ => walk_expr(self, e), @@ -156,10 +152,10 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, sp span_bug!(span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ div = {}, shorts = {}. Please file a bug report.", - cc, - narms, - div, - shorts); + cc, + narms, + div, + shorts); } #[cfg(not(feature="debugging"))] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { diff --git a/src/doc.rs b/src/doc.rs index f27b4d862f1..54d5366729e 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -142,10 +142,10 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp } '`' => { current_word_begin = jump_to!(chars, '`', len); - }, + } '[' => { let end = jump_to!(chars, ']', len); - let link_text = &doc[current_word_begin+1..end]; + let link_text = &doc[current_word_begin + 1..end]; match chars.peek() { Some(&(_, c)) => { @@ -199,7 +199,7 @@ fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span } let s = if s.ends_with('s') { - &s[..s.len()-1] + &s[..s.len() - 1] } else { s }; @@ -223,6 +223,9 @@ fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span } if has_underscore(word) || word.contains("::") || is_camel_case(word) { - span_lint(cx, DOC_MARKDOWN, span, &format!("you should put `{}` between ticks in the documentation", word)); + span_lint(cx, + DOC_MARKDOWN, + span, + &format!("you should put `{}` between ticks in the documentation", word)); } } diff --git a/src/entry.rs b/src/entry.rs index 24810e242ad..d63d8c67c5d 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -47,7 +47,7 @@ impl LateLintPass for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = else_block.is_none() && - ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); + ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); let mut visitor = InsertVisitor { cx: cx, diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs index 671b9bb141c..37a89069d19 100644 --- a/src/enum_glob_use.rs +++ b/src/enum_glob_use.rs @@ -54,7 +54,7 @@ impl EnumGlobUse { let child = cx.sess().cstore.item_children(def.def_id()); if let Some(child) = child.first() { if let DefLike::DlDef(Def::Variant(..)) = child.def { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 4519acc39de..83abe215aa7 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -60,9 +60,10 @@ fn check_closure(cx: &LateContext, expr: &Expr) { let fn_ty = cx.tcx.expr_ty(caller); match fn_ty.sty { // Is it an unsafe function? They don't implement the closure traits - ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { + ty::TyFnDef(_, _, fn_ty) | + ty::TyFnPtr(fn_ty) => { if fn_ty.unsafety == Unsafety::Unsafe || - fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { + fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { return; } } diff --git a/src/functions.rs b/src/functions.rs index ed04473abc3..37b65e471fa 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -31,9 +31,7 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64) -> Functions { - Functions { - threshold: threshold - } + Functions { threshold: threshold } } } @@ -49,7 +47,8 @@ impl LateLintPass for Functions { if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { match item.node { - hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..) => return, + hir::ItemImpl(_, _, _, Some(_), _, _) | + hir::ItemDefaultImpl(..) => return, _ => (), } } @@ -68,7 +67,9 @@ impl Functions { fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { let args = decl.inputs.len() as u64; if args > self.threshold { - span_lint(cx, TOO_MANY_ARGUMENTS, span, + span_lint(cx, + TOO_MANY_ARGUMENTS, + span, &format!("this function has to many arguments ({}/{})", args, self.threshold)); } } diff --git a/src/if_not_else.rs b/src/if_not_else.rs index 1a074a723a9..ebc2ce76fec 100644 --- a/src/if_not_else.rs +++ b/src/if_not_else.rs @@ -37,15 +37,15 @@ impl EarlyLintPass for IfNotElse { item.span, "Unnecessary boolean `not` operation", "remove the `!` and swap the blocks of the if/else"); - }, + } ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { span_help_and_lint(cx, IF_NOT_ELSE, item.span, "Unnecessary `!=` operation", "change to `==` and swap the blocks of the if/else"); - }, - _ => {}, + } + _ => (), } } } diff --git a/src/len_zero.rs b/src/len_zero.rs index 3a376d91c92..7a7a17bc79d 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -64,7 +64,7 @@ impl LateLintPass for LenZero { return; } - if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = expr.node { + if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { match cmp { BiEq => check_cmp(cx, expr.span, left, right, ""), BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), @@ -155,7 +155,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { - if let Spanned{node: LitKind::Int(0, _), ..} = *lit { + if let Spanned { node: LitKind::Int(0, _), .. } = *lit { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| { db.span_suggestion(span, @@ -199,7 +199,8 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { .map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))) } ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), - ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), + ty::TyEnum(ref id, _) | + ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), ty::TyArray(..) | ty::TyStr => true, _ => false, } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index ad42a8568e6..67dfabe2569 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -127,7 +127,7 @@ fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, fun match slf.node { SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), - _ => {} + _ => (), } } // extract lifetimes in input argument types @@ -243,7 +243,8 @@ impl<'v, 't> RefVisitor<'v, 't> { if params.lifetimes.is_empty() { if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { match def { - Def::TyAlias(def_id) | Def::Struct(def_id) => { + Def::TyAlias(def_id) | + Def::Struct(def_id) => { let type_scheme = self.cx.tcx.lookup_item_type(def_id); for _ in type_scheme.generics.regions.as_slice() { self.record(&None); @@ -255,7 +256,7 @@ impl<'v, 't> RefVisitor<'v, 't> { self.record(&None); } } - _ => {} + _ => (), } } } @@ -277,7 +278,7 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { TyPath(_, ref path) => { self.collect_anonymous_lifetimes(path, ty); } - _ => {} + _ => (), } walk_ty(self, ty); } @@ -353,7 +354,7 @@ fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics, match slf.node { SelfRegion(Some(ref lt), _, _) => checker.visit_lifetime(lt), SelfExplicit(ref t, _) => walk_ty(&mut checker, t), - _ => {} + _ => (), } } diff --git a/src/loops.rs b/src/loops.rs index f376e28c992..0b341f645df 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -14,8 +14,8 @@ use std::collections::HashMap; use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, - span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, - unsugar_range, walk_ptrs_ty, recover_for_loop}; + span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range, + walk_ptrs_ty, recover_for_loop}; use utils::paths; use utils::UnsugaredRange; @@ -247,7 +247,8 @@ impl LateLintPass for LoopsPass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | MatchSource::IfLetDesugar{..} => { + MatchSource::Normal | + MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_break_expr(&arms[1].body) { @@ -779,7 +780,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { Some(ref expr) => Some(expr), None if !block.stmts.is_empty() => { match block.stmts[0].node { - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => Some(expr), _ => None, } } diff --git a/src/matches.rs b/src/matches.rs index c1692ee47d2..bce93b717a3 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -252,19 +252,20 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if let Some((ref true_expr, ref false_expr)) = exprs { match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => + (false, false) => { Some(format!("if {} {} else {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))), - (false, true) => - Some(format!("if {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."))), - (true, false) => + expr_block(cx, false_expr, None, ".."))) + } + (false, true) => { + Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) + } + (true, false) => { Some(format!("try\nif !{} {}", snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))), + expr_block(cx, false_expr, None, ".."))) + } (true, true) => None, } } else { @@ -312,9 +313,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match expr.span, "you don't need to add `&` to both the expression and the patterns", |db| { - db.span_suggestion(expr.span, - "try", - template); + db.span_suggestion(expr.span, "try", template); }); } else { let template = match_template(cx, expr.span, source, "*", ex); @@ -324,7 +323,8 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match "you don't need to add `&` to all patterns", |db| { db.span_suggestion(expr.span, - "instead of prefixing all patterns with `&`, you can dereference the expression", + "instead of prefixing all patterns with `&`, you can \ + dereference the expression", template); }); } @@ -373,17 +373,18 @@ type TypedRanges = Vec<SpannedRange<ConstInt>>; /// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than /// `Uint` and `Int` probably don't make sense. fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { - ranges.iter().filter_map(|range| { - if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect() + ranges.iter() + .filter_map(|range| { + if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None + } + }) + .collect() } fn is_unit_expr(expr: &Expr) -> bool { @@ -416,7 +417,7 @@ fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, e MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), - MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!") + MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"), } } @@ -432,13 +433,15 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & impl<'a, T: Copy> Kind<'a, T> { fn range(&self) -> &'a SpannedRange<T> { match *self { - Kind::Start(_, r) | Kind::End(_, r) => r, + Kind::Start(_, r) | + Kind::End(_, r) => r, } } fn value(self) -> T { match self { - Kind::Start(t, _) | Kind::End(t, _) => t, + Kind::Start(t, _) | + Kind::End(t, _) => t, } } } diff --git a/src/methods.rs b/src/methods.rs index d2a91b615ae..4a31a564a3e 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -436,7 +436,8 @@ impl LateLintPass for MethodsPass { } let ret_ty = return_ty(cx, implitem.id); - if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { + if &name.as_str() == &"new" && + !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { span_lint(cx, NEW_RET_NO_SELF, sig.explicit_self.span, @@ -946,7 +947,8 @@ impl SelfKind { (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | (&SelfKind::No, &SelfStatic) => true, - (&SelfKind::Ref, &SelfValue(_)) | (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, + (&SelfKind::Ref, &SelfValue(_)) | + (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), _ => false, } diff --git a/src/minmax.rs b/src/minmax.rs index 67299bac998..7cd2d33cab9 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -34,7 +34,9 @@ impl LateLintPass for MinMaxPass { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), + (_, None) | + (MinMax::Max, Some(Ordering::Less)) | + (MinMax::Min, Some(Ordering::Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); } diff --git a/src/misc.rs b/src/misc.rs index 654e6244c1b..7323f18a46e 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -226,7 +226,7 @@ impl LateLintPass for CmpOwned { fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) { let (arg_ty, snip) = match expr.node { - ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) if args.len() == 1 => { + ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => { if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { (cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) } else { @@ -309,7 +309,7 @@ impl LintPass for ModuloOne { impl LateLintPass for ModuloOne { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprBinary(ref cmp, _, ref right) = expr.node { - if let Spanned {node: BinOp_::BiRem, ..} = *cmp { + if let Spanned { node: BinOp_::BiRem, .. } = *cmp { if is_integer_literal(right, 1) { span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } @@ -422,7 +422,8 @@ impl LateLintPass for UsedUnderscoreBinding { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(ref parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + ExprAssign(_, ref rhs) | + ExprAssignOp(_, _, ref rhs) => **rhs == *expr, _ => is_used(cx, &parent), } } else { diff --git a/src/misc_early.rs b/src/misc_early.rs index b1c584a4b3e..b43359f29b9 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -134,11 +134,11 @@ impl EarlyLintPass for MiscEarly { expr.span, "Try not to call a closure in the expression where it is declared.", |db| { - if decl.inputs.is_empty() { - let hint = format!("{}", snippet(cx, block.span, "..")); - db.span_suggestion(expr.span, "Try doing something like: ", hint); - } - }); + if decl.inputs.is_empty() { + let hint = format!("{}", snippet(cx, block.span, "..")); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + } + }); } } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 65e2c3a46a9..7b7b5ecdf4e 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -52,7 +52,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { unwrap_addr(expr).map_or((), |e| { unwrap_addr(e).map_or_else(|| { - if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) = cx.tcx.expr_ty(e).sty { + if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { span_lint(cx, MUT_MUT, expr.span, @@ -71,7 +71,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) { fn unwrap_mut(ty: &Ty) -> Option<&Ty> { match ty.node { - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Some(pty), + TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) => Some(pty), _ => None, } } diff --git a/src/mut_reference.rs b/src/mut_reference.rs index d74c2c41f23..4ac4d83360e 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -47,19 +47,20 @@ impl LateLintPass for UnnecessaryMutPassed { let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); check_arguments(cx, &arguments, method_type.ty, &name.node.as_str()) } - _ => {} + _ => (), } } } fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { match type_definition.sty { - TypeVariants::TyFnDef(_, _, ref fn_type) | TypeVariants::TyFnPtr(ref fn_type) => { + TypeVariants::TyFnDef(_, _, ref fn_type) | + TypeVariants::TyFnPtr(ref fn_type) => { let parameters = &fn_type.sig.skip_binder().inputs; for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | - TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { + TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) | + TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => { if let ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, @@ -67,7 +68,7 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty &format!("The function/method \"{}\" doesn't need a mutable reference", name)); } } - _ => {} + _ => (), } } } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 07da57c684b..f95d6f5c9c1 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -57,9 +57,10 @@ impl LateLintPass for NeedlessBool { span_lint_and_then(cx, NEEDLESS_BOOL, e.span, - "this if-then-else expression returns a bool literal", |db| { - db.span_suggestion(e.span, "you can reduce it to", hint); - }); + "this if-then-else expression returns a bool literal", + |db| { + db.span_suggestion(e.span, "you can reduce it to", hint); + }); }; match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | @@ -98,7 +99,7 @@ impl LintPass for BoolComparison { impl LateLintPass for BoolComparison { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { use self::Expression::*; - if let ExprBinary(Spanned{ node: BiEq, .. }, ref left_side, ref right_side) = e.node { + if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { let hint = snippet(cx, right_side.span, "..").into_owned(); @@ -155,15 +156,17 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { ([], Some(e)) => fetch_bool_expr(&**e), - ([ref e], None) => if let StmtSemi(ref e, _) = e.node { - if let ExprRet(_) = e.node { - fetch_bool_expr(&**e) + ([ref e], None) => { + if let StmtSemi(ref e, _) = e.node { + if let ExprRet(_) = e.node { + fetch_bool_expr(&**e) + } else { + Expression::Other + } } else { Expression::Other } - } else { - Expression::Other - }, + } _ => Expression::Other, } } @@ -177,11 +180,13 @@ fn fetch_bool_expr(expr: &Expr) -> Expression { } else { Expression::Other } - }, - ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { - Expression::Bool(value) => Expression::RetBool(value), - _ => Expression::Other, - }, + } + ExprRet(Some(ref expr)) => { + match fetch_bool_expr(expr) { + Expression::Bool(value) => Expression::RetBool(value), + _ => Expression::Other, + } + } _ => Expression::Other, } } diff --git a/src/no_effect.rs b/src/no_effect.rs index afb49376b3f..d928de41578 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -52,7 +52,8 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } } Expr_::ExprBlock(ref block) => { - block.stmts.is_empty() && if let Some(ref expr) = block.expr { + block.stmts.is_empty() && + if let Some(ref expr) = block.expr { has_no_effect(cx, expr) } else { false diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 36fcc292bfc..a6f0571c499 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -45,7 +45,7 @@ struct ExistingName { interned: InternedString, span: Span, len: usize, - whitelist: &'static[&'static str], + whitelist: &'static [&'static str], } struct SimilarNamesLocalVisitor<'a, 'b: 'a> { @@ -57,6 +57,7 @@ struct SimilarNamesLocalVisitor<'a, 'b: 'a> { // this list contains lists of names that are allowed to be similar // the assumption is that no name is ever contained in multiple lists. +#[cfg_attr(rustfmt, rustfmt_skip)] const WHITELIST: &'static [&'static [&'static str]] = &[ &["parsed", "parser"], &["lhs", "rhs"], @@ -75,7 +76,7 @@ impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> } } -fn get_whitelist(interned_name: &str) -> Option<&'static[&'static str]> { +fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { for &allow in WHITELIST { if whitelisted(interned_name, allow) { return Some(allow); @@ -112,8 +113,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { span_lint(self.0.cx, MANY_SINGLE_CHAR_NAMES, span, - &format!("{}th binding whose name is just one char", - self.0.single_char_names.len())); + &format!("{}th binding whose name is just one char", self.0.single_char_names.len())); } } fn check_name(&mut self, span: Span, name: Name) { @@ -162,7 +162,8 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } else { let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); - if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || + !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { // allowed similarity foo_x, foo_y // or too many chars differ (foo_x, boo_y) or (foox, booy) continue; @@ -172,7 +173,8 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { } else { let second_i = interned_chars.next().expect("we know we have at least two chars"); let second_e = existing_chars.next().expect("we know we have at least two chars"); - if !eq_or_numeric(second_i, second_e) || second_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + if !eq_or_numeric(second_i, second_e) || second_i == '_' || + !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { // allowed similarity x_foo, y_foo // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) continue; @@ -187,10 +189,11 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { |diag| { diag.span_note(existing_name.span, "existing binding defined here"); if let Some(split) = split_at { - diag.span_help(span, &format!("separate the discriminating character \ - by an underscore like: `{}_{}`", - &interned_name[..split], - &interned_name[split..])); + diag.span_help(span, + &format!("separate the discriminating character by an \ + underscore like: `{}_{}`", + &interned_name[..split], + &interned_name[split..])); } }); return; diff --git a/src/open_options.rs b/src/open_options.rs index aaaebe5b2f8..1d760599e3f 100644 --- a/src/open_options.rs +++ b/src/open_options.rs @@ -65,7 +65,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned {node: LitKind::Bool(lit), ..} = **span { + if let Spanned { node: LitKind::Bool(lit), .. } = **span { if lit { Argument::True } else { @@ -96,7 +96,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp "write" => { options.push((OpenOption::Write, argument_option)); } - _ => {} + _ => (), } get_open_options(cx, &arguments[0], options); diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index 627028ad462..6a8ca368fc1 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint}; +use utils::span_lint; /// **What it does:** This lint finds classic underflow / overflow checks. /// diff --git a/src/precedence.rs b/src/precedence.rs index 7e24f55d1b4..825a1b84450 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -31,7 +31,7 @@ impl LintPass for Precedence { impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Binary(Spanned { node: op, ..}, ref left, ref right) = expr.node { + if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { if !is_bit_op(op) { return; } @@ -75,7 +75,9 @@ impl EarlyLintPass for Precedence { if let Some(slf) = args.first() { if let ExprKind::Lit(ref lit) = slf.node { match lit.node { - LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { + LitKind::Int(..) | + LitKind::Float(..) | + LitKind::FloatUnsuffixed(..) => { span_lint(cx, PRECEDENCE, expr.span, @@ -94,7 +96,7 @@ impl EarlyLintPass for Precedence { fn is_arith_expr(expr: &Expr) -> bool { match expr.node { - ExprKind::Binary(Spanned { node: op, ..}, _, _) => is_arith_op(op), + ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op), _ => false, } } diff --git a/src/regex.rs b/src/regex.rs index 177f7a7b045..3bd17a2d365 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -167,14 +167,14 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { match *s { Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), - Expr::Literal {..} => Some("consider using `str::contains`"), + Expr::Literal { .. } => Some("consider using `str::contains`"), Expr::Concat(ref exprs) => { match exprs.len() { 2 => { match (&exprs[0], &exprs[1]) { (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"), - (&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"), + (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), + (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), _ => None, } } diff --git a/src/returns.rs b/src/returns.rs index bb94b59df7d..d7893821263 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -71,7 +71,7 @@ impl ReturnPass { self.check_final_expr(cx, &arm.body); } } - _ => {} + _ => (), } } diff --git a/src/shadow.rs b/src/shadow.rs index 928d447974a..bb287f449e3 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -77,7 +77,8 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)> for stmt in &block.stmts { match stmt.node { StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), + StmtExpr(ref e, _) | + StmtSemi(ref e, _) => check_expr(cx, e, bindings), } } if let Some(ref o) = block.expr { @@ -94,7 +95,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { return; } if let DeclLocal(ref local) = decl.node { - let Local{ ref pat, ref ty, ref init, span, .. } = **local; + let Local { ref pat, ref ty, ref init, span, .. } = **local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } @@ -109,7 +110,8 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { fn is_binding(cx: &LateContext, pat: &Pat) -> bool { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { - Some(Def::Variant(..)) | Some(Def::Struct(..)) => false, + Some(Def::Variant(..)) | + Some(Def::Struct(..)) => false, _ => true, } } @@ -251,7 +253,8 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => check_expr(cx, e, bindings), - ExprBlock(ref block) | ExprLoop(ref block, _) => check_block(cx, block, bindings), + ExprBlock(ref block) | + ExprLoop(ref block, _) => check_block(cx, block, bindings), // ExprCall // ExprMethodCall ExprVec(ref v) | ExprTup(ref v) => { @@ -297,8 +300,8 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { check_ty(cx, fty, bindings); check_expr(cx, expr, bindings); } - TyPtr(MutTy{ ty: ref mty, .. }) | - TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyPtr(MutTy { ty: ref mty, .. }) | + TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) diff --git a/src/strings.rs b/src/strings.rs index a6808d2dd42..92bce8d0e42 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -74,7 +74,7 @@ impl LintPass for StringAdd { impl LateLintPass for StringAdd { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = e.node { + if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { if is_string(cx, left) { if let Allow = cx.current_level(STRING_ADD_ASSIGN) { // the string_add_assign is allow, so no duplicates @@ -112,7 +112,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), + ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) } @@ -145,8 +145,7 @@ impl LateLintPass for StringLitAsBytes { e.span, "calling `as_bytes()` on a string literal", |db| { - let sugg = format!("b{}", - snippet(cx, args[0].span, r#""foo""#)); + let sugg = format!("b{}", snippet(cx, args[0].span, r#""foo""#)); db.span_suggestion(e.span, "consider using a byte string literal instead", sugg); diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs index 44796410458..1496a45dac2 100644 --- a/src/temporary_assignment.rs +++ b/src/temporary_assignment.rs @@ -18,8 +18,7 @@ declare_lint! { fn is_temporary(expr: &Expr) -> bool { match expr.node { - ExprStruct(..) | - ExprTup(..) => true, + ExprStruct(..) | ExprTup(..) => true, _ => false, } } @@ -37,7 +36,8 @@ impl LateLintPass for TemporaryAssignmentPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { - ExprField(ref base, _) | ExprTupField(ref base, _) => { + ExprField(ref base, _) | + ExprTupField(ref base, _) => { if is_temporary(base) && !is_adjusted(cx, base) { span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); } diff --git a/src/transmute.rs b/src/transmute.rs index 8b74b1989db..2217fd59bd9 100644 --- a/src/transmute.rs +++ b/src/transmute.rs @@ -52,11 +52,7 @@ pub struct Transmute; impl LintPass for Transmute { fn get_lints(&self) -> LintArray { - lint_array! [ - CROSSPOINTER_TRANSMUTE, - TRANSMUTE_PTR_TO_REF, - USELESS_TRANSMUTE - ] + lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE] } } @@ -79,12 +75,16 @@ impl LateLintPass for Transmute { span_lint(cx, CROSSPOINTER_TRANSMUTE, e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", + from_ty, + to_ty)); } else if is_ptr_to(from_ty, to_ty) { span_lint(cx, CROSSPOINTER_TRANSMUTE, e.span, - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty)); } else { check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); } @@ -102,10 +102,7 @@ fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { } } -fn check_ptr_to_ref<'tcx>(cx: &LateContext, - from_ty: ty::Ty<'tcx>, - to_ty: ty::Ty<'tcx>, - e: &Expr, arg: &Expr) { +fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) { if let TyRawPtr(ref from_pty) = from_ty.sty { if let TyRef(_, ref to_rty) = to_ty.sty { let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", @@ -122,8 +119,7 @@ fn check_ptr_to_ref<'tcx>(cx: &LateContext, let sugg = if from_pty.ty == to_rty.ty { format!("{}{}", deref, arg) - } - else { + } else { format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) }; diff --git a/src/types.rs b/src/types.rs index 9d12d7970d1..43d42cde501 100644 --- a/src/types.rs +++ b/src/types.rs @@ -248,7 +248,8 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { fn is_isize_or_usize(typ: &ty::TyS) -> bool { match typ.sty { - ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, + ty::TyInt(IntTy::Is) | + ty::TyUint(UintTy::Us) => true, _ => false, } } @@ -536,9 +537,7 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { fn visit_ty(&mut self, ty: &'v Ty) { let (add_score, sub_nest) = match ty.node { // _, &x and *x have only small overhead; don't mess with nesting level - TyInfer | - TyPtr(..) | - TyRptr(..) => (1, 0), + TyInfer | TyPtr(..) | TyRptr(..) => (1, 0), // the "normal" components of a type: named types, arrays/tuples TyPath(..) | @@ -663,17 +662,17 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs Some(match rel { Rel::Lt => { match (lx, rx) { - (Some(l @ Extr { which: Maximum, ..}), _) => (l, AlwaysFalse), // max < x - (_, Some(r @ Extr { which: Minimum, ..})) => (r, AlwaysFalse), // x < min + (Some(l @ Extr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x + (_, Some(r @ Extr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min _ => return None, } } Rel::Le => { match (lx, rx) { - (Some(l @ Extr { which: Minimum, ..}), _) => (l, AlwaysTrue), // min <= x - (Some(l @ Extr { which: Maximum, ..}), _) => (l, InequalityImpossible), //max <= x - (_, Some(r @ Extr { which: Minimum, ..})) => (r, InequalityImpossible), // x <= min - (_, Some(r @ Extr { which: Maximum, ..})) => (r, AlwaysTrue), // x <= max + (Some(l @ Extr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x + (Some(l @ Extr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x + (_, Some(r @ Extr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min + (_, Some(r @ Extr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max _ => return None, } } @@ -702,14 +701,12 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx let which = match (ty, cv) { (&ty::TyBool, Bool(false)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | @@ -718,14 +715,12 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum, (&ty::TyBool, Bool(true)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | @@ -845,22 +840,26 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( use syntax::ast::{IntTy, UintTy}; use std::*; - if let ExprCast(ref cast_exp,_) = expr.node { + if let ExprCast(ref cast_exp, _) = expr.node { match cx.tcx.expr_ty(cast_exp).sty { - TyInt(int_ty) => Some(match int_ty { - IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), - IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), - IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), - IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), - IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), - }), - TyUint(uint_ty) => Some(match uint_ty { - UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), - UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), - UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), - UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), - UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), - }), + TyInt(int_ty) => { + Some(match int_ty { + IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), + IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), + IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), + IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), + IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), + }) + } + TyUint(uint_ty) => { + Some(match uint_ty { + UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), + UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), + UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), + UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), + UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), + }) + } _ => None, } } else { @@ -885,29 +884,26 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { } else { None } - }, + } Err(_) => None, } } fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { if let ExprCast(ref cast_val, _) = expr.node { - span_lint( - cx, - INVALID_UPCAST_COMPARISONS, - *span, - &format!( + span_lint(cx, + INVALID_UPCAST_COMPARISONS, + *span, + &format!( "because of the numeric bounds on `{}` prior to casting, this expression is always {}", snippet(cx, cast_val.span, "the expression"), if always { "true" } else { "false" }, - ) - ); + )); } } -fn upcast_comparison_bounds_err( - cx: &LateContext, span: &Span, rel: comparisons::Rel, - lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { +fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons::Rel, + lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { use utils::comparisons::*; if let Some((lb, ub)) = lhs_bounds { @@ -917,14 +913,38 @@ fn upcast_comparison_bounds_err( err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => if invert { norm_rhs_val < lb } else { ub < norm_rhs_val }, - Rel::Le => if invert { norm_rhs_val <= lb } else { ub <= norm_rhs_val }, + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } + } + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } + } Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, true) } else if match rel { - Rel::Lt => if invert { norm_rhs_val >= ub } else { lb >= norm_rhs_val }, - Rel::Le => if invert { norm_rhs_val > ub } else { lb > norm_rhs_val }, + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } + } + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } + } Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, &span, lhs, false) diff --git a/src/utils/conf.rs b/src/utils/conf.rs index 74a68d2d730..e773cc0e025 100644 --- a/src/utils/conf.rs +++ b/src/utils/conf.rs @@ -8,7 +8,8 @@ use toml; pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { for arg in args { match arg.node { - ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { + ast::MetaItemKind::Word(ref name) | + ast::MetaItemKind::List(ref name, _) => { if name == &"conf_file" { return Err(("`conf_file` must be a named value", arg.span)); } diff --git a/src/utils/hir.rs b/src/utils/hir.rs index f6fa2176941..379812a283d 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -76,7 +76,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) } (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), @@ -114,9 +116,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) } (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { - self.eq_path(l_path, r_path) && - both(lo, ro, |l, r| self.eq_expr(l, r)) && - over(lf, rf, |l, r| self.eq_field(l, r)) + self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && + over(lf, rf, |l, r| self.eq_field(l, r)) } (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d01b0698de8..d8f5a0757b7 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -144,7 +144,8 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { /// Check if type is struct or enum type with given def path. pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { match ty.sty { - ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), + ty::TyEnum(ref adt, _) | + ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), _ => false, } } @@ -304,9 +305,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { let parent_id = cx.tcx.map.get_parent(expr.id); match cx.tcx.map.find(parent_id) { - Some(Node::NodeItem(&Item{ ref name, .. })) | - Some(Node::NodeTraitItem(&TraitItem{ ref name, .. })) | - Some(Node::NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), + Some(Node::NodeItem(&Item { ref name, .. })) | + Some(Node::NodeTraitItem(&TraitItem { ref name, .. })) | + Some(Node::NodeImplItem(&ImplItem { ref name, .. })) => Some(*name), _ => None, } } @@ -431,7 +432,7 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c if let Some(node) = enclosing_node { match node { Node::NodeBlock(ref block) => Some(block), - Node::NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), + Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), _ => None, } } else { @@ -517,7 +518,8 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), + ty::TyRef(_, ref tm) | + ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), _ => ty, } } @@ -526,7 +528,8 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { match ty.sty { - ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), + ty::TyRef(_, ref tm) | + ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), _ => (ty, depth), } } @@ -730,22 +733,46 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { match unwrap_unstable(&expr).node { ExprPath(None, ref path) => { if match_path(path, &paths::RANGE_FULL) { - Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) + Some(UnsugaredRange { + start: None, + end: None, + limits: RangeLimits::HalfOpen, + }) } else { None } } ExprStruct(ref path, ref fields, None) => { if match_path(path, &paths::RANGE_FROM) { - Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) + Some(UnsugaredRange { + start: get_field("start", fields), + end: None, + limits: RangeLimits::HalfOpen, + }) } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { - Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) + Some(UnsugaredRange { + start: get_field("start", fields), + end: get_field("end", fields), + limits: RangeLimits::Closed, + }) } else if match_path(path, &paths::RANGE) { - Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + Some(UnsugaredRange { + start: get_field("start", fields), + end: get_field("end", fields), + limits: RangeLimits::HalfOpen, + }) } else if match_path(path, &paths::RANGE_TO_INCLUSIVE) { - Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) + Some(UnsugaredRange { + start: None, + end: get_field("end", fields), + limits: RangeLimits::Closed, + }) } else if match_path(path, &paths::RANGE_TO) { - Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) + Some(UnsugaredRange { + start: None, + end: get_field("end", fields), + limits: RangeLimits::HalfOpen, + }) } else { None } diff --git a/src/vec.rs b/src/vec.rs index 513efa1a2a4..63b9952c3c8 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -63,8 +63,7 @@ fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) { }; format!("&[{}]", snippet(cx, span, "..")).into() - } - else { + } else { "&[]".into() } } -- cgit 1.4.1-3-g733a5 From d6073eb54ed338d49cdb1d76c538c07c45d80deb Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 14 Apr 2016 21:24:46 +0200 Subject: Fix regex tests --- .travis.yml | 9 +++++++-- tests/compile-test.rs | 12 ++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f727555bd7..1bc48b0b002 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,13 @@ script: - rm -rf target/ Cargo.lock - cargo test --features debugging - # only test regex_macros if it compiles - - if [[ "$(cargo build --features 'debugging test-regex_macros')" = 101 ]]; then cargo test --features 'debugging test-regex_macros'; fi + - # only test regex_macros if it compiles + - | + #!/bin/bash + cargo test --no-run --features 'debugging test-regex_macros' + if [ "$?" = 101 ]; then + cargo test --features 'debugging test-regex_macros' + fi # trigger rebuild of the clippy-service, to keep it up to date with clippy itself after_success: diff --git a/tests/compile-test.rs b/tests/compile-test.rs index ff2d94d2777..6dcd1ff0524 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,7 +3,7 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; use std::env::var; -fn run_mode(mode: &'static str) { +fn run_mode(dir: &'static str, mode: &'static str) { let mut config = compiletest::default_config(); let cfg_mode = mode.parse().ok().expect("Invalid mode"); @@ -14,7 +14,7 @@ fn run_mode(mode: &'static str) { } config.mode = cfg_mode; - config.src_base = PathBuf::from(format!("tests/{}", mode)); + config.src_base = PathBuf::from(format!("tests/{}", dir)); compiletest::run_tests(&config); } @@ -22,13 +22,13 @@ fn run_mode(mode: &'static str) { #[test] #[cfg(not(feature = "test-regex_macros"))] fn compile_test() { - run_mode("run-pass"); - run_mode("compile-fail"); + run_mode("run-pass", "run-pass"); + run_mode("compile-fail", "compile-fail"); } #[test] #[cfg(feature = "test-regex_macros")] fn compile_test() { - run_mode("run-pass-regex_macros"); - run_mode("compile-fail-regex_macros"); + run_mode("run-pass-regex_macros", "run-pass"); + run_mode("compile-fail-regex_macros", "compile-fail"); } -- cgit 1.4.1-3-g733a5 From 578cc3dc71134594da58a606acce1ef03883fee3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 15 Apr 2016 00:09:37 +0200 Subject: Fix the `REGEX_MACRO` lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [rust-lang-nursery/regex#183](https://github.com/rust-lang-nursery/regex/pull/183) has made the following change that broke the lint: src/re.rs → src/re_unicode.rs --- src/regex.rs | 7 +++---- src/utils/paths.rs | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/regex.rs b/src/regex.rs index 3bd17a2d365..72a33757027 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -9,8 +9,7 @@ use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; -use utils::paths; -use utils::{is_expn_of, match_path, match_type, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_path, match_type, paths, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// @@ -73,8 +72,8 @@ impl LateLintPass for RegexPass { if_let_chain!{[ self.last.is_none(), let Some(ref expr) = block.expr, - match_type(cx, cx.tcx.expr_ty(expr), &["regex", "re", "Regex"]), - let Some(span) = is_expn_of(cx, expr.span, "regex") + match_type(cx, cx.tcx.expr_ty(expr), &paths::REGEX), + let Some(span) = is_expn_of(cx, expr.span, "regex"), ], { if !self.spans.contains(&span) { span_lint(cx, diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 1777c31ef8c..88d0dd415aa 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -29,6 +29,7 @@ pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["std", "ops", "RangeIn pub const RANGE: [&'static str; 3] = ["std", "ops", "Range"]; pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; pub const RANGE_TO: [&'static str; 3] = ["std", "ops", "RangeTo"]; +pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_NEW: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; -- cgit 1.4.1-3-g733a5 From 72b747915c5173a493b58aad1c2292256a85250e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 15 Apr 2016 01:41:06 +0200 Subject: Fix .travis.yml again --- .travis.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1bc48b0b002..f72ac01bc3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,16 +13,15 @@ script: - rm -rf target/ Cargo.lock - cargo test --features debugging - - # only test regex_macros if it compiles - - | +after_success: +# only test regex_macros if it compiles +- | #!/bin/bash cargo test --no-run --features 'debugging test-regex_macros' - if [ "$?" = 101 ]; then - cargo test --features 'debugging test-regex_macros' + if [ "$?" != 101 ]; then + cargo test --features 'debugging test-regex_macros' compile_test fi - # trigger rebuild of the clippy-service, to keep it up to date with clippy itself -after_success: - | #!/bin/bash set -e -- cgit 1.4.1-3-g733a5 From 12b8a0ac148f7fa3120ba99b61b24c5601a7afcf Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Sun, 17 Apr 2016 12:52:38 +0200 Subject: Make if_not_else lint Allow by default (fixes #859) --- README.md | 2 +- src/if_not_else.rs | 2 +- src/lib.rs | 2 +- tests/compile-fail/entry.rs | 2 +- tests/compile-fail/if_not_else.rs | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) mode change 100644 => 100755 tests/compile-fail/entry.rs mode change 100644 => 100755 tests/compile-fail/if_not_else.rs diff --git a/README.md b/README.md index c7cee794db4..80d26cdede0 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ name [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | warn | finds if branches that could be swapped so no negation operation is necessary on the condition +[if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | allow | finds if branches that could be swapped so no negation operation is necessary on the condition [if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks [ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition [indexing_slicing](https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage diff --git a/src/if_not_else.rs b/src/if_not_else.rs index ebc2ce76fec..2fc2cc10e38 100644 --- a/src/if_not_else.rs +++ b/src/if_not_else.rs @@ -14,7 +14,7 @@ use utils::span_help_and_lint; /// /// **Example:** if !v.is_empty() { a() } else { b() } declare_lint! { - pub IF_NOT_ELSE, Warn, + pub IF_NOT_ELSE, Allow, "finds if branches that could be swapped so no negation operation is necessary on the condition" } diff --git a/src/lib.rs b/src/lib.rs index c1a7732e3f5..0f005152239 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -237,6 +237,7 @@ pub fn plugin_registrar(reg: &mut Registry) { array_indexing::INDEXING_SLICING, booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, + if_not_else::IF_NOT_ELSE, matches::SINGLE_MATCH_ELSE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, @@ -289,7 +290,6 @@ pub fn plugin_registrar(reg: &mut Registry) { formatting::SUSPICIOUS_ELSE_FORMATTING, functions::TOO_MANY_ARGUMENTS, identity_op::IDENTITY_OP, - if_not_else::IF_NOT_ELSE, items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs old mode 100644 new mode 100755 index e65ef503ba5..7dc4054ec5b --- a/tests/compile-fail/entry.rs +++ b/tests/compile-fail/entry.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused, if_not_else)] +#![allow(unused)] #![deny(map_entry)] diff --git a/tests/compile-fail/if_not_else.rs b/tests/compile-fail/if_not_else.rs old mode 100644 new mode 100755 index eb716e4599a..a72699adafd --- a/tests/compile-fail/if_not_else.rs +++ b/tests/compile-fail/if_not_else.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] #![deny(clippy)] +#![deny(if_not_else)] fn bla() -> bool { unimplemented!() } -- cgit 1.4.1-3-g733a5 From 0bc067089eae3011b92aed71191a48bf2b9a0d58 Mon Sep 17 00:00:00 2001 From: llogiq <bogusandre@gmail.com> Date: Sun, 17 Apr 2016 23:33:21 +0200 Subject: add neg_multiply lint (#862) add neg_multiply lint --- CHANGELOG.md | 1 + README.md | 3 +- src/consts.rs | 3 +- src/lib.rs | 3 ++ src/neg_multiply.rs | 57 ++++++++++++++++++++++++++++++++++++++ tests/compile-fail/neg_multiply.rs | 40 ++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/neg_multiply.rs create mode 100644 tests/compile-fail/neg_multiply.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 2493ae2502d..d02136421ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,7 @@ All notable changes to this project will be documented in this file. [`needless_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop [`needless_return`]: https://github.com/Manishearth/rust-clippy/wiki#needless_return [`needless_update`]: https://github.com/Manishearth/rust-clippy/wiki#needless_update +[`neg_multiply`]: https://github.com/Manishearth/rust-clippy/wiki#neg_multiply [`new_ret_no_self`]: https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self [`new_without_default`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default [`no_effect`]: https://github.com/Manishearth/rust-clippy/wiki#no_effect diff --git a/README.md b/README.md index 80d26cdede0..3951418eade 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 141 lints included in this crate: +There are 142 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -95,6 +95,7 @@ name [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice [needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `{ ..base }` when there are no missing fields +[neg_multiply](https://github.com/Manishearth/rust-clippy/wiki#neg_multiply) | warn | Warns on multiplying integers with -1 [new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method [new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect diff --git a/src/consts.rs b/src/consts.rs index 0eed34a8055..4a5f457ed7d 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -177,8 +177,9 @@ impl PartialOrd for Constant { } } +/// parse a `LitKind` to a `Constant` #[allow(cast_possible_wrap)] -fn lit_to_constant(lit: &LitKind) -> Constant { +pub fn lit_to_constant(lit: &LitKind) -> Constant { match *lit { LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), diff --git a/src/lib.rs b/src/lib.rs index 0f005152239..6d98cf55f09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ pub mod mut_reference; pub mod mutex_atomic; pub mod needless_bool; pub mod needless_update; +pub mod neg_multiply; pub mod new_without_default; pub mod no_effect; pub mod non_expressive_names; @@ -232,6 +233,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); + reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -343,6 +345,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_update::NEEDLESS_UPDATE, + neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, non_expressive_names::MANY_SINGLE_CHAR_NAMES, diff --git a/src/neg_multiply.rs b/src/neg_multiply.rs new file mode 100644 index 00000000000..fb986409a41 --- /dev/null +++ b/src/neg_multiply.rs @@ -0,0 +1,57 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::{Span, Spanned}; + +use consts::{self, Constant}; +use utils::span_lint; + +/// **What it does:** Checks for multiplication by -1 as a form of negation. +/// +/// **Why is this bad?** It's more readable to just negate. +/// +/// **Known problems:** This only catches integers (for now) +/// +/// **Example:** `x * -1` +declare_lint! { + pub NEG_MULTIPLY, + Warn, + "Warns on multiplying integers with -1" +} + +#[derive(Copy, Clone)] +pub struct NegMultiply; + +impl LintPass for NegMultiply { + fn get_lints(&self) -> LintArray { + lint_array!(NEG_MULTIPLY) + } +} + +#[allow(match_same_arms)] +impl LateLintPass for NegMultiply { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { + match (&l.node, &r.node) { + (&ExprUnary(..), &ExprUnary(..)) => (), + (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), + (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), + _ => () + } + } + } +} + +fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { + if_let_chain!([ + let ExprLit(ref l) = lit.node, + let Constant::Int(ref ci) = consts::lit_to_constant(&l.node), + let Some(val) = ci.to_u64(), + val == 1, + cx.tcx.expr_ty(exp).is_integral() + ], { + span_lint(cx, + NEG_MULTIPLY, + span, + "Negation by multiplying with -1"); + }) +} diff --git a/tests/compile-fail/neg_multiply.rs b/tests/compile-fail/neg_multiply.rs new file mode 100644 index 00000000000..9deb38920de --- /dev/null +++ b/tests/compile-fail/neg_multiply.rs @@ -0,0 +1,40 @@ +#![feature(plugin)] + +#![plugin(clippy)] +#![deny(neg_multiply)] +#![allow(no_effect)] + +use std::ops::Mul; + +struct X; + +impl Mul<isize> for X { + type Output = X; + + fn mul(self, _r: isize) -> Self { + self + } +} + +impl Mul<X> for isize { + type Output = X; + + fn mul(self, _r: X) -> X { + X + } +} + +fn main() { + let x = 0; + + x * -1; + //~^ ERROR Negation by multiplying with -1 + + -1 * x; + //~^ ERROR Negation by multiplying with -1 + + -1 * -1; // should be ok + + X * -1; // should be ok + -1 * X; // should also be ok +} -- cgit 1.4.1-3-g733a5 From 038f528f452e35a5d586898c878b3b69fd8ff539 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Tue, 19 Apr 2016 16:27:01 -0700 Subject: Added lint for use imports which remove unsafe from name --- src/lib.rs | 3 + src/unsafe_removed_from_name.rs | 90 ++++++++++++++++++++++++++ tests/compile-fail/unsafe_removed_from_name.rs | 12 ++++ 3 files changed, 105 insertions(+) create mode 100644 src/unsafe_removed_from_name.rs create mode 100644 tests/compile-fail/unsafe_removed_from_name.rs diff --git a/src/lib.rs b/src/lib.rs index 6d98cf55f09..eee091e6195 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,6 +109,7 @@ pub mod transmute; pub mod types; pub mod unicode; pub mod unused_label; +pub mod unsafe_removed_from_name; pub mod vec; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -234,6 +235,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); reg.register_late_lint_pass(box neg_multiply::NegMultiply); + reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -379,6 +381,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_label::UNUSED_LABEL, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); diff --git a/src/unsafe_removed_from_name.rs b/src/unsafe_removed_from_name.rs new file mode 100644 index 00000000000..86860c67cfe --- /dev/null +++ b/src/unsafe_removed_from_name.rs @@ -0,0 +1,90 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::ast::{Name, NodeId}; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use utils::span_lint; + +/// **What it does:** This lint checks for imports that remove "unsafe" from an item's name +/// +/// **Why is this bad?** Renaming makes it less clear which traits and structures are unsafe. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// use std::cell::{UnsafeCell as TotallySafeCell}; +/// +/// extern crate crossbeam; +/// use crossbeam::{spawn_unsafe as spawn}; +/// ``` +declare_lint! { + pub UNSAFE_REMOVED_FROM_NAME, + Warn, + "unsafe removed from name" +} + +pub struct UnsafeNameRemoval; + +impl LintPass for UnsafeNameRemoval { + fn get_lints(&self) -> LintArray { + lint_array!(UNSAFE_REMOVED_FROM_NAME) + } +} + +impl LateLintPass for UnsafeNameRemoval { + fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) { + // only check top level `use` statements + for item in &m.item_ids { + self.lint_item(cx, cx.krate.item(item.id)); + } + } +} + +impl UnsafeNameRemoval { + fn lint_item(&self, cx: &LateContext, item: &Item) { + if let ItemUse(ref item_use) = item.node { + match item_use.node { + ViewPath_::ViewPathSimple(ref name, ref path) => { + unsafe_to_safe_check( + path.segments + .last() + .expect("use paths cannot be empty") + .identifier.name, + *name, + cx, &item.span + ); + }, + ViewPath_::ViewPathList(_, ref path_list_items) => { + for path_list_item in path_list_items.iter() { + let plid = path_list_item.node; + if let (Some(name), Some(rename)) = (plid.name(), plid.rename()) { + unsafe_to_safe_check(name, rename, cx, &item.span); + }; + } + }, + ViewPath_::ViewPathGlob(_) => {} + } + } + } +} + +fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: &Span) { + let old_str = old_name.as_str(); + let new_str = new_name.as_str(); + if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { + span_lint( + cx, + UNSAFE_REMOVED_FROM_NAME, + *span, + &format!( + "removed \"unsafe\" from the name of `{}` in use as `{}`", + old_str, + new_str + )); + } +} + +fn contains_unsafe(name: &InternedString) -> bool { + name.contains("Unsafe") || name.contains("unsafe") +} diff --git a/tests/compile-fail/unsafe_removed_from_name.rs b/tests/compile-fail/unsafe_removed_from_name.rs new file mode 100644 index 00000000000..facdb2c64ed --- /dev/null +++ b/tests/compile-fail/unsafe_removed_from_name.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(unused_imports)] +#![deny(unsafe_removed_from_name)] + +use std::cell::{UnsafeCell as TotallySafeCell}; +//~^ ERROR removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell` + +use std::cell::UnsafeCell as TotallySafeCellAgain; +//~^ ERROR removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` + +fn main() {} -- cgit 1.4.1-3-g733a5 From b793ad7f2f1cb193422094bf23e2ca1fb93335c8 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Tue, 19 Apr 2016 16:32:04 -0700 Subject: Ran update_lints script --- CHANGELOG.md | 1 + README.md | 3 ++- src/lib.rs | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d02136421ec..d15f85251b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -198,6 +198,7 @@ All notable changes to this project will be documented in this file. [`unit_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#unit_cmp [`unnecessary_mut_passed`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed [`unneeded_field_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern +[`unsafe_removed_from_name`]: https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name [`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice [`unstable_as_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice [`unused_collect`]: https://github.com/Manishearth/rust-clippy/wiki#unused_collect diff --git a/README.md b/README.md index 3951418eade..6aa1e1ecf34 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 142 lints included in this crate: +There are 143 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -146,6 +146,7 @@ name [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference [unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` +[unsafe_removed_from_name](https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name) | warn | unsafe removed from name [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop [unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions diff --git a/src/lib.rs b/src/lib.rs index eee091e6195..5774f3bf7af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,8 +108,8 @@ pub mod temporary_assignment; pub mod transmute; pub mod types; pub mod unicode; -pub mod unused_label; pub mod unsafe_removed_from_name; +pub mod unused_label; pub mod vec; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -380,8 +380,8 @@ pub fn plugin_registrar(reg: &mut Registry) { types::TYPE_COMPLEXITY, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, - unused_label::UNUSED_LABEL, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + unused_label::UNUSED_LABEL, vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); -- cgit 1.4.1-3-g733a5 From 4be11e911662706ffa353225434cd8bd05ea9677 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Tue, 19 Apr 2016 21:41:45 -0700 Subject: Removed unnecessary restriction of unsafe_removed_from_name to top-level use statements --- src/unsafe_removed_from_name.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/unsafe_removed_from_name.rs b/src/unsafe_removed_from_name.rs index 86860c67cfe..404d6d93604 100644 --- a/src/unsafe_removed_from_name.rs +++ b/src/unsafe_removed_from_name.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use syntax::ast::{Name, NodeId}; +use syntax::ast::Name; use syntax::codemap::Span; use syntax::parse::token::InternedString; use utils::span_lint; @@ -33,16 +33,7 @@ impl LintPass for UnsafeNameRemoval { } impl LateLintPass for UnsafeNameRemoval { - fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) { - // only check top level `use` statements - for item in &m.item_ids { - self.lint_item(cx, cx.krate.item(item.id)); - } - } -} - -impl UnsafeNameRemoval { - fn lint_item(&self, cx: &LateContext, item: &Item) { + fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemUse(ref item_use) = item.node { match item_use.node { ViewPath_::ViewPathSimple(ref name, ref path) => { -- cgit 1.4.1-3-g733a5 From 84a480b02b4946d650f833bdc1ecc9e0ea13f702 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Tue, 19 Apr 2016 21:52:10 -0700 Subject: Expanded tests for unsafe_removed_from_name --- tests/compile-fail/unsafe_removed_from_name.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/compile-fail/unsafe_removed_from_name.rs b/tests/compile-fail/unsafe_removed_from_name.rs index facdb2c64ed..3e5f6e58c90 100644 --- a/tests/compile-fail/unsafe_removed_from_name.rs +++ b/tests/compile-fail/unsafe_removed_from_name.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] #![allow(unused_imports)] +#![allow(dead_code)] #![deny(unsafe_removed_from_name)] use std::cell::{UnsafeCell as TotallySafeCell}; @@ -9,4 +10,23 @@ use std::cell::{UnsafeCell as TotallySafeCell}; use std::cell::UnsafeCell as TotallySafeCellAgain; //~^ ERROR removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` +// Shouldn't error +use std::cell::{UnsafeCell as SuperDangerousUnsafeCell}; +use std::cell::{UnsafeCell as Dangerunsafe}; +use std::cell::UnsafeCell as Bombsawayunsafe; +use std::cell::{RefCell as ProbablyNotUnsafe}; +use std::cell::RefCell as RefCellThatCantBeUnsafe; + +mod mod_with_some_unsafe_things { + pub struct Safe {} + pub struct Unsafe {} +} + +use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; +//~^ ERROR removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` + +// Shouldn't error +use mod_with_some_unsafe_things::Safe as IPromiseItsSafeThisTime; +use mod_with_some_unsafe_things::Unsafe as SuperUnsafeModThing; + fn main() {} -- cgit 1.4.1-3-g733a5 From ed65b259ffb67babc36d621b3e2989eed3ab0853 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 09:27:12 -0700 Subject: Added unsafe_removed_from_name to new list in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d15f85251b2..272f5d77f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased -* New lint: [`temporary_cstring_as_ptr`] +* New lint: [`temporary_cstring_as_ptr`] and [`unsafe_removed_from_name`] ## 0.0.63 — 2016-04-08 * Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)* -- cgit 1.4.1-3-g733a5 From de9a80cd102021c05ad0352369abe5bdf38ab57d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 20 Apr 2016 21:09:38 +0200 Subject: Check type for `SINGLE_CHAR_PATTERN` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’d be nicer to actually check for `Pattern` bounds but in the meantime this needs to be fixed. --- src/methods.rs | 20 +++++++++++++------- tests/compile-fail/methods.rs | 4 ++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 4a31a564a3e..73f6a7aa4b0 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -365,16 +365,23 @@ impl LateLintPass for MethodsPass { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); } - lint_or_fun_call(cx, expr, &name.node.as_str(), &args); + + let self_ty = cx.tcx.expr_ty_adjusted(&args[0]); if args.len() == 1 && name.node.as_str() == "clone" { lint_clone_on_copy(cx, expr); - lint_clone_double_ref(cx, expr, &args[0]); + lint_clone_double_ref(cx, expr, &args[0], self_ty); } - for &(method, pos) in &PATTERN_METHODS { - if name.node.as_str() == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); + + match self_ty.sty { + ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => { + for &(method, pos) in &PATTERN_METHODS { + if name.node.as_str() == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); + } + } } + _ => (), } } ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { @@ -552,8 +559,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &Expr) { } /// Checks for the `CLONE_DOUBLE_REF` lint. -fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr) { - let ty = cx.tcx.expr_ty(arg); +fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr, ty: ty::Ty) { if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { if let ty::TyRef(..) = inner.sty { let mut db = span_lint(cx, diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 1869fd12a69..7503cb50746 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -6,6 +6,7 @@ use std::collections::BTreeMap; use std::collections::HashMap; +use std::collections::HashSet; use std::ops::Mul; struct T; @@ -469,6 +470,9 @@ fn single_char_pattern() { //~^ ERROR single-character string constant used as pattern //~| HELP try using a char instead: //~| SUGGESTION x.trim_right_matches('x'); + + let h = HashSet::<String>::new(); + h.contains("X"); // should not warn } #[allow(result_unwrap_used)] -- cgit 1.4.1-3-g733a5 From 447940c889d92b9cfa436a8c7fb964b1e1e4803a Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 13:10:23 -0700 Subject: Added lint for mem_forget --- src/lib.rs | 3 +++ src/mem_forget.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/utils/paths.rs | 1 + tests/compile-fail/mem_forget.rs | 21 +++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 src/mem_forget.rs create mode 100644 tests/compile-fail/mem_forget.rs diff --git a/src/lib.rs b/src/lib.rs index 5774f3bf7af..07a142060cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ pub mod len_zero; pub mod lifetimes; pub mod loops; pub mod map_clone; +pub mod mem_forget; pub mod matches; pub mod methods; pub mod minmax; @@ -236,6 +237,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); + reg.register_late_lint_pass(box mem_forget::MemForget); reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, @@ -243,6 +245,7 @@ pub fn plugin_registrar(reg: &mut Registry) { enum_glob_use::ENUM_GLOB_USE, if_not_else::IF_NOT_ELSE, matches::SINGLE_MATCH_ELSE, + mem_forget::MEM_FORGET, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, diff --git a/src/mem_forget.rs b/src/mem_forget.rs new file mode 100644 index 00000000000..836c60f84a9 --- /dev/null +++ b/src/mem_forget.rs @@ -0,0 +1,38 @@ +use rustc::lint::*; +use rustc::hir::{Expr, ExprCall, ExprPath}; +use utils::{match_def_path, paths, span_lint}; + +/// **What it does:** This lint checks for usage of `std::mem::forget(_)`. +/// +/// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its destructor, possibly causing leaks +/// +/// **Known problems:** None. +/// +/// **Example:** `std::mem::forget(_))` +declare_lint! { + pub MEM_FORGET, + Allow, + "std::mem::forget usage is likely to cause memory leaks" +} + +pub struct MemForget; + +impl LintPass for MemForget { + fn get_lints(&self) -> LintArray { + lint_array![MEM_FORGET] + } +} + +impl LateLintPass for MemForget { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprCall(ref path_expr, _) = e.node { + if let ExprPath(None, _) = path_expr.node { + let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + + if match_def_path(cx, def_id, &paths::MEM_FORGET) { + span_lint(cx, MEM_FORGET, e.span, "usage of std::mem::forget"); + } + } + } + } +} diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 88d0dd415aa..38985373085 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -20,6 +20,7 @@ pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "Ha pub const HASH: [&'static str; 2] = ["hash", "Hash"]; pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; diff --git a/tests/compile-fail/mem_forget.rs b/tests/compile-fail/mem_forget.rs new file mode 100644 index 00000000000..1b9cc810f96 --- /dev/null +++ b/tests/compile-fail/mem_forget.rs @@ -0,0 +1,21 @@ +#![feature(plugin)] +#![plugin(clippy)] + +use std::sync::Arc; + +use std::mem::forget as forgetSomething; +use std::mem as memstuff; + +#[deny(mem_forget)] +fn main() { + let five: i32 = 5; + forgetSomething(five); + //~^ ERROR usage of std::mem::forget + + let six: Arc<i32> = Arc::new(6); + memstuff::forget(six); + //~^ ERROR usage of std::mem::forget + + std::mem::forget(7); + //~^ ERROR usage of std::mem::forget +} -- cgit 1.4.1-3-g733a5 From 7961f59303a0829f0724b236cad0cbb001930d9c Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 13:11:55 -0700 Subject: Ran update_lints and updated CHANGELOG.md to reflect addition of mem_forget --- CHANGELOG.md | 3 ++- README.md | 3 ++- src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 272f5d77f35..0ad943c3f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased -* New lint: [`temporary_cstring_as_ptr`] and [`unsafe_removed_from_name`] +* New lints: [`temporary_cstring_as_ptr`], [`unsafe_removed_from_name`], and [`mem_forget`] ## 0.0.63 — 2016-04-08 * Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)* @@ -135,6 +135,7 @@ All notable changes to this project will be documented in this file. [`match_overlapping_arm`]: https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm [`match_ref_pats`]: https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats [`match_same_arms`]: https://github.com/Manishearth/rust-clippy/wiki#match_same_arms +[`mem_forget`]: https://github.com/Manishearth/rust-clippy/wiki#mem_forget [`min_max`]: https://github.com/Manishearth/rust-clippy/wiki#min_max [`modulo_one`]: https://github.com/Manishearth/rust-clippy/wiki#modulo_one [`mut_mut`]: https://github.com/Manishearth/rust-clippy/wiki#mut_mut diff --git a/README.md b/README.md index 6aa1e1ecf34..7b7a74cca4c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 143 lints included in this crate: +There are 144 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -85,6 +85,7 @@ name [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead [match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies +[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | std::mem::forget usage is likely to cause memory leaks [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) diff --git a/src/lib.rs b/src/lib.rs index 07a142060cb..5f3b3999f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,8 +78,8 @@ pub mod len_zero; pub mod lifetimes; pub mod loops; pub mod map_clone; -pub mod mem_forget; pub mod matches; +pub mod mem_forget; pub mod methods; pub mod minmax; pub mod misc; -- cgit 1.4.1-3-g733a5 From 12ae306630f5029d0c3c7b52fa7532f5a2f308da Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 13:33:05 -0700 Subject: Ticks around std::mem::forget --- README.md | 2 +- src/mem_forget.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7b7a74cca4c..8e8a2627557 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ name [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead [match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | std::mem::forget usage is likely to cause memory leaks +[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `std::mem::forget` usage is likely to cause memory leaks [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) diff --git a/src/mem_forget.rs b/src/mem_forget.rs index 836c60f84a9..651e56d709f 100644 --- a/src/mem_forget.rs +++ b/src/mem_forget.rs @@ -12,7 +12,7 @@ use utils::{match_def_path, paths, span_lint}; declare_lint! { pub MEM_FORGET, Allow, - "std::mem::forget usage is likely to cause memory leaks" + "`std::mem::forget` usage is likely to cause memory leaks" } pub struct MemForget; -- cgit 1.4.1-3-g733a5 From 5158a08c5b048a5e9ce094d4999db8cb6f13ab44 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 18:55:41 -0700 Subject: Changed std::mem::forget errors to mem::forget --- README.md | 2 +- src/mem_forget.rs | 6 +++--- tests/compile-fail/mem_forget.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8e8a2627557..0a4f83ffee6 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ name [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead [match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `std::mem::forget` usage is likely to cause memory leaks +[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage is likely to cause memory leaks [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) diff --git a/src/mem_forget.rs b/src/mem_forget.rs index 651e56d709f..d857adf10d6 100644 --- a/src/mem_forget.rs +++ b/src/mem_forget.rs @@ -8,11 +8,11 @@ use utils::{match_def_path, paths, span_lint}; /// /// **Known problems:** None. /// -/// **Example:** `std::mem::forget(_))` +/// **Example:** `mem::forget(_))` declare_lint! { pub MEM_FORGET, Allow, - "`std::mem::forget` usage is likely to cause memory leaks" + "`mem::forget` usage is likely to cause memory leaks" } pub struct MemForget; @@ -30,7 +30,7 @@ impl LateLintPass for MemForget { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); if match_def_path(cx, def_id, &paths::MEM_FORGET) { - span_lint(cx, MEM_FORGET, e.span, "usage of std::mem::forget"); + span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget"); } } } diff --git a/tests/compile-fail/mem_forget.rs b/tests/compile-fail/mem_forget.rs index 1b9cc810f96..5198b4ea8d3 100644 --- a/tests/compile-fail/mem_forget.rs +++ b/tests/compile-fail/mem_forget.rs @@ -10,12 +10,12 @@ use std::mem as memstuff; fn main() { let five: i32 = 5; forgetSomething(five); - //~^ ERROR usage of std::mem::forget + //~^ ERROR usage of mem::forget let six: Arc<i32> = Arc::new(6); memstuff::forget(six); - //~^ ERROR usage of std::mem::forget + //~^ ERROR usage of mem::forget std::mem::forget(7); - //~^ ERROR usage of std::mem::forget + //~^ ERROR usage of mem::forget } -- cgit 1.4.1-3-g733a5 From 77427b6ead79c54648c47f5048953590a59615bb Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Wed, 20 Apr 2016 19:24:31 -0700 Subject: Limited mem_forget error to only Drop types (fails) --- src/mem_forget.rs | 19 ++++++++++++------- tests/compile-fail/mem_forget.rs | 13 ++++++++++--- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/mem_forget.rs b/src/mem_forget.rs index d857adf10d6..0568e70023a 100644 --- a/src/mem_forget.rs +++ b/src/mem_forget.rs @@ -1,18 +1,18 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{match_def_path, paths, span_lint}; +use utils::{get_trait_def_id, implements_trait, match_def_path, paths, span_lint}; -/// **What it does:** This lint checks for usage of `std::mem::forget(_)`. +/// **What it does:** This lint checks for usage of `std::mem::forget(t)` where `t` is `Drop`. /// /// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its destructor, possibly causing leaks /// /// **Known problems:** None. /// -/// **Example:** `mem::forget(_))` +/// **Example:** `mem::forget(Rc::new(55)))` declare_lint! { pub MEM_FORGET, Allow, - "`mem::forget` usage is likely to cause memory leaks" + "`mem::forget` usage on `Drop` types is likely to cause memory leaks" } pub struct MemForget; @@ -25,12 +25,17 @@ impl LintPass for MemForget { impl LateLintPass for MemForget { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprCall(ref path_expr, _) = e.node { + if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if match_def_path(cx, def_id, &paths::MEM_FORGET) { - span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget"); + if let Some(drop_trait_id) = get_trait_def_id(cx, &paths::DROP) { + let forgot_ty = cx.tcx.expr_ty(&args[0]); + + if implements_trait(cx, forgot_ty, drop_trait_id, Vec::new()) { + span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); + } + } } } } diff --git a/tests/compile-fail/mem_forget.rs b/tests/compile-fail/mem_forget.rs index 5198b4ea8d3..c8cebcb2a42 100644 --- a/tests/compile-fail/mem_forget.rs +++ b/tests/compile-fail/mem_forget.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] use std::sync::Arc; +use std::rc::Rc; use std::mem::forget as forgetSomething; use std::mem as memstuff; @@ -10,12 +11,18 @@ use std::mem as memstuff; fn main() { let five: i32 = 5; forgetSomething(five); - //~^ ERROR usage of mem::forget let six: Arc<i32> = Arc::new(6); memstuff::forget(six); - //~^ ERROR usage of mem::forget + //~^ ERROR usage of mem::forget on Drop type + + let seven: Rc<i32> = Rc::new(7); + std::mem::forget(seven); + //~^ ERROR usage of mem::forget on Drop type + + let eight: Vec<i32> = vec![8]; + forgetSomething(eight); + //~^ ERROR usage of mem::forget on Drop type std::mem::forget(7); - //~^ ERROR usage of mem::forget } -- cgit 1.4.1-3-g733a5 From 8866ba9e2a744c5f033e7d1f5b0298da77550b91 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Thu, 21 Apr 2016 09:36:39 -0700 Subject: Fixed destructor detection in mem_forget --- src/mem_forget.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mem_forget.rs b/src/mem_forget.rs index 0568e70023a..1f627d614ff 100644 --- a/src/mem_forget.rs +++ b/src/mem_forget.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{get_trait_def_id, implements_trait, match_def_path, paths, span_lint}; +use utils::{match_def_path, paths, span_lint}; /// **What it does:** This lint checks for usage of `std::mem::forget(t)` where `t` is `Drop`. /// @@ -29,12 +29,13 @@ impl LateLintPass for MemForget { if let ExprPath(None, _) = path_expr.node { let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); if match_def_path(cx, def_id, &paths::MEM_FORGET) { - if let Some(drop_trait_id) = get_trait_def_id(cx, &paths::DROP) { - let forgot_ty = cx.tcx.expr_ty(&args[0]); + let forgot_ty = cx.tcx.expr_ty(&args[0]); - if implements_trait(cx, forgot_ty, drop_trait_id, Vec::new()) { - span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); - } + if match forgot_ty.ty_adt_def() { + Some(def) => def.has_dtor(), + _ => false + } { + span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } } } -- cgit 1.4.1-3-g733a5 From 1e2cc78e08b2a119a3d69a82e24234fabdeee019 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@cs.washington.edu> Date: Thu, 21 Apr 2016 09:41:38 -0700 Subject: Ran script to update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a4f83ffee6..d55536c033d 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ name [match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match has overlapping arms [match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` has all arms prefixed with `&`; the match expression can be dereferenced instead [match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage is likely to cause memory leaks +[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage on `Drop` types is likely to cause memory leaks [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, or shows a fundamental misunderstanding of references) -- cgit 1.4.1-3-g733a5 From efb541743953f417ab0b10e79c962cbd83ab6875 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 22 Apr 2016 18:06:35 +0200 Subject: Fix grammar. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d55536c033d..80d5c282556 100644 --- a/README.md +++ b/README.md @@ -266,7 +266,7 @@ You can also specify the path to the configuration file with: Both projects are independent and maintained by different people (even if some `clippy-service`'s contributions are authored by some `rust-clippy` members). -You can check it out this great service at [clippy.bashy.io](https://clippy.bashy.io/). +You can check out this great service at [clippy.bashy.io](https://clippy.bashy.io/). ##License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From e3d86800ffae3a88c1284d9bcfd45405f08e807a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sat, 23 Apr 2016 07:50:46 +0200 Subject: allow items_after_statements by default --- README.md | 2 +- src/items_after_statements.rs | 2 +- src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 80d5c282556..59724457ac1 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ name [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations [invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an upcast which is always true or false -[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | warn | finds blocks where an item comes after a statement +[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 952dcb7ed9c..9d8ae2e9913 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -28,7 +28,7 @@ use utils::in_macro; /// ``` declare_lint! { pub ITEMS_AFTER_STATEMENTS, - Warn, + Allow, "finds blocks where an item comes after a statement" } diff --git a/src/lib.rs b/src/lib.rs index 5f3b3999f95..14d1a19f262 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,6 +244,7 @@ pub fn plugin_registrar(reg: &mut Registry) { booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, if_not_else::IF_NOT_ELSE, + items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, methods::OPTION_UNWRAP_USED, @@ -297,7 +298,6 @@ pub fn plugin_registrar(reg: &mut Registry) { formatting::SUSPICIOUS_ELSE_FORMATTING, functions::TOO_MANY_ARGUMENTS, identity_op::IDENTITY_OP, - items_after_statements::ITEMS_AFTER_STATEMENTS, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, lifetimes::NEEDLESS_LIFETIMES, -- cgit 1.4.1-3-g733a5 From bf4221c51a54294482e437c803a7b1f9c37dbcd8 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Sat, 23 Apr 2016 14:30:05 +0200 Subject: cc: early returns are special --- src/cyclomatic_complexity.rs | 37 +++++++++++++------ tests/compile-fail/cyclomatic_complexity.rs | 57 +++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index e8a3a569a14..9b20cc4a312 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -9,7 +9,7 @@ use syntax::ast::Attribute; use syntax::attr; use syntax::codemap::Span; -use utils::{in_macro, LimitStack, span_help_and_lint}; +use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; /// **What it does:** This lint checks for methods with high cyclomatic complexity /// @@ -57,15 +57,26 @@ impl CyclomaticComplexity { match_arms: 0, divergence: 0, short_circuits: 0, + returns: 0, tcx: &cx.tcx, }; helper.visit_block(block); - let CCHelper { match_arms, divergence, short_circuits, .. } = helper; + let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; + let ret_ty = cx.tcx.node_id_to_type(block.id); + let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { + returns + } else { + returns / 2 + }; - if cc + divergence < match_arms + short_circuits { - report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span); + if cc + divergence < match_arms + short_circuits { + report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span); } else { - let rust_cc = cc + divergence - match_arms - short_circuits; + let mut rust_cc = cc + divergence - match_arms - short_circuits; + // prevent degenerate cases where unreachable code contains `return` statements + if rust_cc >= ret_adjust { + rust_cc -= ret_adjust; + } if rust_cc > self.limit.limit() { span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, @@ -109,6 +120,7 @@ impl LateLintPass for CyclomaticComplexity { struct CCHelper<'a, 'tcx: 'a> { match_arms: u64, divergence: u64, + returns: u64, short_circuits: u64, // && and || tcx: &'a ty::TyCtxt<'tcx>, } @@ -142,31 +154,34 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { _ => (), } } + ExprRet(_) => self.returns += 1, _ => walk_expr(self, e), } } } #[cfg(feature="debugging")] -fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { +fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { span_bug!(span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}. Please file a bug report.", + div = {}, shorts = {}, returns = {}. Please file a bug report.", cc, narms, div, - shorts); + shorts, + returns); } #[cfg(not(feature="debugging"))] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { cx.sess().span_note_without_error(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ - = {}, arms = {}, div = {}, shorts = {}. Please file a bug report.", + = {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.", cc, narms, div, - shorts)); + shorts, + returns)); } } diff --git a/tests/compile-fail/cyclomatic_complexity.rs b/tests/compile-fail/cyclomatic_complexity.rs index 4b24f16eda7..2160272bf46 100644 --- a/tests/compile-fail/cyclomatic_complexity.rs +++ b/tests/compile-fail/cyclomatic_complexity.rs @@ -315,3 +315,60 @@ fn mcarton_sees_all() { panic!("meh"); panic!("möh"); } + +#[cyclomatic_complexity = "0"] +fn try() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1 + match 5 { + 5 => Ok(5), + _ => return Err("bla"), + } +} + +#[cyclomatic_complexity = "0"] +fn try_again() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1 + let _ = try!(Ok(42)); + let _ = try!(Ok(43)); + let _ = try!(Ok(44)); + let _ = try!(Ok(45)); + let _ = try!(Ok(46)); + let _ = try!(Ok(47)); + let _ = try!(Ok(48)); + let _ = try!(Ok(49)); + match 5 { + 5 => Ok(5), + _ => return Err("bla"), + } +} + +#[cyclomatic_complexity = "0"] +fn early() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1 + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); + return Ok(5); +} + +#[cyclomatic_complexity = "0"] +fn early_ret() -> i32 { //~ ERROR: cyclomatic complexity of 8 + let a = if true { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + let a = if a < 99 { 42 } else { return 0; }; + match 5 { + 5 => 5, + _ => return 6, + } +} -- cgit 1.4.1-3-g733a5 From c3d75ad80d949be1cdb7c5a6c20d9134df677070 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 24 Apr 2016 17:15:54 +0530 Subject: Improve new_without_default docs --- src/new_without_default.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/new_without_default.rs b/src/new_without_default.rs index f42b1d0d74a..46021ec8836 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -6,10 +6,13 @@ use syntax::codemap::Span; use utils::paths; use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint}; -/// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default` -/// implementation. +/// **What it does:** This lints about type with a `fn new() -> Self` method +/// and no implementation of +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) /// -/// **Why is this bad?** User might expect to be able to use `Default` as the type can be +/// **Why is this bad?** User might expect to be able to use +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// as the type can be /// constructed without arguments. /// /// **Known problems:** Hopefully none. @@ -25,6 +28,21 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, sa /// } /// } /// ``` +/// +/// Instead, use: +/// +/// ```rust +/// struct Foo; +/// +/// impl Default for Foo { +/// fn default() -> Self { +/// Foo +/// } +/// } +/// ``` +/// +/// You can also have `new()` call `Default::default()` +/// declare_lint! { pub NEW_WITHOUT_DEFAULT, Warn, -- cgit 1.4.1-3-g733a5 From 08818de9b7f0a51bf71fc863ae7798be9e19b1c5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 26 Apr 2016 02:01:49 +0530 Subject: Rustup to rustc 1.10.0-nightly (645dd013a 2016-04-24); release 0.0.64 --- Cargo.toml | 2 +- src/block_in_if_condition.rs | 2 +- src/eta_reduction.rs | 2 +- src/map_clone.rs | 2 +- src/misc_early.rs | 4 ++-- src/utils/hir.rs | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b55ab8d2271..5a8968ac2f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.63" +version = "0.0.64" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index 1a2123fe00a..cdaf53684c5 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -43,7 +43,7 @@ struct ExVisitor<'v> { impl<'v> Visitor<'v> for ExVisitor<'v> { fn visit_expr(&mut self, expr: &'v Expr) { - if let ExprClosure(_, _, ref block) = expr.node { + if let ExprClosure(_, _, ref block, _) = expr.node { let complex = { if block.stmts.is_empty() { if let Some(ref ex) = block.expr { diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 83abe215aa7..c9a9ef85ede 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -40,7 +40,7 @@ impl LateLintPass for EtaPass { } fn check_closure(cx: &LateContext, expr: &Expr) { - if let ExprClosure(_, ref decl, ref blk) = expr.node { + if let ExprClosure(_, ref decl, ref blk, _) = expr.node { if !blk.stmts.is_empty() { // || {foo(); bar()}; can't be reduced here return; diff --git a/src/map_clone.rs b/src/map_clone.rs index caefb64eb5f..1cfa339d4a0 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -25,7 +25,7 @@ impl LateLintPass for MapClonePass { if let ExprMethodCall(name, _, ref args) = expr.node { if name.node.as_str() == "map" && args.len() == 2 { match args[1].node { - ExprClosure(_, ref decl, ref blk) => { + ExprClosure(_, ref decl, ref blk, _) => { if_let_chain! { [ // just one expression in the closure diff --git a/src/misc_early.rs b/src/misc_early.rs index b43359f29b9..a7ab59497ac 100644 --- a/src/misc_early.rs +++ b/src/misc_early.rs @@ -128,7 +128,7 @@ impl EarlyLintPass for MiscEarly { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Call(ref paren, _) = expr.node { if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block) = closure.node { + if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { span_lint_and_then(cx, REDUNDANT_CLOSURE_CALL, expr.span, @@ -150,7 +150,7 @@ impl EarlyLintPass for MiscEarly { let StmtKind::Decl(ref first, _) = w[0].node, let DeclKind::Local(ref local) = first.node, let Option::Some(ref t) = local.init, - let ExprKind::Closure(_,_,_) = t.node, + let ExprKind::Closure(_,_,_,_) = t.node, let PatKind::Ident(_,sp_ident,_) = local.pat.node, let StmtKind::Semi(ref second,_) = w[1].node, let ExprKind::Assign(_,ref call) = second.node, diff --git a/src/utils/hir.rs b/src/utils/hir.rs index 379812a283d..fe4c6d30952 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -333,8 +333,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); // TODO: _ty } - ExprClosure(cap, _, ref b) => { - let c: fn(_, _, _) -> _ = ExprClosure; + ExprClosure(cap, _, ref b, _) => { + let c: fn(_, _, _, _) -> _ = ExprClosure; c.hash(&mut self.s); cap.hash(&mut self.s); self.hash_block(b); -- cgit 1.4.1-3-g733a5 From cf5c1ab0b6ce335525ed5a71af1b8b7df637abe0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 26 Apr 2016 13:31:52 +0200 Subject: Fix paths resolution Put more paths into the `utils::paths` module. --- src/loops.rs | 14 ++++++------- src/map_clone.rs | 2 +- src/methods.rs | 4 ++-- src/minmax.rs | 6 +++--- src/ranges.rs | 13 +++++++----- src/utils/mod.rs | 49 ++++++++++++++++++++++++++++----------------- src/utils/paths.rs | 37 ++++++++++++++++++++++++---------- tests/compile-fail/range.rs | 2 ++ 8 files changed, 80 insertions(+), 47 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index 0b341f645df..70abb7a1aac 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -285,7 +285,7 @@ impl LateLintPass for LoopsPass { let iter_expr = &method_args[0]; if let Some(lhs_constructor) = path.segments.last() { if method_name.node.as_str() == "next" && - match_trait_method(cx, match_expr, &["core", "iter", "Iterator"]) && + match_trait_method(cx, match_expr, &paths::ITERATOR) && lhs_constructor.identifier.name.as_str() == "Some" && !is_iterator_used_after_while_let(cx, iter_expr) { let iterator = snippet(cx, method_args[0].span, "_"); @@ -305,7 +305,7 @@ impl LateLintPass for LoopsPass { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.node.as_str() == "collect" && - match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + match_trait_method(cx, expr, &paths::ITERATOR) { span_lint(cx, UNUSED_COLLECT, expr.span, @@ -488,7 +488,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { object, method_name)); } - } else if method_name.as_str() == "next" && match_trait_method(cx, arg, &["core", "iter", "Iterator"]) { + } else if method_name.as_str() == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { span_lint(cx, ITER_NEXT_LOOP, expr.span, @@ -739,11 +739,11 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::HASHMAP) || - match_type(cx, ty, &["std", "collections", "hash", "set", "HashSet"]) || - match_type(cx, ty, &["collections", "vec_deque", "VecDeque"]) || - match_type(cx, ty, &["collections", "binary_heap", "BinaryHeap"]) || + match_type(cx, ty, &paths::HASHSET) || + match_type(cx, ty, &paths::VEC_DEQUE) || + match_type(cx, ty, &paths::BINARY_HEAP) || match_type(cx, ty, &paths::BTREEMAP) || - match_type(cx, ty, &["collections", "btree", "set", "BTreeSet"]) + match_type(cx, ty, &paths::BTREESET) } fn is_iterable_array(ty: ty::Ty) -> bool { diff --git a/src/map_clone.rs b/src/map_clone.rs index 1cfa339d4a0..1a0620d8834 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -96,7 +96,7 @@ fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { } fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { - if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + if match_trait_method(cx, expr, &paths::ITERATOR) { Some("iterator") } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) { Some("Option") diff --git a/src/methods.rs b/src/methods.rs index 73f6a7aa4b0..e25154bd38b 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -752,7 +752,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, /// lint use of `filter().next() for Iterators` fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { // lint if caller of `.filter().next()` is an Iterator - if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) { + if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ instead."; let filter_snippet = snippet(cx, filter_args[1].span, ".."); @@ -776,7 +776,7 @@ fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, search_args: &MethodArgs, is_some_args: &MethodArgs) { // lint if caller of search is an Iterator - if match_trait_method(cx, &*is_some_args[0], &["core", "iter", "Iterator"]) { + if match_trait_method(cx, &*is_some_args[0], &paths::ITERATOR) { let msg = format!("called `is_some()` after searching an iterator with {}. This is more succinctly expressed \ by calling `any()`.", search_method); diff --git a/src/minmax.rs b/src/minmax.rs index 7cd2d33cab9..eaba19b08e4 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::hir::*; use std::cmp::{PartialOrd, Ordering}; use syntax::ptr::P; -use utils::{match_def_path, span_lint}; +use utils::{match_def_path, paths, span_lint}; /// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. /// @@ -57,9 +57,9 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' if let ExprPath(None, _) = path.node { let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); - if match_def_path(cx, def_id, &["core", "cmp", "min"]) { + if match_def_path(cx, def_id, &paths::CMP_MIN) { fetch_const(args, MinMax::Min) - } else if match_def_path(cx, def_id, &["core", "cmp", "max"]) { + } else if match_def_path(cx, def_id, &paths::CMP_MAX) { fetch_const(args, MinMax::Max) } else { None diff --git a/src/ranges.rs b/src/ranges.rs index c2555da1d0b..e96212a9cef 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Spanned; -use utils::{is_integer_literal, match_type, snippet, span_lint, unsugar_range, UnsugaredRange}; +use utils::{is_integer_literal, match_type, paths, snippet, span_lint, unsugar_range, UnsugaredRange}; /// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. /// @@ -39,7 +39,7 @@ impl LateLintPass for StepByZero { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { // Range with step_by(0). - if name.as_str() == "step_by" && args.len() == 2 && is_range(cx, &args[0]) && + if name.as_str() == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) && is_integer_literal(&args[1], 0) { span_lint(cx, RANGE_STEP_BY_ZERO, @@ -77,10 +77,13 @@ impl LateLintPass for StepByZero { } } -fn is_range(cx: &LateContext, expr: &Expr) -> bool { +fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { // No need for walk_ptrs_ty here because step_by moves self, so it // can't be called on a borrowed range. let ty = cx.tcx.expr_ty(expr); - // Note: RangeTo and RangeFull don't have step_by - match_type(cx, ty, &["core", "ops", "Range"]) || match_type(cx, ty, &["core", "ops", "RangeFrom"]) + + // Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by + match_type(cx, ty, &paths::RANGE) + || match_type(cx, ty, &paths::RANGE_FROM) + || match_type(cx, ty, &paths::RANGE_INCLUSIVE) } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d8f5a0757b7..83247a59174 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -122,23 +122,33 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { /// ``` /// match_def_path(cx, id, &["core", "option", "Option"]) /// ``` +/// +/// See also the `paths` module. pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - let krate = &cx.tcx.crate_name(def_id.krate); - if krate != &path[0] { - return false; + use syntax::parse::token; + + struct AbsolutePathBuffer { + names: Vec<token::InternedString>, } - let path = &path[1..]; - let other = cx.tcx.def_path(def_id).data; + impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { + fn root_mode(&self) -> &ty::item_path::RootMode { + const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; + ABSOLUTE + } - if other.len() != path.len() { - return false; + fn push(&mut self, text: &str) { + self.names.push(token::intern(text).as_str()); + } } - other.into_iter() - .map(|e| e.data) - .zip(path) - .all(|(nm, p)| nm.as_interned_str() == *p) + let mut apb = AbsolutePathBuffer { + names: vec![], + }; + + cx.tcx.push_item_path(&mut apb, def_id); + + apb.names == path } /// Check if type is struct or enum type with given def path. @@ -730,9 +740,12 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { Some(unwrap_unstable(expr)) } - match unwrap_unstable(&expr).node { + // The range syntax is expanded to literal paths starting with `core` or `std` depending on + // `#[no_std]`. Testing both instead of resolving the paths. + + match unwrap_unstable(expr).node { ExprPath(None, ref path) => { - if match_path(path, &paths::RANGE_FULL) { + if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { Some(UnsugaredRange { start: None, end: None, @@ -743,31 +756,31 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { } } ExprStruct(ref path, ref fields, None) => { - if match_path(path, &paths::RANGE_FROM) { + if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { + } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed, }) - } else if match_path(path, &paths::RANGE) { + } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_TO_INCLUSIVE) { + } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed, }) - } else if match_path(path, &paths::RANGE_TO) { + } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { Some(UnsugaredRange { start: None, end: get_field("end", fields), diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 38985373085..7da75c3cd55 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -1,12 +1,16 @@ //! This module contains paths to types and functions Clippy needs to know about. pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; -pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; +pub const BINARY_HEAP: [&'static str; 3] = ["collections", "binary_heap", "BinaryHeap"]; pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; -pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; +pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; +pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; +pub const BTREESET: [&'static str; 4] = ["collections", "btree", "set", "BTreeSet"]; pub const CLONE: [&'static str; 3] = ["clone", "Clone", "clone"]; pub const CLONE_TRAIT: [&'static str; 2] = ["clone", "Clone"]; +pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; +pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"]; pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"]; pub const CSTRING_NEW: [&'static str; 4] = ["std", "ffi", "CString", "new"]; pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; @@ -15,25 +19,36 @@ pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Display", "fmt pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; -pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; -pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASH: [&'static str; 2] = ["hash", "Hash"]; +pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; +pub const ITERATOR: [&'static str; 4] = ["core", "iter", "iterator", "Iterator"]; pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; -pub const RANGE_FROM: [&'static str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&'static str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; -pub const RANGE: [&'static str; 3] = ["std", "ops", "Range"]; -pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; -pub const RANGE_TO: [&'static str; 3] = ["std", "ops", "RangeTo"]; +pub const RANGE: [&'static str; 3] = ["core", "ops", "Range"]; +pub const RANGE_FROM: [&'static str; 3] = ["core", "ops", "RangeFrom"]; +pub const RANGE_FROM_STD: [&'static str; 3] = ["std", "ops", "RangeFrom"]; +pub const RANGE_FULL: [&'static str; 3] = ["core", "ops", "RangeFull"]; +pub const RANGE_FULL_STD: [&'static str; 3] = ["std", "ops", "RangeFull"]; +pub const RANGE_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeInclusive"]; +pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["core", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE_INCLUSIVE_NON_EMPTY_STD: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeInclusive"]; +pub const RANGE_STD: [&'static str; 3] = ["std", "ops", "Range"]; +pub const RANGE_TO: [&'static str; 3] = ["core", "ops", "RangeTo"]; +pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclusive"]; +pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; +pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_NEW: [&'static str; 3] = ["regex", "Regex", "new"]; pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; -pub const VEC_FROM_ELEM: [&'static str; 3] = ["std", "vec", "from_elem"]; pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const VEC_DEQUE: [&'static str; 3] = ["collections", "vec_deque", "VecDeque"]; +pub const VEC_FROM_ELEM: [&'static str; 3] = ["std", "vec", "from_elem"]; diff --git a/tests/compile-fail/range.rs b/tests/compile-fail/range.rs index 064d9f55173..fc12155ce9c 100644 --- a/tests/compile-fail/range.rs +++ b/tests/compile-fail/range.rs @@ -1,4 +1,5 @@ #![feature(step_by)] +#![feature(inclusive_range_syntax)] #![feature(plugin)] #![plugin(clippy)] @@ -14,6 +15,7 @@ fn main() { (0..1).step_by(1); (1..).step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator + (1...2).step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator let x = 0..1; x.step_by(0); //~ERROR Range::step_by(0) produces an infinite iterator -- cgit 1.4.1-3-g733a5 From 0664394a4901d0af7717ebf6abd99330ce301ab9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 26 Apr 2016 13:43:23 +0200 Subject: Centralize more paths --- src/map_clone.rs | 2 +- src/utils/paths.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/map_clone.rs b/src/map_clone.rs index 1a0620d8834..d015a165457 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -51,7 +51,7 @@ impl LateLintPass for MapClonePass { else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { if clone_call.node.as_str() == "clone" && clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) && + match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && expr_eq_ident(&clone_args[0], arg_ident) { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 7da75c3cd55..c52324a7448 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -7,8 +7,8 @@ pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREESET: [&'static str; 4] = ["collections", "btree", "set", "BTreeSet"]; -pub const CLONE: [&'static str; 3] = ["clone", "Clone", "clone"]; -pub const CLONE_TRAIT: [&'static str; 2] = ["clone", "Clone"]; +pub const CLONE: [&'static str; 4] = ["core", "clone", "Clone", "clone"]; +pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"]; pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"]; pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"]; -- cgit 1.4.1-3-g733a5 From ffd9f5a3ac23fbc264290d365f76df17195c7493 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 26 Apr 2016 15:08:09 +0200 Subject: Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ad943c3f8a..37cdcc571a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## Unreleased +## 0.0.64 — 2016-04-26 +* Rustup to *rustc 1.10.0-nightly (645dd013a 2016-04-24)* * New lints: [`temporary_cstring_as_ptr`], [`unsafe_removed_from_name`], and [`mem_forget`] ## 0.0.63 — 2016-04-08 -- cgit 1.4.1-3-g733a5 From 9a99979cc4653fc54008590314028da36b7f21f0 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sat, 30 Apr 2016 04:01:47 +0200 Subject: fix #887: New lints for integer/floating-point arithmetic --- CHANGELOG.md | 2 + README.md | 4 +- src/arithmetic.rs | 104 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++ tests/compile-fail/arithmetic.rs | 31 ++++++++++++ 5 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/arithmetic.rs create mode 100644 tests/compile-fail/arithmetic.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 37cdcc571a0..6c51e5595a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,7 @@ All notable changes to this project will be documented in this file. [`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop [`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice [`filter_next`]: https://github.com/Manishearth/rust-clippy/wiki#filter_next +[`float_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic [`float_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#float_cmp [`for_kv_map`]: https://github.com/Manishearth/rust-clippy/wiki#for_kv_map [`for_loop_over_option`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option @@ -118,6 +119,7 @@ All notable changes to this project will be documented in this file. [`indexing_slicing`]: https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing [`ineffective_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask [`inline_always`]: https://github.com/Manishearth/rust-clippy/wiki#inline_always +[`integer_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic [`invalid_regex`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_regex [`invalid_upcast_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons [`items_after_statements`]: https://github.com/Manishearth/rust-clippy/wiki#items_after_statements diff --git a/README.md b/README.md index 59724457ac1..3b0ca3f4a38 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Table of contents: * [License](#license) ##Lints -There are 144 lints included in this crate: +There are 146 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -56,6 +56,7 @@ name [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` +[float_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic) | allow | Any floating-point arithmetic statement [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) [for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` @@ -67,6 +68,7 @@ name [indexing_slicing](https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases +[integer_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic) | allow | Any integer arithmetic statement [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations [invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement diff --git a/src/arithmetic.rs b/src/arithmetic.rs new file mode 100644 index 00000000000..72375f4a15e --- /dev/null +++ b/src/arithmetic.rs @@ -0,0 +1,104 @@ +use rustc::hir; +use rustc::lint::*; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** This lint checks for plain integer arithmetic +/// +/// **Why is this bad?** This is only checked against overflow in debug builds. +/// In some applications one wants explicitly checked, wrapping or saturating +/// arithmetic. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// a + 1 +/// ``` +declare_lint! { + pub INTEGER_ARITHMETIC, + Allow, + "Any integer arithmetic statement" +} + +/// **What it does:** This lint checks for float arithmetic +/// +/// **Why is this bad?** For some embedded systems or kernel development, it +/// can be useful to rule out floating-point numbers +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// a + 1.0 +/// ``` +declare_lint! { + pub FLOAT_ARITHMETIC, + Allow, + "Any floating-point arithmetic statement" +} + +#[derive(Copy, Clone, Default)] +pub struct Arithmetic { + span: Option<Span> +} + +impl LintPass for Arithmetic { + fn get_lints(&self) -> LintArray { + lint_array!(INTEGER_ARITHMETIC, FLOAT_ARITHMETIC) + } +} + +impl LateLintPass for Arithmetic { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + if let Some(_) = self.span { return; } + match expr.node { + hir::ExprBinary(ref op, ref l, ref r) => { + match op.node { + hir::BiRem | hir::BiAnd | hir::BiOr | hir::BiBitAnd | + hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | + hir::BiGt => return, + _ => () + } + let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r)); + if l_ty.is_integral() && r_ty.is_integral() { + span_lint(cx, + INTEGER_ARITHMETIC, + expr.span, + "integer arithmetic detected"); + self.span = Some(expr.span); + } else if l_ty.is_floating_point() && r_ty.is_floating_point() { + span_lint(cx, + FLOAT_ARITHMETIC, + expr.span, + "floating-point arithmetic detected"); + self.span = Some(expr.span); + } + }, + hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { + let ty = cx.tcx.expr_ty(arg); + if ty.is_integral() { + span_lint(cx, + INTEGER_ARITHMETIC, + expr.span, + "integer arithmetic detected"); + self.span = Some(expr.span); + } else if ty.is_floating_point() { + span_lint(cx, + FLOAT_ARITHMETIC, + expr.span, + "floating-point arithmetic detected"); + self.span = Some(expr.span); + } + }, + _ => () + } + } + + fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) { + if Some(expr.span) == self.span { + self.span = None; + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 14d1a19f262..584ae7f77eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ #![feature(question_mark)] #![feature(stmt_expr_attributes)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] +#![allow(float_arithmetic, integer_arithmetic)] // this only exists to allow the "dogfood" integration test to work #[allow(dead_code)] @@ -49,6 +50,7 @@ pub mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; +pub mod arithmetic; pub mod array_indexing; pub mod attrs; pub mod bit_mask; @@ -238,8 +240,11 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_forget::MemForget); + reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); reg.register_lint_group("clippy_pedantic", vec![ + arithmetic::FLOAT_ARITHMETIC, + arithmetic::INTEGER_ARITHMETIC, array_indexing::INDEXING_SLICING, booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, diff --git a/tests/compile-fail/arithmetic.rs b/tests/compile-fail/arithmetic.rs new file mode 100644 index 00000000000..856f390943b --- /dev/null +++ b/tests/compile-fail/arithmetic.rs @@ -0,0 +1,31 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(integer_arithmetic, float_arithmetic)] +#![allow(unused, shadow_reuse, shadow_unrelated, no_effect)] +fn main() { + let i = 1i32; + 1 + i; //~ERROR integer arithmetic detected + i * 2; //~ERROR integer arithmetic detected + 1 % //~ERROR integer arithmetic detected + i / 2; + i - 2 + 2 - i; //~ERROR integer arithmetic detected + -i; //~ERROR integer arithmetic detected + + i & 1; // no wrapping + i | 1; + i ^ 1; + i % 7; + i >> 1; + i << 1; + + let f = 1.0f32; + + f * 2.0; //~ERROR floating-point arithmetic detected + + 1.0 + f; //~ERROR floating-point arithmetic detected + f * 2.0; //~ERROR floating-point arithmetic detected + f / 2.0; //~ERROR floating-point arithmetic detected + f - 2.0 * 4.2; //~ERROR floating-point arithmetic detected + -f; //~ERROR floating-point arithmetic detected +} -- cgit 1.4.1-3-g733a5 From a96744018670a29b926ee084779a1333c2542915 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sat, 30 Apr 2016 17:11:59 +0200 Subject: lint remainder, document test w/ half expr --- src/arithmetic.rs | 2 +- tests/compile-fail/arithmetic.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 72375f4a15e..6f34fdc2427 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -55,7 +55,7 @@ impl LateLintPass for Arithmetic { match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiRem | hir::BiAnd | hir::BiOr | hir::BiBitAnd | + hir::BiAnd | hir::BiOr | hir::BiBitAnd | hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, diff --git a/tests/compile-fail/arithmetic.rs b/tests/compile-fail/arithmetic.rs index 856f390943b..3b9e1b8b85a 100644 --- a/tests/compile-fail/arithmetic.rs +++ b/tests/compile-fail/arithmetic.rs @@ -8,7 +8,7 @@ fn main() { 1 + i; //~ERROR integer arithmetic detected i * 2; //~ERROR integer arithmetic detected 1 % //~ERROR integer arithmetic detected - i / 2; + i / 2; // no error, this is part of the expression in the preceding line i - 2 + 2 - i; //~ERROR integer arithmetic detected -i; //~ERROR integer arithmetic detected -- cgit 1.4.1-3-g733a5 From 0b40ae178a4e3dfa8ec5312562cf473adea3989e Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sat, 30 Apr 2016 23:54:10 +0200 Subject: fixed tests, added clippy_restrictions lint group --- src/arithmetic.rs | 26 ++++++++++++-------------- src/lib.rs | 11 ++++++++++- tests/compile-fail/arithmetic.rs | 1 - util/update_lints.py | 39 +++++++++++++++++++++++++++++++-------- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 6f34fdc2427..be732740442 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -15,9 +15,8 @@ use utils::span_lint; /// ``` /// a + 1 /// ``` -declare_lint! { +declare_restriction_lint! { pub INTEGER_ARITHMETIC, - Allow, "Any integer arithmetic statement" } @@ -32,9 +31,8 @@ declare_lint! { /// ``` /// a + 1.0 /// ``` -declare_lint! { +declare_restriction_lint! { pub FLOAT_ARITHMETIC, - Allow, "Any floating-point arithmetic statement" } @@ -55,32 +53,32 @@ impl LateLintPass for Arithmetic { match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd | hir::BiOr | hir::BiBitAnd | - hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | - hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | + hir::BiAnd | hir::BiOr | hir::BiBitAnd | + hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, _ => () } let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r)); if l_ty.is_integral() && r_ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, + span_lint(cx, + INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.span = Some(expr.span); + self.span = Some(expr.span); } else if l_ty.is_floating_point() && r_ty.is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.span = Some(expr.span); + self.span = Some(expr.span); } }, hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { let ty = cx.tcx.expr_ty(arg); if ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, + span_lint(cx, + INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.span = Some(expr.span); @@ -95,7 +93,7 @@ impl LateLintPass for Arithmetic { _ => () } } - + fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) { if Some(expr.span) == self.span { self.span = None; diff --git a/src/lib.rs b/src/lib.rs index 584ae7f77eb..e22d85a43e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,12 @@ extern crate rustc_const_eval; extern crate rustc_const_math; use rustc_plugin::Registry; +macro_rules! declare_restriction_lint { + { pub $name:tt, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; +} + pub mod consts; #[macro_use] pub mod utils; @@ -242,9 +248,12 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box mem_forget::MemForget); reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); - reg.register_lint_group("clippy_pedantic", vec![ + reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, + ]); + + reg.register_lint_group("clippy_pedantic", vec![ array_indexing::INDEXING_SLICING, booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, diff --git a/tests/compile-fail/arithmetic.rs b/tests/compile-fail/arithmetic.rs index 3b9e1b8b85a..54ac65970ae 100644 --- a/tests/compile-fail/arithmetic.rs +++ b/tests/compile-fail/arithmetic.rs @@ -15,7 +15,6 @@ fn main() { i & 1; // no wrapping i | 1; i ^ 1; - i % 7; i >> 1; i << 1; diff --git a/util/update_lints.py b/util/update_lints.py index bf9728d4f58..bfed0430abb 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -21,12 +21,18 @@ declare_deprecated_lint_re = re.compile(r''' " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] ''', re.VERBOSE | re.DOTALL) +declare_restriction_lint_re = re.compile(r''' + declare_restriction_lint! \s* [{(] \s* + pub \s+ (?P<name>[A-Z_][A-Z_0-9]*) \s*,\s* + " (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})] +''', re.VERBOSE | re.DOTALL) + nl_escape_re = re.compile(r'\\\n\s*') wiki_link = 'https://github.com/Manishearth/rust-clippy/wiki' -def collect(lints, deprecated_lints, fn): +def collect(lints, deprecated_lints, restriction_lints, fn): """Collect all lints from a file. Adds entries to the lints list as `(module, name, level, desc)`. @@ -48,6 +54,14 @@ def collect(lints, deprecated_lints, fn): match.group('name').lower(), desc.replace('\\"', '"'))) + for match in declare_restriction_lint_re.finditer(code): + # remove \-newline escapes from description string + desc = nl_escape_re.sub('', match.group('desc')) + restriction_lints.append((os.path.splitext(os.path.basename(fn))[0], + match.group('name').lower(), + "allow", + desc.replace('\\"', '"'))) + def gen_table(lints, link=None): """Write lint table in Markdown format.""" @@ -86,7 +100,6 @@ def gen_deprecated(lints): for lint in lints: yield ' store.register_removed("%s", "%s");\n' % (lint[1], lint[2]) - def replace_region(fn, region_start, region_end, callback, replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. @@ -128,6 +141,7 @@ def replace_region(fn, region_start, region_end, callback, def main(print_only=False, check=False): lints = [] deprecated_lints = [] + restriction_lints = [] # check directory if not os.path.isfile('src/lib.rs'): @@ -138,22 +152,24 @@ def main(print_only=False, check=False): for root, _, files in os.walk('src'): for fn in files: if fn.endswith('.rs'): - collect(lints, deprecated_lints, os.path.join(root, fn)) + collect(lints, deprecated_lints, restriction_lints, + os.path.join(root, fn)) if print_only: - sys.stdout.writelines(gen_table(lints)) + sys.stdout.writelines(gen_table(lints + restriction_lints)) return # replace table in README.md changed = replace_region( 'README.md', r'^name +\|', '^$', - lambda: gen_table(lints, link=wiki_link), + lambda: gen_table(lints + restriction_lints, link=wiki_link), write_back=not check) changed |= replace_region( 'README.md', r'^There are \d+ lints included in this crate:', "", - lambda: ['There are %d lints included in this crate:\n' % len(lints)], + lambda: ['There are %d lints included in this crate:\n' % (len(lints) + + len(restriction_lints))], write_back=not check) # update the links in the CHANGELOG @@ -162,13 +178,14 @@ def main(print_only=False, check=False): "<!-- begin autogenerated links to wiki -->", "<!-- end autogenerated links to wiki -->", lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], wiki_link) for l in - sorted(lints + deprecated_lints, key=lambda l: l[1])], + sorted(lints + restriction_lints + deprecated_lints, + key=lambda l: l[1])], replace_start=False, write_back=not check) # update the `pub mod` list changed |= replace_region( 'src/lib.rs', r'begin lints modules', r'end lints modules', - lambda: gen_mods(lints), + lambda: gen_mods(lints + restriction_lints), replace_start=False, write_back=not check) # same for "clippy" lint collection @@ -190,6 +207,12 @@ def main(print_only=False, check=False): lambda: gen_group(lints, levels=('allow',)), replace_start=False, write_back=not check) + # same for "clippy_restrictions" lint collection + changed |= replace_region( + 'src/lib.rs', r'reg.register_lint_group\("clippy_restrictions"', + r'\]\);', lambda: gen_group(restriction_lints), + replace_start=False, write_back=not check) + if check and changed: print('Please run util/update_lints.py to regenerate lints lists.') return 1 -- cgit 1.4.1-3-g733a5 From 10f468e679c0e6a6c6dc0e94431f3d63bf3e33e0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 2 May 2016 10:52:55 +0200 Subject: don't lint similar_names inside #[test] functions --- src/non_expressive_names.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index a6f0571c499..c1232fe64b1 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -2,7 +2,8 @@ use rustc::lint::*; use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast::*; -use syntax::visit::{self, FnKind}; +use syntax::attr; +use syntax::visit; use utils::{span_lint_and_then, in_macro, span_lint}; /// **What it does:** This lint warns about names that are very similar and thus confusing @@ -237,24 +238,28 @@ impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { }); } fn visit_item(&mut self, _: &'v Item) { - // do nothing + // do not recurse into inner items } } impl EarlyLintPass for NonExpressiveNames { - fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, blk: &Block, _: Span, _: NodeId) { - let mut visitor = SimilarNamesLocalVisitor { - names: Vec::new(), - cx: cx, - lint: &self, - single_char_names: Vec::new(), - }; - // initialize with function arguments - for arg in &decl.inputs { - visit::walk_pat(&mut SimilarNamesNameVisitor(&mut visitor), &arg.pat); + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node { + if !attr::contains_name(&item.attrs, "test") { + let mut visitor = SimilarNamesLocalVisitor { + names: Vec::new(), + cx: cx, + lint: &self, + single_char_names: Vec::new(), + }; + // initialize with function arguments + for arg in &decl.inputs { + visit::walk_pat(&mut SimilarNamesNameVisitor(&mut visitor), &arg.pat); + } + // walk all other bindings + visit::walk_block(&mut visitor, blk); + } } - // walk all other bindings - visit::walk_block(&mut visitor, blk); } } -- cgit 1.4.1-3-g733a5 From ee35c3722a25dda475a4828c5474795ddde285e2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 2 May 2016 10:53:09 +0200 Subject: similar_names should be allow-by-default --- src/non_expressive_names.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index c1232fe64b1..0c6fdc37066 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -15,7 +15,7 @@ use utils::{span_lint_and_then, in_macro, span_lint}; /// **Example:** `checked_exp` and `checked_expr` declare_lint! { pub SIMILAR_NAMES, - Warn, + Allow, "similarly named items and bindings" } -- cgit 1.4.1-3-g733a5 From 365644e9e63bc4aa100ad4d84e2212f843a912e4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 2 May 2016 14:36:33 +0200 Subject: doc markdown lint's span shows the line instead of the item --- src/doc.rs | 49 +++++++++++++++++------------------------------ tests/compile-fail/doc.rs | 30 ++++++++++++++--------------- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 54d5366729e..6a2b3c27ba9 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -1,7 +1,6 @@ use rustc::lint::*; -use std::borrow::Cow; use syntax::ast; -use syntax::codemap::Span; +use syntax::codemap::{Span, BytePos}; use utils::span_lint; /// **What it does:** This lint checks for the presence of `_`, `::` or camel-case words outside @@ -43,50 +42,38 @@ impl LintPass for Doc { impl EarlyLintPass for Doc { fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { - check_attrs(cx, &self.valid_idents, &krate.attrs, krate.span); + check_attrs(cx, &self.valid_idents, &krate.attrs); } fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { - check_attrs(cx, &self.valid_idents, &item.attrs, item.span); + check_attrs(cx, &self.valid_idents, &item.attrs); } } -/// Collect all doc attributes. Multiple `///` are represented in different attributes. `rustdoc` -/// has a pass to merge them, but we probably don’t want to invoke that here. -fn collect_doc(attrs: &[ast::Attribute]) -> (Cow<str>, Option<Span>) { - fn doc_and_span(attr: &ast::Attribute) -> Option<(&str, Span)> { +pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { + let mut in_multiline = false; + for attr in attrs { if attr.node.is_sugared_doc { if let ast::MetaItemKind::NameValue(_, ref doc) = attr.node.value.node { if let ast::LitKind::Str(ref doc, _) = doc.node { - return Some((&doc[..], attr.span)); + // doc comments start with `///` or `//!` + let real_doc = &doc[3..]; + let mut span = attr.span; + span.lo = span.lo + BytePos(3); + + // check for multiline code blocks + if real_doc.trim_left().starts_with("```") { + in_multiline = !in_multiline; + } + if !in_multiline { + check_doc(cx, valid_idents, real_doc, span); + } } } } - - None - } - let doc_and_span: fn(_) -> _ = doc_and_span; - - let mut doc_attrs = attrs.iter().filter_map(doc_and_span); - - let count = doc_attrs.clone().take(2).count(); - - match count { - 0 => ("".into(), None), - 1 => { - let (doc, span) = doc_attrs.next().unwrap_or_else(|| unreachable!()); - (doc.into(), Some(span)) - } - _ => (doc_attrs.map(|s| format!("{}\n", s.0)).collect::<String>().into(), None), } } -pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute], default_span: Span) { - let (doc, span) = collect_doc(attrs); - let span = span.unwrap_or(default_span); - check_doc(cx, valid_idents, &doc, span); -} - macro_rules! jump_to { // Get the next character’s first byte UTF-8 friendlyly. (@next_char, $chars: expr, $len: expr) => {{ diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 16e460e5055..7a150ba378d 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -7,14 +7,14 @@ #![deny(doc_markdown)] /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +//~^ ERROR: you should put `foo_bar` between ticks +//~| ERROR: you should put `foo::bar` between ticks /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun +//~^ ERROR: you should put `Foo::some_fun` between ticks /// which should be reported only once despite being __doubly bad__. /// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn foo_bar() { -//~^ ERROR: you should put `foo_bar` between ticks -//~| ERROR: you should put `foo::bar` between ticks -//~| ERROR: you should put `Foo::some_fun` between ticks -//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// That one tests multiline ticks. @@ -23,16 +23,16 @@ fn foo_bar() { /// _foo bar_ /// ``` /// be_sure_we_got_to_the_end_of_it -fn multiline_ticks() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn multiline_ticks() { } /// This _is a test for /// multiline /// emphasis_. /// be_sure_we_got_to_the_end_of_it -fn test_emphasis() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn test_emphasis() { } /// This tests units. See also #835. @@ -45,8 +45,8 @@ fn test_emphasis() { /// 32kB 32MB 32GB 32TB 32PB 32EB /// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb /// be_sure_we_got_to_the_end_of_it -fn test_units() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn test_units() { } /// This one checks we don’t try to split unicode codepoints @@ -55,11 +55,15 @@ fn test_units() { /// `💣` /// `❤️` /// ß_foo +//~^ ERROR: you should put `ß_foo` between ticks /// ℝ_foo +//~^ ERROR: you should put `ℝ_foo` between ticks /// 💣_foo /// ❤️_foo /// foo_ß +//~^ ERROR: you should put `foo_ß` between ticks /// foo_ℝ +//~^ ERROR: you should put `foo_ℝ` between ticks /// foo_💣 /// foo_❤️ /// [ßdummy textß][foo_ß] @@ -75,18 +79,16 @@ fn test_units() { /// [foo_💣]: dummy text /// [foo_❤️]: dummy text /// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn test_unicode() { -//~^ ERROR: you should put `ß_foo` between ticks -//~| ERROR: you should put `ℝ_foo` between ticks -//~| ERROR: you should put `foo_ß` between ticks -//~| ERROR: you should put `foo_ℝ` between ticks -//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks } /// This test has [a link_with_underscores][chunked-example] inside it. See #823. +//~^ ERROR: you should put `link_with_underscores` between ticks /// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues) /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. /// It can also be [inline_link2]. +//~^ ERROR: you should put `inline_link2` between ticks /// /// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example /// [inline_link]: https://foobar @@ -98,10 +100,8 @@ fn test_unicode() { /// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` /// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , /// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn main() { -//~^ ERROR: you should put `inline_link2` between ticks -//~| ERROR: you should put `link_with_underscores` between ticks -//~| ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks foo_bar(); multiline_ticks(); test_emphasis(); -- cgit 1.4.1-3-g733a5 From 3a32c2c596d1aaef4ea2c6da4656828869564ff8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 2 May 2016 14:36:48 +0200 Subject: doc markdown lint shows the exact word location --- src/doc.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 6a2b3c27ba9..6212a025c25 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -117,6 +117,15 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp } } + #[allow(cast_possible_truncation)] + fn word_span(mut span: Span, begin: usize, end: usize) -> Span { + debug_assert_eq!(end as u32 as usize, end); + debug_assert_eq!(begin as u32 as usize, begin); + span.hi = span.lo + BytePos(end as u32); + span.lo = span.lo + BytePos(begin as u32); + span + } + let len = doc.len(); let mut chars = doc.char_indices().peekable(); let mut current_word_begin = 0; @@ -133,6 +142,7 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp '[' => { let end = jump_to!(chars, ']', len); let link_text = &doc[current_word_begin + 1..end]; + let word_span = word_span(span, current_word_begin + 1, end + 1); match chars.peek() { Some(&(_, c)) => { @@ -143,18 +153,18 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp match c { '(' => { // inline link current_word_begin = jump_to!(chars, ')', len); - check_doc(cx, valid_idents, link_text, span); + check_doc(cx, valid_idents, link_text, word_span); } '[' => { // reference link current_word_begin = jump_to!(chars, ']', len); - check_doc(cx, valid_idents, link_text, span); + check_doc(cx, valid_idents, link_text, word_span); } ':' => { // reference link current_word_begin = jump_to!(chars, '\n', len); } _ => { // automatic reference link current_word_begin = jump_to!(@next_char, chars, len); - check_doc(cx, valid_idents, link_text, span); + check_doc(cx, valid_idents, link_text, word_span); } } } @@ -166,8 +176,8 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp Some((end, _)) => end, None => len, }; - - check_word(cx, valid_idents, &doc[current_word_begin..end], span); + let word_span = word_span(span, current_word_begin, end); + check_word(cx, valid_idents, &doc[current_word_begin..end], word_span); current_word_begin = jump_to!(@next_char, chars, len); } } -- cgit 1.4.1-3-g733a5 From ca743ecb77c35d7a0a26e625769aa1ec627811bf Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Wed, 4 May 2016 08:54:59 +0200 Subject: rustup: fix breakage in diagnostics API Also adds a function to add the clippy wiki note, which is used a few times. --- src/methods.rs | 2 +- src/swap.rs | 4 ++-- src/utils/mod.rs | 40 +++++++++++++++++++--------------------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index e25154bd38b..44fdab454a3 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -602,7 +602,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &Expr, new: &Expr, unwrap: &Expr) span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, "you are getting the inner pointer of a temporary `CString`", |db| { - db.fileline_note(expr.span, "that pointer will be invalid outside this expression"); + db.note("that pointer will be invalid outside this expression"); db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); }); }} diff --git a/src/swap.rs b/src/swap.rs index 29db0da5cf9..724915b9dd5 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -95,7 +95,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if !what.is_empty() { db.span_suggestion(span, "try", format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); - db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); + db.note("or maybe you should use `std::mem::replace`?"); } }); }} @@ -130,7 +130,7 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { if !what.is_empty() { db.span_suggestion(span, "try", format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); - db.fileline_note(span, "or maybe you should use `std::mem::replace`?"); + db.note("or maybe you should use `std::mem::replace`?"); } }); }} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 83247a59174..3e77ffb2c24 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -471,44 +471,44 @@ impl<'a> Deref for DiagnosticWrapper<'a> { } } +impl<'a> DiagnosticWrapper<'a> { + fn wiki_link(&mut self, lint: &'static Lint) { + self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } +} + pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, sp, msg); + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { - db.fileline_help(sp, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.wiki_link(lint); } - DiagnosticWrapper(db) + db } pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, span, msg); + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { - db.fileline_help(span, - &format!("{}\nfor further information visit \ - https://github.com/Manishearth/rust-clippy/wiki#{}", - help, - lint.name_lower())); + db.help(help); + db.wiki_link(lint); } - DiagnosticWrapper(db) + db } pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, note: &str) -> DiagnosticWrapper<'a> { - let mut db = cx.struct_span_lint(lint, span, msg); + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { if note_span == span { - db.fileline_note(note_span, note); + db.note(note); } else { db.span_note(note_span, note); } - db.fileline_help(span, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.wiki_link(lint); } - DiagnosticWrapper(db) + db } pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) @@ -518,9 +518,7 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { f(&mut db); - db.fileline_help(sp, - &format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + db.wiki_link(lint); } db } -- cgit 1.4.1-3-g733a5 From e14e1a7148375499731f9549eadf5172050fd99a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 5 May 2016 21:32:48 +0200 Subject: Fix issue with `DOC_MARKDOWN` and punctuation --- src/doc.rs | 7 ++++--- tests/compile-fail/doc.rs | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/doc.rs b/src/doc.rs index 6212a025c25..00c3e4398ea 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -133,9 +133,6 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp match chars.next() { Some((_, c)) => { match c { - c if c.is_whitespace() => { - current_word_begin = jump_to!(@next_char, chars, len); - } '`' => { current_word_begin = jump_to!(chars, '`', len); } @@ -171,6 +168,10 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp None => return, } } + // anything that’s neither alphanumeric nor '_' is not part of an ident anyway + c if !c.is_alphanumeric() && c != '_' => { + current_word_begin = jump_to!(@next_char, chars, len); + } _ => { let end = match chars.find(|&(_, c)| !is_word_char(c)) { Some((end, _)) => end, diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 7a150ba378d..045174db78e 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -107,3 +107,11 @@ fn main() { test_emphasis(); test_units(); } + +/// I am confused by brackets? (`x_y`) +/// I am confused by brackets? (foo `x_y`) +/// I am confused by brackets? (`x_y` foo) +/// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn issue900() { +} -- cgit 1.4.1-3-g733a5 From cc2774df60082031b6b21cfac562537cff8163e4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 5 May 2016 21:34:42 +0200 Subject: Test previously reported false positive --- tests/compile-fail/doc.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 045174db78e..0c8d1d50532 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -115,3 +115,17 @@ fn main() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn issue900() { } + +/// Diesel queries also have a similar problem to [Iterator][iterator], where +/// /// More talking +/// returning them from a function requires exposing the implementation of that +/// function. The [`helper_types`][helper_types] module exists to help with this, +/// but you might want to hide the return type or have it conditionally change. +/// Boxing can achieve both. +/// +/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html +/// [helper_types]: ../helper_types/index.html +/// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn issue883() { +} -- cgit 1.4.1-3-g733a5 From 3ce60e973139e1c44ad4bf67d26498c4e6c42d04 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 5 May 2016 21:42:59 +0200 Subject: Don’t warn in titles in DOC_MARKDOWN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/doc.rs | 6 ++++++ tests/compile-fail/doc.rs | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/doc.rs b/src/doc.rs index 00c3e4398ea..cf32c1731fa 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -126,6 +126,7 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp span } + let mut new_line = true; let len = doc.len(); let mut chars = doc.char_indices().peekable(); let mut current_word_begin = 0; @@ -133,6 +134,9 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp match chars.next() { Some((_, c)) => { match c { + '#' if new_line => { // don’t warn on titles + current_word_begin = jump_to!(chars, '\n', len); + } '`' => { current_word_begin = jump_to!(chars, '`', len); } @@ -182,6 +186,8 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp current_word_begin = jump_to!(@next_char, chars, len); } } + + new_line = c == '\n' || (new_line && c.is_whitespace()); } None => break, } diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 0c8d1d50532..eca9d79354c 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -108,6 +108,18 @@ fn main() { test_units(); } +/// ## CamelCaseThing +/// Talks about `CamelCaseThing`. Titles should be ignored, see issue #897. +/// +/// # CamelCaseThing +/// +/// Not a title #897 CamelCaseThing +//~^ ERROR: you should put `CamelCaseThing` between ticks +/// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn issue897() { +} + /// I am confused by brackets? (`x_y`) /// I am confused by brackets? (foo `x_y`) /// I am confused by brackets? (`x_y` foo) -- cgit 1.4.1-3-g733a5 From d1393cfd38c9f78ec63059bba5c633ee12336e89 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 15:32:34 +0200 Subject: run remark-lint on README.md --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index f72ac01bc3e..f22a1610459 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,14 @@ env: # TRAVIS_TOKEN_CLIPPY_SERVICE secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI= +install: + - . $HOME/.nvm/nvm.sh + - nvm install stable + - nvm use stable + - npm install remark remark-lint + script: + - remark -f README.md -u remark-lint > /dev/null - python util/update_lints.py -c - cargo build --features debugging - rm -rf target/ Cargo.lock -- cgit 1.4.1-3-g733a5 From fff6ddea2a8004e9a8a0747541a7543d4e5dcab5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 15:39:10 +0200 Subject: fail fast --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f22a1610459..1c131ec98f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ install: - npm install remark remark-lint script: + - set -e - remark -f README.md -u remark-lint > /dev/null - python util/update_lints.py -c - cargo build --features debugging -- cgit 1.4.1-3-g733a5 From a159f047dd0aec4665f52de533bbd08bb7eaf7c0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:07:47 +0200 Subject: fix markdown --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 9de4eef72ed..17c0ce5235e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -#rust-clippy +# rust-clippy + [![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) [![Clippy Linting Result](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/badge.svg)](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/log) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) @@ -7,13 +8,15 @@ A collection of lints to catch common mistakes and improve your Rust code. Table of contents: -* [Lint list](#lints) -* [Usage instructions](#usage) -* [Configuration](#configuration) -* [*clippy-service*](#link-with-clippy-service) -* [License](#license) -##Lints +* [Lint list](#lints) +* [Usage instructions](#usage) +* [Configuration](#configuration) +* [*clippy-service*](#link-with-clippy-service) +* [License](#license) + +## Lints + There are 146 lints included in this crate: name | default | meaning @@ -27,7 +30,7 @@ name [block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: `if { let x = true; x } ...` [bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box<Vec<T>>`, vector elements are already on the heap -[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using Box<T> where unnecessary +[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using `Box<T>` where unnecessary [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` @@ -145,7 +148,7 @@ name [transmute_ptr_to_ref](https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type [trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information) +[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference [unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` @@ -167,19 +170,25 @@ name More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! -##Usage +## Usage -Compiler plugins are highly unstable and will only work with a nightly Rust for now. Since stable Rust is backwards compatible, you should be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this. +Compiler plugins are highly unstable and will only work with a nightly Rust for now. +Since stable Rust is backwards compatible, you should be able to compile +your stable programs with nightly Rust with clippy plugged in to circumvent +this. Add in your `Cargo.toml`: + ```toml [dependencies] clippy = "*" ``` -You then need to add `#![feature(plugin)]` and `#![plugin(clippy)]` to the top of your crate entry point (`main.rs` or `lib.rs`). +You then need to add `#![feature(plugin)]` and `#![plugin(clippy)]` to the top +of your crate entry point (`main.rs` or `lib.rs`). Sample `main.rs`: + ```rust #![feature(plugin)] @@ -196,7 +205,8 @@ fn main(){ ``` Produces this warning: -``` + +```terminal src/main.rs:8:5: 11:6 warning: you seem to be trying to use match for destructuring a single type. Consider using `if let`, #[warn(single_match)] on by default src/main.rs:8 match x { src/main.rs:9 Some(y) => println!("{:?}", y), @@ -206,29 +216,37 @@ src/main.rs:8:5: 11:6 help: Try if let Some(y) = x { println!("{:?}", y) } ``` - -An alternate way to use clippy is by compiling and using [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), a custom cargo subcommand that runs clippy on a given project. +An alternate way to use clippy is by compiling and using [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), +a custom cargo subcommand that runs clippy on a given project. You can add options to `allow`/`warn`/`deny`: -- the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) -- all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive lints prone to false positives. -- only some lints (`#![deny(single_match, box_vec)]`, etc) -- `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc + +* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) + +* all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, + `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive + lints prone to false positives. + +* only some lints (`#![deny(single_match, box_vec)]`, etc) + +* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc Note: `deny` produces errors instead of warnings To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` in your code, you can use: -``` +```terminal cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy ``` -*[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! +*[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* +Be sure that clippy was compiled with the same version of rustc that cargo invokes here! If you want to make clippy an optional dependency, you can do the following: In your `Cargo.toml`: + ```toml [dependencies] clippy = {version = "*", optional = true} @@ -245,9 +263,13 @@ And, in your `main.rs` or `lib.rs`: #![cfg_attr(feature="clippy", plugin(clippy))] ``` -Instead of adding the `cfg_attr` attributes you can also run clippy on demand: `cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` (the `-Z no trans`, while not neccessary, will stop the compilation process after typechecking (and lints) have completed, which can significantly reduce the runtime). +Instead of adding the `cfg_attr` attributes you can also run clippy on demand: +`cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` +(the `-Z no trans`, while not neccessary, will stop the compilation process after +typechecking (and lints) have completed, which can significantly reduce the runtime). ## Configuration + Some lints can be configured in a `clippy.toml` file. It contains basic `variable = value` mapping eg. ```toml @@ -259,16 +281,21 @@ See the wiki for more information about which lints can be configured and the meaning of the variables. You can also specify the path to the configuration file with: + ```rust #![plugin(clippy(conf_file="path/to/clippy's/configuration"))] ``` -##Link with clippy service +## Link with clippy service + `clippy-service` is a rust web initiative providing `rust-clippy` as a web service. -Both projects are independent and maintained by different people (even if some `clippy-service`'s contributions are authored by some `rust-clippy` members). +Both projects are independent and maintained by different people +(even if some `clippy-service`'s contributions are authored by some `rust-clippy` members). You can check out this great service at [clippy.bashy.io](https://clippy.bashy.io/). -##License -Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). If you're having issues with the license, let me know and I'll try to change it to something more permissive. +## License + +Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). +If you're having issues with the license, let me know and I'll try to change it to something more permissive. -- cgit 1.4.1-3-g733a5 From 6f5c74732425db79a20a0b950ca95588fb587858 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:07:54 +0200 Subject: ignore some markdown lints --- .remarkrc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .remarkrc diff --git a/.remarkrc b/.remarkrc new file mode 100644 index 00000000000..22bae13ccf8 --- /dev/null +++ b/.remarkrc @@ -0,0 +1,12 @@ +{ + "plugins": { + "lint": { + "table-pipes": false, + "table-pipe-alignment": false, + "maximum-line-length": 120 + } + }, + "settings": { + "commonmark": true + } +} -- cgit 1.4.1-3-g733a5 From 0a3ab78bdef4262c7ca912f8d757fb2412fcb61f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:09:05 +0200 Subject: fix markdown generated from code --- src/escape.rs | 2 +- src/unicode.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/escape.rs b/src/escape.rs index fa235244884..ff841b18066 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -31,7 +31,7 @@ pub struct EscapePass; /// } /// ``` declare_lint! { - pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary" + pub BOXED_LOCAL, Warn, "using `Box<T>` where unnecessary" } fn is_non_trait_box(ty: ty::Ty) -> bool { diff --git a/src/unicode.rs b/src/unicode.rs index 26521017ee5..8271fd3ed66 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -40,7 +40,7 @@ declare_lint! { declare_lint! { pub UNICODE_NOT_NFC, Allow, "using a unicode literal not in NFC normal form (see \ - http://www.unicode.org/reports/tr15/ for further information)" + [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } -- cgit 1.4.1-3-g733a5 From a60d65b5a430ad3cc7e73c41c3534e8438477f09 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:13:05 +0200 Subject: use .remarkrc.json for travis --- .remarkrc | 12 ------------ .remarkrc.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 .remarkrc create mode 100644 .remarkrc.json diff --git a/.remarkrc b/.remarkrc deleted file mode 100644 index 22bae13ccf8..00000000000 --- a/.remarkrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "plugins": { - "lint": { - "table-pipes": false, - "table-pipe-alignment": false, - "maximum-line-length": 120 - } - }, - "settings": { - "commonmark": true - } -} diff --git a/.remarkrc.json b/.remarkrc.json new file mode 100644 index 00000000000..22bae13ccf8 --- /dev/null +++ b/.remarkrc.json @@ -0,0 +1,12 @@ +{ + "plugins": { + "lint": { + "table-pipes": false, + "table-pipe-alignment": false, + "maximum-line-length": 120 + } + }, + "settings": { + "commonmark": true + } +} -- cgit 1.4.1-3-g733a5 From 93ae9c32f1cf1d79105eb52a61c2b64c26f0e2ac Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:15:10 +0200 Subject: pass full config path to remark --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c131ec98f3..d0506079b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: script: - set -e - - remark -f README.md -u remark-lint > /dev/null + - remark -f README.md -u remark-lint -c .remarkrc.json > /dev/null - python util/update_lints.py -c - cargo build --features debugging - rm -rf target/ Cargo.lock -- cgit 1.4.1-3-g733a5 From 3ec1b9a40a2d91eae106632d5a75899766ef89ed Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 6 May 2016 16:22:17 +0200 Subject: more arguments don't make stuff better --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d0506079b8d..012d6045cd2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: script: - set -e - - remark -f README.md -u remark-lint -c .remarkrc.json > /dev/null + - remark -f README.md > /dev/null - python util/update_lints.py -c - cargo build --features debugging - rm -rf target/ Cargo.lock -- cgit 1.4.1-3-g733a5 From aa10c93e8f337e43c2cbab63e98f31d95589defe Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 8 May 2016 00:56:23 +0200 Subject: Fix tests --- src/len_zero.rs | 7 +------ src/regex.rs | 19 +++++++++++-------- tests/compile-fail/for_loop.rs | 2 +- tests/compile-fail/matches.rs | 10 +++++----- tests/compile-fail/regex.rs | 2 ++ 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 7a7a17bc79d..7e9d17d643b 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -113,14 +113,9 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { if is_named_self(i, "len") { let ty = cx.tcx.node_id_to_type(item.id); - let s = i.span; span_lint(cx, LEN_WITHOUT_IS_EMPTY, - Span { - lo: s.lo, - hi: s.lo, - expn_id: s.expn_id, - }, + i.span, &format!("item `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ Consider adding one", ty)); diff --git a/src/regex.rs b/src/regex.rs index 72a33757027..e1b4237b9b2 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -143,14 +143,17 @@ impl LateLintPass for RegexPass { #[allow(cast_possible_truncation)] fn str_span(base: Span, s: &str, c: usize) -> Span { - let lo = match s.char_indices().nth(c) { - Some((b, _)) => base.lo + BytePos(b as u32), - _ => base.hi, - }; - Span { - lo: lo, - hi: lo, - ..base + let mut si = s.char_indices().skip(c); + + match (si.next(), si.next()) { + (Some((l, _)), Some((h, _))) => { + Span { + lo: base.lo + BytePos(l as u32), + hi: base.lo + BytePos(h as u32), + ..base + } + } + _ => base, } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 064f66537eb..2f164d1e569 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -340,7 +340,7 @@ fn main() { for (_, v) in &m { //~^ you seem to want to iterate on a map's values //~| HELP use the corresponding method - //~| SUGGESTION for v in &m.values() + //~| SUGGESTION for v in m.values() let _v = v; } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index f5f830fed51..3444e49ec51 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -140,7 +140,7 @@ fn ref_pats() { match v { //~^ERROR add `&` to all patterns //~|HELP instead of - //~|SUGGESTION `match *v { .. }` + //~|SUGGESTION match *v { .. } &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -153,7 +153,7 @@ fn ref_pats() { match tup { //~^ERROR add `&` to all patterns //~|HELP instead of - //~|SUGGESTION `match *tup { .. }` + //~|SUGGESTION match *tup { .. } &(v, 1) => println!("{}", v), _ => println!("none"), } @@ -162,7 +162,7 @@ fn ref_pats() { match &w { //~^ERROR add `&` to both //~|HELP try - //~|SUGGESTION `match w { .. }` + //~|SUGGESTION match w { .. } &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -176,7 +176,7 @@ fn ref_pats() { if let &None = a { //~^ERROR add `&` to all patterns //~|HELP instead of - //~|SUGGESTION `if let ... = *a { .. }` + //~|SUGGESTION if let .. = *a { .. } println!("none"); } @@ -184,7 +184,7 @@ fn ref_pats() { if let &None = &b { //~^ERROR add `&` to both //~|HELP try - //~|SUGGESTION `if let ... = b { .. }` + //~|SUGGESTION if let .. = b { .. } println!("none"); } } diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index 606c3d513b2..9cd2bc8098e 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -16,6 +16,8 @@ fn syntax_error() { //~^ERROR: regex syntax error: empty alternate let wrong_char_ranice = Regex::new("[z-a]"); //~^ERROR: regex syntax error: invalid character class range + let some_unicode = Regex::new("[é-è]"); + //~^ERROR: regex syntax error: invalid character class range let some_regex = Regex::new(OPENING_PAREN); //~^ERROR: regex syntax error on position 0: unclosed -- cgit 1.4.1-3-g733a5 From 7566484b8ad6ea92cc7c69cf77f4c72aed738479 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 8 May 2016 01:03:20 +0200 Subject: Bump to 0.0.65 --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c51e5595a9..6ff3526d841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.65 — 2016-05-08 +* Rustup to *rustc 1.10.0-nightly (62e2b2fb7 2016-05-06)* +* New lints: [`float_arithmetic`], [`integer_arithmetic`] + ## 0.0.64 — 2016-04-26 * Rustup to *rustc 1.10.0-nightly (645dd013a 2016-04-24)* * New lints: [`temporary_cstring_as_ptr`], [`unsafe_removed_from_name`], and [`mem_forget`] diff --git a/Cargo.toml b/Cargo.toml index 5a8968ac2f5..cd6b2834c56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.64" +version = "0.0.65" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 87faaec7a30cab721aa03ad2e6301c9cd91f5847 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 26 Apr 2016 15:49:53 +0200 Subject: add needless_borrow lint --- CHANGELOG.md | 1 + README.md | 3 ++- src/lib.rs | 3 +++ src/needless_borrow.rs | 50 +++++++++++++++++++++++++++++++++++ tests/compile-fail/eta.rs | 1 + tests/compile-fail/needless_borrow.rs | 27 +++++++++++++++++++ 6 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/needless_borrow.rs create mode 100644 tests/compile-fail/needless_borrow.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff3526d841..3fb3c686948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,7 @@ All notable changes to this project will be documented in this file. [`mutex_atomic`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic [`mutex_integer`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_integer [`needless_bool`]: https://github.com/Manishearth/rust-clippy/wiki#needless_bool +[`needless_borrow`]: https://github.com/Manishearth/rust-clippy/wiki#needless_borrow [`needless_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes [`needless_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop [`needless_return`]: https://github.com/Manishearth/rust-clippy/wiki#needless_return diff --git a/README.md b/README.md index 17c0ce5235e..8f3519c95c4 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 146 lints included in this crate: +There are 147 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -97,6 +97,7 @@ name [mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a Mutex where an atomic value could be used instead [mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a Mutex for an integer type [needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_borrow](https://github.com/Manishearth/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced [needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them [needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do [needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice diff --git a/src/lib.rs b/src/lib.rs index 435e6998c16..dc0efe815b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub mod mut_mut; pub mod mut_reference; pub mod mutex_atomic; pub mod needless_bool; +pub mod needless_borrow; pub mod needless_update; pub mod neg_multiply; pub mod new_without_default; @@ -210,6 +211,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); + reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); @@ -364,6 +366,7 @@ pub fn plugin_registrar(reg: &mut Registry) { mutex_atomic::MUTEX_ATOMIC, needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, needless_update::NEEDLESS_UPDATE, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, diff --git a/src/needless_borrow.rs b/src/needless_borrow.rs new file mode 100644 index 00000000000..294a12dad99 --- /dev/null +++ b/src/needless_borrow.rs @@ -0,0 +1,50 @@ +//! Checks for needless address of operations (`&`) +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc::hir::*; +use rustc::ty::TyRef; +use utils::{span_lint, in_macro}; + +/// **What it does:** This lint checks for address of operations (`&`) that are going to be dereferenced immediately by the compiler +/// +/// **Why is this bad?** Suggests that the receiver of the expression borrows the expression +/// +/// **Known problems:** +/// +/// **Example:** `let x: &i32 = &&&&&&5;` +declare_lint! { + pub NEEDLESS_BORROW, + Warn, + "taking a reference that is going to be automatically dereferenced" +} + +#[derive(Copy,Clone)] +pub struct NeedlessBorrow; + +impl LintPass for NeedlessBorrow { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_BORROW) + } +} + +impl LateLintPass for NeedlessBorrow { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if in_macro(cx, e.span) { + return; + } + if let ExprAddrOf(MutImmutable, ref inner) = e.node { + if let TyRef(..) = cx.tcx.expr_ty(inner).sty { + let ty = cx.tcx.expr_ty(e); + let adj_ty = cx.tcx.expr_ty_adjusted(e); + if ty != adj_ty { + span_lint(cx, + NEEDLESS_BORROW, + e.span, + "this expression borrows a reference that is immediately dereferenced by the compiler"); + } + } + } + } +} diff --git a/tests/compile-fail/eta.rs b/tests/compile-fail/eta.rs index a744489fa9c..c932f8f9a0f 100644 --- a/tests/compile-fail/eta.rs +++ b/tests/compile-fail/eta.rs @@ -18,6 +18,7 @@ fn main() { //~| SUGGESTION let c = Some(1u8).map({1+2; foo}); let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted + //~^ WARN needless_borrow unsafe { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } diff --git a/tests/compile-fail/needless_borrow.rs b/tests/compile-fail/needless_borrow.rs new file mode 100644 index 00000000000..242691aa268 --- /dev/null +++ b/tests/compile-fail/needless_borrow.rs @@ -0,0 +1,27 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn x(y: &i32) -> i32 { + *y +} + +#[deny(clippy)] +#[allow(unused_variables)] +fn main() { + let a = 5; + let b = x(&a); + let c = x(&&a); //~ ERROR: needless_borrow + let s = &String::from("hi"); + let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not + let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]` + let vec = Vec::new(); + let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]` +} + +fn f<T:Copy>(y: &T) -> T { + *y +} + +fn g(y: &[u8]) -> u8 { + y[0] +} -- cgit 1.4.1-3-g733a5 From 6edc6a13d4505f7eb20b8f6b4b72b53c328ae9b0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 26 Apr 2016 17:05:39 +0200 Subject: needless borrows found in clippy --- src/array_indexing.rs | 2 +- src/block_in_if_condition.rs | 2 +- src/booleans.rs | 4 ++-- src/consts.rs | 2 +- src/copies.rs | 6 +++--- src/cyclomatic_complexity.rs | 2 +- src/enum_variants.rs | 8 ++++---- src/len_zero.rs | 2 +- src/lib.rs | 2 +- src/lifetimes.rs | 4 ++-- src/loops.rs | 10 +++++----- src/matches.rs | 6 +++--- src/methods.rs | 4 ++-- src/misc.rs | 2 +- src/mut_reference.rs | 4 ++-- src/non_expressive_names.rs | 2 +- src/shadow.rs | 2 +- src/types.rs | 6 +++--- 18 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/array_indexing.rs b/src/array_indexing.rs index 2295bd7832a..ce2b9a7d6c0 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -67,7 +67,7 @@ impl LateLintPass for ArrayIndexing { let size = ConstInt::Infer(size as u64); // Index is a constant uint - let const_index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); + let const_index = eval_const_expr_partial(cx.tcx, index, ExprTypeChecked, None); if let Ok(ConstVal::Integral(const_index)) = const_index { if size <= const_index { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs index cdaf53684c5..c56cf4dcd29 100644 --- a/src/block_in_if_condition.rs +++ b/src/block_in_if_condition.rs @@ -59,7 +59,7 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { } }; if complex { - self.found_block = Some(&expr); + self.found_block = Some(expr); return; } } diff --git a/src/booleans.rs b/src/booleans.rs index 908415acc7b..9ab806f66ec 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -221,7 +221,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push('('); } } - s.push_str(&snip(&terminals[n as usize])); + s.push_str(&snip(terminals[n as usize])); if brackets { if let ExprBinary(..) = terminals[n as usize].node { s.push(')'); @@ -319,7 +319,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } let mut improvements = Vec::new(); 'simplified: for suggestion in &simplified { - let simplified_stats = terminal_stats(&suggestion); + let simplified_stats = terminal_stats(suggestion); let mut improvement = false; for i in 0..32 { // ignore any "simplifications" that end up requiring a terminal more often than in the original expression diff --git a/src/consts.rs b/src/consts.rs index 4a5f457ed7d..248b5bfe9e6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -164,7 +164,7 @@ impl PartialOrd for Constant { } } (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(&r), + (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { match lv.partial_cmp(rv) { Some(Equal) => Some(ls.cmp(rs)), diff --git a/src/copies.rs b/src/copies.rs index aba4638ab8b..aa9f243e8c7 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -142,7 +142,7 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { }; if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { - if let Some((i, j)) = search_same(&arms, hash, eq) { + if let Some((i, j)) = search_same(arms, hash, eq) { span_note_and_lint(cx, MATCH_SAME_ARMS, j.body.span, @@ -256,8 +256,8 @@ fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> match map.entry(hash(expr)) { Entry::Occupied(o) => { for o in o.get() { - if eq(&o, expr) { - return Some((&o, expr)); + if eq(o, expr) { + return Some((o, expr)); } } } diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 9b20cc4a312..858affd2bbb 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -58,7 +58,7 @@ impl CyclomaticComplexity { divergence: 0, short_circuits: 0, returns: 0, - tcx: &cx.tcx, + tcx: cx.tcx, }; helper.visit_block(block); let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; diff --git a/src/enum_variants.rs b/src/enum_variants.rs index d7bd4742ebb..a1f2c5e1441 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -68,9 +68,9 @@ impl EarlyLintPass for EnumVariantNames { for var in &def.variants { let name = var2str(var); - let pre_match = partial_match(&pre, &name); + let pre_match = partial_match(pre, &name); pre = &pre[..pre_match]; - let pre_camel = camel_case_until(&pre); + let pre_camel = camel_case_until(pre); pre = &pre[..pre_camel]; while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { if next.is_lowercase() { @@ -82,10 +82,10 @@ impl EarlyLintPass for EnumVariantNames { } } - let post_match = partial_rmatch(&post, &name); + let post_match = partial_rmatch(post, &name); let post_end = post.len() - post_match; post = &post[post_end..]; - let post_camel = camel_case_from(&post); + let post_camel = camel_case_from(post); post = &post[post_camel..]; } let (what, value) = match (pre.is_empty(), post.is_empty()) { diff --git a/src/len_zero.rs b/src/len_zero.rs index 7e9d17d643b..9dae856764a 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -184,7 +184,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { }) } - let ty = &walk_ptrs_ty(&cx.tcx.expr_ty(expr)); + let ty = &walk_ptrs_ty(cx.tcx.expr_ty(expr)); match ty.sty { ty::TyTrait(_) => { cx.tcx diff --git a/src/lib.rs b/src/lib.rs index dc0efe815b2..e5d374a560f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,7 +141,7 @@ pub fn plugin_registrar(reg: &mut Registry) { ("clippy.toml", false) }; - let (conf, errors) = utils::conf::read_conf(&file_name, must_exist); + let (conf, errors) = utils::conf::read_conf(file_name, must_exist); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { diff --git a/src/lifetimes.rs b/src/lifetimes.rs index 67dfabe2569..b9771e18ffc 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -46,7 +46,7 @@ impl LintPass for LifetimePass { impl LateLintPass for LifetimePass { fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { - check_fn_inner(cx, decl, None, &generics, item.span); + check_fn_inner(cx, decl, None, generics, item.span); } } @@ -102,7 +102,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g span, "explicit lifetimes given in parameter types where they could be elided"); } - report_extra_lifetimes(cx, decl, &generics, slf); + report_extra_lifetimes(cx, decl, generics, slf); } fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, diff --git a/src/loops.rs b/src/loops.rs index 70abb7a1aac..2384c845303 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -328,7 +328,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E /// Check for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(&arg) { + if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(arg) { // the var must be a single name if let PatKind::Ident(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { @@ -363,7 +363,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex }; let take: Cow<_> = if let Some(ref end) = *end { - if is_len_call(&end, &indexed) { + if is_len_call(end, &indexed) { "".into() } else { format!(".take({})", snippet(cx, end.span, "..")).into() @@ -422,10 +422,10 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... - if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(&arg) { + if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(arg) { // ...and both sides are compile-time constant integers... - if let Ok(start_idx) = eval_const_expr_partial(&cx.tcx, start, ExprTypeChecked, None) { - if let Ok(end_idx) = eval_const_expr_partial(&cx.tcx, end, ExprTypeChecked, None) { + if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) { + if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) { // ...and the start index is greater than the end index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the diff --git a/src/matches.rs b/src/matches.rs index bce93b717a3..db4ccf2dcdb 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -461,8 +461,8 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & let mut values = Vec::with_capacity(2 * ranges.len()); for r in ranges { - values.push(Kind::Start(r.node.0, &r)); - values.push(Kind::End(r.node.1, &r)); + values.push(Kind::Start(r.node.0, r)); + values.push(Kind::End(r.node.1, r)); } values.sort(); @@ -475,7 +475,7 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, & } } (&Kind::End(a, _), &Kind::Start(b, _)) if a != b => (), - _ => return Some((&a.range(), &b.range())), + _ => return Some((a.range(), b.range())), } } diff --git a/src/methods.rs b/src/methods.rs index 44fdab454a3..5b86aab1aa1 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -365,7 +365,7 @@ impl LateLintPass for MethodsPass { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); } - lint_or_fun_call(cx, expr, &name.node.as_str(), &args); + lint_or_fun_call(cx, expr, &name.node.as_str(), args); let self_ty = cx.tcx.expr_ty_adjusted(&args[0]); if args.len() == 1 && name.node.as_str() == "clone" { @@ -420,7 +420,7 @@ impl LateLintPass for MethodsPass { // check conventions w.r.t. conversion method names and predicates let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; - let is_copy = is_copy(cx, &ty, &item); + let is_copy = is_copy(cx, ty, item); for &(ref conv, self_kinds) in &CONVENTIONS { if conv.check(&name.as_str()) && !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { diff --git a/src/misc.rs b/src/misc.rs index 7323f18a46e..25747157c0f 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -424,7 +424,7 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { match parent.node { ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, - _ => is_used(cx, &parent), + _ => is_used(cx, parent), } } else { true diff --git a/src/mut_reference.rs b/src/mut_reference.rs index 4ac4d83360e..f6aee54d90b 100644 --- a/src/mut_reference.rs +++ b/src/mut_reference.rs @@ -39,13 +39,13 @@ impl LateLintPass for UnnecessaryMutPassed { If this happened, the compiler would have \ aborted the compilation long ago"); if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, &arguments, function_type, &path.to_string()); + check_arguments(cx, arguments, function_type, &path.to_string()); } } ExprMethodCall(ref name, _, ref arguments) => { let method_call = MethodCall::expr(e.id); let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); - check_arguments(cx, &arguments, method_type.ty, &name.node.as_str()) + check_arguments(cx, arguments, method_type.ty, &name.node.as_str()) } _ => (), } diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 0c6fdc37066..9d2139fe422 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -249,7 +249,7 @@ impl EarlyLintPass for NonExpressiveNames { let mut visitor = SimilarNamesLocalVisitor { names: Vec::new(), cx: cx, - lint: &self, + lint: self, single_char_names: Vec::new(), }; // initialize with function arguments diff --git a/src/shadow.rs b/src/shadow.rs index bb287f449e3..4b6439c4eb3 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -278,7 +278,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { let len = bindings.len(); for ref arm in arms { for ref pat in &arm.pats { - check_pat(cx, &pat, &Some(&**init), pat.span, bindings); + check_pat(cx, pat, &Some(&**init), pat.span, bindings); // This is ugly, but needed to get the right type if let Some(ref guard) = arm.guard { check_expr(cx, guard, bindings); diff --git a/src/types.rs b/src/types.rs index 43d42cde501..f63538e974d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -910,7 +910,7 @@ fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons: if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { if rel == Rel::Eq || rel == Rel::Ne { if norm_rhs_val < lb || norm_rhs_val > ub { - err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne); + err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } } else if match rel { Rel::Lt => { @@ -929,7 +929,7 @@ fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons: } Rel::Eq | Rel::Ne => unreachable!(), } { - err_upcast_comparison(cx, &span, lhs, true) + err_upcast_comparison(cx, span, lhs, true) } else if match rel { Rel::Lt => { if invert { @@ -947,7 +947,7 @@ fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons: } Rel::Eq | Rel::Ne => unreachable!(), } { - err_upcast_comparison(cx, &span, lhs, false) + err_upcast_comparison(cx, span, lhs, false) } } } -- cgit 1.4.1-3-g733a5 From ba8653a8da189aaa629bd1e70c09146e23671328 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 26 Apr 2016 17:06:08 +0200 Subject: fallout --- src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index 248b5bfe9e6..96956d1793b 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -164,6 +164,7 @@ impl PartialOrd for Constant { } } (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { match lv.partial_cmp(rv) { @@ -171,7 +172,6 @@ impl PartialOrd for Constant { x => x, } } - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l.partial_cmp(r), _ => None, //TODO: Are there any useful inter-type orderings? } } -- cgit 1.4.1-3-g733a5 From 654154d8e7e770dc7328024efb5451a7503d5d6d Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 17 Feb 2016 18:16:29 +0100 Subject: `cargo clippy` subcommand --- .travis.yml | 3 +- Cargo.toml | 6 +++ README.md | 30 +++++++++++- src/lib.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- tests/dogfood.rs | 16 ++++--- 5 files changed, 185 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 012d6045cd2..b204bb0b2f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,9 @@ script: - remark -f README.md > /dev/null - python util/update_lints.py -c - cargo build --features debugging - - rm -rf target/ Cargo.lock - cargo test --features debugging + - SYSROOT=~/rust cargo install + - cargo clippy --lib -- -D clippy after_success: # only test regex_macros if it compiles diff --git a/Cargo.toml b/Cargo.toml index cd6b2834c56..470d2dd7096 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,12 @@ keywords = ["clippy", "lint", "plugin"] [lib] name = "clippy" plugin = true +test = false + +[[bin]] +name = "cargo-clippy" +path = "src/lib.rs" +test = false [dependencies] regex-syntax = "0.3.0" diff --git a/README.md b/README.md index 8f3519c95c4..ee234432c63 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,8 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ## Usage +### As a Compiler Plugin + Compiler plugins are highly unstable and will only work with a nightly Rust for now. Since stable Rust is backwards compatible, you should be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent @@ -217,8 +219,28 @@ src/main.rs:8:5: 11:6 help: Try if let Some(y) = x { println!("{:?}", y) } ``` -An alternate way to use clippy is by compiling and using [`cargo clippy`](https://github.com/arcnmx/cargo-clippy), -a custom cargo subcommand that runs clippy on a given project. +### As a cargo subcommand (`cargo clippy`) + +An alternate way to use clippy is by installing clippy through cargo as a cargo +subcommand. + +```terminal +cargo install clippy +``` + +Now you can run clippy by invoking `cargo clippy`, or +`multirust run nightly cargo clippy` directly from a directory that is usually +compiled with stable. + +In case you are not using multirust, you need to set the environment flag +`SYSROOT` during installation so clippy knows where to find `librustc` and +similar crates. + +```terminal +SYSROOT=/path/to/rustc/sysroot cargo install clippy +``` + +### Configuring clippy You can add options to `allow`/`warn`/`deny`: @@ -234,6 +256,8 @@ You can add options to `allow`/`warn`/`deny`: Note: `deny` produces errors instead of warnings +### Running clippy from the command line without installing + To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` in your code, you can use: @@ -244,6 +268,8 @@ cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy *[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! +### Optional dependency + If you want to make clippy an optional dependency, you can do the following: In your `Cargo.toml`: diff --git a/src/lib.rs b/src/lib.rs index e5d374a560f..5dd473c8d09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,11 +9,145 @@ #![allow(indexing_slicing, shadow_reuse, unknown_lints)] #![allow(float_arithmetic, integer_arithmetic)] -// this only exists to allow the "dogfood" integration test to work -#[allow(dead_code)] -#[allow(print_stdout)] -fn main() { - println!("What are you doing? Don't run clippy as an executable"); +extern crate rustc_driver; +extern crate getopts; + +use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use rustc::session::{config, Session}; +use rustc::session::config::{Input, ErrorOutputType}; +use syntax::diagnostics; +use std::path::PathBuf; + +struct ClippyCompilerCalls(RustcDefaultCalls); + +impl std::default::Default for ClippyCompilerCalls { + fn default() -> Self { + Self::new() + } +} + +impl ClippyCompilerCalls { + fn new() -> Self { + ClippyCompilerCalls(RustcDefaultCalls) + } +} + +impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { + fn early_callback(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + descriptions: &diagnostics::registry::Registry, + output: ErrorOutputType) + -> Compilation { + self.0.early_callback(matches, sopts, descriptions, output) + } + fn no_input(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + odir: &Option<PathBuf>, + ofile: &Option<PathBuf>, + descriptions: &diagnostics::registry::Registry) + -> Option<(Input, Option<PathBuf>)> { + self.0.no_input(matches, sopts, odir, ofile, descriptions) + } + fn late_callback(&mut self, + matches: &getopts::Matches, + sess: &Session, + input: &Input, + odir: &Option<PathBuf>, + ofile: &Option<PathBuf>) + -> Compilation { + self.0.late_callback(matches, sess, input, odir, ofile) + } + fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { + let mut control = self.0.build_controller(sess, matches); + + let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); + control.after_parse.callback = Box::new(move |state| { + { + let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed")); + registry.args_hidden = Some(Vec::new()); + plugin_registrar(&mut registry); + + let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } + + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } + + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.mir_passes.borrow_mut().extend(mir_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + } + old(state); + }); + + control + } +} + +use std::path::Path; + +pub fn main() { + use std::env; + + if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { + return; + } + + let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps"); + let sys_root = match (option_env!("MULTIRUST_HOME"), option_env!("MULTIRUST_TOOLCHAIN")) { + (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), + _ => option_env!("SYSROOT").expect("need to specify SYSROOT env var during clippy compilation or use multirust").to_owned(), + }; + + if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { + let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); + let path = std::env::current_exe().expect("current executable path invalid"); + let run = std::process::Command::new("cargo") + .args(&args) + .env("RUSTC", path) + .spawn().expect("could not run cargo") + .wait().expect("failed to wait for cargo?") + .success(); + assert!(run, "cargo rustc failed"); + } else { + let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { + env::args().collect() + } else { + env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() + }; + rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); + } +} + +fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String> + where P: AsRef<Path>, I: Iterator<Item=String> { + + let mut args = vec!["rustc".to_owned()]; + + let mut found_dashes = false; + for arg in old_args { + found_dashes |= arg == "--"; + args.push(arg); + } + if !found_dashes { + args.push("--".to_owned()); + } + args.push("-L".to_owned()); + args.push(dep_path.as_ref().to_string_lossy().into_owned()); + args.push(String::from("--sysroot")); + args.push(sysroot); + args.push("-Zno-trans".to_owned()); + args } #[macro_use] diff --git a/tests/dogfood.rs b/tests/dogfood.rs index b5ae813ae51..d050b4fc5ba 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,9 +1,11 @@ -#![feature(test)] +#![feature(test, plugin)] +#![plugin(clippy)] +#![deny(clippy, clippy_pedantic)] extern crate compiletest_rs as compiletest; extern crate test; -use std::env::var; +use std::env::{var, set_var}; use std::path::PathBuf; use test::TestPaths; @@ -11,15 +13,14 @@ use test::TestPaths; fn dogfood() { let mut config = compiletest::default_config(); - let cfg_mode = "run-pass".parse().ok().expect("Invalid mode"); + let cfg_mode = "run-pass".parse().expect("Invalid mode"); let mut s = String::new(); s.push_str(" -L target/debug/"); s.push_str(" -L target/debug/deps"); s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy"); config.target_rustcflags = Some(s); - if let Ok(name) = var::<&str>("TESTNAME") { - let s : String = name.to_owned(); - config.filter = Some(s) + if let Ok(name) = var("TESTNAME") { + config.filter = Some(name.to_owned()) } config.mode = cfg_mode; @@ -29,5 +30,8 @@ fn dogfood() { file: PathBuf::from("src/lib.rs"), relative_dir: PathBuf::new(), }; + + set_var("CLIPPY_DOGFOOD", "tastes like chicken"); + compiletest::runtest::run(config, &paths); } -- cgit 1.4.1-3-g733a5 From f227225acdd3ca85d619f03b6a4727def546329d Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Tue, 10 May 2016 00:35:51 +0900 Subject: Remove unused imports --- src/attrs.rs | 1 - src/enum_clike.rs | 1 - src/enum_variants.rs | 1 - src/if_not_else.rs | 1 - src/items_after_statements.rs | 1 - src/methods.rs | 1 - 6 files changed, 6 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index 6106486c71e..ca7813d3860 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -5,7 +5,6 @@ use rustc::lint::*; use rustc::hir::*; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; -use syntax::attr::*; use syntax::codemap::Span; use utils::{in_macro, match_path, span_lint}; use utils::paths; diff --git a/src/enum_clike.rs b/src/enum_clike.rs index e3e8f1e5eb6..39c31864f39 100644 --- a/src/enum_clike.rs +++ b/src/enum_clike.rs @@ -4,7 +4,6 @@ use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc_const_math::*; use rustc::hir::*; -use syntax::attr::*; use utils::span_lint; /// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. diff --git a/src/enum_variants.rs b/src/enum_variants.rs index a1f2c5e1441..67a8495e155 100644 --- a/src/enum_variants.rs +++ b/src/enum_variants.rs @@ -2,7 +2,6 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::attr::*; use syntax::parse::token::InternedString; use utils::span_help_and_lint; use utils::{camel_case_from, camel_case_until}; diff --git a/src/if_not_else.rs b/src/if_not_else.rs index 2fc2cc10e38..d78eba9877b 100644 --- a/src/if_not_else.rs +++ b/src/if_not_else.rs @@ -1,7 +1,6 @@ //! lint on if branches that could be swapped so no `!` operation is necessary on the condition use rustc::lint::*; -use syntax::attr::*; use syntax::ast::*; use utils::span_help_and_lint; diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs index 9d8ae2e9913..2e6b33ab390 100644 --- a/src/items_after_statements.rs +++ b/src/items_after_statements.rs @@ -2,7 +2,6 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::attr::*; use utils::in_macro; /// **What it does:** This lints checks for items declared after some statement in a block diff --git a/src/methods.rs b/src/methods.rs index 5b86aab1aa1..c9cc81484cd 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,7 +1,6 @@ use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::middle::cstore::CrateStore; use rustc::ty::subst::{Subst, TypeSpace}; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; -- cgit 1.4.1-3-g733a5 From 11987f5b6f9c478cdd15543625a27fb5df1996f4 Mon Sep 17 00:00:00 2001 From: Josh Stone <cuviper@gmail.com> Date: Tue, 10 May 2016 13:45:37 -0700 Subject: Support either rustup or multirust environment variables Fixes #910 --- src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5dd473c8d09..2d05419673d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,9 +104,14 @@ pub fn main() { } let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps"); - let sys_root = match (option_env!("MULTIRUST_HOME"), option_env!("MULTIRUST_TOOLCHAIN")) { + + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + let sys_root = match (home, toolchain) { (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => option_env!("SYSROOT").expect("need to specify SYSROOT env var during clippy compilation or use multirust").to_owned(), + _ => option_env!("SYSROOT") + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") + .to_owned(), }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { -- cgit 1.4.1-3-g733a5 From c6b4b19a435a825e3c28b2851966164b5ee4ca3c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 11 May 2016 15:32:20 +0200 Subject: suggest `a op= b` over `a = a op b` --- CHANGELOG.md | 2 + README.md | 4 +- src/assign_ops.rs | 158 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +- src/utils/paths.rs | 1 + tests/compile-fail/assign_ops.rs | 65 ++++++++++++++++ tests/compile-fail/strings.rs | 2 +- 7 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 src/assign_ops.rs create mode 100644 tests/compile-fail/assign_ops.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fb3c686948..9591e207a88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,8 @@ All notable changes to this project will be documented in this file. [`absurd_extreme_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons [`almost_swapped`]: https://github.com/Manishearth/rust-clippy/wiki#almost_swapped [`approx_constant`]: https://github.com/Manishearth/rust-clippy/wiki#approx_constant +[`assign_op_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern +[`assign_ops`]: https://github.com/Manishearth/rust-clippy/wiki#assign_ops [`bad_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask [`blacklisted_name`]: https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name [`block_in_if_condition_expr`]: https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr diff --git a/README.md b/README.md index ee234432c63..658e2eb63a5 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,15 @@ Table of contents: ## Lints -There are 147 lints included in this crate: +There are 149 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison involving a maximum or minimum value involves a case that is always true or always false [almost_swapped](https://github.com/Manishearth/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant +[assign_op_pattern](https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern) | warn | assigning the result of an operation on a variable to that same variable +[assign_ops](https://github.com/Manishearth/rust-clippy/wiki#assign_ops) | allow | Any assignment operation [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [blacklisted_name](https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` diff --git a/src/assign_ops.rs b/src/assign_ops.rs new file mode 100644 index 00000000000..8dc072e69f0 --- /dev/null +++ b/src/assign_ops.rs @@ -0,0 +1,158 @@ +use rustc::hir; +use rustc::lint::*; +use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; + +/// **What it does:** This lint checks for `+=` operations and similar +/// +/// **Why is this bad?** Projects with many developers from languages without those operations +/// may find them unreadable and not worth their weight +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// a += 1; +/// ``` +declare_restriction_lint! { + pub ASSIGN_OPS, + "Any assignment operation" +} + +/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns +/// +/// **Why is this bad?** These can be written as the shorter `a op= b` +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ``` +/// let mut a = 5; +/// ... +/// a = a + b; +/// ``` +declare_lint! { + pub ASSIGN_OP_PATTERN, + Warn, + "assigning the result of an operation on a variable to that same variable" +} + +#[derive(Copy, Clone, Default)] +pub struct AssignOps; + +impl LintPass for AssignOps { + fn get_lints(&self) -> LintArray { + lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN) + } +} + +impl LateLintPass for AssignOps { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + match expr.node { + hir::ExprAssignOp(op, ref lhs, ref rhs) => { + if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) { + span_lint_and_then(cx, + ASSIGN_OPS, + expr.span, + "assign operation detected", + |db| { + match rhs.node { + hir::ExprBinary(op2, _, _) if op2 != op => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); + }, + _ => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} {}", l, l, op.node.as_str(), r)); + } + } + }); + } else { + span_lint(cx, + ASSIGN_OPS, + expr.span, + "assign operation detected"); + } + }, + hir::ExprAssign(ref assignee, ref e) => { + if let hir::ExprBinary(op, ref l, ref r) = e.node { + let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { + let ty = cx.tcx.expr_ty(assignee); + if ty.walk_shallow().next().is_some() { + return; // implements_trait does not work with generics + } + let rty = cx.tcx.expr_ty(rhs); + if rty.walk_shallow().next().is_some() { + return; // implements_trait does not work with generics + } + macro_rules! ops { + ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => { + match $op { + $(hir::$full_trait_name => { + let [krate, module] = ::utils::paths::OPS_MODULE; + let path = [krate, module, concat!(stringify!($trait_name), "Assign")]; + let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { + trait_id + } else { + return; // useless if the trait doesn't exist + }; + implements_trait($cx, $ty, trait_id, vec![$rty]) + },)* + _ => false, + } + } + } + if ops!(op.node, cx, ty, rty, Add:BiAdd, + Sub:BiSub, + Mul:BiMul, + Div:BiDiv, + Rem:BiRem, + And:BiAnd, + Or:BiOr, + BitAnd:BiBitAnd, + BitOr:BiBitOr, + BitXor:BiBitXor, + Shr:BiShr, + Shl:BiShl + ) { + if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { + span_lint_and_then(cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |db| { + db.span_suggestion(expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r)); + }); + } else { + span_lint(cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation"); + } + } + }; + // a = a op b + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { + lint(assignee, r); + } + // a = b commutative_op a + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { + match op.node { + hir::BiAdd | hir::BiMul | + hir::BiAnd | hir::BiOr | + hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => { + lint(assignee, l); + }, + _ => {}, + } + } + } + }, + _ => {}, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5dd473c8d09..aac2718b1ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ #![feature(question_mark)] #![feature(stmt_expr_attributes)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] -#![allow(float_arithmetic, integer_arithmetic)] extern crate rustc_driver; extern crate getopts; @@ -192,6 +191,7 @@ pub mod utils; pub mod approx_const; pub mod arithmetic; pub mod array_indexing; +pub mod assign_ops; pub mod attrs; pub mod bit_mask; pub mod blacklisted_name; @@ -383,10 +383,12 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_forget::MemForget); reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); + reg.register_late_lint_pass(box assign_ops::AssignOps); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, + assign_ops::ASSIGN_OPS, ]); reg.register_lint_group("clippy_pedantic", vec![ @@ -421,6 +423,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, array_indexing::OUT_OF_BOUNDS_INDEXING, + assign_ops::ASSIGN_OP_PATTERN, attrs::DEPRECATED_SEMVER, attrs::INLINE_ALWAYS, bit_mask::BAD_BIT_MASK, diff --git a/src/utils/paths.rs b/src/utils/paths.rs index c52324a7448..2e6ceb50096 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -29,6 +29,7 @@ pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "Linke pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; +pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; pub const RANGE: [&'static str; 3] = ["core", "ops", "Range"]; pub const RANGE_FROM: [&'static str; 3] = ["core", "ops", "RangeFrom"]; diff --git a/tests/compile-fail/assign_ops.rs b/tests/compile-fail/assign_ops.rs new file mode 100644 index 00000000000..84d868ecfcc --- /dev/null +++ b/tests/compile-fail/assign_ops.rs @@ -0,0 +1,65 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(assign_ops)] +#[allow(unused_assignments)] +fn main() { + let mut i = 1i32; + i += 2; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i + 2 + i -= 6; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i - 6 + i *= 5; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i * 5 + i /= 32; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i / 32 + i %= 42; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i % 42 + i >>= i; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i >> i + i <<= 9 + 6 - 7; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i << (9 + 6 - 7) +} + +#[allow(dead_code, unused_assignments)] +#[deny(assign_op_pattern)] +fn bla() { + let mut a = 5; + a = a + 1; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a += 1 + a = 1 + a; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a += 1 + a = a - 1; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a -= 1 + a = a * 99; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a *= 99 + a = 42 * a; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a *= 42 + a = a / 2; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a /= 2 + a = a % 5; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a %= 5 + a = a & 1; //~ ERROR manual implementation of an assign operation + //~^ HELP replace it with + //~| SUGGESTION a &= 1 + a = 1 - a; + a = 5 / a; + a = 42 % a; + a = 6 << a; + let mut s = String::new(); + s = s + "bla"; +} diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 656349ba621..542b6db4abb 100644 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -65,6 +65,6 @@ fn main() { // the add is only caught for String let mut x = 1; - x = x + 1; + x = x + 1; //~ WARN assign_op_pattern assert_eq!(2, x); } -- cgit 1.4.1-3-g733a5 From 49e2570b77558e9215b43926d2633eef4a25f7bd Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 11 May 2016 16:44:43 +0200 Subject: don't lint at the use-site of bad struct field bindings if they're shorthand fixes #899 --- src/non_expressive_names.rs | 25 +++++++++++++++---------- tests/compile-fail/non_expressive_names2.rs | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 tests/compile-fail/non_expressive_names2.rs diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index 9d2139fe422..e8f3858a37b 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -3,7 +3,7 @@ use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast::*; use syntax::attr; -use syntax::visit; +use syntax::visit::{Visitor, walk_block, walk_pat, walk_expr}; use utils::{span_lint_and_then, in_macro, span_lint}; /// **What it does:** This lint warns about names that are very similar and thus confusing @@ -68,12 +68,17 @@ const WHITELIST: &'static [&'static [&'static str]] = &[ struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); -impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { +impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { fn visit_pat(&mut self, pat: &'v Pat) { - if let PatKind::Ident(_, id, _) = pat.node { - self.check_name(id.span, id.node.name); + match pat.node { + PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), + PatKind::Struct(_, ref fields, _) => for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); + } + }, + _ => walk_pat(self, pat), } - visit::walk_pat(self, pat); } } @@ -219,22 +224,22 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { } } -impl<'v, 'a, 'b> visit::Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { +impl<'v, 'a, 'b> Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { fn visit_local(&mut self, local: &'v Local) { if let Some(ref init) = local.init { - self.apply(|this| visit::walk_expr(this, &**init)); + self.apply(|this| walk_expr(this, &**init)); } // add the pattern after the expression because the bindings aren't available yet in the init expression SimilarNamesNameVisitor(self).visit_pat(&*local.pat); } fn visit_block(&mut self, blk: &'v Block) { - self.apply(|this| visit::walk_block(this, blk)); + self.apply(|this| walk_block(this, blk)); } fn visit_arm(&mut self, arm: &'v Arm) { self.apply(|this| { // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); - this.apply(|this| visit::walk_expr(this, &arm.body)); + this.apply(|this| walk_expr(this, &arm.body)); }); } fn visit_item(&mut self, _: &'v Item) { @@ -257,7 +262,7 @@ impl EarlyLintPass for NonExpressiveNames { visit::walk_pat(&mut SimilarNamesNameVisitor(&mut visitor), &arg.pat); } // walk all other bindings - visit::walk_block(&mut visitor, blk); + walk_block(&mut visitor, blk); } } } diff --git a/tests/compile-fail/non_expressive_names2.rs b/tests/compile-fail/non_expressive_names2.rs new file mode 100644 index 00000000000..a0e5885c539 --- /dev/null +++ b/tests/compile-fail/non_expressive_names2.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(clippy,similar_names)] +#![allow(unused)] + +struct Foo { + apple: i32, + bpple: i32, +} + +fn main() { + let Foo { apple, bpple } = unimplemented!(); + let Foo { apple: spring, bpple: sprang } = unimplemented!(); //~ ERROR: name is too similar +} -- cgit 1.4.1-3-g733a5 From f004120495b51c925fa72156b69ebd97f011b061 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 11 May 2016 16:45:06 +0200 Subject: properly lint function argument patterns in similar_names --- src/non_expressive_names.rs | 2 +- src/shadow.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs index e8f3858a37b..cbb083a3e16 100644 --- a/src/non_expressive_names.rs +++ b/src/non_expressive_names.rs @@ -259,7 +259,7 @@ impl EarlyLintPass for NonExpressiveNames { }; // initialize with function arguments for arg in &decl.inputs { - visit::walk_pat(&mut SimilarNamesNameVisitor(&mut visitor), &arg.pat); + SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); } // walk all other bindings walk_block(&mut visitor, blk); diff --git a/src/shadow.rs b/src/shadow.rs index 4b6439c4eb3..4639a943965 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -195,7 +195,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind } } -fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: &Option<T>, prev_span: Span) +fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span) where T: Deref<Target = Expr> { fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { @@ -209,15 +209,15 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & SHADOW_SAME, span, &format!("{} is shadowed by itself in {}", - snippet(cx, lspan, "_"), + snippet(cx, pattern_span, "_"), snippet(cx, expr.span, ".."))); note_orig(cx, db, SHADOW_SAME, prev_span); } else if contains_self(name, expr) { let db = span_note_and_lint(cx, SHADOW_REUSE, - lspan, + pattern_span, &format!("{} is shadowed by {} which reuses the original value", - snippet(cx, lspan, "_"), + snippet(cx, pattern_span, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); @@ -225,9 +225,9 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & } else { let db = span_note_and_lint(cx, SHADOW_UNRELATED, - lspan, + pattern_span, &format!("{} is shadowed by {}", - snippet(cx, lspan, "_"), + snippet(cx, pattern_span, "_"), snippet(cx, expr.span, "..")), expr.span, "initialization happens here"); @@ -238,7 +238,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init: & let db = span_lint(cx, SHADOW_UNRELATED, span, - &format!("{} shadows a previous declaration", snippet(cx, lspan, "_"))); + &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_"))); note_orig(cx, db, SHADOW_UNRELATED, prev_span); } } -- cgit 1.4.1-3-g733a5 From 0bef7b5f744b24136dc77a6478aee26e0abce33a Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 11 May 2016 17:01:34 +0200 Subject: merge struct similar_name test into the general test file --- tests/compile-fail/non_expressive_names.rs | 14 ++++++++++++++ tests/compile-fail/non_expressive_names2.rs | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 tests/compile-fail/non_expressive_names2.rs diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index 61fe0067a27..d959507bcb2 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -11,8 +11,15 @@ //~| NOTE: lint level defined here //~| NOTE: lint level defined here //~| NOTE: lint level defined here +//~| NOTE: lint level defined here #![allow(unused)] + +struct Foo { + apple: i32, + bpple: i32, +} + fn main() { let specter: i32; let spectre: i32; @@ -90,6 +97,13 @@ fn main() { let rx_cake: i32; } +fn foo() { + let Foo { apple, bpple } = unimplemented!(); + let Foo { apple: spring, //~NOTE existing binding defined here + bpple: sprang } = unimplemented!(); //~ ERROR: name is too similar + //~^HELP for further information +} + #[derive(Clone, Debug)] enum MaybeInst { Split, diff --git a/tests/compile-fail/non_expressive_names2.rs b/tests/compile-fail/non_expressive_names2.rs deleted file mode 100644 index a0e5885c539..00000000000 --- a/tests/compile-fail/non_expressive_names2.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] -#![deny(clippy,similar_names)] -#![allow(unused)] - -struct Foo { - apple: i32, - bpple: i32, -} - -fn main() { - let Foo { apple, bpple } = unimplemented!(); - let Foo { apple: spring, bpple: sprang } = unimplemented!(); //~ ERROR: name is too similar -} -- cgit 1.4.1-3-g733a5 From b0d008bc9d0e2efd92c29da9c40db768b864b52b Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 11 May 2016 17:04:27 +0200 Subject: add known problems --- src/assign_ops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assign_ops.rs b/src/assign_ops.rs index 8dc072e69f0..2b1aec83e4c 100644 --- a/src/assign_ops.rs +++ b/src/assign_ops.rs @@ -7,7 +7,7 @@ use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_de /// **Why is this bad?** Projects with many developers from languages without those operations /// may find them unreadable and not worth their weight /// -/// **Known problems:** None +/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op` /// /// **Example:** /// ``` @@ -22,7 +22,7 @@ declare_restriction_lint! { /// /// **Why is this bad?** These can be written as the shorter `a op= b` /// -/// **Known problems:** Hopefully none. +/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl /// /// **Example:** /// -- cgit 1.4.1-3-g733a5 From 03a309d1825f5a65f9835c4a1e1e53b9c726011b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Wed, 11 May 2016 11:05:34 -0700 Subject: Use rustc --print sysroot, bump to v66 --- Cargo.toml | 2 +- src/lib.rs | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 470d2dd7096..3a767a97c71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.65" +version = "0.0.66" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/src/lib.rs b/src/lib.rs index 2d05419673d..205f6bd079d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; use syntax::diagnostics; use std::path::PathBuf; +use std::process::Command; struct ClippyCompilerCalls(RustcDefaultCalls); @@ -109,9 +110,14 @@ pub fn main() { let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); let sys_root = match (home, toolchain) { (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => option_env!("SYSROOT") - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") - .to_owned(), + _ => option_env!("SYSROOT").map(|s| s.to_owned()) + .or(Command::new("rustc").arg("--print") + .arg("sysroot") + .output().ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + ) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"), }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { -- cgit 1.4.1-3-g733a5 From 610883b7aa8107e805cd5b43957fb7a5a300a381 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 12 May 2016 10:23:06 +0200 Subject: don't suggest closures over constants fixes #917 --- src/methods.rs | 8 ++++++++ tests/compile-fail/methods.rs | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/methods.rs b/src/methods.rs index c9cc81484cd..b47ae924bf0 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; +use rustc::middle::const_qualif::ConstQualif; use rustc::ty::subst::{Subst, TypeSpace}; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; @@ -502,6 +503,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) /// Check for `*or(foo())`. fn check_general_case(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, or_has_args: bool, span: Span) { + // don't lint for constant values + // FIXME: can we `expect` here instead of match? + if let Some(qualif) = cx.tcx.const_qualif_map.borrow().get(&arg.id) { + if !qualif.contains(ConstQualif::NOT_CONST) { + return; + } + } // (path, fn_has_argument, methods) let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 7503cb50746..0a943840e17 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -1,4 +1,5 @@ #![feature(plugin)] +#![feature(const_fn)] #![plugin(clippy)] #![deny(clippy, clippy_pedantic)] @@ -227,8 +228,20 @@ fn or_fun_call() { fn new() -> Foo { Foo } } + enum Enum { + A(i32), + } + + const fn make_const(i: i32) -> i32 { i } + fn make<T>() -> T { unimplemented!(); } + let with_enum = Some(Enum::A(1)); + with_enum.unwrap_or(Enum::A(5)); + + let with_const_fn = Some(1); + with_const_fn.unwrap_or(make_const(5)); + let with_constructor = Some(vec![1]); with_constructor.unwrap_or(make()); //~^ERROR use of `unwrap_or` -- cgit 1.4.1-3-g733a5 From a9bea1f52b09a66a04548b8e2b959245562db229 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 12 May 2016 19:11:13 +0200 Subject: Rustup to *1.10.0-nightly (22ac88f1a 2016-05-11)* --- src/attrs.rs | 2 +- src/cyclomatic_complexity.rs | 8 ++++---- src/derive.rs | 8 ++++---- src/escape.rs | 23 ++++++++++------------- src/methods.rs | 4 ++-- src/panic.rs | 2 +- src/types.rs | 4 ++-- src/utils/mod.rs | 30 +++++++++++++++--------------- src/utils/paths.rs | 2 +- 9 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/attrs.rs b/src/attrs.rs index ca7813d3860..0cf62633de4 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -130,7 +130,7 @@ fn is_relevant_expr(expr: &Expr) -> bool { ExprRet(None) | ExprBreak(_) => false, ExprCall(ref path_expr, _) => { if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &paths::BEGIN_UNWIND) + !match_path(path, &paths::BEGIN_PANIC) } else { true } diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs index 858affd2bbb..8ae0d2c97c5 100644 --- a/src/cyclomatic_complexity.rs +++ b/src/cyclomatic_complexity.rs @@ -58,7 +58,7 @@ impl CyclomaticComplexity { divergence: 0, short_circuits: 0, returns: 0, - tcx: cx.tcx, + tcx: &cx.tcx, }; helper.visit_block(block); let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; @@ -117,15 +117,15 @@ impl LateLintPass for CyclomaticComplexity { } } -struct CCHelper<'a, 'tcx: 'a> { +struct CCHelper<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { match_arms: u64, divergence: u64, returns: u64, short_circuits: u64, // && and || - tcx: &'a ty::TyCtxt<'tcx>, + tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>, } -impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> { +impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> { fn visit_expr(&mut self, e: &'a Expr) { match e.node { ExprMatch(_, ref arms, _) => { diff --git a/src/derive.rs b/src/derive.rs index c9ac8f0a948..f08522953aa 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -86,7 +86,7 @@ impl LateLintPass for Derive { } /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { +fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { if_let_chain! {[ match_path(&trait_ref.path, &paths::HASH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() @@ -94,7 +94,7 @@ fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: & let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); // Look for the PartialEq implementations for `ty` - peq_trait_def.for_each_relevant_impl(&cx.tcx, ty, |impl_id| { + peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| { let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); if peq_is_automatically_derived == hash_is_automatically_derived { @@ -131,9 +131,9 @@ fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: & fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - let subst_ty = ty.subst(cx.tcx, ¶meter_environment.free_substs); + let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs); - if subst_ty.moves_by_default(¶meter_environment, item.span) { + if subst_ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, item.span) { return; // ty is not Copy } diff --git a/src/escape.rs b/src/escape.rs index ff841b18066..b5172269a1e 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -1,11 +1,9 @@ use rustc::hir::*; use rustc::hir::intravisit as visit; use rustc::hir::map::Node::{NodeExpr, NodeStmt}; -use rustc::infer; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt, Categorization}; -use rustc::traits::ProjectionMode; use rustc::ty::adjustment::AutoAdjustment; use rustc::ty; use rustc::util::nodemap::NodeSet; @@ -42,7 +40,7 @@ fn is_non_trait_box(ty: ty::Ty) -> bool { } struct EscapeDelegate<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, set: NodeSet, } @@ -55,15 +53,18 @@ impl LintPass for EscapePass { impl LateLintPass for EscapePass { fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(param_env), ProjectionMode::Any); + + let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); let mut v = EscapeDelegate { - cx: cx, + tcx: cx.tcx, set: NodeSet(), }; + { let mut vis = ExprUseVisitor::new(&mut v, &infcx); vis.walk_fn(decl, body); } + for node in v.set { span_lint(cx, BOXED_LOCAL, @@ -75,7 +76,6 @@ impl LateLintPass for EscapePass { impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { - if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { if let Move(DirectRefMove) = mode { @@ -87,7 +87,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { - let map = &self.cx.tcx.map; + let map = &self.tcx.map; if map.is_argument(consume_pat.id) { // Skip closure arguments if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { @@ -132,8 +132,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { - if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.cx - .tcx + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx .tables .borrow() .adjustments @@ -148,13 +147,11 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } else if LoanCause::AddrOf == loan_cause { // &x - if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.cx - .tcx + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx .tables .borrow() .adjustments - .get(&self.cx - .tcx + .get(&self.tcx .map .get_parent_node(borrow_id)) { if adj.autoderefs <= 1 { diff --git a/src/methods.rs b/src/methods.rs index b47ae924bf0..c4ea1868d33 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -560,7 +560,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &Expr) { let parent = cx.tcx.map.get_parent(expr.id); let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); - if !ty.moves_by_default(¶meter_environment, expr.span) { + if !ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, expr.span) { span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); } } @@ -1044,5 +1044,5 @@ fn is_bool(ty: &Ty) -> bool { fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &Item) -> bool { let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, item.span) + !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, item.span) } diff --git a/src/panic.rs b/src/panic.rs index 78499fa1a1a..d744d2a6308 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -33,7 +33,7 @@ impl LateLintPass for PanicPass { let ExprCall(ref fun, ref params) = ex.node, params.len() == 2, let ExprPath(None, ref path) = fun.node, - match_path(path, &paths::BEGIN_UNWIND), + match_path(path, &paths::BEGIN_PANIC), let ExprLit(ref lit) = params[0].node, is_direct_expn_of(cx, params[0].span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, diff --git a/src/types.rs b/src/types.rs index f63538e974d..0a0c7252eb7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -105,7 +105,7 @@ declare_lint! { fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; - if *bindtype == ty::TyTuple(vec![]) { + if *bindtype == ty::TyTuple(&[]) { if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { return; } @@ -162,7 +162,7 @@ impl LateLintPass for UnitCmp { if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; let sty = &cx.tcx.expr_ty(left).sty; - if *sty == ty::TyTuple(vec![]) && op.is_comparison() { + if *sty == ty::TyTuple(&[]) && op.is_comparison() { let result = match op { BiEq | BiLe | BiGe => "true", _ => "false", diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 3e77ffb2c24..10bfe56e925 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,7 +2,6 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def_id::DefId; use rustc::hir::map::Node; -use rustc::infer; use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::middle::cstore; use rustc::session::Session; @@ -274,15 +273,15 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); let ty = cx.tcx.erase_regions(&ty); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any); - let obligation = traits::predicate_for_trait_def(cx.tcx, - traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params); - - traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) + cx.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| { + let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), + trait_id, + 0, + ty, + ty_params); + + traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) + }) } /// Match an `Expr` against a chain of methods, and return the matched `Expr`s. @@ -795,7 +794,7 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { /// Convenience function to get the return type of a function or `None` if the function diverges. pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); - let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, ¶meter_env.free_substs); + let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, parameter_env.free_substs); let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); if let ty::FnConverging(ret_ty) = fn_sig.output { Some(ret_ty) @@ -809,10 +808,11 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Optio // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>, parameter_item: NodeId) -> bool { let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, parameter_item); - let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any); - let new_a = a.subst(infcx.tcx, &infcx.parameter_environment.free_substs); - let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs); - infcx.can_equate(&new_a, &new_b).is_ok() + cx.tcx.infer_ctxt(None, Some(parameter_env), ProjectionMode::Any).enter(|infcx| { + let new_a = a.subst(infcx.tcx, infcx.parameter_environment.free_substs); + let new_b = b.subst(infcx.tcx, infcx.parameter_environment.free_substs); + infcx.can_equate(&new_a, &new_b).is_ok() + }) } /// Recover the essential nodes of a desugared for loop: diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 2e6ceb50096..3db1e1c5572 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -1,6 +1,6 @@ //! This module contains paths to types and functions Clippy needs to know about. -pub const BEGIN_UNWIND: [&'static str; 3] = ["std", "rt", "begin_unwind"]; +pub const BEGIN_PANIC: [&'static str; 3] = ["std", "rt", "begin_panic"]; pub const BINARY_HEAP: [&'static str; 3] = ["collections", "binary_heap", "BinaryHeap"]; pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; -- cgit 1.4.1-3-g733a5 From 392df9fbc75ad1c2c9edf5cfda89d6fdc7617e74 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 12 May 2016 19:32:59 +0200 Subject: Bump to 0.0.67 --- CHANGELOG.md | 7 +++++++ Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9591e207a88..e442c4d7b1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.67 — 2016-05-12 +* Rustup to *rustc 1.10.0-nightly (22ac88f1a 2016-05-11)* + +## 0.0.66 — 2016-05-11 +* New `cargo clippy` subcommand +* New lints: [`assign_op_pattern`], [`assign_ops`], [`needless_borrow`] + ## 0.0.65 — 2016-05-08 * Rustup to *rustc 1.10.0-nightly (62e2b2fb7 2016-05-06)* * New lints: [`float_arithmetic`], [`integer_arithmetic`] diff --git a/Cargo.toml b/Cargo.toml index 3a767a97c71..69235f05f6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.66" +version = "0.0.67" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 87df6ae8cb44d57af11ad342ec55a061d3fac199 Mon Sep 17 00:00:00 2001 From: Andreas Fackler <afck@users.noreply.github.com> Date: Thu, 12 May 2016 18:52:51 +0300 Subject: fix typos --- src/functions.rs | 4 ++-- tests/compile-fail/functions.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/functions.rs b/src/functions.rs index 37b65e471fa..d9334447226 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -8,7 +8,7 @@ use utils::span_lint; /// **What it does:** Check for functions with too many parameters. /// /// **Why is this bad?** Functions with lots of parameters are considered bad style and reduce -/// readability (“what does the 5th parameter means?”). Consider grouping some parameters into a +/// readability (“what does the 5th parameter mean?”). Consider grouping some parameters into a /// new type. /// /// **Known problems:** None. @@ -70,7 +70,7 @@ impl Functions { span_lint(cx, TOO_MANY_ARGUMENTS, span, - &format!("this function has to many arguments ({}/{})", args, self.threshold)); + &format!("this function has too many arguments ({}/{})", args, self.threshold)); } } } diff --git a/tests/compile-fail/functions.rs b/tests/compile-fail/functions.rs index d3d5eee335a..2cc16568600 100644 --- a/tests/compile-fail/functions.rs +++ b/tests/compile-fail/functions.rs @@ -7,13 +7,13 @@ fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { - //~^ ERROR: this function has to many arguments (8/7) + //~^ ERROR: this function has too many arguments (8/7) } trait Foo { fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool); fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); - //~^ ERROR: this function has to many arguments (8/7) + //~^ ERROR: this function has too many arguments (8/7) } struct Bar; @@ -21,7 +21,7 @@ struct Bar; impl Bar { fn good_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - //~^ ERROR: this function has to many arguments (8/7) + //~^ ERROR: this function has too many arguments (8/7) } // ok, we don’t want to warn implementations -- cgit 1.4.1-3-g733a5 From 86e4216a5682789326488b151ab8da8c5add9dc1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git1984941651981@oli-obk.de> Date: Fri, 13 May 2016 13:45:25 +0200 Subject: don't check for an exact error message the system might change it, especially if the system language is changed --- tests/compile-fail/conf_non_existant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/conf_non_existant.rs b/tests/compile-fail/conf_non_existant.rs index 13ab7f6cebf..cf1024705ca 100644 --- a/tests/compile-fail/conf_non_existant.rs +++ b/tests/compile-fail/conf_non_existant.rs @@ -1,4 +1,4 @@ -// error-pattern: error reading Clippy's configuration file: No such file or directory +// error-pattern: error reading Clippy's configuration file #![feature(plugin)] #![plugin(clippy(conf_file="./tests/compile-fail/non_existant_conf.toml"))] -- cgit 1.4.1-3-g733a5 From c37300d899fa2dd273ce70163e540c5ecb60e130 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git1984941651981@oli-obk.de> Date: Fri, 13 May 2016 13:45:53 +0200 Subject: ignore the portability test on 32 bit it will fail in rustc --- tests/compile-fail/enums_clike.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/compile-fail/enums_clike.rs b/tests/compile-fail/enums_clike.rs index f48f9b13de4..c342bf8f332 100644 --- a/tests/compile-fail/enums_clike.rs +++ b/tests/compile-fail/enums_clike.rs @@ -1,3 +1,4 @@ +// ignore-x86 #![feature(plugin, associated_consts)] #![plugin(clippy)] #![deny(clippy)] -- cgit 1.4.1-3-g733a5 From d4e11acc1f1d58de3653f1d0878767ea112b97f5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git1984941651981@oli-obk.de> Date: Fri, 13 May 2016 13:46:13 +0200 Subject: make sure compiletest works on windows --- tests/compile-test.rs | 6 +++++- tests/dogfood.rs | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 6dcd1ff0524..66c5734cc11 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,7 +1,7 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; -use std::env::var; +use std::env::{var, temp_dir}; fn run_mode(dir: &'static str, mode: &'static str) { let mut config = compiletest::default_config(); @@ -14,6 +14,10 @@ fn run_mode(dir: &'static str, mode: &'static str) { } config.mode = cfg_mode; + if cfg!(windows) { + // work around https://github.com/laumann/compiletest-rs/issues/35 on msvc windows + config.build_base = temp_dir(); + } config.src_base = PathBuf::from(format!("tests/{}", dir)); compiletest::run_tests(&config); diff --git a/tests/dogfood.rs b/tests/dogfood.rs index d050b4fc5ba..d3021b8f2f9 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -5,7 +5,7 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::env::{var, set_var}; +use std::env::{var, set_var, temp_dir}; use std::path::PathBuf; use test::TestPaths; @@ -23,6 +23,11 @@ fn dogfood() { config.filter = Some(name.to_owned()) } + if cfg!(windows) { + // work around https://github.com/laumann/compiletest-rs/issues/35 on msvc windows + config.build_base = temp_dir(); + } + config.mode = cfg_mode; let paths = TestPaths { -- cgit 1.4.1-3-g733a5 From 1e897f1552aa490f821b7ebef949fa6ee873a04f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git1984941651981@oli-obk.de> Date: Fri, 13 May 2016 16:43:47 +0200 Subject: add a companion lint to `no_effect` with suggestions for partially effective statements --- CHANGELOG.md | 1 + README.md | 3 +- src/lib.rs | 1 + src/no_effect.rs | 78 +++++++++++++++++++++++- tests/compile-fail/absurd-extreme-comparisons.rs | 2 +- tests/compile-fail/arithmetic.rs | 12 ++-- tests/compile-fail/array_indexing.rs | 2 +- tests/compile-fail/bit_masks.rs | 4 +- tests/compile-fail/cast.rs | 2 +- tests/compile-fail/cmp_nan.rs | 2 +- tests/compile-fail/cmp_owned.rs | 1 + tests/compile-fail/copies.rs | 2 +- tests/compile-fail/eq_op.rs | 2 +- tests/compile-fail/float_cmp.rs | 2 +- tests/compile-fail/identity_op.rs | 2 +- tests/compile-fail/invalid_upcast_comparisons.rs | 2 +- tests/compile-fail/methods.rs | 1 + tests/compile-fail/modulo_one.rs | 2 +- tests/compile-fail/mut_mut.rs | 2 +- tests/compile-fail/neg_multiply.rs | 8 +-- tests/compile-fail/no_effect.rs | 75 +++++++++++++++++------ tests/compile-fail/unit_cmp.rs | 2 +- 22 files changed, 161 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e442c4d7b1d..6e27b3909d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -215,6 +215,7 @@ All notable changes to this project will be documented in this file. [`unicode_not_nfc`]: https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc [`unit_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#unit_cmp [`unnecessary_mut_passed`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed +[`unnecessary_operation`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_operation [`unneeded_field_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern [`unsafe_removed_from_name`]: https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name [`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice diff --git a/README.md b/README.md index 658e2eb63a5..c7a839dc803 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 149 lints included in this crate: +There are 150 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -154,6 +154,7 @@ name [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) [unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument is passed as a mutable reference although the function/method only demands an immutable reference +[unnecessary_operation](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_operation) | warn | outer expressions with no effect [unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | Struct fields are bound to a wildcard instead of using `..` [unsafe_removed_from_name](https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name) | warn | unsafe removed from name [unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop diff --git a/src/lib.rs b/src/lib.rs index 37464e766b0..f1c815f0df0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -519,6 +519,7 @@ pub fn plugin_registrar(reg: &mut Registry) { neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, non_expressive_names::MANY_SINGLE_CHAR_NAMES, open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, diff --git a/src/no_effect.rs b/src/no_effect.rs index d928de41578..593a6c4ad59 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,7 +1,8 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::def::Def; +use rustc::hir::def::{Def, PathResolution}; use rustc::hir::{Expr, Expr_, Stmt, StmtSemi}; -use utils::{in_macro, span_lint}; +use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then}; +use std::ops::Deref; /// **What it does:** This lint checks for statements which have no effect. /// @@ -16,6 +17,19 @@ declare_lint! { "statements with no effect" } +/// **What it does:** This lint checks for expression statements that can be reduced to a sub-expression +/// +/// **Why is this bad?** Expressions by themselves often have no side-effects. Having such expressions reduces redability. +/// +/// **Known problems:** None. +/// +/// **Example:** `compute_array()[0];` +declare_lint! { + pub UNNECESSARY_OPERATION, + Warn, + "outer expressions with no effect" +} + fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { if in_macro(cx, expr.span) { return false; @@ -68,7 +82,7 @@ pub struct NoEffectPass; impl LintPass for NoEffectPass { fn get_lints(&self) -> LintArray { - lint_array!(NO_EFFECT) + lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) } } @@ -77,7 +91,65 @@ impl LateLintPass for NoEffectPass { if let StmtSemi(ref expr, _) = stmt.node { if has_no_effect(cx, expr) { span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); + } else if let Some(reduced) = reduce_expression(cx, expr) { + let mut snippet = String::new(); + for e in reduced { + if in_macro(cx, e.span) { + return; + } + if let Some(snip) = snippet_opt(cx, e.span) { + snippet.push_str(&snip); + snippet.push(';'); + } else { + return; + } + } + span_lint_and_then(cx, UNNECESSARY_OPERATION, stmt.span, "statement can be reduced", |db| { + db.span_suggestion(stmt.span, "replace it with", snippet); + }); + } + } + } +} + + +fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Expr>> { + if in_macro(cx, expr.span) { + return None; + } + match expr.node { + Expr_::ExprIndex(ref a, ref b) | + Expr_::ExprBinary(_, ref a, ref b) => Some(vec![&**a, &**b]), + Expr_::ExprVec(ref v) | + Expr_::ExprTup(ref v) => Some(v.iter().map(Deref::deref).collect()), + Expr_::ExprRepeat(ref inner, _) | + Expr_::ExprCast(ref inner, _) | + Expr_::ExprType(ref inner, _) | + Expr_::ExprUnary(_, ref inner) | + Expr_::ExprField(ref inner, _) | + Expr_::ExprTupField(ref inner, _) | + Expr_::ExprAddrOf(_, ref inner) | + Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), + Expr_::ExprStruct(_, ref fields, ref base) => Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()), + Expr_::ExprCall(ref callee, ref args) => { + match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) { + Some(Def::Struct(..)) | + Some(Def::Variant(..)) => Some(args.iter().map(Deref::deref).collect()), + _ => None, + } + } + Expr_::ExprBlock(ref block) => { + if block.stmts.is_empty() { + block.expr.as_ref().and_then(|e| if e.span == expr.span { + // in case of compiler-inserted signaling blocks + reduce_expression(cx, e) + } else { + Some(vec![e]) + }) + } else { + None } } + _ => None, } } diff --git a/tests/compile-fail/absurd-extreme-comparisons.rs b/tests/compile-fail/absurd-extreme-comparisons.rs index 7e2ad1fede5..f1e4a692800 100644 --- a/tests/compile-fail/absurd-extreme-comparisons.rs +++ b/tests/compile-fail/absurd-extreme-comparisons.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(absurd_extreme_comparisons)] -#![allow(unused, eq_op, no_effect)] +#![allow(unused, eq_op, no_effect, unnecessary_operation)] fn main() { const Z: u32 = 0; diff --git a/tests/compile-fail/arithmetic.rs b/tests/compile-fail/arithmetic.rs index 54ac65970ae..5479c55e11e 100644 --- a/tests/compile-fail/arithmetic.rs +++ b/tests/compile-fail/arithmetic.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(integer_arithmetic, float_arithmetic)] -#![allow(unused, shadow_reuse, shadow_unrelated, no_effect)] +#![allow(unused, shadow_reuse, shadow_unrelated, no_effect, unnecessary_operation)] fn main() { let i = 1i32; 1 + i; //~ERROR integer arithmetic detected @@ -11,17 +11,17 @@ fn main() { i / 2; // no error, this is part of the expression in the preceding line i - 2 + 2 - i; //~ERROR integer arithmetic detected -i; //~ERROR integer arithmetic detected - + i & 1; // no wrapping - i | 1; + i | 1; i ^ 1; i >> 1; i << 1; - + let f = 1.0f32; - + f * 2.0; //~ERROR floating-point arithmetic detected - + 1.0 + f; //~ERROR floating-point arithmetic detected f * 2.0; //~ERROR floating-point arithmetic detected f / 2.0; //~ERROR floating-point arithmetic detected diff --git a/tests/compile-fail/array_indexing.rs b/tests/compile-fail/array_indexing.rs index 35fadf8c1e4..dacb72ee8ac 100644 --- a/tests/compile-fail/array_indexing.rs +++ b/tests/compile-fail/array_indexing.rs @@ -3,7 +3,7 @@ #![deny(indexing_slicing)] #![deny(out_of_bounds_indexing)] -#![allow(no_effect)] +#![allow(no_effect, unnecessary_operation)] fn main() { let x = [1,2,3,4]; diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index 98135295862..79772840c73 100644 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -5,7 +5,7 @@ const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] -#[allow(ineffective_bit_mask, identity_op, no_effect)] +#[allow(ineffective_bit_mask, identity_op, no_effect, unnecessary_operation)] fn main() { let x = 5; @@ -45,7 +45,7 @@ fn main() { } #[deny(ineffective_bit_mask)] -#[allow(bad_bit_mask, no_effect)] +#[allow(bad_bit_mask, no_effect, unnecessary_operation)] fn ineffective() { let x = 5; diff --git a/tests/compile-fail/cast.rs b/tests/compile-fail/cast.rs index 0f44fa2c1fd..d0ea5f40789 100644 --- a/tests/compile-fail/cast.rs +++ b/tests/compile-fail/cast.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap)] -#[allow(no_effect)] +#[allow(no_effect, unnecessary_operation)] fn main() { // Test cast_precision_loss 1i32 as f32; //~ERROR casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs index d2188130a61..8d173665a24 100644 --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #[deny(cmp_nan)] -#[allow(float_cmp, no_effect)] +#[allow(float_cmp, no_effect, unnecessary_operation)] fn main() { let x = 5f32; x == std::f32::NAN; //~ERROR doomed comparison with NAN diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs index eb4070d8fd6..f7c7824e9d1 100644 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #[deny(cmp_owned)] +#[allow(unnecessary_operation)] fn main() { fn with_to_string(x : &str) { x != "foo".to_string(); diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 68756a57cc7..bbdd73dc0c8 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -1,7 +1,7 @@ #![feature(plugin, inclusive_range_syntax)] #![plugin(clippy)] -#![allow(dead_code, no_effect)] +#![allow(dead_code, no_effect, unnecessary_operation)] #![allow(let_and_return)] #![allow(needless_return)] #![allow(unused_variables)] diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs index 443bbbaacd3..768eadd00eb 100644 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -3,7 +3,7 @@ #[deny(eq_op)] #[allow(identity_op)] -#[allow(no_effect, unused_variables)] +#[allow(no_effect, unused_variables, unnecessary_operation)] #[deny(nonminimal_bool)] fn main() { // simple values and comparisons diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index d1ecb37cdd5..85df1ded5ac 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(float_cmp)] -#![allow(unused, no_effect)] +#![allow(unused, no_effect, unnecessary_operation)] use std::ops::Add; diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs index 28873ee6b73..329c4a6bbf4 100644 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -5,7 +5,7 @@ const ONE : i64 = 1; const NEG_ONE : i64 = -1; const ZERO : i64 = 0; -#[allow(eq_op, no_effect)] +#[allow(eq_op, no_effect, unnecessary_operation)] #[deny(identity_op)] fn main() { let x = 0; diff --git a/tests/compile-fail/invalid_upcast_comparisons.rs b/tests/compile-fail/invalid_upcast_comparisons.rs index 443dd89aab9..9635f3afede 100644 --- a/tests/compile-fail/invalid_upcast_comparisons.rs +++ b/tests/compile-fail/invalid_upcast_comparisons.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(invalid_upcast_comparisons)] -#![allow(unused, eq_op, no_effect)] +#![allow(unused, eq_op, no_effect, unnecessary_operation)] fn main() { let zero: u32 = 0; let u8_max: u8 = 255; diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 0a943840e17..88a1e7c4cf2 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -341,6 +341,7 @@ struct MyErrorWithParam<T> { x: T } +#[allow(unnecessary_operation)] fn starts_with() { "".chars().next() == Some(' '); //~^ ERROR starts_with diff --git a/tests/compile-fail/modulo_one.rs b/tests/compile-fail/modulo_one.rs index e84209a6d1e..496c1c60d5f 100644 --- a/tests/compile-fail/modulo_one.rs +++ b/tests/compile-fail/modulo_one.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] #![deny(modulo_one)] -#![allow(no_effect)] +#![allow(no_effect, unnecessary_operation)] fn main() { 10 % 1; //~ERROR any number modulo 1 will be 0 diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 0db9cb3bdef..865574eaec0 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused, no_effect)] +#![allow(unused, no_effect, unnecessary_operation)] //#![plugin(regex_macros)] //extern crate regex; diff --git a/tests/compile-fail/neg_multiply.rs b/tests/compile-fail/neg_multiply.rs index 9deb38920de..90c63c5f263 100644 --- a/tests/compile-fail/neg_multiply.rs +++ b/tests/compile-fail/neg_multiply.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(neg_multiply)] -#![allow(no_effect)] +#![allow(no_effect, unnecessary_operation)] use std::ops::Mul; @@ -10,7 +10,7 @@ struct X; impl Mul<isize> for X { type Output = X; - + fn mul(self, _r: isize) -> Self { self } @@ -18,7 +18,7 @@ impl Mul<isize> for X { impl Mul<X> for isize { type Output = X; - + fn mul(self, _r: X) -> X { X } @@ -34,7 +34,7 @@ fn main() { //~^ ERROR Negation by multiplying with -1 -1 * -1; // should be ok - + X * -1; // should be ok -1 * X; // should also be ok } diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index 344c82f3307..ce6daa8d562 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -1,7 +1,7 @@ #![feature(plugin, box_syntax, inclusive_range_syntax)] #![plugin(clippy)] -#![deny(no_effect)] +#![deny(no_effect, unnecessary_operation)] #![allow(dead_code)] #![allow(path_statements)] @@ -50,22 +50,59 @@ fn main() { // Do not warn get_number(); - Tuple(get_number()); - Struct { field: get_number() }; - Struct { ..get_struct() }; - Enum::Tuple(get_number()); - Enum::Struct { field: get_number() }; - 5 + get_number(); - *&get_number(); - &get_number(); - (5, 6, get_number()); - box get_number(); - get_number()..; - ..get_number(); - 5..get_number(); - [42, get_number()]; - [42, 55][get_number() as usize]; - (42, get_number()).1; - [get_number(); 55]; - [42; 55][get_number() as usize]; + + Tuple(get_number()); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + Struct { field: get_number() }; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + Struct { ..get_struct() }; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + Enum::Tuple(get_number()); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + Enum::Struct { field: get_number() }; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + 5 + get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION 5;get_number(); + *&get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION &get_number(); + &get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + (5, 6, get_number()); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION 5;6;get_number(); + box get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + get_number()..; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + ..get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + 5..get_number(); //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION 5;get_number(); + [42, get_number()]; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION 42;get_number(); + [42, 55][get_number() as usize]; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION [42, 55];get_number() as usize; + (42, get_number()).1; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION 42;get_number(); + [get_number(); 55]; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); + [42; 55][get_number() as usize]; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION [42; 55];get_number() as usize; } diff --git a/tests/compile-fail/unit_cmp.rs b/tests/compile-fail/unit_cmp.rs index 1a28953ace1..13095ee6bfb 100644 --- a/tests/compile-fail/unit_cmp.rs +++ b/tests/compile-fail/unit_cmp.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![deny(unit_cmp)] -#![allow(no_effect)] +#![allow(no_effect, unnecessary_operation)] #[derive(PartialEq)] pub struct ContainsUnit(()); // should be fine -- cgit 1.4.1-3-g733a5 From f2f5fefd0017ec22a306e6af85caa9468209a94d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 16 May 2016 22:39:16 +0530 Subject: Allow invalid upcast comparisons --- README.md | 2 +- src/lib.rs | 2 +- src/types.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c7a839dc803..02b7365e890 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ name [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [integer_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic) | allow | Any integer arithmetic statement [invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations -[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | warn | a comparison involving an upcast which is always true or false +[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` diff --git a/src/lib.rs b/src/lib.rs index f1c815f0df0..695491e9523 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -427,6 +427,7 @@ pub fn plugin_registrar(reg: &mut Registry) { types::CAST_POSSIBLE_WRAP, types::CAST_PRECISION_LOSS, types::CAST_SIGN_LOSS, + types::INVALID_UPCAST_COMPARISONS, unicode::NON_ASCII_LITERAL, unicode::UNICODE_NOT_NFC, ]); @@ -543,7 +544,6 @@ pub fn plugin_registrar(reg: &mut Registry) { types::ABSURD_EXTREME_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, - types::INVALID_UPCAST_COMPARISONS, types::LET_UNIT_VALUE, types::LINKEDLIST, types::TYPE_COMPLEXITY, diff --git a/src/types.rs b/src/types.rs index 0a0c7252eb7..c4b810a7880 100644 --- a/src/types.rs +++ b/src/types.rs @@ -777,11 +777,11 @@ impl LateLintPass for AbsurdExtremeComparisons { /// /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` will mistakenly imply that it is possible for `x` to be outside the range of `u8`. /// -/// **Known problems:** None +/// **Known problems:** https://github.com/Manishearth/rust-clippy/issues/886 /// /// **Example:** `let x : u8 = ...; (x as u32) > 300` declare_lint! { - pub INVALID_UPCAST_COMPARISONS, Warn, + pub INVALID_UPCAST_COMPARISONS, Allow, "a comparison involving an upcast which is always true or false" } -- cgit 1.4.1-3-g733a5 From 6a309af2f3855ed16f4f914ccbe13bce7de6c59a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 16 May 2016 23:12:55 +0530 Subject: Don't panic if cargo rustc fails --- src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 695491e9523..d3940575659 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,13 +122,11 @@ pub fn main() { if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); let path = std::env::current_exe().expect("current executable path invalid"); - let run = std::process::Command::new("cargo") + std::process::Command::new("cargo") .args(&args) .env("RUSTC", path) .spawn().expect("could not run cargo") - .wait().expect("failed to wait for cargo?") - .success(); - assert!(run, "cargo rustc failed"); + .wait().expect("failed to wait for cargo?"); } else { let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { env::args().collect() -- cgit 1.4.1-3-g733a5 From ca05e93c105f6bd484258e3dca92bbd99d661e44 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 17 May 2016 23:25:20 +0200 Subject: Rustup to *1.10.0-nightly (cd6a40017 2016-05-16)* --- src/len_zero.rs | 6 +- src/lifetimes.rs | 33 +++------ src/methods.rs | 152 ++++++++++++++++++++-------------------- tests/compile-fail/unused_lt.rs | 6 ++ 4 files changed, 94 insertions(+), 103 deletions(-) diff --git a/src/len_zero.rs b/src/len_zero.rs index 9dae856764a..b6dea831690 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -126,10 +126,10 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { } fn is_self_sig(sig: &MethodSig) -> bool { - if let SelfStatic = sig.explicit_self.node { - false - } else { + if sig.decl.has_self() { sig.decl.inputs.len() == 1 + } else { + false } } diff --git a/src/lifetimes.rs b/src/lifetimes.rs index b9771e18ffc..797e9708b60 100644 --- a/src/lifetimes.rs +++ b/src/lifetimes.rs @@ -46,19 +46,19 @@ impl LintPass for LifetimePass { impl LateLintPass for LifetimePass { fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { - check_fn_inner(cx, decl, None, generics, item.span); + check_fn_inner(cx, decl, generics, item.span); } } fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { if let ImplItemKind::Method(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, &sig.generics, item.span); } } fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { if let MethodTraitItem(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self), &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, &sig.generics, item.span); } } } @@ -87,7 +87,7 @@ fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { } } -fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, generics: &Generics, span: Span) { +fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Span) { if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; } @@ -96,16 +96,16 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>, g .iter() .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); - if could_use_elision(cx, decl, slf, &generics.lifetimes, bounds_lts) { + if could_use_elision(cx, decl, &generics.lifetimes, bounds_lts) { span_lint(cx, NEEDLESS_LIFETIMES, span, "explicit lifetimes given in parameter types where they could be elided"); } - report_extra_lifetimes(cx, decl, generics, slf); + report_extra_lifetimes(cx, decl, generics); } -fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, +fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, named_lts: &[LifetimeDef], bounds_lts: T) -> bool { // There are two scenarios where elision works: @@ -121,15 +121,6 @@ fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, fun let mut input_visitor = RefVisitor::new(cx); let mut output_visitor = RefVisitor::new(cx); - // extract lifetime in "self" argument for methods (there is a "self" argument - // in func.inputs, but its type is TyInfer) - if let Some(slf) = slf { - match slf.node { - SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), - SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), - _ => (), - } - } // extract lifetimes in input argument types for arg in &func.inputs { input_visitor.visit_ty(&arg.ty); @@ -340,7 +331,7 @@ impl<'v> Visitor<'v> for LifetimeChecker { } } -fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics, slf: Option<&ExplicitSelf>) { +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) { let hs = generics.lifetimes .iter() .map(|lt| (lt.lifetime.name, lt.lifetime.span)) @@ -350,14 +341,6 @@ fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics, walk_generics(&mut checker, generics); walk_fn_decl(&mut checker, func); - if let Some(slf) = slf { - match slf.node { - SelfRegion(Some(ref lt), _, _) => checker.visit_lifetime(lt), - SelfExplicit(ref t, _) => walk_ty(&mut checker, t), - _ => (), - } - } - for &v in checker.0.values() { span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); } diff --git a/src/methods.rs b/src/methods.rs index c4ea1868d33..ecbdb62f05e 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -1,4 +1,4 @@ -use rustc::hir::*; +use rustc::hir; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::const_qualif::ConstQualif; @@ -335,13 +335,13 @@ impl LintPass for MethodsPass { } impl LateLintPass for MethodsPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { if in_macro(cx, expr.span) { return; } match expr.node { - ExprMethodCall(name, _, ref args) => { + hir::ExprMethodCall(name, _, ref args) => { // Chain calls if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { lint_unwrap(cx, expr, arglists[0]); @@ -384,37 +384,36 @@ impl LateLintPass for MethodsPass { _ => (), } } - ExprBinary(op, ref lhs, ref rhs) if op.node == BiEq || op.node == BiNe => { - if !lint_chars_next(cx, expr, lhs, rhs, op.node == BiEq) { - lint_chars_next(cx, expr, rhs, lhs, op.node == BiEq); + hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { + if !lint_chars_next(cx, expr, lhs, rhs, op.node == hir::BiEq) { + lint_chars_next(cx, expr, rhs, lhs, op.node == hir::BiEq); } } _ => (), } } - fn check_item(&mut self, cx: &LateContext, item: &Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if in_external_macro(cx, item.span) { return; } - if let ItemImpl(_, _, _, None, _, ref items) = item.node { + if let hir::ItemImpl(_, _, _, None, _, ref items) = item.node { for implitem in items { let name = implitem.name; - if let ImplItemKind::Method(ref sig, _) = implitem.node { + if_let_chain! {[ + let hir::ImplItemKind::Method(ref sig, _) = implitem.node, + let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), + ], { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if_let_chain! { - [ - name.as_str() == method_name, - sig.decl.inputs.len() == n_args, - out_type.matches(&sig.decl.output), - self_kind.matches(&sig.explicit_self.node, false) - ], { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); - } + if name.as_str() == method_name && + sig.decl.inputs.len() == n_args && + out_type.matches(&sig.decl.output) && + self_kind.matches(&explicit_self, false) { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); } } @@ -422,16 +421,19 @@ impl LateLintPass for MethodsPass { let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; let is_copy = is_copy(cx, ty, item); for &(ref conv, self_kinds) in &CONVENTIONS { - if conv.check(&name.as_str()) && - !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) { - let lint = if item.vis == Visibility::Public { + if_let_chain! {[ + conv.check(&name.as_str()), + let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), + !self_kinds.iter().any(|k| k.matches(&explicit_self, is_copy)), + ], { + let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION }; span_lint(cx, lint, - sig.explicit_self.span, + explicit_self.span, &format!("methods called `{}` usually take {}; consider choosing a less \ ambiguous name", conv, @@ -439,7 +441,7 @@ impl LateLintPass for MethodsPass { .map(|k| k.description()) .collect::<Vec<_>>() .join(" or "))); - } + }} } let ret_ty = return_ty(cx, implitem.id); @@ -447,19 +449,19 @@ impl LateLintPass for MethodsPass { !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { span_lint(cx, NEW_RET_NO_SELF, - sig.explicit_self.span, + explicit_self.span, "methods called `new` usually return `Self`"); } } - } + }} } } } /// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) { +fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hir::Expr>]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. - fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, + fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, span: Span) -> bool { if or_has_args { @@ -467,7 +469,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } if name == "unwrap_or" { - if let ExprPath(_, ref path) = fun.node { + if let hir::ExprPath(_, ref path) = fun.node { let path: &str = &path.segments .last() .expect("A path must have at least one segment") @@ -501,7 +503,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } /// Check for `*or(foo())`. - fn check_general_case(cx: &LateContext, name: &str, fun: &Expr, self_expr: &Expr, arg: &Expr, or_has_args: bool, + fn check_general_case(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, span: Span) { // don't lint for constant values // FIXME: can we `expect` here instead of match? @@ -545,7 +547,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } if args.len() == 2 { - if let ExprCall(ref fun, ref or_args) = args[1].node { + if let hir::ExprCall(ref fun, ref or_args) = args[1].node { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { check_general_case(cx, name, fun, &args[0], &args[1], or_has_args, expr.span); @@ -555,7 +557,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &Expr, name: &str, args: &[P<Expr>]) } /// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext, expr: &Expr) { +fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) { let ty = cx.tcx.expr_ty(expr); let parent = cx.tcx.map.get_parent(expr.id); let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); @@ -566,7 +568,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &Expr) { } /// Checks for the `CLONE_DOUBLE_REF` lint. -fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr, ty: ty::Ty) { +fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) { if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { if let ty::TyRef(..) = inner.sty { let mut db = span_lint(cx, @@ -582,7 +584,7 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr, ty: ty::Ty) } } -fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { +fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); if !match_type(cx, obj_ty, &paths::VEC) { return; @@ -599,11 +601,11 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) { } } -fn lint_cstring_as_ptr(cx: &LateContext, expr: &Expr, new: &Expr, unwrap: &Expr) { +fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { if_let_chain!{[ - let ExprCall(ref fun, ref args) = new.node, + let hir::ExprCall(ref fun, ref args) = new.node, args.len() == 1, - let ExprPath(None, ref path) = fun.node, + let hir::ExprPath(None, ref path) = fun.node, match_path(path, &paths::CSTRING_NEW), ], { span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, @@ -615,7 +617,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &Expr, new: &Expr, unwrap: &Expr) }} } -fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { +fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { ty::TySlice(_) => true, @@ -626,7 +628,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, _ => false, } } - if let ExprMethodCall(name, _, ref args) = expr.node { + if let hir::ExprMethodCall(name, _, ref args) = expr.node { if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { Some((args[0].span, "&")) } else { @@ -651,7 +653,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &Expr, ty: &ty::Ty) -> Option<(Span, #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `unwrap()` for `Option`s and `Result`s -fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { +fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); let mess = if match_type(cx, obj_ty, &paths::OPTION) { @@ -677,7 +679,7 @@ fn lint_unwrap(cx: &LateContext, expr: &Expr, unwrap_args: &MethodArgs) { #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { +fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) { // lint if the caller of `ok()` is a `Result` if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) { let result_type = cx.tcx.expr_ty(&ok_args[0]); @@ -695,7 +697,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &Expr, ok_args: &MethodArgs) { #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { +fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { // lint message @@ -726,7 +728,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwr #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { // lint message @@ -757,7 +759,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &Expr, map_args: &MethodArgs, #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint use of `filter().next() for Iterators` -fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { +fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ @@ -780,7 +782,7 @@ fn lint_filter_next(cx: &LateContext, expr: &Expr, filter_args: &MethodArgs) { #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint searching an Iterator followed by `is_some()` -fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, search_args: &MethodArgs, +fn lint_search_is_some(cx: &LateContext, expr: &hir::Expr, search_method: &str, search_args: &MethodArgs, is_some_args: &MethodArgs) { // lint if caller of search is an Iterator if match_trait_method(cx, &*is_some_args[0], &paths::ITERATOR) { @@ -803,12 +805,12 @@ fn lint_search_is_some(cx: &LateContext, expr: &Expr, search_method: &str, searc } /// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next(cx: &LateContext, expr: &Expr, chain: &Expr, other: &Expr, eq: bool) -> bool { +fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: &hir::Expr, eq: bool) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(chain, &["chars", "next"]), - let ExprCall(ref fun, ref arg_char) = other.node, + let hir::ExprCall(ref fun, ref arg_char) = other.node, arg_char.len() == 1, - let ExprPath(None, ref path) = fun.node, + let hir::ExprPath(None, ref path) = fun.node, path.segments.len() == 1 && path.segments[0].identifier.name.as_str() == "Some" ], { let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0])); @@ -838,7 +840,7 @@ fn lint_chars_next(cx: &LateContext, expr: &Expr, chain: &Expr, other: &Expr, eq } /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern(cx: &LateContext, expr: &Expr, arg: &Expr) { +fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { if let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, arg, ExprTypeChecked, None) { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); @@ -954,26 +956,26 @@ enum SelfKind { } impl SelfKind { - fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool { - match (self, slf) { - (&SelfKind::Value, &SelfValue(_)) | - (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | - (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | - (&SelfKind::No, &SelfStatic) => true, - (&SelfKind::Ref, &SelfValue(_)) | - (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, - (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), + fn matches(self, slf: &hir::ExplicitSelf, allow_value_for_ref: bool) -> bool { + match (self, &slf.node) { + (SelfKind::Value, &hir::SelfKind::Value(_)) | + (SelfKind::Ref, &hir::SelfKind::Region(_, hir::Mutability::MutImmutable)) | + (SelfKind::RefMut, &hir::SelfKind::Region(_, hir::Mutability::MutMutable)) => true, + (SelfKind::Ref, &hir::SelfKind::Value(_)) | + (SelfKind::RefMut, &hir::SelfKind::Value(_)) => allow_value_for_ref, + (_, &hir::SelfKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), + _ => false, } } - fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool { + fn matches_explicit_type(self, ty: &hir::Ty, allow_value_for_ref: bool) -> bool { match (self, &ty.node) { - (&SelfKind::Value, &TyPath(..)) | - (&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) | - (&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true, - (&SelfKind::Ref, &TyPath(..)) | - (&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref, + (SelfKind::Value, &hir::TyPath(..)) | + (SelfKind::Ref, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutImmutable, .. })) | + (SelfKind::RefMut, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutMutable, .. })) => true, + (SelfKind::Ref, &hir::TyPath(..)) | + (SelfKind::RefMut, &hir::TyPath(..)) => allow_value_for_ref, _ => false, } } @@ -1015,14 +1017,14 @@ enum OutType { } impl OutType { - fn matches(&self, ty: &FunctionRetTy) -> bool { + fn matches(&self, ty: &hir::FunctionRetTy) -> bool { match (self, ty) { - (&OutType::Unit, &DefaultReturn(_)) => true, - (&OutType::Unit, &Return(ref ty)) if ty.node == TyTup(vec![].into()) => true, - (&OutType::Bool, &Return(ref ty)) if is_bool(ty) => true, - (&OutType::Any, &Return(ref ty)) if ty.node != TyTup(vec![].into()) => true, - (&OutType::Ref, &Return(ref ty)) => { - if let TyRptr(_, _) = ty.node { + (&OutType::Unit, &hir::DefaultReturn(_)) => true, + (&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, + (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, + (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, + (&OutType::Ref, &hir::Return(ref ty)) => { + if let hir::TyRptr(_, _) = ty.node { true } else { false @@ -1033,8 +1035,8 @@ impl OutType { } } -fn is_bool(ty: &Ty) -> bool { - if let TyPath(None, ref p) = ty.node { +fn is_bool(ty: &hir::Ty) -> bool { + if let hir::TyPath(None, ref p) = ty.node { if match_path(p, &["bool"]) { return true; } @@ -1042,7 +1044,7 @@ fn is_bool(ty: &Ty) -> bool { false } -fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &Item) -> bool { +fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &hir::Item) -> bool { let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, item.span) } diff --git a/tests/compile-fail/unused_lt.rs b/tests/compile-fail/unused_lt.rs index a35718b5848..19502720993 100644 --- a/tests/compile-fail/unused_lt.rs +++ b/tests/compile-fail/unused_lt.rs @@ -44,6 +44,12 @@ impl<'a> Foo<'a> for u8 { } } +struct Bar; + +impl Bar { + fn x<'a>(&self) {} //~ ERROR this lifetime +} + // test for #489 (used lifetimes in bounds) pub fn parse<'a, I: Iterator<Item=&'a str>>(_it: &mut I) { unimplemented!() -- cgit 1.4.1-3-g733a5 From 86a2c9440dff5d09d149d7e3d5922da987ab92c9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 17 May 2016 23:26:44 +0200 Subject: Bump to 0.0.68 --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e27b3909d3..017e24b1034 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.68 — 2016-05-17 +* Rustup to *rustc 1.10.0-nightly (cd6a40017 2016-05-16)* +* New lint: [`unnecessary_operation`] + ## 0.0.67 — 2016-05-12 * Rustup to *rustc 1.10.0-nightly (22ac88f1a 2016-05-11)* diff --git a/Cargo.toml b/Cargo.toml index 69235f05f6d..49053ea1e4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.67" +version = "0.0.68" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 2a5416d662724b8e8ba68aeb4069aa37e7a406d5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 19 May 2016 23:14:34 +0200 Subject: Rustup to *1.10.0-nightly (9c6904ca1 2016-05-18)* --- README.md | 2 +- src/blacklisted_name.rs | 4 +- src/copies.rs | 2 +- src/eta_reduction.rs | 2 +- src/lib.rs | 2 +- src/loops.rs | 26 +++++------ src/map_clone.rs | 15 ++++--- src/methods.rs | 3 +- src/misc.rs | 63 ++++++++++++++++----------- src/overflow_check_conditional.rs | 4 +- src/shadow.rs | 10 ++--- src/swap.rs | 2 +- src/unsafe_removed_from_name.rs | 2 +- src/unused_label.rs | 4 +- src/utils/hir.rs | 22 +++++----- src/utils/mod.rs | 2 +- tests/compile-fail/used_underscore_binding.rs | 7 +-- 17 files changed, 93 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 02b7365e890..6843afb4ede 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ name [unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label [unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting -[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore +[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore [useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` diff --git a/src/blacklisted_name.rs b/src/blacklisted_name.rs index b515da000ee..5cb84f62651 100644 --- a/src/blacklisted_name.rs +++ b/src/blacklisted_name.rs @@ -35,11 +35,11 @@ impl LintPass for BlackListedName { impl LateLintPass for BlackListedName { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { if let PatKind::Ident(_, ref ident, _) = pat.node { - if self.blacklist.iter().any(|s| s == &*ident.node.name.as_str()) { + if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) { span_lint(cx, BLACKLISTED_NAME, pat.span, - &format!("use of a blacklisted/placeholder name `{}`", ident.node.name)); + &format!("use of a blacklisted/placeholder name `{}`", ident.node)); } } } diff --git a/src/copies.rs b/src/copies.rs index aa9f243e8c7..4344ba461dd 100644 --- a/src/copies.rs +++ b/src/copies.rs @@ -193,7 +193,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned } } PatKind::Ident(_, ref ident, ref as_pat) => { - if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) { + if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { v.insert(cx.tcx.pat_ty(pat)); } if let Some(ref as_pat) = *as_pat { diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index c9a9ef85ede..f73b6cfed2d 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -77,7 +77,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { // If it's a proper path, it can't be a local variable return; } - if p.segments[0].identifier != ident.node { + if p.segments[0].name != ident.node { // The two idents should be the same return; } diff --git a/src/lib.rs b/src/lib.rs index d3940575659..888abbc92c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -411,6 +411,7 @@ pub fn plugin_registrar(reg: &mut Registry) { methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, + misc::USED_UNDERSCORE_BINDING, mut_mut::MUT_MUT, mutex_atomic::MUTEX_INTEGER, non_expressive_names::SIMILAR_NAMES, @@ -505,7 +506,6 @@ pub fn plugin_registrar(reg: &mut Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, - misc::USED_UNDERSCORE_BINDING, misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, diff --git a/src/loops.rs b/src/loops.rs index 2384c845303..061b8efaa64 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -286,7 +286,7 @@ impl LateLintPass for LoopsPass { if let Some(lhs_constructor) = path.segments.last() { if method_name.node.as_str() == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) && - lhs_constructor.identifier.name.as_str() == "Some" && + lhs_constructor.name.as_str() == "Some" && !is_iterator_used_after_while_let(cx, iter_expr) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); @@ -333,7 +333,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex if let PatKind::Ident(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, - var: ident.node.name, + var: ident.node, indexed: HashMap::new(), nonindex: false, }; @@ -378,9 +378,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex expr.span, &format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \ item) in {}.iter().enumerate(){}{}` or similar iterators", - ident.node.name, + ident.node, indexed, - ident.node.name, + ident.node, indexed, take, skip)); @@ -396,7 +396,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex expr.span, &format!("the loop variable `{}` is only used to index `{}`. \ Consider using `for item in {}` or similar iterators", - ident.node.name, + ident.node, indexed, repl)); } @@ -412,7 +412,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { method.node.as_str() == "len", let ExprPath(_, ref path) = len_args[0].node, path.segments.len() == 1, - &path.segments[0].identifier.name == var + &path.segments[0].name == var ], { return true; }} @@ -613,7 +613,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { PatKind::Wild => true, - PatKind::Ident(_, ident, None) if ident.node.name.as_str().starts_with('_') => { + PatKind::Ident(_, ident, None) if ident.node.as_str().starts_with('_') => { let mut visitor = UsedVisitor { var: ident.node, used: false, @@ -626,14 +626,14 @@ fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { } struct UsedVisitor { - var: Ident, // var to look for + var: ast::Name, // var to look for used: bool, // has the var been used otherwise? } impl<'a> Visitor<'a> for UsedVisitor { fn visit_expr(&mut self, expr: &Expr) { if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && path.segments[0].identifier == self.var { + if path.segments.len() == 1 && path.segments[0].name == self.var { self.used = true; return; } @@ -653,7 +653,7 @@ struct VarVisitor<'v, 't: 'v> { impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { fn visit_expr(&mut self, expr: &'v Expr) { if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && path.segments[0].identifier.name == self.var { + if path.segments.len() == 1 && path.segments[0].name == self.var { // we are referencing our variable! now check if it's as an index if_let_chain! { [ @@ -667,11 +667,11 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { match def.base_def { Def::Local(..) | Def::Upvar(..) => { let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); - self.indexed.insert(seqvar.segments[0].identifier.name, Some(extent)); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); return; // no need to walk further } Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].identifier.name, None); + self.indexed.insert(seqvar.segments[0].name, None); return; // no need to walk further } _ => (), @@ -885,7 +885,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { if let DeclLocal(ref local) = decl.node { if local.pat.id == self.var_id { if let PatKind::Ident(_, ref ident, _) = local.pat.node { - self.name = Some(ident.node.name); + self.name = Some(ident.node); self.state = if let Some(ref init) = local.init { if is_integer_literal(init, 0) { diff --git a/src/map_clone.rs b/src/map_clone.rs index d015a165457..4ad232759cf 100644 --- a/src/map_clone.rs +++ b/src/map_clone.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::hir::*; +use syntax::ast; use utils::{is_adjusted, match_path, match_trait_method, match_type, paths, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; @@ -52,7 +53,7 @@ impl LateLintPass for MapClonePass { if clone_call.node.as_str() == "clone" && clone_args.len() == 1 && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_ident(&clone_args[0], arg_ident) + expr_eq_name(&clone_args[0], arg_ident) { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ @@ -82,11 +83,11 @@ impl LateLintPass for MapClonePass { } } -fn expr_eq_ident(expr: &Expr, id: Ident) -> bool { +fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { match expr.node { ExprPath(None, ref path) => { let arg_segment = [PathSegment { - identifier: id, + name: id, parameters: PathParameters::none(), }]; !path.global && path.segments[..] == arg_segment @@ -105,18 +106,18 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s } } -fn get_arg_name(pat: &Pat) -> Option<Ident> { +fn get_arg_name(pat: &Pat) -> Option<ast::Name> { match pat.node { - PatKind::Ident(_, ident, None) => Some(ident.node), + PatKind::Ident(_, name, None) => Some(name.node), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } } -fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool { +fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { match expr.node { ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), - _ => expr_eq_ident(expr, id), + _ => expr_eq_name(expr, id), } } diff --git a/src/methods.rs b/src/methods.rs index ecbdb62f05e..14bc74d467f 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -473,7 +473,6 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi let path: &str = &path.segments .last() .expect("A path must have at least one segment") - .identifier .name .as_str(); @@ -811,7 +810,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: let hir::ExprCall(ref fun, ref arg_char) = other.node, arg_char.len() == 1, let hir::ExprPath(None, ref path) = fun.node, - path.segments.len() == 1 && path.segments[0].identifier.name.as_str() == "Some" + path.segments.len() == 1 && path.segments[0].name.as_str() == "Some" ], { let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0])); diff --git a/src/misc.rs b/src/misc.rs index 25747157c0f..3ab7823e50d 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -8,8 +8,10 @@ use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; use syntax::codemap::{Span, Spanned, ExpnFormat}; use syntax::ptr::P; -use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint}; -use utils::{span_lint_and_then, walk_ptrs_ty, is_integer_literal, implements_trait}; +use utils::{ + get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet, + span_lint, span_lint_and_then, walk_ptrs_ty +}; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. /// @@ -118,7 +120,7 @@ impl LateLintPass for CmpNan { fn check_nan(cx: &LateContext, path: &Path, span: Span) { path.segments.last().map(|seg| { - if seg.identifier.name.as_str() == "NAN" { + if seg.name.as_str() == "NAN" { span_lint(cx, CMP_NAN, span, @@ -350,8 +352,8 @@ impl LateLintPass for PatternPass { REDUNDANT_PATTERN, pat.span, &format!("the `{} @ _` pattern can be written as just `{}`", - ident.node.name, - ident.node.name)); + ident.node, + ident.node)); } } } @@ -363,7 +365,8 @@ impl LateLintPass for PatternPass { /// **Why is this bad?** A single leading underscore is usually used to indicate that a binding /// will not be used. Using such a binding breaks this expectation. /// -/// **Known problems:** None +/// **Known problems:** The lint does not work properly with desugaring and macro, it has been +/// allowed in the mean time. /// /// **Example**: /// ``` @@ -371,7 +374,7 @@ impl LateLintPass for PatternPass { /// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore. /// // We should rename `_x` to `x` /// ``` -declare_lint!(pub USED_UNDERSCORE_BINDING, Warn, +declare_lint!(pub USED_UNDERSCORE_BINDING, Allow, "using a binding which is prefixed with an underscore"); #[derive(Copy, Clone)] @@ -387,32 +390,42 @@ impl LateLintPass for UsedUnderscoreBinding { #[cfg_attr(rustfmt, rustfmt_skip)] fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if in_attributes_expansion(cx, expr) { - // Don't lint things expanded by #[derive(...)], etc + // Don't lint things expanded by #[derive(...)], etc return; } - let needs_lint = match expr.node { + let binding = match expr.node { ExprPath(_, ref path) => { - let ident = path.segments + let segment = path.segments .last() .expect("path should always have at least one segment") - .identifier; - ident.name.as_str().starts_with('_') && - !ident.name.as_str().starts_with("__") && - ident.name != ident.unhygienic_name && - is_used(cx, expr) // not in bang macro + .name; + if segment.as_str().starts_with('_') && + !segment.as_str().starts_with("__") && + segment != segment.unhygienize() && // not in bang macro + is_used(cx, expr) { + Some(segment.as_str()) + } else { + None + } } ExprField(_, spanned) => { let name = spanned.node.as_str(); - name.starts_with('_') && !name.starts_with("__") + if name.starts_with('_') && !name.starts_with("__") { + Some(name) + } else { + None + } } - _ => false, + _ => None, }; - if needs_lint { - span_lint(cx, - USED_UNDERSCORE_BINDING, - expr.span, - "used binding which is prefixed with an underscore. A leading underscore signals that a \ - binding will not be used."); + if let Some(binding) = binding { + if binding != "_result" { // FIXME: #944 + span_lint(cx, + USED_UNDERSCORE_BINDING, + expr.span, + &format!("used binding `{}` which is prefixed with an underscore. A leading \ + underscore signals that a binding will not be used.", binding)); + } } } } @@ -431,8 +444,8 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { } } -/// Test whether an expression is in a macro expansion (e.g. something generated by #[derive(...)] -/// or the like) +/// Test whether an expression is in a macro expansion (e.g. something generated by +/// `#[derive(...)`] or the like). fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| { info_opt.map_or(false, |info| { diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs index 6a8ca368fc1..34921bc2c04 100644 --- a/src/overflow_check_conditional.rs +++ b/src/overflow_check_conditional.rs @@ -31,7 +31,7 @@ impl LateLintPass for OverflowCheckConditional { let Expr_::ExprPath(_,ref path1) = ident1.node, let Expr_::ExprPath(_, ref path2) = ident2.node, let Expr_::ExprPath(_, ref path3) = second.node, - (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], cx.tcx.expr_ty(ident1).is_integral(), cx.tcx.expr_ty(ident2).is_integral() ], { @@ -53,7 +53,7 @@ impl LateLintPass for OverflowCheckConditional { let Expr_::ExprPath(_,ref path1) = ident1.node, let Expr_::ExprPath(_, ref path2) = ident2.node, let Expr_::ExprPath(_, ref path3) = first.node, - (&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], cx.tcx.expr_ty(ident1).is_integral(), cx.tcx.expr_ty(ident2).is_integral() ], { diff --git a/src/shadow.rs b/src/shadow.rs index 4639a943965..cf7de04cb6f 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -66,7 +66,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { if let PatKind::Ident(_, ident, _) = arg.pat.node { - bindings.push((ident.node.unhygienic_name, ident.span)) + bindings.push((ident.node.unhygienize(), ident.span)) } } check_block(cx, block, &mut bindings); @@ -120,7 +120,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind // TODO: match more stuff / destructuring match pat.node { PatKind::Ident(_, ref ident, ref inner) => { - let name = ident.node.unhygienic_name; + let name = ident.node.unhygienize(); if is_binding(cx, pat) { let mut new_binding = true; for tup in bindings.iter_mut() { @@ -326,7 +326,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - !path.global && path.segments.len() == 1 && path.segments[0].identifier.unhygienic_name == name + !path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name } struct ContainsSelf { @@ -335,8 +335,8 @@ struct ContainsSelf { } impl<'v> Visitor<'v> for ContainsSelf { - fn visit_ident(&mut self, _: Span, ident: Ident) { - if self.name == ident.unhygienic_name { + fn visit_name(&mut self, _: Span, name: Name) { + if self.name == name.unhygienize() { self.result = true; } } diff --git a/src/swap.rs b/src/swap.rs index 724915b9dd5..c5572181395 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -75,7 +75,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { let ExprPath(None, ref rhs2) = rhs2.node, rhs2.segments.len() == 1, - tmp_name.node.name.as_str() == rhs2.segments[0].identifier.name.as_str(), + tmp_name.node.as_str() == rhs2.segments[0].name.as_str(), SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) ], { diff --git a/src/unsafe_removed_from_name.rs b/src/unsafe_removed_from_name.rs index 404d6d93604..3de6719c546 100644 --- a/src/unsafe_removed_from_name.rs +++ b/src/unsafe_removed_from_name.rs @@ -41,7 +41,7 @@ impl LateLintPass for UnsafeNameRemoval { path.segments .last() .expect("use paths cannot be empty") - .identifier.name, + .name, *name, cx, &item.span ); diff --git a/src/unused_label.rs b/src/unused_label.rs index f6ff3c3d4b4..d408f16a371 100644 --- a/src/unused_label.rs +++ b/src/unused_label.rs @@ -65,10 +65,10 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor { fn visit_expr(&mut self, expr: &hir::Expr) { match expr.node { hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => { - self.labels.remove(&label.node.name.as_str()); + self.labels.remove(&label.node.as_str()); } hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { - self.labels.insert(label.name.as_str(), expr.span); + self.labels.insert(label.as_str(), expr.span); } _ => (), } diff --git a/src/utils/hir.rs b/src/utils/hir.rs index fe4c6d30952..0f0a7312ee4 100644 --- a/src/utils/hir.rs +++ b/src/utils/hir.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), - (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), + (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) @@ -80,7 +80,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) } - (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), + (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) @@ -95,7 +95,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { - self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) } (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && @@ -124,7 +124,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) } _ => false, } @@ -146,7 +146,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r))) } (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { - lb == rb && li.node.name.as_str() == ri.node.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) + lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { @@ -172,7 +172,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { left.global == right.global && over(&left.segments, &right.segments, - |l, r| l.identifier.name.as_str() == r.identifier.name.as_str() && l.parameters == r.parameters) + |l, r| l.name.as_str() == r.name.as_str() && l.parameters == r.parameters) } fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool { @@ -281,7 +281,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprAgain; c.hash(&mut self.s); if let Some(i) = i { - self.hash_name(&i.node.name); + self.hash_name(&i.node); } } ExprAssign(ref l, ref r) => { @@ -313,7 +313,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprBreak; c.hash(&mut self.s); if let Some(i) = i { - self.hash_name(&i.node.name); + self.hash_name(&i.node); } } ExprBox(ref e) => { @@ -374,7 +374,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { - self.hash_name(&i.name); + self.hash_name(&i); } } ExprMatch(ref e, ref arms, ref s) => { @@ -468,7 +468,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(cond); self.hash_block(b); if let Some(l) = l { - self.hash_name(&l.name); + self.hash_name(&l); } } } @@ -487,7 +487,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn hash_path(&mut self, p: &Path) { p.global.hash(&mut self.s); for p in &p.segments { - self.hash_name(&p.identifier.name); + self.hash_name(&p.name); } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 10bfe56e925..3ff6167620a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -200,7 +200,7 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// match_path(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name.as_str() == *b) } /// Match a `Path` against a slice of segment string literals, e.g. diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index 6bf4324e623..c571906c53b 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -3,15 +3,16 @@ #![deny(clippy)] #![allow(blacklisted_name)] +#![deny(used_underscore_binding)] /// Test that we lint if we use a binding with a single leading underscore fn prefix_underscore(_foo: u32) -> u32 { - _foo + 1 //~ ERROR used binding which is prefixed with an underscore + _foo + 1 //~ ERROR used binding `_foo` which is prefixed with an underscore } /// Test that we lint even if the use is within a macro expansion fn in_macro(_foo: u32) { - println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore + println!("{}", _foo); //~ ERROR used binding `_foo` which is prefixed with an underscore } // Struct for testing use of fields prefixed with an underscore @@ -22,7 +23,7 @@ struct StructFieldTest { /// Test that we lint the use of a struct field which is prefixed with an underscore fn in_struct_field() { let mut s = StructFieldTest { _underscore_field: 0 }; - s._underscore_field += 1; //~ Error used binding which is prefixed with an underscore + s._underscore_field += 1; //~ Error used binding `_underscore_field` which is prefixed with an underscore } /// Test that we do not lint if the underscore is not a prefix -- cgit 1.4.1-3-g733a5 From 6dd608e53e52d91d01677bc5f0a2eead4757e406 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 20 May 2016 19:18:32 +0200 Subject: Rustup to *1.10.0-nightly (764ef92ae 2016-05-19)* --- src/methods.rs | 2 +- src/vec.rs | 12 +++++++----- tests/compile-fail/methods.rs | 2 +- tests/compile-fail/mut_mut.rs | 11 ++++++----- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/methods.rs b/src/methods.rs index 14bc74d467f..f9f557e7a9a 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -511,7 +511,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi return; } } - // (path, fn_has_argument, methods) + // (path, fn_has_argument, methods, suffix) let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), (&paths::OPTION, diff --git a/src/vec.rs b/src/vec.rs index 63b9952c3c8..e62a8f9c459 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -38,17 +38,19 @@ impl LateLintPass for UselessVec { let TypeVariants::TySlice(..) = ty.ty.sty, let ExprAddrOf(_, ref addressee) = expr.node, ], { - check_vec_macro(cx, expr, addressee); + check_vec_macro(cx, addressee, expr.span); }} // search for `for _ in vec![…]` if let Some((_, arg, _)) = recover_for_loop(expr) { - check_vec_macro(cx, arg, arg); + // report the error around the `vec!` not inside `<std macros>:` + let span = cx.sess().codemap().source_callsite(arg.span); + check_vec_macro(cx, arg, span); } } } -fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) { +fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { if let Some(vec_args) = unexpand_vec(cx, vec) { let snippet = match vec_args { VecArgs::Repeat(elem, len) => { @@ -69,8 +71,8 @@ fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) { } }; - span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| { - db.span_suggestion(expr.span, "you can use a slice directly", snippet); + span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { + db.span_suggestion(span, "you can use a slice directly", snippet); }); } } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 88a1e7c4cf2..9753c021372 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -288,7 +288,7 @@ fn or_fun_call() { with_vec.unwrap_or(vec![]); //~^ERROR use of `unwrap_or` //~|HELP try this - //~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); + // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); let without_default = Some(Foo); without_default.unwrap_or(Foo::new()); diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 865574eaec0..8d9bceb0d0d 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -18,6 +18,7 @@ fn less_fun(x : *mut *mut u32) { macro_rules! mut_ptr { ($p:expr) => { &mut $p } + //~^ ERROR generally you want to avoid `&mut &mut } #[deny(mut_mut)] @@ -30,12 +31,12 @@ fn main() { if fun(x) { let y : &mut &mut &mut u32 = &mut &mut &mut 2; - //~^ ERROR generally you want to avoid `&mut &mut - //~^^ ERROR generally you want to avoid `&mut &mut - //~^^^ ERROR generally you want to avoid `&mut &mut - //~^^^^ ERROR generally you want to avoid `&mut &mut + //~^ ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut ***y + **x; } - let mut z = mut_ptr!(&mut 3u32); //~ERROR generally you want to avoid `&mut &mut + let mut z = mut_ptr!(&mut 3u32); //~ NOTE in this expansion of mut_ptr! } -- cgit 1.4.1-3-g733a5 From ac2e175c1b9aa6ac8da7794a86f7ec4b16f669ac Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 23 May 2016 16:34:09 +0200 Subject: Rustup to *1.10.0-nightly (476fe6eef 2016-05-21)* --- src/shadow.rs | 7 ++++--- tests/compile-fail/methods.rs | 6 ++---- tests/compile-fail/shadow.rs | 16 ++++++++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/shadow.rs b/src/shadow.rs index cf7de04cb6f..2a0d36a80b3 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -208,15 +208,16 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, let db = span_lint(cx, SHADOW_SAME, span, - &format!("{} is shadowed by itself in {}", + &format!("`{}` is shadowed by itself in `{}`", snippet(cx, pattern_span, "_"), snippet(cx, expr.span, ".."))); + note_orig(cx, db, SHADOW_SAME, prev_span); } else if contains_self(name, expr) { let db = span_note_and_lint(cx, SHADOW_REUSE, pattern_span, - &format!("{} is shadowed by {} which reuses the original value", + &format!("`{}` is shadowed by `{}` which reuses the original value", snippet(cx, pattern_span, "_"), snippet(cx, expr.span, "..")), expr.span, @@ -226,7 +227,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, let db = span_note_and_lint(cx, SHADOW_UNRELATED, pattern_span, - &format!("{} is shadowed by {}", + &format!("`{}` is shadowed by `{}`", snippet(cx, pattern_span, "_"), snippet(cx, expr.span, "..")), expr.span, diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 9753c021372..f6e4a9a31e0 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -493,10 +493,8 @@ fn single_char_pattern() { fn temporary_cstring() { use std::ffi::CString; - ( // extra parenthesis to better test spans + CString::new("foo").unwrap().as_ptr(); //~^ ERROR you are getting the inner pointer of a temporary `CString` //~| NOTE that pointer will be invalid outside this expression - CString::new("foo").unwrap() - //~^ HELP assign the `CString` to a variable to extend its lifetime - ).as_ptr(); + //~| HELP assign the `CString` to a variable to extend its lifetime } diff --git a/tests/compile-fail/shadow.rs b/tests/compile-fail/shadow.rs index 0a52a9829ae..1cfcff74a44 100644 --- a/tests/compile-fail/shadow.rs +++ b/tests/compile-fail/shadow.rs @@ -10,15 +10,15 @@ fn first(x: (isize, isize)) -> isize { x.0 } fn main() { let mut x = 1; - let x = &mut x; //~ERROR x is shadowed by itself in &mut x - let x = { x }; //~ERROR x is shadowed by itself in { x } - let x = (&*x); //~ERROR x is shadowed by itself in &*x - let x = { *x + 1 }; //~ERROR x is shadowed by { *x + 1 } which reuses - let x = id(x); //~ERROR x is shadowed by id(x) which reuses - let x = (1, x); //~ERROR x is shadowed by (1, x) which reuses - let x = first(x); //~ERROR x is shadowed by first(x) which reuses + let x = &mut x; //~ERROR `x` is shadowed by itself in `&mut x` + let x = { x }; //~ERROR `x` is shadowed by itself in `{ x }` + let x = (&*x); //~ERROR `x` is shadowed by itself in `(&*x)` + let x = { *x + 1 }; //~ERROR `x` is shadowed by `{ *x + 1 }` which reuses + let x = id(x); //~ERROR `x` is shadowed by `id(x)` which reuses + let x = (1, x); //~ERROR `x` is shadowed by `(1, x)` which reuses + let x = first(x); //~ERROR `x` is shadowed by `first(x)` which reuses let y = 1; - let x = y; //~ERROR x is shadowed by y + let x = y; //~ERROR `x` is shadowed by `y` let o = Some(1u8); -- cgit 1.4.1-3-g733a5 From f2eea6211c4834e8f472352bd3596a73115903b5 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 19 May 2016 23:15:12 +0200 Subject: Bump to 0.0.69 --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 017e24b1034..59b03b301c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.69 — 2016-05-20 +* Rustup to *rustc 1.10.0-nightly (476fe6eef 2016-05-21)* +* `used_underscore_binding` has been made `Allow` temporarily + ## 0.0.68 — 2016-05-17 * Rustup to *rustc 1.10.0-nightly (cd6a40017 2016-05-16)* * New lint: [`unnecessary_operation`] diff --git a/Cargo.toml b/Cargo.toml index 49053ea1e4f..fd0b07428c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.68" +version = "0.0.69" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From 7a9dac4e1cd0a44d69f203ed4c2e09cf6f464977 Mon Sep 17 00:00:00 2001 From: Benoît Zugmeyer <bzugmeyer@gmail.com> Date: Mon, 23 May 2016 22:32:51 +0200 Subject: Let cargo-clippy exit with a code > 0 if some error occured --- src/lib.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 888abbc92c5..bcf8f86b10a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,18 +122,28 @@ pub fn main() { if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); let path = std::env::current_exe().expect("current executable path invalid"); - std::process::Command::new("cargo") + let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC", path) .spawn().expect("could not run cargo") .wait().expect("failed to wait for cargo?"); + + if let Some(code) = exit_status.code() { + std::process::exit(code); + } } else { let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { env::args().collect() } else { env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() }; - rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); + let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); + + if let Err(err_count) = result { + if err_count > 0 { + std::process::exit(1); + } + } } } -- cgit 1.4.1-3-g733a5 From 9cfc42275d400d5b192e10e005d4f7ef772156b7 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 17 May 2016 08:33:57 +0200 Subject: Split `new_without_default` and `new_without_default_derive`. This is still very slow, because we do a trait lookup for each field. Perhaps storing the visited types in a set to reuse types would improve performance somewhat. Also we may want to pre-decide some known types (e.g. `Vec<T>`, `Option<T>`). --- CHANGELOG.md | 1 + README.md | 3 +- src/lib.rs | 1 + src/new_without_default.rs | 84 +++++++++++++++++++++++++++---- tests/compile-fail/methods.rs | 2 +- tests/compile-fail/new_without_default.rs | 6 +-- 6 files changed, 82 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59b03b301c6..9a1e7322e76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -174,6 +174,7 @@ All notable changes to this project will be documented in this file. [`neg_multiply`]: https://github.com/Manishearth/rust-clippy/wiki#neg_multiply [`new_ret_no_self`]: https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self [`new_without_default`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default +[`new_without_default_derive`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive [`no_effect`]: https://github.com/Manishearth/rust-clippy/wiki#no_effect [`non_ascii_literal`]: https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal [`nonminimal_bool`]: https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool diff --git a/README.md b/README.md index 6843afb4ede..4c156dfb7a0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 150 lints included in this crate: +There are 151 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -107,6 +107,7 @@ name [neg_multiply](https://github.com/Manishearth/rust-clippy/wiki#neg_multiply) | warn | Warns on multiplying integers with -1 [new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method [new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation +[new_without_default_derive](https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive) | warn | `fn new() -> Self` without `#[derive]`able `Default` implementation [no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | allow | checks for boolean expressions that can be written more concisely diff --git a/src/lib.rs b/src/lib.rs index bcf8f86b10a..41c26cf7109 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -527,6 +527,7 @@ pub fn plugin_registrar(reg: &mut Registry) { needless_update::NEEDLESS_UPDATE, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, + new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, no_effect::NO_EFFECT, no_effect::UNNECESSARY_OPERATION, non_expressive_names::MANY_SINGLE_CHAR_NAMES, diff --git a/src/new_without_default.rs b/src/new_without_default.rs index 46021ec8836..08d517014ee 100644 --- a/src/new_without_default.rs +++ b/src/new_without_default.rs @@ -1,6 +1,8 @@ use rustc::hir::intravisit::FnKind; +use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::*; +use rustc::ty; use syntax::ast; use syntax::codemap::Span; use utils::paths; @@ -20,11 +22,11 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, sa /// **Example:** /// /// ```rust,ignore -/// struct Foo; +/// struct Foo(Bar); /// /// impl Foo { /// fn new() -> Self { -/// Foo +/// Foo(Bar::new()) /// } /// } /// ``` @@ -32,29 +34,58 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, sa /// Instead, use: /// /// ```rust -/// struct Foo; +/// struct Foo(Bar); /// /// impl Default for Foo { /// fn default() -> Self { -/// Foo +/// Foo(Bar::new()) /// } /// } /// ``` /// /// You can also have `new()` call `Default::default()` -/// declare_lint! { pub NEW_WITHOUT_DEFAULT, Warn, "`fn new() -> Self` method without `Default` implementation" } +/// **What it does:** This lints about type with a `fn new() -> Self` method +/// and no implementation of +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// +/// **Why is this bad?** User might expect to be able to use +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// as the type can be +/// constructed without arguments. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ```rust,ignore +/// struct Foo; +/// +/// impl Foo { +/// fn new() -> Self { +/// Foo +/// } +/// } +/// ``` +/// +/// Just prepend `#[derive(Default)]` before the `struct` definition +declare_lint! { + pub NEW_WITHOUT_DEFAULT_DERIVE, + Warn, + "`fn new() -> Self` without `#[derive]`able `Default` implementation" +} + #[derive(Copy,Clone)] pub struct NewWithoutDefault; impl LintPass for NewWithoutDefault { fn get_lints(&self) -> LintArray { - lint_array!(NEW_WITHOUT_DEFAULT) + lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE) } } @@ -66,8 +97,8 @@ impl LateLintPass for NewWithoutDefault { if let FnKind::Method(name, _, _, _) = kind { if decl.inputs.is_empty() && name.as_str() == "new" { - let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty; - + let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( + cx.tcx.map.get_parent(id))).ty; if_let_chain!{[ self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics let Some(ret_ty) = return_ty(cx, id), @@ -75,10 +106,43 @@ impl LateLintPass for NewWithoutDefault { let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), !implements_trait(cx, self_ty, default_trait_id, Vec::new()) ], { - span_lint(cx, NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a `Default` implementation for `{}`", self_ty)); + if can_derive_default(self_ty, cx, default_trait_id) { + span_lint(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty)). + span_suggestion(span, + "try this", + "#[derive(Default)]".into()); + } else { + span_lint(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty)). + span_suggestion(span, + "try this", + format!("impl Default for {} {{ fn default() -> \ + Self {{ {}::new() }} }}", self_ty, self_ty)); + } }} } } } } + +fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> bool { + match ty.sty { + ty::TyStruct(ref adt_def, ref substs) => { + for field in adt_def.all_fields() { + let f_ty = field.ty(cx.tcx, substs); + if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) { + return false + } + } + true + }, + _ => false + } +} diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index f6e4a9a31e0..78ffbb1a58a 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -3,7 +3,7 @@ #![plugin(clippy)] #![deny(clippy, clippy_pedantic)] -#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default)] +#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index 30015f6c9e8..17f2a8d7b41 100644 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -2,18 +2,18 @@ #![plugin(clippy)] #![allow(dead_code)] -#![deny(new_without_default)] +#![deny(new_without_default, new_without_default_derive)] struct Foo; impl Foo { - fn new() -> Foo { Foo } //~ERROR: you should consider adding a `Default` implementation for `Foo` + fn new() -> Foo { Foo } //~ERROR: you should consider deriving a `Default` implementation for `Foo` } struct Bar; impl Bar { - fn new() -> Self { Bar } //~ERROR: you should consider adding a `Default` implementation for `Bar` + fn new() -> Self { Bar } //~ERROR: you should consider deriving a `Default` implementation for `Bar` } struct Ok; -- cgit 1.4.1-3-g733a5 From e90a0be923906ded7c79d6168a11b8b68d85fd72 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 17 May 2016 16:34:15 +0200 Subject: simplify `mut_mut` lint --- src/mut_mut.rs | 64 +++++++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 7b7b5ecdf4e..4147e288c4f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -28,50 +28,32 @@ impl LintPass for MutMut { impl LateLintPass for MutMut { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - check_expr_mut(cx, expr) - } - - fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| { - span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); - }); - } -} - -fn check_expr_mut(cx: &LateContext, expr: &Expr) { - fn unwrap_addr(expr: &Expr) -> Option<&Expr> { - match expr.node { - ExprAddrOf(MutMutable, ref e) => Some(e), - _ => None, + if in_external_macro(cx, expr.span) { + return; } - } - if in_external_macro(cx, expr.span) { - return; + if let ExprAddrOf(MutMutable, ref e) = expr.node { + if let ExprAddrOf(MutMutable, _) = e.node { + span_lint(cx, + MUT_MUT, + expr.span, + "generally you want to avoid `&mut &mut _` if possible"); + } else { + if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { + span_lint(cx, + MUT_MUT, + expr.span, + "this expression mutably borrows a mutable reference. Consider reborrowing"); + } + } + } } - unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map_or_else(|| { - if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { - span_lint(cx, - MUT_MUT, - expr.span, - "this expression mutably borrows a mutable reference. Consider \ - reborrowing"); - } - }, - |_| { - span_lint(cx, - MUT_MUT, - expr.span, - "generally you want to avoid `&mut &mut _` if possible"); - }) - }) -} - -fn unwrap_mut(ty: &Ty) -> Option<&Ty> { - match ty.node { - TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) => Some(pty), - _ => None, + fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { + if let TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) = ty.node { + if let TyRptr(_, MutTy { mutbl: MutMutable, .. }) = pty.node { + span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); + } + } } } -- cgit 1.4.1-3-g733a5 From bb69e60b3088f5db72e359c19271b8561e882a39 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 25 May 2016 18:51:35 +0200 Subject: fix no_effect lint --- src/no_effect.rs | 10 +++++----- tests/compile-fail/no_effect.rs | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/no_effect.rs b/src/no_effect.rs index 593a6c4ad59..ae3bac00455 100644 --- a/src/no_effect.rs +++ b/src/no_effect.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::{Def, PathResolution}; -use rustc::hir::{Expr, Expr_, Stmt, StmtSemi}; +use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource}; use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then}; use std::ops::Deref; @@ -140,11 +140,11 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp } Expr_::ExprBlock(ref block) => { if block.stmts.is_empty() { - block.expr.as_ref().and_then(|e| if e.span == expr.span { + block.expr.as_ref().and_then(|e| match block.rules { + BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, + BlockCheckMode::DefaultBlock => Some(vec![&**e]), // in case of compiler-inserted signaling blocks - reduce_expression(cx, e) - } else { - Some(vec![e]) + _ => reduce_expression(cx, e), }) } else { None diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index ce6daa8d562..c1d9b175428 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -18,6 +18,8 @@ enum Enum { fn get_number() -> i32 { 0 } fn get_struct() -> Struct { Struct { field: 0 } } +unsafe fn unsafe_fn() -> i32 { 0 } + fn main() { let s = get_struct(); let s2 = get_struct(); @@ -50,6 +52,7 @@ fn main() { // Do not warn get_number(); + unsafe { unsafe_fn() }; Tuple(get_number()); //~ERROR statement can be reduced //~^HELP replace it with @@ -105,4 +108,7 @@ fn main() { [42; 55][get_number() as usize]; //~ERROR statement can be reduced //~^HELP replace it with //~|SUGGESTION [42; 55];get_number() as usize; + {get_number()}; //~ERROR statement can be reduced + //~^HELP replace it with + //~|SUGGESTION get_number(); } -- cgit 1.4.1-3-g733a5 From 4f11f84dee891e80680f47d48cc33a0cb0229080 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 25 May 2016 17:15:19 +0200 Subject: Lint binary regexes --- CHANGELOG.md | 6 ++- src/regex.rs | 108 +++++++++++++++++++++++++++----------------- src/utils/paths.rs | 6 ++- tests/compile-fail/regex.rs | 33 +++++++++++++- 4 files changed, 109 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a1e7322e76..f17b1dd0837 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.70 — TBD +* [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new` and + byte regexes + ## 0.0.69 — 2016-05-20 * Rustup to *rustc 1.10.0-nightly (476fe6eef 2016-05-21)* -* `used_underscore_binding` has been made `Allow` temporarily +* [`used_underscore_binding`] has been made `Allow` temporarily ## 0.0.68 — 2016-05-17 * Rustup to *rustc 1.10.0-nightly (cd6a40017 2016-05-16)* diff --git a/src/regex.rs b/src/regex.rs index e1b4237b9b2..8876a649e5d 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -9,7 +9,7 @@ use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; -use utils::{is_expn_of, match_path, match_type, paths, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; /// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. /// @@ -81,7 +81,7 @@ impl LateLintPass for RegexPass { span, "`regex!(_)` found. \ Please use `Regex::new(_)`, which is faster for now."); - self.spans.insert(span); + self.spans.insert(span); } self.last = Some(block.id); }} @@ -96,46 +96,18 @@ impl LateLintPass for RegexPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, - let ExprPath(_, ref path) = fun.node, - match_path(path, &paths::REGEX_NEW) && args.len() == 1 + args.len() == 1, + let Some(def) = cx.tcx.def_map.borrow().get(&fun.id), ], { - if let ExprLit(ref lit) = args[0].node { - if let LitKind::Str(ref r, _) = lit.node { - match regex_syntax::Expr::parse(r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - "trivial regex", - &format!("consider using {}", repl)); - } - } - Err(e) => { - span_lint(cx, - INVALID_REGEX, - str_span(args[0].span, &r, e.position()), - &format!("regex syntax error: {}", - e.description())); - } - } - } - } else if let Some(r) = const_str(cx, &*args[0]) { - match regex_syntax::Expr::parse(&r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, args[0].span, - "trivial regex", - &format!("consider using {}", repl)); - } - } - Err(e) => { - span_lint(cx, - INVALID_REGEX, - args[0].span, - &format!("regex syntax error on position {}: {}", - e.position(), - e.description())); - } - } + let def_id = def.def_id(); + if match_def_path(cx, def_id, &paths::REGEX_NEW) { + check_regex(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) { + check_regex(cx, &args[0], false); + } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { + check_set(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { + check_set(cx, &args[0], false); } }} } @@ -193,3 +165,57 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { _ => None, } } + +fn check_set(cx: &LateContext, expr: &Expr, utf8: bool) { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, + let ExprVec(ref exprs) = expr.node, + ], { + for expr in exprs { + check_regex(cx, expr, utf8); + } + }} +} + +fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { + let builder = regex_syntax::ExprBuilder::new().unicode(utf8); + + if let ExprLit(ref lit) = expr.node { + if let LitKind::Str(ref r, _) = lit.node { + match builder.parse(r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + "trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { + span_lint(cx, + INVALID_REGEX, + str_span(expr.span, r, e.position()), + &format!("regex syntax error: {}", + e.description())); + } + } + } + } else if let Some(r) = const_str(cx, expr) { + match builder.parse(&r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + "trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { + span_lint(cx, + INVALID_REGEX, + expr.span, + &format!("regex syntax error on position {}: {}", + e.position(), + e.description())); + } + } + } +} diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 3db1e1c5572..b0ce8b4a233 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -46,7 +46,11 @@ pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclus pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; -pub const REGEX_NEW: [&'static str; 3] = ["regex", "Regex", "new"]; +pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; +pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "new"]; +pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; +pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; +pub const REGEX_SET_NEW: [&'static str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index 9cd2bc8098e..d9f262fb045 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -6,7 +6,8 @@ extern crate regex; -use regex::Regex; +use regex::{Regex, RegexSet}; +use regex::bytes::{Regex as BRegex, RegexSet as BRegexSet}; const OPENING_PAREN : &'static str = "("; const NOT_A_REAL_REGEX : &'static str = "foobar"; @@ -22,8 +23,33 @@ fn syntax_error() { let some_regex = Regex::new(OPENING_PAREN); //~^ERROR: regex syntax error on position 0: unclosed + let binary_pipe_in_wrong_position = BRegex::new("|"); + //~^ERROR: regex syntax error: empty alternate + let some_binary_regex = BRegex::new(OPENING_PAREN); + //~^ERROR: regex syntax error on position 0: unclosed + let closing_paren = ")"; let not_linted = Regex::new(closing_paren); + + let set = RegexSet::new(&[ + r"[a-z]+@[a-z]+\.(com|org|net)", + r"[a-z]+\.(com|org|net)", + ]); + let bset = BRegexSet::new(&[ + r"[a-z]+@[a-z]+\.(com|org|net)", + r"[a-z]+\.(com|org|net)", + ]); + + let set_error = RegexSet::new(&[ + OPENING_PAREN, + //~^ERROR: regex syntax error on position 0: unclosed + r"[a-z]+\.(com|org|net)", + ]); + let bset_error = BRegexSet::new(&[ + OPENING_PAREN, + //~^ERROR: regex syntax error on position 0: unclosed + r"[a-z]+\.(com|org|net)", + ]); } fn trivial_regex() { @@ -64,12 +90,17 @@ fn trivial_regex() { //~^ERROR: trivial regex //~|HELP consider using `str::is_empty` + let binary_trivial_empty = BRegex::new("^$"); + //~^ERROR: trivial regex + //~|HELP consider using `str::is_empty` + // non-trivial regexes let non_trivial_dot = Regex::new("a.b"); let non_trivial_eq = Regex::new("^foo|bar$"); let non_trivial_starts_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("foo|bar"); + let non_trivial_binary = BRegex::new("foo|bar"); } fn main() { -- cgit 1.4.1-3-g733a5 From 51d166f17aa2dd73226152ff7ca6c69f2db5947c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 25 May 2016 21:36:51 +0200 Subject: Support `RegexBuilder` --- CHANGELOG.md | 4 ++-- src/regex.rs | 4 ++++ src/utils/paths.rs | 2 ++ tests/compile-fail/regex.rs | 14 ++++++++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f17b1dd0837..928fac7412e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ All notable changes to this project will be documented in this file. ## 0.0.70 — TBD -* [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new` and - byte regexes +* [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new`, + `RegexBuilder::new` and byte regexes ## 0.0.69 — 2016-05-20 * Rustup to *rustc 1.10.0-nightly (476fe6eef 2016-05-21)* diff --git a/src/regex.rs b/src/regex.rs index 8876a649e5d..b335bf993b5 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -104,6 +104,10 @@ impl LateLintPass for RegexPass { check_regex(cx, &args[0], true); } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) { check_regex(cx, &args[0], false); + } else if match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { + check_regex(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { + check_regex(cx, &args[0], false); } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { check_set(cx, &args[0], true); } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { diff --git a/src/utils/paths.rs b/src/utils/paths.rs index b0ce8b4a233..3c91578abd0 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -46,7 +46,9 @@ pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclus pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; +pub const REGEX_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; +pub const REGEX_BYTES_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "new"]; pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; diff --git a/tests/compile-fail/regex.rs b/tests/compile-fail/regex.rs index d9f262fb045..d6287b881a1 100644 --- a/tests/compile-fail/regex.rs +++ b/tests/compile-fail/regex.rs @@ -6,8 +6,8 @@ extern crate regex; -use regex::{Regex, RegexSet}; -use regex::bytes::{Regex as BRegex, RegexSet as BRegexSet}; +use regex::{Regex, RegexSet, RegexBuilder}; +use regex::bytes::{Regex as BRegex, RegexSet as BRegexSet, RegexBuilder as BRegexBuilder}; const OPENING_PAREN : &'static str = "("; const NOT_A_REAL_REGEX : &'static str = "foobar"; @@ -15,6 +15,8 @@ const NOT_A_REAL_REGEX : &'static str = "foobar"; fn syntax_error() { let pipe_in_wrong_position = Regex::new("|"); //~^ERROR: regex syntax error: empty alternate + let pipe_in_wrong_position_builder = RegexBuilder::new("|"); + //~^ERROR: regex syntax error: empty alternate let wrong_char_ranice = Regex::new("[z-a]"); //~^ERROR: regex syntax error: invalid character class range let some_unicode = Regex::new("[é-è]"); @@ -27,6 +29,8 @@ fn syntax_error() { //~^ERROR: regex syntax error: empty alternate let some_binary_regex = BRegex::new(OPENING_PAREN); //~^ERROR: regex syntax error on position 0: unclosed + let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); + //~^ERROR: regex syntax error on position 0: unclosed let closing_paren = ")"; let not_linted = Regex::new(closing_paren); @@ -57,6 +61,10 @@ fn trivial_regex() { //~^ERROR: trivial regex //~|HELP consider using `==` on `str`s + let trivial_eq_builder = RegexBuilder::new("^foobar$"); + //~^ERROR: trivial regex + //~|HELP consider using `==` on `str`s + let trivial_starts_with = Regex::new("^foobar"); //~^ERROR: trivial regex //~|HELP consider using `str::starts_with` @@ -96,11 +104,13 @@ fn trivial_regex() { // non-trivial regexes let non_trivial_dot = Regex::new("a.b"); + let non_trivial_dot_builder = RegexBuilder::new("a.b"); let non_trivial_eq = Regex::new("^foo|bar$"); let non_trivial_starts_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("foo|bar"); let non_trivial_binary = BRegex::new("foo|bar"); + let non_trivial_binary_builder = BRegexBuilder::new("foo|bar"); } fn main() { -- cgit 1.4.1-3-g733a5 From 8ac545d0fe224791875ed939db787cb311fac406 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 26 May 2016 00:08:31 +0200 Subject: Fix documentation --- CHANGELOG.md | 2 +- README.md | 4 ++-- src/regex.rs | 12 ++++++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 928fac7412e..719e6ee287e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,7 +72,7 @@ All notable changes to this project will be documented in this file. ## ~~0.0.52~~ ## 0.0.51 — 2016-03-13 -* Add `str` to types considered by `len_zero` +* Add `str` to types considered by [`len_zero`] * New lints: [`indexing_slicing`] ## 0.0.50 — 2016-03-11 diff --git a/README.md b/README.md index 4c156dfb7a0..c289116809e 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ name [ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` [inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | `#[inline(always)]` is a bad idea in most cases [integer_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic) | allow | Any integer arithmetic statement -[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions in `Regex::new(_)` invocations +[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | finds invalid regular expressions [invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended @@ -150,7 +150,7 @@ name [too_many_arguments](https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments [toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take references with `&`. [transmute_ptr_to_ref](https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type -[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions in `Regex::new(_)` invocations +[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | finds trivial regular expressions [type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types; recommends factoring out parts into `type` definitions [unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) [unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values (which is always `true` or `false`, respectively) diff --git a/src/regex.rs b/src/regex.rs index b335bf993b5..c97a64ebf09 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -11,7 +11,8 @@ use syntax::codemap::{Span, BytePos}; use syntax::parse::token::InternedString; use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; -/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. +/// **What it does:** This lint checks [regex] creation (with `Regex::new`, `RegexBuilder::new` or +/// `RegexSet::new`) for correct regex syntax. /// /// **Why is this bad?** This will lead to a runtime panic. /// @@ -21,10 +22,11 @@ use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_ declare_lint! { pub INVALID_REGEX, Deny, - "finds invalid regular expressions in `Regex::new(_)` invocations" + "finds invalid regular expressions" } -/// **What it does:** This lint checks for `Regex::new(_)` invocations with trivial regex. +/// **What it does:** This lint checks for trivial [regex] creation (with `Regex::new`, +/// `RegexBuilder::new` or `RegexSet::new`). /// /// **Why is this bad?** This can likely be replaced by `==` or `str::starts_with`, /// `str::ends_with` or `std::contains` or other `str` methods. @@ -32,10 +34,12 @@ declare_lint! { /// **Known problems:** None. /// /// **Example:** `Regex::new("^foobar")` +/// +/// [regex]: https://crates.io/crates/regex declare_lint! { pub TRIVIAL_REGEX, Warn, - "finds trivial regular expressions in `Regex::new(_)` invocations" + "finds trivial regular expressions" } /// **What it does:** This lint checks for usage of `regex!(_)` which as of now is usually slower than `Regex::new(_)` unless called in a loop (which is a bad idea anyway). -- cgit 1.4.1-3-g733a5 From 5eca09793e9e6969ce960601d83300e1d6065d97 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 27 May 2016 12:12:38 +0200 Subject: needless_borrow reported on &&T when only &T implements Trait and &Trait is required --- src/needless_borrow.rs | 17 +++++++++-------- tests/compile-fail/needless_borrow.rs | 7 +++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/needless_borrow.rs b/src/needless_borrow.rs index 294a12dad99..033811841ce 100644 --- a/src/needless_borrow.rs +++ b/src/needless_borrow.rs @@ -3,9 +3,10 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::*; +use rustc::hir::{ExprAddrOf, Expr, MutImmutable}; use rustc::ty::TyRef; use utils::{span_lint, in_macro}; +use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef; /// **What it does:** This lint checks for address of operations (`&`) that are going to be dereferenced immediately by the compiler /// @@ -36,13 +37,13 @@ impl LateLintPass for NeedlessBorrow { } if let ExprAddrOf(MutImmutable, ref inner) = e.node { if let TyRef(..) = cx.tcx.expr_ty(inner).sty { - let ty = cx.tcx.expr_ty(e); - let adj_ty = cx.tcx.expr_ty_adjusted(e); - if ty != adj_ty { - span_lint(cx, - NEEDLESS_BORROW, - e.span, - "this expression borrows a reference that is immediately dereferenced by the compiler"); + if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) { + if deref.autoderefs > 1 && deref.autoref.is_some() { + span_lint(cx, + NEEDLESS_BORROW, + e.span, + "this expression borrows a reference that is immediately dereferenced by the compiler"); + } } } } diff --git a/tests/compile-fail/needless_borrow.rs b/tests/compile-fail/needless_borrow.rs index 242691aa268..602e1e0859b 100644 --- a/tests/compile-fail/needless_borrow.rs +++ b/tests/compile-fail/needless_borrow.rs @@ -16,6 +16,7 @@ fn main() { let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]` let vec = Vec::new(); let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]` + h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait` } fn f<T:Copy>(y: &T) -> T { @@ -25,3 +26,9 @@ fn f<T:Copy>(y: &T) -> T { fn g(y: &[u8]) -> u8 { y[0] } + +trait Trait {} + +impl<'a> Trait for &'a str {} + +fn h(_: &Trait) {} -- cgit 1.4.1-3-g733a5 From bf227f4729ecc63147bacaf05d161f3819d13d7e Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 24 May 2016 18:25:25 +0200 Subject: split clippy into lints, plugin and cargo-clippy --- .gitignore | 1 + Cargo.toml | 2 +- clippy_lints/Cargo.toml | 24 + clippy_lints/src/approx_const.rs | 95 +++ clippy_lints/src/arithmetic.rs | 102 +++ clippy_lints/src/array_indexing.rs | 135 +++ clippy_lints/src/assign_ops.rs | 158 ++++ clippy_lints/src/attrs.rs | 176 ++++ clippy_lints/src/bit_mask.rs | 276 +++++++ clippy_lints/src/blacklisted_name.rs | 46 ++ clippy_lints/src/block_in_if_condition.rs | 118 +++ clippy_lints/src/booleans.rs | 389 +++++++++ clippy_lints/src/collapsible_if.rs | 129 +++ clippy_lints/src/consts.rs | 379 +++++++++ clippy_lints/src/copies.rs | 271 ++++++ clippy_lints/src/cyclomatic_complexity.rs | 187 +++++ clippy_lints/src/deprecated_lints.rs | 44 + clippy_lints/src/derive.rs | 180 ++++ clippy_lints/src/doc.rs | 235 ++++++ clippy_lints/src/drop_ref.rs | 61 ++ clippy_lints/src/entry.rs | 148 ++++ clippy_lints/src/enum_clike.rs | 52 ++ clippy_lints/src/enum_glob_use.rs | 65 ++ clippy_lints/src/enum_variants.rs | 104 +++ clippy_lints/src/eq_op.rs | 60 ++ clippy_lints/src/escape.rs | 172 ++++ clippy_lints/src/eta_reduction.rs | 99 +++ clippy_lints/src/format.rs | 119 +++ clippy_lints/src/formatting.rs | 166 ++++ clippy_lints/src/functions.rs | 76 ++ clippy_lints/src/identity_op.rs | 72 ++ clippy_lints/src/if_not_else.rs | 52 ++ clippy_lints/src/items_after_statements.rs | 70 ++ clippy_lints/src/len_zero.rs | 202 +++++ clippy_lints/src/lib.rs | 416 ++++++++++ clippy_lints/src/lifetimes.rs | 347 ++++++++ clippy_lints/src/loops.rs | 976 ++++++++++++++++++++++ clippy_lints/src/map_clone.rs | 128 +++ clippy_lints/src/matches.rs | 483 +++++++++++ clippy_lints/src/mem_forget.rs | 44 + clippy_lints/src/methods.rs | 1049 ++++++++++++++++++++++++ clippy_lints/src/minmax.rs | 93 +++ clippy_lints/src/misc.rs | 458 +++++++++++ clippy_lints/src/misc_early.rs | 166 ++++ clippy_lints/src/mut_mut.rs | 59 ++ clippy_lints/src/mut_reference.rs | 77 ++ clippy_lints/src/mutex_atomic.rs | 75 ++ clippy_lints/src/needless_bool.rs | 192 +++++ clippy_lints/src/needless_borrow.rs | 51 ++ clippy_lints/src/needless_update.rs | 42 + clippy_lints/src/neg_multiply.rs | 57 ++ clippy_lints/src/new_without_default.rs | 148 ++++ clippy_lints/src/no_effect.rs | 155 ++++ clippy_lints/src/non_expressive_names.rs | 291 +++++++ clippy_lints/src/open_options.rs | 185 +++++ clippy_lints/src/overflow_check_conditional.rs | 72 ++ clippy_lints/src/panic.rs | 47 ++ clippy_lints/src/precedence.rs | 118 +++ clippy_lints/src/print.rs | 88 ++ clippy_lints/src/ptr_arg.rs | 78 ++ clippy_lints/src/ranges.rs | 89 ++ clippy_lints/src/regex.rs | 229 ++++++ clippy_lints/src/returns.rs | 137 ++++ clippy_lints/src/shadow.rs | 353 ++++++++ clippy_lints/src/strings.rs | 160 ++++ clippy_lints/src/swap.rs | 138 ++++ clippy_lints/src/temporary_assignment.rs | 49 ++ clippy_lints/src/transmute.rs | 131 +++ clippy_lints/src/types.rs | 974 ++++++++++++++++++++++ clippy_lints/src/unicode.rs | 109 +++ clippy_lints/src/unsafe_removed_from_name.rs | 81 ++ clippy_lints/src/unused_label.rs | 78 ++ clippy_lints/src/utils/comparisons.rs | 23 + clippy_lints/src/utils/conf.rs | 205 +++++ clippy_lints/src/utils/hir.rs | 513 ++++++++++++ clippy_lints/src/utils/mod.rs | 840 +++++++++++++++++++ clippy_lints/src/utils/paths.rs | 61 ++ clippy_lints/src/vec.rs | 116 +++ clippy_lints/src/zero_div_zero.rs | 59 ++ src/approx_const.rs | 95 --- src/arithmetic.rs | 102 --- src/array_indexing.rs | 135 --- src/assign_ops.rs | 158 ---- src/attrs.rs | 176 ---- src/bit_mask.rs | 276 ------- src/blacklisted_name.rs | 46 -- src/block_in_if_condition.rs | 118 --- src/booleans.rs | 389 --------- src/collapsible_if.rs | 129 --- src/consts.rs | 379 --------- src/copies.rs | 271 ------ src/cyclomatic_complexity.rs | 187 ----- src/deprecated_lints.rs | 44 - src/derive.rs | 180 ---- src/doc.rs | 235 ------ src/drop_ref.rs | 61 -- src/entry.rs | 148 ---- src/enum_clike.rs | 52 -- src/enum_glob_use.rs | 65 -- src/enum_variants.rs | 104 --- src/eq_op.rs | 60 -- src/escape.rs | 172 ---- src/eta_reduction.rs | 99 --- src/format.rs | 119 --- src/formatting.rs | 166 ---- src/functions.rs | 76 -- src/identity_op.rs | 72 -- src/if_not_else.rs | 52 -- src/items_after_statements.rs | 70 -- src/len_zero.rs | 202 ----- src/lib.rs | 527 +----------- src/lifetimes.rs | 347 -------- src/loops.rs | 976 ---------------------- src/main.rs | 167 ++++ src/map_clone.rs | 128 --- src/matches.rs | 483 ----------- src/mem_forget.rs | 44 - src/methods.rs | 1049 ------------------------ src/minmax.rs | 93 --- src/misc.rs | 458 ----------- src/misc_early.rs | 166 ---- src/mut_mut.rs | 59 -- src/mut_reference.rs | 77 -- src/mutex_atomic.rs | 75 -- src/needless_bool.rs | 192 ----- src/needless_borrow.rs | 51 -- src/needless_update.rs | 42 - src/neg_multiply.rs | 57 -- src/new_without_default.rs | 148 ---- src/no_effect.rs | 155 ---- src/non_expressive_names.rs | 291 ------- src/open_options.rs | 185 ----- src/overflow_check_conditional.rs | 72 -- src/panic.rs | 47 -- src/precedence.rs | 118 --- src/print.rs | 88 -- src/ptr_arg.rs | 78 -- src/ranges.rs | 89 -- src/regex.rs | 229 ------ src/returns.rs | 137 ---- src/shadow.rs | 353 -------- src/strings.rs | 160 ---- src/swap.rs | 138 ---- src/temporary_assignment.rs | 49 -- src/transmute.rs | 131 --- src/types.rs | 974 ---------------------- src/unicode.rs | 109 --- src/unsafe_removed_from_name.rs | 81 -- src/unused_label.rs | 78 -- src/utils/comparisons.rs | 23 - src/utils/conf.rs | 205 ----- src/utils/hir.rs | 513 ------------ src/utils/mod.rs | 840 ------------------- src/utils/paths.rs | 61 -- src/vec.rs | 116 --- src/zero_div_zero.rs | 59 -- tests/dogfood.rs | 24 +- util/update_lints.py | 20 +- 158 files changed, 14909 insertions(+), 14796 deletions(-) create mode 100644 clippy_lints/Cargo.toml create mode 100644 clippy_lints/src/approx_const.rs create mode 100644 clippy_lints/src/arithmetic.rs create mode 100644 clippy_lints/src/array_indexing.rs create mode 100644 clippy_lints/src/assign_ops.rs create mode 100644 clippy_lints/src/attrs.rs create mode 100644 clippy_lints/src/bit_mask.rs create mode 100644 clippy_lints/src/blacklisted_name.rs create mode 100644 clippy_lints/src/block_in_if_condition.rs create mode 100644 clippy_lints/src/booleans.rs create mode 100644 clippy_lints/src/collapsible_if.rs create mode 100644 clippy_lints/src/consts.rs create mode 100644 clippy_lints/src/copies.rs create mode 100644 clippy_lints/src/cyclomatic_complexity.rs create mode 100644 clippy_lints/src/deprecated_lints.rs create mode 100644 clippy_lints/src/derive.rs create mode 100644 clippy_lints/src/doc.rs create mode 100644 clippy_lints/src/drop_ref.rs create mode 100644 clippy_lints/src/entry.rs create mode 100644 clippy_lints/src/enum_clike.rs create mode 100644 clippy_lints/src/enum_glob_use.rs create mode 100644 clippy_lints/src/enum_variants.rs create mode 100644 clippy_lints/src/eq_op.rs create mode 100644 clippy_lints/src/escape.rs create mode 100644 clippy_lints/src/eta_reduction.rs create mode 100644 clippy_lints/src/format.rs create mode 100644 clippy_lints/src/formatting.rs create mode 100644 clippy_lints/src/functions.rs create mode 100644 clippy_lints/src/identity_op.rs create mode 100644 clippy_lints/src/if_not_else.rs create mode 100644 clippy_lints/src/items_after_statements.rs create mode 100644 clippy_lints/src/len_zero.rs create mode 100644 clippy_lints/src/lib.rs create mode 100644 clippy_lints/src/lifetimes.rs create mode 100644 clippy_lints/src/loops.rs create mode 100644 clippy_lints/src/map_clone.rs create mode 100644 clippy_lints/src/matches.rs create mode 100644 clippy_lints/src/mem_forget.rs create mode 100644 clippy_lints/src/methods.rs create mode 100644 clippy_lints/src/minmax.rs create mode 100644 clippy_lints/src/misc.rs create mode 100644 clippy_lints/src/misc_early.rs create mode 100644 clippy_lints/src/mut_mut.rs create mode 100644 clippy_lints/src/mut_reference.rs create mode 100644 clippy_lints/src/mutex_atomic.rs create mode 100644 clippy_lints/src/needless_bool.rs create mode 100644 clippy_lints/src/needless_borrow.rs create mode 100644 clippy_lints/src/needless_update.rs create mode 100644 clippy_lints/src/neg_multiply.rs create mode 100644 clippy_lints/src/new_without_default.rs create mode 100644 clippy_lints/src/no_effect.rs create mode 100644 clippy_lints/src/non_expressive_names.rs create mode 100644 clippy_lints/src/open_options.rs create mode 100644 clippy_lints/src/overflow_check_conditional.rs create mode 100644 clippy_lints/src/panic.rs create mode 100644 clippy_lints/src/precedence.rs create mode 100644 clippy_lints/src/print.rs create mode 100644 clippy_lints/src/ptr_arg.rs create mode 100644 clippy_lints/src/ranges.rs create mode 100644 clippy_lints/src/regex.rs create mode 100644 clippy_lints/src/returns.rs create mode 100644 clippy_lints/src/shadow.rs create mode 100644 clippy_lints/src/strings.rs create mode 100644 clippy_lints/src/swap.rs create mode 100644 clippy_lints/src/temporary_assignment.rs create mode 100644 clippy_lints/src/transmute.rs create mode 100644 clippy_lints/src/types.rs create mode 100644 clippy_lints/src/unicode.rs create mode 100644 clippy_lints/src/unsafe_removed_from_name.rs create mode 100644 clippy_lints/src/unused_label.rs create mode 100644 clippy_lints/src/utils/comparisons.rs create mode 100644 clippy_lints/src/utils/conf.rs create mode 100644 clippy_lints/src/utils/hir.rs create mode 100644 clippy_lints/src/utils/mod.rs create mode 100644 clippy_lints/src/utils/paths.rs create mode 100644 clippy_lints/src/vec.rs create mode 100644 clippy_lints/src/zero_div_zero.rs delete mode 100644 src/approx_const.rs delete mode 100644 src/arithmetic.rs delete mode 100644 src/array_indexing.rs delete mode 100644 src/assign_ops.rs delete mode 100644 src/attrs.rs delete mode 100644 src/bit_mask.rs delete mode 100644 src/blacklisted_name.rs delete mode 100644 src/block_in_if_condition.rs delete mode 100644 src/booleans.rs delete mode 100644 src/collapsible_if.rs delete mode 100644 src/consts.rs delete mode 100644 src/copies.rs delete mode 100644 src/cyclomatic_complexity.rs delete mode 100644 src/deprecated_lints.rs delete mode 100644 src/derive.rs delete mode 100644 src/doc.rs delete mode 100644 src/drop_ref.rs delete mode 100644 src/entry.rs delete mode 100644 src/enum_clike.rs delete mode 100644 src/enum_glob_use.rs delete mode 100644 src/enum_variants.rs delete mode 100644 src/eq_op.rs delete mode 100644 src/escape.rs delete mode 100644 src/eta_reduction.rs delete mode 100644 src/format.rs delete mode 100644 src/formatting.rs delete mode 100644 src/functions.rs delete mode 100644 src/identity_op.rs delete mode 100644 src/if_not_else.rs delete mode 100644 src/items_after_statements.rs delete mode 100644 src/len_zero.rs delete mode 100644 src/lifetimes.rs delete mode 100644 src/loops.rs create mode 100644 src/main.rs delete mode 100644 src/map_clone.rs delete mode 100644 src/matches.rs delete mode 100644 src/mem_forget.rs delete mode 100644 src/methods.rs delete mode 100644 src/minmax.rs delete mode 100644 src/misc.rs delete mode 100644 src/misc_early.rs delete mode 100644 src/mut_mut.rs delete mode 100644 src/mut_reference.rs delete mode 100644 src/mutex_atomic.rs delete mode 100644 src/needless_bool.rs delete mode 100644 src/needless_borrow.rs delete mode 100644 src/needless_update.rs delete mode 100644 src/neg_multiply.rs delete mode 100644 src/new_without_default.rs delete mode 100644 src/no_effect.rs delete mode 100644 src/non_expressive_names.rs delete mode 100644 src/open_options.rs delete mode 100644 src/overflow_check_conditional.rs delete mode 100644 src/panic.rs delete mode 100644 src/precedence.rs delete mode 100644 src/print.rs delete mode 100644 src/ptr_arg.rs delete mode 100644 src/ranges.rs delete mode 100644 src/regex.rs delete mode 100644 src/returns.rs delete mode 100644 src/shadow.rs delete mode 100644 src/strings.rs delete mode 100644 src/swap.rs delete mode 100644 src/temporary_assignment.rs delete mode 100644 src/transmute.rs delete mode 100644 src/types.rs delete mode 100644 src/unicode.rs delete mode 100644 src/unsafe_removed_from_name.rs delete mode 100644 src/unused_label.rs delete mode 100644 src/utils/comparisons.rs delete mode 100644 src/utils/conf.rs delete mode 100644 src/utils/hir.rs delete mode 100644 src/utils/mod.rs delete mode 100644 src/utils/paths.rs delete mode 100644 src/vec.rs delete mode 100644 src/zero_div_zero.rs diff --git a/.gitignore b/.gitignore index acb3c020fe7..2db1ec5144f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ # Generated by Cargo /target/ +/clippy_lints/target/ # We don't pin yet Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index fd0b07428c0..3a45da08f89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ test = false [[bin]] name = "cargo-clippy" -path = "src/lib.rs" test = false [dependencies] @@ -30,6 +29,7 @@ semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" +clippy_lints = { version = "0.0.*", path = "clippy_lints" } [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml new file mode 100644 index 00000000000..da10ca0c0b7 --- /dev/null +++ b/clippy_lints/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "clippy_lints" +version = "0.0.69" +authors = [ + "Manish Goregaokar <manishsmail@gmail.com>", + "Andre Bogus <bogusandre@gmail.com>", + "Georg Brandl <georg@python.org>", + "Martin Carton <cartonmartin@gmail.com>" +] +description = "A bunch of helpful lints to avoid common pitfalls in Rust" +repository = "https://github.com/Manishearth/rust-clippy" +readme = "README.md" +license = "MPL-2.0" +keywords = ["clippy", "lint", "plugin"] + +[dependencies] +regex-syntax = "0.3.0" +semver = "0.2.1" +toml = "0.1" +unicode-normalization = "0.1" +quine-mc_cluskey = "0.2.2" + +[features] +debugging = [] diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs new file mode 100644 index 00000000000..731f1a45d09 --- /dev/null +++ b/clippy_lints/src/approx_const.rs @@ -0,0 +1,95 @@ +use rustc::lint::*; +use rustc::hir::*; +use std::f64::consts as f64; +use syntax::ast::{Lit, LitKind, FloatTy}; +use utils::span_lint; + +/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. +/// +/// **Why is this bad?** Usually, the definition in the standard library is more precise than what people come up with. If you find that your definition is actually more precise, please [file a Rust issue](https://github.com/rust-lang/rust/issues). +/// +/// **Known problems:** If you happen to have a value that is within 1/8192 of a known constant, but is not *and should not* be the same, this lint will report your value anyway. We have not yet noticed any false positives in code we tested clippy with (this includes servo), but YMMV. +/// +/// **Example:** `let x = 3.14;` +declare_lint! { + pub APPROX_CONSTANT, + Warn, + "the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) \ + is found; suggests to use the constant" +} + +// Tuples are of the form (constant, name, min_digits) +const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), + (f64::FRAC_1_PI, "FRAC_1_PI", 4), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), + (f64::FRAC_2_PI, "FRAC_2_PI", 5), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), + (f64::FRAC_PI_2, "FRAC_PI_2", 5), + (f64::FRAC_PI_3, "FRAC_PI_3", 5), + (f64::FRAC_PI_4, "FRAC_PI_4", 5), + (f64::FRAC_PI_6, "FRAC_PI_6", 5), + (f64::FRAC_PI_8, "FRAC_PI_8", 5), + (f64::LN_10, "LN_10", 5), + (f64::LN_2, "LN_2", 5), + (f64::LOG10_E, "LOG10_E", 5), + (f64::LOG2_E, "LOG2_E", 5), + (f64::PI, "PI", 3), + (f64::SQRT_2, "SQRT_2", 5)]; + +#[derive(Copy,Clone)] +pub struct ApproxConstant; + +impl LintPass for ApproxConstant { + fn get_lints(&self) -> LintArray { + lint_array!(APPROX_CONSTANT) + } +} + +impl LateLintPass for ApproxConstant { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprLit(ref lit) = e.node { + check_lit(cx, lit, e); + } + } +} + +fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { + match lit.node { + LitKind::Float(ref s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), + LitKind::Float(ref s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), + LitKind::FloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), + _ => (), + } +} + +fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { + if let Ok(_) = s.parse::<f64>() { + for &(constant, name, min_digits) in KNOWN_CONSTS { + if is_approx_const(constant, s, min_digits) { + span_lint(cx, + APPROX_CONSTANT, + e.span, + &format!("approximate value of `{}::{}` found. Consider using it directly", module, &name)); + return; + } + } + } +} + +/// Returns false if the number of significant figures in `value` are +/// less than `min_digits`; otherwise, returns true if `value` is equal +/// to `constant`, rounded to the number of digits present in `value`. +fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool { + if value.len() <= min_digits { + false + } else { + let round_const = format!("{:.*}", value.len() - 2, constant); + + let mut trunc_const = constant.to_string(); + if trunc_const.len() > value.len() { + trunc_const.truncate(value.len()); + } + + (value == round_const) || (value == trunc_const) + } +} diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs new file mode 100644 index 00000000000..be732740442 --- /dev/null +++ b/clippy_lints/src/arithmetic.rs @@ -0,0 +1,102 @@ +use rustc::hir; +use rustc::lint::*; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** This lint checks for plain integer arithmetic +/// +/// **Why is this bad?** This is only checked against overflow in debug builds. +/// In some applications one wants explicitly checked, wrapping or saturating +/// arithmetic. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// a + 1 +/// ``` +declare_restriction_lint! { + pub INTEGER_ARITHMETIC, + "Any integer arithmetic statement" +} + +/// **What it does:** This lint checks for float arithmetic +/// +/// **Why is this bad?** For some embedded systems or kernel development, it +/// can be useful to rule out floating-point numbers +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// a + 1.0 +/// ``` +declare_restriction_lint! { + pub FLOAT_ARITHMETIC, + "Any floating-point arithmetic statement" +} + +#[derive(Copy, Clone, Default)] +pub struct Arithmetic { + span: Option<Span> +} + +impl LintPass for Arithmetic { + fn get_lints(&self) -> LintArray { + lint_array!(INTEGER_ARITHMETIC, FLOAT_ARITHMETIC) + } +} + +impl LateLintPass for Arithmetic { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + if let Some(_) = self.span { return; } + match expr.node { + hir::ExprBinary(ref op, ref l, ref r) => { + match op.node { + hir::BiAnd | hir::BiOr | hir::BiBitAnd | + hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | + hir::BiGt => return, + _ => () + } + let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r)); + if l_ty.is_integral() && r_ty.is_integral() { + span_lint(cx, + INTEGER_ARITHMETIC, + expr.span, + "integer arithmetic detected"); + self.span = Some(expr.span); + } else if l_ty.is_floating_point() && r_ty.is_floating_point() { + span_lint(cx, + FLOAT_ARITHMETIC, + expr.span, + "floating-point arithmetic detected"); + self.span = Some(expr.span); + } + }, + hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { + let ty = cx.tcx.expr_ty(arg); + if ty.is_integral() { + span_lint(cx, + INTEGER_ARITHMETIC, + expr.span, + "integer arithmetic detected"); + self.span = Some(expr.span); + } else if ty.is_floating_point() { + span_lint(cx, + FLOAT_ARITHMETIC, + expr.span, + "floating-point arithmetic detected"); + self.span = Some(expr.span); + } + }, + _ => () + } + } + + fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) { + if Some(expr.span) == self.span { + self.span = None; + } + } +} diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs new file mode 100644 index 00000000000..ce2b9a7d6c0 --- /dev/null +++ b/clippy_lints/src/array_indexing.rs @@ -0,0 +1,135 @@ +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc::ty::TyArray; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_math::ConstInt; +use rustc::hir::*; +use syntax::ast::RangeLimits; +use utils; + +/// **What it does:** Check for out of bounds array indexing with a constant index. +/// +/// **Why is this bad?** This will always panic at runtime. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ``` +/// let x = [1,2,3,4]; +/// ... +/// x[9]; +/// &x[2..9]; +/// ``` +declare_lint! { + pub OUT_OF_BOUNDS_INDEXING, + Deny, + "out of bound constant indexing" +} + +/// **What it does:** Check for usage of indexing or slicing. +/// +/// **Why is this bad?** Usually, this can be safely allowed. However, +/// in some domains such as kernel development, a panic can cause the +/// whole operating system to crash. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ``` +/// ... +/// x[2]; +/// &x[0..2]; +/// ``` +declare_lint! { + pub INDEXING_SLICING, + Allow, + "indexing/slicing usage" +} + +#[derive(Copy,Clone)] +pub struct ArrayIndexing; + +impl LintPass for ArrayIndexing { + fn get_lints(&self) -> LintArray { + lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) + } +} + +impl LateLintPass for ArrayIndexing { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprIndex(ref array, ref index) = e.node { + // Array with known size can be checked statically + let ty = cx.tcx.expr_ty(array); + if let TyArray(_, size) = ty.sty { + let size = ConstInt::Infer(size as u64); + + // Index is a constant uint + let const_index = eval_const_expr_partial(cx.tcx, index, ExprTypeChecked, None); + if let Ok(ConstVal::Integral(const_index)) = const_index { + if size <= const_index { + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); + } + + return; + } + + // Index is a constant range + if let Some(range) = utils::unsugar_range(index) { + let start = range.start + .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) + .map(|v| v.ok()); + let end = range.end + .map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)) + .map(|v| v.ok()); + + if let Some((start, end)) = to_const_range(start, end, range.limits, size) { + if start > size || end > size { + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); + } + return; + } + } + } + + if let Some(range) = utils::unsugar_range(index) { + // Full ranges are always valid + if range.start.is_none() && range.end.is_none() { + return; + } + + // Impossible to know if indexing or slicing is correct + utils::span_lint(cx, INDEXING_SLICING, e.span, "slicing may panic"); + } else { + utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); + } + } + } +} + +/// Returns an option containing a tuple with the start and end (exclusive) of the range. +fn to_const_range(start: Option<Option<ConstVal>>, end: Option<Option<ConstVal>>, limits: RangeLimits, + array_size: ConstInt) + -> Option<(ConstInt, ConstInt)> { + let start = match start { + Some(Some(ConstVal::Integral(x))) => x, + Some(_) => return None, + None => ConstInt::Infer(0), + }; + + let end = match end { + Some(Some(ConstVal::Integral(x))) => { + if limits == RangeLimits::Closed { + (x + ConstInt::Infer(1)).expect("such a big array is not realistic") + } else { + x + } + } + Some(_) => return None, + None => array_size, + }; + + Some((start, end)) +} diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs new file mode 100644 index 00000000000..2b1aec83e4c --- /dev/null +++ b/clippy_lints/src/assign_ops.rs @@ -0,0 +1,158 @@ +use rustc::hir; +use rustc::lint::*; +use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; + +/// **What it does:** This lint checks for `+=` operations and similar +/// +/// **Why is this bad?** Projects with many developers from languages without those operations +/// may find them unreadable and not worth their weight +/// +/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op` +/// +/// **Example:** +/// ``` +/// a += 1; +/// ``` +declare_restriction_lint! { + pub ASSIGN_OPS, + "Any assignment operation" +} + +/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns +/// +/// **Why is this bad?** These can be written as the shorter `a op= b` +/// +/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl +/// +/// **Example:** +/// +/// ``` +/// let mut a = 5; +/// ... +/// a = a + b; +/// ``` +declare_lint! { + pub ASSIGN_OP_PATTERN, + Warn, + "assigning the result of an operation on a variable to that same variable" +} + +#[derive(Copy, Clone, Default)] +pub struct AssignOps; + +impl LintPass for AssignOps { + fn get_lints(&self) -> LintArray { + lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN) + } +} + +impl LateLintPass for AssignOps { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + match expr.node { + hir::ExprAssignOp(op, ref lhs, ref rhs) => { + if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) { + span_lint_and_then(cx, + ASSIGN_OPS, + expr.span, + "assign operation detected", + |db| { + match rhs.node { + hir::ExprBinary(op2, _, _) if op2 != op => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); + }, + _ => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} {}", l, l, op.node.as_str(), r)); + } + } + }); + } else { + span_lint(cx, + ASSIGN_OPS, + expr.span, + "assign operation detected"); + } + }, + hir::ExprAssign(ref assignee, ref e) => { + if let hir::ExprBinary(op, ref l, ref r) = e.node { + let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { + let ty = cx.tcx.expr_ty(assignee); + if ty.walk_shallow().next().is_some() { + return; // implements_trait does not work with generics + } + let rty = cx.tcx.expr_ty(rhs); + if rty.walk_shallow().next().is_some() { + return; // implements_trait does not work with generics + } + macro_rules! ops { + ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => { + match $op { + $(hir::$full_trait_name => { + let [krate, module] = ::utils::paths::OPS_MODULE; + let path = [krate, module, concat!(stringify!($trait_name), "Assign")]; + let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { + trait_id + } else { + return; // useless if the trait doesn't exist + }; + implements_trait($cx, $ty, trait_id, vec![$rty]) + },)* + _ => false, + } + } + } + if ops!(op.node, cx, ty, rty, Add:BiAdd, + Sub:BiSub, + Mul:BiMul, + Div:BiDiv, + Rem:BiRem, + And:BiAnd, + Or:BiOr, + BitAnd:BiBitAnd, + BitOr:BiBitOr, + BitXor:BiBitXor, + Shr:BiShr, + Shl:BiShl + ) { + if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { + span_lint_and_then(cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |db| { + db.span_suggestion(expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r)); + }); + } else { + span_lint(cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation"); + } + } + }; + // a = a op b + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { + lint(assignee, r); + } + // a = b commutative_op a + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { + match op.node { + hir::BiAdd | hir::BiMul | + hir::BiAnd | hir::BiOr | + hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => { + lint(assignee, l); + }, + _ => {}, + } + } + } + }, + _ => {}, + } + } +} diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs new file mode 100644 index 00000000000..0cf62633de4 --- /dev/null +++ b/clippy_lints/src/attrs.rs @@ -0,0 +1,176 @@ +//! checks for attributes + +use reexport::*; +use rustc::lint::*; +use rustc::hir::*; +use semver::Version; +use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; +use syntax::codemap::Span; +use utils::{in_macro, match_path, span_lint}; +use utils::paths; + +/// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. +/// +/// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it. +/// +/// As a rule of thumb, before slapping `#[inline(always)]` on a function, measure if that additional function call really affects your runtime profile sufficiently to make up for the increase in compile time. +/// +/// **Known problems:** False positives, big time. This lint is meant to be deactivated by everyone doing serious performance work. This means having done the measurement. +/// +/// **Example:** +/// ``` +/// #[inline(always)] +/// fn not_quite_hot_code(..) { ... } +/// ``` +declare_lint! { + pub INLINE_ALWAYS, Warn, + "`#[inline(always)]` is a bad idea in most cases" +} + +/// **What it does:** This lint checks for `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. +/// +/// **Why is this bad?** For checking the version of the deprecation, it must be valid semver. Failing that, the contained information is useless. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// #[deprecated(since = "forever")] +/// fn something_else(..) { ... } +/// ``` +declare_lint! { + pub DEPRECATED_SEMVER, Warn, + "`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" +} + +#[derive(Copy,Clone)] +pub struct AttrPass; + +impl LintPass for AttrPass { + fn get_lints(&self) -> LintArray { + lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER) + } +} + +impl LateLintPass for AttrPass { + fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) { + if let MetaItemKind::List(ref name, ref items) = attr.node.value.node { + if items.is_empty() || name != &"deprecated" { + return; + } + for ref item in items { + if let MetaItemKind::NameValue(ref name, ref lit) = item.node { + if name == &"since" { + check_semver(cx, item.span, lit); + } + } + } + } + } + + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if is_relevant_item(item) { + check_attrs(cx, item.span, &item.name, &item.attrs) + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + if is_relevant_impl(item) { + check_attrs(cx, item.span, &item.name, &item.attrs) + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + if is_relevant_trait(item) { + check_attrs(cx, item.span, &item.name, &item.attrs) + } + } +} + +fn is_relevant_item(item: &Item) -> bool { + if let ItemFn(_, _, _, _, _, ref block) = item.node { + is_relevant_block(block) + } else { + false + } +} + +fn is_relevant_impl(item: &ImplItem) -> bool { + match item.node { + ImplItemKind::Method(_, ref block) => is_relevant_block(block), + _ => false, + } +} + +fn is_relevant_trait(item: &TraitItem) -> bool { + match item.node { + MethodTraitItem(_, None) => true, + MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), + _ => false, + } +} + +fn is_relevant_block(block: &Block) -> bool { + for stmt in &block.stmts { + match stmt.node { + StmtDecl(_, _) => return true, + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => { + return is_relevant_expr(expr); + } + } + } + block.expr.as_ref().map_or(false, |e| is_relevant_expr(e)) +} + +fn is_relevant_expr(expr: &Expr) -> bool { + match expr.node { + ExprBlock(ref block) => is_relevant_block(block), + ExprRet(Some(ref e)) => is_relevant_expr(e), + ExprRet(None) | ExprBreak(_) => false, + ExprCall(ref path_expr, _) => { + if let ExprPath(_, ref path) = path_expr.node { + !match_path(path, &paths::BEGIN_PANIC) + } else { + true + } + } + _ => true, + } +} + +fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { + if in_macro(cx, span) { + return; + } + + for attr in attrs { + if let MetaItemKind::List(ref inline, ref values) = attr.node.value.node { + if values.len() != 1 || inline != &"inline" { + continue; + } + if let MetaItemKind::Word(ref always) = values[0].node { + if always != &"always" { + continue; + } + span_lint(cx, + INLINE_ALWAYS, + attr.span, + &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea", + name)); + } + } + } +} + +fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { + if let LitKind::Str(ref is, _) = lit.node { + if Version::parse(&*is).is_ok() { + return; + } + } + span_lint(cx, + DEPRECATED_SEMVER, + span, + "the since field must contain a semver-compliant version"); +} diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs new file mode 100644 index 00000000000..aec0990dcc6 --- /dev/null +++ b/clippy_lints/src/bit_mask.rs @@ -0,0 +1,276 @@ +use rustc::hir::*; +use rustc::hir::def::{Def, PathResolution}; +use rustc::lint::*; +use rustc_const_eval::lookup_const_by_id; +use syntax::ast::LitKind; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** This lint checks for incompatible bit masks in comparisons. +/// +/// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: +/// +/// |Comparison |Bit Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// +/// **Why is this bad?** If the bits that the comparison cares about are always set to zero or one by the bit mask, the comparison is constant `true` or `false` (depending on mask, compared value, and operators). +/// +/// So the code is actively misleading, and the only reason someone would write this intentionally is to win an underhanded Rust contest or create a test-case for this lint. +/// +/// **Known problems:** None +/// +/// **Example:** `x & 1 == 2` (also see table above) +declare_lint! { + pub BAD_BIT_MASK, + Warn, + "expressions of the form `_ & mask == select` that will only ever return `true` or `false` \ + (because in the example `select` containing bits that `mask` doesn't have)" +} + +/// **What it does:** This lint checks for bit masks in comparisons which can be removed without changing the outcome. The basic structure can be seen in the following table: +/// +/// |Comparison| Bit Op |Example |equals | +/// |----------|---------|-----------|-------| +/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| +/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`| +/// +/// **Why is this bad?** Not equally evil as [`bad_bit_mask`](#bad_bit_mask), but still a bit misleading, because the bit mask is ineffective. +/// +/// **Known problems:** False negatives: This lint will only match instances where we have figured out the math (which is for a power-of-two compared value). This means things like `x | 1 >= 7` (which would be better written as `x >= 6`) will not be reported (but bit masks like this are fairly uncommon). +/// +/// **Example:** `x | 1 > 3` (also see table above) +declare_lint! { + pub INEFFECTIVE_BIT_MASK, + Warn, + "expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`" +} + +/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. +/// This cannot work because the bit that makes up the value two was +/// zeroed out by the bit-and with 1. So the formula for detecting if an +/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , +/// `!=`, `>=`, `>`}) can be determined from the following table: +/// +/// |Comparison |Bit Op|Example |is always|Formula | +/// |------------|------|------------|---------|----------------------| +/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | +/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | +/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | +/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | +/// +/// This lint is **deny** by default +/// +/// There is also a lint that warns on ineffective masks that is *warn* +/// by default. +/// +/// |Comparison|Bit Op |Example |equals |Formula| +/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| +/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | +/// +/// `¹ power_of_two(c + 1)` +#[derive(Copy,Clone)] +pub struct BitMask; + +impl LintPass for BitMask { + fn get_lints(&self) -> LintArray { + lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) + } +} + +impl LateLintPass for BitMask { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + if cmp.node.is_comparison() { + fetch_int_literal(cx, right).map_or_else(|| { + fetch_int_literal(cx, left).map_or((), |cmp_val| { + check_compare(cx, + right, + invert_cmp(cmp.node), + cmp_val, + &e.span) + }) + }, + |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, &e.span)) + } + } + } +} + +fn invert_cmp(cmp: BinOp_) -> BinOp_ { + match cmp { + BiEq => BiEq, + BiNe => BiNe, + BiLt => BiGt, + BiGt => BiLt, + BiLe => BiGe, + BiGe => BiLe, + _ => BiOr, // Dummy + } +} + + +fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { + if let ExprBinary(ref op, ref left, ref right) = bit_op.node { + if op.node != BiBitAnd && op.node != BiBitOr { + return; + } + fetch_int_literal(cx, right) + .or_else(|| fetch_int_literal(cx, left)) + .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span)) + } +} + +fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { + match cmp_op { + BiEq | BiNe => { + match bit_op { + BiBitAnd => { + if mask_value & cmp_value != cmp_value { + if cmp_value != 0 { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, + cmp_value)); + } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } + BiBitOr => { + if mask_value | cmp_value != cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, + cmp_value)); + } + } + _ => (), + } + } + BiLt | BiGe => { + match bit_op { + BiBitAnd => { + if mask_value < cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, + cmp_value)); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } + BiBitOr => { + if mask_value >= cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, + cmp_value)); + } else { + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); + } + } + BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), + _ => (), + } + } + BiLe | BiGt => { + match bit_op { + BiBitAnd => { + if mask_value <= cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, + cmp_value)); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + } + } + BiBitOr => { + if mask_value > cmp_value { + span_lint(cx, + BAD_BIT_MASK, + *span, + &format!("incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, + cmp_value)); + } else { + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); + } + } + BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), + _ => (), + } + } + _ => (), + } +} + +fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { + if c.is_power_of_two() && m < c { + span_lint(cx, + INEFFECTIVE_BIT_MASK, + span, + &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c)); + } +} + +fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { + if (c + 1).is_power_of_two() && m <= c { + span_lint(cx, + INEFFECTIVE_BIT_MASK, + span, + &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c)); + } +} + +fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { + match lit.node { + ExprLit(ref lit_ptr) => { + if let LitKind::Int(value, _) = lit_ptr.node { + Some(value) //TODO: Handle sign + } else { + None + } + } + ExprPath(_, _) => { + { + // Important to let the borrow expire before the const lookup to avoid double + // borrowing. + let def_map = cx.tcx.def_map.borrow(); + match def_map.get(&lit.id) { + Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id), + _ => None, + } + } + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) + .and_then(|(l, _ty)| fetch_int_literal(cx, l)) + } + _ => None, + } +} diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs new file mode 100644 index 00000000000..5cb84f62651 --- /dev/null +++ b/clippy_lints/src/blacklisted_name.rs @@ -0,0 +1,46 @@ +use rustc::lint::*; +use rustc::hir::*; +use utils::span_lint; + +/// **What it does:** This lints about usage of blacklisted names. +/// +/// **Why is this bad?** These names are usually placeholder names and should be avoided. +/// +/// **Known problems:** None. +/// +/// **Example:** `let foo = 3.14;` +declare_lint! { + pub BLACKLISTED_NAME, + Warn, + "usage of a blacklisted/placeholder name" +} + +#[derive(Clone, Debug)] +pub struct BlackListedName { + blacklist: Vec<String>, +} + +impl BlackListedName { + pub fn new(blacklist: Vec<String>) -> BlackListedName { + BlackListedName { blacklist: blacklist } + } +} + +impl LintPass for BlackListedName { + fn get_lints(&self) -> LintArray { + lint_array!(BLACKLISTED_NAME) + } +} + +impl LateLintPass for BlackListedName { + fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { + if let PatKind::Ident(_, ref ident, _) = pat.node { + if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) { + span_lint(cx, + BLACKLISTED_NAME, + pat.span, + &format!("use of a blacklisted/placeholder name `{}`", ident.node)); + } + } + } +} diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs new file mode 100644 index 00000000000..c56cf4dcd29 --- /dev/null +++ b/clippy_lints/src/block_in_if_condition.rs @@ -0,0 +1,118 @@ +use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr}; +use utils::*; + +/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. +/// +/// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions. +/// +/// **Known problems:** None +/// +/// **Example:** `if { true } ..` +declare_lint! { + pub BLOCK_IN_IF_CONDITION_EXPR, Warn, + "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" +} + +/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. +/// +/// **Why is this bad?** Using blocks in the condition makes it hard to read. +/// +/// **Known problems:** None +/// +/// **Example:** `if { let x = somefunc(); x } ..` or `if somefunc(|x| { x == 47 }) ..` +declare_lint! { + pub BLOCK_IN_IF_CONDITION_STMT, Warn, + "avoid complex blocks in conditions, instead move the block higher and bind it \ + with 'let'; e.g: `if { let x = true; x } ...`" +} + +#[derive(Copy,Clone)] +pub struct BlockInIfCondition; + +impl LintPass for BlockInIfCondition { + fn get_lints(&self) -> LintArray { + lint_array!(BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT) + } +} + +struct ExVisitor<'v> { + found_block: Option<&'v Expr>, +} + +impl<'v> Visitor<'v> for ExVisitor<'v> { + fn visit_expr(&mut self, expr: &'v Expr) { + if let ExprClosure(_, _, ref block, _) = expr.node { + let complex = { + if block.stmts.is_empty() { + if let Some(ref ex) = block.expr { + match ex.node { + ExprBlock(_) => true, + _ => false, + } + } else { + false + } + } else { + true + } + }; + if complex { + self.found_block = Some(expr); + return; + } + } + walk_expr(self, expr); + } +} + +const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition"; +const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ + instead, move the block or closure higher and bind it with a 'let'"; + +impl LateLintPass for BlockInIfCondition { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprIf(ref check, ref then, _) = expr.node { + if let ExprBlock(ref block) = check.node { + if block.rules == DefaultBlock { + if block.stmts.is_empty() { + if let Some(ref ex) = block.expr { + // don't dig into the expression here, just suggest that they remove + // the block + if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, ex.span) { + return; + } + span_help_and_lint(cx, + BLOCK_IN_IF_CONDITION_EXPR, + check.span, + BRACED_EXPR_MESSAGE, + &format!("try\nif {} {} ... ", + snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, ".."))); + } + } else { + let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); + if in_macro(cx, span) || differing_macro_contexts(expr.span, span) { + return; + } + // move block higher + span_help_and_lint(cx, + BLOCK_IN_IF_CONDITION_STMT, + check.span, + COMPLEX_BLOCK_MESSAGE, + &format!("try\nlet res = {};\nif res {} ... ", + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, ".."))); + } + } + } else { + let mut visitor = ExVisitor { found_block: None }; + walk_expr(&mut visitor, check); + if let Some(ref block) = visitor.found_block { + span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE, ""); + } + } + } + } +} diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs new file mode 100644 index 00000000000..9ab806f66ec --- /dev/null +++ b/clippy_lints/src/booleans.rs @@ -0,0 +1,389 @@ +use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::hir::*; +use rustc::hir::intravisit::*; +use syntax::ast::{LitKind, DUMMY_NODE_ID}; +use syntax::codemap::{DUMMY_SP, dummy_spanned}; +use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; + +/// **What it does:** This lint checks for boolean expressions that can be written more concisely +/// +/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication +/// +/// **Known problems:** Ignores short circuting behavior of `||` and `&&`. Ignores `|`, `&` and `^`. +/// +/// **Example:** `if a && true` should be `if a` and `!(a == b)` should be `a != b` +declare_lint! { + pub NONMINIMAL_BOOL, Allow, + "checks for boolean expressions that can be written more concisely" +} + +/// **What it does:** This lint checks for boolean expressions that contain terminals that can be eliminated +/// +/// **Why is this bad?** This is most likely a logic bug +/// +/// **Known problems:** Ignores short circuiting behavior +/// +/// **Example:** The `b` in `if a && b || a` is unnecessary because the expression is equivalent to `if a` +declare_lint! { + pub LOGIC_BUG, Warn, + "checks for boolean expressions that contain terminals which can be eliminated" +} + +#[derive(Copy,Clone)] +pub struct NonminimalBool; + +impl LintPass for NonminimalBool { + fn get_lints(&self) -> LintArray { + lint_array!(NONMINIMAL_BOOL, LOGIC_BUG) + } +} + +impl LateLintPass for NonminimalBool { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + NonminimalBoolVisitor(cx).visit_item(item) + } +} + +struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); + +use quine_mc_cluskey::Bool; +struct Hir2Qmm<'a, 'tcx: 'a, 'v> { + terminals: Vec<&'v Expr>, + cx: &'a LateContext<'a, 'tcx>, +} + +impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { + fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> { + for a in a { + if let ExprBinary(binop, ref lhs, ref rhs) = a.node { + if binop.node == op { + v = self.extract(op, &[lhs, rhs], v)?; + continue; + } + } + v.push(self.run(a)?); + } + Ok(v) + } + + fn run(&mut self, e: &'v Expr) -> Result<Bool, String> { + // prevent folding of `cfg!` macros and the like + if !in_macro(self.cx, e.span) { + match e.node { + ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), + ExprBinary(binop, ref lhs, ref rhs) => { + match binop.node { + BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), + BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + _ => (), + } + } + ExprLit(ref lit) => { + match lit.node { + LitKind::Bool(true) => return Ok(Bool::True), + LitKind::Bool(false) => return Ok(Bool::False), + _ => (), + } + } + _ => (), + } + } + for (n, expr) in self.terminals.iter().enumerate() { + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Term(n as u8)); + } + let negated = match e.node { + ExprBinary(binop, ref lhs, ref rhs) => { + let mk_expr = |op| { + Expr { + id: DUMMY_NODE_ID, + span: DUMMY_SP, + attrs: None, + node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + } + }; + match binop.node { + BiEq => mk_expr(BiNe), + BiNe => mk_expr(BiEq), + BiGt => mk_expr(BiLe), + BiGe => mk_expr(BiLt), + BiLt => mk_expr(BiGe), + BiLe => mk_expr(BiGt), + _ => continue, + } + } + _ => continue, + }; + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + } + } + let n = self.terminals.len(); + self.terminals.push(e); + if n < 32 { + #[allow(cast_possible_truncation)] + Ok(Bool::Term(n as u8)) + } else { + Err("too many literals".to_owned()) + } + } +} + +fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { + fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { + use quine_mc_cluskey::Bool::*; + let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); + match *suggestion { + True => { + s.push_str("true"); + s + } + False => { + s.push_str("false"); + s + } + Not(ref inner) => { + match **inner { + And(_) | Or(_) => { + s.push('!'); + recurse(true, cx, inner, terminals, s) + } + Term(n) => { + if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { + s.push('!'); + return recurse(true, cx, inner, terminals, s); + } + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + } else { + s.push('!'); + recurse(false, cx, inner, terminals, s) + } + } + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + } + } + } + And(ref v) => { + if brackets { + s.push('('); + } + if let Or(_) = v[0] { + s = recurse(true, cx, &v[0], terminals, s); + } else { + s = recurse(false, cx, &v[0], terminals, s); + } + for inner in &v[1..] { + s.push_str(" && "); + if let Or(_) = *inner { + s = recurse(true, cx, inner, terminals, s); + } else { + s = recurse(false, cx, inner, terminals, s); + } + } + if brackets { + s.push(')'); + } + s + } + Or(ref v) => { + if brackets { + s.push('('); + } + s = recurse(false, cx, &v[0], terminals, s); + for inner in &v[1..] { + s.push_str(" || "); + s = recurse(false, cx, inner, terminals, s); + } + if brackets { + s.push(')'); + } + s + } + Term(n) => { + if brackets { + if let ExprBinary(..) = terminals[n as usize].node { + s.push('('); + } + } + s.push_str(&snip(terminals[n as usize])); + if brackets { + if let ExprBinary(..) = terminals[n as usize].node { + s.push(')'); + } + } + s + } + } + } + recurse(false, cx, suggestion, terminals, String::new()) +} + +fn simple_negate(b: Bool) -> Bool { + use quine_mc_cluskey::Bool::*; + match b { + True => False, + False => True, + t @ Term(_) => Not(Box::new(t)), + And(mut v) => { + for el in &mut v { + *el = simple_negate(::std::mem::replace(el, True)); + } + Or(v) + } + Or(mut v) => { + for el in &mut v { + *el = simple_negate(::std::mem::replace(el, True)); + } + And(v) + } + Not(inner) => *inner, + } +} + +#[derive(Default)] +struct Stats { + terminals: [usize; 32], + negations: usize, + ops: usize, +} + +fn terminal_stats(b: &Bool) -> Stats { + fn recurse(b: &Bool, stats: &mut Stats) { + match *b { + True | False => stats.ops += 1, + Not(ref inner) => { + match **inner { + And(_) | Or(_) => stats.ops += 1, // brackets are also operations + _ => stats.negations += 1, + } + recurse(inner, stats); + } + And(ref v) | Or(ref v) => { + stats.ops += v.len() - 1; + for inner in v { + recurse(inner, stats); + } + } + Term(n) => stats.terminals[n as usize] += 1, + } + } + use quine_mc_cluskey::Bool::*; + let mut stats = Stats::default(); + recurse(b, &mut stats); + stats +} + +impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { + fn bool_expr(&self, e: &Expr) { + let mut h2q = Hir2Qmm { + terminals: Vec::new(), + cx: self.0, + }; + if let Ok(expr) = h2q.run(e) { + + if h2q.terminals.len() > 8 { + // QMC has exponentially slow behavior as the number of terminals increases + // 8 is reasonable, it takes approximately 0.2 seconds. + // See #825 + return; + } + + let stats = terminal_stats(&expr); + let mut simplified = expr.simplify(); + for simple in Bool::Not(Box::new(expr.clone())).simplify() { + match simple { + Bool::Not(_) | Bool::True | Bool::False => {} + _ => simplified.push(Bool::Not(Box::new(simple.clone()))), + } + let simple_negated = simple_negate(simple); + if simplified.iter().any(|s| *s == simple_negated) { + continue; + } + simplified.push(simple_negated); + } + let mut improvements = Vec::new(); + 'simplified: for suggestion in &simplified { + let simplified_stats = terminal_stats(suggestion); + let mut improvement = false; + for i in 0..32 { + // ignore any "simplifications" that end up requiring a terminal more often than in the original expression + if stats.terminals[i] < simplified_stats.terminals[i] { + continue 'simplified; + } + if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { + span_lint_and_then(self.0, + LOGIC_BUG, + e.span, + "this boolean expression contains a logic bug", + |db| { + db.span_help(h2q.terminals[i].span, + "this expression can be optimized out by applying \ + boolean operations to the outer expression"); + db.span_suggestion(e.span, + "it would look like the following", + suggest(self.0, suggestion, &h2q.terminals)); + }); + // don't also lint `NONMINIMAL_BOOL` + return; + } + // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases + improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || + (stats.negations > simplified_stats.negations && + stats.ops == simplified_stats.ops) || + (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); + } + if improvement { + improvements.push(suggestion); + } + } + if !improvements.is_empty() { + span_lint_and_then(self.0, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + for suggestion in &improvements { + db.span_suggestion(e.span, + "try", + suggest(self.0, suggestion, &h2q.terminals)); + } + }); + } + } + } +} + +impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { + fn visit_expr(&mut self, e: &'v Expr) { + if in_macro(self.0, e.span) { + return; + } + match e.node { + ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), + ExprUnary(UnNot, ref inner) => { + if self.0.tcx.node_types()[&inner.id].is_bool() { + self.bool_expr(e); + } else { + walk_expr(self, e); + } + } + _ => walk_expr(self, e), + } + } +} diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs new file mode 100644 index 00000000000..38e04723e53 --- /dev/null +++ b/clippy_lints/src/collapsible_if.rs @@ -0,0 +1,129 @@ +//! Checks for if expressions that contain only an if expression. +//! +//! For example, the lint would catch: +//! +//! ``` +//! if x { +//! if y { +//! println!("Hello world"); +//! } +//! } +//! ``` +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc::hir::*; +use std::borrow::Cow; +use syntax::codemap::Spanned; + +use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; + +/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by +/// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to +/// `else if ..`. +/// +/// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. +/// +/// **Known problems:** None +/// +/// **Example:** `if x { if y { .. } }` +declare_lint! { + pub COLLAPSIBLE_IF, + Warn, + "two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` \ + can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to \ + `else if`" +} + +#[derive(Copy,Clone)] +pub struct CollapsibleIf; + +impl LintPass for CollapsibleIf { + fn get_lints(&self) -> LintArray { + lint_array!(COLLAPSIBLE_IF) + } +} + +impl LateLintPass for CollapsibleIf { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if !in_macro(cx, expr.span) { + check_if(cx, expr) + } + } +} + +fn check_if(cx: &LateContext, e: &Expr) { + if let ExprIf(ref check, ref then, ref else_) = e.node { + if let Some(ref else_) = *else_ { + if_let_chain! {[ + let ExprBlock(ref block) = else_.node, + block.stmts.is_empty(), + block.rules == BlockCheckMode::DefaultBlock, + let Some(ref else_) = block.expr, + let ExprIf(_, _, _) = else_.node + ], { + span_lint_and_then(cx, + COLLAPSIBLE_IF, + block.span, + "this `else { if .. }` block can be collapsed", |db| { + db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); + }); + }} + } else if let Some(&Expr { node: ExprIf(ref check_inner, ref content, None), span: sp, .. }) = + single_stmt_of_block(then) { + if e.span.expn_id != sp.expn_id { + return; + } + span_lint_and_then(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", |db| { + db.span_suggestion(e.span, + "try", + format!("if {} && {} {}", + check_to_string(cx, check), + check_to_string(cx, check_inner), + snippet_block(cx, content.span, ".."))); + }); + } + } +} + +fn requires_brackets(e: &Expr) -> bool { + match e.node { + ExprBinary(Spanned { node: n, .. }, _, _) if n == BiEq => false, + _ => true, + } +} + +fn check_to_string(cx: &LateContext, e: &Expr) -> Cow<'static, str> { + if requires_brackets(e) { + format!("({})", snippet(cx, e.span, "..")).into() + } else { + snippet(cx, e.span, "..") + } +} + +fn single_stmt_of_block(block: &Block) -> Option<&Expr> { + if block.stmts.len() == 1 && block.expr.is_none() { + if let StmtExpr(ref expr, _) = block.stmts[0].node { + single_stmt_of_expr(expr) + } else { + None + } + } else if block.stmts.is_empty() { + if let Some(ref p) = block.expr { + Some(p) + } else { + None + } + } else { + None + } +} + +fn single_stmt_of_expr(expr: &Expr) -> Option<&Expr> { + if let ExprBlock(ref block) = expr.node { + single_stmt_of_block(block) + } else { + Some(expr) + } +} diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs new file mode 100644 index 00000000000..96956d1793b --- /dev/null +++ b/clippy_lints/src/consts.rs @@ -0,0 +1,379 @@ +#![allow(cast_possible_truncation)] + +use rustc::lint::LateContext; +use rustc::hir::def::{Def, PathResolution}; +use rustc_const_eval::lookup_const_by_id; +use rustc_const_math::{ConstInt, ConstUsize, ConstIsize}; +use rustc::hir::*; +use std::cmp::Ordering::{self, Equal}; +use std::cmp::PartialOrd; +use std::hash::{Hash, Hasher}; +use std::mem; +use std::ops::Deref; +use std::rc::Rc; +use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy}; +use syntax::ptr::P; + +#[derive(Debug, Copy, Clone)] +pub enum FloatWidth { + F32, + F64, + Any, +} + +impl From<FloatTy> for FloatWidth { + fn from(ty: FloatTy) -> FloatWidth { + match ty { + FloatTy::F32 => FloatWidth::F32, + FloatTy::F64 => FloatWidth::F64, + } + } +} + +/// A `LitKind`-like enum to fold constant `Expr`s into. +#[derive(Debug, Clone)] +pub enum Constant { + /// a String "abc" + Str(String, StrStyle), + /// a Binary String b"abc" + Binary(Rc<Vec<u8>>), + /// a single char 'a' + Char(char), + /// an integer, third argument is whether the value is negated + Int(ConstInt), + /// a float with given type + Float(String, FloatWidth), + /// true or false + Bool(bool), + /// an array of constants + Vec(Vec<Constant>), + /// also an array, but with only one constant, repeated N times + Repeat(Box<Constant>, usize), + /// a tuple of constants + Tuple(Vec<Constant>), +} + +impl Constant { + /// convert to u64 if possible + /// + /// # panics + /// + /// if the constant could not be converted to u64 losslessly + fn as_u64(&self) -> u64 { + if let Constant::Int(val) = *self { + val.to_u64().expect("negative constant can't be casted to u64") + } else { + panic!("Could not convert a {:?} to u64", self); + } + } + + /// convert this constant to a f64, if possible + #[allow(cast_precision_loss, cast_possible_wrap)] + pub fn as_float(&self) -> Option<f64> { + match *self { + Constant::Float(ref s, _) => s.parse().ok(), + Constant::Int(i) if i.is_negative() => Some(i.to_u64_unchecked() as i64 as f64), + Constant::Int(i) => Some(i.to_u64_unchecked() as f64), + _ => None, + } + } +} + +impl PartialEq for Constant { + fn eq(&self, other: &Constant) -> bool { + match (self, other) { + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, + (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, + (&Constant::Char(l), &Constant::Char(r)) => l == r, + (&Constant::Int(l), &Constant::Int(r)) => { + l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked() + } + (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { + // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have + // `Fw32 == Fw64` so don’t compare them + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(l), Ok(r)) => l.eq(&r), + _ => false, + } + } + (&Constant::Bool(l), &Constant::Bool(r)) => l == r, + (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, + _ => false, //TODO: Are there inter-type equalities? + } + } +} + +impl Hash for Constant { + fn hash<H>(&self, state: &mut H) + where H: Hasher + { + match *self { + Constant::Str(ref s, ref k) => { + s.hash(state); + k.hash(state); + } + Constant::Binary(ref b) => { + b.hash(state); + } + Constant::Char(c) => { + c.hash(state); + } + Constant::Int(i) => { + i.to_u64_unchecked().hash(state); + i.is_negative().hash(state); + } + Constant::Float(ref f, _) => { + // don’t use the width here because of PartialEq implementation + if let Ok(f) = f.parse::<f64>() { + unsafe { mem::transmute::<f64, u64>(f) }.hash(state); + } + } + Constant::Bool(b) => { + b.hash(state); + } + Constant::Vec(ref v) | + Constant::Tuple(ref v) => { + v.hash(state); + } + Constant::Repeat(ref c, l) => { + c.hash(state); + l.hash(state); + } + } + } +} + +impl PartialOrd for Constant { + fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { + match (self, other) { + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { + if l_sty == r_sty { + Some(ls.cmp(rs)) + } else { + None + } + } + (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), + (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), + (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { + match (ls.parse::<f64>(), rs.parse::<f64>()) { + (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), + _ => None, + } + } + (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | + (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { + match lv.partial_cmp(rv) { + Some(Equal) => Some(ls.cmp(rs)), + x => x, + } + } + _ => None, //TODO: Are there any useful inter-type orderings? + } + } +} + +/// parse a `LitKind` to a `Constant` +#[allow(cast_possible_wrap)] +pub fn lit_to_constant(lit: &LitKind) -> Constant { + match *lit { + LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), + LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), + LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), + LitKind::Char(c) => Constant::Char(c), + LitKind::Int(value, LitIntType::Unsuffixed) => Constant::Int(ConstInt::Infer(value)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U8)) => Constant::Int(ConstInt::U8(value as u8)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => { + Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))) + } + LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), + LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), + LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), + LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), + LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => { + Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))) + } + LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), + LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), + LitKind::Bool(b) => Constant::Bool(b), + } +} + +fn constant_not(o: Constant) -> Option<Constant> { + use self::Constant::*; + match o { + Bool(b) => Some(Bool(!b)), + Int(value) => (!value).ok().map(Int), + _ => None, + } +} + +fn constant_negate(o: Constant) -> Option<Constant> { + use self::Constant::*; + match o { + Int(value) => (-value).ok().map(Int), + Float(is, ty) => Some(Float(neg_float_str(is), ty)), + _ => None, + } +} + +fn neg_float_str(s: String) -> String { + if s.starts_with('-') { + s[1..].to_owned() + } else { + format!("-{}", s) + } +} + +pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { + let mut cx = ConstEvalLateContext { + lcx: Some(lcx), + needed_resolution: false, + }; + cx.expr(e).map(|cst| (cst, cx.needed_resolution)) +} + +pub fn constant_simple(e: &Expr) -> Option<Constant> { + let mut cx = ConstEvalLateContext { + lcx: None, + needed_resolution: false, + }; + cx.expr(e) +} + +struct ConstEvalLateContext<'c, 'cc: 'c> { + lcx: Option<&'c LateContext<'c, 'cc>>, + needed_resolution: bool, +} + +impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { + /// simple constant folding: Insert an expression, get a constant or none. + fn expr(&mut self, e: &Expr) -> Option<Constant> { + match e.node { + ExprPath(_, _) => self.fetch_path(e), + ExprBlock(ref block) => self.block(block), + ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), + ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), + ExprVec(ref vec) => self.multi(vec).map(Constant::Vec), + ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), + ExprRepeat(ref value, ref number) => { + self.binop_apply(value, number, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) + } + ExprUnary(op, ref operand) => { + self.expr(operand).and_then(|o| { + match op { + UnNot => constant_not(o), + UnNeg => constant_negate(o), + UnDeref => Some(o), + } + }) + } + ExprBinary(op, ref left, ref right) => self.binop(op, left, right), + // TODO: add other expressions + _ => None, + } + } + + /// create `Some(Vec![..])` of all constants, unless there is any + /// non-constant part + fn multi<E: Deref<Target = Expr> + Sized>(&mut self, vec: &[E]) -> Option<Vec<Constant>> { + vec.iter() + .map(|elem| self.expr(elem)) + .collect::<Option<_>>() + } + + /// lookup a possibly constant expression from a ExprPath + fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { + if let Some(lcx) = self.lcx { + let mut maybe_id = None; + if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) { + maybe_id = Some(id); + } + // separate if lets to avoid double borrowing the def_map + if let Some(id) = maybe_id { + if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) { + let ret = self.expr(const_expr); + if ret.is_some() { + self.needed_resolution = true; + } + return ret; + } + } + } + None + } + + /// A block can only yield a constant if it only has one constant expression + fn block(&mut self, block: &Block) -> Option<Constant> { + if block.stmts.is_empty() { + block.expr.as_ref().and_then(|ref b| self.expr(b)) + } else { + None + } + } + + fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) -> Option<Constant> { + if let Some(Constant::Bool(b)) = self.expr(cond) { + if b { + self.block(then) + } else { + otherwise.as_ref().and_then(|expr| self.expr(expr)) + } + } else { + None + } + } + + fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { + let l = if let Some(l) = self.expr(left) { + l + } else { + return None; + }; + let r = self.expr(right); + match (op.node, l, r) { + (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), + (BiSub, Constant::Int(l), Some(Constant::Int(r))) => (l - r).ok().map(Constant::Int), + (BiMul, Constant::Int(l), Some(Constant::Int(r))) => (l * r).ok().map(Constant::Int), + (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int), + (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), + (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), + (BiAnd, Constant::Bool(true), Some(r)) => Some(r), + (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), + (BiOr, Constant::Bool(false), Some(r)) => Some(r), + (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), + (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), + (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), + (BiBitAnd, Constant::Int(l), Some(Constant::Int(r))) => (l & r).ok().map(Constant::Int), + (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), + (BiBitOr, Constant::Int(l), Some(Constant::Int(r))) => (l | r).ok().map(Constant::Int), + (BiShl, Constant::Int(l), Some(Constant::Int(r))) => (l << r).ok().map(Constant::Int), + (BiShr, Constant::Int(l), Some(Constant::Int(r))) => (l >> r).ok().map(Constant::Int), + (BiEq, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l == r)), + (BiNe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l != r)), + (BiLt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l < r)), + (BiLe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l <= r)), + (BiGe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l >= r)), + (BiGt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l > r)), + _ => None, + } + } + + + fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> + where F: Fn(Constant, Constant) -> Option<Constant> + { + if let (Some(lc), Some(rc)) = (self.expr(left), self.expr(right)) { + op(lc, rc) + } else { + None + } + } +} diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs new file mode 100644 index 00000000000..4344ba461dd --- /dev/null +++ b/clippy_lints/src/copies.rs @@ -0,0 +1,271 @@ +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use syntax::parse::token::InternedString; +use syntax::util::small_vector::SmallVector; +use utils::{SpanlessEq, SpanlessHash}; +use utils::{get_parent_expr, in_macro, span_note_and_lint}; + +/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is +/// `Warn` by default. +/// +/// **Why is this bad?** This is probably a copy & paste error. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** `if a == b { .. } else if a == b { .. }` +declare_lint! { + pub IFS_SAME_COND, + Warn, + "consecutive `ifs` with the same condition" +} + +/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the +/// *else* part. This lint is `Warn` by default. +/// +/// **Why is this bad?** This is probably a copy & paste error. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** `if .. { 42 } else { 42 }` +declare_lint! { + pub IF_SAME_THEN_ELSE, + Warn, + "if with the same *then* and *else* blocks" +} + +/// **What it does:** This lint checks for `match` with identical arm bodies. +/// +/// **Why is this bad?** This is probably a copy & paste error. If arm bodies are the same on +/// purpose, you can factor them +/// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust,ignore +/// match foo { +/// Bar => bar(), +/// Quz => quz(), +/// Baz => bar(), // <= oops +/// } +/// ``` +declare_lint! { + pub MATCH_SAME_ARMS, + Warn, + "`match` with identical arm bodies" +} + +#[derive(Copy, Clone, Debug)] +pub struct CopyAndPaste; + +impl LintPass for CopyAndPaste { + fn get_lints(&self) -> LintArray { + lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS] + } +} + +impl LateLintPass for CopyAndPaste { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if !in_macro(cx, expr.span) { + // skip ifs directly in else, it will be checked in the parent if + if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { + if else_expr.id == expr.id { + return; + } + } + + let (conds, blocks) = if_sequence(expr); + lint_same_then_else(cx, blocks.as_slice()); + lint_same_cond(cx, conds.as_slice()); + lint_match_arms(cx, expr); + } + } +} + +/// Implementation of `IF_SAME_THEN_ELSE`. +fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; + + if let Some((i, j)) = search_same(blocks, hash, eq) { + span_note_and_lint(cx, + IF_SAME_THEN_ELSE, + j.span, + "this `if` has identical blocks", + i.span, + "same as this"); + } +} + +/// Implementation of `IFS_SAME_COND`. +fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { + let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_expr(expr); + h.finish() + }; + + let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; + + if let Some((i, j)) = search_same(conds, hash, eq) { + span_note_and_lint(cx, + IFS_SAME_COND, + j.span, + "this `if` has the same condition as a previous if", + i.span, + "same as this"); + } +} + +/// Implementation if `MATCH_SAME_ARMS`. +fn lint_match_arms(cx: &LateContext, expr: &Expr) { + let hash = |arm: &Arm| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_expr(&arm.body); + h.finish() + }; + + let eq = |lhs: &Arm, rhs: &Arm| -> bool { + // Arms with a guard are ignored, those can’t always be merged together + lhs.guard.is_none() && rhs.guard.is_none() && + SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && + // all patterns should have the same bindings + bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) + }; + + if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { + if let Some((i, j)) = search_same(arms, hash, eq) { + span_note_and_lint(cx, + MATCH_SAME_ARMS, + j.body.span, + "this `match` has identical arm bodies", + i.body.span, + "same as this"); + } + } +} + +/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`. +/// Eg. would return `([a, b], [c, d, e])` for the expression +/// `if a { c } else if b { d } else { e }`. +fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { + let mut conds = SmallVector::zero(); + let mut blocks = SmallVector::zero(); + + while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node { + conds.push(&**cond); + blocks.push(&**then_block); + + if let Some(ref else_expr) = *else_expr { + expr = else_expr; + } else { + break; + } + } + + // final `else {..}` + if !blocks.is_empty() { + if let ExprBlock(ref block) = expr.node { + blocks.push(&**block); + } + } + + (conds, blocks) +} + +/// Return the list of bindings in a pattern. +fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { + fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { + match pat.node { + PatKind::Box(ref pat) | + PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), + PatKind::TupleStruct(_, Some(ref pats)) => { + for pat in pats { + bindings_impl(cx, pat, map); + } + } + PatKind::Ident(_, ref ident, ref as_pat) => { + if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { + v.insert(cx.tcx.pat_ty(pat)); + } + if let Some(ref as_pat) = *as_pat { + bindings_impl(cx, as_pat, map); + } + } + PatKind::Struct(_, ref fields, _) => { + for pat in fields { + bindings_impl(cx, &pat.node.pat, map); + } + } + PatKind::Tup(ref fields) => { + for pat in fields { + bindings_impl(cx, pat, map); + } + } + PatKind::Vec(ref lhs, ref mid, ref rhs) => { + for pat in lhs { + bindings_impl(cx, pat, map); + } + if let Some(ref mid) = *mid { + bindings_impl(cx, mid, map); + } + for pat in rhs { + bindings_impl(cx, pat, map); + } + } + PatKind::TupleStruct(..) | + PatKind::Lit(..) | + PatKind::QPath(..) | + PatKind::Range(..) | + PatKind::Wild | + PatKind::Path(..) => (), + } + } + + let mut result = HashMap::new(); + bindings_impl(cx, pat, &mut result); + result +} + +fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> + where Hash: Fn(&T) -> u64, + Eq: Fn(&T, &T) -> bool +{ + // common cases + if exprs.len() < 2 { + return None; + } else if exprs.len() == 2 { + return if eq(&exprs[0], &exprs[1]) { + Some((&exprs[0], &exprs[1])) + } else { + None + }; + } + + let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len()); + + for expr in exprs { + match map.entry(hash(expr)) { + Entry::Occupied(o) => { + for o in o.get() { + if eq(o, expr) { + return Some((o, expr)); + } + } + } + Entry::Vacant(v) => { + v.insert(vec![expr]); + } + } + } + + None +} diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs new file mode 100644 index 00000000000..8ae0d2c97c5 --- /dev/null +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -0,0 +1,187 @@ +//! calculate cyclomatic complexity and warn about overly complex functions + +use rustc::cfg::CFG; +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr}; +use syntax::ast::Attribute; +use syntax::attr; +use syntax::codemap::Span; + +use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; + +/// **What it does:** This lint checks for methods with high cyclomatic complexity +/// +/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better. +/// +/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity +/// +/// **Example:** No. You'll see it when you get the warning. +declare_lint! { + pub CYCLOMATIC_COMPLEXITY, Warn, + "finds functions that should be split up into multiple functions" +} + +pub struct CyclomaticComplexity { + limit: LimitStack, +} + +impl CyclomaticComplexity { + pub fn new(limit: u64) -> Self { + CyclomaticComplexity { limit: LimitStack::new(limit) } + } +} + +impl LintPass for CyclomaticComplexity { + fn get_lints(&self) -> LintArray { + lint_array!(CYCLOMATIC_COMPLEXITY) + } +} + +impl CyclomaticComplexity { + fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) { + if in_macro(cx, span) { + return; + } + + let cfg = CFG::new(cx.tcx, block); + let n = cfg.graph.len_nodes() as u64; + let e = cfg.graph.len_edges() as u64; + if e + 2 < n { + // the function has unreachable code, other lints should catch this + return; + } + let cc = e + 2 - n; + let mut helper = CCHelper { + match_arms: 0, + divergence: 0, + short_circuits: 0, + returns: 0, + tcx: &cx.tcx, + }; + helper.visit_block(block); + let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; + let ret_ty = cx.tcx.node_id_to_type(block.id); + let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { + returns + } else { + returns / 2 + }; + + if cc + divergence < match_arms + short_circuits { + report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span); + } else { + let mut rust_cc = cc + divergence - match_arms - short_circuits; + // prevent degenerate cases where unreachable code contains `return` statements + if rust_cc >= ret_adjust { + rust_cc -= ret_adjust; + } + if rust_cc > self.limit.limit() { + span_help_and_lint(cx, + CYCLOMATIC_COMPLEXITY, + span, + &format!("the function has a cyclomatic complexity of {}", rust_cc), + "you could split it up into multiple smaller functions"); + } + } + } +} + +impl LateLintPass for CyclomaticComplexity { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemFn(_, _, _, _, _, ref block) = item.node { + if !attr::contains_name(&item.attrs, "test") { + self.check(cx, block, item.span); + } + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + if let ImplItemKind::Method(_, ref block) = item.node { + self.check(cx, block, item.span); + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + if let MethodTraitItem(_, Some(ref block)) = item.node { + self.check(cx, block, item.span); + } + } + + fn enter_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { + self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + } + fn exit_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { + self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + } +} + +struct CCHelper<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + match_arms: u64, + divergence: u64, + returns: u64, + short_circuits: u64, // && and || + tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>, +} + +impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> { + fn visit_expr(&mut self, e: &'a Expr) { + match e.node { + ExprMatch(_, ref arms, _) => { + walk_expr(self, e); + let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); + if arms_n > 1 { + self.match_arms += arms_n - 2; + } + } + ExprCall(ref callee, _) => { + walk_expr(self, e); + let ty = self.tcx.node_id_to_type(callee.id); + match ty.sty { + ty::TyFnDef(_, _, ty) | + ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { + self.divergence += 1; + } + _ => (), + } + } + ExprClosure(..) => (), + ExprBinary(op, _, _) => { + walk_expr(self, e); + match op.node { + BiAnd | BiOr => self.short_circuits += 1, + _ => (), + } + } + ExprRet(_) => self.returns += 1, + _ => walk_expr(self, e), + } + } +} + +#[cfg(feature="debugging")] +fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { + span_bug!(span, + "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ + div = {}, shorts = {}, returns = {}. Please file a bug report.", + cc, + narms, + div, + shorts, + returns); +} +#[cfg(not(feature="debugging"))] +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { + if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { + cx.sess().span_note_without_error(span, + &format!("Clippy encountered a bug calculating cyclomatic complexity \ + (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ + = {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.", + cc, + narms, + div, + shorts, + returns)); + } +} diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs new file mode 100644 index 00000000000..abdb6297b9e --- /dev/null +++ b/clippy_lints/src/deprecated_lints.rs @@ -0,0 +1,44 @@ +macro_rules! declare_deprecated_lint { + (pub $name: ident, $_reason: expr) => { + declare_lint!(pub $name, Allow, "deprecated lint") + } +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `Vec::as_slice`, which was unstable with good +/// stable alternatives. `Vec::as_slice` has now been stabilized. +declare_deprecated_lint! { + pub UNSTABLE_AS_SLICE, + "`Vec::as_slice` has been stabilized in 1.7" +} + + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `Vec::as_mut_slice`, which was unstable with good +/// stable alternatives. `Vec::as_mut_slice` has now been stabilized. +declare_deprecated_lint! { + pub UNSTABLE_AS_MUT_SLICE, + "`Vec::as_mut_slice` has been stabilized in 1.7" +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `.to_string()` method calls on values +/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be +/// specialized to be as efficient as `to_owned`. +declare_deprecated_lint! { + pub STR_TO_STRING, + "using `str::to_string` is common even today and specialization will likely happen soon" +} + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `.to_string()` method calls on values +/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be +/// specialized to be as efficient as `clone`. +declare_deprecated_lint! { + pub STRING_TO_STRING, + "using `string::to_string` is common even today and specialization will likely happen soon" +} diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs new file mode 100644 index 00000000000..f08522953aa --- /dev/null +++ b/clippy_lints/src/derive.rs @@ -0,0 +1,180 @@ +use rustc::lint::*; +use rustc::ty::subst::Subst; +use rustc::ty::TypeVariants; +use rustc::ty; +use rustc::hir::*; +use syntax::ast::{Attribute, MetaItemKind}; +use syntax::codemap::Span; +use utils::paths; +use utils::{match_path, span_lint_and_then}; + +/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` +/// explicitly. +/// +/// **Why is this bad?** The implementation of these traits must agree (for example for use with +/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation with +/// an explicitly defined `PartialEq`. In particular, the following must hold for any type: +/// +/// ```rust +/// k1 == k2 ⇒ hash(k1) == hash(k2) +/// ``` +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// #[derive(Hash)] +/// struct Foo; +/// +/// impl PartialEq for Foo { +/// .. +/// } +/// ``` +declare_lint! { + pub DERIVE_HASH_XOR_EQ, + Warn, + "deriving `Hash` but implementing `PartialEq` explicitly" +} + +/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types. +/// +/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour +/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone` +/// implementation that does nothing more than copy the object, which is what +/// `#[derive(Copy, Clone)]` gets you. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// #[derive(Copy)] +/// struct Foo; +/// +/// impl Clone for Foo { +/// .. +/// } +/// ``` +declare_lint! { + pub EXPL_IMPL_CLONE_ON_COPY, + Warn, + "implementing `Clone` explicitly on `Copy` types" +} + +pub struct Derive; + +impl LintPass for Derive { + fn get_lints(&self) -> LintArray { + lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ) + } +} + +impl LateLintPass for Derive { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if_let_chain! {[ + let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node + ], { + let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; + let is_automatically_derived = item.attrs.iter().any(is_automatically_derived); + + check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); + + if !is_automatically_derived { + check_copy_clone(cx, item, trait_ref, ty); + } + }} + } +} + +/// Implementation of the `DERIVE_HASH_XOR_EQ` lint. +fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { + if_let_chain! {[ + match_path(&trait_ref.path, &paths::HASH), + let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() + ], { + let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); + + // Look for the PartialEq implementations for `ty` + peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| { + let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); + + if peq_is_automatically_derived == hash_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialEq<Foo> for Foo` + if trait_ref.input_types()[0] == ty { + let mess = if peq_is_automatically_derived { + "you are implementing `Hash` explicitly but have derived `PartialEq`" + } else { + "you are deriving `Hash` but have implemented `PartialEq` explicitly" + }; + + span_lint_and_then( + cx, DERIVE_HASH_XOR_EQ, span, + mess, + |db| { + if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { + db.span_note( + cx.tcx.map.span(node_id), + "`PartialEq` implemented here" + ); + } + }); + } + }); + }} +} + +/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { + if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); + let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs); + + if subst_ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, item.span) { + return; // ty is not Copy + } + + // Some types are not Clone by default but could be cloned `by hand` if necessary + match ty.sty { + TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => { + for variant in &def.variants { + for field in &variant.fields { + match field.ty(cx.tcx, substs).sty { + TypeVariants::TyArray(_, size) if size > 32 => { + return; + } + TypeVariants::TyFnPtr(..) => { + return; + } + TypeVariants::TyTuple(ref tys) if tys.len() > 12 => { + return; + } + _ => (), + } + } + } + } + _ => (), + } + + span_lint_and_then(cx, + EXPL_IMPL_CLONE_ON_COPY, + item.span, + "you are implementing `Clone` explicitly on a `Copy` type", + |db| { + db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); + }); + } +} + +/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have. +fn is_automatically_derived(attr: &Attribute) -> bool { + if let MetaItemKind::Word(ref word) = attr.node.value.node { + word == &"automatically_derived" + } else { + false + } +} diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs new file mode 100644 index 00000000000..cf32c1731fa --- /dev/null +++ b/clippy_lints/src/doc.rs @@ -0,0 +1,235 @@ +use rustc::lint::*; +use syntax::ast; +use syntax::codemap::{Span, BytePos}; +use utils::span_lint; + +/// **What it does:** This lint checks for the presence of `_`, `::` or camel-case words outside +/// ticks in documentation. +/// +/// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and camel-case probably +/// indicates some code which should be included between ticks. `_` can also be used for empasis in +/// markdown, this lint tries to consider that. +/// +/// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks for is limited. +/// +/// **Examples:** +/// ```rust +/// /// Do something with the foo_bar parameter. See also that::other::module::foo. +/// // ^ `foo_bar` and `that::other::module::foo` should be ticked. +/// fn doit(foo_bar) { .. } +/// ``` +declare_lint! { + pub DOC_MARKDOWN, Warn, + "checks for the presence of `_`, `::` or camel-case outside ticks in documentation" +} + +#[derive(Clone)] +pub struct Doc { + valid_idents: Vec<String>, +} + +impl Doc { + pub fn new(valid_idents: Vec<String>) -> Self { + Doc { valid_idents: valid_idents } + } +} + +impl LintPass for Doc { + fn get_lints(&self) -> LintArray { + lint_array![DOC_MARKDOWN] + } +} + +impl EarlyLintPass for Doc { + fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { + check_attrs(cx, &self.valid_idents, &krate.attrs); + } + + fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { + check_attrs(cx, &self.valid_idents, &item.attrs); + } +} + +pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { + let mut in_multiline = false; + for attr in attrs { + if attr.node.is_sugared_doc { + if let ast::MetaItemKind::NameValue(_, ref doc) = attr.node.value.node { + if let ast::LitKind::Str(ref doc, _) = doc.node { + // doc comments start with `///` or `//!` + let real_doc = &doc[3..]; + let mut span = attr.span; + span.lo = span.lo + BytePos(3); + + // check for multiline code blocks + if real_doc.trim_left().starts_with("```") { + in_multiline = !in_multiline; + } + if !in_multiline { + check_doc(cx, valid_idents, real_doc, span); + } + } + } + } + } +} + +macro_rules! jump_to { + // Get the next character’s first byte UTF-8 friendlyly. + (@next_char, $chars: expr, $len: expr) => {{ + if let Some(&(pos, _)) = $chars.peek() { + pos + } else { + $len + } + }}; + + // Jump to the next `$c`. If no such character is found, give up. + ($chars: expr, $c: expr, $len: expr) => {{ + if $chars.find(|&(_, c)| c == $c).is_some() { + jump_to!(@next_char, $chars, $len) + } + else { + return; + } + }}; +} + +#[allow(while_let_loop)] // #362 +pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) { + // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. + // There really is no markdown specification that would disambiguate this properly. This is + // what GitHub and Rustdoc do: + // + // foo_bar test_quz → foo_bar test_quz + // foo_bar_baz → foo_bar_baz (note that the “official” spec says this should be emphasized) + // _foo bar_ test_quz_ → <em>foo bar</em> test_quz_ + // \_foo bar\_ → _foo bar_ + // (_baz_) → (<em>baz</em>) + // foo _ bar _ baz → foo _ bar _ baz + + /// Character that can appear in a word + fn is_word_char(c: char) -> bool { + match c { + t if t.is_alphanumeric() => true, + ':' | '_' => true, + _ => false, + } + } + + #[allow(cast_possible_truncation)] + fn word_span(mut span: Span, begin: usize, end: usize) -> Span { + debug_assert_eq!(end as u32 as usize, end); + debug_assert_eq!(begin as u32 as usize, begin); + span.hi = span.lo + BytePos(end as u32); + span.lo = span.lo + BytePos(begin as u32); + span + } + + let mut new_line = true; + let len = doc.len(); + let mut chars = doc.char_indices().peekable(); + let mut current_word_begin = 0; + loop { + match chars.next() { + Some((_, c)) => { + match c { + '#' if new_line => { // don’t warn on titles + current_word_begin = jump_to!(chars, '\n', len); + } + '`' => { + current_word_begin = jump_to!(chars, '`', len); + } + '[' => { + let end = jump_to!(chars, ']', len); + let link_text = &doc[current_word_begin + 1..end]; + let word_span = word_span(span, current_word_begin + 1, end + 1); + + match chars.peek() { + Some(&(_, c)) => { + // Trying to parse a link. Let’s ignore the link. + + // FIXME: how does markdown handles such link? + // https://en.wikipedia.org/w/index.php?title=) + match c { + '(' => { // inline link + current_word_begin = jump_to!(chars, ')', len); + check_doc(cx, valid_idents, link_text, word_span); + } + '[' => { // reference link + current_word_begin = jump_to!(chars, ']', len); + check_doc(cx, valid_idents, link_text, word_span); + } + ':' => { // reference link + current_word_begin = jump_to!(chars, '\n', len); + } + _ => { // automatic reference link + current_word_begin = jump_to!(@next_char, chars, len); + check_doc(cx, valid_idents, link_text, word_span); + } + } + } + None => return, + } + } + // anything that’s neither alphanumeric nor '_' is not part of an ident anyway + c if !c.is_alphanumeric() && c != '_' => { + current_word_begin = jump_to!(@next_char, chars, len); + } + _ => { + let end = match chars.find(|&(_, c)| !is_word_char(c)) { + Some((end, _)) => end, + None => len, + }; + let word_span = word_span(span, current_word_begin, end); + check_word(cx, valid_idents, &doc[current_word_begin..end], word_span); + current_word_begin = jump_to!(@next_char, chars, len); + } + } + + new_line = c == '\n' || (new_line && c.is_whitespace()); + } + None => break, + } + } +} + +fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span) { + /// Checks if a string a camel-case, ie. contains at least two uppercase letter (`Clippy` is + /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok). + fn is_camel_case(s: &str) -> bool { + if s.starts_with(|c: char| c.is_digit(10)) { + return false; + } + + let s = if s.ends_with('s') { + &s[..s.len() - 1] + } else { + s + }; + + s.chars().all(char::is_alphanumeric) && + s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && + s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 + } + + fn has_underscore(s: &str) -> bool { + s != "_" && !s.contains("\\_") && s.contains('_') + } + + // Trim punctuation as in `some comment (see foo::bar).` + // ^^ + // Or even as in `_foo bar_` which is emphasized. + let word = word.trim_matches(|c: char| !c.is_alphanumeric()); + + if valid_idents.iter().any(|i| i == word) { + return; + } + + if has_underscore(word) || word.contains("::") || is_camel_case(word) { + span_lint(cx, + DOC_MARKDOWN, + span, + &format!("you should put `{}` between ticks in the documentation", word)); + } +} diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_ref.rs new file mode 100644 index 00000000000..69156f15f31 --- /dev/null +++ b/clippy_lints/src/drop_ref.rs @@ -0,0 +1,61 @@ +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use syntax::codemap::Span; +use utils::{match_def_path, paths, span_note_and_lint}; + +/// **What it does:** This lint checks for calls to `std::mem::drop` with a reference instead of an owned value. +/// +/// **Why is this bad?** Calling `drop` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` method (from the `Drop` trait implementation) on the underlying referenced value, which is likely what was intended. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let mut lock_guard = mutex.lock(); +/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked +/// operation_that_requires_mutex_to_be_unlocked(); +/// ``` +declare_lint! { + pub DROP_REF, Warn, + "call to `std::mem::drop` with a reference instead of an owned value, \ + which will not call the `Drop::drop` method on the underlying value" +} + +#[allow(missing_copy_implementations)] +pub struct DropRefPass; + +impl LintPass for DropRefPass { + fn get_lints(&self) -> LintArray { + lint_array!(DROP_REF) + } +} + +impl LateLintPass for DropRefPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprCall(ref path, ref args) = expr.node { + if let ExprPath(None, _) = path.node { + let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + if match_def_path(cx, def_id, &paths::DROP) { + if args.len() != 1 { + return; + } + check_drop_arg(cx, expr.span, &*args[0]); + } + } + } + } +} + +fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) { + let arg_ty = cx.tcx.expr_ty(arg); + if let ty::TyRef(..) = arg_ty.sty { + span_note_and_lint(cx, + DROP_REF, + call_span, + "call to `std::mem::drop` with a reference argument. \ + Dropping a reference does nothing", + arg.span, + &format!("argument has type {}", arg_ty.sty)); + } +} diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs new file mode 100644 index 00000000000..d63d8c67c5d --- /dev/null +++ b/clippy_lints/src/entry.rs @@ -0,0 +1,148 @@ +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_expr, walk_block}; +use rustc::lint::*; +use syntax::codemap::Span; +use utils::SpanlessEq; +use utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; + +/// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or +/// `BTreeMap`. +/// +/// **Why is this bad?** Using `entry` is more efficient. +/// +/// **Known problems:** Some false negatives, eg.: +/// ``` +/// let k = &key; +/// if !m.contains_key(k) { m.insert(k.clone(), v); } +/// ``` +/// +/// **Example:** +/// ```rust +/// if !m.contains_key(&k) { m.insert(k, v) } +/// ``` +/// can be rewritten as: +/// ```rust +/// m.entry(k).or_insert(v); +/// ``` +declare_lint! { + pub MAP_ENTRY, + Warn, + "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" +} + +#[derive(Copy,Clone)] +pub struct HashMapLint; + +impl LintPass for HashMapLint { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_ENTRY) + } +} + +impl LateLintPass for HashMapLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprIf(ref check, ref then_block, ref else_block) = expr.node { + if let ExprUnary(UnOp::UnNot, ref check) = check.node { + if let Some((ty, map, key)) = check_cond(cx, check) { + // in case of `if !m.contains_key(&k) { m.insert(k, v); }` + // we can give a better error message + let sole_expr = else_block.is_none() && + ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); + + let mut visitor = InsertVisitor { + cx: cx, + span: expr.span, + ty: ty, + map: map, + key: key, + sole_expr: sole_expr, + }; + + walk_block(&mut visitor, then_block); + } + } else if let Some(ref else_block) = *else_block { + if let Some((ty, map, key)) = check_cond(cx, check) { + let mut visitor = InsertVisitor { + cx: cx, + span: expr.span, + ty: ty, + map: map, + key: key, + sole_expr: false, + }; + + walk_expr(&mut visitor, else_block); + } + } + } + } +} + +fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> Option<(&'static str, &'b Expr, &'b Expr)> { + if_let_chain! {[ + let ExprMethodCall(ref name, _, ref params) = check.node, + params.len() >= 2, + name.node.as_str() == "contains_key", + let ExprAddrOf(_, ref key) = params[1].node + ], { + let map = ¶ms[0]; + let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); + + return if match_type(cx, obj_ty, &paths::BTREEMAP) { + Some(("BTreeMap", map, key)) + } + else if match_type(cx, obj_ty, &paths::HASHMAP) { + Some(("HashMap", map, key)) + } + else { + None + }; + }} + + None +} + +struct InsertVisitor<'a, 'tcx: 'a, 'b> { + cx: &'a LateContext<'a, 'tcx>, + span: Span, + ty: &'static str, + map: &'b Expr, + key: &'b Expr, + sole_expr: bool, +} + +impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> { + fn visit_expr(&mut self, expr: &'v Expr) { + if_let_chain! {[ + let ExprMethodCall(ref name, _, ref params) = expr.node, + params.len() == 3, + name.node.as_str() == "insert", + get_item_name(self.cx, self.map) == get_item_name(self.cx, &*params[0]), + SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) + ], { + + span_lint_and_then(self.cx, MAP_ENTRY, self.span, + &format!("usage of `contains_key` followed by `insert` on `{}`", self.ty), |db| { + if self.sole_expr { + let help = format!("{}.entry({}).or_insert({})", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, ".."), + snippet(self.cx, params[2].span, "..")); + + db.span_suggestion(self.span, "Consider using", help); + } + else { + let help = format!("Consider using `{}.entry({})`", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, "..")); + + db.span_note(self.span, &help); + } + }); + }} + + if !self.sole_expr { + walk_expr(self, expr); + } + } +} diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs new file mode 100644 index 00000000000..39c31864f39 --- /dev/null +++ b/clippy_lints/src/enum_clike.rs @@ -0,0 +1,52 @@ +//! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` + +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc_const_math::*; +use rustc::hir::*; +use utils::span_lint; + +/// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. +/// +/// **Why is this bad?** This will truncate the variant value on 32bit architectures, but works fine on 64 bit. +/// +/// **Known problems:** None +/// +/// **Example:** `#[repr(usize)] enum NonPortable { X = 0x1_0000_0000, Y = 0 }` +declare_lint! { + pub ENUM_CLIKE_UNPORTABLE_VARIANT, Warn, + "finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" +} + +pub struct EnumClikeUnportableVariant; + +impl LintPass for EnumClikeUnportableVariant { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) + } +} + +impl LateLintPass for EnumClikeUnportableVariant { + #[allow(cast_possible_truncation, cast_sign_loss)] + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemEnum(ref def, _) = item.node { + for var in &def.variants { + let variant = &var.node; + if let Some(ref disr) = variant.disr_expr { + use rustc_const_eval::*; + let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) { + Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, + Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, + _ => false, + }; + if bad { + span_lint(cx, + ENUM_CLIKE_UNPORTABLE_VARIANT, + var.span, + "Clike enum variant discriminant is not portable to 32-bit targets"); + } + } + } + } + } +} diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs new file mode 100644 index 00000000000..37a89069d19 --- /dev/null +++ b/clippy_lints/src/enum_glob_use.rs @@ -0,0 +1,65 @@ +//! lint on `use`ing all variants of an enum + +use rustc::hir::*; +use rustc::hir::def::Def; +use rustc::hir::map::Node::NodeItem; +use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; +use rustc::middle::cstore::DefLike; +use syntax::ast::NodeId; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** Warns when `use`ing all variants of an enum +/// +/// **Why is this bad?** It is usually better style to use the prefixed name of an enum variant, rather than importing variants +/// +/// **Known problems:** Old-style enums that prefix the variants are still around +/// +/// **Example:** `use std::cmp::Ordering::*;` +declare_lint! { pub ENUM_GLOB_USE, Allow, + "finds use items that import all variants of an enum" } + +pub struct EnumGlobUse; + +impl LintPass for EnumGlobUse { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_GLOB_USE) + } +} + +impl LateLintPass for EnumGlobUse { + fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) { + // only check top level `use` statements + for item in &m.item_ids { + self.lint_item(cx, cx.krate.item(item.id)); + } + } +} + +impl EnumGlobUse { + fn lint_item(&self, cx: &LateContext, item: &Item) { + if item.vis == Visibility::Public { + return; // re-exports are fine + } + if let ItemUse(ref item_use) = item.node { + if let ViewPath_::ViewPathGlob(_) = item_use.node { + if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) { + if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { + if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { + if let ItemEnum(..) = it.node { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } + } + } else { + let child = cx.sess().cstore.item_children(def.def_id()); + if let Some(child) = child.first() { + if let DefLike::DlDef(Def::Variant(..)) = child.def { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + } + } + } + } + } + } + } +} diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs new file mode 100644 index 00000000000..67a8495e155 --- /dev/null +++ b/clippy_lints/src/enum_variants.rs @@ -0,0 +1,104 @@ +//! lint on enum variants that are prefixed or suffixed by the same characters + +use rustc::lint::*; +use syntax::ast::*; +use syntax::parse::token::InternedString; +use utils::span_help_and_lint; +use utils::{camel_case_from, camel_case_until}; + +/// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters +/// +/// **Why is this bad?** Enum variant names should specify their variant, not the enum, too. +/// +/// **Known problems:** None +/// +/// **Example:** enum Cake { BlackForestCake, HummingbirdCake } +declare_lint! { + pub ENUM_VARIANT_NAMES, Warn, + "finds enums where all variants share a prefix/postfix" +} + +pub struct EnumVariantNames; + +impl LintPass for EnumVariantNames { + fn get_lints(&self) -> LintArray { + lint_array!(ENUM_VARIANT_NAMES) + } +} + +fn var2str(var: &Variant) -> InternedString { + var.node.name.name.as_str() +} + +// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 +// fn partial_match(pre: &str, name: &str) -> usize { +// // skip(1) to ensure that the prefix never takes the whole variant name +// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() +// } +// +// fn partial_rmatch(post: &str, name: &str) -> usize { +// // skip(1) to ensure that the postfix never takes the whole variant name +// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() +// } + +fn partial_match(pre: &str, name: &str) -> usize { + let mut name_iter = name.chars(); + let _ = name_iter.next_back(); // make sure the name is never fully matched + pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() +} + +fn partial_rmatch(post: &str, name: &str) -> usize { + let mut name_iter = name.chars(); + let _ = name_iter.next(); // make sure the name is never fully matched + post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() +} + +impl EarlyLintPass for EnumVariantNames { + // FIXME: #600 + #[allow(while_let_on_iterator)] + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemKind::Enum(ref def, _) = item.node { + if def.variants.len() < 2 { + return; + } + let first = var2str(&def.variants[0]); + let mut pre = &first[..camel_case_until(&*first)]; + let mut post = &first[camel_case_from(&*first)..]; + for var in &def.variants { + let name = var2str(var); + + let pre_match = partial_match(pre, &name); + pre = &pre[..pre_match]; + let pre_camel = camel_case_until(pre); + pre = &pre[..pre_camel]; + while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { + if next.is_lowercase() { + let last = pre.len() - last.len_utf8(); + let last_camel = camel_case_until(&pre[..last]); + pre = &pre[..last_camel]; + } else { + break; + } + } + + let post_match = partial_rmatch(post, &name); + let post_end = post.len() - post_match; + post = &post[post_end..]; + let post_camel = camel_case_from(post); + post = &post[post_camel..]; + } + let (what, value) = match (pre.is_empty(), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre), + (true, false) => ("post", post), + }; + span_help_and_lint(cx, + ENUM_VARIANT_NAMES, + item.span, + &format!("All variants have the same {}fix: `{}`", what, value), + &format!("remove the {}fixes and use full paths to \ + the variants instead of glob imports", + what)); + } + } +} diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs new file mode 100644 index 00000000000..fb06639853c --- /dev/null +++ b/clippy_lints/src/eq_op.rs @@ -0,0 +1,60 @@ +use rustc::hir::*; +use rustc::lint::*; +use utils::{SpanlessEq, span_lint}; + +/// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, +/// difference and division binary operators (`==`, `>`, etc., `&&`, `||`, `&`, `|`, `^`, `-` and +/// `/`). +/// +/// **Why is this bad?** This is usually just a typo or a copy and paste error. +/// +/// **Known problems:** False negatives: We had some false positives regarding calls (notably [racer](https://github.com/phildawes/racer) had one instance of `x.pop() && x.pop()`), so we removed matching any function or method calls. We may introduce a whitelist of known pure functions in the future. +/// +/// **Example:** `x + 1 == x + 1` +declare_lint! { + pub EQ_OP, + Warn, + "equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" +} + +#[derive(Copy,Clone)] +pub struct EqOp; + +impl LintPass for EqOp { + fn get_lints(&self) -> LintArray { + lint_array!(EQ_OP) + } +} + +impl LateLintPass for EqOp { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(ref op, ref left, ref right) = e.node { + if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { + span_lint(cx, + EQ_OP, + e.span, + &format!("equal expressions as operands to `{}`", op.node.as_str())); + } + } + } +} + + +fn is_valid_operator(op: &BinOp) -> bool { + match op.node { + BiSub | + BiDiv | + BiEq | + BiLt | + BiLe | + BiGt | + BiGe | + BiNe | + BiAnd | + BiOr | + BiBitXor | + BiBitAnd | + BiBitOr => true, + _ => false, + } +} diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs new file mode 100644 index 00000000000..b5172269a1e --- /dev/null +++ b/clippy_lints/src/escape.rs @@ -0,0 +1,172 @@ +use rustc::hir::*; +use rustc::hir::intravisit as visit; +use rustc::hir::map::Node::{NodeExpr, NodeStmt}; +use rustc::lint::*; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::{cmt, Categorization}; +use rustc::ty::adjustment::AutoAdjustment; +use rustc::ty; +use rustc::util::nodemap::NodeSet; +use syntax::ast::NodeId; +use syntax::codemap::Span; +use utils::span_lint; + +pub struct EscapePass; + +/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. +/// +/// **Why is this bad?** This is an unnecessary allocation, and bad for performance. It is only necessary to allocate if you wish to move the box into something. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ```rust +/// fn main() { +/// let x = Box::new(1); +/// foo(*x); +/// println!("{}", *x); +/// } +/// ``` +declare_lint! { + pub BOXED_LOCAL, Warn, "using `Box<T>` where unnecessary" +} + +fn is_non_trait_box(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyBox(ref inner) => !inner.is_trait(), + _ => false, + } +} + +struct EscapeDelegate<'a, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + set: NodeSet, +} + +impl LintPass for EscapePass { + fn get_lints(&self) -> LintArray { + lint_array!(BOXED_LOCAL) + } +} + +impl LateLintPass for EscapePass { + fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { + let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); + + let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); + let mut v = EscapeDelegate { + tcx: cx.tcx, + set: NodeSet(), + }; + + { + let mut vis = ExprUseVisitor::new(&mut v, &infcx); + vis.walk_fn(decl, body); + } + + for node in v.set { + span_lint(cx, + BOXED_LOCAL, + cx.tcx.map.span(node), + "local variable doesn't need to be boxed here"); + } + } +} + +impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { + fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + if let Move(DirectRefMove) = mode { + // moved out or in. clearly can't be localized + self.set.remove(&lid); + } + } + } + } + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} + fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { + let map = &self.tcx.map; + if map.is_argument(consume_pat.id) { + // Skip closure arguments + if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { + return; + } + if is_non_trait_box(cmt.ty) { + self.set.insert(consume_pat.id); + } + return; + } + if let Categorization::Rvalue(..) = cmt.cat { + if let Some(NodeStmt(st)) = map.find(map.get_parent_node(cmt.id)) { + if let StmtDecl(ref decl, _) = st.node { + if let DeclLocal(ref loc) = decl.node { + if let Some(ref ex) = loc.init { + if let ExprBox(..) = ex.node { + if is_non_trait_box(cmt.ty) { + // let x = box (...) + self.set.insert(consume_pat.id); + } + // TODO Box::new + // TODO vec![] + // TODO "foo".to_owned() and friends + } + } + } + } + } + } + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + // let y = x where x is known + // remove x, insert y + self.set.insert(consume_pat.id); + self.set.remove(&lid); + } + } + + } + fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, + loan_cause: LoanCause) { + + if let Categorization::Local(lid) = cmt.cat { + if self.set.contains(&lid) { + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx + .tables + .borrow() + .adjustments + .get(&borrow_id) { + if LoanCause::AutoRef == loan_cause { + // x.foo() + if adj.autoderefs == 0 { + self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) + } + } else { + span_bug!(cmt.span, "Unknown adjusted AutoRef"); + } + } else if LoanCause::AddrOf == loan_cause { + // &x + if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx + .tables + .borrow() + .adjustments + .get(&self.tcx + .map + .get_parent_node(borrow_id)) { + if adj.autoderefs <= 1 { + // foo(&x) where no extra autoreffing is happening + self.set.remove(&lid); + } + } + + } else if LoanCause::MatchDiscriminant == loan_cause { + self.set.remove(&lid); // `match x` can move + } + // do nothing for matches, etc. These can't escape + } + } + } + fn decl_without_init(&mut self, _: NodeId, _: Span) {} + fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} +} diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs new file mode 100644 index 00000000000..f73b6cfed2d --- /dev/null +++ b/clippy_lints/src/eta_reduction.rs @@ -0,0 +1,99 @@ +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use utils::{snippet_opt, span_lint_and_then, is_adjusted}; + +#[allow(missing_copy_implementations)] +pub struct EtaPass; + + +/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. +/// +/// **Why is this bad?** Needlessly creating a closure just costs heap space and adds code for no benefit. +/// +/// **Known problems:** None +/// +/// **Example:** `xs.map(|x| foo(x))` where `foo(_)` is a plain function that takes the exact argument type of `x`. +declare_lint! { + pub REDUNDANT_CLOSURE, Warn, + "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)" +} + +impl LintPass for EtaPass { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_CLOSURE) + } +} + +impl LateLintPass for EtaPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + match expr.node { + ExprCall(_, ref args) | + ExprMethodCall(_, _, ref args) => { + for arg in args { + check_closure(cx, arg) + } + } + _ => (), + } + } +} + +fn check_closure(cx: &LateContext, expr: &Expr) { + if let ExprClosure(_, ref decl, ref blk, _) = expr.node { + if !blk.stmts.is_empty() { + // || {foo(); bar()}; can't be reduced here + return; + } + + if let Some(ref ex) = blk.expr { + if let ExprCall(ref caller, ref args) = ex.node { + if args.len() != decl.inputs.len() { + // Not the same number of arguments, there + // is no way the closure is the same as the function + return; + } + if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { + // Are the expression or the arguments type-adjusted? Then we need the closure + return; + } + let fn_ty = cx.tcx.expr_ty(caller); + match fn_ty.sty { + // Is it an unsafe function? They don't implement the closure traits + ty::TyFnDef(_, _, fn_ty) | + ty::TyFnPtr(fn_ty) => { + if fn_ty.unsafety == Unsafety::Unsafe || + fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { + return; + } + } + _ => (), + } + for (ref a1, ref a2) in decl.inputs.iter().zip(args) { + if let PatKind::Ident(_, ident, _) = a1.pat.node { + // XXXManishearth Should I be checking the binding mode here? + if let ExprPath(None, ref p) = a2.node { + if p.segments.len() != 1 { + // If it's a proper path, it can't be a local variable + return; + } + if p.segments[0].name != ident.node { + // The two idents should be the same + return; + } + } else { + return; + } + } else { + return; + } + } + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { + if let Some(snippet) = snippet_opt(cx, caller.span) { + db.span_suggestion(expr.span, "remove closure as shown:", snippet); + } + }); + } + } + } +} diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs new file mode 100644 index 00000000000..0726fcaeab7 --- /dev/null +++ b/clippy_lints/src/format.rs @@ -0,0 +1,119 @@ +use rustc::hir::*; +use rustc::hir::map::Node::NodeItem; +use rustc::lint::*; +use rustc::ty::TypeVariants; +use syntax::ast::LitKind; +use utils::paths; +use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty}; + +/// **What it does:** This lints about use of `format!("string literal with no argument")` and +/// `format!("{}", foo)` where `foo` is a string. +/// +/// **Why is this bad?** There is no point of doing that. `format!("too")` can be replaced by `"foo".to_owned()` if you really need a `String`. The even worse `&format!("foo")` is often +/// encountered in the wild. `format!("{}", foo)` can be replaced by `foo.clone()` if `foo: String` +/// or `foo.to_owned()` is `foo: &str`. +/// +/// **Known problems:** None. +/// +/// **Examples:** `format!("foo")` and `format!("{}", foo)` +declare_lint! { + pub USELESS_FORMAT, + Warn, + "useless use of `format!`" +} + +#[derive(Copy, Clone, Debug)] +pub struct FormatMacLint; + +impl LintPass for FormatMacLint { + fn get_lints(&self) -> LintArray { + lint_array![USELESS_FORMAT] + } +} + +impl LateLintPass for FormatMacLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let Some(span) = is_expn_of(cx, expr.span, "format") { + match expr.node { + // `format!("{}", foo)` expansion + ExprCall(ref fun, ref args) => { + if_let_chain!{[ + let ExprPath(_, ref path) = fun.node, + args.len() == 2, + match_path(path, &paths::FMT_ARGUMENTS_NEWV1), + // ensure the format string is `"{..}"` with only one argument and no text + check_static_str(cx, &args[0]), + // ensure the format argument is `{}` ie. Display with no fancy option + check_arg_is_display(cx, &args[1]) + ], { + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); + }} + } + // `format!("foo")` expansion contains `match () { () => [], }` + ExprMatch(ref matchee, _, _) => { + if let ExprTup(ref tup) = matchee.node { + if tup.is_empty() { + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); + } + } + } + _ => (), + } + } + } +} + +/// Checks if the expressions matches +/// ``` +/// { static __STATIC_FMTSTR: &[""] = _; __STATIC_FMTSTR } +/// ``` +fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { + if_let_chain! {[ + let ExprBlock(ref block) = expr.node, + block.stmts.len() == 1, + let StmtDecl(ref decl, _) = block.stmts[0].node, + let DeclItem(ref decl) = decl.node, + let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id), + decl.name.as_str() == "__STATIC_FMTSTR", + let ItemStatic(_, _, ref expr) = decl.node, + let ExprAddrOf(_, ref expr) = expr.node, // &[""] + let ExprVec(ref expr) = expr.node, + expr.len() == 1, + let ExprLit(ref lit) = expr[0].node, + let LitKind::Str(ref lit, _) = lit.node, + lit.is_empty() + ], { + return true; + }} + + false +} + +/// Checks if the expressions matches +/// ``` +/// &match (&42,) { +/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)], +/// }) +/// ``` +fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, + let ExprMatch(_, ref arms, _) = expr.node, + arms.len() == 1, + arms[0].pats.len() == 1, + let PatKind::Tup(ref pat) = arms[0].pats[0].node, + pat.len() == 1, + let ExprVec(ref exprs) = arms[0].body.node, + exprs.len() == 1, + let ExprCall(_, ref args) = exprs[0].node, + args.len() == 2, + let ExprPath(None, ref path) = args[1].node, + match_path(path, &paths::DISPLAY_FMT_METHOD) + ], { + let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0])); + + return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING); + }} + + false +} diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs new file mode 100644 index 00000000000..aa6dd46cf0b --- /dev/null +++ b/clippy_lints/src/formatting.rs @@ -0,0 +1,166 @@ +use rustc::lint::*; +use syntax::codemap::mk_sp; +use syntax::ast; +use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; +use syntax::ptr::P; + +/// **What it does:** This lint looks for use of the non-existent `=*`, `=!` and `=-` operators. +/// +/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// a =- 42; // confusing, should it be `a -= 42` or `a = -42`? +/// ``` +declare_lint! { + pub SUSPICIOUS_ASSIGNMENT_FORMATTING, + Warn, + "suspicious formatting of `*=`, `-=` or `!=`" +} + +/// **What it does:** This lint checks for formatting of `else if`. It lints if the `else` and `if` +/// are not on the same line or the `else` seems to be missing. +/// +/// **Why is this bad?** This is probably some refactoring remnant, even if the code is correct, it +/// might look confusing. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// if foo { +/// } if bar { // looks like an `else` is missing here +/// } +/// +/// if foo { +/// } else +/// +/// if bar { // this is the `else` block of the previous `if`, but should it be? +/// } +/// ``` +declare_lint! { + pub SUSPICIOUS_ELSE_FORMATTING, + Warn, + "suspicious formatting of `else if`" +} + +#[derive(Copy,Clone)] +pub struct Formatting; + +impl LintPass for Formatting { + fn get_lints(&self) -> LintArray { + lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING] + } +} + +impl EarlyLintPass for Formatting { + fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { + for w in block.stmts.windows(2) { + match (&w[0].node, &w[1].node) { + (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Expr(ref second, _)) | + (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Semi(ref second, _)) => { + check_consecutive_ifs(cx, first, second); + } + _ => (), + } + } + + if let Some(ref expr) = block.expr { + if let Some(ref stmt) = block.stmts.iter().last() { + if let ast::StmtKind::Expr(ref first, _) = stmt.node { + check_consecutive_ifs(cx, first, expr); + } + } + } + } + + fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { + check_assign(cx, expr); + check_else_if(cx, expr); + } +} + +/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint. +fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { + if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { + if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) { + let eq_span = mk_sp(lhs.span.hi, rhs.span.lo); + + if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node { + if let Some(eq_snippet) = snippet_opt(cx, eq_span) { + let op = ast::UnOp::to_string(op); + let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo); + if eq_snippet.ends_with('=') { + span_note_and_lint(cx, + SUSPICIOUS_ASSIGNMENT_FORMATTING, + eqop_span, + &format!("this looks like you are trying to use `.. {op}= ..`, but you \ + really are doing `.. = ({op} ..)`", + op = op), + eqop_span, + &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op)); + } + } + } + } + } +} + +/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`. +fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { + if let Some((then, &Some(ref else_))) = unsugar_if(expr) { + if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) { + // this will be a span from the closing ‘}’ of the “then” block (excluding) to the + // “if” of the “else if” block (excluding) + let else_span = mk_sp(then.span.hi, else_.span.lo); + + // the snippet should look like " else \n " with maybe comments anywhere + // it’s bad when there is a ‘\n’ after the “else” + if let Some(else_snippet) = snippet_opt(cx, else_span) { + let else_pos = else_snippet.find("else").expect("there must be a `else` here"); + + if else_snippet[else_pos..].contains('\n') { + span_note_and_lint(cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this is an `else if` but the formatting might hide it", + else_span, + "to remove this lint, remove the `else` or remove the new line between `else` \ + and `if`"); + } + } + } + } +} + +/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. +fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { + if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) && + unsugar_if(first).is_some() && unsugar_if(second).is_some() { + // where the else would be + let else_span = mk_sp(first.span.hi, second.span.lo); + + if let Some(else_snippet) = snippet_opt(cx, else_span) { + if !else_snippet.contains('\n') { + span_note_and_lint(cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this looks like an `else if` but the `else` is missing", + else_span, + "to remove this lint, add the missing `else` or add a new line before the second \ + `if`"); + } + } + } +} + +/// Match `if` or `else if` expressions and return the `then` and `else` block. +fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> { + match expr.node { + ast::ExprKind::If(_, ref then, ref else_) | + ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), + _ => None, + } +} diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs new file mode 100644 index 00000000000..d9334447226 --- /dev/null +++ b/clippy_lints/src/functions.rs @@ -0,0 +1,76 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::hir::intravisit; +use syntax::ast; +use syntax::codemap::Span; +use utils::span_lint; + +/// **What it does:** Check for functions with too many parameters. +/// +/// **Why is this bad?** Functions with lots of parameters are considered bad style and reduce +/// readability (“what does the 5th parameter mean?”). Consider grouping some parameters into a +/// new type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ``` +/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { .. } +/// ``` +declare_lint! { + pub TOO_MANY_ARGUMENTS, + Warn, + "functions with too many arguments" +} + +#[derive(Copy,Clone)] +pub struct Functions { + threshold: u64, +} + +impl Functions { + pub fn new(threshold: u64) -> Functions { + Functions { threshold: threshold } + } +} + +impl LintPass for Functions { + fn get_lints(&self) -> LintArray { + lint_array!(TOO_MANY_ARGUMENTS) + } +} + +impl LateLintPass for Functions { + fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) { + use rustc::hir::map::Node::*; + + if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { + match item.node { + hir::ItemImpl(_, _, _, Some(_), _, _) | + hir::ItemDefaultImpl(..) => return, + _ => (), + } + } + + self.check_arg_number(cx, decl, span); + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { + if let hir::MethodTraitItem(ref sig, _) = item.node { + self.check_arg_number(cx, &sig.decl, item.span); + } + } +} + +impl Functions { + fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { + let args = decl.inputs.len() as u64; + if args > self.threshold { + span_lint(cx, + TOO_MANY_ARGUMENTS, + span, + &format!("this function has too many arguments ({}/{})", args, self.threshold)); + } + } +} diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs new file mode 100644 index 00000000000..4c1f01b7385 --- /dev/null +++ b/clippy_lints/src/identity_op.rs @@ -0,0 +1,72 @@ +use consts::{constant_simple, Constant}; +use rustc::lint::*; +use rustc::hir::*; +use syntax::codemap::Span; +use utils::{span_lint, snippet, in_macro}; +use rustc_const_math::ConstInt; + +/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. +/// +/// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly. +/// +/// **Known problems:** None +/// +/// **Example:** `x / 1 + 0 * 1 - 0 | 0` +declare_lint! { + pub IDENTITY_OP, Warn, + "using identity operations, e.g. `x + 0` or `y / 1`" +} + +#[derive(Copy,Clone)] +pub struct IdentityOp; + +impl LintPass for IdentityOp { + fn get_lints(&self) -> LintArray { + lint_array!(IDENTITY_OP) + } +} + +impl LateLintPass for IdentityOp { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if in_macro(cx, e.span) { + return; + } + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + match cmp.node { + BiAdd | BiBitOr | BiBitXor => { + check(cx, left, 0, e.span, right.span); + check(cx, right, 0, e.span, left.span); + } + BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), + BiMul => { + check(cx, left, 1, e.span, right.span); + check(cx, right, 1, e.span, left.span); + } + BiDiv => check(cx, right, 1, e.span, left.span), + BiBitAnd => { + check(cx, left, -1, e.span, right.span); + check(cx, right, -1, e.span, left.span); + } + _ => (), + } + } + } +} + + +fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { + if let Some(v @ Constant::Int(_)) = constant_simple(e) { + if match m { + 0 => v == Constant::Int(ConstInt::Infer(0)), + -1 => v == Constant::Int(ConstInt::InferSigned(-1)), + 1 => v == Constant::Int(ConstInt::Infer(1)), + _ => unreachable!(), + } { + span_lint(cx, + IDENTITY_OP, + span, + &format!("the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, ".."))); + } + } +} diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs new file mode 100644 index 00000000000..d78eba9877b --- /dev/null +++ b/clippy_lints/src/if_not_else.rs @@ -0,0 +1,52 @@ +//! lint on if branches that could be swapped so no `!` operation is necessary on the condition + +use rustc::lint::*; +use syntax::ast::*; + +use utils::span_help_and_lint; + +/// **What it does:** Warns on the use of `!` or `!=` in an if condition with an else branch +/// +/// **Why is this bad?** Negations reduce the readability of statements +/// +/// **Known problems:** None +/// +/// **Example:** if !v.is_empty() { a() } else { b() } +declare_lint! { + pub IF_NOT_ELSE, Allow, + "finds if branches that could be swapped so no negation operation is necessary on the condition" +} + +pub struct IfNotElse; + +impl LintPass for IfNotElse { + fn get_lints(&self) -> LintArray { + lint_array!(IF_NOT_ELSE) + } +} + +impl EarlyLintPass for IfNotElse { + fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + if let ExprKind::If(ref cond, _, Some(ref els)) = item.node { + if let ExprKind::Block(..) = els.node { + match cond.node { + ExprKind::Unary(UnOp::Not, _) => { + span_help_and_lint(cx, + IF_NOT_ELSE, + item.span, + "Unnecessary boolean `not` operation", + "remove the `!` and swap the blocks of the if/else"); + } + ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { + span_help_and_lint(cx, + IF_NOT_ELSE, + item.span, + "Unnecessary `!=` operation", + "change to `==` and swap the blocks of the if/else"); + } + _ => (), + } + } + } + } +} diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs new file mode 100644 index 00000000000..2e6b33ab390 --- /dev/null +++ b/clippy_lints/src/items_after_statements.rs @@ -0,0 +1,70 @@ +//! lint when items are used after statements + +use rustc::lint::*; +use syntax::ast::*; +use utils::in_macro; + +/// **What it does:** This lints checks for items declared after some statement in a block +/// +/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are +/// processed in order. This might cause confusion as it's hard to figure out which item is meant +/// in a statement. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// fn foo() { +/// println!("cake"); +/// } +/// fn main() { +/// foo(); // prints "foo" +/// fn foo() { +/// println!("foo"); +/// } +/// foo(); // prints "foo" +/// } +/// ``` +declare_lint! { + pub ITEMS_AFTER_STATEMENTS, + Allow, + "finds blocks where an item comes after a statement" +} + +pub struct ItemsAfterStatements; + +impl LintPass for ItemsAfterStatements { + fn get_lints(&self) -> LintArray { + lint_array!(ITEMS_AFTER_STATEMENTS) + } +} + +impl EarlyLintPass for ItemsAfterStatements { + fn check_block(&mut self, cx: &EarlyContext, item: &Block) { + if in_macro(cx, item.span) { + return; + } + let mut stmts = item.stmts.iter().map(|stmt| &stmt.node); + // skip initial items + while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() { + if let DeclKind::Local(_) = decl.node { + break; + } + } + // lint on all further items + for stmt in stmts { + if let StmtKind::Decl(ref decl, _) = *stmt { + if let DeclKind::Item(ref it) = decl.node { + if in_macro(cx, it.span) { + return; + } + cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, + it.span, + "adding items after statements is confusing, since items exist from the \ + start of the scope") + .emit(); + } + } + } + } +} diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs new file mode 100644 index 00000000000..b6dea831690 --- /dev/null +++ b/clippy_lints/src/len_zero.rs @@ -0,0 +1,202 @@ +use rustc::lint::*; +use rustc::hir::def_id::DefId; +use rustc::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; +use rustc::hir::*; +use syntax::ast::{Lit, LitKind, Name}; +use syntax::codemap::{Span, Spanned}; +use syntax::ptr::P; +use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; + +/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. +/// +/// **Why is this bad?** Some structures can answer `.is_empty()` much faster than calculating their length. So it is good to get into the habit of using `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer than a comparison. +/// +/// **Known problems:** None +/// +/// **Example:** `if x.len() == 0 { .. }` +declare_lint! { + pub LEN_ZERO, Warn, + "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ + could be used instead" +} + +/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. +/// +/// **Why is this bad?** It is good custom to have both methods, because for some data structures, asking about the length will be a costly operation, whereas `.is_empty()` can usually answer in constant time. Also it used to lead to false positives on the [`len_zero`](#len_zero) lint – currently that lint will ignore such entities. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// impl X { +/// fn len(&self) -> usize { .. } +/// } +/// ``` +declare_lint! { + pub LEN_WITHOUT_IS_EMPTY, Warn, + "traits and impls that have `.len()` but not `.is_empty()`" +} + +#[derive(Copy,Clone)] +pub struct LenZero; + +impl LintPass for LenZero { + fn get_lints(&self) -> LintArray { + lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) + } +} + +impl LateLintPass for LenZero { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if in_macro(cx, item.span) { + return; + } + + match item.node { + ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), + ItemImpl(_, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), + _ => (), + } + } + + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_macro(cx, expr.span) { + return; + } + + if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { + match cmp { + BiEq => check_cmp(cx, expr.span, left, right, ""), + BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + _ => (), + } + } + } +} + +fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { + fn is_named_self(item: &TraitItem, name: &str) -> bool { + item.name.as_str() == name && + if let MethodTraitItem(ref sig, _) = item.node { + is_self_sig(sig) + } else { + false + } + } + + if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { + for i in trait_items { + if is_named_self(i, "len") { + span_lint(cx, + LEN_WITHOUT_IS_EMPTY, + i.span, + &format!("trait `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ + Consider adding one", + item.name)); + } + } + } +} + +fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { + fn is_named_self(item: &ImplItem, name: &str) -> bool { + item.name.as_str() == name && + if let ImplItemKind::Method(ref sig, _) = item.node { + is_self_sig(sig) + } else { + false + } + } + + if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { + for i in impl_items { + if is_named_self(i, "len") { + let ty = cx.tcx.node_id_to_type(item.id); + + span_lint(cx, + LEN_WITHOUT_IS_EMPTY, + i.span, + &format!("item `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ + Consider adding one", + ty)); + return; + } + } + } +} + +fn is_self_sig(sig: &MethodSig) -> bool { + if sig.decl.has_self() { + sig.decl.inputs.len() == 1 + } else { + false + } +} + +fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { + // check if we are in an is_empty() method + if let Some(name) = get_item_name(cx, left) { + if name.as_str() == "is_empty" { + return; + } + } + match (&left.node, &right.node) { + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) | + (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => { + check_len_zero(cx, span, &method.node, args, lit, op) + } + _ => (), + } +} + +fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { + if let Spanned { node: LitKind::Int(0, _), .. } = *lit { + if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { + span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| { + db.span_suggestion(span, + "consider using `is_empty`", + format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_"))); + }); + } + } +} + +/// Check if this type has an `is_empty` method. +fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { + /// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`. + fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { + if let MethodTraitItemId(def_id) = *id { + if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { + method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 + } else { + false + } + } else { + false + } + } + + /// Check the inherent impl's items for an `is_empty(self)` method. + fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool { + let impl_items = cx.tcx.impl_items.borrow(); + cx.tcx.inherent_impls.borrow().get(id).map_or(false, |ids| { + ids.iter().any(|iid| impl_items.get(iid).map_or(false, |iids| iids.iter().any(|i| is_is_empty(cx, i)))) + }) + } + + let ty = &walk_ptrs_ty(cx.tcx.expr_ty(expr)); + match ty.sty { + ty::TyTrait(_) => { + cx.tcx + .trait_item_def_ids + .borrow() + .get(&ty.ty_to_def_id().expect("trait impl not found")) + .map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))) + } + ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), + ty::TyEnum(ref id, _) | + ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), + ty::TyArray(..) | ty::TyStr => true, + _ => false, + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs new file mode 100644 index 00000000000..f6db7a3a188 --- /dev/null +++ b/clippy_lints/src/lib.rs @@ -0,0 +1,416 @@ +// error-pattern:cargo-clippy + +#![feature(type_macros)] +#![feature(plugin_registrar, box_syntax)] +#![feature(rustc_private, collections)] +#![feature(iter_arith)] +#![feature(custom_attribute)] +#![feature(slice_patterns)] +#![feature(question_mark)] +#![feature(stmt_expr_attributes)] +#![allow(indexing_slicing, shadow_reuse, unknown_lints)] + +extern crate rustc_driver; +extern crate getopts; + +#[macro_use] +extern crate syntax; +#[macro_use] +extern crate rustc; + +extern crate toml; + +// Only for the compile time checking of paths +extern crate core; +extern crate collections; + +// for unicode nfc normalization +extern crate unicode_normalization; + +// for semver check in attrs.rs +extern crate semver; + +// for regex checking +extern crate regex_syntax; + +// for finding minimal boolean expressions +extern crate quine_mc_cluskey; + +extern crate rustc_plugin; +extern crate rustc_const_eval; +extern crate rustc_const_math; + +macro_rules! declare_restriction_lint { + { pub $name:tt, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; +} + +pub mod consts; +#[macro_use] +pub mod utils; + +// begin lints modules, do not remove this comment, it’s used in `update_lints` +pub mod approx_const; +pub mod arithmetic; +pub mod array_indexing; +pub mod assign_ops; +pub mod attrs; +pub mod bit_mask; +pub mod blacklisted_name; +pub mod block_in_if_condition; +pub mod booleans; +pub mod collapsible_if; +pub mod copies; +pub mod cyclomatic_complexity; +pub mod derive; +pub mod doc; +pub mod drop_ref; +pub mod entry; +pub mod enum_clike; +pub mod enum_glob_use; +pub mod enum_variants; +pub mod eq_op; +pub mod escape; +pub mod eta_reduction; +pub mod format; +pub mod formatting; +pub mod functions; +pub mod identity_op; +pub mod if_not_else; +pub mod items_after_statements; +pub mod len_zero; +pub mod lifetimes; +pub mod loops; +pub mod map_clone; +pub mod matches; +pub mod mem_forget; +pub mod methods; +pub mod minmax; +pub mod misc; +pub mod misc_early; +pub mod mut_mut; +pub mod mut_reference; +pub mod mutex_atomic; +pub mod needless_bool; +pub mod needless_borrow; +pub mod needless_update; +pub mod neg_multiply; +pub mod new_without_default; +pub mod no_effect; +pub mod non_expressive_names; +pub mod open_options; +pub mod overflow_check_conditional; +pub mod panic; +pub mod precedence; +pub mod print; +pub mod ptr_arg; +pub mod ranges; +pub mod regex; +pub mod returns; +pub mod shadow; +pub mod strings; +pub mod swap; +pub mod temporary_assignment; +pub mod transmute; +pub mod types; +pub mod unicode; +pub mod unsafe_removed_from_name; +pub mod unused_label; +pub mod vec; +pub mod zero_div_zero; +// end lints modules, do not remove this comment, it’s used in `update_lints` + +mod reexport { + pub use syntax::ast::{Name, NodeId}; +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +pub fn register_plugins(reg: &mut rustc_plugin::Registry) { + let conf = match utils::conf::conf_file(reg.args()) { + Ok(file_name) => { + // if the user specified a file, it must exist, otherwise default to `clippy.toml` but + // do not require the file to exist + let (ref file_name, must_exist) = if let Some(ref file_name) = file_name { + (&**file_name, true) + } else { + ("clippy.toml", false) + }; + + let (conf, errors) = utils::conf::read_conf(file_name, must_exist); + + // all conf errors are non-fatal, we just use the default conf in case of error + for error in errors { + reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", error)).emit(); + } + + conf + } + Err((err, span)) => { + reg.sess.struct_span_err(span, err) + .span_note(span, "Clippy will use default configuration") + .emit(); + utils::conf::Conf::default() + } + }; + + let mut store = reg.sess.lint_store.borrow_mut(); + store.register_removed("unstable_as_slice", "`Vec::as_slice` has been stabilized in 1.7"); + store.register_removed("unstable_as_mut_slice", "`Vec::as_mut_slice` has been stabilized in 1.7"); + store.register_removed("str_to_string", "using `str::to_string` is common even today and specialization will likely happen soon"); + store.register_removed("string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon"); + // end deprecated lints, do not remove this comment, it’s used in `update_lints` + + reg.register_late_lint_pass(box types::TypePass); + reg.register_late_lint_pass(box booleans::NonminimalBool); + reg.register_late_lint_pass(box misc::TopLevelRefPass); + reg.register_late_lint_pass(box misc::CmpNan); + reg.register_late_lint_pass(box eq_op::EqOp); + reg.register_early_lint_pass(box enum_variants::EnumVariantNames); + reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); + reg.register_late_lint_pass(box enum_clike::EnumClikeUnportableVariant); + reg.register_late_lint_pass(box bit_mask::BitMask); + reg.register_late_lint_pass(box ptr_arg::PtrArg); + reg.register_late_lint_pass(box needless_bool::NeedlessBool); + reg.register_late_lint_pass(box needless_bool::BoolComparison); + reg.register_late_lint_pass(box approx_const::ApproxConstant); + reg.register_late_lint_pass(box misc::FloatCmp); + reg.register_early_lint_pass(box precedence::Precedence); + reg.register_late_lint_pass(box eta_reduction::EtaPass); + reg.register_late_lint_pass(box identity_op::IdentityOp); + reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements); + reg.register_late_lint_pass(box mut_mut::MutMut); + reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); + reg.register_late_lint_pass(box len_zero::LenZero); + reg.register_late_lint_pass(box misc::CmpOwned); + reg.register_late_lint_pass(box attrs::AttrPass); + reg.register_late_lint_pass(box collapsible_if::CollapsibleIf); + reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition); + reg.register_late_lint_pass(box misc::ModuloOne); + reg.register_late_lint_pass(box unicode::Unicode); + reg.register_late_lint_pass(box strings::StringAdd); + reg.register_early_lint_pass(box returns::ReturnPass); + reg.register_late_lint_pass(box methods::MethodsPass); + reg.register_late_lint_pass(box shadow::ShadowPass); + reg.register_late_lint_pass(box types::LetPass); + reg.register_late_lint_pass(box types::UnitCmp); + reg.register_late_lint_pass(box loops::LoopsPass); + reg.register_late_lint_pass(box lifetimes::LifetimePass); + reg.register_late_lint_pass(box entry::HashMapLint); + reg.register_late_lint_pass(box ranges::StepByZero); + reg.register_late_lint_pass(box types::CastPass); + reg.register_late_lint_pass(box types::TypeComplexityPass::new(conf.type_complexity_threshold)); + reg.register_late_lint_pass(box matches::MatchPass); + reg.register_late_lint_pass(box misc::PatternPass); + reg.register_late_lint_pass(box minmax::MinMaxPass); + reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); + reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); + reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); + reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); + reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); + reg.register_late_lint_pass(box no_effect::NoEffectPass); + reg.register_late_lint_pass(box map_clone::MapClonePass); + reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); + reg.register_late_lint_pass(box transmute::Transmute); + reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); + reg.register_late_lint_pass(box escape::EscapePass); + reg.register_early_lint_pass(box misc_early::MiscEarly); + reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); + reg.register_late_lint_pass(box array_indexing::ArrayIndexing); + reg.register_late_lint_pass(box panic::PanicPass); + reg.register_late_lint_pass(box strings::StringLitAsBytes); + reg.register_late_lint_pass(box derive::Derive); + reg.register_late_lint_pass(box types::CharLitAsU8); + reg.register_late_lint_pass(box print::PrintLint); + reg.register_late_lint_pass(box vec::UselessVec); + reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { + max_single_char_names: conf.max_single_char_names, + }); + reg.register_late_lint_pass(box drop_ref::DropRefPass); + reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); + reg.register_late_lint_pass(box types::InvalidUpcastComparisons); + reg.register_late_lint_pass(box regex::RegexPass::default()); + reg.register_late_lint_pass(box copies::CopyAndPaste); + reg.register_late_lint_pass(box format::FormatMacLint); + reg.register_early_lint_pass(box formatting::Formatting); + reg.register_late_lint_pass(box swap::Swap); + reg.register_early_lint_pass(box if_not_else::IfNotElse); + reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); + reg.register_late_lint_pass(box unused_label::UnusedLabel); + reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); + reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); + reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); + reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); + reg.register_late_lint_pass(box neg_multiply::NegMultiply); + reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); + reg.register_late_lint_pass(box mem_forget::MemForget); + reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); + reg.register_late_lint_pass(box assign_ops::AssignOps); + + reg.register_lint_group("clippy_restrictions", vec![ + arithmetic::FLOAT_ARITHMETIC, + arithmetic::INTEGER_ARITHMETIC, + assign_ops::ASSIGN_OPS, + ]); + + reg.register_lint_group("clippy_pedantic", vec![ + array_indexing::INDEXING_SLICING, + booleans::NONMINIMAL_BOOL, + enum_glob_use::ENUM_GLOB_USE, + if_not_else::IF_NOT_ELSE, + items_after_statements::ITEMS_AFTER_STATEMENTS, + matches::SINGLE_MATCH_ELSE, + mem_forget::MEM_FORGET, + methods::OPTION_UNWRAP_USED, + methods::RESULT_UNWRAP_USED, + methods::WRONG_PUB_SELF_CONVENTION, + misc::USED_UNDERSCORE_BINDING, + mut_mut::MUT_MUT, + mutex_atomic::MUTEX_INTEGER, + non_expressive_names::SIMILAR_NAMES, + print::PRINT_STDOUT, + print::USE_DEBUG, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, + strings::STRING_ADD, + strings::STRING_ADD_ASSIGN, + types::CAST_POSSIBLE_TRUNCATION, + types::CAST_POSSIBLE_WRAP, + types::CAST_PRECISION_LOSS, + types::CAST_SIGN_LOSS, + types::INVALID_UPCAST_COMPARISONS, + unicode::NON_ASCII_LITERAL, + unicode::UNICODE_NOT_NFC, + ]); + + reg.register_lint_group("clippy", vec![ + approx_const::APPROX_CONSTANT, + array_indexing::OUT_OF_BOUNDS_INDEXING, + assign_ops::ASSIGN_OP_PATTERN, + attrs::DEPRECATED_SEMVER, + attrs::INLINE_ALWAYS, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + blacklisted_name::BLACKLISTED_NAME, + block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, + block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, + booleans::LOGIC_BUG, + collapsible_if::COLLAPSIBLE_IF, + copies::IF_SAME_THEN_ELSE, + copies::IFS_SAME_COND, + copies::MATCH_SAME_ARMS, + cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + derive::DERIVE_HASH_XOR_EQ, + derive::EXPL_IMPL_CLONE_ON_COPY, + doc::DOC_MARKDOWN, + drop_ref::DROP_REF, + entry::MAP_ENTRY, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, + enum_variants::ENUM_VARIANT_NAMES, + eq_op::EQ_OP, + escape::BOXED_LOCAL, + eta_reduction::REDUNDANT_CLOSURE, + format::USELESS_FORMAT, + formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, + formatting::SUSPICIOUS_ELSE_FORMATTING, + functions::TOO_MANY_ARGUMENTS, + identity_op::IDENTITY_OP, + len_zero::LEN_WITHOUT_IS_EMPTY, + len_zero::LEN_ZERO, + lifetimes::NEEDLESS_LIFETIMES, + lifetimes::UNUSED_LIFETIMES, + loops::EMPTY_LOOP, + loops::EXPLICIT_COUNTER_LOOP, + loops::EXPLICIT_ITER_LOOP, + loops::FOR_KV_MAP, + loops::FOR_LOOP_OVER_OPTION, + loops::FOR_LOOP_OVER_RESULT, + loops::ITER_NEXT_LOOP, + loops::NEEDLESS_RANGE_LOOP, + loops::REVERSE_RANGE_LOOP, + loops::UNUSED_COLLECT, + loops::WHILE_LET_LOOP, + loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, + matches::MATCH_BOOL, + matches::MATCH_OVERLAPPING_ARM, + matches::MATCH_REF_PATS, + matches::SINGLE_MATCH, + methods::CHARS_NEXT_CMP, + methods::CLONE_DOUBLE_REF, + methods::CLONE_ON_COPY, + methods::EXTEND_FROM_SLICE, + methods::FILTER_NEXT, + methods::NEW_RET_NO_SELF, + methods::OK_EXPECT, + methods::OPTION_MAP_UNWRAP_OR, + methods::OPTION_MAP_UNWRAP_OR_ELSE, + methods::OR_FUN_CALL, + methods::SEARCH_IS_SOME, + methods::SHOULD_IMPLEMENT_TRAIT, + methods::SINGLE_CHAR_PATTERN, + methods::TEMPORARY_CSTRING_AS_PTR, + methods::WRONG_SELF_CONVENTION, + minmax::MIN_MAX, + misc::CMP_NAN, + misc::CMP_OWNED, + misc::FLOAT_CMP, + misc::MODULO_ONE, + misc::REDUNDANT_PATTERN, + misc::TOPLEVEL_REF_ARG, + misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, + misc_early::REDUNDANT_CLOSURE_CALL, + misc_early::UNNEEDED_FIELD_PATTERN, + mut_reference::UNNECESSARY_MUT_PASSED, + mutex_atomic::MUTEX_ATOMIC, + needless_bool::BOOL_COMPARISON, + needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, + needless_update::NEEDLESS_UPDATE, + neg_multiply::NEG_MULTIPLY, + new_without_default::NEW_WITHOUT_DEFAULT, + new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, + no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, + non_expressive_names::MANY_SINGLE_CHAR_NAMES, + open_options::NONSENSICAL_OPEN_OPTIONS, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, + panic::PANIC_PARAMS, + precedence::PRECEDENCE, + ptr_arg::PTR_ARG, + ranges::RANGE_STEP_BY_ZERO, + ranges::RANGE_ZIP_WITH_LEN, + regex::INVALID_REGEX, + regex::REGEX_MACRO, + regex::TRIVIAL_REGEX, + returns::LET_AND_RETURN, + returns::NEEDLESS_RETURN, + strings::STRING_LIT_AS_BYTES, + swap::ALMOST_SWAPPED, + swap::MANUAL_SWAP, + temporary_assignment::TEMPORARY_ASSIGNMENT, + transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTE_PTR_TO_REF, + transmute::USELESS_TRANSMUTE, + types::ABSURD_EXTREME_COMPARISONS, + types::BOX_VEC, + types::CHAR_LIT_AS_U8, + types::LET_UNIT_VALUE, + types::LINKEDLIST, + types::TYPE_COMPLEXITY, + types::UNIT_CMP, + unicode::ZERO_WIDTH_SPACE, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + unused_label::UNUSED_LABEL, + vec::USELESS_VEC, + zero_div_zero::ZERO_DIVIDED_BY_ZERO, + ]); +} + +// only exists to let the dogfood integration test works. +// Don't run clippy as an executable directly +#[allow(dead_code, print_stdout)] +fn main() { + panic!("Please use the cargo-clippy executable"); +} diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs new file mode 100644 index 00000000000..797e9708b60 --- /dev/null +++ b/clippy_lints/src/lifetimes.rs @@ -0,0 +1,347 @@ +use reexport::*; +use rustc::lint::*; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; +use std::collections::{HashSet, HashMap}; +use syntax::codemap::Span; +use utils::{in_external_macro, span_lint}; + +/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. +/// +/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. +/// +/// **Known problems:** Potential false negatives: we bail out if the function has a `where` clause where lifetimes are mentioned. +/// +/// **Example:** `fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }` +declare_lint! { + pub NEEDLESS_LIFETIMES, + Warn, + "using explicit lifetimes for references in function arguments when elision rules \ + would allow omitting them" +} + +/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. +/// +/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. +/// +/// **Known problems:** None +/// +/// **Example:** `fn unused_lifetime<'a>(x: u8) { .. }` +declare_lint! { + pub UNUSED_LIFETIMES, + Warn, + "unused lifetimes in function definitions" +} + +#[derive(Copy,Clone)] +pub struct LifetimePass; + +impl LintPass for LifetimePass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_LIFETIMES, UNUSED_LIFETIMES) + } +} + +impl LateLintPass for LifetimePass { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { + check_fn_inner(cx, decl, generics, item.span); + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + if let ImplItemKind::Method(ref sig, _) = item.node { + check_fn_inner(cx, &sig.decl, &sig.generics, item.span); + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + if let MethodTraitItem(ref sig, _) = item.node { + check_fn_inner(cx, &sig.decl, &sig.generics, item.span); + } + } +} + +/// The lifetime of a &-reference. +#[derive(PartialEq, Eq, Hash, Debug)] +enum RefLt { + Unnamed, + Static, + Named(Name), +} + +fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { + if let TraitTyParamBound(ref trait_ref, _) = *bound { + let lt = trait_ref.trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .parameters + .lifetimes(); + + Some(lt) + } else { + None + } +} + +fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Span) { + if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { + return; + } + + let bounds_lts = generics.ty_params + .iter() + .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); + + if could_use_elision(cx, decl, &generics.lifetimes, bounds_lts) { + span_lint(cx, + NEEDLESS_LIFETIMES, + span, + "explicit lifetimes given in parameter types where they could be elided"); + } + report_extra_lifetimes(cx, decl, generics); +} + +fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, + named_lts: &[LifetimeDef], bounds_lts: T) + -> bool { + // There are two scenarios where elision works: + // * no output references, all input references have different LT + // * output references, exactly one input reference with same LT + // All lifetimes must be unnamed, 'static or defined without bounds on the + // level of the current item. + + // check named LTs + let allowed_lts = allowed_lts_from(named_lts); + + // these will collect all the lifetimes for references in arg/return types + let mut input_visitor = RefVisitor::new(cx); + let mut output_visitor = RefVisitor::new(cx); + + // extract lifetimes in input argument types + for arg in &func.inputs { + input_visitor.visit_ty(&arg.ty); + } + // extract lifetimes in output type + if let Return(ref ty) = func.output { + output_visitor.visit_ty(ty); + } + + let input_lts = lts_from_bounds(input_visitor.into_vec(), bounds_lts); + let output_lts = output_visitor.into_vec(); + + // check for lifetimes from higher scopes + for lt in input_lts.iter().chain(output_lts.iter()) { + if !allowed_lts.contains(lt) { + return false; + } + } + + // no input lifetimes? easy case! + if input_lts.is_empty() { + false + } else if output_lts.is_empty() { + // no output lifetimes, check distinctness of input lifetimes + + // only unnamed and static, ok + if input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static) { + return false; + } + // we have no output reference, so we only need all distinct lifetimes + input_lts.len() == unique_lifetimes(&input_lts) + } else { + // we have output references, so we need one input reference, + // and all output lifetimes must be the same + if unique_lifetimes(&output_lts) > 1 { + return false; + } + if input_lts.len() == 1 { + match (&input_lts[0], &output_lts[0]) { + (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true, + (&RefLt::Named(_), &RefLt::Unnamed) => true, + _ => false, // already elided, different named lifetimes + // or something static going on + } + } else { + false + } + } +} + +fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { + let mut allowed_lts = HashSet::new(); + for lt in named_lts { + if lt.bounds.is_empty() { + allowed_lts.insert(RefLt::Named(lt.lifetime.name)); + } + } + allowed_lts.insert(RefLt::Unnamed); + allowed_lts.insert(RefLt::Static); + allowed_lts +} + +fn lts_from_bounds<'a, T: Iterator<Item = &'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> { + for lt in bounds_lts { + if lt.name.as_str() != "'static" { + vec.push(RefLt::Named(lt.name)); + } + } + + vec +} + +/// Number of unique lifetimes in the given vector. +fn unique_lifetimes(lts: &[RefLt]) -> usize { + lts.iter().collect::<HashSet<_>>().len() +} + +/// A visitor usable for `rustc_front::visit::walk_ty()`. +struct RefVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, + lts: Vec<RefLt>, +} + +impl<'v, 't> RefVisitor<'v, 't> { + fn new(cx: &'v LateContext<'v, 't>) -> RefVisitor<'v, 't> { + RefVisitor { + cx: cx, + lts: Vec::new(), + } + } + + fn record(&mut self, lifetime: &Option<Lifetime>) { + if let Some(ref lt) = *lifetime { + if lt.name.as_str() == "'static" { + self.lts.push(RefLt::Static); + } else { + self.lts.push(RefLt::Named(lt.name)); + } + } else { + self.lts.push(RefLt::Unnamed); + } + } + + fn into_vec(self) -> Vec<RefLt> { + self.lts + } + + fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) { + let last_path_segment = path.segments.last().map(|s| &s.parameters); + if let Some(&AngleBracketedParameters(ref params)) = last_path_segment { + if params.lifetimes.is_empty() { + if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { + match def { + Def::TyAlias(def_id) | + Def::Struct(def_id) => { + let type_scheme = self.cx.tcx.lookup_item_type(def_id); + for _ in type_scheme.generics.regions.as_slice() { + self.record(&None); + } + } + Def::Trait(def_id) => { + let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; + for _ in &trait_def.generics.regions { + self.record(&None); + } + } + _ => (), + } + } + } + } + } +} + +impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { + // for lifetimes as parameters of generics + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { + self.record(&Some(*lifetime)); + } + + fn visit_ty(&mut self, ty: &'v Ty) { + match ty.node { + TyRptr(None, _) => { + self.record(&None); + } + TyPath(_, ref path) => { + self.collect_anonymous_lifetimes(path, ty); + } + _ => (), + } + walk_ty(self, ty); + } +} + +/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to +/// reason about elision. +fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { + for predicate in &where_clause.predicates { + match *predicate { + WherePredicate::RegionPredicate(..) => return true, + WherePredicate::BoundPredicate(ref pred) => { + // a predicate like F: Trait or F: for<'a> Trait<'a> + let mut visitor = RefVisitor::new(cx); + // walk the type F, it may not contain LT refs + walk_ty(&mut visitor, &pred.bounded_ty); + if !visitor.lts.is_empty() { + return true; + } + // if the bounds define new lifetimes, they are fine to occur + let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); + // now walk the bounds + for bound in pred.bounds.iter() { + walk_ty_param_bound(&mut visitor, bound); + } + // and check that all lifetimes are allowed + for lt in visitor.into_vec() { + if !allowed_lts.contains(<) { + return true; + } + } + } + WherePredicate::EqPredicate(ref pred) => { + let mut visitor = RefVisitor::new(cx); + walk_ty(&mut visitor, &pred.ty); + if !visitor.lts.is_empty() { + return true; + } + } + } + } + false +} + +struct LifetimeChecker(HashMap<Name, Span>); + +impl<'v> Visitor<'v> for LifetimeChecker { + // for lifetimes as parameters of generics + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { + self.0.remove(&lifetime.name); + } + + fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) { + // don't actually visit `<'a>` or `<'a: 'b>` + // we've already visited the `'a` declarations and + // don't want to spuriously remove them + // `'b` in `'a: 'b` is useless unless used elsewhere in + // a non-lifetime bound + } +} + +fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) { + let hs = generics.lifetimes + .iter() + .map(|lt| (lt.lifetime.name, lt.lifetime.span)) + .collect(); + let mut checker = LifetimeChecker(hs); + + walk_generics(&mut checker, generics); + walk_fn_decl(&mut checker, func); + + for &v in checker.0.values() { + span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); + } +} diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs new file mode 100644 index 00000000000..061b8efaa64 --- /dev/null +++ b/clippy_lints/src/loops.rs @@ -0,0 +1,976 @@ +use reexport::*; +use rustc::hir::*; +use rustc::hir::def::Def; +use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; +use rustc::hir::map::Node::NodeBlock; +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc::middle::region::CodeExtent; +use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use std::borrow::Cow; +use std::collections::HashMap; +use syntax::ast; + +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, + span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range, + walk_ptrs_ty, recover_for_loop}; +use utils::paths; +use utils::UnsugaredRange; + +/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. +/// +/// **Why is this bad?** Just iterating the collection itself makes the intent more clear and is probably faster. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// for i in 0..vec.len() { +/// println!("{}", vec[i]); +/// } +/// ``` +declare_lint! { + pub NEEDLESS_RANGE_LOOP, + Warn, + "for-looping over a range of indices where an iterator over items would do" +} + +/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. +/// +/// **Why is this bad?** Readability. +/// +/// **Known problems:** False negatives. We currently only warn on some known types. +/// +/// **Example:** `for x in y.iter() { .. }` (where y is a `Vec` or slice) +declare_lint! { + pub EXPLICIT_ITER_LOOP, + Warn, + "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" +} + +/// **What it does:** This lint checks for loops on `x.next()`. +/// +/// **Why is this bad?** `next()` returns either `Some(value)` if there was a value, or `None` otherwise. The insidious thing is that `Option<_>` implements `IntoIterator`, so that possibly one value will be iterated, leading to some hard to find bugs. No one will want to write such code [except to win an Underhanded Rust Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). +/// +/// **Known problems:** None +/// +/// **Example:** `for x in y.next() { .. }` +declare_lint! { + pub ITER_NEXT_LOOP, + Warn, + "for-looping over `_.next()` which is probably not intended" +} + +/// **What it does:** This lint checks for `for` loops over `Option` values. +/// +/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`. +declare_lint! { + pub FOR_LOOP_OVER_OPTION, + Warn, + "for-looping over an `Option`, which is more clearly expressed as an `if let`" +} + +/// **What it does:** This lint checks for `for` loops over `Result` values. +/// +/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in result { .. }`. This should be `if let Ok(x) = result { .. }`. +declare_lint! { + pub FOR_LOOP_OVER_RESULT, + Warn, + "for-looping over a `Result`, which is more clearly expressed as an `if let`" +} + +/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. +/// +/// **Why is this bad?** The `while let` loop is usually shorter and more readable +/// +/// **Known problems:** Sometimes the wrong binding is displayed (#383) +/// +/// **Example:** +/// +/// ``` +/// loop { +/// let x = match y { +/// Some(x) => x, +/// None => break, +/// } +/// // .. do something with x +/// } +/// // is easier written as +/// while let Some(x) = y { +/// // .. do something with x +/// } +/// ``` +declare_lint! { + pub WHILE_LET_LOOP, + Warn, + "`loop { if let { ... } else break }` can be written as a `while let` loop" +} + +/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. +/// +/// **Why is this bad?** It is more idiomatic to use a `for` loop over the iterator instead. +/// +/// **Known problems:** None +/// +/// **Example:** `vec.iter().map(|x| /* some operation returning () */).collect::<Vec<_>>();` +declare_lint! { + pub UNUSED_COLLECT, + Warn, + "`collect()`ing an iterator without using the result; this is usually better \ + written as a for loop" +} + +/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. +/// +/// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended. +/// +/// **Known problems:** The lint cannot catch loops over dynamically defined ranges. Doing this would require simulating all possible inputs and code paths through the program, which would be complex and error-prone. +/// +/// **Examples**: `for x in 5..10-5 { .. }` (oops, stray `-`) +declare_lint! { + pub REVERSE_RANGE_LOOP, + Warn, + "Iterating over an empty range, such as `10..0` or `5..5`" +} + +/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. +/// +/// **Why is it bad?** Not only is the version using `.enumerate()` more readable, the compiler is able to remove bounds checks which can lead to faster code in some instances. +/// +/// **Known problems:** None. +/// +/// **Example:** `for i in 0..v.len() { foo(v[i]); }` or `for i in 0..v.len() { bar(i, v[i]); }` +declare_lint! { + pub EXPLICIT_COUNTER_LOOP, + Warn, + "for-looping with an explicit counter when `_.enumerate()` would do" +} + +/// **What it does:** This lint checks for empty `loop` expressions. +/// +/// **Why is this bad?** Those busy loops burn CPU cycles without doing anything. Think of the environment and either block on something or at least make the thread sleep for some microseconds. +/// +/// **Known problems:** None +/// +/// **Example:** `loop {}` +declare_lint! { + pub EMPTY_LOOP, + Warn, + "empty `loop {}` detected" +} + +/// **What it does:** This lint checks for `while let` expressions on iterators. +/// +/// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys the intent better. +/// +/// **Known problems:** None +/// +/// **Example:** `while let Some(val) = iter() { .. }` +declare_lint! { + pub WHILE_LET_ON_ITERATOR, + Warn, + "using a while-let loop instead of a for loop on an iterator" +} + +/// **What it does:** This warns when you iterate on a map (`HashMap` or `BTreeMap`) and ignore +/// either the keys or values. +/// +/// **Why is this bad?** Readability. There are `keys` and `values` methods that can be used to +/// express that don't need the values or keys. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// for (k, _) in &map { .. } +/// ``` +/// could be replaced by +/// ```rust +/// for k in map.keys() { .. } +/// ``` +declare_lint! { + pub FOR_KV_MAP, + Warn, + "looping on a map using `iter` when `keys` or `values` would do" +} + +#[derive(Copy, Clone)] +pub struct LoopsPass; + +impl LintPass for LoopsPass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_RANGE_LOOP, + EXPLICIT_ITER_LOOP, + ITER_NEXT_LOOP, + WHILE_LET_LOOP, + UNUSED_COLLECT, + REVERSE_RANGE_LOOP, + EXPLICIT_COUNTER_LOOP, + EMPTY_LOOP, + WHILE_LET_ON_ITERATOR, + FOR_KV_MAP) + } +} + +impl LateLintPass for LoopsPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let Some((pat, arg, body)) = recover_for_loop(expr) { + check_for_loop(cx, pat, arg, body, expr); + } + // check for `loop { if let {} else break }` that could be `while let` + // (also matches an explicit "match" instead of "if let") + // (even if the "match" or "if let" is used for declaration) + if let ExprLoop(ref block, _) = expr.node { + // also check for empty `loop {}` statements + if block.stmts.is_empty() && block.expr.is_none() { + span_lint(cx, + EMPTY_LOOP, + expr.span, + "empty `loop {}` detected. You may want to either use `panic!()` or add \ + `std::thread::sleep(..);` to the loop body."); + } + + // extract the expression from the first statement (if any) in a block + let inner_stmt_expr = extract_expr_from_first_stmt(block); + // or extract the first expression (if any) from the block + if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) { + if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { + // ensure "if let" compatible match structure + match *source { + MatchSource::Normal | + MatchSource::IfLetDesugar { .. } => { + if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + is_break_expr(&arms[1].body) { + if in_external_macro(cx, expr.span) { + return; + } + + // NOTE: we used to make build a body here instead of using + // ellipsis, this was removed because: + // 1) it was ugly with big bodies; + // 2) it was not indented properly; + // 3) it wasn’t very smart (see #675). + span_lint_and_then(cx, + WHILE_LET_LOOP, + expr.span, + "this loop could be written as a `while let` loop", + |db| { + let sug = format!("while let {} = {} {{ .. }}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, matchexpr.span, "..")); + db.span_suggestion(expr.span, "try", sug); + }); + } + } + _ => (), + } + } + } + } + if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { + let pat = &arms[0].pats[0].node; + if let (&PatKind::TupleStruct(ref path, Some(ref pat_args)), + &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { + let iter_expr = &method_args[0]; + if let Some(lhs_constructor) = path.segments.last() { + if method_name.node.as_str() == "next" && + match_trait_method(cx, match_expr, &paths::ITERATOR) && + lhs_constructor.name.as_str() == "Some" && + !is_iterator_used_after_while_let(cx, iter_expr) { + let iterator = snippet(cx, method_args[0].span, "_"); + let loop_var = snippet(cx, pat_args[0].span, "_"); + span_help_and_lint(cx, + WHILE_LET_ON_ITERATOR, + expr.span, + "this loop could be written as a `for` loop", + &format!("try\nfor {} in {} {{...}}", loop_var, iterator)); + } + } + } + } + } + + fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { + if let StmtSemi(ref expr, _) = stmt.node { + if let ExprMethodCall(ref method, _, ref args) = expr.node { + if args.len() == 1 && method.node.as_str() == "collect" && + match_trait_method(cx, expr, &paths::ITERATOR) { + span_lint(cx, + UNUSED_COLLECT, + expr.span, + "you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator"); + } + } + } + } +} + +fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + check_for_loop_range(cx, pat, arg, body, expr); + check_for_loop_reverse_range(cx, arg, expr); + check_for_loop_arg(cx, pat, arg, expr); + check_for_loop_explicit_counter(cx, arg, body, expr); + check_for_loop_over_map_kv(cx, pat, arg, body, expr); +} + +/// Check for looping over a range and then indexing a sequence with it. +/// The iteratee must be a range literal. +fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(arg) { + // the var must be a single name + if let PatKind::Ident(_, ref ident, _) = pat.node { + let mut visitor = VarVisitor { + cx: cx, + var: ident.node, + indexed: HashMap::new(), + nonindex: false, + }; + walk_expr(&mut visitor, body); + + // linting condition: we only indexed one variable + if visitor.indexed.len() == 1 { + let (indexed, indexed_extent) = visitor.indexed + .into_iter() + .next() + .unwrap_or_else(|| unreachable!() /* len == 1 */); + + // ensure that the indexed variable was declared before the loop, see #601 + if let Some(indexed_extent) = indexed_extent { + let pat_extent = cx.tcx.region_maps.var_scope(pat.id); + if cx.tcx.region_maps.is_subscope_of(indexed_extent, pat_extent) { + return; + } + } + + let starts_at_zero = is_integer_literal(start, 0); + + let skip: Cow<_> = if starts_at_zero { + "".into() + } else { + format!(".skip({})", snippet(cx, start.span, "..")).into() + }; + + let take: Cow<_> = if let Some(ref end) = *end { + if is_len_call(end, &indexed) { + "".into() + } else { + format!(".take({})", snippet(cx, end.span, "..")).into() + } + } else { + "".into() + }; + + if visitor.nonindex { + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \ + item) in {}.iter().enumerate(){}{}` or similar iterators", + ident.node, + indexed, + ident.node, + indexed, + take, + skip)); + } else { + let repl = if starts_at_zero && take.is_empty() { + format!("&{}", indexed) + } else { + format!("{}.iter(){}{}", indexed, take, skip) + }; + + span_lint(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`. \ + Consider using `for item in {}` or similar iterators", + ident.node, + indexed, + repl)); + } + } + } + } +} + +fn is_len_call(expr: &Expr, var: &Name) -> bool { + if_let_chain! {[ + let ExprMethodCall(method, _, ref len_args) = expr.node, + len_args.len() == 1, + method.node.as_str() == "len", + let ExprPath(_, ref path) = len_args[0].node, + path.segments.len() == 1, + &path.segments[0].name == var + ], { + return true; + }} + + false +} + +fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { + // if this for loop is iterating over a two-sided range... + if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(arg) { + // ...and both sides are compile-time constant integers... + if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) { + if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) { + // ...and the start index is greater than the end index, + // this loop will never run. This is often confusing for developers + // who think that this will iterate from the larger value to the + // smaller value. + let (sup, eq) = match (start_idx, end_idx) { + (ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => { + (start_idx > end_idx, start_idx == end_idx) + } + _ => (false, false), + }; + + if sup { + let start_snippet = snippet(cx, start.span, "_"); + let end_snippet = snippet(cx, end.span, "_"); + + span_lint_and_then(cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run", + |db| { + db.span_suggestion(expr.span, + "consider using the following if \ + you are attempting to iterate \ + over this range in reverse", + format!("({}..{}).rev()` ", end_snippet, start_snippet)); + }); + } else if eq && limits != ast::RangeLimits::Closed { + // if they are equal, it's also problematic - this loop + // will never run. + span_lint(cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run"); + } + } + } + } +} + +fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { + let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used + if let ExprMethodCall(ref method, _, ref args) = arg.node { + // just the receiver, no arguments + if args.len() == 1 { + let method_name = method.node; + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x + if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { + if is_ref_iterable_type(cx, &args[0]) { + let object = snippet(cx, args[0].span, "_"); + span_lint(cx, + EXPLICIT_ITER_LOOP, + expr.span, + &format!("it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", + if method_name.as_str() == "iter_mut" { + "mut " + } else { + "" + }, + object, + object, + method_name)); + } + } else if method_name.as_str() == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { + span_lint(cx, + ITER_NEXT_LOOP, + expr.span, + "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ + probably not what you want"); + next_loop_linted = true; + } + } + } + if !next_loop_linted { + check_arg_type(cx, pat, arg); + } +} + +/// Check for `for` loops over `Option`s and `Results` +fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { + let ty = cx.tcx.expr_ty(arg); + if match_type(cx, ty, &paths::OPTION) { + span_help_and_lint(cx, + FOR_LOOP_OVER_OPTION, + arg.span, + &format!("for loop over `{0}`, which is an `Option`. This is more readably written as an \ + `if let` statement.", + snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_"))); + } else if match_type(cx, ty, &paths::RESULT) { + span_help_and_lint(cx, + FOR_LOOP_OVER_RESULT, + arg.span, + &format!("for loop over `{0}`, which is a `Result`. This is more readably written as an \ + `if let` statement.", + snippet(cx, arg.span, "_")), + &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_"))); + } +} + +fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { + // Look for variables that are incremented once per loop iteration. + let mut visitor = IncrementVisitor { + cx: cx, + states: HashMap::new(), + depth: 0, + done: false, + }; + walk_expr(&mut visitor, body); + + // For each candidate, check the parent block to see if + // it's initialized to zero at the start of the loop. + let map = &cx.tcx.map; + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id)); + if let Some(parent_id) = parent_scope { + if let NodeBlock(block) = map.get(parent_id) { + for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { + let mut visitor2 = InitializeVisitor { + cx: cx, + end_expr: expr, + var_id: *id, + state: VarState::IncrOnce, + name: None, + depth: 0, + past_loop: false, + }; + walk_block(&mut visitor2, block); + + if visitor2.state == VarState::Warn { + if let Some(name) = visitor2.name { + span_lint(cx, + EXPLICIT_COUNTER_LOOP, + expr.span, + &format!("the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ + item) in {1}.enumerate()` or similar iterators", + name, + snippet(cx, arg.span, "_"))); + } + } + } + } + } +} + +/// Check for the `FOR_KV_MAP` lint. +fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + if let PatKind::Tup(ref pat) = pat.node { + if pat.len() == 2 { + let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), + (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), + _ => return, + }; + + let arg_span = match arg.node { + ExprAddrOf(MutImmutable, ref expr) => expr.span, + ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method + _ => arg.span, + }; + + let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); + if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) { + span_lint_and_then(cx, + FOR_KV_MAP, + expr.span, + &format!("you seem to want to iterate on a map's {}", kind), + |db| { + db.span_suggestion(expr.span, + "use the corresponding method", + format!("for {} in {}.{}() {{...}}", + snippet(cx, *pat_span, ".."), + snippet(cx, arg_span, ".."), + kind)); + }); + } + } + } + +} + +/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. +fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { + match *pat { + PatKind::Wild => true, + PatKind::Ident(_, ident, None) if ident.node.as_str().starts_with('_') => { + let mut visitor = UsedVisitor { + var: ident.node, + used: false, + }; + walk_expr(&mut visitor, body); + !visitor.used + } + _ => false, + } +} + +struct UsedVisitor { + var: ast::Name, // var to look for + used: bool, // has the var been used otherwise? +} + +impl<'a> Visitor<'a> for UsedVisitor { + fn visit_expr(&mut self, expr: &Expr) { + if let ExprPath(None, ref path) = expr.node { + if path.segments.len() == 1 && path.segments[0].name == self.var { + self.used = true; + return; + } + } + + walk_expr(self, expr); + } +} + +struct VarVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, // context reference + var: Name, // var name to look for as index + indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global + nonindex: bool, // has the var been used otherwise? +} + +impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if let ExprPath(None, ref path) = expr.node { + if path.segments.len() == 1 && path.segments[0].name == self.var { + // we are referencing our variable! now check if it's as an index + if_let_chain! { + [ + let Some(parexpr) = get_parent_expr(self.cx, expr), + let ExprIndex(ref seqexpr, _) = parexpr.node, + let ExprPath(None, ref seqvar) = seqexpr.node, + seqvar.segments.len() == 1 + ], { + let def_map = self.cx.tcx.def_map.borrow(); + if let Some(def) = def_map.get(&seqexpr.id) { + match def.base_def { + Def::Local(..) | Def::Upvar(..) => { + let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); + return; // no need to walk further + } + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].name, None); + return; // no need to walk further + } + _ => (), + } + } + } + } + // we are not indexing anything, record that + self.nonindex = true; + return; + } + } + walk_expr(self, expr); + } +} + +fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool { + let def_id = match var_def_id(cx, iter_expr) { + Some(id) => id, + None => return false, + }; + let mut visitor = VarUsedAfterLoopVisitor { + cx: cx, + def_id: def_id, + iter_expr_id: iter_expr.id, + past_while_let: false, + var_used_after_while_let: false, + }; + if let Some(enclosing_block) = get_enclosing_block(cx, def_id) { + walk_block(&mut visitor, enclosing_block); + } + visitor.var_used_after_while_let +} + +struct VarUsedAfterLoopVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, + def_id: NodeId, + iter_expr_id: NodeId, + past_while_let: bool, + var_used_after_while_let: bool, +} + +impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if self.past_while_let { + if Some(self.def_id) == var_def_id(self.cx, expr) { + self.var_used_after_while_let = true; + } + } else if self.iter_expr_id == expr.id { + self.past_while_let = true; + } + walk_expr(self, expr); + } +} + + +/// Return true if the type of expr is one that provides `IntoIterator` impls +/// for `&T` and `&mut T`, such as `Vec`. +#[cfg_attr(rustfmt, rustfmt_skip)] +fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { + // no walk_ptrs_ty: calling iter() on a reference can make sense because it + // will allow further borrows afterwards + let ty = cx.tcx.expr_ty(e); + is_iterable_array(ty) || + match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::LINKED_LIST) || + match_type(cx, ty, &paths::HASHMAP) || + match_type(cx, ty, &paths::HASHSET) || + match_type(cx, ty, &paths::VEC_DEQUE) || + match_type(cx, ty, &paths::BINARY_HEAP) || + match_type(cx, ty, &paths::BTREEMAP) || + match_type(cx, ty, &paths::BTREESET) +} + +fn is_iterable_array(ty: ty::Ty) -> bool { + // IntoIterator is currently only implemented for array sizes <= 32 in rustc + match ty.sty { + ty::TyArray(_, 0...32) => true, + _ => false, + } +} + +/// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. +fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { + if block.stmts.is_empty() { + return None; + } + if let StmtDecl(ref decl, _) = block.stmts[0].node { + if let DeclLocal(ref local) = decl.node { + if let Some(ref expr) = local.init { + Some(expr) + } else { + None + } + } else { + None + } + } else { + None + } +} + +/// If a block begins with an expression (with or without semicolon), return it. +fn extract_first_expr(block: &Block) -> Option<&Expr> { + match block.expr { + Some(ref expr) => Some(expr), + None if !block.stmts.is_empty() => { + match block.stmts[0].node { + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => Some(expr), + _ => None, + } + } + _ => None, + } +} + +/// Return true if expr contains a single break expr (maybe within a block). +fn is_break_expr(expr: &Expr) -> bool { + match expr.node { + ExprBreak(None) => true, + // there won't be a `let <pat> = break` and so we can safely ignore the StmtDecl case + ExprBlock(ref b) => { + match extract_first_expr(b) { + Some(ref subexpr) => is_break_expr(subexpr), + None => false, + } + } + _ => false, + } +} + +// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be +// incremented exactly once in the loop body, and initialized to zero +// at the start of the loop. +#[derive(PartialEq)] +enum VarState { + Initial, // Not examined yet + IncrOnce, // Incremented exactly once, may be a loop counter + Declared, // Declared but not (yet) initialized to zero + Warn, + DontWarn, +} + +/// Scan a for loop for variables that are incremented exactly once. +struct IncrementVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, // context reference + states: HashMap<NodeId, VarState>, // incremented variables + depth: u32, // depth of conditional expressions + done: bool, +} + +impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { + fn visit_expr(&mut self, expr: &'v Expr) { + if self.done { + return; + } + + // If node is a variable + if let Some(def_id) = var_def_id(self.cx, expr) { + if let Some(parent) = get_parent_expr(self.cx, expr) { + let state = self.states.entry(def_id).or_insert(VarState::Initial); + + match parent.node { + ExprAssignOp(op, ref lhs, ref rhs) => { + if lhs.id == expr.id { + if op.node == BiAdd && is_integer_literal(rhs, 1) { + *state = match *state { + VarState::Initial if self.depth == 0 => VarState::IncrOnce, + _ => VarState::DontWarn, + }; + } else { + // Assigned some other value + *state = VarState::DontWarn; + } + } + } + ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, + ExprAddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn, + _ => (), + } + } + } else if is_loop(expr) { + self.states.clear(); + self.done = true; + return; + } else if is_conditional(expr) { + self.depth += 1; + walk_expr(self, expr); + self.depth -= 1; + return; + } + walk_expr(self, expr); + } +} + +/// Check whether a variable is initialized to zero at the start of a loop. +struct InitializeVisitor<'v, 't: 'v> { + cx: &'v LateContext<'v, 't>, // context reference + end_expr: &'v Expr, // the for loop. Stop scanning here. + var_id: NodeId, + state: VarState, + name: Option<Name>, + depth: u32, // depth of conditional expressions + past_loop: bool, +} + +impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { + fn visit_decl(&mut self, decl: &'v Decl) { + // Look for declarations of the variable + if let DeclLocal(ref local) = decl.node { + if local.pat.id == self.var_id { + if let PatKind::Ident(_, ref ident, _) = local.pat.node { + self.name = Some(ident.node); + + self.state = if let Some(ref init) = local.init { + if is_integer_literal(init, 0) { + VarState::Warn + } else { + VarState::Declared + } + } else { + VarState::Declared + } + } + } + } + walk_decl(self, decl); + } + + fn visit_expr(&mut self, expr: &'v Expr) { + if self.state == VarState::DontWarn { + return; + } + if expr == self.end_expr { + self.past_loop = true; + return; + } + // No need to visit expressions before the variable is + // declared + if self.state == VarState::IncrOnce { + return; + } + + // If node is the desired variable, see how it's used + if var_def_id(self.cx, expr) == Some(self.var_id) { + if let Some(parent) = get_parent_expr(self.cx, expr) { + match parent.node { + ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => { + self.state = VarState::DontWarn; + } + ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { + self.state = if is_integer_literal(rhs, 0) && self.depth == 0 { + VarState::Warn + } else { + VarState::DontWarn + } + } + ExprAddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn, + _ => (), + } + } + + if self.past_loop { + self.state = VarState::DontWarn; + return; + } + } else if !self.past_loop && is_loop(expr) { + self.state = VarState::DontWarn; + return; + } else if is_conditional(expr) { + self.depth += 1; + walk_expr(self, expr); + self.depth -= 1; + return; + } + walk_expr(self, expr); + } +} + +fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { + if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { + if let Def::Local(_, node_id) = path_res.base_def { + return Some(node_id); + } + } + None +} + +fn is_loop(expr: &Expr) -> bool { + match expr.node { + ExprLoop(..) | ExprWhile(..) => true, + _ => false, + } +} + +fn is_conditional(expr: &Expr) -> bool { + match expr.node { + ExprIf(..) | ExprMatch(..) => true, + _ => false, + } +} diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs new file mode 100644 index 00000000000..4ad232759cf --- /dev/null +++ b/clippy_lints/src/map_clone.rs @@ -0,0 +1,128 @@ +use rustc::lint::*; +use rustc::hir::*; +use syntax::ast; +use utils::{is_adjusted, match_path, match_trait_method, match_type, paths, snippet, + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; + +/// **What it does:** This lint checks for mapping clone() over an iterator. +/// +/// **Why is this bad?** It makes the code less readable. +/// +/// **Known problems:** None +/// +/// **Example:** `x.map(|e| e.clone());` +declare_lint! { + pub MAP_CLONE, Warn, + "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ + `.cloned()` instead)" +} + +#[derive(Copy, Clone)] +pub struct MapClonePass; + +impl LateLintPass for MapClonePass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // call to .map() + if let ExprMethodCall(name, _, ref args) = expr.node { + if name.node.as_str() == "map" && args.len() == 2 { + match args[1].node { + ExprClosure(_, ref decl, ref blk, _) => { + if_let_chain! { + [ + // just one expression in the closure + blk.stmts.is_empty(), + let Some(ref closure_expr) = blk.expr, + // nothing special in the argument, besides reference bindings + // (e.g. .map(|&x| x) ) + let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), + // the method is being called on a known type (option or iterator) + let Some(type_name) = get_type_name(cx, expr, &args[0]) + ], { + // look for derefs, for .map(|x| *x) + if only_derefs(cx, &*closure_expr, arg_ident) && + // .cloned() only removes one level of indirection, don't lint on more + walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + // explicit clone() calls ( .map(|x| x.clone()) ) + else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { + if clone_call.node.as_str() == "clone" && + clone_args.len() == 1 && + match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && + expr_eq_name(&clone_args[0], arg_ident) + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } + } + } + } + ExprPath(_, ref path) => { + if match_path(path, &paths::CLONE) { + let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); + span_help_and_lint(cx, + MAP_CLONE, + expr.span, + &format!("you seem to be using .map() to clone the contents of an \ + {}, consider using `.cloned()`", + type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } + _ => (), + } + } + } + } +} + +fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { + match expr.node { + ExprPath(None, ref path) => { + let arg_segment = [PathSegment { + name: id, + parameters: PathParameters::none(), + }]; + !path.global && path.segments[..] == arg_segment + } + _ => false, + } +} + +fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { + if match_trait_method(cx, expr, &paths::ITERATOR) { + Some("iterator") + } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) { + Some("Option") + } else { + None + } +} + +fn get_arg_name(pat: &Pat) -> Option<ast::Name> { + match pat.node { + PatKind::Ident(_, name, None) => Some(name.node), + PatKind::Ref(ref subpat, _) => get_arg_name(subpat), + _ => None, + } +} + +fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { + match expr.node { + ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), + _ => expr_eq_name(expr, id), + } +} + +impl LintPass for MapClonePass { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_CLONE) + } +} diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs new file mode 100644 index 00000000000..db4ccf2dcdb --- /dev/null +++ b/clippy_lints/src/matches.rs @@ -0,0 +1,483 @@ +use rustc::hir::*; +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_math::ConstInt; +use std::cmp::Ordering; +use syntax::ast::LitKind; +use syntax::codemap::Span; +use utils::paths; +use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; + +/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. +/// +/// **Why is this bad?** Just readability – `if let` nests less than a `match`. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// match x { +/// Some(ref foo) -> bar(foo), +/// _ => () +/// } +/// ``` +declare_lint! { + pub SINGLE_MATCH, Warn, + "a match statement with a single nontrivial arm (i.e, where the other arm \ + is `_ => {}`) is used; recommends `if let` instead" +} + +/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. +/// +/// **Why is this bad?** Just readability – `if let` nests less than a `match`. +/// +/// **Known problems:** Personal style preferences may differ +/// +/// **Example:** +/// ``` +/// match x { +/// Some(ref foo) -> bar(foo), +/// _ => bar(other_ref), +/// } +/// ``` +declare_lint! { + pub SINGLE_MATCH_ELSE, Allow, + "a match statement with a two arms where the second arm's pattern is a wildcard; \ + recommends `if let` instead" +} + +/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. +/// +/// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// match x { +/// &A(ref y) => foo(y), +/// &B => bar(), +/// _ => frob(&x), +/// } +/// ``` +declare_lint! { + pub MATCH_REF_PATS, Warn, + "a match or `if let` has all arms prefixed with `&`; the match expression can be \ + dereferenced instead" +} + +/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. +/// +/// **Why is this bad?** It makes the code less readable. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let condition: bool = true; +/// match condition { +/// true => foo(), +/// false => bar(), +/// } +/// ``` +declare_lint! { + pub MATCH_BOOL, Warn, + "a match on boolean expression; recommends `if..else` block instead" +} + +/// **What it does:** This lint checks for overlapping match arms. +/// +/// **Why is this bad?** It is likely to be an error and if not, makes the code less obvious. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let x = 5; +/// match x { +/// 1 ... 10 => println!("1 ... 10"), +/// 5 ... 15 => println!("5 ... 15"), +/// _ => (), +/// } +/// ``` +declare_lint! { + pub MATCH_OVERLAPPING_ARM, Warn, "a match has overlapping arms" +} + +#[allow(missing_copy_implementations)] +pub struct MatchPass; + +impl LintPass for MatchPass { + fn get_lints(&self) -> LintArray { + lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL, SINGLE_MATCH_ELSE) + } +} + +impl LateLintPass for MatchPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_external_macro(cx, expr.span) { + return; + } + if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { + check_single_match(cx, ex, arms, expr); + check_match_bool(cx, ex, arms, expr); + check_overlapping_arms(cx, ex, arms); + } + if let ExprMatch(ref ex, ref arms, source) = expr.node { + check_match_ref_pats(cx, ex, arms, source, expr); + } + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + if arms.len() == 2 && + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() { + let els = if is_unit_expr(&arms[1].body) { + None + } else if let ExprBlock(_) = arms[1].body.node { + // matches with blocks that contain statements are prettier as `if let + else` + Some(&*arms[1].body) + } else { + // allow match arms with just expressions + return; + }; + let ty = cx.tcx.expr_ty(ex); + if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { + check_single_match_single_pattern(cx, ex, arms, expr, els); + check_single_match_opt_like(cx, ex, arms, expr, ty, els); + } + } +} + +fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { + if arms[1].pats[0].node == PatKind::Wild { + let lint = if els.is_some() { + SINGLE_MATCH_ELSE + } else { + SINGLE_MATCH + }; + let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); + span_lint_and_then(cx, + lint, + expr.span, + "you seem to be trying to use match for destructuring a single pattern. \ + Consider using `if let`", + |db| { + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); + } +} + +fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) { + // list of candidate Enums we know will never get any more members + let candidates = &[(&paths::COW, "Borrowed"), + (&paths::COW, "Cow::Borrowed"), + (&paths::COW, "Cow::Owned"), + (&paths::COW, "Owned"), + (&paths::OPTION, "None"), + (&paths::RESULT, "Err"), + (&paths::RESULT, "Ok")]; + + let path = match arms[1].pats[0].node { + PatKind::TupleStruct(ref path, Some(ref inner)) => { + // contains any non wildcard patterns? e.g. Err(err) + if inner.iter().any(|pat| pat.node != PatKind::Wild) { + return; + } + path.to_string() + } + PatKind::TupleStruct(ref path, None) => path.to_string(), + PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), + _ => return, + }; + + for &(ty_path, pat_path) in candidates { + if &path == pat_path && match_type(cx, ty, ty_path) { + let lint = if els.is_some() { + SINGLE_MATCH_ELSE + } else { + SINGLE_MATCH + }; + let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); + span_lint_and_then(cx, + lint, + expr.span, + "you seem to be trying to use match for destructuring a single pattern. Consider \ + using `if let`", + |db| { + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); + } + } +} + +fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + // type of expression == bool + if cx.tcx.expr_ty(ex).sty == ty::TyBool { + let sugg = if arms.len() == 2 && arms[0].pats.len() == 1 { + // no guards + let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { + if let ExprLit(ref lit) = arm_bool.node { + match lit.node { + LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), + _ => None, + } + } else { + None + } + } else { + None + }; + + if let Some((ref true_expr, ref false_expr)) = exprs { + match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { + (false, false) => { + Some(format!("if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))) + } + (false, true) => { + Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) + } + (true, false) => { + Some(format!("try\nif !{} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, false_expr, None, ".."))) + } + (true, true) => None, + } + } else { + None + } + } else { + None + }; + + span_lint_and_then(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression. Consider using an if..else block:", + move |db| { + if let Some(sugg) = sugg { + db.span_suggestion(expr.span, "try this", sugg); + } + }); + } +} + +fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { + if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() { + let ranges = all_ranges(cx, arms); + let type_ranges = type_ranges(&ranges); + if !type_ranges.is_empty() { + if let Some((start, end)) = overlapping(&type_ranges) { + span_note_and_lint(cx, + MATCH_OVERLAPPING_ARM, + start.span, + "some ranges overlap", + end.span, + "overlaps with this"); + } + } + } +} + +fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { + if has_only_ref_pats(arms) { + if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + let template = match_template(cx, expr.span, source, "", inner); + span_lint_and_then(cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to both the expression and the patterns", + |db| { + db.span_suggestion(expr.span, "try", template); + }); + } else { + let template = match_template(cx, expr.span, source, "*", ex); + span_lint_and_then(cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to all patterns", + |db| { + db.span_suggestion(expr.span, + "instead of prefixing all patterns with `&`, you can \ + dereference the expression", + template); + }); + } + } +} + +/// Get all arms that are unbounded `PatRange`s. +fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { + arms.iter() + .filter_map(|arm| { + if let Arm { ref pats, guard: None, .. } = *arm { + Some(pats.iter().filter_map(|pat| { + if_let_chain! {[ + let PatKind::Range(ref lhs, ref rhs) = pat.node, + let Ok(lhs) = eval_const_expr_partial(cx.tcx, &lhs, ExprTypeChecked, None), + let Ok(rhs) = eval_const_expr_partial(cx.tcx, &rhs, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); + }} + + if_let_chain! {[ + let PatKind::Lit(ref value) = pat.node, + let Ok(value) = eval_const_expr_partial(cx.tcx, &value, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); + }} + + None + })) + } else { + None + } + }) + .flat_map(IntoIterator::into_iter) + .collect() +} + +#[derive(Debug, Eq, PartialEq)] +pub struct SpannedRange<T> { + pub span: Span, + pub node: (T, T), +} + +type TypedRanges = Vec<SpannedRange<ConstInt>>; + +/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than +/// `Uint` and `Int` probably don't make sense. +fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { + ranges.iter() + .filter_map(|range| { + if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None + } + }) + .collect() +} + +fn is_unit_expr(expr: &Expr) -> bool { + match expr.node { + ExprTup(ref v) if v.is_empty() => true, + ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, + _ => false, + } +} + +fn has_only_ref_pats(arms: &[Arm]) -> bool { + let mapped = arms.iter() + .flat_map(|a| &a.pats) + .map(|p| { + match p.node { + PatKind::Ref(..) => Some(true), // &-patterns + PatKind::Wild => Some(false), // an "anything" wildcard is also fine + _ => None, // any other pattern is not fine + } + }) + .collect::<Option<Vec<bool>>>(); + // look for Some(v) where there's at least one true element + mapped.map_or(false, |v| v.iter().any(|el| *el)) +} + +fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, expr: &Expr) -> String { + let expr_snippet = snippet(cx, expr.span, ".."); + match source { + MatchSource::Normal => format!("match {}{} {{ .. }}", op, expr_snippet), + MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), + MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), + MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), + MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"), + } +} + +pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> + where T: Copy + Ord +{ + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + enum Kind<'a, T: 'a> { + Start(T, &'a SpannedRange<T>), + End(T, &'a SpannedRange<T>), + } + + impl<'a, T: Copy> Kind<'a, T> { + fn range(&self) -> &'a SpannedRange<T> { + match *self { + Kind::Start(_, r) | + Kind::End(_, r) => r, + } + } + + fn value(self) -> T { + match self { + Kind::Start(t, _) | + Kind::End(t, _) => t, + } + } + } + + impl<'a, T: Copy + Ord> PartialOrd for Kind<'a, T> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } + } + + impl<'a, T: Copy + Ord> Ord for Kind<'a, T> { + fn cmp(&self, other: &Self) -> Ordering { + self.value().cmp(&other.value()) + } + } + + let mut values = Vec::with_capacity(2 * ranges.len()); + + for r in ranges { + values.push(Kind::Start(r.node.0, r)); + values.push(Kind::End(r.node.1, r)); + } + + values.sort(); + + for (a, b) in values.iter().zip(values.iter().skip(1)) { + match (a, b) { + (&Kind::Start(_, ra), &Kind::End(_, rb)) => { + if ra.node != rb.node { + return Some((ra, rb)); + } + } + (&Kind::End(a, _), &Kind::Start(b, _)) if a != b => (), + _ => return Some((a.range(), b.range())), + } + } + + None +} diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs new file mode 100644 index 00000000000..1f627d614ff --- /dev/null +++ b/clippy_lints/src/mem_forget.rs @@ -0,0 +1,44 @@ +use rustc::lint::*; +use rustc::hir::{Expr, ExprCall, ExprPath}; +use utils::{match_def_path, paths, span_lint}; + +/// **What it does:** This lint checks for usage of `std::mem::forget(t)` where `t` is `Drop`. +/// +/// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its destructor, possibly causing leaks +/// +/// **Known problems:** None. +/// +/// **Example:** `mem::forget(Rc::new(55)))` +declare_lint! { + pub MEM_FORGET, + Allow, + "`mem::forget` usage on `Drop` types is likely to cause memory leaks" +} + +pub struct MemForget; + +impl LintPass for MemForget { + fn get_lints(&self) -> LintArray { + lint_array![MEM_FORGET] + } +} + +impl LateLintPass for MemForget { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprCall(ref path_expr, ref args) = e.node { + if let ExprPath(None, _) = path_expr.node { + let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + if match_def_path(cx, def_id, &paths::MEM_FORGET) { + let forgot_ty = cx.tcx.expr_ty(&args[0]); + + if match forgot_ty.ty_adt_def() { + Some(def) => def.has_dtor(), + _ => false + } { + span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); + } + } + } + } + } +} diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs new file mode 100644 index 00000000000..f9f557e7a9a --- /dev/null +++ b/clippy_lints/src/methods.rs @@ -0,0 +1,1049 @@ +use rustc::hir; +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc::middle::const_qualif::ConstQualif; +use rustc::ty::subst::{Subst, TypeSpace}; +use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use std::borrow::Cow; +use std::fmt; +use syntax::codemap::Span; +use syntax::ptr::P; +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, + match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, + span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; +use utils::MethodArgs; +use utils::paths; + +#[derive(Clone)] +pub struct MethodsPass; + +/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. +/// +/// **Why is this bad?** Usually it is better to handle the `None` case, or to at least call `.expect(_)` with a more helpful message. Still, for a lot of quick-and-dirty code, `unwrap` is a good choice, which is why this lint is `Allow` by default. +/// +/// **Known problems:** None +/// +/// **Example:** `x.unwrap()` +declare_lint! { + pub OPTION_UNWRAP_USED, Allow, + "using `Option.unwrap()`, which should at least get a better message using `expect()`" +} + +/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. +/// +/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`. +/// +/// Even if you want to panic on errors, not all `Error`s implement good messages on display. Therefore it may be beneficial to look at the places where they may get displayed. Activate this lint to do just that. +/// +/// **Known problems:** None +/// +/// **Example:** `x.unwrap()` +declare_lint! { + pub RESULT_UNWRAP_USED, Allow, + "using `Result.unwrap()`, which might be better handled" +} + +/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. +/// +/// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ``` +/// struct X; +/// impl X { +/// fn add(&self, other: &X) -> X { .. } +/// } +/// ``` +declare_lint! { + pub SHOULD_IMPLEMENT_TRAIT, Warn, + "defining a method that should be implementing a std trait" +} + +/// **What it does:** This lint checks for methods with certain name prefixes and which doesn't match how self is taken. The actual rules are: +/// +/// |Prefix |`self` taken | +/// |-------|--------------------| +/// |`as_` |`&self` or &mut self| +/// |`from_`| none | +/// |`into_`|`self` | +/// |`is_` |`&self` or none | +/// |`to_` |`&self` | +/// +/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_..` function. +/// +/// **Known problems:** None +/// +/// **Example** +/// +/// ``` +/// impl X { +/// fn as_str(self) -> &str { .. } +/// } +/// ``` +declare_lint! { + pub WRONG_SELF_CONVENTION, Warn, + "defining a method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} + +/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. +/// +/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). +/// +/// **Known problems:** Actually *renaming* the function may break clients if the function is part of the public interface. In that case, be mindful of the stability guarantees you've given your users. +/// +/// **Example:** +/// ``` +/// impl X { +/// pub fn as_str(self) -> &str { .. } +/// } +/// ``` +declare_lint! { + pub WRONG_PUB_SELF_CONVENTION, Allow, + "defining a public method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} + +/// **What it does:** This lint checks for usage of `ok().expect(..)`. +/// +/// **Why is this bad?** Because you usually call `expect()` on the `Result` directly to get a good error message. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.ok().expect("why did I do this again?")` +declare_lint! { + pub OK_EXPECT, Warn, + "using `ok().expect()`, which gives worse error messages than \ + calling `expect` directly on the Result" +} + +/// **What it does:** This lint checks for usage of `_.map(_).unwrap_or(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.map(|a| a + 1).unwrap_or(0)` +declare_lint! { + pub OPTION_MAP_UNWRAP_OR, Warn, + "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ + `map_or(a, f)`" +} + +/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or_else(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)` +declare_lint! { + pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, + "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `map_or_else(g, f)`" +} + +/// **What it does:** This lint `Warn`s on `_.filter(_).next()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.find(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `iter.filter(|x| x == 0).next()` +declare_lint! { + pub FILTER_NEXT, Warn, + "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" +} + +/// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or +/// `rposition()`) followed by a call to `is_some()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.any(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `iter.find(|x| x == 0).is_some()` +declare_lint! { + pub SEARCH_IS_SOME, Warn, + "using an iterator search followed by `is_some()`, which is more succinctly \ + expressed as a call to `any()`" +} + +/// **What it does:** This lint `Warn`s on using `.chars().next()` on a `str` to check if it +/// starts with a given char. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.starts_with(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** `name.chars().next() == Some('_')` +declare_lint! { + pub CHARS_NEXT_CMP, Warn, + "using `.chars().next()` to check if a string starts with a char" +} + +/// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and +/// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead. +/// +/// **Why is this bad?** The function will always be called and potentially allocate an object +/// in expressions such as: +/// ```rust +/// foo.unwrap_or(String::new()) +/// ``` +/// this can instead be written: +/// ```rust +/// foo.unwrap_or_else(String::new) +/// ``` +/// or +/// ```rust +/// foo.unwrap_or_default() +/// ``` +/// +/// **Known problems:** If the function as side-effects, not calling it will change the semantic of +/// the program, but you shouldn't rely on that anyway. +declare_lint! { + pub OR_FUN_CALL, Warn, + "using any `*or` method when the `*or_else` would do" +} + +/// **What it does:** This lint checks for usage of `.extend(s)` on a `Vec` to extend the vector by a slice. +/// +/// **Why is this bad?** Since Rust 1.6, the `extend_from_slice(_)` method is stable and at least for now faster. +/// +/// **Known problems:** None. +/// +/// **Example:** `my_vec.extend(&xs)` +declare_lint! { + pub EXTEND_FROM_SLICE, Warn, + "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice" +} + +/// **What it does:** This lint warns on using `.clone()` on a `Copy` type. +/// +/// **Why is this bad?** The only reason `Copy` types implement `Clone` is for generics, not for +/// using the `clone` method on a concrete type. +/// +/// **Known problems:** None. +/// +/// **Example:** `42u64.clone()` +declare_lint! { + pub CLONE_ON_COPY, Warn, "using `clone` on a `Copy` type" +} + +/// **What it does:** This lint warns on using `.clone()` on an `&&T` +/// +/// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of cloning the underlying +/// `T` +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn main() { +/// let x = vec![1]; +/// let y = &&x; +/// let z = y.clone(); +/// println!("{:p} {:p}",*y, z); // prints out the same pointer +/// } +/// ``` +declare_lint! { + pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`" +} + +/// **What it does:** This lint warns about `new` not returning `Self`. +/// +/// **Why is this bad?** As a convention, `new` methods are used to make a new instance of a type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl Foo { +/// fn new(..) -> NotAFoo { +/// } +/// } +/// ``` +declare_lint! { + pub NEW_RET_NO_SELF, Warn, "not returning `Self` in a `new` method" +} + +/// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")`. +/// +/// **Why is this bad?** Performing these methods using a `char` is faster than using a `str`. +/// +/// **Known problems:** Does not catch multi-byte unicode characters. +/// +/// **Example:** `_.split("x")` could be `_.split('x')` +declare_lint! { + pub SINGLE_CHAR_PATTERN, + Warn, + "using a single-character str where a char could be used, e.g. \ + `_.split(\"x\")`" +} + +/// **What it does:** This lint checks for getting the inner pointer of a temporary `CString`. +/// +/// **Why is this bad?** The inner pointer of a `CString` is only valid as long as the `CString` is +/// alive. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap().as_ptr(); +/// unsafe { +/// call_some_ffi_func(c_str); +/// } +/// ``` +/// Here `c_str` point to a freed address. The correct use would be: +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap(); +/// unsafe { +/// call_some_ffi_func(c_str.as_ptr()); +/// } +/// ``` +declare_lint! { + pub TEMPORARY_CSTRING_AS_PTR, + Warn, + "getting the inner pointer of a temporary `CString`" +} + +impl LintPass for MethodsPass { + fn get_lints(&self) -> LintArray { + lint_array!(EXTEND_FROM_SLICE, + OPTION_UNWRAP_USED, + RESULT_UNWRAP_USED, + SHOULD_IMPLEMENT_TRAIT, + WRONG_SELF_CONVENTION, + WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, + OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE, + OR_FUN_CALL, + CHARS_NEXT_CMP, + CLONE_ON_COPY, + CLONE_DOUBLE_REF, + NEW_RET_NO_SELF, + SINGLE_CHAR_PATTERN, + SEARCH_IS_SOME, + TEMPORARY_CSTRING_AS_PTR) + } +} + +impl LateLintPass for MethodsPass { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + if in_macro(cx, expr.span) { + return; + } + + match expr.node { + hir::ExprMethodCall(name, _, ref args) => { + // Chain calls + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + lint_unwrap(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { + lint_ok_expect(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { + lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { + lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { + lint_filter_next(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { + lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { + lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { + lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { + lint_extend(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { + lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); + } + + lint_or_fun_call(cx, expr, &name.node.as_str(), args); + + let self_ty = cx.tcx.expr_ty_adjusted(&args[0]); + if args.len() == 1 && name.node.as_str() == "clone" { + lint_clone_on_copy(cx, expr); + lint_clone_double_ref(cx, expr, &args[0], self_ty); + } + + match self_ty.sty { + ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => { + for &(method, pos) in &PATTERN_METHODS { + if name.node.as_str() == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); + } + } + } + _ => (), + } + } + hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { + if !lint_chars_next(cx, expr, lhs, rhs, op.node == hir::BiEq) { + lint_chars_next(cx, expr, rhs, lhs, op.node == hir::BiEq); + } + } + _ => (), + } + } + + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { + if in_external_macro(cx, item.span) { + return; + } + + if let hir::ItemImpl(_, _, _, None, _, ref items) = item.node { + for implitem in items { + let name = implitem.name; + if_let_chain! {[ + let hir::ImplItemKind::Method(ref sig, _) = implitem.node, + let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), + ], { + // check missing trait implementations + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if name.as_str() == method_name && + sig.decl.inputs.len() == n_args && + out_type.matches(&sig.decl.output) && + self_kind.matches(&explicit_self, false) { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } + } + + // check conventions w.r.t. conversion method names and predicates + let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; + let is_copy = is_copy(cx, ty, item); + for &(ref conv, self_kinds) in &CONVENTIONS { + if_let_chain! {[ + conv.check(&name.as_str()), + let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), + !self_kinds.iter().any(|k| k.matches(&explicit_self, is_copy)), + ], { + let lint = if item.vis == hir::Visibility::Public { + WRONG_PUB_SELF_CONVENTION + } else { + WRONG_SELF_CONVENTION + }; + span_lint(cx, + lint, + explicit_self.span, + &format!("methods called `{}` usually take {}; consider choosing a less \ + ambiguous name", + conv, + &self_kinds.iter() + .map(|k| k.description()) + .collect::<Vec<_>>() + .join(" or "))); + }} + } + + let ret_ty = return_ty(cx, implitem.id); + if &name.as_str() == &"new" && + !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { + span_lint(cx, + NEW_RET_NO_SELF, + explicit_self.span, + "methods called `new` usually return `Self`"); + } + } + }} + } + } +} + +/// Checks for the `OR_FUN_CALL` lint. +fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hir::Expr>]) { + /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. + fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, + or_has_args: bool, span: Span) + -> bool { + if or_has_args { + return false; + } + + if name == "unwrap_or" { + if let hir::ExprPath(_, ref path) = fun.node { + let path: &str = &path.segments + .last() + .expect("A path must have at least one segment") + .name + .as_str(); + + if ["default", "new"].contains(&path) { + let arg_ty = cx.tcx.expr_ty(arg); + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { + default_trait_id + } else { + return false; + }; + + if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) { + span_lint(cx, + OR_FUN_CALL, + span, + &format!("use of `{}` followed by a call to `{}`", name, path)) + .span_suggestion(span, + "try this", + format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); + return true; + } + } + } + } + + false + } + + /// Check for `*or(foo())`. + fn check_general_case(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, + span: Span) { + // don't lint for constant values + // FIXME: can we `expect` here instead of match? + if let Some(qualif) = cx.tcx.const_qualif_map.borrow().get(&arg.id) { + if !qualif.contains(ConstQualif::NOT_CONST) { + return; + } + } + // (path, fn_has_argument, methods, suffix) + let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, + false, + &["map_or", "ok_or", "or", "unwrap_or"], + "else"), + (&paths::RESULT, true, &["or", "unwrap_or"], "else")]; + + let self_ty = cx.tcx.expr_ty(self_expr); + + let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = + know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) { + (fn_has_arguments, poss, suffix) + } else { + return; + }; + + if !poss.contains(&name) { + return; + } + + let sugg: Cow<_> = match (fn_has_arguments, !or_has_args) { + (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), + (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), + (false, true) => snippet(cx, fun.span, ".."), + }; + + span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) + .span_suggestion(span, + "try this", + format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); + } + + if args.len() == 2 { + if let hir::ExprCall(ref fun, ref or_args) = args[1].node { + let or_has_args = !or_args.is_empty(); + if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { + check_general_case(cx, name, fun, &args[0], &args[1], or_has_args, expr.span); + } + } + } +} + +/// Checks for the `CLONE_ON_COPY` lint. +fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) { + let ty = cx.tcx.expr_ty(expr); + let parent = cx.tcx.map.get_parent(expr.id); + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); + + if !ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, expr.span) { + span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); + } +} + +/// Checks for the `CLONE_DOUBLE_REF` lint. +fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) { + if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { + if let ty::TyRef(..) = inner.sty { + let mut db = span_lint(cx, + CLONE_DOUBLE_REF, + expr.span, + "using `clone` on a double-reference; \ + this will copy the reference instead of cloning \ + the inner type"); + if let Some(snip) = snippet_opt(cx, arg.span) { + db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); + } + } + } +} + +fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); + if !match_type(cx, obj_ty, &paths::VEC) { + return; + } + let arg_ty = cx.tcx.expr_ty(&args[1]); + if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { + span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice") + .span_suggestion(expr.span, + "try this", + format!("{}.extend_from_slice({}{})", + snippet(cx, args[0].span, "_"), + r, + snippet(cx, span, "_"))); + } +} + +fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { + if_let_chain!{[ + let hir::ExprCall(ref fun, ref args) = new.node, + args.len() == 1, + let hir::ExprPath(None, ref path) = fun.node, + match_path(path, &paths::CSTRING_NEW), + ], { + span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, + "you are getting the inner pointer of a temporary `CString`", + |db| { + db.note("that pointer will be invalid outside this expression"); + db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); + }); + }} +} + +fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { + fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { + match ty.sty { + ty::TySlice(_) => true, + ty::TyStruct(..) => match_type(cx, ty, &paths::VEC), + ty::TyArray(_, size) => size < 32, + ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | + ty::TyBox(ref inner) => may_slice(cx, inner), + _ => false, + } + } + if let hir::ExprMethodCall(name, _, ref args) = expr.node { + if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { + Some((args[0].span, "&")) + } else { + None + } + } else { + match ty.sty { + ty::TySlice(_) => Some((expr.span, "")), + ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | + ty::TyBox(ref inner) => { + if may_slice(cx, inner) { + Some((expr.span, "")) + } else { + None + } + } + _ => None, + } + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint use of `unwrap()` for `Option`s and `Result`s +fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); + + let mess = if match_type(cx, obj_ty, &paths::OPTION) { + Some((OPTION_UNWRAP_USED, "an Option", "None")) + } else if match_type(cx, obj_ty, &paths::RESULT) { + Some((RESULT_UNWRAP_USED, "a Result", "Err")) + } else { + None + }; + + if let Some((lint, kind, none_value)) = mess { + span_lint(cx, + lint, + expr.span, + &format!("used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ + using expect() to provide a better panic + message", + kind, + none_value)); + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint use of `ok().expect()` for `Result`s +fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) { + // lint if the caller of `ok()` is a `Result` + if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) { + let result_type = cx.tcx.expr_ty(&ok_args[0]); + if let Some(error_type) = get_error_type(cx, result_type) { + if has_debug_impl(error_type, cx) { + span_lint(cx, + OK_EXPECT, + expr.span, + "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`"); + } + } + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint use of `map().unwrap_or()` for `Option`s +fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { + // lint if the caller of `map()` is an `Option` + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { + // lint message + let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ + `map_or(a, f)` instead"; + // get snippets for args to map() and unwrap_or() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or() have the same span + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint(cx, + OPTION_MAP_UNWRAP_OR, + expr.span, + msg, + expr.span, + &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", + map_snippet, + unwrap_snippet)); + } else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); + }; + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint use of `map().unwrap_or_else()` for `Option`s +fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { + // lint if the caller of `map()` is an `Option` + if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { + // lint message + let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ + `map_or_else(g, f)` instead"; + // get snippets for args to map() and unwrap_or_else() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or_else() have the same span + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; + if same_span && !multiline { + span_note_and_lint(cx, + OPTION_MAP_UNWRAP_OR_ELSE, + expr.span, + msg, + expr.span, + &format!("replace `map({0}).unwrap_or_else({1})` with `with map_or_else({1}, {0})`", + map_snippet, + unwrap_snippet)); + } else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); + }; + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint use of `filter().next() for Iterators` +fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs) { + // lint if caller of `.filter().next()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ + instead."; + let filter_snippet = snippet(cx, filter_args[1].span, ".."); + if filter_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint(cx, + FILTER_NEXT, + expr.span, + msg, + expr.span, + &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); + } else { + span_lint(cx, FILTER_NEXT, expr.span, msg); + } + } +} + +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +/// lint searching an Iterator followed by `is_some()` +fn lint_search_is_some(cx: &LateContext, expr: &hir::Expr, search_method: &str, search_args: &MethodArgs, + is_some_args: &MethodArgs) { + // lint if caller of search is an Iterator + if match_trait_method(cx, &*is_some_args[0], &paths::ITERATOR) { + let msg = format!("called `is_some()` after searching an iterator with {}. This is more succinctly expressed \ + by calling `any()`.", + search_method); + let search_snippet = snippet(cx, search_args[1].span, ".."); + if search_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint(cx, + SEARCH_IS_SOME, + expr.span, + &msg, + expr.span, + &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet)); + } else { + span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); + } + } +} + +/// Checks for the `CHARS_NEXT_CMP` lint. +fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: &hir::Expr, eq: bool) -> bool { + if_let_chain! {[ + let Some(args) = method_chain_args(chain, &["chars", "next"]), + let hir::ExprCall(ref fun, ref arg_char) = other.node, + arg_char.len() == 1, + let hir::ExprPath(None, ref path) = fun.node, + path.segments.len() == 1 && path.segments[0].name.as_str() == "Some" + ], { + let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0])); + + if self_ty.sty != ty::TyStr { + return false; + } + + span_lint_and_then(cx, + CHARS_NEXT_CMP, + expr.span, + "you should use the `starts_with` method", + |db| { + let sugg = format!("{}{}.starts_with({})", + if eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + snippet(cx, arg_char[0].span, "_") + ); + + db.span_suggestion(expr.span, "like this", sugg); + }); + + return true; + }} + + false +} + +/// lint for length-1 `str`s for methods in `PATTERN_METHODS` +fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { + if let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, arg, ExprTypeChecked, None) { + if r.len() == 1 { + let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); + span_lint_and_then(cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + |db| { + db.span_suggestion(expr.span, "try using a char instead:", hint); + }); + } + } +} + +/// Given a `Result<T, E>` type, return its error type (`E`). +fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { + if !match_type(cx, ty, &paths::RESULT) { + return None; + } + if let ty::TyEnum(_, substs) = ty.sty { + if let Some(err_ty) = substs.types.opt_get(TypeSpace, 1) { + return Some(err_ty); + } + } + None +} + +/// This checks whether a given type is known to implement Debug. +fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { + match cx.tcx.lang_items.debug_trait() { + Some(debug) => implements_trait(cx, ty, debug, Vec::new()), + None => false, + } +} + +enum Convention { + Eq(&'static str), + StartsWith(&'static str), +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [ + (Convention::Eq("new"), &[SelfKind::No]), + (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), + (Convention::StartsWith("from_"), &[SelfKind::No]), + (Convention::StartsWith("into_"), &[SelfKind::Value]), + (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), + (Convention::StartsWith("to_"), &[SelfKind::Ref]), +]; + +#[cfg_attr(rustfmt, rustfmt_skip)] +const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ + ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), + ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), + ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), + ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), + ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), + ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), + ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), + ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), + ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), + ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), + ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), + ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), + ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), + ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), + ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), + ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), + ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), + ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), + ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), + ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), + ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), + ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), + ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), + ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), + ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), + ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), + ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), + ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), +]; + +#[cfg_attr(rustfmt, rustfmt_skip)] +const PATTERN_METHODS: [(&'static str, usize); 17] = [ + ("contains", 1), + ("starts_with", 1), + ("ends_with", 1), + ("find", 1), + ("rfind", 1), + ("split", 1), + ("rsplit", 1), + ("split_terminator", 1), + ("rsplit_terminator", 1), + ("splitn", 2), + ("rsplitn", 2), + ("matches", 1), + ("rmatches", 1), + ("match_indices", 1), + ("rmatch_indices", 1), + ("trim_left_matches", 1), + ("trim_right_matches", 1), +]; + + +#[derive(Clone, Copy)] +enum SelfKind { + Value, + Ref, + RefMut, + No, +} + +impl SelfKind { + fn matches(self, slf: &hir::ExplicitSelf, allow_value_for_ref: bool) -> bool { + match (self, &slf.node) { + (SelfKind::Value, &hir::SelfKind::Value(_)) | + (SelfKind::Ref, &hir::SelfKind::Region(_, hir::Mutability::MutImmutable)) | + (SelfKind::RefMut, &hir::SelfKind::Region(_, hir::Mutability::MutMutable)) => true, + (SelfKind::Ref, &hir::SelfKind::Value(_)) | + (SelfKind::RefMut, &hir::SelfKind::Value(_)) => allow_value_for_ref, + (_, &hir::SelfKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), + + _ => false, + } + } + + fn matches_explicit_type(self, ty: &hir::Ty, allow_value_for_ref: bool) -> bool { + match (self, &ty.node) { + (SelfKind::Value, &hir::TyPath(..)) | + (SelfKind::Ref, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutImmutable, .. })) | + (SelfKind::RefMut, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutMutable, .. })) => true, + (SelfKind::Ref, &hir::TyPath(..)) | + (SelfKind::RefMut, &hir::TyPath(..)) => allow_value_for_ref, + _ => false, + } + } + + fn description(&self) -> &'static str { + match *self { + SelfKind::Value => "self by value", + SelfKind::Ref => "self by reference", + SelfKind::RefMut => "self by mutable reference", + SelfKind::No => "no self", + } + } +} + +impl Convention { + fn check(&self, other: &str) -> bool { + match *self { + Convention::Eq(this) => this == other, + Convention::StartsWith(this) => other.starts_with(this), + } + } +} + +impl fmt::Display for Convention { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Convention::Eq(this) => this.fmt(f), + Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), + } + } +} + +#[derive(Clone, Copy)] +enum OutType { + Unit, + Bool, + Any, + Ref, +} + +impl OutType { + fn matches(&self, ty: &hir::FunctionRetTy) -> bool { + match (self, ty) { + (&OutType::Unit, &hir::DefaultReturn(_)) => true, + (&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, + (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, + (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, + (&OutType::Ref, &hir::Return(ref ty)) => { + if let hir::TyRptr(_, _) = ty.node { + true + } else { + false + } + } + _ => false, + } + } +} + +fn is_bool(ty: &hir::Ty) -> bool { + if let hir::TyPath(None, ref p) = ty.node { + if match_path(p, &["bool"]) { + return true; + } + } + false +} + +fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &hir::Item) -> bool { + let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); + !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, item.span) +} diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs new file mode 100644 index 00000000000..eaba19b08e4 --- /dev/null +++ b/clippy_lints/src/minmax.rs @@ -0,0 +1,93 @@ +use consts::{Constant, constant_simple}; +use rustc::lint::*; +use rustc::hir::*; +use std::cmp::{PartialOrd, Ordering}; +use syntax::ptr::P; +use utils::{match_def_path, paths, span_lint}; + +/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. +/// +/// **Why is this bad?** This is in all probability not the intended outcome. At the least it hurts readability of the code. +/// +/// **Known problems:** None +/// +/// **Example:** `min(0, max(100, x))` will always be equal to `0`. Probably the author meant to clamp the value between 0 and 100, but has erroneously swapped `min` and `max`. +declare_lint! { + pub MIN_MAX, Warn, + "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" +} + +#[allow(missing_copy_implementations)] +pub struct MinMaxPass; + +impl LintPass for MinMaxPass { + fn get_lints(&self) -> LintArray { + lint_array!(MIN_MAX) + } +} + +impl LateLintPass for MinMaxPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { + if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { + if outer_max == inner_max { + return; + } + match (outer_max, outer_c.partial_cmp(&inner_c)) { + (_, None) | + (MinMax::Max, Some(Ordering::Less)) | + (MinMax::Min, Some(Ordering::Greater)) => (), + _ => { + span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); + } + } + } + } + } +} + +#[derive(PartialEq, Eq, Debug)] +enum MinMax { + Min, + Max, +} + +fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { + if let ExprCall(ref path, ref args) = expr.node { + if let ExprPath(None, _) = path.node { + let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + + if match_def_path(cx, def_id, &paths::CMP_MIN) { + fetch_const(args, MinMax::Min) + } else if match_def_path(cx, def_id, &paths::CMP_MAX) { + fetch_const(args, MinMax::Max) + } else { + None + } + } else { + None + } + } else { + None + } +} + +fn fetch_const(args: &[P<Expr>], m: MinMax) -> Option<(MinMax, Constant, &Expr)> { + if args.len() != 2 { + return None; + } + if let Some(c) = constant_simple(&args[0]) { + if let None = constant_simple(&args[1]) { + // otherwise ignore + Some((m, c, &args[1])) + } else { + None + } + } else { + if let Some(c) = constant_simple(&args[1]) { + Some((m, c, &args[0])) + } else { + None + } + } +} diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs new file mode 100644 index 00000000000..3ab7823e50d --- /dev/null +++ b/clippy_lints/src/misc.rs @@ -0,0 +1,458 @@ +use reexport::*; +use rustc::hir::*; +use rustc::hir::intravisit::FnKind; +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc::ty; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use syntax::codemap::{Span, Spanned, ExpnFormat}; +use syntax::ptr::P; +use utils::{ + get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet, + span_lint, span_lint_and_then, walk_ptrs_ty +}; + +/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. +/// +/// **Why is this bad?** The `ref` declaration makes the function take an owned value, but turns the argument into a reference (which means that the value is destroyed when exiting the function). This adds not much value: either take a reference type, or take an owned value and create references in the body. +/// +/// For let bindings, `let x = &foo;` is preferred over `let ref x = foo`. The type of `x` is more obvious with the former. +/// +/// **Known problems:** If the argument is dereferenced within the function, removing the `ref` will lead to errors. This can be fixed by removing the dereferences, e.g. changing `*x` to `x` within the function. +/// +/// **Example:** `fn foo(ref x: u8) -> bool { .. }` +declare_lint! { + pub TOPLEVEL_REF_ARG, Warn, + "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ + or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ + references with `&`." +} + +#[allow(missing_copy_implementations)] +pub struct TopLevelRefPass; + +impl LintPass for TopLevelRefPass { + fn get_lints(&self) -> LintArray { + lint_array!(TOPLEVEL_REF_ARG) + } +} + +impl LateLintPass for TopLevelRefPass { + fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + if let FnKind::Closure(_) = k { + // Does not apply to closures + return; + } + for ref arg in &decl.inputs { + if let PatKind::Ident(BindByRef(_), _, _) = arg.pat.node { + span_lint(cx, + TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. Consider using a reference type instead."); + } + } + } + fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) { + if_let_chain! { + [ + let StmtDecl(ref d, _) = s.node, + let DeclLocal(ref l) = d.node, + let PatKind::Ident(BindByRef(_), i, None) = l.pat.node, + let Some(ref init) = l.init + ], { + let tyopt = if let Some(ref ty) = l.ty { + format!(": {}", snippet(cx, ty.span, "_")) + } else { + "".to_owned() + }; + span_lint_and_then(cx, + TOPLEVEL_REF_ARG, + l.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", + |db| { + db.span_suggestion(s.span, + "try", + format!("let {}{} = &{};", + snippet(cx, i.span, "_"), + tyopt, + snippet(cx, init.span, "_"))); + } + ); + } + }; + } +} + +/// **What it does:** This lint checks for comparisons to NAN. +/// +/// **Why is this bad?** NAN does not compare meaningfully to anything – not even itself – so those comparisons are simply wrong. +/// +/// **Known problems:** None +/// +/// **Example:** `x == NAN` +declare_lint!(pub CMP_NAN, Deny, + "comparisons to NAN (which will always return false, which is probably not intended)"); + +#[derive(Copy,Clone)] +pub struct CmpNan; + +impl LintPass for CmpNan { + fn get_lints(&self) -> LintArray { + lint_array!(CMP_NAN) + } +} + +impl LateLintPass for CmpNan { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if cmp.node.is_comparison() { + if let ExprPath(_, ref path) = left.node { + check_nan(cx, path, expr.span); + } + if let ExprPath(_, ref path) = right.node { + check_nan(cx, path, expr.span); + } + } + } + } +} + +fn check_nan(cx: &LateContext, path: &Path, span: Span) { + path.segments.last().map(|seg| { + if seg.name.as_str() == "NAN" { + span_lint(cx, + CMP_NAN, + span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); + } + }); +} + +/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). +/// +/// **Why is this bad?** Floating point calculations are usually imprecise, so asking if two values are *exactly* equal is asking for trouble. For a good guide on what to do, see [the floating point guide](http://www.floating-point-gui.de/errors/comparison). +/// +/// **Known problems:** None +/// +/// **Example:** `y == 1.23f64` +declare_lint!(pub FLOAT_CMP, Warn, + "using `==` or `!=` on float values (as floating-point operations \ + usually involve rounding errors, it is always better to check for approximate \ + equality within small bounds)"); + +#[derive(Copy,Clone)] +pub struct FloatCmp; + +impl LintPass for FloatCmp { + fn get_lints(&self) -> LintArray { + lint_array!(FLOAT_CMP) + } +} + +impl LateLintPass for FloatCmp { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + let op = cmp.node; + if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { + if is_allowed(cx, left) || is_allowed(cx, right) { + return; + } + if let Some(name) = get_item_name(cx, expr) { + let name = name.as_str(); + if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || + name.ends_with("_eq") { + return; + } + } + span_lint(cx, + FLOAT_CMP, + expr.span, + &format!("{}-comparison of f32 or f64 detected. Consider changing this to `({} - {}).abs() < \ + epsilon` for some suitable value of epsilon. \ + std::f32::EPSILON and std::f64::EPSILON are available.", + op.as_str(), + snippet(cx, left.span, ".."), + snippet(cx, right.span, ".."))); + } + } + } +} + +fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { + let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); + if let Ok(ConstVal::Float(val)) = res { + val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY + } else { + false + } +} + +fn is_float(cx: &LateContext, expr: &Expr) -> bool { + if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { + true + } else { + false + } +} + +/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. +/// +/// **Why is this bad?** The comparison can operate on a reference, so creating an owned value effectively throws it away directly afterwards, which is needlessly consuming code and heap space. +/// +/// **Known problems:** None +/// +/// **Example:** `x.to_owned() == y` +declare_lint!(pub CMP_OWNED, Warn, + "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`"); + +#[derive(Copy,Clone)] +pub struct CmpOwned; + +impl LintPass for CmpOwned { + fn get_lints(&self) -> LintArray { + lint_array!(CMP_OWNED) + } +} + +impl LateLintPass for CmpOwned { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref left, ref right) = expr.node { + if cmp.node.is_comparison() { + check_to_owned(cx, left, right, true, cmp.span); + check_to_owned(cx, right, left, false, cmp.span) + } + } + } +} + +fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) { + let (arg_ty, snip) = match expr.node { + ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => { + if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { + (cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) + } else { + return; + } + } + ExprCall(ref path, ref v) if v.len() == 1 => { + if let ExprPath(None, ref path) = path.node { + if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { + (cx.tcx.expr_ty(&v[0]), snippet(cx, v[0].span, "..")) + } else { + return; + } + } else { + return; + } + } + _ => return, + }; + + let other_ty = cx.tcx.expr_ty(other); + let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() { + Some(id) => id, + None => return, + }; + + if !implements_trait(cx, arg_ty, partial_eq_trait_id, vec![other_ty]) { + return; + } + + if left { + span_lint(cx, + CMP_OWNED, + expr.span, + &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ + compare without allocation", + snip, + snippet(cx, op, "=="), + snippet(cx, other.span, ".."))); + } else { + span_lint(cx, + CMP_OWNED, + expr.span, + &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ + compare without allocation", + snippet(cx, other.span, ".."), + snippet(cx, op, "=="), + snip)); + } + +} + +fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { + args.len() == 1 && + if let ty::TyStr = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { + true + } else { + false + } +} + +/// **What it does:** This lint checks for getting the remainder of a division by one. +/// +/// **Why is this bad?** The result can only ever be zero. No one will write such code deliberately, unless trying to win an Underhanded Rust Contest. Even for that contest, it's probably a bad idea. Use something more underhanded. +/// +/// **Known problems:** None +/// +/// **Example:** `x % 1` +declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); + +#[derive(Copy,Clone)] +pub struct ModuloOne; + +impl LintPass for ModuloOne { + fn get_lints(&self) -> LintArray { + lint_array!(MODULO_ONE) + } +} + +impl LateLintPass for ModuloOne { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, _, ref right) = expr.node { + if let Spanned { node: BinOp_::BiRem, .. } = *cmp { + if is_integer_literal(right, 1) { + span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); + } + } + } + } +} + +/// **What it does:** This lint checks for patterns in the form `name @ _`. +/// +/// **Why is this bad?** It's almost always more readable to just use direct bindings. +/// +/// **Known problems:** None +/// +/// **Example**: +/// ``` +/// match v { +/// Some(x) => (), +/// y @ _ => (), // easier written as `y`, +/// } +/// ``` +declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern"); + +#[derive(Copy,Clone)] +pub struct PatternPass; + +impl LintPass for PatternPass { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_PATTERN) + } +} + +impl LateLintPass for PatternPass { + fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { + if let PatKind::Ident(_, ref ident, Some(ref right)) = pat.node { + if right.node == PatKind::Wild { + span_lint(cx, + REDUNDANT_PATTERN, + pat.span, + &format!("the `{} @ _` pattern can be written as just `{}`", + ident.node, + ident.node)); + } + } + } +} + + +/// **What it does:** This lint checks for the use of bindings with a single leading underscore +/// +/// **Why is this bad?** A single leading underscore is usually used to indicate that a binding +/// will not be used. Using such a binding breaks this expectation. +/// +/// **Known problems:** The lint does not work properly with desugaring and macro, it has been +/// allowed in the mean time. +/// +/// **Example**: +/// ``` +/// let _x = 0; +/// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore. +/// // We should rename `_x` to `x` +/// ``` +declare_lint!(pub USED_UNDERSCORE_BINDING, Allow, + "using a binding which is prefixed with an underscore"); + +#[derive(Copy, Clone)] +pub struct UsedUnderscoreBinding; + +impl LintPass for UsedUnderscoreBinding { + fn get_lints(&self) -> LintArray { + lint_array!(USED_UNDERSCORE_BINDING) + } +} + +impl LateLintPass for UsedUnderscoreBinding { + #[cfg_attr(rustfmt, rustfmt_skip)] + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_attributes_expansion(cx, expr) { + // Don't lint things expanded by #[derive(...)], etc + return; + } + let binding = match expr.node { + ExprPath(_, ref path) => { + let segment = path.segments + .last() + .expect("path should always have at least one segment") + .name; + if segment.as_str().starts_with('_') && + !segment.as_str().starts_with("__") && + segment != segment.unhygienize() && // not in bang macro + is_used(cx, expr) { + Some(segment.as_str()) + } else { + None + } + } + ExprField(_, spanned) => { + let name = spanned.node.as_str(); + if name.starts_with('_') && !name.starts_with("__") { + Some(name) + } else { + None + } + } + _ => None, + }; + if let Some(binding) = binding { + if binding != "_result" { // FIXME: #944 + span_lint(cx, + USED_UNDERSCORE_BINDING, + expr.span, + &format!("used binding `{}` which is prefixed with an underscore. A leading \ + underscore signals that a binding will not be used.", binding)); + } + } + } +} + +/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea +/// of what it means for an expression to be "used". +fn is_used(cx: &LateContext, expr: &Expr) -> bool { + if let Some(ref parent) = get_parent_expr(cx, expr) { + match parent.node { + ExprAssign(_, ref rhs) | + ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + _ => is_used(cx, parent), + } + } else { + true + } +} + +/// Test whether an expression is in a macro expansion (e.g. something generated by +/// `#[derive(...)`] or the like). +fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { + cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| { + info_opt.map_or(false, |info| { + match info.callee.format { + ExpnFormat::MacroAttribute(_) => true, + _ => false, + } + }) + }) +} diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs new file mode 100644 index 00000000000..a7ab59497ac --- /dev/null +++ b/clippy_lints/src/misc_early.rs @@ -0,0 +1,166 @@ +use rustc::lint::*; +use std::collections::HashMap; +use syntax::ast::*; +use syntax::codemap::Span; +use syntax::visit::FnKind; +use utils::{span_lint, span_help_and_lint, snippet, span_lint_and_then}; +/// **What it does:** This lint checks for structure field patterns bound to wildcards. +/// +/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound. +/// +/// **Known problems:** None. +/// +/// **Example:** `let { a: _, b: ref b, c: _ } = ..` +declare_lint! { + pub UNNEEDED_FIELD_PATTERN, Warn, + "Struct fields are bound to a wildcard instead of using `..`" +} + +/// **What it does:** This lint checks for function arguments having the similar names differing by an underscore +/// +/// **Why is this bad?** It affects code readability +/// +/// **Known problems:** None. +/// +/// **Example:** `fn foo(a: i32, _a: i32) {}` +declare_lint! { + pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn, + "Function arguments having names which only differ by an underscore" +} + +/// **What it does:** This lint detects closures called in the same expression where they are defined. +/// +/// **Why is this bad?** It is unnecessarily adding to the expression's complexity. +/// +/// **Known problems:** None. +/// +/// **Example:** `(|| 42)()` +declare_lint! { + pub REDUNDANT_CLOSURE_CALL, Warn, + "Closures should not be called in the expression they are defined" +} + +#[derive(Copy, Clone)] +pub struct MiscEarly; + +impl LintPass for MiscEarly { + fn get_lints(&self) -> LintArray { + lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL) + } +} + +impl EarlyLintPass for MiscEarly { + fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { + if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { + let mut wilds = 0; + let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name; + + for field in pfields { + if field.node.pat.node == PatKind::Wild { + wilds += 1; + } + } + if !pfields.is_empty() && wilds == pfields.len() { + span_help_and_lint(cx, + UNNEEDED_FIELD_PATTERN, + pat.span, + "All the struct fields are matched to a wildcard pattern, consider using `..`.", + &format!("Try with `{} {{ .. }}` instead", type_name)); + return; + } + if wilds > 0 { + let mut normal = vec![]; + + for field in pfields { + if field.node.pat.node != PatKind::Wild { + if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { + normal.push(n); + } + } + } + for field in pfields { + if field.node.pat.node == PatKind::Wild { + wilds -= 1; + if wilds > 0 { + span_lint(cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` instead"); + } else { + span_help_and_lint(cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` \ + instead", + &format!("Try with `{} {{ {}, .. }}`", + type_name, + normal[..].join(", "))); + } + } + } + } + } + } + + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + let mut registered_names: HashMap<String, Span> = HashMap::new(); + + for ref arg in &decl.inputs { + if let PatKind::Ident(_, sp_ident, None) = arg.pat.node { + let arg_name = sp_ident.node.to_string(); + + if arg_name.starts_with('_') { + if let Some(correspondence) = registered_names.get(&arg_name[1..]) { + span_lint(cx, + DUPLICATE_UNDERSCORE_ARGUMENT, + *correspondence, + &format!("`{}` already exists, having another argument having almost the same \ + name makes code comprehension and documentation more difficult", + arg_name[1..].to_owned()));; + } + } else { + registered_names.insert(arg_name, arg.pat.span); + } + } + } + } + + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if let ExprKind::Call(ref paren, _) = expr.node { + if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { + span_lint_and_then(cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |db| { + if decl.inputs.is_empty() { + let hint = format!("{}", snippet(cx, block.span, "..")); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + } + }); + } + } + } + } + + fn check_block(&mut self, cx: &EarlyContext, block: &Block) { + for w in block.stmts.windows(2) { + if_let_chain! {[ + let StmtKind::Decl(ref first, _) = w[0].node, + let DeclKind::Local(ref local) = first.node, + let Option::Some(ref t) = local.init, + let ExprKind::Closure(_,_,_,_) = t.node, + let PatKind::Ident(_,sp_ident,_) = local.pat.node, + let StmtKind::Semi(ref second,_) = w[1].node, + let ExprKind::Assign(_,ref call) = second.node, + let ExprKind::Call(ref closure,_) = call.node, + let ExprKind::Path(_,ref path) = closure.node + ], { + if sp_ident.node == (&path.segments[0]).identifier { + span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared"); + } + }} + } + } +} diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs new file mode 100644 index 00000000000..4147e288c4f --- /dev/null +++ b/clippy_lints/src/mut_mut.rs @@ -0,0 +1,59 @@ +use rustc::lint::*; +use rustc::ty::{TypeAndMut, TyRef}; +use rustc::hir::*; +use utils::{in_external_macro, span_lint}; + +/// **What it does:** This lint checks for instances of `mut mut` references. +/// +/// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = &mut &mut y;` +declare_lint! { + pub MUT_MUT, + Allow, + "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ + or shows a fundamental misunderstanding of references)" +} + +#[derive(Copy,Clone)] +pub struct MutMut; + +impl LintPass for MutMut { + fn get_lints(&self) -> LintArray { + lint_array!(MUT_MUT) + } +} + +impl LateLintPass for MutMut { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_external_macro(cx, expr.span) { + return; + } + + if let ExprAddrOf(MutMutable, ref e) = expr.node { + if let ExprAddrOf(MutMutable, _) = e.node { + span_lint(cx, + MUT_MUT, + expr.span, + "generally you want to avoid `&mut &mut _` if possible"); + } else { + if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { + span_lint(cx, + MUT_MUT, + expr.span, + "this expression mutably borrows a mutable reference. Consider reborrowing"); + } + } + } + } + + fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { + if let TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) = ty.node { + if let TyRptr(_, MutTy { mutbl: MutMutable, .. }) = pty.node { + span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); + } + } + } +} diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs new file mode 100644 index 00000000000..f6aee54d90b --- /dev/null +++ b/clippy_lints/src/mut_reference.rs @@ -0,0 +1,77 @@ +use rustc::lint::*; +use rustc::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; +use rustc::hir::*; +use syntax::ptr::P; +use utils::span_lint; + +/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. +/// +/// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site. +/// +/// **Known problems:** None +/// +/// **Example** `my_vec.push(&mut value)` +declare_lint! { + pub UNNECESSARY_MUT_PASSED, + Warn, + "an argument is passed as a mutable reference although the function/method only demands an \ + immutable reference" +} + + +#[derive(Copy,Clone)] +pub struct UnnecessaryMutPassed; + +impl LintPass for UnnecessaryMutPassed { + fn get_lints(&self) -> LintArray { + lint_array!(UNNECESSARY_MUT_PASSED) + } +} + +impl LateLintPass for UnnecessaryMutPassed { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + let borrowed_table = cx.tcx.tables.borrow(); + match e.node { + ExprCall(ref fn_expr, ref arguments) => { + let function_type = borrowed_table.node_types + .get(&fn_expr.id) + .expect("A function with an unknown type is called. \ + If this happened, the compiler would have \ + aborted the compilation long ago"); + if let ExprPath(_, ref path) = fn_expr.node { + check_arguments(cx, arguments, function_type, &path.to_string()); + } + } + ExprMethodCall(ref name, _, ref arguments) => { + let method_call = MethodCall::expr(e.id); + let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); + check_arguments(cx, arguments, method_type.ty, &name.node.as_str()) + } + _ => (), + } + } +} + +fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { + match type_definition.sty { + TypeVariants::TyFnDef(_, _, ref fn_type) | + TypeVariants::TyFnPtr(ref fn_type) => { + let parameters = &fn_type.sig.skip_binder().inputs; + for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + match parameter.sty { + TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) | + TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => { + if let ExprAddrOf(MutMutable, _) = argument.node { + span_lint(cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method \"{}\" doesn't need a mutable reference", name)); + } + } + _ => (), + } + } + } + _ => (), + } +} diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs new file mode 100644 index 00000000000..7d637adb8b8 --- /dev/null +++ b/clippy_lints/src/mutex_atomic.rs @@ -0,0 +1,75 @@ +//! Checks for uses of Mutex where an atomic value could be used +//! +//! This lint is **warn** by default + +use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; +use rustc::ty::subst::ParamSpace; +use rustc::ty; +use rustc::hir::Expr; +use syntax::ast; +use utils::{match_type, paths, span_lint}; + +/// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do. +/// +/// **Why is this bad?** Using a Mutex just to make access to a plain bool or reference sequential is shooting flies with cannons. `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and faster. +/// +/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. +/// +/// **Example:** `let x = Mutex::new(&y);` +declare_lint! { + pub MUTEX_ATOMIC, + Warn, + "using a Mutex where an atomic value could be used instead" +} + +/// **What it does:** This lint checks for usages of `Mutex<X>` where `X` is an integral type. +/// +/// **Why is this bad?** Using a Mutex just to make access to a plain integer sequential is shooting flies with cannons. `std::atomic::usize` is leaner and faster. +/// +/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. +/// +/// **Example:** `let x = Mutex::new(0usize);` +declare_lint! { + pub MUTEX_INTEGER, + Allow, + "using a Mutex for an integer type" +} + +impl LintPass for MutexAtomic { + fn get_lints(&self) -> LintArray { + lint_array!(MUTEX_ATOMIC, MUTEX_INTEGER) + } +} + +pub struct MutexAtomic; + +impl LateLintPass for MutexAtomic { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + let ty = cx.tcx.expr_ty(expr); + if let ty::TyStruct(_, subst) = ty.sty { + if match_type(cx, ty, &paths::MUTEX) { + let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; + if let Some(atomic_name) = get_atomic_name(mutex_param) { + let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ + behaviour and not the internal type, consider using Mutex<()>.", + atomic_name); + match *mutex_param { + ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), + }; + } + } + } + } +} + +fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { + match *ty { + ty::TyBool => Some("AtomicBool"), + ty::TyUint(_) => Some("AtomicUsize"), + ty::TyInt(_) => Some("AtomicIsize"), + ty::TyRawPtr(_) => Some("AtomicPtr"), + _ => None, + } +} diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs new file mode 100644 index 00000000000..f95d6f5c9c1 --- /dev/null +++ b/clippy_lints/src/needless_bool.rs @@ -0,0 +1,192 @@ +//! Checks for needless boolean results of if-else expressions +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc::hir::*; +use syntax::ast::LitKind; +use syntax::codemap::Spanned; +use utils::{span_lint, span_lint_and_then, snippet, snippet_opt}; + +/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. +/// +/// **Why is this bad?** Redundant code. +/// +/// **Known problems:** Maybe false positives: Sometimes, the two branches are painstakingly documented (which we of course do not detect), so they *may* have some value. Even then, the documentation can be rewritten to match the shorter code. +/// +/// **Example:** `if x { false } else { true }` +declare_lint! { + pub NEEDLESS_BOOL, + Warn, + "if-statements with plain booleans in the then- and else-clause, e.g. \ + `if p { true } else { false }`" +} + +/// **What it does:** This lint checks for expressions of the form `x == true` (or vice versa) and suggest using the variable directly. +/// +/// **Why is this bad?** Unnecessary code. +/// +/// **Known problems:** None. +/// +/// **Example:** `if x == true { }` could be `if x { }` +declare_lint! { + pub BOOL_COMPARISON, + Warn, + "comparing a variable to a boolean, e.g. \ + `if x == true`" +} + +#[derive(Copy,Clone)] +pub struct NeedlessBool; + +impl LintPass for NeedlessBool { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_BOOL) + } +} + +impl LateLintPass for NeedlessBool { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use self::Expression::*; + if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { + let reduce = |hint: &str, not| { + let hint = match snippet_opt(cx, pred.span) { + Some(pred_snip) => format!("`{}{}`", not, pred_snip), + None => hint.into(), + }; + span_lint_and_then(cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression returns a bool literal", + |db| { + db.span_suggestion(e.span, "you can reduce it to", hint); + }); + }; + match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { + (RetBool(true), RetBool(true)) | + (Bool(true), Bool(true)) => { + span_lint(cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression will always return true"); + } + (RetBool(false), RetBool(false)) | + (Bool(false), Bool(false)) => { + span_lint(cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression will always return false"); + } + (RetBool(true), RetBool(false)) => reduce("its predicate", "return "), + (Bool(true), Bool(false)) => reduce("its predicate", ""), + (RetBool(false), RetBool(true)) => reduce("`!` and its predicate", "return !"), + (Bool(false), Bool(true)) => reduce("`!` and its predicate", "!"), + _ => (), + } + } + } +} + +#[derive(Copy,Clone)] +pub struct BoolComparison; + +impl LintPass for BoolComparison { + fn get_lints(&self) -> LintArray { + lint_array!(BOOL_COMPARISON) + } +} + +impl LateLintPass for BoolComparison { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use self::Expression::*; + if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { + (Bool(true), Other) => { + let hint = snippet(cx, right_side.span, "..").into_owned(); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + |db| { + db.span_suggestion(e.span, "try simplifying it as shown:", hint); + }); + } + (Other, Bool(true)) => { + let hint = snippet(cx, left_side.span, "..").into_owned(); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + |db| { + db.span_suggestion(e.span, "try simplifying it as shown:", hint); + }); + } + (Bool(false), Other) => { + let hint = format!("!{}", snippet(cx, right_side.span, "..")); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + |db| { + db.span_suggestion(e.span, "try simplifying it as shown:", hint); + }); + } + (Other, Bool(false)) => { + let hint = format!("!{}", snippet(cx, left_side.span, "..")); + span_lint_and_then(cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + |db| { + db.span_suggestion(e.span, "try simplifying it as shown:", hint); + }); + } + _ => (), + } + } + } +} + +enum Expression { + Bool(bool), + RetBool(bool), + Other, +} + +fn fetch_bool_block(block: &Block) -> Expression { + match (&*block.stmts, block.expr.as_ref()) { + ([], Some(e)) => fetch_bool_expr(&**e), + ([ref e], None) => { + if let StmtSemi(ref e, _) = e.node { + if let ExprRet(_) = e.node { + fetch_bool_expr(&**e) + } else { + Expression::Other + } + } else { + Expression::Other + } + } + _ => Expression::Other, + } +} + +fn fetch_bool_expr(expr: &Expr) -> Expression { + match expr.node { + ExprBlock(ref block) => fetch_bool_block(block), + ExprLit(ref lit_ptr) => { + if let LitKind::Bool(value) = lit_ptr.node { + Expression::Bool(value) + } else { + Expression::Other + } + } + ExprRet(Some(ref expr)) => { + match fetch_bool_expr(expr) { + Expression::Bool(value) => Expression::RetBool(value), + _ => Expression::Other, + } + } + _ => Expression::Other, + } +} diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs new file mode 100644 index 00000000000..033811841ce --- /dev/null +++ b/clippy_lints/src/needless_borrow.rs @@ -0,0 +1,51 @@ +//! Checks for needless address of operations (`&`) +//! +//! This lint is **warn** by default + +use rustc::lint::*; +use rustc::hir::{ExprAddrOf, Expr, MutImmutable}; +use rustc::ty::TyRef; +use utils::{span_lint, in_macro}; +use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef; + +/// **What it does:** This lint checks for address of operations (`&`) that are going to be dereferenced immediately by the compiler +/// +/// **Why is this bad?** Suggests that the receiver of the expression borrows the expression +/// +/// **Known problems:** +/// +/// **Example:** `let x: &i32 = &&&&&&5;` +declare_lint! { + pub NEEDLESS_BORROW, + Warn, + "taking a reference that is going to be automatically dereferenced" +} + +#[derive(Copy,Clone)] +pub struct NeedlessBorrow; + +impl LintPass for NeedlessBorrow { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_BORROW) + } +} + +impl LateLintPass for NeedlessBorrow { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if in_macro(cx, e.span) { + return; + } + if let ExprAddrOf(MutImmutable, ref inner) = e.node { + if let TyRef(..) = cx.tcx.expr_ty(inner).sty { + if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) { + if deref.autoderefs > 1 && deref.autoref.is_some() { + span_lint(cx, + NEEDLESS_BORROW, + e.span, + "this expression borrows a reference that is immediately dereferenced by the compiler"); + } + } + } + } + } +} diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs new file mode 100644 index 00000000000..d8ae9dc3471 --- /dev/null +++ b/clippy_lints/src/needless_update.rs @@ -0,0 +1,42 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::TyStruct; +use rustc::hir::{Expr, ExprStruct}; +use utils::span_lint; + +/// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway. +/// +/// **Why is this bad?** This will cost resources (because the base has to be somewhere), and make the code less readable. +/// +/// **Known problems:** None. +/// +/// **Example:** `Point { x: 1, y: 0, ..zero_point }` +declare_lint! { + pub NEEDLESS_UPDATE, + Warn, + "using `{ ..base }` when there are no missing fields" +} + +#[derive(Copy, Clone)] +pub struct NeedlessUpdatePass; + +impl LintPass for NeedlessUpdatePass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_UPDATE) + } +} + +impl LateLintPass for NeedlessUpdatePass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { + let ty = cx.tcx.expr_ty(expr); + if let TyStruct(def, _) = ty.sty { + if fields.len() == def.struct_variant().fields.len() { + span_lint(cx, + NEEDLESS_UPDATE, + base.span, + "struct update has no effect, all the fields in the struct have already been specified"); + } + } + } + } +} diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs new file mode 100644 index 00000000000..fb986409a41 --- /dev/null +++ b/clippy_lints/src/neg_multiply.rs @@ -0,0 +1,57 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::{Span, Spanned}; + +use consts::{self, Constant}; +use utils::span_lint; + +/// **What it does:** Checks for multiplication by -1 as a form of negation. +/// +/// **Why is this bad?** It's more readable to just negate. +/// +/// **Known problems:** This only catches integers (for now) +/// +/// **Example:** `x * -1` +declare_lint! { + pub NEG_MULTIPLY, + Warn, + "Warns on multiplying integers with -1" +} + +#[derive(Copy, Clone)] +pub struct NegMultiply; + +impl LintPass for NegMultiply { + fn get_lints(&self) -> LintArray { + lint_array!(NEG_MULTIPLY) + } +} + +#[allow(match_same_arms)] +impl LateLintPass for NegMultiply { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { + match (&l.node, &r.node) { + (&ExprUnary(..), &ExprUnary(..)) => (), + (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), + (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), + _ => () + } + } + } +} + +fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { + if_let_chain!([ + let ExprLit(ref l) = lit.node, + let Constant::Int(ref ci) = consts::lit_to_constant(&l.node), + let Some(val) = ci.to_u64(), + val == 1, + cx.tcx.expr_ty(exp).is_integral() + ], { + span_lint(cx, + NEG_MULTIPLY, + span, + "Negation by multiplying with -1"); + }) +} diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs new file mode 100644 index 00000000000..08d517014ee --- /dev/null +++ b/clippy_lints/src/new_without_default.rs @@ -0,0 +1,148 @@ +use rustc::hir::intravisit::FnKind; +use rustc::hir::def_id::DefId; +use rustc::hir; +use rustc::lint::*; +use rustc::ty; +use syntax::ast; +use syntax::codemap::Span; +use utils::paths; +use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint}; + +/// **What it does:** This lints about type with a `fn new() -> Self` method +/// and no implementation of +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// +/// **Why is this bad?** User might expect to be able to use +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// as the type can be +/// constructed without arguments. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ```rust,ignore +/// struct Foo(Bar); +/// +/// impl Foo { +/// fn new() -> Self { +/// Foo(Bar::new()) +/// } +/// } +/// ``` +/// +/// Instead, use: +/// +/// ```rust +/// struct Foo(Bar); +/// +/// impl Default for Foo { +/// fn default() -> Self { +/// Foo(Bar::new()) +/// } +/// } +/// ``` +/// +/// You can also have `new()` call `Default::default()` +declare_lint! { + pub NEW_WITHOUT_DEFAULT, + Warn, + "`fn new() -> Self` method without `Default` implementation" +} + +/// **What it does:** This lints about type with a `fn new() -> Self` method +/// and no implementation of +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// +/// **Why is this bad?** User might expect to be able to use +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// as the type can be +/// constructed without arguments. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// +/// ```rust,ignore +/// struct Foo; +/// +/// impl Foo { +/// fn new() -> Self { +/// Foo +/// } +/// } +/// ``` +/// +/// Just prepend `#[derive(Default)]` before the `struct` definition +declare_lint! { + pub NEW_WITHOUT_DEFAULT_DERIVE, + Warn, + "`fn new() -> Self` without `#[derive]`able `Default` implementation" +} + +#[derive(Copy,Clone)] +pub struct NewWithoutDefault; + +impl LintPass for NewWithoutDefault { + fn get_lints(&self) -> LintArray { + lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE) + } +} + +impl LateLintPass for NewWithoutDefault { + fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) { + if in_external_macro(cx, span) { + return; + } + + if let FnKind::Method(name, _, _, _) = kind { + if decl.inputs.is_empty() && name.as_str() == "new" { + let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( + cx.tcx.map.get_parent(id))).ty; + if_let_chain!{[ + self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics + let Some(ret_ty) = return_ty(cx, id), + same_tys(cx, self_ty, ret_ty, id), + let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), + !implements_trait(cx, self_ty, default_trait_id, Vec::new()) + ], { + if can_derive_default(self_ty, cx, default_trait_id) { + span_lint(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty)). + span_suggestion(span, + "try this", + "#[derive(Default)]".into()); + } else { + span_lint(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty)). + span_suggestion(span, + "try this", + format!("impl Default for {} {{ fn default() -> \ + Self {{ {}::new() }} }}", self_ty, self_ty)); + } + }} + } + } + } +} + +fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> bool { + match ty.sty { + ty::TyStruct(ref adt_def, ref substs) => { + for field in adt_def.all_fields() { + let f_ty = field.ty(cx.tcx, substs); + if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) { + return false + } + } + true + }, + _ => false + } +} diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs new file mode 100644 index 00000000000..ae3bac00455 --- /dev/null +++ b/clippy_lints/src/no_effect.rs @@ -0,0 +1,155 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::hir::def::{Def, PathResolution}; +use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource}; +use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then}; +use std::ops::Deref; + +/// **What it does:** This lint checks for statements which have no effect. +/// +/// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable. +/// +/// **Known problems:** None. +/// +/// **Example:** `0;` +declare_lint! { + pub NO_EFFECT, + Warn, + "statements with no effect" +} + +/// **What it does:** This lint checks for expression statements that can be reduced to a sub-expression +/// +/// **Why is this bad?** Expressions by themselves often have no side-effects. Having such expressions reduces redability. +/// +/// **Known problems:** None. +/// +/// **Example:** `compute_array()[0];` +declare_lint! { + pub UNNECESSARY_OPERATION, + Warn, + "outer expressions with no effect" +} + +fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { + if in_macro(cx, expr.span) { + return false; + } + match expr.node { + Expr_::ExprLit(..) | + Expr_::ExprClosure(..) | + Expr_::ExprPath(..) => true, + Expr_::ExprIndex(ref a, ref b) | + Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), + Expr_::ExprVec(ref v) | + Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), + Expr_::ExprRepeat(ref inner, _) | + Expr_::ExprCast(ref inner, _) | + Expr_::ExprType(ref inner, _) | + Expr_::ExprUnary(_, ref inner) | + Expr_::ExprField(ref inner, _) | + Expr_::ExprTupField(ref inner, _) | + Expr_::ExprAddrOf(_, ref inner) | + Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), + Expr_::ExprStruct(_, ref fields, ref base) => { + fields.iter().all(|field| has_no_effect(cx, &field.expr)) && + match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } + } + Expr_::ExprCall(ref callee, ref args) => { + let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); + match def { + Some(Def::Struct(..)) | + Some(Def::Variant(..)) => args.iter().all(|arg| has_no_effect(cx, arg)), + _ => false, + } + } + Expr_::ExprBlock(ref block) => { + block.stmts.is_empty() && + if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) + } else { + false + } + } + _ => false, + } +} + +#[derive(Copy, Clone)] +pub struct NoEffectPass; + +impl LintPass for NoEffectPass { + fn get_lints(&self) -> LintArray { + lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) + } +} + +impl LateLintPass for NoEffectPass { + fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { + if let StmtSemi(ref expr, _) = stmt.node { + if has_no_effect(cx, expr) { + span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); + } else if let Some(reduced) = reduce_expression(cx, expr) { + let mut snippet = String::new(); + for e in reduced { + if in_macro(cx, e.span) { + return; + } + if let Some(snip) = snippet_opt(cx, e.span) { + snippet.push_str(&snip); + snippet.push(';'); + } else { + return; + } + } + span_lint_and_then(cx, UNNECESSARY_OPERATION, stmt.span, "statement can be reduced", |db| { + db.span_suggestion(stmt.span, "replace it with", snippet); + }); + } + } + } +} + + +fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Expr>> { + if in_macro(cx, expr.span) { + return None; + } + match expr.node { + Expr_::ExprIndex(ref a, ref b) | + Expr_::ExprBinary(_, ref a, ref b) => Some(vec![&**a, &**b]), + Expr_::ExprVec(ref v) | + Expr_::ExprTup(ref v) => Some(v.iter().map(Deref::deref).collect()), + Expr_::ExprRepeat(ref inner, _) | + Expr_::ExprCast(ref inner, _) | + Expr_::ExprType(ref inner, _) | + Expr_::ExprUnary(_, ref inner) | + Expr_::ExprField(ref inner, _) | + Expr_::ExprTupField(ref inner, _) | + Expr_::ExprAddrOf(_, ref inner) | + Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), + Expr_::ExprStruct(_, ref fields, ref base) => Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()), + Expr_::ExprCall(ref callee, ref args) => { + match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) { + Some(Def::Struct(..)) | + Some(Def::Variant(..)) => Some(args.iter().map(Deref::deref).collect()), + _ => None, + } + } + Expr_::ExprBlock(ref block) => { + if block.stmts.is_empty() { + block.expr.as_ref().and_then(|e| match block.rules { + BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, + BlockCheckMode::DefaultBlock => Some(vec![&**e]), + // in case of compiler-inserted signaling blocks + _ => reduce_expression(cx, e), + }) + } else { + None + } + } + _ => None, + } +} diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs new file mode 100644 index 00000000000..cbb083a3e16 --- /dev/null +++ b/clippy_lints/src/non_expressive_names.rs @@ -0,0 +1,291 @@ +use rustc::lint::*; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use syntax::ast::*; +use syntax::attr; +use syntax::visit::{Visitor, walk_block, walk_pat, walk_expr}; +use utils::{span_lint_and_then, in_macro, span_lint}; + +/// **What it does:** This lint warns about names that are very similar and thus confusing +/// +/// **Why is this bad?** It's hard to distinguish between names that differ only by a single character +/// +/// **Known problems:** None? +/// +/// **Example:** `checked_exp` and `checked_expr` +declare_lint! { + pub SIMILAR_NAMES, + Allow, + "similarly named items and bindings" +} + +/// **What it does:** This lint warns about having too many variables whose name consists of a single character +/// +/// **Why is this bad?** It's hard to memorize what a variable means without a descriptive name. +/// +/// **Known problems:** None? +/// +/// **Example:** let (a, b, c, d, e, f, g) = (...); +declare_lint! { + pub MANY_SINGLE_CHAR_NAMES, + Warn, + "too many single character bindings" +} + +pub struct NonExpressiveNames { + pub max_single_char_names: u64, +} + +impl LintPass for NonExpressiveNames { + fn get_lints(&self) -> LintArray { + lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES) + } +} + +struct ExistingName { + interned: InternedString, + span: Span, + len: usize, + whitelist: &'static [&'static str], +} + +struct SimilarNamesLocalVisitor<'a, 'b: 'a> { + names: Vec<ExistingName>, + cx: &'a EarlyContext<'b>, + lint: &'a NonExpressiveNames, + single_char_names: Vec<char>, +} + +// this list contains lists of names that are allowed to be similar +// the assumption is that no name is ever contained in multiple lists. +#[cfg_attr(rustfmt, rustfmt_skip)] +const WHITELIST: &'static [&'static [&'static str]] = &[ + &["parsed", "parser"], + &["lhs", "rhs"], + &["tx", "rx"], + &["set", "get"], +]; + +struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); + +impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { + fn visit_pat(&mut self, pat: &'v Pat) { + match pat.node { + PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), + PatKind::Struct(_, ref fields, _) => for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); + } + }, + _ => walk_pat(self, pat), + } + } +} + +fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { + for &allow in WHITELIST { + if whitelisted(interned_name, allow) { + return Some(allow); + } + } + None +} + +fn whitelisted(interned_name: &str, list: &[&str]) -> bool { + if list.iter().any(|&name| interned_name == name) { + return true; + } + for name in list { + // name_* + if interned_name.chars().zip(name.chars()).all(|(l, r)| l == r) { + return true; + } + // *_name + if interned_name.chars().rev().zip(name.chars().rev()).all(|(l, r)| l == r) { + return true; + } + } + false +} + +impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { + fn check_short_name(&mut self, c: char, span: Span) { + // make sure we ignore shadowing + if self.0.single_char_names.contains(&c) { + return; + } + self.0.single_char_names.push(c); + if self.0.single_char_names.len() as u64 >= self.0.lint.max_single_char_names { + span_lint(self.0.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("{}th binding whose name is just one char", self.0.single_char_names.len())); + } + } + fn check_name(&mut self, span: Span, name: Name) { + if in_macro(self.0.cx, span) { + return; + } + let interned_name = name.as_str(); + if interned_name.chars().any(char::is_uppercase) { + return; + } + let count = interned_name.chars().count(); + if count < 3 { + if count == 1 { + let c = interned_name.chars().next().expect("already checked"); + self.check_short_name(c, span); + } + return; + } + for existing_name in &self.0.names { + if whitelisted(&interned_name, existing_name.whitelist) { + continue; + } + let mut split_at = None; + if existing_name.len > count { + if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned) { + continue; + } + } else if existing_name.len < count { + if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned, &interned_name) { + continue; + } + } else { + let mut interned_chars = interned_name.chars(); + let mut existing_chars = existing_name.interned.chars(); + let first_i = interned_chars.next().expect("we know we have at least one char"); + let first_e = existing_chars.next().expect("we know we have at least one char"); + let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); + + if eq_or_numeric(first_i, first_e) { + let last_i = interned_chars.next_back().expect("we know we have at least two chars"); + let last_e = existing_chars.next_back().expect("we know we have at least two chars"); + if eq_or_numeric(last_i, last_e) { + if interned_chars.zip(existing_chars).filter(|&(i, e)| !eq_or_numeric(i, e)).count() != 1 { + continue; + } + } else { + let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); + let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); + if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || + !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + // allowed similarity foo_x, foo_y + // or too many chars differ (foo_x, boo_y) or (foox, booy) + continue; + } + split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); + } + } else { + let second_i = interned_chars.next().expect("we know we have at least two chars"); + let second_e = existing_chars.next().expect("we know we have at least two chars"); + if !eq_or_numeric(second_i, second_e) || second_i == '_' || + !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + // allowed similarity x_foo, y_foo + // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) + continue; + } + split_at = interned_name.chars().next().map(|c| c.len_utf8()); + } + } + span_lint_and_then(self.0.cx, + SIMILAR_NAMES, + span, + "binding's name is too similar to existing binding", + |diag| { + diag.span_note(existing_name.span, "existing binding defined here"); + if let Some(split) = split_at { + diag.span_help(span, + &format!("separate the discriminating character by an \ + underscore like: `{}_{}`", + &interned_name[..split], + &interned_name[split..])); + } + }); + return; + } + self.0.names.push(ExistingName { + whitelist: get_whitelist(&interned_name).unwrap_or(&[]), + interned: interned_name, + span: span, + len: count, + }); + } +} + +impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { + /// ensure scoping rules work + fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) { + let n = self.names.len(); + let single_char_count = self.single_char_names.len(); + f(self); + self.names.truncate(n); + self.single_char_names.truncate(single_char_count); + } +} + +impl<'v, 'a, 'b> Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { + fn visit_local(&mut self, local: &'v Local) { + if let Some(ref init) = local.init { + self.apply(|this| walk_expr(this, &**init)); + } + // add the pattern after the expression because the bindings aren't available yet in the init expression + SimilarNamesNameVisitor(self).visit_pat(&*local.pat); + } + fn visit_block(&mut self, blk: &'v Block) { + self.apply(|this| walk_block(this, blk)); + } + fn visit_arm(&mut self, arm: &'v Arm) { + self.apply(|this| { + // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier + SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); + this.apply(|this| walk_expr(this, &arm.body)); + }); + } + fn visit_item(&mut self, _: &'v Item) { + // do not recurse into inner items + } +} + +impl EarlyLintPass for NonExpressiveNames { + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node { + if !attr::contains_name(&item.attrs, "test") { + let mut visitor = SimilarNamesLocalVisitor { + names: Vec::new(), + cx: cx, + lint: self, + single_char_names: Vec::new(), + }; + // initialize with function arguments + for arg in &decl.inputs { + SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); + } + // walk all other bindings + walk_block(&mut visitor, blk); + } + } + } +} + +/// Precondition: `a_name.chars().count() < b_name.chars().count()`. +fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { + debug_assert!(a_name.chars().count() < b_name.chars().count()); + let mut a_chars = a_name.chars(); + let mut b_chars = b_name.chars(); + while let (Some(a), Some(b)) = (a_chars.next(), b_chars.next()) { + if a == b { + continue; + } + if let Some(b2) = b_chars.next() { + // check if there's just one character inserted + return a != b2 || a_chars.ne(b_chars); + } else { + // tuple + // ntuple + return true; + } + } + // for item in items + true +} diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs new file mode 100644 index 00000000000..1d760599e3f --- /dev/null +++ b/clippy_lints/src/open_options.rs @@ -0,0 +1,185 @@ +use rustc::hir::{Expr, ExprMethodCall, ExprLit}; +use rustc::lint::*; +use syntax::ast::LitKind; +use syntax::codemap::{Span, Spanned}; +use utils::{match_type, paths, span_lint, walk_ptrs_ty_depth}; + +/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. +/// +/// **Why is this bad?** In the best case, the code will be harder to read than necessary. I don't know the worst case. +/// +/// **Known problems:** None +/// +/// **Example:** `OpenOptions::new().read(true).truncate(true)` +declare_lint! { + pub NONSENSICAL_OPEN_OPTIONS, + Warn, + "nonsensical combination of options for opening a file" +} + + +#[derive(Copy,Clone)] +pub struct NonSensicalOpenOptions; + +impl LintPass for NonSensicalOpenOptions { + fn get_lints(&self) -> LintArray { + lint_array!(NONSENSICAL_OPEN_OPTIONS) + } +} + +impl LateLintPass for NonSensicalOpenOptions { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprMethodCall(ref name, _, ref arguments) = e.node { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); + if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { + let mut options = Vec::new(); + get_open_options(cx, &arguments[0], &mut options); + check_open_options(cx, &options, e.span); + } + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +enum Argument { + True, + False, + Unknown, +} + +#[derive(Debug)] +enum OpenOption { + Write, + Read, + Truncate, + Create, + Append, +} + +fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { + if let ExprMethodCall(ref name, _, ref arguments) = argument.node { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); + + // Only proceed if this is a call on some object of type std::fs::OpenOptions + if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { + + let argument_option = match arguments[1].node { + ExprLit(ref span) => { + if let Spanned { node: LitKind::Bool(lit), .. } = **span { + if lit { + Argument::True + } else { + Argument::False + } + } else { + return; // The function is called with a literal + // which is not a boolean literal. This is theoretically + // possible, but not very likely. + } + } + _ => Argument::Unknown, + }; + + match &*name.node.as_str() { + "create" => { + options.push((OpenOption::Create, argument_option)); + } + "append" => { + options.push((OpenOption::Append, argument_option)); + } + "truncate" => { + options.push((OpenOption::Truncate, argument_option)); + } + "read" => { + options.push((OpenOption::Read, argument_option)); + } + "write" => { + options.push((OpenOption::Write, argument_option)); + } + _ => (), + } + + get_open_options(cx, &arguments[0], options); + } + } +} + +fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { + let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); + let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, + false, + false, + false, + false); + // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. + + for option in options { + match *option { + (OpenOption::Create, arg) => { + if create { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"create\" is called more than once"); + } else { + create = true + } + create_arg = create_arg || (arg == Argument::True);; + } + (OpenOption::Append, arg) => { + if append { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"append\" is called more than once"); + } else { + append = true + } + append_arg = append_arg || (arg == Argument::True);; + } + (OpenOption::Truncate, arg) => { + if truncate { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"truncate\" is called more than once"); + } else { + truncate = true + } + truncate_arg = truncate_arg || (arg == Argument::True); + } + (OpenOption::Read, arg) => { + if read { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"read\" is called more than once"); + } else { + read = true + } + read_arg = read_arg || (arg == Argument::True);; + } + (OpenOption::Write, arg) => { + if write { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"write\" is called more than once"); + } else { + write = true + } + write_arg = write_arg || (arg == Argument::True);; + } + } + } + + if read && truncate && read_arg && truncate_arg { + span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\""); + } + if append && truncate && append_arg && truncate_arg { + span_lint(cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with \"append\" and \"truncate\""); + } +} diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs new file mode 100644 index 00000000000..34921bc2c04 --- /dev/null +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -0,0 +1,72 @@ +use rustc::lint::*; +use rustc::hir::*; +use utils::span_lint; + +/// **What it does:** This lint finds classic underflow / overflow checks. +/// +/// **Why is this bad?** Most classic C underflow / overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead. +/// +/// **Known problems:** None. +/// +/// **Example:** `a + b < a` + +declare_lint!(pub OVERFLOW_CHECK_CONDITIONAL, Warn, + "Using overflow checks which are likely to panic"); + +#[derive(Copy, Clone)] +pub struct OverflowCheckConditional; + +impl LintPass for OverflowCheckConditional { + fn get_lints(&self) -> LintArray { + lint_array!(OVERFLOW_CHECK_CONDITIONAL) + } +} + +impl LateLintPass for OverflowCheckConditional { + // a + b < a, a > a + b, a < a - b, a - b > a + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! {[ + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, + let Expr_::ExprPath(_, ref path3) = second.node, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() + ], { + if let BinOp_::BiLt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); + } + } + if let BinOp_::BiGt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); + } + } + }} + + if_let_chain! {[ + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, + let Expr_::ExprPath(_, ref path3) = first.node, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() + ], { + if let BinOp_::BiGt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); + } + } + if let BinOp_::BiLt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); + } + } + }} + } +} diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs new file mode 100644 index 00000000000..d744d2a6308 --- /dev/null +++ b/clippy_lints/src/panic.rs @@ -0,0 +1,47 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::ast::LitKind; +use utils::{is_direct_expn_of, match_path, paths, span_lint}; + +/// **What it does:** This lint checks for missing parameters in `panic!`. +/// +/// **Known problems:** Should you want to use curly brackets in `panic!` without any parameter, +/// this lint will warn. +/// +/// **Example:** +/// ``` +/// panic!("This `panic!` is probably missing a parameter there: {}"); +/// ``` +declare_lint! { + pub PANIC_PARAMS, Warn, "missing parameters in `panic!`" +} + +#[allow(missing_copy_implementations)] +pub struct PanicPass; + +impl LintPass for PanicPass { + fn get_lints(&self) -> LintArray { + lint_array!(PANIC_PARAMS) + } +} + +impl LateLintPass for PanicPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain! {[ + let ExprBlock(ref block) = expr.node, + let Some(ref ex) = block.expr, + let ExprCall(ref fun, ref params) = ex.node, + params.len() == 2, + let ExprPath(None, ref path) = fun.node, + match_path(path, &paths::BEGIN_PANIC), + let ExprLit(ref lit) = params[0].node, + is_direct_expn_of(cx, params[0].span, "panic").is_some(), + let LitKind::Str(ref string, _) = lit.node, + let Some(par) = string.find('{'), + string[par..].contains('}') + ], { + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); + }} + } +} diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs new file mode 100644 index 00000000000..825a1b84450 --- /dev/null +++ b/clippy_lints/src/precedence.rs @@ -0,0 +1,118 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::codemap::Spanned; +use utils::{span_lint, snippet}; + +/// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following: +/// * mixed usage of arithmetic and bit shifting/combining operators without parentheses +/// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call +/// +/// **Why is this bad?** Because not everyone knows the precedence of those operators by heart, so expressions like these may trip others trying to reason about the code. +/// +/// **Known problems:** None +/// +/// **Examples:** +/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 +/// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 +declare_lint! { + pub PRECEDENCE, Warn, + "catches operations where precedence may be unclear. See the wiki for a \ + list of cases caught" +} + +#[derive(Copy,Clone)] +pub struct Precedence; + +impl LintPass for Precedence { + fn get_lints(&self) -> LintArray { + lint_array!(PRECEDENCE) + } +} + +impl EarlyLintPass for Precedence { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { + if !is_bit_op(op) { + return; + } + match (is_arith_expr(left), is_arith_expr(right)) { + (true, true) => { + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`({}) {} ({})`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } + (true, false) => { + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`({}) {} {}`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } + (false, true) => { + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("operator precedence can trip the unwary. Consider parenthesizing your \ + expression:`{} {} ({})`", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, ".."))); + } + _ => (), + } + } + + if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.node { + if let ExprKind::MethodCall(_, _, ref args) = rhs.node { + if let Some(slf) = args.first() { + if let ExprKind::Lit(ref lit) = slf.node { + match lit.node { + LitKind::Int(..) | + LitKind::Float(..) | + LitKind::FloatUnsuffixed(..) => { + span_lint(cx, + PRECEDENCE, + expr.span, + &format!("unary minus has lower precedence than method call. Consider \ + adding parentheses to clarify your intent: -({})", + snippet(cx, rhs.span, ".."))); + } + _ => (), + } + } + } + } + } + } +} + +fn is_arith_expr(expr: &Expr) -> bool { + match expr.node { + ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op), + _ => false, + } +} + +fn is_bit_op(op: BinOpKind) -> bool { + use syntax::ast::BinOpKind::*; + match op { + BitXor | BitAnd | BitOr | Shl | Shr => true, + _ => false, + } +} + +fn is_arith_op(op: BinOpKind) -> bool { + use syntax::ast::BinOpKind::*; + match op { + Add | Sub | Mul | Div | Rem => true, + _ => false, + } +} diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs new file mode 100644 index 00000000000..d426286dba4 --- /dev/null +++ b/clippy_lints/src/print.rs @@ -0,0 +1,88 @@ +use rustc::hir::*; +use rustc::hir::map::Node::{NodeItem, NodeImplItem}; +use rustc::lint::*; +use utils::paths; +use utils::{is_expn_of, match_path, span_lint}; + +/// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants. +/// +/// **Why is this bad?** People often print on *stdout* while debugging an application and might +/// forget to remove those prints afterward. +/// +/// **Known problems:** Only catches `print!` and `println!` calls. +/// +/// **Example:** `println!("Hello world!");` +declare_lint! { + pub PRINT_STDOUT, + Allow, + "printing on stdout" +} + +/// **What it does:** This lint warns whenever you use `Debug` formatting. The purpose of this lint is to catch debugging remnants. +/// +/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate debugging Rust code. It +/// should not be used in in user-facing output. +/// +/// **Example:** `println!("{:?}", foo);` +declare_lint! { + pub USE_DEBUG, + Allow, + "use `Debug`-based formatting" +} + +#[derive(Copy, Clone, Debug)] +pub struct PrintLint; + +impl LintPass for PrintLint { + fn get_lints(&self) -> LintArray { + lint_array!(PRINT_STDOUT, USE_DEBUG) + } +} + +impl LateLintPass for PrintLint { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprCall(ref fun, ref args) = expr.node { + if let ExprPath(_, ref path) = fun.node { + // Search for `std::io::_print(..)` which is unique in a + // `print!` expansion. + if match_path(path, &paths::IO_PRINT) { + if let Some(span) = is_expn_of(cx, expr.span, "print") { + // `println!` uses `print!`. + let (span, name) = match is_expn_of(cx, span, "println") { + Some(span) => (span, "println"), + None => (span, "print"), + }; + + span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); + } + } + // Search for something like + // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` + else if args.len() == 2 && match_path(path, &paths::FMT_ARGUMENTV1_NEW) { + if let ExprPath(None, ref path) = args[1].node { + if match_path(path, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && + is_expn_of(cx, expr.span, "panic").is_none() { + span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } + } + } + } + } + } +} + +fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { + let map = &cx.tcx.map; + + // `fmt` method + if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { + // `Debug` impl + if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { + if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node { + return match_path(&tr.path, &["Debug"]); + } + } + } + + false +} diff --git a/clippy_lints/src/ptr_arg.rs b/clippy_lints/src/ptr_arg.rs new file mode 100644 index 00000000000..addcfc9e84d --- /dev/null +++ b/clippy_lints/src/ptr_arg.rs @@ -0,0 +1,78 @@ +//! Checks for usage of `&Vec[_]` and `&String`. + +use rustc::hir::*; +use rustc::hir::map::NodeItem; +use rustc::lint::*; +use rustc::ty; +use syntax::ast::NodeId; +use utils::{match_type, paths, span_lint}; + +/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. +/// +/// **Why is this bad?** Requiring the argument to be of the specific size makes the function less useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be obtained from other types, too. +/// +/// **Known problems:** None +/// +/// **Example:** `fn foo(&Vec<u32>) { .. }` +declare_lint! { + pub PTR_ARG, + Warn, + "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ + instead, respectively" +} + +#[derive(Copy,Clone)] +pub struct PtrArg; + +impl LintPass for PtrArg { + fn get_lints(&self) -> LintArray { + lint_array!(PTR_ARG) + } +} + +impl LateLintPass for PtrArg { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemFn(ref decl, _, _, _, _, _) = item.node { + check_fn(cx, decl, item.id); + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + if let ImplItemKind::Method(ref sig, _) = item.node { + if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { + if let ItemImpl(_, _, _, Some(_), _, _) = it.node { + return; // ignore trait impls + } + } + check_fn(cx, &sig.decl, item.id); + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + if let MethodTraitItem(ref sig, _) = item.node { + check_fn(cx, &sig.decl, item.id); + } + } +} + +fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { + let fn_ty = cx.tcx.node_id_to_type(fn_id).fn_sig().skip_binder(); + + for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) { + if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { + if match_type(cx, ty, &paths::VEC) { + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ + with non-Vec-based slices. Consider changing the type to `&[...]`"); + } else if match_type(cx, ty, &paths::STRING) { + span_lint(cx, + PTR_ARG, + arg.ty.span, + "writing `&String` instead of `&str` involves a new object where a slice will do. \ + Consider changing the type to `&str`"); + } + } + } +} diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs new file mode 100644 index 00000000000..e96212a9cef --- /dev/null +++ b/clippy_lints/src/ranges.rs @@ -0,0 +1,89 @@ +use rustc::lint::*; +use rustc::hir::*; +use syntax::codemap::Spanned; +use utils::{is_integer_literal, match_type, paths, snippet, span_lint, unsugar_range, UnsugaredRange}; + +/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. +/// +/// **Why is this bad?** This very much looks like an oversight, since with `loop { .. }` there is an obvious better way to endlessly loop. +/// +/// **Known problems:** None +/// +/// **Example:** `for x in (5..5).step_by(0) { .. }` +declare_lint! { + pub RANGE_STEP_BY_ZERO, Warn, + "using Range::step_by(0), which produces an infinite iterator" +} +/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. +/// +/// **Why is this bad?** The code is better expressed with `.enumerate()`. +/// +/// **Known problems:** None +/// +/// **Example:** `x.iter().zip(0..x.len())` +declare_lint! { + pub RANGE_ZIP_WITH_LEN, Warn, + "zipping iterator with a range when enumerate() would do" +} + +#[derive(Copy,Clone)] +pub struct StepByZero; + +impl LintPass for StepByZero { + fn get_lints(&self) -> LintArray { + lint_array!(RANGE_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN) + } +} + +impl LateLintPass for StepByZero { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { + // Range with step_by(0). + if name.as_str() == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) && + is_integer_literal(&args[1], 0) { + span_lint(cx, + RANGE_STEP_BY_ZERO, + expr.span, + "Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \ + instead"); + } else if name.as_str() == "zip" && args.len() == 2 { + let iter = &args[0].node; + let zip_arg = &args[1]; + if_let_chain! { + [ + // .iter() call + let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, + iter_name.as_str() == "iter", + // range expression in .zip() call: 0..x.len() + let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), + is_integer_literal(start, 0), + // .len() call + let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, + len_name.as_str() == "len" && len_args.len() == 1, + // .iter() and .len() called on same Path + let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, + let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, + iter_path == len_path + ], { + span_lint(cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); + } + } + } + } + } +} + +fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { + // No need for walk_ptrs_ty here because step_by moves self, so it + // can't be called on a borrowed range. + let ty = cx.tcx.expr_ty(expr); + + // Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by + match_type(cx, ty, &paths::RANGE) + || match_type(cx, ty, &paths::RANGE_FROM) + || match_type(cx, ty, &paths::RANGE_INCLUSIVE) +} diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs new file mode 100644 index 00000000000..c97a64ebf09 --- /dev/null +++ b/clippy_lints/src/regex.rs @@ -0,0 +1,229 @@ +use regex_syntax; +use rustc::hir::*; +use rustc::lint::*; +use rustc::middle::const_val::ConstVal; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; +use std::collections::HashSet; +use std::error::Error; +use syntax::ast::{LitKind, NodeId}; +use syntax::codemap::{Span, BytePos}; +use syntax::parse::token::InternedString; +use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; + +/// **What it does:** This lint checks [regex] creation (with `Regex::new`, `RegexBuilder::new` or +/// `RegexSet::new`) for correct regex syntax. +/// +/// **Why is this bad?** This will lead to a runtime panic. +/// +/// **Known problems:** None. +/// +/// **Example:** `Regex::new("|")` +declare_lint! { + pub INVALID_REGEX, + Deny, + "finds invalid regular expressions" +} + +/// **What it does:** This lint checks for trivial [regex] creation (with `Regex::new`, +/// `RegexBuilder::new` or `RegexSet::new`). +/// +/// **Why is this bad?** This can likely be replaced by `==` or `str::starts_with`, +/// `str::ends_with` or `std::contains` or other `str` methods. +/// +/// **Known problems:** None. +/// +/// **Example:** `Regex::new("^foobar")` +/// +/// [regex]: https://crates.io/crates/regex +declare_lint! { + pub TRIVIAL_REGEX, + Warn, + "finds trivial regular expressions" +} + +/// **What it does:** This lint checks for usage of `regex!(_)` which as of now is usually slower than `Regex::new(_)` unless called in a loop (which is a bad idea anyway). +/// +/// **Why is this bad?** Performance, at least for now. The macro version is likely to catch up long-term, but for now the dynamic version is faster. +/// +/// **Known problems:** None +/// +/// **Example:** `regex!("foo|bar")` +declare_lint! { + pub REGEX_MACRO, + Warn, + "finds use of `regex!(_)`, suggests `Regex::new(_)` instead" +} + +#[derive(Clone, Default)] +pub struct RegexPass { + spans: HashSet<Span>, + last: Option<NodeId>, +} + +impl LintPass for RegexPass { + fn get_lints(&self) -> LintArray { + lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) + } +} + +impl LateLintPass for RegexPass { + fn check_crate(&mut self, _: &LateContext, _: &Crate) { + self.spans.clear(); + } + + fn check_block(&mut self, cx: &LateContext, block: &Block) { + if_let_chain!{[ + self.last.is_none(), + let Some(ref expr) = block.expr, + match_type(cx, cx.tcx.expr_ty(expr), &paths::REGEX), + let Some(span) = is_expn_of(cx, expr.span, "regex"), + ], { + if !self.spans.contains(&span) { + span_lint(cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now."); + self.spans.insert(span); + } + self.last = Some(block.id); + }} + } + + fn check_block_post(&mut self, _: &LateContext, block: &Block) { + if self.last.map_or(false, |id| block.id == id) { + self.last = None; + } + } + + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain!{[ + let ExprCall(ref fun, ref args) = expr.node, + args.len() == 1, + let Some(def) = cx.tcx.def_map.borrow().get(&fun.id), + ], { + let def_id = def.def_id(); + if match_def_path(cx, def_id, &paths::REGEX_NEW) { + check_regex(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) { + check_regex(cx, &args[0], false); + } else if match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { + check_regex(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { + check_regex(cx, &args[0], false); + } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { + check_set(cx, &args[0], true); + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { + check_set(cx, &args[0], false); + } + }} + } +} + +#[allow(cast_possible_truncation)] +fn str_span(base: Span, s: &str, c: usize) -> Span { + let mut si = s.char_indices().skip(c); + + match (si.next(), si.next()) { + (Some((l, _)), Some((h, _))) => { + Span { + lo: base.lo + BytePos(l as u32), + hi: base.lo + BytePos(h as u32), + ..base + } + } + _ => base, + } +} + +fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { + match eval_const_expr_partial(cx.tcx, e, ExprTypeChecked, None) { + Ok(ConstVal::Str(r)) => Some(r), + _ => None, + } +} + +fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { + use regex_syntax::Expr; + + match *s { + Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), + Expr::Literal { .. } => Some("consider using `str::contains`"), + Expr::Concat(ref exprs) => { + match exprs.len() { + 2 => { + match (&exprs[0], &exprs[1]) { + (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), + (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), + (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), + _ => None, + } + } + 3 => { + if let (&Expr::StartText, &Expr::Literal {..}, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { + Some("consider using `==` on `str`s") + } else { + None + } + } + _ => None, + } + } + _ => None, + } +} + +fn check_set(cx: &LateContext, expr: &Expr, utf8: bool) { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, + let ExprVec(ref exprs) = expr.node, + ], { + for expr in exprs { + check_regex(cx, expr, utf8); + } + }} +} + +fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { + let builder = regex_syntax::ExprBuilder::new().unicode(utf8); + + if let ExprLit(ref lit) = expr.node { + if let LitKind::Str(ref r, _) = lit.node { + match builder.parse(r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + "trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { + span_lint(cx, + INVALID_REGEX, + str_span(expr.span, r, e.position()), + &format!("regex syntax error: {}", + e.description())); + } + } + } + } else if let Some(r) = const_str(cx, expr) { + match builder.parse(&r) { + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + "trivial regex", + &format!("consider using {}", repl)); + } + } + Err(e) => { + span_lint(cx, + INVALID_REGEX, + expr.span, + &format!("regex syntax error on position {}: {}", + e.position(), + e.description())); + } + } + } +} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs new file mode 100644 index 00000000000..d7893821263 --- /dev/null +++ b/clippy_lints/src/returns.rs @@ -0,0 +1,137 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::codemap::{Span, Spanned}; +use syntax::visit::FnKind; + +use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; + +/// **What it does:** This lint checks for return statements at the end of a block. +/// +/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty. +/// +/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. +/// +/// **Example:** `fn foo(x: usize) { return x; }` +declare_lint! { + pub NEEDLESS_RETURN, Warn, + "using a return statement like `return expr;` where an expression would suffice" +} + +/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. +/// +/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. +/// +/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. +/// +/// **Example:** `{ let x = ..; x }` +declare_lint! { + pub LET_AND_RETURN, Warn, + "creating a let-binding and then immediately returning it like `let x = expr; x` at \ + the end of a block" +} + +#[derive(Copy, Clone)] +pub struct ReturnPass; + +impl ReturnPass { + // Check the final stmt or expr in a block for unnecessary return. + fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) { + if let Some(ref expr) = block.expr { + self.check_final_expr(cx, expr); + } else if let Some(stmt) = block.stmts.last() { + if let StmtKind::Semi(ref expr, _) = stmt.node { + if let ExprKind::Ret(Some(ref inner)) = expr.node { + self.emit_return_lint(cx, (stmt.span, inner.span)); + } + } + } + } + + // Check a the final expression in a block if it's a return. + fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + match expr.node { + // simple return is always "bad" + ExprKind::Ret(Some(ref inner)) => { + self.emit_return_lint(cx, (expr.span, inner.span)); + } + // a whole block? check it! + ExprKind::Block(ref block) => { + self.check_block_return(cx, block); + } + // an if/if let expr, check both exprs + // note, if without else is going to be a type checking error anyways + // (except for unit type functions) so we don't match it + ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => { + self.check_block_return(cx, ifblock); + self.check_final_expr(cx, elsexpr); + } + // a match expr, check all arms + ExprKind::Match(_, ref arms) => { + for arm in arms { + self.check_final_expr(cx, &arm.body); + } + } + _ => (), + } + } + + fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { + if in_external_macro(cx, spans.1) { + return; + } + span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| { + if let Some(snippet) = snippet_opt(cx, spans.1) { + db.span_suggestion(spans.0, "remove `return` as shown:", snippet); + } + }); + } + + // Check for "let x = EXPR; x" + fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { + // we need both a let-binding stmt and an expr + if_let_chain! { + [ + let Some(stmt) = block.stmts.last(), + let Some(ref retexpr) = block.expr, + let StmtKind::Decl(ref decl, _) = stmt.node, + let DeclKind::Local(ref local) = decl.node, + let Some(ref initexpr) = local.init, + let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, + let ExprKind::Path(_, ref path) = retexpr.node, + match_path_ast(path, &[&id.name.as_str()]) + ], { + self.emit_let_lint(cx, retexpr.span, initexpr.span); + } + } + } + + fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { + if in_external_macro(cx, note_span) { + return; + } + let mut db = span_lint(cx, + LET_AND_RETURN, + lint_span, + "returning the result of a let binding from a block. Consider returning the \ + expression directly."); + if cx.current_level(LET_AND_RETURN) != Level::Allow { + db.span_note(note_span, "this expression can be directly returned"); + } + } +} + +impl LintPass for ReturnPass { + fn get_lints(&self) -> LintArray { + lint_array!(NEEDLESS_RETURN, LET_AND_RETURN) + } +} + +impl EarlyLintPass for ReturnPass { + fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { + self.check_block_return(cx, block); + } + + fn check_block(&mut self, cx: &EarlyContext, block: &Block) { + self.check_let_return(cx, block); + } +} diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs new file mode 100644 index 00000000000..2a0d36a80b3 --- /dev/null +++ b/clippy_lints/src/shadow.rs @@ -0,0 +1,353 @@ +use reexport::*; +use rustc::lint::*; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, FnKind}; +use std::ops::Deref; +use syntax::codemap::Span; +use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; + +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. +/// +/// **Why is this bad?** Not much, in fact it's a very common pattern in Rust code. Still, some may opt to avoid it in their code base, they can set this lint to `Warn`. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = &x;` +declare_lint! { + pub SHADOW_SAME, Allow, + "rebinding a name to itself, e.g. `let mut x = &mut x`" +} + +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. +/// +/// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = x + 1;` +declare_lint! { + pub SHADOW_REUSE, Allow, + "rebinding a name to an expression that re-uses the original value, e.g. \ + `let x = x + 1`" +} + +/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. +/// +/// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings. +/// +/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. +/// +/// **Example:** `let x = y; let x = z; // shadows the earlier binding` +declare_lint! { + pub SHADOW_UNRELATED, Allow, + "The name is re-bound without even using the original value" +} + +#[derive(Copy, Clone)] +pub struct ShadowPass; + +impl LintPass for ShadowPass { + fn get_lints(&self) -> LintArray { + lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) + } +} + +impl LateLintPass for ShadowPass { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { + if in_external_macro(cx, block.span) { + return; + } + check_fn(cx, decl, block); + } +} + +fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { + let mut bindings = Vec::new(); + for arg in &decl.inputs { + if let PatKind::Ident(_, ident, _) = arg.pat.node { + bindings.push((ident.node.unhygienize(), ident.span)) + } + } + check_block(cx, block, &mut bindings); +} + +fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) { + let len = bindings.len(); + for stmt in &block.stmts { + match stmt.node { + StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), + StmtExpr(ref e, _) | + StmtSemi(ref e, _) => check_expr(cx, e, bindings), + } + } + if let Some(ref o) = block.expr { + check_expr(cx, o, bindings); + } + bindings.truncate(len); +} + +fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { + if in_external_macro(cx, decl.span) { + return; + } + if is_from_for_desugar(decl) { + return; + } + if let DeclLocal(ref local) = decl.node { + let Local { ref pat, ref ty, ref init, span, .. } = **local; + if let Some(ref t) = *ty { + check_ty(cx, t, bindings) + } + if let Some(ref o) = *init { + check_expr(cx, o, bindings); + check_pat(cx, pat, &Some(o), span, bindings); + } else { + check_pat(cx, pat, &None, span, bindings); + } + } +} + +fn is_binding(cx: &LateContext, pat: &Pat) -> bool { + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(Def::Variant(..)) | + Some(Def::Struct(..)) => false, + _ => true, + } +} + +fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { + // TODO: match more stuff / destructuring + match pat.node { + PatKind::Ident(_, ref ident, ref inner) => { + let name = ident.node.unhygienize(); + if is_binding(cx, pat) { + let mut new_binding = true; + for tup in bindings.iter_mut() { + if tup.0 == name { + lint_shadow(cx, name, span, pat.span, init, tup.1); + tup.1 = ident.span; + new_binding = false; + break; + } + } + if new_binding { + bindings.push((name, ident.span)); + } + } + if let Some(ref p) = *inner { + check_pat(cx, p, init, span, bindings); + } + } + // PatEnum(Path, Option<Vec<P<Pat>>>), + PatKind::Struct(_, ref pfields, _) => { + if let Some(ref init_struct) = *init { + if let ExprStruct(_, ref efields, _) = init_struct.node { + for field in pfields { + let name = field.node.name; + let efield = efields.iter() + .find(|ref f| f.name.node == name) + .map(|f| &*f.expr); + check_pat(cx, &field.node.pat, &efield, span, bindings); + } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, init, span, bindings); + } + } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, &None, span, bindings); + } + } + } + PatKind::Tup(ref inner) => { + if let Some(ref init_tup) = *init { + if let ExprTup(ref tup) = init_tup.node { + for (i, p) in inner.iter().enumerate() { + check_pat(cx, p, &Some(&tup[i]), p.span, bindings); + } + } else { + for p in inner { + check_pat(cx, p, init, span, bindings); + } + } + } else { + for p in inner { + check_pat(cx, p, &None, span, bindings); + } + } + } + PatKind::Box(ref inner) => { + if let Some(ref initp) = *init { + if let ExprBox(ref inner_init) = initp.node { + check_pat(cx, inner, &Some(&**inner_init), span, bindings); + } else { + check_pat(cx, inner, init, span, bindings); + } + } else { + check_pat(cx, inner, init, span, bindings); + } + } + PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), + // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), + _ => (), + } +} + +fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span) + where T: Deref<Target = Expr> +{ + fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { + if cx.current_level(lint) != Level::Allow { + db.span_note(span, "previous binding is here"); + } + } + if let Some(ref expr) = *init { + if is_self_shadow(name, expr) { + let db = span_lint(cx, + SHADOW_SAME, + span, + &format!("`{}` is shadowed by itself in `{}`", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, ".."))); + + note_orig(cx, db, SHADOW_SAME, prev_span); + } else if contains_self(name, expr) { + let db = span_note_and_lint(cx, + SHADOW_REUSE, + pattern_span, + &format!("`{}` is shadowed by `{}` which reuses the original value", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); + note_orig(cx, db, SHADOW_REUSE, prev_span); + } else { + let db = span_note_and_lint(cx, + SHADOW_UNRELATED, + pattern_span, + &format!("`{}` is shadowed by `{}`", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..")), + expr.span, + "initialization happens here"); + note_orig(cx, db, SHADOW_UNRELATED, prev_span); + } + + } else { + let db = span_lint(cx, + SHADOW_UNRELATED, + span, + &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_"))); + note_orig(cx, db, SHADOW_UNRELATED, prev_span); + } +} + +fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { + if in_external_macro(cx, expr.span) { + return; + } + match expr.node { + ExprUnary(_, ref e) | + ExprField(ref e, _) | + ExprTupField(ref e, _) | + ExprAddrOf(_, ref e) | + ExprBox(ref e) => check_expr(cx, e, bindings), + ExprBlock(ref block) | + ExprLoop(ref block, _) => check_block(cx, block, bindings), + // ExprCall + // ExprMethodCall + ExprVec(ref v) | ExprTup(ref v) => { + for ref e in v { + check_expr(cx, e, bindings) + } + } + ExprIf(ref cond, ref then, ref otherwise) => { + check_expr(cx, cond, bindings); + check_block(cx, then, bindings); + if let Some(ref o) = *otherwise { + check_expr(cx, o, bindings); + } + } + ExprWhile(ref cond, ref block, _) => { + check_expr(cx, cond, bindings); + check_block(cx, block, bindings); + } + ExprMatch(ref init, ref arms, _) => { + check_expr(cx, init, bindings); + let len = bindings.len(); + for ref arm in arms { + for ref pat in &arm.pats { + check_pat(cx, pat, &Some(&**init), pat.span, bindings); + // This is ugly, but needed to get the right type + if let Some(ref guard) = arm.guard { + check_expr(cx, guard, bindings); + } + check_expr(cx, &arm.body, bindings); + bindings.truncate(len); + } + } + } + _ => (), + } +} + +fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { + match ty.node { + TyObjectSum(ref sty, _) | + TyVec(ref sty) => check_ty(cx, sty, bindings), + TyFixedLengthVec(ref fty, ref expr) => { + check_ty(cx, fty, bindings); + check_expr(cx, expr, bindings); + } + TyPtr(MutTy { ty: ref mty, .. }) | + TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyTup(ref tup) => { + for ref t in tup { + check_ty(cx, t, bindings) + } + } + TyTypeof(ref expr) => check_expr(cx, expr, bindings), + _ => (), + } +} + +fn is_self_shadow(name: Name, expr: &Expr) -> bool { + match expr.node { + ExprBox(ref inner) | + ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), + ExprBlock(ref block) => { + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |ref e| is_self_shadow(name, e)) + } + ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), + ExprPath(_, ref path) => path_eq_name(name, path), + _ => false, + } +} + +fn path_eq_name(name: Name, path: &Path) -> bool { + !path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name +} + +struct ContainsSelf { + name: Name, + result: bool, +} + +impl<'v> Visitor<'v> for ContainsSelf { + fn visit_name(&mut self, _: Span, name: Name) { + if self.name == name.unhygienize() { + self.result = true; + } + } +} + +fn contains_self(name: Name, expr: &Expr) -> bool { + let mut cs = ContainsSelf { + name: name, + result: false, + }; + cs.visit_expr(expr); + cs.result +} diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs new file mode 100644 index 00000000000..92bce8d0e42 --- /dev/null +++ b/clippy_lints/src/strings.rs @@ -0,0 +1,160 @@ +//! This lint catches both string addition and string addition + assignment +//! +//! Note that since we have two lints where one subsumes the other, we try to +//! disable the subsumed lint unless it has a higher level + +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::Spanned; +use utils::SpanlessEq; +use utils::{match_type, paths, span_lint, span_lint_and_then, walk_ptrs_ty, get_parent_expr}; + +/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). +/// +/// **Why is this bad?** It's not really bad, but some people think that the `.push_str(_)` method is more readable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ``` +/// let mut x = "Hello".to_owned(); +/// x = x + ", World"; +/// ``` +declare_lint! { + pub STRING_ADD_ASSIGN, + Allow, + "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" +} + +/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. +/// +/// **Why is this bad?** It's not bad in and of itself. However, this particular `Add` implementation is asymmetric (the other operand need not be `String`, but `x` does), while addition as mathematically defined is symmetric, also the `String::push_str(_)` function is a perfectly good replacement. Therefore some dislike it and wish not to have it in their code. +/// +/// That said, other people think that String addition, having a long tradition in other languages is actually fine, which is why we decided to make this particular lint `allow` by default. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ``` +/// let x = "Hello".to_owned(); +/// x + ", World" +/// ``` +declare_lint! { + pub STRING_ADD, + Allow, + "using `x + ..` where x is a `String`; suggests using `push_str()` instead" +} + +/// **What it does:** This lint matches the `as_bytes` method called on string +/// literals that contain only ascii characters. +/// +/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used instead. They are shorter but less discoverable than `as_bytes()`. +/// +/// **Example:** +/// +/// ``` +/// let bs = "a byte string".as_bytes(); +/// ``` +declare_lint! { + pub STRING_LIT_AS_BYTES, + Warn, + "calling `as_bytes` on a string literal; suggests using a byte string literal instead" +} + +#[derive(Copy, Clone)] +pub struct StringAdd; + +impl LintPass for StringAdd { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_ADD, STRING_ADD_ASSIGN) + } +} + +impl LateLintPass for StringAdd { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { + if is_string(cx, left) { + if let Allow = cx.current_level(STRING_ADD_ASSIGN) { + // the string_add_assign is allow, so no duplicates + } else { + let parent = get_parent_expr(cx, e); + if let Some(ref p) = parent { + if let ExprAssign(ref target, _) = p.node { + // avoid duplicate matches + if SpanlessEq::new(cx).eq_expr(target, left) { + return; + } + } + } + } + span_lint(cx, + STRING_ADD, + e.span, + "you added something to a string. Consider using `String::push_str()` instead"); + } + } else if let ExprAssign(ref target, ref src) = e.node { + if is_string(cx, target) && is_add(cx, src, target) { + span_lint(cx, + STRING_ADD_ASSIGN, + e.span, + "you assigned the result of adding something to this string. Consider using \ + `String::push_str()` instead"); + } + } + } +} + +fn is_string(cx: &LateContext, e: &Expr) -> bool { + match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &paths::STRING) +} + +fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { + match src.node { + ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), + ExprBlock(ref block) => { + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) + } + _ => false, + } +} + +#[derive(Copy, Clone)] +pub struct StringLitAsBytes; + +impl LintPass for StringLitAsBytes { + fn get_lints(&self) -> LintArray { + lint_array!(STRING_LIT_AS_BYTES) + } +} + +impl LateLintPass for StringLitAsBytes { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + use std::ascii::AsciiExt; + use syntax::ast::LitKind; + use utils::{snippet, in_macro}; + + if let ExprMethodCall(ref name, _, ref args) = e.node { + if name.node.as_str() == "as_bytes" { + if let ExprLit(ref lit) = args[0].node { + if let LitKind::Str(ref lit_content, _) = lit.node { + if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, args[0].span) { + span_lint_and_then(cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on a string literal", + |db| { + let sugg = format!("b{}", snippet(cx, args[0].span, r#""foo""#)); + db.span_suggestion(e.span, + "consider using a byte string literal instead", + sugg); + }); + + } + } + } + } + } + } +} diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs new file mode 100644 index 00000000000..c5572181395 --- /dev/null +++ b/clippy_lints/src/swap.rs @@ -0,0 +1,138 @@ +use rustc::lint::*; +use rustc::hir::*; +use syntax::codemap::mk_sp; +use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; + +/// **What it does:** This lints manual swapping. +/// +/// **Why is this bad?** The `std::mem::swap` function exposes the intent better without +/// deinitializing or copying either variable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let t = b; +/// b = a; +/// a = t; +/// ``` +declare_lint! { + pub MANUAL_SWAP, + Warn, + "manual swap" +} + +/// **What it does:** This lints `foo = bar; bar = foo` sequences. +/// +/// **Why is this bad?** This looks like a failed attempt to swap. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// a = b; +/// b = a; +/// ``` +declare_lint! { + pub ALMOST_SWAPPED, + Warn, + "`foo = bar; bar = foo` sequence" +} + +#[derive(Copy,Clone)] +pub struct Swap; + +impl LintPass for Swap { + fn get_lints(&self) -> LintArray { + lint_array![MANUAL_SWAP, ALMOST_SWAPPED] + } +} + +impl LateLintPass for Swap { + fn check_block(&mut self, cx: &LateContext, block: &Block) { + check_manual_swap(cx, block); + check_suspicious_swap(cx, block); + } +} + +/// Implementation of the `MANUAL_SWAP` lint. +fn check_manual_swap(cx: &LateContext, block: &Block) { + for w in block.stmts.windows(3) { + if_let_chain!{[ + // let t = foo(); + let StmtDecl(ref tmp, _) = w[0].node, + let DeclLocal(ref tmp) = tmp.node, + let Some(ref tmp_init) = tmp.init, + let PatKind::Ident(_, ref tmp_name, None) = tmp.pat.node, + + // foo() = bar(); + let StmtSemi(ref first, _) = w[1].node, + let ExprAssign(ref lhs1, ref rhs1) = first.node, + + // bar() = t; + let StmtSemi(ref second, _) = w[2].node, + let ExprAssign(ref lhs2, ref rhs2) = second.node, + let ExprPath(None, ref rhs2) = rhs2.node, + rhs2.segments.len() == 1, + + tmp_name.node.as_str() == rhs2.segments[0].name.as_str(), + SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), + SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) + ], { + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { + (format!(" `{}` and `{}`", first, second), first, second) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; + + let span = mk_sp(tmp.span.lo, second.span.hi); + + span_lint_and_then(cx, + MANUAL_SWAP, + span, + &format!("this looks like you are swapping{} manually", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); + db.note("or maybe you should use `std::mem::replace`?"); + } + }); + }} + } +} + +/// Implementation of the `ALMOST_SWAPPED` lint. +fn check_suspicious_swap(cx: &LateContext, block: &Block) { + for w in block.stmts.windows(2) { + if_let_chain!{[ + let StmtSemi(ref first, _) = w[0].node, + let StmtSemi(ref second, _) = w[1].node, + !differing_macro_contexts(first.span, second.span), + let ExprAssign(ref lhs0, ref rhs0) = first.node, + let ExprAssign(ref lhs1, ref rhs1) = second.node, + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), + SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) + ], { + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { + (format!(" `{}` and `{}`", first, second), first, second) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; + + let span = mk_sp(first.span.lo, second.span.hi); + + span_lint_and_then(cx, + ALMOST_SWAPPED, + span, + &format!("this looks like you are trying to swap{}", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); + db.note("or maybe you should use `std::mem::replace`?"); + } + }); + }} + } +} diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs new file mode 100644 index 00000000000..1496a45dac2 --- /dev/null +++ b/clippy_lints/src/temporary_assignment.rs @@ -0,0 +1,49 @@ +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; +use utils::is_adjusted; +use utils::span_lint; + +/// **What it does:** This lint checks for construction of a structure or tuple just to assign a value in it. +/// +/// **Why is this bad?** Readability. If the structure is only created to be updated, why not write the structure you want in the first place? +/// +/// **Known problems:** None. +/// +/// **Example:** `(0, 0).0 = 1` +declare_lint! { + pub TEMPORARY_ASSIGNMENT, + Warn, + "assignments to temporaries" +} + +fn is_temporary(expr: &Expr) -> bool { + match expr.node { + ExprStruct(..) | ExprTup(..) => true, + _ => false, + } +} + +#[derive(Copy, Clone)] +pub struct TemporaryAssignmentPass; + +impl LintPass for TemporaryAssignmentPass { + fn get_lints(&self) -> LintArray { + lint_array!(TEMPORARY_ASSIGNMENT) + } +} + +impl LateLintPass for TemporaryAssignmentPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprAssign(ref target, _) = expr.node { + match target.node { + ExprField(ref base, _) | + ExprTupField(ref base, _) => { + if is_temporary(base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); + } + } + _ => (), + } + } + } +} diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs new file mode 100644 index 00000000000..2217fd59bd9 --- /dev/null +++ b/clippy_lints/src/transmute.rs @@ -0,0 +1,131 @@ +use rustc::lint::*; +use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; +use rustc::ty; +use rustc::hir::*; +use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; + +/// **What it does:** This lint checks for transmutes to the original type of the object. +/// +/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type. +/// +/// **Known problems:** None. +/// +/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `t`'s. +declare_lint! { + pub USELESS_TRANSMUTE, + Warn, + "transmutes that have the same to and from types" +} + +/// **What it does:*** This lint checks for transmutes between a type `T` and `*T`. +/// +/// **Why is this bad?** It's easy to mistakenly transmute between a type and a pointer to that type. +/// +/// **Known problems:** None. +/// +/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `*t` or `&t`'s. +declare_lint! { + pub CROSSPOINTER_TRANSMUTE, + Warn, + "transmutes that have to or from types that are a pointer to the other" +} + +/// **What it does:*** This lint checks for transmutes from a pointer to a reference. +/// +/// **Why is this bad?** This can always be rewritten with `&` and `*`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: &T = std::mem::transmute(p); // where p: *const T +/// // can be written: +/// let _: &T = &*p; +/// ``` +declare_lint! { + pub TRANSMUTE_PTR_TO_REF, + Warn, + "transmutes from a pointer to a reference type" +} + +pub struct Transmute; + +impl LintPass for Transmute { + fn get_lints(&self) -> LintArray { + lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE] + } +} + +impl LateLintPass for Transmute { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprCall(ref path_expr, ref args) = e.node { + if let ExprPath(None, _) = path_expr.node { + let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + + if match_def_path(cx, def_id, &paths::TRANSMUTE) { + let from_ty = cx.tcx.expr_ty(&args[0]); + let to_ty = cx.tcx.expr_ty(e); + + if from_ty == to_ty { + span_lint(cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty)); + } else if is_ptr_to(to_ty, from_ty) { + span_lint(cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", + from_ty, + to_ty)); + } else if is_ptr_to(from_ty, to_ty) { + span_lint(cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty)); + } else { + check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); + } + } + } + } + } +} + +fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { + if let TyRawPtr(from_ptr) = from.sty { + from_ptr.ty == to + } else { + false + } +} + +fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) { + if let TyRawPtr(ref from_pty) = from_ty.sty { + if let TyRef(_, ref to_rty) = to_ty.sty { + let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", + from_ty, + to_ty); + span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| { + if let Some(arg) = snippet_opt(cx, arg.span) { + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; + + + let sugg = if from_pty.ty == to_rty.ty { + format!("{}{}", deref, arg) + } else { + format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + }; + + db.span_suggestion(e.span, "try", sugg); + } + }); + } + } +} diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs new file mode 100644 index 00000000000..c4b810a7880 --- /dev/null +++ b/clippy_lints/src/types.rs @@ -0,0 +1,974 @@ +use reexport::*; +use rustc::hir::*; +use rustc::hir::intravisit::{FnKind, Visitor, walk_ty}; +use rustc::lint::*; +use rustc::ty; +use std::cmp::Ordering; +use syntax::ast::{IntTy, UintTy, FloatTy}; +use syntax::codemap::Span; +use utils::{comparisons, in_external_macro, in_macro, is_from_for_desugar, match_def_path, snippet, + span_help_and_lint, span_lint}; +use utils::paths; + +/// Handles all the linting of funky types +#[allow(missing_copy_implementations)] +pub struct TypePass; + +/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. +/// +/// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever. +/// +/// **Known problems:** None +/// +/// **Example:** `struct X { values: Box<Vec<Foo>> }` +declare_lint! { + pub BOX_VEC, Warn, + "usage of `Box<Vec<T>>`, vector elements are already on the heap" +} + +/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). +/// +/// **Why is this bad?** Gankro says: +/// +/// >The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection. It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while "only" amortized for push/pop, should be faster in the general case for almost every possible workload, and isn't even amortized at all if you can predict the capacity you need. +/// > +/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists. This is because they can just mangle some pointers instead of actually copying the data. Even if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better because of how expensive it is to seek to the middle of a `LinkedList`. +/// +/// **Known problems:** False positives – the instances where using a `LinkedList` makes sense are few and far between, but they can still happen. +/// +/// **Example:** `let x = LinkedList::new();` +declare_lint! { + pub LINKEDLIST, Warn, + "usage of LinkedList, usually a vector is faster, or a more specialized data \ + structure like a VecDeque" +} + +impl LintPass for TypePass { + fn get_lints(&self) -> LintArray { + lint_array!(BOX_VEC, LINKEDLIST) + } +} + +impl LateLintPass for TypePass { + fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) { + if in_macro(cx, ast_ty.span) { + return; + } + if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { + if let def::Def::Struct(..) = did.full_def() { + if Some(did.def_id()) == cx.tcx.lang_items.owned_box() { + if_let_chain! { + [ + let TyPath(_, ref path) = ast_ty.node, + let Some(ref last) = path.segments.last(), + let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, + let Some(ref vec) = ag.types.get(0), + let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), + let def::Def::Struct(..) = did.full_def(), + match_def_path(cx, did.def_id(), &paths::VEC), + ], + { + span_help_and_lint(cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); + } + } + } else if match_def_path(cx, did.def_id(), &paths::LINKED_LIST) { + span_help_and_lint(cx, + LINKEDLIST, + ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a VecDeque might work"); + } + } + } + } +} + +#[allow(missing_copy_implementations)] +pub struct LetPass; + +/// **What it does:** This lint checks for binding a unit value. +/// +/// **Why is this bad?** A unit value cannot usefully be used anywhere. So binding one is kind of pointless. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = { 1; };` +declare_lint! { + pub LET_UNIT_VALUE, Warn, + "creating a let binding to a value of unit type, which usually can't be used afterwards" +} + +fn check_let_unit(cx: &LateContext, decl: &Decl) { + if let DeclLocal(ref local) = decl.node { + let bindtype = &cx.tcx.pat_ty(&local.pat).sty; + if *bindtype == ty::TyTuple(&[]) { + if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { + return; + } + if is_from_for_desugar(decl) { + return; + } + span_lint(cx, + LET_UNIT_VALUE, + decl.span, + &format!("this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, ".."))); + } + } +} + +impl LintPass for LetPass { + fn get_lints(&self) -> LintArray { + lint_array!(LET_UNIT_VALUE) + } +} + +impl LateLintPass for LetPass { + fn check_decl(&mut self, cx: &LateContext, decl: &Decl) { + check_let_unit(cx, decl) + } +} + +/// **What it does:** This lint checks for comparisons to unit. +/// +/// **Why is this bad?** Unit is always equal to itself, and thus is just a clumsily written constant. Mostly this happens when someone accidentally adds semicolons at the end of the operands. +/// +/// **Known problems:** None +/// +/// **Example:** `if { foo(); } == { bar(); } { baz(); }` is equal to `{ foo(); bar(); baz(); }` +declare_lint! { + pub UNIT_CMP, Warn, + "comparing unit values (which is always `true` or `false`, respectively)" +} + +#[allow(missing_copy_implementations)] +pub struct UnitCmp; + +impl LintPass for UnitCmp { + fn get_lints(&self) -> LintArray { + lint_array!(UNIT_CMP) + } +} + +impl LateLintPass for UnitCmp { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if in_macro(cx, expr.span) { + return; + } + if let ExprBinary(ref cmp, ref left, _) = expr.node { + let op = cmp.node; + let sty = &cx.tcx.expr_ty(left).sty; + if *sty == ty::TyTuple(&[]) && op.is_comparison() { + let result = match op { + BiEq | BiLe | BiGe => "true", + _ => "false", + }; + span_lint(cx, + UNIT_CMP, + expr.span, + &format!("{}-comparison of unit values detected. This will always be {}", + op.as_str(), + result)); + } + } + } +} + +pub struct CastPass; + +/// **What it does:** This lint checks for casts from any numerical to a float type where the receiving type cannot store all values from the original type without rounding errors. This possible rounding is to be expected, so this lint is `Allow` by default. +/// +/// Basically, this warns on casting any integer with 32 or more bits to `f32` or any 64-bit integer to `f64`. +/// +/// **Why is this bad?** It's not bad at all. But in some applications it can be helpful to know where precision loss can take place. This lint can help find those places in the code. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = u64::MAX; x as f64` +declare_lint! { + pub CAST_PRECISION_LOSS, Allow, + "casts that cause loss of precision, e.g `x as f32` where `x: u64`" +} + +/// **What it does:** This lint checks for casts from a signed to an unsigned numerical type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default. +/// +/// **Why is this bad?** Possibly surprising results. You can activate this lint as a one-time check to see where numerical wrapping can arise. +/// +/// **Known problems:** None +/// +/// **Example:** `let y : i8 = -1; y as u64` will return 18446744073709551615 +declare_lint! { + pub CAST_SIGN_LOSS, Allow, + "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`" +} + +/// **What it does:** This lint checks for on casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by default. +/// +/// **Why is this bad?** In some problem domains, it is good practice to avoid truncation. This lint can be activated to help assess where additional checks could be beneficial. +/// +/// **Known problems:** None +/// +/// **Example:** `fn as_u8(x: u64) -> u8 { x as u8 }` +declare_lint! { + pub CAST_POSSIBLE_TRUNCATION, Allow, + "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`" +} + +/// **What it does:** This lint checks for casts from an unsigned type to a signed type of the same size. Performing such a cast is a 'no-op' for the compiler, i.e. nothing is changed at the bit level, and the binary representation of the value is reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default. +/// +/// **Why is this bad?** While such a cast is not bad in itself, the results can be surprising when this is not the intended behavior, as demonstrated by the example below. +/// +/// **Known problems:** None +/// +/// **Example:** `u32::MAX as i32` will yield a value of `-1`. +declare_lint! { + pub CAST_POSSIBLE_WRAP, Allow, + "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`" +} + +/// Returns the size in bits of an integral type. +/// Will return 0 if the type is not an int or uint variant +fn int_ty_to_nbits(typ: &ty::TyS) -> usize { + let n = match typ.sty { + ty::TyInt(i) => 4 << (i as usize), + ty::TyUint(u) => 4 << (u as usize), + _ => 0, + }; + // n == 4 is the usize/isize case + if n == 4 { + ::std::mem::size_of::<usize>() * 8 + } else { + n + } +} + +fn is_isize_or_usize(typ: &ty::TyS) -> bool { + match typ.sty { + ty::TyInt(IntTy::Is) | + ty::TyUint(UintTy::Us) => true, + _ => false, + } +} + +fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { + let mantissa_nbits = if cast_to_f64 { + 52 + } else { + 23 + }; + let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; + let arch_dependent_str = "on targets with 64-bit wide pointers "; + let from_nbits_str = if arch_dependent { + "64".to_owned() + } else if is_isize_or_usize(cast_from) { + "32 or 64".to_owned() + } else { + int_ty_to_nbits(cast_from).to_string() + }; + span_lint(cx, + CAST_PRECISION_LOSS, + expr.span, + &format!("casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ + is only {4} bits wide)", + cast_from, + if cast_to_f64 { + "f64" + } else { + "f32" + }, + if arch_dependent { + arch_dependent_str + } else { + "" + }, + from_nbits_str, + mantissa_nbits)); +} + +enum ArchSuffix { + _32, + _64, + None, +} + +fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { + let arch_64_suffix = " on targets with 64-bit wide pointers"; + let arch_32_suffix = " on targets with 32-bit wide pointers"; + let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); + let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); + let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), + is_isize_or_usize(cast_to)) { + (true, true) | (false, false) => { + (to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None) + } + (true, false) => { + (to_nbits <= 32, + if to_nbits == 32 { + ArchSuffix::_64 + } else { + ArchSuffix::None + }, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32) + } + (false, true) => { + (from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 { + ArchSuffix::_64 + } else { + ArchSuffix::_32 + }) + } + }; + if span_truncation { + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!("casting {} to {} may truncate the value{}", + cast_from, + cast_to, + match suffix_truncation { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + })); + } + if span_wrap { + span_lint(cx, + CAST_POSSIBLE_WRAP, + expr.span, + &format!("casting {} to {} may wrap around the value{}", + cast_from, + cast_to, + match suffix_wrap { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + })); + } +} + +impl LintPass for CastPass { + fn get_lints(&self) -> LintArray { + lint_array!(CAST_PRECISION_LOSS, + CAST_SIGN_LOSS, + CAST_POSSIBLE_TRUNCATION, + CAST_POSSIBLE_WRAP) + } +} + +impl LateLintPass for CastPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprCast(ref ex, _) = expr.node { + let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr)); + if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { + match (cast_from.is_integral(), cast_to.is_integral()) { + (true, false) => { + let from_nbits = int_ty_to_nbits(cast_from); + let to_nbits = if let ty::TyFloat(FloatTy::F32) = cast_to.sty { + 32 + } else { + 64 + }; + if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { + span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); + } + } + (false, true) => { + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!("casting {} to {} may truncate the value", cast_from, cast_to)); + if !cast_to.is_signed() { + span_lint(cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + } + } + (true, true) => { + if cast_from.is_signed() && !cast_to.is_signed() { + span_lint(cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + } + check_truncation_and_wrapping(cx, expr, cast_from, cast_to); + } + (false, false) => { + if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, + &cast_to.sty) { + span_lint(cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + "casting f64 to f32 may truncate the value"); + } + } + } + } + } + } +} + +/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. +/// +/// **Why is this bad?** Too complex types make the code less readable. Consider using a `type` definition to simplify them. +/// +/// **Known problems:** None +/// +/// **Example:** `struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }` +declare_lint! { + pub TYPE_COMPLEXITY, Warn, + "usage of very complex types; recommends factoring out parts into `type` definitions" +} + +#[allow(missing_copy_implementations)] +pub struct TypeComplexityPass { + threshold: u64, +} + +impl TypeComplexityPass { + pub fn new(threshold: u64) -> Self { + TypeComplexityPass { threshold: threshold } + } +} + +impl LintPass for TypeComplexityPass { + fn get_lints(&self) -> LintArray { + lint_array!(TYPE_COMPLEXITY) + } +} + +impl LateLintPass for TypeComplexityPass { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + self.check_fndecl(cx, decl); + } + + fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { + // enum variants are also struct fields now + self.check_type(cx, &field.ty); + } + + fn check_item(&mut self, cx: &LateContext, item: &Item) { + match item.node { + ItemStatic(ref ty, _, _) | + ItemConst(ref ty, _) => self.check_type(cx, ty), + // functions, enums, structs, impls and traits are covered + _ => (), + } + } + + fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + match item.node { + ConstTraitItem(ref ty, _) | + TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty), + MethodTraitItem(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl), + // methods with default impl are covered by check_fn + _ => (), + } + } + + fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { + match item.node { + ImplItemKind::Const(ref ty, _) | + ImplItemKind::Type(ref ty) => self.check_type(cx, ty), + // methods are covered by check_fn + _ => (), + } + } + + fn check_local(&mut self, cx: &LateContext, local: &Local) { + if let Some(ref ty) = local.ty { + self.check_type(cx, ty); + } + } +} + +impl TypeComplexityPass { + fn check_fndecl(&self, cx: &LateContext, decl: &FnDecl) { + for arg in &decl.inputs { + self.check_type(cx, &arg.ty); + } + if let Return(ref ty) = decl.output { + self.check_type(cx, ty); + } + } + + fn check_type(&self, cx: &LateContext, ty: &Ty) { + if in_macro(cx, ty.span) { + return; + } + let score = { + let mut visitor = TypeComplexityVisitor { + score: 0, + nest: 1, + }; + visitor.visit_ty(ty); + visitor.score + }; + + if score > self.threshold { + span_lint(cx, + TYPE_COMPLEXITY, + ty.span, + "very complex type used. Consider factoring parts into `type` definitions"); + } + } +} + +/// Walks a type and assigns a complexity score to it. +struct TypeComplexityVisitor { + /// total complexity score of the type + score: u64, + /// current nesting level + nest: u64, +} + +impl<'v> Visitor<'v> for TypeComplexityVisitor { + fn visit_ty(&mut self, ty: &'v Ty) { + let (add_score, sub_nest) = match ty.node { + // _, &x and *x have only small overhead; don't mess with nesting level + TyInfer | TyPtr(..) | TyRptr(..) => (1, 0), + + // the "normal" components of a type: named types, arrays/tuples + TyPath(..) | + TyVec(..) | + TyTup(..) | + TyFixedLengthVec(..) => (10 * self.nest, 1), + + // "Sum" of trait bounds + TyObjectSum(..) => (20 * self.nest, 0), + + // function types and "for<...>" bring a lot of overhead + TyBareFn(..) | + TyPolyTraitRef(..) => (50 * self.nest, 1), + + _ => (0, 0), + }; + self.score += add_score; + self.nest += sub_nest; + walk_ty(self, ty); + self.nest -= sub_nest; + } +} + +/// **What it does:** This lint points out expressions where a character literal is casted to `u8` and suggests using a byte literal instead. +/// +/// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`. +/// +/// **Known problems:** None +/// +/// **Example:** `'x' as u8` +declare_lint! { + pub CHAR_LIT_AS_U8, Warn, + "Casting a character literal to u8" +} + +pub struct CharLitAsU8; + +impl LintPass for CharLitAsU8 { + fn get_lints(&self) -> LintArray { + lint_array!(CHAR_LIT_AS_U8) + } +} + +impl LateLintPass for CharLitAsU8 { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + use syntax::ast::{LitKind, UintTy}; + + if let ExprCast(ref e, _) = expr.node { + if let ExprLit(ref l) = e.node { + if let LitKind::Char(_) = l.node { + if ty::TyUint(UintTy::U8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { + let msg = "casting character literal to u8. `char`s \ + are 4 bytes wide in rust, so casting to u8 \ + truncates them"; + let help = format!("Consider using a byte literal \ + instead:\nb{}", + snippet(cx, e.span, "'x'")); + span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help); + } + } + } + } + } +} + +/// **What it does:** This lint checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked. +/// +/// **Why is this bad?** An expression like `min <= x` may misleadingly imply that is is possible for `x` to be less than the minimum. Expressions like `max < x` are probably mistakes. +/// +/// **Known problems:** None +/// +/// **Example:** `vec.len() <= 0`, `100 > std::i32::MAX` +declare_lint! { + pub ABSURD_EXTREME_COMPARISONS, Warn, + "a comparison involving a maximum or minimum value involves a case that is always \ + true or always false" +} + +pub struct AbsurdExtremeComparisons; + +impl LintPass for AbsurdExtremeComparisons { + fn get_lints(&self) -> LintArray { + lint_array!(ABSURD_EXTREME_COMPARISONS) + } +} + +enum ExtremeType { + Minimum, + Maximum, +} + +struct ExtremeExpr<'a> { + which: ExtremeType, + expr: &'a Expr, +} + +enum AbsurdComparisonResult { + AlwaysFalse, + AlwaysTrue, + InequalityImpossible, +} + + + +fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) + -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { + use types::ExtremeType::*; + use types::AbsurdComparisonResult::*; + use utils::comparisons::*; + type Extr<'a> = ExtremeExpr<'a>; + + let normalized = normalize_comparison(op, lhs, rhs); + let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { + val + } else { + return None; + }; + + let lx = detect_extreme_expr(cx, normalized_lhs); + let rx = detect_extreme_expr(cx, normalized_rhs); + + Some(match rel { + Rel::Lt => { + match (lx, rx) { + (Some(l @ Extr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x + (_, Some(r @ Extr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min + _ => return None, + } + } + Rel::Le => { + match (lx, rx) { + (Some(l @ Extr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x + (Some(l @ Extr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x + (_, Some(r @ Extr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min + (_, Some(r @ Extr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max + _ => return None, + } + } + Rel::Ne | Rel::Eq => return None, + }) +} + +fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeExpr<'a>> { + use rustc::middle::const_val::ConstVal::*; + use rustc_const_math::*; + use rustc_const_eval::EvalHint::ExprTypeChecked; + use rustc_const_eval::*; + use types::ExtremeType::*; + + let ty = &cx.tcx.expr_ty(expr).sty; + + match *ty { + ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (), + _ => return None, + }; + + let cv = match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + Ok(val) => val, + Err(_) => return None, + }; + + let which = match (ty, cv) { + (&ty::TyBool, Bool(false)) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | + (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | + (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | + (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | + (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | + (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | + (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | + (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum, + + (&ty::TyBool, Bool(true)) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | + (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | + (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | + (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | + (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | + (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | + (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | + (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | + (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | + (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) => Maximum, + + _ => return None, + }; + Some(ExtremeExpr { + which: which, + expr: expr, + }) +} + +impl LateLintPass for AbsurdExtremeComparisons { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + use types::ExtremeType::*; + use types::AbsurdComparisonResult::*; + + if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { + if !in_macro(cx, expr.span) { + let msg = "this comparison involving the minimum or maximum element for this \ + type contains a case that is always true or always false"; + + let conclusion = match result { + AlwaysFalse => "this comparison is always false".to_owned(), + AlwaysTrue => "this comparison is always true".to_owned(), + InequalityImpossible => { + format!("the case where the two sides are not equal never occurs, consider using {} == {} \ + instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs")) + } + }; + + let help = format!("because {} is the {} value for this type, {}", + snippet(cx, culprit.expr.span, "x"), + match culprit.which { + Minimum => "minimum", + Maximum => "maximum", + }, + conclusion); + + span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help); + } + } + } + } +} + +/// **What it does:** This lint checks for comparisons where the relation is always either true or false, but where one side has been upcast so that the comparison is necessary. Only integer types are checked. +/// +/// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` will mistakenly imply that it is possible for `x` to be outside the range of `u8`. +/// +/// **Known problems:** https://github.com/Manishearth/rust-clippy/issues/886 +/// +/// **Example:** `let x : u8 = ...; (x as u32) > 300` +declare_lint! { + pub INVALID_UPCAST_COMPARISONS, Allow, + "a comparison involving an upcast which is always true or false" +} + +pub struct InvalidUpcastComparisons; + +impl LintPass for InvalidUpcastComparisons { + fn get_lints(&self) -> LintArray { + lint_array!(INVALID_UPCAST_COMPARISONS) + } +} + +#[derive(Copy, Clone, Debug, Eq)] +enum FullInt { + S(i64), + U(u64), +} + +impl FullInt { + #[allow(cast_sign_loss)] + fn cmp_s_u(s: i64, u: u64) -> Ordering { + if s < 0 { + Ordering::Less + } else if u > (i64::max_value() as u64) { + Ordering::Greater + } else { + (s as u64).cmp(&u) + } + } +} + +impl PartialEq for FullInt { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal + } +} + +impl PartialOrd for FullInt { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(match (self, other) { + (&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o), + (&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o), + (&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o), + (&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(), + }) + } +} +impl Ord for FullInt { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).expect("partial_cmp for FullInt can never return None") + } +} + + +fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { + use rustc::ty::TypeVariants::{TyInt, TyUint}; + use syntax::ast::{IntTy, UintTy}; + use std::*; + + if let ExprCast(ref cast_exp, _) = expr.node { + match cx.tcx.expr_ty(cast_exp).sty { + TyInt(int_ty) => { + Some(match int_ty { + IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), + IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), + IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), + IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), + IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), + }) + } + TyUint(uint_ty) => { + Some(match uint_ty { + UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), + UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), + UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), + UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), + UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), + }) + } + _ => None, + } + } else { + None + } +} + +fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { + use rustc::middle::const_val::ConstVal::*; + use rustc_const_eval::EvalHint::ExprTypeChecked; + use rustc_const_eval::eval_const_expr_partial; + use rustc_const_math::ConstInt; + + match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { + Ok(val) => { + if let Integral(const_int) = val { + Some(match const_int.erase_type() { + ConstInt::InferSigned(x) => FullInt::S(x as i64), + ConstInt::Infer(x) => FullInt::U(x as u64), + _ => unreachable!(), + }) + } else { + None + } + } + Err(_) => None, + } +} + +fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { + if let ExprCast(ref cast_val, _) = expr.node { + span_lint(cx, + INVALID_UPCAST_COMPARISONS, + *span, + &format!( + "because of the numeric bounds on `{}` prior to casting, this expression is always {}", + snippet(cx, cast_val.span, "the expression"), + if always { "true" } else { "false" }, + )); + } +} + +fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons::Rel, + lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { + use utils::comparisons::*; + + if let Some((lb, ub)) = lhs_bounds { + if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { + if rel == Rel::Eq || rel == Rel::Ne { + if norm_rhs_val < lb || norm_rhs_val > ub { + err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); + } + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } + } + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } + } + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, true) + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } + } + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } + } + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, false) + } + } + } +} + +impl LateLintPass for InvalidUpcastComparisons { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + + let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); + let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { + val + } else { + return; + }; + + let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); + let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); + + upcast_comparison_bounds_err(cx, &expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); + upcast_comparison_bounds_err(cx, &expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); + } + } +} diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs new file mode 100644 index 00000000000..8271fd3ed66 --- /dev/null +++ b/clippy_lints/src/unicode.rs @@ -0,0 +1,109 @@ +use rustc::lint::*; +use rustc::hir::*; +use syntax::ast::LitKind; +use syntax::codemap::Span; +use unicode_normalization::UnicodeNormalization; +use utils::{snippet, span_help_and_lint}; + +/// **What it does:** This lint checks for the unicode zero-width space in the code. +/// +/// **Why is this bad?** Having an invisible character in the code makes for all sorts of April fools, but otherwise is very much frowned upon. +/// +/// **Known problems:** None +/// +/// **Example:** You don't see it, but there may be a zero-width space somewhere in this text. +declare_lint! { + pub ZERO_WIDTH_SPACE, Deny, + "using a zero-width space in a string literal, which is confusing" +} + +/// **What it does:** This lint checks for non-ascii characters in string literals. +/// +/// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful. +/// +/// **Known problems:** None +/// +/// **Example:** `let x = "Hä?"` +declare_lint! { + pub NON_ASCII_LITERAL, Allow, + "using any literal non-ASCII chars in a string literal; suggests \ + using the \\u escape instead" +} + +/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). +/// +/// **Why is this bad?** If such a string is compared to another, the results may be surprising. +/// +/// **Known problems** None +/// +/// **Example:** You may not see it, but "à" and "à" aren't the same string. The former when escaped is actually "a\u{300}" while the latter is "\u{e0}". +declare_lint! { + pub UNICODE_NOT_NFC, Allow, + "using a unicode literal not in NFC normal form (see \ + [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" +} + + +#[derive(Copy, Clone)] +pub struct Unicode; + +impl LintPass for Unicode { + fn get_lints(&self) -> LintArray { + lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) + } +} + +impl LateLintPass for Unicode { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if let ExprLit(ref lit) = expr.node { + if let LitKind::Str(_, _) = lit.node { + check_str(cx, lit.span) + } + } + } +} + +fn escape<T: Iterator<Item = char>>(s: T) -> String { + let mut result = String::new(); + for c in s { + if c as u32 > 0x7F { + for d in c.escape_unicode() { + result.push(d) + } + } else { + result.push(c); + } + } + result +} + +fn check_str(cx: &LateContext, span: Span) { + let string = snippet(cx, span, ""); + if string.contains('\u{200B}') { + span_help_and_lint(cx, + ZERO_WIDTH_SPACE, + span, + "zero-width space detected", + &format!("Consider replacing the string with:\n\"{}\"", + string.replace("\u{200B}", "\\u{200B}"))); + } + if string.chars().any(|c| c as u32 > 0x7F) { + span_help_and_lint(cx, + NON_ASCII_LITERAL, + span, + "literal non-ASCII character detected", + &format!("Consider replacing the string with:\n\"{}\"", + if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { + escape(string.chars()) + } else { + escape(string.nfc()) + })); + } + if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { + span_help_and_lint(cx, + UNICODE_NOT_NFC, + span, + "non-nfc unicode sequence detected", + &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::<String>())); + } +} diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs new file mode 100644 index 00000000000..3de6719c546 --- /dev/null +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -0,0 +1,81 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::ast::Name; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use utils::span_lint; + +/// **What it does:** This lint checks for imports that remove "unsafe" from an item's name +/// +/// **Why is this bad?** Renaming makes it less clear which traits and structures are unsafe. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// use std::cell::{UnsafeCell as TotallySafeCell}; +/// +/// extern crate crossbeam; +/// use crossbeam::{spawn_unsafe as spawn}; +/// ``` +declare_lint! { + pub UNSAFE_REMOVED_FROM_NAME, + Warn, + "unsafe removed from name" +} + +pub struct UnsafeNameRemoval; + +impl LintPass for UnsafeNameRemoval { + fn get_lints(&self) -> LintArray { + lint_array!(UNSAFE_REMOVED_FROM_NAME) + } +} + +impl LateLintPass for UnsafeNameRemoval { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemUse(ref item_use) = item.node { + match item_use.node { + ViewPath_::ViewPathSimple(ref name, ref path) => { + unsafe_to_safe_check( + path.segments + .last() + .expect("use paths cannot be empty") + .name, + *name, + cx, &item.span + ); + }, + ViewPath_::ViewPathList(_, ref path_list_items) => { + for path_list_item in path_list_items.iter() { + let plid = path_list_item.node; + if let (Some(name), Some(rename)) = (plid.name(), plid.rename()) { + unsafe_to_safe_check(name, rename, cx, &item.span); + }; + } + }, + ViewPath_::ViewPathGlob(_) => {} + } + } + } +} + +fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: &Span) { + let old_str = old_name.as_str(); + let new_str = new_name.as_str(); + if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { + span_lint( + cx, + UNSAFE_REMOVED_FROM_NAME, + *span, + &format!( + "removed \"unsafe\" from the name of `{}` in use as `{}`", + old_str, + new_str + )); + } +} + +fn contains_unsafe(name: &InternedString) -> bool { + name.contains("Unsafe") || name.contains("unsafe") +} diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs new file mode 100644 index 00000000000..d408f16a371 --- /dev/null +++ b/clippy_lints/src/unused_label.rs @@ -0,0 +1,78 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; +use std::collections::HashMap; +use syntax::ast; +use syntax::codemap::Span; +use syntax::parse::token::InternedString; +use utils::{in_macro, span_lint}; + +/// **What it does:** This lint checks for unused labels. +/// +/// **Why is this bad?** Maybe the label should be used in which case there is an error in the +/// code or it should be removed. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust,ignore +/// fn unused_label() { +/// 'label: for i in 1..2 { +/// if i > 4 { continue } +/// } +/// ``` +declare_lint! { + pub UNUSED_LABEL, + Warn, + "unused label" +} + +pub struct UnusedLabel; + +#[derive(Default)] +struct UnusedLabelVisitor { + labels: HashMap<InternedString, Span>, +} + +impl UnusedLabelVisitor { + pub fn new() -> UnusedLabelVisitor { + ::std::default::Default::default() + } +} + +impl LintPass for UnusedLabel { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_LABEL) + } +} + +impl LateLintPass for UnusedLabel { + fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, _: ast::NodeId) { + if in_macro(cx, span) { + return; + } + + let mut v = UnusedLabelVisitor::new(); + walk_fn(&mut v, kind, decl, body, span); + + for (label, span) in v.labels { + span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label)); + } + } +} + +impl<'v> Visitor<'v> for UnusedLabelVisitor { + fn visit_expr(&mut self, expr: &hir::Expr) { + match expr.node { + hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => { + self.labels.remove(&label.node.as_str()); + } + hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { + self.labels.insert(label.as_str(), expr.span); + } + _ => (), + } + + walk_expr(self, expr); + } +} diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs new file mode 100644 index 00000000000..b890a363fb7 --- /dev/null +++ b/clippy_lints/src/utils/comparisons.rs @@ -0,0 +1,23 @@ +use rustc::hir::{BinOp_, Expr}; + +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub enum Rel { + Lt, + Le, + Eq, + Ne, +} + +/// Put the expression in the form `lhs < rhs` or `lhs <= rhs`. +pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) + -> Option<(Rel, &'a Expr, &'a Expr)> { + match op { + BinOp_::BiLt => Some((Rel::Lt, lhs, rhs)), + BinOp_::BiLe => Some((Rel::Le, lhs, rhs)), + BinOp_::BiGt => Some((Rel::Lt, rhs, lhs)), + BinOp_::BiGe => Some((Rel::Le, rhs, lhs)), + BinOp_::BiEq => Some((Rel::Eq, rhs, lhs)), + BinOp_::BiNe => Some((Rel::Ne, rhs, lhs)), + _ => None, + } +} diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs new file mode 100644 index 00000000000..e773cc0e025 --- /dev/null +++ b/clippy_lints/src/utils/conf.rs @@ -0,0 +1,205 @@ +use std::{fmt, fs, io}; +use std::io::Read; +use syntax::{ast, codemap, ptr}; +use syntax::parse::token; +use toml; + +/// Get the configuration file from arguments. +pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { + for arg in args { + match arg.node { + ast::MetaItemKind::Word(ref name) | + ast::MetaItemKind::List(ref name, _) => { + if name == &"conf_file" { + return Err(("`conf_file` must be a named value", arg.span)); + } + } + ast::MetaItemKind::NameValue(ref name, ref value) => { + if name == &"conf_file" { + return if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.clone())) + } else { + Err(("`conf_file` value must be a string", value.span)) + }; + } + } + } + } + + Ok(None) +} + +/// Error from reading a configuration file. +#[derive(Debug)] +pub enum ConfError { + IoError(io::Error), + TomlError(Vec<toml::ParserError>), + TypeError(&'static str, &'static str, &'static str), + UnknownKey(String), +} + +impl fmt::Display for ConfError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ConfError::IoError(ref err) => err.fmt(f), + ConfError::TomlError(ref errs) => { + let mut first = true; + for err in errs { + if !first { + try!(", ".fmt(f)); + first = false; + } + + try!(err.fmt(f)); + } + + Ok(()) + } + ConfError::TypeError(ref key, ref expected, ref got) => { + write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) + } + ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), + } + } +} + +impl From<io::Error> for ConfError { + fn from(e: io::Error) -> Self { + ConfError::IoError(e) + } +} + +macro_rules! define_Conf { + ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { + /// Type used to store lint configuration. + pub struct Conf { + $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ + } + + impl Default for Conf { + fn default() -> Conf { + Conf { + $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ + } + } + } + + impl Conf { + /// Set the property `name` (which must be the `toml` name) to the given value + #[allow(cast_sign_loss)] + fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + match name.as_str() { + $( + define_Conf!(PAT $toml_name) => { + if let Some(value) = define_Conf!(CONV $($ty)+, value) { + self.$rust_name = value; + } + else { + return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), + stringify!($($ty)+), + value.type_str())); + } + }, + )+ + "third-party" => { + // for external tools such as clippy-service + return Ok(()); + } + _ => { + return Err(ConfError::UnknownKey(name)); + } + } + + Ok(()) + } + } + }; + + // hack to convert tts + (PAT $pat: pat) => { $pat }; + (EXPR $e: expr) => { $e }; + (TY $ty: ty) => { $ty }; + + // how to read the value? + (CONV i64, $value: expr) => { $value.as_integer() }; + (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; + (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; + (CONV Vec<String>, $value: expr) => {{ + let slice = $value.as_slice(); + + if let Some(slice) = slice { + if slice.iter().any(|v| v.as_str().is_none()) { + None + } + else { + Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) + } + } + else { + None + } + }}; + + // provide a nicer syntax to declare the default value of `Vec<String>` variables + (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; + (DEFAULT $ty: ty, $e: expr) => { $e }; +} + +define_Conf! { + /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about + ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), + /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have + ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), + /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub"] => Vec<String>), + /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have + ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), + /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have + ("type-complexity-threshold", type_complexity_threshold, 250 => u64), + /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have + ("single-char-binding-names-threshold", max_single_char_names, 5 => u64), +} + +/// Read the `toml` configuration file. The function will ignore “File not found” errors iif +/// `!must_exist`, in which case, it will return the default configuration. +/// In case of error, the function tries to continue as much as possible. +pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { + let mut conf = Conf::default(); + let mut errors = Vec::new(); + + let file = match fs::File::open(path) { + Ok(mut file) => { + let mut buf = String::new(); + + if let Err(err) = file.read_to_string(&mut buf) { + errors.push(err.into()); + return (conf, errors); + } + + buf + } + Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { + return (conf, errors); + } + Err(err) => { + errors.push(err.into()); + return (conf, errors); + } + }; + + let mut parser = toml::Parser::new(&file); + let toml = if let Some(toml) = parser.parse() { + toml + } else { + errors.push(ConfError::TomlError(parser.errors)); + return (conf, errors); + }; + + for (key, value) in toml { + if let Err(err) = conf.set(key, value) { + errors.push(err); + } + } + + (conf, errors) +} diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs new file mode 100644 index 00000000000..0f0a7312ee4 --- /dev/null +++ b/clippy_lints/src/utils/hir.rs @@ -0,0 +1,513 @@ +use consts::constant; +use rustc::lint::*; +use rustc::hir::*; +use std::hash::{Hash, Hasher, SipHasher}; +use syntax::ast::Name; +use syntax::ptr::P; +use utils::differing_macro_contexts; + +/// Type used to check whether two ast are the same. This is different from the operator +/// `==` on ast types as this operator would compare true equality with ID and span. +/// +/// Note that some expressions kinds are not considered but could be added. +pub struct SpanlessEq<'a, 'tcx: 'a> { + /// Context used to evaluate constant expressions. + cx: &'a LateContext<'a, 'tcx>, + /// If is true, never consider as equal expressions containing function calls. + ignore_fn: bool, +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + SpanlessEq { + cx: cx, + ignore_fn: false, + } + } + + pub fn ignore_fn(self) -> Self { + SpanlessEq { + cx: self.cx, + ignore_fn: true, + } + } + + /// Check whether two statements are the same. + pub fn eq_stmt(&self, left: &Stmt, right: &Stmt) -> bool { + match (&left.node, &right.node) { + (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { + if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { + // TODO: tys + l.ty.is_none() && r.ty.is_none() && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + } else { + false + } + } + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | + (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + _ => false, + } + } + + /// Check whether two blocks are the same. + pub fn eq_block(&self, left: &Block, right: &Block) -> bool { + over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && + both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) + } + + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + if self.ignore_fn && differing_macro_contexts(left.span, right.span) { + return false; + } + + if let (Some(l), Some(r)) = (constant(self.cx, left), constant(self.cx, right)) { + if l == r { + return true; + } + } + + match (&left.node, &right.node) { + (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), + (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), + (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), + (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { + lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + } + (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) + } + (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), + (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), + (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { + !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) + } + (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), + (&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => { + l_f_ident.node == r_f_ident.node && self.eq_expr(l_f_exp, r_f_exp) + } + (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), + (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { + self.eq_expr(lc, rc) && self.eq_block(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r)) + } + (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, + (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { + self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) + } + (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { + ls == rs && self.eq_expr(le, re) && + over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) + } + (&ExprMethodCall(ref l_name, ref l_tys, ref l_args), + &ExprMethodCall(ref r_name, ref r_tys, ref r_args)) => { + // TODO: tys + !self.ignore_fn && l_name.node == r_name.node && l_tys.is_empty() && r_tys.is_empty() && + self.eq_exprs(l_args, r_args) + } + (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), + (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), + (&ExprPath(ref l_qself, ref l_subpath), &ExprPath(ref r_qself, ref r_subpath)) => { + both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) + } + (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { + self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && + over(lf, rf, |l, r| self.eq_field(l, r)) + } + (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), + (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), + (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), + (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), + (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) + } + _ => false, + } + } + + fn eq_exprs(&self, left: &[P<Expr>], right: &[P<Expr>]) -> bool { + over(left, right, |l, r| self.eq_expr(l, r)) + } + + fn eq_field(&self, left: &Field, right: &Field) -> bool { + left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr) + } + + /// Check whether two patterns are the same. + pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { + match (&left.node, &right.node) { + (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), + (&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => { + self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r))) + } + (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { + lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) + } + (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), + (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { + self.eq_qself(ls, rs) && self.eq_path(lp, rp) + } + (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => over(l, r, |l, r| self.eq_pat(l, r)), + (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { + self.eq_expr(ls, rs) && self.eq_expr(le, re) + } + (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), + (&PatKind::Vec(ref ls, ref li, ref le), &PatKind::Vec(ref rs, ref ri, ref re)) => { + over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && + both(li, ri, |l, r| self.eq_pat(l, r)) + } + (&PatKind::Wild, &PatKind::Wild) => true, + _ => false, + } + } + + fn eq_path(&self, left: &Path, right: &Path) -> bool { + // The == of idents doesn't work with different contexts, + // we have to be explicit about hygiene + left.global == right.global && + over(&left.segments, + &right.segments, + |l, r| l.name.as_str() == r.name.as_str() && l.parameters == r.parameters) + } + + fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool { + left.ty.node == right.ty.node && left.position == right.position + } + + fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { + match (&left.node, &right.node) { + (&TyVec(ref l_vec), &TyVec(ref r_vec)) => self.eq_ty(l_vec, r_vec), + (&TyFixedLengthVec(ref lt, ref ll), &TyFixedLengthVec(ref rt, ref rl)) => { + self.eq_ty(lt, rt) && self.eq_expr(ll, rl) + } + (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), + (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { + l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) + } + (&TyPath(ref lq, ref l_path), &TyPath(ref rq, ref r_path)) => { + both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path) + } + (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), + (&TyInfer, &TyInfer) => true, + _ => false, + } + } +} + +fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> { + match binop { + BiAdd | + BiMul | + BiBitXor | + BiBitAnd | + BiEq | + BiNe | + BiBitOr => Some((binop, rhs, lhs)), + BiLt => Some((BiGt, rhs, lhs)), + BiLe => Some((BiGe, rhs, lhs)), + BiGe => Some((BiLe, rhs, lhs)), + BiGt => Some((BiLt, rhs, lhs)), + BiShl | BiShr | BiRem | BiSub | BiDiv | BiAnd | BiOr => None, + } +} + +/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. +fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool +{ + l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) +} + +/// Check if two slices are equal as per `eq_fn`. +fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool + where F: FnMut(&X, &X) -> bool +{ + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) +} + + +/// Type used to hash an ast element. This is different from the `Hash` trait on ast types as this +/// trait would consider IDs and spans. +/// +/// All expressions kind are hashed, but some might have a weaker hash. +pub struct SpanlessHash<'a, 'tcx: 'a> { + /// Context used to evaluate constant expressions. + cx: &'a LateContext<'a, 'tcx>, + s: SipHasher, +} + +impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { + pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + SpanlessHash { + cx: cx, + s: SipHasher::new(), + } + } + + pub fn finish(&self) -> u64 { + self.s.finish() + } + + pub fn hash_block(&mut self, b: &Block) { + for s in &b.stmts { + self.hash_stmt(s); + } + + if let Some(ref e) = b.expr { + self.hash_expr(e); + } + + b.rules.hash(&mut self.s); + } + + pub fn hash_expr(&mut self, e: &Expr) { + if let Some(e) = constant(self.cx, e) { + return e.hash(&mut self.s); + } + + match e.node { + ExprAddrOf(m, ref e) => { + let c: fn(_, _) -> _ = ExprAddrOf; + c.hash(&mut self.s); + m.hash(&mut self.s); + self.hash_expr(e); + } + ExprAgain(i) => { + let c: fn(_) -> _ = ExprAgain; + c.hash(&mut self.s); + if let Some(i) = i { + self.hash_name(&i.node); + } + } + ExprAssign(ref l, ref r) => { + let c: fn(_, _) -> _ = ExprAssign; + c.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprAssignOp(ref o, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprAssignOp; + c.hash(&mut self.s); + o.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprBlock(ref b) => { + let c: fn(_) -> _ = ExprBlock; + c.hash(&mut self.s); + self.hash_block(b); + } + ExprBinary(op, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprBinary; + c.hash(&mut self.s); + op.node.hash(&mut self.s); + self.hash_expr(l); + self.hash_expr(r); + } + ExprBreak(i) => { + let c: fn(_) -> _ = ExprBreak; + c.hash(&mut self.s); + if let Some(i) = i { + self.hash_name(&i.node); + } + } + ExprBox(ref e) => { + let c: fn(_) -> _ = ExprBox; + c.hash(&mut self.s); + self.hash_expr(e); + } + ExprCall(ref fun, ref args) => { + let c: fn(_, _) -> _ = ExprCall; + c.hash(&mut self.s); + self.hash_expr(fun); + self.hash_exprs(args); + } + ExprCast(ref e, ref _ty) => { + let c: fn(_, _) -> _ = ExprCast; + c.hash(&mut self.s); + self.hash_expr(e); + // TODO: _ty + } + ExprClosure(cap, _, ref b, _) => { + let c: fn(_, _, _, _) -> _ = ExprClosure; + c.hash(&mut self.s); + cap.hash(&mut self.s); + self.hash_block(b); + } + ExprField(ref e, ref f) => { + let c: fn(_, _) -> _ = ExprField; + c.hash(&mut self.s); + self.hash_expr(e); + self.hash_name(&f.node); + } + ExprIndex(ref a, ref i) => { + let c: fn(_, _) -> _ = ExprIndex; + c.hash(&mut self.s); + self.hash_expr(a); + self.hash_expr(i); + } + ExprInlineAsm(..) => { + let c: fn(_, _, _) -> _ = ExprInlineAsm; + c.hash(&mut self.s); + } + ExprIf(ref cond, ref t, ref e) => { + let c: fn(_, _, _) -> _ = ExprIf; + c.hash(&mut self.s); + self.hash_expr(cond); + self.hash_block(t); + if let Some(ref e) = *e { + self.hash_expr(e); + } + } + ExprLit(ref l) => { + let c: fn(_) -> _ = ExprLit; + c.hash(&mut self.s); + l.hash(&mut self.s); + } + ExprLoop(ref b, ref i) => { + let c: fn(_, _) -> _ = ExprLoop; + c.hash(&mut self.s); + self.hash_block(b); + if let Some(i) = *i { + self.hash_name(&i); + } + } + ExprMatch(ref e, ref arms, ref s) => { + let c: fn(_, _, _) -> _ = ExprMatch; + c.hash(&mut self.s); + self.hash_expr(e); + + for arm in arms { + // TODO: arm.pat? + if let Some(ref e) = arm.guard { + self.hash_expr(e); + } + self.hash_expr(&arm.body); + } + + s.hash(&mut self.s); + } + ExprMethodCall(ref name, ref _tys, ref args) => { + let c: fn(_, _, _) -> _ = ExprMethodCall; + c.hash(&mut self.s); + self.hash_name(&name.node); + self.hash_exprs(args); + } + ExprRepeat(ref e, ref l) => { + let c: fn(_, _) -> _ = ExprRepeat; + c.hash(&mut self.s); + self.hash_expr(e); + self.hash_expr(l); + } + ExprRet(ref e) => { + let c: fn(_) -> _ = ExprRet; + c.hash(&mut self.s); + if let Some(ref e) = *e { + self.hash_expr(e); + } + } + ExprPath(ref _qself, ref subpath) => { + let c: fn(_, _) -> _ = ExprPath; + c.hash(&mut self.s); + self.hash_path(subpath); + } + ExprStruct(ref path, ref fields, ref expr) => { + let c: fn(_, _, _) -> _ = ExprStruct; + c.hash(&mut self.s); + + self.hash_path(path); + + for f in fields { + self.hash_name(&f.name.node); + self.hash_expr(&f.expr); + } + + if let Some(ref e) = *expr { + self.hash_expr(e); + } + } + ExprTup(ref tup) => { + let c: fn(_) -> _ = ExprTup; + c.hash(&mut self.s); + self.hash_exprs(tup); + } + ExprTupField(ref le, li) => { + let c: fn(_, _) -> _ = ExprTupField; + c.hash(&mut self.s); + + self.hash_expr(le); + li.node.hash(&mut self.s); + } + ExprType(_, _) => { + let c: fn(_, _) -> _ = ExprType; + c.hash(&mut self.s); + // what’s an ExprType anyway? + } + ExprUnary(lop, ref le) => { + let c: fn(_, _) -> _ = ExprUnary; + c.hash(&mut self.s); + + lop.hash(&mut self.s); + self.hash_expr(le); + } + ExprVec(ref v) => { + let c: fn(_) -> _ = ExprVec; + c.hash(&mut self.s); + + self.hash_exprs(v); + } + ExprWhile(ref cond, ref b, l) => { + let c: fn(_, _, _) -> _ = ExprWhile; + c.hash(&mut self.s); + + self.hash_expr(cond); + self.hash_block(b); + if let Some(l) = l { + self.hash_name(&l); + } + } + } + } + + pub fn hash_exprs(&mut self, e: &[P<Expr>]) { + for e in e { + self.hash_expr(e); + } + } + + pub fn hash_name(&mut self, n: &Name) { + n.as_str().hash(&mut self.s); + } + + pub fn hash_path(&mut self, p: &Path) { + p.global.hash(&mut self.s); + for p in &p.segments { + self.hash_name(&p.name); + } + } + + pub fn hash_stmt(&mut self, b: &Stmt) { + match b.node { + StmtDecl(ref _decl, _) => { + let c: fn(_, _) -> _ = StmtDecl; + c.hash(&mut self.s); + // TODO: decl + } + StmtExpr(ref expr, _) => { + let c: fn(_, _) -> _ = StmtExpr; + c.hash(&mut self.s); + self.hash_expr(expr); + } + StmtSemi(ref expr, _) => { + let c: fn(_, _) -> _ = StmtSemi; + c.hash(&mut self.s); + self.hash_expr(expr); + } + } + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs new file mode 100644 index 00000000000..3ff6167620a --- /dev/null +++ b/clippy_lints/src/utils/mod.rs @@ -0,0 +1,840 @@ +use reexport::*; +use rustc::hir::*; +use rustc::hir::def_id::DefId; +use rustc::hir::map::Node; +use rustc::lint::{LintContext, LateContext, Level, Lint}; +use rustc::middle::cstore; +use rustc::session::Session; +use rustc::traits::ProjectionMode; +use rustc::traits; +use rustc::ty::subst::Subst; +use rustc::ty; +use std::borrow::Cow; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::str::FromStr; +use syntax::ast::{self, LitKind, RangeLimits}; +use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; +use syntax::errors::DiagnosticBuilder; +use syntax::ptr::P; + +pub mod comparisons; +pub mod conf; +mod hir; +pub mod paths; +pub use self::hir::{SpanlessEq, SpanlessHash}; + +pub type MethodArgs = HirVec<P<Expr>>; + +/// Produce a nested chain of if-lets and ifs from the patterns: +/// +/// if_let_chain! { +/// [ +/// let Some(y) = x, +/// y.len() == 2, +/// let Some(z) = y, +/// ], +/// { +/// block +/// } +/// } +/// +/// becomes +/// +/// if let Some(y) = x { +/// if y.len() == 2 { +/// if let Some(z) = y { +/// block +/// } +/// } +/// } +#[macro_export] +macro_rules! if_let_chain { + ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { + if let $pat = $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([let $pat:pat = $expr:expr], $block:block) => { + if let $pat = $expr { + $block + } + }; + ([let $pat:pat = $expr:expr,], $block:block) => { + if let $pat = $expr { + $block + } + }; + ([$expr:expr, $($tt:tt)+], $block:block) => { + if $expr { + if_let_chain!{ [$($tt)+], $block } + } + }; + ([$expr:expr], $block:block) => { + if $expr { + $block + } + }; + ([$expr:expr,], $block:block) => { + if $expr { + $block + } + }; +} + +/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one +/// isn't). +pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { + rhs.expn_id != lhs.expn_id +} +/// Returns true if this `expn_info` was expanded by any macro. +pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { + cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) +} + +/// Returns true if the macro that expanded the crate was outside of the current crate or was a +/// compiler plugin. +pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { + /// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use + /// this after other checks have already happened. + fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { + // no ExpnInfo = no macro + opt_info.map_or(false, |info| { + if let ExpnFormat::MacroAttribute(..) = info.callee.format { + // these are all plugins + return true; + } + // no span for the callee = external macro + info.callee.span.map_or(true, |span| { + // no snippet = external macro or compiler-builtin expansion + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) + }) + }) + } + + cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) +} + +/// Check if a `DefId`'s path matches the given absolute type path usage. +/// +/// # Examples +/// ``` +/// match_def_path(cx, id, &["core", "option", "Option"]) +/// ``` +/// +/// See also the `paths` module. +pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { + use syntax::parse::token; + + struct AbsolutePathBuffer { + names: Vec<token::InternedString>, + } + + impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { + fn root_mode(&self) -> &ty::item_path::RootMode { + const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; + ABSOLUTE + } + + fn push(&mut self, text: &str) { + self.names.push(token::intern(text).as_str()); + } + } + + let mut apb = AbsolutePathBuffer { + names: vec![], + }; + + cx.tcx.push_item_path(&mut apb, def_id); + + apb.names == path +} + +/// Check if type is struct or enum type with given def path. +pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { + match ty.sty { + ty::TyEnum(ref adt, _) | + ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), + _ => false, + } +} + +/// Check if the method call given in `expr` belongs to given type. +pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} + +/// Check if the method call given in `expr` belongs to given trait. +pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { + let method_call = ty::MethodCall::expr(expr.id); + + let trt_id = cx.tcx + .tables + .borrow() + .method_map + .get(&method_call) + .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + if let Some(trt_id) = trt_id { + match_def_path(cx, trt_id, path) + } else { + false + } +} + +/// Match a `Path` against a slice of segment string literals. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` +pub fn match_path(path: &Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name.as_str() == *b) +} + +/// Match a `Path` against a slice of segment string literals, e.g. +/// +/// # Examples +/// ``` +/// match_path(path, &["std", "rt", "begin_unwind"]) +/// ``` +pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { + path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) +} + +/// Get the definition associated to a path. +/// TODO: investigate if there is something more efficient for that. +pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { + let cstore = &cx.tcx.sess.cstore; + + let crates = cstore.crates(); + let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); + if let Some(krate) = krate { + let mut items = cstore.crate_top_level_items(*krate); + let mut path_it = path.iter().skip(1).peekable(); + + loop { + let segment = match path_it.next() { + Some(segment) => segment, + None => return None, + }; + + for item in &mem::replace(&mut items, vec![]) { + if item.name.as_str() == *segment { + if path_it.peek().is_none() { + return Some(item.def); + } + + let def_id = match item.def { + cstore::DefLike::DlDef(def) => def.def_id(), + cstore::DefLike::DlImpl(def_id) => def_id, + _ => panic!("Unexpected {:?}", item.def), + }; + + items = cstore.item_children(def_id); + break; + } + } + } + } else { + None + } +} + +/// Convenience function to get the `DefId` of a trait by path. +pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { + let def = match path_to_def(cx, path) { + Some(def) => def, + None => return None, + }; + + match def { + cstore::DlDef(def::Def::Trait(trait_id)) => Some(trait_id), + _ => None, + } +} + +/// Check whether a type implements a trait. +/// See also `get_trait_def_id`. +pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, + ty_params: Vec<ty::Ty<'tcx>>) + -> bool { + cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); + + let ty = cx.tcx.erase_regions(&ty); + cx.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| { + let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), + trait_id, + 0, + ty, + ty_params); + + traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) + }) +} + +/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. +/// +/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, +/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for +/// `.bar()` and `.baz()` +pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { + let mut current = expr; + let mut matched = Vec::with_capacity(methods.len()); + for method_name in methods.iter().rev() { + // method chains are stored last -> first + if let ExprMethodCall(ref name, _, ref args) = current.node { + if name.node.as_str() == *method_name { + matched.push(args); // build up `matched` backwards + current = &args[0] // go to parent expression + } else { + return None; + } + } else { + return None; + } + } + matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` + Some(matched) +} + + +/// Get the name of the item the expression is in, if available. +pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { + let parent_id = cx.tcx.map.get_parent(expr.id); + match cx.tcx.map.find(parent_id) { + Some(Node::NodeItem(&Item { ref name, .. })) | + Some(Node::NodeTraitItem(&TraitItem { ref name, .. })) | + Some(Node::NodeImplItem(&ImplItem { ref name, .. })) => Some(*name), + _ => None, + } +} + +/// Checks if a `let` decl is from a `for` loop desugaring. +pub fn is_from_for_desugar(decl: &Decl) -> bool { + if_let_chain! { + [ + let DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node + ], + { return true; } + }; + false +} + + +/// Convert a span to a code snippet if available, otherwise use default. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` +pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default)) +} + +/// Convert a span to a code snippet. Returns `None` if not available. +pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { + cx.sess().codemap().span_to_snippet(span).ok() +} + +/// Convert a span (from a block) to a code snippet if available, otherwise use default. +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like +/// things which need to be printed as such. +/// +/// # Example +/// ``` +/// snippet(cx, expr.span, "..") +/// ``` +pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + let snip = snippet(cx, span, default); + trim_multiline(snip, true) +} + +/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. +/// Also takes an `Option<String>` which can be put inside the braces. +pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { + let code = snippet_block(cx, expr.span, default); + let string = option.unwrap_or_default(); + if let ExprBlock(_) = expr.node { + Cow::Owned(format!("{}{}", code, string)) + } else if string.is_empty() { + Cow::Owned(format!("{{ {} }}", code)) + } else { + Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) + } +} + +/// Trim indentation from a multiline string with possibility of ignoring the first line. +pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { + let s_space = trim_multiline_inner(s, ignore_first, ' '); + let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); + trim_multiline_inner(s_tab, ignore_first, ' ') +} + +fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { + let x = s.lines() + .skip(ignore_first as usize) + .filter_map(|l| { + if l.is_empty() { + None + } else { + // ignore empty lines + Some(l.char_indices() + .find(|&(_, x)| x != ch) + .unwrap_or((l.len(), ch)) + .0) + } + }) + .min() + .unwrap_or(0); + if x > 0 { + Cow::Owned(s.lines() + .enumerate() + .map(|(i, l)| { + if (ignore_first && i == 0) || l.is_empty() { + l + } else { + l.split_at(x).1 + } + }) + .collect::<Vec<_>>() + .join("\n")) + } else { + s + } +} + +/// Get a parent expressions if any – this is useful to constrain a lint. +pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { + let map = &cx.tcx.map; + let node_id: NodeId = e.id; + let parent_id: NodeId = map.get_parent_node(node_id); + if node_id == parent_id { + return None; + } + map.find(parent_id).and_then(|node| { + if let Node::NodeExpr(parent) = node { + Some(parent) + } else { + None + } + }) +} + +pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { + let map = &cx.tcx.map; + let enclosing_node = map.get_enclosing_scope(node) + .and_then(|enclosing_id| map.find(enclosing_id)); + if let Some(node) = enclosing_node { + match node { + Node::NodeBlock(ref block) => Some(block), + Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), + _ => None, + } + } else { + None + } +} + +pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); + +impl<'a> Drop for DiagnosticWrapper<'a> { + fn drop(&mut self) { + self.0.emit(); + } +} + +impl<'a> DerefMut for DiagnosticWrapper<'a> { + fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { + &mut self.0 + } +} + +impl<'a> Deref for DiagnosticWrapper<'a> { + type Target = DiagnosticBuilder<'a>; + fn deref(&self) -> &DiagnosticBuilder<'a> { + &self.0 + } +} + +impl<'a> DiagnosticWrapper<'a> { + fn wiki_link(&mut self, lint: &'static Lint) { + self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } +} + +pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); + if cx.current_level(lint) != Level::Allow { + db.wiki_link(lint); + } + db +} + +pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) + -> DiagnosticWrapper<'a> { + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); + if cx.current_level(lint) != Level::Allow { + db.help(help); + db.wiki_link(lint); + } + db +} + +pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, + note: &str) + -> DiagnosticWrapper<'a> { + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); + if cx.current_level(lint) != Level::Allow { + if note_span == span { + db.note(note); + } else { + db.span_note(note_span, note); + } + db.wiki_link(lint); + } + db +} + +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) + -> DiagnosticWrapper<'a> + where F: FnOnce(&mut DiagnosticWrapper) +{ + let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); + if cx.current_level(lint) != Level::Allow { + f(&mut db); + db.wiki_link(lint); + } + db +} + +/// Return the base type for references and raw pointers. +pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { + match ty.sty { + ty::TyRef(_, ref tm) | + ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), + _ => ty, + } +} + +/// Return the base type for references and raw pointers, and count reference depth. +pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { + fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { + match ty.sty { + ty::TyRef(_, ref tm) | + ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), + _ => (ty, depth), + } + } + inner(ty, 0) +} + +/// Check whether the given expression is a constant literal of the given value. +pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { + // FIXME: use constant folding + if let ExprLit(ref spanned) = expr.node { + if let LitKind::Int(v, _) = spanned.node { + return v == value; + } + } + false +} + +pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { + cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() +} + +pub struct LimitStack { + stack: Vec<u64>, +} + +impl Drop for LimitStack { + fn drop(&mut self) { + assert_eq!(self.stack.len(), 1); + } +} + +impl LimitStack { + pub fn new(limit: u64) -> LimitStack { + LimitStack { stack: vec![limit] } + } + pub fn limit(&self) -> u64 { + *self.stack.last().expect("there should always be a value in the stack") + } + pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs(sess, attrs, name, |val| stack.push(val)); + } + pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + let stack = &mut self.stack; + parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); + } +} + +fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { + for attr in attrs { + let attr = &attr.node; + if attr.is_sugared_doc { + continue; + } + if let ast::MetaItemKind::NameValue(ref key, ref value) = attr.value.node { + if *key == name { + if let LitKind::Str(ref s, _) = value.node { + if let Ok(value) = FromStr::from_str(s) { + f(value) + } else { + sess.span_err(value.span, "not a number"); + } + } else { + unreachable!() + } + } + } + } +} + +/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. +/// See also `is_direct_expn_of`. +pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { + loop { + let span_name_span = cx.tcx + .sess + .codemap() + .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); + + match span_name_span { + Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), + None => return None, + Some((_, new_span)) => span = new_span, + } + } +} + +/// Return the pre-expansion span if is this directly comes from an expansion of the macro `name`. +/// The difference with `is_expn_of` is that in +/// ```rust,ignore +/// foo!(bar!(42)); +/// ``` +/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only `bar!` by +/// `is_direct_expn_of`. +pub fn is_direct_expn_of(cx: &LateContext, span: Span, name: &str) -> Option<Span> { + let span_name_span = cx.tcx + .sess + .codemap() + .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); + + match span_name_span { + Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span), + _ => None, + } +} + +/// Return the index of the character after the first camel-case component of `s`. +pub fn camel_case_until(s: &str) -> usize { + let mut iter = s.char_indices(); + if let Some((_, first)) = iter.next() { + if !first.is_uppercase() { + return 0; + } + } else { + return 0; + } + let mut up = true; + let mut last_i = 0; + for (i, c) in iter { + if up { + if c.is_lowercase() { + up = false; + } else { + return last_i; + } + } else if c.is_uppercase() { + up = true; + last_i = i; + } else if !c.is_lowercase() { + return i; + } + } + if up { + last_i + } else { + s.len() + } +} + +/// Return index of the last camel-case component of `s`. +pub fn camel_case_from(s: &str) -> usize { + let mut iter = s.char_indices().rev(); + if let Some((_, first)) = iter.next() { + if !first.is_lowercase() { + return s.len(); + } + } else { + return s.len(); + } + let mut down = true; + let mut last_i = s.len(); + for (i, c) in iter { + if down { + if c.is_uppercase() { + down = false; + last_i = i; + } else if !c.is_lowercase() { + return last_i; + } + } else if c.is_lowercase() { + down = true; + } else { + return last_i; + } + } + last_i +} + +/// Represent a range akin to `ast::ExprKind::Range`. +#[derive(Debug, Copy, Clone)] +pub struct UnsugaredRange<'a> { + pub start: Option<&'a Expr>, + pub end: Option<&'a Expr>, + pub limits: RangeLimits, +} + +/// Unsugar a `hir` range. +pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { + // To be removed when ranges get stable. + fn unwrap_unstable(expr: &Expr) -> &Expr { + if let ExprBlock(ref block) = expr.node { + if block.rules == BlockCheckMode::PushUnstableBlock || block.rules == BlockCheckMode::PopUnstableBlock { + if let Some(ref expr) = block.expr { + return expr; + } + } + } + + expr + } + + fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> { + let expr = &fields.iter() + .find(|field| field.name.node.as_str() == name) + .unwrap_or_else(|| panic!("missing {} field for range", name)) + .expr; + + Some(unwrap_unstable(expr)) + } + + // The range syntax is expanded to literal paths starting with `core` or `std` depending on + // `#[no_std]`. Testing both instead of resolving the paths. + + match unwrap_unstable(expr).node { + ExprPath(None, ref path) => { + if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { + Some(UnsugaredRange { + start: None, + end: None, + limits: RangeLimits::HalfOpen, + }) + } else { + None + } + } + ExprStruct(ref path, ref fields, None) => { + if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { + Some(UnsugaredRange { + start: get_field("start", fields), + end: None, + limits: RangeLimits::HalfOpen, + }) + } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { + Some(UnsugaredRange { + start: get_field("start", fields), + end: get_field("end", fields), + limits: RangeLimits::Closed, + }) + } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { + Some(UnsugaredRange { + start: get_field("start", fields), + end: get_field("end", fields), + limits: RangeLimits::HalfOpen, + }) + } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { + Some(UnsugaredRange { + start: None, + end: get_field("end", fields), + limits: RangeLimits::Closed, + }) + } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { + Some(UnsugaredRange { + start: None, + end: get_field("end", fields), + limits: RangeLimits::HalfOpen, + }) + } else { + None + } + } + _ => None, + } +} + +/// Convenience function to get the return type of a function or `None` if the function diverges. +pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { + let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); + let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, parameter_env.free_substs); + let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); + if let ty::FnConverging(ret_ty) = fn_sig.output { + Some(ret_ty) + } else { + None + } +} + +/// Check if two types are the same. +// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but +// not for type parameters. +pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>, parameter_item: NodeId) -> bool { + let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, parameter_item); + cx.tcx.infer_ctxt(None, Some(parameter_env), ProjectionMode::Any).enter(|infcx| { + let new_a = a.subst(infcx.tcx, infcx.parameter_environment.free_substs); + let new_b = b.subst(infcx.tcx, infcx.parameter_environment.free_substs); + infcx.can_equate(&new_a, &new_b).is_ok() + }) +} + +/// Recover the essential nodes of a desugared for loop: +/// `for pat in arg { body }` becomes `(pat, arg, body)`. +pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { + if_let_chain! { + [ + let ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), + let ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); + } + } + None +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs new file mode 100644 index 00000000000..3c91578abd0 --- /dev/null +++ b/clippy_lints/src/utils/paths.rs @@ -0,0 +1,61 @@ +//! This module contains paths to types and functions Clippy needs to know about. + +pub const BEGIN_PANIC: [&'static str; 3] = ["std", "rt", "begin_panic"]; +pub const BINARY_HEAP: [&'static str; 3] = ["collections", "binary_heap", "BinaryHeap"]; +pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; +pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; +pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; +pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; +pub const BTREESET: [&'static str; 4] = ["collections", "btree", "set", "BTreeSet"]; +pub const CLONE: [&'static str; 4] = ["core", "clone", "Clone", "clone"]; +pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"]; +pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; +pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"]; +pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"]; +pub const CSTRING_NEW: [&'static str; 4] = ["std", "ffi", "CString", "new"]; +pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; +pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"]; +pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; +pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; +pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; +pub const HASH: [&'static str; 2] = ["hash", "Hash"]; +pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; +pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; +pub const ITERATOR: [&'static str; 4] = ["core", "iter", "iterator", "Iterator"]; +pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; +pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; +pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; +pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; +pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; +pub const RANGE: [&'static str; 3] = ["core", "ops", "Range"]; +pub const RANGE_FROM: [&'static str; 3] = ["core", "ops", "RangeFrom"]; +pub const RANGE_FROM_STD: [&'static str; 3] = ["std", "ops", "RangeFrom"]; +pub const RANGE_FULL: [&'static str; 3] = ["core", "ops", "RangeFull"]; +pub const RANGE_FULL_STD: [&'static str; 3] = ["std", "ops", "RangeFull"]; +pub const RANGE_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeInclusive"]; +pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["core", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE_INCLUSIVE_NON_EMPTY_STD: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; +pub const RANGE_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeInclusive"]; +pub const RANGE_STD: [&'static str; 3] = ["std", "ops", "Range"]; +pub const RANGE_TO: [&'static str; 3] = ["core", "ops", "RangeTo"]; +pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclusive"]; +pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; +pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; +pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; +pub const REGEX_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; +pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; +pub const REGEX_BYTES_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; +pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "new"]; +pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; +pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; +pub const REGEX_SET_NEW: [&'static str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; +pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; +pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; +pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; +pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"]; +pub const VEC_DEQUE: [&'static str; 3] = ["collections", "vec_deque", "VecDeque"]; +pub const VEC_FROM_ELEM: [&'static str; 3] = ["std", "vec", "from_elem"]; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs new file mode 100644 index 00000000000..e62a8f9c459 --- /dev/null +++ b/clippy_lints/src/vec.rs @@ -0,0 +1,116 @@ +use rustc::lint::*; +use rustc::ty::TypeVariants; +use rustc::hir::*; +use syntax::codemap::Span; +use syntax::ptr::P; +use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; + +/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. +/// +/// **Why is this bad?** This is less efficient. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// foo(&vec![1, 2]) +/// ``` +declare_lint! { + pub USELESS_VEC, + Warn, + "useless `vec!`" +} + +#[derive(Copy, Clone, Debug)] +pub struct UselessVec; + +impl LintPass for UselessVec { + fn get_lints(&self) -> LintArray { + lint_array!(USELESS_VEC) + } +} + +impl LateLintPass for UselessVec { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // search for `&vec![_]` expressions where the adjusted type is `&[_]` + if_let_chain!{[ + let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, + let TypeVariants::TySlice(..) = ty.ty.sty, + let ExprAddrOf(_, ref addressee) = expr.node, + ], { + check_vec_macro(cx, addressee, expr.span); + }} + + // search for `for _ in vec![…]` + if let Some((_, arg, _)) = recover_for_loop(expr) { + // report the error around the `vec!` not inside `<std macros>:` + let span = cx.sess().codemap().source_callsite(arg.span); + check_vec_macro(cx, arg, span); + } + } +} + +fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { + if let Some(vec_args) = unexpand_vec(cx, vec) { + let snippet = match vec_args { + VecArgs::Repeat(elem, len) => { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } + VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = Span { + lo: args[0].span.lo, + hi: last.span.hi, + expn_id: args[0].span.expn_id, + }; + + format!("&[{}]", snippet(cx, span, "..")).into() + } else { + "&[]".into() + } + } + }; + + span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { + db.span_suggestion(span, "you can use a slice directly", snippet); + }); + } +} + +/// Represent the pre-expansion arguments of a `vec!` invocation. +pub enum VecArgs<'a> { + /// `vec![elem; len]` + Repeat(&'a P<Expr>, &'a P<Expr>), + /// `vec![a, b, c]` + Vec(&'a [P<Expr>]), +} + +/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. +pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> { + if_let_chain!{[ + let ExprCall(ref fun, ref args) = expr.node, + let ExprPath(_, ref path) = fun.node, + is_expn_of(cx, fun.span, "vec").is_some() + ], { + return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { + // `vec![elem; size]` case + Some(VecArgs::Repeat(&args[0], &args[1])) + } + else if match_path(path, &["into_vec"]) && args.len() == 1 { + // `vec![a, b, c]` case + if_let_chain!{[ + let ExprBox(ref boxed) = args[0].node, + let ExprVec(ref args) = boxed.node + ], { + return Some(VecArgs::Vec(&*args)); + }} + + None + } + else { + None + }; + }} + + None +} diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs new file mode 100644 index 00000000000..902d84d4dd3 --- /dev/null +++ b/clippy_lints/src/zero_div_zero.rs @@ -0,0 +1,59 @@ +use consts::{Constant, constant_simple, FloatWidth}; +use rustc::lint::*; +use rustc::hir::*; +use utils::span_help_and_lint; + +/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists +/// `of 0.0/0.0`, which is always `NaN`. It is more clear to replace instances of +/// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. +pub struct ZeroDivZeroPass; + +/// **What it does:** This lint checks for `0.0 / 0.0`. +/// +/// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN` +/// +/// **Known problems:** None +/// +/// **Example** `0.0f32 / 0.0` +declare_lint! { + pub ZERO_DIVIDED_BY_ZERO, + Warn, + "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" +} + +impl LintPass for ZeroDivZeroPass { + fn get_lints(&self) -> LintArray { + lint_array!(ZERO_DIVIDED_BY_ZERO) + } +} + +impl LateLintPass for ZeroDivZeroPass { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + // check for instances of 0.0/0.0 + if_let_chain! { + [ + let ExprBinary(ref op, ref left, ref right) = expr.node, + let BinOp_::BiDiv = op.node, + // TODO - constant_simple does not fold many operations involving floats. + // That's probably fine for this lint - it's pretty unlikely that someone would + // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. + let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), + let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), + let Some(0.0) = lhs_value.parse().ok(), + let Some(0.0) = rhs_value.parse().ok() + ], + { + // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, + // match the precision of the literals that are given. + let float_type = match (lhs_width, rhs_width) { + (FloatWidth::F64, _) + | (_, FloatWidth::F64) => "f64", + _ => "f32" + }; + span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, + "constant division of 0.0 with 0.0 will always result in NaN", + &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); + } + } + } +} diff --git a/src/approx_const.rs b/src/approx_const.rs deleted file mode 100644 index 731f1a45d09..00000000000 --- a/src/approx_const.rs +++ /dev/null @@ -1,95 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use std::f64::consts as f64; -use syntax::ast::{Lit, LitKind, FloatTy}; -use utils::span_lint; - -/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. -/// -/// **Why is this bad?** Usually, the definition in the standard library is more precise than what people come up with. If you find that your definition is actually more precise, please [file a Rust issue](https://github.com/rust-lang/rust/issues). -/// -/// **Known problems:** If you happen to have a value that is within 1/8192 of a known constant, but is not *and should not* be the same, this lint will report your value anyway. We have not yet noticed any false positives in code we tested clippy with (this includes servo), but YMMV. -/// -/// **Example:** `let x = 3.14;` -declare_lint! { - pub APPROX_CONSTANT, - Warn, - "the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) \ - is found; suggests to use the constant" -} - -// Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), - (f64::FRAC_1_PI, "FRAC_1_PI", 4), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), - (f64::FRAC_2_PI, "FRAC_2_PI", 5), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), - (f64::FRAC_PI_2, "FRAC_PI_2", 5), - (f64::FRAC_PI_3, "FRAC_PI_3", 5), - (f64::FRAC_PI_4, "FRAC_PI_4", 5), - (f64::FRAC_PI_6, "FRAC_PI_6", 5), - (f64::FRAC_PI_8, "FRAC_PI_8", 5), - (f64::LN_10, "LN_10", 5), - (f64::LN_2, "LN_2", 5), - (f64::LOG10_E, "LOG10_E", 5), - (f64::LOG2_E, "LOG2_E", 5), - (f64::PI, "PI", 3), - (f64::SQRT_2, "SQRT_2", 5)]; - -#[derive(Copy,Clone)] -pub struct ApproxConstant; - -impl LintPass for ApproxConstant { - fn get_lints(&self) -> LintArray { - lint_array!(APPROX_CONSTANT) - } -} - -impl LateLintPass for ApproxConstant { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprLit(ref lit) = e.node { - check_lit(cx, lit, e); - } - } -} - -fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { - match lit.node { - LitKind::Float(ref s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), - LitKind::Float(ref s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), - LitKind::FloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), - _ => (), - } -} - -fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { - if let Ok(_) = s.parse::<f64>() { - for &(constant, name, min_digits) in KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) { - span_lint(cx, - APPROX_CONSTANT, - e.span, - &format!("approximate value of `{}::{}` found. Consider using it directly", module, &name)); - return; - } - } - } -} - -/// Returns false if the number of significant figures in `value` are -/// less than `min_digits`; otherwise, returns true if `value` is equal -/// to `constant`, rounded to the number of digits present in `value`. -fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool { - if value.len() <= min_digits { - false - } else { - let round_const = format!("{:.*}", value.len() - 2, constant); - - let mut trunc_const = constant.to_string(); - if trunc_const.len() > value.len() { - trunc_const.truncate(value.len()); - } - - (value == round_const) || (value == trunc_const) - } -} diff --git a/src/arithmetic.rs b/src/arithmetic.rs deleted file mode 100644 index be732740442..00000000000 --- a/src/arithmetic.rs +++ /dev/null @@ -1,102 +0,0 @@ -use rustc::hir; -use rustc::lint::*; -use syntax::codemap::Span; -use utils::span_lint; - -/// **What it does:** This lint checks for plain integer arithmetic -/// -/// **Why is this bad?** This is only checked against overflow in debug builds. -/// In some applications one wants explicitly checked, wrapping or saturating -/// arithmetic. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// a + 1 -/// ``` -declare_restriction_lint! { - pub INTEGER_ARITHMETIC, - "Any integer arithmetic statement" -} - -/// **What it does:** This lint checks for float arithmetic -/// -/// **Why is this bad?** For some embedded systems or kernel development, it -/// can be useful to rule out floating-point numbers -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// a + 1.0 -/// ``` -declare_restriction_lint! { - pub FLOAT_ARITHMETIC, - "Any floating-point arithmetic statement" -} - -#[derive(Copy, Clone, Default)] -pub struct Arithmetic { - span: Option<Span> -} - -impl LintPass for Arithmetic { - fn get_lints(&self) -> LintArray { - lint_array!(INTEGER_ARITHMETIC, FLOAT_ARITHMETIC) - } -} - -impl LateLintPass for Arithmetic { - fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { - if let Some(_) = self.span { return; } - match expr.node { - hir::ExprBinary(ref op, ref l, ref r) => { - match op.node { - hir::BiAnd | hir::BiOr | hir::BiBitAnd | - hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | - hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | - hir::BiGt => return, - _ => () - } - let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r)); - if l_ty.is_integral() && r_ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, - expr.span, - "integer arithmetic detected"); - self.span = Some(expr.span); - } else if l_ty.is_floating_point() && r_ty.is_floating_point() { - span_lint(cx, - FLOAT_ARITHMETIC, - expr.span, - "floating-point arithmetic detected"); - self.span = Some(expr.span); - } - }, - hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { - let ty = cx.tcx.expr_ty(arg); - if ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, - expr.span, - "integer arithmetic detected"); - self.span = Some(expr.span); - } else if ty.is_floating_point() { - span_lint(cx, - FLOAT_ARITHMETIC, - expr.span, - "floating-point arithmetic detected"); - self.span = Some(expr.span); - } - }, - _ => () - } - } - - fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) { - if Some(expr.span) == self.span { - self.span = None; - } - } -} diff --git a/src/array_indexing.rs b/src/array_indexing.rs deleted file mode 100644 index ce2b9a7d6c0..00000000000 --- a/src/array_indexing.rs +++ /dev/null @@ -1,135 +0,0 @@ -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc::ty::TyArray; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use rustc_const_math::ConstInt; -use rustc::hir::*; -use syntax::ast::RangeLimits; -use utils; - -/// **What it does:** Check for out of bounds array indexing with a constant index. -/// -/// **Why is this bad?** This will always panic at runtime. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// -/// ``` -/// let x = [1,2,3,4]; -/// ... -/// x[9]; -/// &x[2..9]; -/// ``` -declare_lint! { - pub OUT_OF_BOUNDS_INDEXING, - Deny, - "out of bound constant indexing" -} - -/// **What it does:** Check for usage of indexing or slicing. -/// -/// **Why is this bad?** Usually, this can be safely allowed. However, -/// in some domains such as kernel development, a panic can cause the -/// whole operating system to crash. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// -/// ``` -/// ... -/// x[2]; -/// &x[0..2]; -/// ``` -declare_lint! { - pub INDEXING_SLICING, - Allow, - "indexing/slicing usage" -} - -#[derive(Copy,Clone)] -pub struct ArrayIndexing; - -impl LintPass for ArrayIndexing { - fn get_lints(&self) -> LintArray { - lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) - } -} - -impl LateLintPass for ArrayIndexing { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprIndex(ref array, ref index) = e.node { - // Array with known size can be checked statically - let ty = cx.tcx.expr_ty(array); - if let TyArray(_, size) = ty.sty { - let size = ConstInt::Infer(size as u64); - - // Index is a constant uint - let const_index = eval_const_expr_partial(cx.tcx, index, ExprTypeChecked, None); - if let Ok(ConstVal::Integral(const_index)) = const_index { - if size <= const_index { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); - } - - return; - } - - // Index is a constant range - if let Some(range) = utils::unsugar_range(index) { - let start = range.start - .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) - .map(|v| v.ok()); - let end = range.end - .map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)) - .map(|v| v.ok()); - - if let Some((start, end)) = to_const_range(start, end, range.limits, size) { - if start > size || end > size { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); - } - return; - } - } - } - - if let Some(range) = utils::unsugar_range(index) { - // Full ranges are always valid - if range.start.is_none() && range.end.is_none() { - return; - } - - // Impossible to know if indexing or slicing is correct - utils::span_lint(cx, INDEXING_SLICING, e.span, "slicing may panic"); - } else { - utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); - } - } - } -} - -/// Returns an option containing a tuple with the start and end (exclusive) of the range. -fn to_const_range(start: Option<Option<ConstVal>>, end: Option<Option<ConstVal>>, limits: RangeLimits, - array_size: ConstInt) - -> Option<(ConstInt, ConstInt)> { - let start = match start { - Some(Some(ConstVal::Integral(x))) => x, - Some(_) => return None, - None => ConstInt::Infer(0), - }; - - let end = match end { - Some(Some(ConstVal::Integral(x))) => { - if limits == RangeLimits::Closed { - (x + ConstInt::Infer(1)).expect("such a big array is not realistic") - } else { - x - } - } - Some(_) => return None, - None => array_size, - }; - - Some((start, end)) -} diff --git a/src/assign_ops.rs b/src/assign_ops.rs deleted file mode 100644 index 2b1aec83e4c..00000000000 --- a/src/assign_ops.rs +++ /dev/null @@ -1,158 +0,0 @@ -use rustc::hir; -use rustc::lint::*; -use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; - -/// **What it does:** This lint checks for `+=` operations and similar -/// -/// **Why is this bad?** Projects with many developers from languages without those operations -/// may find them unreadable and not worth their weight -/// -/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op` -/// -/// **Example:** -/// ``` -/// a += 1; -/// ``` -declare_restriction_lint! { - pub ASSIGN_OPS, - "Any assignment operation" -} - -/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns -/// -/// **Why is this bad?** These can be written as the shorter `a op= b` -/// -/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl -/// -/// **Example:** -/// -/// ``` -/// let mut a = 5; -/// ... -/// a = a + b; -/// ``` -declare_lint! { - pub ASSIGN_OP_PATTERN, - Warn, - "assigning the result of an operation on a variable to that same variable" -} - -#[derive(Copy, Clone, Default)] -pub struct AssignOps; - -impl LintPass for AssignOps { - fn get_lints(&self) -> LintArray { - lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN) - } -} - -impl LateLintPass for AssignOps { - fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { - match expr.node { - hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) { - span_lint_and_then(cx, - ASSIGN_OPS, - expr.span, - "assign operation detected", - |db| { - match rhs.node { - hir::ExprBinary(op2, _, _) if op2 != op => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); - }, - _ => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} {}", l, l, op.node.as_str(), r)); - } - } - }); - } else { - span_lint(cx, - ASSIGN_OPS, - expr.span, - "assign operation detected"); - } - }, - hir::ExprAssign(ref assignee, ref e) => { - if let hir::ExprBinary(op, ref l, ref r) = e.node { - let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { - let ty = cx.tcx.expr_ty(assignee); - if ty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } - let rty = cx.tcx.expr_ty(rhs); - if rty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } - macro_rules! ops { - ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => { - match $op { - $(hir::$full_trait_name => { - let [krate, module] = ::utils::paths::OPS_MODULE; - let path = [krate, module, concat!(stringify!($trait_name), "Assign")]; - let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { - trait_id - } else { - return; // useless if the trait doesn't exist - }; - implements_trait($cx, $ty, trait_id, vec![$rty]) - },)* - _ => false, - } - } - } - if ops!(op.node, cx, ty, rty, Add:BiAdd, - Sub:BiSub, - Mul:BiMul, - Div:BiDiv, - Rem:BiRem, - And:BiAnd, - Or:BiOr, - BitAnd:BiBitAnd, - BitOr:BiBitOr, - BitXor:BiBitXor, - Shr:BiShr, - Shl:BiShl - ) { - if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - span_lint_and_then(cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation", - |db| { - db.span_suggestion(expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r)); - }); - } else { - span_lint(cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation"); - } - } - }; - // a = a op b - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { - lint(assignee, r); - } - // a = b commutative_op a - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { - match op.node { - hir::BiAdd | hir::BiMul | - hir::BiAnd | hir::BiOr | - hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => { - lint(assignee, l); - }, - _ => {}, - } - } - } - }, - _ => {}, - } - } -} diff --git a/src/attrs.rs b/src/attrs.rs deleted file mode 100644 index 0cf62633de4..00000000000 --- a/src/attrs.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! checks for attributes - -use reexport::*; -use rustc::lint::*; -use rustc::hir::*; -use semver::Version; -use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind}; -use syntax::codemap::Span; -use utils::{in_macro, match_path, span_lint}; -use utils::paths; - -/// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics. -/// -/// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it. -/// -/// As a rule of thumb, before slapping `#[inline(always)]` on a function, measure if that additional function call really affects your runtime profile sufficiently to make up for the increase in compile time. -/// -/// **Known problems:** False positives, big time. This lint is meant to be deactivated by everyone doing serious performance work. This means having done the measurement. -/// -/// **Example:** -/// ``` -/// #[inline(always)] -/// fn not_quite_hot_code(..) { ... } -/// ``` -declare_lint! { - pub INLINE_ALWAYS, Warn, - "`#[inline(always)]` is a bad idea in most cases" -} - -/// **What it does:** This lint checks for `#[deprecated]` annotations with a `since` field that is not a valid semantic version.. -/// -/// **Why is this bad?** For checking the version of the deprecation, it must be valid semver. Failing that, the contained information is useless. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// #[deprecated(since = "forever")] -/// fn something_else(..) { ... } -/// ``` -declare_lint! { - pub DEPRECATED_SEMVER, Warn, - "`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" -} - -#[derive(Copy,Clone)] -pub struct AttrPass; - -impl LintPass for AttrPass { - fn get_lints(&self) -> LintArray { - lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER) - } -} - -impl LateLintPass for AttrPass { - fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) { - if let MetaItemKind::List(ref name, ref items) = attr.node.value.node { - if items.is_empty() || name != &"deprecated" { - return; - } - for ref item in items { - if let MetaItemKind::NameValue(ref name, ref lit) = item.node { - if name == &"since" { - check_semver(cx, item.span, lit); - } - } - } - } - } - - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if is_relevant_item(item) { - check_attrs(cx, item.span, &item.name, &item.attrs) - } - } - - fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if is_relevant_impl(item) { - check_attrs(cx, item.span, &item.name, &item.attrs) - } - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - if is_relevant_trait(item) { - check_attrs(cx, item.span, &item.name, &item.attrs) - } - } -} - -fn is_relevant_item(item: &Item) -> bool { - if let ItemFn(_, _, _, _, _, ref block) = item.node { - is_relevant_block(block) - } else { - false - } -} - -fn is_relevant_impl(item: &ImplItem) -> bool { - match item.node { - ImplItemKind::Method(_, ref block) => is_relevant_block(block), - _ => false, - } -} - -fn is_relevant_trait(item: &TraitItem) -> bool { - match item.node { - MethodTraitItem(_, None) => true, - MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), - _ => false, - } -} - -fn is_relevant_block(block: &Block) -> bool { - for stmt in &block.stmts { - match stmt.node { - StmtDecl(_, _) => return true, - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => { - return is_relevant_expr(expr); - } - } - } - block.expr.as_ref().map_or(false, |e| is_relevant_expr(e)) -} - -fn is_relevant_expr(expr: &Expr) -> bool { - match expr.node { - ExprBlock(ref block) => is_relevant_block(block), - ExprRet(Some(ref e)) => is_relevant_expr(e), - ExprRet(None) | ExprBreak(_) => false, - ExprCall(ref path_expr, _) => { - if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &paths::BEGIN_PANIC) - } else { - true - } - } - _ => true, - } -} - -fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { - if in_macro(cx, span) { - return; - } - - for attr in attrs { - if let MetaItemKind::List(ref inline, ref values) = attr.node.value.node { - if values.len() != 1 || inline != &"inline" { - continue; - } - if let MetaItemKind::Word(ref always) = values[0].node { - if always != &"always" { - continue; - } - span_lint(cx, - INLINE_ALWAYS, - attr.span, - &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea", - name)); - } - } - } -} - -fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { - if let LitKind::Str(ref is, _) = lit.node { - if Version::parse(&*is).is_ok() { - return; - } - } - span_lint(cx, - DEPRECATED_SEMVER, - span, - "the since field must contain a semver-compliant version"); -} diff --git a/src/bit_mask.rs b/src/bit_mask.rs deleted file mode 100644 index aec0990dcc6..00000000000 --- a/src/bit_mask.rs +++ /dev/null @@ -1,276 +0,0 @@ -use rustc::hir::*; -use rustc::hir::def::{Def, PathResolution}; -use rustc::lint::*; -use rustc_const_eval::lookup_const_by_id; -use syntax::ast::LitKind; -use syntax::codemap::Span; -use utils::span_lint; - -/// **What it does:** This lint checks for incompatible bit masks in comparisons. -/// -/// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` -/// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: -/// -/// |Comparison |Bit Op|Example |is always|Formula | -/// |------------|------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | -/// -/// **Why is this bad?** If the bits that the comparison cares about are always set to zero or one by the bit mask, the comparison is constant `true` or `false` (depending on mask, compared value, and operators). -/// -/// So the code is actively misleading, and the only reason someone would write this intentionally is to win an underhanded Rust contest or create a test-case for this lint. -/// -/// **Known problems:** None -/// -/// **Example:** `x & 1 == 2` (also see table above) -declare_lint! { - pub BAD_BIT_MASK, - Warn, - "expressions of the form `_ & mask == select` that will only ever return `true` or `false` \ - (because in the example `select` containing bits that `mask` doesn't have)" -} - -/// **What it does:** This lint checks for bit masks in comparisons which can be removed without changing the outcome. The basic structure can be seen in the following table: -/// -/// |Comparison| Bit Op |Example |equals | -/// |----------|---------|-----------|-------| -/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| -/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`| -/// -/// **Why is this bad?** Not equally evil as [`bad_bit_mask`](#bad_bit_mask), but still a bit misleading, because the bit mask is ineffective. -/// -/// **Known problems:** False negatives: This lint will only match instances where we have figured out the math (which is for a power-of-two compared value). This means things like `x | 1 >= 7` (which would be better written as `x >= 6`) will not be reported (but bit masks like this are fairly uncommon). -/// -/// **Example:** `x | 1 > 3` (also see table above) -declare_lint! { - pub INEFFECTIVE_BIT_MASK, - Warn, - "expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`" -} - -/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. -/// This cannot work because the bit that makes up the value two was -/// zeroed out by the bit-and with 1. So the formula for detecting if an -/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` -/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , -/// `!=`, `>=`, `>`}) can be determined from the following table: -/// -/// |Comparison |Bit Op|Example |is always|Formula | -/// |------------|------|------------|---------|----------------------| -/// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -/// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -/// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -/// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -/// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -/// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | -/// -/// This lint is **deny** by default -/// -/// There is also a lint that warns on ineffective masks that is *warn* -/// by default. -/// -/// |Comparison|Bit Op |Example |equals |Formula| -/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| -/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | -/// -/// `¹ power_of_two(c + 1)` -#[derive(Copy,Clone)] -pub struct BitMask; - -impl LintPass for BitMask { - fn get_lints(&self) -> LintArray { - lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) - } -} - -impl LateLintPass for BitMask { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = e.node { - if cmp.node.is_comparison() { - fetch_int_literal(cx, right).map_or_else(|| { - fetch_int_literal(cx, left).map_or((), |cmp_val| { - check_compare(cx, - right, - invert_cmp(cmp.node), - cmp_val, - &e.span) - }) - }, - |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, &e.span)) - } - } - } -} - -fn invert_cmp(cmp: BinOp_) -> BinOp_ { - match cmp { - BiEq => BiEq, - BiNe => BiNe, - BiLt => BiGt, - BiGt => BiLt, - BiLe => BiGe, - BiGe => BiLe, - _ => BiOr, // Dummy - } -} - - -fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { - if let ExprBinary(ref op, ref left, ref right) = bit_op.node { - if op.node != BiBitAnd && op.node != BiBitOr { - return; - } - fetch_int_literal(cx, right) - .or_else(|| fetch_int_literal(cx, left)) - .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span)) - } -} - -fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { - match cmp_op { - BiEq | BiNe => { - match bit_op { - BiBitAnd => { - if mask_value & cmp_value != cmp_value { - if cmp_value != 0 { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, - cmp_value)); - } - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - } - BiBitOr => { - if mask_value | cmp_value != cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, - cmp_value)); - } - } - _ => (), - } - } - BiLt | BiGe => { - match bit_op { - BiBitAnd => { - if mask_value < cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, - cmp_value)); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - } - BiBitOr => { - if mask_value >= cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, - cmp_value)); - } else { - check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); - } - } - BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } - } - BiLe | BiGt => { - match bit_op { - BiBitAnd => { - if mask_value <= cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, - cmp_value)); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - } - BiBitOr => { - if mask_value > cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, - cmp_value)); - } else { - check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); - } - } - BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } - } - _ => (), - } -} - -fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { - if c.is_power_of_two() && m < c { - span_lint(cx, - INEFFECTIVE_BIT_MASK, - span, - &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c)); - } -} - -fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { - if (c + 1).is_power_of_two() && m <= c { - span_lint(cx, - INEFFECTIVE_BIT_MASK, - span, - &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c)); - } -} - -fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> { - match lit.node { - ExprLit(ref lit_ptr) => { - if let LitKind::Int(value, _) = lit_ptr.node { - Some(value) //TODO: Handle sign - } else { - None - } - } - ExprPath(_, _) => { - { - // Important to let the borrow expire before the const lookup to avoid double - // borrowing. - let def_map = cx.tcx.def_map.borrow(); - match def_map.get(&lit.id) { - Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id), - _ => None, - } - } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None)) - .and_then(|(l, _ty)| fetch_int_literal(cx, l)) - } - _ => None, - } -} diff --git a/src/blacklisted_name.rs b/src/blacklisted_name.rs deleted file mode 100644 index 5cb84f62651..00000000000 --- a/src/blacklisted_name.rs +++ /dev/null @@ -1,46 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use utils::span_lint; - -/// **What it does:** This lints about usage of blacklisted names. -/// -/// **Why is this bad?** These names are usually placeholder names and should be avoided. -/// -/// **Known problems:** None. -/// -/// **Example:** `let foo = 3.14;` -declare_lint! { - pub BLACKLISTED_NAME, - Warn, - "usage of a blacklisted/placeholder name" -} - -#[derive(Clone, Debug)] -pub struct BlackListedName { - blacklist: Vec<String>, -} - -impl BlackListedName { - pub fn new(blacklist: Vec<String>) -> BlackListedName { - BlackListedName { blacklist: blacklist } - } -} - -impl LintPass for BlackListedName { - fn get_lints(&self) -> LintArray { - lint_array!(BLACKLISTED_NAME) - } -} - -impl LateLintPass for BlackListedName { - fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatKind::Ident(_, ref ident, _) = pat.node { - if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) { - span_lint(cx, - BLACKLISTED_NAME, - pat.span, - &format!("use of a blacklisted/placeholder name `{}`", ident.node)); - } - } - } -} diff --git a/src/block_in_if_condition.rs b/src/block_in_if_condition.rs deleted file mode 100644 index c56cf4dcd29..00000000000 --- a/src/block_in_if_condition.rs +++ /dev/null @@ -1,118 +0,0 @@ -use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; -use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr}; -use utils::*; - -/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. -/// -/// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions. -/// -/// **Known problems:** None -/// -/// **Example:** `if { true } ..` -declare_lint! { - pub BLOCK_IN_IF_CONDITION_EXPR, Warn, - "braces can be eliminated in conditions that are expressions, e.g `if { true } ...`" -} - -/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. -/// -/// **Why is this bad?** Using blocks in the condition makes it hard to read. -/// -/// **Known problems:** None -/// -/// **Example:** `if { let x = somefunc(); x } ..` or `if somefunc(|x| { x == 47 }) ..` -declare_lint! { - pub BLOCK_IN_IF_CONDITION_STMT, Warn, - "avoid complex blocks in conditions, instead move the block higher and bind it \ - with 'let'; e.g: `if { let x = true; x } ...`" -} - -#[derive(Copy,Clone)] -pub struct BlockInIfCondition; - -impl LintPass for BlockInIfCondition { - fn get_lints(&self) -> LintArray { - lint_array!(BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT) - } -} - -struct ExVisitor<'v> { - found_block: Option<&'v Expr>, -} - -impl<'v> Visitor<'v> for ExVisitor<'v> { - fn visit_expr(&mut self, expr: &'v Expr) { - if let ExprClosure(_, _, ref block, _) = expr.node { - let complex = { - if block.stmts.is_empty() { - if let Some(ref ex) = block.expr { - match ex.node { - ExprBlock(_) => true, - _ => false, - } - } else { - false - } - } else { - true - } - }; - if complex { - self.found_block = Some(expr); - return; - } - } - walk_expr(self, expr); - } -} - -const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition"; -const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ - instead, move the block or closure higher and bind it with a 'let'"; - -impl LateLintPass for BlockInIfCondition { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprIf(ref check, ref then, _) = expr.node { - if let ExprBlock(ref block) = check.node { - if block.rules == DefaultBlock { - if block.stmts.is_empty() { - if let Some(ref ex) = block.expr { - // don't dig into the expression here, just suggest that they remove - // the block - if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, ex.span) { - return; - } - span_help_and_lint(cx, - BLOCK_IN_IF_CONDITION_EXPR, - check.span, - BRACED_EXPR_MESSAGE, - &format!("try\nif {} {} ... ", - snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, ".."))); - } - } else { - let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); - if in_macro(cx, span) || differing_macro_contexts(expr.span, span) { - return; - } - // move block higher - span_help_and_lint(cx, - BLOCK_IN_IF_CONDITION_STMT, - check.span, - COMPLEX_BLOCK_MESSAGE, - &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, ".."))); - } - } - } else { - let mut visitor = ExVisitor { found_block: None }; - walk_expr(&mut visitor, check); - if let Some(ref block) = visitor.found_block { - span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE, ""); - } - } - } - } -} diff --git a/src/booleans.rs b/src/booleans.rs deleted file mode 100644 index 9ab806f66ec..00000000000 --- a/src/booleans.rs +++ /dev/null @@ -1,389 +0,0 @@ -use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; -use rustc::hir::*; -use rustc::hir::intravisit::*; -use syntax::ast::{LitKind, DUMMY_NODE_ID}; -use syntax::codemap::{DUMMY_SP, dummy_spanned}; -use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; - -/// **What it does:** This lint checks for boolean expressions that can be written more concisely -/// -/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication -/// -/// **Known problems:** Ignores short circuting behavior of `||` and `&&`. Ignores `|`, `&` and `^`. -/// -/// **Example:** `if a && true` should be `if a` and `!(a == b)` should be `a != b` -declare_lint! { - pub NONMINIMAL_BOOL, Allow, - "checks for boolean expressions that can be written more concisely" -} - -/// **What it does:** This lint checks for boolean expressions that contain terminals that can be eliminated -/// -/// **Why is this bad?** This is most likely a logic bug -/// -/// **Known problems:** Ignores short circuiting behavior -/// -/// **Example:** The `b` in `if a && b || a` is unnecessary because the expression is equivalent to `if a` -declare_lint! { - pub LOGIC_BUG, Warn, - "checks for boolean expressions that contain terminals which can be eliminated" -} - -#[derive(Copy,Clone)] -pub struct NonminimalBool; - -impl LintPass for NonminimalBool { - fn get_lints(&self) -> LintArray { - lint_array!(NONMINIMAL_BOOL, LOGIC_BUG) - } -} - -impl LateLintPass for NonminimalBool { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - NonminimalBoolVisitor(cx).visit_item(item) - } -} - -struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); - -use quine_mc_cluskey::Bool; -struct Hir2Qmm<'a, 'tcx: 'a, 'v> { - terminals: Vec<&'v Expr>, - cx: &'a LateContext<'a, 'tcx>, -} - -impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { - fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> { - for a in a { - if let ExprBinary(binop, ref lhs, ref rhs) = a.node { - if binop.node == op { - v = self.extract(op, &[lhs, rhs], v)?; - continue; - } - } - v.push(self.run(a)?); - } - Ok(v) - } - - fn run(&mut self, e: &'v Expr) -> Result<Bool, String> { - // prevent folding of `cfg!` macros and the like - if !in_macro(self.cx, e.span) { - match e.node { - ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprBinary(binop, ref lhs, ref rhs) => { - match binop.node { - BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), - BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), - _ => (), - } - } - ExprLit(ref lit) => { - match lit.node { - LitKind::Bool(true) => return Ok(Bool::True), - LitKind::Bool(false) => return Ok(Bool::False), - _ => (), - } - } - _ => (), - } - } - for (n, expr) in self.terminals.iter().enumerate() { - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { - #[allow(cast_possible_truncation)] - return Ok(Bool::Term(n as u8)); - } - let negated = match e.node { - ExprBinary(binop, ref lhs, ref rhs) => { - let mk_expr = |op| { - Expr { - id: DUMMY_NODE_ID, - span: DUMMY_SP, - attrs: None, - node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), - } - }; - match binop.node { - BiEq => mk_expr(BiNe), - BiNe => mk_expr(BiEq), - BiGt => mk_expr(BiLe), - BiGe => mk_expr(BiLt), - BiLt => mk_expr(BiGe), - BiLe => mk_expr(BiGt), - _ => continue, - } - } - _ => continue, - }; - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { - #[allow(cast_possible_truncation)] - return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); - } - } - let n = self.terminals.len(); - self.terminals.push(e); - if n < 32 { - #[allow(cast_possible_truncation)] - Ok(Bool::Term(n as u8)) - } else { - Err("too many literals".to_owned()) - } - } -} - -fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { - fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { - use quine_mc_cluskey::Bool::*; - let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); - match *suggestion { - True => { - s.push_str("true"); - s - } - False => { - s.push_str("false"); - s - } - Not(ref inner) => { - match **inner { - And(_) | Or(_) => { - s.push('!'); - recurse(true, cx, inner, terminals, s) - } - Term(n) => { - if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { - s.push('!'); - return recurse(true, cx, inner, terminals, s); - } - }; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - } else { - s.push('!'); - recurse(false, cx, inner, terminals, s) - } - } - _ => { - s.push('!'); - recurse(false, cx, inner, terminals, s) - } - } - } - And(ref v) => { - if brackets { - s.push('('); - } - if let Or(_) = v[0] { - s = recurse(true, cx, &v[0], terminals, s); - } else { - s = recurse(false, cx, &v[0], terminals, s); - } - for inner in &v[1..] { - s.push_str(" && "); - if let Or(_) = *inner { - s = recurse(true, cx, inner, terminals, s); - } else { - s = recurse(false, cx, inner, terminals, s); - } - } - if brackets { - s.push(')'); - } - s - } - Or(ref v) => { - if brackets { - s.push('('); - } - s = recurse(false, cx, &v[0], terminals, s); - for inner in &v[1..] { - s.push_str(" || "); - s = recurse(false, cx, inner, terminals, s); - } - if brackets { - s.push(')'); - } - s - } - Term(n) => { - if brackets { - if let ExprBinary(..) = terminals[n as usize].node { - s.push('('); - } - } - s.push_str(&snip(terminals[n as usize])); - if brackets { - if let ExprBinary(..) = terminals[n as usize].node { - s.push(')'); - } - } - s - } - } - } - recurse(false, cx, suggestion, terminals, String::new()) -} - -fn simple_negate(b: Bool) -> Bool { - use quine_mc_cluskey::Bool::*; - match b { - True => False, - False => True, - t @ Term(_) => Not(Box::new(t)), - And(mut v) => { - for el in &mut v { - *el = simple_negate(::std::mem::replace(el, True)); - } - Or(v) - } - Or(mut v) => { - for el in &mut v { - *el = simple_negate(::std::mem::replace(el, True)); - } - And(v) - } - Not(inner) => *inner, - } -} - -#[derive(Default)] -struct Stats { - terminals: [usize; 32], - negations: usize, - ops: usize, -} - -fn terminal_stats(b: &Bool) -> Stats { - fn recurse(b: &Bool, stats: &mut Stats) { - match *b { - True | False => stats.ops += 1, - Not(ref inner) => { - match **inner { - And(_) | Or(_) => stats.ops += 1, // brackets are also operations - _ => stats.negations += 1, - } - recurse(inner, stats); - } - And(ref v) | Or(ref v) => { - stats.ops += v.len() - 1; - for inner in v { - recurse(inner, stats); - } - } - Term(n) => stats.terminals[n as usize] += 1, - } - } - use quine_mc_cluskey::Bool::*; - let mut stats = Stats::default(); - recurse(b, &mut stats); - stats -} - -impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { - fn bool_expr(&self, e: &Expr) { - let mut h2q = Hir2Qmm { - terminals: Vec::new(), - cx: self.0, - }; - if let Ok(expr) = h2q.run(e) { - - if h2q.terminals.len() > 8 { - // QMC has exponentially slow behavior as the number of terminals increases - // 8 is reasonable, it takes approximately 0.2 seconds. - // See #825 - return; - } - - let stats = terminal_stats(&expr); - let mut simplified = expr.simplify(); - for simple in Bool::Not(Box::new(expr.clone())).simplify() { - match simple { - Bool::Not(_) | Bool::True | Bool::False => {} - _ => simplified.push(Bool::Not(Box::new(simple.clone()))), - } - let simple_negated = simple_negate(simple); - if simplified.iter().any(|s| *s == simple_negated) { - continue; - } - simplified.push(simple_negated); - } - let mut improvements = Vec::new(); - 'simplified: for suggestion in &simplified { - let simplified_stats = terminal_stats(suggestion); - let mut improvement = false; - for i in 0..32 { - // ignore any "simplifications" that end up requiring a terminal more often than in the original expression - if stats.terminals[i] < simplified_stats.terminals[i] { - continue 'simplified; - } - if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { - span_lint_and_then(self.0, - LOGIC_BUG, - e.span, - "this boolean expression contains a logic bug", - |db| { - db.span_help(h2q.terminals[i].span, - "this expression can be optimized out by applying \ - boolean operations to the outer expression"); - db.span_suggestion(e.span, - "it would look like the following", - suggest(self.0, suggestion, &h2q.terminals)); - }); - // don't also lint `NONMINIMAL_BOOL` - return; - } - // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases - improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || - (stats.negations > simplified_stats.negations && - stats.ops == simplified_stats.ops) || - (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); - } - if improvement { - improvements.push(suggestion); - } - } - if !improvements.is_empty() { - span_lint_and_then(self.0, - NONMINIMAL_BOOL, - e.span, - "this boolean expression can be simplified", - |db| { - for suggestion in &improvements { - db.span_suggestion(e.span, - "try", - suggest(self.0, suggestion, &h2q.terminals)); - } - }); - } - } - } -} - -impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { - fn visit_expr(&mut self, e: &'v Expr) { - if in_macro(self.0, e.span) { - return; - } - match e.node { - ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), - ExprUnary(UnNot, ref inner) => { - if self.0.tcx.node_types()[&inner.id].is_bool() { - self.bool_expr(e); - } else { - walk_expr(self, e); - } - } - _ => walk_expr(self, e), - } - } -} diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs deleted file mode 100644 index 38e04723e53..00000000000 --- a/src/collapsible_if.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Checks for if expressions that contain only an if expression. -//! -//! For example, the lint would catch: -//! -//! ``` -//! if x { -//! if y { -//! println!("Hello world"); -//! } -//! } -//! ``` -//! -//! This lint is **warn** by default - -use rustc::lint::*; -use rustc::hir::*; -use std::borrow::Cow; -use syntax::codemap::Spanned; - -use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; - -/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by -/// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to -/// `else if ..`. -/// -/// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is. -/// -/// **Known problems:** None -/// -/// **Example:** `if x { if y { .. } }` -declare_lint! { - pub COLLAPSIBLE_IF, - Warn, - "two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` \ - can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to \ - `else if`" -} - -#[derive(Copy,Clone)] -pub struct CollapsibleIf; - -impl LintPass for CollapsibleIf { - fn get_lints(&self) -> LintArray { - lint_array!(COLLAPSIBLE_IF) - } -} - -impl LateLintPass for CollapsibleIf { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if !in_macro(cx, expr.span) { - check_if(cx, expr) - } - } -} - -fn check_if(cx: &LateContext, e: &Expr) { - if let ExprIf(ref check, ref then, ref else_) = e.node { - if let Some(ref else_) = *else_ { - if_let_chain! {[ - let ExprBlock(ref block) = else_.node, - block.stmts.is_empty(), - block.rules == BlockCheckMode::DefaultBlock, - let Some(ref else_) = block.expr, - let ExprIf(_, _, _) = else_.node - ], { - span_lint_and_then(cx, - COLLAPSIBLE_IF, - block.span, - "this `else { if .. }` block can be collapsed", |db| { - db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); - }); - }} - } else if let Some(&Expr { node: ExprIf(ref check_inner, ref content, None), span: sp, .. }) = - single_stmt_of_block(then) { - if e.span.expn_id != sp.expn_id { - return; - } - span_lint_and_then(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", |db| { - db.span_suggestion(e.span, - "try", - format!("if {} && {} {}", - check_to_string(cx, check), - check_to_string(cx, check_inner), - snippet_block(cx, content.span, ".."))); - }); - } - } -} - -fn requires_brackets(e: &Expr) -> bool { - match e.node { - ExprBinary(Spanned { node: n, .. }, _, _) if n == BiEq => false, - _ => true, - } -} - -fn check_to_string(cx: &LateContext, e: &Expr) -> Cow<'static, str> { - if requires_brackets(e) { - format!("({})", snippet(cx, e.span, "..")).into() - } else { - snippet(cx, e.span, "..") - } -} - -fn single_stmt_of_block(block: &Block) -> Option<&Expr> { - if block.stmts.len() == 1 && block.expr.is_none() { - if let StmtExpr(ref expr, _) = block.stmts[0].node { - single_stmt_of_expr(expr) - } else { - None - } - } else if block.stmts.is_empty() { - if let Some(ref p) = block.expr { - Some(p) - } else { - None - } - } else { - None - } -} - -fn single_stmt_of_expr(expr: &Expr) -> Option<&Expr> { - if let ExprBlock(ref block) = expr.node { - single_stmt_of_block(block) - } else { - Some(expr) - } -} diff --git a/src/consts.rs b/src/consts.rs deleted file mode 100644 index 96956d1793b..00000000000 --- a/src/consts.rs +++ /dev/null @@ -1,379 +0,0 @@ -#![allow(cast_possible_truncation)] - -use rustc::lint::LateContext; -use rustc::hir::def::{Def, PathResolution}; -use rustc_const_eval::lookup_const_by_id; -use rustc_const_math::{ConstInt, ConstUsize, ConstIsize}; -use rustc::hir::*; -use std::cmp::Ordering::{self, Equal}; -use std::cmp::PartialOrd; -use std::hash::{Hash, Hasher}; -use std::mem; -use std::ops::Deref; -use std::rc::Rc; -use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy}; -use syntax::ptr::P; - -#[derive(Debug, Copy, Clone)] -pub enum FloatWidth { - F32, - F64, - Any, -} - -impl From<FloatTy> for FloatWidth { - fn from(ty: FloatTy) -> FloatWidth { - match ty { - FloatTy::F32 => FloatWidth::F32, - FloatTy::F64 => FloatWidth::F64, - } - } -} - -/// A `LitKind`-like enum to fold constant `Expr`s into. -#[derive(Debug, Clone)] -pub enum Constant { - /// a String "abc" - Str(String, StrStyle), - /// a Binary String b"abc" - Binary(Rc<Vec<u8>>), - /// a single char 'a' - Char(char), - /// an integer, third argument is whether the value is negated - Int(ConstInt), - /// a float with given type - Float(String, FloatWidth), - /// true or false - Bool(bool), - /// an array of constants - Vec(Vec<Constant>), - /// also an array, but with only one constant, repeated N times - Repeat(Box<Constant>, usize), - /// a tuple of constants - Tuple(Vec<Constant>), -} - -impl Constant { - /// convert to u64 if possible - /// - /// # panics - /// - /// if the constant could not be converted to u64 losslessly - fn as_u64(&self) -> u64 { - if let Constant::Int(val) = *self { - val.to_u64().expect("negative constant can't be casted to u64") - } else { - panic!("Could not convert a {:?} to u64", self); - } - } - - /// convert this constant to a f64, if possible - #[allow(cast_precision_loss, cast_possible_wrap)] - pub fn as_float(&self) -> Option<f64> { - match *self { - Constant::Float(ref s, _) => s.parse().ok(), - Constant::Int(i) if i.is_negative() => Some(i.to_u64_unchecked() as i64 as f64), - Constant::Int(i) => Some(i.to_u64_unchecked() as f64), - _ => None, - } - } -} - -impl PartialEq for Constant { - fn eq(&self, other: &Constant) -> bool { - match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, - (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, - (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(l), &Constant::Int(r)) => { - l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked() - } - (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { - // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have - // `Fw32 == Fw64` so don’t compare them - match (ls.parse::<f64>(), rs.parse::<f64>()) { - (Ok(l), Ok(r)) => l.eq(&r), - _ => false, - } - } - (&Constant::Bool(l), &Constant::Bool(r)) => l == r, - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, - _ => false, //TODO: Are there inter-type equalities? - } - } -} - -impl Hash for Constant { - fn hash<H>(&self, state: &mut H) - where H: Hasher - { - match *self { - Constant::Str(ref s, ref k) => { - s.hash(state); - k.hash(state); - } - Constant::Binary(ref b) => { - b.hash(state); - } - Constant::Char(c) => { - c.hash(state); - } - Constant::Int(i) => { - i.to_u64_unchecked().hash(state); - i.is_negative().hash(state); - } - Constant::Float(ref f, _) => { - // don’t use the width here because of PartialEq implementation - if let Ok(f) = f.parse::<f64>() { - unsafe { mem::transmute::<f64, u64>(f) }.hash(state); - } - } - Constant::Bool(b) => { - b.hash(state); - } - Constant::Vec(ref v) | - Constant::Tuple(ref v) => { - v.hash(state); - } - Constant::Repeat(ref c, l) => { - c.hash(state); - l.hash(state); - } - } - } -} - -impl PartialOrd for Constant { - fn partial_cmp(&self, other: &Constant) -> Option<Ordering> { - match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { - if l_sty == r_sty { - Some(ls.cmp(rs)) - } else { - None - } - } - (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), - (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), - (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { - match (ls.parse::<f64>(), rs.parse::<f64>()) { - (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), - _ => None, - } - } - (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { - match lv.partial_cmp(rv) { - Some(Equal) => Some(ls.cmp(rs)), - x => x, - } - } - _ => None, //TODO: Are there any useful inter-type orderings? - } - } -} - -/// parse a `LitKind` to a `Constant` -#[allow(cast_possible_wrap)] -pub fn lit_to_constant(lit: &LitKind) -> Constant { - match *lit { - LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), - LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), - LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), - LitKind::Char(c) => Constant::Char(c), - LitKind::Int(value, LitIntType::Unsuffixed) => Constant::Int(ConstInt::Infer(value)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U8)) => Constant::Int(ConstInt::U8(value as u8)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => { - Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))) - } - LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), - LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), - LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), - LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), - LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => { - Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))) - } - LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), - LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), - LitKind::Bool(b) => Constant::Bool(b), - } -} - -fn constant_not(o: Constant) -> Option<Constant> { - use self::Constant::*; - match o { - Bool(b) => Some(Bool(!b)), - Int(value) => (!value).ok().map(Int), - _ => None, - } -} - -fn constant_negate(o: Constant) -> Option<Constant> { - use self::Constant::*; - match o { - Int(value) => (-value).ok().map(Int), - Float(is, ty) => Some(Float(neg_float_str(is), ty)), - _ => None, - } -} - -fn neg_float_str(s: String) -> String { - if s.starts_with('-') { - s[1..].to_owned() - } else { - format!("-{}", s) - } -} - -pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { - let mut cx = ConstEvalLateContext { - lcx: Some(lcx), - needed_resolution: false, - }; - cx.expr(e).map(|cst| (cst, cx.needed_resolution)) -} - -pub fn constant_simple(e: &Expr) -> Option<Constant> { - let mut cx = ConstEvalLateContext { - lcx: None, - needed_resolution: false, - }; - cx.expr(e) -} - -struct ConstEvalLateContext<'c, 'cc: 'c> { - lcx: Option<&'c LateContext<'c, 'cc>>, - needed_resolution: bool, -} - -impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { - /// simple constant folding: Insert an expression, get a constant or none. - fn expr(&mut self, e: &Expr) -> Option<Constant> { - match e.node { - ExprPath(_, _) => self.fetch_path(e), - ExprBlock(ref block) => self.block(block), - ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), - ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), - ExprVec(ref vec) => self.multi(vec).map(Constant::Vec), - ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), - ExprRepeat(ref value, ref number) => { - self.binop_apply(value, number, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) - } - ExprUnary(op, ref operand) => { - self.expr(operand).and_then(|o| { - match op { - UnNot => constant_not(o), - UnNeg => constant_negate(o), - UnDeref => Some(o), - } - }) - } - ExprBinary(op, ref left, ref right) => self.binop(op, left, right), - // TODO: add other expressions - _ => None, - } - } - - /// create `Some(Vec![..])` of all constants, unless there is any - /// non-constant part - fn multi<E: Deref<Target = Expr> + Sized>(&mut self, vec: &[E]) -> Option<Vec<Constant>> { - vec.iter() - .map(|elem| self.expr(elem)) - .collect::<Option<_>>() - } - - /// lookup a possibly constant expression from a ExprPath - fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { - if let Some(lcx) = self.lcx { - let mut maybe_id = None; - if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) { - maybe_id = Some(id); - } - // separate if lets to avoid double borrowing the def_map - if let Some(id) = maybe_id { - if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) { - let ret = self.expr(const_expr); - if ret.is_some() { - self.needed_resolution = true; - } - return ret; - } - } - } - None - } - - /// A block can only yield a constant if it only has one constant expression - fn block(&mut self, block: &Block) -> Option<Constant> { - if block.stmts.is_empty() { - block.expr.as_ref().and_then(|ref b| self.expr(b)) - } else { - None - } - } - - fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) -> Option<Constant> { - if let Some(Constant::Bool(b)) = self.expr(cond) { - if b { - self.block(then) - } else { - otherwise.as_ref().and_then(|expr| self.expr(expr)) - } - } else { - None - } - } - - fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { - let l = if let Some(l) = self.expr(left) { - l - } else { - return None; - }; - let r = self.expr(right); - match (op.node, l, r) { - (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), - (BiSub, Constant::Int(l), Some(Constant::Int(r))) => (l - r).ok().map(Constant::Int), - (BiMul, Constant::Int(l), Some(Constant::Int(r))) => (l * r).ok().map(Constant::Int), - (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int), - (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), - (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), - (BiAnd, Constant::Bool(true), Some(r)) => Some(r), - (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BiOr, Constant::Bool(false), Some(r)) => Some(r), - (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), - (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), - (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), - (BiBitAnd, Constant::Int(l), Some(Constant::Int(r))) => (l & r).ok().map(Constant::Int), - (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), - (BiBitOr, Constant::Int(l), Some(Constant::Int(r))) => (l | r).ok().map(Constant::Int), - (BiShl, Constant::Int(l), Some(Constant::Int(r))) => (l << r).ok().map(Constant::Int), - (BiShr, Constant::Int(l), Some(Constant::Int(r))) => (l >> r).ok().map(Constant::Int), - (BiEq, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l == r)), - (BiNe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l != r)), - (BiLt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l < r)), - (BiLe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l <= r)), - (BiGe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l >= r)), - (BiGt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l > r)), - _ => None, - } - } - - - fn binop_apply<F>(&mut self, left: &Expr, right: &Expr, op: F) -> Option<Constant> - where F: Fn(Constant, Constant) -> Option<Constant> - { - if let (Some(lc), Some(rc)) = (self.expr(left), self.expr(right)) { - op(lc, rc) - } else { - None - } - } -} diff --git a/src/copies.rs b/src/copies.rs deleted file mode 100644 index 4344ba461dd..00000000000 --- a/src/copies.rs +++ /dev/null @@ -1,271 +0,0 @@ -use rustc::lint::*; -use rustc::ty; -use rustc::hir::*; -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use syntax::parse::token::InternedString; -use syntax::util::small_vector::SmallVector; -use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, span_note_and_lint}; - -/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is -/// `Warn` by default. -/// -/// **Why is this bad?** This is probably a copy & paste error. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** `if a == b { .. } else if a == b { .. }` -declare_lint! { - pub IFS_SAME_COND, - Warn, - "consecutive `ifs` with the same condition" -} - -/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the -/// *else* part. This lint is `Warn` by default. -/// -/// **Why is this bad?** This is probably a copy & paste error. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** `if .. { 42 } else { 42 }` -declare_lint! { - pub IF_SAME_THEN_ELSE, - Warn, - "if with the same *then* and *else* blocks" -} - -/// **What it does:** This lint checks for `match` with identical arm bodies. -/// -/// **Why is this bad?** This is probably a copy & paste error. If arm bodies are the same on -/// purpose, you can factor them -/// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// ```rust,ignore -/// match foo { -/// Bar => bar(), -/// Quz => quz(), -/// Baz => bar(), // <= oops -/// } -/// ``` -declare_lint! { - pub MATCH_SAME_ARMS, - Warn, - "`match` with identical arm bodies" -} - -#[derive(Copy, Clone, Debug)] -pub struct CopyAndPaste; - -impl LintPass for CopyAndPaste { - fn get_lints(&self) -> LintArray { - lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS] - } -} - -impl LateLintPass for CopyAndPaste { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if !in_macro(cx, expr.span) { - // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { - if else_expr.id == expr.id { - return; - } - } - - let (conds, blocks) = if_sequence(expr); - lint_same_then_else(cx, blocks.as_slice()); - lint_same_cond(cx, conds.as_slice()); - lint_match_arms(cx, expr); - } - } -} - -/// Implementation of `IF_SAME_THEN_ELSE`. -fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - - let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; - - if let Some((i, j)) = search_same(blocks, hash, eq) { - span_note_and_lint(cx, - IF_SAME_THEN_ELSE, - j.span, - "this `if` has identical blocks", - i.span, - "same as this"); - } -} - -/// Implementation of `IFS_SAME_COND`. -fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { - let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_expr(expr); - h.finish() - }; - - let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; - - if let Some((i, j)) = search_same(conds, hash, eq) { - span_note_and_lint(cx, - IFS_SAME_COND, - j.span, - "this `if` has the same condition as a previous if", - i.span, - "same as this"); - } -} - -/// Implementation if `MATCH_SAME_ARMS`. -fn lint_match_arms(cx: &LateContext, expr: &Expr) { - let hash = |arm: &Arm| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_expr(&arm.body); - h.finish() - }; - - let eq = |lhs: &Arm, rhs: &Arm| -> bool { - // Arms with a guard are ignored, those can’t always be merged together - lhs.guard.is_none() && rhs.guard.is_none() && - SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && - // all patterns should have the same bindings - bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) - }; - - if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { - if let Some((i, j)) = search_same(arms, hash, eq) { - span_note_and_lint(cx, - MATCH_SAME_ARMS, - j.body.span, - "this `match` has identical arm bodies", - i.body.span, - "same as this"); - } - } -} - -/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`. -/// Eg. would return `([a, b], [c, d, e])` for the expression -/// `if a { c } else if b { d } else { e }`. -fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { - let mut conds = SmallVector::zero(); - let mut blocks = SmallVector::zero(); - - while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node { - conds.push(&**cond); - blocks.push(&**then_block); - - if let Some(ref else_expr) = *else_expr { - expr = else_expr; - } else { - break; - } - } - - // final `else {..}` - if !blocks.is_empty() { - if let ExprBlock(ref block) = expr.node { - blocks.push(&**block); - } - } - - (conds, blocks) -} - -/// Return the list of bindings in a pattern. -fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { - fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { - match pat.node { - PatKind::Box(ref pat) | - PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), - PatKind::TupleStruct(_, Some(ref pats)) => { - for pat in pats { - bindings_impl(cx, pat, map); - } - } - PatKind::Ident(_, ref ident, ref as_pat) => { - if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { - v.insert(cx.tcx.pat_ty(pat)); - } - if let Some(ref as_pat) = *as_pat { - bindings_impl(cx, as_pat, map); - } - } - PatKind::Struct(_, ref fields, _) => { - for pat in fields { - bindings_impl(cx, &pat.node.pat, map); - } - } - PatKind::Tup(ref fields) => { - for pat in fields { - bindings_impl(cx, pat, map); - } - } - PatKind::Vec(ref lhs, ref mid, ref rhs) => { - for pat in lhs { - bindings_impl(cx, pat, map); - } - if let Some(ref mid) = *mid { - bindings_impl(cx, mid, map); - } - for pat in rhs { - bindings_impl(cx, pat, map); - } - } - PatKind::TupleStruct(..) | - PatKind::Lit(..) | - PatKind::QPath(..) | - PatKind::Range(..) | - PatKind::Wild | - PatKind::Path(..) => (), - } - } - - let mut result = HashMap::new(); - bindings_impl(cx, pat, &mut result); - result -} - -fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> - where Hash: Fn(&T) -> u64, - Eq: Fn(&T, &T) -> bool -{ - // common cases - if exprs.len() < 2 { - return None; - } else if exprs.len() == 2 { - return if eq(&exprs[0], &exprs[1]) { - Some((&exprs[0], &exprs[1])) - } else { - None - }; - } - - let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len()); - - for expr in exprs { - match map.entry(hash(expr)) { - Entry::Occupied(o) => { - for o in o.get() { - if eq(o, expr) { - return Some((o, expr)); - } - } - } - Entry::Vacant(v) => { - v.insert(vec![expr]); - } - } - } - - None -} diff --git a/src/cyclomatic_complexity.rs b/src/cyclomatic_complexity.rs deleted file mode 100644 index 8ae0d2c97c5..00000000000 --- a/src/cyclomatic_complexity.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! calculate cyclomatic complexity and warn about overly complex functions - -use rustc::cfg::CFG; -use rustc::lint::*; -use rustc::ty; -use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr}; -use syntax::ast::Attribute; -use syntax::attr; -use syntax::codemap::Span; - -use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; - -/// **What it does:** This lint checks for methods with high cyclomatic complexity -/// -/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better. -/// -/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity -/// -/// **Example:** No. You'll see it when you get the warning. -declare_lint! { - pub CYCLOMATIC_COMPLEXITY, Warn, - "finds functions that should be split up into multiple functions" -} - -pub struct CyclomaticComplexity { - limit: LimitStack, -} - -impl CyclomaticComplexity { - pub fn new(limit: u64) -> Self { - CyclomaticComplexity { limit: LimitStack::new(limit) } - } -} - -impl LintPass for CyclomaticComplexity { - fn get_lints(&self) -> LintArray { - lint_array!(CYCLOMATIC_COMPLEXITY) - } -} - -impl CyclomaticComplexity { - fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) { - if in_macro(cx, span) { - return; - } - - let cfg = CFG::new(cx.tcx, block); - let n = cfg.graph.len_nodes() as u64; - let e = cfg.graph.len_edges() as u64; - if e + 2 < n { - // the function has unreachable code, other lints should catch this - return; - } - let cc = e + 2 - n; - let mut helper = CCHelper { - match_arms: 0, - divergence: 0, - short_circuits: 0, - returns: 0, - tcx: &cx.tcx, - }; - helper.visit_block(block); - let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; - let ret_ty = cx.tcx.node_id_to_type(block.id); - let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { - returns - } else { - returns / 2 - }; - - if cc + divergence < match_arms + short_circuits { - report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span); - } else { - let mut rust_cc = cc + divergence - match_arms - short_circuits; - // prevent degenerate cases where unreachable code contains `return` statements - if rust_cc >= ret_adjust { - rust_cc -= ret_adjust; - } - if rust_cc > self.limit.limit() { - span_help_and_lint(cx, - CYCLOMATIC_COMPLEXITY, - span, - &format!("the function has a cyclomatic complexity of {}", rust_cc), - "you could split it up into multiple smaller functions"); - } - } - } -} - -impl LateLintPass for CyclomaticComplexity { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemFn(_, _, _, _, _, ref block) = item.node { - if !attr::contains_name(&item.attrs, "test") { - self.check(cx, block, item.span); - } - } - } - - fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let ImplItemKind::Method(_, ref block) = item.node { - self.check(cx, block, item.span); - } - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - if let MethodTraitItem(_, Some(ref block)) = item.node { - self.check(cx, block, item.span); - } - } - - fn enter_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { - self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); - } - fn exit_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) { - self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); - } -} - -struct CCHelper<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - match_arms: u64, - divergence: u64, - returns: u64, - short_circuits: u64, // && and || - tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>, -} - -impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> { - fn visit_expr(&mut self, e: &'a Expr) { - match e.node { - ExprMatch(_, ref arms, _) => { - walk_expr(self, e); - let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); - if arms_n > 1 { - self.match_arms += arms_n - 2; - } - } - ExprCall(ref callee, _) => { - walk_expr(self, e); - let ty = self.tcx.node_id_to_type(callee.id); - match ty.sty { - ty::TyFnDef(_, _, ty) | - ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { - self.divergence += 1; - } - _ => (), - } - } - ExprClosure(..) => (), - ExprBinary(op, _, _) => { - walk_expr(self, e); - match op.node { - BiAnd | BiOr => self.short_circuits += 1, - _ => (), - } - } - ExprRet(_) => self.returns += 1, - _ => walk_expr(self, e), - } - } -} - -#[cfg(feature="debugging")] -fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { - span_bug!(span, - "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}, returns = {}. Please file a bug report.", - cc, - narms, - div, - shorts, - returns); -} -#[cfg(not(feature="debugging"))] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { - if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { - cx.sess().span_note_without_error(span, - &format!("Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ - = {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.", - cc, - narms, - div, - shorts, - returns)); - } -} diff --git a/src/deprecated_lints.rs b/src/deprecated_lints.rs deleted file mode 100644 index abdb6297b9e..00000000000 --- a/src/deprecated_lints.rs +++ /dev/null @@ -1,44 +0,0 @@ -macro_rules! declare_deprecated_lint { - (pub $name: ident, $_reason: expr) => { - declare_lint!(pub $name, Allow, "deprecated lint") - } -} - -/// **What it does:** Nothing. This lint has been deprecated. -/// -/// **Deprecation reason:** This used to check for `Vec::as_slice`, which was unstable with good -/// stable alternatives. `Vec::as_slice` has now been stabilized. -declare_deprecated_lint! { - pub UNSTABLE_AS_SLICE, - "`Vec::as_slice` has been stabilized in 1.7" -} - - -/// **What it does:** Nothing. This lint has been deprecated. -/// -/// **Deprecation reason:** This used to check for `Vec::as_mut_slice`, which was unstable with good -/// stable alternatives. `Vec::as_mut_slice` has now been stabilized. -declare_deprecated_lint! { - pub UNSTABLE_AS_MUT_SLICE, - "`Vec::as_mut_slice` has been stabilized in 1.7" -} - -/// **What it does:** Nothing. This lint has been deprecated. -/// -/// **Deprecation reason:** This used to check for `.to_string()` method calls on values -/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be -/// specialized to be as efficient as `to_owned`. -declare_deprecated_lint! { - pub STR_TO_STRING, - "using `str::to_string` is common even today and specialization will likely happen soon" -} - -/// **What it does:** Nothing. This lint has been deprecated. -/// -/// **Deprecation reason:** This used to check for `.to_string()` method calls on values -/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be -/// specialized to be as efficient as `clone`. -declare_deprecated_lint! { - pub STRING_TO_STRING, - "using `string::to_string` is common even today and specialization will likely happen soon" -} diff --git a/src/derive.rs b/src/derive.rs deleted file mode 100644 index f08522953aa..00000000000 --- a/src/derive.rs +++ /dev/null @@ -1,180 +0,0 @@ -use rustc::lint::*; -use rustc::ty::subst::Subst; -use rustc::ty::TypeVariants; -use rustc::ty; -use rustc::hir::*; -use syntax::ast::{Attribute, MetaItemKind}; -use syntax::codemap::Span; -use utils::paths; -use utils::{match_path, span_lint_and_then}; - -/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq` -/// explicitly. -/// -/// **Why is this bad?** The implementation of these traits must agree (for example for use with -/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation with -/// an explicitly defined `PartialEq`. In particular, the following must hold for any type: -/// -/// ```rust -/// k1 == k2 ⇒ hash(k1) == hash(k2) -/// ``` -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// #[derive(Hash)] -/// struct Foo; -/// -/// impl PartialEq for Foo { -/// .. -/// } -/// ``` -declare_lint! { - pub DERIVE_HASH_XOR_EQ, - Warn, - "deriving `Hash` but implementing `PartialEq` explicitly" -} - -/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types. -/// -/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour -/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone` -/// implementation that does nothing more than copy the object, which is what -/// `#[derive(Copy, Clone)]` gets you. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// #[derive(Copy)] -/// struct Foo; -/// -/// impl Clone for Foo { -/// .. -/// } -/// ``` -declare_lint! { - pub EXPL_IMPL_CLONE_ON_COPY, - Warn, - "implementing `Clone` explicitly on `Copy` types" -} - -pub struct Derive; - -impl LintPass for Derive { - fn get_lints(&self) -> LintArray { - lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ) - } -} - -impl LateLintPass for Derive { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if_let_chain! {[ - let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node - ], { - let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; - let is_automatically_derived = item.attrs.iter().any(is_automatically_derived); - - check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); - - if !is_automatically_derived { - check_copy_clone(cx, item, trait_ref, ty); - } - }} - } -} - -/// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { - if_let_chain! {[ - match_path(&trait_ref.path, &paths::HASH), - let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() - ], { - let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id); - - // Look for the PartialEq implementations for `ty` - peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| { - let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived); - - if peq_is_automatically_derived == hash_is_automatically_derived { - return; - } - - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - - // Only care about `impl PartialEq<Foo> for Foo` - if trait_ref.input_types()[0] == ty { - let mess = if peq_is_automatically_derived { - "you are implementing `Hash` explicitly but have derived `PartialEq`" - } else { - "you are deriving `Hash` but have implemented `PartialEq` explicitly" - }; - - span_lint_and_then( - cx, DERIVE_HASH_XOR_EQ, span, - mess, - |db| { - if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) { - db.span_note( - cx.tcx.map.span(node_id), - "`PartialEq` implemented here" - ); - } - }); - } - }); - }} -} - -/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) { - if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { - let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs); - - if subst_ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, item.span) { - return; // ty is not Copy - } - - // Some types are not Clone by default but could be cloned `by hand` if necessary - match ty.sty { - TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => { - for variant in &def.variants { - for field in &variant.fields { - match field.ty(cx.tcx, substs).sty { - TypeVariants::TyArray(_, size) if size > 32 => { - return; - } - TypeVariants::TyFnPtr(..) => { - return; - } - TypeVariants::TyTuple(ref tys) if tys.len() > 12 => { - return; - } - _ => (), - } - } - } - } - _ => (), - } - - span_lint_and_then(cx, - EXPL_IMPL_CLONE_ON_COPY, - item.span, - "you are implementing `Clone` explicitly on a `Copy` type", - |db| { - db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); - }); - } -} - -/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have. -fn is_automatically_derived(attr: &Attribute) -> bool { - if let MetaItemKind::Word(ref word) = attr.node.value.node { - word == &"automatically_derived" - } else { - false - } -} diff --git a/src/doc.rs b/src/doc.rs deleted file mode 100644 index cf32c1731fa..00000000000 --- a/src/doc.rs +++ /dev/null @@ -1,235 +0,0 @@ -use rustc::lint::*; -use syntax::ast; -use syntax::codemap::{Span, BytePos}; -use utils::span_lint; - -/// **What it does:** This lint checks for the presence of `_`, `::` or camel-case words outside -/// ticks in documentation. -/// -/// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and camel-case probably -/// indicates some code which should be included between ticks. `_` can also be used for empasis in -/// markdown, this lint tries to consider that. -/// -/// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks for is limited. -/// -/// **Examples:** -/// ```rust -/// /// Do something with the foo_bar parameter. See also that::other::module::foo. -/// // ^ `foo_bar` and `that::other::module::foo` should be ticked. -/// fn doit(foo_bar) { .. } -/// ``` -declare_lint! { - pub DOC_MARKDOWN, Warn, - "checks for the presence of `_`, `::` or camel-case outside ticks in documentation" -} - -#[derive(Clone)] -pub struct Doc { - valid_idents: Vec<String>, -} - -impl Doc { - pub fn new(valid_idents: Vec<String>) -> Self { - Doc { valid_idents: valid_idents } - } -} - -impl LintPass for Doc { - fn get_lints(&self) -> LintArray { - lint_array![DOC_MARKDOWN] - } -} - -impl EarlyLintPass for Doc { - fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { - check_attrs(cx, &self.valid_idents, &krate.attrs); - } - - fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { - check_attrs(cx, &self.valid_idents, &item.attrs); - } -} - -pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { - let mut in_multiline = false; - for attr in attrs { - if attr.node.is_sugared_doc { - if let ast::MetaItemKind::NameValue(_, ref doc) = attr.node.value.node { - if let ast::LitKind::Str(ref doc, _) = doc.node { - // doc comments start with `///` or `//!` - let real_doc = &doc[3..]; - let mut span = attr.span; - span.lo = span.lo + BytePos(3); - - // check for multiline code blocks - if real_doc.trim_left().starts_with("```") { - in_multiline = !in_multiline; - } - if !in_multiline { - check_doc(cx, valid_idents, real_doc, span); - } - } - } - } - } -} - -macro_rules! jump_to { - // Get the next character’s first byte UTF-8 friendlyly. - (@next_char, $chars: expr, $len: expr) => {{ - if let Some(&(pos, _)) = $chars.peek() { - pos - } else { - $len - } - }}; - - // Jump to the next `$c`. If no such character is found, give up. - ($chars: expr, $c: expr, $len: expr) => {{ - if $chars.find(|&(_, c)| c == $c).is_some() { - jump_to!(@next_char, $chars, $len) - } - else { - return; - } - }}; -} - -#[allow(while_let_loop)] // #362 -pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) { - // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. - // There really is no markdown specification that would disambiguate this properly. This is - // what GitHub and Rustdoc do: - // - // foo_bar test_quz → foo_bar test_quz - // foo_bar_baz → foo_bar_baz (note that the “official” spec says this should be emphasized) - // _foo bar_ test_quz_ → <em>foo bar</em> test_quz_ - // \_foo bar\_ → _foo bar_ - // (_baz_) → (<em>baz</em>) - // foo _ bar _ baz → foo _ bar _ baz - - /// Character that can appear in a word - fn is_word_char(c: char) -> bool { - match c { - t if t.is_alphanumeric() => true, - ':' | '_' => true, - _ => false, - } - } - - #[allow(cast_possible_truncation)] - fn word_span(mut span: Span, begin: usize, end: usize) -> Span { - debug_assert_eq!(end as u32 as usize, end); - debug_assert_eq!(begin as u32 as usize, begin); - span.hi = span.lo + BytePos(end as u32); - span.lo = span.lo + BytePos(begin as u32); - span - } - - let mut new_line = true; - let len = doc.len(); - let mut chars = doc.char_indices().peekable(); - let mut current_word_begin = 0; - loop { - match chars.next() { - Some((_, c)) => { - match c { - '#' if new_line => { // don’t warn on titles - current_word_begin = jump_to!(chars, '\n', len); - } - '`' => { - current_word_begin = jump_to!(chars, '`', len); - } - '[' => { - let end = jump_to!(chars, ']', len); - let link_text = &doc[current_word_begin + 1..end]; - let word_span = word_span(span, current_word_begin + 1, end + 1); - - match chars.peek() { - Some(&(_, c)) => { - // Trying to parse a link. Let’s ignore the link. - - // FIXME: how does markdown handles such link? - // https://en.wikipedia.org/w/index.php?title=) - match c { - '(' => { // inline link - current_word_begin = jump_to!(chars, ')', len); - check_doc(cx, valid_idents, link_text, word_span); - } - '[' => { // reference link - current_word_begin = jump_to!(chars, ']', len); - check_doc(cx, valid_idents, link_text, word_span); - } - ':' => { // reference link - current_word_begin = jump_to!(chars, '\n', len); - } - _ => { // automatic reference link - current_word_begin = jump_to!(@next_char, chars, len); - check_doc(cx, valid_idents, link_text, word_span); - } - } - } - None => return, - } - } - // anything that’s neither alphanumeric nor '_' is not part of an ident anyway - c if !c.is_alphanumeric() && c != '_' => { - current_word_begin = jump_to!(@next_char, chars, len); - } - _ => { - let end = match chars.find(|&(_, c)| !is_word_char(c)) { - Some((end, _)) => end, - None => len, - }; - let word_span = word_span(span, current_word_begin, end); - check_word(cx, valid_idents, &doc[current_word_begin..end], word_span); - current_word_begin = jump_to!(@next_char, chars, len); - } - } - - new_line = c == '\n' || (new_line && c.is_whitespace()); - } - None => break, - } - } -} - -fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span) { - /// Checks if a string a camel-case, ie. contains at least two uppercase letter (`Clippy` is - /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok). - fn is_camel_case(s: &str) -> bool { - if s.starts_with(|c: char| c.is_digit(10)) { - return false; - } - - let s = if s.ends_with('s') { - &s[..s.len() - 1] - } else { - s - }; - - s.chars().all(char::is_alphanumeric) && - s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && - s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 - } - - fn has_underscore(s: &str) -> bool { - s != "_" && !s.contains("\\_") && s.contains('_') - } - - // Trim punctuation as in `some comment (see foo::bar).` - // ^^ - // Or even as in `_foo bar_` which is emphasized. - let word = word.trim_matches(|c: char| !c.is_alphanumeric()); - - if valid_idents.iter().any(|i| i == word) { - return; - } - - if has_underscore(word) || word.contains("::") || is_camel_case(word) { - span_lint(cx, - DOC_MARKDOWN, - span, - &format!("you should put `{}` between ticks in the documentation", word)); - } -} diff --git a/src/drop_ref.rs b/src/drop_ref.rs deleted file mode 100644 index 69156f15f31..00000000000 --- a/src/drop_ref.rs +++ /dev/null @@ -1,61 +0,0 @@ -use rustc::lint::*; -use rustc::ty; -use rustc::hir::*; -use syntax::codemap::Span; -use utils::{match_def_path, paths, span_note_and_lint}; - -/// **What it does:** This lint checks for calls to `std::mem::drop` with a reference instead of an owned value. -/// -/// **Why is this bad?** Calling `drop` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` method (from the `Drop` trait implementation) on the underlying referenced value, which is likely what was intended. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// let mut lock_guard = mutex.lock(); -/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked -/// operation_that_requires_mutex_to_be_unlocked(); -/// ``` -declare_lint! { - pub DROP_REF, Warn, - "call to `std::mem::drop` with a reference instead of an owned value, \ - which will not call the `Drop::drop` method on the underlying value" -} - -#[allow(missing_copy_implementations)] -pub struct DropRefPass; - -impl LintPass for DropRefPass { - fn get_lints(&self) -> LintArray { - lint_array!(DROP_REF) - } -} - -impl LateLintPass for DropRefPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprCall(ref path, ref args) = expr.node { - if let ExprPath(None, _) = path.node { - let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); - if match_def_path(cx, def_id, &paths::DROP) { - if args.len() != 1 { - return; - } - check_drop_arg(cx, expr.span, &*args[0]); - } - } - } - } -} - -fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) { - let arg_ty = cx.tcx.expr_ty(arg); - if let ty::TyRef(..) = arg_ty.sty { - span_note_and_lint(cx, - DROP_REF, - call_span, - "call to `std::mem::drop` with a reference argument. \ - Dropping a reference does nothing", - arg.span, - &format!("argument has type {}", arg_ty.sty)); - } -} diff --git a/src/entry.rs b/src/entry.rs deleted file mode 100644 index d63d8c67c5d..00000000000 --- a/src/entry.rs +++ /dev/null @@ -1,148 +0,0 @@ -use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, walk_block}; -use rustc::lint::*; -use syntax::codemap::Span; -use utils::SpanlessEq; -use utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; - -/// **What it does:** This lint checks for uses of `contains_key` + `insert` on `HashMap` or -/// `BTreeMap`. -/// -/// **Why is this bad?** Using `entry` is more efficient. -/// -/// **Known problems:** Some false negatives, eg.: -/// ``` -/// let k = &key; -/// if !m.contains_key(k) { m.insert(k.clone(), v); } -/// ``` -/// -/// **Example:** -/// ```rust -/// if !m.contains_key(&k) { m.insert(k, v) } -/// ``` -/// can be rewritten as: -/// ```rust -/// m.entry(k).or_insert(v); -/// ``` -declare_lint! { - pub MAP_ENTRY, - Warn, - "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" -} - -#[derive(Copy,Clone)] -pub struct HashMapLint; - -impl LintPass for HashMapLint { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_ENTRY) - } -} - -impl LateLintPass for HashMapLint { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprIf(ref check, ref then_block, ref else_block) = expr.node { - if let ExprUnary(UnOp::UnNot, ref check) = check.node { - if let Some((ty, map, key)) = check_cond(cx, check) { - // in case of `if !m.contains_key(&k) { m.insert(k, v); }` - // we can give a better error message - let sole_expr = else_block.is_none() && - ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); - - let mut visitor = InsertVisitor { - cx: cx, - span: expr.span, - ty: ty, - map: map, - key: key, - sole_expr: sole_expr, - }; - - walk_block(&mut visitor, then_block); - } - } else if let Some(ref else_block) = *else_block { - if let Some((ty, map, key)) = check_cond(cx, check) { - let mut visitor = InsertVisitor { - cx: cx, - span: expr.span, - ty: ty, - map: map, - key: key, - sole_expr: false, - }; - - walk_expr(&mut visitor, else_block); - } - } - } - } -} - -fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> Option<(&'static str, &'b Expr, &'b Expr)> { - if_let_chain! {[ - let ExprMethodCall(ref name, _, ref params) = check.node, - params.len() >= 2, - name.node.as_str() == "contains_key", - let ExprAddrOf(_, ref key) = params[1].node - ], { - let map = ¶ms[0]; - let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map)); - - return if match_type(cx, obj_ty, &paths::BTREEMAP) { - Some(("BTreeMap", map, key)) - } - else if match_type(cx, obj_ty, &paths::HASHMAP) { - Some(("HashMap", map, key)) - } - else { - None - }; - }} - - None -} - -struct InsertVisitor<'a, 'tcx: 'a, 'b> { - cx: &'a LateContext<'a, 'tcx>, - span: Span, - ty: &'static str, - map: &'b Expr, - key: &'b Expr, - sole_expr: bool, -} - -impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> { - fn visit_expr(&mut self, expr: &'v Expr) { - if_let_chain! {[ - let ExprMethodCall(ref name, _, ref params) = expr.node, - params.len() == 3, - name.node.as_str() == "insert", - get_item_name(self.cx, self.map) == get_item_name(self.cx, &*params[0]), - SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) - ], { - - span_lint_and_then(self.cx, MAP_ENTRY, self.span, - &format!("usage of `contains_key` followed by `insert` on `{}`", self.ty), |db| { - if self.sole_expr { - let help = format!("{}.entry({}).or_insert({})", - snippet(self.cx, self.map.span, "map"), - snippet(self.cx, params[1].span, ".."), - snippet(self.cx, params[2].span, "..")); - - db.span_suggestion(self.span, "Consider using", help); - } - else { - let help = format!("Consider using `{}.entry({})`", - snippet(self.cx, self.map.span, "map"), - snippet(self.cx, params[1].span, "..")); - - db.span_note(self.span, &help); - } - }); - }} - - if !self.sole_expr { - walk_expr(self, expr); - } - } -} diff --git a/src/enum_clike.rs b/src/enum_clike.rs deleted file mode 100644 index 39c31864f39..00000000000 --- a/src/enum_clike.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` - -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc_const_math::*; -use rustc::hir::*; -use utils::span_lint; - -/// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. -/// -/// **Why is this bad?** This will truncate the variant value on 32bit architectures, but works fine on 64 bit. -/// -/// **Known problems:** None -/// -/// **Example:** `#[repr(usize)] enum NonPortable { X = 0x1_0000_0000, Y = 0 }` -declare_lint! { - pub ENUM_CLIKE_UNPORTABLE_VARIANT, Warn, - "finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" -} - -pub struct EnumClikeUnportableVariant; - -impl LintPass for EnumClikeUnportableVariant { - fn get_lints(&self) -> LintArray { - lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) - } -} - -impl LateLintPass for EnumClikeUnportableVariant { - #[allow(cast_possible_truncation, cast_sign_loss)] - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemEnum(ref def, _) = item.node { - for var in &def.variants { - let variant = &var.node; - if let Some(ref disr) = variant.disr_expr { - use rustc_const_eval::*; - let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) { - Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, - Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, - _ => false, - }; - if bad { - span_lint(cx, - ENUM_CLIKE_UNPORTABLE_VARIANT, - var.span, - "Clike enum variant discriminant is not portable to 32-bit targets"); - } - } - } - } - } -} diff --git a/src/enum_glob_use.rs b/src/enum_glob_use.rs deleted file mode 100644 index 37a89069d19..00000000000 --- a/src/enum_glob_use.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! lint on `use`ing all variants of an enum - -use rustc::hir::*; -use rustc::hir::def::Def; -use rustc::hir::map::Node::NodeItem; -use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext}; -use rustc::middle::cstore::DefLike; -use syntax::ast::NodeId; -use syntax::codemap::Span; -use utils::span_lint; - -/// **What it does:** Warns when `use`ing all variants of an enum -/// -/// **Why is this bad?** It is usually better style to use the prefixed name of an enum variant, rather than importing variants -/// -/// **Known problems:** Old-style enums that prefix the variants are still around -/// -/// **Example:** `use std::cmp::Ordering::*;` -declare_lint! { pub ENUM_GLOB_USE, Allow, - "finds use items that import all variants of an enum" } - -pub struct EnumGlobUse; - -impl LintPass for EnumGlobUse { - fn get_lints(&self) -> LintArray { - lint_array!(ENUM_GLOB_USE) - } -} - -impl LateLintPass for EnumGlobUse { - fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) { - // only check top level `use` statements - for item in &m.item_ids { - self.lint_item(cx, cx.krate.item(item.id)); - } - } -} - -impl EnumGlobUse { - fn lint_item(&self, cx: &LateContext, item: &Item) { - if item.vis == Visibility::Public { - return; // re-exports are fine - } - if let ItemUse(ref item_use) = item.node { - if let ViewPath_::ViewPathGlob(_) = item_use.node { - if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) { - if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { - if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { - if let ItemEnum(..) = it.node { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); - } - } - } else { - let child = cx.sess().cstore.item_children(def.def_id()); - if let Some(child) = child.first() { - if let DefLike::DlDef(Def::Variant(..)) = child.def { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); - } - } - } - } - } - } - } -} diff --git a/src/enum_variants.rs b/src/enum_variants.rs deleted file mode 100644 index 67a8495e155..00000000000 --- a/src/enum_variants.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! lint on enum variants that are prefixed or suffixed by the same characters - -use rustc::lint::*; -use syntax::ast::*; -use syntax::parse::token::InternedString; -use utils::span_help_and_lint; -use utils::{camel_case_from, camel_case_until}; - -/// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters -/// -/// **Why is this bad?** Enum variant names should specify their variant, not the enum, too. -/// -/// **Known problems:** None -/// -/// **Example:** enum Cake { BlackForestCake, HummingbirdCake } -declare_lint! { - pub ENUM_VARIANT_NAMES, Warn, - "finds enums where all variants share a prefix/postfix" -} - -pub struct EnumVariantNames; - -impl LintPass for EnumVariantNames { - fn get_lints(&self) -> LintArray { - lint_array!(ENUM_VARIANT_NAMES) - } -} - -fn var2str(var: &Variant) -> InternedString { - var.node.name.name.as_str() -} - -// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 -// fn partial_match(pre: &str, name: &str) -> usize { -// // skip(1) to ensure that the prefix never takes the whole variant name -// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } -// -// fn partial_rmatch(post: &str, name: &str) -> usize { -// // skip(1) to ensure that the postfix never takes the whole variant name -// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } - -fn partial_match(pre: &str, name: &str) -> usize { - let mut name_iter = name.chars(); - let _ = name_iter.next_back(); // make sure the name is never fully matched - pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() -} - -fn partial_rmatch(post: &str, name: &str) -> usize { - let mut name_iter = name.chars(); - let _ = name_iter.next(); // make sure the name is never fully matched - post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() -} - -impl EarlyLintPass for EnumVariantNames { - // FIXME: #600 - #[allow(while_let_on_iterator)] - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemKind::Enum(ref def, _) = item.node { - if def.variants.len() < 2 { - return; - } - let first = var2str(&def.variants[0]); - let mut pre = &first[..camel_case_until(&*first)]; - let mut post = &first[camel_case_from(&*first)..]; - for var in &def.variants { - let name = var2str(var); - - let pre_match = partial_match(pre, &name); - pre = &pre[..pre_match]; - let pre_camel = camel_case_until(pre); - pre = &pre[..pre_camel]; - while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { - if next.is_lowercase() { - let last = pre.len() - last.len_utf8(); - let last_camel = camel_case_until(&pre[..last]); - pre = &pre[..last_camel]; - } else { - break; - } - } - - let post_match = partial_rmatch(post, &name); - let post_end = post.len() - post_match; - post = &post[post_end..]; - let post_camel = camel_case_from(post); - post = &post[post_camel..]; - } - let (what, value) = match (pre.is_empty(), post.is_empty()) { - (true, true) => return, - (false, _) => ("pre", pre), - (true, false) => ("post", post), - }; - span_help_and_lint(cx, - ENUM_VARIANT_NAMES, - item.span, - &format!("All variants have the same {}fix: `{}`", what, value), - &format!("remove the {}fixes and use full paths to \ - the variants instead of glob imports", - what)); - } - } -} diff --git a/src/eq_op.rs b/src/eq_op.rs deleted file mode 100644 index fb06639853c..00000000000 --- a/src/eq_op.rs +++ /dev/null @@ -1,60 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use utils::{SpanlessEq, span_lint}; - -/// **What it does:** This lint checks for equal operands to comparison, logical and bitwise, -/// difference and division binary operators (`==`, `>`, etc., `&&`, `||`, `&`, `|`, `^`, `-` and -/// `/`). -/// -/// **Why is this bad?** This is usually just a typo or a copy and paste error. -/// -/// **Known problems:** False negatives: We had some false positives regarding calls (notably [racer](https://github.com/phildawes/racer) had one instance of `x.pop() && x.pop()`), so we removed matching any function or method calls. We may introduce a whitelist of known pure functions in the future. -/// -/// **Example:** `x + 1 == x + 1` -declare_lint! { - pub EQ_OP, - Warn, - "equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" -} - -#[derive(Copy,Clone)] -pub struct EqOp; - -impl LintPass for EqOp { - fn get_lints(&self) -> LintArray { - lint_array!(EQ_OP) - } -} - -impl LateLintPass for EqOp { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { - span_lint(cx, - EQ_OP, - e.span, - &format!("equal expressions as operands to `{}`", op.node.as_str())); - } - } - } -} - - -fn is_valid_operator(op: &BinOp) -> bool { - match op.node { - BiSub | - BiDiv | - BiEq | - BiLt | - BiLe | - BiGt | - BiGe | - BiNe | - BiAnd | - BiOr | - BiBitXor | - BiBitAnd | - BiBitOr => true, - _ => false, - } -} diff --git a/src/escape.rs b/src/escape.rs deleted file mode 100644 index b5172269a1e..00000000000 --- a/src/escape.rs +++ /dev/null @@ -1,172 +0,0 @@ -use rustc::hir::*; -use rustc::hir::intravisit as visit; -use rustc::hir::map::Node::{NodeExpr, NodeStmt}; -use rustc::lint::*; -use rustc::middle::expr_use_visitor::*; -use rustc::middle::mem_categorization::{cmt, Categorization}; -use rustc::ty::adjustment::AutoAdjustment; -use rustc::ty; -use rustc::util::nodemap::NodeSet; -use syntax::ast::NodeId; -use syntax::codemap::Span; -use utils::span_lint; - -pub struct EscapePass; - -/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. -/// -/// **Why is this bad?** This is an unnecessary allocation, and bad for performance. It is only necessary to allocate if you wish to move the box into something. -/// -/// **Known problems:** None -/// -/// **Example:** -/// -/// ```rust -/// fn main() { -/// let x = Box::new(1); -/// foo(*x); -/// println!("{}", *x); -/// } -/// ``` -declare_lint! { - pub BOXED_LOCAL, Warn, "using `Box<T>` where unnecessary" -} - -fn is_non_trait_box(ty: ty::Ty) -> bool { - match ty.sty { - ty::TyBox(ref inner) => !inner.is_trait(), - _ => false, - } -} - -struct EscapeDelegate<'a, 'tcx: 'a> { - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, - set: NodeSet, -} - -impl LintPass for EscapePass { - fn get_lints(&self) -> LintArray { - lint_array!(BOXED_LOCAL) - } -} - -impl LateLintPass for EscapePass { - fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { - let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); - - let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); - let mut v = EscapeDelegate { - tcx: cx.tcx, - set: NodeSet(), - }; - - { - let mut vis = ExprUseVisitor::new(&mut v, &infcx); - vis.walk_fn(decl, body); - } - - for node in v.set { - span_lint(cx, - BOXED_LOCAL, - cx.tcx.map.span(node), - "local variable doesn't need to be boxed here"); - } - } -} - -impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { - if let Categorization::Local(lid) = cmt.cat { - if self.set.contains(&lid) { - if let Move(DirectRefMove) = mode { - // moved out or in. clearly can't be localized - self.set.remove(&lid); - } - } - } - } - fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} - fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { - let map = &self.tcx.map; - if map.is_argument(consume_pat.id) { - // Skip closure arguments - if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { - return; - } - if is_non_trait_box(cmt.ty) { - self.set.insert(consume_pat.id); - } - return; - } - if let Categorization::Rvalue(..) = cmt.cat { - if let Some(NodeStmt(st)) = map.find(map.get_parent_node(cmt.id)) { - if let StmtDecl(ref decl, _) = st.node { - if let DeclLocal(ref loc) = decl.node { - if let Some(ref ex) = loc.init { - if let ExprBox(..) = ex.node { - if is_non_trait_box(cmt.ty) { - // let x = box (...) - self.set.insert(consume_pat.id); - } - // TODO Box::new - // TODO vec![] - // TODO "foo".to_owned() and friends - } - } - } - } - } - } - if let Categorization::Local(lid) = cmt.cat { - if self.set.contains(&lid) { - // let y = x where x is known - // remove x, insert y - self.set.insert(consume_pat.id); - self.set.remove(&lid); - } - } - - } - fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, - loan_cause: LoanCause) { - - if let Categorization::Local(lid) = cmt.cat { - if self.set.contains(&lid) { - if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx - .tables - .borrow() - .adjustments - .get(&borrow_id) { - if LoanCause::AutoRef == loan_cause { - // x.foo() - if adj.autoderefs == 0 { - self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) - } - } else { - span_bug!(cmt.span, "Unknown adjusted AutoRef"); - } - } else if LoanCause::AddrOf == loan_cause { - // &x - if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx - .tables - .borrow() - .adjustments - .get(&self.tcx - .map - .get_parent_node(borrow_id)) { - if adj.autoderefs <= 1 { - // foo(&x) where no extra autoreffing is happening - self.set.remove(&lid); - } - } - - } else if LoanCause::MatchDiscriminant == loan_cause { - self.set.remove(&lid); // `match x` can move - } - // do nothing for matches, etc. These can't escape - } - } - } - fn decl_without_init(&mut self, _: NodeId, _: Span) {} - fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} -} diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs deleted file mode 100644 index f73b6cfed2d..00000000000 --- a/src/eta_reduction.rs +++ /dev/null @@ -1,99 +0,0 @@ -use rustc::lint::*; -use rustc::ty; -use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then, is_adjusted}; - -#[allow(missing_copy_implementations)] -pub struct EtaPass; - - -/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. -/// -/// **Why is this bad?** Needlessly creating a closure just costs heap space and adds code for no benefit. -/// -/// **Known problems:** None -/// -/// **Example:** `xs.map(|x| foo(x))` where `foo(_)` is a plain function that takes the exact argument type of `x`. -declare_lint! { - pub REDUNDANT_CLOSURE, Warn, - "using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)" -} - -impl LintPass for EtaPass { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_CLOSURE) - } -} - -impl LateLintPass for EtaPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - match expr.node { - ExprCall(_, ref args) | - ExprMethodCall(_, _, ref args) => { - for arg in args { - check_closure(cx, arg) - } - } - _ => (), - } - } -} - -fn check_closure(cx: &LateContext, expr: &Expr) { - if let ExprClosure(_, ref decl, ref blk, _) = expr.node { - if !blk.stmts.is_empty() { - // || {foo(); bar()}; can't be reduced here - return; - } - - if let Some(ref ex) = blk.expr { - if let ExprCall(ref caller, ref args) = ex.node { - if args.len() != decl.inputs.len() { - // Not the same number of arguments, there - // is no way the closure is the same as the function - return; - } - if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { - // Are the expression or the arguments type-adjusted? Then we need the closure - return; - } - let fn_ty = cx.tcx.expr_ty(caller); - match fn_ty.sty { - // Is it an unsafe function? They don't implement the closure traits - ty::TyFnDef(_, _, fn_ty) | - ty::TyFnPtr(fn_ty) => { - if fn_ty.unsafety == Unsafety::Unsafe || - fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { - return; - } - } - _ => (), - } - for (ref a1, ref a2) in decl.inputs.iter().zip(args) { - if let PatKind::Ident(_, ident, _) = a1.pat.node { - // XXXManishearth Should I be checking the binding mode here? - if let ExprPath(None, ref p) = a2.node { - if p.segments.len() != 1 { - // If it's a proper path, it can't be a local variable - return; - } - if p.segments[0].name != ident.node { - // The two idents should be the same - return; - } - } else { - return; - } - } else { - return; - } - } - span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { - if let Some(snippet) = snippet_opt(cx, caller.span) { - db.span_suggestion(expr.span, "remove closure as shown:", snippet); - } - }); - } - } - } -} diff --git a/src/format.rs b/src/format.rs deleted file mode 100644 index 0726fcaeab7..00000000000 --- a/src/format.rs +++ /dev/null @@ -1,119 +0,0 @@ -use rustc::hir::*; -use rustc::hir::map::Node::NodeItem; -use rustc::lint::*; -use rustc::ty::TypeVariants; -use syntax::ast::LitKind; -use utils::paths; -use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty}; - -/// **What it does:** This lints about use of `format!("string literal with no argument")` and -/// `format!("{}", foo)` where `foo` is a string. -/// -/// **Why is this bad?** There is no point of doing that. `format!("too")` can be replaced by `"foo".to_owned()` if you really need a `String`. The even worse `&format!("foo")` is often -/// encountered in the wild. `format!("{}", foo)` can be replaced by `foo.clone()` if `foo: String` -/// or `foo.to_owned()` is `foo: &str`. -/// -/// **Known problems:** None. -/// -/// **Examples:** `format!("foo")` and `format!("{}", foo)` -declare_lint! { - pub USELESS_FORMAT, - Warn, - "useless use of `format!`" -} - -#[derive(Copy, Clone, Debug)] -pub struct FormatMacLint; - -impl LintPass for FormatMacLint { - fn get_lints(&self) -> LintArray { - lint_array![USELESS_FORMAT] - } -} - -impl LateLintPass for FormatMacLint { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some(span) = is_expn_of(cx, expr.span, "format") { - match expr.node { - // `format!("{}", foo)` expansion - ExprCall(ref fun, ref args) => { - if_let_chain!{[ - let ExprPath(_, ref path) = fun.node, - args.len() == 2, - match_path(path, &paths::FMT_ARGUMENTS_NEWV1), - // ensure the format string is `"{..}"` with only one argument and no text - check_static_str(cx, &args[0]), - // ensure the format argument is `{}` ie. Display with no fancy option - check_arg_is_display(cx, &args[1]) - ], { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); - }} - } - // `format!("foo")` expansion contains `match () { () => [], }` - ExprMatch(ref matchee, _, _) => { - if let ExprTup(ref tup) = matchee.node { - if tup.is_empty() { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); - } - } - } - _ => (), - } - } - } -} - -/// Checks if the expressions matches -/// ``` -/// { static __STATIC_FMTSTR: &[""] = _; __STATIC_FMTSTR } -/// ``` -fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { - if_let_chain! {[ - let ExprBlock(ref block) = expr.node, - block.stmts.len() == 1, - let StmtDecl(ref decl, _) = block.stmts[0].node, - let DeclItem(ref decl) = decl.node, - let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id), - decl.name.as_str() == "__STATIC_FMTSTR", - let ItemStatic(_, _, ref expr) = decl.node, - let ExprAddrOf(_, ref expr) = expr.node, // &[""] - let ExprVec(ref expr) = expr.node, - expr.len() == 1, - let ExprLit(ref lit) = expr[0].node, - let LitKind::Str(ref lit, _) = lit.node, - lit.is_empty() - ], { - return true; - }} - - false -} - -/// Checks if the expressions matches -/// ``` -/// &match (&42,) { -/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)], -/// }) -/// ``` -fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, - let ExprMatch(_, ref arms, _) = expr.node, - arms.len() == 1, - arms[0].pats.len() == 1, - let PatKind::Tup(ref pat) = arms[0].pats[0].node, - pat.len() == 1, - let ExprVec(ref exprs) = arms[0].body.node, - exprs.len() == 1, - let ExprCall(_, ref args) = exprs[0].node, - args.len() == 2, - let ExprPath(None, ref path) = args[1].node, - match_path(path, &paths::DISPLAY_FMT_METHOD) - ], { - let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0])); - - return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING); - }} - - false -} diff --git a/src/formatting.rs b/src/formatting.rs deleted file mode 100644 index aa6dd46cf0b..00000000000 --- a/src/formatting.rs +++ /dev/null @@ -1,166 +0,0 @@ -use rustc::lint::*; -use syntax::codemap::mk_sp; -use syntax::ast; -use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; -use syntax::ptr::P; - -/// **What it does:** This lint looks for use of the non-existent `=*`, `=!` and `=-` operators. -/// -/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// a =- 42; // confusing, should it be `a -= 42` or `a = -42`? -/// ``` -declare_lint! { - pub SUSPICIOUS_ASSIGNMENT_FORMATTING, - Warn, - "suspicious formatting of `*=`, `-=` or `!=`" -} - -/// **What it does:** This lint checks for formatting of `else if`. It lints if the `else` and `if` -/// are not on the same line or the `else` seems to be missing. -/// -/// **Why is this bad?** This is probably some refactoring remnant, even if the code is correct, it -/// might look confusing. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// if foo { -/// } if bar { // looks like an `else` is missing here -/// } -/// -/// if foo { -/// } else -/// -/// if bar { // this is the `else` block of the previous `if`, but should it be? -/// } -/// ``` -declare_lint! { - pub SUSPICIOUS_ELSE_FORMATTING, - Warn, - "suspicious formatting of `else if`" -} - -#[derive(Copy,Clone)] -pub struct Formatting; - -impl LintPass for Formatting { - fn get_lints(&self) -> LintArray { - lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING] - } -} - -impl EarlyLintPass for Formatting { - fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { - for w in block.stmts.windows(2) { - match (&w[0].node, &w[1].node) { - (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Expr(ref second, _)) | - (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Semi(ref second, _)) => { - check_consecutive_ifs(cx, first, second); - } - _ => (), - } - } - - if let Some(ref expr) = block.expr { - if let Some(ref stmt) = block.stmts.iter().last() { - if let ast::StmtKind::Expr(ref first, _) = stmt.node { - check_consecutive_ifs(cx, first, expr); - } - } - } - } - - fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { - check_assign(cx, expr); - check_else_if(cx, expr); - } -} - -/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint. -fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { - if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { - if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) { - let eq_span = mk_sp(lhs.span.hi, rhs.span.lo); - - if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node { - if let Some(eq_snippet) = snippet_opt(cx, eq_span) { - let op = ast::UnOp::to_string(op); - let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo); - if eq_snippet.ends_with('=') { - span_note_and_lint(cx, - SUSPICIOUS_ASSIGNMENT_FORMATTING, - eqop_span, - &format!("this looks like you are trying to use `.. {op}= ..`, but you \ - really are doing `.. = ({op} ..)`", - op = op), - eqop_span, - &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op)); - } - } - } - } - } -} - -/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`. -fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { - if let Some((then, &Some(ref else_))) = unsugar_if(expr) { - if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) { - // this will be a span from the closing ‘}’ of the “then” block (excluding) to the - // “if” of the “else if” block (excluding) - let else_span = mk_sp(then.span.hi, else_.span.lo); - - // the snippet should look like " else \n " with maybe comments anywhere - // it’s bad when there is a ‘\n’ after the “else” - if let Some(else_snippet) = snippet_opt(cx, else_span) { - let else_pos = else_snippet.find("else").expect("there must be a `else` here"); - - if else_snippet[else_pos..].contains('\n') { - span_note_and_lint(cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - "this is an `else if` but the formatting might hide it", - else_span, - "to remove this lint, remove the `else` or remove the new line between `else` \ - and `if`"); - } - } - } - } -} - -/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. -fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { - if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) && - unsugar_if(first).is_some() && unsugar_if(second).is_some() { - // where the else would be - let else_span = mk_sp(first.span.hi, second.span.lo); - - if let Some(else_snippet) = snippet_opt(cx, else_span) { - if !else_snippet.contains('\n') { - span_note_and_lint(cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - "this looks like an `else if` but the `else` is missing", - else_span, - "to remove this lint, add the missing `else` or add a new line before the second \ - `if`"); - } - } - } -} - -/// Match `if` or `else if` expressions and return the `then` and `else` block. -fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> { - match expr.node { - ast::ExprKind::If(_, ref then, ref else_) | - ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), - _ => None, - } -} diff --git a/src/functions.rs b/src/functions.rs deleted file mode 100644 index d9334447226..00000000000 --- a/src/functions.rs +++ /dev/null @@ -1,76 +0,0 @@ -use rustc::lint::*; -use rustc::hir; -use rustc::hir::intravisit; -use syntax::ast; -use syntax::codemap::Span; -use utils::span_lint; - -/// **What it does:** Check for functions with too many parameters. -/// -/// **Why is this bad?** Functions with lots of parameters are considered bad style and reduce -/// readability (“what does the 5th parameter mean?”). Consider grouping some parameters into a -/// new type. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ``` -/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { .. } -/// ``` -declare_lint! { - pub TOO_MANY_ARGUMENTS, - Warn, - "functions with too many arguments" -} - -#[derive(Copy,Clone)] -pub struct Functions { - threshold: u64, -} - -impl Functions { - pub fn new(threshold: u64) -> Functions { - Functions { threshold: threshold } - } -} - -impl LintPass for Functions { - fn get_lints(&self) -> LintArray { - lint_array!(TOO_MANY_ARGUMENTS) - } -} - -impl LateLintPass for Functions { - fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) { - use rustc::hir::map::Node::*; - - if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { - match item.node { - hir::ItemImpl(_, _, _, Some(_), _, _) | - hir::ItemDefaultImpl(..) => return, - _ => (), - } - } - - self.check_arg_number(cx, decl, span); - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { - if let hir::MethodTraitItem(ref sig, _) = item.node { - self.check_arg_number(cx, &sig.decl, item.span); - } - } -} - -impl Functions { - fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { - let args = decl.inputs.len() as u64; - if args > self.threshold { - span_lint(cx, - TOO_MANY_ARGUMENTS, - span, - &format!("this function has too many arguments ({}/{})", args, self.threshold)); - } - } -} diff --git a/src/identity_op.rs b/src/identity_op.rs deleted file mode 100644 index 4c1f01b7385..00000000000 --- a/src/identity_op.rs +++ /dev/null @@ -1,72 +0,0 @@ -use consts::{constant_simple, Constant}; -use rustc::lint::*; -use rustc::hir::*; -use syntax::codemap::Span; -use utils::{span_lint, snippet, in_macro}; -use rustc_const_math::ConstInt; - -/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. -/// -/// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly. -/// -/// **Known problems:** None -/// -/// **Example:** `x / 1 + 0 * 1 - 0 | 0` -declare_lint! { - pub IDENTITY_OP, Warn, - "using identity operations, e.g. `x + 0` or `y / 1`" -} - -#[derive(Copy,Clone)] -pub struct IdentityOp; - -impl LintPass for IdentityOp { - fn get_lints(&self) -> LintArray { - lint_array!(IDENTITY_OP) - } -} - -impl LateLintPass for IdentityOp { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if in_macro(cx, e.span) { - return; - } - if let ExprBinary(ref cmp, ref left, ref right) = e.node { - match cmp.node { - BiAdd | BiBitOr | BiBitXor => { - check(cx, left, 0, e.span, right.span); - check(cx, right, 0, e.span, left.span); - } - BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), - BiMul => { - check(cx, left, 1, e.span, right.span); - check(cx, right, 1, e.span, left.span); - } - BiDiv => check(cx, right, 1, e.span, left.span), - BiBitAnd => { - check(cx, left, -1, e.span, right.span); - check(cx, right, -1, e.span, left.span); - } - _ => (), - } - } - } -} - - -fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(v @ Constant::Int(_)) = constant_simple(e) { - if match m { - 0 => v == Constant::Int(ConstInt::Infer(0)), - -1 => v == Constant::Int(ConstInt::InferSigned(-1)), - 1 => v == Constant::Int(ConstInt::Infer(1)), - _ => unreachable!(), - } { - span_lint(cx, - IDENTITY_OP, - span, - &format!("the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, ".."))); - } - } -} diff --git a/src/if_not_else.rs b/src/if_not_else.rs deleted file mode 100644 index d78eba9877b..00000000000 --- a/src/if_not_else.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! lint on if branches that could be swapped so no `!` operation is necessary on the condition - -use rustc::lint::*; -use syntax::ast::*; - -use utils::span_help_and_lint; - -/// **What it does:** Warns on the use of `!` or `!=` in an if condition with an else branch -/// -/// **Why is this bad?** Negations reduce the readability of statements -/// -/// **Known problems:** None -/// -/// **Example:** if !v.is_empty() { a() } else { b() } -declare_lint! { - pub IF_NOT_ELSE, Allow, - "finds if branches that could be swapped so no negation operation is necessary on the condition" -} - -pub struct IfNotElse; - -impl LintPass for IfNotElse { - fn get_lints(&self) -> LintArray { - lint_array!(IF_NOT_ELSE) - } -} - -impl EarlyLintPass for IfNotElse { - fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { - if let ExprKind::If(ref cond, _, Some(ref els)) = item.node { - if let ExprKind::Block(..) = els.node { - match cond.node { - ExprKind::Unary(UnOp::Not, _) => { - span_help_and_lint(cx, - IF_NOT_ELSE, - item.span, - "Unnecessary boolean `not` operation", - "remove the `!` and swap the blocks of the if/else"); - } - ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { - span_help_and_lint(cx, - IF_NOT_ELSE, - item.span, - "Unnecessary `!=` operation", - "change to `==` and swap the blocks of the if/else"); - } - _ => (), - } - } - } - } -} diff --git a/src/items_after_statements.rs b/src/items_after_statements.rs deleted file mode 100644 index 2e6b33ab390..00000000000 --- a/src/items_after_statements.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! lint when items are used after statements - -use rustc::lint::*; -use syntax::ast::*; -use utils::in_macro; - -/// **What it does:** This lints checks for items declared after some statement in a block -/// -/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are -/// processed in order. This might cause confusion as it's hard to figure out which item is meant -/// in a statement. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// fn foo() { -/// println!("cake"); -/// } -/// fn main() { -/// foo(); // prints "foo" -/// fn foo() { -/// println!("foo"); -/// } -/// foo(); // prints "foo" -/// } -/// ``` -declare_lint! { - pub ITEMS_AFTER_STATEMENTS, - Allow, - "finds blocks where an item comes after a statement" -} - -pub struct ItemsAfterStatements; - -impl LintPass for ItemsAfterStatements { - fn get_lints(&self) -> LintArray { - lint_array!(ITEMS_AFTER_STATEMENTS) - } -} - -impl EarlyLintPass for ItemsAfterStatements { - fn check_block(&mut self, cx: &EarlyContext, item: &Block) { - if in_macro(cx, item.span) { - return; - } - let mut stmts = item.stmts.iter().map(|stmt| &stmt.node); - // skip initial items - while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() { - if let DeclKind::Local(_) = decl.node { - break; - } - } - // lint on all further items - for stmt in stmts { - if let StmtKind::Decl(ref decl, _) = *stmt { - if let DeclKind::Item(ref it) = decl.node { - if in_macro(cx, it.span) { - return; - } - cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, - it.span, - "adding items after statements is confusing, since items exist from the \ - start of the scope") - .emit(); - } - } - } - } -} diff --git a/src/len_zero.rs b/src/len_zero.rs deleted file mode 100644 index b6dea831690..00000000000 --- a/src/len_zero.rs +++ /dev/null @@ -1,202 +0,0 @@ -use rustc::lint::*; -use rustc::hir::def_id::DefId; -use rustc::ty::{self, MethodTraitItemId, ImplOrTraitItemId}; -use rustc::hir::*; -use syntax::ast::{Lit, LitKind, Name}; -use syntax::codemap::{Span, Spanned}; -use syntax::ptr::P; -use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; - -/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. -/// -/// **Why is this bad?** Some structures can answer `.is_empty()` much faster than calculating their length. So it is good to get into the habit of using `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer than a comparison. -/// -/// **Known problems:** None -/// -/// **Example:** `if x.len() == 0 { .. }` -declare_lint! { - pub LEN_ZERO, Warn, - "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ - could be used instead" -} - -/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. -/// -/// **Why is this bad?** It is good custom to have both methods, because for some data structures, asking about the length will be a costly operation, whereas `.is_empty()` can usually answer in constant time. Also it used to lead to false positives on the [`len_zero`](#len_zero) lint – currently that lint will ignore such entities. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// impl X { -/// fn len(&self) -> usize { .. } -/// } -/// ``` -declare_lint! { - pub LEN_WITHOUT_IS_EMPTY, Warn, - "traits and impls that have `.len()` but not `.is_empty()`" -} - -#[derive(Copy,Clone)] -pub struct LenZero; - -impl LintPass for LenZero { - fn get_lints(&self) -> LintArray { - lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) - } -} - -impl LateLintPass for LenZero { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if in_macro(cx, item.span) { - return; - } - - match item.node { - ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), - ItemImpl(_, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), - _ => (), - } - } - - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_macro(cx, expr.span) { - return; - } - - if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { - match cmp { - BiEq => check_cmp(cx, expr.span, left, right, ""), - BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), - _ => (), - } - } - } -} - -fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { - fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.name.as_str() == name && - if let MethodTraitItem(ref sig, _) = item.node { - is_self_sig(sig) - } else { - false - } - } - - if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - for i in trait_items { - if is_named_self(i, "len") { - span_lint(cx, - LEN_WITHOUT_IS_EMPTY, - i.span, - &format!("trait `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ - Consider adding one", - item.name)); - } - } - } -} - -fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) { - fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.name.as_str() == name && - if let ImplItemKind::Method(ref sig, _) = item.node { - is_self_sig(sig) - } else { - false - } - } - - if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { - for i in impl_items { - if is_named_self(i, "len") { - let ty = cx.tcx.node_id_to_type(item.id); - - span_lint(cx, - LEN_WITHOUT_IS_EMPTY, - i.span, - &format!("item `{}` has a `.len(_: &Self)` method, but no `.is_empty(_: &Self)` method. \ - Consider adding one", - ty)); - return; - } - } - } -} - -fn is_self_sig(sig: &MethodSig) -> bool { - if sig.decl.has_self() { - sig.decl.inputs.len() == 1 - } else { - false - } -} - -fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { - // check if we are in an is_empty() method - if let Some(name) = get_item_name(cx, left) { - if name.as_str() == "is_empty" { - return; - } - } - match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) | - (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => { - check_len_zero(cx, span, &method.node, args, lit, op) - } - _ => (), - } -} - -fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { - if let Spanned { node: LitKind::Int(0, _), .. } = *lit { - if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { - span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| { - db.span_suggestion(span, - "consider using `is_empty`", - format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_"))); - }); - } - } -} - -/// Check if this type has an `is_empty` method. -fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { - /// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`. - fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool { - if let MethodTraitItemId(def_id) = *id { - if let ty::MethodTraitItem(ref method) = cx.tcx.impl_or_trait_item(def_id) { - method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 - } else { - false - } - } else { - false - } - } - - /// Check the inherent impl's items for an `is_empty(self)` method. - fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool { - let impl_items = cx.tcx.impl_items.borrow(); - cx.tcx.inherent_impls.borrow().get(id).map_or(false, |ids| { - ids.iter().any(|iid| impl_items.get(iid).map_or(false, |iids| iids.iter().any(|i| is_is_empty(cx, i)))) - }) - } - - let ty = &walk_ptrs_ty(cx.tcx.expr_ty(expr)); - match ty.sty { - ty::TyTrait(_) => { - cx.tcx - .trait_item_def_ids - .borrow() - .get(&ty.ty_to_def_id().expect("trait impl not found")) - .map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))) - } - ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)), - ty::TyEnum(ref id, _) | - ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did), - ty::TyArray(..) | ty::TyStr => true, - _ => false, - } -} diff --git a/src/lib.rs b/src/lib.rs index 41c26cf7109..f9a6588e904 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,173 +1,13 @@ +// error-pattern:cargo-clippy #![feature(type_macros)] #![feature(plugin_registrar, box_syntax)] #![feature(rustc_private, collections)] -#![feature(iter_arith)] #![feature(custom_attribute)] #![feature(slice_patterns)] #![feature(question_mark)] #![feature(stmt_expr_attributes)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] -extern crate rustc_driver; -extern crate getopts; - -use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; -use rustc::session::{config, Session}; -use rustc::session::config::{Input, ErrorOutputType}; -use syntax::diagnostics; -use std::path::PathBuf; -use std::process::Command; - -struct ClippyCompilerCalls(RustcDefaultCalls); - -impl std::default::Default for ClippyCompilerCalls { - fn default() -> Self { - Self::new() - } -} - -impl ClippyCompilerCalls { - fn new() -> Self { - ClippyCompilerCalls(RustcDefaultCalls) - } -} - -impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { - fn early_callback(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - descriptions: &diagnostics::registry::Registry, - output: ErrorOutputType) - -> Compilation { - self.0.early_callback(matches, sopts, descriptions, output) - } - fn no_input(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - odir: &Option<PathBuf>, - ofile: &Option<PathBuf>, - descriptions: &diagnostics::registry::Registry) - -> Option<(Input, Option<PathBuf>)> { - self.0.no_input(matches, sopts, odir, ofile, descriptions) - } - fn late_callback(&mut self, - matches: &getopts::Matches, - sess: &Session, - input: &Input, - odir: &Option<PathBuf>, - ofile: &Option<PathBuf>) - -> Compilation { - self.0.late_callback(matches, sess, input, odir, ofile) - } - fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut control = self.0.build_controller(sess, matches); - - let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); - control.after_parse.callback = Box::new(move |state| { - { - let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed")); - registry.args_hidden = Some(Vec::new()); - plugin_registrar(&mut registry); - - let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } - - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); - } - - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.mir_passes.borrow_mut().extend(mir_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - } - old(state); - }); - - control - } -} - -use std::path::Path; - -pub fn main() { - use std::env; - - if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { - return; - } - - let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps"); - - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - let sys_root = match (home, toolchain) { - (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => option_env!("SYSROOT").map(|s| s.to_owned()) - .or(Command::new("rustc").arg("--print") - .arg("sysroot") - .output().ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - ) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"), - }; - - if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); - let path = std::env::current_exe().expect("current executable path invalid"); - let exit_status = std::process::Command::new("cargo") - .args(&args) - .env("RUSTC", path) - .spawn().expect("could not run cargo") - .wait().expect("failed to wait for cargo?"); - - if let Some(code) = exit_status.code() { - std::process::exit(code); - } - } else { - let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { - env::args().collect() - } else { - env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() - }; - let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); - - if let Err(err_count) = result { - if err_count > 0 { - std::process::exit(1); - } - } - } -} - -fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String> - where P: AsRef<Path>, I: Iterator<Item=String> { - - let mut args = vec!["rustc".to_owned()]; - - let mut found_dashes = false; - for arg in old_args { - found_dashes |= arg == "--"; - args.push(arg); - } - if !found_dashes { - args.push("--".to_owned()); - } - args.push("-L".to_owned()); - args.push(dep_path.as_ref().to_string_lossy().into_owned()); - args.push(String::from("--sysroot")); - args.push(sysroot); - args.push("-Zno-trans".to_owned()); - args -} - #[macro_use] extern crate syntax; #[macro_use] @@ -196,371 +36,28 @@ extern crate rustc_const_eval; extern crate rustc_const_math; use rustc_plugin::Registry; +extern crate clippy_lints; + +pub use clippy_lints::*; + macro_rules! declare_restriction_lint { { pub $name:tt, $description:tt } => { declare_lint! { pub $name, Allow, $description } }; } -pub mod consts; -#[macro_use] -pub mod utils; - -// begin lints modules, do not remove this comment, it’s used in `update_lints` -pub mod approx_const; -pub mod arithmetic; -pub mod array_indexing; -pub mod assign_ops; -pub mod attrs; -pub mod bit_mask; -pub mod blacklisted_name; -pub mod block_in_if_condition; -pub mod booleans; -pub mod collapsible_if; -pub mod copies; -pub mod cyclomatic_complexity; -pub mod derive; -pub mod doc; -pub mod drop_ref; -pub mod entry; -pub mod enum_clike; -pub mod enum_glob_use; -pub mod enum_variants; -pub mod eq_op; -pub mod escape; -pub mod eta_reduction; -pub mod format; -pub mod formatting; -pub mod functions; -pub mod identity_op; -pub mod if_not_else; -pub mod items_after_statements; -pub mod len_zero; -pub mod lifetimes; -pub mod loops; -pub mod map_clone; -pub mod matches; -pub mod mem_forget; -pub mod methods; -pub mod minmax; -pub mod misc; -pub mod misc_early; -pub mod mut_mut; -pub mod mut_reference; -pub mod mutex_atomic; -pub mod needless_bool; -pub mod needless_borrow; -pub mod needless_update; -pub mod neg_multiply; -pub mod new_without_default; -pub mod no_effect; -pub mod non_expressive_names; -pub mod open_options; -pub mod overflow_check_conditional; -pub mod panic; -pub mod precedence; -pub mod print; -pub mod ptr_arg; -pub mod ranges; -pub mod regex; -pub mod returns; -pub mod shadow; -pub mod strings; -pub mod swap; -pub mod temporary_assignment; -pub mod transmute; -pub mod types; -pub mod unicode; -pub mod unsafe_removed_from_name; -pub mod unused_label; -pub mod vec; -pub mod zero_div_zero; -// end lints modules, do not remove this comment, it’s used in `update_lints` - mod reexport { pub use syntax::ast::{Name, NodeId}; } #[plugin_registrar] -#[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { - let conf = match utils::conf::conf_file(reg.args()) { - Ok(file_name) => { - // if the user specified a file, it must exist, otherwise default to `clippy.toml` but - // do not require the file to exist - let (ref file_name, must_exist) = if let Some(ref file_name) = file_name { - (&**file_name, true) - } else { - ("clippy.toml", false) - }; - - let (conf, errors) = utils::conf::read_conf(file_name, must_exist); - - // all conf errors are non-fatal, we just use the default conf in case of error - for error in errors { - reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", error)).emit(); - } - - conf - } - Err((err, span)) => { - reg.sess.struct_span_err(span, err) - .span_note(span, "Clippy will use default configuration") - .emit(); - utils::conf::Conf::default() - } - }; - - let mut store = reg.sess.lint_store.borrow_mut(); - store.register_removed("unstable_as_slice", "`Vec::as_slice` has been stabilized in 1.7"); - store.register_removed("unstable_as_mut_slice", "`Vec::as_mut_slice` has been stabilized in 1.7"); - store.register_removed("str_to_string", "using `str::to_string` is common even today and specialization will likely happen soon"); - store.register_removed("string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon"); - // end deprecated lints, do not remove this comment, it’s used in `update_lints` - - reg.register_late_lint_pass(box types::TypePass); - reg.register_late_lint_pass(box booleans::NonminimalBool); - reg.register_late_lint_pass(box misc::TopLevelRefPass); - reg.register_late_lint_pass(box misc::CmpNan); - reg.register_late_lint_pass(box eq_op::EqOp); - reg.register_early_lint_pass(box enum_variants::EnumVariantNames); - reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); - reg.register_late_lint_pass(box enum_clike::EnumClikeUnportableVariant); - reg.register_late_lint_pass(box bit_mask::BitMask); - reg.register_late_lint_pass(box ptr_arg::PtrArg); - reg.register_late_lint_pass(box needless_bool::NeedlessBool); - reg.register_late_lint_pass(box needless_bool::BoolComparison); - reg.register_late_lint_pass(box approx_const::ApproxConstant); - reg.register_late_lint_pass(box misc::FloatCmp); - reg.register_early_lint_pass(box precedence::Precedence); - reg.register_late_lint_pass(box eta_reduction::EtaPass); - reg.register_late_lint_pass(box identity_op::IdentityOp); - reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements); - reg.register_late_lint_pass(box mut_mut::MutMut); - reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); - reg.register_late_lint_pass(box len_zero::LenZero); - reg.register_late_lint_pass(box misc::CmpOwned); - reg.register_late_lint_pass(box attrs::AttrPass); - reg.register_late_lint_pass(box collapsible_if::CollapsibleIf); - reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition); - reg.register_late_lint_pass(box misc::ModuloOne); - reg.register_late_lint_pass(box unicode::Unicode); - reg.register_late_lint_pass(box strings::StringAdd); - reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box methods::MethodsPass); - reg.register_late_lint_pass(box shadow::ShadowPass); - reg.register_late_lint_pass(box types::LetPass); - reg.register_late_lint_pass(box types::UnitCmp); - reg.register_late_lint_pass(box loops::LoopsPass); - reg.register_late_lint_pass(box lifetimes::LifetimePass); - reg.register_late_lint_pass(box entry::HashMapLint); - reg.register_late_lint_pass(box ranges::StepByZero); - reg.register_late_lint_pass(box types::CastPass); - reg.register_late_lint_pass(box types::TypeComplexityPass::new(conf.type_complexity_threshold)); - reg.register_late_lint_pass(box matches::MatchPass); - reg.register_late_lint_pass(box misc::PatternPass); - reg.register_late_lint_pass(box minmax::MinMaxPass); - reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); - reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); - reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); - reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); - reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); - reg.register_late_lint_pass(box no_effect::NoEffectPass); - reg.register_late_lint_pass(box map_clone::MapClonePass); - reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); - reg.register_late_lint_pass(box transmute::Transmute); - reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); - reg.register_late_lint_pass(box escape::EscapePass); - reg.register_early_lint_pass(box misc_early::MiscEarly); - reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); - reg.register_late_lint_pass(box array_indexing::ArrayIndexing); - reg.register_late_lint_pass(box panic::PanicPass); - reg.register_late_lint_pass(box strings::StringLitAsBytes); - reg.register_late_lint_pass(box derive::Derive); - reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box print::PrintLint); - reg.register_late_lint_pass(box vec::UselessVec); - reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { - max_single_char_names: conf.max_single_char_names, - }); - reg.register_late_lint_pass(box drop_ref::DropRefPass); - reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); - reg.register_late_lint_pass(box types::InvalidUpcastComparisons); - reg.register_late_lint_pass(box regex::RegexPass::default()); - reg.register_late_lint_pass(box copies::CopyAndPaste); - reg.register_late_lint_pass(box format::FormatMacLint); - reg.register_early_lint_pass(box formatting::Formatting); - reg.register_late_lint_pass(box swap::Swap); - reg.register_early_lint_pass(box if_not_else::IfNotElse); - reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); - reg.register_late_lint_pass(box unused_label::UnusedLabel); - reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); - reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); - reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); - reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); - reg.register_late_lint_pass(box neg_multiply::NegMultiply); - reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); - reg.register_late_lint_pass(box mem_forget::MemForget); - reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); - reg.register_late_lint_pass(box assign_ops::AssignOps); - - reg.register_lint_group("clippy_restrictions", vec![ - arithmetic::FLOAT_ARITHMETIC, - arithmetic::INTEGER_ARITHMETIC, - assign_ops::ASSIGN_OPS, - ]); - - reg.register_lint_group("clippy_pedantic", vec![ - array_indexing::INDEXING_SLICING, - booleans::NONMINIMAL_BOOL, - enum_glob_use::ENUM_GLOB_USE, - if_not_else::IF_NOT_ELSE, - items_after_statements::ITEMS_AFTER_STATEMENTS, - matches::SINGLE_MATCH_ELSE, - mem_forget::MEM_FORGET, - methods::OPTION_UNWRAP_USED, - methods::RESULT_UNWRAP_USED, - methods::WRONG_PUB_SELF_CONVENTION, - misc::USED_UNDERSCORE_BINDING, - mut_mut::MUT_MUT, - mutex_atomic::MUTEX_INTEGER, - non_expressive_names::SIMILAR_NAMES, - print::PRINT_STDOUT, - print::USE_DEBUG, - shadow::SHADOW_REUSE, - shadow::SHADOW_SAME, - shadow::SHADOW_UNRELATED, - strings::STRING_ADD, - strings::STRING_ADD_ASSIGN, - types::CAST_POSSIBLE_TRUNCATION, - types::CAST_POSSIBLE_WRAP, - types::CAST_PRECISION_LOSS, - types::CAST_SIGN_LOSS, - types::INVALID_UPCAST_COMPARISONS, - unicode::NON_ASCII_LITERAL, - unicode::UNICODE_NOT_NFC, - ]); + register_plugins(reg); +} - reg.register_lint_group("clippy", vec![ - approx_const::APPROX_CONSTANT, - array_indexing::OUT_OF_BOUNDS_INDEXING, - assign_ops::ASSIGN_OP_PATTERN, - attrs::DEPRECATED_SEMVER, - attrs::INLINE_ALWAYS, - bit_mask::BAD_BIT_MASK, - bit_mask::INEFFECTIVE_BIT_MASK, - blacklisted_name::BLACKLISTED_NAME, - block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, - block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, - booleans::LOGIC_BUG, - collapsible_if::COLLAPSIBLE_IF, - copies::IF_SAME_THEN_ELSE, - copies::IFS_SAME_COND, - copies::MATCH_SAME_ARMS, - cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, - derive::DERIVE_HASH_XOR_EQ, - derive::EXPL_IMPL_CLONE_ON_COPY, - doc::DOC_MARKDOWN, - drop_ref::DROP_REF, - entry::MAP_ENTRY, - enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, - enum_variants::ENUM_VARIANT_NAMES, - eq_op::EQ_OP, - escape::BOXED_LOCAL, - eta_reduction::REDUNDANT_CLOSURE, - format::USELESS_FORMAT, - formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, - formatting::SUSPICIOUS_ELSE_FORMATTING, - functions::TOO_MANY_ARGUMENTS, - identity_op::IDENTITY_OP, - len_zero::LEN_WITHOUT_IS_EMPTY, - len_zero::LEN_ZERO, - lifetimes::NEEDLESS_LIFETIMES, - lifetimes::UNUSED_LIFETIMES, - loops::EMPTY_LOOP, - loops::EXPLICIT_COUNTER_LOOP, - loops::EXPLICIT_ITER_LOOP, - loops::FOR_KV_MAP, - loops::FOR_LOOP_OVER_OPTION, - loops::FOR_LOOP_OVER_RESULT, - loops::ITER_NEXT_LOOP, - loops::NEEDLESS_RANGE_LOOP, - loops::REVERSE_RANGE_LOOP, - loops::UNUSED_COLLECT, - loops::WHILE_LET_LOOP, - loops::WHILE_LET_ON_ITERATOR, - map_clone::MAP_CLONE, - matches::MATCH_BOOL, - matches::MATCH_OVERLAPPING_ARM, - matches::MATCH_REF_PATS, - matches::SINGLE_MATCH, - methods::CHARS_NEXT_CMP, - methods::CLONE_DOUBLE_REF, - methods::CLONE_ON_COPY, - methods::EXTEND_FROM_SLICE, - methods::FILTER_NEXT, - methods::NEW_RET_NO_SELF, - methods::OK_EXPECT, - methods::OPTION_MAP_UNWRAP_OR, - methods::OPTION_MAP_UNWRAP_OR_ELSE, - methods::OR_FUN_CALL, - methods::SEARCH_IS_SOME, - methods::SHOULD_IMPLEMENT_TRAIT, - methods::SINGLE_CHAR_PATTERN, - methods::TEMPORARY_CSTRING_AS_PTR, - methods::WRONG_SELF_CONVENTION, - minmax::MIN_MAX, - misc::CMP_NAN, - misc::CMP_OWNED, - misc::FLOAT_CMP, - misc::MODULO_ONE, - misc::REDUNDANT_PATTERN, - misc::TOPLEVEL_REF_ARG, - misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, - misc_early::REDUNDANT_CLOSURE_CALL, - misc_early::UNNEEDED_FIELD_PATTERN, - mut_reference::UNNECESSARY_MUT_PASSED, - mutex_atomic::MUTEX_ATOMIC, - needless_bool::BOOL_COMPARISON, - needless_bool::NEEDLESS_BOOL, - needless_borrow::NEEDLESS_BORROW, - needless_update::NEEDLESS_UPDATE, - neg_multiply::NEG_MULTIPLY, - new_without_default::NEW_WITHOUT_DEFAULT, - new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, - no_effect::NO_EFFECT, - no_effect::UNNECESSARY_OPERATION, - non_expressive_names::MANY_SINGLE_CHAR_NAMES, - open_options::NONSENSICAL_OPEN_OPTIONS, - overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, - panic::PANIC_PARAMS, - precedence::PRECEDENCE, - ptr_arg::PTR_ARG, - ranges::RANGE_STEP_BY_ZERO, - ranges::RANGE_ZIP_WITH_LEN, - regex::INVALID_REGEX, - regex::REGEX_MACRO, - regex::TRIVIAL_REGEX, - returns::LET_AND_RETURN, - returns::NEEDLESS_RETURN, - strings::STRING_LIT_AS_BYTES, - swap::ALMOST_SWAPPED, - swap::MANUAL_SWAP, - temporary_assignment::TEMPORARY_ASSIGNMENT, - transmute::CROSSPOINTER_TRANSMUTE, - transmute::TRANSMUTE_PTR_TO_REF, - transmute::USELESS_TRANSMUTE, - types::ABSURD_EXTREME_COMPARISONS, - types::BOX_VEC, - types::CHAR_LIT_AS_U8, - types::LET_UNIT_VALUE, - types::LINKEDLIST, - types::TYPE_COMPLEXITY, - types::UNIT_CMP, - unicode::ZERO_WIDTH_SPACE, - unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, - unused_label::UNUSED_LABEL, - vec::USELESS_VEC, - zero_div_zero::ZERO_DIVIDED_BY_ZERO, - ]); +// only exists to let the dogfood integration test works. +// Don't run clippy as an executable directly +#[allow(dead_code, print_stdout)] +fn main() { + panic!("Please use the cargo-clippy executable"); } diff --git a/src/lifetimes.rs b/src/lifetimes.rs deleted file mode 100644 index 797e9708b60..00000000000 --- a/src/lifetimes.rs +++ /dev/null @@ -1,347 +0,0 @@ -use reexport::*; -use rustc::lint::*; -use rustc::hir::def::Def; -use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics}; -use std::collections::{HashSet, HashMap}; -use syntax::codemap::Span; -use utils::{in_external_macro, span_lint}; - -/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. -/// -/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. -/// -/// **Known problems:** Potential false negatives: we bail out if the function has a `where` clause where lifetimes are mentioned. -/// -/// **Example:** `fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }` -declare_lint! { - pub NEEDLESS_LIFETIMES, - Warn, - "using explicit lifetimes for references in function arguments when elision rules \ - would allow omitting them" -} - -/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. -/// -/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code. -/// -/// **Known problems:** None -/// -/// **Example:** `fn unused_lifetime<'a>(x: u8) { .. }` -declare_lint! { - pub UNUSED_LIFETIMES, - Warn, - "unused lifetimes in function definitions" -} - -#[derive(Copy,Clone)] -pub struct LifetimePass; - -impl LintPass for LifetimePass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_LIFETIMES, UNUSED_LIFETIMES) - } -} - -impl LateLintPass for LifetimePass { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node { - check_fn_inner(cx, decl, generics, item.span); - } - } - - fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let ImplItemKind::Method(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, &sig.generics, item.span); - } - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - if let MethodTraitItem(ref sig, _) = item.node { - check_fn_inner(cx, &sig.decl, &sig.generics, item.span); - } - } -} - -/// The lifetime of a &-reference. -#[derive(PartialEq, Eq, Hash, Debug)] -enum RefLt { - Unnamed, - Static, - Named(Name), -} - -fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { - if let TraitTyParamBound(ref trait_ref, _) = *bound { - let lt = trait_ref.trait_ref - .path - .segments - .last() - .expect("a path must have at least one segment") - .parameters - .lifetimes(); - - Some(lt) - } else { - None - } -} - -fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Span) { - if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { - return; - } - - let bounds_lts = generics.ty_params - .iter() - .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); - - if could_use_elision(cx, decl, &generics.lifetimes, bounds_lts) { - span_lint(cx, - NEEDLESS_LIFETIMES, - span, - "explicit lifetimes given in parameter types where they could be elided"); - } - report_extra_lifetimes(cx, decl, generics); -} - -fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl, - named_lts: &[LifetimeDef], bounds_lts: T) - -> bool { - // There are two scenarios where elision works: - // * no output references, all input references have different LT - // * output references, exactly one input reference with same LT - // All lifetimes must be unnamed, 'static or defined without bounds on the - // level of the current item. - - // check named LTs - let allowed_lts = allowed_lts_from(named_lts); - - // these will collect all the lifetimes for references in arg/return types - let mut input_visitor = RefVisitor::new(cx); - let mut output_visitor = RefVisitor::new(cx); - - // extract lifetimes in input argument types - for arg in &func.inputs { - input_visitor.visit_ty(&arg.ty); - } - // extract lifetimes in output type - if let Return(ref ty) = func.output { - output_visitor.visit_ty(ty); - } - - let input_lts = lts_from_bounds(input_visitor.into_vec(), bounds_lts); - let output_lts = output_visitor.into_vec(); - - // check for lifetimes from higher scopes - for lt in input_lts.iter().chain(output_lts.iter()) { - if !allowed_lts.contains(lt) { - return false; - } - } - - // no input lifetimes? easy case! - if input_lts.is_empty() { - false - } else if output_lts.is_empty() { - // no output lifetimes, check distinctness of input lifetimes - - // only unnamed and static, ok - if input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static) { - return false; - } - // we have no output reference, so we only need all distinct lifetimes - input_lts.len() == unique_lifetimes(&input_lts) - } else { - // we have output references, so we need one input reference, - // and all output lifetimes must be the same - if unique_lifetimes(&output_lts) > 1 { - return false; - } - if input_lts.len() == 1 { - match (&input_lts[0], &output_lts[0]) { - (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true, - (&RefLt::Named(_), &RefLt::Unnamed) => true, - _ => false, // already elided, different named lifetimes - // or something static going on - } - } else { - false - } - } -} - -fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> { - let mut allowed_lts = HashSet::new(); - for lt in named_lts { - if lt.bounds.is_empty() { - allowed_lts.insert(RefLt::Named(lt.lifetime.name)); - } - } - allowed_lts.insert(RefLt::Unnamed); - allowed_lts.insert(RefLt::Static); - allowed_lts -} - -fn lts_from_bounds<'a, T: Iterator<Item = &'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> { - for lt in bounds_lts { - if lt.name.as_str() != "'static" { - vec.push(RefLt::Named(lt.name)); - } - } - - vec -} - -/// Number of unique lifetimes in the given vector. -fn unique_lifetimes(lts: &[RefLt]) -> usize { - lts.iter().collect::<HashSet<_>>().len() -} - -/// A visitor usable for `rustc_front::visit::walk_ty()`. -struct RefVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, - lts: Vec<RefLt>, -} - -impl<'v, 't> RefVisitor<'v, 't> { - fn new(cx: &'v LateContext<'v, 't>) -> RefVisitor<'v, 't> { - RefVisitor { - cx: cx, - lts: Vec::new(), - } - } - - fn record(&mut self, lifetime: &Option<Lifetime>) { - if let Some(ref lt) = *lifetime { - if lt.name.as_str() == "'static" { - self.lts.push(RefLt::Static); - } else { - self.lts.push(RefLt::Named(lt.name)); - } - } else { - self.lts.push(RefLt::Unnamed); - } - } - - fn into_vec(self) -> Vec<RefLt> { - self.lts - } - - fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) { - let last_path_segment = path.segments.last().map(|s| &s.parameters); - if let Some(&AngleBracketedParameters(ref params)) = last_path_segment { - if params.lifetimes.is_empty() { - if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { - match def { - Def::TyAlias(def_id) | - Def::Struct(def_id) => { - let type_scheme = self.cx.tcx.lookup_item_type(def_id); - for _ in type_scheme.generics.regions.as_slice() { - self.record(&None); - } - } - Def::Trait(def_id) => { - let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; - for _ in &trait_def.generics.regions { - self.record(&None); - } - } - _ => (), - } - } - } - } - } -} - -impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { - // for lifetimes as parameters of generics - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { - self.record(&Some(*lifetime)); - } - - fn visit_ty(&mut self, ty: &'v Ty) { - match ty.node { - TyRptr(None, _) => { - self.record(&None); - } - TyPath(_, ref path) => { - self.collect_anonymous_lifetimes(path, ty); - } - _ => (), - } - walk_ty(self, ty); - } -} - -/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to -/// reason about elision. -fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool { - for predicate in &where_clause.predicates { - match *predicate { - WherePredicate::RegionPredicate(..) => return true, - WherePredicate::BoundPredicate(ref pred) => { - // a predicate like F: Trait or F: for<'a> Trait<'a> - let mut visitor = RefVisitor::new(cx); - // walk the type F, it may not contain LT refs - walk_ty(&mut visitor, &pred.bounded_ty); - if !visitor.lts.is_empty() { - return true; - } - // if the bounds define new lifetimes, they are fine to occur - let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); - // now walk the bounds - for bound in pred.bounds.iter() { - walk_ty_param_bound(&mut visitor, bound); - } - // and check that all lifetimes are allowed - for lt in visitor.into_vec() { - if !allowed_lts.contains(<) { - return true; - } - } - } - WherePredicate::EqPredicate(ref pred) => { - let mut visitor = RefVisitor::new(cx); - walk_ty(&mut visitor, &pred.ty); - if !visitor.lts.is_empty() { - return true; - } - } - } - } - false -} - -struct LifetimeChecker(HashMap<Name, Span>); - -impl<'v> Visitor<'v> for LifetimeChecker { - // for lifetimes as parameters of generics - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { - self.0.remove(&lifetime.name); - } - - fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) { - // don't actually visit `<'a>` or `<'a: 'b>` - // we've already visited the `'a` declarations and - // don't want to spuriously remove them - // `'b` in `'a: 'b` is useless unless used elsewhere in - // a non-lifetime bound - } -} - -fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) { - let hs = generics.lifetimes - .iter() - .map(|lt| (lt.lifetime.name, lt.lifetime.span)) - .collect(); - let mut checker = LifetimeChecker(hs); - - walk_generics(&mut checker, generics); - walk_fn_decl(&mut checker, func); - - for &v in checker.0.values() { - span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); - } -} diff --git a/src/loops.rs b/src/loops.rs deleted file mode 100644 index 061b8efaa64..00000000000 --- a/src/loops.rs +++ /dev/null @@ -1,976 +0,0 @@ -use reexport::*; -use rustc::hir::*; -use rustc::hir::def::Def; -use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; -use rustc::hir::map::Node::NodeBlock; -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc::middle::region::CodeExtent; -use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use std::borrow::Cow; -use std::collections::HashMap; -use syntax::ast; - -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, - span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range, - walk_ptrs_ty, recover_for_loop}; -use utils::paths; -use utils::UnsugaredRange; - -/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. -/// -/// **Why is this bad?** Just iterating the collection itself makes the intent more clear and is probably faster. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// for i in 0..vec.len() { -/// println!("{}", vec[i]); -/// } -/// ``` -declare_lint! { - pub NEEDLESS_RANGE_LOOP, - Warn, - "for-looping over a range of indices where an iterator over items would do" -} - -/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. -/// -/// **Why is this bad?** Readability. -/// -/// **Known problems:** False negatives. We currently only warn on some known types. -/// -/// **Example:** `for x in y.iter() { .. }` (where y is a `Vec` or slice) -declare_lint! { - pub EXPLICIT_ITER_LOOP, - Warn, - "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" -} - -/// **What it does:** This lint checks for loops on `x.next()`. -/// -/// **Why is this bad?** `next()` returns either `Some(value)` if there was a value, or `None` otherwise. The insidious thing is that `Option<_>` implements `IntoIterator`, so that possibly one value will be iterated, leading to some hard to find bugs. No one will want to write such code [except to win an Underhanded Rust Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). -/// -/// **Known problems:** None -/// -/// **Example:** `for x in y.next() { .. }` -declare_lint! { - pub ITER_NEXT_LOOP, - Warn, - "for-looping over `_.next()` which is probably not intended" -} - -/// **What it does:** This lint checks for `for` loops over `Option` values. -/// -/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. -/// -/// **Known problems:** None -/// -/// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`. -declare_lint! { - pub FOR_LOOP_OVER_OPTION, - Warn, - "for-looping over an `Option`, which is more clearly expressed as an `if let`" -} - -/// **What it does:** This lint checks for `for` loops over `Result` values. -/// -/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. -/// -/// **Known problems:** None -/// -/// **Example:** `for x in result { .. }`. This should be `if let Ok(x) = result { .. }`. -declare_lint! { - pub FOR_LOOP_OVER_RESULT, - Warn, - "for-looping over a `Result`, which is more clearly expressed as an `if let`" -} - -/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. -/// -/// **Why is this bad?** The `while let` loop is usually shorter and more readable -/// -/// **Known problems:** Sometimes the wrong binding is displayed (#383) -/// -/// **Example:** -/// -/// ``` -/// loop { -/// let x = match y { -/// Some(x) => x, -/// None => break, -/// } -/// // .. do something with x -/// } -/// // is easier written as -/// while let Some(x) = y { -/// // .. do something with x -/// } -/// ``` -declare_lint! { - pub WHILE_LET_LOOP, - Warn, - "`loop { if let { ... } else break }` can be written as a `while let` loop" -} - -/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. -/// -/// **Why is this bad?** It is more idiomatic to use a `for` loop over the iterator instead. -/// -/// **Known problems:** None -/// -/// **Example:** `vec.iter().map(|x| /* some operation returning () */).collect::<Vec<_>>();` -declare_lint! { - pub UNUSED_COLLECT, - Warn, - "`collect()`ing an iterator without using the result; this is usually better \ - written as a for loop" -} - -/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. -/// -/// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended. -/// -/// **Known problems:** The lint cannot catch loops over dynamically defined ranges. Doing this would require simulating all possible inputs and code paths through the program, which would be complex and error-prone. -/// -/// **Examples**: `for x in 5..10-5 { .. }` (oops, stray `-`) -declare_lint! { - pub REVERSE_RANGE_LOOP, - Warn, - "Iterating over an empty range, such as `10..0` or `5..5`" -} - -/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. -/// -/// **Why is it bad?** Not only is the version using `.enumerate()` more readable, the compiler is able to remove bounds checks which can lead to faster code in some instances. -/// -/// **Known problems:** None. -/// -/// **Example:** `for i in 0..v.len() { foo(v[i]); }` or `for i in 0..v.len() { bar(i, v[i]); }` -declare_lint! { - pub EXPLICIT_COUNTER_LOOP, - Warn, - "for-looping with an explicit counter when `_.enumerate()` would do" -} - -/// **What it does:** This lint checks for empty `loop` expressions. -/// -/// **Why is this bad?** Those busy loops burn CPU cycles without doing anything. Think of the environment and either block on something or at least make the thread sleep for some microseconds. -/// -/// **Known problems:** None -/// -/// **Example:** `loop {}` -declare_lint! { - pub EMPTY_LOOP, - Warn, - "empty `loop {}` detected" -} - -/// **What it does:** This lint checks for `while let` expressions on iterators. -/// -/// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys the intent better. -/// -/// **Known problems:** None -/// -/// **Example:** `while let Some(val) = iter() { .. }` -declare_lint! { - pub WHILE_LET_ON_ITERATOR, - Warn, - "using a while-let loop instead of a for loop on an iterator" -} - -/// **What it does:** This warns when you iterate on a map (`HashMap` or `BTreeMap`) and ignore -/// either the keys or values. -/// -/// **Why is this bad?** Readability. There are `keys` and `values` methods that can be used to -/// express that don't need the values or keys. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// for (k, _) in &map { .. } -/// ``` -/// could be replaced by -/// ```rust -/// for k in map.keys() { .. } -/// ``` -declare_lint! { - pub FOR_KV_MAP, - Warn, - "looping on a map using `iter` when `keys` or `values` would do" -} - -#[derive(Copy, Clone)] -pub struct LoopsPass; - -impl LintPass for LoopsPass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP, - EXPLICIT_ITER_LOOP, - ITER_NEXT_LOOP, - WHILE_LET_LOOP, - UNUSED_COLLECT, - REVERSE_RANGE_LOOP, - EXPLICIT_COUNTER_LOOP, - EMPTY_LOOP, - WHILE_LET_ON_ITERATOR, - FOR_KV_MAP) - } -} - -impl LateLintPass for LoopsPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some((pat, arg, body)) = recover_for_loop(expr) { - check_for_loop(cx, pat, arg, body, expr); - } - // check for `loop { if let {} else break }` that could be `while let` - // (also matches an explicit "match" instead of "if let") - // (even if the "match" or "if let" is used for declaration) - if let ExprLoop(ref block, _) = expr.node { - // also check for empty `loop {}` statements - if block.stmts.is_empty() && block.expr.is_none() { - span_lint(cx, - EMPTY_LOOP, - expr.span, - "empty `loop {}` detected. You may want to either use `panic!()` or add \ - `std::thread::sleep(..);` to the loop body."); - } - - // extract the expression from the first statement (if any) in a block - let inner_stmt_expr = extract_expr_from_first_stmt(block); - // or extract the first expression (if any) from the block - if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) { - if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { - // ensure "if let" compatible match structure - match *source { - MatchSource::Normal | - MatchSource::IfLetDesugar { .. } => { - if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - is_break_expr(&arms[1].body) { - if in_external_macro(cx, expr.span) { - return; - } - - // NOTE: we used to make build a body here instead of using - // ellipsis, this was removed because: - // 1) it was ugly with big bodies; - // 2) it was not indented properly; - // 3) it wasn’t very smart (see #675). - span_lint_and_then(cx, - WHILE_LET_LOOP, - expr.span, - "this loop could be written as a `while let` loop", - |db| { - let sug = format!("while let {} = {} {{ .. }}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, "..")); - db.span_suggestion(expr.span, "try", sug); - }); - } - } - _ => (), - } - } - } - } - if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { - let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref path, Some(ref pat_args)), - &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { - let iter_expr = &method_args[0]; - if let Some(lhs_constructor) = path.segments.last() { - if method_name.node.as_str() == "next" && - match_trait_method(cx, match_expr, &paths::ITERATOR) && - lhs_constructor.name.as_str() == "Some" && - !is_iterator_used_after_while_let(cx, iter_expr) { - let iterator = snippet(cx, method_args[0].span, "_"); - let loop_var = snippet(cx, pat_args[0].span, "_"); - span_help_and_lint(cx, - WHILE_LET_ON_ITERATOR, - expr.span, - "this loop could be written as a `for` loop", - &format!("try\nfor {} in {} {{...}}", loop_var, iterator)); - } - } - } - } - } - - fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { - if let StmtSemi(ref expr, _) = stmt.node { - if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.node.as_str() == "collect" && - match_trait_method(cx, expr, &paths::ITERATOR) { - span_lint(cx, - UNUSED_COLLECT, - expr.span, - "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator"); - } - } - } - } -} - -fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - check_for_loop_range(cx, pat, arg, body, expr); - check_for_loop_reverse_range(cx, arg, expr); - check_for_loop_arg(cx, pat, arg, expr); - check_for_loop_explicit_counter(cx, arg, body, expr); - check_for_loop_over_map_kv(cx, pat, arg, body, expr); -} - -/// Check for looping over a range and then indexing a sequence with it. -/// The iteratee must be a range literal. -fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(arg) { - // the var must be a single name - if let PatKind::Ident(_, ref ident, _) = pat.node { - let mut visitor = VarVisitor { - cx: cx, - var: ident.node, - indexed: HashMap::new(), - nonindex: false, - }; - walk_expr(&mut visitor, body); - - // linting condition: we only indexed one variable - if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed - .into_iter() - .next() - .unwrap_or_else(|| unreachable!() /* len == 1 */); - - // ensure that the indexed variable was declared before the loop, see #601 - if let Some(indexed_extent) = indexed_extent { - let pat_extent = cx.tcx.region_maps.var_scope(pat.id); - if cx.tcx.region_maps.is_subscope_of(indexed_extent, pat_extent) { - return; - } - } - - let starts_at_zero = is_integer_literal(start, 0); - - let skip: Cow<_> = if starts_at_zero { - "".into() - } else { - format!(".skip({})", snippet(cx, start.span, "..")).into() - }; - - let take: Cow<_> = if let Some(ref end) = *end { - if is_len_call(end, &indexed) { - "".into() - } else { - format!(".take({})", snippet(cx, end.span, "..")).into() - } - } else { - "".into() - }; - - if visitor.nonindex { - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \ - item) in {}.iter().enumerate(){}{}` or similar iterators", - ident.node, - indexed, - ident.node, - indexed, - take, - skip)); - } else { - let repl = if starts_at_zero && take.is_empty() { - format!("&{}", indexed) - } else { - format!("{}.iter(){}{}", indexed, take, skip) - }; - - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in {}` or similar iterators", - ident.node, - indexed, - repl)); - } - } - } - } -} - -fn is_len_call(expr: &Expr, var: &Name) -> bool { - if_let_chain! {[ - let ExprMethodCall(method, _, ref len_args) = expr.node, - len_args.len() == 1, - method.node.as_str() == "len", - let ExprPath(_, ref path) = len_args[0].node, - path.segments.len() == 1, - &path.segments[0].name == var - ], { - return true; - }} - - false -} - -fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { - // if this for loop is iterating over a two-sided range... - if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(arg) { - // ...and both sides are compile-time constant integers... - if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) { - if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) { - // ...and the start index is greater than the end index, - // this loop will never run. This is often confusing for developers - // who think that this will iterate from the larger value to the - // smaller value. - let (sup, eq) = match (start_idx, end_idx) { - (ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => { - (start_idx > end_idx, start_idx == end_idx) - } - _ => (false, false), - }; - - if sup { - let start_snippet = snippet(cx, start.span, "_"); - let end_snippet = snippet(cx, end.span, "_"); - - span_lint_and_then(cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - |db| { - db.span_suggestion(expr.span, - "consider using the following if \ - you are attempting to iterate \ - over this range in reverse", - format!("({}..{}).rev()` ", end_snippet, start_snippet)); - }); - } else if eq && limits != ast::RangeLimits::Closed { - // if they are equal, it's also problematic - this loop - // will never run. - span_lint(cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run"); - } - } - } - } -} - -fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { - let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used - if let ExprMethodCall(ref method, _, ref args) = arg.node { - // just the receiver, no arguments - if args.len() == 1 { - let method_name = method.node; - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - if method_name.as_str() == "iter" || method_name.as_str() == "iter_mut" { - if is_ref_iterable_type(cx, &args[0]) { - let object = snippet(cx, args[0].span, "_"); - span_lint(cx, - EXPLICIT_ITER_LOOP, - expr.span, - &format!("it is more idiomatic to loop over `&{}{}` instead of `{}.{}()`", - if method_name.as_str() == "iter_mut" { - "mut " - } else { - "" - }, - object, - object, - method_name)); - } - } else if method_name.as_str() == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { - span_lint(cx, - ITER_NEXT_LOOP, - expr.span, - "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ - probably not what you want"); - next_loop_linted = true; - } - } - } - if !next_loop_linted { - check_arg_type(cx, pat, arg); - } -} - -/// Check for `for` loops over `Option`s and `Results` -fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { - let ty = cx.tcx.expr_ty(arg); - if match_type(cx, ty, &paths::OPTION) { - span_help_and_lint(cx, - FOR_LOOP_OVER_OPTION, - arg.span, - &format!("for loop over `{0}`, which is an `Option`. This is more readably written as an \ - `if let` statement.", - snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", - snippet(cx, pat.span, "_"), - snippet(cx, arg.span, "_"))); - } else if match_type(cx, ty, &paths::RESULT) { - span_help_and_lint(cx, - FOR_LOOP_OVER_RESULT, - arg.span, - &format!("for loop over `{0}`, which is a `Result`. This is more readably written as an \ - `if let` statement.", - snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", - snippet(cx, pat.span, "_"), - snippet(cx, arg.span, "_"))); - } -} - -fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { - // Look for variables that are incremented once per loop iteration. - let mut visitor = IncrementVisitor { - cx: cx, - states: HashMap::new(), - depth: 0, - done: false, - }; - walk_expr(&mut visitor, body); - - // For each candidate, check the parent block to see if - // it's initialized to zero at the start of the loop. - let map = &cx.tcx.map; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id)); - if let Some(parent_id) = parent_scope { - if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { - let mut visitor2 = InitializeVisitor { - cx: cx, - end_expr: expr, - var_id: *id, - state: VarState::IncrOnce, - name: None, - depth: 0, - past_loop: false, - }; - walk_block(&mut visitor2, block); - - if visitor2.state == VarState::Warn { - if let Some(name) = visitor2.name { - span_lint(cx, - EXPLICIT_COUNTER_LOOP, - expr.span, - &format!("the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ - item) in {1}.enumerate()` or similar iterators", - name, - snippet(cx, arg.span, "_"))); - } - } - } - } - } -} - -/// Check for the `FOR_KV_MAP` lint. -fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let PatKind::Tup(ref pat) = pat.node { - if pat.len() == 2 { - let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), - (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), - _ => return, - }; - - let arg_span = match arg.node { - ExprAddrOf(MutImmutable, ref expr) => expr.span, - ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method - _ => arg.span, - }; - - let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); - if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) { - span_lint_and_then(cx, - FOR_KV_MAP, - expr.span, - &format!("you seem to want to iterate on a map's {}", kind), - |db| { - db.span_suggestion(expr.span, - "use the corresponding method", - format!("for {} in {}.{}() {{...}}", - snippet(cx, *pat_span, ".."), - snippet(cx, arg_span, ".."), - kind)); - }); - } - } - } - -} - -/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. -fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { - match *pat { - PatKind::Wild => true, - PatKind::Ident(_, ident, None) if ident.node.as_str().starts_with('_') => { - let mut visitor = UsedVisitor { - var: ident.node, - used: false, - }; - walk_expr(&mut visitor, body); - !visitor.used - } - _ => false, - } -} - -struct UsedVisitor { - var: ast::Name, // var to look for - used: bool, // has the var been used otherwise? -} - -impl<'a> Visitor<'a> for UsedVisitor { - fn visit_expr(&mut self, expr: &Expr) { - if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == self.var { - self.used = true; - return; - } - } - - walk_expr(self, expr); - } -} - -struct VarVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, // context reference - var: Name, // var name to look for as index - indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global - nonindex: bool, // has the var been used otherwise? -} - -impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { - fn visit_expr(&mut self, expr: &'v Expr) { - if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == self.var { - // we are referencing our variable! now check if it's as an index - if_let_chain! { - [ - let Some(parexpr) = get_parent_expr(self.cx, expr), - let ExprIndex(ref seqexpr, _) = parexpr.node, - let ExprPath(None, ref seqvar) = seqexpr.node, - seqvar.segments.len() == 1 - ], { - let def_map = self.cx.tcx.def_map.borrow(); - if let Some(def) = def_map.get(&seqexpr.id) { - match def.base_def { - Def::Local(..) | Def::Upvar(..) => { - let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); - return; // no need to walk further - } - Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); - return; // no need to walk further - } - _ => (), - } - } - } - } - // we are not indexing anything, record that - self.nonindex = true; - return; - } - } - walk_expr(self, expr); - } -} - -fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool { - let def_id = match var_def_id(cx, iter_expr) { - Some(id) => id, - None => return false, - }; - let mut visitor = VarUsedAfterLoopVisitor { - cx: cx, - def_id: def_id, - iter_expr_id: iter_expr.id, - past_while_let: false, - var_used_after_while_let: false, - }; - if let Some(enclosing_block) = get_enclosing_block(cx, def_id) { - walk_block(&mut visitor, enclosing_block); - } - visitor.var_used_after_while_let -} - -struct VarUsedAfterLoopVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, - def_id: NodeId, - iter_expr_id: NodeId, - past_while_let: bool, - var_used_after_while_let: bool, -} - -impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> { - fn visit_expr(&mut self, expr: &'v Expr) { - if self.past_while_let { - if Some(self.def_id) == var_def_id(self.cx, expr) { - self.var_used_after_while_let = true; - } - } else if self.iter_expr_id == expr.id { - self.past_while_let = true; - } - walk_expr(self, expr); - } -} - - -/// Return true if the type of expr is one that provides `IntoIterator` impls -/// for `&T` and `&mut T`, such as `Vec`. -#[cfg_attr(rustfmt, rustfmt_skip)] -fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { - // no walk_ptrs_ty: calling iter() on a reference can make sense because it - // will allow further borrows afterwards - let ty = cx.tcx.expr_ty(e); - is_iterable_array(ty) || - match_type(cx, ty, &paths::VEC) || - match_type(cx, ty, &paths::LINKED_LIST) || - match_type(cx, ty, &paths::HASHMAP) || - match_type(cx, ty, &paths::HASHSET) || - match_type(cx, ty, &paths::VEC_DEQUE) || - match_type(cx, ty, &paths::BINARY_HEAP) || - match_type(cx, ty, &paths::BTREEMAP) || - match_type(cx, ty, &paths::BTREESET) -} - -fn is_iterable_array(ty: ty::Ty) -> bool { - // IntoIterator is currently only implemented for array sizes <= 32 in rustc - match ty.sty { - ty::TyArray(_, 0...32) => true, - _ => false, - } -} - -/// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. -fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { - if block.stmts.is_empty() { - return None; - } - if let StmtDecl(ref decl, _) = block.stmts[0].node { - if let DeclLocal(ref local) = decl.node { - if let Some(ref expr) = local.init { - Some(expr) - } else { - None - } - } else { - None - } - } else { - None - } -} - -/// If a block begins with an expression (with or without semicolon), return it. -fn extract_first_expr(block: &Block) -> Option<&Expr> { - match block.expr { - Some(ref expr) => Some(expr), - None if !block.stmts.is_empty() => { - match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), - _ => None, - } - } - _ => None, - } -} - -/// Return true if expr contains a single break expr (maybe within a block). -fn is_break_expr(expr: &Expr) -> bool { - match expr.node { - ExprBreak(None) => true, - // there won't be a `let <pat> = break` and so we can safely ignore the StmtDecl case - ExprBlock(ref b) => { - match extract_first_expr(b) { - Some(ref subexpr) => is_break_expr(subexpr), - None => false, - } - } - _ => false, - } -} - -// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be -// incremented exactly once in the loop body, and initialized to zero -// at the start of the loop. -#[derive(PartialEq)] -enum VarState { - Initial, // Not examined yet - IncrOnce, // Incremented exactly once, may be a loop counter - Declared, // Declared but not (yet) initialized to zero - Warn, - DontWarn, -} - -/// Scan a for loop for variables that are incremented exactly once. -struct IncrementVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, // context reference - states: HashMap<NodeId, VarState>, // incremented variables - depth: u32, // depth of conditional expressions - done: bool, -} - -impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> { - fn visit_expr(&mut self, expr: &'v Expr) { - if self.done { - return; - } - - // If node is a variable - if let Some(def_id) = var_def_id(self.cx, expr) { - if let Some(parent) = get_parent_expr(self.cx, expr) { - let state = self.states.entry(def_id).or_insert(VarState::Initial); - - match parent.node { - ExprAssignOp(op, ref lhs, ref rhs) => { - if lhs.id == expr.id { - if op.node == BiAdd && is_integer_literal(rhs, 1) { - *state = match *state { - VarState::Initial if self.depth == 0 => VarState::IncrOnce, - _ => VarState::DontWarn, - }; - } else { - // Assigned some other value - *state = VarState::DontWarn; - } - } - } - ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, - ExprAddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn, - _ => (), - } - } - } else if is_loop(expr) { - self.states.clear(); - self.done = true; - return; - } else if is_conditional(expr) { - self.depth += 1; - walk_expr(self, expr); - self.depth -= 1; - return; - } - walk_expr(self, expr); - } -} - -/// Check whether a variable is initialized to zero at the start of a loop. -struct InitializeVisitor<'v, 't: 'v> { - cx: &'v LateContext<'v, 't>, // context reference - end_expr: &'v Expr, // the for loop. Stop scanning here. - var_id: NodeId, - state: VarState, - name: Option<Name>, - depth: u32, // depth of conditional expressions - past_loop: bool, -} - -impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { - fn visit_decl(&mut self, decl: &'v Decl) { - // Look for declarations of the variable - if let DeclLocal(ref local) = decl.node { - if local.pat.id == self.var_id { - if let PatKind::Ident(_, ref ident, _) = local.pat.node { - self.name = Some(ident.node); - - self.state = if let Some(ref init) = local.init { - if is_integer_literal(init, 0) { - VarState::Warn - } else { - VarState::Declared - } - } else { - VarState::Declared - } - } - } - } - walk_decl(self, decl); - } - - fn visit_expr(&mut self, expr: &'v Expr) { - if self.state == VarState::DontWarn { - return; - } - if expr == self.end_expr { - self.past_loop = true; - return; - } - // No need to visit expressions before the variable is - // declared - if self.state == VarState::IncrOnce { - return; - } - - // If node is the desired variable, see how it's used - if var_def_id(self.cx, expr) == Some(self.var_id) { - if let Some(parent) = get_parent_expr(self.cx, expr) { - match parent.node { - ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => { - self.state = VarState::DontWarn; - } - ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { - self.state = if is_integer_literal(rhs, 0) && self.depth == 0 { - VarState::Warn - } else { - VarState::DontWarn - } - } - ExprAddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn, - _ => (), - } - } - - if self.past_loop { - self.state = VarState::DontWarn; - return; - } - } else if !self.past_loop && is_loop(expr) { - self.state = VarState::DontWarn; - return; - } else if is_conditional(expr) { - self.depth += 1; - walk_expr(self, expr); - self.depth -= 1; - return; - } - walk_expr(self, expr); - } -} - -fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { - if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { - if let Def::Local(_, node_id) = path_res.base_def { - return Some(node_id); - } - } - None -} - -fn is_loop(expr: &Expr) -> bool { - match expr.node { - ExprLoop(..) | ExprWhile(..) => true, - _ => false, - } -} - -fn is_conditional(expr: &Expr) -> bool { - match expr.node { - ExprIf(..) | ExprMatch(..) => true, - _ => false, - } -} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000000..970222e1076 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,167 @@ +// error-pattern:yummy +#![feature(box_syntax)] +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate getopts; +extern crate rustc; +extern crate syntax; +extern crate rustc_plugin; +extern crate clippy_lints; + +use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use rustc::session::{config, Session}; +use rustc::session::config::{Input, ErrorOutputType}; +use syntax::diagnostics; +use std::path::PathBuf; +use std::process::Command; + +struct ClippyCompilerCalls(RustcDefaultCalls); + +impl std::default::Default for ClippyCompilerCalls { + fn default() -> Self { + Self::new() + } +} + +impl ClippyCompilerCalls { + fn new() -> Self { + ClippyCompilerCalls(RustcDefaultCalls) + } +} + +impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { + fn early_callback(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + descriptions: &diagnostics::registry::Registry, + output: ErrorOutputType) + -> Compilation { + self.0.early_callback(matches, sopts, descriptions, output) + } + fn no_input(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + odir: &Option<PathBuf>, + ofile: &Option<PathBuf>, + descriptions: &diagnostics::registry::Registry) + -> Option<(Input, Option<PathBuf>)> { + self.0.no_input(matches, sopts, odir, ofile, descriptions) + } + fn late_callback(&mut self, + matches: &getopts::Matches, + sess: &Session, + input: &Input, + odir: &Option<PathBuf>, + ofile: &Option<PathBuf>) + -> Compilation { + self.0.late_callback(matches, sess, input, odir, ofile) + } + fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { + let mut control = self.0.build_controller(sess, matches); + + let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); + control.after_parse.callback = Box::new(move |state| { + { + let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed")); + registry.args_hidden = Some(Vec::new()); + clippy_lints::register_plugins(&mut registry); + + let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } + + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } + + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.mir_passes.borrow_mut().extend(mir_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + } + old(state); + }); + + control + } +} + +use std::path::Path; + +pub fn main() { + use std::env; + + if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { + panic!("yummy"); + } + + let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps"); + + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + let sys_root = match (home, toolchain) { + (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), + _ => option_env!("SYSROOT").map(|s| s.to_owned()) + .or(Command::new("rustc").arg("--print") + .arg("sysroot") + .output().ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + ) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"), + }; + + if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { + let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); + let path = std::env::current_exe().expect("current executable path invalid"); + let exit_status = std::process::Command::new("cargo") + .args(&args) + .env("RUSTC", path) + .spawn().expect("could not run cargo") + .wait().expect("failed to wait for cargo?"); + + if let Some(code) = exit_status.code() { + std::process::exit(code); + } + } else { + let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { + env::args().collect() + } else { + env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() + }; + let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); + + if let Err(err_count) = result { + if err_count > 0 { + std::process::exit(1); + } + } + } +} + +fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String> + where P: AsRef<Path>, I: Iterator<Item=String> { + + let mut args = vec!["rustc".to_owned()]; + + let mut found_dashes = false; + for arg in old_args { + found_dashes |= arg == "--"; + args.push(arg); + } + if !found_dashes { + args.push("--".to_owned()); + } + args.push("-L".to_owned()); + args.push(dep_path.as_ref().to_string_lossy().into_owned()); + args.push(String::from("--sysroot")); + args.push(sysroot); + args.push("-Zno-trans".to_owned()); + args +} diff --git a/src/map_clone.rs b/src/map_clone.rs deleted file mode 100644 index 4ad232759cf..00000000000 --- a/src/map_clone.rs +++ /dev/null @@ -1,128 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use syntax::ast; -use utils::{is_adjusted, match_path, match_trait_method, match_type, paths, snippet, - span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; - -/// **What it does:** This lint checks for mapping clone() over an iterator. -/// -/// **Why is this bad?** It makes the code less readable. -/// -/// **Known problems:** None -/// -/// **Example:** `x.map(|e| e.clone());` -declare_lint! { - pub MAP_CLONE, Warn, - "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \ - `.cloned()` instead)" -} - -#[derive(Copy, Clone)] -pub struct MapClonePass; - -impl LateLintPass for MapClonePass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - // call to .map() - if let ExprMethodCall(name, _, ref args) = expr.node { - if name.node.as_str() == "map" && args.len() == 2 { - match args[1].node { - ExprClosure(_, ref decl, ref blk, _) => { - if_let_chain! { - [ - // just one expression in the closure - blk.stmts.is_empty(), - let Some(ref closure_expr) = blk.expr, - // nothing special in the argument, besides reference bindings - // (e.g. .map(|&x| x) ) - let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), - // the method is being called on a known type (option or iterator) - let Some(type_name) = get_type_name(cx, expr, &args[0]) - ], { - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.node.as_str() == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(&clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - } - } - } - ExprPath(_, ref path) => { - if match_path(path, &paths::CLONE) { - let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint(cx, - MAP_CLONE, - expr.span, - &format!("you seem to be using .map() to clone the contents of an \ - {}, consider using `.cloned()`", - type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - _ => (), - } - } - } - } -} - -fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { - match expr.node { - ExprPath(None, ref path) => { - let arg_segment = [PathSegment { - name: id, - parameters: PathParameters::none(), - }]; - !path.global && path.segments[..] == arg_segment - } - _ => false, - } -} - -fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { - if match_trait_method(cx, expr, &paths::ITERATOR) { - Some("iterator") - } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) { - Some("Option") - } else { - None - } -} - -fn get_arg_name(pat: &Pat) -> Option<ast::Name> { - match pat.node { - PatKind::Ident(_, name, None) => Some(name.node), - PatKind::Ref(ref subpat, _) => get_arg_name(subpat), - _ => None, - } -} - -fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { - match expr.node { - ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), - _ => expr_eq_name(expr, id), - } -} - -impl LintPass for MapClonePass { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_CLONE) - } -} diff --git a/src/matches.rs b/src/matches.rs deleted file mode 100644 index db4ccf2dcdb..00000000000 --- a/src/matches.rs +++ /dev/null @@ -1,483 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use rustc_const_math::ConstInt; -use std::cmp::Ordering; -use syntax::ast::LitKind; -use syntax::codemap::Span; -use utils::paths; -use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; - -/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. -/// -/// **Why is this bad?** Just readability – `if let` nests less than a `match`. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// match x { -/// Some(ref foo) -> bar(foo), -/// _ => () -/// } -/// ``` -declare_lint! { - pub SINGLE_MATCH, Warn, - "a match statement with a single nontrivial arm (i.e, where the other arm \ - is `_ => {}`) is used; recommends `if let` instead" -} - -/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. -/// -/// **Why is this bad?** Just readability – `if let` nests less than a `match`. -/// -/// **Known problems:** Personal style preferences may differ -/// -/// **Example:** -/// ``` -/// match x { -/// Some(ref foo) -> bar(foo), -/// _ => bar(other_ref), -/// } -/// ``` -declare_lint! { - pub SINGLE_MATCH_ELSE, Allow, - "a match statement with a two arms where the second arm's pattern is a wildcard; \ - recommends `if let` instead" -} - -/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. -/// -/// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code. -/// -/// **Known problems:** None -/// -/// **Example:** -/// -/// ``` -/// match x { -/// &A(ref y) => foo(y), -/// &B => bar(), -/// _ => frob(&x), -/// } -/// ``` -declare_lint! { - pub MATCH_REF_PATS, Warn, - "a match or `if let` has all arms prefixed with `&`; the match expression can be \ - dereferenced instead" -} - -/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. -/// -/// **Why is this bad?** It makes the code less readable. -/// -/// **Known problems:** None -/// -/// **Example:** -/// -/// ``` -/// let condition: bool = true; -/// match condition { -/// true => foo(), -/// false => bar(), -/// } -/// ``` -declare_lint! { - pub MATCH_BOOL, Warn, - "a match on boolean expression; recommends `if..else` block instead" -} - -/// **What it does:** This lint checks for overlapping match arms. -/// -/// **Why is this bad?** It is likely to be an error and if not, makes the code less obvious. -/// -/// **Known problems:** None -/// -/// **Example:** -/// -/// ``` -/// let x = 5; -/// match x { -/// 1 ... 10 => println!("1 ... 10"), -/// 5 ... 15 => println!("5 ... 15"), -/// _ => (), -/// } -/// ``` -declare_lint! { - pub MATCH_OVERLAPPING_ARM, Warn, "a match has overlapping arms" -} - -#[allow(missing_copy_implementations)] -pub struct MatchPass; - -impl LintPass for MatchPass { - fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL, SINGLE_MATCH_ELSE) - } -} - -impl LateLintPass for MatchPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { - return; - } - if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { - check_single_match(cx, ex, arms, expr); - check_match_bool(cx, ex, arms, expr); - check_overlapping_arms(cx, ex, arms); - } - if let ExprMatch(ref ex, ref arms, source) = expr.node { - check_match_ref_pats(cx, ex, arms, source, expr); - } - } -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { - if arms.len() == 2 && - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() { - let els = if is_unit_expr(&arms[1].body) { - None - } else if let ExprBlock(_) = arms[1].body.node { - // matches with blocks that contain statements are prettier as `if let + else` - Some(&*arms[1].body) - } else { - // allow match arms with just expressions - return; - }; - let ty = cx.tcx.expr_ty(ex); - if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { - check_single_match_single_pattern(cx, ex, arms, expr, els); - check_single_match_opt_like(cx, ex, arms, expr, ty, els); - } - } -} - -fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { - if arms[1].pats[0].node == PatKind::Wild { - let lint = if els.is_some() { - SINGLE_MATCH_ELSE - } else { - SINGLE_MATCH - }; - let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); - span_lint_and_then(cx, - lint, - expr.span, - "you seem to be trying to use match for destructuring a single pattern. \ - Consider using `if let`", - |db| { - db.span_suggestion(expr.span, - "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); - } -} - -fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) { - // list of candidate Enums we know will never get any more members - let candidates = &[(&paths::COW, "Borrowed"), - (&paths::COW, "Cow::Borrowed"), - (&paths::COW, "Cow::Owned"), - (&paths::COW, "Owned"), - (&paths::OPTION, "None"), - (&paths::RESULT, "Err"), - (&paths::RESULT, "Ok")]; - - let path = match arms[1].pats[0].node { - PatKind::TupleStruct(ref path, Some(ref inner)) => { - // contains any non wildcard patterns? e.g. Err(err) - if inner.iter().any(|pat| pat.node != PatKind::Wild) { - return; - } - path.to_string() - } - PatKind::TupleStruct(ref path, None) => path.to_string(), - PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), - _ => return, - }; - - for &(ty_path, pat_path) in candidates { - if &path == pat_path && match_type(cx, ty, ty_path) { - let lint = if els.is_some() { - SINGLE_MATCH_ELSE - } else { - SINGLE_MATCH - }; - let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); - span_lint_and_then(cx, - lint, - expr.span, - "you seem to be trying to use match for destructuring a single pattern. Consider \ - using `if let`", - |db| { - db.span_suggestion(expr.span, - "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); - } - } -} - -fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { - // type of expression == bool - if cx.tcx.expr_ty(ex).sty == ty::TyBool { - let sugg = if arms.len() == 2 && arms[0].pats.len() == 1 { - // no guards - let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { - if let ExprLit(ref lit) = arm_bool.node { - match lit.node { - LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), - LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), - _ => None, - } - } else { - None - } - } else { - None - }; - - if let Some((ref true_expr, ref false_expr)) = exprs { - match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => { - Some(format!("if {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))) - } - (false, true) => { - Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) - } - (true, false) => { - Some(format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, false_expr, None, ".."))) - } - (true, true) => None, - } - } else { - None - } - } else { - None - }; - - span_lint_and_then(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an if..else block:", - move |db| { - if let Some(sugg) = sugg { - db.span_suggestion(expr.span, "try this", sugg); - } - }); - } -} - -fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { - if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() { - let ranges = all_ranges(cx, arms); - let type_ranges = type_ranges(&ranges); - if !type_ranges.is_empty() { - if let Some((start, end)) = overlapping(&type_ranges) { - span_note_and_lint(cx, - MATCH_OVERLAPPING_ARM, - start.span, - "some ranges overlap", - end.span, - "overlaps with this"); - } - } - } -} - -fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { - if has_only_ref_pats(arms) { - if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - let template = match_template(cx, expr.span, source, "", inner); - span_lint_and_then(cx, - MATCH_REF_PATS, - expr.span, - "you don't need to add `&` to both the expression and the patterns", - |db| { - db.span_suggestion(expr.span, "try", template); - }); - } else { - let template = match_template(cx, expr.span, source, "*", ex); - span_lint_and_then(cx, - MATCH_REF_PATS, - expr.span, - "you don't need to add `&` to all patterns", - |db| { - db.span_suggestion(expr.span, - "instead of prefixing all patterns with `&`, you can \ - dereference the expression", - template); - }); - } - } -} - -/// Get all arms that are unbounded `PatRange`s. -fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { - arms.iter() - .filter_map(|arm| { - if let Arm { ref pats, guard: None, .. } = *arm { - Some(pats.iter().filter_map(|pat| { - if_let_chain! {[ - let PatKind::Range(ref lhs, ref rhs) = pat.node, - let Ok(lhs) = eval_const_expr_partial(cx.tcx, &lhs, ExprTypeChecked, None), - let Ok(rhs) = eval_const_expr_partial(cx.tcx, &rhs, ExprTypeChecked, None) - ], { - return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); - }} - - if_let_chain! {[ - let PatKind::Lit(ref value) = pat.node, - let Ok(value) = eval_const_expr_partial(cx.tcx, &value, ExprTypeChecked, None) - ], { - return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); - }} - - None - })) - } else { - None - } - }) - .flat_map(IntoIterator::into_iter) - .collect() -} - -#[derive(Debug, Eq, PartialEq)] -pub struct SpannedRange<T> { - pub span: Span, - pub node: (T, T), -} - -type TypedRanges = Vec<SpannedRange<ConstInt>>; - -/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than -/// `Uint` and `Int` probably don't make sense. -fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { - ranges.iter() - .filter_map(|range| { - if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect() -} - -fn is_unit_expr(expr: &Expr) -> bool { - match expr.node { - ExprTup(ref v) if v.is_empty() => true, - ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, - _ => false, - } -} - -fn has_only_ref_pats(arms: &[Arm]) -> bool { - let mapped = arms.iter() - .flat_map(|a| &a.pats) - .map(|p| { - match p.node { - PatKind::Ref(..) => Some(true), // &-patterns - PatKind::Wild => Some(false), // an "anything" wildcard is also fine - _ => None, // any other pattern is not fine - } - }) - .collect::<Option<Vec<bool>>>(); - // look for Some(v) where there's at least one true element - mapped.map_or(false, |v| v.iter().any(|el| *el)) -} - -fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, expr: &Expr) -> String { - let expr_snippet = snippet(cx, expr.span, ".."); - match source { - MatchSource::Normal => format!("match {}{} {{ .. }}", op, expr_snippet), - MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), - MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), - MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), - MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"), - } -} - -pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> - where T: Copy + Ord -{ - #[derive(Copy, Clone, Debug, Eq, PartialEq)] - enum Kind<'a, T: 'a> { - Start(T, &'a SpannedRange<T>), - End(T, &'a SpannedRange<T>), - } - - impl<'a, T: Copy> Kind<'a, T> { - fn range(&self) -> &'a SpannedRange<T> { - match *self { - Kind::Start(_, r) | - Kind::End(_, r) => r, - } - } - - fn value(self) -> T { - match self { - Kind::Start(t, _) | - Kind::End(t, _) => t, - } - } - } - - impl<'a, T: Copy + Ord> PartialOrd for Kind<'a, T> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } - } - - impl<'a, T: Copy + Ord> Ord for Kind<'a, T> { - fn cmp(&self, other: &Self) -> Ordering { - self.value().cmp(&other.value()) - } - } - - let mut values = Vec::with_capacity(2 * ranges.len()); - - for r in ranges { - values.push(Kind::Start(r.node.0, r)); - values.push(Kind::End(r.node.1, r)); - } - - values.sort(); - - for (a, b) in values.iter().zip(values.iter().skip(1)) { - match (a, b) { - (&Kind::Start(_, ra), &Kind::End(_, rb)) => { - if ra.node != rb.node { - return Some((ra, rb)); - } - } - (&Kind::End(a, _), &Kind::Start(b, _)) if a != b => (), - _ => return Some((a.range(), b.range())), - } - } - - None -} diff --git a/src/mem_forget.rs b/src/mem_forget.rs deleted file mode 100644 index 1f627d614ff..00000000000 --- a/src/mem_forget.rs +++ /dev/null @@ -1,44 +0,0 @@ -use rustc::lint::*; -use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{match_def_path, paths, span_lint}; - -/// **What it does:** This lint checks for usage of `std::mem::forget(t)` where `t` is `Drop`. -/// -/// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its destructor, possibly causing leaks -/// -/// **Known problems:** None. -/// -/// **Example:** `mem::forget(Rc::new(55)))` -declare_lint! { - pub MEM_FORGET, - Allow, - "`mem::forget` usage on `Drop` types is likely to cause memory leaks" -} - -pub struct MemForget; - -impl LintPass for MemForget { - fn get_lints(&self) -> LintArray { - lint_array![MEM_FORGET] - } -} - -impl LateLintPass for MemForget { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(None, _) = path_expr.node { - let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - if match_def_path(cx, def_id, &paths::MEM_FORGET) { - let forgot_ty = cx.tcx.expr_ty(&args[0]); - - if match forgot_ty.ty_adt_def() { - Some(def) => def.has_dtor(), - _ => false - } { - span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); - } - } - } - } - } -} diff --git a/src/methods.rs b/src/methods.rs deleted file mode 100644 index f9f557e7a9a..00000000000 --- a/src/methods.rs +++ /dev/null @@ -1,1049 +0,0 @@ -use rustc::hir; -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc::middle::const_qualif::ConstQualif; -use rustc::ty::subst::{Subst, TypeSpace}; -use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use std::borrow::Cow; -use std::fmt; -use syntax::codemap::Span; -use syntax::ptr::P; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, - span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; -use utils::MethodArgs; -use utils::paths; - -#[derive(Clone)] -pub struct MethodsPass; - -/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. -/// -/// **Why is this bad?** Usually it is better to handle the `None` case, or to at least call `.expect(_)` with a more helpful message. Still, for a lot of quick-and-dirty code, `unwrap` is a good choice, which is why this lint is `Allow` by default. -/// -/// **Known problems:** None -/// -/// **Example:** `x.unwrap()` -declare_lint! { - pub OPTION_UNWRAP_USED, Allow, - "using `Option.unwrap()`, which should at least get a better message using `expect()`" -} - -/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. -/// -/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`. -/// -/// Even if you want to panic on errors, not all `Error`s implement good messages on display. Therefore it may be beneficial to look at the places where they may get displayed. Activate this lint to do just that. -/// -/// **Known problems:** None -/// -/// **Example:** `x.unwrap()` -declare_lint! { - pub RESULT_UNWRAP_USED, Allow, - "using `Result.unwrap()`, which might be better handled" -} - -/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. -/// -/// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them. -/// -/// **Known problems:** None -/// -/// **Example:** -/// ``` -/// struct X; -/// impl X { -/// fn add(&self, other: &X) -> X { .. } -/// } -/// ``` -declare_lint! { - pub SHOULD_IMPLEMENT_TRAIT, Warn, - "defining a method that should be implementing a std trait" -} - -/// **What it does:** This lint checks for methods with certain name prefixes and which doesn't match how self is taken. The actual rules are: -/// -/// |Prefix |`self` taken | -/// |-------|--------------------| -/// |`as_` |`&self` or &mut self| -/// |`from_`| none | -/// |`into_`|`self` | -/// |`is_` |`&self` or none | -/// |`to_` |`&self` | -/// -/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_..` function. -/// -/// **Known problems:** None -/// -/// **Example** -/// -/// ``` -/// impl X { -/// fn as_str(self) -> &str { .. } -/// } -/// ``` -declare_lint! { - pub WRONG_SELF_CONVENTION, Warn, - "defining a method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" -} - -/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. -/// -/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). -/// -/// **Known problems:** Actually *renaming* the function may break clients if the function is part of the public interface. In that case, be mindful of the stability guarantees you've given your users. -/// -/// **Example:** -/// ``` -/// impl X { -/// pub fn as_str(self) -> &str { .. } -/// } -/// ``` -declare_lint! { - pub WRONG_PUB_SELF_CONVENTION, Allow, - "defining a public method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" -} - -/// **What it does:** This lint checks for usage of `ok().expect(..)`. -/// -/// **Why is this bad?** Because you usually call `expect()` on the `Result` directly to get a good error message. -/// -/// **Known problems:** None. -/// -/// **Example:** `x.ok().expect("why did I do this again?")` -declare_lint! { - pub OK_EXPECT, Warn, - "using `ok().expect()`, which gives worse error messages than \ - calling `expect` directly on the Result" -} - -/// **What it does:** This lint checks for usage of `_.map(_).unwrap_or(_)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or(_, _)`. -/// -/// **Known problems:** None. -/// -/// **Example:** `x.map(|a| a + 1).unwrap_or(0)` -declare_lint! { - pub OPTION_MAP_UNWRAP_OR, Warn, - "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ - `map_or(a, f)`" -} - -/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or_else(_, _)`. -/// -/// **Known problems:** None. -/// -/// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)` -declare_lint! { - pub OPTION_MAP_UNWRAP_OR_ELSE, Warn, - "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`" -} - -/// **What it does:** This lint `Warn`s on `_.filter(_).next()`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as `_.find(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** `iter.filter(|x| x == 0).next()` -declare_lint! { - pub FILTER_NEXT, Warn, - "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" -} - -/// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or -/// `rposition()`) followed by a call to `is_some()`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as `_.any(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** `iter.find(|x| x == 0).is_some()` -declare_lint! { - pub SEARCH_IS_SOME, Warn, - "using an iterator search followed by `is_some()`, which is more succinctly \ - expressed as a call to `any()`" -} - -/// **What it does:** This lint `Warn`s on using `.chars().next()` on a `str` to check if it -/// starts with a given char. -/// -/// **Why is this bad?** Readability, this can be written more concisely as `_.starts_with(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** `name.chars().next() == Some('_')` -declare_lint! { - pub CHARS_NEXT_CMP, Warn, - "using `.chars().next()` to check if a string starts with a char" -} - -/// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and -/// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead. -/// -/// **Why is this bad?** The function will always be called and potentially allocate an object -/// in expressions such as: -/// ```rust -/// foo.unwrap_or(String::new()) -/// ``` -/// this can instead be written: -/// ```rust -/// foo.unwrap_or_else(String::new) -/// ``` -/// or -/// ```rust -/// foo.unwrap_or_default() -/// ``` -/// -/// **Known problems:** If the function as side-effects, not calling it will change the semantic of -/// the program, but you shouldn't rely on that anyway. -declare_lint! { - pub OR_FUN_CALL, Warn, - "using any `*or` method when the `*or_else` would do" -} - -/// **What it does:** This lint checks for usage of `.extend(s)` on a `Vec` to extend the vector by a slice. -/// -/// **Why is this bad?** Since Rust 1.6, the `extend_from_slice(_)` method is stable and at least for now faster. -/// -/// **Known problems:** None. -/// -/// **Example:** `my_vec.extend(&xs)` -declare_lint! { - pub EXTEND_FROM_SLICE, Warn, - "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice" -} - -/// **What it does:** This lint warns on using `.clone()` on a `Copy` type. -/// -/// **Why is this bad?** The only reason `Copy` types implement `Clone` is for generics, not for -/// using the `clone` method on a concrete type. -/// -/// **Known problems:** None. -/// -/// **Example:** `42u64.clone()` -declare_lint! { - pub CLONE_ON_COPY, Warn, "using `clone` on a `Copy` type" -} - -/// **What it does:** This lint warns on using `.clone()` on an `&&T` -/// -/// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of cloning the underlying -/// `T` -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn main() { -/// let x = vec![1]; -/// let y = &&x; -/// let z = y.clone(); -/// println!("{:p} {:p}",*y, z); // prints out the same pointer -/// } -/// ``` -declare_lint! { - pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`" -} - -/// **What it does:** This lint warns about `new` not returning `Self`. -/// -/// **Why is this bad?** As a convention, `new` methods are used to make a new instance of a type. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// impl Foo { -/// fn new(..) -> NotAFoo { -/// } -/// } -/// ``` -declare_lint! { - pub NEW_RET_NO_SELF, Warn, "not returning `Self` in a `new` method" -} - -/// **What it does:** This lint checks for string methods that receive a single-character `str` as an argument, e.g. `_.split("x")`. -/// -/// **Why is this bad?** Performing these methods using a `char` is faster than using a `str`. -/// -/// **Known problems:** Does not catch multi-byte unicode characters. -/// -/// **Example:** `_.split("x")` could be `_.split('x')` -declare_lint! { - pub SINGLE_CHAR_PATTERN, - Warn, - "using a single-character str where a char could be used, e.g. \ - `_.split(\"x\")`" -} - -/// **What it does:** This lint checks for getting the inner pointer of a temporary `CString`. -/// -/// **Why is this bad?** The inner pointer of a `CString` is only valid as long as the `CString` is -/// alive. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// let c_str = CString::new("foo").unwrap().as_ptr(); -/// unsafe { -/// call_some_ffi_func(c_str); -/// } -/// ``` -/// Here `c_str` point to a freed address. The correct use would be: -/// ```rust,ignore -/// let c_str = CString::new("foo").unwrap(); -/// unsafe { -/// call_some_ffi_func(c_str.as_ptr()); -/// } -/// ``` -declare_lint! { - pub TEMPORARY_CSTRING_AS_PTR, - Warn, - "getting the inner pointer of a temporary `CString`" -} - -impl LintPass for MethodsPass { - fn get_lints(&self) -> LintArray { - lint_array!(EXTEND_FROM_SLICE, - OPTION_UNWRAP_USED, - RESULT_UNWRAP_USED, - SHOULD_IMPLEMENT_TRAIT, - WRONG_SELF_CONVENTION, - WRONG_PUB_SELF_CONVENTION, - OK_EXPECT, - OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE, - OR_FUN_CALL, - CHARS_NEXT_CMP, - CLONE_ON_COPY, - CLONE_DOUBLE_REF, - NEW_RET_NO_SELF, - SINGLE_CHAR_PATTERN, - SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR) - } -} - -impl LateLintPass for MethodsPass { - fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { - if in_macro(cx, expr.span) { - return; - } - - match expr.node { - hir::ExprMethodCall(name, _, ref args) => { - // Chain calls - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - lint_unwrap(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { - lint_ok_expect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { - lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { - lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { - lint_filter_next(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { - lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { - lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { - lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { - lint_extend(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { - lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); - } - - lint_or_fun_call(cx, expr, &name.node.as_str(), args); - - let self_ty = cx.tcx.expr_ty_adjusted(&args[0]); - if args.len() == 1 && name.node.as_str() == "clone" { - lint_clone_on_copy(cx, expr); - lint_clone_double_ref(cx, expr, &args[0], self_ty); - } - - match self_ty.sty { - ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => { - for &(method, pos) in &PATTERN_METHODS { - if name.node.as_str() == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); - } - } - } - _ => (), - } - } - hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { - if !lint_chars_next(cx, expr, lhs, rhs, op.node == hir::BiEq) { - lint_chars_next(cx, expr, rhs, lhs, op.node == hir::BiEq); - } - } - _ => (), - } - } - - fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { - if in_external_macro(cx, item.span) { - return; - } - - if let hir::ItemImpl(_, _, _, None, _, ref items) = item.node { - for implitem in items { - let name = implitem.name; - if_let_chain! {[ - let hir::ImplItemKind::Method(ref sig, _) = implitem.node, - let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), - ], { - // check missing trait implementations - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if name.as_str() == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(&sig.decl.output) && - self_kind.matches(&explicit_self, false) { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); - } - } - - // check conventions w.r.t. conversion method names and predicates - let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; - let is_copy = is_copy(cx, ty, item); - for &(ref conv, self_kinds) in &CONVENTIONS { - if_let_chain! {[ - conv.check(&name.as_str()), - let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), - !self_kinds.iter().any(|k| k.matches(&explicit_self, is_copy)), - ], { - let lint = if item.vis == hir::Visibility::Public { - WRONG_PUB_SELF_CONVENTION - } else { - WRONG_SELF_CONVENTION - }; - span_lint(cx, - lint, - explicit_self.span, - &format!("methods called `{}` usually take {}; consider choosing a less \ - ambiguous name", - conv, - &self_kinds.iter() - .map(|k| k.description()) - .collect::<Vec<_>>() - .join(" or "))); - }} - } - - let ret_ty = return_ty(cx, implitem.id); - if &name.as_str() == &"new" && - !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { - span_lint(cx, - NEW_RET_NO_SELF, - explicit_self.span, - "methods called `new` usually return `Self`"); - } - } - }} - } - } -} - -/// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hir::Expr>]) { - /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. - fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, - or_has_args: bool, span: Span) - -> bool { - if or_has_args { - return false; - } - - if name == "unwrap_or" { - if let hir::ExprPath(_, ref path) = fun.node { - let path: &str = &path.segments - .last() - .expect("A path must have at least one segment") - .name - .as_str(); - - if ["default", "new"].contains(&path) { - let arg_ty = cx.tcx.expr_ty(arg); - let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { - default_trait_id - } else { - return false; - }; - - if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) { - span_lint(cx, - OR_FUN_CALL, - span, - &format!("use of `{}` followed by a call to `{}`", name, path)) - .span_suggestion(span, - "try this", - format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); - return true; - } - } - } - } - - false - } - - /// Check for `*or(foo())`. - fn check_general_case(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, - span: Span) { - // don't lint for constant values - // FIXME: can we `expect` here instead of match? - if let Some(qualif) = cx.tcx.const_qualif_map.borrow().get(&arg.id) { - if !qualif.contains(ConstQualif::NOT_CONST) { - return; - } - } - // (path, fn_has_argument, methods, suffix) - let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::OPTION, - false, - &["map_or", "ok_or", "or", "unwrap_or"], - "else"), - (&paths::RESULT, true, &["or", "unwrap_or"], "else")]; - - let self_ty = cx.tcx.expr_ty(self_expr); - - let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = - know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) { - (fn_has_arguments, poss, suffix) - } else { - return; - }; - - if !poss.contains(&name) { - return; - } - - let sugg: Cow<_> = match (fn_has_arguments, !or_has_args) { - (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), - (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), - (false, true) => snippet(cx, fun.span, ".."), - }; - - span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) - .span_suggestion(span, - "try this", - format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); - } - - if args.len() == 2 { - if let hir::ExprCall(ref fun, ref or_args) = args[1].node { - let or_has_args = !or_args.is_empty(); - if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { - check_general_case(cx, name, fun, &args[0], &args[1], or_has_args, expr.span); - } - } - } -} - -/// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) { - let ty = cx.tcx.expr_ty(expr); - let parent = cx.tcx.map.get_parent(expr.id); - let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); - - if !ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, expr.span) { - span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type"); - } -} - -/// Checks for the `CLONE_DOUBLE_REF` lint. -fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) { - if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { - if let ty::TyRef(..) = inner.sty { - let mut db = span_lint(cx, - CLONE_DOUBLE_REF, - expr.span, - "using `clone` on a double-reference; \ - this will copy the reference instead of cloning \ - the inner type"); - if let Some(snip) = snippet_opt(cx, arg.span) { - db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); - } - } - } -} - -fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0])); - if !match_type(cx, obj_ty, &paths::VEC) { - return; - } - let arg_ty = cx.tcx.expr_ty(&args[1]); - if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { - span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice") - .span_suggestion(expr.span, - "try this", - format!("{}.extend_from_slice({}{})", - snippet(cx, args[0].span, "_"), - r, - snippet(cx, span, "_"))); - } -} - -fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { - if_let_chain!{[ - let hir::ExprCall(ref fun, ref args) = new.node, - args.len() == 1, - let hir::ExprPath(None, ref path) = fun.node, - match_path(path, &paths::CSTRING_NEW), - ], { - span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, - "you are getting the inner pointer of a temporary `CString`", - |db| { - db.note("that pointer will be invalid outside this expression"); - db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); - }); - }} -} - -fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { - fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { - match ty.sty { - ty::TySlice(_) => true, - ty::TyStruct(..) => match_type(cx, ty, &paths::VEC), - ty::TyArray(_, size) => size < 32, - ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => may_slice(cx, inner), - _ => false, - } - } - if let hir::ExprMethodCall(name, _, ref args) = expr.node { - if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { - Some((args[0].span, "&")) - } else { - None - } - } else { - match ty.sty { - ty::TySlice(_) => Some((expr.span, "")), - ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | - ty::TyBox(ref inner) => { - if may_slice(cx, inner) { - Some((expr.span, "")) - } else { - None - } - } - _ => None, - } - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `unwrap()` for `Option`s and `Result`s -fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0])); - - let mess = if match_type(cx, obj_ty, &paths::OPTION) { - Some((OPTION_UNWRAP_USED, "an Option", "None")) - } else if match_type(cx, obj_ty, &paths::RESULT) { - Some((RESULT_UNWRAP_USED, "a Result", "Err")) - } else { - None - }; - - if let Some((lint, kind, none_value)) = mess { - span_lint(cx, - lint, - expr.span, - &format!("used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ - using expect() to provide a better panic - message", - kind, - none_value)); - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) { - // lint if the caller of `ok()` is a `Result` - if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) { - let result_type = cx.tcx.expr_ty(&ok_args[0]); - if let Some(error_type) = get_error_type(cx, result_type) { - if has_debug_impl(error_type, cx) { - span_lint(cx, - OK_EXPECT, - expr.span, - "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`"); - } - } - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { - // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { - // lint message - let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ - `map_or(a, f)` instead"; - // get snippets for args to map() and unwrap_or() - let map_snippet = snippet(cx, map_args[1].span, ".."); - let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or() have the same span - let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; - if same_span && !multiline { - span_note_and_lint(cx, - OPTION_MAP_UNWRAP_OR, - expr.span, - msg, - expr.span, - &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", - map_snippet, - unwrap_snippet)); - } else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); - }; - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) { - // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) { - // lint message - let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ - `map_or_else(g, f)` instead"; - // get snippets for args to map() and unwrap_or_else() - let map_snippet = snippet(cx, map_args[1].span, ".."); - let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or_else() have the same span - let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id; - if same_span && !multiline { - span_note_and_lint(cx, - OPTION_MAP_UNWRAP_OR_ELSE, - expr.span, - msg, - expr.span, - &format!("replace `map({0}).unwrap_or_else({1})` with `with map_or_else({1}, {0})`", - map_snippet, - unwrap_snippet)); - } else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); - }; - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint use of `filter().next() for Iterators` -fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs) { - // lint if caller of `.filter().next()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ - instead."; - let filter_snippet = snippet(cx, filter_args[1].span, ".."); - if filter_snippet.lines().count() <= 1 { - // add note if not multi-line - span_note_and_lint(cx, - FILTER_NEXT, - expr.span, - msg, - expr.span, - &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); - } else { - span_lint(cx, FILTER_NEXT, expr.span, msg); - } - } -} - -#[allow(ptr_arg)] -// Type of MethodArgs is potentially a Vec -/// lint searching an Iterator followed by `is_some()` -fn lint_search_is_some(cx: &LateContext, expr: &hir::Expr, search_method: &str, search_args: &MethodArgs, - is_some_args: &MethodArgs) { - // lint if caller of search is an Iterator - if match_trait_method(cx, &*is_some_args[0], &paths::ITERATOR) { - let msg = format!("called `is_some()` after searching an iterator with {}. This is more succinctly expressed \ - by calling `any()`.", - search_method); - let search_snippet = snippet(cx, search_args[1].span, ".."); - if search_snippet.lines().count() <= 1 { - // add note if not multi-line - span_note_and_lint(cx, - SEARCH_IS_SOME, - expr.span, - &msg, - expr.span, - &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet)); - } else { - span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); - } - } -} - -/// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: &hir::Expr, eq: bool) -> bool { - if_let_chain! {[ - let Some(args) = method_chain_args(chain, &["chars", "next"]), - let hir::ExprCall(ref fun, ref arg_char) = other.node, - arg_char.len() == 1, - let hir::ExprPath(None, ref path) = fun.node, - path.segments.len() == 1 && path.segments[0].name.as_str() == "Some" - ], { - let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0])); - - if self_ty.sty != ty::TyStr { - return false; - } - - span_lint_and_then(cx, - CHARS_NEXT_CMP, - expr.span, - "you should use the `starts_with` method", - |db| { - let sugg = format!("{}{}.starts_with({})", - if eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - snippet(cx, arg_char[0].span, "_") - ); - - db.span_suggestion(expr.span, "like this", sugg); - }); - - return true; - }} - - false -} - -/// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { - if let Ok(ConstVal::Str(r)) = eval_const_expr_partial(cx.tcx, arg, ExprTypeChecked, None) { - if r.len() == 1 { - let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); - span_lint_and_then(cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - |db| { - db.span_suggestion(expr.span, "try using a char instead:", hint); - }); - } - } -} - -/// Given a `Result<T, E>` type, return its error type (`E`). -fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> { - if !match_type(cx, ty, &paths::RESULT) { - return None; - } - if let ty::TyEnum(_, substs) = ty.sty { - if let Some(err_ty) = substs.types.opt_get(TypeSpace, 1) { - return Some(err_ty); - } - } - None -} - -/// This checks whether a given type is known to implement Debug. -fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { - match cx.tcx.lang_items.debug_trait() { - Some(debug) => implements_trait(cx, ty, debug, Vec::new()), - None => false, - } -} - -enum Convention { - Eq(&'static str), - StartsWith(&'static str), -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [ - (Convention::Eq("new"), &[SelfKind::No]), - (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), - (Convention::StartsWith("from_"), &[SelfKind::No]), - (Convention::StartsWith("into_"), &[SelfKind::Value]), - (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), - (Convention::StartsWith("to_"), &[SelfKind::Ref]), -]; - -#[cfg_attr(rustfmt, rustfmt_skip)] -const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ - ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), - ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), - ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), - ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), - ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), - ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), - ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), - ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), - ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), - ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), - ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), - ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), - ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), - ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), - ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), - ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), - ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), - ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), - ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), - ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), - ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), - ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), - ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), - ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), - ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), - ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), - ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), - ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), - ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), - ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), -]; - -#[cfg_attr(rustfmt, rustfmt_skip)] -const PATTERN_METHODS: [(&'static str, usize); 17] = [ - ("contains", 1), - ("starts_with", 1), - ("ends_with", 1), - ("find", 1), - ("rfind", 1), - ("split", 1), - ("rsplit", 1), - ("split_terminator", 1), - ("rsplit_terminator", 1), - ("splitn", 2), - ("rsplitn", 2), - ("matches", 1), - ("rmatches", 1), - ("match_indices", 1), - ("rmatch_indices", 1), - ("trim_left_matches", 1), - ("trim_right_matches", 1), -]; - - -#[derive(Clone, Copy)] -enum SelfKind { - Value, - Ref, - RefMut, - No, -} - -impl SelfKind { - fn matches(self, slf: &hir::ExplicitSelf, allow_value_for_ref: bool) -> bool { - match (self, &slf.node) { - (SelfKind::Value, &hir::SelfKind::Value(_)) | - (SelfKind::Ref, &hir::SelfKind::Region(_, hir::Mutability::MutImmutable)) | - (SelfKind::RefMut, &hir::SelfKind::Region(_, hir::Mutability::MutMutable)) => true, - (SelfKind::Ref, &hir::SelfKind::Value(_)) | - (SelfKind::RefMut, &hir::SelfKind::Value(_)) => allow_value_for_ref, - (_, &hir::SelfKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), - - _ => false, - } - } - - fn matches_explicit_type(self, ty: &hir::Ty, allow_value_for_ref: bool) -> bool { - match (self, &ty.node) { - (SelfKind::Value, &hir::TyPath(..)) | - (SelfKind::Ref, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutImmutable, .. })) | - (SelfKind::RefMut, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutMutable, .. })) => true, - (SelfKind::Ref, &hir::TyPath(..)) | - (SelfKind::RefMut, &hir::TyPath(..)) => allow_value_for_ref, - _ => false, - } - } - - fn description(&self) -> &'static str { - match *self { - SelfKind::Value => "self by value", - SelfKind::Ref => "self by reference", - SelfKind::RefMut => "self by mutable reference", - SelfKind::No => "no self", - } - } -} - -impl Convention { - fn check(&self, other: &str) -> bool { - match *self { - Convention::Eq(this) => this == other, - Convention::StartsWith(this) => other.starts_with(this), - } - } -} - -impl fmt::Display for Convention { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Convention::Eq(this) => this.fmt(f), - Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), - } - } -} - -#[derive(Clone, Copy)] -enum OutType { - Unit, - Bool, - Any, - Ref, -} - -impl OutType { - fn matches(&self, ty: &hir::FunctionRetTy) -> bool { - match (self, ty) { - (&OutType::Unit, &hir::DefaultReturn(_)) => true, - (&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, - (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, - (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, - (&OutType::Ref, &hir::Return(ref ty)) => { - if let hir::TyRptr(_, _) = ty.node { - true - } else { - false - } - } - _ => false, - } - } -} - -fn is_bool(ty: &hir::Ty) -> bool { - if let hir::TyPath(None, ref p) = ty.node { - if match_path(p, &["bool"]) { - return true; - } - } - false -} - -fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &hir::Item) -> bool { - let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, item.span) -} diff --git a/src/minmax.rs b/src/minmax.rs deleted file mode 100644 index eaba19b08e4..00000000000 --- a/src/minmax.rs +++ /dev/null @@ -1,93 +0,0 @@ -use consts::{Constant, constant_simple}; -use rustc::lint::*; -use rustc::hir::*; -use std::cmp::{PartialOrd, Ordering}; -use syntax::ptr::P; -use utils::{match_def_path, paths, span_lint}; - -/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. -/// -/// **Why is this bad?** This is in all probability not the intended outcome. At the least it hurts readability of the code. -/// -/// **Known problems:** None -/// -/// **Example:** `min(0, max(100, x))` will always be equal to `0`. Probably the author meant to clamp the value between 0 and 100, but has erroneously swapped `min` and `max`. -declare_lint! { - pub MIN_MAX, Warn, - "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" -} - -#[allow(missing_copy_implementations)] -pub struct MinMaxPass; - -impl LintPass for MinMaxPass { - fn get_lints(&self) -> LintArray { - lint_array!(MIN_MAX) - } -} - -impl LateLintPass for MinMaxPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { - if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { - if outer_max == inner_max { - return; - } - match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | - (MinMax::Max, Some(Ordering::Less)) | - (MinMax::Min, Some(Ordering::Greater)) => (), - _ => { - span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); - } - } - } - } - } -} - -#[derive(PartialEq, Eq, Debug)] -enum MinMax { - Min, - Max, -} - -fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { - if let ExprCall(ref path, ref args) = expr.node { - if let ExprPath(None, _) = path.node { - let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); - - if match_def_path(cx, def_id, &paths::CMP_MIN) { - fetch_const(args, MinMax::Min) - } else if match_def_path(cx, def_id, &paths::CMP_MAX) { - fetch_const(args, MinMax::Max) - } else { - None - } - } else { - None - } - } else { - None - } -} - -fn fetch_const(args: &[P<Expr>], m: MinMax) -> Option<(MinMax, Constant, &Expr)> { - if args.len() != 2 { - return None; - } - if let Some(c) = constant_simple(&args[0]) { - if let None = constant_simple(&args[1]) { - // otherwise ignore - Some((m, c, &args[1])) - } else { - None - } - } else { - if let Some(c) = constant_simple(&args[1]) { - Some((m, c, &args[0])) - } else { - None - } - } -} diff --git a/src/misc.rs b/src/misc.rs deleted file mode 100644 index 3ab7823e50d..00000000000 --- a/src/misc.rs +++ /dev/null @@ -1,458 +0,0 @@ -use reexport::*; -use rustc::hir::*; -use rustc::hir::intravisit::FnKind; -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use syntax::codemap::{Span, Spanned, ExpnFormat}; -use syntax::ptr::P; -use utils::{ - get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet, - span_lint, span_lint_and_then, walk_ptrs_ty -}; - -/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. -/// -/// **Why is this bad?** The `ref` declaration makes the function take an owned value, but turns the argument into a reference (which means that the value is destroyed when exiting the function). This adds not much value: either take a reference type, or take an owned value and create references in the body. -/// -/// For let bindings, `let x = &foo;` is preferred over `let ref x = foo`. The type of `x` is more obvious with the former. -/// -/// **Known problems:** If the argument is dereferenced within the function, removing the `ref` will lead to errors. This can be fixed by removing the dereferences, e.g. changing `*x` to `x` within the function. -/// -/// **Example:** `fn foo(ref x: u8) -> bool { .. }` -declare_lint! { - pub TOPLEVEL_REF_ARG, Warn, - "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ - or a `let` statement (`let ref x = foo()`). In such cases, it is preferred to take \ - references with `&`." -} - -#[allow(missing_copy_implementations)] -pub struct TopLevelRefPass; - -impl LintPass for TopLevelRefPass { - fn get_lints(&self) -> LintArray { - lint_array!(TOPLEVEL_REF_ARG) - } -} - -impl LateLintPass for TopLevelRefPass { - fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - if let FnKind::Closure(_) = k { - // Does not apply to closures - return; - } - for ref arg in &decl.inputs { - if let PatKind::Ident(BindByRef(_), _, _) = arg.pat.node { - span_lint(cx, - TOPLEVEL_REF_ARG, - arg.pat.span, - "`ref` directly on a function argument is ignored. Consider using a reference type instead."); - } - } - } - fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) { - if_let_chain! { - [ - let StmtDecl(ref d, _) = s.node, - let DeclLocal(ref l) = d.node, - let PatKind::Ident(BindByRef(_), i, None) = l.pat.node, - let Some(ref init) = l.init - ], { - let tyopt = if let Some(ref ty) = l.ty { - format!(": {}", snippet(cx, ty.span, "_")) - } else { - "".to_owned() - }; - span_lint_and_then(cx, - TOPLEVEL_REF_ARG, - l.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", - |db| { - db.span_suggestion(s.span, - "try", - format!("let {}{} = &{};", - snippet(cx, i.span, "_"), - tyopt, - snippet(cx, init.span, "_"))); - } - ); - } - }; - } -} - -/// **What it does:** This lint checks for comparisons to NAN. -/// -/// **Why is this bad?** NAN does not compare meaningfully to anything – not even itself – so those comparisons are simply wrong. -/// -/// **Known problems:** None -/// -/// **Example:** `x == NAN` -declare_lint!(pub CMP_NAN, Deny, - "comparisons to NAN (which will always return false, which is probably not intended)"); - -#[derive(Copy,Clone)] -pub struct CmpNan; - -impl LintPass for CmpNan { - fn get_lints(&self) -> LintArray { - lint_array!(CMP_NAN) - } -} - -impl LateLintPass for CmpNan { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if cmp.node.is_comparison() { - if let ExprPath(_, ref path) = left.node { - check_nan(cx, path, expr.span); - } - if let ExprPath(_, ref path) = right.node { - check_nan(cx, path, expr.span); - } - } - } - } -} - -fn check_nan(cx: &LateContext, path: &Path, span: Span) { - path.segments.last().map(|seg| { - if seg.name.as_str() == "NAN" { - span_lint(cx, - CMP_NAN, - span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); - } - }); -} - -/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). -/// -/// **Why is this bad?** Floating point calculations are usually imprecise, so asking if two values are *exactly* equal is asking for trouble. For a good guide on what to do, see [the floating point guide](http://www.floating-point-gui.de/errors/comparison). -/// -/// **Known problems:** None -/// -/// **Example:** `y == 1.23f64` -declare_lint!(pub FLOAT_CMP, Warn, - "using `==` or `!=` on float values (as floating-point operations \ - usually involve rounding errors, it is always better to check for approximate \ - equality within small bounds)"); - -#[derive(Copy,Clone)] -pub struct FloatCmp; - -impl LintPass for FloatCmp { - fn get_lints(&self) -> LintArray { - lint_array!(FLOAT_CMP) - } -} - -impl LateLintPass for FloatCmp { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - let op = cmp.node; - if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { - if is_allowed(cx, left) || is_allowed(cx, right) { - return; - } - if let Some(name) = get_item_name(cx, expr) { - let name = name.as_str(); - if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || - name.ends_with("_eq") { - return; - } - } - span_lint(cx, - FLOAT_CMP, - expr.span, - &format!("{}-comparison of f32 or f64 detected. Consider changing this to `({} - {}).abs() < \ - epsilon` for some suitable value of epsilon. \ - std::f32::EPSILON and std::f64::EPSILON are available.", - op.as_str(), - snippet(cx, left.span, ".."), - snippet(cx, right.span, ".."))); - } - } - } -} - -fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { - let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); - if let Ok(ConstVal::Float(val)) = res { - val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY - } else { - false - } -} - -fn is_float(cx: &LateContext, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { - true - } else { - false - } -} - -/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. -/// -/// **Why is this bad?** The comparison can operate on a reference, so creating an owned value effectively throws it away directly afterwards, which is needlessly consuming code and heap space. -/// -/// **Known problems:** None -/// -/// **Example:** `x.to_owned() == y` -declare_lint!(pub CMP_OWNED, Warn, - "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`"); - -#[derive(Copy,Clone)] -pub struct CmpOwned; - -impl LintPass for CmpOwned { - fn get_lints(&self) -> LintArray { - lint_array!(CMP_OWNED) - } -} - -impl LateLintPass for CmpOwned { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = expr.node { - if cmp.node.is_comparison() { - check_to_owned(cx, left, right, true, cmp.span); - check_to_owned(cx, right, left, false, cmp.span) - } - } - } -} - -fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) { - let (arg_ty, snip) = match expr.node { - ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => { - if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { - (cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) - } else { - return; - } - } - ExprCall(ref path, ref v) if v.len() == 1 => { - if let ExprPath(None, ref path) = path.node { - if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { - (cx.tcx.expr_ty(&v[0]), snippet(cx, v[0].span, "..")) - } else { - return; - } - } else { - return; - } - } - _ => return, - }; - - let other_ty = cx.tcx.expr_ty(other); - let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() { - Some(id) => id, - None => return, - }; - - if !implements_trait(cx, arg_ty, partial_eq_trait_id, vec![other_ty]) { - return; - } - - if left { - span_lint(cx, - CMP_OWNED, - expr.span, - &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ - compare without allocation", - snip, - snippet(cx, op, "=="), - snippet(cx, other.span, ".."))); - } else { - span_lint(cx, - CMP_OWNED, - expr.span, - &format!("this creates an owned instance just for comparison. Consider using `{} {} {}` to \ - compare without allocation", - snippet(cx, other.span, ".."), - snippet(cx, op, "=="), - snip)); - } - -} - -fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { - args.len() == 1 && - if let ty::TyStr = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { - true - } else { - false - } -} - -/// **What it does:** This lint checks for getting the remainder of a division by one. -/// -/// **Why is this bad?** The result can only ever be zero. No one will write such code deliberately, unless trying to win an Underhanded Rust Contest. Even for that contest, it's probably a bad idea. Use something more underhanded. -/// -/// **Known problems:** None -/// -/// **Example:** `x % 1` -declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0"); - -#[derive(Copy,Clone)] -pub struct ModuloOne; - -impl LintPass for ModuloOne { - fn get_lints(&self) -> LintArray { - lint_array!(MODULO_ONE) - } -} - -impl LateLintPass for ModuloOne { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, _, ref right) = expr.node { - if let Spanned { node: BinOp_::BiRem, .. } = *cmp { - if is_integer_literal(right, 1) { - span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); - } - } - } - } -} - -/// **What it does:** This lint checks for patterns in the form `name @ _`. -/// -/// **Why is this bad?** It's almost always more readable to just use direct bindings. -/// -/// **Known problems:** None -/// -/// **Example**: -/// ``` -/// match v { -/// Some(x) => (), -/// y @ _ => (), // easier written as `y`, -/// } -/// ``` -declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern"); - -#[derive(Copy,Clone)] -pub struct PatternPass; - -impl LintPass for PatternPass { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_PATTERN) - } -} - -impl LateLintPass for PatternPass { - fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatKind::Ident(_, ref ident, Some(ref right)) = pat.node { - if right.node == PatKind::Wild { - span_lint(cx, - REDUNDANT_PATTERN, - pat.span, - &format!("the `{} @ _` pattern can be written as just `{}`", - ident.node, - ident.node)); - } - } - } -} - - -/// **What it does:** This lint checks for the use of bindings with a single leading underscore -/// -/// **Why is this bad?** A single leading underscore is usually used to indicate that a binding -/// will not be used. Using such a binding breaks this expectation. -/// -/// **Known problems:** The lint does not work properly with desugaring and macro, it has been -/// allowed in the mean time. -/// -/// **Example**: -/// ``` -/// let _x = 0; -/// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore. -/// // We should rename `_x` to `x` -/// ``` -declare_lint!(pub USED_UNDERSCORE_BINDING, Allow, - "using a binding which is prefixed with an underscore"); - -#[derive(Copy, Clone)] -pub struct UsedUnderscoreBinding; - -impl LintPass for UsedUnderscoreBinding { - fn get_lints(&self) -> LintArray { - lint_array!(USED_UNDERSCORE_BINDING) - } -} - -impl LateLintPass for UsedUnderscoreBinding { - #[cfg_attr(rustfmt, rustfmt_skip)] - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_attributes_expansion(cx, expr) { - // Don't lint things expanded by #[derive(...)], etc - return; - } - let binding = match expr.node { - ExprPath(_, ref path) => { - let segment = path.segments - .last() - .expect("path should always have at least one segment") - .name; - if segment.as_str().starts_with('_') && - !segment.as_str().starts_with("__") && - segment != segment.unhygienize() && // not in bang macro - is_used(cx, expr) { - Some(segment.as_str()) - } else { - None - } - } - ExprField(_, spanned) => { - let name = spanned.node.as_str(); - if name.starts_with('_') && !name.starts_with("__") { - Some(name) - } else { - None - } - } - _ => None, - }; - if let Some(binding) = binding { - if binding != "_result" { // FIXME: #944 - span_lint(cx, - USED_UNDERSCORE_BINDING, - expr.span, - &format!("used binding `{}` which is prefixed with an underscore. A leading \ - underscore signals that a binding will not be used.", binding)); - } - } - } -} - -/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea -/// of what it means for an expression to be "used". -fn is_used(cx: &LateContext, expr: &Expr) -> bool { - if let Some(ref parent) = get_parent_expr(cx, expr) { - match parent.node { - ExprAssign(_, ref rhs) | - ExprAssignOp(_, _, ref rhs) => **rhs == *expr, - _ => is_used(cx, parent), - } - } else { - true - } -} - -/// Test whether an expression is in a macro expansion (e.g. something generated by -/// `#[derive(...)`] or the like). -fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { - cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| { - info_opt.map_or(false, |info| { - match info.callee.format { - ExpnFormat::MacroAttribute(_) => true, - _ => false, - } - }) - }) -} diff --git a/src/misc_early.rs b/src/misc_early.rs deleted file mode 100644 index a7ab59497ac..00000000000 --- a/src/misc_early.rs +++ /dev/null @@ -1,166 +0,0 @@ -use rustc::lint::*; -use std::collections::HashMap; -use syntax::ast::*; -use syntax::codemap::Span; -use syntax::visit::FnKind; -use utils::{span_lint, span_help_and_lint, snippet, span_lint_and_then}; -/// **What it does:** This lint checks for structure field patterns bound to wildcards. -/// -/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound. -/// -/// **Known problems:** None. -/// -/// **Example:** `let { a: _, b: ref b, c: _ } = ..` -declare_lint! { - pub UNNEEDED_FIELD_PATTERN, Warn, - "Struct fields are bound to a wildcard instead of using `..`" -} - -/// **What it does:** This lint checks for function arguments having the similar names differing by an underscore -/// -/// **Why is this bad?** It affects code readability -/// -/// **Known problems:** None. -/// -/// **Example:** `fn foo(a: i32, _a: i32) {}` -declare_lint! { - pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn, - "Function arguments having names which only differ by an underscore" -} - -/// **What it does:** This lint detects closures called in the same expression where they are defined. -/// -/// **Why is this bad?** It is unnecessarily adding to the expression's complexity. -/// -/// **Known problems:** None. -/// -/// **Example:** `(|| 42)()` -declare_lint! { - pub REDUNDANT_CLOSURE_CALL, Warn, - "Closures should not be called in the expression they are defined" -} - -#[derive(Copy, Clone)] -pub struct MiscEarly; - -impl LintPass for MiscEarly { - fn get_lints(&self) -> LintArray { - lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL) - } -} - -impl EarlyLintPass for MiscEarly { - fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { - if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { - let mut wilds = 0; - let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name; - - for field in pfields { - if field.node.pat.node == PatKind::Wild { - wilds += 1; - } - } - if !pfields.is_empty() && wilds == pfields.len() { - span_help_and_lint(cx, - UNNEEDED_FIELD_PATTERN, - pat.span, - "All the struct fields are matched to a wildcard pattern, consider using `..`.", - &format!("Try with `{} {{ .. }}` instead", type_name)); - return; - } - if wilds > 0 { - let mut normal = vec![]; - - for field in pfields { - if field.node.pat.node != PatKind::Wild { - if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { - normal.push(n); - } - } - } - for field in pfields { - if field.node.pat.node == PatKind::Wild { - wilds -= 1; - if wilds > 0 { - span_lint(cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "You matched a field with a wildcard pattern. Consider using `..` instead"); - } else { - span_help_and_lint(cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "You matched a field with a wildcard pattern. Consider using `..` \ - instead", - &format!("Try with `{} {{ {}, .. }}`", - type_name, - normal[..].join(", "))); - } - } - } - } - } - } - - fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - let mut registered_names: HashMap<String, Span> = HashMap::new(); - - for ref arg in &decl.inputs { - if let PatKind::Ident(_, sp_ident, None) = arg.pat.node { - let arg_name = sp_ident.node.to_string(); - - if arg_name.starts_with('_') { - if let Some(correspondence) = registered_names.get(&arg_name[1..]) { - span_lint(cx, - DUPLICATE_UNDERSCORE_ARGUMENT, - *correspondence, - &format!("`{}` already exists, having another argument having almost the same \ - name makes code comprehension and documentation more difficult", - arg_name[1..].to_owned()));; - } - } else { - registered_names.insert(arg_name, arg.pat.span); - } - } - } - } - - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Call(ref paren, _) = expr.node { - if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { - span_lint_and_then(cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| { - if decl.inputs.is_empty() { - let hint = format!("{}", snippet(cx, block.span, "..")); - db.span_suggestion(expr.span, "Try doing something like: ", hint); - } - }); - } - } - } - } - - fn check_block(&mut self, cx: &EarlyContext, block: &Block) { - for w in block.stmts.windows(2) { - if_let_chain! {[ - let StmtKind::Decl(ref first, _) = w[0].node, - let DeclKind::Local(ref local) = first.node, - let Option::Some(ref t) = local.init, - let ExprKind::Closure(_,_,_,_) = t.node, - let PatKind::Ident(_,sp_ident,_) = local.pat.node, - let StmtKind::Semi(ref second,_) = w[1].node, - let ExprKind::Assign(_,ref call) = second.node, - let ExprKind::Call(ref closure,_) = call.node, - let ExprKind::Path(_,ref path) = closure.node - ], { - if sp_ident.node == (&path.segments[0]).identifier { - span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared"); - } - }} - } - } -} diff --git a/src/mut_mut.rs b/src/mut_mut.rs deleted file mode 100644 index 4147e288c4f..00000000000 --- a/src/mut_mut.rs +++ /dev/null @@ -1,59 +0,0 @@ -use rustc::lint::*; -use rustc::ty::{TypeAndMut, TyRef}; -use rustc::hir::*; -use utils::{in_external_macro, span_lint}; - -/// **What it does:** This lint checks for instances of `mut mut` references. -/// -/// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source. -/// -/// **Known problems:** None -/// -/// **Example:** `let x = &mut &mut y;` -declare_lint! { - pub MUT_MUT, - Allow, - "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \ - or shows a fundamental misunderstanding of references)" -} - -#[derive(Copy,Clone)] -pub struct MutMut; - -impl LintPass for MutMut { - fn get_lints(&self) -> LintArray { - lint_array!(MUT_MUT) - } -} - -impl LateLintPass for MutMut { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { - return; - } - - if let ExprAddrOf(MutMutable, ref e) = expr.node { - if let ExprAddrOf(MutMutable, _) = e.node { - span_lint(cx, - MUT_MUT, - expr.span, - "generally you want to avoid `&mut &mut _` if possible"); - } else { - if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { - span_lint(cx, - MUT_MUT, - expr.span, - "this expression mutably borrows a mutable reference. Consider reborrowing"); - } - } - } - } - - fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { - if let TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) = ty.node { - if let TyRptr(_, MutTy { mutbl: MutMutable, .. }) = pty.node { - span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); - } - } - } -} diff --git a/src/mut_reference.rs b/src/mut_reference.rs deleted file mode 100644 index f6aee54d90b..00000000000 --- a/src/mut_reference.rs +++ /dev/null @@ -1,77 +0,0 @@ -use rustc::lint::*; -use rustc::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; -use rustc::hir::*; -use syntax::ptr::P; -use utils::span_lint; - -/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. -/// -/// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site. -/// -/// **Known problems:** None -/// -/// **Example** `my_vec.push(&mut value)` -declare_lint! { - pub UNNECESSARY_MUT_PASSED, - Warn, - "an argument is passed as a mutable reference although the function/method only demands an \ - immutable reference" -} - - -#[derive(Copy,Clone)] -pub struct UnnecessaryMutPassed; - -impl LintPass for UnnecessaryMutPassed { - fn get_lints(&self) -> LintArray { - lint_array!(UNNECESSARY_MUT_PASSED) - } -} - -impl LateLintPass for UnnecessaryMutPassed { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - let borrowed_table = cx.tcx.tables.borrow(); - match e.node { - ExprCall(ref fn_expr, ref arguments) => { - let function_type = borrowed_table.node_types - .get(&fn_expr.id) - .expect("A function with an unknown type is called. \ - If this happened, the compiler would have \ - aborted the compilation long ago"); - if let ExprPath(_, ref path) = fn_expr.node { - check_arguments(cx, arguments, function_type, &path.to_string()); - } - } - ExprMethodCall(ref name, _, ref arguments) => { - let method_call = MethodCall::expr(e.id); - let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); - check_arguments(cx, arguments, method_type.ty, &name.node.as_str()) - } - _ => (), - } - } -} - -fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { - match type_definition.sty { - TypeVariants::TyFnDef(_, _, ref fn_type) | - TypeVariants::TyFnPtr(ref fn_type) => { - let parameters = &fn_type.sig.skip_binder().inputs; - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { - match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) | - TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => { - if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method \"{}\" doesn't need a mutable reference", name)); - } - } - _ => (), - } - } - } - _ => (), - } -} diff --git a/src/mutex_atomic.rs b/src/mutex_atomic.rs deleted file mode 100644 index 7d637adb8b8..00000000000 --- a/src/mutex_atomic.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Checks for uses of Mutex where an atomic value could be used -//! -//! This lint is **warn** by default - -use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; -use rustc::ty::subst::ParamSpace; -use rustc::ty; -use rustc::hir::Expr; -use syntax::ast; -use utils::{match_type, paths, span_lint}; - -/// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do. -/// -/// **Why is this bad?** Using a Mutex just to make access to a plain bool or reference sequential is shooting flies with cannons. `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and faster. -/// -/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. -/// -/// **Example:** `let x = Mutex::new(&y);` -declare_lint! { - pub MUTEX_ATOMIC, - Warn, - "using a Mutex where an atomic value could be used instead" -} - -/// **What it does:** This lint checks for usages of `Mutex<X>` where `X` is an integral type. -/// -/// **Why is this bad?** Using a Mutex just to make access to a plain integer sequential is shooting flies with cannons. `std::atomic::usize` is leaner and faster. -/// -/// **Known problems:** This lint cannot detect if the Mutex is actually used for waiting before a critical section. -/// -/// **Example:** `let x = Mutex::new(0usize);` -declare_lint! { - pub MUTEX_INTEGER, - Allow, - "using a Mutex for an integer type" -} - -impl LintPass for MutexAtomic { - fn get_lints(&self) -> LintArray { - lint_array!(MUTEX_ATOMIC, MUTEX_INTEGER) - } -} - -pub struct MutexAtomic; - -impl LateLintPass for MutexAtomic { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - let ty = cx.tcx.expr_ty(expr); - if let ty::TyStruct(_, subst) = ty.sty { - if match_type(cx, ty, &paths::MUTEX) { - let mutex_param = &subst.types.get(ParamSpace::TypeSpace, 0).sty; - if let Some(atomic_name) = get_atomic_name(mutex_param) { - let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ - behaviour and not the internal type, consider using Mutex<()>.", - atomic_name); - match *mutex_param { - ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), - }; - } - } - } - } -} - -fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { - match *ty { - ty::TyBool => Some("AtomicBool"), - ty::TyUint(_) => Some("AtomicUsize"), - ty::TyInt(_) => Some("AtomicIsize"), - ty::TyRawPtr(_) => Some("AtomicPtr"), - _ => None, - } -} diff --git a/src/needless_bool.rs b/src/needless_bool.rs deleted file mode 100644 index f95d6f5c9c1..00000000000 --- a/src/needless_bool.rs +++ /dev/null @@ -1,192 +0,0 @@ -//! Checks for needless boolean results of if-else expressions -//! -//! This lint is **warn** by default - -use rustc::lint::*; -use rustc::hir::*; -use syntax::ast::LitKind; -use syntax::codemap::Spanned; -use utils::{span_lint, span_lint_and_then, snippet, snippet_opt}; - -/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. -/// -/// **Why is this bad?** Redundant code. -/// -/// **Known problems:** Maybe false positives: Sometimes, the two branches are painstakingly documented (which we of course do not detect), so they *may* have some value. Even then, the documentation can be rewritten to match the shorter code. -/// -/// **Example:** `if x { false } else { true }` -declare_lint! { - pub NEEDLESS_BOOL, - Warn, - "if-statements with plain booleans in the then- and else-clause, e.g. \ - `if p { true } else { false }`" -} - -/// **What it does:** This lint checks for expressions of the form `x == true` (or vice versa) and suggest using the variable directly. -/// -/// **Why is this bad?** Unnecessary code. -/// -/// **Known problems:** None. -/// -/// **Example:** `if x == true { }` could be `if x { }` -declare_lint! { - pub BOOL_COMPARISON, - Warn, - "comparing a variable to a boolean, e.g. \ - `if x == true`" -} - -#[derive(Copy,Clone)] -pub struct NeedlessBool; - -impl LintPass for NeedlessBool { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_BOOL) - } -} - -impl LateLintPass for NeedlessBool { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - use self::Expression::*; - if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { - let reduce = |hint: &str, not| { - let hint = match snippet_opt(cx, pred.span) { - Some(pred_snip) => format!("`{}{}`", not, pred_snip), - None => hint.into(), - }; - span_lint_and_then(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression returns a bool literal", - |db| { - db.span_suggestion(e.span, "you can reduce it to", hint); - }); - }; - match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (RetBool(true), RetBool(true)) | - (Bool(true), Bool(true)) => { - span_lint(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression will always return true"); - } - (RetBool(false), RetBool(false)) | - (Bool(false), Bool(false)) => { - span_lint(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression will always return false"); - } - (RetBool(true), RetBool(false)) => reduce("its predicate", "return "), - (Bool(true), Bool(false)) => reduce("its predicate", ""), - (RetBool(false), RetBool(true)) => reduce("`!` and its predicate", "return !"), - (Bool(false), Bool(true)) => reduce("`!` and its predicate", "!"), - _ => (), - } - } - } -} - -#[derive(Copy,Clone)] -pub struct BoolComparison; - -impl LintPass for BoolComparison { - fn get_lints(&self) -> LintArray { - lint_array!(BOOL_COMPARISON) - } -} - -impl LateLintPass for BoolComparison { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - use self::Expression::*; - if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { - match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Bool(true), Other) => { - let hint = snippet(cx, right_side.span, "..").into_owned(); - span_lint_and_then(cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); - }); - } - (Other, Bool(true)) => { - let hint = snippet(cx, left_side.span, "..").into_owned(); - span_lint_and_then(cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); - }); - } - (Bool(false), Other) => { - let hint = format!("!{}", snippet(cx, right_side.span, "..")); - span_lint_and_then(cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); - }); - } - (Other, Bool(false)) => { - let hint = format!("!{}", snippet(cx, left_side.span, "..")); - span_lint_and_then(cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); - }); - } - _ => (), - } - } - } -} - -enum Expression { - Bool(bool), - RetBool(bool), - Other, -} - -fn fetch_bool_block(block: &Block) -> Expression { - match (&*block.stmts, block.expr.as_ref()) { - ([], Some(e)) => fetch_bool_expr(&**e), - ([ref e], None) => { - if let StmtSemi(ref e, _) = e.node { - if let ExprRet(_) = e.node { - fetch_bool_expr(&**e) - } else { - Expression::Other - } - } else { - Expression::Other - } - } - _ => Expression::Other, - } -} - -fn fetch_bool_expr(expr: &Expr) -> Expression { - match expr.node { - ExprBlock(ref block) => fetch_bool_block(block), - ExprLit(ref lit_ptr) => { - if let LitKind::Bool(value) = lit_ptr.node { - Expression::Bool(value) - } else { - Expression::Other - } - } - ExprRet(Some(ref expr)) => { - match fetch_bool_expr(expr) { - Expression::Bool(value) => Expression::RetBool(value), - _ => Expression::Other, - } - } - _ => Expression::Other, - } -} diff --git a/src/needless_borrow.rs b/src/needless_borrow.rs deleted file mode 100644 index 033811841ce..00000000000 --- a/src/needless_borrow.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! Checks for needless address of operations (`&`) -//! -//! This lint is **warn** by default - -use rustc::lint::*; -use rustc::hir::{ExprAddrOf, Expr, MutImmutable}; -use rustc::ty::TyRef; -use utils::{span_lint, in_macro}; -use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef; - -/// **What it does:** This lint checks for address of operations (`&`) that are going to be dereferenced immediately by the compiler -/// -/// **Why is this bad?** Suggests that the receiver of the expression borrows the expression -/// -/// **Known problems:** -/// -/// **Example:** `let x: &i32 = &&&&&&5;` -declare_lint! { - pub NEEDLESS_BORROW, - Warn, - "taking a reference that is going to be automatically dereferenced" -} - -#[derive(Copy,Clone)] -pub struct NeedlessBorrow; - -impl LintPass for NeedlessBorrow { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_BORROW) - } -} - -impl LateLintPass for NeedlessBorrow { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if in_macro(cx, e.span) { - return; - } - if let ExprAddrOf(MutImmutable, ref inner) = e.node { - if let TyRef(..) = cx.tcx.expr_ty(inner).sty { - if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) { - if deref.autoderefs > 1 && deref.autoref.is_some() { - span_lint(cx, - NEEDLESS_BORROW, - e.span, - "this expression borrows a reference that is immediately dereferenced by the compiler"); - } - } - } - } - } -} diff --git a/src/needless_update.rs b/src/needless_update.rs deleted file mode 100644 index d8ae9dc3471..00000000000 --- a/src/needless_update.rs +++ /dev/null @@ -1,42 +0,0 @@ -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::ty::TyStruct; -use rustc::hir::{Expr, ExprStruct}; -use utils::span_lint; - -/// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway. -/// -/// **Why is this bad?** This will cost resources (because the base has to be somewhere), and make the code less readable. -/// -/// **Known problems:** None. -/// -/// **Example:** `Point { x: 1, y: 0, ..zero_point }` -declare_lint! { - pub NEEDLESS_UPDATE, - Warn, - "using `{ ..base }` when there are no missing fields" -} - -#[derive(Copy, Clone)] -pub struct NeedlessUpdatePass; - -impl LintPass for NeedlessUpdatePass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_UPDATE) - } -} - -impl LateLintPass for NeedlessUpdatePass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { - let ty = cx.tcx.expr_ty(expr); - if let TyStruct(def, _) = ty.sty { - if fields.len() == def.struct_variant().fields.len() { - span_lint(cx, - NEEDLESS_UPDATE, - base.span, - "struct update has no effect, all the fields in the struct have already been specified"); - } - } - } - } -} diff --git a/src/neg_multiply.rs b/src/neg_multiply.rs deleted file mode 100644 index fb986409a41..00000000000 --- a/src/neg_multiply.rs +++ /dev/null @@ -1,57 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use syntax::codemap::{Span, Spanned}; - -use consts::{self, Constant}; -use utils::span_lint; - -/// **What it does:** Checks for multiplication by -1 as a form of negation. -/// -/// **Why is this bad?** It's more readable to just negate. -/// -/// **Known problems:** This only catches integers (for now) -/// -/// **Example:** `x * -1` -declare_lint! { - pub NEG_MULTIPLY, - Warn, - "Warns on multiplying integers with -1" -} - -#[derive(Copy, Clone)] -pub struct NegMultiply; - -impl LintPass for NegMultiply { - fn get_lints(&self) -> LintArray { - lint_array!(NEG_MULTIPLY) - } -} - -#[allow(match_same_arms)] -impl LateLintPass for NegMultiply { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { - match (&l.node, &r.node) { - (&ExprUnary(..), &ExprUnary(..)) => (), - (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), - (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), - _ => () - } - } - } -} - -fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { - if_let_chain!([ - let ExprLit(ref l) = lit.node, - let Constant::Int(ref ci) = consts::lit_to_constant(&l.node), - let Some(val) = ci.to_u64(), - val == 1, - cx.tcx.expr_ty(exp).is_integral() - ], { - span_lint(cx, - NEG_MULTIPLY, - span, - "Negation by multiplying with -1"); - }) -} diff --git a/src/new_without_default.rs b/src/new_without_default.rs deleted file mode 100644 index 08d517014ee..00000000000 --- a/src/new_without_default.rs +++ /dev/null @@ -1,148 +0,0 @@ -use rustc::hir::intravisit::FnKind; -use rustc::hir::def_id::DefId; -use rustc::hir; -use rustc::lint::*; -use rustc::ty; -use syntax::ast; -use syntax::codemap::Span; -use utils::paths; -use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint}; - -/// **What it does:** This lints about type with a `fn new() -> Self` method -/// and no implementation of -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) -/// -/// **Why is this bad?** User might expect to be able to use -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) -/// as the type can be -/// constructed without arguments. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// -/// ```rust,ignore -/// struct Foo(Bar); -/// -/// impl Foo { -/// fn new() -> Self { -/// Foo(Bar::new()) -/// } -/// } -/// ``` -/// -/// Instead, use: -/// -/// ```rust -/// struct Foo(Bar); -/// -/// impl Default for Foo { -/// fn default() -> Self { -/// Foo(Bar::new()) -/// } -/// } -/// ``` -/// -/// You can also have `new()` call `Default::default()` -declare_lint! { - pub NEW_WITHOUT_DEFAULT, - Warn, - "`fn new() -> Self` method without `Default` implementation" -} - -/// **What it does:** This lints about type with a `fn new() -> Self` method -/// and no implementation of -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) -/// -/// **Why is this bad?** User might expect to be able to use -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) -/// as the type can be -/// constructed without arguments. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// -/// ```rust,ignore -/// struct Foo; -/// -/// impl Foo { -/// fn new() -> Self { -/// Foo -/// } -/// } -/// ``` -/// -/// Just prepend `#[derive(Default)]` before the `struct` definition -declare_lint! { - pub NEW_WITHOUT_DEFAULT_DERIVE, - Warn, - "`fn new() -> Self` without `#[derive]`able `Default` implementation" -} - -#[derive(Copy,Clone)] -pub struct NewWithoutDefault; - -impl LintPass for NewWithoutDefault { - fn get_lints(&self) -> LintArray { - lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE) - } -} - -impl LateLintPass for NewWithoutDefault { - fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) { - if in_external_macro(cx, span) { - return; - } - - if let FnKind::Method(name, _, _, _) = kind { - if decl.inputs.is_empty() && name.as_str() == "new" { - let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( - cx.tcx.map.get_parent(id))).ty; - if_let_chain!{[ - self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics - let Some(ret_ty) = return_ty(cx, id), - same_tys(cx, self_ty, ret_ty, id), - let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), - !implements_trait(cx, self_ty, default_trait_id, Vec::new()) - ], { - if can_derive_default(self_ty, cx, default_trait_id) { - span_lint(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty)). - span_suggestion(span, - "try this", - "#[derive(Default)]".into()); - } else { - span_lint(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty)). - span_suggestion(span, - "try this", - format!("impl Default for {} {{ fn default() -> \ - Self {{ {}::new() }} }}", self_ty, self_ty)); - } - }} - } - } - } -} - -fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> bool { - match ty.sty { - ty::TyStruct(ref adt_def, ref substs) => { - for field in adt_def.all_fields() { - let f_ty = field.ty(cx.tcx, substs); - if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) { - return false - } - } - true - }, - _ => false - } -} diff --git a/src/no_effect.rs b/src/no_effect.rs deleted file mode 100644 index ae3bac00455..00000000000 --- a/src/no_effect.rs +++ /dev/null @@ -1,155 +0,0 @@ -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::def::{Def, PathResolution}; -use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource}; -use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then}; -use std::ops::Deref; - -/// **What it does:** This lint checks for statements which have no effect. -/// -/// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable. -/// -/// **Known problems:** None. -/// -/// **Example:** `0;` -declare_lint! { - pub NO_EFFECT, - Warn, - "statements with no effect" -} - -/// **What it does:** This lint checks for expression statements that can be reduced to a sub-expression -/// -/// **Why is this bad?** Expressions by themselves often have no side-effects. Having such expressions reduces redability. -/// -/// **Known problems:** None. -/// -/// **Example:** `compute_array()[0];` -declare_lint! { - pub UNNECESSARY_OPERATION, - Warn, - "outer expressions with no effect" -} - -fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { - if in_macro(cx, expr.span) { - return false; - } - match expr.node { - Expr_::ExprLit(..) | - Expr_::ExprClosure(..) | - Expr_::ExprPath(..) => true, - Expr_::ExprIndex(ref a, ref b) | - Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), - Expr_::ExprVec(ref v) | - Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), - Expr_::ExprRepeat(ref inner, _) | - Expr_::ExprCast(ref inner, _) | - Expr_::ExprType(ref inner, _) | - Expr_::ExprUnary(_, ref inner) | - Expr_::ExprField(ref inner, _) | - Expr_::ExprTupField(ref inner, _) | - Expr_::ExprAddrOf(_, ref inner) | - Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), - Expr_::ExprStruct(_, ref fields, ref base) => { - fields.iter().all(|field| has_no_effect(cx, &field.expr)) && - match *base { - Some(ref base) => has_no_effect(cx, base), - None => true, - } - } - Expr_::ExprCall(ref callee, ref args) => { - let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); - match def { - Some(Def::Struct(..)) | - Some(Def::Variant(..)) => args.iter().all(|arg| has_no_effect(cx, arg)), - _ => false, - } - } - Expr_::ExprBlock(ref block) => { - block.stmts.is_empty() && - if let Some(ref expr) = block.expr { - has_no_effect(cx, expr) - } else { - false - } - } - _ => false, - } -} - -#[derive(Copy, Clone)] -pub struct NoEffectPass; - -impl LintPass for NoEffectPass { - fn get_lints(&self) -> LintArray { - lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) - } -} - -impl LateLintPass for NoEffectPass { - fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { - if let StmtSemi(ref expr, _) = stmt.node { - if has_no_effect(cx, expr) { - span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); - } else if let Some(reduced) = reduce_expression(cx, expr) { - let mut snippet = String::new(); - for e in reduced { - if in_macro(cx, e.span) { - return; - } - if let Some(snip) = snippet_opt(cx, e.span) { - snippet.push_str(&snip); - snippet.push(';'); - } else { - return; - } - } - span_lint_and_then(cx, UNNECESSARY_OPERATION, stmt.span, "statement can be reduced", |db| { - db.span_suggestion(stmt.span, "replace it with", snippet); - }); - } - } - } -} - - -fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Expr>> { - if in_macro(cx, expr.span) { - return None; - } - match expr.node { - Expr_::ExprIndex(ref a, ref b) | - Expr_::ExprBinary(_, ref a, ref b) => Some(vec![&**a, &**b]), - Expr_::ExprVec(ref v) | - Expr_::ExprTup(ref v) => Some(v.iter().map(Deref::deref).collect()), - Expr_::ExprRepeat(ref inner, _) | - Expr_::ExprCast(ref inner, _) | - Expr_::ExprType(ref inner, _) | - Expr_::ExprUnary(_, ref inner) | - Expr_::ExprField(ref inner, _) | - Expr_::ExprTupField(ref inner, _) | - Expr_::ExprAddrOf(_, ref inner) | - Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()), - Expr_::ExprCall(ref callee, ref args) => { - match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) { - Some(Def::Struct(..)) | - Some(Def::Variant(..)) => Some(args.iter().map(Deref::deref).collect()), - _ => None, - } - } - Expr_::ExprBlock(ref block) => { - if block.stmts.is_empty() { - block.expr.as_ref().and_then(|e| match block.rules { - BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, - BlockCheckMode::DefaultBlock => Some(vec![&**e]), - // in case of compiler-inserted signaling blocks - _ => reduce_expression(cx, e), - }) - } else { - None - } - } - _ => None, - } -} diff --git a/src/non_expressive_names.rs b/src/non_expressive_names.rs deleted file mode 100644 index cbb083a3e16..00000000000 --- a/src/non_expressive_names.rs +++ /dev/null @@ -1,291 +0,0 @@ -use rustc::lint::*; -use syntax::codemap::Span; -use syntax::parse::token::InternedString; -use syntax::ast::*; -use syntax::attr; -use syntax::visit::{Visitor, walk_block, walk_pat, walk_expr}; -use utils::{span_lint_and_then, in_macro, span_lint}; - -/// **What it does:** This lint warns about names that are very similar and thus confusing -/// -/// **Why is this bad?** It's hard to distinguish between names that differ only by a single character -/// -/// **Known problems:** None? -/// -/// **Example:** `checked_exp` and `checked_expr` -declare_lint! { - pub SIMILAR_NAMES, - Allow, - "similarly named items and bindings" -} - -/// **What it does:** This lint warns about having too many variables whose name consists of a single character -/// -/// **Why is this bad?** It's hard to memorize what a variable means without a descriptive name. -/// -/// **Known problems:** None? -/// -/// **Example:** let (a, b, c, d, e, f, g) = (...); -declare_lint! { - pub MANY_SINGLE_CHAR_NAMES, - Warn, - "too many single character bindings" -} - -pub struct NonExpressiveNames { - pub max_single_char_names: u64, -} - -impl LintPass for NonExpressiveNames { - fn get_lints(&self) -> LintArray { - lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES) - } -} - -struct ExistingName { - interned: InternedString, - span: Span, - len: usize, - whitelist: &'static [&'static str], -} - -struct SimilarNamesLocalVisitor<'a, 'b: 'a> { - names: Vec<ExistingName>, - cx: &'a EarlyContext<'b>, - lint: &'a NonExpressiveNames, - single_char_names: Vec<char>, -} - -// this list contains lists of names that are allowed to be similar -// the assumption is that no name is ever contained in multiple lists. -#[cfg_attr(rustfmt, rustfmt_skip)] -const WHITELIST: &'static [&'static [&'static str]] = &[ - &["parsed", "parser"], - &["lhs", "rhs"], - &["tx", "rx"], - &["set", "get"], -]; - -struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); - -impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { - fn visit_pat(&mut self, pat: &'v Pat) { - match pat.node { - PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), - PatKind::Struct(_, ref fields, _) => for field in fields { - if !field.node.is_shorthand { - self.visit_pat(&field.node.pat); - } - }, - _ => walk_pat(self, pat), - } - } -} - -fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { - for &allow in WHITELIST { - if whitelisted(interned_name, allow) { - return Some(allow); - } - } - None -} - -fn whitelisted(interned_name: &str, list: &[&str]) -> bool { - if list.iter().any(|&name| interned_name == name) { - return true; - } - for name in list { - // name_* - if interned_name.chars().zip(name.chars()).all(|(l, r)| l == r) { - return true; - } - // *_name - if interned_name.chars().rev().zip(name.chars().rev()).all(|(l, r)| l == r) { - return true; - } - } - false -} - -impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { - fn check_short_name(&mut self, c: char, span: Span) { - // make sure we ignore shadowing - if self.0.single_char_names.contains(&c) { - return; - } - self.0.single_char_names.push(c); - if self.0.single_char_names.len() as u64 >= self.0.lint.max_single_char_names { - span_lint(self.0.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!("{}th binding whose name is just one char", self.0.single_char_names.len())); - } - } - fn check_name(&mut self, span: Span, name: Name) { - if in_macro(self.0.cx, span) { - return; - } - let interned_name = name.as_str(); - if interned_name.chars().any(char::is_uppercase) { - return; - } - let count = interned_name.chars().count(); - if count < 3 { - if count == 1 { - let c = interned_name.chars().next().expect("already checked"); - self.check_short_name(c, span); - } - return; - } - for existing_name in &self.0.names { - if whitelisted(&interned_name, existing_name.whitelist) { - continue; - } - let mut split_at = None; - if existing_name.len > count { - if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned) { - continue; - } - } else if existing_name.len < count { - if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned, &interned_name) { - continue; - } - } else { - let mut interned_chars = interned_name.chars(); - let mut existing_chars = existing_name.interned.chars(); - let first_i = interned_chars.next().expect("we know we have at least one char"); - let first_e = existing_chars.next().expect("we know we have at least one char"); - let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); - - if eq_or_numeric(first_i, first_e) { - let last_i = interned_chars.next_back().expect("we know we have at least two chars"); - let last_e = existing_chars.next_back().expect("we know we have at least two chars"); - if eq_or_numeric(last_i, last_e) { - if interned_chars.zip(existing_chars).filter(|&(i, e)| !eq_or_numeric(i, e)).count() != 1 { - continue; - } - } else { - let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); - let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); - if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { - // allowed similarity foo_x, foo_y - // or too many chars differ (foo_x, boo_y) or (foox, booy) - continue; - } - split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); - } - } else { - let second_i = interned_chars.next().expect("we know we have at least two chars"); - let second_e = existing_chars.next().expect("we know we have at least two chars"); - if !eq_or_numeric(second_i, second_e) || second_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { - // allowed similarity x_foo, y_foo - // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) - continue; - } - split_at = interned_name.chars().next().map(|c| c.len_utf8()); - } - } - span_lint_and_then(self.0.cx, - SIMILAR_NAMES, - span, - "binding's name is too similar to existing binding", - |diag| { - diag.span_note(existing_name.span, "existing binding defined here"); - if let Some(split) = split_at { - diag.span_help(span, - &format!("separate the discriminating character by an \ - underscore like: `{}_{}`", - &interned_name[..split], - &interned_name[split..])); - } - }); - return; - } - self.0.names.push(ExistingName { - whitelist: get_whitelist(&interned_name).unwrap_or(&[]), - interned: interned_name, - span: span, - len: count, - }); - } -} - -impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { - /// ensure scoping rules work - fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) { - let n = self.names.len(); - let single_char_count = self.single_char_names.len(); - f(self); - self.names.truncate(n); - self.single_char_names.truncate(single_char_count); - } -} - -impl<'v, 'a, 'b> Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { - fn visit_local(&mut self, local: &'v Local) { - if let Some(ref init) = local.init { - self.apply(|this| walk_expr(this, &**init)); - } - // add the pattern after the expression because the bindings aren't available yet in the init expression - SimilarNamesNameVisitor(self).visit_pat(&*local.pat); - } - fn visit_block(&mut self, blk: &'v Block) { - self.apply(|this| walk_block(this, blk)); - } - fn visit_arm(&mut self, arm: &'v Arm) { - self.apply(|this| { - // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier - SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); - this.apply(|this| walk_expr(this, &arm.body)); - }); - } - fn visit_item(&mut self, _: &'v Item) { - // do not recurse into inner items - } -} - -impl EarlyLintPass for NonExpressiveNames { - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node { - if !attr::contains_name(&item.attrs, "test") { - let mut visitor = SimilarNamesLocalVisitor { - names: Vec::new(), - cx: cx, - lint: self, - single_char_names: Vec::new(), - }; - // initialize with function arguments - for arg in &decl.inputs { - SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); - } - // walk all other bindings - walk_block(&mut visitor, blk); - } - } - } -} - -/// Precondition: `a_name.chars().count() < b_name.chars().count()`. -fn levenstein_not_1(a_name: &str, b_name: &str) -> bool { - debug_assert!(a_name.chars().count() < b_name.chars().count()); - let mut a_chars = a_name.chars(); - let mut b_chars = b_name.chars(); - while let (Some(a), Some(b)) = (a_chars.next(), b_chars.next()) { - if a == b { - continue; - } - if let Some(b2) = b_chars.next() { - // check if there's just one character inserted - return a != b2 || a_chars.ne(b_chars); - } else { - // tuple - // ntuple - return true; - } - } - // for item in items - true -} diff --git a/src/open_options.rs b/src/open_options.rs deleted file mode 100644 index 1d760599e3f..00000000000 --- a/src/open_options.rs +++ /dev/null @@ -1,185 +0,0 @@ -use rustc::hir::{Expr, ExprMethodCall, ExprLit}; -use rustc::lint::*; -use syntax::ast::LitKind; -use syntax::codemap::{Span, Spanned}; -use utils::{match_type, paths, span_lint, walk_ptrs_ty_depth}; - -/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. -/// -/// **Why is this bad?** In the best case, the code will be harder to read than necessary. I don't know the worst case. -/// -/// **Known problems:** None -/// -/// **Example:** `OpenOptions::new().read(true).truncate(true)` -declare_lint! { - pub NONSENSICAL_OPEN_OPTIONS, - Warn, - "nonsensical combination of options for opening a file" -} - - -#[derive(Copy,Clone)] -pub struct NonSensicalOpenOptions; - -impl LintPass for NonSensicalOpenOptions { - fn get_lints(&self) -> LintArray { - lint_array!(NONSENSICAL_OPEN_OPTIONS) - } -} - -impl LateLintPass for NonSensicalOpenOptions { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprMethodCall(ref name, _, ref arguments) = e.node { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); - if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { - let mut options = Vec::new(); - get_open_options(cx, &arguments[0], &mut options); - check_open_options(cx, &options, e.span); - } - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -enum Argument { - True, - False, - Unknown, -} - -#[derive(Debug)] -enum OpenOption { - Write, - Read, - Truncate, - Create, - Append, -} - -fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { - if let ExprMethodCall(ref name, _, ref arguments) = argument.node { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); - - // Only proceed if this is a call on some object of type std::fs::OpenOptions - if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { - - let argument_option = match arguments[1].node { - ExprLit(ref span) => { - if let Spanned { node: LitKind::Bool(lit), .. } = **span { - if lit { - Argument::True - } else { - Argument::False - } - } else { - return; // The function is called with a literal - // which is not a boolean literal. This is theoretically - // possible, but not very likely. - } - } - _ => Argument::Unknown, - }; - - match &*name.node.as_str() { - "create" => { - options.push((OpenOption::Create, argument_option)); - } - "append" => { - options.push((OpenOption::Append, argument_option)); - } - "truncate" => { - options.push((OpenOption::Truncate, argument_option)); - } - "read" => { - options.push((OpenOption::Read, argument_option)); - } - "write" => { - options.push((OpenOption::Write, argument_option)); - } - _ => (), - } - - get_open_options(cx, &arguments[0], options); - } - } -} - -fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { - let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); - let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, - false, - false, - false, - false); - // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. - - for option in options { - match *option { - (OpenOption::Create, arg) => { - if create { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"create\" is called more than once"); - } else { - create = true - } - create_arg = create_arg || (arg == Argument::True);; - } - (OpenOption::Append, arg) => { - if append { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"append\" is called more than once"); - } else { - append = true - } - append_arg = append_arg || (arg == Argument::True);; - } - (OpenOption::Truncate, arg) => { - if truncate { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"truncate\" is called more than once"); - } else { - truncate = true - } - truncate_arg = truncate_arg || (arg == Argument::True); - } - (OpenOption::Read, arg) => { - if read { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"read\" is called more than once"); - } else { - read = true - } - read_arg = read_arg || (arg == Argument::True);; - } - (OpenOption::Write, arg) => { - if write { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"write\" is called more than once"); - } else { - write = true - } - write_arg = write_arg || (arg == Argument::True);; - } - } - } - - if read && truncate && read_arg && truncate_arg { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\""); - } - if append && truncate && append_arg && truncate_arg { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "file opened with \"append\" and \"truncate\""); - } -} diff --git a/src/overflow_check_conditional.rs b/src/overflow_check_conditional.rs deleted file mode 100644 index 34921bc2c04..00000000000 --- a/src/overflow_check_conditional.rs +++ /dev/null @@ -1,72 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use utils::span_lint; - -/// **What it does:** This lint finds classic underflow / overflow checks. -/// -/// **Why is this bad?** Most classic C underflow / overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead. -/// -/// **Known problems:** None. -/// -/// **Example:** `a + b < a` - -declare_lint!(pub OVERFLOW_CHECK_CONDITIONAL, Warn, - "Using overflow checks which are likely to panic"); - -#[derive(Copy, Clone)] -pub struct OverflowCheckConditional; - -impl LintPass for OverflowCheckConditional { - fn get_lints(&self) -> LintArray { - lint_array!(OVERFLOW_CHECK_CONDITIONAL) - } -} - -impl LateLintPass for OverflowCheckConditional { - // a + b < a, a > a + b, a < a - b, a - b > a - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, - let Expr_::ExprPath(_,ref path1) = ident1.node, - let Expr_::ExprPath(_, ref path2) = ident2.node, - let Expr_::ExprPath(_, ref path3) = second.node, - &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], - cx.tcx.expr_ty(ident1).is_integral(), - cx.tcx.expr_ty(ident2).is_integral() - ], { - if let BinOp_::BiLt = op.node { - if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); - } - } - if let BinOp_::BiGt = op.node { - if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); - } - } - }} - - if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, - let Expr_::ExprPath(_,ref path1) = ident1.node, - let Expr_::ExprPath(_, ref path2) = ident2.node, - let Expr_::ExprPath(_, ref path3) = first.node, - &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], - cx.tcx.expr_ty(ident1).is_integral(), - cx.tcx.expr_ty(ident2).is_integral() - ], { - if let BinOp_::BiGt = op.node { - if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); - } - } - if let BinOp_::BiLt = op.node { - if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); - } - } - }} - } -} diff --git a/src/panic.rs b/src/panic.rs deleted file mode 100644 index d744d2a6308..00000000000 --- a/src/panic.rs +++ /dev/null @@ -1,47 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_path, paths, span_lint}; - -/// **What it does:** This lint checks for missing parameters in `panic!`. -/// -/// **Known problems:** Should you want to use curly brackets in `panic!` without any parameter, -/// this lint will warn. -/// -/// **Example:** -/// ``` -/// panic!("This `panic!` is probably missing a parameter there: {}"); -/// ``` -declare_lint! { - pub PANIC_PARAMS, Warn, "missing parameters in `panic!`" -} - -#[allow(missing_copy_implementations)] -pub struct PanicPass; - -impl LintPass for PanicPass { - fn get_lints(&self) -> LintArray { - lint_array!(PANIC_PARAMS) - } -} - -impl LateLintPass for PanicPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain! {[ - let ExprBlock(ref block) = expr.node, - let Some(ref ex) = block.expr, - let ExprCall(ref fun, ref params) = ex.node, - params.len() == 2, - let ExprPath(None, ref path) = fun.node, - match_path(path, &paths::BEGIN_PANIC), - let ExprLit(ref lit) = params[0].node, - is_direct_expn_of(cx, params[0].span, "panic").is_some(), - let LitKind::Str(ref string, _) = lit.node, - let Some(par) = string.find('{'), - string[par..].contains('}') - ], { - span_lint(cx, PANIC_PARAMS, params[0].span, - "you probably are missing some parameter in your format string"); - }} - } -} diff --git a/src/precedence.rs b/src/precedence.rs deleted file mode 100644 index 825a1b84450..00000000000 --- a/src/precedence.rs +++ /dev/null @@ -1,118 +0,0 @@ -use rustc::lint::*; -use syntax::ast::*; -use syntax::codemap::Spanned; -use utils::{span_lint, snippet}; - -/// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following: -/// * mixed usage of arithmetic and bit shifting/combining operators without parentheses -/// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call -/// -/// **Why is this bad?** Because not everyone knows the precedence of those operators by heart, so expressions like these may trip others trying to reason about the code. -/// -/// **Known problems:** None -/// -/// **Examples:** -/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 -/// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 -declare_lint! { - pub PRECEDENCE, Warn, - "catches operations where precedence may be unclear. See the wiki for a \ - list of cases caught" -} - -#[derive(Copy,Clone)] -pub struct Precedence; - -impl LintPass for Precedence { - fn get_lints(&self) -> LintArray { - lint_array!(PRECEDENCE) - } -} - -impl EarlyLintPass for Precedence { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { - if !is_bit_op(op) { - return; - } - match (is_arith_expr(left), is_arith_expr(right)) { - (true, true) => { - span_lint(cx, - PRECEDENCE, - expr.span, - &format!("operator precedence can trip the unwary. Consider parenthesizing your \ - expression:`({}) {} ({})`", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, ".."))); - } - (true, false) => { - span_lint(cx, - PRECEDENCE, - expr.span, - &format!("operator precedence can trip the unwary. Consider parenthesizing your \ - expression:`({}) {} {}`", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, ".."))); - } - (false, true) => { - span_lint(cx, - PRECEDENCE, - expr.span, - &format!("operator precedence can trip the unwary. Consider parenthesizing your \ - expression:`{} {} ({})`", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, ".."))); - } - _ => (), - } - } - - if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.node { - if let ExprKind::MethodCall(_, _, ref args) = rhs.node { - if let Some(slf) = args.first() { - if let ExprKind::Lit(ref lit) = slf.node { - match lit.node { - LitKind::Int(..) | - LitKind::Float(..) | - LitKind::FloatUnsuffixed(..) => { - span_lint(cx, - PRECEDENCE, - expr.span, - &format!("unary minus has lower precedence than method call. Consider \ - adding parentheses to clarify your intent: -({})", - snippet(cx, rhs.span, ".."))); - } - _ => (), - } - } - } - } - } - } -} - -fn is_arith_expr(expr: &Expr) -> bool { - match expr.node { - ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op), - _ => false, - } -} - -fn is_bit_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; - match op { - BitXor | BitAnd | BitOr | Shl | Shr => true, - _ => false, - } -} - -fn is_arith_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; - match op { - Add | Sub | Mul | Div | Rem => true, - _ => false, - } -} diff --git a/src/print.rs b/src/print.rs deleted file mode 100644 index d426286dba4..00000000000 --- a/src/print.rs +++ /dev/null @@ -1,88 +0,0 @@ -use rustc::hir::*; -use rustc::hir::map::Node::{NodeItem, NodeImplItem}; -use rustc::lint::*; -use utils::paths; -use utils::{is_expn_of, match_path, span_lint}; - -/// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants. -/// -/// **Why is this bad?** People often print on *stdout* while debugging an application and might -/// forget to remove those prints afterward. -/// -/// **Known problems:** Only catches `print!` and `println!` calls. -/// -/// **Example:** `println!("Hello world!");` -declare_lint! { - pub PRINT_STDOUT, - Allow, - "printing on stdout" -} - -/// **What it does:** This lint warns whenever you use `Debug` formatting. The purpose of this lint is to catch debugging remnants. -/// -/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate debugging Rust code. It -/// should not be used in in user-facing output. -/// -/// **Example:** `println!("{:?}", foo);` -declare_lint! { - pub USE_DEBUG, - Allow, - "use `Debug`-based formatting" -} - -#[derive(Copy, Clone, Debug)] -pub struct PrintLint; - -impl LintPass for PrintLint { - fn get_lints(&self) -> LintArray { - lint_array!(PRINT_STDOUT, USE_DEBUG) - } -} - -impl LateLintPass for PrintLint { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprCall(ref fun, ref args) = expr.node { - if let ExprPath(_, ref path) = fun.node { - // Search for `std::io::_print(..)` which is unique in a - // `print!` expansion. - if match_path(path, &paths::IO_PRINT) { - if let Some(span) = is_expn_of(cx, expr.span, "print") { - // `println!` uses `print!`. - let (span, name) = match is_expn_of(cx, span, "println") { - Some(span) => (span, "println"), - None => (span, "print"), - }; - - span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - } - } - // Search for something like - // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` - else if args.len() == 2 && match_path(path, &paths::FMT_ARGUMENTV1_NEW) { - if let ExprPath(None, ref path) = args[1].node { - if match_path(path, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && - is_expn_of(cx, expr.span, "panic").is_none() { - span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); - } - } - } - } - } - } -} - -fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { - let map = &cx.tcx.map; - - // `fmt` method - if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { - // `Debug` impl - if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { - if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node { - return match_path(&tr.path, &["Debug"]); - } - } - } - - false -} diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs deleted file mode 100644 index addcfc9e84d..00000000000 --- a/src/ptr_arg.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Checks for usage of `&Vec[_]` and `&String`. - -use rustc::hir::*; -use rustc::hir::map::NodeItem; -use rustc::lint::*; -use rustc::ty; -use syntax::ast::NodeId; -use utils::{match_type, paths, span_lint}; - -/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. -/// -/// **Why is this bad?** Requiring the argument to be of the specific size makes the function less useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be obtained from other types, too. -/// -/// **Known problems:** None -/// -/// **Example:** `fn foo(&Vec<u32>) { .. }` -declare_lint! { - pub PTR_ARG, - Warn, - "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ - instead, respectively" -} - -#[derive(Copy,Clone)] -pub struct PtrArg; - -impl LintPass for PtrArg { - fn get_lints(&self) -> LintArray { - lint_array!(PTR_ARG) - } -} - -impl LateLintPass for PtrArg { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemFn(ref decl, _, _, _, _, _) = item.node { - check_fn(cx, decl, item.id); - } - } - - fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - if let ImplItemKind::Method(ref sig, _) = item.node { - if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) { - if let ItemImpl(_, _, _, Some(_), _, _) = it.node { - return; // ignore trait impls - } - } - check_fn(cx, &sig.decl, item.id); - } - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - if let MethodTraitItem(ref sig, _) = item.node { - check_fn(cx, &sig.decl, item.id); - } - } -} - -fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { - let fn_ty = cx.tcx.node_id_to_type(fn_id).fn_sig().skip_binder(); - - for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) { - if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { - if match_type(cx, ty, &paths::VEC) { - span_lint(cx, - PTR_ARG, - arg.ty.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`"); - } else if match_type(cx, ty, &paths::STRING) { - span_lint(cx, - PTR_ARG, - arg.ty.span, - "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`"); - } - } - } -} diff --git a/src/ranges.rs b/src/ranges.rs deleted file mode 100644 index e96212a9cef..00000000000 --- a/src/ranges.rs +++ /dev/null @@ -1,89 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use syntax::codemap::Spanned; -use utils::{is_integer_literal, match_type, paths, snippet, span_lint, unsugar_range, UnsugaredRange}; - -/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. -/// -/// **Why is this bad?** This very much looks like an oversight, since with `loop { .. }` there is an obvious better way to endlessly loop. -/// -/// **Known problems:** None -/// -/// **Example:** `for x in (5..5).step_by(0) { .. }` -declare_lint! { - pub RANGE_STEP_BY_ZERO, Warn, - "using Range::step_by(0), which produces an infinite iterator" -} -/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. -/// -/// **Why is this bad?** The code is better expressed with `.enumerate()`. -/// -/// **Known problems:** None -/// -/// **Example:** `x.iter().zip(0..x.len())` -declare_lint! { - pub RANGE_ZIP_WITH_LEN, Warn, - "zipping iterator with a range when enumerate() would do" -} - -#[derive(Copy,Clone)] -pub struct StepByZero; - -impl LintPass for StepByZero { - fn get_lints(&self) -> LintArray { - lint_array!(RANGE_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN) - } -} - -impl LateLintPass for StepByZero { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node { - // Range with step_by(0). - if name.as_str() == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) && - is_integer_literal(&args[1], 0) { - span_lint(cx, - RANGE_STEP_BY_ZERO, - expr.span, - "Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \ - instead"); - } else if name.as_str() == "zip" && args.len() == 2 { - let iter = &args[0].node; - let zip_arg = &args[1]; - if_let_chain! { - [ - // .iter() call - let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, - iter_name.as_str() == "iter", - // range expression in .zip() call: 0..x.len() - let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), - is_integer_literal(start, 0), - // .len() call - let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, - len_name.as_str() == "len" && len_args.len() == 1, - // .iter() and .len() called on same Path - let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, - let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, - iter_path == len_path - ], { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - expr.span, - &format!("It is more idiomatic to use {}.iter().enumerate()", - snippet(cx, iter_args[0].span, "_"))); - } - } - } - } - } -} - -fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { - // No need for walk_ptrs_ty here because step_by moves self, so it - // can't be called on a borrowed range. - let ty = cx.tcx.expr_ty(expr); - - // Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by - match_type(cx, ty, &paths::RANGE) - || match_type(cx, ty, &paths::RANGE_FROM) - || match_type(cx, ty, &paths::RANGE_INCLUSIVE) -} diff --git a/src/regex.rs b/src/regex.rs deleted file mode 100644 index c97a64ebf09..00000000000 --- a/src/regex.rs +++ /dev/null @@ -1,229 +0,0 @@ -use regex_syntax; -use rustc::hir::*; -use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc_const_eval::EvalHint::ExprTypeChecked; -use rustc_const_eval::eval_const_expr_partial; -use std::collections::HashSet; -use std::error::Error; -use syntax::ast::{LitKind, NodeId}; -use syntax::codemap::{Span, BytePos}; -use syntax::parse::token::InternedString; -use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; - -/// **What it does:** This lint checks [regex] creation (with `Regex::new`, `RegexBuilder::new` or -/// `RegexSet::new`) for correct regex syntax. -/// -/// **Why is this bad?** This will lead to a runtime panic. -/// -/// **Known problems:** None. -/// -/// **Example:** `Regex::new("|")` -declare_lint! { - pub INVALID_REGEX, - Deny, - "finds invalid regular expressions" -} - -/// **What it does:** This lint checks for trivial [regex] creation (with `Regex::new`, -/// `RegexBuilder::new` or `RegexSet::new`). -/// -/// **Why is this bad?** This can likely be replaced by `==` or `str::starts_with`, -/// `str::ends_with` or `std::contains` or other `str` methods. -/// -/// **Known problems:** None. -/// -/// **Example:** `Regex::new("^foobar")` -/// -/// [regex]: https://crates.io/crates/regex -declare_lint! { - pub TRIVIAL_REGEX, - Warn, - "finds trivial regular expressions" -} - -/// **What it does:** This lint checks for usage of `regex!(_)` which as of now is usually slower than `Regex::new(_)` unless called in a loop (which is a bad idea anyway). -/// -/// **Why is this bad?** Performance, at least for now. The macro version is likely to catch up long-term, but for now the dynamic version is faster. -/// -/// **Known problems:** None -/// -/// **Example:** `regex!("foo|bar")` -declare_lint! { - pub REGEX_MACRO, - Warn, - "finds use of `regex!(_)`, suggests `Regex::new(_)` instead" -} - -#[derive(Clone, Default)] -pub struct RegexPass { - spans: HashSet<Span>, - last: Option<NodeId>, -} - -impl LintPass for RegexPass { - fn get_lints(&self) -> LintArray { - lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) - } -} - -impl LateLintPass for RegexPass { - fn check_crate(&mut self, _: &LateContext, _: &Crate) { - self.spans.clear(); - } - - fn check_block(&mut self, cx: &LateContext, block: &Block) { - if_let_chain!{[ - self.last.is_none(), - let Some(ref expr) = block.expr, - match_type(cx, cx.tcx.expr_ty(expr), &paths::REGEX), - let Some(span) = is_expn_of(cx, expr.span, "regex"), - ], { - if !self.spans.contains(&span) { - span_lint(cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now."); - self.spans.insert(span); - } - self.last = Some(block.id); - }} - } - - fn check_block_post(&mut self, _: &LateContext, block: &Block) { - if self.last.map_or(false, |id| block.id == id) { - self.last = None; - } - } - - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain!{[ - let ExprCall(ref fun, ref args) = expr.node, - args.len() == 1, - let Some(def) = cx.tcx.def_map.borrow().get(&fun.id), - ], { - let def_id = def.def_id(); - if match_def_path(cx, def_id, &paths::REGEX_NEW) { - check_regex(cx, &args[0], true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) { - check_regex(cx, &args[0], false); - } else if match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { - check_regex(cx, &args[0], true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { - check_regex(cx, &args[0], false); - } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { - check_set(cx, &args[0], true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { - check_set(cx, &args[0], false); - } - }} - } -} - -#[allow(cast_possible_truncation)] -fn str_span(base: Span, s: &str, c: usize) -> Span { - let mut si = s.char_indices().skip(c); - - match (si.next(), si.next()) { - (Some((l, _)), Some((h, _))) => { - Span { - lo: base.lo + BytePos(l as u32), - hi: base.lo + BytePos(h as u32), - ..base - } - } - _ => base, - } -} - -fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> { - match eval_const_expr_partial(cx.tcx, e, ExprTypeChecked, None) { - Ok(ConstVal::Str(r)) => Some(r), - _ => None, - } -} - -fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { - use regex_syntax::Expr; - - match *s { - Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), - Expr::Literal { .. } => Some("consider using `str::contains`"), - Expr::Concat(ref exprs) => { - match exprs.len() { - 2 => { - match (&exprs[0], &exprs[1]) { - (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), - (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), - _ => None, - } - } - 3 => { - if let (&Expr::StartText, &Expr::Literal {..}, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { - Some("consider using `==` on `str`s") - } else { - None - } - } - _ => None, - } - } - _ => None, - } -} - -fn check_set(cx: &LateContext, expr: &Expr, utf8: bool) { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, - let ExprVec(ref exprs) = expr.node, - ], { - for expr in exprs { - check_regex(cx, expr, utf8); - } - }} -} - -fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { - let builder = regex_syntax::ExprBuilder::new().unicode(utf8); - - if let ExprLit(ref lit) = expr.node { - if let LitKind::Str(ref r, _) = lit.node { - match builder.parse(r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, - "trivial regex", - &format!("consider using {}", repl)); - } - } - Err(e) => { - span_lint(cx, - INVALID_REGEX, - str_span(expr.span, r, e.position()), - &format!("regex syntax error: {}", - e.description())); - } - } - } - } else if let Some(r) = const_str(cx, expr) { - match builder.parse(&r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, - "trivial regex", - &format!("consider using {}", repl)); - } - } - Err(e) => { - span_lint(cx, - INVALID_REGEX, - expr.span, - &format!("regex syntax error on position {}: {}", - e.position(), - e.description())); - } - } - } -} diff --git a/src/returns.rs b/src/returns.rs deleted file mode 100644 index d7893821263..00000000000 --- a/src/returns.rs +++ /dev/null @@ -1,137 +0,0 @@ -use rustc::lint::*; -use syntax::ast::*; -use syntax::codemap::{Span, Spanned}; -use syntax::visit::FnKind; - -use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; - -/// **What it does:** This lint checks for return statements at the end of a block. -/// -/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty. -/// -/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. -/// -/// **Example:** `fn foo(x: usize) { return x; }` -declare_lint! { - pub NEEDLESS_RETURN, Warn, - "using a return statement like `return expr;` where an expression would suffice" -} - -/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. -/// -/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty. -/// -/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed. -/// -/// **Example:** `{ let x = ..; x }` -declare_lint! { - pub LET_AND_RETURN, Warn, - "creating a let-binding and then immediately returning it like `let x = expr; x` at \ - the end of a block" -} - -#[derive(Copy, Clone)] -pub struct ReturnPass; - -impl ReturnPass { - // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) { - if let Some(ref expr) = block.expr { - self.check_final_expr(cx, expr); - } else if let Some(stmt) = block.stmts.last() { - if let StmtKind::Semi(ref expr, _) = stmt.node { - if let ExprKind::Ret(Some(ref inner)) = expr.node { - self.emit_return_lint(cx, (stmt.span, inner.span)); - } - } - } - } - - // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - match expr.node { - // simple return is always "bad" - ExprKind::Ret(Some(ref inner)) => { - self.emit_return_lint(cx, (expr.span, inner.span)); - } - // a whole block? check it! - ExprKind::Block(ref block) => { - self.check_block_return(cx, block); - } - // an if/if let expr, check both exprs - // note, if without else is going to be a type checking error anyways - // (except for unit type functions) so we don't match it - ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => { - self.check_block_return(cx, ifblock); - self.check_final_expr(cx, elsexpr); - } - // a match expr, check all arms - ExprKind::Match(_, ref arms) => { - for arm in arms { - self.check_final_expr(cx, &arm.body); - } - } - _ => (), - } - } - - fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { - if in_external_macro(cx, spans.1) { - return; - } - span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| { - if let Some(snippet) = snippet_opt(cx, spans.1) { - db.span_suggestion(spans.0, "remove `return` as shown:", snippet); - } - }); - } - - // Check for "let x = EXPR; x" - fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { - // we need both a let-binding stmt and an expr - if_let_chain! { - [ - let Some(stmt) = block.stmts.last(), - let Some(ref retexpr) = block.expr, - let StmtKind::Decl(ref decl, _) = stmt.node, - let DeclKind::Local(ref local) = decl.node, - let Some(ref initexpr) = local.init, - let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, - let ExprKind::Path(_, ref path) = retexpr.node, - match_path_ast(path, &[&id.name.as_str()]) - ], { - self.emit_let_lint(cx, retexpr.span, initexpr.span); - } - } - } - - fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { - if in_external_macro(cx, note_span) { - return; - } - let mut db = span_lint(cx, - LET_AND_RETURN, - lint_span, - "returning the result of a let binding from a block. Consider returning the \ - expression directly."); - if cx.current_level(LET_AND_RETURN) != Level::Allow { - db.span_note(note_span, "this expression can be directly returned"); - } - } -} - -impl LintPass for ReturnPass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RETURN, LET_AND_RETURN) - } -} - -impl EarlyLintPass for ReturnPass { - fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { - self.check_block_return(cx, block); - } - - fn check_block(&mut self, cx: &EarlyContext, block: &Block) { - self.check_let_return(cx, block); - } -} diff --git a/src/shadow.rs b/src/shadow.rs deleted file mode 100644 index 2a0d36a80b3..00000000000 --- a/src/shadow.rs +++ /dev/null @@ -1,353 +0,0 @@ -use reexport::*; -use rustc::lint::*; -use rustc::hir::def::Def; -use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, FnKind}; -use std::ops::Deref; -use syntax::codemap::Span; -use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; - -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. -/// -/// **Why is this bad?** Not much, in fact it's a very common pattern in Rust code. Still, some may opt to avoid it in their code base, they can set this lint to `Warn`. -/// -/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. -/// -/// **Example:** `let x = &x;` -declare_lint! { - pub SHADOW_SAME, Allow, - "rebinding a name to itself, e.g. `let mut x = &mut x`" -} - -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. -/// -/// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code. -/// -/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. -/// -/// **Example:** `let x = x + 1;` -declare_lint! { - pub SHADOW_REUSE, Allow, - "rebinding a name to an expression that re-uses the original value, e.g. \ - `let x = x + 1`" -} - -/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. -/// -/// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings. -/// -/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns. -/// -/// **Example:** `let x = y; let x = z; // shadows the earlier binding` -declare_lint! { - pub SHADOW_UNRELATED, Allow, - "The name is re-bound without even using the original value" -} - -#[derive(Copy, Clone)] -pub struct ShadowPass; - -impl LintPass for ShadowPass { - fn get_lints(&self) -> LintArray { - lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) - } -} - -impl LateLintPass for ShadowPass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { - if in_external_macro(cx, block.span) { - return; - } - check_fn(cx, decl, block); - } -} - -fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { - let mut bindings = Vec::new(); - for arg in &decl.inputs { - if let PatKind::Ident(_, ident, _) = arg.pat.node { - bindings.push((ident.node.unhygienize(), ident.span)) - } - } - check_block(cx, block, &mut bindings); -} - -fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) { - let len = bindings.len(); - for stmt in &block.stmts { - match stmt.node { - StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => check_expr(cx, e, bindings), - } - } - if let Some(ref o) = block.expr { - check_expr(cx, o, bindings); - } - bindings.truncate(len); -} - -fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, decl.span) { - return; - } - if is_from_for_desugar(decl) { - return; - } - if let DeclLocal(ref local) = decl.node { - let Local { ref pat, ref ty, ref init, span, .. } = **local; - if let Some(ref t) = *ty { - check_ty(cx, t, bindings) - } - if let Some(ref o) = *init { - check_expr(cx, o, bindings); - check_pat(cx, pat, &Some(o), span, bindings); - } else { - check_pat(cx, pat, &None, span, bindings); - } - } -} - -fn is_binding(cx: &LateContext, pat: &Pat) -> bool { - match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { - Some(Def::Variant(..)) | - Some(Def::Struct(..)) => false, - _ => true, - } -} - -fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { - // TODO: match more stuff / destructuring - match pat.node { - PatKind::Ident(_, ref ident, ref inner) => { - let name = ident.node.unhygienize(); - if is_binding(cx, pat) { - let mut new_binding = true; - for tup in bindings.iter_mut() { - if tup.0 == name { - lint_shadow(cx, name, span, pat.span, init, tup.1); - tup.1 = ident.span; - new_binding = false; - break; - } - } - if new_binding { - bindings.push((name, ident.span)); - } - } - if let Some(ref p) = *inner { - check_pat(cx, p, init, span, bindings); - } - } - // PatEnum(Path, Option<Vec<P<Pat>>>), - PatKind::Struct(_, ref pfields, _) => { - if let Some(ref init_struct) = *init { - if let ExprStruct(_, ref efields, _) = init_struct.node { - for field in pfields { - let name = field.node.name; - let efield = efields.iter() - .find(|ref f| f.name.node == name) - .map(|f| &*f.expr); - check_pat(cx, &field.node.pat, &efield, span, bindings); - } - } else { - for field in pfields { - check_pat(cx, &field.node.pat, init, span, bindings); - } - } - } else { - for field in pfields { - check_pat(cx, &field.node.pat, &None, span, bindings); - } - } - } - PatKind::Tup(ref inner) => { - if let Some(ref init_tup) = *init { - if let ExprTup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, &Some(&tup[i]), p.span, bindings); - } - } else { - for p in inner { - check_pat(cx, p, init, span, bindings); - } - } - } else { - for p in inner { - check_pat(cx, p, &None, span, bindings); - } - } - } - PatKind::Box(ref inner) => { - if let Some(ref initp) = *init { - if let ExprBox(ref inner_init) = initp.node { - check_pat(cx, inner, &Some(&**inner_init), span, bindings); - } else { - check_pat(cx, inner, init, span, bindings); - } - } else { - check_pat(cx, inner, init, span, bindings); - } - } - PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), - // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), - _ => (), - } -} - -fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span) - where T: Deref<Target = Expr> -{ - fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { - if cx.current_level(lint) != Level::Allow { - db.span_note(span, "previous binding is here"); - } - } - if let Some(ref expr) = *init { - if is_self_shadow(name, expr) { - let db = span_lint(cx, - SHADOW_SAME, - span, - &format!("`{}` is shadowed by itself in `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, ".."))); - - note_orig(cx, db, SHADOW_SAME, prev_span); - } else if contains_self(name, expr) { - let db = span_note_and_lint(cx, - SHADOW_REUSE, - pattern_span, - &format!("`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_REUSE, prev_span); - } else { - let db = span_note_and_lint(cx, - SHADOW_UNRELATED, - pattern_span, - &format!("`{}` is shadowed by `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_UNRELATED, prev_span); - } - - } else { - let db = span_lint(cx, - SHADOW_UNRELATED, - span, - &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_"))); - note_orig(cx, db, SHADOW_UNRELATED, prev_span); - } -} - -fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, expr.span) { - return; - } - match expr.node { - ExprUnary(_, ref e) | - ExprField(ref e, _) | - ExprTupField(ref e, _) | - ExprAddrOf(_, ref e) | - ExprBox(ref e) => check_expr(cx, e, bindings), - ExprBlock(ref block) | - ExprLoop(ref block, _) => check_block(cx, block, bindings), - // ExprCall - // ExprMethodCall - ExprVec(ref v) | ExprTup(ref v) => { - for ref e in v { - check_expr(cx, e, bindings) - } - } - ExprIf(ref cond, ref then, ref otherwise) => { - check_expr(cx, cond, bindings); - check_block(cx, then, bindings); - if let Some(ref o) = *otherwise { - check_expr(cx, o, bindings); - } - } - ExprWhile(ref cond, ref block, _) => { - check_expr(cx, cond, bindings); - check_block(cx, block, bindings); - } - ExprMatch(ref init, ref arms, _) => { - check_expr(cx, init, bindings); - let len = bindings.len(); - for ref arm in arms { - for ref pat in &arm.pats { - check_pat(cx, pat, &Some(&**init), pat.span, bindings); - // This is ugly, but needed to get the right type - if let Some(ref guard) = arm.guard { - check_expr(cx, guard, bindings); - } - check_expr(cx, &arm.body, bindings); - bindings.truncate(len); - } - } - } - _ => (), - } -} - -fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) { - match ty.node { - TyObjectSum(ref sty, _) | - TyVec(ref sty) => check_ty(cx, sty, bindings), - TyFixedLengthVec(ref fty, ref expr) => { - check_ty(cx, fty, bindings); - check_expr(cx, expr, bindings); - } - TyPtr(MutTy { ty: ref mty, .. }) | - TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => { - for ref t in tup { - check_ty(cx, t, bindings) - } - } - TyTypeof(ref expr) => check_expr(cx, expr, bindings), - _ => (), - } -} - -fn is_self_shadow(name: Name, expr: &Expr) -> bool { - match expr.node { - ExprBox(ref inner) | - ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), - ExprBlock(ref block) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |ref e| is_self_shadow(name, e)) - } - ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), - ExprPath(_, ref path) => path_eq_name(name, path), - _ => false, - } -} - -fn path_eq_name(name: Name, path: &Path) -> bool { - !path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name -} - -struct ContainsSelf { - name: Name, - result: bool, -} - -impl<'v> Visitor<'v> for ContainsSelf { - fn visit_name(&mut self, _: Span, name: Name) { - if self.name == name.unhygienize() { - self.result = true; - } - } -} - -fn contains_self(name: Name, expr: &Expr) -> bool { - let mut cs = ContainsSelf { - name: name, - result: false, - }; - cs.visit_expr(expr); - cs.result -} diff --git a/src/strings.rs b/src/strings.rs deleted file mode 100644 index 92bce8d0e42..00000000000 --- a/src/strings.rs +++ /dev/null @@ -1,160 +0,0 @@ -//! This lint catches both string addition and string addition + assignment -//! -//! Note that since we have two lints where one subsumes the other, we try to -//! disable the subsumed lint unless it has a higher level - -use rustc::hir::*; -use rustc::lint::*; -use syntax::codemap::Spanned; -use utils::SpanlessEq; -use utils::{match_type, paths, span_lint, span_lint_and_then, walk_ptrs_ty, get_parent_expr}; - -/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). -/// -/// **Why is this bad?** It's not really bad, but some people think that the `.push_str(_)` method is more readable. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ``` -/// let mut x = "Hello".to_owned(); -/// x = x + ", World"; -/// ``` -declare_lint! { - pub STRING_ADD_ASSIGN, - Allow, - "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" -} - -/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. -/// -/// **Why is this bad?** It's not bad in and of itself. However, this particular `Add` implementation is asymmetric (the other operand need not be `String`, but `x` does), while addition as mathematically defined is symmetric, also the `String::push_str(_)` function is a perfectly good replacement. Therefore some dislike it and wish not to have it in their code. -/// -/// That said, other people think that String addition, having a long tradition in other languages is actually fine, which is why we decided to make this particular lint `allow` by default. -/// -/// **Known problems:** None -/// -/// **Example:** -/// -/// ``` -/// let x = "Hello".to_owned(); -/// x + ", World" -/// ``` -declare_lint! { - pub STRING_ADD, - Allow, - "using `x + ..` where x is a `String`; suggests using `push_str()` instead" -} - -/// **What it does:** This lint matches the `as_bytes` method called on string -/// literals that contain only ascii characters. -/// -/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used instead. They are shorter but less discoverable than `as_bytes()`. -/// -/// **Example:** -/// -/// ``` -/// let bs = "a byte string".as_bytes(); -/// ``` -declare_lint! { - pub STRING_LIT_AS_BYTES, - Warn, - "calling `as_bytes` on a string literal; suggests using a byte string literal instead" -} - -#[derive(Copy, Clone)] -pub struct StringAdd; - -impl LintPass for StringAdd { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD, STRING_ADD_ASSIGN) - } -} - -impl LateLintPass for StringAdd { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { - if is_string(cx, left) { - if let Allow = cx.current_level(STRING_ADD_ASSIGN) { - // the string_add_assign is allow, so no duplicates - } else { - let parent = get_parent_expr(cx, e); - if let Some(ref p) = parent { - if let ExprAssign(ref target, _) = p.node { - // avoid duplicate matches - if SpanlessEq::new(cx).eq_expr(target, left) { - return; - } - } - } - } - span_lint(cx, - STRING_ADD, - e.span, - "you added something to a string. Consider using `String::push_str()` instead"); - } - } else if let ExprAssign(ref target, ref src) = e.node { - if is_string(cx, target) && is_add(cx, src, target) { - span_lint(cx, - STRING_ADD_ASSIGN, - e.span, - "you assigned the result of adding something to this string. Consider using \ - `String::push_str()` instead"); - } - } - } -} - -fn is_string(cx: &LateContext, e: &Expr) -> bool { - match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &paths::STRING) -} - -fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { - match src.node { - ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), - ExprBlock(ref block) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) - } - _ => false, - } -} - -#[derive(Copy, Clone)] -pub struct StringLitAsBytes; - -impl LintPass for StringLitAsBytes { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_LIT_AS_BYTES) - } -} - -impl LateLintPass for StringLitAsBytes { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - use std::ascii::AsciiExt; - use syntax::ast::LitKind; - use utils::{snippet, in_macro}; - - if let ExprMethodCall(ref name, _, ref args) = e.node { - if name.node.as_str() == "as_bytes" { - if let ExprLit(ref lit) = args[0].node { - if let LitKind::Str(ref lit_content, _) = lit.node { - if lit_content.chars().all(|c| c.is_ascii()) && !in_macro(cx, args[0].span) { - span_lint_and_then(cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `as_bytes()` on a string literal", - |db| { - let sugg = format!("b{}", snippet(cx, args[0].span, r#""foo""#)); - db.span_suggestion(e.span, - "consider using a byte string literal instead", - sugg); - }); - - } - } - } - } - } - } -} diff --git a/src/swap.rs b/src/swap.rs deleted file mode 100644 index c5572181395..00000000000 --- a/src/swap.rs +++ /dev/null @@ -1,138 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use syntax::codemap::mk_sp; -use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; - -/// **What it does:** This lints manual swapping. -/// -/// **Why is this bad?** The `std::mem::swap` function exposes the intent better without -/// deinitializing or copying either variable. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// let t = b; -/// b = a; -/// a = t; -/// ``` -declare_lint! { - pub MANUAL_SWAP, - Warn, - "manual swap" -} - -/// **What it does:** This lints `foo = bar; bar = foo` sequences. -/// -/// **Why is this bad?** This looks like a failed attempt to swap. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// a = b; -/// b = a; -/// ``` -declare_lint! { - pub ALMOST_SWAPPED, - Warn, - "`foo = bar; bar = foo` sequence" -} - -#[derive(Copy,Clone)] -pub struct Swap; - -impl LintPass for Swap { - fn get_lints(&self) -> LintArray { - lint_array![MANUAL_SWAP, ALMOST_SWAPPED] - } -} - -impl LateLintPass for Swap { - fn check_block(&mut self, cx: &LateContext, block: &Block) { - check_manual_swap(cx, block); - check_suspicious_swap(cx, block); - } -} - -/// Implementation of the `MANUAL_SWAP` lint. -fn check_manual_swap(cx: &LateContext, block: &Block) { - for w in block.stmts.windows(3) { - if_let_chain!{[ - // let t = foo(); - let StmtDecl(ref tmp, _) = w[0].node, - let DeclLocal(ref tmp) = tmp.node, - let Some(ref tmp_init) = tmp.init, - let PatKind::Ident(_, ref tmp_name, None) = tmp.pat.node, - - // foo() = bar(); - let StmtSemi(ref first, _) = w[1].node, - let ExprAssign(ref lhs1, ref rhs1) = first.node, - - // bar() = t; - let StmtSemi(ref second, _) = w[2].node, - let ExprAssign(ref lhs2, ref rhs2) = second.node, - let ExprPath(None, ref rhs2) = rhs2.node, - rhs2.segments.len() == 1, - - tmp_name.node.as_str() == rhs2.segments[0].name.as_str(), - SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), - SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) - ], { - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { - (format!(" `{}` and `{}`", first, second), first, second) - } else { - ("".to_owned(), "".to_owned(), "".to_owned()) - }; - - let span = mk_sp(tmp.span.lo, second.span.hi); - - span_lint_and_then(cx, - MANUAL_SWAP, - span, - &format!("this looks like you are swapping{} manually", what), - |db| { - if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); - db.note("or maybe you should use `std::mem::replace`?"); - } - }); - }} - } -} - -/// Implementation of the `ALMOST_SWAPPED` lint. -fn check_suspicious_swap(cx: &LateContext, block: &Block) { - for w in block.stmts.windows(2) { - if_let_chain!{[ - let StmtSemi(ref first, _) = w[0].node, - let StmtSemi(ref second, _) = w[1].node, - !differing_macro_contexts(first.span, second.span), - let ExprAssign(ref lhs0, ref rhs0) = first.node, - let ExprAssign(ref lhs1, ref rhs1) = second.node, - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) - ], { - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { - (format!(" `{}` and `{}`", first, second), first, second) - } else { - ("".to_owned(), "".to_owned(), "".to_owned()) - }; - - let span = mk_sp(first.span.lo, second.span.hi); - - span_lint_and_then(cx, - ALMOST_SWAPPED, - span, - &format!("this looks like you are trying to swap{}", what), - |db| { - if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); - db.note("or maybe you should use `std::mem::replace`?"); - } - }); - }} - } -} diff --git a/src/temporary_assignment.rs b/src/temporary_assignment.rs deleted file mode 100644 index 1496a45dac2..00000000000 --- a/src/temporary_assignment.rs +++ /dev/null @@ -1,49 +0,0 @@ -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; -use utils::is_adjusted; -use utils::span_lint; - -/// **What it does:** This lint checks for construction of a structure or tuple just to assign a value in it. -/// -/// **Why is this bad?** Readability. If the structure is only created to be updated, why not write the structure you want in the first place? -/// -/// **Known problems:** None. -/// -/// **Example:** `(0, 0).0 = 1` -declare_lint! { - pub TEMPORARY_ASSIGNMENT, - Warn, - "assignments to temporaries" -} - -fn is_temporary(expr: &Expr) -> bool { - match expr.node { - ExprStruct(..) | ExprTup(..) => true, - _ => false, - } -} - -#[derive(Copy, Clone)] -pub struct TemporaryAssignmentPass; - -impl LintPass for TemporaryAssignmentPass { - fn get_lints(&self) -> LintArray { - lint_array!(TEMPORARY_ASSIGNMENT) - } -} - -impl LateLintPass for TemporaryAssignmentPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprAssign(ref target, _) = expr.node { - match target.node { - ExprField(ref base, _) | - ExprTupField(ref base, _) => { - if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - } - } - _ => (), - } - } - } -} diff --git a/src/transmute.rs b/src/transmute.rs deleted file mode 100644 index 2217fd59bd9..00000000000 --- a/src/transmute.rs +++ /dev/null @@ -1,131 +0,0 @@ -use rustc::lint::*; -use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; -use rustc::ty; -use rustc::hir::*; -use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; - -/// **What it does:** This lint checks for transmutes to the original type of the object. -/// -/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type. -/// -/// **Known problems:** None. -/// -/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `t`'s. -declare_lint! { - pub USELESS_TRANSMUTE, - Warn, - "transmutes that have the same to and from types" -} - -/// **What it does:*** This lint checks for transmutes between a type `T` and `*T`. -/// -/// **Why is this bad?** It's easy to mistakenly transmute between a type and a pointer to that type. -/// -/// **Known problems:** None. -/// -/// **Example:** `core::intrinsics::transmute(t)` where the result type is the same as `*t` or `&t`'s. -declare_lint! { - pub CROSSPOINTER_TRANSMUTE, - Warn, - "transmutes that have to or from types that are a pointer to the other" -} - -/// **What it does:*** This lint checks for transmutes from a pointer to a reference. -/// -/// **Why is this bad?** This can always be rewritten with `&` and `*`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let _: &T = std::mem::transmute(p); // where p: *const T -/// // can be written: -/// let _: &T = &*p; -/// ``` -declare_lint! { - pub TRANSMUTE_PTR_TO_REF, - Warn, - "transmutes from a pointer to a reference type" -} - -pub struct Transmute; - -impl LintPass for Transmute { - fn get_lints(&self) -> LintArray { - lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE] - } -} - -impl LateLintPass for Transmute { - fn check_expr(&mut self, cx: &LateContext, e: &Expr) { - if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(None, _) = path_expr.node { - let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); - - if match_def_path(cx, def_id, &paths::TRANSMUTE) { - let from_ty = cx.tcx.expr_ty(&args[0]); - let to_ty = cx.tcx.expr_ty(e); - - if from_ty == to_ty { - span_lint(cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty)); - } else if is_ptr_to(to_ty, from_ty) { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", - from_ty, - to_ty)); - } else if is_ptr_to(from_ty, to_ty) { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty)); - } else { - check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); - } - } - } - } - } -} - -fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { - if let TyRawPtr(from_ptr) = from.sty { - from_ptr.ty == to - } else { - false - } -} - -fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) { - if let TyRawPtr(ref from_pty) = from_ty.sty { - if let TyRef(_, ref to_rty) = to_ty.sty { - let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", - from_ty, - to_ty); - span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| { - if let Some(arg) = snippet_opt(cx, arg.span) { - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; - - - let sugg = if from_pty.ty == to_rty.ty { - format!("{}{}", deref, arg) - } else { - format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) - }; - - db.span_suggestion(e.span, "try", sugg); - } - }); - } - } -} diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index c4b810a7880..00000000000 --- a/src/types.rs +++ /dev/null @@ -1,974 +0,0 @@ -use reexport::*; -use rustc::hir::*; -use rustc::hir::intravisit::{FnKind, Visitor, walk_ty}; -use rustc::lint::*; -use rustc::ty; -use std::cmp::Ordering; -use syntax::ast::{IntTy, UintTy, FloatTy}; -use syntax::codemap::Span; -use utils::{comparisons, in_external_macro, in_macro, is_from_for_desugar, match_def_path, snippet, - span_help_and_lint, span_lint}; -use utils::paths; - -/// Handles all the linting of funky types -#[allow(missing_copy_implementations)] -pub struct TypePass; - -/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. -/// -/// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever. -/// -/// **Known problems:** None -/// -/// **Example:** `struct X { values: Box<Vec<Foo>> }` -declare_lint! { - pub BOX_VEC, Warn, - "usage of `Box<Vec<T>>`, vector elements are already on the heap" -} - -/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). -/// -/// **Why is this bad?** Gankro says: -/// -/// >The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection. It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while "only" amortized for push/pop, should be faster in the general case for almost every possible workload, and isn't even amortized at all if you can predict the capacity you need. -/// > -/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists. This is because they can just mangle some pointers instead of actually copying the data. Even if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better because of how expensive it is to seek to the middle of a `LinkedList`. -/// -/// **Known problems:** False positives – the instances where using a `LinkedList` makes sense are few and far between, but they can still happen. -/// -/// **Example:** `let x = LinkedList::new();` -declare_lint! { - pub LINKEDLIST, Warn, - "usage of LinkedList, usually a vector is faster, or a more specialized data \ - structure like a VecDeque" -} - -impl LintPass for TypePass { - fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, LINKEDLIST) - } -} - -impl LateLintPass for TypePass { - fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) { - if in_macro(cx, ast_ty.span) { - return; - } - if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { - if let def::Def::Struct(..) = did.full_def() { - if Some(did.def_id()) == cx.tcx.lang_items.owned_box() { - if_let_chain! { - [ - let TyPath(_, ref path) = ast_ty.node, - let Some(ref last) = path.segments.last(), - let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, - let Some(ref vec) = ag.types.get(0), - let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), - let def::Def::Struct(..) = did.full_def(), - match_def_path(cx, did.def_id(), &paths::VEC), - ], - { - span_help_and_lint(cx, - BOX_VEC, - ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); - } - } - } else if match_def_path(cx, did.def_id(), &paths::LINKED_LIST) { - span_help_and_lint(cx, - LINKEDLIST, - ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a VecDeque might work"); - } - } - } - } -} - -#[allow(missing_copy_implementations)] -pub struct LetPass; - -/// **What it does:** This lint checks for binding a unit value. -/// -/// **Why is this bad?** A unit value cannot usefully be used anywhere. So binding one is kind of pointless. -/// -/// **Known problems:** None -/// -/// **Example:** `let x = { 1; };` -declare_lint! { - pub LET_UNIT_VALUE, Warn, - "creating a let binding to a value of unit type, which usually can't be used afterwards" -} - -fn check_let_unit(cx: &LateContext, decl: &Decl) { - if let DeclLocal(ref local) = decl.node { - let bindtype = &cx.tcx.pat_ty(&local.pat).sty; - if *bindtype == ty::TyTuple(&[]) { - if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { - return; - } - if is_from_for_desugar(decl) { - return; - } - span_lint(cx, - LET_UNIT_VALUE, - decl.span, - &format!("this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, ".."))); - } - } -} - -impl LintPass for LetPass { - fn get_lints(&self) -> LintArray { - lint_array!(LET_UNIT_VALUE) - } -} - -impl LateLintPass for LetPass { - fn check_decl(&mut self, cx: &LateContext, decl: &Decl) { - check_let_unit(cx, decl) - } -} - -/// **What it does:** This lint checks for comparisons to unit. -/// -/// **Why is this bad?** Unit is always equal to itself, and thus is just a clumsily written constant. Mostly this happens when someone accidentally adds semicolons at the end of the operands. -/// -/// **Known problems:** None -/// -/// **Example:** `if { foo(); } == { bar(); } { baz(); }` is equal to `{ foo(); bar(); baz(); }` -declare_lint! { - pub UNIT_CMP, Warn, - "comparing unit values (which is always `true` or `false`, respectively)" -} - -#[allow(missing_copy_implementations)] -pub struct UnitCmp; - -impl LintPass for UnitCmp { - fn get_lints(&self) -> LintArray { - lint_array!(UNIT_CMP) - } -} - -impl LateLintPass for UnitCmp { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_macro(cx, expr.span) { - return; - } - if let ExprBinary(ref cmp, ref left, _) = expr.node { - let op = cmp.node; - let sty = &cx.tcx.expr_ty(left).sty; - if *sty == ty::TyTuple(&[]) && op.is_comparison() { - let result = match op { - BiEq | BiLe | BiGe => "true", - _ => "false", - }; - span_lint(cx, - UNIT_CMP, - expr.span, - &format!("{}-comparison of unit values detected. This will always be {}", - op.as_str(), - result)); - } - } - } -} - -pub struct CastPass; - -/// **What it does:** This lint checks for casts from any numerical to a float type where the receiving type cannot store all values from the original type without rounding errors. This possible rounding is to be expected, so this lint is `Allow` by default. -/// -/// Basically, this warns on casting any integer with 32 or more bits to `f32` or any 64-bit integer to `f64`. -/// -/// **Why is this bad?** It's not bad at all. But in some applications it can be helpful to know where precision loss can take place. This lint can help find those places in the code. -/// -/// **Known problems:** None -/// -/// **Example:** `let x = u64::MAX; x as f64` -declare_lint! { - pub CAST_PRECISION_LOSS, Allow, - "casts that cause loss of precision, e.g `x as f32` where `x: u64`" -} - -/// **What it does:** This lint checks for casts from a signed to an unsigned numerical type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default. -/// -/// **Why is this bad?** Possibly surprising results. You can activate this lint as a one-time check to see where numerical wrapping can arise. -/// -/// **Known problems:** None -/// -/// **Example:** `let y : i8 = -1; y as u64` will return 18446744073709551615 -declare_lint! { - pub CAST_SIGN_LOSS, Allow, - "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`" -} - -/// **What it does:** This lint checks for on casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by default. -/// -/// **Why is this bad?** In some problem domains, it is good practice to avoid truncation. This lint can be activated to help assess where additional checks could be beneficial. -/// -/// **Known problems:** None -/// -/// **Example:** `fn as_u8(x: u64) -> u8 { x as u8 }` -declare_lint! { - pub CAST_POSSIBLE_TRUNCATION, Allow, - "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`" -} - -/// **What it does:** This lint checks for casts from an unsigned type to a signed type of the same size. Performing such a cast is a 'no-op' for the compiler, i.e. nothing is changed at the bit level, and the binary representation of the value is reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default. -/// -/// **Why is this bad?** While such a cast is not bad in itself, the results can be surprising when this is not the intended behavior, as demonstrated by the example below. -/// -/// **Known problems:** None -/// -/// **Example:** `u32::MAX as i32` will yield a value of `-1`. -declare_lint! { - pub CAST_POSSIBLE_WRAP, Allow, - "casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`" -} - -/// Returns the size in bits of an integral type. -/// Will return 0 if the type is not an int or uint variant -fn int_ty_to_nbits(typ: &ty::TyS) -> usize { - let n = match typ.sty { - ty::TyInt(i) => 4 << (i as usize), - ty::TyUint(u) => 4 << (u as usize), - _ => 0, - }; - // n == 4 is the usize/isize case - if n == 4 { - ::std::mem::size_of::<usize>() * 8 - } else { - n - } -} - -fn is_isize_or_usize(typ: &ty::TyS) -> bool { - match typ.sty { - ty::TyInt(IntTy::Is) | - ty::TyUint(UintTy::Us) => true, - _ => false, - } -} - -fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { - let mantissa_nbits = if cast_to_f64 { - 52 - } else { - 23 - }; - let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; - let arch_dependent_str = "on targets with 64-bit wide pointers "; - let from_nbits_str = if arch_dependent { - "64".to_owned() - } else if is_isize_or_usize(cast_from) { - "32 or 64".to_owned() - } else { - int_ty_to_nbits(cast_from).to_string() - }; - span_lint(cx, - CAST_PRECISION_LOSS, - expr.span, - &format!("casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ - is only {4} bits wide)", - cast_from, - if cast_to_f64 { - "f64" - } else { - "f32" - }, - if arch_dependent { - arch_dependent_str - } else { - "" - }, - from_nbits_str, - mantissa_nbits)); -} - -enum ArchSuffix { - _32, - _64, - None, -} - -fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { - let arch_64_suffix = " on targets with 64-bit wide pointers"; - let arch_32_suffix = " on targets with 32-bit wide pointers"; - let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); - let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); - let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), - is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => { - (to_nbits < from_nbits, - ArchSuffix::None, - to_nbits == from_nbits && cast_unsigned_to_signed, - ArchSuffix::None) - } - (true, false) => { - (to_nbits <= 32, - if to_nbits == 32 { - ArchSuffix::_64 - } else { - ArchSuffix::None - }, - to_nbits <= 32 && cast_unsigned_to_signed, - ArchSuffix::_32) - } - (false, true) => { - (from_nbits == 64, - ArchSuffix::_32, - cast_unsigned_to_signed, - if from_nbits == 64 { - ArchSuffix::_64 - } else { - ArchSuffix::_32 - }) - } - }; - if span_truncation { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - &format!("casting {} to {} may truncate the value{}", - cast_from, - cast_to, - match suffix_truncation { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "", - })); - } - if span_wrap { - span_lint(cx, - CAST_POSSIBLE_WRAP, - expr.span, - &format!("casting {} to {} may wrap around the value{}", - cast_from, - cast_to, - match suffix_wrap { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "", - })); - } -} - -impl LintPass for CastPass { - fn get_lints(&self) -> LintArray { - lint_array!(CAST_PRECISION_LOSS, - CAST_SIGN_LOSS, - CAST_POSSIBLE_TRUNCATION, - CAST_POSSIBLE_WRAP) - } -} - -impl LateLintPass for CastPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprCast(ref ex, _) = expr.node { - let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr)); - if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { - match (cast_from.is_integral(), cast_to.is_integral()) { - (true, false) => { - let from_nbits = int_ty_to_nbits(cast_from); - let to_nbits = if let ty::TyFloat(FloatTy::F32) = cast_to.sty { - 32 - } else { - 64 - }; - if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { - span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); - } - } - (false, true) => { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - &format!("casting {} to {} may truncate the value", cast_from, cast_to)); - if !cast_to.is_signed() { - span_lint(cx, - CAST_SIGN_LOSS, - expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); - } - } - (true, true) => { - if cast_from.is_signed() && !cast_to.is_signed() { - span_lint(cx, - CAST_SIGN_LOSS, - expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); - } - check_truncation_and_wrapping(cx, expr, cast_from, cast_to); - } - (false, false) => { - if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, - &cast_to.sty) { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - "casting f64 to f32 may truncate the value"); - } - } - } - } - } - } -} - -/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. -/// -/// **Why is this bad?** Too complex types make the code less readable. Consider using a `type` definition to simplify them. -/// -/// **Known problems:** None -/// -/// **Example:** `struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }` -declare_lint! { - pub TYPE_COMPLEXITY, Warn, - "usage of very complex types; recommends factoring out parts into `type` definitions" -} - -#[allow(missing_copy_implementations)] -pub struct TypeComplexityPass { - threshold: u64, -} - -impl TypeComplexityPass { - pub fn new(threshold: u64) -> Self { - TypeComplexityPass { threshold: threshold } - } -} - -impl LintPass for TypeComplexityPass { - fn get_lints(&self) -> LintArray { - lint_array!(TYPE_COMPLEXITY) - } -} - -impl LateLintPass for TypeComplexityPass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { - self.check_fndecl(cx, decl); - } - - fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { - // enum variants are also struct fields now - self.check_type(cx, &field.ty); - } - - fn check_item(&mut self, cx: &LateContext, item: &Item) { - match item.node { - ItemStatic(ref ty, _, _) | - ItemConst(ref ty, _) => self.check_type(cx, ty), - // functions, enums, structs, impls and traits are covered - _ => (), - } - } - - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { - match item.node { - ConstTraitItem(ref ty, _) | - TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty), - MethodTraitItem(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl), - // methods with default impl are covered by check_fn - _ => (), - } - } - - fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) { - match item.node { - ImplItemKind::Const(ref ty, _) | - ImplItemKind::Type(ref ty) => self.check_type(cx, ty), - // methods are covered by check_fn - _ => (), - } - } - - fn check_local(&mut self, cx: &LateContext, local: &Local) { - if let Some(ref ty) = local.ty { - self.check_type(cx, ty); - } - } -} - -impl TypeComplexityPass { - fn check_fndecl(&self, cx: &LateContext, decl: &FnDecl) { - for arg in &decl.inputs { - self.check_type(cx, &arg.ty); - } - if let Return(ref ty) = decl.output { - self.check_type(cx, ty); - } - } - - fn check_type(&self, cx: &LateContext, ty: &Ty) { - if in_macro(cx, ty.span) { - return; - } - let score = { - let mut visitor = TypeComplexityVisitor { - score: 0, - nest: 1, - }; - visitor.visit_ty(ty); - visitor.score - }; - - if score > self.threshold { - span_lint(cx, - TYPE_COMPLEXITY, - ty.span, - "very complex type used. Consider factoring parts into `type` definitions"); - } - } -} - -/// Walks a type and assigns a complexity score to it. -struct TypeComplexityVisitor { - /// total complexity score of the type - score: u64, - /// current nesting level - nest: u64, -} - -impl<'v> Visitor<'v> for TypeComplexityVisitor { - fn visit_ty(&mut self, ty: &'v Ty) { - let (add_score, sub_nest) = match ty.node { - // _, &x and *x have only small overhead; don't mess with nesting level - TyInfer | TyPtr(..) | TyRptr(..) => (1, 0), - - // the "normal" components of a type: named types, arrays/tuples - TyPath(..) | - TyVec(..) | - TyTup(..) | - TyFixedLengthVec(..) => (10 * self.nest, 1), - - // "Sum" of trait bounds - TyObjectSum(..) => (20 * self.nest, 0), - - // function types and "for<...>" bring a lot of overhead - TyBareFn(..) | - TyPolyTraitRef(..) => (50 * self.nest, 1), - - _ => (0, 0), - }; - self.score += add_score; - self.nest += sub_nest; - walk_ty(self, ty); - self.nest -= sub_nest; - } -} - -/// **What it does:** This lint points out expressions where a character literal is casted to `u8` and suggests using a byte literal instead. -/// -/// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`. -/// -/// **Known problems:** None -/// -/// **Example:** `'x' as u8` -declare_lint! { - pub CHAR_LIT_AS_U8, Warn, - "Casting a character literal to u8" -} - -pub struct CharLitAsU8; - -impl LintPass for CharLitAsU8 { - fn get_lints(&self) -> LintArray { - lint_array!(CHAR_LIT_AS_U8) - } -} - -impl LateLintPass for CharLitAsU8 { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - use syntax::ast::{LitKind, UintTy}; - - if let ExprCast(ref e, _) = expr.node { - if let ExprLit(ref l) = e.node { - if let LitKind::Char(_) = l.node { - if ty::TyUint(UintTy::U8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { - let msg = "casting character literal to u8. `char`s \ - are 4 bytes wide in rust, so casting to u8 \ - truncates them"; - let help = format!("Consider using a byte literal \ - instead:\nb{}", - snippet(cx, e.span, "'x'")); - span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help); - } - } - } - } - } -} - -/// **What it does:** This lint checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked. -/// -/// **Why is this bad?** An expression like `min <= x` may misleadingly imply that is is possible for `x` to be less than the minimum. Expressions like `max < x` are probably mistakes. -/// -/// **Known problems:** None -/// -/// **Example:** `vec.len() <= 0`, `100 > std::i32::MAX` -declare_lint! { - pub ABSURD_EXTREME_COMPARISONS, Warn, - "a comparison involving a maximum or minimum value involves a case that is always \ - true or always false" -} - -pub struct AbsurdExtremeComparisons; - -impl LintPass for AbsurdExtremeComparisons { - fn get_lints(&self) -> LintArray { - lint_array!(ABSURD_EXTREME_COMPARISONS) - } -} - -enum ExtremeType { - Minimum, - Maximum, -} - -struct ExtremeExpr<'a> { - which: ExtremeType, - expr: &'a Expr, -} - -enum AbsurdComparisonResult { - AlwaysFalse, - AlwaysTrue, - InequalityImpossible, -} - - - -fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) - -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { - use types::ExtremeType::*; - use types::AbsurdComparisonResult::*; - use utils::comparisons::*; - type Extr<'a> = ExtremeExpr<'a>; - - let normalized = normalize_comparison(op, lhs, rhs); - let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { - val - } else { - return None; - }; - - let lx = detect_extreme_expr(cx, normalized_lhs); - let rx = detect_extreme_expr(cx, normalized_rhs); - - Some(match rel { - Rel::Lt => { - match (lx, rx) { - (Some(l @ Extr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x - (_, Some(r @ Extr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min - _ => return None, - } - } - Rel::Le => { - match (lx, rx) { - (Some(l @ Extr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x - (Some(l @ Extr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x - (_, Some(r @ Extr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min - (_, Some(r @ Extr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max - _ => return None, - } - } - Rel::Ne | Rel::Eq => return None, - }) -} - -fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeExpr<'a>> { - use rustc::middle::const_val::ConstVal::*; - use rustc_const_math::*; - use rustc_const_eval::EvalHint::ExprTypeChecked; - use rustc_const_eval::*; - use types::ExtremeType::*; - - let ty = &cx.tcx.expr_ty(expr).sty; - - match *ty { - ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (), - _ => return None, - }; - - let cv = match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { - Ok(val) => val, - Err(_) => return None, - }; - - let which = match (ty, cv) { - (&ty::TyBool, Bool(false)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | - (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | - (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | - (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | - (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | - (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | - (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | - (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | - (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum, - - (&ty::TyBool, Bool(true)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | - (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | - (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | - (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | - (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | - (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | - (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | - (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | - (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) => Maximum, - - _ => return None, - }; - Some(ExtremeExpr { - which: which, - expr: expr, - }) -} - -impl LateLintPass for AbsurdExtremeComparisons { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - use types::ExtremeType::*; - use types::AbsurdComparisonResult::*; - - if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { - if !in_macro(cx, expr.span) { - let msg = "this comparison involving the minimum or maximum element for this \ - type contains a case that is always true or always false"; - - let conclusion = match result { - AlwaysFalse => "this comparison is always false".to_owned(), - AlwaysTrue => "this comparison is always true".to_owned(), - InequalityImpossible => { - format!("the case where the two sides are not equal never occurs, consider using {} == {} \ - instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs")) - } - }; - - let help = format!("because {} is the {} value for this type, {}", - snippet(cx, culprit.expr.span, "x"), - match culprit.which { - Minimum => "minimum", - Maximum => "maximum", - }, - conclusion); - - span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help); - } - } - } - } -} - -/// **What it does:** This lint checks for comparisons where the relation is always either true or false, but where one side has been upcast so that the comparison is necessary. Only integer types are checked. -/// -/// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` will mistakenly imply that it is possible for `x` to be outside the range of `u8`. -/// -/// **Known problems:** https://github.com/Manishearth/rust-clippy/issues/886 -/// -/// **Example:** `let x : u8 = ...; (x as u32) > 300` -declare_lint! { - pub INVALID_UPCAST_COMPARISONS, Allow, - "a comparison involving an upcast which is always true or false" -} - -pub struct InvalidUpcastComparisons; - -impl LintPass for InvalidUpcastComparisons { - fn get_lints(&self) -> LintArray { - lint_array!(INVALID_UPCAST_COMPARISONS) - } -} - -#[derive(Copy, Clone, Debug, Eq)] -enum FullInt { - S(i64), - U(u64), -} - -impl FullInt { - #[allow(cast_sign_loss)] - fn cmp_s_u(s: i64, u: u64) -> Ordering { - if s < 0 { - Ordering::Less - } else if u > (i64::max_value() as u64) { - Ordering::Greater - } else { - (s as u64).cmp(&u) - } - } -} - -impl PartialEq for FullInt { - fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal - } -} - -impl PartialOrd for FullInt { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(match (self, other) { - (&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o), - (&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o), - (&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o), - (&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(), - }) - } -} -impl Ord for FullInt { - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).expect("partial_cmp for FullInt can never return None") - } -} - - -fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { - use rustc::ty::TypeVariants::{TyInt, TyUint}; - use syntax::ast::{IntTy, UintTy}; - use std::*; - - if let ExprCast(ref cast_exp, _) = expr.node { - match cx.tcx.expr_ty(cast_exp).sty { - TyInt(int_ty) => { - Some(match int_ty { - IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), - IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), - IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), - IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), - IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), - }) - } - TyUint(uint_ty) => { - Some(match uint_ty { - UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), - UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), - UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), - UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), - UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), - }) - } - _ => None, - } - } else { - None - } -} - -fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> { - use rustc::middle::const_val::ConstVal::*; - use rustc_const_eval::EvalHint::ExprTypeChecked; - use rustc_const_eval::eval_const_expr_partial; - use rustc_const_math::ConstInt; - - match eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None) { - Ok(val) => { - if let Integral(const_int) = val { - Some(match const_int.erase_type() { - ConstInt::InferSigned(x) => FullInt::S(x as i64), - ConstInt::Infer(x) => FullInt::U(x as u64), - _ => unreachable!(), - }) - } else { - None - } - } - Err(_) => None, - } -} - -fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { - if let ExprCast(ref cast_val, _) = expr.node { - span_lint(cx, - INVALID_UPCAST_COMPARISONS, - *span, - &format!( - "because of the numeric bounds on `{}` prior to casting, this expression is always {}", - snippet(cx, cast_val.span, "the expression"), - if always { "true" } else { "false" }, - )); - } -} - -fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons::Rel, - lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) { - use utils::comparisons::*; - - if let Some((lb, ub)) = lhs_bounds { - if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { - if rel == Rel::Eq || rel == Rel::Ne { - if norm_rhs_val < lb || norm_rhs_val > ub { - err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); - } - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - } - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - } - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, true) - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - } - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - } - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, false) - } - } - } -} - -impl LateLintPass for InvalidUpcastComparisons { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - - let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); - let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { - val - } else { - return; - }; - - let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); - let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); - - upcast_comparison_bounds_err(cx, &expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); - upcast_comparison_bounds_err(cx, &expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); - } - } -} diff --git a/src/unicode.rs b/src/unicode.rs deleted file mode 100644 index 8271fd3ed66..00000000000 --- a/src/unicode.rs +++ /dev/null @@ -1,109 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use syntax::ast::LitKind; -use syntax::codemap::Span; -use unicode_normalization::UnicodeNormalization; -use utils::{snippet, span_help_and_lint}; - -/// **What it does:** This lint checks for the unicode zero-width space in the code. -/// -/// **Why is this bad?** Having an invisible character in the code makes for all sorts of April fools, but otherwise is very much frowned upon. -/// -/// **Known problems:** None -/// -/// **Example:** You don't see it, but there may be a zero-width space somewhere in this text. -declare_lint! { - pub ZERO_WIDTH_SPACE, Deny, - "using a zero-width space in a string literal, which is confusing" -} - -/// **What it does:** This lint checks for non-ascii characters in string literals. -/// -/// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful. -/// -/// **Known problems:** None -/// -/// **Example:** `let x = "Hä?"` -declare_lint! { - pub NON_ASCII_LITERAL, Allow, - "using any literal non-ASCII chars in a string literal; suggests \ - using the \\u escape instead" -} - -/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). -/// -/// **Why is this bad?** If such a string is compared to another, the results may be surprising. -/// -/// **Known problems** None -/// -/// **Example:** You may not see it, but "à" and "à" aren't the same string. The former when escaped is actually "a\u{300}" while the latter is "\u{e0}". -declare_lint! { - pub UNICODE_NOT_NFC, Allow, - "using a unicode literal not in NFC normal form (see \ - [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" -} - - -#[derive(Copy, Clone)] -pub struct Unicode; - -impl LintPass for Unicode { - fn get_lints(&self) -> LintArray { - lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) - } -} - -impl LateLintPass for Unicode { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let ExprLit(ref lit) = expr.node { - if let LitKind::Str(_, _) = lit.node { - check_str(cx, lit.span) - } - } - } -} - -fn escape<T: Iterator<Item = char>>(s: T) -> String { - let mut result = String::new(); - for c in s { - if c as u32 > 0x7F { - for d in c.escape_unicode() { - result.push(d) - } - } else { - result.push(c); - } - } - result -} - -fn check_str(cx: &LateContext, span: Span) { - let string = snippet(cx, span, ""); - if string.contains('\u{200B}') { - span_help_and_lint(cx, - ZERO_WIDTH_SPACE, - span, - "zero-width space detected", - &format!("Consider replacing the string with:\n\"{}\"", - string.replace("\u{200B}", "\\u{200B}"))); - } - if string.chars().any(|c| c as u32 > 0x7F) { - span_help_and_lint(cx, - NON_ASCII_LITERAL, - span, - "literal non-ASCII character detected", - &format!("Consider replacing the string with:\n\"{}\"", - if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { - escape(string.chars()) - } else { - escape(string.nfc()) - })); - } - if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { - span_help_and_lint(cx, - UNICODE_NOT_NFC, - span, - "non-nfc unicode sequence detected", - &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::<String>())); - } -} diff --git a/src/unsafe_removed_from_name.rs b/src/unsafe_removed_from_name.rs deleted file mode 100644 index 3de6719c546..00000000000 --- a/src/unsafe_removed_from_name.rs +++ /dev/null @@ -1,81 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use syntax::ast::Name; -use syntax::codemap::Span; -use syntax::parse::token::InternedString; -use utils::span_lint; - -/// **What it does:** This lint checks for imports that remove "unsafe" from an item's name -/// -/// **Why is this bad?** Renaming makes it less clear which traits and structures are unsafe. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// use std::cell::{UnsafeCell as TotallySafeCell}; -/// -/// extern crate crossbeam; -/// use crossbeam::{spawn_unsafe as spawn}; -/// ``` -declare_lint! { - pub UNSAFE_REMOVED_FROM_NAME, - Warn, - "unsafe removed from name" -} - -pub struct UnsafeNameRemoval; - -impl LintPass for UnsafeNameRemoval { - fn get_lints(&self) -> LintArray { - lint_array!(UNSAFE_REMOVED_FROM_NAME) - } -} - -impl LateLintPass for UnsafeNameRemoval { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemUse(ref item_use) = item.node { - match item_use.node { - ViewPath_::ViewPathSimple(ref name, ref path) => { - unsafe_to_safe_check( - path.segments - .last() - .expect("use paths cannot be empty") - .name, - *name, - cx, &item.span - ); - }, - ViewPath_::ViewPathList(_, ref path_list_items) => { - for path_list_item in path_list_items.iter() { - let plid = path_list_item.node; - if let (Some(name), Some(rename)) = (plid.name(), plid.rename()) { - unsafe_to_safe_check(name, rename, cx, &item.span); - }; - } - }, - ViewPath_::ViewPathGlob(_) => {} - } - } - } -} - -fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: &Span) { - let old_str = old_name.as_str(); - let new_str = new_name.as_str(); - if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { - span_lint( - cx, - UNSAFE_REMOVED_FROM_NAME, - *span, - &format!( - "removed \"unsafe\" from the name of `{}` in use as `{}`", - old_str, - new_str - )); - } -} - -fn contains_unsafe(name: &InternedString) -> bool { - name.contains("Unsafe") || name.contains("unsafe") -} diff --git a/src/unused_label.rs b/src/unused_label.rs deleted file mode 100644 index d408f16a371..00000000000 --- a/src/unused_label.rs +++ /dev/null @@ -1,78 +0,0 @@ -use rustc::lint::*; -use rustc::hir; -use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; -use std::collections::HashMap; -use syntax::ast; -use syntax::codemap::Span; -use syntax::parse::token::InternedString; -use utils::{in_macro, span_lint}; - -/// **What it does:** This lint checks for unused labels. -/// -/// **Why is this bad?** Maybe the label should be used in which case there is an error in the -/// code or it should be removed. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// ```rust,ignore -/// fn unused_label() { -/// 'label: for i in 1..2 { -/// if i > 4 { continue } -/// } -/// ``` -declare_lint! { - pub UNUSED_LABEL, - Warn, - "unused label" -} - -pub struct UnusedLabel; - -#[derive(Default)] -struct UnusedLabelVisitor { - labels: HashMap<InternedString, Span>, -} - -impl UnusedLabelVisitor { - pub fn new() -> UnusedLabelVisitor { - ::std::default::Default::default() - } -} - -impl LintPass for UnusedLabel { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_LABEL) - } -} - -impl LateLintPass for UnusedLabel { - fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, _: ast::NodeId) { - if in_macro(cx, span) { - return; - } - - let mut v = UnusedLabelVisitor::new(); - walk_fn(&mut v, kind, decl, body, span); - - for (label, span) in v.labels { - span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label)); - } - } -} - -impl<'v> Visitor<'v> for UnusedLabelVisitor { - fn visit_expr(&mut self, expr: &hir::Expr) { - match expr.node { - hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => { - self.labels.remove(&label.node.as_str()); - } - hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { - self.labels.insert(label.as_str(), expr.span); - } - _ => (), - } - - walk_expr(self, expr); - } -} diff --git a/src/utils/comparisons.rs b/src/utils/comparisons.rs deleted file mode 100644 index b890a363fb7..00000000000 --- a/src/utils/comparisons.rs +++ /dev/null @@ -1,23 +0,0 @@ -use rustc::hir::{BinOp_, Expr}; - -#[derive(PartialEq, Eq, Debug, Copy, Clone)] -pub enum Rel { - Lt, - Le, - Eq, - Ne, -} - -/// Put the expression in the form `lhs < rhs` or `lhs <= rhs`. -pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) - -> Option<(Rel, &'a Expr, &'a Expr)> { - match op { - BinOp_::BiLt => Some((Rel::Lt, lhs, rhs)), - BinOp_::BiLe => Some((Rel::Le, lhs, rhs)), - BinOp_::BiGt => Some((Rel::Lt, rhs, lhs)), - BinOp_::BiGe => Some((Rel::Le, rhs, lhs)), - BinOp_::BiEq => Some((Rel::Eq, rhs, lhs)), - BinOp_::BiNe => Some((Rel::Ne, rhs, lhs)), - _ => None, - } -} diff --git a/src/utils/conf.rs b/src/utils/conf.rs deleted file mode 100644 index e773cc0e025..00000000000 --- a/src/utils/conf.rs +++ /dev/null @@ -1,205 +0,0 @@ -use std::{fmt, fs, io}; -use std::io::Read; -use syntax::{ast, codemap, ptr}; -use syntax::parse::token; -use toml; - -/// Get the configuration file from arguments. -pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { - for arg in args { - match arg.node { - ast::MetaItemKind::Word(ref name) | - ast::MetaItemKind::List(ref name, _) => { - if name == &"conf_file" { - return Err(("`conf_file` must be a named value", arg.span)); - } - } - ast::MetaItemKind::NameValue(ref name, ref value) => { - if name == &"conf_file" { - return if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.clone())) - } else { - Err(("`conf_file` value must be a string", value.span)) - }; - } - } - } - } - - Ok(None) -} - -/// Error from reading a configuration file. -#[derive(Debug)] -pub enum ConfError { - IoError(io::Error), - TomlError(Vec<toml::ParserError>), - TypeError(&'static str, &'static str, &'static str), - UnknownKey(String), -} - -impl fmt::Display for ConfError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ConfError::IoError(ref err) => err.fmt(f), - ConfError::TomlError(ref errs) => { - let mut first = true; - for err in errs { - if !first { - try!(", ".fmt(f)); - first = false; - } - - try!(err.fmt(f)); - } - - Ok(()) - } - ConfError::TypeError(ref key, ref expected, ref got) => { - write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) - } - ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), - } - } -} - -impl From<io::Error> for ConfError { - fn from(e: io::Error) -> Self { - ConfError::IoError(e) - } -} - -macro_rules! define_Conf { - ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { - /// Type used to store lint configuration. - pub struct Conf { - $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ - } - - impl Default for Conf { - fn default() -> Conf { - Conf { - $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ - } - } - } - - impl Conf { - /// Set the property `name` (which must be the `toml` name) to the given value - #[allow(cast_sign_loss)] - fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { - match name.as_str() { - $( - define_Conf!(PAT $toml_name) => { - if let Some(value) = define_Conf!(CONV $($ty)+, value) { - self.$rust_name = value; - } - else { - return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), - stringify!($($ty)+), - value.type_str())); - } - }, - )+ - "third-party" => { - // for external tools such as clippy-service - return Ok(()); - } - _ => { - return Err(ConfError::UnknownKey(name)); - } - } - - Ok(()) - } - } - }; - - // hack to convert tts - (PAT $pat: pat) => { $pat }; - (EXPR $e: expr) => { $e }; - (TY $ty: ty) => { $ty }; - - // how to read the value? - (CONV i64, $value: expr) => { $value.as_integer() }; - (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; - (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; - (CONV Vec<String>, $value: expr) => {{ - let slice = $value.as_slice(); - - if let Some(slice) = slice { - if slice.iter().any(|v| v.as_str().is_none()) { - None - } - else { - Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) - } - } - else { - None - } - }}; - - // provide a nicer syntax to declare the default value of `Vec<String>` variables - (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; - (DEFAULT $ty: ty, $e: expr) => { $e }; -} - -define_Conf! { - /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about - ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>), - /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have - ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), - /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks - ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub"] => Vec<String>), - /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have - ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), - /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have - ("type-complexity-threshold", type_complexity_threshold, 250 => u64), - /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have - ("single-char-binding-names-threshold", max_single_char_names, 5 => u64), -} - -/// Read the `toml` configuration file. The function will ignore “File not found” errors iif -/// `!must_exist`, in which case, it will return the default configuration. -/// In case of error, the function tries to continue as much as possible. -pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { - let mut conf = Conf::default(); - let mut errors = Vec::new(); - - let file = match fs::File::open(path) { - Ok(mut file) => { - let mut buf = String::new(); - - if let Err(err) = file.read_to_string(&mut buf) { - errors.push(err.into()); - return (conf, errors); - } - - buf - } - Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { - return (conf, errors); - } - Err(err) => { - errors.push(err.into()); - return (conf, errors); - } - }; - - let mut parser = toml::Parser::new(&file); - let toml = if let Some(toml) = parser.parse() { - toml - } else { - errors.push(ConfError::TomlError(parser.errors)); - return (conf, errors); - }; - - for (key, value) in toml { - if let Err(err) = conf.set(key, value) { - errors.push(err); - } - } - - (conf, errors) -} diff --git a/src/utils/hir.rs b/src/utils/hir.rs deleted file mode 100644 index 0f0a7312ee4..00000000000 --- a/src/utils/hir.rs +++ /dev/null @@ -1,513 +0,0 @@ -use consts::constant; -use rustc::lint::*; -use rustc::hir::*; -use std::hash::{Hash, Hasher, SipHasher}; -use syntax::ast::Name; -use syntax::ptr::P; -use utils::differing_macro_contexts; - -/// Type used to check whether two ast are the same. This is different from the operator -/// `==` on ast types as this operator would compare true equality with ID and span. -/// -/// Note that some expressions kinds are not considered but could be added. -pub struct SpanlessEq<'a, 'tcx: 'a> { - /// Context used to evaluate constant expressions. - cx: &'a LateContext<'a, 'tcx>, - /// If is true, never consider as equal expressions containing function calls. - ignore_fn: bool, -} - -impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { - pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessEq { - cx: cx, - ignore_fn: false, - } - } - - pub fn ignore_fn(self) -> Self { - SpanlessEq { - cx: self.cx, - ignore_fn: true, - } - } - - /// Check whether two statements are the same. - pub fn eq_stmt(&self, left: &Stmt, right: &Stmt) -> bool { - match (&left.node, &right.node) { - (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { - if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { - // TODO: tys - l.ty.is_none() && r.ty.is_none() && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) - } else { - false - } - } - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), - _ => false, - } - } - - /// Check whether two blocks are the same. - pub fn eq_block(&self, left: &Block, right: &Block) -> bool { - over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && - both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) - } - - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { - if self.ignore_fn && differing_macro_contexts(left.span, right.span) { - return false; - } - - if let (Some(l), Some(r)) = (constant(self.cx, left), constant(self.cx, right)) { - if l == r { - return true; - } - } - - match (&left.node, &right.node) { - (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), - (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), - (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), - (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { - lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - } - (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { - l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - }) - } - (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), - (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), - (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { - !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) - } - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), - (&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => { - l_f_ident.node == r_f_ident.node && self.eq_expr(l_f_exp, r_f_exp) - } - (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), - (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { - self.eq_expr(lc, rc) && self.eq_block(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r)) - } - (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { - self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) - } - (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { - ls == rs && self.eq_expr(le, re) && - over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) - } - (&ExprMethodCall(ref l_name, ref l_tys, ref l_args), - &ExprMethodCall(ref r_name, ref r_tys, ref r_args)) => { - // TODO: tys - !self.ignore_fn && l_name.node == r_name.node && l_tys.is_empty() && r_tys.is_empty() && - self.eq_exprs(l_args, r_args) - } - (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), - (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), - (&ExprPath(ref l_qself, ref l_subpath), &ExprPath(ref r_qself, ref r_subpath)) => { - both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) - } - (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { - self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && - over(lf, rf, |l, r| self.eq_field(l, r)) - } - (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), - (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), - (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), - (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), - (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) - } - _ => false, - } - } - - fn eq_exprs(&self, left: &[P<Expr>], right: &[P<Expr>]) -> bool { - over(left, right, |l, r| self.eq_expr(l, r)) - } - - fn eq_field(&self, left: &Field, right: &Field) -> bool { - left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr) - } - - /// Check whether two patterns are the same. - pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { - match (&left.node, &right.node) { - (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), - (&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => { - self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r))) - } - (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { - lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) - } - (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), - (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { - self.eq_qself(ls, rs) && self.eq_path(lp, rp) - } - (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => over(l, r, |l, r| self.eq_pat(l, r)), - (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { - self.eq_expr(ls, rs) && self.eq_expr(le, re) - } - (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), - (&PatKind::Vec(ref ls, ref li, ref le), &PatKind::Vec(ref rs, ref ri, ref re)) => { - over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && - both(li, ri, |l, r| self.eq_pat(l, r)) - } - (&PatKind::Wild, &PatKind::Wild) => true, - _ => false, - } - } - - fn eq_path(&self, left: &Path, right: &Path) -> bool { - // The == of idents doesn't work with different contexts, - // we have to be explicit about hygiene - left.global == right.global && - over(&left.segments, - &right.segments, - |l, r| l.name.as_str() == r.name.as_str() && l.parameters == r.parameters) - } - - fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool { - left.ty.node == right.ty.node && left.position == right.position - } - - fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { - match (&left.node, &right.node) { - (&TyVec(ref l_vec), &TyVec(ref r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyFixedLengthVec(ref lt, ref ll), &TyFixedLengthVec(ref rt, ref rl)) => { - self.eq_ty(lt, rt) && self.eq_expr(ll, rl) - } - (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), - (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { - l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) - } - (&TyPath(ref lq, ref l_path), &TyPath(ref rq, ref r_path)) => { - both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path) - } - (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), - (&TyInfer, &TyInfer) => true, - _ => false, - } - } -} - -fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> { - match binop { - BiAdd | - BiMul | - BiBitXor | - BiBitAnd | - BiEq | - BiNe | - BiBitOr => Some((binop, rhs, lhs)), - BiLt => Some((BiGt, rhs, lhs)), - BiLe => Some((BiGe, rhs, lhs)), - BiGe => Some((BiLe, rhs, lhs)), - BiGt => Some((BiLt, rhs, lhs)), - BiShl | BiShr | BiRem | BiSub | BiDiv | BiAnd | BiOr => None, - } -} - -/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool -{ - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) -} - -/// Check if two slices are equal as per `eq_fn`. -fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool -{ - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) -} - - -/// Type used to hash an ast element. This is different from the `Hash` trait on ast types as this -/// trait would consider IDs and spans. -/// -/// All expressions kind are hashed, but some might have a weaker hash. -pub struct SpanlessHash<'a, 'tcx: 'a> { - /// Context used to evaluate constant expressions. - cx: &'a LateContext<'a, 'tcx>, - s: SipHasher, -} - -impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { - pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessHash { - cx: cx, - s: SipHasher::new(), - } - } - - pub fn finish(&self) -> u64 { - self.s.finish() - } - - pub fn hash_block(&mut self, b: &Block) { - for s in &b.stmts { - self.hash_stmt(s); - } - - if let Some(ref e) = b.expr { - self.hash_expr(e); - } - - b.rules.hash(&mut self.s); - } - - pub fn hash_expr(&mut self, e: &Expr) { - if let Some(e) = constant(self.cx, e) { - return e.hash(&mut self.s); - } - - match e.node { - ExprAddrOf(m, ref e) => { - let c: fn(_, _) -> _ = ExprAddrOf; - c.hash(&mut self.s); - m.hash(&mut self.s); - self.hash_expr(e); - } - ExprAgain(i) => { - let c: fn(_) -> _ = ExprAgain; - c.hash(&mut self.s); - if let Some(i) = i { - self.hash_name(&i.node); - } - } - ExprAssign(ref l, ref r) => { - let c: fn(_, _) -> _ = ExprAssign; - c.hash(&mut self.s); - self.hash_expr(l); - self.hash_expr(r); - } - ExprAssignOp(ref o, ref l, ref r) => { - let c: fn(_, _, _) -> _ = ExprAssignOp; - c.hash(&mut self.s); - o.hash(&mut self.s); - self.hash_expr(l); - self.hash_expr(r); - } - ExprBlock(ref b) => { - let c: fn(_) -> _ = ExprBlock; - c.hash(&mut self.s); - self.hash_block(b); - } - ExprBinary(op, ref l, ref r) => { - let c: fn(_, _, _) -> _ = ExprBinary; - c.hash(&mut self.s); - op.node.hash(&mut self.s); - self.hash_expr(l); - self.hash_expr(r); - } - ExprBreak(i) => { - let c: fn(_) -> _ = ExprBreak; - c.hash(&mut self.s); - if let Some(i) = i { - self.hash_name(&i.node); - } - } - ExprBox(ref e) => { - let c: fn(_) -> _ = ExprBox; - c.hash(&mut self.s); - self.hash_expr(e); - } - ExprCall(ref fun, ref args) => { - let c: fn(_, _) -> _ = ExprCall; - c.hash(&mut self.s); - self.hash_expr(fun); - self.hash_exprs(args); - } - ExprCast(ref e, ref _ty) => { - let c: fn(_, _) -> _ = ExprCast; - c.hash(&mut self.s); - self.hash_expr(e); - // TODO: _ty - } - ExprClosure(cap, _, ref b, _) => { - let c: fn(_, _, _, _) -> _ = ExprClosure; - c.hash(&mut self.s); - cap.hash(&mut self.s); - self.hash_block(b); - } - ExprField(ref e, ref f) => { - let c: fn(_, _) -> _ = ExprField; - c.hash(&mut self.s); - self.hash_expr(e); - self.hash_name(&f.node); - } - ExprIndex(ref a, ref i) => { - let c: fn(_, _) -> _ = ExprIndex; - c.hash(&mut self.s); - self.hash_expr(a); - self.hash_expr(i); - } - ExprInlineAsm(..) => { - let c: fn(_, _, _) -> _ = ExprInlineAsm; - c.hash(&mut self.s); - } - ExprIf(ref cond, ref t, ref e) => { - let c: fn(_, _, _) -> _ = ExprIf; - c.hash(&mut self.s); - self.hash_expr(cond); - self.hash_block(t); - if let Some(ref e) = *e { - self.hash_expr(e); - } - } - ExprLit(ref l) => { - let c: fn(_) -> _ = ExprLit; - c.hash(&mut self.s); - l.hash(&mut self.s); - } - ExprLoop(ref b, ref i) => { - let c: fn(_, _) -> _ = ExprLoop; - c.hash(&mut self.s); - self.hash_block(b); - if let Some(i) = *i { - self.hash_name(&i); - } - } - ExprMatch(ref e, ref arms, ref s) => { - let c: fn(_, _, _) -> _ = ExprMatch; - c.hash(&mut self.s); - self.hash_expr(e); - - for arm in arms { - // TODO: arm.pat? - if let Some(ref e) = arm.guard { - self.hash_expr(e); - } - self.hash_expr(&arm.body); - } - - s.hash(&mut self.s); - } - ExprMethodCall(ref name, ref _tys, ref args) => { - let c: fn(_, _, _) -> _ = ExprMethodCall; - c.hash(&mut self.s); - self.hash_name(&name.node); - self.hash_exprs(args); - } - ExprRepeat(ref e, ref l) => { - let c: fn(_, _) -> _ = ExprRepeat; - c.hash(&mut self.s); - self.hash_expr(e); - self.hash_expr(l); - } - ExprRet(ref e) => { - let c: fn(_) -> _ = ExprRet; - c.hash(&mut self.s); - if let Some(ref e) = *e { - self.hash_expr(e); - } - } - ExprPath(ref _qself, ref subpath) => { - let c: fn(_, _) -> _ = ExprPath; - c.hash(&mut self.s); - self.hash_path(subpath); - } - ExprStruct(ref path, ref fields, ref expr) => { - let c: fn(_, _, _) -> _ = ExprStruct; - c.hash(&mut self.s); - - self.hash_path(path); - - for f in fields { - self.hash_name(&f.name.node); - self.hash_expr(&f.expr); - } - - if let Some(ref e) = *expr { - self.hash_expr(e); - } - } - ExprTup(ref tup) => { - let c: fn(_) -> _ = ExprTup; - c.hash(&mut self.s); - self.hash_exprs(tup); - } - ExprTupField(ref le, li) => { - let c: fn(_, _) -> _ = ExprTupField; - c.hash(&mut self.s); - - self.hash_expr(le); - li.node.hash(&mut self.s); - } - ExprType(_, _) => { - let c: fn(_, _) -> _ = ExprType; - c.hash(&mut self.s); - // what’s an ExprType anyway? - } - ExprUnary(lop, ref le) => { - let c: fn(_, _) -> _ = ExprUnary; - c.hash(&mut self.s); - - lop.hash(&mut self.s); - self.hash_expr(le); - } - ExprVec(ref v) => { - let c: fn(_) -> _ = ExprVec; - c.hash(&mut self.s); - - self.hash_exprs(v); - } - ExprWhile(ref cond, ref b, l) => { - let c: fn(_, _, _) -> _ = ExprWhile; - c.hash(&mut self.s); - - self.hash_expr(cond); - self.hash_block(b); - if let Some(l) = l { - self.hash_name(&l); - } - } - } - } - - pub fn hash_exprs(&mut self, e: &[P<Expr>]) { - for e in e { - self.hash_expr(e); - } - } - - pub fn hash_name(&mut self, n: &Name) { - n.as_str().hash(&mut self.s); - } - - pub fn hash_path(&mut self, p: &Path) { - p.global.hash(&mut self.s); - for p in &p.segments { - self.hash_name(&p.name); - } - } - - pub fn hash_stmt(&mut self, b: &Stmt) { - match b.node { - StmtDecl(ref _decl, _) => { - let c: fn(_, _) -> _ = StmtDecl; - c.hash(&mut self.s); - // TODO: decl - } - StmtExpr(ref expr, _) => { - let c: fn(_, _) -> _ = StmtExpr; - c.hash(&mut self.s); - self.hash_expr(expr); - } - StmtSemi(ref expr, _) => { - let c: fn(_, _) -> _ = StmtSemi; - c.hash(&mut self.s); - self.hash_expr(expr); - } - } - } -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs deleted file mode 100644 index 3ff6167620a..00000000000 --- a/src/utils/mod.rs +++ /dev/null @@ -1,840 +0,0 @@ -use reexport::*; -use rustc::hir::*; -use rustc::hir::def_id::DefId; -use rustc::hir::map::Node; -use rustc::lint::{LintContext, LateContext, Level, Lint}; -use rustc::middle::cstore; -use rustc::session::Session; -use rustc::traits::ProjectionMode; -use rustc::traits; -use rustc::ty::subst::Subst; -use rustc::ty; -use std::borrow::Cow; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::str::FromStr; -use syntax::ast::{self, LitKind, RangeLimits}; -use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; -use syntax::errors::DiagnosticBuilder; -use syntax::ptr::P; - -pub mod comparisons; -pub mod conf; -mod hir; -pub mod paths; -pub use self::hir::{SpanlessEq, SpanlessHash}; - -pub type MethodArgs = HirVec<P<Expr>>; - -/// Produce a nested chain of if-lets and ifs from the patterns: -/// -/// if_let_chain! { -/// [ -/// let Some(y) = x, -/// y.len() == 2, -/// let Some(z) = y, -/// ], -/// { -/// block -/// } -/// } -/// -/// becomes -/// -/// if let Some(y) = x { -/// if y.len() == 2 { -/// if let Some(z) = y { -/// block -/// } -/// } -/// } -#[macro_export] -macro_rules! if_let_chain { - ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { - if let $pat = $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([let $pat:pat = $expr:expr], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([let $pat:pat = $expr:expr,], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([$expr:expr, $($tt:tt)+], $block:block) => { - if $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([$expr:expr], $block:block) => { - if $expr { - $block - } - }; - ([$expr:expr,], $block:block) => { - if $expr { - $block - } - }; -} - -/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one -/// isn't). -pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { - rhs.expn_id != lhs.expn_id -} -/// Returns true if this `expn_info` was expanded by any macro. -pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some()) -} - -/// Returns true if the macro that expanded the crate was outside of the current crate or was a -/// compiler plugin. -pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool { - /// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use - /// this after other checks have already happened. - fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool { - // no ExpnInfo = no macro - opt_info.map_or(false, |info| { - if let ExpnFormat::MacroAttribute(..) = info.callee.format { - // these are all plugins - return true; - } - // no span for the callee = external macro - info.callee.span.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) - }) - }) - } - - cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info)) -} - -/// Check if a `DefId`'s path matches the given absolute type path usage. -/// -/// # Examples -/// ``` -/// match_def_path(cx, id, &["core", "option", "Option"]) -/// ``` -/// -/// See also the `paths` module. -pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { - use syntax::parse::token; - - struct AbsolutePathBuffer { - names: Vec<token::InternedString>, - } - - impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { - fn root_mode(&self) -> &ty::item_path::RootMode { - const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; - ABSOLUTE - } - - fn push(&mut self, text: &str) { - self.names.push(token::intern(text).as_str()); - } - } - - let mut apb = AbsolutePathBuffer { - names: vec![], - }; - - cx.tcx.push_item_path(&mut apb, def_id); - - apb.names == path -} - -/// Check if type is struct or enum type with given def path. -pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { - match ty.sty { - ty::TyEnum(ref adt, _) | - ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), - _ => false, - } -} - -/// Check if the method call given in `expr` belongs to given type. -pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tcx - .tables - .borrow() - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); - if let Some(trt_id) = trt_id { - match_def_path(cx, trt_id, path) - } else { - false - } -} - -/// Check if the method call given in `expr` belongs to given trait. -pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tcx - .tables - .borrow() - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); - if let Some(trt_id) = trt_id { - match_def_path(cx, trt_id, path) - } else { - false - } -} - -/// Match a `Path` against a slice of segment string literals. -/// -/// # Examples -/// ``` -/// match_path(path, &["std", "rt", "begin_unwind"]) -/// ``` -pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name.as_str() == *b) -} - -/// Match a `Path` against a slice of segment string literals, e.g. -/// -/// # Examples -/// ``` -/// match_path(path, &["std", "rt", "begin_unwind"]) -/// ``` -pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) -} - -/// Get the definition associated to a path. -/// TODO: investigate if there is something more efficient for that. -pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option<cstore::DefLike> { - let cstore = &cx.tcx.sess.cstore; - - let crates = cstore.crates(); - let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); - if let Some(krate) = krate { - let mut items = cstore.crate_top_level_items(*krate); - let mut path_it = path.iter().skip(1).peekable(); - - loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; - - for item in &mem::replace(&mut items, vec![]) { - if item.name.as_str() == *segment { - if path_it.peek().is_none() { - return Some(item.def); - } - - let def_id = match item.def { - cstore::DefLike::DlDef(def) => def.def_id(), - cstore::DefLike::DlImpl(def_id) => def_id, - _ => panic!("Unexpected {:?}", item.def), - }; - - items = cstore.item_children(def_id); - break; - } - } - } - } else { - None - } -} - -/// Convenience function to get the `DefId` of a trait by path. -pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> { - let def = match path_to_def(cx, path) { - Some(def) => def, - None => return None, - }; - - match def { - cstore::DlDef(def::Def::Trait(trait_id)) => Some(trait_id), - _ => None, - } -} - -/// Check whether a type implements a trait. -/// See also `get_trait_def_id`. -pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id: DefId, - ty_params: Vec<ty::Ty<'tcx>>) - -> bool { - cx.tcx.populate_implementations_for_trait_if_necessary(trait_id); - - let ty = cx.tcx.erase_regions(&ty); - cx.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| { - let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params); - - traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) - }) -} - -/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. -/// -/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for -/// `.bar()` and `.baz()` -pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a MethodArgs>> { - let mut current = expr; - let mut matched = Vec::with_capacity(methods.len()); - for method_name in methods.iter().rev() { - // method chains are stored last -> first - if let ExprMethodCall(ref name, _, ref args) = current.node { - if name.node.as_str() == *method_name { - matched.push(args); // build up `matched` backwards - current = &args[0] // go to parent expression - } else { - return None; - } - } else { - return None; - } - } - matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` - Some(matched) -} - - -/// Get the name of the item the expression is in, if available. -pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { - let parent_id = cx.tcx.map.get_parent(expr.id); - match cx.tcx.map.find(parent_id) { - Some(Node::NodeItem(&Item { ref name, .. })) | - Some(Node::NodeTraitItem(&TraitItem { ref name, .. })) | - Some(Node::NodeImplItem(&ImplItem { ref name, .. })) => Some(*name), - _ => None, - } -} - -/// Checks if a `let` decl is from a `for` loop desugaring. -pub fn is_from_for_desugar(decl: &Decl) -> bool { - if_let_chain! { - [ - let DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node - ], - { return true; } - }; - false -} - - -/// Convert a span to a code snippet if available, otherwise use default. -/// -/// # Example -/// ``` -/// snippet(cx, expr.span, "..") -/// ``` -pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default)) -} - -/// Convert a span to a code snippet. Returns `None` if not available. -pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { - cx.sess().codemap().span_to_snippet(span).ok() -} - -/// Convert a span (from a block) to a code snippet if available, otherwise use default. -/// This trims the code of indentation, except for the first line. Use it for blocks or block-like -/// things which need to be printed as such. -/// -/// # Example -/// ``` -/// snippet(cx, expr.span, "..") -/// ``` -pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - let snip = snippet(cx, span, default); - trim_multiline(snip, true) -} - -/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. -/// Also takes an `Option<String>` which can be put inside the braces. -pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> { - let code = snippet_block(cx, expr.span, default); - let string = option.unwrap_or_default(); - if let ExprBlock(_) = expr.node { - Cow::Owned(format!("{}{}", code, string)) - } else if string.is_empty() { - Cow::Owned(format!("{{ {} }}", code)) - } else { - Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) - } -} - -/// Trim indentation from a multiline string with possibility of ignoring the first line. -pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> { - let s_space = trim_multiline_inner(s, ignore_first, ' '); - let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); - trim_multiline_inner(s_tab, ignore_first, ' ') -} - -fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> { - let x = s.lines() - .skip(ignore_first as usize) - .filter_map(|l| { - if l.is_empty() { - None - } else { - // ignore empty lines - Some(l.char_indices() - .find(|&(_, x)| x != ch) - .unwrap_or((l.len(), ch)) - .0) - } - }) - .min() - .unwrap_or(0); - if x > 0 { - Cow::Owned(s.lines() - .enumerate() - .map(|(i, l)| { - if (ignore_first && i == 0) || l.is_empty() { - l - } else { - l.split_at(x).1 - } - }) - .collect::<Vec<_>>() - .join("\n")) - } else { - s - } -} - -/// Get a parent expressions if any – this is useful to constrain a lint. -pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { - let map = &cx.tcx.map; - let node_id: NodeId = e.id; - let parent_id: NodeId = map.get_parent_node(node_id); - if node_id == parent_id { - return None; - } - map.find(parent_id).and_then(|node| { - if let Node::NodeExpr(parent) = node { - Some(parent) - } else { - None - } - }) -} - -pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> { - let map = &cx.tcx.map; - let enclosing_node = map.get_enclosing_scope(node) - .and_then(|enclosing_id| map.find(enclosing_id)); - if let Some(node) = enclosing_node { - match node { - Node::NodeBlock(ref block) => Some(block), - Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), - _ => None, - } - } else { - None - } -} - -pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>); - -impl<'a> Drop for DiagnosticWrapper<'a> { - fn drop(&mut self) { - self.0.emit(); - } -} - -impl<'a> DerefMut for DiagnosticWrapper<'a> { - fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { - &mut self.0 - } -} - -impl<'a> Deref for DiagnosticWrapper<'a> { - type Target = DiagnosticBuilder<'a>; - fn deref(&self) -> &DiagnosticBuilder<'a> { - &self.0 - } -} - -impl<'a> DiagnosticWrapper<'a> { - fn wiki_link(&mut self, lint: &'static Lint) { - self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); - } -} - -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - if cx.current_level(lint) != Level::Allow { - db.wiki_link(lint); - } - db -} - -pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) - -> DiagnosticWrapper<'a> { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - if cx.current_level(lint) != Level::Allow { - db.help(help); - db.wiki_link(lint); - } - db -} - -pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, - note: &str) - -> DiagnosticWrapper<'a> { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - if cx.current_level(lint) != Level::Allow { - if note_span == span { - db.note(note); - } else { - db.span_note(note_span, note); - } - db.wiki_link(lint); - } - db -} - -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) - -> DiagnosticWrapper<'a> - where F: FnOnce(&mut DiagnosticWrapper) -{ - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - if cx.current_level(lint) != Level::Allow { - f(&mut db); - db.wiki_link(lint); - } - db -} - -/// Return the base type for references and raw pointers. -pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { - match ty.sty { - ty::TyRef(_, ref tm) | - ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), - _ => ty, - } -} - -/// Return the base type for references and raw pointers, and count reference depth. -pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { - fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { - match ty.sty { - ty::TyRef(_, ref tm) | - ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), - _ => (ty, depth), - } - } - inner(ty, 0) -} - -/// Check whether the given expression is a constant literal of the given value. -pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { - // FIXME: use constant folding - if let ExprLit(ref spanned) = expr.node { - if let LitKind::Int(v, _) = spanned.node { - return v == value; - } - } - false -} - -pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { - cx.tcx.tables.borrow().adjustments.get(&e.id).is_some() -} - -pub struct LimitStack { - stack: Vec<u64>, -} - -impl Drop for LimitStack { - fn drop(&mut self) { - assert_eq!(self.stack.len(), 1); - } -} - -impl LimitStack { - pub fn new(limit: u64) -> LimitStack { - LimitStack { stack: vec![limit] } - } - pub fn limit(&self) -> u64 { - *self.stack.last().expect("there should always be a value in the stack") - } - pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { - let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| stack.push(val)); - } - pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { - let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); - } -} - -fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { - for attr in attrs { - let attr = &attr.node; - if attr.is_sugared_doc { - continue; - } - if let ast::MetaItemKind::NameValue(ref key, ref value) = attr.value.node { - if *key == name { - if let LitKind::Str(ref s, _) = value.node { - if let Ok(value) = FromStr::from_str(s) { - f(value) - } else { - sess.span_err(value.span, "not a number"); - } - } else { - unreachable!() - } - } - } - } -} - -/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. -/// See also `is_direct_expn_of`. -pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> { - loop { - let span_name_span = cx.tcx - .sess - .codemap() - .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); - - match span_name_span { - Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), - None => return None, - Some((_, new_span)) => span = new_span, - } - } -} - -/// Return the pre-expansion span if is this directly comes from an expansion of the macro `name`. -/// The difference with `is_expn_of` is that in -/// ```rust,ignore -/// foo!(bar!(42)); -/// ``` -/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only `bar!` by -/// `is_direct_expn_of`. -pub fn is_direct_expn_of(cx: &LateContext, span: Span, name: &str) -> Option<Span> { - let span_name_span = cx.tcx - .sess - .codemap() - .with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site))); - - match span_name_span { - Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span), - _ => None, - } -} - -/// Return the index of the character after the first camel-case component of `s`. -pub fn camel_case_until(s: &str) -> usize { - let mut iter = s.char_indices(); - if let Some((_, first)) = iter.next() { - if !first.is_uppercase() { - return 0; - } - } else { - return 0; - } - let mut up = true; - let mut last_i = 0; - for (i, c) in iter { - if up { - if c.is_lowercase() { - up = false; - } else { - return last_i; - } - } else if c.is_uppercase() { - up = true; - last_i = i; - } else if !c.is_lowercase() { - return i; - } - } - if up { - last_i - } else { - s.len() - } -} - -/// Return index of the last camel-case component of `s`. -pub fn camel_case_from(s: &str) -> usize { - let mut iter = s.char_indices().rev(); - if let Some((_, first)) = iter.next() { - if !first.is_lowercase() { - return s.len(); - } - } else { - return s.len(); - } - let mut down = true; - let mut last_i = s.len(); - for (i, c) in iter { - if down { - if c.is_uppercase() { - down = false; - last_i = i; - } else if !c.is_lowercase() { - return last_i; - } - } else if c.is_lowercase() { - down = true; - } else { - return last_i; - } - } - last_i -} - -/// Represent a range akin to `ast::ExprKind::Range`. -#[derive(Debug, Copy, Clone)] -pub struct UnsugaredRange<'a> { - pub start: Option<&'a Expr>, - pub end: Option<&'a Expr>, - pub limits: RangeLimits, -} - -/// Unsugar a `hir` range. -pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { - // To be removed when ranges get stable. - fn unwrap_unstable(expr: &Expr) -> &Expr { - if let ExprBlock(ref block) = expr.node { - if block.rules == BlockCheckMode::PushUnstableBlock || block.rules == BlockCheckMode::PopUnstableBlock { - if let Some(ref expr) = block.expr { - return expr; - } - } - } - - expr - } - - fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> { - let expr = &fields.iter() - .find(|field| field.name.node.as_str() == name) - .unwrap_or_else(|| panic!("missing {} field for range", name)) - .expr; - - Some(unwrap_unstable(expr)) - } - - // The range syntax is expanded to literal paths starting with `core` or `std` depending on - // `#[no_std]`. Testing both instead of resolving the paths. - - match unwrap_unstable(expr).node { - ExprPath(None, ref path) => { - if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { - Some(UnsugaredRange { - start: None, - end: None, - limits: RangeLimits::HalfOpen, - }) - } else { - None - } - } - ExprStruct(ref path, ref fields, None) => { - if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: None, - limits: RangeLimits::HalfOpen, - }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: get_field("end", fields), - limits: RangeLimits::Closed, - }) - } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: get_field("end", fields), - limits: RangeLimits::HalfOpen, - }) - } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { - Some(UnsugaredRange { - start: None, - end: get_field("end", fields), - limits: RangeLimits::Closed, - }) - } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { - Some(UnsugaredRange { - start: None, - end: get_field("end", fields), - limits: RangeLimits::HalfOpen, - }) - } else { - None - } - } - _ => None, - } -} - -/// Convenience function to get the return type of a function or `None` if the function diverges. -pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { - let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); - let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, parameter_env.free_substs); - let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); - if let ty::FnConverging(ret_ty) = fn_sig.output { - Some(ret_ty) - } else { - None - } -} - -/// Check if two types are the same. -// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but -// not for type parameters. -pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>, parameter_item: NodeId) -> bool { - let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, parameter_item); - cx.tcx.infer_ctxt(None, Some(parameter_env), ProjectionMode::Any).enter(|infcx| { - let new_a = a.subst(infcx.tcx, infcx.parameter_environment.free_substs); - let new_b = b.subst(infcx.tcx, infcx.parameter_environment.free_substs); - infcx.can_equate(&new_a, &new_b).is_ok() - }) -} - -/// Recover the essential nodes of a desugared for loop: -/// `for pat in arg { body }` becomes `(pat, arg, body)`. -pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { - if_let_chain! { - [ - let ExprMatch(ref iterexpr, ref arms, _) = expr.node, - let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let ExprLoop(ref block, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, - somepats.len() == 1 - ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); - } - } - None -} diff --git a/src/utils/paths.rs b/src/utils/paths.rs deleted file mode 100644 index 3c91578abd0..00000000000 --- a/src/utils/paths.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! This module contains paths to types and functions Clippy needs to know about. - -pub const BEGIN_PANIC: [&'static str; 3] = ["std", "rt", "begin_panic"]; -pub const BINARY_HEAP: [&'static str; 3] = ["collections", "binary_heap", "BinaryHeap"]; -pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; -pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; -pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; -pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; -pub const BTREESET: [&'static str; 4] = ["collections", "btree", "set", "BTreeSet"]; -pub const CLONE: [&'static str; 4] = ["core", "clone", "Clone", "clone"]; -pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"]; -pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; -pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"]; -pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"]; -pub const CSTRING_NEW: [&'static str; 4] = ["std", "ffi", "CString", "new"]; -pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Debug", "fmt"]; -pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"]; -pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["std", "fmt", "Display", "fmt"]; -pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; -pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["std", "fmt", "Arguments", "new_v1"]; -pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["std", "fmt", "ArgumentV1", "new"]; -pub const HASH: [&'static str; 2] = ["hash", "Hash"]; -pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; -pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; -pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; -pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"]; -pub const ITERATOR: [&'static str; 4] = ["core", "iter", "iterator", "Iterator"]; -pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"]; -pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; -pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; -pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; -pub const RANGE: [&'static str; 3] = ["core", "ops", "Range"]; -pub const RANGE_FROM: [&'static str; 3] = ["core", "ops", "RangeFrom"]; -pub const RANGE_FROM_STD: [&'static str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&'static str; 3] = ["core", "ops", "RangeFull"]; -pub const RANGE_FULL_STD: [&'static str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeInclusive"]; -pub const RANGE_INCLUSIVE_NON_EMPTY: [&'static str; 4] = ["core", "ops", "RangeInclusive", "NonEmpty"]; -pub const RANGE_INCLUSIVE_NON_EMPTY_STD: [&'static str; 4] = ["std", "ops", "RangeInclusive", "NonEmpty"]; -pub const RANGE_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeInclusive"]; -pub const RANGE_STD: [&'static str; 3] = ["std", "ops", "Range"]; -pub const RANGE_TO: [&'static str; 3] = ["core", "ops", "RangeTo"]; -pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclusive"]; -pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; -pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; -pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; -pub const REGEX_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; -pub const REGEX_BYTES_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; -pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "new"]; -pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; -pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; -pub const REGEX_SET_NEW: [&'static str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; -pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; -pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; -pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; -pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"]; -pub const VEC_DEQUE: [&'static str; 3] = ["collections", "vec_deque", "VecDeque"]; -pub const VEC_FROM_ELEM: [&'static str; 3] = ["std", "vec", "from_elem"]; diff --git a/src/vec.rs b/src/vec.rs deleted file mode 100644 index e62a8f9c459..00000000000 --- a/src/vec.rs +++ /dev/null @@ -1,116 +0,0 @@ -use rustc::lint::*; -use rustc::ty::TypeVariants; -use rustc::hir::*; -use syntax::codemap::Span; -use syntax::ptr::P; -use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; - -/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. -/// -/// **Why is this bad?** This is less efficient. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// foo(&vec![1, 2]) -/// ``` -declare_lint! { - pub USELESS_VEC, - Warn, - "useless `vec!`" -} - -#[derive(Copy, Clone, Debug)] -pub struct UselessVec; - -impl LintPass for UselessVec { - fn get_lints(&self) -> LintArray { - lint_array!(USELESS_VEC) - } -} - -impl LateLintPass for UselessVec { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - // search for `&vec![_]` expressions where the adjusted type is `&[_]` - if_let_chain!{[ - let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, - let TypeVariants::TySlice(..) = ty.ty.sty, - let ExprAddrOf(_, ref addressee) = expr.node, - ], { - check_vec_macro(cx, addressee, expr.span); - }} - - // search for `for _ in vec![…]` - if let Some((_, arg, _)) = recover_for_loop(expr) { - // report the error around the `vec!` not inside `<std macros>:` - let span = cx.sess().codemap().source_callsite(arg.span); - check_vec_macro(cx, arg, span); - } - } -} - -fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { - if let Some(vec_args) = unexpand_vec(cx, vec) { - let snippet = match vec_args { - VecArgs::Repeat(elem, len) => { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() - } - VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = Span { - lo: args[0].span.lo, - hi: last.span.hi, - expn_id: args[0].span.expn_id, - }; - - format!("&[{}]", snippet(cx, span, "..")).into() - } else { - "&[]".into() - } - } - }; - - span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { - db.span_suggestion(span, "you can use a slice directly", snippet); - }); - } -} - -/// Represent the pre-expansion arguments of a `vec!` invocation. -pub enum VecArgs<'a> { - /// `vec![elem; len]` - Repeat(&'a P<Expr>, &'a P<Expr>), - /// `vec![a, b, c]` - Vec(&'a [P<Expr>]), -} - -/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. -pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> { - if_let_chain!{[ - let ExprCall(ref fun, ref args) = expr.node, - let ExprPath(_, ref path) = fun.node, - is_expn_of(cx, fun.span, "vec").is_some() - ], { - return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { - // `vec![elem; size]` case - Some(VecArgs::Repeat(&args[0], &args[1])) - } - else if match_path(path, &["into_vec"]) && args.len() == 1 { - // `vec![a, b, c]` case - if_let_chain!{[ - let ExprBox(ref boxed) = args[0].node, - let ExprVec(ref args) = boxed.node - ], { - return Some(VecArgs::Vec(&*args)); - }} - - None - } - else { - None - }; - }} - - None -} diff --git a/src/zero_div_zero.rs b/src/zero_div_zero.rs deleted file mode 100644 index 902d84d4dd3..00000000000 --- a/src/zero_div_zero.rs +++ /dev/null @@ -1,59 +0,0 @@ -use consts::{Constant, constant_simple, FloatWidth}; -use rustc::lint::*; -use rustc::hir::*; -use utils::span_help_and_lint; - -/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists -/// `of 0.0/0.0`, which is always `NaN`. It is more clear to replace instances of -/// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. -pub struct ZeroDivZeroPass; - -/// **What it does:** This lint checks for `0.0 / 0.0`. -/// -/// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN` -/// -/// **Known problems:** None -/// -/// **Example** `0.0f32 / 0.0` -declare_lint! { - pub ZERO_DIVIDED_BY_ZERO, - Warn, - "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" -} - -impl LintPass for ZeroDivZeroPass { - fn get_lints(&self) -> LintArray { - lint_array!(ZERO_DIVIDED_BY_ZERO) - } -} - -impl LateLintPass for ZeroDivZeroPass { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - // check for instances of 0.0/0.0 - if_let_chain! { - [ - let ExprBinary(ref op, ref left, ref right) = expr.node, - let BinOp_::BiDiv = op.node, - // TODO - constant_simple does not fold many operations involving floats. - // That's probably fine for this lint - it's pretty unlikely that someone would - // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), - let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), - let Some(0.0) = lhs_value.parse().ok(), - let Some(0.0) = rhs_value.parse().ok() - ], - { - // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, - // match the precision of the literals that are given. - let float_type = match (lhs_width, rhs_width) { - (FloatWidth::F64, _) - | (_, FloatWidth::F64) => "f64", - _ => "f32" - }; - span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, - "constant division of 0.0 with 0.0 will always result in NaN", - &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); - } - } - } -} diff --git a/tests/dogfood.rs b/tests/dogfood.rs index d3021b8f2f9..5121fd08628 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -13,7 +13,7 @@ use test::TestPaths; fn dogfood() { let mut config = compiletest::default_config(); - let cfg_mode = "run-pass".parse().expect("Invalid mode"); + let cfg_mode = "run-fail".parse().expect("Invalid mode"); let mut s = String::new(); s.push_str(" -L target/debug/"); s.push_str(" -L target/debug/deps"); @@ -30,13 +30,21 @@ fn dogfood() { config.mode = cfg_mode; - let paths = TestPaths { - base: PathBuf::new(), - file: PathBuf::from("src/lib.rs"), - relative_dir: PathBuf::new(), - }; + let files = [ + "src/main.rs", + "src/lib.rs", + "clippy_lints/src/lib.rs", + ]; - set_var("CLIPPY_DOGFOOD", "tastes like chicken"); + for file in &files { + let paths = TestPaths { + base: PathBuf::new(), + file: PathBuf::from(file), + relative_dir: PathBuf::new(), + }; - compiletest::runtest::run(config, &paths); + set_var("CLIPPY_DOGFOOD", "tastes like chicken"); + + compiletest::runtest::run(config.clone(), &paths); + } } diff --git a/util/update_lints.py b/util/update_lints.py index bfed0430abb..8078b68367b 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -61,7 +61,7 @@ def collect(lints, deprecated_lints, restriction_lints, fn): match.group('name').lower(), "allow", desc.replace('\\"', '"'))) - + def gen_table(lints, link=None): """Write lint table in Markdown format.""" @@ -144,15 +144,15 @@ def main(print_only=False, check=False): restriction_lints = [] # check directory - if not os.path.isfile('src/lib.rs'): + if not os.path.isfile('clippy_lints/src/lib.rs'): print('Error: call this script from clippy checkout directory!') return # collect all lints from source files - for root, _, files in os.walk('src'): + for root, _, files in os.walk('clippy_lints/src'): for fn in files: if fn.endswith('.rs'): - collect(lints, deprecated_lints, restriction_lints, + collect(lints, deprecated_lints, restriction_lints, os.path.join(root, fn)) if print_only: @@ -178,38 +178,38 @@ def main(print_only=False, check=False): "<!-- begin autogenerated links to wiki -->", "<!-- end autogenerated links to wiki -->", lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], wiki_link) for l in - sorted(lints + restriction_lints + deprecated_lints, + sorted(lints + restriction_lints + deprecated_lints, key=lambda l: l[1])], replace_start=False, write_back=not check) # update the `pub mod` list changed |= replace_region( - 'src/lib.rs', r'begin lints modules', r'end lints modules', + 'clippy_lints/src/lib.rs', r'begin lints modules', r'end lints modules', lambda: gen_mods(lints + restriction_lints), replace_start=False, write_back=not check) # same for "clippy" lint collection changed |= replace_region( - 'src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', lambda: gen_group(lints, levels=('warn', 'deny')), replace_start=False, write_back=not check) # same for "deprecated" lint collection changed |= replace_region( - 'src/lib.rs', r'let mut store', r'end deprecated lints', + 'clippy_lints/src/lib.rs', r'let mut store', r'end deprecated lints', lambda: gen_deprecated(deprecated_lints), replace_start=False, write_back=not check) # same for "clippy_pedantic" lint collection changed |= replace_region( - 'src/lib.rs', r'reg.register_lint_group\("clippy_pedantic"', r'\]\);', + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_pedantic"', r'\]\);', lambda: gen_group(lints, levels=('allow',)), replace_start=False, write_back=not check) # same for "clippy_restrictions" lint collection changed |= replace_region( - 'src/lib.rs', r'reg.register_lint_group\("clippy_restrictions"', + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_restrictions"', r'\]\);', lambda: gen_group(restriction_lints), replace_start=False, write_back=not check) -- cgit 1.4.1-3-g733a5 From 71b41b6e01af2a68490f219a59a183873f5e1c64 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 27 May 2016 15:55:08 +0200 Subject: Fix wiki links and `char_lit_as_u8` --- util/update_wiki.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index 5040a28bca0..ccb82b9901a 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -59,7 +59,7 @@ def parse_file(d, f): last_comment = [] if not comment: l = line.strip() - m = re.search(r"pub\s+([A-Z_]+)", l) + m = re.search(r"pub\s+([A-Z_][A-Z_0-9]*)", l) if m: name = m.group(1).lower() -- cgit 1.4.1-3-g733a5 From f314fa8d285d4e8924dce798b3da2e0f87c32494 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 27 May 2016 15:57:03 +0200 Subject: Some Python style nits. --- util/update_lints.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/util/update_lints.py b/util/update_lints.py index 8078b68367b..1ed0161ad24 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -58,9 +58,9 @@ def collect(lints, deprecated_lints, restriction_lints, fn): # remove \-newline escapes from description string desc = nl_escape_re.sub('', match.group('desc')) restriction_lints.append((os.path.splitext(os.path.basename(fn))[0], - match.group('name').lower(), - "allow", - desc.replace('\\"', '"'))) + match.group('name').lower(), + "allow", + desc.replace('\\"', '"'))) def gen_table(lints, link=None): @@ -100,6 +100,7 @@ def gen_deprecated(lints): for lint in lints: yield ' store.register_removed("%s", "%s");\n' % (lint[1], lint[2]) + def replace_region(fn, region_start, region_end, callback, replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. @@ -168,8 +169,8 @@ def main(print_only=False, check=False): changed |= replace_region( 'README.md', r'^There are \d+ lints included in this crate:', "", - lambda: ['There are %d lints included in this crate:\n' % (len(lints) - + len(restriction_lints))], + lambda: ['There are %d lints included in this crate:\n' % + (len(lints) + len(restriction_lints))], write_back=not check) # update the links in the CHANGELOG @@ -196,10 +197,10 @@ def main(print_only=False, check=False): # same for "deprecated" lint collection changed |= replace_region( - 'clippy_lints/src/lib.rs', r'let mut store', r'end deprecated lints', - lambda: gen_deprecated(deprecated_lints), - replace_start=False, - write_back=not check) + 'clippy_lints/src/lib.rs', r'let mut store', r'end deprecated lints', + lambda: gen_deprecated(deprecated_lints), + replace_start=False, + write_back=not check) # same for "clippy_pedantic" lint collection changed |= replace_region( -- cgit 1.4.1-3-g733a5 From 5d64b81787de81c43bf770ec4074493e1cafae40 Mon Sep 17 00:00:00 2001 From: Georg Brandl <georg@python.org> Date: Fri, 27 May 2016 15:57:44 +0200 Subject: Ensure the correct clippy_lints dependency version. --- Cargo.toml | 4 +++- clippy_lints/Cargo.toml | 2 ++ util/update_lints.py | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3a45da08f89..09828a2eb51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,9 @@ semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" -clippy_lints = { version = "0.0.*", path = "clippy_lints" } +# begin automatic update +clippy_lints = { version = "0.0.69", path = "clippy_lints" } +# end automatic update [dev-dependencies] compiletest_rs = "0.1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index da10ca0c0b7..91acaee3bb5 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy_lints" +# begin automatic update version = "0.0.69" +# end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/util/update_lints.py b/util/update_lints.py index 1ed0161ad24..35bddcbbb5c 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -156,6 +156,16 @@ def main(print_only=False, check=False): collect(lints, deprecated_lints, restriction_lints, os.path.join(root, fn)) + # determine version + with open('Cargo.toml') as fp: + for line in fp: + if line.startswith('version ='): + clippy_version = line.split()[2].strip('"') + break + else: + print('Error: version not found in Cargo.toml!') + return + if print_only: sys.stdout.writelines(gen_table(lints + restriction_lints)) return @@ -183,6 +193,19 @@ def main(print_only=False, check=False): key=lambda l: l[1])], replace_start=False, write_back=not check) + # update version of clippy_lints in Cargo.toml + changed |= replace_region( + 'Cargo.toml', r'# begin automatic update', '# end automatic update', + lambda: ['clippy_lints = { version = "%s", path = "clippy_lints" }\n' % + clippy_version], + replace_start=False, write_back=not check) + + # update version of clippy_lints in Cargo.toml + changed |= replace_region( + 'clippy_lints/Cargo.toml', r'# begin automatic update', '# end automatic update', + lambda: ['version = "%s"\n' % clippy_version], + replace_start=False, write_back=not check) + # update the `pub mod` list changed |= replace_region( 'clippy_lints/src/lib.rs', r'begin lints modules', r'end lints modules', -- cgit 1.4.1-3-g733a5 From ac0bb4126c835ea89313cbb4f534c37bc14a2694 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 26 May 2016 22:53:38 +0200 Subject: Improve markdown parsing for the doc lint --- clippy_lints/src/doc.rs | 198 ++++++++++++++++++++++++++++------------------ tests/compile-fail/doc.rs | 7 ++ 2 files changed, 128 insertions(+), 77 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index cf32c1731fa..fd4640c2158 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -51,6 +51,8 @@ impl EarlyLintPass for Doc { } pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { + let mut docs = vec![]; + let mut in_multiline = false; for attr in attrs { if attr.node.is_sugared_doc { @@ -66,37 +68,20 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a in_multiline = !in_multiline; } if !in_multiline { - check_doc(cx, valid_idents, real_doc, span); + docs.push((real_doc, span)); } } } } } -} - -macro_rules! jump_to { - // Get the next character’s first byte UTF-8 friendlyly. - (@next_char, $chars: expr, $len: expr) => {{ - if let Some(&(pos, _)) = $chars.peek() { - pos - } else { - $len - } - }}; - // Jump to the next `$c`. If no such character is found, give up. - ($chars: expr, $c: expr, $len: expr) => {{ - if $chars.find(|&(_, c)| c == $c).is_some() { - jump_to!(@next_char, $chars, $len) - } - else { - return; - } - }}; + for (doc, span) in docs { + let _ = check_doc(cx, valid_idents, doc, span); + } } #[allow(while_let_loop)] // #362 -pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) { +pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) -> Result<(), ()> { // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. // There really is no markdown specification that would disambiguate this properly. This is // what GitHub and Rustdoc do: @@ -108,8 +93,8 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp // (_baz_) → (<em>baz</em>) // foo _ bar _ baz → foo _ bar _ baz - /// Character that can appear in a word - fn is_word_char(c: char) -> bool { + /// Character that can appear in a path + fn is_path_char(c: char) -> bool { match c { t if t.is_alphanumeric() => true, ':' | '_' => true, @@ -117,81 +102,140 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp } } - #[allow(cast_possible_truncation)] - fn word_span(mut span: Span, begin: usize, end: usize) -> Span { - debug_assert_eq!(end as u32 as usize, end); - debug_assert_eq!(begin as u32 as usize, begin); - span.hi = span.lo + BytePos(end as u32); - span.lo = span.lo + BytePos(begin as u32); - span + #[derive(Clone, Debug)] + struct Parser<'a> { + link: bool, + line: &'a str, + span: Span, + current_word_begin: usize, + new_line: bool, + pos: usize, + } + + impl<'a> Parser<'a> { + fn advance_begin(&mut self) { + self.current_word_begin = self.pos; + } + + fn peek(&self) -> Option<char> { + self.line[self.pos..].chars().next() + } + + fn jump_to(&mut self, n: char) -> Result<(), ()> { + while let Some(c) = self.next() { + if c == n { + self.advance_begin(); + return Ok(()); + } + } + + return Err(()); + } + + fn put_back(&mut self, c: char) { + self.pos -= c.len_utf8(); + } + + #[allow(cast_possible_truncation)] + fn word(&self) -> (&'a str, Span) { + let begin = self.current_word_begin; + let end = self.pos; + + debug_assert_eq!(end as u32 as usize, end); + debug_assert_eq!(begin as u32 as usize, begin); + + let mut span = self.span; + span.hi = span.lo + BytePos(end as u32); + span.lo = span.lo + BytePos(begin as u32); + + (&self.line[begin..end], span) + } + } + + impl<'a> Iterator for Parser<'a> { + type Item = char; + + fn next(&mut self) -> Option<char> { + let mut chars = self.line[self.pos..].chars(); + let c = chars.next(); + + if let Some(c) = c { + self.pos += c.len_utf8(); + } else { + // TODO: new line + } + + c + } } - let mut new_line = true; - let len = doc.len(); - let mut chars = doc.char_indices().peekable(); - let mut current_word_begin = 0; + let mut parser = Parser { + link: false, + line: doc, + span: span, + current_word_begin: 0, + new_line: true, + pos: 0, + }; + loop { - match chars.next() { - Some((_, c)) => { + match parser.next() { + Some(c) => { match c { '#' if new_line => { // don’t warn on titles - current_word_begin = jump_to!(chars, '\n', len); + try!(parser.jump_to('\n')); } '`' => { - current_word_begin = jump_to!(chars, '`', len); + try!(parser.jump_to('`')); } '[' => { - let end = jump_to!(chars, ']', len); - let link_text = &doc[current_word_begin + 1..end]; - let word_span = word_span(span, current_word_begin + 1, end + 1); - - match chars.peek() { - Some(&(_, c)) => { - // Trying to parse a link. Let’s ignore the link. - - // FIXME: how does markdown handles such link? - // https://en.wikipedia.org/w/index.php?title=) - match c { - '(' => { // inline link - current_word_begin = jump_to!(chars, ')', len); - check_doc(cx, valid_idents, link_text, word_span); - } - '[' => { // reference link - current_word_begin = jump_to!(chars, ']', len); - check_doc(cx, valid_idents, link_text, word_span); - } - ':' => { // reference link - current_word_begin = jump_to!(chars, '\n', len); - } - _ => { // automatic reference link - current_word_begin = jump_to!(@next_char, chars, len); - check_doc(cx, valid_idents, link_text, word_span); - } + // Check for a reference definition `[foo]:` at the beginning of a line + let mut link = true; + if parser.new_line { + let mut lookup_parser = parser.clone(); + if let Some(_) = lookup_parser.find(|&c| c == ']') { + if let Some(':') = lookup_parser.next() { + try!(lookup_parser.jump_to(')')); + parser = lookup_parser; + link = false; } } - None => return, + } + + parser.advance_begin(); + parser.link = link; + } + ']' if parser.link => { + parser.link = false; + + match parser.peek() { + Some('(') => try!(parser.jump_to(')')), + Some('[') => try!(parser.jump_to(']')), + Some(_) => continue, + None => return Err(()), } } - // anything that’s neither alphanumeric nor '_' is not part of an ident anyway - c if !c.is_alphanumeric() && c != '_' => { - current_word_begin = jump_to!(@next_char, chars, len); + c if !is_path_char(c) => { + parser.advance_begin(); } _ => { - let end = match chars.find(|&(_, c)| !is_word_char(c)) { - Some((end, _)) => end, - None => len, - }; - let word_span = word_span(span, current_word_begin, end); - check_word(cx, valid_idents, &doc[current_word_begin..end], word_span); - current_word_begin = jump_to!(@next_char, chars, len); + if let Some(c) = parser.find(|&c| !is_path_char(c)) { + parser.put_back(c); + } + + let (word, span) = parser.word(); + check_word(cx, valid_idents, word, span); + parser.advance_begin(); } } - new_line = c == '\n' || (new_line && c.is_whitespace()); + parser.new_line = c == '\n' || (parser.new_line && c.is_whitespace()); } None => break, } } + + Ok(()) } fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span) { diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index eca9d79354c..f5c1e4768e9 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -12,6 +12,8 @@ /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun //~^ ERROR: you should put `Foo::some_fun` between ticks /// which should be reported only once despite being __doubly bad__. +/// Here be ::is::a::global:path. +//~^ ERROR: you should put `is::a::global:path` between ticks /// be_sure_we_got_to_the_end_of_it //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn foo_bar() { @@ -141,3 +143,8 @@ fn issue900() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn issue883() { } + +/// `foo_bar +/// baz_quz` +fn multiline() { +} -- cgit 1.4.1-3-g733a5 From 97c9930a3f8991da2e8b5edb8d1748ca7e2f20d1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 28 May 2016 03:18:52 +0200 Subject: Fix `doc_markdown` and multiline quotes and links --- clippy_lints/src/doc.rs | 107 +++++++++++++++++++++++++++++++--------------- tests/compile-fail/doc.rs | 26 +++++------ 2 files changed, 87 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index fd4640c2158..af1fbaa0f7d 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -66,8 +66,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a // check for multiline code blocks if real_doc.trim_left().starts_with("```") { in_multiline = !in_multiline; - } - if !in_multiline { + } else if !in_multiline { docs.push((real_doc, span)); } } @@ -75,13 +74,13 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a } } - for (doc, span) in docs { - let _ = check_doc(cx, valid_idents, doc, span); + if !docs.is_empty() { + let _ = check_doc(cx, valid_idents, &docs); } } #[allow(while_let_loop)] // #362 -pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Span) -> Result<(), ()> { +pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) -> Result<(), ()> { // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. // There really is no markdown specification that would disambiguate this properly. This is // what GitHub and Rustdoc do: @@ -103,12 +102,22 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp } #[derive(Clone, Debug)] + /// This type is used to iterate through the documentation characters, keeping the span at the + /// same time. struct Parser<'a> { - link: bool, - line: &'a str, - span: Span, + /// First byte of the current potential match current_word_begin: usize, + /// List of lines and their associated span + docs: &'a[(&'a str, Span)], + /// Index of the current line we are parsing + line: usize, + /// Whether we are in a link + link: bool, + /// Whether we are at the beginning of a line new_line: bool, + /// Whether we were to the end of a line last time `next` was called + reset: bool, + /// The position of the current character within the current line pos: usize, } @@ -117,19 +126,31 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp self.current_word_begin = self.pos; } + fn line(&self) -> (&'a str, Span) { + self.docs[self.line] + } + fn peek(&self) -> Option<char> { - self.line[self.pos..].chars().next() + self.line().0[self.pos..].chars().next() } + #[allow(while_let_on_iterator)] // borrowck complains about for fn jump_to(&mut self, n: char) -> Result<(), ()> { - while let Some(c) = self.next() { + while let Some((_, c)) = self.next() { if c == n { self.advance_begin(); return Ok(()); } } - return Err(()); + Err(()) + } + + fn next_line(&mut self) { + self.pos = 0; + self.current_word_begin = 0; + self.line += 1; + self.new_line = true; } fn put_back(&mut self, c: char) { @@ -144,46 +165,64 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp debug_assert_eq!(end as u32 as usize, end); debug_assert_eq!(begin as u32 as usize, begin); - let mut span = self.span; + let (doc, mut span) = self.line(); span.hi = span.lo + BytePos(end as u32); span.lo = span.lo + BytePos(begin as u32); - (&self.line[begin..end], span) + (&doc[begin..end], span) } } impl<'a> Iterator for Parser<'a> { - type Item = char; - - fn next(&mut self) -> Option<char> { - let mut chars = self.line[self.pos..].chars(); - let c = chars.next(); + type Item = (bool, char); + + fn next(&mut self) -> Option<(bool, char)> { + while self.line < self.docs.len() { + if self.reset { + self.line += 1; + self.reset = false; + self.pos = 0; + self.current_word_begin = 0; + } - if let Some(c) = c { - self.pos += c.len_utf8(); - } else { - // TODO: new line + let mut chars = self.line().0[self.pos..].chars(); + let c = chars.next(); + + if let Some(c) = c { + self.pos += c.len_utf8(); + let new_line = self.new_line; + self.new_line = c == '\n' || (self.new_line && c.is_whitespace()); + return Some((new_line, c)); + } else if self.line == self.docs.len() - 1 { + return None; + } else { + self.new_line = true; + self.reset = true; + self.pos += 1; + return Some((true, '\n')); + } } - c + None } } let mut parser = Parser { - link: false, - line: doc, - span: span, current_word_begin: 0, + docs: docs, + line: 0, + link: false, new_line: true, + reset: false, pos: 0, }; loop { match parser.next() { - Some(c) => { + Some((new_line, c)) => { match c { '#' if new_line => { // don’t warn on titles - try!(parser.jump_to('\n')); + parser.next_line(); } '`' => { try!(parser.jump_to('`')); @@ -191,11 +230,12 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp '[' => { // Check for a reference definition `[foo]:` at the beginning of a line let mut link = true; - if parser.new_line { + + if new_line { let mut lookup_parser = parser.clone(); - if let Some(_) = lookup_parser.find(|&c| c == ']') { - if let Some(':') = lookup_parser.next() { - try!(lookup_parser.jump_to(')')); + if let Some(_) = lookup_parser.find(|&(_, c)| c == ']') { + if let Some((_, ':')) = lookup_parser.next() { + lookup_parser.next_line(); parser = lookup_parser; link = false; } @@ -219,7 +259,7 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp parser.advance_begin(); } _ => { - if let Some(c) = parser.find(|&c| !is_path_char(c)) { + if let Some((_, c)) = parser.find(|&(_, c)| !is_path_char(c)) { parser.put_back(c); } @@ -229,7 +269,6 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp } } - parser.new_line = c == '\n' || (parser.new_line && c.is_whitespace()); } None => break, } diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index f5c1e4768e9..d3b1c037f47 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -68,18 +68,18 @@ fn test_units() { //~^ ERROR: you should put `foo_ℝ` between ticks /// foo_💣 /// foo_❤️ -/// [ßdummy textß][foo_ß] -/// [ℝdummy textℝ][foo_ℝ] -/// [💣dummy tex💣t][foo_💣] -/// [❤️dummy text❤️][foo_❤️] -/// [ßdummy textß](foo_ß) -/// [ℝdummy textℝ](foo_ℝ) -/// [💣dummy tex💣t](foo_💣) -/// [❤️dummy text❤️](foo_❤️) -/// [foo_ß]: dummy text -/// [foo_ℝ]: dummy text -/// [foo_💣]: dummy text -/// [foo_❤️]: dummy text +/// [ßdummy textß][foo_1ß] +/// [ℝdummy textℝ][foo_2ℝ] +/// [💣dummy tex💣t][foo3_💣] +/// [❤️dummy text❤️][foo_4❤️] +/// [ßdummy textß](foo_5ß) +/// [ℝdummy textℝ](foo_6ℝ) +/// [💣dummy tex💣t](fo7o_💣) +/// [❤️dummy text❤️](foo_8❤️) +/// [foo1_ß]: dummy text +/// [foo2_ℝ]: dummy text +/// [foo3_💣]: dummy text +/// [foo4_❤️]: dummy text /// be_sure_we_got_to_the_end_of_it //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn test_unicode() { @@ -146,5 +146,7 @@ fn issue883() { /// `foo_bar /// baz_quz` +/// [foo +/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html) fn multiline() { } -- cgit 1.4.1-3-g733a5 From a892a96eeb6bb0b485dc3d4a436612a77ead5c40 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 27 May 2016 14:24:28 +0200 Subject: Rustup to *1.10.0-nightly (7bddce693 2016-05-27)* --- clippy_lints/src/copies.rs | 5 ++--- clippy_lints/src/format.rs | 2 +- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/matches.rs | 3 +-- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/utils/hir.rs | 14 +++++++------- clippy_lints/src/utils/mod.rs | 2 +- tests/compile-fail/copies.rs | 41 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 57 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 4344ba461dd..3873e82b69a 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -187,7 +187,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned match pat.node { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), - PatKind::TupleStruct(_, Some(ref pats)) => { + PatKind::TupleStruct(_, ref pats, _) => { for pat in pats { bindings_impl(cx, pat, map); } @@ -205,7 +205,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, &pat.node.pat, map); } } - PatKind::Tup(ref fields) => { + PatKind::Tuple(ref fields, _) => { for pat in fields { bindings_impl(cx, pat, map); } @@ -221,7 +221,6 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, pat, map); } } - PatKind::TupleStruct(..) | PatKind::Lit(..) | PatKind::QPath(..) | PatKind::Range(..) | diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 0726fcaeab7..0123dec070f 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -101,7 +101,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { let ExprMatch(_, ref arms, _) = expr.node, arms.len() == 1, arms[0].pats.len() == 1, - let PatKind::Tup(ref pat) = arms[0].pats[0].node, + let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node, pat.len() == 1, let ExprVec(ref exprs) = arms[0].body.node, exprs.len() == 1, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 061b8efaa64..c7f34d338b1 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -280,7 +280,7 @@ impl LateLintPass for LoopsPass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref path, Some(ref pat_args)), + if let (&PatKind::TupleStruct(ref path, ref pat_args, _), &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; if let Some(lhs_constructor) = path.segments.last() { @@ -575,7 +575,7 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex /// Check for the `FOR_KV_MAP` lint. fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let PatKind::Tup(ref pat) = pat.node { + if let PatKind::Tuple(ref pat, _) = pat.node { if pat.len() == 2 { let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index db4ccf2dcdb..ad3b958f585 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -193,14 +193,13 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: (&paths::RESULT, "Ok")]; let path = match arms[1].pats[0].node { - PatKind::TupleStruct(ref path, Some(ref inner)) => { + PatKind::TupleStruct(ref path, ref inner, _) => { // contains any non wildcard patterns? e.g. Err(err) if inner.iter().any(|pat| pat.node != PatKind::Wild) { return; } path.to_string() } - PatKind::TupleStruct(ref path, None) => path.to_string(), PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), _ => return, }; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 2a0d36a80b3..bdaef590de5 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -161,7 +161,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind } } } - PatKind::Tup(ref inner) => { + PatKind::Tuple(ref inner, _) => { if let Some(ref init_tup) = *init { if let ExprTup(ref tup) = init_tup.node { for (i, p) in inner.iter().enumerate() { diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index d408f16a371..6539b835dc7 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -68,7 +68,7 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor { self.labels.remove(&label.node.as_str()); } hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { - self.labels.insert(label.as_str(), expr.span); + self.labels.insert(label.node.as_str(), expr.span); } _ => (), } diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 0f0a7312ee4..92b14b65168 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => { - self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) + self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) } (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && @@ -124,7 +124,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str()) + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) } _ => false, } @@ -142,8 +142,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { match (&left.node, &right.node) { (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), - (&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => { - self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r))) + (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { + self.eq_path(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs } (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) @@ -152,7 +152,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { self.eq_qself(ls, rs) && self.eq_path(lp, rp) } - (&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => over(l, r, |l, r| self.eq_pat(l, r)), + (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { self.eq_expr(ls, rs) && self.eq_expr(le, re) } @@ -374,7 +374,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { - self.hash_name(&i); + self.hash_name(&i.node); } } ExprMatch(ref e, ref arms, ref s) => { @@ -468,7 +468,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(cond); self.hash_block(b); if let Some(l) = l { - self.hash_name(&l); + self.hash_name(&l.node); } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3ff6167620a..c1cbd7ffe93 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -828,7 +828,7 @@ pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { let Some(ref loopexpr) = block.expr, let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, Some(ref somepats)) = innerarms[0].pats[0].node, + let PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, somepats.len() == 1 ], { return Some((&somepats[0], diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index bbdd73dc0c8..6f3076f7775 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -1,4 +1,5 @@ #![feature(plugin, inclusive_range_syntax)] +#![feature(dotdot_in_tuple_patterns)] #![plugin(clippy)] #![allow(dead_code, no_effect, unnecessary_operation)] @@ -129,6 +130,34 @@ fn if_same_then_else() -> Result<&'static str, ()> { if let Some(a) = Some(42) {} } + if true { + if let (1, .., 3) = (1, 2, 3) {} + } + else { //~ERROR this `if` has identical blocks + if let (1, .., 3) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } + else { + if let (.., 3) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } + else { + if let (.., 4) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } + else { + if let (.., 1, 3) = (1, 2, 3) {} + } + if true { if let Some(a) = Some(42) {} } @@ -165,6 +194,18 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => (), } + match (Some(42), Some(42)) { + (Some(a), ..) => bar(a), + (.., Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies + _ => (), + } + + match (1, 2, 3) { + (1, .., 3) => 42, + (.., 3) => 42, //~ERROR this `match` has identical arm bodies + _ => 0, + }; + match (Some(42), Some("")) { (Some(a), None) => bar(a), (None, Some(a)) => bar(a), // bindings have different types -- cgit 1.4.1-3-g733a5 From c1d7babc92b2ffe6f5f527ba11c9f35eb7b3ef59 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 28 May 2016 16:36:44 +0200 Subject: Bump to 0.0.70 --- CHANGELOG.md | 3 ++- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 719e6ee287e..4aaaceb3b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.70 — TBD +## 0.0.70 — 2016-05-28 +* Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)* * [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new`, `RegexBuilder::new` and byte regexes diff --git a/Cargo.toml b/Cargo.toml index 3a45da08f89..f0abb1e90c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.69" +version = "0.0.70" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index da10ca0c0b7..acfb20d9ae6 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.0.69" +version = "0.0.70" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", -- cgit 1.4.1-3-g733a5 From ed7ac0d9b5ff57bda043b088ba81c73e84bc5c83 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 28 May 2016 16:50:34 +0200 Subject: Add a README for `clippy_lints` This avoids the error: > error: failed to read `/tmp/tralala/clippy_lints/README.md` when publishing. --- clippy_lints/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 clippy_lints/README.md diff --git a/clippy_lints/README.md b/clippy_lints/README.md new file mode 100644 index 00000000000..5179690799c --- /dev/null +++ b/clippy_lints/README.md @@ -0,0 +1,3 @@ +This crate contains Clippy lints. For the main crate, check +[*cargo.io*](https://crates.io/crates/clippy) or +[GitHub](https://github.com/Manishearth/rust-clippy). -- cgit 1.4.1-3-g733a5 From 8fbbabb221bddff82c5240d91ab6e2dd813f1e6c Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Sun, 29 May 2016 11:57:56 +0200 Subject: ran update_lints.py I forgot that in the previous commit. Shame on me. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3d8dbf7c1d7..672b9d7ef94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.69", path = "clippy_lints" } +clippy_lints = { version = "0.0.70", path = "clippy_lints" } # end automatic update [dev-dependencies] -- cgit 1.4.1-3-g733a5 From 42879bcdcb4f410f5d8ae2c78cf6c052d62c819a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 30 Mar 2016 19:53:43 +0200 Subject: Add a `USELESS_LET_IF_SEQ` lint --- CHANGELOG.md | 4 + README.md | 3 +- clippy_lints/src/let_if_seq.rs | 176 +++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 + tests/compile-fail/let_if_seq.rs | 79 ++++++++++++++++++ 5 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/let_if_seq.rs create mode 100644 tests/compile-fail/let_if_seq.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aaaceb3b24..b59249b257c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.71 — TBD +* New lint: [`useless_let_if_seq`] + ## 0.0.70 — 2016-05-28 * Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)* * [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new`, @@ -240,6 +243,7 @@ All notable changes to this project will be documented in this file. [`use_debug`]: https://github.com/Manishearth/rust-clippy/wiki#use_debug [`used_underscore_binding`]: https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding [`useless_format`]: https://github.com/Manishearth/rust-clippy/wiki#useless_format +[`useless_let_if_seq`]: https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq [`useless_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#useless_transmute [`useless_vec`]: https://github.com/Manishearth/rust-clippy/wiki#useless_vec [`while_let_loop`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_loop diff --git a/README.md b/README.md index c289116809e..3b5b6768c23 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 151 lints included in this crate: +There are 152 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -164,6 +164,7 @@ name [use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore [useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` +[useless_let_if_seq](https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq) | warn | Checks for unidiomatic `let mut` declaration followed by initialization in `if` [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs new file mode 100644 index 00000000000..29551a413e2 --- /dev/null +++ b/clippy_lints/src/let_if_seq.rs @@ -0,0 +1,176 @@ +use rustc::lint::*; +use rustc::hir; +use syntax::codemap; +use utils::{snippet, span_lint_and_then}; + +/// **What it does:** This lint checks for variable declarations immediately followed by a +/// conditional affectation. +/// +/// **Why is this bad?** This is not idiomatic Rust. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let foo; +/// +/// if bar() { +/// foo = 42; +/// } else { +/// foo = 0; +/// } +/// +/// let mut baz = None; +/// +/// if bar() { +/// baz = Some(42); +/// } +/// ``` +/// +/// should be written +/// +/// ```rust,ignore +/// let foo = if bar() { +/// 42; +/// } else { +/// 0; +/// }; +/// +/// let baz = if bar() { +/// Some(42); +/// } else { +/// None +/// }; +/// ``` +declare_lint! { + pub USELESS_LET_IF_SEQ, + Warn, + "Checks for unidiomatic `let mut` declaration followed by initialization in `if`" +} + +#[derive(Copy,Clone)] +pub struct LetIfSeq; + +impl LintPass for LetIfSeq { + fn get_lints(&self) -> LintArray { + lint_array!(USELESS_LET_IF_SEQ) + } +} + +impl LateLintPass for LetIfSeq { + fn check_block(&mut self, cx: &LateContext, block: &hir::Block) { + let mut it = block.stmts.iter().peekable(); + while let Some(ref stmt) = it.next() { + if_let_chain! {[ + let Some(expr) = it.peek(), + let hir::StmtDecl(ref decl, _) = stmt.node, + let hir::DeclLocal(ref decl) = decl.node, + let hir::PatKind::Ident(mode, ref name, None) = decl.pat.node, + let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id), + let hir::StmtExpr(ref if_, _) = expr.node, + let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, + let Some(value) = check_assign(cx, def.def_id(), then), + ], { + let span = codemap::mk_sp(stmt.span.lo, if_.span.hi); + + let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { + if let hir::ExprBlock(ref else_) = else_.node { + if let Some(default) = check_assign(cx, def.def_id(), else_) { + (else_.stmts.len() > 1, default) + } else if let Some(ref default) = decl.init { + (true, &**default) + } else { + continue; + } + } else { + continue; + } + } else if let Some(ref default) = decl.init { + (false, &**default) + } else { + continue; + }; + + let mutability = match mode { + hir::BindByRef(hir::MutMutable) | hir::BindByValue(hir::MutMutable) => "<mut> ", + _ => "", + }; + + // FIXME: this should not suggest `mut` if we can detect that the variable is not + // use mutably after the `if` + + let sug = format!( + "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", + mut=mutability, + name=name.node, + cond=snippet(cx, cond.span, "_"), + then=if then.stmts.len() > 1 { " ..;" } else { "" }, + else=if default_multi_stmts { " ..;" } else { "" }, + value=snippet(cx, value.span, "<value>"), + default=snippet(cx, default.span, "<default>"), + ); + span_lint_and_then(cx, + USELESS_LET_IF_SEQ, + span, + "`if _ { .. } else { .. }` is an expression", + |db| { + db.span_suggestion(span, + "it is more idiomatic to write", + sug); + if !mutability.is_empty() { + db.note("you might not need `mut` at all"); + } + }); + }} + } + } +} + +struct UsedVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + id: hir::def_id::DefId, + used: bool, +} + +impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'v hir::Expr) { + if_let_chain! {[ + let hir::ExprPath(None, _) = expr.node, + let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id), + self.id == def.def_id(), + ], { + self.used = true; + return; + }} + hir::intravisit::walk_expr(self, expr); + } +} + +fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> { + if_let_chain! {[ + let Some(expr) = block.stmts.iter().last(), + let hir::StmtSemi(ref expr, _) = expr.node, + let hir::ExprAssign(ref var, ref value) = expr.node, + let hir::ExprPath(None, _) = var.node, + let Some(def) = cx.tcx.def_map.borrow().get(&var.id), + decl == def.def_id(), + ], { + let mut v = UsedVisitor { + cx: cx, + id: decl, + used: false, + }; + + for s in block.stmts.iter().take(block.stmts.len()-1) { + hir::intravisit::walk_stmt(&mut v, s); + } + + return if v.used { + None + } else { + Some(value) + }; + }} + + None +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f6db7a3a188..4a5c3a87c8c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -80,6 +80,7 @@ pub mod identity_op; pub mod if_not_else; pub mod items_after_statements; pub mod len_zero; +pub mod let_if_seq; pub mod lifetimes; pub mod loops; pub mod map_clone; @@ -246,6 +247,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box mem_forget::MemForget); reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); reg.register_late_lint_pass(box assign_ops::AssignOps); + reg.register_late_lint_pass(box let_if_seq::LetIfSeq); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -318,6 +320,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_op::IDENTITY_OP, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, + let_if_seq::USELESS_LET_IF_SEQ, lifetimes::NEEDLESS_LIFETIMES, lifetimes::UNUSED_LIFETIMES, loops::EMPTY_LOOP, diff --git a/tests/compile-fail/let_if_seq.rs b/tests/compile-fail/let_if_seq.rs new file mode 100644 index 00000000000..011848e95dd --- /dev/null +++ b/tests/compile-fail/let_if_seq.rs @@ -0,0 +1,79 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused_variables, unused_assignments, similar_names, blacklisted_name)] +#![deny(useless_let_if_seq)] + +fn f() -> bool { true } + +fn early_return() -> u8 { + // FIXME: we could extend the lint to include such cases: + let foo; + + if f() { + return 42; + } else { + foo = 0; + } + + foo +} + +fn main() { + early_return(); + + let mut foo = 0; + //~^ ERROR `if _ { .. } else { .. }` is an expression + //~| HELP more idiomatic + //~| SUGGESTION let <mut> foo = if f() { 42 } else { 0 }; + if f() { + foo = 42; + } + + let mut bar = 0; + //~^ ERROR `if _ { .. } else { .. }` is an expression + //~| HELP more idiomatic + //~| SUGGESTION let <mut> bar = if f() { ..; 42 } else { ..; 0 }; + if f() { + f(); + bar = 42; + } + else { + f(); + } + + let quz; + //~^ ERROR `if _ { .. } else { .. }` is an expression + //~| HELP more idiomatic + //~| SUGGESTION let quz = if f() { 42 } else { 0 }; + + if f() { + quz = 42; + } else { + quz = 0; + } + + // `toto` is used several times + let mut toto; + + if f() { + toto = 42; + } else { + for i in &[1, 2] { + toto = *i; + } + + toto = 2; + } + + // baz needs to be mut + let mut baz = 0; + //~^ ERROR `if _ { .. } else { .. }` is an expression + //~| HELP more idiomatic + //~| SUGGESTION let <mut> baz = if f() { 42 } else { 0 }; + if f() { + baz = 42; + } + + baz = 1337; +} -- cgit 1.4.1-3-g733a5 From 0818e70497f9f18075dbc5c5d56f62fa5025f1d1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 27 May 2016 15:31:19 +0200 Subject: don't require `cargo clippy` to pass a `--lib` or `--bin x` argument --- Cargo.toml | 2 +- src/cargo.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 42 +++++++++++++++++++++++++++++------------- 3 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 src/cargo.rs diff --git a/Cargo.toml b/Cargo.toml index 672b9d7ef94..828857701d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,12 +32,12 @@ quine-mc_cluskey = "0.2.2" # begin automatic update clippy_lints = { version = "0.0.70", path = "clippy_lints" } # end automatic update +rustc-serialize = "0.3" [dev-dependencies] compiletest_rs = "0.1.0" lazy_static = "0.1.15" regex = "0.1.56" -rustc-serialize = "0.3" [features] debugging = [] diff --git a/src/cargo.rs b/src/cargo.rs new file mode 100644 index 00000000000..188d4d38e8d --- /dev/null +++ b/src/cargo.rs @@ -0,0 +1,48 @@ +use std::collections::HashMap; + +#[derive(RustcDecodable, Debug)] +pub struct Metadata { + pub packages: Vec<Package>, + resolve: Option<()>, + pub version: usize, +} + +#[derive(RustcDecodable, Debug)] +pub struct Package { + name: String, + version: String, + id: String, + source: Option<()>, + dependencies: Vec<Dependency>, + pub targets: Vec<Target>, + features: HashMap<String, Vec<String>>, + manifest_path: String, +} + +#[derive(RustcDecodable, Debug)] +pub struct Dependency { + name: String, + source: Option<String>, + req: String, + kind: Option<String>, + optional: bool, + uses_default_features: bool, + features: Vec<HashMap<String, String>>, + target: Option<()>, +} + +#[allow(non_camel_case_types)] +#[derive(RustcDecodable, Debug)] +pub enum Kind { + dylib, + test, + bin, + lib, +} + +#[derive(RustcDecodable, Debug)] +pub struct Target { + pub name: String, + pub kind: Vec<Kind>, + src_path: String, +} diff --git a/src/main.rs b/src/main.rs index 970222e1076..51683060be2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ extern crate rustc; extern crate syntax; extern crate rustc_plugin; extern crate clippy_lints; +extern crate rustc_serialize; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; use rustc::session::{config, Session}; @@ -16,6 +17,8 @@ use syntax::diagnostics; use std::path::PathBuf; use std::process::Command; +mod cargo; + struct ClippyCompilerCalls(RustcDefaultCalls); impl std::default::Default for ClippyCompilerCalls { @@ -118,16 +121,19 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let args = wrap_args(std::env::args().skip(2), dep_path, sys_root); - let path = std::env::current_exe().expect("current executable path invalid"); - let exit_status = std::process::Command::new("cargo") - .args(&args) - .env("RUSTC", path) - .spawn().expect("could not run cargo") - .wait().expect("failed to wait for cargo?"); - - if let Some(code) = exit_status.code() { - std::process::exit(code); + let output = std::process::Command::new("cargo").args(&["metadata", "--no-deps"]).output().expect("could not run `cargo metadata`"); + let stdout = std::str::from_utf8(&output.stdout).expect("`cargo metadata` output is not utf8"); + let mut metadata: cargo::Metadata = rustc_serialize::json::decode(stdout).expect("`cargo metadata` output is not valid json"); + assert_eq!(metadata.version, 1); + for target in metadata.packages.remove(0).targets { + let args = std::env::args().skip(2); + assert_eq!(target.kind.len(), 1); + match target.kind[0] { + cargo::Kind::dylib => process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root), + cargo::Kind::bin => process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root), + // don't process tests + _ => {}, + } } } else { let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { @@ -145,7 +151,7 @@ pub fn main() { } } -fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String> +fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) where P: AsRef<Path>, I: Iterator<Item=String> { let mut args = vec!["rustc".to_owned()]; @@ -161,7 +167,17 @@ fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String> args.push("-L".to_owned()); args.push(dep_path.as_ref().to_string_lossy().into_owned()); args.push(String::from("--sysroot")); - args.push(sysroot); + args.push(sysroot.to_owned()); args.push("-Zno-trans".to_owned()); - args + + let path = std::env::current_exe().expect("current executable path invalid"); + let exit_status = std::process::Command::new("cargo") + .args(&args) + .env("RUSTC", path) + .spawn().expect("could not run cargo") + .wait().expect("failed to wait for cargo?"); + + if let Some(code) = exit_status.code() { + std::process::exit(code); + } } -- cgit 1.4.1-3-g733a5 From e6a089efa952b94af35050e782e7e809f5dca3dc Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 27 May 2016 15:42:33 +0200 Subject: dogfood --- src/main.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 51683060be2..05096e80548 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] +#![feature(slice_patterns)] extern crate rustc_driver; extern crate getopts; @@ -128,10 +129,11 @@ pub fn main() { for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); assert_eq!(target.kind.len(), 1); - match target.kind[0] { - cargo::Kind::dylib => process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root), - cargo::Kind::bin => process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root), - // don't process tests + match &target.kind[..] { + [cargo::Kind::lib] | + [cargo::Kind::dylib] => process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root), + [cargo::Kind::bin] => process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root), + // don't process tests and other stuff _ => {}, } } -- cgit 1.4.1-3-g733a5 From 3ad0a49632b6c06c259ba6e09e55fdda61d5f6d5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 27 May 2016 15:42:45 +0200 Subject: travis should check `clippy-lints` --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b204bb0b2f5..f78f8f43d0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,8 @@ script: - cargo build --features debugging - cargo test --features debugging - SYSROOT=~/rust cargo install - - cargo clippy --lib -- -D clippy + - cargo clippy -- -D clippy + - cd clippy_lints && cargo clippy -- -D clippy after_success: # only test regex_macros if it compiles -- cgit 1.4.1-3-g733a5 From 80e81d351d27e7464ea416e13eb06b30fa31e452 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 30 May 2016 12:47:04 +0200 Subject: add version check to the unit tests --- clippy_lints/Cargo.toml | 1 + clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/utils/cargo.rs | 75 +++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 1 + src/cargo.rs | 48 -------------------------- src/main.rs | 6 ++-- tests/versioncheck.rs | 16 +++++++++ 7 files changed, 97 insertions(+), 52 deletions(-) create mode 100644 clippy_lints/src/utils/cargo.rs delete mode 100644 src/cargo.rs create mode 100644 tests/versioncheck.rs diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index aa994cd7259..c309b7a63e2 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -21,6 +21,7 @@ semver = "0.2.1" toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" +rustc-serialize = "0.3" [features] debugging = [] diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4a5c3a87c8c..944825e2bdc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -36,6 +36,8 @@ extern crate regex_syntax; // for finding minimal boolean expressions extern crate quine_mc_cluskey; +extern crate rustc_serialize; + extern crate rustc_plugin; extern crate rustc_const_eval; extern crate rustc_const_math; diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs new file mode 100644 index 00000000000..c6004864bf0 --- /dev/null +++ b/clippy_lints/src/utils/cargo.rs @@ -0,0 +1,75 @@ +use std::collections::HashMap; +use std::process::Command; +use std::str::{from_utf8, Utf8Error}; +use std::io; +use rustc_serialize::json; + +#[derive(RustcDecodable, Debug)] +pub struct Metadata { + pub packages: Vec<Package>, + resolve: Option<()>, + pub version: usize, +} + +#[derive(RustcDecodable, Debug)] +pub struct Package { + pub name: String, + pub version: String, + id: String, + source: Option<()>, + pub dependencies: Vec<Dependency>, + pub targets: Vec<Target>, + features: HashMap<String, Vec<String>>, + manifest_path: String, +} + +#[derive(RustcDecodable, Debug)] +pub struct Dependency { + pub name: String, + source: Option<String>, + pub req: String, + kind: Option<String>, + optional: bool, + uses_default_features: bool, + features: Vec<HashMap<String, String>>, + target: Option<()>, +} + +#[allow(non_camel_case_types)] +#[derive(RustcDecodable, Debug)] +pub enum Kind { + dylib, + test, + bin, + lib, +} + +#[derive(RustcDecodable, Debug)] +pub struct Target { + pub name: String, + pub kind: Vec<Kind>, + src_path: String, +} + +#[derive(Debug)] +pub enum Error { + Io(io::Error), + Utf8(Utf8Error), + Json(json::DecoderError), +} + +impl From<io::Error> for Error { + fn from(err: io::Error) -> Self { Error::Io(err) } +} +impl From<Utf8Error> for Error { + fn from(err: Utf8Error) -> Self { Error::Utf8(err) } +} +impl From<json::DecoderError> for Error { + fn from(err: json::DecoderError) -> Self { Error::Json(err) } +} + +pub fn metadata() -> Result<Metadata, Error> { + let output = Command::new("cargo").args(&["metadata", "--no-deps"]).output()?; + let stdout = from_utf8(&output.stdout)?; + Ok(json::decode(stdout)?) +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c1cbd7ffe93..986462b3723 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -23,6 +23,7 @@ pub mod conf; mod hir; pub mod paths; pub use self::hir::{SpanlessEq, SpanlessHash}; +pub mod cargo; pub type MethodArgs = HirVec<P<Expr>>; diff --git a/src/cargo.rs b/src/cargo.rs deleted file mode 100644 index 188d4d38e8d..00000000000 --- a/src/cargo.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::collections::HashMap; - -#[derive(RustcDecodable, Debug)] -pub struct Metadata { - pub packages: Vec<Package>, - resolve: Option<()>, - pub version: usize, -} - -#[derive(RustcDecodable, Debug)] -pub struct Package { - name: String, - version: String, - id: String, - source: Option<()>, - dependencies: Vec<Dependency>, - pub targets: Vec<Target>, - features: HashMap<String, Vec<String>>, - manifest_path: String, -} - -#[derive(RustcDecodable, Debug)] -pub struct Dependency { - name: String, - source: Option<String>, - req: String, - kind: Option<String>, - optional: bool, - uses_default_features: bool, - features: Vec<HashMap<String, String>>, - target: Option<()>, -} - -#[allow(non_camel_case_types)] -#[derive(RustcDecodable, Debug)] -pub enum Kind { - dylib, - test, - bin, - lib, -} - -#[derive(RustcDecodable, Debug)] -pub struct Target { - pub name: String, - pub kind: Vec<Kind>, - src_path: String, -} diff --git a/src/main.rs b/src/main.rs index 05096e80548..3ad32a54058 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ use syntax::diagnostics; use std::path::PathBuf; use std::process::Command; -mod cargo; +use clippy_lints::utils::cargo; struct ClippyCompilerCalls(RustcDefaultCalls); @@ -122,9 +122,7 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let output = std::process::Command::new("cargo").args(&["metadata", "--no-deps"]).output().expect("could not run `cargo metadata`"); - let stdout = std::str::from_utf8(&output.stdout).expect("`cargo metadata` output is not utf8"); - let mut metadata: cargo::Metadata = rustc_serialize::json::decode(stdout).expect("`cargo metadata` output is not valid json"); + let mut metadata = cargo::metadata().expect("could not obtain cargo metadata"); assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs new file mode 100644 index 00000000000..b2a2f416a8f --- /dev/null +++ b/tests/versioncheck.rs @@ -0,0 +1,16 @@ +extern crate clippy_lints; +use clippy_lints::utils::cargo; + +#[test] +fn check_that_clippy_lints_has_the_same_version_as_clippy() { + let clippy_meta = cargo::metadata().expect("could not obtain cargo metadata"); + std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); + let clippy_lints_meta = cargo::metadata().expect("could not obtain cargo metadata"); + assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); + for package in &clippy_meta.packages[0].dependencies { + if package.name == "clippy_lints" { + assert_eq!(clippy_lints_meta.packages[0].version, package.req[1..]); + return; + } + } +} -- cgit 1.4.1-3-g733a5 From 41e71b4f4828767c71024ba97038ce4488e8cc77 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 31 May 2016 14:37:25 +0200 Subject: leave the clippy_lints directory after testing --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f78f8f43d0c..c1b91fd75fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ script: - cargo test --features debugging - SYSROOT=~/rust cargo install - cargo clippy -- -D clippy - - cd clippy_lints && cargo clippy -- -D clippy + - cd clippy_lints && cargo clippy -- -D clippy && cd .. after_success: # only test regex_macros if it compiles -- cgit 1.4.1-3-g733a5 From 6aa37e57a2423050cb3442f3a0df45dfab8b6224 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 19:17:31 +0200 Subject: s/PatKind::Ident/PatKind::Binding/g --- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/loops.rs | 6 +++--- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/misc.rs | 6 +++--- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/utils/hir.rs | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 5cb84f62651..a2dbdf34a2f 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -34,7 +34,7 @@ impl LintPass for BlackListedName { impl LateLintPass for BlackListedName { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatKind::Ident(_, ref ident, _) = pat.node { + if let PatKind::Binding(_, ref ident, _) = pat.node { if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) { span_lint(cx, BLACKLISTED_NAME, diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 3873e82b69a..3022ffe730f 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -192,7 +192,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned bindings_impl(cx, pat, map); } } - PatKind::Ident(_, ref ident, ref as_pat) => { + PatKind::Binding(_, ref ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { v.insert(cx.tcx.pat_ty(pat)); } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index f73b6cfed2d..99b40a0231b 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -70,7 +70,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { _ => (), } for (ref a1, ref a2) in decl.inputs.iter().zip(args) { - if let PatKind::Ident(_, ident, _) = a1.pat.node { + if let PatKind::Binding(_, ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? if let ExprPath(None, ref p) = a2.node { if p.segments.len() != 1 { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index c7f34d338b1..3d3c9ab47a4 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -330,7 +330,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(arg) { // the var must be a single name - if let PatKind::Ident(_, ref ident, _) = pat.node { + if let PatKind::Binding(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, var: ident.node, @@ -613,7 +613,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { PatKind::Wild => true, - PatKind::Ident(_, ident, None) if ident.node.as_str().starts_with('_') => { + PatKind::Binding(_, ident, None) if ident.node.as_str().starts_with('_') => { let mut visitor = UsedVisitor { var: ident.node, used: false, @@ -884,7 +884,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { // Look for declarations of the variable if let DeclLocal(ref local) = decl.node { if local.pat.id == self.var_id { - if let PatKind::Ident(_, ref ident, _) = local.pat.node { + if let PatKind::Binding(_, ref ident, _) = local.pat.node { self.name = Some(ident.node); self.state = if let Some(ref init) = local.init { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4ad232759cf..bd81cb2316b 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -108,7 +108,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s fn get_arg_name(pat: &Pat) -> Option<ast::Name> { match pat.node { - PatKind::Ident(_, name, None) => Some(name.node), + PatKind::Binding(_, name, None) => Some(name.node), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index ad3b958f585..4d1d9ac3ffa 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -200,7 +200,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: } path.to_string() } - PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), + PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), _ => return, }; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 3ab7823e50d..5f113cf47ce 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -45,7 +45,7 @@ impl LateLintPass for TopLevelRefPass { return; } for ref arg in &decl.inputs { - if let PatKind::Ident(BindByRef(_), _, _) = arg.pat.node { + if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node { span_lint(cx, TOPLEVEL_REF_ARG, arg.pat.span, @@ -58,7 +58,7 @@ impl LateLintPass for TopLevelRefPass { [ let StmtDecl(ref d, _) = s.node, let DeclLocal(ref l) = d.node, - let PatKind::Ident(BindByRef(_), i, None) = l.pat.node, + let PatKind::Binding(BindByRef(_), i, None) = l.pat.node, let Some(ref init) = l.init ], { let tyopt = if let Some(ref ty) = l.ty { @@ -346,7 +346,7 @@ impl LintPass for PatternPass { impl LateLintPass for PatternPass { fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatKind::Ident(_, ref ident, Some(ref right)) = pat.node { + if let PatKind::Binding(_, ref ident, Some(ref right)) = pat.node { if right.node == PatKind::Wild { span_lint(cx, REDUNDANT_PATTERN, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index bdaef590de5..0954d92cf9a 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -65,7 +65,7 @@ impl LateLintPass for ShadowPass { fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { - if let PatKind::Ident(_, ident, _) = arg.pat.node { + if let PatKind::Binding(_, ident, _) = arg.pat.node { bindings.push((ident.node.unhygienize(), ident.span)) } } @@ -119,7 +119,7 @@ fn is_binding(cx: &LateContext, pat: &Pat) -> bool { fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { // TODO: match more stuff / destructuring match pat.node { - PatKind::Ident(_, ref ident, ref inner) => { + PatKind::Binding(_, ref ident, ref inner) => { let name = ident.node.unhygienize(); if is_binding(cx, pat) { let mut new_binding = true; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index c5572181395..6dc9dda37ec 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -63,7 +63,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { let StmtDecl(ref tmp, _) = w[0].node, let DeclLocal(ref tmp) = tmp.node, let Some(ref tmp_init) = tmp.init, - let PatKind::Ident(_, ref tmp_name, None) = tmp.pat.node, + let PatKind::Binding(_, ref tmp_name, None) = tmp.pat.node, // foo() = bar(); let StmtSemi(ref first, _) = w[1].node, diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 92b14b65168..95028376dca 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { self.eq_path(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs } - (&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => { + (&PatKind::Binding(ref lb, ref li, ref lp), &PatKind::Binding(ref rb, ref ri, ref rp)) => { lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), -- cgit 1.4.1-3-g733a5 From ef5db37d9d0d75587400dec4dee6e6c4b09024ac Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 20:14:32 +0200 Subject: additional error in copies test annotated --- tests/compile-fail/copies.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 6f3076f7775..0f930657bf7 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -173,7 +173,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match Some(42) { Some(_) => 24, - None => 24, + None => 24, //~ERROR this `match` has identical arm bodies }; let _ = match Some(42) { -- cgit 1.4.1-3-g733a5 From 46491443ff5b6e6544b86ffa1755a792f825e0d3 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 20:14:59 +0200 Subject: dogfood error in consts fixed --- clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 96956d1793b..b4c8521a0a9 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -345,8 +345,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int), (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), - (BiAnd, Constant::Bool(true), Some(r)) => Some(r), (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), + (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), -- cgit 1.4.1-3-g733a5 From 1b112f96b8efe4ca0a0cf062fddc973c9845f810 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 21:50:13 +0200 Subject: added mcarton's test suggestion --- tests/compile-fail/copies.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 0f930657bf7..f4e74eed4a4 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -176,6 +176,11 @@ fn if_same_then_else() -> Result<&'static str, ()> { None => 24, //~ERROR this `match` has identical arm bodies }; + let _ = match Some(42) { + Some(foo) => 24, + None => 24, + }; + let _ = match Some(42) { Some(42) => 24, Some(a) => 24, // bindings are different -- cgit 1.4.1-3-g733a5 From e18dc948c76793251524cbb439a37cb33742daad Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 22:07:03 +0200 Subject: another one. Somehow I failed to correctly commit --- clippy_lints/src/let_if_seq.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 29551a413e2..1eb2f756cbf 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -65,7 +65,7 @@ impl LateLintPass for LetIfSeq { let Some(expr) = it.peek(), let hir::StmtDecl(ref decl, _) = stmt.node, let hir::DeclLocal(ref decl) = decl.node, - let hir::PatKind::Ident(mode, ref name, None) = decl.pat.node, + let hir::PatKind::Binding(mode, ref name, None) = decl.pat.node, let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id), let hir::StmtExpr(ref if_, _) = expr.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, -- cgit 1.4.1-3-g733a5 From 2811dd64ec926a923852efe380886177b2221825 Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Tue, 31 May 2016 22:01:56 +0200 Subject: added missing PatKind::Path + tests --- clippy_lints/src/matches.rs | 1 + clippy_lints/src/utils/hir.rs | 1 + tests/compile-fail/matches.rs | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 4d1d9ac3ffa..46bd251016b 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -201,6 +201,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: path.to_string() } PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), + PatKind::Path(ref path) => path.to_string(), _ => return, }; diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 95028376dca..e9c4023e226 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -148,6 +148,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::Binding(ref lb, ref li, ref lp), &PatKind::Binding(ref rb, ref ri, ref rp)) => { lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } + (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_path(l, r), (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { self.eq_qself(ls, rs) && self.eq_path(lp, rp) diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 3444e49ec51..affa7e4e86e 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -216,6 +216,12 @@ fn overlapping() { 11 ... 50 => println!("0 ... 10"), _ => (), } + + if let None = Some(42) { + // nothing + } else if let None = Some(42) { + // another nothing :-) + } } fn main() { -- cgit 1.4.1-3-g733a5 From 5c51a2452d0a443f97aebc089cdf16bbbd4fb1ba Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 31 May 2016 23:32:04 +0200 Subject: Bump to 0.0.71 Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)* --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b59249b257c..7a21dbea2c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.71 — TBD +## 0.0.71 — 2016-05-31 +* Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)* * New lint: [`useless_let_if_seq`] ## 0.0.70 — 2016-05-28 diff --git a/Cargo.toml b/Cargo.toml index 828857701d5..ec38ce91623 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.70" +version = "0.0.71" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.70", path = "clippy_lints" } +clippy_lints = { version = "0.0.71", path = "clippy_lints" } # end automatic update rustc-serialize = "0.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index c309b7a63e2..db6ee124505 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.70" +version = "0.0.71" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From efeba8eec30c5f051b66580da4827bd50d357b4d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 1 Jun 2016 00:04:47 +0200 Subject: Fix CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a21dbea2c2..53cebf4f99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. ## 0.0.71 — 2016-05-31 -* Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)* +* Rustup to *rustc 1.11.0-nightly (a967611d8 2016-05-30)* * New lint: [`useless_let_if_seq`] ## 0.0.70 — 2016-05-28 -- cgit 1.4.1-3-g733a5 From 49982036fc9aeb02da254889ac7785909fdb805a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Wed, 1 Jun 2016 23:35:14 +0200 Subject: only lint `new_without_default` for public items This fixes #953. --- clippy_lints/src/new_without_default.rs | 3 ++- tests/compile-fail/new_without_default.rs | 34 ++++++++++++++++++------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 08d517014ee..15bb782452e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -96,7 +96,8 @@ impl LateLintPass for NewWithoutDefault { } if let FnKind::Method(name, _, _, _) = kind { - if decl.inputs.is_empty() && name.as_str() == "new" { + if decl.inputs.is_empty() && name.as_str() == "new" && + cx.access_levels.is_reachable(id) { let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( cx.tcx.map.get_parent(id))).ty; if_let_chain!{[ diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index 17f2a8d7b41..042fab840c1 100644 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -4,35 +4,35 @@ #![allow(dead_code)] #![deny(new_without_default, new_without_default_derive)] -struct Foo; +pub struct Foo; impl Foo { - fn new() -> Foo { Foo } //~ERROR: you should consider deriving a `Default` implementation for `Foo` + pub fn new() -> Foo { Foo } //~ERROR: you should consider deriving a `Default` implementation for `Foo` } -struct Bar; +pub struct Bar; impl Bar { - fn new() -> Self { Bar } //~ERROR: you should consider deriving a `Default` implementation for `Bar` + pub fn new() -> Self { Bar } //~ERROR: you should consider deriving a `Default` implementation for `Bar` } -struct Ok; +pub struct Ok; impl Ok { - fn new() -> Self { Ok } + pub fn new() -> Self { Ok } } impl Default for Ok { fn default() -> Self { Ok } } -struct Params; +pub struct Params; impl Params { - fn new(_: u32) -> Self { Params } + pub fn new(_: u32) -> Self { Params } } -struct GenericsOk<T> { +pub struct GenericsOk<T> { bar: T, } @@ -41,10 +41,10 @@ impl<U> Default for GenericsOk<U> { } impl<'c, V> GenericsOk<V> { - fn new() -> GenericsOk<V> { unimplemented!() } + pub fn new() -> GenericsOk<V> { unimplemented!() } } -struct LtOk<'a> { +pub struct LtOk<'a> { foo: &'a bool, } @@ -53,15 +53,21 @@ impl<'b> Default for LtOk<'b> { } impl<'c> LtOk<'c> { - fn new() -> LtOk<'c> { unimplemented!() } + pub fn new() -> LtOk<'c> { unimplemented!() } } -struct LtKo<'a> { +pub struct LtKo<'a> { foo: &'a bool, } impl<'c> LtKo<'c> { - fn new() -> LtKo<'c> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for + pub fn new() -> LtKo<'c> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for +} + +struct Private; + +impl Private { + fn new() -> Private { unimplemented!() } // We don't lint private items } fn main() {} -- cgit 1.4.1-3-g733a5 From 7bb8ba46318667da94b1533d371aa28025871a59 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 2 Jun 2016 17:29:25 +0200 Subject: process more kinds of metadata --- clippy_lints/src/utils/cargo.rs | 15 +++------------ src/main.rs | 12 +++++------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index c6004864bf0..c51cfc7304b 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -16,7 +16,7 @@ pub struct Package { pub name: String, pub version: String, id: String, - source: Option<()>, + source: Option<String>, pub dependencies: Vec<Dependency>, pub targets: Vec<Target>, features: HashMap<String, Vec<String>>, @@ -31,23 +31,14 @@ pub struct Dependency { kind: Option<String>, optional: bool, uses_default_features: bool, - features: Vec<HashMap<String, String>>, + features: Vec<String>, target: Option<()>, } -#[allow(non_camel_case_types)] -#[derive(RustcDecodable, Debug)] -pub enum Kind { - dylib, - test, - bin, - lib, -} - #[derive(RustcDecodable, Debug)] pub struct Target { pub name: String, - pub kind: Vec<Kind>, + pub kind: Vec<String>, src_path: String, } diff --git a/src/main.rs b/src/main.rs index 3ad32a54058..8c9220c7fc2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,13 +126,11 @@ pub fn main() { assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); - assert_eq!(target.kind.len(), 1); - match &target.kind[..] { - [cargo::Kind::lib] | - [cargo::Kind::dylib] => process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root), - [cargo::Kind::bin] => process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root), - // don't process tests and other stuff - _ => {}, + assert!(!target.kind.is_empty()); + if target.kind.len() > 1 || target.kind[0].ends_with("lib") { + process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root); + } else if target.kind[0] == "bin" { + process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root); } } } else { -- cgit 1.4.1-3-g733a5 From 078cc68c527faa35c52a88aca22e46ee7402f356 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 2 Jun 2016 17:39:28 +0200 Subject: no indexing --- src/main.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8c9220c7fc2..db0c6613f3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,11 +126,14 @@ pub fn main() { assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); - assert!(!target.kind.is_empty()); - if target.kind.len() > 1 || target.kind[0].ends_with("lib") { - process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root); - } else if target.kind[0] == "bin" { - process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root); + if let Some(first) = target.kind.get(0) { + if target.kind.len() > 1 || first.ends_with("lib") { + process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root); + } else if first == "bin" { + process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root); + } + } else { + panic!("badly formatted cargo metadata: target::kind is an empty array"); } } } else { -- cgit 1.4.1-3-g733a5 From bf4ce86e9e16763fab03cd6322d003fb9792ea2f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Fri, 3 Jun 2016 20:15:07 +0530 Subject: Make new_without_default ignore const fns; fixes #977 --- clippy_lints/src/new_without_default.rs | 6 +++++- tests/compile-fail/new_without_default.rs | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 15bb782452e..dfaefb39ba0 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -95,7 +95,11 @@ impl LateLintPass for NewWithoutDefault { return; } - if let FnKind::Method(name, _, _, _) = kind { + if let FnKind::Method(name, ref sig, _, _) = kind { + if sig.constness == hir::Constness::Const { + // can't be implemented by default + return; + } if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index 042fab840c1..e3a8024dde1 100644 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -1,4 +1,4 @@ -#![feature(plugin)] +#![feature(plugin, const_fn)] #![plugin(clippy)] #![allow(dead_code)] @@ -70,4 +70,9 @@ impl Private { fn new() -> Private { unimplemented!() } // We don't lint private items } +struct Const; + +impl Const { + pub const fn new() -> Const { Const } // const fns can't be implemented via Default +} fn main() {} -- cgit 1.4.1-3-g733a5 From 5c2a10d703ea65741375ba6c27b64d9596b380fc Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 3 Jun 2016 19:35:39 +0200 Subject: Correctly check for variable use in `useless_let_if_seq` --- clippy_lints/src/let_if_seq.rs | 15 ++++++++++----- tests/compile-fail/let_if_seq.rs | 9 +++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 1eb2f756cbf..09172014c8c 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -69,6 +69,11 @@ impl LateLintPass for LetIfSeq { let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id), let hir::StmtExpr(ref if_, _) = expr.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, + { + let mut v = UsedVisitor { cx: cx, id: def.def_id(), used: false }; + hir::intravisit::walk_expr(&mut v, cond); + !v.used + }, let Some(value) = check_assign(cx, def.def_id(), then), ], { let span = codemap::mk_sp(stmt.span.lo, if_.span.hi); @@ -163,13 +168,13 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir:: for s in block.stmts.iter().take(block.stmts.len()-1) { hir::intravisit::walk_stmt(&mut v, s); + + if v.used { + return None; + } } - return if v.used { - None - } else { - Some(value) - }; + return Some(value); }} None diff --git a/tests/compile-fail/let_if_seq.rs b/tests/compile-fail/let_if_seq.rs index 011848e95dd..caa8bae22fd 100644 --- a/tests/compile-fail/let_if_seq.rs +++ b/tests/compile-fail/let_if_seq.rs @@ -6,6 +6,14 @@ fn f() -> bool { true } +fn issue975() -> String { + let mut udn = "dummy".to_string(); + if udn.starts_with("uuid:") { + udn = String::from(&udn[5..]); + } + udn +} + fn early_return() -> u8 { // FIXME: we could extend the lint to include such cases: let foo; @@ -21,6 +29,7 @@ fn early_return() -> u8 { fn main() { early_return(); + issue975(); let mut foo = 0; //~^ ERROR `if _ { .. } else { .. }` is an expression -- cgit 1.4.1-3-g733a5 From 35934befbb3835efc97c963b43b2e733e7e65a84 Mon Sep 17 00:00:00 2001 From: David Tolnay <dtolnay@gmail.com> Date: Sat, 4 Jun 2016 14:31:24 -0700 Subject: Release 0.0.72 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53cebf4f99d..ea59d62a5ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.72 — 2016-06-04 +* Fix false positives in [`useless_let_if_seq`] + ## 0.0.71 — 2016-05-31 * Rustup to *rustc 1.11.0-nightly (a967611d8 2016-05-30)* * New lint: [`useless_let_if_seq`] diff --git a/Cargo.toml b/Cargo.toml index ec38ce91623..202cdb7b592 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.71" +version = "0.0.72" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.71", path = "clippy_lints" } +clippy_lints = { version = "0.0.72", path = "clippy_lints" } # end automatic update rustc-serialize = "0.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index db6ee124505..e3cf22e00e1 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.71" +version = "0.0.72" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From bdd6d2c35ed4d280d3112a3fd97710b53129255c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 15:47:57 +0200 Subject: Fix wrong suggestion in `MANUAL_SWAP` --- clippy_lints/src/swap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 6dc9dda37ec..a518e15ea13 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -85,7 +85,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { ("".to_owned(), "".to_owned(), "".to_owned()) }; - let span = mk_sp(tmp.span.lo, second.span.hi); + let span = mk_sp(w[0].span.lo, second.span.hi); span_lint_and_then(cx, MANUAL_SWAP, -- cgit 1.4.1-3-g733a5 From 9f70d04000aa7ca4c23d6839ac0e98d2074cf28b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 20:19:00 +0200 Subject: Fix wrong suggestion with `MANUAL_SWAP` and slices --- clippy_lints/Cargo.toml | 1 + clippy_lints/src/lib.rs | 3 +++ clippy_lints/src/swap.rs | 51 ++++++++++++++++++++++++++++++++++++++-------- tests/compile-fail/swap.rs | 42 +++++++++++++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e3cf22e00e1..877b9037d37 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -16,6 +16,7 @@ license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] [dependencies] +matches = "0.1.2" regex-syntax = "0.3.0" semver = "0.2.1" toml = "0.1" diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 944825e2bdc..857e11b0bd3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -42,6 +42,9 @@ extern crate rustc_plugin; extern crate rustc_const_eval; extern crate rustc_const_math; +#[macro_use] +extern crate matches as matches_macro; + macro_rules! declare_restriction_lint { { pub $name:tt, $description:tt } => { declare_lint! { pub $name, Allow, $description } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index a518e15ea13..5a3adfee409 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,7 +1,8 @@ -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; +use rustc::ty; use syntax::codemap::mk_sp; -use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq}; +use utils::{differing_macro_contexts, match_type, paths, snippet, snippet_opt, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; /// **What it does:** This lints manual swapping. /// @@ -79,10 +80,40 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) ], { - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { - (format!(" `{}` and `{}`", first, second), first, second) + fn check_for_slice<'a>(cx: &LateContext, lhs1: &'a Expr, lhs2: &'a Expr) -> Option<(&'a Expr, &'a Expr, &'a Expr)> { + if let ExprIndex(ref lhs1, ref idx1) = lhs1.node { + if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { + if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { + let ty = walk_ptrs_ty(cx.tcx.expr_ty(lhs1)); + + if matches!(ty.sty, ty::TySlice(_)) || + matches!(ty.sty, ty::TyArray(_, _)) || + match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::VEC_DEQUE) { + return Some((lhs1, idx1, idx2)); + } + } + } + } + + None + } + + let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) { + if let Some(slice) = snippet_opt(cx, slice.span) { + (false, + format!(" elements of `{}`", slice), + format!("{}.swap({}, {})",slice, snippet(cx, idx1.span, ".."), snippet(cx, idx2.span, ".."))) + } else { + (false, "".to_owned(), "".to_owned()) + } } else { - ("".to_owned(), "".to_owned(), "".to_owned()) + if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { + (true, format!(" `{}` and `{}`", first, second), + format!("std::mem::swap(&mut {}, &mut {})", first, second)) + } else { + (true, "".to_owned(), "".to_owned()) + } }; let span = mk_sp(w[0].span.lo, second.span.hi); @@ -92,10 +123,12 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { span, &format!("this looks like you are swapping{} manually", what), |db| { - if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); - db.note("or maybe you should use `std::mem::replace`?"); + if !sugg.is_empty() { + db.span_suggestion(span, "try", sugg); + + if replace { + db.note("or maybe you should use `std::mem::replace`?"); + } } }); }} diff --git a/tests/compile-fail/swap.rs b/tests/compile-fail/swap.rs index cc0570e6c63..c4135467556 100644 --- a/tests/compile-fail/swap.rs +++ b/tests/compile-fail/swap.rs @@ -2,11 +2,51 @@ #![plugin(clippy)] #![deny(clippy)] -#![allow(unused_assignments)] +#![allow(blacklisted_name, unused_assignments)] struct Foo(u32); +fn array() { + let mut foo = [1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + //~^^^ ERROR this looks like you are swapping elements of `foo` manually + //~| HELP try + //~| SUGGESTION foo.swap(0, 1); + + foo.swap(0, 1); +} + +fn slice() { + let foo = &mut [1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + //~^^^ ERROR this looks like you are swapping elements of `foo` manually + //~| HELP try + //~| SUGGESTION foo.swap(0, 1); + + foo.swap(0, 1); +} + +fn vec() { + let mut foo = vec![1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + //~^^^ ERROR this looks like you are swapping elements of `foo` manually + //~| HELP try + //~| SUGGESTION foo.swap(0, 1); + + foo.swap(0, 1); +} + fn main() { + array(); + slice(); + vec(); + let mut a = 42; let mut b = 1337; -- cgit 1.4.1-3-g733a5 From 7211df5a177eaf58a8c328bf6e0448fe772cbd3e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 20:46:27 +0200 Subject: Remove useless `if_let_chain` --- clippy_lints/src/derive.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f08522953aa..b941d9a7fca 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -70,9 +70,7 @@ impl LintPass for Derive { impl LateLintPass for Derive { fn check_item(&mut self, cx: &LateContext, item: &Item) { - if_let_chain! {[ - let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node - ], { + if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node { let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; let is_automatically_derived = item.attrs.iter().any(is_automatically_derived); @@ -81,7 +79,7 @@ impl LateLintPass for Derive { if !is_automatically_derived { check_copy_clone(cx, item, trait_ref, ty); } - }} + } } } -- cgit 1.4.1-3-g733a5 From 7bc7c675f2fe1fc9176cd45baa3361037b487dec Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 20:46:42 +0200 Subject: Cleanup, use `matches!` some more --- clippy_lints/src/block_in_if_condition.rs | 5 +---- clippy_lints/src/methods.rs | 13 ++++--------- clippy_lints/src/misc.rs | 17 +++-------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index c56cf4dcd29..b8f1bb71ad9 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -47,10 +47,7 @@ impl<'v> Visitor<'v> for ExVisitor<'v> { let complex = { if block.stmts.is_empty() { if let Some(ref ex) = block.expr { - match ex.node { - ExprBlock(_) => true, - _ => false, - } + matches!(ex.node, ExprBlock(_)) } else { false } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f9f557e7a9a..c37fbba9250 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1023,11 +1023,7 @@ impl OutType { (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, (&OutType::Ref, &hir::Return(ref ty)) => { - if let hir::TyRptr(_, _) = ty.node { - true - } else { - false - } + matches!(ty.node, hir::TyRptr(_, _)) } _ => false, } @@ -1036,11 +1032,10 @@ impl OutType { fn is_bool(ty: &hir::Ty) -> bool { if let hir::TyPath(None, ref p) = ty.node { - if match_path(p, &["bool"]) { - return true; - } + match_path(p, &["bool"]) + } else { + false } - false } fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &hir::Item) -> bool { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 5f113cf47ce..53f4c972644 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -189,11 +189,7 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { } fn is_float(cx: &LateContext, expr: &Expr) -> bool { - if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { - true - } else { - false - } + matches!(walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty, ty::TyFloat(_)) } /// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. @@ -283,11 +279,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool { args.len() == 1 && - if let ty::TyStr = walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { - true - } else { - false - } + matches!(walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty, ty::TyStr) } /// **What it does:** This lint checks for getting the remainder of a division by one. @@ -449,10 +441,7 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| { info_opt.map_or(false, |info| { - match info.callee.format { - ExpnFormat::MacroAttribute(_) => true, - _ => false, - } + matches!(info.callee.format, ExpnFormat::MacroAttribute(_)) }) }) } -- cgit 1.4.1-3-g733a5 From 158183adf52f8ddb4d4428c354cd41c7ac504912 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 21:38:15 +0200 Subject: Fix false-positive in `USELESS_LET_IF_SEQ` --- clippy_lints/src/let_if_seq.rs | 17 ++++++++++++----- tests/compile-fail/let_if_seq.rs | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 09172014c8c..a85cb52f2dc 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -69,12 +69,9 @@ impl LateLintPass for LetIfSeq { let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id), let hir::StmtExpr(ref if_, _) = expr.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, - { - let mut v = UsedVisitor { cx: cx, id: def.def_id(), used: false }; - hir::intravisit::walk_expr(&mut v, cond); - !v.used - }, + !used_in_expr(cx, def.def_id(), cond), let Some(value) = check_assign(cx, def.def_id(), then), + !used_in_expr(cx, def.def_id(), value), ], { let span = codemap::mk_sp(stmt.span.lo, if_.span.hi); @@ -179,3 +176,13 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir:: None } + +fn used_in_expr(cx: &LateContext, id: hir::def_id::DefId, expr: &hir::Expr) -> bool { + let mut v = UsedVisitor { + cx: cx, + id: id, + used: false + }; + hir::intravisit::walk_expr(&mut v, expr); + v.used +} diff --git a/tests/compile-fail/let_if_seq.rs b/tests/compile-fail/let_if_seq.rs index caa8bae22fd..0b086faf077 100644 --- a/tests/compile-fail/let_if_seq.rs +++ b/tests/compile-fail/let_if_seq.rs @@ -5,6 +5,27 @@ #![deny(useless_let_if_seq)] fn f() -> bool { true } +fn g(x: i32) -> i32 { x + 1 } + +fn issue985() -> i32 { + let mut x = 42; + if f() { + x = g(x); + } + + x +} + +fn issue985_alt() -> i32 { + let mut x = 42; + if f() { + f(); + } else { + x = g(x); + } + + x +} fn issue975() -> String { let mut udn = "dummy".to_string(); @@ -30,6 +51,8 @@ fn early_return() -> u8 { fn main() { early_return(); issue975(); + issue985(); + issue985_alt(); let mut foo = 0; //~^ ERROR `if _ { .. } else { .. }` is an expression -- cgit 1.4.1-3-g733a5 From 8497e3bacbbf6a729ced38f5481f193c927a164e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 21:43:22 +0200 Subject: Bump to 0.0.73 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea59d62a5ff..166990b3d3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.73 — 2016-06-05 +* Fix false positives in [`useless_let_if_seq`] + ## 0.0.72 — 2016-06-04 * Fix false positives in [`useless_let_if_seq`] diff --git a/Cargo.toml b/Cargo.toml index 202cdb7b592..aadc4e8e041 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.72" +version = "0.0.73" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.72", path = "clippy_lints" } +clippy_lints = { version = "0.0.73", path = "clippy_lints" } # end automatic update rustc-serialize = "0.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 877b9037d37..d0398897bea 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.72" +version = "0.0.73" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From a7a6c0461da71ac838708d2b34a629443f860b60 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 21:05:28 +0200 Subject: Add environment variable to deactivate wiki links --- CHANGELOG.md | 4 ++++ README.md | 3 +++ clippy_lints/src/utils/mod.rs | 7 +++++-- tests/compile-fail/booleans.rs | 21 ++++++++------------- tests/compile-fail/non_expressive_names.rs | 11 ----------- tests/compile-test.rs | 8 +++++++- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 166990b3d3b..51bf4ad2c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.74 — TBR +* Add the `CLIPPY_DISABLE_WIKI_LINKS` environment variable to deactivate the + “for further information visit *wiki-link*” message. + ## 0.0.73 — 2016-06-05 * Fix false positives in [`useless_let_if_seq`] diff --git a/README.md b/README.md index 3b5b6768c23..8f699d2f741 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,9 @@ You can also specify the path to the configuration file with: #![plugin(clippy(conf_file="path/to/clippy's/configuration"))] ``` +To deactivate the “for further information visit *wiki-link*” message you can +define the `CLIPPY_DISABLE_WIKI_LINKS` environment variable. + ## Link with clippy service `clippy-service` is a rust web initiative providing `rust-clippy` as a web service. diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 986462b3723..beec30b32de 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -10,6 +10,7 @@ use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty; use std::borrow::Cow; +use std::env; use std::mem; use std::ops::{Deref, DerefMut}; use std::str::FromStr; @@ -473,8 +474,10 @@ impl<'a> Deref for DiagnosticWrapper<'a> { impl<'a> DiagnosticWrapper<'a> { fn wiki_link(&mut self, lint: &'static Lint) { - self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { + self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower())); + } } } diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index aba55f0b8b4..fc220d1ac22 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -10,29 +10,27 @@ fn main() { let d: bool = unimplemented!(); let e: bool = unimplemented!(); let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug - //~| HELP for further information visit //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = a; let _ = !(a && b); let _ = !true; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = false; let _ = !false; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = true; let _ = !!a; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = a; let _ = false && a; //~ ERROR this boolean expression contains a logic bug - //~| HELP for further information visit //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; let _ = false || a; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = a; // don't lint on cfgs @@ -43,7 +41,7 @@ fn main() { let _ = !(a && b || c); let _ = !(!a && b); //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = !b || a; } @@ -55,32 +53,29 @@ fn equality_stuff() { let d: i32 = unimplemented!(); let e: i32 = unimplemented!(); let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug - //~| HELP for further information visit //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = a == b && c == 5; let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = a == b && c == 5; //~| HELP try //~| SUGGESTION let _ = !(c != 5 || a != b); let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug - //~| HELP for further information visit //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug - //~| HELP for further information visit //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; let _ = a > b && a == b; let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified - //~| HELP for further information visit + //~| HELP try //~| SUGGESTION let _ = c != d || a != b; //~| HELP try //~| SUGGESTION let _ = !(a == b && c == d); diff --git a/tests/compile-fail/non_expressive_names.rs b/tests/compile-fail/non_expressive_names.rs index d959507bcb2..212dc2a96d5 100644 --- a/tests/compile-fail/non_expressive_names.rs +++ b/tests/compile-fail/non_expressive_names.rs @@ -28,10 +28,8 @@ fn main() { //~^ NOTE: existing binding defined here let bpple: i32; //~ ERROR: name is too similar //~| HELP: separate the discriminating character by an underscore like: `b_pple` - //~| HELP: for further information visit let cpple: i32; //~ ERROR: name is too similar //~| HELP: separate the discriminating character by an underscore like: `c_pple` - //~| HELP: for further information visit let a_bar: i32; let b_bar: i32; @@ -56,13 +54,11 @@ fn main() { let blubx: i32; //~ NOTE: existing binding defined here let bluby: i32; //~ ERROR: name is too similar - //~| HELP: for further information visit //~| HELP: separate the discriminating character by an underscore like: `blub_y` let cake: i32; //~ NOTE: existing binding defined here let cakes: i32; let coke: i32; //~ ERROR: name is too similar - //~| HELP: for further information visit match 5 { cheese @ 1 => {}, @@ -81,12 +77,10 @@ fn main() { let xyz1abc: i32; //~ NOTE: existing binding defined here let xyz2abc: i32; let xyzeabc: i32; //~ ERROR: name is too similar - //~| HELP: for further information visit let parser: i32; //~ NOTE: existing binding defined here let parsed: i32; let parsee: i32; //~ ERROR: name is too similar - //~| HELP: for further information visit //~| HELP: separate the discriminating character by an underscore like: `parse_e` let setter: i32; @@ -101,7 +95,6 @@ fn foo() { let Foo { apple, bpple } = unimplemented!(); let Foo { apple: spring, //~NOTE existing binding defined here bpple: sprang } = unimplemented!(); //~ ERROR: name is too similar - //~^HELP for further information } #[derive(Clone, Debug)] @@ -136,18 +129,14 @@ fn bla() { } { let e: i32; //~ ERROR: 5th binding whose name is just one char - //~| HELP: for further information visit } { let e: i32; //~ ERROR: 5th binding whose name is just one char - //~| HELP: for further information visit let f: i32; //~ ERROR: 6th binding whose name is just one char - //~| HELP: for further information visit } match 5 { 1 => println!(""), e => panic!(), //~ ERROR: 5th binding whose name is just one char - //~| HELP: for further information visit } match 5 { 1 => println!(""), diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 66c5734cc11..42a7dd96ae2 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,7 +1,7 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; -use std::env::{var, temp_dir}; +use std::env::{set_var, var, temp_dir}; fn run_mode(dir: &'static str, mode: &'static str) { let mut config = compiletest::default_config(); @@ -23,9 +23,14 @@ fn run_mode(dir: &'static str, mode: &'static str) { compiletest::run_tests(&config); } +fn prepare_env() { + set_var("CLIPPY_DISABLE_WIKI_LINKS", "true"); +} + #[test] #[cfg(not(feature = "test-regex_macros"))] fn compile_test() { + prepare_env(); run_mode("run-pass", "run-pass"); run_mode("compile-fail", "compile-fail"); } @@ -33,6 +38,7 @@ fn compile_test() { #[test] #[cfg(feature = "test-regex_macros")] fn compile_test() { + prepare_env(); run_mode("run-pass-regex_macros", "run-pass"); run_mode("compile-fail-regex_macros", "compile-fail"); } -- cgit 1.4.1-3-g733a5 From a3f7fea36c8874a2ea9824257485f0d3a8d35ea0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 6 Jun 2016 11:03:15 +0200 Subject: simply parse unknown json-strings as strings instead of erroring --- clippy_lints/src/utils/cargo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index c51cfc7304b..b183db84d57 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -32,7 +32,7 @@ pub struct Dependency { optional: bool, uses_default_features: bool, features: Vec<String>, - target: Option<()>, + target: Option<String>, } #[derive(RustcDecodable, Debug)] -- cgit 1.4.1-3-g733a5 From a81181b75854fb23f816dec0e53ceefbb8d22605 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 6 Jun 2016 11:28:09 +0200 Subject: don't abort after successfully linting a target --- src/main.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index db0c6613f3f..75cc507740a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -128,9 +128,13 @@ pub fn main() { let args = std::env::args().skip(2); if let Some(first) = target.kind.get(0) { if target.kind.len() > 1 || first.ends_with("lib") { - process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root); + if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root) { + std::process::exit(code); + } } else if first == "bin" { - process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root); + if let Err(code) = process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root) { + std::process::exit(code); + } } } else { panic!("badly formatted cargo metadata: target::kind is an empty array"); @@ -152,7 +156,7 @@ pub fn main() { } } -fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) +fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32> where P: AsRef<Path>, I: Iterator<Item=String> { let mut args = vec!["rustc".to_owned()]; @@ -178,7 +182,10 @@ fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) .spawn().expect("could not run cargo") .wait().expect("failed to wait for cargo?"); - if let Some(code) = exit_status.code() { - std::process::exit(code); + if exit_status.success() { + Ok(()) + } else { + use std::os::unix::process::ExitStatusExt; + Err(exit_status.code().or(exit_status.signal()).unwrap_or(-1)) } } -- cgit 1.4.1-3-g733a5 From 8d5524f1daf9af3c5e6892c5af91bda49e589835 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 6 Jun 2016 16:43:58 +0200 Subject: clippy should work on all systems --- src/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 75cc507740a..a42610e1732 100644 --- a/src/main.rs +++ b/src/main.rs @@ -185,7 +185,6 @@ fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32> if exit_status.success() { Ok(()) } else { - use std::os::unix::process::ExitStatusExt; - Err(exit_status.code().or(exit_status.signal()).unwrap_or(-1)) + Err(exit_status.code().unwrap_or(-1)) } } -- cgit 1.4.1-3-g733a5 From 1aab0e6729c82c100efc9b63e8791e26e68187f0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 12:22:36 +0200 Subject: Bump to 0.0.74 --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51bf4ad2c15..29fa83ef630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.74 — TBR +## 0.0.74 — 2016-06-07 +* Fix bug with `cargo-clippy` JSON parsing * Add the `CLIPPY_DISABLE_WIKI_LINKS` environment variable to deactivate the “for further information visit *wiki-link*” message. diff --git a/Cargo.toml b/Cargo.toml index aadc4e8e041..81ef9a08bf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.73" +version = "0.0.74" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.73", path = "clippy_lints" } +clippy_lints = { version = "0.0.74", path = "clippy_lints" } # end automatic update rustc-serialize = "0.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d0398897bea..36a8a0d5f0b 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.73" +version = "0.0.74" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From 65c4e391ee0536142b76e78258550e7ba2f71a0a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 5 Jun 2016 18:07:12 +0200 Subject: Fix wrong tests and improve some other --- tests/compile-fail/formatting.rs | 16 ++++++++++++---- tests/compile-fail/let_return.rs | 4 ++-- tests/compile-fail/mut_mut.rs | 4 +++- tests/compile-fail/needless_borrow.rs | 2 +- tests/compile-fail/no_effect.rs | 4 ++-- tests/compile-fail/swap.rs | 8 ++++---- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tests/compile-fail/formatting.rs b/tests/compile-fail/formatting.rs index 14a23111ec7..2436f64d216 100644 --- a/tests/compile-fail/formatting.rs +++ b/tests/compile-fail/formatting.rs @@ -11,24 +11,32 @@ fn foo() -> bool { true } fn main() { // weird `else if` formatting: if foo() { - } if foo() { //~ERROR this looks like an `else if` but the `else` is missing + } if foo() { + //~^ ERROR this looks like an `else if` but the `else` is missing + //~| NOTE add the missing `else` or } let _ = { if foo() { - } if foo() { //~ERROR this looks like an `else if` but the `else` is missing + } if foo() { + //~^ ERROR this looks like an `else if` but the `else` is missing + //~| NOTE add the missing `else` or } else { } }; if foo() { - } else //~ERROR this is an `else if` but the formatting might hide it + } else + //~^ ERROR this is an `else if` but the formatting might hide it + //~| NOTE remove the `else` or if foo() { // the span of the above error should continue here } if foo() { - } //~ERROR this is an `else if` but the formatting might hide it + } + //~^ ERROR this is an `else if` but the formatting might hide it + //~| NOTE remove the `else` or else if foo() { // the span of the above error should continue here } diff --git a/tests/compile-fail/let_return.rs b/tests/compile-fail/let_return.rs index 33d2d6a823a..477786813db 100644 --- a/tests/compile-fail/let_return.rs +++ b/tests/compile-fail/let_return.rs @@ -6,13 +6,13 @@ fn test() -> i32 { let _y = 0; // no warning - let x = 5; //~NOTE + let x = 5; //~NOTE this expression can be directly returned x //~ERROR returning the result of a let binding } fn test_inner() -> i32 { if true { - let x = 5; + let x = 5; //~NOTE this expression can be directly returned x //~ERROR returning the result of a let binding } else { 0 diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 8d9bceb0d0d..92344110d2c 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -38,5 +38,7 @@ fn main() { ***y + **x; } - let mut z = mut_ptr!(&mut 3u32); //~ NOTE in this expansion of mut_ptr! + let mut z = mut_ptr!(&mut 3u32); + //~^ NOTE in this expansion of mut_ptr! + //~| NOTE in this expansion of mut_ptr! } diff --git a/tests/compile-fail/needless_borrow.rs b/tests/compile-fail/needless_borrow.rs index 602e1e0859b..88099297b98 100644 --- a/tests/compile-fail/needless_borrow.rs +++ b/tests/compile-fail/needless_borrow.rs @@ -10,7 +10,7 @@ fn x(y: &i32) -> i32 { fn main() { let a = 5; let b = x(&a); - let c = x(&&a); //~ ERROR: needless_borrow + let c = x(&&a); //~ ERROR: this expression borrows a reference that is immediately dereferenced by the compiler let s = &String::from("hi"); let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]` diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index c1d9b175428..76c7fa54c01 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -62,7 +62,7 @@ fn main() { //~|SUGGESTION get_number(); Struct { ..get_struct() }; //~ERROR statement can be reduced //~^HELP replace it with - //~|SUGGESTION get_number(); + //~|SUGGESTION get_struct(); Enum::Tuple(get_number()); //~ERROR statement can be reduced //~^HELP replace it with //~|SUGGESTION get_number(); @@ -74,7 +74,7 @@ fn main() { //~|SUGGESTION 5;get_number(); *&get_number(); //~ERROR statement can be reduced //~^HELP replace it with - //~|SUGGESTION &get_number(); + //~|SUGGESTION get_number(); &get_number(); //~ERROR statement can be reduced //~^HELP replace it with //~|SUGGESTION get_number(); diff --git a/tests/compile-fail/swap.rs b/tests/compile-fail/swap.rs index c4135467556..c8ff2b610d0 100644 --- a/tests/compile-fail/swap.rs +++ b/tests/compile-fail/swap.rs @@ -57,12 +57,12 @@ fn main() { //~| SUGGESTION std::mem::swap(&mut a, &mut b); //~| NOTE or maybe you should use `std::mem::replace`? - let t = a; + ; let t = a; a = b; b = t; //~^^^ ERROR this looks like you are swapping `a` and `b` manually //~| HELP try - //~| SUGGESTION std::mem::swap(&mut a, &mut b); + //~| SUGGESTION ; std::mem::swap(&mut a, &mut b); //~| NOTE or maybe you should use `std::mem::replace`? let mut c = Foo(42); @@ -74,11 +74,11 @@ fn main() { //~| SUGGESTION std::mem::swap(&mut c.0, &mut a); //~| NOTE or maybe you should use `std::mem::replace`? - let t = c.0; + ; let t = c.0; c.0 = a; a = t; //~^^^ ERROR this looks like you are swapping `c.0` and `a` manually //~| HELP try - //~| SUGGESTION std::mem::swap(&mut c.0, &mut a); + //~| SUGGESTION ; std::mem::swap(&mut c.0, &mut a); //~| NOTE or maybe you should use `std::mem::replace`? } -- cgit 1.4.1-3-g733a5 From 5b09501d6169b56cba665bf45e379fdc3b5ca42c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 17:49:13 +0200 Subject: Fix typo in `REVERSE_RANGE_LOOP`’s suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3d3c9ab47a4..664ff21994e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -450,7 +450,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { "consider using the following if \ you are attempting to iterate \ over this range in reverse", - format!("({}..{}).rev()` ", end_snippet, start_snippet)); + format!("({}..{}).rev()", end_snippet, start_snippet)); }); } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop -- cgit 1.4.1-3-g733a5 From 3df32cc723cc156e0ed5b507220039a52e0cbfde Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 17:58:52 +0200 Subject: Fix span in `REVERSE_RANGE_LOOP`’s suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 664ff21994e..e635b34e1de 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -446,7 +446,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { expr.span, "this range is empty so this for loop will never run", |db| { - db.span_suggestion(expr.span, + db.span_suggestion(arg.span, "consider using the following if \ you are attempting to iterate \ over this range in reverse", -- cgit 1.4.1-3-g733a5 From dd3fd41a037c32098815adab6f6734202f1510c8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 18:32:26 +0200 Subject: Use `span_suggestion` for `WHILE_LET_ON_ITERATOR` --- clippy_lints/src/loops.rs | 10 +++-- tests/compile-fail/absurd-extreme-comparisons.rs | 56 ++++++++++++++++++------ tests/compile-fail/booleans.rs | 20 ++++++--- tests/compile-fail/collapsible_if.rs | 10 ++++- tests/compile-fail/for_loop.rs | 10 ++++- tests/compile-fail/matches.rs | 27 +++++++++--- tests/compile-fail/mut_mut.rs | 1 - 7 files changed, 100 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e635b34e1de..5dcea35e5a7 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -290,11 +290,15 @@ impl LateLintPass for LoopsPass { !is_iterator_used_after_while_let(cx, iter_expr) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); - span_help_and_lint(cx, + span_lint_and_then(cx, WHILE_LET_ON_ITERATOR, expr.span, "this loop could be written as a `for` loop", - &format!("try\nfor {} in {} {{...}}", loop_var, iterator)); + |db| { + db.span_suggestion(expr.span, + "try", + format!("for {} in {} {{ .. }}", loop_var, iterator)); + }); } } } @@ -598,7 +602,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex |db| { db.span_suggestion(expr.span, "use the corresponding method", - format!("for {} in {}.{}() {{...}}", + format!("for {} in {}.{}() {{ .. }}", snippet(cx, *pat_span, ".."), snippet(cx, arg_span, ".."), kind)); diff --git a/tests/compile-fail/absurd-extreme-comparisons.rs b/tests/compile-fail/absurd-extreme-comparisons.rs index f1e4a692800..627cd888aac 100644 --- a/tests/compile-fail/absurd-extreme-comparisons.rs +++ b/tests/compile-fail/absurd-extreme-comparisons.rs @@ -8,15 +8,33 @@ fn main() { let u: u32 = 42; - u <= 0; //~ERROR this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - u <= Z; //~ERROR this comparison involving - u < Z; //~ERROR this comparison involving - Z >= u; //~ERROR this comparison involving - Z > u; //~ERROR this comparison involving - u > std::u32::MAX; //~ERROR this comparison involving - u >= std::u32::MAX; //~ERROR this comparison involving - std::u32::MAX < u; //~ERROR this comparison involving - std::u32::MAX <= u; //~ERROR this comparison involving + u <= 0; + //~^ ERROR this comparison involving the minimum or maximum element for this type contains a case that is always true or always false + //~| HELP using u == 0 instead + u <= Z; + //~^ ERROR this comparison involving + //~| HELP using u == Z instead + u < Z; + //~^ ERROR this comparison involving + //~| HELP comparison is always false + Z >= u; + //~^ ERROR this comparison involving + //~| HELP using Z == u instead + Z > u; + //~^ ERROR this comparison involving + //~| HELP comparison is always false + u > std::u32::MAX; + //~^ ERROR this comparison involving + //~| HELP comparison is always false + u >= std::u32::MAX; + //~^ ERROR this comparison involving + //~| HELP using u == std::u32::MAX instead + std::u32::MAX < u; + //~^ ERROR this comparison involving + //~| HELP comparison is always false + std::u32::MAX <= u; + //~^ ERROR this comparison involving + //~| HELP using std::u32::MAX == u instead 1-1 > u; //~^ ERROR this comparison involving @@ -29,13 +47,23 @@ fn main() { //~| HELP because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead let i: i8 = 0; - i < -127 - 1; //~ERROR this comparison involving - std::i8::MAX >= i; //~ERROR this comparison involving - 3-7 < std::i32::MIN; //~ERROR this comparison involving + i < -127 - 1; + //~^ ERROR this comparison involving + //~| HELP comparison is always false + std::i8::MAX >= i; + //~^ ERROR this comparison involving + //~| HELP comparison is always true + 3-7 < std::i32::MIN; + //~^ ERROR this comparison involving + //~| HELP comparison is always false let b = false; - b >= true; //~ERROR this comparison involving - false > b; //~ERROR this comparison involving + b >= true; + //~^ ERROR this comparison involving + //~| HELP using b == true instead + false > b; + //~^ ERROR this comparison involving + //~| HELP comparison is always false u > 0; // ok diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index fc220d1ac22..193edebf3c4 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -52,29 +52,37 @@ fn equality_stuff() { let c: i32 = unimplemented!(); let d: i32 = unimplemented!(); let e: i32 = unimplemented!(); - let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug + let _ = a == b && a != b; + //~^ ERROR this boolean expression contains a logic bug //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; - let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified + let _ = a == b && c == 5 && a == b; + //~^ ERROR this boolean expression can be simplified //~| HELP try //~| SUGGESTION let _ = a == b && c == 5; - let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified + //~| HELP try + //~| SUGGESTION let _ = !(c != 5 || a != b); + let _ = a == b && c == 5 && b == a; + //~^ ERROR this boolean expression can be simplified //~| HELP try //~| SUGGESTION let _ = a == b && c == 5; //~| HELP try //~| SUGGESTION let _ = !(c != 5 || a != b); - let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug + let _ = a < b && a >= b; + //~^ ERROR this boolean expression contains a logic bug //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; - let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug + let _ = a > b && a <= b; + //~^ ERROR this boolean expression contains a logic bug //~| HELP this expression can be optimized out //~| HELP it would look like the following //~| SUGGESTION let _ = false; let _ = a > b && a == b; - let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified + let _ = a != b || !(a != b || c == d); + //~^ ERROR this boolean expression can be simplified //~| HELP try //~| SUGGESTION let _ = c != d || a != b; //~| HELP try diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index 3bf4128347a..34c55499612 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -5,13 +5,19 @@ fn main() { let x = "hello"; let y = "world"; - if x == "hello" { //~ERROR this if statement can be collapsed + if x == "hello" { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if x == "hello" && y == "world" { if y == "world" { println!("Hello world!"); } } - if x == "hello" || x == "world" { //~ERROR this if statement can be collapsed + if x == "hello" || x == "world" { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if (x == "hello" || x == "world") && (y == "world" || y == "hello") { if y == "world" || y == "hello" { println!("Hello world!"); } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 2f164d1e569..d35beb617e0 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -200,11 +200,17 @@ fn main() { } // testing that the empty range lint folds constants - for i in 10..5+4 { //~ERROR this range is empty so this for loop will never run + for i in 10..5+4 { + //~^ ERROR this range is empty so this for loop will never run + //~| HELP if you are attempting to iterate over this range in reverse + //~| SUGGESTION for i in (5+4..10).rev() { println!("{}", i); } - for i in (5+2)..(3-1) { //~ERROR this range is empty so this for loop will never run + for i in (5+2)..(3-1) { + //~^ ERROR this range is empty so this for loop will never run + //~| HELP if you are attempting to iterate over this range in reverse + //~| SUGGESTION for i in ((3-1)..(5+2)).rev() { println!("{}", i); } diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index affa7e4e86e..650b5917fdc 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -100,28 +100,43 @@ fn single_match_know_enum() { fn match_bool() { let test: bool = true; - match test { //~ ERROR you seem to be trying to match on a boolean expression + match test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~| SUGGESTION if test { 0 } else { 42 }; true => 0, false => 42, }; let option = 1; - match option == 1 { //~ ERROR you seem to be trying to match on a boolean expression + match option == 1 { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~| SUGGESTION if option == 1 { 1 } else { 0 }; true => 1, false => 0, }; - match test { //~ ERROR you seem to be trying to match on a boolean expression + match test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~^^ SUGGESTION if !test { println!("Noooo!"); }; true => (), false => { println!("Noooo!"); } }; - match test { //~ ERROR you seem to be trying to match on a boolean expression + match test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~^^ SUGGESTION if !test { println!("Noooo!"); }; false => { println!("Noooo!"); } _ => (), }; - match test { //~ ERROR you seem to be trying to match on a boolean expression + match test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~| SUGGESTION if test { println!("Yes!"); } else { println!("Noooo!"); }; false => { println!("Noooo!"); } true => { println!("Yes!"); } }; @@ -216,7 +231,7 @@ fn overlapping() { 11 ... 50 => println!("0 ... 10"), _ => (), } - + if let None = Some(42) { // nothing } else if let None = Some(42) { diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 92344110d2c..21c0dcee511 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -40,5 +40,4 @@ fn main() { let mut z = mut_ptr!(&mut 3u32); //~^ NOTE in this expansion of mut_ptr! - //~| NOTE in this expansion of mut_ptr! } -- cgit 1.4.1-3-g733a5 From 1f419a29869eb4788a14e894219d732542cae295 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 18:33:11 +0200 Subject: Add missing suggestions and help message to tests --- tests/compile-fail/methods.rs | 12 +++++++++--- tests/compile-fail/needless_return.rs | 25 ++++++++++++++++++++----- tests/compile-fail/strings.rs | 7 +++++-- tests/compile-fail/while_loop.rs | 20 ++++++++++++++++---- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 78ffbb1a58a..89267462f5d 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -356,13 +356,19 @@ fn starts_with() { fn use_extend_from_slice() { let mut v : Vec<&'static str> = vec![]; - v.extend(&["Hello", "World"]); //~ERROR use of `extend` + v.extend(&["Hello", "World"]); + //~^ ERROR use of `extend` + //~| HELP try this + //~| SUGGESTION v.extend_from_slice(&["Hello", "World"]); v.extend(&vec!["Some", "more"]); - //~^ERROR use of `extend` + //~^ ERROR use of `extend` //~| HELP try this //~| SUGGESTION v.extend_from_slice(&vec!["Some", "more"]); - v.extend(vec!["And", "even", "more"].iter()); //~ERROR use of `extend` + v.extend(vec!["And", "even", "more"].iter()); + //~^ ERROR use of `extend` + //~| HELP try this + //FIXME: the suggestion if broken because of the macro let o : Option<&'static str> = None; v.extend(o); v.extend(Some("Bye")); diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs index fe29d991661..80fed2818ef 100644 --- a/tests/compile-fail/needless_return.rs +++ b/tests/compile-fail/needless_return.rs @@ -23,26 +23,41 @@ fn test_no_semicolon() -> bool { fn test_if_block() -> bool { if true { - return true; //~ERROR unneeded return statement + return true; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION true } else { - return false; //~ERROR unneeded return statement + return false; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION false } } fn test_match(x: bool) -> bool { match x { true => { - return false; //~ERROR unneeded return statement + return false; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION false } false => { - return true; //~ERROR unneeded return statement + return true; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION true } } } fn test_closure() { let _ = || { - return true; //~ERROR unneeded return statement + return true; + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION true }; } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs index 542b6db4abb..d08f8b891bc 100644 --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -63,8 +63,11 @@ fn main() { add_assign_only(); both(); - // the add is only caught for String + // the add is only caught for `String` let mut x = 1; - x = x + 1; //~ WARN assign_op_pattern + ; x = x + 1; + //~^ WARN assign_op_pattern + //~| HELP replace + //~| SUGGESTION ; x += 1; assert_eq!(2, x); } diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index 7c5582ba9bf..4c1090876b4 100644 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -80,17 +80,26 @@ fn main() { } let mut iter = 1..20; - while let Option::Some(x) = iter.next() { //~ERROR this loop could be written as a `for` loop + while let Option::Some(x) = iter.next() { + //~^ ERROR this loop could be written as a `for` loop + //~| HELP try + //~| SUGGESTION for x in iter { println!("{}", x); } let mut iter = 1..20; - while let Some(x) = iter.next() { //~ERROR this loop could be written as a `for` loop + while let Some(x) = iter.next() { + //~^ ERROR this loop could be written as a `for` loop + //~| HELP try + //~| SUGGESTION for x in iter { println!("{}", x); } let mut iter = 1..20; - while let Some(_) = iter.next() {} //~ERROR this loop could be written as a `for` loop + while let Some(_) = iter.next() {} + //~^ ERROR this loop could be written as a `for` loop + //~| HELP try + //~| SUGGESTION for _ in iter { let mut iter = 1..20; while let None = iter.next() {} // this is fine (if nonsensical) @@ -130,7 +139,10 @@ fn main() { // cause this function to trigger it fn no_panic<T>(slice: &[T]) { let mut iter = slice.iter(); - loop { //~ERROR + loop { + //~^ ERROR + //~| HELP try + //~| SUGGESTION while let Some(ele) = iter.next() { .. } let _ = match iter.next() { Some(ele) => ele, None => break -- cgit 1.4.1-3-g733a5 From 35a22bc3f40e1f3c1c73ecf1a960cf0c71374e75 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 18:33:29 +0200 Subject: Bump `compiletest_rs` to 0.2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 81ef9a08bf7..0bfd05a0de4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ clippy_lints = { version = "0.0.74", path = "clippy_lints" } rustc-serialize = "0.3" [dev-dependencies] -compiletest_rs = "0.1.0" +compiletest_rs = "0.2.0" lazy_static = "0.1.15" regex = "0.1.56" -- cgit 1.4.1-3-g733a5 From 3415a18febb8d8afe6de9f462fee953e979a88a9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 8 Jun 2016 12:21:24 +0200 Subject: Rustup to *1.11.0-nightly (763f9234b 2016-06-06)* --- clippy_lints/src/misc.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 53f4c972644..c283dc69b99 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -6,6 +6,7 @@ use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; +use rustc_const_math::ConstFloat; use syntax::codemap::{Span, Spanned, ExpnFormat}; use syntax::ptr::P; use utils::{ @@ -182,7 +183,26 @@ impl LateLintPass for FloatCmp { fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None); if let Ok(ConstVal::Float(val)) = res { - val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY + use std::cmp::Ordering; + + let zero = ConstFloat::FInfer { + f32: 0.0, + f64: 0.0, + }; + + let infinity = ConstFloat::FInfer { + f32: ::std::f32::INFINITY, + f64: ::std::f64::INFINITY, + }; + + let neg_infinity = ConstFloat::FInfer { + f32: ::std::f32::NEG_INFINITY, + f64: ::std::f64::NEG_INFINITY, + }; + + val.try_cmp(zero) == Ok(Ordering::Equal) + || val.try_cmp(infinity) == Ok(Ordering::Equal) + || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) } else { false } -- cgit 1.4.1-3-g733a5 From 11ea3b8be9b32fa8335f3cc7ba70eb33213619a9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 8 Jun 2016 12:23:33 +0200 Subject: Bump to 0.0.75 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29fa83ef630..42ff32fe13f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.75 — 2016-06-08 +* Rustup to *rustc 1.11.0-nightly (763f9234b 2016-06-06)* + ## 0.0.74 — 2016-06-07 * Fix bug with `cargo-clippy` JSON parsing * Add the `CLIPPY_DISABLE_WIKI_LINKS` environment variable to deactivate the diff --git a/Cargo.toml b/Cargo.toml index 0bfd05a0de4..1ea542c7737 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.74" +version = "0.0.75" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -30,7 +30,7 @@ toml = "0.1" unicode-normalization = "0.1" quine-mc_cluskey = "0.2.2" # begin automatic update -clippy_lints = { version = "0.0.74", path = "clippy_lints" } +clippy_lints = { version = "0.0.75", path = "clippy_lints" } # end automatic update rustc-serialize = "0.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 36a8a0d5f0b..793e26ad06d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.74" +version = "0.0.75" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From d7ba66bf44f993e64114e17cc15f1b0d56ae8f70 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 8 Jun 2016 21:48:10 +0200 Subject: Automatically defines the `clippy` feature --- CHANGELOG.md | 3 +++ README.md | 39 +++++++++++++++++++++++---------------- src/main.rs | 7 ++++++- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42ff32fe13f..4009246507c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.76 — TBD +* `cargo clippy` now automatically defines the `clippy` feature + ## 0.0.75 — 2016-06-08 * Rustup to *rustc 1.11.0-nightly (763f9234b 2016-06-06)* diff --git a/README.md b/README.md index 8f699d2f741..2e40f6ed74c 100644 --- a/README.md +++ b/README.md @@ -245,22 +245,6 @@ similar crates. SYSROOT=/path/to/rustc/sysroot cargo install clippy ``` -### Configuring clippy - -You can add options to `allow`/`warn`/`deny`: - -* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) - -* all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, - `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive - lints prone to false positives. - -* only some lints (`#![deny(single_match, box_vec)]`, etc) - -* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc - -Note: `deny` produces errors instead of warnings - ### Running clippy from the command line without installing To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` @@ -321,6 +305,29 @@ You can also specify the path to the configuration file with: To deactivate the “for further information visit *wiki-link*” message you can define the `CLIPPY_DISABLE_WIKI_LINKS` environment variable. +### Allowing/denying lints + +You can add options to `allow`/`warn`/`deny`: + +* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) + +* all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, + `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive + lints prone to false positives. + +* only some lints (`#![deny(single_match, box_vec)]`, etc) + +* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc + +Note: `deny` produces errors instead of warnings. + +For convenience, `cargo clippy` automatically defines a `clippy` features. This +lets you set lints level and compile with or without clippy transparently: + +```rust +#[cfg_attr(feature = "clippy", allow(needless_lifetimes))] +``` + ## Link with clippy service `clippy-service` is a rust web initiative providing `rust-clippy` as a web service. diff --git a/src/main.rs b/src/main.rs index a42610e1732..43483e76a0f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,11 +141,14 @@ pub fn main() { } } } else { - let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { + let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") { env::args().collect() } else { env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() }; + + args.extend_from_slice(&["--cfg".to_owned(), r#"feature="clippy""#.to_owned()]); + let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); if let Err(err_count) = result { @@ -174,6 +177,8 @@ fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32> args.push(String::from("--sysroot")); args.push(sysroot.to_owned()); args.push("-Zno-trans".to_owned()); + args.push("--cfg".to_owned()); + args.push(r#"feature="clippy""#.to_owned()); let path = std::env::current_exe().expect("current executable path invalid"); let exit_status = std::process::Command::new("cargo") -- cgit 1.4.1-3-g733a5 From 8e1dc0481cbeee9b789c70626bc9e82be826c5e8 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Wed, 8 Jun 2016 19:58:29 -0400 Subject: Include `consts` in the approx_consts lint for easier copypasting If you try to use `f64::PI`, it won't work-- you need to use `f64::consts::PI`, so suggest that in the lint message. --- clippy_lints/src/approx_const.rs | 2 +- tests/compile-fail/approx_const.rs | 38 +++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 731f1a45d09..6d842ce64fc 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -69,7 +69,7 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &str, module: &str) { span_lint(cx, APPROX_CONSTANT, e.span, - &format!("approximate value of `{}::{}` found. Consider using it directly", module, &name)); + &format!("approximate value of `{}::consts::{}` found. Consider using it directly", module, &name)); return; } } diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs index 3660fb41919..2240c3799a3 100644 --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -4,54 +4,54 @@ #[deny(approx_constant)] #[allow(unused, shadow_unrelated, similar_names)] fn main() { - let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::E` found - let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::E` found + let my_e = 2.7182; //~ERROR approximate value of `f{32, 64}::consts::E` found + let almost_e = 2.718; //~ERROR approximate value of `f{32, 64}::consts::E` found let no_e = 2.71; - let my_1_frac_pi = 0.3183; //~ERROR approximate value of `f{32, 64}::FRAC_1_PI` found + let my_1_frac_pi = 0.3183; //~ERROR approximate value of `f{32, 64}::consts::FRAC_1_PI` found let no_1_frac_pi = 0.31; - let my_frac_1_sqrt_2 = 0.70710678; //~ERROR approximate value of `f{32, 64}::FRAC_1_SQRT_2` found - let almost_frac_1_sqrt_2 = 0.70711; //~ERROR approximate value of `f{32, 64}::FRAC_1_SQRT_2` found + let my_frac_1_sqrt_2 = 0.70710678; //~ERROR approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found + let almost_frac_1_sqrt_2 = 0.70711; //~ERROR approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found let my_frac_1_sqrt_2 = 0.707; - let my_frac_2_pi = 0.63661977; //~ERROR approximate value of `f{32, 64}::FRAC_2_PI` found + let my_frac_2_pi = 0.63661977; //~ERROR approximate value of `f{32, 64}::consts::FRAC_2_PI` found let no_frac_2_pi = 0.636; - let my_frac_2_sq_pi = 1.128379; //~ERROR approximate value of `f{32, 64}::FRAC_2_SQRT_PI` found + let my_frac_2_sq_pi = 1.128379; //~ERROR approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found let no_frac_2_sq_pi = 1.128; - let my_frac_pi_2 = 1.57079632679; //~ERROR approximate value of `f{32, 64}::FRAC_PI_2` found + let my_frac_pi_2 = 1.57079632679; //~ERROR approximate value of `f{32, 64}::consts::FRAC_PI_2` found let no_frac_pi_2 = 1.5705; - let my_frac_pi_3 = 1.04719755119; //~ERROR approximate value of `f{32, 64}::FRAC_PI_3` found + let my_frac_pi_3 = 1.04719755119; //~ERROR approximate value of `f{32, 64}::consts::FRAC_PI_3` found let no_frac_pi_3 = 1.047; - let my_frac_pi_4 = 0.785398163397; //~ERROR approximate value of `f{32, 64}::FRAC_PI_4` found + let my_frac_pi_4 = 0.785398163397; //~ERROR approximate value of `f{32, 64}::consts::FRAC_PI_4` found let no_frac_pi_4 = 0.785; - let my_frac_pi_6 = 0.523598775598; //~ERROR approximate value of `f{32, 64}::FRAC_PI_6` found + let my_frac_pi_6 = 0.523598775598; //~ERROR approximate value of `f{32, 64}::consts::FRAC_PI_6` found let no_frac_pi_6 = 0.523; - let my_frac_pi_8 = 0.3926990816987; //~ERROR approximate value of `f{32, 64}::FRAC_PI_8` found + let my_frac_pi_8 = 0.3926990816987; //~ERROR approximate value of `f{32, 64}::consts::FRAC_PI_8` found let no_frac_pi_8 = 0.392; - let my_ln_10 = 2.302585092994046; //~ERROR approximate value of `f{32, 64}::LN_10` found + let my_ln_10 = 2.302585092994046; //~ERROR approximate value of `f{32, 64}::consts::LN_10` found let no_ln_10 = 2.303; - let my_ln_2 = 0.6931471805599453; //~ERROR approximate value of `f{32, 64}::LN_2` found + let my_ln_2 = 0.6931471805599453; //~ERROR approximate value of `f{32, 64}::consts::LN_2` found let no_ln_2 = 0.693; - let my_log10_e = 0.43429448190325182; //~ERROR approximate value of `f{32, 64}::LOG10_E` found + let my_log10_e = 0.43429448190325182; //~ERROR approximate value of `f{32, 64}::consts::LOG10_E` found let no_log10_e = 0.434; - let my_log2_e = 1.4426950408889634; //~ERROR approximate value of `f{32, 64}::LOG2_E` found + let my_log2_e = 1.4426950408889634; //~ERROR approximate value of `f{32, 64}::consts::LOG2_E` found let no_log2_e = 1.442; - let my_pi = 3.1415; //~ERROR approximate value of `f{32, 64}::PI` found - let almost_pi = 3.14; //~ERROR approximate value of `f{32, 64}::PI` found + let my_pi = 3.1415; //~ERROR approximate value of `f{32, 64}::consts::PI` found + let almost_pi = 3.14; //~ERROR approximate value of `f{32, 64}::consts::PI` found let no_pi = 3.15; - let my_sq2 = 1.4142; //~ERROR approximate value of `f{32, 64}::SQRT_2` found + let my_sq2 = 1.4142; //~ERROR approximate value of `f{32, 64}::consts::SQRT_2` found let no_sq2 = 1.414; } -- cgit 1.4.1-3-g733a5 From c5affa2efc697f478828c81def852f70968bb329 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 8 Jun 2016 22:00:42 +0200 Subject: Whitelist Nan in `DOC_MARKDOWN` --- clippy_lints/src/utils/conf.rs | 2 +- tests/compile-fail/doc.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index e773cc0e025..851764edc28 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -151,7 +151,7 @@ define_Conf! { /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks - ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub"] => Vec<String>), + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub", "NaN"] => Vec<String>), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index d3b1c037f47..415bcb2e661 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -46,6 +46,7 @@ fn test_emphasis() { /// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib /// 32kB 32MB 32GB 32TB 32PB 32EB /// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb +/// NaN /// be_sure_we_got_to_the_end_of_it //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn test_units() { -- cgit 1.4.1-3-g733a5 From ce2b96abe98ba23362d91094007b2b932cdd89e0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 9 Jun 2016 00:22:59 +0200 Subject: Fix yet another FP in `USELESS_LET_IF_SEQ` The block expression before the assignment must be `None`. --- clippy_lints/src/let_if_seq.rs | 1 + tests/compile-fail/let_if_seq.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index a85cb52f2dc..2f98d10dee0 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -150,6 +150,7 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> { fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> { if_let_chain! {[ + block.expr.is_none(), let Some(expr) = block.stmts.iter().last(), let hir::StmtSemi(ref expr, _) = expr.node, let hir::ExprAssign(ref var, ref value) = expr.node, diff --git a/tests/compile-fail/let_if_seq.rs b/tests/compile-fail/let_if_seq.rs index 0b086faf077..b49e5a26122 100644 --- a/tests/compile-fail/let_if_seq.rs +++ b/tests/compile-fail/let_if_seq.rs @@ -98,6 +98,15 @@ fn main() { toto = 2; } + // found in libcore, the inner if is not a statement but the block's expr + let mut ch = b'x'; + if f() { + ch = b'*'; + if f() { + ch = b'?'; + } + } + // baz needs to be mut let mut baz = 0; //~^ ERROR `if _ { .. } else { .. }` is an expression -- cgit 1.4.1-3-g733a5 From 3ae39145fc763a798404dd9301e8d8f045fdbf4e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 9 Jun 2016 00:24:44 +0200 Subject: Fix false-positive in `LET_AND_RETURN` If the declaration has a type, it might be required for coercion to happen. --- clippy_lints/src/returns.rs | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index d7893821263..7bb468166b8 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,7 +3,7 @@ use syntax::ast::*; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; +use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro}; /// **What it does:** This lint checks for return statements at the end of a block. /// @@ -95,29 +95,23 @@ impl ReturnPass { let Some(ref retexpr) = block.expr, let StmtKind::Decl(ref decl, _) = stmt.node, let DeclKind::Local(ref local) = decl.node, + local.ty.is_none(), let Some(ref initexpr) = local.init, let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, let ExprKind::Path(_, ref path) = retexpr.node, - match_path_ast(path, &[&id.name.as_str()]) + match_path_ast(path, &[&id.name.as_str()]), + !in_external_macro(cx, initexpr.span), ], { - self.emit_let_lint(cx, retexpr.span, initexpr.span); + span_note_and_lint(cx, + LET_AND_RETURN, + retexpr.span, + "returning the result of a let binding from a block. \ + Consider returning the expression directly.", + initexpr.span, + "this expression can be directly returned"); } } } - - fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { - if in_external_macro(cx, note_span) { - return; - } - let mut db = span_lint(cx, - LET_AND_RETURN, - lint_span, - "returning the result of a let binding from a block. Consider returning the \ - expression directly."); - if cx.current_level(LET_AND_RETURN) != Level::Allow { - db.span_note(note_span, "this expression can be directly returned"); - } - } } impl LintPass for ReturnPass { -- cgit 1.4.1-3-g733a5 From e9360f76751b8b60ec14520d23f1edb8263963cd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 9 Jun 2016 23:05:48 +0200 Subject: Fix suggestions for `REVERSE_RANGE_LOOP` --- clippy_lints/src/loops.rs | 10 +++++++++- tests/compile-fail/for_loop.rs | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 5dcea35e5a7..5d431e47465 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -444,6 +444,11 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { if sup { let start_snippet = snippet(cx, start.span, "_"); let end_snippet = snippet(cx, end.span, "_"); + let dots = if limits == ast::RangeLimits::Closed { + "..." + } else { + ".." + }; span_lint_and_then(cx, REVERSE_RANGE_LOOP, @@ -454,7 +459,10 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { "consider using the following if \ you are attempting to iterate \ over this range in reverse", - format!("({}..{}).rev()", end_snippet, start_snippet)); + format!("({end}{dots}{start}).rev()", + end=end_snippet, + dots=dots, + start=start_snippet)); }); } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index d35beb617e0..411a4b11c17 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -169,7 +169,7 @@ fn main() { for i in 10...0 { //~^ERROR this range is empty so this for loop will never run //~|HELP consider - //~|SUGGESTION (0..10).rev() + //~|SUGGESTION (0...10).rev() println!("{}", i); } -- cgit 1.4.1-3-g733a5 From 8756ae5082a556985e16e57d6511bf740bd3003a Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Fri, 10 Jun 2016 00:06:50 +0200 Subject: added GPLv{2,3} to doc-valid-idents --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 851764edc28..0c238400308 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -151,7 +151,7 @@ define_Conf! { /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks - ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub", "NaN"] => Vec<String>), + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub", "NaN", "GPLv2", "GPLv3"] => Vec<String>), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have -- cgit 1.4.1-3-g733a5 From cca6eb2e2bb5756c1c359c56b5664786a36b173a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 01:16:16 +0200 Subject: Cleanup --- clippy_lints/src/bit_mask.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index aec0990dcc6..f1e427c5c61 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -91,16 +91,11 @@ impl LateLintPass for BitMask { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if cmp.node.is_comparison() { - fetch_int_literal(cx, right).map_or_else(|| { - fetch_int_literal(cx, left).map_or((), |cmp_val| { - check_compare(cx, - right, - invert_cmp(cmp.node), - cmp_val, - &e.span) - }) - }, - |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, &e.span)) + if let Some(cmp_opt) = fetch_int_literal(cx, right) { + check_compare(cx, left, cmp.node, cmp_opt, &e.span) + } else if let Some(cmp_val) = fetch_int_literal(cx, left) { + check_compare(cx, right, invert_cmp(cmp.node), cmp_val, &e.span) + } } } } -- cgit 1.4.1-3-g733a5 From 90453fd893c1f1ad739a8f79516591db1af6d307 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 01:42:39 +0200 Subject: Run rustfmt Only partially apply suggestions. --- clippy_lints/src/arithmetic.rs | 40 +++++-------- clippy_lints/src/array_indexing.rs | 8 +-- clippy_lints/src/assign_ops.rs | 88 +++++++++++++--------------- clippy_lints/src/booleans.rs | 30 +++++----- clippy_lints/src/cyclomatic_complexity.rs | 12 ++-- clippy_lints/src/derive.rs | 6 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/functions.rs | 3 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/loops.rs | 14 ++--- clippy_lints/src/matches.rs | 32 +++++----- clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 8 +-- clippy_lints/src/mut_mut.rs | 5 +- clippy_lints/src/needless_borrow.rs | 3 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/new_without_default.rs | 14 ++--- clippy_lints/src/no_effect.rs | 16 +++-- clippy_lints/src/non_expressive_names.rs | 22 +++---- clippy_lints/src/regex.rs | 10 +++- clippy_lints/src/unsafe_removed_from_name.rs | 13 ++-- clippy_lints/src/unused_label.rs | 6 +- clippy_lints/src/utils/cargo.rs | 12 +++- clippy_lints/src/utils/hir.rs | 4 +- clippy_lints/src/utils/mod.rs | 7 +-- src/main.rs | 32 ++++++---- tests/cc_seme.rs | 5 +- tests/compile-test.rs | 2 +- tests/consts.rs | 23 ++++---- tests/dogfood.rs | 6 +- tests/issue-825.rs | 2 +- tests/matches.rs | 7 ++- tests/used_underscore_binding_macro.rs | 2 +- 33 files changed, 231 insertions(+), 209 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index be732740442..4481ab403f8 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -38,7 +38,7 @@ declare_restriction_lint! { #[derive(Copy, Clone, Default)] pub struct Arithmetic { - span: Option<Span> + span: Option<Span>, } impl LintPass for Arithmetic { @@ -49,48 +49,36 @@ impl LintPass for Arithmetic { impl LateLintPass for Arithmetic { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { - if let Some(_) = self.span { return; } + if let Some(_) = self.span { + return; + } match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd | hir::BiOr | hir::BiBitAnd | - hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr | - hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | - hir::BiGt => return, - _ => () + hir::BiAnd | hir::BiOr | hir::BiBitAnd | hir::BiBitOr | hir::BiBitXor | hir::BiShl | + hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, + _ => (), } let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r)); if l_ty.is_integral() && r_ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, - expr.span, - "integer arithmetic detected"); + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.span = Some(expr.span); } else if l_ty.is_floating_point() && r_ty.is_floating_point() { - span_lint(cx, - FLOAT_ARITHMETIC, - expr.span, - "floating-point arithmetic detected"); + span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.span = Some(expr.span); } - }, + } hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { let ty = cx.tcx.expr_ty(arg); if ty.is_integral() { - span_lint(cx, - INTEGER_ARITHMETIC, - expr.span, - "integer arithmetic detected"); + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.span = Some(expr.span); } else if ty.is_floating_point() { - span_lint(cx, - FLOAT_ARITHMETIC, - expr.span, - "floating-point arithmetic detected"); + span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.span = Some(expr.span); } - }, - _ => () + } + _ => (), } } diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index ce2b9a7d6c0..f3b7297b296 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -79,11 +79,11 @@ impl LateLintPass for ArrayIndexing { // Index is a constant range if let Some(range) = utils::unsugar_range(index) { let start = range.start - .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) - .map(|v| v.ok()); + .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) + .map(|v| v.ok()); let end = range.end - .map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)) - .map(|v| v.ok()); + .map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)) + .map(|v| v.ok()); if let Some((start, end)) = to_const_range(start, end, range.limits, size) { if start > size || end > size { diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 2b1aec83e4c..1a5ca16b9c5 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -51,31 +51,24 @@ impl LateLintPass for AssignOps { match expr.node { hir::ExprAssignOp(op, ref lhs, ref rhs) => { if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) { - span_lint_and_then(cx, - ASSIGN_OPS, - expr.span, - "assign operation detected", - |db| { - match rhs.node { - hir::ExprBinary(op2, _, _) if op2 != op => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); - }, - _ => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} {}", l, l, op.node.as_str(), r)); - } - } - }); + span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| { + match rhs.node { + hir::ExprBinary(op2, _, _) if op2 != op => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); + } + _ => { + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {} {} {}", l, l, op.node.as_str(), r)); + } + } + }); } else { - span_lint(cx, - ASSIGN_OPS, - expr.span, - "assign operation detected"); + span_lint(cx, ASSIGN_OPS, expr.span, "assign operation detected"); } - }, + } hir::ExprAssign(ref assignee, ref e) => { if let hir::ExprBinary(op, ref l, ref r) = e.node { let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { @@ -104,28 +97,32 @@ impl LateLintPass for AssignOps { } } } - if ops!(op.node, cx, ty, rty, Add:BiAdd, - Sub:BiSub, - Mul:BiMul, - Div:BiDiv, - Rem:BiRem, - And:BiAnd, - Or:BiOr, - BitAnd:BiBitAnd, - BitOr:BiBitOr, - BitXor:BiBitXor, - Shr:BiShr, - Shl:BiShl - ) { - if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { + if ops!(op.node, + cx, + ty, + rty, + Add: BiAdd, + Sub: BiSub, + Mul: BiMul, + Div: BiDiv, + Rem: BiRem, + And: BiAnd, + Or: BiOr, + BitAnd: BiBitAnd, + BitOr: BiBitOr, + BitXor: BiBitXor, + Shr: BiShr, + Shl: BiShl) { + if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), + snippet_opt(cx, rhs.span)) { span_lint_and_then(cx, ASSIGN_OP_PATTERN, expr.span, "manual implementation of an assign operation", |db| { db.span_suggestion(expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r)); + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r)); }); } else { span_lint(cx, @@ -142,17 +139,16 @@ impl LateLintPass for AssignOps { // a = b commutative_op a if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { match op.node { - hir::BiAdd | hir::BiMul | - hir::BiAnd | hir::BiOr | - hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => { + hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd | + hir::BiBitOr => { lint(assignee, l); - }, - _ => {}, + } + _ => {} } } } - }, - _ => {}, + } + _ => {} } } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 9ab806f66ec..8b7952b3746 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -322,7 +322,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { let simplified_stats = terminal_stats(suggestion); let mut improvement = false; for i in 0..32 { - // ignore any "simplifications" that end up requiring a terminal more often than in the original expression + // ignore any "simplifications" that end up requiring a terminal more often + // than in the original expression if stats.terminals[i] < simplified_stats.terminals[i] { continue 'simplified; } @@ -332,17 +333,18 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "this boolean expression contains a logic bug", |db| { - db.span_help(h2q.terminals[i].span, - "this expression can be optimized out by applying \ - boolean operations to the outer expression"); - db.span_suggestion(e.span, - "it would look like the following", - suggest(self.0, suggestion, &h2q.terminals)); - }); + db.span_help(h2q.terminals[i].span, + "this expression can be optimized out by applying boolean operations to the \ + outer expression"); + db.span_suggestion(e.span, + "it would look like the following", + suggest(self.0, suggestion, &h2q.terminals)); + }); // don't also lint `NONMINIMAL_BOOL` return; } - // if the number of occurrences of a terminal decreases or any of the stats decreases while none increases + // if the number of occurrences of a terminal decreases or any of the stats + // decreases while none increases improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || @@ -358,12 +360,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "this boolean expression can be simplified", |db| { - for suggestion in &improvements { - db.span_suggestion(e.span, - "try", - suggest(self.0, suggestion, &h2q.terminals)); - } - }); + for suggestion in &improvements { + db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); + } + }); } } } diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 8ae0d2c97c5..038d888b0ae 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -13,7 +13,8 @@ use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; /// **What it does:** This lint checks for methods with high cyclomatic complexity /// -/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better. +/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM +/// will usually optimize small methods better. /// /// **Known problems:** Sometimes it's hard to find a way to reduce the complexity /// @@ -69,7 +70,7 @@ impl CyclomaticComplexity { returns / 2 }; - if cc + divergence < match_arms + short_circuits { + if cc + divergence < match_arms + short_circuits { report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span); } else { let mut rust_cc = cc + divergence - match_arms - short_circuits; @@ -117,7 +118,7 @@ impl LateLintPass for CyclomaticComplexity { } } -struct CCHelper<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct CCHelper<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { match_arms: u64, divergence: u64, returns: u64, @@ -176,8 +177,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, r if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { cx.sess().span_note_without_error(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): cc \ - = {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.", + (hide this message with `#[allow(cyclomatic_complexity)]`): \ + cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ + Please file a bug report.", cc, narms, div, diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index b941d9a7fca..5d1eb267343 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -84,7 +84,8 @@ impl LateLintPass for Derive { } /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) { +fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, + hash_is_automatically_derived: bool) { if_let_chain! {[ match_path(&trait_ref.path, &paths::HASH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() @@ -137,7 +138,8 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref // Some types are not Clone by default but could be cloned `by hand` if necessary match ty.sty { - TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => { + TypeVariants::TyEnum(def, substs) | + TypeVariants::TyStruct(def, substs) => { for variant in &def.variants { for field in &variant.fields { match field.ty(cx.tcx, substs).sty { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index af1fbaa0f7d..fc9e95f9495 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -108,7 +108,7 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span /// First byte of the current potential match current_word_begin: usize, /// List of lines and their associated span - docs: &'a[(&'a str, Span)], + docs: &'a [(&'a str, Span)], /// Index of the current line we are parsing line: usize, /// Whether we are in a link diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index d9334447226..3d3423a4743 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -42,7 +42,8 @@ impl LintPass for Functions { } impl LateLintPass for Functions { - fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) { + fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, + nodeid: ast::NodeId) { use rustc::hir::map::Node::*; if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 2f98d10dee0..ac6bee00ff5 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -182,7 +182,7 @@ fn used_in_expr(cx: &LateContext, id: hir::def_id::DefId, expr: &hir::Expr) -> b let mut v = UsedVisitor { cx: cx, id: id, - used: false + used: false, }; hir::intravisit::walk_expr(&mut v, expr); v.used diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 5d431e47465..08978e2c5a0 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -608,13 +608,13 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex expr.span, &format!("you seem to want to iterate on a map's {}", kind), |db| { - db.span_suggestion(expr.span, - "use the corresponding method", - format!("for {} in {}.{}() {{ .. }}", - snippet(cx, *pat_span, ".."), - snippet(cx, arg_span, ".."), - kind)); - }); + db.span_suggestion(expr.span, + "use the corresponding method", + format!("for {} in {}.{}() {{ .. }}", + snippet(cx, *pat_span, ".."), + snippet(cx, arg_span, ".."), + kind)); + }); } } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 46bd251016b..d80f9f3d587 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -171,14 +171,14 @@ fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], "you seem to be trying to use match for destructuring a single pattern. \ Consider using `if let`", |db| { - db.span_suggestion(expr.span, - "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); } } @@ -219,14 +219,14 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: "you seem to be trying to use match for destructuring a single pattern. Consider \ using `if let`", |db| { - db.span_suggestion(expr.span, - "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); - }); + db.span_suggestion(expr.span, + "try this", + format!("if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str)); + }); } } } diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 1f627d614ff..4dfb0fe88e0 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -33,7 +33,7 @@ impl LateLintPass for MemForget { if match forgot_ty.ty_adt_def() { Some(def) => def.has_dtor(), - _ => false + _ => false, } { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index c37fbba9250..9dcc8f9d016 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -452,8 +452,8 @@ impl LateLintPass for MethodsPass { explicit_self.span, "methods called `new` usually return `Self`"); } - } - }} + }} + } } } } @@ -1022,9 +1022,7 @@ impl OutType { (&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, - (&OutType::Ref, &hir::Return(ref ty)) => { - matches!(ty.node, hir::TyRptr(_, _)) - } + (&OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)), _ => false, } } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 4147e288c4f..0bed45b0b5b 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -34,10 +34,7 @@ impl LateLintPass for MutMut { if let ExprAddrOf(MutMutable, ref e) = expr.node { if let ExprAddrOf(MutMutable, _) = e.node { - span_lint(cx, - MUT_MUT, - expr.span, - "generally you want to avoid `&mut &mut _` if possible"); + span_lint(cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible"); } else { if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { span_lint(cx, diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 033811841ce..356a46c28c3 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -42,7 +42,8 @@ impl LateLintPass for NeedlessBorrow { span_lint(cx, NEEDLESS_BORROW, e.span, - "this expression borrows a reference that is immediately dereferenced by the compiler"); + "this expression borrows a reference that is immediately dereferenced by the \ + compiler"); } } } diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index fb986409a41..c661fad2c02 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -35,7 +35,7 @@ impl LateLintPass for NegMultiply { (&ExprUnary(..), &ExprUnary(..)) => (), (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), - _ => () + _ => (), } } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index dfaefb39ba0..f400f1b6643 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -100,10 +100,10 @@ impl LateLintPass for NewWithoutDefault { // can't be implemented by default return; } - if decl.inputs.is_empty() && name.as_str() == "new" && - cx.access_levels.is_reachable(id) { - let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id( - cx.tcx.map.get_parent(id))).ty; + if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) { + let self_ty = cx.tcx + .lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))) + .ty; if_let_chain!{[ self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics let Some(ret_ty) = return_ty(cx, id), @@ -143,11 +143,11 @@ fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_ for field in adt_def.all_fields() { let f_ty = field.ty(cx.tcx, substs); if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) { - return false + return false; } } true - }, - _ => false + } + _ => false, } } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index ae3bac00455..a9ac0a24856 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -130,7 +130,9 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp Expr_::ExprTupField(ref inner, _) | Expr_::ExprAddrOf(_, ref inner) | Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()), + Expr_::ExprStruct(_, ref fields, ref base) => { + Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) + } Expr_::ExprCall(ref callee, ref args) => { match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) { Some(Def::Struct(..)) | @@ -140,11 +142,13 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp } Expr_::ExprBlock(ref block) => { if block.stmts.is_empty() { - block.expr.as_ref().and_then(|e| match block.rules { - BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, - BlockCheckMode::DefaultBlock => Some(vec![&**e]), - // in case of compiler-inserted signaling blocks - _ => reduce_expression(cx, e), + block.expr.as_ref().and_then(|e| { + match block.rules { + BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, + BlockCheckMode::DefaultBlock => Some(vec![&**e]), + // in case of compiler-inserted signaling blocks + _ => reduce_expression(cx, e), + } }) } else { None diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index cbb083a3e16..aa8608fb7bd 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -72,11 +72,13 @@ impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { fn visit_pat(&mut self, pat: &'v Pat) { match pat.node { PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), - PatKind::Struct(_, ref fields, _) => for field in fields { - if !field.node.is_shorthand { - self.visit_pat(&field.node.pat); + PatKind::Struct(_, ref fields, _) => { + for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); + } } - }, + } _ => walk_pat(self, pat), } } @@ -193,15 +195,15 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> { span, "binding's name is too similar to existing binding", |diag| { - diag.span_note(existing_name.span, "existing binding defined here"); - if let Some(split) = split_at { - diag.span_help(span, - &format!("separate the discriminating character by an \ + diag.span_note(existing_name.span, "existing binding defined here"); + if let Some(split) = split_at { + diag.span_help(span, + &format!("separate the discriminating character by an \ underscore like: `{}_{}`", &interned_name[..split], &interned_name[split..])); - } - }); + } + }); return; } self.0.names.push(ExistingName { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index c97a64ebf09..fb59c8c61d3 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -125,7 +125,7 @@ impl LateLintPass for RegexPass { fn str_span(base: Span, s: &str, c: usize) -> Span { let mut si = s.char_indices().skip(c); - match (si.next(), si.next()) { + match (si.next(), si.next()) { (Some((l, _)), Some((h, _))) => { Span { lo: base.lo + BytePos(l as u32), @@ -193,7 +193,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { match builder.parse(r) { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + span_help_and_lint(cx, + TRIVIAL_REGEX, + expr.span, "trivial regex", &format!("consider using {}", repl)); } @@ -211,7 +213,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { match builder.parse(&r) { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, + span_help_and_lint(cx, + TRIVIAL_REGEX, + expr.span, "trivial regex", &format!("consider using {}", repl)); } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 3de6719c546..116e1eb1bdc 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -45,7 +45,7 @@ impl LateLintPass for UnsafeNameRemoval { *name, cx, &item.span ); - }, + } ViewPath_::ViewPathList(_, ref path_list_items) => { for path_list_item in path_list_items.iter() { let plid = path_list_item.node; @@ -53,7 +53,7 @@ impl LateLintPass for UnsafeNameRemoval { unsafe_to_safe_check(name, rename, cx, &item.span); }; } - }, + } ViewPath_::ViewPathGlob(_) => {} } } @@ -64,11 +64,10 @@ fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: let old_str = old_name.as_str(); let new_str = new_name.as_str(); if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { - span_lint( - cx, - UNSAFE_REMOVED_FROM_NAME, - *span, - &format!( + span_lint(cx, + UNSAFE_REMOVED_FROM_NAME, + *span, + &format!( "removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 6539b835dc7..a97b593095f 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -64,10 +64,12 @@ impl LateLintPass for UnusedLabel { impl<'v> Visitor<'v> for UnusedLabelVisitor { fn visit_expr(&mut self, expr: &hir::Expr) { match expr.node { - hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => { + hir::ExprBreak(Some(label)) | + hir::ExprAgain(Some(label)) => { self.labels.remove(&label.node.as_str()); } - hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => { + hir::ExprLoop(_, Some(label)) | + hir::ExprWhile(_, _, Some(label)) => { self.labels.insert(label.node.as_str(), expr.span); } _ => (), diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index b183db84d57..f81fcbc38ab 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -50,13 +50,19 @@ pub enum Error { } impl From<io::Error> for Error { - fn from(err: io::Error) -> Self { Error::Io(err) } + fn from(err: io::Error) -> Self { + Error::Io(err) + } } impl From<Utf8Error> for Error { - fn from(err: Utf8Error) -> Self { Error::Utf8(err) } + fn from(err: Utf8Error) -> Self { + Error::Utf8(err) + } } impl From<json::DecoderError> for Error { - fn from(err: json::DecoderError) -> Self { Error::Json(err) } + fn from(err: json::DecoderError) -> Self { + Error::Json(err) + } } pub fn metadata() -> Result<Metadata, Error> { diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index e9c4023e226..88a9e03182c 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -153,7 +153,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { self.eq_qself(ls, rs) && self.eq_path(lp, rp) } - (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), + (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => { + ls == rs && over(l, r, |l, r| self.eq_pat(l, r)) + } (&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => { self.eq_expr(ls, rs) && self.eq_expr(le, re) } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index beec30b32de..5c61a33cec0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -143,9 +143,7 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { } } - let mut apb = AbsolutePathBuffer { - names: vec![], - }; + let mut apb = AbsolutePathBuffer { names: vec![] }; cx.tcx.push_item_path(&mut apb, def_id); @@ -763,7 +761,8 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { end: None, limits: RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { + } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || + match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), diff --git a/src/main.rs b/src/main.rs index 43483e76a0f..041b828e016 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,7 +71,13 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { registry.args_hidden = Some(Vec::new()); clippy_lints::register_plugins(&mut registry); - let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry; + let rustc_plugin::registry::Registry { early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + mir_passes, + .. } = registry; let sess = &state.session; let mut ls = sess.lint_store.borrow_mut(); for pass in early_lint_passes { @@ -111,14 +117,18 @@ pub fn main() { let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); let sys_root = match (home, toolchain) { (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => option_env!("SYSROOT").map(|s| s.to_owned()) - .or(Command::new("rustc").arg("--print") - .arg("sysroot") - .output().ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - ) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"), + _ => { + option_env!("SYSROOT") + .map(|s| s.to_owned()) + .or(Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned())) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") + } }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { @@ -160,7 +170,9 @@ pub fn main() { } fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32> - where P: AsRef<Path>, I: Iterator<Item=String> { + where P: AsRef<Path>, + I: Iterator<Item = String> +{ let mut args = vec!["rustc".to_owned()]; diff --git a/tests/cc_seme.rs b/tests/cc_seme.rs index cc02853c70a..df2579cab57 100644 --- a/tests/cc_seme.rs +++ b/tests/cc_seme.rs @@ -14,7 +14,10 @@ struct Test { fn main() { use Baz::*; - let x = Test { t: Some(0), b: One }; + let x = Test { + t: Some(0), + b: One, + }; match x { Test { t: Some(_), b: One } => unreachable!(), diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 42a7dd96ae2..2e50f7d9241 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -9,7 +9,7 @@ fn run_mode(dir: &'static str, mode: &'static str) { let cfg_mode = mode.parse().ok().expect("Invalid mode"); config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps".to_owned()); if let Ok(name) = var::<&str>("TESTNAME") { - let s : String = name.to_owned(); + let s: String = name.to_owned(); config.filter = Some(s) } diff --git a/tests/consts.rs b/tests/consts.rs index 4b3aba3f6be..81500f9d393 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -16,15 +16,18 @@ use syntax::parse::token::InternedString; use syntax::ptr::P; fn spanned<T>(t: T) -> Spanned<T> { - Spanned{ node: t, span: COMMAND_LINE_SP } + Spanned { + node: t, + span: COMMAND_LINE_SP, + } } fn expr(n: Expr_) -> Expr { - Expr{ + Expr { id: 1, node: n, span: COMMAND_LINE_SP, - attrs: None + attrs: None, } } @@ -40,19 +43,19 @@ fn check(expect: Constant, expr: &Expr) { assert_eq!(Some(expect), constant_simple(expr)) } -const TRUE : Constant = Constant::Bool(true); -const FALSE : Constant = Constant::Bool(false); -const ZERO : Constant = Constant::Int(ConstInt::Infer(0)); -const ONE : Constant = Constant::Int(ConstInt::Infer(1)); -const TWO : Constant = Constant::Int(ConstInt::Infer(2)); +const TRUE: Constant = Constant::Bool(true); +const FALSE: Constant = Constant::Bool(false); +const ZERO: Constant = Constant::Int(ConstInt::Infer(0)); +const ONE: Constant = Constant::Int(ConstInt::Infer(1)); +const TWO: Constant = Constant::Int(ConstInt::Infer(2)); #[test] fn test_lit() { check(TRUE, &lit(LitKind::Bool(true))); check(FALSE, &lit(LitKind::Bool(false))); check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed))); - check(Constant::Str("cool!".into(), StrStyle::Cooked), &lit(LitKind::Str( - InternedString::new("cool!"), StrStyle::Cooked))); + check(Constant::Str("cool!".into(), StrStyle::Cooked), + &lit(LitKind::Str(InternedString::new("cool!"), StrStyle::Cooked))); } #[test] diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 5121fd08628..821279d909c 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -30,11 +30,7 @@ fn dogfood() { config.mode = cfg_mode; - let files = [ - "src/main.rs", - "src/lib.rs", - "clippy_lints/src/lib.rs", - ]; + let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"]; for file in &files { let paths = TestPaths { diff --git a/tests/issue-825.rs b/tests/issue-825.rs index f5c0725f812..76b0250ca0e 100644 --- a/tests/issue-825.rs +++ b/tests/issue-825.rs @@ -22,4 +22,4 @@ fn rust_type_id(name: String) { } } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/tests/matches.rs b/tests/matches.rs index 03cc5281741..74433fc1f56 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -9,7 +9,12 @@ fn test_overlapping() { use clippy::matches::overlapping; use syntax::codemap::DUMMY_SP; - let sp = |s, e| clippy::matches::SpannedRange { span: DUMMY_SP, node: (s, e) }; + let sp = |s, e| { + clippy::matches::SpannedRange { + span: DUMMY_SP, + node: (s, e), + } + }; assert_eq!(None, overlapping::<u8>(&[])); assert_eq!(None, overlapping(&[sp(1, 4)])); diff --git a/tests/used_underscore_binding_macro.rs b/tests/used_underscore_binding_macro.rs index 7a8faa62742..9cd44d44001 100644 --- a/tests/used_underscore_binding_macro.rs +++ b/tests/used_underscore_binding_macro.rs @@ -12,5 +12,5 @@ struct MacroAttributesTest { #[test] fn macro_attributes_test() { - let _ = MacroAttributesTest{_foo: 0}; + let _ = MacroAttributesTest { _foo: 0 }; } -- cgit 1.4.1-3-g733a5 From 11665a0d79c0413e0e3147b036e206a976a1f897 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 01:53:21 +0200 Subject: Dogfood --- src/main.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index 041b828e016..fb2fffab67d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,20 +115,19 @@ pub fn main() { let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - let sys_root = match (home, toolchain) { - (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => { - option_env!("SYSROOT") - .map(|s| s.to_owned()) - .or(Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned())) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") - } + let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { + format!("{}/toolchains/{}", home, toolchain) + } else { + option_env!("SYSROOT") + .map(|s| s.to_owned()) + .or(Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned())) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { -- cgit 1.4.1-3-g733a5 From 44cb6106a7e6b9d090b87cc904e4b1df3b2c164a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 02:07:47 +0200 Subject: Cleanup trailing space --- clippy_lints/src/neg_multiply.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index c661fad2c02..407ba227674 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -49,7 +49,7 @@ fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { val == 1, cx.tcx.expr_ty(exp).is_integral() ], { - span_lint(cx, + span_lint(cx, NEG_MULTIPLY, span, "Negation by multiplying with -1"); -- cgit 1.4.1-3-g733a5 From d85b8062e3e5fea82e8eeed06432d2a0157d589b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 02:09:19 +0200 Subject: Format all `if_let_chain` consistently --- clippy_lints/src/entry.rs | 1 - clippy_lints/src/loops.rs | 40 ++++++++-------- clippy_lints/src/map_clone.rs | 40 ++++++++-------- clippy_lints/src/misc.rs | 44 ++++++++--------- clippy_lints/src/overflow_check_conditional.rs | 32 ++++++------- clippy_lints/src/ranges.rs | 44 ++++++++--------- clippy_lints/src/returns.rs | 27 +++++------ clippy_lints/src/types.rs | 33 ++++++------- clippy_lints/src/utils/mod.rs | 66 ++++++++++++-------------- clippy_lints/src/zero_div_zero.rs | 47 +++++++++--------- 10 files changed, 175 insertions(+), 199 deletions(-) diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index d63d8c67c5d..bc209fd4846 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -120,7 +120,6 @@ impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> { get_item_name(self.cx, self.map) == get_item_name(self.cx, &*params[0]), SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) ], { - span_lint_and_then(self.cx, MAP_ENTRY, self.span, &format!("usage of `contains_key` followed by `insert` on `{}`", self.ty), |db| { if self.sole_expr { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 08978e2c5a0..f3f10fae16e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -667,30 +667,28 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { if let ExprPath(None, ref path) = expr.node { if path.segments.len() == 1 && path.segments[0].name == self.var { // we are referencing our variable! now check if it's as an index - if_let_chain! { - [ - let Some(parexpr) = get_parent_expr(self.cx, expr), - let ExprIndex(ref seqexpr, _) = parexpr.node, - let ExprPath(None, ref seqvar) = seqexpr.node, - seqvar.segments.len() == 1 - ], { - let def_map = self.cx.tcx.def_map.borrow(); - if let Some(def) = def_map.get(&seqexpr.id) { - match def.base_def { - Def::Local(..) | Def::Upvar(..) => { - let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); - return; // no need to walk further - } - Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); - return; // no need to walk further - } - _ => (), + if_let_chain! {[ + let Some(parexpr) = get_parent_expr(self.cx, expr), + let ExprIndex(ref seqexpr, _) = parexpr.node, + let ExprPath(None, ref seqvar) = seqexpr.node, + seqvar.segments.len() == 1 + ], { + let def_map = self.cx.tcx.def_map.borrow(); + if let Some(def) = def_map.get(&seqexpr.id) { + match def.base_def { + Def::Local(..) | Def::Upvar(..) => { + let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id()); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); + return; // no need to walk further } + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].name, None); + return; // no need to walk further + } + _ => (), } } - } + }} // we are not indexing anything, record that self.nonindex = true; return; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index bd81cb2316b..168aade325d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -27,8 +27,7 @@ impl LateLintPass for MapClonePass { if name.node.as_str() == "map" && args.len() == 2 { match args[1].node { ExprClosure(_, ref decl, ref blk, _) => { - if_let_chain! { - [ + if_let_chain! {[ // just one expression in the closure blk.stmts.is_empty(), let Some(ref closure_expr) = blk.expr, @@ -37,32 +36,31 @@ impl LateLintPass for MapClonePass { let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), // the method is being called on a known type (option or iterator) let Some(type_name) = get_type_name(cx, expr, &args[0]) - ], { - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 + ], { + // look for derefs, for .map(|x| *x) + if only_derefs(cx, &*closure_expr, arg_ident) && + // .cloned() only removes one level of indirection, don't lint on more + walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1 + { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + // explicit clone() calls ( .map(|x| x.clone()) ) + else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { + if clone_call.node.as_str() == "clone" && + clone_args.len() == 1 && + match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && + expr_eq_name(&clone_args[0], arg_ident) { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ using `.cloned()`", type_name), &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.node.as_str() == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(&clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } } - } + }} } ExprPath(_, ref path) => { if match_path(path, &paths::CLONE) { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c283dc69b99..3d9795b0c38 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -55,33 +55,31 @@ impl LateLintPass for TopLevelRefPass { } } fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) { - if_let_chain! { - [ + if_let_chain! {[ let StmtDecl(ref d, _) = s.node, let DeclLocal(ref l) = d.node, let PatKind::Binding(BindByRef(_), i, None) = l.pat.node, let Some(ref init) = l.init - ], { - let tyopt = if let Some(ref ty) = l.ty { - format!(": {}", snippet(cx, ty.span, "_")) - } else { - "".to_owned() - }; - span_lint_and_then(cx, - TOPLEVEL_REF_ARG, - l.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", - |db| { - db.span_suggestion(s.span, - "try", - format!("let {}{} = &{};", - snippet(cx, i.span, "_"), - tyopt, - snippet(cx, init.span, "_"))); - } - ); - } - }; + ], { + let tyopt = if let Some(ref ty) = l.ty { + format!(": {}", snippet(cx, ty.span, "_")) + } else { + "".to_owned() + }; + span_lint_and_then(cx, + TOPLEVEL_REF_ARG, + l.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", + |db| { + db.span_suggestion(s.span, + "try", + format!("let {}{} = &{};", + snippet(cx, i.span, "_"), + tyopt, + snippet(cx, init.span, "_"))); + } + ); + }} } } diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 34921bc2c04..5e4386fb778 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -26,14 +26,14 @@ impl LateLintPass for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, - let Expr_::ExprPath(_,ref path1) = ident1.node, - let Expr_::ExprPath(_, ref path2) = ident2.node, - let Expr_::ExprPath(_, ref path3) = second.node, - &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], - cx.tcx.expr_ty(ident1).is_integral(), - cx.tcx.expr_ty(ident2).is_integral() + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, + let Expr_::ExprPath(_, ref path3) = second.node, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() ], { if let BinOp_::BiLt = op.node { if let BinOp_::BiAdd = op2.node { @@ -48,14 +48,14 @@ impl LateLintPass for OverflowCheckConditional { }} if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, - let Expr_::ExprPath(_,ref path1) = ident1.node, - let Expr_::ExprPath(_, ref path2) = ident2.node, - let Expr_::ExprPath(_, ref path3) = first.node, - &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], - cx.tcx.expr_ty(ident1).is_integral(), - cx.tcx.expr_ty(ident2).is_integral() + let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, + let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, + let Expr_::ExprPath(_,ref path1) = ident1.node, + let Expr_::ExprPath(_, ref path2) = ident2.node, + let Expr_::ExprPath(_, ref path3) = first.node, + &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], + cx.tcx.expr_ty(ident1).is_integral(), + cx.tcx.expr_ty(ident2).is_integral() ], { if let BinOp_::BiGt = op.node { if let BinOp_::BiAdd = op2.node { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index e96212a9cef..8eacbadf8df 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -49,29 +49,27 @@ impl LateLintPass for StepByZero { } else if name.as_str() == "zip" && args.len() == 2 { let iter = &args[0].node; let zip_arg = &args[1]; - if_let_chain! { - [ - // .iter() call - let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, - iter_name.as_str() == "iter", - // range expression in .zip() call: 0..x.len() - let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), - is_integer_literal(start, 0), - // .len() call - let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, - len_name.as_str() == "len" && len_args.len() == 1, - // .iter() and .len() called on same Path - let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, - let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, - iter_path == len_path - ], { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - expr.span, - &format!("It is more idiomatic to use {}.iter().enumerate()", - snippet(cx, iter_args[0].span, "_"))); - } - } + if_let_chain! {[ + // .iter() call + let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, + iter_name.as_str() == "iter", + // range expression in .zip() call: 0..x.len() + let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), + is_integer_literal(start, 0), + // .len() call + let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, + len_name.as_str() == "len" && len_args.len() == 1, + // .iter() and .len() called on same Path + let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node, + let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node, + iter_path == len_path + ], { + span_lint(cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); + }} } } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 7bb468166b8..6beed822a81 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -89,19 +89,17 @@ impl ReturnPass { // Check for "let x = EXPR; x" fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { // we need both a let-binding stmt and an expr - if_let_chain! { - [ - let Some(stmt) = block.stmts.last(), - let Some(ref retexpr) = block.expr, - let StmtKind::Decl(ref decl, _) = stmt.node, - let DeclKind::Local(ref local) = decl.node, - local.ty.is_none(), - let Some(ref initexpr) = local.init, - let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, - let ExprKind::Path(_, ref path) = retexpr.node, - match_path_ast(path, &[&id.name.as_str()]), - !in_external_macro(cx, initexpr.span), - ], { + if_let_chain! {[ + let Some(stmt) = block.stmts.last(), + let Some(ref retexpr) = block.expr, + let StmtKind::Decl(ref decl, _) = stmt.node, + let DeclKind::Local(ref local) = decl.node, + let Some(ref initexpr) = local.init, + let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, + let ExprKind::Path(_, ref path) = retexpr.node, + match_path_ast(path, &[&id.name.as_str()]), + !in_external_macro(cx, initexpr.span), + ], { span_note_and_lint(cx, LET_AND_RETURN, retexpr.span, @@ -109,8 +107,7 @@ impl ReturnPass { Consider returning the expression directly.", initexpr.span, "this expression can be directly returned"); - } - } + }} } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c4b810a7880..8a1a13187b3 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -57,24 +57,21 @@ impl LateLintPass for TypePass { if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { if let def::Def::Struct(..) = did.full_def() { if Some(did.def_id()) == cx.tcx.lang_items.owned_box() { - if_let_chain! { - [ - let TyPath(_, ref path) = ast_ty.node, - let Some(ref last) = path.segments.last(), - let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, - let Some(ref vec) = ag.types.get(0), - let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), - let def::Def::Struct(..) = did.full_def(), - match_def_path(cx, did.def_id(), &paths::VEC), - ], - { - span_help_and_lint(cx, - BOX_VEC, - ast_ty.span, - "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", - "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); - } - } + if_let_chain! {[ + let TyPath(_, ref path) = ast_ty.node, + let Some(ref last) = path.segments.last(), + let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, + let Some(ref vec) = ag.types.get(0), + let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), + let def::Def::Struct(..) = did.full_def(), + match_def_path(cx, did.def_id(), &paths::VEC), + ], { + span_help_and_lint(cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", + "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); + }} } else if match_def_path(cx, did.def_id(), &paths::LINKED_LIST) { span_help_and_lint(cx, LINKEDLIST, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 5c61a33cec0..a2b2ecfbcc0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -30,16 +30,13 @@ pub type MethodArgs = HirVec<P<Expr>>; /// Produce a nested chain of if-lets and ifs from the patterns: /// -/// if_let_chain! { -/// [ -/// let Some(y) = x, -/// y.len() == 2, -/// let Some(z) = y, -/// ], -/// { -/// block -/// } -/// } +/// if_let_chain! {[ +/// let Some(y) = x, +/// y.len() == 2, +/// let Some(z) = y, +/// ], { +/// block +/// }} /// /// becomes /// @@ -323,14 +320,13 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { /// Checks if a `let` decl is from a `for` loop desugaring. pub fn is_from_for_desugar(decl: &Decl) -> bool { - if_let_chain! { - [ - let DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node - ], - { return true; } - }; + if_let_chain! {[ + let DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node + ], { + return true; + }} false } @@ -821,23 +817,21 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { - if_let_chain! { - [ - let ExprMatch(ref iterexpr, ref arms, _) = expr.node, - let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let ExprLoop(ref block, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, - somepats.len() == 1 - ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); - } - } + if_let_chain! {[ + let ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), + let ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); + }} None } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 902d84d4dd3..041ac94836c 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -30,30 +30,27 @@ impl LintPass for ZeroDivZeroPass { impl LateLintPass for ZeroDivZeroPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // check for instances of 0.0/0.0 - if_let_chain! { - [ - let ExprBinary(ref op, ref left, ref right) = expr.node, - let BinOp_::BiDiv = op.node, - // TODO - constant_simple does not fold many operations involving floats. - // That's probably fine for this lint - it's pretty unlikely that someone would - // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), - let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), - let Some(0.0) = lhs_value.parse().ok(), - let Some(0.0) = rhs_value.parse().ok() - ], - { - // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, - // match the precision of the literals that are given. - let float_type = match (lhs_width, rhs_width) { - (FloatWidth::F64, _) - | (_, FloatWidth::F64) => "f64", - _ => "f32" - }; - span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, - "constant division of 0.0 with 0.0 will always result in NaN", - &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); - } - } + if_let_chain! {[ + let ExprBinary(ref op, ref left, ref right) = expr.node, + let BinOp_::BiDiv = op.node, + // TODO - constant_simple does not fold many operations involving floats. + // That's probably fine for this lint - it's pretty unlikely that someone would + // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. + let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), + let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), + let Some(0.0) = lhs_value.parse().ok(), + let Some(0.0) = rhs_value.parse().ok() + ], { + // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, + // match the precision of the literals that are given. + let float_type = match (lhs_width, rhs_width) { + (FloatWidth::F64, _) + | (_, FloatWidth::F64) => "f64", + _ => "f32" + }; + span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, + "constant division of 0.0 with 0.0 will always result in NaN", + &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); + }} } } -- cgit 1.4.1-3-g733a5 From 489576437d5c72029c7af77fc6921b5946cd22e6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 17:09:51 +0200 Subject: Cleanup dependencies and features --- Cargo.toml | 7 +------ clippy_lints/src/lib.rs | 15 +++++++-------- src/lib.rs | 46 +++------------------------------------------- src/main.rs | 2 -- 4 files changed, 11 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1ea542c7737..12c74b653e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,21 +23,16 @@ name = "cargo-clippy" test = false [dependencies] -regex-syntax = "0.3.0" regex_macros = { version = "0.1.33", optional = true } -semver = "0.2.1" -toml = "0.1" -unicode-normalization = "0.1" -quine-mc_cluskey = "0.2.2" # begin automatic update clippy_lints = { version = "0.0.75", path = "clippy_lints" } # end automatic update -rustc-serialize = "0.3" [dev-dependencies] compiletest_rs = "0.2.0" lazy_static = "0.1.15" regex = "0.1.56" +rustc-serialize = "0.3" [features] debugging = [] diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 857e11b0bd3..42a35e7009b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,17 +1,16 @@ // error-pattern:cargo-clippy -#![feature(type_macros)] -#![feature(plugin_registrar, box_syntax)] -#![feature(rustc_private, collections)] -#![feature(iter_arith)] +#![feature(box_syntax)] +#![feature(collections)] #![feature(custom_attribute)] -#![feature(slice_patterns)] +#![feature(iter_arith)] #![feature(question_mark)] +#![feature(rustc_private)] +#![feature(slice_patterns)] #![feature(stmt_expr_attributes)] -#![allow(indexing_slicing, shadow_reuse, unknown_lints)] +#![feature(type_macros)] -extern crate rustc_driver; -extern crate getopts; +#![allow(indexing_slicing, shadow_reuse, unknown_lints)] #[macro_use] extern crate syntax; diff --git a/src/lib.rs b/src/lib.rs index f9a6588e904..f5229d3cb39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,55 +1,15 @@ // error-pattern:cargo-clippy -#![feature(type_macros)] -#![feature(plugin_registrar, box_syntax)] -#![feature(rustc_private, collections)] -#![feature(custom_attribute)] -#![feature(slice_patterns)] -#![feature(question_mark)] -#![feature(stmt_expr_attributes)] -#![allow(indexing_slicing, shadow_reuse, unknown_lints)] - -#[macro_use] -extern crate syntax; -#[macro_use] -extern crate rustc; - -extern crate toml; - -// Only for the compile time checking of paths -extern crate core; -extern crate collections; - -// for unicode nfc normalization -extern crate unicode_normalization; - -// for semver check in attrs.rs -extern crate semver; - -// for regex checking -extern crate regex_syntax; - -// for finding minimal boolean expressions -extern crate quine_mc_cluskey; +#![feature(plugin_registrar)] +#![feature(rustc_private)] +#![allow(unknown_lints)] extern crate rustc_plugin; -extern crate rustc_const_eval; -extern crate rustc_const_math; use rustc_plugin::Registry; extern crate clippy_lints; pub use clippy_lints::*; -macro_rules! declare_restriction_lint { - { pub $name:tt, $description:tt } => { - declare_lint! { pub $name, Allow, $description } - }; -} - -mod reexport { - pub use syntax::ast::{Name, NodeId}; -} - #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { register_plugins(reg); diff --git a/src/main.rs b/src/main.rs index fb2fffab67d..de3361d514f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] -#![feature(slice_patterns)] extern crate rustc_driver; extern crate getopts; @@ -9,7 +8,6 @@ extern crate rustc; extern crate syntax; extern crate rustc_plugin; extern crate clippy_lints; -extern crate rustc_serialize; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; use rustc::session::{config, Session}; -- cgit 1.4.1-3-g733a5 From dd99a88289f12c00f95981f068c3177b3324b72c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 6 Jun 2016 18:55:22 +0200 Subject: Dogfood inside `if_let_chain!` --- clippy_lints/src/matches.rs | 6 +++--- clippy_lints/src/regex.rs | 10 ++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index d80f9f3d587..fab15ac3238 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -339,15 +339,15 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { Some(pats.iter().filter_map(|pat| { if_let_chain! {[ let PatKind::Range(ref lhs, ref rhs) = pat.node, - let Ok(lhs) = eval_const_expr_partial(cx.tcx, &lhs, ExprTypeChecked, None), - let Ok(rhs) = eval_const_expr_partial(cx.tcx, &rhs, ExprTypeChecked, None) + let Ok(lhs) = eval_const_expr_partial(cx.tcx, lhs, ExprTypeChecked, None), + let Ok(rhs) = eval_const_expr_partial(cx.tcx, rhs, ExprTypeChecked, None) ], { return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); }} if_let_chain! {[ let PatKind::Lit(ref value) = pat.node, - let Ok(value) = eval_const_expr_partial(cx.tcx, &value, ExprTypeChecked, None) + let Ok(value) = eval_const_expr_partial(cx.tcx, value, ExprTypeChecked, None) ], { return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); }} diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index fb59c8c61d3..8b84f94fa8e 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -104,13 +104,11 @@ impl LateLintPass for RegexPass { let Some(def) = cx.tcx.def_map.borrow().get(&fun.id), ], { let def_id = def.def_id(); - if match_def_path(cx, def_id, &paths::REGEX_NEW) { + if match_def_path(cx, def_id, &paths::REGEX_NEW) || + match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { check_regex(cx, &args[0], true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) { - check_regex(cx, &args[0], false); - } else if match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { - check_regex(cx, &args[0], true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { + } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) || + match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { check_regex(cx, &args[0], false); } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { check_set(cx, &args[0], true); -- cgit 1.4.1-3-g733a5 From d80436f9f21cf2d6d95e585696a018077ec63ef3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 10 Jun 2016 13:43:32 +0200 Subject: Add a issue template and specify a *recent* nightly is needed --- .github/ISSUE_TEMPLATE.md | 8 ++++++++ README.md | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..a19cb5d2c7c --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,8 @@ +<!-- +Hi there! Whether you've come to make a suggestion for a new lint, an improvement to an existing lint or to report a bug or a false positive in Clippy, you've come to the right place. + +If you want to report that Clippy does not compile, please be sure to be using the *latest version* of *Rust nightly*! Compiler plugins are highly unstable and will only work with a nightly Rust for now. If you are but still have a problem, please let us now! + +Thank you for using Clippy! + +Write your comment below this line: --> diff --git a/README.md b/README.md index 2e40f6ed74c..ffda505eeac 100644 --- a/README.md +++ b/README.md @@ -180,10 +180,10 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ### As a Compiler Plugin -Compiler plugins are highly unstable and will only work with a nightly Rust for now. -Since stable Rust is backwards compatible, you should be able to compile -your stable programs with nightly Rust with clippy plugged in to circumvent -this. +Compiler plugins are highly unstable and will only work with a *recent* nightly +Rust for now. Since stable Rust is backwards compatible, you should be able to +compile your stable programs with nightly Rust with clippy plugged in to +circumvent this. Add in your `Cargo.toml`: -- cgit 1.4.1-3-g733a5 From 350f3a7fe5948feea550ff6481cb39e5c42b7819 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 10 Jun 2016 19:47:10 +0200 Subject: Rustup to *1.11.0-nightly (7d2f75a95 2016-06-09)* --- clippy_lints/src/drop_ref.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 4 ++-- clippy_lints/src/let_if_seq.rs | 12 ++++++------ clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/needless_bool.rs | 4 ++-- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/types.rs | 6 +++--- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_ref.rs index 69156f15f31..268497f99d4 100644 --- a/clippy_lints/src/drop_ref.rs +++ b/clippy_lints/src/drop_ref.rs @@ -35,7 +35,7 @@ impl LateLintPass for DropRefPass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(None, _) = path.node { - let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + let def_id = cx.tcx.expect_def(path.id).def_id(); if match_def_path(cx, def_id, &paths::DROP) { if args.len() != 1 { return; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 37a89069d19..5a4185ec63b 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -44,14 +44,14 @@ impl EnumGlobUse { if let ItemUse(ref item_use) = item.node { if let ViewPath_::ViewPathGlob(_) = item_use.node { if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) { - if let Some(node_id) = cx.tcx.map.as_local_node_id(def.def_id()) { + if let Some(node_id) = cx.tcx.map.as_local_node_id(def.full_def().def_id()) { if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) { if let ItemEnum(..) = it.node { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } } else { - let child = cx.sess().cstore.item_children(def.def_id()); + let child = cx.sess().cstore.item_children(def.full_def().def_id()); if let Some(child) = child.first() { if let DefLike::DlDef(Def::Variant(..)) = child.def { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index ac6bee00ff5..0ed3248228f 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -69,15 +69,15 @@ impl LateLintPass for LetIfSeq { let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id), let hir::StmtExpr(ref if_, _) = expr.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, - !used_in_expr(cx, def.def_id(), cond), - let Some(value) = check_assign(cx, def.def_id(), then), - !used_in_expr(cx, def.def_id(), value), + !used_in_expr(cx, def.full_def().def_id(), cond), + let Some(value) = check_assign(cx, def.full_def().def_id(), then), + !used_in_expr(cx, def.full_def().def_id(), value), ], { let span = codemap::mk_sp(stmt.span.lo, if_.span.hi); let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { if let hir::ExprBlock(ref else_) = else_.node { - if let Some(default) = check_assign(cx, def.def_id(), else_) { + if let Some(default) = check_assign(cx, def.full_def().def_id(), else_) { (else_.stmts.len() > 1, default) } else if let Some(ref default) = decl.init { (true, &**default) @@ -139,7 +139,7 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> { if_let_chain! {[ let hir::ExprPath(None, _) = expr.node, let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id), - self.id == def.def_id(), + self.id == def.full_def().def_id(), ], { self.used = true; return; @@ -156,7 +156,7 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir:: let hir::ExprAssign(ref var, ref value) = expr.node, let hir::ExprPath(None, _) = var.node, let Some(def) = cx.tcx.def_map.borrow().get(&var.id), - decl == def.def_id(), + decl == def.full_def().def_id(), ], { let mut v = UsedVisitor { cx: cx, diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 4dfb0fe88e0..79a71436368 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -27,7 +27,7 @@ impl LateLintPass for MemForget { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(None, _) = path_expr.node { - let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + let def_id = cx.tcx.expect_def(path_expr.id).def_id(); if match_def_path(cx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.tcx.expr_ty(&args[0]); diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index eaba19b08e4..a88324aaf50 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -55,7 +55,7 @@ enum MinMax { fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(None, _) = path.node { - let def_id = cx.tcx.def_map.borrow()[&path.id].def_id(); + let def_id = cx.tcx.expect_def(path.id).def_id(); if match_def_path(cx, def_id, &paths::CMP_MIN) { fetch_const(args, MinMax::Min) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index f95d6f5c9c1..5f912366770 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -155,8 +155,8 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { - ([], Some(e)) => fetch_bool_expr(&**e), - ([ref e], None) => { + (&[], Some(e)) => fetch_bool_expr(&**e), + (&[ref e], None) => { if let StmtSemi(ref e, _) = e.node { if let ExprRet(_) = e.node { fetch_bool_expr(&**e) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 8b84f94fa8e..c2c37fcf686 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -103,7 +103,7 @@ impl LateLintPass for RegexPass { args.len() == 1, let Some(def) = cx.tcx.def_map.borrow().get(&fun.id), ], { - let def_id = def.def_id(); + let def_id = def.full_def().def_id(); if match_def_path(cx, def_id, &paths::REGEX_NEW) || match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { check_regex(cx, &args[0], true); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2217fd59bd9..5d3f27b074b 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -60,7 +60,7 @@ impl LateLintPass for Transmute { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(None, _) = path_expr.node { - let def_id = cx.tcx.def_map.borrow()[&path_expr.id].def_id(); + let def_id = cx.tcx.expect_def(path_expr.id).def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE) { let from_ty = cx.tcx.expr_ty(&args[0]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 8a1a13187b3..83e2c1b549c 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -56,7 +56,7 @@ impl LateLintPass for TypePass { } if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { if let def::Def::Struct(..) = did.full_def() { - if Some(did.def_id()) == cx.tcx.lang_items.owned_box() { + if Some(did.full_def().def_id()) == cx.tcx.lang_items.owned_box() { if_let_chain! {[ let TyPath(_, ref path) = ast_ty.node, let Some(ref last) = path.segments.last(), @@ -64,7 +64,7 @@ impl LateLintPass for TypePass { let Some(ref vec) = ag.types.get(0), let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), let def::Def::Struct(..) = did.full_def(), - match_def_path(cx, did.def_id(), &paths::VEC), + match_def_path(cx, did.full_def().def_id(), &paths::VEC), ], { span_help_and_lint(cx, BOX_VEC, @@ -72,7 +72,7 @@ impl LateLintPass for TypePass { "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`", "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation."); }} - } else if match_def_path(cx, did.def_id(), &paths::LINKED_LIST) { + } else if match_def_path(cx, did.full_def().def_id(), &paths::LINKED_LIST) { span_help_and_lint(cx, LINKEDLIST, ast_ty.span, -- cgit 1.4.1-3-g733a5 From 17dd0da9da6eebbb83856bd6a76ac767be0217f0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 10 Jun 2016 19:48:56 +0200 Subject: Bump to 0.0.76 --- CHANGELOG.md | 1 + Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4009246507c..81102a900e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## 0.0.76 — TBD +* Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)* * `cargo clippy` now automatically defines the `clippy` feature ## 0.0.75 — 2016-06-08 diff --git a/Cargo.toml b/Cargo.toml index 12c74b653e3..60862865b43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.75" +version = "0.0.76" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -25,7 +25,7 @@ test = false [dependencies] regex_macros = { version = "0.1.33", optional = true } # begin automatic update -clippy_lints = { version = "0.0.75", path = "clippy_lints" } +clippy_lints = { version = "0.0.76", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 793e26ad06d..2f748d1ec3c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.75" +version = "0.0.76" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From b8746901bd2615a01053f668398f6ba3fbead584 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 13 Jun 2016 12:09:14 +0200 Subject: s/npm install remark/npm install remark-cli --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c1b91fd75fe..4329bb25804 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ install: - . $HOME/.nvm/nvm.sh - nvm install stable - nvm use stable - - npm install remark remark-lint + - npm install remark-cli remark-lint script: - set -e -- cgit 1.4.1-3-g733a5 From e6cbe970c83f623609cad396aa8113e2340adea9 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 15 Jun 2016 16:27:56 +0200 Subject: Don't use identifier hygiene in HIR --- clippy_lints/src/misc.rs | 47 ++++++++++++++++++--------- clippy_lints/src/shadow.rs | 9 +++-- tests/compile-fail/used_underscore_binding.rs | 17 ++++++++-- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 3d9795b0c38..49532576469 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -10,8 +10,8 @@ use rustc_const_math::ConstFloat; use syntax::codemap::{Span, Spanned, ExpnFormat}; use syntax::ptr::P; use utils::{ - get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet, - span_lint, span_lint_and_then, walk_ptrs_ty + get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path, + snippet, span_lint, span_lint_and_then, walk_ptrs_ty }; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. @@ -405,15 +405,18 @@ impl LateLintPass for UsedUnderscoreBinding { } let binding = match expr.node { ExprPath(_, ref path) => { - let segment = path.segments + let binding = path.segments .last() .expect("path should always have at least one segment") - .name; - if segment.as_str().starts_with('_') && - !segment.as_str().starts_with("__") && - segment != segment.unhygienize() && // not in bang macro - is_used(cx, expr) { - Some(segment.as_str()) + .name + .as_str(); + if binding.starts_with('_') && + !binding.starts_with("__") && + binding != "_result" && // FIXME: #944 + is_used(cx, expr) && + // don't lint if the declaration is in a macro + non_macro_local(cx, &cx.tcx.expect_def(expr.id)) { + Some(binding) } else { None } @@ -429,13 +432,11 @@ impl LateLintPass for UsedUnderscoreBinding { _ => None, }; if let Some(binding) = binding { - if binding != "_result" { // FIXME: #944 - span_lint(cx, - USED_UNDERSCORE_BINDING, - expr.span, - &format!("used binding `{}` which is prefixed with an underscore. A leading \ - underscore signals that a binding will not be used.", binding)); - } + span_lint(cx, + USED_UNDERSCORE_BINDING, + expr.span, + &format!("used binding `{}` which is prefixed with an underscore. A leading \ + underscore signals that a binding will not be used.", binding)); } } } @@ -463,3 +464,17 @@ fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool { }) }) } + +/// Test whether `def` is a variable defined outside a macro. +fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { + match *def { + def::Def::Local(_, id) | def::Def::Upvar(_, id, _, _) => { + if let Some(span) = cx.tcx.map.opt_span(id) { + !in_macro(cx, span) + } else { + true + } + } + _ => false, + } +} diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 0954d92cf9a..9838ce0202c 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -66,7 +66,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) { let mut bindings = Vec::new(); for arg in &decl.inputs { if let PatKind::Binding(_, ident, _) = arg.pat.node { - bindings.push((ident.node.unhygienize(), ident.span)) + bindings.push((ident.node, ident.span)) } } check_block(cx, block, &mut bindings); @@ -120,7 +120,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind // TODO: match more stuff / destructuring match pat.node { PatKind::Binding(_, ref ident, ref inner) => { - let name = ident.node.unhygienize(); + let name = ident.node; if is_binding(cx, pat) { let mut new_binding = true; for tup in bindings.iter_mut() { @@ -139,7 +139,6 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind check_pat(cx, p, init, span, bindings); } } - // PatEnum(Path, Option<Vec<P<Pat>>>), PatKind::Struct(_, ref pfields, _) => { if let Some(ref init_struct) = *init { if let ExprStruct(_, ref efields, _) = init_struct.node { @@ -327,7 +326,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - !path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name + !path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() } struct ContainsSelf { @@ -337,7 +336,7 @@ struct ContainsSelf { impl<'v> Visitor<'v> for ContainsSelf { fn visit_name(&mut self, _: Span, name: Name) { - if self.name == name.unhygienize() { + if self.name == name { self.result = true; } } diff --git a/tests/compile-fail/used_underscore_binding.rs b/tests/compile-fail/used_underscore_binding.rs index c571906c53b..c3700d1b1cd 100644 --- a/tests/compile-fail/used_underscore_binding.rs +++ b/tests/compile-fail/used_underscore_binding.rs @@ -5,14 +5,27 @@ #![allow(blacklisted_name)] #![deny(used_underscore_binding)] +macro_rules! test_macro { + () => {{ + let _foo = 42; + _foo + 1 + }} +} + /// Test that we lint if we use a binding with a single leading underscore fn prefix_underscore(_foo: u32) -> u32 { _foo + 1 //~ ERROR used binding `_foo` which is prefixed with an underscore } -/// Test that we lint even if the use is within a macro expansion +/// Test that we lint if we use a `_`-variable defined outside within a macro expansion fn in_macro(_foo: u32) { - println!("{}", _foo); //~ ERROR used binding `_foo` which is prefixed with an underscore + println!("{}", _foo); + //~^ ERROR used binding `_foo` which is prefixed with an underscore + assert_eq!(_foo, _foo); + //~^ ERROR used binding `_foo` which is prefixed with an underscore + //~| ERROR used binding `_foo` which is prefixed with an underscore + + test_macro!() + 1; } // Struct for testing use of fields prefixed with an underscore -- cgit 1.4.1-3-g733a5 From 555e4555b15b26122ad084ad5983b565200c5992 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 01:29:03 -0700 Subject: Add tests for slice_iter_nth --- tests/compile-fail/methods.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 89267462f5d..591a0c1e3df 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -309,6 +309,15 @@ fn or_fun_call() { //~|SUGGESTION btree.entry(42).or_insert_with(String::new); } +/// Checks implementation of `SLICE_ITER_NTH` lint +fn slice_iter_nth() { + let some_vec = vec![0, 1, 2, 3]; + let bad = &some_vec[..].iter().nth(3); + //~^ERROR called `.iter().nth()` on a slice. + + let ok = some_vec.iter().nth(3); // This should be okay, since some_vec is not a slice +} + #[allow(similar_names)] fn main() { use std::io; -- cgit 1.4.1-3-g733a5 From 7764dc5ef42754c2704217ebec4a82b964835f54 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 01:36:11 -0700 Subject: Add slice_iter_nth lint --- CHANGELOG.md | 1 + README.md | 3 ++- clippy_lints/src/lib.rs | 1 + clippy_lints/src/methods.rs | 39 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81102a900e5..30702057bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -234,6 +234,7 @@ All notable changes to this project will be documented in this file. [`single_char_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern [`single_match`]: https://github.com/Manishearth/rust-clippy/wiki#single_match [`single_match_else`]: https://github.com/Manishearth/rust-clippy/wiki#single_match_else +[`slice_iter_nth`]: https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth [`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string [`string_add`]: https://github.com/Manishearth/rust-clippy/wiki#string_add [`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign diff --git a/README.md b/README.md index ffda505eeac..5707b0ee70c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 152 lints included in this crate: +There are 153 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -140,6 +140,7 @@ name [single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead +[slice_iter_nth](https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth) | warn | using `.iter().nth()` on a slice [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 42a35e7009b..072326b1a08 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -357,6 +357,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, + methods::SLICE_ITER_NTH, methods::TEMPORARY_CSTRING_AS_PTR, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9dcc8f9d016..b7d98b5fdd6 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -312,6 +312,28 @@ declare_lint! { "getting the inner pointer of a temporary `CString`" } +/// **What it does:** This lint checks for use of `.iter().nth()` on a slice. +/// +/// **Why is this bad?** `.get()` is more efficient and more readable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let some_slice = &[0, 1, 2, 3][..]; +/// let third_elem = some_slice.iter().nth(3); +/// ``` +/// The correct use would be: +/// ```rust +/// let some_slice = &[0, 1, 2, 3][..]; +/// let third_elem = some_slice.get(3); +/// ``` +declare_lint! { + pub SLICE_ITER_NTH, + Warn, + "using `.iter().nth()` on a slice" +} + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -330,7 +352,8 @@ impl LintPass for MethodsPass { NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR) + TEMPORARY_CSTRING_AS_PTR, + SLICE_ITER_NTH) } } @@ -363,6 +386,8 @@ impl LateLintPass for MethodsPass { lint_extend(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); + } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { + lint_slice_iter_nth(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &name.node.as_str(), args); @@ -616,6 +641,18 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr }} } +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +fn lint_slice_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs){ + // lint if the caller of `.iter().nth` is a `slice` + if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { + span_lint(cx, + SLICE_ITER_NTH, + expr.span, + "called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable"); + } +} + fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { -- cgit 1.4.1-3-g733a5 From 74025be59db10a5c8f5c0b5175b250730b4d4ca6 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 02:02:00 -0700 Subject: Make iter_nth work for `Vec`s too --- CHANGELOG.md | 2 +- README.md | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/methods.rs | 33 +++++++++++++++++++++------------ tests/compile-fail/methods.rs | 26 ++++++++++++++++++++++---- 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30702057bdb..790bbc04691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -172,6 +172,7 @@ All notable changes to this project will be documented in this file. [`invalid_upcast_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons [`items_after_statements`]: https://github.com/Manishearth/rust-clippy/wiki#items_after_statements [`iter_next_loop`]: https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop +[`iter_nth`]: https://github.com/Manishearth/rust-clippy/wiki#iter_nth [`len_without_is_empty`]: https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty [`len_zero`]: https://github.com/Manishearth/rust-clippy/wiki#len_zero [`let_and_return`]: https://github.com/Manishearth/rust-clippy/wiki#let_and_return @@ -234,7 +235,6 @@ All notable changes to this project will be documented in this file. [`single_char_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern [`single_match`]: https://github.com/Manishearth/rust-clippy/wiki#single_match [`single_match_else`]: https://github.com/Manishearth/rust-clippy/wiki#single_match_else -[`slice_iter_nth`]: https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth [`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string [`string_add`]: https://github.com/Manishearth/rust-clippy/wiki#string_add [`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign diff --git a/README.md b/README.md index 5707b0ee70c..85e9ed70bf8 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ name [invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[iter_nth](https://github.com/Manishearth/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a slice or Vec [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block @@ -140,7 +141,6 @@ name [single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead -[slice_iter_nth](https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth) | warn | using `.iter().nth()` on a slice [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 072326b1a08..d64f653dd4c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -349,6 +349,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::CLONE_ON_COPY, methods::EXTEND_FROM_SLICE, methods::FILTER_NEXT, + methods::ITER_NTH, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, methods::OPTION_MAP_UNWRAP_OR, @@ -357,7 +358,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, - methods::SLICE_ITER_NTH, methods::TEMPORARY_CSTRING_AS_PTR, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index b7d98b5fdd6..da1420c3add 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -312,7 +312,7 @@ declare_lint! { "getting the inner pointer of a temporary `CString`" } -/// **What it does:** This lint checks for use of `.iter().nth()` on a slice. +/// **What it does:** This lint checks for use of `.iter().nth()` on a slice or Vec. /// /// **Why is this bad?** `.get()` is more efficient and more readable. /// @@ -320,18 +320,20 @@ declare_lint! { /// /// **Example:** /// ```rust -/// let some_slice = &[0, 1, 2, 3][..]; -/// let third_elem = some_slice.iter().nth(3); +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.iter().nth(3); +/// let bad_slice = &some_vec[..].iter().nth(3); /// ``` /// The correct use would be: /// ```rust -/// let some_slice = &[0, 1, 2, 3][..]; -/// let third_elem = some_slice.get(3); +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.get(3); +/// let bad_slice = &some_vec[..].get(3); /// ``` declare_lint! { - pub SLICE_ITER_NTH, + pub ITER_NTH, Warn, - "using `.iter().nth()` on a slice" + "using `.iter().nth()` on a slice or Vec" } impl LintPass for MethodsPass { @@ -353,7 +355,7 @@ impl LintPass for MethodsPass { SINGLE_CHAR_PATTERN, SEARCH_IS_SOME, TEMPORARY_CSTRING_AS_PTR, - SLICE_ITER_NTH) + ITER_NTH) } } @@ -387,7 +389,7 @@ impl LateLintPass for MethodsPass { } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { - lint_slice_iter_nth(cx, expr, arglists[0]); + lint_iter_nth(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &name.node.as_str(), args); @@ -643,14 +645,21 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec -fn lint_slice_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs){ - // lint if the caller of `.iter().nth` is a `slice` +fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs){ + // lint if the caller of `.iter().nth()` is a `slice` if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { span_lint(cx, - SLICE_ITER_NTH, + ITER_NTH, expr.span, "called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable"); } + // lint if the caller of `.iter().nth()` is a `Vec` + else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) { + span_lint(cx, + ITER_NTH, + expr.span, + "called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable"); + } } fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 591a0c1e3df..811b9116143 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -128,6 +128,16 @@ fn option_methods() { } +/// Struct to generate false positives for things with .iter() +#[derive(Copy, Clone)] +struct HasIter; + +impl HasIter { + fn iter(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } +} + /// Struct to generate false positive for Iterator-based lints #[derive(Copy, Clone)] struct IteratorFalsePositives { @@ -154,6 +164,10 @@ impl IteratorFalsePositives { fn rposition(self) -> Option<u32> { Some(self.foo) } + + fn nth(self, n: usize) -> Option<u32> { + Some(self.foo) + } } /// Checks implementation of `FILTER_NEXT` lint @@ -309,13 +323,17 @@ fn or_fun_call() { //~|SUGGESTION btree.entry(42).or_insert_with(String::new); } -/// Checks implementation of `SLICE_ITER_NTH` lint -fn slice_iter_nth() { +/// Checks implementation of `ITER_NTH` lint +fn iter_nth() { let some_vec = vec![0, 1, 2, 3]; - let bad = &some_vec[..].iter().nth(3); + let bad_vec = some_vec.iter().nth(3); + //~^ERROR called `.iter().nth()` on a Vec. + let bad_slice = &some_vec[..].iter().nth(3); //~^ERROR called `.iter().nth()` on a slice. - let ok = some_vec.iter().nth(3); // This should be okay, since some_vec is not a slice + let false_positive = HasIter; + let ok = false_positive.iter().nth(3); + // ^This should be okay, because false_positive is not a slice or Vec } #[allow(similar_names)] -- cgit 1.4.1-3-g733a5 From 5726216c9b0756c8a94b6d8af9418b5544afa8bc Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 8 Jun 2016 15:03:30 +0200 Subject: `Skip` for `Chars` doesn't help us b/c of the `ExactSizeIterator` bound --- clippy_lints/src/enum_variants.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 67a8495e155..72553bd5d45 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -30,17 +30,6 @@ fn var2str(var: &Variant) -> InternedString { var.node.name.name.as_str() } -// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 -// fn partial_match(pre: &str, name: &str) -> usize { -// // skip(1) to ensure that the prefix never takes the whole variant name -// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } -// -// fn partial_rmatch(post: &str, name: &str) -> usize { -// // skip(1) to ensure that the postfix never takes the whole variant name -// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } - fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next_back(); // make sure the name is never fully matched -- cgit 1.4.1-3-g733a5 From 32894d503e720130cc6fd0fa193afa2d9f7d4431 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 8 Jun 2016 15:32:30 +0200 Subject: lint enum variants names that start or end with their enum's name --- clippy_lints/src/enum_variants.rs | 17 ++++++++++++++++- tests/compile-fail/enum_variants.rs | 11 ++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 72553bd5d45..ec318a37952 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::parse::token::InternedString; -use utils::span_help_and_lint; +use utils::{span_help_and_lint, span_lint}; use utils::{camel_case_from, camel_case_until}; /// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters @@ -30,12 +30,14 @@ fn var2str(var: &Variant) -> InternedString { var.node.name.name.as_str() } +/// Returns the number of chars that match from the start fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next_back(); // make sure the name is never fully matched pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() } +/// Returns the number of chars that match from the end fn partial_rmatch(post: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next(); // make sure the name is never fully matched @@ -46,7 +48,20 @@ impl EarlyLintPass for EnumVariantNames { // FIXME: #600 #[allow(while_let_on_iterator)] fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + let item_name = item.ident.name.as_str(); + let item_name_chars = item_name.chars().count(); if let ItemKind::Enum(ref def, _) = item.node { + for var in &def.variants { + let name = var2str(var); + let matching = partial_match(&item_name, &name); + let rmatching = partial_rmatch(&item_name, &name); + if matching == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name starts with the enum's name"); + } + if rmatching == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name ends with the enum's name"); + } + } if def.variants.len() < 2 { return; } diff --git a/tests/compile-fail/enum_variants.rs b/tests/compile-fail/enum_variants.rs index 6589bd35fd3..ed7f7823f8f 100644 --- a/tests/compile-fail/enum_variants.rs +++ b/tests/compile-fail/enum_variants.rs @@ -11,7 +11,8 @@ enum FakeCallType2 { } enum Foo { - cFoo, cBar, + cFoo, //~ ERROR: Variant name ends with the enum's name + cBar, } enum BadCallType { //~ ERROR: All variants have the same prefix: `CallType` @@ -68,4 +69,12 @@ enum NonCaps { //~ ERROR: All variants have the same prefix: `Prefix` PrefixCake, } +enum Stuff { + BadStuff, //~ ERROR: Variant name ends with the enum's name +} + +enum Food { + FoodGood, //~ ERROR: Variant name starts with the enum's name +} + fn main() {} -- cgit 1.4.1-3-g733a5 From 8356d2fb2170bf10ecc29edff2a4c0deb569af74 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 8 Jun 2016 17:43:27 +0200 Subject: lint items whose name starts/ends with their enclosing module's name --- clippy_lints/src/enum_variants.rs | 159 +++++++++++++++++++++++++------------- 1 file changed, 105 insertions(+), 54 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index ec318a37952..5ef507e2786 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -2,9 +2,10 @@ use rustc::lint::*; use syntax::ast::*; +use syntax::codemap::Span; use syntax::parse::token::InternedString; use utils::{span_help_and_lint, span_lint}; -use utils::{camel_case_from, camel_case_until}; +use utils::{camel_case_from, camel_case_until, in_macro}; /// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters /// @@ -18,7 +19,10 @@ declare_lint! { "finds enums where all variants share a prefix/postfix" } -pub struct EnumVariantNames; +#[derive(Default)] +pub struct EnumVariantNames { + modules: Vec<String>, +} impl LintPass for EnumVariantNames { fn get_lints(&self) -> LintArray { @@ -44,65 +48,112 @@ fn partial_rmatch(post: &str, name: &str) -> usize { post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() } +// FIXME: #600 +#[allow(while_let_on_iterator)] +fn check_variant(cx: &EarlyContext, def: &EnumDef, item_name: &str, item_name_chars: usize, span: Span) { + for var in &def.variants { + let name = var2str(var); + if partial_match(item_name, &name) == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name starts with the enum's name"); + } + if partial_rmatch(item_name, &name) == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name ends with the enum's name"); + } + } + if def.variants.len() < 2 { + return; + } + let first = var2str(&def.variants[0]); + let mut pre = &first[..camel_case_until(&*first)]; + let mut post = &first[camel_case_from(&*first)..]; + for var in &def.variants { + let name = var2str(var); + + let pre_match = partial_match(pre, &name); + pre = &pre[..pre_match]; + let pre_camel = camel_case_until(pre); + pre = &pre[..pre_camel]; + while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { + if next.is_lowercase() { + let last = pre.len() - last.len_utf8(); + let last_camel = camel_case_until(&pre[..last]); + pre = &pre[..last_camel]; + } else { + break; + } + } + + let post_match = partial_rmatch(post, &name); + let post_end = post.len() - post_match; + post = &post[post_end..]; + let post_camel = camel_case_from(post); + post = &post[post_camel..]; + } + let (what, value) = match (pre.is_empty(), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre), + (true, false) => ("post", post), + }; + span_help_and_lint(cx, + ENUM_VARIANT_NAMES, + span, + &format!("All variants have the same {}fix: `{}`", what, value), + &format!("remove the {}fixes and use full paths to \ + the variants instead of glob imports", + what)); +} + +fn to_camel_case(item_name: &str) -> String { + let mut s = String::new(); + let mut up = true; + for c in item_name.chars() { + if c.is_uppercase() { + // we only turn snake case text into CamelCase + return item_name.to_string(); + } + if c == '_' { + up = true; + continue; + } + if up { + up = false; + s.extend(c.to_uppercase()); + } else { + s.push(c); + } + } + s +} + impl EarlyLintPass for EnumVariantNames { - // FIXME: #600 - #[allow(while_let_on_iterator)] + fn check_item_post(&mut self, _cx: &EarlyContext, _item: &Item) { + let last = self.modules.pop(); + assert!(last.is_some()); + } + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { let item_name = item.ident.name.as_str(); let item_name_chars = item_name.chars().count(); - if let ItemKind::Enum(ref def, _) = item.node { - for var in &def.variants { - let name = var2str(var); - let matching = partial_match(&item_name, &name); - let rmatching = partial_rmatch(&item_name, &name); - if matching == item_name_chars { - span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name starts with the enum's name"); - } - if rmatching == item_name_chars { - span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name ends with the enum's name"); - } - } - if def.variants.len() < 2 { - return; - } - let first = var2str(&def.variants[0]); - let mut pre = &first[..camel_case_until(&*first)]; - let mut post = &first[camel_case_from(&*first)..]; - for var in &def.variants { - let name = var2str(var); - - let pre_match = partial_match(pre, &name); - pre = &pre[..pre_match]; - let pre_camel = camel_case_until(pre); - pre = &pre[..pre_camel]; - while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { - if next.is_lowercase() { - let last = pre.len() - last.len_utf8(); - let last_camel = camel_case_until(&pre[..last]); - pre = &pre[..last_camel]; - } else { - break; + let item_camel = to_camel_case(&item_name); + if !in_macro(cx, item.span) { + if let Some(mod_camel) = self.modules.last() { + // constants don't have surrounding modules + if !mod_camel.is_empty() { + let matching = partial_match(mod_camel, &item_camel); + let rmatching = partial_rmatch(mod_camel, &item_camel); + let nchars = mod_camel.chars().count(); + if matching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); + } + if rmatching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); } } - - let post_match = partial_rmatch(post, &name); - let post_end = post.len() - post_match; - post = &post[post_end..]; - let post_camel = camel_case_from(post); - post = &post[post_camel..]; } - let (what, value) = match (pre.is_empty(), post.is_empty()) { - (true, true) => return, - (false, _) => ("pre", pre), - (true, false) => ("post", post), - }; - span_help_and_lint(cx, - ENUM_VARIANT_NAMES, - item.span, - &format!("All variants have the same {}fix: `{}`", what, value), - &format!("remove the {}fixes and use full paths to \ - the variants instead of glob imports", - what)); } + if let ItemKind::Enum(ref def, _) = item.node { + check_variant(cx, def, &item_name, item_name_chars, item.span); + } + self.modules.push(item_camel); } } -- cgit 1.4.1-3-g733a5 From 7253ce73bb17d1dc872f66b5ed9a02ea68ca0060 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 10 Jun 2016 16:14:36 +0200 Subject: only lint public stutter namings --- clippy_lints/src/enum_variants.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 5ef507e2786..d03afde0132 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -135,18 +135,20 @@ impl EarlyLintPass for EnumVariantNames { let item_name = item.ident.name.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); - if !in_macro(cx, item.span) { - if let Some(mod_camel) = self.modules.last() { - // constants don't have surrounding modules - if !mod_camel.is_empty() { - let matching = partial_match(mod_camel, &item_camel); - let rmatching = partial_rmatch(mod_camel, &item_camel); - let nchars = mod_camel.chars().count(); - if matching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); - } - if rmatching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); + if item.vis == Visibility::Public { + if !in_macro(cx, item.span) { + if let Some(mod_camel) = self.modules.last() { + // constants don't have surrounding modules + if !mod_camel.is_empty() { + let matching = partial_match(mod_camel, &item_camel); + let rmatching = partial_rmatch(mod_camel, &item_camel); + let nchars = mod_camel.chars().count(); + if matching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); + } + if rmatching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); + } } } } -- cgit 1.4.1-3-g733a5 From 4701f13551c42ee574d47560a207ec2ecbb0df4d Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 10 Jun 2016 16:17:20 +0200 Subject: round 1 --- clippy_lints/src/approx_const.rs | 6 ++--- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/drop_ref.rs | 6 ++--- clippy_lints/src/enum_clike.rs | 6 ++--- clippy_lints/src/escape.rs | 6 ++--- clippy_lints/src/format.rs | 6 ++--- clippy_lints/src/lib.rs | 42 ++++++++++++++++---------------- clippy_lints/src/loops.rs | 6 ++--- clippy_lints/src/map_clone.rs | 6 ++--- clippy_lints/src/methods.rs | 6 ++--- clippy_lints/src/needless_update.rs | 6 ++--- clippy_lints/src/no_effect.rs | 6 ++--- clippy_lints/src/open_options.rs | 6 ++--- clippy_lints/src/panic.rs | 6 ++--- clippy_lints/src/print.rs | 6 ++--- clippy_lints/src/regex.rs | 6 ++--- clippy_lints/src/shadow.rs | 6 ++--- clippy_lints/src/temporary_assignment.rs | 6 ++--- clippy_lints/src/utils/conf.rs | 28 ++++++++++----------- clippy_lints/src/vec.rs | 20 +++++++-------- clippy_lints/src/zero_div_zero.rs | 8 +++--- 21 files changed, 98 insertions(+), 98 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 6d842ce64fc..967fd8b47c6 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -37,15 +37,15 @@ const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), (f64::SQRT_2, "SQRT_2", 5)]; #[derive(Copy,Clone)] -pub struct ApproxConstant; +pub struct Pass; -impl LintPass for ApproxConstant { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } } -impl LateLintPass for ApproxConstant { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprLit(ref lit) = e.node { check_lit(cx, lit, e); diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index fc9e95f9495..4306204e527 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -80,7 +80,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a } #[allow(while_let_loop)] // #362 -pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) -> Result<(), ()> { +fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) -> Result<(), ()> { // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. // There really is no markdown specification that would disambiguate this properly. This is // what GitHub and Rustdoc do: diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_ref.rs index 268497f99d4..8c299b8f2d6 100644 --- a/clippy_lints/src/drop_ref.rs +++ b/clippy_lints/src/drop_ref.rs @@ -23,15 +23,15 @@ declare_lint! { } #[allow(missing_copy_implementations)] -pub struct DropRefPass; +pub struct Pass; -impl LintPass for DropRefPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DROP_REF) } } -impl LateLintPass for DropRefPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(None, _) = path.node { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 39c31864f39..0390cd6c5d6 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -18,15 +18,15 @@ declare_lint! { "finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" } -pub struct EnumClikeUnportableVariant; +pub struct UnportableVariant; -impl LintPass for EnumClikeUnportableVariant { +impl LintPass for UnportableVariant { fn get_lints(&self) -> LintArray { lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) } } -impl LateLintPass for EnumClikeUnportableVariant { +impl LateLintPass for UnportableVariant { #[allow(cast_possible_truncation, cast_sign_loss)] fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemEnum(ref def, _) = item.node { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index b5172269a1e..2bdfe91a908 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -11,7 +11,7 @@ use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; -pub struct EscapePass; +pub struct Pass; /// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. /// @@ -44,13 +44,13 @@ struct EscapeDelegate<'a, 'tcx: 'a> { set: NodeSet, } -impl LintPass for EscapePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(BOXED_LOCAL) } } -impl LateLintPass for EscapePass { +impl LateLintPass for Pass { fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 0123dec070f..2b3835d780f 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -23,15 +23,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct FormatMacLint; +pub struct Pass; -impl LintPass for FormatMacLint { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array![USELESS_FORMAT] } } -impl LateLintPass for FormatMacLint { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some(span) = is_expn_of(cx, expr.span, "format") { match expr.node { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d64f653dd4c..32dd274ba6d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -132,7 +132,7 @@ mod reexport { #[cfg_attr(rustfmt, rustfmt_skip)] pub fn register_plugins(reg: &mut rustc_plugin::Registry) { - let conf = match utils::conf::conf_file(reg.args()) { + let conf = match utils::conf::file(reg.args()) { Ok(file_name) => { // if the user specified a file, it must exist, otherwise default to `clippy.toml` but // do not require the file to exist @@ -142,7 +142,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ("clippy.toml", false) }; - let (conf, errors) = utils::conf::read_conf(file_name, must_exist); + let (conf, errors) = utils::conf::read(file_name, must_exist); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { @@ -171,14 +171,14 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); - reg.register_early_lint_pass(box enum_variants::EnumVariantNames); + reg.register_early_lint_pass(box enum_variants::EnumVariantNames::default()); reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); - reg.register_late_lint_pass(box enum_clike::EnumClikeUnportableVariant); + reg.register_late_lint_pass(box enum_clike::UnportableVariant); reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); reg.register_late_lint_pass(box needless_bool::BoolComparison); - reg.register_late_lint_pass(box approx_const::ApproxConstant); + reg.register_late_lint_pass(box approx_const::Pass); reg.register_late_lint_pass(box misc::FloatCmp); reg.register_early_lint_pass(box precedence::Precedence); reg.register_late_lint_pass(box eta_reduction::EtaPass); @@ -195,11 +195,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box methods::MethodsPass); - reg.register_late_lint_pass(box shadow::ShadowPass); + reg.register_late_lint_pass(box methods::Pass); + reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); - reg.register_late_lint_pass(box loops::LoopsPass); + reg.register_late_lint_pass(box loops::Pass); reg.register_late_lint_pass(box lifetimes::LifetimePass); reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); @@ -208,35 +208,35 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); - reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); - reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); + reg.register_late_lint_pass(box open_options::NonSensical); + reg.register_late_lint_pass(box zero_div_zero::Pass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); - reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); + reg.register_late_lint_pass(box needless_update::Pass); reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); - reg.register_late_lint_pass(box no_effect::NoEffectPass); - reg.register_late_lint_pass(box map_clone::MapClonePass); - reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); + reg.register_late_lint_pass(box no_effect::Pass); + reg.register_late_lint_pass(box map_clone::Pass); + reg.register_late_lint_pass(box temporary_assignment::Pass); reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); - reg.register_late_lint_pass(box escape::EscapePass); + reg.register_late_lint_pass(box escape::Pass); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); - reg.register_late_lint_pass(box panic::PanicPass); + reg.register_late_lint_pass(box panic::Pass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box print::PrintLint); - reg.register_late_lint_pass(box vec::UselessVec); + reg.register_late_lint_pass(box print::Pass); + reg.register_late_lint_pass(box vec::Pass); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { max_single_char_names: conf.max_single_char_names, }); - reg.register_late_lint_pass(box drop_ref::DropRefPass); + reg.register_late_lint_pass(box drop_ref::Pass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box types::InvalidUpcastComparisons); - reg.register_late_lint_pass(box regex::RegexPass::default()); + reg.register_late_lint_pass(box regex::Pass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); - reg.register_late_lint_pass(box format::FormatMacLint); + reg.register_late_lint_pass(box format::Pass); reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f3f10fae16e..bcb62ec01b6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -205,9 +205,9 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct LoopsPass; +pub struct Pass; -impl LintPass for LoopsPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, @@ -222,7 +222,7 @@ impl LintPass for LoopsPass { } } -impl LateLintPass for LoopsPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 168aade325d..5959d70d9bc 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -18,9 +18,9 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct MapClonePass; +pub struct Pass; -impl LateLintPass for MapClonePass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // call to .map() if let ExprMethodCall(name, _, ref args) = expr.node { @@ -119,7 +119,7 @@ fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { } } -impl LintPass for MapClonePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MAP_CLONE) } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index da1420c3add..45d2e259dfa 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -17,7 +17,7 @@ use utils::MethodArgs; use utils::paths; #[derive(Clone)] -pub struct MethodsPass; +pub struct Pass; /// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. /// @@ -336,7 +336,7 @@ declare_lint! { "using `.iter().nth()` on a slice or Vec" } -impl LintPass for MethodsPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, OPTION_UNWRAP_USED, @@ -359,7 +359,7 @@ impl LintPass for MethodsPass { } } -impl LateLintPass for MethodsPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { if in_macro(cx, expr.span) { return; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index d8ae9dc3471..f46cfc5f123 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -17,15 +17,15 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct NeedlessUpdatePass; +pub struct Pass; -impl LintPass for NeedlessUpdatePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_UPDATE) } } -impl LateLintPass for NeedlessUpdatePass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tcx.expr_ty(expr); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index a9ac0a24856..5b34348219c 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -78,15 +78,15 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } #[derive(Copy, Clone)] -pub struct NoEffectPass; +pub struct Pass; -impl LintPass for NoEffectPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) } } -impl LateLintPass for NoEffectPass { +impl LateLintPass for Pass { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if has_no_effect(cx, expr) { diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 1d760599e3f..935edbb1f56 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -19,15 +19,15 @@ declare_lint! { #[derive(Copy,Clone)] -pub struct NonSensicalOpenOptions; +pub struct NonSensical; -impl LintPass for NonSensicalOpenOptions { +impl LintPass for NonSensical { fn get_lints(&self) -> LintArray { lint_array!(NONSENSICAL_OPEN_OPTIONS) } } -impl LateLintPass for NonSensicalOpenOptions { +impl LateLintPass for NonSensical { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprMethodCall(ref name, _, ref arguments) = e.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index d744d2a6308..d3306b4bc6f 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -17,15 +17,15 @@ declare_lint! { } #[allow(missing_copy_implementations)] -pub struct PanicPass; +pub struct Pass; -impl LintPass for PanicPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PANIC_PARAMS) } } -impl LateLintPass for PanicPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ let ExprBlock(ref block) = expr.node, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index d426286dba4..56fefb24f75 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -31,15 +31,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct PrintLint; +pub struct Pass; -impl LintPass for PrintLint { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PRINT_STDOUT, USE_DEBUG) } } -impl LateLintPass for PrintLint { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCall(ref fun, ref args) = expr.node { if let ExprPath(_, ref path) = fun.node { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index c2c37fcf686..26c8568473d 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -56,18 +56,18 @@ declare_lint! { } #[derive(Clone, Default)] -pub struct RegexPass { +pub struct Pass { spans: HashSet<Span>, last: Option<NodeId>, } -impl LintPass for RegexPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) } } -impl LateLintPass for RegexPass { +impl LateLintPass for Pass { fn check_crate(&mut self, _: &LateContext, _: &Crate) { self.spans.clear(); } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 0954d92cf9a..c42f9cb32d8 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -45,15 +45,15 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct ShadowPass; +pub struct Pass; -impl LintPass for ShadowPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } } -impl LateLintPass for ShadowPass { +impl LateLintPass for Pass { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { if in_external_macro(cx, block.span) { return; diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 1496a45dac2..5bc3853ac5e 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -24,15 +24,15 @@ fn is_temporary(expr: &Expr) -> bool { } #[derive(Copy, Clone)] -pub struct TemporaryAssignmentPass; +pub struct Pass; -impl LintPass for TemporaryAssignmentPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEMPORARY_ASSIGNMENT) } } -impl LateLintPass for TemporaryAssignmentPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 0c238400308..8bce798eef0 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -5,7 +5,7 @@ use syntax::parse::token; use toml; /// Get the configuration file from arguments. -pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { +pub fn file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { for arg in args { match arg.node { ast::MetaItemKind::Word(ref name) | @@ -31,18 +31,18 @@ pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::Interne /// Error from reading a configuration file. #[derive(Debug)] -pub enum ConfError { +pub enum Error { IoError(io::Error), TomlError(Vec<toml::ParserError>), TypeError(&'static str, &'static str, &'static str), UnknownKey(String), } -impl fmt::Display for ConfError { +impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ConfError::IoError(ref err) => err.fmt(f), - ConfError::TomlError(ref errs) => { + Error::IoError(ref err) => err.fmt(f), + Error::TomlError(ref errs) => { let mut first = true; for err in errs { if !first { @@ -55,17 +55,17 @@ impl fmt::Display for ConfError { Ok(()) } - ConfError::TypeError(ref key, ref expected, ref got) => { + Error::TypeError(ref key, ref expected, ref got) => { write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) } - ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), + Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), } } } -impl From<io::Error> for ConfError { +impl From<io::Error> for Error { fn from(e: io::Error) -> Self { - ConfError::IoError(e) + Error::IoError(e) } } @@ -87,7 +87,7 @@ macro_rules! define_Conf { impl Conf { /// Set the property `name` (which must be the `toml` name) to the given value #[allow(cast_sign_loss)] - fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + fn set(&mut self, name: String, value: toml::Value) -> Result<(), Error> { match name.as_str() { $( define_Conf!(PAT $toml_name) => { @@ -95,7 +95,7 @@ macro_rules! define_Conf { self.$rust_name = value; } else { - return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), + return Err(Error::TypeError(define_Conf!(EXPR $toml_name), stringify!($($ty)+), value.type_str())); } @@ -106,7 +106,7 @@ macro_rules! define_Conf { return Ok(()); } _ => { - return Err(ConfError::UnknownKey(name)); + return Err(Error::UnknownKey(name)); } } @@ -163,7 +163,7 @@ define_Conf! { /// Read the `toml` configuration file. The function will ignore “File not found” errors iif /// `!must_exist`, in which case, it will return the default configuration. /// In case of error, the function tries to continue as much as possible. -pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { +pub fn read(path: &str, must_exist: bool) -> (Conf, Vec<Error>) { let mut conf = Conf::default(); let mut errors = Vec::new(); @@ -191,7 +191,7 @@ pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { let toml = if let Some(toml) = parser.parse() { toml } else { - errors.push(ConfError::TomlError(parser.errors)); + errors.push(Error::TomlError(parser.errors)); return (conf, errors); }; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index e62a8f9c459..73f2fb7caa8 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -22,15 +22,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct UselessVec; +pub struct Pass; -impl LintPass for UselessVec { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(USELESS_VEC) } } -impl LateLintPass for UselessVec { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_let_chain!{[ @@ -51,12 +51,12 @@ impl LateLintPass for UselessVec { } fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { - if let Some(vec_args) = unexpand_vec(cx, vec) { + if let Some(vec_args) = unexpand(cx, vec) { let snippet = match vec_args { - VecArgs::Repeat(elem, len) => { + Args::Repeat(elem, len) => { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() } - VecArgs::Vec(args) => { + Args::Vec(args) => { if let Some(last) = args.iter().last() { let span = Span { lo: args[0].span.lo, @@ -78,7 +78,7 @@ fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { } /// Represent the pre-expansion arguments of a `vec!` invocation. -pub enum VecArgs<'a> { +pub enum Args<'a> { /// `vec![elem; len]` Repeat(&'a P<Expr>, &'a P<Expr>), /// `vec![a, b, c]` @@ -86,7 +86,7 @@ pub enum VecArgs<'a> { } /// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. -pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> { +pub fn unexpand<'e>(cx: &LateContext, expr: &'e Expr) -> Option<Args<'e>> { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, let ExprPath(_, ref path) = fun.node, @@ -94,7 +94,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> ], { return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { // `vec![elem; size]` case - Some(VecArgs::Repeat(&args[0], &args[1])) + Some(Args::Repeat(&args[0], &args[1])) } else if match_path(path, &["into_vec"]) && args.len() == 1 { // `vec![a, b, c]` case @@ -102,7 +102,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>> let ExprBox(ref boxed) = args[0].node, let ExprVec(ref args) = boxed.node ], { - return Some(VecArgs::Vec(&*args)); + return Some(Args::Vec(&*args)); }} None diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 041ac94836c..8c9f9871228 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -3,10 +3,10 @@ use rustc::lint::*; use rustc::hir::*; use utils::span_help_and_lint; -/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists +/// `Pass` is a pass that checks for a binary expression that consists /// `of 0.0/0.0`, which is always `NaN`. It is more clear to replace instances of /// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. -pub struct ZeroDivZeroPass; +pub struct Pass; /// **What it does:** This lint checks for `0.0 / 0.0`. /// @@ -21,13 +21,13 @@ declare_lint! { "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" } -impl LintPass for ZeroDivZeroPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(ZERO_DIVIDED_BY_ZERO) } } -impl LateLintPass for ZeroDivZeroPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // check for instances of 0.0/0.0 if_let_chain! {[ -- cgit 1.4.1-3-g733a5 From a97640117178f97180f3f8646a74cac8dee6c21a Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 10 Jun 2016 16:23:17 +0200 Subject: round 2 --- clippy_lints/src/utils/conf.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 8bce798eef0..323c6536496 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -32,17 +32,17 @@ pub fn file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedStri /// Error from reading a configuration file. #[derive(Debug)] pub enum Error { - IoError(io::Error), - TomlError(Vec<toml::ParserError>), - TypeError(&'static str, &'static str, &'static str), + Io(io::Error), + Toml(Vec<toml::ParserError>), + Type(&'static str, &'static str, &'static str), UnknownKey(String), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - Error::IoError(ref err) => err.fmt(f), - Error::TomlError(ref errs) => { + Error::Io(ref err) => err.fmt(f), + Error::Toml(ref errs) => { let mut first = true; for err in errs { if !first { @@ -55,7 +55,7 @@ impl fmt::Display for Error { Ok(()) } - Error::TypeError(ref key, ref expected, ref got) => { + Error::Type(ref key, ref expected, ref got) => { write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) } Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), @@ -65,7 +65,7 @@ impl fmt::Display for Error { impl From<io::Error> for Error { fn from(e: io::Error) -> Self { - Error::IoError(e) + Error::Io(e) } } @@ -95,9 +95,9 @@ macro_rules! define_Conf { self.$rust_name = value; } else { - return Err(Error::TypeError(define_Conf!(EXPR $toml_name), - stringify!($($ty)+), - value.type_str())); + return Err(Error::Type(define_Conf!(EXPR $toml_name), + stringify!($($ty)+), + value.type_str())); } }, )+ @@ -191,7 +191,7 @@ pub fn read(path: &str, must_exist: bool) -> (Conf, Vec<Error>) { let toml = if let Some(toml) = parser.parse() { toml } else { - errors.push(Error::TomlError(parser.errors)); + errors.push(Error::Toml(parser.errors)); return (conf, errors); }; -- cgit 1.4.1-3-g733a5 From af98a7ce524df692feb353fa4ffff4203083aef1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Fri, 10 Jun 2016 16:30:39 +0200 Subject: round 3 --- clippy_lints/src/enum_variants.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index d03afde0132..8905870f1d8 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -135,20 +135,18 @@ impl EarlyLintPass for EnumVariantNames { let item_name = item.ident.name.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); - if item.vis == Visibility::Public { - if !in_macro(cx, item.span) { - if let Some(mod_camel) = self.modules.last() { - // constants don't have surrounding modules - if !mod_camel.is_empty() { - let matching = partial_match(mod_camel, &item_camel); - let rmatching = partial_rmatch(mod_camel, &item_camel); - let nchars = mod_camel.chars().count(); - if matching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); - } - if rmatching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); - } + if item.vis == Visibility::Public && !in_macro(cx, item.span) { + if let Some(mod_camel) = self.modules.last() { + // constants don't have surrounding modules + if !mod_camel.is_empty() { + let matching = partial_match(mod_camel, &item_camel); + let rmatching = partial_rmatch(mod_camel, &item_camel); + let nchars = mod_camel.chars().count(); + if matching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); + } + if rmatching == nchars { + span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); } } } -- cgit 1.4.1-3-g733a5 From 836554387a86c312a482c95bc9a217303cb399b0 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 16 Jun 2016 16:19:17 +0200 Subject: Fix FP with `WHILE_LET_LOOP` and break expressions --- clippy_lints/src/loops.rs | 11 +++++------ tests/compile-fail/while_loop.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f3f10fae16e..3df766c95d4 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -249,7 +249,8 @@ impl LateLintPass for LoopsPass { match *source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { - if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && + if arms.len() == 2 && + arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { @@ -787,12 +788,11 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { /// If a block begins with an expression (with or without semicolon), return it. fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { - Some(ref expr) => Some(expr), + Some(ref expr) if block.stmts.is_empty() => Some(expr), None if !block.stmts.is_empty() => { match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), - _ => None, + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + StmtDecl(..) => None, } } _ => None, @@ -803,7 +803,6 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { fn is_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(None) => true, - // there won't be a `let <pat> = break` and so we can safely ignore the StmtDecl case ExprBlock(ref b) => { match extract_first_expr(b) { Some(ref subexpr) => is_break_expr(subexpr), diff --git a/tests/compile-fail/while_loop.rs b/tests/compile-fail/while_loop.rs index 4c1090876b4..d8cea42e20b 100644 --- a/tests/compile-fail/while_loop.rs +++ b/tests/compile-fail/while_loop.rs @@ -150,3 +150,18 @@ fn no_panic<T>(slice: &[T]) { loop {} //~ERROR empty `loop {}` detected. } } + +fn issue1017() { + let r: Result<u32, u32> = Ok(42); + let mut len = 1337; + + loop { + match r { + Err(_) => len = 0, + Ok(length) => { + len = length; + break + } + } + } +} -- cgit 1.4.1-3-g733a5 From e628e4d513ac9d85e7dd98740ec107b4d103bb27 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Thu, 16 Jun 2016 18:37:56 +0200 Subject: allow by default --- CHANGELOG.md | 1 + README.md | 3 ++- clippy_lints/src/enum_variants.rs | 18 +++++++++++++++--- clippy_lints/src/lib.rs | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 790bbc04691..3c2f9e1a622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -240,6 +240,7 @@ All notable changes to this project will be documented in this file. [`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign [`string_lit_as_bytes`]: https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes [`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string +[`stutter`]: https://github.com/Manishearth/rust-clippy/wiki#stutter [`suspicious_assignment_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting [`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment diff --git a/README.md b/README.md index 85e9ed70bf8..a8e8cbb3a5a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 153 lints included in this crate: +There are 154 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -144,6 +144,7 @@ name [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead +[stutter](https://github.com/Manishearth/rust-clippy/wiki#stutter) | allow | finds type names prefixed/postfixed with their containing module's name [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 8905870f1d8..4bf65ec4297 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -19,6 +19,18 @@ declare_lint! { "finds enums where all variants share a prefix/postfix" } +/// **What it does:** Warns on type names that are prefixed or suffixed by the containing module's name +/// +/// **Why is this bad?** It requires the user to type the module name twice +/// +/// **Known problems:** None +/// +/// **Example:** mod cake { struct BlackForestCake; } +declare_lint! { + pub STUTTER, Allow, + "finds type names prefixed/postfixed with their containing module's name" +} + #[derive(Default)] pub struct EnumVariantNames { modules: Vec<String>, @@ -26,7 +38,7 @@ pub struct EnumVariantNames { impl LintPass for EnumVariantNames { fn get_lints(&self) -> LintArray { - lint_array!(ENUM_VARIANT_NAMES) + lint_array!(ENUM_VARIANT_NAMES, STUTTER) } } @@ -143,10 +155,10 @@ impl EarlyLintPass for EnumVariantNames { let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); if matching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); + span_lint(cx, STUTTER, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); } if rmatching == nchars { - span_lint(cx, ENUM_VARIANT_NAMES, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); + span_lint(cx, STUTTER, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 32dd274ba6d..b68596f2535 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -263,6 +263,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { array_indexing::INDEXING_SLICING, booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, + enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, -- cgit 1.4.1-3-g733a5 From 12bc90d457594cca77edd430478e88c4a13ff201 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 14:30:05 -0700 Subject: Add tests for extend-iter-nth --- tests/compile-fail/methods.rs | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 811b9116143..647cca5a39c 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -8,6 +8,7 @@ use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::HashSet; +use std::collections::VecDeque; use std::ops::Mul; struct T; @@ -136,6 +137,10 @@ impl HasIter { fn iter(self) -> IteratorFalsePositives { IteratorFalsePositives { foo: 0 } } + + fn iter_mut(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } } /// Struct to generate false positive for Iterator-based lints @@ -325,15 +330,37 @@ fn or_fun_call() { /// Checks implementation of `ITER_NTH` lint fn iter_nth() { - let some_vec = vec![0, 1, 2, 3]; - let bad_vec = some_vec.iter().nth(3); - //~^ERROR called `.iter().nth()` on a Vec. - let bad_slice = &some_vec[..].iter().nth(3); - //~^ERROR called `.iter().nth()` on a slice. + let mut some_vec = vec![0, 1, 2, 3]; + let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect(); + + { + // Make sure we lint `.iter()` for relevant types + let bad_vec = some_vec.iter().nth(3); + //~^ERROR called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable + let bad_slice = &some_vec[..].iter().nth(3); + //~^ERROR called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable + let bad_vec_deque = some_vec_deque.iter().nth(3); + //~^ERROR called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable + } + + { + // Make sure we lint `.iter_mut()` for relevant types + let bad_vec = some_vec.iter_mut().nth(3); + //~^ERROR called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable + } + { + let bad_slice = &some_vec[..].iter_mut().nth(3); + //~^ERROR called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable + } + { + let bad_vec_deque = some_vec_deque.iter_mut().nth(3); + //~^ERROR called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable + } + // Make sure we don't lint for non-relevant types let false_positive = HasIter; let ok = false_positive.iter().nth(3); - // ^This should be okay, because false_positive is not a slice or Vec + let ok_mut = false_positive.iter_mut().nth(3); } #[allow(similar_names)] -- cgit 1.4.1-3-g733a5 From cfa0c5782eabd49b896e287f6a67dc7f3a529d98 Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 14:46:29 -0700 Subject: Extend iter_nth lint to work with iter_mut() and VecDeque --- README.md | 2 +- clippy_lints/src/methods.rs | 39 ++++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index a8e8cbb3a5a..f410ff990d9 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ name [invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false [items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | finds blocks where an item comes after a statement [iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[iter_nth](https://github.com/Manishearth/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a slice or Vec +[iter_nth](https://github.com/Manishearth/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a standard library type with O(1) element access [len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits and impls that have `.len()` but not `.is_empty()` [len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead [let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 45d2e259dfa..2256c8a23fd 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -312,9 +312,10 @@ declare_lint! { "getting the inner pointer of a temporary `CString`" } -/// **What it does:** This lint checks for use of `.iter().nth()` on a slice or Vec. +/// **What it does:** This lint checks for use of `.iter().nth()` (and the related +/// `.iter_mut().nth()`) on standard library types with O(1) element access. /// -/// **Why is this bad?** `.get()` is more efficient and more readable. +/// **Why is this bad?** `.get()` and `.get_mut()` are more efficient and more readable. /// /// **Known problems:** None. /// @@ -333,7 +334,7 @@ declare_lint! { declare_lint! { pub ITER_NTH, Warn, - "using `.iter().nth()` on a slice or Vec" + "using `.iter().nth()` on a standard library type with O(1) element access" } impl LintPass for Pass { @@ -389,7 +390,9 @@ impl LateLintPass for Pass { } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { - lint_iter_nth(cx, expr, arglists[0]); + lint_iter_nth(cx, expr, arglists[0], false); + } else if let Some(arglists) = method_chain_args(expr, &["iter_mut", "nth"]) { + lint_iter_nth(cx, expr, arglists[0], true); } lint_or_fun_call(cx, expr, &name.node.as_str(), args); @@ -645,21 +648,31 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec -fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs){ +fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){ // lint if the caller of `.iter().nth()` is a `slice` + let caller_type; + let mut_str = if is_mut { "_mut" } else {""}; if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { - span_lint(cx, - ITER_NTH, - expr.span, - "called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable"); + caller_type = "slice"; } // lint if the caller of `.iter().nth()` is a `Vec` else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) { - span_lint(cx, - ITER_NTH, - expr.span, - "called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable"); + caller_type = "Vec"; + } + // lint if the caller of `.iter().nth()` is a `VecDeque` + else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { + caller_type = "VecDeque"; + } + else { + return; // caller is not a type that we want to lint } + span_lint( + cx, + ITER_NTH, + expr.span, + &format!("called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", + mut_str, caller_type) + ); } fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { -- cgit 1.4.1-3-g733a5 From 0e04153a7051135dafd8c86b5eab3f591639a96b Mon Sep 17 00:00:00 2001 From: Devon Hollowood <devonhollowood@gmail.com> Date: Thu, 16 Jun 2016 14:51:16 -0700 Subject: Remove uneccessary, leftover comments in lint_iter_mut() --- clippy_lints/src/methods.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 2256c8a23fd..795e4e18d87 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -649,17 +649,14 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){ - // lint if the caller of `.iter().nth()` is a `slice` let caller_type; let mut_str = if is_mut { "_mut" } else {""}; if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { caller_type = "slice"; } - // lint if the caller of `.iter().nth()` is a `Vec` else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) { caller_type = "Vec"; } - // lint if the caller of `.iter().nth()` is a `VecDeque` else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { caller_type = "VecDeque"; } -- cgit 1.4.1-3-g733a5 From d921dfa2c3fc88aef7abb51977419a30e612adee Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 17 Jun 2016 12:57:44 +0200 Subject: Fix paths in *update_wiki.py* --- util/update_wiki.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index ccb82b9901a..c10721cfb5a 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -13,7 +13,7 @@ conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) confvar_re = re.compile(r'''/// Lint: (\w+). (.*).*\n *\("([^"]*)", (?:[^,]*), (.*) => (.*)\),''') -def parse_path(p="src"): +def parse_path(p="clippy_lints/src"): d = {} for f in os.listdir(p): if f.endswith(".rs"): -- cgit 1.4.1-3-g733a5 From 3646b30ccf7d58a70b1dd452491c68ede85be783 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 17 Jun 2016 13:21:46 +0200 Subject: Include restriction lints in the wiki --- util/update_wiki.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/util/update_wiki.py b/util/update_wiki.py index c10721cfb5a..e8b2280cb47 100755 --- a/util/update_wiki.py +++ b/util/update_wiki.py @@ -52,6 +52,11 @@ def parse_file(d, f): elif line.startswith("declare_lint!"): comment = False deprecated = False + restriction = False + elif line.startswith("declare_restriction_lint!"): + comment = False + deprecated = False + restriction = True elif line.startswith("declare_deprecated_lint!"): comment = False deprecated = True @@ -65,7 +70,7 @@ def parse_file(d, f): name = m.group(1).lower() # Intentionally either a never looping or infinite loop - while not deprecated: + while not deprecated and not restriction: m = re.search(level_re, line) if m: level = m.group(0) @@ -75,6 +80,8 @@ def parse_file(d, f): if deprecated: level = "Deprecated" + elif restriction: + level = "Allow" print("found %s with level %s in %s" % (name, level, f)) d[name] = (level, last_comment) @@ -162,6 +169,7 @@ def check_wiki_page(d, c, f): def main(): (d, c) = parse_path() + print('Found %s lints' % len(d)) if "-c" in sys.argv: check_wiki_page(d, c, "../rust-clippy.wiki/Home.md") else: -- cgit 1.4.1-3-g733a5 From b31bebeea4b7ae1a1312049745649d8d2c89c0f4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 11:35:34 +0200 Subject: fix cargo clippy when using with `--manifest-path` --- clippy_lints/src/utils/cargo.rs | 9 +++++++-- src/main.rs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index f81fcbc38ab..48a97f2f1fc 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -65,8 +65,13 @@ impl From<json::DecoderError> for Error { } } -pub fn metadata() -> Result<Metadata, Error> { - let output = Command::new("cargo").args(&["metadata", "--no-deps"]).output()?; +pub fn metadata(manifest_path: Option<String>) -> Result<Metadata, Error> { + let mut cmd = Command::new("cargo"); + cmd.arg("metadata").arg("--no-deps"); + if let Some(ref mani) = manifest_path { + cmd.arg(mani); + } + let output = cmd.output()?; let stdout = from_utf8(&output.stdout)?; Ok(json::decode(stdout)?) } diff --git a/src/main.rs b/src/main.rs index de3361d514f..cf57926440b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,7 +129,8 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let mut metadata = cargo::metadata().expect("could not obtain cargo metadata"); + let manifest_path = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path=")); + let mut metadata = cargo::metadata(manifest_path).expect("could not obtain cargo metadata"); assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); -- cgit 1.4.1-3-g733a5 From 5b1d849c7e1df0b413237d7a0a0a70c2cbfd52e9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 21 Jun 2016 15:24:04 +0530 Subject: Revert "fix cargo clippy when using with `--manifest-path`" This reverts commit b31bebeea4b7ae1a1312049745649d8d2c89c0f4. --- clippy_lints/src/utils/cargo.rs | 9 ++------- src/main.rs | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index 48a97f2f1fc..f81fcbc38ab 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -65,13 +65,8 @@ impl From<json::DecoderError> for Error { } } -pub fn metadata(manifest_path: Option<String>) -> Result<Metadata, Error> { - let mut cmd = Command::new("cargo"); - cmd.arg("metadata").arg("--no-deps"); - if let Some(ref mani) = manifest_path { - cmd.arg(mani); - } - let output = cmd.output()?; +pub fn metadata() -> Result<Metadata, Error> { + let output = Command::new("cargo").args(&["metadata", "--no-deps"]).output()?; let stdout = from_utf8(&output.stdout)?; Ok(json::decode(stdout)?) } diff --git a/src/main.rs b/src/main.rs index cf57926440b..de3361d514f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,8 +129,7 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let manifest_path = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path=")); - let mut metadata = cargo::metadata(manifest_path).expect("could not obtain cargo metadata"); + let mut metadata = cargo::metadata().expect("could not obtain cargo metadata"); assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); -- cgit 1.4.1-3-g733a5 From 69c796e118b1c3b742f30c31fac6bac20ac3f772 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 8 Jun 2016 19:54:22 +0200 Subject: lint on `filter(x).map(y)`, `filter(x).flat_map(y)`, `filter_map(x).flat_map(y)` --- clippy_lints/src/methods.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 795e4e18d87..abb8078c286 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -379,6 +379,12 @@ impl LateLintPass for Pass { lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { lint_filter_next(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { + lint_filter_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "flat_map"]) { + lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { + lint_filter_map_flat_map(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { @@ -834,6 +840,39 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs } } +// Type of MethodArgs is potentially a Vec +/// lint use of `filter().map() for Iterators` +fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { + // lint if caller of `.filter().map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).map(q)` on an Iterator. This is more succinctly expressed by calling `.filter_map(..)` \ + instead."; + span_lint(cx, FILTER_NEXT, expr.span, msg); + } +} + +// Type of MethodArgs is potentially a Vec +/// lint use of `filter().flat_map() for Iterators` +fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { + // lint if caller of `.filter().flat_map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ + and filtering by returning an empty Iterator."; + span_lint(cx, FILTER_NEXT, expr.span, msg); + } +} + +// Type of MethodArgs is potentially a Vec +/// lint use of `filter_map().flat_map() for Iterators` +fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { + // lint if caller of `.filter_map().flat_map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ + and filtering by returning an empty Iterator."; + span_lint(cx, FILTER_NEXT, expr.span, msg); + } +} + #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec /// lint searching an Iterator followed by `is_some()` -- cgit 1.4.1-3-g733a5 From 36c5026c48f1beed77cb4bfacc37d798c1b505a2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 12:31:30 +0200 Subject: fix cargo clippy when using with `--manifest-path` --- clippy_lints/src/utils/cargo.rs | 9 +++++++-- src/main.rs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/cargo.rs b/clippy_lints/src/utils/cargo.rs index f81fcbc38ab..48a97f2f1fc 100644 --- a/clippy_lints/src/utils/cargo.rs +++ b/clippy_lints/src/utils/cargo.rs @@ -65,8 +65,13 @@ impl From<json::DecoderError> for Error { } } -pub fn metadata() -> Result<Metadata, Error> { - let output = Command::new("cargo").args(&["metadata", "--no-deps"]).output()?; +pub fn metadata(manifest_path: Option<String>) -> Result<Metadata, Error> { + let mut cmd = Command::new("cargo"); + cmd.arg("metadata").arg("--no-deps"); + if let Some(ref mani) = manifest_path { + cmd.arg(mani); + } + let output = cmd.output()?; let stdout = from_utf8(&output.stdout)?; Ok(json::decode(stdout)?) } diff --git a/src/main.rs b/src/main.rs index de3361d514f..cf57926440b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,7 +129,8 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { - let mut metadata = cargo::metadata().expect("could not obtain cargo metadata"); + let manifest_path = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path=")); + let mut metadata = cargo::metadata(manifest_path).expect("could not obtain cargo metadata"); assert_eq!(metadata.version, 1); for target in metadata.packages.remove(0).targets { let args = std::env::args().skip(2); -- cgit 1.4.1-3-g733a5 From 44c30ca543642d947116a536223e5f93fb28c35a Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 12:35:49 +0200 Subject: fix tests --- tests/versioncheck.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index b2a2f416a8f..e216c801546 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -3,9 +3,9 @@ use clippy_lints::utils::cargo; #[test] fn check_that_clippy_lints_has_the_same_version_as_clippy() { - let clippy_meta = cargo::metadata().expect("could not obtain cargo metadata"); + let clippy_meta = cargo::metadata(None).expect("could not obtain cargo metadata"); std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); - let clippy_lints_meta = cargo::metadata().expect("could not obtain cargo metadata"); + let clippy_lints_meta = cargo::metadata(None).expect("could not obtain cargo metadata"); assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); for package in &clippy_meta.packages[0].dependencies { if package.name == "clippy_lints" { -- cgit 1.4.1-3-g733a5 From 4e528521467d014cc554976a9ec4e25659d8ead6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 13:04:50 +0200 Subject: create a lint for each of the messages --- clippy_lints/src/methods.rs | 47 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index abb8078c286..3ecbe6251c4 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -159,6 +159,42 @@ declare_lint! { "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" } +/// **What it does:** This lint `Warn`s on `_.filter(_).map(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as `_.filter_map(_)`. +/// +/// **Known problems:** Often requires a condition + Option creation in `filter_map` +/// +/// **Example:** `iter.filter(|x| x == 0).map(|x| x * 2)` +declare_lint! { + pub FILTER_MAP, Allow, + "using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)`" +} + +/// **What it does:** This lint `Warn`s on `_.filter(_).flat_map(_)`. +/// +/// **Why is this bad?** Readability, this just needs the `flat_map` to return an empty iterator, if the value should be filtered. +/// +/// **Known problems:** Often requires a condition + Iterator creation in `flat_map` +/// +/// **Example:** `iter.filter(|x| x == 0).flat_map(|x| x.bits())` +declare_lint! { + pub FILTER_FLAT_MAP, Allow, + "using `filter(_).flat_map(_)`, which can be rewritten using just the flat_map" +} + +/// **What it does:** This lint `Warn`s on `_.filter_map(_).flat_map(_)`. +/// +/// **Why is this bad?** Readability, this just needs the `flat_map` to return an empty iterator, if the value should be filtered. +/// +/// **Known problems:** Often requires a condition + Iterator creation in `flat_map` +/// +/// **Example:** `iter.filter_map(|x| x.process()).flat_map(|x| x.bits())` +declare_lint! { + pub FILTER_MAP_FLAT_MAP, Allow, + "using `filter_map(_).flat_map(_)`, which can be rewritten using just the flat_map" +} + /// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or /// `rposition()`) followed by a call to `is_some()`. /// @@ -356,6 +392,9 @@ impl LintPass for Pass { SINGLE_CHAR_PATTERN, SEARCH_IS_SOME, TEMPORARY_CSTRING_AS_PTR, + FILTER_MAP, + FILTER_FLAT_MAP, + FILTER_MAP_FLAT_MAP, ITER_NTH) } } @@ -847,7 +886,7 @@ fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).map(q)` on an Iterator. This is more succinctly expressed by calling `.filter_map(..)` \ instead."; - span_lint(cx, FILTER_NEXT, expr.span, msg); + span_lint(cx, FILTER_MAP, expr.span, msg); } } @@ -858,7 +897,7 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &Metho if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_NEXT, expr.span, msg); + span_lint(cx, FILTER_FLAT_MAP, expr.span, msg); } } @@ -867,9 +906,9 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &Metho fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ + let msg = "called `filter_map(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_NEXT, expr.span, msg); + span_lint(cx, FILTER_MAP_FLAT_MAP, expr.span, msg); } } -- cgit 1.4.1-3-g733a5 From 77e2155778e9700e4797acb8629ab52d19cd6b29 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 13:32:34 +0200 Subject: update lints --- CHANGELOG.md | 3 +++ README.md | 5 ++++- clippy_lints/src/lib.rs | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2f9e1a622..cbbd5497c79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -154,6 +154,9 @@ All notable changes to this project will be documented in this file. [`explicit_counter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop [`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop [`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice +[`filter_flat_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_flat_map +[`filter_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map +[`filter_map_flat_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map_flat_map [`filter_next`]: https://github.com/Manishearth/rust-clippy/wiki#filter_next [`float_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic [`float_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#float_cmp diff --git a/README.md b/README.md index f410ff990d9..8f9d47f6ee9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 154 lints included in this crate: +There are 157 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -60,6 +60,9 @@ name [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice +[filter_flat_map](https://github.com/Manishearth/rust-clippy/wiki#filter_flat_map) | allow | using `filter(_).flat_map(_)`, which can be rewritten using just the flat_map +[filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)` +[filter_map_flat_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map_flat_map) | allow | using `filter_map(_).flat_map(_)`, which can be rewritten using just the flat_map [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic) | allow | Any floating-point arithmetic statement [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b68596f2535..a10ab8add0c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -268,6 +268,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, + methods::FILTER_FLAT_MAP, + methods::FILTER_MAP, + methods::FILTER_MAP_FLAT_MAP, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, -- cgit 1.4.1-3-g733a5 From eef439cb78d7efbf24856c81a78e2b38ebfbc189 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 13:48:56 +0200 Subject: add tests --- tests/compile-fail/filter_methods.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/compile-fail/filter_methods.rs diff --git a/tests/compile-fail/filter_methods.rs b/tests/compile-fail/filter_methods.rs new file mode 100644 index 00000000000..2a0e4156ceb --- /dev/null +++ b/tests/compile-fail/filter_methods.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(clippy, clippy_pedantic)] +fn main() { + let _: Vec<_> = vec![5; 6].into_iter() //~ERROR called `filter(p).map(q)` on an Iterator + .filter(|&x| x == 0) + .map(|x| x * 2) + .collect(); + + let _: Vec<_> = vec![5i8; 6].into_iter() //~ERROR called `filter(p).flat_map(q)` on an Iterator + .filter(|&x| x == 0) + .flat_map(|x| x.checked_mul(2)) + .collect(); +} -- cgit 1.4.1-3-g733a5 From 48a5f8446d0e23c37a36c808fb68b2796e044ca7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 13:49:08 +0200 Subject: fallout --- clippy_lints/src/lifetimes.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 797e9708b60..dc5df874020 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -71,19 +71,17 @@ enum RefLt { Named(Name), } -fn bound_lifetimes(bound: &TyParamBound) -> Option<HirVec<&Lifetime>> { +fn bound_lifetimes(bound: &TyParamBound) -> HirVec<&Lifetime> { if let TraitTyParamBound(ref trait_ref, _) = *bound { - let lt = trait_ref.trait_ref - .path - .segments - .last() - .expect("a path must have at least one segment") - .parameters - .lifetimes(); - - Some(lt) + trait_ref.trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .parameters + .lifetimes() } else { - None + HirVec::new() } } @@ -94,7 +92,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Sp let bounds_lts = generics.ty_params .iter() - .flat_map(|ref typ| typ.bounds.iter().filter_map(bound_lifetimes).flat_map(|lts| lts)); + .flat_map(|typ| typ.bounds.iter().flat_map(bound_lifetimes)); if could_use_elision(cx, decl, &generics.lifetimes, bounds_lts) { span_lint(cx, -- cgit 1.4.1-3-g733a5 From f5dfcd694bfd9922ee94f59465e31200310a6a39 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 13:51:44 +0200 Subject: fallout2 --- clippy_lints/src/matches.rs | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index fab15ac3238..e578fbf6d68 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -334,31 +334,30 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match /// Get all arms that are unbounded `PatRange`s. fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec<SpannedRange<ConstVal>> { arms.iter() - .filter_map(|arm| { + .flat_map(|arm| { if let Arm { ref pats, guard: None, .. } = *arm { - Some(pats.iter().filter_map(|pat| { - if_let_chain! {[ - let PatKind::Range(ref lhs, ref rhs) = pat.node, - let Ok(lhs) = eval_const_expr_partial(cx.tcx, lhs, ExprTypeChecked, None), - let Ok(rhs) = eval_const_expr_partial(cx.tcx, rhs, ExprTypeChecked, None) - ], { - return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); - }} - - if_let_chain! {[ - let PatKind::Lit(ref value) = pat.node, - let Ok(value) = eval_const_expr_partial(cx.tcx, value, ExprTypeChecked, None) - ], { - return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); - }} - - None - })) + pats.iter() } else { + [].iter() + }.filter_map(|pat| { + if_let_chain! {[ + let PatKind::Range(ref lhs, ref rhs) = pat.node, + let Ok(lhs) = eval_const_expr_partial(cx.tcx, lhs, ExprTypeChecked, None), + let Ok(rhs) = eval_const_expr_partial(cx.tcx, rhs, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); + }} + + if_let_chain! {[ + let PatKind::Lit(ref value) = pat.node, + let Ok(value) = eval_const_expr_partial(cx.tcx, value, ExprTypeChecked, None) + ], { + return Some(SpannedRange { span: pat.span, node: (value.clone(), value) }); + }} + None - } + }) }) - .flat_map(IntoIterator::into_iter) .collect() } -- cgit 1.4.1-3-g733a5 From 8bfb31ee9725c58f5dd2f2b3e3ce9592db49974f Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 14:39:56 +0200 Subject: doc nits --- clippy_lints/src/methods.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 3ecbe6251c4..f3a073521be 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -858,7 +858,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &Method #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec -/// lint use of `filter().next() for Iterators` +/// lint use of `filter().next()` for `Iterators` fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { @@ -880,7 +880,7 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs } // Type of MethodArgs is potentially a Vec -/// lint use of `filter().map() for Iterators` +/// lint use of `filter().map()` for `Iterators` fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { @@ -891,7 +891,7 @@ fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs } // Type of MethodArgs is potentially a Vec -/// lint use of `filter().flat_map() for Iterators` +/// lint use of `filter().flat_map()` for `Iterators` fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { @@ -902,7 +902,7 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &Metho } // Type of MethodArgs is potentially a Vec -/// lint use of `filter_map().flat_map() for Iterators` +/// lint use of `filter_map().flat_map()` for `Iterators` fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { -- cgit 1.4.1-3-g733a5 From 415ddfb6302039e15180f005fb1775f562844ded Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 14:41:16 +0200 Subject: lint message nits --- clippy_lints/src/methods.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f3a073521be..3b7122cb410 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -862,7 +862,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &Method fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).next()` on an Iterator. This is more succinctly expressed by calling `.find(p)` \ + let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` \ instead."; let filter_snippet = snippet(cx, filter_args[1].span, ".."); if filter_snippet.lines().count() <= 1 { @@ -884,7 +884,7 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).map(q)` on an Iterator. This is more succinctly expressed by calling `.filter_map(..)` \ + let msg = "called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` \ instead."; span_lint(cx, FILTER_MAP, expr.span, msg); } @@ -895,7 +895,7 @@ fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ + let msg = "called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; span_lint(cx, FILTER_FLAT_MAP, expr.span, msg); } @@ -906,7 +906,7 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &Metho fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(p).flat_map(q)` on an Iterator. This is more succinctly expressed by calling `.flat_map(..)` \ + let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; span_lint(cx, FILTER_MAP_FLAT_MAP, expr.span, msg); } @@ -919,7 +919,7 @@ fn lint_search_is_some(cx: &LateContext, expr: &hir::Expr, search_method: &str, is_some_args: &MethodArgs) { // lint if caller of search is an Iterator if match_trait_method(cx, &*is_some_args[0], &paths::ITERATOR) { - let msg = format!("called `is_some()` after searching an iterator with {}. This is more succinctly expressed \ + let msg = format!("called `is_some()` after searching an `Iterator` with {}. This is more succinctly expressed \ by calling `any()`.", search_method); let search_snippet = snippet(cx, search_args[1].span, ".."); -- cgit 1.4.1-3-g733a5 From ac6e7b29577285a4476c9cc34395e4d1d51d3aac Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 14:46:02 +0200 Subject: fix tests --- tests/compile-fail/filter_methods.rs | 9 +++++++-- tests/compile-fail/methods.rs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/compile-fail/filter_methods.rs b/tests/compile-fail/filter_methods.rs index 2a0e4156ceb..8f37a8553b4 100644 --- a/tests/compile-fail/filter_methods.rs +++ b/tests/compile-fail/filter_methods.rs @@ -3,13 +3,18 @@ #![deny(clippy, clippy_pedantic)] fn main() { - let _: Vec<_> = vec![5; 6].into_iter() //~ERROR called `filter(p).map(q)` on an Iterator + let _: Vec<_> = vec![5; 6].into_iter() //~ERROR called `filter(p).map(q)` on an `Iterator` .filter(|&x| x == 0) .map(|x| x * 2) .collect(); - let _: Vec<_> = vec![5i8; 6].into_iter() //~ERROR called `filter(p).flat_map(q)` on an Iterator + let _: Vec<_> = vec![5i8; 6].into_iter() //~ERROR called `filter(p).flat_map(q)` on an `Iterator` .filter(|&x| x == 0) .flat_map(|x| x.checked_mul(2)) .collect(); + + let _: Vec<_> = vec![5i8; 6].into_iter() //~ERROR called `filter_map(p).flat_map(q)` on an `Iterator` + .filter_map(|x| x.checked_mul(2)) + .flat_map(|x| x.checked_mul(2)) + .collect(); } diff --git a/tests/compile-fail/methods.rs b/tests/compile-fail/methods.rs index 647cca5a39c..c3f18bef462 100644 --- a/tests/compile-fail/methods.rs +++ b/tests/compile-fail/methods.rs @@ -181,11 +181,11 @@ fn filter_next() { // check single-line case let _ = v.iter().filter(|&x| *x < 0).next(); - //~^ ERROR called `filter(p).next()` on an Iterator. + //~^ ERROR called `filter(p).next()` on an `Iterator`. //~| NOTE replace `filter(|&x| *x < 0).next()` // check multi-line case - let _ = v.iter().filter(|&x| { //~ERROR called `filter(p).next()` on an Iterator. + let _ = v.iter().filter(|&x| { //~ERROR called `filter(p).next()` on an `Iterator`. *x < 0 } ).next(); -- cgit 1.4.1-3-g733a5 From 92c02bd4afdb691a762060a393603321933be34e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 16:26:56 +0200 Subject: Bump to 0.0.77 --- CHANGELOG.md | 6 +++++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81102a900e5..c52cbdbc675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.76 — TBD +## 0.0.77 — 2016-06-21 +* Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)* +* New lints: [`stutter`] and [`iter_nth`] + +## 0.0.76 — 2016-06-10 * Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)* * `cargo clippy` now automatically defines the `clippy` feature diff --git a/Cargo.toml b/Cargo.toml index 60862865b43..e52342d3860 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.76" +version = "0.0.77" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -25,7 +25,7 @@ test = false [dependencies] regex_macros = { version = "0.1.33", optional = true } # begin automatic update -clippy_lints = { version = "0.0.76", path = "clippy_lints" } +clippy_lints = { version = "0.0.77", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 2f748d1ec3c..a1012e94ee5 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.76" +version = "0.0.77" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From b34cdc7a79e1ac36621a70dfaa3661d294e05268 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 21 Jun 2016 17:20:08 +0200 Subject: speed up travis by not recompiling clippy just to test `cargo clippy` --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4329bb25804..403b41f032a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ script: - python util/update_lints.py -c - cargo build --features debugging - cargo test --features debugging - - SYSROOT=~/rust cargo install + - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - cargo clippy -- -D clippy - cd clippy_lints && cargo clippy -- -D clippy && cd .. -- cgit 1.4.1-3-g733a5 From 490030647d7877ce5642e93927513c9b3c3cf7b1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 22 Jun 2016 10:36:18 +0200 Subject: create missing cargo directory --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 403b41f032a..0d5a6bc9fce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ script: - python util/update_lints.py -c - cargo build --features debugging - cargo test --features debugging + - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - cargo clippy -- -D clippy - cd clippy_lints && cargo clippy -- -D clippy && cd .. -- cgit 1.4.1-3-g733a5 From 94eb9013367f01aa2c4441d563e754d3bc7e355c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 22 Jun 2016 10:37:08 +0200 Subject: add cargo/bin to PATH --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d5a6bc9fce..a1425e15f3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,8 @@ script: - cargo test --features debugging - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - - cargo clippy -- -D clippy - - cd clippy_lints && cargo clippy -- -D clippy && cd .. + - PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy + - PATH=$PATH:~/rust/cargo/bin cd clippy_lints && cargo clippy -- -D clippy && cd .. after_success: # only test regex_macros if it compiles -- cgit 1.4.1-3-g733a5 From 5ccbf3d43740a714f7c7a61bf71690fedc65046d Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 22 Jun 2016 10:44:46 +0200 Subject: unify the lints --- CHANGELOG.md | 2 -- README.md | 4 +-- clippy_lints/src/lib.rs | 2 -- clippy_lints/src/methods.rs | 59 +++++++++++++++--------------------- tests/compile-fail/filter_methods.rs | 5 +++ 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbbd5497c79..9bd8affcded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -154,9 +154,7 @@ All notable changes to this project will be documented in this file. [`explicit_counter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop [`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop [`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice -[`filter_flat_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_flat_map [`filter_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map -[`filter_map_flat_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map_flat_map [`filter_next`]: https://github.com/Manishearth/rust-clippy/wiki#filter_next [`float_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic [`float_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#float_cmp diff --git a/README.md b/README.md index 8f9d47f6ee9..4345c504822 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 157 lints included in this crate: +There are 155 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -60,9 +60,7 @@ name [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice -[filter_flat_map](https://github.com/Manishearth/rust-clippy/wiki#filter_flat_map) | allow | using `filter(_).flat_map(_)`, which can be rewritten using just the flat_map [filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)` -[filter_map_flat_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map_flat_map) | allow | using `filter_map(_).flat_map(_)`, which can be rewritten using just the flat_map [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic) | allow | Any floating-point arithmetic statement [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a10ab8add0c..835823b8cd3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -268,9 +268,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, - methods::FILTER_FLAT_MAP, methods::FILTER_MAP, - methods::FILTER_MAP_FLAT_MAP, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 3b7122cb410..97130ee751f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -159,11 +159,11 @@ declare_lint! { "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" } -/// **What it does:** This lint `Warn`s on `_.filter(_).map(_)`. +/// **What it does:** This lint `Warn`s on `_.filter(_).map(_)`, `_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar. /// -/// **Why is this bad?** Readability, this can be written more concisely as `_.filter_map(_)`. +/// **Why is this bad?** Readability, this can be written more concisely as a single method call /// -/// **Known problems:** Often requires a condition + Option creation in `filter_map` +/// **Known problems:** Often requires a condition + Option/Iterator creation inside the closure /// /// **Example:** `iter.filter(|x| x == 0).map(|x| x * 2)` declare_lint! { @@ -171,30 +171,6 @@ declare_lint! { "using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)`" } -/// **What it does:** This lint `Warn`s on `_.filter(_).flat_map(_)`. -/// -/// **Why is this bad?** Readability, this just needs the `flat_map` to return an empty iterator, if the value should be filtered. -/// -/// **Known problems:** Often requires a condition + Iterator creation in `flat_map` -/// -/// **Example:** `iter.filter(|x| x == 0).flat_map(|x| x.bits())` -declare_lint! { - pub FILTER_FLAT_MAP, Allow, - "using `filter(_).flat_map(_)`, which can be rewritten using just the flat_map" -} - -/// **What it does:** This lint `Warn`s on `_.filter_map(_).flat_map(_)`. -/// -/// **Why is this bad?** Readability, this just needs the `flat_map` to return an empty iterator, if the value should be filtered. -/// -/// **Known problems:** Often requires a condition + Iterator creation in `flat_map` -/// -/// **Example:** `iter.filter_map(|x| x.process()).flat_map(|x| x.bits())` -declare_lint! { - pub FILTER_MAP_FLAT_MAP, Allow, - "using `filter_map(_).flat_map(_)`, which can be rewritten using just the flat_map" -} - /// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or /// `rposition()`) followed by a call to `is_some()`. /// @@ -393,8 +369,6 @@ impl LintPass for Pass { SEARCH_IS_SOME, TEMPORARY_CSTRING_AS_PTR, FILTER_MAP, - FILTER_FLAT_MAP, - FILTER_MAP_FLAT_MAP, ITER_NTH) } } @@ -420,6 +394,8 @@ impl LateLintPass for Pass { lint_filter_next(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { lint_filter_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "map"]) { + lint_filter_map_map(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["filter", "flat_map"]) { lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { @@ -884,8 +860,19 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &MethodArgs fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` \ - instead."; + let msg = "called `filter(p).map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.filter_map(..)` instead."; + span_lint(cx, FILTER_MAP, expr.span, msg); + } +} + +// Type of MethodArgs is potentially a Vec +/// lint use of `filter().map()` for `Iterators` +fn lint_filter_map_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { + // lint if caller of `.filter().map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ + This is more succinctly expressed by only calling `.filter_map(..)` instead."; span_lint(cx, FILTER_MAP, expr.span, msg); } } @@ -895,9 +882,10 @@ fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` \ + let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_FLAT_MAP, expr.span, msg); + span_lint(cx, FILTER_MAP, expr.span, msg); } } @@ -906,9 +894,10 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &Metho fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &MethodArgs, _map_args: &MethodArgs) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` \ + let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)` \ and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_MAP_FLAT_MAP, expr.span, msg); + span_lint(cx, FILTER_MAP, expr.span, msg); } } diff --git a/tests/compile-fail/filter_methods.rs b/tests/compile-fail/filter_methods.rs index 8f37a8553b4..743c3c15aeb 100644 --- a/tests/compile-fail/filter_methods.rs +++ b/tests/compile-fail/filter_methods.rs @@ -17,4 +17,9 @@ fn main() { .filter_map(|x| x.checked_mul(2)) .flat_map(|x| x.checked_mul(2)) .collect(); + + let _: Vec<_> = vec![5i8; 6].into_iter() //~ERROR called `filter_map(p).map(q)` on an `Iterator` + .filter_map(|x| x.checked_mul(2)) + .map(|x| x.checked_mul(2)) + .collect(); } -- cgit 1.4.1-3-g733a5 From 262148c946187dd69e2d875360c45fc4cbd9becf Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 22 Jun 2016 13:03:59 +0200 Subject: update lint doc text --- README.md | 2 +- clippy_lints/src/methods.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4345c504822..d210a1b218f 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ name [explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do [explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do [extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice -[filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)` +[filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call [filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` [float_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic) | allow | Any floating-point arithmetic statement [float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 97130ee751f..950a03159b2 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -168,7 +168,7 @@ declare_lint! { /// **Example:** `iter.filter(|x| x == 0).map(|x| x * 2)` declare_lint! { pub FILTER_MAP, Allow, - "using `filter(_).map(_)`, which is more succinctly expressed as `.filter_map(_)`" + "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call" } /// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or -- cgit 1.4.1-3-g733a5 From ba33fd0a3ae47b7bdc9c1cb39343bcf1430108d3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Wed, 22 Jun 2016 14:37:08 +0200 Subject: pass the path to the correct command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a1425e15f3f..b65c8a7c1dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ script: - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy - - PATH=$PATH:~/rust/cargo/bin cd clippy_lints && cargo clippy -- -D clippy && cd .. + - cd clippy_lints && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. after_success: # only test regex_macros if it compiles -- cgit 1.4.1-3-g733a5 From edf32625004aa1335b954a68203d29b05996c95f Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Fri, 24 Jun 2016 07:20:33 +0200 Subject: try out cache: cargo with travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b65c8a7c1dd..d33f8604bcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: rust rust: nightly sudo: false +cache: cargo env: global: -- cgit 1.4.1-3-g733a5 From eeb847ada80a2639949831870a84afa45d318c17 Mon Sep 17 00:00:00 2001 From: Xavier Bestel <xavier.bestel@free.fr> Date: Fri, 24 Jun 2016 14:41:58 +0200 Subject: Suggest Rust nightly Add one line to suggest that clippy won't compile with Rust stable. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d210a1b218f..652aec0e474 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,8 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ## Usage +Clippy will most probably need Rust nightly to compile. + ### As a Compiler Plugin Compiler plugins are highly unstable and will only work with a *recent* nightly -- cgit 1.4.1-3-g733a5 From a8e185646b0fbba010a4945de008396c15da1e36 Mon Sep 17 00:00:00 2001 From: Xavier Bestel <xavier.bestel@free.fr> Date: Fri, 24 Jun 2016 14:55:17 +0200 Subject: *latest* nightly --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 652aec0e474..8a6d212add7 100644 --- a/README.md +++ b/README.md @@ -181,12 +181,11 @@ More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/ ## Usage -Clippy will most probably need Rust nightly to compile. +As a general rule clippy will only work with the *latest* Rust nightly for now. ### As a Compiler Plugin -Compiler plugins are highly unstable and will only work with a *recent* nightly -Rust for now. Since stable Rust is backwards compatible, you should be able to +Since stable Rust is backwards compatible, you should be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this. -- cgit 1.4.1-3-g733a5 From bf4c4294bf344c560115fb0a0112ee4d822dccd0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <oli-obk@users.noreply.github.com> Date: Sat, 25 Jun 2016 15:05:29 +0200 Subject: add myself to Cargo.toml authors --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e52342d3860..d3e67bdb7e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", "Georg Brandl <georg@python.org>", - "Martin Carton <cartonmartin@gmail.com>" + "Martin Carton <cartonmartin@gmail.com>", + "Oliver Schneider <clippy-iethah7aipeen8neex1a@oli-obk.de>" ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/Manishearth/rust-clippy" -- cgit 1.4.1-3-g733a5 From d57192d5c17e3af2b1e73b26e5d35ac4af3e7160 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Sat, 25 Jun 2016 18:12:29 +0200 Subject: don't depend on regex_macros anymore --- .travis.yml | 7 ------- Cargo.toml | 6 +++--- mini-macro/Cargo.toml | 16 ++++++++++++++++ mini-macro/src/lib.rs | 22 ++++++++++++++++++++++ tests/compile-fail-regex_macros/regex.rs | 12 ------------ tests/compile-test.rs | 15 +-------------- tests/run-pass-regex_macros/mut_mut_macro.rs | 12 ------------ tests/run-pass/procedural_macro.rs | 7 +++++++ 8 files changed, 49 insertions(+), 48 deletions(-) create mode 100644 mini-macro/Cargo.toml create mode 100644 mini-macro/src/lib.rs delete mode 100644 tests/compile-fail-regex_macros/regex.rs delete mode 100644 tests/run-pass-regex_macros/mut_mut_macro.rs create mode 100644 tests/run-pass/procedural_macro.rs diff --git a/.travis.yml b/.travis.yml index d33f8604bcf..34e50956cc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,13 +26,6 @@ script: - cd clippy_lints && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. after_success: -# only test regex_macros if it compiles -- | - #!/bin/bash - cargo test --no-run --features 'debugging test-regex_macros' - if [ "$?" != 101 ]; then - cargo test --features 'debugging test-regex_macros' compile_test - fi # trigger rebuild of the clippy-service, to keep it up to date with clippy itself - | #!/bin/bash diff --git a/Cargo.toml b/Cargo.toml index d3e67bdb7e1..9b68a7364ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ name = "cargo-clippy" test = false [dependencies] -regex_macros = { version = "0.1.33", optional = true } # begin automatic update clippy_lints = { version = "0.0.77", path = "clippy_lints" } # end automatic update @@ -32,9 +31,10 @@ clippy_lints = { version = "0.0.77", path = "clippy_lints" } [dev-dependencies] compiletest_rs = "0.2.0" lazy_static = "0.1.15" -regex = "0.1.56" +regex = "0.1.71" rustc-serialize = "0.3" +mini-macro = { version = "0.1", path = "mini-macro" } + [features] debugging = [] -test-regex_macros = ["regex_macros"] diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml new file mode 100644 index 00000000000..171e5dd8172 --- /dev/null +++ b/mini-macro/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "mini-macro" +version = "0.1.0" +authors = [ + "Manish Goregaokar <manishsmail@gmail.com>", + "Andre Bogus <bogusandre@gmail.com>", + "Georg Brandl <georg@python.org>", + "Martin Carton <cartonmartin@gmail.com>", + "Oliver Schneider <clippy-iethah7aipeen8neex1a@oli-obk.de>" +] + +[lib] +name = "mini_macro" +plugin = true + +[dependencies] diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs new file mode 100644 index 00000000000..699d17d4d70 --- /dev/null +++ b/mini-macro/src/lib.rs @@ -0,0 +1,22 @@ +#![feature(plugin_registrar, rustc_private)] + +extern crate syntax; +extern crate rustc; +extern crate rustc_plugin; + +use syntax::codemap::Span; +use syntax::ast::TokenTree; +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; +use syntax::ext::build::AstBuilder; // trait for expr_usize +use rustc_plugin::Registry; + +fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box<MacResult + 'static> { + let e = cx.expr_usize(sp, 42); + let e = cx.expr_mut_addr_of(sp, e); + MacEager::expr(cx.expr_mut_addr_of(sp, e)) +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_macro("mini_macro", expand_macro); +} diff --git a/tests/compile-fail-regex_macros/regex.rs b/tests/compile-fail-regex_macros/regex.rs deleted file mode 100644 index aab196fb795..00000000000 --- a/tests/compile-fail-regex_macros/regex.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy, regex_macros)] - -#![allow(unused)] -#![deny(invalid_regex, trivial_regex, regex_macro)] - -extern crate regex; - -fn main() { - let some_regex = regex!("for real!"); //~ERROR `regex!(_)` - let other_regex = regex!("[a-z]_[A-Z]"); //~ERROR `regex!(_)` -} diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 2e50f7d9241..d21d9750924 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,7 +1,7 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; -use std::env::{set_var, var, temp_dir}; +use std::env::{set_var, var}; fn run_mode(dir: &'static str, mode: &'static str) { let mut config = compiletest::default_config(); @@ -14,10 +14,6 @@ fn run_mode(dir: &'static str, mode: &'static str) { } config.mode = cfg_mode; - if cfg!(windows) { - // work around https://github.com/laumann/compiletest-rs/issues/35 on msvc windows - config.build_base = temp_dir(); - } config.src_base = PathBuf::from(format!("tests/{}", dir)); compiletest::run_tests(&config); @@ -28,17 +24,8 @@ fn prepare_env() { } #[test] -#[cfg(not(feature = "test-regex_macros"))] fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("compile-fail", "compile-fail"); } - -#[test] -#[cfg(feature = "test-regex_macros")] -fn compile_test() { - prepare_env(); - run_mode("run-pass-regex_macros", "run-pass"); - run_mode("compile-fail-regex_macros", "compile-fail"); -} diff --git a/tests/run-pass-regex_macros/mut_mut_macro.rs b/tests/run-pass-regex_macros/mut_mut_macro.rs deleted file mode 100644 index 92b44dbdd48..00000000000 --- a/tests/run-pass-regex_macros/mut_mut_macro.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy, regex_macros)] - -#[macro_use] -extern crate regex; - -#[deny(mut_mut)] -#[allow(regex_macro)] -fn main() { - let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); - assert!(pattern.is_match("# headline")); -} diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs new file mode 100644 index 00000000000..68d86a4d394 --- /dev/null +++ b/tests/run-pass/procedural_macro.rs @@ -0,0 +1,7 @@ +#![feature(plugin)] +#![plugin(clippy, mini_macro)] + +#[deny(warnings)] +fn main() { + let _ = mini_macro!(); +} -- cgit 1.4.1-3-g733a5 From 8c5e617c9a22de40cbde76e8aa2d0fd49d0303f5 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Sat, 25 Jun 2016 18:59:37 +0200 Subject: don't lint on comparing `*const f32`s --- clippy_lints/src/utils/mod.rs | 6 ++---- tests/compile-fail/float_cmp.rs | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a2b2ecfbcc0..e35b1bbac6b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -523,8 +523,7 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { - ty::TyRef(_, ref tm) | - ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), + ty::TyRef(_, ref tm) => walk_ptrs_ty(tm.ty), _ => ty, } } @@ -533,8 +532,7 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { match ty.sty { - ty::TyRef(_, ref tm) | - ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), + ty::TyRef(_, ref tm) => inner(tm.ty, depth + 1), _ => (ty, depth), } } diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 85df1ded5ac..9f611dd3fd9 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -63,4 +63,10 @@ fn main() { x > 0.0; x <= 0.0; x >= 0.0; + + let xs : [f32; 1] = [0.0]; + let a: *const f32 = xs.as_ptr(); + let b: *const f32 = xs.as_ptr(); + + assert!(a == b); // no errors } -- cgit 1.4.1-3-g733a5 From 2e86eb88f3e36a74ab59bfaa77fe01cf8d1cc028 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Sun, 26 Jun 2016 13:26:30 +0200 Subject: rename mini-macro to clippy-mini-macro-test --- Cargo.toml | 2 +- mini-macro/Cargo.toml | 7 +++++-- tests/run-pass/procedural_macro.rs | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9b68a7364ff..5dc1363f3f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ compiletest_rs = "0.2.0" lazy_static = "0.1.15" regex = "0.1.71" rustc-serialize = "0.3" -mini-macro = { version = "0.1", path = "mini-macro" } +clippy-mini-macro-test = { version = "0.1", path = "mini-macro" } [features] diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml index 171e5dd8172..f884ab48059 100644 --- a/mini-macro/Cargo.toml +++ b/mini-macro/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mini-macro" +name = "clippy-mini-macro-test" version = "0.1.0" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", @@ -8,9 +8,12 @@ authors = [ "Martin Carton <cartonmartin@gmail.com>", "Oliver Schneider <clippy-iethah7aipeen8neex1a@oli-obk.de>" ] +license = "MPL-2.0" +description = "A macro to test clippy's procedural macro checks" +repository = "https://github.com/Manishearth/rust-clippy" [lib] -name = "mini_macro" +name = "clippy_mini_macro_test" plugin = true [dependencies] diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index 68d86a4d394..91269726172 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -1,5 +1,5 @@ #![feature(plugin)] -#![plugin(clippy, mini_macro)] +#![plugin(clippy, clippy_mini_macro_test)] #[deny(warnings)] fn main() { -- cgit 1.4.1-3-g733a5 From 083c57867a66f4fc3ba882ebd2515012e79f93a7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 27 Jun 2016 13:46:21 +0200 Subject: refactor transmute lints into a single match --- clippy_lints/src/transmute.rs | 104 +++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 5d3f27b074b..718111bee65 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; -use rustc::ty; use rustc::hir::*; use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; @@ -66,66 +65,59 @@ impl LateLintPass for Transmute { let from_ty = cx.tcx.expr_ty(&args[0]); let to_ty = cx.tcx.expr_ty(e); - if from_ty == to_ty { - span_lint(cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty)); - } else if is_ptr_to(to_ty, from_ty) { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", - from_ty, - to_ty)); - } else if is_ptr_to(from_ty, to_ty) { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty)); - } else { - check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); - } - } - } - } - } -} + match (&from_ty.sty, &to_ty.sty) { + _ if from_ty == to_ty => span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ), + (&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty), + ), + (_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", + from_ty, + to_ty), + ), + (&TyRawPtr(from_pty), &TyRef(_, to_rty)) => span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", + from_ty, + to_ty), + |db| { + if let Some(arg) = snippet_opt(cx, args[0].span) { + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; -fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { - if let TyRawPtr(from_ptr) = from.sty { - from_ptr.ty == to - } else { - false - } -} - -fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) { - if let TyRawPtr(ref from_pty) = from_ty.sty { - if let TyRef(_, ref to_rty) = to_ty.sty { - let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", - from_ty, - to_ty); - span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| { - if let Some(arg) = snippet_opt(cx, arg.span) { - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + let sugg = if from_pty.ty == to_rty.ty { + format!("{}{}", deref, arg) + } else { + format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + }; - let sugg = if from_pty.ty == to_rty.ty { - format!("{}{}", deref, arg) - } else { - format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + db.span_suggestion(e.span, "try", sugg); + } + }, + ), + _ => return, }; - - db.span_suggestion(e.span, "try", sugg); } - }); + } } } } -- cgit 1.4.1-3-g733a5 From a469ee1061fbccd4dda79e07017d35189e367b0e Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 27 Jun 2016 16:12:48 +0200 Subject: lint transmuting references to pointers --- clippy_lints/src/transmute.rs | 17 +++++++++++++++++ tests/compile-fail/transmute.rs | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 718111bee65..0d68789e0be 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -72,6 +72,23 @@ impl LateLintPass for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), + (&TyRef(_, rty), &TyRawPtr(ptr_ty)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |db| { + if let Some(arg) = snippet_opt(cx, args[0].span) { + let sugg = if ptr_ty == rty { + format!("{} as {}", arg, to_ty) + } else { + format!("{} as {} as {}", arg, cx.tcx.mk_ptr(rty), to_ty) + }; + + db.span_suggestion(e.span, "try", sugg); + } + }, + ), (&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index ad97410cf65..4cd19f9bec9 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -21,6 +21,21 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { //~^ ERROR transmute from a type (`&'a T`) to itself let _: &'a U = core::intrinsics::transmute(t); + + let _: *const T = core::intrinsics::transmute(t); + //~^ ERROR transmute from a reference to a pointer + //~| HELP try + //~| SUGGESTION = t as *const T + + let _: *mut T = core::intrinsics::transmute(t); + //~^ ERROR transmute from a reference to a pointer + //~| HELP try + //~| SUGGESTION = t as *const T as *mut T + + let _: *const U = core::intrinsics::transmute(t); + //~^ ERROR transmute from a reference to a pointer + //~| HELP try + //~| SUGGESTION = t as *const T as *const U } #[deny(transmute_ptr_to_ref)] -- cgit 1.4.1-3-g733a5 From 799861d7e03cb9b4d9c1edc4ec491602166aed1c Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 27 Jun 2016 17:14:04 +0200 Subject: use span_lint_and_then instead of adding to the `DiagnosticWrapper` --- clippy_lints/src/methods.rs | 52 +++++++++++++++-------------- clippy_lints/src/new_without_default.rs | 38 +++++++++++---------- clippy_lints/src/shadow.rs | 59 ++++++++++++++++----------------- clippy_lints/src/utils/mod.rs | 40 ++++++---------------- 4 files changed, 85 insertions(+), 104 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 950a03159b2..a959dbe1d6a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -536,13 +536,14 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi }; if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) { - span_lint(cx, + span_lint_and_then(cx, OR_FUN_CALL, span, - &format!("use of `{}` followed by a call to `{}`", name, path)) - .span_suggestion(span, - "try this", - format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); + &format!("use of `{}` followed by a call to `{}`", name, path), + |db| { + db.span_suggestion(span, "try this", + format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); + }); return true; } } @@ -590,10 +591,11 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi (false, true) => snippet(cx, fun.span, ".."), }; - span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name)) - .span_suggestion(span, - "try this", - format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); + span_lint_and_then(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name), |db| { + db.span_suggestion(span, + "try this", + format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); + }); } if args.len() == 2 { @@ -621,15 +623,14 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) { fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) { if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty { if let ty::TyRef(..) = inner.sty { - let mut db = span_lint(cx, - CLONE_DOUBLE_REF, - expr.span, - "using `clone` on a double-reference; \ - this will copy the reference instead of cloning \ - the inner type"); - if let Some(snip) = snippet_opt(cx, arg.span) { - db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); - } + span_lint_and_then(cx, + CLONE_DOUBLE_REF, + expr.span, + "using `clone` on a double-reference; \ + this will copy the reference instead of cloning the inner type", + |db| if let Some(snip) = snippet_opt(cx, arg.span) { + db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); + }); } } } @@ -641,13 +642,14 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) { } let arg_ty = cx.tcx.expr_ty(&args[1]); if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { - span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice") - .span_suggestion(expr.span, - "try this", - format!("{}.extend_from_slice({}{})", - snippet(cx, args[0].span, "_"), - r, - snippet(cx, span, "_"))); + span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| { + db.span_suggestion(expr.span, + "try this", + format!("{}.extend_from_slice({}{})", + snippet(cx, args[0].span, "_"), + r, + snippet(cx, span, "_"))); + }); } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index f400f1b6643..20c0d282bd8 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -6,7 +6,7 @@ use rustc::ty; use syntax::ast; use syntax::codemap::Span; use utils::paths; -use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; /// **What it does:** This lints about type with a `fn new() -> Self` method /// and no implementation of @@ -112,24 +112,26 @@ impl LateLintPass for NewWithoutDefault { !implements_trait(cx, self_ty, default_trait_id, Vec::new()) ], { if can_derive_default(self_ty, cx, default_trait_id) { - span_lint(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty)). - span_suggestion(span, - "try this", - "#[derive(Default)]".into()); + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.span_suggestion(span, "try this", "#[derive(Default)]".into()); + }); } else { - span_lint(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty)). - span_suggestion(span, - "try this", - format!("impl Default for {} {{ fn default() -> \ - Self {{ {}::new() }} }}", self_ty, self_ty)); + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.span_suggestion(span, + "try this", + format!("impl Default for {} {{ fn default() -> \ + Self {{ {}::new() }} }}", self_ty, self_ty)); + }); } }} } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 5bb3e006862..b12e68185c2 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{Visitor, FnKind}; use std::ops::Deref; use syntax::codemap::Span; -use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper}; +use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint_and_then}; /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. /// @@ -197,49 +197,46 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span) where T: Deref<Target = Expr> { - fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) { - if cx.current_level(lint) != Level::Allow { - db.span_note(span, "previous binding is here"); - } - } if let Some(ref expr) = *init { if is_self_shadow(name, expr) { - let db = span_lint(cx, + span_lint_and_then(cx, SHADOW_SAME, span, &format!("`{}` is shadowed by itself in `{}`", snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, ".."))); - - note_orig(cx, db, SHADOW_SAME, prev_span); + snippet(cx, expr.span, "..")), + |db| { db.span_note(prev_span, "previous binding is here"); }, + ); } else if contains_self(name, expr) { - let db = span_note_and_lint(cx, - SHADOW_REUSE, - pattern_span, - &format!("`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_REUSE, prev_span); + span_lint_and_then(cx, + SHADOW_REUSE, + pattern_span, + &format!("`{}` is shadowed by `{}` which reuses the original value", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..")), + |db| { + db.span_note(expr.span, "initialization happens here"); + db.span_note(prev_span, "previous binding is here"); + }); } else { - let db = span_note_and_lint(cx, - SHADOW_UNRELATED, - pattern_span, - &format!("`{}` is shadowed by `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - expr.span, - "initialization happens here"); - note_orig(cx, db, SHADOW_UNRELATED, prev_span); + span_lint_and_then(cx, + SHADOW_UNRELATED, + pattern_span, + &format!("`{}` is shadowed by `{}`", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..")), + |db| { + db.span_note(expr.span, "initialization happens here"); + db.span_note(prev_span, "previous binding is here"); + }); } } else { - let db = span_lint(cx, + span_lint_and_then(cx, SHADOW_UNRELATED, span, - &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_"))); - note_orig(cx, db, SHADOW_UNRELATED, prev_span); + &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")), + |db| { db.span_note(prev_span, "previous binding is here"); }); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e35b1bbac6b..9eb54c2a013 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -12,7 +12,6 @@ use rustc::ty; use std::borrow::Cow; use std::env; use std::mem; -use std::ops::{Deref, DerefMut}; use std::str::FromStr; use syntax::ast::{self, LitKind, RangeLimits}; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; @@ -453,71 +452,52 @@ impl<'a> Drop for DiagnosticWrapper<'a> { } } -impl<'a> DerefMut for DiagnosticWrapper<'a> { - fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> { - &mut self.0 - } -} - -impl<'a> Deref for DiagnosticWrapper<'a> { - type Target = DiagnosticBuilder<'a>; - fn deref(&self) -> &DiagnosticBuilder<'a> { - &self.0 - } -} - impl<'a> DiagnosticWrapper<'a> { fn wiki_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { - self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + self.0.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", lint.name_lower())); } } } -pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> { +pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { db.wiki_link(lint); } - db } -pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) - -> DiagnosticWrapper<'a> { +// FIXME: needless lifetime doesn't trigger here +pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { - db.help(help); + db.0.help(help); db.wiki_link(lint); } - db } pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span, - note: &str) - -> DiagnosticWrapper<'a> { + note: &str) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { if note_span == span { - db.note(note); + db.0.note(note); } else { - db.span_note(note_span, note); + db.0.span_note(note_span, note); } db.wiki_link(lint); } - db } pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) - -> DiagnosticWrapper<'a> - where F: FnOnce(&mut DiagnosticWrapper) + where F: FnOnce(&mut DiagnosticBuilder<'a>) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { - f(&mut db); + f(&mut db.0); db.wiki_link(lint); } - db } /// Return the base type for references and raw pointers. -- cgit 1.4.1-3-g733a5 From f4115f104ed7fea4bb21f0f13423dde29ca0c64f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Mon, 27 Jun 2016 21:08:16 +0530 Subject: readme formatting nit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a6d212add7..c01fac4d5f9 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ In your `Cargo.toml`: clippy = {version = "*", optional = true} [features] -default=[] +default = [] ``` And, in your `main.rs` or `lib.rs`: -- cgit 1.4.1-3-g733a5 From cdce78a4be1b6e4887003425b4d09cae9fdd2888 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Tue, 28 Jun 2016 12:18:44 +0530 Subject: Add parentheses when necessary in transmute suggestion (fixes #1049) --- clippy_lints/src/transmute.rs | 8 +++++++- tests/compile-fail/transmute.rs | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 0d68789e0be..074e4bffec1 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -122,7 +122,13 @@ impl LateLintPass for Transmute { let sugg = if from_pty.ty == to_rty.ty { - format!("{}{}", deref, arg) + // Put things in parentheses if they are more complex + match args[0].node { + ExprPath(..) | ExprCall(..) | ExprMethodCall(..) | ExprBlock(..) => { + format!("{}{}", deref, arg) + } + _ => format!("{}({})", deref, arg) + } } else { format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) }; diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 4cd19f9bec9..a0f7ba0ccde 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -58,6 +58,11 @@ unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { //~| SUGGESTION = &*m; let _: &T = &*m; + let _: &mut T = std::mem::transmute(p as *mut T); + //~^ ERROR transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) + //~| HELP try + //~| SUGGESTION = &mut *(p as *mut T); + let _: &T = std::mem::transmute(o); //~^ ERROR transmute from a pointer type (`*const U`) to a reference type (`&T`) //~| HELP try -- cgit 1.4.1-3-g733a5 From e06bc374776fddaed4d3dffb19b3f40f29bb6995 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Tue, 28 Jun 2016 14:08:08 +0200 Subject: lint on unnecessary and plain wrong transmutes --- CHANGELOG.md | 4 ++++ README.md | 5 ++-- clippy_lints/src/lib.rs | 1 + clippy_lints/src/transmute.rs | 43 +++++++++++++++++++++++++++++++---- tests/compile-fail/transmute.rs | 33 ++++++++++++++++----------- tests/compile-fail/transmute_32bit.rs | 20 ++++++++++++++++ tests/compile-fail/transmute_64bit.rs | 15 ++++++++++++ 7 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 tests/compile-fail/transmute_32bit.rs create mode 100644 tests/compile-fail/transmute_64bit.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 728ed347da2..a71b410a5f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.78 - TBA +* New lints: [`wrong_transmute`] + ## 0.0.77 — 2016-06-21 * Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)* * New lints: [`stutter`] and [`iter_nth`] @@ -276,6 +279,7 @@ All notable changes to this project will be documented in this file. [`while_let_on_iterator`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator [`wrong_pub_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention [`wrong_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention +[`wrong_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute [`zero_divided_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero [`zero_width_space`]: https://github.com/Manishearth/rust-clippy/wiki#zero_width_space <!-- end autogenerated links to wiki --> diff --git a/README.md b/README.md index 8a6d212add7..d5e80238695 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 155 lints included in this crate: +There are 156 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -168,12 +168,13 @@ name [used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore [useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` [useless_let_if_seq](https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq) | warn | Checks for unidiomatic `let mut` declaration followed by initialization in `if` -[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types +[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention [wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_transmute](https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute) | warn | transmutes that are confusing at best, undefined behaviour at worst and always useless [zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 835823b8cd3..3fd94661f67 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -403,6 +403,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::CROSSPOINTER_TRANSMUTE, transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, + transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BOX_VEC, types::CHAR_LIT_AS_U8, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 0d68789e0be..61c5a7b2339 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,11 +1,25 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; +use rustc::ty; use rustc::hir::*; use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; -/// **What it does:** This lint checks for transmutes to the original type of the object. +/// **What it does:** This lint checks for transmutes that can't ever be correct on any architecture /// -/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type. +/// **Why is this bad?** It's basically guaranteed to be undefined behaviour +/// +/// **Known problems:** When accessing C, users might want to store pointer sized objects in `extradata` arguments to save an allocation. +/// +/// **Example:** `let ptr: *const T = core::intrinsics::transmute('x')`. +declare_lint! { + pub WRONG_TRANSMUTE, + Warn, + "transmutes that are confusing at best, undefined behaviour at worst and always useless" +} + +/// **What it does:** This lint checks for transmutes to the original type of the object and transmutes that could be a cast. +/// +/// **Why is this bad?** Readability. The code tricks people into thinking that something complex is going on /// /// **Known problems:** None. /// @@ -13,7 +27,7 @@ use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; declare_lint! { pub USELESS_TRANSMUTE, Warn, - "transmutes that have the same to and from types" + "transmutes that have the same to and from types or could be a cast/coercion" } /// **What it does:*** This lint checks for transmutes between a type `T` and `*T`. @@ -51,7 +65,7 @@ pub struct Transmute; impl LintPass for Transmute { fn get_lints(&self) -> LintArray { - lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE] + lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE] } } @@ -89,6 +103,27 @@ impl LateLintPass for Transmute { } }, ), + (&ty::TyInt(_), &TyRawPtr(_)) | + (&ty::TyUint(_), &TyRawPtr(_)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| { + if let Some(arg) = snippet_opt(cx, args[0].span) { + db.span_suggestion(e.span, "try", format!("{} as {}", arg, to_ty)); + } + }, + ), + (&ty::TyFloat(_), &TyRef(..)) | + (&ty::TyFloat(_), &TyRawPtr(_)) | + (&ty::TyChar, &TyRef(..)) | + (&ty::TyChar, &TyRawPtr(_)) => span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), + ), (&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 4cd19f9bec9..f2762b1767a 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -6,8 +6,8 @@ extern crate core; use std::mem::transmute as my_transmute; use std::vec::Vec as MyVec; -fn my_int() -> usize { - 42 +fn my_int() -> Usize { + Usize(42) } fn my_vec() -> MyVec<i32> { @@ -100,27 +100,34 @@ fn useless() { let _: Vec<u32> = std::intrinsics::transmute(my_vec()); let _: Vec<u32> = std::mem::transmute(my_vec()); let _: Vec<u32> = my_transmute(my_vec()); + + let _: *const usize = std::mem::transmute(5_isize); + //~^ ERROR transmute from an integer to a pointer + //~| HELP try + //~| SUGGESTION 5_isize as *const usize } } +struct Usize(usize); + #[deny(crosspointer_transmute)] fn crosspointer() { - let mut int: usize = 0; - let int_const_ptr: *const usize = &int as *const usize; - let int_mut_ptr: *mut usize = &mut int as *mut usize; + let mut int: Usize = Usize(0); + let int_const_ptr: *const Usize = &int as *const Usize; + let int_mut_ptr: *mut Usize = &mut int as *mut Usize; unsafe { - let _: usize = core::intrinsics::transmute(int_const_ptr); - //~^ ERROR transmute from a type (`*const usize`) to the type that it points to (`usize`) + let _: Usize = core::intrinsics::transmute(int_const_ptr); + //~^ ERROR transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - let _: usize = core::intrinsics::transmute(int_mut_ptr); - //~^ ERROR transmute from a type (`*mut usize`) to the type that it points to (`usize`) + let _: Usize = core::intrinsics::transmute(int_mut_ptr); + //~^ ERROR transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - let _: *const usize = core::intrinsics::transmute(my_int()); - //~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*const usize`) + let _: *const Usize = core::intrinsics::transmute(my_int()); + //~^ ERROR transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - let _: *mut usize = core::intrinsics::transmute(my_int()); - //~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*mut usize`) + let _: *mut Usize = core::intrinsics::transmute(my_int()); + //~^ ERROR transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) } } diff --git a/tests/compile-fail/transmute_32bit.rs b/tests/compile-fail/transmute_32bit.rs new file mode 100644 index 00000000000..1368ab5015d --- /dev/null +++ b/tests/compile-fail/transmute_32bit.rs @@ -0,0 +1,20 @@ +//ignore-x86_64 +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(wrong_transmute)] +fn main() { + unsafe { + let _: *const usize = std::mem::transmute(6.0f32); + //~^ ERROR transmute from a `f32` to a pointer + + let _: *mut usize = std::mem::transmute(6.0f32); + //~^ ERROR transmute from a `f32` to a pointer + + let _: *const usize = std::mem::transmute('x'); + //~^ ERROR transmute from a `char` to a pointer + + let _: *mut usize = std::mem::transmute('x'); + //~^ ERROR transmute from a `char` to a pointer + } +} diff --git a/tests/compile-fail/transmute_64bit.rs b/tests/compile-fail/transmute_64bit.rs new file mode 100644 index 00000000000..8bc6a2367b9 --- /dev/null +++ b/tests/compile-fail/transmute_64bit.rs @@ -0,0 +1,15 @@ +//ignore-x86 +//no-ignore-x86_64 +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(wrong_transmute)] +fn main() { + unsafe { + let _: *const usize = std::mem::transmute(6.0f64); + //~^ ERROR transmute from a `f64` to a pointer + + let _: *mut usize = std::mem::transmute(6.0f64); + //~^ ERROR transmute from a `f64` to a pointer + } +} -- cgit 1.4.1-3-g733a5 From e4dceef7e79c96c4ddeffd59a2c532bd239f98a6 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 13:58:07 +0200 Subject: Revert "Automatically defines the `clippy` feature" This reverts commit d7ba66bf44f993e64114e17cc15f1b0d56ae8f70. It was causing problems with crates with: ```rust #![cfg_attr(feature="clippy", plugin(clippy))] ``` --- CHANGELOG.md | 2 ++ README.md | 7 ------- src/main.rs | 7 +------ 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a71b410a5f6..168d7a12065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. ## 0.0.78 - TBA * New lints: [`wrong_transmute`] +* For compatibility, `cargo clippy` does not defines the `clippy` feature + introduced in 0.0.76 anymore ## 0.0.77 — 2016-06-21 * Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)* diff --git a/README.md b/README.md index 5096ee953b2..2f54835d538 100644 --- a/README.md +++ b/README.md @@ -326,13 +326,6 @@ You can add options to `allow`/`warn`/`deny`: Note: `deny` produces errors instead of warnings. -For convenience, `cargo clippy` automatically defines a `clippy` features. This -lets you set lints level and compile with or without clippy transparently: - -```rust -#[cfg_attr(feature = "clippy", allow(needless_lifetimes))] -``` - ## Link with clippy service `clippy-service` is a rust web initiative providing `rust-clippy` as a web service. diff --git a/src/main.rs b/src/main.rs index cf57926440b..17a219cafa0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,14 +149,11 @@ pub fn main() { } } } else { - let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") { + let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { env::args().collect() } else { env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() }; - - args.extend_from_slice(&["--cfg".to_owned(), r#"feature="clippy""#.to_owned()]); - let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); if let Err(err_count) = result { @@ -187,8 +184,6 @@ fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32> args.push(String::from("--sysroot")); args.push(sysroot.to_owned()); args.push("-Zno-trans".to_owned()); - args.push("--cfg".to_owned()); - args.push(r#"feature="clippy""#.to_owned()); let path = std::env::current_exe().expect("current executable path invalid"); let exit_status = std::process::Command::new("cargo") -- cgit 1.4.1-3-g733a5 From 7fa38f678764d7d5203cd4155eb39a355857e1ce Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 22:54:22 +0200 Subject: Fix FP with `mut_mut` and `for` loops --- clippy_lints/src/mut_mut.rs | 63 ++++++++++++++++++++++++++++++------------- tests/compile-fail/mut_mut.rs | 27 ++++++++++++++++--- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 0bed45b0b5b..8a5439fb11e 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,7 +1,8 @@ +use rustc::hir; +use rustc::hir::intravisit; use rustc::lint::*; use rustc::ty::{TypeAndMut, TyRef}; -use rustc::hir::*; -use utils::{in_external_macro, span_lint}; +use utils::{in_external_macro, recover_for_loop, span_lint}; /// **What it does:** This lint checks for instances of `mut mut` references. /// @@ -27,30 +28,56 @@ impl LintPass for MutMut { } impl LateLintPass for MutMut { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { + fn check_block(&mut self, cx: &LateContext, block: &hir::Block) { + intravisit::walk_block(&mut MutVisitor { cx: cx }, block); + } + + fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) { + use rustc::hir::intravisit::Visitor; + + MutVisitor { cx: cx }.visit_ty(ty); + } +} + +pub struct MutVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, +} + +impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'v hir::Expr) { + if in_external_macro(self.cx, expr.span) { return; } - if let ExprAddrOf(MutMutable, ref e) = expr.node { - if let ExprAddrOf(MutMutable, _) = e.node { - span_lint(cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible"); - } else { - if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty { - span_lint(cx, - MUT_MUT, - expr.span, - "this expression mutably borrows a mutable reference. Consider reborrowing"); - } + if let Some((_, arg, body)) = recover_for_loop(expr) { + // A `for` loop lowers to: + // ```rust + // match ::std::iter::Iterator::next(&mut iter) { + // // ^^^^ + // ``` + // Let's ignore the generated code. + intravisit::walk_expr(self, arg); + intravisit::walk_expr(self, body); + } else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node { + if let hir::ExprAddrOf(hir::MutMutable, _) = e.node { + span_lint(self.cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible"); + } else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.expr_ty(e).sty { + span_lint(self.cx, + MUT_MUT, + expr.span, + "this expression mutably borrows a mutable reference. Consider reborrowing"); } } } - fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { - if let TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) = ty.node { - if let TyRptr(_, MutTy { mutbl: MutMutable, .. }) = pty.node { - span_lint(cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); + fn visit_ty(&mut self, ty: &hir::Ty) { + if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node { + if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node { + span_lint(self.cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible"); } + } + + intravisit::walk_ty(self, ty); } } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 21c0dcee511..edcc6906f08 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -2,16 +2,15 @@ #![plugin(clippy)] #![allow(unused, no_effect, unnecessary_operation)] +#![deny(mut_mut)] //#![plugin(regex_macros)] //extern crate regex; -#[deny(mut_mut)] fn fun(x : &mut &mut u32) -> bool { //~ERROR generally you want to avoid `&mut &mut **x > 0 } -#[deny(mut_mut)] fn less_fun(x : *mut *mut u32) { let y = x; } @@ -21,7 +20,6 @@ macro_rules! mut_ptr { //~^ ERROR generally you want to avoid `&mut &mut } -#[deny(mut_mut)] #[allow(unused_mut, unused_variables)] fn main() { let mut x = &mut &mut 1u32; //~ERROR generally you want to avoid `&mut &mut @@ -29,15 +27,38 @@ fn main() { let mut y = &mut x; //~ERROR this expression mutably borrows a mutable reference } + if fun(x) { + let y : &mut &mut u32 = &mut &mut 2; + //~^ ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut + **y + **x; + } + if fun(x) { let y : &mut &mut &mut u32 = &mut &mut &mut 2; //~^ ERROR generally you want to avoid `&mut &mut //~| ERROR generally you want to avoid `&mut &mut //~| ERROR generally you want to avoid `&mut &mut //~| ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut + //~| ERROR generally you want to avoid `&mut &mut ***y + **x; } let mut z = mut_ptr!(&mut 3u32); //~^ NOTE in this expansion of mut_ptr! } + +fn issue939() { + let array = [5, 6, 7, 8, 9]; + let mut args = array.iter().skip(2); + for &arg in &mut args { + println!("{}", arg); + } + + let args = &mut args; + for arg in args { + println!(":{}", arg); + } +} -- cgit 1.4.1-3-g733a5 From f37c9adbd9f0bae62965fe4197467619fdff5571 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 23:17:18 +0200 Subject: Make `CollapsibleIf` an `EarlyLintPass` It doesn't need any `hir` feature and `ast` is much more stable. --- clippy_lints/src/collapsible_if.rs | 31 +++++++++++++++---------------- clippy_lints/src/lib.rs | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 38e04723e53..9bdc35596bf 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -13,9 +13,9 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::*; use std::borrow::Cow; use syntax::codemap::Spanned; +use syntax::ast; use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; @@ -45,23 +45,22 @@ impl LintPass for CollapsibleIf { } } -impl LateLintPass for CollapsibleIf { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { +impl EarlyLintPass for CollapsibleIf { + fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { if !in_macro(cx, expr.span) { check_if(cx, expr) } } } -fn check_if(cx: &LateContext, e: &Expr) { - if let ExprIf(ref check, ref then, ref else_) = e.node { +fn check_if(cx: &EarlyContext, e: &ast::Expr) { + if let ast::ExprKind::If(ref check, ref then, ref else_) = e.node { if let Some(ref else_) = *else_ { if_let_chain! {[ - let ExprBlock(ref block) = else_.node, + let ast::ExprKind::Block(ref block) = else_.node, block.stmts.is_empty(), - block.rules == BlockCheckMode::DefaultBlock, let Some(ref else_) = block.expr, - let ExprIf(_, _, _) = else_.node + let ast::ExprKind::If(_, _, _) = else_.node ], { span_lint_and_then(cx, COLLAPSIBLE_IF, @@ -70,7 +69,7 @@ fn check_if(cx: &LateContext, e: &Expr) { db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); }); }} - } else if let Some(&Expr { node: ExprIf(ref check_inner, ref content, None), span: sp, .. }) = + } else if let Some(&ast::Expr { node: ast::ExprKind::If(ref check_inner, ref content, None), span: sp, .. }) = single_stmt_of_block(then) { if e.span.expn_id != sp.expn_id { return; @@ -87,14 +86,14 @@ fn check_if(cx: &LateContext, e: &Expr) { } } -fn requires_brackets(e: &Expr) -> bool { +fn requires_brackets(e: &ast::Expr) -> bool { match e.node { - ExprBinary(Spanned { node: n, .. }, _, _) if n == BiEq => false, + ast::ExprKind::Binary(Spanned { node: n, .. }, _, _) if n == ast::BinOpKind::Eq => false, _ => true, } } -fn check_to_string(cx: &LateContext, e: &Expr) -> Cow<'static, str> { +fn check_to_string(cx: &EarlyContext, e: &ast::Expr) -> Cow<'static, str> { if requires_brackets(e) { format!("({})", snippet(cx, e.span, "..")).into() } else { @@ -102,9 +101,9 @@ fn check_to_string(cx: &LateContext, e: &Expr) -> Cow<'static, str> { } } -fn single_stmt_of_block(block: &Block) -> Option<&Expr> { +fn single_stmt_of_block(block: &ast::Block) -> Option<&ast::Expr> { if block.stmts.len() == 1 && block.expr.is_none() { - if let StmtExpr(ref expr, _) = block.stmts[0].node { + if let ast::StmtKind::Expr(ref expr, _) = block.stmts[0].node { single_stmt_of_expr(expr) } else { None @@ -120,8 +119,8 @@ fn single_stmt_of_block(block: &Block) -> Option<&Expr> { } } -fn single_stmt_of_expr(expr: &Expr) -> Option<&Expr> { - if let ExprBlock(ref block) = expr.node { +fn single_stmt_of_expr(expr: &ast::Expr) -> Option<&ast::Expr> { + if let ast::ExprKind::Block(ref block) = expr.node { single_stmt_of_block(block) } else { Some(expr) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fd94661f67..e980f4d081d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -189,7 +189,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box len_zero::LenZero); reg.register_late_lint_pass(box misc::CmpOwned); reg.register_late_lint_pass(box attrs::AttrPass); - reg.register_late_lint_pass(box collapsible_if::CollapsibleIf); + reg.register_early_lint_pass(box collapsible_if::CollapsibleIf); reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition); reg.register_late_lint_pass(box misc::ModuloOne); reg.register_late_lint_pass(box unicode::Unicode); -- cgit 1.4.1-3-g733a5 From f6ba217c1c01b8e24c404d27ea9aba270d5831d2 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 23:53:24 +0200 Subject: Small cleanup --- clippy_lints/src/minmax.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index a88324aaf50..8d3af7742a9 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -83,11 +83,9 @@ fn fetch_const(args: &[P<Expr>], m: MinMax) -> Option<(MinMax, Constant, &Expr)> } else { None } + } else if let Some(c) = constant_simple(&args[1]) { + Some((m, c, &args[0])) } else { - if let Some(c) = constant_simple(&args[1]) { - Some((m, c, &args[0])) - } else { - None - } + None } } -- cgit 1.4.1-3-g733a5 From ea76ac55622250a916898f9c3f6b79b80f074b8e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 23:53:45 +0200 Subject: Make `COLLAPSIBLE_IF` consider `if let` --- clippy_lints/src/collapsible_if.rs | 73 ++++++++++++++++++++++---------- tests/compile-fail/collapsible_if.rs | 81 +++++++++++++++++++++++++++++++++--- tests/compile-fail/copies.rs | 1 + 3 files changed, 126 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 9bdc35596bf..2921bc2769c 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -53,37 +53,64 @@ impl EarlyLintPass for CollapsibleIf { } } -fn check_if(cx: &EarlyContext, e: &ast::Expr) { - if let ast::ExprKind::If(ref check, ref then, ref else_) = e.node { - if let Some(ref else_) = *else_ { - if_let_chain! {[ - let ast::ExprKind::Block(ref block) = else_.node, - block.stmts.is_empty(), - let Some(ref else_) = block.expr, - let ast::ExprKind::If(_, _, _) = else_.node - ], { +fn check_if(cx: &EarlyContext, expr: &ast::Expr) { + match expr.node { + ast::ExprKind::If(ref check, ref then, ref else_) => { + if let Some(ref else_) = *else_ { + check_collapsible_maybe_if_let(cx, else_); + } else { + check_collapsible_no_if_let(cx, expr, check, then); + } + } + ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => { + check_collapsible_maybe_if_let(cx, else_); + } + _ => (), + } +} + +fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { + if_let_chain! {[ + let ast::ExprKind::Block(ref block) = else_.node, + block.stmts.is_empty(), + let Some(ref else_) = block.expr, + ], { + match else_.node { + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { span_lint_and_then(cx, COLLAPSIBLE_IF, block.span, "this `else { if .. }` block can be collapsed", |db| { db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); }); - }} - } else if let Some(&ast::Expr { node: ast::ExprKind::If(ref check_inner, ref content, None), span: sp, .. }) = - single_stmt_of_block(then) { - if e.span.expn_id != sp.expn_id { - return; } - span_lint_and_then(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", |db| { - db.span_suggestion(e.span, - "try", - format!("if {} && {} {}", - check_to_string(cx, check), - check_to_string(cx, check_inner), - snippet_block(cx, content.span, ".."))); - }); + _ => (), } - } + }} +} + +fn check_collapsible_no_if_let( + cx: &EarlyContext, + expr: &ast::Expr, + check: &ast::Expr, + then: &ast::Block, +) { + if_let_chain! {[ + let Some(inner) = single_stmt_of_block(then), + let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node, + ], { + if expr.span.expn_id != inner.span.expn_id { + return; + } + span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { + db.span_suggestion(expr.span, + "try", + format!("if {} && {} {}", + check_to_string(cx, check), + check_to_string(cx, check_inner), + snippet_block(cx, content.span, ".."))); + }); + }} } fn requires_brackets(e: &ast::Expr) -> bool { diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index 34c55499612..ea2ef284f38 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -26,9 +26,10 @@ fn main() { // Collaspe `else { if .. }` to `else if ..` if x == "hello" { print!("Hello "); - } else { //~ERROR: this `else { if .. }` - //~| HELP try - //~| SUGGESTION } else if y == "world" + } else { + //~^ ERROR: this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if y == "world" if y == "world" { println!("world!") } @@ -36,9 +37,21 @@ fn main() { if x == "hello" { print!("Hello "); - } else { //~ERROR this `else { if .. }` - //~| HELP try - //~| SUGGESTION } else if y == "world" + } else { + //~^ ERROR: this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if let Some(42) + if let Some(42) = Some(42) { + println!("world!") + } + } + + if x == "hello" { + print!("Hello "); + } else { + //~^ ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if y == "world" if y == "world" { println!("world") } @@ -47,6 +60,62 @@ fn main() { } } + if x == "hello" { + print!("Hello "); + } else { + //~^ ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if let Some(42) + if let Some(42) = Some(42) { + println!("world") + } + else { + println!("!") + } + } + + if let Some(42) = Some(42) { + print!("Hello "); + } else { + //~^ ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if let Some(42) + if let Some(42) = Some(42) { + println!("world") + } + else { + println!("!") + } + } + + if let Some(42) = Some(42) { + print!("Hello "); + } else { + //~^ ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if x == "hello" + if x == "hello" { + println!("world") + } + else { + println!("!") + } + } + + if let Some(42) = Some(42) { + print!("Hello "); + } else { + //~^ ERROR this `else { if .. }` + //~| HELP try + //~| SUGGESTION } else if let Some(42) + if let Some(42) = Some(42) { + println!("world") + } + else { + println!("!") + } + } + // Works because any if with an else statement cannot be collapsed. if x == "hello" { if y == "world" { diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index f4e74eed4a4..2fd8c766d92 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -8,6 +8,7 @@ #![allow(unused_variables)] #![allow(cyclomatic_complexity)] #![allow(blacklisted_name)] +#![allow(collapsible_if)] fn bar<T>(_: T) {} fn foo() -> bool { unimplemented!() } -- cgit 1.4.1-3-g733a5 From eba449c2c066334c813b1a54c9ec7cc18a4b09c3 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 21 Jun 2016 23:58:13 +0200 Subject: Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 168d7a12065..cfcc2d6bc32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. * New lints: [`wrong_transmute`] * For compatibility, `cargo clippy` does not defines the `clippy` feature introduced in 0.0.76 anymore +* [`collapsible_if`] now considers `if let` ## 0.0.77 — 2016-06-21 * Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)* -- cgit 1.4.1-3-g733a5 From 9e76bcee5dd40ecc012ba3ad2b42fd6bc4f22fa8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 22 Jun 2016 02:17:26 +0200 Subject: Improve `matches` tests --- tests/compile-fail/matches.rs | 72 ++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 650b5917fdc..989106a5a16 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -18,34 +18,38 @@ enum ExprNode { static NODE: ExprNode = ExprNode::Unicorns; +fn dummy() { +} + fn unwrap_addr() -> Option<&'static ExprNode> { - match ExprNode::Butterflies { //~ ERROR you seem to be trying to use match - //~^ HELP try + match ExprNode::Butterflies { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None } ExprNode::ExprAddrOf => Some(&NODE), - _ => { - let x = 5; - None - }, + _ => { let x = 5; None }, } } fn single_match(){ let x = Some(1u8); - match x { //~ ERROR you seem to be trying to use match - //~^ HELP try - Some(y) => { - println!("{:?}", y); - } + match x { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let Some(y) = x { println!("{:?}", y); }; + Some(y) => { println!("{:?}", y); } _ => () - } + }; let z = (1u8,1u8); - match z { //~ ERROR you seem to be trying to use match - //~^ HELP try - (2...3, 7...9) => println!("{:?}", z), + match z { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let (2...3, 7...9) = z { dummy() }; + (2...3, 7...9) => dummy(), _ => {} - } + }; // Not linted (pattern guards used) match x { @@ -64,25 +68,31 @@ fn single_match_know_enum() { let x = Some(1u8); let y : Result<_, i8> = Ok(1i8); - match x { //~ ERROR you seem to be trying to use match - //~^ HELP try - Some(y) => println!("{:?}", y), + match x { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let Some(y) = x { dummy() }; + Some(y) => dummy(), None => () - } + }; - match y { //~ ERROR you seem to be trying to use match - //~^ HELP try - Ok(y) => println!("{:?}", y), + match y { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let Ok(y) = y { dummy() }; + Ok(y) => dummy(), Err(..) => () - } + }; let c = Cow::Borrowed(""); - match c { //~ ERROR you seem to be trying to use match - //~^ HELP try - Cow::Borrowed(..) => println!("42"), + match c { + //~^ ERROR you seem to be trying to use match + //~| HELP try + //~| SUGGESTION if let Cow::Borrowed(..) = c { dummy() }; + Cow::Borrowed(..) => dummy(), Cow::Owned(..) => (), - } + }; let z = Foo::Bar; // no warning @@ -209,19 +219,19 @@ fn overlapping() { match 42 { 0 ... 10 => println!("0 ... 10"), //~ERROR: some ranges overlap - 0 ... 11 => println!("0 ... 10"), + 0 ... 11 => println!("0 ... 10"), //~NOTE overlaps with this _ => (), } match 42 { 0 ... 5 => println!("0 ... 5"), //~ERROR: some ranges overlap 6 ... 7 => println!("6 ... 7"), - FOO ... 11 => println!("0 ... 10"), + FOO ... 11 => println!("0 ... 10"), //~NOTE overlaps with this _ => (), } match 42 { - 2 => println!("2"), + 2 => println!("2"), //~NOTE overlaps with this 0 ... 5 => println!("0 ... 5"), //~ERROR: some ranges overlap _ => (), } -- cgit 1.4.1-3-g733a5 From a12e8394d7ec0677914749de18b56eb2a925bc3d Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Thu, 30 Jun 2016 01:00:25 +0200 Subject: new lint: double_neg --- CHANGELOG.md | 3 ++- README.md | 3 ++- clippy_lints/src/lib.rs | 1 + clippy_lints/src/misc_early.rs | 52 +++++++++++++++++++++++++++++----------- tests/compile-fail/double_neg.rs | 10 ++++++++ 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 tests/compile-fail/double_neg.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index cfcc2d6bc32..fece611c1da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. ## 0.0.78 - TBA -* New lints: [`wrong_transmute`] +* New lints: [`wrong_transmute`, `double_neg`] * For compatibility, `cargo clippy` does not defines the `clippy` feature introduced in 0.0.76 anymore * [`collapsible_if`] now considers `if let` @@ -153,6 +153,7 @@ All notable changes to this project will be documented in this file. [`deprecated_semver`]: https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver [`derive_hash_xor_eq`]: https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq [`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown +[`double_neg`]: https://github.com/Manishearth/rust-clippy/wiki#double_neg [`drop_ref`]: https://github.com/Manishearth/rust-clippy/wiki#drop_ref [`duplicate_underscore_argument`]: https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument [`empty_loop`]: https://github.com/Manishearth/rust-clippy/wiki#empty_loop diff --git a/README.md b/README.md index 2f54835d538..4aa18838718 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 156 lints included in this crate: +There are 157 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -49,6 +49,7 @@ name [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly [doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | checks for the presence of `_`, `::` or camel-case outside ticks in documentation +[double_neg](https://github.com/Manishearth/rust-clippy/wiki#double_neg) | warn | --x is a double negation of x and not a pre-decrement as in C or C++ [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e980f4d081d..040096dcbb4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -369,6 +369,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + misc_early::DOUBLE_NEG, misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index a7ab59497ac..9275af3f12a 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -40,12 +40,25 @@ declare_lint! { "Closures should not be called in the expression they are defined" } +/// **What it does:** This lint detects expressions of the form `--x` +/// +/// **Why is this bad?** It can mislead C/C++ programmers to think `x` was decremented. +/// +/// **Known problems:** None. +/// +/// **Example:** `--x;` +declare_lint! { + pub DOUBLE_NEG, Warn, + "--x is a double negation of x and not a pre-decrement as in C or C++" +} + + #[derive(Copy, Clone)] pub struct MiscEarly; impl LintPass for MiscEarly { fn get_lints(&self) -> LintArray { - lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL) + lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL, DOUBLE_NEG) } } @@ -126,21 +139,32 @@ impl EarlyLintPass for MiscEarly { } fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Call(ref paren, _) = expr.node { - if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { - span_lint_and_then(cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| { - if decl.inputs.is_empty() { - let hint = format!("{}", snippet(cx, block.span, "..")); - db.span_suggestion(expr.span, "Try doing something like: ", hint); - } - }); + match expr.node { + ExprKind::Call(ref paren, _) => { + if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { + span_lint_and_then(cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |db| { + if decl.inputs.is_empty() { + let hint = format!("{}", snippet(cx, block.span, "..")); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + } + }); + } } } + ExprKind::Unary(UnOp::Neg, ref inner) => { + if let ExprKind::Unary(UnOp::Neg, _) = inner.node { + span_lint(cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op"); + } + } + _ => () } } diff --git a/tests/compile-fail/double_neg.rs b/tests/compile-fail/double_neg.rs new file mode 100644 index 00000000000..790ca93728b --- /dev/null +++ b/tests/compile-fail/double_neg.rs @@ -0,0 +1,10 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[deny(double_neg)] +fn main() { + let x = 1; + -x; + -(-x); + --x; //~ERROR: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op +} -- cgit 1.4.1-3-g733a5 From b73180231a9001459f34deba1763cea1dc300c3c Mon Sep 17 00:00:00 2001 From: Andre Bogus <bogusandre@gmail.com> Date: Thu, 30 Jun 2016 06:33:21 +0200 Subject: fixed doc nit --- README.md | 2 +- clippy_lints/src/misc_early.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4aa18838718..2ae53db2d05 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ name [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver [derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly [doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | checks for the presence of `_`, `::` or camel-case outside ticks in documentation -[double_neg](https://github.com/Manishearth/rust-clippy/wiki#double_neg) | warn | --x is a double negation of x and not a pre-decrement as in C or C++ +[double_neg](https://github.com/Manishearth/rust-clippy/wiki#double_neg) | warn | `--x` is a double negation of `x` and not a pre-decrement as in C or C++ [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | call to `std::mem::drop` with a reference instead of an owned value, which will not call the `Drop::drop` method on the underlying value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore [empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 9275af3f12a..e382b7dc5f6 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -49,7 +49,7 @@ declare_lint! { /// **Example:** `--x;` declare_lint! { pub DOUBLE_NEG, Warn, - "--x is a double negation of x and not a pre-decrement as in C or C++" + "`--x` is a double negation of `x` and not a pre-decrement as in C or C++" } -- cgit 1.4.1-3-g733a5 From 580ae5a879073d535c60857b1fbc5204ad2c810e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 19:47:51 +0200 Subject: Use `span_suggestion` in `FLOAT_CMP` --- clippy_lints/src/misc.rs | 21 +++++++++++--------- tests/compile-fail/float_cmp.rs | 44 +++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 49532576469..e57cd50899e 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -164,15 +164,18 @@ impl LateLintPass for FloatCmp { return; } } - span_lint(cx, - FLOAT_CMP, - expr.span, - &format!("{}-comparison of f32 or f64 detected. Consider changing this to `({} - {}).abs() < \ - epsilon` for some suitable value of epsilon. \ - std::f32::EPSILON and std::f64::EPSILON are available.", - op.as_str(), - snippet(cx, left.span, ".."), - snippet(cx, right.span, ".."))); + span_lint_and_then(cx, + FLOAT_CMP, + expr.span, + "strict comparison of f32 or f64", + |db| { + db.span_suggestion(expr.span, + "consider comparing them within some error", + format!("({} - {}).abs() < error", + snippet(cx, left.span, ".."), + snippet(cx, right.span, ".."))); + db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); + }); } } } diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 9f611dd3fd9..cf8cefb3af3 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -40,23 +40,47 @@ fn main() { ZERO == 0.0; //no error, comparison with zero is ok ZERO + ZERO != 1.0; //no error, comparison with zero is ok - ONE == 1f32; //~ERROR ==-comparison of f32 or f64 - ONE == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64 - - ONE + ONE == (ZERO + ONE + ONE); //~ERROR ==-comparison of f32 or f64 - - ONE != 2.0; //~ERROR !=-comparison of f32 or f64 + ONE == 1f32; + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (ONE - 1f32).abs() < error + ONE == (1.0 + 0.0); + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (ONE - (1.0 + 0.0)).abs() < error + + ONE + ONE == (ZERO + ONE + ONE); + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (ONE + ONE - (ZERO + ONE + ONE)).abs() < error + + ONE != 2.0; + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (ONE - 2.0).abs() < error ONE != 0.0; // no error, comparison with zero is ok - twice(ONE) != ONE; //~ERROR !=-comparison of f32 or f64 - ONE as f64 != 2.0; //~ERROR !=-comparison of f32 or f64 + twice(ONE) != ONE; + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (twice(ONE) - ONE).abs() < error + ONE as f64 != 2.0; + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (ONE as f64 - 2.0).abs() < error ONE as f64 != 0.0; // no error, comparison with zero is ok let x : f64 = 1.0; - x == 1.0; //~ERROR ==-comparison of f32 or f64 + x == 1.0; + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (x - 1.0).abs() < error x != 0f64; // no error, comparison with zero is ok - twice(x) != twice(ONE as f64); //~ERROR !=-comparison of f32 or f64 + twice(x) != twice(ONE as f64); + //~^ ERROR strict comparison of f32 or f64 + //~| HELP within some error + //~| SUGGESTION (twice(x) - twice(ONE as f64)).abs() < error x < 0.0; // no errors, lower or greater comparisons need no fuzzyness -- cgit 1.4.1-3-g733a5 From 9811dea2377cfe835dc22f8c129bf83a75669319 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 21:23:21 +0200 Subject: Add a module to pretty-print suggestions --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/utils/higher.rs | 28 +++++ clippy_lints/src/utils/mod.rs | 4 +- clippy_lints/src/utils/sugg.rs | 258 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/utils/higher.rs create mode 100644 clippy_lints/src/utils/sugg.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e980f4d081d..b22531576aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -3,6 +3,7 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(custom_attribute)] +#![feature(dotdot_in_tuple_patterns)] #![feature(iter_arith)] #![feature(question_mark)] #![feature(rustc_private)] diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs new file mode 100644 index 00000000000..5df91ee9ab4 --- /dev/null +++ b/clippy_lints/src/utils/higher.rs @@ -0,0 +1,28 @@ +//! This module contains functions for retrieve the original AST from lowered `hir`. + +use rustc::hir; +use syntax::ast; + +/// Convert a hir binary operator to the corresponding `ast` type. +pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { + match op { + hir::BiEq => ast::BinOpKind::Eq, + hir::BiGe => ast::BinOpKind::Ge, + hir::BiGt => ast::BinOpKind::Gt, + hir::BiLe => ast::BinOpKind::Le, + hir::BiLt => ast::BinOpKind::Lt, + hir::BiNe => ast::BinOpKind::Ne, + hir::BiOr => ast::BinOpKind::Or, + hir::BiAdd => ast::BinOpKind::Add, + hir::BiAnd => ast::BinOpKind::And, + hir::BiBitAnd => ast::BinOpKind::BitAnd, + hir::BiBitOr => ast::BinOpKind::BitOr, + hir::BiBitXor => ast::BinOpKind::BitXor, + hir::BiDiv => ast::BinOpKind::Div, + hir::BiMul => ast::BinOpKind::Mul, + hir::BiRem => ast::BinOpKind::Rem, + hir::BiShl => ast::BinOpKind::Shl, + hir::BiShr => ast::BinOpKind::Shr, + hir::BiSub => ast::BinOpKind::Sub, + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9eb54c2a013..6d41d5039f7 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -18,12 +18,14 @@ use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +pub mod cargo; pub mod comparisons; pub mod conf; +pub mod higher; mod hir; pub mod paths; +pub mod sugg; pub use self::hir::{SpanlessEq, SpanlessHash}; -pub mod cargo; pub type MethodArgs = HirVec<P<Expr>>; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs new file mode 100644 index 00000000000..6667598b009 --- /dev/null +++ b/clippy_lints/src/utils/sugg.rs @@ -0,0 +1,258 @@ +use rustc::hir; +use rustc::lint::{EarlyContext, LateContext}; +use std::borrow::Cow; +use std; +use syntax::ast; +use syntax::util::parser::AssocOp; +use utils::{higher, snippet}; + +/// A helper type to build suggestion correctly handling parenthesis. +pub enum Sugg<'a> { + /// An expression that never needs parenthesis such as `1337` or `[0; 42]`. + NonParen(Cow<'a, str>), + /// An expression that does not fit in other variants. + MaybeParen(Cow<'a, str>), + /// A binary operator expression, including `as`-casts and explicit type coercion. + BinOp(AssocOp, Cow<'a, str>), +} + +impl<'a> std::fmt::Display for Sugg<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match *self { + Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) | Sugg::BinOp(_, ref s) => { + s.fmt(f) + } + } + } +} + +impl<'a> Sugg<'a> { + pub fn hir(cx: &LateContext, expr: &'a hir::Expr, default: &'a str) -> Sugg<'a> { + let snippet = snippet(cx, expr.span, default); + + match expr.node { + hir::ExprAddrOf(..) | + hir::ExprBox(..) | + hir::ExprClosure(..) | + hir::ExprIf(..) | + hir::ExprUnary(..) | + hir::ExprMatch(..) => Sugg::MaybeParen(snippet), + hir::ExprAgain(..) | + hir::ExprBlock(..) | + hir::ExprBreak(..) | + hir::ExprCall(..) | + hir::ExprField(..) | + hir::ExprIndex(..) | + hir::ExprInlineAsm(..) | + hir::ExprLit(..) | + hir::ExprLoop(..) | + hir::ExprMethodCall(..) | + hir::ExprPath(..) | + hir::ExprRepeat(..) | + hir::ExprRet(..) | + hir::ExprStruct(..) | + hir::ExprTup(..) | + hir::ExprTupField(..) | + hir::ExprVec(..) | + hir::ExprWhile(..) => Sugg::NonParen(snippet), + hir::ExprAssign(..) => Sugg::BinOp(AssocOp::Assign, snippet), + hir::ExprAssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), + hir::ExprBinary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), + hir::ExprCast(..) => Sugg::BinOp(AssocOp::As, snippet), + hir::ExprType(..) => Sugg::BinOp(AssocOp::Colon, snippet), + } + } + + pub fn ast(cx: &EarlyContext, expr: &'a ast::Expr, default: &'a str) -> Sugg<'a> { + use syntax::ast::RangeLimits; + + let snippet = snippet(cx, expr.span, default); + + match expr.node { + ast::ExprKind::AddrOf(..) | + ast::ExprKind::Box(..) | + ast::ExprKind::Closure(..) | + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::InPlace(..) | + ast::ExprKind::Unary(..) | + ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), + ast::ExprKind::Again(..) | + ast::ExprKind::Block(..) | + ast::ExprKind::Break(..) | + ast::ExprKind::Call(..) | + ast::ExprKind::Field(..) | + ast::ExprKind::ForLoop(..) | + ast::ExprKind::Index(..) | + ast::ExprKind::InlineAsm(..) | + ast::ExprKind::Lit(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::Mac(..) | + ast::ExprKind::MethodCall(..) | + ast::ExprKind::Paren(..) | + ast::ExprKind::Path(..) | + ast::ExprKind::Repeat(..) | + ast::ExprKind::Ret(..) | + ast::ExprKind::Struct(..) | + ast::ExprKind::Try(..) | + ast::ExprKind::Tup(..) | + ast::ExprKind::TupField(..) | + ast::ExprKind::Vec(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), + ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet), + ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotDot, snippet), + ast::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), + ast::ExprKind::AssignOp(op, ..) => Sugg::BinOp(astbinop2assignop(op), snippet), + ast::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(op.node), snippet), + ast::ExprKind::Cast(..) => Sugg::BinOp(AssocOp::As, snippet), + ast::ExprKind::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet), + } + } + + /// Convenience method to create the `lhs && rhs` suggestion. + pub fn and(&self, rhs: &Self) -> Sugg<'static> { + make_binop(ast::BinOpKind::And, self, rhs) + } +} + +impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> { + type Output = Sugg<'static>; + fn sub(self, rhs: &'b Sugg<'b>) -> Sugg<'static> { + make_binop(ast::BinOpKind::Sub, self, rhs) + } +} + +struct ParenHelper<T> { + paren: bool, + wrapped: T, +} + +impl<T> ParenHelper<T> { + fn new(paren: bool, wrapped: T) -> Self { + ParenHelper { + paren: paren, + wrapped: wrapped, + } + } +} + +impl<T: std::fmt::Display> std::fmt::Display for ParenHelper<T> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + if self.paren { + write!(f, "({})", self.wrapped) + } else { + self.wrapped.fmt(f) + } + } +} + +/// Build the string for `<lhs> <op> <rhs>` adding parenthesis when necessary. +/// +/// Precedence of shift operator relative to other arithmetic operation is often confusing so +/// parenthesis will always be added for a mix of these. +pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { + fn is_shift(op: &AssocOp) -> bool { + matches!(*op, AssocOp::ShiftLeft | AssocOp::ShiftRight) + } + + fn is_arith(op: &AssocOp) -> bool { + matches!(*op, AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus) + } + + fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool { + other.precedence() < op.precedence() || + (other.precedence() == op.precedence() && + ((op != other && associativity(op) != dir) || + (op == other && associativity(op) != Associativity::Both))) || + is_shift(op) && is_arith(other) || + is_shift(other) && is_arith(op) + } + + let aop = AssocOp::from_ast_binop(op); + + let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs { + needs_paren(&aop, lop, Associativity::Left) + } else { + false + }; + + let rhs_paren = if let Sugg::BinOp(ref rop, _) = *rhs { + needs_paren(&aop, rop, Associativity::Right) + } else { + false + }; + + Sugg::BinOp(aop, + format!("{} {} {}", + ParenHelper::new(lhs_paren, lhs), + op.to_string(), + ParenHelper::new(rhs_paren, rhs)).into()) +} + +#[derive(PartialEq, Eq)] +enum Associativity { + Both, + Left, + None, + Right, +} + +/// Return the associativity/fixity of an operator. The difference with `AssocOp::fixity` is that +/// an operator can be both left and right associative (such as `+`: +/// `a + b + c == (a + b) + c == a + (b + c)`. +/// +/// Chained `as` and explicit `:` type coercion never need inner parenthesis so they are considered +/// associative. +fn associativity(op: &AssocOp) -> Associativity { + use syntax::util::parser::AssocOp::*; + + match *op { + Inplace | Assign | AssignOp(_) => Associativity::Right, + Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | + As | Colon => Associativity::Both, + Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | + ShiftRight | Subtract => Associativity::Left, + DotDot | DotDotDot => Associativity::None + } +} + +/// Convert a `hir::BinOp` to the corresponding assigning binary operator. +fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { + use rustc::hir::BinOp_::*; + use syntax::parse::token::BinOpToken::*; + + AssocOp::AssignOp(match op.node { + BiAdd => Plus, + BiBitAnd => And, + BiBitOr => Or, + BiBitXor => Caret, + BiDiv => Slash, + BiMul => Star, + BiRem => Percent, + BiShl => Shl, + BiShr => Shr, + BiSub => Minus, + BiAnd | BiEq | BiGe | BiGt | BiLe | BiLt | BiNe | BiOr => panic!("This operator does not exist"), + }) +} + +/// Convert an `ast::BinOp` to the corresponding assigning binary operator. +fn astbinop2assignop(op: ast::BinOp) -> AssocOp { + use syntax::ast::BinOpKind::*; + use syntax::parse::token::BinOpToken; + + AssocOp::AssignOp(match op.node { + Add => BinOpToken::Plus, + BitAnd => BinOpToken::And, + BitOr => BinOpToken::Or, + BitXor => BinOpToken::Caret, + Div => BinOpToken::Slash, + Mul => BinOpToken::Star, + Rem => BinOpToken::Percent, + Shl => BinOpToken::Shl, + Shr => BinOpToken::Shr, + Sub => BinOpToken::Minus, + And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"), + }) +} -- cgit 1.4.1-3-g733a5 From 8d58a928e5956c8531fecc04cb92bf7d63979605 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 21:24:20 +0200 Subject: Use `utils::sugg` in `ASSIGN_OPS` --- README.md | 2 +- clippy_lints/src/assign_ops.rs | 43 ++++++++++++++++------------------------ tests/compile-fail/assign_ops.rs | 20 +++++++++++++++++++ 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 2f54835d538..20c6c6a38a8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ name [almost_swapped](https://github.com/Manishearth/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence [approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found; suggests to use the constant [assign_op_pattern](https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern) | warn | assigning the result of an operation on a variable to that same variable -[assign_ops](https://github.com/Manishearth/rust-clippy/wiki#assign_ops) | allow | Any assignment operation +[assign_ops](https://github.com/Manishearth/rust-clippy/wiki#assign_ops) | allow | any assignment operation [bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have) [blacklisted_name](https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name [block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces can be eliminated in conditions that are expressions, e.g `if { true } ...` diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 1a5ca16b9c5..6ae76f9c3ef 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,13 +1,14 @@ use rustc::hir; use rustc::lint::*; use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; +use utils::{higher, sugg}; -/// **What it does:** This lint checks for `+=` operations and similar +/// **What it does:** This lint checks for `+=` operations and similar. /// -/// **Why is this bad?** Projects with many developers from languages without those operations -/// may find them unreadable and not worth their weight +/// **Why is this bad?** Projects with many developers from languages without those operations may +/// find them unreadable and not worth their weight. /// -/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op` +/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`. /// /// **Example:** /// ``` @@ -15,14 +16,14 @@ use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_de /// ``` declare_restriction_lint! { pub ASSIGN_OPS, - "Any assignment operation" + "any assignment operation" } -/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns +/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns. /// -/// **Why is this bad?** These can be written as the shorter `a op= b` +/// **Why is this bad?** These can be written as the shorter `a op= b`. /// -/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl +/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl. /// /// **Example:** /// @@ -50,24 +51,14 @@ impl LateLintPass for AssignOps { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { match expr.node { hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) { - span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| { - match rhs.node { - hir::ExprBinary(op2, _, _) if op2 != op => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} ({})", l, l, op.node.as_str(), r)); - } - _ => { - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {} {} {}", l, l, op.node.as_str(), r)); - } - } - }); - } else { - span_lint(cx, ASSIGN_OPS, expr.span, "assign operation detected"); - } + span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| { + let lhs = &sugg::Sugg::hir(cx, lhs, ".."); + let rhs = &sugg::Sugg::hir(cx, rhs, ".."); + + db.span_suggestion(expr.span, + "replace it with", + format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs))); + }); } hir::ExprAssign(ref assignee, ref e) => { if let hir::ExprBinary(op, ref l, ref r) = e.node { diff --git a/tests/compile-fail/assign_ops.rs b/tests/compile-fail/assign_ops.rs index 84d868ecfcc..2b69e110f43 100644 --- a/tests/compile-fail/assign_ops.rs +++ b/tests/compile-fail/assign_ops.rs @@ -8,15 +8,31 @@ fn main() { i += 2; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i + 2 + i += 2 + 17; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i + 2 + 17 i -= 6; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i - 6 + i -= 2 - 1; + //~^ ERROR assign operation detected + //~| HELP replace it with + //~| SUGGESTION i = i - (2 - 1) i *= 5; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i * 5 + i *= 1+5; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i * (1+5) i /= 32; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i / 32 + i /= 32 | 5; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i / (32 | 5) + i /= 32 / 5; //~ ERROR assign operation detected + //~^ HELP replace it with + //~| SUGGESTION i = i / (32 / 5) i %= 42; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i % 42 @@ -26,6 +42,10 @@ fn main() { i <<= 9 + 6 - 7; //~ ERROR assign operation detected //~^ HELP replace it with //~| SUGGESTION i = i << (9 + 6 - 7) + i += 1 << 5; + //~^ ERROR assign operation detected + //~| HELP replace it with + //~| SUGGESTION i = i + (1 << 5) } #[allow(dead_code, unused_assignments)] -- cgit 1.4.1-3-g733a5 From 2e8edde6e9b42b3a8c7e8aefb2ad6c86be404915 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 21:25:23 +0200 Subject: Use `utils::sugg` in `FLOAT_CMP` --- clippy_lints/src/misc.rs | 8 +++++--- tests/compile-fail/float_cmp.rs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e57cd50899e..9c04ad6f3e4 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -13,6 +13,7 @@ use utils::{ get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path, snippet, span_lint, span_lint_and_then, walk_ptrs_ty }; +use utils::sugg::Sugg; /// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. /// @@ -169,11 +170,12 @@ impl LateLintPass for FloatCmp { expr.span, "strict comparison of f32 or f64", |db| { + let lhs = &Sugg::hir(cx, left, ".."); + let rhs = &Sugg::hir(cx, right, ".."); + db.span_suggestion(expr.span, "consider comparing them within some error", - format!("({} - {}).abs() < error", - snippet(cx, left.span, ".."), - snippet(cx, right.span, ".."))); + format!("({}).abs() < error", lhs - rhs)); db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); }); } diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index cf8cefb3af3..314cc721425 100644 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -44,12 +44,12 @@ fn main() { //~^ ERROR strict comparison of f32 or f64 //~| HELP within some error //~| SUGGESTION (ONE - 1f32).abs() < error - ONE == (1.0 + 0.0); + ONE == 1.0 + 0.0; //~^ ERROR strict comparison of f32 or f64 //~| HELP within some error //~| SUGGESTION (ONE - (1.0 + 0.0)).abs() < error - ONE + ONE == (ZERO + ONE + ONE); + ONE + ONE == ZERO + ONE + ONE; //~^ ERROR strict comparison of f32 or f64 //~| HELP within some error //~| SUGGESTION (ONE + ONE - (ZERO + ONE + ONE)).abs() < error -- cgit 1.4.1-3-g733a5 From 66808c1e776ca9303cc04abce4b3b95ee5b669fc Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 21:26:26 +0200 Subject: Use `utils::sugg` in `COLLAPSIBLE_IF` --- clippy_lints/src/collapsible_if.rs | 27 ++++++--------------------- tests/compile-fail/collapsible_if.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 2921bc2769c..350a3cc3ef2 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -13,11 +13,10 @@ //! This lint is **warn** by default use rustc::lint::*; -use std::borrow::Cow; -use syntax::codemap::Spanned; use syntax::ast; -use utils::{in_macro, snippet, snippet_block, span_lint_and_then}; +use utils::{in_macro, snippet_block, span_lint_and_then}; +use utils::sugg::Sugg; /// **What it does:** This lint checks for nested `if`-statements which can be collapsed by /// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to @@ -103,31 +102,17 @@ fn check_collapsible_no_if_let( return; } span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { + let lhs = Sugg::ast(cx, check, ".."); + let rhs = Sugg::ast(cx, check_inner, ".."); db.span_suggestion(expr.span, "try", - format!("if {} && {} {}", - check_to_string(cx, check), - check_to_string(cx, check_inner), + format!("if {} {}", + lhs.and(&rhs), snippet_block(cx, content.span, ".."))); }); }} } -fn requires_brackets(e: &ast::Expr) -> bool { - match e.node { - ast::ExprKind::Binary(Spanned { node: n, .. }, _, _) if n == ast::BinOpKind::Eq => false, - _ => true, - } -} - -fn check_to_string(cx: &EarlyContext, e: &ast::Expr) -> Cow<'static, str> { - if requires_brackets(e) { - format!("({})", snippet(cx, e.span, "..")).into() - } else { - snippet(cx, e.span, "..") - } -} - fn single_stmt_of_block(block: &ast::Block) -> Option<&ast::Expr> { if block.stmts.len() == 1 && block.expr.is_none() { if let ast::StmtKind::Expr(ref expr, _) = block.stmts[0].node { diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index ea2ef284f38..f7e6f15b121 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -23,6 +23,42 @@ fn main() { } } + if x == "hello" && x == "world" { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if x == "hello" && x == "world" && (y == "world" || y == "hello") { + if y == "world" || y == "hello" { + println!("Hello world!"); + } + } + + if x == "hello" || x == "world" { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if (x == "hello" || x == "world") && y == "world" && y == "hello" { + if y == "world" && y == "hello" { + println!("Hello world!"); + } + } + + if x == "hello" && x == "world" { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if x == "hello" && x == "world" && y == "world" && y == "hello" { + if y == "world" && y == "hello" { + println!("Hello world!"); + } + } + + if 42 == 1337 { + //~^ ERROR this if statement can be collapsed + //~| HELP try + //~| SUGGESTION if 42 == 1337 && 'a' != 'A' { + if 'a' != 'A' { + println!("world!") + } + } + // Collaspe `else { if .. }` to `else if ..` if x == "hello" { print!("Hello "); -- cgit 1.4.1-3-g733a5 From 7a1fc9fce5e9d05864567fd3c36502198588a623 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 21:50:21 +0200 Subject: Use `utils::sugg` in `MATCH_BOOL` --- clippy_lints/src/matches.rs | 6 ++++-- clippy_lints/src/utils/sugg.rs | 16 ++++++++++++++++ tests/compile-fail/matches.rs | 13 +++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index e578fbf6d68..8fddcb84922 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -10,6 +10,7 @@ use syntax::ast::LitKind; use syntax::codemap::Span; use utils::paths; use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; +use utils::sugg::Sugg; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. /// @@ -262,8 +263,9 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) } (true, false) => { - Some(format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), + let test = &Sugg::hir(cx, ex, ".."); + Some(format!("if {} {}", + !test, expr_block(cx, false_expr, None, ".."))) } (true, true) => None, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 6667598b009..f4b359b35de 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -123,6 +123,13 @@ impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> { } } +impl<'a> std::ops::Not for &'a Sugg<'a> { + type Output = Sugg<'static>; + fn not(self) -> Sugg<'static> { + make_unop("!", self) + } +} + struct ParenHelper<T> { paren: bool, wrapped: T, @@ -147,6 +154,15 @@ impl<T: std::fmt::Display> std::fmt::Display for ParenHelper<T> { } } +/// Build the string for `<op> <expr>` adding parenthesis when necessary. +/// +/// For convenience, the operator is taken as a string because all unary operators have the same +/// precedence. +pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> { + let needs_paren = !matches!(*expr, Sugg::NonParen(..)); + Sugg::MaybeParen(format!("{}{}", op, ParenHelper::new(needs_paren, expr)).into()) +} + /// Build the string for `<lhs> <op> <rhs>` adding parenthesis when necessary. /// /// Precedence of shift operator relative to other arithmetic operation is often confusing so diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 989106a5a16..e49aeaa6ec8 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -130,7 +130,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression //~| HELP try - //~^^ SUGGESTION if !test { println!("Noooo!"); }; + //~| SUGGESTION if !test { println!("Noooo!"); }; true => (), false => { println!("Noooo!"); } }; @@ -138,7 +138,16 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression //~| HELP try - //~^^ SUGGESTION if !test { println!("Noooo!"); }; + //~| SUGGESTION if !test { println!("Noooo!"); }; + false => { println!("Noooo!"); } + _ => (), + }; + + match test && test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~| SUGGESTION if !(test && test) { println!("Noooo!"); }; + //~| ERROR equal expressions as operands false => { println!("Noooo!"); } _ => (), }; -- cgit 1.4.1-3-g733a5 From a3c505551fc1d5ed4270357e6a616b01b45e9a7d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 22:35:58 +0200 Subject: Cleanup --- clippy_lints/src/methods.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a959dbe1d6a..8a1ebd162af 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -672,20 +672,20 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr #[allow(ptr_arg)] // Type of MethodArgs is potentially a Vec fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){ - let caller_type; let mut_str = if is_mut { "_mut" } else {""}; - if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { - caller_type = "slice"; + let caller_type = if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { + "slice" } else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) { - caller_type = "Vec"; + "Vec" } else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { - caller_type = "VecDeque"; + "VecDeque" } else { return; // caller is not a type that we want to lint - } + }; + span_lint( cx, ITER_NTH, -- cgit 1.4.1-3-g733a5 From 702398802097e5081b15b1a1250e88f6510c3eef Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 22:37:10 +0200 Subject: Use `utils::sugg` in `TOPLEVEL_REF_ARG` --- clippy_lints/src/misc.rs | 5 +++-- clippy_lints/src/utils/sugg.rs | 5 +++++ tests/compile-fail/toplevel_ref_arg.rs | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 9c04ad6f3e4..e5bfc3c34b1 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -72,12 +72,13 @@ impl LateLintPass for TopLevelRefPass { l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", |db| { + let init = &Sugg::hir(cx, init, ".."); db.span_suggestion(s.span, "try", - format!("let {}{} = &{};", + format!("let {}{} = {};", snippet(cx, i.span, "_"), tyopt, - snippet(cx, init.span, "_"))); + init.addr())); } ); }} diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index f4b359b35de..a28c00efcae 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -114,6 +114,11 @@ impl<'a> Sugg<'a> { pub fn and(&self, rhs: &Self) -> Sugg<'static> { make_binop(ast::BinOpKind::And, self, rhs) } + + /// Convenience method to create the `&<expr>` suggestion. + pub fn addr(&self) -> Sugg<'static> { + make_unop("&", self) + } } impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> { diff --git a/tests/compile-fail/toplevel_ref_arg.rs b/tests/compile-fail/toplevel_ref_arg.rs index de1556ed0e3..b2240cffb1a 100644 --- a/tests/compile-fail/toplevel_ref_arg.rs +++ b/tests/compile-fail/toplevel_ref_arg.rs @@ -20,11 +20,16 @@ fn main() { //~| HELP try //~| SUGGESTION let x = &1; - let ref y : (&_, u8) = (&1, 2); + let ref y: (&_, u8) = (&1, 2); //~^ ERROR `ref` on an entire `let` pattern is discouraged //~| HELP try //~| SUGGESTION let y: (&_, u8) = &(&1, 2); + let ref z = 1 + 2; + //~^ ERROR `ref` on an entire `let` pattern is discouraged + //~| HELP try + //~| SUGGESTION let z = &(1 + 2); + let (ref x, _) = (1,2); // okay, not top level println!("The answer is {}.", x); } -- cgit 1.4.1-3-g733a5 From 169b63a84abf1598a83038fcdedceba40255288a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 22:45:58 +0200 Subject: Improve `TOPLEVEL_REF_ARG` message --- clippy_lints/src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e5bfc3c34b1..0931d5aca6b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -70,7 +70,7 @@ impl LateLintPass for TopLevelRefPass { span_lint_and_then(cx, TOPLEVEL_REF_ARG, l.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with & instead", + "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { let init = &Sugg::hir(cx, init, ".."); db.span_suggestion(s.span, -- cgit 1.4.1-3-g733a5 From ebf72cb67f3dcdd05ce812b020346dc318624b8a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 23:02:15 +0200 Subject: Use `util::sugg` in `TRANSMUTE_PTR_TO_REF` --- clippy_lints/src/transmute.rs | 32 +++++++++++++------------------- tests/compile-fail/transmute.rs | 1 + 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index bf6af4411b8..12d2184693a 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -3,6 +3,7 @@ use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; use rustc::ty; use rustc::hir::*; use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; +use utils::sugg; /// **What it does:** This lint checks for transmutes that can't ever be correct on any architecture /// @@ -148,28 +149,21 @@ impl LateLintPass for Transmute { from_ty, to_ty), |db| { - if let Some(arg) = snippet_opt(cx, args[0].span) { - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + let arg = &sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - let sugg = if from_pty.ty == to_rty.ty { - // Put things in parentheses if they are more complex - match args[0].node { - ExprPath(..) | ExprCall(..) | ExprMethodCall(..) | ExprBlock(..) => { - format!("{}{}", deref, arg) - } - _ => format!("{}({})", deref, arg) - } - } else { - format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) - }; + let sugg = if from_pty.ty == to_rty.ty { + sugg::make_unop(deref, arg).to_string() + } else { + format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + }; - db.span_suggestion(e.span, "try", sugg); - } + db.span_suggestion(e.span, "try", sugg); }, ), _ => return, diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 4a120a6eedd..0dbd58b1308 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -62,6 +62,7 @@ unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { //~^ ERROR transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) //~| HELP try //~| SUGGESTION = &mut *(p as *mut T); + let _ = &mut *(p as *mut T); let _: &T = std::mem::transmute(o); //~^ ERROR transmute from a pointer type (`*const U`) to a reference type (`&T`) -- cgit 1.4.1-3-g733a5 From 92b04129fe6b1931f14199b01a5bfc78edb66a72 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 29 Jun 2016 23:16:44 +0200 Subject: Move `unsugar_range` to `utils::higher` --- clippy_lints/src/array_indexing.rs | 6 +-- clippy_lints/src/loops.rs | 7 ++- clippy_lints/src/ranges.rs | 5 ++- clippy_lints/src/utils/higher.rs | 89 ++++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 89 +------------------------------------- 5 files changed, 99 insertions(+), 97 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index f3b7297b296..2c84c7cc132 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -6,7 +6,7 @@ use rustc_const_eval::eval_const_expr_partial; use rustc_const_math::ConstInt; use rustc::hir::*; use syntax::ast::RangeLimits; -use utils; +use utils::{self, higher}; /// **What it does:** Check for out of bounds array indexing with a constant index. /// @@ -77,7 +77,7 @@ impl LateLintPass for ArrayIndexing { } // Index is a constant range - if let Some(range) = utils::unsugar_range(index) { + if let Some(range) = higher::range(index) { let start = range.start .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)) .map(|v| v.ok()); @@ -94,7 +94,7 @@ impl LateLintPass for ArrayIndexing { } } - if let Some(range) = utils::unsugar_range(index) { + if let Some(range) = higher::range(index) { // Full ranges are always valid if range.start.is_none() && range.end.is_none() { return; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 1816d88bddb..e945afbf659 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -14,10 +14,9 @@ use std::collections::HashMap; use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, - span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range, + span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty, recover_for_loop}; use utils::paths; -use utils::UnsugaredRange; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. /// @@ -333,7 +332,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E /// Check for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let Some(UnsugaredRange { start: Some(ref start), ref end, .. }) = unsugar_range(arg) { + if let Some(higher::Range { start: Some(ref start), ref end, .. }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { @@ -427,7 +426,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... - if let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), limits }) = unsugar_range(arg) { + if let Some(higher::Range { start: Some(ref start), end: Some(ref end), limits }) = higher::range(arg) { // ...and both sides are compile-time constant integers... if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) { if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 8eacbadf8df..a042c966d94 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Spanned; -use utils::{is_integer_literal, match_type, paths, snippet, span_lint, unsugar_range, UnsugaredRange}; +use utils::{is_integer_literal, match_type, paths, snippet, span_lint}; +use utils::higher; /// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. /// @@ -54,7 +55,7 @@ impl LateLintPass for StepByZero { let ExprMethodCall( Spanned { node: ref iter_name, .. }, _, ref iter_args ) = *iter, iter_name.as_str() == "iter", // range expression in .zip() call: 0..x.len() - let Some(UnsugaredRange { start: Some(ref start), end: Some(ref end), .. }) = unsugar_range(zip_arg), + let Some(higher::Range { start: Some(ref start), end: Some(ref end), .. }) = higher::range(zip_arg), is_integer_literal(start, 0), // .len() call let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 5df91ee9ab4..979c044cdbf 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -2,6 +2,7 @@ use rustc::hir; use syntax::ast; +use utils::{match_path, paths}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -26,3 +27,91 @@ pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { hir::BiSub => ast::BinOpKind::Sub, } } + +/// Represent a range akin to `ast::ExprKind::Range`. +#[derive(Debug, Copy, Clone)] +pub struct Range<'a> { + pub start: Option<&'a hir::Expr>, + pub end: Option<&'a hir::Expr>, + pub limits: ast::RangeLimits, +} + +/// Higher a `hir` range to something similar to `ast::ExprKind::Range`. +pub fn range(expr: &hir::Expr) -> Option<Range> { + // To be removed when ranges get stable. + fn unwrap_unstable(expr: &hir::Expr) -> &hir::Expr { + if let hir::ExprBlock(ref block) = expr.node { + if block.rules == hir::BlockCheckMode::PushUnstableBlock || block.rules == hir::BlockCheckMode::PopUnstableBlock { + if let Some(ref expr) = block.expr { + return expr; + } + } + } + + expr + } + + fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { + let expr = &fields.iter() + .find(|field| field.name.node.as_str() == name) + .unwrap_or_else(|| panic!("missing {} field for range", name)) + .expr; + + Some(unwrap_unstable(expr)) + } + + // The range syntax is expanded to literal paths starting with `core` or `std` depending on + // `#[no_std]`. Testing both instead of resolving the paths. + + match unwrap_unstable(expr).node { + hir::ExprPath(None, ref path) => { + if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { + Some(Range { + start: None, + end: None, + limits: ast::RangeLimits::HalfOpen, + }) + } else { + None + } + } + hir::ExprStruct(ref path, ref fields, None) => { + if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { + Some(Range { + start: get_field("start", fields), + end: None, + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || + match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else { + None + } + } + _ => None, + } +} + diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6d41d5039f7..3ceae788a4d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; use std::env; use std::mem; use std::str::FromStr; -use syntax::ast::{self, LitKind, RangeLimits}; +use syntax::ast::{self, LitKind}; use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; @@ -683,93 +683,6 @@ pub fn camel_case_from(s: &str) -> usize { last_i } -/// Represent a range akin to `ast::ExprKind::Range`. -#[derive(Debug, Copy, Clone)] -pub struct UnsugaredRange<'a> { - pub start: Option<&'a Expr>, - pub end: Option<&'a Expr>, - pub limits: RangeLimits, -} - -/// Unsugar a `hir` range. -pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> { - // To be removed when ranges get stable. - fn unwrap_unstable(expr: &Expr) -> &Expr { - if let ExprBlock(ref block) = expr.node { - if block.rules == BlockCheckMode::PushUnstableBlock || block.rules == BlockCheckMode::PopUnstableBlock { - if let Some(ref expr) = block.expr { - return expr; - } - } - } - - expr - } - - fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> { - let expr = &fields.iter() - .find(|field| field.name.node.as_str() == name) - .unwrap_or_else(|| panic!("missing {} field for range", name)) - .expr; - - Some(unwrap_unstable(expr)) - } - - // The range syntax is expanded to literal paths starting with `core` or `std` depending on - // `#[no_std]`. Testing both instead of resolving the paths. - - match unwrap_unstable(expr).node { - ExprPath(None, ref path) => { - if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { - Some(UnsugaredRange { - start: None, - end: None, - limits: RangeLimits::HalfOpen, - }) - } else { - None - } - } - ExprStruct(ref path, ref fields, None) => { - if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: None, - limits: RangeLimits::HalfOpen, - }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || - match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: get_field("end", fields), - limits: RangeLimits::Closed, - }) - } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { - Some(UnsugaredRange { - start: get_field("start", fields), - end: get_field("end", fields), - limits: RangeLimits::HalfOpen, - }) - } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { - Some(UnsugaredRange { - start: None, - end: get_field("end", fields), - limits: RangeLimits::Closed, - }) - } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { - Some(UnsugaredRange { - start: None, - end: get_field("end", fields), - limits: RangeLimits::HalfOpen, - }) - } else { - None - } - } - _ => None, - } -} - /// Convenience function to get the return type of a function or `None` if the function diverges. pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> { let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); -- cgit 1.4.1-3-g733a5 From 4dff4df57711b1da61dcbc361b02c6becdefe035 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 30 Jun 2016 00:08:43 +0200 Subject: Move more functions to `utils::higher` --- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/mut_mut.rs | 4 ++-- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/higher.rs | 33 +++++++++++++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 38 ++------------------------------------ clippy_lints/src/vec.rs | 4 ++-- 8 files changed, 46 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index aa6dd46cf0b..cee18337ba1 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -156,7 +156,7 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp } } -/// Match `if` or `else if` expressions and return the `then` and `else` block. +/// Match `if` or `if let` expressions and return the `then` and `else` block. fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> { match expr.node { ast::ExprKind::If(_, ref then, ref else_) | diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e945afbf659..1a6ac75eb37 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -15,7 +15,7 @@ use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, - walk_ptrs_ty, recover_for_loop}; + walk_ptrs_ty}; use utils::paths; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. @@ -223,7 +223,7 @@ impl LintPass for Pass { impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some((pat, arg, body)) = recover_for_loop(expr) { + if let Some((pat, arg, body)) = higher::for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); } // check for `loop { if let {} else break }` that could be `while let` diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 8a5439fb11e..d5d9fe1a0bc 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -2,7 +2,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::*; use rustc::ty::{TypeAndMut, TyRef}; -use utils::{in_external_macro, recover_for_loop, span_lint}; +use utils::{higher, in_external_macro, span_lint}; /// **What it does:** This lint checks for instances of `mut mut` references. /// @@ -49,7 +49,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> { return; } - if let Some((_, arg, body)) = recover_for_loop(expr) { + if let Some((_, arg, body)) = higher::for_loop(expr) { // A `for` loop lowers to: // ```rust // match ::std::iter::Iterator::next(&mut iter) { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index b12e68185c2..7bda94ed639 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{Visitor, FnKind}; use std::ops::Deref; use syntax::codemap::Span; -use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint_and_then}; +use utils::{higher, in_external_macro, snippet, span_lint_and_then}; /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. /// @@ -91,7 +91,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } - if is_from_for_desugar(decl) { + if higher::is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 83e2c1b549c..629834a3c0f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -6,7 +6,7 @@ use rustc::ty; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; -use utils::{comparisons, in_external_macro, in_macro, is_from_for_desugar, match_def_path, snippet, +use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint}; use utils::paths; @@ -106,7 +106,7 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) { if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { return; } - if is_from_for_desugar(decl) { + if higher::is_from_for_desugar(decl) { return; } span_lint(cx, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 979c044cdbf..16ab44881a5 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -115,3 +115,36 @@ pub fn range(expr: &hir::Expr) -> Option<Range> { } } +/// Checks if a `let` decl is from a `for` loop desugaring. +pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { + if_let_chain! {[ + let hir::DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node, + ], { + return true; + }} + false +} + +/// Recover the essential nodes of a desugared for loop: +/// `for pat in arg { body }` becomes `(pat, arg, body)`. +pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { + if_let_chain! {[ + let hir::ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let hir::ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), + let hir::ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let hir::ExprMatch(_, ref innerarms, hir::MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let hir::PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); + }} + None +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3ceae788a4d..df9d09ed010 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -21,7 +21,6 @@ use syntax::ptr::P; pub mod cargo; pub mod comparisons; pub mod conf; -pub mod higher; mod hir; pub mod paths; pub mod sugg; @@ -82,6 +81,8 @@ macro_rules! if_let_chain { }; } +pub mod higher; + /// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one /// isn't). pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { @@ -319,19 +320,6 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { } } -/// Checks if a `let` decl is from a `for` loop desugaring. -pub fn is_from_for_desugar(decl: &Decl) -> bool { - if_let_chain! {[ - let DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node - ], { - return true; - }} - false -} - - /// Convert a span to a code snippet if available, otherwise use default. /// /// # Example @@ -706,25 +694,3 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty infcx.can_equate(&new_a, &new_b).is_ok() }) } - -/// Recover the essential nodes of a desugared for loop: -/// `for pat in arg { body }` becomes `(pat, arg, body)`. -pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { - if_let_chain! {[ - let ExprMatch(ref iterexpr, ref arms, _) = expr.node, - let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let ExprLoop(ref block, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, - somepats.len() == 1 - ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); - }} - None -} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 73f2fb7caa8..97a45da4536 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -3,7 +3,7 @@ use rustc::ty::TypeVariants; use rustc::hir::*; use syntax::codemap::Span; use syntax::ptr::P; -use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; +use utils::{higher, is_expn_of, match_path, paths, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -42,7 +42,7 @@ impl LateLintPass for Pass { }} // search for `for _ in vec![…]` - if let Some((_, arg, _)) = recover_for_loop(expr) { + if let Some((_, arg, _)) = higher::for_loop(expr) { // report the error around the `vec!` not inside `<std macros>:` let span = cx.sess().codemap().source_callsite(arg.span); check_vec_macro(cx, arg, span); -- cgit 1.4.1-3-g733a5 From 98f18f047482c08f173e757c0521820ba2deea58 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 30 Jun 2016 19:49:34 +0200 Subject: Move `vec!` unexpanding function to `utils::higher` --- clippy_lints/src/utils/higher.rs | 42 +++++++++++++++++++++++++++++++++++- clippy_lints/src/vec.rs | 46 ++++------------------------------------ 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 16ab44881a5..ab8b7d8b2b8 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -1,8 +1,10 @@ //! This module contains functions for retrieve the original AST from lowered `hir`. use rustc::hir; +use rustc::lint::LateContext; use syntax::ast; -use utils::{match_path, paths}; +use syntax::ptr::P; +use utils::{is_expn_of, match_path, paths}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -148,3 +150,41 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> }} None } + +/// Represent the pre-expansion arguments of a `vec!` invocation. +pub enum VecArgs<'a> { + /// `vec![elem; len]` + Repeat(&'a P<hir::Expr>, &'a P<hir::Expr>), + /// `vec![a, b, c]` + Vec(&'a [P<hir::Expr>]), +} + +/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. +pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> { + if_let_chain!{[ + let hir::ExprCall(ref fun, ref args) = expr.node, + let hir::ExprPath(_, ref path) = fun.node, + is_expn_of(cx, fun.span, "vec").is_some() + ], { + return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { + // `vec![elem; size]` case + Some(VecArgs::Repeat(&args[0], &args[1])) + } + else if match_path(path, &["into_vec"]) && args.len() == 1 { + // `vec![a, b, c]` case + if_let_chain!{[ + let hir::ExprBox(ref boxed) = args[0].node, + let hir::ExprVec(ref args) = boxed.node + ], { + return Some(VecArgs::Vec(&*args)); + }} + + None + } + else { + None + }; + }} + + None +} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 97a45da4536..8e09f9341c2 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -2,8 +2,7 @@ use rustc::lint::*; use rustc::ty::TypeVariants; use rustc::hir::*; use syntax::codemap::Span; -use syntax::ptr::P; -use utils::{higher, is_expn_of, match_path, paths, snippet, span_lint_and_then}; +use utils::{higher, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -51,12 +50,12 @@ impl LateLintPass for Pass { } fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { - if let Some(vec_args) = unexpand(cx, vec) { + if let Some(vec_args) = higher::vec_macro(cx, vec) { let snippet = match vec_args { - Args::Repeat(elem, len) => { + higher::VecArgs::Repeat(elem, len) => { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() } - Args::Vec(args) => { + higher::VecArgs::Vec(args) => { if let Some(last) = args.iter().last() { let span = Span { lo: args[0].span.lo, @@ -77,40 +76,3 @@ fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { } } -/// Represent the pre-expansion arguments of a `vec!` invocation. -pub enum Args<'a> { - /// `vec![elem; len]` - Repeat(&'a P<Expr>, &'a P<Expr>), - /// `vec![a, b, c]` - Vec(&'a [P<Expr>]), -} - -/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. -pub fn unexpand<'e>(cx: &LateContext, expr: &'e Expr) -> Option<Args<'e>> { - if_let_chain!{[ - let ExprCall(ref fun, ref args) = expr.node, - let ExprPath(_, ref path) = fun.node, - is_expn_of(cx, fun.span, "vec").is_some() - ], { - return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { - // `vec![elem; size]` case - Some(Args::Repeat(&args[0], &args[1])) - } - else if match_path(path, &["into_vec"]) && args.len() == 1 { - // `vec![a, b, c]` case - if_let_chain!{[ - let ExprBox(ref boxed) = args[0].node, - let ExprVec(ref args) = boxed.node - ], { - return Some(Args::Vec(&*args)); - }} - - None - } - else { - None - }; - }} - - None -} -- cgit 1.4.1-3-g733a5 From 28bd591f05770fd35cc6f2f82f0a13e71d13dcea Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Thu, 30 Jun 2016 19:50:03 +0200 Subject: Only build suggestion if necessary in `USELESS_VEC` --- clippy_lints/src/vec.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 8e09f9341c2..6f4c5a1e0e2 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -51,26 +51,26 @@ impl LateLintPass for Pass { fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { if let Some(vec_args) = higher::vec_macro(cx, vec) { - let snippet = match vec_args { - higher::VecArgs::Repeat(elem, len) => { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() - } - higher::VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = Span { - lo: args[0].span.lo, - hi: last.span.hi, - expn_id: args[0].span.expn_id, - }; + span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { + let snippet = match vec_args { + higher::VecArgs::Repeat(elem, len) => { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } + higher::VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = Span { + lo: args[0].span.lo, + hi: last.span.hi, + expn_id: args[0].span.expn_id, + }; - format!("&[{}]", snippet(cx, span, "..")).into() - } else { - "&[]".into() + format!("&[{}]", snippet(cx, span, "..")).into() + } else { + "&[]".into() + } } - } - }; + }; - span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { db.span_suggestion(span, "you can use a slice directly", snippet); }); } -- cgit 1.4.1-3-g733a5 From 3c4af496621cbd5a2a89b2532a2e5f3338cdddf1 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 28 Jun 2016 15:54:23 +0200 Subject: Rustup to ea0dc9297283daff6486807f43e190b4eb561412 --- clippy_lints/src/booleans.rs | 3 ++- clippy_lints/src/formatting.rs | 12 ++---------- clippy_lints/src/items_after_statements.rs | 31 ++++++++++++++---------------- clippy_lints/src/misc_early.rs | 15 +++++++-------- clippy_lints/src/non_expressive_names.rs | 14 +++++++------- clippy_lints/src/returns.rs | 21 ++++++++++---------- mini-macro/src/lib.rs | 2 +- src/main.rs | 12 ++++++------ tests/compile-fail/formatting.rs | 16 ++++++++++++++- tests/compile-fail/item_after_statement.rs | 10 ++++++++++ tests/compile-fail/needless_bool.rs | 18 ++++++++--------- tests/consts.rs | 3 ++- 12 files changed, 86 insertions(+), 71 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 8b7952b3746..672dee77783 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -3,6 +3,7 @@ use rustc::hir::*; use rustc::hir::intravisit::*; use syntax::ast::{LitKind, DUMMY_NODE_ID}; use syntax::codemap::{DUMMY_SP, dummy_spanned}; +use syntax::util::ThinVec; use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// **What it does:** This lint checks for boolean expressions that can be written more concisely @@ -99,7 +100,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { Expr { id: DUMMY_NODE_ID, span: DUMMY_SP, - attrs: None, + attrs: ThinVec::new(), node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), } }; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index aa6dd46cf0b..930fd7ae9a6 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -59,21 +59,13 @@ impl EarlyLintPass for Formatting { fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { for w in block.stmts.windows(2) { match (&w[0].node, &w[1].node) { - (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Expr(ref second, _)) | - (&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Semi(ref second, _)) => { + (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) | + (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => { check_consecutive_ifs(cx, first, second); } _ => (), } } - - if let Some(ref expr) = block.expr { - if let Some(ref stmt) = block.stmts.iter().last() { - if let ast::StmtKind::Expr(ref first, _) = stmt.node { - check_consecutive_ifs(cx, first, expr); - } - } - } } fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 2e6b33ab390..0afc2e8f7ce 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::in_macro; +use utils::{in_macro, span_lint}; /// **What it does:** This lints checks for items declared after some statement in a block /// @@ -44,26 +44,23 @@ impl EarlyLintPass for ItemsAfterStatements { if in_macro(cx, item.span) { return; } - let mut stmts = item.stmts.iter().map(|stmt| &stmt.node); + // skip initial items - while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() { - if let DeclKind::Local(_) = decl.node { - break; - } - } + let stmts = item.stmts.iter() + .map(|stmt| &stmt.node) + .skip_while(|s| matches!(**s, StmtKind::Item(..))); + // lint on all further items for stmt in stmts { - if let StmtKind::Decl(ref decl, _) = *stmt { - if let DeclKind::Item(ref it) = decl.node { - if in_macro(cx, it.span) { - return; - } - cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, - it.span, - "adding items after statements is confusing, since items exist from the \ - start of the scope") - .emit(); + if let StmtKind::Item(ref it) = *stmt { + if in_macro(cx, it.span) { + return; } + span_lint(cx, + ITEMS_AFTER_STATEMENTS, + it.span, + "adding items after statements is confusing, since items exist from the \ + start of the scope"); } } } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index e382b7dc5f6..45964cf3ce7 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -171,15 +171,14 @@ impl EarlyLintPass for MiscEarly { fn check_block(&mut self, cx: &EarlyContext, block: &Block) { for w in block.stmts.windows(2) { if_let_chain! {[ - let StmtKind::Decl(ref first, _) = w[0].node, - let DeclKind::Local(ref local) = first.node, + let StmtKind::Local(ref local) = w[0].node, let Option::Some(ref t) = local.init, - let ExprKind::Closure(_,_,_,_) = t.node, - let PatKind::Ident(_,sp_ident,_) = local.pat.node, - let StmtKind::Semi(ref second,_) = w[1].node, - let ExprKind::Assign(_,ref call) = second.node, - let ExprKind::Call(ref closure,_) = call.node, - let ExprKind::Path(_,ref path) = closure.node + let ExprKind::Closure(_, _, _, _) = t.node, + let PatKind::Ident(_, sp_ident, _) = local.pat.node, + let StmtKind::Semi(ref second) = w[1].node, + let ExprKind::Assign(_, ref call) = second.node, + let ExprKind::Call(ref closure, _) = call.node, + let ExprKind::Path(_, ref path) = closure.node ], { if sp_ident.node == (&path.segments[0]).identifier { span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared"); diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index aa8608fb7bd..17f12afcaec 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -68,8 +68,8 @@ const WHITELIST: &'static [&'static [&'static str]] = &[ struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); -impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { - fn visit_pat(&mut self, pat: &'v Pat) { +impl<'a, 'b, 'c> Visitor for SimilarNamesNameVisitor<'a, 'b, 'c> { + fn visit_pat(&mut self, pat: &Pat) { match pat.node { PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), PatKind::Struct(_, ref fields, _) => { @@ -226,25 +226,25 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> { } } -impl<'v, 'a, 'b> Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { - fn visit_local(&mut self, local: &'v Local) { +impl<'a, 'b> Visitor for SimilarNamesLocalVisitor<'a, 'b> { + fn visit_local(&mut self, local: &Local) { if let Some(ref init) = local.init { self.apply(|this| walk_expr(this, &**init)); } // add the pattern after the expression because the bindings aren't available yet in the init expression SimilarNamesNameVisitor(self).visit_pat(&*local.pat); } - fn visit_block(&mut self, blk: &'v Block) { + fn visit_block(&mut self, blk: &Block) { self.apply(|this| walk_block(this, blk)); } - fn visit_arm(&mut self, arm: &'v Arm) { + fn visit_arm(&mut self, arm: &Arm) { self.apply(|this| { // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); this.apply(|this| walk_expr(this, &arm.body)); }); } - fn visit_item(&mut self, _: &'v Item) { + fn visit_item(&mut self, _: &Item) { // do not recurse into inner items } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 6beed822a81..fda151cd6d7 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -36,13 +36,12 @@ pub struct ReturnPass; impl ReturnPass { // Check the final stmt or expr in a block for unnecessary return. fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) { - if let Some(ref expr) = block.expr { - self.check_final_expr(cx, expr); - } else if let Some(stmt) = block.stmts.last() { - if let StmtKind::Semi(ref expr, _) = stmt.node { - if let ExprKind::Ret(Some(ref inner)) = expr.node { - self.emit_return_lint(cx, (stmt.span, inner.span)); + if let Some(stmt) = block.stmts.last() { + match stmt.node { + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + self.check_final_expr(cx, expr); } + _ => (), } } } @@ -88,12 +87,14 @@ impl ReturnPass { // Check for "let x = EXPR; x" fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { + let mut it = block.stmts.iter(); + // we need both a let-binding stmt and an expr if_let_chain! {[ - let Some(stmt) = block.stmts.last(), - let Some(ref retexpr) = block.expr, - let StmtKind::Decl(ref decl, _) = stmt.node, - let DeclKind::Local(ref local) = decl.node, + let Some(ref retexpr) = it.next_back(), + let StmtKind::Expr(ref retexpr) = retexpr.node, + let Some(stmt) = it.next_back(), + let StmtKind::Local(ref local) = stmt.node, let Some(ref initexpr) = local.init, let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, let ExprKind::Path(_, ref path) = retexpr.node, diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 699d17d4d70..4b0c5ea5afd 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -5,7 +5,7 @@ extern crate rustc; extern crate rustc_plugin; use syntax::codemap::Span; -use syntax::ast::TokenTree; +use syntax::tokenstream::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc_plugin::Registry; diff --git a/src/main.rs b/src/main.rs index 17a219cafa0..c4ad6d66177 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,17 +2,17 @@ #![feature(box_syntax)] #![feature(rustc_private)] -extern crate rustc_driver; +extern crate clippy_lints; extern crate getopts; extern crate rustc; -extern crate syntax; +extern crate rustc_driver; +extern crate rustc_errors; extern crate rustc_plugin; -extern crate clippy_lints; +extern crate syntax; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; -use syntax::diagnostics; use std::path::PathBuf; use std::process::Command; @@ -36,7 +36,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { fn early_callback(&mut self, matches: &getopts::Matches, sopts: &config::Options, - descriptions: &diagnostics::registry::Registry, + descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType) -> Compilation { self.0.early_callback(matches, sopts, descriptions, output) @@ -46,7 +46,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { sopts: &config::Options, odir: &Option<PathBuf>, ofile: &Option<PathBuf>, - descriptions: &diagnostics::registry::Registry) + descriptions: &rustc_errors::registry::Registry) -> Option<(Input, Option<PathBuf>)> { self.0.no_input(matches, sopts, odir, ofile, descriptions) } diff --git a/tests/compile-fail/formatting.rs b/tests/compile-fail/formatting.rs index 2436f64d216..9b8146dc229 100644 --- a/tests/compile-fail/formatting.rs +++ b/tests/compile-fail/formatting.rs @@ -16,7 +16,9 @@ fn main() { //~| NOTE add the missing `else` or } - let _ = { + let _ = { // if as the last expression + let _ = 0; + if foo() { } if foo() { //~^ ERROR this looks like an `else if` but the `else` is missing @@ -26,6 +28,18 @@ fn main() { } }; + let _ = { // if in the middle of a block + if foo() { + } if foo() { + //~^ ERROR this looks like an `else if` but the `else` is missing + //~| NOTE add the missing `else` or + } + else { + } + + let _ = 0; + }; + if foo() { } else //~^ ERROR this is an `else if` but the formatting might hide it diff --git a/tests/compile-fail/item_after_statement.rs b/tests/compile-fail/item_after_statement.rs index f104081faa9..4be89176fc7 100644 --- a/tests/compile-fail/item_after_statement.rs +++ b/tests/compile-fail/item_after_statement.rs @@ -2,6 +2,16 @@ #![plugin(clippy)] #![deny(items_after_statements)] +fn ok() { + fn foo() { println!("foo"); } + foo(); +} + +fn last() { + foo(); + fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing +} + fn main() { foo(); fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index 7f2d7754bda..480c16f1666 100644 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -1,8 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] +#![deny(needless_bool)] #[allow(if_same_then_else)] -#[deny(needless_bool)] fn main() { let x = true; if x { true } else { true }; //~ERROR this if-then-else expression will always return true @@ -22,19 +22,19 @@ fn main() { bool_ret4(x); } -#[deny(needless_bool)] -#[allow(if_same_then_else)] +#[allow(if_same_then_else, needless_return)] fn bool_ret(x: bool) -> bool { - if x { return true } else { return true }; //~ERROR this if-then-else expression will always return true + if x { return true } else { return true }; + //~^ ERROR this if-then-else expression will always return true } -#[deny(needless_bool)] -#[allow(if_same_then_else)] +#[allow(if_same_then_else, needless_return)] fn bool_ret2(x: bool) -> bool { - if x { return false } else { return false }; //~ERROR this if-then-else expression will always return false + if x { return false } else { return false }; + //~^ ERROR this if-then-else expression will always return false } -#[deny(needless_bool)] +#[allow(needless_return)] fn bool_ret3(x: bool) -> bool { if x { return true } else { return false }; //~^ ERROR this if-then-else expression returns a bool literal @@ -42,7 +42,7 @@ fn bool_ret3(x: bool) -> bool { //~| SUGGESTION `return x` } -#[deny(needless_bool)] +#[allow(needless_return)] fn bool_ret4(x: bool) -> bool { if x { return false } else { return true }; //~^ ERROR this if-then-else expression returns a bool literal diff --git a/tests/consts.rs b/tests/consts.rs index 81500f9d393..773b889ebff 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -14,6 +14,7 @@ use syntax::ast::{LitIntType, LitKind, StrStyle}; use syntax::codemap::{Spanned, COMMAND_LINE_SP}; use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::util::ThinVec; fn spanned<T>(t: T) -> Spanned<T> { Spanned { @@ -27,7 +28,7 @@ fn expr(n: Expr_) -> Expr { id: 1, node: n, span: COMMAND_LINE_SP, - attrs: None, + attrs: ThinVec::new(), } } -- cgit 1.4.1-3-g733a5 From 55b78ae47844f65d8d2703a4edd1b9d5a2bfb93e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 17:41:57 +0200 Subject: Rustup to ea0dc9297283daff6486807f43e190b4eb561412 II --- clippy_lints/src/collapsible_if.rs | 34 +++++++++++----------------------- tests/compile-fail/collapsible_if.rs | 5 +++++ 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 2921bc2769c..57252037270 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -72,8 +72,8 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) { fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { if_let_chain! {[ let ast::ExprKind::Block(ref block) = else_.node, - block.stmts.is_empty(), - let Some(ref else_) = block.expr, + let Some(ref else_) = expr_block(block), + !in_macro(cx, else_.span), ], { match else_.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { @@ -96,7 +96,7 @@ fn check_collapsible_no_if_let( then: &ast::Block, ) { if_let_chain! {[ - let Some(inner) = single_stmt_of_block(then), + let Some(inner) = expr_block(then), let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node, ], { if expr.span.expn_id != inner.span.expn_id { @@ -128,28 +128,16 @@ fn check_to_string(cx: &EarlyContext, e: &ast::Expr) -> Cow<'static, str> { } } -fn single_stmt_of_block(block: &ast::Block) -> Option<&ast::Expr> { - if block.stmts.len() == 1 && block.expr.is_none() { - if let ast::StmtKind::Expr(ref expr, _) = block.stmts[0].node { - single_stmt_of_expr(expr) - } else { - None - } - } else if block.stmts.is_empty() { - if let Some(ref p) = block.expr { - Some(p) - } else { - None +/// If the block contains only one expression, returns it. +fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { + let mut it = block.stmts.iter(); + + if let (Some(stmt), None) = (it.next(), it.next()) { + match stmt.node { + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr), + _ => None, } } else { None } } - -fn single_stmt_of_expr(expr: &ast::Expr) -> Option<&ast::Expr> { - if let ast::ExprKind::Block(ref block) = expr.node { - single_stmt_of_block(block) - } else { - Some(expr) - } -} diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs index ea2ef284f38..e51e31c6937 100644 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -139,4 +139,9 @@ fn main() { println!("world!") } } + + if true { + } else { + assert!(true); // assert! is just an `if` + } } -- cgit 1.4.1-3-g733a5 From 97f65b02962af06e351bf33783803caace767f4e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 17:49:05 +0200 Subject: Rustup to ea0dc9297283daff6486807f43e190b4eb561412 III --- clippy_lints/src/utils/sugg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index a28c00efcae..90cb4cf00fd 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -77,10 +77,10 @@ impl<'a> Sugg<'a> { ast::ExprKind::InPlace(..) | ast::ExprKind::Unary(..) | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), - ast::ExprKind::Again(..) | ast::ExprKind::Block(..) | ast::ExprKind::Break(..) | ast::ExprKind::Call(..) | + ast::ExprKind::Continue(..) | ast::ExprKind::Field(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Index(..) | -- cgit 1.4.1-3-g733a5 From e613c8b492495aeb5f75f94a0cdcf252573a345f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 18:38:50 +0200 Subject: Introduce `multispan_sugg` --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/utils/mod.rs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 41a61feab53..6bdfbe98b5b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -38,6 +38,7 @@ extern crate quine_mc_cluskey; extern crate rustc_serialize; +extern crate rustc_errors; extern crate rustc_plugin; extern crate rustc_const_eval; extern crate rustc_const_math; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index df9d09ed010..3e0f0db6ac1 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,12 +9,13 @@ use rustc::traits::ProjectionMode; use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty; +use rustc_errors; use std::borrow::Cow; use std::env; use std::mem; use std::str::FromStr; use syntax::ast::{self, LitKind}; -use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; +use syntax::codemap::{ExpnFormat, ExpnInfo, MultiSpan, Span}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; @@ -490,6 +491,25 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, } } +/// Create a suggestion made from several `span → replacement`. +/// +/// Note: in the JSON format (used by `compiletest_rs`), the help message will appear once per +/// replacement. In human-readable format though, it only appears once before the whole suggestion. +pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: &[(Span, &str)]) { + let sugg = rustc_errors::RenderSpan::Suggestion(rustc_errors::CodeSuggestion { + msp: MultiSpan::from_spans(sugg.iter().map(|&(span, _)| span).collect()), + substitutes: sugg.iter().map(|&(_, subs)| subs.to_owned()).collect(), + }); + + let sub = rustc_errors::SubDiagnostic { + level: rustc_errors::Level::Help, + message: help_msg, + span: MultiSpan::new(), + render_span: Some(sugg), + }; + db.children.push(sub); +} + /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { match ty.sty { -- cgit 1.4.1-3-g733a5 From 9bd7fa05e0fd3049e74a900e39c17cd9d6ebfbbc Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 18:44:59 +0200 Subject: Improve `NEEDLESS_RANGE_LOOP` error reporting --- clippy_lints/src/loops.rs | 41 ++++++++++++++-------------- tests/compile-fail/for_loop.rs | 62 +++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 1a6ac75eb37..0f9d030c2f2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; use std::collections::HashMap; use syntax::ast; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty}; use utils::paths; @@ -377,17 +377,16 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex }; if visitor.nonindex { - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \ - item) in {}.iter().enumerate(){}{}` or similar iterators", - ident.node, - indexed, - ident.node, - indexed, - take, - skip)); + span_lint_and_then(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), + |db| { + multispan_sugg(db, "consider using an iterator".to_string(), &[ + (pat.span, &format!("({}, <item>)", ident.node)), + (arg.span, &format!("{}.iter().enumerate(){}{}", indexed, take, skip)), + ]); + }); } else { let repl = if starts_at_zero && take.is_empty() { format!("&{}", indexed) @@ -395,14 +394,16 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex format!("{}.iter(){}{}", indexed, take, skip) }; - span_lint(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is only used to index `{}`. \ - Consider using `for item in {}` or similar iterators", - ident.node, - indexed, - repl)); + span_lint_and_then(cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`.", ident.node, indexed), + |db| { + multispan_sugg(db, "consider using an iterator".to_string(), &[ + (pat.span, "<item>"), + (arg.span, &repl), + ]); + }); } } } diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 411a4b11c17..6028c5c0f3a 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -96,23 +96,41 @@ fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; for i in 0..vec.len() { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in &vec` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in &vec { println!("{}", vec[i]); } + for i in 0..vec.len() { let _ = vec[i]; } + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in &vec { let _ = vec[i]; } + // ICE #746 for j in 0..4 { //~^ ERROR `j` is only used to index `STATIC` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in STATIC.iter().take(4) { println!("{:?}", STATIC[j]); } for j in 0..4 { //~^ ERROR `j` is only used to index `CONST` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in CONST.iter().take(4) { println!("{:?}", CONST[j]); } for i in 0..vec.len() { - //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate()` + //~^ ERROR `i` is used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for (i, <item>) in vec.iter().enumerate() { println!("{} {}", vec[i], i); } for i in 0..vec.len() { // not an error, indexing more than one variable @@ -120,42 +138,66 @@ fn main() { } for i in 0..vec.len() { - //~^ ERROR `i` is only used to index `vec2`. Consider using `for item in vec2.iter().take(vec.len())` + //~^ ERROR `i` is only used to index `vec2` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec2.iter().take(vec.len()) { println!("{}", vec2[i]); } for i in 5..vec.len() { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().skip(5)` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec.iter().skip(5) { println!("{}", vec[i]); } for i in 0..MAX_LEN { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec.iter().take(MAX_LEN) { println!("{}", vec[i]); } for i in 0...MAX_LEN { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec.iter().take(MAX_LEN) { println!("{}", vec[i]); } for i in 5..10 { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec.iter().take(10).skip(5) { println!("{}", vec[i]); } for i in 5...10 { - //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)` + //~^ ERROR `i` is only used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for <item> in vec.iter().take(10).skip(5) { println!("{}", vec[i]); } for i in 5..vec.len() { - //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().skip(5)` + //~^ ERROR `i` is used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for (i, <item>) in vec.iter().enumerate().skip(5) { println!("{} {}", vec[i], i); } for i in 5..10 { - //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().take(10).skip(5)` + //~^ ERROR `i` is used to index `vec` + //~| HELP consider + //~| HELP consider + //~| SUGGESTION for (i, <item>) in vec.iter().enumerate().take(10).skip(5) { println!("{} {}", vec[i], i); } -- cgit 1.4.1-3-g733a5 From dbf6dc66d8ad9ed6af686aa9fe9ecb893a6cf23e Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 19:30:38 +0200 Subject: Add more sugggestion-building functions --- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/misc.rs | 6 +-- clippy_lints/src/utils/sugg.rs | 88 +++++++++++++++++++++++++++++--------- 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 1d9e3984e74..ca5a097119d 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -107,7 +107,7 @@ fn check_collapsible_no_if_let( db.span_suggestion(expr.span, "try", format!("if {} {}", - lhs.and(&rhs), + lhs.and(rhs), snippet_block(cx, content.span, ".."))); }); }} diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 8fddcb84922..94b36d28ed3 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -263,7 +263,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) } (true, false) => { - let test = &Sugg::hir(cx, ex, ".."); + let test = Sugg::hir(cx, ex, ".."); Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 0931d5aca6b..b1627c31c8b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -72,7 +72,7 @@ impl LateLintPass for TopLevelRefPass { l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { - let init = &Sugg::hir(cx, init, ".."); + let init = Sugg::hir(cx, init, ".."); db.span_suggestion(s.span, "try", format!("let {}{} = {};", @@ -171,8 +171,8 @@ impl LateLintPass for FloatCmp { expr.span, "strict comparison of f32 or f64", |db| { - let lhs = &Sugg::hir(cx, left, ".."); - let rhs = &Sugg::hir(cx, right, ".."); + let lhs = Sugg::hir(cx, left, ".."); + let rhs = Sugg::hir(cx, right, ".."); db.span_suggestion(expr.span, "consider comparing them within some error", diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 90cb4cf00fd..d05629b1a76 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -5,6 +5,7 @@ use std; use syntax::ast; use syntax::util::parser::AssocOp; use utils::{higher, snippet}; +use syntax::print::pprust::binop_to_string; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -16,6 +17,9 @@ pub enum Sugg<'a> { BinOp(AssocOp, Cow<'a, str>), } +/// Literal constant `1`, for convenience. +pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); + impl<'a> std::fmt::Display for Sugg<'a> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match *self { @@ -110,28 +114,43 @@ impl<'a> Sugg<'a> { } } - /// Convenience method to create the `lhs && rhs` suggestion. - pub fn and(&self, rhs: &Self) -> Sugg<'static> { - make_binop(ast::BinOpKind::And, self, rhs) + /// Convenience method to create the `<lhs> && <rhs>` suggestion. + pub fn and(self, rhs: Self) -> Sugg<'static> { + make_binop(ast::BinOpKind::And, &self, &rhs) } /// Convenience method to create the `&<expr>` suggestion. - pub fn addr(&self) -> Sugg<'static> { - make_unop("&", self) + pub fn addr(self) -> Sugg<'static> { + make_unop("&", &self) + } + + /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion. + pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { + match limit { + ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, &end), + ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotDot, &self, &end), + } + } +} + +impl<'a, 'b> std::ops::Add<Sugg<'b>> for Sugg<'a> { + type Output = Sugg<'static>; + fn add(self, rhs: Sugg<'b>) -> Sugg<'static> { + make_binop(ast::BinOpKind::Add, &self, &rhs) } } -impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> { +impl<'a, 'b> std::ops::Sub<Sugg<'b>> for Sugg<'a> { type Output = Sugg<'static>; - fn sub(self, rhs: &'b Sugg<'b>) -> Sugg<'static> { - make_binop(ast::BinOpKind::Sub, self, rhs) + fn sub(self, rhs: Sugg<'b>) -> Sugg<'static> { + make_binop(ast::BinOpKind::Sub, &self, &rhs) } } -impl<'a> std::ops::Not for &'a Sugg<'a> { +impl<'a> std::ops::Not for Sugg<'a> { type Output = Sugg<'static>; fn not(self) -> Sugg<'static> { - make_unop("!", self) + make_unop("!", &self) } } @@ -172,7 +191,7 @@ pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> { /// /// Precedence of shift operator relative to other arithmetic operation is often confusing so /// parenthesis will always be added for a mix of these. -pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { +pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { fn is_shift(op: &AssocOp) -> bool { matches!(*op, AssocOp::ShiftLeft | AssocOp::ShiftRight) } @@ -190,25 +209,54 @@ pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { is_shift(other) && is_arith(op) } - let aop = AssocOp::from_ast_binop(op); - let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs { - needs_paren(&aop, lop, Associativity::Left) + needs_paren(&op, lop, Associativity::Left) } else { false }; let rhs_paren = if let Sugg::BinOp(ref rop, _) = *rhs { - needs_paren(&aop, rop, Associativity::Right) + needs_paren(&op, rop, Associativity::Right) } else { false }; - Sugg::BinOp(aop, - format!("{} {} {}", - ParenHelper::new(lhs_paren, lhs), - op.to_string(), - ParenHelper::new(rhs_paren, rhs)).into()) + let lhs = ParenHelper::new(lhs_paren, lhs); + let rhs = ParenHelper::new(rhs_paren, rhs); + let sugg = match op { + AssocOp::Add | + AssocOp::BitAnd | + AssocOp::BitOr | + AssocOp::BitXor | + AssocOp::Divide | + AssocOp::Equal | + AssocOp::Greater | + AssocOp::GreaterEqual | + AssocOp::LAnd | + AssocOp::LOr | + AssocOp::Less | + AssocOp::LessEqual | + AssocOp::Modulus | + AssocOp::Multiply | + AssocOp::NotEqual | + AssocOp::ShiftLeft | + AssocOp::ShiftRight | + AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), + AssocOp::Inplace => format!("in ({}) {}", lhs, rhs), + AssocOp::Assign => format!("{} = {}", lhs, rhs), + AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, binop_to_string(op), rhs), + AssocOp::As => format!("{} as {}", lhs, rhs), + AssocOp::DotDot => format!("{}..{}", lhs, rhs), + AssocOp::DotDotDot => format!("{}...{}", lhs, rhs), + AssocOp::Colon => format!("{}: {}", lhs, rhs), + }; + + Sugg::BinOp(op, sugg.into()) +} + +/// Convinience wrapper arround `make_assoc` and `AssocOp::from_ast_binop`. +pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { + make_assoc(AssocOp::from_ast_binop(op), lhs, rhs) } #[derive(PartialEq, Eq)] -- cgit 1.4.1-3-g733a5 From f6c9490e6527d204bd4a22273e01f76632460506 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 19:31:14 +0200 Subject: Fix wrong suggestion with `...` and for loops --- clippy_lints/src/loops.rs | 26 +++++++++++++++++--------- tests/compile-fail/for_loop.rs | 4 ++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0f9d030c2f2..2aa0332a824 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -9,9 +9,9 @@ use rustc::middle::region::CodeExtent; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; -use std::borrow::Cow; use std::collections::HashMap; use syntax::ast; +use utils::sugg; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, @@ -332,7 +332,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E /// Check for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { - if let Some(higher::Range { start: Some(ref start), ref end, .. }) = higher::range(arg) { + if let Some(higher::Range { start: Some(ref start), ref end, limits }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { @@ -360,20 +360,28 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex let starts_at_zero = is_integer_literal(start, 0); - let skip: Cow<_> = if starts_at_zero { - "".into() + let skip = if starts_at_zero { + "".to_owned() } else { - format!(".skip({})", snippet(cx, start.span, "..")).into() + format!(".skip({})", snippet(cx, start.span, "..")) }; - let take: Cow<_> = if let Some(ref end) = *end { + let take = if let Some(ref end) = *end { if is_len_call(end, &indexed) { - "".into() + "".to_owned() } else { - format!(".take({})", snippet(cx, end.span, "..")).into() + match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, "<count>"); + format!(".take({})", end + sugg::ONE) + } + ast::RangeLimits::HalfOpen => { + format!(".take({})", snippet(cx, end.span, "..")) + } + } } } else { - "".into() + "".to_owned() }; if visitor.nonindex { diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 6028c5c0f3a..1ef8eacd1d9 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -165,7 +165,7 @@ fn main() { //~^ ERROR `i` is only used to index `vec` //~| HELP consider //~| HELP consider - //~| SUGGESTION for <item> in vec.iter().take(MAX_LEN) { + //~| SUGGESTION for <item> in vec.iter().take(MAX_LEN + 1) { println!("{}", vec[i]); } @@ -181,7 +181,7 @@ fn main() { //~^ ERROR `i` is only used to index `vec` //~| HELP consider //~| HELP consider - //~| SUGGESTION for <item> in vec.iter().take(10).skip(5) { + //~| SUGGESTION for <item> in vec.iter().take(10 + 1).skip(5) { println!("{}", vec[i]); } -- cgit 1.4.1-3-g733a5 From 2a45a2ab6b5fd9075b3488c32825a6686f532559 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 20:55:45 +0200 Subject: Use `utils::sugg` in `FOR_KV_MAP` --- clippy_lints/src/loops.rs | 27 ++++++++++++++------------- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/utils/sugg.rs | 20 ++++++++++++++------ tests/compile-fail/for_loop.rs | 18 ++++++++++++++++-- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2aa0332a824..a4e338053e2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -596,18 +596,20 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex /// Check for the `FOR_KV_MAP` lint. fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { + let pat_span = pat.span; + if let PatKind::Tuple(ref pat, _) = pat.node { if pat.len() == 2 { - let (pat_span, kind) = match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"), - (_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"), + let (new_pat_span, kind) = match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value"), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key"), _ => return, }; - let arg_span = match arg.node { - ExprAddrOf(MutImmutable, ref expr) => expr.span, + let (arg_span, arg) = match arg.node { + ExprAddrOf(MutImmutable, ref expr) => (arg.span, &**expr), ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method - _ => arg.span, + _ => (arg.span, arg), }; let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg)); @@ -615,14 +617,13 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex span_lint_and_then(cx, FOR_KV_MAP, expr.span, - &format!("you seem to want to iterate on a map's {}", kind), + &format!("you seem to want to iterate on a map's {}s", kind), |db| { - db.span_suggestion(expr.span, - "use the corresponding method", - format!("for {} in {}.{}() {{ .. }}", - snippet(cx, *pat_span, ".."), - snippet(cx, arg_span, ".."), - kind)); + let map = sugg::Sugg::hir(cx, arg, "map"); + multispan_sugg(db, "use the corresponding method".into(), &[ + (pat_span, &snippet(cx, new_pat_span, kind)), + (arg_span, &format!("{}.{}s()", map.maybe_par(), kind)), + ]); }); } } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 12d2184693a..d95fad8fc0f 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -149,7 +149,7 @@ impl LateLintPass for Transmute { from_ty, to_ty), |db| { - let arg = &sugg::Sugg::hir(cx, &args[0], ".."); + let arg = sugg::Sugg::hir(cx, &args[0], ".."); let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { ("&mut *", "*mut") } else { diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d05629b1a76..c2fd2c1a6b7 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -121,7 +121,7 @@ impl<'a> Sugg<'a> { /// Convenience method to create the `&<expr>` suggestion. pub fn addr(self) -> Sugg<'static> { - make_unop("&", &self) + make_unop("&", self) } /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion. @@ -131,6 +131,15 @@ impl<'a> Sugg<'a> { ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotDot, &self, &end), } } + + /// Add parenthesis to any expression that might need them. Suitable to the `self` argument of + /// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`). + pub fn maybe_par(self) -> Self { + match self { + Sugg::NonParen(..) => self, + Sugg::MaybeParen(sugg) | Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()), + } + } } impl<'a, 'b> std::ops::Add<Sugg<'b>> for Sugg<'a> { @@ -150,7 +159,7 @@ impl<'a, 'b> std::ops::Sub<Sugg<'b>> for Sugg<'a> { impl<'a> std::ops::Not for Sugg<'a> { type Output = Sugg<'static>; fn not(self) -> Sugg<'static> { - make_unop("!", &self) + make_unop("!", self) } } @@ -178,13 +187,12 @@ impl<T: std::fmt::Display> std::fmt::Display for ParenHelper<T> { } } -/// Build the string for `<op> <expr>` adding parenthesis when necessary. +/// Build the string for `<op><expr>` adding parenthesis when necessary. /// /// For convenience, the operator is taken as a string because all unary operators have the same /// precedence. -pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> { - let needs_paren = !matches!(*expr, Sugg::NonParen(..)); - Sugg::MaybeParen(format!("{}{}", op, ParenHelper::new(needs_paren, expr)).into()) +pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> { + Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into()) } /// Build the string for `<lhs> <op> <rhs>` adding parenthesis when necessary. diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 1ef8eacd1d9..bcb20be4ff4 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] use std::collections::*; +use std::rc::Rc; static STATIC: [usize; 4] = [ 0, 1, 8, 16 ]; const CONST: [usize; 4] = [ 0, 1, 8, 16 ]; @@ -388,8 +389,20 @@ fn main() { for (_, v) in &m { //~^ you seem to want to iterate on a map's values //~| HELP use the corresponding method - //~| SUGGESTION for v in m.values() + //~| HELP use the corresponding method + //~| SUGGESTION for v in m.values() { + let _v = v; + } + + let m : Rc<HashMap<u64, u64>> = Rc::new(HashMap::new()); + for (_, v) in &*m { + //~^ you seem to want to iterate on a map's values + //~| HELP use the corresponding method + //~| HELP use the corresponding method + //~| SUGGESTION for v in (*m).values() { let _v = v; + // Here the `*` is not actually necesarry, but the test tests that we don't suggest + // `in *m.values()` as we used to } let mut m : HashMap<u64, u64> = HashMap::new(); @@ -403,7 +416,8 @@ fn main() { for (k, _value) in rm { //~^ you seem to want to iterate on a map's keys //~| HELP use the corresponding method - //~| SUGGESTION for k in rm.keys() + //~| HELP use the corresponding method + //~| SUGGESTION for k in rm.keys() { let _k = k; } -- cgit 1.4.1-3-g733a5 From 139b977d9d64d67cddabbfee8536b0a7d7ed6de4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 1 Jul 2016 21:01:56 +0200 Subject: Cleanup --- clippy_lints/src/misc_early.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 45964cf3ce7..c0f1c611f71 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -149,7 +149,7 @@ impl EarlyLintPass for MiscEarly { "Try not to call a closure in the expression where it is declared.", |db| { if decl.inputs.is_empty() { - let hint = format!("{}", snippet(cx, block.span, "..")); + let hint = snippet(cx, block.span, "..").into_owned(); db.span_suggestion(expr.span, "Try doing something like: ", hint); } }); -- cgit 1.4.1-3-g733a5 From d35b94349c9973fe372541376f96da682b80d24f Mon Sep 17 00:00:00 2001 From: Ben Boeckel <mathstuf@gmail.com> Date: Fri, 1 Jul 2016 22:59:42 -0400 Subject: typo: use commas around "e.g." --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a959dbe1d6a..c59453333a4 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -73,7 +73,7 @@ declare_lint! { /// |`is_` |`&self` or none | /// |`to_` |`&self` | /// -/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_..` function. +/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they, e.g., need to supply a mutable reference to a `as_..` function. /// /// **Known problems:** None /// -- cgit 1.4.1-3-g733a5 From f609ac5b587f92947b3341a75e663b77ca73037c Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 2 Jul 2016 16:02:27 +0200 Subject: Bump to 0.0.78 --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fece611c1da..7fedd374948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.78 - TBA +## 0.0.78 - 2016-07-02 +* Rustup to *rustc 1.11.0-nightly (01411937f 2016-07-01)* * New lints: [`wrong_transmute`, `double_neg`] * For compatibility, `cargo clippy` does not defines the `clippy` feature introduced in 0.0.76 anymore diff --git a/Cargo.toml b/Cargo.toml index 5dc1363f3f5..f8b63a56257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.77" +version = "0.0.78" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -25,7 +25,7 @@ test = false [dependencies] # begin automatic update -clippy_lints = { version = "0.0.77", path = "clippy_lints" } +clippy_lints = { version = "0.0.78", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a1012e94ee5..e74db2b17a6 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.77" +version = "0.0.78" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From cc18556ae550089bf79fb57013dc83ae5873336b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sat, 2 Jul 2016 17:24:24 +0200 Subject: Use `utils::sugg` in swap lints --- clippy_lints/src/swap.rs | 17 ++++----- clippy_lints/src/utils/sugg.rs | 80 ++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 5a3adfee409..667c450e669 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -2,7 +2,8 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; use syntax::codemap::mk_sp; -use utils::{differing_macro_contexts, match_type, paths, snippet, snippet_opt, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; +use utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; +use utils::sugg::Sugg; /// **What it does:** This lints manual swapping. /// @@ -100,17 +101,17 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { } let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) { - if let Some(slice) = snippet_opt(cx, slice.span) { + if let Some(slice) = Sugg::hir_opt(cx, slice) { (false, format!(" elements of `{}`", slice), - format!("{}.swap({}, {})",slice, snippet(cx, idx1.span, ".."), snippet(cx, idx2.span, ".."))) + format!("{}.swap({}, {})", slice.maybe_par(), snippet(cx, idx1.span, ".."), snippet(cx, idx2.span, ".."))) } else { (false, "".to_owned(), "".to_owned()) } } else { - if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) { + if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) { (true, format!(" `{}` and `{}`", first, second), - format!("std::mem::swap(&mut {}, &mut {})", first, second)) + format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr())) } else { (true, "".to_owned(), "".to_owned()) } @@ -147,8 +148,8 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) ], { - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs0.span), snippet_opt(cx, rhs0.span)) { - (format!(" `{}` and `{}`", first, second), first, second) + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs0), Sugg::hir_opt(cx, rhs0)) { + (format!(" `{}` and `{}`", first, second), first.mut_addr().to_string(), second.mut_addr().to_string()) } else { ("".to_owned(), "".to_owned(), "".to_owned()) }; @@ -162,7 +163,7 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { |db| { if !what.is_empty() { db.span_suggestion(span, "try", - format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs)); + format!("std::mem::swap({}, {})", lhs, rhs)); db.note("or maybe you should use `std::mem::replace`?"); } }); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index c2fd2c1a6b7..bbfa8648c53 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std; use syntax::ast; use syntax::util::parser::AssocOp; -use utils::{higher, snippet}; +use utils::{higher, snippet, snippet_opt}; use syntax::print::pprust::binop_to_string; /// A helper type to build suggestion correctly handling parenthesis. @@ -31,43 +31,48 @@ impl<'a> std::fmt::Display for Sugg<'a> { } impl<'a> Sugg<'a> { - pub fn hir(cx: &LateContext, expr: &'a hir::Expr, default: &'a str) -> Sugg<'a> { - let snippet = snippet(cx, expr.span, default); + pub fn hir_opt(cx: &LateContext, expr: &hir::Expr) -> Option<Sugg<'a>> { + snippet_opt(cx, expr.span).map(|snippet| { + let snippet = Cow::Owned(snippet); + match expr.node { + hir::ExprAddrOf(..) | + hir::ExprBox(..) | + hir::ExprClosure(..) | + hir::ExprIf(..) | + hir::ExprUnary(..) | + hir::ExprMatch(..) => Sugg::MaybeParen(snippet), + hir::ExprAgain(..) | + hir::ExprBlock(..) | + hir::ExprBreak(..) | + hir::ExprCall(..) | + hir::ExprField(..) | + hir::ExprIndex(..) | + hir::ExprInlineAsm(..) | + hir::ExprLit(..) | + hir::ExprLoop(..) | + hir::ExprMethodCall(..) | + hir::ExprPath(..) | + hir::ExprRepeat(..) | + hir::ExprRet(..) | + hir::ExprStruct(..) | + hir::ExprTup(..) | + hir::ExprTupField(..) | + hir::ExprVec(..) | + hir::ExprWhile(..) => Sugg::NonParen(snippet), + hir::ExprAssign(..) => Sugg::BinOp(AssocOp::Assign, snippet), + hir::ExprAssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), + hir::ExprBinary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), + hir::ExprCast(..) => Sugg::BinOp(AssocOp::As, snippet), + hir::ExprType(..) => Sugg::BinOp(AssocOp::Colon, snippet), + } + }) + } - match expr.node { - hir::ExprAddrOf(..) | - hir::ExprBox(..) | - hir::ExprClosure(..) | - hir::ExprIf(..) | - hir::ExprUnary(..) | - hir::ExprMatch(..) => Sugg::MaybeParen(snippet), - hir::ExprAgain(..) | - hir::ExprBlock(..) | - hir::ExprBreak(..) | - hir::ExprCall(..) | - hir::ExprField(..) | - hir::ExprIndex(..) | - hir::ExprInlineAsm(..) | - hir::ExprLit(..) | - hir::ExprLoop(..) | - hir::ExprMethodCall(..) | - hir::ExprPath(..) | - hir::ExprRepeat(..) | - hir::ExprRet(..) | - hir::ExprStruct(..) | - hir::ExprTup(..) | - hir::ExprTupField(..) | - hir::ExprVec(..) | - hir::ExprWhile(..) => Sugg::NonParen(snippet), - hir::ExprAssign(..) => Sugg::BinOp(AssocOp::Assign, snippet), - hir::ExprAssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), - hir::ExprBinary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), - hir::ExprCast(..) => Sugg::BinOp(AssocOp::As, snippet), - hir::ExprType(..) => Sugg::BinOp(AssocOp::Colon, snippet), - } + pub fn hir(cx: &LateContext, expr: &hir::Expr, default: &'a str) -> Sugg<'a> { + Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } - pub fn ast(cx: &EarlyContext, expr: &'a ast::Expr, default: &'a str) -> Sugg<'a> { + pub fn ast(cx: &EarlyContext, expr: &ast::Expr, default: &'a str) -> Sugg<'a> { use syntax::ast::RangeLimits; let snippet = snippet(cx, expr.span, default); @@ -124,6 +129,11 @@ impl<'a> Sugg<'a> { make_unop("&", self) } + /// Convenience method to create the `&mut <expr>` suggestion. + pub fn mut_addr(self) -> Sugg<'static> { + make_unop("&mut ", self) + } + /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion. pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { -- cgit 1.4.1-3-g733a5 From 7781f1d7c5a8ec31f9994ebad0ae1ca140e69ef7 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 16:55:55 +0200 Subject: Add a new `not_unsafe_ptr_arg_deref` lint --- CHANGELOG.md | 2 + README.md | 1 + clippy_lints/src/functions.rs | 128 +++++++++++++++++++++++++++++++++++----- clippy_lints/src/lib.rs | 1 + clippy_lints/src/utils/mod.rs | 9 +++ tests/compile-fail/functions.rs | 50 +++++++++++++++- 6 files changed, 174 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fedd374948..ae316a90b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. ## 0.0.76 — 2016-06-10 * Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)* * `cargo clippy` now automatically defines the `clippy` feature +* New lint: [`not_unsafe_ptr_arg_deref`] ## 0.0.75 — 2016-06-08 * Rustup to *rustc 1.11.0-nightly (763f9234b 2016-06-06)* @@ -220,6 +221,7 @@ All notable changes to this project will be documented in this file. [`non_ascii_literal`]: https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal [`nonminimal_bool`]: https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool [`nonsensical_open_options`]: https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options +[`not_unsafe_ptr_arg_deref`]: https://github.com/Manishearth/rust-clippy/wiki#not_unsafe_ptr_arg_deref [`ok_expect`]: https://github.com/Manishearth/rust-clippy/wiki#ok_expect [`option_map_unwrap_or`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or [`option_map_unwrap_or_else`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else diff --git a/README.md b/README.md index 2ae53db2d05..b1f8e7aabe4 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ name [non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal; suggests using the \\u escape instead [nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | allow | checks for boolean expressions that can be written more concisely [nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[not_unsafe_ptr_arg_deref](https://github.com/Manishearth/rust-clippy/wiki#not_unsafe_ptr_arg_deref) | warn | public functions dereferencing raw pointer arguments but not marked `unsafe` [ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result [option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | warn | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` [option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | warn | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 3d3423a4743..c02f02f064d 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,9 +1,11 @@ -use rustc::lint::*; -use rustc::hir; use rustc::hir::intravisit; +use rustc::hir; +use rustc::ty; +use rustc::lint::*; +use std::collections::HashSet; use syntax::ast; use syntax::codemap::Span; -use utils::span_lint; +use utils::{span_lint, type_is_unsafe_function}; /// **What it does:** Check for functions with too many parameters. /// @@ -15,7 +17,7 @@ use utils::span_lint; /// /// **Example:** /// -/// ``` +/// ```rust /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { .. } /// ``` declare_lint! { @@ -24,6 +26,30 @@ declare_lint! { "functions with too many arguments" } +/// **What it does:** Check for public functions that dereferences raw pointer arguments but are +/// not marked unsafe. +/// +/// **Why is this bad?** The function should probably be marked `unsafe`, since for an arbitrary +/// raw pointer, there is no way of telling for sure if it is valid. +/// +/// **Known problems:** +/// +/// * It does not check functions recursively so if the pointer is passed to a private non- +/// `unsafe` function which does the dereferencing, the lint won't trigger. +/// * It only checks for arguments whose type are raw pointers, not raw pointers got from an +/// argument in some other way (`fn foo(bar: &[*const u8])` or `some_argument.get_raw_ptr()`). +/// +/// **Example:** +/// +/// ```rust +/// pub fn foo(x: *const u8) { println!("{}", unsafe { *x }); } +/// ``` +declare_lint! { + pub NOT_UNSAFE_PTR_ARG_DEREF, + Warn, + "public functions dereferencing raw pointer arguments but not marked `unsafe`" +} + #[derive(Copy,Clone)] pub struct Functions { threshold: u64, @@ -37,29 +63,41 @@ impl Functions { impl LintPass for Functions { fn get_lints(&self) -> LintArray { - lint_array!(TOO_MANY_ARGUMENTS) + lint_array!(TOO_MANY_ARGUMENTS, NOT_UNSAFE_PTR_ARG_DEREF) } } impl LateLintPass for Functions { - fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, - nodeid: ast::NodeId) { + fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) { use rustc::hir::map::Node::*; - if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { - match item.node { - hir::ItemImpl(_, _, _, Some(_), _, _) | - hir::ItemDefaultImpl(..) => return, - _ => (), - } + let is_impl = if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { + matches!(item.node, hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..)) + } else { + false + }; + + let unsafety = match kind { + hir::intravisit::FnKind::ItemFn(_, _, unsafety, _, _, _, _) => unsafety, + hir::intravisit::FnKind::Method(_, sig, _, _) => sig.unsafety, + hir::intravisit::FnKind::Closure(_) => return, + }; + + // don't warn for implementations, it's not their fault + if !is_impl { + self.check_arg_number(cx, decl, span); } - self.check_arg_number(cx, decl, span); + self.check_raw_ptr(cx, unsafety, decl, block, span, nodeid); } fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { - if let hir::MethodTraitItem(ref sig, _) = item.node { + if let hir::MethodTraitItem(ref sig, ref block) = item.node { self.check_arg_number(cx, &sig.decl, item.span); + + if let Some(ref block) = *block { + self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.span, item.id); + } } } } @@ -74,4 +112,64 @@ impl Functions { &format!("this function has too many arguments ({}/{})", args, self.threshold)); } } + + fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) { + if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) { + let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>(); + + if !raw_ptrs.is_empty() { + let mut v = DerefVisitor { + cx: cx, + ptrs: raw_ptrs, + }; + + hir::intravisit::walk_block(&mut v, block); + } + } + } +} + +fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> { + if let (&hir::PatKind::Binding(_, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) { + cx.tcx.def_map.borrow().get(&arg.pat.id).map(hir::def::PathResolution::def_id) + } else { + None + } +} + +struct DerefVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + ptrs: HashSet<hir::def_id::DefId>, +} + +impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'v hir::Expr) { + let ptr = match expr.node { + hir::ExprUnary(hir::UnDeref, ref ptr) => Some(ptr), + hir::ExprMethodCall(_, _, ref args) => { + let method_call = ty::MethodCall::expr(expr.id); + let base_type = self.cx.tcx.tables.borrow().method_map[&method_call].ty; + + if type_is_unsafe_function(base_type) { + Some(&args[0]) + } else { + None + } + } + _ => None, + }; + + if let Some(ptr) = ptr { + if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) { + if self.ptrs.contains(&def.def_id()) { + span_lint(self.cx, + NOT_UNSAFE_PTR_ARG_DEREF, + ptr.span, + "this public function dereferences a raw pointer but is not marked `unsafe`"); + } + } + } + + hir::intravisit::walk_expr(self, expr); + } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 040096dcbb4..5ba52374135 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -322,6 +322,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { format::USELESS_FORMAT, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, + functions::NOT_UNSAFE_PTR_ARG_DEREF, functions::TOO_MANY_ARGUMENTS, identity_op::IDENTITY_OP, len_zero::LEN_WITHOUT_IS_EMPTY, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9eb54c2a013..30bb6dfeb76 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -813,3 +813,12 @@ pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { }} None } + +/// Return whether the given type is an `unsafe` function. +pub fn type_is_unsafe_function(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyFnDef(_, _, ref f) | + ty::TyFnPtr(ref f) => f.unsafety == Unsafety::Unsafe, + _ => false, + } +} diff --git a/tests/compile-fail/functions.rs b/tests/compile-fail/functions.rs index 2cc16568600..311da1ed2fe 100644 --- a/tests/compile-fail/functions.rs +++ b/tests/compile-fail/functions.rs @@ -3,20 +3,24 @@ #![deny(clippy)] #![allow(dead_code)] +#![allow(unused_unsafe)] +// TOO_MANY_ARGUMENTS fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { //~^ ERROR: this function has too many arguments (8/7) } -trait Foo { +pub trait Foo { fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool); fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); //~^ ERROR: this function has too many arguments (8/7) + + fn ptr(p: *const u8); } -struct Bar; +pub struct Bar; impl Bar { fn good_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} @@ -28,6 +32,48 @@ impl Bar { impl Foo for Bar { fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} + + fn ptr(p: *const u8) { + println!("{}", unsafe { *p }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + } +} + +// NOT_UNSAFE_PTR_ARG_DEREF + +fn private(p: *const u8) { + println!("{}", unsafe { *p }); +} + +pub fn public(p: *const u8) { + println!("{}", unsafe { *p }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + println!("{:?}", unsafe { p.as_ref() }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` +} + +impl Bar { + fn private(self, p: *const u8) { + println!("{}", unsafe { *p }); + } + + pub fn public(self, p: *const u8) { + println!("{}", unsafe { *p }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + println!("{:?}", unsafe { p.as_ref() }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + } + + pub fn public_ok(self, p: *const u8) { + if !p.is_null() { + println!("{:p}", p); + } + } + + pub unsafe fn public_unsafe(self, p: *const u8) { + println!("{}", unsafe { *p }); + println!("{:?}", unsafe { p.as_ref() }); + } } fn main() {} -- cgit 1.4.1-3-g733a5 From 0e3dcd13765c5fed9795227ca75e15b8849ff5a4 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 7 Jun 2016 17:29:22 +0200 Subject: Improve `NOT_UNSAFE_PTR_ARG_DEREF` with functions --- README.md | 2 +- clippy_lints/src/functions.rs | 51 +++++++++++++++++++++++++---------------- tests/compile-fail/functions.rs | 8 +++++++ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index b1f8e7aabe4..3159a3e8979 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 157 lints included in this crate: +There are 158 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index c02f02f064d..a1918aed69f 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -88,7 +88,7 @@ impl LateLintPass for Functions { self.check_arg_number(cx, decl, span); } - self.check_raw_ptr(cx, unsafety, decl, block, span, nodeid); + self.check_raw_ptr(cx, unsafety, decl, block, nodeid); } fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { @@ -96,7 +96,7 @@ impl LateLintPass for Functions { self.check_arg_number(cx, &sig.decl, item.span); if let Some(ref block) = *block { - self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.span, item.id); + self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.id); } } } @@ -113,7 +113,7 @@ impl Functions { } } - fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) { + fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, nodeid: ast::NodeId) { if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) { let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>(); @@ -144,32 +144,43 @@ struct DerefVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'v hir::Expr) { - let ptr = match expr.node { - hir::ExprUnary(hir::UnDeref, ref ptr) => Some(ptr), + match expr.node { + hir::ExprCall(ref f, ref args) => { + let ty = self.cx.tcx.expr_ty(f); + + if type_is_unsafe_function(ty) { + for arg in args { + self.check_arg(arg); + } + } + } hir::ExprMethodCall(_, _, ref args) => { let method_call = ty::MethodCall::expr(expr.id); let base_type = self.cx.tcx.tables.borrow().method_map[&method_call].ty; if type_is_unsafe_function(base_type) { - Some(&args[0]) - } else { - None - } - } - _ => None, - }; - - if let Some(ptr) = ptr { - if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) { - if self.ptrs.contains(&def.def_id()) { - span_lint(self.cx, - NOT_UNSAFE_PTR_ARG_DEREF, - ptr.span, - "this public function dereferences a raw pointer but is not marked `unsafe`"); + for arg in args { + self.check_arg(arg); + } } } + hir::ExprUnary(hir::UnDeref, ref ptr) => self.check_arg(ptr), + _ => (), } hir::intravisit::walk_expr(self, expr); } } + +impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { + fn check_arg(&self, ptr: &hir::Expr) { + if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) { + if self.ptrs.contains(&def.def_id()) { + span_lint(self.cx, + NOT_UNSAFE_PTR_ARG_DEREF, + ptr.span, + "this public function dereferences a raw pointer but is not marked `unsafe`"); + } + } + } +} diff --git a/tests/compile-fail/functions.rs b/tests/compile-fail/functions.rs index 311da1ed2fe..f7ee41d2816 100644 --- a/tests/compile-fail/functions.rs +++ b/tests/compile-fail/functions.rs @@ -36,6 +36,10 @@ impl Foo for Bar { fn ptr(p: *const u8) { println!("{}", unsafe { *p }); //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + println!("{:?}", unsafe { p.as_ref() }); + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + unsafe { std::ptr::read(p) }; + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` } } @@ -50,6 +54,8 @@ pub fn public(p: *const u8) { //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` println!("{:?}", unsafe { p.as_ref() }); //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + unsafe { std::ptr::read(p) }; + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` } impl Bar { @@ -62,6 +68,8 @@ impl Bar { //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` println!("{:?}", unsafe { p.as_ref() }); //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` + unsafe { std::ptr::read(p) }; + //~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe` } pub fn public_ok(self, p: *const u8) { -- cgit 1.4.1-3-g733a5 From 31948c481524247ddfe3dd600c51b0f501891414 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 3 Jul 2016 13:55:23 +0530 Subject: Make #991 work with current rust --- clippy_lints/src/functions.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index a1918aed69f..0dec4e94c0b 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -131,7 +131,7 @@ impl Functions { fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> { if let (&hir::PatKind::Binding(_, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) { - cx.tcx.def_map.borrow().get(&arg.pat.id).map(hir::def::PathResolution::def_id) + cx.tcx.def_map.borrow().get(&arg.pat.id).map(|pr| pr.full_def().def_id()) } else { None } @@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr) { if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) { - if self.ptrs.contains(&def.def_id()) { + if self.ptrs.contains(&def.full_def().def_id()) { span_lint(self.cx, NOT_UNSAFE_PTR_ARG_DEREF, ptr.span, -- cgit 1.4.1-3-g733a5 From 10b545e30b18216d536fd4799da65589e499b588 Mon Sep 17 00:00:00 2001 From: James Lucas <LucasJ94@hotmail.co.uk> Date: Sun, 3 Jul 2016 12:12:43 -0700 Subject: Check for constant expression in useless_vec lint --- clippy_lints/src/vec.rs | 10 +++++++++- tests/compile-fail/vec.rs | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 73f2fb7caa8..a6289837d4e 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,6 +1,8 @@ use rustc::lint::*; use rustc::ty::TypeVariants; use rustc::hir::*; +use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::eval_const_expr_partial; use syntax::codemap::Span; use syntax::ptr::P; use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; @@ -52,9 +54,15 @@ impl LateLintPass for Pass { fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { if let Some(vec_args) = unexpand(cx, vec) { + let snippet = match vec_args { Args::Repeat(elem, len) => { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + // Check that the length is a constant expression + if eval_const_expr_partial(cx.tcx, len, ExprTypeChecked, None).is_ok() { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } else { + return; + } } Args::Vec(args) => { if let Some(last) = args.iter().last() { diff --git a/tests/compile-fail/vec.rs b/tests/compile-fail/vec.rs index eda75a2fe8a..92c99c20e36 100644 --- a/tests/compile-fail/vec.rs +++ b/tests/compile-fail/vec.rs @@ -7,6 +7,16 @@ fn on_slice(_: &[u8]) {} #[allow(ptr_arg)] fn on_vec(_: &Vec<u8>) {} +struct Line { + length: usize, +} + +impl Line { + fn length(&self) -> usize { + self.length + } +} + fn main() { on_slice(&vec![]); //~^ ERROR useless use of `vec!` @@ -42,6 +52,12 @@ fn main() { on_vec(&vec![1, 2]); on_vec(&vec![1; 2]); + // Now with non-constant expressions + let line = Line { length: 2 }; + + on_slice(&vec![2; line.length]); + on_slice(&vec![2; line.length()]); + for a in vec![1, 2, 3] { //~^ ERROR useless use of `vec!` //~| HELP you can use -- cgit 1.4.1-3-g733a5 From ffa840d4f2bbe31721b40d56093259c4a5c0b50b Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jul 2016 19:13:01 +0200 Subject: Use `utils::sugg` in `match` related lints Also don't build suggestion when unnecessary. --- clippy_lints/src/matches.rs | 114 ++++++++++++++++++++--------------------- clippy_lints/src/utils/sugg.rs | 5 ++ tests/compile-fail/matches.rs | 12 ++--- 3 files changed, 67 insertions(+), 64 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 94b36d28ed3..de21cabc6fb 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -235,57 +235,54 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tcx.expr_ty(ex).sty == ty::TyBool { - let sugg = if arms.len() == 2 && arms[0].pats.len() == 1 { - // no guards - let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { - if let ExprLit(ref lit) = arm_bool.node { - match lit.node { - LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), - LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), - _ => None, + span_lint_and_then(cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression", + move |db| { + if arms.len() == 2 && arms[0].pats.len() == 1 { + // no guards + let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { + if let ExprLit(ref lit) = arm_bool.node { + match lit.node { + LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), + _ => None, + } + } else { + None } } else { None - } - } else { - None - }; - - if let Some((ref true_expr, ref false_expr)) = exprs { - match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => { - Some(format!("if {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))) + }; + + if let Some((ref true_expr, ref false_expr)) = exprs { + let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { + (false, false) => { + Some(format!("if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, ".."))) + } + (false, true) => { + Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) + } + (true, false) => { + let test = Sugg::hir(cx, ex, ".."); + Some(format!("if {} {}", + !test, + expr_block(cx, false_expr, None, ".."))) + } + (true, true) => None, + }; + + if let Some(sugg) = sugg { + db.span_suggestion(expr.span, "consider using an if/else expression", sugg); } - (false, true) => { - Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) - } - (true, false) => { - let test = Sugg::hir(cx, ex, ".."); - Some(format!("if {} {}", - !test, - expr_block(cx, false_expr, None, ".."))) - } - (true, true) => None, } - } else { - None } - } else { - None - }; - span_lint_and_then(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression. Consider using an if..else block:", - move |db| { - if let Some(sugg) = sugg { - db.span_suggestion(expr.span, "try this", sugg); - } - }); + }); } } @@ -309,26 +306,28 @@ fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - let template = match_template(cx, expr.span, source, "", inner); span_lint_and_then(cx, MATCH_REF_PATS, expr.span, "you don't need to add `&` to both the expression and the patterns", |db| { - db.span_suggestion(expr.span, "try", template); - }); + let inner = Sugg::hir(cx, inner, ".."); + let template = match_template(expr.span, source, inner); + db.span_suggestion(expr.span, "try", template); + }); } else { - let template = match_template(cx, expr.span, source, "*", ex); span_lint_and_then(cx, MATCH_REF_PATS, expr.span, "you don't need to add `&` to all patterns", |db| { - db.span_suggestion(expr.span, - "instead of prefixing all patterns with `&`, you can \ - dereference the expression", - template); - }); + let ex = Sugg::hir(cx, ex, ".."); + let template = match_template(expr.span, source, ex.deref()); + db.span_suggestion(expr.span, + "instead of prefixing all patterns with `&`, you can \ + dereference the expression", + template); + }); } } } @@ -411,12 +410,11 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { mapped.map_or(false, |v| v.iter().any(|el| *el)) } -fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, expr: &Expr) -> String { - let expr_snippet = snippet(cx, expr.span, ".."); +fn match_template(span: Span, source: MatchSource, expr: Sugg) -> String { match source { - MatchSource::Normal => format!("match {}{} {{ .. }}", op, expr_snippet), - MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), - MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), + MatchSource::Normal => format!("match {} {{ .. }}", expr), + MatchSource::IfLetDesugar { .. } => format!("if let .. = {} {{ .. }}", expr), + MatchSource::WhileLetDesugar => format!("while let .. = {} {{ .. }}", expr), MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"), } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index bbfa8648c53..f857c821e7b 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -134,6 +134,11 @@ impl<'a> Sugg<'a> { make_unop("&mut ", self) } + /// Convenience method to create the `*<expr>` suggestion. + pub fn deref(self) -> Sugg<'static> { + make_unop("*", self) + } + /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion. pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index e49aeaa6ec8..f64cceb5c34 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -112,7 +112,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if test { 0 } else { 42 }; true => 0, false => 42, @@ -121,7 +121,7 @@ fn match_bool() { let option = 1; match option == 1 { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if option == 1 { 1 } else { 0 }; true => 1, false => 0, @@ -129,7 +129,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if !test { println!("Noooo!"); }; true => (), false => { println!("Noooo!"); } @@ -137,7 +137,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if !test { println!("Noooo!"); }; false => { println!("Noooo!"); } _ => (), @@ -145,7 +145,7 @@ fn match_bool() { match test && test { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if !(test && test) { println!("Noooo!"); }; //~| ERROR equal expressions as operands false => { println!("Noooo!"); } @@ -154,7 +154,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression - //~| HELP try + //~| HELP consider //~| SUGGESTION if test { println!("Yes!"); } else { println!("Noooo!"); }; false => { println!("Noooo!"); } true => { println!("Yes!"); } -- cgit 1.4.1-3-g733a5 From 2f259b8cd345988090c401f551001dfc63ccfd2d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 3 Jul 2016 19:24:44 +0200 Subject: Use `span_suggestion` in entry lints --- clippy_lints/src/entry.rs | 8 ++++---- tests/compile-fail/entry.rs | 34 ++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index bc209fd4846..c7afc2d5cd9 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -121,21 +121,21 @@ impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> { SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) ], { span_lint_and_then(self.cx, MAP_ENTRY, self.span, - &format!("usage of `contains_key` followed by `insert` on `{}`", self.ty), |db| { + &format!("usage of `contains_key` followed by `insert` on a `{}`", self.ty), |db| { if self.sole_expr { let help = format!("{}.entry({}).or_insert({})", snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, ".."), snippet(self.cx, params[2].span, "..")); - db.span_suggestion(self.span, "Consider using", help); + db.span_suggestion(self.span, "consider using", help); } else { - let help = format!("Consider using `{}.entry({})`", + let help = format!("{}.entry({})", snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, "..")); - db.span_note(self.span, &help); + db.span_suggestion(self.span, "consider using", help); } }); }} diff --git a/tests/compile-fail/entry.rs b/tests/compile-fail/entry.rs index 7dc4054ec5b..ec3b75abb37 100755 --- a/tests/compile-fail/entry.rs +++ b/tests/compile-fail/entry.rs @@ -11,45 +11,51 @@ fn foo() {} fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v); } - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| HELP Consider + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider //~| SUGGESTION m.entry(k).or_insert(v) } fn insert_if_absent1<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v); } - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { m.insert(k, v) } else { None }; - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_if_present2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if m.contains_key(&k) { None } else { m.insert(k, v) }; - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_if_present3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; - //~^ ERROR usage of `contains_key` followed by `insert` on `HashMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `HashMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_in_btreemap<K: Ord, V>(m: &mut BTreeMap<K, V>, k: K, v: V) { if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - //~^ ERROR usage of `contains_key` followed by `insert` on `BTreeMap` - //~| NOTE Consider using `m.entry(k)` + //~^ ERROR usage of `contains_key` followed by `insert` on a `BTreeMap` + //~| HELP consider + //~| SUGGESTION m.entry(k) } fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { -- cgit 1.4.1-3-g733a5 From 9b79b1022c68b79dbcdf2e51d46843c6e801d1f7 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 4 Jul 2016 01:17:31 +0200 Subject: Fix suggestions for `needless_bool` --- clippy_lints/src/needless_bool.rs | 36 +++++++++++++++++++++++------------- tests/compile-fail/needless_bool.rs | 31 +++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 5f912366770..fa2a350c36f 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,7 +6,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; -use utils::{span_lint, span_lint_and_then, snippet, snippet_opt}; +use utils::{span_lint, span_lint_and_then, snippet}; +use utils::sugg::Sugg; /// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. /// @@ -49,11 +50,20 @@ impl LateLintPass for NeedlessBool { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { use self::Expression::*; if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { - let reduce = |hint: &str, not| { - let hint = match snippet_opt(cx, pred.span) { - Some(pred_snip) => format!("`{}{}`", not, pred_snip), - None => hint.into(), + let reduce = |ret, not| { + let snip = Sugg::hir(cx, pred, "<predicate>"); + let snip = if not { + !snip + } else { + snip + }; + + let hint = if ret { + format!("return {};", snip) + } else { + snip.to_string() }; + span_lint_and_then(cx, NEEDLESS_BOOL, e.span, @@ -77,10 +87,10 @@ impl LateLintPass for NeedlessBool { e.span, "this if-then-else expression will always return false"); } - (RetBool(true), RetBool(false)) => reduce("its predicate", "return "), - (Bool(true), Bool(false)) => reduce("its predicate", ""), - (RetBool(false), RetBool(true)) => reduce("`!` and its predicate", "return !"), - (Bool(false), Bool(true)) => reduce("`!` and its predicate", "!"), + (RetBool(true), RetBool(false)) => reduce(true, false), + (Bool(true), Bool(false)) => reduce(false, false), + (RetBool(false), RetBool(true)) => reduce(true, true), + (Bool(false), Bool(true)) => reduce(false, true), _ => (), } } @@ -122,23 +132,23 @@ impl LateLintPass for BoolComparison { }); } (Bool(false), Other) => { - let hint = format!("!{}", snippet(cx, right_side.span, "..")); + let hint = Sugg::hir(cx, right_side, ".."); span_lint_and_then(cx, BOOL_COMPARISON, e.span, "equality checks against false can be replaced by a negation", |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", (!hint).to_string()); }); } (Other, Bool(false)) => { - let hint = format!("!{}", snippet(cx, left_side.span, "..")); + let hint = Sugg::hir(cx, left_side, ".."); span_lint_and_then(cx, BOOL_COMPARISON, e.span, "equality checks against false can be replaced by a negation", |db| { - db.span_suggestion(e.span, "try simplifying it as shown:", hint); + db.span_suggestion(e.span, "try simplifying it as shown:", (!hint).to_string()); }); } _ => (), diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs index 480c16f1666..fb81d44308a 100644 --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -5,21 +5,28 @@ #[allow(if_same_then_else)] fn main() { let x = true; + let y = false; if x { true } else { true }; //~ERROR this if-then-else expression will always return true if x { false } else { false }; //~ERROR this if-then-else expression will always return false if x { true } else { false }; //~^ ERROR this if-then-else expression returns a bool literal //~| HELP you can reduce it to - //~| SUGGESTION `x` + //~| SUGGESTION x if x { false } else { true }; //~^ ERROR this if-then-else expression returns a bool literal //~| HELP you can reduce it to - //~| SUGGESTION `!x` + //~| SUGGESTION !x + if x && y { false } else { true }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION !(x && y) if x { x } else { false }; // would also be questionable, but we don't catch this yet bool_ret(x); bool_ret2(x); bool_ret3(x); + bool_ret5(x, x); bool_ret4(x); + bool_ret6(x, x); } #[allow(if_same_then_else, needless_return)] @@ -39,7 +46,15 @@ fn bool_ret3(x: bool) -> bool { if x { return true } else { return false }; //~^ ERROR this if-then-else expression returns a bool literal //~| HELP you can reduce it to - //~| SUGGESTION `return x` + //~| SUGGESTION return x +} + +#[allow(needless_return)] +fn bool_ret5(x: bool, y: bool) -> bool { + if x && y { return true } else { return false }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION return x && y } #[allow(needless_return)] @@ -47,5 +62,13 @@ fn bool_ret4(x: bool) -> bool { if x { return false } else { return true }; //~^ ERROR this if-then-else expression returns a bool literal //~| HELP you can reduce it to - //~| SUGGESTION `return !x` + //~| SUGGESTION return !x +} + +#[allow(needless_return)] +fn bool_ret6(x: bool, y: bool) -> bool { + if x && y { return false } else { return true }; + //~^ ERROR this if-then-else expression returns a bool literal + //~| HELP you can reduce it to + //~| SUGGESTION return !(x && y) } -- cgit 1.4.1-3-g733a5 From c5e91e70d03ace2c9647e509540a5b6b88aaf801 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Mon, 4 Jul 2016 02:22:57 +0200 Subject: Use `sugg::Sugg` in transmute links --- clippy_lints/src/transmute.rs | 22 +++++++++++----------- clippy_lints/src/utils/sugg.rs | 6 ++++++ tests/compile-fail/transmute.rs | 7 +++++++ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index d95fad8fc0f..88ed11d26e5 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; +use utils::{match_def_path, paths, span_lint, span_lint_and_then}; use utils::sugg; /// **What it does:** This lint checks for transmutes that can't ever be correct on any architecture @@ -93,14 +93,14 @@ impl LateLintPass for Transmute { e.span, "transmute from a reference to a pointer", |db| { - if let Some(arg) = snippet_opt(cx, args[0].span) { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &*args[0]) { let sugg = if ptr_ty == rty { - format!("{} as {}", arg, to_ty) + arg.as_ty(&to_ty.to_string()) } else { - format!("{} as {} as {}", arg, cx.tcx.mk_ptr(rty), to_ty) + arg.as_ty(&format!("{} as {}", cx.tcx.mk_ptr(rty), to_ty)) }; - db.span_suggestion(e.span, "try", sugg); + db.span_suggestion(e.span, "try", sugg.to_string()); } }, ), @@ -111,8 +111,8 @@ impl LateLintPass for Transmute { e.span, "transmute from an integer to a pointer", |db| { - if let Some(arg) = snippet_opt(cx, args[0].span) { - db.span_suggestion(e.span, "try", format!("{} as {}", arg, to_ty)); + if let Some(arg) = sugg::Sugg::hir_opt(cx, &*args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); } }, ), @@ -157,13 +157,13 @@ impl LateLintPass for Transmute { }; - let sugg = if from_pty.ty == to_rty.ty { - sugg::make_unop(deref, arg).to_string() + let arg = if from_pty.ty == to_rty.ty { + arg } else { - format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) + arg.as_ty(&format!("{} {}", cast, to_rty.ty)) }; - db.span_suggestion(e.span, "try", sugg); + db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); }, ), _ => return, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index f857c821e7b..4a9543d47c1 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -30,6 +30,7 @@ impl<'a> std::fmt::Display for Sugg<'a> { } } +#[allow(wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { pub fn hir_opt(cx: &LateContext, expr: &hir::Expr) -> Option<Sugg<'a>> { snippet_opt(cx, expr.span).map(|snippet| { @@ -124,6 +125,11 @@ impl<'a> Sugg<'a> { make_binop(ast::BinOpKind::And, &self, &rhs) } + /// Convenience method to create the `<lhs> as <rhs>` suggestion. + pub fn as_ty(self, rhs: &str) -> Sugg<'static> { + make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.into())) + } + /// Convenience method to create the `&<expr>` suggestion. pub fn addr(self) -> Sugg<'static> { make_unop("&", self) diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 0dbd58b1308..1344858996e 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -111,6 +111,13 @@ fn useless() { //~^ ERROR transmute from an integer to a pointer //~| HELP try //~| SUGGESTION 5_isize as *const usize + let _ = 5_isize as *const usize; + + let _: *const usize = std::mem::transmute(1+1usize); + //~^ ERROR transmute from an integer to a pointer + //~| HELP try + //~| SUGGESTION (1+1usize) as *const usize + let _ = (1+1_usize) as *const usize; } } -- cgit 1.4.1-3-g733a5 From 871f8dcab3ef4ed2a5e65f531afc7b6bd5762cba Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> Date: Mon, 4 Jul 2016 13:33:48 +0200 Subject: don't run clippy on dependencies when running cargo clippy --- src/main.rs | 100 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/src/main.rs b/src/main.rs index c4ad6d66177..9541e70ecc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,17 +18,17 @@ use std::process::Command; use clippy_lints::utils::cargo; -struct ClippyCompilerCalls(RustcDefaultCalls); - -impl std::default::Default for ClippyCompilerCalls { - fn default() -> Self { - Self::new() - } +struct ClippyCompilerCalls { + default: RustcDefaultCalls, + run_lints: bool, } impl ClippyCompilerCalls { - fn new() -> Self { - ClippyCompilerCalls(RustcDefaultCalls) + fn new(run_lints: bool) -> Self { + ClippyCompilerCalls { + default: RustcDefaultCalls, + run_lints: run_lints, + } } } @@ -39,7 +39,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType) -> Compilation { - self.0.early_callback(matches, sopts, descriptions, output) + self.default.early_callback(matches, sopts, descriptions, output) } fn no_input(&mut self, matches: &getopts::Matches, @@ -48,7 +48,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option<PathBuf>, descriptions: &rustc_errors::registry::Registry) -> Option<(Input, Option<PathBuf>)> { - self.0.no_input(matches, sopts, odir, ofile, descriptions) + self.default.no_input(matches, sopts, odir, ofile, descriptions) } fn late_callback(&mut self, matches: &getopts::Matches, @@ -57,44 +57,46 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { odir: &Option<PathBuf>, ofile: &Option<PathBuf>) -> Compilation { - self.0.late_callback(matches, sess, input, odir, ofile) + self.default.late_callback(matches, sess, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut control = self.0.build_controller(sess, matches); - - let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); - control.after_parse.callback = Box::new(move |state| { - { - let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed")); - registry.args_hidden = Some(Vec::new()); - clippy_lints::register_plugins(&mut registry); - - let rustc_plugin::registry::Registry { early_lint_passes, - late_lint_passes, - lint_groups, - llvm_passes, - attributes, - mir_passes, - .. } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } + let mut control = self.default.build_controller(sess, matches); + + if self.run_lints { + let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); + control.after_parse.callback = Box::new(move |state| { + { + let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed")); + registry.args_hidden = Some(Vec::new()); + clippy_lints::register_plugins(&mut registry); + + let rustc_plugin::registry::Registry { early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + mir_passes, + .. } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); - } + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.mir_passes.borrow_mut().extend(mir_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - } - old(state); - }); + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.mir_passes.borrow_mut().extend(mir_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + } + old(state); + }); + } control } @@ -129,6 +131,7 @@ pub fn main() { }; if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { + // this arm is executed on the initial call to `cargo clippy` let manifest_path = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path=")); let mut metadata = cargo::metadata(manifest_path).expect("could not obtain cargo metadata"); assert_eq!(metadata.version, 1); @@ -149,12 +152,19 @@ pub fn main() { } } } else { + // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` env var set to itself + + // this conditional check for the --sysroot flag is there so users can call `cargo-clippy` directly + // without having to pass --sysroot or anything let args: Vec<String> = if env::args().any(|s| s == "--sysroot") { env::args().collect() } else { env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect() }; - let (result, _) = rustc_driver::run_compiler(&args, &mut ClippyCompilerCalls::new()); + // this check ensures that dependencies are built but not linted and the final crate is + // linted but not built + let mut ccc = ClippyCompilerCalls::new(env::args().any(|s| s == "-Zno-trans")); + let (result, _) = rustc_driver::run_compiler(&args, &mut ccc); if let Err(err_count) = result { if err_count > 0 { -- cgit 1.4.1-3-g733a5 From 8aaaf198e31678d5036eae5acd32e71a208df828 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Tue, 5 Jul 2016 23:26:47 +0200 Subject: Use `utils::sugg` in methods lints --- clippy_lints/src/methods.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9d5c436c2cb..f70ec4eac9f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -11,10 +11,11 @@ use std::fmt; use syntax::codemap::Span; use syntax::ptr::P; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, snippet, snippet_opt, span_lint, + match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::MethodArgs; use utils::paths; +use utils::sugg; #[derive(Clone)] pub struct Pass; @@ -628,8 +629,8 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty expr.span, "using `clone` on a double-reference; \ this will copy the reference instead of cloning the inner type", - |db| if let Some(snip) = snippet_opt(cx, arg.span) { - db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip)); + |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { + db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref())); }); } } @@ -641,14 +642,13 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) { return; } let arg_ty = cx.tcx.expr_ty(&args[1]); - if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) { + if let Some(slice) = derefs_to_slice(cx, &args[1], &arg_ty) { span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| { db.span_suggestion(expr.span, "try this", - format!("{}.extend_from_slice({}{})", + format!("{}.extend_from_slice({})", snippet(cx, args[0].span, "_"), - r, - snippet(cx, span, "_"))); + slice)); }); } } @@ -695,7 +695,7 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_ ); } -fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { +fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<sugg::Sugg<'static>> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty { ty::TySlice(_) => true, @@ -706,19 +706,22 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(S _ => false, } } + if let hir::ExprMethodCall(name, _, ref args) = expr.node { if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) { - Some((args[0].span, "&")) + sugg::Sugg::hir_opt(cx, &*args[0]).map(|sugg| { + sugg.addr() + }) } else { None } } else { match ty.sty { - ty::TySlice(_) => Some((expr.span, "")), + ty::TySlice(_) => sugg::Sugg::hir_opt(cx, expr), ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) | ty::TyBox(ref inner) => { if may_slice(cx, inner) { - Some((expr.span, "")) + sugg::Sugg::hir_opt(cx, expr) } else { None } -- cgit 1.4.1-3-g733a5 From ded5b30f2379fd564f07a4d08d2c1a8c970cd1cd Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 6 Jul 2016 14:38:48 +0200 Subject: Mention the major sugg. refactoring in CHANGELOG --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae316a90b05..e0ea031c73f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.78 - 2016-07-02 +## 0.0.79 — ? +* Major suggestions refactoring + +## 0.0.78 — 2016-07-02 * Rustup to *rustc 1.11.0-nightly (01411937f 2016-07-01)* * New lints: [`wrong_transmute`, `double_neg`] * For compatibility, `cargo clippy` does not defines the `clippy` feature -- cgit 1.4.1-3-g733a5 From 3bd0acaa5c75474a58e04411d3a71b5398b3c6df Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 6 Jul 2016 14:51:20 +0200 Subject: Remove useless feature attribute `iter_arith` has been stabilized in rustc 1.11.0. --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5ba52374135..4238ab6f122 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -3,7 +3,6 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(custom_attribute)] -#![feature(iter_arith)] #![feature(question_mark)] #![feature(rustc_private)] #![feature(slice_patterns)] -- cgit 1.4.1-3-g733a5 From bf513229b1be77aca80199d7220257548dff32c8 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Wed, 6 Jul 2016 15:36:42 +0200 Subject: Address PR's comments --- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/transmute.rs | 4 ++-- clippy_lints/src/utils/sugg.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index fa2a350c36f..c3e2a0e6167 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -59,7 +59,7 @@ impl LateLintPass for NeedlessBool { }; let hint = if ret { - format!("return {};", snip) + format!("return {}", snip) } else { snip.to_string() }; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 88ed11d26e5..ba4da0e8f65 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -95,9 +95,9 @@ impl LateLintPass for Transmute { |db| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &*args[0]) { let sugg = if ptr_ty == rty { - arg.as_ty(&to_ty.to_string()) + arg.as_ty(to_ty) } else { - arg.as_ty(&format!("{} as {}", cx.tcx.mk_ptr(rty), to_ty)) + arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) }; db.span_suggestion(e.span, "try", sugg.to_string()); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4a9543d47c1..624c030cdd4 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -126,8 +126,8 @@ impl<'a> Sugg<'a> { } /// Convenience method to create the `<lhs> as <rhs>` suggestion. - pub fn as_ty(self, rhs: &str) -> Sugg<'static> { - make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.into())) + pub fn as_ty<R: std::fmt::Display>(self, rhs: R) -> Sugg<'static> { + make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into())) } /// Convenience method to create the `&<expr>` suggestion. -- cgit 1.4.1-3-g733a5 From 33c767c510e6d0273a725c5ab98e09b3094a6d9b Mon Sep 17 00:00:00 2001 From: David Tolnay <dtolnay@gmail.com> Date: Wed, 6 Jul 2016 21:27:29 -0700 Subject: Add "JavaScript" to doc-valid-idents --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 323c6536496..6f2bf158521 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -151,7 +151,7 @@ define_Conf! { /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks - ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub", "NaN", "GPLv2", "GPLv3"] => Vec<String>), + ("doc-valid-idents", doc_valid_idents, ["MiB", "GiB", "TiB", "PiB", "EiB", "GitHub", "NaN", "GPLv2", "GPLv3", "JavaScript"] => Vec<String>), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have ("too-many-arguments-threshold", too_many_arguments_threshold, 7 => u64), /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have -- cgit 1.4.1-3-g733a5 From b71b1a078cc8fdd13eecc2f623c1cb63794cc558 Mon Sep 17 00:00:00 2001 From: Alberto Leal <dashed@users.noreply.github.com> Date: Thu, 7 Jul 2016 20:36:49 -0400 Subject: Add note on how to enable the optional dependency --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3159a3e8979..db3eca865eb 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,8 @@ And, in your `main.rs` or `lib.rs`: #![cfg_attr(feature="clippy", plugin(clippy))] ``` +Then build by enabling the feature: `cargo build --features "clippy"` + Instead of adding the `cfg_attr` attributes you can also run clippy on demand: `cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` (the `-Z no trans`, while not neccessary, will stop the compilation process after -- cgit 1.4.1-3-g733a5 From 56d3bc70080ec9ae4fca650df8708d0aae410f41 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Fri, 8 Jul 2016 18:18:45 +0200 Subject: Handle `/**` and `~~~` in `DOC_MARKDOWN` --- clippy_lints/src/doc.rs | 126 +++++++++++++++++++++++++++++++++++++++------- tests/compile-fail/doc.rs | 50 +++++++++++++++++- 2 files changed, 156 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 4306204e527..92fcd804d5f 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -50,25 +50,50 @@ impl EarlyLintPass for Doc { } } +/// Cleanup documentation decoration (`///` and such). +/// +/// We can't use `syntax::attr::AttributeMethods::with_desugared_doc` or +/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we need to keep track of +/// the span but this function is inspired from the later. +#[allow(cast_possible_truncation)] +pub fn strip_doc_comment_decoration((comment, span): (&str, Span)) -> Vec<(&str, Span)> { + // one-line comments lose their prefix + const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; + for prefix in ONELINERS { + if comment.starts_with(*prefix) { + return vec![( + &comment[prefix.len()..], + Span { lo: span.lo + BytePos(prefix.len() as u32), ..span } + )]; + } + } + + if comment.starts_with("/*") { + return comment[3..comment.len() - 2].lines().map(|line| { + let offset = line.as_ptr() as usize - comment.as_ptr() as usize; + debug_assert_eq!(offset as u32 as usize, offset); + + ( + line, + Span { + lo: span.lo + BytePos(offset as u32), + ..span + } + ) + }).collect(); + } + + panic!("not a doc-comment: {}", comment); +} + pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { let mut docs = vec![]; - let mut in_multiline = false; for attr in attrs { if attr.node.is_sugared_doc { if let ast::MetaItemKind::NameValue(_, ref doc) = attr.node.value.node { if let ast::LitKind::Str(ref doc, _) = doc.node { - // doc comments start with `///` or `//!` - let real_doc = &doc[3..]; - let mut span = attr.span; - span.lo = span.lo + BytePos(3); - - // check for multiline code blocks - if real_doc.trim_left().starts_with("```") { - in_multiline = !in_multiline; - } else if !in_multiline { - docs.push((real_doc, span)); - } + docs.extend_from_slice(&strip_doc_comment_decoration((doc, attr.span))); } } } @@ -135,11 +160,11 @@ fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) } #[allow(while_let_on_iterator)] // borrowck complains about for - fn jump_to(&mut self, n: char) -> Result<(), ()> { - while let Some((_, c)) = self.next() { + fn jump_to(&mut self, n: char) -> Result<bool, ()> { + while let Some((new_line, c)) = self.next() { if c == n { self.advance_begin(); - return Ok(()); + return Ok(new_line); } } @@ -217,6 +242,54 @@ fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) pos: 0, }; + /// Check for fanced code block. + macro_rules! check_block { + ($parser:expr, $c:tt, $new_line:expr) => {{ + check_block!($parser, $c, $c, $new_line) + }}; + + ($parser:expr, $c:pat, $c_expr:expr, $new_line:expr) => {{ + fn check_block(parser: &mut Parser, new_line: bool) -> Result<bool, ()> { + if new_line { + let mut lookup_parser = parser.clone(); + if let (Some((false, $c)), Some((false, $c))) = (lookup_parser.next(), lookup_parser.next()) { + *parser = lookup_parser; + // 3 or more ` or ~ open a code block to be closed with the same number of ` or ~ + let mut open_count = 3; + while let Some((false, $c)) = parser.next() { + open_count += 1; + } + + loop { + loop { + if try!(parser.jump_to($c_expr)) { + break; + } + } + + lookup_parser = parser.clone(); + if let (Some((false, $c)), Some((false, $c))) = (lookup_parser.next(), lookup_parser.next()) { + let mut close_count = 3; + while let Some((false, $c)) = lookup_parser.next() { + close_count += 1; + } + + if close_count == open_count { + *parser = lookup_parser; + return Ok(true); + } + } + } + } + } + + Ok(false) + } + + check_block(&mut $parser, $new_line) + }}; + } + loop { match parser.next() { Some((new_line, c)) => { @@ -225,7 +298,20 @@ fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) parser.next_line(); } '`' => { - try!(parser.jump_to('`')); + if try!(check_block!(parser, '`', new_line)) { + continue; + } + + try!(parser.jump_to('`')); // not a code block, just inline code + } + '~' => { + if try!(check_block!(parser, '~', new_line)) { + continue; + } + + // ~ does not introduce inline code, but two of them introduce + // strikethrough. Too bad for the consistency but we don't care about + // strikethrough. } '[' => { // Check for a reference definition `[foo]:` at the beginning of a line @@ -249,8 +335,12 @@ fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) parser.link = false; match parser.peek() { - Some('(') => try!(parser.jump_to(')')), - Some('[') => try!(parser.jump_to(']')), + Some('(') => { + try!(parser.jump_to(')')); + } + Some('[') => { + try!(parser.jump_to(']')); + } Some(_) => continue, None => return Err(()), } diff --git a/tests/compile-fail/doc.rs b/tests/compile-fail/doc.rs index 415bcb2e661..84283a8316e 100755 --- a/tests/compile-fail/doc.rs +++ b/tests/compile-fail/doc.rs @@ -14,6 +14,8 @@ /// which should be reported only once despite being __doubly bad__. /// Here be ::is::a::global:path. //~^ ERROR: you should put `is::a::global:path` between ticks +/// That's not code ~NotInCodeBlock~. +//~^ ERROR: you should put `NotInCodeBlock` between ticks /// be_sure_we_got_to_the_end_of_it //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn foo_bar() { @@ -24,9 +26,14 @@ fn foo_bar() { /// foo_bar FOO_BAR /// _foo bar_ /// ``` +/// +/// ~~~rust +/// foo_bar FOO_BAR +/// _foo bar_ +/// ~~~ /// be_sure_we_got_to_the_end_of_it //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks -fn multiline_ticks() { +fn multiline_codeblock() { } /// This _is a test for @@ -106,7 +113,7 @@ fn test_unicode() { //~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks fn main() { foo_bar(); - multiline_ticks(); + multiline_codeblock(); test_emphasis(); test_units(); } @@ -151,3 +158,42 @@ fn issue883() { /// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html) fn multiline() { } + +/** E.g. serialization of an empty list: FooBar +``` +That's in a code block: `PackedNode` +``` + +And BarQuz too. +be_sure_we_got_to_the_end_of_it +*/ +//~^^^^^^^^ ERROR: you should put `FooBar` between ticks +//~^^^^ ERROR: you should put `BarQuz` between ticks +//~^^^^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn issue1073() { +} + +/** E.g. serialization of an empty list: FooBar +``` +That's in a code block: PackedNode +``` + +And BarQuz too. +be_sure_we_got_to_the_end_of_it +*/ +//~^^^^^^^^ ERROR: you should put `FooBar` between ticks +//~^^^^ ERROR: you should put `BarQuz` between ticks +//~^^^^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn issue1073_alt() { +} + +/// Test more than three quotes: +/// ```` +/// DoNotWarn +/// ``` +/// StillDont +/// ```` +/// be_sure_we_got_to_the_end_of_it +//~^ ERROR: you should put `be_sure_we_got_to_the_end_of_it` between ticks +fn four_quotes() { +} -- cgit 1.4.1-3-g733a5 From 585a3b2565669d50a379625269da5e6c60ab8633 Mon Sep 17 00:00:00 2001 From: Martin Pool <mbp@sourcefrog.net> Date: Sat, 9 Jul 2016 12:20:54 -0700 Subject: Fix Markdown syntax in description of collapsible_if --- README.md | 2 +- clippy_lints/src/collapsible_if.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db3eca865eb..48e311fa758 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ name [clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type [cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended) [cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to `else if` +[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }` and an `else { if .. }` expression can be collapsed to `else if` [crosspointer_transmute](https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute) | warn | transmutes that have to or from types that are a pointer to the other [cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | finds functions that should be split up into multiple functions [deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | `Warn` on `#[deprecated(since = "x")]` where x is not semver diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 57252037270..148f5ccc560 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -32,7 +32,8 @@ declare_lint! { pub COLLAPSIBLE_IF, Warn, "two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` \ - can be written as `if x && y { foo() }` and an `else { if .. } expression can be collapsed to \ + can be written as `if x && y { foo() }` \ + and an `else { if .. }` expression can be collapsed to \ `else if`" } -- cgit 1.4.1-3-g733a5 From 3a7402a6d20d308e6c09ffa0101aab108bc2cad7 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 14:05:57 +0200 Subject: Fix FP with `for` loops and shadowed loop variable --- clippy_lints/src/loops.rs | 7 ++++--- tests/compile-fail/for_loop.rs | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a4e338053e2..b87d1d3d5fd 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,6 +1,7 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; +use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl}; use rustc::hir::map::Node::NodeBlock; use rustc::lint::*; @@ -337,7 +338,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex if let PatKind::Binding(_, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, - var: ident.node, + var: cx.tcx.expect_def(pat.id).def_id(), indexed: HashMap::new(), nonindex: false, }; @@ -667,7 +668,7 @@ impl<'a> Visitor<'a> for UsedVisitor { struct VarVisitor<'v, 't: 'v> { cx: &'v LateContext<'v, 't>, // context reference - var: Name, // var name to look for as index + var: DefId, // var name to look for as index indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global nonindex: bool, // has the var been used otherwise? } @@ -675,7 +676,7 @@ struct VarVisitor<'v, 't: 'v> { impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { fn visit_expr(&mut self, expr: &'v Expr) { if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == self.var { + if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var { // we are referencing our variable! now check if it's as an index if_let_chain! {[ let Some(parexpr) = get_parent_expr(self.cx, expr), diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index bcb20be4ff4..91e31adc44d 100644 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -104,6 +104,12 @@ fn main() { println!("{}", vec[i]); } + for i in 0..vec.len() { + //~^ WARNING unused variable + let i = 42; // make a different `i` + println!("{}", vec[i]); // ok, not the `i` of the for-loop + } + for i in 0..vec.len() { let _ = vec[i]; } //~^ ERROR `i` is only used to index `vec` //~| HELP consider -- cgit 1.4.1-3-g733a5 From eb75d4ee6295fdb34a87b1b9eb5494e7eaf5712d Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 14:07:13 +0200 Subject: Fix suggestions for `NEW_WITHOUT_DEFAULT` --- clippy_lints/src/new_without_default.rs | 24 +++++--- clippy_lints/src/utils/sugg.rs | 95 +++++++++++++++++++++++++++++-- tests/compile-fail/new_without_default.rs | 22 ++++++- 3 files changed, 123 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 20c0d282bd8..053e423336e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -7,6 +7,7 @@ use syntax::ast; use syntax::codemap::Span; use utils::paths; use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; +use utils::sugg::DiagnosticBuilderExt; /// **What it does:** This lints about type with a `fn new() -> Self` method /// and no implementation of @@ -14,8 +15,7 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, sa /// /// **Why is this bad?** User might expect to be able to use /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) -/// as the type can be -/// constructed without arguments. +/// as the type can be constructed without arguments. /// /// **Known problems:** Hopefully none. /// @@ -118,8 +118,8 @@ impl LateLintPass for NewWithoutDefault { `Default` implementation for `{}`", self_ty), |db| { - db.span_suggestion(span, "try this", "#[derive(Default)]".into()); - }); + db.suggest_item_with_attr(cx, span, "try this", "#[derive(Default)]"); + }); } else { span_lint_and_then(cx, NEW_WITHOUT_DEFAULT, span, @@ -127,11 +127,17 @@ impl LateLintPass for NewWithoutDefault { `Default` implementation for `{}`", self_ty), |db| { - db.span_suggestion(span, - "try this", - format!("impl Default for {} {{ fn default() -> \ - Self {{ {}::new() }} }}", self_ty, self_ty)); - }); + db.suggest_prepend_item(cx, + span, + "try this", + &format!( +"impl Default for {} {{ + fn default() -> Self {{ + Self::new() + }} +}}", + self_ty)); + }); } }} } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 624c030cdd4..b6ed9071c0a 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -1,11 +1,14 @@ use rustc::hir; -use rustc::lint::{EarlyContext, LateContext}; +use rustc::lint::{EarlyContext, LateContext, LintContext}; +use rustc_errors; use std::borrow::Cow; +use std::fmt::Display; use std; -use syntax::ast; +use syntax::codemap::{CharPos, Span}; +use syntax::print::pprust::binop_to_string; use syntax::util::parser::AssocOp; +use syntax::ast; use utils::{higher, snippet, snippet_opt}; -use syntax::print::pprust::binop_to_string; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -20,7 +23,7 @@ pub enum Sugg<'a> { /// Literal constant `1`, for convenience. pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); -impl<'a> std::fmt::Display for Sugg<'a> { +impl<'a> Display for Sugg<'a> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match *self { Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) | Sugg::BinOp(_, ref s) => { @@ -126,7 +129,7 @@ impl<'a> Sugg<'a> { } /// Convenience method to create the `<lhs> as <rhs>` suggestion. - pub fn as_ty<R: std::fmt::Display>(self, rhs: R) -> Sugg<'static> { + pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> { make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into())) } @@ -198,7 +201,7 @@ impl<T> ParenHelper<T> { } } -impl<T: std::fmt::Display> std::fmt::Display for ParenHelper<T> { +impl<T: Display> Display for ParenHelper<T> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { if self.paren { write!(f, "({})", self.wrapped) @@ -354,3 +357,83 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"), }) } + +/// Return the indentation before `span` if there are nothing but `[ \t]` before it on its line. +fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { + let lo = cx.sess().codemap().lookup_char_pos(span.lo); + if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { + if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { + // we can mix char and byte positions here because we only consider `[ \t]` + if lo.col == CharPos(pos) { + Some(line[..pos].into()) + } else { + None + } + } else { + None + } + } else { + None + } +} + +pub trait DiagnosticBuilderExt<T: LintContext> { + /// Suggests to add an attribute to an item. + /// + /// Correctly handles indentation of the attribute and item. + /// + /// # Example + /// + /// ```rust + /// db.suggest_item_with_attr(cx, item, "#[derive(Default)]"); + /// ``` + fn suggest_item_with_attr<D: Display+?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D); + + /// Suggest to add an item before another. + /// + /// The item should not be indented (expect for inner indentation). + /// + /// # Example + /// + /// ```rust + /// db.suggest_prepend_item(cx, item, + /// "fn foo() { + /// bar(); + /// }"); + /// ``` + fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str); +} + +impl<'a, 'b, T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder<'b> { + fn suggest_item_with_attr<D: Display+?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D) { + if let Some(indent) = indentation(cx, item) { + let span = Span { + hi: item.lo, + ..item + }; + + self.span_suggestion(span, msg, format!("{}\n{}", attr, indent)); + } + } + + fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) { + if let Some(indent) = indentation(cx, item) { + let span = Span { + hi: item.lo, + ..item + }; + + let mut first = true; + let new_item = new_item.lines().map(|l| { + if first { + first = false; + format!("{}\n", l) + } else { + format!("{}{}\n", indent, l) + } + }).collect::<String>(); + + self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent)); + } + } +} diff --git a/tests/compile-fail/new_without_default.rs b/tests/compile-fail/new_without_default.rs index e3a8024dde1..cad675275db 100644 --- a/tests/compile-fail/new_without_default.rs +++ b/tests/compile-fail/new_without_default.rs @@ -7,13 +7,21 @@ pub struct Foo; impl Foo { - pub fn new() -> Foo { Foo } //~ERROR: you should consider deriving a `Default` implementation for `Foo` + pub fn new() -> Foo { Foo } + //~^ERROR: you should consider deriving a `Default` implementation for `Foo` + //~|HELP try this + //~^^^SUGGESTION #[derive(Default)] + //~^^^SUGGESTION pub fn new } pub struct Bar; impl Bar { - pub fn new() -> Self { Bar } //~ERROR: you should consider deriving a `Default` implementation for `Bar` + pub fn new() -> Self { Bar } + //~^ERROR: you should consider deriving a `Default` implementation for `Bar` + //~|HELP try this + //~^^^SUGGESTION #[derive(Default)] + //~^^^SUGGESTION pub fn new } pub struct Ok; @@ -61,7 +69,15 @@ pub struct LtKo<'a> { } impl<'c> LtKo<'c> { - pub fn new() -> LtKo<'c> { unimplemented!() } //~ERROR: you should consider adding a `Default` implementation for + pub fn new() -> LtKo<'c> { unimplemented!() } + //~^ERROR: you should consider adding a `Default` implementation for + //~^^HELP try + //~^^^SUGGESTION impl Default for LtKo<'c> { + //~^^^SUGGESTION fn default() -> Self { + //~^^^SUGGESTION Self::new() + //~^^^SUGGESTION } + //~^^^SUGGESTION } + // FIXME: that suggestion is missing lifetimes } struct Private; -- cgit 1.4.1-3-g733a5 From b8b6b7fee6ac094b5eda18c56cb3855c5ae1e948 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 14:46:39 +0200 Subject: Try to explain `MATCH_SAME_ARMS` better --- clippy_lints/src/copies.rs | 38 ++++++++++++++++++++++++++++++++++---- tests/compile-fail/copies.rs | 22 ++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 3022ffe730f..fc0d829172f 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -6,7 +6,7 @@ use std::collections::hash_map::Entry; use syntax::parse::token::InternedString; use syntax::util::small_vector::SmallVector; use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, span_note_and_lint}; +use utils::{get_parent_expr, in_macro, span_lint_and_then, span_note_and_lint, snippet}; /// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is /// `Warn` by default. @@ -52,6 +52,23 @@ declare_lint! { /// Baz => bar(), // <= oops /// } /// ``` +/// +/// This should probably be +/// ```rust,ignore +/// match foo { +/// Bar => bar(), +/// Quz => quz(), +/// Baz => baz(), // <= fixed +/// } +/// ``` +/// +/// or if the original code was not a typo: +/// ```rust,ignore +/// match foo { +/// Bar | Baz => bar(), // <= shows the intent better +/// Quz => quz(), +/// } +/// ``` declare_lint! { pub MATCH_SAME_ARMS, Warn, @@ -143,12 +160,25 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { if let Some((i, j)) = search_same(arms, hash, eq) { - span_note_and_lint(cx, + span_lint_and_then(cx, MATCH_SAME_ARMS, j.body.span, "this `match` has identical arm bodies", - i.body.span, - "same as this"); + |db| { + db.span_note(i.body.span, "same as this"); + + // Note: this does not use `span_suggestion` on purpose: there is no clean way to + // remove the other arm. Building a span and suggest to replace it to "" makes an + // even more confusing error message. Also in order not to make up a span for the + // whole pattern, the suggestion is only shown when there is only one pattern. The + // user should know about `|` if they are already using it… + + if i.pats.len() == 1 && j.pats.len() == 1 { + let lhs = snippet(cx, i.pats[0].span, "<pat1>"); + let rhs = snippet(cx, j.pats[0].span, "<pat2>"); + db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs)); + } + }); } } } diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 2fd8c766d92..a8d7157629b 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -21,6 +21,7 @@ struct Foo { #[deny(match_same_arms)] fn if_same_then_else() -> Result<&'static str, ()> { if true { + //~^NOTE same as this Foo { bar: 42 }; 0..10; ..; @@ -62,6 +63,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } let _ = if true { + //~^NOTE same as this foo(); 42 } @@ -75,6 +77,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } let _ = if true { + //~^NOTE same as this 42 } else { //~ERROR this `if` has identical blocks @@ -82,6 +85,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { }; if true { + //~^NOTE same as this let bar = if true { 42 } @@ -105,6 +109,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { + //~^NOTE same as this let _ = match 42 { 42 => 1, a if a > 0 => 2, @@ -125,6 +130,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { + //~^NOTE same as this if let Some(a) = Some(42) {} } else { //~ERROR this `if` has identical blocks @@ -132,6 +138,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { + //~^NOTE same as this if let (1, .., 3) = (1, 2, 3) {} } else { //~ERROR this `if` has identical blocks @@ -168,12 +175,16 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match 42 { 42 => foo(), + //~^NOTE same as this + //~|NOTE `42 | 51` 51 => foo(), //~ERROR this `match` has identical arm bodies _ => true, }; let _ = match Some(42) { Some(_) => 24, + //~^NOTE same as this + //~|NOTE `Some(_) | None` None => 24, //~ERROR this `match` has identical arm bodies }; @@ -196,18 +207,24 @@ fn if_same_then_else() -> Result<&'static str, ()> { match (Some(42), Some(42)) { (Some(a), None) => bar(a), + //~^NOTE same as this + //~|NOTE `(Some(a), None) | (None, Some(a))` (None, Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies _ => (), } match (Some(42), Some(42)) { (Some(a), ..) => bar(a), + //~^NOTE same as this + //~|NOTE `(Some(a), ..) | (.., Some(a))` (.., Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies _ => (), } match (1, 2, 3) { (1, .., 3) => 42, + //~^NOTE same as this + //~|NOTE `(1, .., 3) | (.., 3)` (.., 3) => 42, //~ERROR this `match` has identical arm bodies _ => 0, }; @@ -219,6 +236,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { + //~^NOTE same as this try!(Ok("foo")); } else { //~ERROR this `if` has identical blocks @@ -226,6 +244,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { + //~^NOTE same as this let foo = ""; return Ok(&foo[0..]); } @@ -246,16 +265,19 @@ fn ifs_same_cond() { let b = false; if b { + //~^NOTE same as this } else if b { //~ERROR this `if` has the same condition as a previous if } if a == 1 { + //~^NOTE same as this } else if a == 1 { //~ERROR this `if` has the same condition as a previous if } if 2*a == 1 { + //~^NOTE same as this } else if 2*a == 2 { } -- cgit 1.4.1-3-g733a5 From efaed2ecfe6f7236538755cd44a18175e118390f Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 14:53:42 +0200 Subject: Link to known issues for `MATCH_SAME_ARMS` --- clippy_lints/src/copies.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index fc0d829172f..504515be88c 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -42,7 +42,8 @@ declare_lint! { /// purpose, you can factor them /// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). /// -/// **Known problems:** Hopefully none. +/// **Known problems:** False positive possible with order dependent `match` +/// (see issue [#860](https://github.com/Manishearth/rust-clippy/issues/860)). /// /// **Example:** /// ```rust,ignore -- cgit 1.4.1-3-g733a5 From 3a201f43ec3ac295a2f21959524cc6cee662e09a Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 15:42:02 +0200 Subject: Rustup to rustc 1.12.0-nightly (f93aaf84c 2016-07-09) --- clippy_lints/src/copies.rs | 1 - clippy_lints/src/matches.rs | 2 +- clippy_lints/src/utils/hir.rs | 7 +++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 504515be88c..02cd719aa97 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -253,7 +253,6 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned } } PatKind::Lit(..) | - PatKind::QPath(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index de21cabc6fb..7aac6e96508 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -202,7 +202,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: path.to_string() } PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(), - PatKind::Path(ref path) => path.to_string(), + PatKind::Path(None, ref path) => path.to_string(), _ => return, }; diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 88a9e03182c..41b82f7203b 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -148,11 +148,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::Binding(ref lb, ref li, ref lp), &PatKind::Binding(ref rb, ref ri, ref rp)) => { lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } - (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_path(l, r), - (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), - (&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => { - self.eq_qself(ls, rs) && self.eq_path(lp, rp) + (&PatKind::Path(ref ql, ref l), &PatKind::Path(ref qr, ref r)) => { + both(ql, qr, |ql, qr| self.eq_qself(ql, qr)) && self.eq_path(l, r) } + (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => { ls == rs && over(l, r, |l, r| self.eq_pat(l, r)) } -- cgit 1.4.1-3-g733a5 From 62ddefc78316e9d7181990fe718d5da9bc2be638 Mon Sep 17 00:00:00 2001 From: mcarton <cartonmartin+git@gmail.com> Date: Sun, 10 Jul 2016 15:43:06 +0200 Subject: Bump to 0.0.79 --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0ea031c73f..ca3c67e4e8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.79 — ? +## 0.0.79 — 2016-07-10 +* Rustup to *rustc 1.12.0-nightly (f93aaf84c 2016-07-09)* * Major suggestions refactoring ## 0.0.78 — 2016-07-02 diff --git a/Cargo.toml b/Cargo.toml index f8b63a56257..79aefdfce61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.78" +version = "0.0.79" authors = [ "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", @@ -25,7 +25,7 @@ test = false [dependencies] # begin automatic update -clippy_lints = { version = "0.0.78", path = "clippy_lints" } +clippy_lints = { version = "0.0.79", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e74db2b17a6..6f05b99a16f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.78" +version = "0.0.79" # end automatic update authors = [ "Manish Goregaokar <manishsmail@gmail.com>", -- cgit 1.4.1-3-g733a5 From c1421c6e820c147c1572b98bbcac9c05e51fd066 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Sun, 10 Jul 2016 18:53:50 +0530 Subject: Don't warn when boxing large arrays --- clippy_lints/src/escape.rs | 41 ++++++++++++++++++++++++++++++----- clippy_lints/src/lib.rs | 3 ++- clippy_lints/src/utils/conf.rs | 2 ++ tests/compile-fail/escape_analysis.rs | 9 ++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 2bdfe91a908..d98420a69f6 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,17 +1,21 @@ use rustc::hir::*; use rustc::hir::intravisit as visit; use rustc::hir::map::Node::{NodeExpr, NodeStmt}; +use rustc::infer::InferCtxt; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt, Categorization}; use rustc::ty::adjustment::AutoAdjustment; use rustc::ty; +use rustc::ty::layout::TargetDataLayout; use rustc::util::nodemap::NodeSet; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; -pub struct Pass; +pub struct Pass { + pub too_large_for_stack: u64, +} /// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. /// @@ -39,9 +43,12 @@ fn is_non_trait_box(ty: ty::Ty) -> bool { } } -struct EscapeDelegate<'a, 'tcx: 'a> { +struct EscapeDelegate<'a, 'tcx: 'a+'gcx, 'gcx: 'a> { tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, set: NodeSet, + infcx: &'a InferCtxt<'a, 'gcx, 'gcx>, + target: TargetDataLayout, + too_large_for_stack: u64, } impl LintPass for Pass { @@ -55,9 +62,15 @@ impl LateLintPass for Pass { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); + + // we store the infcx because it is expensive to recreate + // the context each time. let mut v = EscapeDelegate { tcx: cx.tcx, set: NodeSet(), + infcx: &infcx, + target: TargetDataLayout::parse(cx.sess()), + too_large_for_stack: self.too_large_for_stack, }; { @@ -74,7 +87,7 @@ impl LateLintPass for Pass { } } -impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { +impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'gcx> { fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { @@ -93,7 +106,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { return; } - if is_non_trait_box(cmt.ty) { + if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { self.set.insert(consume_pat.id); } return; @@ -104,7 +117,7 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { if let ExprBox(..) = ex.node { - if is_non_trait_box(cmt.ty) { + if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { // let x = box (...) self.set.insert(consume_pat.id); } @@ -170,3 +183,21 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn decl_without_init(&mut self, _: NodeId, _: Span) {} fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} } + +impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> EscapeDelegate<'a, 'tcx, 'gcx> { + fn is_large_box(&self, ty: ty::Ty<'gcx>) -> bool { + // Large types need to be boxed to avoid stack + // overflows. + match ty.sty { + ty::TyBox(ref inner) => { + if let Ok(layout) = inner.layout(self.infcx) { + let size = layout.size(&self.target); + size.bytes() > self.too_large_for_stack + } else { + false + } + }, + _ => false, + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c873ef8cc57..5549e19ccb1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -9,6 +9,7 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(type_macros)] +#![feature(iter_arith)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] @@ -219,7 +220,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box temporary_assignment::Pass); reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); - reg.register_late_lint_pass(box escape::Pass); + reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack}); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 6f2bf158521..5d335c8c12c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -158,6 +158,8 @@ define_Conf! { ("type-complexity-threshold", type_complexity_threshold, 250 => u64), /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have ("single-char-binding-names-threshold", max_single_char_names, 5 => u64), + /// Lint: BOXED_LOCAL. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap + ("too-large-for-stack", too_large_for_stack, 200 => u64), } /// Read the `toml` configuration file. The function will ignore “File not found” errors iif diff --git a/tests/compile-fail/escape_analysis.rs b/tests/compile-fail/escape_analysis.rs index c0893bcd767..cb4f2b0a655 100644 --- a/tests/compile-fail/escape_analysis.rs +++ b/tests/compile-fail/escape_analysis.rs @@ -103,3 +103,12 @@ fn warn_match() { ref y => () } } + +fn nowarn_large_array() { + // should not warn, is large array + // and should not be on stack + let x = box [1; 10000]; + match &x { // not moved + ref y => () + } +} -- cgit 1.4.1-3-g733a5 From ba9eda72363ddb5fdc1ee143ee57827eb9a330c7 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif <killercup@gmail.com> Date: Tue, 12 Jul 2016 14:11:18 +0200 Subject: Add First Draft of Lint Listing Page --- .gitignore | 3 ++ .travis.yml | 8 +++ util/export.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++ util/gh-pages/index.html | 114 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 252 insertions(+) create mode 100644 util/export.py create mode 100644 util/gh-pages/index.html diff --git a/.gitignore b/.gitignore index 2db1ec5144f..e5a2f2aa7b7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ Cargo.lock # Generated by dogfood /target_recur/ + +# gh pages docs +util/gh-pages/lints.json diff --git a/.travis.yml b/.travis.yml index 34e50956cc5..96d7915a2e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,3 +46,11 @@ after_success: else echo "Ignored" fi +- | + if [ "$TRAVIS_PULL_REQUEST" == "false" ] && + [ "$TRAVIS_REPO_SLUG" == "Manishearth/rust-clippy" ] && + [ "$TRAVIS_BRANCH" == "master" ] ; then + + python util/export.py + + fi diff --git a/util/export.py b/util/export.py new file mode 100644 index 00000000000..ce5b2240115 --- /dev/null +++ b/util/export.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +import os +import re +import json + +level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''') +conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) +confvar_re = re.compile(r'''/// Lint: (\w+). (.*).*\n *\("([^"]*)", (?:[^,]*), (.*) => (.*)\),''') +lint_subheadline = re.compile(r'''^\*\*([\w\s]+)[:?.!]\*\*(.*)''') + +# TODO: actual logging +def warn(*args): print(args) +def debug(*args): print(args) +def info(*args): print(args) + +def parse_path(p="clippy_lints/src"): + d = [] + for f in os.listdir(p): + if f.endswith(".rs"): + parse_file(d, os.path.join(p, f)) + return (d, parse_conf(p)) + + +def parse_conf(p): + c = {} + with open(p + '/utils/conf.rs') as f: + f = f.read() + + m = re.search(conf_re, f) + m = m.groups()[0] + + m = re.findall(confvar_re, m) + + for (lint, doc, name, default, ty) in m: + c[lint.lower()] = (name, ty, doc, default) + + return c + +def parseLintDef(level, comment, name): + lint = {} + lint['id'] = name + lint['level'] = level + lint['docs'] = {} + + last_section = None + + for line in comment: + if len(line.strip()) == 0: + continue + + match = re.match(lint_subheadline, line) + if match: + last_section = match.groups()[0] + text = match and match.groups()[1] or line + + if not last_section: + warn("Skipping comment line as it was not preceded by a heading") + debug("in lint `%s`, line `%s`" % name, line) + + lint['docs'][last_section] = (lint['docs'].get(last_section, "") + "\n" + text).strip() + + return lint + +def parse_file(d, f): + last_comment = [] + comment = True + + with open(f) as rs: + for line in rs: + if comment: + if line.startswith("///"): + if line.startswith("/// "): + last_comment.append(line[4:]) + else: + last_comment.append(line[3:]) + elif line.startswith("declare_lint!"): + comment = False + deprecated = False + restriction = False + elif line.startswith("declare_restriction_lint!"): + comment = False + deprecated = False + restriction = True + elif line.startswith("declare_deprecated_lint!"): + comment = False + deprecated = True + else: + last_comment = [] + if not comment: + l = line.strip() + m = re.search(r"pub\s+([A-Z_][A-Z_0-9]*)", l) + + if m: + name = m.group(1).lower() + + # Intentionally either a never looping or infinite loop + while not deprecated and not restriction: + m = re.search(level_re, line) + if m: + level = m.group(0) + break + + line = next(rs) + + if deprecated: + level = "Deprecated" + elif restriction: + level = "Allow" + + info("found %s with level %s in %s" % (name, level, f)) + d.append(parseLintDef(level, last_comment, name=name)) + last_comment = [] + comment = True + if "}" in l: + warn("Warning: Missing Lint-Name in", f) + comment = True + +def main(): + (lints, config) = parse_path() + info("got %s lints" % len(lints)) + with open("util/gh-pages/lints.json", "w") as file: + json.dump(lints, file, indent=2) + info("wrote JSON for great justice") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html new file mode 100644 index 00000000000..7b44c4114f6 --- /dev/null +++ b/util/gh-pages/index.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Clippy + + + + + +
+ + + + + +
+
+
+
+ + +
+
+
+
+ Filter: + + + + +
+
+
+
+ +
+
+ + +

+ {{lint.id}} + Allow + Warn + Deny +

+
+ +
    +
  • +

    + {{title}} +

    +
    +
  • +
+
+
+ + + + + + + + + + \ No newline at end of file -- cgit 1.4.1-3-g733a5 From e63b8342c389cd4b12d0daa17c1f7a9aef1065c8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 12 Jul 2016 20:21:45 +0530 Subject: Remove unnecessary feature --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5549e19ccb1..0d6f77b2b0c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -9,7 +9,6 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(type_macros)] -#![feature(iter_arith)] #![allow(indexing_slicing, shadow_reuse, unknown_lints)] -- cgit 1.4.1-3-g733a5 From 319c66a2a4284c682d9575fe7aad5e4b4bf89365 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 12 Jul 2016 17:36:11 +0200 Subject: lint on implementing `visit_string` without also implementing `visit_str` --- CHANGELOG.md | 1 + Cargo.toml | 1 + README.md | 3 ++- clippy_lints/src/lib.rs | 3 +++ clippy_lints/src/serde.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/serde.rs | 39 ++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/serde.rs create mode 100644 tests/compile-fail/serde.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3c67e4e8f..e6ceb413169 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -246,6 +246,7 @@ All notable changes to this project will be documented in this file. [`result_unwrap_used`]: https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used [`reverse_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop [`search_is_some`]: https://github.com/Manishearth/rust-clippy/wiki#search_is_some +[`serde_api_misuse`]: https://github.com/Manishearth/rust-clippy/wiki#serde_api_misuse [`shadow_reuse`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse [`shadow_same`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_same [`shadow_unrelated`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated diff --git a/Cargo.toml b/Cargo.toml index 79aefdfce61..9790937a307 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ lazy_static = "0.1.15" regex = "0.1.71" rustc-serialize = "0.3" clippy-mini-macro-test = { version = "0.1", path = "mini-macro" } +serde = "0.7" [features] diff --git a/README.md b/README.md index f37d242e434..c62edbe03ae 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 158 lints included in this crate: +There are 159 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -136,6 +136,7 @@ name [result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled [reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | Iterating over an empty range, such as `10..0` or `5..5` [search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` +[serde_api_misuse](https://github.com/Manishearth/rust-clippy/wiki#serde_api_misuse) | warn | Various things that will negatively affect your serde experience [shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` [shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` [shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | The name is re-bound without even using the original value diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c873ef8cc57..4a8ecdda6f0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -114,6 +114,7 @@ pub mod ptr_arg; pub mod ranges; pub mod regex; pub mod returns; +pub mod serde; pub mod shadow; pub mod strings; pub mod swap; @@ -167,6 +168,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { store.register_removed("string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon"); // end deprecated lints, do not remove this comment, it’s used in `update_lints` + reg.register_late_lint_pass(box serde::Serde); reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box booleans::NonminimalBool); reg.register_late_lint_pass(box misc::TopLevelRefPass); @@ -399,6 +401,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + serde::SERDE_API_MISUSE, strings::STRING_LIT_AS_BYTES, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, diff --git a/clippy_lints/src/serde.rs b/clippy_lints/src/serde.rs new file mode 100644 index 00000000000..c916ad3c514 --- /dev/null +++ b/clippy_lints/src/serde.rs @@ -0,0 +1,55 @@ +use rustc::lint::*; +use rustc::hir::*; +use utils::{span_lint, get_trait_def_id}; + +/// **What it does:** This lint checks for mis-uses of the serde API +/// +/// **Why is this bad?** Serde is very finnicky about how its API should be used, but the type system can't be used to enforce it (yet) +/// +/// **Known problems:** None. +/// +/// **Example:** implementing `Visitor::visit_string` but not `Visitor::visit_str` +declare_lint! { + pub SERDE_API_MISUSE, Warn, + "Various things that will negatively affect your serde experience" +} + + +#[derive(Copy, Clone)] +pub struct Serde; + +impl LintPass for Serde { + fn get_lints(&self) -> LintArray { + lint_array!(SERDE_API_MISUSE) + } +} + +impl LateLintPass for Serde { + fn check_item(&mut self, cx: &LateContext, item: &Item) { + if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node { + let did = cx.tcx.expect_def(trait_ref.ref_id).def_id(); + if let Some(visit_did) = get_trait_def_id(cx, &["serde", "de", "Visitor"]) { + if did == visit_did { + let mut seen_str = None; + let mut seen_string = None; + for item in items { + match &*item.name.as_str() { + "visit_str" => seen_str = Some(item.span), + "visit_string" => seen_string = Some(item.span), + _ => {}, + } + } + if let Some(span) = seen_string { + if seen_str.is_none() { + span_lint(cx, + SERDE_API_MISUSE, + span, + "you should not implement `visit_string` without also implementing `visit_str`", + ); + } + } + } + } + } + } +} diff --git a/tests/compile-fail/serde.rs b/tests/compile-fail/serde.rs new file mode 100644 index 00000000000..d5099edbc0c --- /dev/null +++ b/tests/compile-fail/serde.rs @@ -0,0 +1,39 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(serde_api_misuse)] +#![allow(dead_code)] + +extern crate serde; + +struct A; + +impl serde::de::Visitor for A { + type Value = (); + fn visit_str(&mut self, _v: &str) -> Result + where E: serde::Error, + { + unimplemented!() + } + + fn visit_string(&mut self, _v: String) -> Result + where E: serde::Error, + { + unimplemented!() + } +} + +struct B; + +impl serde::de::Visitor for B { + type Value = (); + + fn visit_string(&mut self, _v: String) -> Result + //~^ ERROR you should not implement `visit_string` without also implementing `visit_str` + where E: serde::Error, + { + unimplemented!() + } +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 8907cbc0b864c6c4dca3534bf494d25a038fa7f0 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 13 Jul 2016 00:43:33 -0700 Subject: Added sign check on Constant f64 PartialEq implementation --- clippy_lints/src/consts.rs | 3 ++- tests/compile-fail/copies.rs | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index b4c8521a0a9..d4ee7659056 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -92,7 +92,8 @@ impl PartialEq for Constant { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them match (ls.parse::(), rs.parse::()) { - (Ok(l), Ok(r)) => l.eq(&r), + (Ok(l), Ok(r)) => l.eq(&r) && + (l.is_sign_positive() == r.is_sign_positive()), // needed for 0.0 != -0.0 _ => false, } } diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index a8d7157629b..66452048df4 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -229,6 +229,31 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => 0, }; + let _ = if true { + //~^NOTE same as this + 0.0 + } else { //~ERROR this `if` has identical blocks + 0.0 + }; + + let _ = if true { + //~^NOTE same as this + -0.0 + } else { //~ERROR this `if` has identical blocks + -0.0 + }; + + let _ = if true { + 0.0 + } else { + -0.0 + }; + + let _ = match Some(()) { + Some(()) => 0.0, + None => -0.0 + }; + match (Some(42), Some("")) { (Some(a), None) => bar(a), (None, Some(a)) => bar(a), // bindings have different types -- cgit 1.4.1-3-g733a5 From 0dd13b0db2f120577e31bec5c61190eb16d692a3 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 13 Jul 2016 00:59:35 -0700 Subject: Change floating point constant to mem::transmute u64 comparison --- clippy_lints/src/consts.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d4ee7659056..9ed37e70a01 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -92,8 +92,10 @@ impl PartialEq for Constant { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them match (ls.parse::(), rs.parse::()) { - (Ok(l), Ok(r)) => l.eq(&r) && - (l.is_sign_positive() == r.is_sign_positive()), // needed for 0.0 != -0.0 + // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs + (Ok(l), Ok(r)) => unsafe { + mem::transmute::(l) == mem::transmute::(r) + }, _ => false, } } -- cgit 1.4.1-3-g733a5 From 0c21a6b0c4f5db457a40484ce37170c99d6ae8d8 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 13 Jul 2016 09:35:31 -0700 Subject: Add test for different NaNs --- tests/compile-fail/copies.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index 66452048df4..b2b54251799 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -249,6 +249,21 @@ fn if_same_then_else() -> Result<&'static str, ()> { -0.0 }; + // Different NaNs + let _ = if true { + 1.0 / 0.0 + } else { + (-5f32).sqrt() + }; + + // Same NaNs + let _ = if true { + //~^NOTE same as this + std::f32::NAN + } else { //~ERROR this `if` has identical blocks + std::f32::NAN + }; + let _ = match Some(()) { Some(()) => 0.0, None => -0.0 -- cgit 1.4.1-3-g733a5 From 61d1a9b030d01d9b8320688951f42d18507c5535 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 13 Jul 2016 09:55:16 -0700 Subject: Check for comparison of -0.0 and 0.0 in PartialOrd for Constant --- clippy_lints/src/consts.rs | 6 +++++- tests/consts.rs | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 9ed37e70a01..aac9aa3e8ef 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -162,7 +162,11 @@ impl PartialOrd for Constant { (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { match (ls.parse::(), rs.parse::()) { - (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), + (Ok(ref l), Ok(ref r)) => match (l.partial_cmp(r), l.is_sign_positive() == r.is_sign_positive()) { + // Check for comparison of -0.0 and 0.0 + (Some(Ordering::Equal), false) => None, + (x, _) => x + }, _ => None, } } diff --git a/tests/consts.rs b/tests/consts.rs index 773b889ebff..5f5f4cb47d0 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -82,6 +82,12 @@ fn test_ops() { let half_any = Constant::Float("0.5".into(), FloatWidth::Any); let half32 = Constant::Float("0.5".into(), FloatWidth::F32); let half64 = Constant::Float("0.5".into(), FloatWidth::F64); + let pos_zero = Constant::Float("0.0".into(), FloatWidth::F64); + let neg_zero = Constant::Float("-0.0".into(), FloatWidth::F64); + + assert_eq!(pos_zero, pos_zero); + assert_eq!(neg_zero, neg_zero); + assert_eq!(None, pos_zero.partial_cmp(&neg_zero)); assert_eq!(half_any, half32); assert_eq!(half_any, half64); -- cgit 1.4.1-3-g733a5 From 7450d842ea778e351320540ad2d13bc4b1f4a249 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 13 Jul 2016 10:02:28 -0700 Subject: Fix different NaNs in if const expressions test --- tests/compile-fail/copies.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index b2b54251799..3c3e43931ed 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -9,6 +9,7 @@ #![allow(cyclomatic_complexity)] #![allow(blacklisted_name)] #![allow(collapsible_if)] +#![allow(zero_divided_by_zero, eq_op)] fn bar(_: T) {} fn foo() -> bool { unimplemented!() } @@ -251,9 +252,9 @@ fn if_same_then_else() -> Result<&'static str, ()> { // Different NaNs let _ = if true { - 1.0 / 0.0 + 0.0 / 0.0 } else { - (-5f32).sqrt() + std::f32::NAN }; // Same NaNs -- cgit 1.4.1-3-g733a5 From 3447bfccd98d13ff78fe04b4dbbc21fd0de20756 Mon Sep 17 00:00:00 2001 From: mcarton Date: Thu, 14 Jul 2016 17:42:40 +0200 Subject: Fix `MANY_SINGLE_CHAR_NAMES`'s docs --- clippy_lints/src/non_expressive_names.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 17f12afcaec..6d3f44036c0 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -25,7 +25,11 @@ declare_lint! { /// /// **Known problems:** None? /// -/// **Example:** let (a, b, c, d, e, f, g) = (...); +/// **Example:** +/// +/// ```rust +/// let (a, b, c, d, e, f, g) = (...); +/// ``` declare_lint! { pub MANY_SINGLE_CHAR_NAMES, Warn, -- cgit 1.4.1-3-g733a5 From c1eb5828fafae326919c6999bfda075c87dcc296 Mon Sep 17 00:00:00 2001 From: mcarton Date: Thu, 14 Jul 2016 18:32:09 +0200 Subject: Fix suggestion spans for `NEEDLESS_RETURN` --- clippy_lints/src/returns.rs | 20 ++++++++++---------- tests/compile-fail/needless_return.rs | 11 +++++------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index fda151cd6d7..deea50f0303 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -39,7 +39,7 @@ impl ReturnPass { if let Some(stmt) = block.stmts.last() { match stmt.node { StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { - self.check_final_expr(cx, expr); + self.check_final_expr(cx, expr, Some(stmt.span)); } _ => (), } @@ -47,11 +47,11 @@ impl ReturnPass { } // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr, span: Option) { match expr.node { // simple return is always "bad" ExprKind::Ret(Some(ref inner)) => { - self.emit_return_lint(cx, (expr.span, inner.span)); + self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span); } // a whole block? check it! ExprKind::Block(ref block) => { @@ -62,25 +62,25 @@ impl ReturnPass { // (except for unit type functions) so we don't match it ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => { self.check_block_return(cx, ifblock); - self.check_final_expr(cx, elsexpr); + self.check_final_expr(cx, elsexpr, None); } // a match expr, check all arms ExprKind::Match(_, ref arms) => { for arm in arms { - self.check_final_expr(cx, &arm.body); + self.check_final_expr(cx, &arm.body, Some(arm.body.span)); } } _ => (), } } - fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) { - if in_external_macro(cx, spans.1) { + fn emit_return_lint(&mut self, cx: &EarlyContext, ret_span: Span, inner_span: Span) { + if in_external_macro(cx, inner_span) { return; } - span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| { - if let Some(snippet) = snippet_opt(cx, spans.1) { - db.span_suggestion(spans.0, "remove `return` as shown:", snippet); + span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + db.span_suggestion(ret_span, "remove `return` as shown:", snippet); } }); } diff --git a/tests/compile-fail/needless_return.rs b/tests/compile-fail/needless_return.rs index 80fed2818ef..5a391a358b1 100644 --- a/tests/compile-fail/needless_return.rs +++ b/tests/compile-fail/needless_return.rs @@ -37,12 +37,11 @@ fn test_if_block() -> bool { fn test_match(x: bool) -> bool { match x { - true => { - return false; - //~^ ERROR unneeded return statement - //~| HELP remove `return` as shown - //~| SUGGESTION false - } + true => return false, + //~^ ERROR unneeded return statement + //~| HELP remove `return` as shown + //~| SUGGESTION false + false => { return true; //~^ ERROR unneeded return statement -- cgit 1.4.1-3-g733a5 From ea665c38f1ad049935a775d19082adedede9e00e Mon Sep 17 00:00:00 2001 From: mcarton Date: Thu, 14 Jul 2016 19:31:17 +0200 Subject: Fix FP with `USELESS_VEC` and non-copy types --- clippy_lints/src/methods.rs | 15 +++----- clippy_lints/src/utils/mod.rs | 7 +++- clippy_lints/src/vec.rs | 79 ++++++++++++++++++++++++------------------- tests/compile-fail/vec.rs | 9 ++++- 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f70ec4eac9f..755c325fcbc 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -2,7 +2,7 @@ use rustc::hir; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::const_qualif::ConstQualif; -use rustc::ty::subst::{Subst, TypeSpace}; +use rustc::ty::subst::TypeSpace; use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; @@ -10,9 +10,9 @@ use std::borrow::Cow; use std::fmt; use syntax::codemap::Span; use syntax::ptr::P; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, - span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path, + match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet, + span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::MethodArgs; use utils::paths; use utils::sugg; @@ -471,7 +471,7 @@ impl LateLintPass for Pass { // check conventions w.r.t. conversion method names and predicates let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty; - let is_copy = is_copy(cx, ty, item); + let is_copy = is_copy(cx, ty, item.id); for &(ref conv, self_kinds) in &CONVENTIONS { if_let_chain! {[ conv.check(&name.as_str()), @@ -1163,8 +1163,3 @@ fn is_bool(ty: &hir::Ty) -> bool { false } } - -fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, item: &hir::Item) -> bool { - let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id); - !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, item.span) -} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 189801c8c0b..bcc4be745c0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -15,7 +15,7 @@ use std::env; use std::mem; use std::str::FromStr; use syntax::ast::{self, LitKind}; -use syntax::codemap::{ExpnFormat, ExpnInfo, MultiSpan, Span}; +use syntax::codemap::{ExpnFormat, ExpnInfo, MultiSpan, Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; @@ -723,3 +723,8 @@ pub fn type_is_unsafe_function(ty: ty::Ty) -> bool { _ => false, } } + +pub fn is_copy<'a, 'ctx>(cx: &LateContext<'a, 'ctx>, ty: ty::Ty<'ctx>, env: NodeId) -> bool { + let env = ty::ParameterEnvironment::for_item(cx.tcx, env); + !ty.subst(cx.tcx, env.free_substs).moves_by_default(cx.tcx.global_tcx(), &env, DUMMY_SP) +} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 114817989d8..cc9d5a5f224 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,10 +1,10 @@ -use rustc::lint::*; -use rustc::ty::TypeVariants; use rustc::hir::*; +use rustc::lint::*; +use rustc::ty; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::eval_const_expr_partial; use syntax::codemap::Span; -use utils::{higher, snippet, span_lint_and_then}; +use utils::{higher, is_copy, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -35,50 +35,61 @@ impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_let_chain!{[ - let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, - let TypeVariants::TySlice(..) = ty.ty.sty, + let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty, + let ty::TypeVariants::TySlice(..) = ty.ty.sty, let ExprAddrOf(_, ref addressee) = expr.node, + let Some(vec_args) = higher::vec_macro(cx, addressee), ], { - check_vec_macro(cx, addressee, expr.span); + check_vec_macro(cx, &vec_args, expr.span); }} // search for `for _ in vec![…]` - if let Some((_, arg, _)) = higher::for_loop(expr) { + if_let_chain!{[ + let Some((_, arg, _)) = higher::for_loop(expr), + let Some(vec_args) = higher::vec_macro(cx, arg), + is_copy(cx, vec_type(cx.tcx.expr_ty_adjusted(arg)), cx.tcx.map.get_parent(expr.id)), + ], { // report the error around the `vec!` not inside `:` let span = cx.sess().codemap().source_callsite(arg.span); - check_vec_macro(cx, arg, span); - } + check_vec_macro(cx, &vec_args, span); + }} } } -fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { - if let Some(vec_args) = higher::vec_macro(cx, vec) { - let snippet = match vec_args { - higher::VecArgs::Repeat(elem, len) => { - if eval_const_expr_partial(cx.tcx, len, ExprTypeChecked, None).is_ok() { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() - } else { - return; - } +fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { + let snippet = match *vec_args { + higher::VecArgs::Repeat(elem, len) => { + if eval_const_expr_partial(cx.tcx, len, ExprTypeChecked, None).is_ok() { + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + } else { + return; } - higher::VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = Span { - lo: args[0].span.lo, - hi: last.span.hi, - expn_id: args[0].span.expn_id, - }; + } + higher::VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = Span { + lo: args[0].span.lo, + hi: last.span.hi, + expn_id: args[0].span.expn_id, + }; - format!("&[{}]", snippet(cx, span, "..")).into() - } else { - "&[]".into() - } + format!("&[{}]", snippet(cx, span, "..")).into() + } else { + "&[]".into() } - }; + } + }; - span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { - db.span_suggestion(span, "you can use a slice directly", snippet); - }); - } + span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| { + db.span_suggestion(span, "you can use a slice directly", snippet); + }); } +/// Return the item type of the vector (ie. the `T` in `Vec`). +fn vec_type(ty: ty::Ty) -> ty::Ty { + if let ty::TyStruct(_, substs) = ty.sty { + substs.types.get(ty::subst::ParamSpace::TypeSpace, 0) + } else { + panic!("The type of `vec!` is a not a struct?"); + } +} diff --git a/tests/compile-fail/vec.rs b/tests/compile-fail/vec.rs index 92c99c20e36..7a790e62116 100644 --- a/tests/compile-fail/vec.rs +++ b/tests/compile-fail/vec.rs @@ -3,6 +3,9 @@ #![deny(useless_vec)] +#[derive(Debug)] +struct NonCopy; + fn on_slice(_: &[u8]) {} #[allow(ptr_arg)] fn on_vec(_: &Vec) {} @@ -62,6 +65,10 @@ fn main() { //~^ ERROR useless use of `vec!` //~| HELP you can use //~| SUGGESTION for a in &[1, 2, 3] { - println!("{}", a); + println!("{:?}", a); + } + + for a in vec![NonCopy, NonCopy] { + println!("{:?}", a); } } -- cgit 1.4.1-3-g733a5 From bbbd0a5475095962e8eaeef57d9ad62f5ba018fd Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 14 Jul 2016 21:00:20 +0200 Subject: Adjust HTML Docs - Section IDs, with handy anchor links - Multiple filters for levels - Table rendering, block quote size - Nicer loading (hide un-rendered content) - Code highlighting (only for Rust, of course!) - Fix parsing of descriptions that have a newline after the section title (lead to duplicating the title, e.g., "Examples", in the content) --- util/export.py | 13 ++-- util/gh-pages/index.html | 164 +++++++++++++++++++++++++++++------------------ 2 files changed, 111 insertions(+), 66 deletions(-) mode change 100644 => 100755 util/export.py diff --git a/util/export.py b/util/export.py old mode 100644 new mode 100755 index ce5b2240115..152e9de141f --- a/util/export.py +++ b/util/export.py @@ -52,14 +52,17 @@ def parseLintDef(level, comment, name): match = re.match(lint_subheadline, line) if match: last_section = match.groups()[0] - text = match and match.groups()[1] or line - + if match: + text = match.groups()[1] + else: + text = line + if not last_section: warn("Skipping comment line as it was not preceded by a heading") debug("in lint `%s`, line `%s`" % name, line) - lint['docs'][last_section] = (lint['docs'].get(last_section, "") + "\n" + text).strip() - + lint['docs'][last_section] = (lint['docs'].get(last_section, "") + "\n" + text).strip() + return lint def parse_file(d, f): @@ -124,4 +127,4 @@ def main(): info("wrote JSON for great justice") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 7b44c4114f6..dd72ee234d1 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -1,11 +1,19 @@ - + + + Clippy - - + + +
@@ -13,87 +21,121 @@

ALL the Clippy Lints

- - + -
-
-
-
- - +
+ + + + +
+
+
+
+
+ +
+
-
-
-
- Filter: - - - - +
+
+ Filter: + + + + +
-
-
-
- - -

- {{lint.id}} - Allow - Warn - Deny -

-
- -
    -
  • -

    - {{title}} -

    -
    -
  • -
-
+
+
+ + +

+ {{lint.id}} + + Allow + Warn + Deny + + +

+
+ +
    +
  • +

    + {{title}} +

    +
    +
  • +
+
+
- + + + -- cgit 1.4.1-3-g733a5 From e338f6a4f018021a2ffc2574991ec4c3b9329642 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 28 Aug 2016 17:24:19 +0200 Subject: Remove now useless attribute `type_macros` --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 39d2c6b5f0d..c5ce53e66e5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,7 +8,6 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] -#![feature(type_macros)] #![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)] -- cgit 1.4.1-3-g733a5 From 189c5e5cfc549b64625b5b5cc1bb47c46140fb88 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 28 Aug 2016 17:25:41 +0200 Subject: Rustup to rustc 1.13.0-nightly (a23064af5 2016-08-27) --- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/methods.rs | 8 ++++---- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/vec.rs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2a0fca63e5d..a5f3b1c12f6 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -107,7 +107,7 @@ fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_re // Only care about `impl PartialEq for Foo` // For `impl PartialEq for A, input_types is [A, B] - if trait_ref.input_types()[1] == ty { + if trait_ref.substs.type_at(1) == ty { let mess = if peq_is_automatically_derived { "you are implementing `Hash` explicitly but have derived `PartialEq`" } else { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 2e7cd04d78e..30c7e067d28 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'g } } - fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, + fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: &ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 0dc6d5a3b4e..02366c4a52f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1083,12 +1083,12 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option> { if !match_type(cx, ty, &paths::RESULT) { return None; } + if let ty::TyEnum(_, substs) = ty.sty { - if let Some(err_ty) = substs.types.get(1) { - return Some(err_ty); - } + substs.types().nth(1) + } else { + None } - None } /// This checks whether a given type is known to implement Debug. diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 9cd17a07d71..db2c003b61d 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -59,7 +59,7 @@ impl LateLintPass for MutexAtomic { let ty = cx.tcx.expr_ty(expr); if let ty::TyStruct(_, subst) = ty.sty { if match_type(cx, ty, &paths::MUTEX) { - let mutex_param = &subst.types[0].sty; + let mutex_param = &subst.type_at(0).sty; if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ behaviour and not the internal type, consider using Mutex<()>.", diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c458bb1dff3..9e9ff65ac5e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -279,7 +279,7 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, trait_id, 0, ty, - ty_params); + &ty_params); traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) }) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 6943cb2a8f0..053cc69d7e7 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -89,7 +89,7 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { /// Return the item type of the vector (ie. the `T` in `Vec`). fn vec_type(ty: ty::Ty) -> ty::Ty { if let ty::TyStruct(_, substs) = ty.sty { - substs.types[0] + substs.type_at(0) } else { panic!("The type of `vec!` is a not a struct?"); } -- cgit 1.4.1-3-g733a5 From f3062f4199d42a0d1f93e1bdbe4a2d3e22ac2cec Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 28 Aug 2016 17:26:45 +0200 Subject: Bump to 0.0.86 --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7723b558376..185072debab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.86 — ? +## 0.0.86 — 2016-08-28 +* Rustup to *rustc 1.13.0-nightly (a23064af5 2016-08-27)* * New lints: [`missing_docs_in_private_items`], [`zero_prefixed_literal`] ## 0.0.85 — 2016-08-19 diff --git a/Cargo.toml b/Cargo.toml index 89974572eed..78c4b285f70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.85" +version = "0.0.86" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -25,7 +25,7 @@ test = false [dependencies] # begin automatic update -clippy_lints = { version = "0.0.85", path = "clippy_lints" } +clippy_lints = { version = "0.0.86", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 6f6f09d1e67..f629e1deb89 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.85" +version = "0.0.86" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From e922fa80ce5847be4c1cf9926313a02ba6a2b7ae Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 28 Aug 2016 17:59:01 +0200 Subject: Fix FP in `ZERO_PREFIXED_LITERAL` and `0b`/`Oo` --- CHANGELOG.md | 3 +++ clippy_lints/src/misc_early.rs | 2 ++ tests/compile-fail/literals.rs | 3 +++ 3 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 185072debab..636ca3f4f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.87 — ?? +* Fix FP in [`zero_prefixed_literal`] and `0b`/`Oo` + ## 0.0.86 — 2016-08-28 * Rustup to *rustc 1.13.0-nightly (a23064af5 2016-08-27)* * New lints: [`missing_docs_in_private_items`], [`zero_prefixed_literal`] diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 916801943b7..83ba980334a 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -287,6 +287,8 @@ impl EarlyLintPass for MiscEarly { span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span, "inconsistent casing in hexadecimal literal"); } + } else if src.starts_with("0b") || src.starts_with("0o") { + /* nothing to do */ } else if value != 0 && src.starts_with('0') { span_lint_and_then(cx, ZERO_PREFIXED_LITERAL, diff --git a/tests/compile-fail/literals.rs b/tests/compile-fail/literals.rs index 91a63646998..6c8a27c2ed4 100644 --- a/tests/compile-fail/literals.rs +++ b/tests/compile-fail/literals.rs @@ -32,4 +32,7 @@ fn main() { //~|SUGGESTION = 123; //~|HELP use `0o` //~|SUGGESTION = 0o123; + + let ok11 = 0o123; + let ok12 = 0b101010; } -- cgit 1.4.1-3-g733a5 From d87f13725484fef6342f2fc190353579a3ffffb8 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 28 Aug 2016 01:52:01 +0200 Subject: Add a `builtin_type_shadow` lint --- CHANGELOG.md | 2 ++ README.md | 3 ++- clippy_lints/src/lib.rs | 1 + clippy_lints/src/misc_early.rs | 37 +++++++++++++++++++++++++++++-- clippy_lints/src/utils/constants.rs | 21 ++++++++++++++++++ clippy_lints/src/utils/mod.rs | 1 + tests/compile-fail/builtin-type-shadow.rs | 11 +++++++++ 7 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/utils/constants.rs create mode 100644 tests/compile-fail/builtin-type-shadow.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 636ca3f4f2b..6ef4e596a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## 0.0.87 — ?? +* New lints: [`builtin_type_shadow`] * Fix FP in [`zero_prefixed_literal`] and `0b`/`Oo` ## 0.0.86 — 2016-08-28 @@ -178,6 +179,7 @@ All notable changes to this project will be documented in this file. [`bool_comparison`]: https://github.com/Manishearth/rust-clippy/wiki#bool_comparison [`box_vec`]: https://github.com/Manishearth/rust-clippy/wiki#box_vec [`boxed_local`]: https://github.com/Manishearth/rust-clippy/wiki#boxed_local +[`builtin_type_shadow`]: https://github.com/Manishearth/rust-clippy/wiki#builtin_type_shadow [`cast_possible_truncation`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation [`cast_possible_wrap`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap [`cast_precision_loss`]: https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss diff --git a/README.md b/README.md index 64d2932ed66..d305908ea62 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 169 lints included in this crate: +There are 170 lints included in this crate: name | default | triggers on ---------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -33,6 +33,7 @@ name [bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` [box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap [boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary +[builtin_type_shadow](https://github.com/Manishearth/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type [cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64` diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c5ce53e66e5..12370fb2630 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -378,6 +378,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc::MODULO_ONE, misc::REDUNDANT_PATTERN, misc::TOPLEVEL_REF_ARG, + misc_early::BUILTIN_TYPE_SHADOW, misc_early::DOUBLE_NEG, misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::MIXED_CASE_HEX_LITERALS, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 83ba980334a..61e4530a1df 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,7 +4,7 @@ use std::char; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then}; +use utils::{constants, span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -141,6 +141,27 @@ declare_lint! { "integer literals starting with `0`" } +/// **What it does:** Warns if a generic shadows a built-in type. +/// +/// **Why is this bad?** This gives surprising type errors. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// impl Foo { +/// fn impl_func(&self) -> u32 { +/// 42 +/// } +/// } +/// ``` +declare_lint! { + pub BUILTIN_TYPE_SHADOW, + Warn, + "shadowing a builtin type" +} + #[derive(Copy, Clone)] pub struct MiscEarly; @@ -149,11 +170,23 @@ impl LintPass for MiscEarly { fn get_lints(&self) -> LintArray { lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL, DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX, - ZERO_PREFIXED_LITERAL) + ZERO_PREFIXED_LITERAL, BUILTIN_TYPE_SHADOW) } } impl EarlyLintPass for MiscEarly { + fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) { + for ty in &gen.ty_params { + let name = ty.ident.name.as_str(); + if constants::BUILTIN_TYPES.contains(&&*name) { + span_lint(cx, + BUILTIN_TYPE_SHADOW, + ty.span, + &format!("This generic shadows the built-in type `{}`", name)); + } + } + } + fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs new file mode 100644 index 00000000000..179c251e322 --- /dev/null +++ b/clippy_lints/src/utils/constants.rs @@ -0,0 +1,21 @@ +//! This module contains some useful constants. + +#![deny(missing_docs_in_private_items)] + +/// List of the built-in types names. +/// +/// See also [the reference][reference-types] for a list of such types. +/// +/// [reference-types]: https://doc.rust-lang.org/reference.html#types +pub const BUILTIN_TYPES: &'static [&'static str] = &[ + "i8", "u8", + "i16", "u16", + "i32", "u32", + "i64", "u64", + "isize", "usize", + "f32", + "f64", + "bool", + "str", + "char", +]; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9e9ff65ac5e..9e6ee0fbf1b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -22,6 +22,7 @@ use syntax::ptr::P; pub mod cargo; pub mod comparisons; pub mod conf; +pub mod constants; mod hir; pub mod paths; pub mod sugg; diff --git a/tests/compile-fail/builtin-type-shadow.rs b/tests/compile-fail/builtin-type-shadow.rs new file mode 100644 index 00000000000..172875a6b9a --- /dev/null +++ b/tests/compile-fail/builtin-type-shadow.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![deny(builtin_type_shadow)] + +fn foo(a: u32) -> u32 { //~ERROR shadows the built-in type `u32` + 42 //~ERROR E0308 + // ^ rustc's type error +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From 3e2bb3fd813a4ea07668e2a678b8c7cc8878fc82 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sun, 28 Aug 2016 21:08:14 +0200 Subject: Actually scroll lint panels into view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trick to writing horrible hacks such as this is to recognize angular as a technology stack that may be endearing to some as one can do easy stuff quickly. But fundamentally, it is built on top of crazy shit. Like: Yes, I just wrote a directive that for some reason automatically has access to the scope of the repeated item, and fires an event each time the last `np-repeat` item was seen (delayed by one render loop cycle, of course). And – obviously – when defining the directive it is in camelCase but when using it in the template it has to by in dash-case. Great times. --- util/gh-pages/index.html | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index c60d1f3df38..04196eef396 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -62,7 +62,8 @@
-
+
- + -- cgit 1.4.1-3-g733a5 From b3c90efcb43a19d4c65eb7cbd4f406ede7b2a7f3 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 3 Aug 2017 21:17:12 +0200 Subject: Generate version index for docs domain index Uses basically the same code as the lint docs page as I didn't want to reinvent anything: A simple python script (inline in deploy script) writes an array of versions to a JSON file, which gets turned into a list of links using a bit of angular.js code. Fixes #1917 --- .github/deploy.sh | 13 +++++++++ util/gh-pages/versions.html | 70 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 util/gh-pages/versions.html diff --git a/.github/deploy.sh b/.github/deploy.sh index 47bf021c626..8f6abc93ecf 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -33,6 +33,19 @@ if [ -n "$TRAVIS_TAG" ]; then ln -s "$TRAVIS_TAG" out/current fi +# Generate version index that is shown as root index page +( + cp util/gh-pages/versions.html out/index.html + + cd out + python -c '\ + import os, json;\ + print json.dumps([\ + dir for dir in os.listdir(".")\ + if not dir.startswith(".") and os.path.isdir(dir)\ + ])' > versions.json +) + # Pull requests and commits to other branches shouldn't try to deploy, just build to verify if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then # Tags should deploy diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html new file mode 100644 index 00000000000..baa44bf4676 --- /dev/null +++ b/util/gh-pages/versions.html @@ -0,0 +1,70 @@ + + + + + + + Clippy + + + + + +
+ + +
+ + + + +
+
+ + + + + + + + + + -- cgit 1.4.1-3-g733a5 From 3b7f3dc8e7124869c9d2399c37f5d59ddfe4e0ef Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 1 Aug 2017 00:58:26 +0200 Subject: WIP: Find binding or assignment within outer loop --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/loops.rs | 147 ++++++++++++++++++++++++++++++++++++++------- tests/ui/while_loop.rs | 8 ++- tests/ui/while_loop.stderr | 9 ++- 4 files changed, 140 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c1c14f5b8c..18759fb0a91 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -253,7 +253,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); - reg.register_late_lint_pass(box loops::Pass::default()); + reg.register_late_lint_pass(box loops::Pass); reg.register_late_lint_pass(box lifetimes::LifetimePass); reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8b31969d254..b4501315cd3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -304,10 +304,8 @@ declare_lint! { "any loop that will always `break` or `return`" } -#[derive(Copy, Clone, Default)] -pub struct Pass { - loop_count: usize, -} +#[derive(Copy, Clone)] +pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { @@ -329,15 +327,6 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - match expr.node { - ExprWhile(..) | ExprLoop(..) => { - self.loop_count -= 1; - }, - _ => (), - } - } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let Some((pat, arg, body)) = higher::for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); @@ -347,7 +336,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { - self.loop_count += 1; if never_loop(block, &expr.id) { span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); } @@ -410,10 +398,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); - if self.loop_count < 2 && method_path.name == "next" && - match_trait_method(cx, match_expr, &paths::ITERATOR) && + if method_path.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) && lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) && - !is_iterator_used_after_while_let(cx, iter_expr) { + !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0]) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); span_lint_and_sugg(cx, @@ -939,6 +926,15 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { } } +fn match_var(expr: &Expr, var: Name) -> bool { + if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { + if path.segments.len() == 1 && path.segments[0].name == var { + return true + } + } + false +} + struct UsedVisitor { var: ast::Name, // var to look for used: bool, // has the var been used otherwise? @@ -946,15 +942,13 @@ struct UsedVisitor { impl<'tcx> Visitor<'tcx> for UsedVisitor { fn visit_expr(&mut self, expr: &'tcx Expr) { - if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == self.var { - self.used = true; - return; - } + if match_var(expr, self.var) { + self.used = true; + return; } - walk_expr(self, expr); } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } @@ -1328,3 +1322,110 @@ fn is_conditional(expr: &Expr) -> bool { _ => false, } } + +fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool { + if_let_chain! {[ + let Some(loop_block) = get_enclosing_block(cx, match_expr.id), + let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)), + let Some(scope) = get_enclosing_block(cx, loop_expr.id) + ], { + return is_loop_nested(cx, scope, loop_expr.id, iter_expr) + }} + false +} + +fn is_loop_nested(cx: &LateContext, scope: &Block, expr_id: NodeId, iter_expr: &Expr) -> bool { + let mut b = scope; + let mut e = expr_id; + if let Some(name) = path_name(iter_expr) { + loop { + if b.stmts.iter().take_while(|stmt| !is_expr_stmt(stmt, e)).any(|stmt| + is_binding_or_assignment(stmt, name)) { + return false; + } + if let Some(map::Node::NodeExpr(outer)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(scope.id)) { + if let ExprLoop(..) = outer.node { + return true; + } + e = outer.id; + if let Some(eb) = get_enclosing_block(cx, e) { + b = eb; + } else { + return false; + } + } else { + return false; + } + } + } + true +} + +fn path_name(e: &Expr) -> Option { + if let ExprPath(QPath::Resolved(_, ref path)) = e.node { + let segments = &path.segments; + if segments.len() == 1 { + return Some(segments[0].name); + } + }; + None +} + +fn is_binding_or_assignment(stmt: &Stmt, name: Name) -> bool { + match stmt.node { + StmtExpr(ref e, _) | StmtSemi(ref e, _) => contains_assignment(e, name), + StmtDecl(ref decl, _) => is_binding(decl, name) + } +} + +struct AssignmentVisitor { + var: ast::Name, // var to look for + assigned: bool, // has the var been assigned? +} + +impl<'tcx> Visitor<'tcx> for AssignmentVisitor { + fn visit_expr(&mut self, expr: &'tcx Expr) { + match expr.node { + ExprAssign(ref path, _) | + ExprAssignOp(_, ref path, _) => if match_var(path, self.var) { + self.assigned = true; + } + ExprLoop(..) | + ExprIf(..) | + ExprWhile(..) => (), + _ => walk_expr(self, expr) + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +fn contains_assignment(e: &Expr, name: Name) -> bool { + let mut av = AssignmentVisitor { var: name, assigned: false }; + walk_expr(&mut av, e); + av.assigned +} + +fn is_binding(decl: &Decl, name: Name) -> bool { + match decl.node { + DeclLocal(ref local) => { + !local.pat.walk(&mut |p: &Pat| { + if let PatKind::Binding(_, _, span_name, _) = p.node { + name == span_name.node + } else { + false + } + }) + }, + _ => false + } +} + +fn is_expr_stmt(stmt: &Stmt, expr_id: NodeId) -> bool { + match stmt.node { + StmtExpr(ref e, _) | StmtSemi(ref e, _) => e.id == expr_id, + _ => false + } +} diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 58df3ba9dcb..84873582609 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -174,7 +174,13 @@ fn refutable() { let mut y = a.iter(); for _ in 0..2 { - while let Some(v) = y.next() { + while let Some(v) = y.next() { // y is reused, don't lint + } + } + + loop { + let mut y = a.iter(); + while let Some(v) = y.next() { // use a for loop here } } } diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index 7abdefe881b..c31fff3b19e 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -103,5 +103,12 @@ error: empty `loop {}` detected. You may want to either use `panic!()` or add `s | = note: `-D empty-loop` implied by `-D warnings` -error: aborting due to 10 previous errors +error: this loop could be written as a `for` loop + --> while_loop.rs:177:9 + | +177 | / while let Some(v) = y.next() { +178 | | } + | |_________^ help: try: `for v in y { .. }` + +error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 76ca4dca85a17e8e36dae4edeaaddea0a7c22739 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Thu, 3 Aug 2017 00:41:46 +0200 Subject: unify checks into single visitor, fix block walk --- clippy_lints/src/loops.rs | 152 ++++++++++++++++++++++++--------------------- tests/ui/while_loop.stderr | 6 +- 2 files changed, 83 insertions(+), 75 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b4501315cd3..fc28918ff16 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,8 +2,8 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, NestedVisitorMap}; -use rustc::hir::map::Node::NodeBlock; +use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, walk_pat, walk_stmt, NestedVisitorMap}; +use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::region::CodeExtent; @@ -1327,105 +1327,113 @@ fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool { if_let_chain! {[ let Some(loop_block) = get_enclosing_block(cx, match_expr.id), let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)), - let Some(scope) = get_enclosing_block(cx, loop_expr.id) ], { - return is_loop_nested(cx, scope, loop_expr.id, iter_expr) + return is_loop_nested(cx, loop_expr, iter_expr) }} false } -fn is_loop_nested(cx: &LateContext, scope: &Block, expr_id: NodeId, iter_expr: &Expr) -> bool { - let mut b = scope; - let mut e = expr_id; - if let Some(name) = path_name(iter_expr) { - loop { - if b.stmts.iter().take_while(|stmt| !is_expr_stmt(stmt, e)).any(|stmt| - is_binding_or_assignment(stmt, name)) { - return false; - } - if let Some(map::Node::NodeExpr(outer)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(scope.id)) { - if let ExprLoop(..) = outer.node { - return true; +fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool { + let mut id = loop_expr.id; + let iter_name = if let Some(name) = path_name(iter_expr) { + name + } else { + return true; + }; + loop { + let parent = cx.tcx.hir.get_parent_node(id); + if parent == id { + return false; + } + match cx.tcx.hir.find(parent) { + Some(NodeExpr(expr)) => { + match expr.node { + ExprLoop(..) | + ExprWhile(..) => { return true; }, + _ => () } - e = outer.id; - if let Some(eb) = get_enclosing_block(cx, e) { - b = eb; - } else { + }, + Some(NodeBlock(block)) => { + let mut block_visitor = LoopNestVisitor { + id: id, + iterator: iter_name, + nesting: Unknown + }; + walk_block(&mut block_visitor, block); + if block_visitor.nesting == RuledOut { return false; } - } else { + }, + Some(NodeStmt(_)) => (), + _ => { return false; } } + id = parent; } - true } -fn path_name(e: &Expr) -> Option { - if let ExprPath(QPath::Resolved(_, ref path)) = e.node { - let segments = &path.segments; - if segments.len() == 1 { - return Some(segments[0].name); - } - }; - None +#[derive(PartialEq, Eq)] +enum Nesting { + Unknown, // no nesting detected yet + RuledOut, // the iterator is initialized or assigned within scope + LookFurther // no nesting detected, no further walk required } -fn is_binding_or_assignment(stmt: &Stmt, name: Name) -> bool { - match stmt.node { - StmtExpr(ref e, _) | StmtSemi(ref e, _) => contains_assignment(e, name), - StmtDecl(ref decl, _) => is_binding(decl, name) - } -} +use self::Nesting::{Unknown, RuledOut, LookFurther}; -struct AssignmentVisitor { - var: ast::Name, // var to look for - assigned: bool, // has the var been assigned? +struct LoopNestVisitor { + id: NodeId, + iterator: Name, + nesting: Nesting } -impl<'tcx> Visitor<'tcx> for AssignmentVisitor { +impl<'tcx> Visitor<'tcx> for LoopNestVisitor { + fn visit_stmt(&mut self, stmt: &'tcx Stmt) { + if stmt.node.id() == self.id { + self.nesting = LookFurther; + } else if self.nesting == Unknown { + walk_stmt(self, stmt); + } + } + fn visit_expr(&mut self, expr: &'tcx Expr) { + if self.nesting != Unknown { return; } + if expr.id == self.id { + self.nesting = LookFurther; + return; + } match expr.node { ExprAssign(ref path, _) | - ExprAssignOp(_, ref path, _) => if match_var(path, self.var) { - self.assigned = true; - } - ExprLoop(..) | - ExprIf(..) | - ExprWhile(..) => (), + ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { + self.nesting = RuledOut; + }, _ => walk_expr(self, expr) } } - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None + fn visit_pat(&mut self, pat: &'tcx Pat) { + if self.nesting != Unknown { return; } + if let PatKind::Binding(_, _, span_name, _) = pat.node { + if self.iterator == span_name.node { + self.nesting = RuledOut; + return; + } + } + walk_pat(self, pat) } -} - -fn contains_assignment(e: &Expr, name: Name) -> bool { - let mut av = AssignmentVisitor { var: name, assigned: false }; - walk_expr(&mut av, e); - av.assigned -} -fn is_binding(decl: &Decl, name: Name) -> bool { - match decl.node { - DeclLocal(ref local) => { - !local.pat.walk(&mut |p: &Pat| { - if let PatKind::Binding(_, _, span_name, _) = p.node { - name == span_name.node - } else { - false - } - }) - }, - _ => false + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None } } -fn is_expr_stmt(stmt: &Stmt, expr_id: NodeId) -> bool { - match stmt.node { - StmtExpr(ref e, _) | StmtSemi(ref e, _) => e.id == expr_id, - _ => false - } +fn path_name(e: &Expr) -> Option { + if let ExprPath(QPath::Resolved(_, ref path)) = e.node { + let segments = &path.segments; + if segments.len() == 1 { + return Some(segments[0].name); + } + }; + None } diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index c31fff3b19e..689c92d6fb6 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -104,10 +104,10 @@ error: empty `loop {}` detected. You may want to either use `panic!()` or add `s = note: `-D empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> while_loop.rs:177:9 + --> $DIR/while_loop.rs:183:9 | -177 | / while let Some(v) = y.next() { -178 | | } +183 | / while let Some(v) = y.next() { // use a for loop here +184 | | } | |_________^ help: try: `for v in y { .. }` error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 4de37160bb0da14d91a3e58508ab6304556a8b48 Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Sun, 6 Aug 2017 15:06:21 +1000 Subject: fix ConstFloat usage --- clippy_lints/src/misc.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 1804e04d17f..14331d59dae 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -12,7 +12,7 @@ use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integ span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats, in_constant, match_trait_method, paths}; use utils::sugg::Sugg; -use syntax::ast::{LitKind, CRATE_NODE_ID}; +use syntax::ast::{LitKind, CRATE_NODE_ID, FloatTy}; /// **What it does:** Checks for function arguments and let bindings denoted as `ref`. /// @@ -403,23 +403,41 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr); if let Ok(ConstVal::Float(val)) = res { use std::cmp::Ordering; - match val { - val @ ConstFloat::F32(_) => { - let zero = ConstFloat::F32(0.0); + match val.ty { + FloatTy::F32 => { + let zero = ConstFloat { + ty: FloatTy::F32, + bits: 0.0f32.to_bits() as u128, + }; - let infinity = ConstFloat::F32(::std::f32::INFINITY); + let infinity = ConstFloat { + ty: FloatTy::F32, + bits: ::std::f32::INFINITY.to_bits() as u128, + }; - let neg_infinity = ConstFloat::F32(::std::f32::NEG_INFINITY); + let neg_infinity = ConstFloat { + ty: FloatTy::F32, + bits: ::std::f32::NEG_INFINITY.to_bits() as u128, + }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) }, - val @ ConstFloat::F64(_) => { - let zero = ConstFloat::F64(0.0); + FloatTy::F64 => { + let zero = ConstFloat { + ty: FloatTy::F64, + bits: 0.0f64.to_bits() as u128, + }; - let infinity = ConstFloat::F64(::std::f64::INFINITY); + let infinity = ConstFloat { + ty: FloatTy::F64, + bits: ::std::f64::INFINITY.to_bits() as u128, + }; - let neg_infinity = ConstFloat::F64(::std::f64::NEG_INFINITY); + let neg_infinity = ConstFloat { + ty: FloatTy::F64, + bits: ::std::f64::NEG_INFINITY.to_bits() as u128, + }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) -- cgit 1.4.1-3-g733a5 From 0670d0b59bf49f6f5d9700abdb4add828e1ddc2c Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 6 Aug 2017 11:09:53 +0200 Subject: fixing dogfood --- clippy_lints/src/misc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 14331d59dae..70f25e7dff0 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -407,7 +407,7 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { FloatTy::F32 => { let zero = ConstFloat { ty: FloatTy::F32, - bits: 0.0f32.to_bits() as u128, + bits: 0.0_f32.to_bits() as u128, }; let infinity = ConstFloat { @@ -426,7 +426,7 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { FloatTy::F64 => { let zero = ConstFloat { ty: FloatTy::F64, - bits: 0.0f64.to_bits() as u128, + bits: 0.0_f64.to_bits() as u128, }; let infinity = ConstFloat { -- cgit 1.4.1-3-g733a5 From 878333fd6ca568aba90b16a45dd2f02a166cd5c1 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 6 Aug 2017 22:50:19 +0200 Subject: Bump the version --- CHANGELOG.md | 1 + Cargo.toml | 4 ++-- README.md | 3 ++- clippy_lints/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84a5ddf70b..c145618db99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -592,6 +592,7 @@ All notable changes to this project will be documented in this file. [`useless_let_if_seq`]: https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq [`useless_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#useless_transmute [`useless_vec`]: https://github.com/Manishearth/rust-clippy/wiki#useless_vec +[`verbose_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#verbose_bit_mask [`while_let_loop`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_loop [`while_let_on_iterator`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator [`wrong_pub_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention diff --git a/Cargo.toml b/Cargo.toml index 8b9d6f01f63..ef54f15239e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.148" +version = "0.0.149" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.148", path = "clippy_lints" } +clippy_lints = { version = "0.0.149", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/README.md b/README.md index 058116bd2d3..2d711bd9e6a 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 203 lints included in this crate: +There are 204 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -378,6 +378,7 @@ name [useless_let_if_seq](https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq) | warn | unidiomatic `let mut` declaration followed by initialization in `if` [useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion [useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` +[verbose_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#verbose_bit_mask) | warn | expressions where a bit mask is less readable than the corresponding method call [while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }`, which can be written as a `while let` loop [while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator [wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a48ad5a9fdd..7614c048367 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.148" +version = "0.0.149" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From f515d7bb67d228be306d285e9ee7d5dd41ab1602 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 6 Aug 2017 13:10:21 +0200 Subject: Change all links to reflect the move to rust-lang-nursery --- CHANGELOG.md | 420 ++++++++++++++++++++--------------------- CONTRIBUTING.md | 10 +- Cargo.toml | 6 +- PUBLISH.md | 2 +- README.md | 424 +++++++++++++++++++++--------------------- clippy_lints/Cargo.toml | 2 +- clippy_lints/README.md | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- mini-macro/Cargo.toml | 2 +- tests/ui/doc.rs | 4 +- tests/ui/methods.rs | 2 +- tests/ui/module_inception.rs | 2 +- util/gh-pages/index.html | 2 +- util/update_lints.py | 2 +- 16 files changed, 443 insertions(+), 443 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c145618db99..208255eec6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -392,214 +392,214 @@ All notable changes to this project will be documented in this file. [configuration file]: ./rust-clippy#configuration -[`absurd_extreme_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons -[`almost_swapped`]: https://github.com/Manishearth/rust-clippy/wiki#almost_swapped -[`approx_constant`]: https://github.com/Manishearth/rust-clippy/wiki#approx_constant -[`assign_op_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern -[`assign_ops`]: https://github.com/Manishearth/rust-clippy/wiki#assign_ops -[`bad_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask -[`blacklisted_name`]: https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name -[`block_in_if_condition_expr`]: https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr -[`block_in_if_condition_stmt`]: https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt -[`bool_comparison`]: https://github.com/Manishearth/rust-clippy/wiki#bool_comparison -[`borrowed_box`]: https://github.com/Manishearth/rust-clippy/wiki#borrowed_box -[`box_vec`]: https://github.com/Manishearth/rust-clippy/wiki#box_vec -[`boxed_local`]: https://github.com/Manishearth/rust-clippy/wiki#boxed_local -[`builtin_type_shadow`]: https://github.com/Manishearth/rust-clippy/wiki#builtin_type_shadow -[`cast_possible_truncation`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation -[`cast_possible_wrap`]: https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap -[`cast_precision_loss`]: https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss -[`cast_sign_loss`]: https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss -[`char_lit_as_u8`]: https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8 -[`chars_next_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp -[`clone_double_ref`]: https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref -[`clone_on_copy`]: https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy -[`cmp_nan`]: https://github.com/Manishearth/rust-clippy/wiki#cmp_nan -[`cmp_null`]: https://github.com/Manishearth/rust-clippy/wiki#cmp_null -[`cmp_owned`]: https://github.com/Manishearth/rust-clippy/wiki#cmp_owned -[`collapsible_if`]: https://github.com/Manishearth/rust-clippy/wiki#collapsible_if -[`crosspointer_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute -[`cyclomatic_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity -[`deprecated_semver`]: https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver -[`deref_addrof`]: https://github.com/Manishearth/rust-clippy/wiki#deref_addrof -[`derive_hash_xor_eq`]: https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq -[`diverging_sub_expression`]: https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression -[`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown -[`double_neg`]: https://github.com/Manishearth/rust-clippy/wiki#double_neg -[`double_parens`]: https://github.com/Manishearth/rust-clippy/wiki#double_parens -[`drop_copy`]: https://github.com/Manishearth/rust-clippy/wiki#drop_copy -[`drop_ref`]: https://github.com/Manishearth/rust-clippy/wiki#drop_ref -[`duplicate_underscore_argument`]: https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument -[`empty_enum`]: https://github.com/Manishearth/rust-clippy/wiki#empty_enum -[`empty_loop`]: https://github.com/Manishearth/rust-clippy/wiki#empty_loop -[`enum_clike_unportable_variant`]: https://github.com/Manishearth/rust-clippy/wiki#enum_clike_unportable_variant -[`enum_glob_use`]: https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use -[`enum_variant_names`]: https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names -[`eq_op`]: https://github.com/Manishearth/rust-clippy/wiki#eq_op -[`eval_order_dependence`]: https://github.com/Manishearth/rust-clippy/wiki#eval_order_dependence -[`expl_impl_clone_on_copy`]: https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy -[`explicit_counter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop -[`explicit_into_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_into_iter_loop -[`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop -[`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice -[`filter_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map -[`filter_next`]: https://github.com/Manishearth/rust-clippy/wiki#filter_next -[`float_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic -[`float_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#float_cmp -[`for_kv_map`]: https://github.com/Manishearth/rust-clippy/wiki#for_kv_map -[`for_loop_over_option`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option -[`for_loop_over_result`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result -[`forget_copy`]: https://github.com/Manishearth/rust-clippy/wiki#forget_copy -[`forget_ref`]: https://github.com/Manishearth/rust-clippy/wiki#forget_ref -[`get_unwrap`]: https://github.com/Manishearth/rust-clippy/wiki#get_unwrap -[`identity_op`]: https://github.com/Manishearth/rust-clippy/wiki#identity_op -[`if_let_redundant_pattern_matching`]: https://github.com/Manishearth/rust-clippy/wiki#if_let_redundant_pattern_matching -[`if_let_some_result`]: https://github.com/Manishearth/rust-clippy/wiki#if_let_some_result -[`if_not_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_not_else -[`if_same_then_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else -[`ifs_same_cond`]: https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond -[`inconsistent_digit_grouping`]: https://github.com/Manishearth/rust-clippy/wiki#inconsistent_digit_grouping -[`indexing_slicing`]: https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing -[`ineffective_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask -[`inline_always`]: https://github.com/Manishearth/rust-clippy/wiki#inline_always -[`integer_arithmetic`]: https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic -[`invalid_regex`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_regex -[`invalid_upcast_comparisons`]: https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons -[`items_after_statements`]: https://github.com/Manishearth/rust-clippy/wiki#items_after_statements -[`iter_cloned_collect`]: https://github.com/Manishearth/rust-clippy/wiki#iter_cloned_collect -[`iter_next_loop`]: https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop -[`iter_nth`]: https://github.com/Manishearth/rust-clippy/wiki#iter_nth -[`iter_skip_next`]: https://github.com/Manishearth/rust-clippy/wiki#iter_skip_next -[`iterator_step_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#iterator_step_by_zero -[`large_digit_groups`]: https://github.com/Manishearth/rust-clippy/wiki#large_digit_groups -[`large_enum_variant`]: https://github.com/Manishearth/rust-clippy/wiki#large_enum_variant -[`len_without_is_empty`]: https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty -[`len_zero`]: https://github.com/Manishearth/rust-clippy/wiki#len_zero -[`let_and_return`]: https://github.com/Manishearth/rust-clippy/wiki#let_and_return -[`let_unit_value`]: https://github.com/Manishearth/rust-clippy/wiki#let_unit_value -[`linkedlist`]: https://github.com/Manishearth/rust-clippy/wiki#linkedlist -[`logic_bug`]: https://github.com/Manishearth/rust-clippy/wiki#logic_bug -[`manual_swap`]: https://github.com/Manishearth/rust-clippy/wiki#manual_swap -[`many_single_char_names`]: https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names -[`map_clone`]: https://github.com/Manishearth/rust-clippy/wiki#map_clone -[`map_entry`]: https://github.com/Manishearth/rust-clippy/wiki#map_entry -[`match_bool`]: https://github.com/Manishearth/rust-clippy/wiki#match_bool -[`match_overlapping_arm`]: https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm -[`match_ref_pats`]: https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats -[`match_same_arms`]: https://github.com/Manishearth/rust-clippy/wiki#match_same_arms -[`match_wild_err_arm`]: https://github.com/Manishearth/rust-clippy/wiki#match_wild_err_arm -[`mem_forget`]: https://github.com/Manishearth/rust-clippy/wiki#mem_forget -[`min_max`]: https://github.com/Manishearth/rust-clippy/wiki#min_max -[`misrefactored_assign_op`]: https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op -[`missing_docs_in_private_items`]: https://github.com/Manishearth/rust-clippy/wiki#missing_docs_in_private_items -[`mixed_case_hex_literals`]: https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals -[`module_inception`]: https://github.com/Manishearth/rust-clippy/wiki#module_inception -[`modulo_one`]: https://github.com/Manishearth/rust-clippy/wiki#modulo_one -[`mut_from_ref`]: https://github.com/Manishearth/rust-clippy/wiki#mut_from_ref -[`mut_mut`]: https://github.com/Manishearth/rust-clippy/wiki#mut_mut -[`mutex_atomic`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic -[`mutex_integer`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_integer -[`needless_bool`]: https://github.com/Manishearth/rust-clippy/wiki#needless_bool -[`needless_borrow`]: https://github.com/Manishearth/rust-clippy/wiki#needless_borrow -[`needless_borrowed_reference`]: https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference -[`needless_continue`]: https://github.com/Manishearth/rust-clippy/wiki#needless_continue -[`needless_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes -[`needless_pass_by_value`]: https://github.com/Manishearth/rust-clippy/wiki#needless_pass_by_value -[`needless_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop -[`needless_return`]: https://github.com/Manishearth/rust-clippy/wiki#needless_return -[`needless_update`]: https://github.com/Manishearth/rust-clippy/wiki#needless_update -[`neg_multiply`]: https://github.com/Manishearth/rust-clippy/wiki#neg_multiply -[`never_loop`]: https://github.com/Manishearth/rust-clippy/wiki#never_loop -[`new_ret_no_self`]: https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self -[`new_without_default`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default -[`new_without_default_derive`]: https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive -[`no_effect`]: https://github.com/Manishearth/rust-clippy/wiki#no_effect -[`non_ascii_literal`]: https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal -[`nonminimal_bool`]: https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool -[`nonsensical_open_options`]: https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options -[`not_unsafe_ptr_arg_deref`]: https://github.com/Manishearth/rust-clippy/wiki#not_unsafe_ptr_arg_deref -[`ok_expect`]: https://github.com/Manishearth/rust-clippy/wiki#ok_expect -[`op_ref`]: https://github.com/Manishearth/rust-clippy/wiki#op_ref -[`option_map_unwrap_or`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or -[`option_map_unwrap_or_else`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else -[`option_unwrap_used`]: https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used -[`or_fun_call`]: https://github.com/Manishearth/rust-clippy/wiki#or_fun_call -[`out_of_bounds_indexing`]: https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing -[`overflow_check_conditional`]: https://github.com/Manishearth/rust-clippy/wiki#overflow_check_conditional -[`panic_params`]: https://github.com/Manishearth/rust-clippy/wiki#panic_params -[`partialeq_ne_impl`]: https://github.com/Manishearth/rust-clippy/wiki#partialeq_ne_impl -[`possible_missing_comma`]: https://github.com/Manishearth/rust-clippy/wiki#possible_missing_comma -[`precedence`]: https://github.com/Manishearth/rust-clippy/wiki#precedence -[`print_stdout`]: https://github.com/Manishearth/rust-clippy/wiki#print_stdout -[`print_with_newline`]: https://github.com/Manishearth/rust-clippy/wiki#print_with_newline -[`ptr_arg`]: https://github.com/Manishearth/rust-clippy/wiki#ptr_arg -[`pub_enum_variant_names`]: https://github.com/Manishearth/rust-clippy/wiki#pub_enum_variant_names -[`range_step_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#range_step_by_zero -[`range_zip_with_len`]: https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len -[`redundant_closure`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure -[`redundant_closure_call`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call -[`redundant_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern -[`regex_macro`]: https://github.com/Manishearth/rust-clippy/wiki#regex_macro -[`result_unwrap_used`]: https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used -[`reverse_range_loop`]: https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop -[`search_is_some`]: https://github.com/Manishearth/rust-clippy/wiki#search_is_some -[`serde_api_misuse`]: https://github.com/Manishearth/rust-clippy/wiki#serde_api_misuse -[`shadow_reuse`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse -[`shadow_same`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_same -[`shadow_unrelated`]: https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated -[`short_circuit_statement`]: https://github.com/Manishearth/rust-clippy/wiki#short_circuit_statement -[`should_assert_eq`]: https://github.com/Manishearth/rust-clippy/wiki#should_assert_eq -[`should_implement_trait`]: https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait -[`similar_names`]: https://github.com/Manishearth/rust-clippy/wiki#similar_names -[`single_char_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern -[`single_match`]: https://github.com/Manishearth/rust-clippy/wiki#single_match -[`single_match_else`]: https://github.com/Manishearth/rust-clippy/wiki#single_match_else -[`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string -[`string_add`]: https://github.com/Manishearth/rust-clippy/wiki#string_add -[`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign -[`string_extend_chars`]: https://github.com/Manishearth/rust-clippy/wiki#string_extend_chars -[`string_lit_as_bytes`]: https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes -[`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string -[`stutter`]: https://github.com/Manishearth/rust-clippy/wiki#stutter -[`suspicious_assignment_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting -[`suspicious_else_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting -[`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment -[`temporary_cstring_as_ptr`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr -[`too_many_arguments`]: https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments -[`toplevel_ref_arg`]: https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg -[`transmute_ptr_to_ref`]: https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref -[`trivial_regex`]: https://github.com/Manishearth/rust-clippy/wiki#trivial_regex -[`type_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#type_complexity -[`unicode_not_nfc`]: https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc -[`unit_cmp`]: https://github.com/Manishearth/rust-clippy/wiki#unit_cmp -[`unnecessary_cast`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_cast -[`unnecessary_mut_passed`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed -[`unnecessary_operation`]: https://github.com/Manishearth/rust-clippy/wiki#unnecessary_operation -[`unneeded_field_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern -[`unreadable_literal`]: https://github.com/Manishearth/rust-clippy/wiki#unreadable_literal -[`unsafe_removed_from_name`]: https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name -[`unseparated_literal_suffix`]: https://github.com/Manishearth/rust-clippy/wiki#unseparated_literal_suffix -[`unstable_as_mut_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice -[`unstable_as_slice`]: https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice -[`unused_collect`]: https://github.com/Manishearth/rust-clippy/wiki#unused_collect -[`unused_io_amount`]: https://github.com/Manishearth/rust-clippy/wiki#unused_io_amount -[`unused_label`]: https://github.com/Manishearth/rust-clippy/wiki#unused_label -[`unused_lifetimes`]: https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes -[`use_debug`]: https://github.com/Manishearth/rust-clippy/wiki#use_debug -[`used_underscore_binding`]: https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding -[`useless_attribute`]: https://github.com/Manishearth/rust-clippy/wiki#useless_attribute -[`useless_format`]: https://github.com/Manishearth/rust-clippy/wiki#useless_format -[`useless_let_if_seq`]: https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq -[`useless_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#useless_transmute -[`useless_vec`]: https://github.com/Manishearth/rust-clippy/wiki#useless_vec -[`verbose_bit_mask`]: https://github.com/Manishearth/rust-clippy/wiki#verbose_bit_mask -[`while_let_loop`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_loop -[`while_let_on_iterator`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator -[`wrong_pub_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention -[`wrong_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention -[`wrong_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute -[`zero_divided_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero -[`zero_prefixed_literal`]: https://github.com/Manishearth/rust-clippy/wiki#zero_prefixed_literal -[`zero_ptr`]: https://github.com/Manishearth/rust-clippy/wiki#zero_ptr -[`zero_width_space`]: https://github.com/Manishearth/rust-clippy/wiki#zero_width_space +[`absurd_extreme_comparisons`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#absurd_extreme_comparisons +[`almost_swapped`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#almost_swapped +[`approx_constant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#approx_constant +[`assign_op_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_op_pattern +[`assign_ops`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_ops +[`bad_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#bad_bit_mask +[`blacklisted_name`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#blacklisted_name +[`block_in_if_condition_expr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_expr +[`block_in_if_condition_stmt`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_stmt +[`bool_comparison`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#bool_comparison +[`borrowed_box`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#borrowed_box +[`box_vec`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec +[`boxed_local`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local +[`builtin_type_shadow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow +[`cast_possible_truncation`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation +[`cast_possible_wrap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap +[`cast_precision_loss`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss +[`cast_sign_loss`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_sign_loss +[`char_lit_as_u8`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#char_lit_as_u8 +[`chars_next_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#chars_next_cmp +[`clone_double_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_double_ref +[`clone_on_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_on_copy +[`cmp_nan`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_nan +[`cmp_null`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_null +[`cmp_owned`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_owned +[`collapsible_if`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#collapsible_if +[`crosspointer_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#crosspointer_transmute +[`cyclomatic_complexity`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cyclomatic_complexity +[`deprecated_semver`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#deprecated_semver +[`deref_addrof`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#deref_addrof +[`derive_hash_xor_eq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#derive_hash_xor_eq +[`diverging_sub_expression`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#diverging_sub_expression +[`doc_markdown`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#doc_markdown +[`double_neg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#double_neg +[`double_parens`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#double_parens +[`drop_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_copy +[`drop_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_ref +[`duplicate_underscore_argument`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#duplicate_underscore_argument +[`empty_enum`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_enum +[`empty_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_loop +[`enum_clike_unportable_variant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_clike_unportable_variant +[`enum_glob_use`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_glob_use +[`enum_variant_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_variant_names +[`eq_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#eq_op +[`eval_order_dependence`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#eval_order_dependence +[`expl_impl_clone_on_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#expl_impl_clone_on_copy +[`explicit_counter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_counter_loop +[`explicit_into_iter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_into_iter_loop +[`explicit_iter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_iter_loop +[`extend_from_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#extend_from_slice +[`filter_map`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_map +[`filter_next`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_next +[`float_arithmetic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#float_arithmetic +[`float_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#float_cmp +[`for_kv_map`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_kv_map +[`for_loop_over_option`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_option +[`for_loop_over_result`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_result +[`forget_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_copy +[`forget_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_ref +[`get_unwrap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#get_unwrap +[`identity_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#identity_op +[`if_let_redundant_pattern_matching`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_redundant_pattern_matching +[`if_let_some_result`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_some_result +[`if_not_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_not_else +[`if_same_then_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_same_then_else +[`ifs_same_cond`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ifs_same_cond +[`inconsistent_digit_grouping`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping +[`indexing_slicing`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing +[`ineffective_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask +[`inline_always`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always +[`integer_arithmetic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic +[`invalid_regex`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex +[`invalid_upcast_comparisons`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_upcast_comparisons +[`items_after_statements`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#items_after_statements +[`iter_cloned_collect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_cloned_collect +[`iter_next_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_next_loop +[`iter_nth`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_nth +[`iter_skip_next`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_skip_next +[`iterator_step_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iterator_step_by_zero +[`large_digit_groups`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#large_digit_groups +[`large_enum_variant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#large_enum_variant +[`len_without_is_empty`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#len_without_is_empty +[`len_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#len_zero +[`let_and_return`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#let_and_return +[`let_unit_value`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#let_unit_value +[`linkedlist`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#linkedlist +[`logic_bug`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#logic_bug +[`manual_swap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#manual_swap +[`many_single_char_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#many_single_char_names +[`map_clone`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#map_clone +[`map_entry`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#map_entry +[`match_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_bool +[`match_overlapping_arm`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_overlapping_arm +[`match_ref_pats`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats +[`match_same_arms`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms +[`match_wild_err_arm`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm +[`mem_forget`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget +[`min_max`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max +[`misrefactored_assign_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op +[`missing_docs_in_private_items`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#missing_docs_in_private_items +[`mixed_case_hex_literals`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mixed_case_hex_literals +[`module_inception`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#module_inception +[`modulo_one`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#modulo_one +[`mut_from_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_from_ref +[`mut_mut`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut +[`mutex_atomic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic +[`mutex_integer`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer +[`needless_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool +[`needless_borrow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow +[`needless_borrowed_reference`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference +[`needless_continue`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_continue +[`needless_lifetimes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_lifetimes +[`needless_pass_by_value`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_pass_by_value +[`needless_range_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_range_loop +[`needless_return`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_return +[`needless_update`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_update +[`neg_multiply`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#neg_multiply +[`never_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#never_loop +[`new_ret_no_self`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_ret_no_self +[`new_without_default`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default +[`new_without_default_derive`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default_derive +[`no_effect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#no_effect +[`non_ascii_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#non_ascii_literal +[`nonminimal_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#nonminimal_bool +[`nonsensical_open_options`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#nonsensical_open_options +[`not_unsafe_ptr_arg_deref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#not_unsafe_ptr_arg_deref +[`ok_expect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ok_expect +[`op_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#op_ref +[`option_map_unwrap_or`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or +[`option_map_unwrap_or_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or_else +[`option_unwrap_used`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_unwrap_used +[`or_fun_call`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#or_fun_call +[`out_of_bounds_indexing`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#out_of_bounds_indexing +[`overflow_check_conditional`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#overflow_check_conditional +[`panic_params`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#panic_params +[`partialeq_ne_impl`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#partialeq_ne_impl +[`possible_missing_comma`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#possible_missing_comma +[`precedence`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#precedence +[`print_stdout`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#print_stdout +[`print_with_newline`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#print_with_newline +[`ptr_arg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ptr_arg +[`pub_enum_variant_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#pub_enum_variant_names +[`range_step_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#range_step_by_zero +[`range_zip_with_len`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#range_zip_with_len +[`redundant_closure`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure +[`redundant_closure_call`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure_call +[`redundant_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_pattern +[`regex_macro`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#regex_macro +[`result_unwrap_used`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#result_unwrap_used +[`reverse_range_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#reverse_range_loop +[`search_is_some`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#search_is_some +[`serde_api_misuse`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#serde_api_misuse +[`shadow_reuse`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_reuse +[`shadow_same`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_same +[`shadow_unrelated`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_unrelated +[`short_circuit_statement`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#short_circuit_statement +[`should_assert_eq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#should_assert_eq +[`should_implement_trait`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#should_implement_trait +[`similar_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#similar_names +[`single_char_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_char_pattern +[`single_match`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match +[`single_match_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match_else +[`str_to_string`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#str_to_string +[`string_add`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add +[`string_add_assign`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add_assign +[`string_extend_chars`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_extend_chars +[`string_lit_as_bytes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_lit_as_bytes +[`string_to_string`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_to_string +[`stutter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#stutter +[`suspicious_assignment_formatting`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_assignment_formatting +[`suspicious_else_formatting`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_else_formatting +[`temporary_assignment`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_assignment +[`temporary_cstring_as_ptr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_cstring_as_ptr +[`too_many_arguments`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#too_many_arguments +[`toplevel_ref_arg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#toplevel_ref_arg +[`transmute_ptr_to_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#transmute_ptr_to_ref +[`trivial_regex`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#trivial_regex +[`type_complexity`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#type_complexity +[`unicode_not_nfc`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unicode_not_nfc +[`unit_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unit_cmp +[`unnecessary_cast`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_cast +[`unnecessary_mut_passed`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_mut_passed +[`unnecessary_operation`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_operation +[`unneeded_field_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unneeded_field_pattern +[`unreadable_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unreadable_literal +[`unsafe_removed_from_name`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unsafe_removed_from_name +[`unseparated_literal_suffix`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unseparated_literal_suffix +[`unstable_as_mut_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unstable_as_mut_slice +[`unstable_as_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unstable_as_slice +[`unused_collect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_collect +[`unused_io_amount`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_io_amount +[`unused_label`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label +[`unused_lifetimes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes +[`use_debug`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug +[`used_underscore_binding`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding +[`useless_attribute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute +[`useless_format`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format +[`useless_let_if_seq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_let_if_seq +[`useless_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_transmute +[`useless_vec`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_vec +[`verbose_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#verbose_bit_mask +[`while_let_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_loop +[`while_let_on_iterator`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_on_iterator +[`wrong_pub_self_convention`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_pub_self_convention +[`wrong_self_convention`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_self_convention +[`wrong_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_transmute +[`zero_divided_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_divided_by_zero +[`zero_prefixed_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_prefixed_literal +[`zero_ptr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_ptr +[`zero_width_space`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_width_space diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 71a54d85249..277e0f09bb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,16 +6,16 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lin All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth or @llogiq. -Some issues are easier than others. The [E-easy](https://github.com/Manishearth/rust-clippy/labels/E-easy) +Some issues are easier than others. The [E-easy](https://github.com/rust-lang-nursery/rust-clippy/labels/E-easy) label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! -Issues marked [T-AST](https://github.com/Manishearth/rust-clippy/labels/T-AST) involve simple +Issues marked [T-AST](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) involve simple matching of the syntax tree structure, and are generally easier than -[T-middle](https://github.com/Manishearth/rust-clippy/labels/T-middle) issues, which involve types +[T-middle](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues, which involve types and resolved paths. -Issues marked [E-medium](https://github.com/Manishearth/rust-clippy/labels/E-medium) are generally +Issues marked [E-medium](https://github.com/rust-lang-nursery/rust-clippy/labels/E-medium) are generally pretty easy too, though it's recommended you work on an E-easy issue first. [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer @@ -28,7 +28,7 @@ how this syntax structure is encoded in the AST, it is recommended to run `rustc example of the structure and compare with the [nodes in the AST docs](http://manishearth.github.io/rust-internals-docs/syntax/ast/). Usually the lint will end up to be a nested series of matches and ifs, -[like so](https://github.com/Manishearth/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). +[like so](https://github.com/rust-lang-nursery/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). T-middle issues can be more involved and require verifying types. The [`ty`](http://manishearth.github.io/rust-internals-docs/rustc/ty) module contains a diff --git a/Cargo.toml b/Cargo.toml index ef54f15239e..560cb528a4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,15 +9,15 @@ authors = [ "Oliver Schneider " ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" -repository = "https://github.com/Manishearth/rust-clippy" +repository = "https://github.com/rust-lang-nursery/rust-clippy" readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] [badges] -travis-ci = { repository = "Manishearth/rust-clippy" } -appveyor = { repository = "Manishearth/rust-clippy" } +travis-ci = { repository = "rust-lang-nursery/rust-clippy" } +appveyor = { repository = "rust-lang-nursery/rust-clippy" } [lib] name = "clippy" diff --git a/PUBLISH.md b/PUBLISH.md index 9dcfc52a25b..4a910c268e8 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -12,7 +12,7 @@ Steps to publish a new clippy version - `git pull`. - `git tag -s v0.0.X -m "v0.0.X"`. - `git push --tags`. -- `git clone git@github.com:Manishearth/rust-clippy.wiki.git ../rust-clippy.wiki` +- `git clone git@github.com:rust-lang-nursery/rust-clippy.wiki.git ../rust-clippy.wiki` - `./util/update_wiki.py` - `cd ../rust-clippy.wiki` - `git add *` diff --git a/README.md b/README.md index 2d711bd9e6a..b5cc1f09446 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # rust-clippy -[![Build Status](https://travis-ci.org/Manishearth/rust-clippy.svg?branch=master)](https://travis-ci.org/Manishearth/rust-clippy) -[![Windows build status](https://ci.appveyor.com/api/projects/status/github/Manishearth/rust-clippy?svg=true)](https://ci.appveyor.com/project/Manishearth/rust-clippy) -[![Clippy Linting Result](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/badge.svg)](http://clippy.bashy.io/github/Manishearth/rust-clippy/master/log) +[![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) +[![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy) +[![Clippy Linting Result](http://clippy.bashy.io/github/rust-lang-nursery/rust-clippy/master/badge.svg)](http://clippy.bashy.io/github/rust-lang-nursery/rust-clippy/master/log) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) @@ -83,7 +83,7 @@ in your code, you can use: cargo rustc -- -L /path/to/clippy_so/dir/ -Z extra-plugins=clippy ``` -*[Note](https://github.com/Manishearth/rust-clippy/wiki#a-word-of-warning):* +*[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! ### As a Compiler Plugin @@ -182,214 +182,214 @@ transparently: There are 204 lints included in this crate: -name | default | triggers on ------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- -[absurd_extreme_comparisons](https://github.com/Manishearth/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison with a maximum or minimum value that is always true or false -[almost_swapped](https://github.com/Manishearth/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence -[approx_constant](https://github.com/Manishearth/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::fXX::consts`) -[assign_op_pattern](https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern) | warn | assigning the result of an operation on a variable to that same variable -[assign_ops](https://github.com/Manishearth/rust-clippy/wiki#assign_ops) | allow | any compound assignment operation -[bad_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` -[blacklisted_name](https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name -[block_in_if_condition_expr](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces that can be eliminated in conditions, e.g. `if { true } ...` -[block_in_if_condition_stmt](https://github.com/Manishearth/rust-clippy/wiki#block_in_if_condition_stmt) | warn | complex blocks in conditions, e.g. `if { let x = true; x } ...` -[bool_comparison](https://github.com/Manishearth/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` -[borrowed_box](https://github.com/Manishearth/rust-clippy/wiki#borrowed_box) | warn | a borrow of a boxed type -[box_vec](https://github.com/Manishearth/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap -[boxed_local](https://github.com/Manishearth/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary -[builtin_type_shadow](https://github.com/Manishearth/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type -[cast_possible_truncation](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g. `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g. `x as u32` where `x: i32` -[char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | casting a character literal to u8 -[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char -[clone_double_ref](https://github.com/Manishearth/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` -[clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type -[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN, which will always return false, probably not intended -[cmp_null](https://github.com/Manishearth/rust-clippy/wiki#cmp_null) | warn | comparing a pointer to a null pointer, suggesting to use `.is_null()` instead. -[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/Manishearth/rust-clippy/wiki#collapsible_if) | warn | `if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`) -[crosspointer_transmute](https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute) | warn | transmutes that have to or from types that are a pointer to the other -[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | functions that should be split up into multiple functions -[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | use of `#[deprecated(since = "x")]` where x is not semver -[deref_addrof](https://github.com/Manishearth/rust-clippy/wiki#deref_addrof) | warn | use of `*&` or `*&mut` in an expression -[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -[diverging_sub_expression](https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression) | warn | whether an expression contains a diverging sub expression -[doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | presence of `_`, `::` or camel-case outside backticks in documentation -[double_neg](https://github.com/Manishearth/rust-clippy/wiki#double_neg) | warn | `--x`, which is a double negation of `x` and not a pre-decrement as in C/C++ -[double_parens](https://github.com/Manishearth/rust-clippy/wiki#double_parens) | warn | Warn on unnecessary double parentheses -[drop_copy](https://github.com/Manishearth/rust-clippy/wiki#drop_copy) | warn | calls to `std::mem::drop` with a value that implements Copy -[drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | calls to `std::mem::drop` with a reference instead of an owned value -[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | function arguments having names which only differ by an underscore -[empty_enum](https://github.com/Manishearth/rust-clippy/wiki#empty_enum) | allow | enum with no variants -[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}`, which should block or sleep -[enum_clike_unportable_variant](https://github.com/Manishearth/rust-clippy/wiki#enum_clike_unportable_variant) | warn | C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` -[enum_glob_use](https://github.com/Manishearth/rust-clippy/wiki#enum_glob_use) | allow | use items that import all variants of an enum -[enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | enums where all variants share a prefix/postfix -[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[eval_order_dependence](https://github.com/Manishearth/rust-clippy/wiki#eval_order_dependence) | warn | whether a variable read occurs before a write depends on sub-expression evaluation order -[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types -[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do -[explicit_into_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_into_iter_loop) | warn | for-looping over `_.into_iter()` when `_` would do -[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call -[filter_next](https://github.com/Manishearth/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` -[float_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#float_arithmetic) | allow | any floating-point arithmetic statement -[float_cmp](https://github.com/Manishearth/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values instead of comparing difference with an epsilon -[for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do -[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` -[for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` -[forget_copy](https://github.com/Manishearth/rust-clippy/wiki#forget_copy) | warn | calls to `std::mem::forget` with a value that implements Copy -[forget_ref](https://github.com/Manishearth/rust-clippy/wiki#forget_ref) | warn | calls to `std::mem::forget` with a reference instead of an owned value -[get_unwrap](https://github.com/Manishearth/rust-clippy/wiki#get_unwrap) | warn | using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead -[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[if_let_redundant_pattern_matching](https://github.com/Manishearth/rust-clippy/wiki#if_let_redundant_pattern_matching) | warn | use the proper utility function avoiding an `if let` -[if_let_some_result](https://github.com/Manishearth/rust-clippy/wiki#if_let_some_result) | warn | usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead -[if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | allow | `if` branches that could be swapped so no negation operation is necessary on the condition -[if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks -[ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition -[inconsistent_digit_grouping](https://github.com/Manishearth/rust-clippy/wiki#inconsistent_digit_grouping) | warn | integer literals with digits grouped inconsistently -[indexing_slicing](https://github.com/Manishearth/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage -[ineffective_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[inline_always](https://github.com/Manishearth/rust-clippy/wiki#inline_always) | warn | use of `#[inline(always)]` -[integer_arithmetic](https://github.com/Manishearth/rust-clippy/wiki#integer_arithmetic) | allow | any integer arithmetic statement -[invalid_regex](https://github.com/Manishearth/rust-clippy/wiki#invalid_regex) | deny | invalid regular expressions -[invalid_upcast_comparisons](https://github.com/Manishearth/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false -[items_after_statements](https://github.com/Manishearth/rust-clippy/wiki#items_after_statements) | allow | blocks where an item comes after a statement -[iter_cloned_collect](https://github.com/Manishearth/rust-clippy/wiki#iter_cloned_collect) | warn | using `.cloned().collect()` on slice to create a `Vec` -[iter_next_loop](https://github.com/Manishearth/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[iter_nth](https://github.com/Manishearth/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a standard library type with O(1) element access -[iter_skip_next](https://github.com/Manishearth/rust-clippy/wiki#iter_skip_next) | warn | using `.skip(x).next()` on an iterator -[iterator_step_by_zero](https://github.com/Manishearth/rust-clippy/wiki#iterator_step_by_zero) | warn | using `Iterator::step_by(0)`, which produces an infinite iterator -[large_digit_groups](https://github.com/Manishearth/rust-clippy/wiki#large_digit_groups) | warn | grouping digits into groups that are too large -[large_enum_variant](https://github.com/Manishearth/rust-clippy/wiki#large_enum_variant) | warn | large size difference between variants on an enum -[len_without_is_empty](https://github.com/Manishearth/rust-clippy/wiki#len_without_is_empty) | warn | traits or impls with a public `len` method but no corresponding `is_empty` method -[len_zero](https://github.com/Manishearth/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/Manishearth/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block -[let_unit_value](https://github.com/Manishearth/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/Manishearth/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque -[logic_bug](https://github.com/Manishearth/rust-clippy/wiki#logic_bug) | warn | boolean expressions that contain terminals which can be eliminated -[manual_swap](https://github.com/Manishearth/rust-clippy/wiki#manual_swap) | warn | manual swap of two variables -[many_single_char_names](https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names) | warn | too many single character bindings -[map_clone](https://github.com/Manishearth/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents -[map_entry](https://github.com/Manishearth/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` -[match_bool](https://github.com/Manishearth/rust-clippy/wiki#match_bool) | warn | a match on a boolean expression instead of an `if..else` block -[match_overlapping_arm](https://github.com/Manishearth/rust-clippy/wiki#match_overlapping_arm) | warn | a match with overlapping arms -[match_ref_pats](https://github.com/Manishearth/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` with all arms prefixed with `&` instead of deref-ing the match expression -[match_same_arms](https://github.com/Manishearth/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[match_wild_err_arm](https://github.com/Manishearth/rust-clippy/wiki#match_wild_err_arm) | warn | a match with `Err(_)` arm and take drastic actions -[mem_forget](https://github.com/Manishearth/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage on `Drop` types, likely to cause memory leaks -[min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[misrefactored_assign_op](https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op) | warn | having a variable on both sides of an assign op -[missing_docs_in_private_items](https://github.com/Manishearth/rust-clippy/wiki#missing_docs_in_private_items) | allow | detects missing documentation for public and private members -[mixed_case_hex_literals](https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals) | warn | hex literals whose letter digits are not consistently upper- or lowercased -[module_inception](https://github.com/Manishearth/rust-clippy/wiki#module_inception) | warn | modules that have the same name as their parent module -[modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_from_ref](https://github.com/Manishearth/rust-clippy/wiki#mut_from_ref) | warn | fns that create mutable refs from immutable ref args -[mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` -[mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic) | warn | using a mutex where an atomic value could be used instead -[mutex_integer](https://github.com/Manishearth/rust-clippy/wiki#mutex_integer) | allow | using a mutex for an integer type -[needless_bool](https://github.com/Manishearth/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_borrow](https://github.com/Manishearth/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced -[needless_borrowed_reference](https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference) | warn | taking a needless borrowed reference -[needless_continue](https://github.com/Manishearth/rust-clippy/wiki#needless_continue) | warn | `continue` statements that can be replaced by a rearrangement of code -[needless_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_pass_by_value](https://github.com/Manishearth/rust-clippy/wiki#needless_pass_by_value) | warn | functions taking arguments by value, but not consuming them in its body -[needless_range_loop](https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/Manishearth/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[needless_update](https://github.com/Manishearth/rust-clippy/wiki#needless_update) | warn | using `Foo { ..base }` when there are no missing fields -[neg_multiply](https://github.com/Manishearth/rust-clippy/wiki#neg_multiply) | warn | multiplying integers with -1 -[never_loop](https://github.com/Manishearth/rust-clippy/wiki#never_loop) | warn | any loop that will always `break` or `return` -[new_ret_no_self](https://github.com/Manishearth/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method -[new_without_default](https://github.com/Manishearth/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation -[new_without_default_derive](https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive) | warn | `fn new() -> Self` without `#[derive]`able `Default` implementation -[no_effect](https://github.com/Manishearth/rust-clippy/wiki#no_effect) | warn | statements with no effect -[non_ascii_literal](https://github.com/Manishearth/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal instead of using the `\\u` escape -[nonminimal_bool](https://github.com/Manishearth/rust-clippy/wiki#nonminimal_bool) | allow | boolean expressions that can be written more concisely -[nonsensical_open_options](https://github.com/Manishearth/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file -[not_unsafe_ptr_arg_deref](https://github.com/Manishearth/rust-clippy/wiki#not_unsafe_ptr_arg_deref) | warn | public functions dereferencing raw pointer arguments but not marked `unsafe` -[ok_expect](https://github.com/Manishearth/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result -[op_ref](https://github.com/Manishearth/rust-clippy/wiki#op_ref) | warn | taking a reference to satisfy the type constraints on `==` -[option_map_unwrap_or](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or) | allow | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` -[option_map_unwrap_or_else](https://github.com/Manishearth/rust-clippy/wiki#option_map_unwrap_or_else) | allow | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` -[option_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[or_fun_call](https://github.com/Manishearth/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method with a function call, which suggests `*or_else` -[out_of_bounds_indexing](https://github.com/Manishearth/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bounds constant indexing -[overflow_check_conditional](https://github.com/Manishearth/rust-clippy/wiki#overflow_check_conditional) | warn | overflow checks inspired by C which are likely to panic -[panic_params](https://github.com/Manishearth/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` calls -[partialeq_ne_impl](https://github.com/Manishearth/rust-clippy/wiki#partialeq_ne_impl) | warn | re-implementing `PartialEq::ne` -[possible_missing_comma](https://github.com/Manishearth/rust-clippy/wiki#possible_missing_comma) | warn | possible missing comma in array -[precedence](https://github.com/Manishearth/rust-clippy/wiki#precedence) | warn | operations where precedence may be unclear -[print_stdout](https://github.com/Manishearth/rust-clippy/wiki#print_stdout) | allow | printing on stdout -[print_with_newline](https://github.com/Manishearth/rust-clippy/wiki#print_with_newline) | warn | using `print!()` with a format string that ends in a newline -[ptr_arg](https://github.com/Manishearth/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[pub_enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#pub_enum_variant_names) | allow | enums where all variants share a prefix/postfix -[range_zip_with_len](https://github.com/Manishearth/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when `enumerate()` would do -[redundant_closure](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure) | warn | redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_closure_call](https://github.com/Manishearth/rust-clippy/wiki#redundant_closure_call) | warn | throwaway closures called in the expression they are defined -[redundant_pattern](https://github.com/Manishearth/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[regex_macro](https://github.com/Manishearth/rust-clippy/wiki#regex_macro) | warn | use of `regex!(_)` instead of `Regex::new(_)` -[result_unwrap_used](https://github.com/Manishearth/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[reverse_range_loop](https://github.com/Manishearth/rust-clippy/wiki#reverse_range_loop) | warn | iteration over an empty range, such as `10..0` or `5..5` -[search_is_some](https://github.com/Manishearth/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` -[serde_api_misuse](https://github.com/Manishearth/rust-clippy/wiki#serde_api_misuse) | warn | various things that will negatively affect your serde experience -[shadow_reuse](https://github.com/Manishearth/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/Manishearth/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/Manishearth/rust-clippy/wiki#shadow_unrelated) | allow | rebinding a name without even using the original value -[short_circuit_statement](https://github.com/Manishearth/rust-clippy/wiki#short_circuit_statement) | warn | using a short circuit boolean condition as a statement -[should_assert_eq](https://github.com/Manishearth/rust-clippy/wiki#should_assert_eq) | warn | using `assert` macro for asserting equality -[should_implement_trait](https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[similar_names](https://github.com/Manishearth/rust-clippy/wiki#similar_names) | allow | similarly named items and bindings -[single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` -[single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let` -[single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let` -[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String` instead of `push_str()` -[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String` instead of `push_str()` -[string_extend_chars](https://github.com/Manishearth/rust-clippy/wiki#string_extend_chars) | warn | using `x.extend(s.chars())` where s is a `&str` or `String` -[string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal instead of using a byte string literal -[stutter](https://github.com/Manishearth/rust-clippy/wiki#stutter) | allow | type names prefixed/postfixed with their containing module's name -[suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` -[suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` -[temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries -[temporary_cstring_as_ptr](https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr) | warn | getting the inner pointer of a temporary `CString` -[too_many_arguments](https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments -[toplevel_ref_arg](https://github.com/Manishearth/rust-clippy/wiki#toplevel_ref_arg) | warn | an entire binding declared as `ref`, in a function argument or a `let` statement -[transmute_ptr_to_ref](https://github.com/Manishearth/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type -[trivial_regex](https://github.com/Manishearth/rust-clippy/wiki#trivial_regex) | warn | trivial regular expressions -[type_complexity](https://github.com/Manishearth/rust-clippy/wiki#type_complexity) | warn | usage of very complex types that might be better factored into `type` definitions -[unicode_not_nfc](https://github.com/Manishearth/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) -[unit_cmp](https://github.com/Manishearth/rust-clippy/wiki#unit_cmp) | warn | comparing unit values -[unnecessary_cast](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_cast) | warn | cast to the same type, e.g. `x as i32` where `x: i32` -[unnecessary_mut_passed](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument passed as a mutable reference although the callee only demands an immutable reference -[unnecessary_operation](https://github.com/Manishearth/rust-clippy/wiki#unnecessary_operation) | warn | outer expressions with no effect -[unneeded_field_pattern](https://github.com/Manishearth/rust-clippy/wiki#unneeded_field_pattern) | warn | struct fields bound to a wildcard instead of using `..` -[unreadable_literal](https://github.com/Manishearth/rust-clippy/wiki#unreadable_literal) | warn | long integer literal without underscores -[unsafe_removed_from_name](https://github.com/Manishearth/rust-clippy/wiki#unsafe_removed_from_name) | warn | `unsafe` removed from API names on import -[unseparated_literal_suffix](https://github.com/Manishearth/rust-clippy/wiki#unseparated_literal_suffix) | allow | literals whose suffix is not separated by an underscore -[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[unused_io_amount](https://github.com/Manishearth/rust-clippy/wiki#unused_io_amount) | deny | unused written/read amount -[unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused labels -[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions -[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use of `Debug`-based formatting -[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore -[useless_attribute](https://github.com/Manishearth/rust-clippy/wiki#useless_attribute) | warn | use of lint attributes on `extern crate` items -[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!` -[useless_let_if_seq](https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq) | warn | unidiomatic `let mut` declaration followed by initialization in `if` -[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion -[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!` -[verbose_bit_mask](https://github.com/Manishearth/rust-clippy/wiki#verbose_bit_mask) | warn | expressions where a bit mask is less readable than the corresponding method call -[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }`, which can be written as a `while let` loop -[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator -[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_transmute](https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute) | warn | transmutes that are confusing at best, undefined behaviour at worst and always useless -[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN -[zero_prefixed_literal](https://github.com/Manishearth/rust-clippy/wiki#zero_prefixed_literal) | warn | integer literals starting with `0` -[zero_ptr](https://github.com/Manishearth/rust-clippy/wiki#zero_ptr) | warn | using 0 as *{const, mut} T -[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing - -More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas! +name | default | triggers on +-----------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- +[absurd_extreme_comparisons](https://github.com/rust-lang-nursery/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison with a maximum or minimum value that is always true or false +[almost_swapped](https://github.com/rust-lang-nursery/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence +[approx_constant](https://github.com/rust-lang-nursery/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::fXX::consts`) +[assign_op_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_op_pattern) | warn | assigning the result of an operation on a variable to that same variable +[assign_ops](https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_ops) | allow | any compound assignment operation +[bad_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` +[blacklisted_name](https://github.com/rust-lang-nursery/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name +[block_in_if_condition_expr](https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces that can be eliminated in conditions, e.g. `if { true } ...` +[block_in_if_condition_stmt](https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_stmt) | warn | complex blocks in conditions, e.g. `if { let x = true; x } ...` +[bool_comparison](https://github.com/rust-lang-nursery/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` +[borrowed_box](https://github.com/rust-lang-nursery/rust-clippy/wiki#borrowed_box) | warn | a borrow of a boxed type +[box_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap +[boxed_local](https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary +[builtin_type_shadow](https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type +[cast_possible_truncation](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32` +[cast_possible_wrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX` +[cast_precision_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g. `x as f32` where `x: u64` +[cast_sign_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g. `x as u32` where `x: i32` +[char_lit_as_u8](https://github.com/rust-lang-nursery/rust-clippy/wiki#char_lit_as_u8) | warn | casting a character literal to u8 +[chars_next_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char +[clone_double_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` +[clone_on_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type +[cmp_nan](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN, which will always return false, probably not intended +[cmp_null](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_null) | warn | comparing a pointer to a null pointer, suggesting to use `.is_null()` instead. +[cmp_owned](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` +[collapsible_if](https://github.com/rust-lang-nursery/rust-clippy/wiki#collapsible_if) | warn | `if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`) +[crosspointer_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#crosspointer_transmute) | warn | transmutes that have to or from types that are a pointer to the other +[cyclomatic_complexity](https://github.com/rust-lang-nursery/rust-clippy/wiki#cyclomatic_complexity) | warn | functions that should be split up into multiple functions +[deprecated_semver](https://github.com/rust-lang-nursery/rust-clippy/wiki#deprecated_semver) | warn | use of `#[deprecated(since = "x")]` where x is not semver +[deref_addrof](https://github.com/rust-lang-nursery/rust-clippy/wiki#deref_addrof) | warn | use of `*&` or `*&mut` in an expression +[derive_hash_xor_eq](https://github.com/rust-lang-nursery/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly +[diverging_sub_expression](https://github.com/rust-lang-nursery/rust-clippy/wiki#diverging_sub_expression) | warn | whether an expression contains a diverging sub expression +[doc_markdown](https://github.com/rust-lang-nursery/rust-clippy/wiki#doc_markdown) | warn | presence of `_`, `::` or camel-case outside backticks in documentation +[double_neg](https://github.com/rust-lang-nursery/rust-clippy/wiki#double_neg) | warn | `--x`, which is a double negation of `x` and not a pre-decrement as in C/C++ +[double_parens](https://github.com/rust-lang-nursery/rust-clippy/wiki#double_parens) | warn | Warn on unnecessary double parentheses +[drop_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_copy) | warn | calls to `std::mem::drop` with a value that implements Copy +[drop_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_ref) | warn | calls to `std::mem::drop` with a reference instead of an owned value +[duplicate_underscore_argument](https://github.com/rust-lang-nursery/rust-clippy/wiki#duplicate_underscore_argument) | warn | function arguments having names which only differ by an underscore +[empty_enum](https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_enum) | allow | enum with no variants +[empty_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_loop) | warn | empty `loop {}`, which should block or sleep +[enum_clike_unportable_variant](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_clike_unportable_variant) | warn | C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` +[enum_glob_use](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_glob_use) | allow | use items that import all variants of an enum +[enum_variant_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_variant_names) | warn | enums where all variants share a prefix/postfix +[eq_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) +[eval_order_dependence](https://github.com/rust-lang-nursery/rust-clippy/wiki#eval_order_dependence) | warn | whether a variable read occurs before a write depends on sub-expression evaluation order +[expl_impl_clone_on_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types +[explicit_counter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do +[explicit_into_iter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_into_iter_loop) | warn | for-looping over `_.into_iter()` when `_` would do +[explicit_iter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do +[filter_map](https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_map) | allow | using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call +[filter_next](https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` +[float_arithmetic](https://github.com/rust-lang-nursery/rust-clippy/wiki#float_arithmetic) | allow | any floating-point arithmetic statement +[float_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values instead of comparing difference with an epsilon +[for_kv_map](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do +[for_loop_over_option](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` +[for_loop_over_result](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` +[forget_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_copy) | warn | calls to `std::mem::forget` with a value that implements Copy +[forget_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_ref) | warn | calls to `std::mem::forget` with a reference instead of an owned value +[get_unwrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#get_unwrap) | warn | using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead +[identity_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` +[if_let_redundant_pattern_matching](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_redundant_pattern_matching) | warn | use the proper utility function avoiding an `if let` +[if_let_some_result](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_some_result) | warn | usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead +[if_not_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_not_else) | allow | `if` branches that could be swapped so no negation operation is necessary on the condition +[if_same_then_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks +[ifs_same_cond](https://github.com/rust-lang-nursery/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition +[inconsistent_digit_grouping](https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping) | warn | integer literals with digits grouped inconsistently +[indexing_slicing](https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage +[ineffective_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[inline_always](https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always) | warn | use of `#[inline(always)]` +[integer_arithmetic](https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic) | allow | any integer arithmetic statement +[invalid_regex](https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex) | deny | invalid regular expressions +[invalid_upcast_comparisons](https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false +[items_after_statements](https://github.com/rust-lang-nursery/rust-clippy/wiki#items_after_statements) | allow | blocks where an item comes after a statement +[iter_cloned_collect](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_cloned_collect) | warn | using `.cloned().collect()` on slice to create a `Vec` +[iter_next_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended +[iter_nth](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a standard library type with O(1) element access +[iter_skip_next](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_skip_next) | warn | using `.skip(x).next()` on an iterator +[iterator_step_by_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#iterator_step_by_zero) | warn | using `Iterator::step_by(0)`, which produces an infinite iterator +[large_digit_groups](https://github.com/rust-lang-nursery/rust-clippy/wiki#large_digit_groups) | warn | grouping digits into groups that are too large +[large_enum_variant](https://github.com/rust-lang-nursery/rust-clippy/wiki#large_enum_variant) | warn | large size difference between variants on an enum +[len_without_is_empty](https://github.com/rust-lang-nursery/rust-clippy/wiki#len_without_is_empty) | warn | traits or impls with a public `len` method but no corresponding `is_empty` method +[len_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead +[let_and_return](https://github.com/rust-lang-nursery/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block +[let_unit_value](https://github.com/rust-lang-nursery/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards +[linkedlist](https://github.com/rust-lang-nursery/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque +[logic_bug](https://github.com/rust-lang-nursery/rust-clippy/wiki#logic_bug) | warn | boolean expressions that contain terminals which can be eliminated +[manual_swap](https://github.com/rust-lang-nursery/rust-clippy/wiki#manual_swap) | warn | manual swap of two variables +[many_single_char_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#many_single_char_names) | warn | too many single character bindings +[map_clone](https://github.com/rust-lang-nursery/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents +[map_entry](https://github.com/rust-lang-nursery/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` +[match_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_bool) | warn | a match on a boolean expression instead of an `if..else` block +[match_overlapping_arm](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_overlapping_arm) | warn | a match with overlapping arms +[match_ref_pats](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` with all arms prefixed with `&` instead of deref-ing the match expression +[match_same_arms](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies +[match_wild_err_arm](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm) | warn | a match with `Err(_)` arm and take drastic actions +[mem_forget](https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage on `Drop` types, likely to cause memory leaks +[min_max](https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant +[misrefactored_assign_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op) | warn | having a variable on both sides of an assign op +[missing_docs_in_private_items](https://github.com/rust-lang-nursery/rust-clippy/wiki#missing_docs_in_private_items) | allow | detects missing documentation for public and private members +[mixed_case_hex_literals](https://github.com/rust-lang-nursery/rust-clippy/wiki#mixed_case_hex_literals) | warn | hex literals whose letter digits are not consistently upper- or lowercased +[module_inception](https://github.com/rust-lang-nursery/rust-clippy/wiki#module_inception) | warn | modules that have the same name as their parent module +[modulo_one](https://github.com/rust-lang-nursery/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 +[mut_from_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_from_ref) | warn | fns that create mutable refs from immutable ref args +[mut_mut](https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` +[mutex_atomic](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic) | warn | using a mutex where an atomic value could be used instead +[mutex_integer](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer) | allow | using a mutex for an integer type +[needless_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` +[needless_borrow](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced +[needless_borrowed_reference](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference) | warn | taking a needless borrowed reference +[needless_continue](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_continue) | warn | `continue` statements that can be replaced by a rearrangement of code +[needless_lifetimes](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them +[needless_pass_by_value](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_pass_by_value) | warn | functions taking arguments by value, but not consuming them in its body +[needless_range_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do +[needless_return](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice +[needless_update](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_update) | warn | using `Foo { ..base }` when there are no missing fields +[neg_multiply](https://github.com/rust-lang-nursery/rust-clippy/wiki#neg_multiply) | warn | multiplying integers with -1 +[never_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#never_loop) | warn | any loop that will always `break` or `return` +[new_ret_no_self](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method +[new_without_default](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation +[new_without_default_derive](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default_derive) | warn | `fn new() -> Self` without `#[derive]`able `Default` implementation +[no_effect](https://github.com/rust-lang-nursery/rust-clippy/wiki#no_effect) | warn | statements with no effect +[non_ascii_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal instead of using the `\\u` escape +[nonminimal_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#nonminimal_bool) | allow | boolean expressions that can be written more concisely +[nonsensical_open_options](https://github.com/rust-lang-nursery/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file +[not_unsafe_ptr_arg_deref](https://github.com/rust-lang-nursery/rust-clippy/wiki#not_unsafe_ptr_arg_deref) | warn | public functions dereferencing raw pointer arguments but not marked `unsafe` +[ok_expect](https://github.com/rust-lang-nursery/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result +[op_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#op_ref) | warn | taking a reference to satisfy the type constraints on `==` +[option_map_unwrap_or](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or) | allow | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` +[option_map_unwrap_or_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or_else) | allow | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` +[option_unwrap_used](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` +[or_fun_call](https://github.com/rust-lang-nursery/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method with a function call, which suggests `*or_else` +[out_of_bounds_indexing](https://github.com/rust-lang-nursery/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bounds constant indexing +[overflow_check_conditional](https://github.com/rust-lang-nursery/rust-clippy/wiki#overflow_check_conditional) | warn | overflow checks inspired by C which are likely to panic +[panic_params](https://github.com/rust-lang-nursery/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` calls +[partialeq_ne_impl](https://github.com/rust-lang-nursery/rust-clippy/wiki#partialeq_ne_impl) | warn | re-implementing `PartialEq::ne` +[possible_missing_comma](https://github.com/rust-lang-nursery/rust-clippy/wiki#possible_missing_comma) | warn | possible missing comma in array +[precedence](https://github.com/rust-lang-nursery/rust-clippy/wiki#precedence) | warn | operations where precedence may be unclear +[print_stdout](https://github.com/rust-lang-nursery/rust-clippy/wiki#print_stdout) | allow | printing on stdout +[print_with_newline](https://github.com/rust-lang-nursery/rust-clippy/wiki#print_with_newline) | warn | using `print!()` with a format string that ends in a newline +[ptr_arg](https://github.com/rust-lang-nursery/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively +[pub_enum_variant_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#pub_enum_variant_names) | allow | enums where all variants share a prefix/postfix +[range_zip_with_len](https://github.com/rust-lang-nursery/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when `enumerate()` would do +[redundant_closure](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure) | warn | redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) +[redundant_closure_call](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure_call) | warn | throwaway closures called in the expression they are defined +[redundant_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern +[regex_macro](https://github.com/rust-lang-nursery/rust-clippy/wiki#regex_macro) | warn | use of `regex!(_)` instead of `Regex::new(_)` +[result_unwrap_used](https://github.com/rust-lang-nursery/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled +[reverse_range_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#reverse_range_loop) | warn | iteration over an empty range, such as `10..0` or `5..5` +[search_is_some](https://github.com/rust-lang-nursery/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` +[serde_api_misuse](https://github.com/rust-lang-nursery/rust-clippy/wiki#serde_api_misuse) | warn | various things that will negatively affect your serde experience +[shadow_reuse](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` +[shadow_same](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` +[shadow_unrelated](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_unrelated) | allow | rebinding a name without even using the original value +[short_circuit_statement](https://github.com/rust-lang-nursery/rust-clippy/wiki#short_circuit_statement) | warn | using a short circuit boolean condition as a statement +[should_assert_eq](https://github.com/rust-lang-nursery/rust-clippy/wiki#should_assert_eq) | warn | using `assert` macro for asserting equality +[should_implement_trait](https://github.com/rust-lang-nursery/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait +[similar_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#similar_names) | allow | similarly named items and bindings +[single_char_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` +[single_match](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let` +[single_match_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let` +[string_add](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String` instead of `push_str()` +[string_add_assign](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String` instead of `push_str()` +[string_extend_chars](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_extend_chars) | warn | using `x.extend(s.chars())` where s is a `&str` or `String` +[string_lit_as_bytes](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal instead of using a byte string literal +[stutter](https://github.com/rust-lang-nursery/rust-clippy/wiki#stutter) | allow | type names prefixed/postfixed with their containing module's name +[suspicious_assignment_formatting](https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` +[suspicious_else_formatting](https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` +[temporary_assignment](https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries +[temporary_cstring_as_ptr](https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_cstring_as_ptr) | warn | getting the inner pointer of a temporary `CString` +[too_many_arguments](https://github.com/rust-lang-nursery/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments +[toplevel_ref_arg](https://github.com/rust-lang-nursery/rust-clippy/wiki#toplevel_ref_arg) | warn | an entire binding declared as `ref`, in a function argument or a `let` statement +[transmute_ptr_to_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type +[trivial_regex](https://github.com/rust-lang-nursery/rust-clippy/wiki#trivial_regex) | warn | trivial regular expressions +[type_complexity](https://github.com/rust-lang-nursery/rust-clippy/wiki#type_complexity) | warn | usage of very complex types that might be better factored into `type` definitions +[unicode_not_nfc](https://github.com/rust-lang-nursery/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) +[unit_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#unit_cmp) | warn | comparing unit values +[unnecessary_cast](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_cast) | warn | cast to the same type, e.g. `x as i32` where `x: i32` +[unnecessary_mut_passed](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument passed as a mutable reference although the callee only demands an immutable reference +[unnecessary_operation](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_operation) | warn | outer expressions with no effect +[unneeded_field_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#unneeded_field_pattern) | warn | struct fields bound to a wildcard instead of using `..` +[unreadable_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#unreadable_literal) | warn | long integer literal without underscores +[unsafe_removed_from_name](https://github.com/rust-lang-nursery/rust-clippy/wiki#unsafe_removed_from_name) | warn | `unsafe` removed from API names on import +[unseparated_literal_suffix](https://github.com/rust-lang-nursery/rust-clippy/wiki#unseparated_literal_suffix) | allow | literals whose suffix is not separated by an underscore +[unused_collect](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop +[unused_io_amount](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_io_amount) | deny | unused written/read amount +[unused_label](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label) | warn | unused labels +[unused_lifetimes](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions +[use_debug](https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug) | allow | use of `Debug`-based formatting +[used_underscore_binding](https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore +[useless_attribute](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute) | warn | use of lint attributes on `extern crate` items +[useless_format](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format) | warn | useless use of `format!` +[useless_let_if_seq](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_let_if_seq) | warn | unidiomatic `let mut` declaration followed by initialization in `if` +[useless_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion +[useless_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_vec) | warn | useless `vec!` +[verbose_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#verbose_bit_mask) | warn | expressions where a bit mask is less readable than the corresponding method call +[while_let_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }`, which can be written as a `while let` loop +[while_let_on_iterator](https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator +[wrong_pub_self_convention](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_self_convention](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention +[wrong_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_transmute) | warn | transmutes that are confusing at best, undefined behaviour at worst and always useless +[zero_divided_by_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN +[zero_prefixed_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_prefixed_literal) | warn | integer literals starting with `0` +[zero_ptr](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_ptr) | warn | using 0 as *{const, mut} T +[zero_width_space](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing + +More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! ## License diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7614c048367..781d77d48d4 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -10,7 +10,7 @@ authors = [ "Martin Carton " ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" -repository = "https://github.com/Manishearth/rust-clippy" +repository = "https://github.com/rust-lang-nursery/rust-clippy" readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] diff --git a/clippy_lints/README.md b/clippy_lints/README.md index 5179690799c..b226cdea472 100644 --- a/clippy_lints/README.md +++ b/clippy_lints/README.md @@ -1,3 +1,3 @@ This crate contains Clippy lints. For the main crate, check [*cargo.io*](https://crates.io/crates/clippy) or -[GitHub](https://github.com/Manishearth/rust-clippy). +[GitHub](https://github.com/rust-lang-nursery/rust-clippy). diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 8f8bdf472a5..747a62d0585 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -67,7 +67,7 @@ declare_lint! { /// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). /// /// **Known problems:** False positive possible with order dependent `match` -/// (see issue [#860](https://github.com/Manishearth/rust-clippy/issues/860)). +/// (see issue [#860](https://github.com/rust-lang-nursery/rust-clippy/issues/860)). /// /// **Example:** /// ```rust,ignore diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 66cb5671c77..b9d371a1fad 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1072,7 +1072,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { /// will mistakenly imply that it is possible for `x` to be outside the range of /// `u8`. /// -/// **Known problems:** https://github.com/Manishearth/rust-clippy/issues/886 +/// **Known problems:** https://github.com/rust-lang-nursery/rust-clippy/issues/886 /// /// **Example:** /// ```rust diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index cdce1108be2..b4a9607a167 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -498,7 +498,7 @@ impl<'a> Drop for DiagnosticWrapper<'a> { impl<'a> DiagnosticWrapper<'a> { fn wiki_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { - self.0.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + self.0.help(&format!("for further information visit https://github.com/rust-lang-nursery/rust-clippy/wiki#{}", lint.name_lower())); } } diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml index f884ab48059..1b7dc04f7eb 100644 --- a/mini-macro/Cargo.toml +++ b/mini-macro/Cargo.toml @@ -10,7 +10,7 @@ authors = [ ] license = "MPL-2.0" description = "A macro to test clippy's procedural macro checks" -repository = "https://github.com/Manishearth/rust-clippy" +repository = "https://github.com/rust-lang-nursery/rust-clippy" [lib] name = "clippy_mini_macro_test" diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 0be34aa6f53..4a34b561d03 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -50,7 +50,7 @@ fn test_units() { } /// This test has [a link_with_underscores][chunked-example] inside it. See #823. -/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues) +/// See also [the issue tracker](https://github.com/rust-lang-nursery/rust-clippy/search?q=doc_markdown&type=Issues) /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. /// It can also be [inline_link2]. /// @@ -142,7 +142,7 @@ fn four_quotes() { /// See [NIST SP 800-56A, revision 2]. /// /// [NIST SP 800-56A, revision 2]: -/// https://github.com/Manishearth/rust-clippy/issues/902#issuecomment-261919419 +/// https://github.com/rust-lang-nursery/rust-clippy/issues/902#issuecomment-261919419 fn issue_902_comment() {} #[cfg_attr(feature = "a", doc = " ```")] diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 33c507ed82a..a9716d4e7b4 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -483,7 +483,7 @@ fn single_char_pattern() { // should have done this but produced an ICE // // We may not want to suggest changing these anyway - // See: https://github.com/Manishearth/rust-clippy/issues/650#issuecomment-184328984 + // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 x.split("ß"); x.split("ℝ"); x.split("💣"); diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index c1dd7958fff..e934c64023b 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -14,7 +14,7 @@ mod foo { } } -// No warning. See . +// No warning. See . mod bar { #[allow(module_inception)] mod bar { diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 04196eef396..2cac5c6bcde 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -94,7 +94,7 @@ - + diff --git a/util/update_lints.py b/util/update_lints.py index ddb5d3ab32f..9eeb02de9cc 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -29,7 +29,7 @@ declare_restriction_lint_re = re.compile(r''' nl_escape_re = re.compile(r'\\\n\s*') -wiki_link = 'https://github.com/Manishearth/rust-clippy/wiki' +wiki_link = 'https://github.com/rust-lang-nursery/rust-clippy/wiki' def collect(lints, deprecated_lints, restriction_lints, fn): -- cgit 1.4.1-3-g733a5 From 02f20353899fc061fa2a3f93a3202d0d00b673b3 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Mon, 7 Aug 2017 12:57:17 +0200 Subject: Docs index: Sort versions in a nice way This introduces a very sophisticated algorithm to determine the ordering of versions on the rendered docs' start page. (Spoiler alert: It maps "master" and "current" to the largest possible float values and converts a version like "1.2.3" to "1002003".) --- util/gh-pages/versions.html | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index baa44bf4676..310a3873691 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -34,9 +34,9 @@ @@ -54,6 +54,22 @@ .controller('docVersions', function ($scope, $http) { $scope.loading = true; + $scope.normalizeVersion = function(v) { + return v.replace(/^v/, ''); + }; + + $scope.versionOrder = function(v) { + if (v === 'master') { return Infinity; } + if (v === 'current') { return Number.MAX_VALUE; } + + return $scope.normalizeVersion(v) + .split('.') + .reverse() + .reduce(function(acc, val, index) { + return acc + (val * Math.pow(100, index)); + }, 0); + } + $http.get('./versions.json') .success(function (data) { $scope.data = data; -- cgit 1.4.1-3-g733a5 From 1d6adf210509b6efe8782035b2b73bdb41a764c9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 7 Aug 2017 13:34:36 +0200 Subject: Don't cache builds on travis --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97c702f63df..be682688177 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,6 @@ os: sudo: false -cache: - cargo: true - directories: - - target - env: global: # TRAVIS_TOKEN_CLIPPY_SERVICE -- cgit 1.4.1-3-g733a5 From ce80b23e09eb571802faff2f15ca3876b5bc1044 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 7 Aug 2017 17:33:27 +0200 Subject: Update CONTRIBUTING.md --- CONTRIBUTING.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 71a54d85249..e100f09ffe2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,16 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lin ## Getting started -All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth or @llogiq. +High level approach: + +1. Find something to fix/improve +2. Change code (likely some file in `clippy_lints/src/`) +3. Run `cargo test` in the root directory and wiggle code until it passes +4. Open a PR (also can be done between 2. and 3. if you run into problems) + +### Finding something to fix/improve + +All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. Some issues are easier than others. The [E-easy](https://github.com/Manishearth/rust-clippy/labels/E-easy) label can be used to find the easy issues. If you want to work on an issue, please leave a comment @@ -16,7 +25,8 @@ matching of the syntax tree structure, and are generally easier than and resolved paths. Issues marked [E-medium](https://github.com/Manishearth/rust-clippy/labels/E-medium) are generally -pretty easy too, though it's recommended you work on an E-easy issue first. +pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified +as `E-medium`, since they might be somewhat involved code wise, but not difficult per-se. [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of @@ -35,16 +45,14 @@ T-middle issues can be more involved and require verifying types. The lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. +### Writing code + Compiling clippy can take almost a minute or more depending on your machine. You can set the environment flag `CARGO_INCREMENTAL=1` to cut down that time to almost a third on average, depending on the influence your change has. -Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. -Of course there's little sense in writing the output yourself or copying it around. -Therefore you can simply run `tests/ui/update-all-references.sh` and check whether -the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +Please document your lint with a doc comment akin to the following: -Also please document your lint with a doc comment akin to the following: ```rust /// **What it does:** Checks for ... (describe what the lint matches). /// @@ -58,7 +66,12 @@ Also please document your lint with a doc comment akin to the following: /// ``` ``` -Our `util/update_wiki.py` script can then add your lint docs to the wiki. +### Running test suite + +Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. +Of course there's little sense in writing the output yourself or copying it around. +Therefore you can simply run `tests/ui/update-all-references.sh` and check whether +the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. ## Contributions -- cgit 1.4.1-3-g733a5 From 709c7926d4d48ee0d5254c28be700fc64ba8d98b Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Wed, 9 Aug 2017 13:21:33 +1000 Subject: fix usage of for_each_relevant_impl --- clippy_lints/src/derive.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f6642db8fec..5ac4a342274 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -95,10 +95,8 @@ fn check_hash_peq<'a, 'tcx>( match_path_old(&trait_ref.path, &paths::HASH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() ], { - let peq_trait_def = cx.tcx.trait_def(peq_trait_def_id); - // Look for the PartialEq implementations for `ty` - peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| { + cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); if peq_is_automatically_derived == hash_is_automatically_derived { -- cgit 1.4.1-3-g733a5 From 61a73bb630d1f125b407e6d331fd0200ed6b9d30 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 13 Aug 2017 00:14:28 +0200 Subject: some small doc improvements --- clippy_lints/src/len_zero.rs | 7 ++++--- clippy_lints/src/returns.rs | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 3a88c53d61d..9b76986dbcc 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -10,9 +10,10 @@ use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, wal /// just to compare to zero, and suggests using `.is_empty()` where applicable. /// /// **Why is this bad?** Some structures can answer `.is_empty()` much faster -/// than calculating their length. So it is good to get into the habit of using -/// `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer -/// than a comparison. +/// than calculating their length. Notably, for slices, getting the length +/// requires a subtraction whereas `.is_empty()` is just a comparison. So it is +/// good to get into the habit of using `.is_empty()`, and having it is cheap. +/// Besides, it makes the intent clearer than a manual comparison. /// /// **Known problems:** None. /// diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index acd60ba2f46..41601a80890 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -10,7 +10,8 @@ use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, /// **Why is this bad?** Removing the `return` and semicolon will make the code /// more rusty. /// -/// **Known problems:** None. +/// **Known problems:** If the computation returning the value borrows a local +/// variable, removing the `return` may run afoul of the borrow checker. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 705c6ec2a4bfe3beeb802e51d9b8247b33a62997 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 9 Aug 2017 08:57:31 +0200 Subject: Bump the version --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c145618db99..8c72ac8686f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.150 +* Update to *rustc 1.21.0-nightly (215e0b10e 2017-08-08)* + ## 0.0.148 * Update to *rustc 1.21.0-nightly (37c7d0ebb 2017-07-31)* * New lints: [`unreadable_literal`], [`inconsisten_digit_grouping`], [`large_digit_groups`] diff --git a/Cargo.toml b/Cargo.toml index ef54f15239e..a5c615e232c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.149" +version = "0.0.150" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.149", path = "clippy_lints" } +clippy_lints = { version = "0.0.150", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7614c048367..5072175d99c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.149" +version = "0.0.150" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From b25b6b3355efa33c797f4a37afb2f516531ad581 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 9 Aug 2017 09:30:56 +0200 Subject: Rustfmt --- clippy_lints/src/approx_const.rs | 58 +-- clippy_lints/src/array_indexing.rs | 58 ++- clippy_lints/src/assign_ops.rs | 81 ++-- clippy_lints/src/attrs.rs | 62 +-- clippy_lints/src/bit_mask.rs | 137 ++++--- clippy_lints/src/blacklisted_name.rs | 10 +- clippy_lints/src/block_in_if_condition.rs | 35 +- clippy_lints/src/booleans.rs | 75 ++-- clippy_lints/src/collapsible_if.rs | 5 +- clippy_lints/src/consts.rs | 3 +- clippy_lints/src/copies.rs | 93 +++-- clippy_lints/src/cyclomatic_complexity.rs | 75 ++-- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc.rs | 52 ++- clippy_lints/src/drop_forget_ref.rs | 18 +- clippy_lints/src/empty_enum.rs | 9 +- clippy_lints/src/entry.rs | 14 +- clippy_lints/src/enum_clike.rs | 17 +- clippy_lints/src/enum_glob_use.rs | 9 +- clippy_lints/src/enum_variants.rs | 48 ++- clippy_lints/src/eq_op.rs | 59 +-- clippy_lints/src/escape.rs | 12 +- clippy_lints/src/eta_reduction.rs | 15 +- clippy_lints/src/eval_order_dependence.rs | 17 +- clippy_lints/src/format.rs | 6 +- clippy_lints/src/formatting.rs | 88 +++-- clippy_lints/src/functions.rs | 32 +- clippy_lints/src/identity_op.rs | 19 +- .../src/if_let_redundant_pattern_matching.rs | 6 +- clippy_lints/src/if_not_else.rs | 27 +- clippy_lints/src/items_after_statements.rs | 19 +- clippy_lints/src/large_enum_variant.rs | 64 ++-- clippy_lints/src/len_zero.rs | 84 +++-- clippy_lints/src/let_if_seq.rs | 4 +- clippy_lints/src/lifetimes.rs | 27 +- clippy_lints/src/literal_digit_grouping.rs | 45 ++- clippy_lints/src/loops.rs | 337 ++++++++++------- clippy_lints/src/map_clone.rs | 30 +- clippy_lints/src/matches.rs | 211 ++++++----- clippy_lints/src/mem_forget.rs | 6 +- clippy_lints/src/methods.rs | 401 +++++++++++--------- clippy_lints/src/misc.rs | 174 +++++---- clippy_lints/src/misc_early.rs | 112 +++--- clippy_lints/src/missing_doc.rs | 45 ++- clippy_lints/src/mut_mut.rs | 39 +- clippy_lints/src/mut_reference.rs | 22 +- clippy_lints/src/mutex_atomic.rs | 12 +- clippy_lints/src/needless_bool.rs | 97 +++-- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 6 +- clippy_lints/src/needless_continue.rs | 125 ++++--- clippy_lints/src/needless_pass_by_value.rs | 29 +- clippy_lints/src/needless_update.rs | 10 +- clippy_lints/src/new_without_default.rs | 12 +- clippy_lints/src/no_effect.rs | 41 +- clippy_lints/src/non_expressive_names.rs | 101 +++-- clippy_lints/src/ok_if_let.rs | 3 +- clippy_lints/src/open_options.rs | 65 ++-- clippy_lints/src/precedence.rs | 66 ++-- clippy_lints/src/print.rs | 6 +- clippy_lints/src/ptr.rs | 78 ++-- clippy_lints/src/ranges.rs | 15 +- clippy_lints/src/reference.rs | 14 +- clippy_lints/src/regex.rs | 47 ++- clippy_lints/src/returns.rs | 15 +- clippy_lints/src/serde_api.rs | 13 +- clippy_lints/src/shadow.rs | 92 +++-- clippy_lints/src/should_assert_eq.rs | 9 +- clippy_lints/src/strings.rs | 42 ++- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/transmute.rs | 147 ++++---- clippy_lints/src/types.rs | 415 ++++++++++++--------- clippy_lints/src/unicode.rs | 55 +-- clippy_lints/src/unsafe_removed_from_name.rs | 26 +- clippy_lints/src/unused_io_amount.rs | 29 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/utils/author.rs | 46 ++- clippy_lints/src/utils/comparisons.rs | 3 +- clippy_lints/src/utils/conf.rs | 39 +- clippy_lints/src/utils/constants.rs | 19 +- clippy_lints/src/utils/higher.rs | 15 +- clippy_lints/src/utils/hir_utils.rs | 59 +-- clippy_lints/src/utils/inspector.rs | 43 ++- clippy_lints/src/utils/internal_lints.rs | 46 ++- clippy_lints/src/utils/mod.rs | 212 +++++++---- clippy_lints/src/utils/paths.rs | 3 +- clippy_lints/src/utils/sugg.rs | 62 ++- clippy_lints/src/vec.rs | 19 +- clippy_lints/src/zero_div_zero.rs | 3 +- src/main.rs | 159 ++++---- tests/compile-test.rs | 6 +- tests/dogfood.rs | 4 +- tests/issue-825.rs | 7 +- tests/matches.rs | 34 +- tests/needless_continue_helpers.rs | 1 - 95 files changed, 3093 insertions(+), 2025 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 7093e18454f..cbe12e58119 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -7,9 +7,11 @@ use utils::span_lint; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in -/// [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) +/// [`std::f32::consts`](https://doc.rust-lang. +/// org/stable/std/f32/consts/#constants) /// or -/// [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), +/// [`std::f64::consts`](https://doc.rust-lang. +/// org/stable/std/f64/consts/#constants), /// respectively, suggesting to use the predefined constant. /// /// **Why is this bad?** Usually, the definition in the standard library is more @@ -33,24 +35,26 @@ declare_lint! { } // Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), - (f64::FRAC_1_PI, "FRAC_1_PI", 4), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), - (f64::FRAC_2_PI, "FRAC_2_PI", 5), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), - (f64::FRAC_PI_2, "FRAC_PI_2", 5), - (f64::FRAC_PI_3, "FRAC_PI_3", 5), - (f64::FRAC_PI_4, "FRAC_PI_4", 5), - (f64::FRAC_PI_6, "FRAC_PI_6", 5), - (f64::FRAC_PI_8, "FRAC_PI_8", 5), - (f64::LN_10, "LN_10", 5), - (f64::LN_2, "LN_2", 5), - (f64::LOG10_E, "LOG10_E", 5), - (f64::LOG2_E, "LOG2_E", 5), - (f64::PI, "PI", 3), - (f64::SQRT_2, "SQRT_2", 5)]; +const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[ + (f64::E, "E", 4), + (f64::FRAC_1_PI, "FRAC_1_PI", 4), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), + (f64::FRAC_2_PI, "FRAC_2_PI", 5), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), + (f64::FRAC_PI_2, "FRAC_PI_2", 5), + (f64::FRAC_PI_3, "FRAC_PI_3", 5), + (f64::FRAC_PI_4, "FRAC_PI_4", 5), + (f64::FRAC_PI_6, "FRAC_PI_6", 5), + (f64::FRAC_PI_8, "FRAC_PI_8", 5), + (f64::LN_10, "LN_10", 5), + (f64::LN_2, "LN_2", 5), + (f64::LOG10_E, "LOG10_E", 5), + (f64::LOG2_E, "LOG2_E", 5), + (f64::PI, "PI", 3), + (f64::SQRT_2, "SQRT_2", 5), +]; -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct Pass; impl LintPass for Pass { @@ -81,13 +85,17 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &symbol::Symbol, module: &s if s.parse::().is_ok() { for &(constant, name, min_digits) in KNOWN_CONSTS { if is_approx_const(constant, &s, min_digits) { - span_lint(cx, - APPROX_CONSTANT, - e.span, - &format!("approximate value of `{}::consts::{}` found. \ + span_lint( + cx, + APPROX_CONSTANT, + e.span, + &format!( + "approximate value of `{}::consts::{}` found. \ Consider using it directly", - module, - &name)); + module, + &name + ), + ); return; } } diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index baac8d790ba..422935fa067 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -8,7 +8,8 @@ use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; -/// **What it does:** Checks for out of bounds array indexing with a constant index. +/// **What it does:** Checks for out of bounds array indexing with a constant +/// index. /// /// **Why is this bad?** This will always panic at runtime. /// @@ -46,7 +47,7 @@ declare_restriction_lint! { "indexing/slicing usage" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct ArrayIndexing; impl LintPass for ArrayIndexing { @@ -61,8 +62,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, size) = ty.sty { - let size = ConstInt::Usize(ConstUsize::new(size as u64, cx.sess().target.uint_type) - .expect("array size is invalid")); + let size = ConstInt::Usize( + ConstUsize::new(size as u64, cx.sess().target.uint_type).expect("array size is invalid"), + ); let parent_item = cx.tcx.hir.get_parent(e.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); @@ -80,12 +82,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Index is a constant range if let Some(range) = higher::range(index) { - let start = range.start - .map(|start| constcx.eval(start)) - .map(|v| v.ok()); - let end = range.end - .map(|end| constcx.eval(end)) - .map(|v| v.ok()); + let start = range.start.map(|start| constcx.eval(start)).map(|v| v.ok()); + let end = range.end.map(|end| constcx.eval(end)).map(|v| v.ok()); if let Some((start, end)) = to_const_range(&start, &end, range.limits, size) { if start > size || end > size { @@ -111,12 +109,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { } } -/// Returns an option containing a tuple with the start and end (exclusive) of the range. +/// Returns an option containing a tuple with the start and end (exclusive) of +/// the range. fn to_const_range( start: &Option>, end: &Option>, limits: RangeLimits, - array_size: ConstInt + array_size: ConstInt, ) -> Option<(ConstInt, ConstInt)> { let start = match *start { Some(Some(ConstVal::Integral(x))) => x, @@ -128,24 +127,23 @@ fn to_const_range( Some(Some(ConstVal::Integral(x))) => { if limits == RangeLimits::Closed { match x { - ConstInt::U8(_) => (x + ConstInt::U8(1)), - ConstInt::U16(_) => (x + ConstInt::U16(1)), - ConstInt::U32(_) => (x + ConstInt::U32(1)), - ConstInt::U64(_) => (x + ConstInt::U64(1)), - ConstInt::U128(_) => (x + ConstInt::U128(1)), - ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), - ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), - ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), - ConstInt::I8(_) => (x + ConstInt::I8(1)), - ConstInt::I16(_) => (x + ConstInt::I16(1)), - ConstInt::I32(_) => (x + ConstInt::I32(1)), - ConstInt::I64(_) => (x + ConstInt::I64(1)), - ConstInt::I128(_) => (x + ConstInt::I128(1)), - ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), - ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), - ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), - } - .expect("such a big array is not realistic") + ConstInt::U8(_) => (x + ConstInt::U8(1)), + ConstInt::U16(_) => (x + ConstInt::U16(1)), + ConstInt::U32(_) => (x + ConstInt::U32(1)), + ConstInt::U64(_) => (x + ConstInt::U64(1)), + ConstInt::U128(_) => (x + ConstInt::U128(1)), + ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), + ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), + ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), + ConstInt::I8(_) => (x + ConstInt::I8(1)), + ConstInt::I16(_) => (x + ConstInt::I16(1)), + ConstInt::I32(_) => (x + ConstInt::I32(1)), + ConstInt::I64(_) => (x + ConstInt::I64(1)), + ConstInt::I128(_) => (x + ConstInt::I128(1)), + ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), + ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), + ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), + }.expect("such a big array is not realistic") } else { x } diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 07d838bef2e..759bb9f12ec 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -4,12 +4,14 @@ use syntax::ast; use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; use utils::{higher, sugg}; -/// **What it does:** Checks for compound assignment operations (`+=` and similar). +/// **What it does:** Checks for compound assignment operations (`+=` and +/// similar). /// /// **Why is this bad?** Projects with many developers from languages without /// those operations may find them unreadable and not worth their weight. /// -/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`. +/// **Known problems:** Types implementing `OpAssign` don't necessarily +/// implement `Op`. /// /// **Example:** /// ```rust @@ -20,7 +22,8 @@ declare_restriction_lint! { "any compound assignment operation" } -/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` patterns. +/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` +/// patterns. /// /// **Why is this bad?** These can be written as the shorter `a op= b`. /// @@ -41,7 +44,8 @@ declare_lint! { /// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns. /// -/// **Why is this bad?** Most likely these are bugs where one meant to write `a op= b`. +/// **Why is this bad?** Most likely these are bugs where one meant to write `a +/// op= b`. /// /// **Known problems:** Someone might actually mean `a op= a op b`, but that /// should rather be written as `a = (2 * a) op b` where applicable. @@ -75,9 +79,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let lhs = &sugg::Sugg::hir(cx, lhs, ".."); let rhs = &sugg::Sugg::hir(cx, rhs, ".."); - db.span_suggestion(expr.span, - "replace it with", - format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs))); + db.span_suggestion( + expr.span, + "replace it with", + format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)), + ); }); if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { @@ -144,35 +150,40 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } } } - if ops!(op.node, + if ops!( + op.node, + cx, + ty, + rty, + Add: BiAdd, + Sub: BiSub, + Mul: BiMul, + Div: BiDiv, + Rem: BiRem, + And: BiAnd, + Or: BiOr, + BitAnd: BiBitAnd, + BitOr: BiBitOr, + BitXor: BiBitXor, + Shr: BiShr, + Shl: BiShl + ) + { + span_lint_and_then( cx, - ty, - rty, - Add: BiAdd, - Sub: BiSub, - Mul: BiMul, - Div: BiDiv, - Rem: BiRem, - And: BiAnd, - Or: BiOr, - BitAnd: BiBitAnd, - BitOr: BiBitOr, - BitXor: BiBitXor, - Shr: BiShr, - Shl: BiShl) { - span_lint_and_then(cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation", - |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - db.span_suggestion(expr.span, - "replace it with", - format!("{} {}= {}", - snip_a, - op.node.as_str(), - snip_r)); - }); + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |db| if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + db.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + ); + }, + ); } }; // a = a op b diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 88f0ef0955c..a52c4d90aab 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -35,12 +35,15 @@ declare_lint! { "use of `#[inline(always)]`" } -/// **What it does:** Checks for `extern crate` and `use` items annotated with lint attributes +/// **What it does:** Checks for `extern crate` and `use` items annotated with +/// lint attributes /// -/// **Why is this bad?** Lint attributes have no effect on crate imports. Most likely a `!` was +/// **Why is this bad?** Lint attributes have no effect on crate imports. Most +/// likely a `!` was /// forgotten /// -/// **Known problems:** Technically one might allow `unused_import` on a `use` item, +/// **Known problems:** Technically one might allow `unused_import` on a `use` +/// item, /// but it's easier to remove the unused item. /// /// **Example:** @@ -75,7 +78,7 @@ declare_lint! { "use of `#[deprecated(since = \"x\")]` where x is not semver" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct AttrPass; impl LintPass for AttrPass { @@ -124,14 +127,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } if let Some(mut sugg) = snippet_opt(cx, attr.span) { if sugg.len() > 1 { - span_lint_and_then(cx, - USELESS_ATTRIBUTE, - attr.span, - "useless lint attribute", - |db| { - sugg.insert(1, '!'); - db.span_suggestion(attr.span, "if you just forgot a `!`, use", sugg); - }); + span_lint_and_then( + cx, + USELESS_ATTRIBUTE, + attr.span, + "useless lint attribute", + |db| { + sugg.insert(1, '!'); + db.span_suggestion( + attr.span, + "if you just forgot a `!`, use", + sugg, + ); + }, + ); } } }, @@ -191,7 +200,10 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), } } else { - block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) + block.expr.as_ref().map_or( + false, + |e| is_relevant_expr(tcx, tables, e), + ) } } @@ -224,11 +236,15 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { continue; } if is_word(&values[0], "always") { - span_lint(cx, - INLINE_ALWAYS, - attr.span, - &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea", - name)); + span_lint( + cx, + INLINE_ALWAYS, + attr.span, + &format!( + "you have declared `#[inline(always)]` on `{}`. This is usually a bad idea", + name + ), + ); } } } @@ -240,10 +256,12 @@ fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { return; } } - span_lint(cx, - DEPRECATED_SEMVER, - span, - "the since field must contain a semver-compliant version"); + span_lint( + cx, + DEPRECATED_SEMVER, + span, + "the since field must contain a semver-compliant version", + ); } fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index f56c0b2aeb3..64f007bf521 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -74,7 +74,8 @@ declare_lint! { /// **What it does:** Checks for bit masks that can be replaced by a call /// to `trailing_zeros` /// -/// **Why is this bad?** `x.trailing_zeros() > 4` is much clearer than `x & 15 == 0` +/// **Why is this bad?** `x.trailing_zeros() > 4` is much clearer than `x & 15 +/// == 0` /// /// **Known problems:** llvm generates better code for `x & 15 == 0` on x86 /// @@ -88,7 +89,7 @@ declare_lint! { "expressions where a bit mask is less readable than the corresponding method call" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct BitMask; impl LintPass for BitMask { @@ -162,12 +163,16 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: BiBitAnd => { if mask_value & cmp_value != cmp_value { if cmp_value != 0 { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); } } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); @@ -175,12 +180,16 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: }, BiBitOr => { if mask_value | cmp_value != cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); } }, _ => (), @@ -190,24 +199,32 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: match bit_op { BiBitAnd => { if mask_value < cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, + cmp_value + ), + ); } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } }, BiBitOr => { if mask_value >= cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, + cmp_value + ), + ); } else { check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); } @@ -220,24 +237,32 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: match bit_op { BiBitAnd => { if mask_value <= cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, + cmp_value + ), + ); } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); } }, BiBitOr => { if mask_value > cmp_value { - span_lint(cx, - BAD_BIT_MASK, - *span, - &format!("incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, - cmp_value)); + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, + cmp_value + ), + ); } else { check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); } @@ -252,25 +277,33 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { if c.is_power_of_two() && m < c { - span_lint(cx, - INEFFECTIVE_BIT_MASK, - span, - &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c)); + span_lint( + cx, + INEFFECTIVE_BIT_MASK, + span, + &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c + ), + ); } } fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { if (c + 1).is_power_of_two() && m <= c { - span_lint(cx, - INEFFECTIVE_BIT_MASK, - span, - &format!("ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c)); + span_lint( + cx, + INEFFECTIVE_BIT_MASK, + span, + &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, + m, + c + ), + ); } } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index f8f0ea998bc..e88e4108d3d 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -41,10 +41,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(_, _, ref ident, _) = pat.node { if self.blacklist.iter().any(|s| ident.node == *s) { - span_lint(cx, - BLACKLISTED_NAME, - ident.span, - &format!("use of a blacklisted/placeholder name `{}`", ident.node)); + span_lint( + cx, + BLACKLISTED_NAME, + ident.span, + &format!("use of a blacklisted/placeholder name `{}`", ident.node), + ); } } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 6c0523dc198..eea44393e3d 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -40,7 +40,7 @@ declare_lint! { "complex blocks in conditions, e.g. `if { let x = true; x } ...`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct BlockInIfCondition; impl LintPass for BlockInIfCondition { @@ -87,27 +87,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { if in_macro(expr.span) || differing_macro_contexts(expr.span, ex.span) { return; } - span_help_and_lint(cx, - BLOCK_IN_IF_CONDITION_EXPR, - check.span, - BRACED_EXPR_MESSAGE, - &format!("try\nif {} {} ... ", + span_help_and_lint( + cx, + BLOCK_IN_IF_CONDITION_EXPR, + check.span, + BRACED_EXPR_MESSAGE, + &format!("try\nif {} {} ... ", snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, ".."))); + snippet_block(cx, then.span, "..")), + ); } } else { - let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); + let span = block.expr.as_ref().map_or_else( + || block.stmts[0].span, + |e| e.span, + ); if in_macro(span) || differing_macro_contexts(expr.span, span) { return; } // move block higher - span_help_and_lint(cx, - BLOCK_IN_IF_CONDITION_STMT, - check.span, - COMPLEX_BLOCK_MESSAGE, - &format!("try\nlet res = {};\nif res {} ... ", + span_help_and_lint( + cx, + BLOCK_IN_IF_CONDITION_STMT, + check.span, + COMPLEX_BLOCK_MESSAGE, + &format!("try\nlet res = {};\nif res {} ... ", snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, ".."))); + snippet_block(cx, then.span, "..")), + ); } } } else { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index c338189cefe..4c67b260046 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -44,7 +44,7 @@ declare_lint! { "boolean expressions that contain terminals which can be eliminated" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NonminimalBool; impl LintPass for NonminimalBool { @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { _: &'tcx FnDecl, body: &'tcx Body, _: Span, - _: NodeId + _: NodeId, ) { NonminimalBoolVisitor { cx: cx }.visit_body(body) } @@ -115,8 +115,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } for (n, expr) in self.terminals.iter().enumerate() { if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { - #[allow(cast_possible_truncation)] - return Ok(Bool::Term(n as u8)); + #[allow(cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { @@ -141,15 +140,13 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { _ => continue, }; if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { - #[allow(cast_possible_truncation)] - return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + #[allow(cast_possible_truncation)] return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); } } let n = self.terminals.len(); self.terminals.push(e); if n < 32 { - #[allow(cast_possible_truncation)] - Ok(Bool::Term(n as u8)) + #[allow(cast_possible_truncation)] Ok(Bool::Term(n as u8)) } else { Err("too many literals".to_owned()) } @@ -353,44 +350,54 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { continue 'simplified; } if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { - span_lint_and_then(self.cx, - LOGIC_BUG, - e.span, - "this boolean expression contains a logic bug", - |db| { - db.span_help(h2q.terminals[i].span, - "this expression can be optimized out by applying boolean operations to the \ - outer expression"); - db.span_suggestion(e.span, - "it would look like the following", - suggest(self.cx, suggestion, &h2q.terminals)); - }); + span_lint_and_then( + self.cx, + LOGIC_BUG, + e.span, + "this boolean expression contains a logic bug", + |db| { + db.span_help( + h2q.terminals[i].span, + "this expression can be optimized out by applying boolean operations to the \ + outer expression", + ); + db.span_suggestion( + e.span, + "it would look like the following", + suggest(self.cx, suggestion, &h2q.terminals), + ); + }, + ); // don't also lint `NONMINIMAL_BOOL` return; } // if the number of occurrences of a terminal decreases or any of the stats // decreases while none increases improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || - (stats.negations > simplified_stats.negations && - stats.ops == simplified_stats.ops) || - (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); + (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || + (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); } if improvement { improvements.push(suggestion); } } if !improvements.is_empty() { - span_lint_and_then(self.cx, - NONMINIMAL_BOOL, - e.span, - "this boolean expression can be simplified", - |db| { - db.span_suggestions(e.span, - "try", - improvements.into_iter() - .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals)) - .collect()); - }); + span_lint_and_then( + self.cx, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + db.span_suggestions( + e.span, + "try", + improvements + .into_iter() + .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals)) + .collect(), + ); + }, + ); } } } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 1178f98db59..54b6490a183 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -19,7 +19,8 @@ use utils::{in_macro, snippet_block, span_lint_and_then, span_lint_and_sugg}; use utils::sugg::Sugg; /// **What it does:** Checks for nested `if` statements which can be collapsed -/// by `&&`-combining their conditions and for `else { if ... }` expressions that +/// by `&&`-combining their conditions and for `else { if ... }` expressions +/// that /// can be collapsed to `else if ...`. /// /// **Why is this bad?** Each `if`-statement adds one level of nesting, which @@ -67,7 +68,7 @@ declare_lint! { "`if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`)" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct CollapsibleIf; impl LintPass for CollapsibleIf { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 54b297d588d..095fcf06e09 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -83,7 +83,8 @@ impl PartialEq for Constant { impl Hash for Constant { fn hash(&self, state: &mut H) - where H: Hasher + where + H: Hasher, { match *self { Constant::Str(ref s, ref k) => { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 8f8bdf472a5..8a37c7a846d 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -138,12 +138,14 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same(blocks, hash, eq) { - span_note_and_lint(cx, - IF_SAME_THEN_ELSE, - j.span, - "this `if` has identical blocks", - i.span, - "same as this"); + span_note_and_lint( + cx, + IF_SAME_THEN_ELSE, + j.span, + "this `if` has identical blocks", + i.span, + "same as this", + ); } } @@ -158,12 +160,14 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; if let Some((i, j)) = search_same(conds, hash, eq) { - span_note_and_lint(cx, - IFS_SAME_COND, - j.span, - "this `if` has the same condition as a previous if", - i.span, - "same as this"); + span_note_and_lint( + cx, + IFS_SAME_COND, + j.span, + "this `if` has the same condition as a previous if", + i.span, + "same as this", + ); } } @@ -185,40 +189,48 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { if let Some((i, j)) = search_same(arms, hash, eq) { - span_lint_and_then(cx, - MATCH_SAME_ARMS, - j.body.span, - "this `match` has identical arm bodies", - |db| { - db.span_note(i.body.span, "same as this"); + span_lint_and_then( + cx, + MATCH_SAME_ARMS, + j.body.span, + "this `match` has identical arm bodies", + |db| { + db.span_note(i.body.span, "same as this"); - // Note: this does not use `span_suggestion` on purpose: there is no clean way to - // remove the other arm. Building a span and suggest to replace it to "" makes an - // even more confusing error message. Also in order not to make up a span for the - // whole pattern, the suggestion is only shown when there is only one pattern. The - // user should know about `|` if they are already using it… + // Note: this does not use `span_suggestion` on purpose: there is no clean way + // to + // remove the other arm. Building a span and suggest to replace it to "" makes + // an + // even more confusing error message. Also in order not to make up a span for + // the + // whole pattern, the suggestion is only shown when there is only one pattern. + // The + // user should know about `|` if they are already using it… - if i.pats.len() == 1 && j.pats.len() == 1 { - let lhs = snippet(cx, i.pats[0].span, ""); - let rhs = snippet(cx, j.pats[0].span, ""); + if i.pats.len() == 1 && j.pats.len() == 1 { + let lhs = snippet(cx, i.pats[0].span, ""); + let rhs = snippet(cx, j.pats[0].span, ""); - if let PatKind::Wild = j.pats[0].node { - // if the last arm is _, then i could be integrated into _ - // note that i.pats[0] cannot be _, because that would mean that we're - // hiding all the subsequent arms, and rust won't compile - db.span_note(i.body.span, - &format!("`{}` has the same arm body as the `_` wildcard, consider removing it`", - lhs)); - } else { - db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs)); + if let PatKind::Wild = j.pats[0].node { + // if the last arm is _, then i could be integrated into _ + // note that i.pats[0] cannot be _, because that would mean that we're + // hiding all the subsequent arms, and rust won't compile + db.span_note( + i.body.span, + &format!("`{}` has the same arm body as the `_` wildcard, consider removing it`", lhs), + ); + } else { + db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs)); + } } - } - }); + }, + ); } } } -/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`. +/// Return the list of condition expressions and the list of blocks in a +/// sequence of `if/else`. /// Eg. would return `([a, b], [c, d, e])` for the expression /// `if a { c } else if b { d } else { e }`. fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { @@ -303,8 +315,9 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> - where Hash: Fn(&T) -> u64, - Eq: Fn(&T, &T) -> bool +where + Hash: Fn(&T) -> u64, + Eq: Fn(&T, &T) -> bool, { // common cases if exprs.len() < 2 { diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index ffb240d3ab4..e87e60f9d23 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -15,7 +15,8 @@ use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; /// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly /// readable. Also LLVM will usually optimize small methods better. /// -/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity. +/// **Known problems:** Sometimes it's hard to find a way to reduce the +/// complexity. /// /// **Example:** No. You'll see it when you get the warning. declare_lint! { @@ -63,7 +64,13 @@ impl CyclomaticComplexity { cx: cx, }; helper.visit_expr(expr); - let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; + let CCHelper { + match_arms, + divergence, + short_circuits, + returns, + .. + } = helper; let ret_ty = cx.tables.node_id_to_type(expr.id); let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { returns @@ -80,11 +87,13 @@ impl CyclomaticComplexity { rust_cc -= ret_adjust; } if rust_cc > self.limit.limit() { - span_help_and_lint(cx, - CYCLOMATIC_COMPLEXITY, - span, - &format!("the function has a cyclomatic complexity of {}", rust_cc), - "you could split it up into multiple smaller functions"); + span_help_and_lint( + cx, + CYCLOMATIC_COMPLEXITY, + span, + &format!("the function has a cyclomatic complexity of {}", rust_cc), + "you could split it up into multiple smaller functions", + ); } } } @@ -98,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { _: &'tcx FnDecl, body: &'tcx Body, span: Span, - node_id: NodeId + node_id: NodeId, ) { let def_id = cx.tcx.hir.local_def_id(node_id); if !cx.tcx.has_attr(def_id, "test") { @@ -107,10 +116,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { } fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + self.limit.push_attrs( + cx.sess(), + attrs, + "cyclomatic_complexity", + ); } fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + self.limit.pop_attrs( + cx.sess(), + attrs, + "cyclomatic_complexity", + ); } } @@ -162,29 +179,35 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { } } -#[cfg(feature="debugging")] +#[cfg(feature = "debugging")] fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { - span_bug!(span, - "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ + span_bug!( + span, + "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ div = {}, shorts = {}, returns = {}. Please file a bug report.", - cc, - narms, - div, - shorts, - returns); + cc, + narms, + div, + shorts, + returns + ); } -#[cfg(not(feature="debugging"))] +#[cfg(not(feature = "debugging"))] fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { - cx.sess().span_note_without_error(span, - &format!("Clippy encountered a bug calculating cyclomatic complexity \ + cx.sess().span_note_without_error( + span, + &format!( + "Clippy encountered a bug calculating cyclomatic complexity \ (hide this message with `#[allow(cyclomatic_complexity)]`): \ cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ Please file a bug report.", - cc, - narms, - div, - shorts, - returns)); + cc, + narms, + div, + shorts, + returns + ), + ); } } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 5ac4a342274..e186dd5e4db 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -89,7 +89,7 @@ fn check_hash_peq<'a, 'tcx>( span: Span, trait_ref: &TraitRef, ty: Ty<'tcx>, - hash_is_automatically_derived: bool + hash_is_automatically_derived: bool, ) { if_let_chain! {[ match_path_old(&trait_ref.path, &paths::HASH), diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 46c3bd51068..3ca71694bbd 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -19,7 +19,8 @@ use utils::span_lint; /// /// **Examples:** /// ```rust -/// /// Do something with the foo_bar parameter. See also that::other::module::foo. +/// /// Do something with the foo_bar parameter. See also +/// that::other::module::foo. /// // ^ `foo_bar` and `that::other::module::foo` should be ticked. /// fn doit(foo_bar) { .. } /// ``` @@ -78,7 +79,8 @@ impl<'a> Iterator for Parser<'a> { /// Cleanup documentation decoration (`///` and such). /// /// We can't use `syntax::attr::AttributeMethods::with_desugared_doc` or -/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we need to keep track of +/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we +/// need to keep track of /// the spans but this function is inspired from the later. #[allow(cast_possible_truncation)] pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(usize, Span)>) { @@ -89,7 +91,18 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( let doc = &comment[prefix.len()..]; let mut doc = doc.to_owned(); doc.push('\n'); - return (doc.to_owned(), vec![(doc.len(), Span { lo: span.lo + BytePos(prefix.len() as u32), ..span })]); + return ( + doc.to_owned(), + vec![ + ( + doc.len(), + Span { + lo: span.lo + BytePos(prefix.len() as u32), + ..span + } + ), + ], + ); } } @@ -102,7 +115,13 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( debug_assert_eq!(offset as u32 as usize, offset); // +1 for the newline - sizes.push((line.len() + 1, Span { lo: span.lo + BytePos(offset as u32), ..span })); + sizes.push(( + line.len() + 1, + Span { + lo: span.lo + BytePos(offset as u32), + ..span + }, + )); } return (doc.to_string(), sizes); @@ -163,7 +182,7 @@ fn check_doc<'a, Events: Iterator)>>( cx: &EarlyContext, valid_idents: &[String], docs: Events, - spans: &[(usize, Span)] + spans: &[(usize, Span)], ) { use pulldown_cmark::Event::*; use pulldown_cmark::Tag::*; @@ -192,7 +211,10 @@ fn check_doc<'a, Events: Iterator)>>( let (begin, span) = spans[index]; // Adjust for the begining of the current `Event` - let span = Span { lo: span.lo + BytePos::from_usize(offset - begin), ..span }; + let span = Span { + lo: span.lo + BytePos::from_usize(offset - begin), + ..span + }; check_text(cx, valid_idents, &text, span); } @@ -225,8 +247,10 @@ fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span } fn check_word(cx: &EarlyContext, word: &str, span: Span) { - /// Checks if a string is camel-case, ie. contains at least two uppercase letter (`Clippy` is - /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok). + /// Checks if a string is camel-case, ie. contains at least two uppercase + /// letter (`Clippy` is + /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded + /// (`IDs` is ok). fn is_camel_case(s: &str) -> bool { if s.starts_with(|c: char| c.is_digit(10)) { return false; @@ -239,7 +263,7 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { }; s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && - s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 + s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 } fn has_underscore(s: &str) -> bool { @@ -247,9 +271,11 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { } if has_underscore(word) || word.contains("::") || is_camel_case(word) { - span_lint(cx, - DOC_MARKDOWN, - span, - &format!("you should put `{}` between ticks in the documentation", word)); + span_lint( + cx, + DOC_MARKDOWN, + span, + &format!("you should put `{}` between ticks in the documentation", word), + ); } } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 6112aec7cb6..b02333b89a0 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -16,7 +16,8 @@ use utils::{match_def_path, paths, span_note_and_lint, is_copy}; /// **Example:** /// ```rust /// let mut lock_guard = mutex.lock(); -/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked +/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex +/// still locked /// operation_that_requires_mutex_to_be_unlocked(); /// ``` declare_lint! { @@ -29,7 +30,8 @@ declare_lint! { /// instead of an owned value. /// /// **Why is this bad?** Calling `forget` on a reference will only forget the -/// reference itself, which is a no-op. It will not forget the underlying referenced +/// reference itself, which is a no-op. It will not forget the underlying +/// referenced /// value, which is likely what was intended. /// /// **Known problems:** None. @@ -57,7 +59,8 @@ declare_lint! { /// **Example:** /// ```rust /// let x:i32 = 42; // i32 implements Copy -/// std::mem::drop(x) // A copy of x is passed to the function, leaving the original unaffected +/// std::mem::drop(x) // A copy of x is passed to the function, leaving the +/// original unaffected /// ``` declare_lint! { pub DROP_COPY, @@ -72,8 +75,10 @@ declare_lint! { /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the /// value will be copied and moved into the function on invocation. /// -/// An alternative, but also valid, explanation is that Copy types do not implement -/// the Drop trait, which means they have no destructors. Without a destructor, there +/// An alternative, but also valid, explanation is that Copy types do not +/// implement +/// the Drop trait, which means they have no destructors. Without a destructor, +/// there /// is nothing for `std::mem::forget` to ignore. /// /// **Known problems:** None. @@ -81,7 +86,8 @@ declare_lint! { /// **Example:** /// ```rust /// let x:i32 = 42; // i32 implements Copy -/// std::mem::forget(x) // A copy of x is passed to the function, leaving the original unaffected +/// std::mem::forget(x) // A copy of x is passed to the function, leaving the +/// original unaffected /// ``` declare_lint! { pub FORGET_COPY, diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 431e8779842..7845c85b687 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -6,7 +6,8 @@ use utils::span_lint_and_then; /// **What it does:** Checks for `enum`s with no variants. /// -/// **Why is this bad?** Enum's with no variants should be replaced with `!`, the uninhabited type, +/// **Why is this bad?** Enum's with no variants should be replaced with `!`, +/// the uninhabited type, /// or a wrapper around it. /// /// **Known problems:** None. @@ -21,7 +22,7 @@ declare_lint! { "enum with no variants" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct EmptyEnum; impl LintPass for EmptyEnum { @@ -35,7 +36,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(..) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); + let adt = ty.ty_adt_def().expect( + "already checked whether this is an enum", + ); if adt.variants.is_empty() { span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| { db.span_help(item.span, "consider using the uninhabited type `!` or a wrapper around it"); diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 43d8357e335..80288ff2268 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -30,7 +30,7 @@ declare_lint! { "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct HashMapLint; impl LintPass for HashMapLint { @@ -48,11 +48,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { // we can give a better error message let sole_expr = { else_block.is_none() && - if let ExprBlock(ref then_block) = then_block.node { - (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 - } else { - true - } + if let ExprBlock(ref then_block) = then_block.node { + (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 + } else { + true + } }; let mut visitor = InsertVisitor { @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { fn check_cond<'a, 'tcx, 'b>( cx: &'a LateContext<'a, 'tcx>, - check: &'b Expr + check: &'b Expr, ) -> Option<(&'static str, &'b Expr, &'b Expr)> { if_let_chain! {[ let ExprMethodCall(ref path, _, ref params) = check.node, diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 3741b3934bd..bf2ba847ec8 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -1,4 +1,5 @@ -//! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` +//! lint on C-like enums that are `repr(isize/usize)` and have values that +//! don't fit into an `i32` use rustc::lint::*; use rustc::middle::const_val::ConstVal; @@ -50,16 +51,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let did = cx.tcx.hir.body_owner_def_id(body_id); let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); - let bad = match cx.tcx.at(expr.span).const_eval(param_env.and((did, substs))) { + let bad = match cx.tcx.at(expr.span).const_eval( + param_env.and((did, substs)), + ) { Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, _ => false, }; if bad { - span_lint(cx, - ENUM_CLIKE_UNPORTABLE_VARIANT, - var.span, - "Clike enum variant discriminant is not portable to 32-bit targets"); + span_lint( + cx, + ENUM_CLIKE_UNPORTABLE_VARIANT, + var.span, + "Clike enum variant discriminant is not portable to 32-bit targets", + ); } } } diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 12b588967f8..6738f5bb63b 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -48,9 +48,14 @@ impl EnumGlobUse { } if let ItemUse(ref path, UseKind::Glob) = item.node { // FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;` - // extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an `Enum` + // extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an + // `Enum` // if let Def::Enum(_) = path.def { - if path.segments.last().and_then(|seg| seg.name.as_str().chars().next()).map_or(false, char::is_uppercase) { + if path.segments + .last() + .and_then(|seg| seg.name.as_str().chars().next()) + .map_or(false, char::is_uppercase) + { span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 16a2e021723..1227de69db2 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -68,13 +68,16 @@ declare_lint! { "type names prefixed/postfixed with their containing module's name" } -/// **What it does:** Checks for modules that have the same name as their parent module +/// **What it does:** Checks for modules that have the same name as their +/// parent module /// -/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. +/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and +/// again `mod foo { .. /// }` in `foo.rs`. /// The expectation is that items inside the inner `mod foo { .. }` are then /// available -/// through `foo::x`, but they are only available through `foo::foo::x`. +/// through `foo::x`, but they are only available through +/// `foo::foo::x`. /// If this is done on purpose, it would be better to choose a more /// representative module name. /// @@ -123,14 +126,21 @@ fn var2str(var: &Variant) -> InternedString { fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next_back(); // make sure the name is never fully matched - pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() + pre.chars() + .zip(name_iter) + .take_while(|&(l, r)| l == r) + .count() } /// Returns the number of chars that match from the end fn partial_rmatch(post: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next(); // make sure the name is never fully matched - post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() + post.chars() + .rev() + .zip(name_iter.rev()) + .take_while(|&(l, r)| l == r) + .count() } // FIXME: #600 @@ -142,7 +152,7 @@ fn check_variant( item_name: &str, item_name_chars: usize, span: Span, - lint: &'static Lint + lint: &'static Lint, ) { if (def.variants.len() as u64) < threshold { return; @@ -187,13 +197,17 @@ fn check_variant( (false, _) => ("pre", pre), (true, false) => ("post", post), }; - span_help_and_lint(cx, - lint, - span, - &format!("All variants have the same {}fix: `{}`", what, value), - &format!("remove the {}fixes and use full paths to \ + span_help_and_lint( + cx, + lint, + span, + &format!("All variants have the same {}fix: `{}`", what, value), + &format!( + "remove the {}fixes and use full paths to \ the variants instead of glob imports", - what)); + what + ), + ); } fn to_camel_case(item_name: &str) -> String { @@ -234,10 +248,12 @@ impl EarlyLintPass for EnumVariantNames { if !mod_camel.is_empty() { if *mod_name == item_name { if let ItemKind::Mod(..) = item.node { - span_lint(cx, - MODULE_INCEPTION, - item.span, - "module has the same name as its containing module"); + span_lint( + cx, + MODULE_INCEPTION, + item.span, + "module has the same name as its containing module", + ); } } if item.vis == Visibility::Public { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 10e5f2ba7c0..84a54dd215b 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -23,7 +23,8 @@ declare_lint! { "equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" } -/// **What it does:** Checks for arguments to `==` which have their address taken to satisfy a bound +/// **What it does:** Checks for arguments to `==` which have their address +/// taken to satisfy a bound /// and suggests to dereference the other argument instead /// /// **Why is this bad?** It is more idiomatic to dereference the other argument. @@ -40,7 +41,7 @@ declare_lint! { "taking a reference to satisfy the type constraints on `==`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct EqOp; impl LintPass for EqOp { @@ -53,10 +54,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { - span_lint(cx, - EQ_OP, - e.span, - &format!("equal expressions as operands to `{}`", op.node.as_str())); + span_lint( + cx, + EQ_OP, + e.span, + &format!("equal expressions as operands to `{}`", op.node.as_str()), + ); return; } let (trait_id, requires_ref) = match op.node { @@ -89,31 +92,37 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { let rcpy = is_copy(cx, rty); // either operator autorefs or both args are copyable if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty]) { - span_lint_and_then(cx, - OP_REF, - e.span, - "needlessly taken reference of both operands", - |db| { - let lsnip = snippet(cx, l.span, "...").to_string(); - let rsnip = snippet(cx, r.span, "...").to_string(); - multispan_sugg(db, - "use the values directly".to_string(), - vec![(left.span, lsnip), (right.span, rsnip)]); - }) + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of both operands", + |db| { + let lsnip = snippet(cx, l.span, "...").to_string(); + let rsnip = snippet(cx, r.span, "...").to_string(); + multispan_sugg( + db, + "use the values directly".to_string(), + vec![(left.span, lsnip), (right.span, rsnip)], + ); + }, + ) } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion(left.span, "use the left value directly", lsnip); }) } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) { - span_lint_and_then(cx, - OP_REF, - e.span, - "needlessly taken reference of right operand", - |db| { - let rsnip = snippet(cx, r.span, "...").to_string(); - db.span_suggestion(right.span, "use the right value directly", rsnip); - }) + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of right operand", + |db| { + let rsnip = snippet(cx, r.span, "...").to_string(); + db.span_suggestion(right.span, "use the right value directly", rsnip); + }, + ) } }, // &foo == bar diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index c3a3f37fab5..68f0ede8a6c 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: &'tcx FnDecl, body: &'tcx Body, _: Span, - node_id: NodeId + node_id: NodeId, ) { let fn_def_id = cx.tcx.hir.local_def_id(node_id); let mut v = EscapeDelegate { @@ -74,10 +74,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); for node in v.set { - span_lint(cx, - BOXED_LOCAL, - cx.tcx.hir.span(node), - "local variable doesn't need to be boxed here"); + span_lint( + cx, + BOXED_LOCAL, + cx.tcx.hir.span(node), + "local variable doesn't need to be boxed here", + ); } } } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 7ec528b90f4..b5667db920c 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -20,7 +20,8 @@ pub struct EtaPass; /// ```rust /// xs.map(|x| foo(x)) /// ``` -/// where `foo(_)` is a plain function that takes the exact argument type of `x`. +/// where `foo(_)` is a plain function that takes the exact argument type of +/// `x`. declare_lint! { pub REDUNDANT_CLOSURE, Warn, @@ -91,13 +92,11 @@ fn check_closure(cx: &LateContext, expr: &Expr) { return; } } - span_lint_and_then(cx, - REDUNDANT_CLOSURE, - expr.span, - "redundant closure found", - |db| if let Some(snippet) = snippet_opt(cx, caller.span) { - db.span_suggestion(expr.span, "remove closure as shown", snippet); - }); + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { + if let Some(snippet) = snippet_opt(cx, caller.span) { + db.span_suggestion(expr.span, "remove closure as shown", snippet); + } + }); } } } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 765da9ea877..81109761ca7 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -27,12 +27,14 @@ declare_lint! { "whether a variable read occurs before a write depends on sub-expression evaluation order" } -/// **What it does:** Checks for diverging calls that are not match arms or statements. +/// **What it does:** Checks for diverging calls that are not match arms or +/// statements. /// /// **Why is this bad?** It is often confusing to read. In addition, the /// sub-expression evaluation order for Rust is not well documented. /// -/// **Known problems:** Someone might want to use `some_bool || panic!()` as a shorthand. +/// **Known problems:** Someone might want to use `some_bool || panic!()` as a +/// shorthand. /// /// **Example:** /// ```rust @@ -47,7 +49,7 @@ declare_lint! { "whether an expression contains a diverging sub expression" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct EvalOrderDependence; impl LintPass for EvalOrderDependence { @@ -144,7 +146,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { } }, _ => { - // do not lint expressions referencing objects of type `!`, as that required a diverging expression + // do not lint expressions referencing objects of type `!`, as that required a + // diverging expression // to begin with }, } @@ -271,8 +274,10 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St DeclLocal(ref local) => Some(local), _ => None, }; - local.and_then(|local| local.init.as_ref()) - .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) + local.and_then(|local| local.init.as_ref()).map_or( + StopEarly::KeepGoing, + |expr| check_expr(vis, expr), + ) }, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index e7dbc3250f7..16dced95760 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -99,7 +99,8 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp /// Checks if the expressions matches /// ```rust, ignore -/// { static __STATIC_FMTSTR: &'static[&'static str] = &["a", "b", c]; __STATIC_FMTSTR } +/// { static __STATIC_FMTSTR: &'static[&'static str] = &["a", "b", c]; +/// __STATIC_FMTSTR } /// ``` fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { if let Some(expr) = get_argument_fmtstr_parts(cx, expr) { @@ -112,7 +113,8 @@ fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { /// Checks if the expressions matches /// ```rust,ignore /// &match (&42,) { -/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)], +/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, +/// ::std::fmt::Display::fmt)], /// } /// ``` fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 8f8c7db64cf..c478974a5bd 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -4,9 +4,11 @@ use syntax_pos::{Span, NO_EXPANSION}; use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use syntax::ptr::P; -/// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` operators. +/// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` +/// operators. /// -/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing. +/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or +/// confusing. /// /// **Known problems:** None. /// @@ -67,12 +69,16 @@ declare_lint! { } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct Formatting; impl LintPass for Formatting { fn get_lints(&self) -> LintArray { - lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING, POSSIBLE_MISSING_COMMA] + lint_array!( + SUSPICIOUS_ASSIGNMENT_FORMATTING, + SUSPICIOUS_ELSE_FORMATTING, + POSSIBLE_MISSING_COMMA + ) } } @@ -114,14 +120,18 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { ctxt: NO_EXPANSION, }; if eq_snippet.ends_with('=') { - span_note_and_lint(cx, - SUSPICIOUS_ASSIGNMENT_FORMATTING, - eqop_span, - &format!("this looks like you are trying to use `.. {op}= ..`, but you \ + span_note_and_lint( + cx, + SUSPICIOUS_ASSIGNMENT_FORMATTING, + eqop_span, + &format!( + "this looks like you are trying to use `.. {op}= ..`, but you \ really are doing `.. = ({op} ..)`", - op = op), - eqop_span, - &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op)); + op = op + ), + eqop_span, + &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op), + ); } } } @@ -133,7 +143,8 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) { - // this will be a span from the closing ‘}’ of the “then” block (excluding) to the + // this will be a span from the closing ‘}’ of the “then” block (excluding) to + // the // “if” of the “else if” block (excluding) let else_span = Span { lo: then.span.hi, @@ -144,16 +155,20 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” if let Some(else_snippet) = snippet_opt(cx, else_span) { - let else_pos = else_snippet.find("else").expect("there must be a `else` here"); + let else_pos = else_snippet.find("else").expect( + "there must be a `else` here", + ); if else_snippet[else_pos..].contains('\n') { - span_note_and_lint(cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - "this is an `else if` but the formatting might hide it", - else_span, - "to remove this lint, remove the `else` or remove the new line between `else` \ - and `if`"); + span_note_and_lint( + cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this is an `else if` but the formatting might hide it", + else_span, + "to remove this lint, remove the `else` or remove the new line between `else` \ + and `if`", + ); } } } @@ -178,12 +193,14 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) { ctxt: NO_EXPANSION, }; if space_snippet.contains('\n') { - span_note_and_lint(cx, - POSSIBLE_MISSING_COMMA, - lint_span, - "possibly missing a comma here", - lint_span, - "to remove this lint, add a comma or write the expr in a single line"); + span_note_and_lint( + cx, + POSSIBLE_MISSING_COMMA, + lint_span, + "possibly missing a comma here", + lint_span, + "to remove this lint, add a comma or write the expr in a single line", + ); } } } @@ -195,7 +212,8 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) { /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() && - unsugar_if(second).is_some() { + unsugar_if(second).is_some() + { // where the else would be let else_span = Span { lo: first.span.hi, @@ -205,13 +223,15 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp if let Some(else_snippet) = snippet_opt(cx, else_span) { if !else_snippet.contains('\n') { - span_note_and_lint(cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - "this looks like an `else if` but the `else` is missing", - else_span, - "to remove this lint, add the missing `else` or add a new line before the second \ - `if`"); + span_note_and_lint( + cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + "this looks like an `else if` but the `else` is missing", + else_span, + "to remove this lint, add the missing `else` or add a new line before the second \ + `if`", + ); } } } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 79d47b1e7da..e45ab558089 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -17,7 +17,8 @@ use utils::{span_lint, type_is_unsafe_function, iter_input_pats}; /// /// **Example:** /// ```rust -/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { .. } +/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: +/// f32) { .. } /// ``` declare_lint! { pub TOO_MANY_ARGUMENTS, @@ -35,7 +36,8 @@ declare_lint! { /// **Known problems:** /// /// * It does not check functions recursively so if the pointer is passed to a -/// private non-`unsafe` function which does the dereferencing, the lint won't trigger. +/// private non-`unsafe` function which does the dereferencing, the lint won't +/// trigger. /// * It only checks for arguments whose type are raw pointers, not raw pointers /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or /// `some_argument.get_raw_ptr()`). @@ -50,7 +52,7 @@ declare_lint! { "public functions dereferencing raw pointer arguments but not marked `unsafe`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct Functions { threshold: u64, } @@ -75,7 +77,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { decl: &'tcx hir::FnDecl, body: &'tcx hir::Body, span: Span, - nodeid: ast::NodeId + nodeid: ast::NodeId, ) { use rustc::hir::map::Node::*; @@ -123,10 +125,12 @@ impl<'a, 'tcx> Functions { fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { let args = decl.inputs.len() as u64; if args > self.threshold { - span_lint(cx, - TOO_MANY_ARGUMENTS, - span, - &format!("this function has too many arguments ({}/{})", args, self.threshold)); + span_lint( + cx, + TOO_MANY_ARGUMENTS, + span, + &format!("this function has too many arguments ({}/{})", args, self.threshold), + ); } } @@ -136,7 +140,7 @@ impl<'a, 'tcx> Functions { unsafety: hir::Unsafety, decl: &'tcx hir::FnDecl, body: &'tcx hir::Body, - nodeid: ast::NodeId + nodeid: ast::NodeId, ) { let expr = &body.value; if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) { @@ -208,10 +212,12 @@ impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { if let hir::ExprPath(ref qpath) = ptr.node { let def = self.cx.tables.qpath_def(qpath, ptr.id); if self.ptrs.contains(&def.def_id()) { - span_lint(self.cx, - NOT_UNSAFE_PTR_ARG_DEREF, - ptr.span, - "this public function dereferences a raw pointer but is not marked `unsafe`"); + span_lint( + self.cx, + NOT_UNSAFE_PTR_ARG_DEREF, + ptr.span, + "this public function dereferences a raw pointer but is not marked `unsafe`", + ); } } } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 7bac29f6808..a7c254e1e46 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -22,7 +22,7 @@ declare_lint! { "using identity operations, e.g. `x + 0` or `y / 1`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct IdentityOp; impl LintPass for IdentityOp { @@ -71,12 +71,17 @@ fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { }, 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), - } { - span_lint(cx, - IDENTITY_OP, - span, - &format!("the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, ".."))); + } + { + span_lint( + cx, + IDENTITY_OP, + span, + &format!( + "the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, "..") + ), + ); } } } diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 8d6a28e62db..058052769ef 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -3,9 +3,11 @@ use rustc::hir::*; use syntax::codemap::Span; use utils::{paths, span_lint_and_then, match_path, snippet}; -/// **What it does:*** Lint for redundant pattern matching over `Result` or `Option` +/// **What it does:*** Lint for redundant pattern matching over `Result` or +/// `Option` /// -/// **Why is this bad?** It's more concise and clear to just use the proper utility function +/// **Why is this bad?** It's more concise and clear to just use the proper +/// utility function /// /// **Known problems:** None. /// diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 72a3d485bd0..66f2778f215 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,4 +1,5 @@ -//! lint on if branches that could be swapped so no `!` operation is necessary on the condition +//! lint on if branches that could be swapped so no `!` operation is necessary +//! on the condition use rustc::lint::*; use syntax::ast::*; @@ -50,18 +51,22 @@ impl EarlyLintPass for IfNotElse { if let ExprKind::Block(..) = els.node { match cond.node { ExprKind::Unary(UnOp::Not, _) => { - span_help_and_lint(cx, - IF_NOT_ELSE, - item.span, - "Unnecessary boolean `not` operation", - "remove the `!` and swap the blocks of the if/else"); + span_help_and_lint( + cx, + IF_NOT_ELSE, + item.span, + "Unnecessary boolean `not` operation", + "remove the `!` and swap the blocks of the if/else", + ); }, ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { - span_help_and_lint(cx, - IF_NOT_ELSE, - item.span, - "Unnecessary `!=` operation", - "change to `==` and swap the blocks of the if/else"); + span_help_and_lint( + cx, + IF_NOT_ELSE, + item.span, + "Unnecessary `!=` operation", + "change to `==` and swap the blocks of the if/else", + ); }, _ => (), } diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index b3561720cc7..f14c70dc4dd 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -47,10 +47,9 @@ impl EarlyLintPass for ItemsAfterStatements { } // skip initial items - let stmts = item.stmts - .iter() - .map(|stmt| &stmt.node) - .skip_while(|s| matches!(**s, StmtKind::Item(..))); + let stmts = item.stmts.iter().map(|stmt| &stmt.node).skip_while(|s| { + matches!(**s, StmtKind::Item(..)) + }); // lint on all further items for stmt in stmts { @@ -62,11 +61,13 @@ impl EarlyLintPass for ItemsAfterStatements { // do not lint `macro_rules`, but continue processing further statements continue; } - span_lint(cx, - ITEMS_AFTER_STATEMENTS, - it.span, - "adding items after statements is confusing, since items exist from the \ - start of the scope"); + span_lint( + cx, + ITEMS_AFTER_STATEMENTS, + it.span, + "adding items after statements is confusing, since items exist from the \ + start of the scope", + ); } } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 4e9c792c42a..73a62c97bc8 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -5,9 +5,11 @@ use rustc::hir::*; use utils::{span_lint_and_then, snippet_opt, type_size}; use rustc::ty::TypeFoldable; -/// **What it does:** Checks for large size differences between variants on `enum`s. +/// **What it does:** Checks for large size differences between variants on +/// `enum`s. /// -/// **Why is this bad?** Enum size is bounded by the largest variant. Having a large variant +/// **Why is this bad?** Enum size is bounded by the largest variant. Having a +/// large variant /// can penalize the memory layout of that enum. /// /// **Known problems:** None. @@ -25,7 +27,7 @@ declare_lint! { "large size difference between variants on an enum" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct LargeEnumVariant { maximum_size_difference_allowed: u64, } @@ -47,13 +49,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); + let adt = ty.ty_adt_def().expect( + "already checked whether this is an enum", + ); let mut smallest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None; for (i, variant) in adt.variants.iter().enumerate() { - let size: u64 = variant.fields + let size: u64 = variant + .fields .iter() .map(|f| { let ty = cx.tcx.type_of(f.did); @@ -77,28 +82,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { if difference > self.maximum_size_difference_allowed { let (i, variant) = largest.1; - span_lint_and_then(cx, - LARGE_ENUM_VARIANT, - def.variants[i].span, - "large size difference between variants", - |db| { - if variant.fields.len() == 1 { - let span = match def.variants[i].node.data { - VariantData::Struct(ref fields, _) | - VariantData::Tuple(ref fields, _) => fields[0].ty.span, - VariantData::Unit(_) => unreachable!(), - }; - if let Some(snip) = snippet_opt(cx, span) { - db.span_suggestion(span, - "consider boxing the large fields to reduce the total size of the \ + span_lint_and_then( + cx, + LARGE_ENUM_VARIANT, + def.variants[i].span, + "large size difference between variants", + |db| { + if variant.fields.len() == 1 { + let span = match def.variants[i].node.data { + VariantData::Struct(ref fields, _) | + VariantData::Tuple(ref fields, _) => fields[0].ty.span, + VariantData::Unit(_) => unreachable!(), + }; + if let Some(snip) = snippet_opt(cx, span) { + db.span_suggestion( + span, + "consider boxing the large fields to reduce the total size of the \ enum", - format!("Box<{}>", snip)); - return; + format!("Box<{}>", snip), + ); + return; + } } - } - db.span_help(def.variants[i].span, - "consider boxing the large fields to reduce the total size of the enum"); - }); + db.span_help( + def.variants[i].span, + "consider boxing the large fields to reduce the total size of the enum", + ); + }, + ); } } @@ -107,7 +118,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { } fn update_if(old: &mut Option, new: T, f: F) - where F: Fn(&T, &T) -> bool +where + F: Fn(&T, &T) -> bool, { if let Some(ref mut val) = *old { if f(val, &new) { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 9b76986dbcc..4e40348facf 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -51,7 +51,7 @@ declare_lint! { "traits or impls with a public `len` method but no corresponding `is_empty` method" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct LenZero; impl LintPass for LenZero { @@ -91,24 +91,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && + { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + } + } else { + false } - } else { - false - } } if !trait_items.iter().any(|i| is_named_self(cx, i, "is_empty")) { if let Some(i) = trait_items.iter().find(|i| is_named_self(cx, i, "len")) { if cx.access_levels.is_exported(i.id.node_id) { - span_lint(cx, - LEN_WITHOUT_IS_EMPTY, - item.span, - &format!("trait `{}` has a `len` method but no `is_empty` method", item.name)); + span_lint( + cx, + LEN_WITHOUT_IS_EMPTY, + item.span, + &format!("trait `{}` has a `len` method but no `is_empty` method", item.name), + ); } } } @@ -117,15 +119,15 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef] fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool { item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && + { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + } + } else { + false } - } else { - false - } } let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) { @@ -143,10 +145,12 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { let def_id = cx.tcx.hir.local_def_id(item.id); let ty = cx.tcx.type_of(def_id); - span_lint(cx, - LEN_WITHOUT_IS_EMPTY, - item.span, - &format!("item `{}` has a public `len` method but {} `is_empty` method", ty, is_empty)); + span_lint( + cx, + LEN_WITHOUT_IS_EMPTY, + item.span, + &format!("item `{}` has a public `len` method but {} `is_empty` method", ty, is_empty), + ); } } } @@ -170,12 +174,14 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) fn check_len_zero(cx: &LateContext, span: Span, name: Name, args: &[Expr], lit: &Lit, op: &str) { if let Spanned { node: LitKind::Int(0, _), .. } = *lit { if name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { - span_lint_and_sugg(cx, - LEN_ZERO, - span, - "length comparison to zero", - "using `is_empty` is more concise", - format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_"))); + span_lint_and_sugg( + cx, + LEN_ZERO, + span, + "length comparison to zero", + "using `is_empty` is more concise", + format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")), + ); } } } @@ -199,10 +205,11 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { - cx.tcx - .inherent_impls(id) - .iter() - .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item))) + cx.tcx.inherent_impls(id).iter().any(|imp| { + cx.tcx.associated_items(*imp).any( + |item| is_is_empty(cx, &item), + ) + }) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); @@ -212,7 +219,12 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { .associated_items(ty.ty_to_def_id().expect("trait impl not found")) .any(|item| is_is_empty(cx, &item)) }, - ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, id)), + ty::TyProjection(_) => { + ty.ty_to_def_id().map_or( + false, + |id| has_is_empty_impl(cx, id), + ) + }, ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did), ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true, _ => false, diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 93b981a2b4a..ecd18424bd8 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -49,7 +49,7 @@ declare_lint! { "unidiomatic `let mut` declaration followed by initialization in `if`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct LetIfSeq; impl LintPass for LetIfSeq { @@ -154,7 +154,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn check_assign<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, decl: hir::def_id::DefId, - block: &'tcx hir::Block + block: &'tcx hir::Block, ) -> Option<&'tcx hir::Expr> { if_let_chain! {[ block.expr.is_none(), diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index d29ef8200ec..dd721db0f09 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -48,7 +48,7 @@ declare_lint! { "unused lifetimes in function definitions" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct LifetimePass; impl LintPass for LifetimePass { @@ -94,7 +94,7 @@ fn check_fn_inner<'a, 'tcx>( decl: &'tcx FnDecl, body: Option, generics: &'tcx Generics, - span: Span + span: Span, ) { if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; @@ -104,7 +104,8 @@ fn check_fn_inner<'a, 'tcx>( for typ in &generics.ty_params { for bound in &typ.bounds { if let TraitTyParamBound(ref trait_ref, _) = *bound { - let bounds = trait_ref.trait_ref + let bounds = trait_ref + .trait_ref .path .segments .last() @@ -121,10 +122,12 @@ fn check_fn_inner<'a, 'tcx>( } } if could_use_elision(cx, decl, body, &generics.lifetimes, bounds_lts) { - span_lint(cx, - NEEDLESS_LIFETIMES, - span, - "explicit lifetimes given in parameter types where they could be elided"); + span_lint( + cx, + NEEDLESS_LIFETIMES, + span, + "explicit lifetimes given in parameter types where they could be elided", + ); } report_extra_lifetimes(cx, decl, generics); } @@ -134,7 +137,7 @@ fn could_use_elision<'a, 'tcx: 'a>( func: &'tcx FnDecl, body: Option, named_lts: &'tcx [LifetimeDef], - bounds_lts: Vec<&'tcx Lifetime> + bounds_lts: Vec<&'tcx Lifetime>, ) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT @@ -189,7 +192,10 @@ fn could_use_elision<'a, 'tcx: 'a>( // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - if input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static) { + if input_lts.iter().all(|lt| { + *lt == RefLt::Unnamed || *lt == RefLt::Static + }) + { return false; } // we have no output reference, so we only need all distinct lifetimes @@ -406,7 +412,8 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { } fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) { - let hs = generics.lifetimes + let hs = generics + .lifetimes .iter() .map(|lt| (lt.lifetime.name, lt.lifetime.span)) .collect(); diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index 2b1599d79f3..0da8ffd0a30 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -146,7 +146,8 @@ impl<'a> DigitInfo<'a> { let group_size = self.radix.suggest_grouping(); if self.digits.contains('.') { let mut parts = self.digits.split('.'); - let int_part_hint = parts.next() + let int_part_hint = parts + .next() .expect("split always returns at least one element") .chars() .rev() @@ -157,7 +158,8 @@ impl<'a> DigitInfo<'a> { .rev() .collect::>() .join("_"); - let frac_part_hint = parts.next() + let frac_part_hint = parts + .next() .expect("already checked that there is a `.`") .chars() .filter(|&c| c != '_') @@ -194,25 +196,31 @@ impl WarningType { pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { match *self { WarningType::UnreadableLiteral => { - span_help_and_lint(cx, - UNREADABLE_LITERAL, - *span, - "long literal lacking separators", - &format!("consider: {}", grouping_hint)) + span_help_and_lint( + cx, + UNREADABLE_LITERAL, + *span, + "long literal lacking separators", + &format!("consider: {}", grouping_hint), + ) }, WarningType::LargeDigitGroups => { - span_help_and_lint(cx, - LARGE_DIGIT_GROUPS, - *span, - "digit groups should be smaller", - &format!("consider: {}", grouping_hint)) + span_help_and_lint( + cx, + LARGE_DIGIT_GROUPS, + *span, + "digit groups should be smaller", + &format!("consider: {}", grouping_hint), + ) }, WarningType::InconsistentDigitGrouping => { - span_help_and_lint(cx, - INCONSISTENT_DIGIT_GROUPING, - *span, - "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint)) + span_help_and_lint( + cx, + INCONSISTENT_DIGIT_GROUPING, + *span, + "digits grouped inconsistently by underscores", + &format!("consider: {}", grouping_hint), + ) }, }; } @@ -309,7 +317,8 @@ impl LiteralDigitGrouping { /// size on success or `WarningType` when emitting a warning. fn do_lint(digits: &str) -> Result { // Grab underscore indices with respect to the units digit. - let underscore_positions: Vec = digits.chars() + let underscore_positions: Vec = digits + .chars() .rev() .enumerate() .filter_map(|(idx, digit)| if digit == '_' { Some(idx) } else { None }) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index fc28918ff16..25015cb26bb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -83,7 +83,8 @@ declare_lint! { /// implements `IntoIterator`, so that possibly one value will be iterated, /// leading to some hard to find bugs. No one will want to write such code /// [except to win an Underhanded Rust -/// Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). +/// Contest](https://www.reddit. +/// com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). /// /// **Known problems:** None. /// @@ -99,7 +100,8 @@ declare_lint! { /// **What it does:** Checks for `for` loops over `Option` values. /// -/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// **Why is this bad?** Readability. This is more clearly expressed as an `if +/// let`. /// /// **Known problems:** None. /// @@ -120,7 +122,8 @@ declare_lint! { /// **What it does:** Checks for `for` loops over `Result` values. /// -/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`. +/// **Why is this bad?** Readability. This is more clearly expressed as an `if +/// let`. /// /// **Known problems:** None. /// @@ -142,7 +145,8 @@ declare_lint! { /// **What it does:** Detects `loop + match` combinations that are easier /// written as a `while let` loop. /// -/// **Why is this bad?** The `while let` loop is usually shorter and more readable. +/// **Why is this bad?** The `while let` loop is usually shorter and more +/// readable. /// /// **Known problems:** Sometimes the wrong binding is displayed (#383). /// @@ -309,20 +313,22 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RANGE_LOOP, - EXPLICIT_ITER_LOOP, - EXPLICIT_INTO_ITER_LOOP, - ITER_NEXT_LOOP, - FOR_LOOP_OVER_RESULT, - FOR_LOOP_OVER_OPTION, - WHILE_LET_LOOP, - UNUSED_COLLECT, - REVERSE_RANGE_LOOP, - EXPLICIT_COUNTER_LOOP, - EMPTY_LOOP, - WHILE_LET_ON_ITERATOR, - FOR_KV_MAP, - NEVER_LOOP) + lint_array!( + NEEDLESS_RANGE_LOOP, + EXPLICIT_ITER_LOOP, + EXPLICIT_INTO_ITER_LOOP, + ITER_NEXT_LOOP, + FOR_LOOP_OVER_RESULT, + FOR_LOOP_OVER_OPTION, + WHILE_LET_LOOP, + UNUSED_COLLECT, + REVERSE_RANGE_LOOP, + EXPLICIT_COUNTER_LOOP, + EMPTY_LOOP, + WHILE_LET_ON_ITERATOR, + FOR_KV_MAP, + NEVER_LOOP + ) } } @@ -349,11 +355,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprLoop(ref block, _, LoopSource::Loop) = expr.node { // also check for empty `loop {}` statements if block.stmts.is_empty() && block.expr.is_none() { - span_lint(cx, - EMPTY_LOOP, - expr.span, - "empty `loop {}` detected. You may want to either use `panic!()` or add \ - `std::thread::sleep(..);` to the loop body."); + span_lint( + cx, + EMPTY_LOOP, + expr.span, + "empty `loop {}` detected. You may want to either use `panic!()` or add \ + `std::thread::sleep(..);` to the loop body.", + ); } // extract the expression from the first statement (if any) in a block @@ -366,8 +374,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - is_break_expr(&arms[1].body) { + arms[1].pats.len() == 1 && arms[1].guard.is_none() && + is_break_expr(&arms[1].body) + { if in_external_macro(cx, expr.span) { return; } @@ -377,14 +386,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // 1) it was ugly with big bodies; // 2) it was not indented properly; // 3) it wasn’t very smart (see #675). - span_lint_and_sugg(cx, - WHILE_LET_LOOP, - expr.span, - "this loop could be written as a `while let` loop", - "try", - format!("while let {} = {} {{ .. }}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, ".."))); + span_lint_and_sugg( + cx, + WHILE_LET_LOOP, + expr.span, + "this loop could be written as a `while let` loop", + "try", + format!( + "while let {} = {} {{ .. }}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, matchexpr.span, "..") + ), + ); } }, _ => (), @@ -395,20 +408,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) { + &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) + { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); if method_path.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) && - lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) && - !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0]) { + lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) && + !is_iterator_used_after_while_let(cx, iter_expr) && + !is_nested(cx, expr, &method_args[0]) + { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); - span_lint_and_sugg(cx, - WHILE_LET_ON_ITERATOR, - expr.span, - "this loop could be written as a `for` loop", - "try", - format!("for {} in {} {{ .. }}", loop_var, iterator)); + span_lint_and_sugg( + cx, + WHILE_LET_ON_ITERATOR, + expr.span, + "this loop could be written as a `for` loop", + "try", + format!("for {} in {} {{ .. }}", loop_var, iterator), + ); } } } @@ -418,11 +436,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { - span_lint(cx, - UNUSED_COLLECT, - expr.span, - "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator"); + span_lint( + cx, + UNUSED_COLLECT, + expr.span, + "you are collect()ing an iterator and throwing away the result. \ + Consider using an explicit for loop to exhaust the iterator", + ); } } } @@ -435,7 +455,10 @@ fn never_loop(block: &Block, id: &NodeId) -> bool { fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || - block.expr.as_ref().map_or(false, |e| contains_continue_expr(e, dest)) + block.expr.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) } fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { @@ -448,7 +471,12 @@ fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { match decl.node { - DeclLocal(ref local) => local.init.as_ref().map_or(false, |e| contains_continue_expr(e, dest)), + DeclLocal(ref local) => { + local.init.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) + }, _ => false, } } @@ -475,14 +503,21 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprAssignOp(_, ref e1, ref e2) | ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| contains_continue_expr(e, dest)), ExprIf(ref e, ref e2, ref e3) => { - [e, e2].iter().chain(e3.as_ref().iter()).any(|e| contains_continue_expr(e, dest)) + [e, e2].iter().chain(e3.as_ref().iter()).any(|e| { + contains_continue_expr(e, dest) + }) }, ExprWhile(ref e, ref b, _) => contains_continue_expr(e, dest) || contains_continue_block(b, dest), ExprMatch(ref e, ref arms, _) => { contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) }, ExprBlock(ref block) => contains_continue_block(block, dest), - ExprStruct(_, _, ref base) => base.as_ref().map_or(false, |e| contains_continue_expr(e, dest)), + ExprStruct(_, _, ref base) => { + base.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) + }, ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), _ => false, } @@ -541,7 +576,7 @@ fn check_for_loop<'a, 'tcx>( pat: &'tcx Pat, arg: &'tcx Expr, body: &'tcx Expr, - expr: &'tcx Expr + expr: &'tcx Expr, ) { check_for_loop_range(cx, pat, arg, body, expr); check_for_loop_reverse_range(cx, arg, expr); @@ -557,9 +592,14 @@ fn check_for_loop_range<'a, 'tcx>( pat: &'tcx Pat, arg: &'tcx Expr, body: &'tcx Expr, - expr: &'tcx Expr + expr: &'tcx Expr, ) { - if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) { + if let Some(higher::Range { + start: Some(start), + ref end, + limits, + }) = higher::range(arg) + { // the var must be a single name if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { let mut visitor = VarVisitor { @@ -573,10 +613,9 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed - .into_iter() - .next() - .expect("already checked that we have exactly 1 element"); + let (indexed, indexed_extent) = visitor.indexed.into_iter().next().expect( + "already checked that we have exactly 1 element", + ); // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { @@ -589,7 +628,8 @@ fn check_for_loop_range<'a, 'tcx>( } } - // don't lint if the container that is indexed into is also used without indexing + // don't lint if the container that is indexed into is also used without + // indexing if visitor.referenced.contains(&indexed) { return; } @@ -670,7 +710,12 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... - if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { + if let Some(higher::Range { + start: Some(start), + end: Some(end), + limits, + }) = higher::range(arg) + { // ...and both sides are compile-time constant integers... let parent_item = cx.tcx.hir.get_parent(arg.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); @@ -714,10 +759,12 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop // will never run. - span_lint(cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run"); + span_lint( + cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run", + ); } } } @@ -731,13 +778,15 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s } else { "" }; - span_lint_and_sugg(cx, - EXPLICIT_ITER_LOOP, - arg.span, - "it is more idiomatic to loop over references to containers instead of using explicit \ + span_lint_and_sugg( + cx, + EXPLICIT_ITER_LOOP, + arg.span, + "it is more idiomatic to loop over references to containers instead of using explicit \ iteration methods", - "to write this more concisely, try", - format!("&{}{}", muta, object)) + "to write this more concisely, try", + format!("&{}{}", muta, object), + ) } fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { @@ -762,20 +811,24 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { lint_iter_method(cx, args, arg, method_name); } else { let object = snippet(cx, args[0].span, "_"); - span_lint_and_sugg(cx, - EXPLICIT_INTO_ITER_LOOP, - arg.span, - "it is more idiomatic to loop over containers instead of using explicit \ + span_lint_and_sugg( + cx, + EXPLICIT_INTO_ITER_LOOP, + arg.span, + "it is more idiomatic to loop over containers instead of using explicit \ iteration methods`", - "to write this more concisely, try", - object.to_string()); + "to write this more concisely, try", + object.to_string(), + ); } } else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { - span_lint(cx, - ITER_NEXT_LOOP, - expr.span, - "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ - probably not what you want"); + span_lint( + cx, + ITER_NEXT_LOOP, + expr.span, + "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ + probably not what you want", + ); next_loop_linted = true; } } @@ -789,25 +842,37 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { let ty = cx.tables.expr_ty(arg); if match_type(cx, ty, &paths::OPTION) { - span_help_and_lint(cx, - FOR_LOOP_OVER_OPTION, - arg.span, - &format!("for loop over `{0}`, which is an `Option`. This is more readably written as an \ + span_help_and_lint( + cx, + FOR_LOOP_OVER_OPTION, + arg.span, + &format!( + "for loop over `{0}`, which is an `Option`. This is more readably written as an \ `if let` statement.", - snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", - snippet(cx, pat.span, "_"), - snippet(cx, arg.span, "_"))); + snippet(cx, arg.span, "_") + ), + &format!( + "consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_") + ), + ); } else if match_type(cx, ty, &paths::RESULT) { - span_help_and_lint(cx, - FOR_LOOP_OVER_RESULT, - arg.span, - &format!("for loop over `{0}`, which is a `Result`. This is more readably written as an \ + span_help_and_lint( + cx, + FOR_LOOP_OVER_RESULT, + arg.span, + &format!( + "for loop over `{0}`, which is a `Result`. This is more readably written as an \ `if let` statement.", - snippet(cx, arg.span, "_")), - &format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", - snippet(cx, pat.span, "_"), - snippet(cx, arg.span, "_"))); + snippet(cx, arg.span, "_") + ), + &format!( + "consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", + snippet(cx, pat.span, "_"), + snippet(cx, arg.span, "_") + ), + ); } } @@ -815,7 +880,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr, body: &'tcx Expr, - expr: &'tcx Expr + expr: &'tcx Expr, ) { // Look for variables that are incremented once per loop iteration. let mut visitor = IncrementVisitor { @@ -829,10 +894,15 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| map.get_enclosing_scope(id)); + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| { + map.get_enclosing_scope(id) + }); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { + for (id, _) in visitor.states.iter().filter( + |&(_, v)| *v == VarState::IncrOnce, + ) + { let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, @@ -846,13 +916,17 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( if visitor2.state == VarState::Warn { if let Some(name) = visitor2.name { - span_lint(cx, - EXPLICIT_COUNTER_LOOP, - expr.span, - &format!("the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ + span_lint( + cx, + EXPLICIT_COUNTER_LOOP, + expr.span, + &format!( + "the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ item) in {1}.enumerate()` or similar iterators", - name, - snippet(cx, arg.span, "_"))); + name, + snippet(cx, arg.span, "_") + ), + ); } } } @@ -866,7 +940,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( pat: &'tcx Pat, arg: &'tcx Expr, body: &'tcx Expr, - expr: &'tcx Expr + expr: &'tcx Expr, ) { let pat_span = pat.span; @@ -929,7 +1003,7 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { fn match_var(expr: &Expr, var: Name) -> bool { if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { if path.segments.len() == 1 && path.segments[0].name == var { - return true + return true; } } false @@ -964,7 +1038,8 @@ struct VarVisitor<'a, 'tcx: 'a> { /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: HashSet, - /// has the loop variable been used in expressions other than the index of an index op? + /// has the loop variable been used in expressions other than the index of + /// an index op? nonindex: bool, } @@ -1095,7 +1170,8 @@ fn is_iterable_array(ty: Ty) -> bool { } } -/// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. +/// If a block begins with a statement (possibly a `let` binding) and has an +/// expression, return it. fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { if block.stmts.is_empty() { return None; @@ -1302,7 +1378,9 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { if let ExprPath(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.id); if let Def::Local(def_id) = path_res { - let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("That DefId should be valid"); + let node_id = cx.tcx.hir.as_local_node_id(def_id).expect( + "That DefId should be valid", + ); return Some(node_id); } } @@ -1348,17 +1426,18 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool match cx.tcx.hir.find(parent) { Some(NodeExpr(expr)) => { match expr.node { - ExprLoop(..) | - ExprWhile(..) => { return true; }, - _ => () + ExprLoop(..) | ExprWhile(..) => { + return true; + }, + _ => (), } }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { - id: id, - iterator: iter_name, - nesting: Unknown - }; + id: id, + iterator: iter_name, + nesting: Unknown, + }; walk_block(&mut block_visitor, block); if block_visitor.nesting == RuledOut { return false; @@ -1367,7 +1446,7 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool Some(NodeStmt(_)) => (), _ => { return false; - } + }, } id = parent; } @@ -1377,7 +1456,7 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool enum Nesting { Unknown, // no nesting detected yet RuledOut, // the iterator is initialized or assigned within scope - LookFurther // no nesting detected, no further walk required + LookFurther, // no nesting detected, no further walk required } use self::Nesting::{Unknown, RuledOut, LookFurther}; @@ -1385,7 +1464,7 @@ use self::Nesting::{Unknown, RuledOut, LookFurther}; struct LoopNestVisitor { id: NodeId, iterator: Name, - nesting: Nesting + nesting: Nesting, } impl<'tcx> Visitor<'tcx> for LoopNestVisitor { @@ -1398,22 +1477,28 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { } fn visit_expr(&mut self, expr: &'tcx Expr) { - if self.nesting != Unknown { return; } + if self.nesting != Unknown { + return; + } if expr.id == self.id { self.nesting = LookFurther; return; } match expr.node { ExprAssign(ref path, _) | - ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { - self.nesting = RuledOut; + ExprAssignOp(_, ref path, _) => { + if match_var(path, self.iterator) { + self.nesting = RuledOut; + } }, - _ => walk_expr(self, expr) + _ => walk_expr(self, expr), } } fn visit_pat(&mut self, pat: &'tcx Pat) { - if self.nesting != Unknown { return; } + if self.nesting != Unknown { + return; + } if let PatKind::Binding(_, _, span_name, _) = pat.node { if self.iterator == span_name.node { self.nesting = RuledOut; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 1661c71167e..457c6cc8d65 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, span_help_and_lint, - walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; +use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -76,13 +76,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ExprPath(ref path) => { if match_path(path, &paths::CLONE) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint(cx, - MAP_CLONE, - expr.span, - &format!("you seem to be using .map() to clone the contents of an \ + span_help_and_lint( + cx, + MAP_CLONE, + expr.span, + &format!( + "you seem to be using .map() to clone the contents of an \ {}, consider using `.cloned()`", - type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + type_name + ), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), + ); } }, _ => (), @@ -95,10 +99,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { match expr.node { ExprPath(QPath::Resolved(None, ref path)) => { - let arg_segment = [PathSegment { - name: id, - parameters: PathParameters::none(), - }]; + let arg_segment = [ + PathSegment { + name: id, + parameters: PathParameters::none(), + }, + ]; !path.is_global() && path.segments[..] == arg_segment }, _ => false, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index ec06e72749e..5dba102f6a4 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -150,12 +150,14 @@ pub struct MatchPass; impl LintPass for MatchPass { fn get_lints(&self) -> LintArray { - lint_array!(SINGLE_MATCH, - MATCH_REF_PATS, - MATCH_BOOL, - SINGLE_MATCH_ELSE, - MATCH_OVERLAPPING_ARM, - MATCH_WILD_ERR_ARM) + lint_array!( + SINGLE_MATCH, + MATCH_REF_PATS, + MATCH_BOOL, + SINGLE_MATCH_ELSE, + MATCH_OVERLAPPING_ARM, + MATCH_WILD_ERR_ARM + ) } } @@ -212,28 +214,34 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], SINGLE_MATCH }; let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); - span_lint_and_sugg(cx, - lint, - expr.span, - "you seem to be trying to use match for destructuring a single pattern. Consider using `if \ + span_lint_and_sugg( + cx, + lint, + expr.span, + "you seem to be trying to use match for destructuring a single pattern. Consider using `if \ let`", - "try this", - format!("if let {} = {} {}{}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), - els_str)); + "try this", + format!( + "if let {} = {} {}{}", + snippet(cx, arms[0].pats[0].span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, &arms[0].body, None, ".."), + els_str + ), + ); } fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty, els: Option<&Expr>) { // list of candidate Enums we know will never get any more members - let candidates = &[(&paths::COW, "Borrowed"), - (&paths::COW, "Cow::Borrowed"), - (&paths::COW, "Cow::Owned"), - (&paths::COW, "Owned"), - (&paths::OPTION, "None"), - (&paths::RESULT, "Err"), - (&paths::RESULT, "Ok")]; + let candidates = &[ + (&paths::COW, "Borrowed"), + (&paths::COW, "Cow::Borrowed"), + (&paths::COW, "Cow::Owned"), + (&paths::COW, "Owned"), + (&paths::OPTION, "None"), + (&paths::RESULT, "Err"), + (&paths::RESULT, "Ok"), + ]; let path = match arms[1].pats[0].node { PatKind::TupleStruct(ref path, ref inner, _) => { @@ -258,52 +266,60 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tables.expr_ty(ex).sty == ty::TyBool { - span_lint_and_then(cx, - MATCH_BOOL, - expr.span, - "you seem to be trying to match on a boolean expression", - move |db| { - if arms.len() == 2 && arms[0].pats.len() == 1 { - // no guards - let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { - if let ExprLit(ref lit) = arm_bool.node { - match lit.node { - LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), - LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), - _ => None, + span_lint_and_then( + cx, + MATCH_BOOL, + expr.span, + "you seem to be trying to match on a boolean expression", + move |db| { + if arms.len() == 2 && arms[0].pats.len() == 1 { + // no guards + let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { + if let ExprLit(ref lit) = arm_bool.node { + match lit.node { + LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), + LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), + _ => None, + } + } else { + None } } else { None - } - } else { - None - }; - - if let Some((true_expr, false_expr)) = exprs { - let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => { - Some(format!("if {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, ".."))) - }, - (false, true) => { - Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) - }, - (true, false) => { - let test = Sugg::hir(cx, ex, ".."); - Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) - }, - (true, true) => None, }; - if let Some(sugg) = sugg { - db.span_suggestion(expr.span, "consider using an if/else expression", sugg); + if let Some((true_expr, false_expr)) = exprs { + let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { + (false, false) => { + Some(format!( + "if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, "..") + )) + }, + (false, true) => { + Some(format!( + "if {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, "..") + )) + }, + (true, false) => { + let test = Sugg::hir(cx, ex, ".."); + Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) + }, + (true, true) => None, + }; + + if let Some(sugg) = sugg { + db.span_suggestion(expr.span, "consider using an if/else expression", sugg); + } } } - } - }); + }, + ); } } @@ -313,12 +329,14 @@ fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { let type_ranges = type_ranges(&ranges); if !type_ranges.is_empty() { if let Some((start, end)) = overlapping(&type_ranges) { - span_note_and_lint(cx, - MATCH_OVERLAPPING_ARM, - start.span, - "some ranges overlap", - end.span, - "overlaps with this"); + span_note_and_lint( + cx, + MATCH_OVERLAPPING_ARM, + start.span, + "some ranges overlap", + end.span, + "overlaps with this", + ); } } } @@ -376,17 +394,21 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match db.span_suggestion(expr.span, "try", template); }); } else { - span_lint_and_then(cx, - MATCH_REF_PATS, - expr.span, - "you don't need to add `&` to all patterns", - |db| { - let ex = Sugg::hir(cx, ex, ".."); - let template = match_template(expr.span, source, &ex.deref()); - db.span_suggestion(expr.span, - "instead of prefixing all patterns with `&`, you can dereference the expression", - template); - }); + span_lint_and_then( + cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to all patterns", + |db| { + let ex = Sugg::hir(cx, ex, ".."); + let template = match_template(expr.span, source, &ex.deref()); + db.span_suggestion( + expr.span, + "instead of prefixing all patterns with `&`, you can dereference the expression", + template, + ); + }, + ); } } } @@ -399,13 +421,17 @@ fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm], id: NodeId) -> let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables); arms.iter() .flat_map(|arm| { - if let Arm { ref pats, guard: None, .. } = *arm { - pats.iter() - } else { - [].iter() - } - .filter_map(|pat| { - if_let_chain! {[ + if let Arm { + ref pats, + guard: None, + .. + } = *arm + { + pats.iter() + } else { + [].iter() + }.filter_map(|pat| { + if_let_chain! {[ let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node, let Ok(lhs) = constcx.eval(lhs), let Ok(rhs) = constcx.eval(rhs) @@ -417,15 +443,15 @@ fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm], id: NodeId) -> return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); }} - if_let_chain! {[ + if_let_chain! {[ let PatKind::Lit(ref value) = pat.node, let Ok(value) = constcx.eval(value) ], { return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); }} - None - }) + None + }) }) .collect() } @@ -438,10 +464,12 @@ pub struct SpannedRange { type TypedRanges = Vec>; -/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than +/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway +/// and other types than /// `Uint` and `Int` probably don't make sense. fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { - ranges.iter() + ranges + .iter() .filter_map(|range| match range.node { (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => { Some(SpannedRange { @@ -500,7 +528,8 @@ fn match_template(span: Span, source: MatchSource, expr: &Sugg) -> String { } pub fn overlapping(ranges: &[SpannedRange]) -> Option<(&SpannedRange, &SpannedRange)> - where T: Copy + Ord +where + T: Copy + Ord, { #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Kind<'a, T: 'a> { diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index b43a2473f0d..280b51b2312 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -2,7 +2,8 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; use utils::{match_def_path, paths, span_lint}; -/// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is `Drop`. +/// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is +/// `Drop`. /// /// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its /// destructor, possibly causing leaks. @@ -38,7 +39,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { if match forgot_ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, - } { + } + { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 1c6f7dd214e..c04fdde772f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -65,7 +65,8 @@ declare_lint! { /// information) instead of an inherent implementation. /// /// **Why is this bad?** Implementing the traits improve ergonomics for users of -/// the code, often with very little cost. Also people seeing a `mul(...)` method +/// the code, often with very little cost. Also people seeing a `mul(...)` +/// method /// may expect `*` to work equally, so you should have good reason to disappoint /// them. /// @@ -368,7 +369,8 @@ declare_lint! { `_.split(\"x\")`" } -/// **What it does:** Checks for getting the inner pointer of a temporary `CString`. +/// **What it does:** Checks for getting the inner pointer of a temporary +/// `CString`. /// /// **Why is this bad?** The inner pointer of a `CString` is only valid as long /// as the `CString` is alive. @@ -500,7 +502,8 @@ declare_lint! { "using `x.extend(s.chars())` where s is a `&str` or `String`" } -/// **What it does:** Checks for the use of `.cloned().collect()` on slice to create a `Vec`. +/// **What it does:** Checks for the use of `.cloned().collect()` on slice to +/// create a `Vec`. /// /// **Why is this bad?** `.to_vec()` is clearer /// @@ -524,29 +527,31 @@ declare_lint! { impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_UNWRAP_USED, - RESULT_UNWRAP_USED, - SHOULD_IMPLEMENT_TRAIT, - WRONG_SELF_CONVENTION, - WRONG_PUB_SELF_CONVENTION, - OK_EXPECT, - OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE, - OR_FUN_CALL, - CHARS_NEXT_CMP, - CLONE_ON_COPY, - CLONE_DOUBLE_REF, - NEW_RET_NO_SELF, - SINGLE_CHAR_PATTERN, - SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR, - FILTER_NEXT, - FILTER_MAP, - ITER_NTH, - ITER_SKIP_NEXT, - GET_UNWRAP, - STRING_EXTEND_CHARS, - ITER_CLONED_COLLECT) + lint_array!( + OPTION_UNWRAP_USED, + RESULT_UNWRAP_USED, + SHOULD_IMPLEMENT_TRAIT, + WRONG_SELF_CONVENTION, + WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, + OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE, + OR_FUN_CALL, + CHARS_NEXT_CMP, + CLONE_ON_COPY, + CLONE_DOUBLE_REF, + NEW_RET_NO_SELF, + SINGLE_CHAR_PATTERN, + SEARCH_IS_SOME, + TEMPORARY_CSTRING_AS_PTR, + FILTER_NEXT, + FILTER_MAP, + ITER_NTH, + ITER_SKIP_NEXT, + GET_UNWRAP, + STRING_EXTEND_CHARS, + ITER_CLONED_COLLECT + ) } } @@ -706,7 +711,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, - span: Span + span: Span, ) -> bool { if or_has_args { return false; @@ -718,20 +723,22 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: if ["default", "new"].contains(&path) { let arg_ty = cx.tables.expr_ty(arg); - let default_trait_id = if let Some(default_trait_id) = - get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { - default_trait_id - } else { - return false; - }; + let default_trait_id = + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { + default_trait_id + } else { + return false; + }; if implements_trait(cx, arg_ty, default_trait_id, &[]) { - span_lint_and_sugg(cx, - OR_FUN_CALL, - span, - &format!("use of `{}` followed by a call to `{}`", name, path), - "try this", - format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_"))); + span_lint_and_sugg( + cx, + OR_FUN_CALL, + span, + &format!("use of `{}` followed by a call to `{}`", name, path), + "try this", + format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")), + ); return true; } } @@ -749,7 +756,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: self_expr: &hir::Expr, arg: &hir::Expr, or_has_args: bool, - span: Span + span: Span, ) { // don't lint for constant values // FIXME: can we `expect` here instead of match? @@ -765,15 +772,18 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: // (path, fn_has_argument, methods, suffix) let know_types: &[(&[_], _, &[_], _)] = - &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&paths::RESULT, true, &["or", "unwrap_or"], "else")]; + &[ + (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), + (&paths::RESULT, true, &["or", "unwrap_or"], "else"), + ]; let self_ty = cx.tables.expr_ty(self_expr); let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = - know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) { + know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) + { (fn_has_arguments, poss, suffix) } else { return; @@ -789,12 +799,14 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: (false, true) => snippet(cx, fun_span, ".."), }; - span_lint_and_sugg(cx, - OR_FUN_CALL, - span, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg)); + span_lint_and_sugg( + cx, + OR_FUN_CALL, + span, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg), + ); } if args.len() == 2 { @@ -818,32 +830,30 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t let ty = cx.tables.expr_ty(expr); if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty { if let ty::TyRef(..) = inner.sty { - span_lint_and_then(cx, - CLONE_DOUBLE_REF, - expr.span, - "using `clone` on a double-reference; \ + span_lint_and_then( + cx, + CLONE_DOUBLE_REF, + expr.span, + "using `clone` on a double-reference; \ this will copy the reference instead of cloning the inner type", - |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - db.span_suggestion(expr.span, - "try dereferencing it", - format!("({}).clone()", snip.deref())); - }); + |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { + db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref())); + }, + ); return; // don't report clone_on_copy } } if is_copy(cx, ty) { - span_lint_and_then(cx, - CLONE_ON_COPY, - expr.span, - "using `clone` on a `Copy` type", - |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - if let ty::TyRef(..) = cx.tables.expr_ty(arg).sty { - db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref())); - } else { - db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip)); - } - }); + span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { + if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { + if let ty::TyRef(..) = cx.tables.expr_ty(arg).sty { + db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref())); + } else { + db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip)); + } + } + }); } } @@ -860,15 +870,19 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { return; }; - span_lint_and_sugg(cx, - STRING_EXTEND_CHARS, - expr.span, - "calling `.extend(_.chars())`", - "try this", - format!("{}.push_str({}{})", - snippet(cx, args[0].span, "_"), - ref_str, - snippet(cx, target.span, "_"))); + span_lint_and_sugg( + cx, + STRING_EXTEND_CHARS, + expr.span, + "calling `.extend(_.chars())`", + "try this", + format!( + "{}.push_str({}{})", + snippet(cx, args[0].span, "_"), + ref_str, + snippet(cx, target.span, "_") + ), + ); } } @@ -898,12 +912,15 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) && - derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { - span_lint(cx, - ITER_CLONED_COLLECT, - expr.span, - "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable"); + derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() + { + span_lint( + cx, + ITER_CLONED_COLLECT, + expr.span, + "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ + more readable", + ); } } @@ -919,12 +936,16 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is return; // caller is not a type that we want to lint }; - span_lint(cx, - ITER_NTH, - expr.span, - &format!("called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", - mut_str, - caller_type)); + span_lint( + cx, + ITER_NTH, + expr.span, + &format!( + "called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", + mut_str, + caller_type + ), + ); } fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { @@ -947,26 +968,34 @@ fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], i let mut_str = if is_mut { "_mut" } else { "" }; let borrow_str = if is_mut { "&mut " } else { "&" }; - span_lint_and_sugg(cx, - GET_UNWRAP, - expr.span, - &format!("called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", - mut_str, - caller_type), - "try this", - format!("{}{}[{}]", - borrow_str, - snippet(cx, get_args[0].span, "_"), - snippet(cx, get_args[1].span, "_"))); + span_lint_and_sugg( + cx, + GET_UNWRAP, + expr.span, + &format!( + "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", + mut_str, + caller_type + ), + "try this", + format!( + "{}{}[{}]", + borrow_str, + snippet(cx, get_args[0].span, "_"), + snippet(cx, get_args[1].span, "_") + ), + ); } fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) { // lint if caller of skip is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - span_lint(cx, - ITER_SKIP_NEXT, - expr.span, - "called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`"); + span_lint( + cx, + ITER_SKIP_NEXT, + expr.span, + "called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`", + ); } } @@ -1017,14 +1046,18 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { }; if let Some((lint, kind, none_value)) = mess { - span_lint(cx, - lint, - expr.span, - &format!("used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ + span_lint( + cx, + lint, + expr.span, + &format!( + "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ using expect() to provide a better panic \ message", - kind, - none_value)); + kind, + none_value + ), + ); } } @@ -1035,10 +1068,12 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) { let result_type = cx.tables.expr_ty(&ok_args[0]); if let Some(error_type) = get_error_type(cx, result_type) { if has_debug_impl(error_type, cx) { - span_lint(cx, - OK_EXPECT, - expr.span, - "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`"); + span_lint( + cx, + OK_EXPECT, + expr.span, + "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`", + ); } } } @@ -1059,14 +1094,18 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt; if same_span && !multiline { - span_note_and_lint(cx, - OPTION_MAP_UNWRAP_OR, - expr.span, - msg, - expr.span, - &format!("replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", - map_snippet, - unwrap_snippet)); + span_note_and_lint( + cx, + OPTION_MAP_UNWRAP_OR, + expr.span, + msg, + expr.span, + &format!( + "replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", + map_snippet, + unwrap_snippet + ), + ); } else if same_span && multiline { span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); }; @@ -1088,14 +1127,18 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &[hir:: let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt; if same_span && !multiline { - span_note_and_lint(cx, - OPTION_MAP_UNWRAP_OR_ELSE, - expr.span, - msg, - expr.span, - &format!("replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`", - map_snippet, - unwrap_snippet)); + span_note_and_lint( + cx, + OPTION_MAP_UNWRAP_OR_ELSE, + expr.span, + msg, + expr.span, + &format!( + "replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`", + map_snippet, + unwrap_snippet + ), + ); } else if same_span && multiline { span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); }; @@ -1111,12 +1154,14 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &[hir::Expr let filter_snippet = snippet(cx, filter_args[1].span, ".."); if filter_snippet.lines().count() <= 1 { // add note if not multi-line - span_note_and_lint(cx, - FILTER_NEXT, - expr.span, - msg, - expr.span, - &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet)); + span_note_and_lint( + cx, + FILTER_NEXT, + expr.span, + msg, + expr.span, + &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet), + ); } else { span_lint(cx, FILTER_NEXT, expr.span, msg); } @@ -1171,22 +1216,26 @@ fn lint_search_is_some( expr: &hir::Expr, search_method: &str, search_args: &[hir::Expr], - is_some_args: &[hir::Expr] + is_some_args: &[hir::Expr], ) { // lint if caller of search is an Iterator if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { - let msg = format!("called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ + let msg = format!( + "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ expressed by calling `any()`.", - search_method); + search_method + ); let search_snippet = snippet(cx, search_args[1].span, ".."); if search_snippet.lines().count() <= 1 { // add note if not multi-line - span_note_and_lint(cx, - SEARCH_IS_SOME, - expr.span, - &msg, - expr.span, - &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet)); + span_note_and_lint( + cx, + SEARCH_IS_SOME, + expr.span, + &msg, + expr.span, + &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet), + ); } else { span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); } @@ -1233,11 +1282,13 @@ fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) if let Ok(ConstVal::Str(r)) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); - span_lint_and_then(cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - |db| { db.span_suggestion(expr.span, "try using a char instead", hint); }); + span_lint_and_then( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + |db| { db.span_suggestion(expr.span, "try using a char instead", hint); }, + ); } } } @@ -1349,13 +1400,17 @@ impl SelfKind { arg: &hir::Arg, self_ty: &hir::Ty, allow_value_for_ref: bool, - generics: &hir::Generics + generics: &hir::Generics, ) -> bool { - // Self types in the HIR are desugared to explicit self types. So it will always be `self: + // Self types in the HIR are desugared to explicit self types. So it will + // always be `self: // SomeType`, - // where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if the impl is on `Foo`) - // Thus, we only need to test equality against the impl self type or if it is an explicit - // `Self`. Furthermore, the only possible types for `self: ` are `&Self`, `Self`, `&mut Self`, + // where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if + // the impl is on `Foo`) + // Thus, we only need to test equality against the impl self type or if it is + // an explicit + // `Self`. Furthermore, the only possible types for `self: ` are `&Self`, + // `Self`, `&mut Self`, // and `Box`, including the equivalent types with `Foo`. let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty; @@ -1404,18 +1459,22 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { param.name == seg.name && - param.bounds.iter().any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { - let path = &ptr.trait_ref.path; - match_path_old(path, name) && - path.segments.last().map_or(false, |s| if let hir::PathParameters::AngleBracketedParameters(ref data) = - s.parameters { - data.types.len() == 1 && (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty)) - } else { - false + param.bounds.iter().any(|bound| { + if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path_old(path, name) && + path.segments.last().map_or(false, |s| { + if let hir::PathParameters::AngleBracketedParameters(ref data) = s.parameters { + data.types.len() == 1 && + (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty)) + } else { + false + } + }) + } else { + false + } }) - } else { - false - }) }) }) } @@ -1424,7 +1483,9 @@ fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { match (&ty.node, &self_ty.node) { (&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => { - ty_path.segments.iter().map(|seg| seg.name).eq(self_ty_path.segments.iter().map(|seg| seg.name)) + ty_path.segments.iter().map(|seg| seg.name).eq( + self_ty_path.segments.iter().map(|seg| seg.name), + ) }, _ => false, } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 70f25e7dff0..67b0b1e167d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -14,7 +14,8 @@ use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integ use utils::sugg::Sugg; use syntax::ast::{LitKind, CRATE_NODE_ID, FloatTy}; -/// **What it does:** Checks for function arguments and let bindings denoted as `ref`. +/// **What it does:** Checks for function arguments and let bindings denoted as +/// `ref`. /// /// **Why is this bad?** The `ref` declaration makes the function take an owned /// value, but turns the argument into a reference (which means that the value @@ -118,7 +119,8 @@ declare_lint! { /// **What it does:** Checks for patterns in the form `name @ _`. /// -/// **Why is this bad?** It's almost always more readable to just use direct bindings. +/// **Why is this bad?** It's almost always more readable to just use direct +/// bindings. /// /// **Known problems:** None. /// @@ -135,7 +137,8 @@ declare_lint! { "using `name @ _` in a pattern" } -/// **What it does:** Checks for the use of bindings with a single leading underscore. +/// **What it does:** Checks for the use of bindings with a single leading +/// underscore. /// /// **Why is this bad?** A single leading underscore is usually used to indicate /// that a binding will not be used. Using such a binding breaks this @@ -147,7 +150,8 @@ declare_lint! { /// **Example:** /// ```rust /// let _x = 0; -/// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore. +/// let y = _x + 1; // Here we are using `_x`, even though it has a leading +/// underscore. /// // We should rename `_x` to `x` /// ``` declare_lint! { @@ -156,11 +160,14 @@ declare_lint! { "using a binding which is prefixed with an underscore" } -/// **What it does:** Checks for the use of short circuit boolean conditions as a +/// **What it does:** Checks for the use of short circuit boolean conditions as +/// a /// statement. /// -/// **Why is this bad?** Using a short circuit boolean condition as a statement may -/// hide the fact that the second part is executed or not depending on the outcome of +/// **Why is this bad?** Using a short circuit boolean condition as a statement +/// may +/// hide the fact that the second part is executed or not depending on the +/// outcome of /// the first part. /// /// **Known problems:** None. @@ -198,15 +205,17 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(TOPLEVEL_REF_ARG, - CMP_NAN, - FLOAT_CMP, - CMP_OWNED, - MODULO_ONE, - REDUNDANT_PATTERN, - USED_UNDERSCORE_BINDING, - SHORT_CIRCUIT_STATEMENT, - ZERO_PTR) + lint_array!( + TOPLEVEL_REF_ARG, + CMP_NAN, + FLOAT_CMP, + CMP_OWNED, + MODULO_ONE, + REDUNDANT_PATTERN, + USED_UNDERSCORE_BINDING, + SHORT_CIRCUIT_STATEMENT, + ZERO_PTR + ) } } @@ -218,7 +227,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { decl: &'tcx FnDecl, body: &'tcx Body, _: Span, - _: NodeId + _: NodeId, ) { if let FnKind::Closure(_) = k { // Does not apply to closures @@ -228,11 +237,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match arg.pat.node { PatKind::Binding(BindingAnnotation::Ref, _, _, _) | PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => { - span_lint(cx, - TOPLEVEL_REF_ARG, - arg.pat.span, - "`ref` directly on a function argument is ignored. Consider using a reference type \ - instead."); + span_lint( + cx, + TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. Consider using a reference type \ + instead.", + ); }, _ => {}, } @@ -316,7 +327,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || - name.ends_with("_eq") { + name.ends_with("_eq") + { return; } } @@ -324,9 +336,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let lhs = Sugg::hir(cx, left, ".."); let rhs = Sugg::hir(cx, right, ".."); - db.span_suggestion(expr.span, - "consider comparing them within some error", - format!("({}).abs() < error", lhs - rhs)); + db.span_suggestion( + expr.span, + "consider comparing them within some error", + format!("({}).abs() < error", lhs - rhs), + ); db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); }); } else if op == BiRem && is_integer_literal(right, 1) { @@ -347,7 +361,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { binding != "_result" && // FIXME: #944 is_used(cx, expr) && // don't lint if the declaration is in a macro - non_macro_local(cx, &cx.tables.qpath_def(qpath, expr.id)) { + non_macro_local(cx, &cx.tables.qpath_def(qpath, expr.id)) + { Some(binding) } else { None @@ -364,22 +379,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => None, }; if let Some(binding) = binding { - span_lint(cx, - USED_UNDERSCORE_BINDING, - expr.span, - &format!("used binding `{}` which is prefixed with an underscore. A leading \ + span_lint( + cx, + USED_UNDERSCORE_BINDING, + expr.span, + &format!( + "used binding `{}` which is prefixed with an underscore. A leading \ underscore signals that a binding will not be used.", - binding)); + binding + ), + ); } } fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node { if right.node == PatKind::Wild { - span_lint(cx, - REDUNDANT_PATTERN, - pat.span, - &format!("the `{} @ _` pattern can be written as just `{}`", ident.node, ident.node)); + span_lint( + cx, + REDUNDANT_PATTERN, + pat.span, + &format!("the `{} @ _` pattern can be written as just `{}`", ident.node, ident.node), + ); } } } @@ -388,10 +409,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { path.segments.last().map(|seg| if seg.name == "NAN" { - span_lint(cx, - CMP_NAN, - expr.span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead"); + span_lint( + cx, + CMP_NAN, + expr.span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", + ); }); } } @@ -421,7 +444,7 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || - val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + val.try_cmp(neg_infinity) == Ok(Ordering::Equal) }, FloatTy::F64 => { let zero = ConstFloat { @@ -440,7 +463,7 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || - val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + val.try_cmp(neg_infinity) == Ok(Ordering::Equal) }, } } else { @@ -490,37 +513,43 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { .builtin_deref(true, ty::LvaluePreference::NoPreference) .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty])) // arg impls PartialEq - && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) { + && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) + { return; } - span_lint_and_then(cx, - CMP_OWNED, - expr.span, - "this creates an owned instance just for comparison", - |db| { - // this is as good as our recursion check can get, we can't prove that the current function is - // called by - // PartialEq::eq, but we can at least ensure that this code is not part of it - let parent_fn = cx.tcx.hir.get_parent(expr.id); - let parent_impl = cx.tcx.hir.get_parent(parent_fn); - if parent_impl != CRATE_NODE_ID { - if let map::NodeItem(item) = cx.tcx.hir.get(parent_impl) { - if let ItemImpl(.., Some(ref trait_ref), _, _) = item.node { - if trait_ref.path.def.def_id() == partial_eq_trait_id { - // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise we go into - // recursion - db.span_label(expr.span, "try calling implementing the comparison without allocating"); - return; + span_lint_and_then( + cx, + CMP_OWNED, + expr.span, + "this creates an owned instance just for comparison", + |db| { + // this is as good as our recursion check can get, we can't prove that the + // current function is + // called by + // PartialEq::eq, but we can at least ensure that this code is not part of it + let parent_fn = cx.tcx.hir.get_parent(expr.id); + let parent_impl = cx.tcx.hir.get_parent(parent_fn); + if parent_impl != CRATE_NODE_ID { + if let map::NodeItem(item) = cx.tcx.hir.get(parent_impl) { + if let ItemImpl(.., Some(ref trait_ref), _, _) = item.node { + if trait_ref.path.def.def_id() == partial_eq_trait_id { + // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise + // we go into + // recursion + db.span_label(expr.span, "try calling implementing the comparison without allocating"); + return; + } } } } - } - db.span_suggestion(expr.span, "try", snip.to_string()); - }); + db.span_suggestion(expr.span, "try", snip.to_string()); + }, + ); } -/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea +/// Heuristic to see if an expression is used. Should be compatible with +/// `unused_variables`'s idea /// of what it means for an expression to be "used". fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { @@ -534,10 +563,14 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { } } -/// Test whether an expression is in a macro expansion (e.g. something generated by +/// Test whether an expression is in a macro expansion (e.g. something +/// generated by /// `#[derive(...)`] or the like). fn in_attributes_expansion(expr: &Expr) -> bool { - expr.span.ctxt.outer().expn_info().map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_))) + expr.span.ctxt.outer().expn_info().map_or( + false, + |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)), + ) } /// Test whether `def` is a variable defined outside a macro. @@ -545,10 +578,9 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { def::Def::Local(def_id) | def::Def::Upvar(def_id, _, _) => { - let id = cx.tcx - .hir - .as_local_node_id(def_id) - .expect("local variables should be found in the same crate"); + let id = cx.tcx.hir.as_local_node_id(def_id).expect( + "local variables should be found in the same crate", + ); !in_macro(cx.tcx.hir.span(id)) }, _ => false, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index c63dff52ae9..52a97024e44 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -40,9 +40,11 @@ declare_lint! { "function arguments having names which only differ by an underscore" } -/// **What it does:** Detects closures called in the same expression where they are defined. +/// **What it does:** Detects closures called in the same expression where they +/// are defined. /// -/// **Why is this bad?** It is unnecessarily adding to the expression's complexity. +/// **Why is this bad?** It is unnecessarily adding to the expression's +/// complexity. /// /// **Known problems:** None. /// @@ -73,7 +75,8 @@ declare_lint! { "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++" } -/// **What it does:** Warns on hexadecimal literals with mixed-case letter digits. +/// **What it does:** Warns on hexadecimal literals with mixed-case letter +/// digits. /// /// **Why is this bad?** It looks confusing. /// @@ -89,7 +92,8 @@ declare_lint! { "hex literals whose letter digits are not consistently upper- or lowercased" } -/// **What it does:** Warns if literal suffixes are not separated by an underscore. +/// **What it does:** Warns if literal suffixes are not separated by an +/// underscore. /// /// **Why is this bad?** It is much less readable. /// @@ -107,8 +111,10 @@ declare_lint! { /// **What it does:** Warns if an integral constant literal starts with `0`. /// -/// **Why is this bad?** In some languages (including the infamous C language and most of its -/// family), this marks an octal constant. In Rust however, this is a decimal constant. This could +/// **Why is this bad?** In some languages (including the infamous C language +/// and most of its +/// family), this marks an octal constant. In Rust however, this is a decimal +/// constant. This could /// be confusing for both the writer and a reader of the constant. /// /// **Known problems:** None. @@ -167,14 +173,16 @@ pub struct MiscEarly; impl LintPass for MiscEarly { fn get_lints(&self) -> LintArray { - lint_array!(UNNEEDED_FIELD_PATTERN, - DUPLICATE_UNDERSCORE_ARGUMENT, - REDUNDANT_CLOSURE_CALL, - DOUBLE_NEG, - MIXED_CASE_HEX_LITERALS, - UNSEPARATED_LITERAL_SUFFIX, - ZERO_PREFIXED_LITERAL, - BUILTIN_TYPE_SHADOW) + lint_array!( + UNNEEDED_FIELD_PATTERN, + DUPLICATE_UNDERSCORE_ARGUMENT, + REDUNDANT_CLOSURE_CALL, + DOUBLE_NEG, + MIXED_CASE_HEX_LITERALS, + UNSEPARATED_LITERAL_SUFFIX, + ZERO_PREFIXED_LITERAL, + BUILTIN_TYPE_SHADOW + ) } } @@ -183,10 +191,12 @@ impl EarlyLintPass for MiscEarly { for ty in &gen.ty_params { let name = ty.ident.name.as_str(); if constants::BUILTIN_TYPES.contains(&&*name) { - span_lint(cx, - BUILTIN_TYPE_SHADOW, - ty.span, - &format!("This generic shadows the built-in type `{}`", name)); + span_lint( + cx, + BUILTIN_TYPE_SHADOW, + ty.span, + &format!("This generic shadows the built-in type `{}`", name), + ); } } } @@ -194,7 +204,11 @@ impl EarlyLintPass for MiscEarly { fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; - let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name; + let type_name = npat.segments + .last() + .expect("A path must have at least one segment") + .identifier + .name; for field in pfields { if field.node.pat.node == PatKind::Wild { @@ -202,11 +216,13 @@ impl EarlyLintPass for MiscEarly { } } if !pfields.is_empty() && wilds == pfields.len() { - span_help_and_lint(cx, - UNNEEDED_FIELD_PATTERN, - pat.span, - "All the struct fields are matched to a wildcard pattern, consider using `..`.", - &format!("Try with `{} {{ .. }}` instead", type_name)); + span_help_and_lint( + cx, + UNNEEDED_FIELD_PATTERN, + pat.span, + "All the struct fields are matched to a wildcard pattern, consider using `..`.", + &format!("Try with `{} {{ .. }}` instead", type_name), + ); return; } if wilds > 0 { @@ -223,19 +239,21 @@ impl EarlyLintPass for MiscEarly { if field.node.pat.node == PatKind::Wild { wilds -= 1; if wilds > 0 { - span_lint(cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "You matched a field with a wildcard pattern. Consider using `..` instead"); + span_lint( + cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` instead", + ); } else { - span_help_and_lint(cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "You matched a field with a wildcard pattern. Consider using `..` \ + span_help_and_lint( + cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "You matched a field with a wildcard pattern. Consider using `..` \ instead", - &format!("Try with `{} {{ {}, .. }}`", - type_name, - normal[..].join(", "))); + &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), + ); } } } @@ -252,12 +270,16 @@ impl EarlyLintPass for MiscEarly { if arg_name.starts_with('_') { if let Some(correspondence) = registered_names.get(&arg_name[1..]) { - span_lint(cx, - DUPLICATE_UNDERSCORE_ARGUMENT, - *correspondence, - &format!("`{}` already exists, having another argument having almost the same \ + span_lint( + cx, + DUPLICATE_UNDERSCORE_ARGUMENT, + *correspondence, + &format!( + "`{}` already exists, having another argument having almost the same \ name makes code comprehension and documentation more difficult", - arg_name[1..].to_owned()));; + arg_name[1..].to_owned() + ), + );; } } else { registered_names.insert(arg_name, arg.pat.span); @@ -287,10 +309,12 @@ impl EarlyLintPass for MiscEarly { }, ExprKind::Unary(UnOp::Neg, ref inner) => { if let ExprKind::Unary(UnOp::Neg, _) = inner.node { - span_lint(cx, - DOUBLE_NEG, - expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op"); + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); } }, ExprKind::Lit(ref lit) => self.check_lit(cx, lit), diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index c38402ad29c..17b3ad4d9e2 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -11,12 +11,16 @@ // except according to those terms. // -// Note: More specifically this lint is largely inspired (aka copied) from *rustc*'s +// Note: More specifically this lint is largely inspired (aka copied) from +// *rustc*'s // [`missing_doc`]. // // [`missing_doc`]: // https://github. // com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin. +// +// +// // rs#L246 // @@ -28,10 +32,13 @@ use syntax::attr; use syntax::codemap::Span; use utils::in_macro; -/// **What it does:** Warns if there is missing doc for any documentable item (public or private). +/// **What it does:** Warns if there is missing doc for any documentable item +/// (public or private). /// -/// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS` allowed-by-default lint for -/// public members, but has no way to enforce documentation of private items. This lint fixes that. +/// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS` +/// allowed-by-default lint for +/// public members, but has no way to enforce documentation of private items. +/// This lint fixes that. /// /// **Known problems:** None. declare_lint! { @@ -58,7 +65,9 @@ impl MissingDoc { } fn doc_hidden(&self) -> bool { - *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") + *self.doc_hidden_stack.last().expect( + "empty doc_hidden_stack", + ) } fn check_missing_docs_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { @@ -77,11 +86,15 @@ impl MissingDoc { return; } - let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name().map_or(false, |n| n == "doc")); + let has_doc = attrs.iter().any(|a| { + a.is_value_str() && a.name().map_or(false, |n| n == "doc") + }); if !has_doc { - cx.span_lint(MISSING_DOCS_IN_PRIVATE_ITEMS, - sp, - &format!("missing documentation for {}", desc)); + cx.span_lint( + MISSING_DOCS_IN_PRIVATE_ITEMS, + sp, + &format!("missing documentation for {}", desc), + ); } } } @@ -95,13 +108,13 @@ impl LintPass for MissingDoc { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { let doc_hidden = self.doc_hidden() || - attrs.iter().any(|attr| { - attr.check_name("doc") && - match attr.meta_item_list() { - None => false, - Some(l) => attr::list_contains_name(&l[..], "hidden"), - } - }); + attrs.iter().any(|attr| { + attr.check_name("doc") && + match attr.meta_item_list() { + None => false, + Some(l) => attr::list_contains_name(&l[..], "hidden"), + } + }); self.doc_hidden_stack.push(doc_hidden); } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index fc3107c3068..e8133050475 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -22,7 +22,7 @@ declare_lint! { "usage of double-mut refs, e.g. `&mut &mut ...`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct MutMut; impl LintPass for MutMut { @@ -64,26 +64,37 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { intravisit::walk_expr(self, body); } else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node { if let hir::ExprAddrOf(hir::MutMutable, _) = e.node { - span_lint(self.cx, - MUT_MUT, - expr.span, - "generally you want to avoid `&mut &mut _` if possible"); + span_lint( + self.cx, + MUT_MUT, + expr.span, + "generally you want to avoid `&mut &mut _` if possible", + ); } else if let ty::TyRef(_, ty::TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty { - span_lint(self.cx, - MUT_MUT, - expr.span, - "this expression mutably borrows a mutable reference. Consider reborrowing"); + span_lint( + self.cx, + MUT_MUT, + expr.span, + "this expression mutably borrows a mutable reference. Consider reborrowing", + ); } } } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node { + if let hir::TyRptr(_, + hir::MutTy { + ty: ref pty, + mutbl: hir::MutMutable, + }) = ty.node + { if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node { - span_lint(self.cx, - MUT_MUT, - ty.span, - "generally you want to avoid `&mut &mut _` if possible"); + span_lint( + self.cx, + MUT_MUT, + ty.span, + "generally you want to avoid `&mut &mut _` if possible", + ); } } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 0e2c0412702..0c0c8f4061f 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -24,7 +24,7 @@ declare_lint! { } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct UnnecessaryMutPassed; impl LintPass for UnnecessaryMutPassed { @@ -38,10 +38,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { match e.node { ExprCall(ref fn_expr, ref arguments) => { if let ExprPath(ref path) = fn_expr.node { - check_arguments(cx, - arguments, - cx.tables.expr_ty(fn_expr), - &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); + check_arguments( + cx, + arguments, + cx.tables.expr_ty(fn_expr), + &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + ); } }, ExprMethodCall(ref path, _, ref arguments) => { @@ -64,10 +66,12 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ ty::TyRef(_, ty::TypeAndMut { mutbl: MutImmutable, .. }) | ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => { if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint(cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method `{}` doesn't need a mutable reference", name)); + span_lint( + cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method `{}` doesn't need a mutable reference", name), + ); } }, _ => (), diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 085067935a0..25a7118ceda 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -28,9 +28,11 @@ declare_lint! { "using a mutex where an atomic value could be used instead" } -/// **What it does:** Checks for usages of `Mutex` where `X` is an integral type. +/// **What it does:** Checks for usages of `Mutex` where `X` is an integral +/// type. /// -/// **Why is this bad?** Using a mutex just to make access to a plain integer sequential is +/// **Why is this bad?** Using a mutex just to make access to a plain integer +/// sequential is /// shooting flies with cannons. `std::atomic::usize` is leaner and faster. /// /// **Known problems:** This lint cannot detect if the mutex is actually used @@ -61,9 +63,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { if match_type(cx, ty, &paths::MUTEX) { let mutex_param = subst.type_at(0); if let Some(atomic_name) = get_atomic_name(mutex_param) { - let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ + let msg = format!( + "Consider using an {} instead of a Mutex here. If you just want the locking \ behaviour and not the internal type, consider using Mutex<()>.", - atomic_name); + atomic_name + ); match mutex_param.sty { ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 4456547c777..52f0df12bcd 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -9,7 +9,8 @@ use syntax::codemap::Spanned; use utils::{span_lint, span_lint_and_sugg, snippet}; use utils::sugg::Sugg; -/// **What it does:** Checks for expressions of the form `if c { true } else { false }` +/// **What it does:** Checks for expressions of the form `if c { true } else { +/// false }` /// (or vice versa) and suggest using the condition directly. /// /// **Why is this bad?** Redundant code. @@ -47,7 +48,7 @@ declare_lint! { "comparing a variable to a boolean, e.g. `if x == true`" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NeedlessBool; impl LintPass for NeedlessBool { @@ -70,28 +71,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { snip.to_string() }; - span_lint_and_sugg(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression returns a bool literal", - "you can reduce it to", - hint); + span_lint_and_sugg( + cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression returns a bool literal", + "you can reduce it to", + hint, + ); }; if let ExprBlock(ref then_block) = then_block.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { - span_lint(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression will always return true"); + span_lint( + cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression will always return true", + ); }, (RetBool(false), RetBool(false)) | (Bool(false), Bool(false)) => { - span_lint(cx, - NEEDLESS_BOOL, - e.span, - "this if-then-else expression will always return false"); + span_lint( + cx, + NEEDLESS_BOOL, + e.span, + "this if-then-else expression will always return false", + ); }, (RetBool(true), RetBool(false)) => reduce(true, false), (Bool(true), Bool(false)) => reduce(false, false), @@ -106,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { } } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct BoolComparison; impl LintPass for BoolComparison { @@ -122,39 +129,47 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { let hint = snippet(cx, right_side.span, "..").into_owned(); - span_lint_and_sugg(cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); }, (Other, Bool(true)) => { let hint = snippet(cx, left_side.span, "..").into_owned(); - span_lint_and_sugg(cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); }, (Bool(false), Other) => { let hint = Sugg::hir(cx, right_side, ".."); - span_lint_and_sugg(cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string()); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); }, (Other, Bool(false)) => { let hint = Sugg::hir(cx, left_side, ".."); - span_lint_and_sugg(cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string()); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); }, _ => (), } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 385fcc86adb..b331d6910a3 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -26,7 +26,7 @@ declare_lint! { "taking a reference that is going to be automatically dereferenced" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NeedlessBorrow; impl LintPass for NeedlessBorrow { diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index bfe52a41214..6f81c811414 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -9,7 +9,8 @@ use utils::{span_lint, in_macro}; /// **What it does:** Checks for useless borrowed references. /// -/// **Why is this bad?** It is completely useless and make the code look more complex than it +/// **Why is this bad?** It is completely useless and make the code look more +/// complex than it /// actually is. /// /// **Known problems:** None. @@ -19,7 +20,8 @@ use utils::{span_lint, in_macro}; /// let mut v = Vec::::new(); /// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); /// ``` -/// This clojure takes a reference on something that has been matched as a reference and +/// This clojure takes a reference on something that has been matched as a +/// reference and /// de-referenced. /// As such, it could just be |a| a.is_empty() declare_lint! { diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 076bf82b687..692fa19f3ba 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -99,7 +99,7 @@ declare_lint! { "`continue` statements that can be replaced by a rearrangement of code" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NeedlessContinue; impl LintPass for NeedlessContinue { @@ -116,59 +116,60 @@ impl EarlyLintPass for NeedlessContinue { } } -/* This lint has to mainly deal with two cases of needless continue statements. - * - * Case 1 [Continue inside else block]: - * - * loop { - * // region A - * if cond { - * // region B - * } else { - * continue; - * } - * // region C - * } - * - * This code can better be written as follows: - * - * loop { - * // region A - * if cond { - * // region B - * // region C - * } - * } - * - * Case 2 [Continue inside then block]: - * - * loop { - * // region A - * if cond { - * continue; - * // potentially more code here. - * } else { - * // region B - * } - * // region C - * } - * - * - * This snippet can be refactored to: - * - * loop { - * // region A - * if !cond { - * // region B - * // region C - * } - * } - * */ +/* This lint has to mainly deal with two cases of needless continue + * statements. */ +// Case 1 [Continue inside else block]: +// +// loop { +// // region A +// if cond { +// // region B +// } else { +// continue; +// } +// // region C +// } +// +// This code can better be written as follows: +// +// loop { +// // region A +// if cond { +// // region B +// // region C +// } +// } +// +// Case 2 [Continue inside then block]: +// +// loop { +// // region A +// if cond { +// continue; +// // potentially more code here. +// } else { +// // region B +// } +// // region C +// } +// +// +// This snippet can be refactored to: +// +// loop { +// // region A +// if !cond { +// // region B +// // region C +// } +// } +// /// Given an expression, returns true if either of the following is true /// /// - The expression is a `continue` node. -/// - The expression node is a block with the first statement being a `continue`. +/// - The expression node is a block with the first statement being a +/// `continue`. /// fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { match else_expr.node { @@ -195,7 +196,8 @@ fn is_first_block_stmt_continue(block: &ast::Block) -> bool { /// If `expr` is a loop expression (while/while let/for/loop), calls `func` with /// the AST object representing the loop block of `expr`. fn with_loop_block(expr: &ast::Expr, mut func: F) - where F: FnMut(&ast::Block) +where + F: FnMut(&ast::Block), { match expr.node { ast::ExprKind::While(_, ref loop_block, _) | @@ -206,7 +208,8 @@ fn with_loop_block(expr: &ast::Expr, mut func: F) } } -/// If `stmt` is an if expression node with an `else` branch, calls func with the +/// If `stmt` is an if expression node with an `else` branch, calls func with +/// the /// following: /// /// - The `if` expression itself, @@ -215,7 +218,8 @@ fn with_loop_block(expr: &ast::Expr, mut func: F) /// - The `else` expression. /// fn with_if_expr(stmt: &ast::Stmt, mut func: F) - where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr) +where + F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr), { match stmt.node { ast::StmtKind::Semi(ref e) | @@ -271,10 +275,18 @@ fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: L // expr is the expression which the lint warning message refers to. let (snip, message, expr) = match typ { LintType::ContinueInsideElseBlock => { - (suggestion_snippet_for_continue_inside_else(ctx, data, header), MSG_REDUNDANT_ELSE_BLOCK, data.else_expr) + ( + suggestion_snippet_for_continue_inside_else(ctx, data, header), + MSG_REDUNDANT_ELSE_BLOCK, + data.else_expr, + ) }, LintType::ContinueInsideThenBlock => { - (suggestion_snippet_for_continue_inside_if(ctx, data, header), MSG_ELSE_BLOCK_NOT_NEEDED, data.if_expr) + ( + suggestion_snippet_for_continue_inside_if(ctx, data, header), + MSG_ELSE_BLOCK_NOT_NEEDED, + data.if_expr, + ) }, }; span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); @@ -407,7 +419,8 @@ pub fn erode_from_front(s: &str) -> String { } /// If `s` contains the code for a block, delimited by braces, this function -/// tries to get the contents of the block. If there is no closing brace present, +/// tries to get the contents of the block. If there is no closing brace +/// present, /// an empty string is returned. pub fn erode_block(s: &str) -> String { erode_from_back(&erode_from_front(s)) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 0740ca483f7..e4efaf495a8 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -13,10 +13,12 @@ use utils::{in_macro, is_self, is_copy, implements_trait, get_trait_def_id, matc multispan_sugg, paths}; use std::collections::{HashSet, HashMap}; -/// **What it does:** Checks for functions taking arguments by value, but not consuming them in its +/// **What it does:** Checks for functions taking arguments by value, but not +/// consuming them in its /// body. /// -/// **Why is this bad?** Taking arguments by reference is more flexible and can sometimes avoid +/// **Why is this bad?** Taking arguments by reference is more flexible and can +/// sometimes avoid /// unnecessary allocations. /// /// **Known problems:** Hopefully none. @@ -53,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { decl: &'tcx FnDecl, body: &'tcx Body, span: Span, - node_id: NodeId + node_id: NodeId, ) { if in_macro(span) { return; @@ -87,8 +89,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .collect() }; - // Collect moved variables and spans which will need dereferencings from the function body. - let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = { + // Collect moved variables and spans which will need dereferencings from the + // function body. + let MovedVariablesCtxt { + moved_vars, + spans_need_deref, + .. + } = { let mut ctx = MovedVariablesCtxt::new(cx); let region_maps = &cx.tcx.region_maps(fn_def_id); euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); @@ -102,14 +109,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Determines whether `ty` implements `Borrow` (U != ty) specifically. // This is needed due to the `Borrow for T` blanket impl. - let implements_borrow_trait = preds.iter() + let implements_borrow_trait = preds + .iter() .filter_map(|pred| if let ty::Predicate::Trait(ref poly_trait_ref) = *pred { Some(poly_trait_ref.skip_binder()) } else { None }) .filter(|tpred| tpred.def_id() == borrow_trait && tpred.self_ty() == ty) - .any(|tpred| tpred.input_types().nth(1).expect("Borrow trait must have an parameter") != ty); + .any(|tpred| { + tpred.input_types().nth(1).expect( + "Borrow trait must have an parameter", + ) != ty + }); if_let_chain! {[ !is_self(arg), @@ -177,7 +189,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { struct MovedVariablesCtxt<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, moved_vars: HashSet, - /// Spans which need to be prefixed with `*` for dereferencing the suggested additional + /// Spans which need to be prefixed with `*` for dereferencing the + /// suggested additional /// reference. spans_need_deref: HashMap>, } diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index da6f635e34e..d6624411e2f 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -36,10 +36,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ty = cx.tables.expr_ty(expr); if let ty::TyAdt(def, _) = ty.sty { if fields.len() == def.struct_variant().fields.len() { - span_lint(cx, - NEEDLESS_UPDATE, - base.span, - "struct update has no effect, all the fields in the struct have already been specified"); + span_lint( + cx, + NEEDLESS_UPDATE, + base.span, + "struct update has no effect, all the fields in the struct have already been specified", + ); } } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index e5644b606f5..c6bd91919f5 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -80,7 +80,7 @@ declare_lint! { "`fn new() -> Self` without `#[derive]`able `Default` implementation" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NewWithoutDefault; impl LintPass for NewWithoutDefault { @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { decl: &'tcx hir::FnDecl, _: &'tcx hir::Body, span: Span, - id: ast::NodeId + id: ast::NodeId, ) { if in_external_macro(cx, span) { return; @@ -109,13 +109,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if !sig.generics.ty_params.is_empty() { - // when the result of `new()` depends on a type parameter we should not require an + // when the result of `new()` depends on a type parameter we should not require + // an // impl of `Default` return; } if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { - let self_ty = cx.tcx - .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); + let self_ty = cx.tcx.type_of( + cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)), + ); if_let_chain!{[ same_tys(cx, self_ty, return_ty(cx, id)), let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index a88662356fb..c57df468f7c 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -62,10 +62,10 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), Expr_::ExprStruct(_, ref fields, ref base) => { fields.iter().all(|field| has_no_effect(cx, &field.expr)) && - match *base { - Some(ref base) => has_no_effect(cx, base), - None => true, - } + match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } }, Expr_::ExprCall(ref callee, ref args) => { if let Expr_::ExprPath(ref qpath) = callee.node { @@ -83,11 +83,11 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { }, Expr_::ExprBlock(ref block) => { block.stmts.is_empty() && - if let Some(ref expr) = block.expr { - has_no_effect(cx, expr) - } else { - false - } + if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) + } else { + false + } }, _ => false, } @@ -120,12 +120,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } } - span_lint_and_sugg(cx, - UNNECESSARY_OPERATION, - stmt.span, - "statement can be reduced", - "replace it with", - snippet); + span_lint_and_sugg( + cx, + UNNECESSARY_OPERATION, + stmt.span, + "statement can be reduced", + "replace it with", + snippet, + ); } } } @@ -152,7 +154,14 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), Expr_::ExprStruct(_, ref fields, ref base) => { - Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) + Some( + fields + .iter() + .map(|f| &f.expr) + .chain(base) + .map(Deref::deref) + .collect(), + ) }, Expr_::ExprCall(ref callee, ref args) => { if let Expr_::ExprPath(ref qpath) = callee.node { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 6b97ffee6db..fa915e83aed 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -113,7 +113,13 @@ fn whitelisted(interned_name: &str, list: &[&str]) -> bool { return true; } // *_name - if interned_name.chars().rev().zip(name.chars().rev()).all(|(l, r)| l == r) { + if interned_name.chars().rev().zip(name.chars().rev()).all( + |(l, + r)| { + l == r + }, + ) + { return true; } } @@ -128,10 +134,12 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } self.0.single_char_names.push(c); if self.0.single_char_names.len() as u64 >= self.0.lint.single_char_binding_names_threshold { - span_lint(self.0.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!("{}th binding whose name is just one char", self.0.single_char_names.len())); + span_lint( + self.0.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!("{}th binding whose name is just one char", self.0.single_char_names.len()), + ); } } fn check_name(&mut self, span: Span, name: Name) { @@ -166,22 +174,41 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } else { let mut interned_chars = interned_name.chars(); let mut existing_chars = existing_name.interned.chars(); - let first_i = interned_chars.next().expect("we know we have at least one char"); - let first_e = existing_chars.next().expect("we know we have at least one char"); + let first_i = interned_chars.next().expect( + "we know we have at least one char", + ); + let first_e = existing_chars.next().expect( + "we know we have at least one char", + ); let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); if eq_or_numeric(first_i, first_e) { - let last_i = interned_chars.next_back().expect("we know we have at least two chars"); - let last_e = existing_chars.next_back().expect("we know we have at least two chars"); + let last_i = interned_chars.next_back().expect( + "we know we have at least two chars", + ); + let last_e = existing_chars.next_back().expect( + "we know we have at least two chars", + ); if eq_or_numeric(last_i, last_e) { - if interned_chars.zip(existing_chars).filter(|&(i, e)| !eq_or_numeric(i, e)).count() != 1 { + if interned_chars + .zip(existing_chars) + .filter(|&(i, e)| !eq_or_numeric(i, e)) + .count() != 1 + { continue; } } else { - let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); - let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); + let second_last_i = interned_chars.next_back().expect( + "we know we have at least three chars", + ); + let second_last_e = existing_chars.next_back().expect( + "we know we have at least three chars", + ); if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + !interned_chars.zip(existing_chars).all(|(i, e)| { + eq_or_numeric(i, e) + }) + { // allowed similarity foo_x, foo_y // or too many chars differ (foo_x, boo_y) or (foox, booy) continue; @@ -189,10 +216,17 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); } } else { - let second_i = interned_chars.next().expect("we know we have at least two chars"); - let second_e = existing_chars.next().expect("we know we have at least two chars"); + let second_i = interned_chars.next().expect( + "we know we have at least two chars", + ); + let second_e = existing_chars.next().expect( + "we know we have at least two chars", + ); if !eq_or_numeric(second_i, second_e) || second_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { + !interned_chars.zip(existing_chars).all(|(i, e)| { + eq_or_numeric(i, e) + }) + { // allowed similarity x_foo, y_foo // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) continue; @@ -200,20 +234,26 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { split_at = interned_name.chars().next().map(|c| c.len_utf8()); } } - span_lint_and_then(self.0.cx, - SIMILAR_NAMES, - span, - "binding's name is too similar to existing binding", - |diag| { - diag.span_note(existing_name.span, "existing binding defined here"); - if let Some(split) = split_at { - diag.span_help(span, - &format!("separate the discriminating character by an \ + span_lint_and_then( + self.0.cx, + SIMILAR_NAMES, + span, + "binding's name is too similar to existing binding", + |diag| { + diag.span_note(existing_name.span, "existing binding defined here"); + if let Some(split) = split_at { + diag.span_help( + span, + &format!( + "separate the discriminating character by an \ underscore like: `{}_{}`", - &interned_name[..split], - &interned_name[split..])); - } - }); + &interned_name[..split], + &interned_name[split..] + ), + ); + } + }, + ); return; } self.0.names.push(ExistingName { @@ -241,7 +281,8 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { if let Some(ref init) = local.init { self.apply(|this| walk_expr(this, &**init)); } - // add the pattern after the expression because the bindings aren't available yet in the init + // add the pattern after the expression because the bindings aren't available + // yet in the init // expression SimilarNamesNameVisitor(self).visit_pat(&*local.pat); } diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index a831e9bd9b7..ee55ea882b0 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -4,7 +4,8 @@ use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet}; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// -/// **Why is this bad?** Calling `ok()` in if let is unnecessary, instead match on `Ok(pat)` +/// **Why is this bad?** Calling `ok()` in if let is unnecessary, instead match +/// on `Ok(pat)` /// /// **Known problems:** None. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 429d02d068b..e67c1f4d148 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -23,7 +23,7 @@ declare_lint! { } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct NonSensical; impl LintPass for NonSensical { @@ -109,16 +109,19 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, false, false, false, false); - // This code is almost duplicated (oh, the irony), but I haven't found a way to unify it. + // This code is almost duplicated (oh, the irony), but I haven't found a way to + // unify it. for option in options { match *option { (OpenOption::Create, arg) => { if create { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"create\" is called more than once"); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"create\" is called more than once", + ); } else { create = true } @@ -126,10 +129,12 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span }, (OpenOption::Append, arg) => { if append { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"append\" is called more than once"); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"append\" is called more than once", + ); } else { append = true } @@ -137,10 +142,12 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span }, (OpenOption::Truncate, arg) => { if truncate { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"truncate\" is called more than once"); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"truncate\" is called more than once", + ); } else { truncate = true } @@ -148,10 +155,12 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span }, (OpenOption::Read, arg) => { if read { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"read\" is called more than once"); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"read\" is called more than once", + ); } else { read = true } @@ -159,10 +168,12 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span }, (OpenOption::Write, arg) => { if write { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method \"write\" is called more than once"); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "the method \"write\" is called more than once", + ); } else { write = true } @@ -175,9 +186,11 @@ fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\""); } if append && truncate && append_arg && truncate_arg { - span_lint(cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "file opened with \"append\" and \"truncate\""); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with \"append\" and \"truncate\"", + ); } } diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index e7b34136891..f5a6833b4b0 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -5,8 +5,10 @@ use utils::{span_lint_and_sugg, snippet}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: -/// * mixed usage of arithmetic and bit shifting/combining operators without parentheses -/// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) +/// * mixed usage of arithmetic and bit shifting/combining operators without +/// parentheses +/// * a "negative" numeric literal (which is really a unary `-` followed by a +/// numeric literal) /// followed by a method call /// /// **Why is this bad?** Not everyone knows the precedence of those operators by @@ -24,7 +26,7 @@ declare_lint! { "operations where precedence may be unclear" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct Precedence; impl LintPass for Precedence { @@ -37,12 +39,14 @@ impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { let span_sugg = |expr: &Expr, sugg| { - span_lint_and_sugg(cx, - PRECEDENCE, - expr.span, - "operator precedence can trip the unwary", - "consider parenthesizing your expression", - sugg); + span_lint_and_sugg( + cx, + PRECEDENCE, + expr.span, + "operator precedence can trip the unwary", + "consider parenthesizing your expression", + sugg, + ); }; if !is_bit_op(op) { @@ -50,24 +54,30 @@ impl EarlyLintPass for Precedence { } match (is_arith_expr(left), is_arith_expr(right)) { (true, true) => { - let sugg = format!("({}) {} ({})", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, "..")); + let sugg = format!( + "({}) {} ({})", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, "..") + ); span_sugg(expr, sugg); }, (true, false) => { - let sugg = format!("({}) {} {}", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, "..")); + let sugg = format!( + "({}) {} {}", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, "..") + ); span_sugg(expr, sugg); }, (false, true) => { - let sugg = format!("{} {} ({})", - snippet(cx, left.span, ".."), - op.to_string(), - snippet(cx, right.span, "..")); + let sugg = format!( + "{} {} ({})", + snippet(cx, left.span, ".."), + op.to_string(), + snippet(cx, right.span, "..") + ); span_sugg(expr, sugg); }, (false, false) => (), @@ -82,12 +92,14 @@ impl EarlyLintPass for Precedence { LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { - span_lint_and_sugg(cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!("-({})", snippet(cx, rhs.span, ".."))); + span_lint_and_sugg( + cx, + PRECEDENCE, + expr.span, + "unary minus has lower precedence than method call", + "consider adding parentheses to clarify your intent", + format!("-({})", snippet(cx, rhs.span, "..")), + ); }, _ => (), } diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index a7f498af5c2..bf734cc9c0e 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -5,10 +5,12 @@ use utils::paths; use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path_old}; use format::get_argument_fmtstr_parts; -/// **What it does:** This lint warns when you using `print!()` with a format string that +/// **What it does:** This lint warns when you using `print!()` with a format +/// string that /// ends in a newline. /// -/// **Why is this bad?** You should use `println!()` instead, which appends the newline. +/// **Why is this bad?** You should use `println!()` instead, which appends the +/// newline. /// /// **Known problems:** None. /// diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f7017dfc5c3..5b5c63c1aca 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -9,11 +9,14 @@ use syntax::codemap::Span; use syntax_pos::MultiSpan; use utils::{match_path, match_type, paths, span_lint, span_lint_and_then}; -/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless +/// **What it does:** This lint checks for function arguments of type `&String` +/// or `&Vec` unless /// the references are mutable. /// -/// **Why is this bad?** Requiring the argument to be of the specific size makes the function less -/// useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be +/// **Why is this bad?** Requiring the argument to be of the specific size +/// makes the function less +/// useful for no benefit; slices in the form of `&[T]` or `&str` usually +/// suffice and can be /// obtained from other types, too. /// /// **Known problems:** None. @@ -31,7 +34,8 @@ declare_lint! { /// **What it does:** This lint checks for equality comparisons with `ptr::null` /// -/// **Why is this bad?** It's easier and more readable to use the inherent `.is_null()` +/// **Why is this bad?** It's easier and more readable to use the inherent +/// `.is_null()` /// method instead /// /// **Known problems:** None. @@ -46,15 +50,20 @@ declare_lint! { "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead." } -/// **What it does:** This lint checks for functions that take immutable references and return +/// **What it does:** This lint checks for functions that take immutable +/// references and return /// mutable ones. /// -/// **Why is this bad?** This is trivially unsound, as one can create two mutable references -/// from the same (immutable!) source. This [error](https://github.com/rust-lang/rust/issues/39465) +/// **Why is this bad?** This is trivially unsound, as one can create two +/// mutable references +/// from the same (immutable!) source. This +/// [error](https://github.com/rust-lang/rust/issues/39465) /// actually lead to an interim Rust release 1.15.1. /// -/// **Known problems:** To be on the conservative side, if there's at least one mutable reference -/// with the output lifetime, this lint will not trigger. In practice, this case is unlikely anyway. +/// **Known problems:** To be on the conservative side, if there's at least one +/// mutable reference +/// with the output lifetime, this lint will not trigger. In practice, this +/// case is unlikely anyway. /// /// **Example:** /// ```rust @@ -66,7 +75,7 @@ declare_lint! { "fns that create mutable refs from immutable ref args" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct PointerPass; impl LintPass for PointerPass { @@ -102,10 +111,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprBinary(ref op, ref l, ref r) = expr.node { if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) { - span_lint(cx, - CMP_NULL, - expr.span, - "Comparing with null is better expressed by the .is_null() method"); + span_lint( + cx, + CMP_NULL, + expr.span, + "Comparing with null is better expressed by the .is_null() method", + ); } } } @@ -117,19 +128,28 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { let fn_ty = sig.skip_binder(); for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) { - if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { + if let ty::TyRef(_, + ty::TypeAndMut { + ty, + mutbl: MutImmutable, + }) = ty.sty + { if match_type(cx, ty, &paths::VEC) { - span_lint(cx, - PTR_ARG, - arg.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`"); + span_lint( + cx, + PTR_ARG, + arg.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ + with non-Vec-based slices. Consider changing the type to `&[...]`", + ); } else if match_type(cx, ty, &paths::STRING) { - span_lint(cx, - PTR_ARG, - arg.span, - "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`"); + span_lint( + cx, + PTR_ARG, + arg.span, + "writing `&String` instead of `&str` involves a new object where a slice will do. \ + Consider changing the type to `&str`", + ); } } } @@ -138,10 +158,10 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { if let Some((out, MutMutable, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; for (_, ref mutbl, ref argspan) in - decl.inputs - .iter() - .filter_map(|ty| get_rptr_lm(ty)) - .filter(|&(lt, _, _)| lt.name == out.name) { + decl.inputs.iter().filter_map(|ty| get_rptr_lm(ty)).filter( + |&(lt, _, _)| lt.name == out.name, + ) + { if *mutbl == MutMutable { return; } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 037ebf8ba2c..aa43fb6b620 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -21,7 +21,8 @@ declare_lint! { "using `Iterator::step_by(0)`, which produces an infinite iterator" } -/// **What it does:** Checks for zipping a collection with the range of `0.._.len()`. +/// **What it does:** Checks for zipping a collection with the range of +/// `0.._.len()`. /// /// **Why is this bad?** The code is better expressed with `.enumerate()`. /// @@ -37,7 +38,7 @@ declare_lint! { "zipping iterator with a range when `enumerate()` would do" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct StepByZero; impl LintPass for StepByZero { @@ -57,10 +58,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { use rustc_const_math::ConstInt::Usize; if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) { if us.as_u64(cx.sess().target.uint_type) == 0 { - span_lint(cx, - ITERATOR_STEP_BY_ZERO, - expr.span, - "Iterator::step_by(0) will panic at runtime"); + span_lint( + cx, + ITERATOR_STEP_BY_ZERO, + expr.span, + "Iterator::step_by(0) will panic at runtime", + ); } } } else if name == "zip" && args.len() == 2 { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index a148d99aca8..a8360c71f91 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -40,12 +40,14 @@ impl EarlyLintPass for Pass { fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node { if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node { - span_lint_and_sugg(cx, - DEREF_ADDROF, - e.span, - "immediately dereferencing a reference", - "try this", - format!("{}", snippet(cx, addrof_target.span, "_"))); + span_lint_and_sugg( + cx, + DEREF_ADDROF, + e.span, + "immediately dereferencing a reference", + "try this", + format!("{}", snippet(cx, addrof_target.span, "_")), + ); } } } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index f0225591571..4feeb6d0939 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -178,7 +178,8 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { }, 3 => { if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = - (&exprs[0], &exprs[1], &exprs[2]) { + (&exprs[0], &exprs[1], &exprs[2]) + { Some("consider using `==` on `str`s") } else { None @@ -211,18 +212,22 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { match builder.parse(r) { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl)); + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); } }, Err(e) => { - span_lint(cx, - INVALID_REGEX, - str_span(expr.span, r, e.position()), - &format!("regex syntax error: {}", e.description())); + span_lint( + cx, + INVALID_REGEX, + str_span(expr.span, r, e.position()), + &format!("regex syntax error: {}", e.description()), + ); }, } } @@ -230,18 +235,22 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { match builder.parse(&r) { Ok(r) => { if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint(cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl)); + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); } }, Err(e) => { - span_lint(cx, - INVALID_REGEX, - expr.span, - &format!("regex syntax error on position {}: {}", e.position(), e.description())); + span_lint( + cx, + INVALID_REGEX, + expr.span, + &format!("regex syntax error on position {}: {}", e.position(), e.description()), + ); }, } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 41601a80890..b9fcb62de73 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -23,7 +23,8 @@ declare_lint! { "using a return statement like `return expr;` where an expression would suffice" } -/// **What it does:** Checks for `let`-bindings, which are subsequently returned. +/// **What it does:** Checks for `let`-bindings, which are subsequently +/// returned. /// /// **Why is this bad?** It is just extraneous code. Remove it to make your code /// more rusty. @@ -93,13 +94,11 @@ impl ReturnPass { if in_external_macro(cx, inner_span) || in_macro(inner_span) { return; } - span_lint_and_then(cx, - NEEDLESS_RETURN, - ret_span, - "unneeded return statement", - |db| if let Some(snippet) = snippet_opt(cx, inner_span) { - db.span_suggestion(ret_span, "remove `return` as shown", snippet); - }); + span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + db.span_suggestion(ret_span, "remove `return` as shown", snippet); + } + }); } // Check for "let x = EXPR; x" diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index df803473a2a..4feaaa19287 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -9,7 +9,8 @@ use utils::{span_lint, get_trait_def_id, paths}; /// /// **Known problems:** None. /// -/// **Example:** Implementing `Visitor::visit_string` but not `Visitor::visit_str`. +/// **Example:** Implementing `Visitor::visit_string` but not +/// `Visitor::visit_str`. declare_lint! { pub SERDE_API_MISUSE, Warn, @@ -43,10 +44,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde { } if let Some(span) = seen_string { if seen_str.is_none() { - span_lint(cx, - SERDE_API_MISUSE, - span, - "you should not implement `visit_string` without also implementing `visit_str`"); + span_lint( + cx, + SERDE_API_MISUSE, + span, + "you should not implement `visit_string` without also implementing `visit_str`", + ); } } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 8a6b950327b..e80636ca347 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { decl: &'tcx FnDecl, body: &'tcx Body, _: Span, - _: NodeId + _: NodeId, ) { if in_external_macro(cx, body.value.span) { return; @@ -129,7 +129,13 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: return; } if let DeclLocal(ref local) = decl.node { - let Local { ref pat, ref ty, ref init, span, .. } = **local; + let Local { + ref pat, + ref ty, + ref init, + span, + .. + } = **local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } @@ -155,7 +161,7 @@ fn check_pat<'a, 'tcx>( pat: &'tcx Pat, init: Option<&'tcx Expr>, span: Span, - bindings: &mut Vec<(Name, Span)> + bindings: &mut Vec<(Name, Span)>, ) { // TODO: match more stuff / destructuring match pat.node { @@ -184,9 +190,9 @@ fn check_pat<'a, 'tcx>( if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { let name = field.node.name; - let efield = efields.iter() - .find(|f| f.name.node == name) - .map(|f| &*f.expr); + let efield = efields.iter().find(|f| f.name.node == name).map( + |f| &*f.expr, + ); check_pat(cx, &field.node.pat, efield, span, bindings); } } else { @@ -240,39 +246,51 @@ fn lint_shadow<'a, 'tcx: 'a>( span: Span, pattern_span: Span, init: Option<&'tcx Expr>, - prev_span: Span + prev_span: Span, ) { if let Some(expr) = init { if is_self_shadow(name, expr) { - span_lint_and_then(cx, - SHADOW_SAME, - span, - &format!("`{}` is shadowed by itself in `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - |db| { db.span_note(prev_span, "previous binding is here"); }); + span_lint_and_then( + cx, + SHADOW_SAME, + span, + &format!( + "`{}` is shadowed by itself in `{}`", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..") + ), + |db| { db.span_note(prev_span, "previous binding is here"); }, + ); } else if contains_self(name, expr) { - span_lint_and_then(cx, - SHADOW_REUSE, - pattern_span, - &format!("`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - |db| { - db.span_note(expr.span, "initialization happens here"); - db.span_note(prev_span, "previous binding is here"); - }); + span_lint_and_then( + cx, + SHADOW_REUSE, + pattern_span, + &format!( + "`{}` is shadowed by `{}` which reuses the original value", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..") + ), + |db| { + db.span_note(expr.span, "initialization happens here"); + db.span_note(prev_span, "previous binding is here"); + }, + ); } else { - span_lint_and_then(cx, - SHADOW_UNRELATED, - pattern_span, - &format!("`{}` is shadowed by `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..")), - |db| { - db.span_note(expr.span, "initialization happens here"); - db.span_note(prev_span, "previous binding is here"); - }); + span_lint_and_then( + cx, + SHADOW_UNRELATED, + pattern_span, + &format!( + "`{}` is shadowed by `{}`", + snippet(cx, pattern_span, "_"), + snippet(cx, expr.span, "..") + ), + |db| { + db.span_note(expr.span, "initialization happens here"); + db.span_note(prev_span, "previous binding is here"); + }, + ); } } else { @@ -357,7 +375,11 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) + block.stmts.is_empty() && + block.expr.as_ref().map_or( + false, + |e| is_self_shadow(name, e), + ) }, ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path), diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs index ea79a77877a..ecb2c9c3162 100644 --- a/clippy_lints/src/should_assert_eq.rs +++ b/clippy_lints/src/should_assert_eq.rs @@ -2,10 +2,12 @@ use rustc::lint::*; use rustc::hir::*; use utils::{is_direct_expn_of, is_expn_of, implements_trait, span_lint}; -/// **What it does:** Checks for `assert!(x == y)` or `assert!(x != y)` which can be better written +/// **What it does:** Checks for `assert!(x == y)` or `assert!(x != y)` which +/// can be better written /// using `assert_eq` or `assert_ne` if `x` and `y` implement `Debug` trait. /// -/// **Why is this bad?** `assert_eq` and `assert_ne` provide better assertion failure reporting. +/// **Why is this bad?** `assert_eq` and `assert_ne` provide better assertion +/// failure reporting. /// /// **Known problems:** Hopefully none. /// @@ -14,7 +16,8 @@ use utils::{is_direct_expn_of, is_expn_of, implements_trait, span_lint}; /// let (x, y) = (1, 2); /// /// assert!(x == y); // assertion failed: x == y -/// assert_eq!(x, y); // assertion failed: `(left == right)` (left: `1`, right: `2`) +/// assert_eq!(x, y); // assertion failed: `(left == right)` (left: `1`, right: +/// `2`) /// ``` declare_lint! { pub SHOULD_ASSERT_EQ, diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 043d1dff8e5..9b61f902c49 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -96,18 +96,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { } } } - span_lint(cx, - STRING_ADD, - e.span, - "you added something to a string. Consider using `String::push_str()` instead"); + span_lint( + cx, + STRING_ADD, + e.span, + "you added something to a string. Consider using `String::push_str()` instead", + ); } } else if let ExprAssign(ref target, ref src) = e.node { if is_string(cx, target) && is_add(cx, src, target) { - span_lint(cx, - STRING_ADD_ASSIGN, - e.span, - "you assigned the result of adding something to this string. Consider using \ - `String::push_str()` instead"); + span_lint( + cx, + STRING_ADD_ASSIGN, + e.span, + "you assigned the result of adding something to this string. Consider using \ + `String::push_str()` instead", + ); } } } @@ -121,7 +125,11 @@ fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) + block.stmts.is_empty() && + block.expr.as_ref().map_or( + false, + |expr| is_add(cx, expr, target), + ) }, _ => false, } @@ -147,12 +155,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { if let ExprLit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) { - span_lint_and_sugg(cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `as_bytes()` on a string literal", - "consider using a byte string literal instead", - format!("b{}", snippet(cx, args[0].span, r#""foo""#))); + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on a string literal", + "consider using a byte string literal instead", + format!("b{}", snippet(cx, args[0].span, r#""foo""#)), + ); } } } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index b2c56fe8bf3..e17170db192 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -41,7 +41,7 @@ declare_lint! { "`foo = bar; bar = foo` sequence" } -#[derive(Copy,Clone)] +#[derive(Copy, Clone)] pub struct Swap; impl LintPass for Swap { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 1d67e06f811..13555e3bb05 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -49,7 +49,8 @@ declare_lint! { /// /// **Example:** /// ```rust -/// core::intrinsics::transmute(t)` // where the result type is the same as `*t` or `&t`'s +/// core::intrinsics::transmute(t)` // where the result type is the same as +/// `*t` or `&t`'s /// ``` declare_lint! { pub CROSSPOINTER_TRANSMUTE, @@ -79,7 +80,7 @@ pub struct Transmute; impl LintPass for Transmute { fn get_lints(&self) -> LintArray { - lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE] + lint_array!(CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE) } } @@ -95,87 +96,101 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { match (&from_ty.sty, &to_ty.sty) { _ if from_ty == to_ty => { - span_lint(cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty)) + span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ) }, (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => { - span_lint_and_then(cx, - USELESS_TRANSMUTE, - e.span, - "transmute from a reference to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = if ptr_ty == rty { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) - }; + span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = if ptr_ty == rty { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) + }; - db.span_suggestion(e.span, "try", sugg.to_string()); - }) + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ) }, (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => { - span_lint_and_then(cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, - "try", - arg.as_ty(&to_ty.to_string()).to_string()); - }) + span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + }, + ) }, (&ty::TyFloat(_), &ty::TyRef(..)) | (&ty::TyFloat(_), &ty::TyRawPtr(_)) | (&ty::TyChar, &ty::TyRef(..)) | (&ty::TyChar, &ty::TyRawPtr(_)) => { - span_lint(cx, - WRONG_TRANSMUTE, - e.span, - &format!("transmute from a `{}` to a pointer", from_ty)) + span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), + ) }, (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty)) + span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty + ), + ) }, (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => { - span_lint(cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", - from_ty, - to_ty)) + span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), + ) }, (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => { - span_lint_and_then(cx, - TRANSMUTE_PTR_TO_REF, - e.span, - &format!("transmute from a pointer type (`{}`) to a reference type \ + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!( + "transmute from a pointer type (`{}`) to a reference type \ (`{}`)", - from_ty, - to_ty), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + from_ty, + to_ty + ), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - let arg = if from_pty.ty == to_rty.ty { - arg - } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) - }; + let arg = if from_pty.ty == to_rty.ty { + arg + } else { + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) + }; - db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); - }) + db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); + }, + ) }, _ => return, }; @@ -185,8 +200,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } -/// Get the snippet of `Bar` in `…::transmute`. If that snippet is not available , use -/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_` +/// Get the snippet of `Bar` in `…::transmute`. If that snippet is +/// not available , use +/// the type's `ToString` implementation. In weird cases it could lead to types +/// with invalid `'_` /// lifetime, but it should be rare. fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { let seg = last_path_segment(path); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 66cb5671c77..44e33d40a38 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -42,14 +42,21 @@ declare_lint! { /// /// **Why is this bad?** Gankro says: /// -/// > The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection. -/// > It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while -/// > "only" amortized for push/pop, should be faster in the general case for almost every possible -/// > workload, and isn't even amortized at all if you can predict the capacity you need. +/// > The TL;DR of `LinkedList` is that it's built on a massive amount of +/// pointers and indirection. +/// > It wastes memory, it has terrible cache locality, and is all-around slow. +/// `RingBuf`, while +/// > "only" amortized for push/pop, should be faster in the general case for +/// almost every possible +/// > workload, and isn't even amortized at all if you can predict the capacity +/// you need. /// > -/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists. -/// > This is because they can just mangle some pointers instead of actually copying the data. Even -/// > if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better +/// > `LinkedList`s are only really good if you're doing a lot of merging or +/// splitting of lists. +/// > This is because they can just mangle some pointers instead of actually +/// copying the data. Even +/// > if you're doing a lot of insertion in the middle of the list, `RingBuf` +/// can still be better /// > because of how expensive it is to seek to the middle of a `LinkedList`. /// /// **Known problems:** False positives – the instances where using a @@ -68,7 +75,8 @@ declare_lint! { /// **What it does:** Checks for use of `&Box` anywhere in the code. /// -/// **Why is this bad?** Any `&Box` can also be a `&T`, which is more general. +/// **Why is this bad?** Any `&Box` can also be a `&T`, which is more +/// general. /// /// **Known problems:** None. /// @@ -161,11 +169,13 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { return; // don't recurse into the type }} } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) { - span_help_and_lint(cx, - LINKEDLIST, - ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a VecDeque might work"); + span_help_and_lint( + cx, + LINKEDLIST, + ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a VecDeque might work", + ); return; // don't recurse into the type } } @@ -268,11 +278,15 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) { if higher::is_from_for_desugar(decl) { return; } - span_lint(cx, - LET_UNIT_VALUE, - decl.span, - &format!("this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, ".."))); + span_lint( + cx, + LET_UNIT_VALUE, + decl.span, + &format!( + "this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, "..") + ), + ); }, _ => (), } @@ -336,12 +350,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { BiEq | BiLe | BiGe => "true", _ => "false", }; - span_lint(cx, - UNIT_CMP, - expr.span, - &format!("{}-comparison of unit values detected. This will always be {}", - op.as_str(), - result)); + span_lint( + cx, + UNIT_CMP, + expr.span, + &format!( + "{}-comparison of unit values detected. This will always be {}", + op.as_str(), + result + ), + ); }, _ => (), } @@ -493,20 +511,24 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t } else { int_ty_to_nbits(cast_from).to_string() }; - span_lint(cx, - CAST_PRECISION_LOSS, - expr.span, - &format!("casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ + span_lint( + cx, + CAST_PRECISION_LOSS, + expr.span, + &format!( + "casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ is only {4} bits wide)", - cast_from, - if cast_to_f64 { "f64" } else { "f32" }, - if arch_dependent { - arch_dependent_str - } else { - "" - }, - from_nbits_str, - mantissa_nbits)); + cast_from, + if cast_to_f64 { "f64" } else { "f32" }, + if arch_dependent { + arch_dependent_str + } else { + "" + }, + from_nbits_str, + mantissa_nbits + ), + ); } enum ArchSuffix { @@ -520,70 +542,86 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); - let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), - is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => { - (to_nbits < from_nbits, - ArchSuffix::None, - to_nbits == from_nbits && cast_unsigned_to_signed, - ArchSuffix::None) - }, - (true, false) => { - (to_nbits <= 32, - if to_nbits == 32 { - ArchSuffix::_64 - } else { - ArchSuffix::None - }, - to_nbits <= 32 && cast_unsigned_to_signed, - ArchSuffix::_32) - }, - (false, true) => { - (from_nbits == 64, - ArchSuffix::_32, - cast_unsigned_to_signed, - if from_nbits == 64 { - ArchSuffix::_64 - } else { - ArchSuffix::_32 - }) - }, - }; + let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = + match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { + (true, true) | (false, false) => { + ( + to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None, + ) + }, + (true, false) => { + ( + to_nbits <= 32, + if to_nbits == 32 { + ArchSuffix::_64 + } else { + ArchSuffix::None + }, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32, + ) + }, + (false, true) => { + ( + from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 { + ArchSuffix::_64 + } else { + ArchSuffix::_32 + }, + ) + }, + }; if span_truncation { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - &format!("casting {} to {} may truncate the value{}", - cast_from, - cast_to, - match suffix_truncation { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "", - })); + span_lint( + cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!( + "casting {} to {} may truncate the value{}", + cast_from, + cast_to, + match suffix_truncation { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + } + ), + ); } if span_wrap { - span_lint(cx, - CAST_POSSIBLE_WRAP, - expr.span, - &format!("casting {} to {} may wrap around the value{}", - cast_from, - cast_to, - match suffix_wrap { - ArchSuffix::_32 => arch_32_suffix, - ArchSuffix::_64 => arch_64_suffix, - ArchSuffix::None => "", - })); + span_lint( + cx, + CAST_POSSIBLE_WRAP, + expr.span, + &format!( + "casting {} to {} may wrap around the value{}", + cast_from, + cast_to, + match suffix_wrap { + ArchSuffix::_32 => arch_32_suffix, + ArchSuffix::_64 => arch_64_suffix, + ArchSuffix::None => "", + } + ), + ); } } impl LintPass for CastPass { fn get_lints(&self) -> LintArray { - lint_array!(CAST_PRECISION_LOSS, - CAST_SIGN_LOSS, - CAST_POSSIBLE_TRUNCATION, - CAST_POSSIBLE_WRAP, - UNNECESSARY_CAST) + lint_array!( + CAST_PRECISION_LOSS, + CAST_SIGN_LOSS, + CAST_POSSIBLE_TRUNCATION, + CAST_POSSIBLE_WRAP, + UNNECESSARY_CAST + ) } } @@ -598,12 +636,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { LitKind::FloatUnsuffixed(_) => {}, _ => { if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { - span_lint(cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting to the same type is unnecessary (`{}` -> `{}`)", - cast_from, - cast_to)); + span_lint( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), + ); } }, } @@ -622,33 +660,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } }, (false, true) => { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - &format!("casting {} to {} may truncate the value", cast_from, cast_to)); + span_lint( + cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + &format!("casting {} to {} may truncate the value", cast_from, cast_to), + ); if !cast_to.is_signed() { - span_lint(cx, - CAST_SIGN_LOSS, - expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + span_lint( + cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to), + ); } }, (true, true) => { if cast_from.is_signed() && !cast_to.is_signed() { - span_lint(cx, - CAST_SIGN_LOSS, - expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to)); + span_lint( + cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to), + ); } check_truncation_and_wrapping(cx, expr, cast_from, cast_to); }, (false, false) => { if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = - (&cast_from.sty, &cast_to.sty) { - span_lint(cx, - CAST_POSSIBLE_TRUNCATION, - expr.span, - "casting f64 to f32 may truncate the value"); + (&cast_from.sty, &cast_to.sty) + { + span_lint( + cx, + CAST_POSSIBLE_TRUNCATION, + expr.span, + "casting f64 to f32 may truncate the value", + ); } }, } @@ -700,7 +747,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { decl: &'tcx FnDecl, _: &'tcx Body, _: Span, - _: NodeId + _: NodeId, ) { self.check_fndecl(cx, decl); } @@ -760,19 +807,18 @@ impl<'a, 'tcx> TypeComplexityPass { return; } let score = { - let mut visitor = TypeComplexityVisitor { - score: 0, - nest: 1, - }; + let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; visitor.visit_ty(ty); visitor.score }; if score > self.threshold { - span_lint(cx, - TYPE_COMPLEXITY, - ty.span, - "very complex type used. Consider factoring parts into `type` definitions"); + span_lint( + cx, + TYPE_COMPLEXITY, + ty.span, + "very complex type used. Consider factoring parts into `type` definitions", + ); } } } @@ -798,8 +844,9 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyBareFn(..) => (50 * self.nest, 1), TyTraitObject(ref param_bounds, _) => { - let has_lifetime_parameters = param_bounds.iter() - .any(|bound| !bound.bound_lifetimes.is_empty()); + let has_lifetime_parameters = param_bounds.iter().any( + |bound| !bound.bound_lifetimes.is_empty(), + ); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) @@ -922,7 +969,7 @@ fn detect_absurd_comparison<'a>( cx: &LateContext, op: BinOp_, lhs: &'a Expr, - rhs: &'a Expr + rhs: &'a Expr, ) -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { use types::ExtremeType::*; use types::AbsurdComparisonResult::*; @@ -1042,20 +1089,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { AlwaysFalse => "this comparison is always false".to_owned(), AlwaysTrue => "this comparison is always true".to_owned(), InequalityImpossible => { - format!("the case where the two sides are not equal never occurs, consider using {} == {} \ + format!( + "the case where the two sides are not equal never occurs, consider using {} == {} \ instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs")) + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs") + ) }, }; - let help = format!("because {} is the {} value for this type, {}", - snippet(cx, culprit.expr.span, "x"), - match culprit.which { - Minimum => "minimum", - Maximum => "maximum", - }, - conclusion); + let help = format!( + "because {} is the {} value for this type, {}", + snippet(cx, culprit.expr.span, "x"), + match culprit.which { + Minimum => "minimum", + Maximum => "maximum", + }, + conclusion + ); span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help); } @@ -1113,7 +1164,9 @@ impl FullInt { impl PartialEq for FullInt { fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal + self.partial_cmp(other).expect( + "partial_cmp only returns Some(_)", + ) == Ordering::Equal } } @@ -1129,7 +1182,9 @@ impl PartialOrd for FullInt { } impl Ord for FullInt { fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).expect("partial_cmp for FullInt can never return None") + self.partial_cmp(other).expect( + "partial_cmp for FullInt can never return None", + ) } } @@ -1198,14 +1253,16 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { if let ExprCast(ref cast_val, _) = expr.node { - span_lint(cx, - INVALID_UPCAST_COMPARISONS, - *span, - &format!( + span_lint( + cx, + INVALID_UPCAST_COMPARISONS, + *span, + &format!( "because of the numeric bounds on `{}` prior to casting, this expression is always {}", snippet(cx, cast_val.span, "the expression"), if always { "true" } else { "false" }, - )); + ), + ); } } @@ -1216,7 +1273,7 @@ fn upcast_comparison_bounds_err( lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, - invert: bool + invert: bool, ) { use utils::comparisons::*; @@ -1227,40 +1284,42 @@ fn upcast_comparison_bounds_err( err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } + { err_upcast_comparison(cx, span, lhs, true) } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } + { err_upcast_comparison(cx, span, lhs, false) } } diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 1d5ab7db346..ace8ea7558d 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -12,7 +12,8 @@ use utils::{snippet, span_help_and_lint}; /// /// **Known problems:** None. /// -/// **Example:** You don't see it, but there may be a zero-width space somewhere in this text. +/// **Example:** You don't see it, but there may be a zero-width space +/// somewhere in this text. declare_lint! { pub ZERO_WIDTH_SPACE, Deny, @@ -95,30 +96,40 @@ fn escape>(s: T) -> String { fn check_str(cx: &LateContext, span: Span) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { - span_help_and_lint(cx, - ZERO_WIDTH_SPACE, - span, - "zero-width space detected", - &format!("Consider replacing the string with:\n\"{}\"", - string.replace("\u{200B}", "\\u{200B}"))); + span_help_and_lint( + cx, + ZERO_WIDTH_SPACE, + span, + "zero-width space detected", + &format!( + "Consider replacing the string with:\n\"{}\"", + string.replace("\u{200B}", "\\u{200B}") + ), + ); } if string.chars().any(|c| c as u32 > 0x7F) { - span_help_and_lint(cx, - NON_ASCII_LITERAL, - span, - "literal non-ASCII character detected", - &format!("Consider replacing the string with:\n\"{}\"", - if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { - escape(string.chars()) - } else { - escape(string.nfc()) - })); + span_help_and_lint( + cx, + NON_ASCII_LITERAL, + span, + "literal non-ASCII character detected", + &format!( + "Consider replacing the string with:\n\"{}\"", + if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { + escape(string.chars()) + } else { + escape(string.nfc()) + } + ), + ); } if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { - span_help_and_lint(cx, - UNICODE_NOT_NFC, - span, - "non-nfc unicode sequence detected", - &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::())); + span_help_and_lint( + cx, + UNICODE_NOT_NFC, + span, + "non-nfc unicode sequence detected", + &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::()), + ); } } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 07afc55ae7f..036e6f0f0e6 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -38,13 +38,15 @@ impl EarlyLintPass for UnsafeNameRemoval { if let ItemKind::Use(ref item_use) = item.node { match item_use.node { ViewPath_::ViewPathSimple(ref name, ref path) => { - unsafe_to_safe_check(path.segments - .last() - .expect("use paths cannot be empty") - .identifier, - *name, - cx, - &item.span); + unsafe_to_safe_check( + path.segments + .last() + .expect("use paths cannot be empty") + .identifier, + *name, + cx, + &item.span, + ); }, ViewPath_::ViewPathList(_, ref path_list_items) => { for path_list_item in path_list_items.iter() { @@ -64,10 +66,12 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, spa let old_str = old_name.name.as_str(); let new_str = new_name.name.as_str(); if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { - span_lint(cx, - UNSAFE_REMOVED_FROM_NAME, - *span, - &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str)); + span_lint( + cx, + UNSAFE_REMOVED_FROM_NAME, + *span, + &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str), + ); } } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 5a97254f3ad..ff2148c88a9 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -4,9 +4,12 @@ use utils::{span_lint, match_path, match_trait_method, is_try, paths}; /// **What it does:** Checks for unused written/read amount. /// -/// **Why is this bad?** `io::Write::write` and `io::Read::read` are not guaranteed to -/// process the entire buffer. They return how many bytes were processed, which might be smaller -/// than a given buffer's length. If you don't need to deal with partial-write/read, use +/// **Why is this bad?** `io::Write::write` and `io::Read::read` are not +/// guaranteed to +/// process the entire buffer. They return how many bytes were processed, which +/// might be smaller +/// than a given buffer's length. If you don't need to deal with +/// partial-write/read, use /// `write_all`/`read_exact` instead. /// /// **Known problems:** Detects only common patterns. @@ -73,15 +76,19 @@ fn check_method_call(cx: &LateContext, call: &hir::Expr, expr: &hir::Expr) { if let hir::ExprMethodCall(ref path, _, _) = call.node { let symbol = &*path.name.as_str(); if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" { - span_lint(cx, - UNUSED_IO_AMOUNT, - expr.span, - "handle read amount returned or use `Read::read_exact` instead"); + span_lint( + cx, + UNUSED_IO_AMOUNT, + expr.span, + "handle read amount returned or use `Read::read_exact` instead", + ); } else if match_trait_method(cx, call, &paths::IO_WRITE) && symbol == "write" { - span_lint(cx, - UNUSED_IO_AMOUNT, - expr.span, - "handle written amount returned or use `Write::write_all` instead"); + span_lint( + cx, + UNUSED_IO_AMOUNT, + expr.span, + "handle written amount returned or use `Write::write_all` instead", + ); } } } diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 15f327fb5c2..8a8afe8a377 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { decl: &'tcx hir::FnDecl, body: &'tcx hir::Body, span: Span, - fn_id: ast::NodeId + fn_id: ast::NodeId, ) { if in_macro(span) { return; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index af92589b4d2..7466ee9080b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -7,7 +7,7 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::{Expr, QPath, Expr_}; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use syntax::ast::{Attribute, NodeId, LitKind, DUMMY_NODE_ID, self}; +use syntax::ast::{self, Attribute, NodeId, LitKind, DUMMY_NODE_ID}; use syntax::codemap::Span; use std::collections::HashMap; @@ -166,13 +166,14 @@ impl PrintVisitor { Vacant(vac) => { vac.insert(0); s.to_owned() - } + }, } } } struct PrintVisitor { - /// Fields are the current index that needs to be appended to pattern binding names + /// Fields are the current index that needs to be appended to pattern + /// binding names ids: HashMap<&'static str, usize>, /// the name that needs to be destructured current: String, @@ -254,7 +255,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" {}.as_str() == {:?}", str_pat, &*text.as_str()) }, } - } + }, Expr_::ExprCast(ref expr, ref _ty) => { let cast_pat = self.next("expr"); println!("Cast(ref {}, _) = {},", cast_pat, current); @@ -282,7 +283,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(cond); self.current = then_pat; self.visit_expr(then); - } + }, Expr_::ExprWhile(ref _cond, ref _body, ref _opt_label) => { println!("While(ref cond, ref body, ref opt_label) = {},", current); println!(" // unimplemented: `ExprWhile` is not further destructured at the moment"); @@ -398,7 +399,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let fields_pat = self.next("fields"); if let Some(ref base) = *opt_base { let base_pat = self.next("base"); - println!("Struct(ref {}, ref {}, Some(ref {})) = {},", path_pat, fields_pat, base_pat, current); + println!( + "Struct(ref {}, ref {}, Some(ref {})) = {},", + path_pat, + fields_pat, + base_pat, + current + ); self.current = base_pat; self.visit_expr(base); } else { @@ -433,24 +440,27 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { fn has_attr(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { attr.check_name("clippy") && - attr.meta_item_list().map_or(false, |list| { - list.len() == 1 && match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", - ast::NestedMetaItemKind::Literal(_) => false, - } - }) + attr.meta_item_list().map_or(false, |list| { + list.len() == 1 && + match list[0].node { + ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", + ast::NestedMetaItemKind::Literal(_) => false, + } + }) }) } fn print_path(path: &QPath, first: &mut bool) { match *path { - QPath::Resolved(_, ref path) => for segment in &path.segments { - if *first { - *first = false; - } else { - print!(", "); + QPath::Resolved(_, ref path) => { + for segment in &path.segments { + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.name.as_str()); } - print!("{:?}", segment.name.as_str()); }, QPath::TypeRelative(ref ty, ref segment) => { match ty.node { diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index f973c2afd27..5cb9b50a79d 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -17,7 +17,8 @@ pub enum Rel { Ne, } -/// Put the expression in the form `lhs < rhs`, `lhs <= rhs`, `lhs == rhs` or `lhs != rhs`. +/// Put the expression in the form `lhs < rhs`, `lhs <= rhs`, `lhs == rhs` or +/// `lhs != rhs`. pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(Rel, &'a Expr, &'a Expr)> { match op { BinOp_::BiLt => Some((Rel::Lt, lhs, rhs)), diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 0e6f8856382..ad9e7e20176 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -9,8 +9,9 @@ use toml; use std::sync::Mutex; /// Get the configuration file from arguments. -pub fn file_from_args(args: &[codemap::Spanned]) - -> Result, (&'static str, codemap::Span)> { +pub fn file_from_args( + args: &[codemap::Spanned], +) -> Result, (&'static str, codemap::Span)> { for arg in args.iter().filter_map(|a| a.meta_item()) { if arg.name() == "conf_file" { return match arg.node { @@ -38,12 +39,14 @@ pub enum Error { /// Not valid toml or doesn't fit the expected conf format Toml(String), /// Type error. - Type(/// The name of the key. - &'static str, - /// The expected type. - &'static str, - /// The type we got instead. - &'static str), + Type( + /// The name of the key. + &'static str, + /// The expected type. + &'static str, + /// The type we got instead. + &'static str + ), /// There is an unknown key is the file. UnknownKey(String), } @@ -234,11 +237,25 @@ pub fn read(path: Option<&path::Path>) -> (Conf, Vec) { Err(err) => return default(vec![err.into()]), }; - assert!(ERRORS.lock().expect("no threading -> mutex always safe").is_empty()); + assert!( + ERRORS + .lock() + .expect("no threading -> mutex always safe") + .is_empty() + ); match toml::from_str(&file) { - Ok(toml) => (toml, ERRORS.lock().expect("no threading -> mutex always safe").split_off(0)), + Ok(toml) => ( + toml, + ERRORS + .lock() + .expect("no threading -> mutex always safe") + .split_off(0), + ), Err(e) => { - let mut errors = ERRORS.lock().expect("no threading -> mutex always safe").split_off(0); + let mut errors = ERRORS + .lock() + .expect("no threading -> mutex always safe") + .split_off(0); errors.push(Error::Toml(e.to_string())); default(errors) }, diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index 87008307c5f..d47fbd5a043 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -7,5 +7,20 @@ /// See also [the reference][reference-types] for a list of such types. /// /// [reference-types]: https://doc.rust-lang.org/reference.html#types -pub const BUILTIN_TYPES: &'static [&'static str] = &["i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "isize", - "usize", "f32", "f64", "bool", "str", "char"]; +pub const BUILTIN_TYPES: &'static [&'static str] = &[ + "i8", + "u8", + "i16", + "u16", + "i32", + "u32", + "i64", + "u64", + "isize", + "usize", + "f32", + "f64", + "bool", + "str", + "char", +]; diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d25f8e7df2b..593cbf69f5b 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -1,4 +1,5 @@ -//! This module contains functions for retrieve the original AST from lowered `hir`. +//! This module contains functions for retrieve the original AST from lowered +//! `hir`. #![deny(missing_docs_in_private_items)] @@ -44,9 +45,11 @@ pub struct Range<'a> { /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. pub fn range(expr: &hir::Expr) -> Option { - /// Find the field named `name` in the field. Always return `Some` for convenience. + /// Find the field named `name` in the field. Always return `Some` for + /// convenience. fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { - let expr = &fields.iter() + let expr = &fields + .iter() .find(|field| field.name.node == name) .unwrap_or_else(|| panic!("missing {} field for range", name)) .expr; @@ -54,7 +57,8 @@ pub fn range(expr: &hir::Expr) -> Option { Some(expr) } - // The range syntax is expanded to literal paths starting with `core` or `std` depending on + // The range syntax is expanded to literal paths starting with `core` or `std` + // depending on // `#[no_std]`. Testing both instead of resolving the paths. match expr.node { @@ -147,7 +151,8 @@ pub enum VecArgs<'a> { Vec(&'a [hir::Expr]), } -/// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. +/// Returns the arguments of the `vec!` macro if this expression was expanded +/// from `vec!`. pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option> { if_let_chain!{[ let hir::ExprCall(ref fun, ref args) = expr.node, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 3b943b83bb0..658a07ca146 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -7,14 +7,17 @@ use syntax::ast::Name; use syntax::ptr::P; use utils::differing_macro_contexts; -/// Type used to check whether two ast are the same. This is different from the operator -/// `==` on ast types as this operator would compare true equality with ID and span. +/// Type used to check whether two ast are the same. This is different from the +/// operator +/// `==` on ast types as this operator would compare true equality with ID and +/// span. /// /// Note that some expressions kinds are not considered but could be added. pub struct SpanlessEq<'a, 'tcx: 'a> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'a, 'tcx>, - /// If is true, never consider as equal expressions containing function calls. + /// If is true, never consider as equal expressions containing function + /// calls. ignore_fn: bool, } @@ -52,7 +55,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two blocks are the same. pub fn eq_block(&self, left: &Block, right: &Block) -> bool { over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && - both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) + both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { @@ -78,13 +81,13 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { - l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - }) + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) }, (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => { both(&li.ident, &ri.ident, |l, r| l.node.name.as_str() == r.node.name.as_str()) && - both(le, re, |l, r| self.eq_expr(l, r)) + both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { @@ -105,23 +108,23 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && - over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) + over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) }, (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) }, (&ExprRepeat(ref le, ll_id), &ExprRepeat(ref re, rl_id)) => { self.eq_expr(le, re) && - self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) }, (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r), (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && - over(lf, rf, |l, r| self.eq_field(l, r)) + over(lf, rf, |l, r| self.eq_field(l, r)) }, (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), @@ -167,7 +170,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), (&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => { over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && - both(li, ri, |l, r| self.eq_pat(l, r)) + both(li, ri, |l, r| self.eq_pat(l, r)) }, (&PatKind::Wild, &PatKind::Wild) => true, _ => false, @@ -188,19 +191,19 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_path(&self, left: &Path, right: &Path) -> bool { left.is_global() == right.is_global() && - over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) + over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) } fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { match (left, right) { (&AngleBracketedParameters(ref left), &AngleBracketedParameters(ref right)) => { over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && - over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && - over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) + over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && + over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) }, (&ParenthesizedParameters(ref left), &ParenthesizedParameters(ref right)) => { over(&left.inputs, &right.inputs, |l, r| self.eq_ty(l, r)) && - both(&left.output, &right.output, |l, r| self.eq_ty(l, r)) + both(&left.output, &right.output, |l, r| self.eq_ty(l, r)) }, (&AngleBracketedParameters(_), &ParenthesizedParameters(_)) | (&ParenthesizedParameters(_), &AngleBracketedParameters(_)) => false, @@ -218,7 +221,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyArray(ref lt, ll_id), &TyArray(ref rt, rl_id)) => { self.eq_ty(lt, rt) && - self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) }, (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { @@ -247,22 +250,28 @@ fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_ } } -/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. +/// Check if the two `Option`s are both `None` or some equal values as per +/// `eq_fn`. fn both(l: &Option, r: &Option, mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool +where + F: FnMut(&X, &X) -> bool, { - l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) + l.as_ref().map_or_else(|| r.is_none(), |x| { + r.as_ref().map_or(false, |y| eq_fn(x, y)) + }) } /// Check if two slices are equal as per `eq_fn`. fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool - where F: FnMut(&X, &X) -> bool +where + F: FnMut(&X, &X) -> bool, { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -/// Type used to hash an ast element. This is different from the `Hash` trait on ast types as this +/// Type used to hash an ast element. This is different from the `Hash` trait +/// on ast types as this /// trait would consider IDs and spans. /// /// All expressions kind are hashed, but some might have a weaker hash. diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 9962eca5075..ccb2cb7c67f 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -8,7 +8,8 @@ use rustc::hir::print; use syntax::ast::Attribute; use syntax::attr; -/// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` attribute +/// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` +/// attribute /// /// **Example:** /// ```rust @@ -54,8 +55,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), hir::Visibility::Restricted { ref path, .. } => { - println!("visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false))) + println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ) }, hir::Visibility::Inherited => println!("visibility inherited from outer item"), } @@ -71,20 +74,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::ImplItemKind::Type(_) => println!("associated type"), } } - // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { + // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx + // hir::TraitItem) { // if !has_attr(&item.attrs) { // return; // } // } // - // fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx hir::Variant, _: + // fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx + // hir::Variant, _: // &hir::Generics) { // if !has_attr(&var.node.attrs) { // return; // } // } // - // fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField) { + // fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx + // hir::StructField) { // if !has_attr(&field.attrs) { // return; // } @@ -123,7 +129,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), } } - // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ForeignItem) { + // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx + // hir::ForeignItem) { // if !has_attr(&item.attrs) { // return; // } @@ -345,8 +352,10 @@ fn print_item(cx: &LateContext, item: &hir::Item) { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), hir::Visibility::Restricted { ref path, .. } => { - println!("visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false))) + println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ) }, hir::Visibility::Inherited => println!("visibility inherited from outer item"), } @@ -422,9 +431,11 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { }, hir::PatKind::Struct(ref path, ref fields, ignore) => { println!("{}Struct", ind); - println!("{}name: {}", - ind, - print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); + println!( + "{}name: {}", + ind, + print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) + ); println!("{}ignore leftover fields: {}", ind, ignore); println!("{}fields:", ind); for field in fields { @@ -437,9 +448,11 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { }, hir::PatKind::TupleStruct(ref path, ref fields, opt_dots_position) => { println!("{}TupleStruct", ind); - println!("{}path: {}", - ind, - print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); + println!( + "{}path: {}", + ind, + print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) + ); if let Some(dot_position) = opt_dots_position { println!("{}dot position: {}", ind, dot_position); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 038dfc01d13..f81aff24338 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -63,20 +63,28 @@ impl LintPass for Clippy { impl EarlyLintPass for Clippy { fn check_crate(&mut self, cx: &EarlyContext, krate: &AstCrate) { - if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == "utils") { + if let Some(utils) = krate.module.items.iter().find( + |item| item.ident.name == "utils", + ) + { if let ItemKind::Mod(ref utils_mod) = utils.node { - if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name == "paths") { + if let Some(paths) = utils_mod.items.iter().find( + |item| item.ident.name == "paths", + ) + { if let ItemKind::Mod(ref paths_mod) = paths.node { let mut last_name: Option = None; for item in &paths_mod.items { let name = item.ident.name.as_str(); if let Some(ref last_name) = last_name { if **last_name > *name { - span_lint(cx, - CLIPPY_LINTS_INTERNAL, - item.span, - "this constant should be before the previous constant due to lexical \ - ordering"); + span_lint( + cx, + CLIPPY_LINTS_INTERNAL, + item.span, + "this constant should be before the previous constant due to lexical \ + ordering", + ); } } last_name = Some(name); @@ -128,13 +136,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { // not able to capture the error. // Therefore, we need to climb the macro expansion tree and find the // actual span that invoked `declare_lint!`: - let lint_span = lint_span.ctxt.outer().expn_info().map(|ei| ei.call_site).expect("unable to get call_site"); + let lint_span = lint_span + .ctxt + .outer() + .expn_info() + .map(|ei| ei.call_site) + .expect("unable to get call_site"); if !self.registered_lints.contains(lint_name) { - span_lint(cx, - LINT_WITHOUT_LINT_PASS, - lint_span, - &format!("the lint `{}` is not added to any `LintPass`", lint_name)); + span_lint( + cx, + LINT_WITHOUT_LINT_PASS, + lint_span, + &format!("the lint `{}` is not added to any `LintPass`", lint_name), + ); } } } @@ -142,7 +157,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { - if let TyRptr(ref lt, MutTy { ty: ref inner, mutbl: MutImmutable }) = ty.node { + if let TyRptr(ref lt, + MutTy { + ty: ref inner, + mutbl: MutImmutable, + }) = ty.node + { if lt.is_elided() { return false; } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index cdce1108be2..43c0eb68d69 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -93,7 +93,8 @@ macro_rules! if_let_chain { pub mod higher; -/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one +/// Returns true if the two spans come from differing expansions (i.e. one is +/// from a macro and one /// isn't). pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { rhs.ctxt != lhs.ctxt @@ -119,10 +120,12 @@ pub fn in_macro(span: Span) -> bool { }) } -/// Returns true if the macro that expanded the crate was outside of the current crate or was a +/// Returns true if the macro that expanded the crate was outside of the +/// current crate or was a /// compiler plugin. pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { - /// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use + /// Invokes `in_macro` with the expansion info of the given span slightly + /// heavy, try to use /// this after other checks have already happened. fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool { // no ExpnInfo = no macro @@ -133,11 +136,18 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules")) + cx.sess().codemap().span_to_snippet(span).ok().map_or( + true, + |code| { + !code.starts_with("macro_rules") + }, + ) }) } - span.ctxt.outer().expn_info().map_or(false, |info| in_macro_ext(cx, &info)) + span.ctxt.outer().expn_info().map_or(false, |info| { + in_macro_ext(cx, &info) + }) } /// Check if a `DefId`'s path matches the given absolute type path usage. @@ -170,7 +180,10 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { tcx.push_item_path(&mut apb, def_id); - apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) + apb.names.len() == path.len() && + apb.names.into_iter().zip(path.iter()).all( + |(a, &b)| *a == *b, + ) } /// Check if type is struct, enum or union type with given def path. @@ -206,9 +219,9 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool pub fn last_path_segment(path: &QPath) -> &PathSegment { match *path { QPath::Resolved(_, ref path) => { - path.segments - .last() - .expect("A path must have at least one segment") + path.segments.last().expect( + "A path must have at least one segment", + ) }, QPath::TypeRelative(_, ref seg) => seg, } @@ -235,7 +248,7 @@ pub fn match_path(path: &QPath, segments: &[&str]) -> bool { match ty.node { TyPath(ref inner_path) => { !segments.is_empty() && match_path(inner_path, &segments[..(segments.len() - 1)]) && - segment.name == segments[segments.len() - 1] + segment.name == segments[segments.len() - 1] }, _ => false, } @@ -244,7 +257,9 @@ pub fn match_path(path: &QPath, segments: &[&str]) -> bool { } pub fn match_path_old(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name == *b) + path.segments.iter().rev().zip(segments.iter().rev()).all( + |(a, b)| a.name == *b, + ) } /// Match a `Path` against a slice of segment string literals, e.g. @@ -254,7 +269,9 @@ pub fn match_path_old(path: &Path, segments: &[&str]) -> bool { /// match_path(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name == *b) + path.segments.iter().rev().zip(segments.iter().rev()).all( + |(a, b)| a.identifier.name == *b, + ) } /// Get the definition associated to a path. @@ -262,7 +279,9 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { let cstore = &cx.tcx.sess.cstore; let crates = cstore.crates(); - let krate = crates.iter().find(|&&krate| cstore.crate_name(krate) == path[0]); + let krate = crates.iter().find( + |&&krate| cstore.crate_name(krate) == path[0], + ); if let Some(krate) = krate { let krate = DefId { krate: *krate, @@ -312,14 +331,20 @@ pub fn implements_trait<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, trait_id: DefId, - ty_params: &[Ty<'tcx>] + ty_params: &[Ty<'tcx>], ) -> bool { let ty = cx.tcx.erase_regions(&ty); - let obligation = cx.tcx - .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); - cx.tcx - .infer_ctxt() - .enter(|infcx| traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)) + let obligation = cx.tcx.predicate_for_trait_def( + cx.param_env, + traits::ObligationCause::dummy(), + trait_id, + 0, + ty, + ty_params, + ); + cx.tcx.infer_ctxt().enter(|infcx| { + traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) + }) } /// Resolve the definition of a node from its `NodeId`. @@ -330,7 +355,8 @@ pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: NodeId) -> def::Def { /// Match an `Expr` against a chain of methods, and return the matched `Expr`s. /// /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` containing the `Expr`s for +/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` +/// containing the `Expr`s for /// `.bar()` and `.baz()` pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option> { let mut current = expr; @@ -382,8 +408,10 @@ pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option cx.sess().codemap().span_to_snippet(span).ok() } -/// Convert a span (from a block) to a code snippet if available, otherwise use default. -/// This trims the code of indentation, except for the first line. Use it for blocks or block-like +/// Convert a span (from a block) to a code snippet if available, otherwise use +/// default. +/// This trims the code of indentation, except for the first line. Use it for +/// blocks or block-like /// things which need to be printed as such. /// /// # Example @@ -401,7 +429,7 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( cx: &T, expr: &Expr, option: Option, - default: &'a str + default: &'a str, ) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); let string = option.unwrap_or_default(); @@ -414,7 +442,8 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( } } -/// Trim indentation from a multiline string with possibility of ignoring the first line. +/// Trim indentation from a multiline string with possibility of ignoring the +/// first line. pub fn trim_multiline(s: Cow, ignore_first: bool) -> Cow { let s_space = trim_multiline_inner(s, ignore_first, ' '); let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); @@ -429,24 +458,28 @@ fn trim_multiline_inner(s: Cow, ignore_first: bool, ch: char) -> Cow { None } else { // ignore empty lines - Some(l.char_indices() - .find(|&(_, x)| x != ch) - .unwrap_or((l.len(), ch)) - .0) + Some( + l.char_indices() + .find(|&(_, x)| x != ch) + .unwrap_or((l.len(), ch)) + .0, + ) } }) .min() .unwrap_or(0); if x > 0 { - Cow::Owned(s.lines() - .enumerate() - .map(|(i, l)| if (ignore_first && i == 0) || l.is_empty() { - l - } else { - l.split_at(x).1 - }) - .collect::>() - .join("\n")) + Cow::Owned( + s.lines() + .enumerate() + .map(|(i, l)| if (ignore_first && i == 0) || l.is_empty() { + l + } else { + l.split_at(x).1 + }) + .collect::>() + .join("\n"), + ) } else { s } @@ -460,17 +493,22 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if node_id == parent_id { return None; } - map.find(parent_id).and_then(|node| if let Node::NodeExpr(parent) = node { - Some(parent) - } else { - None - }) + map.find(parent_id).and_then( + |node| if let Node::NodeExpr(parent) = + node + { + Some(parent) + } else { + None + }, + ) } pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { let map = &cx.tcx.hir; - let enclosing_node = map.get_enclosing_scope(node) - .and_then(|enclosing_id| map.find(enclosing_id)); + let enclosing_node = map.get_enclosing_scope(node).and_then(|enclosing_id| { + map.find(enclosing_id) + }); if let Some(node) = enclosing_node { match node { Node::NodeBlock(block) => Some(block), @@ -498,8 +536,10 @@ impl<'a> Drop for DiagnosticWrapper<'a> { impl<'a> DiagnosticWrapper<'a> { fn wiki_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { - self.0.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", - lint.name_lower())); + self.0.help(&format!( + "for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}", + lint.name_lower() + )); } } } @@ -516,7 +556,7 @@ pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( lint: &'static Lint, span: Span, msg: &str, - help: &str + help: &str, ) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { @@ -531,7 +571,7 @@ pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( span: Span, msg: &str, note_span: Span, - note: &str + note: &str, ) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); if cx.current_level(lint) != Level::Allow { @@ -549,8 +589,9 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( lint: &'static Lint, sp: Span, msg: &str, - f: F -) where F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>) + f: F, +) where + F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); if cx.current_level(lint) != Level::Allow { @@ -565,15 +606,17 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( sp: Span, msg: &str, help: &str, - sugg: String + sugg: String, ) { span_lint_and_then(cx, lint, sp, msg, |db| { db.span_suggestion(sp, help, sugg); }); } /// Create a suggestion made from several `span → replacement`. /// -/// Note: in the JSON format (used by `compiletest_rs`), the help message will appear once per -/// replacement. In human-readable format though, it only appears once before the whole suggestion. +/// Note: in the JSON format (used by `compiletest_rs`), the help message will +/// appear once per +/// replacement. In human-readable format though, it only appears once before +/// the whole suggestion. pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(Span, String)>) { let sugg = rustc_errors::CodeSuggestion { substitution_parts: sugg.into_iter() @@ -598,7 +641,8 @@ pub fn walk_ptrs_ty(ty: Ty) -> Ty { } } -/// Return the base type for references and raw pointers, and count reference depth. +/// Return the base type for references and raw pointers, and count reference +/// depth. pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) { fn inner(ty: Ty, depth: usize) -> (Ty, usize) { match ty.sty { @@ -639,7 +683,9 @@ impl LimitStack { LimitStack { stack: vec![limit] } } pub fn limit(&self) -> u64 { - *self.stack.last().expect("there should always be a value in the stack") + *self.stack.last().expect( + "there should always be a value in the stack", + ) } pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; @@ -669,14 +715,14 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' } } -/// Return the pre-expansion span if is this comes from an expansion of the macro `name`. +/// Return the pre-expansion span if is this comes from an expansion of the +/// macro `name`. /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt - .outer() - .expn_info() - .map(|ei| (ei.callee.name(), ei.call_site)); + let span_name_span = span.ctxt.outer().expn_info().map(|ei| { + (ei.callee.name(), ei.call_site) + }); match span_name_span { Some((mac_name, new_span)) if mac_name == name => return Some(new_span), @@ -686,18 +732,19 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { } } -/// Return the pre-expansion span if is this directly comes from an expansion of the macro `name`. +/// Return the pre-expansion span if is this directly comes from an expansion +/// of the macro `name`. /// The difference with `is_expn_of` is that in /// ```rust,ignore /// foo!(bar!(42)); /// ``` -/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only `bar!` by +/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only +/// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt - .outer() - .expn_info() - .map(|ei| (ei.callee.name(), ei.call_site)); + let span_name_span = span.ctxt.outer().expn_info().map(|ei| { + (ei.callee.name(), ei.call_site) + }); match span_name_span { Some((mac_name, new_span)) if mac_name == name => Some(new_span), @@ -705,7 +752,8 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { } } -/// Return the index of the character after the first camel-case component of `s`. +/// Return the index of the character after the first camel-case component of +/// `s`. pub fn camel_case_until(s: &str) -> usize { let mut iter = s.char_indices(); if let Some((_, first)) = iter.next() { @@ -771,10 +819,13 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t } /// Check if two types are the same. -// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but +// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for +// <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - cx.tcx.infer_ctxt().enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) + cx.tcx.infer_ctxt().enter(|infcx| { + infcx.can_eq(cx.param_env, a, b).is_ok() + }) } /// Return whether the given type is an `unsafe` function. @@ -792,8 +843,10 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { /// Return whether a pattern is refutable. pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { fn is_enum_variant(cx: &LateContext, qpath: &QPath, did: NodeId) -> bool { - matches!(cx.tables.qpath_def(qpath, did), - def::Def::Variant(..) | def::Def::VariantCtor(..)) + matches!( + cx.tables.qpath_def(qpath, did), + def::Def::Variant(..) | def::Def::VariantCtor(..) + ) } fn are_refutable<'a, I: Iterator>(cx: &LateContext, mut i: I) -> bool { @@ -824,19 +877,26 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { } }, PatKind::Slice(ref head, ref middle, ref tail) => { - are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)) + are_refutable( + cx, + head.iter().chain(middle).chain(tail.iter()).map( + |pat| &**pat, + ), + ) }, } } -/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have. +/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d +/// implementations have. pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { attr::contains_name(attrs, "automatically_derived") } /// Remove blocks around an expression. /// -/// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return themselves. +/// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return +/// themselves. pub fn remove_blocks(expr: &Expr) -> &Expr { if let ExprBlock(ref block) = expr.node { if block.stmts.is_empty() { @@ -948,5 +1008,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - ty.layout(cx.tcx, cx.param_env).ok().map(|layout| layout.size(cx.tcx).bytes()) + ty.layout(cx.tcx, cx.param_env).ok().map(|layout| { + layout.size(cx.tcx).bytes() + }) } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index f423274711a..675d708781c 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,4 +1,5 @@ -//! This module contains paths to types and functions Clippy needs to know about. +//! This module contains paths to types and functions Clippy needs to know +//! about. pub const ASMUT_TRAIT: [&'static str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&'static str; 3] = ["core", "convert", "AsRef"]; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 07872673b42..d46a6526395 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -20,7 +20,8 @@ pub enum Sugg<'a> { NonParen(Cow<'a, str>), /// An expression that does not fit in other variants. MaybeParen(Cow<'a, str>), - /// A binary operator expression, including `as`-casts and explicit type coercion. + /// A binary operator expression, including `as`-casts and explicit type + /// coercion. BinOp(AssocOp, Cow<'a, str>), } @@ -77,7 +78,8 @@ impl<'a> Sugg<'a> { }) } - /// Convenience function around `hir_opt` for suggestions with a default text. + /// Convenience function around `hir_opt` for suggestions with a default + /// text. pub fn hir(cx: &LateContext, expr: &hir::Expr, default: &'a str) -> Sugg<'a> { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } @@ -156,7 +158,8 @@ impl<'a> Sugg<'a> { make_unop("*", self) } - /// Convenience method to create the `..` or `...` suggestion. + /// Convenience method to create the `..` or `...` + /// suggestion. pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, &end), @@ -164,7 +167,8 @@ impl<'a> Sugg<'a> { } } - /// Add parenthesis to any expression that might need them. Suitable to the `self` argument of + /// Add parenthesis to any expression that might need them. Suitable to the + /// `self` argument of /// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`). pub fn maybe_par(self) -> Self { match self { @@ -233,7 +237,8 @@ impl Display for ParenHelper { /// Build the string for `` adding parenthesis when necessary. /// -/// For convenience, the operator is taken as a string because all unary operators have the same +/// For convenience, the operator is taken as a string because all unary +/// operators have the same /// precedence. pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> { Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into()) @@ -241,7 +246,8 @@ pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> { /// Build the string for ` ` adding parenthesis when necessary. /// -/// Precedence of shift operator relative to other arithmetic operation is often confusing so +/// Precedence of shift operator relative to other arithmetic operation is +/// often confusing so /// parenthesis will always be added for a mix of these. pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { /// Whether the operator is a shift operator `<<` or `>>`. @@ -251,18 +257,21 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { /// Whether the operator is a arithmetic operator (`+`, `-`, `*`, `/`, `%`). fn is_arith(op: &AssocOp) -> bool { - matches!(*op, - AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus) + matches!( + *op, + AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus + ) } - /// Whether the operator `op` needs parenthesis with the operator `other` in the direction + /// Whether the operator `op` needs parenthesis with the operator `other` + /// in the direction /// `dir`. fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool { other.precedence() < op.precedence() || - (other.precedence() == op.precedence() && - ((op != other && associativity(op) != dir) || - (op == other && associativity(op) != Associativity::Both))) || is_shift(op) && is_arith(other) || - is_shift(other) && is_arith(op) + (other.precedence() == op.precedence() && + ((op != other && associativity(op) != dir) || + (op == other && associativity(op) != Associativity::Both))) || + is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) } let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs { @@ -316,11 +325,13 @@ enum Associativity { Right, } -/// Return the associativity/fixity of an operator. The difference with `AssocOp::fixity` is that +/// Return the associativity/fixity of an operator. The difference with +/// `AssocOp::fixity` is that /// an operator can be both left and right associative (such as `+`: /// `a + b + c == (a + b) + c == a + (b + c)`. /// -/// Chained `as` and explicit `:` type coercion never need inner parenthesis so they are considered +/// Chained `as` and explicit `:` type coercion never need inner parenthesis so +/// they are considered /// associative. fn associativity(op: &AssocOp) -> Associativity { use syntax::util::parser::AssocOp::*; @@ -374,10 +385,14 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { }) } -/// Return the indentation before `span` if there are nothing but `[ \t]` before it on its line. +/// Return the indentation before `span` if there are nothing but `[ \t]` +/// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { let lo = cx.sess().codemap().lookup_char_pos(span.lo); - if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { + if let Some(line) = lo.file.get_line( + lo.line - 1, /* line numbers in `Loc` are 1-based */ + ) + { if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { // we can mix char and byte positions here because we only consider `[ \t]` if lo.col == CharPos(pos) { @@ -424,7 +439,10 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D) { if let Some(indent) = indentation(cx, item) { - let span = Span { hi: item.lo, ..item }; + let span = Span { + hi: item.lo, + ..item + }; self.span_suggestion(span, msg, format!("{}\n{}", attr, indent)); } @@ -432,10 +450,14 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) { if let Some(indent) = indentation(cx, item) { - let span = Span { hi: item.lo, ..item }; + let span = Span { + hi: item.lo, + ..item + }; let mut first = true; - let new_item = new_item.lines() + let new_item = new_item + .lines() .map(|l| if first { first = false; format!("{}\n", l) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 059f4e36a03..c864c9d2aeb 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -63,7 +63,10 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { let parent_item = cx.tcx.hir.get_parent(len.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(len).is_ok() { + if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables) + .eval(len) + .is_ok() + { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() } else { return; @@ -84,12 +87,14 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { }, }; - span_lint_and_sugg(cx, - USELESS_VEC, - span, - "useless use of `vec!`", - "you can use a slice directly", - snippet); + span_lint_and_sugg( + cx, + USELESS_VEC, + span, + "useless use of `vec!`", + "you can use a slice directly", + snippet, + ); } /// Return the item type of the vector (ie. the `T` in `Vec`). diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index b00d23d6fba..888cd339096 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -5,7 +5,8 @@ use utils::span_help_and_lint; /// **What it does:** Checks for `0.0 / 0.0`. /// -/// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN`. +/// **Why is this bad?** It's less readable than `std::f32::NAN` or +/// `std::f64::NAN`. /// /// **Known problems:** None. /// diff --git a/src/main.rs b/src/main.rs index 266c1373ff2..8e92eb55ff0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,8 +46,13 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType, ) -> Compilation { - self.default - .early_callback(matches, sopts, cfg, descriptions, output) + self.default.early_callback( + matches, + sopts, + cfg, + descriptions, + output, + ) } fn no_input( &mut self, @@ -58,8 +63,14 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry, ) -> Option<(Input, Option)> { - self.default - .no_input(matches, sopts, cfg, odir, ofile, descriptions) + self.default.no_input( + matches, + sopts, + cfg, + odir, + ofile, + descriptions, + ) } fn late_callback( &mut self, @@ -69,8 +80,13 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { odir: &Option, ofile: &Option, ) -> Compilation { - self.default - .late_callback(matches, sess, input, odir, ofile) + self.default.late_callback( + matches, + sess, + input, + odir, + ofile, + ) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { let mut control = self.default.build_controller(sess, matches); @@ -79,13 +95,17 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); control.after_parse.callback = Box::new(move |state| { { - let mut registry = rustc_plugin::registry::Registry::new(state.session, - state - .krate - .as_ref() - .expect("at this compilation stage \ - the krate must be parsed") - .span); + let mut registry = rustc_plugin::registry::Registry::new( + state.session, + state + .krate + .as_ref() + .expect( + "at this compilation stage \ + the krate must be parsed", + ) + .span, + ); registry.args_hidden = Some(Vec::new()); clippy_lints::register_plugins(&mut registry); @@ -179,9 +199,9 @@ pub fn main() { if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { // this arm is executed on the initial call to `cargo clippy` - let manifest_path_arg = std::env::args() - .skip(2) - .find(|val| val.starts_with("--manifest-path=")); + let manifest_path_arg = std::env::args().skip(2).find(|val| { + val.starts_with("--manifest-path=") + }); let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { @@ -191,55 +211,59 @@ pub fn main() { process::exit(101); }; - let manifest_path = manifest_path_arg.map(|arg| Path::new(&arg["--manifest-path=".len()..]) - .canonicalize().expect("manifest path could not be canonicalized")); + let manifest_path = manifest_path_arg.map(|arg| { + Path::new(&arg["--manifest-path=".len()..]) + .canonicalize() + .expect("manifest path could not be canonicalized") + }); let package_index = { - if let Some(manifest_path) = manifest_path { - metadata.packages.iter().position(|package| { + if let Some(manifest_path) = manifest_path { + metadata.packages.iter().position(|package| { + let package_manifest_path = Path::new(&package.manifest_path).canonicalize().expect( + "package manifest path could not be canonicalized", + ); + package_manifest_path == manifest_path + }) + } else { + let package_manifest_paths: HashMap<_, _> = metadata + .packages + .iter() + .enumerate() + .map(|(i, package)| { let package_manifest_path = Path::new(&package.manifest_path) - .canonicalize().expect("package manifest path could not be canonicalized"); - package_manifest_path == manifest_path + .parent() + .expect("could not find parent directory of package manifest") + .canonicalize() + .expect("package directory cannot be canonicalized"); + (package_manifest_path, i) }) - } else { - let package_manifest_paths: HashMap<_, _> = - metadata.packages.iter() - .enumerate() - .map(|(i, package)| { - let package_manifest_path = Path::new(&package.manifest_path) - .parent() - .expect("could not find parent directory of package manifest") - .canonicalize() - .expect("package directory cannot be canonicalized"); - (package_manifest_path, i) - }) - .collect(); - - let current_dir = std::env::current_dir() - .expect("could not read current directory") - .canonicalize() - .expect("current directory cannot be canonicalized"); - - let mut current_path: &Path = ¤t_dir; - - // This gets the most-recent parent (the one that takes the fewest `cd ..`s to - // reach). - loop { - if let Some(&package_index) = package_manifest_paths.get(current_path) { - break Some(package_index); - } - else { - // We'll never reach the filesystem root, because to get to this point in the code - // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to - // unwrap the current path's parent. - current_path = current_path - .parent() - .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display())); - } + .collect(); + + let current_dir = std::env::current_dir() + .expect("could not read current directory") + .canonicalize() + .expect("current directory cannot be canonicalized"); + + let mut current_path: &Path = ¤t_dir; + + // This gets the most-recent parent (the one that takes the fewest `cd ..`s to + // reach). + loop { + if let Some(&package_index) = package_manifest_paths.get(current_path) { + break Some(package_index); + } else { + // We'll never reach the filesystem root, because to get to this point in the + // code + // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to + // unwrap the current path's parent. + current_path = current_path.parent().unwrap_or_else(|| { + panic!("could not find parent of path {}", current_path.display()) + }); } } } - .expect("could not find matching package"); + }.expect("could not find matching package"); let package = metadata.packages.remove(package_index); for target in package.targets { @@ -250,9 +274,12 @@ pub fn main() { std::process::exit(code); } } else if ["bin", "example", "test", "bench"].contains(&&**first) { - if let Err(code) = process(vec![format!("--{}", first), target.name] - .into_iter() - .chain(args)) { + if let Err(code) = process( + vec![format!("--{}", first), target.name] + .into_iter() + .chain(args), + ) + { std::process::exit(code); } } @@ -280,7 +307,9 @@ pub fn main() { .and_then(|out| String::from_utf8(out.stdout).ok()) .map(|s| s.trim().to_owned()) }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") + .expect( + "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust", + ) }; rustc_driver::in_rustc_thread(|| { @@ -310,13 +339,13 @@ pub fn main() { if let Err(CompileIncomplete::Errored(_)) = result { std::process::exit(1); } - }) - .expect("rustc_thread failed"); + }).expect("rustc_thread failed"); } } fn process(old_args: I) -> Result<(), i32> - where I: Iterator +where + I: Iterator, { let mut args = vec!["rustc".to_owned()]; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index f7d0c69afb0..363eeced8a2 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -29,8 +29,6 @@ fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); - #[cfg(target_os = "windows")] - run_mode("ui-windows", "ui"); - #[cfg(not(target_os = "windows"))] - run_mode("ui-posix", "ui"); + #[cfg(target_os = "windows")] run_mode("ui-windows", "ui"); + #[cfg(not(target_os = "windows"))] run_mode("ui-posix", "ui"); } diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 7a2f6701501..378d14972aa 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -24,7 +24,9 @@ fn dogfood() { let mut s = String::new(); s.push_str(" -L target/debug/"); s.push_str(" -L target/debug/deps"); - s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dwarnings -Dclippy_pedantic -Dclippy -Dclippy_internal"); + s.push_str( + " -Zextra-plugins=clippy -Ltarget_recur/debug -Dwarnings -Dclippy_pedantic -Dclippy -Dclippy_internal", + ); config.target_rustcflags = Some(s); if let Ok(name) = var("TESTNAME") { config.filter = Some(name.to_owned()) diff --git a/tests/issue-825.rs b/tests/issue-825.rs index 2d6c8ea384b..685715a111c 100644 --- a/tests/issue-825.rs +++ b/tests/issue-825.rs @@ -6,9 +6,10 @@ // this should compile in a reasonable amount of time fn rust_type_id(name: &str) { if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || - "u32" == &name[..] || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || - "i16" == &name[..] || "i32" == &name[..] || - "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] { + "u32" == &name[..] || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || + "i16" == &name[..] || "i32" == &name[..] || + "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + { unreachable!(); } } diff --git a/tests/matches.rs b/tests/matches.rs index ade8db2aa27..2f9a61ed768 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -19,14 +19,28 @@ fn test_overlapping() { assert_eq!(None, overlapping::(&[])); assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))])); assert_eq!(None, overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])); - assert_eq!(None, - overlapping(&[sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(10, Bound::Included(11))])); - assert_eq!(Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), - overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))])); - assert_eq!(Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), - overlapping(&[sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(6, Bound::Included(11))])); + assert_eq!( + None, + overlapping( + &[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(10, Bound::Included(11)), + ], + ) + ); + assert_eq!( + Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), + overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))]) + ); + assert_eq!( + Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), + overlapping( + &[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(6, Bound::Included(11)), + ], + ) + ); } diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 0fcef518030..a669b6f9477 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -86,4 +86,3 @@ fn test_erode_block() { println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got); assert_eq!(expected, got); } - -- cgit 1.4.1-3-g733a5 From 0e4c49b145a686c83fb669dabb39b9d13a9c6a97 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 9 Aug 2017 09:59:38 +0200 Subject: Handfix dogfood issues with the rustfmt changes --- clippy_lints/src/lifetimes.rs | 6 ++--- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/non_expressive_names.rs | 41 +++++++------------------------- src/lib.rs | 15 ++++++------ 4 files changed, 20 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index dd721db0f09..21b8bf6b5f5 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -192,10 +192,10 @@ fn could_use_elision<'a, 'tcx: 'a>( // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - if input_lts.iter().all(|lt| { + let unnamed_and_static = input_lts.iter().all(|lt| { *lt == RefLt::Unnamed || *lt == RefLt::Static - }) - { + }); + if unnamed_and_static { return false; } // we have no output reference, so we only need all distinct lifetimes diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 17b3ad4d9e2..8f62494109f 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -21,6 +21,7 @@ // // // +// // rs#L246 // diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index fa915e83aed..a28dc42a8f0 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -104,26 +104,7 @@ fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { } fn whitelisted(interned_name: &str, list: &[&str]) -> bool { - if list.iter().any(|&name| interned_name == name) { - return true; - } - for name in list { - // name_* - if interned_name.chars().zip(name.chars()).all(|(l, r)| l == r) { - return true; - } - // *_name - if interned_name.chars().rev().zip(name.chars().rev()).all( - |(l, - r)| { - l == r - }, - ) - { - return true; - } - } - false + list.iter().any(|&name| interned_name.starts_with(name) || interned_name.ends_with(name)) } impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { @@ -180,19 +161,19 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let first_e = existing_chars.next().expect( "we know we have at least one char", ); - let eq_or_numeric = |a: char, b: char| a == b || a.is_numeric() && b.is_numeric(); + let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric(); - if eq_or_numeric(first_i, first_e) { + if eq_or_numeric((first_i, first_e)) { let last_i = interned_chars.next_back().expect( "we know we have at least two chars", ); let last_e = existing_chars.next_back().expect( "we know we have at least two chars", ); - if eq_or_numeric(last_i, last_e) { + if eq_or_numeric((last_i, last_e)) { if interned_chars .zip(existing_chars) - .filter(|&(i, e)| !eq_or_numeric(i, e)) + .filter(|&ie| !eq_or_numeric(ie)) .count() != 1 { continue; @@ -204,10 +185,8 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let second_last_e = existing_chars.next_back().expect( "we know we have at least three chars", ); - if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| { - eq_or_numeric(i, e) - }) + if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' || + !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity foo_x, foo_y // or too many chars differ (foo_x, boo_y) or (foox, booy) @@ -222,10 +201,8 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let second_e = existing_chars.next().expect( "we know we have at least two chars", ); - if !eq_or_numeric(second_i, second_e) || second_i == '_' || - !interned_chars.zip(existing_chars).all(|(i, e)| { - eq_or_numeric(i, e) - }) + if !eq_or_numeric((second_i, second_e)) || second_i == '_' || + !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity x_foo, y_foo // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) diff --git a/src/lib.rs b/src/lib.rs index a1e18ecc9b4..df692b7e60c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,14 +12,13 @@ extern crate clippy_lints; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { if let Ok(lint_store) = reg.sess.lint_store.try_borrow() { - if lint_store - .get_lint_groups() - .iter() - .any(|&(s, _, _)| s == "clippy") { - reg.sess - .struct_warn("running cargo clippy on a crate that also imports the clippy plugin") - .emit(); - return; + for (lint, _, _) in lint_store.get_lint_groups() { + if lint == "clippy" { + reg.sess + .struct_warn("running cargo clippy on a crate that also imports the clippy plugin") + .emit(); + return; + } } } -- cgit 1.4.1-3-g733a5 From 459cf467c56a841b3f426663d8eccaa76e94ae03 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 Aug 2017 14:11:46 +0200 Subject: Rustup --- clippy_lints/src/cyclomatic_complexity.rs | 21 +++++++++++++---- clippy_lints/src/matches.rs | 4 ++-- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/non_expressive_names.rs | 4 +++- clippy_lints/src/strings.rs | 6 ++--- clippy_lints/src/unicode.rs | 12 +++++----- clippy_lints/src/utils/mod.rs | 38 +++++++++++++++---------------- tests/ui/builtin-type-shadow.stderr | 2 ++ tests/ui/for_loop.rs | 2 +- tests/ui/for_loop.stderr | 10 +------- 10 files changed, 52 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index e87e60f9d23..f2ee62995a0 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -8,7 +8,7 @@ use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; use syntax::ast::{Attribute, NodeId}; use syntax::codemap::Span; -use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type}; +use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type, is_allowed}; /// **What it does:** Checks for methods with high cyclomatic complexity. /// @@ -79,7 +79,16 @@ impl CyclomaticComplexity { }; if cc + divergence < match_arms + short_circuits { - report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span); + report_cc_bug( + cx, + cc, + match_arms, + divergence, + short_circuits, + ret_adjust, + span, + body.id().node_id, + ); } else { let mut rust_cc = cc + divergence - match_arms - short_circuits; // prevent degenerate cases where unreachable code contains `return` statements @@ -180,7 +189,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { } #[cfg(feature = "debugging")] -fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { +#[allow(too_many_arguments)] +fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) { span_bug!( span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ @@ -193,8 +203,9 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, re ); } #[cfg(not(feature = "debugging"))] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) { - if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { +#[allow(too_many_arguments)] +fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) { + if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) { cx.sess().span_note_without_error( span, &format!( diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 5dba102f6a4..77050a0e299 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -12,7 +12,7 @@ use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, span_lint_and_sugg, in_external_macro, - expr_block, walk_ptrs_ty, is_expn_of, remove_blocks}; + expr_block, walk_ptrs_ty, is_expn_of, remove_blocks, is_allowed}; use utils::sugg::Sugg; /// **What it does:** Checks for matches with a single arm where an `if let` @@ -194,7 +194,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { return; }; let ty = cx.tables.expr_ty(ex); - if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow { + if ty.sty != ty::TyBool || is_allowed(cx, MATCH_BOOL, ex.id) { check_single_match_single_pattern(cx, ex, arms, expr, els); check_single_match_opt_like(cx, ex, arms, expr, ty, els); } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 8f62494109f..f0c417f4646 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -22,6 +22,7 @@ // // // +// // rs#L246 // diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index a28dc42a8f0..c584e3b1a9e 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -104,7 +104,9 @@ fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { } fn whitelisted(interned_name: &str, list: &[&str]) -> bool { - list.iter().any(|&name| interned_name.starts_with(name) || interned_name.ends_with(name)) + list.iter().any(|&name| { + interned_name.starts_with(name) || interned_name.ends_with(name) + }) } impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 9b61f902c49..587ad38c9e5 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Spanned; use utils::SpanlessEq; -use utils::{match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty, get_parent_expr}; +use utils::{match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty, get_parent_expr, is_allowed}; /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -83,9 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { if is_string(cx, left) { - if let Allow = cx.current_level(STRING_ADD_ASSIGN) { - // the string_add_assign is allow, so no duplicates - } else { + if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) { let parent = get_parent_expr(cx, e); if let Some(p) = parent { if let ExprAssign(ref target, _) = p.node { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index ace8ea7558d..14d6323de47 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,9 +1,9 @@ use rustc::lint::*; use rustc::hir::*; -use syntax::ast::LitKind; +use syntax::ast::{LitKind, NodeId}; use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; -use utils::{snippet, span_help_and_lint}; +use utils::{snippet, span_help_and_lint, is_allowed}; /// **What it does:** Checks for the Unicode zero-width space in the code. /// @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unicode { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprLit(ref lit) = expr.node { if let LitKind::Str(_, _) = lit.node { - check_str(cx, lit.span) + check_str(cx, lit.span, expr.id) } } } @@ -93,7 +93,7 @@ fn escape>(s: T) -> String { result } -fn check_str(cx: &LateContext, span: Span) { +fn check_str(cx: &LateContext, span: Span, id: NodeId) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { span_help_and_lint( @@ -115,7 +115,7 @@ fn check_str(cx: &LateContext, span: Span) { "literal non-ASCII character detected", &format!( "Consider replacing the string with:\n\"{}\"", - if cx.current_level(UNICODE_NOT_NFC) == Level::Allow { + if is_allowed(cx, UNICODE_NOT_NFC, id) { escape(string.chars()) } else { escape(string.nfc()) @@ -123,7 +123,7 @@ fn check_str(cx: &LateContext, span: Span) { ), ); } - if cx.current_level(NON_ASCII_LITERAL) == Level::Allow && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { + if is_allowed(cx, NON_ASCII_LITERAL, id) && string.chars().zip(string.nfc()).any(|(a, b)| a != b) { span_help_and_lint( cx, UNICODE_NOT_NFC, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 43c0eb68d69..bb79fcef909 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::Def; use rustc::hir::map::Node; -use rustc::lint::{LintContext, LateContext, Level, Lint}; +use rustc::lint::{LintContext, Level, LateContext, Lint}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, TyCtxt, Ty}; @@ -545,10 +545,7 @@ impl<'a> DiagnosticWrapper<'a> { } pub fn span_lint<'a, T: LintContext<'a>>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - if cx.current_level(lint) != Level::Allow { - db.wiki_link(lint); - } + DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)).wiki_link(lint); } pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( @@ -559,10 +556,8 @@ pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( help: &str, ) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - if cx.current_level(lint) != Level::Allow { - db.0.help(help); - db.wiki_link(lint); - } + db.0.help(help); + db.wiki_link(lint); } pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( @@ -574,14 +569,12 @@ pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( note: &str, ) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - if cx.current_level(lint) != Level::Allow { - if note_span == span { - db.0.note(note); - } else { - db.0.span_note(note_span, note); - } - db.wiki_link(lint); + if note_span == span { + db.0.note(note); + } else { + db.0.span_note(note_span, note); } + db.wiki_link(lint); } pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( @@ -594,10 +587,8 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - if cx.current_level(lint) != Level::Allow { - f(&mut db.0); - db.wiki_link(lint); - } + f(&mut db.0); + db.wiki_link(lint); } pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( @@ -1012,3 +1003,10 @@ pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option bool { + cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow +} diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 29eec0e1d6c..eb4c73b65c6 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -9,6 +9,8 @@ error: This generic shadows the built-in type `u32` error[E0308]: mismatched types --> $DIR/builtin-type-shadow.rs:6:5 | +5 | fn foo(a: u32) -> u32 { + | --- expected `u32` because of return type 6 | 42 | ^^ expected type parameter, found integral variable | diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 1a4b9765063..0dbebcdca2c 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -75,7 +75,7 @@ impl Unrelated { #[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop, for_kv_map)] #[warn(unused_collect)] #[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] -#[allow(many_single_char_names)] +#[allow(many_single_char_names, unused_variables)] fn main() { const MAX_LEN: usize = 42; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index f350547f6c3..d4954357665 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -84,14 +84,6 @@ help: consider using an iterator 84 | for in &vec { | ^^^^^^ -error: unused variable: `i` - --> $DIR/for_loop.rs:88:9 - | -88 | for i in 0..vec.len() { - | ^ - | - = note: `-D unused-variables` implied by `-D warnings` - error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:93:5 | @@ -506,5 +498,5 @@ help: use the corresponding method 344 | for k in rm.keys() { | ^ -error: aborting due to 51 previous errors +error: aborting due to 50 previous errors -- cgit 1.4.1-3-g733a5 From 4e6dd55bed11da70e25cd418a9bd37c1914a8683 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 13 Aug 2017 20:57:55 +0200 Subject: Bump the version --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c72ac8686f..b55b55943a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.151 +* Update to *rustc 1.21.0-nightly (13d94d5fa 2017-08-10)* + ## 0.0.150 * Update to *rustc 1.21.0-nightly (215e0b10e 2017-08-08)* diff --git a/Cargo.toml b/Cargo.toml index a5c615e232c..7ab43621434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.150" +version = "0.0.151" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.150", path = "clippy_lints" } +clippy_lints = { version = "0.0.151", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 5072175d99c..2be46842aac 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.150" +version = "0.0.151" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From d6fc34fd080bccc81e16b82ab01da3e1bc7e5820 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 14 Aug 2017 09:51:16 +0200 Subject: Update for rustc output changes --- tests/ui/shadow.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 9501fd68fce..3fc2b7234f7 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,8 +1,8 @@ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:13:5 | 13 | let x = &mut x; - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: `-D shadow-same` implied by `-D warnings` note: previous binding is here @@ -12,10 +12,10 @@ note: previous binding is here | ^ error: `x` is shadowed by itself in `{ x }` - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:14:5 | 14 | let x = { x }; - | ^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:13:9 @@ -24,10 +24,10 @@ note: previous binding is here | ^ error: `x` is shadowed by itself in `(&*x)` - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:15:5 | 15 | let x = (&*x); - | ^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:14:9 @@ -123,10 +123,10 @@ note: previous binding is here | ^ error: `x` shadows a previous declaration - --> $DIR/shadow.rs:23:9 + --> $DIR/shadow.rs:23:5 | 23 | let x; - | ^ + | ^^^^^ | note: previous binding is here --> $DIR/shadow.rs:21:9 -- cgit 1.4.1-3-g733a5 From 0d244d3f39b30890983a68646b80e3990aa0042b Mon Sep 17 00:00:00 2001 From: Mateusz Mikula Date: Sun, 13 Aug 2017 15:13:13 +0200 Subject: Fix verbose_bit_mask off by one error Fixes #1940 --- clippy_lints/src/bit_mask.rs | 2 +- tests/ui/bit_masks.stderr | 4 ++-- tests/ui/trailing_zeros.stderr | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 64f007bf521..f711a3680a7 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { "bit mask could be simplified with a call to `trailing_zeros`", |db| { let sugg = Sugg::hir(cx, left1, "...").maybe_par(); - db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() > {}", sugg, n.count_ones())); + db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones())); }); }} } diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 1284dd3321c..4b40fa086b8 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -10,7 +10,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/bit_masks.rs:12:5 | 12 | x & 0 == 0; - | ^^^^^^^^^^ help: try: `x.trailing_zeros() > 0` + | ^^^^^^^^^^ help: try: `x.trailing_zeros() >= 0` | = note: `-D verbose-bit-mask` implied by `-D warnings` @@ -18,7 +18,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/bit_masks.rs:14:5 | 14 | x & 1 == 0; //ok, compared with zero - | ^^^^^^^^^^ help: try: `x.trailing_zeros() > 1` + | ^^^^^^^^^^ help: try: `x.trailing_zeros() >= 1` error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:15:5 diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 5a8de3bcc87..91e4d59da98 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -2,7 +2,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:7:31 | 7 | let _ = #[clippy(author)] (x & 0b1111 == 0); // suggest trailing_zeros - | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() > 4` + | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` | = note: `-D verbose-bit-mask` implied by `-D warnings` @@ -10,7 +10,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:8:13 | 8 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros - | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() > 5` + | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From f3ae929b2ddbf15048e0912974f63c6b799ee643 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 15 Aug 2017 11:10:49 +0200 Subject: Rustup --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 3 ++- clippy_lints/src/consts.rs | 6 +++--- clippy_lints/src/cyclomatic_complexity.rs | 4 ++-- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 4 ++-- clippy_lints/src/format.rs | 4 ++-- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/let_if_seq.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 3 ++- clippy_lints/src/loops.rs | 12 ++++++------ clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/mut_reference.rs | 4 ++-- clippy_lints/src/no_effect.rs | 4 ++-- clippy_lints/src/panic.rs | 2 +- clippy_lints/src/print.rs | 6 +++--- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/types.rs | 9 +++++---- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/inspector.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 20 ++++++++++---------- 27 files changed, 60 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a52c4d90aab..86d72226601 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -215,7 +215,7 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool ExprBreak(_, None) => false, ExprCall(ref path_expr, _) => { if let ExprPath(ref qpath) = path_expr.node { - let fun_id = tables.qpath_def(qpath, path_expr.id).def_id(); + let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) } else { true diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index f711a3680a7..6e5a18240cb 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -318,7 +318,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { } }, ExprPath(ref qpath) => { - let def = cx.tables.qpath_def(qpath, lit.id); + let def = cx.tables.qpath_def(qpath, lit.hir_id); if let Def::Const(def_id) = def { lookup_const_by_id(cx.tcx, cx.param_env.and((def_id, Substs::empty()))).and_then(|(l, _ty)| { let body = if let Some(id) = cx.tcx.hir.as_local_node_id(l) { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 4c67b260046..7c7dbe80883 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -122,6 +122,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { let mk_expr = |op| { Expr { id: DUMMY_NODE_ID, + hir_id: DUMMY_HIR_ID, span: DUMMY_SP, attrs: ThinVec::new(), node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), @@ -411,7 +412,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprUnary(UnNot, ref inner) => { - if self.cx.tables.node_types[&inner.id].is_bool() { + if self.cx.tables.node_types()[inner.hir_id].is_bool() { self.bool_expr(e); } else { walk_expr(self, e); diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 095fcf06e09..2a6fa051d2f 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -12,7 +12,7 @@ use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; use std::mem; use std::rc::Rc; -use syntax::ast::{FloatTy, LitKind, StrStyle, NodeId}; +use syntax::ast::{FloatTy, LitKind, StrStyle}; use syntax::ptr::P; #[derive(Debug, Copy, Clone)] @@ -249,7 +249,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// simple constant folding: Insert an expression, get a constant or none. fn expr(&mut self, e: &Expr) -> Option { match e.node { - ExprPath(ref qpath) => self.fetch_path(qpath, e.id), + ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id), ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tcx, self.tables.expr_ty(e))), @@ -284,7 +284,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } /// lookup a possibly constant expression from a ExprPath - fn fetch_path(&mut self, qpath: &QPath, id: NodeId) -> Option { + fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { let def = self.tables.qpath_def(qpath, id); match def { Def::Const(def_id) | diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index f2ee62995a0..c7593a195ff 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -71,7 +71,7 @@ impl CyclomaticComplexity { returns, .. } = helper; - let ret_ty = cx.tables.node_id_to_type(expr.id); + let ret_ty = cx.tables.node_id_to_type(expr.hir_id); let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { returns } else { @@ -160,7 +160,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { }, ExprCall(ref callee, _) => { walk_expr(self, e); - let ty = self.cx.tables.node_id_to_type(callee.id); + let ty = self.cx.tables.node_id_to_type(callee.hir_id); match ty.sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { let sig = ty.fn_sig(self.cx.tcx); diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index b02333b89a0..dfa8ddbab6c 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprPath(ref qpath) = path.node, args.len() == 1, ], { - let def_id = cx.tables.qpath_def(qpath, path.id).def_id(); + let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id(); let lint; let msg; let arg = &args[0]; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 81109761ca7..549b621812d 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { if let ExprPath(ref qpath) = lhs.node { if let QPath::Resolved(_, ref path) = *qpath { if path.segments.len() == 1 { - let var = cx.tables.qpath_def(qpath, lhs.id).def_id(); + let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); let mut visitor = ReadVisitor { cx: cx, var: var, @@ -304,7 +304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { match expr.node { ExprPath(ref qpath) => { if let QPath::Resolved(None, ref path) = *qpath { - if path.segments.len() == 1 && self.cx.tables.qpath_def(qpath, expr.id).def_id() == self.var { + if path.segments.len() == 1 && self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { if is_in_assignment_position(self.cx, expr) { // This is a write, not a read. } else { diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 16dced95760..fb2e04a3662 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain!{[ let ExprPath(ref qpath) = fun.node, args.len() == 2, - match_def_path(cx.tcx, resolve_node(cx, qpath, fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1), + match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::FMT_ARGUMENTS_NEWV1), // ensure the format string is `"{..}"` with only one argument and no text check_static_str(cx, &args[0]), // ensure the format argument is `{}` ie. Display with no fancy option @@ -130,7 +130,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { let ExprCall(_, ref args) = exprs[0].node, args.len() == 2, let ExprPath(ref qpath) = args[1].node, - match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD), + match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].hir_id).def_id(), &paths::DISPLAY_FMT_METHOD), ], { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index e45ab558089..1bb8780ea4a 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -187,7 +187,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } }, hir::ExprMethodCall(_, _, ref args) => { - let def_id = self.cx.tables.type_dependent_defs[&expr.id].def_id(); + let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); let base_type = self.cx.tcx.type_of(def_id); if type_is_unsafe_function(self.cx, base_type) { @@ -210,7 +210,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr) { if let hir::ExprPath(ref qpath) = ptr.node { - let def = self.cx.tables.qpath_def(qpath, ptr.id); + let def = self.cx.tables.qpath_def(qpath, ptr.hir_id); if self.ptrs.contains(&def.def_id()) { span_lint( self.cx, diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index ecd18424bd8..64ba8adafe2 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if_let_chain! {[ let hir::ExprPath(ref qpath) = expr.node, - self.id == self.cx.tables.qpath_def(qpath, expr.id).def_id(), + self.id == self.cx.tables.qpath_def(qpath, expr.hir_id).def_id(), ], { self.used = true; return; @@ -162,7 +162,7 @@ fn check_assign<'a, 'tcx>( let hir::StmtSemi(ref expr, _) = expr.node, let hir::ExprAssign(ref var, ref value) = expr.node, let hir::ExprPath(ref qpath) = var.node, - decl == cx.tables.qpath_def(qpath, var.id).def_id(), + decl == cx.tables.qpath_def(qpath, var.hir_id).def_id(), ], { let mut v = UsedVisitor { cx: cx, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 21b8bf6b5f5..507373fede5 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -284,7 +284,8 @@ impl<'v, 't> RefVisitor<'v, 't> { let last_path_segment = &last_path_segment(qpath).parameters; if let AngleBracketedParameters(ref params) = *last_path_segment { if params.lifetimes.is_empty() { - match self.cx.tables.qpath_def(qpath, ty.id) { + let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + match self.cx.tables.qpath_def(qpath, hir_id) { Def::TyAlias(def_id) | Def::Struct(def_id) => { let generics = self.cx.tcx.generics_of(def_id); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 25015cb26bb..439a82e41ef 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -801,8 +801,8 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { lint_iter_method(cx, args, arg, method_name); } } else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) { - let def_id = cx.tables.type_dependent_defs[&arg.id].def_id(); - let substs = cx.tables.node_substs(arg.id); + let def_id = cx.tables.type_dependent_defs()[arg.hir_id].def_id(); + let substs = cx.tables.node_substs(arg.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); let fn_arg_tys = method_type.fn_sig(cx.tcx).inputs(); @@ -1053,13 +1053,13 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, // our variable! - self.cx.tables.qpath_def(qpath, expr.id).def_id() == self.var, + self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var, // the indexed container is referenced by a name let ExprPath(ref seqpath) = seqexpr.node, let QPath::Resolved(None, ref seqvar) = *seqpath, seqvar.segments.len() == 1, ], { - let def = self.cx.tables.qpath_def(seqpath, seqexpr.id); + let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { Def::Local(..) | Def::Upvar(..) => { let def_id = def.def_id(); @@ -1085,7 +1085,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, ], { - if self.cx.tables.qpath_def(qpath, expr.id).def_id() == self.var { + if self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { // we are not indexing anything, record that self.nonindex = true; } else { @@ -1376,7 +1376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { if let ExprPath(ref qpath) = expr.node { - let path_res = cx.tables.qpath_def(qpath, expr.id); + let path_res = cx.tables.qpath_def(qpath, expr.hir_id); if let Def::Local(def_id) = path_res { let node_id = cx.tcx.hir.as_local_node_id(def_id).expect( "That DefId should be valid", diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 280b51b2312..edf477720d5 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(ref qpath) = path_expr.node { - let def_id = cx.tables.qpath_def(qpath, path_expr.id).def_id(); + let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.tables.expr_ty(&args[0]); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index c04fdde772f..a50d77f5521 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -898,7 +898,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr let hir::ExprCall(ref fun, ref args) = new.node, args.len() == 1, let hir::ExprPath(ref path) = fun.node, - let Def::Method(did) = cx.tables.qpath_def(path, fun.id), + let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id), match_def_path(cx.tcx, did, &paths::CSTRING_NEW) ], { span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 2c6553e90c9..a86b2b300e5 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -62,7 +62,7 @@ enum MinMax { fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(ref qpath) = path.node { - let def_id = cx.tables.qpath_def(qpath, path.id).def_id(); + let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { fetch_const(cx, args, MinMax::Min) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 67b0b1e167d..ef42bfe0b02 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -361,7 +361,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { binding != "_result" && // FIXME: #944 is_used(cx, expr) && // don't lint if the declaration is in a macro - non_macro_local(cx, &cx.tables.qpath_def(qpath, expr.id)) + non_macro_local(cx, &cx.tables.qpath_def(qpath, expr.hir_id)) { Some(binding) } else { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 0c0c8f4061f..6a7b45bfbfb 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -47,8 +47,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { } }, ExprMethodCall(ref path, _, ref arguments) => { - let def_id = cx.tables.type_dependent_defs[&e.id].def_id(); - let substs = cx.tables.node_substs(e.id); + let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); + let substs = cx.tables.node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); check_arguments(cx, arguments, method_type, &path.name.as_str()) }, diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index c57df468f7c..782b4033645 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -69,7 +69,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { }, Expr_::ExprCall(ref callee, ref args) => { if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.id); + let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | @@ -165,7 +165,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.id); + let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 9c1c6beec4f..e9e529cfdb4 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref fun, ref params) = ex.node, params.len() == 2, let ExprPath(ref qpath) = fun.node, - match_def_path(cx.tcx, resolve_node(cx, qpath, fun.id).def_id(), &paths::BEGIN_PANIC), + match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::BEGIN_PANIC), let ExprLit(ref lit) = params[0].node, is_direct_expn_of(expr.span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index bf734cc9c0e..4a427fc79bd 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref fun, ref args) = expr.node, let ExprPath(ref qpath) = fun.node, ], { - let fun = resolve_node(cx, qpath, fun.id); + let fun = resolve_node(cx, qpath, fun.hir_id); let fun_id = fun.def_id(); // Search for `std::io::_print(..)` which is unique in a @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref args_fun, ref args_args) = args[0].node, let ExprPath(ref qpath) = args_fun.node, match_def_path(cx.tcx, - resolve_node(cx, qpath, args_fun.id).def_id(), + resolve_node(cx, qpath, args_fun.hir_id).def_id(), &paths::FMT_ARGUMENTS_NEWV1), args_args.len() == 2, let ExprAddrOf(_, ref match_expr) = args_args[1].node, @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { if let ExprPath(ref qpath) = args[1].node { - let def_id = cx.tables.qpath_def(qpath, args[1].id).def_id(); + let def_id = cx.tables.qpath_def(qpath, args[1].hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 4feeb6d0939..4241dd94ac9 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprPath(ref qpath) = fun.node, args.len() == 1, ], { - let def_id = cx.tables.qpath_def(qpath, fun.id).def_id(); + let def_id = cx.tables.qpath_def(qpath, fun.hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { check_regex(cx, &args[0], true); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index e80636ca347..b4857f1b613 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -148,7 +148,7 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: } } -fn is_binding(cx: &LateContext, pat_id: NodeId) -> bool { +fn is_binding(cx: &LateContext, pat_id: HirId) -> bool { let var_ty = cx.tables.node_id_to_type(pat_id); match var_ty.sty { ty::TyAdt(..) => false, @@ -167,7 +167,7 @@ fn check_pat<'a, 'tcx>( match pat.node { PatKind::Binding(_, _, ref ident, ref inner) => { let name = ident.node; - if is_binding(cx, pat.id) { + if is_binding(cx, pat.hir_id) { let mut new_binding = true; for tup in bindings.iter_mut() { if tup.0 == name { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 13555e3bb05..bcb03c79215 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -88,7 +88,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(ref qpath) = path_expr.node { - let def_id = cx.tables.qpath_def(qpath, path_expr.id).def_id(); + let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { let from_ty = cx.tables.expr_ty(&args[0]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 44e33d40a38..ed0027af533 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -149,7 +149,8 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } match ast_ty.node { TyPath(ref qpath) if !is_local => { - let def = cx.tables.qpath_def(qpath, ast_ty.id); + let hir_id = cx.tcx.hir.node_to_hir_id(ast_ty.id); + let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { if Some(def_id) == cx.tcx.lang_items.owned_box() { let last = last_path_segment(qpath); @@ -157,8 +158,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, let Some(vec) = ag.types.get(0), let TyPath(ref qpath) = vec.node, - let def::Def::Struct(..) = cx.tables.qpath_def(qpath, vec.id), - let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, vec.id)), + let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))), match_def_path(cx.tcx, did, &paths::VEC), ], { span_help_and_lint(cx, @@ -202,7 +202,8 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { TyRptr(ref lt, MutTy { ref ty, ref mutbl }) => { match ty.node { TyPath(ref qpath) => { - let def = cx.tables.qpath_def(qpath, ast_ty.id); + let hir_id = cx.tcx.hir.node_to_hir_id(ty.id); + let def = cx.tables.qpath_def(qpath, hir_id); if_let_chain! {[ let Some(def_id) = opt_def_id(def), Some(def_id) == cx.tcx.lang_items.owned_box(), diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 593cbf69f5b..d138892a092 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -159,7 +159,7 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option bool { fn print_decl(cx: &LateContext, decl: &hir::Decl) { match decl.node { hir::DeclLocal(ref local) => { - println!("local variable of type {}", cx.tables.node_id_to_type(local.id)); + println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); println!("pattern:"); print_pat(cx, &local.pat, 0); if let Some(ref e) = local.init { @@ -161,7 +161,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); println!("{}ty: {}", ind, cx.tables.expr_ty(expr)); - println!("{}adjustments: {:?}", ind, cx.tables.adjustments.get(&expr.id)); + println!("{}adjustments: {:?}", ind, cx.tables.adjustments().get(expr.hir_id)); match expr.node { hir::ExprBox(ref e) => { println!("{}Box", ind); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bb79fcef909..d62f3963bc3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -196,7 +196,7 @@ pub fn match_type(cx: &LateContext, ty: Ty, path: &[&str]) -> bool { /// Check if the method call given in `expr` belongs to given type. pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = cx.tables.type_dependent_defs[&expr.id]; + let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; let trt_id = cx.tcx.impl_of_method(method_call.def_id()); if let Some(trt_id) = trt_id { match_def_path(cx.tcx, trt_id, path) @@ -207,7 +207,7 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { /// Check if the method call given in `expr` belongs to given trait. pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = cx.tables.type_dependent_defs[&expr.id]; + let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; let trt_id = cx.tcx.trait_of_item(method_call.def_id()); if let Some(trt_id) = trt_id { match_def_path(cx.tcx, trt_id, path) @@ -347,8 +347,8 @@ pub fn implements_trait<'a, 'tcx>( }) } -/// Resolve the definition of a node from its `NodeId`. -pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: NodeId) -> def::Def { +/// Resolve the definition of a node from its `HirId`. +pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: HirId) -> def::Def { cx.tables.qpath_def(qpath, id) } @@ -656,7 +656,7 @@ pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { } pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { - cx.tables.adjustments.get(&e.id).is_some() + cx.tables.adjustments().get(e.hir_id).is_some() } pub struct LimitStack { @@ -833,9 +833,9 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { /// Return whether a pattern is refutable. pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { - fn is_enum_variant(cx: &LateContext, qpath: &QPath, did: NodeId) -> bool { + fn is_enum_variant(cx: &LateContext, qpath: &QPath, id: HirId) -> bool { matches!( - cx.tables.qpath_def(qpath, did), + cx.tables.qpath_def(qpath, id), def::Def::Variant(..) | def::Def::VariantCtor(..) ) } @@ -851,17 +851,17 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { PatKind::Ref(ref pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, - PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.id), + PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), PatKind::Struct(ref qpath, ref fields, _) => { - if is_enum_variant(cx, qpath, pat.id) { + if is_enum_variant(cx, qpath, pat.hir_id) { true } else { are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) } }, PatKind::TupleStruct(ref qpath, ref pats, _) => { - if is_enum_variant(cx, qpath, pat.id) { + if is_enum_variant(cx, qpath, pat.hir_id) { true } else { are_refutable(cx, pats.iter().map(|pat| &**pat)) -- cgit 1.4.1-3-g733a5 From 7cdaeae1b877ca03b26ccb9b82754b826b03da5d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 15 Aug 2017 11:11:20 +0200 Subject: Bump the version --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b55b55943a7..ded1788cd01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.152 +* Update to *rustc 1.21.0-nightly (df511d554 2017-08-14)* + ## 0.0.151 * Update to *rustc 1.21.0-nightly (13d94d5fa 2017-08-10)* diff --git a/Cargo.toml b/Cargo.toml index 7ab43621434..7dc5edfdd16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.151" +version = "0.0.152" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.151", path = "clippy_lints" } +clippy_lints = { version = "0.0.152", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 2be46842aac..0b70f412f3f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.151" +version = "0.0.152" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 4402bc70a3b175c38994bbc802bee41ddc59165b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 15 Aug 2017 18:24:42 +0200 Subject: Rust needs clippy to have a Cargo.lock --- .gitignore | 3 - Cargo.lock | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index d25c1a08ee4..dbb5a66e469 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,6 @@ out /target/ /clippy_lints/target/ -# We don't pin yet -Cargo.lock - # Generated by dogfood /target_recur/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000000..1e23a7e75d5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,460 @@ +[root] +name = "clippy_lints" +version = "0.0.152" +dependencies = [ + "itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cargo_metadata" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clippy" +version = "0.0.152" +dependencies = [ + "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy-mini-macro-test 0.1.0", + "clippy_lints 0.0.152", + "compiletest_rs 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clippy-mini-macro-test" +version = "0.1.0" + +[[package]] +name = "compiletest_rs" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dbghelp-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dtoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "duct" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "error-chain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "getopts" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itertools" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "matches" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "os_pipe" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pulldown-cmark" +version = "0.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quine-mc_cluskey" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "shared_child" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" +"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" +"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum compiletest_rs 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc4720203de7b490e2808cad3e9090e8850eed4ecd4176b246551a952f4ead7" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" +"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" +"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" +"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" +"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" +"checksum itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e58359414720377f59889192f1ec0e726049ce5735bc21fdb0c4c8ae638305bb" +"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" +"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" +"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" +"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" +"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" +"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -- cgit 1.4.1-3-g733a5 From 7759bd61119580cf13d85e6a38ea4254244e84e8 Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Fri, 28 Jul 2017 13:28:07 +0200 Subject: lint #1674: replace struct name with `Self` when applicable --- clippy_lints/src/lib.rs | 2 + clippy_lints/src/use_self.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++ tests/ui/use_self.rs | 45 ++++++++++++++++++++++ tests/ui/use_self.stderr | 40 ++++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 clippy_lints/src/use_self.rs create mode 100644 tests/ui/use_self.rs create mode 100644 tests/ui/use_self.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 18759fb0a91..a8f1b1664b0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -148,6 +148,7 @@ pub mod unicode; pub mod unsafe_removed_from_name; pub mod unused_io_amount; pub mod unused_label; +pub mod use_self; pub mod vec; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -319,6 +320,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box should_assert_eq::ShouldAssertEq); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); + reg.register_late_lint_pass(box use_self::UseSelf); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs new file mode 100644 index 00000000000..6344c25b084 --- /dev/null +++ b/clippy_lints/src/use_self.rs @@ -0,0 +1,90 @@ +use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::hir::*; +use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap}; +use utils::span_lint; +use syntax::ast::NodeId; + +/// **What it does:** Checks for unnecessary repetition of structure name when a +/// replacement with `Self` is applicable. +/// +/// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct name +/// feels inconsistent. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// struct Foo {} +/// impl Foo { +/// fn new() -> Foo { +/// Foo {} +/// } +/// } +/// ``` +/// could be +/// ``` +/// struct Foo {} +/// impl Foo { +/// fn new() -> Self { +/// Self {} +/// } +/// } +/// ``` +declare_lint! { + pub USE_SELF, + Allow, + "Repetitive struct name usage whereas `Self` is applicable" +} + +#[derive(Copy, Clone, Default)] +pub struct UseSelf; + +impl LintPass for UseSelf { + fn get_lints(&self) -> LintArray { + lint_array!(USE_SELF) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if_let_chain!([ + let ItemImpl(.., ref item_type, ref refs) = item.node, + let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, + ], { + let visitor = &mut UseSelfVisitor { + item_path: item_path, + cx: cx, + }; + for impl_item_ref in refs { + visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + } + }) + } +} + +struct UseSelfVisitor<'a, 'tcx: 'a> { + item_path: &'a Path, + cx: &'a LateContext<'a, 'tcx>, +} + +impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { + fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) { + if self.item_path.def == path.def && + path.segments + .last() + .expect("segments should be composed of at least 1 elemnt") + .name + .as_str() != "Self" { + span_lint(self.cx, + USE_SELF, + path.span, + "repetitive struct name usage. Use `Self` instead."); + } + + walk_path(self, path); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + } +} diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs new file mode 100644 index 00000000000..40cef1a9362 --- /dev/null +++ b/tests/ui/use_self.rs @@ -0,0 +1,45 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![warn(use_self)] +#![allow(dead_code)] + + +fn main() {} + +mod use_self { + struct Foo {} + + impl Foo { + fn new() -> Foo { + Foo {} + } + fn test() -> Foo { + Foo::new() + } + } + + impl Default for Foo { + fn default() -> Foo { + Foo::new() + } + } +} + +mod better { + struct Foo {} + + impl Foo { + fn new() -> Self { + Self {} + } + fn test() -> Self { + Self::new() + } + } + + impl Default for Foo { + fn default() -> Self { + Self::new() + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr new file mode 100644 index 00000000000..1529978f2b3 --- /dev/null +++ b/tests/ui/use_self.stderr @@ -0,0 +1,40 @@ +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:13:21 + | +13 | fn new() -> Foo { + | ^^^ + | + = note: `-D use-self` implied by `-D warnings` + +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:14:13 + | +14 | Foo {} + | ^^^ + +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:16:22 + | +16 | fn test() -> Foo { + | ^^^ + +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:17:13 + | +17 | Foo::new() + | ^^^^^^^^ + +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:22:25 + | +22 | fn default() -> Foo { + | ^^^ + +error: repetitive struct name usage. Use `Self` instead. + --> $DIR/use_self.rs:23:13 + | +23 | Foo::new() + | ^^^^^^^^ + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From cf8e95eb2208ab869df241d11c887a33e67d033f Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Fri, 18 Aug 2017 17:07:39 +0300 Subject: is_from_for_desugar: add match for `for _ in x` This will avoid `let_unit_value` in the examples in the ui-test. It might match too widely. --- clippy_lints/src/utils/higher.rs | 16 ++++++++++++++++ tests/ui/let_unit.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d138892a092..3665bdf2360 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -121,6 +121,22 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { ], { return true; }} + + // This detects a variable binding in for loop to avoid `let_unit_value` + // lint (see issue #1964). + // + // ``` + // for _ in vec![()] { + // // anything + // } + // ``` + if_let_chain! {[ + let hir::DeclLocal(ref loc) = decl.node, + let hir::LocalSource::ForLoopDesugar = loc.source, + ], { + return true; + }} + false } diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index ecae967f781..0b0afccef45 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -18,8 +18,30 @@ fn main() { let _a = (); } + consume_units_with_for_loop(); // should be fine as well + let_and_return!(()) // should be fine } +// Related to issue #1964 +fn consume_units_with_for_loop() { + // `for_let_unit` lint should not be triggered by consuming them using for loop. + let v = vec![(), (), ()]; + let mut count = 0; + for _ in v { + count += 1; + } + assert_eq!(count, 3); + + // Same for consuming from some other Iterator<()>. + let (tx, rx) = ::std::sync::mpsc::channel(); + tx.send(()).unwrap(); + count = 0; + for _ in rx.iter() { + count += 1; + } + assert_eq!(count, 1); +} + #[derive(Copy, Clone)] pub struct ContainsUnit(()); // should be fine -- cgit 1.4.1-3-g733a5 From a5147e8a0819dd1daab28a3ef1970069396a5bf1 Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Fri, 18 Aug 2017 17:12:00 +0300 Subject: is_from_for_loop: document what first check matches Removing the first check will break a lot of for-loop UI tests and the dogfood test. --- clippy_lints/src/utils/higher.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 3665bdf2360..67319f0c355 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -114,6 +114,13 @@ pub fn range(expr: &hir::Expr) -> Option { /// Checks if a `let` decl is from a `for` loop desugaring. pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { + // This will detect plain for-loops without an actual variable binding: + // + // ``` + // for x in some_vec { + // // do stuff + // } + // ``` if_let_chain! {[ let hir::DeclLocal(ref loc) = decl.node, let Some(ref expr) = loc.init, -- cgit 1.4.1-3-g733a5 From 171f7b4eb7fed11f9282eb0c5af5eda1e77f9bc6 Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Fri, 18 Aug 2017 17:29:05 +0300 Subject: tests/ui/let_unit: fix comment and example code The previous version would had deadlocked as the Sender remained alive and iterator would had never became complete. Just in case someone decided to run it. --- tests/ui/let_unit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 0b0afccef45..d07cf8ede2f 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -33,9 +33,11 @@ fn consume_units_with_for_loop() { } assert_eq!(count, 3); - // Same for consuming from some other Iterator<()>. + // Same for consuming from some other Iterator. let (tx, rx) = ::std::sync::mpsc::channel(); tx.send(()).unwrap(); + drop(tx); + count = 0; for _ in rx.iter() { count += 1; -- cgit 1.4.1-3-g733a5 From 7aebe3a69046d5f78f614ba80f0db3fe0b0b719b Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Fri, 18 Aug 2017 19:42:26 +0200 Subject: lint #1674: replace struct name with `Self` when applicable SelfType const and suggestion --- clippy_lints/src/use_self.rs | 19 ++++++++++--------- tests/ui/use_self.stderr | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 6344c25b084..2a94d8fe9cc 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,8 +1,9 @@ use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap}; -use utils::span_lint; +use utils::span_lint_and_then; use syntax::ast::NodeId; +use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. @@ -33,7 +34,7 @@ use syntax::ast::NodeId; declare_lint! { pub USE_SELF, Allow, - "Repetitive struct name usage whereas `Self` is applicable" + "Unnecessary structure name repetition whereas `Self` is applicable" } #[derive(Copy, Clone, Default)] @@ -72,13 +73,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { if self.item_path.def == path.def && path.segments .last() - .expect("segments should be composed of at least 1 elemnt") - .name - .as_str() != "Self" { - span_lint(self.cx, - USE_SELF, - path.span, - "repetitive struct name usage. Use `Self` instead."); + .expect("segments should be composed of at least 1 element") + .name != SelfType.name() { + span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { + db.span_suggestion(path.span, + "use the applicable keyword", + "Self".to_owned()); + }); } walk_path(self, path); diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 1529978f2b3..0cbd574b506 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,40 +1,40 @@ -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:13:21 | 13 | fn new() -> Foo { - | ^^^ + | ^^^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:14:13 | 14 | Foo {} - | ^^^ + | ^^^ help: use the applicable keyword: `Self` -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:16:22 | 16 | fn test() -> Foo { - | ^^^ + | ^^^ help: use the applicable keyword: `Self` -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:17:13 | 17 | Foo::new() - | ^^^^^^^^ + | ^^^^^^^^ help: use the applicable keyword: `Self` -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:22:25 | 22 | fn default() -> Foo { - | ^^^ + | ^^^ help: use the applicable keyword: `Self` -error: repetitive struct name usage. Use `Self` instead. +error: unnecessary structure name repetition --> $DIR/use_self.rs:23:13 | 23 | Foo::new() - | ^^^^^^^^ + | ^^^^^^^^ help: use the applicable keyword: `Self` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From f770d15350608c0a81bbd11ad51ef43879def1ad Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Sat, 19 Aug 2017 18:03:29 +1000 Subject: use CompilerDesugaringKind --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d62f3963bc3..f3fae14bae8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -16,7 +16,7 @@ use std::mem; use std::str::FromStr; use syntax::ast::{self, LitKind}; use syntax::attr; -use syntax::codemap::{ExpnFormat, ExpnInfo, Span, DUMMY_SP}; +use syntax::codemap::{CompilerDesugaringKind, ExpnFormat, ExpnInfo, Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; use syntax::symbol::keywords; @@ -114,7 +114,7 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { pub fn in_macro(span: Span) -> bool { span.ctxt.outer().expn_info().map_or(false, |info| { match info.callee.format {// don't treat range expressions desugared to structs as "in_macro" - ExpnFormat::CompilerDesugaring(name) => name != "...", + ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, _ => true, } }) -- cgit 1.4.1-3-g733a5 From 93c48a0977927fc3678600d0d79ef43e8f30761f Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sat, 19 Aug 2017 22:52:49 +0200 Subject: remove stars at the beginning of multiline comments --- clippy_lints/src/doc.rs | 25 +++++++++++++++++++++---- tests/ui/doc.rs | 6 ++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 3ca71694bbd..6dbf2ea959e 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -109,11 +109,11 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( if comment.starts_with("/*") { let doc = &comment[3..comment.len() - 2]; let mut sizes = vec![]; - + let mut contains_initial_stars = false; for line in doc.lines() { let offset = line.as_ptr() as usize - comment.as_ptr() as usize; debug_assert_eq!(offset as u32 as usize, offset); - + contains_initial_stars |= line.trim_left().starts_with('*'); // +1 for the newline sizes.push(( line.len() + 1, @@ -123,8 +123,25 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( }, )); } - - return (doc.to_string(), sizes); + if !contains_initial_stars { + return (doc.to_string(), sizes); + } + // remove the initial '*'s if any + let mut no_stars = String::with_capacity(doc.len()); + for line in doc.lines() { + let mut chars = line.chars(); + while let Some(c) = chars.next() { + if c.is_whitespace() { + no_stars.push(c); + } else { + no_stars.push(if c == '*' { ' ' } else { c }); + break; + } + } + no_stars.push_str(chars.as_str()); + no_stars.push('\n'); + } + return (no_stars, sizes); } panic!("not a doc-comment: {}", comment); diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 0be34aa6f53..b03f90681f2 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -153,3 +153,9 @@ fn issue_902_comment() {} /// } /// ``` fn issue_1469() {} + +/** + * This is a doc comment that should not be a list + *This would also be an error under a strict common mark interpretation + */ +fn issue_1920() {} -- cgit 1.4.1-3-g733a5 From 1265b4647873932ede92cf06d6f2effc2f4f73b3 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 18 Aug 2017 17:57:33 +0100 Subject: Basic implementation of `cargo clippy --all` This implements workspace support for `cargo clippy` by running clippy over all packages in the workspace (in serial). This should probably be parallelised in future (as `cargo build --all`). --- src/main.rs | 138 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8e92eb55ff0..2f4d782f78e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,6 +152,7 @@ Common options: -h, --help Print this message --features Features to compile for the package -V, --version Print version info and exit + --all @@@ something sensible here (copy from cargo-edit?) Other options are the same as `cargo rustc`. @@ -217,74 +218,85 @@ pub fn main() { .expect("manifest path could not be canonicalized") }); - let package_index = { - if let Some(manifest_path) = manifest_path { - metadata.packages.iter().position(|package| { - let package_manifest_path = Path::new(&package.manifest_path).canonicalize().expect( - "package manifest path could not be canonicalized", - ); - package_manifest_path == manifest_path - }) - } else { - let package_manifest_paths: HashMap<_, _> = metadata - .packages - .iter() - .enumerate() - .map(|(i, package)| { - let package_manifest_path = Path::new(&package.manifest_path) - .parent() - .expect("could not find parent directory of package manifest") - .canonicalize() - .expect("package directory cannot be canonicalized"); - (package_manifest_path, i) + let packages = if std::env::args().any(|a| a == "--all" ) { + metadata.packages + } else { + let package_index = { + if let Some(manifest_path) = manifest_path { + metadata.packages.iter().position(|package| { + let package_manifest_path = Path::new(&package.manifest_path).canonicalize().expect( + "package manifest path could not be canonicalized", + ); + package_manifest_path == manifest_path }) - .collect(); - - let current_dir = std::env::current_dir() - .expect("could not read current directory") - .canonicalize() - .expect("current directory cannot be canonicalized"); - - let mut current_path: &Path = ¤t_dir; - - // This gets the most-recent parent (the one that takes the fewest `cd ..`s to - // reach). - loop { - if let Some(&package_index) = package_manifest_paths.get(current_path) { - break Some(package_index); - } else { - // We'll never reach the filesystem root, because to get to this point in the - // code - // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to - // unwrap the current path's parent. - current_path = current_path.parent().unwrap_or_else(|| { - panic!("could not find parent of path {}", current_path.display()) - }); + } else { + let package_manifest_paths: HashMap<_, _> = metadata + .packages + .iter() + .enumerate() + .map(|(i, package)| { + let package_manifest_path = Path::new(&package.manifest_path) + .parent() + .expect("could not find parent directory of package manifest") + .canonicalize() + .expect("package directory cannot be canonicalized"); + (package_manifest_path, i) + }) + .collect(); + + let current_dir = std::env::current_dir() + .expect("could not read current directory") + .canonicalize() + .expect("current directory cannot be canonicalized"); + + let mut current_path: &Path = ¤t_dir; + + // This gets the most-recent parent (the one that takes the fewest `cd ..`s to + // reach). + loop { + if let Some(&package_index) = package_manifest_paths.get(current_path) { + break Some(package_index); + } else { + // We'll never reach the filesystem root, because to get to this point in the + // code + // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to + // unwrap the current path's parent. + current_path = current_path.parent().unwrap_or_else(|| { + panic!("could not find parent of path {}", current_path.display()) + }); + } } } - } - }.expect("could not find matching package"); - - let package = metadata.packages.remove(package_index); - for target in package.targets { - let args = std::env::args().skip(2); - if let Some(first) = target.kind.get(0) { - if target.kind.len() > 1 || first.ends_with("lib") { - if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { - std::process::exit(code); - } - } else if ["bin", "example", "test", "bench"].contains(&&**first) { - if let Err(code) = process( - vec![format!("--{}", first), target.name] - .into_iter() - .chain(args), - ) - { - std::process::exit(code); + }.expect("could not find matching package"); + + vec![metadata.packages.remove(package_index)] + }; + + for package in packages { + let manifest_path = package.manifest_path; + + for target in package.targets { + let args = std::env::args().skip(2).filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); + + let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); + if let Some(first) = target.kind.get(0) { + if target.kind.len() > 1 || first.ends_with("lib") { + if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { + std::process::exit(code); + } + } else if ["bin", "example", "test", "bench"].contains(&&**first) { + if let Err(code) = process( + vec![format!("--{}", first), target.name] + .into_iter() + .chain(args), + ) + { + std::process::exit(code); + } } + } else { + panic!("badly formatted cargo metadata: target::kind is an empty array"); } - } else { - panic!("badly formatted cargo metadata: target::kind is an empty array"); } } } else { -- cgit 1.4.1-3-g733a5 From 5d72cc9b08db57030d29ed46783793c05cbee7dd Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 18 Aug 2017 18:11:15 +0100 Subject: Run Rustfmt-nightly --- src/main.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2f4d782f78e..d559ad14c33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] - #![allow(unknown_lints, missing_docs_in_private_items)] extern crate clippy_lints; @@ -12,9 +11,9 @@ extern crate rustc_errors; extern crate rustc_plugin; extern crate syntax; -use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; -use rustc::session::{config, Session, CompileIncomplete}; -use rustc::session::config::{Input, ErrorOutputType}; +use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; +use rustc::session::{config, CompileIncomplete, Session}; +use rustc::session::config::{ErrorOutputType, Input}; use std::collections::HashMap; use std::path::PathBuf; use std::process::{self, Command}; @@ -200,9 +199,9 @@ pub fn main() { if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { // this arm is executed on the initial call to `cargo clippy` - let manifest_path_arg = std::env::args().skip(2).find(|val| { - val.starts_with("--manifest-path=") - }); + let manifest_path_arg = std::env::args() + .skip(2) + .find(|val| val.starts_with("--manifest-path=")); let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { @@ -218,15 +217,15 @@ pub fn main() { .expect("manifest path could not be canonicalized") }); - let packages = if std::env::args().any(|a| a == "--all" ) { + let packages = if std::env::args().any(|a| a == "--all") { metadata.packages } else { let package_index = { if let Some(manifest_path) = manifest_path { metadata.packages.iter().position(|package| { - let package_manifest_path = Path::new(&package.manifest_path).canonicalize().expect( - "package manifest path could not be canonicalized", - ); + let package_manifest_path = Path::new(&package.manifest_path) + .canonicalize() + .expect("package manifest path could not be canonicalized"); package_manifest_path == manifest_path }) } else { @@ -261,9 +260,9 @@ pub fn main() { // code // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to // unwrap the current path's parent. - current_path = current_path.parent().unwrap_or_else(|| { - panic!("could not find parent of path {}", current_path.display()) - }); + current_path = current_path + .parent() + .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display())); } } } @@ -276,7 +275,9 @@ pub fn main() { let manifest_path = package.manifest_path; for target in package.targets { - let args = std::env::args().skip(2).filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); + let args = std::env::args() + .skip(2) + .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); if let Some(first) = target.kind.get(0) { @@ -289,8 +290,7 @@ pub fn main() { vec![format!("--{}", first), target.name] .into_iter() .chain(args), - ) - { + ) { std::process::exit(code); } } -- cgit 1.4.1-3-g733a5 From f7839a818df28a3400a5d4f7334389f30f80bece Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 18 Aug 2017 18:31:51 +0100 Subject: Add travis testing of `--all` --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index be682688177..1b67f3887d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: - cargo test --features debugging - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - - PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy + - PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy - cd clippy_lints && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. -- cgit 1.4.1-3-g733a5 From 6c665893d521b88f04bdfa010161760f489a225d Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Sun, 20 Aug 2017 05:10:13 +0100 Subject: Add help text for `--all` --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index d559ad14c33..41909477bbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,7 +151,7 @@ Common options: -h, --help Print this message --features Features to compile for the package -V, --version Print version info and exit - --all @@@ something sensible here (copy from cargo-edit?) + --all Run over all packages in the current workspace Other options are the same as `cargo rustc`. -- cgit 1.4.1-3-g733a5 From 2493176f0edae822b037bc9538503f9cbbcd40b3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 09:44:53 +0200 Subject: Version bump --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- README.md | 3 ++- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 1 + 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21fa487ef8c..bb1c606d736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.153 +* Update to *rustc 1.21.0-nightly (8c303ed87 2017-08-20)* +* New lint: [`use_self`] + ## 0.0.152 * Update to *rustc 1.21.0-nightly (df511d554 2017-08-14)* @@ -595,6 +599,7 @@ All notable changes to this project will be documented in this file. [`unused_label`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label [`unused_lifetimes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes [`use_debug`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug +[`use_self`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#use_self [`used_underscore_binding`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding [`useless_attribute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute [`useless_format`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format diff --git a/Cargo.toml b/Cargo.toml index 237ab4f8394..6db6ea54fb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.152" +version = "0.0.153" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.152", path = "clippy_lints" } +clippy_lints = { version = "0.0.153", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/README.md b/README.md index b5cc1f09446..bad6d01b6c8 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 204 lints included in this crate: +There are 205 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -372,6 +372,7 @@ name [unused_label](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label) | warn | unused labels [unused_lifetimes](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions [use_debug](https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug) | allow | use of `Debug`-based formatting +[use_self](https://github.com/rust-lang-nursery/rust-clippy/wiki#use_self) | allow | Unnecessary structure name repetition whereas `Self` is applicable [used_underscore_binding](https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore [useless_attribute](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute) | warn | use of lint attributes on `extern crate` items [useless_format](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format) | warn | useless use of `format!` diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e545b13a678..94094bf49c9 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.152" +version = "0.0.153" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a8f1b1664b0..dc1b147351a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -365,6 +365,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::INVALID_UPCAST_COMPARISONS, unicode::NON_ASCII_LITERAL, unicode::UNICODE_NOT_NFC, + use_self::USE_SELF, ]); reg.register_lint_group("clippy_internal", vec![ -- cgit 1.4.1-3-g733a5 From f1847f7a986716b0146e4f319f6f5fec8943500f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 10:26:46 +0200 Subject: Test changes --- tests/ui/methods.stderr | 132 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 1f9bc9a84c7..99d4ee9d663 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,3 +1,41 @@ +error: unnecessary structure name repetition + --> $DIR/methods.rs:18:25 + | +18 | fn add(self, other: T) -> T { self } + | ^ help: use the applicable keyword: `Self` + | + = note: `-D use-self` implied by `-D warnings` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:18:31 + | +18 | fn add(self, other: T) -> T { self } + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:21:26 + | +21 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:21:33 + | +21 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:22:21 + | +22 | fn div(self) -> T { self } // no error, different #arguments + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:23:25 + | +23 | fn rem(self, other: T) { } // no error, wrong return type + | ^ help: use the applicable keyword: `Self` + error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name --> $DIR/methods.rs:18:5 | @@ -40,6 +78,54 @@ error: methods called `new` usually return `Self` | = note: `-D new-ret-no-self` implied by `-D warnings` +error: unnecessary structure name repetition + --> $DIR/methods.rs:40:35 + | +40 | pub fn new<'b>(s: &'b str) -> Lt<'b> { unimplemented!() } + | ^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:49:28 + | +49 | pub fn new(s: &str) -> Lt2 { unimplemented!() } + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:58:21 + | +58 | pub fn new() -> Lt3<'static> { unimplemented!() } + | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:61:10 + | +61 | #[derive(Clone,Copy)] + | ^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:74:24 + | +74 | fn new() -> Option> { None } + | ^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:78:19 + | +78 | type Output = T; + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:79:25 + | +79 | fn mul(self, other: T) -> T { self } // no error, obviously + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:79:31 + | +79 | fn mul(self, other: T) -> T { self } // no error, obviously + | ^ help: use the applicable keyword: `Self` + error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead --> $DIR/methods.rs:97:13 | @@ -104,6 +190,42 @@ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done mo 125 | | ); | |_________________^ +error: unnecessary structure name repetition + --> $DIR/methods.rs:131:16 + | +131 | #[derive(Copy, Clone)] + | ^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:145:16 + | +145 | #[derive(Copy, Clone)] + | ^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:151:24 + | +151 | fn filter(self) -> IteratorFalsePositives { + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:155:22 + | +155 | fn next(self) -> IteratorFalsePositives { + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:175:32 + | +175 | fn skip(self, _: usize) -> IteratorFalsePositives { + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:180:16 + | +180 | #[derive(Copy, Clone)] + | ^^^^^ help: use the applicable keyword: `Self` + error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. --> $DIR/methods.rs:194:13 | @@ -178,6 +300,12 @@ error: called `is_some()` after searching an `Iterator` with rposition. This is 236 | | ).is_some(); | |______________________________^ +error: unnecessary structure name repetition + --> $DIR/methods.rs:250:21 + | +250 | fn new() -> Foo { Foo } + | ^^^ help: use the applicable keyword: `Self` + error: use of `unwrap_or` followed by a function call --> $DIR/methods.rs:268:5 | @@ -432,6 +560,8 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly 413 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ +error: unnecessary structure name repetition + error: you should use the `starts_with` method --> $DIR/methods.rs:425:5 | @@ -626,5 +756,5 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: aborting due to 89 previous errors +error: aborting due to 111 previous errors -- cgit 1.4.1-3-g733a5 From 56068b1b671f6490c1be9ea3834784e89a0a4ba7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 12:57:33 +0200 Subject: Fix ICE #1969 --- clippy_lints/src/functions.rs | 8 ++++++-- src/main.rs | 2 +- tests/run-pass/ice-1969.rs | 13 +++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 tests/run-pass/ice-1969.rs diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 1bb8780ea4a..9d9bf38c397 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,6 +1,7 @@ use rustc::hir::intravisit; use rustc::hir; use rustc::lint::*; +use rustc::ty; use std::collections::HashSet; use syntax::ast; use syntax::abi::Abi; @@ -150,9 +151,11 @@ impl<'a, 'tcx> Functions { .collect::>(); if !raw_ptrs.is_empty() { + let tables = cx.tcx.body_tables(body.id()); let mut v = DerefVisitor { cx: cx, ptrs: raw_ptrs, + tables, }; hir::intravisit::walk_expr(&mut v, expr); @@ -172,13 +175,14 @@ fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { struct DerefVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, ptrs: HashSet, + tables: &'a ty::TypeckTables<'tcx>, } impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprCall(ref f, ref args) => { - let ty = self.cx.tables.expr_ty(f); + let ty = self.tables.expr_ty(f); if type_is_unsafe_function(self.cx, ty) { for arg in args { @@ -187,7 +191,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } }, hir::ExprMethodCall(_, _, ref args) => { - let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); + let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id(); let base_type = self.cx.tcx.type_of(def_id); if type_is_unsafe_function(self.cx, base_type) { diff --git a/src/main.rs b/src/main.rs index 8e92eb55ff0..8e8ed032c1f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ struct ClippyCompilerCalls { impl ClippyCompilerCalls { fn new(run_lints: bool) -> Self { - ClippyCompilerCalls { + Self { default: RustcDefaultCalls, run_lints: run_lints, } diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs new file mode 100644 index 00000000000..23a002a5cde --- /dev/null +++ b/tests/run-pass/ice-1969.rs @@ -0,0 +1,13 @@ +#![feature(plugin)] +#![plugin(clippy)] +#![allow(clippy)] + +fn main() { } + +pub trait Convert { + type Action: From<*const f64>; + + fn convert(val: *const f64) -> Self::Action { + val.into() + } +} -- cgit 1.4.1-3-g733a5 From 3eab44acb1a5f8a4a8964d3d5f0566c4672e4b05 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 12:58:06 +0200 Subject: Don't trigger `Self` suggestion inside derives --- clippy_lints/src/use_self.rs | 5 ++++- tests/ui/methods.stderr | 28 +--------------------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 2a94d8fe9cc..b1e46e17f13 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap}; -use utils::span_lint_and_then; +use utils::{span_lint_and_then, in_macro}; use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfType; @@ -48,6 +48,9 @@ impl LintPass for UseSelf { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if in_macro(item.span) { + return; + } if_let_chain!([ let ItemImpl(.., ref item_type, ref refs) = item.node, let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 99d4ee9d663..65975c5177c 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -96,12 +96,6 @@ error: unnecessary structure name repetition 58 | pub fn new() -> Lt3<'static> { unimplemented!() } | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` -error: unnecessary structure name repetition - --> $DIR/methods.rs:61:10 - | -61 | #[derive(Clone,Copy)] - | ^^^^^ help: use the applicable keyword: `Self` - error: unnecessary structure name repetition --> $DIR/methods.rs:74:24 | @@ -190,18 +184,6 @@ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done mo 125 | | ); | |_________________^ -error: unnecessary structure name repetition - --> $DIR/methods.rs:131:16 - | -131 | #[derive(Copy, Clone)] - | ^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:145:16 - | -145 | #[derive(Copy, Clone)] - | ^^^^^ help: use the applicable keyword: `Self` - error: unnecessary structure name repetition --> $DIR/methods.rs:151:24 | @@ -220,12 +202,6 @@ error: unnecessary structure name repetition 175 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` -error: unnecessary structure name repetition - --> $DIR/methods.rs:180:16 - | -180 | #[derive(Copy, Clone)] - | ^^^^^ help: use the applicable keyword: `Self` - error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. --> $DIR/methods.rs:194:13 | @@ -560,8 +536,6 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly 413 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: unnecessary structure name repetition - error: you should use the `starts_with` method --> $DIR/methods.rs:425:5 | @@ -756,5 +730,5 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: aborting due to 111 previous errors +error: aborting due to 106 previous errors -- cgit 1.4.1-3-g733a5 From 2430e06a60ca23960bb746af30742607ae41bdb0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 13:32:12 +0200 Subject: Run Dogfood for `use_self` --- CHANGELOG.md | 3 +++ clippy_lints/src/blacklisted_name.rs | 4 ++-- clippy_lints/src/consts.rs | 8 ++++---- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/doc.rs | 4 ++-- clippy_lints/src/enum_variants.rs | 4 ++-- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/literal_digit_grouping.rs | 14 +++++++------- clippy_lints/src/missing_doc.rs | 8 ++++---- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 4 ++-- clippy_lints/src/utils/sugg.rs | 10 ++++++---- 17 files changed, 44 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb1c606d736..6bf262bb72f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.154 +* Fix [`use_self`] triggering inside derives + ## 0.0.153 * Update to *rustc 1.21.0-nightly (8c303ed87 2017-08-20)* * New lint: [`use_self`] diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index e88e4108d3d..e46d8e4855f 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -26,8 +26,8 @@ pub struct BlackListedName { } impl BlackListedName { - pub fn new(blacklist: Vec) -> BlackListedName { - BlackListedName { blacklist: blacklist } + pub fn new(blacklist: Vec) -> Self { + Self { blacklist: blacklist } } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 2a6fa051d2f..0a76b95931d 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -23,7 +23,7 @@ pub enum FloatWidth { } impl From for FloatWidth { - fn from(ty: FloatTy) -> FloatWidth { + fn from(ty: FloatTy) -> Self { match ty { FloatTy::F32 => FloatWidth::F32, FloatTy::F64 => FloatWidth::F64, @@ -55,7 +55,7 @@ pub enum Constant { } impl PartialEq for Constant { - fn eq(&self, other: &Constant) -> bool { + fn eq(&self, other: &Self) -> bool { match (self, other) { (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, @@ -123,7 +123,7 @@ impl Hash for Constant { } impl PartialOrd for Constant { - fn partial_cmp(&self, other: &Constant) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { if l_sty == r_sty { @@ -297,7 +297,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }; let param_env = self.param_env.and((def_id, substs)); if let Some((def_id, substs)) = lookup_const_by_id(self.tcx, param_env) { - let mut cx = ConstEvalLateContext { + let mut cx = Self { tcx: self.tcx, tables: self.tcx.typeck_tables_of(def_id), needed_resolution: false, diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index c7593a195ff..9596e9812ad 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -31,7 +31,7 @@ pub struct CyclomaticComplexity { impl CyclomaticComplexity { pub fn new(limit: u64) -> Self { - CyclomaticComplexity { limit: LimitStack::new(limit) } + Self { limit: LimitStack::new(limit) } } } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 3ca71694bbd..c3eba53e035 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -37,7 +37,7 @@ pub struct Doc { impl Doc { pub fn new(valid_idents: Vec) -> Self { - Doc { valid_idents: valid_idents } + Self { valid_idents: valid_idents } } } @@ -62,7 +62,7 @@ struct Parser<'a> { } impl<'a> Parser<'a> { - fn new(parser: pulldown_cmark::Parser<'a>) -> Parser<'a> { + fn new(parser: pulldown_cmark::Parser<'a>) -> Self { Self { parser: parser } } } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 1227de69db2..eee4e2a7ee1 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -104,8 +104,8 @@ pub struct EnumVariantNames { } impl EnumVariantNames { - pub fn new(threshold: u64) -> EnumVariantNames { - EnumVariantNames { + pub fn new(threshold: u64) -> Self { + Self { modules: Vec::new(), threshold: threshold, } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 9d9bf38c397..70ff96d36d4 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -59,8 +59,8 @@ pub struct Functions { } impl Functions { - pub fn new(threshold: u64) -> Functions { - Functions { threshold: threshold } + pub fn new(threshold: u64) -> Self { + Self { threshold: threshold } } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 73a62c97bc8..917e0b77370 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -34,7 +34,7 @@ pub struct LargeEnumVariant { impl LargeEnumVariant { pub fn new(maximum_size_difference_allowed: u64) -> Self { - LargeEnumVariant { maximum_size_difference_allowed: maximum_size_difference_allowed } + Self { maximum_size_difference_allowed: maximum_size_difference_allowed } } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 507373fede5..47cc41c472c 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -254,8 +254,8 @@ struct RefVisitor<'a, 'tcx: 'a> { } impl<'v, 't> RefVisitor<'v, 't> { - fn new(cx: &'v LateContext<'v, 't>) -> RefVisitor<'v, 't> { - RefVisitor { + fn new(cx: &'v LateContext<'v, 't>) -> Self { + Self { cx: cx, lts: Vec::new(), abort: false, diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index 0da8ffd0a30..dbb1a7a9b86 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -95,7 +95,7 @@ struct DigitInfo<'a> { } impl<'a> DigitInfo<'a> { - pub fn new(lit: &str, float: bool) -> DigitInfo { + pub fn new(lit: &'a str, float: bool) -> Self { // Determine delimiter for radix prefix, if present, and radix. let radix = if lit.starts_with("0x") { Radix::Hexadecimal @@ -120,7 +120,7 @@ impl<'a> DigitInfo<'a> { if !float && (d == 'i' || d == 'u') || float && d == 'f' { let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; let (digits, suffix) = sans_prefix.split_at(suffix_start); - return DigitInfo { + return Self { digits: digits, radix: radix, prefix: prefix, @@ -132,7 +132,7 @@ impl<'a> DigitInfo<'a> { } // No suffix found - DigitInfo { + Self { digits: sans_prefix, radix: radix, prefix: prefix, @@ -257,7 +257,7 @@ impl LiteralDigitGrouping { char::to_digit(firstch, 10).is_some() ], { let digit_info = DigitInfo::new(&src, false); - let _ = LiteralDigitGrouping::do_lint(digit_info.digits).map_err(|warning_type| { + let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) }); }} @@ -278,14 +278,14 @@ impl LiteralDigitGrouping { // Lint integral and fractional parts separately, and then check consistency of digit // groups if both pass. - let _ = LiteralDigitGrouping::do_lint(parts[0]) + let _ = Self::do_lint(parts[0]) .map(|integral_group_size| { if parts.len() > 1 { // Lint the fractional part of literal just like integral part, but reversed. let fractional_part = &parts[1].chars().rev().collect::(); - let _ = LiteralDigitGrouping::do_lint(fractional_part) + let _ = Self::do_lint(fractional_part) .map(|fractional_group_size| { - let consistent = LiteralDigitGrouping::parts_consistent(integral_group_size, fractional_group_size, parts[0].len(), parts[1].len()); + let consistent = Self::parts_consistent(integral_group_size, fractional_group_size, parts[0].len(), parts[1].len()); if !consistent { WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), cx, &lit.span); } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index f0c417f4646..21e19a3af84 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -56,14 +56,14 @@ pub struct MissingDoc { } impl ::std::default::Default for MissingDoc { - fn default() -> MissingDoc { - MissingDoc::new() + fn default() -> Self { + Self::new() } } impl MissingDoc { - pub fn new() -> MissingDoc { - MissingDoc { doc_hidden_stack: vec![false] } + pub fn new() -> Self { + Self { doc_hidden_stack: vec![false] } } fn doc_hidden(&self) -> bool { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index e4efaf495a8..b7de586ed80 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -197,7 +197,7 @@ struct MovedVariablesCtxt<'a, 'tcx: 'a> { impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - MovedVariablesCtxt { + Self { cx: cx, moved_vars: HashSet::new(), spans_need_deref: HashMap::new(), diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9d6167cc041..ea3db0e4690 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -730,7 +730,7 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { - TypeComplexityPass { threshold: threshold } + Self { threshold: threshold } } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 7466ee9080b..a7fdc3d281b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { impl PrintVisitor { fn new(s: &'static str) -> Self { - PrintVisitor { + Self { ids: HashMap::new(), current: s.to_owned(), } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 658a07ca146..b4caad0845a 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -23,14 +23,14 @@ pub struct SpanlessEq<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessEq { + Self { cx: cx, ignore_fn: false, } } pub fn ignore_fn(self) -> Self { - SpanlessEq { + Self { cx: self.cx, ignore_fn: true, } @@ -283,7 +283,7 @@ pub struct SpanlessHash<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { - SpanlessHash { + Self { cx: cx, s: DefaultHasher::new(), } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 01788edfc7e..7f8603f0f27 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -670,8 +670,8 @@ impl Drop for LimitStack { } impl LimitStack { - pub fn new(limit: u64) -> LimitStack { - LimitStack { stack: vec![limit] } + pub fn new(limit: u64) -> Self { + Self { stack: vec![limit] } } pub fn limit(&self) -> u64 { *self.stack.last().expect( diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d46a6526395..6cfbe8c935e 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -1,5 +1,7 @@ //! Contains utility functions to generate suggestions. #![deny(missing_docs_in_private_items)] +// currently ignores lifetimes and generics +#![allow(use_self)] use rustc::hir; use rustc::lint::{EarlyContext, LateContext, LintContext}; @@ -41,7 +43,7 @@ impl<'a> Display for Sugg<'a> { #[allow(wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. - pub fn hir_opt(cx: &LateContext, expr: &hir::Expr) -> Option> { + pub fn hir_opt(cx: &LateContext, expr: &hir::Expr) -> Option { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); match expr.node { @@ -80,12 +82,12 @@ impl<'a> Sugg<'a> { /// Convenience function around `hir_opt` for suggestions with a default /// text. - pub fn hir(cx: &LateContext, expr: &hir::Expr, default: &'a str) -> Sugg<'a> { + pub fn hir(cx: &LateContext, expr: &hir::Expr, default: &'a str) -> Self { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } /// Prepare a suggestion from an expression. - pub fn ast(cx: &EarlyContext, expr: &ast::Expr, default: &'a str) -> Sugg<'a> { + pub fn ast(cx: &EarlyContext, expr: &ast::Expr, default: &'a str) -> Self { use syntax::ast::RangeLimits; let snippet = snippet(cx, expr.span, default); @@ -218,7 +220,7 @@ struct ParenHelper { impl ParenHelper { /// Build a `ParenHelper`. fn new(paren: bool, wrapped: T) -> Self { - ParenHelper { + Self { paren: paren, wrapped: wrapped, } -- cgit 1.4.1-3-g733a5 From 0063309a002b3436c2f924a6442739efd94aeb3e Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Thu, 29 Jun 2017 13:45:35 +0200 Subject: Now register needless borrowed ref. --- clippy_lints/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index dc1b147351a..68e63c33b63 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -267,6 +267,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_update::Pass); reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); + reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); reg.register_late_lint_pass(box no_effect::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box temporary_assignment::Pass); -- cgit 1.4.1-3-g733a5 From 246045415593496d64fc0af41db7650b3680c1dc Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Thu, 29 Jun 2017 13:45:54 +0200 Subject: Improve needless_borrowed_ref lint comments. --- clippy_lints/src/needless_borrowed_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 6f81c811414..0167b171297 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -48,11 +48,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { if_let_chain! {[ // Pat is a pattern whose node - // is a binding which "involves" a immutable reference... + // is a binding which "involves" an immutable reference... let PatKind::Binding(BindingAnnotation::Ref, ..) = pat.node, // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, - // This is an immutable reference. + // Only lint immutable refs, because `&mut ref T` may be useful. tam.mutbl == MutImmutable, ], { span_lint(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced") -- cgit 1.4.1-3-g733a5 From b1d93a595c4a9ea648fee189b13cbdea994f9826 Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Thu, 29 Jun 2017 13:46:07 +0200 Subject: Add needless_borrowed_ref example. --- clippy_tests/examples/needless_borrowed_ref.rs | 9 +++++++++ clippy_tests/examples/needless_borrowed_ref.stderr | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 clippy_tests/examples/needless_borrowed_ref.rs create mode 100644 clippy_tests/examples/needless_borrowed_ref.stderr diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs new file mode 100644 index 00000000000..105a1fa48d4 --- /dev/null +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[warn(needless_borrowed_reference)] +fn main() { + let mut v = Vec::::new(); + let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +} + diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr new file mode 100644 index 00000000000..658318a3c6a --- /dev/null +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -0,0 +1,8 @@ +warning: this pattern takes a reference on something that is being de-referenced + --> needless_borrowed_ref.rs:7:35 + | +7 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^ + | + = note: #[warn(needless_borrowed_reference)] on by default + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference -- cgit 1.4.1-3-g733a5 From d170e765de3d8f84dc2a6f918219c8efed01d862 Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Fri, 30 Jun 2017 16:07:29 +0200 Subject: Update needless_borrowed_ref lint example. --- clippy_tests/examples/needless_borrowed_ref.rs | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs index 105a1fa48d4..e463567ee6f 100644 --- a/clippy_tests/examples/needless_borrowed_ref.rs +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -2,8 +2,36 @@ #![plugin(clippy)] #[warn(needless_borrowed_reference)] +#[allow(unused_variables)] fn main() { let mut v = Vec::::new(); let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + // ^ should be linted + + let mut var = 5; + let thingy = Some(&mut var); + if let Some(&mut ref v) = thingy { + // ^ should *not* be linted + // here, var is borrowed as immutable. + // can't do that: + //*v = 10; + } +} + +#[allow(dead_code)] +enum Animal { + Cat(u64), + Dog(u64), +} + +#[allow(unused_variables)] +#[allow(dead_code)] +fn foo(a: &Animal, b: &Animal) { + match (a, b) { + (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + // ^ and ^ should *not* be linted + (&Animal::Dog(ref a), &Animal::Dog(_)) => () + // ^ should *not* be linted + } } -- cgit 1.4.1-3-g733a5 From 60ca61ee660c156e0ff3fe0ee12a8156b5a425fd Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Sat, 1 Jul 2017 12:01:39 +0200 Subject: Improve needless_borrowed_ref and add suggestion to it. --- clippy_lints/src/needless_borrowed_ref.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 0167b171297..db2c2cc95f8 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,9 +3,14 @@ //! This lint is **warn** by default use rustc::lint::*; +<<<<<<< HEAD use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; +======= +use rustc::hir::{MutImmutable, Pat, PatKind}; +>>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. use rustc::ty; -use utils::{span_lint, in_macro}; +use utils::{span_lint_and_then, in_macro, snippet}; +use syntax_pos::{Span, BytePos}; /// **What it does:** Checks for useless borrowed references. /// @@ -53,9 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, // Only lint immutable refs, because `&mut ref T` may be useful. - tam.mutbl == MutImmutable, + let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, + + // Check sub_pat got a 'ref' keyword. + let ty::TyRef(_, _) = cx.tables.pat_ty(sub_pat).sty, ], { - span_lint(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced") + let part_to_keep = Span{ lo: pat.span.lo + BytePos(5), hi: pat.span.hi, ctxt: pat.span.ctxt }; + span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, + "this pattern takes a reference on something that is being de-referenced", + |db| { + let hint = snippet(cx, part_to_keep, "..").into_owned(); + db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); + }); }} } } -- cgit 1.4.1-3-g733a5 From fe57fdd15e6046720463491359d32c5833ffad9c Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Sat, 1 Jul 2017 12:02:00 +0200 Subject: Improve needless_borrowed_ref and update its stderr. --- clippy_tests/examples/needless_borrowed_ref.rs | 21 ++++++++--- clippy_tests/examples/needless_borrowed_ref.stderr | 43 +++++++++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs index e463567ee6f..4e9986561bc 100644 --- a/clippy_tests/examples/needless_borrowed_ref.rs +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -8,13 +8,24 @@ fn main() { let _ = v.iter_mut().filter(|&ref a| a.is_empty()); // ^ should be linted - let mut var = 5; - let thingy = Some(&mut var); - if let Some(&mut ref v) = thingy { + let var = 3; + let thingy = Some(&var); + if let Some(&ref v) = thingy { + // ^ should be linted + } + + let mut var2 = 5; + let thingy2 = Some(&mut var2); + if let Some(&mut ref mut v) = thingy2 { + // ^ should *not* be linted + // v is borrowed as mutable. + *v = 10; + } + if let Some(&mut ref v) = thingy2 { // ^ should *not* be linted - // here, var is borrowed as immutable. + // here, v is borrowed as immutable. // can't do that: - //*v = 10; + //*v = 15; } } diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr index 658318a3c6a..a9befd5767c 100644 --- a/clippy_tests/examples/needless_borrowed_ref.stderr +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -1,8 +1,41 @@ -warning: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:7:35 +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:8:34 | -7 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - | ^^^^^ +8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep `a` | - = note: #[warn(needless_borrowed_reference)] on by default + = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:13:17 + | +13 | if let Some(&ref v) = thingy { + | ^^^^^^ help: try removing the `&ref` part and just keep `v` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:42:27 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep `k` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:42:38 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep `k` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: aborting due to previous error(s) + +error: Could not compile `clippy_tests`. + +To learn more, run the command again with --verbose. -- cgit 1.4.1-3-g733a5 From c00393163cf1aae888b654a46b5f400e2ded4d1f Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Sat, 1 Jul 2017 16:56:19 +0200 Subject: Improve needless_borrowed_ref lint: remove the hand rolled span part. --- clippy_lints/src/needless_borrowed_ref.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index db2c2cc95f8..6e17d23fb0b 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -7,10 +7,13 @@ use rustc::lint::*; use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; ======= use rustc::hir::{MutImmutable, Pat, PatKind}; +<<<<<<< HEAD >>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. use rustc::ty; +======= +>>>>>>> 4ae45c87... Improve needless_borrowed_ref lint: remove the hand rolled span part. use utils::{span_lint_and_then, in_macro, snippet}; -use syntax_pos::{Span, BytePos}; +use rustc::hir::BindingMode::BindByRef; /// **What it does:** Checks for useless borrowed references. /// @@ -60,14 +63,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { // Only lint immutable refs, because `&mut ref T` may be useful. let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, - // Check sub_pat got a 'ref' keyword. - let ty::TyRef(_, _) = cx.tables.pat_ty(sub_pat).sty, + // Check sub_pat got a `ref` keyword (excluding `ref mut`). + let PatKind::Binding(BindByRef(MutImmutable), _, spanned_name, ..) = sub_pat.node, ], { - let part_to_keep = Span{ lo: pat.span.lo + BytePos(5), hi: pat.span.hi, ctxt: pat.span.ctxt }; span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced", |db| { - let hint = snippet(cx, part_to_keep, "..").into_owned(); + let hint = snippet(cx, spanned_name.span, "..").into_owned(); db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); }); }} -- cgit 1.4.1-3-g733a5 From ee2f54723ae8122b7f7e5cfca48f3f85f7d656ca Mon Sep 17 00:00:00 2001 From: Benoît CORTIER Date: Sat, 1 Jul 2017 18:51:20 +0200 Subject: Finalize needless_borrowed_ref lint doc. Make sure the needless_borrowed_ref.stderr in examples is up to date too. --- clippy_lints/src/needless_borrowed_ref.rs | 33 ++++++++++++++-------- clippy_tests/examples/needless_borrowed_ref.stderr | 11 +++----- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 6e17d23fb0b..1451b19aeca 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,25 +3,33 @@ //! This lint is **warn** by default use rustc::lint::*; -<<<<<<< HEAD -use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; -======= -use rustc::hir::{MutImmutable, Pat, PatKind}; -<<<<<<< HEAD ->>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. +use rustc::hir::{MutImmutable, Pat, PatKind, BindByRef}; use rustc::ty; -======= ->>>>>>> 4ae45c87... Improve needless_borrowed_ref lint: remove the hand rolled span part. use utils::{span_lint_and_then, in_macro, snippet}; -use rustc::hir::BindingMode::BindByRef; /// **What it does:** Checks for useless borrowed references. /// -/// **Why is this bad?** It is completely useless and make the code look more -/// complex than it +/// **Why is this bad?** It is mostly useless and make the code look more complex than it /// actually is. /// -/// **Known problems:** None. +/// **Known problems:** It seems that the `&ref` pattern is sometimes useful. +/// For instance in the following snippet: +/// ```rust +/// enum Animal { +/// Cat(u64), +/// Dog(u64), +/// } +/// +/// fn foo(a: &Animal, b: &Animal) { +/// match (a, b) { +/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error +/// (&Animal::Dog(ref c), &Animal::Dog(_)) => () +/// } +/// } +/// ``` +/// There is a lifetime mismatch error for `k` (indeed a and b have distinct lifetime). +/// This can be fixed by using the `&ref` pattern. +/// However, the code can also be fixed by much cleaner ways /// /// **Example:** /// ```rust @@ -75,3 +83,4 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { }} } } + diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr index a9befd5767c..2b506af88f5 100644 --- a/clippy_tests/examples/needless_borrowed_ref.stderr +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -1,5 +1,5 @@ error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:8:34 + --> needless_borrowed_ref.rs:8:34 | 8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep `a` @@ -8,30 +8,27 @@ error: this pattern takes a reference on something that is being de-referenced = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:13:17 + --> needless_borrowed_ref.rs:13:17 | 13 | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep `v` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:42:27 + --> needless_borrowed_ref.rs:42:27 | 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep `k` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:42:38 + --> needless_borrowed_ref.rs:42:38 | 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep `k` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: aborting due to previous error(s) -- cgit 1.4.1-3-g733a5 From c3ef220bba7521427016f7422994cb8dfa24e1f2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 14:22:41 +0200 Subject: Rebase and update ui test --- clippy_lints/src/needless_borrowed_ref.rs | 10 ++-------- tests/ui/needless_borrow.stderr | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 1451b19aeca..3f7ccca23b4 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,8 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{MutImmutable, Pat, PatKind, BindByRef}; -use rustc::ty; +use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; use utils::{span_lint_and_then, in_macro, snippet}; /// **What it does:** Checks for useless borrowed references. @@ -63,16 +62,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { } if_let_chain! {[ - // Pat is a pattern whose node - // is a binding which "involves" an immutable reference... - let PatKind::Binding(BindingAnnotation::Ref, ..) = pat.node, - // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). - let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, // Only lint immutable refs, because `&mut ref T` may be useful. let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, // Check sub_pat got a `ref` keyword (excluding `ref mut`). - let PatKind::Binding(BindByRef(MutImmutable), _, spanned_name, ..) = sub_pat.node, + let PatKind::Binding(BindingAnnotation::Ref, _, spanned_name, ..) = sub_pat.node, ], { span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced", diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index cc5b1b6c33c..d90c396645e 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -18,11 +18,25 @@ error: this expression borrows a reference that is immediately dereferenced by t 27 | 46 => &&a, | ^^^ +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrow.rs:49:34 + | +49 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrow.rs:50:30 + | +50 | let _ = v.iter().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:50:31 | 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 2362177aaf99767bbe92b324e05374cbdfab24da Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Mon, 21 Aug 2017 23:23:54 +0200 Subject: fix #768 by checking for message macro expansion --- clippy_lints/src/panic.rs | 3 ++- tests/ui/panic.rs | 8 ++++++++ tests/ui/panic.stderr | 10 +--------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index e9e529cfdb4..70ee7de7b4d 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -45,7 +45,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { is_direct_expn_of(expr.span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, let Some(par) = string.as_str().find('{'), - string.as_str()[par..].contains('}') + string.as_str()[par..].contains('}'), + params[0].span.source_callee().is_none() ], { span_lint(cx, PANIC_PARAMS, params[0].span, "you probably are missing some parameter in your format string"); diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs index d1a099c1e66..03d3c3dc2d9 100644 --- a/tests/ui/panic.rs +++ b/tests/ui/panic.rs @@ -34,10 +34,18 @@ fn ok_bracket() { } } +const ONE : u32= 1; + +fn ok_nomsg() { + assert!({ 1 == ONE }); + assert!(if 1 == ONE { ONE == 1 } else { false }); +} + fn main() { missing(); ok_single(); ok_multiple(); ok_bracket(); ok_inner(); + ok_nomsg(); } diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index a7284124b29..25113ed80b6 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -18,13 +18,5 @@ error: you probably are missing some parameter in your format string 12 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: you probably are missing some parameter in your format string - --> $DIR/panic.rs:22:5 - | -22 | assert!("foo bar".contains(&format!("foo {}", "bar"))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From ddc733a429969c84ff0066d84a8932767dc9f672 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Tue, 22 Aug 2017 02:15:45 +0100 Subject: Remove surplus clippy invocation in travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1b67f3887d3..2664a01ea47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,6 @@ script: - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy - - cd clippy_lints && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. - cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. -- cgit 1.4.1-3-g733a5 From 6b0a2846b7342ef8a5c75a4de394338ad5f6a466 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Tue, 22 Aug 2017 09:59:58 +0100 Subject: Changelog entry for `cargo clippy --all` Should have added this as part of #1975 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf262bb72f..e9cc471a156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## 0.0.154 * Fix [`use_self`] triggering inside derives +* Add support for linting an entire workspace with `cargo clippy --all` ## 0.0.153 * Update to *rustc 1.21.0-nightly (8c303ed87 2017-08-20)* -- cgit 1.4.1-3-g733a5 From 3f575d874b921d5cc24a6f1f13d36fba484ab40c Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Tue, 22 Aug 2017 00:18:37 +0200 Subject: lint #1674: lifetimed types exclusion --- clippy_lints/src/use_self.rs | 9 +++++---- tests/ui/use_self.rs | 23 +++++++++++++++++++++++ tests/ui/use_self.stderr | 24 ++++++++++++------------ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b1e46e17f13..3e628c99ff9 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -54,6 +54,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if_let_chain!([ let ItemImpl(.., ref item_type, ref refs) = item.node, let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, + let PathParameters::AngleBracketedParameters(ref angleBracketedParameterData) + = item_path.segments.last().unwrap().parameters, + angleBracketedParameterData.lifetimes.len() == 0, ], { let visitor = &mut UseSelfVisitor { item_path: item_path, @@ -76,12 +79,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { if self.item_path.def == path.def && path.segments .last() - .expect("segments should be composed of at least 1 element") + .unwrap() .name != SelfType.name() { span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { - db.span_suggestion(path.span, - "use the applicable keyword", - "Self".to_owned()); + db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); }); } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 40cef1a9362..14e31aae8ee 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -2,6 +2,7 @@ #![plugin(clippy)] #![warn(use_self)] #![allow(dead_code)] +#![allow(should_implement_trait)] fn main() {} @@ -43,3 +44,25 @@ mod better { } } } + +//todo the lint does not handle lifetimed struct +//the following module should trigger the lint on the third method only +mod lifetimes { + struct Foo<'a>{foo_str: &'a str} + + impl<'a> Foo<'a> { + // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> Foo<'b>` + fn foo(s: &str) -> Foo { + Foo { foo_str: s } + } + // cannot replace with `Self`, because that's `Foo<'a>` + fn bar() -> Foo<'static> { + Foo { foo_str: "foo"} + } + + // `Self` is applicable here + fn clone(&self) -> Foo<'a> { + Foo {foo_str: self.foo_str} + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 0cbd574b506..bfd334335d8 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,39 +1,39 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:13:21 + --> $DIR/use_self.rs:14:21 | -13 | fn new() -> Foo { +14 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:13 + --> $DIR/use_self.rs:15:13 | -14 | Foo {} +15 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:16:22 + --> $DIR/use_self.rs:17:22 | -16 | fn test() -> Foo { +17 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:17:13 + --> $DIR/use_self.rs:18:13 | -17 | Foo::new() +18 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:22:25 + --> $DIR/use_self.rs:23:25 | -22 | fn default() -> Foo { +23 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:13 + --> $DIR/use_self.rs:24:13 | -23 | Foo::new() +24 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 572b3388ac91bdf71d180a0fd2426abe170d12c1 Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Tue, 22 Aug 2017 19:22:47 +0200 Subject: lint #1674: lifetimed types exclusion add expect() message and update test results --- clippy_lints/src/use_self.rs | 10 ++++++---- tests/ui/methods.stderr | 20 +------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 3e628c99ff9..b8c970d376e 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -46,6 +46,8 @@ impl LintPass for UseSelf { } } +const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if in_macro(item.span) { @@ -54,9 +56,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if_let_chain!([ let ItemImpl(.., ref item_type, ref refs) = item.node, let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, - let PathParameters::AngleBracketedParameters(ref angleBracketedParameterData) - = item_path.segments.last().unwrap().parameters, - angleBracketedParameterData.lifetimes.len() == 0, + let PathParameters::AngleBracketedParameters(ref param_data) + = item_path.segments.last().expect(SEGMENTS_MSG).parameters, + param_data.lifetimes.len() == 0, ], { let visitor = &mut UseSelfVisitor { item_path: item_path, @@ -79,7 +81,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { if self.item_path.def == path.def && path.segments .last() - .unwrap() + .expect(SEGMENTS_MSG) .name != SelfType.name() { span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 65975c5177c..8570dccd0fe 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -78,24 +78,6 @@ error: methods called `new` usually return `Self` | = note: `-D new-ret-no-self` implied by `-D warnings` -error: unnecessary structure name repetition - --> $DIR/methods.rs:40:35 - | -40 | pub fn new<'b>(s: &'b str) -> Lt<'b> { unimplemented!() } - | ^^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:49:28 - | -49 | pub fn new(s: &str) -> Lt2 { unimplemented!() } - | ^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:58:21 - | -58 | pub fn new() -> Lt3<'static> { unimplemented!() } - | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` - error: unnecessary structure name repetition --> $DIR/methods.rs:74:24 | @@ -730,5 +712,5 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: aborting due to 106 previous errors +error: aborting due to 103 previous errors -- cgit 1.4.1-3-g733a5 From 70e34077d590136fc1096ea03c887393a1246c93 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 22 Aug 2017 23:45:08 +0200 Subject: new lint: naive_bytecount --- CHANGELOG.md | 3 ++ README.md | 3 +- clippy_lints/src/bytecount.rs | 80 +++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/bytecount.rs | 14 ++++++++ tests/ui/bytecount.stderr | 16 +++++++++ 7 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/bytecount.rs create mode 100644 tests/ui/bytecount.rs create mode 100644 tests/ui/bytecount.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index e9cc471a156..7b72a6c1be7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. +* New lint: [`naive_bytecount`] + ## 0.0.154 * Fix [`use_self`] triggering inside derives * Add support for linting an entire workspace with `cargo clippy --all` @@ -516,6 +518,7 @@ All notable changes to this project will be documented in this file. [`mut_mut`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut [`mutex_atomic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic [`mutex_integer`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer +[`naive_bytecount`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#naive_bytecount [`needless_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool [`needless_borrow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow [`needless_borrowed_reference`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference diff --git a/README.md b/README.md index bad6d01b6c8..bc043ec62d3 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 205 lints included in this crate: +There are 206 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -290,6 +290,7 @@ name [mut_mut](https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` [mutex_atomic](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic) | warn | using a mutex where an atomic value could be used instead [mutex_integer](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer) | allow | using a mutex for an integer type +[naive_bytecount](https://github.com/rust-lang-nursery/rust-clippy/wiki#naive_bytecount) | warn | use of naive `.filter(|&x| x == y).count()` to count byte values [needless_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` [needless_borrow](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced [needless_borrowed_reference](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference) | warn | taking a needless borrowed reference diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs new file mode 100644 index 00000000000..99987f84ba7 --- /dev/null +++ b/clippy_lints/src/bytecount.rs @@ -0,0 +1,80 @@ +use consts::{constant, Constant}; +use rustc_const_math::ConstInt; +use rustc::hir::*; +use rustc::lint::*; +use utils::{match_type, paths, snippet, span_lint_and_sugg, walk_ptrs_ty}; + +/// **What it does:** Checks for naive byte counts +/// +/// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount) +/// crate has methods to count your bytes faster, especially for large slices. +/// +/// **Known problems:** If you have predominantly small slices, the +/// `bytecount::count(..)` method may actually be slower. However, if you can +/// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be +/// faster in those cases. +/// +/// **Example:** +/// +/// ```rust +/// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead +/// ``` +declare_lint! { + pub NAIVE_BYTECOUNT, + Warn, + "use of naive `.filter(|&x| x == y).count()` to count byte values" +} + +#[derive(Copy, Clone)] +pub struct ByteCount; + +impl LintPass for ByteCount { + fn get_lints(&self) -> LintArray { + lint_array!(NAIVE_BYTECOUNT) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + if_let_chain!([ + let ExprMethodCall(ref count, _, ref count_args) = expr.node, + count.name == "count", + count_args.len() == 1, + let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node, + filter.name == "filter", + filter_args.len() == 2, + let ExprClosure(_, _, body_id, _) = filter_args[1].node, + ], { + let body = cx.tcx.hir.body(body_id); + if_let_chain!([ + let ExprBinary(ref op, ref l, ref r) = body.value.node, + op.node == BiEq, + match_type(cx, + walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), + &paths::SLICE_ITER), + let Some((Constant::Int(ConstInt::U8(needle)), _)) = + constant(cx, l).or_else(|| constant(cx, r)) + ], { + let haystack = if let ExprMethodCall(ref path, _, ref args) = + filter_args[0].node { + let p = path.name; + if (p == "iter" || p == "iter_mut") && args.len() == 1 { + &args[0] + } else { + &filter_args[0] + } + } else { + &filter_args[0] + }; + span_lint_and_sugg(cx, + NAIVE_BYTECOUNT, + expr.span, + "You appear to be counting bytes the naive way", + "Consider using the bytecount crate", + format!("bytecount::count({}, {})", + snippet(cx, haystack.span, ".."), + needle)); + }); + }); + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index dc1b147351a..c4c949c792e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -74,6 +74,7 @@ pub mod bit_mask; pub mod blacklisted_name; pub mod block_in_if_condition; pub mod booleans; +pub mod bytecount; pub mod collapsible_if; pub mod copies; pub mod cyclomatic_complexity; @@ -321,6 +322,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); reg.register_late_lint_pass(box use_self::UseSelf); + reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -388,6 +390,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, booleans::LOGIC_BUG, + bytecount::NAIVE_BYTECOUNT, collapsible_if::COLLAPSIBLE_IF, copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 675d708781c..060cf4f978e 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -69,6 +69,7 @@ pub const RESULT_ERR: [&'static str; 4] = ["core", "result", "Result", "Err"]; pub const RESULT_OK: [&'static str; 4] = ["core", "result", "Result", "Ok"]; pub const SERDE_DE_VISITOR: [&'static str; 3] = ["serde", "de", "Visitor"]; pub const SLICE_INTO_VEC: [&'static str; 4] = ["alloc", "slice", "", "into_vec"]; +pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"]; pub const STRING: [&'static str; 3] = ["alloc", "string", "String"]; pub const TO_OWNED: [&'static str; 3] = ["alloc", "borrow", "ToOwned"]; pub const TO_STRING: [&'static str; 3] = ["alloc", "string", "ToString"]; diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs new file mode 100644 index 00000000000..880a86eba60 --- /dev/null +++ b/tests/ui/bytecount.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn main() { + let x = vec![0_u8; 16]; + + let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count + + let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count + + let _ = x.iter().filter(|a| **a > 0).count(); // not an equality count, OK. + + let _ = x.iter().map(|a| a + 1).filter(|&a| a < 15).count(); // not a slice +} diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr new file mode 100644 index 00000000000..818fa7eab1a --- /dev/null +++ b/tests/ui/bytecount.stderr @@ -0,0 +1,16 @@ +error: You appear to be counting bytes the naive way + --> $DIR/bytecount.rs:7:13 + | +7 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` + | + = note: `-D naive-bytecount` implied by `-D warnings` + +error: You appear to be counting bytes the naive way + --> $DIR/bytecount.rs:9:13 + | +9 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 45ff467c31c2cae7d656ff4534c5ddfc614e10db Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 14 Aug 2017 23:04:56 +0300 Subject: Fix borrowed_box lint for Box --- clippy_lints/src/types.rs | 13 ++++++++++- clippy_lints/src/utils/paths.rs | 1 + tests/ui/borrow_box.rs | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ed0027af533..b537ad5e717 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -10,7 +10,7 @@ use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::attr::IntType; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, opt_def_id, last_path_segment, type_size}; + span_lint_and_sugg, opt_def_id, last_path_segment, type_size, match_path_old}; use utils::paths; /// Handles all the linting of funky types @@ -212,6 +212,17 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let PathParameters::AngleBracketedParameters(ref ab_data) = bx.parameters, let [ref inner] = *ab_data.types ], { + if_let_chain! {[ + let TyTraitObject(ref traits, _) = inner.node, + traits.len() >= 1, + // Only Send/Sync can be used as additional traits, so it is enough to + // check only the first trait. + match_path_old(&traits[0].trait_ref.path, &paths::ANY_TRAIT) + ], { + // Ignore `Box` types, see #1884 for details. + return; + }} + let ltopt = if lt.is_elided() { "".to_owned() } else { diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 675d708781c..d5d252009fc 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,6 +1,7 @@ //! This module contains paths to types and functions Clippy needs to know //! about. +pub const ANY_TRAIT: [&'static str; 3] = ["std", "any", "Any"]; pub const ASMUT_TRAIT: [&'static str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&'static str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&'static str; 3] = ["std", "panicking", "begin_panic"]; diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index ef569ab037f..b5543da6e35 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -28,7 +28,57 @@ impl<'a> Test4 for Test3<'a> { } } +use std::any::Any; + +pub fn test5(foo: &mut Box) { + println!("{:?}", foo) +} + +pub fn test6() { + let foo: &Box; +} + +struct Test7<'a> { + foo: &'a Box +} + +trait Test8 { + fn test8(a: &Box); +} + +impl<'a> Test8 for Test7<'a> { + fn test8(a: &Box) { + unimplemented!(); + } +} + +pub fn test9(foo: &mut Box) { + let _ = foo; +} + +pub fn test10() { + let foo: &Box; +} + +struct Test11<'a> { + foo: &'a Box +} + +trait Test12 { + fn test4(a: &Box); +} + +impl<'a> Test12 for Test11<'a> { + fn test4(a: &Box) { + unimplemented!(); + } +} + fn main(){ test1(&mut Box::new(false)); test2(); + test5(&mut (Box::new(false) as Box)); + test6(); + test9(&mut (Box::new(false) as Box)); + test10(); } -- cgit 1.4.1-3-g733a5 From 81538f6ff310e0d8e7ec62542b5eb29f08043081 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 23 Aug 2017 17:13:51 +0300 Subject: Fix 'cyclomatic complexity' warning --- clippy_lints/src/types.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b537ad5e717..1c56be53296 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -212,16 +212,10 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let PathParameters::AngleBracketedParameters(ref ab_data) = bx.parameters, let [ref inner] = *ab_data.types ], { - if_let_chain! {[ - let TyTraitObject(ref traits, _) = inner.node, - traits.len() >= 1, - // Only Send/Sync can be used as additional traits, so it is enough to - // check only the first trait. - match_path_old(&traits[0].trait_ref.path, &paths::ANY_TRAIT) - ], { + if is_any_trait(inner) { // Ignore `Box` types, see #1884 for details. return; - }} + } let ltopt = if lt.is_elided() { "".to_owned() @@ -260,6 +254,21 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } } +// Returns true if given type is `Any` trait. +fn is_any_trait(t: &hir::Ty) -> bool { + if_let_chain! {[ + let TyTraitObject(ref traits, _) = t.node, + traits.len() >= 1, + // Only Send/Sync can be used as additional traits, so it is enough to + // check only the first trait. + match_path_old(&traits[0].trait_ref.path, &paths::ANY_TRAIT) + ], { + return true; + }} + + false +} + #[allow(missing_copy_implementations)] pub struct LetPass; -- cgit 1.4.1-3-g733a5 From 6d989c729d03f5f9900d153417488b5eaf1e2f2f Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 23 Aug 2017 17:54:35 +0200 Subject: add closure arg check, also catch non-consts --- clippy_lints/src/bytecount.rs | 47 +++++++++++++++++++++++++++++++++++++------ clippy_lints/src/shadow.rs | 30 +++------------------------ clippy_lints/src/utils/mod.rs | 28 ++++++++++++++++++++++++++ tests/ui/bytecount.rs | 13 ++++++++++++ tests/ui/bytecount.stderr | 26 ++++++++++++++++-------- 5 files changed, 103 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 99987f84ba7..cbd0c6d20d5 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,8 +1,8 @@ -use consts::{constant, Constant}; -use rustc_const_math::ConstInt; use rustc::hir::*; use rustc::lint::*; -use utils::{match_type, paths, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use rustc::ty; +use syntax::ast::{Name, UintTy}; +use utils::{contains_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for naive byte counts /// @@ -47,14 +47,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { ], { let body = cx.tcx.hir.body(body_id); if_let_chain!([ + body.arguments.len() == 1, + let Some(argname) = get_pat_name(&body.arguments[0].pat), let ExprBinary(ref op, ref l, ref r) = body.value.node, op.node == BiEq, match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), &paths::SLICE_ITER), - let Some((Constant::Int(ConstInt::U8(needle)), _)) = - constant(cx, l).or_else(|| constant(cx, r)) ], { + let needle = match get_path_name(l) { + Some(name) if check_arg(name, argname, r) => r, + _ => match get_path_name(r) { + Some(name) if check_arg(name, argname, l) => l, + _ => { return; } + } + }; + if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { + return; + } let haystack = if let ExprMethodCall(ref path, _, ref args) = filter_args[0].node { let p = path.name; @@ -73,8 +83,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { "Consider using the bytecount crate", format!("bytecount::count({}, {})", snippet(cx, haystack.span, ".."), - needle)); + snippet(cx, needle.span, ".."))); }); }); } } + +fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool { + name == arg && !contains_name(name, needle) +} + +fn get_pat_name(pat: &Pat) -> Option { + match pat.node { + PatKind::Binding(_, _, ref spname, _) => Some(spname.node), + PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), + PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), + _ => None + } +} + +fn get_path_name(expr: &Expr) -> Option { + match expr.node { + ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), + ExprBlock(ref b) => if b.stmts.is_empty() { + b.expr.as_ref().and_then(|p| get_path_name(p)) + } else { None }, + ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), + _ => None + } +} + diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index b4857f1b613..ccb339390b1 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,10 +1,10 @@ use reexport::*; use rustc::lint::*; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, FnKind, NestedVisitorMap}; +use rustc::hir::intravisit::FnKind; use rustc::ty; use syntax::codemap::Span; -use utils::{higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats}; +use utils::{contains_name, higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. @@ -261,7 +261,7 @@ fn lint_shadow<'a, 'tcx: 'a>( ), |db| { db.span_note(prev_span, "previous binding is here"); }, ); - } else if contains_self(name, expr) { + } else if contains_name(name, expr) { span_lint_and_then( cx, SHADOW_REUSE, @@ -391,27 +391,3 @@ fn path_eq_name(name: Name, path: &Path) -> bool { !path.is_global() && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() } -struct ContainsSelf { - name: Name, - result: bool, -} - -impl<'tcx> Visitor<'tcx> for ContainsSelf { - fn visit_name(&mut self, _: Span, name: Name) { - if self.name == name { - self.result = true; - } - } - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } -} - -fn contains_self(name: Name, expr: &Expr) -> bool { - let mut cs = ContainsSelf { - name: name, - result: false, - }; - cs.visit_expr(expr); - cs.result -} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7f8603f0f27..c24ccd5d573 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -3,6 +3,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::Def; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::map::Node; use rustc::lint::{LintContext, Level, LateContext, Lint}; use rustc::session::Session; @@ -393,6 +394,33 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option { } } +struct ContainsName { + name: Name, + result: bool, +} + +impl<'tcx> Visitor<'tcx> for ContainsName { + fn visit_name(&mut self, _: Span, name: Name) { + if self.name == name { + self.result = true; + } + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +/// check if an `Expr` contains a certain name +pub fn contains_name(name: Name, expr: &Expr) -> bool { + let mut cn = ContainsName { + name: name, + result: false, + }; + cn.visit_expr(expr); + cn.result +} + + /// Convert a span to a code snippet if available, otherwise use default. /// /// # Example diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 880a86eba60..8fc27c49f34 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] +#[deny(naive_bytecount)] fn main() { let x = vec![0_u8; 16]; @@ -11,4 +12,16 @@ fn main() { let _ = x.iter().filter(|a| **a > 0).count(); // not an equality count, OK. let _ = x.iter().map(|a| a + 1).filter(|&a| a < 15).count(); // not a slice + + let b = 0; + + let _ = x.iter().filter(|_| b > 0).count(); // woah there + + let _ = x.iter().filter(|_a| b == b + 1).count(); // nothing to see here, move along + + let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count + + let y = vec![0_u16; 3]; + + let _ = y.iter().filter(|&&a| a == 0).count(); // naive count, but not bytes } diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 818fa7eab1a..307edecfde1 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,16 +1,26 @@ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:7:13 + --> $DIR/bytecount.rs:8:13 | -7 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count +8 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` | - = note: `-D naive-bytecount` implied by `-D warnings` +note: lint level defined here + --> $DIR/bytecount.rs:4:8 + | +4 | #[deny(naive_bytecount)] + | ^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:9:13 - | -9 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` + --> $DIR/bytecount.rs:10:13 + | +10 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` + +error: You appear to be counting bytes the naive way + --> $DIR/bytecount.rs:22:13 + | +22 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From d6e4e0639e6ef5213a40cc35231f8be3cdb365ec Mon Sep 17 00:00:00 2001 From: Malo Jaffré Date: Wed, 23 Aug 2017 22:18:04 +0200 Subject: Fix int_ty_to_nbits Thanks @oli-obk for the detailed instructions. Fixes #1957. --- clippy_lints/src/types.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ea3db0e4690..14065aeaf88 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap}; use rustc::lint::*; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; @@ -479,17 +479,25 @@ declare_lint! { /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant -fn int_ty_to_nbits(typ: Ty) -> usize { - let n = match typ.sty { - ty::TyInt(i) => 4 << (i as usize), - ty::TyUint(u) => 4 << (u as usize), +fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { + match typ.sty { + ty::TyInt(i) => match i { + IntTy::Is => tcx.data_layout.pointer_size.bits(), + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, + }, + ty::TyUint(i) => match i { + UintTy::Us => tcx.data_layout.pointer_size.bits(), + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, + }, _ => 0, - }; - // n == 4 is the usize/isize case - if n == 4 { - ::std::mem::size_of::() * 8 - } else { - n } } @@ -510,7 +518,7 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t } else if is_isize_or_usize(cast_from) { "32 or 64".to_owned() } else { - int_ty_to_nbits(cast_from).to_string() + int_ty_to_nbits(cast_from, cx.tcx).to_string() }; span_lint( cx, @@ -542,7 +550,8 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); - let (from_nbits, to_nbits) = (int_ty_to_nbits(cast_from), int_ty_to_nbits(cast_to)); + let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); + let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { (true, true) | (false, false) => { @@ -650,7 +659,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { - let from_nbits = int_ty_to_nbits(cast_from); + let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = if let ty::TyFloat(FloatTy::F32) = cast_to.sty { 32 } else { -- cgit 1.4.1-3-g733a5 From 58a94ea5626520fa3883ae7df1ff21347796e2c9 Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Thu, 24 Aug 2017 18:17:35 +0300 Subject: CONTRIBUTING: add manual testing section --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7da1182ca67..ef95a50dcef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,6 +73,19 @@ Of course there's little sense in writing the output yourself or copying it arou Therefore you can simply run `tests/ui/update-all-references.sh` and check whether the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +### Testing manually + +Manually testing against an example file is useful if you have added some +`println!`s and test suite output becomes unreadable. To try clippy with your +local modifications, run `cargo run -- -L ./target/debug input.rs` from the +working copy root. Your test file, here `input.rs`, needs to have clippy +enabled as a plugin: + +```rust +#![feature(plugin)] +#![plugin(clippy)] +``` + ## Contributions Clippy welcomes contributions from everyone. -- cgit 1.4.1-3-g733a5 From 695bedbe270cbae05d19b7837a95d12d7bd9637a Mon Sep 17 00:00:00 2001 From: Alexey Zabelin Date: Thu, 24 Aug 2017 18:21:46 -0400 Subject: Rename `match_path_old` to `match_path` The old `match_path` was renamed to `match_qpath`. As per #1983. --- clippy_lints/src/derive.rs | 6 +++--- clippy_lints/src/if_let_redundant_pattern_matching.rs | 10 +++++----- clippy_lints/src/map_clone.rs | 4 ++-- clippy_lints/src/methods.rs | 8 ++++---- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/print.rs | 4 ++-- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/unused_io_amount.rs | 4 ++-- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/higher.rs | 14 +++++++------- clippy_lints/src/utils/internal_lints.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 16 ++++++++-------- tests/ui/trailing_zeros.stdout | 2 +- 13 files changed, 42 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index e186dd5e4db..36576365eac 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -3,7 +3,7 @@ use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; use utils::paths; -use utils::{is_automatically_derived, span_lint_and_then, match_path_old, is_copy}; +use utils::{is_automatically_derived, span_lint_and_then, match_path, is_copy}; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly. @@ -92,7 +92,7 @@ fn check_hash_peq<'a, 'tcx>( hash_is_automatically_derived: bool, ) { if_let_chain! {[ - match_path_old(&trait_ref.path, &paths::HASH), + match_path(&trait_ref.path, &paths::HASH), let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() ], { // Look for the PartialEq implementations for `ty` @@ -132,7 +132,7 @@ fn check_hash_peq<'a, 'tcx>( /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: Ty<'tcx>) { - if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) { + if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { if !is_copy(cx, ty) { return; } diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 058052769ef..0e1dd6449ab 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Span; -use utils::{paths, span_lint_and_then, match_path, snippet}; +use utils::{paths, span_lint_and_then, match_qpath, snippet}; /// **What it does:*** Lint for redundant pattern matching over `Result` or /// `Option` @@ -53,18 +53,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let good_method = match arms[0].pats[0].node { PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => { - if match_path(path, &paths::RESULT_OK) { + if match_qpath(path, &paths::RESULT_OK) { "is_ok()" - } else if match_path(path, &paths::RESULT_ERR) { + } else if match_qpath(path, &paths::RESULT_ERR) { "is_err()" - } else if match_path(path, &paths::OPTION_SOME) { + } else if match_qpath(path, &paths::OPTION_SOME) { "is_some()" } else { return; } }, - PatKind::Path(ref path) if match_path(path, &paths::OPTION_NONE) => "is_none()", + PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", _ => return, }; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 457c6cc8d65..fcb84e90eb6 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, +use utils::{is_adjusted, match_qpath, match_trait_method, match_type, remove_blocks, paths, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; /// **What it does:** Checks for mapping `clone()` over an iterator. @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }} }, ExprPath(ref path) => { - if match_path(path, &paths::CLONE) { + if match_qpath(path, &paths::CLONE) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); span_help_and_lint( cx, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a50d77f5521..1811142ae27 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -8,10 +8,10 @@ use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path, match_trait_method, +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_qpath, match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, span_lint_and_then, span_lint_and_sugg, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, last_path_segment, - single_segment_path, match_def_path, is_self, is_self_ty, iter_input_pats, match_path_old}; + single_segment_path, match_def_path, is_self, is_self_ty, iter_input_pats, match_path}; use utils::paths; use utils::sugg; @@ -1462,7 +1462,7 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener param.bounds.iter().any(|bound| { if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; - match_path_old(path, name) && + match_path(path, name) && path.segments.last().map_or(false, |s| { if let hir::PathParameters::AngleBracketedParameters(ref data) = s.parameters { data.types.len() == 1 && @@ -1540,7 +1540,7 @@ impl OutType { fn is_bool(ty: &hir::Ty) -> bool { if let hir::TyPath(ref p) = ty.node { - match_path(p, &["bool"]) + match_qpath(p, &["bool"]) } else { false } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index ef42bfe0b02..43c539a7a65 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -8,7 +8,7 @@ use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; use rustc_const_math::ConstFloat; use syntax::codemap::{Span, ExpnFormat}; -use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path, snippet, +use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_qpath, snippet, span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats, in_constant, match_trait_method, paths}; use utils::sugg::Sugg; @@ -486,7 +486,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { }, ExprCall(ref path, ref v) if v.len() == 1 => { if let ExprPath(ref path) = path.node { - if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { + if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) } else { return; diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 4a427fc79bd..982b46e20d3 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::hir::map::Node::{NodeItem, NodeImplItem}; use rustc::lint::*; use utils::paths; -use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path_old}; +use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path}; use format::get_argument_fmtstr_parts; /// **What it does:** This lint warns when you using `print!()` with a format @@ -144,7 +144,7 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { // `Debug` impl if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { if let ItemImpl(_, _, _, _, Some(ref tr), _, _) = item.node { - return match_path_old(&tr.path, &["Debug"]); + return match_path(&tr.path, &["Debug"]); } } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 5b5c63c1aca..a21142a257d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -7,7 +7,7 @@ use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_path, match_type, paths, span_lint, span_lint_and_then}; +use utils::{match_qpath, match_type, paths, span_lint, span_lint_and_then}; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless @@ -190,7 +190,7 @@ fn is_null_path(expr: &Expr) -> bool { if let ExprCall(ref pathexp, ref args) = expr.node { if args.is_empty() { if let ExprPath(ref path) = pathexp.node { - return match_path(path, &paths::PTR_NULL) || match_path(path, &paths::PTR_NULL_MUT); + return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT); } } } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index ff2148c88a9..1ac775ce7c1 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use utils::{span_lint, match_path, match_trait_method, is_try, paths}; +use utils::{span_lint, match_qpath, match_trait_method, is_try, paths}; /// **What it does:** Checks for unused written/read amount. /// @@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { hir::ExprMatch(ref res, _, _) if is_try(expr).is_some() => { if let hir::ExprCall(ref func, ref args) = res.node { if let hir::ExprPath(ref path) = func.node { - if match_path(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { + if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { check_method_call(cx, &args[0], expr); } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index a7fdc3d281b..ba8f0022b32 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -428,7 +428,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } fn visit_qpath(&mut self, path: &QPath, _: NodeId, _: Span) { - print!(" match_path({}, &[", self.current); + print!(" match_qpath({}, &[", self.current); print_path(path, &mut true); println!("]),"); } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 67319f0c355..aa57e12bca8 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_path, match_def_path, resolve_node, paths}; +use utils::{is_expn_of, match_qpath, match_def_path, resolve_node, paths}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -63,7 +63,7 @@ pub fn range(expr: &hir::Expr) -> Option { match expr.node { hir::ExprPath(ref path) => { - if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { + if match_qpath(path, &paths::RANGE_FULL_STD) || match_qpath(path, &paths::RANGE_FULL) { Some(Range { start: None, end: None, @@ -74,31 +74,31 @@ pub fn range(expr: &hir::Expr) -> Option { } }, hir::ExprStruct(ref path, ref fields, None) => { - if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) { + if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { Some(Range { start: get_field("start", fields), end: None, limits: ast::RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || match_path(path, &paths::RANGE_INCLUSIVE) { + } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { Some(Range { start: get_field("start", fields), end: get_field("end", fields), limits: ast::RangeLimits::Closed, }) - } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) { + } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { Some(Range { start: get_field("start", fields), end: get_field("end", fields), limits: ast::RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) { + } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { Some(Range { start: None, end: get_field("end", fields), limits: ast::RangeLimits::Closed, }) - } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) { + } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { Some(Range { start: None, end: get_field("end", fields), diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index f81aff24338..d83e094212a 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; -use utils::{paths, match_path, span_lint}; +use utils::{paths, match_qpath, span_lint}; use syntax::symbol::InternedString; use syntax::ast::{Name, NodeId, ItemKind, Crate as AstCrate}; use syntax::codemap::Span; @@ -167,7 +167,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool { return false; } if let TyPath(ref path) = inner.node { - return match_path(path, &paths::LINT); + return match_qpath(path, &paths::LINT); } } false @@ -176,7 +176,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool { fn is_lint_array_type(ty: &Ty) -> bool { if let TyPath(ref path) = ty.node { - match_path(path, &paths::LINT_ARRAY) + match_qpath(path, &paths::LINT_ARRAY) } else { false } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c24ccd5d573..c08f7d4254f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -240,15 +240,15 @@ pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> { /// /// # Examples /// ```rust,ignore -/// match_path(path, &["std", "rt", "begin_unwind"]) +/// match_qpath(path, &["std", "rt", "begin_unwind"]) /// ``` -pub fn match_path(path: &QPath, segments: &[&str]) -> bool { +pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { match *path { - QPath::Resolved(_, ref path) => match_path_old(path, segments), + QPath::Resolved(_, ref path) => match_path(path, segments), QPath::TypeRelative(ref ty, ref segment) => { match ty.node { TyPath(ref inner_path) => { - !segments.is_empty() && match_path(inner_path, &segments[..(segments.len() - 1)]) && + !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && segment.name == segments[segments.len() - 1] }, _ => false, @@ -257,7 +257,7 @@ pub fn match_path(path: &QPath, segments: &[&str]) -> bool { } } -pub fn match_path_old(path: &Path, segments: &[&str]) -> bool { +pub fn match_path(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( |(a, b)| a.name == *b, ) @@ -267,7 +267,7 @@ pub fn match_path_old(path: &Path, segments: &[&str]) -> bool { /// /// # Examples /// ```rust,ignore -/// match_path(path, &["std", "rt", "begin_unwind"]) +/// match_qpath(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all( @@ -988,7 +988,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { fn is_ok(arm: &Arm) -> bool { if_let_chain! {[ let PatKind::TupleStruct(ref path, ref pat, None) = arm.pats[0].node, - match_path(path, &paths::RESULT_OK[1..]), + match_qpath(path, &paths::RESULT_OK[1..]), let PatKind::Binding(_, defid, _, None) = pat[0].node, let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node, path.def.def_id() == defid, @@ -1000,7 +1000,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { fn is_err(arm: &Arm) -> bool { if let PatKind::TupleStruct(ref path, _, _) = arm.pats[0].node { - match_path(path, &paths::RESULT_ERR[1..]) + match_qpath(path, &paths::RESULT_ERR[1..]) } else { false } diff --git a/tests/ui/trailing_zeros.stdout b/tests/ui/trailing_zeros.stdout index 98025316da4..52ec01260be 100644 --- a/tests/ui/trailing_zeros.stdout +++ b/tests/ui/trailing_zeros.stdout @@ -4,7 +4,7 @@ if_let_chain!{[ let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node, BinOp_::BiBitAnd == op1.node, let Expr_::ExprPath(ref path) = left1.node, - match_path(path, &["x"]), + match_qpath(path, &["x"]), let Expr_::ExprLit(ref lit) = right1.node, let LitKind::Int(15, _) = lit.node, let Expr_::ExprLit(ref lit1) = right.node, -- cgit 1.4.1-3-g733a5 From cd57add2c321a280bfed6e31bf86a2cfac829890 Mon Sep 17 00:00:00 2001 From: Alexey Zabelin Date: Thu, 24 Aug 2017 20:46:40 -0400 Subject: Incorporate upstream changes --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e48f6a9042b..3eca9ad1baf 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -10,7 +10,7 @@ use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::attr::IntType; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, opt_def_id, last_path_segment, type_size, match_path_old}; + span_lint_and_sugg, opt_def_id, last_path_segment, type_size, match_path}; use utils::paths; /// Handles all the linting of funky types @@ -261,7 +261,7 @@ fn is_any_trait(t: &hir::Ty) -> bool { traits.len() >= 1, // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. - match_path_old(&traits[0].trait_ref.path, &paths::ANY_TRAIT) + match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT) ], { return true; }} -- cgit 1.4.1-3-g733a5 From 70c8fe5539f6a7888e631f2b1a0e59be7260389f Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Fri, 25 Aug 2017 17:30:21 +1000 Subject: fix PathParameters usage --- clippy_lints/src/lifetimes.rs | 40 ++++++++++++++---------------- clippy_lints/src/methods.rs | 8 +++--- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/transmute.rs | 4 +-- clippy_lints/src/types.rs | 14 +++++------ clippy_lints/src/use_self.rs | 18 +++++++------- clippy_lints/src/utils/hir_utils.rs | 15 +++++------ 7 files changed, 48 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 47cc41c472c..4cb386471c9 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -104,14 +104,14 @@ fn check_fn_inner<'a, 'tcx>( for typ in &generics.ty_params { for bound in &typ.bounds { if let TraitTyParamBound(ref trait_ref, _) = *bound { - let bounds = trait_ref + let bounds = &trait_ref .trait_ref .path .segments .last() .expect("a path must have at least one segment") .parameters - .lifetimes(); + .lifetimes; for bound in bounds { if bound.name != "'static" && !bound.is_elided() { return; @@ -282,25 +282,23 @@ impl<'v, 't> RefVisitor<'v, 't> { fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { let last_path_segment = &last_path_segment(qpath).parameters; - if let AngleBracketedParameters(ref params) = *last_path_segment { - if params.lifetimes.is_empty() { - let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); - match self.cx.tables.qpath_def(qpath, hir_id) { - Def::TyAlias(def_id) | - Def::Struct(def_id) => { - let generics = self.cx.tcx.generics_of(def_id); - for _ in generics.regions.as_slice() { - self.record(&None); - } - }, - Def::Trait(def_id) => { - let trait_def = self.cx.tcx.trait_def(def_id); - for _ in &self.cx.tcx.generics_of(trait_def.def_id).regions { - self.record(&None); - } - }, - _ => (), - } + if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { + let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + match self.cx.tables.qpath_def(qpath, hir_id) { + Def::TyAlias(def_id) | + Def::Struct(def_id) => { + let generics = self.cx.tcx.generics_of(def_id); + for _ in generics.regions.as_slice() { + self.record(&None); + } + }, + Def::Trait(def_id) => { + let trait_def = self.cx.tcx.trait_def(def_id); + for _ in &self.cx.tcx.generics_of(trait_def.def_id).regions { + self.record(&None); + } + }, + _ => (), } } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a50d77f5521..bb3ab92047e 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1464,11 +1464,11 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener let path = &ptr.trait_ref.path; match_path_old(path, name) && path.segments.last().map_or(false, |s| { - if let hir::PathParameters::AngleBracketedParameters(ref data) = s.parameters { - data.types.len() == 1 && - (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty)) - } else { + if s.parameters.parenthesized { false + } else { + s.parameters.types.len() == 1 && + (is_self_ty(&s.parameters.types[0]) || is_ty(&*s.parameters.types[0], self_ty)) } }) } else { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index b7de586ed80..15ebe648500 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let TyPath(QPath::Resolved(_, ref path)) = input.node, let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") - .map(|ps| ps.parameters.types()[0]), + .map(|ps| &ps.parameters.types[0]), ], { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); db.span_suggestion(input.span, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index bcb03c79215..83e212c36d1 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -208,8 +208,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { let seg = last_path_segment(path); if_let_chain!{[ - let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters, - let Some(to_ty) = ang.types.get(1), + !seg.parameters.parenthesized, + let Some(to_ty) = seg.parameters.types.get(1), let TyRptr(_, ref to_ty) = to_ty.node, ], { return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e48f6a9042b..7c68eab801d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -155,8 +155,8 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { if Some(def_id) == cx.tcx.lang_items.owned_box() { let last = last_path_segment(qpath); if_let_chain! {[ - let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, - let Some(vec) = ag.types.get(0), + !last.parameters.parenthesized, + let Some(vec) = last.parameters.types.get(0), let TyPath(ref qpath) = vec.node, let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))), match_def_path(cx.tcx, did, &paths::VEC), @@ -182,18 +182,18 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { match *qpath { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); - for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) { + for ty in p.segments.iter().flat_map(|seg| seg.parameters.types.iter()) { check_ty(cx, ty, is_local); } }, QPath::Resolved(None, ref p) => { - for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) { + for ty in p.segments.iter().flat_map(|seg| seg.parameters.types.iter()) { check_ty(cx, ty, is_local); } }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); - for ty in seg.parameters.types() { + for ty in seg.parameters.types.iter() { check_ty(cx, ty, is_local); } }, @@ -209,8 +209,8 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { Some(def_id) == cx.tcx.lang_items.owned_box(), let QPath::Resolved(None, ref path) = *qpath, let [ref bx] = *path.segments, - let PathParameters::AngleBracketedParameters(ref ab_data) = bx.parameters, - let [ref inner] = *ab_data.types + !bx.parameters.parenthesized, + let [ref inner] = *bx.parameters.types ], { if is_any_trait(inner) { // Ignore `Box` types, see #1884 for details. diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b8c970d376e..fffeb3bb699 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -56,16 +56,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if_let_chain!([ let ItemImpl(.., ref item_type, ref refs) = item.node, let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, - let PathParameters::AngleBracketedParameters(ref param_data) - = item_path.segments.last().expect(SEGMENTS_MSG).parameters, - param_data.lifetimes.len() == 0, ], { - let visitor = &mut UseSelfVisitor { - item_path: item_path, - cx: cx, - }; - for impl_item_ref in refs { - visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; + if !parameters.parenthesized && parameters.lifetimes.len() == 0 { + let visitor = &mut UseSelfVisitor { + item_path: item_path, + cx: cx, + }; + for impl_item_ref in refs { + visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + } } }) } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index b4caad0845a..4890bb81dc3 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -195,18 +195,15 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { - match (left, right) { - (&AngleBracketedParameters(ref left), &AngleBracketedParameters(ref right)) => { + if !(left.parenthesized || right.parenthesized) { over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) - }, - (&ParenthesizedParameters(ref left), &ParenthesizedParameters(ref right)) => { - over(&left.inputs, &right.inputs, |l, r| self.eq_ty(l, r)) && - both(&left.output, &right.output, |l, r| self.eq_ty(l, r)) - }, - (&AngleBracketedParameters(_), &ParenthesizedParameters(_)) | - (&ParenthesizedParameters(_), &AngleBracketedParameters(_)) => false, + } else if left.parenthesized && right.parenthesized { + over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) && + both(&Some(&left.bindings[0].ty), &Some(&right.bindings[0].ty), |l, r| self.eq_ty(l, r)) + } else { + false } } -- cgit 1.4.1-3-g733a5 From bec2c68ebcb66a800d0015b2babc4f935ee96fa9 Mon Sep 17 00:00:00 2001 From: mcarton Date: Fri, 25 Aug 2017 12:01:57 +0200 Subject: Bump the version to 0.0.154 --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b72a6c1be7..58ded1b3372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. -* New lint: [`naive_bytecount`] ## 0.0.154 +* Update to *rustc 1.21.0-nightly (2c0558f63 2017-08-24)* * Fix [`use_self`] triggering inside derives * Add support for linting an entire workspace with `cargo clippy --all` +* New lint: [`naive_bytecount`] ## 0.0.153 * Update to *rustc 1.21.0-nightly (8c303ed87 2017-08-20)* diff --git a/Cargo.toml b/Cargo.toml index 6db6ea54fb8..914d453ebf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.153" +version = "0.0.154" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.153", path = "clippy_lints" } +clippy_lints = { version = "0.0.154", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 94094bf49c9..8cdbbaaecf5 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.153" +version = "0.0.154" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From df903eddddb3733f5d03c940333856fbb00e7e4d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 25 Aug 2017 22:20:52 +0200 Subject: New lint: (maybe_)infinite_iter This fixes #1870 (mostly, does not account for loops yet) --- CHANGELOG.md | 2 + README.md | 4 +- clippy_lints/src/infinite_iter.rs | 218 ++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 4 + clippy_lints/src/utils/paths.rs | 2 + tests/ui/infinite_iter.rs | 40 +++++++ tests/ui/infinite_iter.stderr | 100 +++++++++++++++++ 7 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/infinite_iter.rs create mode 100644 tests/ui/infinite_iter.rs create mode 100644 tests/ui/infinite_iter.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ded1b3372..8b0a1f3bee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -481,6 +481,7 @@ All notable changes to this project will be documented in this file. [`inconsistent_digit_grouping`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping [`indexing_slicing`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing [`ineffective_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask +[`infinite_iter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#infinite_iter [`inline_always`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always [`integer_arithmetic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic [`invalid_regex`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex @@ -508,6 +509,7 @@ All notable changes to this project will be documented in this file. [`match_ref_pats`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats [`match_same_arms`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms [`match_wild_err_arm`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm +[`maybe_infinite_iter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#maybe_infinite_iter [`mem_forget`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget [`min_max`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max [`misrefactored_assign_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op diff --git a/README.md b/README.md index bc043ec62d3..aa36871b6dd 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 206 lints included in this crate: +There are 208 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -252,6 +252,7 @@ name [inconsistent_digit_grouping](https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping) | warn | integer literals with digits grouped inconsistently [indexing_slicing](https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage [ineffective_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` +[infinite_iter](https://github.com/rust-lang-nursery/rust-clippy/wiki#infinite_iter) | warn | infinite iteration [inline_always](https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always) | warn | use of `#[inline(always)]` [integer_arithmetic](https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic) | allow | any integer arithmetic statement [invalid_regex](https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex) | deny | invalid regular expressions @@ -279,6 +280,7 @@ name [match_ref_pats](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` with all arms prefixed with `&` instead of deref-ing the match expression [match_same_arms](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies [match_wild_err_arm](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm) | warn | a match with `Err(_)` arm and take drastic actions +[maybe_infinite_iter](https://github.com/rust-lang-nursery/rust-clippy/wiki#maybe_infinite_iter) | allow | possible infinite iteration [mem_forget](https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage on `Drop` types, likely to cause memory leaks [min_max](https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant [misrefactored_assign_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op) | warn | having a variable on both sides of an assign op diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs new file mode 100644 index 00000000000..ea1fb5a037e --- /dev/null +++ b/clippy_lints/src/infinite_iter.rs @@ -0,0 +1,218 @@ +use rustc::hir::*; +use rustc::lint::*; +use utils::{get_trait_def_id, implements_trait, higher, match_path, paths, span_lint}; + +/// **What it does:** Checks for iteration that is guaranteed to be infinite. +/// +/// **Why is this bad?** While there may be places where this is acceptable +/// (e.g. in event streams), in most cases this is simply an error. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// repeat(1_u8).iter().collect::>() +/// ``` +declare_lint! { + pub INFINITE_ITER, + Warn, + "infinite iteration" +} + +/// **What it does:** Checks for iteration that may be infinite. +/// +/// **Why is this bad?** While there may be places where this is acceptable +/// (e.g. in event streams), in most cases this is simply an error. +/// +/// **Known problems:** The code may have a condition to stop iteration, but +/// this lint is not clever enough to analyze it. +/// +/// **Example:** +/// ```rust +/// [0..].iter().zip(infinite_iter.take_while(|x| x > 5)) +/// ``` +declare_lint! { + pub MAYBE_INFINITE_ITER, + Allow, + "possible infinite iteration" +} + +#[derive(Copy, Clone)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(INFINITE_ITER, MAYBE_INFINITE_ITER) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + let (lint, msg) = match complete_infinite_iter(cx, expr) { + True => (INFINITE_ITER, "infinite iteration detected"), + Unknown => (MAYBE_INFINITE_ITER, + "possible infinite iteration detected"), + False => { return; } + }; + span_lint(cx, lint, expr.span, msg) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum TriState { + True, + Unknown, + False +} + +use self::TriState::{True, Unknown, False}; + +impl TriState { + fn and(self, b: Self) -> Self { + match (self, b) { + (False, _) | (_, False) => False, + (Unknown, _) | (_, Unknown) => Unknown, + _ => True + } + } + + fn or(self, b: Self) -> Self { + match (self, b) { + (True, _) | (_, True) => True, + (Unknown, _) | (_, Unknown) => Unknown, + _ => False + } + } +} + +impl From for TriState { + fn from(b: bool) -> Self { + if b { True } else { False } + } +} + +#[derive(Copy, Clone)] +enum Heuristic { + Always, + First, + Any, + All +} + +use self::Heuristic::{Always, First, Any, All}; + +// here we use the `TriState` as (Finite, Possible Infinite, Infinite) +static HEURISTICS : &[(&str, usize, Heuristic, TriState)] = &[ + ("zip", 2, All, True), + ("chain", 2, Any, True), + ("cycle", 1, Always, True), + ("map", 2, First, True), + ("by_ref", 1, First, True), + ("cloned", 1, First, True), + ("rev", 1, First, True), + ("inspect", 1, First, True), + ("enumerate", 1, First, True), + ("peekable", 2, First, True), + ("fuse", 1, First, True), + ("skip", 2, First, True), + ("skip_while", 1, First, True), + ("filter", 2, First, True), + ("filter_map", 2, First, True), + ("flat_map", 2, First, True), + ("unzip", 1, First, True), + ("take_while", 2, First, Unknown), + ("scan", 3, First, Unknown) +]; + +fn is_infinite(cx: &LateContext, expr: &Expr) -> TriState { + match expr.node { + ExprMethodCall(ref method, _, ref args) => { + for &(name, len, heuristic, cap) in HEURISTICS.iter() { + if method.name == name && args.len() == len { + return (match heuristic { + Always => True, + First => is_infinite(cx, &args[0]), + Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), + All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), + }).and(cap); + } + } + if method.name == "flat_map" && args.len() == 2 { + if let ExprClosure(_, _, body_id, _) = args[1].node { + let body = cx.tcx.hir.body(body_id); + return is_infinite(cx, &body.value); + } + } + False + }, + ExprBlock(ref block) => + block.expr.as_ref().map_or(False, |e| is_infinite(cx, e)), + ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), + ExprCall(ref path, _) => { + if let ExprPath(ref qpath) = path.node { + match_path(qpath, &paths::REPEAT).into() + } else { False } + }, + ExprStruct(..) => { + higher::range(expr).map_or(false, |r| r.end.is_none()).into() + }, + _ => False + } +} + +static POSSIBLY_COMPLETING_METHODS : &[(&str, usize)] = &[ + ("find", 2), + ("rfind", 2), + ("position", 2), + ("rposition", 2), + ("any", 2), + ("all", 2) +]; + +static COMPLETING_METHODS : &[(&str, usize)] = &[ + ("count", 1), + ("collect", 1), + ("fold", 3), + ("for_each", 2), + ("partition", 2), + ("max", 1), + ("max_by", 2), + ("max_by_key", 2), + ("min", 1), + ("min_by", 2), + ("min_by_key", 2), + ("sum", 1), + ("product", 1) +]; + +fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> TriState { + match expr.node { + ExprMethodCall(ref method, _, ref args) => { + for &(name, len) in COMPLETING_METHODS.iter() { + if method.name == name && args.len() == len { + return is_infinite(cx, &args[0]); + } + } + for &(name, len) in POSSIBLY_COMPLETING_METHODS.iter() { + if method.name == name && args.len() == len { + return Unknown.and(is_infinite(cx, &args[0])); + } + } + if method.name == "last" && args.len() == 1 && + get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR).map_or(false, + |id| !implements_trait(cx, + cx.tables.expr_ty(&args[0]), + id, + &[])) { + return is_infinite(cx, &args[0]); + } + }, + ExprBinary(op, ref l, ref r) => { + if op.node.is_comparison() { + return is_infinite(cx, l).and(is_infinite(cx, r)).and(Unknown) + } + }, //TODO: ExprLoop + Match + _ => () + } + False +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c4c949c792e..892d664aabb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -97,6 +97,7 @@ pub mod functions; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; +pub mod infinite_iter; pub mod items_after_statements; pub mod large_enum_variant; pub mod len_zero; @@ -323,6 +324,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); + reg.register_late_lint_pass(box infinite_iter::Pass); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -338,6 +340,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, + infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, @@ -422,6 +425,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { functions::TOO_MANY_ARGUMENTS, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + infinite_iter::INFINITE_ITER, large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 1a49dad1ae4..9057920098e 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -21,6 +21,7 @@ pub const CSTRING_NEW: [&'static str; 5] = ["std", "ffi", "c_str", "CString", "n pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"]; pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"]; +pub const DOUBLE_ENDED_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["core", "fmt", "ArgumentV1", "new"]; @@ -65,6 +66,7 @@ pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "n pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; pub const REGEX_SET_NEW: [&'static str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; +pub const REPEAT: [&'static str; 3] = ["core", "iter", "repeat"]; pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; pub const RESULT_ERR: [&'static str; 4] = ["core", "result", "Result", "Err"]; pub const RESULT_OK: [&'static str; 4] = ["core", "result", "Result", "Ok"]; diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs new file mode 100644 index 00000000000..fd433edf98d --- /dev/null +++ b/tests/ui/infinite_iter.rs @@ -0,0 +1,40 @@ +#![feature(plugin)] +#![feature(iterator_for_each)] +#![plugin(clippy)] +use std::iter::repeat; + +fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } + +#[allow(maybe_infinite_iter)] +#[deny(infinite_iter)] +fn infinite_iters() { + repeat(0_u8).collect::>(); // infinite iter + (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter + (0..8_u64).chain(0..).max(); // infinite iter + (0_usize..).chain([0usize, 1, 2].iter().cloned()).skip_while(|x| *x != 42).min(); // infinite iter + (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter + (0..3_u32).flat_map(|x| x..).sum::(); // infinite iter + (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter + (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter + (0..42_u64).by_ref().last(); // not an infinite, because ranges are double-ended + (0..).next(); // iterator is not exhausted +} + +#[deny(maybe_infinite_iter)] +fn potential_infinite_iters() { + (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter + repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter + (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter + (0..).find(|x| *x == 24); // maybe infinite iter + (0..).position(|x| x == 24); // maybe infinite iter + (0..).any(|x| x == 24); // maybe infinite iter + (0..).all(|x| x == 24); // maybe infinite iter + + (0..).zip(0..42).take_while(|&(x, _)| x != 42).count(); // not infinite + repeat(42).take_while(|x| *x == 42).next(); // iterator is not exhausted +} + +fn main() { + infinite_iters(); + potential_infinite_iters(); +} diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr new file mode 100644 index 00000000000..b3d2f08a865 --- /dev/null +++ b/tests/ui/infinite_iter.stderr @@ -0,0 +1,100 @@ +error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator + --> $DIR/infinite_iter.rs:11:5 + | +11 | repeat(0_u8).collect::>(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D unused-collect` implied by `-D warnings` + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:11:5 + | +11 | repeat(0_u8).collect::>(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/infinite_iter.rs:9:8 + | +9 | #[deny(infinite_iter)] + | ^^^^^^^^^^^^^ + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:12:5 + | +12 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:13:5 + | +13 | (0..8_u64).chain(0..).max(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:15:5 + | +15 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:17:5 + | +17 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: infinite iteration detected + --> $DIR/infinite_iter.rs:18:5 + | +18 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:25:5 + | +25 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/infinite_iter.rs:23:8 + | +23 | #[deny(maybe_infinite_iter)] + | ^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:26:5 + | +26 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:27:5 + | +27 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:28:5 + | +28 | (0..).find(|x| *x == 24); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:29:5 + | +29 | (0..).position(|x| x == 24); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:30:5 + | +30 | (0..).any(|x| x == 24); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: possible infinite iteration detected + --> $DIR/infinite_iter.rs:31:5 + | +31 | (0..).all(|x| x == 24); // maybe infinite iter + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors + -- cgit 1.4.1-3-g733a5 From 6e7bc6ad9aab232fecfe6a247a1afd66c830de0a Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sat, 26 Aug 2017 00:09:31 +0200 Subject: fix match_path -> match_qpath rename --- clippy_lints/src/infinite_iter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index ea1fb5a037e..5ec9c97ed92 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{get_trait_def_id, implements_trait, higher, match_path, paths, span_lint}; +use utils::{get_trait_def_id, implements_trait, higher, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// @@ -150,7 +150,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> TriState { ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), ExprCall(ref path, _) => { if let ExprPath(ref qpath) = path.node { - match_path(qpath, &paths::REPEAT).into() + match_qpath(qpath, &paths::REPEAT).into() } else { False } }, ExprStruct(..) => { -- cgit 1.4.1-3-g733a5 From 39ceca8893773e71e34e9eebc6952c71bec5bc5b Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sat, 26 Aug 2017 18:46:42 +0200 Subject: rename TriState -> Finiteness, docs --- clippy_lints/src/infinite_iter.rs | 110 +++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 5ec9c97ed92..72ff75dd994 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -49,88 +49,98 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let (lint, msg) = match complete_infinite_iter(cx, expr) { - True => (INFINITE_ITER, "infinite iteration detected"), - Unknown => (MAYBE_INFINITE_ITER, + Infinite => (INFINITE_ITER, "infinite iteration detected"), + MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"), - False => { return; } + Finite => { return; } }; span_lint(cx, lint, expr.span, msg) } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum TriState { - True, - Unknown, - False +enum Finiteness { + Infinite, + MaybeInfinite, + Finite } -use self::TriState::{True, Unknown, False}; +use self::Finiteness::{Infinite, MaybeInfinite, Finite}; -impl TriState { +impl Finiteness { fn and(self, b: Self) -> Self { match (self, b) { - (False, _) | (_, False) => False, - (Unknown, _) | (_, Unknown) => Unknown, - _ => True + (Finite, _) | (_, Finite) => Finite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, + _ => Infinite } } fn or(self, b: Self) -> Self { match (self, b) { - (True, _) | (_, True) => True, - (Unknown, _) | (_, Unknown) => Unknown, - _ => False + (Infinite, _) | (_, Infinite) => Infinite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, + _ => Finite } } } -impl From for TriState { +impl From for Finiteness { fn from(b: bool) -> Self { - if b { True } else { False } + if b { Infinite } else { Finite } } } +/// This tells us what to look for to know if the iterator returned by +/// this method is infinite #[derive(Copy, Clone)] enum Heuristic { + /// infinite no matter what Always, + /// infinite if the first argument is First, + /// infinite if any of the supplied arguments is Any, + /// infinite if all of the supplied arguments are All } use self::Heuristic::{Always, First, Any, All}; -// here we use the `TriState` as (Finite, Possible Infinite, Infinite) -static HEURISTICS : &[(&str, usize, Heuristic, TriState)] = &[ - ("zip", 2, All, True), - ("chain", 2, Any, True), - ("cycle", 1, Always, True), - ("map", 2, First, True), - ("by_ref", 1, First, True), - ("cloned", 1, First, True), - ("rev", 1, First, True), - ("inspect", 1, First, True), - ("enumerate", 1, First, True), - ("peekable", 2, First, True), - ("fuse", 1, First, True), - ("skip", 2, First, True), - ("skip_while", 1, First, True), - ("filter", 2, First, True), - ("filter_map", 2, First, True), - ("flat_map", 2, First, True), - ("unzip", 1, First, True), - ("take_while", 2, First, Unknown), - ("scan", 3, First, Unknown) +/// a slice of (method name, number of args, heuristic, bounds) tuples +/// that will be used to determine whether the method in question +/// returns an infinite or possibly infinite iterator. The finiteness +/// is an upper bound, e.g. some methods can return a possibly +/// infinite iterator at worst, e.g. `take_while`. +static HEURISTICS : &[(&str, usize, Heuristic, Finiteness)] = &[ + ("zip", 2, All, Infinite), + ("chain", 2, Any, Infinite), + ("cycle", 1, Always, Infinite), + ("map", 2, First, Infinite), + ("by_ref", 1, First, Infinite), + ("cloned", 1, First, Infinite), + ("rev", 1, First, Infinite), + ("inspect", 1, First, Infinite), + ("enumerate", 1, First, Infinite), + ("peekable", 2, First, Infinite), + ("fuse", 1, First, Infinite), + ("skip", 2, First, Infinite), + ("skip_while", 1, First, Infinite), + ("filter", 2, First, Infinite), + ("filter_map", 2, First, Infinite), + ("flat_map", 2, First, Infinite), + ("unzip", 1, First, Infinite), + ("take_while", 2, First, MaybeInfinite), + ("scan", 3, First, MaybeInfinite) ]; -fn is_infinite(cx: &LateContext, expr: &Expr) -> TriState { +fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { ExprMethodCall(ref method, _, ref args) => { for &(name, len, heuristic, cap) in HEURISTICS.iter() { if method.name == name && args.len() == len { return (match heuristic { - Always => True, + Always => Infinite, First => is_infinite(cx, &args[0]), Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), @@ -143,23 +153,25 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> TriState { return is_infinite(cx, &body.value); } } - False + Finite }, ExprBlock(ref block) => - block.expr.as_ref().map_or(False, |e| is_infinite(cx, e)), + block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), ExprCall(ref path, _) => { if let ExprPath(ref qpath) = path.node { match_qpath(qpath, &paths::REPEAT).into() - } else { False } + } else { Finite } }, ExprStruct(..) => { higher::range(expr).map_or(false, |r| r.end.is_none()).into() }, - _ => False + _ => Finite } } +/// the names and argument lengths of methods that *may* exhaust their +/// iterators static POSSIBLY_COMPLETING_METHODS : &[(&str, usize)] = &[ ("find", 2), ("rfind", 2), @@ -169,6 +181,8 @@ static POSSIBLY_COMPLETING_METHODS : &[(&str, usize)] = &[ ("all", 2) ]; +/// the names and argument lengths of methods that *always* exhaust +/// their iterators static COMPLETING_METHODS : &[(&str, usize)] = &[ ("count", 1), ("collect", 1), @@ -185,7 +199,7 @@ static COMPLETING_METHODS : &[(&str, usize)] = &[ ("product", 1) ]; -fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> TriState { +fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { ExprMethodCall(ref method, _, ref args) => { for &(name, len) in COMPLETING_METHODS.iter() { @@ -195,7 +209,7 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> TriState { } for &(name, len) in POSSIBLY_COMPLETING_METHODS.iter() { if method.name == name && args.len() == len { - return Unknown.and(is_infinite(cx, &args[0])); + return MaybeInfinite.and(is_infinite(cx, &args[0])); } } if method.name == "last" && args.len() == 1 && @@ -209,10 +223,10 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> TriState { }, ExprBinary(op, ref l, ref r) => { if op.node.is_comparison() { - return is_infinite(cx, l).and(is_infinite(cx, r)).and(Unknown) + return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite) } }, //TODO: ExprLoop + Match _ => () } - False + Finite } -- cgit 1.4.1-3-g733a5 From f37f2f710cb5b143f332cd29194874d7c29a8c3c Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sun, 27 Aug 2017 16:02:05 +0900 Subject: Reorder allow attributes to suppress unknown lint warning --- clippy_lints/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 892d664aabb..a29e6a84483 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -10,7 +10,7 @@ #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] -#![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)] +#![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] extern crate syntax; extern crate syntax_pos; -- cgit 1.4.1-3-g733a5 From b8da486ce5a8a8a3590cb38497030d293217104f Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sun, 27 Aug 2017 16:04:20 +0900 Subject: Remove unused extern crates --- clippy_lints/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a29e6a84483..feb094cc85b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -16,14 +16,9 @@ extern crate syntax; extern crate syntax_pos; #[macro_use] extern crate rustc; -extern crate rustc_data_structures; extern crate toml; -// Only for the compile time checking of paths -extern crate core; -extern crate alloc; - // for unicode nfc normalization extern crate unicode_normalization; -- cgit 1.4.1-3-g733a5 From 7714203c72ad84f45f756137c25bf6be8681c516 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 13 Aug 2017 14:58:17 -0700 Subject: Add a lint for lossless casts. --- CHANGELOG.md | 1 + README.md | 3 +- clippy_lints/src/enum_clike.rs | 4 +- clippy_lints/src/lib.rs | 1 + clippy_lints/src/misc.rs | 12 +- clippy_lints/src/types.rs | 68 ++++++++- tests/ui/cast.rs | 37 ++++- tests/ui/cast.stderr | 334 +++++++++++++++++++++++++++++++---------- 8 files changed, 360 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b0a1f3bee5..01c0766fe21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -426,6 +426,7 @@ All notable changes to this project will be documented in this file. [`box_vec`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec [`boxed_local`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local [`builtin_type_shadow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow +[`cast_lossless`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless [`cast_possible_truncation`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation [`cast_possible_wrap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap [`cast_precision_loss`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss diff --git a/README.md b/README.md index aa36871b6dd..01c4a89e149 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 208 lints included in this crate: +There are 209 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -198,6 +198,7 @@ name [box_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap [boxed_local](https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary [builtin_type_shadow](https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type +[cast_lossless](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless) | allow | casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8` [cast_possible_truncation](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g. `x as f32` where `x: u64` diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index bf2ba847ec8..e95c37b0aee 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -54,8 +54,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let bad = match cx.tcx.at(expr.span).const_eval( param_env.and((did, substs)), ) { - Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, - Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, + Ok(ConstVal::Integral(Usize(Us64(i)))) => u64::from(i as u32) != i, + Ok(ConstVal::Integral(Isize(Is64(i)))) => i64::from(i as i32) != i, _ => false, }; if bad { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c99df8acdfc..6a0fe5ad0a7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -359,6 +359,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { shadow::SHADOW_UNRELATED, strings::STRING_ADD, strings::STRING_ADD_ASSIGN, + types::CAST_LOSSLESS, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, types::CAST_PRECISION_LOSS, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 43c539a7a65..4e3cb667122 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -430,17 +430,17 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { FloatTy::F32 => { let zero = ConstFloat { ty: FloatTy::F32, - bits: 0.0_f32.to_bits() as u128, + bits: u128::from(0.0_f32.to_bits()), }; let infinity = ConstFloat { ty: FloatTy::F32, - bits: ::std::f32::INFINITY.to_bits() as u128, + bits: u128::from(::std::f32::INFINITY.to_bits()), }; let neg_infinity = ConstFloat { ty: FloatTy::F32, - bits: ::std::f32::NEG_INFINITY.to_bits() as u128, + bits: u128::from(::std::f32::NEG_INFINITY.to_bits()), }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || @@ -449,17 +449,17 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { FloatTy::F64 => { let zero = ConstFloat { ty: FloatTy::F64, - bits: 0.0_f64.to_bits() as u128, + bits: u128::from(0.0_f64.to_bits()), }; let infinity = ConstFloat { ty: FloatTy::F64, - bits: ::std::f64::INFINITY.to_bits() as u128, + bits: u128::from(::std::f64::INFINITY.to_bits()), }; let neg_infinity = ConstFloat { ty: FloatTy::F64, - bits: ::std::f64::NEG_INFINITY.to_bits() as u128, + bits: u128::from(::std::f64::NEG_INFINITY.to_bits()), }; val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index db962ad56f3..9612c670ff0 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -481,6 +481,28 @@ declare_lint! { and `x > i32::MAX`" } +/// **What it does:** Checks for on casts between numerical types that may +/// be replaced by safe conversion functions. +/// +/// **Why is this bad?** Rust's `as` keyword will perform many kinds of +/// conversions, including silently lossy conversions. Conversion functions such +/// as `i32::from` will only perform lossless conversions. Using the conversion +/// functions prevents conversions from turning into silent lossy conversions if +/// the types of the input expressions ever change, and make it easier for +/// people reading the code to know that the conversion is lossless. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn as_u64(x: u8) -> u64 { x as u64 } +/// ``` +declare_lint! { + pub CAST_LOSSLESS, + Allow, + "casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8`" +} + /// **What it does:** Checks for casts to the same type. /// /// **Why is this bad?** It's just unnecessary. @@ -560,6 +582,17 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t ); } +fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { + span_lint_and_sugg(cx, + CAST_LOSSLESS, + expr.span, + &format!("casting {} to {} may become silently lossy if types change", + cast_from, + cast_to), + "try", + format!("{}::from({})", cast_to, &snippet(cx, op.span, ".."))); +} + enum ArchSuffix { _32, _64, @@ -643,6 +676,16 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c } } +fn check_lossless(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { + let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); + let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); + let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); + if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && + from_nbits < to_nbits && !cast_signed_to_unsigned { + span_lossless_lint(cx, expr, op, cast_from, cast_to); + } +} + impl LintPass for CastPass { fn get_lints(&self) -> LintArray { lint_array!( @@ -650,6 +693,7 @@ impl LintPass for CastPass { CAST_SIGN_LOSS, CAST_POSSIBLE_TRUNCATION, CAST_POSSIBLE_WRAP, + CAST_LOSSLESS, UNNECESSARY_CAST ) } @@ -688,6 +732,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if is_isize_or_usize(cast_from) || from_nbits >= to_nbits { span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64); } + if from_nbits < to_nbits { + span_lossless_lint(cx, expr, ex, cast_from, cast_to); + } }, (false, true) => { span_lint( @@ -715,6 +762,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { ); } check_truncation_and_wrapping(cx, expr, cast_from, cast_to); + check_lossless(cx, expr, ex, cast_from, cast_to); }, (false, false) => { if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = @@ -727,6 +775,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { "casting f64 to f32 may truncate the value", ); } + if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = + (&cast_from.sty, &cast_to.sty) { + span_lossless_lint(cx, expr, ex, cast_from, cast_to); + } }, } } @@ -1233,20 +1285,20 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( match pre_cast_ty.sty { ty::TyInt(int_ty) => { Some(match int_ty { - IntTy::I8 => (FullInt::S(i8::min_value() as i128), FullInt::S(i8::max_value() as i128)), - IntTy::I16 => (FullInt::S(i16::min_value() as i128), FullInt::S(i16::max_value() as i128)), - IntTy::I32 => (FullInt::S(i32::min_value() as i128), FullInt::S(i32::max_value() as i128)), - IntTy::I64 => (FullInt::S(i64::min_value() as i128), FullInt::S(i64::max_value() as i128)), + IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), + IntTy::I16 => (FullInt::S(i128::from(i16::min_value())), FullInt::S(i128::from(i16::max_value()))), + IntTy::I32 => (FullInt::S(i128::from(i32::min_value())), FullInt::S(i128::from(i32::max_value()))), + IntTy::I64 => (FullInt::S(i128::from(i64::min_value())), FullInt::S(i128::from(i64::max_value()))), IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }) }, ty::TyUint(uint_ty) => { Some(match uint_ty { - UintTy::U8 => (FullInt::U(u8::min_value() as u128), FullInt::U(u8::max_value() as u128)), - UintTy::U16 => (FullInt::U(u16::min_value() as u128), FullInt::U(u16::max_value() as u128)), - UintTy::U32 => (FullInt::U(u32::min_value() as u128), FullInt::U(u32::max_value() as u128)), - UintTy::U64 => (FullInt::U(u64::min_value() as u128), FullInt::U(u64::max_value() as u128)), + UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), + UintTy::U16 => (FullInt::U(u128::from(u16::min_value())), FullInt::U(u128::from(u16::max_value()))), + UintTy::U32 => (FullInt::U(u128::from(u32::min_value())), FullInt::U(u128::from(u32::max_value()))), + UintTy::U64 => (FullInt::U(u128::from(u64::min_value())), FullInt::U(u128::from(u64::max_value()))), UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), }) diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index bacfaa74454..fd4c4e91c5d 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,7 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] -#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap)] +#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)] #[allow(no_effect, unnecessary_operation)] fn main() { // Test cast_precision_loss @@ -11,8 +11,6 @@ fn main() { 1u32 as f32; 1u64 as f32; 1u64 as f64; - 1i32 as f64; // Should not trigger the lint - 1u32 as f64; // Should not trigger the lint // Test cast_possible_truncation 1f32 as i32; 1f32 as u32; @@ -27,6 +25,38 @@ fn main() { 1u32 as i32; 1u64 as i64; 1usize as isize; + // Test cast_lossless with casts to integer types + 1i8 as i16; + 1i8 as i32; + 1i8 as i64; + 1u8 as i16; + 1u8 as i32; + 1u8 as i64; + 1u8 as u16; + 1u8 as u32; + 1u8 as u64; + 1i16 as i32; + 1i16 as i64; + 1u16 as i32; + 1u16 as i64; + 1u16 as u32; + 1u16 as u64; + 1i32 as i64; + 1u32 as i64; + 1u32 as u64; + // Test cast_lossless with casts to floating-point types + 1i8 as f32; + 1i8 as f64; + 1u8 as f32; + 1u8 as f64; + 1i16 as f32; + 1i16 as f64; + 1u16 as f32; + 1u16 as f64; + 1i32 as f64; + 1u32 as f64; + // Test cast_lossless with casts from floating-point types + 1.0f32 as f64; // Test cast_sign_loss 1i32 as u32; 1isize as usize; @@ -56,7 +86,6 @@ fn main() { false as bool; &1i32 as &i32; // Should not trigger - 1i32 as i64; let v = vec!(1); &v as &[i32]; 1.0 as f64; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index a2d6687ff60..de37be206d0 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -37,246 +37,422 @@ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f | ^^^^^^^^^^^ error: casting f32 to i32 may truncate the value - --> $DIR/cast.rs:17:5 + --> $DIR/cast.rs:15:5 | -17 | 1f32 as i32; +15 | 1f32 as i32; | ^^^^^^^^^^^ | = note: `-D cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value - --> $DIR/cast.rs:18:5 + --> $DIR/cast.rs:16:5 | -18 | 1f32 as u32; +16 | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value - --> $DIR/cast.rs:18:5 + --> $DIR/cast.rs:16:5 | -18 | 1f32 as u32; +16 | 1f32 as u32; | ^^^^^^^^^^^ | = note: `-D cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value - --> $DIR/cast.rs:19:5 + --> $DIR/cast.rs:17:5 | -19 | 1f64 as f32; +17 | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:18:5 | -20 | 1i32 as i8; +18 | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may lose the sign of the value - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:19:5 | -21 | 1i32 as u8; +19 | 1i32 as u8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:19:5 | -21 | 1i32 as u8; +19 | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value - --> $DIR/cast.rs:22:5 + --> $DIR/cast.rs:20:5 | -22 | 1f64 as isize; +20 | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:21:5 | -23 | 1f64 as usize; +21 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:21:5 | -23 | 1f64 as usize; +21 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:23:5 | -25 | 1u8 as i8; +23 | 1u8 as i8; | ^^^^^^^^^ | = note: `-D cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value - --> $DIR/cast.rs:26:5 + --> $DIR/cast.rs:24:5 | -26 | 1u16 as i16; +24 | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value - --> $DIR/cast.rs:27:5 + --> $DIR/cast.rs:25:5 | -27 | 1u32 as i32; +25 | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:26:5 | -28 | 1u64 as i64; +26 | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value - --> $DIR/cast.rs:29:5 + --> $DIR/cast.rs:27:5 | -29 | 1usize as isize; +27 | 1usize as isize; | ^^^^^^^^^^^^^^^ -error: casting i32 to u32 may lose the sign of the value +error: casting i8 to i16 may become silently lossy if types change + --> $DIR/cast.rs:29:5 + | +29 | 1i8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1i8)` + | + = note: `-D cast-lossless` implied by `-D warnings` + +error: casting i8 to i32 may become silently lossy if types change + --> $DIR/cast.rs:30:5 + | +30 | 1i8 as i32; + | ^^^^^^^^^^ help: try: `i32::from(1i8)` + +error: casting i8 to i64 may become silently lossy if types change --> $DIR/cast.rs:31:5 | -31 | 1i32 as u32; +31 | 1i8 as i64; + | ^^^^^^^^^^ help: try: `i64::from(1i8)` + +error: casting u8 to i16 may become silently lossy if types change + --> $DIR/cast.rs:32:5 + | +32 | 1u8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1u8)` + +error: casting u8 to i32 may become silently lossy if types change + --> $DIR/cast.rs:33:5 + | +33 | 1u8 as i32; + | ^^^^^^^^^^ help: try: `i32::from(1u8)` + +error: casting u8 to i64 may become silently lossy if types change + --> $DIR/cast.rs:34:5 + | +34 | 1u8 as i64; + | ^^^^^^^^^^ help: try: `i64::from(1u8)` + +error: casting u8 to u16 may become silently lossy if types change + --> $DIR/cast.rs:35:5 + | +35 | 1u8 as u16; + | ^^^^^^^^^^ help: try: `u16::from(1u8)` + +error: casting u8 to u32 may become silently lossy if types change + --> $DIR/cast.rs:36:5 + | +36 | 1u8 as u32; + | ^^^^^^^^^^ help: try: `u32::from(1u8)` + +error: casting u8 to u64 may become silently lossy if types change + --> $DIR/cast.rs:37:5 + | +37 | 1u8 as u64; + | ^^^^^^^^^^ help: try: `u64::from(1u8)` + +error: casting i16 to i32 may become silently lossy if types change + --> $DIR/cast.rs:38:5 + | +38 | 1i16 as i32; + | ^^^^^^^^^^^ help: try: `i32::from(1i16)` + +error: casting i16 to i64 may become silently lossy if types change + --> $DIR/cast.rs:39:5 + | +39 | 1i16 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1i16)` + +error: casting u16 to i32 may become silently lossy if types change + --> $DIR/cast.rs:40:5 + | +40 | 1u16 as i32; + | ^^^^^^^^^^^ help: try: `i32::from(1u16)` + +error: casting u16 to i64 may become silently lossy if types change + --> $DIR/cast.rs:41:5 + | +41 | 1u16 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1u16)` + +error: casting u16 to u32 may become silently lossy if types change + --> $DIR/cast.rs:42:5 + | +42 | 1u16 as u32; + | ^^^^^^^^^^^ help: try: `u32::from(1u16)` + +error: casting u16 to u64 may become silently lossy if types change + --> $DIR/cast.rs:43:5 + | +43 | 1u16 as u64; + | ^^^^^^^^^^^ help: try: `u64::from(1u16)` + +error: casting i32 to i64 may become silently lossy if types change + --> $DIR/cast.rs:44:5 + | +44 | 1i32 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1i32)` + +error: casting u32 to i64 may become silently lossy if types change + --> $DIR/cast.rs:45:5 + | +45 | 1u32 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1u32)` + +error: casting u32 to u64 may become silently lossy if types change + --> $DIR/cast.rs:46:5 + | +46 | 1u32 as u64; + | ^^^^^^^^^^^ help: try: `u64::from(1u32)` + +error: casting i8 to f32 may become silently lossy if types change + --> $DIR/cast.rs:48:5 + | +48 | 1i8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1i8)` + +error: casting i8 to f64 may become silently lossy if types change + --> $DIR/cast.rs:49:5 + | +49 | 1i8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1i8)` + +error: casting u8 to f32 may become silently lossy if types change + --> $DIR/cast.rs:50:5 + | +50 | 1u8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1u8)` + +error: casting u8 to f64 may become silently lossy if types change + --> $DIR/cast.rs:51:5 + | +51 | 1u8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1u8)` + +error: casting i16 to f32 may become silently lossy if types change + --> $DIR/cast.rs:52:5 + | +52 | 1i16 as f32; + | ^^^^^^^^^^^ help: try: `f32::from(1i16)` + +error: casting i16 to f64 may become silently lossy if types change + --> $DIR/cast.rs:53:5 + | +53 | 1i16 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1i16)` + +error: casting u16 to f32 may become silently lossy if types change + --> $DIR/cast.rs:54:5 + | +54 | 1u16 as f32; + | ^^^^^^^^^^^ help: try: `f32::from(1u16)` + +error: casting u16 to f64 may become silently lossy if types change + --> $DIR/cast.rs:55:5 + | +55 | 1u16 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1u16)` + +error: casting i32 to f64 may become silently lossy if types change + --> $DIR/cast.rs:56:5 + | +56 | 1i32 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1i32)` + +error: casting u32 to f64 may become silently lossy if types change + --> $DIR/cast.rs:57:5 + | +57 | 1u32 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1u32)` + +error: casting f32 to f64 may become silently lossy if types change + --> $DIR/cast.rs:59:5 + | +59 | 1.0f32 as f64; + | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` + +error: casting i32 to u32 may lose the sign of the value + --> $DIR/cast.rs:61:5 + | +61 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:32:5 + --> $DIR/cast.rs:62:5 | -32 | 1isize as usize; +62 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting isize to i8 may truncate the value - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:65:5 | -35 | 1isize as i8; +65 | 1isize as i8; | ^^^^^^^^^^^^ error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:36:5 + --> $DIR/cast.rs:66:5 | -36 | 1isize as f64; +66 | 1isize as f64; | ^^^^^^^^^^^^^ error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:67:5 | -37 | 1usize as f64; +67 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:38:5 + --> $DIR/cast.rs:68:5 | -38 | 1isize as f32; +68 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:39:5 + --> $DIR/cast.rs:69:5 | -39 | 1usize as f32; +69 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:40:5 + --> $DIR/cast.rs:70:5 | -40 | 1isize as i32; +70 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:71:5 | -41 | 1isize as u32; +71 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:71:5 | -41 | 1isize as u32; +71 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:42:5 + --> $DIR/cast.rs:72:5 | -42 | 1usize as u32; +72 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:73:5 | -43 | 1usize as i32; +73 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:73:5 | -43 | 1usize as i32; +73 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:45:5 + --> $DIR/cast.rs:75:5 | -45 | 1i64 as isize; +75 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast.rs:46:5 + --> $DIR/cast.rs:76:5 | -46 | 1i64 as usize; +76 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:46:5 + --> $DIR/cast.rs:76:5 | -46 | 1i64 as usize; +76 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:47:5 + --> $DIR/cast.rs:77:5 | -47 | 1u64 as isize; +77 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:47:5 + --> $DIR/cast.rs:77:5 | -47 | 1u64 as isize; +77 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:48:5 + --> $DIR/cast.rs:78:5 | -48 | 1u64 as usize; +78 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:49:5 + --> $DIR/cast.rs:79:5 | -49 | 1u32 as isize; +79 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast.rs:52:5 + --> $DIR/cast.rs:82:5 | -52 | 1i32 as usize; +82 | 1i32 as usize; | ^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:54:5 + --> $DIR/cast.rs:84:5 | -54 | 1i32 as i32; +84 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:55:5 + --> $DIR/cast.rs:85:5 | -55 | 1f32 as f32; +85 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:56:5 + --> $DIR/cast.rs:86:5 | -56 | false as bool; +86 | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 45 previous errors +error: aborting due to 74 previous errors -- cgit 1.4.1-3-g733a5 From 73d87d966da565bcd2b20f8d5793d4d7bb14cf61 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 18:16:16 +0200 Subject: Update tests to current rustc --- clippy_lints/src/lib.rs | 1 - rls.toml | 2 +- tests/ui/useless_attribute.rs | 2 +- tests/ui/useless_attribute.stderr | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c99df8acdfc..6b236ff516c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,7 +1,6 @@ // error-pattern:cargo-clippy #![feature(box_syntax)] -#![feature(alloc)] #![feature(custom_attribute)] #![feature(i128_type)] #![feature(i128)] diff --git a/rls.toml b/rls.toml index 62f1434c0ab..e3dfeeccd4a 100644 --- a/rls.toml +++ b/rls.toml @@ -1 +1 @@ -build_lib = true \ No newline at end of file +workspace_mode=true diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 332cc09cfea..cd2636a5b6f 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![warn(useless_attribute)] -#[allow(dead_code)] +#[allow(dead_code, unused_extern_crates)] extern crate clippy_lints; // don't lint on unused_import for `use` items diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 6d990ccf05b..707a11d55cc 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,8 +1,8 @@ error: useless lint attribute --> $DIR/useless_attribute.rs:5:1 | -5 | #[allow(dead_code)] - | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` +5 | #[allow(dead_code, unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code, unused_extern_crates)]` | = note: `-D useless-attribute` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From ec799707718bfeff98b874b748cda07e8f3ff704 Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Mon, 28 Aug 2017 23:13:56 +0200 Subject: len_without_is_empty false positive #1740 --- clippy_lints/src/len_zero.rs | 55 ++++++++++++++++++++++++++++++++++++-------- tests/ui/len_zero.rs | 10 ++++++++ tests/ui/len_zero.stderr | 30 ++++++++++++------------ 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 4e40348facf..fceffc4c665 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -2,6 +2,7 @@ use rustc::lint::*; use rustc::hir::def_id::DefId; use rustc::ty; use rustc::hir::*; +use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -88,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } } -fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef]) { +fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { @@ -102,18 +103,52 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef] } } - if !trait_items.iter().any(|i| is_named_self(cx, i, "is_empty")) { - if let Some(i) = trait_items.iter().find(|i| is_named_self(cx, i, "len")) { - if cx.access_levels.is_exported(i.id.node_id) { - span_lint( - cx, - LEN_WITHOUT_IS_EMPTY, - item.span, - &format!("trait `{}` has a `len` method but no `is_empty` method", item.name), - ); + // fill the set with current and super traits + fn fill_trait_set<'a, 'b: 'a>(traitt: &'b Item, set: &'a mut HashSet<&'b Item>, cx: &'b LateContext) { + if set.insert(traitt) { + if let ItemTrait(.., ref ty_param_bounds, _) = traitt.node { + for ty_param_bound in ty_param_bounds { + if let TraitTyParamBound(ref poly_trait_ref, _) = *ty_param_bound { + let super_trait_node_id = cx.tcx + .hir + .as_local_node_id(poly_trait_ref.trait_ref.path.def.def_id()) + .expect("the DefId is local, the NodeId should be available"); + let super_trait = cx.tcx.hir.expect_item(super_trait_node_id); + fill_trait_set(super_trait, set, cx); + } + } } } } + + if cx.access_levels.is_exported(visited_trait.id) && + trait_items + .iter() + .any(|i| is_named_self(cx, i, "len")) + { + let mut current_and_super_traits = HashSet::new(); + fill_trait_set(visited_trait, &mut current_and_super_traits, cx); + + let is_empty_method_found = current_and_super_traits + .iter() + .flat_map(|i| match i.node { + ItemTrait(.., ref trait_items) => trait_items.iter(), + _ => bug!("should only handle traits"), + }) + .any(|i| is_named_self(cx, i, "is_empty")); + + if !is_empty_method_found { + span_lint( + cx, + LEN_WITHOUT_IS_EMPTY, + visited_trait.span, + &format!( + "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method", + visited_trait.name + ), + ); + } + } } fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index c90e1193db1..e0e735a934b 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -125,6 +125,16 @@ impl HasWrongIsEmpty { } } +pub trait Empty { + fn is_empty(&self) -> bool; +} + +pub trait InheritingEmpty: Empty { //must not trigger LEN_WITHOUT_IS_EMPTY + fn len(&self) -> isize; +} + + + fn main() { let x = [1, 2]; if x.len() == 0 { diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 2c9edfe9b0e..5e3961808b8 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -10,7 +10,7 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` m | = note: `-D len-without-is-empty` implied by `-D warnings` -error: trait `PubTraitsToo` has a `len` method but no `is_empty` method +error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method --> $DIR/len_zero.rs:55:1 | 55 | / pub trait PubTraitsToo { @@ -43,47 +43,47 @@ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:130:8 + --> $DIR/len_zero.rs:140:8 | -130 | if x.len() == 0 { +140 | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `x.is_empty()` | = note: `-D len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:134:8 + --> $DIR/len_zero.rs:144:8 | -134 | if "".len() == 0 { +144 | if "".len() == 0 { | ^^^^^^^^^^^^^ help: using `is_empty` is more concise: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:148:8 + --> $DIR/len_zero.rs:158:8 | -148 | if has_is_empty.len() == 0 { +158 | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:151:8 + --> $DIR/len_zero.rs:161:8 | -151 | if has_is_empty.len() != 0 { +161 | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:154:8 + --> $DIR/len_zero.rs:164:8 | -154 | if has_is_empty.len() > 0 { +164 | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:160:8 + --> $DIR/len_zero.rs:170:8 | -160 | if with_is_empty.len() == 0 { +170 | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:172:8 + --> $DIR/len_zero.rs:182:8 | -172 | if b.len() != 0 { +182 | if b.len() != 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 1ea70116d389699400545c6200c38345b1eceeb7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 29 Aug 2017 05:48:19 -0700 Subject: Enable the cast_lossless warning by default. --- README.md | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/types.rs | 2 +- tests/ui/absurd-extreme-comparisons.rs | 4 ++-- tests/ui/float_cmp.rs | 2 +- tests/ui/invalid_upcast_comparisons.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 01c4a89e149..9f2a0128c5a 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ name [box_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap [boxed_local](https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary [builtin_type_shadow](https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type -[cast_lossless](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless) | allow | casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8` +[cast_lossless](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless) | warn | casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8` [cast_possible_truncation](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32` [cast_possible_wrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX` [cast_precision_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g. `x as f32` where `x: u64` diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ef8bff92c07..19b8816cd1e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -358,7 +358,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { shadow::SHADOW_UNRELATED, strings::STRING_ADD, strings::STRING_ADD_ASSIGN, - types::CAST_LOSSLESS, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, types::CAST_PRECISION_LOSS, @@ -530,6 +529,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, + types::CAST_LOSSLESS, types::CHAR_LIT_AS_U8, types::LET_UNIT_VALUE, types::LINKEDLIST, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9612c670ff0..29a7bb75011 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -499,7 +499,7 @@ declare_lint! { /// ``` declare_lint! { pub CAST_LOSSLESS, - Allow, + Warn, "casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8`" } diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index 87c49f88573..ad381c6cd49 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -38,12 +38,12 @@ pub struct U(u64); impl PartialEq for U { fn eq(&self, other: &u32) -> bool { - self.eq(&U(*other as u64)) + self.eq(&U(u64::from(*other))) } } impl PartialOrd for U { fn partial_cmp(&self, other: &u32) -> Option { - self.partial_cmp(&U(*other as u64)) + self.partial_cmp(&U(u64::from(*other))) } } diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 47d29a42183..f3f66f3c9c5 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![warn(float_cmp)] -#![allow(unused, no_effect, unnecessary_operation)] +#![allow(unused, no_effect, unnecessary_operation, cast_lossless)] use std::ops::Add; diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index de606902e72..8d8e7bd8de1 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -2,7 +2,7 @@ #![plugin(clippy)] #![warn(invalid_upcast_comparisons)] -#![allow(unused, eq_op, no_effect, unnecessary_operation)] +#![allow(unused, eq_op, no_effect, unnecessary_operation, cast_lossless)] fn mk_value() -> T { unimplemented!() } -- cgit 1.4.1-3-g733a5 From 9d6c0feef237d0e6155d6d38e81cd4fbfe743b65 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 Aug 2017 10:54:24 +0200 Subject: Rustup (fixes #2002) --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 6 +++--- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/utils/author.rs | 10 ++++++++-- clippy_lints/src/utils/hir_utils.rs | 9 +++++++-- clippy_lints/src/utils/inspector.rs | 6 +++++- clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/utils/sugg.rs | 4 +++- 16 files changed, 40 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c0766fe21..0ca049007a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.155 +* Update to *rustc 1.21.0-nightly (c11f689d2 2017-08-29)* +* New lint: [`infinite_iter`], [`maybe_infinite_iter`], [`cast_lossless`] ## 0.0.154 * Update to *rustc 1.21.0-nightly (2c0558f63 2017-08-24)* diff --git a/Cargo.toml b/Cargo.toml index 914d453ebf8..6ecfa3dfe50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.154" +version = "0.0.155" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.154", path = "clippy_lints" } +clippy_lints = { version = "0.0.155", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 8cdbbaaecf5..7aae50a4745 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.154" +version = "0.0.155" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index eea44393e3d..82a3eb00ab7 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -56,7 +56,7 @@ struct ExVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if let ExprClosure(_, _, eid, _) = expr.node { + if let ExprClosure(_, _, eid, _, _) = expr.node { let body = self.cx.tcx.hir.body(eid); let ex = &body.value; if matches!(ex.node, ExprBlock(_)) { diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index cbd0c6d20d5..a3a53b6dd47 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node, filter.name == "filter", filter_args.len() == 2, - let ExprClosure(_, _, body_id, _) = filter_args[1].node, + let ExprClosure(_, _, body_id, _, _) = filter_args[1].node, ], { let body = cx.tcx.hir.body(body_id); if_let_chain!([ diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 9596e9812ad..edfa5e0fb61 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { _ => (), } }, - ExprClosure(..) => (), + ExprClosure(.., _) => (), ExprBinary(op, _, _) => { walk_expr(self, e); match op.node { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index b5667db920c..42524da7ffc 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { } fn check_closure(cx: &LateContext, expr: &Expr) { - if let ExprClosure(_, ref decl, eid, _) = expr.node { + if let ExprClosure(_, ref decl, eid, _, _) = expr.node { let body = cx.tcx.hir.body(eid); let ex = &body.value; if let ExprCall(ref caller, ref args) = ex.node { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 549b621812d..db952cd5d98 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -104,7 +104,7 @@ struct DivergenceVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { fn maybe_walk_expr(&mut self, e: &'tcx Expr) { match e.node { - ExprClosure(..) => {}, + ExprClosure(.., _) => {}, ExprMatch(ref e, ref arms, _) => { self.visit_expr(e); for arm in arms { @@ -239,7 +239,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St walk_expr(vis, expr); } }, - ExprClosure(_, _, _, _) => { + ExprClosure(_, _, _, _, _) => { // Either // // * `var` is defined in the closure body, in which case we've @@ -323,7 +323,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { // We're about to descend a closure. Since we don't know when (or // if) the closure will be evaluated, any reads in it might not // occur here (or ever). Like above, bail to avoid false positives. - ExprClosure(_, _, _, _) | + ExprClosure(_, _, _, _, _) | // We want to avoid a false positive when a variable name occurs // only to have its address taken, so we stop here. Technically, diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 72ff75dd994..53f74c7afd6 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -148,7 +148,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { } } if method.name == "flat_map" && args.len() == 2 { - if let ExprClosure(_, _, body_id, _) = args[1].node { + if let ExprClosure(_, _, body_id, _, _) = args[1].node { let body = cx.tcx.hir.body(body_id); return is_infinite(cx, &body.value); } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index fcb84e90eb6..f0e19a3b577 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMethodCall(ref method, _, ref args) = expr.node { if method.name == "map" && args.len() == 2 { match args[1].node { - ExprClosure(_, ref decl, closure_eid, _) => { + ExprClosure(_, ref decl, closure_eid, _, _) => { let body = cx.tcx.hir.body(closure_eid); let closure_expr = remove_blocks(&body.value); let ty = cx.tables.pat_ty(&body.arguments[0].pat); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 782b4033645..971309adb33 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -46,7 +46,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } match expr.node { Expr_::ExprLit(..) | - Expr_::ExprClosure(..) | + Expr_::ExprClosure(.., _) | Expr_::ExprPath(..) => true, Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index ba8f0022b32..dfac7366553 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -296,10 +296,16 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Match(ref expr, ref arms, ref desugaring) = {},", current); println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); }, - Expr_::ExprClosure(ref _capture_clause, ref _func, _, _) => { - println!("Closure(ref capture_clause, ref func, _, _) = {},", current); + Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { + println!("Closure(ref capture_clause, ref func, _, _, _) = {},", current); println!(" // unimplemented: `ExprClosure` is not further destructured at the moment"); }, + Expr_::ExprYield(ref sub) => { + let sub_pat = self.next("sub"); + println!("Yield(ref sub) = {},", current); + self.current = sub_pat; + self.visit_expr(sub); + }, Expr_::ExprBlock(ref block) => { let block_pat = self.next("block"); println!("Block(ref {}) = {},", block_pat, current); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 4890bb81dc3..2a4439c4608 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -321,6 +321,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_name(&i.node.name); } }, + ExprYield(ref e) => { + let c: fn(_) -> _ = ExprYield; + c.hash(&mut self.s); + self.hash_expr(e); + }, ExprAssign(ref l, ref r) => { let c: fn(_, _) -> _ = ExprAssign; c.hash(&mut self.s); @@ -373,8 +378,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); // TODO: _ty }, - ExprClosure(cap, _, eid, _) => { - let c: fn(_, _, _, _) -> _ = ExprClosure; + ExprClosure(cap, _, eid, _, _) => { + let c: fn(_, _, _, _, _) -> _ = ExprClosure; c.hash(&mut self.s); cap.hash(&mut self.s); self.hash_expr(&self.cx.tcx.hir.body(eid).value); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 7b06190b2db..081b7ac277a 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -245,10 +245,14 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, cond, indent + 1); println!("{}source: {:?}", ind, source); }, - hir::ExprClosure(ref clause, _, _, _) => { + hir::ExprClosure(ref clause, _, _, _, _) => { println!("{}Closure", ind); println!("{}clause: {:?}", ind, clause); }, + hir::ExprYield(ref sub) => { + println!("{}Yield", ind); + print_expr(cx, sub, indent + 1); + } hir::ExprBlock(_) => { println!("{}Block", ind); }, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c08f7d4254f..9b14dd125ba 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -104,6 +104,7 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { let parent_id = cx.tcx.hir.get_parent(id); match MirSource::from_node(cx.tcx, parent_id) { + MirSource::GeneratorDrop(_) | MirSource::Fn(_) => false, MirSource::Const(_) | MirSource::Static(..) | diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 6cfbe8c935e..1c2e07960cb 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -49,11 +49,12 @@ impl<'a> Sugg<'a> { match expr.node { hir::ExprAddrOf(..) | hir::ExprBox(..) | - hir::ExprClosure(..) | + hir::ExprClosure(.., _) | hir::ExprIf(..) | hir::ExprUnary(..) | hir::ExprMatch(..) => Sugg::MaybeParen(snippet), hir::ExprAgain(..) | + hir::ExprYield(..) | hir::ExprArray(..) | hir::ExprBlock(..) | hir::ExprBreak(..) | @@ -106,6 +107,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::Call(..) | ast::ExprKind::Catch(..) | ast::ExprKind::Continue(..) | + ast::ExprKind::Yield(..) | ast::ExprKind::Field(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Index(..) | -- cgit 1.4.1-3-g733a5 From a8cf4e8ecb0b676ff6895b8ecd90f53f866cd676 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 31 Aug 2017 14:47:45 +0200 Subject: Accessing `Span` internals is deprecated --- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/doc.rs | 25 +++++---------- clippy_lints/src/formatting.rs | 37 ++++------------------ .../src/if_let_redundant_pattern_matching.rs | 10 +++--- clippy_lints/src/let_if_seq.rs | 3 +- clippy_lints/src/methods.rs | 4 +-- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/regex.rs | 10 +++--- clippy_lints/src/swap.rs | 5 ++- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 10 +++--- clippy_lints/src/utils/sugg.rs | 12 ++----- clippy_lints/src/vec.rs | 8 ++--- 13 files changed, 42 insertions(+), 88 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 54b6490a183..1914b83e898 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -126,7 +126,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast: let Some(inner) = expr_block(then), let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node, ], { - if expr.span.ctxt != inner.span.ctxt { + if expr.span.ctxt() != inner.span.ctxt() { return; } span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index c366e17d85f..f72a13147dc 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -96,10 +96,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( vec![ ( doc.len(), - Span { - lo: span.lo + BytePos(prefix.len() as u32), - ..span - } + span.with_lo(span.lo() + BytePos(prefix.len() as u32)), ), ], ); @@ -117,10 +114,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( // +1 for the newline sizes.push(( line.len() + 1, - Span { - lo: span.lo + BytePos(offset as u32), - ..span - }, + span.with_lo(span.lo() + BytePos(offset as u32)), )); } if !contains_initial_stars { @@ -228,10 +222,7 @@ fn check_doc<'a, Events: Iterator)>>( let (begin, span) = spans[index]; // Adjust for the begining of the current `Event` - let span = Span { - lo: span.lo + BytePos::from_usize(offset - begin), - ..span - }; + let span = span.with_lo(span.lo() + BytePos::from_usize(offset - begin)); check_text(cx, valid_idents, &text, span); } @@ -253,11 +244,11 @@ fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span // Adjust for the current word let offset = word.as_ptr() as usize - text.as_ptr() as usize; - let span = Span { - lo: span.lo + BytePos::from_usize(offset), - hi: span.lo + BytePos::from_usize(offset + word.len()), - ..span - }; + let span = Span::new( + span.lo() + BytePos::from_usize(offset), + span.lo() + BytePos::from_usize(offset + word.len()), + span.ctxt(), + ); check_word(cx, word, span); } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index c478974a5bd..e3b3bb408b3 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use syntax::ast; -use syntax_pos::{Span, NO_EXPANSION}; use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use syntax::ptr::P; @@ -106,19 +105,11 @@ impl EarlyLintPass for Formatting { fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(lhs.span) { - let eq_span = Span { - lo: lhs.span.hi, - hi: rhs.span.lo, - ctxt: NO_EXPANSION, - }; + let eq_span = lhs.span.between(rhs.span); if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node { if let Some(eq_snippet) = snippet_opt(cx, eq_span) { let op = ast::UnOp::to_string(op); - let eqop_span = Span { - lo: lhs.span.hi, - hi: sub_rhs.span.lo, - ctxt: NO_EXPANSION, - }; + let eqop_span = lhs.span.between(sub_rhs.span); if eq_snippet.ends_with('=') { span_note_and_lint( cx, @@ -146,11 +137,7 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { // this will be a span from the closing ‘}’ of the “then” block (excluding) to // the // “if” of the “else if” block (excluding) - let else_span = Span { - lo: then.span.hi, - hi: else_.span.lo, - ctxt: NO_EXPANSION, - }; + let else_span = then.span.between(else_.span); // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” @@ -181,17 +168,9 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) { for element in array { if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node { if !differing_macro_contexts(lhs.span, op.span) { - let space_span = Span { - lo: lhs.span.hi, - hi: op.span.lo, - ctxt: NO_EXPANSION, - }; + let space_span = lhs.span.between(op.span); if let Some(space_snippet) = snippet_opt(cx, space_span) { - let lint_span = Span { - lo: lhs.span.hi, - hi: lhs.span.hi, - ctxt: NO_EXPANSION, - }; + let lint_span = lhs.span.with_lo(lhs.span.hi()); if space_snippet.contains('\n') { span_note_and_lint( cx, @@ -215,11 +194,7 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp unsugar_if(second).is_some() { // where the else would be - let else_span = Span { - lo: first.span.hi, - hi: second.span.lo, - ctxt: NO_EXPANSION, - }; + let else_span = first.span.between(second.span); if let Some(else_snippet) = snippet_opt(cx, else_span) { if !else_snippet.contains('\n') { diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 0e1dd6449ab..904d3e9e2af 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -74,11 +74,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { arms[0].pats[0].span, &format!("redundant pattern matching, consider using `{}`", good_method), |db| { - let span = Span { - lo: expr.span.lo, - hi: op.span.hi, - ctxt: expr.span.ctxt, - }; + let span = Span::new( + expr.span.lo(), + op.span.hi(), + expr.span.ctxt(), + ); db.span_suggestion(span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method)); }); } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 64ba8adafe2..9812c759109 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::BindingAnnotation; -use syntax_pos::{Span, NO_EXPANSION}; use utils::{snippet, span_lint_and_then}; /// **What it does:** Checks for variable declarations immediately followed by a @@ -74,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { let Some(value) = check_assign(cx, def_id, &*then), !used_in_expr(cx, def_id, value), ], { - let span = Span { lo: stmt.span.lo, hi: if_.span.hi, ctxt: NO_EXPANSION }; + let span = stmt.span.to(if_.span); let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { if let hir::ExprBlock(ref else_) = else_.node { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 8d28789e737..c47af20e148 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1092,7 +1092,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] // lint, with note if neither arg is > 1 line and both map() and // unwrap_or() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt; + let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); if same_span && !multiline { span_note_and_lint( cx, @@ -1125,7 +1125,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &[hir:: // lint, with note if neither arg is > 1 line and both map() and // unwrap_or_else() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt; + let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); if same_span && !multiline { span_note_and_lint( cx, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 4e3cb667122..e7c3fb895fb 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -567,7 +567,7 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { /// generated by /// `#[derive(...)`] or the like). fn in_attributes_expansion(expr: &Expr) -> bool { - expr.span.ctxt.outer().expn_info().map_or( + expr.span.ctxt().outer().expn_info().map_or( false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)), ) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 4241dd94ac9..2ee33013791 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -140,11 +140,11 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { match (si.next(), si.next()) { (Some((l, _)), Some((h, _))) => { - Span { - lo: base.lo + BytePos(l as u32), - hi: base.lo + BytePos(h as u32), - ..base - } + Span::new( + base.lo() + BytePos(l as u32), + base.lo() + BytePos(h as u32), + base.ctxt(), + ) }, _ => base, } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index e17170db192..6119e5008f3 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -3,7 +3,6 @@ use rustc::lint::*; use rustc::ty; use utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use utils::sugg::Sugg; -use syntax_pos::{Span, NO_EXPANSION}; /// **What it does:** Checks for manual swapping. /// @@ -122,7 +121,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { (true, "".to_owned(), "".to_owned()) }; - let span = Span { lo: w[0].span.lo, hi: second.span.hi, ctxt: NO_EXPANSION}; + let span = w[0].span.to(second.span); span_lint_and_then(cx, MANUAL_SWAP, @@ -161,7 +160,7 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { ("".to_owned(), "".to_owned(), "".to_owned()) }; - let span = Span{ lo: first.span.lo, hi: second.span.hi, ctxt: NO_EXPANSION}; + let span = first.span.to(second.span); span_lint_and_then(cx, ALMOST_SWAPPED, diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index d83e094212a..a2832ef7af2 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -137,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { // Therefore, we need to climb the macro expansion tree and find the // actual span that invoked `declare_lint!`: let lint_span = lint_span - .ctxt + .ctxt() .outer() .expn_info() .map(|ei| ei.call_site) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9b14dd125ba..a0ee741d1dd 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -98,7 +98,7 @@ pub mod higher; /// from a macro and one /// isn't). pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { - rhs.ctxt != lhs.ctxt + rhs.ctxt() != lhs.ctxt() } pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { @@ -114,7 +114,7 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { - span.ctxt.outer().expn_info().map_or(false, |info| { + span.ctxt().outer().expn_info().map_or(false, |info| { match info.callee.format {// don't treat range expressions desugared to structs as "in_macro" ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, _ => true, @@ -147,7 +147,7 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { }) } - span.ctxt.outer().expn_info().map_or(false, |info| { + span.ctxt().outer().expn_info().map_or(false, |info| { in_macro_ext(cx, &info) }) } @@ -740,7 +740,7 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt.outer().expn_info().map(|ei| { + let span_name_span = span.ctxt().outer().expn_info().map(|ei| { (ei.callee.name(), ei.call_site) }); @@ -762,7 +762,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt.outer().expn_info().map(|ei| { + let span_name_span = span.ctxt().outer().expn_info().map(|ei| { (ei.callee.name(), ei.call_site) }); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 1c2e07960cb..4dc2314accb 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -392,7 +392,7 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// Return the indentation before `span` if there are nothing but `[ \t]` /// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { - let lo = cx.sess().codemap().lookup_char_pos(span.lo); + let lo = cx.sess().codemap().lookup_char_pos(span.lo()); if let Some(line) = lo.file.get_line( lo.line - 1, /* line numbers in `Loc` are 1-based */ ) @@ -443,10 +443,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D) { if let Some(indent) = indentation(cx, item) { - let span = Span { - hi: item.lo, - ..item - }; + let span = item.with_hi(item.lo()); self.span_suggestion(span, msg, format!("{}\n{}", attr, indent)); } @@ -454,10 +451,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) { if let Some(indent) = indentation(cx, item) { - let span = Span { - hi: item.lo, - ..item - }; + let span = item.with_hi(item.lo()); let mut first = true; let new_item = new_item diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index c864c9d2aeb..95f3c913dac 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))), ], { // report the error around the `vec!` not inside `:` - let span = arg.span.ctxt.outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); + let span = arg.span.ctxt().outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); check_vec_macro(cx, &vec_args, span); }} } @@ -74,11 +74,7 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { }, higher::VecArgs::Vec(args) => { if let Some(last) = args.iter().last() { - let span = Span { - lo: args[0].span.lo, - hi: last.span.hi, - ctxt: args[0].span.ctxt, - }; + let span = args[0].span.to(last.span); format!("&[{}]", snippet(cx, span, "..")).into() } else { -- cgit 1.4.1-3-g733a5 From 755a236641840a7c071db458c5dbf8afc5debdde Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 31 Aug 2017 14:58:18 +0200 Subject: Get rid of another handwritten Span construtor in favour of a builtin function --- clippy_lints/src/if_let_redundant_pattern_matching.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 904d3e9e2af..36411b73a62 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use rustc::hir::*; -use syntax::codemap::Span; use utils::{paths, span_lint_and_then, match_qpath, snippet}; /// **What it does:*** Lint for redundant pattern matching over `Result` or @@ -74,11 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { arms[0].pats[0].span, &format!("redundant pattern matching, consider using `{}`", good_method), |db| { - let span = Span::new( - expr.span.lo(), - op.span.hi(), - expr.span.ctxt(), - ); + let span = expr.span.with_hi(op.span.hi()); db.span_suggestion(span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method)); }); } -- cgit 1.4.1-3-g733a5 From c64073b2f5b3a548b9a5a4a1492118d5bd149ffa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 31 Aug 2017 15:38:24 +0200 Subject: Deprecate the wiki and remove the lint list from the README (fixes #1933) --- CHANGELOG.md | 430 ++++++++++----------- PUBLISH.md | 6 - README.md | 213 +--------- clippy_lints/src/utils/mod.rs | 2 +- clippy_tests/examples/needless_borrowed_ref.rs | 48 --- clippy_tests/examples/needless_borrowed_ref.stderr | 38 -- tests/ui/needless_borrowed_ref.rs | 48 +++ tests/ui/needless_borrowed_ref.stderr | 28 ++ util/update_lints.py | 25 +- util/update_wiki.py | 95 ----- 10 files changed, 295 insertions(+), 638 deletions(-) delete mode 100644 clippy_tests/examples/needless_borrowed_ref.rs delete mode 100644 clippy_tests/examples/needless_borrowed_ref.stderr create mode 100644 tests/ui/needless_borrowed_ref.rs create mode 100644 tests/ui/needless_borrowed_ref.stderr delete mode 100755 util/update_wiki.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca049007a6..5dd295708e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -415,219 +415,219 @@ All notable changes to this project will be documented in this file. [configuration file]: ./rust-clippy#configuration -[`absurd_extreme_comparisons`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#absurd_extreme_comparisons -[`almost_swapped`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#almost_swapped -[`approx_constant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#approx_constant -[`assign_op_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_op_pattern -[`assign_ops`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_ops -[`bad_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#bad_bit_mask -[`blacklisted_name`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#blacklisted_name -[`block_in_if_condition_expr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_expr -[`block_in_if_condition_stmt`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_stmt -[`bool_comparison`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#bool_comparison -[`borrowed_box`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#borrowed_box -[`box_vec`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec -[`boxed_local`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local -[`builtin_type_shadow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow -[`cast_lossless`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless -[`cast_possible_truncation`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation -[`cast_possible_wrap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap -[`cast_precision_loss`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss -[`cast_sign_loss`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_sign_loss -[`char_lit_as_u8`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#char_lit_as_u8 -[`chars_next_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#chars_next_cmp -[`clone_double_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_double_ref -[`clone_on_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_on_copy -[`cmp_nan`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_nan -[`cmp_null`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_null -[`cmp_owned`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_owned -[`collapsible_if`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#collapsible_if -[`crosspointer_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#crosspointer_transmute -[`cyclomatic_complexity`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#cyclomatic_complexity -[`deprecated_semver`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#deprecated_semver -[`deref_addrof`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#deref_addrof -[`derive_hash_xor_eq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#derive_hash_xor_eq -[`diverging_sub_expression`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#diverging_sub_expression -[`doc_markdown`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#doc_markdown -[`double_neg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#double_neg -[`double_parens`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#double_parens -[`drop_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_copy -[`drop_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_ref -[`duplicate_underscore_argument`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#duplicate_underscore_argument -[`empty_enum`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_enum -[`empty_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_loop -[`enum_clike_unportable_variant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_clike_unportable_variant -[`enum_glob_use`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_glob_use -[`enum_variant_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_variant_names -[`eq_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#eq_op -[`eval_order_dependence`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#eval_order_dependence -[`expl_impl_clone_on_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#expl_impl_clone_on_copy -[`explicit_counter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_counter_loop -[`explicit_into_iter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_into_iter_loop -[`explicit_iter_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_iter_loop -[`extend_from_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#extend_from_slice -[`filter_map`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_map -[`filter_next`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_next -[`float_arithmetic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#float_arithmetic -[`float_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#float_cmp -[`for_kv_map`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_kv_map -[`for_loop_over_option`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_option -[`for_loop_over_result`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_result -[`forget_copy`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_copy -[`forget_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_ref -[`get_unwrap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#get_unwrap -[`identity_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#identity_op -[`if_let_redundant_pattern_matching`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_redundant_pattern_matching -[`if_let_some_result`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_some_result -[`if_not_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_not_else -[`if_same_then_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#if_same_then_else -[`ifs_same_cond`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ifs_same_cond -[`inconsistent_digit_grouping`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping -[`indexing_slicing`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing -[`ineffective_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask -[`infinite_iter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#infinite_iter -[`inline_always`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always -[`integer_arithmetic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic -[`invalid_regex`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex -[`invalid_upcast_comparisons`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_upcast_comparisons -[`items_after_statements`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#items_after_statements -[`iter_cloned_collect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_cloned_collect -[`iter_next_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_next_loop -[`iter_nth`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_nth -[`iter_skip_next`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_skip_next -[`iterator_step_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#iterator_step_by_zero -[`large_digit_groups`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#large_digit_groups -[`large_enum_variant`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#large_enum_variant -[`len_without_is_empty`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#len_without_is_empty -[`len_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#len_zero -[`let_and_return`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#let_and_return -[`let_unit_value`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#let_unit_value -[`linkedlist`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#linkedlist -[`logic_bug`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#logic_bug -[`manual_swap`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#manual_swap -[`many_single_char_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#many_single_char_names -[`map_clone`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#map_clone -[`map_entry`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#map_entry -[`match_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_bool -[`match_overlapping_arm`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_overlapping_arm -[`match_ref_pats`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats -[`match_same_arms`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms -[`match_wild_err_arm`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm -[`maybe_infinite_iter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#maybe_infinite_iter -[`mem_forget`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget -[`min_max`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max -[`misrefactored_assign_op`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op -[`missing_docs_in_private_items`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#missing_docs_in_private_items -[`mixed_case_hex_literals`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mixed_case_hex_literals -[`module_inception`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#module_inception -[`modulo_one`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#modulo_one -[`mut_from_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_from_ref -[`mut_mut`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut -[`mutex_atomic`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic -[`mutex_integer`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer -[`naive_bytecount`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#naive_bytecount -[`needless_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool -[`needless_borrow`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow -[`needless_borrowed_reference`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference -[`needless_continue`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_continue -[`needless_lifetimes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_lifetimes -[`needless_pass_by_value`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_pass_by_value -[`needless_range_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_range_loop -[`needless_return`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_return -[`needless_update`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_update -[`neg_multiply`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#neg_multiply -[`never_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#never_loop -[`new_ret_no_self`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_ret_no_self -[`new_without_default`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default -[`new_without_default_derive`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default_derive -[`no_effect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#no_effect -[`non_ascii_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#non_ascii_literal -[`nonminimal_bool`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#nonminimal_bool -[`nonsensical_open_options`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#nonsensical_open_options -[`not_unsafe_ptr_arg_deref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#not_unsafe_ptr_arg_deref -[`ok_expect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ok_expect -[`op_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#op_ref -[`option_map_unwrap_or`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or -[`option_map_unwrap_or_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or_else -[`option_unwrap_used`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#option_unwrap_used -[`or_fun_call`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#or_fun_call -[`out_of_bounds_indexing`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#out_of_bounds_indexing -[`overflow_check_conditional`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#overflow_check_conditional -[`panic_params`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#panic_params -[`partialeq_ne_impl`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#partialeq_ne_impl -[`possible_missing_comma`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#possible_missing_comma -[`precedence`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#precedence -[`print_stdout`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#print_stdout -[`print_with_newline`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#print_with_newline -[`ptr_arg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#ptr_arg -[`pub_enum_variant_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#pub_enum_variant_names -[`range_step_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#range_step_by_zero -[`range_zip_with_len`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#range_zip_with_len -[`redundant_closure`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure -[`redundant_closure_call`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure_call -[`redundant_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_pattern -[`regex_macro`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#regex_macro -[`result_unwrap_used`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#result_unwrap_used -[`reverse_range_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#reverse_range_loop -[`search_is_some`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#search_is_some -[`serde_api_misuse`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#serde_api_misuse -[`shadow_reuse`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_reuse -[`shadow_same`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_same -[`shadow_unrelated`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_unrelated -[`short_circuit_statement`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#short_circuit_statement -[`should_assert_eq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#should_assert_eq -[`should_implement_trait`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#should_implement_trait -[`similar_names`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#similar_names -[`single_char_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_char_pattern -[`single_match`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match -[`single_match_else`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match_else -[`str_to_string`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#str_to_string -[`string_add`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add -[`string_add_assign`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add_assign -[`string_extend_chars`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_extend_chars -[`string_lit_as_bytes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_lit_as_bytes -[`string_to_string`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#string_to_string -[`stutter`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#stutter -[`suspicious_assignment_formatting`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_assignment_formatting -[`suspicious_else_formatting`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_else_formatting -[`temporary_assignment`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_assignment -[`temporary_cstring_as_ptr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_cstring_as_ptr -[`too_many_arguments`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#too_many_arguments -[`toplevel_ref_arg`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#toplevel_ref_arg -[`transmute_ptr_to_ref`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#transmute_ptr_to_ref -[`trivial_regex`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#trivial_regex -[`type_complexity`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#type_complexity -[`unicode_not_nfc`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unicode_not_nfc -[`unit_cmp`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unit_cmp -[`unnecessary_cast`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_cast -[`unnecessary_mut_passed`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_mut_passed -[`unnecessary_operation`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_operation -[`unneeded_field_pattern`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unneeded_field_pattern -[`unreadable_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unreadable_literal -[`unsafe_removed_from_name`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unsafe_removed_from_name -[`unseparated_literal_suffix`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unseparated_literal_suffix -[`unstable_as_mut_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unstable_as_mut_slice -[`unstable_as_slice`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unstable_as_slice -[`unused_collect`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_collect -[`unused_io_amount`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_io_amount -[`unused_label`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label -[`unused_lifetimes`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes -[`use_debug`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug -[`use_self`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#use_self -[`used_underscore_binding`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding -[`useless_attribute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute -[`useless_format`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format -[`useless_let_if_seq`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_let_if_seq -[`useless_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_transmute -[`useless_vec`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_vec -[`verbose_bit_mask`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#verbose_bit_mask -[`while_let_loop`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_loop -[`while_let_on_iterator`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_on_iterator -[`wrong_pub_self_convention`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_pub_self_convention -[`wrong_self_convention`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_self_convention -[`wrong_transmute`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_transmute -[`zero_divided_by_zero`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_divided_by_zero -[`zero_prefixed_literal`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_prefixed_literal -[`zero_ptr`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_ptr -[`zero_width_space`]: https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_width_space +[`absurd_extreme_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons +[`almost_swapped`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#almost_swapped +[`approx_constant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant +[`assign_op_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#assign_op_pattern +[`assign_ops`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#assign_ops +[`bad_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#bad_bit_mask +[`blacklisted_name`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#blacklisted_name +[`block_in_if_condition_expr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_expr +[`block_in_if_condition_stmt`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt +[`bool_comparison`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#bool_comparison +[`borrowed_box`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#borrowed_box +[`box_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#box_vec +[`boxed_local`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#boxed_local +[`builtin_type_shadow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#builtin_type_shadow +[`cast_lossless`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_lossless +[`cast_possible_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_truncation +[`cast_possible_wrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_wrap +[`cast_precision_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_precision_loss +[`cast_sign_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_sign_loss +[`char_lit_as_u8`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#char_lit_as_u8 +[`chars_next_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_next_cmp +[`clone_double_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_double_ref +[`clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_copy +[`cmp_nan`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_nan +[`cmp_null`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_null +[`cmp_owned`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_owned +[`collapsible_if`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#collapsible_if +[`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute +[`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity +[`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver +[`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof +[`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq +[`diverging_sub_expression`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_markdown`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#doc_markdown +[`double_neg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_neg +[`double_parens`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_parens +[`drop_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_copy +[`drop_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_ref +[`duplicate_underscore_argument`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duplicate_underscore_argument +[`empty_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum +[`empty_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_loop +[`enum_clike_unportable_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant +[`enum_glob_use`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_glob_use +[`enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_variant_names +[`eq_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eq_op +[`eval_order_dependence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eval_order_dependence +[`expl_impl_clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy +[`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop +[`explicit_into_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_into_iter_loop +[`explicit_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_iter_loop +[`extend_from_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extend_from_slice +[`filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_map +[`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next +[`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic +[`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp +[`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map +[`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option +[`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result +[`forget_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_copy +[`forget_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_ref +[`get_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#get_unwrap +[`identity_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#identity_op +[`if_let_redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching +[`if_let_some_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_some_result +[`if_not_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_not_else +[`if_same_then_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_same_then_else +[`ifs_same_cond`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ifs_same_cond +[`inconsistent_digit_grouping`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping +[`indexing_slicing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#indexing_slicing +[`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask +[`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter +[`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always +[`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic +[`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex +[`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons +[`items_after_statements`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#items_after_statements +[`iter_cloned_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_cloned_collect +[`iter_next_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_next_loop +[`iter_nth`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_nth +[`iter_skip_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_skip_next +[`iterator_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iterator_step_by_zero +[`large_digit_groups`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_digit_groups +[`large_enum_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_enum_variant +[`len_without_is_empty`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#len_without_is_empty +[`len_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#len_zero +[`let_and_return`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_and_return +[`let_unit_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_unit_value +[`linkedlist`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#linkedlist +[`logic_bug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#logic_bug +[`manual_swap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_swap +[`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names +[`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone +[`map_entry`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_entry +[`match_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_bool +[`match_overlapping_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_overlapping_arm +[`match_ref_pats`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_ref_pats +[`match_same_arms`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_same_arms +[`match_wild_err_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_wild_err_arm +[`maybe_infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#maybe_infinite_iter +[`mem_forget`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_forget +[`min_max`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#min_max +[`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op +[`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items +[`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals +[`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception +[`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one +[`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref +[`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut +[`mutex_atomic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_atomic +[`mutex_integer`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_integer +[`naive_bytecount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#naive_bytecount +[`needless_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_bool +[`needless_borrow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrow +[`needless_borrowed_reference`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrowed_reference +[`needless_continue`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_continue +[`needless_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_lifetimes +[`needless_pass_by_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_pass_by_value +[`needless_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_range_loop +[`needless_return`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_return +[`needless_update`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_update +[`neg_multiply`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#neg_multiply +[`never_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#never_loop +[`new_ret_no_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_ret_no_self +[`new_without_default`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_without_default +[`new_without_default_derive`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_without_default_derive +[`no_effect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#no_effect +[`non_ascii_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#non_ascii_literal +[`nonminimal_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonminimal_bool +[`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options +[`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref +[`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect +[`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref +[`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or +[`option_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else +[`option_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_unwrap_used +[`or_fun_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#or_fun_call +[`out_of_bounds_indexing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#out_of_bounds_indexing +[`overflow_check_conditional`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#overflow_check_conditional +[`panic_params`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panic_params +[`partialeq_ne_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#partialeq_ne_impl +[`possible_missing_comma`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#possible_missing_comma +[`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence +[`print_stdout`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_stdout +[`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline +[`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg +[`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names +[`range_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_step_by_zero +[`range_zip_with_len`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_zip_with_len +[`redundant_closure`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure +[`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call +[`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern +[`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro +[`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used +[`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop +[`search_is_some`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#search_is_some +[`serde_api_misuse`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#serde_api_misuse +[`shadow_reuse`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_reuse +[`shadow_same`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_same +[`shadow_unrelated`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_unrelated +[`short_circuit_statement`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#short_circuit_statement +[`should_assert_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#should_assert_eq +[`should_implement_trait`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#should_implement_trait +[`similar_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#similar_names +[`single_char_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_char_pattern +[`single_match`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_match +[`single_match_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_match_else +[`str_to_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#str_to_string +[`string_add`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_add +[`string_add_assign`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_add_assign +[`string_extend_chars`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_extend_chars +[`string_lit_as_bytes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_lit_as_bytes +[`string_to_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_to_string +[`stutter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#stutter +[`suspicious_assignment_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting +[`suspicious_else_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_else_formatting +[`temporary_assignment`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_assignment +[`temporary_cstring_as_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr +[`too_many_arguments`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#too_many_arguments +[`toplevel_ref_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`transmute_ptr_to_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref +[`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex +[`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity +[`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc +[`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp +[`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast +[`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed +[`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation +[`unneeded_field_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unneeded_field_pattern +[`unreadable_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unreadable_literal +[`unsafe_removed_from_name`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unsafe_removed_from_name +[`unseparated_literal_suffix`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unseparated_literal_suffix +[`unstable_as_mut_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unstable_as_mut_slice +[`unstable_as_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unstable_as_slice +[`unused_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_collect +[`unused_io_amount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_io_amount +[`unused_label`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_label +[`unused_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_lifetimes +[`use_debug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_debug +[`use_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_self +[`used_underscore_binding`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#used_underscore_binding +[`useless_attribute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_attribute +[`useless_format`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_format +[`useless_let_if_seq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_let_if_seq +[`useless_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_transmute +[`useless_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_vec +[`verbose_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#verbose_bit_mask +[`while_let_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_loop +[`while_let_on_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_on_iterator +[`wrong_pub_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_pub_self_convention +[`wrong_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_self_convention +[`wrong_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_transmute +[`zero_divided_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_divided_by_zero +[`zero_prefixed_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_prefixed_literal +[`zero_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_ptr +[`zero_width_space`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_width_space diff --git a/PUBLISH.md b/PUBLISH.md index 4a910c268e8..1ff3f2b4b73 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -12,9 +12,3 @@ Steps to publish a new clippy version - `git pull`. - `git tag -s v0.0.X -m "v0.0.X"`. - `git push --tags`. -- `git clone git@github.com:rust-lang-nursery/rust-clippy.wiki.git ../rust-clippy.wiki` -- `./util/update_wiki.py` -- `cd ../rust-clippy.wiki` -- `git add *` -- `git commit` -- `git push` diff --git a/README.md b/README.md index 9f2a0128c5a..9698ebf17bf 100644 --- a/README.md +++ b/README.md @@ -181,218 +181,7 @@ transparently: ## Lints There are 209 lints included in this crate: - -name | default | triggers on ------------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- -[absurd_extreme_comparisons](https://github.com/rust-lang-nursery/rust-clippy/wiki#absurd_extreme_comparisons) | warn | a comparison with a maximum or minimum value that is always true or false -[almost_swapped](https://github.com/rust-lang-nursery/rust-clippy/wiki#almost_swapped) | warn | `foo = bar; bar = foo` sequence -[approx_constant](https://github.com/rust-lang-nursery/rust-clippy/wiki#approx_constant) | warn | the approximate of a known float constant (in `std::fXX::consts`) -[assign_op_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_op_pattern) | warn | assigning the result of an operation on a variable to that same variable -[assign_ops](https://github.com/rust-lang-nursery/rust-clippy/wiki#assign_ops) | allow | any compound assignment operation -[bad_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#bad_bit_mask) | warn | expressions of the form `_ & mask == select` that will only ever return `true` or `false` -[blacklisted_name](https://github.com/rust-lang-nursery/rust-clippy/wiki#blacklisted_name) | warn | usage of a blacklisted/placeholder name -[block_in_if_condition_expr](https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_expr) | warn | braces that can be eliminated in conditions, e.g. `if { true } ...` -[block_in_if_condition_stmt](https://github.com/rust-lang-nursery/rust-clippy/wiki#block_in_if_condition_stmt) | warn | complex blocks in conditions, e.g. `if { let x = true; x } ...` -[bool_comparison](https://github.com/rust-lang-nursery/rust-clippy/wiki#bool_comparison) | warn | comparing a variable to a boolean, e.g. `if x == true` -[borrowed_box](https://github.com/rust-lang-nursery/rust-clippy/wiki#borrowed_box) | warn | a borrow of a boxed type -[box_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#box_vec) | warn | usage of `Box>`, vector elements are already on the heap -[boxed_local](https://github.com/rust-lang-nursery/rust-clippy/wiki#boxed_local) | warn | using `Box` where unnecessary -[builtin_type_shadow](https://github.com/rust-lang-nursery/rust-clippy/wiki#builtin_type_shadow) | warn | shadowing a builtin type -[cast_lossless](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_lossless) | warn | casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8` -[cast_possible_truncation](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_truncation) | allow | casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32` -[cast_possible_wrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX` -[cast_precision_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g. `x as f32` where `x: u64` -[cast_sign_loss](https://github.com/rust-lang-nursery/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g. `x as u32` where `x: i32` -[char_lit_as_u8](https://github.com/rust-lang-nursery/rust-clippy/wiki#char_lit_as_u8) | warn | casting a character literal to u8 -[chars_next_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char -[clone_double_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_double_ref) | warn | using `clone` on `&&T` -[clone_on_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#clone_on_copy) | warn | using `clone` on a `Copy` type -[cmp_nan](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN, which will always return false, probably not intended -[cmp_null](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_null) | warn | comparing a pointer to a null pointer, suggesting to use `.is_null()` instead. -[cmp_owned](https://github.com/rust-lang-nursery/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()` -[collapsible_if](https://github.com/rust-lang-nursery/rust-clippy/wiki#collapsible_if) | warn | `if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`) -[crosspointer_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#crosspointer_transmute) | warn | transmutes that have to or from types that are a pointer to the other -[cyclomatic_complexity](https://github.com/rust-lang-nursery/rust-clippy/wiki#cyclomatic_complexity) | warn | functions that should be split up into multiple functions -[deprecated_semver](https://github.com/rust-lang-nursery/rust-clippy/wiki#deprecated_semver) | warn | use of `#[deprecated(since = "x")]` where x is not semver -[deref_addrof](https://github.com/rust-lang-nursery/rust-clippy/wiki#deref_addrof) | warn | use of `*&` or `*&mut` in an expression -[derive_hash_xor_eq](https://github.com/rust-lang-nursery/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly -[diverging_sub_expression](https://github.com/rust-lang-nursery/rust-clippy/wiki#diverging_sub_expression) | warn | whether an expression contains a diverging sub expression -[doc_markdown](https://github.com/rust-lang-nursery/rust-clippy/wiki#doc_markdown) | warn | presence of `_`, `::` or camel-case outside backticks in documentation -[double_neg](https://github.com/rust-lang-nursery/rust-clippy/wiki#double_neg) | warn | `--x`, which is a double negation of `x` and not a pre-decrement as in C/C++ -[double_parens](https://github.com/rust-lang-nursery/rust-clippy/wiki#double_parens) | warn | Warn on unnecessary double parentheses -[drop_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_copy) | warn | calls to `std::mem::drop` with a value that implements Copy -[drop_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#drop_ref) | warn | calls to `std::mem::drop` with a reference instead of an owned value -[duplicate_underscore_argument](https://github.com/rust-lang-nursery/rust-clippy/wiki#duplicate_underscore_argument) | warn | function arguments having names which only differ by an underscore -[empty_enum](https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_enum) | allow | enum with no variants -[empty_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#empty_loop) | warn | empty `loop {}`, which should block or sleep -[enum_clike_unportable_variant](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_clike_unportable_variant) | warn | C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` -[enum_glob_use](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_glob_use) | allow | use items that import all variants of an enum -[enum_variant_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#enum_variant_names) | warn | enums where all variants share a prefix/postfix -[eq_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`) -[eval_order_dependence](https://github.com/rust-lang-nursery/rust-clippy/wiki#eval_order_dependence) | warn | whether a variable read occurs before a write depends on sub-expression evaluation order -[expl_impl_clone_on_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types -[explicit_counter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do -[explicit_into_iter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_into_iter_loop) | warn | for-looping over `_.into_iter()` when `_` would do -[explicit_iter_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do -[filter_map](https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_map) | allow | using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call -[filter_next](https://github.com/rust-lang-nursery/rust-clippy/wiki#filter_next) | warn | using `filter(p).next()`, which is more succinctly expressed as `.find(p)` -[float_arithmetic](https://github.com/rust-lang-nursery/rust-clippy/wiki#float_arithmetic) | allow | any floating-point arithmetic statement -[float_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#float_cmp) | warn | using `==` or `!=` on float values instead of comparing difference with an epsilon -[for_kv_map](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do -[for_loop_over_option](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` -[for_loop_over_result](https://github.com/rust-lang-nursery/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` -[forget_copy](https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_copy) | warn | calls to `std::mem::forget` with a value that implements Copy -[forget_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#forget_ref) | warn | calls to `std::mem::forget` with a reference instead of an owned value -[get_unwrap](https://github.com/rust-lang-nursery/rust-clippy/wiki#get_unwrap) | warn | using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead -[identity_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` -[if_let_redundant_pattern_matching](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_redundant_pattern_matching) | warn | use the proper utility function avoiding an `if let` -[if_let_some_result](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_let_some_result) | warn | usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead -[if_not_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_not_else) | allow | `if` branches that could be swapped so no negation operation is necessary on the condition -[if_same_then_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks -[ifs_same_cond](https://github.com/rust-lang-nursery/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition -[inconsistent_digit_grouping](https://github.com/rust-lang-nursery/rust-clippy/wiki#inconsistent_digit_grouping) | warn | integer literals with digits grouped inconsistently -[indexing_slicing](https://github.com/rust-lang-nursery/rust-clippy/wiki#indexing_slicing) | allow | indexing/slicing usage -[ineffective_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#ineffective_bit_mask) | warn | expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2` -[infinite_iter](https://github.com/rust-lang-nursery/rust-clippy/wiki#infinite_iter) | warn | infinite iteration -[inline_always](https://github.com/rust-lang-nursery/rust-clippy/wiki#inline_always) | warn | use of `#[inline(always)]` -[integer_arithmetic](https://github.com/rust-lang-nursery/rust-clippy/wiki#integer_arithmetic) | allow | any integer arithmetic statement -[invalid_regex](https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_regex) | deny | invalid regular expressions -[invalid_upcast_comparisons](https://github.com/rust-lang-nursery/rust-clippy/wiki#invalid_upcast_comparisons) | allow | a comparison involving an upcast which is always true or false -[items_after_statements](https://github.com/rust-lang-nursery/rust-clippy/wiki#items_after_statements) | allow | blocks where an item comes after a statement -[iter_cloned_collect](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_cloned_collect) | warn | using `.cloned().collect()` on slice to create a `Vec` -[iter_next_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_next_loop) | warn | for-looping over `_.next()` which is probably not intended -[iter_nth](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_nth) | warn | using `.iter().nth()` on a standard library type with O(1) element access -[iter_skip_next](https://github.com/rust-lang-nursery/rust-clippy/wiki#iter_skip_next) | warn | using `.skip(x).next()` on an iterator -[iterator_step_by_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#iterator_step_by_zero) | warn | using `Iterator::step_by(0)`, which produces an infinite iterator -[large_digit_groups](https://github.com/rust-lang-nursery/rust-clippy/wiki#large_digit_groups) | warn | grouping digits into groups that are too large -[large_enum_variant](https://github.com/rust-lang-nursery/rust-clippy/wiki#large_enum_variant) | warn | large size difference between variants on an enum -[len_without_is_empty](https://github.com/rust-lang-nursery/rust-clippy/wiki#len_without_is_empty) | warn | traits or impls with a public `len` method but no corresponding `is_empty` method -[len_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#len_zero) | warn | checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead -[let_and_return](https://github.com/rust-lang-nursery/rust-clippy/wiki#let_and_return) | warn | creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block -[let_unit_value](https://github.com/rust-lang-nursery/rust-clippy/wiki#let_unit_value) | warn | creating a let binding to a value of unit type, which usually can't be used afterwards -[linkedlist](https://github.com/rust-lang-nursery/rust-clippy/wiki#linkedlist) | warn | usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque -[logic_bug](https://github.com/rust-lang-nursery/rust-clippy/wiki#logic_bug) | warn | boolean expressions that contain terminals which can be eliminated -[manual_swap](https://github.com/rust-lang-nursery/rust-clippy/wiki#manual_swap) | warn | manual swap of two variables -[many_single_char_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#many_single_char_names) | warn | too many single character bindings -[map_clone](https://github.com/rust-lang-nursery/rust-clippy/wiki#map_clone) | warn | using `.map(|x| x.clone())` to clone an iterator or option's contents -[map_entry](https://github.com/rust-lang-nursery/rust-clippy/wiki#map_entry) | warn | use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap` -[match_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_bool) | warn | a match on a boolean expression instead of an `if..else` block -[match_overlapping_arm](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_overlapping_arm) | warn | a match with overlapping arms -[match_ref_pats](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats) | warn | a match or `if let` with all arms prefixed with `&` instead of deref-ing the match expression -[match_same_arms](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_same_arms) | warn | `match` with identical arm bodies -[match_wild_err_arm](https://github.com/rust-lang-nursery/rust-clippy/wiki#match_wild_err_arm) | warn | a match with `Err(_)` arm and take drastic actions -[maybe_infinite_iter](https://github.com/rust-lang-nursery/rust-clippy/wiki#maybe_infinite_iter) | allow | possible infinite iteration -[mem_forget](https://github.com/rust-lang-nursery/rust-clippy/wiki#mem_forget) | allow | `mem::forget` usage on `Drop` types, likely to cause memory leaks -[min_max](https://github.com/rust-lang-nursery/rust-clippy/wiki#min_max) | warn | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant -[misrefactored_assign_op](https://github.com/rust-lang-nursery/rust-clippy/wiki#misrefactored_assign_op) | warn | having a variable on both sides of an assign op -[missing_docs_in_private_items](https://github.com/rust-lang-nursery/rust-clippy/wiki#missing_docs_in_private_items) | allow | detects missing documentation for public and private members -[mixed_case_hex_literals](https://github.com/rust-lang-nursery/rust-clippy/wiki#mixed_case_hex_literals) | warn | hex literals whose letter digits are not consistently upper- or lowercased -[module_inception](https://github.com/rust-lang-nursery/rust-clippy/wiki#module_inception) | warn | modules that have the same name as their parent module -[modulo_one](https://github.com/rust-lang-nursery/rust-clippy/wiki#modulo_one) | warn | taking a number modulo 1, which always returns 0 -[mut_from_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_from_ref) | warn | fns that create mutable refs from immutable ref args -[mut_mut](https://github.com/rust-lang-nursery/rust-clippy/wiki#mut_mut) | allow | usage of double-mut refs, e.g. `&mut &mut ...` -[mutex_atomic](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_atomic) | warn | using a mutex where an atomic value could be used instead -[mutex_integer](https://github.com/rust-lang-nursery/rust-clippy/wiki#mutex_integer) | allow | using a mutex for an integer type -[naive_bytecount](https://github.com/rust-lang-nursery/rust-clippy/wiki#naive_bytecount) | warn | use of naive `.filter(|&x| x == y).count()` to count byte values -[needless_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_bool) | warn | if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }` -[needless_borrow](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrow) | warn | taking a reference that is going to be automatically dereferenced -[needless_borrowed_reference](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_borrowed_reference) | warn | taking a needless borrowed reference -[needless_continue](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_continue) | warn | `continue` statements that can be replaced by a rearrangement of code -[needless_lifetimes](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_lifetimes) | warn | using explicit lifetimes for references in function arguments when elision rules would allow omitting them -[needless_pass_by_value](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_pass_by_value) | warn | functions taking arguments by value, but not consuming them in its body -[needless_range_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_range_loop) | warn | for-looping over a range of indices where an iterator over items would do -[needless_return](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_return) | warn | using a return statement like `return expr;` where an expression would suffice -[needless_update](https://github.com/rust-lang-nursery/rust-clippy/wiki#needless_update) | warn | using `Foo { ..base }` when there are no missing fields -[neg_multiply](https://github.com/rust-lang-nursery/rust-clippy/wiki#neg_multiply) | warn | multiplying integers with -1 -[never_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#never_loop) | warn | any loop that will always `break` or `return` -[new_ret_no_self](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_ret_no_self) | warn | not returning `Self` in a `new` method -[new_without_default](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default) | warn | `fn new() -> Self` method without `Default` implementation -[new_without_default_derive](https://github.com/rust-lang-nursery/rust-clippy/wiki#new_without_default_derive) | warn | `fn new() -> Self` without `#[derive]`able `Default` implementation -[no_effect](https://github.com/rust-lang-nursery/rust-clippy/wiki#no_effect) | warn | statements with no effect -[non_ascii_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#non_ascii_literal) | allow | using any literal non-ASCII chars in a string literal instead of using the `\\u` escape -[nonminimal_bool](https://github.com/rust-lang-nursery/rust-clippy/wiki#nonminimal_bool) | allow | boolean expressions that can be written more concisely -[nonsensical_open_options](https://github.com/rust-lang-nursery/rust-clippy/wiki#nonsensical_open_options) | warn | nonsensical combination of options for opening a file -[not_unsafe_ptr_arg_deref](https://github.com/rust-lang-nursery/rust-clippy/wiki#not_unsafe_ptr_arg_deref) | warn | public functions dereferencing raw pointer arguments but not marked `unsafe` -[ok_expect](https://github.com/rust-lang-nursery/rust-clippy/wiki#ok_expect) | warn | using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result -[op_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#op_ref) | warn | taking a reference to satisfy the type constraints on `==` -[option_map_unwrap_or](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or) | allow | using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)` -[option_map_unwrap_or_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_map_unwrap_or_else) | allow | using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)` -[option_unwrap_used](https://github.com/rust-lang-nursery/rust-clippy/wiki#option_unwrap_used) | allow | using `Option.unwrap()`, which should at least get a better message using `expect()` -[or_fun_call](https://github.com/rust-lang-nursery/rust-clippy/wiki#or_fun_call) | warn | using any `*or` method with a function call, which suggests `*or_else` -[out_of_bounds_indexing](https://github.com/rust-lang-nursery/rust-clippy/wiki#out_of_bounds_indexing) | deny | out of bounds constant indexing -[overflow_check_conditional](https://github.com/rust-lang-nursery/rust-clippy/wiki#overflow_check_conditional) | warn | overflow checks inspired by C which are likely to panic -[panic_params](https://github.com/rust-lang-nursery/rust-clippy/wiki#panic_params) | warn | missing parameters in `panic!` calls -[partialeq_ne_impl](https://github.com/rust-lang-nursery/rust-clippy/wiki#partialeq_ne_impl) | warn | re-implementing `PartialEq::ne` -[possible_missing_comma](https://github.com/rust-lang-nursery/rust-clippy/wiki#possible_missing_comma) | warn | possible missing comma in array -[precedence](https://github.com/rust-lang-nursery/rust-clippy/wiki#precedence) | warn | operations where precedence may be unclear -[print_stdout](https://github.com/rust-lang-nursery/rust-clippy/wiki#print_stdout) | allow | printing on stdout -[print_with_newline](https://github.com/rust-lang-nursery/rust-clippy/wiki#print_with_newline) | warn | using `print!()` with a format string that ends in a newline -[ptr_arg](https://github.com/rust-lang-nursery/rust-clippy/wiki#ptr_arg) | warn | fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively -[pub_enum_variant_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#pub_enum_variant_names) | allow | enums where all variants share a prefix/postfix -[range_zip_with_len](https://github.com/rust-lang-nursery/rust-clippy/wiki#range_zip_with_len) | warn | zipping iterator with a range when `enumerate()` would do -[redundant_closure](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure) | warn | redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`) -[redundant_closure_call](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_closure_call) | warn | throwaway closures called in the expression they are defined -[redundant_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#redundant_pattern) | warn | using `name @ _` in a pattern -[regex_macro](https://github.com/rust-lang-nursery/rust-clippy/wiki#regex_macro) | warn | use of `regex!(_)` instead of `Regex::new(_)` -[result_unwrap_used](https://github.com/rust-lang-nursery/rust-clippy/wiki#result_unwrap_used) | allow | using `Result.unwrap()`, which might be better handled -[reverse_range_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#reverse_range_loop) | warn | iteration over an empty range, such as `10..0` or `5..5` -[search_is_some](https://github.com/rust-lang-nursery/rust-clippy/wiki#search_is_some) | warn | using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()` -[serde_api_misuse](https://github.com/rust-lang-nursery/rust-clippy/wiki#serde_api_misuse) | warn | various things that will negatively affect your serde experience -[shadow_reuse](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_reuse) | allow | rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1` -[shadow_same](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_same) | allow | rebinding a name to itself, e.g. `let mut x = &mut x` -[shadow_unrelated](https://github.com/rust-lang-nursery/rust-clippy/wiki#shadow_unrelated) | allow | rebinding a name without even using the original value -[short_circuit_statement](https://github.com/rust-lang-nursery/rust-clippy/wiki#short_circuit_statement) | warn | using a short circuit boolean condition as a statement -[should_assert_eq](https://github.com/rust-lang-nursery/rust-clippy/wiki#should_assert_eq) | warn | using `assert` macro for asserting equality -[should_implement_trait](https://github.com/rust-lang-nursery/rust-clippy/wiki#should_implement_trait) | warn | defining a method that should be implementing a std trait -[similar_names](https://github.com/rust-lang-nursery/rust-clippy/wiki#similar_names) | allow | similarly named items and bindings -[single_char_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` -[single_match](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let` -[single_match_else](https://github.com/rust-lang-nursery/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let` -[string_add](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String` instead of `push_str()` -[string_add_assign](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String` instead of `push_str()` -[string_extend_chars](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_extend_chars) | warn | using `x.extend(s.chars())` where s is a `&str` or `String` -[string_lit_as_bytes](https://github.com/rust-lang-nursery/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal instead of using a byte string literal -[stutter](https://github.com/rust-lang-nursery/rust-clippy/wiki#stutter) | allow | type names prefixed/postfixed with their containing module's name -[suspicious_assignment_formatting](https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` -[suspicious_else_formatting](https://github.com/rust-lang-nursery/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` -[temporary_assignment](https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries -[temporary_cstring_as_ptr](https://github.com/rust-lang-nursery/rust-clippy/wiki#temporary_cstring_as_ptr) | warn | getting the inner pointer of a temporary `CString` -[too_many_arguments](https://github.com/rust-lang-nursery/rust-clippy/wiki#too_many_arguments) | warn | functions with too many arguments -[toplevel_ref_arg](https://github.com/rust-lang-nursery/rust-clippy/wiki#toplevel_ref_arg) | warn | an entire binding declared as `ref`, in a function argument or a `let` statement -[transmute_ptr_to_ref](https://github.com/rust-lang-nursery/rust-clippy/wiki#transmute_ptr_to_ref) | warn | transmutes from a pointer to a reference type -[trivial_regex](https://github.com/rust-lang-nursery/rust-clippy/wiki#trivial_regex) | warn | trivial regular expressions -[type_complexity](https://github.com/rust-lang-nursery/rust-clippy/wiki#type_complexity) | warn | usage of very complex types that might be better factored into `type` definitions -[unicode_not_nfc](https://github.com/rust-lang-nursery/rust-clippy/wiki#unicode_not_nfc) | allow | using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information) -[unit_cmp](https://github.com/rust-lang-nursery/rust-clippy/wiki#unit_cmp) | warn | comparing unit values -[unnecessary_cast](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_cast) | warn | cast to the same type, e.g. `x as i32` where `x: i32` -[unnecessary_mut_passed](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_mut_passed) | warn | an argument passed as a mutable reference although the callee only demands an immutable reference -[unnecessary_operation](https://github.com/rust-lang-nursery/rust-clippy/wiki#unnecessary_operation) | warn | outer expressions with no effect -[unneeded_field_pattern](https://github.com/rust-lang-nursery/rust-clippy/wiki#unneeded_field_pattern) | warn | struct fields bound to a wildcard instead of using `..` -[unreadable_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#unreadable_literal) | warn | long integer literal without underscores -[unsafe_removed_from_name](https://github.com/rust-lang-nursery/rust-clippy/wiki#unsafe_removed_from_name) | warn | `unsafe` removed from API names on import -[unseparated_literal_suffix](https://github.com/rust-lang-nursery/rust-clippy/wiki#unseparated_literal_suffix) | allow | literals whose suffix is not separated by an underscore -[unused_collect](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop -[unused_io_amount](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_io_amount) | deny | unused written/read amount -[unused_label](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_label) | warn | unused labels -[unused_lifetimes](https://github.com/rust-lang-nursery/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions -[use_debug](https://github.com/rust-lang-nursery/rust-clippy/wiki#use_debug) | allow | use of `Debug`-based formatting -[use_self](https://github.com/rust-lang-nursery/rust-clippy/wiki#use_self) | allow | Unnecessary structure name repetition whereas `Self` is applicable -[used_underscore_binding](https://github.com/rust-lang-nursery/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore -[useless_attribute](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_attribute) | warn | use of lint attributes on `extern crate` items -[useless_format](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_format) | warn | useless use of `format!` -[useless_let_if_seq](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_let_if_seq) | warn | unidiomatic `let mut` declaration followed by initialization in `if` -[useless_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion -[useless_vec](https://github.com/rust-lang-nursery/rust-clippy/wiki#useless_vec) | warn | useless `vec!` -[verbose_bit_mask](https://github.com/rust-lang-nursery/rust-clippy/wiki#verbose_bit_mask) | warn | expressions where a bit mask is less readable than the corresponding method call -[while_let_loop](https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }`, which can be written as a `while let` loop -[while_let_on_iterator](https://github.com/rust-lang-nursery/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator -[wrong_pub_self_convention](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_self_convention](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention -[wrong_transmute](https://github.com/rust-lang-nursery/rust-clippy/wiki#wrong_transmute) | warn | transmutes that are confusing at best, undefined behaviour at worst and always useless -[zero_divided_by_zero](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN -[zero_prefixed_literal](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_prefixed_literal) | warn | integer literals starting with `0` -[zero_ptr](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_ptr) | warn | using 0 as *{const, mut} T -[zero_width_space](https://github.com/rust-lang-nursery/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing +https://rust-lang-nursery.github.io/rust-clippy/master/index.html More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a0ee741d1dd..46bc53ce719 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -566,7 +566,7 @@ impl<'a> DiagnosticWrapper<'a> { fn wiki_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://github.com/rust-lang-nursery/rust-clippy/wiki#{}", + "for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#{}", lint.name_lower() )); } diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs deleted file mode 100644 index 4e9986561bc..00000000000 --- a/clippy_tests/examples/needless_borrowed_ref.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#[warn(needless_borrowed_reference)] -#[allow(unused_variables)] -fn main() { - let mut v = Vec::::new(); - let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - // ^ should be linted - - let var = 3; - let thingy = Some(&var); - if let Some(&ref v) = thingy { - // ^ should be linted - } - - let mut var2 = 5; - let thingy2 = Some(&mut var2); - if let Some(&mut ref mut v) = thingy2 { - // ^ should *not* be linted - // v is borrowed as mutable. - *v = 10; - } - if let Some(&mut ref v) = thingy2 { - // ^ should *not* be linted - // here, v is borrowed as immutable. - // can't do that: - //*v = 15; - } -} - -#[allow(dead_code)] -enum Animal { - Cat(u64), - Dog(u64), -} - -#[allow(unused_variables)] -#[allow(dead_code)] -fn foo(a: &Animal, b: &Animal) { - match (a, b) { - (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' - // ^ and ^ should *not* be linted - (&Animal::Dog(ref a), &Animal::Dog(_)) => () - // ^ should *not* be linted - } -} - diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr deleted file mode 100644 index 2b506af88f5..00000000000 --- a/clippy_tests/examples/needless_borrowed_ref.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:8:34 - | -8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - | ^^^^^^ help: try removing the `&ref` part and just keep `a` - | - = note: `-D needless-borrowed-reference` implied by `-D warnings` - = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference - -error: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:13:17 - | -13 | if let Some(&ref v) = thingy { - | ^^^^^^ help: try removing the `&ref` part and just keep `v` - | - = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference - -error: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:42:27 - | -42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' - | ^^^^^^ help: try removing the `&ref` part and just keep `k` - | - = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference - -error: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:42:38 - | -42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' - | ^^^^^^ help: try removing the `&ref` part and just keep `k` - | - = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference - -error: aborting due to previous error(s) - -error: Could not compile `clippy_tests`. - -To learn more, run the command again with --verbose. diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs new file mode 100644 index 00000000000..4e9986561bc --- /dev/null +++ b/tests/ui/needless_borrowed_ref.rs @@ -0,0 +1,48 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[warn(needless_borrowed_reference)] +#[allow(unused_variables)] +fn main() { + let mut v = Vec::::new(); + let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + // ^ should be linted + + let var = 3; + let thingy = Some(&var); + if let Some(&ref v) = thingy { + // ^ should be linted + } + + let mut var2 = 5; + let thingy2 = Some(&mut var2); + if let Some(&mut ref mut v) = thingy2 { + // ^ should *not* be linted + // v is borrowed as mutable. + *v = 10; + } + if let Some(&mut ref v) = thingy2 { + // ^ should *not* be linted + // here, v is borrowed as immutable. + // can't do that: + //*v = 15; + } +} + +#[allow(dead_code)] +enum Animal { + Cat(u64), + Dog(u64), +} + +#[allow(unused_variables)] +#[allow(dead_code)] +fn foo(a: &Animal, b: &Animal) { + match (a, b) { + (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + // ^ and ^ should *not* be linted + (&Animal::Dog(ref a), &Animal::Dog(_)) => () + // ^ should *not* be linted + } +} + diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr new file mode 100644 index 00000000000..2a8cf4348d3 --- /dev/null +++ b/tests/ui/needless_borrowed_ref.stderr @@ -0,0 +1,28 @@ +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrowed_ref.rs:8:34 + | +8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrowed_ref.rs:13:17 + | +13 | if let Some(&ref v) = thingy { + | ^^^^^^ help: try removing the `&ref` part and just keep: `v` + +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrowed_ref.rs:42:27 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep: `k` + +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrowed_ref.rs:42:38 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep: `k` + +error: aborting due to 4 previous errors + diff --git a/util/update_lints.py b/util/update_lints.py index 9eeb02de9cc..a03f114d902 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -29,7 +29,7 @@ declare_restriction_lint_re = re.compile(r''' nl_escape_re = re.compile(r'\\\n\s*') -wiki_link = 'https://github.com/rust-lang-nursery/rust-clippy/wiki' +wiki_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' def collect(lints, deprecated_lints, restriction_lints, fn): @@ -63,22 +63,6 @@ def collect(lints, deprecated_lints, restriction_lints, fn): desc.replace('\\"', '"'))) -def gen_table(lints, link=None): - """Write lint table in Markdown format.""" - if link: - lints = [(p, '[%s](%s#%s)' % (l, link, l), lvl, d) - for (p, l, lvl, d) in lints] - # first and third column widths - w_name = max(len(l[1]) for l in lints) - w_desc = max(len(l[3]) for l in lints) - # header and underline - yield '%-*s | default | triggers on\n' % (w_name, 'name') - yield '%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc) - # one table row per lint - for (_, name, default, meaning) in sorted(lints, key=lambda l: l[1]): - yield '%-*s | %-7s | %s\n' % (w_name, name, default, meaning) - - def gen_group(lints, levels=None): """Write lint group (list of all lints in the form module::NAME).""" if levels: @@ -172,13 +156,8 @@ def main(print_only=False, check=False): sys.stdout.writelines(gen_table(lints + restriction_lints)) return - # replace table in README.md + # update the lint counter in README.md changed = replace_region( - 'README.md', r'^name +\|', '^$', - lambda: gen_table(lints + restriction_lints, link=wiki_link), - write_back=not check) - - changed |= replace_region( 'README.md', r'^There are \d+ lints included in this crate:', "", lambda: ['There are %d lints included in this crate:\n' % diff --git a/util/update_wiki.py b/util/update_wiki.py deleted file mode 100755 index a9bd32f2098..00000000000 --- a/util/update_wiki.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# Generate the wiki Home.md page from the contained doc comments -# requires the checked out wiki in ../rust-clippy.wiki/ -# with -c option, print a warning and set exit status 1 if the file would be -# changed. - -import re -import sys - -from lintlib import log, parse_all - -PREFIX = """Welcome to the rust-clippy wiki! - -Here we aim to collect further explanations on the lints clippy provides. So \ -without further ado: -""" - -WARNING = """ -# A word of warning - -Clippy works as a *plugin* to the compiler, which means using an unstable \ -internal API. We have gotten quite good at keeping pace with the API \ -evolution, but the consequence is that clippy absolutely needs to be compiled \ -with the version of `rustc` it will run on, otherwise you will get strange \ -errors of missing symbols. - -""" - -TEMPLATE = """\n# `%s` - -**Default level:** %s - -%s""" - -CONF_TEMPLATE = """ -**Configuration:** This lint has the following configuration variables: - -* `%s: %s`: %s (defaults to `%s`). -""" - - -def level_message(level): - if level == "Deprecated": - return "\n**Those lints are deprecated**:\n\n" - else: - return "\n**Those lints are %s by default**:\n\n" % level - - -def write_wiki_page(lints, configs, filepath): - lints.sort() - with open(filepath, "w") as fp: - fp.write(PREFIX) - - for level in ('Deny', 'Warn', 'Allow', 'Deprecated'): - fp.write(level_message(level)) - for lint in lints: - if lint.level == level: - fp.write("[`%s`](#%s)\n" % (lint.name, lint.name)) - - fp.write(WARNING) - for lint in lints: - fp.write(TEMPLATE % (lint.name, lint.level, "".join(lint.doc))) - - if lint.name in configs: - fp.write(CONF_TEMPLATE % configs[lint.name]) - - -def check_wiki_page(lints, configs, filepath): - lintdict = dict((lint.name, lint) for lint in lints) - errors = False - with open(filepath) as fp: - for line in fp: - m = re.match("# `([a-z_0-9]+)`", line) - if m: - v = lintdict.pop(m.group(1), None) - if v is None: - log.error("Spurious wiki entry: %s", m.group(1)) - errors = True - for n in sorted(lintdict): - log.error("Missing wiki entry: %s", n) - errors = True - if errors: - return 1 - - -def main(): - lints, configs = parse_all() - if "-c" in sys.argv: - check_wiki_page(lints, configs, "../rust-clippy.wiki/Home.md") - else: - write_wiki_page(lints, configs, "../rust-clippy.wiki/Home.md") - - -if __name__ == "__main__": - main() -- cgit 1.4.1-3-g733a5 From ff91c6359a0ba4f2f1e17383da6cfa4de9516da3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 Sep 2017 10:29:49 +0200 Subject: wiki -> docs --- CHANGELOG.md | 2 +- README.md | 2 +- clippy_lints/src/utils/mod.rs | 12 ++++++------ tests/compile-test.rs | 2 +- util/update_lints.py | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) mode change 100755 => 100644 util/update_lints.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd295708e6..68753594a7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -308,7 +308,7 @@ All notable changes to this project will be documented in this file. ## 0.0.74 — 2016-06-07 * Fix bug with `cargo-clippy` JSON parsing -* Add the `CLIPPY_DISABLE_WIKI_LINKS` environment variable to deactivate the +* Add the `CLIPPY_DISABLE_DOCS_LINKS` environment variable to deactivate the “for further information visit *wiki-link*” message. ## 0.0.73 — 2016-06-05 diff --git a/README.md b/README.md index 9698ebf17bf..659859280d9 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ You can also specify the path to the configuration file with: ``` To deactivate the “for further information visit *wiki-link*” message you can -define the `CLIPPY_DISABLE_WIKI_LINKS` environment variable. +define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. ### Allowing/denying lints diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 46bc53ce719..948adc48c81 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -563,8 +563,8 @@ impl<'a> Drop for DiagnosticWrapper<'a> { } impl<'a> DiagnosticWrapper<'a> { - fn wiki_link(&mut self, lint: &'static Lint) { - if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() { + fn docs_link(&mut self, lint: &'static Lint) { + if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( "for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#{}", lint.name_lower() @@ -574,7 +574,7 @@ impl<'a> DiagnosticWrapper<'a> { } pub fn span_lint<'a, T: LintContext<'a>>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { - DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)).wiki_link(lint); + DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)).docs_link(lint); } pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( @@ -586,7 +586,7 @@ pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( ) { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); db.0.help(help); - db.wiki_link(lint); + db.docs_link(lint); } pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( @@ -603,7 +603,7 @@ pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>( } else { db.0.span_note(note_span, note); } - db.wiki_link(lint); + db.docs_link(lint); } pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( @@ -617,7 +617,7 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( { let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); f(&mut db.0); - db.wiki_link(lint); + db.docs_link(lint); } pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 363eeced8a2..a5d55978d09 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -21,7 +21,7 @@ fn run_mode(dir: &'static str, mode: &'static str) { } fn prepare_env() { - set_var("CLIPPY_DISABLE_WIKI_LINKS", "true"); + set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); } #[test] diff --git a/util/update_lints.py b/util/update_lints.py old mode 100755 new mode 100644 index a03f114d902..b8ae46cced8 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -29,7 +29,7 @@ declare_restriction_lint_re = re.compile(r''' nl_escape_re = re.compile(r'\\\n\s*') -wiki_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' +docs_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' def collect(lints, deprecated_lints, restriction_lints, fn): @@ -169,7 +169,7 @@ def main(print_only=False, check=False): 'CHANGELOG.md', "", "", - lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], wiki_link) for l in + lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], docs_link) for l in sorted(lints + restriction_lints + deprecated_lints, key=lambda l: l[1])], replace_start=False, write_back=not check) -- cgit 1.4.1-3-g733a5 From 045139613a4a08012a43a0528a8d2272608bf809 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 Sep 2017 10:35:58 +0200 Subject: Link to current versions docs instead of master docs --- clippy_lints/src/utils/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 948adc48c81..66a1b010ec8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -566,7 +566,8 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#{}", + "for further information visit https://rust-lang-nursery.github.io/rust-clippy/{}/index.html#{}", + env!("CARGO_PKG_VERSION"), lint.name_lower() )); } -- cgit 1.4.1-3-g733a5 From 0f0075df09fbccec37fa0690bebd31734ddedb2c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 Sep 2017 10:36:20 +0200 Subject: Update README lint counter message --- README.md | 3 +-- util/update_lints.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) mode change 100644 => 100755 util/update_lints.py diff --git a/README.md b/README.md index 659859280d9..b9d97dd3e17 100644 --- a/README.md +++ b/README.md @@ -180,8 +180,7 @@ transparently: ## Lints -There are 209 lints included in this crate: -https://rust-lang-nursery.github.io/rust-clippy/master/index.html +[There are 209 lints included in this crate](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! diff --git a/util/update_lints.py b/util/update_lints.py old mode 100644 new mode 100755 index b8ae46cced8..6c08f575d05 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -159,8 +159,8 @@ def main(print_only=False, check=False): # update the lint counter in README.md changed = replace_region( 'README.md', - r'^There are \d+ lints included in this crate:', "", - lambda: ['There are %d lints included in this crate:\n' % + r'^\[There are \d+ lints included in this crate\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)$', "", + lambda: ['[There are %d lints included in this crate](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)\n' % (len(lints) + len(restriction_lints))], write_back=not check) -- cgit 1.4.1-3-g733a5 From e5e1afac5f46686d9c8baf073841afe91d983ec9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 Sep 2017 15:14:49 +0200 Subject: Remove clippy.bashy.io The service seems to be defunct for a while now --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b9d97dd3e17..7a5a54564e5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy) -[![Clippy Linting Result](http://clippy.bashy.io/github/rust-lang-nursery/rust-clippy/master/badge.svg)](http://clippy.bashy.io/github/rust-lang-nursery/rust-clippy/master/log) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) -- cgit 1.4.1-3-g733a5 From 285a33a569081ac33da3e8e5a982845ededc03da Mon Sep 17 00:00:00 2001 From: Martin Carton Date: Fri, 1 Sep 2017 20:29:36 +0200 Subject: Move the number of lints back to the top of README This used to be at the top and was moved at the bottom when the big list of lints started to be so ridiculously long that people had to scroll for 10 minutes to have usage information :smile: --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7a5a54564e5..8ef61a9df0f 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,12 @@ A collection of lints to catch common mistakes and improve your Rust code. +[There are 209 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) + +More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! + Table of contents: -* [Lint list](#lints) * [Usage instructions](#usage) * [Configuration](#configuration) * [License](#license) @@ -177,12 +180,6 @@ transparently: #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] ``` -## Lints - -[There are 209 lints included in this crate](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) - -More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! - ## License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). -- cgit 1.4.1-3-g733a5 From df29c8730383b81ae1c1d24f71d684fc20ab5d16 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 1 Sep 2017 22:43:34 +0200 Subject: some small doc improvements --- clippy_lints/src/overflow_check_conditional.rs | 1 - clippy_lints/src/regex.rs | 7 +++---- clippy_lints/src/types.rs | 6 +++++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 41ea6fbc461..ee44cc70b43 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -13,7 +13,6 @@ use utils::span_lint; /// ```rust /// a + b < a /// ``` - declare_lint! { pub OVERFLOW_CHECK_CONDITIONAL, Warn, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 2ee33013791..6ee357fd81f 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -11,10 +11,9 @@ use syntax::codemap::{Span, BytePos}; use syntax::symbol::InternedString; use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; -/// **What it does:** Checks [regex] creation (with `Regex::new`, -/// `RegexBuilder::new` or `RegexSet::new`) for correct regex syntax. -/// -/// [regex]: https://crates.io/crates/regex +/// **What it does:** Checks [regex](https://crates.io/crates/regex) creation +/// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct +/// regex syntax. /// /// **Why is this bad?** This will lead to a runtime panic. /// diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 29a7bb75011..eaa01fb1d82 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1008,7 +1008,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { /// that is is possible for `x` to be less than the minimum. Expressions like /// `max < x` are probably mistakes. /// -/// **Known problems:** None. +/// **Known problems:** For `usize` the size of the current compile target will +/// be assumed (e.g. 64 bits on 64 bit systems). This means code that uses such +/// a comparison to detect target pointer width will trigger this lint. One can +/// use `mem::sizeof` and compare its value or conditional compilation attributes +/// like `#[cfg(target_pointer_width = "64")] ..` instead. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From f581aa77793fd7114c070b8f6dc1f98fda064c70 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 11:25:33 -0700 Subject: Initial commit of unit expr --- clippy_lints/src/is_unit_expr.rs | 47 ++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 +++ 2 files changed, 50 insertions(+) create mode 100644 clippy_lints/src/is_unit_expr.rs diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs new file mode 100644 index 00000000000..4547630bffb --- /dev/null +++ b/clippy_lints/src/is_unit_expr.rs @@ -0,0 +1,47 @@ +use rustc::lint::*; +use syntax::ast::*; +use syntax::codemap::Spanned; +use utils::{span_lint_and_sugg, snippet}; + + +/// **What it does:** Checks for +/// - () being assigned to a variable +/// - () being passed to a function +/// +/// **Why is this bad?** It is extremely unlikely that a user intended to assign '()' to valiable. Instead, +/// Unit is what a block evaluates to when it returns nothing. This is typically caused by a trailing +/// unintended semicolon. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// * `let x = {"foo" ;}` when the user almost certainly intended `let x ={"foo"}` + +declare_lint! { + pub UNIT_EXPR, + Warn, + "unintended assignment or use of a unit typed value" +} + +#[derive(Copy, Clone)] +pub struct UnitExpr; + +impl LintPass for UnitExpr { + fn get_lints(&self) -> LintArray { + lint_array!(UNIT_EXPR) + } +} + +impl EarlyLintPass for UnitExpr { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if let ExprKind::Assign(ref left, ref right) = expr.node { + unimplemented!(); + } + if let ExprKind::MethodCall(ref path, ref args) = expr.node { + unimplemented!(); + } + if let ExprKind::Call(ref path, ref args) = expr.node{ + unimplemented!(); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 19b8816cd1e..0324ff46b61 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -91,6 +91,7 @@ pub mod functions; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; +pub mod is_unit_expr; pub mod infinite_iter; pub mod items_after_statements; pub mod large_enum_variant; @@ -233,6 +234,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box approx_const::Pass); reg.register_late_lint_pass(box misc::Pass); reg.register_early_lint_pass(box precedence::Precedence); + reg.register_early_lint_pass(box is_unit_expr::UnitExpr); reg.register_early_lint_pass(box needless_continue::NeedlessContinue); reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); @@ -504,6 +506,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, + is_unit_expr::UnitExpr, print::PRINT_WITH_NEWLINE, ptr::CMP_NULL, ptr::MUT_FROM_REF, -- cgit 1.4.1-3-g733a5 From a25a172e60db5638614ce77580bfe872df3fef90 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 11:29:01 -0700 Subject: Use the type from the macro --- clippy_lints/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0324ff46b61..5b484aceed8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -506,7 +506,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, - is_unit_expr::UnitExpr, + is_unit_expr::UNIT_EXPR, print::PRINT_WITH_NEWLINE, ptr::CMP_NULL, ptr::MUT_FROM_REF, -- cgit 1.4.1-3-g733a5 From 9e3be6ae49a914b616503e83a203dbc7a9ef905a Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 12:20:43 -0700 Subject: Introduce check_stmt --- clippy_lints/src/is_unit_expr.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 4547630bffb..b8c85813d3f 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -44,4 +44,10 @@ impl EarlyLintPass for UnitExpr { unimplemented!(); } } + + fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { + if let StmtKind::Local(ref data) = stmt.node{ + unimplemented!(); + } + } } -- cgit 1.4.1-3-g733a5 From 2a97aadacf2907b82bd57d0dafe8aa4f7e904153 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 14:09:41 -0700 Subject: More initial work --- clippy_lints/src/is_unit_expr.rs | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index b8c85813d3f..07991082872 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -35,19 +35,55 @@ impl LintPass for UnitExpr { impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref left, ref right) = expr.node { - unimplemented!(); - } - if let ExprKind::MethodCall(ref path, ref args) = expr.node { - unimplemented!(); - } - if let ExprKind::Call(ref path, ref args) = expr.node{ - unimplemented!(); + if is_unit_expr(right){ + span_lint_and_sugg( + cx, + UNIT_EXPR, + right.span, + "trailing semicolons can be tricky", + "remove the last semicolon", + "TODO".to_owned() + ) + } } + // if let ExprKind::MethodCall(ref path, ref args) = expr.node { + // unimplemented!(); + // } + // if let ExprKind::Call(ref path, ref args) = expr.node{ + // unimplemented!(); + // } } fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { - if let StmtKind::Local(ref data) = stmt.node{ - unimplemented!(); - } + if let StmtKind::Local(ref local) = stmt.node{ + if local.pat.node == PatKind::Wild {return;} + if let Some(ref expr) = local.init{ + if is_unit_expr(expr){ + span_lint_and_sugg( + cx, + UNIT_EXPR, + local.span, + "trailing semicolons can be tricky", + "remove the last semicolon", + "TODO".to_owned() + ) + } + } + } } } + +fn is_unit_expr(expr: &Expr)->bool{ + match expr.node{ + ExprKind::Block(ref next) => { + let ref final_stmt = &next.stmts[next.stmts.len()-1]; + if let StmtKind::Expr(_) = final_stmt.node{ + return false; + } + else{ + return true; + } + }, + _ => return false, + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From d6d78cdbbec1600cf2bd9f77a96d23df135ab550 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 14:19:45 -0700 Subject: Check method calls --- clippy_lints/src/is_unit_expr.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 07991082872..63bdaaa5231 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -46,12 +46,31 @@ impl EarlyLintPass for UnitExpr { ) } } - // if let ExprKind::MethodCall(ref path, ref args) = expr.node { - // unimplemented!(); - // } - // if let ExprKind::Call(ref path, ref args) = expr.node{ - // unimplemented!(); - // } + if let ExprKind::MethodCall(_, ref args) = expr.node { + for ref arg in args{ + if is_unit_expr(arg){ + span_lint_and_sugg( + cx, + UNIT_EXPR, + arg.span, + "trailing semicolons can be tricky", + "remove the last semicolon", + "TODO".to_owned() + ) + } } + } + if let ExprKind::Call( _, ref args) = expr.node{ + for ref arg in args{ + if is_unit_expr(arg){ + span_lint_and_sugg( + cx, + UNIT_EXPR, + arg.span, + "trailing semicolons can be tricky", + "remove the last semicolon", + "TODO".to_owned() + ) + } } } } fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { -- cgit 1.4.1-3-g733a5 From e7c5825378166a5ceeedd2b5b5168dd3866bb105 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 14:20:22 -0700 Subject: Fix brace indentation --- clippy_lints/src/is_unit_expr.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 63bdaaa5231..d62436dd80e 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -57,7 +57,8 @@ impl EarlyLintPass for UnitExpr { "remove the last semicolon", "TODO".to_owned() ) - } } + } + } } if let ExprKind::Call( _, ref args) = expr.node{ for ref arg in args{ @@ -70,7 +71,9 @@ impl EarlyLintPass for UnitExpr { "remove the last semicolon", "TODO".to_owned() ) - } } } + } + } + } } fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { -- cgit 1.4.1-3-g733a5 From 34edc3f782a7929fb72efc82929bb070ea74e020 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 15:04:52 -0700 Subject: Handle method calls --- clippy_lints/src/is_unit_expr.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index d62436dd80e..6239fa85077 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Spanned; use utils::{span_lint_and_sugg, snippet}; - +use std::ops::Deref; /// **What it does:** Checks for /// - () being assigned to a variable @@ -34,7 +34,7 @@ impl LintPass for UnitExpr { impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Assign(ref left, ref right) = expr.node { + if let ExprKind::Assign(ref _left, ref right) = expr.node { if is_unit_expr(right){ span_lint_and_sugg( cx, @@ -46,7 +46,7 @@ impl EarlyLintPass for UnitExpr { ) } } - if let ExprKind::MethodCall(_, ref args) = expr.node { + if let ExprKind::MethodCall(ref _left, ref args) = expr.node { for ref arg in args{ if is_unit_expr(arg){ span_lint_and_sugg( @@ -97,15 +97,26 @@ impl EarlyLintPass for UnitExpr { fn is_unit_expr(expr: &Expr)->bool{ match expr.node{ - ExprKind::Block(ref next) => { - let ref final_stmt = &next.stmts[next.stmts.len()-1]; - if let StmtKind::Expr(_) = final_stmt.node{ + ExprKind::Block(ref block) => { + return check_last_stmt_in_block(block); + }, + ExprKind::If(_, ref then, ref else_)=>{ + let check_then = check_last_stmt_in_block(then); + if let Some(ref else_) = *else_{ + return check_then && is_unit_expr(else_.deref()); + } + return check_then; + } + _ => return false, + } +} + +fn check_last_stmt_in_block(block: &Block)->bool{ + let ref final_stmt = &block.stmts[block.stmts.len()-1]; + if let StmtKind::Expr(_) = final_stmt.node{ return false; } else{ return true; } - }, - _ => return false, - } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 789e78e72ed5c6db874ff3446a4817a4bf017990 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 20:36:24 -0700 Subject: Improved spans for lints and support match expressions --- clippy_lints/src/is_unit_expr.rs | 87 ++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 6239fa85077..c919c49a326 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::codemap::Spanned; -use utils::{span_lint_and_sugg, snippet}; use std::ops::Deref; +use syntax::ext::quote::rt::Span; + /// **What it does:** Checks for /// - () being assigned to a variable @@ -35,42 +35,21 @@ impl LintPass for UnitExpr { impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref _left, ref right) = expr.node { - if is_unit_expr(right){ - span_lint_and_sugg( - cx, - UNIT_EXPR, - right.span, - "trailing semicolons can be tricky", - "remove the last semicolon", - "TODO".to_owned() - ) + if let Some(span) = is_unit_expr(right){ + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); } } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { for ref arg in args{ - if is_unit_expr(arg){ - span_lint_and_sugg( - cx, - UNIT_EXPR, - arg.span, - "trailing semicolons can be tricky", - "remove the last semicolon", - "TODO".to_owned() - ) + if let Some(span) = is_unit_expr(arg){ + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); } } } if let ExprKind::Call( _, ref args) = expr.node{ for ref arg in args{ - if is_unit_expr(arg){ - span_lint_and_sugg( - cx, - UNIT_EXPR, - arg.span, - "trailing semicolons can be tricky", - "remove the last semicolon", - "TODO".to_owned() - ) + if let Some(span) = is_unit_expr(arg){ + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); } } } @@ -80,34 +59,48 @@ impl EarlyLintPass for UnitExpr { if let StmtKind::Local(ref local) = stmt.node{ if local.pat.node == PatKind::Wild {return;} if let Some(ref expr) = local.init{ - if is_unit_expr(expr){ - span_lint_and_sugg( - cx, - UNIT_EXPR, - local.span, - "trailing semicolons can be tricky", - "remove the last semicolon", - "TODO".to_owned() - ) - } - } + if let Some(span) = is_unit_expr(expr){ + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); } } } - -fn is_unit_expr(expr: &Expr)->bool{ +} +} +fn is_unit_expr(expr: &Expr)->Option{ match expr.node{ ExprKind::Block(ref block) => { - return check_last_stmt_in_block(block); + if check_last_stmt_in_block(block){ + return Some(block.stmts[block.stmts.len()-1].span.clone()); + } else{ + return None; + } }, ExprKind::If(_, ref then, ref else_)=>{ let check_then = check_last_stmt_in_block(then); if let Some(ref else_) = *else_{ - return check_then && is_unit_expr(else_.deref()); + let check_else = is_unit_expr(*else_); + if let Some(ref expr_else) = check_else{ + return Some(expr_else.clone()); + }else{ + return Some(expr.span.clone()); + } } - return check_then; + if check_then { + return Some(expr.span.clone()); + + } else{ + return Some(expr.span.clone()); + } + }, + ExprKind::Match(ref _pattern, ref arms ) =>{ + for ref arm in arms{ + if let Some(expr) = is_unit_expr(&arm.body){ + return Some(expr); + } + } + return None; } - _ => return false, + _ => return None, } } @@ -117,6 +110,6 @@ fn check_last_stmt_in_block(block: &Block)->bool{ return false; } else{ - return true; + return true; } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 27e55c96ceaf489f74bcbe13c066a9d6b1b18c16 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 20:45:40 -0700 Subject: Switch back to manual deref --- clippy_lints/src/is_unit_expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index c919c49a326..ddcb5c5fc78 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -78,7 +78,7 @@ fn is_unit_expr(expr: &Expr)->Option{ ExprKind::If(_, ref then, ref else_)=>{ let check_then = check_last_stmt_in_block(then); if let Some(ref else_) = *else_{ - let check_else = is_unit_expr(*else_); + let check_else = is_unit_expr(else_.deref()); if let Some(ref expr_else) = check_else{ return Some(expr_else.clone()); }else{ -- cgit 1.4.1-3-g733a5 From 93e78c81a1124566e079a065b631727b552fbba6 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sat, 2 Sep 2017 21:33:26 -0700 Subject: RustFmt changes --- clippy_lints/src/is_unit_expr.rs | 105 ++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index ddcb5c5fc78..be6a750fec9 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -4,18 +4,21 @@ use std::ops::Deref; use syntax::ext::quote::rt::Span; -/// **What it does:** Checks for +/// **What it does:** Checks for /// - () being assigned to a variable /// - () being passed to a function /// -/// **Why is this bad?** It is extremely unlikely that a user intended to assign '()' to valiable. Instead, -/// Unit is what a block evaluates to when it returns nothing. This is typically caused by a trailing -/// unintended semicolon. +/// **Why is this bad?** It is extremely unlikely that a user intended to +/// assign '()' to valiable. Instead, +/// Unit is what a block evaluates to when it returns nothing. This is +/// typically caused by a trailing +/// unintended semicolon. /// /// **Known problems:** None. /// /// **Example:** -/// * `let x = {"foo" ;}` when the user almost certainly intended `let x ={"foo"}` +/// * `let x = {"foo" ;}` when the user almost certainly intended `let x +/// ={"foo"}` declare_lint! { pub UNIT_EXPR, @@ -35,81 +38,79 @@ impl LintPass for UnitExpr { impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref _left, ref right) = expr.node { - if let Some(span) = is_unit_expr(right){ - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + if let Some(span) = is_unit_expr(right) { + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); } } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { - for ref arg in args{ - if let Some(span) = is_unit_expr(arg){ + for ref arg in args { + if let Some(span) = is_unit_expr(arg) { cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); - } + } } } - if let ExprKind::Call( _, ref args) = expr.node{ - for ref arg in args{ - if let Some(span) = is_unit_expr(arg){ - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); - } - } + if let ExprKind::Call(_, ref args) = expr.node { + for ref arg in args { + if let Some(span) = is_unit_expr(arg) { + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + } + } } } fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { - if let StmtKind::Local(ref local) = stmt.node{ - if local.pat.node == PatKind::Wild {return;} - if let Some(ref expr) = local.init{ - if let Some(span) = is_unit_expr(expr){ - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + if let StmtKind::Local(ref local) = stmt.node { + if local.pat.node == PatKind::Wild { + return; } + if let Some(ref expr) = local.init { + if let Some(span) = is_unit_expr(expr) { + cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + } + } + } } } -} -} -fn is_unit_expr(expr: &Expr)->Option{ - match expr.node{ - ExprKind::Block(ref block) => { - if check_last_stmt_in_block(block){ - return Some(block.stmts[block.stmts.len()-1].span.clone()); - } else{ - return None; - } +fn is_unit_expr(expr: &Expr) -> Option { + match expr.node { + ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { + return Some(block.stmts[block.stmts.len() - 1].span.clone()); + } else { + return None; }, - ExprKind::If(_, ref then, ref else_)=>{ + ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); - if let Some(ref else_) = *else_{ + if let Some(ref else_) = *else_ { let check_else = is_unit_expr(else_.deref()); - if let Some(ref expr_else) = check_else{ + if let Some(ref expr_else) = check_else { return Some(expr_else.clone()); - }else{ + } else { return Some(expr.span.clone()); } - } - if check_then { + } + if check_then { return Some(expr.span.clone()); - - } else{ + } else { return Some(expr.span.clone()); } }, - ExprKind::Match(ref _pattern, ref arms ) =>{ - for ref arm in arms{ - if let Some(expr) = is_unit_expr(&arm.body){ + ExprKind::Match(ref _pattern, ref arms) => { + for ref arm in arms { + if let Some(expr) = is_unit_expr(&arm.body) { return Some(expr); } } return None; - } + }, _ => return None, } } -fn check_last_stmt_in_block(block: &Block)->bool{ - let ref final_stmt = &block.stmts[block.stmts.len()-1]; - if let StmtKind::Expr(_) = final_stmt.node{ - return false; - } - else{ - return true; - } -} \ No newline at end of file +fn check_last_stmt_in_block(block: &Block) -> bool { + let ref final_stmt = &block.stmts[block.stmts.len() - 1]; + if let StmtKind::Expr(_) = final_stmt.node { + return false; + } else { + return true; + } +} -- cgit 1.4.1-3-g733a5 From 0233d9b0e7ccaa527b54f3866bbbac1d30cbfd63 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 08:31:15 -0700 Subject: Fix false positives in assignment inside the else condition --- clippy_lints/src/is_unit_expr.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index be6a750fec9..82460f82fa1 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -84,14 +84,12 @@ fn is_unit_expr(expr: &Expr) -> Option { let check_else = is_unit_expr(else_.deref()); if let Some(ref expr_else) = check_else { return Some(expr_else.clone()); - } else { - return Some(expr.span.clone()); - } + } } if check_then { return Some(expr.span.clone()); } else { - return Some(expr.span.clone()); + return None; } }, ExprKind::Match(ref _pattern, ref arms) => { -- cgit 1.4.1-3-g733a5 From 33e86407fd0abff6c42efc404b321b8dbcba3533 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 08:56:34 -0700 Subject: early tests --- tests/ui/is_unit_expr.rs | 14 ++++++++++++++ tests/ui/is_unit_expr.stderr | 0 2 files changed, 14 insertions(+) create mode 100644 tests/ui/is_unit_expr.rs create mode 100644 tests/ui/is_unit_expr.stderr diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs new file mode 100644 index 00000000000..0919e7f3675 --- /dev/null +++ b/tests/ui/is_unit_expr.rs @@ -0,0 +1,14 @@ + +#![feature(plugin)] +#[plugin(clippy)] +#[warn(unit_expr)] +#[allow(unused_variables)] +#[allow(no_effect)] + +fn main() { + let x = { + "foo"; + "baz"; + }; + +} diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From 436d838ad758e609667623ce5793a9d5bc3e12ff Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 09:12:55 -0700 Subject: Update unit tests --- tests/ui/is_unit_expr.stderr | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index e69de29bb2d..c6e2c3aaf7b 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -0,0 +1,16 @@ +error: unknown lint: `unit_expr` + --> $DIR/is_unit_expr.rs:4:8 + | +4 | #[warn(unit_expr)] + | ^^^^^^^^^ + | + = note: `-D unknown-lints` implied by `-D warnings` + +error: unknown lint: `no_effect` + --> $DIR/is_unit_expr.rs:6:9 + | +6 | #[allow(no_effect)] + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 98ec8657e4b85229b1472b1caf8421e88a575097 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 09:52:28 -0700 Subject: Improve the lint message --- clippy_lints/src/is_unit_expr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 82460f82fa1..9db045ccd91 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use syntax::ast::*; use std::ops::Deref; use syntax::ext::quote::rt::Span; - +use utils::span_note_and_lint; /// **What it does:** Checks for /// - () being assigned to a variable @@ -39,20 +39,20 @@ impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref _left, ref right) = expr.node { if let Some(span) = is_unit_expr(right) { - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); } } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { for ref arg in args { if let Some(span) = is_unit_expr(arg) { - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); } } } if let ExprKind::Call(_, ref args) = expr.node { for ref arg in args { if let Some(span) = is_unit_expr(arg) { - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); } } } @@ -65,7 +65,7 @@ impl EarlyLintPass for UnitExpr { } if let Some(ref expr) = local.init { if let Some(span) = is_unit_expr(expr) { - cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon"); + span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); } } } -- cgit 1.4.1-3-g733a5 From eb7955b2658edef5745f105ed3025b2799d495b1 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 10:39:28 -0700 Subject: More relevant tests --- tests/ui/is_unit_expr.rs | 7 +++---- tests/ui/is_unit_expr.stderr | 31 +++++++++++++++++-------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 0919e7f3675..60b07f45c6a 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -1,9 +1,8 @@ - #![feature(plugin)] -#[plugin(clippy)] -#[warn(unit_expr)] +#![plugin(clippy)] + +#![warn(unit_expr)] #[allow(unused_variables)] -#[allow(no_effect)] fn main() { let x = { diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index c6e2c3aaf7b..73b1e04cba7 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -1,16 +1,19 @@ -error: unknown lint: `unit_expr` - --> $DIR/is_unit_expr.rs:4:8 - | -4 | #[warn(unit_expr)] - | ^^^^^^^^^ - | - = note: `-D unknown-lints` implied by `-D warnings` +error: This expression assigns the Unit type () + --> $DIR/is_unit_expr.rs:8:13 + | +8 | let x = { + | _____________^ +9 | | "foo"; +10 | | "baz"; +11 | | }; + | |_____^ + | + = note: `-D unit-expr` implied by `-D warnings` +note: Consider removing the trailing semicolon + --> $DIR/is_unit_expr.rs:10:9 + | +10 | "baz"; + | ^^^^^^ -error: unknown lint: `no_effect` - --> $DIR/is_unit_expr.rs:6:9 - | -6 | #[allow(no_effect)] - | ^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 1c7583776b8d87bf5c73bfe9298f463c278615e8 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 11:17:20 -0700 Subject: Don't trigger lint on break or return --- clippy_lints/src/is_unit_expr.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 9db045ccd91..c9bba0c532d 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -106,9 +106,17 @@ fn is_unit_expr(expr: &Expr) -> Option { fn check_last_stmt_in_block(block: &Block) -> bool { let ref final_stmt = &block.stmts[block.stmts.len() - 1]; - if let StmtKind::Expr(_) = final_stmt.node { - return false; - } else { - return true; + + match final_stmt.node{ + StmtKind::Expr(_) => return false, + StmtKind::Semi(ref expr)=>{ + match expr.node{ + ExprKind::Break(_,_) => return false, + ExprKind::Ret(_) => return false, + _ => return true, + } + }, + _ => return true, } + } -- cgit 1.4.1-3-g733a5 From e0caf26586caf8df3b683f4fe6ee4979a3c9e8dc Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 11:19:59 -0700 Subject: RustFmt file and tests --- clippy_lints/src/is_unit_expr.rs | 53 +++++++++++++++++++++++++++++----------- tests/ui/is_unit_expr.rs | 2 -- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index c9bba0c532d..c3860d2b92a 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -39,20 +39,41 @@ impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref _left, ref right) = expr.node { if let Some(span) = is_unit_expr(right) { - span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); + span_note_and_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression assigns the Unit type ()", + span, + "Consider removing the trailing semicolon", + ); } } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { for ref arg in args { if let Some(span) = is_unit_expr(arg) { - span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); + span_note_and_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression assigns the Unit type ()", + span, + "Consider removing the trailing semicolon", + ); } } } if let ExprKind::Call(_, ref args) = expr.node { for ref arg in args { if let Some(span) = is_unit_expr(arg) { - span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); + span_note_and_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression assigns the Unit type ()", + span, + "Consider removing the trailing semicolon", + ); } } } @@ -65,7 +86,14 @@ impl EarlyLintPass for UnitExpr { } if let Some(ref expr) = local.init { if let Some(span) = is_unit_expr(expr) { - span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon"); + span_note_and_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression assigns the Unit type ()", + span, + "Consider removing the trailing semicolon", + ); } } } @@ -84,7 +112,7 @@ fn is_unit_expr(expr: &Expr) -> Option { let check_else = is_unit_expr(else_.deref()); if let Some(ref expr_else) = check_else { return Some(expr_else.clone()); - } + } } if check_then { return Some(expr.span.clone()); @@ -106,17 +134,14 @@ fn is_unit_expr(expr: &Expr) -> Option { fn check_last_stmt_in_block(block: &Block) -> bool { let ref final_stmt = &block.stmts[block.stmts.len() - 1]; - - match final_stmt.node{ + + match final_stmt.node { StmtKind::Expr(_) => return false, - StmtKind::Semi(ref expr)=>{ - match expr.node{ - ExprKind::Break(_,_) => return false, - ExprKind::Ret(_) => return false, - _ => return true, - } + StmtKind::Semi(ref expr) => match expr.node { + ExprKind::Break(_, _) => return false, + ExprKind::Ret(_) => return false, + _ => return true, }, _ => return true, } - } diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 60b07f45c6a..63f3fcfa28c 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -1,6 +1,5 @@ #![feature(plugin)] #![plugin(clippy)] - #![warn(unit_expr)] #[allow(unused_variables)] @@ -9,5 +8,4 @@ fn main() { "foo"; "baz"; }; - } -- cgit 1.4.1-3-g733a5 From 6657d4e7ffac84cb51d3a7d9137132480992817e Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 12:50:02 -0700 Subject: Remove direct call for Deref Remove "assigns" from the lint --- clippy_lints/src/is_unit_expr.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index c3860d2b92a..ad55d0b0973 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -1,6 +1,5 @@ use rustc::lint::*; use syntax::ast::*; -use std::ops::Deref; use syntax::ext::quote::rt::Span; use utils::span_note_and_lint; @@ -43,7 +42,7 @@ impl EarlyLintPass for UnitExpr { cx, UNIT_EXPR, expr.span, - "This expression assigns the Unit type ()", + "This expression evaluates to the Unit type ()", span, "Consider removing the trailing semicolon", ); @@ -56,7 +55,7 @@ impl EarlyLintPass for UnitExpr { cx, UNIT_EXPR, expr.span, - "This expression assigns the Unit type ()", + "This expression evaluates to the Unit type ()", span, "Consider removing the trailing semicolon", ); @@ -70,7 +69,7 @@ impl EarlyLintPass for UnitExpr { cx, UNIT_EXPR, expr.span, - "This expression assigns the Unit type ()", + "This expression evaluates to the Unit type ()", span, "Consider removing the trailing semicolon", ); @@ -90,7 +89,7 @@ impl EarlyLintPass for UnitExpr { cx, UNIT_EXPR, expr.span, - "This expression assigns the Unit type ()", + "This expression evaluates to the Unit type ()", span, "Consider removing the trailing semicolon", ); @@ -109,7 +108,7 @@ fn is_unit_expr(expr: &Expr) -> Option { ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); if let Some(ref else_) = *else_ { - let check_else = is_unit_expr(else_.deref()); + let check_else = is_unit_expr(&else_); if let Some(ref expr_else) = check_else { return Some(expr_else.clone()); } -- cgit 1.4.1-3-g733a5 From 8b53f2238bb0ea6645a8ea0e4a5af16ee550399f Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 13:39:49 -0700 Subject: Fix all the clippy lints Add false positive tests --- clippy_lints/src/is_unit_expr.rs | 33 +++++++++++++------------- tests/ui/is_unit_expr.rs | 34 +++++++++++++++++++++++++++ tests/ui/is_unit_expr.stderr | 51 +++++++++++++++++++++++++++++++++------- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index ad55d0b0973..abaa1edf090 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -49,7 +49,7 @@ impl EarlyLintPass for UnitExpr { } } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { - for ref arg in args { + for arg in args { if let Some(span) = is_unit_expr(arg) { span_note_and_lint( cx, @@ -63,7 +63,7 @@ impl EarlyLintPass for UnitExpr { } } if let ExprKind::Call(_, ref args) = expr.node { - for ref arg in args { + for arg in args { if let Some(span) = is_unit_expr(arg) { span_note_and_lint( cx, @@ -101,46 +101,45 @@ impl EarlyLintPass for UnitExpr { fn is_unit_expr(expr: &Expr) -> Option { match expr.node { ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { - return Some(block.stmts[block.stmts.len() - 1].span.clone()); + Some(block.stmts[block.stmts.len() - 1].span) } else { - return None; + None }, ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); if let Some(ref else_) = *else_ { - let check_else = is_unit_expr(&else_); + let check_else = is_unit_expr(else_); if let Some(ref expr_else) = check_else { - return Some(expr_else.clone()); + return Some(*expr_else); } } if check_then { - return Some(expr.span.clone()); + Some(expr.span) } else { - return None; + None } }, ExprKind::Match(ref _pattern, ref arms) => { - for ref arm in arms { + for arm in arms { if let Some(expr) = is_unit_expr(&arm.body) { return Some(expr); } } - return None; + None }, - _ => return None, + _ => None, } } fn check_last_stmt_in_block(block: &Block) -> bool { - let ref final_stmt = &block.stmts[block.stmts.len() - 1]; + let final_stmt = &block.stmts[block.stmts.len() - 1]; match final_stmt.node { - StmtKind::Expr(_) => return false, + StmtKind::Expr(_) => false, StmtKind::Semi(ref expr) => match expr.node { - ExprKind::Break(_, _) => return false, - ExprKind::Ret(_) => return false, - _ => return true, + ExprKind::Break(_, _) | ExprKind::Ret(_) => false, + _ => true, }, - _ => return true, + _ => true, } } diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 63f3fcfa28c..8a986494eaf 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -4,8 +4,42 @@ #[allow(unused_variables)] fn main() { + + //lint should note removing the semicolon from "baz" let x = { "foo"; "baz"; }; + + + //lint should ignore false positive. + let y = if true{ + "foo" + } else{ + return; + }; + + //lint should note removing semicolon from "bar" + let z = if true{ + "foo"; + } else{ + "bar"; + }; + + + let a1 = Some(5); + + //lint should ignore false positive + let a2 = match a1 { + Some(x) => x, + _ => {return;}, + }; + + //lint should note removing the semicolon after `x;` + let a3 = match a1 { + Some(x) => {x;}, + _ => {0;}, + }; + + } diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index 73b1e04cba7..dafebb1c82a 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -1,19 +1,52 @@ -error: This expression assigns the Unit type () - --> $DIR/is_unit_expr.rs:8:13 +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:9:13 | -8 | let x = { +9 | let x = { | _____________^ -9 | | "foo"; -10 | | "baz"; -11 | | }; +10 | | "foo"; +11 | | "baz"; +12 | | }; | |_____^ | = note: `-D unit-expr` implied by `-D warnings` note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:10:9 + --> $DIR/is_unit_expr.rs:11:9 | -10 | "baz"; +11 | "baz"; | ^^^^^^ -error: aborting due to previous error +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:23:13 + | +23 | let z = if true{ + | _____________^ +24 | | "foo"; +25 | | } else{ +26 | | "bar"; +27 | | }; + | |_____^ + | +note: Consider removing the trailing semicolon + --> $DIR/is_unit_expr.rs:26:9 + | +26 | "bar"; + | ^^^^^^ + +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:39:14 + | +39 | let a3 = match a1 { + | ______________^ +40 | | Some(x) => {x;}, +41 | | _ => {0;}, +42 | | }; + | |_____^ + | +note: Consider removing the trailing semicolon + --> $DIR/is_unit_expr.rs:40:21 + | +40 | Some(x) => {x;}, + | ^^ + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 44f694d0a1e3d78528c437b0acfabcfa5e230862 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 13:46:49 -0700 Subject: Rustfmt tests --- tests/ui/is_unit_expr.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 8a986494eaf..d1f45d517b0 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -4,42 +4,45 @@ #[allow(unused_variables)] fn main() { - - //lint should note removing the semicolon from "baz" + // lint should note removing the semicolon from "baz" let x = { "foo"; "baz"; }; - //lint should ignore false positive. - let y = if true{ - "foo" - } else{ + // lint should ignore false positive. + let y = if true { + "foo" + } else { return; }; - //lint should note removing semicolon from "bar" - let z = if true{ + // lint should note removing semicolon from "bar" + let z = if true { "foo"; - } else{ + } else { "bar"; }; let a1 = Some(5); - //lint should ignore false positive + // lint should ignore false positive let a2 = match a1 { Some(x) => x, - _ => {return;}, + _ => { + return; + }, }; - //lint should note removing the semicolon after `x;` + // lint should note removing the semicolon after `x;` let a3 = match a1 { - Some(x) => {x;}, - _ => {0;}, + Some(x) => { + x; + }, + _ => { + 0; + }, }; - - } -- cgit 1.4.1-3-g733a5 From 4807909152d64827363c712242ef6831b32533c9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 3 Sep 2017 13:55:45 -0700 Subject: Rustup to rustc 1.22.0-nightly (744dd6c1d 2017-09-02) (fixes #2013) --- clippy_lints/src/loops.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 439a82e41ef..68830eacfa3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -622,7 +622,7 @@ fn check_for_loop_range<'a, 'tcx>( let parent_id = cx.tcx.hir.get_parent(expr.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_id); let region_maps = cx.tcx.region_maps(parent_def_id); - let pat_extent = region_maps.var_scope(pat.id); + let pat_extent = region_maps.var_scope(pat.hir_id.local_id); if region_maps.is_subscope_of(indexed_extent, pat_extent) { return; } @@ -1064,10 +1064,11 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { Def::Local(..) | Def::Upvar(..) => { let def_id = def.def_id(); let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); + let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); let parent_id = self.cx.tcx.hir.get_parent(expr.id); let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); - let extent = self.cx.tcx.region_maps(parent_def_id).var_scope(node_id); + let extent = self.cx.tcx.region_maps(parent_def_id).var_scope(hir_id.local_id); self.indexed.insert(seqvar.segments[0].name, Some(extent)); return; // no need to walk further } -- cgit 1.4.1-3-g733a5 From 5bc0a2dbfc224b6960059a79ea4c2e3f96dc7b62 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 3 Sep 2017 13:57:40 -0700 Subject: Bump to 0.0.156 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68753594a7c..e3231d9f38e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.156 +* Update to *rustc 1.22.0-nightly (744dd6c1d 2017-09-02)* + ## 0.0.155 * Update to *rustc 1.21.0-nightly (c11f689d2 2017-08-29)* * New lint: [`infinite_iter`], [`maybe_infinite_iter`], [`cast_lossless`] diff --git a/Cargo.toml b/Cargo.toml index 6ecfa3dfe50..959fdfb0c1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.155" +version = "0.0.156" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.155", path = "clippy_lints" } +clippy_lints = { version = "0.0.156", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7aae50a4745..c3a6200f209 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.155" +version = "0.0.156" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 0d9f56674daf4acb7d2fdfdcee2211052837b873 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 3 Sep 2017 14:01:29 -0700 Subject: Mention the false positive --- clippy_lints/src/is_unit_expr.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index abaa1edf090..4f3c755d731 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -134,6 +134,8 @@ fn is_unit_expr(expr: &Expr) -> Option { fn check_last_stmt_in_block(block: &Block) -> bool { let final_stmt = &block.stmts[block.stmts.len() - 1]; + + //Made a choice here to risk false positives on divergent macro invocations like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, StmtKind::Semi(ref expr) => match expr.node { -- cgit 1.4.1-3-g733a5 From 35eda0531a51115cdae893fac68b6fae976cab1f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 3 Sep 2017 14:14:07 -0700 Subject: Fix unit_expr expectations and changelog entry --- CHANGELOG.md | 6 +++++- clippy_lints/src/lib.rs | 4 ++-- tests/ui/is_unit_expr.stderr | 49 +++++++++++++++++++++++--------------------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3231d9f38e..94cf6748d0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.156 +## Master +* New lint: [`unit_expr`] + +## 0.0.156 - 2017-09-03 * Update to *rustc 1.22.0-nightly (744dd6c1d 2017-09-02)* ## 0.0.155 @@ -602,6 +605,7 @@ All notable changes to this project will be documented in this file. [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity [`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp +[`unit_expr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_expr [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5b484aceed8..95d45bed133 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -91,8 +91,8 @@ pub mod functions; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; -pub mod is_unit_expr; pub mod infinite_iter; +pub mod is_unit_expr; pub mod items_after_statements; pub mod large_enum_variant; pub mod len_zero; @@ -423,6 +423,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infinite_iter::INFINITE_ITER, + is_unit_expr::UNIT_EXPR, large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, @@ -506,7 +507,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, - is_unit_expr::UNIT_EXPR, print::PRINT_WITH_NEWLINE, ptr::CMP_NULL, ptr::MUT_FROM_REF, diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index dafebb1c82a..2d9fcfff74f 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -1,52 +1,55 @@ error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:9:13 + --> $DIR/is_unit_expr.rs:8:13 | -9 | let x = { +8 | let x = { | _____________^ -10 | | "foo"; -11 | | "baz"; -12 | | }; +9 | | "foo"; +10 | | "baz"; +11 | | }; | |_____^ | = note: `-D unit-expr` implied by `-D warnings` note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:11:9 + --> $DIR/is_unit_expr.rs:10:9 | -11 | "baz"; +10 | "baz"; | ^^^^^^ error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:23:13 + --> $DIR/is_unit_expr.rs:22:13 | -23 | let z = if true{ +22 | let z = if true { | _____________^ -24 | | "foo"; -25 | | } else{ -26 | | "bar"; -27 | | }; +23 | | "foo"; +24 | | } else { +25 | | "bar"; +26 | | }; | |_____^ | note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:26:9 + --> $DIR/is_unit_expr.rs:25:9 | -26 | "bar"; +25 | "bar"; | ^^^^^^ error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:39:14 + --> $DIR/is_unit_expr.rs:40:14 | -39 | let a3 = match a1 { +40 | let a3 = match a1 { | ______________^ -40 | | Some(x) => {x;}, -41 | | _ => {0;}, -42 | | }; +41 | | Some(x) => { +42 | | x; +43 | | }, +... | +46 | | }, +47 | | }; | |_____^ | note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:40:21 + --> $DIR/is_unit_expr.rs:42:13 | -40 | Some(x) => {x;}, - | ^^ +42 | x; + | ^^ error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 25444585592f5da648edd5317fcdd21f2db8bb64 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 3 Sep 2017 14:15:15 -0700 Subject: Run rustfmt --- clippy_lints/src/bytecount.rs | 22 ++++--- clippy_lints/src/copies.rs | 3 +- clippy_lints/src/doc.rs | 10 +-- clippy_lints/src/infinite_iter.rs | 77 ++++++++++++---------- clippy_lints/src/is_unit_expr.rs | 30 +++++---- clippy_lints/src/len_zero.rs | 6 +- clippy_lints/src/methods.rs | 9 +-- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/needless_borrowed_ref.rs | 10 +-- clippy_lints/src/regex.rs | 6 +- clippy_lints/src/shadow.rs | 1 - clippy_lints/src/types.rs | 102 ++++++++++++++++++++---------- clippy_lints/src/use_self.rs | 9 +-- clippy_lints/src/utils/higher.rs | 4 +- clippy_lints/src/utils/hir_utils.rs | 14 ++-- clippy_lints/src/utils/inspector.rs | 2 +- 16 files changed, 175 insertions(+), 131 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index a3a53b6dd47..1d7afbe084d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -97,19 +97,25 @@ fn get_pat_name(pat: &Pat) -> Option { match pat.node { PatKind::Binding(_, _, ref spname, _) => Some(spname.node), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), - PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), - _ => None + PatKind::Box(ref p) | + PatKind::Ref(ref p, _) => get_pat_name(&*p), + _ => None, } } fn get_path_name(expr: &Expr) -> Option { match expr.node { - ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprBlock(ref b) => if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { None }, + ExprBox(ref e) | + ExprAddrOf(_, ref e) | + ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), + ExprBlock(ref b) => { + if b.stmts.is_empty() { + b.expr.as_ref().and_then(|p| get_path_name(p)) + } else { + None + } + }, ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), - _ => None + _ => None, } } - diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 06c986c6086..f9e11d06882 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -67,7 +67,8 @@ declare_lint! { /// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns). /// /// **Known problems:** False positive possible with order dependent `match` -/// (see issue [#860](https://github.com/rust-lang-nursery/rust-clippy/issues/860)). +/// (see issue +/// [#860](https://github.com/rust-lang-nursery/rust-clippy/issues/860)). /// /// **Example:** /// ```rust,ignore diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index f72a13147dc..8977ea437d1 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -94,10 +94,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( return ( doc.to_owned(), vec![ - ( - doc.len(), - span.with_lo(span.lo() + BytePos(prefix.len() as u32)), - ), + (doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32))), ], ); } @@ -112,10 +109,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( debug_assert_eq!(offset as u32 as usize, offset); contains_initial_stars |= line.trim_left().starts_with('*'); // +1 for the newline - sizes.push(( - line.len() + 1, - span.with_lo(span.lo() + BytePos(offset as u32)), - )); + sizes.push((line.len() + 1, span.with_lo(span.lo() + BytePos(offset as u32)))); } if !contains_initial_stars { return (doc.to_string(), sizes); diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 53f74c7afd6..3e2cfc033fc 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -50,9 +50,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let (lint, msg) = match complete_infinite_iter(cx, expr) { Infinite => (INFINITE_ITER, "infinite iteration detected"), - MaybeInfinite => (MAYBE_INFINITE_ITER, - "possible infinite iteration detected"), - Finite => { return; } + MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"), + Finite => { + return; + }, }; span_lint(cx, lint, expr.span, msg) } @@ -62,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { enum Finiteness { Infinite, MaybeInfinite, - Finite + Finite, } use self::Finiteness::{Infinite, MaybeInfinite, Finite}; @@ -71,16 +72,18 @@ impl Finiteness { fn and(self, b: Self) -> Self { match (self, b) { (Finite, _) | (_, Finite) => Finite, - (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, - _ => Infinite + (MaybeInfinite, _) | + (_, MaybeInfinite) => MaybeInfinite, + _ => Infinite, } } fn or(self, b: Self) -> Self { match (self, b) { (Infinite, _) | (_, Infinite) => Infinite, - (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, - _ => Finite + (MaybeInfinite, _) | + (_, MaybeInfinite) => MaybeInfinite, + _ => Finite, } } } @@ -102,7 +105,7 @@ enum Heuristic { /// infinite if any of the supplied arguments is Any, /// infinite if all of the supplied arguments are - All + All, } use self::Heuristic::{Always, First, Any, All}; @@ -112,7 +115,7 @@ use self::Heuristic::{Always, First, Any, All}; /// returns an infinite or possibly infinite iterator. The finiteness /// is an upper bound, e.g. some methods can return a possibly /// infinite iterator at worst, e.g. `take_while`. -static HEURISTICS : &[(&str, usize, Heuristic, Finiteness)] = &[ +static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[ ("zip", 2, All, Infinite), ("chain", 2, Any, Infinite), ("cycle", 1, Always, Infinite), @@ -131,7 +134,7 @@ static HEURISTICS : &[(&str, usize, Heuristic, Finiteness)] = &[ ("flat_map", 2, First, Infinite), ("unzip", 1, First, Infinite), ("take_while", 2, First, MaybeInfinite), - ("scan", 3, First, MaybeInfinite) + ("scan", 3, First, MaybeInfinite), ]; fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { @@ -140,11 +143,11 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { for &(name, len, heuristic, cap) in HEURISTICS.iter() { if method.name == name && args.len() == len { return (match heuristic { - Always => Infinite, - First => is_infinite(cx, &args[0]), - Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), - All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), - }).and(cap); + Always => Infinite, + First => is_infinite(cx, &args[0]), + Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), + All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), + }).and(cap); } } if method.name == "flat_map" && args.len() == 2 { @@ -155,35 +158,39 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { } Finite }, - ExprBlock(ref block) => - block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), - ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), + ExprBlock(ref block) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), + ExprBox(ref e) | + ExprAddrOf(_, ref e) => is_infinite(cx, e), ExprCall(ref path, _) => { if let ExprPath(ref qpath) = path.node { match_qpath(qpath, &paths::REPEAT).into() - } else { Finite } + } else { + Finite + } }, ExprStruct(..) => { - higher::range(expr).map_or(false, |r| r.end.is_none()).into() + higher::range(expr) + .map_or(false, |r| r.end.is_none()) + .into() }, - _ => Finite + _ => Finite, } } /// the names and argument lengths of methods that *may* exhaust their /// iterators -static POSSIBLY_COMPLETING_METHODS : &[(&str, usize)] = &[ +static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[ ("find", 2), ("rfind", 2), ("position", 2), ("rposition", 2), ("any", 2), - ("all", 2) + ("all", 2), ]; /// the names and argument lengths of methods that *always* exhaust /// their iterators -static COMPLETING_METHODS : &[(&str, usize)] = &[ +static COMPLETING_METHODS: &[(&str, usize)] = &[ ("count", 1), ("collect", 1), ("fold", 3), @@ -196,7 +203,7 @@ static COMPLETING_METHODS : &[(&str, usize)] = &[ ("min_by", 2), ("min_by_key", 2), ("sum", 1), - ("product", 1) + ("product", 1), ]; fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { @@ -213,20 +220,24 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { } } if method.name == "last" && args.len() == 1 && - get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR).map_or(false, - |id| !implements_trait(cx, - cx.tables.expr_ty(&args[0]), - id, - &[])) { + get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR).map_or( + false, + |id| { + !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]) + }, + ) + { return is_infinite(cx, &args[0]); } }, ExprBinary(op, ref l, ref r) => { if op.node.is_comparison() { - return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite) + return is_infinite(cx, l).and(is_infinite(cx, r)).and( + MaybeInfinite, + ); } }, //TODO: ExprLoop + Match - _ => () + _ => (), } Finite } diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 4f3c755d731..5939cd36bf8 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -42,7 +42,7 @@ impl EarlyLintPass for UnitExpr { cx, UNIT_EXPR, expr.span, - "This expression evaluates to the Unit type ()", + "This expression evaluates to the Unit type ()", span, "Consider removing the trailing semicolon", ); @@ -100,10 +100,12 @@ impl EarlyLintPass for UnitExpr { } fn is_unit_expr(expr: &Expr) -> Option { match expr.node { - ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { - Some(block.stmts[block.stmts.len() - 1].span) - } else { - None + ExprKind::Block(ref block) => { + if check_last_stmt_in_block(block) { + Some(block.stmts[block.stmts.len() - 1].span) + } else { + None + } }, ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); @@ -113,11 +115,7 @@ fn is_unit_expr(expr: &Expr) -> Option { return Some(*expr_else); } } - if check_then { - Some(expr.span) - } else { - None - } + if check_then { Some(expr.span) } else { None } }, ExprKind::Match(ref _pattern, ref arms) => { for arm in arms { @@ -135,12 +133,16 @@ fn check_last_stmt_in_block(block: &Block) -> bool { let final_stmt = &block.stmts[block.stmts.len() - 1]; - //Made a choice here to risk false positives on divergent macro invocations like `panic!()` + // Made a choice here to risk false positives on divergent macro invocations + // like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, - StmtKind::Semi(ref expr) => match expr.node { - ExprKind::Break(_, _) | ExprKind::Ret(_) => false, - _ => true, + StmtKind::Semi(ref expr) => { + match expr.node { + ExprKind::Break(_, _) | + ExprKind::Ret(_) => false, + _ => true, + } }, _ => true, } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index fceffc4c665..798d48f177d 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -121,11 +121,7 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai } } - if cx.access_levels.is_exported(visited_trait.id) && - trait_items - .iter() - .any(|i| is_named_self(cx, i, "len")) - { + if cx.access_levels.is_exported(visited_trait.id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { let mut current_and_super_traits = HashSet::new(); fill_trait_set(visited_trait, &mut current_and_super_traits, cx); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index c47af20e148..cfaa9f698e0 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1463,14 +1463,15 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; match_path(path, name) && - path.segments.last().map_or(false, |s| { - if s.parameters.parenthesized { + path.segments.last().map_or( + false, + |s| if s.parameters.parenthesized { false } else { s.parameters.types.len() == 1 && (is_self_ty(&s.parameters.types[0]) || is_ty(&*s.parameters.types[0], self_ty)) - } - }) + }, + ) } else { false } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 21e19a3af84..9ce7df474a3 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -23,6 +23,7 @@ // // // +// // rs#L246 // diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 3f7ccca23b4..0aa741db076 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -8,7 +8,8 @@ use utils::{span_lint_and_then, in_macro, snippet}; /// **What it does:** Checks for useless borrowed references. /// -/// **Why is this bad?** It is mostly useless and make the code look more complex than it +/// **Why is this bad?** It is mostly useless and make the code look more +/// complex than it /// actually is. /// /// **Known problems:** It seems that the `&ref` pattern is sometimes useful. @@ -21,12 +22,14 @@ use utils::{span_lint_and_then, in_macro, snippet}; /// /// fn foo(a: &Animal, b: &Animal) { /// match (a, b) { -/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error +/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime +/// mismatch error /// (&Animal::Dog(ref c), &Animal::Dog(_)) => () /// } /// } /// ``` -/// There is a lifetime mismatch error for `k` (indeed a and b have distinct lifetime). +/// There is a lifetime mismatch error for `k` (indeed a and b have distinct +/// lifetime). /// This can be fixed by using the `&ref` pattern. /// However, the code can also be fixed by much cleaner ways /// @@ -77,4 +80,3 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { }} } } - diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 6ee357fd81f..c1011168c52 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -139,11 +139,7 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { match (si.next(), si.next()) { (Some((l, _)), Some((h, _))) => { - Span::new( - base.lo() + BytePos(l as u32), - base.lo() + BytePos(h as u32), - base.ctxt(), - ) + Span::new(base.lo() + BytePos(l as u32), base.lo() + BytePos(h as u32), base.ctxt()) }, _ => base, } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index ccb339390b1..5649847b334 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -390,4 +390,3 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { fn path_eq_name(name: Name, path: &Path) -> bool { !path.is_global() && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() } - diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index eaa01fb1d82..05a498ff262 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -182,12 +182,18 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { match *qpath { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); - for ty in p.segments.iter().flat_map(|seg| seg.parameters.types.iter()) { + for ty in p.segments.iter().flat_map( + |seg| seg.parameters.types.iter(), + ) + { check_ty(cx, ty, is_local); } }, QPath::Resolved(None, ref p) => { - for ty in p.segments.iter().flat_map(|seg| seg.parameters.types.iter()) { + for ty in p.segments.iter().flat_map( + |seg| seg.parameters.types.iter(), + ) + { check_ty(cx, ty, is_local); } }, @@ -523,21 +529,25 @@ declare_lint! { /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { match typ.sty { - ty::TyInt(i) => match i { - IntTy::Is => tcx.data_layout.pointer_size.bits(), - IntTy::I8 => 8, - IntTy::I16 => 16, - IntTy::I32 => 32, - IntTy::I64 => 64, - IntTy::I128 => 128, + ty::TyInt(i) => { + match i { + IntTy::Is => tcx.data_layout.pointer_size.bits(), + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, + } }, - ty::TyUint(i) => match i { - UintTy::Us => tcx.data_layout.pointer_size.bits(), - UintTy::U8 => 8, - UintTy::U16 => 16, - UintTy::U32 => 32, - UintTy::U64 => 64, - UintTy::U128 => 128, + ty::TyUint(i) => { + match i { + UintTy::Us => tcx.data_layout.pointer_size.bits(), + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, + } }, _ => 0, } @@ -583,14 +593,14 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t } fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { - span_lint_and_sugg(cx, - CAST_LOSSLESS, - expr.span, - &format!("casting {} to {} may become silently lossy if types change", - cast_from, - cast_to), - "try", - format!("{}::from({})", cast_to, &snippet(cx, op.span, ".."))); + span_lint_and_sugg( + cx, + CAST_LOSSLESS, + expr.span, + &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to), + "try", + format!("{}::from({})", cast_to, &snippet(cx, op.span, "..")), + ); } enum ArchSuffix { @@ -680,8 +690,9 @@ fn check_lossless(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_ let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); - if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && - from_nbits < to_nbits && !cast_signed_to_unsigned { + if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && + !cast_signed_to_unsigned + { span_lossless_lint(cx, expr, op, cast_from, cast_to); } } @@ -776,7 +787,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { ); } if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = - (&cast_from.sty, &cast_to.sty) { + (&cast_from.sty, &cast_to.sty) + { span_lossless_lint(cx, expr, ex, cast_from, cast_to); } }, @@ -1011,7 +1023,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { /// **Known problems:** For `usize` the size of the current compile target will /// be assumed (e.g. 64 bits on 64 bit systems). This means code that uses such /// a comparison to detect target pointer width will trigger this lint. One can -/// use `mem::sizeof` and compare its value or conditional compilation attributes +/// use `mem::sizeof` and compare its value or conditional compilation +/// attributes /// like `#[cfg(target_pointer_width = "64")] ..` instead. /// /// **Example:** @@ -1209,7 +1222,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { /// will mistakenly imply that it is possible for `x` to be outside the range of /// `u8`. /// -/// **Known problems:** https://github.com/rust-lang-nursery/rust-clippy/issues/886 +/// **Known problems:** +/// https://github.com/rust-lang-nursery/rust-clippy/issues/886 /// /// **Example:** /// ```rust @@ -1290,9 +1304,18 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( ty::TyInt(int_ty) => { Some(match int_ty { IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), - IntTy::I16 => (FullInt::S(i128::from(i16::min_value())), FullInt::S(i128::from(i16::max_value()))), - IntTy::I32 => (FullInt::S(i128::from(i32::min_value())), FullInt::S(i128::from(i32::max_value()))), - IntTy::I64 => (FullInt::S(i128::from(i64::min_value())), FullInt::S(i128::from(i64::max_value()))), + IntTy::I16 => ( + FullInt::S(i128::from(i16::min_value())), + FullInt::S(i128::from(i16::max_value())), + ), + IntTy::I32 => ( + FullInt::S(i128::from(i32::min_value())), + FullInt::S(i128::from(i32::max_value())), + ), + IntTy::I64 => ( + FullInt::S(i128::from(i64::min_value())), + FullInt::S(i128::from(i64::max_value())), + ), IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }) @@ -1300,9 +1323,18 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( ty::TyUint(uint_ty) => { Some(match uint_ty { UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), - UintTy::U16 => (FullInt::U(u128::from(u16::min_value())), FullInt::U(u128::from(u16::max_value()))), - UintTy::U32 => (FullInt::U(u128::from(u32::min_value())), FullInt::U(u128::from(u32::max_value()))), - UintTy::U64 => (FullInt::U(u128::from(u64::min_value())), FullInt::U(u128::from(u64::max_value()))), + UintTy::U16 => ( + FullInt::U(u128::from(u16::min_value())), + FullInt::U(u128::from(u16::max_value())), + ), + UintTy::U32 => ( + FullInt::U(u128::from(u32::min_value())), + FullInt::U(u128::from(u32::max_value())), + ), + UintTy::U64 => ( + FullInt::U(u128::from(u64::min_value())), + FullInt::U(u128::from(u64::max_value())), + ), UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), }) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index fffeb3bb699..9f75ed2717b 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -8,7 +8,8 @@ use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. /// -/// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct name +/// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct +/// name /// feels inconsistent. /// /// **Known problems:** None. @@ -78,11 +79,7 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) { - if self.item_path.def == path.def && - path.segments - .last() - .expect(SEGMENTS_MSG) - .name != SelfType.name() { + if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).name != SelfType.name() { span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); }); diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index aa57e12bca8..d9a454aaf7e 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -92,7 +92,9 @@ pub fn range(expr: &hir::Expr) -> Option { end: get_field("end", fields), limits: ast::RangeLimits::HalfOpen, }) - } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { + } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || + match_qpath(path, &paths::RANGE_TO_INCLUSIVE) + { Some(Range { start: None, end: get_field("end", fields), diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2a4439c4608..0b3f409adf4 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -196,12 +196,16 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { if !(left.parenthesized || right.parenthesized) { - over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && - over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && - over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) + over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && + over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && + over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) } else if left.parenthesized && right.parenthesized { - over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) && - both(&Some(&left.bindings[0].ty), &Some(&right.bindings[0].ty), |l, r| self.eq_ty(l, r)) + over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) && + both( + &Some(&left.bindings[0].ty), + &Some(&right.bindings[0].ty), + |l, r| self.eq_ty(l, r), + ) } else { false } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 081b7ac277a..315f4987071 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -252,7 +252,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { hir::ExprYield(ref sub) => { println!("{}Yield", ind); print_expr(cx, sub, indent + 1); - } + }, hir::ExprBlock(_) => { println!("{}Block", ind); }, -- cgit 1.4.1-3-g733a5 From 5e1899138f122f5493ba29fe3c4313ca0d873018 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 3 Sep 2017 14:58:27 -0700 Subject: Fix dogfood --- clippy_lints/src/infinite_iter.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 3e2cfc033fc..d542ddb029f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -219,15 +219,15 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { return MaybeInfinite.and(is_infinite(cx, &args[0])); } } - if method.name == "last" && args.len() == 1 && - get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR).map_or( - false, - |id| { + if method.name == "last" && args.len() == 1 { + let not_double_ended = get_trait_def_id(cx, + &paths::DOUBLE_ENDED_ITERATOR) + .map_or(false, |id| { !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]) - }, - ) - { - return is_infinite(cx, &args[0]); + }); + if not_double_ended { + return is_infinite(cx, &args[0]); + } } }, ExprBinary(op, ref l, ref r) => { -- cgit 1.4.1-3-g733a5 From 009f5aaf836d8457389eb718e6c9f830faf1e7cc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 4 Sep 2017 16:10:36 +0200 Subject: Update to latest nightly --- clippy_lints/src/escape.rs | 4 ++-- clippy_lints/src/loops.rs | 12 ++++++------ clippy_lints/src/needless_pass_by_value.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 68f0ede8a6c..c6183948ef3 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -70,8 +70,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { too_large_for_stack: self.too_large_for_stack, }; - let region_maps = &cx.tcx.region_maps(fn_def_id); - ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); + let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); + ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables).consume_body(body); for node in v.set { span_lint( diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 68830eacfa3..7a5f7b49278 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -6,7 +6,7 @@ use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, walk_pat use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::middle::region::CodeExtent; +use rustc::middle::region; use rustc::ty::{self, Ty}; use rustc::ty::subst::{Subst, Substs}; use rustc_const_eval::ConstContext; @@ -621,9 +621,9 @@ fn check_for_loop_range<'a, 'tcx>( if let Some(indexed_extent) = indexed_extent { let parent_id = cx.tcx.hir.get_parent(expr.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_id); - let region_maps = cx.tcx.region_maps(parent_def_id); - let pat_extent = region_maps.var_scope(pat.hir_id.local_id); - if region_maps.is_subscope_of(indexed_extent, pat_extent) { + let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); + let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id); + if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { return; } } @@ -1034,7 +1034,7 @@ struct VarVisitor<'a, 'tcx: 'a> { /// var name to look for as index var: DefId, /// indexed variables, the extend is `None` for global - indexed: HashMap>, + indexed: HashMap>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: HashSet, @@ -1068,7 +1068,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let parent_id = self.cx.tcx.hir.get_parent(expr.id); let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); - let extent = self.cx.tcx.region_maps(parent_def_id).var_scope(hir_id.local_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); self.indexed.insert(seqvar.segments[0].name, Some(extent)); return; // no need to walk further } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 15ebe648500..89ef4ff67f3 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -97,8 +97,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .. } = { let mut ctx = MovedVariablesCtxt::new(cx); - let region_maps = &cx.tcx.region_maps(fn_def_id); - euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); + let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); + euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_scope_tree, cx.tables).consume_body(body); ctx }; -- cgit 1.4.1-3-g733a5 From 7757c893ef89690e52ff71dd7ee65d02edd8ea49 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 4 Sep 2017 17:05:47 +0200 Subject: Fix `len_zero` ICE --- clippy_lints/src/len_zero.rs | 30 ++++++++++++------------------ tests/ui/len_zero.rs | 7 +++++++ tests/ui/len_zero.stderr | 10 +++++++++- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 798d48f177d..e862240da59 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -104,34 +104,28 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai } // fill the set with current and super traits - fn fill_trait_set<'a, 'b: 'a>(traitt: &'b Item, set: &'a mut HashSet<&'b Item>, cx: &'b LateContext) { + fn fill_trait_set(traitt: DefId, set: &mut HashSet, cx: &LateContext) { if set.insert(traitt) { - if let ItemTrait(.., ref ty_param_bounds, _) = traitt.node { - for ty_param_bound in ty_param_bounds { - if let TraitTyParamBound(ref poly_trait_ref, _) = *ty_param_bound { - let super_trait_node_id = cx.tcx - .hir - .as_local_node_id(poly_trait_ref.trait_ref.path.def.def_id()) - .expect("the DefId is local, the NodeId should be available"); - let super_trait = cx.tcx.hir.expect_item(super_trait_node_id); - fill_trait_set(super_trait, set, cx); - } - } + for supertrait in ::rustc::traits::supertrait_def_ids(cx.tcx, traitt) { + fill_trait_set(supertrait, set, cx); } } } if cx.access_levels.is_exported(visited_trait.id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { let mut current_and_super_traits = HashSet::new(); - fill_trait_set(visited_trait, &mut current_and_super_traits, cx); + let visited_trait_def_id = cx.tcx.hir.local_def_id(visited_trait.id); + fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx); let is_empty_method_found = current_and_super_traits .iter() - .flat_map(|i| match i.node { - ItemTrait(.., ref trait_items) => trait_items.iter(), - _ => bug!("should only handle traits"), - }) - .any(|i| is_named_self(cx, i, "is_empty")); + .flat_map(|&i| cx.tcx.associated_items(i)) + .any(|i| { + i.kind == ty::AssociatedKind::Method && + i.method_has_self_argument && + i.name == "is_empty" && + cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 + }); if !is_empty_method_found { span_lint( diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index e0e735a934b..9c66d5a8148 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -182,3 +182,10 @@ fn test_slice(b: &[u8]) { if b.len() != 0 { } } + +// this used to ICE +pub trait Foo: Sized {} + +pub trait DependsOnFoo: Foo { + fn len(&mut self) -> usize; +} diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 5e3961808b8..6e3cf1b3ca1 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -86,5 +86,13 @@ error: length comparison to zero 182 | if b.len() != 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` -error: aborting due to 11 previous errors +error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method + --> $DIR/len_zero.rs:189:1 + | +189 | / pub trait DependsOnFoo: Foo { +190 | | fn len(&mut self) -> usize; +191 | | } + | |_^ + +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From 1850c8952876d9f8cb5644622fef17674cc918e3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 4 Sep 2017 17:07:19 +0200 Subject: Version Bump --- CHANGELOG.md | 3 ++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94cf6748d0b..e3eea80fe18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## Master +## 0.0.157 - 2017-09-04 +* Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* * New lint: [`unit_expr`] ## 0.0.156 - 2017-09-03 diff --git a/Cargo.toml b/Cargo.toml index 959fdfb0c1d..42323f27ad1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.156" +version = "0.0.157" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.156", path = "clippy_lints" } +clippy_lints = { version = "0.0.157", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index c3a6200f209..8c7addf468c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.156" +version = "0.0.157" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From ee8c51be00634bf6f3583ffa9110b4bd01c0a5b4 Mon Sep 17 00:00:00 2001 From: "M. Hasbini" Date: Mon, 4 Sep 2017 20:03:51 +0300 Subject: Fix "further information" link "further information" link was missing the `v` part from the url. e.g. wrong (404 notfound): https://rust-lang-nursery.github.io/rust-clippy/0.0.157/index.html#map_entry correct: https://rust-lang-nursery.github.io/rust-clippy/v0.0.157/index.html#map_entry --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 66a1b010ec8..8828a32512b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -566,7 +566,7 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/{}/index.html#{}", + "for further information visit https://rust-lang-nursery.github.io/rust-clippy/v{}/index.html#{}", env!("CARGO_PKG_VERSION"), lint.name_lower() )); -- cgit 1.4.1-3-g733a5 From e4524ac4de5327a4c25a3ba8f0fcdd0ccfc7523d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Sep 2017 11:33:04 +0200 Subject: Run nightly rustfmt --- clippy_lints/src/approx_const.rs | 4 +- clippy_lints/src/arithmetic.rs | 15 +- clippy_lints/src/array_indexing.rs | 46 ++- clippy_lints/src/assign_ops.rs | 40 ++- clippy_lints/src/attrs.rs | 31 +- clippy_lints/src/bit_mask.rs | 202 ++++++------ clippy_lints/src/blacklisted_name.rs | 4 +- clippy_lints/src/block_in_if_condition.rs | 20 +- clippy_lints/src/booleans.rs | 112 +++---- clippy_lints/src/bytecount.rs | 17 +- clippy_lints/src/collapsible_if.rs | 15 +- clippy_lints/src/consts.rs | 72 ++--- clippy_lints/src/copies.rs | 42 +-- clippy_lints/src/cyclomatic_complexity.rs | 30 +- clippy_lints/src/derive.rs | 42 +-- clippy_lints/src/doc.rs | 20 +- clippy_lints/src/double_parens.rs | 35 +- clippy_lints/src/drop_forget_ref.rs | 10 +- clippy_lints/src/empty_enum.rs | 5 +- clippy_lints/src/entry.rs | 13 +- clippy_lints/src/enum_clike.rs | 7 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 5 +- clippy_lints/src/escape.rs | 1 - clippy_lints/src/eta_reduction.rs | 9 +- clippy_lints/src/eval_order_dependence.rs | 56 ++-- clippy_lints/src/format.rs | 8 +- clippy_lints/src/formatting.rs | 17 +- clippy_lints/src/functions.rs | 6 +- clippy_lints/src/identity_op.rs | 13 +- .../src/if_let_redundant_pattern_matching.rs | 28 +- clippy_lints/src/infinite_iter.rs | 70 ++-- clippy_lints/src/is_unit_expr.rs | 25 +- clippy_lints/src/items_after_statements.rs | 9 +- clippy_lints/src/large_enum_variant.rs | 19 +- clippy_lints/src/len_zero.rs | 66 ++-- clippy_lints/src/lib.rs | 15 +- clippy_lints/src/lifetimes.rs | 45 +-- clippy_lints/src/literal_digit_grouping.rs | 50 ++- clippy_lints/src/loops.rs | 307 +++++++++--------- clippy_lints/src/map_clone.rs | 32 +- clippy_lints/src/matches.rs | 118 +++---- clippy_lints/src/mem_forget.rs | 3 +- clippy_lints/src/methods.rs | 92 +++--- clippy_lints/src/minmax.rs | 8 +- clippy_lints/src/misc.rs | 48 ++- clippy_lints/src/misc_early.rs | 42 ++- clippy_lints/src/missing_doc.rs | 38 ++- clippy_lints/src/mut_mut.rs | 31 +- clippy_lints/src/mut_reference.rs | 43 +-- clippy_lints/src/mutex_atomic.rs | 4 +- clippy_lints/src/needless_bool.rs | 38 +-- clippy_lints/src/needless_borrow.rs | 34 +- clippy_lints/src/needless_borrowed_ref.rs | 4 +- clippy_lints/src/needless_continue.rs | 41 +-- clippy_lints/src/needless_pass_by_value.rs | 35 +- clippy_lints/src/new_without_default.rs | 61 ++-- clippy_lints/src/no_effect.rs | 99 +++--- clippy_lints/src/non_expressive_names.rs | 67 ++-- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 15 +- clippy_lints/src/panic.rs | 2 +- clippy_lints/src/precedence.rs | 6 +- clippy_lints/src/print.rs | 4 +- clippy_lints/src/ptr.rs | 24 +- clippy_lints/src/ranges.rs | 4 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 72 ++--- clippy_lints/src/returns.rs | 14 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 116 +++---- clippy_lints/src/should_assert_eq.rs | 2 +- clippy_lints/src/strings.rs | 14 +- clippy_lints/src/temporary_assignment.rs | 7 +- clippy_lints/src/transmute.rs | 169 +++++----- clippy_lints/src/types.rs | 354 +++++++++------------ clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 12 +- clippy_lints/src/unused_io_amount.rs | 17 +- clippy_lints/src/unused_label.rs | 12 +- clippy_lints/src/use_self.rs | 6 +- clippy_lints/src/utils/author.rs | 66 ++-- clippy_lints/src/utils/conf.rs | 23 +- clippy_lints/src/utils/higher.rs | 72 ++--- clippy_lints/src/utils/hir_utils.rs | 19 +- clippy_lints/src/utils/inspector.rs | 23 +- clippy_lints/src/utils/internal_lints.rs | 37 ++- clippy_lints/src/utils/mod.rs | 201 ++++++------ clippy_lints/src/utils/sugg.rs | 58 ++-- clippy_lints/src/vec.rs | 12 +- clippy_lints/src/zero_div_zero.rs | 2 +- mini-macro/src/lib.rs | 7 +- src/main.rs | 45 +-- tests/compile-test.rs | 6 +- tests/dogfood.rs | 2 +- tests/issue-825.rs | 8 +- tests/matches.rs | 24 +- tests/needless_continue_helpers.rs | 3 +- 99 files changed, 1791 insertions(+), 2048 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index cbe12e58119..9d5d87dc4b3 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use std::f64::consts as f64; -use syntax::ast::{Lit, LitKind, FloatTy}; +use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; use utils::span_lint; @@ -91,7 +91,7 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &symbol::Symbol, module: &s e.span, &format!( "approximate value of `{}::consts::{}` found. \ - Consider using it directly", + Consider using it directly", module, &name ), diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 8c370213f80..a551ebf046b 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -55,8 +55,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd | hir::BiOr | hir::BiBitAnd | hir::BiBitOr | hir::BiBitXor | hir::BiShl | - hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, + hir::BiAnd | + hir::BiOr | + hir::BiBitAnd | + hir::BiBitOr | + hir::BiBitXor | + hir::BiShl | + hir::BiShr | + hir::BiEq | + hir::BiLt | + hir::BiLe | + hir::BiNe | + hir::BiGe | + hir::BiGt => return, _ => (), } let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 422935fa067..5815f645686 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -3,7 +3,7 @@ use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; -use rustc_const_math::{ConstUsize, ConstIsize, ConstInt}; +use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; @@ -124,29 +124,27 @@ fn to_const_range( }; let end = match *end { - Some(Some(ConstVal::Integral(x))) => { - if limits == RangeLimits::Closed { - match x { - ConstInt::U8(_) => (x + ConstInt::U8(1)), - ConstInt::U16(_) => (x + ConstInt::U16(1)), - ConstInt::U32(_) => (x + ConstInt::U32(1)), - ConstInt::U64(_) => (x + ConstInt::U64(1)), - ConstInt::U128(_) => (x + ConstInt::U128(1)), - ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), - ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), - ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), - ConstInt::I8(_) => (x + ConstInt::I8(1)), - ConstInt::I16(_) => (x + ConstInt::I16(1)), - ConstInt::I32(_) => (x + ConstInt::I32(1)), - ConstInt::I64(_) => (x + ConstInt::I64(1)), - ConstInt::I128(_) => (x + ConstInt::I128(1)), - ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), - ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), - ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), - }.expect("such a big array is not realistic") - } else { - x - } + Some(Some(ConstVal::Integral(x))) => if limits == RangeLimits::Closed { + match x { + ConstInt::U8(_) => (x + ConstInt::U8(1)), + ConstInt::U16(_) => (x + ConstInt::U16(1)), + ConstInt::U32(_) => (x + ConstInt::U32(1)), + ConstInt::U64(_) => (x + ConstInt::U64(1)), + ConstInt::U128(_) => (x + ConstInt::U128(1)), + ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), + ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), + ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), + ConstInt::I8(_) => (x + ConstInt::I8(1)), + ConstInt::I16(_) => (x + ConstInt::I16(1)), + ConstInt::I32(_) => (x + ConstInt::I32(1)), + ConstInt::I64(_) => (x + ConstInt::I64(1)), + ConstInt::I128(_) => (x + ConstInt::I128(1)), + ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), + ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), + ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), + }.expect("such a big array is not realistic") + } else { + x }, Some(_) => return None, None => array_size, diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 759bb9f12ec..33a1d94f420 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use syntax::ast; -use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; +use utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; use utils::{higher, sugg}; /// **What it does:** Checks for compound assignment operations (`+=` and @@ -88,19 +88,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { - span_lint_and_then(cx, - MISREFACTORED_ASSIGN_OP, - expr.span, - "variable appears on both sides of an assignment operation", - |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - db.span_suggestion(expr.span, - "replace it with", - format!("{} {}= {}", - snip_a, - op.node.as_str(), - snip_r)); - }); + span_lint_and_then( + cx, + MISREFACTORED_ASSIGN_OP, + expr.span, + "variable appears on both sides of an assignment operation", + |db| if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + db.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + ); + }, + ); }; // lhs op= l op r if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) { @@ -167,8 +169,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { BitXor: BiBitXor, Shr: BiShr, Shl: BiShl - ) - { + ) { span_lint_and_then( cx, ASSIGN_OP_PATTERN, @@ -193,7 +194,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // a = b commutative_op a if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { match op.node { - hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd | + hir::BiAdd | + hir::BiMul | + hir::BiAnd | + hir::BiOr | + hir::BiBitXor | + hir::BiBitAnd | hir::BiBitOr => { lint(assignee, l); }, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 86d72226601..12339c039d9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, match_def_path, paths, span_lint, span_lint_and_then, snippet_opt}; +use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -110,8 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { check_attrs(cx, item.span, &item.name, &item.attrs) } match item.node { - ItemExternCrate(_) | - ItemUse(_, _) => { + ItemExternCrate(_) | ItemUse(_, _) => { for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { if let Some(name) = attr.name() { @@ -196,14 +195,13 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b if let Some(stmt) = block.stmts.first() { match stmt.node { StmtDecl(_, _) => true, - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), } } else { - block.expr.as_ref().map_or( - false, - |e| is_relevant_expr(tcx, tables, e), - ) + block + .expr + .as_ref() + .map_or(false, |e| is_relevant_expr(tcx, tables, e)) } } @@ -211,15 +209,12 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool match expr.node { ExprBlock(ref block) => is_relevant_block(tcx, tables, block), ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), - ExprRet(None) | - ExprBreak(_, None) => false, - ExprCall(ref path_expr, _) => { - if let ExprPath(ref qpath) = path_expr.node { - let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); - !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) - } else { - true - } + ExprRet(None) | ExprBreak(_, None) => false, + ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { + let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); + !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + } else { + true }, _ => true, } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 6e5a18240cb..ecb12b60a16 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -158,118 +158,100 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u12 fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: &Span) { match cmp_op { - BiEq | BiNe => { - match bit_op { - BiBitAnd => { - if mask_value & cmp_value != cmp_value { - if cmp_value != 0 { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, - cmp_value - ), - ); - } - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value | cmp_value != cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, - cmp_value - ), - ); - } - }, - _ => (), - } + BiEq | BiNe => match bit_op { + BiBitAnd => if mask_value & cmp_value != cmp_value { + if cmp_value != 0 { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); + } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value | cmp_value != cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); + }, + _ => (), }, - BiLt | BiGe => { - match bit_op { - BiBitAnd => { - if mask_value < cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value >= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); - } - }, - BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } + BiLt | BiGe => match bit_op { + BiBitAnd => if mask_value < cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, + cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value >= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, + cmp_value + ), + ); + } else { + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); + }, + BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), + _ => (), }, - BiLe | BiGt => { - match bit_op { - BiBitAnd => { - if mask_value <= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value > cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); - } - }, - BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } + BiLe | BiGt => match bit_op { + BiBitAnd => if mask_value <= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, + cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value > cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, + cmp_value + ), + ); + } else { + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); + }, + BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), + _ => (), }, _ => (), } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index e46d8e4855f..114ba5fa782 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -27,7 +27,9 @@ pub struct BlackListedName { impl BlackListedName { pub fn new(blacklist: Vec) -> Self { - Self { blacklist: blacklist } + Self { + blacklist: blacklist, + } } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 82a3eb00ab7..d67a1a5394e 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,6 +1,6 @@ -use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use utils::*; /// **What it does:** Checks for `if` conditions that use blocks to contain an @@ -93,15 +93,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { check.span, BRACED_EXPR_MESSAGE, &format!("try\nif {} {} ... ", - snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, "..")), + snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, "..")), ); } } else { - let span = block.expr.as_ref().map_or_else( - || block.stmts[0].span, - |e| e.span, - ); + let span = block + .expr + .as_ref() + .map_or_else(|| block.stmts[0].span, |e| e.span); if in_macro(span) || differing_macro_contexts(expr.span, span) { return; } @@ -112,8 +112,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { check.span, COMPLEX_BLOCK_MESSAGE, &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, "..")), + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, "..")), ); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 7c7dbe80883..2587937616c 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,10 +1,10 @@ -use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::*; -use syntax::ast::{LitKind, DUMMY_NODE_ID, NodeId}; -use syntax::codemap::{DUMMY_SP, dummy_spanned, Span}; +use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; +use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; use syntax::util::ThinVec; -use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; +use utils::{in_macro, snippet_opt, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -96,26 +96,23 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { if !in_macro(e.span) { match e.node { ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprBinary(binop, ref lhs, ref rhs) => { - match binop.node { - BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), - BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), - _ => (), - } + ExprBinary(binop, ref lhs, ref rhs) => match binop.node { + BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), + BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + _ => (), }, - ExprLit(ref lit) => { - match lit.node { - LitKind::Bool(true) => return Ok(Bool::True), - LitKind::Bool(false) => return Ok(Bool::False), - _ => (), - } + ExprLit(ref lit) => match lit.node { + LitKind::Bool(true) => return Ok(Bool::True), + LitKind::Bool(false) => return Ok(Bool::False), + _ => (), }, _ => (), } } for (n, expr) in self.terminals.iter().enumerate() { if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { - #[allow(cast_possible_truncation)] return Ok(Bool::Term(n as u8)); + #[allow(cast_possible_truncation)] + return Ok(Bool::Term(n as u8)); } let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { @@ -141,13 +138,15 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { _ => continue, }; if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { - #[allow(cast_possible_truncation)] return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + #[allow(cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); } } let n = self.terminals.len(); self.terminals.push(e); if n < 32 { - #[allow(cast_possible_truncation)] Ok(Bool::Term(n as u8)) + #[allow(cast_possible_truncation)] + Ok(Bool::Term(n as u8)) } else { Err("too many literals".to_owned()) } @@ -167,40 +166,36 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push_str("false"); s }, - Not(ref inner) => { - match **inner { - And(_) | Or(_) => { - s.push('!'); - recurse(true, cx, inner, terminals, s) - }, - Term(n) => { - if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { - s.push('!'); - return recurse(true, cx, inner, terminals, s); - }, - }; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - } else { + Not(ref inner) => match **inner { + And(_) | Or(_) => { + s.push('!'); + recurse(true, cx, inner, terminals, s) + }, + Term(n) => if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { s.push('!'); - recurse(false, cx, inner, terminals, s) - } - }, - _ => { - s.push('!'); - recurse(false, cx, inner, terminals, s) - }, - } + return recurse(true, cx, inner, terminals, s); + }, + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + } else { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, }, And(ref v) => { if brackets { @@ -319,7 +314,6 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { cx: self.cx, }; if let Ok(expr) = h2q.run(e) { - if h2q.terminals.len() > 8 { // QMC has exponentially slow behavior as the number of terminals increases // 8 is reasonable, it takes approximately 0.2 seconds. @@ -360,7 +354,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { db.span_help( h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the \ - outer expression", + outer expression", ); db.span_suggestion( e.span, @@ -411,12 +405,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), - ExprUnary(UnNot, ref inner) => { - if self.cx.tables.node_types()[inner.hir_id].is_bool() { - self.bool_expr(e); - } else { - walk_expr(self, e); - } + ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { + self.bool_expr(e); + } else { + walk_expr(self, e); }, _ => walk_expr(self, e), } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 1d7afbe084d..447214c70f8 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -97,23 +97,18 @@ fn get_pat_name(pat: &Pat) -> Option { match pat.node { PatKind::Binding(_, _, ref spname, _) => Some(spname.node), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), - PatKind::Box(ref p) | - PatKind::Ref(ref p, _) => get_pat_name(&*p), + PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), _ => None, } } fn get_path_name(expr: &Expr) -> Option { match expr.node { - ExprBox(ref e) | - ExprAddrOf(_, ref e) | - ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprBlock(ref b) => { - if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { - None - } + ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), + ExprBlock(ref b) => if b.stmts.is_empty() { + b.expr.as_ref().and_then(|p| get_path_name(p)) + } else { + None }, ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), _ => None, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 1914b83e898..fb0ff23cc63 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -15,7 +15,7 @@ use rustc::lint::*; use syntax::ast; -use utils::{in_macro, snippet_block, span_lint_and_then, span_lint_and_sugg}; +use utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; use utils::sugg::Sugg; /// **What it does:** Checks for nested `if` statements which can be collapsed @@ -87,12 +87,10 @@ impl EarlyLintPass for CollapsibleIf { fn check_if(cx: &EarlyContext, expr: &ast::Expr) { match expr.node { - ast::ExprKind::If(ref check, ref then, ref else_) => { - if let Some(ref else_) = *else_ { - check_collapsible_maybe_if_let(cx, else_); - } else { - check_collapsible_no_if_let(cx, expr, check, then); - } + ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ { + check_collapsible_maybe_if_let(cx, else_); + } else { + check_collapsible_no_if_let(cx, expr, check, then); }, ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => { check_collapsible_maybe_if_let(cx, else_); @@ -147,8 +145,7 @@ fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { if let (Some(stmt), None) = (it.next(), it.next()) { match stmt.node { - ast::StmtKind::Expr(ref expr) | - ast::StmtKind::Semi(ref expr) => Some(expr), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr), _ => None, } } else { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 0a76b95931d..de62990afd5 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -5,8 +5,8 @@ use rustc::hir::def::Def; use rustc_const_eval::lookup_const_by_id; use rustc_const_math::ConstInt; use rustc::hir::*; -use rustc::ty::{self, TyCtxt, Ty}; -use rustc::ty::subst::{Substs, Subst}; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::{Subst, Substs}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; @@ -76,7 +76,7 @@ impl PartialEq for Constant { (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, - _ => false, //TODO: Are there inter-type equalities? + _ => false, // TODO: Are there inter-type equalities? } } } @@ -110,8 +110,7 @@ impl Hash for Constant { Constant::Bool(b) => { b.hash(state); }, - Constant::Vec(ref v) | - Constant::Tuple(ref v) => { + Constant::Vec(ref v) | Constant::Tuple(ref v) => { v.hash(state); }, Constant::Repeat(ref c, l) => { @@ -125,12 +124,10 @@ impl Hash for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { - if l_sty == r_sty { - Some(ls.cmp(rs)) - } else { - None - } + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => if l_sty == r_sty { + Some(ls.cmp(rs)) + } else { + None }, (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), @@ -147,15 +144,14 @@ impl PartialOrd for Constant { } }, (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { - match lv.partial_cmp(rv) { - Some(Equal) => Some(ls.cmp(rs)), - x => x, - } + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => { + l.partial_cmp(r) + }, + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => match lv.partial_cmp(rv) { + Some(Equal) => Some(ls.cmp(rs)), + x => x, }, - _ => None, //TODO: Are there any useful inter-type orderings? + _ => None, // TODO: Are there any useful inter-type orderings? } } } @@ -177,18 +173,14 @@ pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(n, hint) => { - match (&ty.sty, hint) { - (&ty::TyInt(ity), _) | - (_, Signed(ity)) => { - Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.int_type)) - }, - (&ty::TyUint(uty), _) | - (_, Unsigned(uty)) => { - Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.uint_type)) - }, - _ => bug!(), - } + LitKind::Int(n, hint) => match (&ty.sty, hint) { + (&ty::TyInt(ity), _) | (_, Signed(ity)) => { + Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.int_type)) + }, + (&ty::TyUint(uty), _) | (_, Unsigned(uty)) => { + Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.uint_type)) + }, + _ => bug!(), }, LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), @@ -262,13 +254,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) }, - ExprUnary(op, ref operand) => { - self.expr(operand).and_then(|o| match op { - UnNot => constant_not(&o), - UnNeg => constant_negate(o), - UnDeref => Some(o), - }) - }, + ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op { + UnNot => constant_not(&o), + UnNeg => constant_negate(o), + UnDeref => Some(o), + }), ExprBinary(op, ref left, ref right) => self.binop(op, left, right), // TODO: add other expressions _ => None, @@ -287,8 +277,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { let def = self.tables.qpath_def(qpath, id); match def { - Def::Const(def_id) | - Def::AssociatedConst(def_id) => { + Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = self.tables.node_substs(id); let substs = if self.substs.is_empty() { substs @@ -358,8 +347,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BiAnd, Constant::Bool(true), Some(r)) | - (BiOr, Constant::Bool(false), Some(r)) => Some(r), + (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index f9e11d06882..862272456ea 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -6,7 +6,7 @@ use std::collections::hash_map::Entry; use syntax::symbol::InternedString; use syntax::util::small_vector::SmallVector; use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, span_lint_and_then, span_note_and_lint, snippet}; +use utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for consecutive `if`s with the same condition. /// @@ -114,7 +114,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if !in_macro(expr.span) { // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { + if let Some(&Expr { + node: ExprIf(_, _, Some(ref else_expr)), + .. + }) = get_parent_expr(cx, expr) + { if else_expr.id == expr.id { return; } @@ -267,12 +271,9 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { match pat.node { - PatKind::Box(ref pat) | - PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), - PatKind::TupleStruct(_, ref pats, _) => { - for pat in pats { - bindings_impl(cx, pat, map); - } + PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), + PatKind::TupleStruct(_, ref pats, _) => for pat in pats { + bindings_impl(cx, pat, map); }, PatKind::Binding(_, _, ref ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { @@ -282,15 +283,11 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap { - for pat in fields { - bindings_impl(cx, &pat.node.pat, map); - } + PatKind::Struct(_, ref fields, _) => for pat in fields { + bindings_impl(cx, &pat.node.pat, map); }, - PatKind::Tuple(ref fields, _) => { - for pat in fields { - bindings_impl(cx, pat, map); - } + PatKind::Tuple(ref fields, _) => for pat in fields { + bindings_impl(cx, pat, map); }, PatKind::Slice(ref lhs, ref mid, ref rhs) => { for pat in lhs { @@ -303,10 +300,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap (), + PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (), } } @@ -335,11 +329,9 @@ where for expr in exprs { match map.entry(hash(expr)) { - Entry::Occupied(o) => { - for o in o.get() { - if eq(o, expr) { - return Some((o, expr)); - } + Entry::Occupied(o) => for o in o.get() { + if eq(o, expr) { + return Some((o, expr)); } }, Entry::Vacant(v) => { diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index edfa5e0fb61..ede9dcb1fbd 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -4,11 +4,11 @@ use rustc::cfg::CFG; use rustc::lint::*; use rustc::hir::*; use rustc::ty; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, NodeId}; use syntax::codemap::Span; -use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type, is_allowed}; +use utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; /// **What it does:** Checks for methods with high cyclomatic complexity. /// @@ -31,7 +31,9 @@ pub struct CyclomaticComplexity { impl CyclomaticComplexity { pub fn new(limit: u64) -> Self { - Self { limit: LimitStack::new(limit) } + Self { + limit: LimitStack::new(limit), + } } } @@ -125,18 +127,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { } fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.push_attrs( - cx.sess(), - attrs, - "cyclomatic_complexity", - ); + self.limit + .push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.pop_attrs( - cx.sess(), - attrs, - "cyclomatic_complexity", - ); + self.limit + .pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } } @@ -194,7 +190,7 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, re span_bug!( span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}, returns = {}. Please file a bug report.", + div = {}, shorts = {}, returns = {}. Please file a bug report.", cc, narms, div, @@ -210,9 +206,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, r span, &format!( "Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): \ - cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ - Please file a bug report.", + (hide this message with `#[allow(cyclomatic_complexity)]`): \ + cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ + Please file a bug report.", cc, narms, div, diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 36576365eac..b70e591f995 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -3,7 +3,7 @@ use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; use utils::paths; -use utils::{is_automatically_derived, span_lint_and_then, match_path, is_copy}; +use utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly. @@ -141,31 +141,31 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref ty::TyAdt(def, _) if def.is_union() => return, // Some types are not Clone by default but could be cloned “by hand” if necessary - ty::TyAdt(def, substs) => { - for variant in &def.variants { - for field in &variant.fields { - match field.ty(cx.tcx, substs).sty { - ty::TyArray(_, size) if size > 32 => { - return; - }, - ty::TyFnPtr(..) => { - return; - }, - ty::TyTuple(tys, _) if tys.len() > 12 => { - return; - }, - _ => (), - } + ty::TyAdt(def, substs) => for variant in &def.variants { + for field in &variant.fields { + match field.ty(cx.tcx, substs).sty { + ty::TyArray(_, size) if size > 32 => { + return; + }, + ty::TyFnPtr(..) => { + return; + }, + ty::TyTuple(tys, _) if tys.len() > 12 => { + return; + }, + _ => (), } } }, _ => (), } - span_lint_and_then(cx, - EXPL_IMPL_CLONE_ON_COPY, - item.span, - "you are implementing `Clone` explicitly on a `Copy` type", - |db| { db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }); + span_lint_and_then( + cx, + EXPL_IMPL_CLONE_ON_COPY, + item.span, + "you are implementing `Clone` explicitly on a `Copy` type", + |db| { db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }, + ); } } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 8977ea437d1..170ca5cf007 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::*; use syntax::ast; -use syntax::codemap::{Span, BytePos}; +use syntax::codemap::{BytePos, Span}; use syntax_pos::Pos; use utils::span_lint; @@ -37,7 +37,9 @@ pub struct Doc { impl Doc { pub fn new(valid_idents: Vec) -> Self { - Self { valid_idents: valid_idents } + Self { + valid_idents: valid_idents, + } } } @@ -196,17 +198,13 @@ fn check_doc<'a, Events: Iterator)>>( for (offset, event) in docs { match event { - Start(CodeBlock(_)) | - Start(Code) => in_code = true, - End(CodeBlock(_)) | - End(Code) => in_code = false, - Start(_tag) | End(_tag) => (), // We don't care about other tags - Html(_html) | - InlineHtml(_html) => (), // HTML is weird, just ignore it + Start(CodeBlock(_)) | Start(Code) => in_code = true, + End(CodeBlock(_)) | End(Code) => in_code = false, + Start(_tag) | End(_tag) => (), // We don't care about other tags + Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it SoftBreak => (), HardBreak => (), - FootnoteReference(text) | - Text(text) => { + FootnoteReference(text) | Text(text) => { if !in_code { let index = match spans.binary_search_by(|c| c.0.cmp(&offset)) { Ok(o) => o, diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 5ef16638878..be5e056d5df 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,5 +1,5 @@ use syntax::ast::*; -use rustc::lint::{EarlyContext, LintContext, LintArray, LintPass, EarlyLintPass}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; /// **What it does:** Checks for unnecessary double parentheses. /// @@ -31,29 +31,22 @@ impl LintPass for DoubleParens { impl EarlyLintPass for DoubleParens { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { match expr.node { - ExprKind::Paren(ref in_paren) => { - match in_paren.node { - ExprKind::Paren(_) | - ExprKind::Tup(_) => { - cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); - }, - _ => {}, - } + ExprKind::Paren(ref in_paren) => match in_paren.node { + ExprKind::Paren(_) | ExprKind::Tup(_) => { + cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); + }, + _ => {}, }, - ExprKind::Call(_, ref params) => { - if params.len() == 1 { - let param = ¶ms[0]; - if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); - } + ExprKind::Call(_, ref params) => if params.len() == 1 { + let param = ¶ms[0]; + if let ExprKind::Paren(_) = param.node { + cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, - ExprKind::MethodCall(_, ref params) => { - if params.len() == 2 { - let param = ¶ms[1]; - if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); - } + ExprKind::MethodCall(_, ref params) => if params.len() == 2 { + let param = ¶ms[1]; + if let ExprKind::Paren(_) = param.node { + cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, _ => {}, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index dfa8ddbab6c..6ca04d40067 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, paths, span_note_and_lint, is_copy}; +use utils::{is_copy, match_def_path, paths, span_note_and_lint}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. @@ -96,13 +96,13 @@ declare_lint! { } const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \ - Dropping a reference does nothing."; + Dropping a reference does nothing."; const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \ - Forgetting a reference does nothing."; + Forgetting a reference does nothing."; const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements Copy. \ - Dropping a copy leaves the original intact."; + Dropping a copy leaves the original intact."; const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements Copy. \ - Forgetting a copy leaves the original intact."; + Forgetting a copy leaves the original intact."; #[allow(missing_copy_implementations)] pub struct Pass; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 7845c85b687..67a4b8d4030 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -36,9 +36,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(..) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect( - "already checked whether this is an enum", - ); + let adt = ty.ty_adt_def() + .expect("already checked whether this is an enum"); if adt.variants.is_empty() { span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| { db.span_help(item.span, "consider using the uninhabited type `!` or a wrapper around it"); diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 80288ff2268..a3558a189e2 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::codemap::Span; use utils::SpanlessEq; @@ -47,12 +47,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = { - else_block.is_none() && - if let ExprBlock(ref then_block) = then_block.node { - (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 - } else { - true - } + else_block.is_none() && if let ExprBlock(ref then_block) = then_block.node { + (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 + } else { + true + } }; let mut visitor = InsertVisitor { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e95c37b0aee..c776681d51c 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,9 +51,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let did = cx.tcx.hir.body_owner_def_id(body_id); let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); - let bad = match cx.tcx.at(expr.span).const_eval( - param_env.and((did, substs)), - ) { + let bad = match cx.tcx + .at(expr.span) + .const_eval(param_env.and((did, substs))) + { Ok(ConstVal::Integral(Usize(Us64(i)))) => u64::from(i as u32) != i, Ok(ConstVal::Integral(Isize(Is64(i)))) => i64::from(i as i32) != i, _ => false, diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 6738f5bb63b..9aa43653ab5 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -1,7 +1,7 @@ //! lint on `use`ing all variants of an enum use rustc::hir::*; -use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index eee4e2a7ee1..c4f7f39003e 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -204,7 +204,7 @@ fn check_variant( &format!("All variants have the same {}fix: `{}`", what, value), &format!( "remove the {}fixes and use full paths to \ - the variants instead of glob imports", + the variants instead of glob imports", what ), ); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 84a54dd215b..2c268c18835 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{SpanlessEq, span_lint, span_lint_and_then, multispan_sugg, snippet, implements_trait, is_copy}; +use utils::{implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, @@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { #[allow(match_same_arms)] match (&left.node, &right.node) { // do not suggest to dereference literals - (&ExprLit(..), _) | - (_, &ExprLit(..)) => {}, + (&ExprLit(..), _) | (_, &ExprLit(..)) => {}, // &foo == &bar (&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => { let lty = cx.tables.expr_ty(l); diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index c6183948ef3..beb96f333cb 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -133,7 +133,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { self.set.remove(&lid); } } - } fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 42524da7ffc..0710689c3d4 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then, is_adjusted, iter_input_pats}; +use utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; #[allow(missing_copy_implementations)] pub struct EtaPass; @@ -37,11 +37,8 @@ impl LintPass for EtaPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { - ExprCall(_, ref args) | - ExprMethodCall(_, _, ref args) => { - for arg in args { - check_closure(cx, arg) - } + ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => for arg in args { + check_closure(cx, arg) }, _ => (), } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index db952cd5d98..621438b9a87 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,9 +1,9 @@ use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; use rustc::lint::*; -use utils::{get_parent_expr, span_note_and_lint, span_lint}; +use utils::{get_parent_expr, span_lint, span_note_and_lint}; /// **What it does:** Checks for a read and a write to the same variable where /// whether the read occurs before or after the write depends on the evaluation @@ -62,20 +62,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Find a write to a local variable. match expr.node { - ExprAssign(ref lhs, _) | - ExprAssignOp(_, ref lhs, _) => { - if let ExprPath(ref qpath) = lhs.node { - if let QPath::Resolved(_, ref path) = *qpath { - if path.segments.len() == 1 { - let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); - let mut visitor = ReadVisitor { - cx: cx, - var: var, - write_expr: expr, - last_expr: expr, - }; - check_for_unsequenced_reads(&mut visitor); - } + ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node { + if let QPath::Resolved(_, ref path) = *qpath { + if path.segments.len() == 1 { + let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); + let mut visitor = ReadVisitor { + cx: cx, + var: var, + write_expr: expr, + last_expr: expr, + }; + check_for_unsequenced_reads(&mut visitor); } } }, @@ -84,13 +81,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e), - StmtDecl(ref d, _) => { - if let DeclLocal(ref local) = d.node { - if let Local { init: Some(ref e), .. } = **local { - DivergenceVisitor { cx: cx }.visit_expr(e); - } + StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e), + StmtDecl(ref d, _) => if let DeclLocal(ref local) = d.node { + if let Local { + init: Some(ref e), .. + } = **local + { + DivergenceVisitor { cx: cx }.visit_expr(e); } }, } @@ -230,8 +227,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St ExprStruct(_, _, _) => { walk_expr(vis, expr); }, - ExprBinary(op, _, _) | - ExprAssignOp(op, _, _) => { + ExprBinary(op, _, _) | ExprAssignOp(op, _, _) => { if op.node == BiAnd || op.node == BiOr { // x && y and x || y always evaluate x first, so these are // strictly sequenced. @@ -265,8 +261,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly { match stmt.node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => check_expr(vis, expr), + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => check_expr(vis, expr), StmtDecl(ref decl, _) => { // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. @@ -274,10 +269,9 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St DeclLocal(ref local) => Some(local), _ => None, }; - local.and_then(|local| local.init.as_ref()).map_or( - StopEarly::KeepGoing, - |expr| check_expr(vis, expr), - ) + local + .and_then(|local| local.init.as_ref()) + .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) }, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index fb2e04a3662..2577e2908a8 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -57,11 +57,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }} }, // `format!("foo")` expansion contains `match () { () => [], }` - ExprMatch(ref matchee, _, _) => { - if let ExprTup(ref tup) = matchee.node { - if tup.is_empty() { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); - } + ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node { + if tup.is_empty() { + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); } }, _ => (), diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index e3b3bb408b3..7d712942986 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -117,7 +117,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { eqop_span, &format!( "this looks like you are trying to use `.. {op}= ..`, but you \ - really are doing `.. = ({op} ..)`", + really are doing `.. = ({op} ..)`", op = op ), eqop_span, @@ -142,9 +142,9 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” if let Some(else_snippet) = snippet_opt(cx, else_span) { - let else_pos = else_snippet.find("else").expect( - "there must be a `else` here", - ); + let else_pos = else_snippet + .find("else") + .expect("there must be a `else` here"); if else_snippet[else_pos..].contains('\n') { span_note_and_lint( @@ -154,7 +154,7 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { "this is an `else if` but the formatting might hide it", else_span, "to remove this lint, remove the `else` or remove the new line between `else` \ - and `if`", + and `if`", ); } } @@ -205,7 +205,7 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp "this looks like an `else if` but the `else` is missing", else_span, "to remove this lint, add the missing `else` or add a new line before the second \ - `if`", + `if`", ); } } @@ -215,8 +215,9 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp /// Match `if` or `if let` expressions and return the `then` and `else` block. fn unsugar_if(expr: &ast::Expr) -> Option<(&P, &Option>)> { match expr.node { - ast::ExprKind::If(_, ref then, ref else_) | - ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), + ast::ExprKind::If(_, ref then, ref else_) | ast::ExprKind::IfLet(_, _, ref then, ref else_) => { + Some((then, else_)) + }, _ => None, } } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 70ff96d36d4..869e621eab6 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::abi::Abi; use syntax::codemap::Span; -use utils::{span_lint, type_is_unsafe_function, iter_input_pats}; +use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// **What it does:** Checks for functions with too many parameters. /// @@ -60,7 +60,9 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64) -> Self { - Self { threshold: threshold } + Self { + threshold: threshold, + } } } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index a7c254e1e46..a409f4c7d65 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -2,7 +2,7 @@ use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Span; -use utils::{span_lint, snippet, in_macro}; +use utils::{in_macro, snippet, span_lint}; use syntax::attr::IntType::{SignedInt, UnsignedInt}; /// **What it does:** Checks for identity operations, e.g. `x + 0`. @@ -63,16 +63,13 @@ fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { 0 => v.to_u128_unchecked() == 0, - -1 => { - match v.int_type() { - SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), - UnsignedInt(_) => false, - } + -1 => match v.int_type() { + SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), + UnsignedInt(_) => false, }, 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), - } - { + } { span_lint( cx, IDENTITY_OP, diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 36411b73a62..27f41c0e698 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{paths, span_lint_and_then, match_qpath, snippet}; +use utils::{match_qpath, paths, snippet, span_lint_and_then}; /// **What it does:*** Lint for redundant pattern matching over `Result` or /// `Option` @@ -45,11 +45,8 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { - if arms[0].pats.len() == 1 { - let good_method = match arms[0].pats[0].node { PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => { if match_qpath(path, &paths::RESULT_OK) { @@ -68,16 +65,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => return, }; - span_lint_and_then(cx, - IF_LET_REDUNDANT_PATTERN_MATCHING, - arms[0].pats[0].span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |db| { - let span = expr.span.with_hi(op.span.hi()); - db.span_suggestion(span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method)); - }); + span_lint_and_then( + cx, + IF_LET_REDUNDANT_PATTERN_MATCHING, + arms[0].pats[0].span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.with_hi(op.span.hi()); + db.span_suggestion( + span, + "try this", + format!("if {}.{}", snippet(cx, op.span, "_"), good_method), + ); + }, + ); } - } } } diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index d542ddb029f..3a5bcdc78d4 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{get_trait_def_id, implements_trait, higher, match_qpath, paths, span_lint}; +use utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// @@ -66,14 +66,13 @@ enum Finiteness { Finite, } -use self::Finiteness::{Infinite, MaybeInfinite, Finite}; +use self::Finiteness::{Finite, Infinite, MaybeInfinite}; impl Finiteness { fn and(self, b: Self) -> Self { match (self, b) { (Finite, _) | (_, Finite) => Finite, - (MaybeInfinite, _) | - (_, MaybeInfinite) => MaybeInfinite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, _ => Infinite, } } @@ -81,8 +80,7 @@ impl Finiteness { fn or(self, b: Self) -> Self { match (self, b) { (Infinite, _) | (_, Infinite) => Infinite, - (MaybeInfinite, _) | - (_, MaybeInfinite) => MaybeInfinite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, _ => Finite, } } @@ -90,7 +88,11 @@ impl Finiteness { impl From for Finiteness { fn from(b: bool) -> Self { - if b { Infinite } else { Finite } + if b { + Infinite + } else { + Finite + } } } @@ -108,7 +110,7 @@ enum Heuristic { All, } -use self::Heuristic::{Always, First, Any, All}; +use self::Heuristic::{All, Always, Any, First}; /// a slice of (method name, number of args, heuristic, bounds) tuples /// that will be used to determine whether the method in question @@ -143,11 +145,11 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { for &(name, len, heuristic, cap) in HEURISTICS.iter() { if method.name == name && args.len() == len { return (match heuristic { - Always => Infinite, - First => is_infinite(cx, &args[0]), - Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), - All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), - }).and(cap); + Always => Infinite, + First => is_infinite(cx, &args[0]), + Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), + All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), + }).and(cap); } } if method.name == "flat_map" && args.len() == 2 { @@ -159,20 +161,15 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { Finite }, ExprBlock(ref block) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), - ExprBox(ref e) | - ExprAddrOf(_, ref e) => is_infinite(cx, e), - ExprCall(ref path, _) => { - if let ExprPath(ref qpath) = path.node { - match_qpath(qpath, &paths::REPEAT).into() - } else { - Finite - } - }, - ExprStruct(..) => { - higher::range(expr) - .map_or(false, |r| r.end.is_none()) - .into() + ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), + ExprCall(ref path, _) => if let ExprPath(ref qpath) = path.node { + match_qpath(qpath, &paths::REPEAT).into() + } else { + Finite }, + ExprStruct(..) => higher::range(expr) + .map_or(false, |r| r.end.is_none()) + .into(), _ => Finite, } } @@ -220,23 +217,18 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { } } if method.name == "last" && args.len() == 1 { - let not_double_ended = get_trait_def_id(cx, - &paths::DOUBLE_ENDED_ITERATOR) - .map_or(false, |id| { - !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]) - }); + let not_double_ended = get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR) + .map_or(false, |id| !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[])); if not_double_ended { - return is_infinite(cx, &args[0]); + return is_infinite(cx, &args[0]); } } }, - ExprBinary(op, ref l, ref r) => { - if op.node.is_comparison() { - return is_infinite(cx, l).and(is_infinite(cx, r)).and( - MaybeInfinite, - ); - } - }, //TODO: ExprLoop + Match + ExprBinary(op, ref l, ref r) => if op.node.is_comparison() { + return is_infinite(cx, l) + .and(is_infinite(cx, r)) + .and(MaybeInfinite); + }, // TODO: ExprLoop + Match _ => (), } Finite diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 5939cd36bf8..152612bd8ff 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -100,12 +100,10 @@ impl EarlyLintPass for UnitExpr { } fn is_unit_expr(expr: &Expr) -> Option { match expr.node { - ExprKind::Block(ref block) => { - if check_last_stmt_in_block(block) { - Some(block.stmts[block.stmts.len() - 1].span) - } else { - None - } + ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { + Some(block.stmts[block.stmts.len() - 1].span) + } else { + None }, ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); @@ -115,7 +113,11 @@ fn is_unit_expr(expr: &Expr) -> Option { return Some(*expr_else); } } - if check_then { Some(expr.span) } else { None } + if check_then { + Some(expr.span) + } else { + None + } }, ExprKind::Match(ref _pattern, ref arms) => { for arm in arms { @@ -137,12 +139,9 @@ fn check_last_stmt_in_block(block: &Block) -> bool { // like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, - StmtKind::Semi(ref expr) => { - match expr.node { - ExprKind::Break(_, _) | - ExprKind::Ret(_) => false, - _ => true, - } + StmtKind::Semi(ref expr) => match expr.node { + ExprKind::Break(_, _) | ExprKind::Ret(_) => false, + _ => true, }, _ => true, } diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index f14c70dc4dd..2aabecabff0 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -47,9 +47,10 @@ impl EarlyLintPass for ItemsAfterStatements { } // skip initial items - let stmts = item.stmts.iter().map(|stmt| &stmt.node).skip_while(|s| { - matches!(**s, StmtKind::Item(..)) - }); + let stmts = item.stmts + .iter() + .map(|stmt| &stmt.node) + .skip_while(|s| matches!(**s, StmtKind::Item(..))); // lint on all further items for stmt in stmts { @@ -66,7 +67,7 @@ impl EarlyLintPass for ItemsAfterStatements { ITEMS_AFTER_STATEMENTS, it.span, "adding items after statements is confusing, since items exist from the \ - start of the scope", + start of the scope", ); } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 917e0b77370..ceb0cbd6688 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_then, snippet_opt, type_size}; +use utils::{snippet_opt, span_lint_and_then, type_size}; use rustc::ty::TypeFoldable; /// **What it does:** Checks for large size differences between variants on @@ -34,7 +34,9 @@ pub struct LargeEnumVariant { impl LargeEnumVariant { pub fn new(maximum_size_difference_allowed: u64) -> Self { - Self { maximum_size_difference_allowed: maximum_size_difference_allowed } + Self { + maximum_size_difference_allowed: maximum_size_difference_allowed, + } } } @@ -49,9 +51,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect( - "already checked whether this is an enum", - ); + let adt = ty.ty_adt_def() + .expect("already checked whether this is an enum"); let mut smallest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None; @@ -90,15 +91,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { |db| { if variant.fields.len() == 1 { let span = match def.variants[i].node.data { - VariantData::Struct(ref fields, _) | - VariantData::Tuple(ref fields, _) => fields[0].ty.span, + VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => { + fields[0].ty.span + }, VariantData::Unit(_) => unreachable!(), }; if let Some(snip) = snippet_opt(cx, span) { db.span_suggestion( span, "consider boxing the large fields to reduce the total size of the \ - enum", + enum", format!("Box<{}>", snip), ); return; @@ -112,7 +114,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { ); } } - } } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index e862240da59..9b14a44f2c0 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -91,16 +91,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { - item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 - } - } else { - false + item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } + } else { + false + } } // fill the set with current and super traits @@ -121,10 +119,8 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai .iter() .flat_map(|&i| cx.tcx.associated_items(i)) .any(|i| { - i.kind == ty::AssociatedKind::Method && - i.method_has_self_argument && - i.name == "is_empty" && - cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 + i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.name == "is_empty" && + cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); if !is_empty_method_found { @@ -143,16 +139,14 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool { - item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 - } - } else { - false + item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } + } else { + false + } } let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) { @@ -197,7 +191,11 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } fn check_len_zero(cx: &LateContext, span: Span, name: Name, args: &[Expr], lit: &Lit, op: &str) { - if let Spanned { node: LitKind::Int(0, _), .. } = *lit { + if let Spanned { + node: LitKind::Int(0, _), + .. + } = *lit + { if name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint_and_sugg( cx, @@ -231,25 +229,19 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { cx.tcx.inherent_impls(id).iter().any(|imp| { - cx.tcx.associated_items(*imp).any( - |item| is_is_empty(cx, &item), - ) + cx.tcx + .associated_items(*imp) + .any(|item| is_is_empty(cx, &item)) }) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::TyDynamic(..) => { - cx.tcx - .associated_items(ty.ty_to_def_id().expect("trait impl not found")) - .any(|item| is_is_empty(cx, &item)) - }, - ty::TyProjection(_) => { - ty.ty_to_def_id().map_or( - false, - |id| has_is_empty_impl(cx, id), - ) - }, + ty::TyDynamic(..) => cx.tcx + .associated_items(ty.ty_to_def_id().expect("trait impl not found")) + .any(|item| is_is_empty(cx, &item)), + ty::TyProjection(_) => ty.ty_to_def_id() + .map_or(false, |id| has_is_empty_impl(cx, id)), ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did), ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true, _ => false, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 95d45bed133..41ca62b470c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,39 +8,42 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] - #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] -extern crate syntax; -extern crate syntax_pos; #[macro_use] extern crate rustc; +extern crate syntax; +extern crate syntax_pos; extern crate toml; // for unicode nfc normalization + extern crate unicode_normalization; // for semver check in attrs.rs + extern crate semver; // for regex checking + extern crate regex_syntax; // for finding minimal boolean expressions + extern crate quine_mc_cluskey; -extern crate rustc_errors; -extern crate rustc_plugin; extern crate rustc_const_eval; extern crate rustc_const_math; +extern crate rustc_errors; +extern crate rustc_plugin; #[macro_use] extern crate matches as matches_macro; +extern crate serde; #[macro_use] extern crate serde_derive; -extern crate serde; #[macro_use] extern crate lazy_static; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 4cb386471c9..9e7e19a8df5 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -2,10 +2,10 @@ use reexport::*; use rustc::lint::*; use rustc::hir::def::Def; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics, NestedVisitorMap}; -use std::collections::{HashSet, HashMap}; +use rustc::hir::intravisit::{walk_fn_decl, walk_generics, walk_ty, walk_ty_param_bound, NestedVisitorMap, Visitor}; +use std::collections::{HashMap, HashSet}; use syntax::codemap::Span; -use utils::{in_external_macro, span_lint, last_path_segment}; +use utils::{in_external_macro, last_path_segment, span_lint}; use syntax::symbol::keywords; /// **What it does:** Checks for lifetime annotations which can be removed by @@ -171,7 +171,9 @@ fn could_use_elision<'a, 'tcx: 'a>( }; if let Some(body_id) = body { - let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false }; + let mut checker = BodyLifetimeChecker { + lifetimes_used_in_body: false, + }; checker.visit_expr(&cx.tcx.hir.body(body_id).value); if checker.lifetimes_used_in_body { return false; @@ -192,9 +194,9 @@ fn could_use_elision<'a, 'tcx: 'a>( // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - let unnamed_and_static = input_lts.iter().all(|lt| { - *lt == RefLt::Unnamed || *lt == RefLt::Static - }); + let unnamed_and_static = input_lts + .iter() + .all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static); if unnamed_and_static { return false; } @@ -210,8 +212,8 @@ fn could_use_elision<'a, 'tcx: 'a>( match (&input_lts[0], &output_lts[0]) { (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true, (&RefLt::Named(_), &RefLt::Unnamed) => true, - _ => false, // already elided, different named lifetimes - // or something static going on + _ => false, /* already elided, different named lifetimes + * or something static going on */ } } else { false @@ -277,7 +279,11 @@ impl<'v, 't> RefVisitor<'v, 't> { } fn into_vec(self) -> Option> { - if self.abort { None } else { Some(self.lts) } + if self.abort { + None + } else { + Some(self.lts) + } } fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { @@ -285,8 +291,7 @@ impl<'v, 't> RefVisitor<'v, 't> { if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { - Def::TyAlias(def_id) | - Def::Struct(def_id) => { + Def::TyAlias(def_id) | Def::Struct(def_id) => { let generics = self.cx.tcx.generics_of(def_id); for _ in generics.regions.as_slice() { self.record(&None); @@ -318,11 +323,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); }, - TyImplTrait(ref param_bounds) => { - for bound in param_bounds { - if let RegionTyParamBound(_) = *bound { - self.record(&None); - } + TyImplTrait(ref param_bounds) => for bound in param_bounds { + if let RegionTyParamBound(_) = *bound { + self.record(&None); } }, TyTraitObject(ref bounds, ref lt) => { @@ -366,11 +369,9 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & // and check that all lifetimes are allowed match visitor.into_vec() { None => return false, - Some(lts) => { - for lt in lts { - if !allowed_lts.contains(<) { - return true; - } + Some(lts) => for lt in lts { + if !allowed_lts.contains(<) { + return true; } }, } diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index dbb1a7a9b86..1cd539eac39 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax_pos; -use utils::{span_help_and_lint, snippet_opt, in_external_macro}; +use utils::{in_external_macro, snippet_opt, span_help_and_lint}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -195,33 +195,27 @@ enum WarningType { impl WarningType { pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { match *self { - WarningType::UnreadableLiteral => { - span_help_and_lint( - cx, - UNREADABLE_LITERAL, - *span, - "long literal lacking separators", - &format!("consider: {}", grouping_hint), - ) - }, - WarningType::LargeDigitGroups => { - span_help_and_lint( - cx, - LARGE_DIGIT_GROUPS, - *span, - "digit groups should be smaller", - &format!("consider: {}", grouping_hint), - ) - }, - WarningType::InconsistentDigitGrouping => { - span_help_and_lint( - cx, - INCONSISTENT_DIGIT_GROUPING, - *span, - "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint), - ) - }, + WarningType::UnreadableLiteral => span_help_and_lint( + cx, + UNREADABLE_LITERAL, + *span, + "long literal lacking separators", + &format!("consider: {}", grouping_hint), + ), + WarningType::LargeDigitGroups => span_help_and_lint( + cx, + LARGE_DIGIT_GROUPS, + *span, + "digit groups should be smaller", + &format!("consider: {}", grouping_hint), + ), + WarningType::InconsistentDigitGrouping => span_help_and_lint( + cx, + INCONSISTENT_DIGIT_GROUPING, + *span, + "digits grouped inconsistently by underscores", + &format!("consider: {}", grouping_hint), + ), }; } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7a5f7b49278..2f87fe0f396 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,7 +2,7 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, walk_pat, walk_stmt, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; @@ -14,9 +14,9 @@ use std::collections::{HashMap, HashSet}; use syntax::ast; use utils::sugg; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg, in_external_macro, - is_refutable, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, - last_path_segment, span_lint_and_sugg}; +use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, + last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, span_help_and_lint, span_lint, + span_lint_and_sugg, span_lint_and_then}; use utils::paths; /// **What it does:** Checks for looping over the range of `0..len` of some @@ -340,11 +340,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { - ExprWhile(_, ref block, _) | - ExprLoop(ref block, _, _) => { - if never_loop(block, &expr.id) { - span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); - } + ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => if never_loop(block, &expr.id) { + span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); }, _ => (), } @@ -360,7 +357,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { EMPTY_LOOP, expr.span, "empty `loop {}` detected. You may want to either use `panic!()` or add \ - `std::thread::sleep(..);` to the loop body.", + `std::thread::sleep(..);` to the loop body.", ); } @@ -371,8 +368,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | - MatchSource::IfLetDesugar { .. } => { + MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_break_expr(&arms[1].body) @@ -407,8 +403,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) + if let ( + &PatKind::TupleStruct(ref qpath, ref pat_args, _), + &ExprMethodCall(ref method_path, _, ref method_args), + ) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); @@ -441,7 +439,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { UNUSED_COLLECT, expr.span, "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator", + Consider using an explicit for loop to exhaust the iterator", ); } } @@ -455,28 +453,25 @@ fn never_loop(block: &Block, id: &NodeId) -> bool { fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || - block.expr.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) + block + .expr + .as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)) } fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => contains_continue_expr(e, dest), + StmtSemi(ref e, _) | StmtExpr(ref e, _) => contains_continue_expr(e, dest), StmtDecl(ref d, _) => contains_continue_decl(d, dest), } } fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { match decl.node { - DeclLocal(ref local) => { - local.init.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, + DeclLocal(ref local) => local + .init + .as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)), _ => false, } } @@ -492,9 +487,9 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => contains_continue_expr(e, dest), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| contains_continue_expr(e, dest)), + ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => { + es.iter().any(|e| contains_continue_expr(e, dest)) + }, ExprCall(ref e, ref es) => { contains_continue_expr(e, dest) || es.iter().any(|e| contains_continue_expr(e, dest)) }, @@ -502,22 +497,17 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| contains_continue_expr(e, dest)), - ExprIf(ref e, ref e2, ref e3) => { - [e, e2].iter().chain(e3.as_ref().iter()).any(|e| { - contains_continue_expr(e, dest) - }) - }, + ExprIf(ref e, ref e2, ref e3) => [e, e2] + .iter() + .chain(e3.as_ref().iter()) + .any(|e| contains_continue_expr(e, dest)), ExprWhile(ref e, ref b, _) => contains_continue_expr(e, dest) || contains_continue_block(b, dest), ExprMatch(ref e, ref arms, _) => { contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) }, ExprBlock(ref block) => contains_continue_block(block, dest), - ExprStruct(_, _, ref base) => { - base.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, + ExprStruct(_, _, ref base) => base.as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)), ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), _ => false, } @@ -529,8 +519,7 @@ fn loop_exit_block(block: &Block) -> bool { fn loop_exit_stmt(stmt: &Stmt) -> bool { match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => loop_exit_expr(e), + StmtSemi(ref e, _) | StmtExpr(ref e, _) => loop_exit_expr(e), StmtDecl(ref d, _) => loop_exit_decl(d), } } @@ -552,9 +541,7 @@ fn loop_exit_expr(expr: &Expr) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => loop_exit_expr(e), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), + ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), ExprCall(ref e, ref es) => loop_exit_expr(e) || es.iter().any(|e| loop_exit_expr(e)), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | @@ -595,10 +582,10 @@ fn check_for_loop_range<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { @@ -613,9 +600,11 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed.into_iter().next().expect( - "already checked that we have exactly 1 element", - ); + let (indexed, indexed_extent) = visitor + .indexed + .into_iter() + .next() + .expect("already checked that we have exactly 1 element"); // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { @@ -659,16 +648,22 @@ fn check_for_loop_range<'a, 'tcx>( }; if visitor.nonindex { - span_lint_and_then(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), - |db| { - multispan_sugg(db, - "consider using an iterator".to_string(), - vec![(pat.span, format!("({}, )", ident.node)), - (arg.span, format!("{}.iter().enumerate(){}{}", indexed, take, skip))]); - }); + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), + |db| { + multispan_sugg( + db, + "consider using an iterator".to_string(), + vec![ + (pat.span, format!("({}, )", ident.node)), + (arg.span, format!("{}.iter().enumerate(){}{}", indexed, take, skip)), + ], + ); + }, + ); } else { let repl = if starts_at_zero && take.is_empty() { format!("&{}", indexed) @@ -676,17 +671,19 @@ fn check_for_loop_range<'a, 'tcx>( format!("{}.iter(){}{}", indexed, take, skip) }; - span_lint_and_then(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is only used to index `{}`.", - ident.node, - indexed), - |db| { - multispan_sugg(db, - "consider using an iterator".to_string(), - vec![(pat.span, "".to_string()), (arg.span, repl)]); - }); + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`.", ident.node, indexed), + |db| { + multispan_sugg( + db, + "consider using an iterator".to_string(), + vec![(pat.span, "".to_string()), (arg.span, repl)], + ); + }, + ); } } } @@ -711,10 +708,10 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(arg) + start: Some(start), + end: Some(end), + limits, + }) = higher::range(arg) { // ...and both sides are compile-time constant integers... let parent_item = cx.tcx.hir.get_parent(arg.id); @@ -743,19 +740,25 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { ".." }; - span_lint_and_then(cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - |db| { - db.span_suggestion(arg.span, - "consider using the following if you are attempting to iterate over this \ - range in reverse", - format!("({end}{dots}{start}).rev()", - end = end_snippet, - dots = dots, - start = start_snippet)); - }); + span_lint_and_then( + cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run", + |db| { + db.span_suggestion( + arg.span, + "consider using the following if you are attempting to iterate over this \ + range in reverse", + format!( + "({end}{dots}{start}).rev()", + end = end_snippet, + dots = dots, + start = start_snippet + ), + ); + }, + ); } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop // will never run. @@ -783,7 +786,7 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s EXPLICIT_ITER_LOOP, arg.span, "it is more idiomatic to loop over references to containers instead of using explicit \ - iteration methods", + iteration methods", "to write this more concisely, try", format!("&{}{}", muta, object), ) @@ -816,7 +819,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { EXPLICIT_INTO_ITER_LOOP, arg.span, "it is more idiomatic to loop over containers instead of using explicit \ - iteration methods`", + iteration methods`", "to write this more concisely, try", object.to_string(), ); @@ -827,7 +830,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { ITER_NEXT_LOOP, expr.span, "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ - probably not what you want", + probably not what you want", ); next_loop_linted = true; } @@ -848,7 +851,7 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { arg.span, &format!( "for loop over `{0}`, which is an `Option`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), &format!( @@ -864,7 +867,7 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { arg.span, &format!( "for loop over `{0}`, which is a `Result`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), &format!( @@ -894,14 +897,14 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| { - map.get_enclosing_scope(id) - }); + let parent_scope = map.get_enclosing_scope(expr.id) + .and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter( - |&(_, v)| *v == VarState::IncrOnce, - ) + for (id, _) in visitor + .states + .iter() + .filter(|&(_, v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { cx: cx, @@ -922,7 +925,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( expr.span, &format!( "the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ - item) in {1}.enumerate()` or similar iterators", + item) in {1}.enumerate()` or similar iterators", name, snippet(cx, arg.span, "_") ), @@ -948,12 +951,10 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ref tam) => { - match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), - (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), - _ => return, - } + ty::TyRef(_, ref tam) => match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), + _ => return, }, _ => return, }; @@ -967,21 +968,26 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( }; if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) { - span_lint_and_then(cx, - FOR_KV_MAP, - expr.span, - &format!("you seem to want to iterate on a map's {}s", kind), - |db| { - let map = sugg::Sugg::hir(cx, arg, "map"); - multispan_sugg(db, - "use the corresponding method".into(), - vec![(pat_span, snippet(cx, new_pat_span, kind).into_owned()), - (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl))]); - }); + span_lint_and_then( + cx, + FOR_KV_MAP, + expr.span, + &format!("you seem to want to iterate on a map's {}s", kind), + |db| { + let map = sugg::Sugg::hir(cx, arg, "map"); + multispan_sugg( + db, + "use the corresponding method".into(), + vec![ + (pat_span, snippet(cx, new_pat_span, kind).into_owned()), + (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)), + ], + ); + }, + ); } } } - } /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. @@ -1011,7 +1017,7 @@ fn match_var(expr: &Expr, var: Name) -> bool { struct UsedVisitor { var: ast::Name, // var to look for - used: bool, // has the var been used otherwise? + used: bool, // has the var been used otherwise? } impl<'tcx> Visitor<'tcx> for UsedVisitor { @@ -1196,12 +1202,9 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), - None if !block.stmts.is_empty() => { - match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), - StmtDecl(..) => None, - } + None if !block.stmts.is_empty() => match block.stmts[0].node { + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + StmtDecl(..) => None, }, _ => None, } @@ -1211,11 +1214,9 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { fn is_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(dest, _) if dest.ident.is_none() => true, - ExprBlock(ref b) => { - match extract_first_expr(b) { - Some(subexpr) => is_break_expr(subexpr), - None => false, - } + ExprBlock(ref b) => match extract_first_expr(b) { + Some(subexpr) => is_break_expr(subexpr), + None => false, }, _ => false, } @@ -1226,7 +1227,7 @@ fn is_break_expr(expr: &Expr) -> bool { // at the start of the loop. #[derive(PartialEq)] enum VarState { - Initial, // Not examined yet + Initial, // Not examined yet IncrOnce, // Incremented exactly once, may be a loop counter Declared, // Declared but not (yet) initialized to zero Warn, @@ -1235,9 +1236,9 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'a, 'tcx>, // context reference states: HashMap, // incremented variables - depth: u32, // depth of conditional expressions + depth: u32, // depth of conditional expressions done: bool, } @@ -1291,7 +1292,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { /// Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, // context reference - end_expr: &'tcx Expr, // the for loop. Stop scanning here. + end_expr: &'tcx Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, name: Option, @@ -1379,9 +1380,10 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { if let ExprPath(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.hir_id); if let Def::Local(def_id) = path_res { - let node_id = cx.tcx.hir.as_local_node_id(def_id).expect( - "That DefId should be valid", - ); + let node_id = cx.tcx + .hir + .as_local_node_id(def_id) + .expect("That DefId should be valid"); return Some(node_id); } } @@ -1425,13 +1427,11 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool return false; } match cx.tcx.hir.find(parent) { - Some(NodeExpr(expr)) => { - match expr.node { - ExprLoop(..) | ExprWhile(..) => { - return true; - }, - _ => (), - } + Some(NodeExpr(expr)) => match expr.node { + ExprLoop(..) | ExprWhile(..) => { + return true; + }, + _ => (), }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { @@ -1455,12 +1455,12 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool #[derive(PartialEq, Eq)] enum Nesting { - Unknown, // no nesting detected yet - RuledOut, // the iterator is initialized or assigned within scope + Unknown, // no nesting detected yet + RuledOut, // the iterator is initialized or assigned within scope LookFurther, // no nesting detected, no further walk required } -use self::Nesting::{Unknown, RuledOut, LookFurther}; +use self::Nesting::{LookFurther, RuledOut, Unknown}; struct LoopNestVisitor { id: NodeId, @@ -1486,11 +1486,8 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprAssign(ref path, _) | - ExprAssignOp(_, ref path, _) => { - if match_var(path, self.iterator) { - self.nesting = RuledOut; - } + ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { + self.nesting = RuledOut; }, _ => walk_expr(self, expr), } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index f0e19a3b577..733022f1703 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{is_adjusted, match_qpath, match_trait_method, match_type, remove_blocks, paths, snippet, - span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; +use utils::{is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, paths, remove_blocks, snippet, + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -73,21 +73,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }} }, - ExprPath(ref path) => { - if match_qpath(path, &paths::CLONE) { - let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint( - cx, - MAP_CLONE, - expr.span, - &format!( - "you seem to be using .map() to clone the contents of an \ - {}, consider using `.cloned()`", - type_name - ), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), - ); - } + ExprPath(ref path) => if match_qpath(path, &paths::CLONE) { + let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); + span_help_and_lint( + cx, + MAP_CLONE, + expr.span, + &format!( + "you seem to be using .map() to clone the contents of an \ + {}, consider using `.cloned()`", + type_name + ), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), + ); }, _ => (), } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 77050a0e299..b9a4507c5d7 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -11,8 +11,8 @@ use syntax::ast::LitKind; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; -use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, span_lint_and_sugg, in_external_macro, - expr_block, walk_ptrs_ty, is_expn_of, remove_blocks, is_allowed}; +use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_type, remove_blocks, snippet, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use utils::sugg::Sugg; /// **What it does:** Checks for matches with a single arm where an `if let` @@ -219,7 +219,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], lint, expr.span, "you seem to be trying to use match for destructuring a single pattern. Consider using `if \ - let`", + let`", "try this", format!( "if let {} = {} {}{}", @@ -290,21 +290,17 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if let Some((true_expr, false_expr)) = exprs { let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => { - Some(format!( - "if {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, "..") - )) - }, - (false, true) => { - Some(format!( - "if {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, "..") - )) - }, + (false, false) => Some(format!( + "if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, "..") + )), + (false, true) => Some(format!( + "if {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, "..") + )), (true, false) => { let test = Sugg::hir(cx, ex, ".."); Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) @@ -317,7 +313,6 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } } - }, ); } @@ -384,15 +379,17 @@ fn is_panic_block(block: &Block) -> bool { fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - span_lint_and_then(cx, - MATCH_REF_PATS, - expr.span, - "you don't need to add `&` to both the expression and the patterns", - |db| { - let inner = Sugg::hir(cx, inner, ".."); - let template = match_template(expr.span, source, &inner); - db.span_suggestion(expr.span, "try", template); - }); + span_lint_and_then( + cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to both the expression and the patterns", + |db| { + let inner = Sugg::hir(cx, inner, ".."); + let template = match_template(expr.span, source, &inner); + db.span_suggestion(expr.span, "try", template); + }, + ); } else { span_lint_and_then( cx, @@ -471,24 +468,18 @@ fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { - (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Included(end)), - }) - }, - (ConstVal::Integral(start), Bound::Excluded(ConstVal::Integral(end))) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Excluded(end)), - }) - }, - (ConstVal::Integral(start), Bound::Unbounded) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Unbounded), - }) - }, + (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Included(end)), + }), + (ConstVal::Integral(start), Bound::Excluded(ConstVal::Integral(end))) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Excluded(end)), + }), + (ConstVal::Integral(start), Bound::Unbounded) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Unbounded), + }), _ => None, }) .collect() @@ -507,9 +498,9 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { .flat_map(|a| &a.pats) .map(|p| { match p.node { - PatKind::Ref(..) => Some(true), // &-patterns + PatKind::Ref(..) => Some(true), // &-patterns PatKind::Wild => Some(false), // an "anything" wildcard is also fine - _ => None, // any other pattern is not fine + _ => None, // any other pattern is not fine } }) .collect::>>(); @@ -540,8 +531,7 @@ where impl<'a, T: Copy> Kind<'a, T> { fn range(&self) -> &'a SpannedRange { match *self { - Kind::Start(_, r) | - Kind::End(_, r) => r, + Kind::Start(_, r) | Kind::End(_, r) => r, } } @@ -562,22 +552,16 @@ where impl<'a, T: Copy + Ord> Ord for Kind<'a, T> { fn cmp(&self, other: &Self) -> Ordering { match (self.value(), other.value()) { - (Bound::Included(a), Bound::Included(b)) | - (Bound::Excluded(a), Bound::Excluded(b)) => a.cmp(&b), + (Bound::Included(a), Bound::Included(b)) | (Bound::Excluded(a), Bound::Excluded(b)) => a.cmp(&b), // Range patterns cannot be unbounded (yet) - (Bound::Unbounded, _) | - (_, Bound::Unbounded) => unimplemented!(), - (Bound::Included(a), Bound::Excluded(b)) => { - match a.cmp(&b) { - Ordering::Equal => Ordering::Greater, - other => other, - } + (Bound::Unbounded, _) | (_, Bound::Unbounded) => unimplemented!(), + (Bound::Included(a), Bound::Excluded(b)) => match a.cmp(&b) { + Ordering::Equal => Ordering::Greater, + other => other, }, - (Bound::Excluded(a), Bound::Included(b)) => { - match a.cmp(&b) { - Ordering::Equal => Ordering::Less, - other => other, - } + (Bound::Excluded(a), Bound::Included(b)) => match a.cmp(&b) { + Ordering::Equal => Ordering::Less, + other => other, }, } } @@ -594,10 +578,8 @@ where for (a, b) in values.iter().zip(values.iter().skip(1)) { match (a, b) { - (&Kind::Start(_, ra), &Kind::End(_, rb)) => { - if ra.node != rb.node { - return Some((ra, rb)); - } + (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node { + return Some((ra, rb)); }, (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (), _ => return Some((a.range(), b.range())), diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index edf477720d5..9058d0d102d 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -39,8 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { if match forgot_ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, - } - { + } { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index cfaa9f698e0..84c213023a2 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -8,10 +8,10 @@ use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_qpath, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, span_lint_and_then, - span_lint_and_sugg, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, last_path_segment, - single_segment_path, match_def_path, is_self, is_self_ty, iter_input_pats, match_path}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, + iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, + match_type, method_chain_args, return_ty, same_tys, single_segment_path, snippet, span_lint, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; @@ -618,11 +618,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match self_ty.sty { - ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => { - for &(method, pos) in &PATTERN_METHODS { - if method_call.name == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); - } + ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { + if method_call.name == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); } }, _ => (), @@ -723,12 +721,11 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: if ["default", "new"].contains(&path) { let arg_ty = cx.tables.expr_ty(arg); - let default_trait_id = - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { - default_trait_id - } else { - return false; - }; + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { + default_trait_id + } else { + return false; + }; if implements_trait(cx, arg_ty, default_trait_id, &[]) { span_lint_and_sugg( @@ -771,13 +768,12 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: } // (path, fn_has_argument, methods, suffix) - let know_types: &[(&[_], _, &[_], _)] = - &[ - (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&paths::RESULT, true, &["or", "unwrap_or"], "else"), - ]; + let know_types: &[(&[_], _, &[_], _)] = &[ + (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), + (&paths::RESULT, true, &["or", "unwrap_or"], "else"), + ]; let self_ty = cx.tables.expr_ty(self_expr); @@ -835,7 +831,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t CLONE_DOUBLE_REF, expr.span, "using `clone` on a double-reference; \ - this will copy the reference instead of cloning the inner type", + this will copy the reference instead of cloning the inner type", |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref())); }, @@ -919,7 +915,7 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir ITER_CLONED_COLLECT, expr.span, "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable", + more readable", ); } } @@ -1021,12 +1017,10 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option sugg::Sugg::hir_opt(cx, expr), ty::TyAdt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => { - if may_slice(cx, inner) { - sugg::Sugg::hir_opt(cx, expr) - } else { - None - } + ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => if may_slice(cx, inner) { + sugg::Sugg::hir_opt(cx, expr) + } else { + None }, _ => None, } @@ -1052,8 +1046,8 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { expr.span, &format!( "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ - using expect() to provide a better panic \ - message", + using expect() to provide a better panic \ + message", kind, none_value ), @@ -1222,7 +1216,7 @@ fn lint_search_is_some( if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { let msg = format!( "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ - expressed by calling `any()`.", + expressed by calling `any()`.", search_method ); let search_snippet = snippet(cx, search_args[1].span, ".."); @@ -1459,35 +1453,37 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { param.name == seg.name && - param.bounds.iter().any(|bound| { - if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { + param + .bounds + .iter() + .any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; match_path(path, name) && - path.segments.last().map_or( - false, - |s| if s.parameters.parenthesized { + path.segments + .last() + .map_or(false, |s| if s.parameters.parenthesized { false } else { s.parameters.types.len() == 1 && (is_self_ty(&s.parameters.types[0]) || is_ty(&*s.parameters.types[0], self_ty)) - }, - ) + }) } else { false - } - }) + }) }) }) } fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { match (&ty.node, &self_ty.node) { - (&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), - &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => { - ty_path.segments.iter().map(|seg| seg.name).eq( - self_ty_path.segments.iter().map(|seg| seg.name), - ) - }, + ( + &hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), + &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path)), + ) => ty_path + .segments + .iter() + .map(|seg| seg.name) + .eq(self_ty_path.segments.iter().map(|seg| seg.name)), _ => false, } } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index a86b2b300e5..aea92311763 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,7 +1,7 @@ -use consts::{Constant, constant_simple}; +use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; -use std::cmp::{PartialOrd, Ordering}; +use std::cmp::{Ordering, PartialOrd}; use utils::{match_def_path, paths, span_lint}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are @@ -41,9 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | - (MinMax::Max, Some(Ordering::Less)) | - (MinMax::Min, Some(Ordering::Greater)) => (), + (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); }, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e7c3fb895fb..da6919da93d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,12 +7,12 @@ use rustc::ty; use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; use rustc_const_math::ConstFloat; -use syntax::codemap::{Span, ExpnFormat}; -use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_qpath, snippet, - span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats, in_constant, - match_trait_method, paths}; +use syntax::codemap::{ExpnFormat, Span}; +use utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, + iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, + span_lint_and_then, walk_ptrs_ty}; use utils::sugg::Sugg; -use syntax::ast::{LitKind, CRATE_NODE_ID, FloatTy}; +use syntax::ast::{FloatTy, LitKind, CRATE_NODE_ID}; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -242,7 +242,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { TOPLEVEL_REF_ARG, arg.pat.span, "`ref` directly on a function argument is ignored. Consider using a reference type \ - instead.", + instead.", ); }, _ => {}, @@ -385,7 +385,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, &format!( "used binding `{}` which is prefixed with an underscore. A leading \ - underscore signals that a binding will not be used.", + underscore signals that a binding will not be used.", binding ), ); @@ -484,16 +484,14 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { return; } }, - ExprCall(ref path, ref v) if v.len() == 1 => { - if let ExprPath(ref path) = path.node { - if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { - (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) - } else { - return; - } + ExprCall(ref path, ref v) if v.len() == 1 => if let ExprPath(ref path) = path.node { + if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { + (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) } else { return; } + } else { + return; }, _ => return, }; @@ -554,8 +552,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) | - ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, _ => is_used(cx, parent), } } else { @@ -567,20 +564,21 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { /// generated by /// `#[derive(...)`] or the like). fn in_attributes_expansion(expr: &Expr) -> bool { - expr.span.ctxt().outer().expn_info().map_or( - false, - |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)), - ) + expr.span + .ctxt() + .outer() + .expn_info() + .map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_))) } /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { - def::Def::Local(def_id) | - def::Def::Upvar(def_id, _, _) => { - let id = cx.tcx.hir.as_local_node_id(def_id).expect( - "local variables should be found in the same crate", - ); + def::Def::Local(def_id) | def::Def::Upvar(def_id, _, _) => { + let id = cx.tcx + .hir + .as_local_node_id(def_id) + .expect("local variables should be found in the same crate"); !in_macro(cx.tcx.hir.span(id)) }, _ => false, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 52a97024e44..bf4df6e2873 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,7 +4,7 @@ use std::char; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{constants, span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then, in_external_macro}; +use utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -251,7 +251,7 @@ impl EarlyLintPass for MiscEarly { UNNEEDED_FIELD_PATTERN, field.span, "You matched a field with a wildcard pattern. Consider using `..` \ - instead", + instead", &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), ); } @@ -276,7 +276,7 @@ impl EarlyLintPass for MiscEarly { *correspondence, &format!( "`{}` already exists, having another argument having almost the same \ - name makes code comprehension and documentation more difficult", + name makes code comprehension and documentation more difficult", arg_name[1..].to_owned() ), );; @@ -293,30 +293,28 @@ impl EarlyLintPass for MiscEarly { return; } match expr.node { - ExprKind::Call(ref paren, _) => { - if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { - span_lint_and_then(cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| if decl.inputs.is_empty() { - let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion(expr.span, "Try doing something like: ", hint); - }); - } - } - }, - ExprKind::Unary(UnOp::Neg, ref inner) => { - if let ExprKind::Unary(UnOp::Neg, _) = inner.node { - span_lint( + ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { + span_lint_and_then( cx, - DOUBLE_NEG, + REDUNDANT_CLOSURE_CALL, expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + "Try not to call a closure in the expression where it is declared.", + |db| if decl.inputs.is_empty() { + let hint = snippet(cx, block.span, "..").into_owned(); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + }, ); } }, + ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node { + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); + }, ExprKind::Lit(ref lit) => self.check_lit(cx, lit), _ => (), } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 9ce7df474a3..81a8b4ffb2e 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -18,7 +18,7 @@ // [`missing_doc`]: // https://github. // com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin. -// +// // // // @@ -64,13 +64,15 @@ impl ::std::default::Default for MissingDoc { impl MissingDoc { pub fn new() -> Self { - Self { doc_hidden_stack: vec![false] } + Self { + doc_hidden_stack: vec![false], + } } fn doc_hidden(&self) -> bool { - *self.doc_hidden_stack.last().expect( - "empty doc_hidden_stack", - ) + *self.doc_hidden_stack + .last() + .expect("empty doc_hidden_stack") } fn check_missing_docs_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { @@ -89,9 +91,9 @@ impl MissingDoc { return; } - let has_doc = attrs.iter().any(|a| { - a.is_value_str() && a.name().map_or(false, |n| n == "doc") - }); + let has_doc = attrs + .iter() + .any(|a| a.is_value_str() && a.name().map_or(false, |n| n == "doc")); if !has_doc { cx.span_lint( MISSING_DOCS_IN_PRIVATE_ITEMS, @@ -110,14 +112,12 @@ impl LintPass for MissingDoc { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { - let doc_hidden = self.doc_hidden() || - attrs.iter().any(|attr| { - attr.check_name("doc") && - match attr.meta_item_list() { - None => false, - Some(l) => attr::list_contains_name(&l[..], "hidden"), - } - }); + let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { + attr.check_name("doc") && match attr.meta_item_list() { + None => false, + Some(l) => attr::list_contains_name(&l[..], "hidden"), + } + }); self.doc_hidden_stack.push(doc_hidden); } @@ -166,10 +166,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let def_id = cx.tcx.hir.local_def_id(impl_item.id); match cx.tcx.associated_item(def_id).container { ty::TraitContainer(_) => return, - ty::ImplContainer(cid) => { - if cx.tcx.impl_trait_ref(cid).is_some() { - return; - } + ty::ImplContainer(cid) => if cx.tcx.impl_trait_ref(cid).is_some() { + return; }, } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index e8133050475..c12d3dde2be 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -70,7 +70,14 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { expr.span, "generally you want to avoid `&mut &mut _` if possible", ); - } else if let ty::TyRef(_, ty::TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty { + } else if let ty::TyRef( + _, + ty::TypeAndMut { + mutbl: hir::MutMutable, + .. + }, + ) = self.cx.tables.expr_ty(e).sty + { span_lint( self.cx, MUT_MUT, @@ -82,13 +89,22 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyRptr(_, - hir::MutTy { - ty: ref pty, - mutbl: hir::MutMutable, - }) = ty.node + if let hir::TyRptr( + _, + hir::MutTy { + ty: ref pty, + mutbl: hir::MutMutable, + }, + ) = ty.node { - if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node { + if let hir::TyRptr( + _, + hir::MutTy { + mutbl: hir::MutMutable, + .. + }, + ) = pty.node + { span_lint( self.cx, MUT_MUT, @@ -96,7 +112,6 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { "generally you want to avoid `&mut &mut _` if possible", ); } - } intravisit::walk_ty(self, ty); diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 6a7b45bfbfb..63ccc77a03d 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -36,15 +36,13 @@ impl LintPass for UnnecessaryMutPassed { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { match e.node { - ExprCall(ref fn_expr, ref arguments) => { - if let ExprPath(ref path) = fn_expr.node { - check_arguments( - cx, - arguments, - cx.tables.expr_ty(fn_expr), - &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), - ); - } + ExprCall(ref fn_expr, ref arguments) => if let ExprPath(ref path) = fn_expr.node { + check_arguments( + cx, + arguments, + cx.tables.expr_ty(fn_expr), + &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + ); }, ExprMethodCall(ref path, _, ref arguments) => { let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); @@ -63,16 +61,23 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - ty::TyRef(_, ty::TypeAndMut { mutbl: MutImmutable, .. }) | - ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => { - if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint( - cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method `{}` doesn't need a mutable reference", name), - ); - } + ty::TyRef( + _, + ty::TypeAndMut { + mutbl: MutImmutable, + .. + }, + ) | + ty::TyRawPtr(ty::TypeAndMut { + mutbl: MutImmutable, + .. + }) => if let ExprAddrOf(MutMutable, _) = argument.node { + span_lint( + cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method `{}` doesn't need a mutable reference", name), + ); }, _ => (), } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 25a7118ceda..6fe365fd255 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -2,7 +2,7 @@ //! //! This lint is **warn** by default -use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!( "Consider using an {} instead of a Mutex here. If you just want the locking \ - behaviour and not the internal type, consider using Mutex<()>.", + behaviour and not the internal type, consider using Mutex<()>.", atomic_name ); match mutex_param.sty { diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 52f0df12bcd..bc93190cd09 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; -use utils::{span_lint, span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint, span_lint_and_sugg}; use utils::sugg::Sugg; /// **What it does:** Checks for expressions of the form `if c { true } else { @@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { }; if let ExprBlock(ref then_block) = then_block.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (RetBool(true), RetBool(true)) | - (Bool(true), Bool(true)) => { + (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { span_lint( cx, NEEDLESS_BOOL, @@ -91,8 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { "this if-then-else expression will always return true", ); }, - (RetBool(false), RetBool(false)) | - (Bool(false), Bool(false)) => { + (RetBool(false), RetBool(false)) | (Bool(false), Bool(false)) => { span_lint( cx, NEEDLESS_BOOL, @@ -186,16 +184,14 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), - (&[ref e], None) => { - if let StmtSemi(ref e, _) = e.node { - if let ExprRet(_) = e.node { - fetch_bool_expr(&**e) - } else { - Expression::Other - } + (&[ref e], None) => if let StmtSemi(ref e, _) = e.node { + if let ExprRet(_) = e.node { + fetch_bool_expr(&**e) } else { Expression::Other } + } else { + Expression::Other }, _ => Expression::Other, } @@ -204,18 +200,14 @@ fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), - ExprLit(ref lit_ptr) => { - if let LitKind::Bool(value) = lit_ptr.node { - Expression::Bool(value) - } else { - Expression::Other - } + ExprLit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { + Expression::Bool(value) + } else { + Expression::Other }, - ExprRet(Some(ref expr)) => { - match fetch_bool_expr(expr) { - Expression::Bool(value) => Expression::RetBool(value), - _ => Expression::Other, - } + ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { + Expression::Bool(value) => Expression::RetBool(value), + _ => Expression::Other, }, _ => Expression::Other, } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index b331d6910a3..7dd42bca3ab 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -3,10 +3,10 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingAnnotation}; +use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind}; use rustc::ty; -use rustc::ty::adjustment::{Adjustment, Adjust}; -use utils::{span_lint, in_macro}; +use rustc::ty::adjustment::{Adjust, Adjustment}; +use utils::{in_macro, span_lint}; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. @@ -43,16 +43,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if let ExprAddrOf(MutImmutable, ref inner) = e.node { if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty { for adj3 in cx.tables.expr_adjustments(e).windows(3) { - if let [ - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Borrow(_), .. } - ] = *adj3 { - span_lint(cx, - NEEDLESS_BORROW, - e.span, - "this expression borrows a reference that is immediately dereferenced by the \ - compiler"); + if let [Adjustment { + kind: Adjust::Deref(_), + .. + }, Adjustment { + kind: Adjust::Deref(_), + .. + }, Adjustment { + kind: Adjust::Borrow(_), + .. + }] = *adj3 + { + span_lint( + cx, + NEEDLESS_BORROW, + e.span, + "this expression borrows a reference that is immediately dereferenced by the \ + compiler", + ); } } } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 0aa741db076..1c00263cbc2 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,8 +3,8 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; -use utils::{span_lint_and_then, in_macro, snippet}; +use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; +use utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for useless borrowed references. /// diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 692fa19f3ba..b369d8b570b 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -32,7 +32,7 @@ use syntax::ast; use syntax::codemap::{original_sp, DUMMY_SP}; use std::borrow::Cow; -use utils::{in_macro, span_help_and_lint, snippet_block, snippet, trim_multiline}; +use utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; /// **What it does:** The lint checks for `if`-statements appearing in loops /// that contain a `continue` statement in either their main blocks or their @@ -181,13 +181,10 @@ fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { fn is_first_block_stmt_continue(block: &ast::Block) -> bool { block.stmts.get(0).map_or(false, |stmt| match stmt.node { - ast::StmtKind::Semi(ref e) | - ast::StmtKind::Expr(ref e) => { - if let ast::ExprKind::Continue(_) = e.node { - true - } else { - false - } + ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node { + true + } else { + false }, _ => false, }) @@ -222,8 +219,7 @@ where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr), { match stmt.node { - ast::StmtKind::Semi(ref e) | - ast::StmtKind::Expr(ref e) => { + ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => { if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node { func(e, cond, if_block, else_expr); } @@ -269,25 +265,20 @@ const DROP_ELSE_BLOCK_MSG: &'static str = "Consider dropping the else clause, an fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: LintType) { - // snip is the whole *help* message that appears after the warning. // message is the warning message. // expr is the expression which the lint warning message refers to. let (snip, message, expr) = match typ { - LintType::ContinueInsideElseBlock => { - ( - suggestion_snippet_for_continue_inside_else(ctx, data, header), - MSG_REDUNDANT_ELSE_BLOCK, - data.else_expr, - ) - }, - LintType::ContinueInsideThenBlock => { - ( - suggestion_snippet_for_continue_inside_if(ctx, data, header), - MSG_ELSE_BLOCK_NOT_NEEDED, - data.if_expr, - ) - }, + LintType::ContinueInsideElseBlock => ( + suggestion_snippet_for_continue_inside_else(ctx, data, header), + MSG_REDUNDANT_ELSE_BLOCK, + data.else_expr, + ), + LintType::ContinueInsideThenBlock => ( + suggestion_snippet_for_continue_inside_if(ctx, data, header), + MSG_ELSE_BLOCK_NOT_NEEDED, + data.if_expr, + ), }; span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 89ef4ff67f3..f53e8521076 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -9,9 +9,9 @@ use rustc::middle::mem_categorization as mc; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; -use utils::{in_macro, is_self, is_copy, implements_trait, get_trait_def_id, match_type, snippet, span_lint_and_then, - multispan_sugg, paths}; -use std::collections::{HashSet, HashMap}; +use utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, + snippet, span_lint_and_then}; +use std::collections::{HashMap, HashSet}; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its @@ -62,16 +62,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } match kind { - FnKind::ItemFn(.., attrs) => { - for a in attrs { - if_let_chain!{[ - a.meta_item_list().is_some(), - let Some(name) = a.name(), - name == "proc_macro_derive", - ], { - return; - }} - } + FnKind::ItemFn(.., attrs) => for a in attrs { + if_let_chain!{[ + a.meta_item_list().is_some(), + let Some(name) = a.name(), + name == "proc_macro_derive", + ], { + return; + }} }, _ => return, } @@ -106,7 +104,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { - // Determines whether `ty` implements `Borrow` (U != ty) specifically. // This is needed due to the `Borrow for T` blanket impl. let implements_borrow_trait = preds @@ -118,9 +115,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { }) .filter(|tpred| tpred.def_id() == borrow_trait && tpred.self_ty() == ty) .any(|tpred| { - tpred.input_types().nth(1).expect( - "Borrow trait must have an parameter", - ) != ty + tpred + .input_types() + .nth(1) + .expect("Borrow trait must have an parameter") != ty }); if_let_chain! {[ @@ -299,8 +297,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { fn unwrap_downcast_or_interior(mut cmt: mc::cmt) -> mc::cmt { loop { match cmt.cat.clone() { - mc::Categorization::Downcast(c, _) | - mc::Categorization::Interior(c, _) => { + mc::Categorization::Downcast(c, _) | mc::Categorization::Interior(c, _) => { cmt = c; }, _ => return cmt, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index c6bd91919f5..1c5524af68e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -115,43 +115,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { - let self_ty = cx.tcx.type_of( - cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)), - ); + let self_ty = cx.tcx + .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); if_let_chain!{[ - same_tys(cx, self_ty, return_ty(cx, id)), - let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), - !implements_trait(cx, self_ty, default_trait_id, &[]) - ], { - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); - }); - } else { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_prepend_item(cx, - span, - "try this", - &format!( + same_tys(cx, self_ty, return_ty(cx, id)), + let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), + !implements_trait(cx, self_ty, default_trait_id, &[]) + ], { + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + }); + } else { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_prepend_item(cx, + span, + "try this", + &format!( "impl Default for {} {{ fn default() -> Self {{ Self::new() }} }}", - self_ty)); - }); - } - }} + self_ty)); + }); + } + }} } } } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 971309adb33..1d5e51187bb 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; -use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource, BiAnd, BiOr}; -use utils::{in_macro, span_lint, snippet_opt, span_lint_and_sugg}; +use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; +use utils::{in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. @@ -45,13 +45,11 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { return false; } match expr.node { - Expr_::ExprLit(..) | - Expr_::ExprClosure(.., _) | - Expr_::ExprPath(..) => true, - Expr_::ExprIndex(ref a, ref b) | - Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), - Expr_::ExprArray(ref v) | - Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), + Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) | Expr_::ExprPath(..) => true, + Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => { + has_no_effect(cx, a) && has_no_effect(cx, b) + }, + Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), Expr_::ExprRepeat(ref inner, _) | Expr_::ExprCast(ref inner, _) | Expr_::ExprType(ref inner, _) | @@ -61,33 +59,28 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { Expr_::ExprAddrOf(_, ref inner) | Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), Expr_::ExprStruct(_, ref fields, ref base) => { - fields.iter().all(|field| has_no_effect(cx, &field.expr)) && - match *base { - Some(ref base) => has_no_effect(cx, base), - None => true, - } + fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } }, - Expr_::ExprCall(ref callee, ref args) => { - if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | - Def::Variant(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => args.iter().all(|arg| has_no_effect(cx, arg)), - _ => false, - } - } else { - false + Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + args.iter().all(|arg| has_no_effect(cx, arg)) + }, + _ => false, } + } else { + false }, Expr_::ExprBlock(ref block) => { - block.stmts.is_empty() && - if let Some(ref expr) = block.expr { - has_no_effect(cx, expr) - } else { - false - } + block.stmts.is_empty() && if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) + } else { + false + } }, _ => false, } @@ -143,8 +136,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { Some(vec![&**a, &**b]) }, - Expr_::ExprArray(ref v) | - Expr_::ExprTup(ref v) => Some(v.iter().collect()), + Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => Some(v.iter().collect()), Expr_::ExprRepeat(ref inner, _) | Expr_::ExprCast(ref inner, _) | Expr_::ExprType(ref inner, _) | @@ -153,29 +145,24 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => { - Some( - fields - .iter() - .map(|f| &f.expr) - .chain(base) - .map(Deref::deref) - .collect(), - ) - }, - Expr_::ExprCall(ref callee, ref args) => { - if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | - Def::Variant(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => Some(args.iter().collect()), - _ => None, - } - } else { - None + Expr_::ExprStruct(_, ref fields, ref base) => Some( + fields + .iter() + .map(|f| &f.expr) + .chain(base) + .map(Deref::deref) + .collect(), + ), + Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + Some(args.iter().collect()) + }, + _ => None, } + } else { + None }, Expr_::ExprBlock(ref block) => { if block.stmts.is_empty() { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index c584e3b1a9e..d36054eacf4 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -3,8 +3,8 @@ use syntax::codemap::Span; use syntax::symbol::InternedString; use syntax::ast::*; use syntax::attr; -use syntax::visit::{Visitor, walk_block, walk_pat, walk_expr}; -use utils::{span_lint_and_then, in_macro, span_lint}; +use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; +use utils::{in_macro, span_lint, span_lint_and_then}; /// **What it does:** Checks for names that are very similar and thus confusing. /// @@ -82,11 +82,9 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.node { PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), - PatKind::Struct(_, ref fields, _) => { - for field in fields { - if !field.node.is_shorthand { - self.visit_pat(&field.node.pat); - } + PatKind::Struct(_, ref fields, _) => for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); } }, _ => walk_pat(self, pat), @@ -104,9 +102,8 @@ fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { } fn whitelisted(interned_name: &str, list: &[&str]) -> bool { - list.iter().any(|&name| { - interned_name.starts_with(name) || interned_name.ends_with(name) - }) + list.iter() + .any(|&name| interned_name.starts_with(name) || interned_name.ends_with(name)) } impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { @@ -157,21 +154,21 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } else { let mut interned_chars = interned_name.chars(); let mut existing_chars = existing_name.interned.chars(); - let first_i = interned_chars.next().expect( - "we know we have at least one char", - ); - let first_e = existing_chars.next().expect( - "we know we have at least one char", - ); + let first_i = interned_chars + .next() + .expect("we know we have at least one char"); + let first_e = existing_chars + .next() + .expect("we know we have at least one char"); let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric(); if eq_or_numeric((first_i, first_e)) { - let last_i = interned_chars.next_back().expect( - "we know we have at least two chars", - ); - let last_e = existing_chars.next_back().expect( - "we know we have at least two chars", - ); + let last_i = interned_chars + .next_back() + .expect("we know we have at least two chars"); + let last_e = existing_chars + .next_back() + .expect("we know we have at least two chars"); if eq_or_numeric((last_i, last_e)) { if interned_chars .zip(existing_chars) @@ -181,12 +178,12 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { continue; } } else { - let second_last_i = interned_chars.next_back().expect( - "we know we have at least three chars", - ); - let second_last_e = existing_chars.next_back().expect( - "we know we have at least three chars", - ); + let second_last_i = interned_chars + .next_back() + .expect("we know we have at least three chars"); + let second_last_e = existing_chars + .next_back() + .expect("we know we have at least three chars"); if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { @@ -197,12 +194,12 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); } } else { - let second_i = interned_chars.next().expect( - "we know we have at least two chars", - ); - let second_e = existing_chars.next().expect( - "we know we have at least two chars", - ); + let second_i = interned_chars + .next() + .expect("we know we have at least two chars"); + let second_e = existing_chars + .next() + .expect("we know we have at least two chars"); if !eq_or_numeric((second_i, second_e)) || second_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { @@ -225,7 +222,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { span, &format!( "separate the discriminating character by an \ - underscore like: `{}_{}`", + underscore like: `{}_{}`", &interned_name[..split], &interned_name[split..] ), diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index ee55ea882b0..67d39333ff9 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet}; +use utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index e67c1f4d148..62760888933 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,4 +1,4 @@ -use rustc::hir::{Expr, ExprMethodCall, ExprLit}; +use rustc::hir::{Expr, ExprLit, ExprMethodCall}; use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; @@ -67,11 +67,18 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp // Only proceed if this is a call on some object of type std::fs::OpenOptions if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { - let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned { node: LitKind::Bool(lit), .. } = **span { - if lit { Argument::True } else { Argument::False } + if let Spanned { + node: LitKind::Bool(lit), + .. + } = **span + { + if lit { + Argument::True + } else { + Argument::False + } } else { return; // The function is called with a literal // which is not a boolean literal. This is theoretically diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 70ee7de7b4d..a050873187d 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, resolve_node, paths, span_lint}; +use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index f5a6833b4b0..e06c571b6f6 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: @@ -89,9 +89,7 @@ impl EarlyLintPass for Precedence { if let Some(slf) = args.first() { if let ExprKind::Lit(ref lit) = slf.node { match lit.node { - LitKind::Int(..) | - LitKind::Float(..) | - LitKind::FloatUnsuffixed(..) => { + LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { span_lint_and_sugg( cx, PRECEDENCE, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 982b46e20d3..9aca7543396 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -1,8 +1,8 @@ use rustc::hir::*; -use rustc::hir::map::Node::{NodeItem, NodeImplItem}; +use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::lint::*; use utils::paths; -use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path}; +use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use format::get_argument_fmtstr_parts; /// **What it does:** This lint warns when you using `print!()` with a format diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a21142a257d..f12ec039f73 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -128,11 +128,13 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { let fn_ty = sig.skip_binder(); for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) { - if let ty::TyRef(_, - ty::TypeAndMut { - ty, - mutbl: MutImmutable, - }) = ty.sty + if let ty::TyRef( + _, + ty::TypeAndMut { + ty, + mutbl: MutImmutable, + }, + ) = ty.sty { if match_type(cx, ty, &paths::VEC) { span_lint( @@ -140,7 +142,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { PTR_ARG, arg.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`", + with non-Vec-based slices. Consider changing the type to `&[...]`", ); } else if match_type(cx, ty, &paths::STRING) { span_lint( @@ -148,7 +150,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { PTR_ARG, arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`", + Consider changing the type to `&str`", ); } } @@ -157,10 +159,10 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { if let FunctionRetTy::Return(ref ty) = decl.output { if let Some((out, MutMutable, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; - for (_, ref mutbl, ref argspan) in - decl.inputs.iter().filter_map(|ty| get_rptr_lm(ty)).filter( - |&(lt, _, _)| lt.name == out.name, - ) + for (_, ref mutbl, ref argspan) in decl.inputs + .iter() + .filter_map(|ty| get_rptr_lm(ty)) + .filter(|&(lt, _, _)| lt.name == out.name) { if *mutbl == MutMutable { return; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index aa43fb6b620..44c909810ea 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use utils::{is_integer_literal, paths, snippet, span_lint}; -use utils::{higher, implements_trait, get_trait_def_id}; +use utils::{get_trait_def_id, higher, implements_trait}; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { - use consts::{Constant, constant}; + use consts::{constant, Constant}; use rustc_const_math::ConstInt::Usize; if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) { if us.as_u64(cx.sess().target.uint_type) == 0 { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index a8360c71f91..fce3c6ad285 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,6 +1,6 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::*; -use utils::{span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. /// diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index c1011168c52..8b5dedfccd4 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -7,9 +7,9 @@ use rustc::ty::subst::Substs; use std::collections::HashSet; use std::error::Error; use syntax::ast::{LitKind, NodeId}; -use syntax::codemap::{Span, BytePos}; +use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; -use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -161,27 +161,19 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { match *s { Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), Expr::Literal { .. } => Some("consider using `str::contains`"), - Expr::Concat(ref exprs) => { - match exprs.len() { - 2 => { - match (&exprs[0], &exprs[1]) { - (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), - (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), - _ => None, - } - }, - 3 => { - if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = - (&exprs[0], &exprs[1], &exprs[2]) - { - Some("consider using `==` on `str`s") - } else { - None - } - }, + Expr::Concat(ref exprs) => match exprs.len() { + 2 => match (&exprs[0], &exprs[1]) { + (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), + (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), + (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), _ => None, - } + }, + 3 => if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { + Some("consider using `==` on `str`s") + } else { + None + }, + _ => None, }, _ => None, } @@ -205,16 +197,14 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { if let LitKind::Str(ref r, _) = lit.node { let r = &r.as_str(); match builder.parse(r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl), - ); - } + Ok(r) => if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); }, Err(e) => { span_lint( @@ -228,16 +218,14 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { } } else if let Some(r) = const_str(cx, expr) { match builder.parse(&r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl), - ); - } + Ok(r) => if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); }, Err(e) => { span_lint( diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index b9fcb62de73..0884ebbf5cf 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, in_macro, in_external_macro}; +use utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for return statements at the end of a block. /// @@ -50,8 +50,7 @@ impl ReturnPass { fn check_block_return(&mut self, cx: &EarlyContext, block: &ast::Block) { if let Some(stmt) = block.stmts.last() { match stmt.node { - ast::StmtKind::Expr(ref expr) | - ast::StmtKind::Semi(ref expr) => { + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { self.check_final_expr(cx, expr, Some(stmt.span)); }, _ => (), @@ -81,10 +80,8 @@ impl ReturnPass { self.check_final_expr(cx, elsexpr, None); }, // a match expr, check all arms - ast::ExprKind::Match(_, ref arms) => { - for arm in arms { - self.check_final_expr(cx, &arm.body, Some(arm.body.span)); - } + ast::ExprKind::Match(_, ref arms) => for arm in arms { + self.check_final_expr(cx, &arm.body, Some(arm.body.span)); }, _ => (), } @@ -140,8 +137,7 @@ impl LintPass for ReturnPass { impl EarlyLintPass for ReturnPass { fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { match kind { - FnKind::ItemFn(.., block) | - FnKind::Method(.., block) => self.check_block_return(cx, block), + FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), FnKind::Closure(body) => self.check_final_expr(cx, body, Some(body.span)), } } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 4feaaa19287..0ea24a33393 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint, get_trait_def_id, paths}; +use utils::{get_trait_def_id, paths, span_lint}; /// **What it does:** Checks for mis-uses of the serde API. /// diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 5649847b334..f6461b2d438 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; use syntax::codemap::Span; -use utils::{contains_name, higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats}; +use utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, span_lint_and_then}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. @@ -111,8 +111,7 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding for stmt in &block.stmts { match stmt.node { StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => check_expr(cx, e, bindings), + StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), } } if let Some(ref o) = block.expr { @@ -185,54 +184,49 @@ fn check_pat<'a, 'tcx>( check_pat(cx, p, init, span, bindings); } }, - PatKind::Struct(_, ref pfields, _) => { - if let Some(init_struct) = init { - if let ExprStruct(_, ref efields, _) = init_struct.node { - for field in pfields { - let name = field.node.name; - let efield = efields.iter().find(|f| f.name.node == name).map( - |f| &*f.expr, - ); - check_pat(cx, &field.node.pat, efield, span, bindings); - } - } else { - for field in pfields { - check_pat(cx, &field.node.pat, init, span, bindings); - } + PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init { + if let ExprStruct(_, ref efields, _) = init_struct.node { + for field in pfields { + let name = field.node.name; + let efield = efields + .iter() + .find(|f| f.name.node == name) + .map(|f| &*f.expr); + check_pat(cx, &field.node.pat, efield, span, bindings); } } else { for field in pfields { - check_pat(cx, &field.node.pat, None, span, bindings); + check_pat(cx, &field.node.pat, init, span, bindings); } } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, None, span, bindings); + } }, - PatKind::Tuple(ref inner, _) => { - if let Some(init_tup) = init { - if let ExprTup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, Some(&tup[i]), p.span, bindings); - } - } else { - for p in inner { - check_pat(cx, p, init, span, bindings); - } + PatKind::Tuple(ref inner, _) => if let Some(init_tup) = init { + if let ExprTup(ref tup) = init_tup.node { + for (i, p) in inner.iter().enumerate() { + check_pat(cx, p, Some(&tup[i]), p.span, bindings); } } else { for p in inner { - check_pat(cx, p, None, span, bindings); + check_pat(cx, p, init, span, bindings); } } + } else { + for p in inner { + check_pat(cx, p, None, span, bindings); + } }, - PatKind::Box(ref inner) => { - if let Some(initp) = init { - if let ExprBox(ref inner_init) = initp.node { - check_pat(cx, inner, Some(&**inner_init), span, bindings); - } else { - check_pat(cx, inner, init, span, bindings); - } + PatKind::Box(ref inner) => if let Some(initp) = init { + if let ExprBox(ref inner_init) = initp.node { + check_pat(cx, inner, Some(&**inner_init), span, bindings); } else { check_pat(cx, inner, init, span, bindings); } + } else { + check_pat(cx, inner, init, span, bindings); }, PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), // PatVec(Vec>, Option>, Vec>), @@ -292,13 +286,14 @@ fn lint_shadow<'a, 'tcx: 'a>( }, ); } - } else { - span_lint_and_then(cx, - SHADOW_UNRELATED, - span, - &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), - |db| { db.span_note(prev_span, "previous binding is here"); }); + span_lint_and_then( + cx, + SHADOW_UNRELATED, + span, + &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), + |db| { db.span_note(prev_span, "previous binding is here"); }, + ); } } @@ -307,19 +302,14 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: return; } match expr.node { - ExprUnary(_, ref e) | - ExprField(ref e, _) | - ExprTupField(ref e, _) | - ExprAddrOf(_, ref e) | - ExprBox(ref e) => check_expr(cx, e, bindings), - ExprBlock(ref block) | - ExprLoop(ref block, _, _) => check_block(cx, block, bindings), + ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { + check_expr(cx, e, bindings) + }, + ExprBlock(ref block) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), // ExprCall // ExprMethodCall - ExprArray(ref v) | ExprTup(ref v) => { - for e in v { - check_expr(cx, e, bindings) - } + ExprArray(ref v) | ExprTup(ref v) => for e in v { + check_expr(cx, e, bindings) }, ExprIf(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); @@ -358,12 +348,9 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V check_ty(cx, fty, bindings); check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings); }, - TyPtr(MutTy { ty: ref mty, .. }) | - TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => { - for t in tup { - check_ty(cx, t, bindings) - } + TyPtr(MutTy { ty: ref mty, .. }) | TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyTup(ref tup) => for t in tup { + check_ty(cx, t, bindings) }, TyTypeof(body_id) => check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings), _ => (), @@ -372,14 +359,13 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { - ExprBox(ref inner) | - ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), + ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => { block.stmts.is_empty() && - block.expr.as_ref().map_or( - false, - |e| is_self_shadow(name, e), - ) + block + .expr + .as_ref() + .map_or(false, |e| is_self_shadow(name, e)) }, ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path), diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs index ecb2c9c3162..b8cc6873adc 100644 --- a/clippy_lints/src/should_assert_eq.rs +++ b/clippy_lints/src/should_assert_eq.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{is_direct_expn_of, is_expn_of, implements_trait, span_lint}; +use utils::{implements_trait, is_direct_expn_of, is_expn_of, span_lint}; /// **What it does:** Checks for `assert!(x == y)` or `assert!(x != y)` which /// can be better written diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 587ad38c9e5..0365322ef68 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Spanned; use utils::SpanlessEq; -use utils::{match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty, get_parent_expr, is_allowed}; +use utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. Consider using \ - `String::push_str()` instead", + `String::push_str()` instead", ); } } @@ -124,10 +124,10 @@ fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { block.stmts.is_empty() && - block.expr.as_ref().map_or( - false, - |expr| is_add(cx, expr, target), - ) + block + .expr + .as_ref() + .map_or(false, |expr| is_add(cx, expr, target)) }, _ => false, } @@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use std::ascii::AsciiExt; use syntax::ast::LitKind; - use utils::{snippet, in_macro}; + use utils::{in_macro, snippet}; if let ExprMethodCall(ref path, _, ref args) = e.node { if path.name == "as_bytes" { diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 1669b2d6557..877321255c1 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -41,11 +41,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { - ExprField(ref base, _) | - ExprTupField(ref base, _) => { - if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - } + ExprField(ref base, _) | ExprTupField(ref base, _) => if is_temporary(base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); }, _ => (), } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 83e212c36d1..a590bf744bf 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; -use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment}; +use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::sugg; /// **What it does:** Checks for transmutes that can't ever be correct on any @@ -95,103 +95,88 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { let to_ty = cx.tables.expr_ty(e); match (&from_ty.sty, &to_ty.sty) { - _ if from_ty == to_ty => { - span_lint( - cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty), - ) - }, - (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from a reference to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = if ptr_ty == rty { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) - }; + _ if from_ty == to_ty => span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ), + (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = if ptr_ty == rty { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) + }; - db.span_suggestion(e.span, "try", sugg.to_string()); - }, - ) - }, - (&ty::TyInt(_), &ty::TyRawPtr(_)) | - (&ty::TyUint(_), &ty::TyRawPtr(_)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); - }, - ) - }, + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ), + (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + }, + ), (&ty::TyFloat(_), &ty::TyRef(..)) | (&ty::TyFloat(_), &ty::TyRawPtr(_)) | (&ty::TyChar, &ty::TyRef(..)) | - (&ty::TyChar, &ty::TyRawPtr(_)) => { - span_lint( - cx, - WRONG_TRANSMUTE, - e.span, - &format!("transmute from a `{}` to a pointer", from_ty), - ) - }, - (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => { - span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!( - "transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty - ), - ) - }, - (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => { - span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), - ) - }, - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => { - span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_REF, - e.span, - &format!( - "transmute from a pointer type (`{}`) to a reference type \ - (`{}`)", - from_ty, - to_ty - ), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), + ), + (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty + ), + ), + (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), + ), + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!( + "transmute from a pointer type (`{}`) to a reference type \ + (`{}`)", + from_ty, + to_ty + ), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - let arg = if from_pty.ty == to_rty.ty { - arg - } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) - }; + let arg = if from_pty.ty == to_rty.ty { + arg + } else { + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) + }; - db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); - }, - ) - }, + db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); + }, + ), _ => return, }; } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 05a498ff262..78e06fa80dd 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,16 +1,16 @@ use reexport::*; use rustc::hir; use rustc::hir::*; -use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use std::cmp::Ordering; -use syntax::ast::{IntTy, UintTy, FloatTy}; +use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; -use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, opt_def_id, last_path_segment, type_size, match_path}; +use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, + opt_def_id, snippet, span_help_and_lint, span_lint, span_lint_and_sugg, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -114,8 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { match item.node { - TraitItemKind::Const(ref ty, _) | - TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false), + TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false), TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl), _ => (), } @@ -182,20 +181,18 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { match *qpath { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); - for ty in p.segments.iter().flat_map( - |seg| seg.parameters.types.iter(), - ) + for ty in p.segments + .iter() + .flat_map(|seg| seg.parameters.types.iter()) { check_ty(cx, ty, is_local); } }, - QPath::Resolved(None, ref p) => { - for ty in p.segments.iter().flat_map( - |seg| seg.parameters.types.iter(), - ) - { - check_ty(cx, ty, is_local); - } + QPath::Resolved(None, ref p) => for ty in p.segments + .iter() + .flat_map(|seg| seg.parameters.types.iter()) + { + check_ty(cx, ty, is_local); }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); @@ -248,13 +245,9 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } }, // recurse - TySlice(ref ty) | - TyArray(ref ty, _) | - TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), - TyTup(ref tys) => { - for ty in tys { - check_ty(cx, ty, is_local); - } + TySlice(ref ty) | TyArray(ref ty, _) | TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), + TyTup(ref tys) => for ty in tys { + check_ty(cx, ty, is_local); }, _ => {}, } @@ -529,25 +522,21 @@ declare_lint! { /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { match typ.sty { - ty::TyInt(i) => { - match i { - IntTy::Is => tcx.data_layout.pointer_size.bits(), - IntTy::I8 => 8, - IntTy::I16 => 16, - IntTy::I32 => 32, - IntTy::I64 => 64, - IntTy::I128 => 128, - } + ty::TyInt(i) => match i { + IntTy::Is => tcx.data_layout.pointer_size.bits(), + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, }, - ty::TyUint(i) => { - match i { - UintTy::Us => tcx.data_layout.pointer_size.bits(), - UintTy::U8 => 8, - UintTy::U16 => 16, - UintTy::U32 => 32, - UintTy::U64 => 64, - UintTy::U128 => 128, - } + ty::TyUint(i) => match i { + UintTy::Us => tcx.data_layout.pointer_size.bits(), + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, }, _ => 0, } @@ -555,8 +544,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { fn is_isize_or_usize(typ: Ty) -> bool { match typ.sty { - ty::TyInt(IntTy::Is) | - ty::TyUint(UintTy::Us) => true, + ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, _ => false, } } @@ -578,7 +566,7 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t expr.span, &format!( "casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ - is only {4} bits wide)", + is only {4} bits wide)", cast_from, if cast_to_f64 { "f64" } else { "f32" }, if arch_dependent { @@ -617,38 +605,32 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => { - ( - to_nbits < from_nbits, - ArchSuffix::None, - to_nbits == from_nbits && cast_unsigned_to_signed, - ArchSuffix::None, - ) - }, - (true, false) => { - ( - to_nbits <= 32, - if to_nbits == 32 { - ArchSuffix::_64 - } else { - ArchSuffix::None - }, - to_nbits <= 32 && cast_unsigned_to_signed, - ArchSuffix::_32, - ) - }, - (false, true) => { - ( - from_nbits == 64, - ArchSuffix::_32, - cast_unsigned_to_signed, - if from_nbits == 64 { - ArchSuffix::_64 - } else { - ArchSuffix::_32 - }, - ) - }, + (true, true) | (false, false) => ( + to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None, + ), + (true, false) => ( + to_nbits <= 32, + if to_nbits == 32 { + ArchSuffix::_64 + } else { + ArchSuffix::None + }, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32, + ), + (false, true) => ( + from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 { + ArchSuffix::_64 + } else { + ArchSuffix::_32 + }, + ), }; if span_truncation { span_lint( @@ -690,8 +672,7 @@ fn check_lossless(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_ let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); - if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && - !cast_signed_to_unsigned + if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && !cast_signed_to_unsigned { span_lossless_lint(cx, expr, op, cast_from, cast_to); } @@ -715,19 +696,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if let ExprCast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); if let ExprLit(ref lit) = ex.node { - use syntax::ast::{LitKind, LitIntType}; + use syntax::ast::{LitIntType, LitKind}; match lit.node { - LitKind::Int(_, LitIntType::Unsuffixed) | - LitKind::FloatUnsuffixed(_) => {}, - _ => { - if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { - span_lint( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), - ); - } + LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, + _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { + span_lint( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), + ); }, } } @@ -776,8 +754,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { check_lossless(cx, expr, ex, cast_from, cast_to); }, (false, false) => { - if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = - (&cast_from.sty, &cast_to.sty) + if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { span_lint( cx, @@ -786,8 +763,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { "casting f64 to f32 may truncate the value", ); } - if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = - (&cast_from.sty, &cast_to.sty) + if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) { span_lossless_lint(cx, expr, ex, cast_from, cast_to); } @@ -823,7 +799,9 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { - Self { threshold: threshold } + Self { + threshold: threshold, + } } } @@ -853,8 +831,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { match item.node { - ItemStatic(ref ty, _, _) | - ItemConst(ref ty, _) => self.check_type(cx, ty), + ItemStatic(ref ty, _, _) | ItemConst(ref ty, _) => self.check_type(cx, ty), // functions, enums, structs, impls and traits are covered _ => (), } @@ -862,8 +839,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { match item.node { - TraitItemKind::Const(ref ty, _) | - TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), + TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), TraitItemKind::Method(MethodSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), @@ -872,8 +848,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { match item.node { - ImplItemKind::Const(ref ty, _) | - ImplItemKind::Type(ref ty) => self.check_type(cx, ty), + ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => self.check_type(cx, ty), // methods are covered by check_fn _ => (), } @@ -938,9 +913,9 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyBareFn(..) => (50 * self.nest, 1), TyTraitObject(ref param_bounds, _) => { - let has_lifetime_parameters = param_bounds.iter().any( - |bound| !bound.bound_lifetimes.is_empty(), - ); + let has_lifetime_parameters = param_bounds + .iter() + .any(|bound| !bound.bound_lifetimes.is_empty()); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) @@ -1101,7 +1076,7 @@ fn detect_absurd_comparison<'a>( Rel::Le => { match (lx, rx) { (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x - (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x + (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max _ => return None, @@ -1187,14 +1162,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { let conclusion = match result { AlwaysFalse => "this comparison is always false".to_owned(), AlwaysTrue => "this comparison is always true".to_owned(), - InequalityImpossible => { - format!( - "the case where the two sides are not equal never occurs, consider using {} == {} \ - instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs") - ) - }, + InequalityImpossible => format!( + "the case where the two sides are not equal never occurs, consider using {} == {} \ + instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs") + ), }; let help = format!( @@ -1264,9 +1237,8 @@ impl FullInt { impl PartialEq for FullInt { fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other).expect( - "partial_cmp only returns Some(_)", - ) == Ordering::Equal + self.partial_cmp(other) + .expect("partial_cmp only returns Some(_)") == Ordering::Equal } } @@ -1282,9 +1254,8 @@ impl PartialOrd for FullInt { } impl Ord for FullInt { fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).expect( - "partial_cmp for FullInt can never return None", - ) + self.partial_cmp(other) + .expect("partial_cmp for FullInt can never return None") } } @@ -1301,44 +1272,40 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( return None; } match pre_cast_ty.sty { - ty::TyInt(int_ty) => { - Some(match int_ty { - IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), - IntTy::I16 => ( - FullInt::S(i128::from(i16::min_value())), - FullInt::S(i128::from(i16::max_value())), - ), - IntTy::I32 => ( - FullInt::S(i128::from(i32::min_value())), - FullInt::S(i128::from(i32::max_value())), - ), - IntTy::I64 => ( - FullInt::S(i128::from(i64::min_value())), - FullInt::S(i128::from(i64::max_value())), - ), - IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), - IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), - }) - }, - ty::TyUint(uint_ty) => { - Some(match uint_ty { - UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), - UintTy::U16 => ( - FullInt::U(u128::from(u16::min_value())), - FullInt::U(u128::from(u16::max_value())), - ), - UintTy::U32 => ( - FullInt::U(u128::from(u32::min_value())), - FullInt::U(u128::from(u32::max_value())), - ), - UintTy::U64 => ( - FullInt::U(u128::from(u64::min_value())), - FullInt::U(u128::from(u64::max_value())), - ), - UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), - UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), - }) - }, + ty::TyInt(int_ty) => Some(match int_ty { + IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), + IntTy::I16 => ( + FullInt::S(i128::from(i16::min_value())), + FullInt::S(i128::from(i16::max_value())), + ), + IntTy::I32 => ( + FullInt::S(i128::from(i32::min_value())), + FullInt::S(i128::from(i32::max_value())), + ), + IntTy::I64 => ( + FullInt::S(i128::from(i64::min_value())), + FullInt::S(i128::from(i64::max_value())), + ), + IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), + IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), + }), + ty::TyUint(uint_ty) => Some(match uint_ty { + UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), + UintTy::U16 => ( + FullInt::U(u128::from(u16::min_value())), + FullInt::U(u128::from(u16::max_value())), + ), + UintTy::U32 => ( + FullInt::U(u128::from(u32::min_value())), + FullInt::U(u128::from(u32::max_value())), + ), + UintTy::U64 => ( + FullInt::U(u128::from(u64::min_value())), + FullInt::U(u128::from(u64::max_value())), + ), + UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), + UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), + }), _ => None, } } else { @@ -1355,15 +1322,13 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) { - Ok(val) => { - if let Integral(const_int) = val { - match const_int.int_type() { - IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), - IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), - } - } else { - None + Ok(val) => if let Integral(const_int) = val { + match const_int.int_type() { + IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), + IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), } + } else { + None }, Err(_) => None, } @@ -1402,42 +1367,32 @@ fn upcast_comparison_bounds_err( err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } - { + Rel::Lt => if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + }, + Rel::Le => if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { err_upcast_comparison(cx, span, lhs, true) } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } - { + Rel::Lt => if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + }, + Rel::Le => if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { err_upcast_comparison(cx, span, lhs, false) } } @@ -1447,7 +1402,6 @@ fn upcast_comparison_bounds_err( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { val diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 14d6323de47..c045c870810 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; -use utils::{snippet, span_help_and_lint, is_allowed}; +use utils::{is_allowed, snippet, span_help_and_lint}; /// **What it does:** Checks for the Unicode zero-width space in the code. /// diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 036e6f0f0e6..1c9bf70429d 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -48,13 +48,11 @@ impl EarlyLintPass for UnsafeNameRemoval { &item.span, ); }, - ViewPath_::ViewPathList(_, ref path_list_items) => { - for path_list_item in path_list_items.iter() { - let plid = path_list_item.node; - if let Some(rename) = plid.rename { - unsafe_to_safe_check(plid.name, rename, cx, &item.span); - }; - } + ViewPath_::ViewPathList(_, ref path_list_items) => for path_list_item in path_list_items.iter() { + let plid = path_list_item.node; + if let Some(rename) = plid.rename { + unsafe_to_safe_check(plid.name, rename, cx, &item.span); + }; }, ViewPath_::ViewPathGlob(_) => {}, } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1ac775ce7c1..1af63c56107 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use utils::{span_lint, match_qpath, match_trait_method, is_try, paths}; +use utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; /// **What it does:** Checks for unused written/read amount. /// @@ -40,8 +40,7 @@ impl LintPass for UnusedIoAmount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { - hir::StmtSemi(ref expr, _) | - hir::StmtExpr(ref expr, _) => &**expr, + hir::StmtSemi(ref expr, _) | hir::StmtExpr(ref expr, _) => &**expr, _ => return, }; @@ -58,13 +57,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } }, - hir::ExprMethodCall(ref path, _, ref args) => { - match &*path.name.as_str() { - "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { - check_method_call(cx, &args[0], expr); - }, - _ => (), - } + hir::ExprMethodCall(ref path, _, ref args) => match &*path.name.as_str() { + "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { + check_method_call(cx, &args[0], expr); + }, + _ => (), }, _ => (), diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 8a8afe8a377..6f91b873a48 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use std::collections::HashMap; use syntax::ast; use syntax::codemap::Span; @@ -69,14 +69,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBreak(destination, _) | - hir::ExprAgain(destination) => { - if let Some(label) = destination.ident { - self.labels.remove(&label.node.name.as_str()); - } + hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.ident { + self.labels.remove(&label.node.name.as_str()); }, - hir::ExprLoop(_, Some(label), _) | - hir::ExprWhile(_, _, Some(label)) => { + hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { self.labels.insert(label.node.as_str(), expr.span); }, _ => (), diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 9f75ed2717b..bb5f6075d0d 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ -use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap}; -use utils::{span_lint_and_then, in_macro}; +use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; +use utils::{in_macro, span_lint_and_then}; use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfType; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index dfac7366553..fafb6d12d1f 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -5,9 +5,9 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::{Expr, QPath, Expr_}; -use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use syntax::ast::{self, Attribute, NodeId, LitKind, DUMMY_NODE_ID}; +use rustc::hir::{Expr, Expr_, QPath}; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::Span; use std::collections::HashMap; @@ -386,15 +386,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Again(ref {}) = {},", destination_pat, current); // FIXME: implement label printing }, - Expr_::ExprRet(ref opt_value) => { - if let Some(ref value) = *opt_value { - let value_pat = self.next("value"); - println!("Ret(Some(ref {})) = {},", value_pat, current); - self.current = value_pat; - self.visit_expr(value); - } else { - println!("Ret(None) = {},", current); - } + Expr_::ExprRet(ref opt_value) => if let Some(ref value) = *opt_value { + let value_pat = self.next("value"); + println!("Ret(Some(ref {})) = {},", value_pat, current); + self.current = value_pat; + self.visit_expr(value); + } else { + println!("Ret(None) = {},", current); }, Expr_::ExprInlineAsm(_, ref _input, ref _output) => { println!("InlineAsm(_, ref input, ref output) = {},", current); @@ -445,42 +443,36 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { fn has_attr(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { - attr.check_name("clippy") && - attr.meta_item_list().map_or(false, |list| { - list.len() == 1 && - match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", - ast::NestedMetaItemKind::Literal(_) => false, - } - }) + attr.check_name("clippy") && attr.meta_item_list().map_or(false, |list| { + list.len() == 1 && match list[0].node { + ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", + ast::NestedMetaItemKind::Literal(_) => false, + } + }) }) } fn print_path(path: &QPath, first: &mut bool) { match *path { - QPath::Resolved(_, ref path) => { - for segment in &path.segments { + QPath::Resolved(_, ref path) => for segment in &path.segments { + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.name.as_str()); + }, + QPath::TypeRelative(ref ty, ref segment) => match ty.node { + hir::Ty_::TyPath(ref inner_path) => { + print_path(inner_path, first); if *first { *first = false; } else { print!(", "); } print!("{:?}", segment.name.as_str()); - } - }, - QPath::TypeRelative(ref ty, ref segment) => { - match ty.node { - hir::Ty_::TyPath(ref inner_path) => { - print_path(inner_path, first); - if *first { - *first = false; - } else { - print!(", "); - } - print!("{:?}", segment.name.as_str()); - }, - ref other => print!("/* unimplemented: {:?}*/", other), - } + }, + ref other => print!("/* unimplemented: {:?}*/", other), }, } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index ad9e7e20176..7251538c09a 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -15,14 +15,13 @@ pub fn file_from_args( for arg in args.iter().filter_map(|a| a.meta_item()) { if arg.name() == "conf_file" { return match arg.node { - ast::MetaItemKind::Word | - ast::MetaItemKind::List(_) => Err(("`conf_file` must be a named value", arg.span)), - ast::MetaItemKind::NameValue(ref value) => { - if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.to_string().into())) - } else { - Err(("`conf_file` value must be a string", value.span)) - } + ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { + Err(("`conf_file` must be a named value", arg.span)) + }, + ast::MetaItemKind::NameValue(ref value) => if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.to_string().into())) + } else { + Err(("`conf_file` value must be a string", value.span)) }, }; } @@ -45,7 +44,7 @@ pub enum Error { /// The expected type. &'static str, /// The type we got instead. - &'static str + &'static str, ), /// There is an unknown key is the file. UnknownKey(String), @@ -191,10 +190,8 @@ pub fn lookup_conf_file() -> io::Result> { Ok(ref md) if md.is_file() => return Ok(Some(config_file)), // Return the error if it's something other than `NotFound`; otherwise we didn't // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != io::ErrorKind::NotFound { - return Err(e); - } + Err(e) => if e.kind() != io::ErrorKind::NotFound { + return Err(e); }, _ => (), } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d9a454aaf7e..09e40aea80d 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_qpath, match_def_path, resolve_node, paths}; +use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -73,42 +73,40 @@ pub fn range(expr: &hir::Expr) -> Option { None } }, - hir::ExprStruct(ref path, ref fields, None) => { - if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { - Some(Range { - start: get_field("start", fields), - end: None, - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { - Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), - limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { - Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || - match_qpath(path, &paths::RANGE_TO_INCLUSIVE) - { - Some(Range { - start: None, - end: get_field("end", fields), - limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { - Some(Range { - start: None, - end: get_field("end", fields), - limits: ast::RangeLimits::HalfOpen, - }) - } else { - None - } + hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) || + match_qpath(path, &paths::RANGE_FROM) + { + Some(Range { + start: get_field("start", fields), + end: None, + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else { + None }, _ => None, } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 0b3f409adf4..2d3d5874d82 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -46,8 +46,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { false } }, - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => { + self.eq_expr(l, r) + }, _ => false, } } @@ -107,11 +108,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { - ls == rs && self.eq_expr(le, re) && - over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) + ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) }, (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) @@ -257,9 +257,8 @@ fn both(l: &Option, r: &Option, mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool, { - l.as_ref().map_or_else(|| r.is_none(), |x| { - r.as_ref().map_or(false, |y| eq_fn(x, y)) - }) + l.as_ref() + .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) } /// Check if two slices are equal as per `eq_fn`. diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 315f4987071..cdc8ce509b4 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -54,12 +54,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => { - println!( - "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) - ) - }, + hir::Visibility::Restricted { ref path, .. } => println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } if item.defaultness.is_default() { @@ -125,8 +123,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match stmt.node { hir::StmtDecl(ref decl, _) => print_decl(cx, decl), - hir::StmtExpr(ref e, _) | - hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), + hir::StmtExpr(ref e, _) | hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), } } // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx @@ -355,12 +352,10 @@ fn print_item(cx: &LateContext, item: &hir::Item) { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => { - println!( - "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) - ) - }, + hir::Visibility::Restricted { ref path, .. } => println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } match item.node { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index a2832ef7af2..a35b034d791 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,11 +1,11 @@ use rustc::lint::*; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; -use utils::{paths, match_qpath, span_lint}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use utils::{match_qpath, paths, span_lint}; use syntax::symbol::InternedString; -use syntax::ast::{Name, NodeId, ItemKind, Crate as AstCrate}; +use syntax::ast::{Crate as AstCrate, ItemKind, Name, NodeId}; use syntax::codemap::Span; -use std::collections::{HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; /// **What it does:** Checks for various things we like to keep tidy in clippy. @@ -63,14 +63,17 @@ impl LintPass for Clippy { impl EarlyLintPass for Clippy { fn check_crate(&mut self, cx: &EarlyContext, krate: &AstCrate) { - if let Some(utils) = krate.module.items.iter().find( - |item| item.ident.name == "utils", - ) + if let Some(utils) = krate + .module + .items + .iter() + .find(|item| item.ident.name == "utils") { if let ItemKind::Mod(ref utils_mod) = utils.node { - if let Some(paths) = utils_mod.items.iter().find( - |item| item.ident.name == "paths", - ) + if let Some(paths) = utils_mod + .items + .iter() + .find(|item| item.ident.name == "paths") { if let ItemKind::Mod(ref paths_mod) = paths.node { let mut last_name: Option = None; @@ -83,7 +86,7 @@ impl EarlyLintPass for Clippy { CLIPPY_LINTS_INTERNAL, item.span, "this constant should be before the previous constant due to lexical \ - ordering", + ordering", ); } } @@ -157,11 +160,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { - if let TyRptr(ref lt, - MutTy { - ty: ref inner, - mutbl: MutImmutable, - }) = ty.node + if let TyRptr( + ref lt, + MutTy { + ty: ref inner, + mutbl: MutImmutable, + }, + ) = ty.node { if lt.is_elided() { return false; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8828a32512b..29fddeaa052 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -5,10 +5,10 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::Def; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::map::Node; -use rustc::lint::{LintContext, Level, LateContext, Lint}; +use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, TyCtxt, Ty}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::transform::MirSource; use rustc_errors; use std::borrow::Cow; @@ -104,18 +104,16 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { let parent_id = cx.tcx.hir.get_parent(id); match MirSource::from_node(cx.tcx, parent_id) { - MirSource::GeneratorDrop(_) | - MirSource::Fn(_) => false, - MirSource::Const(_) | - MirSource::Static(..) | - MirSource::Promoted(..) => true, + MirSource::GeneratorDrop(_) | MirSource::Fn(_) => false, + MirSource::Const(_) | MirSource::Static(..) | MirSource::Promoted(..) => true, } } /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().map_or(false, |info| { - match info.callee.format {// don't treat range expressions desugared to structs as "in_macro" + match info.callee.format { + // don't treat range expressions desugared to structs as "in_macro" ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, _ => true, } @@ -138,18 +136,18 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or( - true, - |code| { - !code.starts_with("macro_rules") - }, - ) + cx.sess() + .codemap() + .span_to_snippet(span) + .ok() + .map_or(true, |code| !code.starts_with("macro_rules")) }) } - span.ctxt().outer().expn_info().map_or(false, |info| { - in_macro_ext(cx, &info) - }) + span.ctxt() + .outer() + .expn_info() + .map_or(false, |info| in_macro_ext(cx, &info)) } /// Check if a `DefId`'s path matches the given absolute type path usage. @@ -183,9 +181,10 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { tcx.push_item_path(&mut apb, def_id); apb.names.len() == path.len() && - apb.names.into_iter().zip(path.iter()).all( - |(a, &b)| *a == *b, - ) + apb.names + .into_iter() + .zip(path.iter()) + .all(|(a, &b)| *a == *b) } /// Check if type is struct, enum or union type with given def path. @@ -220,11 +219,9 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool pub fn last_path_segment(path: &QPath) -> &PathSegment { match *path { - QPath::Resolved(_, ref path) => { - path.segments.last().expect( - "A path must have at least one segment", - ) - }, + QPath::Resolved(_, ref path) => path.segments + .last() + .expect("A path must have at least one segment"), QPath::TypeRelative(_, ref seg) => seg, } } @@ -246,22 +243,22 @@ pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> { pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { match *path { QPath::Resolved(_, ref path) => match_path(path, segments), - QPath::TypeRelative(ref ty, ref segment) => { - match ty.node { - TyPath(ref inner_path) => { - !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && - segment.name == segments[segments.len() - 1] - }, - _ => false, - } + QPath::TypeRelative(ref ty, ref segment) => match ty.node { + TyPath(ref inner_path) => { + !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && + segment.name == segments[segments.len() - 1] + }, + _ => false, }, } } pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.name == *b, - ) + path.segments + .iter() + .rev() + .zip(segments.iter().rev()) + .all(|(a, b)| a.name == *b) } /// Match a `Path` against a slice of segment string literals, e.g. @@ -271,9 +268,11 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { /// match_qpath(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.identifier.name == *b, - ) + path.segments + .iter() + .rev() + .zip(segments.iter().rev()) + .all(|(a, b)| a.identifier.name == *b) } /// Get the definition associated to a path. @@ -281,9 +280,9 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { let cstore = &cx.tcx.sess.cstore; let crates = cstore.crates(); - let krate = crates.iter().find( - |&&krate| cstore.crate_name(krate) == path[0], - ); + let krate = crates + .iter() + .find(|&&krate| cstore.crate_name(krate) == path[0]); if let Some(krate) = krate { let krate = DefId { krate: *krate, @@ -336,14 +335,9 @@ pub fn implements_trait<'a, 'tcx>( ty_params: &[Ty<'tcx>], ) -> bool { let ty = cx.tcx.erase_regions(&ty); - let obligation = cx.tcx.predicate_for_trait_def( - cx.param_env, - traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params, - ); + let obligation = + cx.tcx + .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); cx.tcx.infer_ctxt().enter(|infcx| { traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) }) @@ -522,30 +516,27 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if node_id == parent_id { return None; } - map.find(parent_id).and_then( - |node| if let Node::NodeExpr(parent) = - node - { + map.find(parent_id) + .and_then(|node| if let Node::NodeExpr(parent) = node { Some(parent) } else { None - }, - ) + }) } pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { let map = &cx.tcx.hir; - let enclosing_node = map.get_enclosing_scope(node).and_then(|enclosing_id| { - map.find(enclosing_id) - }); + let enclosing_node = map.get_enclosing_scope(node) + .and_then(|enclosing_id| map.find(enclosing_id)); if let Some(node) = enclosing_node { match node { Node::NodeBlock(block) => Some(block), - Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. }) => { - match cx.tcx.hir.body(eid).value.node { - ExprBlock(ref block) => Some(block), - _ => None, - } + Node::NodeItem(&Item { + node: ItemFn(_, _, _, _, _, eid), + .. + }) => match cx.tcx.hir.body(eid).value.node { + ExprBlock(ref block) => Some(block), + _ => None, }, _ => None, } @@ -704,9 +695,9 @@ impl LimitStack { Self { stack: vec![limit] } } pub fn limit(&self) -> u64 { - *self.stack.last().expect( - "there should always be a value in the stack", - ) + *self.stack + .last() + .expect("there should always be a value in the stack") } pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; @@ -741,9 +732,10 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt().outer().expn_info().map(|ei| { - (ei.callee.name(), ei.call_site) - }); + let span_name_span = span.ctxt() + .outer() + .expn_info() + .map(|ei| (ei.callee.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => return Some(new_span), @@ -763,9 +755,10 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt().outer().expn_info().map(|ei| { - (ei.callee.name(), ei.call_site) - }); + let span_name_span = span.ctxt() + .outer() + .expn_info() + .map(|ei| (ei.callee.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => Some(new_span), @@ -800,7 +793,11 @@ pub fn camel_case_until(s: &str) -> usize { return i; } } - if up { last_i } else { s.len() } + if up { + last_i + } else { + s.len() + } } /// Return index of the last camel-case component of `s`. @@ -844,9 +841,9 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t // <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - cx.tcx.infer_ctxt().enter(|infcx| { - infcx.can_eq(cx.param_env, a, b).is_ok() - }) + cx.tcx + .infer_ctxt() + .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) } /// Return whether the given type is an `unsafe` function. @@ -875,36 +872,28 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { } match pat.node { - PatKind::Binding(..) | - PatKind::Wild => false, - PatKind::Box(ref pat) | - PatKind::Ref(ref pat, _) => is_refutable(cx, pat), - PatKind::Lit(..) | - PatKind::Range(..) => true, + PatKind::Binding(..) | PatKind::Wild => false, + PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), + PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), - PatKind::Struct(ref qpath, ref fields, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) - } - }, - PatKind::TupleStruct(ref qpath, ref pats, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, pats.iter().map(|pat| &**pat)) - } + PatKind::Struct(ref qpath, ref fields, _) => if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) }, - PatKind::Slice(ref head, ref middle, ref tail) => { - are_refutable( - cx, - head.iter().chain(middle).chain(tail.iter()).map( - |pat| &**pat, - ), - ) + PatKind::TupleStruct(ref qpath, ref pats, _) => if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, pats.iter().map(|pat| &**pat)) }, + PatKind::Slice(ref head, ref middle, ref tail) => are_refutable( + cx, + head.iter() + .chain(middle) + .chain(tail.iter()) + .map(|pat| &**pat), + ), } } @@ -1029,9 +1018,9 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - ty.layout(cx.tcx, cx.param_env).ok().map(|layout| { - layout.size(cx.tcx).bytes() - }) + ty.layout(cx.tcx, cx.param_env) + .ok() + .map(|layout| layout.size(cx.tcx).bytes()) } /// Returns true if the lint is allowed in the current context diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4dc2314accb..ec0a351b8b0 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -33,9 +33,7 @@ pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); impl<'a> Display for Sugg<'a> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match *self { - Sugg::NonParen(ref s) | - Sugg::MaybeParen(ref s) | - Sugg::BinOp(_, ref s) => s.fmt(f), + Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) | Sugg::BinOp(_, ref s) => s.fmt(f), } } } @@ -178,12 +176,10 @@ impl<'a> Sugg<'a> { match self { Sugg::NonParen(..) => self, // (x) and (x).y() both don't need additional parens - Sugg::MaybeParen(sugg) => { - if sugg.starts_with('(') && sugg.ends_with(')') { - Sugg::MaybeParen(sugg) - } else { - Sugg::NonParen(format!("({})", sugg).into()) - } + Sugg::MaybeParen(sugg) => if sugg.starts_with('(') && sugg.ends_with(')') { + Sugg::MaybeParen(sugg) + } else { + Sugg::NonParen(format!("({})", sugg).into()) }, Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()), } @@ -273,8 +269,8 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool { other.precedence() < op.precedence() || (other.precedence() == op.precedence() && - ((op != other && associativity(op) != dir) || - (op == other && associativity(op) != Associativity::Both))) || + ((op != other && associativity(op) != dir) || + (op == other && associativity(op) != Associativity::Both))) || is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) } @@ -293,12 +289,24 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { let lhs = ParenHelper::new(lhs_paren, lhs); let rhs = ParenHelper::new(rhs_paren, rhs); let sugg = match op { - AssocOp::Add | AssocOp::BitAnd | AssocOp::BitOr | AssocOp::BitXor | AssocOp::Divide | AssocOp::Equal | - AssocOp::Greater | AssocOp::GreaterEqual | AssocOp::LAnd | AssocOp::LOr | AssocOp::Less | - AssocOp::LessEqual | AssocOp::Modulus | AssocOp::Multiply | AssocOp::NotEqual | AssocOp::ShiftLeft | - AssocOp::ShiftRight | AssocOp::Subtract => { - format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs) - }, + AssocOp::Add | + AssocOp::BitAnd | + AssocOp::BitOr | + AssocOp::BitXor | + AssocOp::Divide | + AssocOp::Equal | + AssocOp::Greater | + AssocOp::GreaterEqual | + AssocOp::LAnd | + AssocOp::LOr | + AssocOp::Less | + AssocOp::LessEqual | + AssocOp::Modulus | + AssocOp::Multiply | + AssocOp::NotEqual | + AssocOp::ShiftLeft | + AssocOp::ShiftRight | + AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), AssocOp::Inplace => format!("in ({}) {}", lhs, rhs), AssocOp::Assign => format!("{} = {}", lhs, rhs), AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), @@ -343,7 +351,16 @@ fn associativity(op: &AssocOp) -> Associativity { match *op { Inplace | Assign | AssignOp(_) => Associativity::Right, Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, - Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight | + Divide | + Equal | + Greater | + GreaterEqual | + Less | + LessEqual | + Modulus | + NotEqual | + ShiftLeft | + ShiftRight | Subtract => Associativity::Left, DotDot | DotDotDot => Associativity::None, } @@ -393,9 +410,8 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { let lo = cx.sess().codemap().lookup_char_pos(span.lo()); - if let Some(line) = lo.file.get_line( - lo.line - 1, /* line numbers in `Loc` are 1-based */ - ) + if let Some(line) = lo.file + .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { // we can mix char and byte positions here because we only consider `[ \t]` diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 95f3c913dac..71f53a3e051 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -72,14 +72,12 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { return; } }, - higher::VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = args[0].span.to(last.span); + higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() { + let span = args[0].span.to(last.span); - format!("&[{}]", snippet(cx, span, "..")).into() - } else { - "&[]".into() - } + format!("&[{}]", snippet(cx, span, "..")).into() + } else { + "&[]".into() }, }; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 888cd339096..5ff9fb9ffd5 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,4 +1,4 @@ -use consts::{Constant, constant_simple, FloatWidth}; +use consts::{constant_simple, Constant, FloatWidth}; use rustc::lint::*; use rustc::hir::*; use utils::span_help_and_lint; diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 4b0c5ea5afd..fda167b69c7 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,13 +1,12 @@ #![feature(plugin_registrar, rustc_private)] -extern crate syntax; -extern crate rustc; extern crate rustc_plugin; +extern crate syntax; use syntax::codemap::Span; use syntax::tokenstream::TokenTree; -use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; -use syntax::ext::build::AstBuilder; // trait for expr_usize +use syntax::ext::base::{ExtCtxt, MacEager, MacResult}; +use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc_plugin::Registry; fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box { diff --git a/src/main.rs b/src/main.rs index 054ceae94e3..89de07115c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,13 +45,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType, ) -> Compilation { - self.default.early_callback( - matches, - sopts, - cfg, - descriptions, - output, - ) + self.default + .early_callback(matches, sopts, cfg, descriptions, output) } fn no_input( &mut self, @@ -62,14 +57,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry, ) -> Option<(Input, Option)> { - self.default.no_input( - matches, - sopts, - cfg, - odir, - ofile, - descriptions, - ) + self.default + .no_input(matches, sopts, cfg, odir, ofile, descriptions) } fn late_callback( &mut self, @@ -79,13 +68,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { odir: &Option, ofile: &Option, ) -> Compilation { - self.default.late_callback( - matches, - sess, - input, - odir, - ofile, - ) + self.default + .late_callback(matches, sess, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { let mut control = self.default.build_controller(sess, matches); @@ -101,7 +85,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { .as_ref() .expect( "at this compilation stage \ - the krate must be parsed", + the krate must be parsed", ) .span, ); @@ -203,13 +187,13 @@ pub fn main() { .skip(2) .find(|val| val.starts_with("--manifest-path=")); - let mut metadata = - if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { - metadata - } else { - let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); - process::exit(101); - }; + let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) + { + metadata + } else { + let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); + process::exit(101); + }; let manifest_path = manifest_path_arg.map(|arg| { Path::new(&arg["--manifest-path=".len()..]) @@ -359,7 +343,6 @@ fn process(old_args: I) -> Result<(), i32> where I: Iterator, { - let mut args = vec!["rustc".to_owned()]; let mut found_dashes = false; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a5d55978d09..8fa0d440ee7 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -29,6 +29,8 @@ fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); - #[cfg(target_os = "windows")] run_mode("ui-windows", "ui"); - #[cfg(not(target_os = "windows"))] run_mode("ui-posix", "ui"); + #[cfg(target_os = "windows")] + run_mode("ui-windows", "ui"); + #[cfg(not(target_os = "windows"))] + run_mode("ui-posix", "ui"); } diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 378d14972aa..aa2c4d03bd5 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -5,7 +5,7 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::env::{var, set_var}; +use std::env::{set_var, var}; use std::path::PathBuf; use test::TestPaths; diff --git a/tests/issue-825.rs b/tests/issue-825.rs index 685715a111c..50de10b936c 100644 --- a/tests/issue-825.rs +++ b/tests/issue-825.rs @@ -1,14 +1,12 @@ #![feature(plugin)] #![plugin(clippy)] - #![allow(warnings)] // this should compile in a reasonable amount of time fn rust_type_id(name: &str) { - if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || - "u32" == &name[..] || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || - "i16" == &name[..] || "i32" == &name[..] || - "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] || + "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] || + "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] { unreachable!(); } diff --git a/tests/matches.rs b/tests/matches.rs index 2f9a61ed768..42d1154bf1a 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -21,13 +21,11 @@ fn test_overlapping() { assert_eq!(None, overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])); assert_eq!( None, - overlapping( - &[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(10, Bound::Included(11)), - ], - ) + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(10, Bound::Included(11)) + ],) ); assert_eq!( Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), @@ -35,12 +33,10 @@ fn test_overlapping() { ); assert_eq!( Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), - overlapping( - &[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(6, Bound::Included(11)), - ], - ) + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(6, Bound::Included(11)) + ],) ); } diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index a669b6f9477..853f64b4698 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,7 +1,8 @@ // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. + extern crate clippy_lints; -use clippy_lints::needless_continue::{erode_from_back, erode_block, erode_from_front}; +use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; #[test] #[cfg_attr(rustfmt, rustfmt_skip)] -- cgit 1.4.1-3-g733a5 From b32631794a413cea7ce29abd9f194fff59f05fa1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Sep 2017 12:53:52 +0200 Subject: Rustfmt for_loop.rs and add false positive tests --- tests/ui/for_loop.rs | 287 ++++++++++++++++++++++++------- tests/ui/for_loop.stderr | 433 +++++++++++++++++++++++++++-------------------- 2 files changed, 468 insertions(+), 252 deletions(-) diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 0dbebcdca2c..b4aee6d8ce2 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -4,14 +4,14 @@ use std::collections::*; use std::rc::Rc; -static STATIC: [usize; 4] = [ 0, 1, 8, 16 ]; -const CONST: [usize; 4] = [ 0, 1, 8, 16 ]; +static STATIC: [usize; 4] = [0, 1, 8, 16]; +const CONST: [usize; 4] = [0, 1, 8, 16]; #[warn(clippy)] fn for_loop_over_option_and_result() { let option = Some(1); let result = option.ok_or("x not found"); - let v = vec![0,1,2]; + let v = vec![0, 1, 2]; // check FOR_LOOP_OVER_OPTION lint for x in option { @@ -27,7 +27,8 @@ fn for_loop_over_option_and_result() { println!("{}", x); } - // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call in the chain + // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call + // in the chain for x in v.iter().next() { println!("{}", x); } @@ -72,7 +73,8 @@ impl Unrelated { } } -#[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop, for_kv_map)] +#[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, + explicit_counter_loop, for_kv_map)] #[warn(unused_collect)] #[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] #[allow(many_single_char_names, unused_variables)] @@ -90,7 +92,9 @@ fn main() { println!("{}", vec[i]); // ok, not the `i` of the for-loop } - for i in 0..vec.len() { let _ = vec[i]; } + for i in 0..vec.len() { + let _ = vec[i]; + } // ICE #746 for j in 0..4 { @@ -104,7 +108,8 @@ fn main() { for i in 0..vec.len() { println!("{} {}", vec[i], i); } - for i in 0..vec.len() { // not an error, indexing more than one variable + for i in 0..vec.len() { + // not an error, indexing more than one variable println!("{} {}", vec[i], vec2[i]); } @@ -156,97 +161,104 @@ fn main() { println!("{}", i); } - for i in 5...5 { // not an error, this is the range with only one element “5” + for i in 5...5 { + // not an error, this is the range with only one element “5” println!("{}", i); } - for i in 0..10 { // not an error, the start index is less than the end index + for i in 0..10 { + // not an error, the start index is less than the end index println!("{}", i); } - for i in -10..0 { // not an error + for i in -10..0 { + // not an error println!("{}", i); } - for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range + for i in (10..0).map(|x| x * 2) { + // not an error, it can't be known what arbitrary methods do to a range println!("{}", i); } // testing that the empty range lint folds constants - for i in 10..5+4 { + for i in 10..5 + 4 { println!("{}", i); } - for i in (5+2)..(3-1) { + for i in (5 + 2)..(3 - 1) { println!("{}", i); } - for i in (5+2)..(8-1) { + for i in (5 + 2)..(8 - 1) { println!("{}", i); } - for i in (2*2)..(2*3) { // no error, 4..6 is fine + for i in (2 * 2)..(2 * 3) { + // no error, 4..6 is fine println!("{}", i); } let x = 42; - for i in x..10 { // no error, not constant-foldable + for i in x..10 { + // no error, not constant-foldable println!("{}", i); } // See #601 - for i in 0..10 { // no error, id_col does not exist outside the loop + for i in 0..10 { + // no error, id_col does not exist outside the loop let mut id_col = vec![0f64; 10]; id_col[i] = 1f64; } - for _v in vec.iter() { } + for _v in vec.iter() {} - for _v in vec.iter_mut() { } + for _v in vec.iter_mut() {} - let out_vec = vec![1,2,3]; - for _v in out_vec.into_iter() { } + let out_vec = vec![1, 2, 3]; + for _v in out_vec.into_iter() {} let array = [1, 2, 3]; for _v in array.into_iter() {} - for _v in &vec { } // these are fine - for _v in &mut vec { } // these are fine + for _v in &vec {} // these are fine + for _v in &mut vec {} // these are fine - for _v in [1, 2, 3].iter() { } + for _v in [1, 2, 3].iter() {} - for _v in (&mut [1, 2, 3]).iter() { } // no error + for _v in (&mut [1, 2, 3]).iter() {} // no error for _v in [0; 32].iter() {} for _v in [0; 33].iter() {} // no error let ll: LinkedList<()> = LinkedList::new(); - for _v in ll.iter() { } + for _v in ll.iter() {} let vd: VecDeque<()> = VecDeque::new(); - for _v in vd.iter() { } + for _v in vd.iter() {} let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in bh.iter() { } + for _v in bh.iter() {} let hm: HashMap<(), ()> = HashMap::new(); - for _v in hm.iter() { } + for _v in hm.iter() {} let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in bt.iter() { } + for _v in bt.iter() {} let hs: HashSet<()> = HashSet::new(); - for _v in hs.iter() { } + for _v in hs.iter() {} let bs: BTreeSet<()> = BTreeSet::new(); - for _v in bs.iter() { } + for _v in bs.iter() {} - for _v in vec.iter().next() { } + for _v in vec.iter().next() {} let u = Unrelated(vec![]); - for _v in u.next() { } // no error - for _v in u.iter() { } // no error + for _v in u.next() {} // no error + for _v in u.iter() {} // no error let mut out = vec![]; vec.iter().cloned().map(|x| out.push(x)).collect::>(); @@ -254,82 +266,135 @@ fn main() { // Loop with explicit counter variable let mut _index = 0; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 1; _index = 0; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } // Potential false positives let mut _index = 0; _index = 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; _index += 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; - if true { _index = 1 } - for _v in &vec { _index += 1 } + if true { + _index = 1 + } + for _v in &vec { + _index += 1 + } let mut _index = 0; let mut _index = 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; - for _v in &vec { _index += 1; _index += 1 } + for _v in &vec { + _index += 1; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index *= 2; _index += 1 } + for _v in &vec { + _index *= 2; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index = 1; _index += 1 } + for _v in &vec { + _index = 1; + _index += 1 + } let mut _index = 0; - for _v in &vec { let mut _index = 0; _index += 1 } + for _v in &vec { + let mut _index = 0; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index += 1; _index = 0; } + for _v in &vec { + _index += 1; + _index = 0; + } let mut _index = 0; - for _v in &vec { for _x in 0..1 { _index += 1; }; _index += 1 } + for _v in &vec { + for _x in 0..1 { + _index += 1; + } + _index += 1 + } let mut _index = 0; - for x in &vec { if *x == 1 { _index += 1 } } + for x in &vec { + if *x == 1 { + _index += 1 + } + } let mut _index = 0; - if true { _index = 1 }; - for _v in &vec { _index += 1 } + if true { + _index = 1 + }; + for _v in &vec { + _index += 1 + } let mut _index = 1; - if false { _index = 0 }; - for _v in &vec { _index += 1 } + if false { + _index = 0 + }; + for _v in &vec { + _index += 1 + } let mut index = 0; - { let mut _x = &mut index; } - for _v in &vec { _index += 1 } + { + let mut _x = &mut index; + } + for _v in &vec { + _index += 1 + } let mut index = 0; - for _v in &vec { index += 1 } + for _v in &vec { + index += 1 + } println!("index: {}", index); for_loop_over_option_and_result(); - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); for (_, v) in &m { let _v = v; } - let m : Rc> = Rc::new(HashMap::new()); + let m: Rc> = Rc::new(HashMap::new()); for (_, v) in &*m { let _v = v; - // Here the `*` is not actually necesarry, but the test tests that we don't suggest + // Here the `*` is not actually necesarry, but the test tests that we don't + // suggest // `in *m.values()` as we used to } - let mut m : HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); for (_, v) in &mut m { let _v = v; } @@ -339,7 +404,7 @@ fn main() { let _v = v; } - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); let rm = &m; for (k, _value) in rm { let _k = k; @@ -347,8 +412,12 @@ fn main() { test_for_kv_map(); - fn f(_: &T, _: &T) -> bool { unimplemented!() } - fn g(_: &mut [T], _: usize, _: usize) { unimplemented!() } + fn f(_: &T, _: &T) -> bool { + unimplemented!() + } + fn g(_: &mut [T], _: usize, _: usize) { + unimplemented!() + } for i in 1..vec.len() { if f(&vec[i - 1], &vec[i]) { g(&mut vec, i - 1, i); @@ -362,7 +431,7 @@ fn main() { #[allow(used_underscore_binding)] fn test_for_kv_map() { - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); // No error, _value is actually used for (k, _value) in &m { @@ -372,7 +441,7 @@ fn test_for_kv_map() { } #[allow(dead_code)] -fn partition(v: &mut [T]) -> usize { +fn partition(v: &mut [T]) -> usize { let pivot = v.len() - 1; let mut i = 0; for j in 0..pivot { @@ -384,3 +453,91 @@ fn partition(v: &mut [T]) -> usize { v.swap(i, pivot); i } + +const LOOP_OFFSET: usize = 5000; + +#[warn(needless_range_loop)] +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + // plain manual memcpy + for i in 0..src.len() { + dst[i] = src[i]; + } + + // dst offset memcpy + for i in 0..src.len() { + dst[i + 10] = src[i]; + } + + // src offset memcpy + for i in 0..src.len() { + dst[i] = src[i + 10]; + } + + // src offset memcpy + for i in 11..src.len() { + dst[i] = src[i - 10]; + } + + // overwrite entire dst + for i in 0..dst.len() { + dst[i] = src[i]; + } + + // manual copy with branch - can't easily convert to memcpy! + for i in 0..src.len() { + dst[i] = src[i]; + if dst[i] > 5 { + break; + } + } + + // multiple copies - suggest two memcpy statements + for i in 10..256 { + dst[i] = src[i - 5]; + dst2[i + 500] = src[i] + } + + // this is a reversal - the copy lint shouldn't be triggered + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i]; + } + + let some_var = 5; + // Offset in variable + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[i - some_var]; + } + + // Non continuous copy - don't trigger lint + for i in 0..10 { + dst[i + i] = src[i]; + } + + let src_vec = vec![1, 2, 3, 4, 5]; + let mut dst_vec = vec![0, 0, 0, 0, 0]; + + // make sure vectors are supported + for i in 0..src_vec.len() { + dst_vec[i] = src_vec[i]; + } + + // lint should not trigger when either + // source or destination type is not + // slice-like, like DummyStruct + struct DummyStruct(i32); + + impl ::std::ops::Index for DummyStruct { + type Output = i32; + + fn index(&self, _: usize) -> &i32 { + &self.0 + } + } + + let src = DummyStruct(5); + let mut dst_vec = vec![0; 10]; + + for i in 0..10 { + dst_vec[i] = src[i]; + } +} diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index d4954357665..090caf1779a 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -25,478 +25,537 @@ error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:31:5 + --> $DIR/for_loop.rs:32:5 | -31 | / for x in v.iter().next() { -32 | | println!("{}", x); -33 | | } +32 | / for x in v.iter().next() { +33 | | println!("{}", x); +34 | | } | |_____^ | = note: `-D iter-next-loop` implied by `-D warnings` error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:36:14 + --> $DIR/for_loop.rs:37:14 | -36 | for x in v.iter().next().and(Some(0)) { +37 | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:40:14 + --> $DIR/for_loop.rs:41:14 | -40 | for x in v.iter().next().ok_or("x not found") { +41 | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop.rs:52:5 + --> $DIR/for_loop.rs:53:5 | -52 | / while let Some(x) = option { -53 | | println!("{}", x); -54 | | break; -55 | | } +53 | / while let Some(x) = option { +54 | | println!("{}", x); +55 | | break; +56 | | } | |_____^ | = note: `-D never-loop` implied by `-D warnings` error: this loop never actually loops - --> $DIR/for_loop.rs:58:5 + --> $DIR/for_loop.rs:59:5 | -58 | / while let Ok(x) = result { -59 | | println!("{}", x); -60 | | break; -61 | | } +59 | / while let Ok(x) = result { +60 | | println!("{}", x); +61 | | break; +62 | | } | |_____^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:84:5 + --> $DIR/for_loop.rs:86:5 | -84 | / for i in 0..vec.len() { -85 | | println!("{}", vec[i]); -86 | | } +86 | / for i in 0..vec.len() { +87 | | println!("{}", vec[i]); +88 | | } | |_____^ | = note: `-D needless-range-loop` implied by `-D warnings` help: consider using an iterator | -84 | for in &vec { +86 | for in &vec { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:93:5 + --> $DIR/for_loop.rs:95:5 | -93 | for i in 0..vec.len() { let _ = vec[i]; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using an iterator - | -93 | for in &vec { let _ = vec[i]; } - | ^^^^^^ - -error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:96:5 - | -96 | / for j in 0..4 { -97 | | println!("{:?}", STATIC[j]); -98 | | } +95 | / for i in 0..vec.len() { +96 | | let _ = vec[i]; +97 | | } | |_____^ | help: consider using an iterator | -96 | for in STATIC.iter().take(4) { +95 | for in &vec { | ^^^^^^ -error: the loop variable `j` is only used to index `CONST`. +error: the loop variable `j` is only used to index `STATIC`. --> $DIR/for_loop.rs:100:5 | 100 | / for j in 0..4 { -101 | | println!("{:?}", CONST[j]); +101 | | println!("{:?}", STATIC[j]); 102 | | } | |_____^ | help: consider using an iterator | -100 | for in CONST.iter().take(4) { +100 | for in STATIC.iter().take(4) { | ^^^^^^ -error: the loop variable `i` is used to index `vec` +error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:104:5 | -104 | / for i in 0..vec.len() { -105 | | println!("{} {}", vec[i], i); +104 | / for j in 0..4 { +105 | | println!("{:?}", CONST[j]); 106 | | } | |_____^ | help: consider using an iterator | -104 | for (i, ) in vec.iter().enumerate() { +104 | for in CONST.iter().take(4) { + | ^^^^^^ + +error: the loop variable `i` is used to index `vec` + --> $DIR/for_loop.rs:108:5 + | +108 | / for i in 0..vec.len() { +109 | | println!("{} {}", vec[i], i); +110 | | } + | |_____^ + | +help: consider using an iterator + | +108 | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:111:5 + --> $DIR/for_loop.rs:116:5 | -111 | / for i in 0..vec.len() { -112 | | println!("{}", vec2[i]); -113 | | } +116 | / for i in 0..vec.len() { +117 | | println!("{}", vec2[i]); +118 | | } | |_____^ | help: consider using an iterator | -111 | for in vec2.iter().take(vec.len()) { +116 | for in vec2.iter().take(vec.len()) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:115:5 + --> $DIR/for_loop.rs:120:5 | -115 | / for i in 5..vec.len() { -116 | | println!("{}", vec[i]); -117 | | } +120 | / for i in 5..vec.len() { +121 | | println!("{}", vec[i]); +122 | | } | |_____^ | help: consider using an iterator | -115 | for in vec.iter().skip(5) { +120 | for in vec.iter().skip(5) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:119:5 + --> $DIR/for_loop.rs:124:5 | -119 | / for i in 0..MAX_LEN { -120 | | println!("{}", vec[i]); -121 | | } +124 | / for i in 0..MAX_LEN { +125 | | println!("{}", vec[i]); +126 | | } | |_____^ | help: consider using an iterator | -119 | for in vec.iter().take(MAX_LEN) { +124 | for in vec.iter().take(MAX_LEN) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:123:5 + --> $DIR/for_loop.rs:128:5 | -123 | / for i in 0...MAX_LEN { -124 | | println!("{}", vec[i]); -125 | | } +128 | / for i in 0...MAX_LEN { +129 | | println!("{}", vec[i]); +130 | | } | |_____^ | help: consider using an iterator | -123 | for in vec.iter().take(MAX_LEN + 1) { +128 | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:127:5 + --> $DIR/for_loop.rs:132:5 | -127 | / for i in 5..10 { -128 | | println!("{}", vec[i]); -129 | | } +132 | / for i in 5..10 { +133 | | println!("{}", vec[i]); +134 | | } | |_____^ | help: consider using an iterator | -127 | for in vec.iter().take(10).skip(5) { +132 | for in vec.iter().take(10).skip(5) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:131:5 + --> $DIR/for_loop.rs:136:5 | -131 | / for i in 5...10 { -132 | | println!("{}", vec[i]); -133 | | } +136 | / for i in 5...10 { +137 | | println!("{}", vec[i]); +138 | | } | |_____^ | help: consider using an iterator | -131 | for in vec.iter().take(10 + 1).skip(5) { +136 | for in vec.iter().take(10 + 1).skip(5) { | ^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:135:5 + --> $DIR/for_loop.rs:140:5 | -135 | / for i in 5..vec.len() { -136 | | println!("{} {}", vec[i], i); -137 | | } +140 | / for i in 5..vec.len() { +141 | | println!("{} {}", vec[i], i); +142 | | } | |_____^ | help: consider using an iterator | -135 | for (i, ) in vec.iter().enumerate().skip(5) { +140 | for (i, ) in vec.iter().enumerate().skip(5) { | ^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:139:5 + --> $DIR/for_loop.rs:144:5 | -139 | / for i in 5..10 { -140 | | println!("{} {}", vec[i], i); -141 | | } +144 | / for i in 5..10 { +145 | | println!("{} {}", vec[i], i); +146 | | } | |_____^ | help: consider using an iterator | -139 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { +144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:143:5 + --> $DIR/for_loop.rs:148:5 | -143 | / for i in 10..0 { -144 | | println!("{}", i); -145 | | } +148 | / for i in 10..0 { +149 | | println!("{}", i); +150 | | } | |_____^ | = note: `-D reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | -143 | for i in (0..10).rev() { +148 | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:147:5 + --> $DIR/for_loop.rs:152:5 | -147 | / for i in 10...0 { -148 | | println!("{}", i); -149 | | } +152 | / for i in 10...0 { +153 | | println!("{}", i); +154 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -147 | for i in (0...10).rev() { +152 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:151:5 + --> $DIR/for_loop.rs:156:5 | -151 | / for i in MAX_LEN..0 { -152 | | println!("{}", i); -153 | | } +156 | / for i in MAX_LEN..0 { +157 | | println!("{}", i); +158 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -151 | for i in (0..MAX_LEN).rev() { +156 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:155:5 + --> $DIR/for_loop.rs:160:5 | -155 | / for i in 5..5 { -156 | | println!("{}", i); -157 | | } +160 | / for i in 5..5 { +161 | | println!("{}", i); +162 | | } | |_____^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:176:5 + --> $DIR/for_loop.rs:185:5 | -176 | / for i in 10..5+4 { -177 | | println!("{}", i); -178 | | } +185 | / for i in 10..5 + 4 { +186 | | println!("{}", i); +187 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -176 | for i in (5+4..10).rev() { - | ^^^^^^^^^^^^^^^ +185 | for i in (5 + 4..10).rev() { + | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:180:5 + --> $DIR/for_loop.rs:189:5 | -180 | / for i in (5+2)..(3-1) { -181 | | println!("{}", i); -182 | | } +189 | / for i in (5 + 2)..(3 - 1) { +190 | | println!("{}", i); +191 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -180 | for i in ((3-1)..(5+2)).rev() { - | ^^^^^^^^^^^^^^^^^^^^ +189 | for i in ((3 - 1)..(5 + 2)).rev() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:184:5 + --> $DIR/for_loop.rs:193:5 | -184 | / for i in (5+2)..(8-1) { -185 | | println!("{}", i); -186 | | } +193 | / for i in (5 + 2)..(8 - 1) { +194 | | println!("{}", i); +195 | | } | |_____^ error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:203:15 + --> $DIR/for_loop.rs:215:15 | -203 | for _v in vec.iter() { } +215 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | = note: `-D explicit-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:205:15 + --> $DIR/for_loop.rs:217:15 | -205 | for _v in vec.iter_mut() { } +217 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more idiomatic to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:208:15 + --> $DIR/for_loop.rs:220:15 | -208 | for _v in out_vec.into_iter() { } +220 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | = note: `-D explicit-into-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:211:15 + --> $DIR/for_loop.rs:223:15 | -211 | for _v in array.into_iter() {} +223 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:216:15 + --> $DIR/for_loop.rs:228:15 | -216 | for _v in [1, 2, 3].iter() { } +228 | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:220:15 + --> $DIR/for_loop.rs:232:15 | -220 | for _v in [0; 32].iter() {} +232 | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:225:15 + --> $DIR/for_loop.rs:237:15 | -225 | for _v in ll.iter() { } +237 | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:228:15 + --> $DIR/for_loop.rs:240:15 | -228 | for _v in vd.iter() { } +240 | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:231:15 + --> $DIR/for_loop.rs:243:15 | -231 | for _v in bh.iter() { } +243 | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:234:15 + --> $DIR/for_loop.rs:246:15 | -234 | for _v in hm.iter() { } +246 | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:237:15 + --> $DIR/for_loop.rs:249:15 | -237 | for _v in bt.iter() { } +249 | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:240:15 + --> $DIR/for_loop.rs:252:15 | -240 | for _v in hs.iter() { } +252 | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:243:15 + --> $DIR/for_loop.rs:255:15 | -243 | for _v in bs.iter() { } +255 | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:245:5 + --> $DIR/for_loop.rs:257:5 | -245 | for _v in vec.iter().next() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +257 | for _v in vec.iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:252:5 + --> $DIR/for_loop.rs:264:5 | -252 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); +264 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-collect` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:257:5 + --> $DIR/for_loop.rs:269:5 | -257 | for _v in &vec { _index += 1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +269 | / for _v in &vec { +270 | | _index += 1 +271 | | } + | |_____^ | = note: `-D explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:261:5 + --> $DIR/for_loop.rs:275:5 | -261 | for _v in &vec { _index += 1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +275 | / for _v in &vec { +276 | | _index += 1 +277 | | } + | |_____^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:321:5 + --> $DIR/for_loop.rs:385:5 | -321 | / for (_, v) in &m { -322 | | let _v = v; -323 | | } +385 | / for (_, v) in &m { +386 | | let _v = v; +387 | | } | |_____^ | = note: `-D for-kv-map` implied by `-D warnings` help: use the corresponding method | -321 | for v in m.values() { +385 | for v in m.values() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:326:5 - | -326 | / for (_, v) in &*m { -327 | | let _v = v; -328 | | // Here the `*` is not actually necesarry, but the test tests that we don't suggest -329 | | // `in *m.values()` as we used to -330 | | } + --> $DIR/for_loop.rs:390:5 + | +390 | / for (_, v) in &*m { +391 | | let _v = v; +392 | | // Here the `*` is not actually necesarry, but the test tests that we don't +393 | | // suggest +394 | | // `in *m.values()` as we used to +395 | | } | |_____^ | help: use the corresponding method | -326 | for v in (*m).values() { +390 | for v in (*m).values() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:333:5 + --> $DIR/for_loop.rs:398:5 | -333 | / for (_, v) in &mut m { -334 | | let _v = v; -335 | | } +398 | / for (_, v) in &mut m { +399 | | let _v = v; +400 | | } | |_____^ | help: use the corresponding method | -333 | for v in m.values_mut() { +398 | for v in m.values_mut() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:338:5 + --> $DIR/for_loop.rs:403:5 | -338 | / for (_, v) in &mut *m { -339 | | let _v = v; -340 | | } +403 | / for (_, v) in &mut *m { +404 | | let _v = v; +405 | | } | |_____^ | help: use the corresponding method | -338 | for v in (*m).values_mut() { +403 | for v in (*m).values_mut() { | ^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:344:5 + --> $DIR/for_loop.rs:409:5 | -344 | / for (k, _value) in rm { -345 | | let _k = k; -346 | | } +409 | / for (k, _value) in rm { +410 | | let _k = k; +411 | | } | |_____^ | help: use the corresponding method | -344 | for k in rm.keys() { +409 | for k in rm.keys() { | ^ -error: aborting due to 50 previous errors +error: the loop variable `i` is used to index `src` + --> $DIR/for_loop.rs:467:5 + | +467 | / for i in 0..src.len() { +468 | | dst[i + 10] = src[i]; +469 | | } + | |_____^ + | +help: consider using an iterator + | +467 | for (i, ) in src.iter().enumerate() { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `dst` + --> $DIR/for_loop.rs:472:5 + | +472 | / for i in 0..src.len() { +473 | | dst[i] = src[i + 10]; +474 | | } + | |_____^ + | +help: consider using an iterator + | +472 | for (i, ) in dst.iter().enumerate().take(src.len()) { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `dst` + --> $DIR/for_loop.rs:477:5 + | +477 | / for i in 11..src.len() { +478 | | dst[i] = src[i - 10]; +479 | | } + | |_____^ + | +help: consider using an iterator + | +477 | for (i, ) in dst.iter().enumerate().take(src.len()).skip(11) { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `src` + --> $DIR/for_loop.rs:512:5 + | +512 | / for i in 0..10 { +513 | | dst[i + i] = src[i]; +514 | | } + | |_____^ + | +help: consider using an iterator + | +512 | for (i, ) in src.iter().enumerate().take(10) { + | ^^^^^^^^^^^ + +error: aborting due to 54 previous errors -- cgit 1.4.1-3-g733a5 From 90f345df94ffa92760ce338208a034d0a3785a2d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 4 Sep 2017 20:16:34 -0400 Subject: Add lint to detect manual slice copies --- clippy_lints/src/loops.rs | 346 ++++++++++++++++++++++++++++++++++++++++++---- tests/ui/for_loop.stderr | 79 +++++++---- 2 files changed, 368 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2f87fe0f396..6cf2b1d9fed 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; @@ -15,10 +16,29 @@ use syntax::ast; use utils::sugg; use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, - last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then}; + last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, snippet_opt, + span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; use utils::paths; +/// **What it does:** Checks for for loops that manually copy items between +/// slices that could be optimized by having a memcpy. +/// +/// **Why is this bad?** It is not as fast as a memcpy. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// for i in 0..src.len() { +/// dst[i + 64] = src[i]; +/// } +/// ``` +declare_lint! { + pub MANUAL_MEMCPY, + Warn, + "manually copying items between slices" +} + /// **What it does:** Checks for looping over the range of `0..len` of some /// collection just to get the values by index. /// @@ -314,6 +334,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( + MANUAL_MEMCPY, NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, EXPLICIT_INTO_ITER_LOOP, @@ -570,6 +591,249 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); + detect_manual_memcpy(cx, pat, arg, body, expr); +} + +fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> bool { + if_let_chain! {[ + let ExprPath(ref qpath) = expr.node, + let QPath::Resolved(None, ref path) = *qpath, + path.segments.len() == 1, + // our variable! + cx.tables.qpath_def(qpath, expr.hir_id).def_id() == var + ], { + return true; + }} + + false +} + +struct Offset { + value: String, + negate: bool, +} + +impl Offset { + fn negative(s: String) -> Self { + Self { + value: s, + negate: true, + } + } + + fn positive(s: String) -> Self { + Self { + value: s, + negate: false, + } + } +} + +struct FixedOffsetVar { + var_name: String, + offset: Offset, +} + +fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { + let is_slice = match ty.sty { + ty::TyRef(_, ref subty) => is_slice_like(cx, subty.ty), + ty::TySlice(..) | ty::TyArray(..) => true, + _ => false, + }; + + is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) +} + +fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> Option { + fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: DefId) -> Option { + match e.node { + ExprLit(ref l) => match l.node { + ast::LitKind::Int(x, _ty) => Some(x.to_string()), + _ => None, + }, + ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), + _ => None, + } + } + + if let ExprIndex(ref seqexpr, ref idx) = expr.node { + let ty = cx.tables.expr_ty(seqexpr); + if !is_slice_like(cx, ty) { + return None; + } + + let offset = match idx.node { + ExprBinary(op, ref lhs, ref rhs) => match op.node { + BinOp_::BiAdd => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; + + offset_opt.map(Offset::positive) + }, + BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), + _ => None, + }, + ExprPath(..) => if same_var(cx, idx, var) { + Some(Offset::positive("0".into())) + } else { + None + }, + _ => None, + }; + + offset.map(|o| { + FixedOffsetVar { + var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), + offset: o, + } + }) + } else { + None + } +} + +fn get_indexed_assignments<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + body: &Expr, + var: DefId, +) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { + fn get_assignment<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + e: &Expr, + var: DefId, + ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { + if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { + match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) { + (Some(offset_left), Some(offset_right)) => Some((offset_left, offset_right)), + _ => None, + } + } else { + None + } + } + + if let Expr_::ExprBlock(ref b) = body.node { + let Block { + ref stmts, + ref expr, + .. + } = **b; + + stmts + .iter() + .map(|stmt| match stmt.node { + Stmt_::StmtDecl(..) => None, + Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + }) + .chain( + expr.as_ref() + .into_iter() + .map(|e| Some(get_assignment(cx, &*e, var))), + ) + .filter_map(|op| op) + .collect::>>() + .unwrap_or_else(|| vec![]) + } else { + get_assignment(cx, body, var).into_iter().collect() + } +} + +/// Check for for loops that sequentially copy items from one slice-like +/// object to another. +fn detect_manual_memcpy<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + pat: &'tcx Pat, + arg: &'tcx Expr, + body: &'tcx Expr, + expr: &'tcx Expr, +) { + if let Some(higher::Range { + start: Some(start), + ref end, + limits, + }) = higher::range(arg) + { + // the var must be a single name + if let PatKind::Binding(_, def_id, _, _) = pat.node { + let print_sum = |arg1: &Offset, arg2: &Offset| -> String { + match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { + ("0", _, "0", _) => "".into(), + ("0", _, x, false) | (x, false, "0", false) => x.into(), + ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), + (x, false, y, false) => format!("({} + {})", x, y), + (x, false, y, true) => format!("({} - {})", x, y), + (x, true, y, false) => format!("({} - {})", y, x), + (x, true, y, true) => format!("-({} + {})", x, y), + } + }; + + let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { + if_let_chain! {[ + let ExprMethodCall(ref method, _, ref len_args) = end.node, + method.name == "len", + len_args.len() == 1, + let Some(arg) = len_args.get(0), + snippet(cx, arg.span, "??") == var_name, + ], { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) + } else { + "".to_owned() + }; + }} + + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&Offset::positive(end_str), &offset) + } else { + "..".into() + }; + + // The only statements in the for loops can be indexed assignments from + // indexed retrievals. + let manual_copies = get_indexed_assignments(cx, body, def_id); + + let big_sugg = manual_copies + .into_iter() + .map(|(dst_var, src_var)| { + let start_str = Offset::positive(snippet_opt(cx, start.span).unwrap_or_else(|| "".into())); + let dst_offset = print_sum(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let src_offset = print_sum(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let dst = if dst_offset == "" && dst_limit == "" { + dst_var.var_name + } else { + format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + }; + + format!("{}.clone_from_slice(&{}[{}..{}])", dst, src_var.var_name, src_offset, src_limit) + }) + .join("\n "); + + if !big_sugg.is_empty() { + span_lint_and_sugg( + cx, + MANUAL_MEMCPY, + expr.span, + "it looks like you're manually copying between slices", + "try replacing the loop by", + big_sugg, + ); + } + } + } } /// Check for looping over a range and then indexing a sequence with it. @@ -1024,9 +1288,29 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor { fn visit_expr(&mut self, expr: &'tcx Expr) { if match_var(expr, self.var) { self.used = true; - return; + } else { + walk_expr(self, expr); + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +struct DefIdUsedVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + def_id: DefId, + used: bool, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for DefIdUsedVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if same_var(self.cx, expr, self.def_id) { + self.used = true; + } else { + walk_expr(self, expr); } - walk_expr(self, expr); } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { @@ -1054,40 +1338,46 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_let_chain! {[ // an index op let ExprIndex(ref seqexpr, ref idx) = expr.node, - // directly indexing a variable - let ExprPath(ref qpath) = idx.node, - let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, - // our variable! - self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var, // the indexed container is referenced by a name let ExprPath(ref seqpath) = seqexpr.node, let QPath::Resolved(None, ref seqvar) = *seqpath, seqvar.segments.len() == 1, ], { - let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); - match def { - Def::Local(..) | Def::Upvar(..) => { - let def_id = def.def_id(); - let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); - let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); - - let parent_id = self.cx.tcx.hir.get_parent(expr.id); - let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); - return; // no need to walk further - } - Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); - return; // no need to walk further + let index_used = same_var(self.cx, idx, self.var) || { + let mut used_visitor = DefIdUsedVisitor { + cx: self.cx, + def_id: self.var, + used: false, + }; + walk_expr(&mut used_visitor, idx); + used_visitor.used + }; + + if index_used { + let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); + match def { + Def::Local(..) | Def::Upvar(..) => { + let def_id = def.def_id(); + let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); + let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); + + let parent_id = self.cx.tcx.hir.get_parent(expr.id); + let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); + return; // no need to walk further *on the variable* + } + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].name, None); + return; // no need to walk further *on the variable* + } + _ => (), } - _ => (), } }} if_let_chain! {[ - // directly indexing a variable + // directly using a variable let ExprPath(ref qpath) = expr.node, let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 090caf1779a..721b2833dec 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -505,57 +505,78 @@ help: use the corresponding method 409 | for k in rm.keys() { | ^ -error: the loop variable `i` is used to index `src` +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:462:5 + | +462 | / for i in 0..src.len() { +463 | | dst[i] = src[i]; +464 | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` + | + = note: `-D manual-memcpy` implied by `-D warnings` + +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:467:5 | 467 | / for i in 0..src.len() { 468 | | dst[i + 10] = src[i]; 469 | | } - | |_____^ - | -help: consider using an iterator - | -467 | for (i, ) in src.iter().enumerate() { - | ^^^^^^^^^^^ + | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` -error: the loop variable `i` is used to index `dst` +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:472:5 | 472 | / for i in 0..src.len() { 473 | | dst[i] = src[i + 10]; 474 | | } - | |_____^ - | -help: consider using an iterator - | -472 | for (i, ) in dst.iter().enumerate().take(src.len()) { - | ^^^^^^^^^^^ + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` -error: the loop variable `i` is used to index `dst` +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:477:5 | 477 | / for i in 11..src.len() { 478 | | dst[i] = src[i - 10]; 479 | | } - | |_____^ - | -help: consider using an iterator + | |_____^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:482:5 | -477 | for (i, ) in dst.iter().enumerate().take(src.len()).skip(11) { - | ^^^^^^^^^^^ +482 | / for i in 0..dst.len() { +483 | | dst[i] = src[i]; +484 | | } + | |_____^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` -error: the loop variable `i` is used to index `src` - --> $DIR/for_loop.rs:512:5 +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:495:5 | -512 | / for i in 0..10 { -513 | | dst[i + i] = src[i]; -514 | | } +495 | / for i in 10..256 { +496 | | dst[i] = src[i - 5]; +497 | | dst2[i + 500] = src[i] +498 | | } | |_____^ | -help: consider using an iterator +help: try replacing the loop by | -512 | for (i, ) in src.iter().enumerate().take(10) { - | ^^^^^^^^^^^ +495 | dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) + | + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:507:5 + | +507 | / for i in 10..LOOP_OFFSET { +508 | | dst[i + LOOP_OFFSET] = src[i - some_var]; +509 | | } + | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:520:5 + | +520 | / for i in 0..src_vec.len() { +521 | | dst_vec[i] = src_vec[i]; +522 | | } + | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` -error: aborting due to 54 previous errors +error: aborting due to 58 previous errors -- cgit 1.4.1-3-g733a5 From 07d5dba0b75c4714006ffb1c61887560ec57d7bb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 5 Sep 2017 09:45:14 -0700 Subject: Update changelog --- CHANGELOG.md | 4 ++++ clippy_lints/src/lib.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3eea80fe18..10bcd9e4dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## Upcoming +* New lint: [`manual_memcpy`] + ## 0.0.157 - 2017-09-04 * Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* * New lint: [`unit_expr`] @@ -511,6 +514,7 @@ All notable changes to this project will be documented in this file. [`let_unit_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_unit_value [`linkedlist`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#logic_bug +[`manual_memcpy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_swap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 41ca62b470c..a9e5310dd7f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -444,6 +444,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, + loops::MANUAL_MEMCPY, loops::NEEDLESS_RANGE_LOOP, loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, -- cgit 1.4.1-3-g733a5 From bc602df324c3c52ea112a3d1d3f107fcce9a8981 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 5 Sep 2017 09:45:14 -0700 Subject: Update changelog --- CHANGELOG.md | 4 ++++ clippy_lints/src/lib.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3eea80fe18..10bcd9e4dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## Upcoming +* New lint: [`manual_memcpy`] + ## 0.0.157 - 2017-09-04 * Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* * New lint: [`unit_expr`] @@ -511,6 +514,7 @@ All notable changes to this project will be documented in this file. [`let_unit_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_unit_value [`linkedlist`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#logic_bug +[`manual_memcpy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_swap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 41ca62b470c..a9e5310dd7f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -444,6 +444,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, + loops::MANUAL_MEMCPY, loops::NEEDLESS_RANGE_LOOP, loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, -- cgit 1.4.1-3-g733a5 From 35cf2715dcaa887bc72973ea3d220054dbf0c98a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 30 Aug 2017 16:06:21 -0700 Subject: When suggesting `from(x)` for lossless casts, strip parens from `x`. --- clippy_lints/src/types.rs | 17 +++++++- tests/ui/cast.rs | 2 + tests/ui/cast.stderr | 104 ++++++++++++++++++++++++---------------------- 3 files changed, 72 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 78e06fa80dd..e01ec291d5d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -10,7 +10,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, - opt_def_id, snippet, span_help_and_lint, span_lint, span_lint_and_sugg, type_size}; + opt_def_id, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -581,13 +581,26 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t } fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { + // The suggestion is to use a function call, so if the original expression + // has parens on the outside, they are no longer needed. + let opt = snippet_opt(cx, op.span); + let sugg = if let Some(ref snip) = opt { + if snip.starts_with('(') && snip.ends_with(')') { + &snip[1..snip.len()-1] + } else { + snip.as_str() + } + } else { + ".." + }; + span_lint_and_sugg( cx, CAST_LOSSLESS, expr.span, &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to), "try", - format!("{}::from({})", cast_to, &snippet(cx, op.span, "..")), + format!("{}::from({})", cast_to, sugg), ); } diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index fd4c4e91c5d..82427c128e4 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -57,6 +57,8 @@ fn main() { 1u32 as f64; // Test cast_lossless with casts from floating-point types 1.0f32 as f64; + // Test cast_lossless with an expression wrapped in parens + (1u8 + 1u8) as u16; // Test cast_sign_loss 1i32 as u32; 1isize as usize; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index de37be206d0..8787083b429 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -308,151 +308,157 @@ error: casting f32 to f64 may become silently lossy if types change 59 | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` -error: casting i32 to u32 may lose the sign of the value +error: casting u8 to u16 may become silently lossy if types change --> $DIR/cast.rs:61:5 | -61 | 1i32 as u32; +61 | (1u8 + 1u8) as u16; + | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` + +error: casting i32 to u32 may lose the sign of the value + --> $DIR/cast.rs:63:5 + | +63 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:62:5 + --> $DIR/cast.rs:64:5 | -62 | 1isize as usize; +64 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting isize to i8 may truncate the value - --> $DIR/cast.rs:65:5 + --> $DIR/cast.rs:67:5 | -65 | 1isize as i8; +67 | 1isize as i8; | ^^^^^^^^^^^^ error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:66:5 + --> $DIR/cast.rs:68:5 | -66 | 1isize as f64; +68 | 1isize as f64; | ^^^^^^^^^^^^^ error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:67:5 + --> $DIR/cast.rs:69:5 | -67 | 1usize as f64; +69 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:68:5 + --> $DIR/cast.rs:70:5 | -68 | 1isize as f32; +70 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:69:5 + --> $DIR/cast.rs:71:5 | -69 | 1usize as f32; +71 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:70:5 + --> $DIR/cast.rs:72:5 | -70 | 1isize as i32; +72 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast.rs:71:5 + --> $DIR/cast.rs:73:5 | -71 | 1isize as u32; +73 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:71:5 + --> $DIR/cast.rs:73:5 | -71 | 1isize as u32; +73 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:72:5 + --> $DIR/cast.rs:74:5 | -72 | 1usize as u32; +74 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:75:5 | -73 | 1usize as i32; +75 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:75:5 | -73 | 1usize as i32; +75 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:75:5 + --> $DIR/cast.rs:77:5 | -75 | 1i64 as isize; +77 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast.rs:76:5 + --> $DIR/cast.rs:78:5 | -76 | 1i64 as usize; +78 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:76:5 + --> $DIR/cast.rs:78:5 | -76 | 1i64 as usize; +78 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:77:5 + --> $DIR/cast.rs:79:5 | -77 | 1u64 as isize; +79 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:77:5 + --> $DIR/cast.rs:79:5 | -77 | 1u64 as isize; +79 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:78:5 + --> $DIR/cast.rs:80:5 | -78 | 1u64 as usize; +80 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:79:5 + --> $DIR/cast.rs:81:5 | -79 | 1u32 as isize; +81 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast.rs:82:5 + --> $DIR/cast.rs:84:5 | -82 | 1i32 as usize; +84 | 1i32 as usize; | ^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:84:5 + --> $DIR/cast.rs:86:5 | -84 | 1i32 as i32; +86 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:85:5 + --> $DIR/cast.rs:87:5 | -85 | 1f32 as f32; +87 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:86:5 + --> $DIR/cast.rs:88:5 | -86 | false as bool; +88 | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 74 previous errors +error: aborting due to 75 previous errors -- cgit 1.4.1-3-g733a5 From ffa0bd24ed33f90bb7a6a04b66107aa3396acbe0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 30 Aug 2017 16:45:36 -0700 Subject: Add a testcase demonstrating how precedence interacts with the lossless-cast lint. --- tests/ui/cast.rs | 1 + tests/ui/cast.stderr | 104 +++++++++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 82427c128e4..54012923df4 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -59,6 +59,7 @@ fn main() { 1.0f32 as f64; // Test cast_lossless with an expression wrapped in parens (1u8 + 1u8) as u16; + (1u16) + (1u8) as u16; // Test cast_sign_loss 1i32 as u32; 1isize as usize; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 8787083b429..93c5aad0c59 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -314,151 +314,157 @@ error: casting u8 to u16 may become silently lossy if types change 61 | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` +error: casting u8 to u16 may become silently lossy if types change + --> $DIR/cast.rs:62:14 + | +62 | (1u16) + (1u8) as u16; + | ^^^^^^^^^^^^ help: try: `u16::from(1u8)` + error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:63:5 + --> $DIR/cast.rs:64:5 | -63 | 1i32 as u32; +64 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:64:5 + --> $DIR/cast.rs:65:5 | -64 | 1isize as usize; +65 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting isize to i8 may truncate the value - --> $DIR/cast.rs:67:5 + --> $DIR/cast.rs:68:5 | -67 | 1isize as i8; +68 | 1isize as i8; | ^^^^^^^^^^^^ error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:68:5 + --> $DIR/cast.rs:69:5 | -68 | 1isize as f64; +69 | 1isize as f64; | ^^^^^^^^^^^^^ error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:69:5 + --> $DIR/cast.rs:70:5 | -69 | 1usize as f64; +70 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:70:5 + --> $DIR/cast.rs:71:5 | -70 | 1isize as f32; +71 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:71:5 + --> $DIR/cast.rs:72:5 | -71 | 1usize as f32; +72 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:72:5 + --> $DIR/cast.rs:73:5 | -72 | 1isize as i32; +73 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:74:5 | -73 | 1isize as u32; +74 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:74:5 | -73 | 1isize as u32; +74 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:74:5 + --> $DIR/cast.rs:75:5 | -74 | 1usize as u32; +75 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:75:5 + --> $DIR/cast.rs:76:5 | -75 | 1usize as i32; +76 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:75:5 + --> $DIR/cast.rs:76:5 | -75 | 1usize as i32; +76 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:77:5 + --> $DIR/cast.rs:78:5 | -77 | 1i64 as isize; +78 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast.rs:78:5 + --> $DIR/cast.rs:79:5 | -78 | 1i64 as usize; +79 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:78:5 + --> $DIR/cast.rs:79:5 | -78 | 1i64 as usize; +79 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:79:5 + --> $DIR/cast.rs:80:5 | -79 | 1u64 as isize; +80 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:79:5 + --> $DIR/cast.rs:80:5 | -79 | 1u64 as isize; +80 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:80:5 + --> $DIR/cast.rs:81:5 | -80 | 1u64 as usize; +81 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:81:5 + --> $DIR/cast.rs:82:5 | -81 | 1u32 as isize; +82 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast.rs:84:5 + --> $DIR/cast.rs:85:5 | -84 | 1i32 as usize; +85 | 1i32 as usize; | ^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:86:5 + --> $DIR/cast.rs:87:5 | -86 | 1i32 as i32; +87 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:87:5 + --> $DIR/cast.rs:88:5 | -87 | 1f32 as f32; +88 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:88:5 + --> $DIR/cast.rs:89:5 | -88 | false as bool; +89 | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 75 previous errors +error: aborting due to 76 previous errors -- cgit 1.4.1-3-g733a5 From 396cfa70551a80570e3e305ca15ab9589319b49a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 5 Sep 2017 04:05:26 -0700 Subject: Only strip parens for binary expressions. --- clippy_lints/src/types.rs | 11 ++++- tests/ui/cast.rs | 1 - tests/ui/cast.stderr | 104 ++++++++++++++++++++++------------------------ 3 files changed, 59 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e01ec291d5d..f166d6c227c 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -580,12 +580,21 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t ); } +fn should_strip_parens(op: &Expr, snip: &str) -> bool { + if let ExprBinary(_, _, _) = op.node { + if snip.starts_with('(') && snip.ends_with(')') { + return true; + } + } + false +} + fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. let opt = snippet_opt(cx, op.span); let sugg = if let Some(ref snip) = opt { - if snip.starts_with('(') && snip.ends_with(')') { + if should_strip_parens(op, snip) { &snip[1..snip.len()-1] } else { snip.as_str() diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 54012923df4..82427c128e4 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -59,7 +59,6 @@ fn main() { 1.0f32 as f64; // Test cast_lossless with an expression wrapped in parens (1u8 + 1u8) as u16; - (1u16) + (1u8) as u16; // Test cast_sign_loss 1i32 as u32; 1isize as usize; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 93c5aad0c59..8787083b429 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -314,157 +314,151 @@ error: casting u8 to u16 may become silently lossy if types change 61 | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` -error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:62:14 - | -62 | (1u16) + (1u8) as u16; - | ^^^^^^^^^^^^ help: try: `u16::from(1u8)` - error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:64:5 + --> $DIR/cast.rs:63:5 | -64 | 1i32 as u32; +63 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:65:5 + --> $DIR/cast.rs:64:5 | -65 | 1isize as usize; +64 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting isize to i8 may truncate the value - --> $DIR/cast.rs:68:5 + --> $DIR/cast.rs:67:5 | -68 | 1isize as i8; +67 | 1isize as i8; | ^^^^^^^^^^^^ error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:69:5 + --> $DIR/cast.rs:68:5 | -69 | 1isize as f64; +68 | 1isize as f64; | ^^^^^^^^^^^^^ error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:70:5 + --> $DIR/cast.rs:69:5 | -70 | 1usize as f64; +69 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:71:5 + --> $DIR/cast.rs:70:5 | -71 | 1isize as f32; +70 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:72:5 + --> $DIR/cast.rs:71:5 | -72 | 1usize as f32; +71 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:72:5 | -73 | 1isize as i32; +72 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast.rs:74:5 + --> $DIR/cast.rs:73:5 | -74 | 1isize as u32; +73 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:74:5 + --> $DIR/cast.rs:73:5 | -74 | 1isize as u32; +73 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:75:5 + --> $DIR/cast.rs:74:5 | -75 | 1usize as u32; +74 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:76:5 + --> $DIR/cast.rs:75:5 | -76 | 1usize as i32; +75 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:76:5 + --> $DIR/cast.rs:75:5 | -76 | 1usize as i32; +75 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:78:5 + --> $DIR/cast.rs:77:5 | -78 | 1i64 as isize; +77 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast.rs:79:5 + --> $DIR/cast.rs:78:5 | -79 | 1i64 as usize; +78 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:79:5 + --> $DIR/cast.rs:78:5 | -79 | 1i64 as usize; +78 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:80:5 + --> $DIR/cast.rs:79:5 | -80 | 1u64 as isize; +79 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:80:5 + --> $DIR/cast.rs:79:5 | -80 | 1u64 as isize; +79 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:81:5 + --> $DIR/cast.rs:80:5 | -81 | 1u64 as usize; +80 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:82:5 + --> $DIR/cast.rs:81:5 | -82 | 1u32 as isize; +81 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast.rs:85:5 + --> $DIR/cast.rs:84:5 | -85 | 1i32 as usize; +84 | 1i32 as usize; | ^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:87:5 + --> $DIR/cast.rs:86:5 | -87 | 1i32 as i32; +86 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:88:5 + --> $DIR/cast.rs:87:5 | -88 | 1f32 as f32; +87 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:89:5 + --> $DIR/cast.rs:88:5 | -89 | false as bool; +88 | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 76 previous errors +error: aborting due to 75 previous errors -- cgit 1.4.1-3-g733a5 From 7e9ba81297936a20f0894749243073d38e2eb657 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 5 Sep 2017 12:10:53 -0700 Subject: for loops -> for-loops --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6cf2b1d9fed..0ed8debfa1e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -20,7 +20,7 @@ use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_ span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; use utils::paths; -/// **What it does:** Checks for for loops that manually copy items between +/// **What it does:** Checks for for-loops that manually copy items between /// slices that could be optimized by having a memcpy. /// /// **Why is this bad?** It is not as fast as a memcpy. -- cgit 1.4.1-3-g733a5 From 8c824e4cbc3ad5933724da1bea069fe5824551c1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Sep 2017 11:25:20 +0200 Subject: Also ignore `continue` statements in `is_unit_expr` --- clippy_lints/src/is_unit_expr.rs | 11 ++++++++--- tests/ui/is_unit_expr.rs | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 152612bd8ff..58df45ad89a 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -98,6 +98,7 @@ impl EarlyLintPass for UnitExpr { } } } + fn is_unit_expr(expr: &Expr) -> Option { match expr.node { ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { @@ -139,9 +140,13 @@ fn check_last_stmt_in_block(block: &Block) -> bool { // like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, - StmtKind::Semi(ref expr) => match expr.node { - ExprKind::Break(_, _) | ExprKind::Ret(_) => false, - _ => true, + StmtKind::Semi(ref expr) => { + match expr.node { + ExprKind::Break(_, _) | + ExprKind::Continue(_) | + ExprKind::Ret(_) => false, + _ => true, + } }, _ => true, } diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index d1f45d517b0..164e391ff24 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -45,4 +45,29 @@ fn main() { 0; }, }; + + loop { + let a2 = match a1 { + Some(x) => x, + _ => { + break; + }, + }; + let a2 = match a1 { + Some(x) => x, + _ => { + continue; + }, + }; + } +} + +pub fn foo() -> i32 { + let a2 = match None { + Some(x) => x, + _ => { + return 42; + }, + }; + 55 } -- cgit 1.4.1-3-g733a5 From 7489a84c6a72d37c71f13f51f125c96ac7cbf340 Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Tue, 5 Sep 2017 22:28:30 +0200 Subject: `while_let_loop` doesn't take into account break-with-value #1948 --- clippy_lints/src/loops.rs | 17 ++++++++++------- tests/ui/while_loop.rs | 10 ++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0ed8debfa1e..4452cee8613 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -392,7 +392,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && - is_break_expr(&arms[1].body) + is_simple_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { return; @@ -1500,13 +1500,16 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { } } -/// Return true if expr contains a single break expr (maybe within a block). -fn is_break_expr(expr: &Expr) -> bool { +/// Return true if expr contains a single break expr without destination label and +/// passed expression. The expression may be within a block. +fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { - ExprBreak(dest, _) if dest.ident.is_none() => true, - ExprBlock(ref b) => match extract_first_expr(b) { - Some(subexpr) => is_break_expr(subexpr), - None => false, + ExprBreak(dest, ref passed_expr) if dest.ident.is_none() && passed_expr.is_none() => true, + ExprBlock(ref b) => { + match extract_first_expr(b) { + Some(subexpr) => is_simple_break_expr(subexpr), + None => false, + } }, _ => false, } diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 84873582609..b67c41621e6 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -183,4 +183,14 @@ fn refutable() { while let Some(v) = y.next() { // use a for loop here } } + + //should not trigger while_let_loop lint because break passes an expression + let a = Some(10); + let b = loop { + if let Some(c) = a { + break Some(c); + } else { + break None; + } + }; } -- cgit 1.4.1-3-g733a5 From 0ceba6bed6c4265bce7a1fe885dfee869dd90cde Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 5 Sep 2017 14:19:51 -0700 Subject: format comment --- tests/ui/while_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index b67c41621e6..9bae1bc48e6 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -184,7 +184,7 @@ fn refutable() { } } - //should not trigger while_let_loop lint because break passes an expression + // should not trigger while_let_loop lint because break passes an expression let a = Some(10); let b = loop { if let Some(c) = a { -- cgit 1.4.1-3-g733a5 From 0a238a48524640c0416132c83d1fab310f746ac8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 5 Sep 2017 15:10:41 -0700 Subject: Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bcd9e4dc9..0ce03bbfc79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## Upcoming * New lint: [`manual_memcpy`] +* [`cast_lossless`] no longer has redundant parentheses in its suggestions ## 0.0.157 - 2017-09-04 * Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* -- cgit 1.4.1-3-g733a5 From 78f6db907ca2ec3909e8e02f49df6d0c757f964f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 8 Sep 2017 12:28:31 +0200 Subject: Soft rustup (only fixed some tests) --- Cargo.lock | 92 ++++++++++++++++++++++++------------------------ tests/ui/booleans.stderr | 14 +------- 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e23a7e75d5..40385f6db25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,16 @@ [root] name = "clippy_lints" -version = "0.0.152" +version = "0.0.157" dependencies = [ - "itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -25,14 +25,14 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -42,8 +42,8 @@ name = "backtrace-sys" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -61,9 +61,9 @@ name = "cargo_metadata" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -73,17 +73,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.152" +version = "0.0.157" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.152", - "compiletest_rs 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.157", + "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,7 +92,7 @@ version = "0.1.0" [[package]] name = "compiletest_rs" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -110,7 +110,7 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -134,22 +134,22 @@ name = "error-chain" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -181,7 +181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.29" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -199,7 +199,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -234,7 +234,7 @@ version = "0.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -289,12 +289,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -313,13 +313,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -328,7 +328,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -364,7 +364,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -407,26 +407,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" +"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" "checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum compiletest_rs 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc4720203de7b490e2808cad3e9090e8850eed4ecd4176b246551a952f4ead7" +"checksum compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2741d378feb7a434dba54228c89a70b4e427fee521de67cdda3750b8a0265f5a" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" -"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e58359414720377f59889192f1ec0e726049ce5735bc21fdb0c4c8ae638305bb" -"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" +"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" +"checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" +"checksum itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac17257442c2ed77dbc9fd555cf83c58b0c7f7d0e8f2ae08c0ac05c72842e1f6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264" +"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" @@ -442,10 +442,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" -"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" +"checksum serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7f61b753dd58ec5d4c735f794dbddde1f28b977f652afbcde89d75bc77902216" +"checksum serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2a169fa5384d751ada1da9f3992b81830151a03c875e40dcb37c9fb31aafc68f" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index a15267f2263..a76eb7a5cc0 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -49,18 +49,6 @@ error: this boolean expression can be simplified 18 | let _ = false || a; | ^^^^^^^^^^ help: try: `a` -error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:20:13 - | -20 | let _ = cfg!(you_shall_not_not_pass) && a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: it would look like the following: `false` - | -help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:20:45 - | -20 | let _ = cfg!(you_shall_not_not_pass) && a; - | ^ - error: this boolean expression can be simplified --> $DIR/booleans.rs:23:13 | @@ -142,5 +130,5 @@ help: try 39 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 8adc42b5b4a51e635644a17b30aaea04fc563277 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 9 Sep 2017 01:23:08 -0400 Subject: Update for latest Rust This is mainly due to https://github.com/rust-lang/rust/commit/dead08cb33134 --- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/eq_op.rs | 24 ++++++++++++------------ clippy_lints/src/methods.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/should_assert_eq.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/inspector.rs | 8 ++++---- clippy_lints/src/utils/mod.rs | 12 ++++++------ 12 files changed, 32 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index ecb12b60a16..db57864cb2f 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -307,7 +307,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { cx.tcx.mir_const_qualif(def_id); cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id)) } else { - cx.tcx.sess.cstore.item_body(cx.tcx, def_id) + cx.tcx.extern_const_body(def_id) }; fetch_int_literal(cx, &body.value) }) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index de62990afd5..d50cb05576f 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -297,7 +297,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { self.tcx.mir_const_qualif(def_id); self.tcx.hir.body(self.tcx.hir.body_owned_by(id)) } else { - self.tcx.sess.cstore.item_body(self.tcx, def_id) + self.tcx.extern_const_body(def_id) }; let ret = cx.expr(&body.value); if ret.is_some() { diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index b70e591f995..5baaa4bd59d 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -93,7 +93,7 @@ fn check_hash_peq<'a, 'tcx>( ) { if_let_chain! {[ match_path(&trait_ref.path, &paths::HASH), - let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait() + let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait() ], { // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 2c268c18835..dbe0d68ad69 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -63,20 +63,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { return; } let (trait_id, requires_ref) = match op.node { - BiAdd => (cx.tcx.lang_items.add_trait(), false), - BiSub => (cx.tcx.lang_items.sub_trait(), false), - BiMul => (cx.tcx.lang_items.mul_trait(), false), - BiDiv => (cx.tcx.lang_items.div_trait(), false), - BiRem => (cx.tcx.lang_items.rem_trait(), false), + BiAdd => (cx.tcx.lang_items().add_trait(), false), + BiSub => (cx.tcx.lang_items().sub_trait(), false), + BiMul => (cx.tcx.lang_items().mul_trait(), false), + BiDiv => (cx.tcx.lang_items().div_trait(), false), + BiRem => (cx.tcx.lang_items().rem_trait(), false), // don't lint short circuiting ops BiAnd | BiOr => return, - BiBitXor => (cx.tcx.lang_items.bitxor_trait(), false), - BiBitAnd => (cx.tcx.lang_items.bitand_trait(), false), - BiBitOr => (cx.tcx.lang_items.bitor_trait(), false), - BiShl => (cx.tcx.lang_items.shl_trait(), false), - BiShr => (cx.tcx.lang_items.shr_trait(), false), - BiNe | BiEq => (cx.tcx.lang_items.eq_trait(), true), - BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items.ord_trait(), true), + BiBitXor => (cx.tcx.lang_items().bitxor_trait(), false), + BiBitAnd => (cx.tcx.lang_items().bitand_trait(), false), + BiBitOr => (cx.tcx.lang_items().bitor_trait(), false), + BiShl => (cx.tcx.lang_items().shl_trait(), false), + BiShr => (cx.tcx.lang_items().shr_trait(), false), + BiNe | BiEq => (cx.tcx.lang_items().eq_trait(), true), + BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items().ord_trait(), true), }; if let Some(trait_id) = trait_id { #[allow(match_same_arms)] diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 84c213023a2..74719d006d0 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1302,7 +1302,7 @@ fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option> { /// This checks whether a given type is known to implement Debug. fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { - match cx.tcx.lang_items.debug_trait() { + match cx.tcx.lang_items().debug_trait() { Some(debug) => implements_trait(cx, ty, debug, &[]), None => false, } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index da6919da93d..fcb29439a64 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -497,7 +497,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { }; let other_ty = cx.tables.expr_ty_adjusted(other); - let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() { + let partial_eq_trait_id = match cx.tcx.lang_items().eq_trait() { Some(id) => id, None => return, }; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f53e8521076..da3bfc7594c 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } // Allows these to be passed by value. - let fn_trait = need!(cx.tcx.lang_items.fn_trait()); + let fn_trait = need!(cx.tcx.lang_items().fn_trait()); let asref_trait = need!(get_trait_def_id(cx, &paths::ASREF_TRAIT)); let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 64b58b6e277..34f1e4bc493 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain! {[ let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node, !is_automatically_derived(&*item.attrs), - let Some(eq_trait) = cx.tcx.lang_items.eq_trait(), + let Some(eq_trait) = cx.tcx.lang_items().eq_trait(), trait_ref.path.def.def_id() == eq_trait ], { for impl_item in impl_items { diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs index b8cc6873adc..47e444c8c88 100644 --- a/clippy_lints/src/should_assert_eq.rs +++ b/clippy_lints/src/should_assert_eq.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq { let ExprUnary(UnOp::UnNot, ref cond) = cond.node, let ExprBinary(ref binop, ref expr1, ref expr2) = cond.node, is_direct_expn_of(e.span, "assert").is_some(), - let Some(debug_trait) = cx.tcx.lang_items.debug_trait(), + let Some(debug_trait) = cx.tcx.lang_items().debug_trait(), ], { let debug = is_expn_of(e.span, "debug_assert").map_or("", |_| "debug_"); let sugg = match binop.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f166d6c227c..6eb78d02d30 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -151,7 +151,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let hir_id = cx.tcx.hir.node_to_hir_id(ast_ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { - if Some(def_id) == cx.tcx.lang_items.owned_box() { + if Some(def_id) == cx.tcx.lang_items().owned_box() { let last = last_path_segment(qpath); if_let_chain! {[ !last.parameters.parenthesized, @@ -209,7 +209,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let def = cx.tables.qpath_def(qpath, hir_id); if_let_chain! {[ let Some(def_id) = opt_def_id(def), - Some(def_id) == cx.tcx.lang_items.owned_box(), + Some(def_id) == cx.tcx.lang_items().owned_box(), let QPath::Resolved(None, ref path) = *qpath, let [ref bx] = *path.segments, !bx.parameters.parenthesized, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index cdc8ce509b4..1713096ff2d 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -360,12 +360,12 @@ fn print_item(cx: &LateContext, item: &hir::Item) { } match item.node { hir::ItemExternCrate(ref _renamed_from) => { - if let Some(crate_id) = cx.tcx.sess.cstore.extern_mod_stmt_cnum(item.id) { - let source = cx.tcx.sess.cstore.used_crate_source(crate_id); - if let Some(src) = source.dylib { + if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(cx.tcx.hir.node_to_hir_id(item.id)) { + let source = cx.tcx.used_crate_source(crate_id); + if let Some(ref src) = source.dylib { println!("extern crate dylib source: {:?}", src.0); } - if let Some(src) = source.rlib { + if let Some(ref src) = source.rlib { println!("extern crate rlib source: {:?}", src.0); } } else { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 29fddeaa052..582cdae47b8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -15,6 +15,7 @@ use std::borrow::Cow; use std::env; use std::mem; use std::str::FromStr; +use std::rc::Rc; use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::codemap::{CompilerDesugaringKind, ExpnFormat, ExpnInfo, Span, DUMMY_SP}; @@ -277,18 +278,17 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { /// Get the definition associated to a path. pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { - let cstore = &cx.tcx.sess.cstore; - let crates = cstore.crates(); + let crates = cx.tcx.crates(); let krate = crates .iter() - .find(|&&krate| cstore.crate_name(krate) == path[0]); + .find(|&&krate| cx.tcx.crate_name(krate) == path[0]); if let Some(krate) = krate { let krate = DefId { krate: *krate, index: CRATE_DEF_INDEX, }; - let mut items = cstore.item_children(krate, cx.tcx.sess); + let mut items = cx.tcx.item_children(krate); let mut path_it = path.iter().skip(1).peekable(); loop { @@ -297,13 +297,13 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { None => return None, }; - for item in &mem::replace(&mut items, vec![]) { + for item in mem::replace(&mut items, Rc::new(vec![])).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return Some(item.def); } - items = cstore.item_children(item.def.def_id(), cx.tcx.sess); + items = cx.tcx.item_children(item.def.def_id()); break; } } -- cgit 1.4.1-3-g733a5 From edcf6e7e8044069f1b4f890248cb29d20bf8de35 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 9 Sep 2017 14:06:41 +0200 Subject: Use hir_id instead of fetching hir_id via the NodeId --- clippy_lints/src/utils/inspector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 1713096ff2d..e74f1639e4b 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -360,7 +360,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { } match item.node { hir::ItemExternCrate(ref _renamed_from) => { - if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(cx.tcx.hir.node_to_hir_id(item.id)) { + if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(item.hir_id) { let source = cx.tcx.used_crate_source(crate_id); if let Some(ref src) = source.dylib { println!("extern crate dylib source: {:?}", src.0); -- cgit 1.4.1-3-g733a5 From 81d32123f41070d6c2c5f7ffec6d78fc3859ba4f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 9 Sep 2017 14:37:16 +0200 Subject: Bump version --- CHANGELOG.md | 3 ++- Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce03bbfc79..49e576454ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. -## Upcoming +## 0.0.158 * New lint: [`manual_memcpy`] * [`cast_lossless`] no longer has redundant parentheses in its suggestions +* Update to *rustc 1.22.0-nightly (dead08cb3 2017-09-08)* ## 0.0.157 - 2017-09-04 * Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* diff --git a/Cargo.lock b/Cargo.lock index 40385f6db25..d4ce1aaa43d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.157" +version = "0.0.158" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,11 +73,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.157" +version = "0.0.158" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.157", + "clippy_lints 0.0.158", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 42323f27ad1..b078f0bc6df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.157" +version = "0.0.158" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.157", path = "clippy_lints" } +clippy_lints = { version = "0.0.158", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 8c7addf468c..153ef23d543 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.157" +version = "0.0.158" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From d318ced660bee68bac0c2c2810b45d747f673cee Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 9 Sep 2017 21:51:54 -0400 Subject: Add CLONE_ON_REF_PTR lint Closes issue #1645 --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/methods.rs | 48 ++++ clippy_lints/src/utils/paths.rs | 4 + tests/ui/methods.rs | 24 ++ tests/ui/methods.stderr | 512 +++++++++++++++++++++------------------- 5 files changed, 346 insertions(+), 244 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d50cb05576f..b1bd6b06ee4 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -171,7 +171,7 @@ pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut match *lit { LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), - LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), + LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, hint) => match (&ty.sty, hint) { (&ty::TyInt(ity), _) | (_, Signed(ity)) => { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 74719d006d0..90208369caa 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -310,6 +310,24 @@ declare_lint! { "using `clone` on a `Copy` type" } +/// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer, +/// (Rc, Arc, rc::Weak, or sync::Weak), and suggests calling Clone on +/// the corresponding trait instead. +/// +/// **Why is this bad?**: Calling '.clone()' on an Rc, Arc, or Weak +/// can obscure the fact that only the pointer is being cloned, not the underlying +/// data. +/// +/// **Example:** +/// ```rust +/// x.clone() +/// ``` +declare_lint! { + pub CLONE_ON_REF_PTR, + Warn, + "using 'clone' on a ref-counted pointer" +} + /// **What it does:** Checks for usage of `.clone()` on an `&&T`. /// /// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of @@ -539,6 +557,7 @@ impl LintPass for Pass { OR_FUN_CALL, CHARS_NEXT_CMP, CLONE_ON_COPY, + CLONE_ON_REF_PTR, CLONE_DOUBLE_REF, NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, @@ -615,6 +634,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let self_ty = cx.tables.expr_ty_adjusted(&args[0]); if args.len() == 1 && method_call.name == "clone" { lint_clone_on_copy(cx, expr, &args[0], self_ty); + lint_clone_on_ref_ptr(cx, expr, &args[0]); } match self_ty.sty { @@ -853,6 +873,34 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } } +fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { + let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(arg)); + + let caller_type = if match_type(cx, obj_ty, &paths::RC) { + "Rc" + } else if match_type(cx, obj_ty, &paths::ARC) { + "Arc" + } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { + "Weak" + } else { + return; + }; + + span_lint_and_sugg( + cx, + CLONE_ON_REF_PTR, + expr.span, + "using '.clone()' on a ref-counted pointer", + "try this", + format!("{}::clone(&{})", + caller_type, + snippet(cx, arg.span, "_") + ) + ); + +} + + fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { let arg = &args[1]; if let Some(arglists) = method_chain_args(arg, &["chars"]) { diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 9057920098e..d18a5af59e3 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -2,6 +2,7 @@ //! about. pub const ANY_TRAIT: [&'static str; 3] = ["std", "any", "Any"]; +pub const ARC: [&'static str; 3] = ["alloc", "arc", "Arc"]; pub const ASMUT_TRAIT: [&'static str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&'static str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&'static str; 3] = ["std", "panicking", "begin_panic"]; @@ -58,6 +59,7 @@ pub const RANGE_TO: [&'static str; 3] = ["core", "ops", "RangeTo"]; pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclusive"]; pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; +pub const RC: [&'static str; 3] = ["alloc", "rc", "Rc"]; pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; @@ -81,3 +83,5 @@ pub const TRY_INTO_RESULT: [&'static str; 4] = ["std", "ops", "Try", "into_resul pub const VEC: [&'static str; 3] = ["alloc", "vec", "Vec"]; pub const VEC_DEQUE: [&'static str; 3] = ["alloc", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&'static str; 3] = ["alloc", "vec", "from_elem"]; +pub const WEAK_ARC: [&'static str; 3] = ["alloc", "arc", "Weak"]; +pub const WEAK_RC: [&'static str; 3] = ["alloc", "rc", "Weak"]; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index a9716d4e7b4..3bbaff29c98 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -11,6 +11,8 @@ use std::collections::HashSet; use std::collections::VecDeque; use std::ops::Mul; use std::iter::FromIterator; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; struct T; @@ -456,6 +458,28 @@ fn clone_on_copy() { (&42).clone(); } +fn clone_on_ref_ptr() { + let rc = Rc::new(true); + let arc = Arc::new(true); + + let rcweak = Rc::downgrade(&rc); + let arc_weak = Arc::downgrade(&arc); + + rc.clone(); + Rc::clone(&rc); + + arc.clone(); + Arc::clone(&arc); + + rcweak.clone(); + rc::Weak::clone(&rcweak); + + arc_weak.clone(); + sync::Weak::clone(&arc_weak); + + +} + fn clone_on_copy_generic(t: T) { t.clone(); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 8570dccd0fe..e22fdc116c1 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,716 +1,742 @@ error: unnecessary structure name repetition - --> $DIR/methods.rs:18:25 + --> $DIR/methods.rs:20:25 | -18 | fn add(self, other: T) -> T { self } +20 | fn add(self, other: T) -> T { self } | ^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:18:31 + --> $DIR/methods.rs:20:31 | -18 | fn add(self, other: T) -> T { self } +20 | fn add(self, other: T) -> T { self } | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:21:26 + --> $DIR/methods.rs:23:26 | -21 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +23 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:21:33 + --> $DIR/methods.rs:23:33 | -21 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +23 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:22:21 + --> $DIR/methods.rs:24:21 | -22 | fn div(self) -> T { self } // no error, different #arguments +24 | fn div(self) -> T { self } // no error, different #arguments | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:23:25 + --> $DIR/methods.rs:25:25 | -23 | fn rem(self, other: T) { } // no error, wrong return type +25 | fn rem(self, other: T) { } // no error, wrong return type | ^ help: use the applicable keyword: `Self` error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:18:5 + --> $DIR/methods.rs:20:5 | -18 | fn add(self, other: T) -> T { self } +20 | fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D should-implement-trait` implied by `-D warnings` error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name - --> $DIR/methods.rs:19:5 + --> $DIR/methods.rs:21:5 | -19 | fn drop(&mut self) { } +21 | fn drop(&mut self) { } | ^^^^^^^^^^^^^^^^^^^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:26:17 + --> $DIR/methods.rs:28:17 | -26 | fn into_u16(&self) -> u16 { 0 } +28 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:28:21 + --> $DIR/methods.rs:30:21 | -28 | fn to_something(self) -> u32 { 0 } +30 | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:30:12 + --> $DIR/methods.rs:32:12 | -30 | fn new(self) {} +32 | fn new(self) {} | ^^^^ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:30:5 + --> $DIR/methods.rs:32:5 | -30 | fn new(self) {} +32 | fn new(self) {} | ^^^^^^^^^^^^^^^ | = note: `-D new-ret-no-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:74:24 + --> $DIR/methods.rs:76:24 | -74 | fn new() -> Option> { None } +76 | fn new() -> Option> { None } | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:78:19 + --> $DIR/methods.rs:80:19 | -78 | type Output = T; +80 | type Output = T; | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:79:25 + --> $DIR/methods.rs:81:25 | -79 | fn mul(self, other: T) -> T { self } // no error, obviously +81 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:79:31 + --> $DIR/methods.rs:81:31 | -79 | fn mul(self, other: T) -> T { self } // no error, obviously +81 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:97:13 - | -97 | let _ = opt.map(|x| x + 1) - | _____________^ -98 | | -99 | | .unwrap_or(0); // should lint even though this call is on a separate line - | |____________________________^ - | - = note: `-D option-map-unwrap-or` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` + --> $DIR/methods.rs:99:13 + | +99 | let _ = opt.map(|x| x + 1) + | _____________^ +100 | | +101 | | .unwrap_or(0); // should lint even though this call is on a separate line + | |____________________________^ + | + = note: `-D option-map-unwrap-or` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:101:13 + --> $DIR/methods.rs:103:13 | -101 | let _ = opt.map(|x| { +103 | let _ = opt.map(|x| { | _____________^ -102 | | x + 1 -103 | | } -104 | | ).unwrap_or(0); +104 | | x + 1 +105 | | } +106 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:105:13 + --> $DIR/methods.rs:107:13 | -105 | let _ = opt.map(|x| x + 1) +107 | let _ = opt.map(|x| x + 1) | _____________^ -106 | | .unwrap_or({ -107 | | 0 -108 | | }); +108 | | .unwrap_or({ +109 | | 0 +110 | | }); | |__________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:114:13 + --> $DIR/methods.rs:116:13 | -114 | let _ = opt.map(|x| x + 1) +116 | let _ = opt.map(|x| x + 1) | _____________^ -115 | | -116 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +117 | | +118 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:118:13 + --> $DIR/methods.rs:120:13 | -118 | let _ = opt.map(|x| { +120 | let _ = opt.map(|x| { | _____________^ -119 | | x + 1 -120 | | } -121 | | ).unwrap_or_else(|| 0); +121 | | x + 1 +122 | | } +123 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:122:13 + --> $DIR/methods.rs:124:13 | -122 | let _ = opt.map(|x| x + 1) +124 | let _ = opt.map(|x| x + 1) | _____________^ -123 | | .unwrap_or_else(|| -124 | | 0 -125 | | ); +125 | | .unwrap_or_else(|| +126 | | 0 +127 | | ); | |_________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:151:24 + --> $DIR/methods.rs:153:24 | -151 | fn filter(self) -> IteratorFalsePositives { +153 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:155:22 + --> $DIR/methods.rs:157:22 | -155 | fn next(self) -> IteratorFalsePositives { +157 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:175:32 + --> $DIR/methods.rs:177:32 | -175 | fn skip(self, _: usize) -> IteratorFalsePositives { +177 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:194:13 + --> $DIR/methods.rs:196:13 | -194 | let _ = v.iter().filter(|&x| *x < 0).next(); +196 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:197:13 + --> $DIR/methods.rs:199:13 | -197 | let _ = v.iter().filter(|&x| { +199 | let _ = v.iter().filter(|&x| { | _____________^ -198 | | *x < 0 -199 | | } -200 | | ).next(); +200 | | *x < 0 +201 | | } +202 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:212:13 + --> $DIR/methods.rs:214:13 | -212 | let _ = v.iter().find(|&x| *x < 0).is_some(); +214 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:215:13 + --> $DIR/methods.rs:217:13 | -215 | let _ = v.iter().find(|&x| { +217 | let _ = v.iter().find(|&x| { | _____________^ -216 | | *x < 0 -217 | | } -218 | | ).is_some(); +218 | | *x < 0 +219 | | } +220 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:221:13 + --> $DIR/methods.rs:223:13 | -221 | let _ = v.iter().position(|&x| x < 0).is_some(); +223 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:224:13 + --> $DIR/methods.rs:226:13 | -224 | let _ = v.iter().position(|&x| { +226 | let _ = v.iter().position(|&x| { | _____________^ -225 | | x < 0 -226 | | } -227 | | ).is_some(); +227 | | x < 0 +228 | | } +229 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:230:13 + --> $DIR/methods.rs:232:13 | -230 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +232 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:233:13 + --> $DIR/methods.rs:235:13 | -233 | let _ = v.iter().rposition(|&x| { +235 | let _ = v.iter().rposition(|&x| { | _____________^ -234 | | x < 0 -235 | | } -236 | | ).is_some(); +236 | | x < 0 +237 | | } +238 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:250:21 + --> $DIR/methods.rs:252:21 | -250 | fn new() -> Foo { Foo } +252 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:268:5 + --> $DIR/methods.rs:270:5 | -268 | with_constructor.unwrap_or(make()); +270 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:271:5 + --> $DIR/methods.rs:273:5 | -271 | with_new.unwrap_or(Vec::new()); +273 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:274:5 + --> $DIR/methods.rs:276:5 | -274 | with_const_args.unwrap_or(Vec::with_capacity(12)); +276 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:277:5 + --> $DIR/methods.rs:279:5 | -277 | with_err.unwrap_or(make()); +279 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:280:5 + --> $DIR/methods.rs:282:5 | -280 | with_err_args.unwrap_or(Vec::with_capacity(12)); +282 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:283:5 + --> $DIR/methods.rs:285:5 | -283 | with_default_trait.unwrap_or(Default::default()); +285 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:286:5 + --> $DIR/methods.rs:288:5 | -286 | with_default_type.unwrap_or(u64::default()); +288 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:289:5 + --> $DIR/methods.rs:291:5 | -289 | with_vec.unwrap_or(vec![]); +291 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:294:5 + --> $DIR/methods.rs:296:5 | -294 | without_default.unwrap_or(Foo::new()); +296 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:297:5 + --> $DIR/methods.rs:299:5 | -297 | map.entry(42).or_insert(String::new()); +299 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:300:5 + --> $DIR/methods.rs:302:5 | -300 | btree.entry(42).or_insert(String::new()); +302 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:303:13 + --> $DIR/methods.rs:305:13 | -303 | let _ = stringy.unwrap_or("".to_owned()); +305 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:314:23 + --> $DIR/methods.rs:316:23 | -314 | let bad_vec = some_vec.iter().nth(3); +316 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:315:26 + --> $DIR/methods.rs:317:26 | -315 | let bad_slice = &some_vec[..].iter().nth(3); +317 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:316:31 + --> $DIR/methods.rs:318:31 | -316 | let bad_boxed_slice = boxed_slice.iter().nth(3); +318 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:317:29 + --> $DIR/methods.rs:319:29 | -317 | let bad_vec_deque = some_vec_deque.iter().nth(3); +319 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:322:23 + --> $DIR/methods.rs:324:23 | -322 | let bad_vec = some_vec.iter_mut().nth(3); +324 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:325:26 + --> $DIR/methods.rs:327:26 | -325 | let bad_slice = &some_vec[..].iter_mut().nth(3); +327 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:328:29 + --> $DIR/methods.rs:330:29 | -328 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +330 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:340:13 + --> $DIR/methods.rs:342:13 | -340 | let _ = some_vec.iter().skip(42).next(); +342 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:341:13 + --> $DIR/methods.rs:343:13 | -341 | let _ = some_vec.iter().cycle().skip(42).next(); +343 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:342:13 + --> $DIR/methods.rs:344:13 | -342 | let _ = (1..10).skip(10).next(); +344 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:343:14 + --> $DIR/methods.rs:345:14 | -343 | let _ = &some_vec[..].iter().skip(3).next(); +345 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:369:17 + --> $DIR/methods.rs:371:17 | -369 | let _ = boxed_slice.get(1).unwrap(); +371 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:370:17 + --> $DIR/methods.rs:372:17 | -370 | let _ = some_slice.get(0).unwrap(); +372 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:371:17 + --> $DIR/methods.rs:373:17 | -371 | let _ = some_vec.get(0).unwrap(); +373 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:372:17 + --> $DIR/methods.rs:374:17 | -372 | let _ = some_vecdeque.get(0).unwrap(); +374 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:373:17 + --> $DIR/methods.rs:375:17 | -373 | let _ = some_hashmap.get(&1).unwrap(); +375 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:374:17 + --> $DIR/methods.rs:376:17 | -374 | let _ = some_btreemap.get(&1).unwrap(); +376 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:379:10 + --> $DIR/methods.rs:381:10 | -379 | *boxed_slice.get_mut(0).unwrap() = 1; +381 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:380:10 + --> $DIR/methods.rs:382:10 | -380 | *some_slice.get_mut(0).unwrap() = 1; +382 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:381:10 + --> $DIR/methods.rs:383:10 | -381 | *some_vec.get_mut(0).unwrap() = 1; +383 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:382:10 + --> $DIR/methods.rs:384:10 | -382 | *some_vecdeque.get_mut(0).unwrap() = 1; +384 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:396:13 + --> $DIR/methods.rs:398:13 | -396 | let _ = opt.unwrap(); +398 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:399:13 + --> $DIR/methods.rs:401:13 | -399 | let _ = res.unwrap(); +401 | let _ = res.unwrap(); | ^^^^^^^^^^^^ | = note: `-D result-unwrap-used` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:401:5 + --> $DIR/methods.rs:403:5 | -401 | res.ok().expect("disaster!"); +403 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:407:5 + --> $DIR/methods.rs:409:5 | -407 | res3.ok().expect("whoof"); +409 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:409:5 + --> $DIR/methods.rs:411:5 | -409 | res4.ok().expect("argh"); +411 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:411:5 + --> $DIR/methods.rs:413:5 | -411 | res5.ok().expect("oops"); +413 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:413:5 + --> $DIR/methods.rs:415:5 | -413 | res6.ok().expect("meh"); +415 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `starts_with` method - --> $DIR/methods.rs:425:5 + --> $DIR/methods.rs:427:5 | -425 | "".chars().next() == Some(' '); +427 | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | = note: `-D chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/methods.rs:426:5 + --> $DIR/methods.rs:428:5 | -426 | Some(' ') != "".chars().next(); +428 | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:435:5 + --> $DIR/methods.rs:437:5 | -435 | s.extend(abc.chars()); +437 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:438:5 + --> $DIR/methods.rs:440:5 | -438 | s.extend("abc".chars()); +440 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:441:5 + --> $DIR/methods.rs:443:5 | -441 | s.extend(def.chars()); +443 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:452:5 + --> $DIR/methods.rs:454:5 | -452 | 42.clone(); +454 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:456:5 + --> $DIR/methods.rs:458:5 | -456 | (&42).clone(); +458 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` +error: using '.clone()' on a ref-counted pointer + --> $DIR/methods.rs:468:5 + | +468 | rc.clone(); + | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` + | + = note: `-D clone-on-ref-ptr` implied by `-D warnings` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/methods.rs:471:5 + | +471 | arc.clone(); + | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/methods.rs:474:5 + | +474 | rcweak.clone(); + | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/methods.rs:477:5 + | +477 | arc_weak.clone(); + | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` + error: using `clone` on a `Copy` type - --> $DIR/methods.rs:460:5 + --> $DIR/methods.rs:484:5 | -460 | t.clone(); +484 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:462:5 + --> $DIR/methods.rs:486:5 | -462 | Some(t).clone(); +486 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:468:22 + --> $DIR/methods.rs:492:22 | -468 | let z: &Vec<_> = y.clone(); +492 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` | = note: `-D clone-double-ref` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:475:13 + --> $DIR/methods.rs:499:13 | -475 | x.split("x"); +499 | x.split("x"); | --------^^^- help: try using a char instead: `x.split('x')` | = note: `-D single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:492:16 + --> $DIR/methods.rs:516:16 | -492 | x.contains("x"); +516 | x.contains("x"); | -----------^^^- help: try using a char instead: `x.contains('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:493:19 + --> $DIR/methods.rs:517:19 | -493 | x.starts_with("x"); +517 | x.starts_with("x"); | --------------^^^- help: try using a char instead: `x.starts_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:494:17 + --> $DIR/methods.rs:518:17 | -494 | x.ends_with("x"); +518 | x.ends_with("x"); | ------------^^^- help: try using a char instead: `x.ends_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:495:12 + --> $DIR/methods.rs:519:12 | -495 | x.find("x"); +519 | x.find("x"); | -------^^^- help: try using a char instead: `x.find('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:496:13 + --> $DIR/methods.rs:520:13 | -496 | x.rfind("x"); +520 | x.rfind("x"); | --------^^^- help: try using a char instead: `x.rfind('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:497:14 + --> $DIR/methods.rs:521:14 | -497 | x.rsplit("x"); +521 | x.rsplit("x"); | ---------^^^- help: try using a char instead: `x.rsplit('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:498:24 + --> $DIR/methods.rs:522:24 | -498 | x.split_terminator("x"); +522 | x.split_terminator("x"); | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:499:25 + --> $DIR/methods.rs:523:25 | -499 | x.rsplit_terminator("x"); +523 | x.rsplit_terminator("x"); | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:500:17 + --> $DIR/methods.rs:524:17 | -500 | x.splitn(0, "x"); +524 | x.splitn(0, "x"); | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:501:18 + --> $DIR/methods.rs:525:18 | -501 | x.rsplitn(0, "x"); +525 | x.rsplitn(0, "x"); | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:502:15 + --> $DIR/methods.rs:526:15 | -502 | x.matches("x"); +526 | x.matches("x"); | ----------^^^- help: try using a char instead: `x.matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:503:16 + --> $DIR/methods.rs:527:16 | -503 | x.rmatches("x"); +527 | x.rmatches("x"); | -----------^^^- help: try using a char instead: `x.rmatches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:504:21 + --> $DIR/methods.rs:528:21 | -504 | x.match_indices("x"); +528 | x.match_indices("x"); | ----------------^^^- help: try using a char instead: `x.match_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:505:22 + --> $DIR/methods.rs:529:22 | -505 | x.rmatch_indices("x"); +529 | x.rmatch_indices("x"); | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:506:25 + --> $DIR/methods.rs:530:25 | -506 | x.trim_left_matches("x"); +530 | x.trim_left_matches("x"); | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:507:26 + --> $DIR/methods.rs:531:26 | -507 | x.trim_right_matches("x"); +531 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:517:5 + --> $DIR/methods.rs:541:5 | -517 | CString::new("foo").unwrap().as_ptr(); +541 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:517:5 + --> $DIR/methods.rs:541:5 | -517 | CString::new("foo").unwrap().as_ptr(); +541 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:522:27 + --> $DIR/methods.rs:546:27 | -522 | let v2 : Vec = v.iter().cloned().collect(); +546 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: aborting due to 103 previous errors +error: aborting due to 107 previous errors -- cgit 1.4.1-3-g733a5 From e7e8e790206a94ae96f7c6af944f789b77c7b93d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 10 Sep 2017 19:32:24 +0200 Subject: suggestion for ptr_arg --- clippy_lints/src/ptr.rs | 30 ++++++++++++++++++++++++------ clippy_lints/src/utils/mod.rs | 9 +++++++++ tests/ui/ptr_arg.stderr | 12 ++++++------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f12ec039f73..4d119c3a42d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -7,7 +7,8 @@ use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_qpath, match_type, paths, span_lint, span_lint_and_then}; +use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, + span_lint_and_sugg, walk_ptrs_hir_ty}; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless @@ -137,20 +138,37 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { ) = ty.sty { if match_type(cx, ty, &paths::VEC) { - span_lint( + let mut ty_snippet = None; + if_let_chain!([ + let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node, + let Some(&PathSegment{ref parameters, ..}) = path.segments.last(), + parameters.types.len() == 1, + ], { + ty_snippet = snippet_opt(cx, parameters.types[0].span); + }); + //TODO: Suggestion + span_lint_and_then( cx, PTR_ARG, arg.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`", + with non-Vec-based slices.", + |db| { + if let Some(ref snippet) = ty_snippet { + db.span_suggestion(arg.span, + "change this to", + format!("&[{}]", snippet)); + } + } ); } else if match_type(cx, ty, &paths::STRING) { - span_lint( + span_lint_and_sugg( cx, PTR_ARG, arg.span, - "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`", + "writing `&String` instead of `&str` involves a new object where a slice will do.", + "change this to", + "&str".to_string() ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 582cdae47b8..8e816ffbfa4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -645,6 +645,15 @@ pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(S db.suggestions.push(sugg); } +/// Return the base type for HIR references and pointers. +pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { + match ty.node { + TyPtr(ref mut_ty) | + TyRptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + _ => ty + } +} + /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: Ty) -> Ty { match ty.sty { diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index bc5ca11155f..4eafc237a82 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,22 +1,22 @@ -error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. Consider changing the type to `&[...]` +error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:6:14 | 6 | fn do_vec(x: &Vec) { - | ^^^^^^^^^ + | ^^^^^^^^^ help: change this to: `&[i64]` | = note: `-D ptr-arg` implied by `-D warnings` -error: writing `&String` instead of `&str` involves a new object where a slice will do. Consider changing the type to `&str` +error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:14:14 | 14 | fn do_str(x: &String) { - | ^^^^^^^ + | ^^^^^^^ help: change this to: `&str` -error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. Consider changing the type to `&[...]` +error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:27:18 | 27 | fn do_vec(x: &Vec); - | ^^^^^^^^^ + | ^^^^^^^^^ help: change this to: `&[i64]` error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 36cd745640fdfa3f3305d22ada3598a268977578 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 12 Sep 2017 14:25:58 +0200 Subject: Regressions (#2041) --- tests/ui/format.stderr | 14 +--- tests/ui/matches.stderr | 129 ++++++++++++++++++++++++++++++++++++- tests/ui/print_with_newline.stderr | 28 -------- 3 files changed, 129 insertions(+), 42 deletions(-) diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index d2c9f393831..5f5bdc02a59 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,17 +6,5 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` -error: useless use of `format!` - --> $DIR/format.rs:8:5 - | -8 | format!("{}", "foo"); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: useless use of `format!` - --> $DIR/format.rs:15:5 - | -15 | format!("{}", arg); - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 29a558aef92..2f55428cca7 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -249,6 +249,25 @@ error: Err(_) will match all errors, maybe not a good idea = note: `-D match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error seperately or use unreachable macro +error: this `match` has identical arm bodies + --> $DIR/matches.rs:239:18 + | +239 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | + = note: `-D match-same-arms` implied by `-D warnings` +note: same as this + --> $DIR/matches.rs:238:18 + | +238 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:238:18 + | +238 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:246:9 | @@ -257,6 +276,24 @@ error: Err(_) will match all errors, maybe not a good idea | = note: to remove this warning, match each error seperately or use unreachable macro +error: this `match` has identical arm bodies + --> $DIR/matches.rs:245:18 + | +245 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:244:18 + | +244 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:244:18 + | +244 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:252:9 | @@ -265,5 +302,95 @@ error: Err(_) will match all errors, maybe not a good idea | = note: to remove this warning, match each error seperately or use unreachable macro -error: aborting due to 26 previous errors +error: this `match` has identical arm bodies + --> $DIR/matches.rs:251:18 + | +251 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:250:18 + | +250 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:250:18 + | +250 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: this `match` has identical arm bodies + --> $DIR/matches.rs:258:18 + | +258 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:257:18 + | +257 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:257:18 + | +257 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: this `match` has identical arm bodies + --> $DIR/matches.rs:265:18 + | +265 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:264:18 + | +264 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:264:18 + | +264 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: this `match` has identical arm bodies + --> $DIR/matches.rs:271:18 + | +271 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:270:18 + | +270 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:270:18 + | +270 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: this `match` has identical arm bodies + --> $DIR/matches.rs:277:18 + | +277 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:276:18 + | +276 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:276:18 + | +276 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: aborting due to 33 previous errors diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 1bacc40bfb4..e69de29bb2d 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,28 +0,0 @@ -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:6:5 - | -6 | print!("Hello/n"); - | ^^^^^^^^^^^^^^^^^^ - | - = note: `-D print-with-newline` implied by `-D warnings` - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:7:5 - | -7 | print!("Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:8:5 - | -8 | print!("Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:9:5 - | -9 | print!("{}/n", 1265); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -- cgit 1.4.1-3-g733a5 From b127ad251fa44ce5faab8e043948bdad73e2a7ab Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 12 Sep 2017 14:26:40 +0200 Subject: Rustup --- Cargo.lock | 30 ++--- clippy_lints/src/attrs.rs | 9 +- clippy_lints/src/drop_forget_ref.rs | 4 +- clippy_lints/src/eval_order_dependence.rs | 54 ++++----- clippy_lints/src/format.rs | 8 +- clippy_lints/src/functions.rs | 26 +++-- clippy_lints/src/let_if_seq.rs | 24 ++-- clippy_lints/src/loops.rs | 49 ++++----- clippy_lints/src/mem_forget.rs | 19 ++-- clippy_lints/src/minmax.rs | 20 ++-- clippy_lints/src/misc.rs | 6 +- clippy_lints/src/needless_pass_by_value.rs | 25 ++--- clippy_lints/src/panic.rs | 5 +- clippy_lints/src/print.rs | 18 ++- clippy_lints/src/regex.rs | 4 +- clippy_lints/src/transmute.rs | 171 +++++++++++++++-------------- clippy_lints/src/utils/higher.rs | 8 +- clippy_lints/src/utils/inspector.rs | 3 +- clippy_lints/src/utils/mod.rs | 7 +- 19 files changed, 245 insertions(+), 245 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4ce1aaa43d..a255b5ab904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,8 +9,8 @@ dependencies = [ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,8 +61,8 @@ name = "cargo_metadata" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -82,8 +82,8 @@ dependencies = [ "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -289,22 +289,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -319,7 +319,7 @@ dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -364,7 +364,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -442,9 +442,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7f61b753dd58ec5d4c735f794dbddde1f28b977f652afbcde89d75bc77902216" -"checksum serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2a169fa5384d751ada1da9f3992b81830151a03c875e40dcb37c9fb31aafc68f" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34" +"checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c" +"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 12339c039d9..83ec32615d1 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; +use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then, opt_def_id}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -211,8 +211,11 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), ExprRet(None) | ExprBreak(_, None) => false, ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { - let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); - !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) { + !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + } else { + true + } } else { true }, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 6ca04d40067..46b228e70ab 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{is_copy, match_def_path, paths, span_note_and_lint}; +use utils::{is_copy, match_def_path, paths, span_note_and_lint, opt_def_id}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. @@ -119,8 +119,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref path, ref args) = expr.node, let ExprPath(ref qpath) = path.node, args.len() == 1, + let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)), ], { - let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id(); let lint; let msg; let arg = &args[0]; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 621438b9a87..42af597125d 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,8 +1,8 @@ -use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; use rustc::lint::*; +use syntax::ast; use utils::{get_parent_expr, span_lint, span_note_and_lint}; /// **What it does:** Checks for a read and a write to the same variable where @@ -65,14 +65,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node { if let QPath::Resolved(_, ref path) = *qpath { if path.segments.len() == 1 { - let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); - let mut visitor = ReadVisitor { - cx: cx, - var: var, - write_expr: expr, - last_expr: expr, - }; - check_for_unsequenced_reads(&mut visitor); + if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) { + let mut visitor = ReadVisitor { + cx: cx, + var: var, + write_expr: expr, + last_expr: expr, + }; + check_for_unsequenced_reads(&mut visitor); + } } } }, @@ -280,7 +281,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St struct ReadVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, /// The id of the variable we're looking for. - var: DefId, + var: ast::NodeId, /// The expressions where the write to the variable occurred (for reporting /// in the lint). write_expr: &'tcx Expr, @@ -297,22 +298,23 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { match expr.node { ExprPath(ref qpath) => { - if let QPath::Resolved(None, ref path) = *qpath { - if path.segments.len() == 1 && self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { - if is_in_assignment_position(self.cx, expr) { - // This is a write, not a read. - } else { - span_note_and_lint( - self.cx, - EVAL_ORDER_DEPENDENCE, - expr.span, - "unsequenced read of a variable", - self.write_expr.span, - "whether read occurs before this write depends on evaluation order" - ); - } - } - } + if_let_chain! {[ + let QPath::Resolved(None, ref path) = *qpath, + path.segments.len() == 1, + let def::Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), + local_id == self.var, + // Check that this is a read, not a write. + !is_in_assignment_position(self.cx, expr), + ], { + span_note_and_lint( + self.cx, + EVAL_ORDER_DEPENDENCE, + expr.span, + "unsequenced read of a variable", + self.write_expr.span, + "whether read occurs before this write depends on evaluation order" + ); + }} } // We're about to descend a closure. Since we don't know when (or // if) the closure will be evaluated, any reads in it might not diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 2577e2908a8..f1a450e58df 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -5,7 +5,7 @@ use rustc::ty; use syntax::ast::LitKind; use syntax::symbol::InternedString; use utils::paths; -use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty}; +use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty, opt_def_id}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -47,7 +47,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain!{[ let ExprPath(ref qpath) = fun.node, args.len() == 2, - match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::FMT_ARGUMENTS_NEWV1), + let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), + match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1), // ensure the format string is `"{..}"` with only one argument and no text check_static_str(cx, &args[0]), // ensure the format argument is `{}` ie. Display with no fancy option @@ -128,7 +129,8 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { let ExprCall(_, ref args) = exprs[0].node, args.len() == 2, let ExprPath(ref qpath) = args[1].node, - match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].hir_id).def_id(), &paths::DISPLAY_FMT_METHOD), + let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id)), + match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD), ], { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 869e621eab6..def357c55e3 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -2,6 +2,7 @@ use rustc::hir::intravisit; use rustc::hir; use rustc::lint::*; use rustc::ty; +use rustc::hir::def::Def; use std::collections::HashSet; use syntax::ast; use syntax::abi::Abi; @@ -166,9 +167,9 @@ impl<'a, 'tcx> Functions { } } -fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { - if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) { - Some(def_id) +fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { + if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) { + Some(id) } else { None } @@ -176,7 +177,7 @@ fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { struct DerefVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ptrs: HashSet, + ptrs: HashSet, tables: &'a ty::TypeckTables<'tcx>, } @@ -216,14 +217,15 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr) { if let hir::ExprPath(ref qpath) = ptr.node { - let def = self.cx.tables.qpath_def(qpath, ptr.hir_id); - if self.ptrs.contains(&def.def_id()) { - span_lint( - self.cx, - NOT_UNSAFE_PTR_ARG_DEREF, - ptr.span, - "this public function dereferences a raw pointer but is not marked `unsafe`", - ); + if let Def::Local(id) = self.cx.tables.qpath_def(qpath, ptr.hir_id) { + if self.ptrs.contains(&id) { + span_lint( + self.cx, + NOT_UNSAFE_PTR_ARG_DEREF, + ptr.span, + "this public function dereferences a raw pointer but is not marked `unsafe`", + ); + } } } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 9812c759109..789dee6b05d 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,6 +1,8 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::BindingAnnotation; +use rustc::hir::def::Def; +use syntax::ast; use utils::{snippet, span_lint_and_then}; /// **What it does:** Checks for variable declarations immediately followed by a @@ -65,19 +67,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { let Some(expr) = it.peek(), let hir::StmtDecl(ref decl, _) = stmt.node, let hir::DeclLocal(ref decl) = decl.node, - let hir::PatKind::Binding(mode, def_id, ref name, None) = decl.pat.node, + let hir::PatKind::Binding(mode, canonical_id, ref name, None) = decl.pat.node, let hir::StmtExpr(ref if_, _) = expr.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, - !used_in_expr(cx, def_id, cond), + !used_in_expr(cx, canonical_id, cond), let hir::ExprBlock(ref then) = then.node, - let Some(value) = check_assign(cx, def_id, &*then), - !used_in_expr(cx, def_id, value), + let Some(value) = check_assign(cx, canonical_id, &*then), + !used_in_expr(cx, canonical_id, value), ], { let span = stmt.span.to(if_.span); let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { if let hir::ExprBlock(ref else_) = else_.node { - if let Some(default) = check_assign(cx, def_id, else_) { + if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) } else if let Some(ref default) = decl.init { (true, &**default) @@ -130,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { struct UsedVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - id: hir::def_id::DefId, + id: ast::NodeId, used: bool, } @@ -138,7 +140,8 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if_let_chain! {[ let hir::ExprPath(ref qpath) = expr.node, - self.id == self.cx.tables.qpath_def(qpath, expr.hir_id).def_id(), + let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), + self.id == local_id, ], { self.used = true; return; @@ -152,7 +155,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn check_assign<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - decl: hir::def_id::DefId, + decl: ast::NodeId, block: &'tcx hir::Block, ) -> Option<&'tcx hir::Expr> { if_let_chain! {[ @@ -161,7 +164,8 @@ fn check_assign<'a, 'tcx>( let hir::StmtSemi(ref expr, _) = expr.node, let hir::ExprAssign(ref var, ref value) = expr.node, let hir::ExprPath(ref qpath) = var.node, - decl == cx.tables.qpath_def(qpath, var.hir_id).def_id(), + let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id), + decl == local_id, ], { let mut v = UsedVisitor { cx: cx, @@ -183,7 +187,7 @@ fn check_assign<'a, 'tcx>( None } -fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: hir::def_id::DefId, expr: &'tcx hir::Expr) -> bool { +fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: ast::NodeId, expr: &'tcx hir::Expr) -> bool { let mut v = UsedVisitor { cx: cx, id: id, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 4452cee8613..f8ed0422289 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,7 +2,6 @@ use itertools::Itertools; use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; @@ -594,13 +593,14 @@ fn check_for_loop<'a, 'tcx>( detect_manual_memcpy(cx, pat, arg, body, expr); } -fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> bool { +fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool { if_let_chain! {[ let ExprPath(ref qpath) = expr.node, let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, + let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id), // our variable! - cx.tables.qpath_def(qpath, expr.hir_id).def_id() == var + local_id == var ], { return true; }} @@ -644,8 +644,8 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) } -fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> Option { - fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: DefId) -> Option { +fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option { + fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option { match e.node { ExprLit(ref l) => match l.node { ast::LitKind::Int(x, _ty) => Some(x.to_string()), @@ -700,12 +700,12 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: fn get_indexed_assignments<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, body: &Expr, - var: DefId, + var: ast::NodeId, ) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { fn get_assignment<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &Expr, - var: DefId, + var: ast::NodeId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) { @@ -759,7 +759,7 @@ fn detect_manual_memcpy<'a, 'tcx>( }) = higher::range(arg) { // the var must be a single name - if let PatKind::Binding(_, def_id, _, _) = pat.node { + if let PatKind::Binding(_, canonical_id, _, _) = pat.node { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), @@ -802,7 +802,7 @@ fn detect_manual_memcpy<'a, 'tcx>( // The only statements in the for loops can be indexed assignments from // indexed retrievals. - let manual_copies = get_indexed_assignments(cx, body, def_id); + let manual_copies = get_indexed_assignments(cx, body, canonical_id); let big_sugg = manual_copies .into_iter() @@ -852,10 +852,10 @@ fn check_for_loop_range<'a, 'tcx>( }) = higher::range(arg) { // the var must be a single name - if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { + if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, - var: def_id, + var: canonical_id, indexed: HashMap::new(), referenced: HashSet::new(), nonindex: false, @@ -1298,15 +1298,15 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor { } } -struct DefIdUsedVisitor<'a, 'tcx: 'a> { +struct LocalUsedVisitor <'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - def_id: DefId, + local: ast::NodeId, used: bool, } -impl<'a, 'tcx: 'a> Visitor<'tcx> for DefIdUsedVisitor<'a, 'tcx> { +impl<'a, 'tcx: 'a> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if same_var(self.cx, expr, self.def_id) { + if same_var(self.cx, expr, self.local) { self.used = true; } else { walk_expr(self, expr); @@ -1322,7 +1322,7 @@ struct VarVisitor<'a, 'tcx: 'a> { /// context reference cx: &'a LateContext<'a, 'tcx>, /// var name to look for as index - var: DefId, + var: ast::NodeId, /// indexed variables, the extend is `None` for global indexed: HashMap>, /// Any names that are used outside an index operation. @@ -1344,9 +1344,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { seqvar.segments.len() == 1, ], { let index_used = same_var(self.cx, idx, self.var) || { - let mut used_visitor = DefIdUsedVisitor { + let mut used_visitor = LocalUsedVisitor { cx: self.cx, - def_id: self.var, + local: self.var, used: false, }; walk_expr(&mut used_visitor, idx); @@ -1356,9 +1356,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if index_used { let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { - Def::Local(..) | Def::Upvar(..) => { - let def_id = def.def_id(); - let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); + Def::Local(node_id) | Def::Upvar(node_id, ..) => { let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); let parent_id = self.cx.tcx.hir.get_parent(expr.id); @@ -1381,8 +1379,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let ExprPath(ref qpath) = expr.node, let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, + let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), ], { - if self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { + if local_id == self.var { // we are not indexing anything, record that self.nonindex = true; } else { @@ -1672,11 +1671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { if let ExprPath(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.hir_id); - if let Def::Local(def_id) = path_res { - let node_id = cx.tcx - .hir - .as_local_node_id(def_id) - .expect("That DefId should be valid"); + if let Def::Local(node_id) = path_res { return Some(node_id); } } diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 9058d0d102d..43409eaea50 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{match_def_path, paths, span_lint}; +use utils::{match_def_path, paths, span_lint, opt_def_id}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is /// `Drop`. @@ -32,15 +32,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(ref qpath) = path_expr.node { - let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); - if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { - let forgot_ty = cx.tables.expr_ty(&args[0]); + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + let forgot_ty = cx.tables.expr_ty(&args[0]); - if match forgot_ty.ty_adt_def() { - Some(def) => def.has_dtor(cx.tcx), - _ => false, - } { - span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); + if match forgot_ty.ty_adt_def() { + Some(def) => def.has_dtor(cx.tcx), + _ => false, + } { + span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); + } } } } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index aea92311763..bcdbd738ee1 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -2,7 +2,7 @@ use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use std::cmp::{Ordering, PartialOrd}; -use utils::{match_def_path, paths, span_lint}; +use utils::{match_def_path, paths, span_lint, opt_def_id}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// used to clamp values, but switched so that the result is constant. @@ -60,15 +60,15 @@ enum MinMax { fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(ref qpath) = path.node { - let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id(); - - if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { - fetch_const(cx, args, MinMax::Min) - } else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) { - fetch_const(cx, args, MinMax::Max) - } else { - None - } + opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)).and_then(|def_id| { + if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { + fetch_const(cx, args, MinMax::Min) + } else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) { + fetch_const(cx, args, MinMax::Max) + } else { + None + } + }) } else { None } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index fcb29439a64..2c764109ea6 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -574,11 +574,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool { /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { - def::Def::Local(def_id) | def::Def::Upvar(def_id, _, _) => { - let id = cx.tcx - .hir - .as_local_node_id(def_id) - .expect("local variables should be found in the same crate"); + def::Def::Local(id) | def::Def::Upvar(id, _, _) => { !in_macro(cx.tcx.hir.span(id)) }, _ => false, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index da3bfc7594c..4a7a042924a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,6 +1,5 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; -use rustc::hir::def_id::DefId; use rustc::lint::*; use rustc::ty::{self, TypeFoldable}; use rustc::traits; @@ -129,8 +128,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { !implements_trait(cx, ty, asref_trait, &[]), !implements_borrow_trait, - let PatKind::Binding(mode, defid, ..) = arg.pat.node, - !moved_vars.contains(&defid), + let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node, + !moved_vars.contains(&canonical_id), ], { // Note: `toplevel_ref_arg` warns if `BindByRef` if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { @@ -139,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Suggestion logic let sugg = |db: &mut DiagnosticBuilder| { - let deref_span = spans_need_deref.get(&defid); + let deref_span = spans_need_deref.get(&canonical_id); if_let_chain! {[ match_type(cx, ty, &paths::VEC), let TyPath(QPath::Resolved(_, ref path)) = input.node, @@ -186,11 +185,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { struct MovedVariablesCtxt<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - moved_vars: HashSet, + moved_vars: HashSet, /// Spans which need to be prefixed with `*` for dereferencing the /// suggested additional /// reference. - spans_need_deref: HashMap>, + spans_need_deref: HashMap>, } impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { @@ -205,12 +204,9 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt<'tcx>) { let cmt = unwrap_downcast_or_interior(cmt); - if_let_chain! {[ - let mc::Categorization::Local(vid) = cmt.cat, - let Some(def_id) = self.cx.tcx.hir.opt_local_def_id(vid), - ], { - self.moved_vars.insert(def_id); - }} + if let mc::Categorization::Local(vid) = cmt.cat { + self.moved_vars.insert(vid); + } } fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) { @@ -218,7 +214,6 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { if_let_chain! {[ let mc::Categorization::Local(vid) = cmt.cat, - let Some(def_id) = self.cx.tcx.hir.opt_local_def_id(vid), ], { let mut id = matched_pat.id; loop { @@ -235,7 +230,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { // `match` and `if let` if let ExprMatch(ref c, ..) = e.node { self.spans_need_deref - .entry(def_id) + .entry(vid) .or_insert_with(HashSet::new) .insert(c.span); } @@ -248,7 +243,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { let DeclLocal(ref local) = decl.node, ], { self.spans_need_deref - .entry(def_id) + .entry(vid) .or_insert_with(HashSet::new) .insert(local.init .as_ref() diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index a050873187d..f0428534456 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint}; +use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint, opt_def_id}; /// **What it does:** Checks for missing parameters in `panic!`. /// @@ -40,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref fun, ref params) = ex.node, params.len() == 2, let ExprPath(ref qpath) = fun.node, - match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::BEGIN_PANIC), + let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), + match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC), let ExprLit(ref lit) = params[0].node, is_direct_expn_of(expr.span, "panic").is_some(), let LitKind::Str(ref string, _) = lit.node, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 9aca7543396..1f24a7af052 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::lint::*; -use utils::paths; +use utils::{paths, opt_def_id}; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use format::get_argument_fmtstr_parts; @@ -72,9 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain! {[ let ExprCall(ref fun, ref args) = expr.node, let ExprPath(ref qpath) = fun.node, + let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), ], { - let fun = resolve_node(cx, qpath, fun.hir_id); - let fun_id = fun.def_id(); // Search for `std::io::_print(..)` which is unique in a // `print!` expansion. @@ -96,9 +95,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { args.len() == 1, let ExprCall(ref args_fun, ref args_args) = args[0].node, let ExprPath(ref qpath) = args_fun.node, - match_def_path(cx.tcx, - resolve_node(cx, qpath, args_fun.hir_id).def_id(), - &paths::FMT_ARGUMENTS_NEWV1), + let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)), + match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1), args_args.len() == 2, let ExprAddrOf(_, ref match_expr) = args_args[1].node, let ExprMatch(ref args, _, _) = match_expr.node, @@ -125,10 +123,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { if let ExprPath(ref qpath) = args[1].node { - let def_id = cx.tables.qpath_def(qpath, args[1].hir_id).def_id(); - if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && - is_expn_of(expr.span, "panic").is_none() { - span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { + span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } } } } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 8b5dedfccd4..a18bf628601 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -9,7 +9,7 @@ use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; -use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; +use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint, opt_def_id}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -116,8 +116,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprCall(ref fun, ref args) = expr.node, let ExprPath(ref qpath) = fun.node, args.len() == 1, + let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, fun.hir_id)), ], { - let def_id = cx.tables.qpath_def(qpath, fun.hir_id).def_id(); if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { check_regex(cx, &args[0], true); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index a590bf744bf..18b80c76810 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; -use utils::sugg; +use utils::{sugg, opt_def_id}; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. @@ -88,97 +88,98 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(ref qpath) = path_expr.node { - let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { - let from_ty = cx.tables.expr_ty(&args[0]); - let to_ty = cx.tables.expr_ty(e); + if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { + let from_ty = cx.tables.expr_ty(&args[0]); + let to_ty = cx.tables.expr_ty(e); - match (&from_ty.sty, &to_ty.sty) { - _ if from_ty == to_ty => span_lint( - cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty), - ), - (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from a reference to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = if ptr_ty == rty { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) - }; + match (&from_ty.sty, &to_ty.sty) { + _ if from_ty == to_ty => span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ), + (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = if ptr_ty == rty { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) + }; - db.span_suggestion(e.span, "try", sugg.to_string()); - }, - ), - (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); - }, - ), - (&ty::TyFloat(_), &ty::TyRef(..)) | - (&ty::TyFloat(_), &ty::TyRawPtr(_)) | - (&ty::TyChar, &ty::TyRef(..)) | - (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint( - cx, - WRONG_TRANSMUTE, - e.span, - &format!("transmute from a `{}` to a pointer", from_ty), - ), - (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!( - "transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ), + (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + }, + ), + (&ty::TyFloat(_), &ty::TyRef(..)) | + (&ty::TyFloat(_), &ty::TyRawPtr(_)) | + (&ty::TyChar, &ty::TyRef(..)) | + (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), ), - ), - (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), - ), - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_REF, - e.span, - &format!( - "transmute from a pointer type (`{}`) to a reference type \ - (`{}`)", - from_ty, - to_ty + (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty + ), ), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), + ), + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!( + "transmute from a pointer type (`{}`) to a reference type \ + (`{}`)", + from_ty, + to_ty + ), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - let arg = if from_pty.ty == to_rty.ty { - arg - } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) - }; + let arg = if from_pty.ty == to_rty.ty { + arg + } else { + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) + }; - db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); - }, - ), - _ => return, - }; + db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); + }, + ), + _ => return, + }; + } } } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 09e40aea80d..550ecedeae4 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; +use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node, opt_def_id}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -181,13 +181,13 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option { - if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(item.hir_id) { + let def_id = cx.tcx.hir.local_def_id(item.id); + if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(def_id) { let source = cx.tcx.used_crate_source(crate_id); if let Some(ref src) = source.dylib { println!("extern crate dylib source: {:?}", src.0); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8e816ffbfa4..5157d416b23 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -950,12 +950,10 @@ pub fn opt_def_id(def: Def) -> Option { Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | - Def::Local(id) | - Def::Upvar(id, ..) | Def::Macro(id, ..) | Def::GlobalAsm(id) => Some(id), - Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, + Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, } } @@ -991,7 +989,8 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { match_qpath(path, &paths::RESULT_OK[1..]), let PatKind::Binding(_, defid, _, None) = pat[0].node, let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node, - path.def.def_id() == defid, + let Def::Local(lid) = path.def, + lid == defid, ], { return true; }} -- cgit 1.4.1-3-g733a5 From b7222be9173d891c0d4e69e89ddf2dd2857cdef9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 12 Sep 2017 14:40:24 +0200 Subject: Version bump --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e576454ea..c14a9fac6c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.159 +* Update to *rustc 1.22.0-nightly (eba374fb2 2017-09-11)* +* New lint: [`clone_on_ref_ptr`] + ## 0.0.158 * New lint: [`manual_memcpy`] * [`cast_lossless`] no longer has redundant parentheses in its suggestions @@ -450,6 +454,7 @@ All notable changes to this project will be documented in this file. [`chars_next_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_next_cmp [`clone_double_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_double_ref [`clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_copy +[`clone_on_ref_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_ref_ptr [`cmp_nan`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_nan [`cmp_null`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_null [`cmp_owned`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_owned diff --git a/Cargo.toml b/Cargo.toml index b078f0bc6df..e3e7a25b05f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.158" +version = "0.0.159" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.158", path = "clippy_lints" } +clippy_lints = { version = "0.0.159", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 153ef23d543..92d3b29bead 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.158" +version = "0.0.159" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a9e5310dd7f..c6f52cd9370 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -460,6 +460,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::CHARS_NEXT_CMP, methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, + methods::CLONE_ON_REF_PTR, methods::FILTER_NEXT, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, -- cgit 1.4.1-3-g733a5 From 2b698db1ae2a7c540590c05eb9d6c75e48dbe858 Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Tue, 12 Sep 2017 19:03:34 +0300 Subject: Fix links in approx_const --- clippy_lints/src/approx_const.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 9d5d87dc4b3..ed65366d21f 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -7,11 +7,9 @@ use utils::span_lint; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in -/// [`std::f32::consts`](https://doc.rust-lang. -/// org/stable/std/f32/consts/#constants) +/// [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) /// or -/// [`std::f64::consts`](https://doc.rust-lang. -/// org/stable/std/f64/consts/#constants), +/// [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), /// respectively, suggesting to use the predefined constant. /// /// **Why is this bad?** Usually, the definition in the standard library is more -- cgit 1.4.1-3-g733a5 From 6d3db724b74f4b729623ef8e529599e9c2b54513 Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Tue, 12 Sep 2017 19:04:05 +0300 Subject: Fix empty documentation in unit_expr --- clippy_lints/src/is_unit_expr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 58df45ad89a..734ef1ecb76 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -18,7 +18,6 @@ use utils::span_note_and_lint; /// **Example:** /// * `let x = {"foo" ;}` when the user almost certainly intended `let x /// ={"foo"}` - declare_lint! { pub UNIT_EXPR, Warn, -- cgit 1.4.1-3-g733a5 From d768fe8c1666fe2203ceb5eb856992c6a41cced9 Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Tue, 12 Sep 2017 19:04:57 +0300 Subject: Fix link in trivial_regex --- clippy_lints/src/regex.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index a18bf628601..e73b98756a1 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -29,10 +29,8 @@ declare_lint! { "invalid regular expressions" } -/// **What it does:** Checks for trivial [regex] creation (with `Regex::new`, -/// `RegexBuilder::new` or `RegexSet::new`). -/// -/// [regex]: https://crates.io/crates/regex +/// **What it does:** Checks for trivial [regex](https://crates.io/crates/regex) +/// creation (with `Regex::new`, `RegexBuilder::new` or `RegexSet::new`). /// /// **Why is this bad?** Matching the regex can likely be replaced by `==` or /// `str::starts_with`, `str::ends_with` or `std::contains` or other `str` -- cgit 1.4.1-3-g733a5 From 32a9394490ce0a2dc6fbbb6792570c8652c101ef Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 13 Sep 2017 15:34:04 +0200 Subject: Rustup --- CHANGELOG.md | 3 +++ Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/array_indexing.rs | 24 +++++++++++++----------- clippy_lints/src/consts.rs | 9 +++++---- clippy_lints/src/derive.rs | 13 ++----------- clippy_lints/src/enum_clike.rs | 4 ++-- clippy_lints/src/lib.rs | 1 + clippy_lints/src/loops.rs | 7 ++++--- clippy_lints/src/matches.rs | 14 +++++++------- clippy_lints/src/methods.rs | 31 ++++++++++++++++--------------- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/regex.rs | 9 +++++---- clippy_lints/src/types.rs | 26 +++++++++++++------------- clippy_lints/src/utils/mod.rs | 4 ++++ clippy_lints/src/vec.rs | 2 +- tests/ui/derive.stderr | 34 +++++++++++++++++++++++++++++++++- 19 files changed, 118 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c14a9fac6c9..17a12efda59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.160 +* Update to *rustc 1.22.0-nightly (dd08c3070 2017-09-12)* + ## 0.0.159 * Update to *rustc 1.22.0-nightly (eba374fb2 2017-09-11)* * New lint: [`clone_on_ref_ptr`] diff --git a/Cargo.lock b/Cargo.lock index a255b5ab904..6511a5c2010 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.158" +version = "0.0.159" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,11 +73,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.158" +version = "0.0.159" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.158", + "clippy_lints 0.0.159", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index e3e7a25b05f..b1676b45a8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.159" +version = "0.0.160" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.159", path = "clippy_lints" } +clippy_lints = { version = "0.0.160", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 92d3b29bead..b0e86bb7760 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.159" +version = "0.0.160" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 5815f645686..aa2d6db6853 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -7,6 +7,7 @@ use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; +use utils::const_to_u64; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. @@ -63,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, size) = ty.sty { let size = ConstInt::Usize( - ConstUsize::new(size as u64, cx.sess().target.uint_type).expect("array size is invalid"), + ConstUsize::new(const_to_u64(size), cx.sess().target.usize_ty).expect("array size is invalid"), ); let parent_item = cx.tcx.hir.get_parent(e.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); @@ -71,13 +72,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables); // Index is a constant uint - let const_index = constcx.eval(index); - if let Ok(ConstVal::Integral(const_index)) = const_index { - if size <= const_index { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); - } + if let Ok(const_index) = constcx.eval(index) { + if let ConstVal::Integral(const_index) = const_index.val { + if size <= const_index { + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); + } - return; + return; + } } // Index is a constant range @@ -112,19 +114,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { /// Returns an option containing a tuple with the start and end (exclusive) of /// the range. fn to_const_range( - start: &Option>, - end: &Option>, + start: &Option>, + end: &Option>, limits: RangeLimits, array_size: ConstInt, ) -> Option<(ConstInt, ConstInt)> { let start = match *start { - Some(Some(ConstVal::Integral(x))) => x, + Some(Some(&ty::Const { val: ConstVal::Integral(x), .. })) => x, Some(_) => return None, None => ConstInt::U8(0), }; let end = match *end { - Some(Some(ConstVal::Integral(x))) => if limits == RangeLimits::Closed { + Some(Some(&ty::Const { val: ConstVal::Integral(x), .. })) => if limits == RangeLimits::Closed { match x { ConstInt::U8(_) => (x + ConstInt::U8(1)), ConstInt::U16(_) => (x + ConstInt::U16(1)), diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index b1bd6b06ee4..2611ba1adf2 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -14,6 +14,7 @@ use std::mem; use std::rc::Rc; use syntax::ast::{FloatTy, LitKind, StrStyle}; use syntax::ptr::P; +use utils::const_to_u64; #[derive(Debug, Copy, Clone)] pub enum FloatWidth { @@ -49,7 +50,7 @@ pub enum Constant { /// an array of constants Vec(Vec), /// also an array, but with only one constant, repeated N times - Repeat(Box, usize), + Repeat(Box, u64), /// a tuple of constants Tuple(Vec), } @@ -175,10 +176,10 @@ pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, hint) => match (&ty.sty, hint) { (&ty::TyInt(ity), _) | (_, Signed(ity)) => { - Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.int_type)) + Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.isize_ty)) }, (&ty::TyUint(uty), _) | (_, Unsigned(uty)) => { - Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.uint_type)) + Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.usize_ty)) }, _ => bug!(), }, @@ -249,7 +250,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprRepeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::TyArray(_, n) => n, + ty::TyArray(_, n) => const_to_u64(n), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 5baaa4bd59d..a891d7721c3 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -143,17 +143,8 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref // Some types are not Clone by default but could be cloned “by hand” if necessary ty::TyAdt(def, substs) => for variant in &def.variants { for field in &variant.fields { - match field.ty(cx.tcx, substs).sty { - ty::TyArray(_, size) if size > 32 => { - return; - }, - ty::TyFnPtr(..) => { - return; - }, - ty::TyTuple(tys, _) if tys.len() > 12 => { - return; - }, - _ => (), + if let ty::TyFnDef(..) = field.ty(cx.tcx, substs).sty { + return; } } }, diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index c776681d51c..c019ab0b385 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -55,8 +55,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { .at(expr.span) .const_eval(param_env.and((did, substs))) { - Ok(ConstVal::Integral(Usize(Us64(i)))) => u64::from(i as u32) != i, - Ok(ConstVal::Integral(Isize(Is64(i)))) => i64::from(i as i32) != i, + Ok(&ty::Const { val: ConstVal::Integral(Usize(Us64(i))), .. }) => u64::from(i as u32) != i, + Ok(&ty::Const { val: ConstVal::Integral(Isize(Is64(i))), .. }) => i64::from(i as i32) != i, _ => false, }; if bad { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c6f52cd9370..520f9362c0f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,6 +8,7 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] +#![feature(inclusive_range_syntax, range_contains)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #[macro_use] diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f8ed0422289..41218a989fc 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -13,6 +13,7 @@ use rustc_const_eval::ConstContext; use std::collections::{HashMap, HashSet}; use syntax::ast; use utils::sugg; +use utils::const_to_u64; use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, snippet_opt, @@ -969,7 +970,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { false } -fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { +fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr, expr: &'tcx Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { start: Some(start), @@ -989,7 +990,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, end_idx) { - (ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => { + (&ty::Const{ val: ConstVal::Integral(start_idx), .. }, &ty::Const{ val: ConstVal::Integral(end_idx), .. }) => { (start_idx > end_idx, start_idx == end_idx) }, _ => (false, false), @@ -1461,7 +1462,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, 0...32) => true, + ty::TyArray(_, n) => (0...32).contains(const_to_u64(n)), _ => false, } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b9a4507c5d7..78a85c4a686 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -318,7 +318,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } -fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { +fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr, arms: &'tcx [Arm]) { if arms.len() >= 2 && cx.tables.expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms, ex.id); let type_ranges = type_ranges(&ranges); @@ -411,7 +411,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match } /// Get all arms that are unbounded `PatRange`s. -fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm], id: NodeId) -> Vec>> { +fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm], id: NodeId) -> Vec>> { let parent_item = cx.tcx.hir.get_parent(id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); @@ -444,7 +444,7 @@ fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm], id: NodeId) -> let PatKind::Lit(ref value) = pat.node, let Ok(value) = constcx.eval(value) ], { - return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); + return Some(SpannedRange { span: pat.span, node: (value, Bound::Included(value)) }); }} None @@ -464,19 +464,19 @@ type TypedRanges = Vec>; /// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway /// and other types than /// `Uint` and `Int` probably don't make sense. -fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { +fn type_ranges(ranges: &[SpannedRange<&ty::Const>]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { - (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => Some(SpannedRange { + (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Included(&ty::Const { val: ConstVal::Integral(end), .. })) => Some(SpannedRange { span: range.span, node: (start, Bound::Included(end)), }), - (ConstVal::Integral(start), Bound::Excluded(ConstVal::Integral(end))) => Some(SpannedRange { + (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Excluded(&ty::Const { val: ConstVal::Integral(end), .. })) => Some(SpannedRange { span: range.span, node: (start, Bound::Excluded(end)), }), - (ConstVal::Integral(start), Bound::Unbounded) => Some(SpannedRange { + (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Unbounded) => Some(SpannedRange { span: range.span, node: (start, Bound::Unbounded), }), diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 90208369caa..08336fca0ae 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -14,6 +14,7 @@ use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_ span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; +use utils::const_to_u64; #[derive(Clone)] pub struct Pass; @@ -1049,7 +1050,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option true, ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::TyAdt(..) => match_type(cx, ty, &paths::VEC), - ty::TyArray(_, size) => size < 32, + ty::TyArray(_, size) => const_to_u64(size) < 32, ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => may_slice(cx, inner), _ => false, } @@ -1155,7 +1156,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] } /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { +fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr], unwrap_args: &'tcx [hir::Expr]) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { // lint message @@ -1188,7 +1189,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &[hir:: } /// lint use of `filter().next()` for `Iterators` -fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &[hir::Expr]) { +fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \ @@ -1211,7 +1212,7 @@ fn lint_filter_next(cx: &LateContext, expr: &hir::Expr, filter_args: &[hir::Expr } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir::Expr], _map_args: &[hir::Expr]) { +fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).map(q)` on an `Iterator`. \ @@ -1221,7 +1222,7 @@ fn lint_filter_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir::Expr } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir::Expr], _map_args: &[hir::Expr]) { +fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ @@ -1231,7 +1232,7 @@ fn lint_filter_map_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir:: } /// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir::Expr], _map_args: &[hir::Expr]) { +fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ @@ -1242,7 +1243,7 @@ fn lint_filter_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir: } /// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[hir::Expr], _map_args: &[hir::Expr]) { +fn lint_filter_map_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ @@ -1253,12 +1254,12 @@ fn lint_filter_map_flat_map(cx: &LateContext, expr: &hir::Expr, _filter_args: &[ } /// lint searching an Iterator followed by `is_some()` -fn lint_search_is_some( - cx: &LateContext, - expr: &hir::Expr, +fn lint_search_is_some<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, search_method: &str, - search_args: &[hir::Expr], - is_some_args: &[hir::Expr], + search_args: &'tcx [hir::Expr], + is_some_args: &'tcx [hir::Expr], ) { // lint if caller of search is an Iterator if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { @@ -1285,7 +1286,7 @@ fn lint_search_is_some( } /// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: &hir::Expr, eq: bool) -> bool { +fn lint_chars_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, chain: &'tcx hir::Expr, other: &'tcx hir::Expr, eq: bool) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(chain, &["chars", "next"]), let hir::ExprCall(ref fun, ref arg_char) = other.node, @@ -1317,11 +1318,11 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: } /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { +fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { let parent_item = cx.tcx.hir.get_parent(arg.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if let Ok(ConstVal::Str(r)) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { + if let Ok(&ty::Const { val: ConstVal::Str(r), .. }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then( diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 2c764109ea6..98fb90f57c1 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -419,12 +419,12 @@ fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { } } -fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { +fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { let parent_item = cx.tcx.hir.get_parent(expr.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr); - if let Ok(ConstVal::Float(val)) = res { + if let Ok(&ty::Const { val: ConstVal::Float(val), .. }) = res { use std::cmp::Ordering; match val.ty { FloatTy::F32 => { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 44c909810ea..61b61c9fb6f 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { use consts::{constant, Constant}; use rustc_const_math::ConstInt::Usize; if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) { - if us.as_u64(cx.sess().target.uint_type) == 0 { + if us.as_u64() == 0 { span_lint( cx, ITERATOR_STEP_BY_ZERO, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index a18bf628601..a9bee3a5261 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,6 +1,7 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::*; +use rustc::ty; use rustc::middle::const_val::ConstVal; use rustc_const_eval::ConstContext; use rustc::ty::subst::Substs; @@ -145,12 +146,12 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { } } -fn const_str(cx: &LateContext, e: &Expr) -> Option { +fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option { let parent_item = cx.tcx.hir.get_parent(e.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(e) { - Ok(ConstVal::Str(r)) => Some(r), + Ok(&ty::Const { val: ConstVal::Str(r), .. }) => Some(r), _ => None, } } @@ -179,7 +180,7 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { } } -fn check_set(cx: &LateContext, expr: &Expr, utf8: bool) { +fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { if_let_chain! {[ let ExprAddrOf(_, ref expr) = expr.node, let ExprArray(ref exprs) = expr.node, @@ -190,7 +191,7 @@ fn check_set(cx: &LateContext, expr: &Expr, utf8: bool) { }} } -fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { +fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { let builder = regex_syntax::ExprBuilder::new().unicode(utf8); if let ExprLit(ref lit) = expr.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6eb78d02d30..567e8b5423e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1061,12 +1061,12 @@ enum AbsurdComparisonResult { -fn detect_absurd_comparison<'a>( - cx: &LateContext, +fn detect_absurd_comparison<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, op: BinOp_, - lhs: &'a Expr, - rhs: &'a Expr, -) -> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> { + lhs: &'tcx Expr, + rhs: &'tcx Expr, +) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { use types::ExtremeType::*; use types::AbsurdComparisonResult::*; use utils::comparisons::*; @@ -1108,7 +1108,7 @@ fn detect_absurd_comparison<'a>( }) } -fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option> { +fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option> { use rustc::middle::const_val::ConstVal::*; use rustc_const_math::*; use rustc_const_eval::*; @@ -1129,7 +1129,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option return None, }; - let which = match (&ty.sty, cv) { + let which = match (&ty.sty, cv.val) { (&ty::TyBool, Bool(false)) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | @@ -1336,7 +1336,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( } #[allow(cast_possible_wrap)] -fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { +fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option { use rustc::middle::const_val::ConstVal::*; use rustc_const_eval::ConstContext; @@ -1344,7 +1344,7 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) { - Ok(val) => if let Integral(const_int) = val { + Ok(val) => if let Integral(const_int) = val.val { match const_int.int_type() { IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), @@ -1371,13 +1371,13 @@ fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: boo } } -fn upcast_comparison_bounds_err( - cx: &LateContext, +fn upcast_comparison_bounds_err<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, span: &Span, rel: comparisons::Rel, lhs_bounds: Option<(FullInt, FullInt)>, - lhs: &Expr, - rhs: &Expr, + lhs: &'tcx Expr, + rhs: &'tcx Expr, invert: bool, ) { use utils::comparisons::*; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 5157d416b23..6173073fb76 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -313,6 +313,10 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { } } +pub fn const_to_u64(c: &ty::Const) -> u64 { + c.val.to_const_int().expect("eddyb says this works").to_u64().expect("see previous expect") +} + /// Convenience function to get the `DefId` of a trait by path. pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option { let def = match path_to_def(cx, path) { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 71f53a3e051..367235f7eee 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { +fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { let parent_item = cx.tcx.hir.get_parent(len.id); diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index e34ba09bb81..ffeed948ba5 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -74,5 +74,37 @@ note: consider deriving `Clone` or removing `Copy` 67 | | } | |_^ -error: aborting due to 5 previous errors +error: you are implementing `Clone` explicitly on a `Copy` type + --> $DIR/derive.rs:75:1 + | +75 | / impl Clone for BigArray { +76 | | fn clone(&self) -> Self { unimplemented!() } +77 | | } + | |_^ + | +note: consider deriving `Clone` or removing `Copy` + --> $DIR/derive.rs:75:1 + | +75 | / impl Clone for BigArray { +76 | | fn clone(&self) -> Self { unimplemented!() } +77 | | } + | |_^ + +error: you are implementing `Clone` explicitly on a `Copy` type + --> $DIR/derive.rs:85:1 + | +85 | / impl Clone for FnPtr { +86 | | fn clone(&self) -> Self { unimplemented!() } +87 | | } + | |_^ + | +note: consider deriving `Clone` or removing `Copy` + --> $DIR/derive.rs:85:1 + | +85 | / impl Clone for FnPtr { +86 | | fn clone(&self) -> Self { unimplemented!() } +87 | | } + | |_^ + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 86e178e7864ff89624f011421f42fc3252f3ce94 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 14 Sep 2017 13:18:08 +0900 Subject: Add a missing argument --- src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 89de07115c5..f4945998fde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,12 +64,13 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { &mut self, matches: &getopts::Matches, sess: &Session, + crate_stores: &rustc::middle::cstore::CrateStore, input: &Input, odir: &Option, ofile: &Option, ) -> Compilation { self.default - .late_callback(matches, sess, input, odir, ofile) + .late_callback(matches, sess, crate_stores, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { let mut control = self.default.build_controller(sess, matches); -- cgit 1.4.1-3-g733a5 From 49d388d4ec415107340b9b84d8a9544bc46ee5e8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 14 Sep 2017 13:18:34 +0900 Subject: Remove '\t' from .stderr to make cargo test pass --- tests/ui/never_loop.stderr | 26 ++++++++++++------------ tests/ui/overflow_check_conditional.stderr | 32 +++++++++++++++--------------- tests/ui/redundant_closure_call.stderr | 20 +++++++++---------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 97205690da6..d1bfc4a95a8 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -24,12 +24,12 @@ error: this loop never actually loops error: this loop never actually loops --> $DIR/never_loop.rs:47:2 | -47 | / \tloop { // never loops -48 | | \t while i == 0 { // never loops -49 | | \t break -50 | | \t } -51 | | \t return -52 | | \t} +47 | / loop { // never loops +48 | | while i == 0 { // never loops +49 | | break +50 | | } +51 | | return +52 | | } | |__^ error: this loop never actually loops @@ -45,20 +45,20 @@ error: this loop never actually loops | 57 | / 'outer: loop { // never loops 58 | | x += 1; -59 | | \t\tloop { // never loops +59 | | loop { // never loops 60 | | if x == 5 { break } ... | -63 | | \t\treturn -64 | | \t} +63 | | return +64 | | } | |__^ error: this loop never actually loops --> $DIR/never_loop.rs:59:3 | -59 | / \t\tloop { // never loops -60 | | \t\t if x == 5 { break } -61 | | \t\t\tcontinue 'outer -62 | | \t\t} +59 | / loop { // never loops +60 | | if x == 5 { break } +61 | | continue 'outer +62 | | } | |___^ error: this loop never actually loops diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 543075ff5de..8a80dbedaeb 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,52 +1,52 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:11:5 | -11 | \tif a + b < a { - | \t ^^^^^^^^^ +11 | if a + b < a { + | ^^^^^^^^^ | = note: `-D overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:14:5 | -14 | \tif a > a + b { - | \t ^^^^^^^^^ +14 | if a > a + b { + | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:17:5 | -17 | \tif a + b < b { - | \t ^^^^^^^^^ +17 | if a + b < b { + | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:20:5 | -20 | \tif b > a + b { - | \t ^^^^^^^^^ +20 | if b > a + b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:23:5 | -23 | \tif a - b > b { - | \t ^^^^^^^^^ +23 | if a - b > b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:26:5 | -26 | \tif b < a - b { - | \t ^^^^^^^^^ +26 | if b < a - b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:29:5 | -29 | \tif a - b > a { - | \t ^^^^^^^^^ +29 | if a - b > a { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:32:5 | -32 | \tif a < a - b { - | \t ^^^^^^^^^ +32 | if a < a - b { + | ^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 599574a185e..e2865edc870 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,34 +1,34 @@ error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:15:2 | -15 | \ti = closure(); - | \t^^^^^^^^^^^^^ +15 | i = closure(); + | ^^^^^^^^^^^^^ | = note: `-D redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:18:2 | -18 | \ti = closure(3); - | \t^^^^^^^^^^^^^^ +18 | i = closure(3); + | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:7:10 | -7 | \tlet a = (|| 42)(); - | \t ^^^^^^^^^ help: Try doing something like: : `42` +7 | let a = (|| 42)(); + | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:10:14 | -10 | \tlet mut k = (|m| m+1)(i); - | \t ^^^^^^^^^^^^ +10 | let mut k = (|m| m+1)(i); + | ^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:12:6 | -12 | \tk = (|a,b| a*b)(1,5); - | \t ^^^^^^^^^^^^^^^^ +12 | k = (|a,b| a*b)(1,5); + | ^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 86d609fdf650baa97cda77156ffa9116468d98fc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 14 Sep 2017 09:13:54 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17a12efda59..989f9f2da78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.161 +* Update to *rustc 1.22.0-nightly (539f2083d 2017-09-13)* + ## 0.0.160 * Update to *rustc 1.22.0-nightly (dd08c3070 2017-09-12)* diff --git a/Cargo.toml b/Cargo.toml index b1676b45a8e..41ea684f327 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.160" +version = "0.0.161" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.160", path = "clippy_lints" } +clippy_lints = { version = "0.0.161", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index b0e86bb7760..fee0391dacd 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.160" +version = "0.0.161" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 9f0cc93ac60806b17e1df7309cb2dc0d262bb2ee Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 14 Sep 2017 22:24:00 +0900 Subject: Bump version --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6511a5c2010..ffc84a488eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.159" +version = "0.0.161" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,11 +73,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.159" +version = "0.0.161" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.159", + "clippy_lints 0.0.161", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -- cgit 1.4.1-3-g733a5 From 1f6801dd6ab1044143594334229c62f2c7346c8e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 14 Sep 2017 22:26:59 +0900 Subject: Add ExprLoop to contains_continue_expr() --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 41218a989fc..f06831556c2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -526,7 +526,7 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprMatch(ref e, ref arms, _) => { contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) }, - ExprBlock(ref block) => contains_continue_block(block, dest), + ExprBlock(ref block) | ExprLoop(ref block, ..) => contains_continue_block(block, dest), ExprStruct(_, _, ref base) => base.as_ref() .map_or(false, |e| contains_continue_expr(e, dest)), ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), -- cgit 1.4.1-3-g733a5 From 0215a1acb0230c3f81d47a3ee31ba562678f6be1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 14 Sep 2017 22:27:29 +0900 Subject: Update a test --- tests/ui/never_loop.rs | 17 ++++++++++++++++- tests/ui/never_loop.stderr | 14 +------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 50b8d499414..ff0126704b5 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -54,7 +54,7 @@ fn test5() { fn test6() { let mut x = 0; - 'outer: loop { // never loops + 'outer: loop { x += 1; loop { // never loops if x == 5 { break } @@ -112,6 +112,20 @@ fn test11 i32>(mut f: F) { } } +pub fn test12(a: bool, b: bool) { + 'label: loop { + loop { + if a { + continue 'label; + } + if b { + break; + } + } + break; + } +} + fn main() { test1(); test2(); @@ -124,5 +138,6 @@ fn main() { test9(); test10(); test11(|| 0); + test12(true, false); } diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index d1bfc4a95a8..dace2b7e261 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -40,18 +40,6 @@ error: this loop never actually loops 50 | | } | |_________^ -error: this loop never actually loops - --> $DIR/never_loop.rs:57:5 - | -57 | / 'outer: loop { // never loops -58 | | x += 1; -59 | | loop { // never loops -60 | | if x == 5 { break } -... | -63 | | return -64 | | } - | |__^ - error: this loop never actually loops --> $DIR/never_loop.rs:59:3 | @@ -80,5 +68,5 @@ error: this loop never actually loops 103 | | } | |_____^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 197664e98990d378b1de634d37dd878783ae8103 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 16 Sep 2017 11:27:24 +0900 Subject: Add suggestion to needless_borrow --- clippy_lints/src/needless_borrow.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 7dd42bca3ab..d8f892d4073 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; -use utils::{in_macro, span_lint}; +use utils::{in_macro, snippet_opt, span_lint_and_then}; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. @@ -54,12 +54,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { .. }] = *adj3 { - span_lint( + span_lint_and_then( cx, NEEDLESS_BORROW, e.span, - "this expression borrows a reference that is immediately dereferenced by the \ - compiler", + "this expression borrows a reference that is immediately dereferenced \ + by the compiler", + |db| { + if let Some(snippet) = snippet_opt(cx, inner.span) { + db.span_suggestion(e.span, "change this to", snippet); + } + } ); } } @@ -71,14 +76,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { return; } if_let_chain! {[ - let PatKind::Binding(BindingAnnotation::Ref, _, _, _) = pat.node, + let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node, let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, tam.mutbl == MutImmutable, let ty::TyRef(_, ref tam) = tam.ty.sty, // only lint immutable refs, because borrowed `&mut T` cannot be moved out tam.mutbl == MutImmutable, ], { - span_lint(cx, NEEDLESS_BORROW, pat.span, "this pattern creates a reference to a reference") + span_lint_and_then( + cx, + NEEDLESS_BORROW, + pat.span, + "this pattern creates a reference to a reference", + |db| { + if let Some(snippet) = snippet_opt(cx, name.span) { + db.span_suggestion(pat.span, "change this to", snippet); + } + } + ) }} } } -- cgit 1.4.1-3-g733a5 From d8afe2ccbcab2248be6eedf7cf5f2cc77a4e8230 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 16 Sep 2017 11:27:46 +0900 Subject: Update tests --- tests/ui/eta.stderr | 2 +- tests/ui/needless_borrow.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 88abbaa7343..5dca265c2a4 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -22,7 +22,7 @@ error: this expression borrows a reference that is immediately dereferenced by t --> $DIR/eta.rs:11:21 | 11 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted - | ^^^ + | ^^^ help: change this to: `&2` | = note: `-D needless-borrow` implied by `-D warnings` diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index d90c396645e..fde38508b32 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -2,7 +2,7 @@ error: this expression borrows a reference that is immediately dereferenced by t --> $DIR/needless_borrow.rs:13:15 | 13 | let c = x(&&a); - | ^^^ + | ^^^ help: change this to: `&a` | = note: `-D needless-borrow` implied by `-D warnings` @@ -10,13 +10,13 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:20:17 | 20 | if let Some(ref cake) = Some(&5) {} - | ^^^^^^^^ + | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:27:15 | 27 | 46 => &&a, - | ^^^ + | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrow.rs:49:34 @@ -36,7 +36,7 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:50:31 | 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); - | ^^^^^ + | ^^^^^ help: change this to: `a` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 81f5c691310b3960b4ee59e8a7415050ce284506 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 16 Sep 2017 14:50:07 +0900 Subject: Enhance CHARS_*_CMP lint --- clippy_lints/src/methods.rs | 131 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 08336fca0ae..b36e1851d0d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -7,6 +7,7 @@ use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; +use syntax::ast; use syntax::codemap::Span; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, @@ -544,6 +545,24 @@ declare_lint! { "using `.cloned().collect()` on slice to create a `Vec`" } +/// **What it does:** Checks for usage of `.chars().last()` or +/// `.chars().next_back()` on a `str` to check if it ends with a given char. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.ends_with(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-') +/// ``` +declare_lint! { + pub CHARS_LAST_CMP, + Warn, + "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( @@ -557,6 +576,7 @@ impl LintPass for Pass { OPTION_MAP_UNWRAP_OR_ELSE, OR_FUN_CALL, CHARS_NEXT_CMP, + CHARS_LAST_CMP, CLONE_ON_COPY, CLONE_ON_REF_PTR, CLONE_DOUBLE_REF, @@ -648,9 +668,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }, hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { - if !lint_chars_next(cx, expr, lhs, rhs, op.node == hir::BiEq) { - lint_chars_next(cx, expr, rhs, lhs, op.node == hir::BiEq); - } + let mut info = BinaryExprInfo { + expr: expr, + chain: lhs, + other: rhs, + eq: op.node == hir::BiEq, + }; + lint_binary_expr_with_method_call(cx, &mut info); }, _ => (), } @@ -1285,11 +1309,39 @@ fn lint_search_is_some<'a, 'tcx>( } } -/// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, chain: &'tcx hir::Expr, other: &'tcx hir::Expr, eq: bool) -> bool { +/// Used for `lint_binary_expr_with_method_call`. +#[derive(Copy, Clone)] +struct BinaryExprInfo<'a> { + expr: &'a hir::Expr, + chain: &'a hir::Expr, + other: &'a hir::Expr, + eq: bool, +} + +/// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. +fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, info: &mut BinaryExprInfo) { + macro_rules! lint_with_both_lhs_and_rhs { + ($func:ident, $cx:expr, $info:ident) => { + if !$func($cx, $info) { + ::std::mem::swap(&mut $info.chain, &mut $info.other); + if $func($cx, $info) { + return; + } + } + } + } + + lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); +} + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. +fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { if_let_chain! {[ - let Some(args) = method_chain_args(chain, &["chars", "next"]), - let hir::ExprCall(ref fun, ref arg_char) = other.node, + let Some(args) = method_chain_args(info.chain, chain_methods), + let hir::ExprCall(ref fun, ref arg_char) = info.other.node, arg_char.len() == 1, let hir::ExprPath(ref qpath) = fun.node, let Some(segment) = single_segment_path(qpath), @@ -1302,13 +1354,14 @@ fn lint_chars_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } span_lint_and_sugg(cx, - CHARS_NEXT_CMP, - expr.span, - "you should use the `starts_with` method", + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), "like this", - format!("{}{}.starts_with({})", - if eq { "" } else { "!" }, + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, snippet(cx, args[0][0].span, "_"), + suggest, snippet(cx, arg_char[0].span, "_"))); return true; @@ -1317,6 +1370,60 @@ fn lint_chars_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, false } +/// Checks for the `CHARS_NEXT_CMP` lint. +fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { + lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") +} + +/// Checks for the `CHARS_LAST_CMP` lint. +fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { + if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") { + true + } else { + lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_NEXT_CMP, "ends_with") + } +} + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. +fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { + if_let_chain! {[ + let Some(args) = method_chain_args(info.chain, chain_methods), + let hir::ExprLit(ref lit) = info.other.node, + let ast::LitKind::Char(c) = lit.node, + ], { + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}('{}')", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + c) + ); + + return true; + }} + + false +} + +/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. +fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { + lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") +} + +/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. +fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { + if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { + true + } else { + lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") + } +} + /// lint for length-1 `str`s for methods in `PATTERN_METHODS` fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { let parent_item = cx.tcx.hir.get_parent(arg.id); -- cgit 1.4.1-3-g733a5 From d5d300c0349c350db13009a4889dbcee3e1a509b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 16 Sep 2017 14:50:30 +0900 Subject: Update tests --- tests/ui/methods.rs | 30 +++++++++++++++ tests/ui/methods.stderr | 100 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 3bbaff29c98..48132cc662c 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -547,3 +547,33 @@ fn iter_clone_collect() { let v3 : HashSet = v.iter().cloned().collect(); let v4 : VecDeque = v.iter().cloned().collect(); } + +fn chars_cmp_with_unwrap() { + let s = String::from("foo"); + if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } +} + +#[allow(unnecessary_operation)] +fn ends_with() { + "".chars().last() == Some(' '); + Some(' ') != "".chars().last(); + "".chars().next_back() == Some(' '); + Some(' ') != "".chars().next_back(); +} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index e22fdc116c1..7f3d505a3cd 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -738,5 +738,103 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: aborting due to 107 previous errors +error: you should use the `starts_with` method + --> $DIR/methods.rs:553:8 + | +553 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:553:8 + | +553 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `ends_with` method + --> $DIR/methods.rs:556:8 + | +556 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + | + = note: `-D chars-last-cmp` implied by `-D warnings` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:556:8 + | +556 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `ends_with` method + --> $DIR/methods.rs:559:8 + | +559 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:559:8 + | +559 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `starts_with` method + --> $DIR/methods.rs:562:8 + | +562 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:562:8 + | +562 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `ends_with` method + --> $DIR/methods.rs:565:8 + | +565 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:565:8 + | +565 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `ends_with` method + --> $DIR/methods.rs:568:8 + | +568 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message + --> $DIR/methods.rs:568:8 + | +568 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should use the `ends_with` method + --> $DIR/methods.rs:575:5 + | +575 | "".chars().last() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/methods.rs:576:5 + | +576 | Some(' ') != "".chars().last(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/methods.rs:577:5 + | +577 | "".chars().next_back() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/methods.rs:578:5 + | +578 | Some(' ') != "".chars().next_back(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + +error: aborting due to 123 previous errors -- cgit 1.4.1-3-g733a5 From 72be16675691dbfa326624c7672d9f5ad1f17796 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sat, 16 Sep 2017 09:10:26 +0200 Subject: add suggestions for .clone() in ptr_arg fns --- clippy_lints/src/bytecount.rs | 12 +---- clippy_lints/src/loops.rs | 11 +--- clippy_lints/src/ptr.rs | 123 ++++++++++++++++++++++++++++++++++-------- clippy_lints/src/utils/mod.rs | 21 ++++++++ tests/ui/ptr_arg.rs | 23 +++++++- tests/ui/ptr_arg.stderr | 44 ++++++++++++++- 6 files changed, 189 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 447214c70f8..58f1227d91e 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -2,7 +2,8 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; use syntax::ast::{Name, UintTy}; -use utils::{contains_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, + snippet, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for naive byte counts /// @@ -93,15 +94,6 @@ fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool { name == arg && !contains_name(name, needle) } -fn get_pat_name(pat: &Pat) -> Option { - match pat.node { - PatKind::Binding(_, _, ref spname, _) => Some(spname.node), - PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), - PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), - _ => None, - } -} - fn get_path_name(expr: &Expr) -> Option { match expr.node { ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f06831556c2..3d6f7d56808 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -16,7 +16,7 @@ use utils::sugg; use utils::const_to_u64; use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, - last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, snippet_opt, + last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; use utils::paths; @@ -1271,15 +1271,6 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { } } -fn match_var(expr: &Expr, var: Name) -> bool { - if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == var { - return true; - } - } - false -} - struct UsedVisitor { var: ast::Name, // var to look for used: bool, // has the var been used otherwise? diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 4d119c3a42d..cbba4ad2610 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -1,26 +1,42 @@ //! Checks for usage of `&Vec[_]` and `&String`. use rustc::hir::*; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::map::NodeItem; use rustc::lint::*; use rustc::ty; -use syntax::ast::NodeId; +use syntax::ast::{Name, NodeId}; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, - span_lint_and_sugg, walk_ptrs_hir_ty}; +use utils::{get_pat_name, match_qpath, match_type, match_var, paths, + snippet, snippet_opt, span_lint, span_lint_and_then, + walk_ptrs_hir_ty}; /// **What it does:** This lint checks for function arguments of type `&String` -/// or `&Vec` unless -/// the references are mutable. +/// or `&Vec` unless the references are mutable. It will also suggest you +/// replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()` +/// calls. /// /// **Why is this bad?** Requiring the argument to be of the specific size -/// makes the function less -/// useful for no benefit; slices in the form of `&[T]` or `&str` usually -/// suffice and can be -/// obtained from other types, too. +/// makes the function less useful for no benefit; slices in the form of `&[T]` +/// or `&str` usually suffice and can be obtained from other types, too. /// -/// **Known problems:** None. +/// **Known problems:** The lint does not follow data. So if you have an +/// argument `x` and write `let y = x; y.clone()` the lint will not suggest +/// changing that `.clone()` to `.to_owned()`. +/// +/// Other functions called from this function taking a `&String` or `&Vec` +/// argument may also fail to compile if you change the argument. Applying +/// this lint on them will fix the problem, but they may be in other crates. +/// +/// Also there may be `fn(&Vec)`-typed references pointing to your function. +/// If you have them, you will get a compiler error after applying this lint's +/// suggestions. You then have the choice to undo your changes or change the +/// type of the reference. +/// +/// Note that if the function is part of your public interface, there may be +/// other crates referencing it you may not be aware. Carefully deprecate the +/// function before applying the lint suggestions in this case. /// /// **Example:** /// ```rust @@ -87,25 +103,26 @@ impl LintPass for PointerPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemFn(ref decl, _, _, _, _, _) = item.node { - check_fn(cx, decl, item.id); + if let ItemFn(ref decl, _, _, _, _, body_id) = item.node { + check_fn(cx, decl, item.id, Some(body_id)); } } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { - if let ImplItemKind::Method(ref sig, _) = item.node { + if let ImplItemKind::Method(ref sig, body_id) = item.node { if let Some(NodeItem(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) { if let ItemImpl(_, _, _, _, Some(_), _, _) = it.node { return; // ignore trait impls } } - check_fn(cx, &sig.decl, item.id); + check_fn(cx, &sig.decl, item.id, Some(body_id)); } } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - if let TraitItemKind::Method(ref sig, _) = item.node { - check_fn(cx, &sig.decl, item.id); + if let TraitItemKind::Method(ref sig, ref trait_method) = item.node { + let body_id = if let TraitMethod::Provided(b) = *trait_method { Some(b) } else { None }; + check_fn(cx, &sig.decl, item.id, body_id); } } @@ -123,12 +140,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } } -fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { +fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option) { let fn_def_id = cx.tcx.hir.local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); let fn_ty = sig.skip_binder(); - for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) { + for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { if let ty::TyRef( _, ty::TypeAndMut { @@ -146,7 +163,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { ], { ty_snippet = snippet_opt(cx, parameters.types[0].span); }); - //TODO: Suggestion + let spans = get_spans(cx, opt_body_id, idx, "to_owned"); span_lint_and_then( cx, PTR_ARG, @@ -159,16 +176,30 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { "change this to", format!("&[{}]", snippet)); } + for (clonespan, suggestion) in spans { + db.span_suggestion(clonespan, + "change the `.clone()` to", + suggestion); + } } ); } else if match_type(cx, ty, &paths::STRING) { - span_lint_and_sugg( + let spans = get_spans(cx, opt_body_id, idx, "to_string"); + span_lint_and_then( cx, PTR_ARG, arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do.", - "change this to", - "&str".to_string() + |db| { + db.span_suggestion(arg.span, + "change this to", + "&str".into()); + for (clonespan, suggestion) in spans { + db.span_suggestion_short(clonespan, + "change the `.clone` to ", + suggestion); + } + } ); } } @@ -198,6 +229,54 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { } } +fn get_spans(cx: &LateContext, opt_body_id: Option, idx: usize, fn_name: &'static str) -> Vec<(Span, String)> { + if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { + get_binding_name(&body.arguments[idx]).map_or_else(Vec::new, + |name| extract_clone_suggestions(cx, name, fn_name, body)) + } else { + vec![] + } +} + +fn extract_clone_suggestions<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, name: Name, fn_name: &'static str, body: &'tcx Body) -> Vec<(Span, String)> { + let mut visitor = PtrCloneVisitor { + cx, + name, + fn_name, + spans: vec![] + }; + visitor.visit_body(body); + visitor.spans +} + +struct PtrCloneVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + name: Name, + fn_name: &'static str, + spans: Vec<(Span, String)>, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if let ExprMethodCall(ref seg, _, ref args) = expr.node { + if args.len() == 1 && match_var(&args[0], self.name) && seg.name == "clone" { + self.spans.push((expr.span, format!("{}.{}()", snippet(self.cx, args[0].span, "_"), self.fn_name))); + } + return; + } + walk_expr(self, expr); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + +} + +fn get_binding_name(arg: &Arg) -> Option { + get_pat_name(&arg.pat) +} + fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> { if let Ty_::TyRptr(ref lt, ref m) = ty.node { Some((lt, m.mutbl, ty.span)) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6173073fb76..ec0521ce4f2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -218,6 +218,17 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool } } +/// Check if an expression references a variable of the given name. +pub fn match_var(expr: &Expr, var: Name) -> bool { + if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { + if path.segments.len() == 1 && path.segments[0].name == var { + return true; + } + } + false +} + + pub fn last_path_segment(path: &QPath) -> &PathSegment { match *path { QPath::Resolved(_, ref path) => path.segments @@ -393,6 +404,16 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option { } } +/// Get the name of a `Pat`, if any +pub fn get_pat_name(pat: &Pat) -> Option { + match pat.node { + PatKind::Binding(_, _, ref spname, _) => Some(spname.node), + PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), + PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), + _ => None, + } +} + struct ContainsName { name: Name, result: bool, diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 5649bfec347..a386fcf82df 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,6 +1,6 @@ #![feature(plugin)] #![plugin(clippy)] -#![allow(unused)] +#![allow(unused, many_single_char_names)] #![warn(ptr_arg)] fn do_vec(x: &Vec) { @@ -34,5 +34,24 @@ struct Bar; impl Foo for Bar { type Item = Vec; fn do_vec(x: &Vec) {} - fn do_item(x: &Vec) {} + fn do_item(x: &Vec) {} +} + +fn cloned(x: &Vec) -> Vec { + let e = x.clone(); + let f = e.clone(); // OK + let g = x; + let h = g.clone(); // Alas, we cannot reliably detect this without following data. + let i = (e).clone(); + x.clone() +} + +fn str_cloned(x: &String) -> String { + let a = x.clone(); + let b = x.clone(); + let c = b.clone(); + let d = a.clone() + .clone() + .clone(); + x.clone() } diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 4eafc237a82..46d7cbdb031 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -18,5 +18,47 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and canno 27 | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` -error: aborting due to 3 previous errors +error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. + --> $DIR/ptr_arg.rs:40:14 + | +40 | fn cloned(x: &Vec) -> Vec { + | ^^^^^^^^ + | +help: change this to + | +40 | fn cloned(x: &[u8]) -> Vec { + | ^^^^^ +help: change the `.clone()` to + | +41 | let e = x.to_owned(); + | ^^^^^^^^^^^^ +help: change the `.clone()` to + | +46 | x.to_owned() + | ^^^^^^^^^^^^ + +error: writing `&String` instead of `&str` involves a new object where a slice will do. + --> $DIR/ptr_arg.rs:49:18 + | +49 | fn str_cloned(x: &String) -> String { + | ^^^^^^^ + | +help: change this to + | +49 | fn str_cloned(x: &str) -> String { + | ^^^^ +help: change the `.clone` to + | +50 | let a = x.to_string(); + | ^^^^^^^^^^^^^ +help: change the `.clone` to + | +51 | let b = x.to_string(); + | ^^^^^^^^^^^^^ +help: change the `.clone` to + | +56 | x.to_string() + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From e461e3f9158b3ca4f051bd947d94d91c48aafca1 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 16 Sep 2017 18:45:28 -0400 Subject: Format loops.rs with latest stable rustfmt --- clippy_lints/src/loops.rs | 237 ++++++++++++++++++++++++++-------------------- 1 file changed, 134 insertions(+), 103 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f06831556c2..260f9b8884b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -361,8 +361,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { - ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => if never_loop(block, &expr.id) { - span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); + ExprWhile(_, ref block, _) | + ExprLoop(ref block, _, _) => { + if never_loop(block, &expr.id) { + span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); + } }, _ => (), } @@ -389,7 +392,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { + MatchSource::Normal | + MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_simple_break_expr(&arms[1].body) @@ -424,10 +428,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let ( - &PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args), - ) = (pat, &match_expr.node) + if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), + &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); @@ -474,25 +476,28 @@ fn never_loop(block: &Block, id: &NodeId) -> bool { fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || - block - .expr - .as_ref() - .map_or(false, |e| contains_continue_expr(e, dest)) + block.expr.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) } fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { match stmt.node { - StmtSemi(ref e, _) | StmtExpr(ref e, _) => contains_continue_expr(e, dest), + StmtSemi(ref e, _) | + StmtExpr(ref e, _) => contains_continue_expr(e, dest), StmtDecl(ref d, _) => contains_continue_decl(d, dest), } } fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { match decl.node { - DeclLocal(ref local) => local - .init - .as_ref() - .map_or(false, |e| contains_continue_expr(e, dest)), + DeclLocal(ref local) => { + local.init.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) + }, _ => false, } } @@ -508,9 +513,9 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => contains_continue_expr(e, dest), - ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => { - es.iter().any(|e| contains_continue_expr(e, dest)) - }, + ExprArray(ref es) | + ExprMethodCall(_, _, ref es) | + ExprTup(ref es) => es.iter().any(|e| contains_continue_expr(e, dest)), ExprCall(ref e, ref es) => { contains_continue_expr(e, dest) || es.iter().any(|e| contains_continue_expr(e, dest)) }, @@ -518,17 +523,23 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| contains_continue_expr(e, dest)), - ExprIf(ref e, ref e2, ref e3) => [e, e2] - .iter() - .chain(e3.as_ref().iter()) - .any(|e| contains_continue_expr(e, dest)), + ExprIf(ref e, ref e2, ref e3) => { + [e, e2].iter().chain(e3.as_ref().iter()).any(|e| { + contains_continue_expr(e, dest) + }) + }, ExprWhile(ref e, ref b, _) => contains_continue_expr(e, dest) || contains_continue_block(b, dest), ExprMatch(ref e, ref arms, _) => { contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) }, - ExprBlock(ref block) | ExprLoop(ref block, ..) => contains_continue_block(block, dest), - ExprStruct(_, _, ref base) => base.as_ref() - .map_or(false, |e| contains_continue_expr(e, dest)), + ExprBlock(ref block) | + ExprLoop(ref block, ..) => contains_continue_block(block, dest), + ExprStruct(_, _, ref base) => { + base.as_ref().map_or( + false, + |e| contains_continue_expr(e, dest), + ) + }, ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), _ => false, } @@ -540,7 +551,8 @@ fn loop_exit_block(block: &Block) -> bool { fn loop_exit_stmt(stmt: &Stmt) -> bool { match stmt.node { - StmtSemi(ref e, _) | StmtExpr(ref e, _) => loop_exit_expr(e), + StmtSemi(ref e, _) | + StmtExpr(ref e, _) => loop_exit_expr(e), StmtDecl(ref d, _) => loop_exit_decl(d), } } @@ -562,7 +574,9 @@ fn loop_exit_expr(expr: &Expr) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => loop_exit_expr(e), - ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), + ExprArray(ref es) | + ExprMethodCall(_, _, ref es) | + ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), ExprCall(ref e, ref es) => loop_exit_expr(e) || es.iter().any(|e| loop_exit_expr(e)), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | @@ -648,9 +662,11 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option { match e.node { - ExprLit(ref l) => match l.node { - ast::LitKind::Int(x, _ty) => Some(x.to_string()), - _ => None, + ExprLit(ref l) => { + match l.node { + ast::LitKind::Int(x, _ty) => Some(x.to_string()), + _ => None, + } }, ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), _ => None, @@ -664,25 +680,29 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: } let offset = match idx.node { - ExprBinary(op, ref lhs, ref rhs) => match op.node { - BinOp_::BiAdd => { - let offset_opt = if same_var(cx, lhs, var) { - extract_offset(cx, rhs, var) - } else if same_var(cx, rhs, var) { - extract_offset(cx, lhs, var) - } else { - None - }; + ExprBinary(op, ref lhs, ref rhs) => { + match op.node { + BinOp_::BiAdd => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; - offset_opt.map(Offset::positive) - }, - BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), - _ => None, + offset_opt.map(Offset::positive) + }, + BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), + _ => None, + } }, - ExprPath(..) => if same_var(cx, idx, var) { - Some(Offset::positive("0".into())) - } else { - None + ExprPath(..) => { + if same_var(cx, idx, var) { + Some(Offset::positive("0".into())) + } else { + None + } }, _ => None, }; @@ -729,13 +749,12 @@ fn get_indexed_assignments<'a, 'tcx>( .iter() .map(|stmt| match stmt.node { Stmt_::StmtDecl(..) => None, - Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + Stmt_::StmtExpr(ref e, _node_id) | + Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), }) - .chain( - expr.as_ref() - .into_iter() - .map(|e| Some(get_assignment(cx, &*e, var))), - ) + .chain(expr.as_ref().into_iter().map(|e| { + Some(get_assignment(cx, &*e, var)) + })) .filter_map(|op| op) .collect::>>() .unwrap_or_else(|| vec![]) @@ -754,18 +773,20 @@ fn detect_manual_memcpy<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.node { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), - ("0", _, x, false) | (x, false, "0", false) => x.into(), - ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), + ("0", _, x, false) | + (x, false, "0", false) => x.into(), + ("0", _, x, true) | + (x, false, "0", true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), (x, false, y, true) => format!("({} - {})", x, y), (x, true, y, false) => format!("({} - {})", y, x), @@ -847,10 +868,10 @@ fn check_for_loop_range<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { @@ -865,11 +886,9 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor - .indexed - .into_iter() - .next() - .expect("already checked that we have exactly 1 element"); + let (indexed, indexed_extent) = visitor.indexed.into_iter().next().expect( + "already checked that we have exactly 1 element", + ); // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { @@ -973,10 +992,10 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr, expr: &'tcx Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(arg) + start: Some(start), + end: Some(end), + limits, + }) = higher::range(arg) { // ...and both sides are compile-time constant integers... let parent_item = cx.tcx.hir.get_parent(arg.id); @@ -990,7 +1009,8 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, end_idx) { - (&ty::Const{ val: ConstVal::Integral(start_idx), .. }, &ty::Const{ val: ConstVal::Integral(end_idx), .. }) => { + (&ty::Const { val: ConstVal::Integral(start_idx), .. }, + &ty::Const { val: ConstVal::Integral(end_idx), .. }) => { (start_idx > end_idx, start_idx == end_idx) }, _ => (false, false), @@ -1162,14 +1182,14 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id) - .and_then(|id| map.get_enclosing_scope(id)); + let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| { + map.get_enclosing_scope(id) + }); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor - .states - .iter() - .filter(|&(_, v)| *v == VarState::IncrOnce) + for (id, _) in visitor.states.iter().filter( + |&(_, v)| *v == VarState::IncrOnce, + ) { let mut visitor2 = InitializeVisitor { cx: cx, @@ -1216,10 +1236,12 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ref tam) => match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), - (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), - _ => return, + ty::TyRef(_, ref tam) => { + match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), + _ => return, + } }, _ => return, }; @@ -1282,7 +1304,7 @@ fn match_var(expr: &Expr, var: Name) -> bool { struct UsedVisitor { var: ast::Name, // var to look for - used: bool, // has the var been used otherwise? + used: bool, // has the var been used otherwise? } impl<'tcx> Visitor<'tcx> for UsedVisitor { @@ -1299,7 +1321,7 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor { } } -struct LocalUsedVisitor <'a, 'tcx: 'a> { +struct LocalUsedVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, local: ast::NodeId, used: bool, @@ -1492,15 +1514,19 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), - None if !block.stmts.is_empty() => match block.stmts[0].node { - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), - StmtDecl(..) => None, + None if !block.stmts.is_empty() => { + match block.stmts[0].node { + StmtExpr(ref expr, _) | + StmtSemi(ref expr, _) => Some(expr), + StmtDecl(..) => None, + } }, _ => None, } } -/// Return true if expr contains a single break expr without destination label and +/// Return true if expr contains a single break expr without destination label +/// and /// passed expression. The expression may be within a block. fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { @@ -1520,7 +1546,7 @@ fn is_simple_break_expr(expr: &Expr) -> bool { // at the start of the loop. #[derive(PartialEq)] enum VarState { - Initial, // Not examined yet + Initial, // Not examined yet IncrOnce, // Incremented exactly once, may be a loop counter Declared, // Declared but not (yet) initialized to zero Warn, @@ -1529,9 +1555,9 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'a, 'tcx>, // context reference states: HashMap, // incremented variables - depth: u32, // depth of conditional expressions + depth: u32, // depth of conditional expressions done: bool, } @@ -1585,7 +1611,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { /// Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, // context reference - end_expr: &'tcx Expr, // the for loop. Stop scanning here. + end_expr: &'tcx Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, name: Option, @@ -1716,11 +1742,13 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool return false; } match cx.tcx.hir.find(parent) { - Some(NodeExpr(expr)) => match expr.node { - ExprLoop(..) | ExprWhile(..) => { - return true; - }, - _ => (), + Some(NodeExpr(expr)) => { + match expr.node { + ExprLoop(..) | ExprWhile(..) => { + return true; + }, + _ => (), + } }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { @@ -1744,8 +1772,8 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool #[derive(PartialEq, Eq)] enum Nesting { - Unknown, // no nesting detected yet - RuledOut, // the iterator is initialized or assigned within scope + Unknown, // no nesting detected yet + RuledOut, // the iterator is initialized or assigned within scope LookFurther, // no nesting detected, no further walk required } @@ -1775,8 +1803,11 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { - self.nesting = RuledOut; + ExprAssign(ref path, _) | + ExprAssignOp(_, ref path, _) => { + if match_var(path, self.iterator) { + self.nesting = RuledOut; + } }, _ => walk_expr(self, expr), } -- cgit 1.4.1-3-g733a5 From a6206cc5f88a1a5396425269c04f91e9e92a3261 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 16 Sep 2017 18:53:55 -0400 Subject: Add test for manual slice clones --- tests/ui/for_loop.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index b4aee6d8ce2..aa8b9632293 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -541,3 +541,10 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { dst_vec[i] = src[i]; } } + +#[warn(needless_range_loop)] +pub fn manual_clone(src: &[String], dst: &mut [String]) { + for i in 0..src.len() { + dst[i] = src[i].clone(); + } +} -- cgit 1.4.1-3-g733a5 From 48ed3c058f0e24dab66ce486d0080e96634529c6 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 16 Sep 2017 19:17:22 -0400 Subject: Extend MANUAL_MEMCPY lint so that it also detects manual clones between slices --- clippy_lints/src/loops.rs | 19 ++++++++++++++++++- tests/ui/for_loop.stderr | 10 +++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 260f9b8884b..5beb7eab71d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -718,6 +718,23 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: } } +fn fetch_cloned_fixed_offset_var<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &Expr, + var: ast::NodeId, +) -> Option { + if_let_chain! {[ + let ExprMethodCall(ref method, _, ref args) = expr.node, + method.name == "clone", + args.len() == 1, + let Some(arg) = args.get(0), + ], { + return get_fixed_offset_var(cx, arg, var); + }} + + get_fixed_offset_var(cx, expr, var) +} + fn get_indexed_assignments<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, body: &Expr, @@ -729,7 +746,7 @@ fn get_indexed_assignments<'a, 'tcx>( var: ast::NodeId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { - match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) { + match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) { (Some(offset_left), Some(offset_right)) => Some((offset_left, offset_right)), _ => None, } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 721b2833dec..79c6c781a7a 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -578,5 +578,13 @@ error: it looks like you're manually copying between slices 522 | | } | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` -error: aborting due to 58 previous errors +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:547:5 + | +547 | / for i in 0..src.len() { +548 | | dst[i] = src[i].clone(); +549 | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` + +error: aborting due to 59 previous errors -- cgit 1.4.1-3-g733a5 From d7ea6addf06f0db99f4d21b229c7bfea223d827d Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 17 Sep 2017 17:18:12 +0100 Subject: (#1955): Suggests `x > y` over `x >= y + 1` for ints This module handles the following cases: - `... >= ... + 1` and `... >= 1 + ...` - `... - 1 >= ...` and `-1 + ... >= ...` - `... + 1 <= ...` and `... + 1 <= ...` - `... <= ... - 1` and `... <= -1 + ...` Note: this only goes 1 level deep (i.e., does not constant-fold) and does not currently simplify expressions. Examples of these cases include: ```rust let x = 1; y >= y + x; // won't catch this case or any permutation x + 1 >= y + 2; // won't catch this case x + 1 - 1 >= y - 1 + 1; // WILL catch this case when it likely shouldn't ``` --- clippy_lints/src/int_plus_one.rs | 115 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 clippy_lints/src/int_plus_one.rs diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs new file mode 100644 index 00000000000..75538e7946e --- /dev/null +++ b/clippy_lints/src/int_plus_one.rs @@ -0,0 +1,115 @@ +//! lint on blocks unnecessarily using >= with a + 1 or - 1 + +use rustc::lint::*; +use syntax::ast::*; + +use utils::span_help_and_lint; + +/// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block +/// +/// +/// **Why is this bad?** Readability -- better to use `> y` instead of `>= y + 1`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x >= y + 1 +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// x > y +/// ``` +declare_lint! { + pub INT_PLUS_ONE, + Allow, + "instead of using x >= y + 1, use x > y" +} + +pub struct IntPlusOne; + +impl LintPass for IntPlusOne { + fn get_lints(&self) -> LintArray { + lint_array!(INT_PLUS_ONE) + } +} + +// cases: +// BinOpKind::Ge +// x >= y + 1 +// x - 1 >= y +// +// BinOpKind::Le +// x + 1 <= y +// x <= y - 1 + +impl IntPlusOne { + #[allow(cast_sign_loss)] + fn check_lit(&self, lit: &Lit, target_value: i128) -> bool { + if let LitKind::Int(value, ..) = lit.node { + return value == (target_value as u128) + } + false + } + + fn check_binop(&self, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> bool { + match (binop, &lhs.node, &rhs.node) { + // case where `x - 1 >= ...` or `-1 + x >= ...` + (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { + match (lhskind.node, &lhslhs.node, &lhsrhs.node) { + // `-1 + x` + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1), + // `x - 1` + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), + _ => false + } + }, + // case where `... >= y + 1` or `... >= 1 + y` + (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) if rhskind.node == BinOpKind::Add => { + match (&rhslhs.node, &rhsrhs.node) { + // `y + 1` and `1 + y` + (&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), + _ => false + } + }, + // case where `x + 1 <= ...` or `1 + x <= ...` + (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => { + match (&lhslhs.node, &lhsrhs.node) { + // `1 + x` and `x + 1` + (&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), + _ => false + } + }, + // case where `... >= y - 1` or `... >= -1 + y` + (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => { + match (rhskind.node, &rhslhs.node, &rhsrhs.node) { + // `-1 + y` + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1), + // `y - 1` + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), + _ => false + } + }, + _ => false + } + } + +} + +impl EarlyLintPass for IntPlusOne { + fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node { + if self.check_binop(kind.node, lhs, rhs) { + span_help_and_lint( + cx, + INT_PLUS_ONE, + item.span, + "Unnecessary `>= y + 1` or `x - 1 >=`", + "Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`", + ); + } + } + } +} -- cgit 1.4.1-3-g733a5 From 535302efda3b36b850f74019adc3f0e9823efeba Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 17 Sep 2017 17:27:16 +0100 Subject: Register 'int_plus_one' lint case in clippy_lints --- clippy_lints/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 520f9362c0f..e8b468e13f6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -96,6 +96,7 @@ pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; pub mod infinite_iter; +pub mod int_plus_one; pub mod is_unit_expr; pub mod items_after_statements; pub mod large_enum_variant; @@ -299,6 +300,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); + reg.register_early_lint_pass(box int_plus_one::IntPlusOne); reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); @@ -341,6 +343,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, + int_plus_one::INT_PLUS_ONE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, -- cgit 1.4.1-3-g733a5 From bb40bd68a460b024a6141db290dccd51bdc7f747 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 17 Sep 2017 17:27:40 +0100 Subject: Add tests for 'int_plus_one' --- tests/ui/int_plus_one.rs | 18 ++++++++++++++++++ tests/ui/int_plus_one.stderr | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/ui/int_plus_one.rs create mode 100644 tests/ui/int_plus_one.stderr diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs new file mode 100644 index 00000000000..90375dad555 --- /dev/null +++ b/tests/ui/int_plus_one.rs @@ -0,0 +1,18 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[allow(no_effect, unnecessary_operation)] +#[warn(int_plus_one)] +fn main() { + let x = 1i32; + let y = 0i32; + + x >= y + 1; + y + 1 <= x; + + x - 1 >= y; + y <= x - 1; + + x > y; // should be ok + y < x; // should be ok +} diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr new file mode 100644 index 00000000000..fd39e038e01 --- /dev/null +++ b/tests/ui/int_plus_one.stderr @@ -0,0 +1,35 @@ +error: Unnecessary `>= y + 1` or `x - 1 >=` + --> $DIR/int_plus_one.rs:10:5 + | +10 | x >= y + 1; + | ^^^^^^^^^^ + | + = note: `-D int-plus-one` implied by `-D warnings` + = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` + +error: Unnecessary `>= y + 1` or `x - 1 >=` + --> $DIR/int_plus_one.rs:11:5 + | +11 | y + 1 <= x; + | ^^^^^^^^^^ + | + = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` + +error: Unnecessary `>= y + 1` or `x - 1 >=` + --> $DIR/int_plus_one.rs:13:5 + | +13 | x - 1 >= y; + | ^^^^^^^^^^ + | + = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` + +error: Unnecessary `>= y + 1` or `x - 1 >=` + --> $DIR/int_plus_one.rs:14:5 + | +14 | y <= x - 1; + | ^^^^^^^^^^ + | + = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 62ae6d225185843a5b0d9d543e2f710d1a3306cc Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Mon, 18 Sep 2017 14:44:28 +0000 Subject: lints/doc_markdown: add two more entries --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 7251538c09a..3c05fca316f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -154,7 +154,7 @@ define_Conf! { "JavaScript", "NaN", "OAuth", - "OpenGL", + "OpenGL", "OpenSSH", "OpenSSL", "TrueType", "iOS", "macOS", "TeX", "LaTeX", "BibTex", "BibLaTex", -- cgit 1.4.1-3-g733a5 From f680eb164d8365160d6d43ca2589d95b97d5610b Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Mon, 18 Sep 2017 20:07:33 +0100 Subject: Update unnecessary_operation and no_effect to not suggest removing structs/enums wrappers when that type implements Drop as noted in #2061. --- clippy_lints/src/no_effect.rs | 39 +++++--- tests/ui/no_effect.rs | 35 +++++++ tests/ui/no_effect.stderr | 220 +++++++++++++++++++++--------------------- 3 files changed, 172 insertions(+), 122 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 1d5e51187bb..230c811935c 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -40,12 +40,22 @@ declare_lint! { "outer expressions with no effect" } +/// Check whether this type implements Drop. +fn has_drop(cx: &LateContext, expr: &Expr) -> bool { + let struct_ty = cx.tables.expr_ty(expr); + match struct_ty.ty_adt_def() { + Some(def) => def.has_dtor(cx.tcx), + _ => false, + } +} + fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { if in_macro(expr.span) { return false; } match expr.node { - Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) | Expr_::ExprPath(..) => true, + Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) => true, + Expr_::ExprPath(..) => !has_drop(cx, expr), Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => { has_no_effect(cx, a) && has_no_effect(cx, b) }, @@ -59,7 +69,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { Expr_::ExprAddrOf(_, ref inner) | Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), Expr_::ExprStruct(_, ref fields, ref base) => { - fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { + !has_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { Some(ref base) => has_no_effect(cx, base), None => true, } @@ -68,7 +78,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { - args.iter().all(|arg| has_no_effect(cx, arg)) + !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg)) }, _ => false, } @@ -145,18 +155,23 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => Some( - fields - .iter() - .map(|f| &f.expr) - .chain(base) - .map(Deref::deref) - .collect(), - ), + Expr_::ExprStruct(_, ref fields, ref base) => { + if has_drop(cx, expr) { + None + } else { + Some( + fields + .iter() + .map(|f| &f.expr) + .chain(base) + .map(Deref::deref) + .collect()) + } + }, Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { - Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) if !has_drop(cx, expr) => { Some(args.iter().collect()) }, _ => None, diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index bef1fad4f69..4062b36883a 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -16,6 +16,27 @@ enum Enum { Tuple(i32), Struct { field: i32 }, } +struct DropUnit; +impl Drop for DropUnit { + fn drop(&mut self) {} +} +struct DropStruct { + field: i32 +} +impl Drop for DropStruct { + fn drop(&mut self) {} +} +struct DropTuple(i32); +impl Drop for DropTuple { + fn drop(&mut self) {} +} +enum DropEnum { + Tuple(i32), + Struct { field: i32 }, +} +impl Drop for DropEnum { + fn drop(&mut self) {} +} union Union { a: u8, @@ -24,6 +45,7 @@ union Union { fn get_number() -> i32 { 0 } fn get_struct() -> Struct { Struct { field: 0 } } +fn get_drop_struct() -> DropStruct { DropStruct { field: 0 } } unsafe fn unsafe_fn() -> i32 { 0 } @@ -61,6 +83,11 @@ fn main() { // Do not warn get_number(); unsafe { unsafe_fn() }; + DropUnit; + DropStruct { field: 0 }; + DropTuple(0); + DropEnum::Tuple(0); + DropEnum::Struct { field: 0 }; Tuple(get_number()); Struct { field: get_number() }; @@ -81,4 +108,12 @@ fn main() { [get_number(); 55]; [42; 55][get_number() as usize]; {get_number()}; + + // Do not warn + DropTuple(get_number()); + DropStruct { field: get_number() }; + DropStruct { field: get_number() }; + DropStruct { ..get_drop_struct() }; + DropEnum::Tuple(get_number()); + DropEnum::Struct { field: get_number() }; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 590b1eab497..c7c334546ff 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,270 +1,270 @@ error: statement with no effect - --> $DIR/no_effect.rs:34:5 + --> $DIR/no_effect.rs:56:5 | -34 | 0; +56 | 0; | ^^ | = note: `-D no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:35:5 + --> $DIR/no_effect.rs:57:5 | -35 | s2; +57 | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:36:5 + --> $DIR/no_effect.rs:58:5 | -36 | Unit; +58 | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:37:5 + --> $DIR/no_effect.rs:59:5 | -37 | Tuple(0); +59 | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:38:5 + --> $DIR/no_effect.rs:60:5 | -38 | Struct { field: 0 }; +60 | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:39:5 + --> $DIR/no_effect.rs:61:5 | -39 | Struct { ..s }; +61 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:40:5 + --> $DIR/no_effect.rs:62:5 | -40 | Union { a: 0 }; +62 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:41:5 + --> $DIR/no_effect.rs:63:5 | -41 | Enum::Tuple(0); +63 | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:42:5 + --> $DIR/no_effect.rs:64:5 | -42 | Enum::Struct { field: 0 }; +64 | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:43:5 + --> $DIR/no_effect.rs:65:5 | -43 | 5 + 6; +65 | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:44:5 + --> $DIR/no_effect.rs:66:5 | -44 | *&42; +66 | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:45:5 + --> $DIR/no_effect.rs:67:5 | -45 | &6; +67 | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:46:5 + --> $DIR/no_effect.rs:68:5 | -46 | (5, 6, 7); +68 | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:47:5 + --> $DIR/no_effect.rs:69:5 | -47 | box 42; +69 | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:48:5 + --> $DIR/no_effect.rs:70:5 | -48 | ..; +70 | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:49:5 + --> $DIR/no_effect.rs:71:5 | -49 | 5..; +71 | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:50:5 + --> $DIR/no_effect.rs:72:5 | -50 | ..5; +72 | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:51:5 + --> $DIR/no_effect.rs:73:5 | -51 | 5..6; +73 | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:52:5 + --> $DIR/no_effect.rs:74:5 | -52 | 5...6; +74 | 5...6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:53:5 + --> $DIR/no_effect.rs:75:5 | -53 | [42, 55]; +75 | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:54:5 + --> $DIR/no_effect.rs:76:5 | -54 | [42, 55][1]; +76 | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:55:5 + --> $DIR/no_effect.rs:77:5 | -55 | (42, 55).1; +77 | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:56:5 + --> $DIR/no_effect.rs:78:5 | -56 | [42; 55]; +78 | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:57:5 + --> $DIR/no_effect.rs:79:5 | -57 | [42; 55][13]; +79 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:59:5 + --> $DIR/no_effect.rs:81:5 | -59 | || x += 5; +81 | || x += 5; | ^^^^^^^^^^ error: statement can be reduced - --> $DIR/no_effect.rs:65:5 + --> $DIR/no_effect.rs:92:5 | -65 | Tuple(get_number()); +92 | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | = note: `-D unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/no_effect.rs:66:5 + --> $DIR/no_effect.rs:93:5 | -66 | Struct { field: get_number() }; +93 | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:67:5 + --> $DIR/no_effect.rs:94:5 | -67 | Struct { ..get_struct() }; +94 | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/no_effect.rs:68:5 + --> $DIR/no_effect.rs:95:5 | -68 | Enum::Tuple(get_number()); +95 | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:69:5 + --> $DIR/no_effect.rs:96:5 | -69 | Enum::Struct { field: get_number() }; +96 | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:70:5 + --> $DIR/no_effect.rs:97:5 | -70 | 5 + get_number(); +97 | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:98:5 | -71 | *&get_number(); +98 | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:99:5 | -72 | &get_number(); +99 | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:73:5 - | -73 | (5, 6, get_number()); - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` + --> $DIR/no_effect.rs:100:5 + | +100 | (5, 6, get_number()); + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:74:5 - | -74 | box get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:101:5 + | +101 | box get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:75:5 - | -75 | get_number()..; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:102:5 + | +102 | get_number()..; + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:76:5 - | -76 | ..get_number(); - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:103:5 + | +103 | ..get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:77:5 - | -77 | 5..get_number(); - | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` + --> $DIR/no_effect.rs:104:5 + | +104 | 5..get_number(); + | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:78:5 - | -78 | [42, get_number()]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` + --> $DIR/no_effect.rs:105:5 + | +105 | [42, get_number()]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:79:5 - | -79 | [42, 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` + --> $DIR/no_effect.rs:106:5 + | +106 | [42, 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:80:5 - | -80 | (42, get_number()).1; - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` + --> $DIR/no_effect.rs:107:5 + | +107 | (42, get_number()).1; + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:81:5 - | -81 | [get_number(); 55]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:108:5 + | +108 | [get_number(); 55]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:82:5 - | -82 | [42; 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` + --> $DIR/no_effect.rs:109:5 + | +109 | [42; 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:83:5 - | -83 | {get_number()}; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:110:5 + | +110 | {get_number()}; + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: aborting due to 44 previous errors -- cgit 1.4.1-3-g733a5 From 0b64222a68abb56798ddb57dbbd1fb3ddf2e4b9e Mon Sep 17 00:00:00 2001 From: Martin Carton Date: Mon, 18 Sep 2017 22:40:00 +0200 Subject: Fix case in doc_valid_idents BibTeX and BibLaTeX use the usual capitalization of TeX tools: - https://www.ctan.org/pkg/bibtex - https://www.ctan.org/pkg/biblatex --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 3c05fca316f..f88294763dc 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -157,7 +157,7 @@ define_Conf! { "OpenGL", "OpenSSH", "OpenSSL", "TrueType", "iOS", "macOS", - "TeX", "LaTeX", "BibTex", "BibLaTex", + "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", ] => Vec), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have -- cgit 1.4.1-3-g733a5 From 35fa4429e3889cc87c2087d5faa351b5861d408c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 Sep 2017 20:23:08 -0700 Subject: Rust upgrade to rustc 1.22.0-nightly (0701b37d9 2017-09-18) --- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/consts.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index db57864cb2f..9b64a42d4f7 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -307,7 +307,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { cx.tcx.mir_const_qualif(def_id); cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id)) } else { - cx.tcx.extern_const_body(def_id) + cx.tcx.extern_const_body(def_id).body }; fetch_int_literal(cx, &body.value) }) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 2611ba1adf2..7e6f3c2acf1 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -298,7 +298,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { self.tcx.mir_const_qualif(def_id); self.tcx.hir.body(self.tcx.hir.body_owned_by(id)) } else { - self.tcx.extern_const_body(def_id) + self.tcx.extern_const_body(def_id).body }; let ret = cx.expr(&body.value); if ret.is_some() { -- cgit 1.4.1-3-g733a5 From 31489d75a3492f3e6e0d2394d54caa9ea69df084 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 Sep 2017 20:26:36 -0700 Subject: Bump to 0.0.162 --- CHANGELOG.md | 6 ++++++ Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 1 + 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 989f9f2da78..d000f2dd999 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.162 +* Update to *rustc 1.22.0-nightly (0701b37d9 2017-09-18)* +* New lint: [`chars_last_cmp`] +* Improved suggestions for [`needless_borrow`], [`ptr_arg`], + ## 0.0.161 * Update to *rustc 1.22.0-nightly (539f2083d 2017-09-13)* @@ -457,6 +462,7 @@ All notable changes to this project will be documented in this file. [`cast_precision_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_precision_loss [`cast_sign_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_sign_loss [`char_lit_as_u8`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#char_lit_as_u8 +[`chars_last_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_last_cmp [`chars_next_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_next_cmp [`clone_double_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_double_ref [`clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_copy diff --git a/Cargo.lock b/Cargo.lock index ffc84a488eb..88f1a8a7f3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.161" +version = "0.0.162" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,11 +73,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.161" +version = "0.0.162" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.161", + "clippy_lints 0.0.162", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 41ea684f327..46780712ad9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.161" +version = "0.0.162" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.161", path = "clippy_lints" } +clippy_lints = { version = "0.0.162", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index fee0391dacd..ef527dbf039 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.161" +version = "0.0.162" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 520f9362c0f..5cb7034c7bf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -458,6 +458,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { matches::MATCH_REF_PATS, matches::MATCH_WILD_ERR_ARM, matches::SINGLE_MATCH, + methods::CHARS_LAST_CMP, methods::CHARS_NEXT_CMP, methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, -- cgit 1.4.1-3-g733a5 From 9a0a8a0010e0da18d664e8895a3d73b784f026b8 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Tue, 19 Sep 2017 21:38:35 +0100 Subject: Move has_drop to the utils module. --- clippy_lints/src/no_effect.rs | 11 +---------- clippy_lints/src/utils/mod.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 230c811935c..f5543821949 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; -use utils::{in_macro, snippet_opt, span_lint, span_lint_and_sugg}; +use utils::{in_macro, snippet_opt, span_lint, span_lint_and_sugg, has_drop}; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. @@ -40,15 +40,6 @@ declare_lint! { "outer expressions with no effect" } -/// Check whether this type implements Drop. -fn has_drop(cx: &LateContext, expr: &Expr) -> bool { - let struct_ty = cx.tables.expr_ty(expr); - match struct_ty.ty_adt_def() { - Some(def) => def.has_dtor(cx.tcx), - _ => false, - } -} - fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { if in_macro(expr.span) { return false; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ec0521ce4f2..cf0aaf6dbaa 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -358,6 +358,15 @@ pub fn implements_trait<'a, 'tcx>( }) } +/// Check whether this type implements Drop. +pub fn has_drop(cx: &LateContext, expr: &Expr) -> bool { + let struct_ty = cx.tables.expr_ty(expr); + match struct_ty.ty_adt_def() { + Some(def) => def.has_dtor(cx.tcx), + _ => false, + } +} + /// Resolve the definition of a node from its `HirId`. pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: HirId) -> def::Def { cx.tables.qpath_def(qpath, id) -- cgit 1.4.1-3-g733a5 From 1e0268fda85abecd3b9f6d2f6d401c51ca09acc1 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 20 Sep 2017 23:59:23 +0200 Subject: avoid linting `ptr_arg` if `.capacity()` is called. Also suggest removing `.as_str()` where applicable. THis fixes #2070. Also fixes a few formatting mishaps --- Cargo.lock | 64 ++++++++--------- clippy_lints/src/literal_digit_grouping.rs | 16 +++-- clippy_lints/src/missing_doc.rs | 11 +-- clippy_lints/src/print.rs | 3 +- clippy_lints/src/ptr.rs | 111 +++++++++++++++++------------ clippy_lints/src/utils/conf.rs | 9 ++- tests/ui/ptr_arg.rs | 12 ++++ tests/ui/ptr_arg.stderr | 31 ++++++-- 8 files changed, 154 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88f1a8a7f3a..53e3cc9ff6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,8 +9,8 @@ dependencies = [ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -28,22 +28,22 @@ name = "backtrace" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -61,11 +61,16 @@ name = "cargo_metadata" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.2" @@ -82,8 +87,8 @@ dependencies = [ "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -137,11 +142,6 @@ dependencies = [ "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gcc" -version = "0.3.53" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "getopts" version = "0.2.15" @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -181,7 +181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -199,7 +199,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -289,12 +289,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -317,9 +317,9 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -328,7 +328,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -364,7 +364,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -408,10 +408,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" -"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" +"checksum backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c63ea141ef8fdb10409d0f5daf30ac51f84ef43bff66f16627773d2a292cd189" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" +"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2741d378feb7a434dba54228c89a70b4e427fee521de67cdda3750b8a0265f5a" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" @@ -419,14 +420,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" "checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" -"checksum itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac17257442c2ed77dbc9fd555cf83c58b0c7f7d0e8f2ae08c0ac05c72842e1f6" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" +"checksum libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d1419b2939a0bc44b77feb34661583c7546b532b192feab36249ab584b86856c" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" @@ -442,8 +442,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34" -"checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c" +"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799" +"checksum serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1afcaae083fd1c46952a315062326bc9957f182358eb7da03b57ef1c688f7aa9" "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index 1cd539eac39..b656fed1cfb 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -279,12 +279,19 @@ impl LiteralDigitGrouping { let fractional_part = &parts[1].chars().rev().collect::(); let _ = Self::do_lint(fractional_part) .map(|fractional_group_size| { - let consistent = Self::parts_consistent(integral_group_size, fractional_group_size, parts[0].len(), parts[1].len()); + let consistent = Self::parts_consistent(integral_group_size, + fractional_group_size, + parts[0].len(), + parts[1].len()); if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), cx, &lit.span); + WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), + cx, + &lit.span); } }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), + cx, + &lit.span)); } }) .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); @@ -332,7 +339,8 @@ impl LiteralDigitGrouping { .windows(2) .all(|ps| ps[1] - ps[0] == group_size + 1) // number of digits to the left of the last group cannot be bigger than group size. - && (digits.len() - underscore_positions.last().expect("there's at least one element") <= group_size + 1); + && (digits.len() - underscore_positions.last() + .expect("there's at least one element") <= group_size + 1); if !consistent { return Err(WarningType::InconsistentDigitGrouping); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 81a8b4ffb2e..2ad6c36ab5f 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -15,16 +15,7 @@ // *rustc*'s // [`missing_doc`]. // -// [`missing_doc`]: -// https://github. -// com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin. -// -// -// -// -// -// -// rs#L246 +// [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246 // use rustc::hir; diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 1f24a7af052..078e208467a 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -124,7 +124,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { if let ExprPath(ref qpath) = args[1].node { if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { + if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) + && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index cbba4ad2610..69ba0d8bccf 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -1,5 +1,6 @@ //! Checks for usage of `&Vec[_]` and `&String`. +use std::borrow::Cow; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::map::NodeItem; @@ -163,44 +164,48 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< ], { ty_snippet = snippet_opt(cx, parameters.types[0].span); }); - let spans = get_spans(cx, opt_body_id, idx, "to_owned"); - span_lint_and_then( - cx, - PTR_ARG, - arg.span, - "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices.", - |db| { - if let Some(ref snippet) = ty_snippet { - db.span_suggestion(arg.span, - "change this to", - format!("&[{}]", snippet)); + if let Ok(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { + span_lint_and_then( + cx, + PTR_ARG, + arg.span, + "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ + with non-Vec-based slices.", + |db| { + if let Some(ref snippet) = ty_snippet { + db.span_suggestion(arg.span, + "change this to", + format!("&[{}]", snippet)); + } + for (clonespan, suggestion) in spans { + db.span_suggestion(clonespan, + &snippet_opt(cx, clonespan).map_or("change the call to".into(), + |x| Cow::Owned(format!("change `{}` to", x))), + suggestion.into()); + } } - for (clonespan, suggestion) in spans { - db.span_suggestion(clonespan, - "change the `.clone()` to", - suggestion); - } - } - ); + ); + } } else if match_type(cx, ty, &paths::STRING) { - let spans = get_spans(cx, opt_body_id, idx, "to_string"); - span_lint_and_then( - cx, - PTR_ARG, - arg.span, - "writing `&String` instead of `&str` involves a new object where a slice will do.", - |db| { - db.span_suggestion(arg.span, - "change this to", - "&str".into()); - for (clonespan, suggestion) in spans { - db.span_suggestion_short(clonespan, - "change the `.clone` to ", - suggestion); + if let Ok(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { + span_lint_and_then( + cx, + PTR_ARG, + arg.span, + "writing `&String` instead of `&str` involves a new object where a slice will do.", + |db| { + db.span_suggestion(arg.span, + "change this to", + "&str".into()); + for (clonespan, suggestion) in spans { + db.span_suggestion_short(clonespan, + &snippet_opt(cx, clonespan).map_or("change the call to".into(), + |x| Cow::Owned(format!("change `{}` to", x))), + suggestion.into()); + } } - } - ); + ); + } } } } @@ -229,38 +234,50 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< } } -fn get_spans(cx: &LateContext, opt_body_id: Option, idx: usize, fn_name: &'static str) -> Vec<(Span, String)> { +fn get_spans(cx: &LateContext, opt_body_id: Option, idx: usize, replacements: &'static [(&'static str, &'static str)]) -> Result)>, ()> { if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { - get_binding_name(&body.arguments[idx]).map_or_else(Vec::new, - |name| extract_clone_suggestions(cx, name, fn_name, body)) + get_binding_name(&body.arguments[idx]).map_or_else(|| Ok(vec![]), + |name| extract_clone_suggestions(cx, name, replacements, body)) } else { - vec![] + Ok(vec![]) } } -fn extract_clone_suggestions<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, name: Name, fn_name: &'static str, body: &'tcx Body) -> Vec<(Span, String)> { +fn extract_clone_suggestions<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, name: Name, replace: &'static [(&'static str, &'static str)], body: &'tcx Body) -> Result)>, ()> { let mut visitor = PtrCloneVisitor { cx, name, - fn_name, - spans: vec![] + replace, + spans: vec![], + abort: false, }; visitor.visit_body(body); - visitor.spans + if visitor.abort { Err(()) } else { Ok(visitor.spans) } } struct PtrCloneVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, name: Name, - fn_name: &'static str, - spans: Vec<(Span, String)>, + replace: &'static [(&'static str, &'static str)], + spans: Vec<(Span, Cow<'static, str>)>, + abort: bool, } impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { + if self.abort { return; } if let ExprMethodCall(ref seg, _, ref args) = expr.node { - if args.len() == 1 && match_var(&args[0], self.name) && seg.name == "clone" { - self.spans.push((expr.span, format!("{}.{}()", snippet(self.cx, args[0].span, "_"), self.fn_name))); + if args.len() == 1 && match_var(&args[0], self.name) { + if seg.name == "capacity" { + self.abort = true; + return; + } + for &(fn_name, suffix) in self.replace { + if seg.name == fn_name { + self.spans.push((expr.span, snippet(self.cx, args[0].span, "_") + suffix)); + return; + } + } } return; } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index f88294763dc..4145f74e936 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -82,7 +82,8 @@ macro_rules! define_Conf { #[serde(rename_all="kebab-case")] #[serde(deny_unknown_fields)] pub struct Conf { - $(#[$doc] #[serde(default=$rust_name_str)] #[serde(with=$rust_name_str)] pub $rust_name: define_Conf!(TY $($ty)+),)+ + $(#[$doc] #[serde(default=$rust_name_str)] #[serde(with=$rust_name_str)] + pub $rust_name: define_Conf!(TY $($ty)+),)+ #[allow(dead_code)] #[serde(default)] third_party: Option<::toml::Value>, @@ -91,10 +92,12 @@ macro_rules! define_Conf { mod $rust_name { use serde; use serde::Deserialize; - pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { + pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) + -> Result { type T = define_Conf!(TY $($ty)+); Ok(T::deserialize(deserializer).unwrap_or_else(|e| { - ::utils::conf::ERRORS.lock().expect("no threading here").push(::utils::conf::Error::Toml(e.to_string())); + ::utils::conf::ERRORS.lock().expect("no threading here") + .push(::utils::conf::Error::Toml(e.to_string())); super::$rust_name() })) } diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index a386fcf82df..127ae703702 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -55,3 +55,15 @@ fn str_cloned(x: &String) -> String { .clone(); x.clone() } + +fn false_positive_capacity(x: &Vec, y: &String) { + let a = x.capacity(); + let b = y.clone(); + let c = y.as_str(); +} + +fn false_positive_capacity_too(x: &String) -> String { + if x.capacity() > 1024 { panic!("Too large!"); } + x.clone() +} + diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 46d7cbdb031..e9ada9f8aaa 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -28,11 +28,11 @@ help: change this to | 40 | fn cloned(x: &[u8]) -> Vec { | ^^^^^ -help: change the `.clone()` to +help: change `x.clone()` to | 41 | let e = x.to_owned(); | ^^^^^^^^^^^^ -help: change the `.clone()` to +help: change `x.clone()` to | 46 | x.to_owned() | ^^^^^^^^^^^^ @@ -47,18 +47,37 @@ help: change this to | 49 | fn str_cloned(x: &str) -> String { | ^^^^ -help: change the `.clone` to +help: change `x.clone()` to | 50 | let a = x.to_string(); | ^^^^^^^^^^^^^ -help: change the `.clone` to +help: change `x.clone()` to | 51 | let b = x.to_string(); | ^^^^^^^^^^^^^ -help: change the `.clone` to +help: change `x.clone()` to | 56 | x.to_string() | ^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: writing `&String` instead of `&str` involves a new object where a slice will do. + --> $DIR/ptr_arg.rs:59:44 + | +59 | fn false_positive_capacity(x: &Vec, y: &String) { + | ^^^^^^^ + | +help: change this to + | +59 | fn false_positive_capacity(x: &Vec, y: &str) { + | ^^^^ +help: change `y.clone()` to + | +61 | let b = y.to_string(); + | ^^^^^^^^^^^^^ +help: change `y.as_str()` to + | +62 | let c = y; + | ^ + +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 21e9a1285de20f2aaad9b644655fb24f146f3a76 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sat, 23 Sep 2017 19:32:11 +0100 Subject: Use span_lint_and_then as per feedback --- clippy_lints/src/int_plus_one.rs | 112 +++++++++++++++++++++++++++++++-------- tests/ui/int_plus_one.stderr | 20 +++++-- 2 files changed, 106 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 75538e7946e..d8b056fc29a 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::span_help_and_lint; +use utils::{span_lint_and_then, snippet_opt}; /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block /// @@ -45,6 +45,11 @@ impl LintPass for IntPlusOne { // x + 1 <= y // x <= y - 1 +enum Side { + LHS, + RHS, +} + impl IntPlusOne { #[allow(cast_sign_loss)] fn check_lit(&self, lit: &Lit, target_value: i128) -> bool { @@ -54,62 +59,125 @@ impl IntPlusOne { false } - fn check_binop(&self, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> bool { + fn check_binop(&self, cx: &EarlyContext, block: &Expr, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<(bool, Option)> { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { match (lhskind.node, &lhslhs.node, &lhsrhs.node) { // `-1 + x` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1), + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { + let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS); + if self.check_lit(lit, -1) { + self.emit_warning(cx, block, recommendation) + } + }, // `x - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), - _ => false + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { + let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + } + _ => () } }, // case where `... >= y + 1` or `... >= 1 + y` (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) if rhskind.node == BinOpKind::Add => { match (&rhslhs.node, &rhsrhs.node) { // `y + 1` and `1 + y` - (&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), - _ => false + (&ExprKind::Lit(ref lit), _) => { + let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + }, + (_, &ExprKind::Lit(ref lit)) => { + let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + }, + _ => () } }, // case where `x + 1 <= ...` or `1 + x <= ...` (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => { match (&lhslhs.node, &lhsrhs.node) { // `1 + x` and `x + 1` - (&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), - _ => false + (&ExprKind::Lit(ref lit), _) => { + let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + }, + (_, &ExprKind::Lit(ref lit)) => { + let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + }, + _ => () } }, // case where `... >= y - 1` or `... >= -1 + y` (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => { match (rhskind.node, &rhslhs.node, &rhsrhs.node) { // `-1 + y` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1), + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { + let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS); + if self.check_lit(lit, -1) { + self.emit_warning(cx, block, recommendation) + } + }, // `y - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1), - _ => false + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { + let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS); + if self.check_lit(lit, 1) { + self.emit_warning(cx, block, recommendation) + } + }, + _ => () } }, - _ => false + _ => () } } + fn generate_recommendation(&self, cx: &EarlyContext, binop: BinOpKind, node: &Expr, other_side: &Expr, side: Side) -> Option { + let binop_string = match binop { + BinOpKind::Ge => ">", + BinOpKind::Le => "<", + _ => return None + }; + if let Some(snippet) = snippet_opt(cx, node.span) { + if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) { + let rec = match side { + Side::LHS => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)), + Side::RHS => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)), + }; + return rec; + } + } + None + } + + fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: Option) { + if let Some(rec) = recommendation { + span_lint_and_then(cx, + INT_PLUS_ONE, + block.span, + "Unnecessary `>= y + 1` or `x - 1 >=`", + |db| { + db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", rec); + }); + } + } } impl EarlyLintPass for IntPlusOne { fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node { - if self.check_binop(kind.node, lhs, rhs) { - span_help_and_lint( - cx, - INT_PLUS_ONE, - item.span, - "Unnecessary `>= y + 1` or `x - 1 >=`", - "Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`", - ); - } + self.check_binop(cx, item, kind.node, lhs, rhs); } } } diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index fd39e038e01..6f69ba9d714 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -5,7 +5,10 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` | ^^^^^^^^^^ | = note: `-D int-plus-one` implied by `-D warnings` - = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` +help: change `>= y + 1` to `> y` as shown + | +10 | x > y; + | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:11:5 @@ -13,7 +16,10 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` 11 | y + 1 <= x; | ^^^^^^^^^^ | - = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` +help: change `>= y + 1` to `> y` as shown + | +11 | y < x; + | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:13:5 @@ -21,7 +27,10 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` 13 | x - 1 >= y; | ^^^^^^^^^^ | - = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` +help: change `>= y + 1` to `> y` as shown + | +13 | x > y; + | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:14:5 @@ -29,7 +38,10 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` 14 | y <= x - 1; | ^^^^^^^^^^ | - = help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y` +help: change `>= y + 1` to `> y` as shown + | +14 | y < x; + | ^^^^^ error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From e3c4ec74d7f0661fdcab30566c2065ecafb66ecb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 23 Sep 2017 13:30:29 -0700 Subject: Rust upgrade to rustc 1.22.0-nightly (14039a42a 2017-09-22) --- clippy_lints/src/lifetimes.rs | 18 +++++++++--------- clippy_lints/src/types.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 9e7e19a8df5..5cbb854be92 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -113,7 +113,7 @@ fn check_fn_inner<'a, 'tcx>( .parameters .lifetimes; for bound in bounds { - if bound.name != "'static" && !bound.is_elided() { + if bound.name.name() != "'static" && !bound.is_elided() { return; } bounds_lts.push(bound); @@ -225,7 +225,7 @@ fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet { let mut allowed_lts = HashSet::new(); for lt in named_lts { if lt.bounds.is_empty() { - allowed_lts.insert(RefLt::Named(lt.lifetime.name)); + allowed_lts.insert(RefLt::Named(lt.lifetime.name.name())); } } allowed_lts.insert(RefLt::Unnamed); @@ -235,8 +235,8 @@ fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet { fn lts_from_bounds<'a, T: Iterator>(mut vec: Vec, bounds_lts: T) -> Vec { for lt in bounds_lts { - if lt.name != "'static" { - vec.push(RefLt::Named(lt.name)); + if lt.name.name() != "'static" { + vec.push(RefLt::Named(lt.name.name())); } } @@ -266,12 +266,12 @@ impl<'v, 't> RefVisitor<'v, 't> { fn record(&mut self, lifetime: &Option) { if let Some(ref lt) = *lifetime { - if lt.name == "'static" { + if lt.name.name() == "'static" { self.lts.push(RefLt::Static); } else if lt.is_elided() { self.lts.push(RefLt::Unnamed); } else { - self.lts.push(RefLt::Named(lt.name)); + self.lts.push(RefLt::Named(lt.name.name())); } } else { self.lts.push(RefLt::Unnamed); @@ -396,7 +396,7 @@ struct LifetimeChecker { impl<'tcx> Visitor<'tcx> for LifetimeChecker { // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - self.map.remove(&lifetime.name); + self.map.remove(&lifetime.name.name()); } fn visit_lifetime_def(&mut self, _: &'tcx LifetimeDef) { @@ -415,7 +415,7 @@ fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx let hs = generics .lifetimes .iter() - .map(|lt| (lt.lifetime.name, lt.lifetime.span)) + .map(|lt| (lt.lifetime.name.name(), lt.lifetime.span)) .collect(); let mut checker = LifetimeChecker { map: hs }; @@ -434,7 +434,7 @@ struct BodyLifetimeChecker { impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - if lifetime.name != keywords::Invalid.name() && lifetime.name != "'static" { + if lifetime.name.name() != keywords::Invalid.name() && lifetime.name.name() != "'static" { self.lifetimes_used_in_body = true; } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 567e8b5423e..90f1e87796d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -223,7 +223,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let ltopt = if lt.is_elided() { "".to_owned() } else { - format!("{} ", lt.name.as_str()) + format!("{} ", lt.name.name().as_str()) }; let mutopt = if *mutbl == Mutability::MutMutable { "mut " -- cgit 1.4.1-3-g733a5 From 50e410e7968540cfd55b43720c599f653d7d1162 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 23 Sep 2017 13:35:06 -0700 Subject: Update test expectations --- tests/ui/mut_mut.stderr | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index dd3a85c9776..7a7bb840ba9 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -28,16 +28,16 @@ error: this expression mutably borrows a mutable reference. Consider reborrowing | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:30:17 + --> $DIR/mut_mut.rs:30:33 | 30 | let y : &mut &mut u32 = &mut &mut 2; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:30:33 + --> $DIR/mut_mut.rs:30:17 | 30 | let y : &mut &mut u32 = &mut &mut 2; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:30:17 @@ -46,22 +46,22 @@ error: generally you want to avoid `&mut &mut _` if possible | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:17 + --> $DIR/mut_mut.rs:35:38 | 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:22 + --> $DIR/mut_mut.rs:35:17 | 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:38 + --> $DIR/mut_mut.rs:35:22 | 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:35:17 -- cgit 1.4.1-3-g733a5 From 287e997b1e2a92a0e887c1918ad6f1c9ed5e7a4f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 23 Sep 2017 13:36:18 -0700 Subject: Bump to 0.0.163 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d000f2dd999..15a0ee74e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.163 +* Update to *rustc 1.22.0-nightly (14039a42a 2017-09-22)* + ## 0.0.162 * Update to *rustc 1.22.0-nightly (0701b37d9 2017-09-18)* * New lint: [`chars_last_cmp`] diff --git a/Cargo.toml b/Cargo.toml index 46780712ad9..16aaf148c60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.162" +version = "0.0.163" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.162", path = "clippy_lints" } +clippy_lints = { version = "0.0.163", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ef527dbf039..96bd05162dc 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.162" +version = "0.0.163" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From a822cab01f7f7c0db3fb55182e38a30b4fcbd3e4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 23 Sep 2017 13:36:40 -0700 Subject: fix docs --- PUBLISH.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PUBLISH.md b/PUBLISH.md index 1ff3f2b4b73..a9496d5b414 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -7,7 +7,7 @@ Steps to publish a new clippy version - `git push` - Wait for Travis's approval. - Merge. -- `cargo publish` in `./clippy_clints`. +- `cargo publish` in `./clippy_lints`. - `cargo publish` in the root directory. - `git pull`. - `git tag -s v0.0.X -m "v0.0.X"`. -- cgit 1.4.1-3-g733a5 From fff35736e4d91f62e0ee3a6d4350c76ab578c38f Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 24 Sep 2017 09:58:58 +0100 Subject: Remove old return-value --- clippy_lints/src/int_plus_one.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index d8b056fc29a..eeb0c7edb7a 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -59,7 +59,7 @@ impl IntPlusOne { false } - fn check_binop(&self, cx: &EarlyContext, block: &Expr, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<(bool, Option)> { + fn check_binop(&self, cx: &EarlyContext, block: &Expr, binop: BinOpKind, lhs: &Expr, rhs: &Expr) { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { -- cgit 1.4.1-3-g733a5 From 9437d2909c601525a7313cf8a4d72ef3b9810127 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 24 Sep 2017 10:30:29 +0100 Subject: Change to returning Option<(bool, Option)> --- clippy_lints/src/int_plus_one.rs | 75 ++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index eeb0c7edb7a..54142b924ae 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -59,26 +59,20 @@ impl IntPlusOne { false } - fn check_binop(&self, cx: &EarlyContext, block: &Expr, binop: BinOpKind, lhs: &Expr, rhs: &Expr) { + fn check_binop(&self, cx: &EarlyContext, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<(bool, Option)> { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { match (lhskind.node, &lhslhs.node, &lhsrhs.node) { // `-1 + x` (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { - let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS); - if self.check_lit(lit, -1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, -1), self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS))) }, // `x - 1` (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { - let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS))) } - _ => () + _ => None } }, // case where `... >= y + 1` or `... >= 1 + y` @@ -86,18 +80,12 @@ impl IntPlusOne { match (&rhslhs.node, &rhsrhs.node) { // `y + 1` and `1 + y` (&ExprKind::Lit(ref lit), _) => { - let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS))) }, (_, &ExprKind::Lit(ref lit)) => { - let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS))) }, - _ => () + _ => None } }, // case where `x + 1 <= ...` or `1 + x <= ...` @@ -105,18 +93,12 @@ impl IntPlusOne { match (&lhslhs.node, &lhsrhs.node) { // `1 + x` and `x + 1` (&ExprKind::Lit(ref lit), _) => { - let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS))) }, (_, &ExprKind::Lit(ref lit)) => { - let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS))) }, - _ => () + _ => None } }, // case where `... >= y - 1` or `... >= -1 + y` @@ -124,22 +106,16 @@ impl IntPlusOne { match (rhskind.node, &rhslhs.node, &rhsrhs.node) { // `-1 + y` (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { - let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS); - if self.check_lit(lit, -1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, -1), self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS))) }, // `y - 1` (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { - let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS); - if self.check_lit(lit, 1) { - self.emit_warning(cx, block, recommendation) - } + Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS))) }, - _ => () + _ => None } }, - _ => () + _ => None } } @@ -161,23 +137,24 @@ impl IntPlusOne { None } - fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: Option) { - if let Some(rec) = recommendation { - span_lint_and_then(cx, - INT_PLUS_ONE, - block.span, - "Unnecessary `>= y + 1` or `x - 1 >=`", - |db| { - db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", rec); - }); - } + fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: String) { + span_lint_and_then(cx, + INT_PLUS_ONE, + block.span, + "Unnecessary `>= y + 1` or `x - 1 >=`", + |db| { + db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation); + }); } } impl EarlyLintPass for IntPlusOne { fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node { - self.check_binop(cx, item, kind.node, lhs, rhs); + match self.check_binop(cx, kind.node, lhs, rhs) { + Some((should_emit, Some(ref rec))) if should_emit => self.emit_warning(cx, item, rec.clone()), + _ => () + } } } } -- cgit 1.4.1-3-g733a5 From f571cf0b5e56ff2f7651fdd809410d35edba09bd Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 24 Sep 2017 12:31:12 +0100 Subject: Change rtype of int_plus_one detection to Option --- clippy_lints/src/int_plus_one.rs | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 54142b924ae..420427e7d0a 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -59,19 +59,15 @@ impl IntPlusOne { false } - fn check_binop(&self, cx: &EarlyContext, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<(bool, Option)> { + fn check_binop(&self, cx: &EarlyContext, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { match (lhskind.node, &lhslhs.node, &lhsrhs.node) { // `-1 + x` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { - Some((self.check_lit(lit, -1), self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS))) - }, + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS), // `x - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS))) - } + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS), _ => None } }, @@ -79,12 +75,8 @@ impl IntPlusOne { (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) if rhskind.node == BinOpKind::Add => { match (&rhslhs.node, &rhsrhs.node) { // `y + 1` and `1 + y` - (&ExprKind::Lit(ref lit), _) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS))) - }, - (_, &ExprKind::Lit(ref lit)) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS))) - }, + (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS), + (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS), _ => None } }, @@ -92,12 +84,8 @@ impl IntPlusOne { (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => { match (&lhslhs.node, &lhsrhs.node) { // `1 + x` and `x + 1` - (&ExprKind::Lit(ref lit), _) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS))) - }, - (_, &ExprKind::Lit(ref lit)) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS))) - }, + (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS), + (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS), _ => None } }, @@ -105,13 +93,9 @@ impl IntPlusOne { (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => { match (rhskind.node, &rhslhs.node, &rhsrhs.node) { // `-1 + y` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) => { - Some((self.check_lit(lit, -1), self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS))) - }, + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS), // `y - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => { - Some((self.check_lit(lit, 1), self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS))) - }, + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS), _ => None } }, @@ -151,9 +135,8 @@ impl IntPlusOne { impl EarlyLintPass for IntPlusOne { fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node { - match self.check_binop(cx, kind.node, lhs, rhs) { - Some((should_emit, Some(ref rec))) if should_emit => self.emit_warning(cx, item, rec.clone()), - _ => () + if let Some(ref rec) = self.check_binop(cx, kind.node, lhs, rhs) { + self.emit_warning(cx, item, rec.clone()); } } } -- cgit 1.4.1-3-g733a5 From b091fb9b2464907a34279ab99aeffd0552827192 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Fri, 11 Aug 2017 02:21:43 +0300 Subject: add lint declaration and example that should trigger the lint --- clippy_lints/src/loops.rs | 11 ++++++++++- mut_range_bound | Bin 0 -> 422840 bytes tests/run-pass/mut_range_bound.rs | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100755 mut_range_bound create mode 100644 tests/run-pass/mut_range_bound.rs diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 42b31f8eaaa..e994b88fdcf 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -328,6 +328,14 @@ declare_lint! { "any loop that will always `break` or `return`" } +/// TODO: add documentation + +declare_lint! { + pub MUT_RANGE_BOUND, + Warn, + "for loop over a range where one of the bounds is a mutable variable" +} + #[derive(Copy, Clone)] pub struct Pass; @@ -348,7 +356,8 @@ impl LintPass for Pass { EMPTY_LOOP, WHILE_LET_ON_ITERATOR, FOR_KV_MAP, - NEVER_LOOP + NEVER_LOOP, + MUT_RANGE_BOUND ) } } diff --git a/mut_range_bound b/mut_range_bound new file mode 100755 index 00000000000..fdf917d5158 Binary files /dev/null and b/mut_range_bound differ diff --git a/tests/run-pass/mut_range_bound.rs b/tests/run-pass/mut_range_bound.rs new file mode 100644 index 00000000000..e08babe3137 --- /dev/null +++ b/tests/run-pass/mut_range_bound.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] +#![plugin(clippy)] + +// cause the build to fail if this warning is invoked +#![deny(check_for_loop_mut_bound)] + +// an example +fn mut_range_bound() { + let mut m = 4; + for i in 0..m { continue; } // ERROR One of the range bounds is mutable +} + +fn main(){ + mut_range_bound(); +} -- cgit 1.4.1-3-g733a5 From 319f12a4c4d290b12a6d7396e8592391d4fcb1a9 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Tue, 15 Aug 2017 19:41:59 +0300 Subject: implement lint for mutable range bound --- clippy_lints/src/loops.rs | 39 +++++++++++++++++++++++++++++++++++ tests/run-pass/mut_range_bound_tmp.rs | 30 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/run-pass/mut_range_bound_tmp.rs diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e994b88fdcf..31b8b04ecf6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -614,6 +614,7 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); + check_for_mut_range_bound(cx, arg, expr); detect_manual_memcpy(cx, pat, arg, body, expr); } @@ -1303,6 +1304,44 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } +fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, expr: &Expr) { + if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { + let bounds = vec![start, end]; + for bound in &bounds { + if check_for_mutability(cx, bound) { + span_lint(cx, MUT_RANGE_BOUND, expr.span, "you are looping over a range where at least one bound was defined as a mutable variable. keep in mind that mutating this variable inside the loop will not affect the range"); + return; + } + } + } +} + +fn check_for_mutability(cx: &LateContext, bound: &Expr) -> bool { + if_let_chain! {[ + let ExprPath(ref qpath) = bound.node, + let QPath::Resolved(None, ref path) = *qpath, + path.segments.len() == 1, + ], { + let def = cx.tables.qpath_def(qpath, bound.id); + match def { + Def::Local(..) | Def::Upvar(..) => { + let def_id = def.def_id(); + let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); + let node_str = cx.tcx.hir.get(node_id); + if_let_chain! {[ + let map::Node::NodeLocal(pat) = node_str, + let PatKind::Binding(bind_ann, _, _, _) = pat.node, + let BindingAnnotation::Mutable = bind_ann, + ], { + return true; + }} + }, + _ => (), + }} + } + return false; +} + /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { match *pat { diff --git a/tests/run-pass/mut_range_bound_tmp.rs b/tests/run-pass/mut_range_bound_tmp.rs new file mode 100644 index 00000000000..af5cb8f8035 --- /dev/null +++ b/tests/run-pass/mut_range_bound_tmp.rs @@ -0,0 +1,30 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn main() { + mut_range_bound_upper(); + mut_range_bound_lower(); + mut_range_bound_both(); + immut_range_bound(); +} + +fn mut_range_bound_upper() { + let mut m = 4; + for i in 0..m { continue; } // WARNING the range upper bound is mutable +} + +fn mut_range_bound_lower() { + let mut m = 4; + for i in m..10 { continue; } // WARNING the range lower bound is mutable +} + +fn mut_range_bound_both() { + let mut m = 4; + let mut n = 6; + for i in m..n { continue; } // WARNING both bounds are mutable (should get just one warning for this) +} + +fn immut_range_bound() { + let m = 4; + for i in 0..m { continue; } // no warning +} -- cgit 1.4.1-3-g733a5 From 74f4fd32e98f59414758f3b156e417742ef59e29 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Wed, 30 Aug 2017 17:38:13 +0300 Subject: attempt to add check for mutation of range bound within loop; compiles but doesn't work as intended. pushed for feedback --- clippy_lints/src/loops.rs | 62 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 31b8b04ecf6..a40278982ab 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,11 +7,15 @@ use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::region; +use rustc::middle::region::CodeExtent; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::cmt; use rustc::ty::{self, Ty}; use rustc::ty::subst::{Subst, Substs}; use rustc_const_eval::ConstContext; use std::collections::{HashMap, HashSet}; use syntax::ast; +use syntax::codemap::Span; use utils::sugg; use utils::const_to_u64; @@ -614,7 +618,7 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); - check_for_mut_range_bound(cx, arg, expr); + check_for_mut_range_bound(cx, arg, body, expr); detect_manual_memcpy(cx, pat, arg, body, expr); } @@ -1304,11 +1308,49 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, expr: &Expr) { +// TODO: clippy builds, but the `mutate` method of `Delegate` is never called when compiling `tests/run-pass/mut_range_bound_tmp.rs`. what's wrong? + +struct MutateDelegate<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + node_id: NodeId, + was_mutated: bool +} + +impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { + fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { + } + + fn matched_pat(&mut self, matched_pat: &Pat, cmt: cmt<'tcx>, mode: MatchMode) { + } + + fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, mode: ConsumeMode) { + } + + fn borrow(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, _: LoanCause) { + } + + fn mutate(&mut self, assignment_id: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) { + println!("something was mutated"); // tmp: see if this function is ever called at all (no) + if assignment_id == self.node_id { + self.was_mutated = true; + } + } + + fn decl_without_init(&mut self, _: NodeId, _: Span) { + } +} + +impl<'a, 'tcx> MutateDelegate<'a, 'tcx> { + fn bound_was_mutated(&self) -> bool { + self.was_mutated + } +} + +fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { let bounds = vec![start, end]; for bound in &bounds { - if check_for_mutability(cx, bound) { + if check_for_mutation(cx, body, bound) { span_lint(cx, MUT_RANGE_BOUND, expr.span, "you are looping over a range where at least one bound was defined as a mutable variable. keep in mind that mutating this variable inside the loop will not affect the range"); return; } @@ -1316,11 +1358,10 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, expr: &Expr) { } } -fn check_for_mutability(cx: &LateContext, bound: &Expr) -> bool { +fn check_for_mutation(cx: &LateContext, body: &Expr, bound: &Expr) -> bool { if_let_chain! {[ let ExprPath(ref qpath) = bound.node, let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, ], { let def = cx.tables.qpath_def(qpath, bound.id); match def { @@ -1328,13 +1369,18 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> bool { let def_id = def.def_id(); let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); let node_str = cx.tcx.hir.get(node_id); - if_let_chain! {[ + if_let_chain! {[ // prob redundant now, remove let map::Node::NodeLocal(pat) = node_str, let PatKind::Binding(bind_ann, _, _, _) = pat.node, let BindingAnnotation::Mutable = bind_ann, + ], { - return true; - }} + println!("bound was mutable"); // tmp: make sure the full if-let chain executes when it should (yes) + let mut delegate = MutateDelegate { cx: cx, node_id: node_id, was_mutated: false }; + let region_maps = &cx.tcx.region_maps(def_id); // is this the correct argument? + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_maps, cx.tables).walk_expr(body); + return delegate.bound_was_mutated(); + }} }, _ => (), }} -- cgit 1.4.1-3-g733a5 From 27d5ff6c9cafe87411b067b9ef21c50e7590171a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 30 Aug 2017 09:47:28 -0700 Subject: Rustup --- clippy_lints/src/loops.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a40278982ab..bcae2868db2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1363,15 +1363,15 @@ fn check_for_mutation(cx: &LateContext, body: &Expr, bound: &Expr) -> bool { let ExprPath(ref qpath) = bound.node, let QPath::Resolved(None, ref path) = *qpath, ], { - let def = cx.tables.qpath_def(qpath, bound.id); + let def = cx.tables.qpath_def(qpath, bound.hir_id); match def { Def::Local(..) | Def::Upvar(..) => { let def_id = def.def_id(); let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); let node_str = cx.tcx.hir.get(node_id); if_let_chain! {[ // prob redundant now, remove - let map::Node::NodeLocal(pat) = node_str, - let PatKind::Binding(bind_ann, _, _, _) = pat.node, + let map::Node::NodeLocal(local) = node_str, + let PatKind::Binding(bind_ann, _, _, _) = local.pat.node, let BindingAnnotation::Mutable = bind_ann, ], { -- cgit 1.4.1-3-g733a5 From d0eff10a7c3837e447f73864fd61478c7bfbd591 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 30 Aug 2017 10:07:25 -0700 Subject: Update test, fix lint --- clippy_lints/src/loops.rs | 13 +++++++------ tests/run-pass/mut_range_bound_tmp.rs | 7 ++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index bcae2868db2..e1db9447d39 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1329,8 +1329,8 @@ impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { fn borrow(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, _: LoanCause) { } - fn mutate(&mut self, assignment_id: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) { - println!("something was mutated"); // tmp: see if this function is ever called at all (no) + fn mutate(&mut self, assignment_id: NodeId, sp: Span, _: cmt<'tcx>, _: MutateMode) { + self.cx.sess().span_note_without_error(sp, "mutates!"); if assignment_id == self.node_id { self.was_mutated = true; } @@ -1364,18 +1364,19 @@ fn check_for_mutation(cx: &LateContext, body: &Expr, bound: &Expr) -> bool { let QPath::Resolved(None, ref path) = *qpath, ], { let def = cx.tables.qpath_def(qpath, bound.hir_id); + + cx.sess().span_note_without_error(body.span, "loop"); match def { Def::Local(..) | Def::Upvar(..) => { let def_id = def.def_id(); let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); let node_str = cx.tcx.hir.get(node_id); - if_let_chain! {[ // prob redundant now, remove - let map::Node::NodeLocal(local) = node_str, - let PatKind::Binding(bind_ann, _, _, _) = local.pat.node, + if_let_chain! {[ + let map::Node::NodeBinding(pat) = node_str, + let PatKind::Binding(bind_ann, _, _, _) = pat.node, let BindingAnnotation::Mutable = bind_ann, ], { - println!("bound was mutable"); // tmp: make sure the full if-let chain executes when it should (yes) let mut delegate = MutateDelegate { cx: cx, node_id: node_id, was_mutated: false }; let region_maps = &cx.tcx.region_maps(def_id); // is this the correct argument? ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_maps, cx.tables).walk_expr(body); diff --git a/tests/run-pass/mut_range_bound_tmp.rs b/tests/run-pass/mut_range_bound_tmp.rs index af5cb8f8035..ff164438f3f 100644 --- a/tests/run-pass/mut_range_bound_tmp.rs +++ b/tests/run-pass/mut_range_bound_tmp.rs @@ -1,6 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(unused)] + fn main() { mut_range_bound_upper(); mut_range_bound_lower(); @@ -10,7 +12,10 @@ fn main() { fn mut_range_bound_upper() { let mut m = 4; - for i in 0..m { continue; } // WARNING the range upper bound is mutable + for i in 0..m { + + m = 5; + continue; } // WARNING the range upper bound is mutable } fn mut_range_bound_lower() { -- cgit 1.4.1-3-g733a5 From 9a17150a0683129e6f781958fb55836994ed6ce4 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Mon, 18 Sep 2017 17:10:33 -0700 Subject: refactor, add spans to warnings, add tests --- clippy_lints/src/loops.rs | 91 ++++++++++++++++++++++------------- tests/run-pass/mut_range_bound_tmp.rs | 24 ++++++--- 2 files changed, 76 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e1db9447d39..522e0ae79c0 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,8 +7,9 @@ use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::region; -use rustc::middle::region::CodeExtent; +// use rustc::middle::region::CodeExtent; use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::cmt; use rustc::ty::{self, Ty}; use rustc::ty::subst::{Subst, Substs}; @@ -1308,31 +1309,35 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -// TODO: clippy builds, but the `mutate` method of `Delegate` is never called when compiling `tests/run-pass/mut_range_bound_tmp.rs`. what's wrong? - struct MutateDelegate<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - node_id: NodeId, - was_mutated: bool + node_id_low: Option, + node_id_high: Option, + span_low: Option, + span_high: Option, } impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { - fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { + fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) { } - fn matched_pat(&mut self, matched_pat: &Pat, cmt: cmt<'tcx>, mode: MatchMode) { + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) { } - fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, mode: ConsumeMode) { + fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) { } fn borrow(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, _: LoanCause) { } - fn mutate(&mut self, assignment_id: NodeId, sp: Span, _: cmt<'tcx>, _: MutateMode) { - self.cx.sess().span_note_without_error(sp, "mutates!"); - if assignment_id == self.node_id { - self.was_mutated = true; + fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { + if let Categorization::Local(id) = cmt.cat { + if Some(id) == self.node_id_low { + self.span_low = Some(sp) + } + if Some(id) == self.node_id_high { + self.span_high = Some(sp) + } } } @@ -1341,31 +1346,34 @@ impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { } impl<'a, 'tcx> MutateDelegate<'a, 'tcx> { - fn bound_was_mutated(&self) -> bool { - self.was_mutated + fn mutation_span(&self) -> (Option, Option) { + (self.span_low, self.span_high) } } fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { - let bounds = vec![start, end]; - for bound in &bounds { - if check_for_mutation(cx, body, bound) { - span_lint(cx, MUT_RANGE_BOUND, expr.span, "you are looping over a range where at least one bound was defined as a mutable variable. keep in mind that mutating this variable inside the loop will not affect the range"); - return; - } + let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; + if mut_ids[0].is_some() || mut_ids[1].is_some() { + let (span_low, span_high) = check_for_mutation(cx, body, mut_ids); + mut_warn_with_span(cx, span_low); + mut_warn_with_span(cx, span_high); } } } -fn check_for_mutation(cx: &LateContext, body: &Expr, bound: &Expr) -> bool { +fn mut_warn_with_span(cx: &LateContext, span: Option) { + if let Some(sp) = span { + span_lint(cx, MUT_RANGE_BOUND, sp, "attempt to mutate range bound within loop; note that the range of the loop is unchanged"); + } +} + +fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { if_let_chain! {[ let ExprPath(ref qpath) = bound.node, let QPath::Resolved(None, ref path) = *qpath, ], { let def = cx.tables.qpath_def(qpath, bound.hir_id); - - cx.sess().span_note_without_error(body.span, "loop"); match def { Def::Local(..) | Def::Upvar(..) => { let def_id = def.def_id(); @@ -1375,18 +1383,35 @@ fn check_for_mutation(cx: &LateContext, body: &Expr, bound: &Expr) -> bool { let map::Node::NodeBinding(pat) = node_str, let PatKind::Binding(bind_ann, _, _, _) = pat.node, let BindingAnnotation::Mutable = bind_ann, - - ], { - let mut delegate = MutateDelegate { cx: cx, node_id: node_id, was_mutated: false }; - let region_maps = &cx.tcx.region_maps(def_id); // is this the correct argument? - ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_maps, cx.tables).walk_expr(body); - return delegate.bound_was_mutated(); + ], { + return Some(node_id); }} - }, - _ => (), - }} + } + _ => () + } + }} + return None; +} + +fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: Vec>) -> (Option, Option) { + let mut delegate = MutateDelegate { cx: cx, node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; + if let Some(id) = get_id_if_some(&bound_ids) { + let def_id = cx.tcx.hir.local_def_id(id); + let region_scope_tree = &cx.tcx.region_scope_tree(def_id); + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); + return delegate.mutation_span(); + } else { + return (None, None); + } +} + +fn get_id_if_some(bound_ids: &Vec>) -> Option { + for id in bound_ids.into_iter() { + if id.is_some() { + return *id; + } } - return false; + return None; } /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. diff --git a/tests/run-pass/mut_range_bound_tmp.rs b/tests/run-pass/mut_range_bound_tmp.rs index ff164438f3f..c13c0c0ae85 100644 --- a/tests/run-pass/mut_range_bound_tmp.rs +++ b/tests/run-pass/mut_range_bound_tmp.rs @@ -7,28 +7,40 @@ fn main() { mut_range_bound_upper(); mut_range_bound_lower(); mut_range_bound_both(); + mut_range_bound_no_mutation(); immut_range_bound(); } fn mut_range_bound_upper() { let mut m = 4; - for i in 0..m { - - m = 5; - continue; } // WARNING the range upper bound is mutable + for i in 0..m { m = 5; } // warning } fn mut_range_bound_lower() { let mut m = 4; - for i in m..10 { continue; } // WARNING the range lower bound is mutable + for i in m..10 { m *= 2; } // warning } fn mut_range_bound_both() { let mut m = 4; let mut n = 6; - for i in m..n { continue; } // WARNING both bounds are mutable (should get just one warning for this) + for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) +} + +fn mut_range_bound_no_mutation() { + let mut m = 4; + for i in 0..m { continue; } // no warning } +fn mut_borrow_range_bound() { + let mut m = 4; + for i in 0..m { + let n = &mut m; + *n += 1; + } +} + + fn immut_range_bound() { let m = 4; for i in 0..m { continue; } // no warning -- cgit 1.4.1-3-g733a5 From c326a779dd5edf1bdeec207723da928cc2d4aec8 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Sun, 24 Sep 2017 15:40:10 -0400 Subject: use def_id of function in check_for_mutation --- clippy_lints/src/loops.rs | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 522e0ae79c0..f8c3e7b4cbd 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,6 +2,7 @@ use itertools::Itertools; use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; +use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; @@ -619,7 +620,7 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); - check_for_mut_range_bound(cx, arg, body, expr); + check_for_mut_range_bound(cx, arg, body); detect_manual_memcpy(cx, pat, arg, body, expr); } @@ -1309,15 +1310,14 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -struct MutateDelegate<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, +struct MutateDelegate { node_id_low: Option, node_id_high: Option, span_low: Option, span_high: Option, } -impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { +impl<'tcx> Delegate<'tcx> for MutateDelegate { fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) { } @@ -1345,14 +1345,14 @@ impl<'a, 'tcx> Delegate<'tcx> for MutateDelegate<'a, 'tcx> { } } -impl<'a, 'tcx> MutateDelegate<'a, 'tcx> { +impl<'tcx> MutateDelegate { fn mutation_span(&self) -> (Option, Option) { (self.span_low, self.span_high) } } -fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) { - if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { +fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { + if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(arg) { let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; if mut_ids[0].is_some() || mut_ids[1].is_some() { let (span_low, span_high) = check_for_mutation(cx, body, mut_ids); @@ -1371,7 +1371,7 @@ fn mut_warn_with_span(cx: &LateContext, span: Option) { fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { if_let_chain! {[ let ExprPath(ref qpath) = bound.node, - let QPath::Resolved(None, ref path) = *qpath, + let QPath::Resolved(None, _) = *qpath, ], { let def = cx.tables.qpath_def(qpath, bound.hir_id); match def { @@ -1394,24 +1394,11 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { } fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: Vec>) -> (Option, Option) { - let mut delegate = MutateDelegate { cx: cx, node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; - if let Some(id) = get_id_if_some(&bound_ids) { - let def_id = cx.tcx.hir.local_def_id(id); - let region_scope_tree = &cx.tcx.region_scope_tree(def_id); - ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); - return delegate.mutation_span(); - } else { - return (None, None); - } -} - -fn get_id_if_some(bound_ids: &Vec>) -> Option { - for id in bound_ids.into_iter() { - if id.is_some() { - return *id; - } - } - return None; + let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; + let def_id = def_id::DefId::local(body.hir_id.owner); + let region_scope_tree = &cx.tcx.region_scope_tree(def_id); + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); + return delegate.mutation_span(); } /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. -- cgit 1.4.1-3-g733a5 From 2fe968774abcaa806fc7227f70bd2416d2a4a71f Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Mon, 25 Sep 2017 01:44:47 -0400 Subject: replace defids with nodeids for local variables --- Cargo.lock | 6 +++--- clippy_lints/src/loops.rs | 27 +++++++++++---------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88f1a8a7f3a..21f2b4332c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.162" +version = "0.0.163" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,11 +73,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.162" +version = "0.0.163" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.162", + "clippy_lints 0.0.163", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f8c3e7b4cbd..518b6e21347 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1374,20 +1374,15 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { let QPath::Resolved(None, _) = *qpath, ], { let def = cx.tables.qpath_def(qpath, bound.hir_id); - match def { - Def::Local(..) | Def::Upvar(..) => { - let def_id = def.def_id(); - let node_id = cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); - let node_str = cx.tcx.hir.get(node_id); - if_let_chain! {[ - let map::Node::NodeBinding(pat) = node_str, - let PatKind::Binding(bind_ann, _, _, _) = pat.node, - let BindingAnnotation::Mutable = bind_ann, - ], { - return Some(node_id); - }} - } - _ => () + if let Def::Local(node_id) = def { + let node_str = cx.tcx.hir.get(node_id); + if_let_chain! {[ + let map::Node::NodeBinding(pat) = node_str, + let PatKind::Binding(bind_ann, _, _, _) = pat.node, + let BindingAnnotation::Mutable = bind_ann, + ], { + return Some(node_id); + }} } }} return None; @@ -1395,8 +1390,8 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: Vec>) -> (Option, Option) { let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; - let def_id = def_id::DefId::local(body.hir_id.owner); - let region_scope_tree = &cx.tcx.region_scope_tree(def_id); + let d = def_id::DefId::local(body.hir_id.owner); + let region_scope_tree = &cx.tcx.region_scope_tree(d); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); return delegate.mutation_span(); } -- cgit 1.4.1-3-g733a5 From d7867ef8c15bfa199bac13ae919e9b93f9a34b57 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Mon, 25 Sep 2017 02:00:21 -0400 Subject: add lint for mutable borrow; may have false positives. pushed for feedback --- clippy_lints/src/loops.rs | 19 ++++++++++++++++--- tests/run-pass/mut_range_bound_tmp.rs | 13 +++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 518b6e21347..c82ddb7383d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1327,7 +1327,20 @@ impl<'tcx> Delegate<'tcx> for MutateDelegate { fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) { } - fn borrow(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + match bk { + ty::BorrowKind::MutBorrow => { + if let Categorization::Local(id) = cmt.cat { + if Some(id) == self.node_id_low { + self.span_low = Some(sp) + } + if Some(id) == self.node_id_high { + self.span_high = Some(sp) + } + } + }, + _ => (), + } } fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { @@ -1390,8 +1403,8 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: Vec>) -> (Option, Option) { let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; - let d = def_id::DefId::local(body.hir_id.owner); - let region_scope_tree = &cx.tcx.region_scope_tree(d); + let def_id = def_id::DefId::local(body.hir_id.owner); + let region_scope_tree = &cx.tcx.region_scope_tree(def_id); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); return delegate.mutation_span(); } diff --git a/tests/run-pass/mut_range_bound_tmp.rs b/tests/run-pass/mut_range_bound_tmp.rs index c13c0c0ae85..1a7159c330e 100644 --- a/tests/run-pass/mut_range_bound_tmp.rs +++ b/tests/run-pass/mut_range_bound_tmp.rs @@ -9,6 +9,8 @@ fn main() { mut_range_bound_both(); mut_range_bound_no_mutation(); immut_range_bound(); + mut_borrow_range_bound(); + immut_borrow_range_bound(); } fn mut_range_bound_upper() { @@ -35,8 +37,15 @@ fn mut_range_bound_no_mutation() { fn mut_borrow_range_bound() { let mut m = 4; for i in 0..m { - let n = &mut m; - *n += 1; + let n = &mut m; // warning here? + *n += 1; // or here? + } +} + +fn immut_borrow_range_bound() { + let mut m = 4; + for i in 0..m { + let n = &m; // should be no warning? } } -- cgit 1.4.1-3-g733a5 From a3ad409341ceb557169479d9fce06ac1dadbec4d Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Mon, 25 Sep 2017 23:38:49 +0300 Subject: Configuration option for VERBOSE_BIT_MASK threshold By default is 1. u64, because I didn't figure out how to deserialize u128 option from config. --- clippy_lints/src/bit_mask.rs | 13 ++++++++++++- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 ++ tests/ui/bit_masks.stderr | 16 +--------------- tests/ui/conf_unknown_key.stderr | 2 +- tests/ui/trailing_zeros.rs | 1 + 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 9b64a42d4f7..6372221fd44 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -90,7 +90,17 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct BitMask; +pub struct BitMask { + verbose_bit_mask_threshold: u64, +} + +impl BitMask { + pub fn new(verbose_bit_mask_threshold: u64) -> Self { + Self { + verbose_bit_mask_threshold: verbose_bit_mask_threshold, + } + } +} impl LintPass for BitMask { fn get_lints(&self) -> LintArray { @@ -119,6 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { let Expr_::ExprLit(ref lit1) = right.node, let LitKind::Int(0, _) = lit1.node, n.leading_zeros() == n.count_zeros(), + n > u128::from(self.verbose_bit_mask_threshold), ], { span_lint_and_then(cx, VERBOSE_BIT_MASK, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5cb7034c7bf..955bb883635 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -231,7 +231,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold)); reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); reg.register_late_lint_pass(box enum_clike::UnportableVariant); - reg.register_late_lint_pass(box bit_mask::BitMask); + reg.register_late_lint_pass(box bit_mask::BitMask::new(conf.verbose_bit_mask_threshold)); reg.register_late_lint_pass(box ptr::PointerPass); reg.register_late_lint_pass(box needless_bool::NeedlessBool); reg.register_late_lint_pass(box needless_bool::BoolComparison); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index f88294763dc..5272e8a6ca6 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -172,6 +172,8 @@ define_Conf! { (enum_variant_name_threshold, "enum_variant_name_threshold", 3 => u64), /// Lint: LARGE_ENUM_VARIANT. The maximum size of a emum's variant to avoid box suggestion (enum_variant_size_threshold, "enum_variant_size_threshold", 200 => u64), + /// Lint: VERBOSE_BIT_MASK. The maximum size of a bit mask, that won't be checked on verbosity + (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), } /// Search for the configuration file. diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 4b40fa086b8..40aa585d124 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -6,20 +6,6 @@ error: &-masking with zero | = note: `-D bad-bit-mask` implied by `-D warnings` -error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/bit_masks.rs:12:5 - | -12 | x & 0 == 0; - | ^^^^^^^^^^ help: try: `x.trailing_zeros() >= 0` - | - = note: `-D verbose-bit-mask` implied by `-D warnings` - -error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/bit_masks.rs:14:5 - | -14 | x & 1 == 0; //ok, compared with zero - | ^^^^^^^^^^ help: try: `x.trailing_zeros() >= 1` - error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:15:5 | @@ -106,5 +92,5 @@ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared 55 | x | 1 >= 8; | ^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index bd16dfd47da..8de3cd93370 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `third-party` +error: error reading Clippy's configuration file: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `third-party` error: aborting due to previous error diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 40f588cecef..9fc71506ffe 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -7,4 +7,5 @@ fn main() { let _ = #[clippy(author)] (x & 0b1111 == 0); // suggest trailing_zeros let _ = x & 0b1_1111 == 0; // suggest trailing_zeros let _ = x & 0b1_1010 == 0; // do not lint + let _ = x & 1 == 0; // do not lint } -- cgit 1.4.1-3-g733a5 From 44ecc19a3f25f8741736c05c477047386ff9f2fb Mon Sep 17 00:00:00 2001 From: Michal Budzynski Date: Thu, 14 Sep 2017 16:04:04 +0200 Subject: stabilizing feature iterator_for_each for rust 1.21.0 --- tests/ui/infinite_iter.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index fd433edf98d..deb5c5edd8c 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,5 +1,4 @@ #![feature(plugin)] -#![feature(iterator_for_each)] #![plugin(clippy)] use std::iter::repeat; -- cgit 1.4.1-3-g733a5 From 04c44fa3fe5960e924ce25fca43e80c097f24eab Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 13:52:17 -0700 Subject: Update line numbers --- tests/ui/infinite_iter.stderr | 64 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index b3d2f08a865..f79db778488 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,99 +1,99 @@ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/infinite_iter.rs:11:5 + --> $DIR/infinite_iter.rs:10:5 | -11 | repeat(0_u8).collect::>(); // infinite iter +10 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-collect` implied by `-D warnings` error: infinite iteration detected - --> $DIR/infinite_iter.rs:11:5 + --> $DIR/infinite_iter.rs:10:5 | -11 | repeat(0_u8).collect::>(); // infinite iter +10 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:9:8 + --> $DIR/infinite_iter.rs:8:8 | -9 | #[deny(infinite_iter)] +8 | #[deny(infinite_iter)] | ^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:12:5 + --> $DIR/infinite_iter.rs:11:5 | -12 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter +11 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:13:5 + --> $DIR/infinite_iter.rs:12:5 | -13 | (0..8_u64).chain(0..).max(); // infinite iter +12 | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:15:5 + --> $DIR/infinite_iter.rs:14:5 | -15 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter +14 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:17:5 + --> $DIR/infinite_iter.rs:16:5 | -17 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter +16 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:18:5 + --> $DIR/infinite_iter.rs:17:5 | -18 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter +17 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:25:5 + --> $DIR/infinite_iter.rs:24:5 | -25 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter +24 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:23:8 + --> $DIR/infinite_iter.rs:22:8 | -23 | #[deny(maybe_infinite_iter)] +22 | #[deny(maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:26:5 + --> $DIR/infinite_iter.rs:25:5 | -26 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter +25 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:27:5 + --> $DIR/infinite_iter.rs:26:5 | -27 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter +26 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:28:5 + --> $DIR/infinite_iter.rs:27:5 | -28 | (0..).find(|x| *x == 24); // maybe infinite iter +27 | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:29:5 + --> $DIR/infinite_iter.rs:28:5 | -29 | (0..).position(|x| x == 24); // maybe infinite iter +28 | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:30:5 + --> $DIR/infinite_iter.rs:29:5 | -30 | (0..).any(|x| x == 24); // maybe infinite iter +29 | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:31:5 + --> $DIR/infinite_iter.rs:30:5 | -31 | (0..).all(|x| x == 24); // maybe infinite iter +30 | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 8408d486585c9c8757d0e65ace1daabf3b0dfcd9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 13:52:23 -0700 Subject: Update lockfile --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53e3cc9ff6a..4d5f05f93bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.162" +version = "0.0.163" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -78,11 +78,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.162" +version = "0.0.163" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.162", + "clippy_lints 0.0.163", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -- cgit 1.4.1-3-g733a5 From bfc31536c74a30b49ba84c6539620a0aecc1504a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 18:32:05 -0700 Subject: Make it a ui test, update --- tests/run-pass/mut_range_bound.rs | 15 ---------- tests/run-pass/mut_range_bound_tmp.rs | 56 ----------------------------------- tests/ui/mut_range_bound.rs | 56 +++++++++++++++++++++++++++++++++++ tests/ui/mut_range_bound.stderr | 34 +++++++++++++++++++++ 4 files changed, 90 insertions(+), 71 deletions(-) delete mode 100644 tests/run-pass/mut_range_bound.rs delete mode 100644 tests/run-pass/mut_range_bound_tmp.rs create mode 100644 tests/ui/mut_range_bound.rs create mode 100644 tests/ui/mut_range_bound.stderr diff --git a/tests/run-pass/mut_range_bound.rs b/tests/run-pass/mut_range_bound.rs deleted file mode 100644 index e08babe3137..00000000000 --- a/tests/run-pass/mut_range_bound.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -// cause the build to fail if this warning is invoked -#![deny(check_for_loop_mut_bound)] - -// an example -fn mut_range_bound() { - let mut m = 4; - for i in 0..m { continue; } // ERROR One of the range bounds is mutable -} - -fn main(){ - mut_range_bound(); -} diff --git a/tests/run-pass/mut_range_bound_tmp.rs b/tests/run-pass/mut_range_bound_tmp.rs deleted file mode 100644 index 1a7159c330e..00000000000 --- a/tests/run-pass/mut_range_bound_tmp.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#![allow(unused)] - -fn main() { - mut_range_bound_upper(); - mut_range_bound_lower(); - mut_range_bound_both(); - mut_range_bound_no_mutation(); - immut_range_bound(); - mut_borrow_range_bound(); - immut_borrow_range_bound(); -} - -fn mut_range_bound_upper() { - let mut m = 4; - for i in 0..m { m = 5; } // warning -} - -fn mut_range_bound_lower() { - let mut m = 4; - for i in m..10 { m *= 2; } // warning -} - -fn mut_range_bound_both() { - let mut m = 4; - let mut n = 6; - for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) -} - -fn mut_range_bound_no_mutation() { - let mut m = 4; - for i in 0..m { continue; } // no warning -} - -fn mut_borrow_range_bound() { - let mut m = 4; - for i in 0..m { - let n = &mut m; // warning here? - *n += 1; // or here? - } -} - -fn immut_borrow_range_bound() { - let mut m = 4; - for i in 0..m { - let n = &m; // should be no warning? - } -} - - -fn immut_range_bound() { - let m = 4; - for i in 0..m { continue; } // no warning -} diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs new file mode 100644 index 00000000000..835ceeedc94 --- /dev/null +++ b/tests/ui/mut_range_bound.rs @@ -0,0 +1,56 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused)] + +fn main() { + mut_range_bound_upper(); + mut_range_bound_lower(); + mut_range_bound_both(); + mut_range_bound_no_mutation(); + immut_range_bound(); + mut_borrow_range_bound(); + immut_borrow_range_bound(); +} + +fn mut_range_bound_upper() { + let mut m = 4; + for i in 0..m { m = 5; } // warning +} + +fn mut_range_bound_lower() { + let mut m = 4; + for i in m..10 { m *= 2; } // warning +} + +fn mut_range_bound_both() { + let mut m = 4; + let mut n = 6; + for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) +} + +fn mut_range_bound_no_mutation() { + let mut m = 4; + for i in 0..m { continue; } // no warning +} + +fn mut_borrow_range_bound() { + let mut m = 4; + for i in 0..m { + let n = &mut m; // warning + *n += 1; + } +} + +fn immut_borrow_range_bound() { + let mut m = 4; + for i in 0..m { + let n = &m; // should be no warning? + } +} + + +fn immut_range_bound() { + let m = 4; + for i in 0..m { continue; } // no warning +} diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr new file mode 100644 index 00000000000..d7be7ae1e6f --- /dev/null +++ b/tests/ui/mut_range_bound.stderr @@ -0,0 +1,34 @@ +error: attempt to mutate range bound within loop; note that the range of the loop is unchanged + --> $DIR/mut_range_bound.rs:18:21 + | +18 | for i in 0..m { m = 5; } // warning + | ^^^^^ + | + = note: `-D mut-range-bound` implied by `-D warnings` + +error: attempt to mutate range bound within loop; note that the range of the loop is unchanged + --> $DIR/mut_range_bound.rs:23:22 + | +23 | for i in m..10 { m *= 2; } // warning + | ^^^^^^ + +error: attempt to mutate range bound within loop; note that the range of the loop is unchanged + --> $DIR/mut_range_bound.rs:29:21 + | +29 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) + | ^^^^^ + +error: attempt to mutate range bound within loop; note that the range of the loop is unchanged + --> $DIR/mut_range_bound.rs:29:28 + | +29 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) + | ^^^^^ + +error: attempt to mutate range bound within loop; note that the range of the loop is unchanged + --> $DIR/mut_range_bound.rs:40:22 + | +40 | let n = &mut m; // warning + | ^ + +error: aborting due to 5 previous errors + -- cgit 1.4.1-3-g733a5 From 94c6f4a868a56667d695db98beff5ec10f294ec9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 18:39:50 -0700 Subject: Pass dogfood --- clippy_lints/src/loops.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index c82ddb7383d..a0300530a59 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1328,18 +1328,15 @@ impl<'tcx> Delegate<'tcx> for MutateDelegate { } fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { - match bk { - ty::BorrowKind::MutBorrow => { - if let Categorization::Local(id) = cmt.cat { - if Some(id) == self.node_id_low { - self.span_low = Some(sp) - } - if Some(id) == self.node_id_high { - self.span_high = Some(sp) - } + if let ty::BorrowKind::MutBorrow = bk { + if let Categorization::Local(id) = cmt.cat { + if Some(id) == self.node_id_low { + self.span_low = Some(sp) } - }, - _ => (), + if Some(id) == self.node_id_high { + self.span_high = Some(sp) + } + } } } @@ -1368,7 +1365,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(arg) { let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; if mut_ids[0].is_some() || mut_ids[1].is_some() { - let (span_low, span_high) = check_for_mutation(cx, body, mut_ids); + let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids); mut_warn_with_span(cx, span_low); mut_warn_with_span(cx, span_high); } @@ -1398,15 +1395,15 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { }} } }} - return None; + None } -fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: Vec>) -> (Option, Option) { +fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; let def_id = def_id::DefId::local(body.hir_id.owner); let region_scope_tree = &cx.tcx.region_scope_tree(def_id); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); - return delegate.mutation_span(); + delegate.mutation_span() } /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. -- cgit 1.4.1-3-g733a5 From d337c7f9270f6a414ff9c51b6e81e919222488f1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 18:43:34 -0700 Subject: Update changelog --- CHANGELOG.md | 5 +++++ clippy_lints/src/lib.rs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a0ee74e6b..2730ca6a181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## Trunk +* New lints: [`mut_range_bound`], [`int_plus_one`] + ## 0.0.163 * Update to *rustc 1.22.0-nightly (14039a42a 2017-09-22)* @@ -519,6 +522,7 @@ All notable changes to this project will be documented in this file. [`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask [`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter [`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always +[`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic [`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons @@ -556,6 +560,7 @@ All notable changes to this project will be documented in this file. [`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one [`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref [`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut +[`mut_range_bound`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_range_bound [`mutex_atomic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_atomic [`mutex_integer`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_integer [`naive_bytecount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#naive_bytecount diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f4c9aaf3b08..b840c3ddd02 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -343,8 +343,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, - int_plus_one::INT_PLUS_ONE, infinite_iter::MAYBE_INFINITE_ITER, + int_plus_one::INT_PLUS_ONE, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, @@ -449,6 +449,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, loops::MANUAL_MEMCPY, + loops::MUT_RANGE_BOUND, loops::NEEDLESS_RANGE_LOOP, loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, -- cgit 1.4.1-3-g733a5 From fabb6b6645ec9f804b17707fb1e69ff09c15cbed Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:04:55 -0700 Subject: Rustup to rustc 1.22.0-nightly (6c476ce46 2017-09-25) --- clippy_lints/src/lifetimes.rs | 50 ++++++++++++++++-------------- clippy_lints/src/map_clone.rs | 3 +- clippy_lints/src/methods.rs | 17 +++++++--- clippy_lints/src/needless_pass_by_value.rs | 3 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/transmute.rs | 5 +-- clippy_lints/src/types.rs | 22 ++++++++----- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 9 +++++- 9 files changed, 69 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 5cbb854be92..16d636c68ab 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -104,19 +104,20 @@ fn check_fn_inner<'a, 'tcx>( for typ in &generics.ty_params { for bound in &typ.bounds { if let TraitTyParamBound(ref trait_ref, _) = *bound { - let bounds = &trait_ref + let params = &trait_ref .trait_ref .path .segments .last() .expect("a path must have at least one segment") - .parameters - .lifetimes; - for bound in bounds { - if bound.name.name() != "'static" && !bound.is_elided() { - return; + .parameters; + if let Some(ref params) = *params { + for bound in ¶ms.lifetimes { + if bound.name.name() != "'static" && !bound.is_elided() { + return; + } + bounds_lts.push(bound); } - bounds_lts.push(bound); } } } @@ -287,23 +288,24 @@ impl<'v, 't> RefVisitor<'v, 't> { } fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { - let last_path_segment = &last_path_segment(qpath).parameters; - if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { - let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); - match self.cx.tables.qpath_def(qpath, hir_id) { - Def::TyAlias(def_id) | Def::Struct(def_id) => { - let generics = self.cx.tcx.generics_of(def_id); - for _ in generics.regions.as_slice() { - self.record(&None); - } - }, - Def::Trait(def_id) => { - let trait_def = self.cx.tcx.trait_def(def_id); - for _ in &self.cx.tcx.generics_of(trait_def.def_id).regions { - self.record(&None); - } - }, - _ => (), + if let Some(ref last_path_segment) = last_path_segment(qpath).parameters { + if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { + let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + match self.cx.tables.qpath_def(qpath, hir_id) { + Def::TyAlias(def_id) | Def::Struct(def_id) => { + let generics = self.cx.tcx.generics_of(def_id); + for _ in generics.regions.as_slice() { + self.record(&None); + } + }, + Def::Trait(def_id) => { + let trait_def = self.cx.tcx.trait_def(def_id); + for _ in &self.cx.tcx.generics_of(trait_def.def_id).regions { + self.record(&None); + } + }, + _ => (), + } } } } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 733022f1703..e35e1ab477c 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -100,7 +100,8 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { let arg_segment = [ PathSegment { name: id, - parameters: PathParameters::none(), + parameters: None, + infer_types: true, }, ]; !path.is_global() && path.segments[..] == arg_segment diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index b36e1851d0d..6d3a3f39d1a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1617,11 +1617,18 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener match_path(path, name) && path.segments .last() - .map_or(false, |s| if s.parameters.parenthesized { - false - } else { - s.parameters.types.len() == 1 && - (is_self_ty(&s.parameters.types[0]) || is_ty(&*s.parameters.types[0], self_ty)) + .map_or(false, |s| { + if let Some(ref params) = s.parameters { + if params.parenthesized { + false + } else { + params.types.len() == 1 && + (is_self_ty(¶ms.types[0]) + || is_ty(&*params.types[0], self_ty)) + } + } else { + false + } }) } else { false diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 4a7a042924a..35cbd6ff3db 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -144,7 +144,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let TyPath(QPath::Resolved(_, ref path)) = input.node, let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") - .map(|ps| &ps.parameters.types[0]), + .and_then(|ref ps| ps.parameters.as_ref()) + .map(|params| ¶ms.types[0]), ], { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); db.span_suggestion(input.span, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 69ba0d8bccf..03c94cbf3fb 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -159,7 +159,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< let mut ty_snippet = None; if_let_chain!([ let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node, - let Some(&PathSegment{ref parameters, ..}) = path.segments.last(), + let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last(), parameters.types.len() == 1, ], { ty_snippet = snippet_opt(cx, parameters.types[0].span); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 18b80c76810..76110ecb152 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -194,8 +194,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { let seg = last_path_segment(path); if_let_chain!{[ - !seg.parameters.parenthesized, - let Some(to_ty) = seg.parameters.types.get(1), + let Some(ref params) = seg.parameters, + !params.parenthesized, + let Some(to_ty) = params.types.get(1), let TyRptr(_, ref to_ty) = to_ty.node, ], { return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 90f1e87796d..50683d1fb40 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -154,8 +154,9 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { if Some(def_id) == cx.tcx.lang_items().owned_box() { let last = last_path_segment(qpath); if_let_chain! {[ - !last.parameters.parenthesized, - let Some(vec) = last.parameters.types.get(0), + let Some(ref params) = last.parameters, + !params.parenthesized, + let Some(vec) = params.types.get(0), let TyPath(ref qpath) = vec.node, let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))), match_def_path(cx.tcx, did, &paths::VEC), @@ -183,21 +184,25 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { check_ty(cx, ty, is_local); for ty in p.segments .iter() - .flat_map(|seg| seg.parameters.types.iter()) + .filter_map(|ref seg| seg.parameters.as_ref()) + .flat_map(|ref params| params.types.iter()) { check_ty(cx, ty, is_local); } }, QPath::Resolved(None, ref p) => for ty in p.segments .iter() - .flat_map(|seg| seg.parameters.types.iter()) + .filter_map(|ref seg| seg.parameters.as_ref()) + .flat_map(|ref params| params.types.iter()) { check_ty(cx, ty, is_local); }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); - for ty in seg.parameters.types.iter() { - check_ty(cx, ty, is_local); + if let Some(ref params) = seg.parameters { + for ty in params.types.iter() { + check_ty(cx, ty, is_local); + } } }, } @@ -212,8 +217,9 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { Some(def_id) == cx.tcx.lang_items().owned_box(), let QPath::Resolved(None, ref path) = *qpath, let [ref bx] = *path.segments, - !bx.parameters.parenthesized, - let [ref inner] = *bx.parameters.types + let Some(ref params) = bx.parameters, + !params.parenthesized, + let [ref inner] = *params.types ], { if is_any_trait(inner) { // Ignore `Box` types, see #1884 for details. diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index bb5f6075d0d..d4166f6a2bd 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, ], { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; - if !parameters.parenthesized && parameters.lifetimes.len() == 0 { + if parameters.is_none() { let visitor = &mut UseSelfVisitor { item_path: item_path, cx: cx, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2d3d5874d82..f7867dfd0bd 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -214,7 +214,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_path_segment(&self, left: &PathSegment, right: &PathSegment) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene - left.name.as_str() == right.name.as_str() && self.eq_path_parameters(&left.parameters, &right.parameters) + if left.name.as_str() != right.name.as_str() { + return false; + } + match (&left.parameters, &right.parameters) { + (&None, &None) => true, + (&Some(ref l), &Some(ref r)) => self.eq_path_parameters(l, r), + _ => false + } } fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { -- cgit 1.4.1-3-g733a5 From 2551bd8924e17b8d10f8331d11cf0e469558b5f1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:44:50 -0700 Subject: Reduce cyclomatic complexity of types::check_ty --- clippy_lints/src/types.rs | 96 ++++++++++++++++++++++---------------------- clippy_lints/src/use_self.rs | 7 +++- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 50683d1fb40..9d57527faee 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -184,16 +184,16 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { check_ty(cx, ty, is_local); for ty in p.segments .iter() - .filter_map(|ref seg| seg.parameters.as_ref()) - .flat_map(|ref params| params.types.iter()) + .filter_map(|seg| seg.parameters.as_ref()) + .flat_map(|params| params.types.iter()) { check_ty(cx, ty, is_local); } }, QPath::Resolved(None, ref p) => for ty in p.segments .iter() - .filter_map(|ref seg| seg.parameters.as_ref()) - .flat_map(|ref params| params.types.iter()) + .filter_map(|seg| seg.parameters.as_ref()) + .flat_map(|params| params.types.iter()) { check_ty(cx, ty, is_local); }, @@ -207,49 +207,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { }, } }, - TyRptr(ref lt, MutTy { ref ty, ref mutbl }) => { - match ty.node { - TyPath(ref qpath) => { - let hir_id = cx.tcx.hir.node_to_hir_id(ty.id); - let def = cx.tables.qpath_def(qpath, hir_id); - if_let_chain! {[ - let Some(def_id) = opt_def_id(def), - Some(def_id) == cx.tcx.lang_items().owned_box(), - let QPath::Resolved(None, ref path) = *qpath, - let [ref bx] = *path.segments, - let Some(ref params) = bx.parameters, - !params.parenthesized, - let [ref inner] = *params.types - ], { - if is_any_trait(inner) { - // Ignore `Box` types, see #1884 for details. - return; - } - - let ltopt = if lt.is_elided() { - "".to_owned() - } else { - format!("{} ", lt.name.name().as_str()) - }; - let mutopt = if *mutbl == Mutability::MutMutable { - "mut " - } else { - "" - }; - span_lint_and_sugg(cx, - BORROWED_BOX, - ast_ty.span, - "you seem to be trying to use `&Box`. Consider using just `&T`", - "try", - format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")) - ); - return; // don't recurse into the type - }}; - check_ty(cx, ty, is_local); - }, - _ => check_ty(cx, ty, is_local), - } - }, + TyRptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty), // recurse TySlice(ref ty) | TyArray(ref ty, _) | TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), TyTup(ref tys) => for ty in tys { @@ -259,6 +217,50 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } } +fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { + match mut_ty.ty.node { + TyPath(ref qpath) => { + let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id); + let def = cx.tables.qpath_def(qpath, hir_id); + if_let_chain! {[ + let Some(def_id) = opt_def_id(def), + Some(def_id) == cx.tcx.lang_items().owned_box(), + let QPath::Resolved(None, ref path) = *qpath, + let [ref bx] = *path.segments, + let Some(ref params) = bx.parameters, + !params.parenthesized, + let [ref inner] = *params.types + ], { + if is_any_trait(inner) { + // Ignore `Box` types, see #1884 for details. + return; + } + + let ltopt = if lt.is_elided() { + "".to_owned() + } else { + format!("{} ", lt.name.name().as_str()) + }; + let mutopt = if mut_ty.mutbl == Mutability::MutMutable { + "mut " + } else { + "" + }; + span_lint_and_sugg(cx, + BORROWED_BOX, + ast_ty.span, + "you seem to be trying to use `&Box`. Consider using just `&T`", + "try", + format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")) + ); + return; // don't recurse into the type + }}; + check_ty(cx, &mut_ty.ty, is_local); + }, + _ => check_ty(cx, &mut_ty.ty, is_local), + } +} + // Returns true if given type is `Any` trait. fn is_any_trait(t: &hir::Ty) -> bool { if_let_chain! {[ diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index d4166f6a2bd..946df625cb6 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -59,7 +59,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, ], { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; - if parameters.is_none() { + let should_check = if let Some(ref params) = *parameters { + !params.parenthesized && params.lifetimes.len() == 0 + } else { + true + }; + if should_check { let visitor = &mut UseSelfVisitor { item_path: item_path, cx: cx, -- cgit 1.4.1-3-g733a5 From 1b4aba47b7978cd1b1af11c2d406a4160f8a0fcb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:52:13 -0700 Subject: Fix dogfood filter-map --- clippy_lints/src/types.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9d57527faee..acea709123b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -184,16 +184,18 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { check_ty(cx, ty, is_local); for ty in p.segments .iter() - .filter_map(|seg| seg.parameters.as_ref()) - .flat_map(|params| params.types.iter()) + .flat_map(|seg| seg.parameters.as_ref() + .map_or_else(|| [].iter(), + |params| params.types.iter())) { check_ty(cx, ty, is_local); } }, QPath::Resolved(None, ref p) => for ty in p.segments .iter() - .filter_map(|seg| seg.parameters.as_ref()) - .flat_map(|params| params.types.iter()) + .flat_map(|seg| seg.parameters.as_ref() + .map_or_else(|| [].iter(), + |params| params.types.iter())) { check_ty(cx, ty, is_local); }, -- cgit 1.4.1-3-g733a5 From 66eea5e662db32dcdd233c48b3cddd691c2cb8fa Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:52:20 -0700 Subject: Fix dogfood needless-borrow --- clippy_lints/src/needless_pass_by_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 35cbd6ff3db..ccdb3c179cc 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let TyPath(QPath::Resolved(_, ref path)) = input.node, let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") - .and_then(|ref ps| ps.parameters.as_ref()) + .and_then(|ps| ps.parameters.as_ref()) .map(|params| ¶ms.types[0]), ], { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); -- cgit 1.4.1-3-g733a5 From bebc99d893cf2aebec87f925c80209971eba10da Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:54:24 -0700 Subject: Run prepublish script --- clippy_lints/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f4c9aaf3b08..2d600277e83 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -343,8 +343,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, - int_plus_one::INT_PLUS_ONE, infinite_iter::MAYBE_INFINITE_ITER, + int_plus_one::INT_PLUS_ONE, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, -- cgit 1.4.1-3-g733a5 From 15a2d1a473596e6c6e9b05681556ca72d6506f67 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Sep 2017 19:56:48 -0700 Subject: Bump to 0.0.164 --- CHANGELOG.md | 5 +++++ Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a0ee74e6b..d3c8071f369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.164 +* Update to *rustc 1.22.0-nightly (6c476ce46 2017-09-25)* +* New lint: [`int_plus_one`] + ## 0.0.163 * Update to *rustc 1.22.0-nightly (14039a42a 2017-09-22)* @@ -519,6 +523,7 @@ All notable changes to this project will be documented in this file. [`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask [`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter [`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always +[`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic [`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons diff --git a/Cargo.lock b/Cargo.lock index 4d5f05f93bf..2a0b20d5891 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.163" +version = "0.0.164" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -78,11 +78,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.163" +version = "0.0.164" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.163", + "clippy_lints 0.0.164", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 16aaf148c60..80ea4188c3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.163" +version = "0.0.164" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.163", path = "clippy_lints" } +clippy_lints = { version = "0.0.164", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 96bd05162dc..ef1dcb23818 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.163" +version = "0.0.164" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 5c56c924fc587b0343f1a878f04895e2e20bae73 Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Tue, 26 Sep 2017 18:54:08 +0300 Subject: Clarify verbose_bit_mask_threshold description --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 5272e8a6ca6..ff2832186bf 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -172,7 +172,7 @@ define_Conf! { (enum_variant_name_threshold, "enum_variant_name_threshold", 3 => u64), /// Lint: LARGE_ENUM_VARIANT. The maximum size of a emum's variant to avoid box suggestion (enum_variant_size_threshold, "enum_variant_size_threshold", 200 => u64), - /// Lint: VERBOSE_BIT_MASK. The maximum size of a bit mask, that won't be checked on verbosity + /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), } -- cgit 1.4.1-3-g733a5 From 0ca166277cb663465430d79e5311bd1ea97a27d5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Sep 2017 07:11:34 -0700 Subject: Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27) --- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/utils/sugg.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a0300530a59..76f1a603f24 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1604,7 +1604,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0...32).contains(const_to_u64(n)), + ty::TyArray(_, n) => (0..=32).contains(const_to_u64(n)), _ => false, } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index ec0a351b8b0..d376a62912d 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -126,7 +126,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet), - ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotDot, snippet), + ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotEq, snippet), ast::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), ast::ExprKind::AssignOp(op, ..) => Sugg::BinOp(astbinop2assignop(op), snippet), ast::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(op.node), snippet), @@ -165,7 +165,7 @@ impl<'a> Sugg<'a> { pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, &end), - ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotDot, &self, &end), + ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, &end), } } @@ -312,7 +312,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), AssocOp::As => format!("{} as {}", lhs, rhs), AssocOp::DotDot => format!("{}..{}", lhs, rhs), - AssocOp::DotDotDot => format!("{}...{}", lhs, rhs), + AssocOp::DotDotEq => format!("{}...{}", lhs, rhs), AssocOp::Colon => format!("{}: {}", lhs, rhs), }; @@ -362,7 +362,7 @@ fn associativity(op: &AssocOp) -> Associativity { ShiftLeft | ShiftRight | Subtract => Associativity::Left, - DotDot | DotDotDot => Associativity::None, + DotDot | DotDotEq => Associativity::None, } } -- cgit 1.4.1-3-g733a5 From 201b5c2f2444e242c9f96e732a3e4cc5e5cc4e8d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Sep 2017 10:35:14 -0700 Subject: Use ..= in the suggestion --- Cargo.lock | 6 +++--- clippy_lints/src/utils/sugg.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a0b20d5891..34be0d11a52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "clippy_lints" -version = "0.0.164" +version = "0.0.165" dependencies = [ "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -78,11 +78,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clippy" -version = "0.0.164" +version = "0.0.165" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.164", + "clippy_lints 0.0.165", "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d376a62912d..d811de59844 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -312,7 +312,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), AssocOp::As => format!("{} as {}", lhs, rhs), AssocOp::DotDot => format!("{}..{}", lhs, rhs), - AssocOp::DotDotEq => format!("{}...{}", lhs, rhs), + AssocOp::DotDotEq => format!("{}..={}", lhs, rhs), AssocOp::Colon => format!("{}: {}", lhs, rhs), }; -- cgit 1.4.1-3-g733a5 From 3159a7f2a12c8e1b753598544c71be8ae8eae628 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Sep 2017 10:40:19 -0700 Subject: Update ... -> ..= in tests --- tests/ui/array_indexing.rs | 16 ++++++++-------- tests/ui/array_indexing.stderr | 16 ++++++++-------- tests/ui/copies.rs | 12 ++++++------ tests/ui/for_loop.rs | 8 ++++---- tests/ui/for_loop.stderr | 6 +++--- tests/ui/no_effect.rs | 2 +- tests/ui/no_effect.stderr | 2 +- tests/ui/range.rs | 2 +- tests/ui/range.stderr | 2 +- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/tests/ui/array_indexing.rs b/tests/ui/array_indexing.rs index 34b422db6e9..c38342daf68 100644 --- a/tests/ui/array_indexing.rs +++ b/tests/ui/array_indexing.rs @@ -13,8 +13,8 @@ fn main() { x[1 << 3]; &x[1..5]; &x[0..3]; - &x[0...4]; - &x[...4]; + &x[0..=4]; + &x[..=4]; &x[..]; &x[1..]; &x[4..]; @@ -26,19 +26,19 @@ fn main() { y[0]; &y[1..2]; &y[..]; - &y[0...4]; - &y[...4]; + &y[0..=4]; + &y[..=4]; let empty: [i8; 0] = []; empty[0]; &empty[1..5]; - &empty[0...4]; - &empty[...4]; + &empty[0..=4]; + &empty[..=4]; &empty[..]; &empty[0..]; &empty[0..0]; - &empty[0...0]; - &empty[...0]; + &empty[0..=0]; + &empty[..=0]; &empty[..0]; &empty[1..]; &empty[..4]; diff --git a/tests/ui/array_indexing.stderr b/tests/ui/array_indexing.stderr index ea95c325460..d730b012932 100644 --- a/tests/ui/array_indexing.stderr +++ b/tests/ui/array_indexing.stderr @@ -21,13 +21,13 @@ error: range is out of bounds error: range is out of bounds --> $DIR/array_indexing.rs:16:6 | -16 | &x[0...4]; +16 | &x[0..=4]; | ^^^^^^^^ error: range is out of bounds --> $DIR/array_indexing.rs:17:6 | -17 | &x[...4]; +17 | &x[..=4]; | ^^^^^^^ error: range is out of bounds @@ -59,13 +59,13 @@ error: slicing may panic error: slicing may panic --> $DIR/array_indexing.rs:29:6 | -29 | &y[0...4]; +29 | &y[0..=4]; | ^^^^^^^^ error: slicing may panic --> $DIR/array_indexing.rs:30:6 | -30 | &y[...4]; +30 | &y[..=4]; | ^^^^^^^ error: const index is out of bounds @@ -83,25 +83,25 @@ error: range is out of bounds error: range is out of bounds --> $DIR/array_indexing.rs:35:6 | -35 | &empty[0...4]; +35 | &empty[0..=4]; | ^^^^^^^^^^^^ error: range is out of bounds --> $DIR/array_indexing.rs:36:6 | -36 | &empty[...4]; +36 | &empty[..=4]; | ^^^^^^^^^^^ error: range is out of bounds --> $DIR/array_indexing.rs:40:6 | -40 | &empty[0...0]; +40 | &empty[0..=0]; | ^^^^^^^^^^^^ error: range is out of bounds --> $DIR/array_indexing.rs:41:6 | -41 | &empty[...0]; +41 | &empty[..=0]; | ^^^^^^^^^^^ error: range is out of bounds diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index a7b99252735..652afac6c68 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,4 +1,4 @@ -#![feature(plugin, inclusive_range_syntax)] +#![feature(plugin, dotdoteq_in_patterns, inclusive_range_syntax)] #![plugin(clippy)] #![allow(dead_code, no_effect, unnecessary_operation)] @@ -33,7 +33,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { ..; 0..; ..10; - 0...10; + 0..=10; foo(); } else { @@ -42,7 +42,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { ..; 0..; ..10; - 0...10; + 0..=10; foo(); } @@ -64,7 +64,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { 0..10; } else { - 0...10; + 0..=10; } if true { @@ -161,7 +161,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match 42 { 42 => 1, a if a > 0 => 2, - 10...15 => 3, + 10..=15 => 3, _ => 4, }; } @@ -172,7 +172,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match 42 { 42 => 1, a if a > 0 => 2, - 10...15 => 3, + 10..=15 => 3, _ => 4, }; } diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index aa8b9632293..95d15776a36 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -125,7 +125,7 @@ fn main() { println!("{}", vec[i]); } - for i in 0...MAX_LEN { + for i in 0..=MAX_LEN { println!("{}", vec[i]); } @@ -133,7 +133,7 @@ fn main() { println!("{}", vec[i]); } - for i in 5...10 { + for i in 5..=10 { println!("{}", vec[i]); } @@ -149,7 +149,7 @@ fn main() { println!("{}", i); } - for i in 10...0 { + for i in 10..=0 { println!("{}", i); } @@ -161,7 +161,7 @@ fn main() { println!("{}", i); } - for i in 5...5 { + for i in 5..=5 { // not an error, this is the range with only one element “5” println!("{}", i); } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 79c6c781a7a..09c4deb492a 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -178,7 +178,7 @@ help: consider using an iterator error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:128:5 | -128 | / for i in 0...MAX_LEN { +128 | / for i in 0..=MAX_LEN { 129 | | println!("{}", vec[i]); 130 | | } | |_____^ @@ -204,7 +204,7 @@ help: consider using an iterator error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:136:5 | -136 | / for i in 5...10 { +136 | / for i in 5..=10 { 137 | | println!("{}", vec[i]); 138 | | } | |_____^ @@ -257,7 +257,7 @@ help: consider using the following if you are attempting to iterate over this ra error: this range is empty so this for loop will never run --> $DIR/for_loop.rs:152:5 | -152 | / for i in 10...0 { +152 | / for i in 10..=0 { 153 | | println!("{}", i); 154 | | } | |_____^ diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index bef1fad4f69..5c3a1a041c2 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -49,7 +49,7 @@ fn main() { 5..; ..5; 5..6; - 5...6; + 5..=6; [42, 55]; [42, 55][1]; (42, 55).1; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 590b1eab497..b6db8e7498e 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -111,7 +111,7 @@ error: statement with no effect error: statement with no effect --> $DIR/no_effect.rs:52:5 | -52 | 5...6; +52 | 5..=6; | ^^^^^^ error: statement with no effect diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 4f4573d9e60..bb1a04cfcf3 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -15,7 +15,7 @@ fn main() { let _ = (0..1).step_by(1); let _ = (1..).step_by(0); - let _ = (1...2).step_by(0); + let _ = (1..=2).step_by(0); let x = 0..1; let _ = x.step_by(0); diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 772375c179b..fc51f1a07f0 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -15,7 +15,7 @@ error: Iterator::step_by(0) will panic at runtime error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:18:13 | -18 | let _ = (1...2).step_by(0); +18 | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime -- cgit 1.4.1-3-g733a5 From b1c62e12958170326e973c910d559bccea0f70ff Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Sep 2017 10:44:26 -0700 Subject: Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c95d96c2c3f..0e3fb8be43d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. -## Trunk +## 0.0.165 +* Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27) * New lint: [`mut_range_bound`] ## 0.0.164 -- cgit 1.4.1-3-g733a5 From 02e7fada5cdcf4c8573ca5ab81037fd80fa6ca49 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Sep 2017 10:44:29 -0700 Subject: Bump to 0.0.165 --- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 80ea4188c3a..f9c3fd0fd67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.164" +version = "0.0.165" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ path = "src/main.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.164", path = "clippy_lints" } +clippy_lints = { version = "0.0.165", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ef1dcb23818..85d65c79176 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.164" +version = "0.0.165" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 4da0aeb40e2459a86bda60a1883b21690943d130 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 27 Sep 2017 14:17:08 -0400 Subject: Set RUSTC_WRAPPER instead of RUSTC when invoking Cargo Some build scripts rely on the RUSTC binary being the actual compiler (e.g. parsing the output of 'RUSTC --version'). To prevent clippy from breaking these build scripts, this commit sets RUSTC_WRAPPER instead. This will cause Cargo to leave RUSTC unchanged, making the use of clippy transparent to build scripts. --- src/main.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index f4945998fde..f21cd7bd28c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -181,7 +181,7 @@ pub fn main() { return; } - if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) { + if "clippy" == std::env::args().nth(1).as_ref().expect("cargo-clippy should be called with at least one argument!") { // this arm is executed on the initial call to `cargo clippy` let manifest_path_arg = std::env::args() @@ -285,7 +285,7 @@ pub fn main() { } } } else { - // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` + // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC_WRAPPER` // env var set to itself let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); @@ -310,13 +310,17 @@ pub fn main() { }; rustc_driver::in_rustc_thread(|| { + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programatically, so we ignore this/ + let orig_args: Vec = env::args().skip(1).collect(); + // this conditional check for the --sysroot flag is there so users can call // `cargo-clippy` directly // without having to pass --sysroot or anything - let mut args: Vec = if env::args().any(|s| s == "--sysroot") { - env::args().collect() + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() } else { - env::args() + orig_args.clone().into_iter() .chain(Some("--sysroot".to_owned())) .chain(Some(sys_root)) .collect() @@ -325,7 +329,7 @@ pub fn main() { // this check ensures that dependencies are built but not linted and the final // crate is // linted but not built - let clippy_enabled = env::args().any(|s| s == "--emit=metadata"); + let clippy_enabled = orig_args.iter().any(|s| s == "--emit=metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); @@ -361,7 +365,7 @@ where let path = std::env::current_exe().expect("current executable path invalid"); let exit_status = std::process::Command::new("cargo") .args(&args) - .env("RUSTC", path) + .env("RUSTC_WRAPPER", path) .spawn() .expect("could not run cargo") .wait() -- cgit 1.4.1-3-g733a5 From cae9cedeb5acc9b4edc23b376e15fba339254c31 Mon Sep 17 00:00:00 2001 From: mcarton Date: Fri, 29 Sep 2017 18:36:03 +0200 Subject: Fix regression with `format!` --- clippy_lints/src/format.rs | 27 +++++++++++++++------------ tests/ui/format.stderr | 14 +++++++++++++- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index f1a450e58df..26b500d5546 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -50,8 +50,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1), // ensure the format string is `"{..}"` with only one argument and no text - check_static_str(cx, &args[0]), + check_static_str(&args[0]), // ensure the format argument is `{}` ie. Display with no fancy option + // and that the argument is a string check_arg_is_display(cx, &args[1]) ], { span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); @@ -96,17 +97,19 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp None } -/// Checks if the expressions matches -/// ```rust, ignore -/// { static __STATIC_FMTSTR: &'static[&'static str] = &["a", "b", c]; -/// __STATIC_FMTSTR } -/// ``` -fn check_static_str(cx: &LateContext, expr: &Expr) -> bool { - if let Some(expr) = get_argument_fmtstr_parts(cx, expr) { - expr.len() == 1 && expr[0].is_empty() - } else { - false - } +/// Checks if the expressions matches `&[""]` +fn check_static_str(expr: &Expr) -> bool { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, // &[""] + let ExprArray(ref exprs) = expr.node, // [""] + exprs.len() == 1, + let ExprLit(ref lit) = exprs[0].node, + let LitKind::Str(ref lit, _) = lit.node, + ], { + return lit.as_str().is_empty(); + }} + + false } /// Checks if the expressions matches diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 5f5bdc02a59..d2c9f393831 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,5 +6,17 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` -error: aborting due to previous error +error: useless use of `format!` + --> $DIR/format.rs:8:5 + | +8 | format!("{}", "foo"); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: useless use of `format!` + --> $DIR/format.rs:15:5 + | +15 | format!("{}", arg); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 7e956ac7c4a38c862e344e5e60243b3995bc5831 Mon Sep 17 00:00:00 2001 From: mcarton Date: Fri, 29 Sep 2017 19:13:21 +0200 Subject: Fix regression with `print!` --- clippy_lints/src/format.rs | 29 ----------------------------- clippy_lints/src/print.rs | 26 ++++++++++++++++++++------ tests/ui/print_with_newline.stderr | 28 ++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 26b500d5546..6a6cbadb6fa 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,9 +1,7 @@ use rustc::hir::*; -use rustc::hir::map::Node::NodeItem; use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; -use syntax::symbol::InternedString; use utils::paths; use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty, opt_def_id}; @@ -70,33 +68,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -/// Returns the slice of format string parts in an `Arguments::new_v1` call. -/// Public because it's shared with a lint in print.rs. -pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr) -> Option> { - if_let_chain! {[ - let ExprBlock(ref block) = expr.node, - block.stmts.len() == 1, - let StmtDecl(ref decl, _) = block.stmts[0].node, - let DeclItem(ref decl) = decl.node, - let Some(NodeItem(decl)) = cx.tcx.hir.find(decl.id), - decl.name == "__STATIC_FMTSTR", - let ItemStatic(_, _, ref expr) = decl.node, - let ExprAddrOf(_, ref expr) = cx.tcx.hir.body(*expr).value.node, // &["…", "…", …] - let ExprArray(ref exprs) = expr.node, - ], { - let mut result = Vec::new(); - for expr in exprs { - if let ExprLit(ref lit) = expr.node { - if let LitKind::Str(ref lit, _) = lit.node { - result.push(lit.as_str()); - } - } - } - return Some(result); - }} - None -} - /// Checks if the expressions matches `&[""]` fn check_static_str(expr: &Expr) -> bool { if_let_chain! {[ diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 078e208467a..96557b8b0cb 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -1,9 +1,10 @@ use rustc::hir::*; use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::lint::*; -use utils::{paths, opt_def_id}; +use syntax::ast::LitKind; +use syntax::symbol::InternedString; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; -use format::get_argument_fmtstr_parts; +use utils::{paths, opt_def_id}; /// **What it does:** This lint warns when you using `print!()` with a format /// string that @@ -103,15 +104,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprTup(ref args) = args.node, // collect the format string parts and check the last one - let Some(fmtstrs) = get_argument_fmtstr_parts(cx, &args_args[0]), - let Some(last_str) = fmtstrs.last(), - let Some('\n') = last_str.chars().last(), + let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]), + let Some('\n') = fmtstr.chars().last(), // "foo{}bar" is made into two strings + one argument, // if the format string starts with `{}` (eg. "{}foo"), // the string array is prepended an empty string "". // We only want to check the last string after any `{}`: - args.len() < fmtstrs.len(), + args.len() < fmtlen, ], { span_lint(cx, PRINT_WITH_NEWLINE, span, "using `print!()` with a format string that ends in a \ @@ -150,3 +150,17 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { false } + +/// Returns the slice of format string parts in an `Arguments::new_v1` call. +fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(InternedString, usize)> { + if_let_chain! {[ + let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …] + let ExprArray(ref exprs) = expr.node, + let Some(expr) = exprs.last(), + let ExprLit(ref lit) = expr.node, + let LitKind::Str(ref lit, _) = lit.node, + ], { + return Some((lit.as_str(), exprs.len())); + }} + None +} diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index e69de29bb2d..1bacc40bfb4 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -0,0 +1,28 @@ +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:6:5 + | +6 | print!("Hello/n"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D print-with-newline` implied by `-D warnings` + +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:7:5 + | +7 | print!("Hello {}/n", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:8:5 + | +8 | print!("Hello {} {}/n/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:9:5 + | +9 | print!("{}/n", 1265); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From f3e51d8d65e7188ae10506807591aca621f8ad96 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Thu, 28 Sep 2017 22:24:31 -0400 Subject: add lint for creation of invalid references --- clippy_lints/src/invalid_ref.rs | 59 +++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 +++ clippy_lints/src/utils/paths.rs | 4 +++ tests/ui/invalid_ref.rs | 45 +++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 clippy_lints/src/invalid_ref.rs create mode 100644 tests/ui/invalid_ref.rs diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs new file mode 100644 index 00000000000..440e3055bb1 --- /dev/null +++ b/clippy_lints/src/invalid_ref.rs @@ -0,0 +1,59 @@ +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use utils::{match_def_path, paths, span_help_and_lint, opt_def_id}; + +/// **What it does:** Checks for creation of references to zeroed or uninitialized memory. +/// +/// **Why is this bad?** Creation of null references is undefined behavior. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let bad_ref: &usize = std::mem::zeroed(); +/// ``` + +declare_lint! { + pub INVALID_REF, + Warn, + "creation of invalid reference" +} + +const ZERO_REF_SUMMARY: &str = "reference to zeroed memory"; +const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; + +pub struct InvalidRef; + +impl LintPass for InvalidRef { + fn get_lints(&self) -> LintArray { + lint_array!(INVALID_REF) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_let_chain!{[ + let ty::TyRef(..) = cx.tables.expr_ty(expr).sty, + let ExprCall(ref path, ref args) = expr.node, + let ExprPath(ref qpath) = path.node, + args.len() == 0, + let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)), + ], { + let help = "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; + if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { + let lint = INVALID_REF; + let msg = ZERO_REF_SUMMARY; + span_help_and_lint(cx, lint, expr.span, &msg, &help); + } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | match_def_path(cx.tcx, def_id, &paths::UNINIT) { + let lint = INVALID_REF; + let msg = UNINIT_REF_SUMMARY; + span_help_and_lint(cx, lint, expr.span, &msg, &help); + } else { + return; + } + }} + return; + } +} + diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bca15f69326..759a66eaae5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -97,6 +97,7 @@ pub mod if_let_redundant_pattern_matching; pub mod if_not_else; pub mod infinite_iter; pub mod int_plus_one; +pub mod invalid_ref; pub mod is_unit_expr; pub mod items_after_statements; pub mod large_enum_variant; @@ -328,6 +329,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::Pass); + reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -345,6 +347,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, int_plus_one::INT_PLUS_ONE, + invalid_ref::INVALID_REF, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index d18a5af59e3..89bc84f4a50 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -30,6 +30,7 @@ pub const HASH: [&'static str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; +pub const INIT: [&'static str; 4] = ["core", "intrinsics", "", "init"]; pub const INTO_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "IntoIterator"]; pub const IO_PRINT: [&'static str; 4] = ["std", "io", "stdio", "_print"]; pub const IO_READ: [&'static str; 3] = ["std", "io", "Read"]; @@ -39,6 +40,8 @@ pub const LINKED_LIST: [&'static str; 3] = ["alloc", "linked_list", "LinkedList" pub const LINT: [&'static str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&'static str; 3] = ["rustc", "lint", "LintArray"]; pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; +pub const MEM_ZEROED: [&'static str; 3] = ["core", "mem", "zeroed"]; +pub const MEM_UNINIT: [&'static str; 3] = ["core", "mem", "uninitialized"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; @@ -80,6 +83,7 @@ pub const TO_OWNED: [&'static str; 3] = ["alloc", "borrow", "ToOwned"]; pub const TO_STRING: [&'static str; 3] = ["alloc", "string", "ToString"]; pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_INTO_RESULT: [&'static str; 4] = ["std", "ops", "Try", "into_result"]; +pub const UNINIT: [&'static str; 4] = ["core", "intrinsics", "", "uninit"]; pub const VEC: [&'static str; 3] = ["alloc", "vec", "Vec"]; pub const VEC_DEQUE: [&'static str; 3] = ["alloc", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&'static str; 3] = ["alloc", "vec", "from_elem"]; diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs new file mode 100644 index 00000000000..d7341575e95 --- /dev/null +++ b/tests/ui/invalid_ref.rs @@ -0,0 +1,45 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![allow(unused)] +#![feature(core_intrinsics)] + +extern crate core; +use std::intrinsics::{init, uninit}; + +fn main() { + let x = 1; + unsafe { + ref_to_zeroed_std(&x); + ref_to_zeroed_core(&x); + ref_to_zeroed_intr(&x); + ref_to_uninit_std(&x); + ref_to_uninit_core(&x); + ref_to_uninit_intr(&x); + } +} + +unsafe fn ref_to_zeroed_std(t: &T) { + let ref_zero: &T = std::mem::zeroed(); // warning +} + +unsafe fn ref_to_zeroed_core(t: &T) { + let ref_zero: &T = core::mem::zeroed(); // warning +} + +unsafe fn ref_to_zeroed_intr(t: &T) { + let ref_zero: &T = std::intrinsics::init(); // warning +} + +unsafe fn ref_to_uninit_std(t: &T) { + let ref_uninit: &T = std::mem::uninitialized(); // warning +} + +unsafe fn ref_to_uninit_core(t: &T) { + let ref_uninit: &T = core::mem::uninitialized(); // warning +} + +unsafe fn ref_to_uninit_intr(t: &T) { + let ref_uninit: &T = std::intrinsics::uninit(); // warning +} + -- cgit 1.4.1-3-g733a5 From 7fd11d23b04d6117e1e90c74b4091509c8aff249 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Thu, 28 Sep 2017 22:52:10 -0400 Subject: add ui test for invalid_ref --- tests/ui/invalid_ref.stderr | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/ui/invalid_ref.stderr diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr new file mode 100644 index 00000000000..7cdc31a0ffa --- /dev/null +++ b/tests/ui/invalid_ref.stderr @@ -0,0 +1,51 @@ +error: reference to zeroed memory + --> $DIR/invalid_ref.rs:23:24 + | +23 | let ref_zero: &T = std::mem::zeroed(); // warning + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D invalid-ref` implied by `-D warnings` + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: reference to zeroed memory + --> $DIR/invalid_ref.rs:27:24 + | +27 | let ref_zero: &T = core::mem::zeroed(); // warning + | ^^^^^^^^^^^^^^^^^^^ + | + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: reference to zeroed memory + --> $DIR/invalid_ref.rs:31:24 + | +31 | let ref_zero: &T = std::intrinsics::init(); // warning + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: reference to uninitialized memory + --> $DIR/invalid_ref.rs:35:26 + | +35 | let ref_uninit: &T = std::mem::uninitialized(); // warning + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: reference to uninitialized memory + --> $DIR/invalid_ref.rs:39:26 + | +39 | let ref_uninit: &T = core::mem::uninitialized(); // warning + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: reference to uninitialized memory + --> $DIR/invalid_ref.rs:43:26 + | +43 | let ref_uninit: &T = std::intrinsics::uninit(); // warning + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From ddad5e0f86176e7bd2edaa95ec5272911791669f Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Fri, 29 Sep 2017 21:01:02 -0400 Subject: add tests for false positives --- clippy_lints/src/invalid_ref.rs | 20 ++++++++------------ tests/ui/invalid_ref.rs | 21 +++++++++++++++++++++ tests/ui/invalid_ref.stderr | 24 ++++++++++++------------ 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 440e3055bb1..ad3398cb078 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -22,6 +22,7 @@ declare_lint! { const ZERO_REF_SUMMARY: &str = "reference to zeroed memory"; const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; +const HELP: &str = "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; pub struct InvalidRef; @@ -34,26 +35,21 @@ impl LintPass for InvalidRef { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_let_chain!{[ - let ty::TyRef(..) = cx.tables.expr_ty(expr).sty, let ExprCall(ref path, ref args) = expr.node, let ExprPath(ref qpath) = path.node, args.len() == 0, + let ty::TyRef(..) = cx.tables.expr_ty(expr).sty, let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)), ], { - let help = "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; - if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { - let lint = INVALID_REF; - let msg = ZERO_REF_SUMMARY; - span_help_and_lint(cx, lint, expr.span, &msg, &help); + let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { + ZERO_REF_SUMMARY } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | match_def_path(cx.tcx, def_id, &paths::UNINIT) { - let lint = INVALID_REF; - let msg = UNINIT_REF_SUMMARY; - span_help_and_lint(cx, lint, expr.span, &msg, &help); + UNINIT_REF_SUMMARY } else { return; - } - }} + }; + span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP); + }} return; } } - diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs index d7341575e95..2b8f04c9781 100644 --- a/tests/ui/invalid_ref.rs +++ b/tests/ui/invalid_ref.rs @@ -16,6 +16,10 @@ fn main() { ref_to_uninit_std(&x); ref_to_uninit_core(&x); ref_to_uninit_intr(&x); + some_ref(); + std_zeroed_no_ref(); + core_zeroed_no_ref(); + intr_init_no_ref(); } } @@ -43,3 +47,20 @@ unsafe fn ref_to_uninit_intr(t: &T) { let ref_uninit: &T = std::intrinsics::uninit(); // warning } +fn some_ref() { + let some_ref = &1; +} + +unsafe fn std_zeroed_no_ref() { + let mem_zero: usize = std::mem::zeroed(); // no warning +} + +unsafe fn core_zeroed_no_ref() { + let mem_zero: usize = core::mem::zeroed(); // no warning +} + +unsafe fn intr_init_no_ref() { + let mem_zero: usize = std::intrinsics::init(); // no warning +} + + diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 7cdc31a0ffa..420fed01744 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,48 +1,48 @@ error: reference to zeroed memory - --> $DIR/invalid_ref.rs:23:24 + --> $DIR/invalid_ref.rs:27:24 | -23 | let ref_zero: &T = std::mem::zeroed(); // warning +27 | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | = note: `-D invalid-ref` implied by `-D warnings` = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:27:24 + --> $DIR/invalid_ref.rs:31:24 | -27 | let ref_zero: &T = core::mem::zeroed(); // warning +31 | let ref_zero: &T = core::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:31:24 + --> $DIR/invalid_ref.rs:35:24 | -31 | let ref_zero: &T = std::intrinsics::init(); // warning +35 | let ref_zero: &T = std::intrinsics::init(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:35:26 + --> $DIR/invalid_ref.rs:39:26 | -35 | let ref_uninit: &T = std::mem::uninitialized(); // warning +39 | let ref_uninit: &T = std::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:39:26 + --> $DIR/invalid_ref.rs:43:26 | -39 | let ref_uninit: &T = core::mem::uninitialized(); // warning +43 | let ref_uninit: &T = core::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:43:26 + --> $DIR/invalid_ref.rs:47:26 | -43 | let ref_uninit: &T = std::intrinsics::uninit(); // warning +47 | let ref_uninit: &T = std::intrinsics::uninit(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html -- cgit 1.4.1-3-g733a5 From 8e6abc6fd761b8a1c607d9d1f626db99f146aee7 Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Fri, 29 Sep 2017 21:48:10 -0400 Subject: alphabetize paths to pass dogfood --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 89bc84f4a50..2a2eabcca1f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -40,8 +40,8 @@ pub const LINKED_LIST: [&'static str; 3] = ["alloc", "linked_list", "LinkedList" pub const LINT: [&'static str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&'static str; 3] = ["rustc", "lint", "LintArray"]; pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; -pub const MEM_ZEROED: [&'static str; 3] = ["core", "mem", "zeroed"]; pub const MEM_UNINIT: [&'static str; 3] = ["core", "mem", "uninitialized"]; +pub const MEM_ZEROED: [&'static str; 3] = ["core", "mem", "zeroed"]; pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; -- cgit 1.4.1-3-g733a5 From e40c270d4f37662b7263ab40914105978da2dbb3 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 18 Jun 2017 23:00:14 +0200 Subject: Don't lint autolinks in `doc_markdown` --- clippy_lints/src/doc.rs | 12 +++++++++++- tests/ui/doc.rs | 5 +++++ tests/ui/doc.stderr | 8 +++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 170ca5cf007..0c4a2a88ae0 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -195,16 +195,26 @@ fn check_doc<'a, Events: Iterator)>>( use pulldown_cmark::Tag::*; let mut in_code = false; + let mut in_link = None; for (offset, event) in docs { match event { Start(CodeBlock(_)) | Start(Code) => in_code = true, End(CodeBlock(_)) | End(Code) => in_code = false, - Start(_tag) | End(_tag) => (), // We don't care about other tags + Start(Link(link, _)) => in_link = Some(link), + End(Link(_, _)) => in_link = None, + Start(_tag) | End(_tag) => (), // We don't care about other tags Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it SoftBreak => (), HardBreak => (), FootnoteReference(text) | Text(text) => { + if Some(&text) == in_link.as_ref() { + // Probably a link of the form `` + // Which are represented as a link to "http://example.com" with + // text "http://example.com" by pulldown-cmark + continue; + } + if !in_code { let index = match spans.binary_search_by(|c| c.0.cmp(&offset)) { Ok(o) => o, diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 9e7b34e3ea5..21449e526af 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -159,3 +159,8 @@ fn issue_1469() {} *This would also be an error under a strict common mark interpretation */ fn issue_1920() {} + +/// Ok: +/// +/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +fn issue_1832() {} diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index c3146f17d08..fb0d724172d 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -156,5 +156,11 @@ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the doc 138 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 26 previous errors +error: you should put `http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels` between ticks in the documentation + --> $DIR/doc.rs:165:13 + | +165 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 27 previous errors -- cgit 1.4.1-3-g733a5 From b10610cdebc4d86349985c8dbca5a523a92b9aec Mon Sep 17 00:00:00 2001 From: mcarton Date: Mon, 19 Jun 2017 19:49:29 +0200 Subject: Add the `url` crate as a dependency --- Cargo.lock | 38 ++++++++++++++++++++++++++++++++++++++ clippy_lints/Cargo.toml | 1 + clippy_lints/src/lib.rs | 1 + 3 files changed, 40 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 34be0d11a52..1eed9fa4e95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,7 @@ dependencies = [ "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -147,6 +148,16 @@ name = "getopts" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "idna" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.6.2" @@ -228,6 +239,11 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "percent-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pulldown-cmark" version = "0.0.15" @@ -367,6 +383,14 @@ dependencies = [ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-normalization" version = "0.1.5" @@ -385,6 +409,16 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "url" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "1.0.0" @@ -421,6 +455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" +"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -433,6 +468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -451,9 +487,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 85d65c79176..9c78514285d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -28,6 +28,7 @@ serde_derive = "1.0" toml = "0.4" unicode-normalization = "0.1" pulldown-cmark = "0.0.15" +url = "1.5.0" [features] debugging = [] diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bca15f69326..c61d78c6410 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -51,6 +51,7 @@ extern crate lazy_static; extern crate itertools; extern crate pulldown_cmark; +extern crate url; macro_rules! declare_restriction_lint { { pub $name:tt, $description:tt } => { -- cgit 1.4.1-3-g733a5 From aca6c1e06576b41f75da5b5faa682cdd3f17531e Mon Sep 17 00:00:00 2001 From: mcarton Date: Mon, 19 Jun 2017 21:23:50 +0200 Subject: Have a separate message for raw URLs in doc --- clippy_lints/src/doc.rs | 13 +++++++++++++ tests/ui/doc.rs | 3 +++ tests/ui/doc.stderr | 24 +++++++++++++++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 0c4a2a88ae0..3162dbc422b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -5,6 +5,7 @@ use syntax::ast; use syntax::codemap::{BytePos, Span}; use syntax_pos::Pos; use utils::span_lint; +use url::Url; /// **What it does:** Checks for the presence of `_`, `::` or camel-case words /// outside ticks in documentation. @@ -280,6 +281,18 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { s != "_" && !s.contains("\\_") && s.contains('_') } + if let Ok(url) = Url::parse(word) { + // try to get around the fact that `foo::bar` parses as a valid URL + if !url.cannot_be_a_base() { + span_lint(cx, + DOC_MARKDOWN, + span, + "you should put bare URLs between `<`/`>` or make a proper Markdown link"); + + return; + } + } + if has_underscore(word) || word.contains("::") || is_camel_case(word) { span_lint( cx, diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 21449e526af..70009d76f5d 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -162,5 +162,8 @@ fn issue_1920() {} /// Ok: /// +/// Not ok: http://www.unicode.org +/// Not ok: https://www.unicode.org +/// Not ok: http://www.unicode.org/ /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels fn issue_1832() {} diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index fb0d724172d..f38678e89aa 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -156,11 +156,29 @@ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the doc 138 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: you should put `http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels` between ticks in the documentation +error: you should put bare URLs between `<`/`>` or make a proper Markdown link --> $DIR/doc.rs:165:13 | -165 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +165 | /// Not ok: http://www.unicode.org + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: you should put bare URLs between `<`/`>` or make a proper Markdown link + --> $DIR/doc.rs:166:13 + | +166 | /// Not ok: https://www.unicode.org + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: you should put bare URLs between `<`/`>` or make a proper Markdown link + --> $DIR/doc.rs:167:13 + | +167 | /// Not ok: http://www.unicode.org/ + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: you should put bare URLs between `<`/`>` or make a proper Markdown link + --> $DIR/doc.rs:168:13 + | +168 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 27 previous errors +error: aborting due to 30 previous errors -- cgit 1.4.1-3-g733a5 From 50ffaca4c9686af96ab86a8ec201f5b31dd62a32 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Sep 2017 12:47:33 +0200 Subject: Reduce the hackiness of cargo-clippy --- .travis.yml | 1 + Cargo.toml | 6 + build.rs | 8 + src/driver.rs | 198 ++++++++++++ src/main.rs | 353 ++++++---------------- tests/compile-test.rs | 15 +- tests/conf_whitelisted.rs | 3 + tests/run-pass/associated-constant-ice.rs | 4 +- tests/run-pass/conf_whitelisted.rs | 4 - tests/run-pass/enum-glob-import-crate.rs | 4 +- tests/run-pass/ice-1588.rs | 4 +- tests/run-pass/ice-1969.rs | 4 +- tests/run-pass/ice-700.rs | 4 +- tests/run-pass/mut_mut_macro.rs | 4 +- tests/run-pass/needless_lifetimes_impl_trait.rs | 4 +- tests/run-pass/procedural_macro.rs | 2 +- tests/run-pass/regressions.rs | 4 +- tests/run-pass/single-match-else.rs | 4 +- tests/ui-posix/conf_non_existant.rs | 6 - tests/ui-posix/conf_non_existant.stderr | 4 - tests/ui-posix/update-all-references.sh | 28 -- tests/ui-posix/update-references.sh | 50 --- tests/ui-windows/conf_non_existant.rs | 6 - tests/ui-windows/conf_non_existant.stderr | 4 - tests/ui-windows/update-all-references.sh | 28 -- tests/ui-windows/update-references.sh | 50 --- tests/ui/absurd-extreme-comparisons.rs | 4 +- tests/ui/absurd-extreme-comparisons.stderr | 2 - tests/ui/approx_const.rs | 4 +- tests/ui/approx_const.stderr | 2 - tests/ui/arithmetic.rs | 4 +- tests/ui/arithmetic.stderr | 2 - tests/ui/array_indexing.rs | 2 +- tests/ui/array_indexing.stderr | 2 - tests/ui/assign_ops.rs | 4 +- tests/ui/assign_ops.stderr | 2 - tests/ui/assign_ops2.rs | 4 +- tests/ui/assign_ops2.stderr | 2 - tests/ui/attrs.rs | 4 +- tests/ui/attrs.stderr | 2 - tests/ui/bit_masks.rs | 4 +- tests/ui/bit_masks.stderr | 2 - tests/ui/blacklisted_name.rs | 4 +- tests/ui/blacklisted_name.stderr | 2 - tests/ui/block_in_if_condition.rs | 4 +- tests/ui/block_in_if_condition.stderr | 2 - tests/ui/bool_comparison.rs | 4 +- tests/ui/bool_comparison.stderr | 2 - tests/ui/booleans.rs | 4 +- tests/ui/booleans.stderr | 2 - tests/ui/borrow_box.rs | 4 +- tests/ui/borrow_box.stderr | 2 - tests/ui/box_vec.rs | 4 +- tests/ui/box_vec.stderr | 2 - tests/ui/builtin-type-shadow.rs | 4 +- tests/ui/builtin-type-shadow.stderr | 2 - tests/ui/bytecount.rs | 4 +- tests/ui/bytecount.stderr | 2 - tests/ui/cast.rs | 4 +- tests/ui/cast.stderr | 2 - tests/ui/char_lit_as_u8.rs | 4 +- tests/ui/char_lit_as_u8.stderr | 2 - tests/ui/cmp_nan.rs | 4 +- tests/ui/cmp_nan.stderr | 2 - tests/ui/cmp_null.rs | 4 +- tests/ui/cmp_null.stderr | 2 - tests/ui/cmp_owned.rs | 4 +- tests/ui/cmp_owned.stderr | 2 - tests/ui/collapsible_if.rs | 4 +- tests/ui/collapsible_if.stderr | 2 - tests/ui/complex_types.rs | 4 +- tests/ui/complex_types.stderr | 2 - tests/ui/conf_bad_arg.rs | 2 +- tests/ui/conf_bad_arg.stderr | 14 +- tests/ui/conf_bad_toml.rs | 2 +- tests/ui/conf_bad_toml.stderr | 10 +- tests/ui/conf_bad_type.rs | 2 +- tests/ui/conf_bad_type.stderr | 10 +- tests/ui/conf_french_blacklisted_name.rs | 2 +- tests/ui/conf_french_blacklisted_name.stderr | 48 +-- tests/ui/conf_path_non_string.rs | 2 +- tests/ui/conf_path_non_string.stderr | 14 +- tests/ui/conf_unknown_key.rs | 2 +- tests/ui/conf_unknown_key.stderr | 10 +- tests/ui/copies.rs | 3 +- tests/ui/copies.stderr | 18 +- tests/ui/cyclomatic_complexity.rs | 2 +- tests/ui/cyclomatic_complexity.stderr | 2 - tests/ui/cyclomatic_complexity_attr_used.rs | 2 +- tests/ui/cyclomatic_complexity_attr_used.stderr | 2 - tests/ui/deprecated.rs | 4 +- tests/ui/deprecated.stderr | 2 - tests/ui/derive.rs | 4 +- tests/ui/derive.stderr | 2 - tests/ui/diverging_sub_expression.rs | 2 +- tests/ui/diverging_sub_expression.stderr | 2 - tests/ui/dlist.rs | 2 +- tests/ui/dlist.stderr | 2 - tests/ui/doc.rs | 4 +- tests/ui/doc.stderr | 2 - tests/ui/double_neg.rs | 4 +- tests/ui/double_neg.stderr | 2 - tests/ui/double_parens.rs | 4 +- tests/ui/double_parens.stderr | 2 - tests/ui/drop_forget_copy.rs | 4 +- tests/ui/drop_forget_copy.stderr | 2 - tests/ui/drop_forget_ref.rs | 4 +- tests/ui/drop_forget_ref.stderr | 2 - tests/ui/duplicate_underscore_argument.rs | 4 +- tests/ui/duplicate_underscore_argument.stderr | 2 - tests/ui/empty_enum.rs | 4 +- tests/ui/empty_enum.stderr | 2 - tests/ui/entry.rs | 4 +- tests/ui/entry.stderr | 2 - tests/ui/enum_glob_use.rs | 4 +- tests/ui/enum_glob_use.stderr | 2 - tests/ui/enum_variants.rs | 2 +- tests/ui/enum_variants.stderr | 2 - tests/ui/enums_clike.rs | 4 +- tests/ui/enums_clike.stderr | 2 - tests/ui/eq_op.rs | 4 +- tests/ui/eq_op.stderr | 2 - tests/ui/escape_analysis.rs | 2 +- tests/ui/eta.rs | 4 +- tests/ui/eta.stderr | 2 - tests/ui/eval_order_dependence.rs | 4 +- tests/ui/eval_order_dependence.stderr | 2 - tests/ui/filter_methods.rs | 4 +- tests/ui/filter_methods.stderr | 2 - tests/ui/float_cmp.rs | 4 +- tests/ui/float_cmp.stderr | 2 - tests/ui/for_loop.rs | 2 +- tests/ui/for_loop.stderr | 2 - tests/ui/format.rs | 4 +- tests/ui/format.stderr | 2 - tests/ui/formatting.rs | 4 +- tests/ui/formatting.stderr | 2 - tests/ui/functions.rs | 4 +- tests/ui/functions.stderr | 2 - tests/ui/ices.rs | 5 - tests/ui/ices.stderr | 8 - tests/ui/identity_op.rs | 4 +- tests/ui/identity_op.stderr | 2 - tests/ui/if_let_redundant_pattern_matching.rs | 4 +- tests/ui/if_let_redundant_pattern_matching.stderr | 2 - tests/ui/if_not_else.rs | 4 +- tests/ui/if_not_else.stderr | 2 - tests/ui/inconsistent_digit_grouping.rs | 4 +- tests/ui/inconsistent_digit_grouping.stderr | 2 - tests/ui/infinite_iter.rs | 4 +- tests/ui/infinite_iter.stderr | 2 - tests/ui/int_plus_one.stderr | 4 +- tests/ui/invalid_ref.stderr | 4 +- tests/ui/invalid_upcast_comparisons.rs | 4 +- tests/ui/invalid_upcast_comparisons.stderr | 2 - tests/ui/is_unit_expr.rs | 4 +- tests/ui/is_unit_expr.stderr | 2 - tests/ui/item_after_statement.rs | 4 +- tests/ui/item_after_statement.stderr | 2 - tests/ui/large_digit_groups.rs | 4 +- tests/ui/large_digit_groups.stderr | 2 - tests/ui/large_enum_variant.rs | 4 +- tests/ui/large_enum_variant.stderr | 2 - tests/ui/len_zero.rs | 4 +- tests/ui/len_zero.stderr | 2 - tests/ui/let_if_seq.rs | 4 +- tests/ui/let_if_seq.stderr | 2 - tests/ui/let_return.rs | 4 +- tests/ui/let_return.stderr | 2 - tests/ui/let_unit.rs | 4 +- tests/ui/let_unit.stderr | 2 - tests/ui/lifetimes.rs | 4 +- tests/ui/lifetimes.stderr | 2 - tests/ui/lint_pass.rs | 4 +- tests/ui/lint_pass.stderr | 2 - tests/ui/literals.rs | 4 +- tests/ui/literals.stderr | 2 - tests/ui/map_clone.rs | 4 +- tests/ui/map_clone.stderr | 2 - tests/ui/matches.rs | 4 +- tests/ui/matches.stderr | 2 - tests/ui/mem_forget.rs | 4 +- tests/ui/mem_forget.stderr | 2 - tests/ui/methods.rs | 4 +- tests/ui/methods.stderr | 2 - tests/ui/min_max.rs | 4 +- tests/ui/min_max.stderr | 2 - tests/ui/missing-doc.rs | 4 +- tests/ui/missing-doc.stderr | 2 - tests/ui/module_inception.rs | 4 +- tests/ui/module_inception.stderr | 2 - tests/ui/modulo_one.rs | 4 +- tests/ui/modulo_one.stderr | 2 - tests/ui/mut_from_ref.rs | 4 +- tests/ui/mut_from_ref.stderr | 2 - tests/ui/mut_mut.rs | 4 +- tests/ui/mut_mut.stderr | 2 - tests/ui/mut_range_bound.stderr | 4 +- tests/ui/mut_reference.rs | 4 +- tests/ui/mut_reference.stderr | 2 - tests/ui/mutex_atomic.rs | 4 +- tests/ui/mutex_atomic.stderr | 2 - tests/ui/needless_bool.rs | 4 +- tests/ui/needless_bool.stderr | 2 - tests/ui/needless_borrow.rs | 4 +- tests/ui/needless_borrow.stderr | 2 - tests/ui/needless_borrowed_ref.rs | 4 +- tests/ui/needless_borrowed_ref.stderr | 2 - tests/ui/needless_continue.rs | 4 +- tests/ui/needless_continue.stderr | 2 - tests/ui/needless_pass_by_value.rs | 4 +- tests/ui/needless_pass_by_value.stderr | 2 - tests/ui/needless_pass_by_value_proc_macro.rs | 4 +- tests/ui/needless_return.rs | 4 +- tests/ui/needless_return.stderr | 2 - tests/ui/needless_update.rs | 4 +- tests/ui/needless_update.stderr | 2 - tests/ui/neg_multiply.rs | 4 +- tests/ui/neg_multiply.stderr | 2 - tests/ui/never_loop.rs | 4 +- tests/ui/never_loop.stderr | 2 - tests/ui/new_without_default.rs | 2 +- tests/ui/new_without_default.stderr | 2 - tests/ui/no_effect.rs | 2 +- tests/ui/no_effect.stderr | 2 - tests/ui/non_expressive_names.rs | 4 +- tests/ui/non_expressive_names.stderr | 2 - tests/ui/ok_if_let.rs | 4 +- tests/ui/ok_if_let.stderr | 2 - tests/ui/op_ref.rs | 6 +- tests/ui/op_ref.stderr | 2 - tests/ui/open_options.rs | 4 +- tests/ui/open_options.stderr | 2 - tests/ui/overflow_check_conditional.rs | 4 +- tests/ui/overflow_check_conditional.stderr | 2 - tests/ui/panic.rs | 4 +- tests/ui/panic.stderr | 2 - tests/ui/partialeq_ne_impl.rs | 4 +- tests/ui/partialeq_ne_impl.stderr | 2 - tests/ui/patterns.rs | 4 +- tests/ui/patterns.stderr | 2 - tests/ui/precedence.rs | 4 +- tests/ui/precedence.stderr | 2 - tests/ui/print.rs | 4 +- tests/ui/print.stderr | 2 - tests/ui/print_with_newline.rs | 4 +- tests/ui/print_with_newline.stderr | 2 - tests/ui/ptr_arg.rs | 4 +- tests/ui/ptr_arg.stderr | 2 - tests/ui/range.rs | 4 +- tests/ui/range.stderr | 2 - tests/ui/redundant_closure_call.rs | 4 +- tests/ui/redundant_closure_call.stderr | 2 - tests/ui/reference.rs | 4 +- tests/ui/reference.stderr | 2 - tests/ui/regex.rs | 4 +- tests/ui/regex.stderr | 2 - tests/ui/serde.rs | 4 +- tests/ui/serde.stderr | 2 - tests/ui/shadow.rs | 4 +- tests/ui/shadow.stderr | 2 - tests/ui/short_circuit_statement.rs | 4 +- tests/ui/short_circuit_statement.stderr | 2 - tests/ui/should_assert_eq.rs | 4 +- tests/ui/should_assert_eq.stderr | 2 - tests/ui/strings.rs | 4 +- tests/ui/strings.stderr | 2 - tests/ui/stutter.rs | 4 +- tests/ui/stutter.stderr | 2 - tests/ui/swap.rs | 4 +- tests/ui/swap.stderr | 2 - tests/ui/temporary_assignment.rs | 4 +- tests/ui/temporary_assignment.stderr | 2 - tests/ui/toplevel_ref_arg.rs | 4 +- tests/ui/toplevel_ref_arg.stderr | 2 - tests/ui/trailing_zeros.rs | 2 +- tests/ui/trailing_zeros.stderr | 2 - tests/ui/transmute.rs | 4 +- tests/ui/transmute.stderr | 2 - tests/ui/transmute_32bit.rs | 4 +- tests/ui/transmute_64bit.rs | 4 +- tests/ui/transmute_64bit.stderr | 2 - tests/ui/unicode.rs | 4 +- tests/ui/unicode.stderr | 2 - tests/ui/unit_cmp.rs | 4 +- tests/ui/unit_cmp.stderr | 2 - tests/ui/unneeded_field_pattern.rs | 4 +- tests/ui/unneeded_field_pattern.stderr | 2 - tests/ui/unreadable_literal.rs | 4 +- tests/ui/unreadable_literal.stderr | 2 - tests/ui/unsafe_removed_from_name.rs | 4 +- tests/ui/unsafe_removed_from_name.stderr | 2 - tests/ui/unused_io_amount.rs | 4 +- tests/ui/unused_io_amount.stderr | 2 - tests/ui/unused_labels.rs | 4 +- tests/ui/unused_labels.stderr | 2 - tests/ui/unused_lt.rs | 4 +- tests/ui/unused_lt.stderr | 2 - tests/ui/use_self.rs | 4 +- tests/ui/use_self.stderr | 2 - tests/ui/used_underscore_binding.rs | 4 +- tests/ui/used_underscore_binding.stderr | 2 - tests/ui/useless_attribute.rs | 4 +- tests/ui/useless_attribute.stderr | 2 - tests/ui/vec.rs | 4 +- tests/ui/vec.stderr | 2 - tests/ui/while_loop.rs | 4 +- tests/ui/while_loop.stderr | 2 - tests/ui/wrong_self_convention.rs | 4 +- tests/ui/wrong_self_convention.stderr | 2 - tests/ui/zero_div_zero.rs | 4 +- tests/ui/zero_div_zero.stderr | 2 - tests/ui/zero_ptr.rs | 4 +- tests/ui/zero_ptr.stderr | 2 - 314 files changed, 652 insertions(+), 1104 deletions(-) create mode 100644 build.rs create mode 100644 src/driver.rs create mode 100644 tests/conf_whitelisted.rs delete mode 100644 tests/run-pass/conf_whitelisted.rs delete mode 100644 tests/ui-posix/conf_non_existant.rs delete mode 100644 tests/ui-posix/conf_non_existant.stderr delete mode 100755 tests/ui-posix/update-all-references.sh delete mode 100755 tests/ui-posix/update-references.sh delete mode 100644 tests/ui-windows/conf_non_existant.rs delete mode 100644 tests/ui-windows/conf_non_existant.stderr delete mode 100755 tests/ui-windows/update-all-references.sh delete mode 100755 tests/ui-windows/update-references.sh delete mode 100644 tests/ui/ices.rs delete mode 100644 tests/ui/ices.stderr diff --git a/.travis.yml b/.travis.yml index 2664a01ea47..8fe1be2ddfa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ script: - cargo test --features debugging - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy + - cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver - PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy - cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. diff --git a/Cargo.toml b/Cargo.toml index f9c3fd0fd67..3d3b8abaa76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] +build = "build.rs" [badges] travis-ci = { repository = "rust-lang-nursery/rust-clippy" } @@ -29,6 +30,11 @@ name = "cargo-clippy" test = false path = "src/main.rs" +[[bin]] +name = "clippy-driver" +test = false +path = "src/driver.rs" + [dependencies] # begin automatic update clippy_lints = { version = "0.0.165", path = "clippy_lints" } diff --git a/build.rs b/build.rs new file mode 100644 index 00000000000..1c930c1b2c9 --- /dev/null +++ b/build.rs @@ -0,0 +1,8 @@ +use std::env; + +fn main() { + // Forward the profile to the main compilation + println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + // Don't rebuild even if nothing changed + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/driver.rs b/src/driver.rs new file mode 100644 index 00000000000..ab5e90141a9 --- /dev/null +++ b/src/driver.rs @@ -0,0 +1,198 @@ +// error-pattern:yummy +#![feature(box_syntax)] +#![feature(rustc_private)] +#![allow(unknown_lints, missing_docs_in_private_items)] + +extern crate clippy_lints; +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_plugin; +extern crate syntax; + +use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; +use rustc::session::{config, CompileIncomplete, Session}; +use rustc::session::config::{ErrorOutputType, Input}; +use std::path::PathBuf; +use std::process::Command; +use syntax::ast; + +struct ClippyCompilerCalls { + default: RustcDefaultCalls, + run_lints: bool, +} + +impl ClippyCompilerCalls { + fn new(run_lints: bool) -> Self { + Self { + default: RustcDefaultCalls, + run_lints: run_lints, + } + } +} + +impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { + fn early_callback( + &mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + descriptions: &rustc_errors::registry::Registry, + output: ErrorOutputType, + ) -> Compilation { + self.default + .early_callback(matches, sopts, cfg, descriptions, output) + } + fn no_input( + &mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + odir: &Option, + ofile: &Option, + descriptions: &rustc_errors::registry::Registry, + ) -> Option<(Input, Option)> { + self.default + .no_input(matches, sopts, cfg, odir, ofile, descriptions) + } + fn late_callback( + &mut self, + matches: &getopts::Matches, + sess: &Session, + crate_stores: &rustc::middle::cstore::CrateStore, + input: &Input, + odir: &Option, + ofile: &Option, + ) -> Compilation { + self.default + .late_callback(matches, sess, crate_stores, input, odir, ofile) + } + fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { + let mut control = self.default.build_controller(sess, matches); + + if self.run_lints { + let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); + control.after_parse.callback = Box::new(move |state| { + { + let mut registry = rustc_plugin::registry::Registry::new( + state.session, + state + .krate + .as_ref() + .expect( + "at this compilation stage \ + the krate must be parsed", + ) + .span, + ); + registry.args_hidden = Some(Vec::new()); + clippy_lints::register_plugins(&mut registry); + + let rustc_plugin::registry::Registry { + early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + .. + } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } + + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } + + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + } + old(state); + }); + } + + control + } +} + +#[allow(print_stdout)] +fn show_version() { + println!("{}", env!("CARGO_PKG_VERSION")); +} + +pub fn main() { + use std::env; + + if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { + panic!("yummy"); + } + + if std::env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + return; + } + + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { + format!("{}/toolchains/{}", home, toolchain) + } else { + option_env!("SYSROOT") + .map(|s| s.to_owned()) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect( + "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust", + ) + }; + + rustc_driver::in_rustc_thread(|| { + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args[1] == "rustc" { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args.clone().into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + // this check ensures that dependencies are built but not linted and the final + // crate is + // linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") || + orig_args.iter().any(|s| s == "--emit=metadata"); + + if clippy_enabled { + args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + } + + let mut ccc = ClippyCompilerCalls::new(clippy_enabled); + let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None); + if let Err(CompileIncomplete::Errored(_)) = result { + std::process::exit(1); + } + }).expect("rustc_thread failed"); +} diff --git a/src/main.rs b/src/main.rs index f21cd7bd28c..69f416e2092 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,128 +3,12 @@ #![feature(rustc_private)] #![allow(unknown_lints, missing_docs_in_private_items)] -extern crate clippy_lints; -extern crate getopts; -extern crate rustc; -extern crate rustc_driver; -extern crate rustc_errors; -extern crate rustc_plugin; -extern crate syntax; - -use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use rustc::session::{config, CompileIncomplete, Session}; -use rustc::session::config::{ErrorOutputType, Input}; use std::collections::HashMap; -use std::path::PathBuf; -use std::process::{self, Command}; -use syntax::ast; +use std::process; use std::io::{self, Write}; extern crate cargo_metadata; -struct ClippyCompilerCalls { - default: RustcDefaultCalls, - run_lints: bool, -} - -impl ClippyCompilerCalls { - fn new(run_lints: bool) -> Self { - Self { - default: RustcDefaultCalls, - run_lints: run_lints, - } - } -} - -impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { - fn early_callback( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - descriptions: &rustc_errors::registry::Registry, - output: ErrorOutputType, - ) -> Compilation { - self.default - .early_callback(matches, sopts, cfg, descriptions, output) - } - fn no_input( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - odir: &Option, - ofile: &Option, - descriptions: &rustc_errors::registry::Registry, - ) -> Option<(Input, Option)> { - self.default - .no_input(matches, sopts, cfg, odir, ofile, descriptions) - } - fn late_callback( - &mut self, - matches: &getopts::Matches, - sess: &Session, - crate_stores: &rustc::middle::cstore::CrateStore, - input: &Input, - odir: &Option, - ofile: &Option, - ) -> Compilation { - self.default - .late_callback(matches, sess, crate_stores, input, odir, ofile) - } - fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut control = self.default.build_controller(sess, matches); - - if self.run_lints { - let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); - control.after_parse.callback = Box::new(move |state| { - { - let mut registry = rustc_plugin::registry::Registry::new( - state.session, - state - .krate - .as_ref() - .expect( - "at this compilation stage \ - the krate must be parsed", - ) - .span, - ); - registry.args_hidden = Some(Vec::new()); - clippy_lints::register_plugins(&mut registry); - - let rustc_plugin::registry::Registry { - early_lint_passes, - late_lint_passes, - lint_groups, - llvm_passes, - attributes, - .. - } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } - - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); - } - - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - } - old(state); - }); - } - - control - } -} - use std::path::Path; const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. @@ -181,166 +65,105 @@ pub fn main() { return; } - if "clippy" == std::env::args().nth(1).as_ref().expect("cargo-clippy should be called with at least one argument!") { - // this arm is executed on the initial call to `cargo clippy` - - let manifest_path_arg = std::env::args() - .skip(2) - .find(|val| val.starts_with("--manifest-path=")); - - let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) - { - metadata - } else { - let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); - process::exit(101); - }; + let manifest_path_arg = std::env::args() + .skip(2) + .find(|val| val.starts_with("--manifest-path=")); - let manifest_path = manifest_path_arg.map(|arg| { - Path::new(&arg["--manifest-path=".len()..]) - .canonicalize() - .expect("manifest path could not be canonicalized") - }); - - let packages = if std::env::args().any(|a| a == "--all") { - metadata.packages - } else { - let package_index = { - if let Some(manifest_path) = manifest_path { - metadata.packages.iter().position(|package| { + let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) + { + metadata + } else { + let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); + process::exit(101); + }; + + let manifest_path = manifest_path_arg.map(|arg| { + Path::new(&arg["--manifest-path=".len()..]) + .canonicalize() + .expect("manifest path could not be canonicalized") + }); + + let packages = if std::env::args().any(|a| a == "--all") { + metadata.packages + } else { + let package_index = { + if let Some(manifest_path) = manifest_path { + metadata.packages.iter().position(|package| { + let package_manifest_path = Path::new(&package.manifest_path) + .canonicalize() + .expect("package manifest path could not be canonicalized"); + package_manifest_path == manifest_path + }) + } else { + let package_manifest_paths: HashMap<_, _> = metadata + .packages + .iter() + .enumerate() + .map(|(i, package)| { let package_manifest_path = Path::new(&package.manifest_path) + .parent() + .expect("could not find parent directory of package manifest") .canonicalize() - .expect("package manifest path could not be canonicalized"); - package_manifest_path == manifest_path + .expect("package directory cannot be canonicalized"); + (package_manifest_path, i) }) - } else { - let package_manifest_paths: HashMap<_, _> = metadata - .packages - .iter() - .enumerate() - .map(|(i, package)| { - let package_manifest_path = Path::new(&package.manifest_path) - .parent() - .expect("could not find parent directory of package manifest") - .canonicalize() - .expect("package directory cannot be canonicalized"); - (package_manifest_path, i) - }) - .collect(); - - let current_dir = std::env::current_dir() - .expect("could not read current directory") - .canonicalize() - .expect("current directory cannot be canonicalized"); - - let mut current_path: &Path = ¤t_dir; - - // This gets the most-recent parent (the one that takes the fewest `cd ..`s to - // reach). - loop { - if let Some(&package_index) = package_manifest_paths.get(current_path) { - break Some(package_index); - } else { - // We'll never reach the filesystem root, because to get to this point in the - // code - // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to - // unwrap the current path's parent. - current_path = current_path - .parent() - .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display())); - } + .collect(); + + let current_dir = std::env::current_dir() + .expect("could not read current directory") + .canonicalize() + .expect("current directory cannot be canonicalized"); + + let mut current_path: &Path = ¤t_dir; + + // This gets the most-recent parent (the one that takes the fewest `cd ..`s to + // reach). + loop { + if let Some(&package_index) = package_manifest_paths.get(current_path) { + break Some(package_index); + } else { + // We'll never reach the filesystem root, because to get to this point in the + // code + // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to + // unwrap the current path's parent. + current_path = current_path + .parent() + .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display())); } } - }.expect("could not find matching package"); + } + }.expect("could not find matching package"); - vec![metadata.packages.remove(package_index)] - }; + vec![metadata.packages.remove(package_index)] + }; - for package in packages { - let manifest_path = package.manifest_path; + for package in packages { + let manifest_path = package.manifest_path; - for target in package.targets { - let args = std::env::args() - .skip(2) - .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); + for target in package.targets { + let args = std::env::args() + .skip(2) + .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); - let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); - if let Some(first) = target.kind.get(0) { - if target.kind.len() > 1 || first.ends_with("lib") { - if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { - std::process::exit(code); - } - } else if ["bin", "example", "test", "bench"].contains(&&**first) { - if let Err(code) = process( - vec![format!("--{}", first), target.name] - .into_iter() - .chain(args), - ) { - std::process::exit(code); - } + let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); + if let Some(first) = target.kind.get(0) { + if target.kind.len() > 1 || first.ends_with("lib") { + if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { + std::process::exit(code); + } + } else if ["bin", "example", "test", "bench"].contains(&&**first) { + if let Err(code) = process( + vec![format!("--{}", first), target.name] + .into_iter() + .chain(args), + ) { + std::process::exit(code); } - } else { - panic!("badly formatted cargo metadata: target::kind is an empty array"); } - } - } - } else { - // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC_WRAPPER` - // env var set to itself - - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { - format!("{}/toolchains/{}", home, toolchain) - } else { - option_env!("SYSROOT") - .map(|s| s.to_owned()) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect( - "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust", - ) - }; - - rustc_driver::in_rustc_thread(|| { - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programatically, so we ignore this/ - let orig_args: Vec = env::args().skip(1).collect(); - - // this conditional check for the --sysroot flag is there so users can call - // `cargo-clippy` directly - // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() } else { - orig_args.clone().into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; - - // this check ensures that dependencies are built but not linted and the final - // crate is - // linted but not built - let clippy_enabled = orig_args.iter().any(|s| s == "--emit=metadata"); - - if clippy_enabled { - args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + panic!("badly formatted cargo metadata: target::kind is an empty array"); } - - let mut ccc = ClippyCompilerCalls::new(clippy_enabled); - let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None); - if let Err(CompileIncomplete::Errored(_)) = result { - std::process::exit(1); - } - }).expect("rustc_thread failed"); + } } } @@ -362,7 +185,9 @@ where args.push("--cfg".to_owned()); args.push(r#"feature="cargo-clippy""#.to_owned()); - let path = std::env::current_exe().expect("current executable path invalid"); + let path = std::env::current_exe() + .expect("current executable path invalid") + .with_file_name("clippy-driver"); let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 8fa0d440ee7..be8793215dc 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,6 +3,14 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; use std::env::{set_var, var}; +fn clippy_driver_path() -> PathBuf { + if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { + PathBuf::from(path) + } else { + PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver")) + } +} + fn run_mode(dir: &'static str, mode: &'static str) { let mut config = compiletest::Config::default(); @@ -16,12 +24,15 @@ fn run_mode(dir: &'static str, mode: &'static str) { config.mode = cfg_mode; config.build_base = PathBuf::from("target/debug/test_build_base"); config.src_base = PathBuf::from(format!("tests/{}", dir)); + config.rustc_path = clippy_driver_path(); compiletest::run_tests(&config); } fn prepare_env() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); + set_var("CLIPPY_TESTS", "true"); + set_var("RUST_BACKTRACE", "0"); } #[test] @@ -29,8 +40,4 @@ fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); - #[cfg(target_os = "windows")] - run_mode("ui-windows", "ui"); - #[cfg(not(target_os = "windows"))] - run_mode("ui-posix", "ui"); } diff --git a/tests/conf_whitelisted.rs b/tests/conf_whitelisted.rs new file mode 100644 index 00000000000..198bf465bd5 --- /dev/null +++ b/tests/conf_whitelisted.rs @@ -0,0 +1,3 @@ +#![feature(plugin)] +#![plugin(clippy(conf_file="./tests/auxiliary/conf_whitelisted.toml"))] + diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs index 8fb55fa2272..744de9bcf38 100644 --- a/tests/run-pass/associated-constant-ice.rs +++ b/tests/run-pass/associated-constant-ice.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + pub trait Trait { const CONSTANT: u8; diff --git a/tests/run-pass/conf_whitelisted.rs b/tests/run-pass/conf_whitelisted.rs deleted file mode 100644 index 1c82a010b3d..00000000000 --- a/tests/run-pass/conf_whitelisted.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy(conf_file="./tests/auxiliary/conf_whitelisted.toml"))] - -fn main() {} diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index e08a00d26e2..21ed2dbf991 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![deny(clippy)] #![allow(unused_imports)] diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index d53d3a1cc75..780df523511 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(clippy)] fn main() { diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 23a002a5cde..29633982848 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(clippy)] fn main() { } diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index a7ff78eac14..a1e3a6756e9 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![deny(clippy)] fn core() {} diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index a6473b0f909..adc308626b1 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![deny(mut_mut, zero_ptr, cmp_nan)] #![allow(dead_code)] diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 8edb444f936..0ebc1bf3c6c 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![feature(conservative_impl_trait)] #![deny(needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index 91269726172..b185f6dc427 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -1,5 +1,5 @@ #![feature(plugin)] -#![plugin(clippy, clippy_mini_macro_test)] +#![plugin(clippy_mini_macro_test)] #[deny(warnings)] fn main() { diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index 442b01d35f8..d5e343c56c2 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(blacklisted_name)] pub fn foo(bar: *const u8) { diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index fe3cf1ce71f..b8fa7294dcd 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(single_match_else)] fn main() { diff --git a/tests/ui-posix/conf_non_existant.rs b/tests/ui-posix/conf_non_existant.rs deleted file mode 100644 index e287f7e02af..00000000000 --- a/tests/ui-posix/conf_non_existant.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file - -#![feature(plugin)] -#![plugin(clippy(conf_file="./tests/auxiliary/non_existant_conf.toml"))] - -fn main() {} diff --git a/tests/ui-posix/conf_non_existant.stderr b/tests/ui-posix/conf_non_existant.stderr deleted file mode 100644 index 7920bd35589..00000000000 --- a/tests/ui-posix/conf_non_existant.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: error reading Clippy's configuration file: No such file or directory (os error 2) - -error: aborting due to previous error - diff --git a/tests/ui-posix/update-all-references.sh b/tests/ui-posix/update-all-references.sh deleted file mode 100755 index d6aa69c7e8d..00000000000 --- a/tests/ui-posix/update-all-references.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# A script to update the references for all tests. The idea is that -# you do a run, which will generate files in the build directory -# containing the (normalized) actual output of the compiler. You then -# run this script, which will copy those files over. If you find -# yourself manually editing a foo.stderr file, you're doing it wrong. -# -# See all `update-references.sh`, if you just want to update a single test. - -if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" ]]; then - echo "usage: $0" -fi - -BUILD_DIR=$PWD/target/debug/test_build_base -MY_DIR=$(dirname $0) -cd $MY_DIR -find . -name '*.rs' | xargs ./update-references.sh $BUILD_DIR diff --git a/tests/ui-posix/update-references.sh b/tests/ui-posix/update-references.sh deleted file mode 100755 index aa99d35f7aa..00000000000 --- a/tests/ui-posix/update-references.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# A script to update the references for particular tests. The idea is -# that you do a run, which will generate files in the build directory -# containing the (normalized) actual output of the compiler. This -# script will then copy that output and replace the "expected output" -# files. You can then commit the changes. -# -# If you find yourself manually editing a foo.stderr file, you're -# doing it wrong. - -if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then - echo "usage: $0 " - echo "" - echo "For example:" - echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs" -fi - -MYDIR=$(dirname $0) - -BUILD_DIR="$1" -shift - -while [[ "$1" != "" ]]; do - STDERR_NAME="${1/%.rs/.stderr}" - STDOUT_NAME="${1/%.rs/.stdout}" - shift - if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ - ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then - echo updating $MYDIR/$STDOUT_NAME - cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME - fi - if [ -f $BUILD_DIR/$STDERR_NAME ] && \ - ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then - echo updating $MYDIR/$STDERR_NAME - cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME - fi -done - - diff --git a/tests/ui-windows/conf_non_existant.rs b/tests/ui-windows/conf_non_existant.rs deleted file mode 100644 index e287f7e02af..00000000000 --- a/tests/ui-windows/conf_non_existant.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file - -#![feature(plugin)] -#![plugin(clippy(conf_file="./tests/auxiliary/non_existant_conf.toml"))] - -fn main() {} diff --git a/tests/ui-windows/conf_non_existant.stderr b/tests/ui-windows/conf_non_existant.stderr deleted file mode 100644 index f21ae524f5e..00000000000 --- a/tests/ui-windows/conf_non_existant.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: error reading Clippy's configuration file: The system cannot find the file specified. (os error 2) - -error: aborting due to previous error - diff --git a/tests/ui-windows/update-all-references.sh b/tests/ui-windows/update-all-references.sh deleted file mode 100755 index d6aa69c7e8d..00000000000 --- a/tests/ui-windows/update-all-references.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# A script to update the references for all tests. The idea is that -# you do a run, which will generate files in the build directory -# containing the (normalized) actual output of the compiler. You then -# run this script, which will copy those files over. If you find -# yourself manually editing a foo.stderr file, you're doing it wrong. -# -# See all `update-references.sh`, if you just want to update a single test. - -if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" ]]; then - echo "usage: $0" -fi - -BUILD_DIR=$PWD/target/debug/test_build_base -MY_DIR=$(dirname $0) -cd $MY_DIR -find . -name '*.rs' | xargs ./update-references.sh $BUILD_DIR diff --git a/tests/ui-windows/update-references.sh b/tests/ui-windows/update-references.sh deleted file mode 100755 index aa99d35f7aa..00000000000 --- a/tests/ui-windows/update-references.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# A script to update the references for particular tests. The idea is -# that you do a run, which will generate files in the build directory -# containing the (normalized) actual output of the compiler. This -# script will then copy that output and replace the "expected output" -# files. You can then commit the changes. -# -# If you find yourself manually editing a foo.stderr file, you're -# doing it wrong. - -if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then - echo "usage: $0 " - echo "" - echo "For example:" - echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs" -fi - -MYDIR=$(dirname $0) - -BUILD_DIR="$1" -shift - -while [[ "$1" != "" ]]; do - STDERR_NAME="${1/%.rs/.stderr}" - STDOUT_NAME="${1/%.rs/.stdout}" - shift - if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ - ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then - echo updating $MYDIR/$STDOUT_NAME - cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME - fi - if [ -f $BUILD_DIR/$STDERR_NAME ] && \ - ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then - echo updating $MYDIR/$STDERR_NAME - cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME - fi -done - - diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index ad381c6cd49..1f88d94bd2b 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(absurd_extreme_comparisons)] #![allow(unused, eq_op, no_effect, unnecessary_operation, needless_pass_by_value)] diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 2b1e9ad66fe..a4b8839797c 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -143,5 +143,3 @@ error: <-comparison of unit values detected. This will always be false | = note: `-D unit-cmp` implied by `-D warnings` -error: aborting due to 18 previous errors - diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index eb66a633f9e..f2239ecb467 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(approx_constant)] #[allow(unused, shadow_unrelated, similar_names)] diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index dda28433d7a..f102dc5b5dc 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -114,5 +114,3 @@ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it 55 | let my_sq2 = 1.4142; | ^^^^^^ -error: aborting due to 19 previous errors - diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index b281c239f36..7ed71b59707 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(integer_arithmetic, float_arithmetic)] #![allow(unused, shadow_reuse, shadow_unrelated, no_effect, unnecessary_operation)] diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index ad4a02e2190..ea32a005219 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -69,5 +69,3 @@ error: floating-point arithmetic detected 29 | -f; | ^^ -error: aborting due to 11 previous errors - diff --git a/tests/ui/array_indexing.rs b/tests/ui/array_indexing.rs index c38342daf68..faafa9a7a0d 100644 --- a/tests/ui/array_indexing.rs +++ b/tests/ui/array_indexing.rs @@ -1,5 +1,5 @@ #![feature(inclusive_range_syntax, plugin)] -#![plugin(clippy)] + #![warn(indexing_slicing)] #![warn(out_of_bounds_indexing)] diff --git a/tests/ui/array_indexing.stderr b/tests/ui/array_indexing.stderr index d730b012932..dd11247243c 100644 --- a/tests/ui/array_indexing.stderr +++ b/tests/ui/array_indexing.stderr @@ -116,5 +116,3 @@ error: range is out of bounds 44 | &empty[..4]; | ^^^^^^^^^^ -error: aborting due to 19 previous errors - diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index f92f2252114..2b49f2146ba 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(assign_ops)] #[allow(unused_assignments)] diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 2123507e2ef..c1cc5d24426 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -134,5 +134,3 @@ error: manual implementation of an assign operation 40 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` -error: aborting due to 22 previous errors - diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index b5de5b712ff..8d6ef827f52 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[allow(unused_assignments)] #[warn(misrefactored_assign_op)] diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 0ff211259c0..47528c315d4 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -48,5 +48,3 @@ error: variable appears on both sides of an assignment operation 15 | a &= a & 1; | ^^^^^^^^^^ help: replace it with: `a &= 1` -error: aborting due to 8 previous errors - diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 1ff5edcd630..eb27b833ade 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(inline_always, deprecated_semver)] diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index f743399a606..9e4ac3d1283 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -20,5 +20,3 @@ error: the since field must contain a semver-compliant version 30 | #[deprecated(since = "1")] | ^^^^^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index c211b85d7e2..4843b4eba0d 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 40aa585d124..9f2c2d0a2c4 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -92,5 +92,3 @@ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared 55 | x | 1 >= 8; | ^^^^^^^^^^ -error: aborting due to 15 previous errors - diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index dabce55883b..7baeb7bb75c 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code, similar_names, single_match, toplevel_ref_arg, unused_mut, unused_variables)] #![warn(blacklisted_name)] diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 68fbe27a01e..a08a5326894 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -84,5 +84,3 @@ error: use of a blacklisted/placeholder name `baz` 35 | if let Some(ref mut baz) = Some(42) {} | ^^^ -error: aborting due to 14 previous errors - diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index 08e510317d9..9e65a127af2 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(block_in_if_condition_expr)] #![warn(block_in_if_condition_stmt)] diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index 4b7d12598ec..86a289c19a8 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -50,5 +50,3 @@ error: this boolean expression can be simplified | = note: `-D nonminimal-bool` implied by `-D warnings` -error: aborting due to 5 previous errors - diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 9b32ed7304b..f05b9894fea 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(bool_comparison)] fn main() { diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 4436980bc11..e5e062e0246 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -24,5 +24,3 @@ error: equality checks against false can be replaced by a negation 10 | if false == x { "yes" } else { "no" }; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` -error: aborting due to 4 previous errors - diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index ac60bf5e345..0434285a523 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(nonminimal_bool, logic_bug)] #[allow(unused, many_single_char_names)] diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index a76eb7a5cc0..0311e95a4f1 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -130,5 +130,3 @@ help: try 39 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors - diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index b5543da6e35..394b810ed86 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![deny(borrowed_box)] #![allow(blacklisted_name)] diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 2cf0ea79626..74134f4f2b1 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -28,5 +28,3 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` 22 | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` -error: aborting due to 4 previous errors - diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index f8c5a80c59d..75b3b62643e 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(boxed_local, needless_pass_by_value)] diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index 254d0771386..c1badd0dc9b 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -7,5 +7,3 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` = note: `-D box-vec` implied by `-D warnings` = help: `Vec` is already on the heap, `Box>` makes an extra allocation. -error: aborting due to previous error - diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index a3609cfe104..4c4f5cbd3fe 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(builtin_type_shadow)] fn foo(a: u32) -> u32 { diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index eb4c73b65c6..058813356cd 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -17,5 +17,3 @@ error[E0308]: mismatched types = note: expected type `u32` found type `{integer}` -error: aborting due to 2 previous errors - diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 8fc27c49f34..fc94667d968 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[deny(naive_bytecount)] fn main() { diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 307edecfde1..c4f6b65a21e 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -22,5 +22,3 @@ error: You appear to be counting bytes the naive way 22 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` -error: aborting due to 3 previous errors - diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 82427c128e4..1ad4630989d 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)] #[allow(no_effect, unnecessary_operation)] diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 8787083b429..5e7ed6fae99 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -460,5 +460,3 @@ error: casting to the same type is unnecessary (`bool` -> `bool`) 88 | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 75 previous errors - diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index 6f07b60fb10..c69181c7649 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(char_lit_as_u8)] #![allow(unused_variables)] diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index fcf038fe002..4e7c1866a9a 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -8,5 +8,3 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so cas = help: Consider using a byte literal instead: b'a' -error: aborting due to previous error - diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index e8639273485..71dfdd43da7 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(cmp_nan)] #[allow(float_cmp, no_effect, unnecessary_operation)] diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 46f3d3d57e0..9ea1a29d29d 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -72,5 +72,3 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead 21 | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors - diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 47ecacd5558..0f463bcfc30 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(cmp_null)] #![allow(unused_mut)] diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 481a4d0f942..51c0ceea4b1 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -12,5 +12,3 @@ error: Comparing with null is better expressed by the .is_null() method 16 | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 4b9b6434ebc..36d3140d246 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(cmp_owned)] #[allow(unnecessary_operation)] diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index d40fb4b8add..e6996244664 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -36,5 +36,3 @@ error: this creates an owned instance just for comparison 30 | self.to_owned() == *other | ^^^^^^^^^^^^^^^ try calling implementing the comparison without allocating -error: aborting due to 6 previous errors - diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index d03a1ee1980..3c5c38525fe 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(collapsible_if)] fn main() { diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 940749d3f40..e726a36282b 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -252,5 +252,3 @@ help: try 112 | } | -error: aborting due to 13 previous errors - diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index 481a6a82cf5..7719a7a8632 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(unused, needless_pass_by_value)] #![feature(associated_type_defaults)] diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 829a22c233f..8ce63652f0b 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -90,5 +90,3 @@ error: very complex type used. Consider factoring parts into `type` definitions 40 | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors - diff --git a/tests/ui/conf_bad_arg.rs b/tests/ui/conf_bad_arg.rs index 68b902719f6..b988fdb1385 100644 --- a/tests/ui/conf_bad_arg.rs +++ b/tests/ui/conf_bad_arg.rs @@ -1,6 +1,6 @@ // error-pattern: `conf_file` must be a named value -#![feature(plugin)] + #![plugin(clippy(conf_file))] fn main() {} diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index 92b3c82d458..d91729039b1 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -1,14 +1,8 @@ -error: `conf_file` must be a named value - --> $DIR/conf_bad_arg.rs:4:18 +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_bad_arg.rs:4:1 | 4 | #![plugin(clippy(conf_file))] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Clippy will use default configuration - --> $DIR/conf_bad_arg.rs:4:18 - | -4 | #![plugin(clippy(conf_file))] - | ^^^^^^^^^ - -error: aborting due to previous error + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_bad_toml.rs b/tests/ui/conf_bad_toml.rs index 22cbfca759e..4de2cf6ae73 100644 --- a/tests/ui/conf_bad_toml.rs +++ b/tests/ui/conf_bad_toml.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file -#![feature(plugin)] + #![plugin(clippy(conf_file="./tests/ui/conf_bad_toml.toml"))] fn main() {} diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index 8ee392f8924..5ddf8c14f70 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -1,4 +1,8 @@ -error: error reading Clippy's configuration file: expected an equals, found an identifier at line 1 - -error: aborting due to previous error +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_bad_toml.rs:4:1 + | +4 | #![plugin(clippy(conf_file="./$DIR/conf_bad_toml.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_bad_type.rs b/tests/ui/conf_bad_type.rs index d5cca60a301..4cb21b91582 100644 --- a/tests/ui/conf_bad_type.rs +++ b/tests/ui/conf_bad_type.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` -#![feature(plugin)] + #![plugin(clippy(conf_file="./tests/ui/conf_bad_type.toml"))] fn main() {} diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 5cb4d05afef..961df381c99 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -1,4 +1,8 @@ -error: error reading Clippy's configuration file: invalid type: integer `42`, expected a sequence - -error: aborting due to previous error +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_bad_type.rs:4:1 + | +4 | #![plugin(clippy(conf_file="./$DIR/conf_bad_type.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_french_blacklisted_name.rs b/tests/ui/conf_french_blacklisted_name.rs index 5bf1e896f5d..9f22ff659f2 100644 --- a/tests/ui/conf_french_blacklisted_name.rs +++ b/tests/ui/conf_french_blacklisted_name.rs @@ -1,4 +1,4 @@ -#![feature(plugin)] + #![plugin(clippy(conf_file="./tests/auxiliary/conf_french_blacklisted_name.toml"))] #![allow(dead_code)] diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index b2b0f26b140..c98adb6029f 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -1,46 +1,8 @@ -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:9:9 +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_french_blacklisted_name.rs:2:1 | -9 | fn test(toto: ()) {} - | ^^^^ +2 | #![plugin(clippy(conf_file="./tests/auxiliary/conf_french_blacklisted_name.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D blacklisted-name` implied by `-D warnings` - -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:12:9 - | -12 | let toto = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:13:9 - | -13 | let tata = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:14:9 - | -14 | let titi = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:20:10 - | -20 | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:20:21 - | -20 | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:20:28 - | -20 | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: aborting due to 7 previous errors + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_path_non_string.rs b/tests/ui/conf_path_non_string.rs index f6f40513be8..8d1f01358fc 100644 --- a/tests/ui/conf_path_non_string.rs +++ b/tests/ui/conf_path_non_string.rs @@ -1,5 +1,5 @@ #![feature(attr_literals)] -#![feature(plugin)] + #![plugin(clippy(conf_file=42))] fn main() {} diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index 3bf53f10cce..4b15b5d0e17 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -1,14 +1,8 @@ -error: `conf_file` value must be a string - --> $DIR/conf_path_non_string.rs:3:28 +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_path_non_string.rs:3:1 | 3 | #![plugin(clippy(conf_file=42))] - | ^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Clippy will use default configuration - --> $DIR/conf_path_non_string.rs:3:28 - | -3 | #![plugin(clippy(conf_file=42))] - | ^^ - -error: aborting due to previous error + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_unknown_key.rs b/tests/ui/conf_unknown_key.rs index b5c1b240e4d..aec2c883367 100644 --- a/tests/ui/conf_unknown_key.rs +++ b/tests/ui/conf_unknown_key.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file: unknown key `foobar` -#![feature(plugin)] + #![plugin(clippy(conf_file="./tests/auxiliary/conf_unknown_key.toml"))] fn main() {} diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index 8de3cd93370..9fc7dbea563 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -1,4 +1,8 @@ -error: error reading Clippy's configuration file: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `third-party` - -error: aborting due to previous error +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/conf_unknown_key.rs:4:1 + | +4 | #![plugin(clippy(conf_file="./tests/auxiliary/conf_unknown_key.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 652afac6c68..4c4050c014f 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,5 +1,4 @@ -#![feature(plugin, dotdoteq_in_patterns, inclusive_range_syntax)] -#![plugin(clippy)] +#![feature(dotdoteq_in_patterns, inclusive_range_syntax)] #![allow(dead_code, no_effect, unnecessary_operation)] #![allow(let_and_return)] diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index bf9e8ed577d..4457e2b7d73 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,11 +1,11 @@ error: This else block is redundant. - --> $DIR/copies.rs:121:20 + --> $DIR/copies.rs:120:20 | -121 | } else { +120 | } else { | ____________________^ -122 | | continue; -123 | | } +121 | | continue; +122 | | } | |_____________^ | = note: `-D needless-continue` implied by `-D warnings` @@ -18,12 +18,12 @@ error: This else block is redundant. error: This else block is redundant. - --> $DIR/copies.rs:131:20 + --> $DIR/copies.rs:130:20 | -131 | } else { +130 | } else { | ____________________^ -132 | | continue; -133 | | } +131 | | continue; +132 | | } | |_____________^ | = help: Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so: @@ -33,5 +33,3 @@ error: This else block is redundant. } -error: aborting due to 2 previous errors - diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index a236d6e869f..0f5726e1ad7 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,5 +1,5 @@ #![feature(plugin, custom_attribute)] -#![plugin(clippy)] + #![allow(clippy)] #![warn(cyclomatic_complexity)] #![allow(unused)] diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index 43676762d6c..62fd5313ccb 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -269,5 +269,3 @@ error: the function has a cyclomatic complexity of 8 | = help: you could split it up into multiple smaller functions -error: aborting due to 20 previous errors - diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index 48ae12bc2d8..5284d60a524 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,5 +1,5 @@ #![feature(plugin, custom_attribute)] -#![plugin(clippy)] + #![warn(cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index e671b34393b..a9cefe93e32 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -13,5 +13,3 @@ error: the function has a cyclomatic complexity of 3 = note: `-D cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions -error: aborting due to previous error - diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index e0c856e3d7c..0598e174e50 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(str_to_string)] diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 7d5d594cfa1..4255959675a 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -24,5 +24,3 @@ error: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been 10 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 11cade0dc8e..6440f73f31b 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![feature(untagged_unions)] diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index ffeed948ba5..f336dc3a8e1 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -106,5 +106,3 @@ note: consider deriving `Clone` or removing `Copy` 87 | | } | |_^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 7ae531cc6f2..d2aea93a77d 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,5 +1,5 @@ #![feature(plugin, never_type)] -#![plugin(clippy)] + #![warn(diverging_sub_expression)] #![allow(match_same_arms, logic_bug)] diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 0d7b1ca6fd6..b39d1ae07e5 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -36,5 +36,3 @@ error: sub-expression diverges 37 | _ => true || break, | ^^^^^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 5e4e1cb2a64..217a564742c 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -1,7 +1,7 @@ #![feature(plugin, alloc)] #![feature(associated_type_defaults)] -#![plugin(clippy)] + #![warn(clippy)] #![allow(dead_code, needless_pass_by_value)] diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index de0422e17ed..95872c02994 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -47,5 +47,3 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct | = help: a VecDeque might work -error: aborting due to 6 previous errors - diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 70009d76f5d..45e25409b12 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -1,7 +1,7 @@ //! This file tests for the DOC_MARKDOWN lint -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] #![warn(doc_markdown)] diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index f38678e89aa..fc036d01b86 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -180,5 +180,3 @@ error: you should put bare URLs between `<`/`>` or make a proper Markdown link 168 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 30 previous errors - diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index d462e6f4ab6..641e334fd16 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(double_neg)] fn main() { diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index fd4da8820a2..8c64eb37e15 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -6,5 +6,3 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usual | = note: `-D double-neg` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index 8b57619edb0..19d17732867 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(double_parens)] #![allow(dead_code)] diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index a77b08528c4..ab3e844d7a7 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -30,5 +30,3 @@ error: Consider removing unnecessary double parentheses 32 | (()) | ^^^^ -error: aborting due to 5 previous errors - diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 4e48a89b659..9fef06b0ede 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(drop_copy, forget_copy)] #![allow(toplevel_ref_arg, drop_ref, forget_ref, unused_mut)] diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index 3ea7bf9735a..f399c5a125f 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -72,5 +72,3 @@ note: argument has type SomeStruct 42 | forget(s4); | ^^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index 48811f03b6f..e8ab6a0d5d1 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(drop_ref, forget_ref)] #![allow(toplevel_ref_arg, similar_names, needless_pass_by_value)] diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 1654fdd2861..6058b89c70f 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -216,5 +216,3 @@ note: argument has type &SomeStruct 59 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ -error: aborting due to 18 previous errors - diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index 893cc43f364..df00f56aa62 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(duplicate_underscore_argument)] #[allow(dead_code, unused)] diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index c926f57f154..de9e6f1e056 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -6,5 +6,3 @@ error: `darth` already exists, having another argument having almost the same na | = note: `-D duplicate-underscore-argument` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index 98138add0de..c6e6946de86 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] #![warn(empty_enum)] diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index ca377cee822..a0d491b6f96 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -11,5 +11,3 @@ help: consider using the uninhabited type `!` or a wrapper around it 7 | enum Empty {} | ^^^^^^^^^^^^^ -error: aborting due to previous error - diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 1ae39689d8b..ccbc7038f13 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused, needless_pass_by_value)] #![warn(map_entry)] diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 09c4a882280..e60c158d7c0 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -42,5 +42,3 @@ error: usage of `contains_key` followed by `insert` on a `BTreeMap` 37 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` -error: aborting due to 7 previous errors - diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 514ef47c566..76d0d29bb53 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy, clippy_pedantic)] #![allow(unused_imports, dead_code, missing_docs_in_private_items)] diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 2d53618c1b1..1e0fffb9ac4 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -12,5 +12,3 @@ error: don't use glob imports for enum variants 12 | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index a12eb3fd344..9901baf9e12 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,5 +1,5 @@ #![feature(plugin, non_ascii_idents)] -#![plugin(clippy)] + #![warn(clippy, pub_enum_variant_names)] enum FakeCallType { diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index e33e29ec78e..7e2716b8ea2 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -97,5 +97,3 @@ error: All variants have the same prefix: `With` = note: `-D pub-enum-variant-names` implied by `-D warnings` = help: remove the prefixes and use full paths to the variants instead of glob imports -error: aborting due to 10 previous errors - diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index fd2240353dd..618603683e8 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -1,6 +1,6 @@ // ignore-x86 -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(unused)] diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index d6a137c6fe4..e0555bb0239 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -48,5 +48,3 @@ error: Clike enum variant discriminant is not portable to 32-bit targets 37 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors - diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 12d62042dca..89d85d1b3e9 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(eq_op)] #[allow(identity_op, double_parens, many_single_char_names)] diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 46c0ac108cd..914a85719d0 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -204,5 +204,3 @@ error: taken reference of right operand | = note: `-D op-ref` implied by `-D warnings` -error: aborting due to 33 previous errors - diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index b4793198b7a..b99534d05e1 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -1,5 +1,5 @@ #![feature(plugin, box_syntax)] -#![plugin(clippy)] + #![allow(warnings, clippy)] #![warn(boxed_local)] diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 46ac0ec8c73..0ff02a0b2cc 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value)] #![warn(redundant_closure)] diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 5dca265c2a4..34a6217cd70 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -32,5 +32,3 @@ error: redundant closure found 18 | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` -error: aborting due to 5 previous errors - diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index 853c61af2f2..e7ccb190d2c 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(eval_order_dependence)] #[allow(unused_assignments, unused_variables, many_single_char_names, no_effect, dead_code, blacklisted_name)] diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index 2e01a167c01..e9bdc3b51d9 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -47,5 +47,3 @@ note: whether read occurs before this write depends on evaluation order 21 | x += { x = 20; 2 }; | ^^^^^^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index 77ebe9d12dd..29230c48ea3 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy, clippy_pedantic)] #![allow(missing_docs_in_private_items)] diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index cec03a47bfd..8f1853c3952 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -36,5 +36,3 @@ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly e 25 | | .map(|x| x.checked_mul(2)) | |__________________________________________________________^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index f3f66f3c9c5..9dd9ea9b04d 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(float_cmp)] #![allow(unused, no_effect, unnecessary_operation, cast_lossless)] diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index a764403d039..d2903f501f5 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -95,5 +95,3 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 57 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors - diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 95d15776a36..083e6f9a6e5 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,5 +1,5 @@ #![feature(plugin, inclusive_range_syntax)] -#![plugin(clippy)] + use std::collections::*; use std::rc::Rc; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 09c4deb492a..620c32b6ab5 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -586,5 +586,3 @@ error: it looks like you're manually copying between slices 549 | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 59 previous errors - diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 377bcc7ca8d..e9379d0a05b 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(useless_format)] fn main() { diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index d2c9f393831..67d97f295d8 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -18,5 +18,3 @@ error: useless use of `format!` 15 | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 7e2691776bf..20b1c1655a7 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(unused_variables)] diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 266de262ea0..d121929d0c2 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -86,5 +86,3 @@ error: possibly missing a comma here | = note: to remove this lint, add a comma or write the expr in a single line -error: aborting due to 10 previous errors - diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 13d116542ac..5688c471d86 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(dead_code)] diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 0a97748954f..c8b4db35245 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -75,5 +75,3 @@ error: this public function dereferences a raw pointer but is not marked `unsafe 63 | unsafe { std::ptr::read(p) }; | ^ -error: aborting due to 12 previous errors - diff --git a/tests/ui/ices.rs b/tests/ui/ices.rs deleted file mode 100644 index 9c5129654e4..00000000000 --- a/tests/ui/ices.rs +++ /dev/null @@ -1,5 +0,0 @@ - -// this used to ICE -fubar!(); - -fn main() {} diff --git a/tests/ui/ices.stderr b/tests/ui/ices.stderr deleted file mode 100644 index cadd7cd417d..00000000000 --- a/tests/ui/ices.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot find macro `fubar!` in this scope - --> $DIR/ices.rs:3:1 - | -3 | fubar!(); - | ^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index e6ebb972643..b474344977c 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + const ONE : i64 = 1; const NEG_ONE : i64 = -1; diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 94b9b727a51..30367c989ec 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -42,5 +42,3 @@ error: the operation is ineffective. Consider reducing it to `x` 29 | -1 & x; | ^^^^^^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs index 6444bd8ef68..0963caa62e2 100644 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ b/tests/ui/if_let_redundant_pattern_matching.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![warn(if_let_redundant_pattern_matching)] diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index e7bfd0275d8..b15d17e372e 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -24,5 +24,3 @@ error: redundant pattern matching, consider using `is_some()` 17 | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` -error: aborting due to 4 previous errors - diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index 7b838560ed1..9436af70cb8 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![warn(if_not_else)] diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index b920ef3b625..f9462f422ea 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -23,5 +23,3 @@ error: Unnecessary `!=` operation | = help: change to `==` and swap the blocks of the if/else -error: aborting due to 2 previous errors - diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index 06e8996deb7..ed6dc06edb1 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(inconsistent_digit_grouping)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 12d9e3cf0fd..2725d5f4ef7 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -39,5 +39,3 @@ error: digits grouped inconsistently by underscores | = help: consider: 1.234_567_8_f32 -error: aborting due to 5 previous errors - diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index deb5c5edd8c..08596ff2016 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] +#![feature(iterator_for_each)] + use std::iter::repeat; fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index f79db778488..87b7ca49322 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -96,5 +96,3 @@ error: possible infinite iteration detected 30 | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors - diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 6f69ba9d714..92b012bd104 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,3 +1,5 @@ +warning: running cargo clippy on a crate that also imports the clippy plugin + error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:10:5 | @@ -43,5 +45,3 @@ help: change `>= y + 1` to `> y` as shown 14 | y < x; | ^^^^^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 420fed01744..18064c91a01 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,3 +1,5 @@ +warning: running cargo clippy on a crate that also imports the clippy plugin + error: reference to zeroed memory --> $DIR/invalid_ref.rs:27:24 | @@ -47,5 +49,3 @@ error: reference to uninitialized memory | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html -error: aborting due to 6 previous errors - diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 8d8e7bd8de1..5bf0bfdcb98 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(invalid_upcast_comparisons)] #![allow(unused, eq_op, no_effect, unnecessary_operation, cast_lossless)] diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index eb46802899e..3f11c373074 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -162,5 +162,3 @@ error: because of the numeric bounds on `u8` prior to casting, this expression i 78 | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 27 previous errors - diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 164e391ff24..24a2587dc53 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(unit_expr)] #[allow(unused_variables)] diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index 2d9fcfff74f..5524f866488 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -51,5 +51,3 @@ note: Consider removing the trailing semicolon 42 | x; | ^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index e3e4a4c7578..710a1adca56 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(items_after_statements)] fn ok() { diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index ec1296caf83..e98e7ee129d 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -12,5 +12,3 @@ error: adding items after statements is confusing, since items exist from the st 17 | fn foo() { println!("foo"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 65bcdc7435e..5d0fb11dbea 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(large_digit_groups)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 6fc285274a0..db49ded1d8a 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -47,5 +47,3 @@ error: digit groups should be smaller | = help: consider: 123_456.123_456_f32 -error: aborting due to 6 previous errors - diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index 31a7760aa19..aaf3e2924b3 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index bb889087095..899a84edeaa 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -68,5 +68,3 @@ help: consider boxing the large fields to reduce the total size of the enum 49 | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 9c66d5a8148..aba1dd3055a 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(len_without_is_empty, len_zero)] #![allow(dead_code, unused)] diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 6e3cf1b3ca1..d23a972dddc 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -94,5 +94,3 @@ error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_e 191 | | } | |_^ -error: aborting due to 12 previous errors - diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 2d3ab7da996..564a67d2c8e 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused_variables, unused_assignments, similar_names, blacklisted_name)] #![warn(useless_let_if_seq)] diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index b912373f95c..39686a9dd07 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -46,5 +46,3 @@ error: `if _ { .. } else { .. }` is an expression | = note: you might not need `mut` at all -error: aborting due to 4 previous errors - diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index 6aab70dbd8a..1083603b2d6 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] #![warn(let_and_return)] diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index 459b2eafa26..b38c9ab2e91 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -23,5 +23,3 @@ note: this expression can be directly returned 15 | let x = 5; | ^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index d07cf8ede2f..032dc85f2cd 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(let_unit_value)] #![allow(unused_variables)] diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index da579ec80f3..196afc0570c 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -12,5 +12,3 @@ error: this let-binding has unit value. Consider omitting `let _a =` 18 | let _a = (); | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 5f3c3604d80..dce9c23da68 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(needless_lifetimes, unused_lifetimes)] #![allow(dead_code, needless_pass_by_value)] diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 23b353d13d2..744e1ce21ec 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -86,5 +86,3 @@ error: explicit lifetimes given in parameter types where they could be elided 120 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors - diff --git a/tests/ui/lint_pass.rs b/tests/ui/lint_pass.rs index 5ecbeb7f11a..1990e137e67 100644 --- a/tests/ui/lint_pass.rs +++ b/tests/ui/lint_pass.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] + #![feature(rustc_private)] -#![plugin(clippy)] + #![warn(lint_without_lint_pass)] diff --git a/tests/ui/lint_pass.stderr b/tests/ui/lint_pass.stderr index 2f9a6813b96..66f2d62ed24 100644 --- a/tests/ui/lint_pass.stderr +++ b/tests/ui/lint_pass.stderr @@ -6,5 +6,3 @@ error: the lint `MISSING_LINT` is not added to any `LintPass` | = note: `-D lint-without-lint-pass` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index e8105a74b5c..c11adc0b090 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(mixed_case_hex_literals)] #![warn(unseparated_literal_suffix)] #![warn(zero_prefixed_literal)] diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 17210b6b275..82c651e6290 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -87,5 +87,3 @@ help: if you mean to use an octal constant, use `0o` 30 | let fail8 = 0o123; | ^^^^^ -error: aborting due to 11 previous errors - diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 81e298390f5..f11d21d2dfa 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(map_clone)] #![allow(clone_on_copy, unused)] diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index c29f3791851..272b868a278 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -98,5 +98,3 @@ error: you seem to be using .map() to clone the contents of an Option, consider = help: try x.as_ref().cloned() -error: aborting due to 11 previous errors - diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index be1ca72aece..f97038ca1f0 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,7 +1,7 @@ -#![feature(plugin)] + #![feature(exclusive_range_pattern)] -#![plugin(clippy)] + #![warn(clippy)] #![allow(unused, if_let_redundant_pattern_matching)] #![warn(single_match_else)] diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 2f55428cca7..1c2452c46ce 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -392,5 +392,3 @@ note: consider refactoring into `Ok(3) | Ok(_)` | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to 33 previous errors - diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 7854a373968..991a402e207 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + use std::sync::Arc; diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 6e7a44694e1..c79afa829fe 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -18,5 +18,3 @@ error: usage of mem::forget on Drop type 24 | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 48132cc662c..08ff4771420 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] + #![feature(const_fn)] -#![plugin(clippy)] + #![warn(clippy, clippy_pedantic)] #![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive, missing_docs_in_private_items)] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 7f3d505a3cd..c5fab711fe1 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -836,5 +836,3 @@ error: you should use the `ends_with` method 578 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` -error: aborting due to 123 previous errors - diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 9a077eae4d9..1199206e42c 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] use std::cmp::{min, max}; diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index de4c4e16fa0..e9225f93b5e 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -42,5 +42,3 @@ error: this min/max combination leads to constant result 30 | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index 596cec886f4..cbd6439d47e 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -11,8 +11,8 @@ * except according to those terms. */ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index e25edb64181..55eab4f5d69 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -270,5 +270,3 @@ error: missing documentation for a function 202 | fn main() {} | ^^^^^^^^^^^^ -error: aborting due to 40 previous errors - diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index e934c64023b..77bd446c569 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(module_inception)] mod foo { diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index c9d3319db1b..cb6ea951a17 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -16,5 +16,3 @@ error: module has the same name as its containing module 14 | | } | |_____^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index cda3f190f1e..847ea1d9ab6 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(modulo_one)] #![allow(no_effect, unnecessary_operation)] diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index ccfca7154e0..48cfe6c38cc 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -6,5 +6,3 @@ error: any number modulo 1 will be 0 | = note: `-D modulo-one` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 55498bad759..9e757155260 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] #![warn(mut_from_ref)] diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index a7cbc0b7a09..eacda70ce07 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -59,5 +59,3 @@ note: immutable borrow here 32 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ -error: aborting due to 5 previous errors - diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 766276bc417..54176cd6d55 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused, no_effect, unnecessary_operation)] #![warn(mut_mut)] diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 7a7bb840ba9..31f9178aa27 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -81,5 +81,3 @@ error: generally you want to avoid `&mut &mut _` if possible 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ -error: aborting due to 13 previous errors - diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index d7be7ae1e6f..f516ec9d95e 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,3 +1,5 @@ +warning: running cargo clippy on a crate that also imports the clippy plugin + error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:18:21 | @@ -30,5 +32,3 @@ error: attempt to mutate range bound within loop; note that the range of the loo 40 | let n = &mut m; // warning | ^ -error: aborting due to 5 previous errors - diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index d746fc5e529..ac40bf2a186 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused_variables)] diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 73df19bf158..6708bca8b2e 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -18,5 +18,3 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable 28 | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index b84ece497eb..96502738456 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![warn(mutex_integer)] diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 354f9891c17..d46c713164a 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -44,5 +44,3 @@ error: Consider using an AtomicIsize instead of a Mutex here. If you just want t 16 | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index bd44332a170..1213539c827 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(needless_bool)] #[allow(if_same_then_else)] diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index 63e0632445f..a25b34bfaaf 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -66,5 +66,3 @@ error: this if-then-else expression returns a bool literal 50 | if x && y { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !(x && y)` -error: aborting due to 11 previous errors - diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 23d935e7df8..78c1a125c94 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + fn x(y: &i32) -> i32 { *y diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index fde38508b32..16962bb48f1 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -38,5 +38,3 @@ error: this pattern creates a reference to a reference 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` -error: aborting due to 6 previous errors - diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 4e9986561bc..75ffa211180 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(needless_borrowed_reference)] #[allow(unused_variables)] diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 2a8cf4348d3..c85bf9f5a7c 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -24,5 +24,3 @@ error: this pattern takes a reference on something that is being de-referenced 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` -error: aborting due to 4 previous errors - diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 6710867077d..3574b0fb3fd 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + macro_rules! zero { ($x:expr) => ($x == 0); diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 3e0368892a4..f63f120fcc7 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -55,5 +55,3 @@ error: There is no need for an explicit `else` block for this `if` expression println!("Jabber"); ... -error: aborting due to 2 previous errors - diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index ea97e875ff7..6218bfb0920 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(needless_pass_by_value)] #![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names)] diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 02293c9cb3c..c081574127a 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -56,5 +56,3 @@ help: consider taking a reference instead 56 | let Wrapper(_) = *y; // still not moved | -error: aborting due to 7 previous errors - diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 0d5bc4172d8..652e11fee9d 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![crate_type = "proc-macro"] #![warn(needless_pass_by_value)] diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 403e5b8342e..4739ded7b7e 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(needless_return)] diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 42dc6e6594c..68c2654c863 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -48,5 +48,3 @@ error: unneeded return statement 39 | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` -error: aborting due to 8 previous errors - diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 99876121ae7..35d5730dda1 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(needless_update)] #![allow(no_effect)] diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index 3e509870d00..978fd8e625b 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -6,5 +6,3 @@ error: struct update has no effect, all the fields in the struct have already be | = note: `-D needless-update` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 75dc7c381fd..367d2d5edfb 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(neg_multiply)] #![allow(no_effect, unnecessary_operation)] diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 1d52ba16eae..6ed31d384a0 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -12,5 +12,3 @@ error: Negation by multiplying with -1 32 | -1 * x; | ^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index ff0126704b5..4866db1a541 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(single_match, unused_assignments, unused_variables)] fn test1() { diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index dace2b7e261..1ecdb5030f9 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -68,5 +68,3 @@ error: this loop never actually loops 103 | | } | |_____^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index a10db135c5e..9fd0fea137c 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,5 +1,5 @@ #![feature(plugin, const_fn)] -#![plugin(clippy)] + #![allow(dead_code)] #![warn(new_without_default, new_without_default_derive)] diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 91e437a6eb5..0ced183b1e0 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -38,5 +38,3 @@ help: try this 69 | ... -error: aborting due to 3 previous errors - diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 5c3a1a041c2..ba7826d653e 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,5 +1,5 @@ #![feature(plugin, box_syntax, inclusive_range_syntax)] -#![plugin(clippy)] + #![warn(no_effect, unnecessary_operation)] #![allow(dead_code)] diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index b6db8e7498e..43e7fbb3609 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -266,5 +266,3 @@ error: statement can be reduced 83 | {get_number()}; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` -error: aborting due to 44 previous errors - diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index f32dad2080f..9eb3e5a82a7 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy,similar_names)] #![allow(unused)] diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 780d7d8aec9..014d4599271 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -129,5 +129,3 @@ error: 5th binding whose name is just one char 129 | e => panic!(), | ^ -error: aborting due to 11 previous errors - diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index dda38fec287..fdc01bcc7bc 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(if_let_some_result)] diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index e1371d924eb..b696672d2fd 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -11,5 +11,3 @@ error: Matching on `Some` with `ok()` is redundant = note: `-D if-let-some-result` implied by `-D warnings` = help: Consider matching on `Ok(y)` and removing the call to `ok` instead -error: aborting due to previous error - diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index 315e6535ef6..9eb697571b6 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused_variables, blacklisted_name)] @@ -21,4 +21,4 @@ fn main() { if b < &a { println!("OK"); } -} \ No newline at end of file +} diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 715c7378e0c..dbe53933fd5 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -10,5 +10,3 @@ help: use the values directly 13 | let foo = 5 - 6; | ^ -error: aborting due to previous error - diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index c409aa564f8..514808d41f1 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + use std::fs::OpenOptions; #[allow(unused_must_use)] diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index f0d41904152..2f4070c2868 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -42,5 +42,3 @@ error: the method "truncate" is called more than once 15 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors - diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index a669f741f29..889c339c8fd 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(many_single_char_names)] #![warn(overflow_check_conditional)] diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 8a80dbedaeb..9f23e96c065 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -48,5 +48,3 @@ error: You are trying to use classic C underflow conditions that will fail in Ru 32 | if a < a - b { | ^^^^^^^^^ -error: aborting due to 8 previous errors - diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs index 03d3c3dc2d9..f621a5f636d 100644 --- a/tests/ui/panic.rs +++ b/tests/ui/panic.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(panic_params)] diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index 25113ed80b6..f2480dfea6e 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -18,5 +18,3 @@ error: you probably are missing some parameter in your format string 12 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index 41772700109..36dd4df8a6e 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index 5e536cc51d2..c332ce53c1a 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -6,5 +6,3 @@ error: re-implementing `PartialEq::ne` is unnecessary | = note: `-D partialeq-ne-impl` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 793b2b111d6..65e319e2f88 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] #![warn(clippy)] diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 59bce3a9a8f..9a246c483b2 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -6,5 +6,3 @@ error: the `y @ _` pattern can be written as just `y` | = note: `-D redundant-pattern` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index c6865632cf7..720637c94b5 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(precedence)] #[allow(identity_op)] diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 9f0e53ffca2..26fbd75164d 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -54,5 +54,3 @@ error: unary minus has lower precedence than method call 16 | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` -error: aborting due to 9 previous errors - diff --git a/tests/ui/print.rs b/tests/ui/print.rs index f1fb3cba8c1..91304d961a7 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(print_stdout, use_debug)] use std::fmt::{Debug, Display, Formatter, Result}; diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 789e1218b78..fa547949bdb 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -50,5 +50,3 @@ error: use of `Debug`-based formatting 31 | print!("Hello {:#?}", "#orld"); | ^^^^^^^ -error: aborting due to 8 previous errors - diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index d852e375ded..5cc50dea810 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(print_with_newline)] fn main() { diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 1bacc40bfb4..2ade3ae4ef5 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -24,5 +24,3 @@ error: using `print!()` with a format string that ends in a newline, consider us 9 | print!("{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 127ae703702..14b26e16847 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused, many_single_char_names)] #![warn(ptr_arg)] diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index e9ada9f8aaa..13be68d4cd4 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -79,5 +79,3 @@ help: change `y.as_str()` to 62 | let c = y; | ^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/range.rs b/tests/ui/range.rs index bb1a04cfcf3..71f2f2b219b 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,7 +1,7 @@ #![feature(iterator_step_by)] #![feature(inclusive_range_syntax)] -#![feature(plugin)] -#![plugin(clippy)] + + struct NotARange; impl NotARange { diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index fc51f1a07f0..4098d32d08e 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -38,5 +38,3 @@ error: Iterator::step_by(0) will panic at runtime 33 | let _ = v1.iter().step_by(2/3); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index 2c079273b7b..ab3897bc315 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(redundant_closure_call)] diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index e2865edc870..d8ec72fda92 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -30,5 +30,3 @@ error: Try not to call a closure in the expression where it is declared. 12 | k = (|a,b| a*b)(1,5); | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors - diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index 9451e19e336..0bd000082e8 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + fn get_number() -> usize { 10 diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 741c0cc1038..2e6b23f6dc0 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -66,5 +66,3 @@ error: immediately dereferencing a reference 53 | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` -error: aborting due to 11 previous errors - diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 56539c5468f..3dd1f64202c 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] #![warn(invalid_regex, trivial_regex, regex_macro)] diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1c3a47b82be..1c244c1df12 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -149,5 +149,3 @@ error: trivial regex | = help: consider using consider using `str::is_empty` -error: aborting due to 21 previous errors - diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index 61c691c01c1..792ebc9b0ea 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(serde_api_misuse)] #![allow(dead_code)] diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index 58667e0f820..da0a96b2a3d 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -10,5 +10,3 @@ error: you should not implement `visit_string` without also implementing `visit_ | = note: `-D serde-api-misuse` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index e1f2ffacf49..fbe695a7657 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy, clippy_pedantic)] #![allow(unused_parens, unused_variables, missing_docs_in_private_items)] diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 3fc2b7234f7..50f41627acb 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -134,5 +134,3 @@ note: previous binding is here 21 | let x = y; | ^ -error: aborting due to 9 previous errors - diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index e783c6e5e69..0f5773623be 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(short_circuit_statement)] diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index 7697cbd1c64..d7a02d7b9c3 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -18,5 +18,3 @@ error: boolean short circuit operator in statement may be clearer using an expli 9 | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` -error: aborting due to 3 previous errors - diff --git a/tests/ui/should_assert_eq.rs b/tests/ui/should_assert_eq.rs index ac5fca8dd0b..5814e997753 100644 --- a/tests/ui/should_assert_eq.rs +++ b/tests/ui/should_assert_eq.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(needless_pass_by_value)] #![warn(should_assert_eq)] diff --git a/tests/ui/should_assert_eq.stderr b/tests/ui/should_assert_eq.stderr index 57abf800498..5b393e1dbe8 100644 --- a/tests/ui/should_assert_eq.stderr +++ b/tests/ui/should_assert_eq.stderr @@ -55,5 +55,3 @@ error: use `assert_ne` for better reporting | = note: this error originates in a macro outside of the current crate -error: aborting due to 7 previous errors - diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 1cb5619dd1d..66d24a3c070 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(string_add)] #[allow(string_add_assign)] diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index d098ce9df5e..a8fd59e12b2 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -72,5 +72,3 @@ error: manual implementation of an assign operation 65 | ; x = x + 1; | ^^^^^^^^^ help: replace it with: `x += 1` -error: aborting due to 11 previous errors - diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index 3fd410c08af..24612fd3b3e 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(stutter)] #![allow(dead_code)] diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index b68f561b483..38cbcaa32f5 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -24,5 +24,3 @@ error: item name ends with its containing module's name 11 | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors - diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index abcafac4b9d..d1d12641c46 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(blacklisted_name, unused_assignments)] diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index a01ec375e63..0bda9bc8d2b 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -65,5 +65,3 @@ error: this looks like you are trying to swap `c.0` and `a` | = note: or maybe you should use `std::mem::replace`? -error: aborting due to 7 previous errors - diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 4a12d38285c..8f25aad72bb 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(temporary_assignment)] diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 979720c914d..73a4818ba16 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -12,5 +12,3 @@ error: assignment to temporary 30 | (0, 0).0 = 1; | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 7be52580c6f..a0d6dd2dabd 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,6 +1,6 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(unused)] diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index f360e85329f..525b181bf91 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -30,5 +30,3 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `& 24 | let ref mut z = 1 + 2; | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` -error: aborting due to 5 previous errors - diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 9fc71506ffe..6a7b6b05e70 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,5 +1,5 @@ #![feature(plugin, custom_attribute, stmt_expr_attributes)] -#![plugin(clippy)] + #![allow(unused_parens)] fn main() { diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 91e4d59da98..0a4b5361d86 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -12,5 +12,3 @@ error: bit mask could be simplified with a call to `trailing_zeros` 8 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` -error: aborting due to 2 previous errors - diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index a83e5194736..31cd8304eba 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index a571fed24f0..0c5aff11b0c 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -154,5 +154,3 @@ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) 117 | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 25 previous errors - diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index 4f9555297ff..08866c63ec6 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,6 +1,6 @@ //ignore-x86_64 -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 9be1e37b13e..65240c80a48 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,7 +1,7 @@ //ignore-x86 //no-ignore-x86_64 -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index 3a6a6e73f57..b679b913877 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -12,5 +12,3 @@ error: transmute from a `f64` to a pointer 11 | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 55dd0862700..5bb0e7edfed 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(zero_width_space)] fn zero() { diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 8a173daec9d..73599235ea8 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -28,5 +28,3 @@ error: literal non-ASCII character detected = help: Consider replacing the string with: ""/u{dc}ben!"" -error: aborting due to 3 previous errors - diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index ff57d2822cb..2b6d757845f 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(unit_cmp)] #![allow(no_effect, unnecessary_operation)] diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 51ad3fca947..a85e4150a3e 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -12,5 +12,3 @@ error: >-comparison of unit values detected. This will always be false 19 | if { true; } > { false; } { | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index c2f5b11e24c..8c960602264 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(unneeded_field_pattern)] #[allow(dead_code, unused)] diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 7e4c3a6cb9c..ef1a8d75732 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -15,5 +15,3 @@ error: All the struct fields are matched to a wildcard pattern, consider using ` | = help: Try with `Foo { .. }` instead -error: aborting due to 2 previous errors - diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 45daf70b171..327fea254a8 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[warn(unreadable_literal)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 72cb160fafc..81b69937a6d 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -31,5 +31,3 @@ error: long literal lacking separators | = help: consider: 1.234_56_f32 -error: aborting due to 4 previous errors - diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index 8e90964da8c..29f34d31a8e 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused_imports)] #![allow(dead_code)] #![warn(unsafe_removed_from_name)] diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 93f2ddd533f..7d455d31bce 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -18,5 +18,3 @@ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` 23 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 9beec63a6f0..ea72c1b1b70 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(dead_code)] #![warn(unused_io_amount)] diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 0ce6887f5f2..8739ac245a7 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -39,5 +39,3 @@ error: handle read amount returned or use `Read::read_exact` instead 27 | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors - diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index 6d1e8c2a31c..115121dc275 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -1,5 +1,5 @@ -#![plugin(clippy)] -#![feature(plugin)] + + #![allow(dead_code, items_after_statements, never_loop)] #![warn(unused_label)] diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index 19c91e2a6a3..338eb2f1551 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -22,5 +22,3 @@ error: unused label `'same_label_in_two_fns` 34 | | } | |_____^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 722e19e6217..91bca47eb12 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused, dead_code, needless_lifetimes, needless_pass_by_value)] #![warn(unused_lifetimes)] diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index b1fcebe6eed..a4f01de18f7 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -18,5 +18,3 @@ error: this lifetime isn't used in the function definition 50 | fn x<'a>(&self) {} | ^^ -error: aborting due to 3 previous errors - diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 14e31aae8ee..b12900b7691 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(use_self)] #![allow(dead_code)] #![allow(should_implement_trait)] diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index bfd334335d8..9d316dd3e08 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -36,5 +36,3 @@ error: unnecessary structure name repetition 24 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` -error: aborting due to 6 previous errors - diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index d8fc7c7cbca..60a2c4e8b4c 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(clippy)] #![allow(blacklisted_name)] diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 712f81c1b6f..388a3491477 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -30,5 +30,3 @@ error: used binding `_underscore_field` which is prefixed with an underscore. A 36 | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors - diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index cd2636a5b6f..4c2fb221af8 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(useless_attribute)] #[allow(dead_code, unused_extern_crates)] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 707a11d55cc..0bb87f8c538 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -6,5 +6,3 @@ error: useless lint attribute | = note: `-D useless-attribute` implied by `-D warnings` -error: aborting due to previous error - diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 1845b509af0..23e43872454 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(useless_vec)] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 6a47eb5b064..a1555bc7907 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -36,5 +36,3 @@ error: useless use of `vec!` 49 | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` -error: aborting due to 6 previous errors - diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 9bae1bc48e6..b7ef39da817 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(while_let_loop, empty_loop, while_let_on_iterator)] #![allow(dead_code, never_loop, unused, cyclomatic_complexity)] diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index 689c92d6fb6..edc88405c40 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -110,5 +110,3 @@ error: this loop could be written as a `for` loop 184 | | } | |_________^ help: try: `for v in y { .. }` -error: aborting due to 11 previous errors - diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 91b60c8faaa..bef87e2bb01 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![warn(wrong_self_convention)] #![warn(wrong_pub_self_convention)] diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index 216fd0bb82b..e57ffc3266b 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -72,5 +72,3 @@ error: methods called `from_*` usually take no self; consider choosing a less am 54 | pub fn from_i64(self) {} | ^^^^ -error: aborting due to 12 previous errors - diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index af61e1c8429..65e1e239980 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[allow(unused_variables)] #[warn(zero_divided_by_zero)] diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index b81e59c07f1..697432af408 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -57,5 +57,3 @@ error: constant division of 0.0 with 0.0 will always result in NaN | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN -error: aborting due to 8 previous errors - diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index a72223ef54c..4a6010f4bd0 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[allow(unused_variables)] fn main() { diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 5155dc401bd..fb87a47536e 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -12,5 +12,3 @@ error: `0 as *mut _` detected. Consider using `ptr::null_mut()` 7 | let y = 0 as *mut f64; | ^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - -- cgit 1.4.1-3-g733a5 From 47df71722923474014f26510d59968f063d8ecdd Mon Sep 17 00:00:00 2001 From: PizzaIter Date: Mon, 2 Oct 2017 17:23:24 +0200 Subject: Add lints `transmute_int_to_*` --- clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/transmute.rs | 110 +++++++++++++++++++++++++++++++++++++++++- tests/ui/transmute.rs | 17 +++++++ tests/ui/transmute.stderr | 36 ++++++++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 38d7847f42b..933ec1a8e70 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -544,6 +544,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, + transmute::TRANSMUTE_INT_TO_CHAR, + transmute::TRANSMUTE_INT_TO_BOOL, + transmute::TRANSMUTE_INT_TO_FLOAT, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 76110ecb152..a97c24166b4 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,6 +1,8 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; +use std::borrow::Cow; +use syntax::ast; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::{sugg, opt_def_id}; @@ -76,11 +78,73 @@ declare_lint! { "transmutes from a pointer to a reference type" } +/// **What it does:** Checks for transmutes from an integer to a `char`. +/// +/// **Why is this bad?** Not every integer is a unicode scalar value. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: char = std::mem::transmute(x); // where x: u32 +/// // should be: +/// let _: Option = std::char::from_u32(x); +/// ``` +declare_lint! { + pub TRANSMUTE_INT_TO_CHAR, + Warn, + "transmutes from an integer to a `char`" +} + +/// **What it does:** Checks for transmutes from an integer to a `bool`. +/// +/// **Why is this bad?** This might result in an invalid in-memory representation of a `bool`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: bool = std::mem::transmute(x); // where x: u8 +/// // should be: +/// let _: bool = x != 0; +/// ``` +declare_lint! { + pub TRANSMUTE_INT_TO_BOOL, + Warn, + "transmutes from an integer to a `bool`" +} + +/// **What it does:** Checks for transmutes from an integer to a float. +/// +/// **Why is this bad?** This might result in an invalid in-memory representation of a float. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: f32 = std::mem::transmute(x); // where x: u32 +/// // should be: +/// let _: f32 = f32::from_bits(x); +/// ``` +declare_lint! { + pub TRANSMUTE_INT_TO_FLOAT, + Warn, + "transmutes from an integer to a float" +} + pub struct Transmute; impl LintPass for Transmute { fn get_lints(&self) -> LintArray { - lint_array!(CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE) + lint_array!( + CROSSPOINTER_TRANSMUTE, + TRANSMUTE_PTR_TO_REF, + USELESS_TRANSMUTE, + WRONG_TRANSMUTE, + TRANSMUTE_INT_TO_CHAR, + TRANSMUTE_INT_TO_BOOL, + TRANSMUTE_INT_TO_FLOAT + ) } } @@ -177,6 +241,50 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); }, ), + (&ty::TyInt(ast::IntTy::I32), &ty::TyChar) | + (&ty::TyUint(ast::UintTy::U32), &ty::TyChar) => span_lint_and_then( + cx, + TRANSMUTE_INT_TO_CHAR, + e.span, + &format!("transmute from a `{}` to a `char`", from_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::TyInt(_) = from_ty.sty { + arg.as_ty(ty::TyUint(ast::UintTy::U32)) + } else { + arg + }; + db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({})", arg.to_string())); + } + ), + (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | + (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then( + cx, + TRANSMUTE_INT_TO_BOOL, + e.span, + &format!("transmute from a `{}` to a `bool`", from_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let zero = sugg::Sugg::NonParen(Cow::from("0")); + db.span_suggestion(e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string()); + } + ), + (&ty::TyInt(_), &ty::TyFloat(_)) | + (&ty::TyUint(_), &ty::TyFloat(_)) => span_lint_and_then( + cx, + TRANSMUTE_INT_TO_FLOAT, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::TyInt(int_ty) = from_ty.sty { + arg.as_ty(format!("u{}", int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string()))) + } else { + arg + }; + db.span_suggestion(e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string())); + } + ), _ => return, }; } diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 31cd8304eba..81582b5a15f 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -118,4 +118,21 @@ fn crosspointer() { } } +#[warn(transmute_int_to_char)] +fn int_to_char() { + let _: char = unsafe { std::mem::transmute(0_u32) }; + let _: char = unsafe { std::mem::transmute(0_i32) }; +} + +#[warn(transmute_int_to_bool)] +fn int_to_bool() { + let _: bool = unsafe { std::mem::transmute(0_u8) }; +} + +#[warn(transmute_int_to_float)] +fn int_to_float() { + let _: f32 = unsafe { std::mem::transmute(0_u32) }; + let _: f32 = unsafe { std::mem::transmute(0_i32) }; +} + fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 0c5aff11b0c..c81ec5260be 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -154,3 +154,39 @@ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) 117 | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: transmute from a `u32` to a `char` + --> $DIR/transmute.rs:123:28 + | +123 | let _: char = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32)` + | + = note: `-D transmute-int-to-char` implied by `-D warnings` + +error: transmute from a `i32` to a `char` + --> $DIR/transmute.rs:124:28 + | +124 | let _: char = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32)` + +error: transmute from a `u8` to a `bool` + --> $DIR/transmute.rs:129:28 + | +129 | let _: bool = unsafe { std::mem::transmute(0_u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` + | + = note: `-D transmute-int-to-bool` implied by `-D warnings` + +error: transmute from a `u32` to a `f32` + --> $DIR/transmute.rs:134:27 + | +134 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` + | + = note: `-D transmute-int-to-float` implied by `-D warnings` + +error: transmute from a `i32` to a `f32` + --> $DIR/transmute.rs:135:27 + | +135 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` + -- cgit 1.4.1-3-g733a5 From 771d2220d28f458e59b2f12a571d2963bf7255f5 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 5 Feb 2017 13:41:09 +0900 Subject: Add identity_conversion lint (fixes #1051) --- clippy_lints/src/identity_conversion.rs | 96 +++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/utils/paths.rs | 2 + clippy_lints/src/vec.rs | 4 +- tests/ui/identity_conversion.rs | 35 ++++++++++++ tests/ui/identity_conversion.stderr | 42 +++++++++++++++ 6 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/identity_conversion.rs create mode 100644 tests/ui/identity_conversion.rs create mode 100644 tests/ui/identity_conversion.stderr diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs new file mode 100644 index 00000000000..d64f352d7f1 --- /dev/null +++ b/clippy_lints/src/identity_conversion.rs @@ -0,0 +1,96 @@ +use rustc::lint::*; +use rustc::hir::*; +use syntax::ast::NodeId; +use utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; +use utils::{opt_def_id, paths, resolve_node}; + +/// **What it does:** Checks for always-identical `Into`/`From` conversions. +/// +/// **Why is this bad?** Redundant code. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // format!() returns a `String` +/// let s: String = format!("hello").into(); +/// ``` +declare_lint! { + pub IDENTITY_CONVERSION, + Warn, + "using always-identical `Into`/`From` conversions" +} + +#[derive(Default)] +pub struct IdentityConversion { + try_desugar_arm: Vec, +} + +impl LintPass for IdentityConversion { + fn get_lints(&self) -> LintArray { + lint_array!(IDENTITY_CONVERSION) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if in_macro(e.span) { + return; + } + + if Some(&e.id) == self.try_desugar_arm.last() { + return; + } + + match e.node { + ExprMatch(_, ref arms, MatchSource::TryDesugar) => { + let e = match arms[0].body.node { + ExprRet(Some(ref e)) | ExprBreak(_, Some(ref e)) => e, + _ => return, + }; + if let ExprCall(_, ref args) = e.node { + self.try_desugar_arm.push(args[0].id); + } else { + return; + } + }, + + ExprMethodCall(ref name, .., ref args) => { + if match_trait_method(cx, e, &paths::INTO[..]) && &*name.name.as_str() == "into" { + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + if same_tys(cx, a, b) { + let sugg = snippet(cx, args[0].span, "").into_owned(); + span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { + db.span_suggestion(e.span, "consider removing `.into()`", sugg); + }); + } + } + }, + + ExprCall(ref path, ref args) => if let ExprPath(ref qpath) = path.node { + if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) { + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + if same_tys(cx, a, b) { + let sugg = snippet(cx, args[0].span, "").into_owned(); + let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); + span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { + db.span_suggestion(e.span, &sugg_msg, sugg); + }); + } + } + } + }, + + _ => {}, + } + } + + fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if Some(&e.id) == self.try_desugar_arm.last() { + self.try_desugar_arm.pop(); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 933ec1a8e70..d4af88d5fed 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -93,6 +93,7 @@ pub mod eval_order_dependence; pub mod format; pub mod formatting; pub mod functions; +pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; @@ -331,6 +332,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::Pass); reg.register_late_lint_pass(box invalid_ref::InvalidRef); + reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -431,6 +433,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { formatting::SUSPICIOUS_ELSE_FORMATTING, functions::NOT_UNSAFE_PTR_ARG_DEREF, functions::TOO_MANY_ARGUMENTS, + identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infinite_iter::INFINITE_ITER, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 2a2eabcca1f..d517d32b64c 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -26,11 +26,13 @@ pub const DOUBLE_ENDED_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["core", "fmt", "ArgumentV1", "new"]; +pub const FROM_FROM: [&'static str; 4] = ["core", "convert", "From", "from"]; pub const HASH: [&'static str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; pub const INIT: [&'static str; 4] = ["core", "intrinsics", "", "init"]; +pub const INTO: [&'static str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "IntoIterator"]; pub const IO_PRINT: [&'static str; 4] = ["std", "io", "stdio", "_print"]; pub const IO_READ: [&'static str; 3] = ["std", "io", "Read"]; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 367235f7eee..6044eaac376 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -67,7 +67,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA .eval(len) .is_ok() { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() + format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")) } else { return; } @@ -75,7 +75,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() { let span = args[0].span.to(last.span); - format!("&[{}]", snippet(cx, span, "..")).into() + format!("&[{}]", snippet(cx, span, "..")) } else { "&[]".into() }, diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs new file mode 100644 index 00000000000..81cbdd9643a --- /dev/null +++ b/tests/ui/identity_conversion.rs @@ -0,0 +1,35 @@ +#![deny(identity_conversion)] + +fn test_generic(val: T) -> T { + let _ = T::from(val); + val.into() +} + +fn test_generic2 + Into, U: From>(val: T) { + // ok + let _: i32 = val.into(); + let _: U = val.into(); + let _ = U::from(val); +} + +fn test_questionmark() -> Result<(), ()> { + { + let _: i32 = 0i32.into(); + Ok(Ok(())) + }??; + Ok(()) +} + +fn main() { + test_generic(10i32); + test_generic2::(10i32); + test_questionmark().unwrap(); + + let _: String = "foo".into(); + let _: String = From::from("foo"); + let _ = String::from("foo"); + + let _: String = "foo".to_string().into(); + let _: String = From::from("foo".to_string()); + let _ = String::from("foo".to_string()); +} diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr new file mode 100644 index 00000000000..8e8d8a70124 --- /dev/null +++ b/tests/ui/identity_conversion.stderr @@ -0,0 +1,42 @@ +error: identical conversion + --> $DIR/identity_conversion.rs:4:13 + | +4 | let _ = T::from(val); + | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` + | +note: lint level defined here + --> $DIR/identity_conversion.rs:1:9 + | +1 | #![deny(identity_conversion)] + | ^^^^^^^^^^^^^^^^^^^ + +error: identical conversion + --> $DIR/identity_conversion.rs:5:5 + | +5 | val.into() + | ^^^^^^^^^^ help: consider removing `.into()`: `val` + +error: identical conversion + --> $DIR/identity_conversion.rs:17:22 + | +17 | let _: i32 = 0i32.into(); + | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` + +error: identical conversion + --> $DIR/identity_conversion.rs:32:21 + | +32 | let _: String = "foo".to_string().into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` + +error: identical conversion + --> $DIR/identity_conversion.rs:33:21 + | +33 | let _: String = From::from("foo".to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` + +error: identical conversion + --> $DIR/identity_conversion.rs:34:13 + | +34 | let _ = String::from("foo".to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` + -- cgit 1.4.1-3-g733a5 From 1b1b41a5e6c77f80762be0cff6f759461e70ce61 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 4 Oct 2017 22:26:41 +0900 Subject: Test if #[allow] works --- tests/ui/identity_conversion.rs | 5 +++++ tests/ui/identity_conversion.stderr | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 81cbdd9643a..d254b746d79 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -28,6 +28,11 @@ fn main() { let _: String = "foo".into(); let _: String = From::from("foo"); let _ = String::from("foo"); + #[allow(identity_conversion)] + { + let _: String = "foo".into(); + let _ = String::from("foo"); + } let _: String = "foo".to_string().into(); let _: String = From::from("foo".to_string()); diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 8e8d8a70124..152bb8882bd 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -23,20 +23,20 @@ error: identical conversion | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:32:21 + --> $DIR/identity_conversion.rs:37:21 | -32 | let _: String = "foo".to_string().into(); +37 | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:33:21 + --> $DIR/identity_conversion.rs:38:21 | -33 | let _: String = From::from("foo".to_string()); +38 | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:34:13 + --> $DIR/identity_conversion.rs:39:13 | -34 | let _ = String::from("foo".to_string()); +39 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -- cgit 1.4.1-3-g733a5 From d6b35f98397625fdae521fe3902f1f7077fdd707 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 5 Oct 2017 23:46:08 -0500 Subject: add never_loop test --- tests/ui/never_loop.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 4866db1a541..715a83efd93 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -126,6 +126,19 @@ pub fn test12(a: bool, b: bool) { } } +pub fn test13() { + let mut a = true; + loop { // infinite loop + while a { + if true { + a = false; + continue; + } + return; + } + } +} + fn main() { test1(); test2(); @@ -139,5 +152,6 @@ fn main() { test10(); test11(|| 0); test12(true, false); + test13(); } -- cgit 1.4.1-3-g733a5 From d92d5a88118c98477b33ed14b7ae3dc9ca4b394f Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Fri, 6 Oct 2017 00:04:39 -0500 Subject: fix never_loop --- clippy_lints/src/loops.rs | 65 ++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 76f1a603f24..8d2a2f8fac6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -378,7 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { - if never_loop(block, &expr.id) { + if never_loop(block, expr.id) { span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); } }, @@ -485,11 +485,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn never_loop(block: &Block, id: &NodeId) -> bool { - !contains_continue_block(block, id) && loop_exit_block(block) +fn never_loop(block: &Block, id: NodeId) -> bool { + !contains_continue_block(block, Some(id)) && loop_exit_block(block, &mut vec![id]) } -fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { +fn contains_continue_block(block: &Block, dest: Option) -> bool { block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || block.expr.as_ref().map_or( false, @@ -497,7 +497,7 @@ fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { ) } -fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { +fn contains_continue_stmt(stmt: &Stmt, dest: Option) -> bool { match stmt.node { StmtSemi(ref e, _) | StmtExpr(ref e, _) => contains_continue_expr(e, dest), @@ -505,7 +505,7 @@ fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { } } -fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { +fn contains_continue_decl(decl: &Decl, dest: Option) -> bool { match decl.node { DeclLocal(ref local) => { local.init.as_ref().map_or( @@ -517,7 +517,7 @@ fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { } } -fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { +fn contains_continue_expr(expr: &Expr, dest: Option) -> bool { match expr.node { ExprRet(Some(ref e)) | ExprBox(ref e) | @@ -555,31 +555,32 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { |e| contains_continue_expr(e, dest), ) }, - ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), + ExprAgain(d) => dest.map_or(true, |dest| d.target_id.opt_id().map_or(false, |id| id == dest)), _ => false, } } -fn loop_exit_block(block: &Block) -> bool { - block.stmts.iter().any(|e| loop_exit_stmt(e)) || block.expr.as_ref().map_or(false, |e| loop_exit_expr(e)) +fn loop_exit_block(block: &Block, loops: &mut Vec) -> bool { + block.stmts.iter().take_while(|s| !contains_continue_stmt(s, None)).any(|s| loop_exit_stmt(s, loops)) + || block.expr.as_ref().map_or(false, |e| loop_exit_expr(e, loops)) } -fn loop_exit_stmt(stmt: &Stmt) -> bool { +fn loop_exit_stmt(stmt: &Stmt, loops: &mut Vec) -> bool { match stmt.node { StmtSemi(ref e, _) | - StmtExpr(ref e, _) => loop_exit_expr(e), - StmtDecl(ref d, _) => loop_exit_decl(d), + StmtExpr(ref e, _) => loop_exit_expr(e, loops), + StmtDecl(ref d, _) => loop_exit_decl(d, loops), } } -fn loop_exit_decl(decl: &Decl) -> bool { +fn loop_exit_decl(decl: &Decl, loops: &mut Vec) -> bool { match decl.node { - DeclLocal(ref local) => local.init.as_ref().map_or(false, |e| loop_exit_expr(e)), + DeclLocal(ref local) => local.init.as_ref().map_or(false, |e| loop_exit_expr(e, loops)), _ => false, } } -fn loop_exit_expr(expr: &Expr) -> bool { +fn loop_exit_expr(expr: &Expr, loops: &mut Vec) -> bool { match expr.node { ExprBox(ref e) | ExprUnary(_, ref e) | @@ -588,22 +589,34 @@ fn loop_exit_expr(expr: &Expr) -> bool { ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | - ExprRepeat(ref e, _) => loop_exit_expr(e), + ExprRepeat(ref e, _) => loop_exit_expr(e, loops), ExprArray(ref es) | ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), - ExprCall(ref e, ref es) => loop_exit_expr(e) || es.iter().any(|e| loop_exit_expr(e)), + ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e, loops)), + ExprCall(ref e, ref es) => loop_exit_expr(e, loops) || es.iter().any(|e| loop_exit_expr(e, loops)), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | - ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| loop_exit_expr(e)), - ExprIf(ref e, ref e2, ref e3) => { - loop_exit_expr(e) || e3.as_ref().map_or(false, |e| loop_exit_expr(e)) && loop_exit_expr(e2) + ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| loop_exit_expr(e, loops)), + ExprIf(ref e, ref e2, ref e3) => loop_exit_expr(e, loops) + || e3.as_ref().map_or(false, |e3| loop_exit_expr(e3, loops)) && loop_exit_expr(e2, loops), + ExprLoop(ref b, _, _) => { + loops.push(expr.id); + let val = loop_exit_block(b, loops); + loops.pop(); + val + }, + ExprWhile(ref e, ref b, _) => { + loops.push(expr.id); + let val = loop_exit_expr(e, loops) || loop_exit_block(b, loops); + loops.pop(); + val }, - ExprWhile(ref e, ref b, _) => loop_exit_expr(e) || loop_exit_block(b), - ExprMatch(ref e, ref arms, _) => loop_exit_expr(e) || arms.iter().all(|a| loop_exit_expr(&a.body)), - ExprBlock(ref b) => loop_exit_block(b), - ExprBreak(_, _) | ExprAgain(_) | ExprRet(_) => true, + ExprMatch(ref e, ref arms, _) => loop_exit_expr(e, loops) || arms.iter().all(|a| loop_exit_expr(&a.body, loops)), + ExprBlock(ref b) => loop_exit_block(b, loops), + ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| loops.iter().skip(1).all(|&id2| id != id2)), + ExprBreak(d, _) => d.target_id.opt_id().map_or(false, |id| loops[0] == id), + ExprRet(_) => true, _ => false, } } -- cgit 1.4.1-3-g733a5 From f5c941a4046398c261b8dad4109ac3732a0de1d5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Oct 2017 22:04:16 +0900 Subject: Update OPTION_MAP_UNWRAP_OR lint Add a suggestion to replace `map(f).unwrap_or(None)` with `and_then(f)`. --- clippy_lints/src/methods.rs | 34 ++-- tests/ui/methods.rs | 2 + tests/ui/methods.stderr | 468 ++++++++++++++++++++++---------------------- 3 files changed, 260 insertions(+), 244 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 6d3a3f39d1a..0fd301d8950 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1150,29 +1150,35 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) { fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { - // lint message - let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ - `map_or(a, f)` instead"; // get snippets for args to map() and unwrap_or() let map_snippet = snippet(cx, map_args[1].span, ".."); let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint message + let arg = if unwrap_snippet == "None" { "None" } else { "a" }; + let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { "map_or(a, f)" }; + let msg = &format!( + "called `map(f).unwrap_or({})` on an Option value. \ + This can be done more directly by calling `{}` instead", + arg, + suggest + ); // lint, with note if neither arg is > 1 line and both map() and // unwrap_or() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); if same_span && !multiline { - span_note_and_lint( - cx, - OPTION_MAP_UNWRAP_OR, - expr.span, - msg, - expr.span, - &format!( - "replace `map({0}).unwrap_or({1})` with `map_or({1}, {0})`", - map_snippet, - unwrap_snippet - ), + let suggest = if unwrap_snippet == "None" { + format!("and_then({})", map_snippet) + } else { + format!("map_or({}, {})", unwrap_snippet, map_snippet) + }; + let note = format!( + "replace `map({}).unwrap_or({})` with `{}`", + map_snippet, + unwrap_snippet, + suggest ); + span_note_and_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, ¬e); } else if same_span && multiline { span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); }; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 08ff4771420..20372f7590a 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -108,6 +108,8 @@ fn option_methods() { .unwrap_or({ 0 }); + // map(f).unwrap_or(None) case + let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); // macro case let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index c5fab711fe1..0e8c729d6e6 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -134,705 +134,713 @@ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more di 110 | | }); | |__________________^ +error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/methods.rs:112:13 + | +112 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` + error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:116:13 + --> $DIR/methods.rs:118:13 | -116 | let _ = opt.map(|x| x + 1) +118 | let _ = opt.map(|x| x + 1) | _____________^ -117 | | -118 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +119 | | +120 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:120:13 + --> $DIR/methods.rs:122:13 | -120 | let _ = opt.map(|x| { +122 | let _ = opt.map(|x| { | _____________^ -121 | | x + 1 -122 | | } -123 | | ).unwrap_or_else(|| 0); +123 | | x + 1 +124 | | } +125 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:124:13 + --> $DIR/methods.rs:126:13 | -124 | let _ = opt.map(|x| x + 1) +126 | let _ = opt.map(|x| x + 1) | _____________^ -125 | | .unwrap_or_else(|| -126 | | 0 -127 | | ); +127 | | .unwrap_or_else(|| +128 | | 0 +129 | | ); | |_________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:153:24 + --> $DIR/methods.rs:155:24 | -153 | fn filter(self) -> IteratorFalsePositives { +155 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:157:22 + --> $DIR/methods.rs:159:22 | -157 | fn next(self) -> IteratorFalsePositives { +159 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:177:32 + --> $DIR/methods.rs:179:32 | -177 | fn skip(self, _: usize) -> IteratorFalsePositives { +179 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:196:13 + --> $DIR/methods.rs:198:13 | -196 | let _ = v.iter().filter(|&x| *x < 0).next(); +198 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:199:13 + --> $DIR/methods.rs:201:13 | -199 | let _ = v.iter().filter(|&x| { +201 | let _ = v.iter().filter(|&x| { | _____________^ -200 | | *x < 0 -201 | | } -202 | | ).next(); +202 | | *x < 0 +203 | | } +204 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:214:13 + --> $DIR/methods.rs:216:13 | -214 | let _ = v.iter().find(|&x| *x < 0).is_some(); +216 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:217:13 + --> $DIR/methods.rs:219:13 | -217 | let _ = v.iter().find(|&x| { +219 | let _ = v.iter().find(|&x| { | _____________^ -218 | | *x < 0 -219 | | } -220 | | ).is_some(); +220 | | *x < 0 +221 | | } +222 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:223:13 + --> $DIR/methods.rs:225:13 | -223 | let _ = v.iter().position(|&x| x < 0).is_some(); +225 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:226:13 + --> $DIR/methods.rs:228:13 | -226 | let _ = v.iter().position(|&x| { +228 | let _ = v.iter().position(|&x| { | _____________^ -227 | | x < 0 -228 | | } -229 | | ).is_some(); +229 | | x < 0 +230 | | } +231 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:232:13 + --> $DIR/methods.rs:234:13 | -232 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +234 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:235:13 + --> $DIR/methods.rs:237:13 | -235 | let _ = v.iter().rposition(|&x| { +237 | let _ = v.iter().rposition(|&x| { | _____________^ -236 | | x < 0 -237 | | } -238 | | ).is_some(); +238 | | x < 0 +239 | | } +240 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:252:21 + --> $DIR/methods.rs:254:21 | -252 | fn new() -> Foo { Foo } +254 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:270:5 + --> $DIR/methods.rs:272:5 | -270 | with_constructor.unwrap_or(make()); +272 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:273:5 + --> $DIR/methods.rs:275:5 | -273 | with_new.unwrap_or(Vec::new()); +275 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:276:5 + --> $DIR/methods.rs:278:5 | -276 | with_const_args.unwrap_or(Vec::with_capacity(12)); +278 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:279:5 + --> $DIR/methods.rs:281:5 | -279 | with_err.unwrap_or(make()); +281 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:282:5 + --> $DIR/methods.rs:284:5 | -282 | with_err_args.unwrap_or(Vec::with_capacity(12)); +284 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:285:5 + --> $DIR/methods.rs:287:5 | -285 | with_default_trait.unwrap_or(Default::default()); +287 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:288:5 + --> $DIR/methods.rs:290:5 | -288 | with_default_type.unwrap_or(u64::default()); +290 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:291:5 + --> $DIR/methods.rs:293:5 | -291 | with_vec.unwrap_or(vec![]); +293 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:296:5 + --> $DIR/methods.rs:298:5 | -296 | without_default.unwrap_or(Foo::new()); +298 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:299:5 + --> $DIR/methods.rs:301:5 | -299 | map.entry(42).or_insert(String::new()); +301 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:302:5 + --> $DIR/methods.rs:304:5 | -302 | btree.entry(42).or_insert(String::new()); +304 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:305:13 + --> $DIR/methods.rs:307:13 | -305 | let _ = stringy.unwrap_or("".to_owned()); +307 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:316:23 + --> $DIR/methods.rs:318:23 | -316 | let bad_vec = some_vec.iter().nth(3); +318 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:317:26 + --> $DIR/methods.rs:319:26 | -317 | let bad_slice = &some_vec[..].iter().nth(3); +319 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:318:31 + --> $DIR/methods.rs:320:31 | -318 | let bad_boxed_slice = boxed_slice.iter().nth(3); +320 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:319:29 + --> $DIR/methods.rs:321:29 | -319 | let bad_vec_deque = some_vec_deque.iter().nth(3); +321 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:324:23 + --> $DIR/methods.rs:326:23 | -324 | let bad_vec = some_vec.iter_mut().nth(3); +326 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:327:26 + --> $DIR/methods.rs:329:26 | -327 | let bad_slice = &some_vec[..].iter_mut().nth(3); +329 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:330:29 + --> $DIR/methods.rs:332:29 | -330 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +332 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:342:13 + --> $DIR/methods.rs:344:13 | -342 | let _ = some_vec.iter().skip(42).next(); +344 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:343:13 + --> $DIR/methods.rs:345:13 | -343 | let _ = some_vec.iter().cycle().skip(42).next(); +345 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:344:13 + --> $DIR/methods.rs:346:13 | -344 | let _ = (1..10).skip(10).next(); +346 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:345:14 + --> $DIR/methods.rs:347:14 | -345 | let _ = &some_vec[..].iter().skip(3).next(); +347 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:371:17 + --> $DIR/methods.rs:373:17 | -371 | let _ = boxed_slice.get(1).unwrap(); +373 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:372:17 + --> $DIR/methods.rs:374:17 | -372 | let _ = some_slice.get(0).unwrap(); +374 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:373:17 + --> $DIR/methods.rs:375:17 | -373 | let _ = some_vec.get(0).unwrap(); +375 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:374:17 + --> $DIR/methods.rs:376:17 | -374 | let _ = some_vecdeque.get(0).unwrap(); +376 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:375:17 + --> $DIR/methods.rs:377:17 | -375 | let _ = some_hashmap.get(&1).unwrap(); +377 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:376:17 + --> $DIR/methods.rs:378:17 | -376 | let _ = some_btreemap.get(&1).unwrap(); +378 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:381:10 + --> $DIR/methods.rs:383:10 | -381 | *boxed_slice.get_mut(0).unwrap() = 1; +383 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:382:10 + --> $DIR/methods.rs:384:10 | -382 | *some_slice.get_mut(0).unwrap() = 1; +384 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:383:10 + --> $DIR/methods.rs:385:10 | -383 | *some_vec.get_mut(0).unwrap() = 1; +385 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:384:10 + --> $DIR/methods.rs:386:10 | -384 | *some_vecdeque.get_mut(0).unwrap() = 1; +386 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:398:13 + --> $DIR/methods.rs:400:13 | -398 | let _ = opt.unwrap(); +400 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:401:13 + --> $DIR/methods.rs:403:13 | -401 | let _ = res.unwrap(); +403 | let _ = res.unwrap(); | ^^^^^^^^^^^^ | = note: `-D result-unwrap-used` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:403:5 + --> $DIR/methods.rs:405:5 | -403 | res.ok().expect("disaster!"); +405 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:409:5 + --> $DIR/methods.rs:411:5 | -409 | res3.ok().expect("whoof"); +411 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:411:5 + --> $DIR/methods.rs:413:5 | -411 | res4.ok().expect("argh"); +413 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:413:5 + --> $DIR/methods.rs:415:5 | -413 | res5.ok().expect("oops"); +415 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:415:5 + --> $DIR/methods.rs:417:5 | -415 | res6.ok().expect("meh"); +417 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `starts_with` method - --> $DIR/methods.rs:427:5 + --> $DIR/methods.rs:429:5 | -427 | "".chars().next() == Some(' '); +429 | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | = note: `-D chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/methods.rs:428:5 + --> $DIR/methods.rs:430:5 | -428 | Some(' ') != "".chars().next(); +430 | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:437:5 + --> $DIR/methods.rs:439:5 | -437 | s.extend(abc.chars()); +439 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:440:5 + --> $DIR/methods.rs:442:5 | -440 | s.extend("abc".chars()); +442 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:443:5 + --> $DIR/methods.rs:445:5 | -443 | s.extend(def.chars()); +445 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:454:5 + --> $DIR/methods.rs:456:5 | -454 | 42.clone(); +456 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:458:5 + --> $DIR/methods.rs:460:5 | -458 | (&42).clone(); +460 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:468:5 + --> $DIR/methods.rs:470:5 | -468 | rc.clone(); +470 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` | = note: `-D clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:471:5 + --> $DIR/methods.rs:473:5 | -471 | arc.clone(); +473 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:474:5 + --> $DIR/methods.rs:476:5 | -474 | rcweak.clone(); +476 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:477:5 + --> $DIR/methods.rs:479:5 | -477 | arc_weak.clone(); +479 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:484:5 + --> $DIR/methods.rs:486:5 | -484 | t.clone(); +486 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:486:5 + --> $DIR/methods.rs:488:5 | -486 | Some(t).clone(); +488 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:492:22 + --> $DIR/methods.rs:494:22 | -492 | let z: &Vec<_> = y.clone(); +494 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` | = note: `-D clone-double-ref` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:499:13 + --> $DIR/methods.rs:501:13 | -499 | x.split("x"); +501 | x.split("x"); | --------^^^- help: try using a char instead: `x.split('x')` | = note: `-D single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:516:16 + --> $DIR/methods.rs:518:16 | -516 | x.contains("x"); +518 | x.contains("x"); | -----------^^^- help: try using a char instead: `x.contains('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:517:19 + --> $DIR/methods.rs:519:19 | -517 | x.starts_with("x"); +519 | x.starts_with("x"); | --------------^^^- help: try using a char instead: `x.starts_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:518:17 + --> $DIR/methods.rs:520:17 | -518 | x.ends_with("x"); +520 | x.ends_with("x"); | ------------^^^- help: try using a char instead: `x.ends_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:519:12 + --> $DIR/methods.rs:521:12 | -519 | x.find("x"); +521 | x.find("x"); | -------^^^- help: try using a char instead: `x.find('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:520:13 + --> $DIR/methods.rs:522:13 | -520 | x.rfind("x"); +522 | x.rfind("x"); | --------^^^- help: try using a char instead: `x.rfind('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:521:14 + --> $DIR/methods.rs:523:14 | -521 | x.rsplit("x"); +523 | x.rsplit("x"); | ---------^^^- help: try using a char instead: `x.rsplit('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:522:24 + --> $DIR/methods.rs:524:24 | -522 | x.split_terminator("x"); +524 | x.split_terminator("x"); | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:523:25 + --> $DIR/methods.rs:525:25 | -523 | x.rsplit_terminator("x"); +525 | x.rsplit_terminator("x"); | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:524:17 + --> $DIR/methods.rs:526:17 | -524 | x.splitn(0, "x"); +526 | x.splitn(0, "x"); | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:525:18 + --> $DIR/methods.rs:527:18 | -525 | x.rsplitn(0, "x"); +527 | x.rsplitn(0, "x"); | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:526:15 + --> $DIR/methods.rs:528:15 | -526 | x.matches("x"); +528 | x.matches("x"); | ----------^^^- help: try using a char instead: `x.matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:527:16 + --> $DIR/methods.rs:529:16 | -527 | x.rmatches("x"); +529 | x.rmatches("x"); | -----------^^^- help: try using a char instead: `x.rmatches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:528:21 + --> $DIR/methods.rs:530:21 | -528 | x.match_indices("x"); +530 | x.match_indices("x"); | ----------------^^^- help: try using a char instead: `x.match_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:529:22 + --> $DIR/methods.rs:531:22 | -529 | x.rmatch_indices("x"); +531 | x.rmatch_indices("x"); | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:530:25 + --> $DIR/methods.rs:532:25 | -530 | x.trim_left_matches("x"); +532 | x.trim_left_matches("x"); | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:531:26 + --> $DIR/methods.rs:533:26 | -531 | x.trim_right_matches("x"); +533 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:541:5 + --> $DIR/methods.rs:543:5 | -541 | CString::new("foo").unwrap().as_ptr(); +543 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:541:5 + --> $DIR/methods.rs:543:5 | -541 | CString::new("foo").unwrap().as_ptr(); +543 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:546:27 + --> $DIR/methods.rs:548:27 | -546 | let v2 : Vec = v.iter().cloned().collect(); +548 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/methods.rs:553:8 + --> $DIR/methods.rs:555:8 | -553 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +555 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:553:8 + --> $DIR/methods.rs:555:8 | -553 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +555 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:556:8 + --> $DIR/methods.rs:558:8 | -556 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +558 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | = note: `-D chars-last-cmp` implied by `-D warnings` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:556:8 + --> $DIR/methods.rs:558:8 | -556 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +558 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:559:8 + --> $DIR/methods.rs:561:8 | -559 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +561 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:559:8 + --> $DIR/methods.rs:561:8 | -559 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +561 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `starts_with` method - --> $DIR/methods.rs:562:8 + --> $DIR/methods.rs:564:8 | -562 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +564 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:562:8 + --> $DIR/methods.rs:564:8 | -562 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +564 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:565:8 + --> $DIR/methods.rs:567:8 | -565 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +567 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:565:8 + --> $DIR/methods.rs:567:8 | -565 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +567 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:568:8 + --> $DIR/methods.rs:570:8 | -568 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +570 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:568:8 + --> $DIR/methods.rs:570:8 | -568 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +570 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:575:5 + --> $DIR/methods.rs:577:5 | -575 | "".chars().last() == Some(' '); +577 | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:576:5 + --> $DIR/methods.rs:578:5 | -576 | Some(' ') != "".chars().last(); +578 | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:577:5 + --> $DIR/methods.rs:579:5 | -577 | "".chars().next_back() == Some(' '); +579 | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:578:5 + --> $DIR/methods.rs:580:5 | -578 | Some(' ') != "".chars().next_back(); +580 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` -- cgit 1.4.1-3-g733a5 From 63d6df210105cc28e431f7c218fda441cce785e4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 00:10:45 +0900 Subject: Add a comment that explains about comparing snippet to raw text --- clippy_lints/src/methods.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 0fd301d8950..ca0d7230229 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1154,6 +1154,8 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] let map_snippet = snippet(cx, map_args[1].span, ".."); let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); // lint message + // comparing the snippet from source to raw text ("None") below is safe + // because we already have checked the type. let arg = if unwrap_snippet == "None" { "None" } else { "a" }; let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { "map_or(a, f)" }; let msg = &format!( -- cgit 1.4.1-3-g733a5 From 7f4b583c477850c937b5ad3012cc3f5216c2baeb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 21:14:30 +0900 Subject: Add multiline case for test against map(f).unwrap_or(None) --- tests/ui/methods.rs | 10 +- tests/ui/methods.stderr | 481 +++++++++++++++++++++++++----------------------- 2 files changed, 260 insertions(+), 231 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 20372f7590a..3395280ba05 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -108,8 +108,16 @@ fn option_methods() { .unwrap_or({ 0 }); - // map(f).unwrap_or(None) case + // single line `map(f).unwrap_or(None)` case let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); + // multiline `map(f).unwrap_or(None)` cases + let _ = opt.map(|x| { + Some(x + 1) + } + ).unwrap_or(None); + let _ = opt + .map(|x| Some(x + 1)) + .unwrap_or(None); // macro case let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 0e8c729d6e6..a1bc219eaf8 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -142,705 +142,726 @@ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` -error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead +error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/methods.rs:114:13 + | +114 | let _ = opt.map(|x| { + | _____________^ +115 | | Some(x + 1) +116 | | } +117 | | ).unwrap_or(None); + | |_____________________^ + +error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead --> $DIR/methods.rs:118:13 | -118 | let _ = opt.map(|x| x + 1) +118 | let _ = opt + | _____________^ +119 | | .map(|x| Some(x + 1)) +120 | | .unwrap_or(None); + | |________________________^ + | + = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` + +error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead + --> $DIR/methods.rs:126:13 + | +126 | let _ = opt.map(|x| x + 1) | _____________^ -119 | | -120 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +127 | | +128 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:122:13 + --> $DIR/methods.rs:130:13 | -122 | let _ = opt.map(|x| { +130 | let _ = opt.map(|x| { | _____________^ -123 | | x + 1 -124 | | } -125 | | ).unwrap_or_else(|| 0); +131 | | x + 1 +132 | | } +133 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:126:13 + --> $DIR/methods.rs:134:13 | -126 | let _ = opt.map(|x| x + 1) +134 | let _ = opt.map(|x| x + 1) | _____________^ -127 | | .unwrap_or_else(|| -128 | | 0 -129 | | ); +135 | | .unwrap_or_else(|| +136 | | 0 +137 | | ); | |_________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:155:24 + --> $DIR/methods.rs:163:24 | -155 | fn filter(self) -> IteratorFalsePositives { +163 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:159:22 + --> $DIR/methods.rs:167:22 | -159 | fn next(self) -> IteratorFalsePositives { +167 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:179:32 + --> $DIR/methods.rs:187:32 | -179 | fn skip(self, _: usize) -> IteratorFalsePositives { +187 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:198:13 + --> $DIR/methods.rs:206:13 | -198 | let _ = v.iter().filter(|&x| *x < 0).next(); +206 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:201:13 + --> $DIR/methods.rs:209:13 | -201 | let _ = v.iter().filter(|&x| { +209 | let _ = v.iter().filter(|&x| { | _____________^ -202 | | *x < 0 -203 | | } -204 | | ).next(); +210 | | *x < 0 +211 | | } +212 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:216:13 + --> $DIR/methods.rs:224:13 | -216 | let _ = v.iter().find(|&x| *x < 0).is_some(); +224 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:219:13 + --> $DIR/methods.rs:227:13 | -219 | let _ = v.iter().find(|&x| { +227 | let _ = v.iter().find(|&x| { | _____________^ -220 | | *x < 0 -221 | | } -222 | | ).is_some(); +228 | | *x < 0 +229 | | } +230 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:225:13 + --> $DIR/methods.rs:233:13 | -225 | let _ = v.iter().position(|&x| x < 0).is_some(); +233 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:228:13 + --> $DIR/methods.rs:236:13 | -228 | let _ = v.iter().position(|&x| { +236 | let _ = v.iter().position(|&x| { | _____________^ -229 | | x < 0 -230 | | } -231 | | ).is_some(); +237 | | x < 0 +238 | | } +239 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:234:13 + --> $DIR/methods.rs:242:13 | -234 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +242 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:237:13 + --> $DIR/methods.rs:245:13 | -237 | let _ = v.iter().rposition(|&x| { +245 | let _ = v.iter().rposition(|&x| { | _____________^ -238 | | x < 0 -239 | | } -240 | | ).is_some(); +246 | | x < 0 +247 | | } +248 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:254:21 + --> $DIR/methods.rs:262:21 | -254 | fn new() -> Foo { Foo } +262 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:272:5 + --> $DIR/methods.rs:280:5 | -272 | with_constructor.unwrap_or(make()); +280 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:275:5 + --> $DIR/methods.rs:283:5 | -275 | with_new.unwrap_or(Vec::new()); +283 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:278:5 + --> $DIR/methods.rs:286:5 | -278 | with_const_args.unwrap_or(Vec::with_capacity(12)); +286 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:281:5 + --> $DIR/methods.rs:289:5 | -281 | with_err.unwrap_or(make()); +289 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:284:5 + --> $DIR/methods.rs:292:5 | -284 | with_err_args.unwrap_or(Vec::with_capacity(12)); +292 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:287:5 + --> $DIR/methods.rs:295:5 | -287 | with_default_trait.unwrap_or(Default::default()); +295 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:290:5 + --> $DIR/methods.rs:298:5 | -290 | with_default_type.unwrap_or(u64::default()); +298 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:293:5 + --> $DIR/methods.rs:301:5 | -293 | with_vec.unwrap_or(vec![]); +301 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:298:5 + --> $DIR/methods.rs:306:5 | -298 | without_default.unwrap_or(Foo::new()); +306 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:301:5 + --> $DIR/methods.rs:309:5 | -301 | map.entry(42).or_insert(String::new()); +309 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:304:5 + --> $DIR/methods.rs:312:5 | -304 | btree.entry(42).or_insert(String::new()); +312 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:13 + --> $DIR/methods.rs:315:13 | -307 | let _ = stringy.unwrap_or("".to_owned()); +315 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:318:23 + --> $DIR/methods.rs:326:23 | -318 | let bad_vec = some_vec.iter().nth(3); +326 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:319:26 + --> $DIR/methods.rs:327:26 | -319 | let bad_slice = &some_vec[..].iter().nth(3); +327 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:320:31 + --> $DIR/methods.rs:328:31 | -320 | let bad_boxed_slice = boxed_slice.iter().nth(3); +328 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:321:29 + --> $DIR/methods.rs:329:29 | -321 | let bad_vec_deque = some_vec_deque.iter().nth(3); +329 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:326:23 + --> $DIR/methods.rs:334:23 | -326 | let bad_vec = some_vec.iter_mut().nth(3); +334 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:329:26 + --> $DIR/methods.rs:337:26 | -329 | let bad_slice = &some_vec[..].iter_mut().nth(3); +337 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:332:29 + --> $DIR/methods.rs:340:29 | -332 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +340 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:344:13 + --> $DIR/methods.rs:352:13 | -344 | let _ = some_vec.iter().skip(42).next(); +352 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:345:13 + --> $DIR/methods.rs:353:13 | -345 | let _ = some_vec.iter().cycle().skip(42).next(); +353 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:346:13 + --> $DIR/methods.rs:354:13 | -346 | let _ = (1..10).skip(10).next(); +354 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:347:14 + --> $DIR/methods.rs:355:14 | -347 | let _ = &some_vec[..].iter().skip(3).next(); +355 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:373:17 + --> $DIR/methods.rs:381:17 | -373 | let _ = boxed_slice.get(1).unwrap(); +381 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:374:17 + --> $DIR/methods.rs:382:17 | -374 | let _ = some_slice.get(0).unwrap(); +382 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:375:17 + --> $DIR/methods.rs:383:17 | -375 | let _ = some_vec.get(0).unwrap(); +383 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:376:17 + --> $DIR/methods.rs:384:17 | -376 | let _ = some_vecdeque.get(0).unwrap(); +384 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:377:17 + --> $DIR/methods.rs:385:17 | -377 | let _ = some_hashmap.get(&1).unwrap(); +385 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:378:17 + --> $DIR/methods.rs:386:17 | -378 | let _ = some_btreemap.get(&1).unwrap(); +386 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:383:10 + --> $DIR/methods.rs:391:10 | -383 | *boxed_slice.get_mut(0).unwrap() = 1; +391 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:384:10 + --> $DIR/methods.rs:392:10 | -384 | *some_slice.get_mut(0).unwrap() = 1; +392 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:385:10 + --> $DIR/methods.rs:393:10 | -385 | *some_vec.get_mut(0).unwrap() = 1; +393 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:386:10 + --> $DIR/methods.rs:394:10 | -386 | *some_vecdeque.get_mut(0).unwrap() = 1; +394 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:400:13 + --> $DIR/methods.rs:408:13 | -400 | let _ = opt.unwrap(); +408 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:403:13 + --> $DIR/methods.rs:411:13 | -403 | let _ = res.unwrap(); +411 | let _ = res.unwrap(); | ^^^^^^^^^^^^ | = note: `-D result-unwrap-used` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:405:5 + --> $DIR/methods.rs:413:5 | -405 | res.ok().expect("disaster!"); +413 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:411:5 + --> $DIR/methods.rs:419:5 | -411 | res3.ok().expect("whoof"); +419 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:413:5 + --> $DIR/methods.rs:421:5 | -413 | res4.ok().expect("argh"); +421 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:415:5 + --> $DIR/methods.rs:423:5 | -415 | res5.ok().expect("oops"); +423 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:417:5 + --> $DIR/methods.rs:425:5 | -417 | res6.ok().expect("meh"); +425 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `starts_with` method - --> $DIR/methods.rs:429:5 + --> $DIR/methods.rs:437:5 | -429 | "".chars().next() == Some(' '); +437 | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | = note: `-D chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/methods.rs:430:5 + --> $DIR/methods.rs:438:5 | -430 | Some(' ') != "".chars().next(); +438 | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:439:5 + --> $DIR/methods.rs:447:5 | -439 | s.extend(abc.chars()); +447 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:442:5 + --> $DIR/methods.rs:450:5 | -442 | s.extend("abc".chars()); +450 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:445:5 + --> $DIR/methods.rs:453:5 | -445 | s.extend(def.chars()); +453 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:456:5 + --> $DIR/methods.rs:464:5 | -456 | 42.clone(); +464 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:460:5 + --> $DIR/methods.rs:468:5 | -460 | (&42).clone(); +468 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:470:5 + --> $DIR/methods.rs:478:5 | -470 | rc.clone(); +478 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` | = note: `-D clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:473:5 + --> $DIR/methods.rs:481:5 | -473 | arc.clone(); +481 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:476:5 + --> $DIR/methods.rs:484:5 | -476 | rcweak.clone(); +484 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:479:5 + --> $DIR/methods.rs:487:5 | -479 | arc_weak.clone(); +487 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:486:5 + --> $DIR/methods.rs:494:5 | -486 | t.clone(); +494 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:488:5 + --> $DIR/methods.rs:496:5 | -488 | Some(t).clone(); +496 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:494:22 + --> $DIR/methods.rs:502:22 | -494 | let z: &Vec<_> = y.clone(); +502 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` | = note: `-D clone-double-ref` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:501:13 + --> $DIR/methods.rs:509:13 | -501 | x.split("x"); +509 | x.split("x"); | --------^^^- help: try using a char instead: `x.split('x')` | = note: `-D single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:518:16 + --> $DIR/methods.rs:526:16 | -518 | x.contains("x"); +526 | x.contains("x"); | -----------^^^- help: try using a char instead: `x.contains('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:519:19 + --> $DIR/methods.rs:527:19 | -519 | x.starts_with("x"); +527 | x.starts_with("x"); | --------------^^^- help: try using a char instead: `x.starts_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:520:17 + --> $DIR/methods.rs:528:17 | -520 | x.ends_with("x"); +528 | x.ends_with("x"); | ------------^^^- help: try using a char instead: `x.ends_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:521:12 + --> $DIR/methods.rs:529:12 | -521 | x.find("x"); +529 | x.find("x"); | -------^^^- help: try using a char instead: `x.find('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:522:13 + --> $DIR/methods.rs:530:13 | -522 | x.rfind("x"); +530 | x.rfind("x"); | --------^^^- help: try using a char instead: `x.rfind('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:523:14 + --> $DIR/methods.rs:531:14 | -523 | x.rsplit("x"); +531 | x.rsplit("x"); | ---------^^^- help: try using a char instead: `x.rsplit('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:524:24 + --> $DIR/methods.rs:532:24 | -524 | x.split_terminator("x"); +532 | x.split_terminator("x"); | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:525:25 + --> $DIR/methods.rs:533:25 | -525 | x.rsplit_terminator("x"); +533 | x.rsplit_terminator("x"); | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:526:17 + --> $DIR/methods.rs:534:17 | -526 | x.splitn(0, "x"); +534 | x.splitn(0, "x"); | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:527:18 + --> $DIR/methods.rs:535:18 | -527 | x.rsplitn(0, "x"); +535 | x.rsplitn(0, "x"); | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:528:15 + --> $DIR/methods.rs:536:15 | -528 | x.matches("x"); +536 | x.matches("x"); | ----------^^^- help: try using a char instead: `x.matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:529:16 + --> $DIR/methods.rs:537:16 | -529 | x.rmatches("x"); +537 | x.rmatches("x"); | -----------^^^- help: try using a char instead: `x.rmatches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:530:21 + --> $DIR/methods.rs:538:21 | -530 | x.match_indices("x"); +538 | x.match_indices("x"); | ----------------^^^- help: try using a char instead: `x.match_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:531:22 + --> $DIR/methods.rs:539:22 | -531 | x.rmatch_indices("x"); +539 | x.rmatch_indices("x"); | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:532:25 + --> $DIR/methods.rs:540:25 | -532 | x.trim_left_matches("x"); +540 | x.trim_left_matches("x"); | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:533:26 + --> $DIR/methods.rs:541:26 | -533 | x.trim_right_matches("x"); +541 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:543:5 + --> $DIR/methods.rs:551:5 | -543 | CString::new("foo").unwrap().as_ptr(); +551 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:543:5 + --> $DIR/methods.rs:551:5 | -543 | CString::new("foo").unwrap().as_ptr(); +551 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:548:27 + --> $DIR/methods.rs:556:27 | -548 | let v2 : Vec = v.iter().cloned().collect(); +556 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/methods.rs:555:8 + --> $DIR/methods.rs:563:8 | -555 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:555:8 + --> $DIR/methods.rs:563:8 | -555 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:558:8 + --> $DIR/methods.rs:566:8 | -558 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | = note: `-D chars-last-cmp` implied by `-D warnings` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:558:8 + --> $DIR/methods.rs:566:8 | -558 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:561:8 + --> $DIR/methods.rs:569:8 | -561 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:561:8 + --> $DIR/methods.rs:569:8 | -561 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `starts_with` method - --> $DIR/methods.rs:564:8 + --> $DIR/methods.rs:572:8 | -564 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:564:8 + --> $DIR/methods.rs:572:8 | -564 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:567:8 + --> $DIR/methods.rs:575:8 | -567 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:567:8 + --> $DIR/methods.rs:575:8 | -567 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:570:8 + --> $DIR/methods.rs:578:8 | -570 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:570:8 + --> $DIR/methods.rs:578:8 | -570 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should use the `ends_with` method - --> $DIR/methods.rs:577:5 + --> $DIR/methods.rs:585:5 | -577 | "".chars().last() == Some(' '); +585 | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:578:5 + --> $DIR/methods.rs:586:5 | -578 | Some(' ') != "".chars().last(); +586 | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:579:5 + --> $DIR/methods.rs:587:5 | -579 | "".chars().next_back() == Some(' '); +587 | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/methods.rs:580:5 + --> $DIR/methods.rs:588:5 | -580 | Some(' ') != "".chars().next_back(); +588 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` -- cgit 1.4.1-3-g733a5 From dcaaab3801e095283706dc8d97ff69833aebe732 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Sat, 7 Oct 2017 23:32:09 +0100 Subject: Add a test with a struct containing a String. --- tests/ui/no_effect.rs | 7 +- tests/ui/no_effect.stderr | 204 ++++++++++++++++++++++++---------------------- 2 files changed, 114 insertions(+), 97 deletions(-) diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 1b7da6496bf..a037ac3cf0e 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -37,7 +37,9 @@ enum DropEnum { impl Drop for DropEnum { fn drop(&mut self) {} } - +struct FooString { + s: String, +} union Union { a: u8, b: f64, @@ -79,6 +81,8 @@ fn main() { [42; 55][13]; let mut x = 0; || x += 5; + let s: String = "foo".into(); + FooString { s: s }; // Do not warn get_number(); @@ -108,6 +112,7 @@ fn main() { [get_number(); 55]; [42; 55][get_number() as usize]; {get_number()}; + FooString { s: String::from("blah"), }; // Do not warn DropTuple(get_number()); diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 9a161ce9643..0d8d6624a83 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,268 +1,280 @@ error: statement with no effect - --> $DIR/no_effect.rs:56:5 + --> $DIR/no_effect.rs:58:5 | -56 | 0; +58 | 0; | ^^ | = note: `-D no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:57:5 + --> $DIR/no_effect.rs:59:5 | -57 | s2; +59 | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:58:5 + --> $DIR/no_effect.rs:60:5 | -58 | Unit; +60 | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:59:5 + --> $DIR/no_effect.rs:61:5 | -59 | Tuple(0); +61 | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:60:5 + --> $DIR/no_effect.rs:62:5 | -60 | Struct { field: 0 }; +62 | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:61:5 + --> $DIR/no_effect.rs:63:5 | -61 | Struct { ..s }; +63 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:62:5 + --> $DIR/no_effect.rs:64:5 | -62 | Union { a: 0 }; +64 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:63:5 + --> $DIR/no_effect.rs:65:5 | -63 | Enum::Tuple(0); +65 | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:64:5 + --> $DIR/no_effect.rs:66:5 | -64 | Enum::Struct { field: 0 }; +66 | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:65:5 + --> $DIR/no_effect.rs:67:5 | -65 | 5 + 6; +67 | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:66:5 + --> $DIR/no_effect.rs:68:5 | -66 | *&42; +68 | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:67:5 + --> $DIR/no_effect.rs:69:5 | -67 | &6; +69 | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:68:5 + --> $DIR/no_effect.rs:70:5 | -68 | (5, 6, 7); +70 | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:69:5 + --> $DIR/no_effect.rs:71:5 | -69 | box 42; +71 | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:70:5 + --> $DIR/no_effect.rs:72:5 | -70 | ..; +72 | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:73:5 | -71 | 5..; +73 | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:74:5 | -72 | ..5; +74 | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:73:5 + --> $DIR/no_effect.rs:75:5 | -73 | 5..6; +75 | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:76:5 | -74 | 5..=6; +76 | 5..=6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:77:5 | -75 | [42, 55]; +77 | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:78:5 | -76 | [42, 55][1]; +78 | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:79:5 | -77 | (42, 55).1; +79 | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:80:5 | -78 | [42; 55]; +80 | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:81:5 | -79 | [42; 55][13]; +81 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:83:5 | -81 | || x += 5; +83 | || x += 5; | ^^^^^^^^^^ +error: statement with no effect + --> $DIR/no_effect.rs:85:5 + | +85 | FooString { s: s }; + | ^^^^^^^^^^^^^^^^^^^ + error: statement can be reduced - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:96:5 | -92 | Tuple(get_number()); +96 | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | = note: `-D unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:97:5 | -93 | Struct { field: get_number() }; +97 | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:98:5 | -94 | Struct { ..get_struct() }; +98 | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:99:5 | -95 | Enum::Tuple(get_number()); +99 | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:96:5 - | -96 | Enum::Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:100:5 + | +100 | Enum::Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:97:5 - | -97 | 5 + get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` + --> $DIR/no_effect.rs:101:5 + | +101 | 5 + get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:98:5 - | -98 | *&get_number(); - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:102:5 + | +102 | *&get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:99:5 - | -99 | &get_number(); - | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:103:5 + | +103 | &get_number(); + | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:104:5 | -100 | (5, 6, get_number()); +104 | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:105:5 | -101 | box get_number(); +105 | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:106:5 | -102 | get_number()..; +106 | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:107:5 | -103 | ..get_number(); +107 | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:108:5 | -104 | 5..get_number(); +108 | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:109:5 | -105 | [42, get_number()]; +109 | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:110:5 | -106 | [42, 55][get_number() as usize]; +110 | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:111:5 | -107 | (42, get_number()).1; +111 | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:112:5 | -108 | [get_number(); 55]; +112 | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:113:5 | -109 | [42; 55][get_number() as usize]; +113 | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:114:5 | -110 | {get_number()}; +114 | {get_number()}; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +error: statement can be reduced + --> $DIR/no_effect.rs:115:5 + | +115 | FooString { s: String::from("blah"), }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` + -- cgit 1.4.1-3-g733a5 From bf97cd0338aa0de4d4e3946f7ccb68a2ac19193c Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 8 Oct 2017 10:23:41 +0900 Subject: Reduce false-positives for needless_pass_by_value lint Excluding a type whose reference also fulfills the trait bound. --- clippy_lints/src/needless_pass_by_value.rs | 110 ++++++++++++++++------------- tests/ui/needless_pass_by_value.rs | 19 ++++- tests/ui/needless_pass_by_value.stderr | 56 ++++++++------- 3 files changed, 108 insertions(+), 77 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ccdb3c179cc..c16be95587b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; -use rustc::ty::{self, TypeFoldable}; +use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; @@ -73,18 +73,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { _ => return, } - // Allows these to be passed by value. - let fn_trait = need!(cx.tcx.lang_items().fn_trait()); - let asref_trait = need!(get_trait_def_id(cx, &paths::ASREF_TRAIT)); let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); + let fn_trait = need!(cx.tcx.lang_items().fn_trait()); + + let sized_trait = need!(cx.tcx.lang_items().sized_trait()); let fn_def_id = cx.tcx.hir.local_def_id(node_id); - let preds: Vec = { - traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) - .filter(|p| !p.is_global()) - .collect() - }; + let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) + .filter(|p| !p.is_global()) + .collect::>(); + let preds = preds + .iter() + .filter_map(|pred| if let ty::Predicate::Trait(ref poly_trait_ref) = *pred { + Some(poly_trait_ref.skip_binder()) + } else { + None + }) + .filter(|t| t.def_id() != sized_trait && !t.has_escaping_regions()) + .collect::>(); // Collect moved variables and spans which will need dereferencings from the // function body. @@ -103,40 +110,44 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { - // Determines whether `ty` implements `Borrow` (U != ty) specifically. - // This is needed due to the `Borrow for T` blanket impl. - let implements_borrow_trait = preds - .iter() - .filter_map(|pred| if let ty::Predicate::Trait(ref poly_trait_ref) = *pred { - Some(poly_trait_ref.skip_binder()) - } else { - None - }) - .filter(|tpred| tpred.def_id() == borrow_trait && tpred.self_ty() == ty) - .any(|tpred| { - tpred - .input_types() - .nth(1) - .expect("Borrow trait must have an parameter") != ty - }); + // * Exclude a type that is specifically bounded by `Borrow`. + // * Exclude a type whose reference also fulfills its bound. + // (e.g. `std::borrow::Borrow`, `serde::Serialize`) + let (implements_borrow_trait, all_borrowable_trait) = { + let preds = preds + .iter() + .filter(|t| t.self_ty() == ty) + .collect::>(); + + ( + preds.iter().any(|t| t.def_id() == borrow_trait), + !preds.is_empty() && preds.iter().all(|t| { + implements_trait( + cx, + cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), + t.def_id(), + &t.input_types().skip(1).collect::>(), + ) + }), + ) + }; if_let_chain! {[ !is_self(arg), !ty.is_mutable_pointer(), !is_copy(cx, ty), !implements_trait(cx, ty, fn_trait, &[]), - !implements_trait(cx, ty, asref_trait, &[]), !implements_borrow_trait, + !all_borrowable_trait, let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node, !moved_vars.contains(&canonical_id), ], { - // Note: `toplevel_ref_arg` warns if `BindByRef` if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { continue; } - // Suggestion logic + // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder| { let deref_span = spans_need_deref.get(&canonical_id); if_let_chain! {[ @@ -152,33 +163,37 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { "consider changing the type to", slice_ty); assert!(deref_span.is_none()); - return; // `Vec` and `String` cannot be destructured - no need for `*` suggestion + return; // `Vec` cannot be destructured - no need for `*` suggestion }} if match_type(cx, ty, &paths::STRING) { - db.span_suggestion(input.span, - "consider changing the type to", - "&str".to_string()); + db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); assert!(deref_span.is_none()); - return; + return; // ditto } let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; // Suggests adding `*` to dereference the added reference. if let Some(deref_span) = deref_span { - spans.extend(deref_span.iter().cloned() - .map(|span| (span, format!("*{}", snippet(cx, span, ""))))); + spans.extend( + deref_span + .iter() + .cloned() + .map(|span| (span, format!("*{}", snippet(cx, span, "")))), + ); spans.sort_by_key(|&(span, _)| span); } multispan_sugg(db, "consider taking a reference instead".to_string(), spans); }; - span_lint_and_then(cx, - NEEDLESS_PASS_BY_VALUE, - input.span, - "this argument is passed by value, but not consumed in the function body", - sugg); + span_lint_and_then( + cx, + NEEDLESS_PASS_BY_VALUE, + input.span, + "this argument is passed by value, but not consumed in the function body", + sugg, + ); }} } } @@ -188,8 +203,7 @@ struct MovedVariablesCtxt<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, moved_vars: HashSet, /// Spans which need to be prefixed with `*` for dereferencing the - /// suggested additional - /// reference. + /// suggested additional reference. spans_need_deref: HashMap>, } @@ -213,9 +227,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) { let cmt = unwrap_downcast_or_interior(cmt); - if_let_chain! {[ - let mc::Categorization::Local(vid) = cmt.cat, - ], { + if let mc::Categorization::Local(vid) = cmt.cat { let mut id = matched_pat.id; loop { let parent = self.cx.tcx.hir.get_parent_node(id); @@ -235,7 +247,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { .or_insert_with(HashSet::new) .insert(c.span); } - } + }, map::Node::NodeStmt(s) => { // `let = x;` @@ -251,13 +263,13 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { .map(|e| e.span) .expect("`let` stmt without init aren't caught by match_pat")); }} - } + }, - _ => {} + _ => {}, } } } - }} + } } } diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 6218bfb0920..59167683595 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -4,6 +4,9 @@ #![warn(needless_pass_by_value)] #![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names)] +use std::borrow::Borrow; +use std::convert::AsRef; + // `v` should be warned // `w`, `x` and `y` are allowed (moved or mutated) fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { @@ -25,10 +28,11 @@ fn bar(x: String, y: Wrapper) { assert_eq!(y.0.len(), 42); } -// U implements `Borrow`, but should be warned correctly -fn test_borrow_trait, U>(t: T, u: U) { +// V implements `Borrow`, but should be warned correctly +fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { println!("{}", t.borrow()); - consume(&u); + println!("{}", u.as_ref()); + consume(&v); } // ok @@ -59,4 +63,13 @@ fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { println!("{}", t); } +trait Foo {} + +// `S: Serialize` can be passed by value +trait Serialize {} +impl<'a, T> Serialize for &'a T where T: Serialize {} +impl Serialize for i32 {} + +fn test_blanket_ref(_foo: T, _serializable: S) {} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index c081574127a..0968b68d82f 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,58 +1,64 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:9:23 - | -9 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { - | ^^^^^^ help: consider changing the type to: `&[T]` - | - = note: `-D needless-pass-by-value` implied by `-D warnings` + --> $DIR/needless_pass_by_value.rs:12:23 + | +12 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { + | ^^^^^^ help: consider changing the type to: `&[T]` + | + = note: `-D needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:23:11 + --> $DIR/needless_pass_by_value.rs:26:11 | -23 | fn bar(x: String, y: Wrapper) { +26 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:23:22 + --> $DIR/needless_pass_by_value.rs:26:22 | -23 | fn bar(x: String, y: Wrapper) { +26 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:29:63 + --> $DIR/needless_pass_by_value.rs:32:71 | -29 | fn test_borrow_trait, U>(t: T, u: U) { - | ^ help: consider taking a reference instead: `&U` +32 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { + | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:40:18 + --> $DIR/needless_pass_by_value.rs:44:18 | -40 | fn test_match(x: Option>, y: Option>) { +44 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ | help: consider taking a reference instead | -40 | fn test_match(x: &Option>, y: Option>) { -41 | match *x { +44 | fn test_match(x: &Option>, y: Option>) { +45 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:53:24 + --> $DIR/needless_pass_by_value.rs:57:24 | -53 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:53:36 + --> $DIR/needless_pass_by_value.rs:57:36 | -53 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ | help: consider taking a reference instead | -53 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -54 | let Wrapper(s) = z; // moved -55 | let Wrapper(ref t) = *y; // not moved -56 | let Wrapper(_) = *y; // still not moved +57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +58 | let Wrapper(s) = z; // moved +59 | let Wrapper(ref t) = *y; // not moved +60 | let Wrapper(_) = *y; // still not moved + | + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:73:49 | +73 | fn test_blanket_ref(_foo: T, _serializable: S) {} + | ^ help: consider taking a reference instead: `&T` -- cgit 1.4.1-3-g733a5 From 2be62451799456eb2b7c07aa173b800264e41bdb Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 8 Oct 2017 17:51:44 +0900 Subject: Duplicate ptr_arg's suggestion logic --- clippy_lints/src/needless_pass_by_value.rs | 51 +++++++++++++++--- clippy_lints/src/ptr.rs | 71 ++----------------------- clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/utils/ptr.rs | 83 ++++++++++++++++++++++++++++++ tests/ui/needless_pass_by_value.rs | 7 +++ tests/ui/needless_pass_by_value.stderr | 42 +++++++++++++++ 6 files changed, 183 insertions(+), 72 deletions(-) create mode 100644 clippy_lints/src/utils/ptr.rs diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c16be95587b..a995593e8e5 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -9,8 +9,10 @@ use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; use utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, - snippet, span_lint_and_then}; + snippet, snippet_opt, span_lint_and_then}; +use utils::ptr::get_spans; use std::collections::{HashMap, HashSet}; +use std::borrow::Cow; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its @@ -109,7 +111,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); - for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { + for (idx, ((input, &ty), arg)) in decl.inputs + .iter() + .zip(fn_sig.inputs()) + .zip(&body.arguments) + .enumerate() + { // * Exclude a type that is specifically bounded by `Borrow`. // * Exclude a type whose reference also fulfills its bound. // (e.g. `std::borrow::Borrow`, `serde::Serialize`) @@ -152,6 +159,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let deref_span = spans_need_deref.get(&canonical_id); if_let_chain! {[ match_type(cx, ty, &paths::VEC), + let Some(clone_spans) = + get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]), let TyPath(QPath::Resolved(_, ref path)) = input.node, let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") @@ -162,14 +171,44 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { db.span_suggestion(input.span, "consider changing the type to", slice_ty); + + for (span, suggestion) in clone_spans { + db.span_suggestion( + span, + &snippet_opt(cx, span) + .map_or( + "change the call to".into(), + |x| Cow::from(format!("change `{}` to", x)), + ), + suggestion.into() + ); + } + + // cannot be destructured, no need for `*` suggestion assert!(deref_span.is_none()); - return; // `Vec` cannot be destructured - no need for `*` suggestion + return; }} if match_type(cx, ty, &paths::STRING) { - db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); - assert!(deref_span.is_none()); - return; // ditto + if let Some(clone_spans) = + get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { + db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); + + for (span, suggestion) in clone_spans { + db.span_suggestion( + span, + &snippet_opt(cx, span) + .map_or( + "change the call to".into(), + |x| Cow::from(format!("change `{}` to", x)) + ), + suggestion.into(), + ); + } + + assert!(deref_span.is_none()); + return; + } } let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 03c94cbf3fb..8f42750e19b 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -2,16 +2,15 @@ use std::borrow::Cow; use rustc::hir::*; -use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::map::NodeItem; use rustc::lint::*; use rustc::ty; -use syntax::ast::{Name, NodeId}; +use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{get_pat_name, match_qpath, match_type, match_var, paths, - snippet, snippet_opt, span_lint, span_lint_and_then, +use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; +use utils::ptr::get_spans; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless the references are mutable. It will also suggest you @@ -164,7 +163,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< ], { ty_snippet = snippet_opt(cx, parameters.types[0].span); }); - if let Ok(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { + if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { span_lint_and_then( cx, PTR_ARG, @@ -187,7 +186,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< ); } } else if match_type(cx, ty, &paths::STRING) { - if let Ok(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { + if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { span_lint_and_then( cx, PTR_ARG, @@ -234,66 +233,6 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< } } -fn get_spans(cx: &LateContext, opt_body_id: Option, idx: usize, replacements: &'static [(&'static str, &'static str)]) -> Result)>, ()> { - if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { - get_binding_name(&body.arguments[idx]).map_or_else(|| Ok(vec![]), - |name| extract_clone_suggestions(cx, name, replacements, body)) - } else { - Ok(vec![]) - } -} - -fn extract_clone_suggestions<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, name: Name, replace: &'static [(&'static str, &'static str)], body: &'tcx Body) -> Result)>, ()> { - let mut visitor = PtrCloneVisitor { - cx, - name, - replace, - spans: vec![], - abort: false, - }; - visitor.visit_body(body); - if visitor.abort { Err(()) } else { Ok(visitor.spans) } -} - -struct PtrCloneVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, - name: Name, - replace: &'static [(&'static str, &'static str)], - spans: Vec<(Span, Cow<'static, str>)>, - abort: bool, -} - -impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr) { - if self.abort { return; } - if let ExprMethodCall(ref seg, _, ref args) = expr.node { - if args.len() == 1 && match_var(&args[0], self.name) { - if seg.name == "capacity" { - self.abort = true; - return; - } - for &(fn_name, suffix) in self.replace { - if seg.name == fn_name { - self.spans.push((expr.span, snippet(self.cx, args[0].span, "_") + suffix)); - return; - } - } - } - return; - } - walk_expr(self, expr); - } - - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - -} - -fn get_binding_name(arg: &Arg) -> Option { - get_pat_name(&arg.pat) -} - fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> { if let Ty_::TyRptr(ref lt, ref m) = ty.node { Some((lt, m.mutbl, ty.span)) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ec0521ce4f2..07caf07ac8d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -32,6 +32,7 @@ pub mod sugg; pub mod inspector; pub mod internal_lints; pub mod author; +pub mod ptr; pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs new file mode 100644 index 00000000000..7782fb8bc76 --- /dev/null +++ b/clippy_lints/src/utils/ptr.rs @@ -0,0 +1,83 @@ +use std::borrow::Cow; +use rustc::hir::*; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::lint::LateContext; +use syntax::ast::Name; +use syntax::codemap::Span; +use utils::{get_pat_name, match_var, snippet}; + +pub fn get_spans( + cx: &LateContext, + opt_body_id: Option, + idx: usize, + replacements: &'static [(&'static str, &'static str)], +) -> Option)>> { + if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { + get_binding_name(&body.arguments[idx]) + .map_or_else(|| Some(vec![]), |name| extract_clone_suggestions(cx, name, replacements, body)) + } else { + Some(vec![]) + } +} + +fn extract_clone_suggestions<'a, 'tcx: 'a>( + cx: &LateContext<'a, 'tcx>, + name: Name, + replace: &'static [(&'static str, &'static str)], + body: &'tcx Body, +) -> Option)>> { + let mut visitor = PtrCloneVisitor { + cx, + name, + replace, + spans: vec![], + abort: false, + }; + visitor.visit_body(body); + if visitor.abort { + None + } else { + Some(visitor.spans) + } +} + +struct PtrCloneVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + name: Name, + replace: &'static [(&'static str, &'static str)], + spans: Vec<(Span, Cow<'static, str>)>, + abort: bool, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if self.abort { + return; + } + if let ExprMethodCall(ref seg, _, ref args) = expr.node { + if args.len() == 1 && match_var(&args[0], self.name) { + if seg.name == "capacity" { + self.abort = true; + return; + } + for &(fn_name, suffix) in self.replace { + if seg.name == fn_name { + self.spans + .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix)); + return; + } + } + } + return; + } + walk_expr(self, expr); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +fn get_binding_name(arg: &Arg) -> Option { + get_pat_name(&arg.pat) +} diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 59167683595..ac37b0bdda1 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -72,4 +72,11 @@ impl Serialize for i32 {} fn test_blanket_ref(_foo: T, _serializable: S) {} +fn issue_2114(s: String, t: String, u: Vec, v: Vec) { + s.capacity(); + let _ = t.clone(); + u.capacity(); + let _ = v.clone(); +} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 0968b68d82f..f23b0714c59 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -62,3 +62,45 @@ error: this argument is passed by value, but not consumed in the function body 73 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:75:18 + | +75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { + | ^^^^^^ help: consider taking a reference instead: `&String` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:75:29 + | +75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { + | ^^^^^^ + | +help: consider changing the type to + | +75 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { + | ^^^^ +help: change `t.clone()` to + | +77 | let _ = t.to_string(); + | ^^^^^^^^^^^^^ + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:75:40 + | +75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { + | ^^^^^^^^ help: consider taking a reference instead: `&Vec` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:75:53 + | +75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { + | ^^^^^^^^ + | +help: consider changing the type to + | +75 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { + | ^^^^^^ +help: change `v.clone()` to + | +79 | let _ = v.to_owned(); + | ^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From fdc9a649fffa5662571b27bb2353f55dca53277c Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 8 Oct 2017 18:04:45 +0900 Subject: Exclude Fn traits --- clippy_lints/src/needless_pass_by_value.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index a995593e8e5..29598a20f0d 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -75,8 +75,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { _ => return, } + // Allow `Borrow` or functions to be taken by value let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); - let fn_trait = need!(cx.tcx.lang_items().fn_trait()); + let fn_traits = [ + need!(cx.tcx.lang_items().fn_trait()), + need!(cx.tcx.lang_items().fn_once_trait()), + need!(cx.tcx.lang_items().fn_mut_trait()), + ]; let sized_trait = need!(cx.tcx.lang_items().sized_trait()); @@ -119,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { { // * Exclude a type that is specifically bounded by `Borrow`. // * Exclude a type whose reference also fulfills its bound. - // (e.g. `std::borrow::Borrow`, `serde::Serialize`) + // (e.g. `std::convert::AsRef`, `serde::Serialize`) let (implements_borrow_trait, all_borrowable_trait) = { let preds = preds .iter() @@ -143,7 +148,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { !is_self(arg), !ty.is_mutable_pointer(), !is_copy(cx, ty), - !implements_trait(cx, ty, fn_trait, &[]), + !fn_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])), !implements_borrow_trait, !all_borrowable_trait, -- cgit 1.4.1-3-g733a5 From ff25013384bbd19944e0a9a91b0b9c4a4a92e3c7 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sat, 7 Oct 2017 13:54:40 +0200 Subject: Fix manual testing command in docs --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef95a50dcef..631e9663db4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,7 +77,7 @@ the output looks as you expect with `git diff`. Commit all `*.stderr` files, too Manually testing against an example file is useful if you have added some `println!`s and test suite output becomes unreadable. To try clippy with your -local modifications, run `cargo run -- -L ./target/debug input.rs` from the +local modifications, run `cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. Your test file, here `input.rs`, needs to have clippy enabled as a plugin: -- cgit 1.4.1-3-g733a5 From d8e01237e2e173503f0339d4fa093bf7cb695c7e Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sat, 7 Oct 2017 16:56:45 +0200 Subject: Lint range_plus_one and range_minus_one (closes #329) --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/ranges.rs | 116 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d4af88d5fed..0f27a74ac8e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -263,7 +263,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box loops::Pass); reg.register_late_lint_pass(box lifetimes::LifetimePass); reg.register_late_lint_pass(box entry::HashMapLint); - reg.register_late_lint_pass(box ranges::StepByZero); + reg.register_late_lint_pass(box ranges::Pass); reg.register_late_lint_pass(box types::CastPass); reg.register_late_lint_pass(box types::TypeComplexityPass::new(conf.type_complexity_threshold)); reg.register_late_lint_pass(box matches::MatchPass); diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 61b61c9fb6f..636a5d093be 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,10 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{is_integer_literal, paths, snippet, span_lint}; +use syntax::ast::RangeLimits; +use syntax::codemap::Spanned; +use utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; use utils::{get_trait_def_id, higher, implements_trait}; +use utils::sugg::Sugg; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -38,16 +41,57 @@ declare_lint! { "zipping iterator with a range when `enumerate()` would do" } +/// **What it does:** Checks for exclusive ranges where 1 is added to the +/// upper bound, e.g. `x..(y+1)`. +/// +/// **Why is this bad?** The code is more readable with an inclusive range +/// like `x..=y`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// for x..(y+1) { .. } +/// ``` +declare_lint! { + pub RANGE_PLUS_ONE, + Warn, + "`x..(y+1)` reads better as `x..=y`" +} + +/// **What it does:** Checks for inclusive ranges where 1 is subtracted from +/// the upper bound, e.g. `x..=(y-1)`. +/// +/// **Why is this bad?** The code is more readable with an exclusive range +/// like `x..y`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// for x..=(y-1) { .. } +/// ``` +declare_lint! { + pub RANGE_MINUS_ONE, + Warn, + "`x..=(y-1)` reads better as `x..y`" +} + #[derive(Copy, Clone)] -pub struct StepByZero; +pub struct Pass; -impl LintPass for StepByZero { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN) + lint_array!( + ITERATOR_STEP_BY_ZERO, + RANGE_ZIP_WITH_LEN, + RANGE_PLUS_ONE, + RANGE_MINUS_ONE + ) } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprMethodCall(ref path, _, ref args) = expr.node { let name = path.name.as_str(); @@ -92,6 +136,46 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { }} } } + + // exclusive range plus one: x..(y+1) + if_let_chain! {[ + let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(expr), + let Some(y) = y_plus_one(end), + ], { + span_lint_and_then( + cx, + RANGE_PLUS_ONE, + expr.span, + "an inclusive range would be more readable", + |db| { + let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let end = Sugg::hir(cx, y, "y"); + db.span_suggestion(expr.span, + "use", + format!("{}..={}", start, end)); + }, + ); + }} + + // inclusive range minus one: x..=(y-1) + if_let_chain! {[ + let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr), + let Some(y) = y_minus_one(end), + ], { + span_lint_and_then( + cx, + RANGE_MINUS_ONE, + expr.span, + "an exclusive range would be more readable", + |db| { + let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let end = Sugg::hir(cx, y, "y"); + db.span_suggestion(expr.span, + "use", + format!("{}..{}", start, end)); + }, + ); + }} } } @@ -102,3 +186,25 @@ fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |iterator_trait| implements_trait(cx, ty, iterator_trait, &[])) } + +fn y_plus_one(expr: &Expr) -> Option<&Expr> { + match expr.node { + ExprBinary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => { + if is_integer_literal(lhs, 1) { + Some(rhs) + } else if is_integer_literal(rhs, 1) { + Some(lhs) + } else { + None + } + }, + _ => None, + } +} + +fn y_minus_one(expr: &Expr) -> Option<&Expr> { + match expr.node { + ExprBinary(Spanned { node: BiSub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), + _ => None, + } +} -- cgit 1.4.1-3-g733a5 From e9be7530c661136019977acf2eb6682cc9b4c289 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sun, 8 Oct 2017 12:42:17 +0200 Subject: Allow range_plus_one while ..= ranges are unstable --- clippy_lints/src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 636a5d093be..aff0c4b08ab 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -55,7 +55,7 @@ declare_lint! { /// ``` declare_lint! { pub RANGE_PLUS_ONE, - Warn, + Allow, "`x..(y+1)` reads better as `x..=y`" } -- cgit 1.4.1-3-g733a5 From 8ffec33fd3017b9e7e41f5c8a0b857fca7df9349 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 8 Oct 2017 20:17:04 +0900 Subject: Remove intermediate vec --- clippy_lints/src/needless_pass_by_value.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 29598a20f0d..3c1f6ef2c4b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -89,15 +89,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) .filter(|p| !p.is_global()) - .collect::>(); - let preds = preds - .iter() - .filter_map(|pred| if let ty::Predicate::Trait(ref poly_trait_ref) = *pred { - Some(poly_trait_ref.skip_binder()) + .filter_map(|pred| if let ty::Predicate::Trait(poly_trait_ref) = pred { + if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_regions() { + return None; + } + Some(poly_trait_ref) } else { None }) - .filter(|t| t.def_id() != sized_trait && !t.has_escaping_regions()) .collect::>(); // Collect moved variables and spans which will need dereferencings from the @@ -128,7 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let (implements_borrow_trait, all_borrowable_trait) = { let preds = preds .iter() - .filter(|t| t.self_ty() == ty) + .filter(|t| t.skip_binder().self_ty() == ty) .collect::>(); ( @@ -138,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), - &t.input_types().skip(1).collect::>(), + &t.skip_binder().input_types().skip(1).collect::>(), ) }), ) -- cgit 1.4.1-3-g733a5 From 16781a1d89b3cbc89bfb9127885d658f83f310e7 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sun, 8 Oct 2017 12:43:23 +0200 Subject: Add tests for range_plus_one and range_minus_one --- tests/ui/range_plus_minus_one.rs | 34 ++++++++++++++++++ tests/ui/range_plus_minus_one.stderr | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tests/ui/range_plus_minus_one.rs create mode 100644 tests/ui/range_plus_minus_one.stderr diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs new file mode 100644 index 00000000000..dce81634876 --- /dev/null +++ b/tests/ui/range_plus_minus_one.rs @@ -0,0 +1,34 @@ +#![feature(inclusive_range_syntax)] + +fn f() -> usize { + 42 +} + +#[warn(range_plus_one)] +fn main() { + for _ in 0..2 { } + for _ in 0..=2 { } + + for _ in 0..3+1 { } + for _ in 0..=3+1 { } + + for _ in 0..1+5 { } + for _ in 0..=1+5 { } + + for _ in 1..1+1 { } + for _ in 1..=1+1 { } + + for _ in 0..13+13 { } + for _ in 0..=13-7 { } + + for _ in 0..(1+f()) { } + for _ in 0..=(1+f()) { } + + let _ = ..11-1; + let _ = ..=11-1; + let _ = ..=(11-1); + let _ = (f()+1)..(f()+1); + + let mut vec: Vec<()> = std::vec::Vec::new(); + vec.drain(..); +} diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr new file mode 100644 index 00000000000..a2a3ae6077f --- /dev/null +++ b/tests/ui/range_plus_minus_one.stderr @@ -0,0 +1,67 @@ +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:12:14 + | +12 | for _ in 0..3+1 { } + | ------ + | | + | help: use: `0..=3` + | in this macro invocation + | + = note: `-D range-plus-one` implied by `-D warnings` + +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:15:14 + | +15 | for _ in 0..1+5 { } + | ------ + | | + | help: use: `0..=5` + | in this macro invocation + +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:18:14 + | +18 | for _ in 1..1+1 { } + | ------ + | | + | help: use: `1..=1` + | in this macro invocation + +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:24:14 + | +24 | for _ in 0..(1+f()) { } + | ---------- + | | + | help: use: `0..=f()` + | in this macro invocation + +error: an exclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:28:13 + | +28 | let _ = ..=11-1; + | ------- + | | + | help: use: `..11` + | in this macro invocation + | + = note: `-D range-minus-one` implied by `-D warnings` + +error: an exclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:29:13 + | +29 | let _ = ..=(11-1); + | --------- + | | + | help: use: `..11` + | in this macro invocation + +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:30:13 + | +30 | let _ = (f()+1)..(f()+1); + | ---------------- + | | + | help: use: `(f()+1)..=f()` + | in this macro invocation + -- cgit 1.4.1-3-g733a5 From 52bd7bb6625e78b74c8b5339a6e51dad5f4c7ff7 Mon Sep 17 00:00:00 2001 From: "Andriy S. from cobalt" Date: Sun, 8 Oct 2017 18:34:31 +0300 Subject: relax `needless_range_loop` so that it reports only direct indexing --- clippy_lints/src/loops.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8d2a2f8fac6..f1483cd7ecb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -925,14 +925,16 @@ fn check_for_loop_range<'a, 'tcx>( cx: cx, var: canonical_id, indexed: HashMap::new(), + indexed_directly: HashMap::new(), referenced: HashSet::new(), nonindex: false, }; walk_expr(&mut visitor, body); - // linting condition: we only indexed one variable - if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed.into_iter().next().expect( + // linting condition: we only indexed one variable, and indexed it directly + // (`indexed_directly` is subset of `indexed`) + if visitor.indexed.len() == 1 && visitor.indexed_directly.len() == 1 { + let (indexed, indexed_extent) = visitor.indexed_directly.into_iter().next().expect( "already checked that we have exactly 1 element", ); @@ -1481,6 +1483,9 @@ struct VarVisitor<'a, 'tcx: 'a> { var: ast::NodeId, /// indexed variables, the extend is `None` for global indexed: HashMap>, + /// subset of `indexed` of vars that are indexed directly: `v[i]` + /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` + indexed_directly: HashMap>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: HashSet, @@ -1499,7 +1504,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let QPath::Resolved(None, ref seqvar) = *seqpath, seqvar.segments.len() == 1, ], { - let index_used = same_var(self.cx, idx, self.var) || { + let index_used_directly = same_var(self.cx, idx, self.var); + let index_used = index_used_directly || { let mut used_visitor = LocalUsedVisitor { cx: self.cx, local: self.var, @@ -1519,10 +1525,16 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); self.indexed.insert(seqvar.segments[0].name, Some(extent)); + if index_used_directly { + self.indexed_directly.insert(seqvar.segments[0].name, Some(extent)); + } return; // no need to walk further *on the variable* } Def::Static(..) | Def::Const(..) => { self.indexed.insert(seqvar.segments[0].name, None); + if index_used_directly { + self.indexed_directly.insert(seqvar.segments[0].name, None); + } return; // no need to walk further *on the variable* } _ => (), -- cgit 1.4.1-3-g733a5 From 1dc0b5c9ec8e803df7858dd060c47bdc9ea5c9da Mon Sep 17 00:00:00 2001 From: "Andriy S. from cobalt" Date: Sun, 8 Oct 2017 22:37:04 +0300 Subject: tests for `needless_range_loop` --- tests/ui/needless_range_loop.rs | 27 +++++++++++++++++++++++++++ tests/ui/needless_range_loop.stderr | 14 ++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/ui/needless_range_loop.rs create mode 100644 tests/ui/needless_range_loop.stderr diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs new file mode 100644 index 00000000000..b960e3990c1 --- /dev/null +++ b/tests/ui/needless_range_loop.rs @@ -0,0 +1,27 @@ +fn calc_idx(i: usize) -> usize { + (i + i + 20) % 4 +} + +fn main() { + let ns = [2, 3, 5, 7]; + + for i in 3..10 { + println!("{}", ns[i]); + } + + for i in 3..10 { + println!("{}", ns[i % 4]); + } + + for i in 3..10 { + println!("{}", ns[i % ns.len()]); + } + + for i in 3..10 { + println!("{}", ns[calc_idx(i)]); + } + + for i in 3..10 { + println!("{}", ns[calc_idx(i) % 4]); + } +} diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr new file mode 100644 index 00000000000..e2c3e18e821 --- /dev/null +++ b/tests/ui/needless_range_loop.stderr @@ -0,0 +1,14 @@ +error: the loop variable `i` is only used to index `ns`. + --> $DIR/needless_range_loop.rs:8:5 + | +8 | / for i in 3..10 { +9 | | println!("{}", ns[i]); +10 | | } + | |_____^ + | + = note: `-D needless-range-loop` implied by `-D warnings` +help: consider using an iterator + | +8 | for in ns.iter().take(10).skip(3) { + | ^^^^^^ + -- cgit 1.4.1-3-g733a5 From a013568f70ab5099f269c5f86eeca5f71d1275e6 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 5 Oct 2017 23:46:08 -0500 Subject: add never_loop tests --- tests/ui/never_loop.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 715a83efd93..3bb25f68840 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -139,6 +139,19 @@ pub fn test13() { } } +pub fn test14() { + let mut a = true; + 'outer: while a { // never loops + while a { + if a { + a = false; + continue + } + } + break 'outer; + } +} + fn main() { test1(); test2(); @@ -153,5 +166,6 @@ fn main() { test11(|| 0); test12(true, false); test13(); + test14(); } -- cgit 1.4.1-3-g733a5 From 533a50547f9868ed8a278b80f2504b5ddf65dfb5 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 8 Oct 2017 17:24:32 -0500 Subject: remove contains_continue functions --- clippy_lints/src/loops.rs | 71 ----------------------------------------------- 1 file changed, 71 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8d2a2f8fac6..0844b1b1608 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -489,77 +489,6 @@ fn never_loop(block: &Block, id: NodeId) -> bool { !contains_continue_block(block, Some(id)) && loop_exit_block(block, &mut vec![id]) } -fn contains_continue_block(block: &Block, dest: Option) -> bool { - block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || - block.expr.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) -} - -fn contains_continue_stmt(stmt: &Stmt, dest: Option) -> bool { - match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => contains_continue_expr(e, dest), - StmtDecl(ref d, _) => contains_continue_decl(d, dest), - } -} - -fn contains_continue_decl(decl: &Decl, dest: Option) -> bool { - match decl.node { - DeclLocal(ref local) => { - local.init.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, - _ => false, - } -} - -fn contains_continue_expr(expr: &Expr, dest: Option) -> bool { - match expr.node { - ExprRet(Some(ref e)) | - ExprBox(ref e) | - ExprUnary(_, ref e) | - ExprCast(ref e, _) | - ExprType(ref e, _) | - ExprField(ref e, _) | - ExprTupField(ref e, _) | - ExprAddrOf(_, ref e) | - ExprRepeat(ref e, _) => contains_continue_expr(e, dest), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| contains_continue_expr(e, dest)), - ExprCall(ref e, ref es) => { - contains_continue_expr(e, dest) || es.iter().any(|e| contains_continue_expr(e, dest)) - }, - ExprBinary(_, ref e1, ref e2) | - ExprAssign(ref e1, ref e2) | - ExprAssignOp(_, ref e1, ref e2) | - ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| contains_continue_expr(e, dest)), - ExprIf(ref e, ref e2, ref e3) => { - [e, e2].iter().chain(e3.as_ref().iter()).any(|e| { - contains_continue_expr(e, dest) - }) - }, - ExprWhile(ref e, ref b, _) => contains_continue_expr(e, dest) || contains_continue_block(b, dest), - ExprMatch(ref e, ref arms, _) => { - contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) - }, - ExprBlock(ref block) | - ExprLoop(ref block, ..) => contains_continue_block(block, dest), - ExprStruct(_, _, ref base) => { - base.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, - ExprAgain(d) => dest.map_or(true, |dest| d.target_id.opt_id().map_or(false, |id| id == dest)), - _ => false, - } -} - fn loop_exit_block(block: &Block, loops: &mut Vec) -> bool { block.stmts.iter().take_while(|s| !contains_continue_stmt(s, None)).any(|s| loop_exit_stmt(s, loops)) || block.expr.as_ref().map_or(false, |e| loop_exit_expr(e, loops)) -- cgit 1.4.1-3-g733a5 From 9ccb7108b5284ddcb70920240bf0d4a9b177adb2 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 8 Oct 2017 17:26:39 -0500 Subject: fix never_loop --- clippy_lints/src/loops.rs | 112 +++++++++++++++++++++++++++++++-------------- tests/ui/never_loop.stderr | 12 +++++ 2 files changed, 90 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0844b1b1608..3b158e280ad 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -16,6 +16,7 @@ use rustc::ty::{self, Ty}; use rustc::ty::subst::{Subst, Substs}; use rustc_const_eval::ConstContext; use std::collections::{HashMap, HashSet}; +use std::iter::{Iterator, once}; use syntax::ast; use syntax::codemap::Span; use utils::sugg; @@ -378,7 +379,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { - if never_loop(block, expr.id) { + let mut state = NeverLoopState { + breaks: HashSet::new(), + continues: HashSet::new(), + }; + let may_complete = never_loop_block(block, &mut state); + if !may_complete && !state.continues.contains(&expr.id) { span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); } }, @@ -485,31 +491,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn never_loop(block: &Block, id: NodeId) -> bool { - !contains_continue_block(block, Some(id)) && loop_exit_block(block, &mut vec![id]) +struct NeverLoopState { + breaks: HashSet, + continues: HashSet, } -fn loop_exit_block(block: &Block, loops: &mut Vec) -> bool { - block.stmts.iter().take_while(|s| !contains_continue_stmt(s, None)).any(|s| loop_exit_stmt(s, loops)) - || block.expr.as_ref().map_or(false, |e| loop_exit_expr(e, loops)) +fn never_loop_block(block: &Block, state: &mut NeverLoopState) -> bool { + let stmts = block.stmts.iter().map(stmt_to_expr); + let expr = once(block.expr.as_ref().map(|p| &**p)); + let mut iter = stmts.chain(expr).filter_map(|e| e); + never_loop_expr_seq(&mut iter, state) } -fn loop_exit_stmt(stmt: &Stmt, loops: &mut Vec) -> bool { +fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => loop_exit_expr(e, loops), - StmtDecl(ref d, _) => loop_exit_decl(d, loops), + StmtSemi(ref e, ..) | + StmtExpr(ref e, ..) => Some(e), + StmtDecl(ref d, ..) => decl_to_expr(d), } } -fn loop_exit_decl(decl: &Decl, loops: &mut Vec) -> bool { +fn decl_to_expr(decl: &Decl) -> Option<&Expr> { match decl.node { - DeclLocal(ref local) => local.init.as_ref().map_or(false, |e| loop_exit_expr(e, loops)), - _ => false, + DeclLocal(ref local) => local.init.as_ref().map(|p| &**p), + _ => None, } } -fn loop_exit_expr(expr: &Expr, loops: &mut Vec) -> bool { +fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { match expr.node { ExprBox(ref e) | ExprUnary(_, ref e) | @@ -518,38 +527,73 @@ fn loop_exit_expr(expr: &Expr, loops: &mut Vec) -> bool { ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | - ExprRepeat(ref e, _) => loop_exit_expr(e, loops), + ExprRepeat(ref e, _) => never_loop_expr(e, state), ExprArray(ref es) | ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e, loops)), - ExprCall(ref e, ref es) => loop_exit_expr(e, loops) || es.iter().any(|e| loop_exit_expr(e, loops)), + ExprTup(ref es) => never_loop_expr_seq(&mut es.iter(), state), + ExprCall(ref e, ref es) => never_loop_expr_seq(&mut once(&**e).chain(es.iter()), state), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | - ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| loop_exit_expr(e, loops)), - ExprIf(ref e, ref e2, ref e3) => loop_exit_expr(e, loops) - || e3.as_ref().map_or(false, |e3| loop_exit_expr(e3, loops)) && loop_exit_expr(e2, loops), + ExprIndex(ref e1, ref e2) => never_loop_expr_seq(&mut [&**e1, &**e2].iter().cloned(), state), + ExprIf(ref e, ref e2, ref e3) => { + let e1 = never_loop_expr(e, state); + let e2 = never_loop_expr(e2, state); + match *e3 { + Some(ref e3) => { + let e3 = never_loop_expr(e3, state); + e1 && (e2 || e3) + }, + None => e1, + } + }, ExprLoop(ref b, _, _) => { - loops.push(expr.id); - let val = loop_exit_block(b, loops); - loops.pop(); - val + let block_may_complete = never_loop_block(b, state); + let has_break = state.breaks.remove(&expr.id); + state.continues.remove(&expr.id); + block_may_complete || has_break }, ExprWhile(ref e, ref b, _) => { - loops.push(expr.id); - let val = loop_exit_expr(e, loops) || loop_exit_block(b, loops); - loops.pop(); - val + let e = never_loop_expr(e, state); + let block_may_complete = never_loop_block(b, state); + let has_break = state.breaks.remove(&expr.id); + let has_continue = state.continues.remove(&expr.id); + e && (block_may_complete || has_break || has_continue) }, - ExprMatch(ref e, ref arms, _) => loop_exit_expr(e, loops) || arms.iter().all(|a| loop_exit_expr(&a.body, loops)), - ExprBlock(ref b) => loop_exit_block(b, loops), - ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| loops.iter().skip(1).all(|&id2| id != id2)), - ExprBreak(d, _) => d.target_id.opt_id().map_or(false, |id| loops[0] == id), - ExprRet(_) => true, - _ => false, + ExprMatch(ref e, ref arms, _) => { + let e = never_loop_expr(e, state); + let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), state); + e && arms + }, + ExprBlock(ref b) => never_loop_block(b, state), + ExprAgain(d) => { + let id = d.target_id.opt_id().expect("continue is missing target id"); + state.continues.insert(id); + false + }, + ExprBreak(d, _) => { + let id = d.target_id.opt_id().expect("break is missing target id"); + state.breaks.insert(id); + false + }, + ExprRet(ref e) => { + if let Some(ref e) = *e { + never_loop_expr(e, state); + } + false + }, + _ => true, } } +fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, state: &mut NeverLoopState) -> bool { + es.map(|e| never_loop_expr(e, state)).fold(true, |a, b| a && b) +} + +fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, state: &mut NeverLoopState) -> bool { + e.map(|e| never_loop_expr(e, state)).fold(false, |a, b| a || b) +} + fn check_for_loop<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat, diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 1ecdb5030f9..80eeb6c2888 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -68,3 +68,15 @@ error: this loop never actually loops 103 | | } | |_____^ +error: this loop never actually loops + --> $DIR/never_loop.rs:144:5 + | +144 | / 'outer: while a { // never loops +145 | | while a { +146 | | if a { +147 | | a = false; +... | +151 | | break 'outer; +152 | | } + | |_____^ + -- cgit 1.4.1-3-g733a5 From 9ebc30cb0c05e07e62883ce131bc24ac8459b14b Mon Sep 17 00:00:00 2001 From: sinkuu Date: Mon, 9 Oct 2017 22:49:54 +0900 Subject: rustc 1.22.0-nightly (150b625a0 2017-10-08) --- tests/ui/shadow.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 50f41627acb..d5043261188 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -2,7 +2,7 @@ error: `x` is shadowed by itself in `&mut x` --> $DIR/shadow.rs:13:5 | 13 | let x = &mut x; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: `-D shadow-same` implied by `-D warnings` note: previous binding is here @@ -15,7 +15,7 @@ error: `x` is shadowed by itself in `{ x }` --> $DIR/shadow.rs:14:5 | 14 | let x = { x }; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:13:9 @@ -27,7 +27,7 @@ error: `x` is shadowed by itself in `(&*x)` --> $DIR/shadow.rs:15:5 | 15 | let x = (&*x); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:14:9 @@ -126,7 +126,7 @@ error: `x` shadows a previous declaration --> $DIR/shadow.rs:23:5 | 23 | let x; - | ^^^^^ + | ^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:21:9 -- cgit 1.4.1-3-g733a5 From c1a147f48ebf4c53cfc46fc9674d01e61824b4ad Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 9 Oct 2017 22:45:03 -0500 Subject: move starts_ends_with tests --- tests/ui/methods.rs | 36 ------ tests/ui/methods.stderr | 240 +++++++++++---------------------------- tests/ui/starts_ends_with.rs | 39 +++++++ tests/ui/starts_ends_with.stderr | 76 +++++++++++++ 4 files changed, 179 insertions(+), 212 deletions(-) create mode 100644 tests/ui/starts_ends_with.rs create mode 100644 tests/ui/starts_ends_with.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 3395280ba05..54296a74759 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -432,12 +432,6 @@ struct MyErrorWithParam { x: T } -#[allow(unnecessary_operation)] -fn starts_with() { - "".chars().next() == Some(' '); - Some(' ') != "".chars().next(); -} - fn str_extend_chars() { let abc = "abc"; let def = String::from("def"); @@ -557,33 +551,3 @@ fn iter_clone_collect() { let v3 : HashSet = v.iter().cloned().collect(); let v4 : VecDeque = v.iter().cloned().collect(); } - -fn chars_cmp_with_unwrap() { - let s = String::from("foo"); - if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - // Nothing here - } - if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - // Nothing here - } - if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - // Nothing here - } - if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - // Nothing here - } - if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - // Nothing here - } - if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - // Nothing here - } -} - -#[allow(unnecessary_operation)] -fn ends_with() { - "".chars().last() == Some(' '); - Some(' ') != "".chars().last(); - "".chars().next_back() == Some(' '); - Some(' ') != "".chars().next_back(); -} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index a1bc219eaf8..d50ef4e5284 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -547,321 +547,209 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly 425 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: you should use the `starts_with` method - --> $DIR/methods.rs:437:5 - | -437 | "".chars().next() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` - | - = note: `-D chars-next-cmp` implied by `-D warnings` - -error: you should use the `starts_with` method - --> $DIR/methods.rs:438:5 - | -438 | Some(' ') != "".chars().next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` - error: calling `.extend(_.chars())` - --> $DIR/methods.rs:447:5 + --> $DIR/methods.rs:441:5 | -447 | s.extend(abc.chars()); +441 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:450:5 + --> $DIR/methods.rs:444:5 | -450 | s.extend("abc".chars()); +444 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/methods.rs:453:5 + --> $DIR/methods.rs:447:5 | -453 | s.extend(def.chars()); +447 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:464:5 + --> $DIR/methods.rs:458:5 | -464 | 42.clone(); +458 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:468:5 + --> $DIR/methods.rs:462:5 | -468 | (&42).clone(); +462 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:478:5 + --> $DIR/methods.rs:472:5 | -478 | rc.clone(); +472 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` | = note: `-D clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:481:5 + --> $DIR/methods.rs:475:5 | -481 | arc.clone(); +475 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:484:5 + --> $DIR/methods.rs:478:5 | -484 | rcweak.clone(); +478 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:487:5 + --> $DIR/methods.rs:481:5 | -487 | arc_weak.clone(); +481 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:494:5 + --> $DIR/methods.rs:488:5 | -494 | t.clone(); +488 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/methods.rs:496:5 + --> $DIR/methods.rs:490:5 | -496 | Some(t).clone(); +490 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:502:22 + --> $DIR/methods.rs:496:22 | -502 | let z: &Vec<_> = y.clone(); +496 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` | = note: `-D clone-double-ref` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:509:13 + --> $DIR/methods.rs:503:13 | -509 | x.split("x"); +503 | x.split("x"); | --------^^^- help: try using a char instead: `x.split('x')` | = note: `-D single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/methods.rs:526:16 + --> $DIR/methods.rs:520:16 | -526 | x.contains("x"); +520 | x.contains("x"); | -----------^^^- help: try using a char instead: `x.contains('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:527:19 + --> $DIR/methods.rs:521:19 | -527 | x.starts_with("x"); +521 | x.starts_with("x"); | --------------^^^- help: try using a char instead: `x.starts_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:528:17 + --> $DIR/methods.rs:522:17 | -528 | x.ends_with("x"); +522 | x.ends_with("x"); | ------------^^^- help: try using a char instead: `x.ends_with('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:529:12 + --> $DIR/methods.rs:523:12 | -529 | x.find("x"); +523 | x.find("x"); | -------^^^- help: try using a char instead: `x.find('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:530:13 + --> $DIR/methods.rs:524:13 | -530 | x.rfind("x"); +524 | x.rfind("x"); | --------^^^- help: try using a char instead: `x.rfind('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:531:14 + --> $DIR/methods.rs:525:14 | -531 | x.rsplit("x"); +525 | x.rsplit("x"); | ---------^^^- help: try using a char instead: `x.rsplit('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:532:24 + --> $DIR/methods.rs:526:24 | -532 | x.split_terminator("x"); +526 | x.split_terminator("x"); | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:533:25 + --> $DIR/methods.rs:527:25 | -533 | x.rsplit_terminator("x"); +527 | x.rsplit_terminator("x"); | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:534:17 + --> $DIR/methods.rs:528:17 | -534 | x.splitn(0, "x"); +528 | x.splitn(0, "x"); | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:535:18 + --> $DIR/methods.rs:529:18 | -535 | x.rsplitn(0, "x"); +529 | x.rsplitn(0, "x"); | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:536:15 + --> $DIR/methods.rs:530:15 | -536 | x.matches("x"); +530 | x.matches("x"); | ----------^^^- help: try using a char instead: `x.matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:537:16 + --> $DIR/methods.rs:531:16 | -537 | x.rmatches("x"); +531 | x.rmatches("x"); | -----------^^^- help: try using a char instead: `x.rmatches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:538:21 + --> $DIR/methods.rs:532:21 | -538 | x.match_indices("x"); +532 | x.match_indices("x"); | ----------------^^^- help: try using a char instead: `x.match_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:539:22 + --> $DIR/methods.rs:533:22 | -539 | x.rmatch_indices("x"); +533 | x.rmatch_indices("x"); | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:540:25 + --> $DIR/methods.rs:534:25 | -540 | x.trim_left_matches("x"); +534 | x.trim_left_matches("x"); | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` error: single-character string constant used as pattern - --> $DIR/methods.rs:541:26 + --> $DIR/methods.rs:535:26 | -541 | x.trim_right_matches("x"); +535 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:551:5 + --> $DIR/methods.rs:545:5 | -551 | CString::new("foo").unwrap().as_ptr(); +545 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:551:5 + --> $DIR/methods.rs:545:5 | -551 | CString::new("foo").unwrap().as_ptr(); +545 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:556:27 + --> $DIR/methods.rs:550:27 | -556 | let v2 : Vec = v.iter().cloned().collect(); +550 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` -error: you should use the `starts_with` method - --> $DIR/methods.rs:563:8 - | -563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:563:8 - | -563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:566:8 - | -566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` - | - = note: `-D chars-last-cmp` implied by `-D warnings` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:566:8 - | -566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:569:8 - | -569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:569:8 - | -569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `starts_with` method - --> $DIR/methods.rs:572:8 - | -572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:572:8 - | -572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:575:8 - | -575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:575:8 - | -575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:578:8 - | -578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:578:8 - | -578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:585:5 - | -585 | "".chars().last() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:586:5 - | -586 | Some(' ') != "".chars().last(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:587:5 - | -587 | "".chars().next_back() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:588:5 - | -588 | Some(' ') != "".chars().next_back(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` - diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs new file mode 100644 index 00000000000..d47c8a5b076 --- /dev/null +++ b/tests/ui/starts_ends_with.rs @@ -0,0 +1,39 @@ +#![allow(dead_code)] + +fn main() {} + +#[allow(unnecessary_operation)] +fn starts_with() { + "".chars().next() == Some(' '); + Some(' ') != "".chars().next(); +} + +fn chars_cmp_with_unwrap() { + let s = String::from("foo"); + if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } +} + +#[allow(unnecessary_operation)] +fn ends_with() { + "".chars().last() == Some(' '); + Some(' ') != "".chars().last(); + "".chars().next_back() == Some(' '); + Some(' ') != "".chars().next_back(); +} diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr new file mode 100644 index 00000000000..c67cc8a86ea --- /dev/null +++ b/tests/ui/starts_ends_with.stderr @@ -0,0 +1,76 @@ +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:7:5 + | +7 | "".chars().next() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` + | + = note: `-D chars-next-cmp` implied by `-D warnings` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:8:5 + | +8 | Some(' ') != "".chars().next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:13:8 + | +13 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:16:8 + | +16 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + | + = note: `-D chars-last-cmp` implied by `-D warnings` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:19:8 + | +19 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:22:8 + | +22 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:25:8 + | +25 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:28:8 + | +28 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:35:5 + | +35 | "".chars().last() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:36:5 + | +36 | Some(' ') != "".chars().last(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:37:5 + | +37 | "".chars().next_back() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:38:5 + | +38 | Some(' ') != "".chars().next_back(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + -- cgit 1.4.1-3-g733a5 From 18717ae088a3b956baaf60942028ea1336d1bfef Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 9 Oct 2017 23:00:47 -0500 Subject: move single_char_pattern tests --- tests/ui/methods.rs | 40 ------------- tests/ui/methods.stderr | 116 ++---------------------------------- tests/ui/single_char_pattern.rs | 41 +++++++++++++ tests/ui/single_char_pattern.stderr | 104 ++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 150 deletions(-) create mode 100644 tests/ui/single_char_pattern.rs create mode 100644 tests/ui/single_char_pattern.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 54296a74759..4769906e2ff 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -498,46 +498,6 @@ fn clone_on_double_ref() { println!("{:p} {:p}",*y, z); } -fn single_char_pattern() { - let x = "foo"; - x.split("x"); - x.split("xx"); - x.split('x'); - - let y = "x"; - x.split(y); - // Not yet testing for multi-byte characters - // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` - // should have done this but produced an ICE - // - // We may not want to suggest changing these anyway - // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 - x.split("ß"); - x.split("ℝ"); - x.split("💣"); - // Can't use this lint for unicode code points which don't fit in a char - x.split("❤️"); - x.contains("x"); - x.starts_with("x"); - x.ends_with("x"); - x.find("x"); - x.rfind("x"); - x.rsplit("x"); - x.split_terminator("x"); - x.rsplit_terminator("x"); - x.splitn(0, "x"); - x.rsplitn(0, "x"); - x.matches("x"); - x.rmatches("x"); - x.match_indices("x"); - x.rmatch_indices("x"); - x.trim_left_matches("x"); - x.trim_right_matches("x"); - - let h = HashSet::::new(); - h.contains("X"); // should not warn -} - #[allow(result_unwrap_used)] fn temporary_cstring() { use std::ffi::CString; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index d50ef4e5284..2500c30b402 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -627,128 +627,24 @@ error: using `clone` on a double-reference; this will copy the reference instead | = note: `-D clone-double-ref` implied by `-D warnings` -error: single-character string constant used as pattern - --> $DIR/methods.rs:503:13 - | -503 | x.split("x"); - | --------^^^- help: try using a char instead: `x.split('x')` - | - = note: `-D single-char-pattern` implied by `-D warnings` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:520:16 - | -520 | x.contains("x"); - | -----------^^^- help: try using a char instead: `x.contains('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:521:19 - | -521 | x.starts_with("x"); - | --------------^^^- help: try using a char instead: `x.starts_with('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:522:17 - | -522 | x.ends_with("x"); - | ------------^^^- help: try using a char instead: `x.ends_with('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:523:12 - | -523 | x.find("x"); - | -------^^^- help: try using a char instead: `x.find('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:524:13 - | -524 | x.rfind("x"); - | --------^^^- help: try using a char instead: `x.rfind('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:525:14 - | -525 | x.rsplit("x"); - | ---------^^^- help: try using a char instead: `x.rsplit('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:526:24 - | -526 | x.split_terminator("x"); - | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:527:25 - | -527 | x.rsplit_terminator("x"); - | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:528:17 - | -528 | x.splitn(0, "x"); - | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:529:18 - | -529 | x.rsplitn(0, "x"); - | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:530:15 - | -530 | x.matches("x"); - | ----------^^^- help: try using a char instead: `x.matches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:531:16 - | -531 | x.rmatches("x"); - | -----------^^^- help: try using a char instead: `x.rmatches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:532:21 - | -532 | x.match_indices("x"); - | ----------------^^^- help: try using a char instead: `x.match_indices('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:533:22 - | -533 | x.rmatch_indices("x"); - | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:534:25 - | -534 | x.trim_left_matches("x"); - | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:535:26 - | -535 | x.trim_right_matches("x"); - | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` - error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:545:5 + --> $DIR/methods.rs:505:5 | -545 | CString::new("foo").unwrap().as_ptr(); +505 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:545:5 + --> $DIR/methods.rs:505:5 | -545 | CString::new("foo").unwrap().as_ptr(); +505 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:550:27 + --> $DIR/methods.rs:510:27 | -550 | let v2 : Vec = v.iter().cloned().collect(); +510 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs new file mode 100644 index 00000000000..948a8ff0e41 --- /dev/null +++ b/tests/ui/single_char_pattern.rs @@ -0,0 +1,41 @@ +use std::collections::HashSet; + +fn main() { + let x = "foo"; + x.split("x"); + x.split("xx"); + x.split('x'); + + let y = "x"; + x.split(y); + // Not yet testing for multi-byte characters + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` + // should have done this but produced an ICE + // + // We may not want to suggest changing these anyway + // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 + x.split("ß"); + x.split("ℝ"); + x.split("💣"); + // Can't use this lint for unicode code points which don't fit in a char + x.split("❤️"); + x.contains("x"); + x.starts_with("x"); + x.ends_with("x"); + x.find("x"); + x.rfind("x"); + x.rsplit("x"); + x.split_terminator("x"); + x.rsplit_terminator("x"); + x.splitn(0, "x"); + x.rsplitn(0, "x"); + x.matches("x"); + x.rmatches("x"); + x.match_indices("x"); + x.rmatch_indices("x"); + x.trim_left_matches("x"); + x.trim_right_matches("x"); + + let h = HashSet::::new(); + h.contains("X"); // should not warn +} diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr new file mode 100644 index 00000000000..d5f21f210a3 --- /dev/null +++ b/tests/ui/single_char_pattern.stderr @@ -0,0 +1,104 @@ +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:5:13 + | +5 | x.split("x"); + | --------^^^- help: try using a char instead: `x.split('x')` + | + = note: `-D single-char-pattern` implied by `-D warnings` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:22:16 + | +22 | x.contains("x"); + | -----------^^^- help: try using a char instead: `x.contains('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:23:19 + | +23 | x.starts_with("x"); + | --------------^^^- help: try using a char instead: `x.starts_with('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:24:17 + | +24 | x.ends_with("x"); + | ------------^^^- help: try using a char instead: `x.ends_with('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:25:12 + | +25 | x.find("x"); + | -------^^^- help: try using a char instead: `x.find('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:26:13 + | +26 | x.rfind("x"); + | --------^^^- help: try using a char instead: `x.rfind('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:27:14 + | +27 | x.rsplit("x"); + | ---------^^^- help: try using a char instead: `x.rsplit('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:28:24 + | +28 | x.split_terminator("x"); + | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:29:25 + | +29 | x.rsplit_terminator("x"); + | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:30:17 + | +30 | x.splitn(0, "x"); + | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:31:18 + | +31 | x.rsplitn(0, "x"); + | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:32:15 + | +32 | x.matches("x"); + | ----------^^^- help: try using a char instead: `x.matches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:33:16 + | +33 | x.rmatches("x"); + | -----------^^^- help: try using a char instead: `x.rmatches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:34:21 + | +34 | x.match_indices("x"); + | ----------------^^^- help: try using a char instead: `x.match_indices('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:35:22 + | +35 | x.rmatch_indices("x"); + | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:36:25 + | +36 | x.trim_left_matches("x"); + | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:37:26 + | +37 | x.trim_right_matches("x"); + | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` + -- cgit 1.4.1-3-g733a5 From 5eeadcfc436b4b69bdba68ef61e5362b83e68ed2 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 9 Oct 2017 23:07:12 -0500 Subject: move unnecessary clone tests --- tests/ui/methods.rs | 51 -------------------------- tests/ui/methods.stderr | 76 +++------------------------------------ tests/ui/unnecessary_clone.rs | 59 ++++++++++++++++++++++++++++++ tests/ui/unnecessary_clone.stderr | 68 +++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 123 deletions(-) create mode 100644 tests/ui/unnecessary_clone.rs create mode 100644 tests/ui/unnecessary_clone.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 4769906e2ff..4eb7846d3cc 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -454,60 +454,9 @@ fn str_extend_chars() { s.extend(f.chars()); } -fn clone_on_copy() { - 42.clone(); - - vec![1].clone(); // ok, not a Copy type - Some(vec![1]).clone(); // ok, not a Copy type - (&42).clone(); -} - -fn clone_on_ref_ptr() { - let rc = Rc::new(true); - let arc = Arc::new(true); - - let rcweak = Rc::downgrade(&rc); - let arc_weak = Arc::downgrade(&arc); - - rc.clone(); - Rc::clone(&rc); - - arc.clone(); - Arc::clone(&arc); - - rcweak.clone(); - rc::Weak::clone(&rcweak); - - arc_weak.clone(); - sync::Weak::clone(&arc_weak); - - -} - -fn clone_on_copy_generic(t: T) { - t.clone(); - - Some(t).clone(); -} - -fn clone_on_double_ref() { - let x = vec![1]; - let y = &&x; - let z: &Vec<_> = y.clone(); - - println!("{:p} {:p}",*y, z); -} - #[allow(result_unwrap_used)] fn temporary_cstring() { use std::ffi::CString; CString::new("foo").unwrap().as_ptr(); } - -fn iter_clone_collect() { - let v = [1,2,3,4,5]; - let v2 : Vec = v.iter().cloned().collect(); - let v3 : HashSet = v.iter().cloned().collect(); - let v4 : VecDeque = v.iter().cloned().collect(); -} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 2500c30b402..0bf7dc321c9 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -567,85 +567,17 @@ error: calling `.extend(_.chars())` 447 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:458:5 - | -458 | 42.clone(); - | ^^^^^^^^^^ help: try removing the `clone` call: `42` - | - = note: `-D clone-on-copy` implied by `-D warnings` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:462:5 - | -462 | (&42).clone(); - | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:472:5 - | -472 | rc.clone(); - | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` - | - = note: `-D clone-on-ref-ptr` implied by `-D warnings` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:475:5 - | -475 | arc.clone(); - | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:478:5 - | -478 | rcweak.clone(); - | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:481:5 - | -481 | arc_weak.clone(); - | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:488:5 - | -488 | t.clone(); - | ^^^^^^^^^ help: try removing the `clone` call: `t` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:490:5 - | -490 | Some(t).clone(); - | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` - -error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:496:22 - | -496 | let z: &Vec<_> = y.clone(); - | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` - | - = note: `-D clone-double-ref` implied by `-D warnings` - error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:505:5 + --> $DIR/methods.rs:461:5 | -505 | CString::new("foo").unwrap().as_ptr(); +461 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:505:5 + --> $DIR/methods.rs:461:5 | -505 | CString::new("foo").unwrap().as_ptr(); +461 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:510:27 - | -510 | let v2 : Vec = v.iter().cloned().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D iter-cloned-collect` implied by `-D warnings` - diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs new file mode 100644 index 00000000000..f33def9eb4e --- /dev/null +++ b/tests/ui/unnecessary_clone.rs @@ -0,0 +1,59 @@ +#![allow(unused)] + +use std::collections::HashSet; +use std::collections::VecDeque; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} + +fn clone_on_copy() { + 42.clone(); + + vec![1].clone(); // ok, not a Copy type + Some(vec![1]).clone(); // ok, not a Copy type + (&42).clone(); +} + +fn clone_on_ref_ptr() { + let rc = Rc::new(true); + let arc = Arc::new(true); + + let rcweak = Rc::downgrade(&rc); + let arc_weak = Arc::downgrade(&arc); + + rc.clone(); + Rc::clone(&rc); + + arc.clone(); + Arc::clone(&arc); + + rcweak.clone(); + rc::Weak::clone(&rcweak); + + arc_weak.clone(); + sync::Weak::clone(&arc_weak); + + +} + +fn clone_on_copy_generic(t: T) { + t.clone(); + + Some(t).clone(); +} + +fn clone_on_double_ref() { + let x = vec![1]; + let y = &&x; + let z: &Vec<_> = y.clone(); + + println!("{:p} {:p}",*y, z); +} + +fn iter_clone_collect() { + let v = [1,2,3,4,5]; + let v2 : Vec = v.iter().cloned().collect(); + let v3 : HashSet = v.iter().cloned().collect(); + let v4 : VecDeque = v.iter().cloned().collect(); +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr new file mode 100644 index 00000000000..17263756980 --- /dev/null +++ b/tests/ui/unnecessary_clone.stderr @@ -0,0 +1,68 @@ +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:11:5 + | +11 | 42.clone(); + | ^^^^^^^^^^ help: try removing the `clone` call: `42` + | + = note: `-D clone-on-copy` implied by `-D warnings` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:15:5 + | +15 | (&42).clone(); + | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:25:5 + | +25 | rc.clone(); + | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` + | + = note: `-D clone-on-ref-ptr` implied by `-D warnings` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:28:5 + | +28 | arc.clone(); + | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:31:5 + | +31 | rcweak.clone(); + | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:34:5 + | +34 | arc_weak.clone(); + | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:41:5 + | +41 | t.clone(); + | ^^^^^^^^^ help: try removing the `clone` call: `t` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:43:5 + | +43 | Some(t).clone(); + | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` + +error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type + --> $DIR/unnecessary_clone.rs:49:22 + | +49 | let z: &Vec<_> = y.clone(); + | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` + | + = note: `-D clone-double-ref` implied by `-D warnings` + +error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable + --> $DIR/unnecessary_clone.rs:56:27 + | +56 | let v2 : Vec = v.iter().cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D iter-cloned-collect` implied by `-D warnings` + -- cgit 1.4.1-3-g733a5 From 6d94167014e1738486601e05bdfb5cdef812d18f Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 9 Oct 2017 23:15:19 -0500 Subject: move cstring tests --- tests/ui/cstring.rs | 8 ++++++++ tests/ui/cstring.stderr | 22 ++++++++++++++++++++++ tests/ui/methods.rs | 7 ------- tests/ui/methods.stderr | 14 -------------- 4 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 tests/ui/cstring.rs create mode 100644 tests/ui/cstring.stderr diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs new file mode 100644 index 00000000000..8b7b0b66bc6 --- /dev/null +++ b/tests/ui/cstring.rs @@ -0,0 +1,8 @@ +fn main() {} + +#[allow(result_unwrap_used)] +fn temporary_cstring() { + use std::ffi::CString; + + CString::new("foo").unwrap().as_ptr(); +} diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr new file mode 100644 index 00000000000..ddb74ce9cac --- /dev/null +++ b/tests/ui/cstring.stderr @@ -0,0 +1,22 @@ +error: function is never used: `temporary_cstring` + --> $DIR/cstring.rs:4:1 + | +4 | fn temporary_cstring() { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D dead-code` implied by `-D warnings` + +error: you are getting the inner pointer of a temporary `CString` + --> $DIR/cstring.rs:7:5 + | +7 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` + = note: that pointer will be invalid outside this expression +help: assign the `CString` to a variable to extend its lifetime + --> $DIR/cstring.rs:7:5 + | +7 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 4eb7846d3cc..a422cffafab 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -453,10 +453,3 @@ fn str_extend_chars() { let f = HasChars; s.extend(f.chars()); } - -#[allow(result_unwrap_used)] -fn temporary_cstring() { - use std::ffi::CString; - - CString::new("foo").unwrap().as_ptr(); -} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 0bf7dc321c9..d80ff30ec71 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -567,17 +567,3 @@ error: calling `.extend(_.chars())` 447 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` -error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:461:5 - | -461 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` - = note: that pointer will be invalid outside this expression -help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:461:5 - | -461 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From 3356d121df25bc5decc8ebe52f53d9e6952a1cac Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 9 Oct 2017 23:56:49 -0500 Subject: move string_extend tests --- tests/ui/methods.rs | 31 ------ tests/ui/methods.stderr | 240 +++++++++++++++++++----------------------- tests/ui/string_extend.rs | 30 ++++++ tests/ui/string_extend.stderr | 20 ++++ 4 files changed, 160 insertions(+), 161 deletions(-) create mode 100644 tests/ui/string_extend.rs create mode 100644 tests/ui/string_extend.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index a422cffafab..20776ca15da 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -189,15 +189,6 @@ impl IteratorFalsePositives { } } -#[derive(Copy, Clone)] -struct HasChars; - -impl HasChars { - fn chars(self) -> std::str::Chars<'static> { - "HasChars".chars() - } -} - /// Checks implementation of `FILTER_NEXT` lint fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; @@ -431,25 +422,3 @@ struct MyError(()); // doesn't implement Debug struct MyErrorWithParam { x: T } - -fn str_extend_chars() { - let abc = "abc"; - let def = String::from("def"); - let mut s = String::new(); - - s.push_str(abc); - s.extend(abc.chars()); - - s.push_str("abc"); - s.extend("abc".chars()); - - s.push_str(&def); - s.extend(def.chars()); - - s.extend(abc.chars().skip(1)); - s.extend("abc".chars().skip(1)); - s.extend(['a', 'b', 'c'].iter()); - - let f = HasChars; - s.extend(f.chars()); -} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index d80ff30ec71..1b5deef998e 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -214,356 +214,336 @@ error: unnecessary structure name repetition | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:206:13 + --> $DIR/methods.rs:197:13 | -206 | let _ = v.iter().filter(|&x| *x < 0).next(); +197 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:209:13 + --> $DIR/methods.rs:200:13 | -209 | let _ = v.iter().filter(|&x| { +200 | let _ = v.iter().filter(|&x| { | _____________^ -210 | | *x < 0 -211 | | } -212 | | ).next(); +201 | | *x < 0 +202 | | } +203 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:224:13 + --> $DIR/methods.rs:215:13 | -224 | let _ = v.iter().find(|&x| *x < 0).is_some(); +215 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:227:13 + --> $DIR/methods.rs:218:13 | -227 | let _ = v.iter().find(|&x| { +218 | let _ = v.iter().find(|&x| { | _____________^ -228 | | *x < 0 -229 | | } -230 | | ).is_some(); +219 | | *x < 0 +220 | | } +221 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:233:13 + --> $DIR/methods.rs:224:13 | -233 | let _ = v.iter().position(|&x| x < 0).is_some(); +224 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:236:13 + --> $DIR/methods.rs:227:13 | -236 | let _ = v.iter().position(|&x| { +227 | let _ = v.iter().position(|&x| { | _____________^ -237 | | x < 0 -238 | | } -239 | | ).is_some(); +228 | | x < 0 +229 | | } +230 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:242:13 + --> $DIR/methods.rs:233:13 | -242 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +233 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:245:13 + --> $DIR/methods.rs:236:13 | -245 | let _ = v.iter().rposition(|&x| { +236 | let _ = v.iter().rposition(|&x| { | _____________^ -246 | | x < 0 -247 | | } -248 | | ).is_some(); +237 | | x < 0 +238 | | } +239 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:262:21 + --> $DIR/methods.rs:253:21 | -262 | fn new() -> Foo { Foo } +253 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:280:5 + --> $DIR/methods.rs:271:5 | -280 | with_constructor.unwrap_or(make()); +271 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:283:5 + --> $DIR/methods.rs:274:5 | -283 | with_new.unwrap_or(Vec::new()); +274 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:286:5 + --> $DIR/methods.rs:277:5 | -286 | with_const_args.unwrap_or(Vec::with_capacity(12)); +277 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:289:5 + --> $DIR/methods.rs:280:5 | -289 | with_err.unwrap_or(make()); +280 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:292:5 + --> $DIR/methods.rs:283:5 | -292 | with_err_args.unwrap_or(Vec::with_capacity(12)); +283 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:295:5 + --> $DIR/methods.rs:286:5 | -295 | with_default_trait.unwrap_or(Default::default()); +286 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:298:5 + --> $DIR/methods.rs:289:5 | -298 | with_default_type.unwrap_or(u64::default()); +289 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:301:5 + --> $DIR/methods.rs:292:5 | -301 | with_vec.unwrap_or(vec![]); +292 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:306:5 + --> $DIR/methods.rs:297:5 | -306 | without_default.unwrap_or(Foo::new()); +297 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:309:5 + --> $DIR/methods.rs:300:5 | -309 | map.entry(42).or_insert(String::new()); +300 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:312:5 + --> $DIR/methods.rs:303:5 | -312 | btree.entry(42).or_insert(String::new()); +303 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:315:13 + --> $DIR/methods.rs:306:13 | -315 | let _ = stringy.unwrap_or("".to_owned()); +306 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:326:23 + --> $DIR/methods.rs:317:23 | -326 | let bad_vec = some_vec.iter().nth(3); +317 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:327:26 + --> $DIR/methods.rs:318:26 | -327 | let bad_slice = &some_vec[..].iter().nth(3); +318 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:328:31 + --> $DIR/methods.rs:319:31 | -328 | let bad_boxed_slice = boxed_slice.iter().nth(3); +319 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:329:29 + --> $DIR/methods.rs:320:29 | -329 | let bad_vec_deque = some_vec_deque.iter().nth(3); +320 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:334:23 + --> $DIR/methods.rs:325:23 | -334 | let bad_vec = some_vec.iter_mut().nth(3); +325 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:337:26 + --> $DIR/methods.rs:328:26 | -337 | let bad_slice = &some_vec[..].iter_mut().nth(3); +328 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:340:29 + --> $DIR/methods.rs:331:29 | -340 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +331 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:352:13 + --> $DIR/methods.rs:343:13 | -352 | let _ = some_vec.iter().skip(42).next(); +343 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:353:13 + --> $DIR/methods.rs:344:13 | -353 | let _ = some_vec.iter().cycle().skip(42).next(); +344 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:354:13 + --> $DIR/methods.rs:345:13 | -354 | let _ = (1..10).skip(10).next(); +345 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:355:14 + --> $DIR/methods.rs:346:14 | -355 | let _ = &some_vec[..].iter().skip(3).next(); +346 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:381:17 + --> $DIR/methods.rs:372:17 | -381 | let _ = boxed_slice.get(1).unwrap(); +372 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:382:17 + --> $DIR/methods.rs:373:17 | -382 | let _ = some_slice.get(0).unwrap(); +373 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:383:17 + --> $DIR/methods.rs:374:17 | -383 | let _ = some_vec.get(0).unwrap(); +374 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:384:17 + --> $DIR/methods.rs:375:17 | -384 | let _ = some_vecdeque.get(0).unwrap(); +375 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:385:17 + --> $DIR/methods.rs:376:17 | -385 | let _ = some_hashmap.get(&1).unwrap(); +376 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:386:17 + --> $DIR/methods.rs:377:17 | -386 | let _ = some_btreemap.get(&1).unwrap(); +377 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:391:10 + --> $DIR/methods.rs:382:10 | -391 | *boxed_slice.get_mut(0).unwrap() = 1; +382 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:392:10 + --> $DIR/methods.rs:383:10 | -392 | *some_slice.get_mut(0).unwrap() = 1; +383 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:393:10 + --> $DIR/methods.rs:384:10 | -393 | *some_vec.get_mut(0).unwrap() = 1; +384 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:394:10 + --> $DIR/methods.rs:385:10 | -394 | *some_vecdeque.get_mut(0).unwrap() = 1; +385 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:408:13 + --> $DIR/methods.rs:399:13 | -408 | let _ = opt.unwrap(); +399 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:411:13 + --> $DIR/methods.rs:402:13 | -411 | let _ = res.unwrap(); +402 | let _ = res.unwrap(); | ^^^^^^^^^^^^ | = note: `-D result-unwrap-used` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:413:5 + --> $DIR/methods.rs:404:5 | -413 | res.ok().expect("disaster!"); +404 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:419:5 + --> $DIR/methods.rs:410:5 | -419 | res3.ok().expect("whoof"); +410 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:421:5 + --> $DIR/methods.rs:412:5 | -421 | res4.ok().expect("argh"); +412 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:423:5 + --> $DIR/methods.rs:414:5 | -423 | res5.ok().expect("oops"); +414 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:425:5 + --> $DIR/methods.rs:416:5 | -425 | res6.ok().expect("meh"); +416 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:441:5 - | -441 | s.extend(abc.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` - | - = note: `-D string-extend-chars` implied by `-D warnings` - -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:444:5 - | -444 | s.extend("abc".chars()); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` - -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:447:5 - | -447 | s.extend(def.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` - diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs new file mode 100644 index 00000000000..d99adb19f89 --- /dev/null +++ b/tests/ui/string_extend.rs @@ -0,0 +1,30 @@ +#[derive(Copy, Clone)] +struct HasChars; + +impl HasChars { + fn chars(self) -> std::str::Chars<'static> { + "HasChars".chars() + } +} + +fn main() { + let abc = "abc"; + let def = String::from("def"); + let mut s = String::new(); + + s.push_str(abc); + s.extend(abc.chars()); + + s.push_str("abc"); + s.extend("abc".chars()); + + s.push_str(&def); + s.extend(def.chars()); + + s.extend(abc.chars().skip(1)); + s.extend("abc".chars().skip(1)); + s.extend(['a', 'b', 'c'].iter()); + + let f = HasChars; + s.extend(f.chars()); +} diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr new file mode 100644 index 00000000000..1f6d9400743 --- /dev/null +++ b/tests/ui/string_extend.stderr @@ -0,0 +1,20 @@ +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:16:5 + | +16 | s.extend(abc.chars()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` + | + = note: `-D string-extend-chars` implied by `-D warnings` + +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:19:5 + | +19 | s.extend("abc".chars()); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` + +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:22:5 + | +22 | s.extend(def.chars()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` + -- cgit 1.4.1-3-g733a5 From 90b428e88d3fd5d392ece183347cbfbc8accbd5c Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Tue, 10 Oct 2017 00:03:39 -0500 Subject: move ok_expect tests --- tests/ui/methods.rs | 26 -------------------------- tests/ui/methods.stderr | 44 ++------------------------------------------ tests/ui/ok_expect.rs | 27 +++++++++++++++++++++++++++ tests/ui/ok_expect.stderr | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 68 deletions(-) create mode 100644 tests/ui/ok_expect.rs create mode 100644 tests/ui/ok_expect.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 20776ca15da..e3a75521f30 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -393,32 +393,6 @@ fn get_unwrap() { #[allow(similar_names)] fn main() { - use std::io; - let opt = Some(0); let _ = opt.unwrap(); - - let res: Result = Ok(0); - let _ = res.unwrap(); - - res.ok().expect("disaster!"); - // the following should not warn, since `expect` isn't implemented unless - // the error type implements `Debug` - let res2: Result = Ok(0); - res2.ok().expect("oh noes!"); - let res3: Result>= Ok(0); - res3.ok().expect("whoof"); - let res4: Result = Ok(0); - res4.ok().expect("argh"); - let res5: io::Result = Ok(0); - res5.ok().expect("oops"); - let res6: Result = Ok(0); - res6.ok().expect("meh"); -} - -struct MyError(()); // doesn't implement Debug - -#[derive(Debug)] -struct MyErrorWithParam { - x: T } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 1b5deef998e..18b04371d1b 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -500,50 +500,10 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:399:13 + --> $DIR/methods.rs:397:13 | -399 | let _ = opt.unwrap(); +397 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:402:13 - | -402 | let _ = res.unwrap(); - | ^^^^^^^^^^^^ - | - = note: `-D result-unwrap-used` implied by `-D warnings` - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:404:5 - | -404 | res.ok().expect("disaster!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D ok-expect` implied by `-D warnings` - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:410:5 - | -410 | res3.ok().expect("whoof"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:412:5 - | -412 | res4.ok().expect("argh"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:414:5 - | -414 | res5.ok().expect("oops"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:416:5 - | -416 | res6.ok().expect("meh"); - | ^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs new file mode 100644 index 00000000000..4341e8ea70b --- /dev/null +++ b/tests/ui/ok_expect.rs @@ -0,0 +1,27 @@ +use std::io; + +struct MyError(()); // doesn't implement Debug + +#[derive(Debug)] +struct MyErrorWithParam { + x: T +} + +fn main() { + let res: Result = Ok(0); + let _ = res.unwrap(); + + res.ok().expect("disaster!"); + // the following should not warn, since `expect` isn't implemented unless + // the error type implements `Debug` + let res2: Result = Ok(0); + res2.ok().expect("oh noes!"); + let res3: Result>= Ok(0); + res3.ok().expect("whoof"); + let res4: Result = Ok(0); + res4.ok().expect("argh"); + let res5: io::Result = Ok(0); + res5.ok().expect("oops"); + let res6: Result = Ok(0); + res6.ok().expect("meh"); +} diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr new file mode 100644 index 00000000000..79b09b3fa8a --- /dev/null +++ b/tests/ui/ok_expect.stderr @@ -0,0 +1,32 @@ +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:14:5 + | +14 | res.ok().expect("disaster!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D ok-expect` implied by `-D warnings` + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:20:5 + | +20 | res3.ok().expect("whoof"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:22:5 + | +22 | res4.ok().expect("argh"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:24:5 + | +24 | res5.ok().expect("oops"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:26:5 + | +26 | res6.ok().expect("meh"); + | ^^^^^^^^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 35882b09da379f63f39c4368e85ba6b3e0c57c44 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Tue, 10 Oct 2017 00:14:47 -0500 Subject: move get_unwrap tests --- tests/ui/get_unwrap.rs | 46 ++++++++++++++++++++++++++++++++ tests/ui/get_unwrap.stderr | 62 +++++++++++++++++++++++++++++++++++++++++++ tests/ui/methods.rs | 42 ----------------------------- tests/ui/methods.stderr | 66 ++-------------------------------------------- 4 files changed, 110 insertions(+), 106 deletions(-) create mode 100644 tests/ui/get_unwrap.rs create mode 100644 tests/ui/get_unwrap.stderr diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs new file mode 100644 index 00000000000..a10d4d18262 --- /dev/null +++ b/tests/ui/get_unwrap.rs @@ -0,0 +1,46 @@ +#![allow(unused_mut)] + +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::collections::VecDeque; +use std::iter::FromIterator; + +struct GetFalsePositive { + arr: [u32; 3], +} + +impl GetFalsePositive { + fn get(&self, pos: usize) -> Option<&u32> { self.arr.get(pos) } + fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { self.arr.get_mut(pos) } +} + +fn main() { + let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); + let mut some_slice = &mut [0, 1, 2, 3]; + let mut some_vec = vec![0, 1, 2, 3]; + let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect(); + let mut some_hashmap: HashMap = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; + + { // Test `get().unwrap()` + let _ = boxed_slice.get(1).unwrap(); + let _ = some_slice.get(0).unwrap(); + let _ = some_vec.get(0).unwrap(); + let _ = some_vecdeque.get(0).unwrap(); + let _ = some_hashmap.get(&1).unwrap(); + let _ = some_btreemap.get(&1).unwrap(); + let _ = false_positive.get(0).unwrap(); + } + + { // Test `get_mut().unwrap()` + *boxed_slice.get_mut(0).unwrap() = 1; + *some_slice.get_mut(0).unwrap() = 1; + *some_vec.get_mut(0).unwrap() = 1; + *some_vecdeque.get_mut(0).unwrap() = 1; + // Check false positives + *some_hashmap.get_mut(&1).unwrap() = 'b'; + *some_btreemap.get_mut(&1).unwrap() = 'b'; + *false_positive.get_mut(0).unwrap() = 1; + } +} diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr new file mode 100644 index 00000000000..3724cbfc852 --- /dev/null +++ b/tests/ui/get_unwrap.stderr @@ -0,0 +1,62 @@ +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:27:17 + | +27 | let _ = boxed_slice.get(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | + = note: `-D get-unwrap` implied by `-D warnings` + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:28:17 + | +28 | let _ = some_slice.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` + +error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:29:17 + | +29 | let _ = some_vec.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` + +error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:30:17 + | +30 | let _ = some_vecdeque.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` + +error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:31:17 + | +31 | let _ = some_hashmap.get(&1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` + +error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:32:17 + | +32 | let _ = some_btreemap.get(&1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` + +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:37:10 + | +37 | *boxed_slice.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` + +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:38:10 + | +38 | *some_slice.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` + +error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:39:10 + | +39 | *some_vec.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` + +error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:40:10 + | +40 | *some_vecdeque.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index e3a75521f30..827d2182cab 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -349,48 +349,6 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -struct GetFalsePositive { - arr: [u32; 3], -} - -impl GetFalsePositive { - fn get(&self, pos: usize) -> Option<&u32> { self.arr.get(pos) } - fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { self.arr.get_mut(pos) } -} - -/// Checks implementation of `GET_UNWRAP` lint -fn get_unwrap() { - let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); - let mut some_slice = &mut [0, 1, 2, 3]; - let mut some_vec = vec![0, 1, 2, 3]; - let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect(); - let mut some_hashmap: HashMap = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]); - let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); - let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; - - { // Test `get().unwrap()` - let _ = boxed_slice.get(1).unwrap(); - let _ = some_slice.get(0).unwrap(); - let _ = some_vec.get(0).unwrap(); - let _ = some_vecdeque.get(0).unwrap(); - let _ = some_hashmap.get(&1).unwrap(); - let _ = some_btreemap.get(&1).unwrap(); - let _ = false_positive.get(0).unwrap(); - } - - { // Test `get_mut().unwrap()` - *boxed_slice.get_mut(0).unwrap() = 1; - *some_slice.get_mut(0).unwrap() = 1; - *some_vec.get_mut(0).unwrap() = 1; - *some_vecdeque.get_mut(0).unwrap() = 1; - // Check false positives - *some_hashmap.get_mut(&1).unwrap() = 'b'; - *some_btreemap.get_mut(&1).unwrap() = 'b'; - *false_positive.get_mut(0).unwrap() = 1; - } -} - - #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 18b04371d1b..167ad8c768e 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -437,72 +437,10 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 346 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:372:17 - | -372 | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` - | - = note: `-D get-unwrap` implied by `-D warnings` - -error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:373:17 - | -373 | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` - -error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:374:17 - | -374 | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` - -error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:375:17 - | -375 | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` - -error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:376:17 - | -376 | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` - -error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:377:17 - | -377 | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` - -error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:382:10 - | -382 | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` - -error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:383:10 - | -383 | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` - -error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:384:10 - | -384 | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` - -error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:385:10 - | -385 | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` - error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:397:13 + --> $DIR/methods.rs:355:13 | -397 | let _ = opt.unwrap(); +355 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From af6e2a1e4e26ce342578607d5a88631be05aea73 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Oct 2017 12:15:55 +0200 Subject: Don't lint accidental "prefixes" on enum variants --- clippy_lints/src/enum_variants.rs | 3 ++- tests/ui/enum_variants.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c4f7f39003e..6dc6f122eba 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -159,7 +159,8 @@ fn check_variant( } for var in &def.variants { let name = var2str(var); - if partial_match(item_name, &name) == item_name_chars { + if partial_match(item_name, &name) == item_name_chars && + name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) { span_lint(cx, lint, var.span, "Variant name starts with the enum's name"); } if partial_rmatch(item_name, &name) == item_name_chars { diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 9901baf9e12..3be01427134 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -102,4 +102,18 @@ mod allowed { } } +// should not lint +enum Pat { + Foo, + Bar, + Path, +} + +// should not lint +enum N { + Pos, + Neg, + Float, +} + fn main() {} -- cgit 1.4.1-3-g733a5 From eb53cca768ea98f36d26abd3960de26d3f1af385 Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Tue, 10 Oct 2017 12:06:01 +0200 Subject: Add lint for opt.map_or(None, f) Change to Warn and add multiline support Fix typo Update reference --- clippy_lints/src/methods.rs | 52 +++++++++ tests/ui/methods.rs | 10 ++ tests/ui/methods.stderr | 265 ++++++++++++++++++++++++-------------------- 3 files changed, 204 insertions(+), 123 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index ca0d7230229..20f07e0df87 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -193,6 +193,24 @@ declare_lint! { `map_or_else(g, f)`" } +/// **What it does:** Checks for usage of `_.map_or(None, _)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.and_then(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// opt.map_or(None, |a| a + 1) +/// ``` +declare_lint! { + pub OPTION_MAP_OR_NONE, + Warn, + "using `Option.map_or(None, f)`, which is more succinctly expressed as \ + `map_or_else(g, f)`" +} + /// **What it does:** Checks for usage of `_.filter(_).next()`. /// /// **Why is this bad?** Readability, this can be written more concisely as @@ -574,6 +592,7 @@ impl LintPass for Pass { OK_EXPECT, OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE, + OPTION_MAP_OR_NONE, OR_FUN_CALL, CHARS_NEXT_CMP, CHARS_LAST_CMP, @@ -620,6 +639,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map_or"]) { + lint_map_or_none(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { lint_filter_next(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { @@ -1220,6 +1241,37 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir } } +/// lint use of `_.map_or(None, _)` for `Option`s +fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { + // check if the first non-self argument to map_or() is None + let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { + match_qpath(&qpath, &paths::OPTION_NONE) + } else { + false + }; + + if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) && map_or_arg_is_none { + // lint message + let msg = "called `map_or(None, f)` on an Option value. This can be done more directly by calling \ + `and_then(f)` instead"; + let map_or_none_snippet = snippet(cx, map_or_args[1].span, ".."); + let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); + let multiline = map_or_func_snippet.lines().count() > 1 || map_or_none_snippet.lines().count() > 1; + if multiline { + span_lint(cx, OPTION_MAP_OR_NONE, expr.span, msg); + } else { + span_note_and_lint( + cx, + OPTION_MAP_OR_NONE, + expr.span, + msg, + expr.span, + &format!("replace `map_or({0}, {1})` with `and_then({1})`", map_or_none_snippet, map_or_func_snippet) + ); + } + } +} + /// lint use of `filter().next()` for `Iterators` fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().next()` is an Iterator diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 827d2182cab..24adbe943e1 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -91,6 +91,7 @@ macro_rules! opt_map { /// Checks implementation of the following lints: /// * `OPTION_MAP_UNWRAP_OR` /// * `OPTION_MAP_UNWRAP_OR_ELSE` +/// * `OPTION_MAP_OR_NONE` fn option_methods() { let opt = Some(1); @@ -137,6 +138,15 @@ fn option_methods() { ); // macro case let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); // should not lint + + // Check OPTION_MAP_OR_NONE + // single line case + let _ = opt.map_or(None, |x| Some(x + 1)); + // multi line case + let _ = opt.map_or(None, |x| { + Some(x + 1) + } + ); } /// Struct to generate false positives for things with .iter() diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 167ad8c768e..a2f310037f5 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -103,344 +103,363 @@ error: unnecessary structure name repetition | ^ help: use the applicable keyword: `Self` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:99:13 + --> $DIR/methods.rs:100:13 | -99 | let _ = opt.map(|x| x + 1) +100 | let _ = opt.map(|x| x + 1) | _____________^ -100 | | -101 | | .unwrap_or(0); // should lint even though this call is on a separate line +101 | | +102 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | = note: `-D option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:103:13 + --> $DIR/methods.rs:104:13 | -103 | let _ = opt.map(|x| { +104 | let _ = opt.map(|x| { | _____________^ -104 | | x + 1 -105 | | } -106 | | ).unwrap_or(0); +105 | | x + 1 +106 | | } +107 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:107:13 + --> $DIR/methods.rs:108:13 | -107 | let _ = opt.map(|x| x + 1) +108 | let _ = opt.map(|x| x + 1) | _____________^ -108 | | .unwrap_or({ -109 | | 0 -110 | | }); +109 | | .unwrap_or({ +110 | | 0 +111 | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:112:13 + --> $DIR/methods.rs:113:13 | -112 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); +113 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:114:13 + --> $DIR/methods.rs:115:13 | -114 | let _ = opt.map(|x| { +115 | let _ = opt.map(|x| { | _____________^ -115 | | Some(x + 1) -116 | | } -117 | | ).unwrap_or(None); +116 | | Some(x + 1) +117 | | } +118 | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:118:13 + --> $DIR/methods.rs:119:13 | -118 | let _ = opt +119 | let _ = opt | _____________^ -119 | | .map(|x| Some(x + 1)) -120 | | .unwrap_or(None); +120 | | .map(|x| Some(x + 1)) +121 | | .unwrap_or(None); | |________________________^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:126:13 + --> $DIR/methods.rs:127:13 | -126 | let _ = opt.map(|x| x + 1) +127 | let _ = opt.map(|x| x + 1) | _____________^ -127 | | -128 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +128 | | +129 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:130:13 + --> $DIR/methods.rs:131:13 | -130 | let _ = opt.map(|x| { +131 | let _ = opt.map(|x| { | _____________^ -131 | | x + 1 -132 | | } -133 | | ).unwrap_or_else(|| 0); +132 | | x + 1 +133 | | } +134 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:134:13 + --> $DIR/methods.rs:135:13 | -134 | let _ = opt.map(|x| x + 1) +135 | let _ = opt.map(|x| x + 1) | _____________^ -135 | | .unwrap_or_else(|| -136 | | 0 -137 | | ); +136 | | .unwrap_or_else(|| +137 | | 0 +138 | | ); + | |_________________^ + +error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/methods.rs:144:13 + | +144 | let _ = opt.map_or(None, |x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D option-map-or-none` implied by `-D warnings` + = note: replace `map_or(None, |x| Some(x + 1))` with `and_then(|x| Some(x + 1))` + +error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/methods.rs:146:13 + | +146 | let _ = opt.map_or(None, |x| { + | _____________^ +147 | | Some(x + 1) +148 | | } +149 | | ); | |_________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:163:24 + --> $DIR/methods.rs:173:24 | -163 | fn filter(self) -> IteratorFalsePositives { +173 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:167:22 + --> $DIR/methods.rs:177:22 | -167 | fn next(self) -> IteratorFalsePositives { +177 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:187:32 + --> $DIR/methods.rs:197:32 | -187 | fn skip(self, _: usize) -> IteratorFalsePositives { +197 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:197:13 + --> $DIR/methods.rs:207:13 | -197 | let _ = v.iter().filter(|&x| *x < 0).next(); +207 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:200:13 + --> $DIR/methods.rs:210:13 | -200 | let _ = v.iter().filter(|&x| { +210 | let _ = v.iter().filter(|&x| { | _____________^ -201 | | *x < 0 -202 | | } -203 | | ).next(); +211 | | *x < 0 +212 | | } +213 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:215:13 + --> $DIR/methods.rs:225:13 | -215 | let _ = v.iter().find(|&x| *x < 0).is_some(); +225 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:218:13 + --> $DIR/methods.rs:228:13 | -218 | let _ = v.iter().find(|&x| { +228 | let _ = v.iter().find(|&x| { | _____________^ -219 | | *x < 0 -220 | | } -221 | | ).is_some(); +229 | | *x < 0 +230 | | } +231 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:224:13 + --> $DIR/methods.rs:234:13 | -224 | let _ = v.iter().position(|&x| x < 0).is_some(); +234 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:227:13 + --> $DIR/methods.rs:237:13 | -227 | let _ = v.iter().position(|&x| { +237 | let _ = v.iter().position(|&x| { | _____________^ -228 | | x < 0 -229 | | } -230 | | ).is_some(); +238 | | x < 0 +239 | | } +240 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:233:13 + --> $DIR/methods.rs:243:13 | -233 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +243 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:236:13 + --> $DIR/methods.rs:246:13 | -236 | let _ = v.iter().rposition(|&x| { +246 | let _ = v.iter().rposition(|&x| { | _____________^ -237 | | x < 0 -238 | | } -239 | | ).is_some(); +247 | | x < 0 +248 | | } +249 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:253:21 + --> $DIR/methods.rs:263:21 | -253 | fn new() -> Foo { Foo } +263 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:271:5 + --> $DIR/methods.rs:281:5 | -271 | with_constructor.unwrap_or(make()); +281 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:274:5 + --> $DIR/methods.rs:284:5 | -274 | with_new.unwrap_or(Vec::new()); +284 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:277:5 + --> $DIR/methods.rs:287:5 | -277 | with_const_args.unwrap_or(Vec::with_capacity(12)); +287 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:280:5 + --> $DIR/methods.rs:290:5 | -280 | with_err.unwrap_or(make()); +290 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:283:5 + --> $DIR/methods.rs:293:5 | -283 | with_err_args.unwrap_or(Vec::with_capacity(12)); +293 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:286:5 + --> $DIR/methods.rs:296:5 | -286 | with_default_trait.unwrap_or(Default::default()); +296 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:289:5 + --> $DIR/methods.rs:299:5 | -289 | with_default_type.unwrap_or(u64::default()); +299 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:292:5 + --> $DIR/methods.rs:302:5 | -292 | with_vec.unwrap_or(vec![]); +302 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:297:5 + --> $DIR/methods.rs:307:5 | -297 | without_default.unwrap_or(Foo::new()); +307 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:300:5 + --> $DIR/methods.rs:310:5 | -300 | map.entry(42).or_insert(String::new()); +310 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:303:5 + --> $DIR/methods.rs:313:5 | -303 | btree.entry(42).or_insert(String::new()); +313 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:306:13 + --> $DIR/methods.rs:316:13 | -306 | let _ = stringy.unwrap_or("".to_owned()); +316 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:317:23 + --> $DIR/methods.rs:327:23 | -317 | let bad_vec = some_vec.iter().nth(3); +327 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:318:26 + --> $DIR/methods.rs:328:26 | -318 | let bad_slice = &some_vec[..].iter().nth(3); +328 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:319:31 + --> $DIR/methods.rs:329:31 | -319 | let bad_boxed_slice = boxed_slice.iter().nth(3); +329 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:320:29 + --> $DIR/methods.rs:330:29 | -320 | let bad_vec_deque = some_vec_deque.iter().nth(3); +330 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:325:23 + --> $DIR/methods.rs:335:23 | -325 | let bad_vec = some_vec.iter_mut().nth(3); +335 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:328:26 + --> $DIR/methods.rs:338:26 | -328 | let bad_slice = &some_vec[..].iter_mut().nth(3); +338 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:331:29 + --> $DIR/methods.rs:341:29 | -331 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +341 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:343:13 + --> $DIR/methods.rs:353:13 | -343 | let _ = some_vec.iter().skip(42).next(); +353 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:344:13 + --> $DIR/methods.rs:354:13 | -344 | let _ = some_vec.iter().cycle().skip(42).next(); +354 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:345:13 + --> $DIR/methods.rs:355:13 | -345 | let _ = (1..10).skip(10).next(); +355 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:346:14 + --> $DIR/methods.rs:356:14 | -346 | let _ = &some_vec[..].iter().skip(3).next(); +356 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:355:13 + --> $DIR/methods.rs:365:13 | -355 | let _ = opt.unwrap(); +365 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From c0fac7cf5624e19adb618477b98078d6e31f5e56 Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Tue, 10 Oct 2017 14:04:41 +0200 Subject: Remove unnecessary borrow --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 20f07e0df87..08c94be27c5 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1245,7 +1245,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { // check if the first non-self argument to map_or() is None let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { - match_qpath(&qpath, &paths::OPTION_NONE) + match_qpath(qpath, &paths::OPTION_NONE) } else { false }; -- cgit 1.4.1-3-g733a5 From 4438c41d145813e61fcb91ef4c4b5d24f7fd6ddd Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Tue, 10 Oct 2017 15:35:24 +0200 Subject: Make suggested changes - Fix copy-paste error - Check for opt.map_or argument after ensuring that opt is an Option - Use span_lint_and_then and span_suggestion - Update reference --- clippy_lints/src/methods.rs | 36 +++++++++++++++++------------------- tests/ui/methods.stderr | 10 ++++++++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 08c94be27c5..d986a548576 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -208,7 +208,7 @@ declare_lint! { pub OPTION_MAP_OR_NONE, Warn, "using `Option.map_or(None, f)`, which is more succinctly expressed as \ - `map_or_else(g, f)`" + `and_then(f)`" } /// **What it does:** Checks for usage of `_.filter(_).next()`. @@ -1243,30 +1243,28 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir /// lint use of `_.map_or(None, _)` for `Option`s fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { - // check if the first non-self argument to map_or() is None - let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { - match_qpath(qpath, &paths::OPTION_NONE) - } else { - false - }; - if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) && map_or_arg_is_none { - // lint message - let msg = "called `map_or(None, f)` on an Option value. This can be done more directly by calling \ - `and_then(f)` instead"; - let map_or_none_snippet = snippet(cx, map_or_args[1].span, ".."); - let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); - let multiline = map_or_func_snippet.lines().count() > 1 || map_or_none_snippet.lines().count() > 1; - if multiline { - span_lint(cx, OPTION_MAP_OR_NONE, expr.span, msg); + if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { + // check if the first non-self argument to map_or() is None + let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { + match_qpath(qpath, &paths::OPTION_NONE) } else { - span_note_and_lint( + false + }; + + if map_or_arg_is_none { + // lint message + let msg = "called `map_or(None, f)` on an Option value. This can be done more directly by calling \ + `and_then(f)` instead"; + let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); + let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); + let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); + span_lint_and_then( cx, OPTION_MAP_OR_NONE, expr.span, msg, - expr.span, - &format!("replace `map_or({0}, {1})` with `and_then({1})`", map_or_none_snippet, map_or_func_snippet) + |db| { db.span_suggestion(expr.span, "try using and_then instead", hint); }, ); } } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index a2f310037f5..97e8c25ad75 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -199,10 +199,9 @@ error: called `map_or(None, f)` on an Option value. This can be done more direct --> $DIR/methods.rs:144:13 | 144 | let _ = opt.map_or(None, |x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | = note: `-D option-map-or-none` implied by `-D warnings` - = note: replace `map_or(None, |x| Some(x + 1))` with `and_then(|x| Some(x + 1))` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead --> $DIR/methods.rs:146:13 @@ -213,6 +212,13 @@ error: called `map_or(None, f)` on an Option value. This can be done more direct 148 | | } 149 | | ); | |_________________^ + | +help: try using and_then instead + | +146 | let _ = opt.and_then(|x| { +147 | Some(x + 1) +148 | }); + | error: unnecessary structure name repetition --> $DIR/methods.rs:173:24 -- cgit 1.4.1-3-g733a5 From 752900ca3b4224437995e49b5b8481bddf4e190f Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Tue, 10 Oct 2017 16:30:10 -0500 Subject: change expect message --- clippy_lints/src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3b158e280ad..d2858ebe2d0 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -567,12 +567,12 @@ fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { }, ExprBlock(ref b) => never_loop_block(b, state), ExprAgain(d) => { - let id = d.target_id.opt_id().expect("continue is missing target id"); + let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); state.continues.insert(id); false }, ExprBreak(d, _) => { - let id = d.target_id.opt_id().expect("break is missing target id"); + let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); state.breaks.insert(id); false }, -- cgit 1.4.1-3-g733a5 From 159cc8413cf0f228a5e590a1d3a88f84c6e6cc4a Mon Sep 17 00:00:00 2001 From: sinkuu Date: Thu, 5 Oct 2017 23:57:31 +0900 Subject: Add implicit_hasher lint (#2101) --- clippy_lints/src/lib.rs | 2 + clippy_lints/src/types.rs | 354 ++++++++++++++++++++++++++++++++++++++-- tests/ui/implicit_hasher.rs | 68 ++++++++ tests/ui/implicit_hasher.stderr | 154 +++++++++++++++++ 4 files changed, 563 insertions(+), 15 deletions(-) create mode 100644 tests/ui/implicit_hasher.rs create mode 100644 tests/ui/implicit_hasher.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0f27a74ac8e..d8f99ae6cb3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -333,6 +333,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box infinite_iter::Pass); reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); + reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -555,6 +556,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::BOX_VEC, types::CAST_LOSSLESS, types::CHAR_LIT_AS_U8, + types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::LINKEDLIST, types::TYPE_COMPLEXITY, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index acea709123b..006833ba934 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,16 +1,19 @@ use reexport::*; use rustc::hir; use rustc::hir::*; -use rustc::hir::intravisit::{walk_ty, FnKind, NestedVisitorMap, Visitor}; +use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use std::cmp::Ordering; +use std::collections::BTreeMap; +use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, - opt_def_id, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, type_size}; + opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, + span_lint_and_then, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -182,21 +185,19 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { match *qpath { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); - for ty in p.segments - .iter() - .flat_map(|seg| seg.parameters.as_ref() - .map_or_else(|| [].iter(), - |params| params.types.iter())) - { + for ty in p.segments.iter().flat_map(|seg| { + seg.parameters + .as_ref() + .map_or_else(|| [].iter(), |params| params.types.iter()) + }) { check_ty(cx, ty, is_local); } }, - QPath::Resolved(None, ref p) => for ty in p.segments - .iter() - .flat_map(|seg| seg.parameters.as_ref() - .map_or_else(|| [].iter(), - |params| params.types.iter())) - { + QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| { + seg.parameters + .as_ref() + .map_or_else(|| [].iter(), |params| params.types.iter()) + }) { check_ty(cx, ty, is_local); }, QPath::TypeRelative(ref ty, ref seg) => { @@ -605,7 +606,7 @@ fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, c let opt = snippet_opt(cx, op.span); let sugg = if let Some(ref snip) = opt { if should_strip_parens(op, snip) { - &snip[1..snip.len()-1] + &snip[1..snip.len() - 1] } else { snip.as_str() } @@ -1449,3 +1450,326 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { } } } + +/// **What it does:** Checks for `impl` or `fn` missing generalization over +/// different hashers and implicitly defaulting to the default hashing +/// algorithm (SipHash). This lint ignores private free-functions. +/// +/// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be +/// used with them. +/// +/// **Known problems:** Suggestions for replacing constructors are not always +/// accurate. +/// +/// **Example:** +/// ```rust +/// impl Serialize for HashMap { ... } +/// +/// pub foo(map: &mut HashMap) { .. } +/// ``` +declare_lint! { + pub IMPLICIT_HASHER, + Warn, + "missing generalization over different hashers" +} + +pub struct ImplicitHasher; + +impl LintPass for ImplicitHasher { + fn get_lints(&self) -> LintArray { + lint_array!(IMPLICIT_HASHER) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { + #[allow(cast_possible_truncation)] + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if let ItemImpl(_, _, _, ref generics, _, ref ty, ref items) = item.node { + let mut vis = ImplicitHasherTypeVisitor::new(cx); + vis.visit_ty(ty); + + for target in vis.found { + let generics_snip = snippet(cx, generics.span, ""); + let generics_snip_trimmed = if generics_snip.len() == 0 { + "" + } else { + // trim `<` `>` + &generics_snip[1..generics_snip.len() - 1] + }; + let generics_span = generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(target.span())) + .and_then(|snip| { + Some(item.span.lo() + ::syntax_pos::BytePos(snip.find("impl")? as u32 + 4)) + }) + .expect("failed to create span for type arguments"); + Span::new(pos, pos, item.span.data().ctxt) + }); + + let mut vis = ImplicitHasherConstructorVisitor::new(cx, target.clone()); + for item in items.iter().map(|item| cx.tcx.hir.impl_item(item.id)) { + vis.visit_impl_item(item); + } + + span_lint_and_then( + cx, + IMPLICIT_HASHER, + target.span(), + &format!("impl for `{}` should be generarized over different hashers", target.type_name()), + move |db| { + db.span_suggestion( + generics_span, + "consider adding a type parameter", + format!( + "<{}{}S: ::std::hash::BuildHasher{}>", + generics_snip_trimmed, + if generics_snip_trimmed.is_empty() { + "" + } else { + ", " + }, + if vis.suggestions.is_empty() { + "" + } else { + // request users to add `Default` bound so that generic constructors can be used + " + Default" + }, + ), + ); + + db.span_suggestion( + target.span(), + "...and change the type to", + format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + ); + + for (span, sugg) in vis.suggestions { + db.span_suggestion(span, "...and use generic constructor here", sugg); + } + }, + ); + } + } + + if let ItemFn(ref decl, .., ref generics, body) = item.node { + if item.vis != Public { + return; + } + + for ty in &decl.inputs { + let mut vis = ImplicitHasherTypeVisitor::new(cx); + vis.visit_ty(ty); + + for target in vis.found { + let generics_snip = snippet(cx, generics.span, ""); + let generics_snip_trimmed = if generics_snip.len() == 0 { + "" + } else { + // trim `<` `>` + &generics_snip[1..generics_snip.len() - 1] + }; + let generics_span = generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(ty.span)) + .and_then(|snip| { + let i = snip.find("fn")?; + Some(item.span.lo() + ::syntax_pos::BytePos(i as u32 + (&snip[i..]).find('(')? as u32)) + }) + .expect("failed to create span for type parameters"); + Span::new(pos, pos, item.span.data().ctxt) + }); + + let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target.clone()); + ctr_vis.visit_body(cx.tcx.hir.body(body)); + assert!(ctr_vis.suggestions.is_empty()); + + span_lint_and_then( + cx, + IMPLICIT_HASHER, + target.span(), + &format!( + "parameter of type `{}` should be generarized over different hashers", + target.type_name() + ), + move |db| { + db.span_suggestion( + generics_span, + "consider adding a type parameter", + format!( + "<{}{}S: ::std::hash::BuildHasher>", + generics_snip_trimmed, + if generics_snip_trimmed.is_empty() { + "" + } else { + ", " + }, + ), + ); + + db.span_suggestion( + target.span(), + "...and change the type to", + format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + ); + }, + ); + } + } + } + } +} + +#[derive(Clone)] +enum ImplicitHasherType<'tcx> { + HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>), + HashSet(Span, Ty<'tcx>, Cow<'static, str>), +} + +impl<'tcx> ImplicitHasherType<'tcx> { + /// Checks that `ty` is a target type without a BuildHasher. + fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { + if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node { + let params = &path.segments.last().as_ref()?.parameters.as_ref()?.types; + let params_len = params.len(); + + let ty = cx.tcx.type_of(opt_def_id(path.def)?); + + if match_path(path, &paths::HASHMAP) && params_len == 2 { + Some(ImplicitHasherType::HashMap( + hir_ty.span, + ty, + snippet(cx, params[0].span, "K"), + snippet(cx, params[1].span, "V"), + )) + } else if match_path(path, &paths::HASHSET) && params_len == 1 { + Some(ImplicitHasherType::HashSet(hir_ty.span, ty, snippet(cx, params[0].span, "T"))) + } else { + None + } + } else { + None + } + } + + fn type_name(&self) -> &'static str { + match *self { + ImplicitHasherType::HashMap(..) => "HashMap", + ImplicitHasherType::HashSet(..) => "HashSet", + } + } + + fn type_arguments(&self) -> String { + match *self { + ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v), + ImplicitHasherType::HashSet(.., ref t) => format!("{}", t), + } + } + + fn ty(&self) -> Ty<'tcx> { + match *self { + ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty, + } + } + + fn span(&self) -> Span { + match *self { + ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span, + } + } +} + +struct ImplicitHasherTypeVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + found: Vec>, +} + +impl<'a, 'tcx: 'a> ImplicitHasherTypeVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + Self { cx, found: vec![] } + } +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { + fn visit_ty(&mut self, t: &'tcx hir::Ty) { + if let Some(target) = ImplicitHasherType::new(self.cx, t) { + self.found.push(target); + } + + walk_ty(self, t); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +/// Looks for default-hasher-dependent constructors like `HashMap::new`. +struct ImplicitHasherConstructorVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + body: Option, + target: ImplicitHasherType<'tcx>, + suggestions: BTreeMap, +} + +impl<'a, 'tcx: 'a> ImplicitHasherConstructorVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'a, 'tcx>, target: ImplicitHasherType<'tcx>) -> Self { + Self { + cx, + body: None, + target, + suggestions: BTreeMap::new(), + } + } +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'tcx> { + fn visit_body(&mut self, body: &'tcx Body) { + self.body = Some(body.id()); + walk_body(self, body); + } + + fn visit_expr(&mut self, e: &'tcx Expr) { + if_let_chain!{[ + let Some(body) = self.body, + let ExprCall(ref fun, ref args) = e.node, + let ExprPath(QPath::TypeRelative(ref ty, ref method)) = fun.node, + let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node, + ], { + if same_tys(self.cx, self.cx.tcx.body_tables(body).expr_ty(e), self.target.ty()) { + return; + } + + if match_path(ty_path, &paths::HASHMAP) { + if method.name == "new" { + self.suggestions + .insert(e.span, "HashMap::default()".to_string()); + } else if method.name == "with_capacity" { + self.suggestions.insert( + e.span, + format!( + "HashMap::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } else if match_path(ty_path, &paths::HASHSET) { + if method.name == "new" { + self.suggestions + .insert(e.span, "HashSet::default()".to_string()); + } else if method.name == "with_capacity" { + self.suggestions.insert( + e.span, + format!( + "HashSet::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } + }} + + walk_expr(self, e); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + } +} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs new file mode 100644 index 00000000000..7e1eef9b11c --- /dev/null +++ b/tests/ui/implicit_hasher.rs @@ -0,0 +1,68 @@ +#![allow(unused)] +//#![feature(plugin)]#![plugin(clippy)] +use std::collections::{HashMap, HashSet}; +use std::cmp::Eq; +use std::hash::{Hash, BuildHasher}; + +trait Foo: Sized { + fn make() -> (Self, Self); +} + +impl Foo for HashMap { + fn make() -> (Self, Self) { + // OK, don't suggest to modify these + let _: HashMap = HashMap::new(); + let _: HashSet = HashSet::new(); + + (HashMap::new(), HashMap::with_capacity(10)) + } +} +impl Foo for (HashMap,) { + fn make() -> (Self, Self) { + ((HashMap::new(),), (HashMap::with_capacity(10),)) + } +} +impl Foo for HashMap { + fn make() -> (Self, Self) { + (HashMap::new(), HashMap::with_capacity(10)) + } +} + +impl Foo for HashMap { + fn make() -> (Self, Self) { + (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + } +} +impl Foo for HashMap { + fn make() -> (Self, Self) { + (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + } +} + + +impl Foo for HashSet { + fn make() -> (Self, Self) { + (HashSet::new(), HashSet::with_capacity(10)) + } +} +impl Foo for HashSet { + fn make() -> (Self, Self) { + (HashSet::new(), HashSet::with_capacity(10)) + } +} + +impl Foo for HashSet { + fn make() -> (Self, Self) { + (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + } +} +impl Foo for HashSet { + fn make() -> (Self, Self) { + (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + } +} + +pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +} + +fn main() {} diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr new file mode 100644 index 00000000000..086362185cf --- /dev/null +++ b/tests/ui/implicit_hasher.stderr @@ -0,0 +1,154 @@ +error: impl for `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:11:35 + | +11 | impl Foo for HashMap { + | ^^^^^^^^^^^^^ + | + = note: `-D implicit-hasher` implied by `-D warnings` +help: consider adding a type parameter + | +11 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +11 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +14 | let _: HashMap = HashMap::default(); + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +15 | let _: HashSet = HashSet::default(); + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +17 | (HashMap::default(), HashMap::with_capacity(10)) + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +17 | (HashMap::new(), HashMap::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: impl for `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:20:36 + | +20 | impl Foo for (HashMap,) { + | ^^^^^^^^^^^^^ + | +help: consider adding a type parameter + | +20 | impl Foo for (HashMap,) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +20 | impl Foo for (HashMap,) { + | ^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +22 | ((HashMap::default(),), (HashMap::with_capacity(10),)) + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +22 | ((HashMap::new(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: impl for `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:25:19 + | +25 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a type parameter + | +25 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +25 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +27 | (HashMap::default(), HashMap::with_capacity(10)) + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +27 | (HashMap::new(), HashMap::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: impl for `HashSet` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:43:32 + | +43 | impl Foo for HashSet { + | ^^^^^^^^^^ + | +help: consider adding a type parameter + | +43 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +43 | impl Foo for HashSet { + | ^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +45 | (HashSet::default(), HashSet::with_capacity(10)) + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +45 | (HashSet::new(), HashSet::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: impl for `HashSet` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:48:19 + | +48 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^ + | +help: consider adding a type parameter + | +48 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +48 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +50 | (HashSet::default(), HashSet::with_capacity(10)) + | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor here + | +50 | (HashSet::new(), HashSet::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: parameter of type `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:65:23 + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^ + | +help: consider adding a type parameter + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: parameter of type `HashSet` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:65:53 + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^ + | +help: consider adding a type parameter + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 5a61d88fa11e649fbd231a523606f5a5c33ce916 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 11 Oct 2017 12:10:10 +0900 Subject: Apply suggestions --- clippy_lints/src/types.rs | 233 +++++++++++++++++++--------------------- clippy_lints/src/utils/mod.rs | 5 +- tests/ui/implicit_hasher.rs | 18 ++++ tests/ui/implicit_hasher.stderr | 122 +++++++++++---------- 4 files changed, 197 insertions(+), 181 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 006833ba934..6d2fee6a8d9 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::subst::Substs; use std::cmp::Ordering; use std::collections::BTreeMap; @@ -11,9 +11,10 @@ use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; +use syntax::errors::DiagnosticBuilder; use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, - opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, - span_lint_and_then, type_size}; + multispan_sugg, opt_def_id, snippet, snippet_opt, span_help_and_lint, span_lint, + span_lint_and_sugg, span_lint_and_then, type_size, same_tys}; use utils::paths; /// Handles all the linting of funky types @@ -1484,140 +1485,129 @@ impl LintPass for ImplicitHasher { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { #[allow(cast_possible_truncation)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemImpl(_, _, _, ref generics, _, ref ty, ref items) = item.node { - let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(ty); - - for target in vis.found { - let generics_snip = snippet(cx, generics.span, ""); - let generics_snip_trimmed = if generics_snip.len() == 0 { - "" - } else { - // trim `<` `>` - &generics_snip[1..generics_snip.len() - 1] - }; - let generics_span = generics.span.substitute_dummy({ - let pos = snippet_opt(cx, item.span.until(target.span())) - .and_then(|snip| { - Some(item.span.lo() + ::syntax_pos::BytePos(snip.find("impl")? as u32 + 4)) - }) - .expect("failed to create span for type arguments"); - Span::new(pos, pos, item.span.data().ctxt) - }); - - let mut vis = ImplicitHasherConstructorVisitor::new(cx, target.clone()); - for item in items.iter().map(|item| cx.tcx.hir.impl_item(item.id)) { - vis.visit_impl_item(item); - } + use syntax_pos::BytePos; + + fn suggestion<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + db: &mut DiagnosticBuilder, + generics_span: Span, + generics_suggestion_span: Span, + target: &ImplicitHasherType, + vis: ImplicitHasherConstructorVisitor, + ) { + let generics_snip = snippet(cx, generics_span, ""); + // trim `<` `>` + let generics_snip = if generics_snip.is_empty() { + "" + } else { + &generics_snip[1..generics_snip.len() - 1] + }; - span_lint_and_then( - cx, - IMPLICIT_HASHER, - target.span(), - &format!("impl for `{}` should be generarized over different hashers", target.type_name()), - move |db| { - db.span_suggestion( - generics_span, - "consider adding a type parameter", - format!( - "<{}{}S: ::std::hash::BuildHasher{}>", - generics_snip_trimmed, - if generics_snip_trimmed.is_empty() { - "" - } else { - ", " - }, - if vis.suggestions.is_empty() { - "" - } else { - // request users to add `Default` bound so that generic constructors can be used - " + Default" - }, - ), - ); + db.span_suggestion( + generics_suggestion_span, + "consider adding a type parameter", + format!( + "<{}{}S: ::std::hash::BuildHasher{}>", + generics_snip, + if generics_snip.is_empty() { "" } else { ", " }, + if vis.suggestions.is_empty() { + "" + } else { + // request users to add `Default` bound so that generic constructors can be used + " + Default" + }, + ), + ); - db.span_suggestion( - target.span(), - "...and change the type to", - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), - ); + db.span_suggestion( + target.span(), + "...and change the type to", + format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + ); - for (span, sugg) in vis.suggestions { - db.span_suggestion(span, "...and use generic constructor here", sugg); - } - }, - ); + if !vis.suggestions.is_empty() { + multispan_sugg(db, "...and use generic constructor".into(), vis.suggestions); } + // for (span, sugg) in vis.suggestions { + // db.span_suggestion(span, "...and use generic constructor here", sugg); + // } } - if let ItemFn(ref decl, .., ref generics, body) = item.node { - if item.vis != Public { - return; - } - - for ty in &decl.inputs { + match item.node { + ItemImpl(_, _, _, ref generics, _, ref ty, ref items) => { let mut vis = ImplicitHasherTypeVisitor::new(cx); vis.visit_ty(ty); - for target in vis.found { - let generics_snip = snippet(cx, generics.span, ""); - let generics_snip_trimmed = if generics_snip.len() == 0 { - "" - } else { - // trim `<` `>` - &generics_snip[1..generics_snip.len() - 1] - }; - let generics_span = generics.span.substitute_dummy({ - let pos = snippet_opt(cx, item.span.until(ty.span)) - .and_then(|snip| { - let i = snip.find("fn")?; - Some(item.span.lo() + ::syntax_pos::BytePos(i as u32 + (&snip[i..]).find('(')? as u32)) - }) - .expect("failed to create span for type parameters"); + for target in &vis.found { + let generics_suggestion_span = generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(target.span())) + .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))) + .expect("failed to create span for type arguments"); Span::new(pos, pos, item.span.data().ctxt) }); - let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target.clone()); - ctr_vis.visit_body(cx.tcx.hir.body(body)); - assert!(ctr_vis.suggestions.is_empty()); + let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); + for item in items.iter().map(|item| cx.tcx.hir.impl_item(item.id)) { + ctr_vis.visit_impl_item(item); + } span_lint_and_then( cx, IMPLICIT_HASHER, target.span(), - &format!( - "parameter of type `{}` should be generarized over different hashers", - target.type_name() - ), + &format!("impl for `{}` should be generarized over different hashers", target.type_name()), move |db| { - db.span_suggestion( - generics_span, - "consider adding a type parameter", - format!( - "<{}{}S: ::std::hash::BuildHasher>", - generics_snip_trimmed, - if generics_snip_trimmed.is_empty() { - "" - } else { - ", " - }, - ), - ); - - db.span_suggestion( - target.span(), - "...and change the type to", - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), - ); + suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis); }, ); } - } + }, + ItemFn(ref decl, .., ref generics, body_id) => { + if item.vis != Public { + return; + } + + let body = cx.tcx.hir.body(body_id); + + for ty in &decl.inputs { + let mut vis = ImplicitHasherTypeVisitor::new(cx); + vis.visit_ty(ty); + + for target in &vis.found { + let generics_suggestion_span = generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(body.arguments[0].pat.span)) + .and_then(|snip| { + let i = snip.find("fn")?; + Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) + }) + .expect("failed to create span for type parameters"); + Span::new(pos, pos, item.span.data().ctxt) + }); + + let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); + ctr_vis.visit_body(body); + assert!(ctr_vis.suggestions.is_empty()); + + span_lint_and_then( + cx, + IMPLICIT_HASHER, + target.span(), + &format!( + "parameter of type `{}` should be generarized over different hashers", + target.type_name() + ), + move |db| { + suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis); + }, + ); + } + } + }, + _ => {}, } } } -#[derive(Clone)] enum ImplicitHasherType<'tcx> { HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>), HashSet(Span, Ty<'tcx>, Cow<'static, str>), @@ -1702,38 +1692,37 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { } /// Looks for default-hasher-dependent constructors like `HashMap::new`. -struct ImplicitHasherConstructorVisitor<'a, 'tcx: 'a> { +struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx: 'a + 'b> { cx: &'a LateContext<'a, 'tcx>, - body: Option, - target: ImplicitHasherType<'tcx>, + body: &'a TypeckTables<'tcx>, + target: &'b ImplicitHasherType<'tcx>, suggestions: BTreeMap, } -impl<'a, 'tcx: 'a> ImplicitHasherConstructorVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>, target: ImplicitHasherType<'tcx>) -> Self { +impl<'a, 'b, 'tcx: 'a + 'b> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { + fn new(cx: &'a LateContext<'a, 'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { Self { cx, - body: None, + body: cx.tables, target, suggestions: BTreeMap::new(), } } } -impl<'a, 'tcx: 'a> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'tcx> { +impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { fn visit_body(&mut self, body: &'tcx Body) { - self.body = Some(body.id()); + self.body = self.cx.tcx.body_tables(body.id()); walk_body(self, body); } fn visit_expr(&mut self, e: &'tcx Expr) { if_let_chain!{[ - let Some(body) = self.body, let ExprCall(ref fun, ref args) = e.node, let ExprPath(QPath::TypeRelative(ref ty, ref method)) = fun.node, let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node, ], { - if same_tys(self.cx, self.cx.tcx.body_tables(body).expr_ty(e), self.target.ty()) { + if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { return; } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 240301708b7..239370d9811 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -664,7 +664,10 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( /// appear once per /// replacement. In human-readable format though, it only appears once before /// the whole suggestion. -pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(Span, String)>) { +pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: I) +where + I: IntoIterator, +{ let sugg = rustc_errors::CodeSuggestion { substitution_parts: sugg.into_iter() .map(|(span, sub)| { diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index 7e1eef9b11c..b6a49869270 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -65,4 +65,22 @@ impl Foo for HashSet { pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { } +macro_rules! gen { + (impl) => { + impl Foo for HashMap { + fn make() -> (Self, Self) { + (HashMap::new(), HashMap::with_capacity(10)) + } + } + }; + + (fn $name:ident) => { + pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + } + } +} + +gen!(impl); +gen!(fn bar); + fn main() {} diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 086362185cf..33788624b92 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -7,28 +7,12 @@ error: impl for `HashMap` should be generarized over different hashers = note: `-D implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -11 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +11 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 11 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -14 | let _: HashMap = HashMap::default(); - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -15 | let _: HashSet = HashSet::default(); - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -17 | (HashMap::default(), HashMap::with_capacity(10)) - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -17 | (HashMap::new(), HashMap::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:20:36 @@ -38,20 +22,12 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -20 | impl Foo for (HashMap,) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +20 | impl Foo for (HashMap,) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 20 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -22 | ((HashMap::default(),), (HashMap::with_capacity(10),)) - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -22 | ((HashMap::new(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:25:19 @@ -61,20 +37,12 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -25 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +25 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 25 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -27 | (HashMap::default(), HashMap::with_capacity(10)) - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -27 | (HashMap::new(), HashMap::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:43:32 @@ -84,20 +52,12 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -43 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +43 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 43 | impl Foo for HashSet { | ^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -45 | (HashSet::default(), HashSet::with_capacity(10)) - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -45 | (HashSet::new(), HashSet::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:48:19 @@ -107,20 +67,12 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -48 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +48 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 48 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -50 | (HashSet::default(), HashSet::with_capacity(10)) - | ^^^^^^^^^^^^^^^^^^ -help: ...and use generic constructor here - | -50 | (HashSet::new(), HashSet::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:65:23 @@ -152,3 +104,57 @@ help: ...and change the type to 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^ +error: impl for `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:70:43 + | +70 | impl Foo for HashMap { + | ^^^^^^^^^^^^^ +... +83 | gen!(impl); + | ----------- in this macro invocation + | +help: consider adding a type parameter + | +70 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +70 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^ + +error: parameter of type `HashMap` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:78:33 + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^ +... +84 | gen!(fn bar); + | ------------- in this macro invocation + | +help: consider adding a type parameter + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: parameter of type `HashSet` should be generarized over different hashers + --> $DIR/implicit_hasher.rs:78:63 + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^ +... +84 | gen!(fn bar); + | ------------- in this macro invocation + | +help: consider adding a type parameter + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and change the type to + | +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { + | ^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 31f16b87b7eb5a771351e11eecd4a9962199ba19 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 11 Oct 2017 23:08:36 +0900 Subject: Use `rustc_typeck::hir_ty_to_ty` --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/types.rs | 12 ++++++----- tests/ui/implicit_hasher.stderr | 48 ++++++++++++++++++++++++++++++----------- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d8f99ae6cb3..412d83d8ec8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -13,6 +13,7 @@ #[macro_use] extern crate rustc; +extern crate rustc_typeck; extern crate syntax; extern crate syntax_pos; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6d2fee6a8d9..18cfbe27cdc 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -5,6 +5,7 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::subst::Substs; +use rustc_typeck::hir_ty_to_ty; use std::cmp::Ordering; use std::collections::BTreeMap; use std::borrow::Cow; @@ -13,8 +14,8 @@ use syntax::attr::IntType; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, - multispan_sugg, opt_def_id, snippet, snippet_opt, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then, type_size, same_tys}; + multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, + span_lint_and_sugg, span_lint_and_then, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -1459,8 +1460,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be /// used with them. /// -/// **Known problems:** Suggestions for replacing constructors are not always -/// accurate. +/// **Known problems:** Suggestions for replacing constructors contains +/// false-positives. Also applying suggestion can require modification of other +/// pieces of code, possibly including external crates. /// /// **Example:** /// ```rust @@ -1620,7 +1622,7 @@ impl<'tcx> ImplicitHasherType<'tcx> { let params = &path.segments.last().as_ref()?.parameters.as_ref()?.types; let params_len = params.len(); - let ty = cx.tcx.type_of(opt_def_id(path.def)?); + let ty = hir_ty_to_ty(cx.tcx, hir_ty); if match_path(path, &paths::HASHMAP) && params_len == 2 { Some(ImplicitHasherType::HashMap( diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 33788624b92..be799f49d00 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -7,12 +7,16 @@ error: impl for `HashMap` should be generarized over different hashers = note: `-D implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -11 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +11 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 11 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^ +help: ...and use generic constructor + | +17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:20:36 @@ -22,12 +26,16 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -20 | impl Foo for (HashMap,) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +20 | impl Foo for (HashMap,) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 20 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^ +help: ...and use generic constructor + | +22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) + | ^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:25:19 @@ -37,12 +45,16 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -25 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +25 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 25 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor + | +27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:43:32 @@ -52,12 +64,16 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -43 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +43 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 43 | impl Foo for HashSet { | ^^^^^^^^^^^^^ +help: ...and use generic constructor + | +45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:48:19 @@ -67,12 +83,16 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -48 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +48 | impl Foo for HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 48 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^ +help: ...and use generic constructor + | +50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:65:23 @@ -115,12 +135,16 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -70 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +70 | impl Foo for HashMap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and change the type to | 70 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^ +help: ...and use generic constructor + | +72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + | ^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:78:33 -- cgit 1.4.1-3-g733a5 From 888076b698fb8212c135f361eaa12843d6959cf1 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 12 Oct 2017 03:18:43 -0300 Subject: Add suggest_print lint --- clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/suggest_print.rs | 102 ++++++++++++++++++++++++++++++++++++++ tests/ui/suggest_print.rs | 46 +++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 clippy_lints/src/suggest_print.rs create mode 100644 tests/ui/suggest_print.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0f27a74ac8e..2e481151d29 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -145,6 +145,7 @@ pub mod serde_api; pub mod shadow; pub mod should_assert_eq; pub mod strings; +pub mod suggest_print; pub mod swap; pub mod temporary_assignment; pub mod transmute; @@ -326,6 +327,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount); reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box should_assert_eq::ShouldAssertEq); + reg.register_late_lint_pass(box suggest_print::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); reg.register_late_lint_pass(box use_self::UseSelf); @@ -540,6 +542,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { serde_api::SERDE_API_MISUSE, should_assert_eq::SHOULD_ASSERT_EQ, strings::STRING_LIT_AS_BYTES, + suggest_print::SUGGEST_PRINT, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs new file mode 100644 index 00000000000..0ef7f1fe56f --- /dev/null +++ b/clippy_lints/src/suggest_print.rs @@ -0,0 +1,102 @@ +use rustc::hir::*; +use rustc::lint::*; +use utils::{is_expn_of, match_def_path, resolve_node, span_lint}; +use utils::opt_def_id; + +/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be +/// replaced with `(e)print!()` / `(e)println!()` +/// +/// **Why is this bad?** Using `(e)println! is clearer and more concise +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // this would be clearer as `eprintln!("foo: {:?}", bar);` +/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); +/// ``` +declare_lint! { + pub SUGGEST_PRINT, + Warn, + "using `write!()` family of functions instead of `print!()` family of \ + functions" +} + +#[derive(Copy, Clone, Debug)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!( + SUGGEST_PRINT + ) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_let_chain! {[ + // match call to unwrap + let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node, + unwrap_fun.name == "unwrap", + // match call to write_fmt + unwrap_args.len() > 0, + let ExprMethodCall(ref write_fun, _, ref write_args) = + unwrap_args[0].node, + write_fun.name == "write_fmt", + // match calls to std::io::stdout() / std::io::stderr () + write_args.len() > 0, + let ExprCall(ref dest_fun, _) = write_args[0].node, + let ExprPath(ref qpath) = dest_fun.node, + let Some(dest_fun_id) = + opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)), + let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdout"]) { + Some("stdout") + } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stderr"]) { + Some("stderr") + } else { + None + }, + ], { + let dest_expr = &write_args[0]; + let (span, calling_macro) = + if let Some(span) = is_expn_of(dest_expr.span, "write") { + (span, Some("write")) + } else if let Some(span) = is_expn_of(dest_expr.span, "writeln") { + (span, Some("writeln")) + } else { + (dest_expr.span, None) + }; + let prefix = if dest_name == "stderr" { + "e" + } else { + "" + }; + if let Some(macro_name) = calling_macro { + span_lint( + cx, + SUGGEST_PRINT, + span, + &format!( + "use of `{}!({}, ...).unwrap()`. Consider using `{}{}!` instead", + macro_name, + dest_name, + prefix, + macro_name.replace("write", "print") + ) + ); + } else { + span_lint( + cx, + SUGGEST_PRINT, + span, + &format!( + "use of `{}.write_fmt(...).unwrap()`. Consider using `{}print!` instead", + dest_name, + prefix, + ) + ); + } + }} + } +} diff --git a/tests/ui/suggest_print.rs b/tests/ui/suggest_print.rs new file mode 100644 index 00000000000..0466d6c0b60 --- /dev/null +++ b/tests/ui/suggest_print.rs @@ -0,0 +1,46 @@ +#![warn(suggest_print)] + + +fn stdout() -> String { + String::new() +} + +fn stderr() -> String { + String::new() +} + +fn main() { + // these should warn + { + use std::io::Write; + write!(std::io::stdout(), "test").unwrap(); + write!(std::io::stderr(), "test").unwrap(); + writeln!(std::io::stdout(), "test").unwrap(); + writeln!(std::io::stderr(), "test").unwrap(); + std::io::stdout().write_fmt(format_args!("test")).unwrap(); + std::io::stderr().write_fmt(format_args!("test")).unwrap(); + } + // these should not warn, different destination + { + use std::fmt::Write; + let mut s = String::new(); + write!(s, "test").unwrap(); + write!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + write!(stdout(), "test").unwrap(); + write!(stderr(), "test").unwrap(); + writeln!(stdout(), "test").unwrap(); + writeln!(stderr(), "test").unwrap(); + stdout().write_fmt(format_args!("test")).unwrap(); + stderr().write_fmt(format_args!("test")).unwrap(); + } + // these should not warn, no unwrap + { + use std::io::Write; + std::io::stdout().write_fmt(format_args!("test")).expect("no stdout"); + std::io::stderr().write_fmt(format_args!("test")).expect("no stderr"); + } +} -- cgit 1.4.1-3-g733a5 From 10893805185d102c038beb196b030edf7797c114 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 12 Oct 2017 05:33:00 -0300 Subject: Add expected output --- tests/ui/suggest_print.stderr | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/ui/suggest_print.stderr diff --git a/tests/ui/suggest_print.stderr b/tests/ui/suggest_print.stderr new file mode 100644 index 00000000000..f83f6cf7ad3 --- /dev/null +++ b/tests/ui/suggest_print.stderr @@ -0,0 +1,38 @@ +error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead + --> $DIR/suggest_print.rs:16:16 + | +16 | write!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D suggest-print` implied by `-D warnings` + +error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead + --> $DIR/suggest_print.rs:17:16 + | +17 | write!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^ + +error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead + --> $DIR/suggest_print.rs:18:18 + | +18 | writeln!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^ + +error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead + --> $DIR/suggest_print.rs:19:18 + | +19 | writeln!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^ + +error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead + --> $DIR/suggest_print.rs:20:9 + | +20 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^ + +error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead + --> $DIR/suggest_print.rs:21:9 + | +21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 4105593eeeeb2ce0a7d6fb338fe71ea10c68f965 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 12 Oct 2017 05:35:13 -0300 Subject: Run rustfmt --- clippy_lints/src/suggest_print.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs index 0ef7f1fe56f..1bc58297476 100644 --- a/clippy_lints/src/suggest_print.rs +++ b/clippy_lints/src/suggest_print.rs @@ -27,9 +27,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!( - SUGGEST_PRINT - ) + lint_array!(SUGGEST_PRINT) } } @@ -50,9 +48,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprPath(ref qpath) = dest_fun.node, let Some(dest_fun_id) = opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)), - let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdout"]) { + let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { Some("stdout") - } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stderr"]) { + } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) { Some("stderr") } else { None -- cgit 1.4.1-3-g733a5 From e31a0941e20851933eb80b14da8d2a11b6f614b1 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 12 Oct 2017 05:53:20 -0300 Subject: Fix output for write macros --- clippy_lints/src/suggest_print.rs | 23 ++++++++++++----------- tests/ui/suggest_print.stderr | 32 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs index 1bc58297476..bf202b20057 100644 --- a/clippy_lints/src/suggest_print.rs +++ b/clippy_lints/src/suggest_print.rs @@ -56,14 +56,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { None }, ], { - let dest_expr = &write_args[0]; - let (span, calling_macro) = - if let Some(span) = is_expn_of(dest_expr.span, "write") { - (span, Some("write")) - } else if let Some(span) = is_expn_of(dest_expr.span, "writeln") { - (span, Some("writeln")) + let write_span = unwrap_args[0].span; + let calling_macro = + // ordering is important here, since `writeln!` uses `write!` internally + if is_expn_of(write_span, "writeln").is_some() { + Some("writeln") + } else if is_expn_of(write_span, "write").is_some() { + Some("write") } else { - (dest_expr.span, None) + None }; let prefix = if dest_name == "stderr" { "e" @@ -74,9 +75,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span_lint( cx, SUGGEST_PRINT, - span, + expr.span, &format!( - "use of `{}!({}, ...).unwrap()`. Consider using `{}{}!` instead", + "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", macro_name, dest_name, prefix, @@ -87,9 +88,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span_lint( cx, SUGGEST_PRINT, - span, + expr.span, &format!( - "use of `{}.write_fmt(...).unwrap()`. Consider using `{}print!` instead", + "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix, ) diff --git a/tests/ui/suggest_print.stderr b/tests/ui/suggest_print.stderr index f83f6cf7ad3..bae9f6f2679 100644 --- a/tests/ui/suggest_print.stderr +++ b/tests/ui/suggest_print.stderr @@ -1,38 +1,38 @@ -error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/suggest_print.rs:16:16 +error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead + --> $DIR/suggest_print.rs:16:9 | 16 | write!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D suggest-print` implied by `-D warnings` -error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/suggest_print.rs:17:16 +error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead + --> $DIR/suggest_print.rs:17:9 | 17 | write!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/suggest_print.rs:18:18 +error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead + --> $DIR/suggest_print.rs:18:9 | 18 | writeln!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/suggest_print.rs:19:18 +error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead + --> $DIR/suggest_print.rs:19:9 | 19 | writeln!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of `stdout.write_fmt(...).unwrap()`. Consider using `print!` instead +error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead --> $DIR/suggest_print.rs:20:9 | 20 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of `stderr.write_fmt(...).unwrap()`. Consider using `eprint!` instead +error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead --> $DIR/suggest_print.rs:21:9 | 21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From a46bf3f456ee5d0bfade70dcddbad6496c5575d0 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 12 Oct 2017 05:54:33 -0300 Subject: Clarify lint description --- clippy_lints/src/suggest_print.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs index bf202b20057..eb1266af7b7 100644 --- a/clippy_lints/src/suggest_print.rs +++ b/clippy_lints/src/suggest_print.rs @@ -19,7 +19,7 @@ declare_lint! { pub SUGGEST_PRINT, Warn, "using `write!()` family of functions instead of `print!()` family of \ - functions" + functions, when using the latter would work" } #[derive(Copy, Clone, Debug)] -- cgit 1.4.1-3-g733a5 From c3332ca92e646f7f360817b2a72f830fef9ad1b3 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Thu, 12 Oct 2017 23:24:21 +0900 Subject: Fix panic with fake `Range` type --- clippy_lints/src/utils/higher.rs | 17 ++++++++--------- tests/ui/range.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 550ecedeae4..d162dea7f11 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -50,8 +50,7 @@ pub fn range(expr: &hir::Expr) -> Option { fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { let expr = &fields .iter() - .find(|field| field.name.node == name) - .unwrap_or_else(|| panic!("missing {} field for range", name)) + .find(|field| field.name.node == name)? .expr; Some(expr) @@ -77,32 +76,32 @@ pub fn range(expr: &hir::Expr) -> Option { match_qpath(path, &paths::RANGE_FROM) { Some(Range { - start: get_field("start", fields), + start: Some(get_field("start", fields)?), end: None, limits: ast::RangeLimits::HalfOpen, }) } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), + start: Some(get_field("start", fields)?), + end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, }) } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), + start: Some(get_field("start", fields)?), + end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, }) } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { Some(Range { start: None, - end: get_field("end", fields), + end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, }) } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { Some(Range { start: None, - end: get_field("end", fields), + end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, }) } else { diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 71f2f2b219b..d9db28c8513 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -32,3 +32,12 @@ fn main() { // check const eval let _ = v1.iter().step_by(2/3); } + +#[allow(unused)] +fn no_panic_with_fake_range_types() { + struct Range { + foo: i32, + } + + let _ = Range { foo: 0 }; +} -- cgit 1.4.1-3-g733a5 From f68e408cb6d0bb0a548b1ed54213e04b245f92cf Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Sat, 30 Sep 2017 11:33:15 +0300 Subject: identity_op lint fix for '&' with unsigned types --- clippy_lints/src/identity_op.rs | 25 +++++++++++++++++++------ tests/ui/identity_op.rs | 3 +++ tests/ui/identity_op.stderr | 6 ++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index a409f4c7d65..21aa914155e 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,9 +1,9 @@ use consts::{constant_simple, Constant}; -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; +use rustc_const_math::ConstInt; use syntax::codemap::Span; use utils::{in_macro, snippet, span_lint}; -use syntax::attr::IntType::{SignedInt, UnsignedInt}; /// **What it does:** Checks for identity operations, e.g. `x + 0`. /// @@ -58,15 +58,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } +fn no_zeros(v: &ConstInt) -> bool { + match *v { + ConstInt::I8(i) => i.count_zeros() == 0, + ConstInt::I16(i) => i.count_zeros() == 0, + ConstInt::I32(i) => i.count_zeros() == 0, + ConstInt::I64(i) => i.count_zeros() == 0, + ConstInt::I128(i) => i.count_zeros() == 0, + ConstInt::U8(i) => i.count_zeros() == 0, + ConstInt::U16(i) => i.count_zeros() == 0, + ConstInt::U32(i) => i.count_zeros() == 0, + ConstInt::U64(i) => i.count_zeros() == 0, + ConstInt::U128(i) => i.count_zeros() == 0, + _ => false + } +} + #[allow(cast_possible_wrap)] fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { 0 => v.to_u128_unchecked() == 0, - -1 => match v.int_type() { - SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), - UnsignedInt(_) => false, - }, + -1 => no_zeros(&v), 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), } { diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index b474344977c..1ed9f974d43 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -27,4 +27,7 @@ fn main() { x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; + + let u : u8 = 0; + u & 255; } diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 30367c989ec..c1ce8d2ec4c 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -42,3 +42,9 @@ error: the operation is ineffective. Consider reducing it to `x` 29 | -1 & x; | ^^^^^^ +error: the operation is ineffective. Consider reducing it to `u` + --> $DIR/identity_op.rs:32:5 + | +32 | u & 255; + | ^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 033c99b1baaa87587132debafaa8d2d0ccb7dde8 Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Sat, 30 Sep 2017 20:14:00 +0300 Subject: Add erasing_op lint For expressions that can be replaced by a zero. --- clippy_lints/src/erasing_op.rs | 62 ++++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 2 ++ tests/ui/bit_masks.stderr | 14 ++++++++++ tests/ui/erasing_op.rs | 12 ++++++++ tests/ui/erasing_op.stderr | 20 ++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 clippy_lints/src/erasing_op.rs create mode 100644 tests/ui/erasing_op.rs create mode 100644 tests/ui/erasing_op.stderr diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs new file mode 100644 index 00000000000..7b5b4a3d3af --- /dev/null +++ b/clippy_lints/src/erasing_op.rs @@ -0,0 +1,62 @@ +use consts::{constant_simple, Constant}; +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::Span; +use utils::{in_macro, span_lint}; + +/// **What it does:** Checks for erasing operations, e.g. `x * 0`. +/// +/// **Why is this bad?** The whole expression can be replaced by zero. +/// Most likely mistake was made and code should be reviewed or simplified. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// 0 / x; 0 * x; x & 0 +/// ``` +declare_lint! { + pub ERASING_OP, + Warn, + "using erasing operations, e.g. `x * 0` or `y & 0`" +} + +#[derive(Copy, Clone)] +pub struct ErasingOp; + +impl LintPass for ErasingOp { + fn get_lints(&self) -> LintArray { + lint_array!(ERASING_OP) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if in_macro(e.span) { + return; + } + if let ExprBinary(ref cmp, ref left, ref right) = e.node { + match cmp.node { + BiMul | BiBitAnd => { + check(cx, left, e.span); + check(cx, right, e.span); + }, + BiDiv => check(cx, left, e.span), + _ => (), + } + } + } +} + +fn check(cx: &LateContext, e: &Expr, span: Span) { + if let Some(Constant::Int(v)) = constant_simple(cx, e) { + if v.to_u128_unchecked() == 0 { + span_lint( + cx, + ERASING_OP, + span, + "the operation is ineffective. Consider reducing it to `0`", + ); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0f27a74ac8e..6c85b9efa55 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -86,6 +86,7 @@ pub mod entry; pub mod enum_clike; pub mod enum_glob_use; pub mod enum_variants; +pub mod erasing_op; pub mod eq_op; pub mod escape; pub mod eta_reduction; @@ -246,6 +247,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box needless_continue::NeedlessContinue); reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); + reg.register_late_lint_pass(box erasing_op::ErasingOp); reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements); reg.register_late_lint_pass(box mut_mut::MutMut); reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 9f2c2d0a2c4..45b8bbe6d9e 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -6,6 +6,14 @@ error: &-masking with zero | = note: `-D bad-bit-mask` implied by `-D warnings` +error: the operation is ineffective. Consider reducing it to `0` + --> $DIR/bit_masks.rs:12:5 + | +12 | x & 0 == 0; + | ^^^^^ + | + = note: `-D erasing-op` implied by `-D warnings` + error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:15:5 | @@ -48,6 +56,12 @@ error: &-masking with zero 35 | 0 & x == 0; | ^^^^^^^^^^ +error: the operation is ineffective. Consider reducing it to `0` + --> $DIR/bit_masks.rs:35:5 + | +35 | 0 & x == 0; + | ^^^^^ + error: incompatible bit mask: `_ | 2` will always be higher than `1` --> $DIR/bit_masks.rs:39:5 | diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs new file mode 100644 index 00000000000..e5143146f26 --- /dev/null +++ b/tests/ui/erasing_op.rs @@ -0,0 +1,12 @@ + + + +#[allow(no_effect)] +#[warn(erasing_op)] +fn main() { + let x: u8 = 0; + + x * 0; + 0 & x; + 0 / x; +} diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr new file mode 100644 index 00000000000..496c297ef2b --- /dev/null +++ b/tests/ui/erasing_op.stderr @@ -0,0 +1,20 @@ +error: the operation is ineffective. Consider reducing it to `0` + --> $DIR/erasing_op.rs:9:5 + | +9 | x * 0; + | ^^^^^ + | + = note: `-D erasing-op` implied by `-D warnings` + +error: the operation is ineffective. Consider reducing it to `0` + --> $DIR/erasing_op.rs:10:5 + | +10 | 0 & x; + | ^^^^^ + +error: the operation is ineffective. Consider reducing it to `0` + --> $DIR/erasing_op.rs:11:5 + | +11 | 0 / x; + | ^^^^^ + -- cgit 1.4.1-3-g733a5 From 46d6f2454e994fbaf7caddfb3c34c82895c805b3 Mon Sep 17 00:00:00 2001 From: Joe Rattazzi Date: Sat, 14 Oct 2017 14:47:38 -0500 Subject: Add link to Rust Github Linking to the Rust-lang Github repository: https://github.com/rust-lang/rust --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ef61a9df0f..26e7f12dc83 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) -A collection of lints to catch common mistakes and improve your Rust code. +A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. [There are 209 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) -- cgit 1.4.1-3-g733a5 From aeeb38dab13742935df22408ec805f7196fece01 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sat, 14 Oct 2017 21:26:39 -0300 Subject: Change lint name From `suggest_print` to `explicit_write` --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/suggest_print.rs | 8 ++++---- tests/ui/suggest_print.rs | 2 +- tests/ui/suggest_print.stderr | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2e481151d29..8ea4aa35140 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -542,7 +542,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { serde_api::SERDE_API_MISUSE, should_assert_eq::SHOULD_ASSERT_EQ, strings::STRING_LIT_AS_BYTES, - suggest_print::SUGGEST_PRINT, + suggest_print::EXPLICIT_WRITE, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs index eb1266af7b7..8349328a18a 100644 --- a/clippy_lints/src/suggest_print.rs +++ b/clippy_lints/src/suggest_print.rs @@ -16,7 +16,7 @@ use utils::opt_def_id; /// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); /// ``` declare_lint! { - pub SUGGEST_PRINT, + pub EXPLICIT_WRITE, Warn, "using `write!()` family of functions instead of `print!()` family of \ functions, when using the latter would work" @@ -27,7 +27,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(SUGGEST_PRINT) + lint_array!(EXPLICIT_WRITE) } } @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(macro_name) = calling_macro { span_lint( cx, - SUGGEST_PRINT, + EXPLICIT_WRITE, expr.span, &format!( "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } else { span_lint( cx, - SUGGEST_PRINT, + EXPLICIT_WRITE, expr.span, &format!( "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", diff --git a/tests/ui/suggest_print.rs b/tests/ui/suggest_print.rs index 0466d6c0b60..71992123ceb 100644 --- a/tests/ui/suggest_print.rs +++ b/tests/ui/suggest_print.rs @@ -1,4 +1,4 @@ -#![warn(suggest_print)] +#![warn(explicit_write)] fn stdout() -> String { diff --git a/tests/ui/suggest_print.stderr b/tests/ui/suggest_print.stderr index bae9f6f2679..12e656b5540 100644 --- a/tests/ui/suggest_print.stderr +++ b/tests/ui/suggest_print.stderr @@ -4,7 +4,7 @@ error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead 16 | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D suggest-print` implied by `-D warnings` + = note: `-D explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead --> $DIR/suggest_print.rs:17:9 -- cgit 1.4.1-3-g733a5 From eda013d3afd6311f1fd5bad56155d4ce7b76eb66 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sat, 14 Oct 2017 21:42:14 -0300 Subject: Change lint filename suggest_print.rs -> explicit_write.rs --- clippy_lints/src/explicit_write.rs | 101 +++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 6 +-- clippy_lints/src/suggest_print.rs | 101 ------------------------------------- tests/ui/explicit_write.rs | 46 +++++++++++++++++ tests/ui/explicit_write.stderr | 38 ++++++++++++++ tests/ui/suggest_print.rs | 46 ----------------- tests/ui/suggest_print.stderr | 38 -------------- 7 files changed, 188 insertions(+), 188 deletions(-) create mode 100644 clippy_lints/src/explicit_write.rs delete mode 100644 clippy_lints/src/suggest_print.rs create mode 100644 tests/ui/explicit_write.rs create mode 100644 tests/ui/explicit_write.stderr delete mode 100644 tests/ui/suggest_print.rs delete mode 100644 tests/ui/suggest_print.stderr diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs new file mode 100644 index 00000000000..8349328a18a --- /dev/null +++ b/clippy_lints/src/explicit_write.rs @@ -0,0 +1,101 @@ +use rustc::hir::*; +use rustc::lint::*; +use utils::{is_expn_of, match_def_path, resolve_node, span_lint}; +use utils::opt_def_id; + +/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be +/// replaced with `(e)print!()` / `(e)println!()` +/// +/// **Why is this bad?** Using `(e)println! is clearer and more concise +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // this would be clearer as `eprintln!("foo: {:?}", bar);` +/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); +/// ``` +declare_lint! { + pub EXPLICIT_WRITE, + Warn, + "using `write!()` family of functions instead of `print!()` family of \ + functions, when using the latter would work" +} + +#[derive(Copy, Clone, Debug)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(EXPLICIT_WRITE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_let_chain! {[ + // match call to unwrap + let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node, + unwrap_fun.name == "unwrap", + // match call to write_fmt + unwrap_args.len() > 0, + let ExprMethodCall(ref write_fun, _, ref write_args) = + unwrap_args[0].node, + write_fun.name == "write_fmt", + // match calls to std::io::stdout() / std::io::stderr () + write_args.len() > 0, + let ExprCall(ref dest_fun, _) = write_args[0].node, + let ExprPath(ref qpath) = dest_fun.node, + let Some(dest_fun_id) = + opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)), + let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { + Some("stdout") + } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) { + Some("stderr") + } else { + None + }, + ], { + let write_span = unwrap_args[0].span; + let calling_macro = + // ordering is important here, since `writeln!` uses `write!` internally + if is_expn_of(write_span, "writeln").is_some() { + Some("writeln") + } else if is_expn_of(write_span, "write").is_some() { + Some("write") + } else { + None + }; + let prefix = if dest_name == "stderr" { + "e" + } else { + "" + }; + if let Some(macro_name) = calling_macro { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", + macro_name, + dest_name, + prefix, + macro_name.replace("write", "print") + ) + ); + } else { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", + dest_name, + prefix, + ) + ); + } + }} + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8ea4aa35140..a2878b8640c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -145,7 +145,7 @@ pub mod serde_api; pub mod shadow; pub mod should_assert_eq; pub mod strings; -pub mod suggest_print; +pub mod explicit_write; pub mod swap; pub mod temporary_assignment; pub mod transmute; @@ -327,7 +327,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount); reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box should_assert_eq::ShouldAssertEq); - reg.register_late_lint_pass(box suggest_print::Pass); + reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); reg.register_late_lint_pass(box use_self::UseSelf); @@ -542,7 +542,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { serde_api::SERDE_API_MISUSE, should_assert_eq::SHOULD_ASSERT_EQ, strings::STRING_LIT_AS_BYTES, - suggest_print::EXPLICIT_WRITE, + explicit_write::EXPLICIT_WRITE, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, diff --git a/clippy_lints/src/suggest_print.rs b/clippy_lints/src/suggest_print.rs deleted file mode 100644 index 8349328a18a..00000000000 --- a/clippy_lints/src/suggest_print.rs +++ /dev/null @@ -1,101 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use utils::{is_expn_of, match_def_path, resolve_node, span_lint}; -use utils::opt_def_id; - -/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be -/// replaced with `(e)print!()` / `(e)println!()` -/// -/// **Why is this bad?** Using `(e)println! is clearer and more concise -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// // this would be clearer as `eprintln!("foo: {:?}", bar);` -/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); -/// ``` -declare_lint! { - pub EXPLICIT_WRITE, - Warn, - "using `write!()` family of functions instead of `print!()` family of \ - functions, when using the latter would work" -} - -#[derive(Copy, Clone, Debug)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(EXPLICIT_WRITE) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ - // match call to unwrap - let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node, - unwrap_fun.name == "unwrap", - // match call to write_fmt - unwrap_args.len() > 0, - let ExprMethodCall(ref write_fun, _, ref write_args) = - unwrap_args[0].node, - write_fun.name == "write_fmt", - // match calls to std::io::stdout() / std::io::stderr () - write_args.len() > 0, - let ExprCall(ref dest_fun, _) = write_args[0].node, - let ExprPath(ref qpath) = dest_fun.node, - let Some(dest_fun_id) = - opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)), - let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { - Some("stdout") - } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) { - Some("stderr") - } else { - None - }, - ], { - let write_span = unwrap_args[0].span; - let calling_macro = - // ordering is important here, since `writeln!` uses `write!` internally - if is_expn_of(write_span, "writeln").is_some() { - Some("writeln") - } else if is_expn_of(write_span, "write").is_some() { - Some("write") - } else { - None - }; - let prefix = if dest_name == "stderr" { - "e" - } else { - "" - }; - if let Some(macro_name) = calling_macro { - span_lint( - cx, - EXPLICIT_WRITE, - expr.span, - &format!( - "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", - macro_name, - dest_name, - prefix, - macro_name.replace("write", "print") - ) - ); - } else { - span_lint( - cx, - EXPLICIT_WRITE, - expr.span, - &format!( - "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", - dest_name, - prefix, - ) - ); - } - }} - } -} diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs new file mode 100644 index 00000000000..71992123ceb --- /dev/null +++ b/tests/ui/explicit_write.rs @@ -0,0 +1,46 @@ +#![warn(explicit_write)] + + +fn stdout() -> String { + String::new() +} + +fn stderr() -> String { + String::new() +} + +fn main() { + // these should warn + { + use std::io::Write; + write!(std::io::stdout(), "test").unwrap(); + write!(std::io::stderr(), "test").unwrap(); + writeln!(std::io::stdout(), "test").unwrap(); + writeln!(std::io::stderr(), "test").unwrap(); + std::io::stdout().write_fmt(format_args!("test")).unwrap(); + std::io::stderr().write_fmt(format_args!("test")).unwrap(); + } + // these should not warn, different destination + { + use std::fmt::Write; + let mut s = String::new(); + write!(s, "test").unwrap(); + write!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + write!(stdout(), "test").unwrap(); + write!(stderr(), "test").unwrap(); + writeln!(stdout(), "test").unwrap(); + writeln!(stderr(), "test").unwrap(); + stdout().write_fmt(format_args!("test")).unwrap(); + stderr().write_fmt(format_args!("test")).unwrap(); + } + // these should not warn, no unwrap + { + use std::io::Write; + std::io::stdout().write_fmt(format_args!("test")).expect("no stdout"); + std::io::stderr().write_fmt(format_args!("test")).expect("no stderr"); + } +} diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr new file mode 100644 index 00000000000..9a813e89793 --- /dev/null +++ b/tests/ui/explicit_write.stderr @@ -0,0 +1,38 @@ +error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead + --> $DIR/explicit_write.rs:16:9 + | +16 | write!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D explicit-write` implied by `-D warnings` + +error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead + --> $DIR/explicit_write.rs:17:9 + | +17 | write!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead + --> $DIR/explicit_write.rs:18:9 + | +18 | writeln!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead + --> $DIR/explicit_write.rs:19:9 + | +19 | writeln!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead + --> $DIR/explicit_write.rs:20:9 + | +20 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead + --> $DIR/explicit_write.rs:21:9 + | +21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/suggest_print.rs b/tests/ui/suggest_print.rs deleted file mode 100644 index 71992123ceb..00000000000 --- a/tests/ui/suggest_print.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![warn(explicit_write)] - - -fn stdout() -> String { - String::new() -} - -fn stderr() -> String { - String::new() -} - -fn main() { - // these should warn - { - use std::io::Write; - write!(std::io::stdout(), "test").unwrap(); - write!(std::io::stderr(), "test").unwrap(); - writeln!(std::io::stdout(), "test").unwrap(); - writeln!(std::io::stderr(), "test").unwrap(); - std::io::stdout().write_fmt(format_args!("test")).unwrap(); - std::io::stderr().write_fmt(format_args!("test")).unwrap(); - } - // these should not warn, different destination - { - use std::fmt::Write; - let mut s = String::new(); - write!(s, "test").unwrap(); - write!(s, "test").unwrap(); - writeln!(s, "test").unwrap(); - writeln!(s, "test").unwrap(); - s.write_fmt(format_args!("test")).unwrap(); - s.write_fmt(format_args!("test")).unwrap(); - write!(stdout(), "test").unwrap(); - write!(stderr(), "test").unwrap(); - writeln!(stdout(), "test").unwrap(); - writeln!(stderr(), "test").unwrap(); - stdout().write_fmt(format_args!("test")).unwrap(); - stderr().write_fmt(format_args!("test")).unwrap(); - } - // these should not warn, no unwrap - { - use std::io::Write; - std::io::stdout().write_fmt(format_args!("test")).expect("no stdout"); - std::io::stderr().write_fmt(format_args!("test")).expect("no stderr"); - } -} diff --git a/tests/ui/suggest_print.stderr b/tests/ui/suggest_print.stderr deleted file mode 100644 index 12e656b5540..00000000000 --- a/tests/ui/suggest_print.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead - --> $DIR/suggest_print.rs:16:9 - | -16 | write!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D explicit-write` implied by `-D warnings` - -error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead - --> $DIR/suggest_print.rs:17:9 - | -17 | write!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead - --> $DIR/suggest_print.rs:18:9 - | -18 | writeln!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead - --> $DIR/suggest_print.rs:19:9 - | -19 | writeln!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/suggest_print.rs:20:9 - | -20 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/suggest_print.rs:21:9 - | -21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From 2842038627402052494f03ec32fc0f9dd548b05b Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sat, 14 Oct 2017 21:46:19 -0300 Subject: Improve lint description --- clippy_lints/src/explicit_write.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 8349328a18a..9650dd0909c 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -18,8 +18,8 @@ use utils::opt_def_id; declare_lint! { pub EXPLICIT_WRITE, Warn, - "using `write!()` family of functions instead of `print!()` family of \ - functions, when using the latter would work" + "using the `write!()` family of functions instead of the `print!()` family \ + of functions, when using the latter would work" } #[derive(Copy, Clone, Debug)] -- cgit 1.4.1-3-g733a5 From a5d2bfebc458d0d11a1f0318ee89b1434b6d675c Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Sun, 15 Oct 2017 10:21:56 +0300 Subject: Simplify checking for all ones in int --- clippy_lints/src/identity_op.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 21aa914155e..85dfb6b4ad0 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -58,18 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } -fn no_zeros(v: &ConstInt) -> bool { +fn all_ones(v: &ConstInt) -> bool { match *v { - ConstInt::I8(i) => i.count_zeros() == 0, - ConstInt::I16(i) => i.count_zeros() == 0, - ConstInt::I32(i) => i.count_zeros() == 0, - ConstInt::I64(i) => i.count_zeros() == 0, - ConstInt::I128(i) => i.count_zeros() == 0, - ConstInt::U8(i) => i.count_zeros() == 0, - ConstInt::U16(i) => i.count_zeros() == 0, - ConstInt::U32(i) => i.count_zeros() == 0, - ConstInt::U64(i) => i.count_zeros() == 0, - ConstInt::U128(i) => i.count_zeros() == 0, + ConstInt::I8(i) => i == !0, + ConstInt::I16(i) => i == !0, + ConstInt::I32(i) => i == !0, + ConstInt::I64(i) => i == !0, + ConstInt::I128(i) => i == !0, + ConstInt::U8(i) => i == !0, + ConstInt::U16(i) => i == !0, + ConstInt::U32(i) => i == !0, + ConstInt::U64(i) => i == !0, + ConstInt::U128(i) => i == !0, _ => false } } @@ -79,7 +79,7 @@ fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { 0 => v.to_u128_unchecked() == 0, - -1 => no_zeros(&v), + -1 => all_ones(&v), 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), } { -- cgit 1.4.1-3-g733a5 From 7b16f4d7ff772b2885a4d184ef29af4edc07a144 Mon Sep 17 00:00:00 2001 From: Yury Krivopalov Date: Sun, 15 Oct 2017 10:32:47 +0300 Subject: Clarify message for erasing_op lint --- clippy_lints/src/erasing_op.rs | 5 +++-- tests/ui/bit_masks.stderr | 4 ++-- tests/ui/erasing_op.stderr | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 7b5b4a3d3af..dd8f029501f 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -7,7 +7,8 @@ use utils::{in_macro, span_lint}; /// **What it does:** Checks for erasing operations, e.g. `x * 0`. /// /// **Why is this bad?** The whole expression can be replaced by zero. -/// Most likely mistake was made and code should be reviewed or simplified. +/// This is most likely not the intended outcome and should probably be +/// corrected /// /// **Known problems:** None. /// @@ -55,7 +56,7 @@ fn check(cx: &LateContext, e: &Expr, span: Span) { cx, ERASING_OP, span, - "the operation is ineffective. Consider reducing it to `0`", + "this operation will always return zero. This is likely not the intended outcome", ); } } diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 45b8bbe6d9e..39320bb9c30 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -6,7 +6,7 @@ error: &-masking with zero | = note: `-D bad-bit-mask` implied by `-D warnings` -error: the operation is ineffective. Consider reducing it to `0` +error: this operation will always return zero. This is likely not the intended outcome --> $DIR/bit_masks.rs:12:5 | 12 | x & 0 == 0; @@ -56,7 +56,7 @@ error: &-masking with zero 35 | 0 & x == 0; | ^^^^^^^^^^ -error: the operation is ineffective. Consider reducing it to `0` +error: this operation will always return zero. This is likely not the intended outcome --> $DIR/bit_masks.rs:35:5 | 35 | 0 & x == 0; diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 496c297ef2b..8a05d2c251d 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -1,4 +1,4 @@ -error: the operation is ineffective. Consider reducing it to `0` +error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:9:5 | 9 | x * 0; @@ -6,13 +6,13 @@ error: the operation is ineffective. Consider reducing it to `0` | = note: `-D erasing-op` implied by `-D warnings` -error: the operation is ineffective. Consider reducing it to `0` +error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:10:5 | 10 | 0 & x; | ^^^^^ -error: the operation is ineffective. Consider reducing it to `0` +error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:11:5 | 11 | 0 / x; -- cgit 1.4.1-3-g733a5 From def4a2627db70e8b25022822976b3b178d082440 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Wed, 11 Oct 2017 20:50:58 +0200 Subject: Include a conditional update script --- README.md | 9 +++++++++ rust-update | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100755 rust-update diff --git a/README.md b/README.md index 8ef61a9df0f..755c88840e8 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,15 @@ transparently: #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] ``` +## Updating rustc + +Sometimes, rustc moves forward without clippy catching up. Therefore updating +rustc may leave clippy a non-functional state until we fix the resulting +breakage. + +You can use the [rust-update](rust-update) script to update rustc only if +clippy would also update correctly. + ## License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). diff --git a/rust-update b/rust-update new file mode 100755 index 00000000000..a987bbe94ff --- /dev/null +++ b/rust-update @@ -0,0 +1,31 @@ +#!/bin/sh + +if [ "$1" = '-h' ] ; then + echo 'Updates rustc & clippy' + echo 'It first checks if clippy would compile at currentl nightly and if so, it updates.' + echo 'Options:' + echo '-h: This help message' + echo '-f: Skips the check and just updates' + exit +fi + +set -ex + +renice -n 10 -p $$ + +export CARGO_INCREMENTAL=0 +export RUSTFLAGS='-C target-cpu=native' + +try_out() { + export RUSTUP_HOME=$HOME/.rustup-attempt + test -d $RUSTUP_HOME || (rustup toolchain add nightly && rustup default nightly) + rustup update + cargo +nightly install --force clippy + unset RUSTUP_HOME + export RUSTUP_HOME +} + +[ "$1" = '-f' ] || try_out + +rustup update +cargo +nightly install --force clippy -- cgit 1.4.1-3-g733a5 From da14435ed2b97a96dc6df3f84df851c001a3e93f Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sun, 15 Oct 2017 15:39:47 -0400 Subject: Updated clippy to account for changes from rust-lang/rust#44766 --- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/methods.rs | 4 ++-- clippy_lints/src/new_without_default.rs | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 16d636c68ab..7cfe2c1cdcb 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if let ImplItemKind::Method(ref sig, id) = item.node { - check_fn_inner(cx, &sig.decl, Some(id), &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, Some(id), &item.generics, item.span); } } @@ -76,7 +76,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { TraitMethod::Required(_) => None, TraitMethod::Provided(id) => Some(id), }; - check_fn_inner(cx, &sig.decl, body, &sig.generics, item.span); + check_fn_inner(cx, &sig.decl, body, &item.generics, item.span); } } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d986a548576..fd888d23f8c 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -719,7 +719,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if name == method_name && sig.decl.inputs.len() == n_args && out_type.matches(&sig.decl.output) && - self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { + self_kind.matches(first_arg_ty, first_arg, self_ty, false, &implitem.generics) { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); @@ -733,7 +733,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { for &(ref conv, self_kinds) in &CONVENTIONS { if_let_chain! {[ conv.check(&name.as_str()), - !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &sig.generics)), + !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)), ], { let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 1c5524af68e..a566941a502 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -108,12 +108,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } - if !sig.generics.ty_params.is_empty() { - // when the result of `new()` depends on a type parameter we should not require - // an - // impl of `Default` - return; - } + //TODO: There is no sig.generics anymore and I don't know how to fix this. + //if !sig.generics.ty_params.is_empty() { + // // when the result of `new()` depends on a type parameter we should not require + // // an + // // impl of `Default` + // return; + //} if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); -- cgit 1.4.1-3-g733a5 From a4f45e85b1adb87de2f1e46a5aeaef7b78dba288 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 17 Oct 2017 21:12:31 +0900 Subject: Use cx.access_levels.exported() instead of visibility --- clippy_lints/src/types.rs | 19 ++++++++----------- tests/ui/implicit_hasher.rs | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 18cfbe27cdc..082dce43e09 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1453,15 +1453,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { } } -/// **What it does:** Checks for `impl` or `fn` missing generalization over +/// **What it does:** Checks for public `impl` or `fn` missing generalization over /// different hashers and implicitly defaulting to the default hashing -/// algorithm (SipHash). This lint ignores private free-functions. +/// algorithm (SipHash). /// /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be /// used with them. /// -/// **Known problems:** Suggestions for replacing constructors contains -/// false-positives. Also applying suggestion can require modification of other +/// **Known problems:** Suggestions for replacing constructors can contain +/// false-positives. Also applying suggestions can require modification of other /// pieces of code, possibly including external crates. /// /// **Example:** @@ -1530,9 +1530,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { if !vis.suggestions.is_empty() { multispan_sugg(db, "...and use generic constructor".into(), vis.suggestions); } - // for (span, sugg) in vis.suggestions { - // db.span_suggestion(span, "...and use generic constructor here", sugg); - // } + } + + if !cx.access_levels.is_exported(item.id) { + return; } match item.node { @@ -1565,10 +1566,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { } }, ItemFn(ref decl, .., ref generics, body_id) => { - if item.vis != Public { - return; - } - let body = cx.tcx.hir.body(body_id); for ty in &decl.inputs { diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index b6a49869270..32ca0f56d77 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -4,7 +4,7 @@ use std::collections::{HashMap, HashSet}; use std::cmp::Eq; use std::hash::{Hash, BuildHasher}; -trait Foo: Sized { +pub trait Foo: Sized { fn make() -> (Self, Self); } -- cgit 1.4.1-3-g733a5 From eea30777ddef56383199ff70fd14b28335afc1e5 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 17 Oct 2017 21:39:24 +0900 Subject: Type parameter change and type change are now in a multispan suggestion --- clippy_lints/src/types.rs | 47 +++++++++++++++++--------------- tests/ui/implicit_hasher.stderr | 60 +++++++---------------------------------- 2 files changed, 35 insertions(+), 72 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 082dce43e09..a284392bfa0 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1453,8 +1453,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { } } -/// **What it does:** Checks for public `impl` or `fn` missing generalization over -/// different hashers and implicitly defaulting to the default hashing +/// **What it does:** Checks for public `impl` or `fn` missing generalization +/// over different hashers and implicitly defaulting to the default hashing /// algorithm (SipHash). /// /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be @@ -1505,26 +1505,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { &generics_snip[1..generics_snip.len() - 1] }; - db.span_suggestion( - generics_suggestion_span, - "consider adding a type parameter", - format!( - "<{}{}S: ::std::hash::BuildHasher{}>", - generics_snip, - if generics_snip.is_empty() { "" } else { ", " }, - if vis.suggestions.is_empty() { - "" - } else { - // request users to add `Default` bound so that generic constructors can be used - " + Default" - }, - ), - ); - - db.span_suggestion( - target.span(), - "...and change the type to", - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + multispan_sugg( + db, + "consider adding a type parameter".to_string(), + vec![ + ( + generics_suggestion_span, + format!( + "<{}{}S: ::std::hash::BuildHasher{}>", + generics_snip, + if generics_snip.is_empty() { "" } else { ", " }, + if vis.suggestions.is_empty() { + "" + } else { + // request users to add `Default` bound so that generic constructors can be used + " + Default" + }, + ), + ), + ( + target.span(), + format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + ), + ], ); if !vis.suggestions.is_empty() { diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index be799f49d00..cc0bdc327b4 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -7,12 +7,8 @@ error: impl for `HashMap` should be generarized over different hashers = note: `-D implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -11 | impl Foo for HashMap { +11 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -11 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) @@ -26,12 +22,8 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -20 | impl Foo for (HashMap,) { +20 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -20 | impl Foo for (HashMap,) { - | ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) @@ -45,12 +37,8 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -25 | impl Foo for HashMap { +25 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -25 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) @@ -64,12 +52,8 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -43 | impl Foo for HashSet { +43 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -43 | impl Foo for HashSet { - | ^^^^^^^^^^^^^ help: ...and use generic constructor | 45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) @@ -83,12 +67,8 @@ error: impl for `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -48 | impl Foo for HashSet { +48 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -48 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) @@ -102,12 +82,8 @@ error: parameter of type `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:65:53 @@ -117,12 +93,8 @@ error: parameter of type `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generarized over different hashers --> $DIR/implicit_hasher.rs:70:43 @@ -135,12 +107,8 @@ error: impl for `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -70 | impl Foo for HashMap { +70 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -70 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) @@ -157,12 +125,8 @@ error: parameter of type `HashMap` should be generarized over different hashers | help: consider adding a type parameter | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generarized over different hashers --> $DIR/implicit_hasher.rs:78:63 @@ -175,10 +139,6 @@ error: parameter of type `HashSet` should be generarized over different hashers | help: consider adding a type parameter | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...and change the type to - | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 4d9ed8beefe36610b07ab6ea3e77046ed6705d68 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 17 Oct 2017 15:32:50 +0200 Subject: E-easy -> "good first issue" issue label --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 631e9663db4..81618aacebc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ High level approach: All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. -Some issues are easier than others. The [E-easy](https://github.com/rust-lang-nursery/rust-clippy/labels/E-easy) +Some issues are easier than others. The [good first issue](https://github.com/rust-lang-nursery/rust-clippy/labels/good%20first%20issue) label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! -- cgit 1.4.1-3-g733a5 From dfa4cb7ade73e135e689270399f0e2b2a143447d Mon Sep 17 00:00:00 2001 From: clippered Date: Wed, 18 Oct 2017 07:04:35 +1100 Subject: Fix #2123 : check that the source and destination are different for manual memcpy --- clippy_lints/src/loops.rs | 9 ++++++++- tests/ui/for_loop.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 97925b0bd0c..e647ff44772 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -749,7 +749,14 @@ fn get_indexed_assignments<'a, 'tcx>( ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) { - (Some(offset_left), Some(offset_right)) => Some((offset_left, offset_right)), + (Some(offset_left), Some(offset_right)) => { + // Source and destination must be different + if offset_left.var_name != offset_right.var_name { + Some((offset_left, offset_right)) + } else { + None + } + }, _ => None, } } else { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 083e6f9a6e5..03630f87108 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -548,3 +548,11 @@ pub fn manual_clone(src: &[String], dst: &mut [String]) { dst[i] = src[i].clone(); } } + +#[warn(needless_range_loop)] +pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { + // Same source and destination - don't trigger lint + for i in 0..dst.len() { + dst[d + i] = dst[s + i]; + } +} -- cgit 1.4.1-3-g733a5 From b4ea47d23e88b6bd9859b10daf3f482290379a90 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 18 Oct 2017 07:29:47 +0900 Subject: Detect proc-macro in needless_pass_by_value Fixes #1876 --- clippy_lints/src/needless_pass_by_value.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 3c1f6ef2c4b..bc54d4ebe5f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -121,6 +121,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .zip(&body.arguments) .enumerate() { + // All spans generated from a proc-macro invocation are the same... + if span == input.span { + return; + } + // * Exclude a type that is specifically bounded by `Borrow`. // * Exclude a type whose reference also fulfills its bound. // (e.g. `std::convert::AsRef`, `serde::Serialize`) -- cgit 1.4.1-3-g733a5 From 9221bd9c97047d9eac21867f5a11651080e2b88f Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 18 Oct 2017 14:06:38 +0900 Subject: Add test --- mini-macro/src/lib.rs | 26 ++++++++++++++++++++++---- tests/run-pass/procedural_macro.rs | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index fda167b69c7..67337afd3e7 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,13 +1,15 @@ -#![feature(plugin_registrar, rustc_private)] +#![feature(plugin_registrar, rustc_private, quote)] extern crate rustc_plugin; extern crate syntax; +use rustc_plugin::Registry; +use syntax::ast::MetaItem; use syntax::codemap::Span; -use syntax::tokenstream::TokenTree; -use syntax::ext::base::{ExtCtxt, MacEager, MacResult}; +use syntax::ext::base::{Annotatable, ExtCtxt, MacEager, MacResult, SyntaxExtension}; use syntax::ext::build::AstBuilder; // trait for expr_usize -use rustc_plugin::Registry; +use syntax::symbol::Symbol; +use syntax::tokenstream::TokenTree; fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box { let e = cx.expr_usize(sp, 42); @@ -15,7 +17,23 @@ fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box Vec { + vec![ + Annotatable::Item( + quote_item!( + cx, + #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } + ).unwrap() + ), + annotated, + ] +} + #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("mini_macro", expand_macro); + reg.register_syntax_extension( + Symbol::intern("mini_macro_attr"), + SyntaxExtension::MultiModifier(Box::new(expand_attr_macro)), + ); } diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index b185f6dc427..f52c778a49d 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -2,6 +2,7 @@ #![plugin(clippy_mini_macro_test)] #[deny(warnings)] +#[mini_macro_attr] fn main() { let _ = mini_macro!(); } -- cgit 1.4.1-3-g733a5 From 52c58335aaf720d5ae306d01732b372c5660ad32 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 18 Oct 2017 08:22:06 +0200 Subject: Remove workspace and Cargo.lock --- Cargo.lock | 498 ------------------------------------------------ Cargo.toml | 2 - clippy_lints/Cargo.toml | 1 - 3 files changed, 501 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 1eed9fa4e95..00000000000 --- a/Cargo.lock +++ /dev/null @@ -1,498 +0,0 @@ -[root] -name = "clippy_lints" -version = "0.0.165" -dependencies = [ - "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cargo_metadata" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clippy" -version = "0.0.165" -dependencies = [ - "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy-mini-macro-test 0.1.0", - "clippy_lints 0.0.165", - "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clippy-mini-macro-test" -version = "0.1.0" - -[[package]] -name = "compiletest_rs" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dtoa" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "duct" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "error-chain" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "getopts" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "idna" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "matches" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nix" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "os_pipe" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "percent-encoding" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pulldown-cmark" -version = "0.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quine-mc_cluskey" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-demangle" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "semver" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "shared_child" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" -"checksum backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c63ea141ef8fdb10409d0f5daf30ac51f84ef43bff66f16627773d2a292cd189" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" -"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1" -"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2741d378feb7a434dba54228c89a70b4e427fee521de67cdda3750b8a0265f5a" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" -"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" -"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" -"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" -"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d1419b2939a0bc44b77feb34661583c7546b532b192feab36249ab584b86856c" -"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" -"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" -"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" -"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" -"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799" -"checksum serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1afcaae083fd1c46952a315062326bc9957f182358eb7da03b57ef1c688f7aa9" -"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" -"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" -"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" -"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 3d3b8abaa76..e997eeb8f3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,5 +52,3 @@ serde = "1.0" [features] debugging = [] - -[workspace] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 9c78514285d..46a5936d271 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -14,7 +14,6 @@ repository = "https://github.com/rust-lang-nursery/rust-clippy" readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] -workspace = ".." [dependencies] itertools = "0.6.0" -- cgit 1.4.1-3-g733a5 From 1f81dcbebd3af4d448f0304d632c0952852652e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Oct 2017 09:27:58 -0700 Subject: Pass null borrow context to EUV --- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index beb96f333cb..2038a59137c 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }; let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); - ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables).consume_body(body); + ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body); for node in v.set { span_lint( diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 97925b0bd0c..6ea48c5ea81 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1390,7 +1390,7 @@ fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; let def_id = def_id::DefId::local(body.hir_id.owner); let region_scope_tree = &cx.tcx.region_scope_tree(def_id); - ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables).walk_expr(body); + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(body); delegate.mutation_span() } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 3c1f6ef2c4b..60509c1aabb 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } = { let mut ctx = MovedVariablesCtxt::new(cx); let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); - euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_scope_tree, cx.tables).consume_body(body); + euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body); ctx }; -- cgit 1.4.1-3-g733a5 From 3e108b71907b8da09176cac271e9e8ae8b46f352 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Oct 2017 10:16:03 -0700 Subject: Fix constant promotion stuff --- clippy_lints/src/methods.rs | 28 +++++++++++++---------- tests/ui/methods.stderr | 56 +-------------------------------------------- 2 files changed, 17 insertions(+), 67 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d986a548576..38e7009653f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -821,18 +821,6 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: or_has_args: bool, span: Span, ) { - // don't lint for constant values - // FIXME: can we `expect` here instead of match? - let promotable = cx.tcx - .rvalue_promotable_to_static - .borrow() - .get(&arg.id) - .cloned() - .unwrap_or(true); - if promotable { - return; - } - // (path, fn_has_argument, methods, suffix) let know_types: &[(&[_], _, &[_], _)] = &[ (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), @@ -841,6 +829,22 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: (&paths::RESULT, true, &["or", "unwrap_or"], "else"), ]; + // early check if the name is one we care about + if know_types.iter().all(|k| !k.2.contains(&name)) { + return; + } + + // don't lint for constant values + // FIXME: can we `expect` here instead of match? + let owner = cx.tcx.hir.get_parent(arg.id); + let owner_def = cx.tcx.hir.local_def_id(owner); + let promotable = cx.tcx + .rvalue_promotable_map(owner_def) + .contains_key(&arg.hir_id.local_id); + if promotable { + return; + } + let self_ty = cx.tables.expr_ty(self_expr); let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 97e8c25ad75..068cbbcd193 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -318,37 +318,13 @@ error: unnecessary structure name repetition 263 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:281:5 - | -281 | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` - | - = note: `-D or-fun-call` implied by `-D warnings` - error: use of `unwrap_or` followed by a call to `new` --> $DIR/methods.rs:284:5 | 284 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:287:5 | -287 | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:290:5 - | -290 | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:293:5 - | -293 | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` + = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `default` --> $DIR/methods.rs:296:5 @@ -362,36 +338,6 @@ error: use of `unwrap_or` followed by a call to `default` 299 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:302:5 - | -302 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:5 - | -307 | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:310:5 - | -310 | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:313:5 - | -313 | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:13 - | -316 | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` - error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable --> $DIR/methods.rs:327:23 | -- cgit 1.4.1-3-g733a5 From 4960d9de86160a85a899d504e3c15b09ba7b6ac0 Mon Sep 17 00:00:00 2001 From: cgm616 Date: Thu, 19 Oct 2017 23:42:04 -0500 Subject: Deprecate should_assert_eq lint This should close #2090. --- README.md | 2 +- clippy_lints/src/deprecated_lints.rs | 8 +++++ clippy_lints/src/lib.rs | 7 +++-- clippy_lints/src/should_assert_eq.rs | 61 ------------------------------------ tests/ui/should_assert_eq.rs | 32 ------------------- tests/ui/should_assert_eq.stderr | 57 --------------------------------- 6 files changed, 13 insertions(+), 154 deletions(-) delete mode 100644 clippy_lints/src/should_assert_eq.rs delete mode 100644 tests/ui/should_assert_eq.rs delete mode 100644 tests/ui/should_assert_eq.stderr diff --git a/README.md b/README.md index 26e7f12dc83..cd8e8a409e0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 209 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 208 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 0c40823cd06..e51d7cc6d38 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -4,6 +4,14 @@ macro_rules! declare_deprecated_lint { } } +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend +/// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011. +declare_deprecated_lint! { + pub SHOULD_ASSERT_EQ, + "`assert!()` will be more flexible with RFC 2011" +} /// **What it does:** Nothing. This lint has been deprecated. /// diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 355b03b2b6a..735df8fc090 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -144,7 +144,6 @@ pub mod regex; pub mod returns; pub mod serde_api; pub mod shadow; -pub mod should_assert_eq; pub mod strings; pub mod explicit_write; pub mod swap; @@ -200,6 +199,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { }; let mut store = reg.sess.lint_store.borrow_mut(); + store.register_removed( + "should_assert_eq", + "`assert!()` will be more flexible with RFC 2011" + ); store.register_removed( "extend_from_slice", "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice", @@ -327,7 +330,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box double_parens::DoubleParens); reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount); reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); - reg.register_late_lint_pass(box should_assert_eq::ShouldAssertEq); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); @@ -542,7 +544,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, serde_api::SERDE_API_MISUSE, - should_assert_eq::SHOULD_ASSERT_EQ, strings::STRING_LIT_AS_BYTES, explicit_write::EXPLICIT_WRITE, swap::ALMOST_SWAPPED, diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs deleted file mode 100644 index 47e444c8c88..00000000000 --- a/clippy_lints/src/should_assert_eq.rs +++ /dev/null @@ -1,61 +0,0 @@ -use rustc::lint::*; -use rustc::hir::*; -use utils::{implements_trait, is_direct_expn_of, is_expn_of, span_lint}; - -/// **What it does:** Checks for `assert!(x == y)` or `assert!(x != y)` which -/// can be better written -/// using `assert_eq` or `assert_ne` if `x` and `y` implement `Debug` trait. -/// -/// **Why is this bad?** `assert_eq` and `assert_ne` provide better assertion -/// failure reporting. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// ```rust -/// let (x, y) = (1, 2); -/// -/// assert!(x == y); // assertion failed: x == y -/// assert_eq!(x, y); // assertion failed: `(left == right)` (left: `1`, right: -/// `2`) -/// ``` -declare_lint! { - pub SHOULD_ASSERT_EQ, - Warn, - "using `assert` macro for asserting equality" -} - -pub struct ShouldAssertEq; - -impl LintPass for ShouldAssertEq { - fn get_lints(&self) -> LintArray { - lint_array![SHOULD_ASSERT_EQ] - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if_let_chain! {[ - let ExprIf(ref cond, ..) = e.node, - let ExprUnary(UnOp::UnNot, ref cond) = cond.node, - let ExprBinary(ref binop, ref expr1, ref expr2) = cond.node, - is_direct_expn_of(e.span, "assert").is_some(), - let Some(debug_trait) = cx.tcx.lang_items().debug_trait(), - ], { - let debug = is_expn_of(e.span, "debug_assert").map_or("", |_| "debug_"); - let sugg = match binop.node { - BinOp_::BiEq => "assert_eq", - BinOp_::BiNe => "assert_ne", - _ => return, - }; - - let ty1 = cx.tables.expr_ty(expr1); - let ty2 = cx.tables.expr_ty(expr2); - - if implements_trait(cx, ty1, debug_trait, &[]) && - implements_trait(cx, ty2, debug_trait, &[]) { - span_lint(cx, SHOULD_ASSERT_EQ, e.span, &format!("use `{}{}` for better reporting", debug, sugg)); - } - }} - } -} diff --git a/tests/ui/should_assert_eq.rs b/tests/ui/should_assert_eq.rs deleted file mode 100644 index 5814e997753..00000000000 --- a/tests/ui/should_assert_eq.rs +++ /dev/null @@ -1,32 +0,0 @@ - - - -#![allow(needless_pass_by_value)] -#![warn(should_assert_eq)] - -#[derive(PartialEq, Eq)] -struct NonDebug(i32); - -#[derive(Debug, PartialEq, Eq)] -struct Debug(i32); - -fn main() { - assert!(1 == 2); - assert!(Debug(1) == Debug(2)); - assert!(NonDebug(1) == NonDebug(1)); // ok - assert!(Debug(1) != Debug(2)); - assert!(NonDebug(1) != NonDebug(2)); // ok - - test_generic(1, 2, 3, 4); - - debug_assert!(4 == 5); - debug_assert!(4 != 6); -} - -fn test_generic(x: T, y: T, z: U, w: U) { - assert!(x == y); - assert!(z == w); // ok - - assert!(x != y); - assert!(z != w); // ok -} diff --git a/tests/ui/should_assert_eq.stderr b/tests/ui/should_assert_eq.stderr deleted file mode 100644 index 5b393e1dbe8..00000000000 --- a/tests/ui/should_assert_eq.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error: use `assert_eq` for better reporting - --> $DIR/should_assert_eq.rs:14:5 - | -14 | assert!(1 == 2); - | ^^^^^^^^^^^^^^^^ - | - = note: `-D should-assert-eq` implied by `-D warnings` - = note: this error originates in a macro outside of the current crate - -error: use `assert_eq` for better reporting - --> $DIR/should_assert_eq.rs:15:5 - | -15 | assert!(Debug(1) == Debug(2)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: use `assert_ne` for better reporting - --> $DIR/should_assert_eq.rs:17:5 - | -17 | assert!(Debug(1) != Debug(2)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: use `debug_assert_eq` for better reporting - --> $DIR/should_assert_eq.rs:22:5 - | -22 | debug_assert!(4 == 5); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: use `debug_assert_ne` for better reporting - --> $DIR/should_assert_eq.rs:23:5 - | -23 | debug_assert!(4 != 6); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: use `assert_eq` for better reporting - --> $DIR/should_assert_eq.rs:27:5 - | -27 | assert!(x == y); - | ^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -error: use `assert_ne` for better reporting - --> $DIR/should_assert_eq.rs:30:5 - | -30 | assert!(x != y); - | ^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate - -- cgit 1.4.1-3-g733a5 From 35b2669219002529411fda269b193cd9d89b605a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Oct 2017 09:02:32 +0200 Subject: Check the map for promotable instead for existance of a node (which is always the case) --- clippy_lints/src/methods.rs | 5 ++-- tests/ui/methods.stderr | 56 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 38e7009653f..d8309ff6f8d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -836,11 +836,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: // don't lint for constant values // FIXME: can we `expect` here instead of match? - let owner = cx.tcx.hir.get_parent(arg.id); - let owner_def = cx.tcx.hir.local_def_id(owner); + let owner_def = cx.tcx.hir.get_parent_did(arg.id); let promotable = cx.tcx .rvalue_promotable_map(owner_def) - .contains_key(&arg.hir_id.local_id); + [&arg.hir_id.local_id]; if promotable { return; } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 068cbbcd193..97e8c25ad75 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -318,13 +318,37 @@ error: unnecessary structure name repetition 263 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:281:5 + | +281 | with_constructor.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` + | + = note: `-D or-fun-call` implied by `-D warnings` + error: use of `unwrap_or` followed by a call to `new` --> $DIR/methods.rs:284:5 | 284 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` + +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:287:5 | - = note: `-D or-fun-call` implied by `-D warnings` +287 | with_const_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` + +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:290:5 + | +290 | with_err.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` + +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:293:5 + | +293 | with_err_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` --> $DIR/methods.rs:296:5 @@ -338,6 +362,36 @@ error: use of `unwrap_or` followed by a call to `default` 299 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:302:5 + | +302 | with_vec.unwrap_or(vec![]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` + +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:307:5 + | +307 | without_default.unwrap_or(Foo::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/methods.rs:310:5 + | +310 | map.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/methods.rs:313:5 + | +313 | btree.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` + +error: use of `unwrap_or` followed by a function call + --> $DIR/methods.rs:316:13 + | +316 | let _ = stringy.unwrap_or("".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` + error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable --> $DIR/methods.rs:327:23 | -- cgit 1.4.1-3-g733a5 From e2429f023b9a84786eb0092805d909c323118576 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Oct 2017 09:24:37 +0200 Subject: Version bump --- CHANGELOG.md | 14 ++++++++++++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 15 +++++++++------ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e3fb8be43d..0a6f91e3bb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.166 +* Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)* +* New lints: [`explicit_write`], [`identity_conversion`], [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], [`transmute_int_to_float`] + ## 0.0.165 * Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27) * New lint: [`mut_range_bound`] @@ -505,6 +509,7 @@ All notable changes to this project will be documented in this file. [`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_into_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_into_iter_loop [`explicit_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_iter_loop +[`explicit_write`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extend_from_slice [`filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_map [`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next @@ -516,12 +521,14 @@ All notable changes to this project will be documented in this file. [`forget_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_copy [`forget_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_ref [`get_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#get_unwrap +[`identity_conversion`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#identity_op [`if_let_redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching [`if_let_some_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_some_result [`if_not_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_not_else [`if_same_then_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_same_then_else [`ifs_same_cond`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ifs_same_cond +[`implicit_hasher`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#implicit_hasher [`inconsistent_digit_grouping`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask @@ -529,6 +536,7 @@ All notable changes to this project will be documented in this file. [`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always [`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic +[`invalid_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons [`items_after_statements`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#items_after_statements @@ -590,6 +598,7 @@ All notable changes to this project will be documented in this file. [`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect [`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref +[`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or [`option_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else [`option_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_unwrap_used @@ -604,6 +613,8 @@ All notable changes to this project will be documented in this file. [`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline [`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg [`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names +[`range_minus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_minus_one +[`range_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_step_by_zero [`range_zip_with_len`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_zip_with_len [`redundant_closure`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure @@ -637,6 +648,9 @@ All notable changes to this project will be documented in this file. [`temporary_cstring_as_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`too_many_arguments`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#too_many_arguments [`toplevel_ref_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`transmute_int_to_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_bool +[`transmute_int_to_char`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_char +[`transmute_int_to_float`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_float [`transmute_ptr_to_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity diff --git a/Cargo.toml b/Cargo.toml index e997eeb8f3e..35e078d6577 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.165" +version = "0.0.166" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.165", path = "clippy_lints" } +clippy_lints = { version = "0.0.166", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 46a5936d271..414cd68a660 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.165" +version = "0.0.166" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 355b03b2b6a..e3bccc7e9e0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -91,6 +91,7 @@ pub mod eq_op; pub mod escape; pub mod eta_reduction; pub mod eval_order_dependence; +pub mod explicit_write; pub mod format; pub mod formatting; pub mod functions; @@ -146,7 +147,6 @@ pub mod serde_api; pub mod shadow; pub mod should_assert_eq; pub mod strings; -pub mod explicit_write; pub mod swap; pub mod temporary_assignment; pub mod transmute; @@ -354,7 +354,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, int_plus_one::INT_PLUS_ONE, - invalid_ref::INVALID_REF, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, mem_forget::MEM_FORGET, @@ -372,6 +371,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::SIMILAR_NAMES, print::PRINT_STDOUT, print::USE_DEBUG, + ranges::RANGE_PLUS_ONE, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, @@ -431,6 +431,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { eta_reduction::REDUNDANT_CLOSURE, eval_order_dependence::DIVERGING_SUB_EXPRESSION, eval_order_dependence::EVAL_ORDER_DEPENDENCE, + explicit_write::EXPLICIT_WRITE, format::USELESS_FORMAT, formatting::POSSIBLE_MISSING_COMMA, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, @@ -441,6 +442,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infinite_iter::INFINITE_ITER, + invalid_ref::INVALID_REF, is_unit_expr::UNIT_EXPR, large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, @@ -485,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::ITER_SKIP_NEXT, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, + methods::OPTION_MAP_OR_NONE, methods::OR_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, @@ -534,6 +537,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ptr::MUT_FROM_REF, ptr::PTR_ARG, ranges::ITERATOR_STEP_BY_ZERO, + ranges::RANGE_MINUS_ONE, ranges::RANGE_ZIP_WITH_LEN, reference::DEREF_ADDROF, regex::INVALID_REGEX, @@ -544,17 +548,16 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { serde_api::SERDE_API_MISUSE, should_assert_eq::SHOULD_ASSERT_EQ, strings::STRING_LIT_AS_BYTES, - explicit_write::EXPLICIT_WRITE, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTE_INT_TO_BOOL, + transmute::TRANSMUTE_INT_TO_CHAR, + transmute::TRANSMUTE_INT_TO_FLOAT, transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, - transmute::TRANSMUTE_INT_TO_CHAR, - transmute::TRANSMUTE_INT_TO_BOOL, - transmute::TRANSMUTE_INT_TO_FLOAT, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, -- cgit 1.4.1-3-g733a5 From ebdefff88a5df05d196b178259effef14e465fe8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Oct 2017 16:13:50 +0200 Subject: Something went through the cracks of our CI --- clippy_lints/src/loops.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 77519d9e179..cea0cfb7028 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -751,10 +751,10 @@ fn get_indexed_assignments<'a, 'tcx>( match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) { (Some(offset_left), Some(offset_right)) => { // Source and destination must be different - if offset_left.var_name != offset_right.var_name { - Some((offset_left, offset_right)) - } else { + if offset_left.var_name == offset_right.var_name { None + } else { + Some((offset_left, offset_right)) } }, _ => None, -- cgit 1.4.1-3-g733a5 From 322effe4158cd3f2c48eba83af86383cd8d5612f Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 09:51:35 -0400 Subject: Implementation of the `const_static_lifetime` lint. --- clippy_lints/src/const_static_lifetime.rs | 82 +++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ tests/ui/const_static_lifetime.rs | 33 +++++++++++++ tests/ui/regex.rs | 4 +- 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/const_static_lifetime.rs create mode 100644 tests/ui/const_static_lifetime.rs diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs new file mode 100644 index 00000000000..3e426d9cebb --- /dev/null +++ b/clippy_lints/src/const_static_lifetime.rs @@ -0,0 +1,82 @@ +use syntax::ast::{Item, ItemKind, TyKind, Ty}; +use rustc::lint::{LintPass, EarlyLintPass, LintArray, EarlyContext}; +use utils::{span_help_and_lint, in_macro}; + +/// **What it does:** Checks for constants with an explicit `'static` lifetime. +/// +/// **Why is this bad?** Adding `'static` to every reference can create very complicated types. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = &[..] +/// ``` +/// This code can be rewritten as +/// ```rust +/// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...] +/// ``` + +declare_lint! { + pub CONST_STATIC_LIFETIME, + Warn, + "Using explicit `'static` lifetime for constants when elision rules would allow omitting them." +} + +pub struct StaticConst; + +impl LintPass for StaticConst { + fn get_lints(&self) -> LintArray { + lint_array!(CONST_STATIC_LIFETIME) + } +} + +impl StaticConst { + // Recursively visit types + fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext) { + match ty.node { + // Be carefull of nested structures (arrays and tuples) + TyKind::Array(ref ty, _) => { + println!("array"); + self.visit_type(&*ty, cx); + }, + TyKind::Tup(ref tup) => { + for tup_ty in tup { + self.visit_type(&*tup_ty, cx); + } + }, + // This is what we are looking for ! + TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { + // Match the 'static lifetime + if let Some(lifetime) = *optional_lifetime { + if let TyKind::Path(_, _) = borrow_type.ty.node { + // Verify that the path is a str + if lifetime.ident.name == "'static" { + span_help_and_lint(cx, + CONST_STATIC_LIFETIME, + lifetime.span, + "Constants have by default a `'static` lifetime", + "consider removing `'static`"); + } + } + } + self.visit_type(&*borrow_type.ty, cx); + }, + TyKind::Slice(ref ty) => { + self.visit_type(&ty, cx); + }, + _ => {}, + } + } +} + +impl EarlyLintPass for StaticConst { + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if !in_macro(item.span) { + // Match only constants... + if let ItemKind::Const(ref var_type, _) = item.node { + self.visit_type(var_type, cx); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 198a876c352..9b78e435645 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -76,6 +76,7 @@ pub mod block_in_if_condition; pub mod booleans; pub mod bytecount; pub mod collapsible_if; +pub mod const_static_lifetime; pub mod copies; pub mod cyclomatic_complexity; pub mod derive; @@ -339,6 +340,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); + reg.register_early_lint_pass(box const_static_lifetime::StaticConst); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -349,6 +351,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_pedantic", vec![ booleans::NONMINIMAL_BOOL, + const_static_lifetime::CONST_STATIC_LIFETIME, empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, enum_variants::PUB_ENUM_VARIANT_NAMES, diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs new file mode 100644 index 00000000000..05b7a3e0117 --- /dev/null +++ b/tests/ui/const_static_lifetime.rs @@ -0,0 +1,33 @@ +#![feature(plugin)] + +#[derive(Debug)] +struct Foo {} + +const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. + +const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. + +const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static + +const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static + +const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static + +const VAR_SIX: &'static u8 = &5; + +const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; + +const VAR_HEIGHT: &'static Foo = &Foo {}; + +fn main() { + let false_positive: &'static str = "test"; + println!("{}", VAR_ONE); + println!("{}", VAR_TWO); + println!("{:?}", VAR_THREE); + println!("{:?}", VAR_FOUR); + println!("{:?}", VAR_FIVE); + println!("{:?}", VAR_SIX); + println!("{:?}", VAR_SEVEN); + println!("{:?}", VAR_HEIGHT); + println!("{}", false_positive); +} diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 3dd1f64202c..2007f1fad55 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -9,8 +9,8 @@ extern crate regex; use regex::{Regex, RegexSet, RegexBuilder}; use regex::bytes::{Regex as BRegex, RegexSet as BRegexSet, RegexBuilder as BRegexBuilder}; -const OPENING_PAREN : &'static str = "("; -const NOT_A_REAL_REGEX : &'static str = "foobar"; +const OPENING_PAREN: &str = "("; +const NOT_A_REAL_REGEX: &str = "foobar"; fn syntax_error() { let pipe_in_wrong_position = Regex::new("|"); -- cgit 1.4.1-3-g733a5 From 406931381b154a9d939078d482af94dae63ab366 Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 08:41:24 -0400 Subject: Fixed some code in clippy to pass the new, removed formatting changes. --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 4 +- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/methods.rs | 6 +- clippy_lints/src/needless_continue.rs | 8 +- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/constants.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/paths.rs | 178 +++++++++++++++--------------- 11 files changed, 105 insertions(+), 105 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index ed65366d21f..36f3579e548 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -33,7 +33,7 @@ declare_lint! { } // Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[ +const KNOWN_CONSTS: &[(f64, &str, usize)] = &[ (f64::E, "E", 4), (f64::FRAC_1_PI, "FRAC_1_PI", 4), (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index d67a1a5394e..af99b77163b 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -71,8 +71,8 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { } } -const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition"; -const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ +const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition"; +const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ instead, move the block or closure higher and bind it with a 'let'"; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 3e426d9cebb..a56e73e2c50 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -63,7 +63,7 @@ impl StaticConst { self.visit_type(&*borrow_type.ty, cx); }, TyKind::Slice(ref ty) => { - self.visit_type(&ty, cx); + self.visit_type(ty, cx); }, _ => {}, } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 3162dbc422b..abe9897ba4d 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -88,7 +88,7 @@ impl<'a> Iterator for Parser<'a> { #[allow(cast_possible_truncation)] pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(usize, Span)>) { // one-line comments lose their prefix - const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; + const ONELINERS: &[&str] = &["///!", "///", "//!", "//"]; for prefix in ONELINERS { if comment.starts_with(*prefix) { let doc = &comment[prefix.len()..]; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d8309ff6f8d..849f0024415 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1531,7 +1531,7 @@ enum Convention { } #[cfg_attr(rustfmt, rustfmt_skip)] -const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [ +const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ (Convention::Eq("new"), &[SelfKind::No]), (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), (Convention::StartsWith("from_"), &[SelfKind::No]), @@ -1541,7 +1541,7 @@ const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [ ]; #[cfg_attr(rustfmt, rustfmt_skip)] -const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [ +const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), @@ -1575,7 +1575,7 @@ const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30 ]; #[cfg_attr(rustfmt, rustfmt_skip)] -const PATTERN_METHODS: [(&'static str, usize); 17] = [ +const PATTERN_METHODS: [(&str, usize); 17] = [ ("contains", 1), ("starts_with", 1), ("ends_with", 1), diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index b369d8b570b..00d7a945595 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -252,15 +252,15 @@ struct LintData<'a> { block_stmts: &'a [ast::Stmt], } -const MSG_REDUNDANT_ELSE_BLOCK: &'static str = "This else block is redundant.\n"; +const MSG_REDUNDANT_ELSE_BLOCK: &str = "This else block is redundant.\n"; -const MSG_ELSE_BLOCK_NOT_NEEDED: &'static str = "There is no need for an explicit `else` block for this `if` \ +const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \ expression\n"; -const DROP_ELSE_BLOCK_AND_MERGE_MSG: &'static str = "Consider dropping the else clause and merging the code that \ +const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause and merging the code that \ follows (in the loop) with the if block, like so:\n"; -const DROP_ELSE_BLOCK_MSG: &'static str = "Consider dropping the else clause, and moving out the code in the else \ +const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \ block, like so:\n"; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index d36054eacf4..478b4c3e0eb 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -69,7 +69,7 @@ struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> { // this list contains lists of names that are allowed to be similar // the assumption is that no name is ever contained in multiple lists. #[cfg_attr(rustfmt, rustfmt_skip)] -const WHITELIST: &'static [&'static [&'static str]] = &[ +const WHITELIST: &[&[&str]] = &[ &["parsed", "parser"], &["lhs", "rhs"], &["tx", "rx"], diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 68ac74d4eef..83413ae8b48 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -182,7 +182,7 @@ define_Conf! { /// Search for the configuration file. pub fn lookup_conf_file() -> io::Result> { /// Possible filename to search for. - const CONFIG_FILE_NAMES: [&'static str; 2] = [".clippy.toml", "clippy.toml"]; + const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"]; let mut current = try!(env::current_dir()); diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index d47fbd5a043..f59716268a0 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -7,7 +7,7 @@ /// See also [the reference][reference-types] for a list of such types. /// /// [reference-types]: https://doc.rust-lang.org/reference.html#types -pub const BUILTIN_TYPES: &'static [&'static str] = &[ +pub const BUILTIN_TYPES: &[&str] = &[ "i8", "u8", "i16", diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 239370d9811..cf3bf41a925 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -169,7 +169,7 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { fn root_mode(&self) -> &ty::item_path::RootMode { - const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; + const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; ABSOLUTE } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index d517d32b64c..c198ad64b0f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,93 +1,93 @@ //! This module contains paths to types and functions Clippy needs to know //! about. -pub const ANY_TRAIT: [&'static str; 3] = ["std", "any", "Any"]; -pub const ARC: [&'static str; 3] = ["alloc", "arc", "Arc"]; -pub const ASMUT_TRAIT: [&'static str; 3] = ["core", "convert", "AsMut"]; -pub const ASREF_TRAIT: [&'static str; 3] = ["core", "convert", "AsRef"]; -pub const BEGIN_PANIC: [&'static str; 3] = ["std", "panicking", "begin_panic"]; -pub const BINARY_HEAP: [&'static str; 3] = ["alloc", "binary_heap", "BinaryHeap"]; -pub const BORROW_TRAIT: [&'static str; 3] = ["core", "borrow", "Borrow"]; -pub const BOX: [&'static str; 3] = ["std", "boxed", "Box"]; -pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; -pub const BTREEMAP: [&'static str; 4] = ["alloc", "btree", "map", "BTreeMap"]; -pub const BTREEMAP_ENTRY: [&'static str; 4] = ["alloc", "btree", "map", "Entry"]; -pub const BTREESET: [&'static str; 4] = ["alloc", "btree", "set", "BTreeSet"]; -pub const CLONE: [&'static str; 4] = ["core", "clone", "Clone", "clone"]; -pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"]; -pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; -pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"]; -pub const COW: [&'static str; 3] = ["alloc", "borrow", "Cow"]; -pub const CSTRING_NEW: [&'static str; 5] = ["std", "ffi", "c_str", "CString", "new"]; -pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"]; -pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"]; -pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"]; -pub const DOUBLE_ENDED_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; -pub const DROP: [&'static str; 3] = ["core", "mem", "drop"]; -pub const FMT_ARGUMENTS_NEWV1: [&'static str; 4] = ["core", "fmt", "Arguments", "new_v1"]; -pub const FMT_ARGUMENTV1_NEW: [&'static str; 4] = ["core", "fmt", "ArgumentV1", "new"]; -pub const FROM_FROM: [&'static str; 4] = ["core", "convert", "From", "from"]; -pub const HASH: [&'static str; 2] = ["hash", "Hash"]; -pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"]; -pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"]; -pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"]; -pub const INIT: [&'static str; 4] = ["core", "intrinsics", "", "init"]; -pub const INTO: [&'static str; 3] = ["core", "convert", "Into"]; -pub const INTO_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "IntoIterator"]; -pub const IO_PRINT: [&'static str; 4] = ["std", "io", "stdio", "_print"]; -pub const IO_READ: [&'static str; 3] = ["std", "io", "Read"]; -pub const IO_WRITE: [&'static str; 3] = ["std", "io", "Write"]; -pub const ITERATOR: [&'static str; 4] = ["core", "iter", "iterator", "Iterator"]; -pub const LINKED_LIST: [&'static str; 3] = ["alloc", "linked_list", "LinkedList"]; -pub const LINT: [&'static str; 3] = ["rustc", "lint", "Lint"]; -pub const LINT_ARRAY: [&'static str; 3] = ["rustc", "lint", "LintArray"]; -pub const MEM_FORGET: [&'static str; 3] = ["core", "mem", "forget"]; -pub const MEM_UNINIT: [&'static str; 3] = ["core", "mem", "uninitialized"]; -pub const MEM_ZEROED: [&'static str; 3] = ["core", "mem", "zeroed"]; -pub const MUTEX: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"]; -pub const OPEN_OPTIONS: [&'static str; 3] = ["std", "fs", "OpenOptions"]; -pub const OPS_MODULE: [&'static str; 2] = ["core", "ops"]; -pub const OPTION: [&'static str; 3] = ["core", "option", "Option"]; -pub const OPTION_NONE: [&'static str; 4] = ["core", "option", "Option", "None"]; -pub const OPTION_SOME: [&'static str; 4] = ["core", "option", "Option", "Some"]; -pub const PTR_NULL: [&'static str; 2] = ["ptr", "null"]; -pub const PTR_NULL_MUT: [&'static str; 2] = ["ptr", "null_mut"]; -pub const RANGE: [&'static str; 3] = ["core", "ops", "Range"]; -pub const RANGE_FROM: [&'static str; 3] = ["core", "ops", "RangeFrom"]; -pub const RANGE_FROM_STD: [&'static str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&'static str; 3] = ["core", "ops", "RangeFull"]; -pub const RANGE_FULL_STD: [&'static str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeInclusive"]; -pub const RANGE_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeInclusive"]; -pub const RANGE_STD: [&'static str; 3] = ["std", "ops", "Range"]; -pub const RANGE_TO: [&'static str; 3] = ["core", "ops", "RangeTo"]; -pub const RANGE_TO_INCLUSIVE: [&'static str; 3] = ["core", "ops", "RangeToInclusive"]; -pub const RANGE_TO_INCLUSIVE_STD: [&'static str; 3] = ["std", "ops", "RangeToInclusive"]; -pub const RANGE_TO_STD: [&'static str; 3] = ["std", "ops", "RangeTo"]; -pub const RC: [&'static str; 3] = ["alloc", "rc", "Rc"]; -pub const REGEX: [&'static str; 3] = ["regex", "re_unicode", "Regex"]; -pub const REGEX_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -pub const REGEX_BYTES: [&'static str; 3] = ["regex", "re_bytes", "Regex"]; -pub const REGEX_BYTES_BUILDER_NEW: [&'static str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; -pub const REGEX_BYTES_NEW: [&'static str; 4] = ["regex", "re_bytes", "Regex", "new"]; -pub const REGEX_BYTES_SET_NEW: [&'static str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; -pub const REGEX_NEW: [&'static str; 4] = ["regex", "re_unicode", "Regex", "new"]; -pub const REGEX_SET_NEW: [&'static str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; -pub const REPEAT: [&'static str; 3] = ["core", "iter", "repeat"]; -pub const RESULT: [&'static str; 3] = ["core", "result", "Result"]; -pub const RESULT_ERR: [&'static str; 4] = ["core", "result", "Result", "Err"]; -pub const RESULT_OK: [&'static str; 4] = ["core", "result", "Result", "Ok"]; -pub const SERDE_DE_VISITOR: [&'static str; 3] = ["serde", "de", "Visitor"]; -pub const SLICE_INTO_VEC: [&'static str; 4] = ["alloc", "slice", "", "into_vec"]; +pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; +pub const ARC: [&str; 3] = ["alloc", "arc", "Arc"]; +pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; +pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; +pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; +pub const BINARY_HEAP: [&str; 3] = ["alloc", "binary_heap", "BinaryHeap"]; +pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; +pub const BOX: [&str; 3] = ["std", "boxed", "Box"]; +pub const BOX_NEW: [&str; 4] = ["std", "boxed", "Box", "new"]; +pub const BTREEMAP: [&str; 4] = ["alloc", "btree", "map", "BTreeMap"]; +pub const BTREEMAP_ENTRY: [&str; 4] = ["alloc", "btree", "map", "Entry"]; +pub const BTREESET: [&str; 4] = ["alloc", "btree", "set", "BTreeSet"]; +pub const CLONE: [&str; 4] = ["core", "clone", "Clone", "clone"]; +pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"]; +pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; +pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; +pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; +pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; +pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"]; +pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; +pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; +pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; +pub const DROP: [&str; 3] = ["core", "mem", "drop"]; +pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; +pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; +pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; +pub const HASH: [&str; 2] = ["hash", "Hash"]; +pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"]; +pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"]; +pub const INTO: [&str; 3] = ["core", "convert", "Into"]; +pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; +pub const IO_PRINT: [&str; 4] = ["std", "io", "stdio", "_print"]; +pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; +pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; +pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; +pub const LINKED_LIST: [&str; 3] = ["alloc", "linked_list", "LinkedList"]; +pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; +pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; +pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; +pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"]; +pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"]; +pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"]; +pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; +pub const OPS_MODULE: [&str; 2] = ["core", "ops"]; +pub const OPTION: [&str; 3] = ["core", "option", "Option"]; +pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"]; +pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; +pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; +pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; +pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; +pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; +pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; +pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; +pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; +pub const RANGE_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeInclusive"]; +pub const RANGE_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeInclusive"]; +pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"]; +pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"]; +pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"]; +pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"]; +pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; +pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; +pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"]; +pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; +pub const REGEX_BYTES: [&str; 3] = ["regex", "re_bytes", "Regex"]; +pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; +pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; +pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; +pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; +pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; +pub const REPEAT: [&str; 3] = ["core", "iter", "repeat"]; +pub const RESULT: [&str; 3] = ["core", "result", "Result"]; +pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"]; +pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"]; +pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; +pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"]; -pub const STRING: [&'static str; 3] = ["alloc", "string", "String"]; -pub const TO_OWNED: [&'static str; 3] = ["alloc", "borrow", "ToOwned"]; -pub const TO_STRING: [&'static str; 3] = ["alloc", "string", "ToString"]; -pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; -pub const TRY_INTO_RESULT: [&'static str; 4] = ["std", "ops", "Try", "into_result"]; -pub const UNINIT: [&'static str; 4] = ["core", "intrinsics", "", "uninit"]; -pub const VEC: [&'static str; 3] = ["alloc", "vec", "Vec"]; -pub const VEC_DEQUE: [&'static str; 3] = ["alloc", "vec_deque", "VecDeque"]; -pub const VEC_FROM_ELEM: [&'static str; 3] = ["alloc", "vec", "from_elem"]; -pub const WEAK_ARC: [&'static str; 3] = ["alloc", "arc", "Weak"]; -pub const WEAK_RC: [&'static str; 3] = ["alloc", "rc", "Weak"]; +pub const STRING: [&str; 3] = ["alloc", "string", "String"]; +pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"]; +pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"]; +pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; +pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; +pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"]; +pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; +pub const VEC_DEQUE: [&str; 3] = ["alloc", "vec_deque", "VecDeque"]; +pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; +pub const WEAK_ARC: [&str; 3] = ["alloc", "arc", "Weak"]; +pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; -- cgit 1.4.1-3-g733a5 From fbce5046640e27db2502bec603e67ca3c430daae Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 09:56:26 -0400 Subject: Added the test results. --- tests/ui/const_static_lifetime.stderr | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/ui/const_static_lifetime.stderr diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr new file mode 100644 index 00000000000..30b6165d1f3 --- /dev/null +++ b/tests/ui/const_static_lifetime.stderr @@ -0,0 +1,65 @@ +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:6:17 + | +6 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. + | ^^^^^^^ + | + = note: `-D const-static-lifetime` implied by `-D warnings` + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:10:21 + | +10 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:12:32 + | +12 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:12:47 + | +12 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:14:30 + | +14 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:16:17 + | +16 | const VAR_SIX: &'static u8 = &5; + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:18:39 + | +18 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; + | ^^^^^^^ + | + = help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:20:20 + | +20 | const VAR_HEIGHT: &'static Foo = &Foo {}; + | ^^^^^^^ + | + = help: consider removing `'static` + -- cgit 1.4.1-3-g733a5 From 4bbda68d56f68161517742bf9fe8298a9a3c9c78 Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 10:00:44 -0400 Subject: Better linting : use of span_lint_and_then. --- clippy_lints/src/const_static_lifetime.rs | 13 ++++--- tests/ui/const_static_lifetime.stderr | 65 +++++++++++++------------------ 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index a56e73e2c50..4f2d8656532 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,16 +1,18 @@ use syntax::ast::{Item, ItemKind, TyKind, Ty}; use rustc::lint::{LintPass, EarlyLintPass, LintArray, EarlyContext}; -use utils::{span_help_and_lint, in_macro}; +use utils::{span_lint_and_then, in_macro}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// -/// **Why is this bad?** Adding `'static` to every reference can create very complicated types. +/// **Why is this bad?** Adding `'static` to every reference can create very +/// complicated types. /// /// **Known problems:** None. /// /// **Example:** /// ```rust -/// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = &[..] +/// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = +/// &[...] /// ``` /// This code can be rewritten as /// ```rust @@ -52,11 +54,12 @@ impl StaticConst { if let TyKind::Path(_, _) = borrow_type.ty.node { // Verify that the path is a str if lifetime.ident.name == "'static" { - span_help_and_lint(cx, + let mut sug: String = String::new(); + span_lint_and_then(cx, CONST_STATIC_LIFETIME, lifetime.span, "Constants have by default a `'static` lifetime", - "consider removing `'static`"); + |db| {db.span_suggestion(lifetime.span,"consider removing `'static`",sug);}); } } } diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index 30b6165d1f3..a6fed5f58d2 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,65 +1,52 @@ +warning: running cargo clippy on a crate that also imports the clippy plugin + error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:6:17 + --> $DIR/const_static_lifetime.rs:7:17 | -6 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. - | ^^^^^^^ +7 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. + | ^^^^^^^ help: consider removing `'static`: `&str` | = note: `-D const-static-lifetime` implied by `-D warnings` - = help: consider removing `'static` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:10:21 - | -10 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static - | ^^^^^^^ + --> $DIR/const_static_lifetime.rs:11:21 | - = help: consider removing `'static` +11 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:12:32 + --> $DIR/const_static_lifetime.rs:13:32 | -12 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ - | - = help: consider removing `'static` +13 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:12:47 - | -12 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ + --> $DIR/const_static_lifetime.rs:13:47 | - = help: consider removing `'static` +13 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:14:30 + --> $DIR/const_static_lifetime.rs:15:30 | -14 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static - | ^^^^^^^ - | - = help: consider removing `'static` +15 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:16:17 - | -16 | const VAR_SIX: &'static u8 = &5; - | ^^^^^^^ + --> $DIR/const_static_lifetime.rs:17:17 | - = help: consider removing `'static` +17 | const VAR_SIX: &'static u8 = &5; + | ^^^^^^^ help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:18:39 + --> $DIR/const_static_lifetime.rs:19:39 | -18 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; - | ^^^^^^^ - | - = help: consider removing `'static` +19 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:20:20 - | -20 | const VAR_HEIGHT: &'static Foo = &Foo {}; - | ^^^^^^^ + --> $DIR/const_static_lifetime.rs:21:20 | - = help: consider removing `'static` +21 | const VAR_HEIGHT: &'static Foo = &Foo {}; + | ^^^^^^^ help: consider removing `'static`: `&Foo` -- cgit 1.4.1-3-g733a5 From 0928168a79e4e2166cdc33b2d133bd82e42c4b33 Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 09:53:39 -0400 Subject: Remove "#![feature(plugin)]" in the test". --- clippy_lints/src/const_static_lifetime.rs | 1 - tests/ui/const_static_lifetime.rs | 2 -- tests/ui/const_static_lifetime.stderr | 38 +++++++++++++++---------------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 4f2d8656532..4801f788856 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -39,7 +39,6 @@ impl StaticConst { match ty.node { // Be carefull of nested structures (arrays and tuples) TyKind::Array(ref ty, _) => { - println!("array"); self.visit_type(&*ty, cx); }, TyKind::Tup(ref tup) => { diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index 05b7a3e0117..d2caf59935e 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -1,5 +1,3 @@ -#![feature(plugin)] - #[derive(Debug)] struct Foo {} diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index a6fed5f58d2..8445e46758c 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,52 +1,50 @@ -warning: running cargo clippy on a crate that also imports the clippy plugin - error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:7:17 + --> $DIR/const_static_lifetime.rs:4:17 | -7 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | ^^^^^^^ help: consider removing `'static`: `&str` | = note: `-D const-static-lifetime` implied by `-D warnings` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:11:21 - | -11 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static`: `&str` + --> $DIR/const_static_lifetime.rs:8:21 + | +8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:13:32 + --> $DIR/const_static_lifetime.rs:10:32 | -13 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:13:47 + --> $DIR/const_static_lifetime.rs:10:47 | -13 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:15:30 + --> $DIR/const_static_lifetime.rs:12:30 | -15 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:17:17 + --> $DIR/const_static_lifetime.rs:14:17 | -17 | const VAR_SIX: &'static u8 = &5; +14 | const VAR_SIX: &'static u8 = &5; | ^^^^^^^ help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:19:39 + --> $DIR/const_static_lifetime.rs:16:39 | -19 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | ^^^^^^^ help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:21:20 + --> $DIR/const_static_lifetime.rs:18:20 | -21 | const VAR_HEIGHT: &'static Foo = &Foo {}; +18 | const VAR_HEIGHT: &'static Foo = &Foo {}; | ^^^^^^^ help: consider removing `'static`: `&Foo` -- cgit 1.4.1-3-g733a5 From acdd93a5ccd5f3284ea5e059ce17e0cd79e41cc4 Mon Sep 17 00:00:00 2001 From: Paul Florence Date: Fri, 20 Oct 2017 10:02:43 -0400 Subject: Final .stderr for `const_static_lifetime`. --- tests/ui/const_static_lifetime.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index 8445e46758c..1eeb27c2448 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -2,7 +2,7 @@ error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:4:17 | 4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` | = note: `-D const-static-lifetime` implied by `-D warnings` @@ -10,41 +10,41 @@ error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:8:21 | 8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:10:32 | 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:10:47 | 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:12:30 | 12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:14:17 | 14 | const VAR_SIX: &'static u8 = &5; - | ^^^^^^^ help: consider removing `'static`: `&u8` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:16:39 | 16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; - | ^^^^^^^ help: consider removing `'static`: `&str` + | ^^^^^^^ help: consider removing `'static` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:18:20 | 18 | const VAR_HEIGHT: &'static Foo = &Foo {}; - | ^^^^^^^ help: consider removing `'static`: `&Foo` + | ^^^^^^^ help: consider removing `'static` -- cgit 1.4.1-3-g733a5 From 22f3ca0e2ce547ceb0138d8acc209a0f29d924f0 Mon Sep 17 00:00:00 2001 From: Malo Jaffré Date: Fri, 20 Oct 2017 16:45:17 +0200 Subject: Add PRINTLN_EMPTY_STRING lint. --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/print.rs | 81 +++++++++++++++++++++++++++++------- tests/ui/println_empty_string.rs | 4 ++ tests/ui/println_empty_string.stderr | 8 ++++ 4 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 tests/ui/println_empty_string.rs create mode 100644 tests/ui/println_empty_string.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 355b03b2b6a..524b5977d13 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -530,6 +530,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, print::PRINT_WITH_NEWLINE, + print::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, ptr::MUT_FROM_REF, ptr::PTR_ARG, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 96557b8b0cb..b7ccf19a313 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -1,11 +1,30 @@ +use std::ops::Deref; use rustc::hir::*; use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::lint::*; use syntax::ast::LitKind; use syntax::symbol::InternedString; +use syntax_pos::Span; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use utils::{paths, opt_def_id}; +/// **What it does:** This lint warns when you using `println!("")` to +/// print a newline. +/// +/// **Why is this bad?** You should use `println!()`, which is simpler. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// println!(""); +/// ``` +declare_lint! { + pub PRINTLN_EMPTY_STRING, + Warn, + "using `print!()` with a format string that ends in a newline" +} + /// **What it does:** This lint warns when you using `print!()` with a format /// string that /// ends in a newline. @@ -64,7 +83,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(PRINT_WITH_NEWLINE, PRINT_STDOUT, USE_DEBUG) + lint_array!(PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, USE_DEBUG) } } @@ -88,10 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - // Check print! with format string ending in "\n". if_let_chain!{[ - name == "print", - // ensure we're calling Arguments::new_v1 args.len() == 1, let ExprCall(ref args_fun, ref args_args) = args[0].node, @@ -102,20 +118,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ExprAddrOf(_, ref match_expr) = args_args[1].node, let ExprMatch(ref args, _, _) = match_expr.node, let ExprTup(ref args) = args.node, - - // collect the format string parts and check the last one let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]), - let Some('\n') = fmtstr.chars().last(), - - // "foo{}bar" is made into two strings + one argument, - // if the format string starts with `{}` (eg. "{}foo"), - // the string array is prepended an empty string "". - // We only want to check the last string after any `{}`: - args.len() < fmtlen, ], { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `print!()` with a format string that ends in a \ - newline, consider using `println!()` instead"); + match name { + "print" => check_print(cx, span, args, fmtstr, fmtlen), + "println" => check_println(cx, span, fmtstr, fmtlen), + _ => (), + } }} } } @@ -135,6 +144,46 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } +// Check for print!("... \n", ...). +fn check_print<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + span: Span, + args: &HirVec, + fmtstr: InternedString, + fmtlen: usize, +) { + if_let_chain!{[ + // check the final format string part + let Some('\n') = fmtstr.chars().last(), + + // "foo{}bar" is made into two strings + one argument, + // if the format string starts with `{}` (eg. "{}foo"), + // the string array is prepended an empty string "". + // We only want to check the last string after any `{}`: + args.len() < fmtlen, + ], { + span_lint(cx, PRINT_WITH_NEWLINE, span, + "using `print!()` with a format string that ends in a \ + newline, consider using `println!()` instead"); + }} +} + +/// Check for println!("") +fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) { + if_let_chain!{[ + // check that the string is empty + fmtlen == 1, + fmtstr.deref() == "\n", + + // check the presence of that string + let Ok(snippet) = cx.sess().codemap().span_to_snippet(span), + snippet.contains("\"\""), + ], { + span_lint(cx, PRINT_WITH_NEWLINE, span, + "using `println!(\"\")`, consider using `println!()` instead"); + }} +} + fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { let map = &cx.tcx.hir; diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs new file mode 100644 index 00000000000..82495f1b39d --- /dev/null +++ b/tests/ui/println_empty_string.rs @@ -0,0 +1,4 @@ +fn main() { + println!(); + println!(""); +} diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr new file mode 100644 index 00000000000..8beca8b88cb --- /dev/null +++ b/tests/ui/println_empty_string.stderr @@ -0,0 +1,8 @@ +error: using `println!("")`, consider using `println!()` instead + --> $DIR/println_empty_string.rs:3:5 + | +3 | println!(""); + | ^^^^^^^^^^^^^ + | + = note: `-D print-with-newline` implied by `-D warnings` + -- cgit 1.4.1-3-g733a5 From 4734bc015029d83c6b71620e8481583a0d4e8065 Mon Sep 17 00:00:00 2001 From: Malo Jaffré Date: Fri, 20 Oct 2017 23:20:44 +0200 Subject: Ignore Cargo.lock in .gitignore Since the merge of #2146, `Cargo.lock` is no longer checked in the git repository, but `cargo` generates it anyway, if we are not in the main rust repository. Ignore it to avoid eventual confusion when contributing directly to clippy. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dbb5a66e469..64d0c25752d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ out *.exe # Generated by Cargo +Cargo.lock /target/ /clippy_lints/target/ -- cgit 1.4.1-3-g733a5 From ff4a85035328e4cff43ac7dbeb1615b2a8cc4621 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 20 Oct 2017 11:39:20 -0400 Subject: Add lint for useless `as_ref` calls --- clippy_lints/src/methods.rs | 55 ++++++++++++++++++++++++- tests/ui/useless_asref.rs | 94 +++++++++++++++++++++++++++++++++++++++++++ tests/ui/useless_asref.stderr | 60 +++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 tests/ui/useless_asref.rs create mode 100644 tests/ui/useless_asref.stderr diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 849f0024415..4a0d1cf19cb 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -581,6 +581,29 @@ declare_lint! { "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char" } +/// **What it does:** Checks for usage of `.as_ref()` or `.as_mut()` where the +/// types before and after the call are the same. +/// +/// **Why is this bad?** The call is unnecessary. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x: &[i32] = &[1,2,3,4,5]; +/// do_stuff(x.as_ref()); +/// ``` +/// The correct use would be: +/// ```rust +/// let x: &[i32] = &[1,2,3,4,5]; +/// do_stuff(x); +/// ``` +declare_lint! { + pub USELESS_ASREF, + Warn, + "using `as_ref` where the types before and after the call are the same" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( @@ -609,8 +632,8 @@ impl LintPass for Pass { ITER_SKIP_NEXT, GET_UNWRAP, STRING_EXTEND_CHARS, - ITER_CLONED_COLLECT - ) + ITER_CLONED_COLLECT, + USELESS_ASREF) } } @@ -669,6 +692,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_iter_skip_next(cx, expr); } else if let Some(arglists) = method_chain_args(expr, &["cloned", "collect"]) { lint_iter_cloned_collect(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["as_ref"]) { + lint_asref(cx, expr, "as_ref", arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { + lint_asref(cx, expr, "as_mut", arglists[0]); } lint_or_fun_call(cx, expr, &method_call.name.as_str(), args); @@ -1504,6 +1531,30 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi } } +/// Checks for the `USELESS_ASREF` lint. +fn lint_asref(cx: &LateContext, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) { + // when we get here, we've already checked that the call name is "as_ref" or "as_mut" + // check if the call is to the actual `AsRef` or `AsMut` trait + if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { + // check if the type after `as_ref` or `as_mut` is the same as before + let recvr = &as_ref_args[0]; + let rcv_ty = cx.tables.expr_ty(recvr); + let res_ty = cx.tables.expr_ty(expr); + let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); + let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); + if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { + span_lint_and_sugg( + cx, + USELESS_ASREF, + expr.span, + &format!("this call to `{}` does nothing", call_name), + "try this", + snippet(cx, recvr.span, "_").into_owned(), + ); + } + } +} + /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option> { if let ty::TyAdt(_, substs) = ty.sty { diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs new file mode 100644 index 00000000000..ef0174ad71f --- /dev/null +++ b/tests/ui/useless_asref.rs @@ -0,0 +1,94 @@ +#![deny(useless_asref)] + +struct FakeAsRef; + +#[allow(should_implement_trait)] +impl FakeAsRef { + fn as_ref(&self) -> &Self { self } +} + +struct MoreRef; + +impl<'a, 'b, 'c> AsRef<&'a &'b &'c MoreRef> for MoreRef { + fn as_ref(&self) -> &&'a &'b &'c MoreRef { + &&&&MoreRef + } +} + +fn foo_rstr(x: &str) { println!("{:?}", x); } +fn foo_rslice(x: &[i32]) { println!("{:?}", x); } +fn foo_mrslice(x: &mut [i32]) { println!("{:?}", x); } +fn foo_rrrrmr(_: &&&&MoreRef) { println!("so many refs"); } + +fn not_ok() { + let rstr: &str = "hello"; + let mut mrslice: &mut [i32] = &mut [1,2,3]; + + { + let rslice: &[i32] = &*mrslice; + foo_rstr(rstr.as_ref()); + foo_rstr(rstr); + foo_rslice(rslice.as_ref()); + foo_rslice(rslice); + } + { + foo_mrslice(mrslice.as_mut()); + foo_mrslice(mrslice); + foo_rslice(mrslice.as_ref()); + foo_rslice(mrslice); + } + + { + let rrrrrstr = &&&&rstr; + let rrrrrslice = &&&&&*mrslice; + foo_rslice(rrrrrslice.as_ref()); + foo_rslice(rrrrrslice); + foo_rstr(rrrrrstr.as_ref()); + foo_rstr(rrrrrstr); + } + { + let mrrrrrslice = &mut &mut &mut &mut mrslice; + foo_mrslice(mrrrrrslice.as_mut()); + foo_mrslice(mrrrrrslice); + foo_rslice(mrrrrrslice.as_ref()); + foo_rslice(mrrrrrslice); + } + foo_rrrrmr((&&&&MoreRef).as_ref()); +} + +fn ok() { + let string = "hello".to_owned(); + let mut arr = [1,2,3]; + let mut vec = vec![1,2,3]; + + { + foo_rstr(string.as_ref()); + foo_rslice(arr.as_ref()); + foo_rslice(vec.as_ref()); + } + { + foo_mrslice(arr.as_mut()); + foo_mrslice(vec.as_mut()); + } + + { + let rrrrstring = &&&&string; + let rrrrarr = &&&&arr; + let rrrrvec = &&&&vec; + foo_rstr(rrrrstring.as_ref()); + foo_rslice(rrrrarr.as_ref()); + foo_rslice(rrrrvec.as_ref()); + } + { + let mrrrrarr = &mut &mut &mut &mut arr; + let mrrrrvec = &mut &mut &mut &mut vec; + foo_mrslice(mrrrrarr.as_mut()); + foo_mrslice(mrrrrvec.as_mut()); + } + FakeAsRef.as_ref(); + foo_rrrrmr(MoreRef.as_ref()); +} +fn main() { + not_ok(); + ok(); +} diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr new file mode 100644 index 00000000000..8cc869ad775 --- /dev/null +++ b/tests/ui/useless_asref.stderr @@ -0,0 +1,60 @@ +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:29:18 + | +29 | foo_rstr(rstr.as_ref()); + | ^^^^^^^^^^^^^ help: try this: `rstr` + | +note: lint level defined here + --> $DIR/useless_asref.rs:1:9 + | +1 | #![deny(useless_asref)] + | ^^^^^^^^^^^^^ + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:31:20 + | +31 | foo_rslice(rslice.as_ref()); + | ^^^^^^^^^^^^^^^ help: try this: `rslice` + +error: this call to `as_mut` does nothing + --> $DIR/useless_asref.rs:35:21 + | +35 | foo_mrslice(mrslice.as_mut()); + | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:37:20 + | +37 | foo_rslice(mrslice.as_ref()); + | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:44:20 + | +44 | foo_rslice(rrrrrslice.as_ref()); + | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:46:18 + | +46 | foo_rstr(rrrrrstr.as_ref()); + | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` + +error: this call to `as_mut` does nothing + --> $DIR/useless_asref.rs:51:21 + | +51 | foo_mrslice(mrrrrrslice.as_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:53:20 + | +53 | foo_rslice(mrrrrrslice.as_ref()); + | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:56:16 + | +56 | foo_rrrrmr((&&&&MoreRef).as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` + -- cgit 1.4.1-3-g733a5 From e5076d06dbb767a3bd17b4bf70f03c2e5d1221d9 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Mon, 16 Oct 2017 17:06:31 -0400 Subject: Add lint for `From` --- clippy_lints/src/impl_from_str.rs | 136 ++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 + clippy_lints/src/utils/paths.rs | 2 + tests/ui/impl_from_str.rs | 69 +++++++++++++++++++ tests/ui/impl_from_str.stderr | 80 ++++++++++++++++++++++ 5 files changed, 290 insertions(+) create mode 100644 clippy_lints/src/impl_from_str.rs create mode 100644 tests/ui/impl_from_str.rs create mode 100644 tests/ui/impl_from_str.stderr diff --git a/clippy_lints/src/impl_from_str.rs b/clippy_lints/src/impl_from_str.rs new file mode 100644 index 00000000000..5d9b3226e11 --- /dev/null +++ b/clippy_lints/src/impl_from_str.rs @@ -0,0 +1,136 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::ty; +use syntax_pos::Span; +use utils::{method_chain_args, match_def_path, span_lint_and_then, walk_ptrs_ty}; +use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT, STRING}; + +/// **What it does:** Checks for impls of `From<&str>` and `From` that contain `panic!()` or +/// `unwrap()` +/// +/// **Why is this bad?** `FromStr` should be used if there's a possibility of failure. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// struct Foo(i32); +/// impl From for Foo { +/// fn from(s: String) -> Self { +/// Foo(s.parse().unwrap()) +/// } +/// } +/// ``` +declare_lint! { + pub IMPL_FROM_STR, Warn, + "Warn on impls of `From<&str>` and `From` that contain `panic!()` or `unwrap()`" +} + +pub struct ImplFromStr; + +impl LintPass for ImplFromStr { + fn get_lints(&self) -> LintArray { + lint_array!(IMPL_FROM_STR) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplFromStr { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { + // check for `impl From for ..` + let impl_def_id = cx.tcx.hir.local_def_id(item.id); + if_let_chain!{[ + let hir::ItemImpl(.., ref impl_items) = item.node, + let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id), + match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT), + ], { + // check if the type parameter is `str` or `String` + let from_ty_param = impl_trait_ref.substs.type_at(1); + let base_from_ty_param = + walk_ptrs_ty(cx.tcx.normalize_associated_type(&from_ty_param)); + if base_from_ty_param.sty == ty::TyStr || + match_type(cx.tcx, base_from_ty_param, &STRING) + { + lint_impl_body(cx, item.span, impl_items); + } + }} + } +} + +fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec) { + use rustc::hir::*; + use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; + + struct FindPanicUnwrap<'a, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + tables: &'tcx ty::TypeckTables<'tcx>, + result: Vec, + } + + impl<'a, 'tcx: 'a> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + // check for `begin_panic` + if_let_chain!{[ + let ExprCall(ref func_expr, _) = expr.node, + let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node, + match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || + match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT), + ], { + self.result.push(expr.span); + }} + + // check for `unwrap` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); + if match_type(self.tcx, reciever_ty, &OPTION) || + match_type(self.tcx, reciever_ty, &RESULT) + { + self.result.push(expr.span); + } + } + + // and check sub-expressions + intravisit::walk_expr(self, expr); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + } + + for impl_item in impl_items { + if_let_chain!{[ + impl_item.name == "from", + let ImplItemKind::Method(_, body_id) = + cx.tcx.hir.impl_item(impl_item.id).node, + ], { + // check the body for `begin_panic` or `unwrap` + let body = cx.tcx.hir.body(body_id); + let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); + let mut fpu = FindPanicUnwrap { + tcx: cx.tcx, + tables: cx.tcx.typeck_tables_of(impl_item_def_id), + result: Vec::new(), + }; + fpu.visit_expr(&body.value); + + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + IMPL_FROM_STR, + impl_span, + "consider implementing `FromStr` instead", + move |db| { + db.span_note(fpu.result, "potential failure(s)"); + }); + } + }} + } +} + +fn match_type(tcx: ty::TyCtxt, ty: ty::Ty, path: &[&str]) -> bool { + match ty.sty { + ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path), + _ => false, + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 110f6b63c82..96bc4fe729c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -100,6 +100,7 @@ pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; +pub mod impl_from_str; pub mod infinite_iter; pub mod int_plus_one; pub mod invalid_ref; @@ -341,6 +342,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_early_lint_pass(box const_static_lifetime::StaticConst); + reg.register_late_lint_pass(box impl_from_str::ImplFromStr); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -446,6 +448,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + impl_from_str::IMPL_FROM_STR, infinite_iter::INFINITE_ITER, invalid_ref::INVALID_REF, is_unit_expr::UNIT_EXPR, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index c198ad64b0f..96ccddaf2d0 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -6,6 +6,7 @@ pub const ARC: [&str; 3] = ["alloc", "arc", "Arc"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; +pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; pub const BINARY_HEAP: [&str; 3] = ["alloc", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BOX: [&str; 3] = ["std", "boxed", "Box"]; @@ -27,6 +28,7 @@ pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; +pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/tests/ui/impl_from_str.rs b/tests/ui/impl_from_str.rs new file mode 100644 index 00000000000..d0ebe5d988a --- /dev/null +++ b/tests/ui/impl_from_str.rs @@ -0,0 +1,69 @@ +// docs example +struct Foo(i32); +impl From for Foo { + fn from(s: String) -> Self { + Foo(s.parse().unwrap()) + } +} + + +struct Valid(Vec); + +impl<'a> From<&'a str> for Valid { + fn from(s: &'a str) -> Valid { + Valid(s.to_owned().into_bytes()) + } +} +impl From for Valid { + fn from(s: String) -> Valid { + Valid(s.into_bytes()) + } +} +impl From for Valid { + fn from(i: usize) -> Valid { + if i == 0 { + panic!(); + } + Valid(Vec::with_capacity(i)) + } +} + + +struct Invalid; + +impl<'a> From<&'a str> for Invalid { + fn from(s: &'a str) -> Invalid { + if !s.is_empty() { + panic!(); + } + Invalid + } +} + +impl From for Invalid { + fn from(s: String) -> Invalid { + if !s.is_empty() { + panic!(42); + } else if s.parse::().unwrap() != 42 { + panic!("{:?}", s); + } + Invalid + } +} + +trait ProjStrTrait { + type ProjString; +} +impl ProjStrTrait for Box { + type ProjString = String; +} +impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { + fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { + if s.parse::().ok().unwrap() != 42 { + panic!("{:?}", s); + } + Invalid + } +} + +fn main() {} diff --git a/tests/ui/impl_from_str.stderr b/tests/ui/impl_from_str.stderr new file mode 100644 index 00000000000..b394df153e2 --- /dev/null +++ b/tests/ui/impl_from_str.stderr @@ -0,0 +1,80 @@ +error: consider implementing `FromStr` instead + --> $DIR/impl_from_str.rs:3:1 + | +3 | / impl From for Foo { +4 | | fn from(s: String) -> Self { +5 | | Foo(s.parse().unwrap()) +6 | | } +7 | | } + | |_^ + | + = note: `-D impl-from-str` implied by `-D warnings` +note: potential failure(s) + --> $DIR/impl_from_str.rs:5:13 + | +5 | Foo(s.parse().unwrap()) + | ^^^^^^^^^^^^^^^^^^ + +error: consider implementing `FromStr` instead + --> $DIR/impl_from_str.rs:34:1 + | +34 | / impl<'a> From<&'a str> for Invalid { +35 | | fn from(s: &'a str) -> Invalid { +36 | | if !s.is_empty() { +37 | | panic!(); +... | +40 | | } +41 | | } + | |_^ + | +note: potential failure(s) + --> $DIR/impl_from_str.rs:37:13 + | +37 | panic!(); + | ^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: consider implementing `FromStr` instead + --> $DIR/impl_from_str.rs:43:1 + | +43 | / impl From for Invalid { +44 | | fn from(s: String) -> Invalid { +45 | | if !s.is_empty() { +46 | | panic!(42); +... | +51 | | } +52 | | } + | |_^ + | +note: potential failure(s) + --> $DIR/impl_from_str.rs:46:13 + | +46 | panic!(42); + | ^^^^^^^^^^^ +47 | } else if s.parse::().unwrap() != 42 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +48 | panic!("{:?}", s); + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: consider implementing `FromStr` instead + --> $DIR/impl_from_str.rs:60:1 + | +60 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +61 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +62 | | if s.parse::().ok().unwrap() != 42 { +63 | | panic!("{:?}", s); +... | +66 | | } +67 | | } + | |_^ + | +note: potential failure(s) + --> $DIR/impl_from_str.rs:62:12 + | +62 | if s.parse::().ok().unwrap() != 42 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +63 | panic!("{:?}", s); + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + -- cgit 1.4.1-3-g733a5 From 7206023b1b203e478fdbe450e63829690a92d6a4 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Tue, 17 Oct 2017 12:09:10 -0400 Subject: Change to `TryFrom` --- clippy_lints/src/fallible_impl_from.rs | 130 +++++++++++++++++++++++++++++++ clippy_lints/src/impl_from_str.rs | 136 --------------------------------- clippy_lints/src/lib.rs | 6 +- tests/ui/fallible_impl_from.rs | 64 ++++++++++++++++ tests/ui/fallible_impl_from.stderr | 91 ++++++++++++++++++++++ tests/ui/impl_from_str.rs | 69 ----------------- tests/ui/impl_from_str.stderr | 80 ------------------- 7 files changed, 288 insertions(+), 288 deletions(-) create mode 100644 clippy_lints/src/fallible_impl_from.rs delete mode 100644 clippy_lints/src/impl_from_str.rs create mode 100644 tests/ui/fallible_impl_from.rs create mode 100644 tests/ui/fallible_impl_from.stderr delete mode 100644 tests/ui/impl_from_str.rs delete mode 100644 tests/ui/impl_from_str.stderr diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs new file mode 100644 index 00000000000..bdcda99124c --- /dev/null +++ b/clippy_lints/src/fallible_impl_from.rs @@ -0,0 +1,130 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::ty; +use syntax_pos::Span; +use utils::{method_chain_args, match_def_path, span_lint_and_then, walk_ptrs_ty}; +use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; + +/// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` +/// +/// **Why is this bad?** `TryFrom` should be used if there's a possibility of failure. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// struct Foo(i32); +/// impl From for Foo { +/// fn from(s: String) -> Self { +/// Foo(s.parse().unwrap()) +/// } +/// } +/// ``` +declare_lint! { + pub FALLIBLE_IMPL_FROM, Allow, + "Warn on impls of `From<..>` that contain `panic!()` or `unwrap()`" +} + +pub struct FallibleImplFrom; + +impl LintPass for FallibleImplFrom { + fn get_lints(&self) -> LintArray { + lint_array!(FALLIBLE_IMPL_FROM) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { + // check for `impl From for ..` + let impl_def_id = cx.tcx.hir.local_def_id(item.id); + if_let_chain!{[ + let hir::ItemImpl(.., ref impl_items) = item.node, + let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id), + match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT), + ], { + lint_impl_body(cx, item.span, impl_items); + }} + } +} + +fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec) { + use rustc::hir::*; + use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; + + struct FindPanicUnwrap<'a, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + tables: &'tcx ty::TypeckTables<'tcx>, + result: Vec, + } + + impl<'a, 'tcx: 'a> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + // check for `begin_panic` + if_let_chain!{[ + let ExprCall(ref func_expr, _) = expr.node, + let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node, + match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || + match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT), + ], { + self.result.push(expr.span); + }} + + // check for `unwrap` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); + if match_type(self.tcx, reciever_ty, &OPTION) || + match_type(self.tcx, reciever_ty, &RESULT) + { + self.result.push(expr.span); + } + } + + // and check sub-expressions + intravisit::walk_expr(self, expr); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + } + + for impl_item in impl_items { + if_let_chain!{[ + impl_item.name == "from", + let ImplItemKind::Method(_, body_id) = + cx.tcx.hir.impl_item(impl_item.id).node, + ], { + // check the body for `begin_panic` or `unwrap` + let body = cx.tcx.hir.body(body_id); + let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); + let mut fpu = FindPanicUnwrap { + tcx: cx.tcx, + tables: cx.tcx.typeck_tables_of(impl_item_def_id), + result: Vec::new(), + }; + fpu.visit_expr(&body.value); + + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + FALLIBLE_IMPL_FROM, + impl_span, + "consider implementing `TryFrom` instead", + move |db| { + db.help( + "`From` is intended for infallible conversions only. \ + Use `TryFrom` if there's a possibility for the conversion to fail."); + db.span_note(fpu.result, "potential failure(s)"); + }); + } + }} + } +} + +fn match_type(tcx: ty::TyCtxt, ty: ty::Ty, path: &[&str]) -> bool { + match ty.sty { + ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path), + _ => false, + } +} diff --git a/clippy_lints/src/impl_from_str.rs b/clippy_lints/src/impl_from_str.rs deleted file mode 100644 index 5d9b3226e11..00000000000 --- a/clippy_lints/src/impl_from_str.rs +++ /dev/null @@ -1,136 +0,0 @@ -use rustc::lint::*; -use rustc::hir; -use rustc::ty; -use syntax_pos::Span; -use utils::{method_chain_args, match_def_path, span_lint_and_then, walk_ptrs_ty}; -use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT, STRING}; - -/// **What it does:** Checks for impls of `From<&str>` and `From` that contain `panic!()` or -/// `unwrap()` -/// -/// **Why is this bad?** `FromStr` should be used if there's a possibility of failure. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// struct Foo(i32); -/// impl From for Foo { -/// fn from(s: String) -> Self { -/// Foo(s.parse().unwrap()) -/// } -/// } -/// ``` -declare_lint! { - pub IMPL_FROM_STR, Warn, - "Warn on impls of `From<&str>` and `From` that contain `panic!()` or `unwrap()`" -} - -pub struct ImplFromStr; - -impl LintPass for ImplFromStr { - fn get_lints(&self) -> LintArray { - lint_array!(IMPL_FROM_STR) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplFromStr { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { - // check for `impl From for ..` - let impl_def_id = cx.tcx.hir.local_def_id(item.id); - if_let_chain!{[ - let hir::ItemImpl(.., ref impl_items) = item.node, - let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id), - match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT), - ], { - // check if the type parameter is `str` or `String` - let from_ty_param = impl_trait_ref.substs.type_at(1); - let base_from_ty_param = - walk_ptrs_ty(cx.tcx.normalize_associated_type(&from_ty_param)); - if base_from_ty_param.sty == ty::TyStr || - match_type(cx.tcx, base_from_ty_param, &STRING) - { - lint_impl_body(cx, item.span, impl_items); - } - }} - } -} - -fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec) { - use rustc::hir::*; - use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; - - struct FindPanicUnwrap<'a, 'tcx: 'a> { - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, - tables: &'tcx ty::TypeckTables<'tcx>, - result: Vec, - } - - impl<'a, 'tcx: 'a> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr) { - // check for `begin_panic` - if_let_chain!{[ - let ExprCall(ref func_expr, _) = expr.node, - let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node, - match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || - match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT), - ], { - self.result.push(expr.span); - }} - - // check for `unwrap` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); - if match_type(self.tcx, reciever_ty, &OPTION) || - match_type(self.tcx, reciever_ty, &RESULT) - { - self.result.push(expr.span); - } - } - - // and check sub-expressions - intravisit::walk_expr(self, expr); - } - - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - } - - for impl_item in impl_items { - if_let_chain!{[ - impl_item.name == "from", - let ImplItemKind::Method(_, body_id) = - cx.tcx.hir.impl_item(impl_item.id).node, - ], { - // check the body for `begin_panic` or `unwrap` - let body = cx.tcx.hir.body(body_id); - let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); - let mut fpu = FindPanicUnwrap { - tcx: cx.tcx, - tables: cx.tcx.typeck_tables_of(impl_item_def_id), - result: Vec::new(), - }; - fpu.visit_expr(&body.value); - - // if we've found one, lint - if !fpu.result.is_empty() { - span_lint_and_then( - cx, - IMPL_FROM_STR, - impl_span, - "consider implementing `FromStr` instead", - move |db| { - db.span_note(fpu.result, "potential failure(s)"); - }); - } - }} - } -} - -fn match_type(tcx: ty::TyCtxt, ty: ty::Ty, path: &[&str]) -> bool { - match ty.sty { - ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path), - _ => false, - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 96bc4fe729c..81839b92cd5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -100,7 +100,7 @@ pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; -pub mod impl_from_str; +pub mod fallible_impl_from; pub mod infinite_iter; pub mod int_plus_one; pub mod invalid_ref; @@ -342,7 +342,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_early_lint_pass(box const_static_lifetime::StaticConst); - reg.register_late_lint_pass(box impl_from_str::ImplFromStr); + reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -448,7 +448,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, - impl_from_str::IMPL_FROM_STR, + fallible_impl_from::FALLIBLE_IMPL_FROM, infinite_iter::INFINITE_ITER, invalid_ref::INVALID_REF, is_unit_expr::UNIT_EXPR, diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs new file mode 100644 index 00000000000..eb1cd4c5e9a --- /dev/null +++ b/tests/ui/fallible_impl_from.rs @@ -0,0 +1,64 @@ +#![deny(fallible_impl_from)] + +// docs example +struct Foo(i32); +impl From for Foo { + fn from(s: String) -> Self { + Foo(s.parse().unwrap()) + } +} + + +struct Valid(Vec); + +impl<'a> From<&'a str> for Valid { + fn from(s: &'a str) -> Valid { + Valid(s.to_owned().into_bytes()) + } +} +impl From for Valid { + fn from(i: usize) -> Valid { + Valid(Vec::with_capacity(i)) + } +} + + +struct Invalid; + +impl From for Invalid { + fn from(i: usize) -> Invalid { + if i != 42 { + panic!(); + } + Invalid + } +} + +impl From> for Invalid { + fn from(s: Option) -> Invalid { + let s = s.unwrap(); + if !s.is_empty() { + panic!(42); + } else if s.parse::().unwrap() != 42 { + panic!("{:?}", s); + } + Invalid + } +} + +trait ProjStrTrait { + type ProjString; +} +impl ProjStrTrait for Box { + type ProjString = String; +} +impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { + fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { + if s.parse::().ok().unwrap() != 42 { + panic!("{:?}", s); + } + Invalid + } +} + +fn main() {} diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr new file mode 100644 index 00000000000..89dfaf623ed --- /dev/null +++ b/tests/ui/fallible_impl_from.stderr @@ -0,0 +1,91 @@ +error: consider implementing `TryFrom` instead + --> $DIR/fallible_impl_from.rs:5:1 + | +5 | / impl From for Foo { +6 | | fn from(s: String) -> Self { +7 | | Foo(s.parse().unwrap()) +8 | | } +9 | | } + | |_^ + | +note: lint level defined here + --> $DIR/fallible_impl_from.rs:1:9 + | +1 | #![deny(fallible_impl_from)] + | ^^^^^^^^^^^^^^^^^^ + = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. +note: potential failure(s) + --> $DIR/fallible_impl_from.rs:7:13 + | +7 | Foo(s.parse().unwrap()) + | ^^^^^^^^^^^^^^^^^^ + +error: consider implementing `TryFrom` instead + --> $DIR/fallible_impl_from.rs:28:1 + | +28 | / impl From for Invalid { +29 | | fn from(i: usize) -> Invalid { +30 | | if i != 42 { +31 | | panic!(); +... | +34 | | } +35 | | } + | |_^ + | + = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. +note: potential failure(s) + --> $DIR/fallible_impl_from.rs:31:13 + | +31 | panic!(); + | ^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: consider implementing `TryFrom` instead + --> $DIR/fallible_impl_from.rs:37:1 + | +37 | / impl From> for Invalid { +38 | | fn from(s: Option) -> Invalid { +39 | | let s = s.unwrap(); +40 | | if !s.is_empty() { +... | +46 | | } +47 | | } + | |_^ + | + = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. +note: potential failure(s) + --> $DIR/fallible_impl_from.rs:39:17 + | +39 | let s = s.unwrap(); + | ^^^^^^^^^^ +40 | if !s.is_empty() { +41 | panic!(42); + | ^^^^^^^^^^^ +42 | } else if s.parse::().unwrap() != 42 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +43 | panic!("{:?}", s); + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + +error: consider implementing `TryFrom` instead + --> $DIR/fallible_impl_from.rs:55:1 + | +55 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +56 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +57 | | if s.parse::().ok().unwrap() != 42 { +58 | | panic!("{:?}", s); +... | +61 | | } +62 | | } + | |_^ + | + = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. +note: potential failure(s) + --> $DIR/fallible_impl_from.rs:57:12 + | +57 | if s.parse::().ok().unwrap() != 42 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +58 | panic!("{:?}", s); + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate + diff --git a/tests/ui/impl_from_str.rs b/tests/ui/impl_from_str.rs deleted file mode 100644 index d0ebe5d988a..00000000000 --- a/tests/ui/impl_from_str.rs +++ /dev/null @@ -1,69 +0,0 @@ -// docs example -struct Foo(i32); -impl From for Foo { - fn from(s: String) -> Self { - Foo(s.parse().unwrap()) - } -} - - -struct Valid(Vec); - -impl<'a> From<&'a str> for Valid { - fn from(s: &'a str) -> Valid { - Valid(s.to_owned().into_bytes()) - } -} -impl From for Valid { - fn from(s: String) -> Valid { - Valid(s.into_bytes()) - } -} -impl From for Valid { - fn from(i: usize) -> Valid { - if i == 0 { - panic!(); - } - Valid(Vec::with_capacity(i)) - } -} - - -struct Invalid; - -impl<'a> From<&'a str> for Invalid { - fn from(s: &'a str) -> Invalid { - if !s.is_empty() { - panic!(); - } - Invalid - } -} - -impl From for Invalid { - fn from(s: String) -> Invalid { - if !s.is_empty() { - panic!(42); - } else if s.parse::().unwrap() != 42 { - panic!("{:?}", s); - } - Invalid - } -} - -trait ProjStrTrait { - type ProjString; -} -impl ProjStrTrait for Box { - type ProjString = String; -} -impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { - fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { - if s.parse::().ok().unwrap() != 42 { - panic!("{:?}", s); - } - Invalid - } -} - -fn main() {} diff --git a/tests/ui/impl_from_str.stderr b/tests/ui/impl_from_str.stderr deleted file mode 100644 index b394df153e2..00000000000 --- a/tests/ui/impl_from_str.stderr +++ /dev/null @@ -1,80 +0,0 @@ -error: consider implementing `FromStr` instead - --> $DIR/impl_from_str.rs:3:1 - | -3 | / impl From for Foo { -4 | | fn from(s: String) -> Self { -5 | | Foo(s.parse().unwrap()) -6 | | } -7 | | } - | |_^ - | - = note: `-D impl-from-str` implied by `-D warnings` -note: potential failure(s) - --> $DIR/impl_from_str.rs:5:13 - | -5 | Foo(s.parse().unwrap()) - | ^^^^^^^^^^^^^^^^^^ - -error: consider implementing `FromStr` instead - --> $DIR/impl_from_str.rs:34:1 - | -34 | / impl<'a> From<&'a str> for Invalid { -35 | | fn from(s: &'a str) -> Invalid { -36 | | if !s.is_empty() { -37 | | panic!(); -... | -40 | | } -41 | | } - | |_^ - | -note: potential failure(s) - --> $DIR/impl_from_str.rs:37:13 - | -37 | panic!(); - | ^^^^^^^^^ - = note: this error originates in a macro outside of the current crate - -error: consider implementing `FromStr` instead - --> $DIR/impl_from_str.rs:43:1 - | -43 | / impl From for Invalid { -44 | | fn from(s: String) -> Invalid { -45 | | if !s.is_empty() { -46 | | panic!(42); -... | -51 | | } -52 | | } - | |_^ - | -note: potential failure(s) - --> $DIR/impl_from_str.rs:46:13 - | -46 | panic!(42); - | ^^^^^^^^^^^ -47 | } else if s.parse::().unwrap() != 42 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -48 | panic!("{:?}", s); - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate - -error: consider implementing `FromStr` instead - --> $DIR/impl_from_str.rs:60:1 - | -60 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { -61 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -62 | | if s.parse::().ok().unwrap() != 42 { -63 | | panic!("{:?}", s); -... | -66 | | } -67 | | } - | |_^ - | -note: potential failure(s) - --> $DIR/impl_from_str.rs:62:12 - | -62 | if s.parse::().ok().unwrap() != 42 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -63 | panic!("{:?}", s); - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate - -- cgit 1.4.1-3-g733a5 From 00d35eea2621ffb4ddfc69f7d5b2385b2ef53c21 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 21 Oct 2017 10:07:24 +0900 Subject: Fix typo --- clippy_lints/src/types.rs | 4 ++-- tests/ui/implicit_hasher.stderr | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index a284392bfa0..44aab3917c7 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1561,7 +1561,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { cx, IMPLICIT_HASHER, target.span(), - &format!("impl for `{}` should be generarized over different hashers", target.type_name()), + &format!("impl for `{}` should be generalized over different hashers", target.type_name()), move |db| { suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis); }, @@ -1595,7 +1595,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { IMPLICIT_HASHER, target.span(), &format!( - "parameter of type `{}` should be generarized over different hashers", + "parameter of type `{}` should be generalized over different hashers", target.type_name() ), move |db| { diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index cc0bdc327b4..27d6e2cec08 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,4 +1,4 @@ -error: impl for `HashMap` should be generarized over different hashers +error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:11:35 | 11 | impl Foo for HashMap { @@ -14,7 +14,7 @@ help: ...and use generic constructor 17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ -error: impl for `HashMap` should be generarized over different hashers +error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:20:36 | 20 | impl Foo for (HashMap,) { @@ -29,7 +29,7 @@ help: ...and use generic constructor 22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) | ^^^^^^^^^^^^^^^^^^ -error: impl for `HashMap` should be generarized over different hashers +error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:25:19 | 25 | impl Foo for HashMap { @@ -44,7 +44,7 @@ help: ...and use generic constructor 27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ -error: impl for `HashSet` should be generarized over different hashers +error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:43:32 | 43 | impl Foo for HashSet { @@ -59,7 +59,7 @@ help: ...and use generic constructor 45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ -error: impl for `HashSet` should be generarized over different hashers +error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:48:19 | 48 | impl Foo for HashSet { @@ -74,7 +74,7 @@ help: ...and use generic constructor 50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ -error: parameter of type `HashMap` should be generarized over different hashers +error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:23 | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { @@ -85,7 +85,7 @@ help: consider adding a type parameter 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: parameter of type `HashSet` should be generarized over different hashers +error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:53 | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { @@ -96,7 +96,7 @@ help: consider adding a type parameter 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: impl for `HashMap` should be generarized over different hashers +error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:70:43 | 70 | impl Foo for HashMap { @@ -114,7 +114,7 @@ help: ...and use generic constructor 72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ -error: parameter of type `HashMap` should be generarized over different hashers +error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:33 | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { @@ -128,7 +128,7 @@ help: consider adding a type parameter 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: parameter of type `HashSet` should be generarized over different hashers +error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:63 | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { -- cgit 1.4.1-3-g733a5 From 60c7bd47a56f72938bdd8a7dce328f414e1bc78f Mon Sep 17 00:00:00 2001 From: cgm616 Date: Sat, 21 Oct 2017 07:53:57 -0400 Subject: Prevent should_implement_trait on private method This should close #2159. --- clippy_lints/src/methods.rs | 143 ++++++++++++------- tests/ui/methods.rs | 7 +- tests/ui/methods.stderr | 340 ++++++++++++++++++++++---------------------- 3 files changed, 271 insertions(+), 219 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 849f0024415..54523841b09 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -335,7 +335,8 @@ declare_lint! { /// the corresponding trait instead. /// /// **Why is this bad?**: Calling '.clone()' on an Rc, Arc, or Weak -/// can obscure the fact that only the pointer is being cloned, not the underlying +/// can obscure the fact that only the pointer is being cloned, not the +/// underlying /// data. /// /// **Example:** @@ -714,15 +715,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(), let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node, ], { - // check missing trait implementations - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if name == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(&sig.decl.output) && - self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); + if implitem.vis == hir::Visibility::Public || + implitem.vis.is_pub_restricted() { + // check missing trait implementations + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if name == method_name && + sig.decl.inputs.len() == n_args && + out_type.matches(&sig.decl.output) && + self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } } } @@ -941,12 +945,8 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { expr.span, "using '.clone()' on a ref-counted pointer", "try this", - format!("{}::clone(&{})", - caller_type, - snippet(cx, arg.span, "_") - ) + format!("{}::clone(&{})", caller_type, snippet(cx, arg.span, "_")), ); - } @@ -1004,8 +1004,8 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr } fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) && - derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() + if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) + && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { span_lint( cx, @@ -1180,8 +1180,16 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { "None" } else { "a" }; - let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { "map_or(a, f)" }; + let arg = if unwrap_snippet == "None" { + "None" + } else { + "a" + }; + let suggest = if unwrap_snippet == "None" { + "and_then(f)" + } else { + "map_or(a, f)" + }; let msg = &format!( "called `map(f).unwrap_or({})` on an Option value. \ This can be done more directly by calling `{}` instead", @@ -1212,7 +1220,12 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] } /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr], unwrap_args: &'tcx [hir::Expr]) { +fn lint_map_unwrap_or_else<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + map_args: &'tcx [hir::Expr], + unwrap_args: &'tcx [hir::Expr], +) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { // lint message @@ -1246,7 +1259,6 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir /// lint use of `_.map_or(None, _)` for `Option`s fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { // check if the first non-self argument to map_or() is None let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { @@ -1262,13 +1274,9 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); - span_lint_and_then( - cx, - OPTION_MAP_OR_NONE, - expr.span, - msg, - |db| { db.span_suggestion(expr.span, "try using and_then instead", hint); }, - ); + span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { + db.span_suggestion(expr.span, "try using and_then instead", hint); + }); } } } @@ -1297,7 +1305,12 @@ fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).map(q)` on an `Iterator`. \ @@ -1307,7 +1320,12 @@ fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ @@ -1317,7 +1335,12 @@ fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Ex } /// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ @@ -1328,7 +1351,12 @@ fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::E } /// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ @@ -1399,7 +1427,13 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. -fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { +fn lint_chars_cmp<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + info: &BinaryExprInfo, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(info.chain, chain_methods), let hir::ExprCall(ref fun, ref arg_char) = info.other.node, @@ -1446,7 +1480,13 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { +fn lint_chars_cmp_with_unwrap<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + info: &BinaryExprInfo, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(info.chain, chain_methods), let hir::ExprLit(ref lit) = info.other.node, @@ -1490,7 +1530,11 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi let parent_item = cx.tcx.hir.get_parent(arg.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if let Ok(&ty::Const { val: ConstVal::Str(r), .. }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { + if let Ok(&ty::Const { + val: ConstVal::Str(r), + .. + }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) + { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then( @@ -1498,7 +1542,9 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi SINGLE_CHAR_PATTERN, arg.span, "single-character string constant used as pattern", - |db| { db.span_suggestion(expr.span, "try using a char instead", hint); }, + |db| { + db.span_suggestion(expr.span, "try using a char instead", hint); + }, ); } } @@ -1669,27 +1715,24 @@ impl SelfKind { fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { - param.name == seg.name && - param + param.name == seg.name + && param .bounds .iter() .any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; - match_path(path, name) && - path.segments + match_path(path, name) + && path.segments .last() - .map_or(false, |s| { - if let Some(ref params) = s.parameters { - if params.parenthesized { - false - } else { - params.types.len() == 1 && - (is_self_ty(¶ms.types[0]) - || is_ty(&*params.types[0], self_ty)) - } - } else { + .map_or(false, |s| if let Some(ref params) = s.parameters { + if params.parenthesized { false + } else { + params.types.len() == 1 + && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) } + } else { + false }) } else { false diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 24adbe943e1..c13caf84b98 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -17,8 +17,11 @@ use std::sync::{self, Arc}; struct T; impl T { - fn add(self, other: T) -> T { self } - fn drop(&mut self) { } + pub fn add(self, other: T) -> T { self } + pub fn drop(&mut self) { } + + fn neg(self) -> Self { self } // no error, private function + fn eq(&self, other: T) -> bool { true } // no error, private function fn sub(&self, other: T) -> &T { self } // no error, self is a ref fn div(self) -> T { self } // no error, different #arguments diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 97e8c25ad75..9591d1f4fb4 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,471 +1,477 @@ error: unnecessary structure name repetition - --> $DIR/methods.rs:20:25 + --> $DIR/methods.rs:20:29 | -20 | fn add(self, other: T) -> T { self } - | ^ help: use the applicable keyword: `Self` +20 | pub fn add(self, other: T) -> T { self } + | ^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:20:31 + --> $DIR/methods.rs:20:35 | -20 | fn add(self, other: T) -> T { self } - | ^ help: use the applicable keyword: `Self` +20 | pub fn add(self, other: T) -> T { self } + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/methods.rs:24:25 + | +24 | fn eq(&self, other: T) -> bool { true } // no error, private function + | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:23:26 + --> $DIR/methods.rs:26:26 | -23 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:23:33 + --> $DIR/methods.rs:26:33 | -23 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:24:21 + --> $DIR/methods.rs:27:21 | -24 | fn div(self) -> T { self } // no error, different #arguments +27 | fn div(self) -> T { self } // no error, different #arguments | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:25:25 + --> $DIR/methods.rs:28:25 | -25 | fn rem(self, other: T) { } // no error, wrong return type +28 | fn rem(self, other: T) { } // no error, wrong return type | ^ help: use the applicable keyword: `Self` error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name --> $DIR/methods.rs:20:5 | -20 | fn add(self, other: T) -> T { self } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +20 | pub fn add(self, other: T) -> T { self } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D should-implement-trait` implied by `-D warnings` error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name --> $DIR/methods.rs:21:5 | -21 | fn drop(&mut self) { } - | ^^^^^^^^^^^^^^^^^^^^^^ +21 | pub fn drop(&mut self) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:28:17 + --> $DIR/methods.rs:31:17 | -28 | fn into_u16(&self) -> u16 { 0 } +31 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:30:21 + --> $DIR/methods.rs:33:21 | -30 | fn to_something(self) -> u32 { 0 } +33 | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:32:12 + --> $DIR/methods.rs:35:12 | -32 | fn new(self) {} +35 | fn new(self) {} | ^^^^ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:32:5 + --> $DIR/methods.rs:35:5 | -32 | fn new(self) {} +35 | fn new(self) {} | ^^^^^^^^^^^^^^^ | = note: `-D new-ret-no-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:76:24 + --> $DIR/methods.rs:79:24 | -76 | fn new() -> Option> { None } +79 | fn new() -> Option> { None } | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:80:19 + --> $DIR/methods.rs:83:19 | -80 | type Output = T; +83 | type Output = T; | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:81:25 + --> $DIR/methods.rs:84:25 | -81 | fn mul(self, other: T) -> T { self } // no error, obviously +84 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:81:31 + --> $DIR/methods.rs:84:31 | -81 | fn mul(self, other: T) -> T { self } // no error, obviously +84 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:100:13 + --> $DIR/methods.rs:103:13 | -100 | let _ = opt.map(|x| x + 1) +103 | let _ = opt.map(|x| x + 1) | _____________^ -101 | | -102 | | .unwrap_or(0); // should lint even though this call is on a separate line +104 | | +105 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | = note: `-D option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:104:13 + --> $DIR/methods.rs:107:13 | -104 | let _ = opt.map(|x| { +107 | let _ = opt.map(|x| { | _____________^ -105 | | x + 1 -106 | | } -107 | | ).unwrap_or(0); +108 | | x + 1 +109 | | } +110 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:108:13 + --> $DIR/methods.rs:111:13 | -108 | let _ = opt.map(|x| x + 1) +111 | let _ = opt.map(|x| x + 1) | _____________^ -109 | | .unwrap_or({ -110 | | 0 -111 | | }); +112 | | .unwrap_or({ +113 | | 0 +114 | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:113:13 + --> $DIR/methods.rs:116:13 | -113 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); +116 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:115:13 + --> $DIR/methods.rs:118:13 | -115 | let _ = opt.map(|x| { +118 | let _ = opt.map(|x| { | _____________^ -116 | | Some(x + 1) -117 | | } -118 | | ).unwrap_or(None); +119 | | Some(x + 1) +120 | | } +121 | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:119:13 + --> $DIR/methods.rs:122:13 | -119 | let _ = opt +122 | let _ = opt | _____________^ -120 | | .map(|x| Some(x + 1)) -121 | | .unwrap_or(None); +123 | | .map(|x| Some(x + 1)) +124 | | .unwrap_or(None); | |________________________^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:127:13 + --> $DIR/methods.rs:130:13 | -127 | let _ = opt.map(|x| x + 1) +130 | let _ = opt.map(|x| x + 1) | _____________^ -128 | | -129 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +131 | | +132 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:131:13 + --> $DIR/methods.rs:134:13 | -131 | let _ = opt.map(|x| { +134 | let _ = opt.map(|x| { | _____________^ -132 | | x + 1 -133 | | } -134 | | ).unwrap_or_else(|| 0); +135 | | x + 1 +136 | | } +137 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:135:13 + --> $DIR/methods.rs:138:13 | -135 | let _ = opt.map(|x| x + 1) +138 | let _ = opt.map(|x| x + 1) | _____________^ -136 | | .unwrap_or_else(|| -137 | | 0 -138 | | ); +139 | | .unwrap_or_else(|| +140 | | 0 +141 | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:144:13 + --> $DIR/methods.rs:147:13 | -144 | let _ = opt.map_or(None, |x| Some(x + 1)); +147 | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | = note: `-D option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:146:13 + --> $DIR/methods.rs:149:13 | -146 | let _ = opt.map_or(None, |x| { +149 | let _ = opt.map_or(None, |x| { | _____________^ -147 | | Some(x + 1) -148 | | } -149 | | ); +150 | | Some(x + 1) +151 | | } +152 | | ); | |_________________^ | help: try using and_then instead | -146 | let _ = opt.and_then(|x| { -147 | Some(x + 1) -148 | }); +149 | let _ = opt.and_then(|x| { +150 | Some(x + 1) +151 | }); | error: unnecessary structure name repetition - --> $DIR/methods.rs:173:24 + --> $DIR/methods.rs:176:24 | -173 | fn filter(self) -> IteratorFalsePositives { +176 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:177:22 + --> $DIR/methods.rs:180:22 | -177 | fn next(self) -> IteratorFalsePositives { +180 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:197:32 + --> $DIR/methods.rs:200:32 | -197 | fn skip(self, _: usize) -> IteratorFalsePositives { +200 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:207:13 + --> $DIR/methods.rs:210:13 | -207 | let _ = v.iter().filter(|&x| *x < 0).next(); +210 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:210:13 + --> $DIR/methods.rs:213:13 | -210 | let _ = v.iter().filter(|&x| { +213 | let _ = v.iter().filter(|&x| { | _____________^ -211 | | *x < 0 -212 | | } -213 | | ).next(); +214 | | *x < 0 +215 | | } +216 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:225:13 + --> $DIR/methods.rs:228:13 | -225 | let _ = v.iter().find(|&x| *x < 0).is_some(); +228 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:228:13 + --> $DIR/methods.rs:231:13 | -228 | let _ = v.iter().find(|&x| { +231 | let _ = v.iter().find(|&x| { | _____________^ -229 | | *x < 0 -230 | | } -231 | | ).is_some(); +232 | | *x < 0 +233 | | } +234 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:234:13 + --> $DIR/methods.rs:237:13 | -234 | let _ = v.iter().position(|&x| x < 0).is_some(); +237 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:237:13 + --> $DIR/methods.rs:240:13 | -237 | let _ = v.iter().position(|&x| { +240 | let _ = v.iter().position(|&x| { | _____________^ -238 | | x < 0 -239 | | } -240 | | ).is_some(); +241 | | x < 0 +242 | | } +243 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:243:13 + --> $DIR/methods.rs:246:13 | -243 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +246 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:246:13 + --> $DIR/methods.rs:249:13 | -246 | let _ = v.iter().rposition(|&x| { +249 | let _ = v.iter().rposition(|&x| { | _____________^ -247 | | x < 0 -248 | | } -249 | | ).is_some(); +250 | | x < 0 +251 | | } +252 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:263:21 + --> $DIR/methods.rs:266:21 | -263 | fn new() -> Foo { Foo } +266 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:281:5 + --> $DIR/methods.rs:284:5 | -281 | with_constructor.unwrap_or(make()); +284 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:284:5 + --> $DIR/methods.rs:287:5 | -284 | with_new.unwrap_or(Vec::new()); +287 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:287:5 + --> $DIR/methods.rs:290:5 | -287 | with_const_args.unwrap_or(Vec::with_capacity(12)); +290 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:290:5 + --> $DIR/methods.rs:293:5 | -290 | with_err.unwrap_or(make()); +293 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:293:5 + --> $DIR/methods.rs:296:5 | -293 | with_err_args.unwrap_or(Vec::with_capacity(12)); +296 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:296:5 + --> $DIR/methods.rs:299:5 | -296 | with_default_trait.unwrap_or(Default::default()); +299 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:299:5 + --> $DIR/methods.rs:302:5 | -299 | with_default_type.unwrap_or(u64::default()); +302 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:302:5 + --> $DIR/methods.rs:305:5 | -302 | with_vec.unwrap_or(vec![]); +305 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:5 + --> $DIR/methods.rs:310:5 | -307 | without_default.unwrap_or(Foo::new()); +310 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:310:5 + --> $DIR/methods.rs:313:5 | -310 | map.entry(42).or_insert(String::new()); +313 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:313:5 + --> $DIR/methods.rs:316:5 | -313 | btree.entry(42).or_insert(String::new()); +316 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:13 + --> $DIR/methods.rs:319:13 | -316 | let _ = stringy.unwrap_or("".to_owned()); +319 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:327:23 + --> $DIR/methods.rs:330:23 | -327 | let bad_vec = some_vec.iter().nth(3); +330 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:328:26 + --> $DIR/methods.rs:331:26 | -328 | let bad_slice = &some_vec[..].iter().nth(3); +331 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:329:31 + --> $DIR/methods.rs:332:31 | -329 | let bad_boxed_slice = boxed_slice.iter().nth(3); +332 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:330:29 + --> $DIR/methods.rs:333:29 | -330 | let bad_vec_deque = some_vec_deque.iter().nth(3); +333 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:335:23 + --> $DIR/methods.rs:338:23 | -335 | let bad_vec = some_vec.iter_mut().nth(3); +338 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:338:26 + --> $DIR/methods.rs:341:26 | -338 | let bad_slice = &some_vec[..].iter_mut().nth(3); +341 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:341:29 + --> $DIR/methods.rs:344:29 | -341 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +344 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:353:13 + --> $DIR/methods.rs:356:13 | -353 | let _ = some_vec.iter().skip(42).next(); +356 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:354:13 + --> $DIR/methods.rs:357:13 | -354 | let _ = some_vec.iter().cycle().skip(42).next(); +357 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:355:13 + --> $DIR/methods.rs:358:13 | -355 | let _ = (1..10).skip(10).next(); +358 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:356:14 + --> $DIR/methods.rs:359:14 | -356 | let _ = &some_vec[..].iter().skip(3).next(); +359 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:365:13 + --> $DIR/methods.rs:368:13 | -365 | let _ = opt.unwrap(); +368 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From bfa7a9b138b82b69ff170dd76522adc43465ccb1 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Sat, 21 Oct 2017 13:42:35 -0400 Subject: Add tests for generic code --- tests/ui/useless_asref.rs | 24 ++++++++++++++++++++++ tests/ui/useless_asref.stderr | 48 +++++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index ef0174ad71f..8599d67c767 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,5 +1,7 @@ #![deny(useless_asref)] +use std::fmt::Debug; + struct FakeAsRef; #[allow(should_implement_trait)] @@ -54,6 +56,9 @@ fn not_ok() { foo_rslice(mrrrrrslice); } foo_rrrrmr((&&&&MoreRef).as_ref()); + + generic_not_ok(mrslice); + generic_ok(mrslice); } fn ok() { @@ -87,7 +92,26 @@ fn ok() { } FakeAsRef.as_ref(); foo_rrrrmr(MoreRef.as_ref()); + + generic_not_ok(arr.as_mut()); + generic_ok(&mut arr); } + +fn foo_mrt(t: &mut T) { println!("{:?}", t); } +fn foo_rt(t: &T) { println!("{:?}", t); } + +fn generic_not_ok + AsRef + Debug + ?Sized>(mrt: &mut T) { + foo_mrt(mrt.as_mut()); + foo_mrt(mrt); + foo_rt(mrt.as_ref()); + foo_rt(mrt); +} + +fn generic_ok + AsRef + ?Sized, T: Debug + ?Sized>(mru: &mut U) { + foo_mrt(mru.as_mut()); + foo_rt(mru.as_ref()); +} + fn main() { not_ok(); ok(); diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 8cc869ad775..4b6af9b877e 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,7 +1,7 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:29:18 + --> $DIR/useless_asref.rs:31:18 | -29 | foo_rstr(rstr.as_ref()); +31 | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here @@ -11,50 +11,62 @@ note: lint level defined here | ^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:31:20 + --> $DIR/useless_asref.rs:33:20 | -31 | foo_rslice(rslice.as_ref()); +33 | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:35:21 + --> $DIR/useless_asref.rs:37:21 | -35 | foo_mrslice(mrslice.as_mut()); +37 | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:37:20 + --> $DIR/useless_asref.rs:39:20 | -37 | foo_rslice(mrslice.as_ref()); +39 | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:44:20 + --> $DIR/useless_asref.rs:46:20 | -44 | foo_rslice(rrrrrslice.as_ref()); +46 | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:46:18 + --> $DIR/useless_asref.rs:48:18 | -46 | foo_rstr(rrrrrstr.as_ref()); +48 | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:51:21 + --> $DIR/useless_asref.rs:53:21 | -51 | foo_mrslice(mrrrrrslice.as_mut()); +53 | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:53:20 + --> $DIR/useless_asref.rs:55:20 | -53 | foo_rslice(mrrrrrslice.as_ref()); +55 | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:56:16 + --> $DIR/useless_asref.rs:58:16 | -56 | foo_rrrrmr((&&&&MoreRef).as_ref()); +58 | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` +error: this call to `as_mut` does nothing + --> $DIR/useless_asref.rs:104:13 + | +104 | foo_mrt(mrt.as_mut()); + | ^^^^^^^^^^^^ help: try this: `mrt` + +error: this call to `as_ref` does nothing + --> $DIR/useless_asref.rs:106:12 + | +106 | foo_rt(mrt.as_ref()); + | ^^^^^^^^^^^^ help: try this: `mrt` + -- cgit 1.4.1-3-g733a5 From 0b0eb8ead6604df3dc43529ffab4880c1d35fc2d Mon Sep 17 00:00:00 2001 From: cgm616 Date: Sun, 22 Oct 2017 09:59:19 -0400 Subject: Undo rustfmt changes unrelated to issue --- clippy_lints/src/methods.rs | 122 +++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 81 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 54523841b09..6a68ee961f0 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -335,8 +335,7 @@ declare_lint! { /// the corresponding trait instead. /// /// **Why is this bad?**: Calling '.clone()' on an Rc, Arc, or Weak -/// can obscure the fact that only the pointer is being cloned, not the -/// underlying +/// can obscure the fact that only the pointer is being cloned, not the underlying /// data. /// /// **Example:** @@ -945,8 +944,12 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { expr.span, "using '.clone()' on a ref-counted pointer", "try this", - format!("{}::clone(&{})", caller_type, snippet(cx, arg.span, "_")), + format!("{}::clone(&{})", + caller_type, + snippet(cx, arg.span, "_") + ) ); + } @@ -1004,8 +1007,8 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr } fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) - && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() + if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) && + derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { span_lint( cx, @@ -1180,16 +1183,8 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { - "None" - } else { - "a" - }; - let suggest = if unwrap_snippet == "None" { - "and_then(f)" - } else { - "map_or(a, f)" - }; + let arg = if unwrap_snippet == "None" { "None" } else { "a" }; + let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { "map_or(a, f)" }; let msg = &format!( "called `map(f).unwrap_or({})` on an Option value. \ This can be done more directly by calling `{}` instead", @@ -1220,12 +1215,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] } /// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - map_args: &'tcx [hir::Expr], - unwrap_args: &'tcx [hir::Expr], -) { +fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr], unwrap_args: &'tcx [hir::Expr]) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { // lint message @@ -1259,6 +1249,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( /// lint use of `_.map_or(None, _)` for `Option`s fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { + if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { // check if the first non-self argument to map_or() is None let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { @@ -1274,9 +1265,13 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); - span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { - db.span_suggestion(expr.span, "try using and_then instead", hint); - }); + span_lint_and_then( + cx, + OPTION_MAP_OR_NONE, + expr.span, + msg, + |db| { db.span_suggestion(expr.span, "try using and_then instead", hint); }, + ); } } } @@ -1305,12 +1300,7 @@ fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { +fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).map(q)` on an `Iterator`. \ @@ -1320,12 +1310,7 @@ fn lint_filter_map<'a, 'tcx>( } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { +fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ @@ -1335,12 +1320,7 @@ fn lint_filter_map_map<'a, 'tcx>( } /// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { +fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ @@ -1351,12 +1331,7 @@ fn lint_filter_flat_map<'a, 'tcx>( } /// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { +fn lint_filter_map_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ @@ -1427,13 +1402,7 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. -fn lint_chars_cmp<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - info: &BinaryExprInfo, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { +fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(info.chain, chain_methods), let hir::ExprCall(ref fun, ref arg_char) = info.other.node, @@ -1480,13 +1449,7 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - info: &BinaryExprInfo, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { +fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { if_let_chain! {[ let Some(args) = method_chain_args(info.chain, chain_methods), let hir::ExprLit(ref lit) = info.other.node, @@ -1530,11 +1493,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi let parent_item = cx.tcx.hir.get_parent(arg.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if let Ok(&ty::Const { - val: ConstVal::Str(r), - .. - }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) - { + if let Ok(&ty::Const { val: ConstVal::Str(r), .. }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then( @@ -1542,9 +1501,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi SINGLE_CHAR_PATTERN, arg.span, "single-character string constant used as pattern", - |db| { - db.span_suggestion(expr.span, "try using a char instead", hint); - }, + |db| { db.span_suggestion(expr.span, "try using a char instead", hint); }, ); } } @@ -1715,24 +1672,27 @@ impl SelfKind { fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { - param.name == seg.name - && param + param.name == seg.name && + param .bounds .iter() .any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; - match_path(path, name) - && path.segments + match_path(path, name) && + path.segments .last() - .map_or(false, |s| if let Some(ref params) = s.parameters { - if params.parenthesized { - false + .map_or(false, |s| { + if let Some(ref params) = s.parameters { + if params.parenthesized { + false + } else { + params.types.len() == 1 && + (is_self_ty(¶ms.types[0]) + || is_ty(&*params.types[0], self_ty)) + } } else { - params.types.len() == 1 - && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) + false } - } else { - false }) } else { false -- cgit 1.4.1-3-g733a5 From 41840ae3c41483745ff92f3ba8e99f9ffcb3dff8 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 23 Oct 2017 15:18:02 -0400 Subject: mechanically swap if_let_chain -> if_chain --- clippy_lints/src/attrs.rs | 15 +- clippy_lints/src/bit_mask.rs | 43 ++--- clippy_lints/src/bytecount.rs | 98 ++++++----- clippy_lints/src/collapsible_if.rs | 64 +++---- clippy_lints/src/derive.rs | 75 ++++---- clippy_lints/src/drop_forget_ref.rs | 87 +++++----- clippy_lints/src/entry.rs | 90 +++++----- clippy_lints/src/eval_order_dependence.rs | 33 ++-- clippy_lints/src/explicit_write.rs | 107 ++++++------ clippy_lints/src/fallible_impl_from.rs | 91 +++++----- clippy_lints/src/format.rs | 79 +++++---- clippy_lints/src/invalid_ref.rs | 33 ++-- clippy_lints/src/let_if_seq.rs | 181 +++++++++---------- clippy_lints/src/literal_digit_grouping.rs | 102 +++++------ clippy_lints/src/loops.rs | 231 +++++++++++++------------ clippy_lints/src/map_clone.rs | 55 +++--- clippy_lints/src/matches.rs | 69 ++++---- clippy_lints/src/methods.rs | 227 ++++++++++++------------ clippy_lints/src/misc.rs | 121 ++++++------- clippy_lints/src/misc_early.rs | 163 ++++++++--------- clippy_lints/src/needless_borrow.rs | 37 ++-- clippy_lints/src/needless_borrowed_ref.rs | 23 +-- clippy_lints/src/needless_pass_by_value.rs | 226 ++++++++++++------------ clippy_lints/src/neg_multiply.rs | 25 +-- clippy_lints/src/new_without_default.rs | 67 +++---- clippy_lints/src/ok_if_let.rs | 31 ++-- clippy_lints/src/overflow_check_conditional.rs | 82 ++++----- clippy_lints/src/panic.rs | 37 ++-- clippy_lints/src/partialeq_ne_impl.rs | 27 +-- clippy_lints/src/print.rs | 149 ++++++++-------- clippy_lints/src/ptr.rs | 15 +- clippy_lints/src/ranges.rs | 109 ++++++------ clippy_lints/src/regex.rs | 81 ++++----- clippy_lints/src/returns.rs | 43 ++--- clippy_lints/src/swap.rs | 198 ++++++++++----------- clippy_lints/src/transmute.rs | 17 +- clippy_lints/src/types.rs | 180 +++++++++---------- clippy_lints/src/use_self.rs | 35 ++-- clippy_lints/src/utils/higher.rs | 105 +++++------ clippy_lints/src/utils/mod.rs | 55 +++--- clippy_lints/src/vec.rs | 36 ++-- clippy_lints/src/zero_div_zero.rs | 39 +++-- 42 files changed, 1837 insertions(+), 1744 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 83ec32615d1..8baff551910 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -94,13 +94,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { return; } for item in items { - if_let_chain! {[ - let NestedMetaItemKind::MetaItem(ref mi) = item.node, - let MetaItemKind::NameValue(ref lit) = mi.node, - mi.name() == "since", - ], { - check_semver(cx, item.span, lit); - }} + if_chain! { + if let NestedMetaItemKind::MetaItem(ref mi) = item.node; + if let MetaItemKind::NameValue(ref lit) = mi.node; + if mi.name() == "since"; + then { + check_semver(cx, item.span, lit); + } + } } } } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 6372221fd44..f0ff27d4d63 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -119,27 +119,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { } } } - if_let_chain!{[ - let Expr_::ExprBinary(ref op, ref left, ref right) = e.node, - BinOp_::BiEq == op.node, - let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node, - BinOp_::BiBitAnd == op1.node, - let Expr_::ExprLit(ref lit) = right1.node, - let LitKind::Int(n, _) = lit.node, - let Expr_::ExprLit(ref lit1) = right.node, - let LitKind::Int(0, _) = lit1.node, - n.leading_zeros() == n.count_zeros(), - n > u128::from(self.verbose_bit_mask_threshold), - ], { - span_lint_and_then(cx, - VERBOSE_BIT_MASK, - e.span, - "bit mask could be simplified with a call to `trailing_zeros`", - |db| { - let sugg = Sugg::hir(cx, left1, "...").maybe_par(); - db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones())); - }); - }} + if_chain! { + if let Expr_::ExprBinary(ref op, ref left, ref right) = e.node; + if BinOp_::BiEq == op.node; + if let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node; + if BinOp_::BiBitAnd == op1.node; + if let Expr_::ExprLit(ref lit) = right1.node; + if let LitKind::Int(n, _) = lit.node; + if let Expr_::ExprLit(ref lit1) = right.node; + if let LitKind::Int(0, _) = lit1.node; + if n.leading_zeros() == n.count_zeros(); + if n > u128::from(self.verbose_bit_mask_threshold); + then { + span_lint_and_then(cx, + VERBOSE_BIT_MASK, + e.span, + "bit mask could be simplified with a call to `trailing_zeros`", + |db| { + let sugg = Sugg::hir(cx, left1, "...").maybe_par(); + db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones())); + }); + } + } } } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 58f1227d91e..e0ce4bbc93b 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -37,56 +37,58 @@ impl LintPass for ByteCount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if_let_chain!([ - let ExprMethodCall(ref count, _, ref count_args) = expr.node, - count.name == "count", - count_args.len() == 1, - let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node, - filter.name == "filter", - filter_args.len() == 2, - let ExprClosure(_, _, body_id, _, _) = filter_args[1].node, - ], { - let body = cx.tcx.hir.body(body_id); - if_let_chain!([ - body.arguments.len() == 1, - let Some(argname) = get_pat_name(&body.arguments[0].pat), - let ExprBinary(ref op, ref l, ref r) = body.value.node, - op.node == BiEq, - match_type(cx, - walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), - &paths::SLICE_ITER), - ], { - let needle = match get_path_name(l) { - Some(name) if check_arg(name, argname, r) => r, - _ => match get_path_name(r) { - Some(name) if check_arg(name, argname, l) => l, - _ => { return; } + if_chain! { + if let ExprMethodCall(ref count, _, ref count_args) = expr.node; + if count.name == "count"; + if count_args.len() == 1; + if let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node; + if filter.name == "filter"; + if filter_args.len() == 2; + if let ExprClosure(_, _, body_id, _, _) = filter_args[1].node; + then { + let body = cx.tcx.hir.body(body_id); + if_chain! { + if body.arguments.len() == 1; + if let Some(argname) = get_pat_name(&body.arguments[0].pat); + if let ExprBinary(ref op, ref l, ref r) = body.value.node; + if op.node == BiEq; + if match_type(cx, + walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), + &paths::SLICE_ITER); + then { + let needle = match get_path_name(l) { + Some(name) if check_arg(name, argname, r) => r, + _ => match get_path_name(r) { + Some(name) if check_arg(name, argname, l) => l, + _ => { return; } + } + }; + if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { + return; + } + let haystack = if let ExprMethodCall(ref path, _, ref args) = + filter_args[0].node { + let p = path.name; + if (p == "iter" || p == "iter_mut") && args.len() == 1 { + &args[0] + } else { + &filter_args[0] + } + } else { + &filter_args[0] + }; + span_lint_and_sugg(cx, + NAIVE_BYTECOUNT, + expr.span, + "You appear to be counting bytes the naive way", + "Consider using the bytecount crate", + format!("bytecount::count({}, {})", + snippet(cx, haystack.span, ".."), + snippet(cx, needle.span, ".."))); } }; - if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { - return; - } - let haystack = if let ExprMethodCall(ref path, _, ref args) = - filter_args[0].node { - let p = path.name; - if (p == "iter" || p == "iter_mut") && args.len() == 1 { - &args[0] - } else { - &filter_args[0] - } - } else { - &filter_args[0] - }; - span_lint_and_sugg(cx, - NAIVE_BYTECOUNT, - expr.span, - "You appear to be counting bytes the naive way", - "Consider using the bytecount crate", - format!("bytecount::count({}, {})", - snippet(cx, haystack.span, ".."), - snippet(cx, needle.span, ".."))); - }); - }); + } + }; } } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index fb0ff23cc63..3ac19980a6d 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -100,43 +100,45 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) { } fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { - if_let_chain! {[ - let ast::ExprKind::Block(ref block) = else_.node, - let Some(else_) = expr_block(block), - !in_macro(else_.span), - ], { - match else_.node { - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { - span_lint_and_sugg(cx, - COLLAPSIBLE_IF, - block.span, - "this `else { if .. }` block can be collapsed", - "try", - snippet_block(cx, else_.span, "..").into_owned()); + if_chain! { + if let ast::ExprKind::Block(ref block) = else_.node; + if let Some(else_) = expr_block(block); + if !in_macro(else_.span); + then { + match else_.node { + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { + span_lint_and_sugg(cx, + COLLAPSIBLE_IF, + block.span, + "this `else { if .. }` block can be collapsed", + "try", + snippet_block(cx, else_.span, "..").into_owned()); + } + _ => (), } - _ => (), } - }} + } } fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { - if_let_chain! {[ - let Some(inner) = expr_block(then), - let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node, - ], { - if expr.span.ctxt() != inner.span.ctxt() { - return; + if_chain! { + if let Some(inner) = expr_block(then); + if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node; + then { + if expr.span.ctxt() != inner.span.ctxt() { + return; + } + span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { + let lhs = Sugg::ast(cx, check, ".."); + let rhs = Sugg::ast(cx, check_inner, ".."); + db.span_suggestion(expr.span, + "try", + format!("if {} {}", + lhs.and(rhs), + snippet_block(cx, content.span, ".."))); + }); } - span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { - let lhs = Sugg::ast(cx, check, ".."); - let rhs = Sugg::ast(cx, check_inner, ".."); - db.span_suggestion(expr.span, - "try", - format!("if {} {}", - lhs.and(rhs), - snippet_block(cx, content.span, ".."))); - }); - }} + } } /// If the block contains only one expression, return it. diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index a891d7721c3..2c45aaf6ac9 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -91,43 +91,44 @@ fn check_hash_peq<'a, 'tcx>( ty: Ty<'tcx>, hash_is_automatically_derived: bool, ) { - if_let_chain! {[ - match_path(&trait_ref.path, &paths::HASH), - let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait() - ], { - // Look for the PartialEq implementations for `ty` - cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); - - if peq_is_automatically_derived == hash_is_automatically_derived { - return; - } - - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - - // Only care about `impl PartialEq for Foo` - // For `impl PartialEq for A, input_types is [A, B] - if trait_ref.substs.type_at(1) == ty { - let mess = if peq_is_automatically_derived { - "you are implementing `Hash` explicitly but have derived `PartialEq`" - } else { - "you are deriving `Hash` but have implemented `PartialEq` explicitly" - }; - - span_lint_and_then( - cx, DERIVE_HASH_XOR_EQ, span, - mess, - |db| { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(impl_id) { - db.span_note( - cx.tcx.hir.span(node_id), - "`PartialEq` implemented here" - ); - } - }); - } - }); - }} + if_chain! { + if match_path(&trait_ref.path, &paths::HASH); + if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait(); + then { + // Look for the PartialEq implementations for `ty` + cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { + let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + + if peq_is_automatically_derived == hash_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialEq for Foo` + // For `impl PartialEq for A, input_types is [A, B] + if trait_ref.substs.type_at(1) == ty { + let mess = if peq_is_automatically_derived { + "you are implementing `Hash` explicitly but have derived `PartialEq`" + } else { + "you are deriving `Hash` but have implemented `PartialEq` explicitly" + }; + + span_lint_and_then( + cx, DERIVE_HASH_XOR_EQ, span, + mess, + |db| { + if let Some(node_id) = cx.tcx.hir.as_local_node_id(impl_id) { + db.span_note( + cx.tcx.hir.span(node_id), + "`PartialEq` implemented here" + ); + } + }); + } + }); + } + } } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 46b228e70ab..1601c276e2b 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -115,50 +115,51 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain!{[ - let ExprCall(ref path, ref args) = expr.node, - let ExprPath(ref qpath) = path.node, - args.len() == 1, - let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)), - ], { - let lint; - let msg; - let arg = &args[0]; - let arg_ty = cx.tables.expr_ty(arg); - - if let ty::TyRef(..) = arg_ty.sty { - if match_def_path(cx.tcx, def_id, &paths::DROP) { - lint = DROP_REF; - msg = DROP_REF_SUMMARY.to_string(); - } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { - lint = FORGET_REF; - msg = FORGET_REF_SUMMARY.to_string(); - } else { - return; - } - span_note_and_lint(cx, - lint, - expr.span, - &msg, - arg.span, - &format!("argument has type {}", arg_ty)); - } else if is_copy(cx, arg_ty) { - if match_def_path(cx.tcx, def_id, &paths::DROP) { - lint = DROP_COPY; - msg = DROP_COPY_SUMMARY.to_string(); - } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { - lint = FORGET_COPY; - msg = FORGET_COPY_SUMMARY.to_string(); - } else { - return; + if_chain! { + if let ExprCall(ref path, ref args) = expr.node; + if let ExprPath(ref qpath) = path.node; + if args.len() == 1; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); + then { + let lint; + let msg; + let arg = &args[0]; + let arg_ty = cx.tables.expr_ty(arg); + + if let ty::TyRef(..) = arg_ty.sty { + if match_def_path(cx.tcx, def_id, &paths::DROP) { + lint = DROP_REF; + msg = DROP_REF_SUMMARY.to_string(); + } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + lint = FORGET_REF; + msg = FORGET_REF_SUMMARY.to_string(); + } else { + return; + } + span_note_and_lint(cx, + lint, + expr.span, + &msg, + arg.span, + &format!("argument has type {}", arg_ty)); + } else if is_copy(cx, arg_ty) { + if match_def_path(cx.tcx, def_id, &paths::DROP) { + lint = DROP_COPY; + msg = DROP_COPY_SUMMARY.to_string(); + } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + lint = FORGET_COPY; + msg = FORGET_COPY_SUMMARY.to_string(); + } else { + return; + } + span_note_and_lint(cx, + lint, + expr.span, + &msg, + arg.span, + &format!("argument has type {}", arg_ty)); } - span_note_and_lint(cx, - lint, - expr.span, - &msg, - arg.span, - &format!("argument has type {}", arg_ty)); } - }} + } } } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index a3558a189e2..6c7a5fec03c 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -87,25 +87,26 @@ fn check_cond<'a, 'tcx, 'b>( cx: &'a LateContext<'a, 'tcx>, check: &'b Expr, ) -> Option<(&'static str, &'b Expr, &'b Expr)> { - if_let_chain! {[ - let ExprMethodCall(ref path, _, ref params) = check.node, - params.len() >= 2, - path.name == "contains_key", - let ExprAddrOf(_, ref key) = params[1].node - ], { - let map = ¶ms[0]; - let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map)); - - return if match_type(cx, obj_ty, &paths::BTREEMAP) { - Some(("BTreeMap", map, key)) - } - else if match_type(cx, obj_ty, &paths::HASHMAP) { - Some(("HashMap", map, key)) + if_chain! { + if let ExprMethodCall(ref path, _, ref params) = check.node; + if params.len() >= 2; + if path.name == "contains_key"; + if let ExprAddrOf(_, ref key) = params[1].node; + then { + let map = ¶ms[0]; + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map)); + + return if match_type(cx, obj_ty, &paths::BTREEMAP) { + Some(("BTreeMap", map, key)) + } + else if match_type(cx, obj_ty, &paths::HASHMAP) { + Some(("HashMap", map, key)) + } + else { + None + }; } - else { - None - }; - }} + } None } @@ -121,32 +122,33 @@ struct InsertVisitor<'a, 'tcx: 'a, 'b> { impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if_let_chain! {[ - let ExprMethodCall(ref path, _, ref params) = expr.node, - params.len() == 3, - path.name == "insert", - get_item_name(self.cx, self.map) == get_item_name(self.cx, ¶ms[0]), - SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]) - ], { - span_lint_and_then(self.cx, MAP_ENTRY, self.span, - &format!("usage of `contains_key` followed by `insert` on a `{}`", self.ty), |db| { - if self.sole_expr { - let help = format!("{}.entry({}).or_insert({})", - snippet(self.cx, self.map.span, "map"), - snippet(self.cx, params[1].span, ".."), - snippet(self.cx, params[2].span, "..")); - - db.span_suggestion(self.span, "consider using", help); - } - else { - let help = format!("{}.entry({})", - snippet(self.cx, self.map.span, "map"), - snippet(self.cx, params[1].span, "..")); - - db.span_suggestion(self.span, "consider using", help); - } - }); - }} + if_chain! { + if let ExprMethodCall(ref path, _, ref params) = expr.node; + if params.len() == 3; + if path.name == "insert"; + if get_item_name(self.cx, self.map) == get_item_name(self.cx, ¶ms[0]); + if SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]); + then { + span_lint_and_then(self.cx, MAP_ENTRY, self.span, + &format!("usage of `contains_key` followed by `insert` on a `{}`", self.ty), |db| { + if self.sole_expr { + let help = format!("{}.entry({}).or_insert({})", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, ".."), + snippet(self.cx, params[2].span, "..")); + + db.span_suggestion(self.span, "consider using", help); + } + else { + let help = format!("{}.entry({})", + snippet(self.cx, self.map.span, "map"), + snippet(self.cx, params[1].span, "..")); + + db.span_suggestion(self.span, "consider using", help); + } + }); + } + } if !self.sole_expr { walk_expr(self, expr); diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 42af597125d..847aec41500 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -298,23 +298,24 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { match expr.node { ExprPath(ref qpath) => { - if_let_chain! {[ - let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, - let def::Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), - local_id == self.var, + if_chain! { + if let QPath::Resolved(None, ref path) = *qpath; + if path.segments.len() == 1; + if let def::Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); + if local_id == self.var; // Check that this is a read, not a write. - !is_in_assignment_position(self.cx, expr), - ], { - span_note_and_lint( - self.cx, - EVAL_ORDER_DEPENDENCE, - expr.span, - "unsequenced read of a variable", - self.write_expr.span, - "whether read occurs before this write depends on evaluation order" - ); - }} + if !is_in_assignment_position(self.cx, expr); + then { + span_note_and_lint( + self.cx, + EVAL_ORDER_DEPENDENCE, + expr.span, + "unsequenced read of a variable", + self.write_expr.span, + "whether read occurs before this write depends on evaluation order" + ); + } + } } // We're about to descend a closure. Since we don't know when (or // if) the closure will be evaluated, any reads in it might not diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 9650dd0909c..7ea96cabfac 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -33,69 +33,70 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ + if_chain! { // match call to unwrap - let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node, - unwrap_fun.name == "unwrap", + if let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node; + if unwrap_fun.name == "unwrap"; // match call to write_fmt - unwrap_args.len() > 0, - let ExprMethodCall(ref write_fun, _, ref write_args) = - unwrap_args[0].node, - write_fun.name == "write_fmt", + if unwrap_args.len() > 0; + if let ExprMethodCall(ref write_fun, _, ref write_args) = + unwrap_args[0].node; + if write_fun.name == "write_fmt"; // match calls to std::io::stdout() / std::io::stderr () - write_args.len() > 0, - let ExprCall(ref dest_fun, _) = write_args[0].node, - let ExprPath(ref qpath) = dest_fun.node, - let Some(dest_fun_id) = - opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)), - let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { + if write_args.len() > 0; + if let ExprCall(ref dest_fun, _) = write_args[0].node; + if let ExprPath(ref qpath) = dest_fun.node; + if let Some(dest_fun_id) = + opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)); + if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { Some("stdout") } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) { Some("stderr") } else { None - }, - ], { - let write_span = unwrap_args[0].span; - let calling_macro = - // ordering is important here, since `writeln!` uses `write!` internally - if is_expn_of(write_span, "writeln").is_some() { - Some("writeln") - } else if is_expn_of(write_span, "write").is_some() { - Some("write") + }; + then { + let write_span = unwrap_args[0].span; + let calling_macro = + // ordering is important here, since `writeln!` uses `write!` internally + if is_expn_of(write_span, "writeln").is_some() { + Some("writeln") + } else if is_expn_of(write_span, "write").is_some() { + Some("write") + } else { + None + }; + let prefix = if dest_name == "stderr" { + "e" } else { - None + "" }; - let prefix = if dest_name == "stderr" { - "e" - } else { - "" - }; - if let Some(macro_name) = calling_macro { - span_lint( - cx, - EXPLICIT_WRITE, - expr.span, - &format!( - "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", - macro_name, - dest_name, - prefix, - macro_name.replace("write", "print") - ) - ); - } else { - span_lint( - cx, - EXPLICIT_WRITE, - expr.span, - &format!( - "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", - dest_name, - prefix, - ) - ); + if let Some(macro_name) = calling_macro { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", + macro_name, + dest_name, + prefix, + macro_name.replace("write", "print") + ) + ); + } else { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", + dest_name, + prefix, + ) + ); + } } - }} + } } } diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index bdcda99124c..e6efd41e6fb 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -37,13 +37,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { // check for `impl From for ..` let impl_def_id = cx.tcx.hir.local_def_id(item.id); - if_let_chain!{[ - let hir::ItemImpl(.., ref impl_items) = item.node, - let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id), - match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT), - ], { - lint_impl_body(cx, item.span, impl_items); - }} + if_chain! { + if let hir::ItemImpl(.., ref impl_items) = item.node; + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); + if match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT); + then { + lint_impl_body(cx, item.span, impl_items); + } + } } } @@ -60,14 +61,15 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it impl<'a, 'tcx: 'a> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { // check for `begin_panic` - if_let_chain!{[ - let ExprCall(ref func_expr, _) = expr.node, - let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node, - match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || - match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT), - ], { - self.result.push(expr.span); - }} + if_chain! { + if let ExprCall(ref func_expr, _) = expr.node; + if let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node; + if match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || + match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT); + then { + self.result.push(expr.span); + } + } // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { @@ -89,36 +91,37 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it } for impl_item in impl_items { - if_let_chain!{[ - impl_item.name == "from", - let ImplItemKind::Method(_, body_id) = - cx.tcx.hir.impl_item(impl_item.id).node, - ], { - // check the body for `begin_panic` or `unwrap` - let body = cx.tcx.hir.body(body_id); - let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); - let mut fpu = FindPanicUnwrap { - tcx: cx.tcx, - tables: cx.tcx.typeck_tables_of(impl_item_def_id), - result: Vec::new(), - }; - fpu.visit_expr(&body.value); - - // if we've found one, lint - if !fpu.result.is_empty() { - span_lint_and_then( - cx, - FALLIBLE_IMPL_FROM, - impl_span, - "consider implementing `TryFrom` instead", - move |db| { - db.help( - "`From` is intended for infallible conversions only. \ - Use `TryFrom` if there's a possibility for the conversion to fail."); - db.span_note(fpu.result, "potential failure(s)"); - }); + if_chain! { + if impl_item.name == "from"; + if let ImplItemKind::Method(_, body_id) = + cx.tcx.hir.impl_item(impl_item.id).node; + then { + // check the body for `begin_panic` or `unwrap` + let body = cx.tcx.hir.body(body_id); + let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); + let mut fpu = FindPanicUnwrap { + tcx: cx.tcx, + tables: cx.tcx.typeck_tables_of(impl_item_def_id), + result: Vec::new(), + }; + fpu.visit_expr(&body.value); + + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + FALLIBLE_IMPL_FROM, + impl_span, + "consider implementing `TryFrom` instead", + move |db| { + db.help( + "`From` is intended for infallible conversions only. \ + Use `TryFrom` if there's a possibility for the conversion to fail."); + db.span_note(fpu.result, "potential failure(s)"); + }); + } } - }} + } } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 6a6cbadb6fa..8004dc17083 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -42,19 +42,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { // `format!("{}", foo)` expansion ExprCall(ref fun, ref args) => { - if_let_chain!{[ - let ExprPath(ref qpath) = fun.node, - args.len() == 2, - let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), - match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1), + if_chain! { + if let ExprPath(ref qpath) = fun.node; + if args.len() == 2; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1); // ensure the format string is `"{..}"` with only one argument and no text - check_static_str(&args[0]), + if check_static_str(&args[0]); // ensure the format argument is `{}` ie. Display with no fancy option // and that the argument is a string - check_arg_is_display(cx, &args[1]) - ], { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); - }} + if check_arg_is_display(cx, &args[1]); + then { + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); + } + } }, // `format!("foo")` expansion contains `match () { () => [], }` ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node { @@ -70,15 +71,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { /// Checks if the expressions matches `&[""]` fn check_static_str(expr: &Expr) -> bool { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, // &[""] - let ExprArray(ref exprs) = expr.node, // [""] - exprs.len() == 1, - let ExprLit(ref lit) = exprs[0].node, - let LitKind::Str(ref lit, _) = lit.node, - ], { - return lit.as_str().is_empty(); - }} + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; // &[""] + if let ExprArray(ref exprs) = expr.node; // [""] + if exprs.len() == 1; + if let ExprLit(ref lit) = exprs[0].node; + if let LitKind::Str(ref lit, _) = lit.node; + then { + return lit.as_str().is_empty(); + } + } false } @@ -91,25 +93,26 @@ fn check_static_str(expr: &Expr) -> bool { /// } /// ``` fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, - let ExprMatch(_, ref arms, _) = expr.node, - arms.len() == 1, - arms[0].pats.len() == 1, - let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node, - pat.len() == 1, - let ExprArray(ref exprs) = arms[0].body.node, - exprs.len() == 1, - let ExprCall(_, ref args) = exprs[0].node, - args.len() == 2, - let ExprPath(ref qpath) = args[1].node, - let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id)), - match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD), - ], { - let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); - - return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING); - }} + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; + if let ExprMatch(_, ref arms, _) = expr.node; + if arms.len() == 1; + if arms[0].pats.len() == 1; + if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node; + if pat.len() == 1; + if let ExprArray(ref exprs) = arms[0].body.node; + if exprs.len() == 1; + if let ExprCall(_, ref args) = exprs[0].node; + if args.len() == 2; + if let ExprPath(ref qpath) = args[1].node; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); + then { + let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); + + return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING); + } + } false } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index ad3398cb078..649e1f7ac78 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -34,22 +34,23 @@ impl LintPass for InvalidRef { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain!{[ - let ExprCall(ref path, ref args) = expr.node, - let ExprPath(ref qpath) = path.node, - args.len() == 0, - let ty::TyRef(..) = cx.tables.expr_ty(expr).sty, - let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)), - ], { - let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { - ZERO_REF_SUMMARY - } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | match_def_path(cx.tcx, def_id, &paths::UNINIT) { - UNINIT_REF_SUMMARY - } else { - return; - }; - span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP); - }} + if_chain! { + if let ExprCall(ref path, ref args) = expr.node; + if let ExprPath(ref qpath) = path.node; + if args.len() == 0; + if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); + then { + let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { + ZERO_REF_SUMMARY + } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | match_def_path(cx.tcx, def_id, &paths::UNINIT) { + UNINIT_REF_SUMMARY + } else { + return; + }; + span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP); + } + } return; } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 789dee6b05d..931b872e036 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -63,69 +63,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { - if_let_chain! {[ - let Some(expr) = it.peek(), - let hir::StmtDecl(ref decl, _) = stmt.node, - let hir::DeclLocal(ref decl) = decl.node, - let hir::PatKind::Binding(mode, canonical_id, ref name, None) = decl.pat.node, - let hir::StmtExpr(ref if_, _) = expr.node, - let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, - !used_in_expr(cx, canonical_id, cond), - let hir::ExprBlock(ref then) = then.node, - let Some(value) = check_assign(cx, canonical_id, &*then), - !used_in_expr(cx, canonical_id, value), - ], { - let span = stmt.span.to(if_.span); - - let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { - if let hir::ExprBlock(ref else_) = else_.node { - if let Some(default) = check_assign(cx, canonical_id, else_) { - (else_.stmts.len() > 1, default) - } else if let Some(ref default) = decl.init { - (true, &**default) + if_chain! { + if let Some(expr) = it.peek(); + if let hir::StmtDecl(ref decl, _) = stmt.node; + if let hir::DeclLocal(ref decl) = decl.node; + if let hir::PatKind::Binding(mode, canonical_id, ref name, None) = decl.pat.node; + if let hir::StmtExpr(ref if_, _) = expr.node; + if let hir::ExprIf(ref cond, ref then, ref else_) = if_.node; + if !used_in_expr(cx, canonical_id, cond); + if let hir::ExprBlock(ref then) = then.node; + if let Some(value) = check_assign(cx, canonical_id, &*then); + if !used_in_expr(cx, canonical_id, value); + then { + let span = stmt.span.to(if_.span); + + let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { + if let hir::ExprBlock(ref else_) = else_.node { + if let Some(default) = check_assign(cx, canonical_id, else_) { + (else_.stmts.len() > 1, default) + } else if let Some(ref default) = decl.init { + (true, &**default) + } else { + continue; + } } else { continue; } + } else if let Some(ref default) = decl.init { + (false, &**default) } else { continue; - } - } else if let Some(ref default) = decl.init { - (false, &**default) - } else { - continue; - }; - - let mutability = match mode { - BindingAnnotation::RefMut | BindingAnnotation::Mutable => " ", - _ => "", - }; - - // FIXME: this should not suggest `mut` if we can detect that the variable is not - // use mutably after the `if` - - let sug = format!( - "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", - mut=mutability, - name=name.node, - cond=snippet(cx, cond.span, "_"), - then=if then.stmts.len() > 1 { " ..;" } else { "" }, - else=if default_multi_stmts { " ..;" } else { "" }, - value=snippet(cx, value.span, ""), - default=snippet(cx, default.span, ""), - ); - span_lint_and_then(cx, - USELESS_LET_IF_SEQ, - span, - "`if _ { .. } else { .. }` is an expression", - |db| { - db.span_suggestion(span, - "it is more idiomatic to write", - sug); - if !mutability.is_empty() { - db.note("you might not need `mut` at all"); - } - }); - }} + }; + + let mutability = match mode { + BindingAnnotation::RefMut | BindingAnnotation::Mutable => " ", + _ => "", + }; + + // FIXME: this should not suggest `mut` if we can detect that the variable is not + // use mutably after the `if` + + let sug = format!( + "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", + mut=mutability, + name=name.node, + cond=snippet(cx, cond.span, "_"), + then=if then.stmts.len() > 1 { " ..;" } else { "" }, + else=if default_multi_stmts { " ..;" } else { "" }, + value=snippet(cx, value.span, ""), + default=snippet(cx, default.span, ""), + ); + span_lint_and_then(cx, + USELESS_LET_IF_SEQ, + span, + "`if _ { .. } else { .. }` is an expression", + |db| { + db.span_suggestion(span, + "it is more idiomatic to write", + sug); + if !mutability.is_empty() { + db.note("you might not need `mut` at all"); + } + }); + } + } } } } @@ -138,14 +139,15 @@ struct UsedVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if_let_chain! {[ - let hir::ExprPath(ref qpath) = expr.node, - let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), - self.id == local_id, - ], { - self.used = true; - return; - }} + if_chain! { + if let hir::ExprPath(ref qpath) = expr.node; + if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); + if self.id == local_id; + then { + self.used = true; + return; + } + } hir::intravisit::walk_expr(self, expr); } fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> { @@ -158,31 +160,32 @@ fn check_assign<'a, 'tcx>( decl: ast::NodeId, block: &'tcx hir::Block, ) -> Option<&'tcx hir::Expr> { - if_let_chain! {[ - block.expr.is_none(), - let Some(expr) = block.stmts.iter().last(), - let hir::StmtSemi(ref expr, _) = expr.node, - let hir::ExprAssign(ref var, ref value) = expr.node, - let hir::ExprPath(ref qpath) = var.node, - let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id), - decl == local_id, - ], { - let mut v = UsedVisitor { - cx: cx, - id: decl, - used: false, - }; - - for s in block.stmts.iter().take(block.stmts.len()-1) { - hir::intravisit::walk_stmt(&mut v, s); - - if v.used { - return None; + if_chain! { + if block.expr.is_none(); + if let Some(expr) = block.stmts.iter().last(); + if let hir::StmtSemi(ref expr, _) = expr.node; + if let hir::ExprAssign(ref var, ref value) = expr.node; + if let hir::ExprPath(ref qpath) = var.node; + if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id); + if decl == local_id; + then { + let mut v = UsedVisitor { + cx: cx, + id: decl, + used: false, + }; + + for s in block.stmts.iter().take(block.stmts.len()-1) { + hir::intravisit::walk_stmt(&mut v, s); + + if v.used { + return None; + } } + + return Some(value); } - - return Some(value); - }} + } None } diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index b656fed1cfb..91e4c567488 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -244,58 +244,60 @@ impl EarlyLintPass for LiteralDigitGrouping { impl LiteralDigitGrouping { fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { // Lint integral literals. - if_let_chain! {[ - let LitKind::Int(..) = lit.node, - let Some(src) = snippet_opt(cx, lit.span), - let Some(firstch) = src.chars().next(), - char::to_digit(firstch, 10).is_some() - ], { - let digit_info = DigitInfo::new(&src, false); - let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { - warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) - }); - }} + if_chain! { + if let LitKind::Int(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, false); + let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { + warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + }); + } + } // Lint floating-point literals. - if_let_chain! {[ - let LitKind::Float(..) = lit.node, - let Some(src) = snippet_opt(cx, lit.span), - let Some(firstch) = src.chars().next(), - char::to_digit(firstch, 10).is_some() - ], { - let digit_info = DigitInfo::new(&src, true); - // Separate digits into integral and fractional parts. - let parts: Vec<&str> = digit_info - .digits - .split_terminator('.') - .collect(); - - // Lint integral and fractional parts separately, and then check consistency of digit - // groups if both pass. - let _ = Self::do_lint(parts[0]) - .map(|integral_group_size| { - if parts.len() > 1 { - // Lint the fractional part of literal just like integral part, but reversed. - let fractional_part = &parts[1].chars().rev().collect::(); - let _ = Self::do_lint(fractional_part) - .map(|fractional_group_size| { - let consistent = Self::parts_consistent(integral_group_size, - fractional_group_size, - parts[0].len(), - parts[1].len()); - if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), - cx, - &lit.span); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), - cx, - &lit.span)); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); - }} + if_chain! { + if let LitKind::Float(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, true); + // Separate digits into integral and fractional parts. + let parts: Vec<&str> = digit_info + .digits + .split_terminator('.') + .collect(); + + // Lint integral and fractional parts separately, and then check consistency of digit + // groups if both pass. + let _ = Self::do_lint(parts[0]) + .map(|integral_group_size| { + if parts.len() > 1 { + // Lint the fractional part of literal just like integral part, but reversed. + let fractional_part = &parts[1].chars().rev().collect::(); + let _ = Self::do_lint(fractional_part) + .map(|fractional_group_size| { + let consistent = Self::parts_consistent(integral_group_size, + fractional_group_size, + parts[0].len(), + parts[1].len()); + if !consistent { + WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), + cx, + &lit.span); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), + cx, + &lit.span)); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); + } + } } /// Given the sizes of the digit groups of both integral and fractional diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cea0cfb7028..0c3fd915399 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -611,16 +611,17 @@ fn check_for_loop<'a, 'tcx>( } fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool { - if_let_chain! {[ - let ExprPath(ref qpath) = expr.node, - let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, - let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id), + if_chain! { + if let ExprPath(ref qpath) = expr.node; + if let QPath::Resolved(None, ref path) = *qpath; + if path.segments.len() == 1; + if let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id); // our variable! - local_id == var - ], { - return true; - }} + if local_id == var; + then { + return true; + } + } false } @@ -725,14 +726,15 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( expr: &Expr, var: ast::NodeId, ) -> Option { - if_let_chain! {[ - let ExprMethodCall(ref method, _, ref args) = expr.node, - method.name == "clone", - args.len() == 1, - let Some(arg) = args.get(0), - ], { - return get_fixed_offset_var(cx, arg, var); - }} + if_chain! { + if let ExprMethodCall(ref method, _, ref args) = expr.node; + if method.name == "clone"; + if args.len() == 1; + if let Some(arg) = args.get(0); + then { + return get_fixed_offset_var(cx, arg, var); + } + } get_fixed_offset_var(cx, expr, var) } @@ -821,19 +823,20 @@ fn detect_manual_memcpy<'a, 'tcx>( }; let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { - if_let_chain! {[ - let ExprMethodCall(ref method, _, ref len_args) = end.node, - method.name == "len", - len_args.len() == 1, - let Some(arg) = len_args.get(0), - snippet(cx, arg.span, "??") == var_name, - ], { - return if offset.negate { - format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) - } else { - "".to_owned() - }; - }} + if_chain! { + if let ExprMethodCall(ref method, _, ref len_args) = end.node; + if method.name == "len"; + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if snippet(cx, arg.span, "??") == var_name; + then { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) + } else { + "".to_owned() + }; + } + } let end_str = match limits { ast::RangeLimits::Closed => { @@ -1003,16 +1006,17 @@ fn check_for_loop_range<'a, 'tcx>( } fn is_len_call(expr: &Expr, var: &Name) -> bool { - if_let_chain! {[ - let ExprMethodCall(ref method, _, ref len_args) = expr.node, - len_args.len() == 1, - method.name == "len", - let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node, - path.segments.len() == 1, - path.segments[0].name == *var - ], { - return true; - }} + if_chain! { + if let ExprMethodCall(ref method, _, ref len_args) = expr.node; + if len_args.len() == 1; + if method.name == "len"; + if let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node; + if path.segments.len() == 1; + if path.segments[0].name == *var; + then { + return true; + } + } false } @@ -1374,22 +1378,24 @@ fn mut_warn_with_span(cx: &LateContext, span: Option) { } fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { - if_let_chain! {[ - let ExprPath(ref qpath) = bound.node, - let QPath::Resolved(None, _) = *qpath, - ], { - let def = cx.tables.qpath_def(qpath, bound.hir_id); - if let Def::Local(node_id) = def { - let node_str = cx.tcx.hir.get(node_id); - if_let_chain! {[ - let map::Node::NodeBinding(pat) = node_str, - let PatKind::Binding(bind_ann, _, _, _) = pat.node, - let BindingAnnotation::Mutable = bind_ann, - ], { - return Some(node_id); - }} + if_chain! { + if let ExprPath(ref qpath) = bound.node; + if let QPath::Resolved(None, _) = *qpath; + then { + let def = cx.tables.qpath_def(qpath, bound.hir_id); + if let Def::Local(node_id) = def { + let node_str = cx.tcx.hir.get(node_id); + if_chain! { + if let map::Node::NodeBinding(pat) = node_str; + if let PatKind::Binding(bind_ann, _, _, _) = pat.node; + if let BindingAnnotation::Mutable = bind_ann; + then { + return Some(node_id); + } + } + } } - }} + } None } @@ -1476,67 +1482,69 @@ struct VarVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if_let_chain! {[ + if_chain! { // an index op - let ExprIndex(ref seqexpr, ref idx) = expr.node, + if let ExprIndex(ref seqexpr, ref idx) = expr.node; // the indexed container is referenced by a name - let ExprPath(ref seqpath) = seqexpr.node, - let QPath::Resolved(None, ref seqvar) = *seqpath, - seqvar.segments.len() == 1, - ], { - let index_used_directly = same_var(self.cx, idx, self.var); - let index_used = index_used_directly || { - let mut used_visitor = LocalUsedVisitor { - cx: self.cx, - local: self.var, - used: false, + if let ExprPath(ref seqpath) = seqexpr.node; + if let QPath::Resolved(None, ref seqvar) = *seqpath; + if seqvar.segments.len() == 1; + then { + let index_used_directly = same_var(self.cx, idx, self.var); + let index_used = index_used_directly || { + let mut used_visitor = LocalUsedVisitor { + cx: self.cx, + local: self.var, + used: false, + }; + walk_expr(&mut used_visitor, idx); + used_visitor.used }; - walk_expr(&mut used_visitor, idx); - used_visitor.used - }; - - if index_used { - let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); - match def { - Def::Local(node_id) | Def::Upvar(node_id, ..) => { - let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); - - let parent_id = self.cx.tcx.hir.get_parent(expr.id); - let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); - if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].name, Some(extent)); + + if index_used { + let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); + match def { + Def::Local(node_id) | Def::Upvar(node_id, ..) => { + let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); + + let parent_id = self.cx.tcx.hir.get_parent(expr.id); + let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); + if index_used_directly { + self.indexed_directly.insert(seqvar.segments[0].name, Some(extent)); + } + return; // no need to walk further *on the variable* } - return; // no need to walk further *on the variable* - } - Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); - if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].name, None); + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].name, None); + if index_used_directly { + self.indexed_directly.insert(seqvar.segments[0].name, None); + } + return; // no need to walk further *on the variable* } - return; // no need to walk further *on the variable* + _ => (), } - _ => (), } } - }} + } - if_let_chain! {[ + if_chain! { // directly using a variable - let ExprPath(ref qpath) = expr.node, - let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, - let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id), - ], { - if local_id == self.var { - // we are not indexing anything, record that - self.nonindex = true; - } else { - // not the correct variable, but still a variable - self.referenced.insert(path.segments[0].name); + if let ExprPath(ref qpath) = expr.node; + if let QPath::Resolved(None, ref path) = *qpath; + if path.segments.len() == 1; + if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); + then { + if local_id == self.var { + // we are not indexing anything, record that + self.nonindex = true; + } else { + // not the correct variable, but still a variable + self.referenced.insert(path.segments[0].name); + } } - }} + } walk_expr(self, expr); } @@ -1845,12 +1853,13 @@ fn is_conditional(expr: &Expr) -> bool { } fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool { - if_let_chain! {[ - let Some(loop_block) = get_enclosing_block(cx, match_expr.id), - let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)), - ], { - return is_loop_nested(cx, loop_expr, iter_expr) - }} + if_chain! { + if let Some(loop_block) = get_enclosing_block(cx, match_expr.id); + if let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)); + then { + return is_loop_nested(cx, loop_expr, iter_expr) + } + } false } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index e35e1ab477c..e126d5c07d7 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -35,22 +35,36 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let body = cx.tcx.hir.body(closure_eid); let closure_expr = remove_blocks(&body.value); let ty = cx.tables.pat_ty(&body.arguments[0].pat); - if_let_chain! {[ + if_chain! { // nothing special in the argument, besides reference bindings // (e.g. .map(|&x| x) ) - let Some(first_arg) = iter_input_pats(decl, body).next(), - let Some(arg_ident) = get_arg_name(&first_arg.pat), + if let Some(first_arg) = iter_input_pats(decl, body).next(); + if let Some(arg_ident) = get_arg_name(&first_arg.pat); // the method is being called on a known type (option or iterator) - let Some(type_name) = get_type_name(cx, expr, &args[0]) - ], { - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 - { - // the argument is not an &mut T - if let ty::TyRef(_, tam) = ty.sty { - if tam.mutbl == MutImmutable { + if let Some(type_name) = get_type_name(cx, expr, &args[0]); + then { + // look for derefs, for .map(|x| *x) + if only_derefs(cx, &*closure_expr, arg_ident) && + // .cloned() only removes one level of indirection, don't lint on more + walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 + { + // the argument is not an &mut T + if let ty::TyRef(_, tam) = ty.sty { + if tam.mutbl == MutImmutable { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } + } + // explicit clone() calls ( .map(|x| x.clone()) ) + else if let ExprMethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { + if clone_call.name == "clone" && + clone_args.len() == 1 && + match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && + expr_eq_name(&clone_args[0], arg_ident) + { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ using `.cloned()`", type_name), @@ -58,20 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprMethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.name == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(&clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - }} + } }, ExprPath(ref path) => if match_qpath(path, &paths::CLONE) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 78a85c4a686..18ba34f8621 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -343,21 +343,22 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { for arm in arms { if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pats[0].node { let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)); - if_let_chain! {[ - path_str == "Err", - inner.iter().any(|pat| pat.node == PatKind::Wild), - let ExprBlock(ref block) = arm.body.node, - is_panic_block(block) - ], { - // `Err(_)` arm with `panic!` found - span_note_and_lint(cx, - MATCH_WILD_ERR_ARM, - arm.pats[0].span, - "Err(_) will match all errors, maybe not a good idea", - arm.pats[0].span, - "to remove this warning, match each error seperately \ - or use unreachable macro"); - }} + if_chain! { + if path_str == "Err"; + if inner.iter().any(|pat| pat.node == PatKind::Wild); + if let ExprBlock(ref block) = arm.body.node; + if is_panic_block(block); + then { + // `Err(_)` arm with `panic!` found + span_note_and_lint(cx, + MATCH_WILD_ERR_ARM, + arm.pats[0].span, + "Err(_) will match all errors, maybe not a good idea", + arm.pats[0].span, + "to remove this warning, match each error seperately \ + or use unreachable macro"); + } + } } } } @@ -428,24 +429,26 @@ fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm], id: NodeI } else { [].iter() }.filter_map(|pat| { - if_let_chain! {[ - let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node, - let Ok(lhs) = constcx.eval(lhs), - let Ok(rhs) = constcx.eval(rhs) - ], { - let rhs = match *range_end { - RangeEnd::Included => Bound::Included(rhs), - RangeEnd::Excluded => Bound::Excluded(rhs), - }; - return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); - }} - - if_let_chain! {[ - let PatKind::Lit(ref value) = pat.node, - let Ok(value) = constcx.eval(value) - ], { - return Some(SpannedRange { span: pat.span, node: (value, Bound::Included(value)) }); - }} + if_chain! { + if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node; + if let Ok(lhs) = constcx.eval(lhs); + if let Ok(rhs) = constcx.eval(rhs); + then { + let rhs = match *range_end { + RangeEnd::Included => Bound::Included(rhs), + RangeEnd::Excluded => Bound::Excluded(rhs), + }; + return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); + } + } + + if_chain! { + if let PatKind::Lit(ref value) = pat.node; + if let Ok(value) = constcx.eval(value); + then { + return Some(SpannedRange { span: pat.span, node: (value, Bound::Included(value)) }); + } + } None }) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4a0d1cf19cb..8b4520a5e03 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -735,60 +735,62 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let name = implitem.name; let parent = cx.tcx.hir.get_parent(implitem.id); let item = cx.tcx.hir.expect_item(parent); - if_let_chain! {[ - let hir::ImplItemKind::Method(ref sig, id) = implitem.node, - let Some(first_arg_ty) = sig.decl.inputs.get(0), - let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(), - let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node, - ], { - // check missing trait implementations - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if name == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(&sig.decl.output) && - self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); + if_chain! { + if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; + if let Some(first_arg_ty) = sig.decl.inputs.get(0); + if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); + if let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node; + then { + // check missing trait implementations + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if name == method_name && + sig.decl.inputs.len() == n_args && + out_type.matches(&sig.decl.output) && + self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } } - } - - // check conventions w.r.t. conversion method names and predicates - let def_id = cx.tcx.hir.local_def_id(item.id); - let ty = cx.tcx.type_of(def_id); - let is_copy = is_copy(cx, ty); - for &(ref conv, self_kinds) in &CONVENTIONS { - if_let_chain! {[ - conv.check(&name.as_str()), - !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &sig.generics)), - ], { - let lint = if item.vis == hir::Visibility::Public { - WRONG_PUB_SELF_CONVENTION - } else { - WRONG_SELF_CONVENTION - }; + + // check conventions w.r.t. conversion method names and predicates + let def_id = cx.tcx.hir.local_def_id(item.id); + let ty = cx.tcx.type_of(def_id); + let is_copy = is_copy(cx, ty); + for &(ref conv, self_kinds) in &CONVENTIONS { + if_chain! { + if conv.check(&name.as_str()); + if !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &sig.generics)); + then { + let lint = if item.vis == hir::Visibility::Public { + WRONG_PUB_SELF_CONVENTION + } else { + WRONG_SELF_CONVENTION + }; + span_lint(cx, + lint, + first_arg.pat.span, + &format!("methods called `{}` usually take {}; consider choosing a less \ + ambiguous name", + conv, + &self_kinds.iter() + .map(|k| k.description()) + .collect::>() + .join(" or "))); + } + } + } + + let ret_ty = return_ty(cx, implitem.id); + if name == "new" && + !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { span_lint(cx, - lint, - first_arg.pat.span, - &format!("methods called `{}` usually take {}; consider choosing a less \ - ambiguous name", - conv, - &self_kinds.iter() - .map(|k| k.description()) - .collect::>() - .join(" or "))); - }} - } - - let ret_ty = return_ty(cx, implitem.id); - if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { - span_lint(cx, - NEW_RET_NO_SELF, - implitem.span, - "methods called `new` usually return `Self`"); + NEW_RET_NO_SELF, + implitem.span, + "methods called `new` usually return `Self`"); + } } - }} + } } } @@ -1014,20 +1016,21 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { } fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { - if_let_chain!{[ - let hir::ExprCall(ref fun, ref args) = new.node, - args.len() == 1, - let hir::ExprPath(ref path) = fun.node, - let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id), - match_def_path(cx.tcx, did, &paths::CSTRING_NEW) - ], { - span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, - "you are getting the inner pointer of a temporary `CString`", - |db| { - db.note("that pointer will be invalid outside this expression"); - db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); - }); - }} + if_chain! { + if let hir::ExprCall(ref fun, ref args) = new.node; + if args.len() == 1; + if let hir::ExprPath(ref path) = fun.node; + if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); + if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); + then { + span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, + "you are getting the inner pointer of a temporary `CString`", + |db| { + db.note("that pointer will be invalid outside this expression"); + db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); + }); + } + } } fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { @@ -1427,33 +1430,34 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { - if_let_chain! {[ - let Some(args) = method_chain_args(info.chain, chain_methods), - let hir::ExprCall(ref fun, ref arg_char) = info.other.node, - arg_char.len() == 1, - let hir::ExprPath(ref qpath) = fun.node, - let Some(segment) = single_segment_path(qpath), - segment.name == "Some" - ], { - let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); - - if self_ty.sty != ty::TyStr { - return false; + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprCall(ref fun, ref arg_char) = info.other.node; + if arg_char.len() == 1; + if let hir::ExprPath(ref qpath) = fun.node; + if let Some(segment) = single_segment_path(qpath); + if segment.name == "Some"; + then { + let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); + + if self_ty.sty != ty::TyStr { + return false; + } + + span_lint_and_sugg(cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + snippet(cx, arg_char[0].span, "_"))); + + return true; } - - span_lint_and_sugg(cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}({})", - if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - suggest, - snippet(cx, arg_char[0].span, "_"))); - - return true; - }} + } false } @@ -1474,26 +1478,27 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { - if_let_chain! {[ - let Some(args) = method_chain_args(info.chain, chain_methods), - let hir::ExprLit(ref lit) = info.other.node, - let ast::LitKind::Char(c) = lit.node, - ], { - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}('{}')", - if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - suggest, - c) - ); - - return true; - }} + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprLit(ref lit) = info.other.node; + if let ast::LitKind::Char(c) = lit.node; + then { + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}('{}')", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + c) + ); + + return true; + } + } false } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 98fb90f57c1..18d7f7230a8 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -251,55 +251,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) { - if_let_chain! {[ - let StmtDecl(ref d, _) = s.node, - let DeclLocal(ref l) = d.node, - let PatKind::Binding(an, _, i, None) = l.pat.node, - let Some(ref init) = l.init - ], { - if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut { - let init = Sugg::hir(cx, init, ".."); - let (mutopt,initref) = if an == BindingAnnotation::RefMut { - ("mut ", init.mut_addr()) - } else { - ("", init.addr()) - }; - let tyopt = if let Some(ref ty) = l.ty { - format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_")) - } else { - "".to_owned() - }; + if_chain! { + if let StmtDecl(ref d, _) = s.node; + if let DeclLocal(ref l) = d.node; + if let PatKind::Binding(an, _, i, None) = l.pat.node; + if let Some(ref init) = l.init; + then { + if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut { + let init = Sugg::hir(cx, init, ".."); + let (mutopt,initref) = if an == BindingAnnotation::RefMut { + ("mut ", init.mut_addr()) + } else { + ("", init.addr()) + }; + let tyopt = if let Some(ref ty) = l.ty { + format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_")) + } else { + "".to_owned() + }; + span_lint_and_then(cx, + TOPLEVEL_REF_ARG, + l.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", + |db| { + db.span_suggestion(s.span, + "try", + format!("let {name}{tyopt} = {initref};", + name=snippet(cx, i.span, "_"), + tyopt=tyopt, + initref=initref)); + } + ); + } + } + }; + if_chain! { + if let StmtSemi(ref expr, _) = s.node; + if let Expr_::ExprBinary(ref binop, ref a, ref b) = expr.node; + if binop.node == BiAnd || binop.node == BiOr; + if let Some(sugg) = Sugg::hir_opt(cx, a); + then { span_lint_and_then(cx, - TOPLEVEL_REF_ARG, - l.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", + SHORT_CIRCUIT_STATEMENT, + s.span, + "boolean short circuit operator in statement may be clearer using an explicit test", |db| { - db.span_suggestion(s.span, - "try", - format!("let {name}{tyopt} = {initref};", - name=snippet(cx, i.span, "_"), - tyopt=tyopt, - initref=initref)); - } - ); + let sugg = if binop.node == BiOr { !sugg } else { sugg }; + db.span_suggestion(s.span, "replace it with", + format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, ".."))); + }); } - }}; - if_let_chain! {[ - let StmtSemi(ref expr, _) = s.node, - let Expr_::ExprBinary(ref binop, ref a, ref b) = expr.node, - binop.node == BiAnd || binop.node == BiOr, - let Some(sugg) = Sugg::hir_opt(cx, a), - ], { - span_lint_and_then(cx, - SHORT_CIRCUIT_STATEMENT, - s.span, - "boolean short circuit operator in statement may be clearer using an explicit test", - |db| { - let sugg = if binop.node == BiOr { !sugg } else { sugg }; - db.span_suggestion(s.span, "replace it with", - format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, ".."))); - }); - }}; + }; } fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -582,17 +584,18 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { } fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { - if_let_chain! {[ - let TyPtr(MutTy { mutbl, .. }) = ty.node, - let ExprLit(ref lit) = e.node, - let LitKind::Int(value, ..) = lit.node, - value == 0, - !in_constant(cx, e.id) - ], { - let msg = match mutbl { - Mutability::MutMutable => "`0 as *mut _` detected. Consider using `ptr::null_mut()`", - Mutability::MutImmutable => "`0 as *const _` detected. Consider using `ptr::null()`", - }; - span_lint(cx, ZERO_PTR, span, msg); - }} + if_chain! { + if let TyPtr(MutTy { mutbl, .. }) = ty.node; + if let ExprLit(ref lit) = e.node; + if let LitKind::Int(value, ..) = lit.node; + if value == 0; + if !in_constant(cx, e.id); + then { + let msg = match mutbl { + Mutability::MutMutable => "`0 as *mut _` detected. Consider using `ptr::null_mut()`", + Mutability::MutImmutable => "`0 as *const _` detected. Consider using `ptr::null()`", + }; + span_lint(cx, ZERO_PTR, span, msg); + } + } } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index bf4df6e2873..160ccd8e9b3 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -322,100 +322,103 @@ impl EarlyLintPass for MiscEarly { fn check_block(&mut self, cx: &EarlyContext, block: &Block) { for w in block.stmts.windows(2) { - if_let_chain! {[ - let StmtKind::Local(ref local) = w[0].node, - let Option::Some(ref t) = local.init, - let ExprKind::Closure(_, _, _, _) = t.node, - let PatKind::Ident(_, sp_ident, _) = local.pat.node, - let StmtKind::Semi(ref second) = w[1].node, - let ExprKind::Assign(_, ref call) = second.node, - let ExprKind::Call(ref closure, _) = call.node, - let ExprKind::Path(_, ref path) = closure.node - ], { - if sp_ident.node == (&path.segments[0]).identifier { - span_lint( - cx, - REDUNDANT_CLOSURE_CALL, - second.span, - "Closure called just once immediately after it was declared", - ); + if_chain! { + if let StmtKind::Local(ref local) = w[0].node; + if let Option::Some(ref t) = local.init; + if let ExprKind::Closure(_, _, _, _) = t.node; + if let PatKind::Ident(_, sp_ident, _) = local.pat.node; + if let StmtKind::Semi(ref second) = w[1].node; + if let ExprKind::Assign(_, ref call) = second.node; + if let ExprKind::Call(ref closure, _) = call.node; + if let ExprKind::Path(_, ref path) = closure.node; + then { + if sp_ident.node == (&path.segments[0]).identifier { + span_lint( + cx, + REDUNDANT_CLOSURE_CALL, + second.span, + "Closure called just once immediately after it was declared", + ); + } } - }} + } } } } impl MiscEarly { fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { - if_let_chain! {[ - let LitKind::Int(value, ..) = lit.node, - let Some(src) = snippet_opt(cx, lit.span), - let Some(firstch) = src.chars().next(), - char::to_digit(firstch, 10).is_some() - ], { - let mut prev = '\0'; - for ch in src.chars() { - if ch == 'i' || ch == 'u' { - if prev != '_' { - span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span, - "integer type suffix should be separated by an underscore"); - } - break; - } - prev = ch; - } - if src.starts_with("0x") { - let mut seen = (false, false); + if_chain! { + if let LitKind::Int(value, ..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let mut prev = '\0'; for ch in src.chars() { - match ch { - 'a' ... 'f' => seen.0 = true, - 'A' ... 'F' => seen.1 = true, - 'i' | 'u' => break, // start of suffix already - _ => () + if ch == 'i' || ch == 'u' { + if prev != '_' { + span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span, + "integer type suffix should be separated by an underscore"); + } + break; } + prev = ch; } - if seen.0 && seen.1 { - span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span, - "inconsistent casing in hexadecimal literal"); + if src.starts_with("0x") { + let mut seen = (false, false); + for ch in src.chars() { + match ch { + 'a' ... 'f' => seen.0 = true, + 'A' ... 'F' => seen.1 = true, + 'i' | 'u' => break, // start of suffix already + _ => () + } + } + if seen.0 && seen.1 { + span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span, + "inconsistent casing in hexadecimal literal"); + } + } else if src.starts_with("0b") || src.starts_with("0o") { + /* nothing to do */ + } else if value != 0 && src.starts_with('0') { + span_lint_and_then(cx, + ZERO_PREFIXED_LITERAL, + lit.span, + "this is a decimal constant", + |db| { + db.span_suggestion( + lit.span, + "if you mean to use a decimal constant, remove the `0` to remove confusion", + src.trim_left_matches(|c| c == '_' || c == '0').to_string(), + ); + db.span_suggestion( + lit.span, + "if you mean to use an octal constant, use `0o`", + format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')), + ); + }); } - } else if src.starts_with("0b") || src.starts_with("0o") { - /* nothing to do */ - } else if value != 0 && src.starts_with('0') { - span_lint_and_then(cx, - ZERO_PREFIXED_LITERAL, - lit.span, - "this is a decimal constant", - |db| { - db.span_suggestion( - lit.span, - "if you mean to use a decimal constant, remove the `0` to remove confusion", - src.trim_left_matches(|c| c == '_' || c == '0').to_string(), - ); - db.span_suggestion( - lit.span, - "if you mean to use an octal constant, use `0o`", - format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')), - ); - }); } - }} - if_let_chain! {[ - let LitKind::Float(..) = lit.node, - let Some(src) = snippet_opt(cx, lit.span), - let Some(firstch) = src.chars().next(), - char::to_digit(firstch, 10).is_some() - ], { - let mut prev = '\0'; - for ch in src.chars() { - if ch == 'f' { - if prev != '_' { - span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span, - "float type suffix should be separated by an underscore"); + } + if_chain! { + if let LitKind::Float(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let mut prev = '\0'; + for ch in src.chars() { + if ch == 'f' { + if prev != '_' { + span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span, + "float type suffix should be separated by an underscore"); + } + break; } - break; + prev = ch; } - prev = ch; } - }} + } } } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index d8f892d4073..be1fd1dc525 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -75,25 +75,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if in_macro(pat.span) { return; } - if_let_chain! {[ - let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node, - let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, - tam.mutbl == MutImmutable, - let ty::TyRef(_, ref tam) = tam.ty.sty, + if_chain! { + if let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node; + if let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty; + if tam.mutbl == MutImmutable; + if let ty::TyRef(_, ref tam) = tam.ty.sty; // only lint immutable refs, because borrowed `&mut T` cannot be moved out - tam.mutbl == MutImmutable, - ], { - span_lint_and_then( - cx, - NEEDLESS_BORROW, - pat.span, - "this pattern creates a reference to a reference", - |db| { - if let Some(snippet) = snippet_opt(cx, name.span) { - db.span_suggestion(pat.span, "change this to", snippet); + if tam.mutbl == MutImmutable; + then { + span_lint_and_then( + cx, + NEEDLESS_BORROW, + pat.span, + "this pattern creates a reference to a reference", + |db| { + if let Some(snippet) = snippet_opt(cx, name.span) { + db.span_suggestion(pat.span, "change this to", snippet); + } } - } - ) - }} + ) + } + } } } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 1c00263cbc2..c9a2e6b0935 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -64,19 +64,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { return; } - if_let_chain! {[ + if_chain! { // Only lint immutable refs, because `&mut ref T` may be useful. - let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, + if let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node; // Check sub_pat got a `ref` keyword (excluding `ref mut`). - let PatKind::Binding(BindingAnnotation::Ref, _, spanned_name, ..) = sub_pat.node, - ], { - span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, - "this pattern takes a reference on something that is being de-referenced", - |db| { - let hint = snippet(cx, spanned_name.span, "..").into_owned(); - db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); - }); - }} + if let PatKind::Binding(BindingAnnotation::Ref, _, spanned_name, ..) = sub_pat.node; + then { + span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, + "this pattern takes a reference on something that is being de-referenced", + |db| { + let hint = snippet(cx, spanned_name.span, "..").into_owned(); + db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); + }); + } + } } } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index e67dca5d00d..e00938fb3ef 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -64,13 +64,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { match kind { FnKind::ItemFn(.., attrs) => for a in attrs { - if_let_chain!{[ - a.meta_item_list().is_some(), - let Some(name) = a.name(), - name == "proc_macro_derive", - ], { - return; - }} + if_chain! { + if a.meta_item_list().is_some(); + if let Some(name) = a.name(); + if name == "proc_macro_derive"; + then { + return; + } + } }, _ => return, } @@ -148,101 +149,103 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ) }; - if_let_chain! {[ - !is_self(arg), - !ty.is_mutable_pointer(), - !is_copy(cx, ty), - !fn_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])), - !implements_borrow_trait, - !all_borrowable_trait, - - let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node, - !moved_vars.contains(&canonical_id), - ], { - if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { - continue; - } - - // Dereference suggestion - let sugg = |db: &mut DiagnosticBuilder| { - let deref_span = spans_need_deref.get(&canonical_id); - if_let_chain! {[ - match_type(cx, ty, &paths::VEC), - let Some(clone_spans) = - get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]), - let TyPath(QPath::Resolved(_, ref path)) = input.node, - let Some(elem_ty) = path.segments.iter() - .find(|seg| seg.name == "Vec") - .and_then(|ps| ps.parameters.as_ref()) - .map(|params| ¶ms.types[0]), - ], { - let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); - db.span_suggestion(input.span, - "consider changing the type to", - slice_ty); - - for (span, suggestion) in clone_spans { - db.span_suggestion( - span, - &snippet_opt(cx, span) - .map_or( - "change the call to".into(), - |x| Cow::from(format!("change `{}` to", x)), - ), - suggestion.into() - ); + if_chain! { + if !is_self(arg); + if !ty.is_mutable_pointer(); + if !is_copy(cx, ty); + if !fn_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); + if !implements_borrow_trait; + if !all_borrowable_trait; + + if let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node; + if !moved_vars.contains(&canonical_id); + then { + if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { + continue; + } + + // Dereference suggestion + let sugg = |db: &mut DiagnosticBuilder| { + let deref_span = spans_need_deref.get(&canonical_id); + if_chain! { + if match_type(cx, ty, &paths::VEC); + if let Some(clone_spans) = + get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); + if let TyPath(QPath::Resolved(_, ref path)) = input.node; + if let Some(elem_ty) = path.segments.iter() + .find(|seg| seg.name == "Vec") + .and_then(|ps| ps.parameters.as_ref()) + .map(|params| ¶ms.types[0]); + then { + let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); + db.span_suggestion(input.span, + "consider changing the type to", + slice_ty); + + for (span, suggestion) in clone_spans { + db.span_suggestion( + span, + &snippet_opt(cx, span) + .map_or( + "change the call to".into(), + |x| Cow::from(format!("change `{}` to", x)), + ), + suggestion.into() + ); + } + + // cannot be destructured, no need for `*` suggestion + assert!(deref_span.is_none()); + return; + } } - - // cannot be destructured, no need for `*` suggestion - assert!(deref_span.is_none()); - return; - }} - - if match_type(cx, ty, &paths::STRING) { - if let Some(clone_spans) = - get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { - db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); - - for (span, suggestion) in clone_spans { - db.span_suggestion( - span, - &snippet_opt(cx, span) - .map_or( - "change the call to".into(), - |x| Cow::from(format!("change `{}` to", x)) - ), - suggestion.into(), - ); + + if match_type(cx, ty, &paths::STRING) { + if let Some(clone_spans) = + get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { + db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); + + for (span, suggestion) in clone_spans { + db.span_suggestion( + span, + &snippet_opt(cx, span) + .map_or( + "change the call to".into(), + |x| Cow::from(format!("change `{}` to", x)) + ), + suggestion.into(), + ); + } + + assert!(deref_span.is_none()); + return; } - - assert!(deref_span.is_none()); - return; } - } - - let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; - - // Suggests adding `*` to dereference the added reference. - if let Some(deref_span) = deref_span { - spans.extend( - deref_span - .iter() - .cloned() - .map(|span| (span, format!("*{}", snippet(cx, span, "")))), - ); - spans.sort_by_key(|&(span, _)| span); - } - multispan_sugg(db, "consider taking a reference instead".to_string(), spans); - }; - - span_lint_and_then( - cx, - NEEDLESS_PASS_BY_VALUE, - input.span, - "this argument is passed by value, but not consumed in the function body", - sugg, - ); - }} + + let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; + + // Suggests adding `*` to dereference the added reference. + if let Some(deref_span) = deref_span { + spans.extend( + deref_span + .iter() + .cloned() + .map(|span| (span, format!("*{}", snippet(cx, span, "")))), + ); + spans.sort_by_key(|&(span, _)| span); + } + multispan_sugg(db, "consider taking a reference instead".to_string(), spans); + }; + + span_lint_and_then( + cx, + NEEDLESS_PASS_BY_VALUE, + input.span, + "this argument is passed by value, but not consumed in the function body", + sugg, + ); + } + } } } } @@ -299,18 +302,19 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { map::Node::NodeStmt(s) => { // `let = x;` - if_let_chain! {[ - let StmtDecl(ref decl, _) = s.node, - let DeclLocal(ref local) = decl.node, - ], { - self.spans_need_deref - .entry(vid) - .or_insert_with(HashSet::new) - .insert(local.init - .as_ref() - .map(|e| e.span) - .expect("`let` stmt without init aren't caught by match_pat")); - }} + if_chain! { + if let StmtDecl(ref decl, _) = s.node; + if let DeclLocal(ref local) = decl.node; + then { + self.spans_need_deref + .entry(vid) + .or_insert_with(HashSet::new) + .insert(local.init + .as_ref() + .map(|e| e.span) + .expect("`let` stmt without init aren't caught by match_pat")); + } + } }, _ => {}, diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index d7437f34cff..e34136face9 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -45,16 +45,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { } fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { - if_let_chain!([ - let ExprLit(ref l) = lit.node, - let Constant::Int(ref ci) = consts::lit_to_constant(&l.node, cx.tcx, cx.tables.expr_ty(lit)), - let Some(val) = ci.to_u64(), - val == 1, - cx.tables.expr_ty(exp).is_integral() - ], { - span_lint(cx, - NEG_MULTIPLY, - span, - "Negation by multiplying with -1"); - }) + if_chain! { + if let ExprLit(ref l) = lit.node; + if let Constant::Int(ref ci) = consts::lit_to_constant(&l.node, cx.tcx, cx.tables.expr_ty(lit)); + if let Some(val) = ci.to_u64(); + if val == 1; + if cx.tables.expr_ty(exp).is_integral(); + then { + span_lint(cx, + NEG_MULTIPLY, + span, + "Negation by multiplying with -1"); + } + } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 1c5524af68e..53d6d3f2fb8 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -117,40 +117,41 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); - if_let_chain!{[ - same_tys(cx, self_ty, return_ty(cx, id)), - let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), - !implements_trait(cx, self_ty, default_trait_id, &[]) - ], { - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); - }); - } else { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_prepend_item(cx, - span, - "try this", - &format!( -"impl Default for {} {{ - fn default() -> Self {{ - Self::new() - }} -}}", - self_ty)); - }); + if_chain! { + if same_tys(cx, self_ty, return_ty(cx, id)); + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); + if !implements_trait(cx, self_ty, default_trait_id, &[]); + then { + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + }); + } else { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_prepend_item(cx, + span, + "try this", + &format!( + "impl Default for {} {{ + fn default() -> Self {{ + Self::new() + }} + }}", + self_ty)); + }); + } } - }} + } } } } diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 67d39333ff9..e6fe0631a63 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -43,21 +43,22 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ //begin checking variables - let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match - let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let - let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result.ok() - let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node, //get operation - method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized; - - ], { - let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT); - let some_expr_string = snippet(cx, y[0].span, ""); - if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type { - span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span, - "Matching on `Some` with `ok()` is redundant", - &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string)); + if_chain! { //begin checking variables + if let ExprMatch(ref op, ref body, ref source) = expr.node; //test if expr is a match + if let MatchSource::IfLetDesugar { .. } = *source; //test if it is an If Let + if let ExprMethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result.ok() + if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node; //get operation + if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; + + then { + let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT); + let some_expr_string = snippet(cx, y[0].span, ""); + if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type { + span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span, + "Matching on `Some` with `ok()` is redundant", + &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string)); + } } - }} + } } } diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index ee44cc70b43..4177f4a3e73 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -31,52 +31,54 @@ impl LintPass for OverflowCheckConditional { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node, - path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0], - cx.tables.expr_ty(ident1).is_integral(), - cx.tables.expr_ty(ident2).is_integral() - ], { - if let BinOp_::BiLt = op.node { - if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C overflow conditions that will fail in Rust."); + if_chain! { + if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node; + if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node; + if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0]; + if cx.tables.expr_ty(ident1).is_integral(); + if cx.tables.expr_ty(ident2).is_integral(); + then { + if let BinOp_::BiLt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, + "You are trying to use classic C overflow conditions that will fail in Rust."); + } } - } - if let BinOp_::BiGt = op.node { - if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C underflow conditions that will fail in Rust."); + if let BinOp_::BiGt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, + "You are trying to use classic C underflow conditions that will fail in Rust."); + } } } - }} + } - if_let_chain! {[ - let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node, - let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node, - let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node, - path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0], - cx.tables.expr_ty(ident1).is_integral(), - cx.tables.expr_ty(ident2).is_integral() - ], { - if let BinOp_::BiGt = op.node { - if let BinOp_::BiAdd = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C overflow conditions that will fail in Rust."); + if_chain! { + if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node; + if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; + if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node; + if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0]; + if cx.tables.expr_ty(ident1).is_integral(); + if cx.tables.expr_ty(ident2).is_integral(); + then { + if let BinOp_::BiGt = op.node { + if let BinOp_::BiAdd = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, + "You are trying to use classic C overflow conditions that will fail in Rust."); + } } - } - if let BinOp_::BiLt = op.node { - if let BinOp_::BiSub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C underflow conditions that will fail in Rust."); + if let BinOp_::BiLt = op.node { + if let BinOp_::BiSub = op2.node { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, + "You are trying to use classic C underflow conditions that will fail in Rust."); + } } } - }} + } } } diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index f0428534456..1a14a0bc45d 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -34,23 +34,24 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ - let ExprBlock(ref block) = expr.node, - let Some(ref ex) = block.expr, - let ExprCall(ref fun, ref params) = ex.node, - params.len() == 2, - let ExprPath(ref qpath) = fun.node, - let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), - match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC), - let ExprLit(ref lit) = params[0].node, - is_direct_expn_of(expr.span, "panic").is_some(), - let LitKind::Str(ref string, _) = lit.node, - let Some(par) = string.as_str().find('{'), - string.as_str()[par..].contains('}'), - params[0].span.source_callee().is_none() - ], { - span_lint(cx, PANIC_PARAMS, params[0].span, - "you probably are missing some parameter in your format string"); - }} + if_chain! { + if let ExprBlock(ref block) = expr.node; + if let Some(ref ex) = block.expr; + if let ExprCall(ref fun, ref params) = ex.node; + if params.len() == 2; + if let ExprPath(ref qpath) = fun.node; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); + if let ExprLit(ref lit) = params[0].node; + if is_direct_expn_of(expr.span, "panic").is_some(); + if let LitKind::Str(ref string, _) = lit.node; + if let Some(par) = string.as_str().find('{'); + if string.as_str()[par..].contains('}'); + if params[0].span.source_callee().is_none(); + then { + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); + } + } } } diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 34f1e4bc493..22dc43eb6c5 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -37,20 +37,21 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if_let_chain! {[ - let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node, - !is_automatically_derived(&*item.attrs), - let Some(eq_trait) = cx.tcx.lang_items().eq_trait(), - trait_ref.path.def.def_id() == eq_trait - ], { - for impl_item in impl_items { - if impl_item.name == "ne" { - span_lint(cx, - PARTIALEQ_NE_IMPL, - impl_item.span, - "re-implementing `PartialEq::ne` is unnecessary") + if_chain! { + if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node; + if !is_automatically_derived(&*item.attrs); + if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); + if trait_ref.path.def.def_id() == eq_trait; + then { + for impl_item in impl_items { + if impl_item.name == "ne" { + span_lint(cx, + PARTIALEQ_NE_IMPL, + impl_item.span, + "re-implementing `PartialEq::ne` is unnecessary") + } } } - }}; + }; } } diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index b7ccf19a313..ce6b96108a4 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -89,58 +89,60 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain! {[ - let ExprCall(ref fun, ref args) = expr.node, - let ExprPath(ref qpath) = fun.node, - let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)), - ], { - - // Search for `std::io::_print(..)` which is unique in a - // `print!` expansion. - if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { - if let Some(span) = is_expn_of(expr.span, "print") { - // `println!` uses `print!`. - let (span, name) = match is_expn_of(span, "println") { - Some(span) => (span, "println"), - None => (span, "print"), - }; - - span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - - if_let_chain!{[ - // ensure we're calling Arguments::new_v1 - args.len() == 1, - let ExprCall(ref args_fun, ref args_args) = args[0].node, - let ExprPath(ref qpath) = args_fun.node, - let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)), - match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1), - args_args.len() == 2, - let ExprAddrOf(_, ref match_expr) = args_args[1].node, - let ExprMatch(ref args, _, _) = match_expr.node, - let ExprTup(ref args) = args.node, - let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]), - ], { - match name { - "print" => check_print(cx, span, args, fmtstr, fmtlen), - "println" => check_println(cx, span, fmtstr, fmtlen), - _ => (), + if_chain! { + if let ExprCall(ref fun, ref args) = expr.node; + if let ExprPath(ref qpath) = fun.node; + if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); + then { + + // Search for `std::io::_print(..)` which is unique in a + // `print!` expansion. + if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { + if let Some(span) = is_expn_of(expr.span, "print") { + // `println!` uses `print!`. + let (span, name) = match is_expn_of(span, "println") { + Some(span) => (span, "println"), + None => (span, "print"), + }; + + span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); + + if_chain! { + // ensure we're calling Arguments::new_v1 + if args.len() == 1; + if let ExprCall(ref args_fun, ref args_args) = args[0].node; + if let ExprPath(ref qpath) = args_fun.node; + if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); + if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1); + if args_args.len() == 2; + if let ExprAddrOf(_, ref match_expr) = args_args[1].node; + if let ExprMatch(ref args, _, _) = match_expr.node; + if let ExprTup(ref args) = args.node; + if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); + then { + match name { + "print" => check_print(cx, span, args, fmtstr, fmtlen), + "println" => check_println(cx, span, fmtstr, fmtlen), + _ => (), + } + } } - }} + } } - } - // Search for something like - // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` - else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { - if let ExprPath(ref qpath) = args[1].node { - if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) - && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { - span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + // Search for something like + // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` + else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { + if let ExprPath(ref qpath) = args[1].node { + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) + && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { + span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } } } } } - }} + } } } @@ -152,36 +154,38 @@ fn check_print<'a, 'tcx>( fmtstr: InternedString, fmtlen: usize, ) { - if_let_chain!{[ + if_chain! { // check the final format string part - let Some('\n') = fmtstr.chars().last(), + if let Some('\n') = fmtstr.chars().last(); // "foo{}bar" is made into two strings + one argument, // if the format string starts with `{}` (eg. "{}foo"), // the string array is prepended an empty string "". // We only want to check the last string after any `{}`: - args.len() < fmtlen, - ], { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `print!()` with a format string that ends in a \ - newline, consider using `println!()` instead"); - }} + if args.len() < fmtlen; + then { + span_lint(cx, PRINT_WITH_NEWLINE, span, + "using `print!()` with a format string that ends in a \ + newline, consider using `println!()` instead"); + } + } } /// Check for println!("") fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) { - if_let_chain!{[ + if_chain! { // check that the string is empty - fmtlen == 1, - fmtstr.deref() == "\n", + if fmtlen == 1; + if fmtstr.deref() == "\n"; // check the presence of that string - let Ok(snippet) = cx.sess().codemap().span_to_snippet(span), - snippet.contains("\"\""), - ], { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `println!(\"\")`, consider using `println!()` instead"); - }} + if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); + if snippet.contains("\"\""); + then { + span_lint(cx, PRINT_WITH_NEWLINE, span, + "using `println!(\"\")`, consider using `println!()` instead"); + } + } } fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { @@ -202,14 +206,15 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { /// Returns the slice of format string parts in an `Arguments::new_v1` call. fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(InternedString, usize)> { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …] - let ExprArray(ref exprs) = expr.node, - let Some(expr) = exprs.last(), - let ExprLit(ref lit) = expr.node, - let LitKind::Str(ref lit, _) = lit.node, - ], { - return Some((lit.as_str(), exprs.len())); - }} + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; // &["…", "…", …] + if let ExprArray(ref exprs) = expr.node; + if let Some(expr) = exprs.last(); + if let ExprLit(ref lit) = expr.node; + if let LitKind::Str(ref lit, _) = lit.node; + then { + return Some((lit.as_str(), exprs.len())); + } + } None } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 8f42750e19b..916132daeff 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -156,13 +156,14 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< { if match_type(cx, ty, &paths::VEC) { let mut ty_snippet = None; - if_let_chain!([ - let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node, - let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last(), - parameters.types.len() == 1, - ], { - ty_snippet = snippet_opt(cx, parameters.types[0].span); - }); + if_chain! { + if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node; + if let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last(); + if parameters.types.len() == 1; + then { + ty_snippet = snippet_opt(cx, parameters.types[0].span); + } + }; if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { span_lint_and_then( cx, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index aff0c4b08ab..6e9bebca757 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -113,69 +113,72 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } else if name == "zip" && args.len() == 2 { let iter = &args[0].node; let zip_arg = &args[1]; - if_let_chain! {[ + if_chain! { // .iter() call - let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter, - iter_path.name == "iter", + if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter; + if iter_path.name == "iter"; // range expression in .zip() call: 0..x.len() - let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg), - is_integer_literal(start, 0), + if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg); + if is_integer_literal(start, 0); // .len() call - let ExprMethodCall(ref len_path, _, ref len_args) = end.node, - len_path.name == "len" && len_args.len() == 1, + if let ExprMethodCall(ref len_path, _, ref len_args) = end.node; + if len_path.name == "len" && len_args.len() == 1; // .iter() and .len() called on same Path - let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node, - let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node, - iter_path.segments == len_path.segments - ], { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - expr.span, - &format!("It is more idiomatic to use {}.iter().enumerate()", - snippet(cx, iter_args[0].span, "_"))); - }} + if let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; + if let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node; + if iter_path.segments == len_path.segments; + then { + span_lint(cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); + } + } } } // exclusive range plus one: x..(y+1) - if_let_chain! {[ - let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(expr), - let Some(y) = y_plus_one(end), - ], { - span_lint_and_then( - cx, - RANGE_PLUS_ONE, - expr.span, - "an inclusive range would be more readable", - |db| { - let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); - let end = Sugg::hir(cx, y, "y"); - db.span_suggestion(expr.span, - "use", - format!("{}..={}", start, end)); - }, - ); - }} + if_chain! { + if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(expr); + if let Some(y) = y_plus_one(end); + then { + span_lint_and_then( + cx, + RANGE_PLUS_ONE, + expr.span, + "an inclusive range would be more readable", + |db| { + let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let end = Sugg::hir(cx, y, "y"); + db.span_suggestion(expr.span, + "use", + format!("{}..={}", start, end)); + }, + ); + } + } // inclusive range minus one: x..=(y-1) - if_let_chain! {[ - let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr), - let Some(y) = y_minus_one(end), - ], { - span_lint_and_then( - cx, - RANGE_MINUS_ONE, - expr.span, - "an exclusive range would be more readable", - |db| { - let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); - let end = Sugg::hir(cx, y, "y"); - db.span_suggestion(expr.span, - "use", - format!("{}..{}", start, end)); - }, - ); - }} + if_chain! { + if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr); + if let Some(y) = y_minus_one(end); + then { + span_lint_and_then( + cx, + RANGE_MINUS_ONE, + expr.span, + "an exclusive range would be more readable", + |db| { + let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let end = Sugg::hir(cx, y, "y"); + db.span_suggestion(expr.span, + "use", + format!("{}..{}", start, end)); + }, + ); + } + } } } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index dc284001b1d..0c125825d8a 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -86,22 +86,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) { - if_let_chain!{[ - self.last.is_none(), - let Some(ref expr) = block.expr, - match_type(cx, cx.tables.expr_ty(expr), &paths::REGEX), - let Some(span) = is_expn_of(expr.span, "regex"), - ], { - if !self.spans.contains(&span) { - span_lint(cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now."); - self.spans.insert(span); + if_chain! { + if self.last.is_none(); + if let Some(ref expr) = block.expr; + if match_type(cx, cx.tables.expr_ty(expr), &paths::REGEX); + if let Some(span) = is_expn_of(expr.span, "regex"); + then { + if !self.spans.contains(&span) { + span_lint(cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now."); + self.spans.insert(span); + } + self.last = Some(block.id); } - self.last = Some(block.id); - }} + } } fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, block: &'tcx Block) { @@ -111,24 +112,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_let_chain!{[ - let ExprCall(ref fun, ref args) = expr.node, - let ExprPath(ref qpath) = fun.node, - args.len() == 1, - let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, fun.hir_id)), - ], { - if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || - match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { - check_regex(cx, &args[0], true); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_NEW) || - match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { - check_regex(cx, &args[0], false); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_SET_NEW) { - check_set(cx, &args[0], true); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_SET_NEW) { - check_set(cx, &args[0], false); + if_chain! { + if let ExprCall(ref fun, ref args) = expr.node; + if let ExprPath(ref qpath) = fun.node; + if args.len() == 1; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, fun.hir_id)); + then { + if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || + match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { + check_regex(cx, &args[0], true); + } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_NEW) || + match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { + check_regex(cx, &args[0], false); + } else if match_def_path(cx.tcx, def_id, &paths::REGEX_SET_NEW) { + check_set(cx, &args[0], true); + } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_SET_NEW) { + check_set(cx, &args[0], false); + } } - }} + } } } @@ -179,14 +181,15 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { } fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { - if_let_chain! {[ - let ExprAddrOf(_, ref expr) = expr.node, - let ExprArray(ref exprs) = expr.node, - ], { - for expr in exprs { - check_regex(cx, expr, utf8); + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; + if let ExprArray(ref exprs) = expr.node; + then { + for expr in exprs { + check_regex(cx, expr, utf8); + } } - }} + } } fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 0884ebbf5cf..98027885ccf 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -103,28 +103,29 @@ impl ReturnPass { let mut it = block.stmts.iter(); // we need both a let-binding stmt and an expr - if_let_chain! {[ - let Some(retexpr) = it.next_back(), - let ast::StmtKind::Expr(ref retexpr) = retexpr.node, - let Some(stmt) = it.next_back(), - let ast::StmtKind::Local(ref local) = stmt.node, + if_chain! { + if let Some(retexpr) = it.next_back(); + if let ast::StmtKind::Expr(ref retexpr) = retexpr.node; + if let Some(stmt) = it.next_back(); + if let ast::StmtKind::Local(ref local) = stmt.node; // don't lint in the presence of type inference - local.ty.is_none(), - !local.attrs.iter().any(attr_is_cfg), - let Some(ref initexpr) = local.init, - let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, - let ast::ExprKind::Path(_, ref path) = retexpr.node, - match_path_ast(path, &[&id.name.as_str()]), - !in_external_macro(cx, initexpr.span), - ], { - span_note_and_lint(cx, - LET_AND_RETURN, - retexpr.span, - "returning the result of a let binding from a block. \ - Consider returning the expression directly.", - initexpr.span, - "this expression can be directly returned"); - }} + if local.ty.is_none(); + if !local.attrs.iter().any(attr_is_cfg); + if let Some(ref initexpr) = local.init; + if let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node; + if let ast::ExprKind::Path(_, ref path) = retexpr.node; + if match_path_ast(path, &[&id.name.as_str()]); + if !in_external_macro(cx, initexpr.span); + then { + span_note_and_lint(cx, + LET_AND_RETURN, + retexpr.span, + "returning the result of a let binding from a block. \ + Consider returning the expression directly.", + initexpr.span, + "this expression can be directly returned"); + } + } } } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 6119e5008f3..6497bb9b443 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -59,120 +59,122 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap { /// Implementation of the `MANUAL_SWAP` lint. fn check_manual_swap(cx: &LateContext, block: &Block) { for w in block.stmts.windows(3) { - if_let_chain!{[ + if_chain! { // let t = foo(); - let StmtDecl(ref tmp, _) = w[0].node, - let DeclLocal(ref tmp) = tmp.node, - let Some(ref tmp_init) = tmp.init, - let PatKind::Binding(_, _, ref tmp_name, None) = tmp.pat.node, + if let StmtDecl(ref tmp, _) = w[0].node; + if let DeclLocal(ref tmp) = tmp.node; + if let Some(ref tmp_init) = tmp.init; + if let PatKind::Binding(_, _, ref tmp_name, None) = tmp.pat.node; // foo() = bar(); - let StmtSemi(ref first, _) = w[1].node, - let ExprAssign(ref lhs1, ref rhs1) = first.node, + if let StmtSemi(ref first, _) = w[1].node; + if let ExprAssign(ref lhs1, ref rhs1) = first.node; // bar() = t; - let StmtSemi(ref second, _) = w[2].node, - let ExprAssign(ref lhs2, ref rhs2) = second.node, - let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node, - rhs2.segments.len() == 1, - - tmp_name.node.as_str() == rhs2.segments[0].name.as_str(), - SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1), - SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2) - ], { - fn check_for_slice<'a>( - cx: &LateContext, - lhs1: &'a Expr, - lhs2: &'a Expr, - ) -> Option<(&'a Expr, &'a Expr, &'a Expr)> { - if let ExprIndex(ref lhs1, ref idx1) = lhs1.node { - if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { - let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); - - if matches!(ty.sty, ty::TySlice(_)) || - matches!(ty.sty, ty::TyArray(_, _)) || - match_type(cx, ty, &paths::VEC) || - match_type(cx, ty, &paths::VEC_DEQUE) { - return Some((lhs1, idx1, idx2)); + if let StmtSemi(ref second, _) = w[2].node; + if let ExprAssign(ref lhs2, ref rhs2) = second.node; + if let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node; + if rhs2.segments.len() == 1; + + if tmp_name.node.as_str() == rhs2.segments[0].name.as_str(); + if SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1); + if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2); + then { + fn check_for_slice<'a>( + cx: &LateContext, + lhs1: &'a Expr, + lhs2: &'a Expr, + ) -> Option<(&'a Expr, &'a Expr, &'a Expr)> { + if let ExprIndex(ref lhs1, ref idx1) = lhs1.node { + if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { + if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { + let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); + + if matches!(ty.sty, ty::TySlice(_)) || + matches!(ty.sty, ty::TyArray(_, _)) || + match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::VEC_DEQUE) { + return Some((lhs1, idx1, idx2)); + } } } } + + None } - - None - } - - let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) { - if let Some(slice) = Sugg::hir_opt(cx, slice) { - (false, - format!(" elements of `{}`", slice), - format!("{}.swap({}, {})", - slice.maybe_par(), - snippet(cx, idx1.span, ".."), - snippet(cx, idx2.span, ".."))) + + let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) { + if let Some(slice) = Sugg::hir_opt(cx, slice) { + (false, + format!(" elements of `{}`", slice), + format!("{}.swap({}, {})", + slice.maybe_par(), + snippet(cx, idx1.span, ".."), + snippet(cx, idx2.span, ".."))) + } else { + (false, "".to_owned(), "".to_owned()) + } + } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) { + (true, format!(" `{}` and `{}`", first, second), + format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr())) } else { - (false, "".to_owned(), "".to_owned()) - } - } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) { - (true, format!(" `{}` and `{}`", first, second), - format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr())) - } else { - (true, "".to_owned(), "".to_owned()) - }; - - let span = w[0].span.to(second.span); - - span_lint_and_then(cx, - MANUAL_SWAP, - span, - &format!("this looks like you are swapping{} manually", what), - |db| { - if !sugg.is_empty() { - db.span_suggestion(span, "try", sugg); - - if replace { - db.note("or maybe you should use `std::mem::replace`?"); + (true, "".to_owned(), "".to_owned()) + }; + + let span = w[0].span.to(second.span); + + span_lint_and_then(cx, + MANUAL_SWAP, + span, + &format!("this looks like you are swapping{} manually", what), + |db| { + if !sugg.is_empty() { + db.span_suggestion(span, "try", sugg); + + if replace { + db.note("or maybe you should use `std::mem::replace`?"); + } } - } - }); - }} + }); + } + } } } /// Implementation of the `ALMOST_SWAPPED` lint. fn check_suspicious_swap(cx: &LateContext, block: &Block) { for w in block.stmts.windows(2) { - if_let_chain!{[ - let StmtSemi(ref first, _) = w[0].node, - let StmtSemi(ref second, _) = w[1].node, - !differing_macro_contexts(first.span, second.span), - let ExprAssign(ref lhs0, ref rhs0) = first.node, - let ExprAssign(ref lhs1, ref rhs1) = second.node, - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1), - SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0) - ], { - let lhs0 = Sugg::hir_opt(cx, lhs0); - let rhs0 = Sugg::hir_opt(cx, rhs0); - let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) { - (format!(" `{}` and `{}`", first, second), first.mut_addr().to_string(), second.mut_addr().to_string()) - } else { - ("".to_owned(), "".to_owned(), "".to_owned()) - }; - - let span = first.span.to(second.span); - - span_lint_and_then(cx, - ALMOST_SWAPPED, - span, - &format!("this looks like you are trying to swap{}", what), - |db| { - if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap({}, {})", lhs, rhs)); - db.note("or maybe you should use `std::mem::replace`?"); - } - }); - }} + if_chain! { + if let StmtSemi(ref first, _) = w[0].node; + if let StmtSemi(ref second, _) = w[1].node; + if !differing_macro_contexts(first.span, second.span); + if let ExprAssign(ref lhs0, ref rhs0) = first.node; + if let ExprAssign(ref lhs1, ref rhs1) = second.node; + if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1); + if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0); + then { + let lhs0 = Sugg::hir_opt(cx, lhs0); + let rhs0 = Sugg::hir_opt(cx, rhs0); + let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) { + (format!(" `{}` and `{}`", first, second), first.mut_addr().to_string(), second.mut_addr().to_string()) + } else { + ("".to_owned(), "".to_owned(), "".to_owned()) + }; + + let span = first.span.to(second.span); + + span_lint_and_then(cx, + ALMOST_SWAPPED, + span, + &format!("this looks like you are trying to swap{}", what), + |db| { + if !what.is_empty() { + db.span_suggestion(span, "try", + format!("std::mem::swap({}, {})", lhs, rhs)); + db.note("or maybe you should use `std::mem::replace`?"); + } + }); + } + } } } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index a97c24166b4..f816ddc464f 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -301,14 +301,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { /// lifetime, but it should be rare. fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { let seg = last_path_segment(path); - if_let_chain!{[ - let Some(ref params) = seg.parameters, - !params.parenthesized, - let Some(to_ty) = params.types.get(1), - let TyRptr(_, ref to_ty) = to_ty.node, - ], { - return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); - }} + if_chain! { + if let Some(ref params) = seg.parameters; + if !params.parenthesized; + if let Some(to_ty) = params.types.get(1); + if let TyRptr(_, ref to_ty) = to_ty.node; + then { + return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); + } + } to_rty.to_string() } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 44aab3917c7..96caea5c17d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -158,21 +158,22 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { if let Some(def_id) = opt_def_id(def) { if Some(def_id) == cx.tcx.lang_items().owned_box() { let last = last_path_segment(qpath); - if_let_chain! {[ - let Some(ref params) = last.parameters, - !params.parenthesized, - let Some(vec) = params.types.get(0), - let TyPath(ref qpath) = vec.node, - let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))), - match_def_path(cx.tcx, did, &paths::VEC), - ], { - span_help_and_lint(cx, - BOX_VEC, - ast_ty.span, - "you seem to be trying to use `Box>`. Consider using just `Vec`", - "`Vec` is already on the heap, `Box>` makes an extra allocation."); - return; // don't recurse into the type - }} + if_chain! { + if let Some(ref params) = last.parameters; + if !params.parenthesized; + if let Some(vec) = params.types.get(0); + if let TyPath(ref qpath) = vec.node; + if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))); + if match_def_path(cx.tcx, did, &paths::VEC); + then { + span_help_and_lint(cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box>`. Consider using just `Vec`", + "`Vec` is already on the heap, `Box>` makes an extra allocation."); + return; // don't recurse into the type + } + } } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) { span_help_and_lint( cx, @@ -227,39 +228,40 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti TyPath(ref qpath) => { let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id); let def = cx.tables.qpath_def(qpath, hir_id); - if_let_chain! {[ - let Some(def_id) = opt_def_id(def), - Some(def_id) == cx.tcx.lang_items().owned_box(), - let QPath::Resolved(None, ref path) = *qpath, - let [ref bx] = *path.segments, - let Some(ref params) = bx.parameters, - !params.parenthesized, - let [ref inner] = *params.types - ], { - if is_any_trait(inner) { - // Ignore `Box` types, see #1884 for details. - return; + if_chain! { + if let Some(def_id) = opt_def_id(def); + if Some(def_id) == cx.tcx.lang_items().owned_box(); + if let QPath::Resolved(None, ref path) = *qpath; + if let [ref bx] = *path.segments; + if let Some(ref params) = bx.parameters; + if !params.parenthesized; + if let [ref inner] = *params.types; + then { + if is_any_trait(inner) { + // Ignore `Box` types, see #1884 for details. + return; + } + + let ltopt = if lt.is_elided() { + "".to_owned() + } else { + format!("{} ", lt.name.name().as_str()) + }; + let mutopt = if mut_ty.mutbl == Mutability::MutMutable { + "mut " + } else { + "" + }; + span_lint_and_sugg(cx, + BORROWED_BOX, + ast_ty.span, + "you seem to be trying to use `&Box`. Consider using just `&T`", + "try", + format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")) + ); + return; // don't recurse into the type } - - let ltopt = if lt.is_elided() { - "".to_owned() - } else { - format!("{} ", lt.name.name().as_str()) - }; - let mutopt = if mut_ty.mutbl == Mutability::MutMutable { - "mut " - } else { - "" - }; - span_lint_and_sugg(cx, - BORROWED_BOX, - ast_ty.span, - "you seem to be trying to use `&Box`. Consider using just `&T`", - "try", - format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")) - ); - return; // don't recurse into the type - }}; + }; check_ty(cx, &mut_ty.ty, is_local); }, _ => check_ty(cx, &mut_ty.ty, is_local), @@ -268,15 +270,16 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti // Returns true if given type is `Any` trait. fn is_any_trait(t: &hir::Ty) -> bool { - if_let_chain! {[ - let TyTraitObject(ref traits, _) = t.node, - traits.len() >= 1, + if_chain! { + if let TyTraitObject(ref traits, _) = t.node; + if traits.len() >= 1; // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. - match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT) - ], { - return true; - }} + if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT); + then { + return true; + } + } false } @@ -1719,43 +1722,44 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' } fn visit_expr(&mut self, e: &'tcx Expr) { - if_let_chain!{[ - let ExprCall(ref fun, ref args) = e.node, - let ExprPath(QPath::TypeRelative(ref ty, ref method)) = fun.node, - let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node, - ], { - if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { - return; - } - - if match_path(ty_path, &paths::HASHMAP) { - if method.name == "new" { - self.suggestions - .insert(e.span, "HashMap::default()".to_string()); - } else if method.name == "with_capacity" { - self.suggestions.insert( - e.span, - format!( - "HashMap::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); + if_chain! { + if let ExprCall(ref fun, ref args) = e.node; + if let ExprPath(QPath::TypeRelative(ref ty, ref method)) = fun.node; + if let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node; + then { + if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { + return; } - } else if match_path(ty_path, &paths::HASHSET) { - if method.name == "new" { - self.suggestions - .insert(e.span, "HashSet::default()".to_string()); - } else if method.name == "with_capacity" { - self.suggestions.insert( - e.span, - format!( - "HashSet::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); + + if match_path(ty_path, &paths::HASHMAP) { + if method.name == "new" { + self.suggestions + .insert(e.span, "HashMap::default()".to_string()); + } else if method.name == "with_capacity" { + self.suggestions.insert( + e.span, + format!( + "HashMap::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } else if match_path(ty_path, &paths::HASHSET) { + if method.name == "new" { + self.suggestions + .insert(e.span, "HashSet::default()".to_string()); + } else if method.name == "with_capacity" { + self.suggestions.insert( + e.span, + format!( + "HashSet::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } } } - }} + } walk_expr(self, e); } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 946df625cb6..985b52b4f53 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -54,26 +54,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if in_macro(item.span) { return; } - if_let_chain!([ - let ItemImpl(.., ref item_type, ref refs) = item.node, - let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node, - ], { - let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; - let should_check = if let Some(ref params) = *parameters { - !params.parenthesized && params.lifetimes.len() == 0 - } else { - true - }; - if should_check { - let visitor = &mut UseSelfVisitor { - item_path: item_path, - cx: cx, + if_chain! { + if let ItemImpl(.., ref item_type, ref refs) = item.node; + if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node; + then { + let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; + let should_check = if let Some(ref params) = *parameters { + !params.parenthesized && params.lifetimes.len() == 0 + } else { + true }; - for impl_item_ref in refs { - visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + if should_check { + let visitor = &mut UseSelfVisitor { + item_path: item_path, + cx: cx, + }; + for impl_item_ref in refs { + visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + } } } - }) + } } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d162dea7f11..93afb449cf6 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -120,13 +120,14 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // // do stuff // } // ``` - if_let_chain! {[ - let hir::DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node, - ], { - return true; - }} + if_chain! { + if let hir::DeclLocal(ref loc) = decl.node; + if let Some(ref expr) = loc.init; + if let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node; + then { + return true; + } + } // This detects a variable binding in for loop to avoid `let_unit_value` // lint (see issue #1964). @@ -136,12 +137,13 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // // anything // } // ``` - if_let_chain! {[ - let hir::DeclLocal(ref loc) = decl.node, - let hir::LocalSource::ForLoopDesugar = loc.source, - ], { - return true; - }} + if_chain! { + if let hir::DeclLocal(ref loc) = decl.node; + if let hir::LocalSource::ForLoopDesugar = loc.source; + then { + return true; + } + } false } @@ -149,19 +151,20 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { /// Recover the essential nodes of a desugared for loop: /// `for pat in arg { body }` becomes `(pat, arg, body)`. pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { - if_let_chain! {[ - let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node, - let hir::ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let hir::ExprLoop(ref block, _, _) = arms[0].body.node, - block.expr.is_none(), - let [ _, _, ref let_stmt, ref body ] = *block.stmts, - let hir::StmtDecl(ref decl, _) = let_stmt.node, - let hir::DeclLocal(ref decl) = decl.node, - let hir::StmtExpr(ref expr, _) = body.node, - ], { - return Some((&*decl.pat, &iterargs[0], expr)); - }} + if_chain! { + if let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node; + if let hir::ExprCall(_, ref iterargs) = iterexpr.node; + if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(); + if let hir::ExprLoop(ref block, _, _) = arms[0].body.node; + if block.expr.is_none(); + if let [ _, _, ref let_stmt, ref body ] = *block.stmts; + if let hir::StmtDecl(ref decl, _) = let_stmt.node; + if let hir::DeclLocal(ref decl) = decl.node; + if let hir::StmtExpr(ref expr, _) = body.node; + then { + return Some((&*decl.pat, &iterargs[0], expr)); + } + } None } @@ -176,31 +179,33 @@ pub enum VecArgs<'a> { /// Returns the arguments of the `vec!` macro if this expression was expanded /// from `vec!`. pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option> { - if_let_chain!{[ - let hir::ExprCall(ref fun, ref args) = expr.node, - let hir::ExprPath(ref path) = fun.node, - is_expn_of(fun.span, "vec").is_some(), - let Some(fun_def_id) = opt_def_id(resolve_node(cx, path, fun.hir_id)), - ], { - return if match_def_path(cx.tcx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 { - // `vec![elem; size]` case - Some(VecArgs::Repeat(&args[0], &args[1])) - } - else if match_def_path(cx.tcx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { - // `vec![a, b, c]` case - if_let_chain!{[ - let hir::ExprBox(ref boxed) = args[0].node, - let hir::ExprArray(ref args) = boxed.node - ], { - return Some(VecArgs::Vec(&*args)); - }} - - None + if_chain! { + if let hir::ExprCall(ref fun, ref args) = expr.node; + if let hir::ExprPath(ref path) = fun.node; + if is_expn_of(fun.span, "vec").is_some(); + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, path, fun.hir_id)); + then { + return if match_def_path(cx.tcx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 { + // `vec![elem; size]` case + Some(VecArgs::Repeat(&args[0], &args[1])) + } + else if match_def_path(cx.tcx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { + // `vec![a, b, c]` case + if_chain! { + if let hir::ExprBox(ref boxed) = args[0].node; + if let hir::ExprArray(ref args) = boxed.node; + then { + return Some(VecArgs::Vec(&*args)); + } + } + + None + } + else { + None + }; } - else { - None - }; - }} + } None } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index cf3bf41a925..9bc87dee68c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1004,13 +1004,14 @@ pub fn is_self(slf: &Arg) -> bool { } pub fn is_self_ty(slf: &hir::Ty) -> bool { - if_let_chain! {[ - let TyPath(ref qp) = slf.node, - let QPath::Resolved(None, ref path) = *qp, - let Def::SelfTy(..) = path.def, - ], { - return true - }} + if_chain! { + if let TyPath(ref qp) = slf.node; + if let QPath::Resolved(None, ref path) = *qp; + if let Def::SelfTy(..) = path.def; + then { + return true + } + } false } @@ -1022,16 +1023,17 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl, body: &'tcx Body) -> impl Iterator Option<&Expr> { fn is_ok(arm: &Arm) -> bool { - if_let_chain! {[ - let PatKind::TupleStruct(ref path, ref pat, None) = arm.pats[0].node, - match_qpath(path, &paths::RESULT_OK[1..]), - let PatKind::Binding(_, defid, _, None) = pat[0].node, - let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node, - let Def::Local(lid) = path.def, - lid == defid, - ], { - return true; - }} + if_chain! { + if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pats[0].node; + if match_qpath(path, &paths::RESULT_OK[1..]); + if let PatKind::Binding(_, defid, _, None) = pat[0].node; + if let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node; + if let Def::Local(lid) = path.def; + if lid == defid; + then { + return true; + } + } false } @@ -1049,15 +1051,16 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { return Some(expr); } - if_let_chain! {[ - arms.len() == 2, - arms[0].pats.len() == 1 && arms[0].guard.is_none(), - arms[1].pats.len() == 1 && arms[1].guard.is_none(), - (is_ok(&arms[0]) && is_err(&arms[1])) || - (is_ok(&arms[1]) && is_err(&arms[0])), - ], { - return Some(expr); - }} + if_chain! { + if arms.len() == 2; + if arms[0].pats.len() == 1 && arms[0].guard.is_none(); + if arms[1].pats.len() == 1 && arms[1].guard.is_none(); + if (is_ok(&arms[0]) && is_err(&arms[1])) || + (is_ok(&arms[1]) && is_err(&arms[0])); + then { + return Some(expr); + } + } } None diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 6044eaac376..90a6896b348 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -35,25 +35,27 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` - if_let_chain!{[ - let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty, - let ty::TySlice(..) = ty.ty.sty, - let ExprAddrOf(_, ref addressee) = expr.node, - let Some(vec_args) = higher::vec_macro(cx, addressee), - ], { - check_vec_macro(cx, &vec_args, expr.span); - }} + if_chain! { + if let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty; + if let ty::TySlice(..) = ty.ty.sty; + if let ExprAddrOf(_, ref addressee) = expr.node; + if let Some(vec_args) = higher::vec_macro(cx, addressee); + then { + check_vec_macro(cx, &vec_args, expr.span); + } + } // search for `for _ in vec![…]` - if_let_chain!{[ - let Some((_, arg, _)) = higher::for_loop(expr), - let Some(vec_args) = higher::vec_macro(cx, arg), - is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))), - ], { - // report the error around the `vec!` not inside `:` - let span = arg.span.ctxt().outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); - check_vec_macro(cx, &vec_args, span); - }} + if_chain! { + if let Some((_, arg, _)) = higher::for_loop(expr); + if let Some(vec_args) = higher::vec_macro(cx, arg); + if is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))); + then { + // report the error around the `vec!` not inside `:` + let span = arg.span.ctxt().outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); + check_vec_macro(cx, &vec_args, span); + } + } } } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 5ff9fb9ffd5..313af61bf15 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -31,27 +31,28 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // check for instances of 0.0/0.0 - if_let_chain! {[ - let ExprBinary(ref op, ref left, ref right) = expr.node, - let BinOp_::BiDiv = op.node, + if_chain! { + if let ExprBinary(ref op, ref left, ref right) = expr.node; + if let BinOp_::BiDiv = op.node; // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(cx, left), - let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(cx, right), - Ok(0.0) == lhs_value.parse(), - Ok(0.0) == rhs_value.parse() - ], { - // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, - // match the precision of the literals that are given. - let float_type = match (lhs_width, rhs_width) { - (FloatWidth::F64, _) - | (_, FloatWidth::F64) => "f64", - _ => "f32" - }; - span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, - "constant division of 0.0 with 0.0 will always result in NaN", - &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); - }} + if let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(cx, left); + if let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(cx, right); + if Ok(0.0) == lhs_value.parse(); + if Ok(0.0) == rhs_value.parse(); + then { + // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, + // match the precision of the literals that are given. + let float_type = match (lhs_width, rhs_width) { + (FloatWidth::F64, _) + | (_, FloatWidth::F64) => "f64", + _ => "f32" + }; + span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, + "constant division of 0.0 with 0.0 will always result in NaN", + &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); + } + } } } -- cgit 1.4.1-3-g733a5 From 2153d1e560a2de06ddd60f29df86c342f1f83a90 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 23 Oct 2017 15:20:37 -0400 Subject: manual fixups if_let_chain -> if_chain --- clippy_lints/src/assign_ops.rs | 13 +-- clippy_lints/src/new_without_default.rs | 10 +-- clippy_lints/src/utils/author.rs | 136 ++++++++++++++++---------------- tests/ui/trailing_zeros.stdout | 29 +++---- 4 files changed, 96 insertions(+), 92 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 33a1d94f420..ab9ba4a9327 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -140,12 +140,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let parent_fn = cx.tcx.hir.get_parent(e.id); let parent_impl = cx.tcx.hir.get_parent(parent_fn); // the crate node is the only one that is not in the map - if_let_chain!{[ - parent_impl != ast::CRATE_NODE_ID, - let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl), - let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node, - trait_ref.path.def.def_id() == trait_id - ], { return; }} + if_chain! { + if parent_impl != ast::CRATE_NODE_ID; + if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); + if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; + if trait_ref.path.def.def_id() == trait_id; + then { return; } + } implements_trait($cx, $ty, trait_id, &[$rty]) },)* _ => false, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 53d6d3f2fb8..31a9de871b4 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -142,11 +142,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { span, "try this", &format!( - "impl Default for {} {{ - fn default() -> Self {{ - Self::new() - }} - }}", +"impl Default for {} {{ + fn default() -> Self {{ + Self::new() + }} +}}", self_ty)); }); } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index fafb6d12d1f..a4bdcd15290 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -28,15 +28,16 @@ use std::collections::HashMap; /// prints /// /// ``` -/// if_let_chain!{[ -/// let Expr_::ExprIf(ref cond, ref then, None) = item.node, -/// let Expr_::ExprBinary(BinOp::Eq, ref left, ref right) = cond.node, -/// let Expr_::ExprPath(ref path) = left.node, -/// let Expr_::ExprLit(ref lit) = right.node, -/// let LitKind::Int(42, _) = lit.node, -/// ], { -/// // report your lint here -/// }} +/// if_chain!{ +/// if let Expr_::ExprIf(ref cond, ref then, None) = item.node, +/// if let Expr_::ExprBinary(BinOp::Eq, ref left, ref right) = cond.node, +/// if let Expr_::ExprPath(ref path) = left.node, +/// if let Expr_::ExprLit(ref lit) = right.node, +/// if let LitKind::Int(42, _) = lit.node, +/// then { +/// // report your lint here +/// } +/// } /// ``` declare_lint! { pub LINT_AUTHOR, @@ -53,13 +54,14 @@ impl LintPass for Pass { } fn prelude() { - println!("if_let_chain!{{["); + println!("if_chain! {{"); } fn done() { - println!("], {{"); - println!(" // report your lint here"); - println!("}}}}"); + println!(" then {{"); + println!(" // report your lint here"); + println!(" }}"); + println!("}}"); } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { @@ -181,36 +183,36 @@ struct PrintVisitor { impl<'tcx> Visitor<'tcx> for PrintVisitor { fn visit_expr(&mut self, expr: &Expr) { - print!(" let Expr_::Expr"); + print!(" if let Expr_::Expr"); let current = format!("{}.node", self.current); match expr.node { Expr_::ExprBox(ref inner) => { let inner_pat = self.next("inner"); - println!("Box(ref {}) = {},", inner_pat, current); + println!("Box(ref {}) = {};", inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, Expr_::ExprArray(ref elements) => { let elements_pat = self.next("elements"); - println!("Array(ref {}) = {},", elements_pat, current); - println!(" {}.len() == {},", elements_pat, elements.len()); + println!("Array(ref {}) = {};", elements_pat, current); + println!(" if {}.len() == {};", elements_pat, elements.len()); for (i, element) in elements.iter().enumerate() { self.current = format!("{}[{}]", elements_pat, i); self.visit_expr(element); } }, Expr_::ExprCall(ref _func, ref _args) => { - println!("Call(ref func, ref args) = {},", current); + println!("Call(ref func, ref args) = {};", current); println!(" // unimplemented: `ExprCall` is not further destructured at the moment"); }, Expr_::ExprMethodCall(ref _method_name, ref _generics, ref _args) => { - println!("MethodCall(ref method_name, ref generics, ref args) = {},", current); + println!("MethodCall(ref method_name, ref generics, ref args) = {};", current); println!(" // unimplemented: `ExprMethodCall` is not further destructured at the moment"); }, Expr_::ExprTup(ref elements) => { let elements_pat = self.next("elements"); - println!("Tup(ref {}) = {},", elements_pat, current); - println!(" {}.len() == {},", elements_pat, elements.len()); + println!("Tup(ref {}) = {};", elements_pat, current); + println!(" if {}.len() == {};", elements_pat, elements.len()); for (i, element) in elements.iter().enumerate() { self.current = format!("{}[{}]", elements_pat, i); self.visit_expr(element); @@ -220,8 +222,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let op_pat = self.next("op"); let left_pat = self.next("left"); let right_pat = self.next("right"); - println!("Binary(ref {}, ref {}, ref {}) = {},", op_pat, left_pat, right_pat, current); - println!(" BinOp_::{:?} == {}.node,", op.node, op_pat); + println!("Binary(ref {}, ref {}, ref {}) = {};", op_pat, left_pat, right_pat, current); + println!(" if BinOp_::{:?} == {}.node;", op.node, op_pat); self.current = left_pat; self.visit_expr(left); self.current = right_pat; @@ -229,42 +231,42 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, Expr_::ExprUnary(ref op, ref inner) => { let inner_pat = self.next("inner"); - println!("Unary(UnOp::{:?}, ref {}) = {},", op, inner_pat, current); + println!("Unary(UnOp::{:?}, ref {}) = {};", op, inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, Expr_::ExprLit(ref lit) => { let lit_pat = self.next("lit"); - println!("Lit(ref {}) = {},", lit_pat, current); + println!("Lit(ref {}) = {};", lit_pat, current); match lit.node { - LitKind::Bool(val) => println!(" let LitKind::Bool({:?}) = {}.node,", val, lit_pat), - LitKind::Char(c) => println!(" let LitKind::Char({:?}) = {}.node,", c, lit_pat), - LitKind::Byte(b) => println!(" let LitKind::Byte({}) = {}.node,", b, lit_pat), + LitKind::Bool(val) => println!(" if let LitKind::Bool({:?}) = {}.node;", val, lit_pat), + LitKind::Char(c) => println!(" if let LitKind::Char({:?}) = {}.node;", c, lit_pat), + LitKind::Byte(b) => println!(" if let LitKind::Byte({}) = {}.node;", b, lit_pat), // FIXME: also check int type - LitKind::Int(i, _) => println!(" let LitKind::Int({}, _) = {}.node,", i, lit_pat), - LitKind::Float(..) => println!(" let LitKind::Float(..) = {}.node,", lit_pat), - LitKind::FloatUnsuffixed(_) => println!(" let LitKind::FloatUnsuffixed(_) = {}.node,", lit_pat), + LitKind::Int(i, _) => println!(" if let LitKind::Int({}, _) = {}.node;", i, lit_pat), + LitKind::Float(..) => println!(" if let LitKind::Float(..) = {}.node;", lit_pat), + LitKind::FloatUnsuffixed(_) => println!(" if let LitKind::FloatUnsuffixed(_) = {}.node;", lit_pat), LitKind::ByteStr(ref vec) => { let vec_pat = self.next("vec"); - println!(" let LitKind::ByteStr(ref {}) = {}.node,", vec_pat, lit_pat); - println!(" let [{:?}] = **{},", vec, vec_pat); + println!(" if let LitKind::ByteStr(ref {}) = {}.node;", vec_pat, lit_pat); + println!(" if let [{:?}] = **{};", vec, vec_pat); }, LitKind::Str(ref text, _) => { let str_pat = self.next("s"); - println!(" let LitKind::Str(ref {}) = {}.node,", str_pat, lit_pat); - println!(" {}.as_str() == {:?}", str_pat, &*text.as_str()) + println!(" if let LitKind::Str(ref {}) = {}.node;", str_pat, lit_pat); + println!(" if {}.as_str() == {:?}", str_pat, &*text.as_str()) }, } }, Expr_::ExprCast(ref expr, ref _ty) => { let cast_pat = self.next("expr"); - println!("Cast(ref {}, _) = {},", cast_pat, current); + println!("Cast(ref {}, _) = {};", cast_pat, current); self.current = cast_pat; self.visit_expr(expr); }, Expr_::ExprType(ref expr, ref _ty) => { let cast_pat = self.next("expr"); - println!("Type(ref {}, _) = {},", cast_pat, current); + println!("Type(ref {}, _) = {};", cast_pat, current); self.current = cast_pat; self.visit_expr(expr); }, @@ -273,11 +275,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let then_pat = self.next("then"); if let Some(ref else_) = *opt_else { let else_pat = self.next("else_"); - println!("If(ref {}, ref {}, Some(ref {})) = {},", cond_pat, then_pat, else_pat, current); + println!("If(ref {}, ref {}, Some(ref {})) = {};", cond_pat, then_pat, else_pat, current); self.current = else_pat; self.visit_expr(else_); } else { - println!("If(ref {}, ref {}, None) = {},", cond_pat, then_pat, current); + println!("If(ref {}, ref {}, None) = {};", cond_pat, then_pat, current); } self.current = cond_pat; self.visit_expr(cond); @@ -285,37 +287,37 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(then); }, Expr_::ExprWhile(ref _cond, ref _body, ref _opt_label) => { - println!("While(ref cond, ref body, ref opt_label) = {},", current); + println!("While(ref cond, ref body, ref opt_label) = {};", current); println!(" // unimplemented: `ExprWhile` is not further destructured at the moment"); }, Expr_::ExprLoop(ref _body, ref _opt_label, ref _desuraging) => { - println!("Loop(ref body, ref opt_label, ref desugaring) = {},", current); + println!("Loop(ref body, ref opt_label, ref desugaring) = {};", current); println!(" // unimplemented: `ExprLoop` is not further destructured at the moment"); }, Expr_::ExprMatch(ref _expr, ref _arms, ref _desugaring) => { - println!("Match(ref expr, ref arms, ref desugaring) = {},", current); + println!("Match(ref expr, ref arms, ref desugaring) = {};", current); println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); }, Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { - println!("Closure(ref capture_clause, ref func, _, _, _) = {},", current); + println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current); println!(" // unimplemented: `ExprClosure` is not further destructured at the moment"); }, Expr_::ExprYield(ref sub) => { let sub_pat = self.next("sub"); - println!("Yield(ref sub) = {},", current); + println!("Yield(ref sub) = {};", current); self.current = sub_pat; self.visit_expr(sub); }, Expr_::ExprBlock(ref block) => { let block_pat = self.next("block"); - println!("Block(ref {}) = {},", block_pat, current); + println!("Block(ref {}) = {};", block_pat, current); self.current = block_pat; self.visit_block(block); }, Expr_::ExprAssign(ref target, ref value) => { let target_pat = self.next("target"); let value_pat = self.next("value"); - println!("Assign(ref {}, ref {}) = {},", target_pat, value_pat, current); + println!("Assign(ref {}, ref {}) = {};", target_pat, value_pat, current); self.current = target_pat; self.visit_expr(target); self.current = value_pat; @@ -325,8 +327,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let op_pat = self.next("op"); let target_pat = self.next("target"); let value_pat = self.next("value"); - println!("AssignOp(ref {}, ref {}, ref {}) = {},", op_pat, target_pat, value_pat, current); - println!(" BinOp_::{:?} == {}.node,", op.node, op_pat); + println!("AssignOp(ref {}, ref {}, ref {}) = {};", op_pat, target_pat, value_pat, current); + println!(" if BinOp_::{:?} == {}.node;", op.node, op_pat); self.current = target_pat; self.visit_expr(target); self.current = value_pat; @@ -335,23 +337,23 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { Expr_::ExprField(ref object, ref field_name) => { let obj_pat = self.next("object"); let field_name_pat = self.next("field_name"); - println!("Field(ref {}, ref {}) = {},", obj_pat, field_name_pat, current); - println!(" {}.node.as_str() == {:?}", field_name_pat, field_name.node.as_str()); + println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current); + println!(" if {}.node.as_str() == {:?}", field_name_pat, field_name.node.as_str()); self.current = obj_pat; self.visit_expr(object); }, Expr_::ExprTupField(ref object, ref field_id) => { let obj_pat = self.next("object"); let field_id_pat = self.next("field_id"); - println!("TupField(ref {}, ref {}) = {},", obj_pat, field_id_pat, current); - println!(" {}.node == {}", field_id_pat, field_id.node); + println!("TupField(ref {}, ref {}) = {};", obj_pat, field_id_pat, current); + println!(" if {}.node == {}", field_id_pat, field_id.node); self.current = obj_pat; self.visit_expr(object); }, Expr_::ExprIndex(ref object, ref index) => { let object_pat = self.next("object"); let index_pat = self.next("index"); - println!("Index(ref {}, ref {}) = {},", object_pat, index_pat, current); + println!("Index(ref {}, ref {}) = {};", object_pat, index_pat, current); self.current = object_pat; self.visit_expr(object); self.current = index_pat; @@ -359,13 +361,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, Expr_::ExprPath(ref path) => { let path_pat = self.next("path"); - println!("Path(ref {}) = {},", path_pat, current); + println!("Path(ref {}) = {};", path_pat, current); self.current = path_pat; self.visit_qpath(path, expr.id, expr.span); }, Expr_::ExprAddrOf(mutability, ref inner) => { let inner_pat = self.next("inner"); - println!("AddrOf({:?}, ref {}) = {},", mutability, inner_pat, current); + println!("AddrOf({:?}, ref {}) = {};", mutability, inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, @@ -373,29 +375,29 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let destination_pat = self.next("destination"); if let Some(ref value) = *opt_value { let value_pat = self.next("value"); - println!("Break(ref {}, Some(ref {})) = {},", destination_pat, value_pat, current); + println!("Break(ref {}, Some(ref {})) = {};", destination_pat, value_pat, current); self.current = value_pat; self.visit_expr(value); } else { - println!("Break(ref {}, None) = {},", destination_pat, current); + println!("Break(ref {}, None) = {};", destination_pat, current); } // FIXME: implement label printing }, Expr_::ExprAgain(ref _destination) => { let destination_pat = self.next("destination"); - println!("Again(ref {}) = {},", destination_pat, current); + println!("Again(ref {}) = {};", destination_pat, current); // FIXME: implement label printing }, Expr_::ExprRet(ref opt_value) => if let Some(ref value) = *opt_value { let value_pat = self.next("value"); - println!("Ret(Some(ref {})) = {},", value_pat, current); + println!("Ret(Some(ref {})) = {};", value_pat, current); self.current = value_pat; self.visit_expr(value); } else { - println!("Ret(None) = {},", current); + println!("Ret(None) = {};", current); }, Expr_::ExprInlineAsm(_, ref _input, ref _output) => { - println!("InlineAsm(_, ref input, ref output) = {},", current); + println!("InlineAsm(_, ref input, ref output) = {};", current); println!(" // unimplemented: `ExprInlineAsm` is not further destructured at the moment"); }, Expr_::ExprStruct(ref path, ref fields, ref opt_base) => { @@ -404,7 +406,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { if let Some(ref base) = *opt_base { let base_pat = self.next("base"); println!( - "Struct(ref {}, ref {}, Some(ref {})) = {},", + "Struct(ref {}, ref {}, Some(ref {})) = {};", path_pat, fields_pat, base_pat, @@ -413,17 +415,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = base_pat; self.visit_expr(base); } else { - println!("Struct(ref {}, ref {}, None) = {},", path_pat, fields_pat, current); + println!("Struct(ref {}, ref {}, None) = {};", path_pat, fields_pat, current); } self.current = path_pat; self.visit_qpath(path, expr.id, expr.span); - println!(" {}.len() == {},", fields_pat, fields.len()); + println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, // FIXME: compute length (needs type info) Expr_::ExprRepeat(ref value, _) => { let value_pat = self.next("value"); - println!("Repeat(ref {}, _) = {},", value_pat, current); + println!("Repeat(ref {}, _) = {};", value_pat, current); println!("// unimplemented: repeat count check"); self.current = value_pat; self.visit_expr(value); @@ -432,9 +434,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } fn visit_qpath(&mut self, path: &QPath, _: NodeId, _: Span) { - print!(" match_qpath({}, &[", self.current); + print!(" if match_qpath({}, &[", self.current); print_path(path, &mut true); - println!("]),"); + println!("]);"); } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None diff --git a/tests/ui/trailing_zeros.stdout b/tests/ui/trailing_zeros.stdout index 52ec01260be..145c102ed95 100644 --- a/tests/ui/trailing_zeros.stdout +++ b/tests/ui/trailing_zeros.stdout @@ -1,14 +1,15 @@ -if_let_chain!{[ - let Expr_::ExprBinary(ref op, ref left, ref right) = expr.node, - BinOp_::BiEq == op.node, - let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node, - BinOp_::BiBitAnd == op1.node, - let Expr_::ExprPath(ref path) = left1.node, - match_qpath(path, &["x"]), - let Expr_::ExprLit(ref lit) = right1.node, - let LitKind::Int(15, _) = lit.node, - let Expr_::ExprLit(ref lit1) = right.node, - let LitKind::Int(0, _) = lit1.node, -], { - // report your lint here -}} +if_chain! { + if let Expr_::ExprBinary(ref op, ref left, ref right) = expr.node; + if BinOp_::BiEq == op.node; + if let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node; + if BinOp_::BiBitAnd == op1.node; + if let Expr_::ExprPath(ref path) = left1.node; + if match_qpath(path, &["x"]); + if let Expr_::ExprLit(ref lit) = right1.node; + if let LitKind::Int(15, _) = lit.node; + if let Expr_::ExprLit(ref lit1) = right.node; + if let LitKind::Int(0, _) = lit1.node; + then { + // report your lint here + } +} -- cgit 1.4.1-3-g733a5 From 24a2c14733604132135b2ab598e7a1cf95d8b3ab Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 23 Oct 2017 15:20:58 -0400 Subject: remove if_let_chain --- clippy_lints/Cargo.toml | 1 + clippy_lints/src/lib.rs | 5 ++++ clippy_lints/src/utils/mod.rs | 57 ------------------------------------------- 3 files changed, 6 insertions(+), 57 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 414cd68a660..2dcac941c09 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -28,6 +28,7 @@ toml = "0.4" unicode-normalization = "0.1" pulldown-cmark = "0.0.15" url = "1.5.0" +if_chain = "0.1" [features] debugging = [] diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 27ef37dd00f..1cd3479f11d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,6 +11,8 @@ #![feature(inclusive_range_syntax, range_contains)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] +#![recursion_limit="256"] + #[macro_use] extern crate rustc; extern crate rustc_typeck; @@ -54,6 +56,9 @@ extern crate itertools; extern crate pulldown_cmark; extern crate url; +#[macro_use] +extern crate if_chain; + macro_rules! declare_restriction_lint { { pub $name:tt, $description:tt } => { declare_lint! { pub $name, Allow, $description } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9bc87dee68c..e0ed6689458 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -37,63 +37,6 @@ pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>; -/// Produce a nested chain of if-lets and ifs from the patterns: -/// -/// ```rust,ignore -/// if_let_chain! {[ -/// let Some(y) = x, -/// y.len() == 2, -/// let Some(z) = y, -/// ], { -/// block -/// }} -/// ``` -/// -/// becomes -/// -/// ```rust,ignore -/// if let Some(y) = x { -/// if y.len() == 2 { -/// if let Some(z) = y { -/// block -/// } -/// } -/// } -/// ``` -#[macro_export] -macro_rules! if_let_chain { - ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => { - if let $pat = $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([let $pat:pat = $expr:expr], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([let $pat:pat = $expr:expr,], $block:block) => { - if let $pat = $expr { - $block - } - }; - ([$expr:expr, $($tt:tt)+], $block:block) => { - if $expr { - if_let_chain!{ [$($tt)+], $block } - } - }; - ([$expr:expr], $block:block) => { - if $expr { - $block - } - }; - ([$expr:expr,], $block:block) => { - if $expr { - $block - } - }; -} - pub mod higher; /// Returns true if the two spans come from differing expansions (i.e. one is -- cgit 1.4.1-3-g733a5 From 0ae2ece91e0bb9dd2dc5ce151d6fc280183f0792 Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Wed, 25 Oct 2017 21:41:31 +0200 Subject: Check for arrays with size > 32 --- clippy_lints/src/loops.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0c3fd915399..2e6835b7f68 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; -use rustc::hir::def_id; +use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; @@ -363,7 +363,7 @@ impl LintPass for Pass { EMPTY_LOOP, WHILE_LET_ON_ITERATOR, FOR_KV_MAP, - NEVER_LOOP, + NEVER_LOOP, MUT_RANGE_BOUND ) } @@ -1128,7 +1128,12 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { let fn_arg_tys = method_type.fn_sig(cx.tcx).inputs(); assert_eq!(fn_arg_tys.skip_binder().len(), 1); if fn_arg_tys.skip_binder()[0].is_region_ptr() { - lint_iter_method(cx, args, arg, method_name); + match cx.tables.expr_ty(&args[0]).sty { + // If the length is greater than 32 no traits are implemented for array and + // therefore we cannot use `&`. + ty::TypeVariants::TyArray(_, size) if const_to_u64(size) > 32 => (), + _ => lint_iter_method(cx, args, arg, method_name) + }; } else { let object = snippet(cx, args[0].span, "_"); span_lint_and_sugg( @@ -1319,7 +1324,7 @@ struct MutateDelegate { impl<'tcx> Delegate<'tcx> for MutateDelegate { fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) { } - + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) { } @@ -1500,13 +1505,13 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { walk_expr(&mut used_visitor, idx); used_visitor.used }; - + if index_used { let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { Def::Local(node_id) | Def::Upvar(node_id, ..) => { let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); - + let parent_id = self.cx.tcx.hir.get_parent(expr.id); let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); -- cgit 1.4.1-3-g733a5 From e76eac4b18fde208f1df7d1ad653354cf35a6724 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 27 Oct 2017 10:51:43 +0200 Subject: Fix dogfood --- clippy_lints/src/if_not_else.rs | 5 ++++- clippy_lints/src/non_expressive_names.rs | 3 +++ clippy_lints/src/transmute.rs | 14 +++++++------- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 66f2778f215..3cdffbf82ae 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::span_help_and_lint; +use utils::{span_help_and_lint, in_external_macro}; /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an /// else branch. @@ -47,6 +47,9 @@ impl LintPass for IfNotElse { impl EarlyLintPass for IfNotElse { fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + if in_external_macro(cx, item.span) { + return; + } if let ExprKind::If(ref cond, _, Some(ref els)) = item.node { if let ExprKind::Block(..) = els.node { match cond.node { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 478b4c3e0eb..6cbeea8214d 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -74,6 +74,9 @@ const WHITELIST: &[&[&str]] = &[ &["lhs", "rhs"], &["tx", "rx"], &["set", "get"], + &["args", "arms"], + &["qpath", "path"], + &["lit", "lint"], ]; struct SimilarNamesNameVisitor<'a: 'b, 'tcx: 'a, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index f816ddc464f..fde6abe48af 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), ), - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, e.span, @@ -226,16 +226,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ), |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + let (deref, cast) = if to_ref_ty.mutbl == Mutability::MutMutable { ("&mut *", "*mut") } else { ("&*", "*const") }; - let arg = if from_pty.ty == to_rty.ty { + let arg = if from_pty.ty == to_ref_ty.ty { arg } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty.ty))) }; db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); @@ -299,7 +299,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { /// the type's `ToString` implementation. In weird cases it could lead to types /// with invalid `'_` /// lifetime, but it should be rare. -fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { +fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String { let seg = last_path_segment(path); if_chain! { if let Some(ref params) = seg.parameters; @@ -307,9 +307,9 @@ fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { if let Some(to_ty) = params.types.get(1); if let TyRptr(_, ref to_ty) = to_ty.node; then { - return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); + return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); } } - to_rty.to_string() + to_ref_ty.to_string() } -- cgit 1.4.1-3-g733a5 From 85683bf07c098dfc6b63a83c8c4b9a6257bad838 Mon Sep 17 00:00:00 2001 From: cgm616 Date: Sat, 28 Oct 2017 13:23:05 -0500 Subject: Fix mistake in merging --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 5c119b57531..1651aa9c611 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -735,7 +735,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let name = implitem.name; let parent = cx.tcx.hir.get_parent(implitem.id); let item = cx.tcx.hir.expect_item(parent); - if_chain! {[ + if_chain! { if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; if let Some(first_arg_ty) = sig.decl.inputs.get(0); if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); -- cgit 1.4.1-3-g733a5 From fed5a89076afa6b57af92aa489b7ba179cbd6f59 Mon Sep 17 00:00:00 2001 From: cgm616 Date: Sat, 28 Oct 2017 13:24:39 -0500 Subject: Add tests for pub_restricted --- tests/ui/methods.rs | 2 +- tests/ui/methods.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index c13caf84b98..9075d2024a2 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -18,7 +18,7 @@ struct T; impl T { pub fn add(self, other: T) -> T { self } - pub fn drop(&mut self) { } + pub(crate) fn drop(&mut self) { } fn neg(self) -> Self { self } // no error, private function fn eq(&self, other: T) -> bool { true } // no error, private function diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 9591d1f4fb4..d7596c89fbb 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -53,8 +53,8 @@ error: defining a method called `add` on this type; consider implementing the `s error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name --> $DIR/methods.rs:21:5 | -21 | pub fn drop(&mut self) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +21 | pub(crate) fn drop(&mut self) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/methods.rs:31:17 -- cgit 1.4.1-3-g733a5 From 09143cdaf08c835bd0111e5b10694088e7fe4b8b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 28 Oct 2017 14:52:45 -0400 Subject: Update tests; make it work with generics on context --- clippy_lints/src/new_without_default.rs | 13 ++++++------- tests/ui/mut_mut.stderr | 24 ------------------------ 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 2fc6695fa8b..e28d077f999 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -108,13 +108,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } - //TODO: There is no sig.generics anymore and I don't know how to fix this. - //if !sig.generics.ty_params.is_empty() { - // // when the result of `new()` depends on a type parameter we should not require - // // an - // // impl of `Default` - // return; - //} + if !cx.generics.expect("method must have generics").ty_params.is_empty() { + // when the result of `new()` depends on a type parameter we should not require + // an + // impl of `Default` + return; + } if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 31f9178aa27..8bfc2fc8a5c 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -39,12 +39,6 @@ error: generally you want to avoid `&mut &mut _` if possible 30 | let y : &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ -error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:30:17 - | -30 | let y : &mut &mut u32 = &mut &mut 2; - | ^^^^^^^^^^^^^ - error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:35:38 | @@ -63,21 +57,3 @@ error: generally you want to avoid `&mut &mut _` if possible 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ -error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:17 - | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^^^^^^ - -error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:22 - | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^ - -error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:22 - | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From f76225e3887170743403af9204887918b5db5a80 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 29 Oct 2017 05:21:25 -0400 Subject: Handle TyForeign --- clippy_lints/src/utils/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e0ed6689458..a3b0e928aa2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -924,6 +924,7 @@ pub fn opt_def_id(def: Def) -> Option { Def::TyAlias(id) | Def::AssociatedTy(id) | Def::TyParam(id) | + Def::TyForeign(id) | Def::Struct(id) | Def::StructCtor(id, ..) | Def::Union(id) | -- cgit 1.4.1-3-g733a5 From a69764d93d8fc6f9d6a668e8a24d0cb936e7fe70 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 29 Oct 2017 05:30:33 -0400 Subject: Bump to 0.0.167 (rustup to rustc 1.23.0-nightly (90ef3372e 2017-10-29)) --- CHANGELOG.md | 9 +++++++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 12 +++++++----- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a6f91e3bb6..8c744796681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.167 +* Rustup to *rustc 1.23.0-nightly (90ef3372e 2017-10-29)* +* New lints: [`const_static_lifetime`], [`erasing_op`], [`fallible_impl_from`], [`println_empty_string`], [`useless_asref`] + ## 0.0.166 * Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)* * New lints: [`explicit_write`], [`identity_conversion`], [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], [`transmute_int_to_float`] @@ -486,6 +490,7 @@ All notable changes to this project will be documented in this file. [`cmp_null`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_null [`cmp_owned`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_owned [`collapsible_if`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#collapsible_if +[`const_static_lifetime`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#const_static_lifetime [`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity [`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver @@ -504,6 +509,7 @@ All notable changes to this project will be documented in this file. [`enum_glob_use`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_glob_use [`enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_variant_names [`eq_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eq_op +[`erasing_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#erasing_op [`eval_order_dependence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eval_order_dependence [`expl_impl_clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop @@ -511,6 +517,7 @@ All notable changes to this project will be documented in this file. [`explicit_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_iter_loop [`explicit_write`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extend_from_slice +[`fallible_impl_from`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fallible_impl_from [`filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_map [`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next [`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic @@ -611,6 +618,7 @@ All notable changes to this project will be documented in this file. [`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence [`print_stdout`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_stdout [`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline +[`println_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#println_empty_string [`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg [`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`range_minus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_minus_one @@ -673,6 +681,7 @@ All notable changes to this project will be documented in this file. [`use_debug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#used_underscore_binding +[`useless_asref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_asref [`useless_attribute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_attribute [`useless_format`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_format [`useless_let_if_seq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_let_if_seq diff --git a/Cargo.toml b/Cargo.toml index 35e078d6577..6e6704bb6b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.166" +version = "0.0.167" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.166", path = "clippy_lints" } +clippy_lints = { version = "0.0.167", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 2dcac941c09..ed0e2430636 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.166" +version = "0.0.167" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1cd3479f11d..18361f54d64 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -93,12 +93,13 @@ pub mod entry; pub mod enum_clike; pub mod enum_glob_use; pub mod enum_variants; -pub mod erasing_op; pub mod eq_op; +pub mod erasing_op; pub mod escape; pub mod eta_reduction; pub mod eval_order_dependence; pub mod explicit_write; +pub mod fallible_impl_from; pub mod format; pub mod formatting; pub mod functions; @@ -106,7 +107,6 @@ pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; -pub mod fallible_impl_from; pub mod infinite_iter; pub mod int_plus_one; pub mod invalid_ref; @@ -209,7 +209,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { let mut store = reg.sess.lint_store.borrow_mut(); store.register_removed( "should_assert_eq", - "`assert!()` will be more flexible with RFC 2011" + "`assert!()` will be more flexible with RFC 2011", ); store.register_removed( "extend_from_slice", @@ -360,11 +360,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_pedantic", vec![ booleans::NONMINIMAL_BOOL, - const_static_lifetime::CONST_STATIC_LIFETIME, empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, + fallible_impl_from::FALLIBLE_IMPL_FROM, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, int_plus_one::INT_PLUS_ONE, @@ -423,6 +423,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { booleans::LOGIC_BUG, bytecount::NAIVE_BYTECOUNT, collapsible_if::COLLAPSIBLE_IF, + const_static_lifetime::CONST_STATIC_LIFETIME, copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, copies::MATCH_SAME_ARMS, @@ -441,6 +442,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::MODULE_INCEPTION, eq_op::EQ_OP, eq_op::OP_REF, + erasing_op::ERASING_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, eval_order_dependence::DIVERGING_SUB_EXPRESSION, @@ -455,7 +457,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, - fallible_impl_from::FALLIBLE_IMPL_FROM, infinite_iter::INFINITE_ITER, invalid_ref::INVALID_REF, is_unit_expr::UNIT_EXPR, @@ -509,6 +510,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SINGLE_CHAR_PATTERN, methods::STRING_EXTEND_CHARS, methods::TEMPORARY_CSTRING_AS_PTR, + methods::USELESS_ASREF, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, misc::CMP_NAN, -- cgit 1.4.1-3-g733a5 From f0a1eff1c47b57815bda774a7e16fcc2a39eaa65 Mon Sep 17 00:00:00 2001 From: "G. Endignoux" Date: Mon, 30 Oct 2017 13:04:26 +0100 Subject: Start working on #1590 --- clippy_lints/src/methods.rs | 63 ++++++++++++++--- tests/ui/methods.rs | 23 ++++++ tests/ui/methods.stderr | 168 ++++++++++++++++++++++---------------------- 3 files changed, 161 insertions(+), 93 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index caccfccdda2..baa1b852fe1 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -193,6 +193,24 @@ declare_lint! { `map_or_else(g, f)`" } +/// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `result.ok().map_or_else(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x.map(|a| a + 1).unwrap_or_else(some_function) +/// ``` +declare_lint! { + pub RESULT_MAP_UNWRAP_OR_ELSE, + Allow, + "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `.ok().map_or_else(g, f)`" +} + /// **What it does:** Checks for usage of `_.map_or(None, _)`. /// /// **Why is this bad?** Readability, this can be written more concisely as @@ -615,6 +633,7 @@ impl LintPass for Pass { OK_EXPECT, OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE, + RESULT_MAP_UNWRAP_OR_ELSE, OPTION_MAP_OR_NONE, OR_FUN_CALL, CHARS_NEXT_CMP, @@ -1241,13 +1260,25 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] } } -/// lint use of `map().unwrap_or_else()` for `Option`s -fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr], unwrap_args: &'tcx [hir::Expr]) { +/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s +fn lint_map_unwrap_or_else<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + map_args: &'tcx [hir::Expr], + unwrap_args: &'tcx [hir::Expr], +) { // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { + let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION); + let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT); + if is_option || is_result { // lint message - let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ - `map_or_else(g, f)` instead"; + let msg = if is_option { + "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ + `map_or_else(g, f)` instead" + } else { + "called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling \ + `ok().map_or_else(g, f)` instead" + }; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_args[1].span, ".."); let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); @@ -1258,18 +1289,32 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir if same_span && !multiline { span_note_and_lint( cx, - OPTION_MAP_UNWRAP_OR_ELSE, + if is_option { + OPTION_MAP_UNWRAP_OR_ELSE + } else { + RESULT_MAP_UNWRAP_OR_ELSE + }, expr.span, msg, expr.span, &format!( - "replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`", + "replace `map({0}).unwrap_or_else({1})` with `{2}map_or_else({1}, {0})`", map_snippet, - unwrap_snippet + unwrap_snippet, + if is_result { "ok()." } else { "" } ), ); } else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR_ELSE, expr.span, msg); + span_lint( + cx, + if is_option { + OPTION_MAP_UNWRAP_OR_ELSE + } else { + RESULT_MAP_UNWRAP_OR_ELSE + }, + expr.span, + msg, + ); }; } } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 24adbe943e1..9e37c894001 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -149,6 +149,29 @@ fn option_methods() { ); } +/// Checks implementation of the following lints: +/// * `RESULT_MAP_UNWRAP_OR_ELSE` +fn result_methods() { + let res: Result = Ok(1); + + // Check RESULT_MAP_UNWRAP_OR_ELSE + // single line case + let _ = res.map(|x| x + 1) + + .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = res.map(|x| { + x + 1 + } + ).unwrap_or_else(|e| 0); + let _ = res.map(|x| x + 1) + .unwrap_or_else(|e| + 0 + ); + // macro case + let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint +} + /// Struct to generate false positives for things with .iter() #[derive(Copy, Clone)] struct HasIter; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 97e8c25ad75..a34b80823b9 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -221,251 +221,251 @@ help: try using and_then instead | error: unnecessary structure name repetition - --> $DIR/methods.rs:173:24 + --> $DIR/methods.rs:196:24 | -173 | fn filter(self) -> IteratorFalsePositives { +196 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:177:22 + --> $DIR/methods.rs:200:22 | -177 | fn next(self) -> IteratorFalsePositives { +200 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:197:32 + --> $DIR/methods.rs:220:32 | -197 | fn skip(self, _: usize) -> IteratorFalsePositives { +220 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:207:13 + --> $DIR/methods.rs:230:13 | -207 | let _ = v.iter().filter(|&x| *x < 0).next(); +230 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:210:13 + --> $DIR/methods.rs:233:13 | -210 | let _ = v.iter().filter(|&x| { +233 | let _ = v.iter().filter(|&x| { | _____________^ -211 | | *x < 0 -212 | | } -213 | | ).next(); +234 | | *x < 0 +235 | | } +236 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:225:13 + --> $DIR/methods.rs:248:13 | -225 | let _ = v.iter().find(|&x| *x < 0).is_some(); +248 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:228:13 + --> $DIR/methods.rs:251:13 | -228 | let _ = v.iter().find(|&x| { +251 | let _ = v.iter().find(|&x| { | _____________^ -229 | | *x < 0 -230 | | } -231 | | ).is_some(); +252 | | *x < 0 +253 | | } +254 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:234:13 + --> $DIR/methods.rs:257:13 | -234 | let _ = v.iter().position(|&x| x < 0).is_some(); +257 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:237:13 + --> $DIR/methods.rs:260:13 | -237 | let _ = v.iter().position(|&x| { +260 | let _ = v.iter().position(|&x| { | _____________^ -238 | | x < 0 -239 | | } -240 | | ).is_some(); +261 | | x < 0 +262 | | } +263 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:243:13 + --> $DIR/methods.rs:266:13 | -243 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +266 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:246:13 + --> $DIR/methods.rs:269:13 | -246 | let _ = v.iter().rposition(|&x| { +269 | let _ = v.iter().rposition(|&x| { | _____________^ -247 | | x < 0 -248 | | } -249 | | ).is_some(); +270 | | x < 0 +271 | | } +272 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:263:21 + --> $DIR/methods.rs:286:21 | -263 | fn new() -> Foo { Foo } +286 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:281:5 + --> $DIR/methods.rs:304:5 | -281 | with_constructor.unwrap_or(make()); +304 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:284:5 + --> $DIR/methods.rs:307:5 | -284 | with_new.unwrap_or(Vec::new()); +307 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:287:5 + --> $DIR/methods.rs:310:5 | -287 | with_const_args.unwrap_or(Vec::with_capacity(12)); +310 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:290:5 + --> $DIR/methods.rs:313:5 | -290 | with_err.unwrap_or(make()); +313 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:293:5 + --> $DIR/methods.rs:316:5 | -293 | with_err_args.unwrap_or(Vec::with_capacity(12)); +316 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:296:5 + --> $DIR/methods.rs:319:5 | -296 | with_default_trait.unwrap_or(Default::default()); +319 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:299:5 + --> $DIR/methods.rs:322:5 | -299 | with_default_type.unwrap_or(u64::default()); +322 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:302:5 + --> $DIR/methods.rs:325:5 | -302 | with_vec.unwrap_or(vec![]); +325 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:5 + --> $DIR/methods.rs:330:5 | -307 | without_default.unwrap_or(Foo::new()); +330 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:310:5 + --> $DIR/methods.rs:333:5 | -310 | map.entry(42).or_insert(String::new()); +333 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:313:5 + --> $DIR/methods.rs:336:5 | -313 | btree.entry(42).or_insert(String::new()); +336 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:13 + --> $DIR/methods.rs:339:13 | -316 | let _ = stringy.unwrap_or("".to_owned()); +339 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:327:23 + --> $DIR/methods.rs:350:23 | -327 | let bad_vec = some_vec.iter().nth(3); +350 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:328:26 + --> $DIR/methods.rs:351:26 | -328 | let bad_slice = &some_vec[..].iter().nth(3); +351 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:329:31 + --> $DIR/methods.rs:352:31 | -329 | let bad_boxed_slice = boxed_slice.iter().nth(3); +352 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:330:29 + --> $DIR/methods.rs:353:29 | -330 | let bad_vec_deque = some_vec_deque.iter().nth(3); +353 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:335:23 + --> $DIR/methods.rs:358:23 | -335 | let bad_vec = some_vec.iter_mut().nth(3); +358 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:338:26 + --> $DIR/methods.rs:361:26 | -338 | let bad_slice = &some_vec[..].iter_mut().nth(3); +361 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:341:29 + --> $DIR/methods.rs:364:29 | -341 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +364 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:353:13 + --> $DIR/methods.rs:376:13 | -353 | let _ = some_vec.iter().skip(42).next(); +376 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:354:13 + --> $DIR/methods.rs:377:13 | -354 | let _ = some_vec.iter().cycle().skip(42).next(); +377 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:355:13 + --> $DIR/methods.rs:378:13 | -355 | let _ = (1..10).skip(10).next(); +378 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:356:14 + --> $DIR/methods.rs:379:14 | -356 | let _ = &some_vec[..].iter().skip(3).next(); +379 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:365:13 + --> $DIR/methods.rs:388:13 | -365 | let _ = opt.unwrap(); +388 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 87fd68731d5f61f11f5780a4a6fb6f5e1b1acc3f Mon Sep 17 00:00:00 2001 From: "G. Endignoux" Date: Mon, 30 Oct 2017 14:10:38 +0100 Subject: Update UI tests. --- clippy_lints/src/lib.rs | 1 + tests/ui/methods.stderr | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 18361f54d64..69885dec1a9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -374,6 +374,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, + methods::RESULT_MAP_UNWRAP_OR_ELSE, methods::OPTION_UNWRAP_USED, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index a34b80823b9..b8bac95c2d5 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -220,6 +220,38 @@ help: try using and_then instead 148 | }); | +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/methods.rs:159:13 + | +159 | let _ = res.map(|x| x + 1) + | _____________^ +160 | | +161 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | |_____________________________________^ + | + = note: `-D result-map-unwrap-or-else` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/methods.rs:163:13 + | +163 | let _ = res.map(|x| { + | _____________^ +164 | | x + 1 +165 | | } +166 | | ).unwrap_or_else(|e| 0); + | |_____________________________________^ + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/methods.rs:167:13 + | +167 | let _ = res.map(|x| x + 1) + | _____________^ +168 | | .unwrap_or_else(|e| +169 | | 0 +170 | | ); + | |_________________^ + error: unnecessary structure name repetition --> $DIR/methods.rs:196:24 | -- cgit 1.4.1-3-g733a5 From c526c51923b30d6c372c5a45a27f4caded53060d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 30 Oct 2017 18:21:23 -0700 Subject: Update clippy for rustc 1.23.0-nightly (f0fe716db 2017-10-30) --- clippy_lints/src/lib.rs | 1 + src/lib.rs | 1 + tests/ui/lint_pass.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 18361f54d64..fdd02ba54e8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -9,6 +9,7 @@ #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] #![feature(inclusive_range_syntax, range_contains)] +#![feature(macro_vis_matcher)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit="256"] diff --git a/src/lib.rs b/src/lib.rs index df692b7e60c..8f0c6a63207 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] +#![feature(macro_vis_matcher)] #![allow(unknown_lints)] #![allow(missing_docs_in_private_items)] diff --git a/tests/ui/lint_pass.rs b/tests/ui/lint_pass.rs index 1990e137e67..b576f72e8e7 100644 --- a/tests/ui/lint_pass.rs +++ b/tests/ui/lint_pass.rs @@ -1,5 +1,6 @@ #![feature(rustc_private)] +#![feature(macro_vis_matcher)] #![warn(lint_without_lint_pass)] -- cgit 1.4.1-3-g733a5 From 7bce43b66b1028ae1402e3f9bfd8225400912586 Mon Sep 17 00:00:00 2001 From: Martin Lindhe Date: Tue, 31 Oct 2017 08:34:27 +0100 Subject: fix some typos --- CHANGELOG.md | 2 +- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/doc.rs | 2 +- src/driver.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c744796681..b6ce809f2de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,7 +72,7 @@ All notable changes to this project will be documented in this file. ## 0.0.148 * Update to *rustc 1.21.0-nightly (37c7d0ebb 2017-07-31)* -* New lints: [`unreadable_literal`], [`inconsisten_digit_grouping`], [`large_digit_groups`] +* New lints: [`unreadable_literal`], [`inconsistent_digit_grouping`], [`large_digit_groups`] ## 0.0.147 * Update to *rustc 1.21.0-nightly (aac223f4f 2017-07-30)* diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 4801f788856..03771f0375b 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -37,7 +37,7 @@ impl StaticConst { // Recursively visit types fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext) { match ty.node { - // Be carefull of nested structures (arrays and tuples) + // Be careful of nested structures (arrays and tuples) TyKind::Array(ref ty, _) => { self.visit_type(&*ty, cx); }, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index abe9897ba4d..9ed09d96e1b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -224,7 +224,7 @@ fn check_doc<'a, Events: Iterator)>>( let (begin, span) = spans[index]; - // Adjust for the begining of the current `Event` + // Adjust for the beginning of the current `Event` let span = span.with_lo(span.lo() + BytePos::from_usize(offset - begin)); check_text(cx, valid_idents, &text, span); diff --git a/src/driver.rs b/src/driver.rs index ab5e90141a9..ec5c10d4c6d 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -82,7 +82,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { .as_ref() .expect( "at this compilation stage \ - the krate must be parsed", + the crate must be parsed", ) .span, ); -- cgit 1.4.1-3-g733a5 From 44d3ea53081f7f0065d54fc29cbfd234b44208a8 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 31 Oct 2017 10:03:54 -0700 Subject: Fix lint_without_lint_pass --- clippy_lints/src/utils/internal_lints.rs | 5 +---- clippy_lints/src/utils/paths.rs | 4 ++-- tests/ui/lint_pass.rs | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index a35b034d791..6e62f96749e 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -161,16 +161,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { if let TyRptr( - ref lt, + _, MutTy { ty: ref inner, mutbl: MutImmutable, }, ) = ty.node { - if lt.is_elided() { - return false; - } if let TyPath(ref path) = inner.node { return match_qpath(path, &paths::LINT); } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 96ccddaf2d0..95e14609182 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -41,8 +41,8 @@ pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; pub const LINKED_LIST: [&str; 3] = ["alloc", "linked_list", "LinkedList"]; -pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; -pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; +pub const LINT: [&str; 2] = ["lint", "Lint"]; +pub const LINT_ARRAY: [&str; 2] = ["lint", "LintArray"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"]; pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"]; diff --git a/tests/ui/lint_pass.rs b/tests/ui/lint_pass.rs index b576f72e8e7..29c93e745b3 100644 --- a/tests/ui/lint_pass.rs +++ b/tests/ui/lint_pass.rs @@ -2,7 +2,6 @@ #![feature(rustc_private)] #![feature(macro_vis_matcher)] - #![warn(lint_without_lint_pass)] #[macro_use] extern crate rustc; -- cgit 1.4.1-3-g733a5 From fc2099b96d008fec6195c1d5a5681f5ba1b3de3d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 30 Oct 2017 18:23:06 -0700 Subject: Bump to 0.0.168 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c744796681..b708ef63158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.168 +* Rustup to *rustc 1.23.0-nightly (f0fe716db 2017-10-30)* + ## 0.0.167 * Rustup to *rustc 1.23.0-nightly (90ef3372e 2017-10-29)* * New lints: [`const_static_lifetime`], [`erasing_op`], [`fallible_impl_from`], [`println_empty_string`], [`useless_asref`] diff --git a/Cargo.toml b/Cargo.toml index 6e6704bb6b2..cb8e5b2adf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.167" +version = "0.0.168" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.167", path = "clippy_lints" } +clippy_lints = { version = "0.0.168", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ed0e2430636..57fa3ce91ba 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.167" +version = "0.0.168" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 7fa27d938774891cfca3c488db0edc0eb926c12f Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sun, 29 Oct 2017 10:27:45 +0900 Subject: Lint `transmute::<&[u8], &str>` --- clippy_lints/src/transmute.rs | 55 +++++++++++++++++++++++++++++++++++++++++-- tests/ui/transmute.rs | 5 ++++ tests/ui/transmute.stderr | 18 ++++++++++++-- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index fde6abe48af..cc8c6d28445 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -88,7 +88,7 @@ declare_lint! { /// ```rust /// let _: char = std::mem::transmute(x); // where x: u32 /// // should be: -/// let _: Option = std::char::from_u32(x); +/// let _ = std::char::from_u32(x).unwrap(); /// ``` declare_lint! { pub TRANSMUTE_INT_TO_CHAR, @@ -96,6 +96,24 @@ declare_lint! { "transmutes from an integer to a `char`" } +/// **What it does:** Checks for transmutes from a `&[u8] to a `&str`. +/// +/// **Why is this bad?** Not every byte slice is a valid UTF-8 string. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _: &str = std::mem::transmute(b); // where b: &[u8] +/// // should be: +/// let _ = std::str::from_utf8(b).unwrap(); +/// ``` +declare_lint! { + pub TRANSMUTE_BYTES_TO_STR, + Warn, + "transmutes from a `&[u8]` to a `&str`" +} + /// **What it does:** Checks for transmutes from an integer to a `bool`. /// /// **Why is this bad?** This might result in an invalid in-memory representation of a `bool`. @@ -142,6 +160,7 @@ impl LintPass for Transmute { USELESS_TRANSMUTE, WRONG_TRANSMUTE, TRANSMUTE_INT_TO_CHAR, + TRANSMUTE_BYTES_TO_STR, TRANSMUTE_INT_TO_BOOL, TRANSMUTE_INT_TO_FLOAT ) @@ -254,9 +273,41 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({})", arg.to_string())); + db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string())); } ), + (&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => { + if_chain! { + if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ref_from.ty.sty, &ref_to.ty.sty); + if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty; + if ref_from.mutbl == ref_to.mutbl; + then { + let postfix = if ref_from.mutbl == Mutability::MutMutable { + "_mut" + } else { + "" + }; + + span_lint_and_then( + cx, + TRANSMUTE_BYTES_TO_STR, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |db| { + db.span_suggestion( + e.span, + "consider using", + format!( + "std::str::from_utf8{}({}).unwrap()", + postfix, + snippet(cx, args[0].span, ".."), + ), + ); + } + ) + } + } + }, (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then( cx, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 81582b5a15f..b04297f01fb 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -135,4 +135,9 @@ fn int_to_float() { let _: f32 = unsafe { std::mem::transmute(0_i32) }; } +fn bytes_to_str(b: &[u8], mb: &mut [u8]) { + let _: &str = unsafe { std::mem::transmute(b) }; + let _: &mut str = unsafe { std::mem::transmute(mb) }; +} + fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index c81ec5260be..6504f55845d 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -158,7 +158,7 @@ error: transmute from a `u32` to a `char` --> $DIR/transmute.rs:123:28 | 123 | let _: char = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` | = note: `-D transmute-int-to-char` implied by `-D warnings` @@ -166,7 +166,7 @@ error: transmute from a `i32` to a `char` --> $DIR/transmute.rs:124:28 | 124 | let _: char = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` --> $DIR/transmute.rs:129:28 @@ -190,3 +190,17 @@ error: transmute from a `i32` to a `f32` 135 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` +error: transmute from a `&[u8]` to a `&str` + --> $DIR/transmute.rs:139:28 + | +139 | let _: &str = unsafe { std::mem::transmute(b) }; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` + | + = note: `-D transmute-bytes-to-str` implied by `-D warnings` + +error: transmute from a `&mut [u8]` to a `&mut str` + --> $DIR/transmute.rs:140:32 + | +140 | let _: &mut str = unsafe { std::mem::transmute(mb) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` + -- cgit 1.4.1-3-g733a5 From b9f272cdc2ac262f533ca1d1e648ec13c02404a4 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 1 Nov 2017 21:10:48 +0900 Subject: Known problems --- clippy_lints/src/transmute.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index cc8c6d28445..eec633953c7 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -96,11 +96,20 @@ declare_lint! { "transmutes from an integer to a `char`" } -/// **What it does:** Checks for transmutes from a `&[u8] to a `&str`. +/// **What it does:** Checks for transmutes from a `&[u8]` to a `&str`. /// /// **Why is this bad?** Not every byte slice is a valid UTF-8 string. /// -/// **Known problems:** None. +/// **Known problems:** +/// - [`from_utf8`] which this lint suggests using is slower than `transmute` +/// as it needs to validate the input. +/// If you are certain that the input is always a valid UTF-8, +/// use [`from_utf8_unchecked`] which is as fast as `transmute` +/// but has a semantically meaningful name. +/// - You might want to handle errors returned from [`from_utf8`] instead of calling `unwrap`. +/// +/// [`from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html +/// [`from_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 0328d4c6e582f63e38f20803d9f3ab97649caf45 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 1 Nov 2017 23:29:40 +0900 Subject: Known problems --- clippy_lints/src/transmute.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index eec633953c7..d01a63f0494 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -80,9 +80,18 @@ declare_lint! { /// **What it does:** Checks for transmutes from an integer to a `char`. /// -/// **Why is this bad?** Not every integer is a unicode scalar value. +/// **Why is this bad?** Not every integer is a Unicode scalar value. /// -/// **Known problems:** None. +/// **Known problems:** +/// - [`from_u32`] which this lint suggests using is slower than `transmute` +/// as it needs to validate the input. +/// If you are certain that the input is always a valid Unicode scalar value, +/// use [`from_u32_unchecked`] which is as fast as `transmute` +/// but has a semantically meaningful name. +/// - You might want to handle `None` returned from [`from_u32`] instead of calling `unwrap`. +/// +/// [`from_u32`]: https://doc.rust-lang.org/std/char/fn.from_u32.html +/// [`from_u32_unchecked`]: https://doc.rust-lang.org/std/char/fn.from_u32_unchecked.html /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 1326accdcfbc8123e06d6331ebd276f73b005991 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 07:09:46 +0900 Subject: Use is_ok() --- src/driver.rs | 2 +- src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index ab5e90141a9..df0ff4c3f1f 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -129,7 +129,7 @@ fn show_version() { pub fn main() { use std::env; - if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { + if env::var("CLIPPY_DOGFOOD").is_ok() { panic!("yummy"); } diff --git a/src/main.rs b/src/main.rs index 69f416e2092..11ae135bfa9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ fn show_version() { pub fn main() { use std::env; - if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) { + if env::var("CLIPPY_DOGFOOD").is_ok() { panic!("yummy"); } -- cgit 1.4.1-3-g733a5 From 49392fce53f938fda5b34673c98001ac7fea5d0f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 07:13:14 +0900 Subject: Avoid panicking when no arg is given to clippy_driver --- src/driver.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/driver.rs b/src/driver.rs index df0ff4c3f1f..8e4114bac1b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -163,6 +163,9 @@ pub fn main() { // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programatically, so we ignore this/ let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } if orig_args[1] == "rustc" { // we still want to be able to invoke it normally though orig_args.remove(1); -- cgit 1.4.1-3-g733a5 From 9b34edf2c662a0c32da7eed01d6d5b6396e57e0f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 07:13:59 +0900 Subject: Remove an unused binary file --- mut_range_bound | Bin 422840 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 mut_range_bound diff --git a/mut_range_bound b/mut_range_bound deleted file mode 100755 index fdf917d5158..00000000000 Binary files a/mut_range_bound and /dev/null differ -- cgit 1.4.1-3-g733a5 From 6fc9fe2eba79958672a859497f75a689fa3e87f6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 07:18:34 +0900 Subject: Fix a typo --- src/driver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index 8e4114bac1b..7bc5a109d5c 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -161,7 +161,7 @@ pub fn main() { rustc_driver::in_rustc_thread(|| { // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programatically, so we ignore this/ + // We're invoking the compiler programmatically, so we ignore this/ let mut orig_args: Vec = env::args().collect(); if orig_args.len() <= 1 { std::process::exit(1); -- cgit 1.4.1-3-g733a5 From 9d01468bc7a3e7311ff6ed4e64395818dc64fee1 Mon Sep 17 00:00:00 2001 From: Alexandru Ene Date: Fri, 3 Nov 2017 01:01:41 +0000 Subject: Warns if variable name is composed only of underscores and digits. --- clippy_lints/src/non_expressive_names.rs | 31 ++++++++++++++++++++++++++++++- tests/ui/non_expressive_names.rs | 7 +++++++ tests/ui/non_expressive_names.stderr | 20 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 6cbeea8214d..e4d7049bf01 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -42,13 +42,33 @@ declare_lint! { "too many single character bindings" } +/// **What it does:** Checks if you have variables whose name consists of just +/// underscores and digits. +/// +/// **Why is this bad?** It's hard to memorize what a variable means without a +/// descriptive name. +/// +/// **Known problems:** None? +/// +/// **Example:** +/// ```rust +/// let _1 = 1; +/// let ___1 = 1; +/// let __1___2 = 11; +/// ``` +declare_lint! { + pub JUST_UNDERSCORES_AND_DIGITS, + Warn, + "unclear name" +} + pub struct NonExpressiveNames { pub single_char_binding_names_threshold: u64, } impl LintPass for NonExpressiveNames { fn get_lints(&self) -> LintArray { - lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES) + lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS) } } @@ -133,6 +153,15 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { if interned_name.chars().any(char::is_uppercase) { return; } + if interned_name.chars().all(|c| c.is_digit(10) || c == '_') { + span_lint( + self.0.cx, + JUST_UNDERSCORES_AND_NUMBERS, + span, + "binding whose name is just underscores and digits", + ); + return; + } let count = interned_name.chars().count(); if count < 3 { if count == 1 { diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 9eb3e5a82a7..16a035ca024 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -134,3 +134,10 @@ fn bla() { } } } + +fn underscores_and_numbers() { + let _1 = 1; //~ERROR Consider a more descriptive name + let ____1 = 1; //~ERROR Consider a more descriptive name + let __1___2 = 12; //~ERROR Consider a more descriptive name + let _1_ok= 1; +} \ No newline at end of file diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 014d4599271..7141c97dd1a 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -129,3 +129,23 @@ error: 5th binding whose name is just one char 129 | e => panic!(), | ^ +error: binding whose name is just underscores and digits + --> $DIR/non_expressive_names.rs:139:9 + | +139 | let _1 = 1; //~ERROR Consider a more descriptive name + | ^^ + | + = note: `-D just-underscores-and-numbers` implied by `-D warnings` + +error: binding whose name is just underscores and digits + --> $DIR/non_expressive_names.rs:140:9 + | +140 | let ____1 = 1; //~ERROR Consider a more descriptive name + | ^^^^^ + +error: binding whose name is just underscores and digits + --> $DIR/non_expressive_names.rs:141:9 + | +141 | let __1___2 = 12; //~ERROR Consider a more descriptive name + | ^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 76e765aeda1ad2b6901b1255a6baa434bad76f1b Mon Sep 17 00:00:00 2001 From: cgm616 Date: Thu, 2 Nov 2017 23:53:48 -0500 Subject: Switch to new method of checking access --- clippy_lints/src/methods.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f6787c61ae2..4f55162e57f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -760,8 +760,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); if let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node; then { - if implitem.vis == hir::Visibility::Public || - implitem.vis.is_pub_restricted() { + if cx.access_levels.is_exported(implitem.id) { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if name == method_name && -- cgit 1.4.1-3-g733a5 From 3902b836e742e1e914218b1178244dfe2fdb4c84 Mon Sep 17 00:00:00 2001 From: cgm616 Date: Thu, 2 Nov 2017 23:54:35 -0500 Subject: Update tests --- tests/ui/methods.rs | 4 +- tests/ui/methods.stderr | 432 +++++++++++------------------------------------- 2 files changed, 99 insertions(+), 337 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index f114ef44c15..6ecb3963154 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -14,12 +14,12 @@ use std::iter::FromIterator; use std::rc::{self, Rc}; use std::sync::{self, Arc}; -struct T; +pub struct T; impl T { pub fn add(self, other: T) -> T { self } - pub(crate) fn drop(&mut self) { } + pub(crate) fn drop(&mut self) { } // no error, not public interfact fn neg(self) -> Self { self } // no error, private function fn eq(&self, other: T) -> bool { true } // no error, private function diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index c7a1fd5c708..469f81c657a 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -50,12 +50,6 @@ error: defining a method called `add` on this type; consider implementing the `s | = note: `-D should-implement-trait` implied by `-D warnings` -error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name - --> $DIR/methods.rs:21:5 - | -21 | pub(crate) fn drop(&mut self) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/methods.rs:31:17 | @@ -227,515 +221,283 @@ help: try using and_then instead | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:159:13 + --> $DIR/methods.rs:162:13 | -159 | let _ = res.map(|x| x + 1) +162 | let _ = res.map(|x| x + 1) | _____________^ -160 | | -161 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line +163 | | +164 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | |_____________________________________^ | = note: `-D result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:163:13 + --> $DIR/methods.rs:166:13 | -163 | let _ = res.map(|x| { +166 | let _ = res.map(|x| { | _____________^ -164 | | x + 1 -165 | | } -166 | | ).unwrap_or_else(|e| 0); +167 | | x + 1 +168 | | } +169 | | ).unwrap_or_else(|e| 0); | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:167:13 + --> $DIR/methods.rs:170:13 | -167 | let _ = res.map(|x| x + 1) +170 | let _ = res.map(|x| x + 1) | _____________^ -168 | | .unwrap_or_else(|e| -169 | | 0 -170 | | ); +171 | | .unwrap_or_else(|e| +172 | | 0 +173 | | ); | |_________________^ error: unnecessary structure name repetition -<<<<<<< HEAD - --> $DIR/methods.rs:176:24 - | -176 | fn filter(self) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:180:22 - | -180 | fn next(self) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:200:32 + --> $DIR/methods.rs:199:24 | -200 | fn skip(self, _: usize) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - -error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:210:13 - | -210 | let _ = v.iter().filter(|&x| *x < 0).next(); -======= - --> $DIR/methods.rs:196:24 - | -196 | fn filter(self) -> IteratorFalsePositives { +199 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:200:22 + --> $DIR/methods.rs:203:22 | -200 | fn next(self) -> IteratorFalsePositives { +203 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:220:32 + --> $DIR/methods.rs:223:32 | -220 | fn skip(self, _: usize) -> IteratorFalsePositives { +223 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:230:13 + --> $DIR/methods.rs:233:13 | -230 | let _ = v.iter().filter(|&x| *x < 0).next(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +233 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. -<<<<<<< HEAD - --> $DIR/methods.rs:213:13 + --> $DIR/methods.rs:236:13 | -213 | let _ = v.iter().filter(|&x| { +236 | let _ = v.iter().filter(|&x| { | _____________^ -214 | | *x < 0 -215 | | } -216 | | ).next(); +237 | | *x < 0 +238 | | } +239 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:228:13 - | -228 | let _ = v.iter().find(|&x| *x < 0).is_some(); -======= - --> $DIR/methods.rs:233:13 - | -233 | let _ = v.iter().filter(|&x| { - | _____________^ -234 | | *x < 0 -235 | | } -236 | | ).next(); - | |___________________________^ - -error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:248:13 + --> $DIR/methods.rs:251:13 | -248 | let _ = v.iter().find(|&x| *x < 0).is_some(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +251 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. -<<<<<<< HEAD - --> $DIR/methods.rs:231:13 + --> $DIR/methods.rs:254:13 | -231 | let _ = v.iter().find(|&x| { +254 | let _ = v.iter().find(|&x| { | _____________^ -232 | | *x < 0 -233 | | } -234 | | ).is_some(); +255 | | *x < 0 +256 | | } +257 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:237:13 - | -237 | let _ = v.iter().position(|&x| x < 0).is_some(); -======= - --> $DIR/methods.rs:251:13 - | -251 | let _ = v.iter().find(|&x| { - | _____________^ -252 | | *x < 0 -253 | | } -254 | | ).is_some(); - | |______________________________^ - -error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:257:13 + --> $DIR/methods.rs:260:13 | -257 | let _ = v.iter().position(|&x| x < 0).is_some(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +260 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. -<<<<<<< HEAD - --> $DIR/methods.rs:240:13 - | -240 | let _ = v.iter().position(|&x| { - | _____________^ -241 | | x < 0 -242 | | } -243 | | ).is_some(); - | |______________________________^ - -error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:246:13 - | -246 | let _ = v.iter().rposition(|&x| x < 0).is_some(); -======= - --> $DIR/methods.rs:260:13 + --> $DIR/methods.rs:263:13 | -260 | let _ = v.iter().position(|&x| { +263 | let _ = v.iter().position(|&x| { | _____________^ -261 | | x < 0 -262 | | } -263 | | ).is_some(); +264 | | x < 0 +265 | | } +266 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:266:13 + --> $DIR/methods.rs:269:13 | -266 | let _ = v.iter().rposition(|&x| x < 0).is_some(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +269 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. -<<<<<<< HEAD - --> $DIR/methods.rs:249:13 + --> $DIR/methods.rs:272:13 | -249 | let _ = v.iter().rposition(|&x| { +272 | let _ = v.iter().rposition(|&x| { | _____________^ -250 | | x < 0 -251 | | } -252 | | ).is_some(); +273 | | x < 0 +274 | | } +275 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:266:21 + --> $DIR/methods.rs:289:21 | -266 | fn new() -> Foo { Foo } +289 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:284:5 - | -284 | with_constructor.unwrap_or(make()); -======= - --> $DIR/methods.rs:269:13 - | -269 | let _ = v.iter().rposition(|&x| { - | _____________^ -270 | | x < 0 -271 | | } -272 | | ).is_some(); - | |______________________________^ - -error: unnecessary structure name repetition - --> $DIR/methods.rs:286:21 - | -286 | fn new() -> Foo { Foo } - | ^^^ help: use the applicable keyword: `Self` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:304:5 + --> $DIR/methods.rs:307:5 | -304 | with_constructor.unwrap_or(make()); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +307 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` -<<<<<<< HEAD - --> $DIR/methods.rs:287:5 - | -287 | with_new.unwrap_or(Vec::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:290:5 - | -290 | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:293:5 - | -293 | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:296:5 - | -296 | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:299:5 - | -299 | with_default_trait.unwrap_or(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:302:5 - | -302 | with_default_type.unwrap_or(u64::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:305:5 - | -305 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` - -error: use of `unwrap_or` followed by a function call --> $DIR/methods.rs:310:5 | -310 | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:313:5 - | -313 | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:316:5 - | -316 | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:319:13 - | -319 | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` - -error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:330:23 - | -330 | let bad_vec = some_vec.iter().nth(3); -======= - --> $DIR/methods.rs:307:5 - | -307 | with_new.unwrap_or(Vec::new()); +310 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:310:5 + --> $DIR/methods.rs:313:5 | -310 | with_const_args.unwrap_or(Vec::with_capacity(12)); +313 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:313:5 + --> $DIR/methods.rs:316:5 | -313 | with_err.unwrap_or(make()); +316 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:5 + --> $DIR/methods.rs:319:5 | -316 | with_err_args.unwrap_or(Vec::with_capacity(12)); +319 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:319:5 + --> $DIR/methods.rs:322:5 | -319 | with_default_trait.unwrap_or(Default::default()); +322 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:322:5 + --> $DIR/methods.rs:325:5 | -322 | with_default_type.unwrap_or(u64::default()); +325 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:325:5 + --> $DIR/methods.rs:328:5 | -325 | with_vec.unwrap_or(vec![]); +328 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:330:5 + --> $DIR/methods.rs:333:5 | -330 | without_default.unwrap_or(Foo::new()); +333 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:333:5 + --> $DIR/methods.rs:336:5 | -333 | map.entry(42).or_insert(String::new()); +336 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:336:5 + --> $DIR/methods.rs:339:5 | -336 | btree.entry(42).or_insert(String::new()); +339 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:339:13 + --> $DIR/methods.rs:342:13 | -339 | let _ = stringy.unwrap_or("".to_owned()); +342 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:350:23 + --> $DIR/methods.rs:353:23 | -350 | let bad_vec = some_vec.iter().nth(3); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +353 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable -<<<<<<< HEAD - --> $DIR/methods.rs:331:26 + --> $DIR/methods.rs:354:26 | -331 | let bad_slice = &some_vec[..].iter().nth(3); +354 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:332:31 + --> $DIR/methods.rs:355:31 | -332 | let bad_boxed_slice = boxed_slice.iter().nth(3); +355 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:333:29 + --> $DIR/methods.rs:356:29 | -333 | let bad_vec_deque = some_vec_deque.iter().nth(3); +356 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:338:23 + --> $DIR/methods.rs:361:23 | -338 | let bad_vec = some_vec.iter_mut().nth(3); +361 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:341:26 + --> $DIR/methods.rs:364:26 | -341 | let bad_slice = &some_vec[..].iter_mut().nth(3); +364 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:344:29 + --> $DIR/methods.rs:367:29 | -344 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +367 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:356:13 + --> $DIR/methods.rs:379:13 | -356 | let _ = some_vec.iter().skip(42).next(); -======= - --> $DIR/methods.rs:351:26 - | -351 | let bad_slice = &some_vec[..].iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:352:31 - | -352 | let bad_boxed_slice = boxed_slice.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:353:29 - | -353 | let bad_vec_deque = some_vec_deque.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:358:23 - | -358 | let bad_vec = some_vec.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:361:26 - | -361 | let bad_slice = &some_vec[..].iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:364:29 - | -364 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:376:13 - | -376 | let _ = some_vec.iter().skip(42).next(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +379 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` -<<<<<<< HEAD - --> $DIR/methods.rs:357:13 - | -357 | let _ = some_vec.iter().cycle().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:358:13 - | -358 | let _ = (1..10).skip(10).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:359:14 - | -359 | let _ = &some_vec[..].iter().skip(3).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:368:13 - | -368 | let _ = opt.unwrap(); -======= - --> $DIR/methods.rs:377:13 + --> $DIR/methods.rs:380:13 | -377 | let _ = some_vec.iter().cycle().skip(42).next(); +380 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:378:13 + --> $DIR/methods.rs:381:13 | -378 | let _ = (1..10).skip(10).next(); +381 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:379:14 + --> $DIR/methods.rs:382:14 | -379 | let _ = &some_vec[..].iter().skip(3).next(); +382 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:388:13 + --> $DIR/methods.rs:391:13 | -388 | let _ = opt.unwrap(); ->>>>>>> 47be6927239cc8dabeb59764581fc4ac73327f22 +391 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From cad33c0306ecc73e280a063700c2878798cbc348 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 3 Nov 2017 17:24:10 +0900 Subject: Extend needless_pass_by_value to methods --- clippy_lints/src/needless_pass_by_value.rs | 48 +++++++++++++++++++++++------- tests/ui/needless_pass_by_value.rs | 25 +++++++++++++++- tests/ui/needless_pass_by_value.stderr | 18 +++++++++++ 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index e00938fb3ef..ac965a59bd5 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,4 +1,5 @@ use rustc::hir::*; +use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::ty::{self, RegionKind, TypeFoldable}; @@ -22,13 +23,20 @@ use std::borrow::Cow; /// sometimes avoid /// unnecessary allocations. /// -/// **Known problems:** Hopefully none. +/// **Known problems:** +/// * This lint suggests taking an argument by reference, +/// however sometimes it is better to let users decide the argument type +/// (by using `Borrow` trait, for example), depending on how the function is used. /// /// **Example:** /// ```rust /// fn foo(v: Vec) { /// assert_eq!(v.len(), 42); /// } +/// // should be +/// fn foo(v: &[i32]) { +/// assert_eq!(v.len(), 42); +/// } /// ``` declare_lint! { pub NEEDLESS_PASS_BY_VALUE, @@ -73,9 +81,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } } }, + FnKind::Method(..) => (), _ => return, } + // Exclude non-inherent impls + if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemDefaultImpl(..)) { + return; + } + } + // Allow `Borrow` or functions to be taken by value let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); let fn_traits = [ @@ -109,7 +125,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } = { let mut ctx = MovedVariablesCtxt::new(cx); let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); - euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body); + euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None) + .consume_body(body); ctx }; @@ -127,6 +144,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { return; } + // Ignore `self`s. + if idx == 0 { + if let PatKind::Binding(_, _, name, ..) = arg.pat.node { + if name.node.as_str() == "self" { + continue; + } + } + } + // * Exclude a type that is specifically bounded by `Borrow`. // * Exclude a type whose reference also fulfills its bound. // (e.g. `std::convert::AsRef`, `serde::Serialize`) @@ -163,7 +189,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { continue; } - + // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder| { let deref_span = spans_need_deref.get(&canonical_id); @@ -181,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { db.span_suggestion(input.span, "consider changing the type to", slice_ty); - + for (span, suggestion) in clone_spans { db.span_suggestion( span, @@ -193,18 +219,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { suggestion.into() ); } - + // cannot be destructured, no need for `*` suggestion assert!(deref_span.is_none()); return; } } - + if match_type(cx, ty, &paths::STRING) { if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); - + for (span, suggestion) in clone_spans { db.span_suggestion( span, @@ -216,14 +242,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { suggestion.into(), ); } - + assert!(deref_span.is_none()); return; } } - + let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; - + // Suggests adding `*` to dereference the added reference. if let Some(deref_span) = deref_span { spans.extend( @@ -236,7 +262,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } multispan_sugg(db, "consider taking a reference instead".to_string(), spans); }; - + span_lint_and_then( cx, NEEDLESS_PASS_BY_VALUE, diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index ac37b0bdda1..307acb45bcb 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -65,7 +65,7 @@ fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { trait Foo {} -// `S: Serialize` can be passed by value +// `S: Serialize` is allowed to be passed by value, since a caller can pass `&S` instead trait Serialize {} impl<'a, T> Serialize for &'a T where T: Serialize {} impl Serialize for i32 {} @@ -79,4 +79,27 @@ fn issue_2114(s: String, t: String, u: Vec, v: Vec) { let _ = v.clone(); } +struct S(T, U); + +impl S { + fn foo( + self, // taking `self` by value is always allowed + s: String, + t: String, + ) -> usize { + s.len() + t.capacity() + } + + fn bar( + _t: T, // Ok, since `&T: Serialize` too + ) { + } + + fn baz( + &self, + _u: U, + ) { + } +} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index f23b0714c59..3e4d0c7e44f 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -104,3 +104,21 @@ help: change `v.clone()` to 79 | let _ = v.to_owned(); | ^^^^^^^^^^^^ +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:87:12 + | +87 | s: String, + | ^^^^^^ help: consider changing the type to: `&str` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:88:12 + | +88 | t: String, + | ^^^^^^ help: consider taking a reference instead: `&String` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:100:13 + | +100 | _u: U, + | ^ help: consider taking a reference instead: `&U` + -- cgit 1.4.1-3-g733a5 From be7c4b48621b905eece89b4941fedaa2decec319 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 3 Nov 2017 17:24:28 +0900 Subject: Fix test --- clippy_lints/src/int_plus_one.rs | 1 + clippy_lints/src/utils/sugg.rs | 12 ++++++------ tests/ui/methods.rs | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 420427e7d0a..396b06524d0 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -45,6 +45,7 @@ impl LintPass for IntPlusOne { // x + 1 <= y // x <= y - 1 +#[derive(Copy, Clone)] enum Side { LHS, RHS, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d811de59844..388c1ae7e34 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::{EarlyContext, LateContext, LintContext}; use rustc_errors; -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; use std::fmt::Display; use std; use syntax::codemap::{CharPos, Span}; @@ -136,8 +136,8 @@ impl<'a> Sugg<'a> { } /// Convenience method to create the ` && ` suggestion. - pub fn and(self, rhs: Self) -> Sugg<'static> { - make_binop(ast::BinOpKind::And, &self, &rhs) + pub fn and>(self, rhs: R) -> Sugg<'static> { + make_binop(ast::BinOpKind::And, &self, rhs.borrow()) } /// Convenience method to create the ` as ` suggestion. @@ -162,10 +162,10 @@ impl<'a> Sugg<'a> { /// Convenience method to create the `..` or `...` /// suggestion. - pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> { + pub fn range>(self, end: E, limit: ast::RangeLimits) -> Sugg<'static> { match limit { - ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, &end), - ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, &end), + ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end.borrow()), + ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end.borrow()), } } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 6ecb3963154..c80f6acd06b 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,9 +1,9 @@ #![feature(const_fn)] - #![warn(clippy, clippy_pedantic)] -#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive, missing_docs_in_private_items)] +#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, + new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value)] use std::collections::BTreeMap; use std::collections::HashMap; -- cgit 1.4.1-3-g733a5 From c102d50ece44256c3b889d754b34375fb9496a33 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 3 Nov 2017 17:56:17 +0900 Subject: &Self --- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/utils/sugg.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 3ac19980a6d..fa0d7de6676 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -134,7 +134,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast: db.span_suggestion(expr.span, "try", format!("if {} {}", - lhs.and(rhs), + lhs.and(&rhs), snippet_block(cx, content.span, ".."))); }); } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 388c1ae7e34..3fd372052f6 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::{EarlyContext, LateContext, LintContext}; use rustc_errors; -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; use std::fmt::Display; use std; use syntax::codemap::{CharPos, Span}; @@ -136,8 +136,8 @@ impl<'a> Sugg<'a> { } /// Convenience method to create the ` && ` suggestion. - pub fn and>(self, rhs: R) -> Sugg<'static> { - make_binop(ast::BinOpKind::And, &self, rhs.borrow()) + pub fn and(self, rhs: &Self) -> Sugg<'static> { + make_binop(ast::BinOpKind::And, &self, rhs) } /// Convenience method to create the ` as ` suggestion. @@ -162,10 +162,10 @@ impl<'a> Sugg<'a> { /// Convenience method to create the `..` or `...` /// suggestion. - pub fn range>(self, end: E, limit: ast::RangeLimits) -> Sugg<'static> { + pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { - ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end.borrow()), - ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end.borrow()), + ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end), + ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end), } } -- cgit 1.4.1-3-g733a5 From d88cc5376e0cba84273161c8bc0d67127c6f9064 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 3 Nov 2017 17:56:26 +0900 Subject: Add test to take `Self` as an argument --- tests/ui/needless_pass_by_value.rs | 1 + tests/ui/needless_pass_by_value.stderr | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 307acb45bcb..f4d490b214f 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -98,6 +98,7 @@ impl S { fn baz( &self, _u: U, + _s: Self, ) { } } diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 3e4d0c7e44f..a6c0c0454cb 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -122,3 +122,9 @@ error: this argument is passed by value, but not consumed in the function body 100 | _u: U, | ^ help: consider taking a reference instead: `&U` +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:101:13 + | +101 | _s: Self, + | ^^^^ help: consider taking a reference instead: `&Self` + -- cgit 1.4.1-3-g733a5 From f92c91601e1f28dd29be7157010673a2b5b6b87d Mon Sep 17 00:00:00 2001 From: Alexandru Ene Date: Fri, 3 Nov 2017 20:54:33 +0000 Subject: Addressed PR comments --- clippy_lints/src/non_expressive_names.rs | 4 ++-- tests/ui/non_expressive_names.rs | 2 +- tests/ui/non_expressive_names.stderr | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index e4d7049bf01..408e6304a37 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -156,9 +156,9 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { if interned_name.chars().all(|c| c.is_digit(10) || c == '_') { span_lint( self.0.cx, - JUST_UNDERSCORES_AND_NUMBERS, + JUST_UNDERSCORES_AND_DIGITS, span, - "binding whose name is just underscores and digits", + "consider choosing a more descriptive name", ); return; } diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 16a035ca024..29a677004b8 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -140,4 +140,4 @@ fn underscores_and_numbers() { let ____1 = 1; //~ERROR Consider a more descriptive name let __1___2 = 12; //~ERROR Consider a more descriptive name let _1_ok= 1; -} \ No newline at end of file +} diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 7141c97dd1a..6412b47aab4 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -129,21 +129,21 @@ error: 5th binding whose name is just one char 129 | e => panic!(), | ^ -error: binding whose name is just underscores and digits +error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:139:9 | 139 | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ | - = note: `-D just-underscores-and-numbers` implied by `-D warnings` + = note: `-D just-underscores-and-digits` implied by `-D warnings` -error: binding whose name is just underscores and digits +error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:140:9 | 140 | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ -error: binding whose name is just underscores and digits +error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:141:9 | 141 | let __1___2 = 12; //~ERROR Consider a more descriptive name -- cgit 1.4.1-3-g733a5 From 65e75c56479112a3af16c95e09364d871b051fad Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 04:25:13 +0900 Subject: Fix excessive indentation in if_chain! --- clippy_lints/src/new_without_default.rs | 68 +++++++++++++++++---------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index e28d077f999..74465b64051 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -118,45 +118,47 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); if_chain! { - if same_tys(cx, self_ty, return_ty(cx, id)); - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); - if !implements_trait(cx, self_ty, default_trait_id, &[]); - then { - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); - }); - } else { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_prepend_item(cx, - span, - "try this", - &format!( -"impl Default for {} {{ - fn default() -> Self {{ - Self::new() - }} -}}", - self_ty)); - }); - } - } + if same_tys(cx, self_ty, return_ty(cx, id)); + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); + if !implements_trait(cx, self_ty, default_trait_id, &[]); + then { + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { + span_lint_and_then( + cx, + NEW_WITHOUT_DEFAULT_DERIVE, + span, + &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), + |db| { + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + }); + } else { + span_lint_and_then( + cx, + NEW_WITHOUT_DEFAULT, + span, + &format!("you should consider adding a `Default` implementation for `{}`", self_ty), + |db| { + db.suggest_prepend_item(cx, span, "try this", &create_new_without_default_suggest_msg(self_ty)); + }, + ); + } + } } } } } } +fn create_new_without_default_suggest_msg(ty: Ty) -> String { + #[rustfmt_skip] + format!( +"impl Default for {} {{ + fn default() -> Self {{ + Self::new() + }} +}}", ty) +} + fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option { match ty.sty { ty::TyAdt(adt_def, substs) if adt_def.is_struct() => { -- cgit 1.4.1-3-g733a5 From 2ca1d30348ffb973e359a1d84ef45f76ccbacb33 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 04:36:56 +0900 Subject: Update rustfmt.toml --- rustfmt.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 18d146d4917..205b7d897d3 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,8 +1,6 @@ max_width = 120 -ideal_width = 100 +comment_width = 100 fn_call_width = 80 match_block_trailing_comma = true -fn_args_layout = "Block" closure_block_indent_threshold = 0 -fn_return_indent = "WithWhereClause" wrap_comments = true -- cgit 1.4.1-3-g733a5 From 7a06d312fd4d900946f8dba8bae5baaf877e5103 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 04:55:56 +0900 Subject: Cargo fmt --- clippy_lints/src/array_indexing.rs | 10 +- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 18 +- clippy_lints/src/booleans.rs | 6 +- clippy_lints/src/bytecount.rs | 4 +- clippy_lints/src/const_static_lifetime.rs | 28 +-- clippy_lints/src/derive.rs | 12 +- clippy_lints/src/doc.rs | 16 +- clippy_lints/src/drop_forget_ref.rs | 4 +- clippy_lints/src/entry.rs | 6 +- clippy_lints/src/enum_clike.rs | 10 +- clippy_lints/src/enum_variants.rs | 7 +- clippy_lints/src/fallible_impl_from.rs | 8 +- clippy_lints/src/format.rs | 4 +- clippy_lints/src/formatting.rs | 4 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/int_plus_one.rs | 75 +++++--- clippy_lints/src/invalid_ref.rs | 13 +- clippy_lints/src/is_unit_expr.rs | 10 +- clippy_lints/src/len_zero.rs | 4 +- clippy_lints/src/let_if_seq.rs | 14 +- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/literal_digit_grouping.rs | 2 +- clippy_lints/src/loops.rs | 276 +++++++++++++++-------------- clippy_lints/src/matches.rs | 36 +++- clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 152 +++++++++------- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 38 ++-- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_continue.rs | 40 +++-- clippy_lints/src/needless_pass_by_value.rs | 14 +- clippy_lints/src/new_without_default.rs | 14 +- clippy_lints/src/no_effect.rs | 29 +-- clippy_lints/src/non_expressive_names.rs | 8 +- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 4 +- clippy_lints/src/panic.rs | 2 +- clippy_lints/src/print.rs | 8 +- clippy_lints/src/ptr.rs | 45 +++-- clippy_lints/src/ranges.rs | 21 +-- clippy_lints/src/regex.rs | 7 +- clippy_lints/src/shadow.rs | 12 +- clippy_lints/src/strings.rs | 4 +- clippy_lints/src/swap.rs | 16 +- clippy_lints/src/transmute.rs | 110 +++++++----- clippy_lints/src/types.rs | 4 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 4 +- clippy_lints/src/utils/higher.rs | 13 +- clippy_lints/src/utils/hir_utils.rs | 48 ++--- clippy_lints/src/utils/mod.rs | 43 +++-- clippy_lints/src/utils/sugg.rs | 22 +-- src/driver.rs | 14 +- src/main.rs | 3 +- tests/conf_whitelisted.rs | 3 +- tests/dogfood.rs | 4 +- tests/issue-825.rs | 6 +- 59 files changed, 716 insertions(+), 558 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index aa2d6db6853..8949e4cc387 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -120,13 +120,19 @@ fn to_const_range( array_size: ConstInt, ) -> Option<(ConstInt, ConstInt)> { let start = match *start { - Some(Some(&ty::Const { val: ConstVal::Integral(x), .. })) => x, + Some(Some(&ty::Const { + val: ConstVal::Integral(x), + .. + })) => x, Some(_) => return None, None => ConstInt::U8(0), }; let end = match *end { - Some(Some(&ty::Const { val: ConstVal::Integral(x), .. })) => if limits == RangeLimits::Closed { + Some(Some(&ty::Const { + val: ConstVal::Integral(x), + .. + })) => if limits == RangeLimits::Closed { match x { ConstInt::U8(_) => (x + ConstInt::U8(1)), ConstInt::U16(_) => (x + ConstInt::U16(1)), diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 8baff551910..da7fff2ed93 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then, opt_def_id}; +use utils::{in_macro, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index af99b77163b..a89959d9506 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition"; const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks or closures with blocks; \ - instead, move the block or closure higher and bind it with a 'let'"; + instead, move the block or closure higher and bind it with a 'let'"; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -92,9 +92,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { BLOCK_IN_IF_CONDITION_EXPR, check.span, BRACED_EXPR_MESSAGE, - &format!("try\nif {} {} ... ", - snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, "..")), + &format!( + "try\nif {} {} ... ", + snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, "..") + ), ); } } else { @@ -111,9 +113,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { BLOCK_IN_IF_CONDITION_STMT, check.span, COMPLEX_BLOCK_MESSAGE, - &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, "..")), + &format!( + "try\nlet res = {};\nif res {} ... ", + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, "..") + ), ); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 2587937616c..ca3fb4017df 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -368,9 +368,9 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } // if the number of occurrences of a terminal decreases or any of the stats // decreases while none increases - improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) || - (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) || - (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); + improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) + || (stats.negations > simplified_stats.negations && stats.ops == simplified_stats.ops) + || (stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); } if improvement { improvements.push(suggestion); diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index e0ce4bbc93b..886834e3981 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -2,8 +2,8 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; use syntax::ast::{Name, UintTy}; -use utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, - snippet, span_lint_and_sugg, walk_ptrs_ty}; +use utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, + walk_ptrs_ty}; /// **What it does:** Checks for naive byte counts /// diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 03771f0375b..6ee4dad7db4 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,6 +1,6 @@ -use syntax::ast::{Item, ItemKind, TyKind, Ty}; -use rustc::lint::{LintPass, EarlyLintPass, LintArray, EarlyContext}; -use utils::{span_lint_and_then, in_macro}; +use syntax::ast::{Item, ItemKind, Ty, TyKind}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use utils::{in_macro, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// @@ -20,7 +20,7 @@ use utils::{span_lint_and_then, in_macro}; /// ``` declare_lint! { - pub CONST_STATIC_LIFETIME, + pub CONST_STATIC_LIFETIME, Warn, "Using explicit `'static` lifetime for constants when elision rules would allow omitting them." } @@ -41,10 +41,8 @@ impl StaticConst { TyKind::Array(ref ty, _) => { self.visit_type(&*ty, cx); }, - TyKind::Tup(ref tup) => { - for tup_ty in tup { - self.visit_type(&*tup_ty, cx); - } + TyKind::Tup(ref tup) => for tup_ty in tup { + self.visit_type(&*tup_ty, cx); }, // This is what we are looking for ! TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { @@ -54,11 +52,15 @@ impl StaticConst { // Verify that the path is a str if lifetime.ident.name == "'static" { let mut sug: String = String::new(); - span_lint_and_then(cx, - CONST_STATIC_LIFETIME, - lifetime.span, - "Constants have by default a `'static` lifetime", - |db| {db.span_suggestion(lifetime.span,"consider removing `'static`",sug);}); + span_lint_and_then( + cx, + CONST_STATIC_LIFETIME, + lifetime.span, + "Constants have by default a `'static` lifetime", + |db| { + db.span_suggestion(lifetime.span, "consider removing `'static`", sug); + }, + ); } } } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2c45aaf6ac9..6ce67a9b05c 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -98,13 +98,13 @@ fn check_hash_peq<'a, 'tcx>( // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); - + if peq_is_automatically_derived == hash_is_automatically_derived { return; } - + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - + // Only care about `impl PartialEq for Foo` // For `impl PartialEq for A, input_types is [A, B] if trait_ref.substs.type_at(1) == ty { @@ -113,7 +113,7 @@ fn check_hash_peq<'a, 'tcx>( } else { "you are deriving `Hash` but have implemented `PartialEq` explicitly" }; - + span_lint_and_then( cx, DERIVE_HASH_XOR_EQ, span, mess, @@ -157,7 +157,9 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref EXPL_IMPL_CLONE_ON_COPY, item.span, "you are implementing `Clone` explicitly on a `Copy` type", - |db| { db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }, + |db| { + db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); + }, ); } } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 9ed09d96e1b..b6542b2ebca 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -204,7 +204,7 @@ fn check_doc<'a, Events: Iterator)>>( End(CodeBlock(_)) | End(Code) => in_code = false, Start(Link(link, _)) => in_link = Some(link), End(Link(_, _)) => in_link = None, - Start(_tag) | End(_tag) => (), // We don't care about other tags + Start(_tag) | End(_tag) => (), // We don't care about other tags Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it SoftBreak => (), HardBreak => (), @@ -273,8 +273,8 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { s }; - s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && - s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 + s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 + && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 } fn has_underscore(s: &str) -> bool { @@ -284,10 +284,12 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) { if let Ok(url) = Url::parse(word) { // try to get around the fact that `foo::bar` parses as a valid URL if !url.cannot_be_a_base() { - span_lint(cx, - DOC_MARKDOWN, - span, - "you should put bare URLs between `<`/`>` or make a proper Markdown link"); + span_lint( + cx, + DOC_MARKDOWN, + span, + "you should put bare URLs between `<`/`>` or make a proper Markdown link", + ); return; } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 1601c276e2b..c523c569a68 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{is_copy, match_def_path, paths, span_note_and_lint, opt_def_id}; +use utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let msg; let arg = &args[0]; let arg_ty = cx.tables.expr_ty(arg); - + if let ty::TyRef(..) = arg_ty.sty { if match_def_path(cx.tcx, def_id, &paths::DROP) { lint = DROP_REF; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 6c7a5fec03c..b86a4a43fb1 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -95,7 +95,7 @@ fn check_cond<'a, 'tcx, 'b>( then { let map = ¶ms[0]; let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map)); - + return if match_type(cx, obj_ty, &paths::BTREEMAP) { Some(("BTreeMap", map, key)) } @@ -136,14 +136,14 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, ".."), snippet(self.cx, params[2].span, "..")); - + db.span_suggestion(self.span, "consider using", help); } else { let help = format!("{}.entry({})", snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, "..")); - + db.span_suggestion(self.span, "consider using", help); } }); diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index c019ab0b385..c65cf92590a 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -55,8 +55,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { .at(expr.span) .const_eval(param_env.and((did, substs))) { - Ok(&ty::Const { val: ConstVal::Integral(Usize(Us64(i))), .. }) => u64::from(i as u32) != i, - Ok(&ty::Const { val: ConstVal::Integral(Isize(Is64(i))), .. }) => i64::from(i as i32) != i, + Ok(&ty::Const { + val: ConstVal::Integral(Usize(Us64(i))), + .. + }) => u64::from(i as u32) != i, + Ok(&ty::Const { + val: ConstVal::Integral(Isize(Is64(i))), + .. + }) => i64::from(i as i32) != i, _ => false, }; if bad { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 6dc6f122eba..ea7a378de22 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -159,8 +159,11 @@ fn check_variant( } for var in &def.variants { let name = var2str(var); - if partial_match(item_name, &name) == item_name_chars && - name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) { + if partial_match(item_name, &name) == item_name_chars + && name.chars() + .nth(item_name_chars) + .map_or(false, |c| !c.is_lowercase()) + { span_lint(cx, lint, var.span, "Variant name starts with the enum's name"); } if partial_rmatch(item_name, &name) == item_name_chars { diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index e6efd41e6fb..0c91d0cd97c 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir; use rustc::ty; use syntax_pos::Span; -use utils::{method_chain_args, match_def_path, span_lint_and_then, walk_ptrs_ty}; +use utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` @@ -74,9 +74,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); - if match_type(self.tcx, reciever_ty, &OPTION) || - match_type(self.tcx, reciever_ty, &RESULT) - { + if match_type(self.tcx, reciever_ty, &OPTION) || match_type(self.tcx, reciever_ty, &RESULT) { self.result.push(expr.span); } } @@ -105,7 +103,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it result: Vec::new(), }; fpu.visit_expr(&body.value); - + // if we've found one, lint if !fpu.result.is_empty() { span_lint_and_then( diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 8004dc17083..dcafbc50d0c 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; use utils::paths; -use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty, opt_def_id}; +use utils::{is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, span_lint, walk_ptrs_ty}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -109,7 +109,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); - + return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING); } } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 7d712942986..e016fa3d595 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -190,8 +190,8 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) { /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { - if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() && - unsugar_if(second).is_some() + if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() + && unsugar_if(second).is_some() { // where the else would be let else_span = first.span.between(second.span); diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 85dfb6b4ad0..e1d84a07439 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -70,7 +70,7 @@ fn all_ones(v: &ConstInt) -> bool { ConstInt::U32(i) => i == !0, ConstInt::U64(i) => i == !0, ConstInt::U128(i) => i == !0, - _ => false + _ => false, } } diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 3cdffbf82ae..d7d98351647 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{span_help_and_lint, in_external_macro}; +use utils::{in_external_macro, span_help_and_lint}; /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an /// else branch. diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 396b06524d0..6e74547b75f 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{span_lint_and_then, snippet_opt}; +use utils::{snippet_opt, span_lint_and_then}; /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block /// @@ -55,7 +55,7 @@ impl IntPlusOne { #[allow(cast_sign_loss)] fn check_lit(&self, lit: &Lit, target_value: i128) -> bool { if let LitKind::Int(value, ..) = lit.node { - return value == (target_value as u128) + return value == (target_value as u128); } false } @@ -66,49 +66,76 @@ impl IntPlusOne { (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { match (lhskind.node, &lhslhs.node, &lhsrhs.node) { // `-1 + x` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS), + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => { + self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS) + }, // `x - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS), - _ => None + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS) + }, + _ => None, } }, // case where `... >= y + 1` or `... >= 1 + y` - (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) if rhskind.node == BinOpKind::Add => { + (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) + if rhskind.node == BinOpKind::Add => + { match (&rhslhs.node, &rhsrhs.node) { // `y + 1` and `1 + y` - (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS), - (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS), - _ => None + (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS) + }, + (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS) + }, + _ => None, } - }, + } // case where `x + 1 <= ...` or `1 + x <= ...` - (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => { + (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) + if lhskind.node == BinOpKind::Add => + { match (&lhslhs.node, &lhsrhs.node) { // `1 + x` and `x + 1` - (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS), - (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS), - _ => None + (&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS) + }, + (_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS) + }, + _ => None, } - }, + } // case where `... >= y - 1` or `... >= -1 + y` (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => { match (rhskind.node, &rhslhs.node, &rhsrhs.node) { // `-1 + y` - (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS), + (BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => { + self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS) + }, // `y - 1` - (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS), - _ => None + (BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => { + self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS) + }, + _ => None, } }, - _ => None + _ => None, } } - fn generate_recommendation(&self, cx: &EarlyContext, binop: BinOpKind, node: &Expr, other_side: &Expr, side: Side) -> Option { + fn generate_recommendation( + &self, + cx: &EarlyContext, + binop: BinOpKind, + node: &Expr, + other_side: &Expr, + side: Side, + ) -> Option { let binop_string = match binop { BinOpKind::Ge => ">", BinOpKind::Le => "<", - _ => return None + _ => return None, }; if let Some(snippet) = snippet_opt(cx, node.span) { if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) { @@ -123,11 +150,7 @@ impl IntPlusOne { } fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: String) { - span_lint_and_then(cx, - INT_PLUS_ONE, - block.span, - "Unnecessary `>= y + 1` or `x - 1 >=`", - |db| { + span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation); }); } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 649e1f7ac78..8cc12323fd5 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,13 +1,13 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, paths, span_help_and_lint, opt_def_id}; +use utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. /// /// **Why is this bad?** Creation of null references is undefined behavior. /// -/// **Known problems:** None. +/// **Known problems:** None. /// /// **Example:** /// ```rust @@ -22,9 +22,10 @@ declare_lint! { const ZERO_REF_SUMMARY: &str = "reference to zeroed memory"; const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; -const HELP: &str = "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; +const HELP: &str = + "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; -pub struct InvalidRef; +pub struct InvalidRef; impl LintPass for InvalidRef { fn get_lints(&self) -> LintArray { @@ -38,7 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { if let ExprCall(ref path, ref args) = expr.node; if let ExprPath(ref qpath) = path.node; if args.len() == 0; - if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; + if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); then { let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { @@ -50,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { }; span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP); } - } + } return; } } diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 734ef1ecb76..3f94178e524 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -139,13 +139,9 @@ fn check_last_stmt_in_block(block: &Block) -> bool { // like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, - StmtKind::Semi(ref expr) => { - match expr.node { - ExprKind::Break(_, _) | - ExprKind::Continue(_) | - ExprKind::Ret(_) => false, - _ => true, - } + StmtKind::Semi(ref expr) => match expr.node { + ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => false, + _ => true, }, _ => true, } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 9b14a44f2c0..967688e4f46 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -119,8 +119,8 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai .iter() .flat_map(|&i| cx.tcx.associated_items(i)) .any(|i| { - i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.name == "is_empty" && - cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 + i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.name == "is_empty" + && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); if !is_empty_method_found { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 931b872e036..34863208fde 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if !used_in_expr(cx, canonical_id, value); then { let span = stmt.span.to(if_.span); - + let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { if let hir::ExprBlock(ref else_) = else_.node { if let Some(default) = check_assign(cx, canonical_id, else_) { @@ -94,15 +94,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { } else { continue; }; - + let mutability = match mode { BindingAnnotation::RefMut | BindingAnnotation::Mutable => " ", _ => "", }; - + // FIXME: this should not suggest `mut` if we can detect that the variable is not // use mutably after the `if` - + let sug = format!( "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", mut=mutability, @@ -174,15 +174,15 @@ fn check_assign<'a, 'tcx>( id: decl, used: false, }; - + for s in block.stmts.iter().take(block.stmts.len()-1) { hir::intravisit::walk_stmt(&mut v, s); - + if v.used { return None; } } - + return Some(value); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5549c98aaf3..0f8f4610871 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,8 +11,7 @@ #![feature(inclusive_range_syntax, range_contains)] #![feature(macro_vis_matcher)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] - -#![recursion_limit="256"] +#![recursion_limit = "256"] #[macro_use] extern crate rustc; diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index 91e4c567488..011b5ec1d5e 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -270,7 +270,7 @@ impl LiteralDigitGrouping { .digits .split_terminator('.') .collect(); - + // Lint integral and fractional parts separately, and then check consistency of digit // groups if both pass. let _ = Self::do_lint(parts[0]) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2e6835b7f68..2d994d468c6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -16,7 +16,7 @@ use rustc::ty::{self, Ty}; use rustc::ty::subst::{Subst, Substs}; use rustc_const_eval::ConstContext; use std::collections::{HashMap, HashSet}; -use std::iter::{Iterator, once}; +use std::iter::{once, Iterator}; use syntax::ast; use syntax::codemap::Span; use utils::sugg; @@ -377,8 +377,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { - ExprWhile(_, ref block, _) | - ExprLoop(ref block, _, _) => { + ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { let mut state = NeverLoopState { breaks: HashSet::new(), continues: HashSet::new(), @@ -413,11 +412,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | - MatchSource::IfLetDesugar { .. } => { - if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() && - is_simple_break_expr(&arms[1].body) + MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { + if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() + && arms[1].pats.len() == 1 && arms[1].guard.is_none() + && is_simple_break_expr(&arms[1].body) { if in_external_macro(cx, expr.span) { return; @@ -449,15 +447,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) + if let ( + &PatKind::TupleStruct(ref qpath, ref pat_args, _), + &ExprMethodCall(ref method_path, _, ref method_args), + ) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); - if method_path.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) && - lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) && - !is_iterator_used_after_while_let(cx, iter_expr) && - !is_nested(cx, expr, &method_args[0]) + if method_path.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) + && lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) + && !is_iterator_used_after_while_let(cx, iter_expr) + && !is_nested(cx, expr, &method_args[0]) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = snippet(cx, pat_args[0].span, "_"); @@ -505,8 +505,7 @@ fn never_loop_block(block: &Block, state: &mut NeverLoopState) -> bool { fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { match stmt.node { - StmtSemi(ref e, ..) | - StmtExpr(ref e, ..) => Some(e), + StmtSemi(ref e, ..) | StmtExpr(ref e, ..) => Some(e), StmtDecl(ref d, ..) => decl_to_expr(d), } } @@ -528,9 +527,9 @@ fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => never_loop_expr(e, state), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => never_loop_expr_seq(&mut es.iter(), state), + ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => { + never_loop_expr_seq(&mut es.iter(), state) + }, ExprCall(ref e, ref es) => never_loop_expr_seq(&mut once(&**e).chain(es.iter()), state), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | @@ -567,12 +566,16 @@ fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { }, ExprBlock(ref b) => never_loop_block(b, state), ExprAgain(d) => { - let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); + let id = d.target_id + .opt_id() + .expect("target id can only be missing in the presence of compilation errors"); state.continues.insert(id); false }, ExprBreak(d, _) => { - let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); + let id = d.target_id + .opt_id() + .expect("target id can only be missing in the presence of compilation errors"); state.breaks.insert(id); false }, @@ -586,12 +589,14 @@ fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { } } -fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, state: &mut NeverLoopState) -> bool { - es.map(|e| never_loop_expr(e, state)).fold(true, |a, b| a && b) +fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, state: &mut NeverLoopState) -> bool { + es.map(|e| never_loop_expr(e, state)) + .fold(true, |a, b| a && b) } -fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, state: &mut NeverLoopState) -> bool { - e.map(|e| never_loop_expr(e, state)).fold(false, |a, b| a || b) +fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, state: &mut NeverLoopState) -> bool { + e.map(|e| never_loop_expr(e, state)) + .fold(false, |a, b| a || b) } fn check_for_loop<'a, 'tcx>( @@ -665,11 +670,9 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option { match e.node { - ExprLit(ref l) => { - match l.node { - ast::LitKind::Int(x, _ty) => Some(x.to_string()), - _ => None, - } + ExprLit(ref l) => match l.node { + ast::LitKind::Int(x, _ty) => Some(x.to_string()), + _ => None, }, ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), _ => None, @@ -683,29 +686,25 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: } let offset = match idx.node { - ExprBinary(op, ref lhs, ref rhs) => { - match op.node { - BinOp_::BiAdd => { - let offset_opt = if same_var(cx, lhs, var) { - extract_offset(cx, rhs, var) - } else if same_var(cx, rhs, var) { - extract_offset(cx, lhs, var) - } else { - None - }; + ExprBinary(op, ref lhs, ref rhs) => match op.node { + BinOp_::BiAdd => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; - offset_opt.map(Offset::positive) - }, - BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), - _ => None, - } + offset_opt.map(Offset::positive) + }, + BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), + _ => None, }, - ExprPath(..) => { - if same_var(cx, idx, var) { - Some(Offset::positive("0".into())) - } else { - None - } + ExprPath(..) => if same_var(cx, idx, var) { + Some(Offset::positive("0".into())) + } else { + None }, _ => None, }; @@ -777,12 +776,13 @@ fn get_indexed_assignments<'a, 'tcx>( .iter() .map(|stmt| match stmt.node { Stmt_::StmtDecl(..) => None, - Stmt_::StmtExpr(ref e, _node_id) | - Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), }) - .chain(expr.as_ref().into_iter().map(|e| { - Some(get_assignment(cx, &*e, var)) - })) + .chain( + expr.as_ref() + .into_iter() + .map(|e| Some(get_assignment(cx, &*e, var))), + ) .filter_map(|op| op) .collect::>>() .unwrap_or_else(|| vec![]) @@ -801,20 +801,18 @@ fn detect_manual_memcpy<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.node { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), - ("0", _, x, false) | - (x, false, "0", false) => x.into(), - ("0", _, x, true) | - (x, false, "0", true) => format!("-{}", x), + ("0", _, x, false) | (x, false, "0", false) => x.into(), + ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), (x, false, y, true) => format!("({} - {})", x, y), (x, true, y, false) => format!("({} - {})", y, x), @@ -897,10 +895,10 @@ fn check_for_loop_range<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { @@ -917,9 +915,11 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable, and indexed it directly // (`indexed_directly` is subset of `indexed`) if visitor.indexed.len() == 1 && visitor.indexed_directly.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed_directly.into_iter().next().expect( - "already checked that we have exactly 1 element", - ); + let (indexed, indexed_extent) = visitor + .indexed_directly + .into_iter() + .next() + .expect("already checked that we have exactly 1 element"); // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { @@ -1024,10 +1024,10 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr, expr: &'tcx Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(arg) + start: Some(start), + end: Some(end), + limits, + }) = higher::range(arg) { // ...and both sides are compile-time constant integers... let parent_item = cx.tcx.hir.get_parent(arg.id); @@ -1041,10 +1041,16 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, end_idx) { - (&ty::Const { val: ConstVal::Integral(start_idx), .. }, - &ty::Const { val: ConstVal::Integral(end_idx), .. }) => { - (start_idx > end_idx, start_idx == end_idx) - }, + ( + &ty::Const { + val: ConstVal::Integral(start_idx), + .. + }, + &ty::Const { + val: ConstVal::Integral(end_idx), + .. + }, + ) => (start_idx > end_idx, start_idx == end_idx), _ => (false, false), }; @@ -1132,7 +1138,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. ty::TypeVariants::TyArray(_, size) if const_to_u64(size) > 32 => (), - _ => lint_iter_method(cx, args, arg, method_name) + _ => lint_iter_method(cx, args, arg, method_name), }; } else { let object = snippet(cx, args[0].span, "_"); @@ -1219,14 +1225,14 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| { - map.get_enclosing_scope(id) - }); + let parent_scope = map.get_enclosing_scope(expr.id) + .and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter( - |&(_, v)| *v == VarState::IncrOnce, - ) + for (id, _) in visitor + .states + .iter() + .filter(|&(_, v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { cx: cx, @@ -1273,12 +1279,10 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ref tam) => { - match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), - (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), - _ => return, - } + ty::TyRef(_, ref tam) => match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), + _ => return, }, _ => return, }; @@ -1322,14 +1326,11 @@ struct MutateDelegate { } impl<'tcx> Delegate<'tcx> for MutateDelegate { - fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) { - } + fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) {} - fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) { - } + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} - fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) { - } + fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) {} fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { @@ -1355,8 +1356,7 @@ impl<'tcx> Delegate<'tcx> for MutateDelegate { } } - fn decl_without_init(&mut self, _: NodeId, _: Span) { - } + fn decl_without_init(&mut self, _: NodeId, _: Span) {} } impl<'tcx> MutateDelegate { @@ -1366,8 +1366,16 @@ impl<'tcx> MutateDelegate { } fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { - if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(arg) { - let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; + if let Some(higher::Range { + start: Some(start), + end: Some(end), + .. + }) = higher::range(arg) + { + let mut_ids = vec![ + check_for_mutability(cx, start), + check_for_mutability(cx, end), + ]; if mut_ids[0].is_some() || mut_ids[1].is_some() { let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids); mut_warn_with_span(cx, span_low); @@ -1378,7 +1386,12 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { fn mut_warn_with_span(cx: &LateContext, span: Option) { if let Some(sp) = span { - span_lint(cx, MUT_RANGE_BOUND, sp, "attempt to mutate range bound within loop; note that the range of the loop is unchanged"); + span_lint( + cx, + MUT_RANGE_BOUND, + sp, + "attempt to mutate range bound within loop; note that the range of the loop is unchanged", + ); } } @@ -1405,7 +1418,12 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { } fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { - let mut delegate = MutateDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, span_high: None }; + let mut delegate = MutateDelegate { + node_id_low: bound_ids[0], + node_id_high: bound_ids[1], + span_low: None, + span_high: None, + }; let def_id = def_id::DefId::local(body.hir_id.owner); let region_scope_tree = &cx.tcx.region_scope_tree(def_id); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(body); @@ -1430,7 +1448,7 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { struct UsedVisitor { var: ast::Name, // var to look for - used: bool, // has the var been used otherwise? + used: bool, // has the var been used otherwise? } impl<'tcx> Visitor<'tcx> for UsedVisitor { @@ -1652,12 +1670,9 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), - None if !block.stmts.is_empty() => { - match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), - StmtDecl(..) => None, - } + None if !block.stmts.is_empty() => match block.stmts[0].node { + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + StmtDecl(..) => None, }, _ => None, } @@ -1669,11 +1684,9 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(dest, ref passed_expr) if dest.ident.is_none() && passed_expr.is_none() => true, - ExprBlock(ref b) => { - match extract_first_expr(b) { - Some(subexpr) => is_simple_break_expr(subexpr), - None => false, - } + ExprBlock(ref b) => match extract_first_expr(b) { + Some(subexpr) => is_simple_break_expr(subexpr), + None => false, }, _ => false, } @@ -1684,7 +1697,7 @@ fn is_simple_break_expr(expr: &Expr) -> bool { // at the start of the loop. #[derive(PartialEq)] enum VarState { - Initial, // Not examined yet + Initial, // Not examined yet IncrOnce, // Incremented exactly once, may be a loop counter Declared, // Declared but not (yet) initialized to zero Warn, @@ -1693,9 +1706,9 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'a, 'tcx>, // context reference states: HashMap, // incremented variables - depth: u32, // depth of conditional expressions + depth: u32, // depth of conditional expressions done: bool, } @@ -1749,7 +1762,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { /// Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, // context reference - end_expr: &'tcx Expr, // the for loop. Stop scanning here. + end_expr: &'tcx Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, name: Option, @@ -1881,13 +1894,11 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool return false; } match cx.tcx.hir.find(parent) { - Some(NodeExpr(expr)) => { - match expr.node { - ExprLoop(..) | ExprWhile(..) => { - return true; - }, - _ => (), - } + Some(NodeExpr(expr)) => match expr.node { + ExprLoop(..) | ExprWhile(..) => { + return true; + }, + _ => (), }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { @@ -1911,8 +1922,8 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool #[derive(PartialEq, Eq)] enum Nesting { - Unknown, // no nesting detected yet - RuledOut, // the iterator is initialized or assigned within scope + Unknown, // no nesting detected yet + RuledOut, // the iterator is initialized or assigned within scope LookFurther, // no nesting detected, no further walk required } @@ -1942,11 +1953,8 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprAssign(ref path, _) | - ExprAssignOp(_, ref path, _) => { - if match_var(path, self.iterator) { - self.nesting = RuledOut; - } + ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { + self.nesting = RuledOut; }, _ => walk_expr(self, expr), } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 18ba34f8621..dd3b2f00b7d 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -412,7 +412,11 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match } /// Get all arms that are unbounded `PatRange`s. -fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm], id: NodeId) -> Vec>> { +fn all_ranges<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + arms: &'tcx [Arm], + id: NodeId, +) -> Vec>> { let parent_item = cx.tcx.hir.get_parent(id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); @@ -471,15 +475,39 @@ fn type_ranges(ranges: &[SpannedRange<&ty::Const>]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { - (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Included(&ty::Const { val: ConstVal::Integral(end), .. })) => Some(SpannedRange { + ( + &ty::Const { + val: ConstVal::Integral(start), + .. + }, + Bound::Included(&ty::Const { + val: ConstVal::Integral(end), + .. + }), + ) => Some(SpannedRange { span: range.span, node: (start, Bound::Included(end)), }), - (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Excluded(&ty::Const { val: ConstVal::Integral(end), .. })) => Some(SpannedRange { + ( + &ty::Const { + val: ConstVal::Integral(start), + .. + }, + Bound::Excluded(&ty::Const { + val: ConstVal::Integral(end), + .. + }), + ) => Some(SpannedRange { span: range.span, node: (start, Bound::Excluded(end)), }), - (&ty::Const { val: ConstVal::Integral(start), .. }, Bound::Unbounded) => Some(SpannedRange { + ( + &ty::Const { + val: ConstVal::Integral(start), + .. + }, + Bound::Unbounded, + ) => Some(SpannedRange { span: range.span, node: (start, Bound::Unbounded), }), diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 43409eaea50..103dbb72229 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{match_def_path, paths, span_lint, opt_def_id}; +use utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is /// `Drop`. diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4f55162e57f..547caf46082 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -652,7 +652,8 @@ impl LintPass for Pass { GET_UNWRAP, STRING_EXTEND_CHARS, ITER_CLONED_COLLECT, - USELESS_ASREF) + USELESS_ASREF + ) } } @@ -773,7 +774,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } - + // check conventions w.r.t. conversion method names and predicates let def_id = cx.tcx.hir.local_def_id(item.id); let ty = cx.tcx.type_of(def_id); @@ -801,7 +802,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } - + let ret_ty = return_ty(cx, implitem.id); if name == "new" && !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { @@ -887,9 +888,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: // don't lint for constant values // FIXME: can we `expect` here instead of match? let owner_def = cx.tcx.hir.get_parent_did(arg.id); - let promotable = cx.tcx - .rvalue_promotable_map(owner_def) - [&arg.hir_id.local_id]; + let promotable = cx.tcx.rvalue_promotable_map(owner_def)[&arg.hir_id.local_id]; if promotable { return; } @@ -991,12 +990,8 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { expr.span, "using '.clone()' on a ref-counted pointer", "try this", - format!("{}::clone(&{})", - caller_type, - snippet(cx, arg.span, "_") - ) + format!("{}::clone(&{})", caller_type, snippet(cx, arg.span, "_")), ); - } @@ -1055,8 +1050,8 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr } fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) && - derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() + if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) + && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { span_lint( cx, @@ -1231,8 +1226,16 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr] // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { "None" } else { "a" }; - let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { "map_or(a, f)" }; + let arg = if unwrap_snippet == "None" { + "None" + } else { + "a" + }; + let suggest = if unwrap_snippet == "None" { + "and_then(f)" + } else { + "map_or(a, f)" + }; let msg = &format!( "called `map(f).unwrap_or({})` on an Option value. \ This can be done more directly by calling `{}` instead", @@ -1276,10 +1279,10 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( // lint message let msg = if is_option { "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ - `map_or_else(g, f)` instead" + `map_or_else(g, f)` instead" } else { "called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling \ - `ok().map_or_else(g, f)` instead" + `ok().map_or_else(g, f)` instead" }; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_args[1].span, ".."); @@ -1323,7 +1326,6 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( /// lint use of `_.map_or(None, _)` for `Option`s fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { // check if the first non-self argument to map_or() is None let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { @@ -1339,13 +1341,9 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); - span_lint_and_then( - cx, - OPTION_MAP_OR_NONE, - expr.span, - msg, - |db| { db.span_suggestion(expr.span, "try using and_then instead", hint); }, - ); + span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { + db.span_suggestion(expr.span, "try using and_then instead", hint); + }); } } } @@ -1374,7 +1372,12 @@ fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).map(q)` on an `Iterator`. \ @@ -1384,7 +1387,12 @@ fn lint_filter_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ @@ -1394,7 +1402,12 @@ fn lint_filter_map_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Ex } /// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ @@ -1405,7 +1418,12 @@ fn lint_filter_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::E } /// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, _filter_args: &'tcx [hir::Expr], _map_args: &'tcx [hir::Expr]) { +fn lint_filter_map_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { // lint if caller of `.filter_map().flat_map()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ @@ -1476,7 +1494,13 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. -fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { +fn lint_chars_cmp<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + info: &BinaryExprInfo, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { if_chain! { if let Some(args) = method_chain_args(info.chain, chain_methods); if let hir::ExprCall(ref fun, ref arg_char) = info.other.node; @@ -1486,11 +1510,11 @@ fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, c if segment.name == "Some"; then { let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); - + if self_ty.sty != ty::TyStr { return false; } - + span_lint_and_sugg(cx, lint, info.expr.span, @@ -1501,7 +1525,7 @@ fn lint_chars_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, c snippet(cx, args[0][0].span, "_"), suggest, snippet(cx, arg_char[0].span, "_"))); - + return true; } } @@ -1524,7 +1548,13 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo, chain_methods: &[&str], lint: &'static Lint, suggest: &str) -> bool { +fn lint_chars_cmp_with_unwrap<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + info: &BinaryExprInfo, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { if_chain! { if let Some(args) = method_chain_args(info.chain, chain_methods); if let hir::ExprLit(ref lit) = info.other.node; @@ -1542,7 +1572,7 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &Binar suggest, c) ); - + return true; } } @@ -1569,7 +1599,11 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi let parent_item = cx.tcx.hir.get_parent(arg.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if let Ok(&ty::Const { val: ConstVal::Str(r), .. }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { + if let Ok(&ty::Const { + val: ConstVal::Str(r), + .. + }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) + { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then( @@ -1577,7 +1611,9 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi SINGLE_CHAR_PATTERN, arg.span, "single-character string constant used as pattern", - |db| { db.span_suggestion(expr.span, "try using a char instead", hint); }, + |db| { + db.span_suggestion(expr.span, "try using a char instead", hint); + }, ); } } @@ -1772,31 +1808,25 @@ impl SelfKind { fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { - param.name == seg.name && - param - .bounds - .iter() - .any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { - let path = &ptr.trait_ref.path; - match_path(path, name) && - path.segments - .last() - .map_or(false, |s| { - if let Some(ref params) = s.parameters { - if params.parenthesized { - false - } else { - params.types.len() == 1 && - (is_self_ty(¶ms.types[0]) - || is_ty(&*params.types[0], self_ty)) - } - } else { - false - } - }) - } else { - false + param.name == seg.name && param.bounds.iter().any(|bound| { + if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path(path, name) && path.segments.last().map_or(false, |s| { + if let Some(ref params) = s.parameters { + if params.parenthesized { + false + } else { + params.types.len() == 1 + && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) + } + } else { + false + } }) + } else { + false + } + }) }) }) } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index bcdbd738ee1..b5b844e199e 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -2,7 +2,7 @@ use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use std::cmp::{Ordering, PartialOrd}; -use utils::{match_def_path, paths, span_lint, opt_def_id}; +use utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// used to clamp values, but switched so that the result is constant. diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 18d7f7230a8..e1d350a9ad2 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -328,8 +328,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); - if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || - name.ends_with("_eq") + if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") + || name.ends_with("_eq") { return; } @@ -410,13 +410,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { - path.segments.last().map(|seg| if seg.name == "NAN" { - span_lint( - cx, - CMP_NAN, - expr.span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", - ); + path.segments.last().map(|seg| { + if seg.name == "NAN" { + span_lint( + cx, + CMP_NAN, + expr.span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", + ); + } }); } } @@ -426,7 +428,11 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr); - if let Ok(&ty::Const { val: ConstVal::Float(val), .. }) = res { + if let Ok(&ty::Const { + val: ConstVal::Float(val), + .. + }) = res + { use std::cmp::Ordering; match val.ty { FloatTy::F32 => { @@ -445,8 +451,8 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { bits: u128::from(::std::f32::NEG_INFINITY.to_bits()), }; - val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || - val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) + || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) }, FloatTy::F64 => { let zero = ConstFloat { @@ -464,8 +470,8 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { bits: u128::from(::std::f64::NEG_INFINITY.to_bits()), }; - val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || - val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) + || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) }, } } else { @@ -576,9 +582,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool { /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { - def::Def::Local(id) | def::Def::Upvar(id, _, _) => { - !in_macro(cx.tcx.hir.span(id)) - }, + def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir.span(id)), _ => false, } } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index be1fd1dc525..b1388864bdc 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if let Some(snippet) = snippet_opt(cx, inner.span) { db.span_suggestion(e.span, "change this to", snippet); } - } + }, ); } } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 00d7a945595..ccf9c62d93c 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -255,13 +255,13 @@ struct LintData<'a> { const MSG_REDUNDANT_ELSE_BLOCK: &str = "This else block is redundant.\n"; const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \ - expression\n"; + expression\n"; const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause and merging the code that \ - follows (in the loop) with the if block, like so:\n"; + follows (in the loop) with the if block, like so:\n"; const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \ - block, like so:\n"; + block, like so:\n"; fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: LintType) { @@ -332,22 +332,24 @@ fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext, data: &'a } fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) { - with_loop_block(expr, |loop_block| for (i, stmt) in loop_block.stmts.iter().enumerate() { - with_if_expr(stmt, |if_expr, cond, then_block, else_expr| { - let data = &LintData { - stmt_idx: i, - if_expr: if_expr, - if_cond: cond, - if_block: then_block, - else_expr: else_expr, - block_stmts: &loop_block.stmts, - }; - if needless_continue_in_else(else_expr) { - emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock); - } else if is_first_block_stmt_continue(then_block) { - emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock); - } - }); + with_loop_block(expr, |loop_block| { + for (i, stmt) in loop_block.stmts.iter().enumerate() { + with_if_expr(stmt, |if_expr, cond, then_block, else_expr| { + let data = &LintData { + stmt_idx: i, + if_expr: if_expr, + if_cond: cond, + if_block: then_block, + else_expr: else_expr, + block_stmts: &loop_block.stmts, + }; + if needless_continue_in_else(else_expr) { + emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock); + } else if is_first_block_stmt_continue(then_block) { + emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock); + } + }); + } }); } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ac965a59bd5..5675d38af06 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -106,13 +106,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) .filter(|p| !p.is_global()) - .filter_map(|pred| if let ty::Predicate::Trait(poly_trait_ref) = pred { - if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_regions() { - return None; + .filter_map(|pred| { + if let ty::Predicate::Trait(poly_trait_ref) = pred { + if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_regions() { + return None; + } + Some(poly_trait_ref) + } else { + None } - Some(poly_trait_ref) - } else { - None }) .collect::>(); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 74465b64051..b09fb107b07 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -108,11 +108,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } - if !cx.generics.expect("method must have generics").ty_params.is_empty() { - // when the result of `new()` depends on a type parameter we should not require - // an - // impl of `Default` - return; + if !cx.generics + .expect("method must have generics") + .ty_params + .is_empty() + { + // when the result of `new()` depends on a type parameter we should not require + // an + // impl of `Default` + return; } if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index f5543821949..a1139ff7464 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; -use utils::{in_macro, snippet_opt, span_lint, span_lint_and_sugg, has_drop}; +use utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. @@ -146,23 +146,24 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => { - if has_drop(cx, expr) { - None - } else { - Some( - fields - .iter() - .map(|f| &f.expr) - .chain(base) - .map(Deref::deref) - .collect()) - } + Expr_::ExprStruct(_, ref fields, ref base) => if has_drop(cx, expr) { + None + } else { + Some( + fields + .iter() + .map(|f| &f.expr) + .chain(base) + .map(Deref::deref) + .collect(), + ) }, Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { - Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) if !has_drop(cx, expr) => { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) + if !has_drop(cx, expr) => + { Some(args.iter().collect()) }, _ => None, diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 6cbeea8214d..d0bbb10fb4d 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -187,8 +187,8 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let second_last_e = existing_chars .next_back() .expect("we know we have at least three chars"); - if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' || - !interned_chars.zip(existing_chars).all(eq_or_numeric) + if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' + || !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity foo_x, foo_y // or too many chars differ (foo_x, boo_y) or (foox, booy) @@ -203,8 +203,8 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let second_e = existing_chars .next() .expect("we know we have at least two chars"); - if !eq_or_numeric((second_i, second_e)) || second_i == '_' || - !interned_chars.zip(existing_chars).all(eq_or_numeric) + if !eq_or_numeric((second_i, second_e)) || second_i == '_' + || !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity x_foo, y_foo // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index e6fe0631a63..b79e90f910b 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result.ok() if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node; //get operation if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; - + then { let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT); let some_expr_string = snippet(cx, y[0].span, ""); diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 62760888933..673f428eb07 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -81,8 +81,8 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp } } else { return; // The function is called with a literal - // which is not a boolean literal. This is theoretically - // possible, but not very likely. + // which is not a boolean literal. This is theoretically + // possible, but not very likely. } }, _ => Argument::Unknown, diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 1a14a0bc45d..9430e59ac86 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint, opt_def_id}; +use utils::{is_direct_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index ce6b96108a4..61ed8d5ac25 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -6,7 +6,7 @@ use syntax::ast::LitKind; use syntax::symbol::InternedString; use syntax_pos::Span; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; -use utils::{paths, opt_def_id}; +use utils::{opt_def_id, paths}; /// **What it does:** This lint warns when you using `println!("")` to /// print a newline. @@ -94,7 +94,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprPath(ref qpath) = fun.node; if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); then { - + // Search for `std::io::_print(..)` which is unique in a // `print!` expansion. if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { @@ -104,9 +104,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { Some(span) => (span, "println"), None => (span, "print"), }; - + span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - + if_chain! { // ensure we're calling Arguments::new_v1 if args.len() == 1; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 916132daeff..a6a3690202f 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -8,8 +8,7 @@ use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, - walk_ptrs_hir_ty}; +use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; use utils::ptr::get_spans; /// **What it does:** This lint checks for function arguments of type `&String` @@ -121,7 +120,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if let TraitItemKind::Method(ref sig, ref trait_method) = item.node { - let body_id = if let TraitMethod::Provided(b) = *trait_method { Some(b) } else { None }; + let body_id = if let TraitMethod::Provided(b) = *trait_method { + Some(b) + } else { + None + }; check_fn(cx, &sig.decl, item.id, body_id); } } @@ -173,17 +176,19 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< with non-Vec-based slices.", |db| { if let Some(ref snippet) = ty_snippet { - db.span_suggestion(arg.span, - "change this to", - format!("&[{}]", snippet)); + db.span_suggestion(arg.span, "change this to", format!("&[{}]", snippet)); } for (clonespan, suggestion) in spans { - db.span_suggestion(clonespan, - &snippet_opt(cx, clonespan).map_or("change the call to".into(), - |x| Cow::Owned(format!("change `{}` to", x))), - suggestion.into()); + db.span_suggestion( + clonespan, + &snippet_opt(cx, clonespan).map_or( + "change the call to".into(), + |x| Cow::Owned(format!("change `{}` to", x)), + ), + suggestion.into(), + ); } - } + }, ); } } else if match_type(cx, ty, &paths::STRING) { @@ -194,16 +199,18 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do.", |db| { - db.span_suggestion(arg.span, - "change this to", - "&str".into()); + db.span_suggestion(arg.span, "change this to", "&str".into()); for (clonespan, suggestion) in spans { - db.span_suggestion_short(clonespan, - &snippet_opt(cx, clonespan).map_or("change the call to".into(), - |x| Cow::Owned(format!("change `{}` to", x))), - suggestion.into()); + db.span_suggestion_short( + clonespan, + &snippet_opt(cx, clonespan).map_or( + "change the call to".into(), + |x| Cow::Owned(format!("change `{}` to", x)), + ), + suggestion.into(), + ); } - } + }, ); } } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 6e9bebca757..39252ceed1c 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -82,12 +82,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!( - ITERATOR_STEP_BY_ZERO, - RANGE_ZIP_WITH_LEN, - RANGE_PLUS_ONE, - RANGE_MINUS_ONE - ) + lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, RANGE_MINUS_ONE) } } @@ -192,14 +187,12 @@ fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { fn y_plus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprBinary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => { - if is_integer_literal(lhs, 1) { - Some(rhs) - } else if is_integer_literal(rhs, 1) { - Some(lhs) - } else { - None - } + ExprBinary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { + Some(rhs) + } else if is_integer_literal(rhs, 1) { + Some(lhs) + } else { + None }, _ => None, } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 0c125825d8a..beb24a3dbe4 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -10,7 +10,7 @@ use std::error::Error; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; -use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint, opt_def_id}; +use utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -151,7 +151,10 @@ fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option Some(r), + Ok(&ty::Const { + val: ConstVal::Str(r), + .. + }) => Some(r), _ => None, } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index f6461b2d438..92ac65b5abc 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -253,7 +253,9 @@ fn lint_shadow<'a, 'tcx: 'a>( snippet(cx, pattern_span, "_"), snippet(cx, expr.span, "..") ), - |db| { db.span_note(prev_span, "previous binding is here"); }, + |db| { + db.span_note(prev_span, "previous binding is here"); + }, ); } else if contains_name(name, expr) { span_lint_and_then( @@ -292,7 +294,9 @@ fn lint_shadow<'a, 'tcx: 'a>( SHADOW_UNRELATED, span, &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), - |db| { db.span_note(prev_span, "previous binding is here"); }, + |db| { + db.span_note(prev_span, "previous binding is here"); + }, ); } } @@ -361,8 +365,8 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => { - block.stmts.is_empty() && - block + block.stmts.is_empty() + && block .expr .as_ref() .map_or(false, |e| is_self_shadow(name, e)) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 0365322ef68..17514d9d658 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -123,8 +123,8 @@ fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { - block.stmts.is_empty() && - block + block.stmts.is_empty() + && block .expr .as_ref() .map_or(false, |expr| is_add(cx, expr, target)) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 6497bb9b443..22722c919a2 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -89,7 +89,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); - + if matches!(ty.sty, ty::TySlice(_)) || matches!(ty.sty, ty::TyArray(_, _)) || match_type(cx, ty, &paths::VEC) || @@ -99,10 +99,10 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { } } } - + None } - + let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) { if let Some(slice) = Sugg::hir_opt(cx, slice) { (false, @@ -120,9 +120,9 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { } else { (true, "".to_owned(), "".to_owned()) }; - + let span = w[0].span.to(second.span); - + span_lint_and_then(cx, MANUAL_SWAP, span, @@ -130,7 +130,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { |db| { if !sugg.is_empty() { db.span_suggestion(span, "try", sugg); - + if replace { db.note("or maybe you should use `std::mem::replace`?"); } @@ -160,9 +160,9 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { } else { ("".to_owned(), "".to_owned(), "".to_owned()) }; - + let span = first.span.to(second.span); - + span_lint_and_then(cx, ALMOST_SWAPPED, span, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index d01a63f0494..1028381e20a 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use std::borrow::Cow; use syntax::ast; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; -use utils::{sugg, opt_def_id}; +use utils::{opt_def_id, sugg}; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. @@ -190,7 +190,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { if let ExprCall(ref path_expr, ref args) = e.node { if let ExprPath(ref qpath) = path_expr.node { if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { let from_ty = cx.tables.expr_ty(&args[0]); let to_ty = cx.tables.expr_ty(e); @@ -217,15 +216,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg.to_string()); }, ), - (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); - }, - ), + (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => { + span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + }, + ) + }, (&ty::TyFloat(_), &ty::TyRef(..)) | (&ty::TyFloat(_), &ty::TyRawPtr(_)) | (&ty::TyChar, &ty::TyRef(..)) | @@ -249,7 +250,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { cx, CROSSPOINTER_TRANSMUTE, e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), + &format!( + "transmute from a type (`{}`) to a pointer to that type (`{}`)", + from_ty, + to_ty + ), ), (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty)) => span_lint_and_then( cx, @@ -257,7 +262,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!( "transmute from a pointer type (`{}`) to a reference type \ - (`{}`)", + (`{}`)", from_ty, to_ty ), @@ -291,8 +296,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string())); - } + db.span_suggestion( + e.span, + "consider using", + format!("std::char::from_u32({}).unwrap()", arg.to_string()), + ); + }, ), (&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => { if_chain! { @@ -326,34 +335,49 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } }, - (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | - (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then( - cx, - TRANSMUTE_INT_TO_BOOL, - e.span, - &format!("transmute from a `{}` to a `bool`", from_ty), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let zero = sugg::Sugg::NonParen(Cow::from("0")); - db.span_suggestion(e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string()); - } - ), - (&ty::TyInt(_), &ty::TyFloat(_)) | - (&ty::TyUint(_), &ty::TyFloat(_)) => span_lint_and_then( - cx, - TRANSMUTE_INT_TO_FLOAT, - e.span, - &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::TyInt(int_ty) = from_ty.sty { - arg.as_ty(format!("u{}", int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string()))) - } else { - arg - }; - db.span_suggestion(e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string())); - } - ), + (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_BOOL, + e.span, + &format!("transmute from a `{}` to a `bool`", from_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let zero = sugg::Sugg::NonParen(Cow::from("0")); + db.span_suggestion( + e.span, + "consider using", + sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(), + ); + }, + ) + }, + (&ty::TyInt(_), &ty::TyFloat(_)) | (&ty::TyUint(_), &ty::TyFloat(_)) => { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_FLOAT, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::TyInt(int_ty) = from_ty.sty { + arg.as_ty(format!( + "u{}", + int_ty + .bit_width() + .map_or_else(|| "size".to_string(), |v| v.to_string()) + )) + } else { + arg + }; + db.span_suggestion( + e.span, + "consider using", + format!("{}::from_bits({})", to_ty, arg.to_string()), + ); + }, + ) + }, _ => return, }; } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 96caea5c17d..cb472789099 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -241,7 +241,7 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti // Ignore `Box` types, see #1884 for details. return; } - + let ltopt = if lt.is_elided() { "".to_owned() } else { @@ -1730,7 +1730,7 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { return; } - + if match_path(ty_path, &paths::HASHMAP) { if method.name == "new" { self.suggestions diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 985b52b4f53..8203377e465 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; let should_check = if let Some(ref params) = *parameters { - !params.parenthesized && params.lifetimes.len() == 0 + !params.parenthesized && params.lifetimes.len() == 0 } else { true }; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index a4bdcd15290..eadc672e56b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -245,7 +245,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { // FIXME: also check int type LitKind::Int(i, _) => println!(" if let LitKind::Int({}, _) = {}.node;", i, lit_pat), LitKind::Float(..) => println!(" if let LitKind::Float(..) = {}.node;", lit_pat), - LitKind::FloatUnsuffixed(_) => println!(" if let LitKind::FloatUnsuffixed(_) = {}.node;", lit_pat), + LitKind::FloatUnsuffixed(_) => { + println!(" if let LitKind::FloatUnsuffixed(_) = {}.node;", lit_pat) + }, LitKind::ByteStr(ref vec) => { let vec_pat = self.next("vec"); println!(" if let LitKind::ByteStr(ref {}) = {}.node;", vec_pat, lit_pat); diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 93afb449cf6..091261ffbec 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node, opt_def_id}; +use utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -48,10 +48,7 @@ pub fn range(expr: &hir::Expr) -> Option { /// Find the field named `name` in the field. Always return `Some` for /// convenience. fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { - let expr = &fields - .iter() - .find(|field| field.name.node == name)? - .expr; + let expr = &fields.iter().find(|field| field.name.node == name)?.expr; Some(expr) } @@ -72,8 +69,8 @@ pub fn range(expr: &hir::Expr) -> Option { None } }, - hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) || - match_qpath(path, &paths::RANGE_FROM) + hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) + || match_qpath(path, &paths::RANGE_FROM) { Some(Range { start: Some(get_field("start", fields)?), @@ -198,7 +195,7 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option SpanlessEq<'a, 'tcx> { /// Check whether two blocks are the same. pub fn eq_block(&self, left: &Block, right: &Block) -> bool { - over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && - both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) + over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) + && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { @@ -81,14 +81,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => { - both(&li.ident, &ri.ident, |l, r| l.node.name.as_str() == r.node.name.as_str()) && - both(le, re, |l, r| self.eq_expr(l, r)) + both(&li.ident, &ri.ident, |l, r| l.node.name.as_str() == r.node.name.as_str()) + && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { @@ -109,22 +109,22 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) + && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) }) }, (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) }, (&ExprRepeat(ref le, ll_id), &ExprRepeat(ref re, rl_id)) => { - self.eq_expr(le, re) && - self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + self.eq_expr(le, re) + && self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) }, (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r), (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { - self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && - over(lf, rf, |l, r| self.eq_field(l, r)) + self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) + && over(lf, rf, |l, r| self.eq_field(l, r)) }, (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), @@ -169,8 +169,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), (&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => { - over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && - both(li, ri, |l, r| self.eq_pat(l, r)) + over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) + && both(li, ri, |l, r| self.eq_pat(l, r)) }, (&PatKind::Wild, &PatKind::Wild) => true, _ => false, @@ -190,18 +190,18 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } fn eq_path(&self, left: &Path, right: &Path) -> bool { - left.is_global() == right.is_global() && - over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) + left.is_global() == right.is_global() + && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) } fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { if !(left.parenthesized || right.parenthesized) { - over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && - over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) && - over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) + over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) + && over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) + && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) } else if left.parenthesized && right.parenthesized { - over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) && - both( + over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) + && both( &Some(&left.bindings[0].ty), &Some(&right.bindings[0].ty), |l, r| self.eq_ty(l, r), @@ -220,7 +220,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.parameters, &right.parameters) { (&None, &None) => true, (&Some(ref l), &Some(ref r)) => self.eq_path_parameters(l, r), - _ => false + _ => false, } } @@ -228,8 +228,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyArray(ref lt, ll_id), &TyArray(ref rt, rl_id)) => { - self.eq_ty(lt, rt) && - self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + self.eq_ty(lt, rt) + && self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) }, (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a3b0e928aa2..c557e856bf4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -125,8 +125,8 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { tcx.push_item_path(&mut apb, def_id); - apb.names.len() == path.len() && - apb.names + apb.names.len() == path.len() + && apb.names .into_iter() .zip(path.iter()) .all(|(a, &b)| *a == *b) @@ -201,8 +201,8 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { QPath::Resolved(_, ref path) => match_path(path, segments), QPath::TypeRelative(ref ty, ref segment) => match ty.node { TyPath(ref inner_path) => { - !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && - segment.name == segments[segments.len() - 1] + !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) + && segment.name == segments[segments.len() - 1] }, _ => false, }, @@ -233,7 +233,6 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { /// Get the definition associated to a path. pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { - let crates = cx.tcx.crates(); let krate = crates .iter() @@ -269,7 +268,11 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { } pub fn const_to_u64(c: &ty::Const) -> u64 { - c.val.to_const_int().expect("eddyb says this works").to_u64().expect("see previous expect") + c.val + .to_const_int() + .expect("eddyb says this works") + .to_u64() + .expect("see previous expect") } /// Convenience function to get the `DefId` of a trait by path. @@ -473,10 +476,12 @@ fn trim_multiline_inner(s: Cow, ignore_first: bool, ch: char) -> Cow { Cow::Owned( s.lines() .enumerate() - .map(|(i, l)| if (ignore_first && i == 0) || l.is_empty() { - l - } else { - l.split_at(x).1 + .map(|(i, l)| { + if (ignore_first && i == 0) || l.is_empty() { + l + } else { + l.split_at(x).1 + } }) .collect::>() .join("\n"), @@ -494,12 +499,13 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if node_id == parent_id { return None; } - map.find(parent_id) - .and_then(|node| if let Node::NodeExpr(parent) = node { + map.find(parent_id).and_then(|node| { + if let Node::NodeExpr(parent) = node { Some(parent) } else { None - }) + } + }) } pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { @@ -598,7 +604,9 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( help: &str, sugg: String, ) { - span_lint_and_then(cx, lint, sp, msg, |db| { db.span_suggestion(sp, help, sugg); }); + span_lint_and_then(cx, lint, sp, msg, |db| { + db.span_suggestion(sp, help, sugg); + }); } /// Create a suggestion made from several `span → replacement`. @@ -609,7 +617,7 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( /// the whole suggestion. pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: I) where - I: IntoIterator, + I: IntoIterator, { let sugg = rustc_errors::CodeSuggestion { substitution_parts: sugg.into_iter() @@ -629,9 +637,8 @@ where /// Return the base type for HIR references and pointers. pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { match ty.node { - TyPtr(ref mut_ty) | - TyRptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), - _ => ty + TyPtr(ref mut_ty) | TyRptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + _ => ty, } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 3fd372052f6..c680e3eeb5b 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -267,11 +267,11 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { /// in the direction /// `dir`. fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool { - other.precedence() < op.precedence() || - (other.precedence() == op.precedence() && - ((op != other && associativity(op) != dir) || - (op == other && associativity(op) != Associativity::Both))) || - is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) + other.precedence() < op.precedence() + || (other.precedence() == op.precedence() + && ((op != other && associativity(op) != dir) + || (op == other && associativity(op) != Associativity::Both))) + || is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) } let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs { @@ -472,11 +472,13 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error let mut first = true; let new_item = new_item .lines() - .map(|l| if first { - first = false; - format!("{}\n", l) - } else { - format!("{}{}\n", indent, l) + .map(|l| { + if first { + first = false; + format!("{}\n", l) + } else { + format!("{}{}\n", indent, l) + } }) .collect::(); diff --git a/src/driver.rs b/src/driver.rs index 4e367406bcc..8e88cc2e346 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -154,9 +154,7 @@ pub fn main() { .and_then(|out| String::from_utf8(out.stdout).ok()) .map(|s| s.trim().to_owned()) }) - .expect( - "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust", - ) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") }; rustc_driver::in_rustc_thread(|| { @@ -176,7 +174,9 @@ pub fn main() { let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { orig_args.clone() } else { - orig_args.clone().into_iter() + orig_args + .clone() + .into_iter() .chain(Some("--sysroot".to_owned())) .chain(Some(sys_root)) .collect() @@ -185,8 +185,10 @@ pub fn main() { // this check ensures that dependencies are built but not linted and the final // crate is // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") || - orig_args.iter().any(|s| s == "--emit=metadata"); + let clippy_enabled = env::var("CLIPPY_TESTS") + .ok() + .map_or(false, |val| val == "true") + || orig_args.iter().any(|s| s == "--emit=metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); diff --git a/src/main.rs b/src/main.rs index 11ae135bfa9..10c0360a267 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,8 +69,7 @@ pub fn main() { .skip(2) .find(|val| val.starts_with("--manifest-path=")); - let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) - { + let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { metadata } else { let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); diff --git a/tests/conf_whitelisted.rs b/tests/conf_whitelisted.rs index 198bf465bd5..5ada775560e 100644 --- a/tests/conf_whitelisted.rs +++ b/tests/conf_whitelisted.rs @@ -1,3 +1,2 @@ #![feature(plugin)] -#![plugin(clippy(conf_file="./tests/auxiliary/conf_whitelisted.toml"))] - +#![plugin(clippy(conf_file = "./tests/auxiliary/conf_whitelisted.toml"))] diff --git a/tests/dogfood.rs b/tests/dogfood.rs index aa2c4d03bd5..4870bd285b4 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -24,9 +24,7 @@ fn dogfood() { let mut s = String::new(); s.push_str(" -L target/debug/"); s.push_str(" -L target/debug/deps"); - s.push_str( - " -Zextra-plugins=clippy -Ltarget_recur/debug -Dwarnings -Dclippy_pedantic -Dclippy -Dclippy_internal", - ); + s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dwarnings -Dclippy_pedantic -Dclippy -Dclippy_internal"); config.target_rustcflags = Some(s); if let Ok(name) = var("TESTNAME") { config.filter = Some(name.to_owned()) diff --git a/tests/issue-825.rs b/tests/issue-825.rs index 50de10b936c..f806c2c6fde 100644 --- a/tests/issue-825.rs +++ b/tests/issue-825.rs @@ -4,9 +4,9 @@ // this should compile in a reasonable amount of time fn rust_type_id(name: &str) { - if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] || - "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] || - "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] + || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] + || "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] { unreachable!(); } -- cgit 1.4.1-3-g733a5 From a6c71e9c0ddceeb3711e1b147103e2ba0a68b551 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 04:56:05 +0900 Subject: Fix lines that exceed max width manually --- clippy_lints/src/assign_ops.rs | 3 ++- clippy_lints/src/invalid_ref.rs | 12 ++++++++---- clippy_lints/src/methods.rs | 19 ++++++++++++------- clippy_lints/src/new_without_default.rs | 7 ++++++- clippy_lints/src/swap.rs | 6 +++++- clippy_lints/src/types.rs | 12 +++++++----- clippy_lints/src/vec.rs | 7 ++++++- clippy_lints/src/zero_div_zero.rs | 11 +++++++++-- 8 files changed, 55 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index ab9ba4a9327..790c2884273 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -143,7 +143,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if_chain! { if parent_impl != ast::CRATE_NODE_ID; if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); - if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; + if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = + item.node; if trait_ref.path.def.def_id() == trait_id; then { return; } } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 8cc12323fd5..90eb92b8ca4 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -22,8 +22,8 @@ declare_lint! { const ZERO_REF_SUMMARY: &str = "reference to zeroed memory"; const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; -const HELP: &str = - "Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; +const HELP: &str = "Creation of a null reference is undefined behavior; \ + see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; pub struct InvalidRef; @@ -42,9 +42,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); then { - let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | match_def_path(cx.tcx, def_id, &paths::INIT) { + let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | + match_def_path(cx.tcx, def_id, &paths::INIT) + { ZERO_REF_SUMMARY - } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | match_def_path(cx.tcx, def_id, &paths::UNINIT) { + } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | + match_def_path(cx.tcx, def_id, &paths::UNINIT) + { UNINIT_REF_SUMMARY } else { return; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 547caf46082..251c4ac3a11 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -782,7 +782,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { for &(ref conv, self_kinds) in &CONVENTIONS { if_chain! { if conv.check(&name.as_str()); - if !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); + if !self_kinds + .iter() + .any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); then { let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION @@ -1039,12 +1041,15 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); then { - span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, - "you are getting the inner pointer of a temporary `CString`", - |db| { - db.note("that pointer will be invalid outside this expression"); - db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); - }); + span_lint_and_then( + cx, + TEMPORARY_CSTRING_AS_PTR, + expr.span, + "you are getting the inner pointer of a temporary `CString`", + |db| { + db.note("that pointer will be invalid outside this expression"); + db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); + }); } } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index b09fb107b07..d56833eb457 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -142,7 +142,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { span, &format!("you should consider adding a `Default` implementation for `{}`", self_ty), |db| { - db.suggest_prepend_item(cx, span, "try this", &create_new_without_default_suggest_msg(self_ty)); + db.suggest_prepend_item( + cx, + span, + "try this", + &create_new_without_default_suggest_msg(self_ty), + ); }, ); } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 22722c919a2..25fc666d3e1 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -156,7 +156,11 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { let lhs0 = Sugg::hir_opt(cx, lhs0); let rhs0 = Sugg::hir_opt(cx, rhs0); let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) { - (format!(" `{}` and `{}`", first, second), first.mut_addr().to_string(), second.mut_addr().to_string()) + ( + format!(" `{}` and `{}`", first, second), + first.mut_addr().to_string(), + second.mut_addr().to_string(), + ) } else { ("".to_owned(), "".to_owned(), "".to_owned()) }; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index cb472789099..8d5dd3d19b4 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -166,11 +166,13 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))); if match_def_path(cx.tcx, did, &paths::VEC); then { - span_help_and_lint(cx, - BOX_VEC, - ast_ty.span, - "you seem to be trying to use `Box>`. Consider using just `Vec`", - "`Vec` is already on the heap, `Box>` makes an extra allocation."); + span_help_and_lint( + cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box>`. Consider using just `Vec`", + "`Vec` is already on the heap, `Box>` makes an extra allocation.", + ); return; // don't recurse into the type } } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 90a6896b348..e1c226466f9 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -52,7 +52,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))); then { // report the error around the `vec!` not inside `:` - let span = arg.span.ctxt().outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); + let span = arg.span + .ctxt() + .outer() + .expn_info() + .map(|info| info.call_site) + .expect("unable to get call_site"); check_vec_macro(cx, &vec_args, span); } } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 313af61bf15..efe23bcdc47 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -49,9 +49,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { | (_, FloatWidth::F64) => "f64", _ => "f32" }; - span_help_and_lint(cx, ZERO_DIVIDED_BY_ZERO, expr.span, + span_help_and_lint( + cx, + ZERO_DIVIDED_BY_ZERO, + expr.span, "constant division of 0.0 with 0.0 will always result in NaN", - &format!("Consider using `std::{}::NAN` if you would like a constant representing NaN", float_type)); + &format!( + "Consider using `std::{}::NAN` if you would like a constant representing NaN", + float_type, + ), + ); } } } -- cgit 1.4.1-3-g733a5 From 2787a60fc23accc81c9f9c7350b62c73f1c368a4 Mon Sep 17 00:00:00 2001 From: clippered Date: Sat, 4 Nov 2017 19:32:58 +1100 Subject: Fix #1142 float constant comparison lint --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/misc.rs | 40 ++++++++++++++++++- tests/ui/float_cmp_const.rs | 31 +++++++++++++++ tests/ui/float_cmp_const.stderr | 85 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tests/ui/float_cmp_const.rs create mode 100644 tests/ui/float_cmp_const.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5549c98aaf3..eea590f033f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -357,6 +357,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { arithmetic::INTEGER_ARITHMETIC, array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, + misc::FLOAT_CMP_CONST, ]); reg.register_lint_group("clippy_pedantic", vec![ diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 18d7f7230a8..dfe1187916f 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -13,6 +13,7 @@ use utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_ma span_lint_and_then, walk_ptrs_ty}; use utils::sugg::Sugg; use syntax::ast::{FloatTy, LitKind, CRATE_NODE_ID}; +use consts::constant; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -200,6 +201,27 @@ declare_lint! { "using 0 as *{const, mut} T" } +/// **What it does:** Checks for (in-)equality comparisons on floating-point +/// value and constant, except in functions called `*eq*` (which probably +/// implement equality for a type involving floats). +/// +/// **Why is this bad?** Floating point calculations are usually imprecise, so +/// asking if two values are *exactly* equal is asking for trouble. For a good +/// guide on what to do, see [the floating point +/// guide](http://www.floating-point-gui.de/errors/comparison). +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// const ONE == 1.00f64 +/// x == ONE // where both are floats +/// ``` +declare_restriction_lint! { + pub FLOAT_CMP_CONST, + "using `==` or `!=` on float constants instead of comparing difference with an epsilon" +} + #[derive(Copy, Clone)] pub struct Pass; @@ -214,7 +236,8 @@ impl LintPass for Pass { REDUNDANT_PATTERN, USED_UNDERSCORE_BINDING, SHORT_CIRCUIT_STATEMENT, - ZERO_PTR + ZERO_PTR, + FLOAT_CMP_CONST ) } } @@ -334,7 +357,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } } - span_lint_and_then(cx, FLOAT_CMP, expr.span, "strict comparison of f32 or f64", |db| { + let (lint, msg) = if is_named_constant(cx, left) || is_named_constant(cx, right) { + (FLOAT_CMP_CONST, "strict comparison of f32 or f64 constant") + } else { + (FLOAT_CMP, "strict comparison of f32 or f64") + }; + span_lint_and_then(cx, lint, expr.span, msg, |db| { let lhs = Sugg::hir(cx, left, ".."); let rhs = Sugg::hir(cx, right, ".."); @@ -421,6 +449,14 @@ fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { } } +fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { + if let Some((_, res)) = constant(cx, expr) { + res + } else { + false + } +} + fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { let parent_item = cx.tcx.hir.get_parent(expr.id); let parent_def_id = cx.tcx.hir.local_def_id(parent_item); diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs new file mode 100644 index 00000000000..12ffb5b3301 --- /dev/null +++ b/tests/ui/float_cmp_const.rs @@ -0,0 +1,31 @@ + + + +#![warn(float_cmp_const)] +#![allow(unused, no_effect, unnecessary_operation)] + +const ONE: f32 = 1.0; +const TWO: f32 = 2.0; + +fn eq_one(x: f32) -> bool { + if x.is_nan() { false } else { x == ONE } // no error, inside "eq" fn +} + +fn main() { + // has errors + 1f32 == ONE; + TWO == ONE; + TWO != ONE; + ONE + ONE == TWO; + 1 as f32 == ONE; + + let v = 0.9; + v == ONE; + v != ONE; + + // no errors, lower than or greater than comparisons + v < ONE; + v > ONE; + v <= ONE; + v >= ONE; +} diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr new file mode 100644 index 00000000000..0bdbb6770dc --- /dev/null +++ b/tests/ui/float_cmp_const.stderr @@ -0,0 +1,85 @@ +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:16:5 + | +16 | 1f32 == ONE; + | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` + | + = note: `-D float-cmp-const` implied by `-D warnings` +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:16:5 + | +16 | 1f32 == ONE; + | ^^^^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:17:5 + | +17 | TWO == ONE; + | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:17:5 + | +17 | TWO == ONE; + | ^^^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:18:5 + | +18 | TWO != ONE; + | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:18:5 + | +18 | TWO != ONE; + | ^^^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:19:5 + | +19 | ONE + ONE == TWO; + | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:19:5 + | +19 | ONE + ONE == TWO; + | ^^^^^^^^^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:20:5 + | +20 | 1 as f32 == ONE; + | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(1 as f32 - ONE).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:20:5 + | +20 | 1 as f32 == ONE; + | ^^^^^^^^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:23:5 + | +23 | v == ONE; + | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:23:5 + | +23 | v == ONE; + | ^^^^^^^^ + +error: strict comparison of f32 or f64 constant + --> $DIR/float_cmp_const.rs:24:5 + | +24 | v != ONE; + | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:24:5 + | +24 | v != ONE; + | ^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From b778659c42eb395babd0b940e3bc5167a89280f6 Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Sun, 5 Nov 2017 04:19:11 -0800 Subject: Fix compilation errors with rustc 1.23.0-nightly (d762b1d6c 2017-11-04) Fixes #2204 --- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/utils/inspector.rs | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index def357c55e3..12e5ffa0651 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { use rustc::hir::map::Node::*; let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { - matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..)) + matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _) | hir::ItemAutoImpl(..)) } else { false }; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 9b14a44f2c0..3a80f837316 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } match item.node { - ItemTrait(_, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), + ItemTrait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), ItemImpl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), _ => (), } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 2ad6c36ab5f..768e6cc3ec6 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemGlobalAsm(..) => "an assembly blob", hir::ItemTy(..) => "a type alias", hir::ItemUnion(..) => "a union", - hir::ItemDefaultImpl(..) | + hir::ItemAutoImpl(..) | hir::ItemExternCrate(..) | hir::ItemForeignMod(..) | hir::ItemImpl(..) | diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ac965a59bd5..45ea040362a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Exclude non-inherent impls if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { - if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemDefaultImpl(..)) { + if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemAutoImpl(..)) { return; } } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index bf3aa3f6b69..ae1d9462b7c 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -397,14 +397,14 @@ fn print_item(cx: &LateContext, item: &hir::Item) { }, hir::ItemTrait(..) => { println!("trait decl"); - if cx.tcx.trait_has_default_impl(did) { - println!("trait has a default impl"); + if cx.tcx.trait_is_auto(did) { + println!("trait is auto"); } else { - println!("trait has no default impl"); + println!("trait is not auto"); } }, - hir::ItemDefaultImpl(_, ref _trait_ref) => { - println!("default impl"); + hir::ItemAutoImpl(_, ref _trait_ref) => { + println!("auto impl"); }, hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => { println!("trait impl"); -- cgit 1.4.1-3-g733a5 From bcdf57e220e022e9507b97299f5f0d3f1a5c027a Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 5 Nov 2017 14:43:28 +0000 Subject: Refactor the never-loop detection, fixes #1991. --- clippy_lints/src/loops.rs | 156 ++++++++++++++++++++++++++++++--------------- tests/ui/never_loop.rs | 9 +++ tests/ui/never_loop.stderr | 8 +++ 3 files changed, 121 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2e6835b7f68..f13941bffc2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -379,13 +379,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { - let mut state = NeverLoopState { - breaks: HashSet::new(), - continues: HashSet::new(), - }; - let may_complete = never_loop_block(block, &mut state); - if !may_complete && !state.continues.contains(&expr.id) { - span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); + match never_loop_block(block, &expr.id) { + NeverLoopResult::AlwaysBreak => + span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), + NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), } }, _ => (), @@ -491,16 +488,59 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -struct NeverLoopState { - breaks: HashSet, - continues: HashSet, +enum NeverLoopResult { + // A break/return always get triggered but not necessarily for the main loop. + AlwaysBreak, + // A continue may occur for the main loop. + MayContinueMainLoop, + Otherwise, +} + +fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult { + match arg { + NeverLoopResult::AlwaysBreak | + NeverLoopResult::Otherwise => NeverLoopResult::Otherwise, + NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop, + } +} + +// Combine two results for parts that are called in order. +fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResult { + match first { + NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop => first, + NeverLoopResult::Otherwise => second, + } +} + +// Combine two results where both parts are called but not necessarily in order. +fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult { + match (left, right) { + (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => + NeverLoopResult::MayContinueMainLoop, + (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => + NeverLoopResult::AlwaysBreak, + (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => + NeverLoopResult::Otherwise, + } +} + +// Combine two results where only one of the part may have been executed. +fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult { + match (b1, b2) { + (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => + NeverLoopResult::AlwaysBreak, + (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => + NeverLoopResult::MayContinueMainLoop, + (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => + NeverLoopResult::Otherwise, + } } -fn never_loop_block(block: &Block, state: &mut NeverLoopState) -> bool { +fn never_loop_block(block: &Block, main_loop_id: &NodeId) -> NeverLoopResult { let stmts = block.stmts.iter().map(stmt_to_expr); let expr = once(block.expr.as_ref().map(|p| &**p)); let mut iter = stmts.chain(expr).filter_map(|e| e); - never_loop_expr_seq(&mut iter, state) + never_loop_expr_seq(&mut iter, main_loop_id) } fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { @@ -518,7 +558,7 @@ fn decl_to_expr(decl: &Decl) -> Option<&Expr> { } } -fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { +fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { match expr.node { ExprBox(ref e) | ExprUnary(_, ref e) | @@ -527,71 +567,83 @@ fn never_loop_expr(expr: &Expr, state: &mut NeverLoopState) -> bool { ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | - ExprRepeat(ref e, _) => never_loop_expr(e, state), + ExprStruct(_, _, Some(ref e)) | + ExprRepeat(ref e, _) => never_loop_expr(e, main_loop_id), ExprArray(ref es) | ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => never_loop_expr_seq(&mut es.iter(), state), - ExprCall(ref e, ref es) => never_loop_expr_seq(&mut once(&**e).chain(es.iter()), state), + ExprTup(ref es) => never_loop_expr_all(&mut es.iter(), main_loop_id), + ExprCall(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | - ExprIndex(ref e1, ref e2) => never_loop_expr_seq(&mut [&**e1, &**e2].iter().cloned(), state), + ExprIndex(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), ExprIf(ref e, ref e2, ref e3) => { - let e1 = never_loop_expr(e, state); - let e2 = never_loop_expr(e2, state); - match *e3 { - Some(ref e3) => { - let e3 = never_loop_expr(e3, state); - e1 && (e2 || e3) - }, - None => e1, - } + let e1 = never_loop_expr(e, main_loop_id); + let e2 = never_loop_expr(e2, main_loop_id); + let e3 = + match *e3 { + Some(ref e3) => never_loop_expr(e3, main_loop_id), + None => NeverLoopResult::Otherwise, + }; + combine_seq(e1, combine_branches(e2, e3)) }, ExprLoop(ref b, _, _) => { - let block_may_complete = never_loop_block(b, state); - let has_break = state.breaks.remove(&expr.id); - state.continues.remove(&expr.id); - block_may_complete || has_break + // Break can come from the inner loop so remove them. + absorb_break(never_loop_block(b, main_loop_id)) }, ExprWhile(ref e, ref b, _) => { - let e = never_loop_expr(e, state); - let block_may_complete = never_loop_block(b, state); - let has_break = state.breaks.remove(&expr.id); - let has_continue = state.continues.remove(&expr.id); - e && (block_may_complete || has_break || has_continue) + let e = never_loop_expr(e, main_loop_id); + let result = never_loop_block(b, main_loop_id); + // Break can come from the inner loop so remove them. + combine_seq(e, absorb_break(result)) }, ExprMatch(ref e, ref arms, _) => { - let e = never_loop_expr(e, state); - let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), state); - e && arms + let e = never_loop_expr(e, main_loop_id); + if arms.is_empty() { + NeverLoopResult::Otherwise + } else { + let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), main_loop_id); + combine_seq(e, arms) + } }, - ExprBlock(ref b) => never_loop_block(b, state), + ExprBlock(ref b) => never_loop_block(b, main_loop_id), ExprAgain(d) => { let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); - state.continues.insert(id); - false + if id == *main_loop_id { + NeverLoopResult::MayContinueMainLoop + } else { + NeverLoopResult::AlwaysBreak + } }, - ExprBreak(d, _) => { - let id = d.target_id.opt_id().expect("target id can only be missing in the presence of compilation errors"); - state.breaks.insert(id); - false + ExprBreak(_, _) => { + NeverLoopResult::AlwaysBreak }, ExprRet(ref e) => { if let Some(ref e) = *e { - never_loop_expr(e, state); + combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) + } else { + NeverLoopResult::AlwaysBreak } - false }, - _ => true, + ExprStruct(_, _, None) | + ExprYield(_) | + ExprClosure(_, _, _, _, _) | + ExprInlineAsm(_, _, _) | + ExprPath(_) | + ExprLit(_) => NeverLoopResult::Otherwise, } } -fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, state: &mut NeverLoopState) -> bool { - es.map(|e| never_loop_expr(e, state)).fold(true, |a, b| a && b) +fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { + es.map(|e| never_loop_expr(e, main_loop_id)).fold(NeverLoopResult::Otherwise, combine_seq) +} + +fn never_loop_expr_all<'a, T: Iterator>(es: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { + es.map(|e| never_loop_expr(e, main_loop_id)).fold(NeverLoopResult::Otherwise, combine_both) } -fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, state: &mut NeverLoopState) -> bool { - e.map(|e| never_loop_expr(e, state)).fold(false, |a, b| a || b) +fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { + e.map(|e| never_loop_expr(e, main_loop_id)).fold(NeverLoopResult::AlwaysBreak, combine_branches) } fn check_for_loop<'a, 'tcx>( diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 3bb25f68840..2712db2bd31 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -152,6 +152,15 @@ pub fn test14() { } } +// Issue #1991: the outter loop should not warn. +pub fn test15() { + 'label: loop { + while false { + break 'label; + } + } +} + fn main() { test1(); test2(); diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 80eeb6c2888..1f9df6f9ccc 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -80,3 +80,11 @@ error: this loop never actually loops 152 | | } | |_____^ +error: this loop never actually loops + --> $DIR/never_loop.rs:158:9 + | +158 | / while false { +159 | | break 'label; +160 | | } + | |_________^ + -- cgit 1.4.1-3-g733a5 From 7624736961dbac65623192f8c4c7c61df810e11b Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 5 Nov 2017 14:56:15 +0000 Subject: Bugfix. --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f13941bffc2..b1937a11efa 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -600,7 +600,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprMatch(ref e, ref arms, _) => { let e = never_loop_expr(e, main_loop_id); if arms.is_empty() { - NeverLoopResult::Otherwise + e } else { let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), main_loop_id); combine_seq(e, arms) -- cgit 1.4.1-3-g733a5 From 42f44d5c78b05f846584249704ebdd026e208fec Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 5 Nov 2017 15:04:01 +0000 Subject: Cosmetic change. --- clippy_lints/src/loops.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b1937a11efa..0184ad2712a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -580,11 +580,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprIf(ref e, ref e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); - let e3 = - match *e3 { - Some(ref e3) => never_loop_expr(e3, main_loop_id), - None => NeverLoopResult::Otherwise, - }; + let e3 = e3.as_ref().map(|ref e| never_loop_expr(e, main_loop_id)).unwrap_or(NeverLoopResult::Otherwise); combine_seq(e1, combine_branches(e2, e3)) }, ExprLoop(ref b, _, _) => { -- cgit 1.4.1-3-g733a5 From 4fb1bb124e3856c6668afe9069254ae42723e6d2 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 5 Nov 2017 15:17:28 +0000 Subject: Make the dogfood test happy. --- clippy_lints/src/loops.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0184ad2712a..705487dc67d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -496,8 +496,8 @@ enum NeverLoopResult { Otherwise, } -fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult { - match arg { +fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult { + match *arg { NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise, NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop, @@ -580,18 +580,22 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprIf(ref e, ref e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); - let e3 = e3.as_ref().map(|ref e| never_loop_expr(e, main_loop_id)).unwrap_or(NeverLoopResult::Otherwise); + let e3 = + match *e3 { + Some(ref e3) => never_loop_expr(e3, main_loop_id), + None => NeverLoopResult::Otherwise, + }; combine_seq(e1, combine_branches(e2, e3)) }, ExprLoop(ref b, _, _) => { // Break can come from the inner loop so remove them. - absorb_break(never_loop_block(b, main_loop_id)) + absorb_break(&never_loop_block(b, main_loop_id)) }, ExprWhile(ref e, ref b, _) => { let e = never_loop_expr(e, main_loop_id); let result = never_loop_block(b, main_loop_id); // Break can come from the inner loop so remove them. - combine_seq(e, absorb_break(result)) + combine_seq(e, absorb_break(&result)) }, ExprMatch(ref e, ref arms, _) => { let e = never_loop_expr(e, main_loop_id); -- cgit 1.4.1-3-g733a5 From af2c93eeb2be35bf94189b301b023418051a9d73 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 5 Nov 2017 15:45:23 +0000 Subject: Clean the code a bit. --- clippy_lints/src/loops.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 705487dc67d..1b8febcdded 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -580,11 +580,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprIf(ref e, ref e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); - let e3 = - match *e3 { - Some(ref e3) => never_loop_expr(e3, main_loop_id), - None => NeverLoopResult::Otherwise, - }; + let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); combine_seq(e1, combine_branches(e2, e3)) }, ExprLoop(ref b, _, _) => { -- cgit 1.4.1-3-g733a5 From cd3106d99fd95390a870622e22eef0cedbefaac9 Mon Sep 17 00:00:00 2001 From: clippered Date: Mon, 6 Nov 2017 20:02:42 +1100 Subject: add more negative tests --- tests/ui/float_cmp_const.rs | 13 +++++++++++ tests/ui/float_cmp_const.stderr | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 12ffb5b3301..fe69eeeed0a 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -28,4 +28,17 @@ fn main() { v > ONE; v <= ONE; v >= ONE; + + // has float_cmp warns (as expected), no float constants + let w = 1.1; + v == w; + v != w; + v == 1.0; + v != 1.0; + + // no errors, zero and infinity values + ONE != 0f32; + TWO == 0f32; + ONE != ::std::f32::INFINITY; + ONE == ::std::f32::NEG_INFINITY; } diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index 0bdbb6770dc..f8933938ed8 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -83,3 +83,52 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 24 | v != ONE; | ^^^^^^^^ +error: strict comparison of f32 or f64 + --> $DIR/float_cmp_const.rs:34:5 + | +34 | v == w; + | ^^^^^^ help: consider comparing them within some error: `(v - w).abs() < error` + | + = note: `-D float-cmp` implied by `-D warnings` +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:34:5 + | +34 | v == w; + | ^^^^^^ + +error: strict comparison of f32 or f64 + --> $DIR/float_cmp_const.rs:35:5 + | +35 | v != w; + | ^^^^^^ help: consider comparing them within some error: `(v - w).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:35:5 + | +35 | v != w; + | ^^^^^^ + +error: strict comparison of f32 or f64 + --> $DIR/float_cmp_const.rs:36:5 + | +36 | v == 1.0; + | ^^^^^^^^ help: consider comparing them within some error: `(v - 1.0).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:36:5 + | +36 | v == 1.0; + | ^^^^^^^^ + +error: strict comparison of f32 or f64 + --> $DIR/float_cmp_const.rs:37:5 + | +37 | v != 1.0; + | ^^^^^^^^ help: consider comparing them within some error: `(v - 1.0).abs() < error` + | +note: std::f32::EPSILON and std::f64::EPSILON are available. + --> $DIR/float_cmp_const.rs:37:5 + | +37 | v != 1.0; + | ^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From ddaf8580d58b859701a94695368120023ba0ef34 Mon Sep 17 00:00:00 2001 From: clippered Date: Mon, 6 Nov 2017 20:23:18 +1100 Subject: remove duplicate tests with float_cmp --- tests/ui/float_cmp_const.rs | 10 +++------ tests/ui/float_cmp_const.stderr | 49 ----------------------------------------- 2 files changed, 3 insertions(+), 56 deletions(-) diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index fe69eeeed0a..990a8373068 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -29,16 +29,12 @@ fn main() { v <= ONE; v >= ONE; - // has float_cmp warns (as expected), no float constants - let w = 1.1; - v == w; - v != w; - v == 1.0; - v != 1.0; - // no errors, zero and infinity values ONE != 0f32; TWO == 0f32; ONE != ::std::f32::INFINITY; ONE == ::std::f32::NEG_INFINITY; + + // Note: float_cmp will warn as expected on cases where there are no float constants + // e.g. v == 1.0 } diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index f8933938ed8..0bdbb6770dc 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -83,52 +83,3 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 24 | v != ONE; | ^^^^^^^^ -error: strict comparison of f32 or f64 - --> $DIR/float_cmp_const.rs:34:5 - | -34 | v == w; - | ^^^^^^ help: consider comparing them within some error: `(v - w).abs() < error` - | - = note: `-D float-cmp` implied by `-D warnings` -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:34:5 - | -34 | v == w; - | ^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp_const.rs:35:5 - | -35 | v != w; - | ^^^^^^ help: consider comparing them within some error: `(v - w).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:35:5 - | -35 | v != w; - | ^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp_const.rs:36:5 - | -36 | v == 1.0; - | ^^^^^^^^ help: consider comparing them within some error: `(v - 1.0).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:36:5 - | -36 | v == 1.0; - | ^^^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp_const.rs:37:5 - | -37 | v != 1.0; - | ^^^^^^^^ help: consider comparing them within some error: `(v - 1.0).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:37:5 - | -37 | v != 1.0; - | ^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From 66bc12564a5c7494cb17ac816255ac87b6f4016b Mon Sep 17 00:00:00 2001 From: clippered Date: Mon, 6 Nov 2017 21:34:30 +1100 Subject: put back negative tests but allow float_cmp --- tests/ui/float_cmp_const.rs | 9 +++++-- tests/ui/float_cmp_const.stderr | 56 ++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 990a8373068..adf2ab70368 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -2,6 +2,7 @@ #![warn(float_cmp_const)] +#![allow(float_cmp)] #![allow(unused, no_effect, unnecessary_operation)] const ONE: f32 = 1.0; @@ -35,6 +36,10 @@ fn main() { ONE != ::std::f32::INFINITY; ONE == ::std::f32::NEG_INFINITY; - // Note: float_cmp will warn as expected on cases where there are no float constants - // e.g. v == 1.0 + // no errors, but will warn float_cmp if '#![allow(float_cmp)]' above is removed + let w = 1.1; + v == w; + v != w; + v == 1.0; + v != 1.0; } diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index 0bdbb6770dc..fe277de28dd 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -1,85 +1,85 @@ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:16:5 + --> $DIR/float_cmp_const.rs:17:5 | -16 | 1f32 == ONE; +17 | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | = note: `-D float-cmp-const` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:16:5 + --> $DIR/float_cmp_const.rs:17:5 | -16 | 1f32 == ONE; +17 | 1f32 == ONE; | ^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:17:5 + --> $DIR/float_cmp_const.rs:18:5 | -17 | TWO == ONE; +18 | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:17:5 + --> $DIR/float_cmp_const.rs:18:5 | -17 | TWO == ONE; +18 | TWO == ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:18:5 + --> $DIR/float_cmp_const.rs:19:5 | -18 | TWO != ONE; +19 | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:18:5 + --> $DIR/float_cmp_const.rs:19:5 | -18 | TWO != ONE; +19 | TWO != ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:19:5 + --> $DIR/float_cmp_const.rs:20:5 | -19 | ONE + ONE == TWO; +20 | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:19:5 + --> $DIR/float_cmp_const.rs:20:5 | -19 | ONE + ONE == TWO; +20 | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:20:5 + --> $DIR/float_cmp_const.rs:21:5 | -20 | 1 as f32 == ONE; +21 | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(1 as f32 - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:20:5 + --> $DIR/float_cmp_const.rs:21:5 | -20 | 1 as f32 == ONE; +21 | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:23:5 + --> $DIR/float_cmp_const.rs:24:5 | -23 | v == ONE; +24 | v == ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:23:5 + --> $DIR/float_cmp_const.rs:24:5 | -23 | v == ONE; +24 | v == ONE; | ^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:24:5 + --> $DIR/float_cmp_const.rs:25:5 | -24 | v != ONE; +25 | v != ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:24:5 + --> $DIR/float_cmp_const.rs:25:5 | -24 | v != ONE; +25 | v != ONE; | ^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 2b9762a96dc1ec224c760560643a429f3ead3917 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 6 Nov 2017 08:15:11 +0100 Subject: `rls.toml` is not the way to go anymore --- rls.toml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rls.toml diff --git a/rls.toml b/rls.toml deleted file mode 100644 index e3dfeeccd4a..00000000000 --- a/rls.toml +++ /dev/null @@ -1 +0,0 @@ -workspace_mode=true -- cgit 1.4.1-3-g733a5 From 9cd778ac9aa8514fa921093e0963ba9b32fbc3a0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 6 Nov 2017 08:17:25 +0100 Subject: Version bump --- CHANGELOG.md | 7 +++++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 4 +++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 062aab05e86..df19e84a194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.169 +* Rustup to *rustc 1.23.0-nightly (3b82e4c74 2017-11-05)* +* New lints: [`just_underscores_and_digits`], [`result_map_unwrap_or_else`], [`transmute_bytes_to_str`] + ## 0.0.168 * Rustup to *rustc 1.23.0-nightly (f0fe716db 2017-10-30)* @@ -555,6 +559,7 @@ All notable changes to this project will be documented in this file. [`iter_nth`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_nth [`iter_skip_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_skip_next [`iterator_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iterator_step_by_zero +[`just_underscores_and_digits`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#just_underscores_and_digits [`large_digit_groups`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_digit_groups [`large_enum_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_enum_variant [`len_without_is_empty`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#len_without_is_empty @@ -632,6 +637,7 @@ All notable changes to this project will be documented in this file. [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro +[`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used [`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop [`search_is_some`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#search_is_some @@ -659,6 +665,7 @@ All notable changes to this project will be documented in this file. [`temporary_cstring_as_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`too_many_arguments`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#too_many_arguments [`toplevel_ref_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`transmute_bytes_to_str`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_bytes_to_str [`transmute_int_to_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_bool [`transmute_int_to_char`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_char [`transmute_int_to_float`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_float diff --git a/Cargo.toml b/Cargo.toml index cb8e5b2adf9..047d966be66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.168" +version = "0.0.169" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.168", path = "clippy_lints" } +clippy_lints = { version = "0.0.169", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 57fa3ce91ba..41803b6ee3e 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.168" +version = "0.0.169" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0f8f4610871..275508a372a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -374,8 +374,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, - methods::RESULT_MAP_UNWRAP_OR_ELSE, methods::OPTION_UNWRAP_USED, + methods::RESULT_MAP_UNWRAP_OR_ELSE, methods::RESULT_UNWRAP_USED, methods::WRONG_PUB_SELF_CONVENTION, misc::USED_UNDERSCORE_BINDING, @@ -543,6 +543,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, no_effect::NO_EFFECT, no_effect::UNNECESSARY_OPERATION, + non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, open_options::NONSENSICAL_OPEN_OPTIONS, @@ -570,6 +571,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, -- cgit 1.4.1-3-g733a5 From 00081be73d2ba5203a2317708d912d497e2e3b0c Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 7 Nov 2017 06:32:12 +0900 Subject: Rustup --- clippy_lints/src/strings.rs | 1 - tests/ui/unicode.stderr | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 17514d9d658..b7c671c0c48 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -144,7 +144,6 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use std::ascii::AsciiExt; use syntax::ast::LitKind; use utils::{in_macro, snippet}; diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 73599235ea8..870a12ee4c4 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -2,7 +2,7 @@ error: zero-width space detected --> $DIR/unicode.rs:6:12 | 6 | print!("Here >​< is a ZWS, and ​another"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D zero-width-space` implied by `-D warnings` = help: Consider replacing the string with: @@ -12,7 +12,7 @@ error: non-nfc unicode sequence detected --> $DIR/unicode.rs:12:12 | 12 | print!("̀àh?"); - | ^^^^^^^ + | ^^^^^ | = note: `-D unicode-not-nfc` implied by `-D warnings` = help: Consider replacing the string with: -- cgit 1.4.1-3-g733a5 From 6fb736bd42d487947d97a477e95b0b3f1ab7c8a6 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 7 Nov 2017 06:33:25 +0900 Subject: Fix false positive in needless_pass_by_value trait methods --- clippy_lints/src/needless_pass_by_value.rs | 4 +++- tests/ui/needless_pass_by_value.rs | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 81edd58af57..c7410d29df4 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -87,7 +87,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Exclude non-inherent impls if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { - if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemAutoImpl(..)) { + if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemAutoImpl(..) | + ItemTrait(..)) + { return; } } diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index f4d490b214f..84c7e832951 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -103,4 +103,11 @@ impl S { } } +trait FalsePositive { + fn visit_str(s: &str); + fn visit_string(s: String) { + Self::visit_str(&s); + } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From c9681905baf3613dbc17308cc171a0b60788ae5d Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 6 Nov 2017 23:26:44 +0000 Subject: Fix broken tests. --- clippy_lints/src/strings.rs | 1 - tests/ui/unicode.stderr | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 17514d9d658..b7c671c0c48 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -144,7 +144,6 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use std::ascii::AsciiExt; use syntax::ast::LitKind; use utils::{in_macro, snippet}; diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 73599235ea8..870a12ee4c4 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -2,7 +2,7 @@ error: zero-width space detected --> $DIR/unicode.rs:6:12 | 6 | print!("Here >​< is a ZWS, and ​another"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D zero-width-space` implied by `-D warnings` = help: Consider replacing the string with: @@ -12,7 +12,7 @@ error: non-nfc unicode sequence detected --> $DIR/unicode.rs:12:12 | 12 | print!("̀àh?"); - | ^^^^^^^ + | ^^^^^ | = note: `-D unicode-not-nfc` implied by `-D warnings` = help: Consider replacing the string with: -- cgit 1.4.1-3-g733a5 From 652df0fb79666dc976bed3a08d0db7f454014951 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 7 Nov 2017 14:41:54 +0100 Subject: Differentiate between mutable iteration and immutable iteration in `needless_range_loop` --- clippy_lints/src/loops.rs | 65 ++++++++++++++++++++++++++++++++++--- tests/ui/needless_range_loop.rs | 13 ++++++++ tests/ui/needless_range_loop.stderr | 27 +++++++++++++++ 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 80aa7892a26..ecaa64c8724 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -952,10 +952,12 @@ fn check_for_loop_range<'a, 'tcx>( let mut visitor = VarVisitor { cx: cx, var: canonical_id, + indexed_mut: HashSet::new(), indexed: HashMap::new(), indexed_directly: HashMap::new(), referenced: HashSet::new(), nonindex: false, + prefer_mutable: false, }; walk_expr(&mut visitor, body); @@ -1009,6 +1011,12 @@ fn check_for_loop_range<'a, 'tcx>( "".to_owned() }; + let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) { + ("mut ", "iter_mut") + } else { + ("", "iter") + }; + if visitor.nonindex { span_lint_and_then( cx, @@ -1021,16 +1029,16 @@ fn check_for_loop_range<'a, 'tcx>( "consider using an iterator".to_string(), vec![ (pat.span, format!("({}, )", ident.node)), - (arg.span, format!("{}.iter().enumerate(){}{}", indexed, take, skip)), + (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, take, skip)), ], ); }, ); } else { let repl = if starts_at_zero && take.is_empty() { - format!("&{}", indexed) + format!("&{}{}", ref_mut, indexed) } else { - format!("{}.iter(){}{}", indexed, take, skip) + format!("{}.{}(){}{}", indexed, method, take, skip) }; span_lint_and_then( @@ -1537,6 +1545,8 @@ struct VarVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, /// var name to look for as index var: ast::NodeId, + /// indexed variables that are used mutably + indexed_mut: HashSet, /// indexed variables, the extend is `None` for global indexed: HashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` @@ -1548,6 +1558,9 @@ struct VarVisitor<'a, 'tcx: 'a> { /// has the loop variable been used in expressions other than the index of /// an index op? nonindex: bool, + /// Whether we are inside the `$` in `&mut $` or `$ = foo` or `$.bar`, where bar + /// takes `&mut self` + prefer_mutable: bool, } impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { @@ -1572,6 +1585,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { }; if index_used { + if self.prefer_mutable { + self.indexed_mut.insert(seqvar.segments[0].name); + } let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { Def::Local(node_id) | Def::Upvar(node_id, ..) => { @@ -1615,8 +1631,47 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } } } - - walk_expr(self, expr); + let old = self.prefer_mutable; + match expr.node { + ExprAssignOp(_, ref lhs, ref rhs) | + ExprAssign(ref lhs, ref rhs) => { + self.prefer_mutable = true; + self.visit_expr(lhs); + self.prefer_mutable = false; + self.visit_expr(rhs); + }, + ExprAddrOf(mutbl, ref expr) => { + if mutbl == MutMutable { + self.prefer_mutable = true; + } + self.visit_expr(expr); + }, + ExprCall(ref f, ref args) => { + for (ty, expr) in self.cx.tables.expr_ty(f).fn_sig(self.cx.tcx).inputs().skip_binder().iter().zip(args) { + self.prefer_mutable = false; + if let ty::TyRef(_, mutbl) = ty.sty { + if mutbl.mutbl == MutMutable { + self.prefer_mutable = true; + } + } + self.visit_expr(expr); + } + }, + ExprMethodCall(_, _, ref args) => { + let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); + for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { + self.prefer_mutable = false; + if let ty::TyRef(_, mutbl) = ty.sty { + if mutbl.mutbl == MutMutable { + self.prefer_mutable = true; + } + } + self.visit_expr(expr); + } + }, + _ => walk_expr(self, expr), + } + self.prefer_mutable = old; } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index b960e3990c1..6f1e5f53ce2 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -24,4 +24,17 @@ fn main() { for i in 3..10 { println!("{}", ns[calc_idx(i) % 4]); } + + let mut ms = vec![1, 2, 3, 4, 5, 6]; + for i in 0..ms.len() { + ms[i] *= 2; + } + assert_eq!(ms, vec![2, 4, 6, 8, 10, 12]); + + let mut ms = vec![1, 2, 3, 4, 5, 6]; + for i in 0..ms.len() { + let x = &mut ms[i]; + *x *= 2; + } + assert_eq!(ms, vec![2, 4, 6, 8, 10, 12]); } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index e2c3e18e821..9b6be856b85 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -12,3 +12,30 @@ help: consider using an iterator 8 | for in ns.iter().take(10).skip(3) { | ^^^^^^ +error: the loop variable `i` is only used to index `ms`. + --> $DIR/needless_range_loop.rs:29:5 + | +29 | / for i in 0..ms.len() { +30 | | ms[i] *= 2; +31 | | } + | |_____^ + | +help: consider using an iterator + | +29 | for in &mut ms { + | ^^^^^^ + +error: the loop variable `i` is only used to index `ms`. + --> $DIR/needless_range_loop.rs:35:5 + | +35 | / for i in 0..ms.len() { +36 | | let x = &mut ms[i]; +37 | | *x *= 2; +38 | | } + | |_____^ + | +help: consider using an iterator + | +35 | for in &mut ms { + | ^^^^^^ + -- cgit 1.4.1-3-g733a5 From 1b323b9f355c0b3cdf0729f57880240ade00d56f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 7 Nov 2017 15:32:52 +0100 Subject: Don't lint mixed slice indexing and usize indexing in `needless_range_loop` --- clippy_lints/src/loops.rs | 51 +++++++++++++++++++++++++++++------------ tests/ui/needless_range_loop.rs | 15 ++++++++++++ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ecaa64c8724..babf3d3cc16 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -953,7 +953,7 @@ fn check_for_loop_range<'a, 'tcx>( cx: cx, var: canonical_id, indexed_mut: HashSet::new(), - indexed: HashMap::new(), + indexed_indirectly: HashMap::new(), indexed_directly: HashMap::new(), referenced: HashSet::new(), nonindex: false, @@ -962,8 +962,7 @@ fn check_for_loop_range<'a, 'tcx>( walk_expr(&mut visitor, body); // linting condition: we only indexed one variable, and indexed it directly - // (`indexed_directly` is subset of `indexed`) - if visitor.indexed.len() == 1 && visitor.indexed_directly.len() == 1 { + if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 { let (indexed, indexed_extent) = visitor .indexed_directly .into_iter() @@ -1547,8 +1546,8 @@ struct VarVisitor<'a, 'tcx: 'a> { var: ast::NodeId, /// indexed variables that are used mutably indexed_mut: HashSet, - /// indexed variables, the extend is `None` for global - indexed: HashMap>, + /// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global + indexed_indirectly: HashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` indexed_directly: HashMap>, @@ -1563,18 +1562,16 @@ struct VarVisitor<'a, 'tcx: 'a> { prefer_mutable: bool, } -impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr) { +impl<'a, 'tcx> VarVisitor<'a, 'tcx> { + fn check(&mut self, idx: &'tcx Expr, seqexpr: &'tcx Expr, expr: &'tcx Expr) -> bool { if_chain! { - // an index op - if let ExprIndex(ref seqexpr, ref idx) = expr.node; // the indexed container is referenced by a name if let ExprPath(ref seqpath) = seqexpr.node; if let QPath::Resolved(None, ref seqvar) = *seqpath; if seqvar.segments.len() == 1; then { let index_used_directly = same_var(self.cx, idx, self.var); - let index_used = index_used_directly || { + let indexed_indirectly = { let mut used_visitor = LocalUsedVisitor { cx: self.cx, local: self.var, @@ -1584,7 +1581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { used_visitor.used }; - if index_used { + if indexed_indirectly || index_used_directly { if self.prefer_mutable { self.indexed_mut.insert(seqvar.segments[0].name); } @@ -1596,24 +1593,48 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let parent_id = self.cx.tcx.hir.get_parent(expr.id); let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); + if indexed_indirectly { + self.indexed_indirectly.insert(seqvar.segments[0].name, Some(extent)); + } if index_used_directly { self.indexed_directly.insert(seqvar.segments[0].name, Some(extent)); } - return; // no need to walk further *on the variable* + return false; // no need to walk further *on the variable* } Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); + if indexed_indirectly { + self.indexed_indirectly.insert(seqvar.segments[0].name, None); + } if index_used_directly { self.indexed_directly.insert(seqvar.segments[0].name, None); } - return; // no need to walk further *on the variable* + return false; // no need to walk further *on the variable* } _ => (), } } } } + true + } +} + +impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if_chain! { + // a range index op + if let ExprMethodCall(ref meth, _, ref args) = expr.node; + if meth.name == "index" || meth.name == "index_mut"; + if !self.check(&args[1], &args[0], expr); + then { return } + } + + if_chain! { + // an index op + if let ExprIndex(ref seqexpr, ref idx) = expr.node; + if !self.check(idx, seqexpr, expr); + then { return } + } if_chain! { // directly using a variable diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 6f1e5f53ce2..30613f98f2b 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -37,4 +37,19 @@ fn main() { *x *= 2; } assert_eq!(ms, vec![2, 4, 6, 8, 10, 12]); + + let g = vec![1, 2, 3, 4, 5, 6]; + let glen = g.len(); + for i in 0..glen { + let x: u32 = g[i+1..].iter().sum(); + println!("{}", g[i] + x); + } + assert_eq!(g, vec![20, 18, 15, 11, 6, 0]); + + let mut g = vec![1, 2, 3, 4, 5, 6]; + let glen = g.len(); + for i in 0..glen { + g[i] = g[i+1..].iter().sum(); + } + assert_eq!(g, vec![20, 18, 15, 11, 6, 0]); } -- cgit 1.4.1-3-g733a5 From 82793768b79ef6415c79df0f0385ae5a5d3b00c5 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 7 Nov 2017 21:43:24 +0000 Subject: Handle methods with an immediate negation in the non-minimal boolean lint, fixes #1930. --- clippy_lints/src/booleans.rs | 30 ++++++++++++++++++++++++++++++ tests/ui/booleans.rs | 14 ++++++++++++++ tests/ui/booleans.stderr | 24 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ca3fb4017df..86d1f2fb9ee 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -44,6 +44,13 @@ declare_lint! { "boolean expressions that contain terminals which can be eliminated" } +const METHODS_WITH_NEGATION: [(&str, &str); 4] = [ + ("is_some", "is_none"), + ("is_none", "is_some"), + ("is_err", "is_ok"), + ("is_ok", "is_err"), +]; + #[derive(Copy, Clone)] pub struct NonminimalBool; @@ -396,6 +403,28 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } } } + + fn handle_method_call_in_not(&mut self, e: &'tcx Expr, inner: &'tcx Expr) { + if let ExprMethodCall(ref path, _, _) = inner.node { + METHODS_WITH_NEGATION.iter().for_each(|&(method, negation_method)| { + if method == path.name.as_str() { + span_lint_and_then( + self.cx, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + db.span_suggestion( + e.span, + "try", + negation_method.to_owned() + ); + } + ) + } + }) + } + } } impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { @@ -406,6 +435,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { + self.handle_method_call_in_not(e, inner); self.bool_expr(e); } else { walk_expr(self, e); diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 0434285a523..a3c37fecfdc 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -38,3 +38,17 @@ fn equality_stuff() { let _ = a > b && a == b; let _ = a != b || !(a != b || c == d); } + +#[allow(unused, many_single_char_names)] +fn methods_with_negation() { + let a: Option = unimplemented!(); + let b: Result = unimplemented!(); + let _ = a.is_some(); + let _ = !a.is_some(); + let _ = a.is_none(); + let _ = !a.is_none(); + let _ = b.is_err(); + let _ = !b.is_err(); + let _ = b.is_ok(); + let _ = !b.is_ok(); +} diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 0311e95a4f1..b7256ee0f3a 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -130,3 +130,27 @@ help: try 39 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ +error: this boolean expression can be simplified + --> $DIR/booleans.rs:47:13 + | +47 | let _ = !a.is_some(); + | ^^^^^^^^^^^^ help: try: `is_none` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:49:13 + | +49 | let _ = !a.is_none(); + | ^^^^^^^^^^^^ help: try: `is_some` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:51:13 + | +51 | let _ = !b.is_err(); + | ^^^^^^^^^^^ help: try: `is_ok` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:53:13 + | +53 | let _ = !b.is_ok(); + | ^^^^^^^^^^ help: try: `is_err` + -- cgit 1.4.1-3-g733a5 From 67aeb2eaeb9910d2177a6fc0e675c6bc84261c3d Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 7 Nov 2017 21:49:30 +0000 Subject: Only apply when there is a single argument. --- clippy_lints/src/booleans.rs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 86d1f2fb9ee..7fe3b878233 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -405,24 +405,26 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } fn handle_method_call_in_not(&mut self, e: &'tcx Expr, inner: &'tcx Expr) { - if let ExprMethodCall(ref path, _, _) = inner.node { - METHODS_WITH_NEGATION.iter().for_each(|&(method, negation_method)| { - if method == path.name.as_str() { - span_lint_and_then( - self.cx, - NONMINIMAL_BOOL, - e.span, - "this boolean expression can be simplified", - |db| { - db.span_suggestion( - e.span, - "try", - negation_method.to_owned() - ); - } - ) - } - }) + if let ExprMethodCall(ref path, _, ref args) = inner.node { + if args.len() == 1 { + METHODS_WITH_NEGATION.iter().for_each(|&(method, negation_method)| { + if method == path.name.as_str() { + span_lint_and_then( + self.cx, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + db.span_suggestion( + e.span, + "try", + negation_method.to_owned() + ); + } + ) + } + }) + } } } } -- cgit 1.4.1-3-g733a5 From 5c0b99820b6f7d4e35cc8c8a73f60f7de4001e73 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 9 Nov 2017 11:05:49 +0900 Subject: Use compiletest 0.3 --- Cargo.toml | 2 +- tests/compile-test.rs | 4 +++- tests/ui/cstring.stderr | 8 -------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 047d966be66..2fbf6d17ce4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ clippy_lints = { version = "0.0.169", path = "clippy_lints" } cargo_metadata = "0.2" [dev-dependencies] -compiletest_rs = "0.2.7" +compiletest_rs = "0.3" duct = "0.8.2" lazy_static = "0.2" regex = "0.2" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index be8793215dc..cda3a586546 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -22,7 +22,9 @@ fn run_mode(dir: &'static str, mode: &'static str) { } config.mode = cfg_mode; - config.build_base = PathBuf::from("target/debug/test_build_base"); + config.build_base = PathBuf::from("target/debug/test_build_base") + .canonicalize() + .unwrap(); config.src_base = PathBuf::from(format!("tests/{}", dir)); config.rustc_path = clippy_driver_path(); diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index ddb74ce9cac..c3dd9cf83f6 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,11 +1,3 @@ -error: function is never used: `temporary_cstring` - --> $DIR/cstring.rs:4:1 - | -4 | fn temporary_cstring() { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D dead-code` implied by `-D warnings` - error: you are getting the inner pointer of a temporary `CString` --> $DIR/cstring.rs:7:5 | -- cgit 1.4.1-3-g733a5 From b17899878f3efe6802bc6604b922822c7d9ab309 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 9 Nov 2017 14:47:14 +0900 Subject: Build path from current_dir --- tests/compile-test.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index cda3a586546..bd968cc6009 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -22,9 +22,11 @@ fn run_mode(dir: &'static str, mode: &'static str) { } config.mode = cfg_mode; - config.build_base = PathBuf::from("target/debug/test_build_base") - .canonicalize() - .unwrap(); + config.build_base = { + let mut path = std::env::current_dir().unwrap(); + path.push("target/debug/test_build_base"); + path + }; config.src_base = PathBuf::from(format!("tests/{}", dir)); config.rustc_path = clippy_driver_path(); -- cgit 1.4.1-3-g733a5 From 299f1270a6d0dfa9b77ab0c61b1f25f257a9b692 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 10 Nov 2017 08:58:54 +0100 Subject: Rustup --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/methods.rs | 3 +-- clippy_lints/src/utils/mod.rs | 20 ++++++++++++-------- tests/ui/for_loop.stderr | 36 ++++++++++++++++++------------------ tests/ui/implicit_hasher.stderr | 32 ++++++++++++++++---------------- tests/ui/matches.stderr | 6 +++--- tests/ui/needless_range_loop.stderr | 2 +- tests/ui/op_ref.stderr | 2 +- tests/ui/ptr_arg.stderr | 4 ++-- 11 files changed, 60 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df19e84a194..4603c27e266 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.170 +* Rustup to *rustc 1.23.0-nightly (d6b06c63a 2017-11-09)* + ## 0.0.169 * Rustup to *rustc 1.23.0-nightly (3b82e4c74 2017-11-05)* * New lints: [`just_underscores_and_digits`], [`result_map_unwrap_or_else`], [`transmute_bytes_to_str`] diff --git a/Cargo.toml b/Cargo.toml index 2fbf6d17ce4..157a0d18a99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.169" +version = "0.0.170" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.169", path = "clippy_lints" } +clippy_lints = { version = "0.0.170", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 41803b6ee3e..e2b8d654682 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.169" +version = "0.0.170" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 251c4ac3a11..ee61920b489 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -888,9 +888,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: } // don't lint for constant values - // FIXME: can we `expect` here instead of match? let owner_def = cx.tcx.hir.get_parent_did(arg.id); - let promotable = cx.tcx.rvalue_promotable_map(owner_def)[&arg.hir_id.local_id]; + let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); if promotable { return; } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c557e856bf4..a0323df1f62 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -620,14 +620,18 @@ where I: IntoIterator, { let sugg = rustc_errors::CodeSuggestion { - substitution_parts: sugg.into_iter() - .map(|(span, sub)| { - rustc_errors::Substitution { - span: span, - substitutions: vec![sub], - } - }) - .collect(), + substitutions: vec![ + rustc_errors::Substitution { + parts: sugg.into_iter() + .map(|(span, snippet)| { + rustc_errors::SubstitutionPart { + snippet, + span, + } + }) + .collect(), + } + ], msg: help_msg, show_code_when_inline: true, }; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 620c32b6ab5..f968e088866 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -82,7 +82,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 86 | for in &vec { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:95:5 @@ -95,7 +95,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 95 | for in &vec { - | ^^^^^^ + | error: the loop variable `j` is only used to index `STATIC`. --> $DIR/for_loop.rs:100:5 @@ -108,7 +108,7 @@ error: the loop variable `j` is only used to index `STATIC`. help: consider using an iterator | 100 | for in STATIC.iter().take(4) { - | ^^^^^^ + | error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:104:5 @@ -121,7 +121,7 @@ error: the loop variable `j` is only used to index `CONST`. help: consider using an iterator | 104 | for in CONST.iter().take(4) { - | ^^^^^^ + | error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:108:5 @@ -134,7 +134,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 108 | for (i, ) in vec.iter().enumerate() { - | ^^^^^^^^^^^ + | error: the loop variable `i` is only used to index `vec2`. --> $DIR/for_loop.rs:116:5 @@ -147,7 +147,7 @@ error: the loop variable `i` is only used to index `vec2`. help: consider using an iterator | 116 | for in vec2.iter().take(vec.len()) { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:120:5 @@ -160,7 +160,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 120 | for in vec.iter().skip(5) { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:124:5 @@ -173,7 +173,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 124 | for in vec.iter().take(MAX_LEN) { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:128:5 @@ -186,7 +186,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 128 | for in vec.iter().take(MAX_LEN + 1) { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:132:5 @@ -199,7 +199,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 132 | for in vec.iter().take(10).skip(5) { - | ^^^^^^ + | error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:136:5 @@ -212,7 +212,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 136 | for in vec.iter().take(10 + 1).skip(5) { - | ^^^^^^ + | error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:140:5 @@ -225,7 +225,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 140 | for (i, ) in vec.iter().enumerate().skip(5) { - | ^^^^^^^^^^^ + | error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:144:5 @@ -238,7 +238,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { - | ^^^^^^^^^^^ + | error: this range is empty so this for loop will never run --> $DIR/for_loop.rs:148:5 @@ -448,7 +448,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 385 | for v in m.values() { - | ^ + | error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:390:5 @@ -464,7 +464,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 390 | for v in (*m).values() { - | ^ + | error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:398:5 @@ -477,7 +477,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 398 | for v in m.values_mut() { - | ^ + | error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:403:5 @@ -490,7 +490,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 403 | for v in (*m).values_mut() { - | ^ + | error: you seem to want to iterate on a map's keys --> $DIR/for_loop.rs:409:5 @@ -503,7 +503,7 @@ error: you seem to want to iterate on a map's keys help: use the corresponding method | 409 | for k in rm.keys() { - | ^ + | error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:462:5 diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 27d6e2cec08..52b686bf8ae 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -8,11 +8,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 11 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^ + | error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:20:36 @@ -23,11 +23,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 20 | impl Foo for (HashMap,) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) - | ^^^^^^^^^^^^^^^^^^ + | error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:25:19 @@ -38,11 +38,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 25 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^ + | error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:43:32 @@ -53,11 +53,11 @@ error: impl for `HashSet` should be generalized over different hashers help: consider adding a type parameter | 43 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^ + | error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:48:19 @@ -68,11 +68,11 @@ error: impl for `HashSet` should be generalized over different hashers help: consider adding a type parameter | 48 | impl Foo for HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^ + | error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:23 @@ -83,7 +83,7 @@ error: parameter of type `HashMap` should be generalized over different hashers help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:53 @@ -94,7 +94,7 @@ error: parameter of type `HashSet` should be generalized over different hashers help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:70:43 @@ -108,11 +108,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 70 | impl Foo for HashMap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: ...and use generic constructor | 72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | ^^^^^^^^^^^^^^^^^^ + | error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:33 @@ -126,7 +126,7 @@ error: parameter of type `HashMap` should be generalized over different hashers help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:63 @@ -140,5 +140,5 @@ error: parameter of type `HashSet` should be generalized over different hashers help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 1c2452c46ce..7ff38a35341 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -133,7 +133,7 @@ error: you don't need to add `&` to all patterns help: instead of prefixing all patterns with `&`, you can dereference the expression | 138 | match *v { .. } - | ^^^^^^^^^^^^^^^ + | error: you don't need to add `&` to all patterns --> $DIR/matches.rs:148:5 @@ -147,7 +147,7 @@ error: you don't need to add `&` to all patterns help: instead of prefixing all patterns with `&`, you can dereference the expression | 148 | match *tup { .. } - | ^^^^^^^^^^^^^^^^^ + | error: you don't need to add `&` to both the expression and the patterns --> $DIR/matches.rs:154:5 @@ -169,7 +169,7 @@ error: you don't need to add `&` to all patterns help: instead of prefixing all patterns with `&`, you can dereference the expression | 165 | if let .. = *a { .. } - | ^^^^^^^^^^^^^^^^^^^^^ + | error: you don't need to add `&` to both the expression and the patterns --> $DIR/matches.rs:170:5 diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index e2c3e18e821..e54c0e7d011 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -10,5 +10,5 @@ error: the loop variable `i` is only used to index `ns`. help: consider using an iterator | 8 | for in ns.iter().take(10).skip(3) { - | ^^^^^^ + | diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index dbe53933fd5..32596944570 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -8,5 +8,5 @@ error: needlessly taken reference of both operands help: use the values directly | 13 | let foo = 5 - 6; - | ^ + | diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 13be68d4cd4..9c6804cd9a0 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -35,7 +35,7 @@ help: change `x.clone()` to help: change `x.clone()` to | 46 | x.to_owned() - | ^^^^^^^^^^^^ + | error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:49:18 @@ -58,7 +58,7 @@ help: change `x.clone()` to help: change `x.clone()` to | 56 | x.to_string() - | ^^^^^^^^^^^^^ + | error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:59:44 -- cgit 1.4.1-3-g733a5 From 14d50133141d3c728c4497375dab7de14f19dbf5 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 10 Nov 2017 19:55:15 +0000 Subject: Use both pair orders. --- clippy_lints/src/booleans.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 7fe3b878233..e1e8bce1f7d 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -44,11 +44,10 @@ declare_lint! { "boolean expressions that contain terminals which can be eliminated" } -const METHODS_WITH_NEGATION: [(&str, &str); 4] = [ +// For each pairs, both orders are considered. +const METHODS_WITH_NEGATION: [(&str, &str); 2] = [ ("is_some", "is_none"), - ("is_none", "is_some"), ("is_err", "is_ok"), - ("is_ok", "is_err"), ]; #[derive(Copy, Clone)] @@ -407,21 +406,23 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { fn handle_method_call_in_not(&mut self, e: &'tcx Expr, inner: &'tcx Expr) { if let ExprMethodCall(ref path, _, ref args) = inner.node { if args.len() == 1 { - METHODS_WITH_NEGATION.iter().for_each(|&(method, negation_method)| { - if method == path.name.as_str() { - span_lint_and_then( - self.cx, - NONMINIMAL_BOOL, - e.span, - "this boolean expression can be simplified", - |db| { - db.span_suggestion( - e.span, - "try", - negation_method.to_owned() - ); - } - ) + METHODS_WITH_NEGATION.iter().for_each(|&(method1, method2)| { + for &(method, negation_method) in &[(method1, method2), (method2, method1)] { + if method == path.name.as_str() { + span_lint_and_then( + self.cx, + NONMINIMAL_BOOL, + e.span, + "this boolean expression can be simplified", + |db| { + db.span_suggestion( + e.span, + "try", + negation_method.to_owned() + ); + } + ) + } } }) } -- cgit 1.4.1-3-g733a5 From 127c41f700a719cc60594382d7ae0409ba238d0b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 14 Nov 2017 14:56:00 +0100 Subject: Apply changes that were required for running in the rustc test suite --- Cargo.toml | 2 +- clippy_lints/src/lib.rs | 15 ++++++-- src/driver.rs | 40 ++++++++++----------- src/main.rs | 6 ---- tests/compile-test.rs | 53 +++++++++++++++++++++++++--- tests/conf_whitelisted.rs | 2 +- tests/dogfood.rs | 49 ------------------------- tests/ui/conf_bad_toml.rs | 2 +- tests/ui/conf_bad_toml.stderr | 4 +-- tests/ui/conf_bad_type.rs | 2 +- tests/ui/conf_bad_type.stderr | 4 +-- tests/ui/conf_french_blacklisted_name.rs | 2 +- tests/ui/conf_french_blacklisted_name.stderr | 4 +-- tests/ui/conf_unknown_key.rs | 2 +- tests/ui/conf_unknown_key.stderr | 4 +-- tests/ui/format.stderr | 12 ------- tests/ui/implicit_hasher.rs | 2 +- tests/ui/int_plus_one.rs | 4 +-- tests/ui/int_plus_one.stderr | 2 -- tests/ui/invalid_ref.rs | 4 +-- tests/ui/invalid_ref.stderr | 2 -- tests/ui/mut_range_bound.rs | 4 +-- tests/ui/mut_range_bound.stderr | 2 -- tests/ui/print_with_newline.stderr | 18 ---------- 24 files changed, 101 insertions(+), 140 deletions(-) delete mode 100644 tests/dogfood.rs diff --git a/Cargo.toml b/Cargo.toml index 157a0d18a99..38fcae19354 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,12 +40,12 @@ path = "src/driver.rs" clippy_lints = { version = "0.0.170", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" +regex = "0.2" [dev-dependencies] compiletest_rs = "0.3" duct = "0.8.2" lazy_static = "0.2" -regex = "0.2" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.1", path = "mini-macro" } serde = "1.0" diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 275508a372a..b53b34b3b2b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -183,17 +183,28 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { match utils::conf::lookup_conf_file() { Ok(path) => path, Err(error) => { - reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", error)).emit(); + reg.sess.struct_err(&format!("error finding Clippy's configuration file: {}", error)).emit(); None } } }; + let file_name = file_name.map(|file_name| if file_name.is_relative() { + reg.sess + .local_crate_source_file + .as_ref() + .and_then(|file| std::path::Path::new(&file).parent().map(std::path::Path::to_path_buf)) + .unwrap_or_default() + .join(file_name) + } else { + file_name + }); + let (conf, errors) = utils::conf::read(file_name.as_ref().map(|p| p.as_ref())); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { - reg.sess.struct_err(&format!("error reading Clippy's configuration file: {}", error)).emit(); + reg.sess.struct_err(&format!("error reading Clippy's configuration file `{}`: {}", file_name.as_ref().and_then(|p| p.to_str()).unwrap_or(""), error)).emit(); } conf diff --git a/src/driver.rs b/src/driver.rs index 8e88cc2e346..090e69cf027 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -129,33 +129,29 @@ fn show_version() { pub fn main() { use std::env; - if env::var("CLIPPY_DOGFOOD").is_ok() { - panic!("yummy"); - } - if std::env::args().any(|a| a == "--version" || a == "-V") { show_version(); return; } - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { - format!("{}/toolchains/{}", home, toolchain) - } else { - option_env!("SYSROOT") - .map(|s| s.to_owned()) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") - }; + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); rustc_driver::in_rustc_thread(|| { // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. diff --git a/src/main.rs b/src/main.rs index 10c0360a267..c613f029b16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,12 +49,6 @@ fn show_version() { } pub fn main() { - use std::env; - - if env::var("CLIPPY_DOGFOOD").is_ok() { - panic!("yummy"); - } - // Check for version and help flags even when invoked as 'cargo-clippy' if std::env::args().any(|a| a == "--help" || a == "-h") { show_help(); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index bd968cc6009..51ab6aee3a4 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,6 +1,9 @@ +#![feature(test)] + extern crate compiletest_rs as compiletest; +extern crate test; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; use std::env::{set_var, var}; fn clippy_driver_path() -> PathBuf { @@ -11,16 +14,37 @@ fn clippy_driver_path() -> PathBuf { } } -fn run_mode(dir: &'static str, mode: &'static str) { +fn host_libs() -> PathBuf { + if let Some(path) = option_env!("HOST_LIBS") { + PathBuf::from(path) + } else { + Path::new("target").join(env!("PROFILE")) + } +} + +fn rustc_test_suite() -> Option { + option_env!("RUSTC_TEST_SUITE").map(PathBuf::from) +} + +fn rustc_lib_path() -> PathBuf { + option_env!("RUSTC_LIB_PATH").unwrap().into() +} + +fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { let mut config = compiletest::Config::default(); let cfg_mode = mode.parse().expect("Invalid mode"); - config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps -Dwarnings".to_owned()); if let Ok(name) = var::<&str>("TESTNAME") { let s: String = name.to_owned(); config.filter = Some(s) } + if rustc_test_suite().is_some() { + config.run_lib_path = rustc_lib_path(); + config.compile_lib_path = rustc_lib_path(); + } + config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); + config.mode = cfg_mode; config.build_base = { let mut path = std::env::current_dir().unwrap(); @@ -29,8 +53,11 @@ fn run_mode(dir: &'static str, mode: &'static str) { }; config.src_base = PathBuf::from(format!("tests/{}", dir)); config.rustc_path = clippy_driver_path(); + config +} - compiletest::run_tests(&config); +fn run_mode(dir: &'static str, mode: &'static str) { + compiletest::run_tests(&config(dir, mode)); } fn prepare_env() { @@ -45,3 +72,21 @@ fn compile_test() { run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); } + +#[test] +fn dogfood() { + prepare_env(); + let files = ["src/main.rs", "src/driver.rs", "src/lib.rs", "clippy_lints/src/lib.rs"]; + let mut config = config("dogfood", "ui"); + config.target_rustcflags = config.target_rustcflags.map(|flags| format!("{} -Dclippy -Dclippy_pedantic -Dclippy_internal", flags)); + + for file in &files { + let paths = test::TestPaths { + base: PathBuf::new(), + file: PathBuf::from(file), + relative_dir: PathBuf::new(), + }; + + compiletest::runtest::run(config.clone(), &paths); + } +} diff --git a/tests/conf_whitelisted.rs b/tests/conf_whitelisted.rs index 5ada775560e..10a7d3e72d7 100644 --- a/tests/conf_whitelisted.rs +++ b/tests/conf_whitelisted.rs @@ -1,2 +1,2 @@ #![feature(plugin)] -#![plugin(clippy(conf_file = "./tests/auxiliary/conf_whitelisted.toml"))] +#![plugin(clippy(conf_file = "./auxiliary/conf_whitelisted.toml"))] diff --git a/tests/dogfood.rs b/tests/dogfood.rs deleted file mode 100644 index 4870bd285b4..00000000000 --- a/tests/dogfood.rs +++ /dev/null @@ -1,49 +0,0 @@ -#![feature(test, plugin)] -#![plugin(clippy)] -#![deny(clippy, clippy_pedantic)] - -extern crate compiletest_rs as compiletest; -extern crate test; - -use std::env::{set_var, var}; -use std::path::PathBuf; -use test::TestPaths; - -#[test] -fn dogfood() { - // don't run dogfood on travis, cargo-clippy already runs clippy on itself - if let Ok(travis) = var("TRAVIS") { - if travis == "true" { - return; - } - } - - let mut config = compiletest::Config::default(); - - let cfg_mode = "run-fail".parse().expect("Invalid mode"); - let mut s = String::new(); - s.push_str(" -L target/debug/"); - s.push_str(" -L target/debug/deps"); - s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dwarnings -Dclippy_pedantic -Dclippy -Dclippy_internal"); - config.target_rustcflags = Some(s); - if let Ok(name) = var("TESTNAME") { - config.filter = Some(name.to_owned()) - } - - config.mode = cfg_mode; - config.verbose = true; - - let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"]; - - for file in &files { - let paths = TestPaths { - base: PathBuf::new(), - file: PathBuf::from(file), - relative_dir: PathBuf::new(), - }; - - set_var("CLIPPY_DOGFOOD", "tastes like chicken"); - - compiletest::runtest::run(config.clone(), &paths); - } -} diff --git a/tests/ui/conf_bad_toml.rs b/tests/ui/conf_bad_toml.rs index 4de2cf6ae73..a2ce7ecc519 100644 --- a/tests/ui/conf_bad_toml.rs +++ b/tests/ui/conf_bad_toml.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file -#![plugin(clippy(conf_file="./tests/ui/conf_bad_toml.toml"))] +#![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] fn main() {} diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index 5ddf8c14f70..45477ff0855 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -1,8 +1,8 @@ error: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_bad_toml.rs:4:1 | -4 | #![plugin(clippy(conf_file="./$DIR/conf_bad_toml.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +4 | #![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_bad_type.rs b/tests/ui/conf_bad_type.rs index 4cb21b91582..cb18bfb8c90 100644 --- a/tests/ui/conf_bad_type.rs +++ b/tests/ui/conf_bad_type.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` -#![plugin(clippy(conf_file="./tests/ui/conf_bad_type.toml"))] +#![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] fn main() {} diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 961df381c99..0fa40cfca9b 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -1,8 +1,8 @@ error: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_bad_type.rs:4:1 | -4 | #![plugin(clippy(conf_file="./$DIR/conf_bad_type.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +4 | #![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_french_blacklisted_name.rs b/tests/ui/conf_french_blacklisted_name.rs index 9f22ff659f2..dbe6d85e5d2 100644 --- a/tests/ui/conf_french_blacklisted_name.rs +++ b/tests/ui/conf_french_blacklisted_name.rs @@ -1,5 +1,5 @@ -#![plugin(clippy(conf_file="./tests/auxiliary/conf_french_blacklisted_name.toml"))] +#![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] #![allow(dead_code)] #![allow(single_match)] diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index c98adb6029f..f7eb174f9a6 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -1,8 +1,8 @@ error: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_french_blacklisted_name.rs:2:1 | -2 | #![plugin(clippy(conf_file="./tests/auxiliary/conf_french_blacklisted_name.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +2 | #![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/conf_unknown_key.rs b/tests/ui/conf_unknown_key.rs index aec2c883367..437d0f9d8b0 100644 --- a/tests/ui/conf_unknown_key.rs +++ b/tests/ui/conf_unknown_key.rs @@ -1,6 +1,6 @@ // error-pattern: error reading Clippy's configuration file: unknown key `foobar` -#![plugin(clippy(conf_file="./tests/auxiliary/conf_unknown_key.toml"))] +#![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] fn main() {} diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index 9fc7dbea563..c525366c129 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -1,8 +1,8 @@ error: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_unknown_key.rs:4:1 | -4 | #![plugin(clippy(conf_file="./tests/auxiliary/conf_unknown_key.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +4 | #![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(plugin)] to the crate attributes to enable diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 67d97f295d8..558e9e83c33 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,15 +6,3 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` -error: useless use of `format!` - --> $DIR/format.rs:8:5 - | -8 | format!("{}", "foo"); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: useless use of `format!` - --> $DIR/format.rs:15:5 - | -15 | format!("{}", arg); - | ^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index 32ca0f56d77..c93f858b5ca 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,5 +1,5 @@ #![allow(unused)] -//#![feature(plugin)]#![plugin(clippy)] + use std::collections::{HashMap, HashSet}; use std::cmp::Eq; use std::hash::{Hash, BuildHasher}; diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index 90375dad555..a9e059f4a3e 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #[allow(no_effect, unnecessary_operation)] #[warn(int_plus_one)] diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 92b012bd104..5d42ebb8986 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,5 +1,3 @@ -warning: running cargo clippy on a crate that also imports the clippy plugin - error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:10:5 | diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs index 2b8f04c9781..ce2596c0c1a 100644 --- a/tests/ui/invalid_ref.rs +++ b/tests/ui/invalid_ref.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] #![feature(core_intrinsics)] diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 18064c91a01..c018bdf6dd3 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,5 +1,3 @@ -warning: running cargo clippy on a crate that also imports the clippy plugin - error: reference to zeroed memory --> $DIR/invalid_ref.rs:27:24 | diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs index 835ceeedc94..0e397c7ae8c 100644 --- a/tests/ui/mut_range_bound.rs +++ b/tests/ui/mut_range_bound.rs @@ -1,5 +1,5 @@ -#![feature(plugin)] -#![plugin(clippy)] + + #![allow(unused)] diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index f516ec9d95e..20dbb6511d7 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,5 +1,3 @@ -warning: running cargo clippy on a crate that also imports the clippy plugin - error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:18:21 | diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 2ade3ae4ef5..0148a470e0d 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -6,21 +6,3 @@ error: using `print!()` with a format string that ends in a newline, consider us | = note: `-D print-with-newline` implied by `-D warnings` -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:7:5 - | -7 | print!("Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:8:5 - | -8 | print!("Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:9:5 - | -9 | print!("{}/n", 1265); - | ^^^^^^^^^^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From bdf3887d22a7352c20d97cef9cf9f8f4ac41ccff Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 14 Nov 2017 17:07:04 +0100 Subject: Move 'handle_method_call_in_not' code into 'suggest' --- clippy_lints/src/booleans.rs | 84 +++++++++++++++++-------------------- tests/ui/booleans.rs | 2 + tests/ui/booleans.stderr | 24 ++--------- tests/ui/format.stderr | 12 ------ tests/ui/needless_range_loop.stderr | 4 +- tests/ui/print_with_newline.stderr | 18 -------- 6 files changed, 45 insertions(+), 99 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index e1e8bce1f7d..5de3246f1a9 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -177,26 +177,45 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push('!'); recurse(true, cx, inner, terminals, s) }, - Term(n) => if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { + Term(n) => match terminals[n as usize].node { + ExprBinary(binop, ref lhs, ref rhs) => { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { + s.push('!'); + return recurse(true, cx, inner, terminals, s); + }, + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + }, + ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { + let negation = METHODS_WITH_NEGATION + .iter().cloned() + .flat_map(|(a, b)| vec![(a, b), (b, a)]) + .find(|&(a, _)| a == path.name.as_str()); + if let Some((_, negation_method)) = negation { + s.push_str(&snip(&args[0])); + s.push('.'); + s.push_str(negation_method); + s.push_str("()"); + s + } else { s.push('!'); - return recurse(true, cx, inner, terminals, s); - }, - }; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - } else { - s.push('!'); - recurse(false, cx, inner, terminals, s) + recurse(false, cx, inner, terminals, s) + } + }, + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, }, _ => { s.push('!'); @@ -402,32 +421,6 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } } } - - fn handle_method_call_in_not(&mut self, e: &'tcx Expr, inner: &'tcx Expr) { - if let ExprMethodCall(ref path, _, ref args) = inner.node { - if args.len() == 1 { - METHODS_WITH_NEGATION.iter().for_each(|&(method1, method2)| { - for &(method, negation_method) in &[(method1, method2), (method2, method1)] { - if method == path.name.as_str() { - span_lint_and_then( - self.cx, - NONMINIMAL_BOOL, - e.span, - "this boolean expression can be simplified", - |db| { - db.span_suggestion( - e.span, - "try", - negation_method.to_owned() - ); - } - ) - } - } - }) - } - } - } } impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { @@ -438,7 +431,6 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { - self.handle_method_call_in_not(e, inner); self.bool_expr(e); } else { walk_expr(self, e); diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index a3c37fecfdc..52ce90dd63d 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -51,4 +51,6 @@ fn methods_with_negation() { let _ = !b.is_err(); let _ = b.is_ok(); let _ = !b.is_ok(); + let c = false; + let _ = !(a.is_some() && !c); } diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index b7256ee0f3a..e50961323e5 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -131,26 +131,8 @@ help: try | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:47:13 + --> $DIR/booleans.rs:55:13 | -47 | let _ = !a.is_some(); - | ^^^^^^^^^^^^ help: try: `is_none` - -error: this boolean expression can be simplified - --> $DIR/booleans.rs:49:13 - | -49 | let _ = !a.is_none(); - | ^^^^^^^^^^^^ help: try: `is_some` - -error: this boolean expression can be simplified - --> $DIR/booleans.rs:51:13 - | -51 | let _ = !b.is_err(); - | ^^^^^^^^^^^ help: try: `is_ok` - -error: this boolean expression can be simplified - --> $DIR/booleans.rs:53:13 - | -53 | let _ = !b.is_ok(); - | ^^^^^^^^^^ help: try: `is_err` +55 | let _ = !(a.is_some() && !c); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 67d97f295d8..558e9e83c33 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,15 +6,3 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` -error: useless use of `format!` - --> $DIR/format.rs:8:5 - | -8 | format!("{}", "foo"); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: useless use of `format!` - --> $DIR/format.rs:15:5 - | -15 | format!("{}", arg); - | ^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 97328f3d4d1..94ee5f613fc 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -23,7 +23,7 @@ error: the loop variable `i` is only used to index `ms`. help: consider using an iterator | 29 | for in &mut ms { - | ^^^^^^ + | error: the loop variable `i` is only used to index `ms`. --> $DIR/needless_range_loop.rs:35:5 @@ -37,5 +37,5 @@ error: the loop variable `i` is only used to index `ms`. help: consider using an iterator | 35 | for in &mut ms { - | ^^^^^^ + | diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 2ade3ae4ef5..0148a470e0d 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -6,21 +6,3 @@ error: using `print!()` with a format string that ends in a newline, consider us | = note: `-D print-with-newline` implied by `-D warnings` -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:7:5 - | -7 | print!("Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:8:5 - | -8 | print!("Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:9:5 - | -9 | print!("{}/n", 1265); - | ^^^^^^^^^^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From 25783fa485933158870260b68bff94998d95ca48 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 14 Nov 2017 21:14:08 +0000 Subject: Raise a lint when suggest has simplified the expression. --- clippy_lints/src/booleans.rs | 68 +++++++++++++++++++++++++++----------------- tests/ui/booleans.stderr | 24 ++++++++++++++++ 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 5de3246f1a9..9310cca4aee 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -159,8 +159,16 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } -fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { - fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { +// The boolean part of the return indicates whether some simplifications have been applied. +fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { + fn recurse( + brackets: bool, + cx: &LateContext, + suggestion: &Bool, + terminals: &[&Expr], + mut s: String, + simplified: &mut bool, + ) -> String { use quine_mc_cluskey::Bool::*; let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); match *suggestion { @@ -175,7 +183,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { Not(ref inner) => match **inner { And(_) | Or(_) => { s.push('!'); - recurse(true, cx, inner, terminals, s) + recurse(true, cx, inner, terminals, s, simplified) }, Term(n) => match terminals[n as usize].node { ExprBinary(binop, ref lhs, ref rhs) => { @@ -188,9 +196,10 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { BiGe => " < ", _ => { s.push('!'); - return recurse(true, cx, inner, terminals, s); + return recurse(true, cx, inner, terminals, s, simplified); }, }; + *simplified = true; s.push_str(&snip(lhs)); s.push_str(op); s.push_str(&snip(rhs)); @@ -202,6 +211,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { .flat_map(|(a, b)| vec![(a, b), (b, a)]) .find(|&(a, _)| a == path.name.as_str()); if let Some((_, negation_method)) = negation { + *simplified = true; s.push_str(&snip(&args[0])); s.push('.'); s.push_str(negation_method); @@ -209,17 +219,17 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s } else { s.push('!'); - recurse(false, cx, inner, terminals, s) + recurse(false, cx, inner, terminals, s, simplified) } }, _ => { s.push('!'); - recurse(false, cx, inner, terminals, s) + recurse(false, cx, inner, terminals, s, simplified) }, }, _ => { s.push('!'); - recurse(false, cx, inner, terminals, s) + recurse(false, cx, inner, terminals, s, simplified) }, }, And(ref v) => { @@ -227,16 +237,16 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push('('); } if let Or(_) = v[0] { - s = recurse(true, cx, &v[0], terminals, s); + s = recurse(true, cx, &v[0], terminals, s, simplified); } else { - s = recurse(false, cx, &v[0], terminals, s); + s = recurse(false, cx, &v[0], terminals, s, simplified); } for inner in &v[1..] { s.push_str(" && "); if let Or(_) = *inner { - s = recurse(true, cx, inner, terminals, s); + s = recurse(true, cx, inner, terminals, s, simplified); } else { - s = recurse(false, cx, inner, terminals, s); + s = recurse(false, cx, inner, terminals, s, simplified); } } if brackets { @@ -248,10 +258,10 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { if brackets { s.push('('); } - s = recurse(false, cx, &v[0], terminals, s); + s = recurse(false, cx, &v[0], terminals, s, simplified); for inner in &v[1..] { s.push_str(" || "); - s = recurse(false, cx, inner, terminals, s); + s = recurse(false, cx, inner, terminals, s, simplified); } if brackets { s.push(')'); @@ -274,7 +284,9 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { }, } } - recurse(false, cx, suggestion, terminals, String::new()) + let mut simplified = false; + let s = recurse(false, cx, suggestion, terminals, String::new(), &mut simplified); + (s, simplified) } fn simple_negate(b: Bool) -> Bool { @@ -384,7 +396,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { db.span_suggestion( e.span, "it would look like the following", - suggest(self.cx, suggestion, &h2q.terminals), + suggest(self.cx, suggestion, &h2q.terminals).0, ); }, ); @@ -401,22 +413,26 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { improvements.push(suggestion); } } - if !improvements.is_empty() { + let nonminimal_bool_lint = |suggestions| { span_lint_and_then( self.cx, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", - |db| { - db.span_suggestions( - e.span, - "try", - improvements - .into_iter() - .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals)) - .collect(), - ); - }, + |db| { db.span_suggestions(e.span, "try", suggestions); }, + ); + }; + if improvements.is_empty() { + let suggest = suggest(self.cx, &expr, &h2q.terminals); + if suggest.1 { + nonminimal_bool_lint(vec![suggest.0]) + } + } else { + nonminimal_bool_lint( + improvements + .into_iter() + .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals).0) + .collect() ); } } diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index e50961323e5..05696ba0f59 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -130,6 +130,30 @@ help: try 39 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ +error: this boolean expression can be simplified + --> $DIR/booleans.rs:47:13 + | +47 | let _ = !a.is_some(); + | ^^^^^^^^^^^^ help: try: `a.is_none()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:49:13 + | +49 | let _ = !a.is_none(); + | ^^^^^^^^^^^^ help: try: `a.is_some()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:51:13 + | +51 | let _ = !b.is_err(); + | ^^^^^^^^^^^ help: try: `b.is_ok()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:53:13 + | +53 | let _ = !b.is_ok(); + | ^^^^^^^^^^ help: try: `b.is_err()` + error: this boolean expression can be simplified --> $DIR/booleans.rs:55:13 | -- cgit 1.4.1-3-g733a5 From c6a4eaeb0d574b92b167fb8bbff02539ea8af3b1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 15 Nov 2017 08:38:43 +0100 Subject: Rustup --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/utils/mod.rs | 7 +++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4603c27e266..60a42ac1f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.171 +* Rustup to *rustc 1.23.0-nightly (ff0f5de3b 2017-11-14)* + ## 0.0.170 * Rustup to *rustc 1.23.0-nightly (d6b06c63a 2017-11-09)* diff --git a/Cargo.toml b/Cargo.toml index 38fcae19354..a022264985d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.170" +version = "0.0.171" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.170", path = "clippy_lints" } +clippy_lints = { version = "0.0.171", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e2b8d654682..94f4621987f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.170" +version = "0.0.171" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a0323df1f62..8571e5bb563 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,6 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::mir::transform::MirSource; use rustc_errors; use std::borrow::Cow; use std::env; @@ -48,9 +47,9 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { let parent_id = cx.tcx.hir.get_parent(id); - match MirSource::from_node(cx.tcx, parent_id) { - MirSource::GeneratorDrop(_) | MirSource::Fn(_) => false, - MirSource::Const(_) | MirSource::Static(..) | MirSource::Promoted(..) => true, + match cx.tcx.hir.body_owner_kind(parent_id) { + hir::BodyOwnerKind::Fn => false, + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(..) => true, } } -- cgit 1.4.1-3-g733a5 From 0155ecf6b077bf8d5b333662059d78533e5b2ac0 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Wed, 15 Nov 2017 17:52:25 -0500 Subject: Split TyImplTrait into Universal and Existential This fixes build after the implementation of impl Trait in argument position lands in rustc --- clippy_lints/src/lifetimes.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7cfe2c1cdcb..90c532f0746 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -325,7 +325,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); }, - TyImplTrait(ref param_bounds) => for bound in param_bounds { + TyImplTraitExistential(ref param_bounds) | + TyImplTraitUniversal(_, ref param_bounds) => for bound in param_bounds { if let RegionTyParamBound(_) = *bound { self.record(&None); } -- cgit 1.4.1-3-g733a5 From e44af6b14d6912e1ea7c5e2d10dd830cf1b42ed7 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 16 Nov 2017 21:08:08 +0000 Subject: First attempt at simplifying boolean processing. --- clippy_lints/src/booleans.rs | 143 +++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 66 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 9310cca4aee..f6440dcc428 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -159,6 +159,56 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } +// A very simple expression type used for straightforward simplifications. +enum BinaryOrCall<'a> { + Binary(&'a str, &'a Expr, &'a Expr), + MethodCall(&'a str, &'a Expr), +} + +impl<'a> BinaryOrCall<'a> { + fn to_string(&self, cx: &LateContext, s: &mut String) { + let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); + match *self { + BinaryOrCall::Binary(op, lhs, rhs) => { + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + } + BinaryOrCall::MethodCall(method, arg) => { + s.push_str(&snip(arg)); + s.push('.'); + s.push_str(method); + s.push_str("()"); + } + } + } +} + +fn simplify_not(expr: &Expr) -> Option { + match expr.node { + ExprBinary(binop, ref lhs, ref rhs) => { + let neg_op = match binop.node { + BiEq => Some(" != "), + BiNe => Some(" == "), + BiLt => Some(" >= "), + BiGt => Some(" <= "), + BiLe => Some(" > "), + BiGe => Some(" < "), + _ => None, + }; + neg_op.map(|op| BinaryOrCall::Binary(op, lhs, rhs)) + }, + ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { + METHODS_WITH_NEGATION + .iter().cloned() + .flat_map(|(a, b)| vec![(a, b), (b, a)]) + .find(|&(a, _)| a == path.name.as_str()) + .map(|(_, neg_method)| BinaryOrCall::MethodCall(neg_method, &args[0])) + }, + _ => None, + } +} + // The boolean part of the return indicates whether some simplifications have been applied. fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { fn recurse( @@ -166,68 +216,33 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], - mut s: String, + s: &mut String, simplified: &mut bool, - ) -> String { + ) { use quine_mc_cluskey::Bool::*; let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); match *suggestion { True => { s.push_str("true"); - s }, False => { s.push_str("false"); - s }, Not(ref inner) => match **inner { And(_) | Or(_) => { s.push('!'); recurse(true, cx, inner, terminals, s, simplified) }, - Term(n) => match terminals[n as usize].node { - ExprBinary(binop, ref lhs, ref rhs) => { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { - s.push('!'); - return recurse(true, cx, inner, terminals, s, simplified); - }, - }; + Term(n) => { + if let Some(binary_or_call) = simplify_not(terminals[n as usize]) { *simplified = true; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - }, - ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { - let negation = METHODS_WITH_NEGATION - .iter().cloned() - .flat_map(|(a, b)| vec![(a, b), (b, a)]) - .find(|&(a, _)| a == path.name.as_str()); - if let Some((_, negation_method)) = negation { - *simplified = true; - s.push_str(&snip(&args[0])); - s.push('.'); - s.push_str(negation_method); - s.push_str("()"); - s - } else { - s.push('!'); - recurse(false, cx, inner, terminals, s, simplified) - } - }, - _ => { + binary_or_call.to_string(cx, s) + } else { s.push('!'); recurse(false, cx, inner, terminals, s, simplified) - }, + } }, - _ => { + True | False | Not(_) => { s.push('!'); recurse(false, cx, inner, terminals, s, simplified) }, @@ -236,56 +251,52 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, if brackets { s.push('('); } - if let Or(_) = v[0] { - s = recurse(true, cx, &v[0], terminals, s, simplified); - } else { - s = recurse(false, cx, &v[0], terminals, s, simplified); - } - for inner in &v[1..] { - s.push_str(" && "); + for (index, inner) in v.iter().enumerate() { + if index > 0 { + s.push_str(" && "); + } if let Or(_) = *inner { - s = recurse(true, cx, inner, terminals, s, simplified); + recurse(true, cx, inner, terminals, s, simplified); } else { - s = recurse(false, cx, inner, terminals, s, simplified); + recurse(false, cx, inner, terminals, s, simplified); } } if brackets { s.push(')'); } - s }, Or(ref v) => { if brackets { s.push('('); } - s = recurse(false, cx, &v[0], terminals, s, simplified); - for inner in &v[1..] { - s.push_str(" || "); - s = recurse(false, cx, inner, terminals, s, simplified); + for (index, inner) in v.iter().enumerate() { + if index > 0 { + s.push_str(" || "); + } + recurse(false, cx, inner, terminals, s, simplified); } if brackets { s.push(')'); } - s }, Term(n) => { + let brackets = brackets && match terminals[n as usize].node { + ExprBinary(..) => true, + _ => false, + }; if brackets { - if let ExprBinary(..) = terminals[n as usize].node { - s.push('('); - } + s.push('('); } s.push_str(&snip(terminals[n as usize])); if brackets { - if let ExprBinary(..) = terminals[n as usize].node { - s.push(')'); - } + s.push(')'); } - s }, } } let mut simplified = false; - let s = recurse(false, cx, suggestion, terminals, String::new(), &mut simplified); + let mut s = String::new(); + recurse(false, cx, suggestion, terminals, &mut s, &mut simplified); (s, simplified) } -- cgit 1.4.1-3-g733a5 From 87f5b1f043c4184ee504de4d384213b57ada912d Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 16 Nov 2017 21:20:17 +0000 Subject: Remove the union type. --- clippy_lints/src/booleans.rs | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f6440dcc428..58c2376c3a1 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -159,35 +159,11 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } -// A very simple expression type used for straightforward simplifications. -enum BinaryOrCall<'a> { - Binary(&'a str, &'a Expr, &'a Expr), - MethodCall(&'a str, &'a Expr), -} - -impl<'a> BinaryOrCall<'a> { - fn to_string(&self, cx: &LateContext, s: &mut String) { - let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); - match *self { - BinaryOrCall::Binary(op, lhs, rhs) => { - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - } - BinaryOrCall::MethodCall(method, arg) => { - s.push_str(&snip(arg)); - s.push('.'); - s.push_str(method); - s.push_str("()"); - } - } - } -} - -fn simplify_not(expr: &Expr) -> Option { +fn simplify_not(expr: &Expr, cx: &LateContext) -> Option { + let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); match expr.node { ExprBinary(binop, ref lhs, ref rhs) => { - let neg_op = match binop.node { + match binop.node { BiEq => Some(" != "), BiNe => Some(" == "), BiLt => Some(" >= "), @@ -195,15 +171,14 @@ fn simplify_not(expr: &Expr) -> Option { BiLe => Some(" > "), BiGe => Some(" < "), _ => None, - }; - neg_op.map(|op| BinaryOrCall::Binary(op, lhs, rhs)) + }.map(|op| format!("{}{}{}", &snip(lhs), op, &snip(rhs))) }, ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { METHODS_WITH_NEGATION .iter().cloned() .flat_map(|(a, b)| vec![(a, b), (b, a)]) .find(|&(a, _)| a == path.name.as_str()) - .map(|(_, neg_method)| BinaryOrCall::MethodCall(neg_method, &args[0])) + .map(|(_, neg_method)| format!("{}.{}()", &snip(&args[0]), neg_method)) }, _ => None, } @@ -234,9 +209,9 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, recurse(true, cx, inner, terminals, s, simplified) }, Term(n) => { - if let Some(binary_or_call) = simplify_not(terminals[n as usize]) { + if let Some(str) = simplify_not(terminals[n as usize], cx) { *simplified = true; - binary_or_call.to_string(cx, s) + s.push_str(&str) } else { s.push('!'); recurse(false, cx, inner, terminals, s, simplified) -- cgit 1.4.1-3-g733a5 From 7ce3b742881b048418daff97a503d99f3fc600d1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 17 Nov 2017 08:29:48 +0100 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a42ac1f9a..9eb5d8b5476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.172 +* Rustup to *rustc 1.23.0-nightly (d0f8e2913 2017-11-16)* + ## 0.0.171 * Rustup to *rustc 1.23.0-nightly (ff0f5de3b 2017-11-14)* diff --git a/Cargo.toml b/Cargo.toml index a022264985d..6328078c1d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.171" +version = "0.0.172" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.171", path = "clippy_lints" } +clippy_lints = { version = "0.0.172", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 94f4621987f..23f7f79cf66 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.171" +version = "0.0.172" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 296edda3a9fa4bdfe89bf52155432b8fcc949a8c Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 18 Nov 2017 16:10:28 +0100 Subject: const_static_lifetime: this applies not only to path types For example, &'static [u8] or &'static (t1, t2). --- clippy_lints/src/const_static_lifetime.rs | 29 ++++++++++++++++------------- tests/ui/const_static_lifetime.rs | 6 ++++++ tests/ui/const_static_lifetime.stderr | 30 ++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 6ee4dad7db4..69a4c0ae880 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -48,20 +48,23 @@ impl StaticConst { TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { - if let TyKind::Path(_, _) = borrow_type.ty.node { - // Verify that the path is a str - if lifetime.ident.name == "'static" { - let mut sug: String = String::new(); - span_lint_and_then( - cx, - CONST_STATIC_LIFETIME, - lifetime.span, - "Constants have by default a `'static` lifetime", - |db| { - db.span_suggestion(lifetime.span, "consider removing `'static`", sug); - }, - ); + match borrow_type.ty.node { + TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | + TyKind::Tup(..) => { + if lifetime.ident.name == "'static" { + let mut sug: String = String::new(); + span_lint_and_then( + cx, + CONST_STATIC_LIFETIME, + lifetime.span, + "Constants have by default a `'static` lifetime", + |db| { + db.span_suggestion(lifetime.span, "consider removing `'static`", sug); + }, + ); + } } + _ => {} } } self.visit_type(&*borrow_type.ty, cx); diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index d2caf59935e..a033f2b368e 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -17,6 +17,12 @@ const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"] const VAR_HEIGHT: &'static Foo = &Foo {}; +const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. + +const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. + +const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. + fn main() { let false_positive: &'static str = "test"; println!("{}", VAR_ONE); diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index 1eeb27c2448..d4558f7b241 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -24,6 +24,12 @@ error: Constants have by default a `'static` lifetime 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | ^^^^^^^ help: consider removing `'static` +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:12:18 + | +12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static + | ^^^^^^^ help: consider removing `'static` + error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:12:30 | @@ -36,6 +42,12 @@ error: Constants have by default a `'static` lifetime 14 | const VAR_SIX: &'static u8 = &5; | ^^^^^^^ help: consider removing `'static` +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:16:29 + | +16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; + | ^^^^^^^ help: consider removing `'static` + error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:16:39 | @@ -48,3 +60,21 @@ error: Constants have by default a `'static` lifetime 18 | const VAR_HEIGHT: &'static Foo = &Foo {}; | ^^^^^^^ help: consider removing `'static` +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:20:19 + | +20 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. + | ^^^^^^^ help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:22:19 + | +22 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. + | ^^^^^^^ help: consider removing `'static` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:24:19 + | +24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. + | ^^^^^^^ help: consider removing `'static` + -- cgit 1.4.1-3-g733a5 From 3d26c7bb7f4fe9a10c17db7dc94c46b741e45fa8 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 18 Nov 2017 16:11:07 +0100 Subject: CONTRIBUTING: clarify how to regenerate ui test output --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81618aacebc..c5dcec2167e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,8 +70,9 @@ Please document your lint with a doc comment akin to the following: Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. Of course there's little sense in writing the output yourself or copying it around. -Therefore you can simply run `tests/ui/update-all-references.sh` and check whether -the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +Therefore you can simply run `tests/ui/update-all-references.sh` (after running +`cargo test`) and check whether the output looks as you expect with `git diff`. Commit all +`*.stderr` files, too. ### Testing manually -- cgit 1.4.1-3-g733a5 From 76324851b58652d05c92c084f3274748261ca1a4 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 18 Nov 2017 16:11:55 +0100 Subject: tests: fixup arg handling for update-all-references This script does not take any args, so $1 being empty is expected. --- tests/ui/update-all-references.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/update-all-references.sh b/tests/ui/update-all-references.sh index d6aa69c7e8d..acc38f15fbd 100755 --- a/tests/ui/update-all-references.sh +++ b/tests/ui/update-all-references.sh @@ -18,7 +18,7 @@ # # See all `update-references.sh`, if you just want to update a single test. -if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" ]]; then +if [[ "$1" == "--help" || "$1" == "-h" ]]; then echo "usage: $0" fi -- cgit 1.4.1-3-g733a5 From 3efa07f9599b1e9f3c245cb7a31945e5874696c7 Mon Sep 17 00:00:00 2001 From: Johannes Hofmann Date: Sat, 18 Nov 2017 19:13:07 +0100 Subject: Ignore identifier 'OpenStreetMap' for DOC_MARKDOWN lint --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 83413ae8b48..31ed71695ce 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -157,7 +157,7 @@ define_Conf! { "JavaScript", "NaN", "OAuth", - "OpenGL", "OpenSSH", "OpenSSL", + "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", "TrueType", "iOS", "macOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", -- cgit 1.4.1-3-g733a5 From b74ed09d42b258c2ac0244d7d6ed78dfd08585f3 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 17 Nov 2017 21:18:32 +0000 Subject: Use a struct to store most of the recurse parameters for boolean expr suggestion. --- clippy_lints/src/booleans.rs | 134 +++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 58c2376c3a1..6fd935ea0f8 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -159,120 +159,130 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } -fn simplify_not(expr: &Expr, cx: &LateContext) -> Option { - let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); - match expr.node { - ExprBinary(binop, ref lhs, ref rhs) => { - match binop.node { - BiEq => Some(" != "), - BiNe => Some(" == "), - BiLt => Some(" >= "), - BiGt => Some(" <= "), - BiLe => Some(" > "), - BiGe => Some(" < "), - _ => None, - }.map(|op| format!("{}{}{}", &snip(lhs), op, &snip(rhs))) - }, - ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { - METHODS_WITH_NEGATION - .iter().cloned() - .flat_map(|(a, b)| vec![(a, b), (b, a)]) - .find(|&(a, _)| a == path.name.as_str()) - .map(|(_, neg_method)| format!("{}.{}()", &snip(&args[0]), neg_method)) - }, - _ => None, - } +struct SuggestContext<'a, 'tcx: 'a, 'v> { + terminals: &'v [&'v Expr], + cx: &'a LateContext<'a, 'tcx>, + output: String, + simplified: bool, } -// The boolean part of the return indicates whether some simplifications have been applied. -fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { - fn recurse( - brackets: bool, - cx: &LateContext, - suggestion: &Bool, - terminals: &[&Expr], - s: &mut String, - simplified: &mut bool, - ) { +impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { + fn snip(&self, e: &Expr) -> String { + snippet_opt(self.cx, e.span).expect("don't try to improve booleans created by macros") + } + + fn simplify_not(&self, expr: &Expr) -> Option { + match expr.node { + ExprBinary(binop, ref lhs, ref rhs) => { + match binop.node { + BiEq => Some(" != "), + BiNe => Some(" == "), + BiLt => Some(" >= "), + BiGt => Some(" <= "), + BiLe => Some(" > "), + BiGe => Some(" < "), + _ => None, + }.map(|op| format!("{}{}{}", self.snip(lhs), op, self.snip(rhs))) + }, + ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { + METHODS_WITH_NEGATION + .iter().cloned() + .flat_map(|(a, b)| vec![(a, b), (b, a)]) + .find(|&(a, _)| a == path.name.as_str()) + .map(|(_, neg_method)| format!("{}.{}()", self.snip(&args[0]), neg_method)) + }, + _ => None, + } + } + + fn recurse(&mut self, brackets: bool, suggestion: &Bool) { use quine_mc_cluskey::Bool::*; - let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros"); match *suggestion { True => { - s.push_str("true"); + self.output.push_str("true"); }, False => { - s.push_str("false"); + self.output.push_str("false"); }, Not(ref inner) => match **inner { And(_) | Or(_) => { - s.push('!'); - recurse(true, cx, inner, terminals, s, simplified) + self.output.push('!'); + self.recurse(true, inner) }, Term(n) => { - if let Some(str) = simplify_not(terminals[n as usize], cx) { - *simplified = true; - s.push_str(&str) + if let Some(str) = self.simplify_not(self.terminals[n as usize]) { + self.simplified = true; + self.output.push_str(&str) } else { - s.push('!'); - recurse(false, cx, inner, terminals, s, simplified) + self.output.push('!'); + self.recurse(false, inner) } }, True | False | Not(_) => { - s.push('!'); - recurse(false, cx, inner, terminals, s, simplified) + self.output.push('!'); + self.recurse(false, inner) }, }, And(ref v) => { if brackets { - s.push('('); + self.output.push('('); } for (index, inner) in v.iter().enumerate() { if index > 0 { - s.push_str(" && "); + self.output.push_str(" && "); } if let Or(_) = *inner { - recurse(true, cx, inner, terminals, s, simplified); + self.recurse(true, inner); } else { - recurse(false, cx, inner, terminals, s, simplified); + self.recurse(false, inner); } } if brackets { - s.push(')'); + self.output.push(')'); } }, Or(ref v) => { if brackets { - s.push('('); + self.output.push('('); } for (index, inner) in v.iter().enumerate() { if index > 0 { - s.push_str(" || "); + self.output.push_str(" || "); } - recurse(false, cx, inner, terminals, s, simplified); + self.recurse(false, inner); } if brackets { - s.push(')'); + self.output.push(')'); } }, Term(n) => { - let brackets = brackets && match terminals[n as usize].node { + let brackets = brackets && match self.terminals[n as usize].node { ExprBinary(..) => true, _ => false, }; if brackets { - s.push('('); + self.output.push('('); } - s.push_str(&snip(terminals[n as usize])); + let snip = self.snip(self.terminals[n as usize]); + self.output.push_str(&snip); if brackets { - s.push(')'); + self.output.push(')'); } }, } } - let mut simplified = false; - let mut s = String::new(); - recurse(false, cx, suggestion, terminals, &mut s, &mut simplified); - (s, simplified) +} + +// The boolean part of the return indicates whether some simplifications have been applied. +fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { + let mut suggest_context = SuggestContext { + terminals: terminals, + cx: cx, + output: String::new(), + simplified: false, + }; + suggest_context.recurse(false, suggestion); + (suggest_context.output, suggest_context.simplified) } fn simple_negate(b: Bool) -> Bool { -- cgit 1.4.1-3-g733a5 From 8e9d0c277c44b89aa4ff278c2f73094daf8675f0 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 17 Nov 2017 21:42:25 +0000 Subject: Remove the brackets argument. --- clippy_lints/src/booleans.rs | 51 +++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 6fd935ea0f8..b0969f36378 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } } - fn recurse(&mut self, brackets: bool, suggestion: &Bool) { + fn recurse(&mut self, suggestion: &Bool) { use quine_mc_cluskey::Bool::*; match *suggestion { True => { @@ -207,67 +207,56 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { Not(ref inner) => match **inner { And(_) | Or(_) => { self.output.push('!'); - self.recurse(true, inner) + self.output.push('('); + self.recurse(inner); + self.output.push(')'); }, Term(n) => { - if let Some(str) = self.simplify_not(self.terminals[n as usize]) { + let terminal = self.terminals[n as usize]; + if let Some(str) = self.simplify_not(terminal) { self.simplified = true; self.output.push_str(&str) } else { self.output.push('!'); - self.recurse(false, inner) + if let ExprBinary(..) = terminal.node { + self.output.push('('); + } + self.recurse(inner); + if let ExprBinary(..) = terminal.node { + self.output.push(';'); + } } }, True | False | Not(_) => { self.output.push('!'); - self.recurse(false, inner) + self.recurse(inner) }, }, And(ref v) => { - if brackets { - self.output.push('('); - } for (index, inner) in v.iter().enumerate() { if index > 0 { self.output.push_str(" && "); } if let Or(_) = *inner { - self.recurse(true, inner); + self.output.push('('); + self.recurse(inner); + self.output.push(')'); } else { - self.recurse(false, inner); + self.recurse(inner); } } - if brackets { - self.output.push(')'); - } }, Or(ref v) => { - if brackets { - self.output.push('('); - } for (index, inner) in v.iter().enumerate() { if index > 0 { self.output.push_str(" || "); } - self.recurse(false, inner); - } - if brackets { - self.output.push(')'); + self.recurse(inner); } }, Term(n) => { - let brackets = brackets && match self.terminals[n as usize].node { - ExprBinary(..) => true, - _ => false, - }; - if brackets { - self.output.push('('); - } let snip = self.snip(self.terminals[n as usize]); self.output.push_str(&snip); - if brackets { - self.output.push(')'); - } }, } } @@ -281,7 +270,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, output: String::new(), simplified: false, }; - suggest_context.recurse(false, suggestion); + suggest_context.recurse(suggestion); (suggest_context.output, suggest_context.simplified) } -- cgit 1.4.1-3-g733a5 From ed202b60555a19eeb3a0efc4832887dac4ab6016 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 17 Nov 2017 21:52:11 +0000 Subject: Bugfix + add test. --- clippy_lints/src/booleans.rs | 9 ++------- tests/ui/booleans.rs | 1 + tests/ui/booleans.stderr | 6 ++++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index b0969f36378..cce59df8086 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -218,13 +218,8 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.output.push_str(&str) } else { self.output.push('!'); - if let ExprBinary(..) = terminal.node { - self.output.push('('); - } - self.recurse(inner); - if let ExprBinary(..) = terminal.node { - self.output.push(';'); - } + let snip = self.snip(terminal); + self.output.push_str(&snip); } }, True | False | Not(_) => { diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 52ce90dd63d..b3463d03ccb 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -53,4 +53,5 @@ fn methods_with_negation() { let _ = !b.is_ok(); let c = false; let _ = !(a.is_some() && !c); + let _ = !(!c ^ c) || !a.is_some(); } diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 05696ba0f59..f38e5586078 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -160,3 +160,9 @@ error: this boolean expression can be simplified 55 | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` +error: this boolean expression can be simplified + --> $DIR/booleans.rs:56:13 + | +56 | let _ = !(!c ^ c) || !a.is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` + -- cgit 1.4.1-3-g733a5 From 41a6d015ff6d7fb778b96dec0426223a7f1b4e44 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 19 Nov 2017 09:07:50 +0000 Subject: More tests. --- tests/ui/booleans.rs | 2 ++ tests/ui/booleans.stderr | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index b3463d03ccb..0898de105af 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -54,4 +54,6 @@ fn methods_with_negation() { let c = false; let _ = !(a.is_some() && !c); let _ = !(!c ^ c) || !a.is_some(); + let _ = (!c ^ c) || !a.is_some(); + let _ = !c ^ c || !a.is_some(); } diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index f38e5586078..37b9b3941df 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -166,3 +166,15 @@ error: this boolean expression can be simplified 56 | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` +error: this boolean expression can be simplified + --> $DIR/booleans.rs:57:13 + | +57 | let _ = (!c ^ c) || !a.is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:58:13 + | +58 | let _ = !c ^ c || !a.is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` + -- cgit 1.4.1-3-g733a5 From e7f4a9bb465fd7694d9a25c56a7c8eebf73893d1 Mon Sep 17 00:00:00 2001 From: Laurent Mazare Date: Mon, 20 Nov 2017 07:47:28 +0000 Subject: Fix for the new nightly version. --- tests/ui/booleans.stderr | 3 --- tests/ui/collapsible_if.stderr | 12 ------------ tests/ui/for_loop.stderr | 21 --------------------- tests/ui/implicit_hasher.stderr | 9 --------- tests/ui/int_plus_one.stderr | 3 --- tests/ui/large_enum_variant.stderr | 2 -- tests/ui/literals.stderr | 1 - tests/ui/matches.stderr | 2 -- tests/ui/methods.stderr | 1 - tests/ui/needless_pass_by_value.stderr | 4 ---- tests/ui/needless_range_loop.stderr | 2 -- tests/ui/new_without_default.stderr | 1 - tests/ui/ptr_arg.stderr | 3 --- 13 files changed, 64 deletions(-) diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 37b9b3941df..6367ba0348c 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -72,7 +72,6 @@ error: this boolean expression can be simplified | 34 | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: try | 34 | let _ = a == b && c == 5; @@ -85,7 +84,6 @@ error: this boolean expression can be simplified | 35 | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: try | 35 | let _ = a == b && c == 5; @@ -122,7 +120,6 @@ error: this boolean expression can be simplified | 39 | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: try | 39 | let _ = c != d || a != b; diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index e726a36282b..bc10afcedb3 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -25,7 +25,6 @@ error: this if statement can be collapsed 17 | | } 18 | | } | |_____^ - | help: try | 14 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { @@ -42,7 +41,6 @@ error: this if statement can be collapsed 23 | | } 24 | | } | |_____^ - | help: try | 20 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { @@ -59,7 +57,6 @@ error: this if statement can be collapsed 29 | | } 30 | | } | |_____^ - | help: try | 26 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { @@ -76,7 +73,6 @@ error: this if statement can be collapsed 35 | | } 36 | | } | |_____^ - | help: try | 32 | if x == "hello" && x == "world" && y == "world" && y == "hello" { @@ -93,7 +89,6 @@ error: this if statement can be collapsed 41 | | } 42 | | } | |_____^ - | help: try | 38 | if 42 == 1337 && 'a' != 'A' { @@ -111,7 +106,6 @@ error: this `else { if .. }` block can be collapsed 50 | | } 51 | | } | |_____^ - | help: try | 47 | } else if y == "world" { @@ -129,7 +123,6 @@ error: this `else { if .. }` block can be collapsed 58 | | } 59 | | } | |_____^ - | help: try | 55 | } else if let Some(42) = Some(42) { @@ -149,7 +142,6 @@ error: this `else { if .. }` block can be collapsed 69 | | } 70 | | } | |_____^ - | help: try | 63 | } else if y == "world" { @@ -172,7 +164,6 @@ error: this `else { if .. }` block can be collapsed 80 | | } 81 | | } | |_____^ - | help: try | 74 | } else if let Some(42) = Some(42) { @@ -195,7 +186,6 @@ error: this `else { if .. }` block can be collapsed 91 | | } 92 | | } | |_____^ - | help: try | 85 | } else if let Some(42) = Some(42) { @@ -218,7 +208,6 @@ error: this `else { if .. }` block can be collapsed 102 | | } 103 | | } | |_____^ - | help: try | 96 | } else if x == "hello" { @@ -241,7 +230,6 @@ error: this `else { if .. }` block can be collapsed 113 | | } 114 | | } | |_____^ - | help: try | 107 | } else if let Some(42) = Some(42) { diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index f968e088866..b09350970fc 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -91,7 +91,6 @@ error: the loop variable `i` is only used to index `vec`. 96 | | let _ = vec[i]; 97 | | } | |_____^ - | help: consider using an iterator | 95 | for in &vec { @@ -104,7 +103,6 @@ error: the loop variable `j` is only used to index `STATIC`. 101 | | println!("{:?}", STATIC[j]); 102 | | } | |_____^ - | help: consider using an iterator | 100 | for in STATIC.iter().take(4) { @@ -117,7 +115,6 @@ error: the loop variable `j` is only used to index `CONST`. 105 | | println!("{:?}", CONST[j]); 106 | | } | |_____^ - | help: consider using an iterator | 104 | for in CONST.iter().take(4) { @@ -130,7 +127,6 @@ error: the loop variable `i` is used to index `vec` 109 | | println!("{} {}", vec[i], i); 110 | | } | |_____^ - | help: consider using an iterator | 108 | for (i, ) in vec.iter().enumerate() { @@ -143,7 +139,6 @@ error: the loop variable `i` is only used to index `vec2`. 117 | | println!("{}", vec2[i]); 118 | | } | |_____^ - | help: consider using an iterator | 116 | for in vec2.iter().take(vec.len()) { @@ -156,7 +151,6 @@ error: the loop variable `i` is only used to index `vec`. 121 | | println!("{}", vec[i]); 122 | | } | |_____^ - | help: consider using an iterator | 120 | for in vec.iter().skip(5) { @@ -169,7 +163,6 @@ error: the loop variable `i` is only used to index `vec`. 125 | | println!("{}", vec[i]); 126 | | } | |_____^ - | help: consider using an iterator | 124 | for in vec.iter().take(MAX_LEN) { @@ -182,7 +175,6 @@ error: the loop variable `i` is only used to index `vec`. 129 | | println!("{}", vec[i]); 130 | | } | |_____^ - | help: consider using an iterator | 128 | for in vec.iter().take(MAX_LEN + 1) { @@ -195,7 +187,6 @@ error: the loop variable `i` is only used to index `vec`. 133 | | println!("{}", vec[i]); 134 | | } | |_____^ - | help: consider using an iterator | 132 | for in vec.iter().take(10).skip(5) { @@ -208,7 +199,6 @@ error: the loop variable `i` is only used to index `vec`. 137 | | println!("{}", vec[i]); 138 | | } | |_____^ - | help: consider using an iterator | 136 | for in vec.iter().take(10 + 1).skip(5) { @@ -221,7 +211,6 @@ error: the loop variable `i` is used to index `vec` 141 | | println!("{} {}", vec[i], i); 142 | | } | |_____^ - | help: consider using an iterator | 140 | for (i, ) in vec.iter().enumerate().skip(5) { @@ -234,7 +223,6 @@ error: the loop variable `i` is used to index `vec` 145 | | println!("{} {}", vec[i], i); 146 | | } | |_____^ - | help: consider using an iterator | 144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { @@ -261,7 +249,6 @@ error: this range is empty so this for loop will never run 153 | | println!("{}", i); 154 | | } | |_____^ - | help: consider using the following if you are attempting to iterate over this range in reverse | 152 | for i in (0...10).rev() { @@ -274,7 +261,6 @@ error: this range is empty so this for loop will never run 157 | | println!("{}", i); 158 | | } | |_____^ - | help: consider using the following if you are attempting to iterate over this range in reverse | 156 | for i in (0..MAX_LEN).rev() { @@ -295,7 +281,6 @@ error: this range is empty so this for loop will never run 186 | | println!("{}", i); 187 | | } | |_____^ - | help: consider using the following if you are attempting to iterate over this range in reverse | 185 | for i in (5 + 4..10).rev() { @@ -308,7 +293,6 @@ error: this range is empty so this for loop will never run 190 | | println!("{}", i); 191 | | } | |_____^ - | help: consider using the following if you are attempting to iterate over this range in reverse | 189 | for i in ((3 - 1)..(5 + 2)).rev() { @@ -460,7 +444,6 @@ error: you seem to want to iterate on a map's values 394 | | // `in *m.values()` as we used to 395 | | } | |_____^ - | help: use the corresponding method | 390 | for v in (*m).values() { @@ -473,7 +456,6 @@ error: you seem to want to iterate on a map's values 399 | | let _v = v; 400 | | } | |_____^ - | help: use the corresponding method | 398 | for v in m.values_mut() { @@ -486,7 +468,6 @@ error: you seem to want to iterate on a map's values 404 | | let _v = v; 405 | | } | |_____^ - | help: use the corresponding method | 403 | for v in (*m).values_mut() { @@ -499,7 +480,6 @@ error: you seem to want to iterate on a map's keys 410 | | let _k = k; 411 | | } | |_____^ - | help: use the corresponding method | 409 | for k in rm.keys() { @@ -555,7 +535,6 @@ error: it looks like you're manually copying between slices 497 | | dst2[i + 500] = src[i] 498 | | } | |_____^ - | help: try replacing the loop by | 495 | dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 52b686bf8ae..aaa1e37ca82 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -19,7 +19,6 @@ error: impl for `HashMap` should be generalized over different hashers | 20 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ - | help: consider adding a type parameter | 20 | impl Foo for (HashMap,) { @@ -34,7 +33,6 @@ error: impl for `HashMap` should be generalized over different hashers | 25 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ - | help: consider adding a type parameter | 25 | impl Foo for HashMap { @@ -49,7 +47,6 @@ error: impl for `HashSet` should be generalized over different hashers | 43 | impl Foo for HashSet { | ^^^^^^^^^^ - | help: consider adding a type parameter | 43 | impl Foo for HashSet { @@ -64,7 +61,6 @@ error: impl for `HashSet` should be generalized over different hashers | 48 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ - | help: consider adding a type parameter | 48 | impl Foo for HashSet { @@ -79,7 +75,6 @@ error: parameter of type `HashMap` should be generalized over different hashers | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^ - | help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { @@ -90,7 +85,6 @@ error: parameter of type `HashSet` should be generalized over different hashers | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^ - | help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { @@ -104,7 +98,6 @@ error: impl for `HashMap` should be generalized over different hashers ... 83 | gen!(impl); | ----------- in this macro invocation - | help: consider adding a type parameter | 70 | impl Foo for HashMap { @@ -122,7 +115,6 @@ error: parameter of type `HashMap` should be generalized over different hashers ... 84 | gen!(fn bar); | ------------- in this macro invocation - | help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { @@ -136,7 +128,6 @@ error: parameter of type `HashSet` should be generalized over different hashers ... 84 | gen!(fn bar); | ------------- in this macro invocation - | help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 5d42ebb8986..69a8621fb16 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -15,7 +15,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` | 11 | y + 1 <= x; | ^^^^^^^^^^ - | help: change `>= y + 1` to `> y` as shown | 11 | y < x; @@ -26,7 +25,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` | 13 | x - 1 >= y; | ^^^^^^^^^^ - | help: change `>= y + 1` to `> y` as shown | 13 | x > y; @@ -37,7 +35,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` | 14 | y <= x - 1; | ^^^^^^^^^^ - | help: change `>= y + 1` to `> y` as shown | 14 | y < x; diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 899a84edeaa..5c6aac7d4ee 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -27,7 +27,6 @@ error: large size difference between variants | 34 | ContainingLargeEnum(LargeEnum), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: consider boxing the large fields to reduce the total size of the enum | 34 | ContainingLargeEnum(Box), @@ -62,7 +61,6 @@ error: large size difference between variants | 49 | StructLikeLarge2 { x: [i32; 8000] }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: consider boxing the large fields to reduce the total size of the enum | 49 | StructLikeLarge2 { x: Box<[i32; 8000]> }, diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 82c651e6290..bcb9dbd136b 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -77,7 +77,6 @@ error: this is a decimal constant | 30 | let fail8 = 0123; | ^^^^ - | help: if you mean to use a decimal constant, remove the `0` to remove confusion | 30 | let fail8 = 123; diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 7ff38a35341..e44a4dd7894 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -143,7 +143,6 @@ error: you don't need to add `&` to all patterns 150 | | _ => println!("none"), 151 | | } | |_____^ - | help: instead of prefixing all patterns with `&`, you can dereference the expression | 148 | match *tup { .. } @@ -165,7 +164,6 @@ error: you don't need to add `&` to all patterns 166 | | println!("none"); 167 | | } | |_____^ - | help: instead of prefixing all patterns with `&`, you can dereference the expression | 165 | if let .. = *a { .. } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 469f81c657a..65d8b82da14 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -212,7 +212,6 @@ error: called `map_or(None, f)` on an Option value. This can be done more direct 151 | | } 152 | | ); | |_________________^ - | help: try using and_then instead | 149 | let _ = opt.and_then(|x| { diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index a6c0c0454cb..2ca96b127e5 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -29,7 +29,6 @@ error: this argument is passed by value, but not consumed in the function body | 44 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ - | help: consider taking a reference instead | 44 | fn test_match(x: &Option>, y: Option>) { @@ -47,7 +46,6 @@ error: this argument is passed by value, but not consumed in the function body | 57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ - | help: consider taking a reference instead | 57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { @@ -73,7 +71,6 @@ error: this argument is passed by value, but not consumed in the function body | 75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ - | help: consider changing the type to | 75 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { @@ -94,7 +91,6 @@ error: this argument is passed by value, but not consumed in the function body | 75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ - | help: consider changing the type to | 75 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 94ee5f613fc..af78b370a12 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -19,7 +19,6 @@ error: the loop variable `i` is only used to index `ms`. 30 | | ms[i] *= 2; 31 | | } | |_____^ - | help: consider using an iterator | 29 | for in &mut ms { @@ -33,7 +32,6 @@ error: the loop variable `i` is only used to index `ms`. 37 | | *x *= 2; 38 | | } | |_____^ - | help: consider using an iterator | 35 | for in &mut ms { diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 0ced183b1e0..1f14b13306f 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -15,7 +15,6 @@ error: you should consider deriving a `Default` implementation for `Bar` | 16 | pub fn new() -> Self { Bar } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | help: try this | 13 | #[derive(Default)] diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 9c6804cd9a0..4fbf73183c4 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -23,7 +23,6 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and canno | 40 | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ - | help: change this to | 40 | fn cloned(x: &[u8]) -> Vec { @@ -42,7 +41,6 @@ error: writing `&String` instead of `&str` involves a new object where a slice w | 49 | fn str_cloned(x: &String) -> String { | ^^^^^^^ - | help: change this to | 49 | fn str_cloned(x: &str) -> String { @@ -65,7 +63,6 @@ error: writing `&String` instead of `&str` involves a new object where a slice w | 59 | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ - | help: change this to | 59 | fn false_positive_capacity(x: &Vec, y: &str) { -- cgit 1.4.1-3-g733a5 From e91b01348e4d1ebbb35232d78fd3e8b380d1e7fd Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Tue, 21 Nov 2017 16:51:36 +1100 Subject: fix usage of LayoutDetails --- clippy_lints/src/utils/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8571e5bb563..77c70922dba 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,6 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::layout::LayoutOf; use rustc_errors; use std::borrow::Cow; use std::env; @@ -1021,9 +1022,9 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - ty.layout(cx.tcx, cx.param_env) + (cx.tcx, cx.param_env).layout_of(ty) .ok() - .map(|layout| layout.size(cx.tcx).bytes()) + .map(|layout| layout.size.bytes()) } /// Returns true if the lint is allowed in the current context -- cgit 1.4.1-3-g733a5 From c362efa42048d632c968a84002ca29396f0eb115 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 21 Nov 2017 08:17:28 +0100 Subject: Version bump --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb5d8b5476..c766a8c5123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.173 +* Rustup to *rustc 1.23.0-nightly (33374fa9d 2017-11-20)* + ## 0.0.172 * Rustup to *rustc 1.23.0-nightly (d0f8e2913 2017-11-16)* @@ -538,6 +541,7 @@ All notable changes to this project will be documented in this file. [`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next [`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp +[`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result diff --git a/Cargo.toml b/Cargo.toml index 6328078c1d9..5afd8a1cb57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.172" +version = "0.0.173" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.172", path = "clippy_lints" } +clippy_lints = { version = "0.0.173", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 23f7f79cf66..a670e8c232e 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.172" +version = "0.0.173" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From af718413db3435ea7b0fe77d7a531b0dabb8f33c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 22 Nov 2017 10:55:12 +0100 Subject: Rustup --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lifetimes.rs | 10 ++++++++-- tests/ui/fallible_impl_from.stderr | 6 +++--- tests/ui/matches.stderr | 14 +++++++------- tests/ui/unused_io_amount.stderr | 4 ++-- 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c766a8c5123..25fcaf9d2da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.174 +* Rustup to *rustc 1.23.0-nightly (63739ab7b 2017-11-21)* + ## 0.0.173 * Rustup to *rustc 1.23.0-nightly (33374fa9d 2017-11-20)* diff --git a/Cargo.toml b/Cargo.toml index 5afd8a1cb57..7bdb619e8d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.173" +version = "0.0.174" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.173", path = "clippy_lints" } +clippy_lints = { version = "0.0.174", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a670e8c232e..4c88cc0c071 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.173" +version = "0.0.174" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 90c532f0746..280e504d88e 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -325,8 +325,14 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); }, - TyImplTraitExistential(ref param_bounds) | - TyImplTraitUniversal(_, ref param_bounds) => for bound in param_bounds { + TyImplTraitExistential(ref exist_ty, _) => { + for bound in &exist_ty.bounds { + if let RegionTyParamBound(_) = *bound { + self.record(&None); + } + } + } + TyImplTraitUniversal(_, ref param_bounds) => for bound in param_bounds { if let RegionTyParamBound(_) = *bound { self.record(&None); } diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 89dfaf623ed..448a1fe0559 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,7 @@ note: potential failure(s) | 31 | panic!(); | ^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:37:1 @@ -65,7 +65,7 @@ note: potential failure(s) | ^^^^^^^^^^^^^^^^^^^^^^^^^ 43 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:55:1 @@ -87,5 +87,5 @@ note: potential failure(s) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index e44a4dd7894..8ddb12b653c 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -264,7 +264,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 238 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:246:9 @@ -290,7 +290,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 244 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:252:9 @@ -316,7 +316,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 250 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:258:18 @@ -334,7 +334,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 257 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:265:18 @@ -352,7 +352,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 264 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:271:18 @@ -370,7 +370,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 270 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:277:18 @@ -388,5 +388,5 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 276 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 8739ac245a7..0ec8615a010 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -5,7 +5,7 @@ error: handle written amount returned or use `Write::write_all` instead | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-io-amount` implied by `-D warnings` - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:13:5 @@ -13,7 +13,7 @@ error: handle read amount returned or use `Read::read_exact` instead 13 | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate + = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:18:5 -- cgit 1.4.1-3-g733a5 From 464f455fe165c869bdd5504ca6e115a32593ba1e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 22 Nov 2017 21:26:11 +0100 Subject: Fix license badge anchor link [skip ci] The anchor name is lowercase, not uppercase. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52c1905c7ac..82f1908bb23 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy) [![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) -[![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#License) +[![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -- cgit 1.4.1-3-g733a5 From c22455cb9efe52d42d38922bcc309d43c50cab70 Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Sun, 26 Nov 2017 18:36:12 +0100 Subject: Check for word beginning in stutter lint --- clippy_lints/src/enum_variants.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index ea7a378de22..b3dd275f668 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -264,8 +264,17 @@ impl EarlyLintPass for EnumVariantNames { let matching = partial_match(mod_camel, &item_camel); let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); + + let is_word_beginning = |c: char| { + c == '_' || c.is_uppercase() || c.is_numeric() + }; + if matching == nchars { - span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name"); + match item_camel.chars().nth(nchars) { + Some(c) if is_word_beginning(c) => + span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name"), + _ => () + } } if rmatching == nchars { span_lint(cx, STUTTER, item.span, "item name ends with its containing module's name"); -- cgit 1.4.1-3-g733a5 From d55d4e5144602b11544ea5d8047d45d9cf02f98b Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Sun, 26 Nov 2017 18:57:34 +0100 Subject: Update ui tests --- tests/ui/stutter.rs | 4 ++++ tests/ui/stutter.stderr | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index 24612fd3b3e..761339b0a8e 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -9,6 +9,10 @@ mod foo { pub fn bar_foo() {} pub struct FooCake {} pub enum CakeFoo {} + pub struct Foo7Bar; + + // Should not warn + pub struct Foobar; } fn main() {} diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index 38cbcaa32f5..e6465a2bce9 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -24,3 +24,9 @@ error: item name ends with its containing module's name 11 | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ +error: item name starts with its containing module's name + --> $DIR/stutter.rs:12:5 + | +12 | pub struct Foo7Bar; + | ^^^^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 656df3c5ed05575ebb2cdaa27a95d8b185792ff8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 27 Nov 2017 10:20:38 +0100 Subject: Update stderr output to rustc changes --- tests/ui/regex.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1c244c1df12..9f1397990bb 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -112,7 +112,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:62:40 | -62 | let trivial_backslash = Regex::new("a//.b"); +62 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` -- cgit 1.4.1-3-g733a5 From ad63e4eaefc8063c20c8941de28211604ff02eab Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 15:45:12 +0100 Subject: Update ui output to latest nightly --- tests/ui/fallible_impl_from.stderr | 6 +++--- tests/ui/matches.stderr | 14 +++++++------- tests/ui/regex.stderr | 2 +- tests/ui/unused_io_amount.stderr | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 448a1fe0559..8e93966ccd1 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,7 @@ note: potential failure(s) | 31 | panic!(); | ^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:37:1 @@ -65,7 +65,7 @@ note: potential failure(s) | ^^^^^^^^^^^^^^^^^^^^^^^^^ 43 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:55:1 @@ -87,5 +87,5 @@ note: potential failure(s) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 8ddb12b653c..bcb94bab26c 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -264,7 +264,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 238 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:246:9 @@ -290,7 +290,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 244 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:252:9 @@ -316,7 +316,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 250 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:258:18 @@ -334,7 +334,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 257 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:265:18 @@ -352,7 +352,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 264 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:271:18 @@ -370,7 +370,7 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 270 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:277:18 @@ -388,5 +388,5 @@ note: consider refactoring into `Ok(3) | Ok(_)` | 276 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 9f1397990bb..1c244c1df12 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -112,7 +112,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:62:40 | -62 | let trivial_backslash = Regex::new("a/.b"); +62 | let trivial_backslash = Regex::new("a//.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 0ec8615a010..b4a3cb2122d 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -5,7 +5,7 @@ error: handle written amount returned or use `Write::write_all` instead | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-io-amount` implied by `-D warnings` - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:13:5 @@ -13,7 +13,7 @@ error: handle read amount returned or use `Read::read_exact` instead 13 | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:18:5 -- cgit 1.4.1-3-g733a5 From 0b0337d258857508995c8400272a637eec856a5a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 15:52:57 +0100 Subject: Fix #2247 --- clippy_lints/src/loops.rs | 4 +++- tests/ui/ty_fn_sig.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/ui/ty_fn_sig.rs diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index babf3d3cc16..dfdbe97cef4 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1668,7 +1668,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { self.visit_expr(expr); }, ExprCall(ref f, ref args) => { - for (ty, expr) in self.cx.tables.expr_ty(f).fn_sig(self.cx.tcx).inputs().skip_binder().iter().zip(args) { + self.visit_expr(f); + for expr in args { + let ty = self.cx.tables.expr_ty_adjusted(expr); self.prefer_mutable = false; if let ty::TyRef(_, mutbl) = ty.sty { if mutbl.mutbl == MutMutable { diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs new file mode 100644 index 00000000000..b6f9e645d26 --- /dev/null +++ b/tests/ui/ty_fn_sig.rs @@ -0,0 +1,9 @@ +// Regression test + +pub fn retry(f: F) { + for _i in 0.. { + f(); + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From f65a022ace92d9db4849dae2955a5b1bc8daca79 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 16:03:05 +0100 Subject: Fix #2245 --- clippy_lints/src/booleans.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index cce59df8086..50afd1b1e4f 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -167,8 +167,8 @@ struct SuggestContext<'a, 'tcx: 'a, 'v> { } impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { - fn snip(&self, e: &Expr) -> String { - snippet_opt(self.cx, e.span).expect("don't try to improve booleans created by macros") + fn snip(&self, e: &Expr) -> Option { + snippet_opt(self.cx, e.span) } fn simplify_not(&self, expr: &Expr) -> Option { @@ -182,20 +182,20 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { BiLe => Some(" > "), BiGe => Some(" < "), _ => None, - }.map(|op| format!("{}{}{}", self.snip(lhs), op, self.snip(rhs))) + }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { METHODS_WITH_NEGATION .iter().cloned() .flat_map(|(a, b)| vec![(a, b), (b, a)]) .find(|&(a, _)| a == path.name.as_str()) - .map(|(_, neg_method)| format!("{}.{}()", self.snip(&args[0]), neg_method)) + .and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method))) }, _ => None, } } - fn recurse(&mut self, suggestion: &Bool) { + fn recurse(&mut self, suggestion: &Bool) -> Option<()> { use quine_mc_cluskey::Bool::*; match *suggestion { True => { @@ -218,13 +218,13 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.output.push_str(&str) } else { self.output.push('!'); - let snip = self.snip(terminal); + let snip = self.snip(terminal)?; self.output.push_str(&snip); } }, True | False | Not(_) => { self.output.push('!'); - self.recurse(inner) + self.recurse(inner)?; }, }, And(ref v) => { @@ -250,10 +250,11 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } }, Term(n) => { - let snip = self.snip(self.terminals[n as usize]); + let snip = self.snip(self.terminals[n as usize])?; self.output.push_str(&snip); }, } + Some(()) } } -- cgit 1.4.1-3-g733a5 From e62727ee514f0820bfc3b70af99bf3cd0e9718bb Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 16:05:13 +0100 Subject: Add regression test (fixes #2234) --- tests/ui/ty_fn_sig.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs index b6f9e645d26..9e2753dcb18 100644 --- a/tests/ui/ty_fn_sig.rs +++ b/tests/ui/ty_fn_sig.rs @@ -6,4 +6,9 @@ pub fn retry(f: F) { } } -fn main() {} +fn main() { + for y in 0..4 { + let func = || (); + func(); + } +} -- cgit 1.4.1-3-g733a5 From 317e97bae79331cba506da9615850405fa82d937 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 17:06:27 +0100 Subject: Fix #2196 --- clippy_lints/src/new_without_default.rs | 123 ++++++++++++++++---------------- tests/ui/new_without_default.rs | 6 ++ 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index d56833eb457..b037ef6c42b 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,9 +1,7 @@ -use rustc::hir::intravisit::FnKind; use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::*; use rustc::ty::{self, Ty}; -use syntax::ast; use syntax::codemap::Span; use utils::paths; use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; @@ -90,66 +88,67 @@ impl LintPass for NewWithoutDefault { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { - fn check_fn( - &mut self, - cx: &LateContext<'a, 'tcx>, - kind: FnKind<'tcx>, - decl: &'tcx hir::FnDecl, - _: &'tcx hir::Body, - span: Span, - id: ast::NodeId, - ) { - if in_external_macro(cx, span) { - return; - } - - if let FnKind::Method(name, sig, _, _) = kind { - if sig.constness == hir::Constness::Const { - // can't be implemented by default - return; - } - if !cx.generics - .expect("method must have generics") - .ty_params - .is_empty() - { - // when the result of `new()` depends on a type parameter we should not require - // an - // impl of `Default` - return; - } - if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { - let self_ty = cx.tcx - .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); - if_chain! { - if same_tys(cx, self_ty, return_ty(cx, id)); - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); - if !implements_trait(cx, self_ty, default_trait_id, &[]); - then { - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then( - cx, - NEW_WITHOUT_DEFAULT_DERIVE, - span, - &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), - |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); - }); - } else { - span_lint_and_then( - cx, - NEW_WITHOUT_DEFAULT, - span, - &format!("you should consider adding a `Default` implementation for `{}`", self_ty), - |db| { - db.suggest_prepend_item( - cx, - span, - "try this", - &create_new_without_default_suggest_msg(self_ty), - ); - }, - ); + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { + if let hir::ItemImpl(_, _, _, _, None, _, ref items) = item.node { + for assoc_item in items { + if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind { + let impl_item = cx.tcx.hir.impl_item(assoc_item.id); + if in_external_macro(cx, impl_item.span) { + return; + } + if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { + let name = impl_item.name; + let span = impl_item.span; + let id = impl_item.id; + let decl = &sig.decl; + if sig.constness == hir::Constness::Const { + // can't be implemented by default + return; + } + if !impl_item.generics + .ty_params + .is_empty() + { + // when the result of `new()` depends on a type parameter we should not require + // an + // impl of `Default` + return; + } + if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { + let self_ty = cx.tcx + .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); + if_chain! { + if same_tys(cx, self_ty, return_ty(cx, id)); + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); + if !implements_trait(cx, self_ty, default_trait_id, &[]); + then { + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { + span_lint_and_then( + cx, + NEW_WITHOUT_DEFAULT_DERIVE, + span, + &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), + |db| { + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + }); + } else { + span_lint_and_then( + cx, + NEW_WITHOUT_DEFAULT, + span, + &format!("you should consider adding a `Default` implementation for `{}`", self_ty), + |db| { + db.suggest_prepend_item( + cx, + span, + "try this", + &create_new_without_default_suggest_msg(self_ty), + ); + }, + ); + } + } + } } } } diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 9fd0fea137c..e618bf1c231 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -83,4 +83,10 @@ impl IgnoreGenericNew { pub fn new() -> Self { IgnoreGenericNew } // the derived Default does not make sense here as the result depends on T } +pub trait TraitWithNew: Sized { + fn new() -> Self { + panic!() + } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From d5b73c184b31f90ae0ef299e109d87225f139d5e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 17:10:53 +0100 Subject: Fix placement of new_without_default suggestion --- clippy_lints/src/new_without_default.rs | 15 +++++---------- tests/ui/new_without_default.stderr | 13 ++++++------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index b037ef6c42b..b281fd3060e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -98,23 +98,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { let name = impl_item.name; - let span = impl_item.span; let id = impl_item.id; - let decl = &sig.decl; if sig.constness == hir::Constness::Const { // can't be implemented by default return; } - if !impl_item.generics - .ty_params - .is_empty() - { + if !impl_item.generics.ty_params.is_empty() { // when the result of `new()` depends on a type parameter we should not require // an // impl of `Default` return; } - if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { + if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); if_chain! { @@ -126,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { span_lint_and_then( cx, NEW_WITHOUT_DEFAULT_DERIVE, - span, + impl_item.span, &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), |db| { db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); @@ -135,12 +130,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { span_lint_and_then( cx, NEW_WITHOUT_DEFAULT, - span, + impl_item.span, &format!("you should consider adding a `Default` implementation for `{}`", self_ty), |db| { db.suggest_prepend_item( cx, - span, + item.span, "try this", &create_new_without_default_suggest_msg(self_ty), ); diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 1f14b13306f..c12c10b9ae0 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -29,11 +29,10 @@ error: you should consider adding a `Default` implementation for `LtKo<'c>` = note: `-D new-without-default` implied by `-D warnings` help: try this | -64 | impl Default for LtKo<'c> { -65 | fn default() -> Self { -66 | Self::new() -67 | } -68 | } -69 | - ... +63 | impl Default for LtKo<'c> { +64 | fn default() -> Self { +65 | Self::new() +66 | } +67 | } + | -- cgit 1.4.1-3-g733a5 From 273ddafac59869d35dc654be79e89b0c33b33569 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Nov 2017 17:20:00 +0100 Subject: Fix #2188 --- clippy_lints/src/fallible_impl_from.rs | 3 ++- tests/ui/fallible_impl_from.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 0c91d0cd97c..5b9830ad0ab 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir; use rustc::ty; use syntax_pos::Span; -use utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; +use utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of}; use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` @@ -66,6 +66,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it if let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node; if match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT); + if is_expn_of(expr.span, "unreachable").is_none(); then { self.result.push(expr.span); } diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index eb1cd4c5e9a..db118919071 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -61,4 +61,18 @@ impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { } } +struct Unreachable; + +impl From for Unreachable { + fn from(s: String) -> Unreachable { + if s.is_empty() { + return Unreachable; + } + match s.chars().next() { + Some(_) => Unreachable, + None => unreachable!(), // do not lint the unreachable macro + } + } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From f8dbd32433bce7e63f48604423ba8d88e2bf47aa Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 29 Nov 2017 20:42:37 +0000 Subject: Add a couple small tests to the match-same-arm lint. --- clippy_lints/src/copies.rs | 12 ++++-------- tests/ui/matches.rs | 20 ++++++++++++++++++++ tests/ui/matches.stderr | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 862272456ea..04874e60224 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -203,14 +203,10 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { db.span_note(i.body.span, "same as this"); // Note: this does not use `span_suggestion` on purpose: there is no clean way - // to - // remove the other arm. Building a span and suggest to replace it to "" makes - // an - // even more confusing error message. Also in order not to make up a span for - // the - // whole pattern, the suggestion is only shown when there is only one pattern. - // The - // user should know about `|` if they are already using it… + // to remove the other arm. Building a span and suggest to replace it to "" + // makes an even more confusing error message. Also in order not to make up a + // span for the whole pattern, the suggestion is only shown when there is only + // one pattern. The user should know about `|` if they are already using it… if i.pats.len() == 1 && j.pats.len() == 1 { let lhs = snippet(cx, i.pats[0].span, ""); diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index f97038ca1f0..f15a57c4f85 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -277,6 +277,26 @@ fn match_wild_err_arm() { Ok(_) => println!("ok"), Err(_) => {unreachable!();} } + + // no warning because of the guard + match x { + Ok(x) if x*x == 64 => println!("ok"), + Ok(_) => println!("ok"), + Err(_) => println!("err") + } + + match (x, Some(1i32)) { + (Ok(x), Some(_)) => println!("ok {}", x), + (Ok(_), Some(x)) => println!("ok {}", x), + _ => println!("err") + } + + // no warning because of the different types for x + match (x, Some(1.0f64)) { + (Ok(x), Some(_)) => println!("ok {}", x), + (Ok(_), Some(x)) => println!("ok {}", x), + _ => println!("err") + } } fn main() { diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index bcb94bab26c..cc7c5a4fee2 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -390,3 +390,21 @@ note: consider refactoring into `Ok(3) | Ok(_)` | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +error: this `match` has identical arm bodies + --> $DIR/matches.rs:290:29 + | +290 | (Ok(_), Some(x)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:289:29 + | +289 | (Ok(x), Some(_)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ +note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` + --> $DIR/matches.rs:289:29 + | +289 | (Ok(x), Some(_)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + -- cgit 1.4.1-3-g733a5 From 3eb642bcdd0ce547c4e361b1b8635c69aabb37ca Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 29 Nov 2017 20:52:49 +0000 Subject: Add another test. --- tests/ui/matches.rs | 8 ++++++++ tests/ui/matches.stderr | 30 ++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index f15a57c4f85..7da2858d6ec 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -285,6 +285,14 @@ fn match_wild_err_arm() { Err(_) => println!("err") } + // this is a current false positive, see #1996 + match x { + Ok(3) => println!("ok"), + Ok(x) if x*x == 64 => println!("ok 64"), + Ok(_) => println!("ok"), + Err(_) => println!("err") + } + match (x, Some(1i32)) { (Ok(x), Some(_)) => println!("ok {}", x), (Ok(_), Some(x)) => println!("ok {}", x), diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index cc7c5a4fee2..49c0e900d06 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -391,20 +391,38 @@ note: consider refactoring into `Ok(3) | Ok(_)` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:290:29 + --> $DIR/matches.rs:292:18 | -290 | (Ok(_), Some(x)) => println!("ok {}", x), +292 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:290:18 + | +290 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:290:18 + | +290 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: this `match` has identical arm bodies + --> $DIR/matches.rs:298:29 + | +298 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:289:29 + --> $DIR/matches.rs:297:29 | -289 | (Ok(x), Some(_)) => println!("ok {}", x), +297 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:289:29 + --> $DIR/matches.rs:297:29 | -289 | (Ok(x), Some(_)) => println!("ok {}", x), +297 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -- cgit 1.4.1-3-g733a5 From c3ae2ddeb36d59432e97c07f85ac841abf3483b6 Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 29 Nov 2017 21:42:58 +0000 Subject: Fix a bug in search_same + add a test case. --- clippy_lints/src/consts.rs | 3 +-- clippy_lints/src/copies.rs | 9 ++++++--- clippy_lints/src/doc.rs | 3 +-- tests/ui/matches.rs | 8 ++++++++ tests/ui/matches.stderr | 18 ++++++++++++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 7e6f3c2acf1..69527ba6ff8 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -74,9 +74,8 @@ impl PartialEq for Constant { } }, (&Constant::Bool(l), &Constant::Bool(r)) => l == r, - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, + (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, _ => false, // TODO: Are there inter-type equalities? } } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 04874e60224..5a693ce5524 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -325,10 +325,13 @@ where for expr in exprs { match map.entry(hash(expr)) { - Entry::Occupied(o) => for o in o.get() { - if eq(o, expr) { - return Some((o, expr)); + Entry::Occupied(mut o) => { + for o in o.get() { + if eq(o, expr) { + return Some((o, expr)); + } } + o.get_mut().push(expr); }, Entry::Vacant(v) => { v.insert(vec![expr]); diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index b6542b2ebca..ea8ecb91d0a 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -206,8 +206,7 @@ fn check_doc<'a, Events: Iterator)>>( End(Link(_, _)) => in_link = None, Start(_tag) | End(_tag) => (), // We don't care about other tags Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it - SoftBreak => (), - HardBreak => (), + SoftBreak | HardBreak => (), FootnoteReference(text) | Text(text) => { if Some(&text) == in_link.as_ref() { // Probably a link of the form `` diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 7da2858d6ec..352749d48e1 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -305,6 +305,14 @@ fn match_wild_err_arm() { (Ok(_), Some(x)) => println!("ok {}", x), _ => println!("err") } + + // because of a bug, no warning was generated for this case before #2251 + match x { + Ok(_tmp) => println!("ok"), + Ok(3) => println!("ok"), + Ok(_) => println!("ok"), + Err(_) => {unreachable!();} + } } fn main() { diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 49c0e900d06..beb3387d038 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -426,3 +426,21 @@ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +error: this `match` has identical arm bodies + --> $DIR/matches.rs:313:18 + | +313 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | +note: same as this + --> $DIR/matches.rs:312:18 + | +312 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ +note: consider refactoring into `Ok(3) | Ok(_)` + --> $DIR/matches.rs:312:18 + | +312 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + -- cgit 1.4.1-3-g733a5 From 4d9c41f5666d25dd2747ed610bc7d58e8cdea6a5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Nov 2017 09:31:23 +0100 Subject: Use latest compiletest --- tests/ui/regex.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1c244c1df12..9f1397990bb 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -112,7 +112,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:62:40 | -62 | let trivial_backslash = Regex::new("a//.b"); +62 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` -- cgit 1.4.1-3-g733a5 From 7d7fef1690218bbb406cf3bcadf7bb29dbb40cc5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Nov 2017 10:54:55 +0100 Subject: Fix #1925 --- clippy_lints/src/methods.rs | 54 +++++++++++++++++++++++++++++++++------ tests/ui/clone_on_copy_mut.rs | 18 +++++++++++++ tests/ui/unnecessary_clone.stderr | 10 +++++++- 3 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 tests/ui/clone_on_copy_mut.rs diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index ee61920b489..4a52df92b27 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -7,6 +7,7 @@ use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; +use std::iter; use syntax::ast; use syntax::codemap::Span; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, @@ -944,7 +945,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) { let ty = cx.tables.expr_ty(expr); if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty { - if let ty::TyRef(..) = inner.sty { + if let ty::TyRef(_, ty::TypeAndMut { ty: innermost, .. }) = inner.sty { span_lint_and_then( cx, CLONE_DOUBLE_REF, @@ -952,7 +953,17 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t "using `clone` on a double-reference; \ this will copy the reference instead of cloning the inner type", |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref())); + let mut ty = innermost; + let mut n = 0; + while let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = ty.sty { + ty = inner; + n += 1; + } + let refs: String = iter::repeat('&').take(n + 1).collect(); + let derefs: String = iter::repeat('*').take(n).collect(); + let explicit = format!("{}{}::clone({})", refs, ty, snip); + db.span_suggestion(expr.span, "try dereferencing it", format!("{}({}{}).clone()", refs, derefs, snip.deref())); + db.span_suggestion(expr.span, "or try being explicit about what type to clone", explicit); }, ); return; // don't report clone_on_copy @@ -960,13 +971,40 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } if is_copy(cx, ty) { - span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { - if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - if let ty::TyRef(..) = cx.tables.expr_ty(arg).sty { - db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref())); - } else { - db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip)); + let snip; + if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { + if let ty::TyRef(..) = cx.tables.expr_ty(arg).sty { + let parent = cx.tcx.hir.get_parent_node(expr.id); + match cx.tcx.hir.get(parent) { + hir::map::NodeExpr(parent) => match parent.node { + // &*x is a nop, &x.clone() is not + hir::ExprAddrOf(..) | + // (*x).func() is useless, x.clone().func() can work in case func borrows mutably + hir::ExprMethodCall(..) => return, + _ => {}, + } + hir::map::NodeStmt(stmt) => { + if let hir::StmtDecl(ref decl, _) = stmt.node { + if let hir::DeclLocal(ref loc) = decl.node { + if let hir::PatKind::Ref(..) = loc.pat.node { + // let ref y = *x borrows x, let ref y = x.clone() does not + return; + } + } + } + }, + _ => {}, } + snip = Some(("try dereferencing it", format!("{}", snippet.deref()))); + } else { + snip = Some(("try removing the `clone` call", format!("{}", snippet))); + } + } else { + snip = None; + } + span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { + if let Some((text, snip)) = snip { + db.span_suggestion(expr.span, text, snip); } }); } diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs new file mode 100644 index 00000000000..5bfa256623b --- /dev/null +++ b/tests/ui/clone_on_copy_mut.rs @@ -0,0 +1,18 @@ +pub fn dec_read_dec(i: &mut i32) -> i32 { + *i -= 1; + let ret = *i; + *i -= 1; + ret +} + +pub fn minus_1(i: &i32) -> i32 { + dec_read_dec(&mut i.clone()) +} + +fn main() { + let mut i = 10; + assert_eq!(minus_1(&i), 9); + assert_eq!(i, 10); + assert_eq!(dec_read_dec(&mut i), 9); + assert_eq!(i, 8); +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 17263756980..437df1ee97c 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -54,9 +54,17 @@ error: using `clone` on a double-reference; this will copy the reference instead --> $DIR/unnecessary_clone.rs:49:22 | 49 | let z: &Vec<_> = y.clone(); - | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` + | ^^^^^^^^^ | = note: `-D clone-double-ref` implied by `-D warnings` +help: try dereferencing it + | +49 | let z: &Vec<_> = &(*y).clone(); + | ^^^^^^^^^^^^^ +help: or try being explicit about what type to clone + | +49 | let z: &Vec<_> = &std::vec::Vec::clone(y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable --> $DIR/unnecessary_clone.rs:56:27 -- cgit 1.4.1-3-g733a5 From 5fca6eb89eebe00238c66bc57b1ab2ecf236dfdd Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 20 Oct 2017 21:26:41 -0400 Subject: Fix #2160 --- clippy_lints/src/is_unit_expr.rs | 1 + tests/ui/is_unit_expr.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 3f94178e524..422d9739ef9 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -132,6 +132,7 @@ fn is_unit_expr(expr: &Expr) -> Option { } fn check_last_stmt_in_block(block: &Block) -> bool { + if block.stmts.is_empty() { return false; } let final_stmt = &block.stmts[block.stmts.len() - 1]; diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 24a2587dc53..7e2cc4725f0 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -71,3 +71,7 @@ pub fn foo() -> i32 { }; 55 } + +pub fn issue_2160() { + let x = {}; +} -- cgit 1.4.1-3-g733a5 From e2bc383383b211c63e5edf136c47e6d4449c8a6f Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 30 Nov 2017 19:38:29 -0500 Subject: Add linting for empty blocks too --- clippy_lints/src/is_unit_expr.rs | 109 ++++++++++++++++++--------------------- tests/ui/is_unit_expr.rs | 4 +- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 422d9739ef9..90e2ef760f7 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::ext::quote::rt::Span; -use utils::span_note_and_lint; +use utils::{span_lint, span_note_and_lint}; /// **What it does:** Checks for /// - () being assigned to a variable @@ -24,6 +24,12 @@ declare_lint! { "unintended assignment or use of a unit typed value" } +#[derive(Copy, Clone)] +enum UnitCause { + SemiColon, + EmptyBlock, +} + #[derive(Copy, Clone)] pub struct UnitExpr; @@ -36,43 +42,16 @@ impl LintPass for UnitExpr { impl EarlyLintPass for UnitExpr { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { if let ExprKind::Assign(ref _left, ref right) = expr.node { - if let Some(span) = is_unit_expr(right) { - span_note_and_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - span, - "Consider removing the trailing semicolon", - ); - } + check_for_unit(cx, right); } if let ExprKind::MethodCall(ref _left, ref args) = expr.node { for arg in args { - if let Some(span) = is_unit_expr(arg) { - span_note_and_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - span, - "Consider removing the trailing semicolon", - ); - } + check_for_unit(cx, arg); } } if let ExprKind::Call(_, ref args) = expr.node { for arg in args { - if let Some(span) = is_unit_expr(arg) { - span_note_and_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - span, - "Consider removing the trailing semicolon", - ); - } + check_for_unit(cx, arg); } } } @@ -83,28 +62,41 @@ impl EarlyLintPass for UnitExpr { return; } if let Some(ref expr) = local.init { - if let Some(span) = is_unit_expr(expr) { - span_note_and_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - span, - "Consider removing the trailing semicolon", - ); - } + check_for_unit(cx, expr); } } } } -fn is_unit_expr(expr: &Expr) -> Option { +fn check_for_unit(cx: &EarlyContext, expr: &Expr) { + match is_unit_expr(expr) { + Some((span, UnitCause::SemiColon)) => span_note_and_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression evaluates to the Unit type ()", + span, + "Consider removing the trailing semicolon", + ), + Some((_span, UnitCause::EmptyBlock)) => span_lint( + cx, + UNIT_EXPR, + expr.span, + "This expression evaluates to the Unit type ()", + ), + None => (), + } +} + +fn is_unit_expr(expr: &Expr) -> Option<(Span, UnitCause)> { match expr.node { - ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { - Some(block.stmts[block.stmts.len() - 1].span) - } else { - None - }, + ExprKind::Block(ref block) => match check_last_stmt_in_block(block) { + Some(UnitCause::SemiColon) => + Some((block.stmts[block.stmts.len() - 1].span, UnitCause::SemiColon)), + Some(UnitCause::EmptyBlock) => + Some((block.span, UnitCause::EmptyBlock)), + None => None + } ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); if let Some(ref else_) = *else_ { @@ -113,16 +105,15 @@ fn is_unit_expr(expr: &Expr) -> Option { return Some(*expr_else); } } - if check_then { - Some(expr.span) - } else { - None + match check_then { + Some(c) => Some((expr.span, c)), + None => None, } }, ExprKind::Match(ref _pattern, ref arms) => { for arm in arms { - if let Some(expr) = is_unit_expr(&arm.body) { - return Some(expr); + if let Some(r) = is_unit_expr(&arm.body) { + return Some(r); } } None @@ -131,19 +122,19 @@ fn is_unit_expr(expr: &Expr) -> Option { } } -fn check_last_stmt_in_block(block: &Block) -> bool { - if block.stmts.is_empty() { return false; } +fn check_last_stmt_in_block(block: &Block) -> Option { + if block.stmts.is_empty() { return Some(UnitCause::EmptyBlock); } let final_stmt = &block.stmts[block.stmts.len() - 1]; // Made a choice here to risk false positives on divergent macro invocations // like `panic!()` match final_stmt.node { - StmtKind::Expr(_) => false, + StmtKind::Expr(_) => None, StmtKind::Semi(ref expr) => match expr.node { - ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => false, - _ => true, + ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => None, + _ => Some(UnitCause::SemiColon), }, - _ => true, + _ => Some(UnitCause::SemiColon), // not sure what's happening here } } diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs index 7e2cc4725f0..6c8f108d9f6 100644 --- a/tests/ui/is_unit_expr.rs +++ b/tests/ui/is_unit_expr.rs @@ -73,5 +73,7 @@ pub fn foo() -> i32 { } pub fn issue_2160() { - let x = {}; + let x1 = {}; + let x2 = if true {} else {}; + let x3 = match None { Some(_) => {}, None => {}, }; } -- cgit 1.4.1-3-g733a5 From c2c324ec657888667a71f361f3cdca48ff843a61 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 30 Nov 2017 19:50:31 -0500 Subject: Update ui test --- tests/ui/is_unit_expr.stderr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index 5524f866488..64a7ad86b70 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -51,3 +51,21 @@ note: Consider removing the trailing semicolon 42 | x; | ^^ +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:76:14 + | +76 | let x1 = {}; + | ^^ + +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:77:14 + | +77 | let x2 = if true {} else {}; + | ^^^^^^^^^^^^^^^^^^ + +error: This expression evaluates to the Unit type () + --> $DIR/is_unit_expr.rs:78:14 + | +78 | let x3 = match None { Some(_) => {}, None => {}, }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 904f27a2ea7b13161cefc0a359b51a0e49f878b3 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 1 Dec 2017 19:25:43 +0000 Subject: Do raise a same-arms warning when the two arms are separated by an arm with a guard, fix #1996. --- clippy_lints/src/copies.rs | 32 ++++++++++++++++++-------------- tests/ui/matches.rs | 2 +- tests/ui/matches.stderr | 18 ------------------ tests/ui/regex.stderr | 2 +- 4 files changed, 20 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 5a693ce5524..140b895526d 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -178,22 +178,26 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { /// Implementation if `MATCH_SAME_ARMS`. fn lint_match_arms(cx: &LateContext, expr: &Expr) { - let hash = |arm: &Arm| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_expr(&arm.body); - h.finish() - }; + if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { + let hash = |&(_, arm): &(usize, &Arm)| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_expr(&arm.body); + h.finish() + }; - let eq = |lhs: &Arm, rhs: &Arm| -> bool { - // Arms with a guard are ignored, those can’t always be merged together - lhs.guard.is_none() && rhs.guard.is_none() && - SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && - // all patterns should have the same bindings - bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) - }; + let eq = |&(lindex, lhs): &(usize, &Arm), &(rindex, rhs): &(usize, &Arm)| -> bool { + let min_index = usize::min(lindex, rindex); + let max_index = usize::max(rindex, rindex); + // Arms with a guard are ignored, those can’t always be merged together + // This is also the case for arms in-between each there is an arm with a guard + (min_index..=max_index).all(|index| arms[index].guard.is_none()) && + SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && + // all patterns should have the same bindings + bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0]) + }; - if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { - if let Some((i, j)) = search_same(arms, hash, eq) { + let indexed_arms: Vec<(usize, &Arm)> = arms.iter().enumerate().collect(); + if let Some((&(_, i), &(_, j))) = search_same(&indexed_arms, hash, eq) { span_lint_and_then( cx, MATCH_SAME_ARMS, diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 352749d48e1..8130436d485 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -285,7 +285,7 @@ fn match_wild_err_arm() { Err(_) => println!("err") } - // this is a current false positive, see #1996 + // this used to be a false positive, see #1996 match x { Ok(3) => println!("ok"), Ok(x) if x*x == 64 => println!("ok 64"), diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index beb3387d038..8c0ec49e626 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -390,24 +390,6 @@ note: consider refactoring into `Ok(3) | Ok(_)` | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: this `match` has identical arm bodies - --> $DIR/matches.rs:292:18 - | -292 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | -note: same as this - --> $DIR/matches.rs:290:18 - | -290 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ -note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:290:18 - | -290 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - error: this `match` has identical arm bodies --> $DIR/matches.rs:298:29 | diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 9f1397990bb..1c244c1df12 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -112,7 +112,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:62:40 | -62 | let trivial_backslash = Regex::new("a/.b"); +62 | let trivial_backslash = Regex::new("a//.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` -- cgit 1.4.1-3-g733a5 From c3a8946a46195ed44da95fb62f55ee527d9d5c6e Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 1 Dec 2017 19:27:02 +0000 Subject: Bugfix the bugfix. --- clippy_lints/src/copies.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 140b895526d..181158a5f17 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -187,7 +187,7 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) { let eq = |&(lindex, lhs): &(usize, &Arm), &(rindex, rhs): &(usize, &Arm)| -> bool { let min_index = usize::min(lindex, rindex); - let max_index = usize::max(rindex, rindex); + let max_index = usize::max(lindex, rindex); // Arms with a guard are ignored, those can’t always be merged together // This is also the case for arms in-between each there is an arm with a guard (min_index..=max_index).all(|index| arms[index].guard.is_none()) && -- cgit 1.4.1-3-g733a5 From 6c18811764ab951f7c6599daf623ddd856fa1c3b Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 1 Dec 2017 19:59:40 +0000 Subject: Revert the regex test change. --- tests/ui/regex.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1c244c1df12..9f1397990bb 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -112,7 +112,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:62:40 | -62 | let trivial_backslash = Regex::new("a//.b"); +62 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` -- cgit 1.4.1-3-g733a5 From 4121507a48906753d79071f36a8821760e68527c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 2 Dec 2017 18:23:32 +0900 Subject: Rustup to rustc 1.24.0-nightly (bb42071f6 2017-12-01) --- clippy_lints/src/unsafe_removed_from_name.rs | 41 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 1c9bf70429d..637df96180a 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -35,26 +35,27 @@ impl LintPass for UnsafeNameRemoval { impl EarlyLintPass for UnsafeNameRemoval { fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemKind::Use(ref item_use) = item.node { - match item_use.node { - ViewPath_::ViewPathSimple(ref name, ref path) => { - unsafe_to_safe_check( - path.segments - .last() - .expect("use paths cannot be empty") - .identifier, - *name, - cx, - &item.span, - ); - }, - ViewPath_::ViewPathList(_, ref path_list_items) => for path_list_item in path_list_items.iter() { - let plid = path_list_item.node; - if let Some(rename) = plid.rename { - unsafe_to_safe_check(plid.name, rename, cx, &item.span); - }; - }, - ViewPath_::ViewPathGlob(_) => {}, + if let ItemKind::Use(ref use_tree) = item.node { + check_use_tree(use_tree, cx, &item.span); + } + } +} + +fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { + match use_tree.kind { + UseTreeKind::Simple(new_name) => { + let old_name = use_tree + .prefix + .segments + .last() + .expect("use paths cannot be empty") + .identifier; + unsafe_to_safe_check(old_name, new_name, cx, span); + } + UseTreeKind::Glob => {}, + UseTreeKind::Nested(ref nested_use_tree) => { + for &(ref use_tree, _) in nested_use_tree { + check_use_tree(use_tree, cx, span); } } } -- cgit 1.4.1-3-g733a5 From 7525854f302e05d9d91894089b48fe2319ece494 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 2 Dec 2017 13:02:02 +0100 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25fcaf9d2da..6093bc0b5b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.175 +* Rustup to *rustc 1.24.0-nightly (bb42071f6 2017-12-01)* + ## 0.0.174 * Rustup to *rustc 1.23.0-nightly (63739ab7b 2017-11-21)* diff --git a/Cargo.toml b/Cargo.toml index 7bdb619e8d0..5101ae05d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.174" +version = "0.0.175" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.174", path = "clippy_lints" } +clippy_lints = { version = "0.0.175", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 4c88cc0c071..cbf40240a7f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.174" +version = "0.0.175" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 299ffcab776cbcf09da4a613d75dec2ff7d43868 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Dec 2017 08:09:46 +0100 Subject: Try fixing const_with_static_lifetime docs --- clippy_lints/src/const_static_lifetime.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 69a4c0ae880..3ad3be181d2 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -18,7 +18,6 @@ use utils::{in_macro, span_lint_and_then}; /// ```rust /// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...] /// ``` - declare_lint! { pub CONST_STATIC_LIFETIME, Warn, -- cgit 1.4.1-3-g733a5 From f5f0273f53f06f19da441e3cedc2ba69300cf568 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Dec 2017 11:20:48 +0100 Subject: Update ui tests to latest rustc changes --- tests/ui/never_loop.stderr | 16 ++++++++------- tests/ui/overflow_check_conditional.stderr | 32 +++++++++++++++--------------- tests/ui/redundant_closure_call.stderr | 20 +++++++++---------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 1f9df6f9ccc..e62fe0c2905 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -24,13 +24,14 @@ error: this loop never actually loops error: this loop never actually loops --> $DIR/never_loop.rs:47:2 | -47 | / loop { // never loops +47 | loop { // never loops + | _____^ 48 | | while i == 0 { // never loops 49 | | break 50 | | } 51 | | return -52 | | } - | |__^ +52 | | } + | |_____^ error: this loop never actually loops --> $DIR/never_loop.rs:48:9 @@ -43,11 +44,12 @@ error: this loop never actually loops error: this loop never actually loops --> $DIR/never_loop.rs:59:3 | -59 | / loop { // never loops +59 | loop { // never loops + | _________^ 60 | | if x == 5 { break } -61 | | continue 'outer -62 | | } - | |___^ +61 | | continue 'outer +62 | | } + | |_________^ error: this loop never actually loops --> $DIR/never_loop.rs:92:5 diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 9f23e96c065..6efcbfe38e1 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,50 +1,50 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:11:5 | -11 | if a + b < a { - | ^^^^^^^^^ +11 | if a + b < a { + | ^^^^^^^^^ | = note: `-D overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:14:5 | -14 | if a > a + b { - | ^^^^^^^^^ +14 | if a > a + b { + | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:17:5 | -17 | if a + b < b { - | ^^^^^^^^^ +17 | if a + b < b { + | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:20:5 | -20 | if b > a + b { - | ^^^^^^^^^ +20 | if b > a + b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:23:5 | -23 | if a - b > b { - | ^^^^^^^^^ +23 | if a - b > b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:26:5 | -26 | if b < a - b { - | ^^^^^^^^^ +26 | if b < a - b { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:29:5 | -29 | if a - b > a { - | ^^^^^^^^^ +29 | if a - b > a { + | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:32:5 | -32 | if a < a - b { - | ^^^^^^^^^ +32 | if a < a - b { + | ^^^^^^^^^ diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index d8ec72fda92..5acc3e9dde7 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,32 +1,32 @@ error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:15:2 | -15 | i = closure(); - | ^^^^^^^^^^^^^ +15 | i = closure(); + | ^^^^^^^^^^^^^ | = note: `-D redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:18:2 | -18 | i = closure(3); - | ^^^^^^^^^^^^^^ +18 | i = closure(3); + | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:7:10 | -7 | let a = (|| 42)(); - | ^^^^^^^^^ help: Try doing something like: : `42` +7 | let a = (|| 42)(); + | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:10:14 | -10 | let mut k = (|m| m+1)(i); - | ^^^^^^^^^^^^ +10 | let mut k = (|m| m+1)(i); + | ^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:12:6 | -12 | k = (|a,b| a*b)(1,5); - | ^^^^^^^^^^^^^^^^ +12 | k = (|a,b| a*b)(1,5); + | ^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 2703e74440138de340ba1a09ab80f442cedaf647 Mon Sep 17 00:00:00 2001 From: letheed Date: Mon, 11 Dec 2017 16:16:44 +0100 Subject: Disable cast_lossless on const items --- clippy_lints/src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 8d5dd3d19b4..903c1cd4c9b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -13,7 +13,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; -use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, +use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, type_size}; use utils::paths; @@ -608,6 +608,8 @@ fn should_strip_parens(op: &Expr, snip: &str) -> bool { } fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { + // Do not suggest using From in consts/statics until it is valid to do so (see #2267). + if in_constant(cx, expr.id) { return } // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. let opt = snippet_opt(cx, op.span); -- cgit 1.4.1-3-g733a5 From e7bd1625855b8b1fcd15fa16ff3904cabf71479b Mon Sep 17 00:00:00 2001 From: Cyril Plisko Date: Fri, 15 Dec 2017 00:33:23 +0200 Subject: Fix crates.io site name --- clippy_lints/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/README.md b/clippy_lints/README.md index b226cdea472..2fa5b0ae3e4 100644 --- a/clippy_lints/README.md +++ b/clippy_lints/README.md @@ -1,3 +1,3 @@ This crate contains Clippy lints. For the main crate, check -[*cargo.io*](https://crates.io/crates/clippy) or +[*crates.io*](https://crates.io/crates/clippy) or [GitHub](https://github.com/rust-lang-nursery/rust-clippy). -- cgit 1.4.1-3-g733a5 From 8ddcb81a15d6d186a71e7954d709ac94cbb7b718 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 15 Dec 2017 10:02:39 +0100 Subject: Rustup and lazy_static version mismatch fix fixes #2274 --- CHANGELOG.md | 3 +++ Cargo.toml | 6 +++--- clippy_lints/Cargo.toml | 4 ++-- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/utils/inspector.rs | 3 +++ clippy_lints/src/utils/mod.rs | 1 + src/main.rs | 2 ++ tests/compile-test.rs | 18 ------------------ tests/dogfood.rs | 17 +++++++++++++++++ tests/mut_mut_macro.rs | 31 +++++++++++++++++++++++++++++++ tests/run-pass/mut_mut_macro.rs | 31 ------------------------------- 11 files changed, 63 insertions(+), 54 deletions(-) create mode 100644 tests/dogfood.rs create mode 100644 tests/mut_mut_macro.rs delete mode 100644 tests/run-pass/mut_mut_macro.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6093bc0b5b0..90ea18f5f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.176 +* Rustup to *rustc 1.24.0-nightly (0077d128d 2017-12-14)* + ## 0.0.175 * Rustup to *rustc 1.24.0-nightly (bb42071f6 2017-12-01)* diff --git a/Cargo.toml b/Cargo.toml index 5101ae05d32..75e57b6889a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.175" +version = "0.0.176" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.175", path = "clippy_lints" } +clippy_lints = { version = "0.0.176", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" @@ -45,7 +45,7 @@ regex = "0.2" [dev-dependencies] compiletest_rs = "0.3" duct = "0.8.2" -lazy_static = "0.2" +lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.1", path = "mini-macro" } serde = "1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index cbf40240a7f..00416d24d64 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.175" +version = "0.0.176" # end automatic update authors = [ "Manish Goregaokar ", @@ -17,7 +17,7 @@ keywords = ["clippy", "lint", "plugin"] [dependencies] itertools = "0.6.0" -lazy_static = "0.2.8" +lazy_static = "1.0" matches = "0.1.2" quine-mc_cluskey = "0.2.2" regex-syntax = "0.4.0" diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 768e6cc3ec6..2a3a4e365a5 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -129,6 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemStatic(..) => "a static", hir::ItemStruct(..) => "a struct", hir::ItemTrait(..) => "a trait", + hir::ItemTraitAlias(..) => "a trait alias", hir::ItemGlobalAsm(..) => "an assembly blob", hir::ItemTy(..) => "a type alias", hir::ItemUnion(..) => "a union", diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ae1d9462b7c..fa6681ef078 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -403,6 +403,9 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("trait is not auto"); } }, + hir::ItemTraitAlias(..) => { + println!("trait alias"); + } hir::ItemAutoImpl(_, ref _trait_ref) => { println!("auto impl"); }, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 77c70922dba..0c1b10f05c8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -940,6 +940,7 @@ pub fn opt_def_id(def: Def) -> Option { Def::StructCtor(id, ..) | Def::Union(id) | Def::Trait(id) | + Def::TraitAlias(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | diff --git a/src/main.rs b/src/main.rs index c613f029b16..8affe549348 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,10 +141,12 @@ pub fn main() { let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); if let Some(first) = target.kind.get(0) { if target.kind.len() > 1 || first.ends_with("lib") { + println!("lib: {}", target.name); if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { std::process::exit(code); } } else if ["bin", "example", "test", "bench"].contains(&&**first) { + println!("{}: {}", first, target.name); if let Err(code) = process( vec![format!("--{}", first), target.name] .into_iter() diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 51ab6aee3a4..d532d4e5a59 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -72,21 +72,3 @@ fn compile_test() { run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); } - -#[test] -fn dogfood() { - prepare_env(); - let files = ["src/main.rs", "src/driver.rs", "src/lib.rs", "clippy_lints/src/lib.rs"]; - let mut config = config("dogfood", "ui"); - config.target_rustcflags = config.target_rustcflags.map(|flags| format!("{} -Dclippy -Dclippy_pedantic -Dclippy_internal", flags)); - - for file in &files { - let paths = test::TestPaths { - base: PathBuf::new(), - file: PathBuf::from(file), - relative_dir: PathBuf::new(), - }; - - compiletest::runtest::run(config.clone(), &paths); - } -} diff --git a/tests/dogfood.rs b/tests/dogfood.rs new file mode 100644 index 00000000000..1514383e6de --- /dev/null +++ b/tests/dogfood.rs @@ -0,0 +1,17 @@ +#[test] +fn dogfood() { + let root_dir = std::env::current_dir().unwrap(); + for d in &[".", "clippy_lints"] { + std::env::set_current_dir(root_dir.join(d)).unwrap(); + let output = std::process::Command::new("cargo") + .arg("run") + .arg("--bin").arg("cargo-clippy") + .arg("--manifest-path").arg(root_dir.join("Cargo.toml")) + .output().unwrap(); + println!("status: {}", output.status); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + + assert!(output.status.success()); + } +} diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs new file mode 100644 index 00000000000..adc308626b1 --- /dev/null +++ b/tests/mut_mut_macro.rs @@ -0,0 +1,31 @@ + + +#![deny(mut_mut, zero_ptr, cmp_nan)] +#![allow(dead_code)] + +#[macro_use] +extern crate lazy_static; + +use std::collections::HashMap; + +// ensure that we don't suggest `is_nan` and `is_null` inside constants +// FIXME: once const fn is stable, suggest these functions again in constants +const BAA: *const i32 = 0 as *const i32; +static mut BAR: *const i32 = BAA; +static mut FOO: *const i32 = 0 as *const i32; +static mut BUH: bool = 42.0 < std::f32::NAN; + +#[allow(unused_variables, unused_mut)] +fn main() { + lazy_static! { + static ref MUT_MAP : HashMap = { + let mut m = HashMap::new(); + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert_eq!(*MUT_COUNT, 1); + // FIXME: don't lint in array length, requires `check_body` + //let _ = [""; (42.0 < std::f32::NAN) as usize]; +} diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs deleted file mode 100644 index adc308626b1..00000000000 --- a/tests/run-pass/mut_mut_macro.rs +++ /dev/null @@ -1,31 +0,0 @@ - - -#![deny(mut_mut, zero_ptr, cmp_nan)] -#![allow(dead_code)] - -#[macro_use] -extern crate lazy_static; - -use std::collections::HashMap; - -// ensure that we don't suggest `is_nan` and `is_null` inside constants -// FIXME: once const fn is stable, suggest these functions again in constants -const BAA: *const i32 = 0 as *const i32; -static mut BAR: *const i32 = BAA; -static mut FOO: *const i32 = 0 as *const i32; -static mut BUH: bool = 42.0 < std::f32::NAN; - -#[allow(unused_variables, unused_mut)] -fn main() { - lazy_static! { - static ref MUT_MAP : HashMap = { - let mut m = HashMap::new(); - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert_eq!(*MUT_COUNT, 1); - // FIXME: don't lint in array length, requires `check_body` - //let _ = [""; (42.0 < std::f32::NAN) as usize]; -} -- cgit 1.4.1-3-g733a5 From 919601bc511608f1b66fe7c51d4b879e2abdec40 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Tue, 19 Dec 2017 23:22:16 +0100 Subject: Lint for matching option as ref --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/matches.rs | 75 +++++++++++++++++++++++++++++++++++++++++++-- tests/ui/matches.rs | 15 +++++++++ tests/ui/matches.stderr | 22 +++++++++++++ 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ceb6176bd7..9b598df4fa6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -499,6 +499,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, map_clone::MAP_CLONE, + matches::MATCH_AS_REF, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index dd3b2f00b7d..326ce83a84f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -11,8 +11,8 @@ use syntax::ast::LitKind; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; -use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_type, remove_blocks, snippet, - span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; +use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, remove_blocks, + snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use utils::sugg::Sugg; /// **What it does:** Checks for matches with a single arm where an `if let` @@ -145,6 +145,27 @@ declare_lint! { "a match with `Err(_)` arm and take drastic actions" } +/// **What it does:** Checks for match which is used to add a reference to an +/// `Option` value. +/// +/// **Why is this bad?** Using `as_ref()` instead is shorter. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x: Option<()> = None; +/// let r: Option<&()> = match x { +/// None => None, +/// Some(ref v) => Some(v), +/// }; +/// ``` +declare_lint! { + pub MATCH_AS_REF, + Warn, + "a match on an Option value instead of using `as_ref()`" +} + #[allow(missing_copy_implementations)] pub struct MatchPass; @@ -156,7 +177,8 @@ impl LintPass for MatchPass { MATCH_BOOL, SINGLE_MATCH_ELSE, MATCH_OVERLAPPING_ARM, - MATCH_WILD_ERR_ARM + MATCH_WILD_ERR_ARM, + MATCH_AS_REF ) } } @@ -171,6 +193,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); check_wild_err_arm(cx, ex, arms); + check_match_as_ref(cx, ex, arms, expr); } if let ExprMatch(ref ex, ref arms, source) = expr.node { check_match_ref_pats(cx, ex, arms, source, expr); @@ -411,6 +434,24 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match } } +fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { + if arms.len() == 2 && + arms[0].pats.len() == 1 && arms[0].guard.is_none() && + arms[1].pats.len() == 1 && arms[1].guard.is_none() { + if (is_ref_some_arm(&arms[0]) && is_none_arm(&arms[1])) || + (is_ref_some_arm(&arms[1]) && is_none_arm(&arms[0])) { + span_lint_and_sugg( + cx, + MATCH_AS_REF, + expr.span, + "use as_ref() instead", + "try this", + format!("{}.as_ref()", snippet(cx, ex.span, "_")) + ) + } + } +} + /// Get all arms that are unbounded `PatRange`s. fn all_ranges<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, @@ -524,6 +565,34 @@ fn is_unit_expr(expr: &Expr) -> bool { } } +// Checks if arm has the form `None => None` +fn is_none_arm(arm: &Arm) -> bool { + match arm.pats[0].node { + PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => true, + _ => false, + } +} + +// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) +fn is_ref_some_arm(arm: &Arm) -> bool { + if_chain! { + if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pats[0].node; + if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); + if let PatKind::Binding(rb, _, ref ident, _) = pats[0].node; + if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; + if let ExprCall(ref e, ref args) = remove_blocks(&arm.body).node; + if let ExprPath(ref some_path) = e.node; + if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; + if let ExprPath(ref qpath) = args[0].node; + if let &QPath::Resolved(_, ref path2) = qpath; + if path2.segments.len() == 1; + then { + return ident.node == path2.segments[0].name + } + } + false +} + fn has_only_ref_pats(arms: &[Arm]) -> bool { let mapped = arms.iter() .flat_map(|a| &a.pats) diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 8130436d485..72a36338aa2 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -315,5 +315,20 @@ fn match_wild_err_arm() { } } +fn match_as_ref() { + let owned : Option<()> = None; + let borrowed = match owned { + None => None, + Some(ref v) => Some(v), + }; + + let mut mut_owned : Option<()> = None; + let mut mut_borrowed = match mut_owned { + None => None, + Some(ref mut v) => Some(v), + }; + +} + fn main() { } diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 8c0ec49e626..3d7b8f78473 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -426,3 +426,25 @@ note: consider refactoring into `Ok(3) | Ok(_)` | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +error: use as_ref() instead + --> $DIR/matches.rs:320:20 + | +320 | let borrowed = match owned { + | ____________________^ +321 | | None => None, +322 | | Some(ref v) => Some(v), +323 | | }; + | |_____^ help: try this: `owned.as_ref()` + | + = note: `-D match-as-ref` implied by `-D warnings` + +error: use as_ref() instead + --> $DIR/matches.rs:326:28 + | +326 | let mut mut_borrowed = match mut_owned { + | ____________________________^ +327 | | None => None, +328 | | Some(ref mut v) => Some(v), +329 | | }; + | |_____^ help: try this: `mut_owned.as_ref()` + -- cgit 1.4.1-3-g733a5 From a6ccc6fe3d67f4802d58a9a76a4f1d308a8a96f3 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Wed, 20 Dec 2017 10:39:48 +0100 Subject: Also suggest as_mut for match_as_ref --- clippy_lints/src/matches.rs | 27 +++++++++++++++++---------- tests/ui/matches.rs | 8 ++++---- tests/ui/matches.stderr | 16 ++++++++-------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 326ce83a84f..2183c6e4fa6 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -148,7 +148,7 @@ declare_lint! { /// **What it does:** Checks for match which is used to add a reference to an /// `Option` value. /// -/// **Why is this bad?** Using `as_ref()` instead is shorter. +/// **Why is this bad?** Using `as_ref()` or `as_mut()` instead is shorter. /// /// **Known problems:** None. /// @@ -163,7 +163,7 @@ declare_lint! { declare_lint! { pub MATCH_AS_REF, Warn, - "a match on an Option value instead of using `as_ref()`" + "a match on an Option value instead of using `as_ref()` or `as_mut`" } #[allow(missing_copy_implementations)] @@ -438,15 +438,22 @@ fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() { - if (is_ref_some_arm(&arms[0]) && is_none_arm(&arms[1])) || - (is_ref_some_arm(&arms[1]) && is_none_arm(&arms[0])) { + let arm_ref: Option = if is_none_arm(&arms[0]) { + is_ref_some_arm(&arms[1]) + } else if is_none_arm(&arms[1]) { + is_ref_some_arm(&arms[0]) + } else { + None + }; + if let Some(rb) = arm_ref { + let suggestion = if rb == BindingAnnotation::Ref { "as_ref" } else { "as_mut" }; span_lint_and_sugg( cx, MATCH_AS_REF, expr.span, - "use as_ref() instead", + &format!("use {}() instead", suggestion), "try this", - format!("{}.as_ref()", snippet(cx, ex.span, "_")) + format!("{}.{}()", snippet(cx, ex.span, "_"), suggestion) ) } } @@ -574,7 +581,7 @@ fn is_none_arm(arm: &Arm) -> bool { } // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) -fn is_ref_some_arm(arm: &Arm) -> bool { +fn is_ref_some_arm(arm: &Arm) -> Option { if_chain! { if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pats[0].node; if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); @@ -585,12 +592,12 @@ fn is_ref_some_arm(arm: &Arm) -> bool { if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; if let ExprPath(ref qpath) = args[0].node; if let &QPath::Resolved(_, ref path2) = qpath; - if path2.segments.len() == 1; + if path2.segments.len() == 1 && ident.node == path2.segments[0].name; then { - return ident.node == path2.segments[0].name + return Some(rb) } } - false + None } fn has_only_ref_pats(arms: &[Arm]) -> bool { diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 72a36338aa2..67a901f65b2 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -316,14 +316,14 @@ fn match_wild_err_arm() { } fn match_as_ref() { - let owned : Option<()> = None; - let borrowed = match owned { + let owned: Option<()> = None; + let borrowed: Option<&()> = match owned { None => None, Some(ref v) => Some(v), }; - let mut mut_owned : Option<()> = None; - let mut mut_borrowed = match mut_owned { + let mut mut_owned: Option<()> = None; + let borrow_mut: Option<&mut ()> = match mut_owned { None => None, Some(ref mut v) => Some(v), }; diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 3d7b8f78473..62c77c778be 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -427,10 +427,10 @@ note: consider refactoring into `Ok(3) | Ok(_)` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:320:20 + --> $DIR/matches.rs:320:33 | -320 | let borrowed = match owned { - | ____________________^ +320 | let borrowed: Option<&()> = match owned { + | _________________________________^ 321 | | None => None, 322 | | Some(ref v) => Some(v), 323 | | }; @@ -438,13 +438,13 @@ error: use as_ref() instead | = note: `-D match-as-ref` implied by `-D warnings` -error: use as_ref() instead - --> $DIR/matches.rs:326:28 +error: use as_mut() instead + --> $DIR/matches.rs:326:39 | -326 | let mut mut_borrowed = match mut_owned { - | ____________________________^ +326 | let borrow_mut: Option<&mut ()> = match mut_owned { + | _______________________________________^ 327 | | None => None, 328 | | Some(ref mut v) => Some(v), 329 | | }; - | |_____^ help: try this: `mut_owned.as_ref()` + | |_____^ help: try this: `mut_owned.as_mut()` -- cgit 1.4.1-3-g733a5 From 775372db90326fdcd779203e34ebdd31382db8f4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 20 Dec 2017 08:16:43 -0800 Subject: Move mini-macro to proc macro We can add a bang-style proc macro again once it stabilizes (we can use the proc macro hack, but it's unnecessary for now) --- Cargo.toml | 2 +- mini-macro/Cargo.toml | 4 ++-- mini-macro/src/lib.rs | 46 ++++++++------------------------------ tests/run-pass/procedural_macro.rs | 12 ++++++---- 4 files changed, 20 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 75e57b6889a..df59225b83f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ compiletest_rs = "0.3" duct = "0.8.2" lazy_static = "1.0" serde_derive = "1.0" -clippy-mini-macro-test = { version = "0.1", path = "mini-macro" } +clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = "1.0" [features] diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml index 1b7dc04f7eb..ac3272030ba 100644 --- a/mini-macro/Cargo.toml +++ b/mini-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy-mini-macro-test" -version = "0.1.0" +version = "0.2.0" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -14,6 +14,6 @@ repository = "https://github.com/rust-lang-nursery/rust-clippy" [lib] name = "clippy_mini_macro_test" -plugin = true +proc-macro = true [dependencies] diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 67337afd3e7..3caf85103b5 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,39 +1,11 @@ -#![feature(plugin_registrar, rustc_private, quote)] +#![feature(proc_macro)] +extern crate proc_macro; -extern crate rustc_plugin; -extern crate syntax; +use proc_macro::{TokenStream, quote}; -use rustc_plugin::Registry; -use syntax::ast::MetaItem; -use syntax::codemap::Span; -use syntax::ext::base::{Annotatable, ExtCtxt, MacEager, MacResult, SyntaxExtension}; -use syntax::ext::build::AstBuilder; // trait for expr_usize -use syntax::symbol::Symbol; -use syntax::tokenstream::TokenTree; - -fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box { - let e = cx.expr_usize(sp, 42); - let e = cx.expr_mut_addr_of(sp, e); - MacEager::expr(cx.expr_mut_addr_of(sp, e)) -} - -fn expand_attr_macro(cx: &mut ExtCtxt, _: Span, _: &MetaItem, annotated: Annotatable) -> Vec { - vec![ - Annotatable::Item( - quote_item!( - cx, - #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } - ).unwrap() - ), - annotated, - ] -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_macro("mini_macro", expand_macro); - reg.register_syntax_extension( - Symbol::intern("mini_macro_attr"), - SyntaxExtension::MultiModifier(Box::new(expand_attr_macro)), - ); -} +#[proc_macro_derive(ClippyMiniMacroTest)] +pub fn mini_macro(_: TokenStream) -> TokenStream { + quote!( + #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } + ) +} \ No newline at end of file diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index f52c778a49d..2b7ff123ea6 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -1,8 +1,12 @@ -#![feature(plugin)] -#![plugin(clippy_mini_macro_test)] +#[macro_use] +extern crate clippy_mini_macro_test; #[deny(warnings)] -#[mini_macro_attr] fn main() { - let _ = mini_macro!(); + let x = Foo; + println!("{:?}", x); } + + +#[derive(ClippyMiniMacroTest, Debug)] +struct Foo; \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 1d523ce8f79f6053c89051f661d09d53bd038b19 Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Thu, 21 Dec 2017 15:21:28 -0800 Subject: Add “, add these lines” as well as removing the extra space between the attributes to make it more clear that both should be included. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 82f1908bb23..35095ed05aa 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,10 @@ clippy = {version = "*", optional = true} default = [] ``` -And, in your `main.rs` or `lib.rs`: +And, in your `main.rs` or `lib.rs`, add these lines: ```rust #![cfg_attr(feature="clippy", feature(plugin))] - #![cfg_attr(feature="clippy", plugin(clippy))] ``` -- cgit 1.4.1-3-g733a5 From 203038cbe5defbe435881dbb3553413c95b1573c Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Thu, 21 Dec 2017 15:24:18 -0800 Subject: Add +nightly to command for running cargo build. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 35095ed05aa..3195a2851df 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ And, in your `main.rs` or `lib.rs`, add these lines: #![cfg_attr(feature="clippy", plugin(clippy))] ``` -Then build by enabling the feature: `cargo build --features "clippy"` +Then build by enabling the feature: `cargo +nightly build --features "clippy"`. Instead of adding the `cfg_attr` attributes you can also run clippy on demand: `cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` -- cgit 1.4.1-3-g733a5 From 7e099903be62a4028e481547e19bd926099641e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 21 Dec 2017 20:42:47 -0800 Subject: Update to handle GenericParam introduced in https://github.com/rust-lang/rust/pull/45930 --- clippy_lints/src/lifetimes.rs | 30 +++++++++++++++++------------- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/misc_early.rs | 20 +++++++++++--------- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/types.rs | 2 +- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 280e504d88e..684e09e93c4 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -2,7 +2,7 @@ use reexport::*; use rustc::lint::*; use rustc::hir::def::Def; use rustc::hir::*; -use rustc::hir::intravisit::{walk_fn_decl, walk_generics, walk_ty, walk_ty_param_bound, NestedVisitorMap, Visitor}; +use rustc::hir::intravisit::*; use std::collections::{HashMap, HashSet}; use syntax::codemap::Span; use utils::{in_external_macro, last_path_segment, span_lint}; @@ -101,7 +101,7 @@ fn check_fn_inner<'a, 'tcx>( } let mut bounds_lts = Vec::new(); - for typ in &generics.ty_params { + for typ in generics.ty_params() { for bound in &typ.bounds { if let TraitTyParamBound(ref trait_ref, _) = *bound { let params = &trait_ref @@ -122,7 +122,7 @@ fn check_fn_inner<'a, 'tcx>( } } } - if could_use_elision(cx, decl, body, &generics.lifetimes, bounds_lts) { + if could_use_elision(cx, decl, body, &generics.params, bounds_lts) { span_lint( cx, NEEDLESS_LIFETIMES, @@ -137,7 +137,7 @@ fn could_use_elision<'a, 'tcx: 'a>( cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, body: Option, - named_lts: &'tcx [LifetimeDef], + named_generics: &'tcx [GenericParam], bounds_lts: Vec<&'tcx Lifetime>, ) -> bool { // There are two scenarios where elision works: @@ -147,7 +147,7 @@ fn could_use_elision<'a, 'tcx: 'a>( // level of the current item. // check named LTs - let allowed_lts = allowed_lts_from(named_lts); + let allowed_lts = allowed_lts_from(named_generics); // these will collect all the lifetimes for references in arg/return types let mut input_visitor = RefVisitor::new(cx); @@ -222,11 +222,13 @@ fn could_use_elision<'a, 'tcx: 'a>( } } -fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet { +fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { let mut allowed_lts = HashSet::new(); - for lt in named_lts { - if lt.bounds.is_empty() { - allowed_lts.insert(RefLt::Named(lt.lifetime.name.name())); + for par in named_generics.iter() { + if let GenericParam::Lifetime(ref lt) = *par { + if lt.bounds.is_empty() { + allowed_lts.insert(RefLt::Named(lt.lifetime.name.name())); + } } } allowed_lts.insert(RefLt::Unnamed); @@ -370,7 +372,7 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & return true; } // if the bounds define new lifetimes, they are fine to occur - let allowed_lts = allowed_lts_from(&pred.bound_lifetimes); + let allowed_lts = allowed_lts_from(&pred.bound_generic_params); // now walk the bounds for bound in pred.bounds.iter() { walk_ty_param_bound(&mut visitor, bound); @@ -408,12 +410,15 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { self.map.remove(&lifetime.name.name()); } - fn visit_lifetime_def(&mut self, _: &'tcx LifetimeDef) { + fn visit_generic_param(&mut self, param: &'tcx GenericParam) { // don't actually visit `<'a>` or `<'a: 'b>` // we've already visited the `'a` declarations and // don't want to spuriously remove them // `'b` in `'a: 'b` is useless unless used elsewhere in // a non-lifetime bound + if param.is_type_param() { + walk_generic_param(self, param) + } } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None @@ -422,8 +427,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) { let hs = generics - .lifetimes - .iter() + .lifetimes() .map(|lt| (lt.lifetime.name.name(), lt.lifetime.span)) .collect(); let mut checker = LifetimeChecker { map: hs }; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4a52df92b27..64335f81a63 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1849,7 +1849,7 @@ impl SelfKind { fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { single_segment_ty(ty).map_or(false, |seg| { - generics.ty_params.iter().any(|param| { + generics.ty_params().any(|param| { param.name == seg.name && param.bounds.iter().any(|bound| { if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 160ccd8e9b3..4e45525ed09 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -188,15 +188,17 @@ impl LintPass for MiscEarly { impl EarlyLintPass for MiscEarly { fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) { - for ty in &gen.ty_params { - let name = ty.ident.name.as_str(); - if constants::BUILTIN_TYPES.contains(&&*name) { - span_lint( - cx, - BUILTIN_TYPE_SHADOW, - ty.span, - &format!("This generic shadows the built-in type `{}`", name), - ); + for param in &gen.params { + if let GenericParam::Type(ref ty) = *param { + let name = ty.ident.name.as_str(); + if constants::BUILTIN_TYPES.contains(&&*name) { + span_lint( + cx, + BUILTIN_TYPE_SHADOW, + ty.span, + &format!("This generic shadows the built-in type `{}`", name), + ); + } } } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index b281fd3060e..5f237095115 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -103,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } - if !impl_item.generics.ty_params.is_empty() { + if impl_item.generics.params.iter().any(|gen| gen.is_type_param()) { // when the result of `new()` depends on a type parameter we should not require // an // impl of `Default` diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 903c1cd4c9b..c146d306a5a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -957,7 +957,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyTraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds .iter() - .any(|bound| !bound.bound_lifetimes.is_empty()); + .any(|bound| bound.bound_generic_params.iter().any(|gen| gen.is_lifetime_param())); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) -- cgit 1.4.1-3-g733a5 From bebc192df413e4c975c26c04200365dff251c29e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 21 Dec 2017 20:45:01 -0800 Subject: Universal impl traits get removed earlier now https://github.com/rust-lang/rust/pull/46754 --- clippy_lints/src/lifetimes.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 684e09e93c4..567b06a8ac1 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -334,11 +334,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { } } } - TyImplTraitUniversal(_, ref param_bounds) => for bound in param_bounds { - if let RegionTyParamBound(_) = *bound { - self.record(&None); - } - }, TyTraitObject(ref bounds, ref lt) => { if !lt.is_elided() { self.abort = true; -- cgit 1.4.1-3-g733a5 From fae8a763f84324fb7c65d6d7c83973912573168d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 21 Dec 2017 20:56:20 -0800 Subject: Bump to 0.0.177 --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ea18f5f6f..ddfd801c929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.177 +* Rustup to *rustc 1.24.0-nightly (250b49205 2017-12-21)* +* New lint: [`match_as_ref`] + ## 0.0.176 * Rustup to *rustc 1.24.0-nightly (0077d128d 2017-12-14)* @@ -595,6 +599,7 @@ All notable changes to this project will be documented in this file. [`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone [`map_entry`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_entry +[`match_as_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_bool [`match_overlapping_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_overlapping_arm [`match_ref_pats`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_ref_pats diff --git a/Cargo.toml b/Cargo.toml index df59225b83f..510f53becdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.176" +version = "0.0.177" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.176", path = "clippy_lints" } +clippy_lints = { version = "0.0.177", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 00416d24d64..de4a1035cb1 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.176" +version = "0.0.177" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 50eb48e42b0be3dc124ad04eb14adfafabcaf155 Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Fri, 22 Dec 2017 10:37:44 -0800 Subject: Create failing test for equal inside macro --- tests/ui/eq_op.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 89d85d1b3e9..70c932a6cdf 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -87,4 +87,20 @@ fn main() { let x = Y(1); let y = Y(2); let z = x & &y; + + check_ignore_macro(); +} + +macro_rules! check_if_named_foo { + ($expression:expr) => ( + if stringify!($expression) == "foo" { + println!("foo!"); + } else { + println!("not foo."); + } + ) +} + +fn check_ignore_macro() { + check_if_named_foo!(foo); } -- cgit 1.4.1-3-g733a5 From 1f36aa519ee7ede53b8d788257ecb25174539942 Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Fri, 22 Dec 2017 10:51:41 -0800 Subject: Check that eq_op lint doesn’t mark macro use of functions as errors since macros, fix #2265 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/eq_op.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index dbe0d68ad69..9bea91848dc 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; +use utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, @@ -53,7 +53,7 @@ impl LintPass for EqOp { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { + if !in_macro(e.span) && is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { span_lint( cx, EQ_OP, -- cgit 1.4.1-3-g733a5 From b9abe028c9d1df5df5871f431319bd60c34e7253 Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Fri, 22 Dec 2017 10:54:52 -0800 Subject: Move in_macro check to end of expression since usual case is not inside macro --- clippy_lints/src/eq_op.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 9bea91848dc..d62b937f52f 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -53,7 +53,7 @@ impl LintPass for EqOp { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if !in_macro(e.span) && is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { + if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) && !in_macro(e.span) { span_lint( cx, EQ_OP, -- cgit 1.4.1-3-g733a5 From 0f4c40b229710fe087bef70ab79d3ede552a6bb7 Mon Sep 17 00:00:00 2001 From: Darren Tsung Date: Sat, 23 Dec 2017 10:15:11 -0800 Subject: Start regression tests for types.rs --- tests/ui/types.rs | 10 ++++++++++ tests/ui/types.stderr | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/types.rs create mode 100644 tests/ui/types.stderr diff --git a/tests/ui/types.rs b/tests/ui/types.rs new file mode 100644 index 00000000000..10d1c490ee6 --- /dev/null +++ b/tests/ui/types.rs @@ -0,0 +1,10 @@ +// should not warn on lossy casting in constant types +// because not supported yet +const C : i32 = 42; +const C_I64 : i64 = C as i64; + +fn main() { + // should suggest i64::from(c) + let c : i32 = 42; + let c_i64 : i64 = c as i64; +} diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr new file mode 100644 index 00000000000..a2f4ede5ca2 --- /dev/null +++ b/tests/ui/types.stderr @@ -0,0 +1,8 @@ +error: casting i32 to i64 may become silently lossy if types change + --> $DIR/types.rs:9:23 + | +9 | let c_i64 : i64 = c as i64; + | ^^^^^^^^ help: try: `i64::from(c)` + | + = note: `-D cast-lossless` implied by `-D warnings` + -- cgit 1.4.1-3-g733a5 From 6737bae9b117f875907f037df90c66318efd496b Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 26 Dec 2017 07:25:13 +0200 Subject: Implemented option_option lint --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/types.rs | 77 ++++++++++++++++++++++++++++---------- tests/ui/needless_pass_by_value.rs | 2 +- tests/ui/option_option.rs | 46 +++++++++++++++++++++++ tests/ui/option_option.stderr | 57 ++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 tests/ui/option_option.rs create mode 100644 tests/ui/option_option.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9b598df4fa6..1f81dd0b9ff 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -599,6 +599,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::LINKEDLIST, + types::OPTION_OPTION, types::TYPE_COMPLEXITY, types::UNIT_CMP, types::UNNECESSARY_CAST, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c146d306a5a..2297ccc3f02 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -42,6 +42,26 @@ declare_lint! { "usage of `Box>`, vector elements are already on the heap" } +/// **What it does:** Checks for use of `Option>` in function signatures and type +/// definitions +/// +/// **Why is this bad?** `Option<_>` represents an optional value. `Option>` +/// represents an optional optional value which is logically the same thing as an optional +/// value but has an unneeded extra level of wrapping. +/// +/// **Known problems:** None. +/// +/// **Example** +/// ```rust +/// fn x() -> Option> { +/// None +/// } +declare_lint! { + pub OPTION_OPTION, + Warn, + "usage of `Option>`" +} + /// **What it does:** Checks for usage of any `LinkedList`, suggesting to use a /// `Vec` or a `VecDeque` (formerly called `RingBuf`). /// @@ -97,7 +117,7 @@ declare_lint! { impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, LINKEDLIST, BORROWED_BOX) + lint_array!(BOX_VEC, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) } } @@ -142,6 +162,23 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { } } +/// Check if `qpath` has last segment with type parameter matching `path` +fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool { + let last = last_path_segment(qpath); + if_chain! { + if let Some(ref params) = last.parameters; + if !params.parenthesized; + if let Some(vec) = params.types.get(0); + if let TyPath(ref qpath) = vec.node; + if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))); + if match_def_path(cx.tcx, did, path); + then { + return true; + } + } + false +} + /// Recursively check for `TypePass` lints in the given type. Stop at the first /// lint found. /// @@ -157,24 +194,26 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { if Some(def_id) == cx.tcx.lang_items().owned_box() { - let last = last_path_segment(qpath); - if_chain! { - if let Some(ref params) = last.parameters; - if !params.parenthesized; - if let Some(vec) = params.types.get(0); - if let TyPath(ref qpath) = vec.node; - if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))); - if match_def_path(cx.tcx, did, &paths::VEC); - then { - span_help_and_lint( - cx, - BOX_VEC, - ast_ty.span, - "you seem to be trying to use `Box>`. Consider using just `Vec`", - "`Vec` is already on the heap, `Box>` makes an extra allocation.", - ); - return; // don't recurse into the type - } + if match_type_parameter(cx, qpath, &paths::VEC) { + span_help_and_lint( + cx, + BOX_VEC, + ast_ty.span, + "you seem to be trying to use `Box>`. Consider using just `Vec`", + "`Vec` is already on the heap, `Box>` makes an extra allocation.", + ); + return; // don't recurse into the type + } + } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { + if match_type_parameter(cx, qpath, &paths::OPTION) { + span_help_and_lint( + cx, + OPTION_OPTION, + ast_ty.span, + "consider using `Option` instead of `Option>`", + "`Option<_>` is easier to use than `Option`", + ); + return; // don't recurse into the type } } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) { span_help_and_lint( diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 84c7e832951..081ff0dc596 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -2,7 +2,7 @@ #![warn(needless_pass_by_value)] -#![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names)] +#![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names, option_option)] use std::borrow::Borrow; use std::convert::AsRef; diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs new file mode 100644 index 00000000000..88232c3b23f --- /dev/null +++ b/tests/ui/option_option.rs @@ -0,0 +1,46 @@ +fn input(_: Option>) { +} + +fn output() -> Option> { + None +} + +fn output_nested() -> Vec>> { + vec![None] +} + +// The lint only generates one warning for this +fn output_nested_nested() -> Option>> { + None +} + +struct Struct { + x: Option>, +} + +enum Enum { + Tuple(Option>), + Struct{x: Option>}, +} + +// The lint allows this +type OptionOption = Option>; + +// The lint allows this +fn output_type_alias() -> OptionOption { + None +} + +fn main() { + input(None); + output(); + output_nested(); + + // The lint allows this + let local: Option> = None; + + // The lint allows this + let expr = Some(Some(true)); +} + + diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr new file mode 100644 index 00000000000..514538be167 --- /dev/null +++ b/tests/ui/option_option.stderr @@ -0,0 +1,57 @@ +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:1:13 + | +1 | fn input(_: Option>) { + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D option-option` implied by `-D warnings` + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:4:16 + | +4 | fn output() -> Option> { + | ^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:8:27 + | +8 | fn output_nested() -> Vec>> { + | ^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:13:30 + | +13 | fn output_nested_nested() -> Option>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:18:8 + | +18 | x: Option>, + | ^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:22:11 + | +22 | Tuple(Option>), + | ^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + +error: consider using `Option` instead of `Option>` + --> $DIR/option_option.rs:23:15 + | +23 | Struct{x: Option>}, + | ^^^^^^^^^^^^^^^^^^ + | + = help: `Option<_>` is easier to use than `Option` + -- cgit 1.4.1-3-g733a5 From 8abf9647cef4c39c890062b20e2ceee8132a0aed Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 27 Dec 2017 11:06:40 -0500 Subject: Rearrange README.md. This suggests `cargo clippy` first, which is probably the best method at this point. It also describes how to enable clippy only when testing. --- README.md | 54 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3195a2851df..4be313c392e 100644 --- a/README.md +++ b/README.md @@ -26,18 +26,35 @@ as an included feature during build. All of these options are detailed below. As a general rule clippy will only work with the *latest* Rust nightly for now. -### Optional dependency +### As a cargo subcommand (`cargo clippy`) + +One way to use clippy is by installing clippy through cargo as a cargo +subcommand. + +```terminal +cargo install clippy +``` + +Now you can run clippy by invoking `cargo clippy`, or +`cargo +nightly clippy` directly from a directory that is usually +compiled with stable. + +In case you are not using rustup, you need to set the environment flag +`SYSROOT` during installation so clippy knows where to find `librustc` and +similar crates. + +```terminal +SYSROOT=/path/to/rustc/sysroot cargo install clippy +``` -If you want to make clippy an optional dependency, you can do the following: +### Optional dependency -In your `Cargo.toml`: +In some cases you might want to include clippy in your project directly, as an +optional dependency. To do this, just modify `Cargo.toml`: ```toml [dependencies] -clippy = {version = "*", optional = true} - -[features] -default = [] +clippy = { version = "*", optional = true } ``` And, in your `main.rs` or `lib.rs`, add these lines: @@ -54,25 +71,18 @@ Instead of adding the `cfg_attr` attributes you can also run clippy on demand: (the `-Z no trans`, while not necessary, will stop the compilation process after typechecking (and lints) have completed, which can significantly reduce the runtime). -### As a cargo subcommand (`cargo clippy`) +Alternatively, to only run clippy when testing: -An alternate way to use clippy is by installing clippy through cargo as a cargo -subcommand. - -```terminal -cargo install clippy +```toml +[dev-dependencies]` +clippy = { version = "*" } ``` -Now you can run clippy by invoking `cargo clippy`, or -`rustup run nightly cargo clippy` directly from a directory that is usually -compiled with stable. +and add to `main.rs` or `lib.rs`: -In case you are not using rustup, you need to set the environment flag -`SYSROOT` during installation so clippy knows where to find `librustc` and -similar crates. - -```terminal -SYSROOT=/path/to/rustc/sysroot cargo install clippy +``` +#![cfg_attr(test, feature(plugin))] +#![cfg_attr(test, plugin(clippy))] ``` ### Running clippy from the command line without installing -- cgit 1.4.1-3-g733a5 From a7f423b114420b6ad7265faff2c90441f380de4f Mon Sep 17 00:00:00 2001 From: zmt00 Date: Mon, 1 Jan 2018 13:55:40 -0800 Subject: Fix typos in README, documentation --- README.md | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4be313c392e..4b2af3f782a 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ typechecking (and lints) have completed, which can significantly reduce the runt Alternatively, to only run clippy when testing: ```toml -[dev-dependencies]` +[dev-dependencies] clippy = { version = "*" } ``` diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index c9a2e6b0935..f0e5db6d404 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -38,7 +38,7 @@ use utils::{in_macro, snippet, span_lint_and_then}; /// let mut v = Vec::::new(); /// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); /// ``` -/// This clojure takes a reference on something that has been matched as a +/// This closure takes a reference on something that has been matched as a /// reference and /// de-referenced. /// As such, it could just be |a| a.is_empty() -- cgit 1.4.1-3-g733a5 From a5d0569a20a5def753e2c423e33b3980e4f44b8d Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 2 Jan 2018 13:51:35 +0100 Subject: Add "NaNs" and "GitLab" to `doc-valid-idents` --- clippy_lints/src/utils/conf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 31ed71695ce..b13ceb8692a 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -152,10 +152,10 @@ define_Conf! { "DirectX", "ECMAScript", "GPLv2", "GPLv3", - "GitHub", + "GitHub", "GitLab", "IPv4", "IPv6", "JavaScript", - "NaN", + "NaN", "NaNs", "OAuth", "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", "TrueType", -- cgit 1.4.1-3-g733a5 From 82d91c5fcb01c35c0337d152cfac9c85957e2eb3 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 4 Jan 2018 12:37:47 +0100 Subject: Add auto-fixable `println!()` suggestion Fixes #2319 --- clippy_lints/src/print.rs | 12 +++++++++--- tests/ui/println_empty_string.stderr | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 61ed8d5ac25..451b27033ea 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use syntax::ast::LitKind; use syntax::symbol::InternedString; use syntax_pos::Span; -use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; +use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; use utils::{opt_def_id, paths}; /// **What it does:** This lint warns when you using `println!("")` to @@ -182,8 +182,14 @@ fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: Inter if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); if snippet.contains("\"\""); then { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `println!(\"\")`, consider using `println!()` instead"); + span_lint_and_sugg( + cx, + PRINT_WITH_NEWLINE, + span, + "using `println!(\"\")`", + "replace it with", + "println!()".to_string(), + ); } } } diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 8beca8b88cb..2036d7d976b 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,8 +1,8 @@ -error: using `println!("")`, consider using `println!()` instead +error: using `println!("")` --> $DIR/println_empty_string.rs:3:5 | 3 | println!(""); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: replace it with: `println!()` | = note: `-D print-with-newline` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 6802232e2872cad9974e5ee98fbe9a52a3ee1cb9 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 4 Jan 2018 20:39:17 +0200 Subject: Fix build Trying the work-around suggested at https://github.com/travis-ci/travis-ci/issues/6307 to fix the Travis CI MacOS build. --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8fe1be2ddfa..40a1287d1eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,9 @@ env: - secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI= - RUST_BACKTRACE=1 +before_install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm get stable; fi + install: - . $HOME/.nvm/nvm.sh - nvm install stable -- cgit 1.4.1-3-g733a5 From 5068a1252d07b5338dc19dc7f4839cf02810bccd Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 4 Jan 2018 21:17:04 +0200 Subject: Fix build Adding gpg key import. --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 40a1287d1eb..e4b00e42fd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,11 @@ env: - RUST_BACKTRACE=1 before_install: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm get stable; fi + - | + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + command curl -sSL https://rvm.io/mpapis.asc | gpg --import -; + rvm get stable + fi install: - . $HOME/.nvm/nvm.sh -- cgit 1.4.1-3-g733a5 From 80f86633a96e7baef289b3d7fe03549677465cfb Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 6 Jan 2018 08:14:52 +0200 Subject: Make style consistent --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4b00e42fd1..22ac973cf6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,8 @@ env: before_install: - | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - command curl -sSL https://rvm.io/mpapis.asc | gpg --import -; + if [ "$TRAVIS_OS_NAME" == "osx" ]; then + command curl -sSL https://rvm.io/mpapis.asc | gpg --import - rvm get stable fi -- cgit 1.4.1-3-g733a5 From 1afbe3203c97bf4f5d8aa7cb564c2e674b2eb36e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 6 Jan 2018 08:31:39 +0200 Subject: Fix build Added comment --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 22ac973cf6f..92d48101254 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,8 @@ env: before_install: - | + # work-around for issue https://github.com/travis-ci/travis-ci/issues/6307 + # might not be necessary in the future if [ "$TRAVIS_OS_NAME" == "osx" ]; then command curl -sSL https://rvm.io/mpapis.asc | gpg --import - rvm get stable -- cgit 1.4.1-3-g733a5 From fded77d85e948bb7896f8c73e0a89b7a0199869c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 6 Jan 2018 00:23:28 +0100 Subject: Split up casting UI tests Part of #2038 --- tests/ui/cast.rs | 49 ------ tests/ui/cast.stderr | 312 ++-------------------------------- tests/ui/cast_lossless_float.rs | 15 ++ tests/ui/cast_lossless_float.stderr | 62 +++++++ tests/ui/cast_lossless_integer.rs | 24 +++ tests/ui/cast_lossless_integer.stderr | 110 ++++++++++++ tests/ui/cast_size.rs | 23 +++ tests/ui/cast_size.stderr | 122 +++++++++++++ 8 files changed, 371 insertions(+), 346 deletions(-) create mode 100644 tests/ui/cast_lossless_float.rs create mode 100644 tests/ui/cast_lossless_float.stderr create mode 100644 tests/ui/cast_lossless_integer.rs create mode 100644 tests/ui/cast_lossless_integer.stderr create mode 100644 tests/ui/cast_size.rs create mode 100644 tests/ui/cast_size.stderr diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 1ad4630989d..833e5a55780 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -25,36 +25,6 @@ fn main() { 1u32 as i32; 1u64 as i64; 1usize as isize; - // Test cast_lossless with casts to integer types - 1i8 as i16; - 1i8 as i32; - 1i8 as i64; - 1u8 as i16; - 1u8 as i32; - 1u8 as i64; - 1u8 as u16; - 1u8 as u32; - 1u8 as u64; - 1i16 as i32; - 1i16 as i64; - 1u16 as i32; - 1u16 as i64; - 1u16 as u32; - 1u16 as u64; - 1i32 as i64; - 1u32 as i64; - 1u32 as u64; - // Test cast_lossless with casts to floating-point types - 1i8 as f32; - 1i8 as f64; - 1u8 as f32; - 1u8 as f64; - 1i16 as f32; - 1i16 as f64; - 1u16 as f32; - 1u16 as f64; - 1i32 as f64; - 1u32 as f64; // Test cast_lossless with casts from floating-point types 1.0f32 as f64; // Test cast_lossless with an expression wrapped in parens @@ -63,25 +33,6 @@ fn main() { 1i32 as u32; 1isize as usize; // Extra checks for *size - // Casting from *size - 1isize as i8; - 1isize as f64; - 1usize as f64; - 1isize as f32; - 1usize as f32; - 1isize as i32; - 1isize as u32; - 1usize as u32; - 1usize as i32; - // Casting to *size - 1i64 as isize; - 1i64 as usize; - 1u64 as isize; - 1u64 as usize; - 1u32 as isize; - 1u32 as usize; // Should not trigger any lint - 1i32 as isize; // Neither should this - 1i32 as usize; // Test cast_unnecessary 1i32 as i32; 1f32 as f32; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 5e7ed6fae99..ac409a813cc 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -132,331 +132,49 @@ error: casting usize to isize may wrap around the value 27 | 1usize as isize; | ^^^^^^^^^^^^^^^ -error: casting i8 to i16 may become silently lossy if types change +error: casting f32 to f64 may become silently lossy if types change --> $DIR/cast.rs:29:5 | -29 | 1i8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1i8)` +29 | 1.0f32 as f64; + | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` | = note: `-D cast-lossless` implied by `-D warnings` -error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast.rs:30:5 - | -30 | 1i8 as i32; - | ^^^^^^^^^^ help: try: `i32::from(1i8)` - -error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast.rs:31:5 - | -31 | 1i8 as i64; - | ^^^^^^^^^^ help: try: `i64::from(1i8)` - -error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast.rs:32:5 - | -32 | 1u8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1u8)` - -error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast.rs:33:5 - | -33 | 1u8 as i32; - | ^^^^^^^^^^ help: try: `i32::from(1u8)` - -error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast.rs:34:5 - | -34 | 1u8 as i64; - | ^^^^^^^^^^ help: try: `i64::from(1u8)` - error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:35:5 - | -35 | 1u8 as u16; - | ^^^^^^^^^^ help: try: `u16::from(1u8)` - -error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast.rs:36:5 - | -36 | 1u8 as u32; - | ^^^^^^^^^^ help: try: `u32::from(1u8)` - -error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast.rs:37:5 - | -37 | 1u8 as u64; - | ^^^^^^^^^^ help: try: `u64::from(1u8)` - -error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast.rs:38:5 - | -38 | 1i16 as i32; - | ^^^^^^^^^^^ help: try: `i32::from(1i16)` - -error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast.rs:39:5 - | -39 | 1i16 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1i16)` - -error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast.rs:40:5 - | -40 | 1u16 as i32; - | ^^^^^^^^^^^ help: try: `i32::from(1u16)` - -error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast.rs:41:5 - | -41 | 1u16 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1u16)` - -error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast.rs:42:5 - | -42 | 1u16 as u32; - | ^^^^^^^^^^^ help: try: `u32::from(1u16)` - -error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast.rs:43:5 - | -43 | 1u16 as u64; - | ^^^^^^^^^^^ help: try: `u64::from(1u16)` - -error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast.rs:44:5 - | -44 | 1i32 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1i32)` - -error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast.rs:45:5 - | -45 | 1u32 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1u32)` - -error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast.rs:46:5 - | -46 | 1u32 as u64; - | ^^^^^^^^^^^ help: try: `u64::from(1u32)` - -error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast.rs:48:5 - | -48 | 1i8 as f32; - | ^^^^^^^^^^ help: try: `f32::from(1i8)` - -error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast.rs:49:5 - | -49 | 1i8 as f64; - | ^^^^^^^^^^ help: try: `f64::from(1i8)` - -error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast.rs:50:5 - | -50 | 1u8 as f32; - | ^^^^^^^^^^ help: try: `f32::from(1u8)` - -error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast.rs:51:5 - | -51 | 1u8 as f64; - | ^^^^^^^^^^ help: try: `f64::from(1u8)` - -error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast.rs:52:5 - | -52 | 1i16 as f32; - | ^^^^^^^^^^^ help: try: `f32::from(1i16)` - -error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast.rs:53:5 - | -53 | 1i16 as f64; - | ^^^^^^^^^^^ help: try: `f64::from(1i16)` - -error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast.rs:54:5 - | -54 | 1u16 as f32; - | ^^^^^^^^^^^ help: try: `f32::from(1u16)` - -error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast.rs:55:5 - | -55 | 1u16 as f64; - | ^^^^^^^^^^^ help: try: `f64::from(1u16)` - -error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:56:5 - | -56 | 1i32 as f64; - | ^^^^^^^^^^^ help: try: `f64::from(1i32)` - -error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:57:5 - | -57 | 1u32 as f64; - | ^^^^^^^^^^^ help: try: `f64::from(1u32)` - -error: casting f32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:59:5 - | -59 | 1.0f32 as f64; - | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` - -error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:61:5 + --> $DIR/cast.rs:31:5 | -61 | (1u8 + 1u8) as u16; +31 | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:63:5 + --> $DIR/cast.rs:33:5 | -63 | 1i32 as u32; +33 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:64:5 + --> $DIR/cast.rs:34:5 | -64 | 1isize as usize; +34 | 1isize as usize; | ^^^^^^^^^^^^^^^ -error: casting isize to i8 may truncate the value - --> $DIR/cast.rs:67:5 - | -67 | 1isize as i8; - | ^^^^^^^^^^^^ - -error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:68:5 - | -68 | 1isize as f64; - | ^^^^^^^^^^^^^ - -error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:69:5 - | -69 | 1usize as f64; - | ^^^^^^^^^^^^^ - -error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:70:5 - | -70 | 1isize as f32; - | ^^^^^^^^^^^^^ - -error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:71:5 - | -71 | 1usize as f32; - | ^^^^^^^^^^^^^ - -error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:72:5 - | -72 | 1isize as i32; - | ^^^^^^^^^^^^^ - -error: casting isize to u32 may lose the sign of the value - --> $DIR/cast.rs:73:5 - | -73 | 1isize as u32; - | ^^^^^^^^^^^^^ - -error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:73:5 - | -73 | 1isize as u32; - | ^^^^^^^^^^^^^ - -error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:74:5 - | -74 | 1usize as u32; - | ^^^^^^^^^^^^^ - -error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:75:5 - | -75 | 1usize as i32; - | ^^^^^^^^^^^^^ - -error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:75:5 - | -75 | 1usize as i32; - | ^^^^^^^^^^^^^ - -error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:77:5 - | -77 | 1i64 as isize; - | ^^^^^^^^^^^^^ - -error: casting i64 to usize may lose the sign of the value - --> $DIR/cast.rs:78:5 - | -78 | 1i64 as usize; - | ^^^^^^^^^^^^^ - -error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:78:5 - | -78 | 1i64 as usize; - | ^^^^^^^^^^^^^ - -error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:79:5 - | -79 | 1u64 as isize; - | ^^^^^^^^^^^^^ - -error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:79:5 - | -79 | 1u64 as isize; - | ^^^^^^^^^^^^^ - -error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:80:5 - | -80 | 1u64 as usize; - | ^^^^^^^^^^^^^ - -error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:81:5 - | -81 | 1u32 as isize; - | ^^^^^^^^^^^^^ - -error: casting i32 to usize may lose the sign of the value - --> $DIR/cast.rs:84:5 - | -84 | 1i32 as usize; - | ^^^^^^^^^^^^^ - error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:86:5 + --> $DIR/cast.rs:37:5 | -86 | 1i32 as i32; +37 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:87:5 + --> $DIR/cast.rs:38:5 | -87 | 1f32 as f32; +38 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:88:5 + --> $DIR/cast.rs:39:5 | -88 | false as bool; +39 | false as bool; | ^^^^^^^^^^^^^ diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs new file mode 100644 index 00000000000..9e61059b630 --- /dev/null +++ b/tests/ui/cast_lossless_float.rs @@ -0,0 +1,15 @@ +#[warn(cast_lossless)] +#[allow(no_effect, unnecessary_operation)] +fn main() { + // Test cast_lossless with casts to floating-point types + 1i8 as f32; + 1i8 as f64; + 1u8 as f32; + 1u8 as f64; + 1i16 as f32; + 1i16 as f64; + 1u16 as f32; + 1u16 as f64; + 1i32 as f64; + 1u32 as f64; +} diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr new file mode 100644 index 00000000000..781d9c89767 --- /dev/null +++ b/tests/ui/cast_lossless_float.stderr @@ -0,0 +1,62 @@ +error: casting i8 to f32 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:5:5 + | +5 | 1i8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1i8)` + | + = note: `-D cast-lossless` implied by `-D warnings` + +error: casting i8 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:6:5 + | +6 | 1i8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1i8)` + +error: casting u8 to f32 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:7:5 + | +7 | 1u8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1u8)` + +error: casting u8 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:8:5 + | +8 | 1u8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1u8)` + +error: casting i16 to f32 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:9:5 + | +9 | 1i16 as f32; + | ^^^^^^^^^^^ help: try: `f32::from(1i16)` + +error: casting i16 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:10:5 + | +10 | 1i16 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1i16)` + +error: casting u16 to f32 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:11:5 + | +11 | 1u16 as f32; + | ^^^^^^^^^^^ help: try: `f32::from(1u16)` + +error: casting u16 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:12:5 + | +12 | 1u16 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1u16)` + +error: casting i32 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:13:5 + | +13 | 1i32 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1i32)` + +error: casting u32 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:14:5 + | +14 | 1u32 as f64; + | ^^^^^^^^^^^ help: try: `f64::from(1u32)` + diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs new file mode 100644 index 00000000000..5f89d057c33 --- /dev/null +++ b/tests/ui/cast_lossless_integer.rs @@ -0,0 +1,24 @@ + +#[warn(cast_lossless)] +#[allow(no_effect, unnecessary_operation)] +fn main() { + // Test cast_lossless with casts to integer types + 1i8 as i16; + 1i8 as i32; + 1i8 as i64; + 1u8 as i16; + 1u8 as i32; + 1u8 as i64; + 1u8 as u16; + 1u8 as u32; + 1u8 as u64; + 1i16 as i32; + 1i16 as i64; + 1u16 as i32; + 1u16 as i64; + 1u16 as u32; + 1u16 as u64; + 1i32 as i64; + 1u32 as i64; + 1u32 as u64; +} diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr new file mode 100644 index 00000000000..fdd915979e4 --- /dev/null +++ b/tests/ui/cast_lossless_integer.stderr @@ -0,0 +1,110 @@ +error: casting i8 to i16 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:6:5 + | +6 | 1i8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1i8)` + | + = note: `-D cast-lossless` implied by `-D warnings` + +error: casting i8 to i32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:7:5 + | +7 | 1i8 as i32; + | ^^^^^^^^^^ help: try: `i32::from(1i8)` + +error: casting i8 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:8:5 + | +8 | 1i8 as i64; + | ^^^^^^^^^^ help: try: `i64::from(1i8)` + +error: casting u8 to i16 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:9:5 + | +9 | 1u8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1u8)` + +error: casting u8 to i32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:10:5 + | +10 | 1u8 as i32; + | ^^^^^^^^^^ help: try: `i32::from(1u8)` + +error: casting u8 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:11:5 + | +11 | 1u8 as i64; + | ^^^^^^^^^^ help: try: `i64::from(1u8)` + +error: casting u8 to u16 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:12:5 + | +12 | 1u8 as u16; + | ^^^^^^^^^^ help: try: `u16::from(1u8)` + +error: casting u8 to u32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:13:5 + | +13 | 1u8 as u32; + | ^^^^^^^^^^ help: try: `u32::from(1u8)` + +error: casting u8 to u64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:14:5 + | +14 | 1u8 as u64; + | ^^^^^^^^^^ help: try: `u64::from(1u8)` + +error: casting i16 to i32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:15:5 + | +15 | 1i16 as i32; + | ^^^^^^^^^^^ help: try: `i32::from(1i16)` + +error: casting i16 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:16:5 + | +16 | 1i16 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1i16)` + +error: casting u16 to i32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:17:5 + | +17 | 1u16 as i32; + | ^^^^^^^^^^^ help: try: `i32::from(1u16)` + +error: casting u16 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:18:5 + | +18 | 1u16 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1u16)` + +error: casting u16 to u32 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:19:5 + | +19 | 1u16 as u32; + | ^^^^^^^^^^^ help: try: `u32::from(1u16)` + +error: casting u16 to u64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:20:5 + | +20 | 1u16 as u64; + | ^^^^^^^^^^^ help: try: `u64::from(1u16)` + +error: casting i32 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:21:5 + | +21 | 1i32 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1i32)` + +error: casting u32 to i64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:22:5 + | +22 | 1u32 as i64; + | ^^^^^^^^^^^ help: try: `i64::from(1u32)` + +error: casting u32 to u64 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:23:5 + | +23 | 1u32 as u64; + | ^^^^^^^^^^^ help: try: `u64::from(1u32)` + diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs new file mode 100644 index 00000000000..d0bef860c70 --- /dev/null +++ b/tests/ui/cast_size.rs @@ -0,0 +1,23 @@ +#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)] +#[allow(no_effect, unnecessary_operation)] +fn main() { + // Casting from *size + 1isize as i8; + 1isize as f64; + 1usize as f64; + 1isize as f32; + 1usize as f32; + 1isize as i32; + 1isize as u32; + 1usize as u32; + 1usize as i32; + // Casting to *size + 1i64 as isize; + 1i64 as usize; + 1u64 as isize; + 1u64 as usize; + 1u32 as isize; + 1u32 as usize; // Should not trigger any lint + 1i32 as isize; // Neither should this + 1i32 as usize; +} diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr new file mode 100644 index 00000000000..a6aac1300a3 --- /dev/null +++ b/tests/ui/cast_size.stderr @@ -0,0 +1,122 @@ +error: casting isize to i8 may truncate the value + --> $DIR/cast_size.rs:5:5 + | +5 | 1isize as i8; + | ^^^^^^^^^^^^ + | + = note: `-D cast-possible-truncation` implied by `-D warnings` + +error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) + --> $DIR/cast_size.rs:6:5 + | +6 | 1isize as f64; + | ^^^^^^^^^^^^^ + | + = note: `-D cast-precision-loss` implied by `-D warnings` + +error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) + --> $DIR/cast_size.rs:7:5 + | +7 | 1usize as f64; + | ^^^^^^^^^^^^^ + +error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + --> $DIR/cast_size.rs:8:5 + | +8 | 1isize as f32; + | ^^^^^^^^^^^^^ + +error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + --> $DIR/cast_size.rs:9:5 + | +9 | 1usize as f32; + | ^^^^^^^^^^^^^ + +error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size.rs:10:5 + | +10 | 1isize as i32; + | ^^^^^^^^^^^^^ + +error: casting isize to u32 may lose the sign of the value + --> $DIR/cast_size.rs:11:5 + | +11 | 1isize as u32; + | ^^^^^^^^^^^^^ + | + = note: `-D cast-sign-loss` implied by `-D warnings` + +error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size.rs:11:5 + | +11 | 1isize as u32; + | ^^^^^^^^^^^^^ + +error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size.rs:12:5 + | +12 | 1usize as u32; + | ^^^^^^^^^^^^^ + +error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size.rs:13:5 + | +13 | 1usize as i32; + | ^^^^^^^^^^^^^ + +error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:13:5 + | +13 | 1usize as i32; + | ^^^^^^^^^^^^^ + | + = note: `-D cast-possible-wrap` implied by `-D warnings` + +error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:15:5 + | +15 | 1i64 as isize; + | ^^^^^^^^^^^^^ + +error: casting i64 to usize may lose the sign of the value + --> $DIR/cast_size.rs:16:5 + | +16 | 1i64 as usize; + | ^^^^^^^^^^^^^ + +error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:16:5 + | +16 | 1i64 as usize; + | ^^^^^^^^^^^^^ + +error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:17:5 + | +17 | 1u64 as isize; + | ^^^^^^^^^^^^^ + +error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast_size.rs:17:5 + | +17 | 1u64 as isize; + | ^^^^^^^^^^^^^ + +error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:18:5 + | +18 | 1u64 as usize; + | ^^^^^^^^^^^^^ + +error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast_size.rs:19:5 + | +19 | 1u32 as isize; + | ^^^^^^^^^^^^^ + +error: casting i32 to usize may lose the sign of the value + --> $DIR/cast_size.rs:22:5 + | +22 | 1i32 as usize; + | ^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 91ecb3b8ed4ced1022d9e6cc06c1e15580f45938 Mon Sep 17 00:00:00 2001 From: Mikko Rantanen Date: Sun, 7 Jan 2018 05:58:53 +0200 Subject: Implement nightly libsyntax changes --- clippy_lints/src/mutex_atomic.rs | 4 ++-- clippy_lints/src/types.rs | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 6fe365fd255..3a1ecfbefc7 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -69,8 +69,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { atomic_name ); match mutex_param.sty { - ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyUint(t) if t != ast::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::TyInt(t) if t != ast::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c146d306a5a..9b58062d7de 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -541,7 +541,7 @@ declare_lint! { fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { match typ.sty { ty::TyInt(i) => match i { - IntTy::Is => tcx.data_layout.pointer_size.bits(), + IntTy::Isize => tcx.data_layout.pointer_size.bits(), IntTy::I8 => 8, IntTy::I16 => 16, IntTy::I32 => 32, @@ -549,7 +549,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { IntTy::I128 => 128, }, ty::TyUint(i) => match i { - UintTy::Us => tcx.data_layout.pointer_size.bits(), + UintTy::Usize => tcx.data_layout.pointer_size.bits(), UintTy::U8 => 8, UintTy::U16 => 16, UintTy::U32 => 32, @@ -562,7 +562,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { fn is_isize_or_usize(typ: Ty) -> bool { match typ.sty { - ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, + ty::TyInt(IntTy::Isize) | ty::TyUint(UintTy::Usize) => true, _ => false, } } @@ -1151,15 +1151,15 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - let which = match (&ty.sty, cv.val) { (&ty::TyBool, Bool(false)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | + (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MIN)))) | + (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MIN)))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | + (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MIN)))) | + (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MIN)))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | @@ -1167,15 +1167,15 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum, (&ty::TyBool, Bool(true)) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | - (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | + (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MAX)))) | + (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MAX)))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | - (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | + (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MAX)))) | + (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MAX)))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | @@ -1329,7 +1329,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( FullInt::S(i128::from(i64::max_value())), ), IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), - IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), + IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }), ty::TyUint(uint_ty) => Some(match uint_ty { UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), @@ -1346,7 +1346,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( FullInt::U(u128::from(u64::max_value())), ), UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), - UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), + UintTy::Usize => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), }), _ => None, } -- cgit 1.4.1-3-g733a5 From ab5b7dd7c1d66f2fe187dce23a41b953b4081cfd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 7 Jan 2018 12:50:42 +0100 Subject: Add link to lints in README configuration section The wiki has been deprecated. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b2af3f782a..0a859d2e85a 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ blacklisted-names = ["toto", "tata", "titi"] cyclomatic-complexity-threshold = 30 ``` -See the wiki for more information about which lints can be configured and the +See the [list of lints](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the meaning of the variables. You can also specify the path to the configuration file with: @@ -162,7 +162,7 @@ You can also specify the path to the configuration file with: #![plugin(clippy(conf_file="path/to/clippy's/configuration"))] ``` -To deactivate the “for further information visit *wiki-link*” message you can +To deactivate the “for further information visit *lint-link*” message you can define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. ### Allowing/denying lints -- cgit 1.4.1-3-g733a5 From 1a16ac058dda3bcb20c57d9f1daf1d22b6a992a4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 8 Jan 2018 10:17:05 +0100 Subject: Add 'positive' examples for some lints This allows to see at a quick glance what the improved code could look like for these lints. --- clippy_lints/src/types.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c146d306a5a..bf4e85f689f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -36,6 +36,14 @@ pub struct TypePass; /// values: Box>, /// } /// ``` +/// +/// Better: +/// +/// ```rust +/// struct X { +/// values: Vec, +/// } +/// ``` declare_lint! { pub BOX_VEC, Warn, @@ -89,6 +97,12 @@ declare_lint! { /// ```rust /// fn foo(bar: &Box) { ... } /// ``` +/// +/// Better: +/// +/// ```rust +/// fn foo(bar: &T) { ... } +/// ``` declare_lint! { pub BORROWED_BOX, Warn, @@ -514,6 +528,12 @@ declare_lint! { /// ```rust /// fn as_u64(x: u8) -> u64 { x as u64 } /// ``` +/// +/// Using `::from` would look like this: +/// +/// ```rust +/// fn as_u64(x: u8) -> u64 { u64::from(x) } +/// ``` declare_lint! { pub CAST_LOSSLESS, Warn, @@ -994,6 +1014,12 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { /// ```rust /// 'x' as u8 /// ``` +/// +/// A better version, using the byte literal: +/// +/// ```rust +/// b'x' +/// ``` declare_lint! { pub CHAR_LIT_AS_U8, Warn, -- cgit 1.4.1-3-g733a5 From 18f3f0dd6232aa5cf47063b6118ea58ee1f9f52d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 8 Jan 2018 11:42:29 +0100 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddfd801c929..ea8af2ee0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.178 +* Rustup to *rustc 1.25.0-nightly (ee220daca 2018-01-07)* + ## 0.0.177 * Rustup to *rustc 1.24.0-nightly (250b49205 2017-12-21)* * New lint: [`match_as_ref`] diff --git a/Cargo.toml b/Cargo.toml index 510f53becdb..320f5cd2220 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.177" +version = "0.0.178" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.177", path = "clippy_lints" } +clippy_lints = { version = "0.0.178", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index de4a1035cb1..d83747852e8 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.177" +version = "0.0.178" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 75c92aa2d2ccf69e360e13c450b0b0436015ae69 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 9 Jan 2018 14:57:06 +0100 Subject: Fix an ICE in HashMap generalization suggestions --- clippy_lints/src/types.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4543dfcfb74..7c536140f28 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1621,7 +1621,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); ctr_vis.visit_body(body); - assert!(ctr_vis.suggestions.is_empty()); span_lint_and_then( cx, -- cgit 1.4.1-3-g733a5 From 41a710e3f4d52f08a487b22debd5940fe705e38b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 10 Jan 2018 09:50:58 +0100 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/needless_update.rs | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8af2ee0e9..ffa7f89eb50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.179 +* Rustup to *rustc 1.25.0-nightly (61452e506 2018-01-09)* + ## 0.0.178 * Rustup to *rustc 1.25.0-nightly (ee220daca 2018-01-07)* diff --git a/Cargo.toml b/Cargo.toml index 320f5cd2220..701c27bf26d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.178" +version = "0.0.179" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.178", path = "clippy_lints" } +clippy_lints = { version = "0.0.179", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d83747852e8..2d5038abd6b 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.178" +version = "0.0.179" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index d6624411e2f..5512a2092b4 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tables.expr_ty(expr); if let ty::TyAdt(def, _) = ty.sty { - if fields.len() == def.struct_variant().fields.len() { + if fields.len() == def.non_enum_variant().fields.len() { span_lint( cx, NEEDLESS_UPDATE, -- cgit 1.4.1-3-g733a5 From 1245de1e468761b123fad5d5214c37cb12c66f94 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 11 Jan 2018 10:28:42 +0100 Subject: Don't suggest changing explicit Clone impls if they have generics --- clippy_lints/src/derive.rs | 7 +++++++ tests/ui/clone_on_copy_impl.rs | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/ui/clone_on_copy_impl.rs diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 6ce67a9b05c..d327d0570f1 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -148,6 +148,13 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref return; } } + for subst in substs { + if let Some(subst) = subst.as_type() { + if let ty::TyParam(_) = subst.sty { + return; + } + } + } }, _ => (), } diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs new file mode 100644 index 00000000000..e21441640f3 --- /dev/null +++ b/tests/ui/clone_on_copy_impl.rs @@ -0,0 +1,22 @@ +use std::marker::PhantomData; +use std::fmt; + +pub struct Key { + #[doc(hidden)] + pub __name: &'static str, + #[doc(hidden)] + pub __phantom: PhantomData, +} + +impl Copy for Key {} + +impl Clone for Key { + fn clone(&self) -> Self { + Key { + __name: self.__name, + __phantom: self.__phantom, + } + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 8505ee7028e00003e7e13c0f15ba9c2cf787f67c Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Tue, 9 Jan 2018 23:42:07 -0500 Subject: Add lint to replace `const`s with `const fn`s --- clippy_lints/src/lib.rs | 3 + clippy_lints/src/replace_consts.rs | 102 ++++++++++++++++++ tests/ui/replace_consts.rs | 96 +++++++++++++++++ tests/ui/replace_consts.stderr | 216 +++++++++++++++++++++++++++++++++++++ 4 files changed, 417 insertions(+) create mode 100644 clippy_lints/src/replace_consts.rs create mode 100644 tests/ui/replace_consts.rs create mode 100644 tests/ui/replace_consts.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9b598df4fa6..13760e8c0fb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -150,6 +150,7 @@ pub mod ptr; pub mod ranges; pub mod reference; pub mod regex; +pub mod replace_consts; pub mod returns; pub mod serde_api; pub mod shadow; @@ -361,6 +362,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_early_lint_pass(box const_static_lifetime::StaticConst); reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); + reg.register_late_lint_pass(box replace_consts::ReplaceConsts); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -399,6 +401,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { print::PRINT_STDOUT, print::USE_DEBUG, ranges::RANGE_PLUS_ONE, + replace_consts::REPLACE_CONSTS, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs new file mode 100644 index 00000000000..511dbf7a40f --- /dev/null +++ b/clippy_lints/src/replace_consts.rs @@ -0,0 +1,102 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::hir::def::Def; +use utils::{match_def_path, span_lint_and_sugg}; + +/// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and +/// `uX/iX::MIN/MAX`. +/// +/// **Why is this bad?** `const fn`s exist +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT; +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// static FOO: AtomicIsize = AtomicIsize::new(0); +/// ``` +declare_lint! { + pub REPLACE_CONSTS, + Allow, + "Lint usages of standard library `const`s that could be replaced by `const fn`s" +} + +pub struct ReplaceConsts; + +impl LintPass for ReplaceConsts { + fn get_lints(&self) -> LintArray { + lint_array!(REPLACE_CONSTS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + if_chain! { + if let hir::ExprPath(ref qp) = expr.node; + if let Def::Const(def_id) = cx.tables.qpath_def(qp, expr.hir_id); + then { + for &(const_path, repl_snip) in REPLACEMENTS { + if match_def_path(cx.tcx, def_id, const_path) { + span_lint_and_sugg( + cx, + REPLACE_CONSTS, + expr.span, + &format!("using `{}`", const_path.last().expect("empty path")), + "try this", + repl_snip.to_string(), + ); + return; + } + } + } + } + } +} + +const REPLACEMENTS: &[(&[&str], &str)] = &[ + // Once + (&["core", "sync", "ONCE_INIT"], "Once::new()"), + // Atomic + (&["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], "AtomicBool::new(false)"), + (&["core", "sync", "atomic", "ATOMIC_ISIZE_INIT"], "AtomicIsize::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_USIZE_INIT"], "AtomicUsize::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"), + // Min + (&["core", "isize", "MIN"], "isize::min_value()"), + (&["core", "i8", "MIN"], "i8::min_value()"), + (&["core", "i16", "MIN"], "i16::min_value()"), + (&["core", "i32", "MIN"], "i32::min_value()"), + (&["core", "i64", "MIN"], "i64::min_value()"), + (&["core", "i128", "MIN"], "i128::min_value()"), + (&["core", "usize", "MIN"], "usize::min_value()"), + (&["core", "u8", "MIN"], "u8::min_value()"), + (&["core", "u16", "MIN"], "u16::min_value()"), + (&["core", "u32", "MIN"], "u32::min_value()"), + (&["core", "u64", "MIN"], "u64::min_value()"), + (&["core", "u128", "MIN"], "u128::min_value()"), + // Max + (&["core", "isize", "MAX"], "isize::max_value()"), + (&["core", "i8", "MAX"], "i8::max_value()"), + (&["core", "i16", "MAX"], "i16::max_value()"), + (&["core", "i32", "MAX"], "i32::max_value()"), + (&["core", "i64", "MAX"], "i64::max_value()"), + (&["core", "i128", "MAX"], "i128::max_value()"), + (&["core", "usize", "MAX"], "usize::max_value()"), + (&["core", "u8", "MAX"], "u8::max_value()"), + (&["core", "u16", "MAX"], "u16::max_value()"), + (&["core", "u32", "MAX"], "u32::max_value()"), + (&["core", "u64", "MAX"], "u64::max_value()"), + (&["core", "u128", "MAX"], "u128::max_value()"), +]; diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs new file mode 100644 index 00000000000..31c58b4bb4e --- /dev/null +++ b/tests/ui/replace_consts.rs @@ -0,0 +1,96 @@ +#![feature(integer_atomics, i128, i128_type)] +#![allow(blacklisted_name)] +#![deny(replace_consts)] +use std::sync::atomic::*; +use std::sync::{ONCE_INIT, Once}; + +fn bad() { + // Once + { let foo = ONCE_INIT; }; + // Atomic + { let foo = ATOMIC_BOOL_INIT; }; + { let foo = ATOMIC_ISIZE_INIT; }; + { let foo = ATOMIC_I8_INIT; }; + { let foo = ATOMIC_I16_INIT; }; + { let foo = ATOMIC_I32_INIT; }; + { let foo = ATOMIC_I64_INIT; }; + { let foo = ATOMIC_USIZE_INIT; }; + { let foo = ATOMIC_U8_INIT; }; + { let foo = ATOMIC_U16_INIT; }; + { let foo = ATOMIC_U32_INIT; }; + { let foo = ATOMIC_U64_INIT; }; + // Min + { let foo = std::isize::MIN; }; + { let foo = std::i8::MIN; }; + { let foo = std::i16::MIN; }; + { let foo = std::i32::MIN; }; + { let foo = std::i64::MIN; }; + { let foo = std::i128::MIN; }; + { let foo = std::usize::MIN; }; + { let foo = std::u8::MIN; }; + { let foo = std::u16::MIN; }; + { let foo = std::u32::MIN; }; + { let foo = std::u64::MIN; }; + { let foo = std::u128::MIN; }; + // Max + { let foo = std::isize::MAX; }; + { let foo = std::i8::MAX; }; + { let foo = std::i16::MAX; }; + { let foo = std::i32::MAX; }; + { let foo = std::i64::MAX; }; + { let foo = std::i128::MAX; }; + { let foo = std::usize::MAX; }; + { let foo = std::u8::MAX; }; + { let foo = std::u16::MAX; }; + { let foo = std::u32::MAX; }; + { let foo = std::u64::MAX; }; + { let foo = std::u128::MAX; }; +} + +fn good() { + // Once + { let foo = Once::new(); }; + // Atomic + { let foo = AtomicBool::new(false); }; + { let foo = AtomicIsize::new(0); }; + { let foo = AtomicI8::new(0); }; + { let foo = AtomicI16::new(0); }; + { let foo = AtomicI32::new(0); }; + { let foo = AtomicI64::new(0); }; + { let foo = AtomicUsize::new(0); }; + { let foo = AtomicU8::new(0); }; + { let foo = AtomicU16::new(0); }; + { let foo = AtomicU32::new(0); }; + { let foo = AtomicU64::new(0); }; + // Min + { let foo = isize::min_value(); }; + { let foo = i8::min_value(); }; + { let foo = i16::min_value(); }; + { let foo = i32::min_value(); }; + { let foo = i64::min_value(); }; + { let foo = i128::min_value(); }; + { let foo = usize::min_value(); }; + { let foo = u8::min_value(); }; + { let foo = u16::min_value(); }; + { let foo = u32::min_value(); }; + { let foo = u64::min_value(); }; + { let foo = u128::min_value(); }; + // Max + { let foo = isize::max_value(); }; + { let foo = i8::max_value(); }; + { let foo = i16::max_value(); }; + { let foo = i32::max_value(); }; + { let foo = i64::max_value(); }; + { let foo = i128::max_value(); }; + { let foo = usize::max_value(); }; + { let foo = u8::max_value(); }; + { let foo = u16::max_value(); }; + { let foo = u32::max_value(); }; + { let foo = u64::max_value(); }; + { let foo = u128::max_value(); }; +} + +fn main() { + bad(); + good(); +} diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr new file mode 100644 index 00000000000..a8e3dd2d00e --- /dev/null +++ b/tests/ui/replace_consts.stderr @@ -0,0 +1,216 @@ +error: using `ATOMIC_BOOL_INIT` + --> $DIR/replace_consts.rs:11:17 + | +11 | { let foo = ATOMIC_BOOL_INIT; }; + | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` + | +note: lint level defined here + --> $DIR/replace_consts.rs:3:9 + | +3 | #![deny(replace_consts)] + | ^^^^^^^^^^^^^^ + +error: using `ATOMIC_ISIZE_INIT` + --> $DIR/replace_consts.rs:12:17 + | +12 | { let foo = ATOMIC_ISIZE_INIT; }; + | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` + +error: using `ATOMIC_I8_INIT` + --> $DIR/replace_consts.rs:13:17 + | +13 | { let foo = ATOMIC_I8_INIT; }; + | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` + +error: using `ATOMIC_I16_INIT` + --> $DIR/replace_consts.rs:14:17 + | +14 | { let foo = ATOMIC_I16_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` + +error: using `ATOMIC_I32_INIT` + --> $DIR/replace_consts.rs:15:17 + | +15 | { let foo = ATOMIC_I32_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` + +error: using `ATOMIC_I64_INIT` + --> $DIR/replace_consts.rs:16:17 + | +16 | { let foo = ATOMIC_I64_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` + +error: using `ATOMIC_USIZE_INIT` + --> $DIR/replace_consts.rs:17:17 + | +17 | { let foo = ATOMIC_USIZE_INIT; }; + | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` + +error: using `ATOMIC_U8_INIT` + --> $DIR/replace_consts.rs:18:17 + | +18 | { let foo = ATOMIC_U8_INIT; }; + | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` + +error: using `ATOMIC_U16_INIT` + --> $DIR/replace_consts.rs:19:17 + | +19 | { let foo = ATOMIC_U16_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` + +error: using `ATOMIC_U32_INIT` + --> $DIR/replace_consts.rs:20:17 + | +20 | { let foo = ATOMIC_U32_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` + +error: using `ATOMIC_U64_INIT` + --> $DIR/replace_consts.rs:21:17 + | +21 | { let foo = ATOMIC_U64_INIT; }; + | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` + +error: using `MIN` + --> $DIR/replace_consts.rs:23:17 + | +23 | { let foo = std::isize::MIN; }; + | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:24:17 + | +24 | { let foo = std::i8::MIN; }; + | ^^^^^^^^^^^^ help: try this: `i8::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:25:17 + | +25 | { let foo = std::i16::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:26:17 + | +26 | { let foo = std::i32::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:27:17 + | +27 | { let foo = std::i64::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:28:17 + | +28 | { let foo = std::i128::MIN; }; + | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:29:17 + | +29 | { let foo = std::usize::MIN; }; + | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:30:17 + | +30 | { let foo = std::u8::MIN; }; + | ^^^^^^^^^^^^ help: try this: `u8::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:31:17 + | +31 | { let foo = std::u16::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:32:17 + | +32 | { let foo = std::u32::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:33:17 + | +33 | { let foo = std::u64::MIN; }; + | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` + +error: using `MIN` + --> $DIR/replace_consts.rs:34:17 + | +34 | { let foo = std::u128::MIN; }; + | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:36:17 + | +36 | { let foo = std::isize::MAX; }; + | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:37:17 + | +37 | { let foo = std::i8::MAX; }; + | ^^^^^^^^^^^^ help: try this: `i8::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:38:17 + | +38 | { let foo = std::i16::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:39:17 + | +39 | { let foo = std::i32::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:40:17 + | +40 | { let foo = std::i64::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:41:17 + | +41 | { let foo = std::i128::MAX; }; + | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:42:17 + | +42 | { let foo = std::usize::MAX; }; + | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:43:17 + | +43 | { let foo = std::u8::MAX; }; + | ^^^^^^^^^^^^ help: try this: `u8::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:44:17 + | +44 | { let foo = std::u16::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:45:17 + | +45 | { let foo = std::u32::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:46:17 + | +46 | { let foo = std::u64::MAX; }; + | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` + +error: using `MAX` + --> $DIR/replace_consts.rs:47:17 + | +47 | { let foo = std::u128::MAX; }; + | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` + -- cgit 1.4.1-3-g733a5 From c66eaee77c095a31e64c2e6ca56536d50ac31ab9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 12 Jan 2018 16:03:13 +0530 Subject: Nightly only --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0a859d2e85a..e4f0f3547ce 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,12 @@ One way to use clippy is by installing clippy through cargo as a cargo subcommand. ```terminal -cargo install clippy +cargo +nightly install clippy ``` -Now you can run clippy by invoking `cargo clippy`, or -`cargo +nightly clippy` directly from a directory that is usually -compiled with stable. +(The `+nightly` is not necessary if your default `rustup` install is nightly) + +Now you can run clippy by invoking `cargo +nightly clippy`. In case you are not using rustup, you need to set the environment flag `SYSROOT` during installation so clippy knows where to find `librustc` and -- cgit 1.4.1-3-g733a5 From 53c0ae01698a9b53d56d7186c55a617a75668187 Mon Sep 17 00:00:00 2001 From: kimsnj Date: Fri, 12 Jan 2018 18:24:24 +0100 Subject: Fix #1159: avoid comparing fixed and target sized types in lint --- clippy_lints/src/types.rs | 19 +++++++++++++++++++ tests/ui/absurd-extreme-comparisons.rs | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 7c536140f28..c0c72408c7d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1106,6 +1106,20 @@ enum AbsurdComparisonResult { } +fn is_cast_between_fixed_and_target<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr +) -> bool { + + if let ExprCast(ref cast_exp, _) = expr.node { + let precast_ty = cx.tables.expr_ty(cast_exp); + let cast_ty = cx.tables.expr_ty(expr); + + return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty) + } + + return false; +} fn detect_absurd_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, @@ -1123,6 +1137,11 @@ fn detect_absurd_comparison<'a, 'tcx>( return None; } + // comparisons between fix sized types and target sized types are considered unanalyzable + if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) { + return None; + } + let normalized = normalize_comparison(op, lhs, rhs); let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { val diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index 1f88d94bd2b..8c036e6c072 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -50,3 +50,8 @@ impl PartialOrd for U { pub fn foo(val: U) -> bool { val > std::u32::MAX } + +pub fn bar(len: u64) -> bool { + // This is OK as we are casting from target sized to fixed size + len >= std::usize::MAX as u64 +} -- cgit 1.4.1-3-g733a5 From 7e63f93d81062fa810eaefe368b38892bf11f909 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 14 Jan 2018 11:35:07 +0530 Subject: Don't warn about missing docs for main() Fixes #2348 --- clippy_lints/src/missing_doc.rs | 12 +++++++++++- tests/ui/missing-doc.stderr | 6 ------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 2a3a4e365a5..ecc8f50d6a0 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -124,7 +124,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let desc = match it.node { hir::ItemConst(..) => "a constant", hir::ItemEnum(..) => "an enum", - hir::ItemFn(..) => "a function", + hir::ItemFn(..) => { + // ignore main() + if it.name == "main" { + let def_id = cx.tcx.hir.local_def_id(it.id); + let def_key = cx.tcx.hir.def_key(def_id); + if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { + return; + } + } + "a function" + }, hir::ItemMod(..) => "a module", hir::ItemStatic(..) => "a static", hir::ItemStruct(..) => "a struct", diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index 55eab4f5d69..340a53386f9 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -264,9 +264,3 @@ error: missing documentation for a function 191 | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing documentation for a function - --> $DIR/missing-doc.rs:202:1 - | -202 | fn main() {} - | ^^^^^^^^^^^^ - -- cgit 1.4.1-3-g733a5 From f6e56d255905abd2b7728ffbf24c0c5b09f5d1ed Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 08:27:53 +0000 Subject: First pass at linting for .any expressed as a .fold --- clippy_lints/src/methods.rs | 88 +++++++++++++++++++++++++++++++++++++++++++-- tests/ui/methods.rs | 5 +++ tests/ui/methods.stderr | 12 +++++-- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 64335f81a63..4277b4b15d3 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -12,7 +12,7 @@ use syntax::ast; use syntax::codemap::Span; use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, single_segment_path, snippet, span_lint, + match_type, method_chain_args, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; @@ -623,6 +623,23 @@ declare_lint! { "using `as_ref` where the types before and after the call are the same" } + +/// **What it does:** Checks for using `fold` to implement `any`. +/// +/// **Why is this bad?** Readability. +/// +/// **Known problems:** Changes semantics - the suggested replacement is short-circuiting. +/// +/// **Example:** +/// ```rust +/// let _ = (0..3).fold(false, |acc, x| acc || x > 2); +/// ``` +declare_lint! { + pub FOLD_ANY, + Warn, + "TODO" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( @@ -653,7 +670,8 @@ impl LintPass for Pass { GET_UNWRAP, STRING_EXTEND_CHARS, ITER_CLONED_COLLECT, - USELESS_ASREF + USELESS_ASREF, + FOLD_ANY ) } } @@ -717,6 +735,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_asref(cx, expr, "as_ref", arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { lint_asref(cx, expr, "as_mut", arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { + lint_fold_any(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &method_call.name.as_str(), args); @@ -1105,6 +1125,70 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir } } +// DONOTMERGE: copy-pasted from map_clone +fn get_arg_name(pat: &hir::Pat) -> Option { + match pat.node { + hir::PatKind::Binding(_, _, name, None) => Some(name.node), + hir::PatKind::Ref(ref subpat, _) => get_arg_name(subpat), + _ => None, + } +} + +fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { + // DONOTMERGE: What if this is just some other method called fold? + assert!(fold_args.len() == 3, + "Expected fold_args to have three entries - the receiver, the initial value and the closure"); + + if let hir::ExprLit(ref lit) = fold_args[1].node { + if let ast::LitKind::Bool(ref b) = lit.node { + let initial_value = b.to_string(); + + if let hir::ExprClosure(_, ref decl, body_id, _, _) = fold_args[2].node { + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); + + let first_arg = &closure_body.arguments[0]; + let arg_ident = get_arg_name(&first_arg.pat).unwrap(); + + let second_arg = &closure_body.arguments[1]; + let second_arg_ident = get_arg_name(&second_arg.pat).unwrap(); + + if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node { + if bin_op.node != hir::BinOp_::BiOr { + return; + } + if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node { + if path.segments.len() == 1 { + let left_name = &path.segments[0].name; + let right_source = cx.sess().codemap().span_to_snippet(right_expr.span).unwrap(); + + if left_name == &arg_ident { + span_lint( + cx, + FOLD_ANY, + expr.span, + // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) + // TODO: these have difference semantics - original code might be deliberately avoiding short-circuiting + &format!( + ".fold(false, |{f}, {s}| {f} || {r})) is more succinctly expressed as .any(|{s}| {r})", + f = arg_ident, + s = second_arg_ident, + r = right_source + ), + ); + } + } + } + } + } else{ + panic!("DONOTMERGE: can this happen?"); + } + } + } else { + return; + } +} + fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index c80f6acd06b..2dcc085add3 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -385,6 +385,11 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } +/// Checks implementation of the `FOLD_ANY` lint +fn fold_any() { + let _ = (0..3).fold(false, |acc, x| acc || x > 2); +} + #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 65d8b82da14..768fbd1df54 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -493,10 +493,18 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 382 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: .fold(false, |acc, x| acc || x > 2)) is more succinctly expressed as .any(|x| x > 2) + --> $DIR/methods.rs:390:13 + | +390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D fold-any` implied by `-D warnings` + error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:391:13 + --> $DIR/methods.rs:396:13 | -391 | let _ = opt.unwrap(); +396 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 1feb9fd5502d50f50b2e6e3bf8101e1d860e3dba Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 09:30:08 +0000 Subject: Tidy using if_chain and snippet function. Actually check that the initial fold value is false. Remove some unwraps --- clippy_lints/src/methods.rs | 73 +++++++++++++++++++-------------------------- tests/ui/methods.rs | 5 ++++ tests/ui/methods.stderr | 4 +-- 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4277b4b15d3..36e6fb4b1a2 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1139,53 +1139,42 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); - if let hir::ExprLit(ref lit) = fold_args[1].node { - if let ast::LitKind::Bool(ref b) = lit.node { - let initial_value = b.to_string(); + if_chain! { + // Check if the initial value for the fold is the literal `false` + if let hir::ExprLit(ref lit) = fold_args[1].node; + if lit.node == ast::LitKind::Bool(false); - if let hir::ExprClosure(_, ref decl, body_id, _, _) = fold_args[2].node { - let closure_body = cx.tcx.hir.body(body_id); - let closure_expr = remove_blocks(&closure_body.value); + // Extract the body of the closure passed to fold + if let hir::ExprClosure(_, _, body_id, _, _) = fold_args[2].node; + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); - let first_arg = &closure_body.arguments[0]; - let arg_ident = get_arg_name(&first_arg.pat).unwrap(); + // Extract the names of the two arguments to the closure + if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); + if let Some(second_first_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); - let second_arg = &closure_body.arguments[1]; - let second_arg_ident = get_arg_name(&second_arg.pat).unwrap(); + // Check if the closure body is of the form `acc || some_expr(x)` + if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; + if bin_op.node == hir::BinOp_::BiOr; + if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node; + if path.segments.len() == 1 && &path.segments[0].name == &first_arg_ident; - if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node { - if bin_op.node != hir::BinOp_::BiOr { - return; - } - if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node { - if path.segments.len() == 1 { - let left_name = &path.segments[0].name; - let right_source = cx.sess().codemap().span_to_snippet(right_expr.span).unwrap(); - - if left_name == &arg_ident { - span_lint( - cx, - FOLD_ANY, - expr.span, - // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) - // TODO: these have difference semantics - original code might be deliberately avoiding short-circuiting - &format!( - ".fold(false, |{f}, {s}| {f} || {r})) is more succinctly expressed as .any(|{s}| {r})", - f = arg_ident, - s = second_arg_ident, - r = right_source - ), - ); - } - } - } - } - } else{ - panic!("DONOTMERGE: can this happen?"); - } + then { + let right_source = snippet(cx, right_expr.span, "EXPR"); + + span_lint( + cx, + FOLD_ANY, + expr.span, + // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) + &format!( + ".fold(false, |{f}, {s}| {f} || {r})) is more succinctly expressed as .any(|{s}| {r})", + f = first_arg_ident, + s = second_first_arg_ident, + r = right_source + ), + ); } - } else { - return; } } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 2dcc085add3..0dd4ff47fa9 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -390,6 +390,11 @@ fn fold_any() { let _ = (0..3).fold(false, |acc, x| acc || x > 2); } +/// Checks implementation of the `FOLD_ANY` lint +fn fold_any_ignore_initial_value_of_true() { + let _ = (0..3).fold(true, |acc, x| acc || x > 2); +} + #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 768fbd1df54..ef24e4a8e22 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -502,9 +502,9 @@ error: .fold(false, |acc, x| acc || x > 2)) is more succinctly expressed as .any = note: `-D fold-any` implied by `-D warnings` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:396:13 + --> $DIR/methods.rs:401:13 | -396 | let _ = opt.unwrap(); +401 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 528be23c07f1578161713a3a217876a60117cd81 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 10:05:01 +0000 Subject: Move get_arg_name into utils --- clippy_lints/src/map_clone.rs | 12 ++---------- clippy_lints/src/methods.rs | 11 +---------- clippy_lints/src/utils/mod.rs | 8 ++++++++ 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index e126d5c07d7..3bcaccf345a 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, paths, remove_blocks, snippet, - span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; +use utils::{get_arg_name, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, + paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -121,14 +121,6 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s } } -fn get_arg_name(pat: &Pat) -> Option { - match pat.node { - PatKind::Binding(_, _, name, None) => Some(name.node), - PatKind::Ref(ref subpat, _) => get_arg_name(subpat), - _ => None, - } -} - fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { match expr.node { ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 36e6fb4b1a2..67bbed48741 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -10,7 +10,7 @@ use std::fmt; use std::iter; use syntax::ast; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, +use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; @@ -1125,15 +1125,6 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir } } -// DONOTMERGE: copy-pasted from map_clone -fn get_arg_name(pat: &hir::Pat) -> Option { - match pat.node { - hir::PatKind::Binding(_, _, name, None) => Some(name.node), - hir::PatKind::Ref(ref subpat, _) => get_arg_name(subpat), - _ => None, - } -} - fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { // DONOTMERGE: What if this is just some other method called fold? assert!(fold_args.len() == 3, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0c1b10f05c8..94d2caf9c50 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1034,3 +1034,11 @@ pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option bool { cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } + +pub fn get_arg_name(pat: &Pat) -> Option { + match pat.node { + PatKind::Binding(_, _, name, None) => Some(name.node), + PatKind::Ref(ref subpat, _) => get_arg_name(subpat), + _ => None, + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 7e833ea5ce306566e273e078974d922bc2b45fb1 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 10:07:41 +0000 Subject: Add description --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 67bbed48741..bdfd729a327 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -637,7 +637,7 @@ declare_lint! { declare_lint! { pub FOLD_ANY, Warn, - "TODO" + "using `fold` to emulate the behaviour of `any`" } impl LintPass for Pass { -- cgit 1.4.1-3-g733a5 From 360f2359d5c4d8a332182143c4aa350b0f2734df Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 15:30:06 +0000 Subject: Fix name --- clippy_lints/src/methods.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index bdfd729a327..138dbed3135 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1142,7 +1142,7 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { // Extract the names of the two arguments to the closure if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); - if let Some(second_first_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); + if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); // Check if the closure body is of the form `acc || some_expr(x)` if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; @@ -1161,7 +1161,7 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { &format!( ".fold(false, |{f}, {s}| {f} || {r})) is more succinctly expressed as .any(|{s}| {r})", f = first_arg_ident, - s = second_first_arg_ident, + s = second_arg_ident, r = right_source ), ); -- cgit 1.4.1-3-g733a5 From 70a5535ffa2040829e6a7a8f673b1fb13505b636 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 18:18:09 +0000 Subject: Address some review comments --- clippy_lints/src/methods.rs | 11 ++++++----- clippy_lints/src/utils/mod.rs | 14 ++++++++++++++ tests/ui/methods.rs | 7 ++++++- tests/ui/methods.stderr | 8 ++++---- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 138dbed3135..9661a6011bd 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1153,17 +1153,18 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { then { let right_source = snippet(cx, right_expr.span, "EXPR"); - span_lint( + span_lint_and_sugg( cx, FOLD_ANY, expr.span, // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) - &format!( - ".fold(false, |{f}, {s}| {f} || {r})) is more succinctly expressed as .any(|{s}| {r})", - f = first_arg_ident, + "this `.fold` can more succintly be expressed as `.any`", + "try", + format!( + ".any(|{s}| {r})", s = second_arg_ident, r = right_source - ), + ) ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 94d2caf9c50..44ebc5aa600 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -596,6 +596,20 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( db.docs_link(lint); } +/// Add a span lint with a suggestion on how to fix it. +/// +/// These suggestions can be parsed by rustfix to allow it to automatically fix your code. +/// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > 2)"`. +/// +///
+/// error: This `.fold` can be more succinctly expressed as `.any`
+/// --> $DIR/methods.rs:390:13
+///     |
+/// 390 |     let _ = (0..3).fold(false, |acc, x| acc || x > 2);
+///     |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)`
+///     |
+///     = note: `-D fold-any` implied by `-D warnings`
+/// 
pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( cx: &'a T, lint: &'static Lint, diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 0dd4ff47fa9..8cffbf76924 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -391,10 +391,15 @@ fn fold_any() { } /// Checks implementation of the `FOLD_ANY` lint -fn fold_any_ignore_initial_value_of_true() { +fn fold_any_ignores_initial_value_of_true() { let _ = (0..3).fold(true, |acc, x| acc || x > 2); } +/// Checks implementation of the `FOLD_ANY` lint +fn fold_any_ignores_non_boolean_accumalator() { + let _ = (0..3).fold(0, |acc, x| acc + if x > 2 { 1 } else { 0 }); +} + #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index ef24e4a8e22..f1746354380 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -493,18 +493,18 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 382 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: .fold(false, |acc, x| acc || x > 2)) is more succinctly expressed as .any(|x| x > 2) +error: this `.fold` can more succintly be expressed as `.any` --> $DIR/methods.rs:390:13 | 390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | = note: `-D fold-any` implied by `-D warnings` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:401:13 + --> $DIR/methods.rs:406:13 | -401 | let _ = opt.unwrap(); +406 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From ad164939ed1cdd7164683814f8411d20d49e090b Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Sun, 14 Jan 2018 20:04:34 +0000 Subject: Check that we're calling Iterator::fold --- clippy_lints/src/methods.rs | 6 +++++- tests/ui/methods.rs | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9661a6011bd..98dfb3ad980 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1126,7 +1126,11 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir } fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { - // DONOTMERGE: What if this is just some other method called fold? + // Check that this is a call to Iterator::fold rather than just some function called fold + if !match_trait_method(cx, expr, &paths::ITERATOR) { + return; + } + assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 8cffbf76924..ae347269430 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -385,17 +385,17 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -/// Checks implementation of the `FOLD_ANY` lint +/// Should trigger the `FOLD_ANY` lint fn fold_any() { let _ = (0..3).fold(false, |acc, x| acc || x > 2); } -/// Checks implementation of the `FOLD_ANY` lint +/// Should not trigger the `FOLD_ANY` lint as the initial value is not the literal `false` fn fold_any_ignores_initial_value_of_true() { let _ = (0..3).fold(true, |acc, x| acc || x > 2); } -/// Checks implementation of the `FOLD_ANY` lint +/// Should not trigger the `FOLD_ANY` lint as the accumulator is not integer valued fn fold_any_ignores_non_boolean_accumalator() { let _ = (0..3).fold(0, |acc, x| acc + if x > 2 { 1 } else { 0 }); } -- cgit 1.4.1-3-g733a5 From 16158139605059b76bf72f948e90f063ee918414 Mon Sep 17 00:00:00 2001 From: Adam Lusch Date: Sun, 14 Jan 2018 19:58:09 -0800 Subject: Moves `clone_on_ref_ptr` to be a restriction lint Also updates the suggestion to include the full type (e.g. `Arc::clone(&rc)`) and adds a case using trait objects to the UI tests. --- clippy_lints/src/methods.rs | 39 ++++++++++++++++++++------------------- tests/ui/unnecessary_clone.rs | 8 +++++++- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 64335f81a63..8803c4e3019 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -361,9 +361,8 @@ declare_lint! { /// ```rust /// x.clone() /// ``` -declare_lint! { +declare_restriction_lint! { pub CLONE_ON_REF_PTR, - Warn, "using 'clone' on a ref-counted pointer" } @@ -1013,24 +1012,26 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(arg)); - let caller_type = if match_type(cx, obj_ty, &paths::RC) { - "Rc" - } else if match_type(cx, obj_ty, &paths::ARC) { - "Arc" - } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { - "Weak" - } else { - return; - }; + if let ty::TyAdt(_, subst) = obj_ty.sty { + let caller_type = if match_type(cx, obj_ty, &paths::RC) { + "Rc" + } else if match_type(cx, obj_ty, &paths::ARC) { + "Arc" + } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { + "Weak" + } else { + return; + }; - span_lint_and_sugg( - cx, - CLONE_ON_REF_PTR, - expr.span, - "using '.clone()' on a ref-counted pointer", - "try this", - format!("{}::clone(&{})", caller_type, snippet(cx, arg.span, "_")), - ); + span_lint_and_sugg( + cx, + CLONE_ON_REF_PTR, + expr.span, + "using '.clone()' on a ref-counted pointer", + "try this", + format!("{}<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), + ); + } } diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index f33def9eb4e..96166ed4f13 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -1,3 +1,4 @@ +#![warn(clone_on_ref_ptr)] #![allow(unused)] use std::collections::HashSet; @@ -5,6 +6,10 @@ use std::collections::VecDeque; use std::rc::{self, Rc}; use std::sync::{self, Arc}; +trait SomeTrait {} +struct SomeImpl; +impl SomeTrait for SomeImpl {} + fn main() {} fn clone_on_copy() { @@ -34,7 +39,8 @@ fn clone_on_ref_ptr() { arc_weak.clone(); sync::Weak::clone(&arc_weak); - + let x = Arc::new(SomeImpl); + let _: Arc = x.clone(); } fn clone_on_copy_generic(t: T) { -- cgit 1.4.1-3-g733a5 From 30de2e71065dc0af710de34d72db20679ddd5c6a Mon Sep 17 00:00:00 2001 From: Adam Lusch Date: Sun, 14 Jan 2018 20:10:36 -0800 Subject: Update UI test expected output --- tests/ui/unnecessary_clone.stderr | 58 +++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 437df1ee97c..298a9393486 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,75 +1,81 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:11:5 + --> $DIR/unnecessary_clone.rs:16:5 | -11 | 42.clone(); +16 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:15:5 + --> $DIR/unnecessary_clone.rs:20:5 | -15 | (&42).clone(); +20 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:25:5 + --> $DIR/unnecessary_clone.rs:30:5 | -25 | rc.clone(); - | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` +30 | rc.clone(); + | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` | = note: `-D clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:28:5 + --> $DIR/unnecessary_clone.rs:33:5 | -28 | arc.clone(); - | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` +33 | arc.clone(); + | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:31:5 + --> $DIR/unnecessary_clone.rs:36:5 | -31 | rcweak.clone(); - | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` +36 | rcweak.clone(); + | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:34:5 + --> $DIR/unnecessary_clone.rs:39:5 | -34 | arc_weak.clone(); - | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` +39 | arc_weak.clone(); + | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:43:29 + | +43 | let _: Arc = x.clone(); + | ^^^^^^^^^ help: try this: `Arc::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:41:5 + --> $DIR/unnecessary_clone.rs:47:5 | -41 | t.clone(); +47 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:43:5 + --> $DIR/unnecessary_clone.rs:49:5 | -43 | Some(t).clone(); +49 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:49:22 + --> $DIR/unnecessary_clone.rs:55:22 | -49 | let z: &Vec<_> = y.clone(); +55 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | = note: `-D clone-double-ref` implied by `-D warnings` help: try dereferencing it | -49 | let z: &Vec<_> = &(*y).clone(); +55 | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -49 | let z: &Vec<_> = &std::vec::Vec::clone(y); +55 | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:56:27 + --> $DIR/unnecessary_clone.rs:62:27 | -56 | let v2 : Vec = v.iter().cloned().collect(); +62 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-cloned-collect` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From f343cd22f63d0d769dd3bfd44b53347d2d4a58c0 Mon Sep 17 00:00:00 2001 From: Adam Lusch Date: Sun, 14 Jan 2018 20:19:55 -0800 Subject: Adds the missing turbofish --- clippy_lints/src/methods.rs | 2 +- tests/ui/unnecessary_clone.stderr | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 8803c4e3019..8a92e49340f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1029,7 +1029,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { expr.span, "using '.clone()' on a ref-counted pointer", "try this", - format!("{}<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), + format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), ); } } diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 298a9393486..bb78bfa164e 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -16,7 +16,7 @@ error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:30:5 | 30 | rc.clone(); - | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` + | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | = note: `-D clone-on-ref-ptr` implied by `-D warnings` @@ -24,25 +24,25 @@ error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:33:5 | 33 | arc.clone(); - | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` + | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:36:5 | 36 | rcweak.clone(); - | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` + | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:39:5 | 39 | arc_weak.clone(); - | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` + | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:43:29 | 43 | let _: Arc = x.clone(); - | ^^^^^^^^^ help: try this: `Arc::clone(&x)` + | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:47:5 -- cgit 1.4.1-3-g733a5 From 40c6f431da2133e743570cf2ab870741fd4aeb28 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Sat, 16 Dec 2017 14:37:44 -0600 Subject: add new lint else_if_without_else --- clippy_lints/src/else_if_without_else.rs | 70 ++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ tests/ui/else_if_without_else.rs | 50 +++++++++++++++++++++++ tests/ui/else_if_without_else.stderr | 20 +++++++++ 4 files changed, 143 insertions(+) create mode 100644 clippy_lints/src/else_if_without_else.rs create mode 100644 tests/ui/else_if_without_else.rs create mode 100644 tests/ui/else_if_without_else.stderr diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs new file mode 100644 index 00000000000..b354fe70596 --- /dev/null +++ b/clippy_lints/src/else_if_without_else.rs @@ -0,0 +1,70 @@ +//! lint on if expressions with an else if, but without a final else branch + +use rustc::lint::*; +use syntax::ast::*; + +use utils::{in_external_macro, span_lint_and_sugg}; + +/// **What it does:** Checks for usage of if expressions with an `else if` branch, +/// but without a final `else` branch. +/// +/// **Why is this bad?** Some coding guidelines require this (e.g. MISRA-C:2004 Rule 14.10). +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// if x.is_positive() { +/// a(); +/// } else if x.is_negative() { +/// b(); +/// } +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// if x.is_positive() { +/// a(); +/// } else if x.is_negative() { +/// b(); +/// } else { +/// // we don't care about zero +/// } +/// ``` +declare_restriction_lint! { + pub ELSE_IF_WITHOUT_ELSE, + "if expression with an `else if`, but without a final `else` branch" +} + +#[derive(Copy, Clone)] +pub struct ElseIfWithoutElse; + +impl LintPass for ElseIfWithoutElse { + fn get_lints(&self) -> LintArray { + lint_array!(ELSE_IF_WITHOUT_ELSE) + } +} + +impl EarlyLintPass for ElseIfWithoutElse { + fn check_expr(&mut self, cx: &EarlyContext, mut item: &Expr) { + if in_external_macro(cx, item.span) { + return; + } + + while let ExprKind::If(_, _, Some(ref els)) = item.node { + if let ExprKind::If(_, _, None) = els.node { + span_lint_and_sugg( + cx, + ELSE_IF_WITHOUT_ELSE, + els.span, + "if expression with an `else if`, but without a final `else`", + "add an `else` block here", + "".to_string() + ); + } + + item = els; + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 13760e8c0fb..11afefd6d4b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -88,6 +88,7 @@ pub mod derive; pub mod doc; pub mod double_parens; pub mod drop_forget_ref; +pub mod else_if_without_else; pub mod empty_enum; pub mod entry; pub mod enum_clike; @@ -329,6 +330,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); + reg.register_early_lint_pass(box else_if_without_else::ElseIfWithoutElse); reg.register_early_lint_pass(box int_plus_one::IntPlusOne); reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); @@ -369,6 +371,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { arithmetic::INTEGER_ARITHMETIC, array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, + else_if_without_else::ELSE_IF_WITHOUT_ELSE, misc::FLOAT_CMP_CONST, ]); diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs new file mode 100644 index 00000000000..4f019819eff --- /dev/null +++ b/tests/ui/else_if_without_else.rs @@ -0,0 +1,50 @@ +#![warn(clippy)] +#![warn(else_if_without_else)] + +fn bla1() -> bool { unimplemented!() } +fn bla2() -> bool { unimplemented!() } +fn bla3() -> bool { unimplemented!() } + +fn main() { + if bla1() { + println!("if"); + } + + if bla1() { + println!("if"); + } else { + println!("else"); + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if"); + } else { + println!("else") + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else if bla3() { + println!("else if 2"); + } else { + println!("else") + } + + if bla1() { + println!("if"); + } else if bla2() { //~ ERROR else if without else + println!("else if"); + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else if bla3() { //~ ERROR else if without else + println!("else if 2"); + } +} diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr new file mode 100644 index 00000000000..2395c2afde1 --- /dev/null +++ b/tests/ui/else_if_without_else.stderr @@ -0,0 +1,20 @@ +error: if expression with an `else if`, but without a final `else` + --> $DIR/else_if_without_else.rs:39:12 + | +39 | } else if bla2() { //~ ERROR else if without else + | ____________^ +40 | | println!("else if"); +41 | | } + | |_____^ help: add an `else` block here + | + = note: `-D else-if-without-else` implied by `-D warnings` + +error: if expression with an `else if`, but without a final `else` + --> $DIR/else_if_without_else.rs:47:12 + | +47 | } else if bla3() { //~ ERROR else if without else + | ____________^ +48 | | println!("else if 2"); +49 | | } + | |_____^ help: add an `else` block here + -- cgit 1.4.1-3-g733a5 From d011dae96dccc119e65c5ff9417522f613398928 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 15 Jan 2018 12:07:38 +0100 Subject: Rustup --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/missing_doc.rs | 1 - clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/utils/inspector.rs | 3 --- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffa7f89eb50..77e9babf9d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.180 +* Rustup to *rustc 1.25.0-nightly (3f92e8d89 2018-01-14)* + ## 0.0.179 * Rustup to *rustc 1.25.0-nightly (61452e506 2018-01-09)* @@ -670,6 +673,7 @@ All notable changes to this project will be documented in this file. [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro +[`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts [`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used [`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop diff --git a/Cargo.toml b/Cargo.toml index 701c27bf26d..e2a4f0f1fbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.179" +version = "0.0.180" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.179", path = "clippy_lints" } +clippy_lints = { version = "0.0.180", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 2d5038abd6b..87d7c7aee66 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.179" +version = "0.0.180" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 12e5ffa0651..3df037f3329 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { use rustc::hir::map::Node::*; let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { - matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _) | hir::ItemAutoImpl(..)) + matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _)) } else { false }; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index ecc8f50d6a0..82df78ec234 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -143,7 +143,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemGlobalAsm(..) => "an assembly blob", hir::ItemTy(..) => "a type alias", hir::ItemUnion(..) => "a union", - hir::ItemAutoImpl(..) | hir::ItemExternCrate(..) | hir::ItemForeignMod(..) | hir::ItemImpl(..) | diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c7410d29df4..f7c93e7907a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Exclude non-inherent impls if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { - if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemAutoImpl(..) | + if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemTrait(..)) { return; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index fa6681ef078..9ade2778e0c 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -406,9 +406,6 @@ fn print_item(cx: &LateContext, item: &hir::Item) { hir::ItemTraitAlias(..) => { println!("trait alias"); } - hir::ItemAutoImpl(_, ref _trait_ref) => { - println!("auto impl"); - }, hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => { println!("trait impl"); }, -- cgit 1.4.1-3-g733a5 From 28c3d0321aea44716b7898ed29f6dcc4eb1dfc74 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 16 Jan 2018 08:52:14 +0100 Subject: Update changed test output from rustc --- tests/ui/conf_bad_arg.stderr | 2 +- tests/ui/conf_bad_toml.stderr | 2 +- tests/ui/conf_bad_type.stderr | 2 +- tests/ui/conf_french_blacklisted_name.stderr | 2 +- tests/ui/conf_path_non_string.stderr | 2 +- tests/ui/conf_unknown_key.stderr | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index d91729039b1..66c32aed07a 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_bad_arg.rs:4:1 | 4 | #![plugin(clippy(conf_file))] diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index 45477ff0855..f2a741c7075 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_bad_toml.rs:4:1 | 4 | #![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 0fa40cfca9b..679418f38b7 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_bad_type.rs:4:1 | 4 | #![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index f7eb174f9a6..71c0d578a6c 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_french_blacklisted_name.rs:2:1 | 2 | #![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index 4b15b5d0e17..f1f679e6b0a 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_path_non_string.rs:3:1 | 3 | #![plugin(clippy(conf_file=42))] diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index c525366c129..fc1c33426f5 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: compiler plugins are experimental and possibly buggy (see issue #29597) +error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) --> $DIR/conf_unknown_key.rs:4:1 | 4 | #![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] -- cgit 1.4.1-3-g733a5 From 647da97622a4df64b4e67a2b11a73f60035874a9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 16 Jan 2018 14:01:07 +0100 Subject: Lint for numeric literals that have a better representation in another format --- clippy_lints/src/lib.rs | 12 +- clippy_lints/src/literal_digit_grouping.rs | 355 ---------------------- clippy_lints/src/literal_representation.rs | 471 +++++++++++++++++++++++++++++ tests/ui/bad_literal_representation.rs | 23 ++ tests/ui/bad_literal_representation.stderr | 97 ++++++ tests/ui/drop_forget_copy.rs | 2 +- tests/ui/identity_op.rs | 2 +- tests/ui/identity_op.stderr | 4 +- 8 files changed, 602 insertions(+), 364 deletions(-) delete mode 100644 clippy_lints/src/literal_digit_grouping.rs create mode 100644 clippy_lints/src/literal_representation.rs create mode 100644 tests/ui/bad_literal_representation.rs create mode 100644 tests/ui/bad_literal_representation.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 13760e8c0fb..f893a3d45e3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -116,7 +116,7 @@ pub mod large_enum_variant; pub mod len_zero; pub mod let_if_seq; pub mod lifetimes; -pub mod literal_digit_grouping; +pub mod literal_representation; pub mod loops; pub mod map_clone; pub mod matches; @@ -353,7 +353,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); - reg.register_early_lint_pass(box literal_digit_grouping::LiteralDigitGrouping); + reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); + reg.register_early_lint_pass(box literal_representation::LiteralRepresentation); reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::Pass); @@ -482,9 +483,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { let_if_seq::USELESS_LET_IF_SEQ, lifetimes::NEEDLESS_LIFETIMES, lifetimes::UNUSED_LIFETIMES, - literal_digit_grouping::INCONSISTENT_DIGIT_GROUPING, - literal_digit_grouping::LARGE_DIGIT_GROUPS, - literal_digit_grouping::UNREADABLE_LITERAL, + literal_representation::INCONSISTENT_DIGIT_GROUPING, + literal_representation::LARGE_DIGIT_GROUPS, + literal_representation::UNREADABLE_LITERAL, + literal_representation::BAD_LITERAL_REPRESENTATION, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_INTO_ITER_LOOP, diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs deleted file mode 100644 index 011b5ec1d5e..00000000000 --- a/clippy_lints/src/literal_digit_grouping.rs +++ /dev/null @@ -1,355 +0,0 @@ -//! Lints concerned with the grouping of digits with underscores in integral or -//! floating-point literal expressions. - -use rustc::lint::*; -use syntax::ast::*; -use syntax_pos; -use utils::{in_external_macro, snippet_opt, span_help_and_lint}; - -/// **What it does:** Warns if a long integral or floating-point constant does -/// not contain underscores. -/// -/// **Why is this bad?** Reading long numbers is difficult without separators. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ```rust -/// 61864918973511 -/// ``` -declare_lint! { - pub UNREADABLE_LITERAL, - Warn, - "long integer literal without underscores" -} - -/// **What it does:** Warns if an integral or floating-point constant is -/// grouped inconsistently with underscores. -/// -/// **Why is this bad?** Readers may incorrectly interpret inconsistently -/// grouped digits. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ```rust -/// 618_64_9189_73_511 -/// ``` -declare_lint! { - pub INCONSISTENT_DIGIT_GROUPING, - Warn, - "integer literals with digits grouped inconsistently" -} - -/// **What it does:** Warns if the digits of an integral or floating-point -/// constant are grouped into groups that -/// are too large. -/// -/// **Why is this bad?** Negatively impacts readability. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ```rust -/// 6186491_8973511 -/// ``` -declare_lint! { - pub LARGE_DIGIT_GROUPS, - Warn, - "grouping digits into groups that are too large" -} - -#[derive(Debug)] -enum Radix { - Binary, - Octal, - Decimal, - Hexadecimal, -} - -impl Radix { - /// Return a reasonable digit group size for this radix. - pub fn suggest_grouping(&self) -> usize { - match *self { - Radix::Binary | Radix::Hexadecimal => 4, - Radix::Octal | Radix::Decimal => 3, - } - } -} - -#[derive(Debug)] -struct DigitInfo<'a> { - /// Characters of a literal between the radix prefix and type suffix. - pub digits: &'a str, - /// Which radix the literal was represented in. - pub radix: Radix, - /// The radix prefix, if present. - pub prefix: Option<&'a str>, - /// The type suffix, including preceding underscore if present. - pub suffix: Option<&'a str>, - /// True for floating-point literals. - pub float: bool, -} - -impl<'a> DigitInfo<'a> { - pub fn new(lit: &'a str, float: bool) -> Self { - // Determine delimiter for radix prefix, if present, and radix. - let radix = if lit.starts_with("0x") { - Radix::Hexadecimal - } else if lit.starts_with("0b") { - Radix::Binary - } else if lit.starts_with("0o") { - Radix::Octal - } else { - Radix::Decimal - }; - - // Grab part of the literal after prefix, if present. - let (prefix, sans_prefix) = if let Radix::Decimal = radix { - (None, lit) - } else { - let (p, s) = lit.split_at(2); - (Some(p), s) - }; - - let mut last_d = '\0'; - for (d_idx, d) in sans_prefix.char_indices() { - if !float && (d == 'i' || d == 'u') || float && d == 'f' { - let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; - let (digits, suffix) = sans_prefix.split_at(suffix_start); - return Self { - digits: digits, - radix: radix, - prefix: prefix, - suffix: Some(suffix), - float: float, - }; - } - last_d = d - } - - // No suffix found - Self { - digits: sans_prefix, - radix: radix, - prefix: prefix, - suffix: None, - float: float, - } - } - - /// Returns digits grouped in a sensible way. - fn grouping_hint(&self) -> String { - let group_size = self.radix.suggest_grouping(); - if self.digits.contains('.') { - let mut parts = self.digits.split('.'); - let int_part_hint = parts - .next() - .expect("split always returns at least one element") - .chars() - .rev() - .filter(|&c| c != '_') - .collect::>() - .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) - .rev() - .collect::>() - .join("_"); - let frac_part_hint = parts - .next() - .expect("already checked that there is a `.`") - .chars() - .filter(|&c| c != '_') - .collect::>() - .chunks(group_size) - .map(|chunk| chunk.into_iter().collect()) - .collect::>() - .join("_"); - format!("{}.{}{}", int_part_hint, frac_part_hint, self.suffix.unwrap_or("")) - } else { - let hint = self.digits - .chars() - .rev() - .filter(|&c| c != '_') - .collect::>() - .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) - .rev() - .collect::>() - .join("_"); - format!("{}{}{}", self.prefix.unwrap_or(""), hint, self.suffix.unwrap_or("")) - } - } -} - -enum WarningType { - UnreadableLiteral, - InconsistentDigitGrouping, - LargeDigitGroups, -} - - -impl WarningType { - pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { - match *self { - WarningType::UnreadableLiteral => span_help_and_lint( - cx, - UNREADABLE_LITERAL, - *span, - "long literal lacking separators", - &format!("consider: {}", grouping_hint), - ), - WarningType::LargeDigitGroups => span_help_and_lint( - cx, - LARGE_DIGIT_GROUPS, - *span, - "digit groups should be smaller", - &format!("consider: {}", grouping_hint), - ), - WarningType::InconsistentDigitGrouping => span_help_and_lint( - cx, - INCONSISTENT_DIGIT_GROUPING, - *span, - "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint), - ), - }; - } -} - -#[derive(Copy, Clone)] -pub struct LiteralDigitGrouping; - -impl LintPass for LiteralDigitGrouping { - fn get_lints(&self) -> LintArray { - lint_array!(UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, LARGE_DIGIT_GROUPS) - } -} - -impl EarlyLintPass for LiteralDigitGrouping { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if in_external_macro(cx, expr.span) { - return; - } - - if let ExprKind::Lit(ref lit) = expr.node { - self.check_lit(cx, lit) - } - } -} - -impl LiteralDigitGrouping { - fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { - // Lint integral literals. - if_chain! { - if let LitKind::Int(..) = lit.node; - if let Some(src) = snippet_opt(cx, lit.span); - if let Some(firstch) = src.chars().next(); - if char::to_digit(firstch, 10).is_some(); - then { - let digit_info = DigitInfo::new(&src, false); - let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { - warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) - }); - } - } - - // Lint floating-point literals. - if_chain! { - if let LitKind::Float(..) = lit.node; - if let Some(src) = snippet_opt(cx, lit.span); - if let Some(firstch) = src.chars().next(); - if char::to_digit(firstch, 10).is_some(); - then { - let digit_info = DigitInfo::new(&src, true); - // Separate digits into integral and fractional parts. - let parts: Vec<&str> = digit_info - .digits - .split_terminator('.') - .collect(); - - // Lint integral and fractional parts separately, and then check consistency of digit - // groups if both pass. - let _ = Self::do_lint(parts[0]) - .map(|integral_group_size| { - if parts.len() > 1 { - // Lint the fractional part of literal just like integral part, but reversed. - let fractional_part = &parts[1].chars().rev().collect::(); - let _ = Self::do_lint(fractional_part) - .map(|fractional_group_size| { - let consistent = Self::parts_consistent(integral_group_size, - fractional_group_size, - parts[0].len(), - parts[1].len()); - if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), - cx, - &lit.span); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), - cx, - &lit.span)); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); - } - } - } - - /// Given the sizes of the digit groups of both integral and fractional - /// parts, and the length - /// of both parts, determine if the digits have been grouped consistently. - fn parts_consistent(int_group_size: usize, frac_group_size: usize, int_size: usize, frac_size: usize) -> bool { - match (int_group_size, frac_group_size) { - // No groups on either side of decimal point - trivially consistent. - (0, 0) => true, - // Integral part has grouped digits, fractional part does not. - (_, 0) => frac_size <= int_group_size, - // Fractional part has grouped digits, integral part does not. - (0, _) => int_size <= frac_group_size, - // Both parts have grouped digits. Groups should be the same size. - (_, _) => int_group_size == frac_group_size, - } - } - - /// Performs lint on `digits` (no decimal point) and returns the group - /// size on success or `WarningType` when emitting a warning. - fn do_lint(digits: &str) -> Result { - // Grab underscore indices with respect to the units digit. - let underscore_positions: Vec = digits - .chars() - .rev() - .enumerate() - .filter_map(|(idx, digit)| if digit == '_' { Some(idx) } else { None }) - .collect(); - - if underscore_positions.is_empty() { - // Check if literal needs underscores. - if digits.len() > 4 { - Err(WarningType::UnreadableLiteral) - } else { - Ok(0) - } - } else { - // Check consistency and the sizes of the groups. - let group_size = underscore_positions[0]; - let consistent = underscore_positions - .windows(2) - .all(|ps| ps[1] - ps[0] == group_size + 1) - // number of digits to the left of the last group cannot be bigger than group size. - && (digits.len() - underscore_positions.last() - .expect("there's at least one element") <= group_size + 1); - - if !consistent { - return Err(WarningType::InconsistentDigitGrouping); - } else if group_size > 4 { - return Err(WarningType::LargeDigitGroups); - } - Ok(group_size) - } - } -} diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs new file mode 100644 index 00000000000..91f01bae257 --- /dev/null +++ b/clippy_lints/src/literal_representation.rs @@ -0,0 +1,471 @@ +//! Lints concerned with the grouping of digits with underscores in integral or +//! floating-point literal expressions. + +use rustc::lint::*; +use syntax::ast::*; +use syntax_pos; +use utils::{in_external_macro, snippet_opt, span_help_and_lint}; + +/// **What it does:** Warns if a long integral or floating-point constant does +/// not contain underscores. +/// +/// **Why is this bad?** Reading long numbers is difficult without separators. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// 61864918973511 +/// ``` +declare_lint! { + pub UNREADABLE_LITERAL, + Warn, + "long integer literal without underscores" +} + +/// **What it does:** Warns if an integral or floating-point constant is +/// grouped inconsistently with underscores. +/// +/// **Why is this bad?** Readers may incorrectly interpret inconsistently +/// grouped digits. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// 618_64_9189_73_511 +/// ``` +declare_lint! { + pub INCONSISTENT_DIGIT_GROUPING, + Warn, + "integer literals with digits grouped inconsistently" +} + +/// **What it does:** Warns if the digits of an integral or floating-point +/// constant are grouped into groups that +/// are too large. +/// +/// **Why is this bad?** Negatively impacts readability. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// 6186491_8973511 +/// ``` +declare_lint! { + pub LARGE_DIGIT_GROUPS, + Warn, + "grouping digits into groups that are too large" +} + +/// **What it does:** Warns if there is a better representation for a numeric literal. +/// +/// **Why is this bad?** Especially for big powers of 2 a hexadecimal representation is more +/// readable than a decimal representation. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// `255` => `0xFF` +/// `65_535` => `0xFFFF` +/// `4_042_322_160` => `0xF0F0_F0F0` +declare_lint! { + pub BAD_LITERAL_REPRESENTATION, + Warn, + "using decimal representation when hexadecimal would be better" +} + +#[derive(Debug, PartialEq)] +enum Radix { + Binary, + Octal, + Decimal, + Hexadecimal, +} + +impl Radix { + /// Return a reasonable digit group size for this radix. + pub fn suggest_grouping(&self) -> usize { + match *self { + Radix::Binary | Radix::Hexadecimal => 4, + Radix::Octal | Radix::Decimal => 3, + } + } +} + +#[derive(Debug)] +struct DigitInfo<'a> { + /// Characters of a literal between the radix prefix and type suffix. + pub digits: &'a str, + /// Which radix the literal was represented in. + pub radix: Radix, + /// The radix prefix, if present. + pub prefix: Option<&'a str>, + /// The type suffix, including preceding underscore if present. + pub suffix: Option<&'a str>, + /// True for floating-point literals. + pub float: bool, +} + +impl<'a> DigitInfo<'a> { + pub fn new(lit: &'a str, float: bool) -> Self { + // Determine delimiter for radix prefix, if present, and radix. + let radix = if lit.starts_with("0x") { + Radix::Hexadecimal + } else if lit.starts_with("0b") { + Radix::Binary + } else if lit.starts_with("0o") { + Radix::Octal + } else { + Radix::Decimal + }; + + // Grab part of the literal after prefix, if present. + let (prefix, sans_prefix) = if let Radix::Decimal = radix { + (None, lit) + } else { + let (p, s) = lit.split_at(2); + (Some(p), s) + }; + + let mut last_d = '\0'; + for (d_idx, d) in sans_prefix.char_indices() { + if !float && (d == 'i' || d == 'u') || float && d == 'f' { + let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; + let (digits, suffix) = sans_prefix.split_at(suffix_start); + return Self { + digits: digits, + radix: radix, + prefix: prefix, + suffix: Some(suffix), + float: float, + }; + } + last_d = d + } + + // No suffix found + Self { + digits: sans_prefix, + radix: radix, + prefix: prefix, + suffix: None, + float: float, + } + } + + /// Returns digits grouped in a sensible way. + fn grouping_hint(&self) -> String { + let group_size = self.radix.suggest_grouping(); + if self.digits.contains('.') { + let mut parts = self.digits.split('.'); + let int_part_hint = parts + .next() + .expect("split always returns at least one element") + .chars() + .rev() + .filter(|&c| c != '_') + .collect::>() + .chunks(group_size) + .map(|chunk| chunk.into_iter().rev().collect()) + .rev() + .collect::>() + .join("_"); + let frac_part_hint = parts + .next() + .expect("already checked that there is a `.`") + .chars() + .filter(|&c| c != '_') + .collect::>() + .chunks(group_size) + .map(|chunk| chunk.into_iter().collect()) + .collect::>() + .join("_"); + format!( + "{}.{}{}", + int_part_hint, + frac_part_hint, + self.suffix.unwrap_or("") + ) + } else { + let hint = self.digits + .chars() + .rev() + .filter(|&c| c != '_') + .collect::>() + .chunks(group_size) + .map(|chunk| chunk.into_iter().rev().collect()) + .rev() + .collect::>() + .join("_"); + format!( + "{}{}{}", + self.prefix.unwrap_or(""), + hint, + self.suffix.unwrap_or("") + ) + } + } +} + +enum WarningType { + UnreadableLiteral, + InconsistentDigitGrouping, + LargeDigitGroups, + BadRepresentation, +} + +impl WarningType { + pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { + match *self { + WarningType::UnreadableLiteral => span_help_and_lint( + cx, + UNREADABLE_LITERAL, + *span, + "long literal lacking separators", + &format!("consider: {}", grouping_hint), + ), + WarningType::LargeDigitGroups => span_help_and_lint( + cx, + LARGE_DIGIT_GROUPS, + *span, + "digit groups should be smaller", + &format!("consider: {}", grouping_hint), + ), + WarningType::InconsistentDigitGrouping => span_help_and_lint( + cx, + INCONSISTENT_DIGIT_GROUPING, + *span, + "digits grouped inconsistently by underscores", + &format!("consider: {}", grouping_hint), + ), + WarningType::BadRepresentation => span_help_and_lint( + cx, + BAD_LITERAL_REPRESENTATION, + *span, + "bad representation of integer literal", + &format!("consider: {}", grouping_hint), + ), + }; + } +} + +#[derive(Copy, Clone)] +pub struct LiteralDigitGrouping; + +impl LintPass for LiteralDigitGrouping { + fn get_lints(&self) -> LintArray { + lint_array!( + UNREADABLE_LITERAL, + INCONSISTENT_DIGIT_GROUPING, + LARGE_DIGIT_GROUPS + ) + } +} + +impl EarlyLintPass for LiteralDigitGrouping { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if in_external_macro(cx, expr.span) { + return; + } + + if let ExprKind::Lit(ref lit) = expr.node { + self.check_lit(cx, lit) + } + } +} + +impl LiteralDigitGrouping { + fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { + // Lint integral literals. + if_chain! { + if let LitKind::Int(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, false); + let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { + warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + }); + } + } + + // Lint floating-point literals. + if_chain! { + if let LitKind::Float(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, true); + // Separate digits into integral and fractional parts. + let parts: Vec<&str> = digit_info + .digits + .split_terminator('.') + .collect(); + + // Lint integral and fractional parts separately, and then check consistency of digit + // groups if both pass. + let _ = Self::do_lint(parts[0]) + .map(|integral_group_size| { + if parts.len() > 1 { + // Lint the fractional part of literal just like integral part, but reversed. + let fractional_part = &parts[1].chars().rev().collect::(); + let _ = Self::do_lint(fractional_part) + .map(|fractional_group_size| { + let consistent = Self::parts_consistent(integral_group_size, + fractional_group_size, + parts[0].len(), + parts[1].len()); + if !consistent { + WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), + cx, + &lit.span); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), + cx, + &lit.span)); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); + } + } + } + + /// Given the sizes of the digit groups of both integral and fractional + /// parts, and the length + /// of both parts, determine if the digits have been grouped consistently. + fn parts_consistent(int_group_size: usize, frac_group_size: usize, int_size: usize, frac_size: usize) -> bool { + match (int_group_size, frac_group_size) { + // No groups on either side of decimal point - trivially consistent. + (0, 0) => true, + // Integral part has grouped digits, fractional part does not. + (_, 0) => frac_size <= int_group_size, + // Fractional part has grouped digits, integral part does not. + (0, _) => int_size <= frac_group_size, + // Both parts have grouped digits. Groups should be the same size. + (_, _) => int_group_size == frac_group_size, + } + } + + /// Performs lint on `digits` (no decimal point) and returns the group + /// size on success or `WarningType` when emitting a warning. + fn do_lint(digits: &str) -> Result { + // Grab underscore indices with respect to the units digit. + let underscore_positions: Vec = digits + .chars() + .rev() + .enumerate() + .filter_map(|(idx, digit)| if digit == '_' { Some(idx) } else { None }) + .collect(); + + if underscore_positions.is_empty() { + // Check if literal needs underscores. + if digits.len() > 4 { + Err(WarningType::UnreadableLiteral) + } else { + Ok(0) + } + } else { + // Check consistency and the sizes of the groups. + let group_size = underscore_positions[0]; + let consistent = underscore_positions + .windows(2) + .all(|ps| ps[1] - ps[0] == group_size + 1) + // number of digits to the left of the last group cannot be bigger than group size. + && (digits.len() - underscore_positions.last() + .expect("there's at least one element") <= group_size + 1); + + if !consistent { + return Err(WarningType::InconsistentDigitGrouping); + } else if group_size > 4 { + return Err(WarningType::LargeDigitGroups); + } + Ok(group_size) + } + } +} + +#[derive(Copy, Clone)] +pub struct LiteralRepresentation; + +impl LintPass for LiteralRepresentation { + fn get_lints(&self) -> LintArray { + lint_array!(BAD_LITERAL_REPRESENTATION) + } +} + +impl EarlyLintPass for LiteralRepresentation { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if in_external_macro(cx, expr.span) { + return; + } + + if let ExprKind::Lit(ref lit) = expr.node { + self.check_lit(cx, lit) + } + } +} + +impl LiteralRepresentation { + fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { + // Lint integral literals. + if_chain! { + if let LitKind::Int(..) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, false); + if digit_info.radix == Radix::Decimal { + let hex = format!("{:#X}", digit_info.digits + .chars() + .filter(|&c| c != '_') + .collect::() + .parse::().unwrap()); + let digit_info = DigitInfo::new(&hex[..], false); + let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { + warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + }); + } + } + } + } + + fn do_lint(digits: &str) -> Result<(), WarningType> { + if digits.len() == 2 && digits == "FF" { + return Err(WarningType::BadRepresentation); + } else if digits.len() == 3 { + // Lint for Literals with a hex-representation of 3 digits + let f = &digits[0..1]; // first digit + let s = &digits[1..]; // suffix + // Powers of 2 minus 1 + if (f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.eq("FF") { + return Err(WarningType::BadRepresentation); + } + } else if digits.len() > 3 { + // Lint for Literals with a hex-representation of 4 digits or more + let f = &digits[0..1]; // first digit + let m = &digits[1..digits.len() - 1]; // middle digits, except last + let s = &digits[1..]; // suffix + // Powers of 2 with a margin of +15/-16 + if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && m.chars().all(|c| c == '0')) + || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && m.chars().all(|c| c == 'F')) + // Lint for representations with only 0s and Fs, while allowing 7 as the first + // digit + || ((f.eq("7") || f.eq("F")) && s.chars().all(|c| c == '0' || c == 'F')) + { + return Err(WarningType::BadRepresentation); + } + } + + Ok(()) + } +} diff --git a/tests/ui/bad_literal_representation.rs b/tests/ui/bad_literal_representation.rs new file mode 100644 index 00000000000..00126152fe1 --- /dev/null +++ b/tests/ui/bad_literal_representation.rs @@ -0,0 +1,23 @@ + + + +#[warn(bad_literal_representation)] +#[allow(unused_variables)] +fn main() { + // Hex: 7F, 80, 100, 800, FFA, F0F3, 7F0F_F00D + let good = (127, 128, 256, 2048, 4090, 61_683, 2_131_750_925); + let bad = ( // Hex: + 255, // 0xFF + 511, // 0x1FF + 1023, // 0x3FF + 2047, // 0x7FF + 4095, // 0xFFF + 4096, // 0x1000 + 16_371, // 0x3FF3 + 32_773, // 0x8005 + 65_280, // 0xFF00 + 2_131_750_927, // 0x7F0F_F00F + 2_147_483_647, // 0x7FFF_FFFF + 4_042_322_160, // 0xF0F0_F0F0 + ); +} diff --git a/tests/ui/bad_literal_representation.stderr b/tests/ui/bad_literal_representation.stderr new file mode 100644 index 00000000000..f57956c23d6 --- /dev/null +++ b/tests/ui/bad_literal_representation.stderr @@ -0,0 +1,97 @@ +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:10:9 + | +10 | 255, // 0xFF + | ^^^ + | + = note: `-D bad-literal-representation` implied by `-D warnings` + = help: consider: 0xFF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:11:9 + | +11 | 511, // 0x1FF + | ^^^ + | + = help: consider: 0x1FF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:12:9 + | +12 | 1023, // 0x3FF + | ^^^^ + | + = help: consider: 0x3FF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:13:9 + | +13 | 2047, // 0x7FF + | ^^^^ + | + = help: consider: 0x7FF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:14:9 + | +14 | 4095, // 0xFFF + | ^^^^ + | + = help: consider: 0xFFF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:15:9 + | +15 | 4096, // 0x1000 + | ^^^^ + | + = help: consider: 0x1000 + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:16:9 + | +16 | 16_371, // 0x3FF3 + | ^^^^^^ + | + = help: consider: 0x3FF3 + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:17:9 + | +17 | 32_773, // 0x8005 + | ^^^^^^ + | + = help: consider: 0x8005 + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:18:9 + | +18 | 65_280, // 0xFF00 + | ^^^^^^ + | + = help: consider: 0xFF00 + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:19:9 + | +19 | 2_131_750_927, // 0x7F0F_F00F + | ^^^^^^^^^^^^^ + | + = help: consider: 0x7F0F_F00F + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:20:9 + | +20 | 2_147_483_647, // 0x7FFF_FFFF + | ^^^^^^^^^^^^^ + | + = help: consider: 0x7FFF_FFFF + +error: bad representation of integer literal + --> $DIR/bad_literal_representation.rs:21:9 + | +21 | 4_042_322_160, // 0xF0F0_F0F0 + | ^^^^^^^^^^^^^ + | + = help: consider: 0xF0F0_F0F0 + diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 9fef06b0ede..a4d38d99c95 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -42,7 +42,7 @@ fn main() { forget(s4); forget(s5); - let a1 = AnotherStruct {x: 255, y: 0, z: vec![1, 2, 3]}; + let a1 = AnotherStruct {x: 0xFF, y: 0, z: vec![1, 2, 3]}; let a2 = &a1; let mut a3 = a1.clone(); let ref a4 = a1; diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 1ed9f974d43..d4bc7df4424 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -29,5 +29,5 @@ fn main() { -1 & x; let u : u8 = 0; - u & 255; + u & 0xFF; } diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index c1ce8d2ec4c..b3f7bb713e6 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -45,6 +45,6 @@ error: the operation is ineffective. Consider reducing it to `x` error: the operation is ineffective. Consider reducing it to `u` --> $DIR/identity_op.rs:32:5 | -32 | u & 255; - | ^^^^^^^ +32 | u & 0xFF; + | ^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 877321ba328918a09bec8f13b4695f0c423ab212 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 16 Jan 2018 15:52:16 +0100 Subject: Add macro check to precedence lint --- clippy_lints/src/precedence.rs | 6 +++++- tests/ui/precedence.rs | 13 ++++++++++++ tests/ui/precedence.stderr | 48 +++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index e06c571b6f6..5d56a927bc0 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{snippet, span_lint_and_sugg}; +use utils::{in_macro, snippet, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: @@ -37,6 +37,10 @@ impl LintPass for Precedence { impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + if in_macro(expr.span) { + return; + } + if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { let span_sugg = |expr: &Expr, sugg| { span_lint_and_sugg( diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 720637c94b5..aacd90cdf92 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -4,6 +4,16 @@ #[warn(precedence)] #[allow(identity_op)] #[allow(eq_op)] + +macro_rules! trip { + ($a:expr) => { + match $a & 0b1111_1111i8 { + 0 => println!("a is zero ({})", $a), + _ => println!("a is {}", $a), + } + }; +} + fn main() { 1 << 2 + 3; 1 + 2 << 3; @@ -22,4 +32,7 @@ fn main() { let _ = -(1f32).abs(); let _ = -(1i32.abs()); let _ = -(1f32.abs()); + + let b = 3; + trip!(b * 8); } diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 26fbd75164d..768983ac35a 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,56 +1,56 @@ error: operator precedence can trip the unwary - --> $DIR/precedence.rs:8:5 - | -8 | 1 << 2 + 3; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` - | - = note: `-D precedence` implied by `-D warnings` + --> $DIR/precedence.rs:18:5 + | +18 | 1 << 2 + 3; + | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` + | + = note: `-D precedence` implied by `-D warnings` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:9:5 - | -9 | 1 + 2 << 3; - | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` + --> $DIR/precedence.rs:19:5 + | +19 | 1 + 2 << 3; + | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:10:5 + --> $DIR/precedence.rs:20:5 | -10 | 4 >> 1 + 1; +20 | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:11:5 + --> $DIR/precedence.rs:21:5 | -11 | 1 + 3 >> 2; +21 | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:12:5 + --> $DIR/precedence.rs:22:5 | -12 | 1 ^ 1 - 1; +22 | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:13:5 + --> $DIR/precedence.rs:23:5 | -13 | 3 | 2 - 1; +23 | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:14:5 + --> $DIR/precedence.rs:24:5 | -14 | 3 & 5 - 2; +24 | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:15:5 + --> $DIR/precedence.rs:25:5 | -15 | -1i32.abs(); +25 | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:16:5 + --> $DIR/precedence.rs:26:5 | -16 | -1f32.abs(); +26 | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` -- cgit 1.4.1-3-g733a5 From 37f62a54f83b094cb5de55345945d1fb58d7d1b0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 16 Jan 2018 20:46:43 +0530 Subject: Show wider and more accurate suggestion for const_static_lifetime fixes #2365 --- clippy_lints/src/const_static_lifetime.rs | 7 ++++--- tests/ui/const_static_lifetime.stderr | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 3ad3be181d2..293d63daaaa 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,6 +1,6 @@ use syntax::ast::{Item, ItemKind, Ty, TyKind}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use utils::{in_macro, span_lint_and_then}; +use utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// @@ -51,14 +51,15 @@ impl StaticConst { TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => { if lifetime.ident.name == "'static" { - let mut sug: String = String::new(); + let snip = snippet(cx, borrow_type.ty.span, ""); + let sugg = format!("&{}", snip); span_lint_and_then( cx, CONST_STATIC_LIFETIME, lifetime.span, "Constants have by default a `'static` lifetime", |db| { - db.span_suggestion(lifetime.span, "consider removing `'static`", sug); + db.span_suggestion(ty.span, "consider removing `'static`", sugg); }, ); } diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index d4558f7b241..448d83ee921 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -2,7 +2,7 @@ error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:4:17 | 4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` | = note: `-D const-static-lifetime` implied by `-D warnings` @@ -10,71 +10,71 @@ error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:8:21 | 8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:10:32 | 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:10:47 | 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:12:18 | 12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:12:30 | 12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:14:17 | 14 | const VAR_SIX: &'static u8 = &5; - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^--- help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:16:29 | 16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:16:39 | 16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:18:20 | 18 | const VAR_HEIGHT: &'static Foo = &Foo {}; - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:20:19 | 20 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:22:19 | 22 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:24:19 | 24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. - | ^^^^^^^ help: consider removing `'static` + | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` -- cgit 1.4.1-3-g733a5 From a64d19cc0e8c1c47dd253b5bcb4a1a619c4ae7d3 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Tue, 16 Jan 2018 21:20:55 +0000 Subject: Fix error span to play nicely with rustfix --- clippy_lints/src/methods.rs | 7 +++++-- clippy_lints/src/utils/mod.rs | 4 ++-- tests/ui/methods.rs | 5 +++++ tests/ui/methods.stderr | 14 ++++++++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 98dfb3ad980..5ff48a25b1c 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -9,7 +9,7 @@ use std::borrow::Cow; use std::fmt; use std::iter; use syntax::ast; -use syntax::codemap::Span; +use syntax::codemap::{Span, BytePos}; use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, @@ -1157,10 +1157,13 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { then { let right_source = snippet(cx, right_expr.span, "EXPR"); + // Span containing `.fold(...)` + let fold_span = fold_args[0].span.next_point().with_hi(fold_args[2].span.hi() + BytePos(1)); + span_lint_and_sugg( cx, FOLD_ANY, - expr.span, + fold_span, // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) "this `.fold` can more succintly be expressed as `.any`", "try", diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 44ebc5aa600..d4f7539cea9 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -606,7 +606,7 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( /// --> $DIR/methods.rs:390:13 /// | /// 390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); -/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` /// | /// = note: `-D fold-any` implied by `-D warnings` /// @@ -1055,4 +1055,4 @@ pub fn get_arg_name(pat: &Pat) -> Option { PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } -} \ No newline at end of file +} diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index ae347269430..d50f8e35fa4 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -400,6 +400,11 @@ fn fold_any_ignores_non_boolean_accumalator() { let _ = (0..3).fold(0, |acc, x| acc + if x > 2 { 1 } else { 0 }); } +/// Should trigger the `FOLD_ANY` lint, with the error span including exactly `.fold(...)` +fn fold_any_span_for_multi_element_chain() { + let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +} + #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index f1746354380..2c03e077d57 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -494,17 +494,23 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `.fold` can more succintly be expressed as `.any` - --> $DIR/methods.rs:390:13 + --> $DIR/methods.rs:390:19 | 390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | = note: `-D fold-any` implied by `-D warnings` +error: this `.fold` can more succintly be expressed as `.any` + --> $DIR/methods.rs:405:34 + | +405 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` + error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:406:13 + --> $DIR/methods.rs:411:13 | -406 | let _ = opt.unwrap(); +411 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From e7567f2eac94006ae92fc0c0435630c2eef07c65 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 17 Jan 2018 07:24:33 +0200 Subject: Made requested changes --- clippy_lints/src/types.rs | 6 +++--- tests/ui/option_option.stderr | 27 +++++++-------------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c8b564e4228..e5109cf3ebb 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -220,12 +220,12 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { if match_type_parameter(cx, qpath, &paths::OPTION) { - span_help_and_lint( + span_lint( cx, OPTION_OPTION, ast_ty.span, - "consider using `Option` instead of `Option>`", - "`Option<_>` is easier to use than `Option`", + "consider using `Option` instead of `Option>` or a custom \ + enum if you need to distinguish all 3 cases", ); return; // don't recurse into the type } diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 514538be167..91f686288dd 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,57 +1,44 @@ -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:1:13 | 1 | fn input(_: Option>) { | ^^^^^^^^^^^^^^^^^^ | = note: `-D option-option` implied by `-D warnings` - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:4:16 | 4 | fn output() -> Option> { | ^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:8:27 | 8 | fn output_nested() -> Vec>> { | ^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:13:30 | 13 | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:18:8 | 18 | x: Option>, | ^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:22:11 | 22 | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -error: consider using `Option` instead of `Option>` +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:23:15 | 23 | Struct{x: Option>}, | ^^^^^^^^^^^^^^^^^^ - | - = help: `Option<_>` is easier to use than `Option` -- cgit 1.4.1-3-g733a5 From 3c4f5bfae23ea80e4a09e6887c94d14139106bdf Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Dec 2017 17:34:11 +0530 Subject: Use rustc_driver::run (fixes #2303) This internally uses monitor() which catches panics and stuff --- src/driver.rs | 83 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 090e69cf027..bc766496cfb 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -12,7 +12,7 @@ extern crate rustc_plugin; extern crate syntax; use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use rustc::session::{config, CompileIncomplete, Session}; +use rustc::session::{config, Session}; use rustc::session::config::{ErrorOutputType, Input}; use std::path::PathBuf; use std::process::Command; @@ -153,47 +153,44 @@ pub fn main() { }) .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - rustc_driver::in_rustc_thread(|| { - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); - if orig_args.len() <= 1 { - std::process::exit(1); - } - if orig_args[1] == "rustc" { - // we still want to be able to invoke it normally though - orig_args.remove(1); - } - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() - } else { - orig_args - .clone() - .into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; - - // this check ensures that dependencies are built but not linted and the final - // crate is - // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS") - .ok() - .map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=metadata"); - - if clippy_enabled { - args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); - } + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + if orig_args[1] == "rustc" { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + // this check ensures that dependencies are built but not linted and the final + // crate is + // linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS") + .ok() + .map_or(false, |val| val == "true") + || orig_args.iter().any(|s| s == "--emit=metadata"); + + if clippy_enabled { + args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + } - let mut ccc = ClippyCompilerCalls::new(clippy_enabled); - let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None); - if let Err(CompileIncomplete::Errored(_)) = result { - std::process::exit(1); - } - }).expect("rustc_thread failed"); + let mut ccc = ClippyCompilerCalls::new(clippy_enabled); + rustc_driver::run(move || { + rustc_driver::run_compiler(&args, &mut ccc, None, None) + }); } -- cgit 1.4.1-3-g733a5 From 4f21b5b11207166dbd8210a0ec7510fc09734fb7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 16 Jan 2018 17:06:27 +0100 Subject: Update changed ui tests --- tests/compile-test.rs | 4 +++- tests/ui/absurd-extreme-comparisons.stderr | 2 ++ tests/ui/approx_const.stderr | 2 ++ tests/ui/arithmetic.stderr | 2 ++ tests/ui/array_indexing.stderr | 2 ++ tests/ui/assign_ops.stderr | 2 ++ tests/ui/assign_ops2.stderr | 2 ++ tests/ui/attrs.stderr | 2 ++ tests/ui/bit_masks.stderr | 2 ++ tests/ui/blacklisted_name.stderr | 2 ++ tests/ui/block_in_if_condition.stderr | 2 ++ tests/ui/bool_comparison.stderr | 2 ++ tests/ui/booleans.stderr | 2 ++ tests/ui/borrow_box.stderr | 2 ++ tests/ui/box_vec.stderr | 2 ++ tests/ui/builtin-type-shadow.stderr | 2 ++ tests/ui/bytecount.stderr | 2 ++ tests/ui/cast.stderr | 2 ++ tests/ui/cast_lossless_float.stderr | 2 ++ tests/ui/cast_lossless_integer.stderr | 2 ++ tests/ui/cast_size.stderr | 2 ++ tests/ui/char_lit_as_u8.stderr | 2 ++ tests/ui/cmp_nan.stderr | 2 ++ tests/ui/cmp_null.stderr | 2 ++ tests/ui/cmp_owned.stderr | 2 ++ tests/ui/collapsible_if.stderr | 2 ++ tests/ui/complex_types.stderr | 2 ++ tests/ui/conf_bad_arg.stderr | 2 ++ tests/ui/conf_bad_toml.stderr | 2 ++ tests/ui/conf_bad_type.stderr | 2 ++ tests/ui/conf_french_blacklisted_name.stderr | 2 ++ tests/ui/conf_path_non_string.stderr | 2 ++ tests/ui/conf_unknown_key.stderr | 2 ++ tests/ui/const_static_lifetime.stderr | 2 ++ tests/ui/copies.stderr | 2 ++ tests/ui/cstring.stderr | 2 ++ tests/ui/cyclomatic_complexity.stderr | 2 ++ tests/ui/cyclomatic_complexity_attr_used.stderr | 2 ++ tests/ui/deprecated.stderr | 2 ++ tests/ui/derive.stderr | 2 ++ tests/ui/diverging_sub_expression.stderr | 2 ++ tests/ui/dlist.stderr | 2 ++ tests/ui/doc.stderr | 2 ++ tests/ui/double_neg.stderr | 2 ++ tests/ui/double_parens.stderr | 2 ++ tests/ui/drop_forget_copy.stderr | 2 ++ tests/ui/drop_forget_ref.stderr | 2 ++ tests/ui/duplicate_underscore_argument.stderr | 2 ++ tests/ui/else_if_without_else.stderr | 2 ++ tests/ui/empty_enum.stderr | 2 ++ tests/ui/entry.stderr | 2 ++ tests/ui/enum_glob_use.stderr | 2 ++ tests/ui/enum_variants.stderr | 2 ++ tests/ui/enums_clike.stderr | 2 ++ tests/ui/eq_op.stderr | 2 ++ tests/ui/erasing_op.stderr | 2 ++ tests/ui/eta.stderr | 2 ++ tests/ui/eval_order_dependence.stderr | 2 ++ tests/ui/explicit_write.stderr | 2 ++ tests/ui/fallible_impl_from.stderr | 2 ++ tests/ui/filter_methods.stderr | 2 ++ tests/ui/float_cmp.stderr | 2 ++ tests/ui/float_cmp_const.stderr | 2 ++ tests/ui/for_loop.stderr | 2 ++ tests/ui/format.stderr | 2 ++ tests/ui/formatting.stderr | 2 ++ tests/ui/functions.stderr | 2 ++ tests/ui/get_unwrap.stderr | 2 ++ tests/ui/identity_conversion.stderr | 2 ++ tests/ui/identity_op.stderr | 2 ++ tests/ui/if_let_redundant_pattern_matching.stderr | 2 ++ tests/ui/if_not_else.stderr | 2 ++ tests/ui/implicit_hasher.stderr | 2 ++ tests/ui/inconsistent_digit_grouping.stderr | 2 ++ tests/ui/infinite_iter.stderr | 2 ++ tests/ui/int_plus_one.stderr | 2 ++ tests/ui/invalid_ref.stderr | 2 ++ tests/ui/invalid_upcast_comparisons.stderr | 2 ++ tests/ui/is_unit_expr.stderr | 2 ++ tests/ui/item_after_statement.stderr | 2 ++ tests/ui/large_digit_groups.stderr | 2 ++ tests/ui/large_enum_variant.stderr | 2 ++ tests/ui/len_zero.stderr | 2 ++ tests/ui/let_if_seq.stderr | 2 ++ tests/ui/let_return.stderr | 2 ++ tests/ui/let_unit.stderr | 2 ++ tests/ui/lifetimes.stderr | 2 ++ tests/ui/lint_pass.stderr | 2 ++ tests/ui/literals.stderr | 2 ++ tests/ui/map_clone.stderr | 2 ++ tests/ui/matches.stderr | 2 ++ tests/ui/mem_forget.stderr | 2 ++ tests/ui/methods.stderr | 2 ++ tests/ui/min_max.stderr | 2 ++ tests/ui/missing-doc.stderr | 2 ++ tests/ui/module_inception.stderr | 2 ++ tests/ui/modulo_one.stderr | 2 ++ tests/ui/mut_from_ref.stderr | 2 ++ tests/ui/mut_mut.stderr | 2 ++ tests/ui/mut_range_bound.stderr | 2 ++ tests/ui/mut_reference.stderr | 2 ++ tests/ui/mutex_atomic.stderr | 2 ++ tests/ui/needless_bool.stderr | 2 ++ tests/ui/needless_borrow.stderr | 2 ++ tests/ui/needless_borrowed_ref.stderr | 2 ++ tests/ui/needless_continue.stderr | 2 ++ tests/ui/needless_pass_by_value.stderr | 2 ++ tests/ui/needless_range_loop.stderr | 2 ++ tests/ui/needless_return.stderr | 2 ++ tests/ui/needless_update.stderr | 2 ++ tests/ui/neg_multiply.stderr | 2 ++ tests/ui/never_loop.stderr | 2 ++ tests/ui/new_without_default.stderr | 2 ++ tests/ui/no_effect.stderr | 2 ++ tests/ui/non_expressive_names.stderr | 2 ++ tests/ui/ok_expect.stderr | 2 ++ tests/ui/ok_if_let.stderr | 2 ++ tests/ui/op_ref.stderr | 2 ++ tests/ui/open_options.stderr | 2 ++ tests/ui/overflow_check_conditional.stderr | 2 ++ tests/ui/panic.stderr | 2 ++ tests/ui/partialeq_ne_impl.stderr | 2 ++ tests/ui/patterns.stderr | 2 ++ tests/ui/precedence.stderr | 2 ++ tests/ui/print.stderr | 2 ++ tests/ui/print_with_newline.stderr | 2 ++ tests/ui/println_empty_string.stderr | 2 ++ tests/ui/ptr_arg.stderr | 2 ++ tests/ui/range.stderr | 2 ++ tests/ui/range_plus_minus_one.stderr | 2 ++ tests/ui/redundant_closure_call.stderr | 2 ++ tests/ui/reference.stderr | 2 ++ tests/ui/regex.stderr | 2 ++ tests/ui/replace_consts.stderr | 2 ++ tests/ui/serde.stderr | 2 ++ tests/ui/shadow.stderr | 2 ++ tests/ui/short_circuit_statement.stderr | 2 ++ tests/ui/single_char_pattern.stderr | 2 ++ tests/ui/starts_ends_with.stderr | 2 ++ tests/ui/string_extend.stderr | 2 ++ tests/ui/strings.stderr | 2 ++ tests/ui/stutter.stderr | 2 ++ tests/ui/swap.stderr | 2 ++ tests/ui/temporary_assignment.stderr | 2 ++ tests/ui/toplevel_ref_arg.stderr | 2 ++ tests/ui/trailing_zeros.stderr | 2 ++ tests/ui/transmute.stderr | 2 ++ tests/ui/transmute_64bit.stderr | 2 ++ tests/ui/types.stderr | 2 ++ tests/ui/unicode.stderr | 2 ++ tests/ui/unit_cmp.stderr | 2 ++ tests/ui/unnecessary_clone.stderr | 2 ++ tests/ui/unneeded_field_pattern.stderr | 2 ++ tests/ui/unreadable_literal.stderr | 2 ++ tests/ui/unsafe_removed_from_name.stderr | 2 ++ tests/ui/unused_io_amount.stderr | 2 ++ tests/ui/unused_labels.stderr | 2 ++ tests/ui/unused_lt.stderr | 2 ++ tests/ui/use_self.stderr | 2 ++ tests/ui/used_underscore_binding.stderr | 2 ++ tests/ui/useless_asref.stderr | 2 ++ tests/ui/useless_attribute.stderr | 2 ++ tests/ui/vec.stderr | 2 ++ tests/ui/while_loop.stderr | 2 ++ tests/ui/wrong_self_convention.stderr | 2 ++ tests/ui/zero_div_zero.stderr | 2 ++ tests/ui/zero_ptr.stderr | 2 ++ 167 files changed, 335 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index d532d4e5a59..2b0fea0f8b9 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -46,7 +46,9 @@ fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); config.mode = cfg_mode; - config.build_base = { + config.build_base = if rustc_test_suite().is_some() { + PathBuf::from("/tmp/clippy_test_build_base") + } else { let mut path = std::env::current_dir().unwrap(); path.push("target/debug/test_build_base"); path diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index a4b8839797c..2b1e9ad66fe 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -143,3 +143,5 @@ error: <-comparison of unit values detected. This will always be false | = note: `-D unit-cmp` implied by `-D warnings` +error: aborting due to 18 previous errors + diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index f102dc5b5dc..dda28433d7a 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -114,3 +114,5 @@ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it 55 | let my_sq2 = 1.4142; | ^^^^^^ +error: aborting due to 19 previous errors + diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index ea32a005219..ad4a02e2190 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -69,3 +69,5 @@ error: floating-point arithmetic detected 29 | -f; | ^^ +error: aborting due to 11 previous errors + diff --git a/tests/ui/array_indexing.stderr b/tests/ui/array_indexing.stderr index dd11247243c..d730b012932 100644 --- a/tests/ui/array_indexing.stderr +++ b/tests/ui/array_indexing.stderr @@ -116,3 +116,5 @@ error: range is out of bounds 44 | &empty[..4]; | ^^^^^^^^^^ +error: aborting due to 19 previous errors + diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index c1cc5d24426..2123507e2ef 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -134,3 +134,5 @@ error: manual implementation of an assign operation 40 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` +error: aborting due to 22 previous errors + diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 47528c315d4..0ff211259c0 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -48,3 +48,5 @@ error: variable appears on both sides of an assignment operation 15 | a &= a & 1; | ^^^^^^^^^^ help: replace it with: `a &= 1` +error: aborting due to 8 previous errors + diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index 9e4ac3d1283..f743399a606 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -20,3 +20,5 @@ error: the since field must contain a semver-compliant version 30 | #[deprecated(since = "1")] | ^^^^^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 39320bb9c30..6aad98ff528 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -106,3 +106,5 @@ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared 55 | x | 1 >= 8; | ^^^^^^^^^^ +error: aborting due to 17 previous errors + diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index a08a5326894..68fbe27a01e 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -84,3 +84,5 @@ error: use of a blacklisted/placeholder name `baz` 35 | if let Some(ref mut baz) = Some(42) {} | ^^^ +error: aborting due to 14 previous errors + diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index 86a289c19a8..4b7d12598ec 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -50,3 +50,5 @@ error: this boolean expression can be simplified | = note: `-D nonminimal-bool` implied by `-D warnings` +error: aborting due to 5 previous errors + diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index e5e062e0246..4436980bc11 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -24,3 +24,5 @@ error: equality checks against false can be replaced by a negation 10 | if false == x { "yes" } else { "no" }; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` +error: aborting due to 4 previous errors + diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 6367ba0348c..c88a7a7be60 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -175,3 +175,5 @@ error: this boolean expression can be simplified 58 | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` +error: aborting due to 21 previous errors + diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 74134f4f2b1..2cf0ea79626 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -28,3 +28,5 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` 22 | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` +error: aborting due to 4 previous errors + diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index c1badd0dc9b..254d0771386 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -7,3 +7,5 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` = note: `-D box-vec` implied by `-D warnings` = help: `Vec` is already on the heap, `Box>` makes an extra allocation. +error: aborting due to previous error + diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 058813356cd..eb4c73b65c6 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -17,3 +17,5 @@ error[E0308]: mismatched types = note: expected type `u32` found type `{integer}` +error: aborting due to 2 previous errors + diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index c4f6b65a21e..307edecfde1 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -22,3 +22,5 @@ error: You appear to be counting bytes the naive way 22 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` +error: aborting due to 3 previous errors + diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index ac409a813cc..0a008cb68bb 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -178,3 +178,5 @@ error: casting to the same type is unnecessary (`bool` -> `bool`) 39 | false as bool; | ^^^^^^^^^^^^^ +error: aborting due to 28 previous errors + diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 781d9c89767..a60f838fae8 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -60,3 +60,5 @@ error: casting u32 to f64 may become silently lossy if types change 14 | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` +error: aborting due to 10 previous errors + diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index fdd915979e4..19d6176193c 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -108,3 +108,5 @@ error: casting u32 to u64 may become silently lossy if types change 23 | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` +error: aborting due to 18 previous errors + diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index a6aac1300a3..1c4b12bcebf 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -120,3 +120,5 @@ error: casting i32 to usize may lose the sign of the value 22 | 1i32 as usize; | ^^^^^^^^^^^^^ +error: aborting due to 19 previous errors + diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index 4e7c1866a9a..fcf038fe002 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -8,3 +8,5 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so cas = help: Consider using a byte literal instead: b'a' +error: aborting due to previous error + diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 9ea1a29d29d..46f3d3d57e0 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -72,3 +72,5 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead 21 | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ +error: aborting due to 12 previous errors + diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 51c0ceea4b1..481a4d0f942 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -12,3 +12,5 @@ error: Comparing with null is better expressed by the .is_null() method 16 | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index e6996244664..d40fb4b8add 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -36,3 +36,5 @@ error: this creates an owned instance just for comparison 30 | self.to_owned() == *other | ^^^^^^^^^^^^^^^ try calling implementing the comparison without allocating +error: aborting due to 6 previous errors + diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index bc10afcedb3..69f2013c1dc 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -240,3 +240,5 @@ help: try 112 | } | +error: aborting due to 13 previous errors + diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 8ce63652f0b..829a22c233f 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -90,3 +90,5 @@ error: very complex type used. Consider factoring parts into `type` definitions 40 | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 15 previous errors + diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index 66c32aed07a..bc44cebdbbb 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index f2a741c7075..d4236926522 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 679418f38b7..440437d140e 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index 71c0d578a6c..19c8e5c9777 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index f1f679e6b0a..7a0aebb572e 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index fc1c33426f5..d1957c311ad 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -6,3 +6,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 | = help: add #![feature(plugin)] to the crate attributes to enable +error: aborting due to previous error + diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index 448d83ee921..db33744c7a9 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -78,3 +78,5 @@ error: Constants have by default a `'static` lifetime 24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` +error: aborting due to 13 previous errors + diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 4457e2b7d73..9accb310d12 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -33,3 +33,5 @@ error: This else block is redundant. } +error: aborting due to 2 previous errors + diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index c3dd9cf83f6..973f26a96db 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -12,3 +12,5 @@ help: assign the `CString` to a variable to extend its lifetime 7 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index 62fd5313ccb..43676762d6c 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -269,3 +269,5 @@ error: the function has a cyclomatic complexity of 8 | = help: you could split it up into multiple smaller functions +error: aborting due to 20 previous errors + diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index a9cefe93e32..e671b34393b 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -13,3 +13,5 @@ error: the function has a cyclomatic complexity of 3 = note: `-D cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions +error: aborting due to previous error + diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 4255959675a..7d5d594cfa1 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -24,3 +24,5 @@ error: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been 10 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 4 previous errors + diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index f336dc3a8e1..ffeed948ba5 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -106,3 +106,5 @@ note: consider deriving `Clone` or removing `Copy` 87 | | } | |_^ +error: aborting due to 7 previous errors + diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index b39d1ae07e5..0d7b1ca6fd6 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -36,3 +36,5 @@ error: sub-expression diverges 37 | _ => true || break, | ^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index 95872c02994..de0422e17ed 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -47,3 +47,5 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct | = help: a VecDeque might work +error: aborting due to 6 previous errors + diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index fc036d01b86..f38678e89aa 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -180,3 +180,5 @@ error: you should put bare URLs between `<`/`>` or make a proper Markdown link 168 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 30 previous errors + diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index 8c64eb37e15..fd4da8820a2 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -6,3 +6,5 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usual | = note: `-D double-neg` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index ab3e844d7a7..a77b08528c4 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -30,3 +30,5 @@ error: Consider removing unnecessary double parentheses 32 | (()) | ^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index f399c5a125f..3ea7bf9735a 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -72,3 +72,5 @@ note: argument has type SomeStruct 42 | forget(s4); | ^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 6058b89c70f..1654fdd2861 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -216,3 +216,5 @@ note: argument has type &SomeStruct 59 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ +error: aborting due to 18 previous errors + diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index de9e6f1e056..c926f57f154 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -6,3 +6,5 @@ error: `darth` already exists, having another argument having almost the same na | = note: `-D duplicate-underscore-argument` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 2395c2afde1..b8a5031fbcf 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -18,3 +18,5 @@ error: if expression with an `else if`, but without a final `else` 49 | | } | |_____^ help: add an `else` block here +error: aborting due to 2 previous errors + diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index a0d491b6f96..ca377cee822 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -11,3 +11,5 @@ help: consider using the uninhabited type `!` or a wrapper around it 7 | enum Empty {} | ^^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index e60c158d7c0..09c4a882280 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -42,3 +42,5 @@ error: usage of `contains_key` followed by `insert` on a `BTreeMap` 37 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +error: aborting due to 7 previous errors + diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 1e0fffb9ac4..2d53618c1b1 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -12,3 +12,5 @@ error: don't use glob imports for enum variants 12 | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 7e2716b8ea2..e33e29ec78e 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -97,3 +97,5 @@ error: All variants have the same prefix: `With` = note: `-D pub-enum-variant-names` implied by `-D warnings` = help: remove the prefixes and use full paths to the variants instead of glob imports +error: aborting due to 10 previous errors + diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index e0555bb0239..d6a137c6fe4 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -48,3 +48,5 @@ error: Clike enum variant discriminant is not portable to 32-bit targets 37 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ +error: aborting due to 8 previous errors + diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 914a85719d0..46c0ac108cd 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -204,3 +204,5 @@ error: taken reference of right operand | = note: `-D op-ref` implied by `-D warnings` +error: aborting due to 33 previous errors + diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 8a05d2c251d..310c41c541b 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -18,3 +18,5 @@ error: this operation will always return zero. This is likely not the intended o 11 | 0 / x; | ^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 34a6217cd70..5dca265c2a4 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -32,3 +32,5 @@ error: redundant closure found 18 | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` +error: aborting due to 5 previous errors + diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index e9bdc3b51d9..2e01a167c01 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -47,3 +47,5 @@ note: whether read occurs before this write depends on evaluation order 21 | x += { x = 20; 2 }; | ^^^^^^ +error: aborting due to 4 previous errors + diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 9a813e89793..7a2a0c66f23 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -36,3 +36,5 @@ error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` inste 21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 8e93966ccd1..c8af77ecab3 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -89,3 +89,5 @@ note: potential failure(s) | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +error: aborting due to 4 previous errors + diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index 8f1853c3952..cec03a47bfd 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -36,3 +36,5 @@ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly e 25 | | .map(|x| x.checked_mul(2)) | |__________________________________________________________^ +error: aborting due to 4 previous errors + diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index d2903f501f5..a764403d039 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -95,3 +95,5 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 57 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 8 previous errors + diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index fe277de28dd..6367ec73c96 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -83,3 +83,5 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 25 | v != ONE; | ^^^^^^^^ +error: aborting due to 7 previous errors + diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index b09350970fc..1e7ff40e1ac 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -565,3 +565,5 @@ error: it looks like you're manually copying between slices 549 | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` +error: aborting due to 59 previous errors + diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 558e9e83c33..5f5bdc02a59 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,3 +6,5 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index d121929d0c2..266de262ea0 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -86,3 +86,5 @@ error: possibly missing a comma here | = note: to remove this lint, add a comma or write the expr in a single line +error: aborting due to 10 previous errors + diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index c8b4db35245..0a97748954f 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -75,3 +75,5 @@ error: this public function dereferences a raw pointer but is not marked `unsafe 63 | unsafe { std::ptr::read(p) }; | ^ +error: aborting due to 12 previous errors + diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 3724cbfc852..b5ada862531 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -60,3 +60,5 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and 40 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` +error: aborting due to 10 previous errors + diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 152bb8882bd..1ae3f229dd8 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -40,3 +40,5 @@ error: identical conversion 39 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` +error: aborting due to 6 previous errors + diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index c1ce8d2ec4c..45f579ce832 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -48,3 +48,5 @@ error: the operation is ineffective. Consider reducing it to `u` 32 | u & 255; | ^^^^^^^ +error: aborting due to 8 previous errors + diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index b15d17e372e..e7bfd0275d8 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -24,3 +24,5 @@ error: redundant pattern matching, consider using `is_some()` 17 | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` +error: aborting due to 4 previous errors + diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index f9462f422ea..b920ef3b625 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -23,3 +23,5 @@ error: Unnecessary `!=` operation | = help: change to `==` and swap the blocks of the if/else +error: aborting due to 2 previous errors + diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index aaa1e37ca82..cdba5372b3c 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -133,3 +133,5 @@ help: consider adding a type parameter 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | +error: aborting due to 10 previous errors + diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 2725d5f4ef7..12d9e3cf0fd 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -39,3 +39,5 @@ error: digits grouped inconsistently by underscores | = help: consider: 1.234_567_8_f32 +error: aborting due to 5 previous errors + diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 87b7ca49322..f79db778488 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -96,3 +96,5 @@ error: possible infinite iteration detected 30 | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 14 previous errors + diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 69a8621fb16..deecaffa1cf 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -40,3 +40,5 @@ help: change `>= y + 1` to `> y` as shown 14 | y < x; | ^^^^^ +error: aborting due to 4 previous errors + diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index c018bdf6dd3..420fed01744 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -47,3 +47,5 @@ error: reference to uninitialized memory | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html +error: aborting due to 6 previous errors + diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index 3f11c373074..eb46802899e 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -162,3 +162,5 @@ error: because of the numeric bounds on `u8` prior to casting, this expression i 78 | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ +error: aborting due to 27 previous errors + diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr index 64a7ad86b70..7a16fe971f3 100644 --- a/tests/ui/is_unit_expr.stderr +++ b/tests/ui/is_unit_expr.stderr @@ -69,3 +69,5 @@ error: This expression evaluates to the Unit type () 78 | let x3 = match None { Some(_) => {}, None => {}, }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index e98e7ee129d..ec1296caf83 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -12,3 +12,5 @@ error: adding items after statements is confusing, since items exist from the st 17 | fn foo() { println!("foo"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index db49ded1d8a..6fc285274a0 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -47,3 +47,5 @@ error: digit groups should be smaller | = help: consider: 123_456.123_456_f32 +error: aborting due to 6 previous errors + diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 5c6aac7d4ee..5e938337bc0 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -66,3 +66,5 @@ help: consider boxing the large fields to reduce the total size of the enum 49 | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index d23a972dddc..6e3cf1b3ca1 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -94,3 +94,5 @@ error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_e 191 | | } | |_^ +error: aborting due to 12 previous errors + diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 39686a9dd07..b912373f95c 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -46,3 +46,5 @@ error: `if _ { .. } else { .. }` is an expression | = note: you might not need `mut` at all +error: aborting due to 4 previous errors + diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index b38c9ab2e91..459b2eafa26 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -23,3 +23,5 @@ note: this expression can be directly returned 15 | let x = 5; | ^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index 196afc0570c..da579ec80f3 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -12,3 +12,5 @@ error: this let-binding has unit value. Consider omitting `let _a =` 18 | let _a = (); | ^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 744e1ce21ec..23b353d13d2 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -86,3 +86,5 @@ error: explicit lifetimes given in parameter types where they could be elided 120 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 14 previous errors + diff --git a/tests/ui/lint_pass.stderr b/tests/ui/lint_pass.stderr index 66f2d62ed24..2f9a6813b96 100644 --- a/tests/ui/lint_pass.stderr +++ b/tests/ui/lint_pass.stderr @@ -6,3 +6,5 @@ error: the lint `MISSING_LINT` is not added to any `LintPass` | = note: `-D lint-without-lint-pass` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index bcb9dbd136b..92540b73462 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -86,3 +86,5 @@ help: if you mean to use an octal constant, use `0o` 30 | let fail8 = 0o123; | ^^^^^ +error: aborting due to 11 previous errors + diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 272b868a278..c29f3791851 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -98,3 +98,5 @@ error: you seem to be using .map() to clone the contents of an Option, consider = help: try x.as_ref().cloned() +error: aborting due to 11 previous errors + diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 62c77c778be..fd22247cb1f 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -448,3 +448,5 @@ error: use as_mut() instead 329 | | }; | |_____^ help: try this: `mut_owned.as_mut()` +error: aborting due to 37 previous errors + diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index c79afa829fe..6e7a44694e1 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -18,3 +18,5 @@ error: usage of mem::forget on Drop type 24 | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 65d8b82da14..feea8e5e512 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -501,3 +501,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D option-unwrap-used` implied by `-D warnings` +error: aborting due to 66 previous errors + diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index e9225f93b5e..de4c4e16fa0 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -42,3 +42,5 @@ error: this min/max combination leads to constant result 30 | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 7 previous errors + diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index 340a53386f9..54834f9021c 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -264,3 +264,5 @@ error: missing documentation for a function 191 | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 39 previous errors + diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index cb6ea951a17..c9d3319db1b 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -16,3 +16,5 @@ error: module has the same name as its containing module 14 | | } | |_____^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index 48cfe6c38cc..ccfca7154e0 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -6,3 +6,5 @@ error: any number modulo 1 will be 0 | = note: `-D modulo-one` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index eacda70ce07..a7cbc0b7a09 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -59,3 +59,5 @@ note: immutable borrow here 32 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 8bfc2fc8a5c..d1f05ea8091 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -57,3 +57,5 @@ error: generally you want to avoid `&mut &mut _` if possible 35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ +error: aborting due to 9 previous errors + diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index 20dbb6511d7..d7be7ae1e6f 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -30,3 +30,5 @@ error: attempt to mutate range bound within loop; note that the range of the loo 40 | let n = &mut m; // warning | ^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 6708bca8b2e..73df19bf158 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -18,3 +18,5 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable 28 | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index d46c713164a..354f9891c17 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -44,3 +44,5 @@ error: Consider using an AtomicIsize instead of a Mutex here. If you just want t 16 | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ +error: aborting due to 7 previous errors + diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index a25b34bfaaf..63e0632445f 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -66,3 +66,5 @@ error: this if-then-else expression returns a bool literal 50 | if x && y { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !(x && y)` +error: aborting due to 11 previous errors + diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 16962bb48f1..fde38508b32 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -38,3 +38,5 @@ error: this pattern creates a reference to a reference 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` +error: aborting due to 6 previous errors + diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index c85bf9f5a7c..2a8cf4348d3 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -24,3 +24,5 @@ error: this pattern takes a reference on something that is being de-referenced 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` +error: aborting due to 4 previous errors + diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index f63f120fcc7..3e0368892a4 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -55,3 +55,5 @@ error: There is no need for an explicit `else` block for this `if` expression println!("Jabber"); ... +error: aborting due to 2 previous errors + diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 2ca96b127e5..33bda7d9872 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -124,3 +124,5 @@ error: this argument is passed by value, but not consumed in the function body 101 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` +error: aborting due to 16 previous errors + diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index af78b370a12..7fb4571e0c3 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -37,3 +37,5 @@ help: consider using an iterator 35 | for in &mut ms { | +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 68c2654c863..42dc6e6594c 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -48,3 +48,5 @@ error: unneeded return statement 39 | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` +error: aborting due to 8 previous errors + diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index 978fd8e625b..3e509870d00 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -6,3 +6,5 @@ error: struct update has no effect, all the fields in the struct have already be | = note: `-D needless-update` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 6ed31d384a0..1d52ba16eae 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -12,3 +12,5 @@ error: Negation by multiplying with -1 32 | -1 * x; | ^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index e62fe0c2905..83c10c9b193 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -90,3 +90,5 @@ error: this loop never actually loops 160 | | } | |_________^ +error: aborting due to 9 previous errors + diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index c12c10b9ae0..335e60404fa 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -36,3 +36,5 @@ help: try this 67 | } | +error: aborting due to 3 previous errors + diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 0d8d6624a83..5bcab9f2b5e 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -278,3 +278,5 @@ error: statement can be reduced 115 | FooString { s: String::from("blah"), }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` +error: aborting due to 46 previous errors + diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 6412b47aab4..850a3ccd951 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -149,3 +149,5 @@ error: consider choosing a more descriptive name 141 | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ +error: aborting due to 14 previous errors + diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 79b09b3fa8a..da2d3b9500f 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -30,3 +30,5 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly 26 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index b696672d2fd..e1371d924eb 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -11,3 +11,5 @@ error: Matching on `Some` with `ok()` is redundant = note: `-D if-let-some-result` implied by `-D warnings` = help: Consider matching on `Ok(y)` and removing the call to `ok` instead +error: aborting due to previous error + diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 32596944570..a4f7b3c6761 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -10,3 +10,5 @@ help: use the values directly 13 | let foo = 5 - 6; | +error: aborting due to previous error + diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 2f4070c2868..f0d41904152 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -42,3 +42,5 @@ error: the method "truncate" is called more than once 15 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 7 previous errors + diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 6efcbfe38e1..adf353a1c4b 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -48,3 +48,5 @@ error: You are trying to use classic C underflow conditions that will fail in Ru 32 | if a < a - b { | ^^^^^^^^^ +error: aborting due to 8 previous errors + diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index f2480dfea6e..25113ed80b6 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -18,3 +18,5 @@ error: you probably are missing some parameter in your format string 12 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index c332ce53c1a..5e536cc51d2 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -6,3 +6,5 @@ error: re-implementing `PartialEq::ne` is unnecessary | = note: `-D partialeq-ne-impl` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 9a246c483b2..59bce3a9a8f 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -6,3 +6,5 @@ error: the `y @ _` pattern can be written as just `y` | = note: `-D redundant-pattern` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 26fbd75164d..9f0e53ffca2 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -54,3 +54,5 @@ error: unary minus has lower precedence than method call 16 | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` +error: aborting due to 9 previous errors + diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index fa547949bdb..789e1218b78 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -50,3 +50,5 @@ error: use of `Debug`-based formatting 31 | print!("Hello {:#?}", "#orld"); | ^^^^^^^ +error: aborting due to 8 previous errors + diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 0148a470e0d..4f32d1b2a2d 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -6,3 +6,5 @@ error: using `print!()` with a format string that ends in a newline, consider us | = note: `-D print-with-newline` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 2036d7d976b..f70b056e562 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -6,3 +6,5 @@ error: using `println!("")` | = note: `-D print-with-newline` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 4fbf73183c4..bf8608111cf 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -76,3 +76,5 @@ help: change `y.as_str()` to 62 | let c = y; | ^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 4098d32d08e..fc51f1a07f0 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -38,3 +38,5 @@ error: Iterator::step_by(0) will panic at runtime 33 | let _ = v1.iter().step_by(2/3); | ^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index a2a3ae6077f..cc0038c3442 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -65,3 +65,5 @@ error: an inclusive range would be more readable | help: use: `(f()+1)..=f()` | in this macro invocation +error: aborting due to 7 previous errors + diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 5acc3e9dde7..d2b5616a481 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -30,3 +30,5 @@ error: Try not to call a closure in the expression where it is declared. 12 | k = (|a,b| a*b)(1,5); | ^^^^^^^^^^^^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 2e6b23f6dc0..741c0cc1038 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -66,3 +66,5 @@ error: immediately dereferencing a reference 53 | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` +error: aborting due to 11 previous errors + diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 9f1397990bb..433061e41fb 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -149,3 +149,5 @@ error: trivial regex | = help: consider using consider using `str::is_empty` +error: aborting due to 21 previous errors + diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index a8e3dd2d00e..fb2e71db171 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -214,3 +214,5 @@ error: using `MAX` 47 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` +error: aborting due to 35 previous errors + diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index da0a96b2a3d..58667e0f820 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -10,3 +10,5 @@ error: you should not implement `visit_string` without also implementing `visit_ | = note: `-D serde-api-misuse` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index d5043261188..0eb5e5b2a2b 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -134,3 +134,5 @@ note: previous binding is here 21 | let x = y; | ^ +error: aborting due to 9 previous errors + diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index d7a02d7b9c3..7697cbd1c64 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -18,3 +18,5 @@ error: boolean short circuit operator in statement may be clearer using an expli 9 | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` +error: aborting due to 3 previous errors + diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index d5f21f210a3..42ee2b9fef4 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -102,3 +102,5 @@ error: single-character string constant used as pattern 37 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` +error: aborting due to 17 previous errors + diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index c67cc8a86ea..7d73f201b69 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -74,3 +74,5 @@ error: you should use the `ends_with` method 38 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` +error: aborting due to 12 previous errors + diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 1f6d9400743..4be2037ad31 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -18,3 +18,5 @@ error: calling `.extend(_.chars())` 22 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` +error: aborting due to 3 previous errors + diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index a8fd59e12b2..d098ce9df5e 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -72,3 +72,5 @@ error: manual implementation of an assign operation 65 | ; x = x + 1; | ^^^^^^^^^ help: replace it with: `x += 1` +error: aborting due to 11 previous errors + diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index e6465a2bce9..25e857991b8 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -30,3 +30,5 @@ error: item name starts with its containing module's name 12 | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 0bda9bc8d2b..a01ec375e63 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -65,3 +65,5 @@ error: this looks like you are trying to swap `c.0` and `a` | = note: or maybe you should use `std::mem::replace`? +error: aborting due to 7 previous errors + diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 73a4818ba16..979720c914d 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -12,3 +12,5 @@ error: assignment to temporary 30 | (0, 0).0 = 1; | ^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index 525b181bf91..f360e85329f 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -30,3 +30,5 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `& 24 | let ref mut z = 1 + 2; | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` +error: aborting due to 5 previous errors + diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 0a4b5361d86..91e4d59da98 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -12,3 +12,5 @@ error: bit mask could be simplified with a call to `trailing_zeros` 8 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 6504f55845d..f3ac9a101ae 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -204,3 +204,5 @@ error: transmute from a `&mut [u8]` to a `&mut str` 140 | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` +error: aborting due to 32 previous errors + diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index b679b913877..3a6a6e73f57 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -12,3 +12,5 @@ error: transmute from a `f64` to a pointer 11 | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index a2f4ede5ca2..b41bff7a9b0 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -6,3 +6,5 @@ error: casting i32 to i64 may become silently lossy if types change | = note: `-D cast-lossless` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 870a12ee4c4..9e99a44bb60 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -28,3 +28,5 @@ error: literal non-ASCII character detected = help: Consider replacing the string with: ""/u{dc}ben!"" +error: aborting due to 3 previous errors + diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index a85e4150a3e..51ad3fca947 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -12,3 +12,5 @@ error: >-comparison of unit values detected. This will always be false 19 | if { true; } > { false; } { | ^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index bb78bfa164e..486d2e350f2 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -80,3 +80,5 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D iter-cloned-collect` implied by `-D warnings` +error: aborting due to 11 previous errors + diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index ef1a8d75732..7e4c3a6cb9c 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -15,3 +15,5 @@ error: All the struct fields are matched to a wildcard pattern, consider using ` | = help: Try with `Foo { .. }` instead +error: aborting due to 2 previous errors + diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 81b69937a6d..72cb160fafc 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -31,3 +31,5 @@ error: long literal lacking separators | = help: consider: 1.234_56_f32 +error: aborting due to 4 previous errors + diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 7d455d31bce..93f2ddd533f 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -18,3 +18,5 @@ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` 23 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index b4a3cb2122d..5114d375fff 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -39,3 +39,5 @@ error: handle read amount returned or use `Read::read_exact` instead 27 | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors + diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index 338eb2f1551..19c91e2a6a3 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -22,3 +22,5 @@ error: unused label `'same_label_in_two_fns` 34 | | } | |_____^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index a4f01de18f7..b1fcebe6eed 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -18,3 +18,5 @@ error: this lifetime isn't used in the function definition 50 | fn x<'a>(&self) {} | ^^ +error: aborting due to 3 previous errors + diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 9d316dd3e08..bfd334335d8 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -36,3 +36,5 @@ error: unnecessary structure name repetition 24 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` +error: aborting due to 6 previous errors + diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 388a3491477..712f81c1b6f 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -30,3 +30,5 @@ error: used binding `_underscore_field` which is prefixed with an underscore. A 36 | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 4b6af9b877e..875d830a353 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -70,3 +70,5 @@ error: this call to `as_ref` does nothing 106 | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` +error: aborting due to 11 previous errors + diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 0bb87f8c538..707a11d55cc 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -6,3 +6,5 @@ error: useless lint attribute | = note: `-D useless-attribute` implied by `-D warnings` +error: aborting due to previous error + diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index a1555bc7907..6a47eb5b064 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -36,3 +36,5 @@ error: useless use of `vec!` 49 | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` +error: aborting due to 6 previous errors + diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index edc88405c40..689c92d6fb6 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -110,3 +110,5 @@ error: this loop could be written as a `for` loop 184 | | } | |_________^ help: try: `for v in y { .. }` +error: aborting due to 11 previous errors + diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index e57ffc3266b..216fd0bb82b 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -72,3 +72,5 @@ error: methods called `from_*` usually take no self; consider choosing a less am 54 | pub fn from_i64(self) {} | ^^^^ +error: aborting due to 12 previous errors + diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 697432af408..b81e59c07f1 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -57,3 +57,5 @@ error: constant division of 0.0 with 0.0 will always result in NaN | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN +error: aborting due to 8 previous errors + diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index fb87a47536e..5155dc401bd 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -12,3 +12,5 @@ error: `0 as *mut _` detected. Consider using `ptr::null_mut()` 7 | let y = 0 as *mut f64; | ^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From ada0d2c54831a904a53ff4106e0ebb6a0f06a687 Mon Sep 17 00:00:00 2001 From: Vlad-Shcherbina Date: Wed, 17 Jan 2018 21:40:47 +0300 Subject: Document map_clone known problems #498 --- clippy_lints/src/map_clone.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index e126d5c07d7..8403974629d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -10,7 +10,9 @@ use utils::{is_adjusted, iter_input_pats, match_qpath, match_trait_method, match /// **Why is this bad?** It makes the code less readable than using the /// `.cloned()` adapter. /// -/// **Known problems:** None. +/// **Known problems:** Sometimes `.cloned()` requires stricter trait +/// bound than `.map(|e| e.clone())` (which works because of the coercion). +/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498). /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 1cac693bc767e6c5648baeab1164feb4aea6ae30 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Wed, 17 Jan 2018 19:12:44 +0000 Subject: Lint on folds implementing .all, .sum and .product --- clippy_lints/src/methods.rs | 93 +++++++++++++++++++++++++++++---------------- tests/ui/methods.rs | 37 ++++++++++++------ tests/ui/methods.stderr | 34 +++++++++++++---- 3 files changed, 111 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 5ff48a25b1c..6eb48a1bc29 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1134,47 +1134,74 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); - if_chain! { - // Check if the initial value for the fold is the literal `false` - if let hir::ExprLit(ref lit) = fold_args[1].node; - if lit.node == ast::LitKind::Bool(false); + fn check_fold_with_op( + cx: &LateContext, + fold_args: &[hir::Expr], + op: hir::BinOp_, + replacement_method_name: &str) { - // Extract the body of the closure passed to fold - if let hir::ExprClosure(_, _, body_id, _, _) = fold_args[2].node; - let closure_body = cx.tcx.hir.body(body_id); - let closure_expr = remove_blocks(&closure_body.value); + if_chain! { + // Extract the body of the closure passed to fold + if let hir::ExprClosure(_, _, body_id, _, _) = fold_args[2].node; + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); - // Extract the names of the two arguments to the closure - if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); - if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); + // Check if the closure body is of the form `acc some_expr(x)` + if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; + if bin_op.node == op; - // Check if the closure body is of the form `acc || some_expr(x)` - if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; - if bin_op.node == hir::BinOp_::BiOr; - if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node; - if path.segments.len() == 1 && &path.segments[0].name == &first_arg_ident; + // Extract the names of the two arguments to the closure + if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); + if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); - then { - let right_source = snippet(cx, right_expr.span, "EXPR"); + if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node; + if path.segments.len() == 1 && &path.segments[0].name == &first_arg_ident; + + then { + let right_source = snippet(cx, right_expr.span, "EXPR"); - // Span containing `.fold(...)` - let fold_span = fold_args[0].span.next_point().with_hi(fold_args[2].span.hi() + BytePos(1)); + // Span containing `.fold(...)` + let fold_span = fold_args[0].span.next_point().with_hi(fold_args[2].span.hi() + BytePos(1)); - span_lint_and_sugg( - cx, - FOLD_ANY, - fold_span, - // TODO: don't suggest .any(|x| f(x)) if we can suggest .any(f) - "this `.fold` can more succintly be expressed as `.any`", - "try", - format!( - ".any(|{s}| {r})", - s = second_arg_ident, - r = right_source - ) - ); + span_lint_and_sugg( + cx, + FOLD_ANY, + fold_span, + // TODO: don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) + "this `.fold` can be written more succinctly using another method", + "try", + format!( + ".{replacement}(|{s}| {r})", + replacement = replacement_method_name, + s = second_arg_ident, + r = right_source + ) + ); + } } } + + // Check if the first argument to .fold is a suitable literal + match fold_args[1].node { + hir::ExprLit(ref lit) => { + match lit.node { + ast::LitKind::Bool(false) => check_fold_with_op( + cx, fold_args, hir::BinOp_::BiOr, "any" + ), + ast::LitKind::Bool(true) => check_fold_with_op( + cx, fold_args, hir::BinOp_::BiAnd, "all" + ), + ast::LitKind::Int(0, _) => check_fold_with_op( + cx, fold_args, hir::BinOp_::BiAdd, "sum" + ), + ast::LitKind::Int(1, _) => check_fold_with_op( + cx, fold_args, hir::BinOp_::BiMul, "product" + ), + _ => return + } + } + _ => return + }; } fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index d50f8e35fa4..3ca77f744fe 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -385,26 +385,39 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -/// Should trigger the `FOLD_ANY` lint -fn fold_any() { +/// Calls which should trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold() { + // Can be replaced by .any let _ = (0..3).fold(false, |acc, x| acc || x > 2); -} + let _ = (0..3).fold(false, |acc, x| x > 2 || acc); -/// Should not trigger the `FOLD_ANY` lint as the initial value is not the literal `false` -fn fold_any_ignores_initial_value_of_true() { - let _ = (0..3).fold(true, |acc, x| acc || x > 2); -} + // Can be replaced by .all + let _ = (0..3).fold(true, |acc, x| acc && x > 2); + let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + + // Can be replaced by .sum + let _ = (0..3).fold(0, |acc, x| acc + x); + let _ = (0..3).fold(0, |acc, x| x + acc); -/// Should not trigger the `FOLD_ANY` lint as the accumulator is not integer valued -fn fold_any_ignores_non_boolean_accumalator() { - let _ = (0..3).fold(0, |acc, x| acc + if x > 2 { 1 } else { 0 }); + // Can be replaced by .product + let _ = (0..3).fold(1, |acc, x| acc * x); + let _ = (0..3).fold(1, |acc, x| x * acc); } -/// Should trigger the `FOLD_ANY` lint, with the error span including exactly `.fold(...)` -fn fold_any_span_for_multi_element_chain() { +/// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` +fn unnecessary_fold_span_for_multi_element_chain() { let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); } +/// Calls which should not trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold_should_ignore() { + let _ = (0..3).fold(true, |acc, x| acc || x > 2); + let _ = (0..3).fold(false, |acc, x| acc && x > 2); + let _ = (0..3).fold(1, |acc, x| acc + x); + let _ = (0..3).fold(0, |acc, x| acc * x); + let _ = (0..3).fold(0, |acc, x| 1 + acc + x); +} + #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 2c03e077d57..1c8569e8d6b 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -493,24 +493,42 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 382 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this `.fold` can more succintly be expressed as `.any` - --> $DIR/methods.rs:390:19 +error: this `.fold` can be written more succinctly using another method + --> $DIR/methods.rs:391:19 | -390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); +391 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | = note: `-D fold-any` implied by `-D warnings` -error: this `.fold` can more succintly be expressed as `.any` - --> $DIR/methods.rs:405:34 +error: this `.fold` can be written more succinctly using another method + --> $DIR/methods.rs:395:19 | -405 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +395 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/methods.rs:399:19 + | +399 | let _ = (0..3).fold(0, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum(|x| x)` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/methods.rs:403:19 + | +403 | let _ = (0..3).fold(1, |acc, x| acc * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product(|x| x)` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/methods.rs:409:34 + | +409 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:411:13 + --> $DIR/methods.rs:424:13 | -411 | let _ = opt.unwrap(); +424 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 29a2dd4cb8f8f386656f6207ff007f068d170887 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Wed, 17 Jan 2018 20:11:40 +0000 Subject: Fix bug. Don't expect lint when acc is on rhs --- tests/ui/methods.rs | 17 ++++++++++------- tests/ui/methods.stderr | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 3ca77f744fe..f7a4b39c7a6 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -389,19 +389,12 @@ fn iter_skip_next() { fn unnecessary_fold() { // Can be replaced by .any let _ = (0..3).fold(false, |acc, x| acc || x > 2); - let _ = (0..3).fold(false, |acc, x| x > 2 || acc); - // Can be replaced by .all let _ = (0..3).fold(true, |acc, x| acc && x > 2); - let _ = (0..3).fold(true, |acc, x| x > 2 && acc); - // Can be replaced by .sum let _ = (0..3).fold(0, |acc, x| acc + x); - let _ = (0..3).fold(0, |acc, x| x + acc); - // Can be replaced by .product let _ = (0..3).fold(1, |acc, x| acc * x); - let _ = (0..3).fold(1, |acc, x| x * acc); } /// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` @@ -416,6 +409,16 @@ fn unnecessary_fold_should_ignore() { let _ = (0..3).fold(1, |acc, x| acc + x); let _ = (0..3).fold(0, |acc, x| acc * x); let _ = (0..3).fold(0, |acc, x| 1 + acc + x); + + // We only match against an accumulator on the left + // hand side. We could lint for .sum and .product when + // it's on the right, but don't for now (and this wouldn't + // be valid if we extended the lint to cover arbitrary numeric + // types). + let _ = (0..3).fold(false, |acc, x| x > 2 || acc); + let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + let _ = (0..3).fold(0, |acc, x| x + acc); + let _ = (0..3).fold(1, |acc, x| x * acc); } #[allow(similar_names)] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 1c8569e8d6b..57f073f00b0 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -502,33 +502,33 @@ error: this `.fold` can be written more succinctly using another method = note: `-D fold-any` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:395:19 + --> $DIR/methods.rs:393:19 | -395 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); +393 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:399:19 + --> $DIR/methods.rs:395:19 | -399 | let _ = (0..3).fold(0, |acc, x| acc + x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum(|x| x)` +395 | let _ = (0..3).fold(0, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:403:19 + --> $DIR/methods.rs:397:19 | -403 | let _ = (0..3).fold(1, |acc, x| acc * x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product(|x| x)` +397 | let _ = (0..3).fold(1, |acc, x| acc * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:409:34 + --> $DIR/methods.rs:402:34 | -409 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +402 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:424:13 + --> $DIR/methods.rs:427:13 | -424 | let _ = opt.unwrap(); +427 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 9806b31d530eabaaccaef17f2755000979a4c2a7 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Wed, 17 Jan 2018 20:21:29 +0000 Subject: Rename lint, improve documentation --- clippy_lints/src/methods.rs | 56 ++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 6eb48a1bc29..822bae14ff9 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -624,20 +624,26 @@ declare_lint! { } -/// **What it does:** Checks for using `fold` to implement `any`. +/// **What it does:** Checks for using `fold` when a more succint alternative exists. +/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, +/// `sum` or `product`. /// /// **Why is this bad?** Readability. /// -/// **Known problems:** Changes semantics - the suggested replacement is short-circuiting. +/// **Known problems:** None. /// /// **Example:** /// ```rust /// let _ = (0..3).fold(false, |acc, x| acc || x > 2); /// ``` +/// This could be written as: +/// ```rust +/// let _ = (0..3).any(|x| x > 2); +/// ``` declare_lint! { - pub FOLD_ANY, + pub UNNECESSARY_FOLD, Warn, - "using `fold` to emulate the behaviour of `any`" + "using `fold` when a more succint alternative exists" } impl LintPass for Pass { @@ -671,7 +677,7 @@ impl LintPass for Pass { STRING_EXTEND_CHARS, ITER_CLONED_COLLECT, USELESS_ASREF, - FOLD_ANY + UNNECESSARY_FOLD ) } } @@ -736,7 +742,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { lint_asref(cx, expr, "as_mut", arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { - lint_fold_any(cx, expr, arglists[0]); + lint_unnecessary_fold(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &method_call.name.as_str(), args); @@ -1125,7 +1131,7 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir } } -fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { +fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { // Check that this is a call to Iterator::fold rather than just some function called fold if !match_trait_method(cx, expr, &paths::ITERATOR) { return; @@ -1138,7 +1144,8 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { cx: &LateContext, fold_args: &[hir::Expr], op: hir::BinOp_, - replacement_method_name: &str) { + replacement_method_name: &str, + replacement_has_args: bool) { if_chain! { // Extract the body of the closure passed to fold @@ -1158,24 +1165,31 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { if path.segments.len() == 1 && &path.segments[0].name == &first_arg_ident; then { - let right_source = snippet(cx, right_expr.span, "EXPR"); - // Span containing `.fold(...)` let fold_span = fold_args[0].span.next_point().with_hi(fold_args[2].span.hi() + BytePos(1)); + let sugg = if replacement_has_args { + format!( + ".{replacement}(|{s}| {r})", + replacement = replacement_method_name, + s = second_arg_ident, + r = snippet(cx, right_expr.span, "EXPR") + ) + } else { + format!( + ".{replacement}()", + replacement = replacement_method_name, + ) + }; + span_lint_and_sugg( cx, - FOLD_ANY, + UNNECESSARY_FOLD, fold_span, // TODO: don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) "this `.fold` can be written more succinctly using another method", "try", - format!( - ".{replacement}(|{s}| {r})", - replacement = replacement_method_name, - s = second_arg_ident, - r = right_source - ) + sugg ); } } @@ -1186,16 +1200,16 @@ fn lint_fold_any(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { hir::ExprLit(ref lit) => { match lit.node { ast::LitKind::Bool(false) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiOr, "any" + cx, fold_args, hir::BinOp_::BiOr, "any", true ), ast::LitKind::Bool(true) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiAnd, "all" + cx, fold_args, hir::BinOp_::BiAnd, "all", true ), ast::LitKind::Int(0, _) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiAdd, "sum" + cx, fold_args, hir::BinOp_::BiAdd, "sum", false ), ast::LitKind::Int(1, _) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiMul, "product" + cx, fold_args, hir::BinOp_::BiMul, "product", false ), _ => return } -- cgit 1.4.1-3-g733a5 From b73efad6001ac140aa233b63cc093ea71049e2bb Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Wed, 17 Jan 2018 21:06:16 +0000 Subject: Add some reviewer comments --- clippy_lints/src/methods.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 4 ++-- tests/ui/methods.stderr | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 822bae14ff9..556c6988d66 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1173,7 +1173,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E ".{replacement}(|{s}| {r})", replacement = replacement_method_name, s = second_arg_ident, - r = snippet(cx, right_expr.span, "EXPR") + r = snippet(cx, right_expr.span, "EXPR"), ) } else { format!( @@ -1186,10 +1186,10 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E cx, UNNECESSARY_FOLD, fold_span, - // TODO: don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) + // TODO #2371 don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) "this `.fold` can be written more succinctly using another method", "try", - sugg + sugg, ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d4f7539cea9..4019321d711 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -601,7 +601,7 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( /// These suggestions can be parsed by rustfix to allow it to automatically fix your code. /// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > 2)"`. /// -///
+/// ```
 /// error: This `.fold` can be more succinctly expressed as `.any`
 /// --> $DIR/methods.rs:390:13
 ///     |
@@ -609,7 +609,7 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>(
 ///     |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)`
 ///     |
 ///     = note: `-D fold-any` implied by `-D warnings`
-/// 
+/// ``` pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( cx: &'a T, lint: &'static Lint, diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 57f073f00b0..254c7bf1895 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -499,7 +499,7 @@ error: this `.fold` can be written more succinctly using another method 391 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | - = note: `-D fold-any` implied by `-D warnings` + = note: `-D unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method --> $DIR/methods.rs:393:19 -- cgit 1.4.1-3-g733a5 From a324a2bc38738f288b1fd0bd39c1d203aef88bd4 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Wed, 17 Jan 2018 21:54:09 +0000 Subject: Fix typos --- clippy_lints/src/methods.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 556c6988d66..ea5fba8adb2 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -624,7 +624,7 @@ declare_lint! { } -/// **What it does:** Checks for using `fold` when a more succint alternative exists. +/// **What it does:** Checks for using `fold` when a more succinct alternative exists. /// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, /// `sum` or `product`. /// @@ -643,7 +643,7 @@ declare_lint! { declare_lint! { pub UNNECESSARY_FOLD, Warn, - "using `fold` when a more succint alternative exists" + "using `fold` when a more succinct alternative exists" } impl LintPass for Pass { -- cgit 1.4.1-3-g733a5 From d13af87d8a5786c26ab8c497079a248115cead95 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 18 Jan 2018 07:48:03 +0200 Subject: Fixed tests --- tests/ui/option_option.stderr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 91f686288dd..ebdc4fe9266 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -42,3 +42,5 @@ error: consider using `Option` instead of `Option>` or a custom enu 23 | Struct{x: Option>}, | ^^^^^^^^^^^^^^^^^^ +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From bf7efead17dcb685cff8c7696f1ba6f7c28a82f1 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 18 Jan 2018 07:52:24 +0200 Subject: Rename variable Rename `vec` to `ty` in `match_type_parameter`. This variable is a type and not a vector. Previously it would only refer to `Vec<_>` so the name used to make sense. --- clippy_lints/src/types.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e5109cf3ebb..d10199c992d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -182,9 +182,9 @@ fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool if_chain! { if let Some(ref params) = last.parameters; if !params.parenthesized; - if let Some(vec) = params.types.get(0); - if let TyPath(ref qpath) = vec.node; - if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(vec.id))); + if let Some(ty) = params.types.get(0); + if let TyPath(ref qpath) = ty.node; + if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id))); if match_def_path(cx.tcx, did, path); then { return true; -- cgit 1.4.1-3-g733a5 From cf1fbaa36ab853e09407ed62edf269aa1628d484 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 18 Jan 2018 14:00:52 +0530 Subject: needless_pass_by_value: Ignore for extern funcs (fixes #1844) --- clippy_lints/src/needless_pass_by_value.rs | 20 +++++++++++++------- tests/ui/needless_pass_by_value.rs | 3 +++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f7c93e7907a..f404d343439 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -6,6 +6,7 @@ use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; +use syntax::abi::Abi; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; @@ -71,13 +72,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } match kind { - FnKind::ItemFn(.., attrs) => for a in attrs { - if_chain! { - if a.meta_item_list().is_some(); - if let Some(name) = a.name(); - if name == "proc_macro_derive"; - then { - return; + FnKind::ItemFn(.., abi, _, attrs) => { + if abi != Abi::Rust { + return; + } + for a in attrs { + if_chain! { + if a.meta_item_list().is_some(); + if let Some(name) = a.name(); + if name == "proc_macro_derive"; + then { + return; + } } } }, diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 84c7e832951..e5138c37e8c 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -110,4 +110,7 @@ trait FalsePositive { } } +// shouldn't warn on extern funcs +extern "C" fn ext(x: String) -> usize { x.len() } + fn main() {} -- cgit 1.4.1-3-g733a5 From 2a30c8a194deedde2ff2326180cfbd38303c2bdb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 18 Jan 2018 14:15:41 +0530 Subject: needless_pass_by_value: Add suggestion for implementing Copy (fixes #2222) --- clippy_lints/src/needless_pass_by_value.rs | 7 +++++++ tests/ui/needless_pass_by_value.stderr | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f404d343439..92dc330779f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -202,6 +202,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder| { + if let ty::TypeVariants::TyAdt(ref def, ..) = ty.sty { + if let Some(span) = cx.tcx.hir.span_if_local(def.did) { + // FIXME (#2374) Restrict this to types which can impl Copy + db.span_help(span, "consider marking this type as Copy if possible"); + } + } + let deref_span = spans_need_deref.get(&canonical_id); if_chain! { if match_type(cx, ty, &paths::VEC); diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 33bda7d9872..441a9095b6a 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -17,6 +17,12 @@ error: this argument is passed by value, but not consumed in the function body | 26 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | +help: consider marking this type as Copy if possible + --> $DIR/needless_pass_by_value.rs:24:1 + | +24 | struct Wrapper(String); + | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:32:71 @@ -40,12 +46,24 @@ error: this argument is passed by value, but not consumed in the function body | 57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | +help: consider marking this type as Copy if possible + --> $DIR/needless_pass_by_value.rs:24:1 + | +24 | struct Wrapper(String); + | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:57:36 | 57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ + | +help: consider marking this type as Copy if possible + --> $DIR/needless_pass_by_value.rs:24:1 + | +24 | struct Wrapper(String); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | 57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { @@ -123,6 +141,12 @@ error: this argument is passed by value, but not consumed in the function body | 101 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` + | +help: consider marking this type as Copy if possible + --> $DIR/needless_pass_by_value.rs:82:1 + | +82 | struct S(T, U); + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From 552e950080f4fa2a4570e9719f2b4f7effed047e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 18 Jan 2018 14:19:19 +0530 Subject: needless_pass_by_value: Whitelist RangeArgument (fixes #2357) --- clippy_lints/src/needless_pass_by_value.rs | 5 +- clippy_lints/src/utils/paths.rs | 1 + tests/ui/needless_pass_by_value.rs | 7 ++ tests/ui/needless_pass_by_value.stderr | 100 ++++++++++++++--------------- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 92dc330779f..f5ff0ef8285 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -102,10 +102,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Allow `Borrow` or functions to be taken by value let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); - let fn_traits = [ + let whitelisted_traits = [ need!(cx.tcx.lang_items().fn_trait()), need!(cx.tcx.lang_items().fn_once_trait()), need!(cx.tcx.lang_items().fn_mut_trait()), + need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)) ]; let sized_trait = need!(cx.tcx.lang_items().sized_trait()); @@ -189,7 +190,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if !is_self(arg); if !ty.is_mutable_pointer(); if !is_copy(cx, ty); - if !fn_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); + if !whitelisted_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); if !implements_borrow_trait; if !all_borrowable_trait; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 95e14609182..20244a19f4f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -55,6 +55,7 @@ pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["alloc", "range", "RangeArgument"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index e5138c37e8c..bca48c97e4c 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -4,6 +4,8 @@ #![warn(needless_pass_by_value)] #![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names)] +#![feature(collections_range)] + use std::borrow::Borrow; use std::convert::AsRef; @@ -113,4 +115,9 @@ trait FalsePositive { // shouldn't warn on extern funcs extern "C" fn ext(x: String) -> usize { x.len() } +// whitelist RangeArgument +fn range>(range: T) { + let _ = range.start(); +} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 441a9095b6a..f03fbfee9ff 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,151 +1,151 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:12:23 + --> $DIR/needless_pass_by_value.rs:14:23 | -12 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { +14 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` | = note: `-D needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:26:11 + --> $DIR/needless_pass_by_value.rs:28:11 | -26 | fn bar(x: String, y: Wrapper) { +28 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:26:22 + --> $DIR/needless_pass_by_value.rs:28:22 | -26 | fn bar(x: String, y: Wrapper) { +28 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:32:71 + --> $DIR/needless_pass_by_value.rs:34:71 | -32 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +34 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:44:18 + --> $DIR/needless_pass_by_value.rs:46:18 | -44 | fn test_match(x: Option>, y: Option>) { +46 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -44 | fn test_match(x: &Option>, y: Option>) { -45 | match *x { +46 | fn test_match(x: &Option>, y: Option>) { +47 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:57:24 + --> $DIR/needless_pass_by_value.rs:59:24 | -57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:57:36 + --> $DIR/needless_pass_by_value.rs:59:36 | -57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -58 | let Wrapper(s) = z; // moved -59 | let Wrapper(ref t) = *y; // not moved -60 | let Wrapper(_) = *y; // still not moved +59 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +60 | let Wrapper(s) = z; // moved +61 | let Wrapper(ref t) = *y; // not moved +62 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:73:49 + --> $DIR/needless_pass_by_value.rs:75:49 | -73 | fn test_blanket_ref(_foo: T, _serializable: S) {} +75 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:18 + --> $DIR/needless_pass_by_value.rs:77:18 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:29 + --> $DIR/needless_pass_by_value.rs:77:29 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -75 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -77 | let _ = t.to_string(); +79 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:40 + --> $DIR/needless_pass_by_value.rs:77:40 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:53 + --> $DIR/needless_pass_by_value.rs:77:53 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -75 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -79 | let _ = v.to_owned(); +81 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:12 + --> $DIR/needless_pass_by_value.rs:89:12 | -87 | s: String, +89 | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:88:12 + --> $DIR/needless_pass_by_value.rs:90:12 | -88 | t: String, +90 | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:100:13 + --> $DIR/needless_pass_by_value.rs:102:13 | -100 | _u: U, +102 | _u: U, | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:13 + --> $DIR/needless_pass_by_value.rs:103:13 | -101 | _s: Self, +103 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:82:1 + --> $DIR/needless_pass_by_value.rs:84:1 | -82 | struct S(T, U); +84 | struct S(T, U); | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From 5f3c340bfbc61dd676bab8b383a6ad080ef554b8 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Wed, 17 Jan 2018 20:41:24 +1100 Subject: Lint for trait methods without bodies As discussed in rust-lang/rust#47475 the #[inline] attribute is currently allowed on trait methods without bodies (i.e. without a default implementation). This is misleading as it could be interpreted as affecting the implementations of the trait method. Add a lint for any use of #[inline] on a trait method without a body. Fixes rust-lang/rust#47475 --- CHANGELOG.md | 1 + clippy_lints/src/inline_fn_without_body.rs | 61 +++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ main | Bin 0 -> 558396 bytes tests/ui/inline_fn_without_body.rs | 18 +++++++++ tests/ui/inline_fn_without_body.stderr | 14 +++++++ 6 files changed, 97 insertions(+) create mode 100644 clippy_lints/src/inline_fn_without_body.rs create mode 100755 main create mode 100644 tests/ui/inline_fn_without_body.rs create mode 100644 tests/ui/inline_fn_without_body.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 77e9babf9d4..7af39eda8ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -583,6 +583,7 @@ All notable changes to this project will be documented in this file. [`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask [`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter [`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always +[`inline_fn_without_body`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_fn_without_body [`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic [`invalid_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_ref diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs new file mode 100644 index 00000000000..f2b75608674 --- /dev/null +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -0,0 +1,61 @@ +//! checks for `#[inline]` on trait methods without bodies + +use rustc::lint::*; +use rustc::hir::*; +use syntax::ast::{Attribute, Name}; +use utils::span_lint; + +/// **What it does:** Checks for `#[inline]` on trait methods without bodies +/// +/// **Why is this bad?** Only implementations of trait methods may be inlined. +/// The inline attribute is ignored for trait methods without bodies. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// trait Animal { +/// #[inline] +/// fn name(&self) -> &'static str; +/// } +/// ``` +declare_lint! { + pub INLINE_FN_WITHOUT_BODY, + Warn, + "use of `#[inline]` on trait methods without bodies" +} + +#[derive(Copy, Clone)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(INLINE_FN_WITHOUT_BODY) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { + match item.node { + TraitItemKind::Method(_, TraitMethod::Required(_)) => { + check_attrs(cx, &item.name, &item.attrs); + }, + _ => {}, + } + } +} + +fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) { + for attr in attrs { + if attr.name().map_or(true, |n| n != "inline") { + continue; + } + + span_lint( + cx, + INLINE_FN_WITHOUT_BODY, + attr.span, + &format!("use of `#[inline]` on trait method `{}` which has no body", name), + ); + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 11afefd6d4b..68ef021e76d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -109,6 +109,7 @@ pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; pub mod infinite_iter; +pub mod inline_fn_without_body; pub mod int_plus_one; pub mod invalid_ref; pub mod is_unit_expr; @@ -359,6 +360,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::Pass); + reg.register_late_lint_pass(box inline_fn_without_body::Pass); reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); @@ -477,6 +479,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infinite_iter::INFINITE_ITER, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, invalid_ref::INVALID_REF, is_unit_expr::UNIT_EXPR, large_enum_variant::LARGE_ENUM_VARIANT, diff --git a/main b/main new file mode 100755 index 00000000000..c5f9f914d33 Binary files /dev/null and b/main differ diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs new file mode 100644 index 00000000000..aa50d7c96c6 --- /dev/null +++ b/tests/ui/inline_fn_without_body.rs @@ -0,0 +1,18 @@ + + + +#![warn(inline_fn_without_body)] +#![allow(inline_always)] +trait Foo { + #[inline] + fn default_inline(); + + #[inline(always)] + fn always_inline(); + + #[inline] + fn has_body() { + } +} + +fn main() {} diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr new file mode 100644 index 00000000000..1f4b4afb264 --- /dev/null +++ b/tests/ui/inline_fn_without_body.stderr @@ -0,0 +1,14 @@ +error: use of `#[inline]` on trait method `default_inline` which has no body + --> $DIR/inline_fn_without_body.rs:7:5 + | +7 | #[inline] + | ^^^^^^^^^ + | + = note: `-D inline-fn-without-body` implied by `-D warnings` + +error: use of `#[inline]` on trait method `always_inline` which has no body + --> $DIR/inline_fn_without_body.rs:10:5 + | +10 | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 7467b83377e47a5f99b68737e5855ec4db1501e2 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Thu, 18 Jan 2018 06:08:03 +1100 Subject: Suggest removing inline attributes This adds a `suggest_remove_item` helper that will remove an item and all trailing whitespace. This should handle both attributes on the same line as the function and on a separate line; the function takes the position of the original attribute. --- clippy_lints/src/inline_fn_without_body.rs | 8 ++++++-- clippy_lints/src/utils/sugg.rs | 31 ++++++++++++++++++++++++++++++ tests/ui/inline_fn_without_body.rs | 11 ++++++++--- tests/ui/inline_fn_without_body.stderr | 25 ++++++++++++++++++------ 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index f2b75608674..1bb9519d304 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -3,7 +3,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::{Attribute, Name}; -use utils::span_lint; +use utils::span_lint_and_then; +use utils::sugg::DiagnosticBuilderExt; /// **What it does:** Checks for `#[inline]` on trait methods without bodies /// @@ -51,11 +52,14 @@ fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) { continue; } - span_lint( + span_lint_and_then( cx, INLINE_FN_WITHOUT_BODY, attr.span, &format!("use of `#[inline]` on trait method `{}` which has no body", name), + |db| { + db.suggest_remove_item(cx, attr.span, "remove"); + }, ); } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index c680e3eeb5b..2f651917bc1 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -15,6 +15,7 @@ use syntax::print::pprust::token_to_string; use syntax::util::parser::AssocOp; use syntax::ast; use utils::{higher, snippet, snippet_opt}; +use syntax_pos::{BytePos, Pos}; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -454,6 +455,19 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { /// }"); /// ``` fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str); + + /// Suggest to completely remove an item. + /// + /// This will remove an item and all following whitespace until the next non-whitespace + /// character. This should work correctly if item is on the same indentation level as the + /// following item. + /// + /// # Example + /// + /// ```rust,ignore + /// db.suggest_remove_item(cx, item, "remove this") + /// ``` + fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str); } impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { @@ -485,4 +499,21 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent)); } } + + fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) { + let mut remove_span = item; + let fmpos = cx.sess() + .codemap() + .lookup_byte_offset(remove_span.next_point().hi()); + + if let Some(ref src) = fmpos.fm.src { + let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); + + if let Some(non_whitespace_offset) = non_whitespace_offset { + remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset as u32)) + } + } + + self.span_suggestion(remove_span, msg, String::new()); + } } diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index aa50d7c96c6..82e073184d3 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -3,16 +3,21 @@ #![warn(inline_fn_without_body)] #![allow(inline_always)] + trait Foo { #[inline] fn default_inline(); - #[inline(always)] - fn always_inline(); + #[inline(always)]fn always_inline(); + + #[inline(never)] + + fn never_inline(); #[inline] fn has_body() { } } -fn main() {} +fn main() { +} diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 1f4b4afb264..fd26013d11e 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,14 +1,27 @@ error: use of `#[inline]` on trait method `default_inline` which has no body - --> $DIR/inline_fn_without_body.rs:7:5 + --> $DIR/inline_fn_without_body.rs:8:5 | -7 | #[inline] - | ^^^^^^^^^ +8 | #[inline] + | _____-^^^^^^^^ +9 | | fn default_inline(); + | |____- help: remove | = note: `-D inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body - --> $DIR/inline_fn_without_body.rs:10:5 + --> $DIR/inline_fn_without_body.rs:11:5 | -10 | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ +11 | #[inline(always)]fn always_inline(); + | ^^^^^^^^^^^^^^^^^ help: remove + +error: use of `#[inline]` on trait method `never_inline` which has no body + --> $DIR/inline_fn_without_body.rs:13:5 + | +13 | #[inline(never)] + | _____-^^^^^^^^^^^^^^^ +14 | | +15 | | fn never_inline(); + | |____- help: remove + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 8217e33718402111d871551e8608bd6f7868a9a4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 18 Jan 2018 14:27:47 +0100 Subject: Only suggest implementing Copy if it can actually be done --- clippy_lints/src/needless_pass_by_value.rs | 6 ++- tests/ui/needless_pass_by_value.rs | 17 +++++++ tests/ui/needless_pass_by_value.stderr | 82 +++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f5ff0ef8285..21a7542e6c7 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -205,8 +205,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let sugg = |db: &mut DiagnosticBuilder| { if let ty::TypeVariants::TyAdt(ref def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { - // FIXME (#2374) Restrict this to types which can impl Copy - db.span_help(span, "consider marking this type as Copy if possible"); + let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); + if param_env.can_type_implement_copy(cx.tcx, ty, span).is_ok() { + db.span_help(span, "consider marking this type as Copy"); + } } } diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index bca48c97e4c..6e87fcc7b44 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -120,4 +120,21 @@ fn range>(range: T) { let _ = range.start(); } +struct CopyWrapper(u32); + +fn bar_copy(x: u32, y: CopyWrapper) { + assert_eq!(x, 42); + assert_eq!(y.0, 42); +} + +// x and y should be warned, but z is ok +fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + let CopyWrapper(s) = z; // moved + let CopyWrapper(ref t) = y; // not moved + let CopyWrapper(_) = y; // still not moved + + assert_eq!(x.0, s); + println!("{}", t); +} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index f03fbfee9ff..469c16fa3d5 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -17,12 +17,6 @@ error: this argument is passed by value, but not consumed in the function body | 28 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` - | -help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:26:1 - | -26 | struct Wrapper(String); - | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:34:71 @@ -46,24 +40,12 @@ error: this argument is passed by value, but not consumed in the function body | 59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` - | -help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:26:1 - | -26 | struct Wrapper(String); - | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:59:36 | 59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ - | -help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:26:1 - | -26 | struct Wrapper(String); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | 59 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { @@ -141,12 +123,66 @@ error: this argument is passed by value, but not consumed in the function body | 103 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:125:24 + | +125 | fn bar_copy(x: u32, y: CopyWrapper) { + | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | +help: consider marking this type as Copy + --> $DIR/needless_pass_by_value.rs:123:1 + | +123 | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:131:29 + | +131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | +help: consider marking this type as Copy + --> $DIR/needless_pass_by_value.rs:123:1 + | +123 | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:131:45 + | +131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ + | +help: consider marking this type as Copy + --> $DIR/needless_pass_by_value.rs:123:1 + | +123 | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +131 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { +132 | let CopyWrapper(s) = z; // moved +133 | let CopyWrapper(ref t) = *y; // not moved +134 | let CopyWrapper(_) = *y; // still not moved + | + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:131:61 + | +131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ + | +help: consider marking this type as Copy + --> $DIR/needless_pass_by_value.rs:123:1 + | +123 | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead | -help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:84:1 +131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { +132 | let CopyWrapper(s) = *z; // moved | -84 | struct S(T, U); - | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From 10c96e50c3d2ef2977e0338cf3fae6384c77a331 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 18 Jan 2018 22:02:58 +0100 Subject: Don't run dogfood tests in the rustc test suite --- tests/dogfood.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 1514383e6de..8ca9b5c92a4 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,5 +1,8 @@ #[test] fn dogfood() { + if option_env!("RUSTC_TEST_SUITE").is_some() { + return; + } let root_dir = std::env::current_dir().unwrap(); for d in &[".", "clippy_lints"] { std::env::set_current_dir(root_dir.join(d)).unwrap(); -- cgit 1.4.1-3-g733a5 From 8081f6fd6e01ac737f00b4871209703b36717412 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 18 Jan 2018 17:02:18 -0500 Subject: Replace `is_unit_expr` --- clippy_lints/src/is_unit_expr.rs | 140 --------------------------------- clippy_lints/src/lib.rs | 5 +- clippy_lints/src/types.rs | 162 +++++++++++++++++++++++++++++---------- tests/ui/is_unit_expr.rs | 79 ------------------- tests/ui/is_unit_expr.stderr | 73 ------------------ tests/ui/unit_arg.rs | 55 +++++++++++++ tests/ui/unit_arg.stderr | 68 ++++++++++++++++ 7 files changed, 248 insertions(+), 334 deletions(-) delete mode 100644 clippy_lints/src/is_unit_expr.rs delete mode 100644 tests/ui/is_unit_expr.rs delete mode 100644 tests/ui/is_unit_expr.stderr create mode 100644 tests/ui/unit_arg.rs create mode 100644 tests/ui/unit_arg.stderr diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs deleted file mode 100644 index 90e2ef760f7..00000000000 --- a/clippy_lints/src/is_unit_expr.rs +++ /dev/null @@ -1,140 +0,0 @@ -use rustc::lint::*; -use syntax::ast::*; -use syntax::ext::quote::rt::Span; -use utils::{span_lint, span_note_and_lint}; - -/// **What it does:** Checks for -/// - () being assigned to a variable -/// - () being passed to a function -/// -/// **Why is this bad?** It is extremely unlikely that a user intended to -/// assign '()' to valiable. Instead, -/// Unit is what a block evaluates to when it returns nothing. This is -/// typically caused by a trailing -/// unintended semicolon. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// * `let x = {"foo" ;}` when the user almost certainly intended `let x -/// ={"foo"}` -declare_lint! { - pub UNIT_EXPR, - Warn, - "unintended assignment or use of a unit typed value" -} - -#[derive(Copy, Clone)] -enum UnitCause { - SemiColon, - EmptyBlock, -} - -#[derive(Copy, Clone)] -pub struct UnitExpr; - -impl LintPass for UnitExpr { - fn get_lints(&self) -> LintArray { - lint_array!(UNIT_EXPR) - } -} - -impl EarlyLintPass for UnitExpr { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - if let ExprKind::Assign(ref _left, ref right) = expr.node { - check_for_unit(cx, right); - } - if let ExprKind::MethodCall(ref _left, ref args) = expr.node { - for arg in args { - check_for_unit(cx, arg); - } - } - if let ExprKind::Call(_, ref args) = expr.node { - for arg in args { - check_for_unit(cx, arg); - } - } - } - - fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) { - if let StmtKind::Local(ref local) = stmt.node { - if local.pat.node == PatKind::Wild { - return; - } - if let Some(ref expr) = local.init { - check_for_unit(cx, expr); - } - } - } -} - -fn check_for_unit(cx: &EarlyContext, expr: &Expr) { - match is_unit_expr(expr) { - Some((span, UnitCause::SemiColon)) => span_note_and_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - span, - "Consider removing the trailing semicolon", - ), - Some((_span, UnitCause::EmptyBlock)) => span_lint( - cx, - UNIT_EXPR, - expr.span, - "This expression evaluates to the Unit type ()", - ), - None => (), - } -} - -fn is_unit_expr(expr: &Expr) -> Option<(Span, UnitCause)> { - match expr.node { - ExprKind::Block(ref block) => match check_last_stmt_in_block(block) { - Some(UnitCause::SemiColon) => - Some((block.stmts[block.stmts.len() - 1].span, UnitCause::SemiColon)), - Some(UnitCause::EmptyBlock) => - Some((block.span, UnitCause::EmptyBlock)), - None => None - } - ExprKind::If(_, ref then, ref else_) => { - let check_then = check_last_stmt_in_block(then); - if let Some(ref else_) = *else_ { - let check_else = is_unit_expr(else_); - if let Some(ref expr_else) = check_else { - return Some(*expr_else); - } - } - match check_then { - Some(c) => Some((expr.span, c)), - None => None, - } - }, - ExprKind::Match(ref _pattern, ref arms) => { - for arm in arms { - if let Some(r) = is_unit_expr(&arm.body) { - return Some(r); - } - } - None - }, - _ => None, - } -} - -fn check_last_stmt_in_block(block: &Block) -> Option { - if block.stmts.is_empty() { return Some(UnitCause::EmptyBlock); } - let final_stmt = &block.stmts[block.stmts.len() - 1]; - - - // Made a choice here to risk false positives on divergent macro invocations - // like `panic!()` - match final_stmt.node { - StmtKind::Expr(_) => None, - StmtKind::Semi(ref expr) => match expr.node { - ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => None, - _ => Some(UnitCause::SemiColon), - }, - _ => Some(UnitCause::SemiColon), // not sure what's happening here - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 11afefd6d4b..c1472484078 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -111,7 +111,6 @@ pub mod if_not_else; pub mod infinite_iter; pub mod int_plus_one; pub mod invalid_ref; -pub mod is_unit_expr; pub mod items_after_statements; pub mod large_enum_variant; pub mod len_zero; @@ -268,7 +267,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box approx_const::Pass); reg.register_late_lint_pass(box misc::Pass); reg.register_early_lint_pass(box precedence::Precedence); - reg.register_early_lint_pass(box is_unit_expr::UnitExpr); reg.register_early_lint_pass(box needless_continue::NeedlessContinue); reg.register_late_lint_pass(box eta_reduction::EtaPass); reg.register_late_lint_pass(box identity_op::IdentityOp); @@ -365,6 +363,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box const_static_lifetime::StaticConst); reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_late_lint_pass(box replace_consts::ReplaceConsts); + reg.register_late_lint_pass(box types::UnitArg); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -478,7 +477,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infinite_iter::INFINITE_ITER, invalid_ref::INVALID_REF, - is_unit_expr::UNIT_EXPR, large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, @@ -607,6 +605,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::LINKEDLIST, types::TYPE_COMPLEXITY, types::UNIT_CMP, + types::UNIT_ARG, types::UNNECESSARY_CAST, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c0c72408c7d..8d88217b924 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -322,25 +322,22 @@ declare_lint! { fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { - match cx.tables.pat_ty(&local.pat).sty { - ty::TyTuple(slice, _) if slice.is_empty() => { - if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { - return; - } - if higher::is_from_for_desugar(decl) { - return; - } - span_lint( - cx, - LET_UNIT_VALUE, - decl.span, - &format!( - "this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, "..") - ), - ); - }, - _ => (), + if is_unit(cx.tables.pat_ty(&local.pat)) { + if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { + return; + } + if higher::is_from_for_desugar(decl) { + return; + } + span_lint( + cx, + LET_UNIT_VALUE, + decl.span, + &format!( + "this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, "..") + ), + ); } } } @@ -395,31 +392,118 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { } if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; - if op.is_comparison() { - match cx.tables.expr_ty(left).sty { - ty::TyTuple(slice, _) if slice.is_empty() => { - let result = match op { - BiEq | BiLe | BiGe => "true", - _ => "false", - }; - span_lint( - cx, - UNIT_CMP, - expr.span, - &format!( - "{}-comparison of unit values detected. This will always be {}", - op.as_str(), - result - ), - ); - }, - _ => (), - } + if op.is_comparison() && is_unit(cx.tables.expr_ty(left)) { + let result = match op { + BiEq | BiLe | BiGe => "true", + _ => "false", + }; + span_lint( + cx, + UNIT_CMP, + expr.span, + &format!( + "{}-comparison of unit values detected. This will always be {}", + op.as_str(), + result + ), + ); } } } } +/// **What it does:** Checks for passing a unit value as an argument to a function without using a unit literal (`()`). +/// +/// **Why is this bad?** This is likely the result of an accidental semicolon. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// foo({ +/// let a = bar(); +/// baz(a); +/// }) +/// ``` +declare_lint! { + pub UNIT_ARG, + Warn, + "passing unit to a function" +} + +pub struct UnitArg; + +impl LintPass for UnitArg { + fn get_lints(&self) -> LintArray { + lint_array!(UNIT_ARG) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if in_macro(expr.span) { + return; + } + match expr.node { + ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => { + for arg in args { + if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { + let map = &cx.tcx.hir; + // apparently stuff in the desugaring of `?` can trigger this + // so check for that here + // only the calls to `Try::from_error` is marked as desugared, + // so we need to check both the current Expr and its parent. + if !is_questionmark_desugar_marked_call(expr) { + if_chain!{ + let opt_parent_node = map.find(map.get_parent_node(expr.id)); + if let Some(hir::map::NodeExpr(parent_expr)) = opt_parent_node; + if is_questionmark_desugar_marked_call(parent_expr); + then {} + else { + // `expr` and `parent_expr` where _both_ not from + // desugaring `?`, so lint + span_lint_and_sugg( + cx, + UNIT_ARG, + arg.span, + "passing a unit value to a function", + "if you intended to pass a unit value, use a unit literal instead", + "()".to_string(), + ); + } + } + } + } + } + }, + _ => (), + } + } +} + +fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { + use syntax_pos::hygiene::CompilerDesugaringKind; + if let ExprCall(ref callee, _) = expr.node { + callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark) + } else { + false + } +} + +fn is_unit(ty: Ty) -> bool { + match ty.sty { + ty::TyTuple(slice, _) if slice.is_empty() => true, + _ => false, + } +} + +fn is_unit_literal(expr: &Expr) -> bool { + match expr.node { + ExprTup(ref slice) if slice.is_empty() => true, + _ => false, + } +} + pub struct CastPass; /// **What it does:** Checks for casts from any numerical to a float type where diff --git a/tests/ui/is_unit_expr.rs b/tests/ui/is_unit_expr.rs deleted file mode 100644 index 6c8f108d9f6..00000000000 --- a/tests/ui/is_unit_expr.rs +++ /dev/null @@ -1,79 +0,0 @@ - - -#![warn(unit_expr)] -#[allow(unused_variables)] - -fn main() { - // lint should note removing the semicolon from "baz" - let x = { - "foo"; - "baz"; - }; - - - // lint should ignore false positive. - let y = if true { - "foo" - } else { - return; - }; - - // lint should note removing semicolon from "bar" - let z = if true { - "foo"; - } else { - "bar"; - }; - - - let a1 = Some(5); - - // lint should ignore false positive - let a2 = match a1 { - Some(x) => x, - _ => { - return; - }, - }; - - // lint should note removing the semicolon after `x;` - let a3 = match a1 { - Some(x) => { - x; - }, - _ => { - 0; - }, - }; - - loop { - let a2 = match a1 { - Some(x) => x, - _ => { - break; - }, - }; - let a2 = match a1 { - Some(x) => x, - _ => { - continue; - }, - }; - } -} - -pub fn foo() -> i32 { - let a2 = match None { - Some(x) => x, - _ => { - return 42; - }, - }; - 55 -} - -pub fn issue_2160() { - let x1 = {}; - let x2 = if true {} else {}; - let x3 = match None { Some(_) => {}, None => {}, }; -} diff --git a/tests/ui/is_unit_expr.stderr b/tests/ui/is_unit_expr.stderr deleted file mode 100644 index 7a16fe971f3..00000000000 --- a/tests/ui/is_unit_expr.stderr +++ /dev/null @@ -1,73 +0,0 @@ -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:8:13 - | -8 | let x = { - | _____________^ -9 | | "foo"; -10 | | "baz"; -11 | | }; - | |_____^ - | - = note: `-D unit-expr` implied by `-D warnings` -note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:10:9 - | -10 | "baz"; - | ^^^^^^ - -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:22:13 - | -22 | let z = if true { - | _____________^ -23 | | "foo"; -24 | | } else { -25 | | "bar"; -26 | | }; - | |_____^ - | -note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:25:9 - | -25 | "bar"; - | ^^^^^^ - -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:40:14 - | -40 | let a3 = match a1 { - | ______________^ -41 | | Some(x) => { -42 | | x; -43 | | }, -... | -46 | | }, -47 | | }; - | |_____^ - | -note: Consider removing the trailing semicolon - --> $DIR/is_unit_expr.rs:42:13 - | -42 | x; - | ^^ - -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:76:14 - | -76 | let x1 = {}; - | ^^ - -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:77:14 - | -77 | let x2 = if true {} else {}; - | ^^^^^^^^^^^^^^^^^^ - -error: This expression evaluates to the Unit type () - --> $DIR/is_unit_expr.rs:78:14 - | -78 | let x3 = match None { Some(_) => {}, None => {}, }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs new file mode 100644 index 00000000000..8f290446b5e --- /dev/null +++ b/tests/ui/unit_arg.rs @@ -0,0 +1,55 @@ +#![warn(unit_arg)] +#![allow(no_effect)] + +use std::fmt::Debug; + +fn foo(t: T) { + println!("{:?}", t); +} + +fn foo3(t1: T1, t2: T2, t3: T3) { + println!("{:?}, {:?}, {:?}", t1, t2, t3); +} + +struct Bar; + +impl Bar { + fn bar(&self, t: T) { + println!("{:?}", t); + } +} + +fn bad() { + foo({}); + foo({ 1; }); + foo(foo(1)); + foo({ + foo(1); + foo(2); + }); + foo3({}, 2, 2); + let b = Bar; + b.bar({ 1; }); +} + +fn ok() { + foo(()); + foo(1); + foo({ 1 }); + foo3("a", 3, vec![3]); + let b = Bar; + b.bar({ 1 }); + b.bar(()); + question_mark(); +} + +fn question_mark() -> Result<(), ()> { + Ok(Ok(())?)?; + Ok(Ok(()))??; + Ok(()) +} + +fn main() { + bad(); + ok(); +} diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr new file mode 100644 index 00000000000..ca48f39263b --- /dev/null +++ b/tests/ui/unit_arg.stderr @@ -0,0 +1,68 @@ +error: passing a unit value to a function + --> $DIR/unit_arg.rs:23:9 + | +23 | foo({}); + | ^^ + | + = note: `-D unit-arg` implied by `-D warnings` +help: if you intended to pass a unit value, use a unit literal instead + | +23 | foo(()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:24:9 + | +24 | foo({ 1; }); + | ^^^^^^ +help: if you intended to pass a unit value, use a unit literal instead + | +24 | foo(()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:25:9 + | +25 | foo(foo(1)); + | ^^^^^^ +help: if you intended to pass a unit value, use a unit literal instead + | +25 | foo(()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:26:9 + | +26 | foo({ + | _________^ +27 | | foo(1); +28 | | foo(2); +29 | | }); + | |_____^ +help: if you intended to pass a unit value, use a unit literal instead + | +26 | foo(()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:30:10 + | +30 | foo3({}, 2, 2); + | ^^ +help: if you intended to pass a unit value, use a unit literal instead + | +30 | foo3((), 2, 2); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:32:11 + | +32 | b.bar({ 1; }); + | ^^^^^^ +help: if you intended to pass a unit value, use a unit literal instead + | +32 | b.bar(()); + | ^^ + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From 5a794d3ee9f413982e8f50bbd9c48e5280e6b7fd Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 18 Jan 2018 23:05:29 +0100 Subject: Update compiletest --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e2a4f0f1fbb..040cb78d1c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ cargo_metadata = "0.2" regex = "0.2" [dev-dependencies] -compiletest_rs = "0.3" +compiletest_rs = "0.3.5" duct = "0.8.2" lazy_static = "1.0" serde_derive = "1.0" -- cgit 1.4.1-3-g733a5 From 7a6c03f876ee49754cd2a75b846bd38b17d7a1cf Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 18 Jan 2018 17:29:14 -0500 Subject: Add `is_unit_expr` to deprecated lints list --- clippy_lints/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c1472484078..3f2ae888bc0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -247,6 +247,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { "string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon", ); + store.register_removed( + "is_unit_expr", + "superseded by `let_unit_value` and `unit_arg`", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); -- cgit 1.4.1-3-g733a5 From e09805e8ca8a88d1450d145d9221223142b1928e Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 18 Jan 2018 17:33:09 -0500 Subject: Use `unit_expr` --- clippy_lints/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3f2ae888bc0..8b2da4641a2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -248,7 +248,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { "using `string::to_string` is common even today and specialization will likely happen soon", ); store.register_removed( - "is_unit_expr", + "unit_expr", "superseded by `let_unit_value` and `unit_arg`", ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` -- cgit 1.4.1-3-g733a5 From 79c6c60f511da6db0cce1707ef2923ee7038ae95 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 19 Jan 2018 08:10:09 +0200 Subject: Added further tests --- tests/ui/option_option.rs | 17 +++++++++++++++++ tests/ui/option_option.stderr | 22 +++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 88232c3b23f..249745c6a45 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -18,6 +18,16 @@ struct Struct { x: Option>, } +impl Struct { + fn struct_fn() -> Option> { + None + } +} + +trait Trait { + fn trait_fn() -> Option>; +} + enum Enum { Tuple(Option>), Struct{x: Option>}, @@ -31,6 +41,13 @@ fn output_type_alias() -> OptionOption { None } +// The line allows this +impl Trait for Struct { + fn trait_fn() -> Option> { + None + } +} + fn main() { input(None); output(); diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index ebdc4fe9266..19e00efae71 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -31,16 +31,28 @@ error: consider using `Option` instead of `Option>` or a custom enu | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:22:11 + --> $DIR/option_option.rs:22:23 | -22 | Tuple(Option>), +22 | fn struct_fn() -> Option> { + | ^^^^^^^^^^^^^^^^^^ + +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases + --> $DIR/option_option.rs:28:22 + | +28 | fn trait_fn() -> Option>; + | ^^^^^^^^^^^^^^^^^^ + +error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases + --> $DIR/option_option.rs:32:11 + | +32 | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:23:15 + --> $DIR/option_option.rs:33:15 | -23 | Struct{x: Option>}, +33 | Struct{x: Option>}, | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 8e03769bd245eef7b42a94773fcc5d7d9b4bbd24 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 19 Jan 2018 09:16:33 +0100 Subject: Disable osx builder on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 92d48101254..29879e44755 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ rust: nightly os: - linux - - osx + # - osx # doesn't even start atm. Not sure what travis is up to. Disabling to reduce the noise sudo: false -- cgit 1.4.1-3-g733a5 From 920fc174853a2a31111349d695841c5dd61f61fb Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 16 Jan 2018 15:26:32 +0100 Subject: Don't run dogfood on windows or in the rustc test suite --- tests/dogfood.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 8ca9b5c92a4..590027f8491 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -3,6 +3,9 @@ fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() { return; } + if cfg!(windows) { + return; + } let root_dir = std::env::current_dir().unwrap(); for d in &[".", "clippy_lints"] { std::env::set_current_dir(root_dir.join(d)).unwrap(); -- cgit 1.4.1-3-g733a5 From b1001e47d6933ce3a5252c0713827b1b9903984b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 16 Jan 2018 16:36:58 +0100 Subject: Disable gnu builds on appveyor, rustc plugins are broken there --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c17b12a33b3..729216d0b90 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,12 +2,12 @@ environment: global: PROJECT_NAME: rust-clippy matrix: - - TARGET: i686-pc-windows-gnu - MSYS2_BITS: 32 + #- TARGET: i686-pc-windows-gnu + # MSYS2_BITS: 32 - TARGET: i686-pc-windows-msvc MSYS2_BITS: 32 - - TARGET: x86_64-pc-windows-gnu - MSYS2_BITS: 64 + #- TARGET: x86_64-pc-windows-gnu + # MSYS2_BITS: 64 - TARGET: x86_64-pc-windows-msvc MSYS2_BITS: 64 -- cgit 1.4.1-3-g733a5 From 26f83d621889b2a7474cd0542c63c77a5a15c02e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 17 Jan 2018 08:52:41 +0100 Subject: Readd the .exe extension on windows --- src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 8affe549348..8fd485b9efa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,9 +180,12 @@ where args.push("--cfg".to_owned()); args.push(r#"feature="cargo-clippy""#.to_owned()); - let path = std::env::current_exe() + let mut path = std::env::current_exe() .expect("current executable path invalid") .with_file_name("clippy-driver"); + if cfg!(windows) { + path.set_extension("exe"); + } let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) -- cgit 1.4.1-3-g733a5 From 248bef67f2023f2c9a0af52eea1cc830c87f1b37 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 17 Jan 2018 08:53:13 +0100 Subject: Don't run 32 bit checks on windows --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 729216d0b90..a0110a546c2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,8 +4,8 @@ environment: matrix: #- TARGET: i686-pc-windows-gnu # MSYS2_BITS: 32 - - TARGET: i686-pc-windows-msvc - MSYS2_BITS: 32 + #- TARGET: i686-pc-windows-msvc + # MSYS2_BITS: 32 #- TARGET: x86_64-pc-windows-gnu # MSYS2_BITS: 64 - TARGET: x86_64-pc-windows-msvc -- cgit 1.4.1-3-g733a5 From d9063b70d3abcc2fa16200d7c49bf0db39fbc66c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 19 Jan 2018 13:12:57 +0100 Subject: Don't run cargo clippy on appveyor --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a0110a546c2..32ea8c62a2d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,9 +26,9 @@ test_script: - set RUST_BACKTRACE=1 - cargo build --features debugging - cargo test --features debugging - - copy target\debug\cargo-clippy.exe C:\Users\appveyor\.cargo\bin\ - - cargo clippy -- -D clippy - - cd clippy_lints && cargo clippy -- -D clippy && cd .. + #- copy target\debug\cargo-clippy.exe C:\Users\appveyor\.cargo\bin\ + #- cargo clippy -- -D clippy + #- cd clippy_lints && cargo clippy -- -D clippy && cd .. notifications: - provider: Email -- cgit 1.4.1-3-g733a5 From 71abd81d221235bb61fc6683e81b346234802879 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 19 Jan 2018 13:18:44 +0100 Subject: Update error count --- tests/ui/methods.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 149fa4c1796..5d3015f5e60 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -533,5 +533,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D option-unwrap-used` implied by `-D warnings` -error: aborting due to 66 previous errors +error: aborting due to 71 previous errors -- cgit 1.4.1-3-g733a5 From eb009e2de93cd3bcb2d91497db00ddca014266f9 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sat, 20 Jan 2018 23:32:02 +0100 Subject: Small documentation formatting fix --- clippy_lints/src/misc.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c9c404c1740..50ae695f4c5 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -152,8 +152,7 @@ declare_lint! { /// ```rust /// let _x = 0; /// let y = _x + 1; // Here we are using `_x`, even though it has a leading -/// underscore. -/// // We should rename `_x` to `x` +/// // underscore. We should rename `_x` to `x` /// ``` declare_lint! { pub USED_UNDERSCORE_BINDING, @@ -166,10 +165,8 @@ declare_lint! { /// statement. /// /// **Why is this bad?** Using a short circuit boolean condition as a statement -/// may -/// hide the fact that the second part is executed or not depending on the -/// outcome of -/// the first part. +/// may hide the fact that the second part is executed or not depending on the +/// outcome of the first part. /// /// **Known problems:** None. /// -- cgit 1.4.1-3-g733a5 From a2fec0e3e3a43554ea83977cb8d99f10cd56759d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 22 Jan 2018 13:23:57 +0900 Subject: Rustup to rustc 1.25.0-nightly (97520ccb1 2018-01-21) --- src/driver.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index bc766496cfb..7e0a82188f9 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -9,9 +9,11 @@ extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_plugin; +extern crate rustc_trans_utils; extern crate syntax; use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; +use rustc_trans_utils::trans_crate::TransCrate; use rustc::session::{config, Session}; use rustc::session::config::{ErrorOutputType, Input}; use std::path::PathBuf; @@ -58,6 +60,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { } fn late_callback( &mut self, + trans_crate: &TransCrate, matches: &getopts::Matches, sess: &Session, crate_stores: &rustc::middle::cstore::CrateStore, @@ -66,7 +69,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option, ) -> Compilation { self.default - .late_callback(matches, sess, crate_stores, input, odir, ofile) + .late_callback(trans_crate, matches, sess, crate_stores, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { let mut control = self.default.build_controller(sess, matches); -- cgit 1.4.1-3-g733a5 From 96cba36b46ae1ab24da8de0d75e35328f23f7ebb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 22 Jan 2018 10:35:01 +0530 Subject: Rustup to rustc 1.25.0-nightly (97520ccb1 2018-01-21) --- CHANGELOG.md | 11 ++++++++++- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 9 +++------ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7af39eda8ec..c202f256e3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.181 +* Rustup to *rustc 1.25.0-nightly (97520ccb1 2018-01-21)* +* New lints: [`else_if_without_else`], [`option_option`], [`unit_arg`], [`unnecessary_fold`] +* Removed [`unit_expr`] +* Various false positive fixes for [`needless_pass_by_value`] + ## 0.0.180 * Rustup to *rustc 1.25.0-nightly (3f92e8d89 2018-01-14)* @@ -544,6 +550,7 @@ All notable changes to this project will be documented in this file. [`drop_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_copy [`drop_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_ref [`duplicate_underscore_argument`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duplicate_underscore_argument +[`else_if_without_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum [`empty_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_loop [`enum_clike_unportable_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant @@ -653,6 +660,7 @@ All notable changes to this project will be documented in this file. [`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or [`option_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else +[`option_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_option [`option_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_unwrap_used [`or_fun_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#or_fun_call [`out_of_bounds_indexing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#out_of_bounds_indexing @@ -711,9 +719,10 @@ All notable changes to this project will be documented in this file. [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity [`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc +[`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp -[`unit_expr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_expr [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast +[`unnecessary_fold`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation [`unneeded_field_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unneeded_field_pattern diff --git a/Cargo.toml b/Cargo.toml index 040cb78d1c6..23147c6e707 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.180" +version = "0.0.181" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.180", path = "clippy_lints" } +clippy_lints = { version = "0.0.181", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 87d7c7aee66..380fc1369ba 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.180" +version = "0.0.181" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ee59745353b..3a870fe7174 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -248,10 +248,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { "string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon", ); - store.register_removed( - "unit_expr", - "superseded by `let_unit_value` and `unit_arg`", - ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); @@ -377,6 +373,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, + methods::CLONE_ON_REF_PTR, misc::FLOAT_CMP_CONST, ]); @@ -520,7 +517,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::CHARS_NEXT_CMP, methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, - methods::CLONE_ON_REF_PTR, methods::FILTER_NEXT, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, @@ -535,6 +531,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SINGLE_CHAR_PATTERN, methods::STRING_EXTEND_CHARS, methods::TEMPORARY_CSTRING_AS_PTR, + methods::UNNECESSARY_FOLD, methods::USELESS_ASREF, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, @@ -612,8 +609,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::LINKEDLIST, types::OPTION_OPTION, types::TYPE_COMPLEXITY, - types::UNIT_CMP, types::UNIT_ARG, + types::UNIT_CMP, types::UNNECESSARY_CAST, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, -- cgit 1.4.1-3-g733a5 From 2132e5c58c5b9493fdfa28dc70fd6c7e3fe47bfa Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Mon, 22 Jan 2018 05:34:42 +0000 Subject: Fix unnecessary_fold bug --- clippy_lints/src/methods.rs | 11 +++++++++-- tests/ui/methods.rs | 3 +++ tests/ui/methods.stderr | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d9b61a9e5cd..e9b82ca0ac9 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1141,6 +1141,13 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); + fn is_exactly_closure_param(expr: &hir::Expr, closure_param: ast::Name) -> bool { + if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = expr.node { + return path.segments.len() == 1 && &path.segments[0].name == &closure_param; + } + false + } + fn check_fold_with_op( cx: &LateContext, fold_args: &[hir::Expr], @@ -1162,8 +1169,8 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); - if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = left_expr.node; - if path.segments.len() == 1 && &path.segments[0].name == &first_arg_ident; + if is_exactly_closure_param(&*left_expr, first_arg_ident); + if replacement_has_args || is_exactly_closure_param(&*right_expr, second_arg_ident); then { // Span containing `.fold(...)` diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index f7a4b39c7a6..4afab4c8be6 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -419,6 +419,9 @@ fn unnecessary_fold_should_ignore() { let _ = (0..3).fold(true, |acc, x| x > 2 && acc); let _ = (0..3).fold(0, |acc, x| x + acc); let _ = (0..3).fold(1, |acc, x| x * acc); + + let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); + let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); } #[allow(similar_names)] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 5d3015f5e60..ef52d85c31f 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -526,9 +526,9 @@ error: this `.fold` can be written more succinctly using another method | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:427:13 + --> $DIR/methods.rs:430:13 | -427 | let _ = opt.unwrap(); +430 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 29f8cea5fd999629b3ca5e46e4150836c4233f05 Mon Sep 17 00:00:00 2001 From: Phil Ellison Date: Mon, 22 Jan 2018 05:46:32 +0000 Subject: Use existing match_var function --- clippy_lints/src/methods.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index e9b82ca0ac9..550b9f16e5a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -12,8 +12,8 @@ use syntax::ast; use syntax::codemap::{Span, BytePos}; use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, - match_type, method_chain_args, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, - span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; + match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, + span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; use utils::const_to_u64; @@ -1141,13 +1141,6 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); - fn is_exactly_closure_param(expr: &hir::Expr, closure_param: ast::Name) -> bool { - if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = expr.node { - return path.segments.len() == 1 && &path.segments[0].name == &closure_param; - } - false - } - fn check_fold_with_op( cx: &LateContext, fold_args: &[hir::Expr], @@ -1169,8 +1162,8 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); - if is_exactly_closure_param(&*left_expr, first_arg_ident); - if replacement_has_args || is_exactly_closure_param(&*right_expr, second_arg_ident); + if match_var(&*left_expr, first_arg_ident); + if replacement_has_args || match_var(&*right_expr, second_arg_ident); then { // Span containing `.fold(...)` -- cgit 1.4.1-3-g733a5 From 23f90afa1b9e6b7e60a9e0d510ce3446bc954380 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 23 Jan 2018 12:34:40 +0100 Subject: Add configurable threshold, default: 4096 --- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/literal_representation.rs | 47 +++++++++++++++------ clippy_lints/src/utils/conf.rs | 2 + tests/ui/bad_literal_representation.rs | 9 +--- tests/ui/bad_literal_representation.stderr | 68 ++++++------------------------ 5 files changed, 54 insertions(+), 76 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f893a3d45e3..f57092b7ff5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -354,7 +354,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); - reg.register_early_lint_pass(box literal_representation::LiteralRepresentation); + reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( + conf.literal_representation_threshold + )); reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::Pass); diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 91f01bae257..0d0e985f994 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -394,7 +394,9 @@ impl LiteralDigitGrouping { } #[derive(Copy, Clone)] -pub struct LiteralRepresentation; +pub struct LiteralRepresentation { + threshold: u64, +} impl LintPass for LiteralRepresentation { fn get_lints(&self) -> LintArray { @@ -415,6 +417,11 @@ impl EarlyLintPass for LiteralRepresentation { } impl LiteralRepresentation { + pub fn new(threshold: u64) -> Self { + Self { + threshold: threshold, + } + } fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { // Lint integral literals. if_chain! { @@ -425,11 +432,15 @@ impl LiteralRepresentation { then { let digit_info = DigitInfo::new(&src, false); if digit_info.radix == Radix::Decimal { - let hex = format!("{:#X}", digit_info.digits - .chars() - .filter(|&c| c != '_') - .collect::() - .parse::().unwrap()); + let val = digit_info.digits + .chars() + .filter(|&c| c != '_') + .collect::() + .parse::().unwrap(); + if val < self.threshold as u128 { + return + } + let hex = format!("{:#X}", val); let digit_info = DigitInfo::new(&hex[..], false); let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) @@ -440,22 +451,30 @@ impl LiteralRepresentation { } fn do_lint(digits: &str) -> Result<(), WarningType> { - if digits.len() == 2 && digits == "FF" { - return Err(WarningType::BadRepresentation); - } else if digits.len() == 3 { - // Lint for Literals with a hex-representation of 3 digits + if digits.len() == 1 { + // Lint for 1 digit literals, if someone really sets the threshold that low + if digits == "1" || digits == "2" || digits == "4" || digits == "8" || digits == "3" || digits == "7" + || digits == "F" + { + return Err(WarningType::BadRepresentation); + } + } else if digits.len() < 4 { + // Lint for Literals with a hex-representation of 2 or 3 digits let f = &digits[0..1]; // first digit let s = &digits[1..]; // suffix - // Powers of 2 minus 1 - if (f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.eq("FF") { + // Powers of 2 + if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && s.chars().all(|c| c == '0')) + // Powers of 2 minus 1 + || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.chars().all(|c| c == 'F')) + { return Err(WarningType::BadRepresentation); } - } else if digits.len() > 3 { + } else { // Lint for Literals with a hex-representation of 4 digits or more let f = &digits[0..1]; // first digit let m = &digits[1..digits.len() - 1]; // middle digits, except last let s = &digits[1..]; // suffix - // Powers of 2 with a margin of +15/-16 + // Powers of 2 with a margin of +15/-16 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && m.chars().all(|c| c == '0')) || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && m.chars().all(|c| c == 'F')) // Lint for representations with only 0s and Fs, while allowing 7 as the first diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index b13ceb8692a..e1298be81e5 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -177,6 +177,8 @@ define_Conf! { (enum_variant_size_threshold, "enum_variant_size_threshold", 200 => u64), /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), + /// Lint: BAD_LITERAL_REPRESENTATION. The lower bound for linting decimal literals + (literal_representation_threshold, "literal_representation_threshold", 4096 => u64), } /// Search for the configuration file. diff --git a/tests/ui/bad_literal_representation.rs b/tests/ui/bad_literal_representation.rs index 00126152fe1..ab12d605596 100644 --- a/tests/ui/bad_literal_representation.rs +++ b/tests/ui/bad_literal_representation.rs @@ -4,14 +4,9 @@ #[warn(bad_literal_representation)] #[allow(unused_variables)] fn main() { - // Hex: 7F, 80, 100, 800, FFA, F0F3, 7F0F_F00D - let good = (127, 128, 256, 2048, 4090, 61_683, 2_131_750_925); + // Hex: 7F, 80, 100, 1FF, 800, FFA, F0F3, 7F0F_F00D + let good = (127, 128, 256, 511, 2048, 4090, 61_683, 2_131_750_925); let bad = ( // Hex: - 255, // 0xFF - 511, // 0x1FF - 1023, // 0x3FF - 2047, // 0x7FF - 4095, // 0xFFF 4096, // 0x1000 16_371, // 0x3FF3 32_773, // 0x8005 diff --git a/tests/ui/bad_literal_representation.stderr b/tests/ui/bad_literal_representation.stderr index f57956c23d6..68e66ef1cee 100644 --- a/tests/ui/bad_literal_representation.stderr +++ b/tests/ui/bad_literal_representation.stderr @@ -1,96 +1,56 @@ error: bad representation of integer literal --> $DIR/bad_literal_representation.rs:10:9 | -10 | 255, // 0xFF - | ^^^ - | - = note: `-D bad-literal-representation` implied by `-D warnings` - = help: consider: 0xFF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:11:9 - | -11 | 511, // 0x1FF - | ^^^ - | - = help: consider: 0x1FF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:12:9 - | -12 | 1023, // 0x3FF - | ^^^^ - | - = help: consider: 0x3FF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:13:9 - | -13 | 2047, // 0x7FF - | ^^^^ - | - = help: consider: 0x7FF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:14:9 - | -14 | 4095, // 0xFFF - | ^^^^ - | - = help: consider: 0xFFF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:15:9 - | -15 | 4096, // 0x1000 +10 | 4096, // 0x1000 | ^^^^ | + = note: `-D bad-literal-representation` implied by `-D warnings` = help: consider: 0x1000 error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:16:9 + --> $DIR/bad_literal_representation.rs:11:9 | -16 | 16_371, // 0x3FF3 +11 | 16_371, // 0x3FF3 | ^^^^^^ | = help: consider: 0x3FF3 error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:17:9 + --> $DIR/bad_literal_representation.rs:12:9 | -17 | 32_773, // 0x8005 +12 | 32_773, // 0x8005 | ^^^^^^ | = help: consider: 0x8005 error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:18:9 + --> $DIR/bad_literal_representation.rs:13:9 | -18 | 65_280, // 0xFF00 +13 | 65_280, // 0xFF00 | ^^^^^^ | = help: consider: 0xFF00 error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:19:9 + --> $DIR/bad_literal_representation.rs:14:9 | -19 | 2_131_750_927, // 0x7F0F_F00F +14 | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ | = help: consider: 0x7F0F_F00F error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:20:9 + --> $DIR/bad_literal_representation.rs:15:9 | -20 | 2_147_483_647, // 0x7FFF_FFFF +15 | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ | = help: consider: 0x7FFF_FFFF error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:21:9 + --> $DIR/bad_literal_representation.rs:16:9 | -21 | 4_042_322_160, // 0xF0F0_F0F0 +16 | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ | = help: consider: 0xF0F0_F0F0 -- cgit 1.4.1-3-g733a5 From d7677fb2b66ccc3c55ab28782376d8d0055d50dd Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 23 Jan 2018 12:52:20 +0100 Subject: Adapt to updated ui tests --- tests/ui/bad_literal_representation.stderr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/bad_literal_representation.stderr b/tests/ui/bad_literal_representation.stderr index 68e66ef1cee..ed687c4026e 100644 --- a/tests/ui/bad_literal_representation.stderr +++ b/tests/ui/bad_literal_representation.stderr @@ -55,3 +55,5 @@ error: bad representation of integer literal | = help: consider: 0xF0F0_F0F0 +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 600147926bfd18b67ac53b6800dc23c09fb60704 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 23 Jan 2018 15:29:31 +0100 Subject: Apply requested changes --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/literal_representation.rs | 18 ++++---- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/bad_literal_representation.rs | 18 -------- tests/ui/bad_literal_representation.stderr | 59 -------------------------- tests/ui/decimal_literal_representation.rs | 18 ++++++++ tests/ui/decimal_literal_representation.stderr | 59 ++++++++++++++++++++++++++ tests/ui/drop_forget_copy.rs | 2 +- tests/ui/identity_op.rs | 2 +- tests/ui/identity_op.stderr | 6 ++- 10 files changed, 94 insertions(+), 92 deletions(-) delete mode 100644 tests/ui/bad_literal_representation.rs delete mode 100644 tests/ui/bad_literal_representation.stderr create mode 100644 tests/ui/decimal_literal_representation.rs create mode 100644 tests/ui/decimal_literal_representation.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f57092b7ff5..e14e20011e1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -488,7 +488,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, - literal_representation::BAD_LITERAL_REPRESENTATION, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_INTO_ITER_LOOP, diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 0d0e985f994..a0c4f537a15 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -75,7 +75,7 @@ declare_lint! { /// `65_535` => `0xFFFF` /// `4_042_322_160` => `0xF0F0_F0F0` declare_lint! { - pub BAD_LITERAL_REPRESENTATION, + pub DECIMAL_LITERAL_REPRESENTATION, Warn, "using decimal representation when hexadecimal would be better" } @@ -217,7 +217,7 @@ enum WarningType { UnreadableLiteral, InconsistentDigitGrouping, LargeDigitGroups, - BadRepresentation, + DecimalRepresentation, } impl WarningType { @@ -244,11 +244,11 @@ impl WarningType { "digits grouped inconsistently by underscores", &format!("consider: {}", grouping_hint), ), - WarningType::BadRepresentation => span_help_and_lint( + WarningType::DecimalRepresentation => span_help_and_lint( cx, - BAD_LITERAL_REPRESENTATION, + DECIMAL_LITERAL_REPRESENTATION, *span, - "bad representation of integer literal", + "integer literal has a better hexadecimal representation", &format!("consider: {}", grouping_hint), ), }; @@ -400,7 +400,7 @@ pub struct LiteralRepresentation { impl LintPass for LiteralRepresentation { fn get_lints(&self) -> LintArray { - lint_array!(BAD_LITERAL_REPRESENTATION) + lint_array!(DECIMAL_LITERAL_REPRESENTATION) } } @@ -456,7 +456,7 @@ impl LiteralRepresentation { if digits == "1" || digits == "2" || digits == "4" || digits == "8" || digits == "3" || digits == "7" || digits == "F" { - return Err(WarningType::BadRepresentation); + return Err(WarningType::DecimalRepresentation); } } else if digits.len() < 4 { // Lint for Literals with a hex-representation of 2 or 3 digits @@ -467,7 +467,7 @@ impl LiteralRepresentation { // Powers of 2 minus 1 || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.chars().all(|c| c == 'F')) { - return Err(WarningType::BadRepresentation); + return Err(WarningType::DecimalRepresentation); } } else { // Lint for Literals with a hex-representation of 4 digits or more @@ -481,7 +481,7 @@ impl LiteralRepresentation { // digit || ((f.eq("7") || f.eq("F")) && s.chars().all(|c| c == '0' || c == 'F')) { - return Err(WarningType::BadRepresentation); + return Err(WarningType::DecimalRepresentation); } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index e1298be81e5..2906da3c028 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -177,7 +177,7 @@ define_Conf! { (enum_variant_size_threshold, "enum_variant_size_threshold", 200 => u64), /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), - /// Lint: BAD_LITERAL_REPRESENTATION. The lower bound for linting decimal literals + /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals (literal_representation_threshold, "literal_representation_threshold", 4096 => u64), } diff --git a/tests/ui/bad_literal_representation.rs b/tests/ui/bad_literal_representation.rs deleted file mode 100644 index ab12d605596..00000000000 --- a/tests/ui/bad_literal_representation.rs +++ /dev/null @@ -1,18 +0,0 @@ - - - -#[warn(bad_literal_representation)] -#[allow(unused_variables)] -fn main() { - // Hex: 7F, 80, 100, 1FF, 800, FFA, F0F3, 7F0F_F00D - let good = (127, 128, 256, 511, 2048, 4090, 61_683, 2_131_750_925); - let bad = ( // Hex: - 4096, // 0x1000 - 16_371, // 0x3FF3 - 32_773, // 0x8005 - 65_280, // 0xFF00 - 2_131_750_927, // 0x7F0F_F00F - 2_147_483_647, // 0x7FFF_FFFF - 4_042_322_160, // 0xF0F0_F0F0 - ); -} diff --git a/tests/ui/bad_literal_representation.stderr b/tests/ui/bad_literal_representation.stderr deleted file mode 100644 index ed687c4026e..00000000000 --- a/tests/ui/bad_literal_representation.stderr +++ /dev/null @@ -1,59 +0,0 @@ -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:10:9 - | -10 | 4096, // 0x1000 - | ^^^^ - | - = note: `-D bad-literal-representation` implied by `-D warnings` - = help: consider: 0x1000 - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:11:9 - | -11 | 16_371, // 0x3FF3 - | ^^^^^^ - | - = help: consider: 0x3FF3 - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:12:9 - | -12 | 32_773, // 0x8005 - | ^^^^^^ - | - = help: consider: 0x8005 - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:13:9 - | -13 | 65_280, // 0xFF00 - | ^^^^^^ - | - = help: consider: 0xFF00 - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:14:9 - | -14 | 2_131_750_927, // 0x7F0F_F00F - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7F0F_F00F - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:15:9 - | -15 | 2_147_483_647, // 0x7FFF_FFFF - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7FFF_FFFF - -error: bad representation of integer literal - --> $DIR/bad_literal_representation.rs:16:9 - | -16 | 4_042_322_160, // 0xF0F0_F0F0 - | ^^^^^^^^^^^^^ - | - = help: consider: 0xF0F0_F0F0 - -error: aborting due to 7 previous errors - diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs new file mode 100644 index 00000000000..3ac33d7ac4a --- /dev/null +++ b/tests/ui/decimal_literal_representation.rs @@ -0,0 +1,18 @@ + + + +#[warn(decimal_literal_representation)] +#[allow(unused_variables)] +fn main() { + // Hex: 7F, 80, 100, 1FF, 800, FFA, F0F3, 7F0F_F00D + let good = (127, 128, 256, 511, 2048, 4090, 61_683, 2_131_750_925); + let bad = ( // Hex: + 4096, // 0x1000 + 16_371, // 0x3FF3 + 32_773, // 0x8005 + 65_280, // 0xFF00 + 2_131_750_927, // 0x7F0F_F00F + 2_147_483_647, // 0x7FFF_FFFF + 4_042_322_160, // 0xF0F0_F0F0 + ); +} diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr new file mode 100644 index 00000000000..bd3c727b728 --- /dev/null +++ b/tests/ui/decimal_literal_representation.stderr @@ -0,0 +1,59 @@ +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:10:9 + | +10 | 4096, // 0x1000 + | ^^^^ + | + = note: `-D decimal-literal-representation` implied by `-D warnings` + = help: consider: 0x1000 + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:11:9 + | +11 | 16_371, // 0x3FF3 + | ^^^^^^ + | + = help: consider: 0x3FF3 + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:12:9 + | +12 | 32_773, // 0x8005 + | ^^^^^^ + | + = help: consider: 0x8005 + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:13:9 + | +13 | 65_280, // 0xFF00 + | ^^^^^^ + | + = help: consider: 0xFF00 + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:14:9 + | +14 | 2_131_750_927, // 0x7F0F_F00F + | ^^^^^^^^^^^^^ + | + = help: consider: 0x7F0F_F00F + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:15:9 + | +15 | 2_147_483_647, // 0x7FFF_FFFF + | ^^^^^^^^^^^^^ + | + = help: consider: 0x7FFF_FFFF + +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:16:9 + | +16 | 4_042_322_160, // 0xF0F0_F0F0 + | ^^^^^^^^^^^^^ + | + = help: consider: 0xF0F0_F0F0 + +error: aborting due to 7 previous errors + diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index a4d38d99c95..9fef06b0ede 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -42,7 +42,7 @@ fn main() { forget(s4); forget(s5); - let a1 = AnotherStruct {x: 0xFF, y: 0, z: vec![1, 2, 3]}; + let a1 = AnotherStruct {x: 255, y: 0, z: vec![1, 2, 3]}; let a2 = &a1; let mut a3 = a1.clone(); let ref a4 = a1; diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index d4bc7df4424..1ed9f974d43 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -29,5 +29,5 @@ fn main() { -1 & x; let u : u8 = 0; - u & 0xFF; + u & 255; } diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index b3f7bb713e6..45f579ce832 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -45,6 +45,8 @@ error: the operation is ineffective. Consider reducing it to `x` error: the operation is ineffective. Consider reducing it to `u` --> $DIR/identity_op.rs:32:5 | -32 | u & 0xFF; - | ^^^^^^^^ +32 | u & 255; + | ^^^^^^^ + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 31892e205e7b03ea3dc3a7d31f5e5f2f25dee058 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 23 Jan 2018 16:52:14 +0100 Subject: let invalid_regex point to the right place for raw strings --- clippy_lints/src/regex.rs | 7 +++--- tests/ui/regex.rs | 3 +++ tests/ui/regex.stderr | 58 ++++++++++++++++++++++++++++------------------- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index beb24a3dbe4..bbb70e0cdea 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -7,7 +7,7 @@ use rustc_const_eval::ConstContext; use rustc::ty::subst::Substs; use std::collections::HashSet; use std::error::Error; -use syntax::ast::{LitKind, NodeId}; +use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; use utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; @@ -199,8 +199,9 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo let builder = regex_syntax::ExprBuilder::new().unicode(utf8); if let ExprLit(ref lit) = expr.node { - if let LitKind::Str(ref r, _) = lit.node { + if let LitKind::Str(ref r, style) = lit.node { let r = &r.as_str(); + let offset = if let StrStyle::Raw(n) = style { 1 + n } else { 0 }; match builder.parse(r) { Ok(r) => if let Some(repl) = is_trivial_regex(&r) { span_help_and_lint( @@ -215,7 +216,7 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo span_lint( cx, INVALID_REGEX, - str_span(expr.span, r, e.position()), + str_span(expr.span, r, e.position() + offset), &format!("regex syntax error: {}", e.description()), ); }, diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 2007f1fad55..37c98027fcc 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -44,6 +44,9 @@ fn syntax_error() { OPENING_PAREN, r"[a-z]+\.(com|org|net)", ]); + + let raw_string_error = Regex::new(r"[...\/...]"); + let raw_string_error = Regex::new(r#"[...\/...]"#); } fn trivial_regex() { diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 433061e41fb..58c6e47afb7 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -60,94 +60,106 @@ error: regex syntax error on position 0: unclosed parenthesis 44 | OPENING_PAREN, | ^^^^^^^^^^^^^ +error: regex syntax error: unrecognized escape sequence + --> $DIR/regex.rs:48:45 + | +48 | let raw_string_error = Regex::new(r"[...//...]"); + | ^ + +error: regex syntax error: unrecognized escape sequence + --> $DIR/regex.rs:49:46 + | +49 | let raw_string_error = Regex::new(r#"[...//...]"#); + | ^ + error: trivial regex - --> $DIR/regex.rs:50:33 + --> $DIR/regex.rs:53:33 | -50 | let trivial_eq = Regex::new("^foobar$"); +53 | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | = note: `-D trivial-regex` implied by `-D warnings` = help: consider using consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:52:48 + --> $DIR/regex.rs:55:48 | -52 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); +55 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:54:42 + --> $DIR/regex.rs:57:42 | -54 | let trivial_starts_with = Regex::new("^foobar"); +57 | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | = help: consider using consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:56:40 + --> $DIR/regex.rs:59:40 | -56 | let trivial_ends_with = Regex::new("foobar$"); +59 | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | = help: consider using consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:58:39 + --> $DIR/regex.rs:61:39 | -58 | let trivial_contains = Regex::new("foobar"); +61 | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | = help: consider using consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:60:39 + --> $DIR/regex.rs:63:39 | -60 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); +63 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | = help: consider using consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:62:40 + --> $DIR/regex.rs:65:40 | -62 | let trivial_backslash = Regex::new("a/.b"); +65 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:65:36 + --> $DIR/regex.rs:68:36 | -65 | let trivial_empty = Regex::new(""); +68 | let trivial_empty = Regex::new(""); | ^^ | = help: consider using the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:67:36 + --> $DIR/regex.rs:70:36 | -67 | let trivial_empty = Regex::new("^"); +70 | let trivial_empty = Regex::new("^"); | ^^^ | = help: consider using the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:69:36 + --> $DIR/regex.rs:72:36 | -69 | let trivial_empty = Regex::new("^$"); +72 | let trivial_empty = Regex::new("^$"); | ^^^^ | = help: consider using consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:71:44 + --> $DIR/regex.rs:74:44 | -71 | let binary_trivial_empty = BRegex::new("^$"); +74 | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using consider using `str::is_empty` -error: aborting due to 21 previous errors +error: aborting due to 23 previous errors -- cgit 1.4.1-3-g733a5 From ea042657e53a355dd242d1857db9ed72f5205415 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 24 Jan 2018 13:04:06 +0100 Subject: Enable more patterns in the author lint --- clippy_lints/src/utils/author.rs | 49 ++++++++++++++++++++++++++++++++-------- tests/ui/for_loop.rs | 4 ++-- tests/ui/for_loop.stderr | 6 ++--- tests/ui/for_loop.stdout | 20 ++++++++++++++++ 4 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 tests/ui/for_loop.stdout diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index eadc672e56b..c824c8906a7 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -288,16 +288,27 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = then_pat; self.visit_expr(then); }, - Expr_::ExprWhile(ref _cond, ref _body, ref _opt_label) => { - println!("While(ref cond, ref body, ref opt_label) = {};", current); - println!(" // unimplemented: `ExprWhile` is not further destructured at the moment"); - }, - Expr_::ExprLoop(ref _body, ref _opt_label, ref _desuraging) => { - println!("Loop(ref body, ref opt_label, ref desugaring) = {};", current); - println!(" // unimplemented: `ExprLoop` is not further destructured at the moment"); - }, - Expr_::ExprMatch(ref _expr, ref _arms, ref _desugaring) => { - println!("Match(ref expr, ref arms, ref desugaring) = {};", current); + Expr_::ExprWhile(ref cond, ref body, _) => { + let cond_pat = self.next("cond"); + let body_pat = self.next("body"); + let label_pat = self.next("label"); + println!("While(ref {}, ref {}, ref {}) = {};", cond_pat, body_pat, label_pat, current); + self.current = cond_pat; + self.visit_expr(cond); + self.current = body_pat; + self.visit_block(body); + }, + Expr_::ExprLoop(ref body, _, desugaring) => { + let body_pat = self.next("body"); + let des = loop_desugaring_name(desugaring); + let label_pat = self.next("label"); + println!("Loop(ref {}, ref {}, {}) = {};", body_pat, label_pat, des, current); + self.current = body_pat; + self.visit_block(body); + }, + Expr_::ExprMatch(ref _expr, ref _arms, desugaring) => { + let des = desugaring_name(desugaring); + println!("Match(ref expr, ref arms, {}) = {};", des, current); println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); }, Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { @@ -456,6 +467,24 @@ fn has_attr(attrs: &[Attribute]) -> bool { }) } +fn desugaring_name(des: hir::MatchSource) -> String { + match des { + hir::MatchSource::ForLoopDesugar => "MatchSource::ForLoopDesugar".to_string(), + hir::MatchSource::TryDesugar => "MatchSource::TryDesugar".to_string(), + hir::MatchSource::WhileLetDesugar => "MatchSource::WhileLetDesugar".to_string(), + hir::MatchSource::Normal => "MatchSource::Normal".to_string(), + hir::MatchSource::IfLetDesugar { contains_else_clause } => format!("MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", contains_else_clause), + } +} + +fn loop_desugaring_name(des: hir::LoopSource) -> &'static str { + match des { + hir::LoopSource::ForLoop => "LoopSource::ForLoop", + hir::LoopSource::Loop => "LoopSource::Loop", + hir::LoopSource::WhileLet => "LoopSource::WhileLet", + } +} + fn print_path(path: &QPath, first: &mut bool) { match *path { QPath::Resolved(_, ref path) => for segment in &path.segments { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 03630f87108..d606e7a15fc 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin, inclusive_range_syntax)] +#![feature(plugin, inclusive_range_syntax, custom_attribute)] use std::collections::*; @@ -14,7 +14,7 @@ fn for_loop_over_option_and_result() { let v = vec![0, 1, 2]; // check FOR_LOOP_OVER_OPTION lint - for x in option { + #[clippy(author)]for x in option { println!("{}", x); } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 1e7ff40e1ac..e588bfa0849 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,8 +1,8 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:17:14 + --> $DIR/for_loop.rs:17:31 | -17 | for x in option { - | ^^^^^^ +17 | #[clippy(author)]for x in option { + | ^^^^^^ | = note: `-D for-loop-over-option` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` diff --git a/tests/ui/for_loop.stdout b/tests/ui/for_loop.stdout new file mode 100644 index 00000000000..ce4186fa6a1 --- /dev/null +++ b/tests/ui/for_loop.stdout @@ -0,0 +1,20 @@ +if_chain! { + if let Expr_::ExprBlock(ref block) = stmt.node; + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; + // unimplemented: `ExprMatch` is not further destructured at the moment + if let Expr_::ExprPath(ref path) = block.node; + if match_qpath(path, &["_result"]); + then { + // report your lint here + } +} +if_chain! { + if let Expr_::ExprBlock(ref block) = expr.node; + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; + // unimplemented: `ExprMatch` is not further destructured at the moment + if let Expr_::ExprPath(ref path) = block.node; + if match_qpath(path, &["_result"]); + then { + // report your lint here + } +} -- cgit 1.4.1-3-g733a5 From 383cc9e545efd0c02f907a38562f427be0d40332 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Jan 2018 12:55:58 +0530 Subject: Add known false positive for enum_glob_use --- clippy_lints/src/enum_glob_use.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 9aa43653ab5..c00cdc07f84 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -12,7 +12,8 @@ use utils::span_lint; /// an enumeration variant, rather than importing variants. /// /// **Known problems:** Old-style enumerations that prefix the variants are -/// still around. +/// still around. May cause problems with modules that are not snake_case (see +/// [#2397](https://github.com/rust-lang-nursery/rust-clippy/issues/2397)) /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 54370500135a0803232cf03521d5fd5ea3009e8d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Jan 2018 13:14:04 +0530 Subject: Rustup to rustc 1.25.0-nightly (a0dcecff9 2018-01-24) --- clippy_lints/src/misc_early.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 4e45525ed09..8ac0c4bf098 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -296,7 +296,7 @@ impl EarlyLintPass for MiscEarly { } match expr.node { ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { + if let ExprKind::Closure(_, _, ref decl, ref block, _) = closure.node { span_lint_and_then( cx, REDUNDANT_CLOSURE_CALL, @@ -327,7 +327,7 @@ impl EarlyLintPass for MiscEarly { if_chain! { if let StmtKind::Local(ref local) = w[0].node; if let Option::Some(ref t) = local.init; - if let ExprKind::Closure(_, _, _, _) = t.node; + if let ExprKind::Closure(_, _, _, _, _) = t.node; if let PatKind::Ident(_, sp_ident, _) = local.pat.node; if let StmtKind::Semi(ref second) = w[1].node; if let ExprKind::Assign(_, ref call) = second.node; -- cgit 1.4.1-3-g733a5 From 930a8c6cab34133aa0bafbdcf041169189df1863 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 25 Jan 2018 08:58:47 +0100 Subject: Version Bump --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c202f256e3b..6140de473a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.182 +* Rustup to *rustc 1.25.0-nightly (a0dcecff9 2018-01-24)* +* New lint: [`decimal_literal_representation`] + ## 0.0.181 * Rustup to *rustc 1.25.0-nightly (97520ccb1 2018-01-21)* * New lints: [`else_if_without_else`], [`option_option`], [`unit_arg`], [`unnecessary_fold`] @@ -540,6 +544,7 @@ All notable changes to this project will be documented in this file. [`const_static_lifetime`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#const_static_lifetime [`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity +[`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation [`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof [`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq diff --git a/Cargo.toml b/Cargo.toml index 23147c6e707..c285dd10140 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.181" +version = "0.0.182" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.181", path = "clippy_lints" } +clippy_lints = { version = "0.0.182", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 380fc1369ba..1616b6f1ef0 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.181" +version = "0.0.182" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 037b9f82729..3920b7e6c68 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -490,10 +490,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { let_if_seq::USELESS_LET_IF_SEQ, lifetimes::NEEDLESS_LIFETIMES, lifetimes::UNUSED_LIFETIMES, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, - literal_representation::DECIMAL_LITERAL_REPRESENTATION, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_INTO_ITER_LOOP, -- cgit 1.4.1-3-g733a5 From 0413b3f6cf6db900ad86cb9df3a2877fdce59207 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 25 Jan 2018 00:33:41 -0800 Subject: Add misaligned_transmute lint --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/transmute.rs | 35 +++++++++++++++++++++++++++++++++-- clippy_lints/src/utils/mod.rs | 7 ++++++- tests/ui/transmute.rs | 7 +++++++ tests/ui/transmute.stderr | 10 +++++++++- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3920b7e6c68..a4e18c7eec3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -603,6 +603,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, + transmute::MISALIGNED_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 1028381e20a..090f9397472 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -3,7 +3,8 @@ use rustc::ty::{self, Ty}; use rustc::hir::*; use std::borrow::Cow; use syntax::ast; -use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; +use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, + alignment}; use utils::{opt_def_id, sugg}; /// **What it does:** Checks for transmutes that can't ever be correct on any @@ -168,6 +169,23 @@ declare_lint! { "transmutes from an integer to a float" } +/// **What it does:** Checks for transmutes to a potentially less-aligned type. +/// +/// **Why is this bad?** This might result in undefined behavior. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // u32 is 32-bit aligned; u8 is 8-bit aligned +/// let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; +/// ``` +declare_lint! { + pub MISALIGNED_TRANSMUTE, + Warn, + "transmutes to a potentially less-aligned type" +} + pub struct Transmute; impl LintPass for Transmute { @@ -180,7 +198,8 @@ impl LintPass for Transmute { TRANSMUTE_INT_TO_CHAR, TRANSMUTE_BYTES_TO_STR, TRANSMUTE_INT_TO_BOOL, - TRANSMUTE_INT_TO_FLOAT + TRANSMUTE_INT_TO_FLOAT, + MISALIGNED_TRANSMUTE ) } } @@ -201,6 +220,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), + _ if alignment(cx, from_ty).map(|a| a.abi()) + < alignment(cx, to_ty).map(|a| a.abi()) + => span_lint( + cx, + MISALIGNED_TRANSMUTE, + e.span, + &format!( + "transmute from `{}` to a less-aligned type (`{}`)", + from_ty, + to_ty, + ) + ), (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( cx, USELESS_TRANSMUTE, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4019321d711..b7f1e7b2454 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::LayoutOf; +use rustc::ty::layout::{LayoutOf, Align}; use rustc_errors; use std::borrow::Cow; use std::env; @@ -1056,3 +1056,8 @@ pub fn get_arg_name(pat: &Pat) -> Option { _ => None, } } + +/// Returns alignment for a type, or None if alignment is undefined +pub fn alignment<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { + (cx.tcx, cx.param_env).layout_of(ty).ok().map(|layout| layout.align) +} diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index b04297f01fb..48b89c33ab9 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -140,4 +140,11 @@ fn bytes_to_str(b: &[u8], mb: &mut [u8]) { let _: &mut str = unsafe { std::mem::transmute(mb) }; } +#[warn(misaligned_transmute)] +fn misaligned_transmute() { + let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err + let _: u32 = unsafe { std::mem::transmute(0f32) }; // ok (alignment-wise) + let _: [u8; 4] = unsafe { std::mem::transmute(0u32) }; // ok (alignment-wise) +} + fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index f3ac9a101ae..74bbf95d525 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -204,5 +204,13 @@ error: transmute from a `&mut [u8]` to a `&mut str` 140 | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: aborting due to 32 previous errors +error: transmute from `[u8; 4]` to a less-aligned type (`u32`) + --> $DIR/transmute.rs:145:27 + | +145 | let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D misaligned-transmute` implied by `-D warnings` + +error: aborting due to 33 previous errors -- cgit 1.4.1-3-g733a5 From daa39b3be1a67dfa3124551c2792a028b9a34cad Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 27 Jan 2018 14:57:31 +0200 Subject: Fix compilation Fix the compilation broken by these two changes: + https://github.com/rust-lang/rust/commit/2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd#diff-7fceb7ede15b205bf5ad812c31d75384L1459 + https://github.com/rust-lang/rust/commit/ccf0d8399e1ef3ed6bf7005650ce42aa646b5cc7#diff-64b696b0ef6ad44140e973801ed82b25L2771 --- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/unused_label.rs | 6 +++--- clippy_lints/src/utils/hir_utils.rs | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index dfdbe97cef4..ca1d987dbf2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1808,7 +1808,7 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { /// passed expression. The expression may be within a block. fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { - ExprBreak(dest, ref passed_expr) if dest.ident.is_none() && passed_expr.is_none() => true, + ExprBreak(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, ExprBlock(ref b) => match extract_first_expr(b) { Some(subexpr) => is_simple_break_expr(subexpr), None => false, diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 6f91b873a48..37e7c5e3bd4 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -69,11 +69,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.ident { - self.labels.remove(&label.node.name.as_str()); + hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.label { + self.labels.remove(&label.name.as_str()); }, hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { - self.labels.insert(label.node.as_str(), expr.span); + self.labels.insert(label.name.as_str(), expr.span); }, _ => (), } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 397b925a566..5932c41dc13 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), (&ExprAgain(li), &ExprAgain(ri)) => { - both(&li.ident, &ri.ident, |l, r| l.node.name.as_str() == r.node.name.as_str()) + both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str()) }, (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { @@ -87,7 +87,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }) }, (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => { - both(&li.ident, &ri.ident, |l, r| l.node.name.as_str() == r.node.name.as_str()) + both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str()) && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), @@ -105,7 +105,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprLoop(ref lb, ref ll, ref lls), &ExprLoop(ref rb, ref rl, ref rls)) => { - lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) + lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprArray(ref l), &ExprArray(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) }, _ => false, } @@ -327,8 +327,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { ExprAgain(i) => { let c: fn(_) -> _ = ExprAgain; c.hash(&mut self.s); - if let Some(i) = i.ident { - self.hash_name(&i.node.name); + if let Some(i) = i.label { + self.hash_name(&i.name); } }, ExprYield(ref e) => { @@ -364,8 +364,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { ExprBreak(i, ref j) => { let c: fn(_, _) -> _ = ExprBreak; c.hash(&mut self.s); - if let Some(i) = i.ident { - self.hash_name(&i.node.name); + if let Some(i) = i.label { + self.hash_name(&i.name); } if let Some(ref j) = *j { self.hash_expr(&*j); @@ -429,7 +429,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { - self.hash_name(&i.node); + self.hash_name(&i.name); } }, ExprMatch(ref e, ref arms, ref s) => { @@ -524,7 +524,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(cond); self.hash_block(b); if let Some(l) = l { - self.hash_name(&l.node); + self.hash_name(&l.name); } }, } -- cgit 1.4.1-3-g733a5 From e40bc64f4fcf9617af5c0e3d7b69fdca3b61b31a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 28 Jan 2018 16:28:48 +0900 Subject: Rustup to rustc 1.25.0-nightly (7d6e5b9da 2018-01-27) --- clippy_lints/src/methods.rs | 3 ++- clippy_lints/src/utils/sugg.rs | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 550b9f16e5a..04a5f157cf3 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1167,7 +1167,8 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E then { // Span containing `.fold(...)` - let fold_span = fold_args[0].span.next_point().with_hi(fold_args[2].span.hi() + BytePos(1)); + let next_point = cx.sess().codemap().next_point(fold_args[0].span); + let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1)); let sugg = if replacement_has_args { format!( diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 2f651917bc1..e18c1274498 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -502,9 +502,8 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) { let mut remove_span = item; - let fmpos = cx.sess() - .codemap() - .lookup_byte_offset(remove_span.next_point().hi()); + let hi = cx.sess().codemap().next_point(remove_span).hi(); + let fmpos = cx.sess().codemap().lookup_byte_offset(hi); if let Some(ref src) = fmpos.fm.src { let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); -- cgit 1.4.1-3-g733a5 From 7a69a4c82d9954b2b456546770abf6038d3024c9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jan 2018 05:37:47 +0900 Subject: Remove an unused binary file --- main | Bin 558396 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 main diff --git a/main b/main deleted file mode 100755 index c5f9f914d33..00000000000 Binary files a/main and /dev/null differ -- cgit 1.4.1-3-g733a5 From bca80a83a51fa34e60f1a79243b5ec8c9cd2e192 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 29 Jan 2018 09:48:06 +0530 Subject: mut_mut_macro is missing plugin(clippy) --- tests/mut_mut_macro.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs index adc308626b1..a6473b0f909 100644 --- a/tests/mut_mut_macro.rs +++ b/tests/mut_mut_macro.rs @@ -1,5 +1,5 @@ - - +#![feature(plugin)] +#![plugin(clippy)] #![deny(mut_mut, zero_ptr, cmp_nan)] #![allow(dead_code)] -- cgit 1.4.1-3-g733a5 From 4b9a0b86441a92e5f83a2c5c941590846ab7e2ff Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 29 Jan 2018 09:48:11 +0530 Subject: Update spans --- tests/ui/for_loop.stderr | 310 +++++++++++++---------------------- tests/ui/needless_range_loop.stderr | 37 ++--- tests/ui/range_plus_minus_one.stderr | 35 +--- tests/ui/while_loop.stderr | 27 ++- 4 files changed, 149 insertions(+), 260 deletions(-) diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index e588bfa0849..261a403de57 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -25,12 +25,10 @@ error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:32:5 + --> $DIR/for_loop.rs:32:14 | -32 | / for x in v.iter().next() { -33 | | println!("{}", x); -34 | | } - | |_____^ +32 | for x in v.iter().next() { + | ^^^^^^^^^^^^^^^ | = note: `-D iter-next-loop` implied by `-D warnings` @@ -71,12 +69,10 @@ error: this loop never actually loops | |_____^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:86:5 + --> $DIR/for_loop.rs:86:14 | -86 | / for i in 0..vec.len() { -87 | | println!("{}", vec[i]); -88 | | } - | |_____^ +86 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ | = note: `-D needless-range-loop` implied by `-D warnings` help: consider using an iterator @@ -85,156 +81,130 @@ help: consider using an iterator | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:95:5 + --> $DIR/for_loop.rs:95:14 | -95 | / for i in 0..vec.len() { -96 | | let _ = vec[i]; -97 | | } - | |_____^ +95 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator | 95 | for in &vec { | error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:100:5 + --> $DIR/for_loop.rs:100:14 | -100 | / for j in 0..4 { -101 | | println!("{:?}", STATIC[j]); -102 | | } - | |_____^ +100 | for j in 0..4 { + | ^^^^ help: consider using an iterator | 100 | for in STATIC.iter().take(4) { | error: the loop variable `j` is only used to index `CONST`. - --> $DIR/for_loop.rs:104:5 + --> $DIR/for_loop.rs:104:14 | -104 | / for j in 0..4 { -105 | | println!("{:?}", CONST[j]); -106 | | } - | |_____^ +104 | for j in 0..4 { + | ^^^^ help: consider using an iterator | 104 | for in CONST.iter().take(4) { | error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:108:5 + --> $DIR/for_loop.rs:108:14 | -108 | / for i in 0..vec.len() { -109 | | println!("{} {}", vec[i], i); -110 | | } - | |_____^ +108 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator | 108 | for (i, ) in vec.iter().enumerate() { | error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:116:5 + --> $DIR/for_loop.rs:116:14 | -116 | / for i in 0..vec.len() { -117 | | println!("{}", vec2[i]); -118 | | } - | |_____^ +116 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator | 116 | for in vec2.iter().take(vec.len()) { | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:120:5 + --> $DIR/for_loop.rs:120:14 | -120 | / for i in 5..vec.len() { -121 | | println!("{}", vec[i]); -122 | | } - | |_____^ +120 | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator | 120 | for in vec.iter().skip(5) { | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:124:5 + --> $DIR/for_loop.rs:124:14 | -124 | / for i in 0..MAX_LEN { -125 | | println!("{}", vec[i]); -126 | | } - | |_____^ +124 | for i in 0..MAX_LEN { + | ^^^^^^^^^^ help: consider using an iterator | 124 | for in vec.iter().take(MAX_LEN) { | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:128:5 + --> $DIR/for_loop.rs:128:14 | -128 | / for i in 0..=MAX_LEN { -129 | | println!("{}", vec[i]); -130 | | } - | |_____^ +128 | for i in 0..=MAX_LEN { + | ^^^^^^^^^^^ help: consider using an iterator | 128 | for in vec.iter().take(MAX_LEN + 1) { | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:132:5 + --> $DIR/for_loop.rs:132:14 | -132 | / for i in 5..10 { -133 | | println!("{}", vec[i]); -134 | | } - | |_____^ +132 | for i in 5..10 { + | ^^^^^ help: consider using an iterator | 132 | for in vec.iter().take(10).skip(5) { | error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:136:5 + --> $DIR/for_loop.rs:136:14 | -136 | / for i in 5..=10 { -137 | | println!("{}", vec[i]); -138 | | } - | |_____^ +136 | for i in 5..=10 { + | ^^^^^^ help: consider using an iterator | 136 | for in vec.iter().take(10 + 1).skip(5) { | error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:140:5 + --> $DIR/for_loop.rs:140:14 | -140 | / for i in 5..vec.len() { -141 | | println!("{} {}", vec[i], i); -142 | | } - | |_____^ +140 | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator | 140 | for (i, ) in vec.iter().enumerate().skip(5) { | error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:144:5 + --> $DIR/for_loop.rs:144:14 | -144 | / for i in 5..10 { -145 | | println!("{} {}", vec[i], i); -146 | | } - | |_____^ +144 | for i in 5..10 { + | ^^^^^ help: consider using an iterator | 144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:148:5 + --> $DIR/for_loop.rs:148:14 | -148 | / for i in 10..0 { -149 | | println!("{}", i); -150 | | } - | |_____^ +148 | for i in 10..0 { + | ^^^^^ | = note: `-D reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse @@ -243,68 +213,56 @@ help: consider using the following if you are attempting to iterate over this ra | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:152:5 + --> $DIR/for_loop.rs:152:14 | -152 | / for i in 10..=0 { -153 | | println!("{}", i); -154 | | } - | |_____^ +152 | for i in 10..=0 { + | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | 152 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:156:5 + --> $DIR/for_loop.rs:156:14 | -156 | / for i in MAX_LEN..0 { -157 | | println!("{}", i); -158 | | } - | |_____^ +156 | for i in MAX_LEN..0 { + | ^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | 156 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:160:5 + --> $DIR/for_loop.rs:160:14 | -160 | / for i in 5..5 { -161 | | println!("{}", i); -162 | | } - | |_____^ +160 | for i in 5..5 { + | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:185:5 + --> $DIR/for_loop.rs:185:14 | -185 | / for i in 10..5 + 4 { -186 | | println!("{}", i); -187 | | } - | |_____^ +185 | for i in 10..5 + 4 { + | ^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | 185 | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:189:5 + --> $DIR/for_loop.rs:189:14 | -189 | / for i in (5 + 2)..(3 - 1) { -190 | | println!("{}", i); -191 | | } - | |_____^ +189 | for i in (5 + 2)..(3 - 1) { + | ^^^^^^^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | 189 | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:193:5 + --> $DIR/for_loop.rs:193:14 | -193 | / for i in (5 + 2)..(8 - 1) { -194 | | println!("{}", i); -195 | | } - | |_____^ +193 | for i in (5 + 2)..(8 - 1) { + | ^^^^^^^^^^^^^^^^ error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:215:15 @@ -389,10 +347,10 @@ error: it is more idiomatic to loop over references to containers instead of usi | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:257:5 + --> $DIR/for_loop.rs:257:15 | 257 | for _v in vec.iter().next() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator --> $DIR/for_loop.rs:264:5 @@ -403,30 +361,24 @@ error: you are collect()ing an iterator and throwing away the result. Consider u = note: `-D unused-collect` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:269:5 + --> $DIR/for_loop.rs:269:15 | -269 | / for _v in &vec { -270 | | _index += 1 -271 | | } - | |_____^ +269 | for _v in &vec { + | ^^^^ | = note: `-D explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:275:5 + --> $DIR/for_loop.rs:275:15 | -275 | / for _v in &vec { -276 | | _index += 1 -277 | | } - | |_____^ +275 | for _v in &vec { + | ^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:385:5 + --> $DIR/for_loop.rs:385:19 | -385 | / for (_, v) in &m { -386 | | let _v = v; -387 | | } - | |_____^ +385 | for (_, v) in &m { + | ^^ | = note: `-D for-kv-map` implied by `-D warnings` help: use the corresponding method @@ -435,135 +387,105 @@ help: use the corresponding method | error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:390:5 - | -390 | / for (_, v) in &*m { -391 | | let _v = v; -392 | | // Here the `*` is not actually necesarry, but the test tests that we don't -393 | | // suggest -394 | | // `in *m.values()` as we used to -395 | | } - | |_____^ + --> $DIR/for_loop.rs:390:19 + | +390 | for (_, v) in &*m { + | ^^^ help: use the corresponding method | 390 | for v in (*m).values() { | error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:398:5 + --> $DIR/for_loop.rs:398:19 | -398 | / for (_, v) in &mut m { -399 | | let _v = v; -400 | | } - | |_____^ +398 | for (_, v) in &mut m { + | ^^^^^^ help: use the corresponding method | 398 | for v in m.values_mut() { | error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:403:5 + --> $DIR/for_loop.rs:403:19 | -403 | / for (_, v) in &mut *m { -404 | | let _v = v; -405 | | } - | |_____^ +403 | for (_, v) in &mut *m { + | ^^^^^^^ help: use the corresponding method | 403 | for v in (*m).values_mut() { | error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:409:5 + --> $DIR/for_loop.rs:409:24 | -409 | / for (k, _value) in rm { -410 | | let _k = k; -411 | | } - | |_____^ +409 | for (k, _value) in rm { + | ^^ help: use the corresponding method | 409 | for k in rm.keys() { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:462:5 + --> $DIR/for_loop.rs:462:14 | -462 | / for i in 0..src.len() { -463 | | dst[i] = src[i]; -464 | | } - | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` +462 | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | = note: `-D manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:467:5 + --> $DIR/for_loop.rs:467:14 | -467 | / for i in 0..src.len() { -468 | | dst[i + 10] = src[i]; -469 | | } - | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` +467 | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:5 + --> $DIR/for_loop.rs:472:14 | -472 | / for i in 0..src.len() { -473 | | dst[i] = src[i + 10]; -474 | | } - | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` +472 | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:477:5 + --> $DIR/for_loop.rs:477:14 | -477 | / for i in 11..src.len() { -478 | | dst[i] = src[i - 10]; -479 | | } - | |_____^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` +477 | for i in 11..src.len() { + | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:482:5 + --> $DIR/for_loop.rs:482:14 | -482 | / for i in 0..dst.len() { -483 | | dst[i] = src[i]; -484 | | } - | |_____^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` +482 | for i in 0..dst.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:495:5 + --> $DIR/for_loop.rs:495:14 | -495 | / for i in 10..256 { -496 | | dst[i] = src[i - 5]; -497 | | dst2[i + 500] = src[i] -498 | | } - | |_____^ +495 | for i in 10..256 { + | ^^^^^^^ help: try replacing the loop by | -495 | dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) +495 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:507:5 + --> $DIR/for_loop.rs:507:14 | -507 | / for i in 10..LOOP_OFFSET { -508 | | dst[i + LOOP_OFFSET] = src[i - some_var]; -509 | | } - | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` +507 | for i in 10..LOOP_OFFSET { + | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:520:5 + --> $DIR/for_loop.rs:520:14 | -520 | / for i in 0..src_vec.len() { -521 | | dst_vec[i] = src_vec[i]; -522 | | } - | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` +520 | for i in 0..src_vec.len() { + | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:547:5 + --> $DIR/for_loop.rs:547:14 | -547 | / for i in 0..src.len() { -548 | | dst[i] = src[i].clone(); -549 | | } - | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` +547 | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` error: aborting due to 59 previous errors diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 7fb4571e0c3..84ccd5d4620 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,37 +1,30 @@ error: the loop variable `i` is only used to index `ns`. - --> $DIR/needless_range_loop.rs:8:5 - | -8 | / for i in 3..10 { -9 | | println!("{}", ns[i]); -10 | | } - | |_____^ - | - = note: `-D needless-range-loop` implied by `-D warnings` + --> $DIR/needless_range_loop.rs:8:14 + | +8 | for i in 3..10 { + | ^^^^^ + | + = note: `-D needless-range-loop` implied by `-D warnings` help: consider using an iterator - | -8 | for in ns.iter().take(10).skip(3) { - | + | +8 | for in ns.iter().take(10).skip(3) { + | error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:29:5 + --> $DIR/needless_range_loop.rs:29:14 | -29 | / for i in 0..ms.len() { -30 | | ms[i] *= 2; -31 | | } - | |_____^ +29 | for i in 0..ms.len() { + | ^^^^^^^^^^^ help: consider using an iterator | 29 | for in &mut ms { | error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:35:5 + --> $DIR/needless_range_loop.rs:35:14 | -35 | / for i in 0..ms.len() { -36 | | let x = &mut ms[i]; -37 | | *x *= 2; -38 | | } - | |_____^ +35 | for i in 0..ms.len() { + | ^^^^^^^^^^^ help: consider using an iterator | 35 | for in &mut ms { diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index cc0038c3442..80dfcddbe05 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -2,10 +2,7 @@ error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:12:14 | 12 | for _ in 0..3+1 { } - | ------ - | | - | help: use: `0..=3` - | in this macro invocation + | ^^^^^^ help: use: `0..=3` | = note: `-D range-plus-one` implied by `-D warnings` @@ -13,37 +10,25 @@ error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:15:14 | 15 | for _ in 0..1+5 { } - | ------ - | | - | help: use: `0..=5` - | in this macro invocation + | ^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:18:14 | 18 | for _ in 1..1+1 { } - | ------ - | | - | help: use: `1..=1` - | in this macro invocation + | ^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:24:14 | 24 | for _ in 0..(1+f()) { } - | ---------- - | | - | help: use: `0..=f()` - | in this macro invocation + | ^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable --> $DIR/range_plus_minus_one.rs:28:13 | 28 | let _ = ..=11-1; - | ------- - | | - | help: use: `..11` - | in this macro invocation + | ^^^^^^^ help: use: `..11` | = note: `-D range-minus-one` implied by `-D warnings` @@ -51,19 +36,13 @@ error: an exclusive range would be more readable --> $DIR/range_plus_minus_one.rs:29:13 | 29 | let _ = ..=(11-1); - | --------- - | | - | help: use: `..11` - | in this macro invocation + | ^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:30:13 | 30 | let _ = (f()+1)..(f()+1); - | ---------------- - | | - | help: use: `(f()+1)..=f()` - | in this macro invocation + | ^^^^^^^^^^^^^^^^ help: use: `(f()+1)..=f()` error: aborting due to 7 previous errors diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index 689c92d6fb6..e495fefbdd8 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -60,28 +60,24 @@ error: this loop could be written as a `while let` loop | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:68:5 + --> $DIR/while_loop.rs:68:33 | -68 | / while let Option::Some(x) = iter.next() { -69 | | println!("{}", x); -70 | | } - | |_____^ help: try: `for x in iter { .. }` +68 | while let Option::Some(x) = iter.next() { + | ^^^^^^^^^^^ help: try: `for x in iter { .. }` | = note: `-D while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:73:5 + --> $DIR/while_loop.rs:73:25 | -73 | / while let Some(x) = iter.next() { -74 | | println!("{}", x); -75 | | } - | |_____^ help: try: `for x in iter { .. }` +73 | while let Some(x) = iter.next() { + | ^^^^^^^^^^^ help: try: `for x in iter { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:78:5 + --> $DIR/while_loop.rs:78:25 | 78 | while let Some(_) = iter.next() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter { .. }` + | ^^^^^^^^^^^ help: try: `for _ in iter { .. }` error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:118:5 @@ -104,11 +100,10 @@ error: empty `loop {}` detected. You may want to either use `panic!()` or add `s = note: `-D empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:183:9 + --> $DIR/while_loop.rs:183:29 | -183 | / while let Some(v) = y.next() { // use a for loop here -184 | | } - | |_________^ help: try: `for v in y { .. }` +183 | while let Some(v) = y.next() { // use a for loop here + | ^^^^^^^^ help: try: `for v in y { .. }` error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From b369d0234eae44ed37f31932a33e7d94d7cdffa9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 29 Jan 2018 11:20:17 +0530 Subject: Bump compiletest version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c285dd10140..714f0b969af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ cargo_metadata = "0.2" regex = "0.2" [dev-dependencies] -compiletest_rs = "0.3.5" +compiletest_rs = "0.3.6" duct = "0.8.2" lazy_static = "1.0" serde_derive = "1.0" -- cgit 1.4.1-3-g733a5 From 81c5a05648f7faa28cf92c745969c8dcb4fd17f8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 29 Jan 2018 11:20:29 +0530 Subject: Bump to 0.0.183 --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6140de473a0..1e3f0102866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.183 +* Rustup to *rustc 1.25.0-nightly (21882aad7 2018-01-28)* +* New lint: [`misaligned_transmute`] + ## 0.0.182 * Rustup to *rustc 1.25.0-nightly (a0dcecff9 2018-01-24)* * New lint: [`decimal_literal_representation`] @@ -630,6 +634,7 @@ All notable changes to this project will be documented in this file. [`maybe_infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#maybe_infinite_iter [`mem_forget`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_forget [`min_max`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#min_max +[`misaligned_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misaligned_transmute [`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals diff --git a/Cargo.toml b/Cargo.toml index 714f0b969af..7b0b93fcda0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.182" +version = "0.0.183" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.182", path = "clippy_lints" } +clippy_lints = { version = "0.0.183", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 1616b6f1ef0..51d5bcafb7e 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.182" +version = "0.0.183" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a4e18c7eec3..62df7fd1058 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -596,6 +596,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, + transmute::MISALIGNED_TRANSMUTE, transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, @@ -603,7 +604,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, - transmute::MISALIGNED_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, -- cgit 1.4.1-3-g733a5 From 80827c1f749b0da9fab95f2d47417f91d52c4a46 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 9 Jan 2018 00:22:42 +0100 Subject: Warn on empty lines after outer attributes --- clippy_lints/src/attrs.rs | 53 +++++++++++++++++++++++- clippy_lints/src/lib.rs | 1 + tests/ui/empty_line_after_outer_attribute.rs | 21 ++++++++++ tests/ui/empty_line_after_outer_attribute.stderr | 19 +++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tests/ui/empty_line_after_outer_attribute.rs create mode 100644 tests/ui/empty_line_after_outer_attribute.stderr diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index da7fff2ed93..a96193bacf1 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty::{self, TyCtxt}; use semver::Version; -use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; use utils::{in_macro, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; @@ -78,12 +78,44 @@ declare_lint! { "use of `#[deprecated(since = \"x\")]` where x is not semver" } +/// **What it does:** Checks for empty lines after outer attributes +/// +/// **Why is this bad?** +/// Most likely the attribute was meant to be an inner attribute using a '!'. +/// If it was meant to be an outer attribute, then the following item +/// should not be separated by empty lines. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// // Bad +/// #[inline(always)] +/// +/// fn not_quite_good_code(..) { ... } +/// +/// // Good (as inner attribute) +/// #![inline(always)] +/// +/// fn this_is_fine_too(..) { ... } +/// +/// // Good (as outer attribute) +/// #[inline(always)] +/// fn this_is_fine(..) { ... } +/// +/// ``` +declare_lint! { + pub EMPTY_LINE_AFTER_OUTER_ATTR, + Warn, + "empty line after outer attribute" +} + #[derive(Copy, Clone)] pub struct AttrPass; impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { - lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE) + lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, EMPTY_LINE_AFTER_OUTER_ATTR) } } @@ -230,6 +262,23 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } for attr in attrs { + if attr.style == AttrStyle::Outer { + let attr_to_item_span = Span::new(attr.span.lo(), span.lo(), span.ctxt()); + + if let Some(snippet) = snippet_opt(cx, attr_to_item_span) { + let lines = snippet.split('\n').collect::>(); + if lines.iter().filter(|l| l.trim().is_empty()).count() > 1 { + span_lint( + cx, + EMPTY_LINE_AFTER_OUTER_ATTR, + attr_to_item_span, + &format!("Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?") + ); + + } + } + } + if let Some(ref values) = attr.meta_item_list() { if values.len() != 1 || attr.name().map_or(true, |n| n != "inline") { continue; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 62df7fd1058..723d15e8760 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -438,6 +438,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { attrs::DEPRECATED_SEMVER, attrs::INLINE_ALWAYS, attrs::USELESS_ATTRIBUTE, + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, bit_mask::VERBOSE_BIT_MASK, diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs new file mode 100644 index 00000000000..fa8958612f8 --- /dev/null +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -0,0 +1,21 @@ + +#![warn(empty_line_after_outer_attr)] + +// This should produce a warning +#[crate_type = "lib"] + +fn with_one_newline() { assert!(true) } + +// This should produce a warning, too +#[crate_type = "lib"] + + +fn with_two_newlines() { assert!(true) } + +// This should not produce a warning +#[allow(non_camel_case_types)] +#[allow(missing_docs)] +#[allow(missing_docs)] +fn three_attributes() { assert!(true) } + +fn main() { } diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr new file mode 100644 index 00000000000..04de89c60f6 --- /dev/null +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -0,0 +1,19 @@ +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:5:1 + | +5 | / #[crate_type = "lib"] +6 | | +7 | | fn with_one_newline() { assert!(true) } + | |_ + | + = note: `-D empty-line-after-outer-attr` implied by `-D warnings` + +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:10:1 + | +10 | / #[crate_type = "lib"] +11 | | +12 | | +13 | | fn with_two_newlines() { assert!(true) } + | |_ + -- cgit 1.4.1-3-g733a5 From 83909398d288579837922e68482f2e22b24f8406 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 19 Jan 2018 08:18:29 +0100 Subject: Add test case for comments between item and attr --- tests/ui/empty_line_after_outer_attribute.rs | 12 ++++++++++++ tests/ui/empty_line_after_outer_attribute.stderr | 23 +++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index fa8958612f8..648a25f1dd0 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,6 +1,18 @@ #![warn(empty_line_after_outer_attr)] +// This should produce a warning +#[crate_type = "lib"] + +/// some comment +fn with_one_newline_and_comment() { assert!(true) } + +// This should not produce a warning +#[crate_type = "lib"] +/// some comment +fn with_no_newline_and_comment() { assert!(true) } + + // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index 04de89c60f6..481f95443ce 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -3,17 +3,28 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a | 5 | / #[crate_type = "lib"] 6 | | -7 | | fn with_one_newline() { assert!(true) } +7 | | /// some comment +8 | | fn with_one_newline_and_comment() { assert!(true) } | |_ | = note: `-D empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:10:1 + --> $DIR/empty_line_after_outer_attribute.rs:17:1 | -10 | / #[crate_type = "lib"] -11 | | -12 | | -13 | | fn with_two_newlines() { assert!(true) } +17 | / #[crate_type = "lib"] +18 | | +19 | | fn with_one_newline() { assert!(true) } | |_ +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:22:1 + | +22 | / #[crate_type = "lib"] +23 | | +24 | | +25 | | fn with_two_newlines() { assert!(true) } + | |_ + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From aade0d563e1eb668566872d4c300a734b67f6600 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 23 Jan 2018 21:32:06 +0100 Subject: Make lint work on all members of ast::Item_ --- clippy_lints/src/attrs.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 23 +++++++++++++++++++++ tests/ui/empty_line_after_outer_attribute.stderr | 26 +++++++++++++++++++++++- tests/ui/inline_fn_without_body.rs | 1 - tests/ui/inline_fn_without_body.stderr | 3 +-- 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a96193bacf1..5df932a8d93 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -203,7 +203,7 @@ fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { if let ItemFn(_, _, _, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) } else { - false + true } } diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 648a25f1dd0..3d62a4913ac 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -24,6 +24,29 @@ fn with_one_newline() { assert!(true) } fn with_two_newlines() { assert!(true) } + +// This should produce a warning +#[crate_type = "lib"] + +enum Baz { + One, + Two +} + +// This should produce a warning +#[crate_type = "lib"] + +struct Foo { + one: isize, + two: isize +} + +// This should produce a warning +#[crate_type = "lib"] + +mod foo { +} + // This should not produce a warning #[allow(non_camel_case_types)] #[allow(missing_docs)] diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index 481f95443ce..7c9c7b8f349 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -26,5 +26,29 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a 25 | | fn with_two_newlines() { assert!(true) } | |_ -error: aborting due to 3 previous errors +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:29:1 + | +29 | / #[crate_type = "lib"] +30 | | +31 | | enum Baz { + | |_ + +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:37:1 + | +37 | / #[crate_type = "lib"] +38 | | +39 | | struct Foo { + | |_ + +error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? + --> $DIR/empty_line_after_outer_attribute.rs:45:1 + | +45 | / #[crate_type = "lib"] +46 | | +47 | | mod foo { + | |_ + +error: aborting due to 6 previous errors diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 82e073184d3..76e50e56780 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -11,7 +11,6 @@ trait Foo { #[inline(always)]fn always_inline(); #[inline(never)] - fn never_inline(); #[inline] diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index fd26013d11e..2b466b68610 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -19,8 +19,7 @@ error: use of `#[inline]` on trait method `never_inline` which has no body | 13 | #[inline(never)] | _____-^^^^^^^^^^^^^^^ -14 | | -15 | | fn never_inline(); +14 | | fn never_inline(); | |____- help: remove error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 3d54e56ed4898c2b01dd008f12ab41cf54710f43 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 26 Jan 2018 07:51:27 +0100 Subject: Add workaround for hidden outer attribute If the snippet is empty, it's an attribute that was inserted during macro expansion and we want to ignore those, because they could come from external sources that the user has no control over. For some reason these attributes don't have any expansion info on them, so we have to check it this way until there is a better way. --- clippy_lints/src/attrs.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 5df932a8d93..939fdf1fae9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -263,6 +263,10 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { for attr in attrs { if attr.style == AttrStyle::Outer { + if !is_present_in_source(cx, attr.span) { + return; + } + let attr_to_item_span = Span::new(attr.span.lo(), span.lo(), span.ctxt()); if let Some(snippet) = snippet_opt(cx, attr_to_item_span) { @@ -319,3 +323,17 @@ fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { false } } + +// If the snippet is empty, it's an attribute that was inserted during macro +// expansion and we want to ignore those, because they could come from external +// sources that the user has no control over. +// For some reason these attributes don't have any expansion info on them, so +// we have to check it this way until there is a better way. +fn is_present_in_source(cx: &LateContext, span: Span) -> bool { + if let Some(snippet) = snippet_opt(cx, span) { + if snippet.is_empty() { + return false; + } + } + true +} -- cgit 1.4.1-3-g733a5 From 0778ac81c8e73b88fdae07e737bfc3b8fd3b92fb Mon Sep 17 00:00:00 2001 From: Tim Nielens Date: Mon, 29 Jan 2018 16:52:22 +0100 Subject: #1121: already fixed, adding a test --- tests/ui/while_loop.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index b7ef39da817..b4c3eb0f58e 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -193,4 +193,12 @@ fn refutable() { break None; } }; + + use std::collections::HashSet; + let mut values = HashSet::new(); + values.insert(1); + + while let Some(&value) = values.iter().next() { + values.remove(&value); + } } -- cgit 1.4.1-3-g733a5 From c3e9ec65a1be17aa3bfb139659be34f969be3ce6 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 10:35:22 +0900 Subject: Rustup to rustc 1.25.0-nightly (90eb44a58 2018-01-29) --- clippy_lints/src/misc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 50ae695f4c5..04cc488d562 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -545,11 +545,11 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { // *arg impls PartialEq if !arg_ty - .builtin_deref(true, ty::LvaluePreference::NoPreference) + .builtin_deref(true) .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty])) // arg impls PartialEq<*other> && !other_ty - .builtin_deref(true, ty::LvaluePreference::NoPreference) + .builtin_deref(true) .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty])) // arg impls PartialEq && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) -- cgit 1.4.1-3-g733a5 From a3c23237674290e380c8046a430d7ea61f86c7b2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 10:35:35 +0900 Subject: Add double comparions lint --- clippy_lints/src/double_comparison.rs | 85 +++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 2 + tests/ui/double_comparison.rs | 28 ++++++++++++ tests/ui/double_comparison.stderr | 52 +++++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 clippy_lints/src/double_comparison.rs create mode 100644 tests/ui/double_comparison.rs create mode 100644 tests/ui/double_comparison.stderr diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs new file mode 100644 index 00000000000..a4124883fcb --- /dev/null +++ b/clippy_lints/src/double_comparison.rs @@ -0,0 +1,85 @@ +//! Lint on unnecessary double comparisons. Some examples: + +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::Span; + +use utils::{snippet, span_lint_and_sugg, SpanlessEq}; + +/// **What it does:** Checks for double comparions that could be simpified to a single expression. +/// +/// +/// **Why is this bad?** Readability. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x == y || x < y +/// ``` +/// +/// Could be written as: +/// +/// ```rust +/// x <= y +/// ``` +declare_lint! { + pub DOUBLE_COMPARISONS, + Deny, + "unnecessary double comparisons that can be simplified" +} + +pub struct DoubleComparisonPass; + +impl LintPass for DoubleComparisonPass { + fn get_lints(&self) -> LintArray { + lint_array!(DOUBLE_COMPARISONS) + } +} + +impl<'a, 'tcx> DoubleComparisonPass { + fn check_binop( + &self, + cx: &LateContext<'a, 'tcx>, + op: BinOp_, + lhs: &'tcx Expr, + rhs: &'tcx Expr, + span: Span, + ) { + let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) { + (ExprBinary(lb, llhs, lrhs), ExprBinary(rb, rlhs, rrhs)) => { + (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) + } + _ => return, + }; + let spanless_eq = SpanlessEq::new(cx).ignore_fn(); + if !(spanless_eq.eq_expr(&llhs, &rlhs) && spanless_eq.eq_expr(&lrhs, &rrhs)) { + return; + } + macro_rules! lint_double_comparison { + ($op:tt) => {{ + let lhs_str = snippet(cx, llhs.span, ""); + let rhs_str = snippet(cx, lrhs.span, ""); + let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str); + span_lint_and_sugg(cx, DOUBLE_COMPARISONS, span, + "This binary expression can be simplified", + "try", sugg); + }} + } + match (op, lkind, rkind) { + (BiOr, BiEq, BiLt) | (BiOr, BiLt, BiEq) => lint_double_comparison!(<=), + (BiOr, BiEq, BiGt) | (BiOr, BiGt, BiEq) => lint_double_comparison!(>=), + (BiOr, BiLt, BiGt) | (BiOr, BiGt, BiLt) => lint_double_comparison!(!=), + (BiAnd, BiLe, BiGe) | (BiAnd, BiGe, BiLe) => lint_double_comparison!(==), + _ => (), + }; + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisonPass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprBinary(ref kind, ref lhs, ref rhs) = expr.node { + self.check_binop(cx, kind.node, lhs, rhs, expr.span); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 62df7fd1058..5f2d34d9eaa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -86,6 +86,7 @@ pub mod copies; pub mod cyclomatic_complexity; pub mod derive; pub mod doc; +pub mod double_comparison; pub mod double_parens; pub mod drop_forget_ref; pub mod else_if_without_else; @@ -369,6 +370,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_late_lint_pass(box replace_consts::ReplaceConsts); reg.register_late_lint_pass(box types::UnitArg); + reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs new file mode 100644 index 00000000000..2c8f116281b --- /dev/null +++ b/tests/ui/double_comparison.rs @@ -0,0 +1,28 @@ +fn main() { + let x = 1; + let y = 2; + if x == y || x < y { + // do something + } + if x < y || x == y { + // do something + } + if x == y || x > y { + // do something + } + if x > y || x == y { + // do something + } + if x < y || x > y { + // do something + } + if x > y || x < y { + // do something + } + if x <= y && x >= y { + // do something + } + if x >= y && x <= y { + // do something + } +} diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr new file mode 100644 index 00000000000..a97b0a246af --- /dev/null +++ b/tests/ui/double_comparison.stderr @@ -0,0 +1,52 @@ +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:4:8 + | +4 | if x == y || x < y { + | ^^^^^^^^^^^^^^^ help: try: `x <= y` + | + = note: #[deny(double_comparisons)] on by default + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:7:8 + | +7 | if x < y || x == y { + | ^^^^^^^^^^^^^^^ help: try: `x <= y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:10:8 + | +10 | if x == y || x > y { + | ^^^^^^^^^^^^^^^ help: try: `x >= y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:13:8 + | +13 | if x > y || x == y { + | ^^^^^^^^^^^^^^^ help: try: `x >= y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:16:8 + | +16 | if x < y || x > y { + | ^^^^^^^^^^^^^^ help: try: `x != y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:19:8 + | +19 | if x > y || x < y { + | ^^^^^^^^^^^^^^ help: try: `x != y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:22:8 + | +22 | if x <= y && x >= y { + | ^^^^^^^^^^^^^^^^ help: try: `x == y` + +error: This binary expression can be simplified + --> $DIR/double_comparison.rs:25:8 + | +25 | if x >= y && x <= y { + | ^^^^^^^^^^^^^^^^ help: try: `x == y` + +error: aborting due to 8 previous errors + -- cgit 1.4.1-3-g733a5 From b7cb0752ff5ba28b4aa8e4bb8befc6b8977513d4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 30 Jan 2018 14:58:38 +0100 Subject: Improved suggestion on misrefactored_assign_op lint. Fixes #1239 --- clippy_lints/src/assign_ops.rs | 12 ++++++--- tests/ui/assign_ops2.rs | 1 + tests/ui/assign_ops2.stderr | 60 +++++++++++++++++++++++++++++++++++------- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 790c2884273..fe6949566e4 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -87,19 +87,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { }); if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { - let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { + let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| { span_lint_and_then( cx, MISREFACTORED_ASSIGN_OP, expr.span, "variable appears on both sides of an assignment operation", |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { + let a = &sugg::Sugg::hir(cx, assignee, ".."); + let r = &sugg::Sugg::hir(cx, rhs, ".."); db.span_suggestion( expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + &format!("Did you mean {} = {} {} {} or {} = {}? Consider replacing it with", + snip_a, snip_a, op.node.as_str(), snip_r, + snip_a, sugg::make_binop(higher::binop(op.node), a, r)), + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r) ); }, ); diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 8d6ef827f52..821f6a1a9bf 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -13,6 +13,7 @@ fn main() { a /= a / 2; a %= a % 5; a &= a & 1; + a *= a * a; a -= 1 - a; a /= 5 / a; a %= 42 % a; diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 0ff211259c0..992bb4079ea 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -2,51 +2,93 @@ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:8:5 | 8 | a += a + 1; - | ^^^^^^^^^^ help: replace it with: `a += 1` + | ^^^^^^^^^^ | = note: `-D misrefactored-assign-op` implied by `-D warnings` +help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with + | +8 | a += 1; + | ^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:9:5 | 9 | a += 1 + a; - | ^^^^^^^^^^ help: replace it with: `a += 1` + | ^^^^^^^^^^ +help: Did you mean a = a + 1 or a = a + 1 + a? Consider replacing it with + | +9 | a += 1; + | ^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:10:5 | 10 | a -= a - 1; - | ^^^^^^^^^^ help: replace it with: `a -= 1` + | ^^^^^^^^^^ +help: Did you mean a = a - 1 or a = a - (a - 1)? Consider replacing it with + | +10 | a -= 1; + | ^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:11:5 | 11 | a *= a * 99; - | ^^^^^^^^^^^ help: replace it with: `a *= 99` + | ^^^^^^^^^^^ +help: Did you mean a = a * 99 or a = a * a * 99? Consider replacing it with + | +11 | a *= 99; + | ^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:12:5 | 12 | a *= 42 * a; - | ^^^^^^^^^^^ help: replace it with: `a *= 42` + | ^^^^^^^^^^^ +help: Did you mean a = a * 42 or a = a * 42 * a? Consider replacing it with + | +12 | a *= 42; + | ^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:13:5 | 13 | a /= a / 2; - | ^^^^^^^^^^ help: replace it with: `a /= 2` + | ^^^^^^^^^^ +help: Did you mean a = a / 2 or a = a / (a / 2)? Consider replacing it with + | +13 | a /= 2; + | ^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:14:5 | 14 | a %= a % 5; - | ^^^^^^^^^^ help: replace it with: `a %= 5` + | ^^^^^^^^^^ +help: Did you mean a = a % 5 or a = a % (a % 5)? Consider replacing it with + | +14 | a %= 5; + | ^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:15:5 | 15 | a &= a & 1; - | ^^^^^^^^^^ help: replace it with: `a &= 1` + | ^^^^^^^^^^ +help: Did you mean a = a & 1 or a = a & a & 1? Consider replacing it with + | +15 | a &= 1; + | ^^^^^^ + +error: variable appears on both sides of an assignment operation + --> $DIR/assign_ops2.rs:16:5 + | +16 | a *= a * a; + | ^^^^^^^^^^ +help: Did you mean a = a * a or a = a * a * a? Consider replacing it with + | +16 | a *= a; + | ^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 8123495e0f36c429a865645a15a2bbb02e9a0c0f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 30 Jan 2018 15:02:47 +0100 Subject: Version bump --- CHANGELOG.md | 6 ++++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3f0102866..288cc8bb02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.184 +* Rustup to *rustc 1.25.0-nightly (90eb44a58 2018-01-29)* +* New lints: [`double_comparisons`], [`empty_line_after_outer_attr`] + ## 0.0.183 * Rustup to *rustc 1.25.0-nightly (21882aad7 2018-01-28)* * New lint: [`misaligned_transmute`] @@ -554,6 +558,7 @@ All notable changes to this project will be documented in this file. [`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq [`diverging_sub_expression`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_markdown`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#doc_markdown +[`double_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_comparisons [`double_neg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_neg [`double_parens`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_parens [`drop_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_copy @@ -561,6 +566,7 @@ All notable changes to this project will be documented in this file. [`duplicate_underscore_argument`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`else_if_without_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum +[`empty_line_after_outer_attr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr [`empty_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_loop [`enum_clike_unportable_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant [`enum_glob_use`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_glob_use diff --git a/Cargo.toml b/Cargo.toml index 7b0b93fcda0..a87afab2319 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.183" +version = "0.0.184" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.183", path = "clippy_lints" } +clippy_lints = { version = "0.0.184", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 51d5bcafb7e..60e7a7b28df 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.183" +version = "0.0.184" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 836d4531a92..25fb171720f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -438,9 +438,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_SEMVER, + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, attrs::INLINE_ALWAYS, attrs::USELESS_ATTRIBUTE, - attrs::EMPTY_LINE_AFTER_OUTER_ATTR, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, bit_mask::VERBOSE_BIT_MASK, @@ -458,6 +458,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { derive::DERIVE_HASH_XOR_EQ, derive::EXPL_IMPL_CLONE_ON_COPY, doc::DOC_MARKDOWN, + double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, drop_forget_ref::DROP_COPY, drop_forget_ref::DROP_REF, -- cgit 1.4.1-3-g733a5 From bd421cb5a5937ce42ddddd392ec743c8154f5d56 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 30 Jan 2018 17:45:35 +0100 Subject: Additionally suggest the semantic equal variant --- clippy_lints/src/assign_ops.rs | 75 +++++++++++++++++++++++++++++++----------- tests/ui/assign_ops2.rs | 5 ++- tests/ui/assign_ops2.stderr | 36 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index fe6949566e4..d285e71bd16 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,4 +1,5 @@ use rustc::hir; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::ast; use utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; @@ -98,13 +99,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { { let a = &sugg::Sugg::hir(cx, assignee, ".."); let r = &sugg::Sugg::hir(cx, rhs, ".."); + let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); db.span_suggestion( expr.span, - &format!("Did you mean {} = {} {} {} or {} = {}? Consider replacing it with", + &format!("Did you mean {} = {} {} {} or {}? Consider replacing it with", snip_a, snip_a, op.node.as_str(), snip_r, - snip_a, sugg::make_binop(higher::binop(op.node), a, r)), + long), format!("{} {}= {}", snip_a, op.node.as_str(), snip_r) ); + db.span_suggestion( + expr.span, + "or", + long + ); }, ); }; @@ -193,23 +200,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { ); } }; - // a = a op b - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { - lint(assignee, r); - } - // a = b commutative_op a - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { - match op.node { - hir::BiAdd | - hir::BiMul | - hir::BiAnd | - hir::BiOr | - hir::BiBitXor | - hir::BiBitAnd | - hir::BiBitOr => { - lint(assignee, l); - }, - _ => {}, + + let mut visitor = ExprVisitor { + assignee: assignee, + counter: 0, + cx: cx + }; + + walk_expr(&mut visitor, e); + + if visitor.counter == 1 { + // a = a op b + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { + lint(assignee, r); + } + // a = b commutative_op a + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { + match op.node { + hir::BiAdd | + hir::BiMul | + hir::BiAnd | + hir::BiOr | + hir::BiBitXor | + hir::BiBitAnd | + hir::BiBitOr => { + lint(assignee, l); + }, + _ => {}, + } } } } @@ -226,3 +244,22 @@ fn is_commutative(op: hir::BinOp_) -> bool { BiSub | BiDiv | BiRem | BiShl | BiShr | BiLt | BiLe | BiGe | BiGt => false, } } + +struct ExprVisitor<'a, 'tcx: 'a> { + assignee: &'a hir::Expr, + counter: u8, + cx: &'a LateContext<'a, 'tcx>, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, &expr) { + self.counter += 1; + } + + walk_expr(self, expr); + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 821f6a1a9bf..2d3adc2a661 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -2,7 +2,7 @@ #[allow(unused_assignments)] -#[warn(misrefactored_assign_op)] +#[warn(misrefactored_assign_op, assign_op_pattern)] fn main() { let mut a = 5; a += a + 1; @@ -14,6 +14,9 @@ fn main() { a %= a % 5; a &= a & 1; a *= a * a; + a = a * a * a; + a = a * 42 * a; + a = a * 2 + a; a -= 1 - a; a /= 5 / a; a %= 42 % a; diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 992bb4079ea..2858af1f8c0 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -9,6 +9,10 @@ help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with | 8 | a += 1; | ^^^^^^ +help: or + | +8 | a = a + a + 1; + | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:9:5 @@ -19,6 +23,10 @@ help: Did you mean a = a + 1 or a = a + 1 + a? Consider replacing it with | 9 | a += 1; | ^^^^^^ +help: or + | +9 | a = a + 1 + a; + | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:10:5 @@ -29,6 +37,10 @@ help: Did you mean a = a - 1 or a = a - (a - 1)? Consider replacing it with | 10 | a -= 1; | ^^^^^^ +help: or + | +10 | a = a - (a - 1); + | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:11:5 @@ -39,6 +51,10 @@ help: Did you mean a = a * 99 or a = a * a * 99? Consider replacing it with | 11 | a *= 99; | ^^^^^^^ +help: or + | +11 | a = a * a * 99; + | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:12:5 @@ -49,6 +65,10 @@ help: Did you mean a = a * 42 or a = a * 42 * a? Consider replacing it with | 12 | a *= 42; | ^^^^^^^ +help: or + | +12 | a = a * 42 * a; + | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:13:5 @@ -59,6 +79,10 @@ help: Did you mean a = a / 2 or a = a / (a / 2)? Consider replacing it with | 13 | a /= 2; | ^^^^^^ +help: or + | +13 | a = a / (a / 2); + | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:14:5 @@ -69,6 +93,10 @@ help: Did you mean a = a % 5 or a = a % (a % 5)? Consider replacing it with | 14 | a %= 5; | ^^^^^^ +help: or + | +14 | a = a % (a % 5); + | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:15:5 @@ -79,6 +107,10 @@ help: Did you mean a = a & 1 or a = a & a & 1? Consider replacing it with | 15 | a &= 1; | ^^^^^^ +help: or + | +15 | a = a & a & 1; + | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:16:5 @@ -89,6 +121,10 @@ help: Did you mean a = a * a or a = a * a * a? Consider replacing it with | 16 | a *= a; | ^^^^^^ +help: or + | +16 | a = a * a * a; + | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 74ae9b15b5c9fa535239b769b8292b4ccf29a4f9 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Sun, 28 Jan 2018 01:04:22 +0100 Subject: Add question mark operator --- clippy_lints/src/lib.rs | 2 + clippy_lints/src/question_mark.rs | 138 ++++++++++++++++++++++++++++++++++++++ tests/ui/question_mark.rs | 54 +++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 clippy_lints/src/question_mark.rs create mode 100644 tests/ui/question_mark.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 25fb171720f..287595a6e8a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -89,6 +89,7 @@ pub mod doc; pub mod double_comparison; pub mod double_parens; pub mod drop_forget_ref; +pub mod question_mark; pub mod else_if_without_else; pub mod empty_enum; pub mod entry; @@ -371,6 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box replace_consts::ReplaceConsts); reg.register_late_lint_pass(box types::UnitArg); reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); + reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs new file mode 100644 index 00000000000..4c01899936b --- /dev/null +++ b/clippy_lints/src/question_mark.rs @@ -0,0 +1,138 @@ +use rustc::lint::*; +use rustc::hir::*; +use rustc::hir::def::Def; +use utils::sugg::Sugg; +use syntax::ptr::P; + +use utils::{match_def_path, match_type, span_lint_and_then}; +use utils::paths::*; + +/// **What it does:** Checks for expressions that could be replaced by the question mark operator +/// +/// **Why is this bad?** Question mark usage is more idiomatic +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// if option.is_none() { +/// return None; +/// } +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// option?; +/// ``` +declare_lint!{ + pub QUESTION_MARK, + Warn, + "checks for expressions that could be replaced by the question mark operator" +} + +#[derive(Copy, Clone)] +pub struct QuestionMarkPass; + +impl LintPass for QuestionMarkPass { + fn get_lints(&self) -> LintArray { + lint_array!(QUESTION_MARK) + } +} + +impl QuestionMarkPass { + /// Check if the given expression on the given context matches the following structure: + /// + /// ``` + /// if option.is_none() { + /// return None; + /// } + /// ``` + /// + /// If it matches, it will suggest to use the question mark operator instead + fn check_is_none_and_early_return_none(cx: &LateContext, expr: &Expr) { + if_chain! { + if let ExprIf(ref if_expr, ref body, _) = expr.node; + if let ExprMethodCall(ref segment, _, ref args) = if_expr.node; + if segment.name == "is_none"; + if Self::expression_returns_none(cx, &body); + if let Some(subject) = args.get(0); + if Self::is_option(cx, subject); + + then { + span_lint_and_then( + cx, + QUESTION_MARK, + expr.span, + &format!("this block may be rewritten with the `?` operator"), + |db| { + let receiver_str = &Sugg::hir(cx, subject, ".."); + + db.span_suggestion( + expr.span, + "replace_it_with", + format!("{}?;", receiver_str), + ); + } + ) + } + } + } + + fn is_option(cx: &LateContext, expression: &Expr) -> bool { + let expr_ty = cx.tables.expr_ty(expression); + + return match_type(cx, expr_ty, &OPTION); + } + + fn expression_returns_none(cx: &LateContext, expression: &Expr) -> bool { + match expression.node { + ExprBlock(ref block) => { + if let Some(return_expression) = Self::return_expression(block) { + return Self::expression_returns_none(cx, &return_expression); + } + + false + }, + ExprRet(Some(ref expr)) => { + Self::expression_returns_none(cx, expr) + }, + ExprPath(ref qp) => { + if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { + return match_def_path(cx.tcx, def_id, &OPTION_NONE); + } + + false + }, + _ => false + } + } + + fn return_expression(block: &Block) -> Option> { + // Check if last expression is a return statement. Then, return the expression + if_chain! { + if block.stmts.len() == 1; + if let Some(expr) = block.stmts.iter().last(); + if let StmtSemi(ref expr, _) = expr.node; + if let ExprRet(ref ret_expr) = expr.node; + if let &Some(ref ret_expr) = ret_expr; + + then { + return Some(ret_expr.clone()); + } + } + + // Check if the block has an implicit return expression + if let Some(ref ret_expr) = block.expr { + return Some(ret_expr.clone()); + } + + return None; + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMarkPass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + Self::check_is_none_and_early_return_none(cx, expr); + } +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs new file mode 100644 index 00000000000..369b868a50d --- /dev/null +++ b/tests/ui/question_mark.rs @@ -0,0 +1,54 @@ +fn some_func(a: Option) -> Option { + if a.is_none() { + return None + } + + a +} + +pub enum SeemsOption { + Some(T), + None +} + +impl SeemsOption { + pub fn is_none(&self) -> bool { + match *self { + SeemsOption::None => true, + SeemsOption::Some(_) => false, + } + } +} + +fn returns_something_similar_to_option(a: SeemsOption) -> SeemsOption { + if a.is_none() { + return SeemsOption::None; + } + + a +} + +pub struct SomeStruct { + pub opt: Option, +} + +impl SomeStruct { + pub fn func(&self) -> Option { + if (self.opt).is_none() { + return None; + } + + self.opt + } +} + +fn main() { + some_func(Some(42)); + some_func(None); + + let some_struct = SomeStruct { opt: Some(54) }; + some_struct.func(); + + let so = SeemsOption::Some(45); + returns_something_similar_to_option(so); +} -- cgit 1.4.1-3-g733a5 From 05ed42193055b6c01cf31f82e782e313e807880e Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Wed, 31 Jan 2018 00:09:16 +0100 Subject: Update UI tests --- tests/ui/question_mark.stderr | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/question_mark.stderr diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr new file mode 100644 index 00000000000..e97b1869824 --- /dev/null +++ b/tests/ui/question_mark.stderr @@ -0,0 +1,22 @@ +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:2:2 + | +2 | if a.is_none() { + | _____^ +3 | | return None +4 | | } + | |_____^ help: replace_it_with: `a?;` + | + = note: `-D question-mark` implied by `-D warnings` + +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:37:3 + | +37 | if (self.opt).is_none() { + | _________^ +38 | | return None; +39 | | } + | |_________^ help: replace_it_with: `(self.opt)?;` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 3358dd72edda08b8796dfca883b714ec1a23cd97 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 31 Jan 2018 14:51:40 -0500 Subject: gitignore: support ignoring target as symlinks --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 64d0c25752d..43552238725 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,8 @@ out # Generated by Cargo Cargo.lock -/target/ -/clippy_lints/target/ +/target +/clippy_lints/target # Generated by dogfood /target_recur/ -- cgit 1.4.1-3-g733a5 From a64724fac49a91b1049f377f296b16a4725b713b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Feb 2018 07:43:03 +0100 Subject: Fix false positive in empty_line_after_outer_attr Doc comments are syntactic sugar for #[doc] attributes, so this lint was catching them, too. This commit makes it so that doc comments are ignored in this lint. I think, for normal attributes it makes sense to warn about following empty lines, for doc comments, less. This way the user has some freedom over the formatting. --- clippy_lints/src/attrs.rs | 5 ++++- tests/ui/empty_line_after_outer_attribute.rs | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 939fdf1fae9..73f25aa76e0 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -262,6 +262,9 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } for attr in attrs { + if attr.is_sugared_doc { + return; + } if attr.style == AttrStyle::Outer { if !is_present_in_source(cx, attr.span) { return; @@ -276,7 +279,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { cx, EMPTY_LINE_AFTER_OUTER_ATTR, attr_to_item_span, - &format!("Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?") + "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?" ); } diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 3d62a4913ac..ef78ca530c1 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -47,6 +47,11 @@ struct Foo { mod foo { } +/// This doc comment should not produce a warning + +/** This is also a doc comment and should not produce a warning + */ + // This should not produce a warning #[allow(non_camel_case_types)] #[allow(missing_docs)] -- cgit 1.4.1-3-g733a5 From d5bac828379abd4c03df26bdbe5bd2f06ea36dc4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 1 Feb 2018 14:35:56 +0100 Subject: Give travis a guaranteed existing directory for ui test output --- tests/compile-test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 2b0fea0f8b9..5bf1bd5d13b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -47,7 +47,10 @@ fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { - PathBuf::from("/tmp/clippy_test_build_base") + // we don't need access to the stderr files on travis + let mut path = PathBuf::from(env!("OUT_DIR")); + path.push("test_build_base"); + path } else { let mut path = std::env::current_dir().unwrap(); path.push("target/debug/test_build_base"); -- cgit 1.4.1-3-g733a5 From 5c28cd259a174e906b733da93fe387124ed2dd02 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Feb 2018 23:04:59 +0100 Subject: Allow empty lines in lint doc examples This makes sure that empty lines in lint examples are preserved. It also fixes the documentation for the invalid_ref lint, which was not shown because of an extra newline before the lint declaration. --- clippy_lints/src/attrs.rs | 5 ++--- clippy_lints/src/invalid_ref.rs | 1 - util/export.py | 11 ++++++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 939fdf1fae9..2237a463ddc 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -97,12 +97,11 @@ declare_lint! { /// // Good (as inner attribute) /// #![inline(always)] /// -/// fn this_is_fine_too(..) { ... } +/// fn this_is_fine(..) { ... } /// /// // Good (as outer attribute) /// #[inline(always)] -/// fn this_is_fine(..) { ... } -/// +/// fn this_is_fine_too(..) { ... } /// ``` declare_lint! { pub EMPTY_LINE_AFTER_OUTER_ATTR, diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 90eb92b8ca4..6e6b0392a90 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -13,7 +13,6 @@ use utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; /// ```rust /// let bad_ref: &usize = std::mem::zeroed(); /// ``` - declare_lint! { pub INVALID_REF, Warn, diff --git a/util/export.py b/util/export.py index ae8e4a72c08..0607c864259 100755 --- a/util/export.py +++ b/util/export.py @@ -24,7 +24,7 @@ def parse_lint_def(lint): last_section = None for line in lint.doc: - if len(line.strip()) == 0: + if len(line.strip()) == 0 and not last_section.startswith("Example"): continue match = re.match(lint_subheadline, line) @@ -39,8 +39,13 @@ def parse_lint_def(lint): log.warn("Skipping comment line as it was not preceded by a heading") log.debug("in lint `%s`, line `%s`", lint.name, line) - lint_dict['docs'][last_section] = \ - (lint_dict['docs'].get(last_section, "") + "\n" + text).strip() + fragment = lint_dict['docs'].get(last_section, "") + if text == "\n": + line = fragment + text + else: + line = (fragment + "\n" + text).strip() + + lint_dict['docs'][last_section] = line return lint_dict -- cgit 1.4.1-3-g733a5 From c5ee8b5dfbbb9da99636770543335bd59963b000 Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Fri, 2 Feb 2018 16:24:32 +1100 Subject: set CodeSuggestion approximate to false. fixes #2429 --- clippy_lints/src/utils/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b7f1e7b2454..7cb3e08a116 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -648,6 +648,7 @@ where ], msg: help_msg, show_code_when_inline: true, + approximate: false, }; db.suggestions.push(sugg); } -- cgit 1.4.1-3-g733a5 From 3a4ea45821f3f8c5cb75425e21985279790d4ff1 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Tue, 30 Jan 2018 14:52:45 -0500 Subject: Fix `get_enclosing_block` --- clippy_lints/src/utils/mod.rs | 3 +++ tests/ui/issue_2356.rs | 24 ++++++++++++++++++++++++ tests/ui/issue_2356.stderr | 14 ++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 tests/ui/issue_2356.rs create mode 100644 tests/ui/issue_2356.stderr diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b7f1e7b2454..53ea5ab4a79 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -518,6 +518,9 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. + }) | Node::NodeImplItem(&ImplItem { + node: ImplItemKind::Method(_, eid), + .. }) => match cx.tcx.hir.body(eid).value.node { ExprBlock(ref block) => Some(block), _ => None, diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs new file mode 100644 index 00000000000..d4cefb0f1e3 --- /dev/null +++ b/tests/ui/issue_2356.rs @@ -0,0 +1,24 @@ +#![deny(while_let_on_iterator)] + +use std::iter::Iterator; + +struct Foo; + +impl Foo { + fn foo1>(mut it: I) { + while let Some(_) = it.next() { + println!("{:?}", it.size_hint()); + } + } + + fn foo2>(mut it: I) { + while let Some(e) = it.next() { + println!("{:?}", e); + } + } +} + +fn main() { + Foo::foo1(vec![].into_iter()); + Foo::foo2(vec![].into_iter()); +} diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr new file mode 100644 index 00000000000..4b82a0a7565 --- /dev/null +++ b/tests/ui/issue_2356.stderr @@ -0,0 +1,14 @@ +error: this loop could be written as a `for` loop + --> $DIR/issue_2356.rs:15:29 + | +15 | while let Some(e) = it.next() { + | ^^^^^^^^^ help: try: `for e in it { .. }` + | +note: lint level defined here + --> $DIR/issue_2356.rs:1:9 + | +1 | #![deny(while_let_on_iterator)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From ff83b3ecb9a9e791d1a0f389a2a3bf6a2d041fcf Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 2 Feb 2018 01:49:47 -0500 Subject: Fix `non_expressive_names` --- clippy_lints/src/non_expressive_names.rs | 39 ++++++++++++++++++++------------ tests/ui/non_expressive_names.rs | 11 +++++++++ tests/ui/non_expressive_names.stderr | 20 +++++++++++++++- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index d3b6aefe5f4..9ef55907ecd 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -313,21 +313,32 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext, item: &Item) { if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node { - if !attr::contains_name(&item.attrs, "test") { - let mut visitor = SimilarNamesLocalVisitor { - names: Vec::new(), - cx: cx, - lint: self, - single_char_names: Vec::new(), - }; - // initialize with function arguments - for arg in &decl.inputs { - SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); - } - // walk all other bindings - walk_block(&mut visitor, blk); - } + do_check(self, cx, &item.attrs, decl, blk); + } + } + + fn check_impl_item(&mut self, cx: &EarlyContext, item: &ImplItem) { + if let ImplItemKind::Method(ref sig, ref blk) = item.node { + do_check(self, cx, &item.attrs, &sig.decl, blk); + } + } + +} + +fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { + if !attr::contains_name(attrs, "test") { + let mut visitor = SimilarNamesLocalVisitor { + names: Vec::new(), + cx: cx, + lint: lint, + single_char_names: Vec::new(), + }; + // initialize with function arguments + for arg in &decl.inputs { + SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); } + // walk all other bindings + walk_block(&mut visitor, blk); } } diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 29a677004b8..19f0889a92c 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -141,3 +141,14 @@ fn underscores_and_numbers() { let __1___2 = 12; //~ERROR Consider a more descriptive name let _1_ok= 1; } + +struct Bar; + +impl Bar { + fn bar() { + let _1 = 1; + let ____1 = 1; + let __1___2 = 12; + let _1_ok= 1; + } +} diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 850a3ccd951..4b95a1a9e70 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -149,5 +149,23 @@ error: consider choosing a more descriptive name 141 | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ -error: aborting due to 14 previous errors +error: consider choosing a more descriptive name + --> $DIR/non_expressive_names.rs:149:13 + | +149 | let _1 = 1; + | ^^ + +error: consider choosing a more descriptive name + --> $DIR/non_expressive_names.rs:150:13 + | +150 | let ____1 = 1; + | ^^^^^ + +error: consider choosing a more descriptive name + --> $DIR/non_expressive_names.rs:151:13 + | +151 | let __1___2 = 12; + | ^^^^^^^ + +error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From 10d2feddba907015cca79a23d451f00254ae4a36 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 2 Feb 2018 02:03:21 -0500 Subject: Fix `const_static_lifetime` --- clippy_lints/src/const_static_lifetime.rs | 20 +++++++++++++++++++- tests/ui/const_static_lifetime.rs | 12 ++++++++++++ tests/ui/const_static_lifetime.stderr | 20 +++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 293d63daaaa..2872cb12729 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,4 +1,4 @@ -use syntax::ast::{Item, ItemKind, Ty, TyKind}; +use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use utils::{in_macro, snippet, span_lint_and_then}; @@ -86,4 +86,22 @@ impl EarlyLintPass for StaticConst { } } } + + fn check_trait_item(&mut self, cx: &EarlyContext, item: &TraitItem) { + if !in_macro(item.span) { + // Match only constants... + if let TraitItemKind::Const(ref var_type, _) = item.node { + self.visit_type(var_type, cx); + } + } + } + + fn check_impl_item(&mut self, cx: &EarlyContext, item: &ImplItem) { + if !in_macro(item.span) { + // Match only constants... + if let ImplItemKind::Const(ref var_type, _) = item.node { + self.visit_type(var_type, cx); + } + } + } } diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index a033f2b368e..745821a1503 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -35,3 +35,15 @@ fn main() { println!("{:?}", VAR_HEIGHT); println!("{}", false_positive); } + +trait Bar { + const TRAIT_VAR: &'static str; +} + +impl Foo { + const IMPL_VAR: &'static str = "var"; +} + +impl Bar for Foo { + const TRAIT_VAR: &'static str = "foo"; +} diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index db33744c7a9..b1059d2ef01 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -78,5 +78,23 @@ error: Constants have by default a `'static` lifetime 24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` -error: aborting due to 13 previous errors +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:40:23 + | +40 | const TRAIT_VAR: &'static str; + | -^^^^^^^---- help: consider removing `'static`: `&str` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:44:22 + | +44 | const IMPL_VAR: &'static str = "var"; + | -^^^^^^^---- help: consider removing `'static`: `&str` + +error: Constants have by default a `'static` lifetime + --> $DIR/const_static_lifetime.rs:48:23 + | +48 | const TRAIT_VAR: &'static str = "foo"; + | -^^^^^^^---- help: consider removing `'static`: `&str` + +error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From 8e8cf2feb1bcb15950758c9213c3976713c1c6f1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 2 Feb 2018 13:23:32 +0530 Subject: Bump to 0.0.185 --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 288cc8bb02c..1970732e46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.185 +* Rustup to *rustc 1.25.0-nightly (56733bc9f 2018-02-01)* +* New lint: [`question_mark`] + ## 0.0.184 * Rustup to *rustc 1.25.0-nightly (90eb44a58 2018-01-29)* * New lints: [`double_comparisons`], [`empty_line_after_outer_attr`] @@ -690,6 +694,7 @@ All notable changes to this project will be documented in this file. [`println_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#println_empty_string [`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg [`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names +[`question_mark`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#question_mark [`range_minus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_minus_one [`range_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_step_by_zero diff --git a/Cargo.toml b/Cargo.toml index a87afab2319..638e3ee33a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.184" +version = "0.0.185" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.184", path = "clippy_lints" } +clippy_lints = { version = "0.0.185", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 60e7a7b28df..4f25dd8043f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.184" +version = "0.0.185" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 287595a6e8a..1d3cab85b1a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -89,7 +89,6 @@ pub mod doc; pub mod double_comparison; pub mod double_parens; pub mod drop_forget_ref; -pub mod question_mark; pub mod else_if_without_else; pub mod empty_enum; pub mod entry; @@ -150,6 +149,7 @@ pub mod partialeq_ne_impl; pub mod precedence; pub mod print; pub mod ptr; +pub mod question_mark; pub mod ranges; pub mod reference; pub mod regex; @@ -587,6 +587,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ptr::CMP_NULL, ptr::MUT_FROM_REF, ptr::PTR_ARG, + question_mark::QUESTION_MARK, ranges::ITERATOR_STEP_BY_ZERO, ranges::RANGE_MINUS_ONE, ranges::RANGE_ZIP_WITH_LEN, -- cgit 1.4.1-3-g733a5 From 9575dac49157a5939c9903fc6bc03324b1fadc14 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Sun, 4 Feb 2018 13:41:54 +0100 Subject: Fix suggestions for ref matches --- clippy_lints/src/matches.rs | 69 ++++++++++++++++++--------------------------- tests/ui/matches.stderr | 24 ++++++++++++---- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 2183c6e4fa6..979f0806e52 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -11,8 +11,8 @@ use syntax::ast::LitKind; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; -use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, remove_blocks, - snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; +use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, + remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use utils::sugg::Sugg; /// **What it does:** Checks for matches with a single arm where an `if let` @@ -195,8 +195,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { check_wild_err_arm(cx, ex, arms); check_match_as_ref(cx, ex, arms, expr); } - if let ExprMatch(ref ex, ref arms, source) = expr.node { - check_match_ref_pats(cx, ex, arms, source, expr); + if let ExprMatch(ref ex, ref arms, _) = expr.node { + check_match_ref_pats(cx, ex, arms, expr); } } } @@ -400,37 +400,34 @@ fn is_panic_block(block: &Block) -> bool { } } -fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { +fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if has_only_ref_pats(arms) { - if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - span_lint_and_then( - cx, - MATCH_REF_PATS, - expr.span, + let mut suggs = Vec::new(); + let (title, msg) = if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + suggs.push((ex.span, Sugg::hir(cx, inner, "..").to_string())); + ( "you don't need to add `&` to both the expression and the patterns", - |db| { - let inner = Sugg::hir(cx, inner, ".."); - let template = match_template(expr.span, source, &inner); - db.span_suggestion(expr.span, "try", template); - }, - ); + "try", + ) } else { - span_lint_and_then( - cx, - MATCH_REF_PATS, - expr.span, + suggs.push((ex.span, Sugg::hir(cx, ex, "..").deref().to_string())); + ( "you don't need to add `&` to all patterns", - |db| { - let ex = Sugg::hir(cx, ex, ".."); - let template = match_template(expr.span, source, &ex.deref()); - db.span_suggestion( - expr.span, - "instead of prefixing all patterns with `&`, you can dereference the expression", - template, - ); - }, - ); - } + "instead of prefixing all patterns with `&`, you can dereference the expression", + ) + }; + + suggs.extend(arms.iter().flat_map(|a| &a.pats).filter_map(|p| { + if let PatKind::Ref(ref refp, _) = p.node { + Some((p.span, snippet(cx, refp.span, "..").to_string())) + } else { + None + } + })); + + span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |db| { + multispan_sugg(db, msg.to_owned(), suggs); + }); } } @@ -615,16 +612,6 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { mapped.map_or(false, |v| v.iter().any(|el| *el)) } -fn match_template(span: Span, source: MatchSource, expr: &Sugg) -> String { - match source { - MatchSource::Normal => format!("match {} {{ .. }}", expr), - MatchSource::IfLetDesugar { .. } => format!("if let .. = {} {{ .. }}", expr), - MatchSource::WhileLetDesugar => format!("while let .. = {} {{ .. }}", expr), - MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), - MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"), - } -} - pub fn overlapping(ranges: &[SpannedRange]) -> Option<(&SpannedRange, &SpannedRange)> where T: Copy + Ord, diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index fd22247cb1f..af7aa33dc77 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -132,7 +132,9 @@ error: you don't need to add `&` to all patterns = note: `-D match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -138 | match *v { .. } +138 | match *v { +139 | Some(v) => println!("{:?}", v), +140 | None => println!("none"), | error: you don't need to add `&` to all patterns @@ -145,7 +147,8 @@ error: you don't need to add `&` to all patterns | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -148 | match *tup { .. } +148 | match *tup { +149 | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns @@ -155,7 +158,13 @@ error: you don't need to add `&` to both the expression and the patterns 155 | | &Some(v) => println!("{:?}", v), 156 | | &None => println!("none"), 157 | | } - | |_____^ help: try: `match w { .. }` + | |_____^ +help: try + | +154 | match w { +155 | Some(v) => println!("{:?}", v), +156 | None => println!("none"), + | error: you don't need to add `&` to all patterns --> $DIR/matches.rs:165:5 @@ -166,7 +175,7 @@ error: you don't need to add `&` to all patterns | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -165 | if let .. = *a { .. } +165 | if let None = *a { | error: you don't need to add `&` to both the expression and the patterns @@ -175,7 +184,11 @@ error: you don't need to add `&` to both the expression and the patterns 170 | / if let &None = &b { 171 | | println!("none"); 172 | | } - | |_____^ help: try: `if let .. = b { .. }` + | |_____^ +help: try + | +170 | if let None = b { + | error: some ranges overlap --> $DIR/matches.rs:179:9 @@ -450,3 +463,4 @@ error: use as_mut() instead error: aborting due to 37 previous errors + -- cgit 1.4.1-3-g733a5 From 21f606bd688c9a45b372790b26d3c3d083f1cdd1 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Sun, 4 Feb 2018 13:55:37 +0100 Subject: Removing extra newline --- tests/ui/matches.stderr | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index af7aa33dc77..5b4c222e6dc 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -463,4 +463,3 @@ error: use as_mut() instead error: aborting due to 37 previous errors - -- cgit 1.4.1-3-g733a5 From 5226b664a17f8b91b577bab4df217ad07ebd0dce Mon Sep 17 00:00:00 2001 From: messense Date: Mon, 5 Feb 2018 12:16:17 +0800 Subject: Rustup to rustc 1.25.0-nightly (0c6091fbd 2018-02-04) --- clippy_lints/src/utils/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7cb3e08a116..9cb67d4da41 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{LayoutOf, Align}; +use rustc::ty::layout::Align; use rustc_errors; use std::borrow::Cow; use std::env; @@ -1038,7 +1038,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - (cx.tcx, cx.param_env).layout_of(ty) + cx.tcx.layout_of(cx.param_env.and(ty)) .ok() .map(|layout| layout.size.bytes()) } @@ -1060,5 +1060,7 @@ pub fn get_arg_name(pat: &Pat) -> Option { /// Returns alignment for a type, or None if alignment is undefined pub fn alignment<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - (cx.tcx, cx.param_env).layout_of(ty).ok().map(|layout| layout.align) + cx.tcx.layout_of(cx.param_env.and(ty)) + .ok() + .map(|layout| layout.align) } -- cgit 1.4.1-3-g733a5 From ce47e529d29f0bf19b31ae80b37b467e42fb97e2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 5 Feb 2018 08:48:40 +0100 Subject: Version Bump --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1970732e46e..d953f0f22cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.186 +* Rustup to *rustc 1.25.0-nightly (0c6091fbd 2018-02-04)* +* Various false positive fixes + ## 0.0.185 * Rustup to *rustc 1.25.0-nightly (56733bc9f 2018-02-01)* * New lint: [`question_mark`] diff --git a/Cargo.toml b/Cargo.toml index 638e3ee33a3..0ba3e5e6c6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.185" +version = "0.0.186" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.185", path = "clippy_lints" } +clippy_lints = { version = "0.0.186", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 4f25dd8043f..9249e871204 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.185" +version = "0.0.186" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 503a63390df10c6c025f1c1c514a232a0a163c38 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 5 Feb 2018 11:28:09 +0100 Subject: Cleanup calls to `layout_of` --- clippy_lints/src/transmute.rs | 8 ++++---- clippy_lints/src/utils/mod.rs | 11 ++--------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 090f9397472..2be5f4764f4 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,10 +1,10 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; +use rustc::ty::layout::LayoutOf; use std::borrow::Cow; use syntax::ast; -use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, - alignment}; +use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::{opt_def_id, sugg}; /// **What it does:** Checks for transmutes that can't ever be correct on any @@ -220,8 +220,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), - _ if alignment(cx, from_ty).map(|a| a.abi()) - < alignment(cx, to_ty).map(|a| a.abi()) + _ if cx.layout_of(from_ty).ok().map(|a| a.align.abi()) + < cx.layout_of(to_ty).ok().map(|a| a.align.abi()) => span_lint( cx, MISALIGNED_TRANSMUTE, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 161ce866fd7..75aa235ed3c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::Align; +use rustc::ty::layout::LayoutOf; use rustc_errors; use std::borrow::Cow; use std::env; @@ -1041,7 +1041,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - cx.tcx.layout_of(cx.param_env.and(ty)) + cx.layout_of(ty) .ok() .map(|layout| layout.size.bytes()) } @@ -1060,10 +1060,3 @@ pub fn get_arg_name(pat: &Pat) -> Option { _ => None, } } - -/// Returns alignment for a type, or None if alignment is undefined -pub fn alignment<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - cx.tcx.layout_of(cx.param_env.and(ty)) - .ok() - .map(|layout| layout.align) -} -- cgit 1.4.1-3-g733a5 From bcf2e4142127c5e8411f69878de2fe4895608a06 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Tue, 6 Feb 2018 00:31:06 +0100 Subject: Fix ICE comparing `ExprRange` `eq_expr` on hir::utils was throwing an ICE due to an invalid LateContext being used. Due to this missusage, it was generating an ICE with the code on the following issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2423 --- clippy_lints/src/consts.rs | 15 +++++++++++++-- clippy_lints/src/utils/hir_utils.rs | 10 +++++++--- tests/ui/copies.rs | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 69527ba6ff8..a99a56bc554 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -229,7 +229,18 @@ pub fn constant_simple(lcx: &LateContext, e: &Expr) -> Option { constant(lcx, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } -struct ConstEvalLateContext<'a, 'tcx: 'a> { +/// Creates a ConstEvalLateContext from the given LateContext and TypeckTables +pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'cc ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> { + ConstEvalLateContext { + tcx: lcx.tcx, + tables, + param_env: lcx.param_env, + needed_resolution: false, + substs: lcx.tcx.intern_substs(&[]), + } +} + +pub struct ConstEvalLateContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -239,7 +250,7 @@ struct ConstEvalLateContext<'a, 'tcx: 'a> { impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// simple constant folding: Insert an expression, get a constant or none. - fn expr(&mut self, e: &Expr) -> Option { + pub fn expr(&mut self, e: &Expr) -> Option { match e.node { ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id), ExprBlock(ref block) => self.block(block), diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 5932c41dc13..34073d9725b 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,4 +1,4 @@ -use consts::constant; +use consts::{constant, constant_context}; use rustc::lint::*; use rustc::hir::*; use std::hash::{Hash, Hasher}; @@ -117,8 +117,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) }, (&ExprRepeat(ref le, ll_id), &ExprRepeat(ref re, rl_id)) => { - self.eq_expr(le, re) - && self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id)); + let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id).value); + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id)); + let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id).value); + + self.eq_expr(le, re) && ll == rl }, (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r), diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 4c4050c014f..0488591bae9 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -396,3 +396,18 @@ fn ifs_same_cond() { } fn main() {} + +// Issue #2423. This was causing an ICE +fn func() { + if true { + f(&[0; 62]); + f(&[0; 4]); + f(&[0; 3]); + } else { + f(&[0; 62]); + f(&[0; 6]); + f(&[0; 6]); + } +} + +fn f(val: &[u8]) {} -- cgit 1.4.1-3-g733a5 From 63a7daf78c9f57fc190fba6b783c9509aa8306cd Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 6 Feb 2018 13:05:20 +0100 Subject: Make decimal_literal_representation a restriction lint --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/literal_representation.rs | 3 +- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/decimal_literal_representation.rs | 14 ++++++--- tests/ui/decimal_literal_representation.stderr | 40 ++++++++------------------ 5 files changed, 25 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d3cab85b1a..bec46ba180c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -382,6 +382,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { else_if_without_else::ELSE_IF_WITHOUT_ELSE, methods::CLONE_ON_REF_PTR, misc::FLOAT_CMP_CONST, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, ]); reg.register_lint_group("clippy_pedantic", vec![ @@ -496,7 +497,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { let_if_seq::USELESS_LET_IF_SEQ, lifetimes::NEEDLESS_LIFETIMES, lifetimes::UNUSED_LIFETIMES, - literal_representation::DECIMAL_LITERAL_REPRESENTATION, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index a0c4f537a15..9633ac00b15 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -74,9 +74,8 @@ declare_lint! { /// `255` => `0xFF` /// `65_535` => `0xFFFF` /// `4_042_322_160` => `0xF0F0_F0F0` -declare_lint! { +declare_restriction_lint! { pub DECIMAL_LITERAL_REPRESENTATION, - Warn, "using decimal representation when hexadecimal would be better" } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 2906da3c028..9f40713f6e4 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -178,7 +178,7 @@ define_Conf! { /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals - (literal_representation_threshold, "literal_representation_threshold", 4096 => u64), + (literal_representation_threshold, "literal_representation_threshold", 16384 => u64), } /// Search for the configuration file. diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index 3ac33d7ac4a..5463b8957f3 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -4,11 +4,17 @@ #[warn(decimal_literal_representation)] #[allow(unused_variables)] fn main() { - // Hex: 7F, 80, 100, 1FF, 800, FFA, F0F3, 7F0F_F00D - let good = (127, 128, 256, 511, 2048, 4090, 61_683, 2_131_750_925); + let good = ( // Hex: + 127, // 0x7F + 256, // 0x100 + 511, // 0x1FF + 2048, // 0x800 + 4090, // 0xFFA + 16_371, // 0x3FF3 + 61_683, // 0xF0F3 + 2_131_750_925, // 0x7F0F_F00D + ); let bad = ( // Hex: - 4096, // 0x1000 - 16_371, // 0x3FF3 32_773, // 0x8005 65_280, // 0xFF00 2_131_750_927, // 0x7F0F_F00F diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index bd3c727b728..e3fbeba8148 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,59 +1,43 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:10:9 + --> $DIR/decimal_literal_representation.rs:18:9 | -10 | 4096, // 0x1000 - | ^^^^ - | - = note: `-D decimal-literal-representation` implied by `-D warnings` - = help: consider: 0x1000 - -error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:11:9 - | -11 | 16_371, // 0x3FF3 - | ^^^^^^ - | - = help: consider: 0x3FF3 - -error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:12:9 - | -12 | 32_773, // 0x8005 +18 | 32_773, // 0x8005 | ^^^^^^ | + = note: `-D decimal-literal-representation` implied by `-D warnings` = help: consider: 0x8005 error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:13:9 + --> $DIR/decimal_literal_representation.rs:19:9 | -13 | 65_280, // 0xFF00 +19 | 65_280, // 0xFF00 | ^^^^^^ | = help: consider: 0xFF00 error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:14:9 + --> $DIR/decimal_literal_representation.rs:20:9 | -14 | 2_131_750_927, // 0x7F0F_F00F +20 | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ | = help: consider: 0x7F0F_F00F error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:15:9 + --> $DIR/decimal_literal_representation.rs:21:9 | -15 | 2_147_483_647, // 0x7FFF_FFFF +21 | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ | = help: consider: 0x7FFF_FFFF error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:16:9 + --> $DIR/decimal_literal_representation.rs:22:9 | -16 | 4_042_322_160, // 0xF0F0_F0F0 +22 | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ | = help: consider: 0xF0F0_F0F0 -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 73f2ba5ded4452839d2025f6fe6eb0818685fa2a Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Tue, 6 Feb 2018 12:22:34 -0600 Subject: don't suggest eliding 'static on associated consts --- clippy_lints/src/const_static_lifetime.rs | 18 +----------------- tests/ui/const_static_lifetime.stderr | 20 +------------------- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 2872cb12729..66a1634ebce 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -87,21 +87,5 @@ impl EarlyLintPass for StaticConst { } } - fn check_trait_item(&mut self, cx: &EarlyContext, item: &TraitItem) { - if !in_macro(item.span) { - // Match only constants... - if let TraitItemKind::Const(ref var_type, _) = item.node { - self.visit_type(var_type, cx); - } - } - } - - fn check_impl_item(&mut self, cx: &EarlyContext, item: &ImplItem) { - if !in_macro(item.span) { - // Match only constants... - if let ImplItemKind::Const(ref var_type, _) = item.node { - self.visit_type(var_type, cx); - } - } - } + // Don't check associated consts because `'static` cannot be elided on those (issue #2438) } diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index b1059d2ef01..db33744c7a9 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -78,23 +78,5 @@ error: Constants have by default a `'static` lifetime 24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` -error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:40:23 - | -40 | const TRAIT_VAR: &'static str; - | -^^^^^^^---- help: consider removing `'static`: `&str` - -error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:44:22 - | -44 | const IMPL_VAR: &'static str = "var"; - | -^^^^^^^---- help: consider removing `'static`: `&str` - -error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:48:23 - | -48 | const TRAIT_VAR: &'static str = "foo"; - | -^^^^^^^---- help: consider removing `'static`: `&str` - -error: aborting due to 16 previous errors +error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 81f5969704b57215ac12a78459c8ccfbad9be654 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 6 Feb 2018 22:14:23 +0100 Subject: Partly fix incorrect useless_attribute suggestion This fixes an incorrect suggestion from the `useless_attribute` lint when using `cfg_attr`. Additionally, it will not show a suggestion anymore, if the attribute begins on a previous line, because it is much harder to construct the span of multi-line `cfg_attr` attributes as they don't appear in the AST. To fix it completely, one would have to parse upwards into the file, and find the beginning of the `cfg_attr` attribute. --- clippy_lints/src/attrs.rs | 14 ++++++++------ clippy_lints/src/utils/mod.rs | 8 ++++++++ tests/ui/useless_attribute.rs | 3 +++ tests/ui/useless_attribute.stderr | 8 +++++++- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index aefdd6527a9..50aaa66aada 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; +use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -156,17 +156,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } } - if let Some(mut sugg) = snippet_opt(cx, attr.span) { - if sugg.len() > 1 { + let line_span = last_line_of_span(cx, attr.span); + + if let Some(mut sugg) = snippet_opt(cx, line_span) { + if sugg.contains("#[") { span_lint_and_then( cx, USELESS_ATTRIBUTE, - attr.span, + line_span, "useless lint attribute", |db| { - sugg.insert(1, '!'); + sugg = sugg.replacen("#[", "#![", 1); db.span_suggestion( - attr.span, + line_span, "if you just forgot a `!`, use", sugg, ); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 75aa235ed3c..e89163fb52b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -427,6 +427,14 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' trim_multiline(snip, true) } +/// Returns a new Span that covers the full last line of the given Span +pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { + let file_map_and_line = cx.sess().codemap().lookup_line(span.lo()).unwrap(); + let line_no = file_map_and_line.line; + let line_start = &file_map_and_line.fm.lines.clone().into_inner()[line_no]; + Span::new(*line_start, span.hi(), span.ctxt()) +} + /// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. /// Also takes an `Option` which can be put inside the braces. pub fn expr_block<'a, 'b, T: LintContext<'b>>( diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 4c2fb221af8..217e886c8be 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -3,6 +3,9 @@ #![warn(useless_attribute)] #[allow(dead_code, unused_extern_crates)] +#[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] +#[cfg_attr(feature = "cargo-clippy", + allow(dead_code, unused_extern_crates))] extern crate clippy_lints; // don't lint on unused_import for `use` items diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 707a11d55cc..84b81e56107 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -6,5 +6,11 @@ error: useless lint attribute | = note: `-D useless-attribute` implied by `-D warnings` -error: aborting due to previous error +error: useless lint attribute + --> $DIR/useless_attribute.rs:6:1 + | +6 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 45e4f3aac79bb4f34952ff70a15aaed36bcd811c Mon Sep 17 00:00:00 2001 From: Guido Date: Wed, 7 Feb 2018 19:24:38 +0100 Subject: Simplify recommended command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e4f0f3547ce..46b069eb661 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ To have cargo compile your crate with clippy without needing `#![plugin(clippy)] in your code, you can use: ```terminal -cargo rustc -- -L /path/to/clippy_so/dir/ -Z extra-plugins=clippy +cargo-clippy ``` *[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* -- cgit 1.4.1-3-g733a5 From b52f46d1d17301d75fe212d4b95bfd7fdf4d9fb8 Mon Sep 17 00:00:00 2001 From: Guido Date: Thu, 8 Feb 2018 12:37:56 +0100 Subject: Change command to run clippy without installation --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46b069eb661..ecf00f2fdba 100644 --- a/README.md +++ b/README.md @@ -85,13 +85,13 @@ and add to `main.rs` or `lib.rs`: #![cfg_attr(test, plugin(clippy))] ``` -### Running clippy from the command line without installing +### Running clippy from the command line without installing it -To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` +To have cargo compile your crate with clippy without clippy installation and without needing `#![plugin(clippy)]` in your code, you can use: ```terminal -cargo-clippy +cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` *[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* -- cgit 1.4.1-3-g733a5 From 44780aca5d9a92251df6b027747790bdcbb29c06 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Thu, 8 Feb 2018 13:26:50 -0600 Subject: make the copies.rs test actually test the correct lints --- tests/ui/copies.rs | 55 +++--- tests/ui/copies.stderr | 466 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 454 insertions(+), 67 deletions(-) diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 0488591bae9..e5f5810795d 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,14 +1,7 @@ #![feature(dotdoteq_in_patterns, inclusive_range_syntax)] -#![allow(dead_code, no_effect, unnecessary_operation)] -#![allow(let_and_return)] -#![allow(needless_return)] -#![allow(unused_variables)] -#![allow(cyclomatic_complexity)] -#![allow(blacklisted_name)] -#![allow(collapsible_if)] -#![allow(zero_divided_by_zero, eq_op)] -#![allow(path_statements)] +#![allow(blacklisted_name, collapsible_if, cyclomatic_complexity, eq_op, needless_continue, + needless_return, never_loop, no_effect, zero_divided_by_zero)] fn bar(_: T) {} fn foo() -> bool { unimplemented!() } @@ -35,7 +28,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { 0..=10; foo(); } - else { + else { //~ ERROR same body as `if` block Foo { bar: 42 }; 0..10; ..; @@ -84,7 +77,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { a = -31-a; a } - _ => { + _ => { //~ ERROR match arms have same body foo(); let mut a = 42 + [23].len() as i32; if true { @@ -98,7 +91,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match Abc::A { Abc::A => 0, Abc::B => 1, - _ => 0, + _ => 0, //~ ERROR match arms have same body }; if true { @@ -108,7 +101,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = if true { 42 } - else { + else { //~ ERROR same body as `if` block 42 }; @@ -122,7 +115,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { } } } - else { + else { //~ ERROR same body as `if` block for _ in &[42] { let foo: &Option<_> = &Some::(42); if true { @@ -144,7 +137,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { while foo() { break; } bar + 1; } - else { + else { //~ ERROR same body as `if` block let bar = if true { 42 } @@ -167,7 +160,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { else if false { foo(); } - else if foo() { + else if foo() { //~ ERROR same body as `if` block let _ = match 42 { 42 => 1, a if a > 0 => 2, @@ -179,14 +172,14 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { if let Some(a) = Some(42) {} } - else { + else { //~ ERROR same body as `if` block if let Some(a) = Some(42) {} } if true { if let (1, .., 3) = (1, 2, 3) {} } - else { + else { //~ ERROR same body as `if` block if let (1, .., 3) = (1, 2, 3) {} } @@ -241,13 +234,13 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = match 42 { 42 => foo(), - 51 => foo(), + 51 => foo(), //~ ERROR match arms have same body _ => true, }; let _ = match Some(42) { Some(_) => 24, - None => 24, + None => 24, //~ ERROR match arms have same body }; let _ = match Some(42) { @@ -269,31 +262,31 @@ fn if_same_then_else() -> Result<&'static str, ()> { match (Some(42), Some(42)) { (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), + (None, Some(a)) => bar(a), //~ ERROR match arms have same body _ => (), } match (Some(42), Some(42)) { (Some(a), ..) => bar(a), - (.., Some(a)) => bar(a), + (.., Some(a)) => bar(a), //~ ERROR match arms have same body _ => (), } match (1, 2, 3) { (1, .., 3) => 42, - (.., 3) => 42, + (.., 3) => 42, //~ ERROR match arms have same body _ => 0, }; let _ = if true { 0.0 - } else { + } else { //~ ERROR same body as `if` block 0.0 }; let _ = if true { -0.0 - } else { + } else { //~ ERROR same body as `if` block -0.0 }; @@ -313,7 +306,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { // Same NaNs let _ = if true { std::f32::NAN - } else { + } else { //~ ERROR same body as `if` block std::f32::NAN }; @@ -331,7 +324,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { try!(Ok("foo")); } - else { + else { //~ ERROR same body as `if` block try!(Ok("foo")); } @@ -343,7 +336,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let foo = "bar"; return Ok(&foo[0..]); } - else { + else { //~ ERROR same body as `if` block let foo = ""; return Ok(&foo[0..]); } @@ -357,19 +350,19 @@ fn ifs_same_cond() { if b { } - else if b { + else if b { //~ ERROR ifs same condition } if a == 1 { } - else if a == 1 { + else if a == 1 { //~ ERROR ifs same condition } if 2*a == 1 { } else if 2*a == 2 { } - else if 2*a == 1 { + else if 2*a == 1 { //~ ERROR ifs same condition } else if a == 1 { } diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 9accb310d12..c6034a19906 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,37 +1,431 @@ -error: This else block is redundant. - - --> $DIR/copies.rs:120:20 - | -120 | } else { - | ____________________^ -121 | | continue; -122 | | } - | |_____________^ - | - = note: `-D needless-continue` implied by `-D warnings` - = help: Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so: - if true { - break; - // Merged code follows... - } - - -error: This else block is redundant. - - --> $DIR/copies.rs:130:20 - | -130 | } else { - | ____________________^ -131 | | continue; -132 | | } - | |_____________^ - | - = help: Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so: - if true { - break; - // Merged code follows... - } - - -error: aborting due to 2 previous errors +error: this `if` has identical blocks + --> $DIR/copies.rs:31:10 + | +31 | else { //~ ERROR same body as `if` block + | __________^ +32 | | Foo { bar: 42 }; +33 | | 0..10; +34 | | ..; +... | +38 | | foo(); +39 | | } + | |_____^ + | + = note: `-D if-same-then-else` implied by `-D warnings` +note: same as this + --> $DIR/copies.rs:22:13 + | +22 | if true { + | _____________^ +23 | | Foo { bar: 42 }; +24 | | 0..10; +25 | | ..; +... | +29 | | foo(); +30 | | } + | |_____^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:80:14 + | +80 | _ => { //~ ERROR match arms have same body + | ______________^ +81 | | foo(); +82 | | let mut a = 42 + [23].len() as i32; +83 | | if true { +... | +87 | | a +88 | | } + | |_________^ + | + = note: `-D match-same-arms` implied by `-D warnings` +note: same as this + --> $DIR/copies.rs:71:15 + | +71 | 42 => { + | _______________^ +72 | | foo(); +73 | | let mut a = 42 + [23].len() as i32; +74 | | if true { +... | +78 | | a +79 | | } + | |_________^ +note: `42` has the same arm body as the `_` wildcard, consider removing it` + --> $DIR/copies.rs:71:15 + | +71 | 42 => { + | _______________^ +72 | | foo(); +73 | | let mut a = 42 + [23].len() as i32; +74 | | if true { +... | +78 | | a +79 | | } + | |_________^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:94:14 + | +94 | _ => 0, //~ ERROR match arms have same body + | ^ + | +note: same as this + --> $DIR/copies.rs:92:19 + | +92 | Abc::A => 0, + | ^ +note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` + --> $DIR/copies.rs:92:19 + | +92 | Abc::A => 0, + | ^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:104:10 + | +104 | else { //~ ERROR same body as `if` block + | __________^ +105 | | 42 +106 | | }; + | |_____^ + | +note: same as this + --> $DIR/copies.rs:101:21 + | +101 | let _ = if true { + | _____________________^ +102 | | 42 +103 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:118:10 + | +118 | else { //~ ERROR same body as `if` block + | __________^ +119 | | for _ in &[42] { +120 | | let foo: &Option<_> = &Some::(42); +121 | | if true { +... | +126 | | } +127 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:108:13 + | +108 | if true { + | _____________^ +109 | | for _ in &[42] { +110 | | let foo: &Option<_> = &Some::(42); +111 | | if true { +... | +116 | | } +117 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:140:10 + | +140 | else { //~ ERROR same body as `if` block + | __________^ +141 | | let bar = if true { +142 | | 42 +143 | | } +... | +149 | | bar + 1; +150 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:129:13 + | +129 | if true { + | _____________^ +130 | | let bar = if true { +131 | | 42 +132 | | } +... | +138 | | bar + 1; +139 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:163:19 + | +163 | else if foo() { //~ ERROR same body as `if` block + | ___________________^ +164 | | let _ = match 42 { +165 | | 42 => 1, +166 | | a if a > 0 => 2, +... | +169 | | }; +170 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:152:13 + | +152 | if true { + | _____________^ +153 | | let _ = match 42 { +154 | | 42 => 1, +155 | | a if a > 0 => 2, +... | +158 | | }; +159 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:175:10 + | +175 | else { //~ ERROR same body as `if` block + | __________^ +176 | | if let Some(a) = Some(42) {} +177 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:172:13 + | +172 | if true { + | _____________^ +173 | | if let Some(a) = Some(42) {} +174 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:182:10 + | +182 | else { //~ ERROR same body as `if` block + | __________^ +183 | | if let (1, .., 3) = (1, 2, 3) {} +184 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:179:13 + | +179 | if true { + | _____________^ +180 | | if let (1, .., 3) = (1, 2, 3) {} +181 | | } + | |_____^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:237:15 + | +237 | 51 => foo(), //~ ERROR match arms have same body + | ^^^^^ + | +note: same as this + --> $DIR/copies.rs:236:15 + | +236 | 42 => foo(), + | ^^^^^ +note: consider refactoring into `42 | 51` + --> $DIR/copies.rs:236:15 + | +236 | 42 => foo(), + | ^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:243:17 + | +243 | None => 24, //~ ERROR match arms have same body + | ^^ + | +note: same as this + --> $DIR/copies.rs:242:20 + | +242 | Some(_) => 24, + | ^^ +note: consider refactoring into `Some(_) | None` + --> $DIR/copies.rs:242:20 + | +242 | Some(_) => 24, + | ^^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:265:28 + | +265 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | +note: same as this + --> $DIR/copies.rs:264:28 + | +264 | (Some(a), None) => bar(a), + | ^^^^^^ +note: consider refactoring into `(Some(a), None) | (None, Some(a))` + --> $DIR/copies.rs:264:28 + | +264 | (Some(a), None) => bar(a), + | ^^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:271:26 + | +271 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | +note: same as this + --> $DIR/copies.rs:270:26 + | +270 | (Some(a), ..) => bar(a), + | ^^^^^^ +note: consider refactoring into `(Some(a), ..) | (.., Some(a))` + --> $DIR/copies.rs:270:26 + | +270 | (Some(a), ..) => bar(a), + | ^^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/copies.rs:277:20 + | +277 | (.., 3) => 42, //~ ERROR match arms have same body + | ^^ + | +note: same as this + --> $DIR/copies.rs:276:23 + | +276 | (1, .., 3) => 42, + | ^^ +note: consider refactoring into `(1, .., 3) | (.., 3)` + --> $DIR/copies.rs:276:23 + | +276 | (1, .., 3) => 42, + | ^^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:283:12 + | +283 | } else { //~ ERROR same body as `if` block + | ____________^ +284 | | 0.0 +285 | | }; + | |_____^ + | +note: same as this + --> $DIR/copies.rs:281:21 + | +281 | let _ = if true { + | _____________________^ +282 | | 0.0 +283 | | } else { //~ ERROR same body as `if` block + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:289:12 + | +289 | } else { //~ ERROR same body as `if` block + | ____________^ +290 | | -0.0 +291 | | }; + | |_____^ + | +note: same as this + --> $DIR/copies.rs:287:21 + | +287 | let _ = if true { + | _____________________^ +288 | | -0.0 +289 | | } else { //~ ERROR same body as `if` block + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:309:12 + | +309 | } else { //~ ERROR same body as `if` block + | ____________^ +310 | | std::f32::NAN +311 | | }; + | |_____^ + | +note: same as this + --> $DIR/copies.rs:307:21 + | +307 | let _ = if true { + | _____________________^ +308 | | std::f32::NAN +309 | | } else { //~ ERROR same body as `if` block + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:327:10 + | +327 | else { //~ ERROR same body as `if` block + | __________^ +328 | | try!(Ok("foo")); +329 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:324:13 + | +324 | if true { + | _____________^ +325 | | try!(Ok("foo")); +326 | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/copies.rs:339:10 + | +339 | else { //~ ERROR same body as `if` block + | __________^ +340 | | let foo = ""; +341 | | return Ok(&foo[0..]); +342 | | } + | |_____^ + | +note: same as this + --> $DIR/copies.rs:331:13 + | +331 | if true { + | _____________^ +332 | | let foo = ""; +333 | | return Ok(&foo[0..]); +334 | | } + | |_____^ + +error: this `if` has the same condition as a previous if + --> $DIR/copies.rs:353:13 + | +353 | else if b { //~ ERROR ifs same condition + | ^ + | + = note: `-D ifs-same-cond` implied by `-D warnings` +note: same as this + --> $DIR/copies.rs:351:8 + | +351 | if b { + | ^ + +error: this `if` has the same condition as a previous if + --> $DIR/copies.rs:358:13 + | +358 | else if a == 1 { //~ ERROR ifs same condition + | ^^^^^^ + | +note: same as this + --> $DIR/copies.rs:356:8 + | +356 | if a == 1 { + | ^^^^^^ + +error: this `if` has the same condition as a previous if + --> $DIR/copies.rs:365:13 + | +365 | else if 2*a == 1 { //~ ERROR ifs same condition + | ^^^^^^^^ + | +note: same as this + --> $DIR/copies.rs:361:8 + | +361 | if 2*a == 1 { + | ^^^^^^^^ + +error: aborting due to 22 previous errors -- cgit 1.4.1-3-g733a5 From 88970ec8cf8645e4af826f54341486b04f853846 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Feb 2018 14:22:41 +0100 Subject: Remove rarely used `type_size` helper function --- clippy_lints/src/escape.rs | 5 +++-- clippy_lints/src/large_enum_variant.rs | 14 ++++++-------- clippy_lints/src/types.rs | 5 +++-- clippy_lints/src/utils/mod.rs | 7 ------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 2038a59137c..d4c91eab1c3 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -5,10 +5,11 @@ use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt, Categorization}; use rustc::ty::{self, Ty}; +use rustc::ty::layout::LayoutOf; use rustc::util::nodemap::NodeSet; use syntax::ast::NodeId; use syntax::codemap::Span; -use utils::{span_lint, type_size}; +use utils::span_lint; pub struct Pass { pub too_large_for_stack: u64, @@ -164,7 +165,7 @@ impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { // Large types need to be boxed to avoid stack // overflows. if ty.is_box() { - type_size(self.cx, ty.boxed_ty()).unwrap_or(0) > self.too_large_for_stack + self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack } else { false } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index ceb0cbd6688..e13b771cf24 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then, type_size}; -use rustc::ty::TypeFoldable; +use utils::{snippet_opt, span_lint_and_then}; +use rustc::ty::layout::LayoutOf; /// **What it does:** Checks for large size differences between variants on /// `enum`s. @@ -61,13 +61,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let size: u64 = variant .fields .iter() - .map(|f| { + .filter_map(|f| { let ty = cx.tcx.type_of(f.did); - if ty.needs_subst() { - 0 // we can't reason about generics, so we treat them as zero sized - } else { - type_size(cx, ty).expect("size should be computable for concrete type") - } + // don't count generics by filtering out everything + // that does not have a layout + cx.layout_of(ty).ok().map(|l| l.size.bytes()) }) .sum(); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c7e724625be..ba79bf4407b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -4,6 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; +use rustc::ty::layout::LayoutOf; use rustc::ty::subst::Substs; use rustc_typeck::hir_ty_to_ty; use std::cmp::Ordering; @@ -15,7 +16,7 @@ use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then, type_size}; + span_lint_and_sugg, span_lint_and_then}; use utils::paths; /// Handles all the linting of funky types @@ -1478,7 +1479,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( let pre_cast_ty = cx.tables.expr_ty(cast_exp); let cast_ty = cx.tables.expr_ty(expr); // if it's a cast from i32 to u32 wrapping will invalidate all these checks - if type_size(cx, pre_cast_ty) == type_size(cx, cast_ty) { + if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) { return None; } match pre_cast_ty.sty { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e89163fb52b..c501dadeb79 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,6 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::LayoutOf; use rustc_errors; use std::borrow::Cow; use std::env; @@ -1048,12 +1047,6 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { None } -pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - cx.layout_of(ty) - .ok() - .map(|layout| layout.size.bytes()) -} - /// Returns true if the lint is allowed in the current context /// /// Useful for skipping long running code when it's unnecessary -- cgit 1.4.1-3-g733a5 From ff32d5f7343934f4267af4e270017c716fb9d4ad Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Feb 2018 14:22:50 +0100 Subject: Fix #2427 --- clippy_lints/src/utils/hir_utils.rs | 6 +++--- tests/run-pass/match_same_arms_const.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 tests/run-pass/match_same_arms_const.rs diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 34073d9725b..cad6ec532a6 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,4 +1,4 @@ -use consts::{constant, constant_context}; +use consts::{constant_simple, constant_context}; use rustc::lint::*; use rustc::hir::*; use std::hash::{Hash, Hasher}; @@ -64,7 +64,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { return false; } - if let (Some(l), Some(r)) = (constant(self.cx, left), constant(self.cx, right)) { + if let (Some(l), Some(r)) = (constant_simple(self.cx, left), constant_simple(self.cx, right)) { if l == r { return true; } @@ -317,7 +317,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { } pub fn hash_expr(&mut self, e: &Expr) { - if let Some(e) = constant(self.cx, e) { + if let Some(e) = constant_simple(self.cx, e) { return e.hash(&mut self.s); } diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs new file mode 100644 index 00000000000..08acc2bc4d8 --- /dev/null +++ b/tests/run-pass/match_same_arms_const.rs @@ -0,0 +1,16 @@ +#![deny(match_same_arms)] + +const PRICE_OF_SWEETS: u32 = 5; +const PRICE_OF_KINDNESS: u32 = 0; +const PRICE_OF_DRINKS: u32 = 5; + +pub fn price(thing: &str) -> u32 { + match thing { + "rolo" => PRICE_OF_SWEETS, + "advice" => PRICE_OF_KINDNESS, + "juice" => PRICE_OF_DRINKS, + _ => panic!() + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 6feb0dd9824e81c2ee9a2389e53e564d25bdca2d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Feb 2018 15:23:51 +0100 Subject: Fixes #2426 (if_same_then_else false positive) --- clippy_lints/src/copies.rs | 21 ++++++++++------ tests/run-pass/if_same_then_else.rs | 13 ++++++++++ tests/ui/copies.rs | 4 ++-- tests/ui/copies.stderr | 48 +------------------------------------ 4 files changed, 30 insertions(+), 56 deletions(-) create mode 100644 tests/run-pass/if_same_then_else.rs diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 181158a5f17..d41ea5849a8 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -134,15 +134,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { /// Implementation of `IF_SAME_THEN_ELSE`. fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; - if let Some((i, j)) = search_same(blocks, hash, eq) { + if let Some((i, j)) = search_same_sequenced(blocks, eq) { span_note_and_lint( cx, IF_SAME_THEN_ELSE, @@ -309,6 +303,19 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap(exprs: &[T], eq: Eq) -> Option<(&T, &T)> +where + Eq: Fn(&T, &T) -> bool, +{ + for win in exprs.windows(2) { + if eq(&win[0], &win[1]) { + return Some((&win[0], &win[1])); + } + } + None +} + fn search_same(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> where Hash: Fn(&T) -> u64, diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs new file mode 100644 index 00000000000..eb14ce80756 --- /dev/null +++ b/tests/run-pass/if_same_then_else.rs @@ -0,0 +1,13 @@ +#![deny(if_same_then_else)] + +fn main() {} + +pub fn foo(a: i32, b: i32) -> Option<&'static str> { + if a == b { + None + } else if a > b { + Some("a pfeil b") + } else { + None + } +} diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index e5f5810795d..0588c141103 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -160,7 +160,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { else if false { foo(); } - else if foo() { //~ ERROR same body as `if` block + else if foo() { let _ = match 42 { 42 => 1, a if a > 0 => 2, @@ -336,7 +336,7 @@ fn if_same_then_else() -> Result<&'static str, ()> { let foo = "bar"; return Ok(&foo[0..]); } - else { //~ ERROR same body as `if` block + else { let foo = ""; return Ok(&foo[0..]); } diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index c6034a19906..5faf41b51e3 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -151,32 +151,6 @@ note: same as this 139 | | } | |_____^ -error: this `if` has identical blocks - --> $DIR/copies.rs:163:19 - | -163 | else if foo() { //~ ERROR same body as `if` block - | ___________________^ -164 | | let _ = match 42 { -165 | | 42 => 1, -166 | | a if a > 0 => 2, -... | -169 | | }; -170 | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:152:13 - | -152 | if true { - | _____________^ -153 | | let _ = match 42 { -154 | | 42 => 1, -155 | | a if a > 0 => 2, -... | -158 | | }; -159 | | } - | |_____^ - error: this `if` has identical blocks --> $DIR/copies.rs:175:10 | @@ -370,26 +344,6 @@ note: same as this 326 | | } | |_____^ -error: this `if` has identical blocks - --> $DIR/copies.rs:339:10 - | -339 | else { //~ ERROR same body as `if` block - | __________^ -340 | | let foo = ""; -341 | | return Ok(&foo[0..]); -342 | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:331:13 - | -331 | if true { - | _____________^ -332 | | let foo = ""; -333 | | return Ok(&foo[0..]); -334 | | } - | |_____^ - error: this `if` has the same condition as a previous if --> $DIR/copies.rs:353:13 | @@ -427,5 +381,5 @@ note: same as this 361 | if 2*a == 1 { | ^^^^^^^^ -error: aborting due to 22 previous errors +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From 85642ddd23e14c26f2f5064bf515e9d327f8222c Mon Sep 17 00:00:00 2001 From: TomasKralCZ Date: Sat, 10 Feb 2018 21:13:17 +0100 Subject: Implement redundant field names lint #2244 --- clippy_lints/src/lib.rs | 3 + clippy_lints/src/redundant_field_names.rs | 68 +++++++++++ tests/ui/no_effect.rs | 1 + tests/ui/no_effect.stderr | 188 +++++++++++++++--------------- tests/ui/redundant_field_names.rs | 28 +++++ tests/ui/redundant_field_names.stderr | 16 +++ 6 files changed, 210 insertions(+), 94 deletions(-) create mode 100644 clippy_lints/src/redundant_field_names.rs create mode 100644 tests/ui/redundant_field_names.rs create mode 100644 tests/ui/redundant_field_names.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bec46ba180c..1f78bee00e7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -152,6 +152,7 @@ pub mod ptr; pub mod question_mark; pub mod ranges; pub mod reference; +pub mod redundant_field_names; pub mod regex; pub mod replace_consts; pub mod returns; @@ -373,6 +374,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box types::UnitArg); reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); reg.register_late_lint_pass(box question_mark::QuestionMarkPass); + reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -591,6 +593,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ranges::ITERATOR_STEP_BY_ZERO, ranges::RANGE_MINUS_ONE, ranges::RANGE_ZIP_WITH_LEN, + redundant_field_names::REDUNDANT_FIELD_NAMES, reference::DEREF_ADDROF, regex::INVALID_REGEX, regex::REGEX_MACRO, diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs new file mode 100644 index 00000000000..d6164e21152 --- /dev/null +++ b/clippy_lints/src/redundant_field_names.rs @@ -0,0 +1,68 @@ +use rustc::lint::*; +use rustc::hir::*; +use utils::{span_lint_and_sugg}; + +/// **What it does:** Checks for redundnat field names where shorthands +/// can be used. +/// +/// **Why is this bad?** If the field and variable names are the same, +/// the field name is redundant. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let bar: u8 = 123; +/// +/// struct Foo { +/// bar: u8, +/// } +/// +/// let foo = Foo{ bar: bar } +/// ``` +declare_lint! { + pub REDUNDANT_FIELD_NAMES, + Warn, + "using same name for field and variable ,where shorthand can be used" +} + +pub struct RedundantFieldNames; + +impl LintPass for RedundantFieldNames { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_FIELD_NAMES) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprStruct(_, ref fields, _) = expr.node { + for field in fields { + let name = field.name.node; + if let ExprPath(ref qpath) = field.expr.node { + if let &QPath::Resolved(_, ref path) = qpath { + let segments = &path.segments; + + if segments.len() == 1 { + let expr_name = segments[0].name; + + if name == expr_name { + span_lint_and_sugg( + cx, + REDUNDANT_FIELD_NAMES, + path.span, + "redundant field names in struct initialization", + &format!( + "replace '{0}: {0}' with '{0}'", + name, + ), + "".to_string() + ); + } + } + } + } + } + } + } +} diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index a037ac3cf0e..a782063e391 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -5,6 +5,7 @@ #![allow(dead_code)] #![allow(path_statements)] #![allow(deref_addrof)] +#![allow(redundant_field_names)] #![feature(untagged_unions)] struct Unit; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 5bcab9f2b5e..64c0267a8b8 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,281 +1,281 @@ error: statement with no effect - --> $DIR/no_effect.rs:58:5 + --> $DIR/no_effect.rs:59:5 | -58 | 0; +59 | 0; | ^^ | = note: `-D no-effect` implied by `-D warnings` -error: statement with no effect - --> $DIR/no_effect.rs:59:5 - | -59 | s2; - | ^^^ - error: statement with no effect --> $DIR/no_effect.rs:60:5 | -60 | Unit; - | ^^^^^ +60 | s2; + | ^^^ error: statement with no effect --> $DIR/no_effect.rs:61:5 | -61 | Tuple(0); - | ^^^^^^^^^ +61 | Unit; + | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:62:5 | -62 | Struct { field: 0 }; - | ^^^^^^^^^^^^^^^^^^^^ +62 | Tuple(0); + | ^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:63:5 | -63 | Struct { ..s }; - | ^^^^^^^^^^^^^^^ +63 | Struct { field: 0 }; + | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:64:5 | -64 | Union { a: 0 }; +64 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:65:5 | -65 | Enum::Tuple(0); +65 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:66:5 | -66 | Enum::Struct { field: 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +66 | Enum::Tuple(0); + | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:67:5 | -67 | 5 + 6; - | ^^^^^^ +67 | Enum::Struct { field: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:68:5 | -68 | *&42; - | ^^^^^ +68 | 5 + 6; + | ^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:69:5 | -69 | &6; - | ^^^ +69 | *&42; + | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:70:5 | -70 | (5, 6, 7); - | ^^^^^^^^^^ +70 | &6; + | ^^^ error: statement with no effect --> $DIR/no_effect.rs:71:5 | -71 | box 42; - | ^^^^^^^ +71 | (5, 6, 7); + | ^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:72:5 | -72 | ..; - | ^^^ +72 | box 42; + | ^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:73:5 | -73 | 5..; - | ^^^^ +73 | ..; + | ^^^ error: statement with no effect --> $DIR/no_effect.rs:74:5 | -74 | ..5; +74 | 5..; | ^^^^ error: statement with no effect --> $DIR/no_effect.rs:75:5 | -75 | 5..6; - | ^^^^^ +75 | ..5; + | ^^^^ error: statement with no effect --> $DIR/no_effect.rs:76:5 | -76 | 5..=6; - | ^^^^^^ +76 | 5..6; + | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:77:5 | -77 | [42, 55]; - | ^^^^^^^^^ +77 | 5..=6; + | ^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:78:5 | -78 | [42, 55][1]; - | ^^^^^^^^^^^^ +78 | [42, 55]; + | ^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:79:5 | -79 | (42, 55).1; - | ^^^^^^^^^^^ +79 | [42, 55][1]; + | ^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:80:5 | -80 | [42; 55]; - | ^^^^^^^^^ +80 | (42, 55).1; + | ^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:81:5 | -81 | [42; 55][13]; +81 | [42; 55]; + | ^^^^^^^^^ + +error: statement with no effect + --> $DIR/no_effect.rs:82:5 + | +82 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:84:5 | -83 | || x += 5; +84 | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:86:5 | -85 | FooString { s: s }; +86 | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: statement can be reduced - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:97:5 | -96 | Tuple(get_number()); +97 | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | = note: `-D unnecessary-operation` implied by `-D warnings` -error: statement can be reduced - --> $DIR/no_effect.rs:97:5 - | -97 | Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - error: statement can be reduced --> $DIR/no_effect.rs:98:5 | -98 | Struct { ..get_struct() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` +98 | Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:99:5 | -99 | Enum::Tuple(get_number()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +99 | Struct { ..get_struct() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced --> $DIR/no_effect.rs:100:5 | -100 | Enum::Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +100 | Enum::Tuple(get_number()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:101:5 | -101 | 5 + get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` +101 | Enum::Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:102:5 | -102 | *&get_number(); - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +102 | 5 + get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced --> $DIR/no_effect.rs:103:5 | -103 | &get_number(); - | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` +103 | *&get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:104:5 | -104 | (5, 6, get_number()); - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` +104 | &get_number(); + | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:105:5 | -105 | box get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +105 | (5, 6, get_number()); + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced --> $DIR/no_effect.rs:106:5 | -106 | get_number()..; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +106 | box get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:107:5 | -107 | ..get_number(); +107 | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:108:5 | -108 | 5..get_number(); - | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` +108 | ..get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:109:5 | -109 | [42, get_number()]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` +109 | 5..get_number(); + | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced --> $DIR/no_effect.rs:110:5 | -110 | [42, 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` +110 | [42, get_number()]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced --> $DIR/no_effect.rs:111:5 | -111 | (42, get_number()).1; - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` +111 | [42, 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced --> $DIR/no_effect.rs:112:5 | -112 | [get_number(); 55]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +112 | (42, get_number()).1; + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced --> $DIR/no_effect.rs:113:5 | -113 | [42; 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` +113 | [get_number(); 55]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/no_effect.rs:114:5 | -114 | {get_number()}; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +114 | [42; 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced --> $DIR/no_effect.rs:115:5 | -115 | FooString { s: String::from("blah"), }; +115 | {get_number()}; + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/no_effect.rs:116:5 + | +116 | FooString { s: String::from("blah"), }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` error: aborting due to 46 previous errors diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs new file mode 100644 index 00000000000..d562fa44f83 --- /dev/null +++ b/tests/ui/redundant_field_names.rs @@ -0,0 +1,28 @@ +#![warn(redundant_field_names)] +#![allow(unused_variables)] + +mod foo { + pub const BAR: u8 = 0; +} + +struct Person { + gender: u8, + age: u8, + + buzz: u64, + foo: u8, +} + +fn main() { + let gender: u8 = 42; + let age = 0; + let fizz: u64 = 0; + + let me = Person { + gender: gender, + age: age, + + buzz: fizz, //should be ok + foo: foo::BAR, //should be ok + }; +} diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr new file mode 100644 index 00000000000..594282d2309 --- /dev/null +++ b/tests/ui/redundant_field_names.stderr @@ -0,0 +1,16 @@ +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:22:17 + | +22 | gender: gender, + | ^^^^^^ help: replace 'gender: gender' with 'gender' + | + = note: `-D redundant-field-names` implied by `-D warnings` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:23:14 + | +23 | age: age, + | ^^^ help: replace 'age: age' with 'age' + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 42120141bd8e9684143dd61e6d37da8541a94d0f Mon Sep 17 00:00:00 2001 From: TomasKralCZ Date: Sun, 11 Feb 2018 10:50:19 +0100 Subject: Suggestion fixed, simplified lint logic. --- clippy_lints/src/redundant_field_names.rs | 38 +++++++++++-------------------- src/driver.rs | 2 +- tests/ui/redundant_field_names.rs | 4 +++- tests/ui/redundant_field_names.stderr | 12 +++++----- 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index d6164e21152..e4d113bd3de 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,9 +1,9 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_sugg}; +use utils::{span_lint_and_sugg, match_var}; -/// **What it does:** Checks for redundnat field names where shorthands -/// can be used. +/// **What it does:** Checks for fields in struct literals where shorthands +/// could be used. /// /// **Why is this bad?** If the field and variable names are the same, /// the field name is redundant. @@ -23,7 +23,7 @@ use utils::{span_lint_and_sugg}; declare_lint! { pub REDUNDANT_FIELD_NAMES, Warn, - "using same name for field and variable ,where shorthand can be used" + "checks for fields in struct literals where shorthands could be used" } pub struct RedundantFieldNames; @@ -39,28 +39,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { if let ExprStruct(_, ref fields, _) = expr.node { for field in fields { let name = field.name.node; - if let ExprPath(ref qpath) = field.expr.node { - if let &QPath::Resolved(_, ref path) = qpath { - let segments = &path.segments; - if segments.len() == 1 { - let expr_name = segments[0].name; - - if name == expr_name { - span_lint_and_sugg( - cx, - REDUNDANT_FIELD_NAMES, - path.span, - "redundant field names in struct initialization", - &format!( - "replace '{0}: {0}' with '{0}'", - name, - ), - "".to_string() - ); - } - } - } + if match_var(&field.expr, name) && !field.is_shorthand { + span_lint_and_sugg ( + cx, + REDUNDANT_FIELD_NAMES, + field.span, + "redundant field names in struct initialization", + "replace it with", + name.to_string() + ); } } } diff --git a/src/driver.rs b/src/driver.rs index 7e0a82188f9..7b7167cef70 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -29,7 +29,7 @@ impl ClippyCompilerCalls { fn new(run_lints: bool) -> Self { Self { default: RustcDefaultCalls, - run_lints: run_lints, + run_lints, } } } diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index d562fa44f83..0eb9bef45b5 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -8,7 +8,7 @@ mod foo { struct Person { gender: u8, age: u8, - + name: u8, buzz: u64, foo: u8, } @@ -17,11 +17,13 @@ fn main() { let gender: u8 = 42; let age = 0; let fizz: u64 = 0; + let name: u8 = 0; let me = Person { gender: gender, age: age, + name, //should be ok buzz: fizz, //should be ok foo: foo::BAR, //should be ok }; diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 594282d2309..d6d752b93a3 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,16 +1,16 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:22:17 + --> $DIR/redundant_field_names.rs:23:9 | -22 | gender: gender, - | ^^^^^^ help: replace 'gender: gender' with 'gender' +23 | gender: gender, + | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:23:14 + --> $DIR/redundant_field_names.rs:24:9 | -23 | age: age, - | ^^^ help: replace 'age: age' with 'age' +24 | age: age, + | ^^^^^^^^ help: replace it with: `age` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From aa20277a171c108b69dc7241e40bac41c5e1c84b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 13 Feb 2018 15:40:17 +0100 Subject: Lint for suspicious implementations of arithmetic std::ops traits --- clippy_lints/src/lib.rs | 4 + clippy_lints/src/suspicious_trait_impl.rs | 192 +++++++++++++++++++++++++++++ tests/ui/suspicious_arithmetic_impl.rs | 52 ++++++++ tests/ui/suspicious_arithmetic_impl.stderr | 18 +++ 4 files changed, 266 insertions(+) create mode 100644 clippy_lints/src/suspicious_trait_impl.rs create mode 100644 tests/ui/suspicious_arithmetic_impl.rs create mode 100644 tests/ui/suspicious_arithmetic_impl.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bec46ba180c..cda5306dd2a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -158,6 +158,7 @@ pub mod returns; pub mod serde_api; pub mod shadow; pub mod strings; +pub mod suspicious_trait_impl; pub mod swap; pub mod temporary_assignment; pub mod transmute; @@ -373,6 +374,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box types::UnitArg); reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); reg.register_late_lint_pass(box question_mark::QuestionMarkPass); + reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -599,6 +601,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { returns::NEEDLESS_RETURN, serde_api::SERDE_API_MISUSE, strings::STRING_LIT_AS_BYTES, + suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, + suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs new file mode 100644 index 00000000000..682ab4d15ea --- /dev/null +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -0,0 +1,192 @@ +use rustc::lint::*; +use rustc::hir; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use syntax::ast; +use utils::{get_trait_def_id, span_lint}; + +/// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g. +/// subtracting elements in an Add impl. +/// +/// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl Add for Foo { +/// type Output = Foo; +/// +/// fn add(self, other: Foo) -> Foo { +/// Foo(self.0 - other.0) +/// } +/// } +/// ``` +declare_lint! { + pub SUSPICIOUS_ARITHMETIC_IMPL, + Warn, + "suspicious use of operators in impl of arithmetic trait" +} + +/// **What it does:** Lints for suspicious operations in impls of OpAssign, e.g. +/// subtracting elements in an AddAssign impl. +/// +/// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl AddAssign for Foo { +/// fn add_assign(&mut self, other: Foo) { +/// *self = *self - other; +/// } +/// } +/// ``` +declare_lint! { + pub SUSPICIOUS_OP_ASSIGN_IMPL, + Warn, + "suspicious use of operators in impl of OpAssign trait" +} + +#[derive(Copy, Clone)] +pub struct SuspiciousImpl; + +impl LintPass for SuspiciousImpl { + fn get_lints(&self) -> LintArray { + lint_array![SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + use rustc::hir::BinOp_::*; + if let hir::ExprBinary(binop, _, _) = expr.node { + // Check if the binary expression is part of another binary expression + // as a child node + let mut parent_expr = cx.tcx.hir.get_parent_node(expr.id); + while parent_expr != ast::CRATE_NODE_ID { + if_chain! { + if let hir::map::Node::NodeExpr(e) = cx.tcx.hir.get(parent_expr); + if let hir::ExprBinary(_, _, _) = e.node; + then { + return + } + } + + parent_expr = cx.tcx.hir.get_parent_node(parent_expr); + } + // as a parent node + let mut visitor = BinaryExprVisitor { + in_binary_expr: false, + }; + walk_expr(&mut visitor, expr); + + if visitor.in_binary_expr { + return; + } + + if let Some(impl_trait) = check_binop( + cx, + expr, + &binop.node, + &["Add", "Sub", "Mul", "Div"], + &[BiAdd, BiSub, BiMul, BiDiv], + ) { + span_lint( + cx, + SUSPICIOUS_ARITHMETIC_IMPL, + binop.span, + &format!( + r#"Suspicious use of binary operator in `{}` impl"#, + impl_trait + ), + ); + } + + if let Some(impl_trait) = check_binop( + cx, + expr, + &binop.node, + &[ + "AddAssign", + "SubAssign", + "MulAssign", + "DivAssign", + "BitAndAssign", + "BitOrAssign", + "BitXorAssign", + "RemAssign", + "ShlAssign", + "ShrAssign", + ], + &[ + BiAdd, BiSub, BiMul, BiDiv, BiBitAnd, BiBitOr, BiBitXor, BiRem, BiShl, BiShr + ], + ) { + span_lint( + cx, + SUSPICIOUS_OP_ASSIGN_IMPL, + binop.span, + &format!( + r#"Suspicious use of binary operator in `{}` impl"#, + impl_trait + ), + ); + } + } + } +} + +fn check_binop<'a>( + cx: &LateContext, + expr: &hir::Expr, + binop: &hir::BinOp_, + traits: &[&'a str], + expected_ops: &[hir::BinOp_], +) -> Option<&'a str> { + let mut trait_ids = vec![]; + let [krate, module] = ::utils::paths::OPS_MODULE; + + for t in traits { + let path = [krate, module, t]; + if let Some(trait_id) = get_trait_def_id(cx, &path) { + trait_ids.push(trait_id); + } else { + return None; + } + } + + // Get the actually implemented trait + let parent_fn = cx.tcx.hir.get_parent(expr.id); + let parent_impl = cx.tcx.hir.get_parent(parent_fn); + + if_chain! { + if parent_impl != ast::CRATE_NODE_ID; + if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); + if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; + if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.def.def_id()); + if *binop != expected_ops[idx]; + then{ + return Some(traits[idx]) + } + } + + None +} + +struct BinaryExprVisitor { + in_binary_expr: bool, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for BinaryExprVisitor { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if let hir::ExprBinary(_, _, _) = expr.node { + self.in_binary_expr = true; + } + + walk_expr(self, expr); + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs new file mode 100644 index 00000000000..097627e1d7c --- /dev/null +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -0,0 +1,52 @@ + + + +#![warn(suspicious_arithmetic_impl)] +use std::ops::{Add, AddAssign, Mul, Sub, Div}; + +#[derive(Copy, Clone)] +struct Foo(u32); + +impl Add for Foo { + type Output = Foo; + + fn add(self, other: Self) -> Self { + Foo(self.0 - other.0) + } +} + +impl AddAssign for Foo { + fn add_assign(&mut self, other: Foo) { + *self = *self - other; + } +} + +impl Mul for Foo { + type Output = Foo; + + fn mul(self, other: Foo) -> Foo { + Foo(self.0 * other.0 % 42) // OK: BiRem part of BiExpr as parent node + } +} + +impl Sub for Foo { + type Output = Foo; + + fn sub(self, other: Self) -> Self { + Foo(self.0 * other.0 - 42) // OK: BiMul part of BiExpr as child node + } +} + +impl Div for Foo { + type Output = Foo; + + fn div(self, other: Self) -> Self { + Foo(do_nothing(self.0 + other.0) / 42) // OK: BiAdd part of BiExpr as child node + } +} + +fn main() {} + +fn do_nothing(x: u32) -> u32 { + x +} diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr new file mode 100644 index 00000000000..9d5086e5497 --- /dev/null +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -0,0 +1,18 @@ +error: Suspicious use of binary operator in `Add` impl + --> $DIR/suspicious_arithmetic_impl.rs:14:20 + | +14 | Foo(self.0 - other.0) + | ^ + | + = note: `-D suspicious-arithmetic-impl` implied by `-D warnings` + +error: Suspicious use of binary operator in `AddAssign` impl + --> $DIR/suspicious_arithmetic_impl.rs:20:23 + | +20 | *self = *self - other; + | ^ + | + = note: `-D suspicious-op-assign-impl` implied by `-D warnings` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 0b4e0b82a9e8f771ea1aee768fbd5842ad006fab Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 13 Feb 2018 22:33:42 +0100 Subject: Explain how to execute a single UI test --- CONTRIBUTING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5dcec2167e..61e5cd67936 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,6 +74,18 @@ Therefore you can simply run `tests/ui/update-all-references.sh` (after running `cargo test`) and check whether the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +If you don't want to wait for all tests to finish, you can also execute a single test file by using `TESTNAME` to specify the test to run: + +```bash +TESTNAME=ui/empty_line_after_outer_attr cargo test --test compile-test +``` + +And you can also combine this with `CARGO_INCREMENTAL`: + +```bash +CARGO_INCREMENTAL=1 TESTNAME=ui/doc cargo test --test compile-test +``` + ### Testing manually Manually testing against an example file is useful if you have added some -- cgit 1.4.1-3-g733a5 From 339d2d5be0f924e4f5d093577f171158ef41be73 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 19 Feb 2018 16:30:19 +0100 Subject: Fix name of configuration parameters in documentation --- util/lintlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/lintlib.py b/util/lintlib.py index c46706352b7..190bce5e2f3 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -77,7 +77,7 @@ def parse_configs(path): confvars = re.findall(confvar_re, match.group(1)) for (lint, doc, name, default, ty) in confvars: - configs[lint.lower()] = Config(name, ty, doc, default) + configs[lint.lower()] = Config(name.replace("_", "-"), ty, doc, default) return configs -- cgit 1.4.1-3-g733a5 From 941e062fd41fd4eb73a1254d8da1acf9d751ce62 Mon Sep 17 00:00:00 2001 From: bootandy Date: Thu, 15 Feb 2018 09:56:12 -0500 Subject: Fix: point to correct problem part of code Fix span so it no longer contains the whole train-wreck of code and only points to the problem function (for the unwrap_or lint). https://github.com/rust-lang-nursery/rust-clippy/issues/2422 Update ui test methods - it had several cases where the error message span is now shorter --- clippy_lints/src/methods.rs | 9 ++++++--- tests/ui/methods.stderr | 36 ++++++++++++++++++------------------ tests/ui/unwrap_or.rs | 5 +++++ tests/ui/unwrap_or.stderr | 10 ++++++++++ tests/ui/unwrap_or.stdout | 0 5 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 tests/ui/unwrap_or.rs create mode 100644 tests/ui/unwrap_or.stderr create mode 100644 tests/ui/unwrap_or.stdout diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 04a5f157cf3..b65775ea7b3 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -913,6 +913,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: return; } + let start_point = self_expr.span.hi(); + let end_point = span.hi(); + let span_replace_word = Span::new(start_point, end_point, span.ctxt()); + // don't lint for constant values let owner_def = cx.tcx.hir.get_parent_did(arg.id); let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); @@ -939,14 +943,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), (false, true) => snippet(cx, fun_span, ".."), }; - span_lint_and_sugg( cx, OR_FUN_CALL, - span, + span_replace_word , &format!("use of `{}` followed by a function call", name), "try this", - format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg), + format!(".{}_{}({})", name, suffix, sugg), ); } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index ef52d85c31f..952a5ee124e 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -350,10 +350,10 @@ error: unnecessary structure name repetition | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:5 + --> $DIR/methods.rs:307:21 | 307 | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` + | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` @@ -364,22 +364,22 @@ error: use of `unwrap_or` followed by a call to `new` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:313:5 + --> $DIR/methods.rs:313:20 | 313 | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:5 + --> $DIR/methods.rs:316:13 | 316 | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` + | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:319:5 + --> $DIR/methods.rs:319:18 | 319 | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` --> $DIR/methods.rs:322:5 @@ -394,34 +394,34 @@ error: use of `unwrap_or` followed by a call to `default` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:328:5 + --> $DIR/methods.rs:328:13 | 328 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` + | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:333:5 + --> $DIR/methods.rs:333:20 | 333 | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:336:5 + --> $DIR/methods.rs:336:18 | 336 | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:339:5 + --> $DIR/methods.rs:339:20 | 339 | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:342:13 + --> $DIR/methods.rs:342:20 | 342 | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable --> $DIR/methods.rs:353:23 diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs new file mode 100644 index 00000000000..b95e58ee9a3 --- /dev/null +++ b/tests/ui/unwrap_or.rs @@ -0,0 +1,5 @@ +#![warn(clippy)] + +fn main() { + let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); +} diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr new file mode 100644 index 00000000000..e9bf57ba0ec --- /dev/null +++ b/tests/ui/unwrap_or.stderr @@ -0,0 +1,10 @@ +error: use of `unwrap_or` followed by a function call + --> $DIR/unwrap_or.rs:4:46 + | +4 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| "Fail".to_string())` + | + = note: `-D or-fun-call` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/unwrap_or.stdout b/tests/ui/unwrap_or.stdout new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From f3d1a0cec2222b6cad88ddaa3159235950c4dc7d Mon Sep 17 00:00:00 2001 From: bootandy Date: Tue, 20 Feb 2018 12:37:30 -0500 Subject: Add newlines in unwrap_or ui test --- tests/ui/unwrap_or.rs | 6 ++++++ tests/ui/unwrap_or.stderr | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index b95e58ee9a3..79e3900fef0 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -3,3 +3,9 @@ fn main() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); } + +fn new_lines() { + let s = Some(String::from("test string")) + .unwrap_or("Fail".to_string()) + .len(); +} diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index e9bf57ba0ec..ec5232d65a0 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -6,5 +6,13 @@ error: use of `unwrap_or` followed by a function call | = note: `-D or-fun-call` implied by `-D warnings` -error: aborting due to previous error +error: use of `unwrap_or` followed by a function call + --> $DIR/unwrap_or.rs:8:46 + | +8 | let s = Some(String::from("test string")) + | ______________________________________________^ +9 | | .unwrap_or("Fail".to_string()) + | |______________________________________^ help: try this: `.unwrap_or_else(|| "Fail".to_string())` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From c708154c168dd198d0127f1a891dcbdba1796e2c Mon Sep 17 00:00:00 2001 From: bootandy Date: Tue, 20 Feb 2018 12:38:20 -0500 Subject: Simplify creation of span_replace_word Part of unwrap_or test --- clippy_lints/src/methods.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index b65775ea7b3..9d829007bca 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -913,9 +913,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: return; } - let start_point = self_expr.span.hi(); - let end_point = span.hi(); - let span_replace_word = Span::new(start_point, end_point, span.ctxt()); + let span_replace_word = self_expr.span.with_lo(span.hi()); // don't lint for constant values let owner_def = cx.tcx.hir.get_parent_did(arg.id); @@ -946,7 +944,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: span_lint_and_sugg( cx, OR_FUN_CALL, - span_replace_word , + span_replace_word, &format!("use of `{}` followed by a function call", name), "try this", format!(".{}_{}({})", name, suffix, sugg), -- cgit 1.4.1-3-g733a5 From a7c97256dc5548576bbad7200cfb5ab4d4dc5ed3 Mon Sep 17 00:00:00 2001 From: bootandy Date: Wed, 21 Feb 2018 11:25:18 -0500 Subject: Stop unwanted newlines being applied on unwrap_or --- clippy_lints/src/methods.rs | 16 ++++++++-------- tests/ui/methods.stderr | 36 ++++++++++++++++++------------------ tests/ui/unwrap_or.stderr | 12 +++++------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9d829007bca..1c02f73cc1a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -691,7 +691,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match expr.node { - hir::ExprMethodCall(ref method_call, _, ref args) => { + hir::ExprMethodCall(ref method_call, ref method_span, ref args) => { // Chain calls // GET_UNWRAP needs to be checked before general `UNWRAP` lints if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) { @@ -744,7 +744,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_unnecessary_fold(cx, expr, arglists[0]); } - lint_or_fun_call(cx, expr, &method_call.name.as_str(), args); + lint_or_fun_call(cx, expr, method_span, &method_call.name.as_str(), args); let self_ty = cx.tables.expr_ty_adjusted(&args[0]); if args.len() == 1 && method_call.name == "clone" { @@ -845,7 +845,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } /// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir::Expr]) { +fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: &Span, name: &str, args: &[hir::Expr]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. fn check_unwrap_or_default( cx: &LateContext, @@ -894,6 +894,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: fn check_general_case( cx: &LateContext, name: &str, + method_span: &Span, fun_span: Span, self_expr: &hir::Expr, arg: &hir::Expr, @@ -913,8 +914,6 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: return; } - let span_replace_word = self_expr.span.with_lo(span.hi()); - // don't lint for constant values let owner_def = cx.tcx.hir.get_parent_did(arg.id); let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); @@ -941,13 +940,14 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), (false, true) => snippet(cx, fun_span, ".."), }; + let span_replace_word = method_span.with_hi(span.hi()); span_lint_and_sugg( cx, OR_FUN_CALL, span_replace_word, &format!("use of `{}` followed by a function call", name), "try this", - format!(".{}_{}({})", name, suffix, sugg), + format!("{}_{}({})", name, suffix, sugg), ); } @@ -956,11 +956,11 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: hir::ExprCall(ref fun, ref or_args) => { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { - check_general_case(cx, name, fun.span, &args[0], &args[1], or_has_args, expr.span); + check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span); } }, hir::ExprMethodCall(_, span, ref or_args) => { - check_general_case(cx, name, span, &args[0], &args[1], !or_args.is_empty(), expr.span) + check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span) }, _ => {}, } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 952a5ee124e..42cf3d3cbc5 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -350,10 +350,10 @@ error: unnecessary structure name repetition | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:21 + --> $DIR/methods.rs:307:22 | 307 | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(make)` + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` @@ -364,22 +364,22 @@ error: use of `unwrap_or` followed by a call to `new` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:313:20 + --> $DIR/methods.rs:313:21 | 313 | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:13 + --> $DIR/methods.rs:316:14 | 316 | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|_| make())` + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:319:18 + --> $DIR/methods.rs:319:19 | 319 | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|_| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` --> $DIR/methods.rs:322:5 @@ -394,34 +394,34 @@ error: use of `unwrap_or` followed by a call to `default` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:328:13 + --> $DIR/methods.rs:328:14 | 328 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:333:20 + --> $DIR/methods.rs:333:21 | 333 | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(Foo::new)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:336:18 + --> $DIR/methods.rs:336:19 | 336 | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.or_insert_with(String::new)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:339:20 + --> $DIR/methods.rs:339:21 | 339 | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.or_insert_with(String::new)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:342:20 + --> $DIR/methods.rs:342:21 | 342 | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| "".to_owned())` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable --> $DIR/methods.rs:353:23 diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index ec5232d65a0..e4704dd0e43 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,18 +1,16 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:4:46 + --> $DIR/unwrap_or.rs:4:47 | 4 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `.unwrap_or_else(|| "Fail".to_string())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:8:46 + --> $DIR/unwrap_or.rs:9:10 | -8 | let s = Some(String::from("test string")) - | ______________________________________________^ -9 | | .unwrap_or("Fail".to_string()) - | |______________________________________^ help: try this: `.unwrap_or_else(|| "Fail".to_string())` +9 | .unwrap_or("Fail".to_string()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From d3d3d7d7be481086063ee2174776e93c6e2d6c08 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 21 Feb 2018 21:11:38 +0100 Subject: Lint multiline attributes properly This makes it so that the `empty_line_after_outer_attribute` lint only checks for newlines between the end of the attribute and the beginning of the following item. We need to check for the empty line count being bigger than 2 because now the snippet of valid code contains only `\n` and splitting it produces `["", ""]` Invalid code will contain more than 2 empty strings. --- clippy_lints/src/attrs.rs | 12 ++++++------ tests/ui/empty_line_after_outer_attribute.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 50aaa66aada..417ddbe8c12 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -271,18 +271,18 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { return; } - let attr_to_item_span = Span::new(attr.span.lo(), span.lo(), span.ctxt()); + let begin_of_attr_to_item = Span::new(attr.span.lo(), span.lo(), span.ctxt()); + let end_of_attr_to_item = Span::new(attr.span.hi(), span.lo(), span.ctxt()); - if let Some(snippet) = snippet_opt(cx, attr_to_item_span) { + if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { let lines = snippet.split('\n').collect::>(); - if lines.iter().filter(|l| l.trim().is_empty()).count() > 1 { + if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { span_lint( cx, EMPTY_LINE_AFTER_OUTER_ATTR, - attr_to_item_span, + begin_of_attr_to_item, "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?" - ); - + ); } } } diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index ef78ca530c1..beaa98953da 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -58,4 +58,13 @@ mod foo { #[allow(missing_docs)] fn three_attributes() { assert!(true) } +// This should not produce a warning +#[doc = " +Returns the escaped value of the textual representation of + +"] +pub fn function() -> bool { + true +} + fn main() { } -- cgit 1.4.1-3-g733a5 From aef07e33929b235c63178d541ac0e1b4823ee8f3 Mon Sep 17 00:00:00 2001 From: bootandy Date: Thu, 22 Feb 2018 10:11:20 -0500 Subject: Do not pass Span by reference --- clippy_lints/src/methods.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 1c02f73cc1a..a7bdd10ed66 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -744,7 +744,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_unnecessary_fold(cx, expr, arglists[0]); } - lint_or_fun_call(cx, expr, method_span, &method_call.name.as_str(), args); + lint_or_fun_call(cx, expr, *method_span, &method_call.name.as_str(), args); let self_ty = cx.tables.expr_ty_adjusted(&args[0]); if args.len() == 1 && method_call.name == "clone" { @@ -845,7 +845,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } /// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: &Span, name: &str, args: &[hir::Expr]) { +fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. fn check_unwrap_or_default( cx: &LateContext, @@ -894,7 +894,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: &Span, name fn check_general_case( cx: &LateContext, name: &str, - method_span: &Span, + method_span: Span, fun_span: Span, self_expr: &hir::Expr, arg: &hir::Expr, -- cgit 1.4.1-3-g733a5 From f69fcc08d2a3fdd5a1d06219c839f562ba8f2003 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 23 Feb 2018 08:59:42 -0800 Subject: Update Rust to 063deba92e --- clippy_lints/src/enum_variants.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index b3dd275f668..b72949a7381 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -260,7 +260,7 @@ impl EarlyLintPass for EnumVariantNames { ); } } - if item.vis == Visibility::Public { + if item.vis.node == VisibilityKind::Public { let matching = partial_match(mod_camel, &item_camel); let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); @@ -284,8 +284,8 @@ impl EarlyLintPass for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.node { - let lint = match item.vis { - Visibility::Public => PUB_ENUM_VARIANT_NAMES, + let lint = match item.vis.node { + VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES, _ => ENUM_VARIANT_NAMES, }; check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint); -- cgit 1.4.1-3-g733a5 From 8494f57c82f6a1ff79a1065c8025f7e68dbe26de Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Sat, 24 Feb 2018 02:02:48 +0100 Subject: Fix author lint The author lint was generating invalid code as shown on issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2442 I've changed the generated code to properly track cast expressions. Unfortunatelly, I've had to rewrite the `visit_decl` method, to avoid that last if of the chain will be added. After looking at the code, this last line was being added because of the `let x: char` part, but not because of the `0x45df as char` expression. It seems that let statements should not generate code on the author lint, but I'm not sure that this is true or if I'm breaking something on other code generation parts. Finally, I've added a test for the author lint, but I'm not sure that this needs to be added to the testsuite. --- clippy_lints/src/utils/author.rs | 30 ++++++++++++++++++++++++++---- tests/ui/author.rs | 7 +++++++ tests/ui/author.stdout | 10 ++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/ui/author.rs create mode 100644 tests/ui/author.stdout diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index c824c8906a7..d7d29ceda6e 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -5,8 +5,9 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::{Expr, Expr_, QPath}; -use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc::hir::{Expr, Expr_, QPath, Ty_}; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor, walk_decl}; +use rustc::hir::Decl; use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::Span; use std::collections::HashMap; @@ -79,6 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } prelude(); + PrintVisitor::new("item").visit_impl_item(item); done(); } @@ -182,6 +184,18 @@ struct PrintVisitor { } impl<'tcx> Visitor<'tcx> for PrintVisitor { + fn visit_decl(&mut self, d: &'tcx Decl) { + match d.node { + hir::DeclLocal(ref local) => { + self.visit_pat(&local.pat); + if let Some(ref e) = local.init { + self.visit_expr(e); + } + }, + _ => walk_decl(self, d) + } + } + fn visit_expr(&mut self, expr: &Expr) { print!(" if let Expr_::Expr"); let current = format!("{}.node", self.current); @@ -260,9 +274,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, } }, - Expr_::ExprCast(ref expr, ref _ty) => { + Expr_::ExprCast(ref expr, ref ty) => { let cast_pat = self.next("expr"); - println!("Cast(ref {}, _) = {};", cast_pat, current); + let cast_ty = self.next("cast_ty"); + let qp_label = self.next("qp"); + + println!("Cast(ref {}, ref {}) = {};", cast_pat, cast_ty, current); + if let Ty_::TyPath(ref qp) = ty.node { + println!(" if let Ty_::TyPath(ref {}) = {}.node;", qp_label, cast_ty); + self.current = qp_label; + self.visit_qpath(&qp, ty.id, ty.span); + } self.current = cast_pat; self.visit_expr(expr); }, diff --git a/tests/ui/author.rs b/tests/ui/author.rs new file mode 100644 index 00000000000..3a819872bc5 --- /dev/null +++ b/tests/ui/author.rs @@ -0,0 +1,7 @@ +#![feature(plugin, custom_attribute)] + +fn main() { + + #[clippy(author)] + let x: char = 0x45 as char; +} diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout new file mode 100644 index 00000000000..0efb3e8b272 --- /dev/null +++ b/tests/ui/author.stdout @@ -0,0 +1,10 @@ +if_chain! { + if let Expr_::ExprCast(ref expr, ref cast_ty) = stmt.node; + if let Ty_::TyPath(ref qp) = cast_ty.node; + if match_qpath(qp, &["char"]); + if let Expr_::ExprLit(ref lit) = expr.node; + if let LitKind::Int(69, _) = lit.node; + then { + // report your lint here + } +} -- cgit 1.4.1-3-g733a5 From 3ac84b2542ec1c4caeab54239c67202113c82ea0 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Sat, 24 Feb 2018 19:34:51 +0100 Subject: Remove explicit visit_qpath method Instead of replacing the default behaviour of the visit_qpath method, I've moved the printing code to private method of PrintVisitor (print_qpath). --- clippy_lints/src/utils/author.rs | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index d7d29ceda6e..beae98f81f6 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -6,10 +6,8 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::{Expr, Expr_, QPath, Ty_}; -use rustc::hir::intravisit::{NestedVisitorMap, Visitor, walk_decl}; -use rustc::hir::Decl; -use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID}; -use syntax::codemap::Span; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use syntax::ast::{self, Attribute, LitKind, DUMMY_NODE_ID}; use std::collections::HashMap; /// **What it does:** Generates clippy code that detects the offending pattern @@ -80,7 +78,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } prelude(); - PrintVisitor::new("item").visit_impl_item(item); done(); } @@ -173,6 +170,12 @@ impl PrintVisitor { }, } } + + fn print_qpath(&mut self, path: &QPath) { + print!(" if match_qpath({}, &[", self.current); + print_path(path, &mut true); + println!("]);"); + } } struct PrintVisitor { @@ -184,18 +187,6 @@ struct PrintVisitor { } impl<'tcx> Visitor<'tcx> for PrintVisitor { - fn visit_decl(&mut self, d: &'tcx Decl) { - match d.node { - hir::DeclLocal(ref local) => { - self.visit_pat(&local.pat); - if let Some(ref e) = local.init { - self.visit_expr(e); - } - }, - _ => walk_decl(self, d) - } - } - fn visit_expr(&mut self, expr: &Expr) { print!(" if let Expr_::Expr"); let current = format!("{}.node", self.current); @@ -283,7 +274,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { if let Ty_::TyPath(ref qp) = ty.node { println!(" if let Ty_::TyPath(ref {}) = {}.node;", qp_label, cast_ty); self.current = qp_label; - self.visit_qpath(&qp, ty.id, ty.span); + self.print_qpath(&qp); } self.current = cast_pat; self.visit_expr(expr); @@ -398,7 +389,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let path_pat = self.next("path"); println!("Path(ref {}) = {};", path_pat, current); self.current = path_pat; - self.visit_qpath(path, expr.id, expr.span); + self.print_qpath(path); }, Expr_::ExprAddrOf(mutability, ref inner) => { let inner_pat = self.next("inner"); @@ -453,7 +444,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Struct(ref {}, ref {}, None) = {};", path_pat, fields_pat, current); } self.current = path_pat; - self.visit_qpath(path, expr.id, expr.span); + self.print_qpath(path); println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, @@ -468,11 +459,6 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } - fn visit_qpath(&mut self, path: &QPath, _: NodeId, _: Span) { - print!(" if match_qpath({}, &[", self.current); - print_path(path, &mut true); - println!("]);"); - } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } -- cgit 1.4.1-3-g733a5 From 5c1be4a4ba6c56394545a95e92e4ad6f62c3605f Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Sun, 25 Feb 2018 18:25:31 +0100 Subject: lint: immutable only vars in while condition --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/loops.rs | 69 ++++++++++++++++++++++++++++++++- tests/ui/infinite_loop.rs | 89 +++++++++++++++++++++++++++++++++++++++++++ tests/ui/infinite_loop.stderr | 22 +++++++++++ tests/ui/never_loop.rs | 2 +- 5 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 tests/ui/infinite_loop.rs create mode 100644 tests/ui/infinite_loop.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7f3b176b889..fbfa598e77d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -521,6 +521,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::UNUSED_COLLECT, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, + loops::WHILE_IMMUTABLE_CONDITION, map_clone::MAP_CLONE, matches::MATCH_AS_REF, matches::MATCH_BOOL, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ca1d987dbf2..d70d32f2306 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -343,6 +343,27 @@ declare_lint! { "for loop over a range where one of the bounds is a mutable variable" } +/// **What it does:** Checks whether variables used within while loop condition +/// can be (and are) mutated in the body. +/// +/// **Why is this bad?** If the condition is unchanged, entering the body of the loop +/// will lead to an infinite loop. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let i = 0; +/// while i > 10 { +/// println!("let me loop forever!"); +/// } +/// ``` +declare_lint! { + pub WHILE_IMMUTABLE_CONDITION, + Warn, + "variables used within while expression are not mutated in the body" +} + #[derive(Copy, Clone)] pub struct Pass; @@ -364,7 +385,8 @@ impl LintPass for Pass { WHILE_LET_ON_ITERATOR, FOR_KV_MAP, NEVER_LOOP, - MUT_RANGE_BOUND + MUT_RANGE_BOUND, + WHILE_IMMUTABLE_CONDITION, ) } } @@ -469,6 +491,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } + + // check for while loops which conditions never change + if let ExprWhile(ref cond, ref block, _) = expr.node { + check_infinite_loop(cx, cond, block, expr); + } } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { @@ -662,6 +689,46 @@ fn check_for_loop<'a, 'tcx>( detect_manual_memcpy(cx, pat, arg, body, expr); } +fn search_mutable_vars<'a, 'tcx> ( + cx: &LateContext<'a, 'tcx>, + ex: &'tcx Expr, + acc: &mut Vec, +) -> bool { + match ex.node { + ExprBinary(_, ref a, ref b) => + search_mutable_vars(cx, a, acc) && search_mutable_vars(cx, b, acc), + + ExprUnary(_, ref a) => search_mutable_vars(cx, a, acc), + ExprPath(_) => { + if let Some(node_id) = check_for_mutability(cx, &ex) { + acc.push(node_id); + } + true + } + ExprLit(_) => true, + + // Skip if any method or function call is encountered + _ => false + } +} + +fn check_infinite_loop<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + cond: &'tcx Expr, + _block: &'tcx Block, + _expr: &'tcx Expr, +) { + let mut mutable_vars = Vec::new(); + if search_mutable_vars(cx, cond, &mut mutable_vars) && mutable_vars.len() == 0 { + span_lint( + cx, + WHILE_IMMUTABLE_CONDITION, + cond.span, + "all variables in condition are immutable. This might lead to infinite loops." + ) + } +} + fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool { if_chain! { if let ExprPath(ref qpath) = expr.node; diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs new file mode 100644 index 00000000000..e6078a8ef98 --- /dev/null +++ b/tests/ui/infinite_loop.rs @@ -0,0 +1,89 @@ +fn fn_val(i: i32) -> i32 { unimplemented!() } +fn fn_constref(i: &i32) -> i32 { unimplemented!() } +fn fn_mutref(i: &mut i32) { unimplemented!() } +fn foo() -> i32 { unimplemented!() } + +fn immutable_condition() { + // Should warn when all vars mentionned are immutable + let y = 0; + while y < 10 { + println!("KO - y is immutable"); + } + + let x = 0; + while y < 10 && x < 3 { + println!("KO - x and y immutable"); + } + + let cond = false; + while !cond { + println!("KO - cond immutable"); + } + + let mut i = 0; + while y < 10 && i < 3 { + i += 1; + println!("OK - i is mutable"); + } + + let mut mut_cond = false; + while !mut_cond || cond { + mut_cond = true; + println!("OK - mut_cond is mutable"); + } + + while foo() < x { + println!("OK - Fn call results may vary"); + } + +} + +fn unused_var() { + // Should warn when a (mutable) var is not used in while body + let (mut i, mut j) = (0, 0); + + while i < 3 { + j = 3; + println!("KO - i not mentionned"); + } + + while i < 3 && j > 0 { + println!("KO - i and j not mentionned"); + } + + while i < 3 { + let mut i = 5; + fn_mutref(&mut i); + println!("KO - shadowed"); + } + + while i < 3 && j > 0 { + i = 5; + println!("OK - i in cond and mentionned"); + } +} + +fn used_immutable() { + let mut i = 0; + + while i < 3 { + fn_constref(&i); + println!("KO - const reference"); + } + + while i < 3 { + fn_val(i); + println!("KO - passed by value"); + } + + while i < 3 { + fn_mutref(&mut i); + println!("OK - passed by mutable reference"); + } +} + +fn main() { + immutable_condition(); + unused_var(); + used_immutable(); +} diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr new file mode 100644 index 00000000000..ddc556f426c --- /dev/null +++ b/tests/ui/infinite_loop.stderr @@ -0,0 +1,22 @@ +error: all variables in condition are immutable. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:9:11 + | +9 | while y < 10 { + | ^^^^^^ + | + = note: `-D while-immutable-condition` implied by `-D warnings` + +error: all variables in condition are immutable. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:14:11 + | +14 | while y < 10 && x < 3 { + | ^^^^^^^^^^^^^^^ + +error: all variables in condition are immutable. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:19:11 + | +19 | while !cond { + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 2712db2bd31..20500126662 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,6 +1,6 @@ -#![allow(single_match, unused_assignments, unused_variables)] +#![allow(single_match, unused_assignments, unused_variables, while_immutable_condition)] fn test1() { let mut x = 0; -- cgit 1.4.1-3-g733a5 From 04118431702ec57575bc9948361f4b50a315c162 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 26 Feb 2018 18:01:10 +0900 Subject: Fix for rustc 1.26.0-nightly (322d7f7b9 2018-02-25) --- clippy_lints/src/derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d327d0570f1..8702ec1e716 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -149,7 +149,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref } } for subst in substs { - if let Some(subst) = subst.as_type() { + if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { if let ty::TyParam(_) = subst.sty { return; } -- cgit 1.4.1-3-g733a5 From 167d978372c21036ae0485ede7ba49436f78b294 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 26 Feb 2018 11:57:14 -0800 Subject: Rustup to rustc 1.26.0-nightly (322d7f7b9 2018-02-25) --- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/lib.rs | 1 + clippy_lints/src/misc.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d327d0570f1..8702ec1e716 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -149,7 +149,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref } } for subst in substs { - if let Some(subst) = subst.as_type() { + if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { if let ty::TyParam(_) = subst.sty { return; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7f3b176b889..9142ebdbf21 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -377,6 +377,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); + reg.register_late_lint_pass(box misc::BareTraitLate); reg.register_lint_group("clippy_restrictions", vec![ diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 04cc488d562..97bfd3d0c95 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -636,3 +636,61 @@ fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { } } } + +declare_lint! { + pub BARE_TRAIT_OBJECT, + Warn, + "suggest using `dyn Trait` for trait objects" +} + +#[derive(Copy, Clone)] +pub struct BareTraitLate; + +impl LintPass for BareTraitLate { + fn get_lints(&self) -> LintArray { + lint_array!(BARE_TRAIT_OBJECT) + } +} + +use rustc::hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; + +struct TraitTyVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx> +} + +impl<'a, 'tcx> Visitor<'tcx> for TraitTyVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: &'tcx Ty) { + println!("{:?}", ty.node); + if let TyPath(ref qpath) = ty.node { + println!("{:?}", qpath); + let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + let def = self.cx.tables.qpath_def(qpath, hir_id); + let t = self.cx.tcx.type_of(def.def_id()); + println!("{:?}", t); + if let ty::TyDynamic(..) = t.sty { + let mut err = self.cx.struct_span_lint(BARE_TRAIT_OBJECT, ty.span, + "Trait objects without an explicit `dyn` are deprecated"); + let sugg = match self.cx.tcx.sess.codemap().span_to_snippet(ty.span) { + Ok(s) => format!("dyn {}", s), + Err(_) => format!("dyn ") + }; + err.span_suggestion(ty.span, "use `dyn`", sugg); + err.emit(); + } + } + walk_ty(self, ty) + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BareTraitLate { + fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty) { + if !cx.sess().features.borrow().dyn_trait { + return; + } + println!("toplevel {:?}", ty); + TraitTyVisitor { cx }.visit_ty(ty) + } +} -- cgit 1.4.1-3-g733a5 From a512fb265b4799c83e2de7a69cf6ac5d65cb268d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 26 Feb 2018 12:31:29 -0800 Subject: oops --- clippy_lints/src/lib.rs | 1 - clippy_lints/src/misc.rs | 58 ------------------------------------------------ 2 files changed, 59 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9142ebdbf21..7f3b176b889 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -377,7 +377,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); - reg.register_late_lint_pass(box misc::BareTraitLate); reg.register_lint_group("clippy_restrictions", vec![ diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 97bfd3d0c95..04cc488d562 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -636,61 +636,3 @@ fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { } } } - -declare_lint! { - pub BARE_TRAIT_OBJECT, - Warn, - "suggest using `dyn Trait` for trait objects" -} - -#[derive(Copy, Clone)] -pub struct BareTraitLate; - -impl LintPass for BareTraitLate { - fn get_lints(&self) -> LintArray { - lint_array!(BARE_TRAIT_OBJECT) - } -} - -use rustc::hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; - -struct TraitTyVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx> -} - -impl<'a, 'tcx> Visitor<'tcx> for TraitTyVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &'tcx Ty) { - println!("{:?}", ty.node); - if let TyPath(ref qpath) = ty.node { - println!("{:?}", qpath); - let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); - let def = self.cx.tables.qpath_def(qpath, hir_id); - let t = self.cx.tcx.type_of(def.def_id()); - println!("{:?}", t); - if let ty::TyDynamic(..) = t.sty { - let mut err = self.cx.struct_span_lint(BARE_TRAIT_OBJECT, ty.span, - "Trait objects without an explicit `dyn` are deprecated"); - let sugg = match self.cx.tcx.sess.codemap().span_to_snippet(ty.span) { - Ok(s) => format!("dyn {}", s), - Err(_) => format!("dyn ") - }; - err.span_suggestion(ty.span, "use `dyn`", sugg); - err.emit(); - } - } - walk_ty(self, ty) - } - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BareTraitLate { - fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty) { - if !cx.sess().features.borrow().dyn_trait { - return; - } - println!("toplevel {:?}", ty); - TraitTyVisitor { cx }.visit_ty(ty) - } -} -- cgit 1.4.1-3-g733a5 From 539b4b61ec8bc63ea65e31de1435afe8ce78e9e0 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 26 Feb 2018 12:32:18 -0800 Subject: Bump to 0.0.187 --- CHANGELOG.md | 7 +++++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d953f0f22cc..1dd1fdbf09a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.187 +* Rustup to *rustc 1.26.0-nightly (322d7f7b9 2018-02-25)* +* New lints: [`redundant_field_names`], [`suspicious_arithmetic_impl`], [`suspicious_op_assign_impl`] + ## 0.0.186 * Rustup to *rustc 1.25.0-nightly (0c6091fbd 2018-02-04)* * Various false positive fixes @@ -705,6 +709,7 @@ All notable changes to this project will be documented in this file. [`range_zip_with_len`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_zip_with_len [`redundant_closure`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call +[`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts @@ -730,8 +735,10 @@ All notable changes to this project will be documented in this file. [`string_lit_as_bytes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_lit_as_bytes [`string_to_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_to_string [`stutter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#stutter +[`suspicious_arithmetic_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl [`suspicious_assignment_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_else_formatting +[`suspicious_op_assign_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl [`temporary_assignment`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`too_many_arguments`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#too_many_arguments diff --git a/Cargo.toml b/Cargo.toml index 0ba3e5e6c6a..d8ab9491020 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.186" +version = "0.0.187" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.186", path = "clippy_lints" } +clippy_lints = { version = "0.0.187", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 9249e871204..cee48c1514d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.186" +version = "0.0.187" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7f3b176b889..ce952690811 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -151,8 +151,8 @@ pub mod print; pub mod ptr; pub mod question_mark; pub mod ranges; -pub mod reference; pub mod redundant_field_names; +pub mod reference; pub mod regex; pub mod replace_consts; pub mod returns; @@ -385,9 +385,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, methods::CLONE_ON_REF_PTR, misc::FLOAT_CMP_CONST, - literal_representation::DECIMAL_LITERAL_REPRESENTATION, ]); reg.register_lint_group("clippy_pedantic", vec![ -- cgit 1.4.1-3-g733a5 From 9a002e52e55211f2753ef5e217d1be042dd4fdf9 Mon Sep 17 00:00:00 2001 From: bootandy Date: Wed, 28 Feb 2018 10:24:10 -0500 Subject: Lint passing Cow by reference Add lint for reference to Cow to the same place in the code where lint for reference to String lives. https://github.com/rust-lang-nursery/rust-clippy/issues/2405 --- clippy_lints/src/ptr.rs | 15 +++++++++++++++ tests/ui/needless_borrow.rs | 11 ++++++++++- tests/ui/needless_borrow.stderr | 12 +++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a6a3690202f..44ea35a9fb8 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -213,6 +213,21 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< }, ); } + } else if match_type(cx, ty, &paths::COW) { + let as_str = format!("{}", snippet_opt(cx, arg.span).unwrap()); + let mut cc = as_str.chars(); + cc.next(); + let replacement: String = cc.collect(); + + span_lint_and_then( + cx, + PTR_ARG, + arg.span, + "using a reference to `Cow` is not recommended.", + |db| { + db.span_suggestion(arg.span, "change this to", replacement); + }, + ); } } } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 78c1a125c94..088d33b875f 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,4 +1,4 @@ - +use std::borrow::Cow; fn x(y: &i32) -> i32 { @@ -51,3 +51,12 @@ fn issue_1432() { let _ = v.iter().filter(|&a| a.is_empty()); } + +#[allow(dead_code)] +fn test_cow_with_ref(c: &Cow<[i32]>) { +} + +#[allow(dead_code)] +fn test_cow(c: Cow<[i32]>) { + let _c = c; +} diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index fde38508b32..6cdcbb275cd 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -38,5 +38,15 @@ error: this pattern creates a reference to a reference 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` -error: aborting due to 6 previous errors +a> $DIR/needless_borrow.rs:56:25: 56:36 +b> $DIR/needless_borrow.rs:56:25: 56:36 +error: using a reference to `Cow` is not recommended. + --> $DIR/needless_borrow.rs:56:25 + | +56 | fn test_cow_with_ref(c: &Cow<[i32]>) { + | ^^^^^^^^^^^ help: change this to: `Cow<[i32]>` + | + = note: `-D ptr-arg` implied by `-D warnings` + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 42000c6cf9e229092076501aacd868d18a707e93 Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Thu, 1 Mar 2018 15:15:41 +0000 Subject: Fix #2494 add suggestion for unreadable_literal Add `rustc --explain E0308` line to relevant tests --- clippy_lints/src/literal_representation.rs | 22 +++++++++++++--------- tests/ui/builtin-type-shadow.stderr | 1 + tests/ui/conf_bad_arg.stderr | 1 + tests/ui/conf_bad_toml.stderr | 1 + tests/ui/conf_bad_type.stderr | 1 + tests/ui/conf_french_blacklisted_name.stderr | 1 + tests/ui/conf_path_non_string.stderr | 1 + tests/ui/conf_unknown_key.stderr | 1 + tests/ui/decimal_literal_representation.stderr | 19 +++++-------------- tests/ui/inconsistent_digit_grouping.stderr | 19 +++++-------------- tests/ui/large_digit_groups.stderr | 23 ++++++----------------- tests/ui/unreadable_literal.stderr | 15 ++++----------- 12 files changed, 40 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9633ac00b15..1b93f6bf3f4 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax_pos; -use utils::{in_external_macro, snippet_opt, span_help_and_lint}; +use utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -222,33 +222,37 @@ enum WarningType { impl WarningType { pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { match *self { - WarningType::UnreadableLiteral => span_help_and_lint( + WarningType::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, *span, "long literal lacking separators", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::LargeDigitGroups => span_help_and_lint( + WarningType::LargeDigitGroups => span_lint_and_sugg( cx, LARGE_DIGIT_GROUPS, *span, "digit groups should be smaller", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::InconsistentDigitGrouping => span_help_and_lint( + WarningType::InconsistentDigitGrouping => span_lint_and_sugg( cx, INCONSISTENT_DIGIT_GROUPING, *span, "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::DecimalRepresentation => span_help_and_lint( + WarningType::DecimalRepresentation => span_lint_and_sugg( cx, DECIMAL_LITERAL_REPRESENTATION, *span, "integer literal has a better hexadecimal representation", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), }; } diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index eb4c73b65c6..85595fb0233 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -19,3 +19,4 @@ error[E0308]: mismatched types error: aborting due to 2 previous errors +If you want more information on this error, try using "rustc --explain E0308" diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index bc44cebdbbb..30a87e23275 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index d4236926522..f01b5605a51 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 440437d140e..ea9cf0acdd8 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index 19c8e5c9777..d09ae43301c 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index 7a0aebb572e..6af3b595921 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index d1957c311ad..80a60bd8f2e 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index e3fbeba8148..baed3c41180 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -2,42 +2,33 @@ error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:18:9 | 18 | 32_773, // 0x8005 - | ^^^^^^ + | ^^^^^^ help: consider: `0x8005` | = note: `-D decimal-literal-representation` implied by `-D warnings` - = help: consider: 0x8005 error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:19:9 | 19 | 65_280, // 0xFF00 - | ^^^^^^ - | - = help: consider: 0xFF00 + | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:20:9 | 20 | 2_131_750_927, // 0x7F0F_F00F - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7F0F_F00F + | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:21:9 | 21 | 2_147_483_647, // 0x7FFF_FFFF - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7FFF_FFFF + | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:22:9 | 22 | 4_042_322_160, // 0xF0F0_F0F0 - | ^^^^^^^^^^^^^ - | - = help: consider: 0xF0F0_F0F0 + | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 12d9e3cf0fd..4d30529d820 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -2,42 +2,33 @@ error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:16 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ + | ^^^^^^^^ help: consider: `123_456` | = note: `-D inconsistent-digit-grouping` implied by `-D warnings` - = help: consider: 123_456 error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:26 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^ - | - = help: consider: 12_345_678 + | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:38 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ - | - = help: consider: 1_234_567 + | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:48 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 1_234.567_8_f32 + | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:64 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 1.234_567_8_f32 + | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: aborting due to 5 previous errors diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 6fc285274a0..284c5ecf339 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -2,50 +2,39 @@ error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:16 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D large-digit-groups` implied by `-D warnings` - = help: consider: 0b11_0110_i64 error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:31 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 0x123_4567_8901_usize + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:54 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^ - | - = help: consider: 123_456_f32 + | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:67 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 123_456.12_f32 + | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:83 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider: 123_456.123_45_f32 + | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:102 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 123_456.123_456_f32 + | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` error: aborting due to 6 previous errors diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 72cb160fafc..4fcae9bf725 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -2,34 +2,27 @@ error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:16 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ help: consider: `0b1_0110_i64` | = note: `-D unreadable-literal` implied by `-D warnings` - = help: consider: 0b1_0110_i64 error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:29 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 0x123_4567_8901_usize + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:50 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^ - | - = help: consider: 12_345_f32 + | ^^^^^^^^^ help: consider: `12_345_f32` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:61 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ - | - = help: consider: 1.234_56_f32 + | ^^^^^^^^^^^ help: consider: `1.234_56_f32` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 37eca59438e46ed4b6d52bf8d25e035fee160f40 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Thu, 1 Mar 2018 22:00:43 +0100 Subject: lint: while immutable condition: refactor to use hir::Visitor --- clippy_lints/src/loops.rs | 82 ++++++++++++++++++++++++----------------------- tests/ui/infinite_loop.rs | 2 +- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d70d32f2306..20623620f3e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -689,46 +689,6 @@ fn check_for_loop<'a, 'tcx>( detect_manual_memcpy(cx, pat, arg, body, expr); } -fn search_mutable_vars<'a, 'tcx> ( - cx: &LateContext<'a, 'tcx>, - ex: &'tcx Expr, - acc: &mut Vec, -) -> bool { - match ex.node { - ExprBinary(_, ref a, ref b) => - search_mutable_vars(cx, a, acc) && search_mutable_vars(cx, b, acc), - - ExprUnary(_, ref a) => search_mutable_vars(cx, a, acc), - ExprPath(_) => { - if let Some(node_id) = check_for_mutability(cx, &ex) { - acc.push(node_id); - } - true - } - ExprLit(_) => true, - - // Skip if any method or function call is encountered - _ => false - } -} - -fn check_infinite_loop<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - cond: &'tcx Expr, - _block: &'tcx Block, - _expr: &'tcx Expr, -) { - let mut mutable_vars = Vec::new(); - if search_mutable_vars(cx, cond, &mut mutable_vars) && mutable_vars.len() == 0 { - span_lint( - cx, - WHILE_IMMUTABLE_CONDITION, - cond.span, - "all variables in condition are immutable. This might lead to infinite loops." - ) - } -} - fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool { if_chain! { if let ExprPath(ref qpath) = expr.node; @@ -2179,3 +2139,45 @@ fn path_name(e: &Expr) -> Option { }; None } + +fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, _block: &'tcx Block, _expr: &'tcx Expr) { + let mut mut_var_visitor = MutableVarsVisitor { + cx, + ids: HashSet::new(), + skip: false, + }; + walk_expr(&mut mut_var_visitor, cond); + if !mut_var_visitor.skip && mut_var_visitor.ids.len() == 0 { + span_lint( + cx, + WHILE_IMMUTABLE_CONDITION, + cond.span, + "all variables in condition are immutable. This might lead to infinite loops.", + ) + } +} + +struct MutableVarsVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + ids: HashSet, + skip: bool, +} + +impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { + fn visit_expr(&mut self, ex: &'tcx Expr) { + match ex.node { + ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, &ex) { + self.ids.insert(node_id); + }, + + // If there is any fuction/method call… we just stop analysis + ExprCall(_, _) | ExprMethodCall(_, _, _) => self.skip = true, + + _ => walk_expr(self, ex), + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} \ No newline at end of file diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index e6078a8ef98..ecdf42c6d3d 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -77,8 +77,8 @@ fn used_immutable() { } while i < 3 { - fn_mutref(&mut i); println!("OK - passed by mutable reference"); + fn_mutref(&mut i) } } -- cgit 1.4.1-3-g733a5 From 7d35fab304aa154a9f0d8236e3fe176ab68f01ea Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Thu, 1 Mar 2018 23:23:41 +0100 Subject: lint: while loop: detect if no var from the condition is mutated --- clippy_lints/src/loops.rs | 66 ++++++++++++++++++++++++++++++++++++++---- tests/ui/infinite_loop.rs | 16 +++++++++-- tests/ui/infinite_loop.stderr | 67 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 131 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 20623620f3e..51ccbc1297a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2140,23 +2140,45 @@ fn path_name(e: &Expr) -> Option { None } -fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, _block: &'tcx Block, _expr: &'tcx Expr) { +fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, block: &'tcx Block, expr: &'tcx Expr) { let mut mut_var_visitor = MutableVarsVisitor { cx, ids: HashSet::new(), skip: false, }; - walk_expr(&mut mut_var_visitor, cond); - if !mut_var_visitor.skip && mut_var_visitor.ids.len() == 0 { + walk_expr(&mut mut_var_visitor, expr); + if mut_var_visitor.skip { + return; + } + + if mut_var_visitor.ids.len() == 0 { span_lint( cx, WHILE_IMMUTABLE_CONDITION, cond.span, "all variables in condition are immutable. This might lead to infinite loops.", - ) + ); + return; + } + + let mut use_visitor = MutablyUsedVisitor { + cx, + ids: mut_var_visitor.ids, + any_used: false, + }; + walk_block(&mut use_visitor, block); + if !use_visitor.any_used { + span_lint( + cx, + WHILE_IMMUTABLE_CONDITION, + expr.span, + "Variable in the condition are not mutated in the loop body. This might lead to infinite loops.", + ); } } +/// Collects the set of mutable variable in an expression +/// Stops analysis if a function call is found struct MutableVarsVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, ids: HashSet, @@ -2171,12 +2193,46 @@ impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { }, // If there is any fuction/method call… we just stop analysis - ExprCall(_, _) | ExprMethodCall(_, _, _) => self.skip = true, + ExprCall(..) | ExprMethodCall(..) => self.skip = true, _ => walk_expr(self, ex), } } + fn visit_block(&mut self, _b: &'tcx Block) {} + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +/// checks within an expression/statement if any of the variables are used mutably +struct MutablyUsedVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + ids: HashSet, + any_used: bool, +} + +impl<'a, 'tcx> Visitor<'tcx> for MutablyUsedVisitor<'a, 'tcx> { + fn visit_expr(&mut self, ex: &'tcx Expr) { + if self.any_used { return; } + + match ex.node { + ExprAddrOf(MutMutable, ref p) | ExprAssign(ref p, _) | ExprAssignOp(_, ref p, _) => + if let Some(id) = check_for_mutability(self.cx, p) { + self.any_used = self.ids.contains(&id); + } + _ => walk_expr(self, ex) + } + } + + fn visit_stmt(&mut self, s: &'tcx Stmt) { + match s.node { + StmtExpr(..) | StmtSemi (..) => walk_stmt(self, s), + _ => {} + } + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index ecdf42c6d3d..d86e6c042b3 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,7 +1,8 @@ fn fn_val(i: i32) -> i32 { unimplemented!() } fn fn_constref(i: &i32) -> i32 { unimplemented!() } fn fn_mutref(i: &mut i32) { unimplemented!() } -fn foo() -> i32 { unimplemented!() } +fn fooi() -> i32 { unimplemented!() } +fn foob() -> bool { unimplemented!() } fn immutable_condition() { // Should warn when all vars mentionned are immutable @@ -12,6 +13,8 @@ fn immutable_condition() { let x = 0; while y < 10 && x < 3 { + let mut k = 1; + k += 2; println!("KO - x and y immutable"); } @@ -32,7 +35,11 @@ fn immutable_condition() { println!("OK - mut_cond is mutable"); } - while foo() < x { + while fooi() < x { + println!("OK - Fn call results may vary"); + } + + while foob() { println!("OK - Fn call results may vary"); } @@ -80,6 +87,11 @@ fn used_immutable() { println!("OK - passed by mutable reference"); fn_mutref(&mut i) } + + while i < 3 { + fn_mutref(&mut i); + println!("OK - passed by mutable reference"); + } } fn main() { diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index ddc556f426c..fba90823173 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,22 +1,67 @@ error: all variables in condition are immutable. This might lead to infinite loops. - --> $DIR/infinite_loop.rs:9:11 - | -9 | while y < 10 { - | ^^^^^^ - | - = note: `-D while-immutable-condition` implied by `-D warnings` + --> $DIR/infinite_loop.rs:10:11 + | +10 | while y < 10 { + | ^^^^^^ + | + = note: `-D while-immutable-condition` implied by `-D warnings` error: all variables in condition are immutable. This might lead to infinite loops. - --> $DIR/infinite_loop.rs:14:11 + --> $DIR/infinite_loop.rs:15:11 | -14 | while y < 10 && x < 3 { +15 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: all variables in condition are immutable. This might lead to infinite loops. - --> $DIR/infinite_loop.rs:19:11 + --> $DIR/infinite_loop.rs:22:11 | -19 | while !cond { +22 | while !cond { | ^^^^^ -error: aborting due to 3 previous errors +error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:52:5 + | +52 | / while i < 3 { +53 | | j = 3; +54 | | println!("KO - i not mentionned"); +55 | | } + | |_____^ + +error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:57:5 + | +57 | / while i < 3 && j > 0 { +58 | | println!("KO - i and j not mentionned"); +59 | | } + | |_____^ + +error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:61:5 + | +61 | / while i < 3 { +62 | | let mut i = 5; +63 | | fn_mutref(&mut i); +64 | | println!("KO - shadowed"); +65 | | } + | |_____^ + +error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:76:5 + | +76 | / while i < 3 { +77 | | fn_constref(&i); +78 | | println!("KO - const reference"); +79 | | } + | |_____^ + +error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. + --> $DIR/infinite_loop.rs:81:5 + | +81 | / while i < 3 { +82 | | fn_val(i); +83 | | println!("KO - passed by value"); +84 | | } + | |_____^ + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 769a1d9b6c1048a9e71f0ce180b8fbd9b2312419 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 2 Mar 2018 22:00:01 +0700 Subject: Fix single_char_pattern for \n, \t, etc. Single characters that are escaped weren't being searched / replaced correctly in the hint string, so it was saying to replace, say, `"\n"` with `"\n"` rather than `'\n'`. --- clippy_lints/src/methods.rs | 6 +++++- tests/ui/single_char_pattern.rs | 2 ++ tests/ui/single_char_pattern.stderr | 8 +++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a7bdd10ed66..57d93b44328 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1763,7 +1763,11 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) { if r.len() == 1 { - let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); + let c = r.chars().next().unwrap(); + let snip = snippet(cx, expr.span, ".."); + let hint = snip.replace( + &format!("\"{}\"", c.escape_default()), + &format!("'{}'", c.escape_default())); span_lint_and_then( cx, SINGLE_CHAR_PATTERN, diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 948a8ff0e41..4f940c74896 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -35,6 +35,8 @@ fn main() { x.rmatch_indices("x"); x.trim_left_matches("x"); x.trim_right_matches("x"); + // Make sure we escape characters correctly. + x.split("\n"); let h = HashSet::::new(); h.contains("X"); // should not warn diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 42ee2b9fef4..82d06ca90ac 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -102,5 +102,11 @@ error: single-character string constant used as pattern 37 | x.trim_right_matches("x"); | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` -error: aborting due to 17 previous errors +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:39:13 + | +39 | x.split("/n"); + | --------^^^^- help: try using a char instead: `x.split('/n')` + +error: aborting due to 18 previous errors -- cgit 1.4.1-3-g733a5 From fc5b377cec9e9444a227063b032d1525d2b40c5e Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Thu, 1 Mar 2018 15:15:41 +0000 Subject: Fix #2494 add suggestion for unreadable_literal Add `rustc --explain E0308` line to relevant tests --- clippy_lints/src/literal_representation.rs | 22 +++++++++++++--------- tests/ui/builtin-type-shadow.stderr | 1 + tests/ui/conf_bad_arg.stderr | 1 + tests/ui/conf_bad_toml.stderr | 1 + tests/ui/conf_bad_type.stderr | 1 + tests/ui/conf_french_blacklisted_name.stderr | 1 + tests/ui/conf_path_non_string.stderr | 1 + tests/ui/conf_unknown_key.stderr | 1 + tests/ui/decimal_literal_representation.stderr | 19 +++++-------------- tests/ui/inconsistent_digit_grouping.stderr | 19 +++++-------------- tests/ui/large_digit_groups.stderr | 23 ++++++----------------- tests/ui/unreadable_literal.stderr | 15 ++++----------- 12 files changed, 40 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9633ac00b15..1b93f6bf3f4 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax_pos; -use utils::{in_external_macro, snippet_opt, span_help_and_lint}; +use utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -222,33 +222,37 @@ enum WarningType { impl WarningType { pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { match *self { - WarningType::UnreadableLiteral => span_help_and_lint( + WarningType::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, *span, "long literal lacking separators", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::LargeDigitGroups => span_help_and_lint( + WarningType::LargeDigitGroups => span_lint_and_sugg( cx, LARGE_DIGIT_GROUPS, *span, "digit groups should be smaller", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::InconsistentDigitGrouping => span_help_and_lint( + WarningType::InconsistentDigitGrouping => span_lint_and_sugg( cx, INCONSISTENT_DIGIT_GROUPING, *span, "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), - WarningType::DecimalRepresentation => span_help_and_lint( + WarningType::DecimalRepresentation => span_lint_and_sugg( cx, DECIMAL_LITERAL_REPRESENTATION, *span, "integer literal has a better hexadecimal representation", - &format!("consider: {}", grouping_hint), + "consider", + grouping_hint.to_owned(), ), }; } diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index eb4c73b65c6..85595fb0233 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -19,3 +19,4 @@ error[E0308]: mismatched types error: aborting due to 2 previous errors +If you want more information on this error, try using "rustc --explain E0308" diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index bc44cebdbbb..30a87e23275 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index d4236926522..f01b5605a51 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index 440437d140e..ea9cf0acdd8 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index 19c8e5c9777..d09ae43301c 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index 7a0aebb572e..6af3b595921 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index d1957c311ad..80a60bd8f2e 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -8,3 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error +If you want more information on this error, try using "rustc --explain E0658" diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index e3fbeba8148..baed3c41180 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -2,42 +2,33 @@ error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:18:9 | 18 | 32_773, // 0x8005 - | ^^^^^^ + | ^^^^^^ help: consider: `0x8005` | = note: `-D decimal-literal-representation` implied by `-D warnings` - = help: consider: 0x8005 error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:19:9 | 19 | 65_280, // 0xFF00 - | ^^^^^^ - | - = help: consider: 0xFF00 + | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:20:9 | 20 | 2_131_750_927, // 0x7F0F_F00F - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7F0F_F00F + | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:21:9 | 21 | 2_147_483_647, // 0x7FFF_FFFF - | ^^^^^^^^^^^^^ - | - = help: consider: 0x7FFF_FFFF + | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:22:9 | 22 | 4_042_322_160, // 0xF0F0_F0F0 - | ^^^^^^^^^^^^^ - | - = help: consider: 0xF0F0_F0F0 + | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 12d9e3cf0fd..4d30529d820 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -2,42 +2,33 @@ error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:16 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ + | ^^^^^^^^ help: consider: `123_456` | = note: `-D inconsistent-digit-grouping` implied by `-D warnings` - = help: consider: 123_456 error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:26 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^ - | - = help: consider: 12_345_678 + | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:38 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ - | - = help: consider: 1_234_567 + | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:48 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 1_234.567_8_f32 + | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:64 | 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 1.234_567_8_f32 + | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: aborting due to 5 previous errors diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 6fc285274a0..284c5ecf339 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -2,50 +2,39 @@ error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:16 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D large-digit-groups` implied by `-D warnings` - = help: consider: 0b11_0110_i64 error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:31 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 0x123_4567_8901_usize + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:54 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^ - | - = help: consider: 123_456_f32 + | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:67 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^ - | - = help: consider: 123_456.12_f32 + | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:83 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider: 123_456.123_45_f32 + | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:102 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 123_456.123_456_f32 + | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` error: aborting due to 6 previous errors diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 72cb160fafc..4fcae9bf725 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -2,34 +2,27 @@ error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:16 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ help: consider: `0b1_0110_i64` | = note: `-D unreadable-literal` implied by `-D warnings` - = help: consider: 0b1_0110_i64 error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:29 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider: 0x123_4567_8901_usize + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:50 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^ - | - = help: consider: 12_345_f32 + | ^^^^^^^^^ help: consider: `12_345_f32` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:61 | 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ - | - = help: consider: 1.234_56_f32 + | ^^^^^^^^^^^ help: consider: `1.234_56_f32` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From e3c13da830cf4a6a1b6df8ec0683e3e7b44aeb41 Mon Sep 17 00:00:00 2001 From: bootandy Date: Fri, 2 Mar 2018 19:13:54 -0500 Subject: Change recomendation to: &[type] from Cow --- clippy_lints/src/ptr.rs | 41 +++++++++++++++++++++++++++-------------- tests/ui/needless_borrow.stderr | 4 +--- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 44ea35a9fb8..139b5883fb0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc::hir::*; use rustc::hir::map::NodeItem; +use rustc::hir::QPath; use rustc::lint::*; use rustc::ty; use syntax::ast::NodeId; @@ -214,20 +215,32 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< ); } } else if match_type(cx, ty, &paths::COW) { - let as_str = format!("{}", snippet_opt(cx, arg.span).unwrap()); - let mut cc = as_str.chars(); - cc.next(); - let replacement: String = cc.collect(); - - span_lint_and_then( - cx, - PTR_ARG, - arg.span, - "using a reference to `Cow` is not recommended.", - |db| { - db.span_suggestion(arg.span, "change this to", replacement); - }, - ); + if_chain! { + if let TyRptr(_, MutTy { ref ty, ..} ) = arg.node; + if let TyPath(ref path) = ty.node; + if let QPath::Resolved(None, ref pp) = *path; + if let [ref bx] = *pp.segments; + if let Some(ref params) = bx.parameters; + if !params.parenthesized; + if let [ref inner] = *params.types; + then { + let replacement = snippet_opt(cx, inner.span); + match replacement { + Some(r) => { + span_lint_and_then( + cx, + PTR_ARG, + arg.span, + "using a reference to `Cow` is not recommended.", + |db| { + db.span_suggestion(arg.span, "change this to", "&".to_owned() + &r); + }, + ); + }, + None => (), + } + } + } } } } diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 6cdcbb275cd..e319efa939c 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -38,13 +38,11 @@ error: this pattern creates a reference to a reference 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` -a> $DIR/needless_borrow.rs:56:25: 56:36 -b> $DIR/needless_borrow.rs:56:25: 56:36 error: using a reference to `Cow` is not recommended. --> $DIR/needless_borrow.rs:56:25 | 56 | fn test_cow_with_ref(c: &Cow<[i32]>) { - | ^^^^^^^^^^^ help: change this to: `Cow<[i32]>` + | ^^^^^^^^^^^ help: change this to: `&[i32]` | = note: `-D ptr-arg` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 926e8ff48ad1262e01fea0abdee877eba120929b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 4 Mar 2018 13:20:25 +0100 Subject: Use compiletest version v0.3.7 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d8ab9491020..802e7733985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ cargo_metadata = "0.2" regex = "0.2" [dev-dependencies] -compiletest_rs = "0.3.6" +compiletest_rs = "0.3.7" duct = "0.8.2" lazy_static = "1.0" serde_derive = "1.0" -- cgit 1.4.1-3-g733a5 From 86ce897084ecf90238bde0194c07a7886b0c36ba Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 4 Mar 2018 16:28:34 +0100 Subject: Fix unreadable_literal lint for scientific float notation --- clippy_lints/src/literal_representation.rs | 114 +++++++++++++++-------------- tests/ui/approx_const.rs | 2 +- tests/ui/unreadable_literal.rs | 2 + tests/ui/unreadable_literal.stderr | 8 +- 4 files changed, 69 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 1b93f6bf3f4..8b8d7903fed 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -134,7 +134,7 @@ impl<'a> DigitInfo<'a> { let mut last_d = '\0'; for (d_idx, d) in sans_prefix.char_indices() { - if !float && (d == 'i' || d == 'u') || float && d == 'f' { + if !float && (d == 'i' || d == 'u') || float && (d == 'f' || d == 'e' || d == 'E') { let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; let (digits, suffix) = sans_prefix.split_at(suffix_start); return Self { @@ -285,60 +285,64 @@ impl EarlyLintPass for LiteralDigitGrouping { impl LiteralDigitGrouping { fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { - // Lint integral literals. - if_chain! { - if let LitKind::Int(..) = lit.node; - if let Some(src) = snippet_opt(cx, lit.span); - if let Some(firstch) = src.chars().next(); - if char::to_digit(firstch, 10).is_some(); - then { - let digit_info = DigitInfo::new(&src, false); - let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { - warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) - }); - } - } - - // Lint floating-point literals. - if_chain! { - if let LitKind::Float(..) = lit.node; - if let Some(src) = snippet_opt(cx, lit.span); - if let Some(firstch) = src.chars().next(); - if char::to_digit(firstch, 10).is_some(); - then { - let digit_info = DigitInfo::new(&src, true); - // Separate digits into integral and fractional parts. - let parts: Vec<&str> = digit_info - .digits - .split_terminator('.') - .collect(); - - // Lint integral and fractional parts separately, and then check consistency of digit - // groups if both pass. - let _ = Self::do_lint(parts[0]) - .map(|integral_group_size| { - if parts.len() > 1 { - // Lint the fractional part of literal just like integral part, but reversed. - let fractional_part = &parts[1].chars().rev().collect::(); - let _ = Self::do_lint(fractional_part) - .map(|fractional_group_size| { - let consistent = Self::parts_consistent(integral_group_size, - fractional_group_size, - parts[0].len(), - parts[1].len()); - if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), - cx, - &lit.span); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), - cx, - &lit.span)); - } - }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); - } + match lit.node { + LitKind::Int(..) => { + // Lint integral literals. + if_chain! { + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, false); + let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { + warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + }); + } + } + }, + LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { + // Lint floating-point literals. + if_chain! { + if let Some(src) = snippet_opt(cx, lit.span); + if let Some(firstch) = src.chars().next(); + if char::to_digit(firstch, 10).is_some(); + then { + let digit_info = DigitInfo::new(&src, true); + // Separate digits into integral and fractional parts. + let parts: Vec<&str> = digit_info + .digits + .split_terminator('.') + .collect(); + + // Lint integral and fractional parts separately, and then check consistency of digit + // groups if both pass. + let _ = Self::do_lint(parts[0]) + .map(|integral_group_size| { + if parts.len() > 1 { + // Lint the fractional part of literal just like integral part, but reversed. + let fractional_part = &parts[1].chars().rev().collect::(); + let _ = Self::do_lint(fractional_part) + .map(|fractional_group_size| { + let consistent = Self::parts_consistent(integral_group_size, + fractional_group_size, + parts[0].len(), + parts[1].len()); + if !consistent { + WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), + cx, + &lit.span); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), + cx, + &lit.span)); + } + }) + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); + } + } + }, + _ => (), } } diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index f2239ecb467..394aa9d1eb3 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -2,7 +2,7 @@ #[warn(approx_constant)] -#[allow(unused, shadow_unrelated, similar_names)] +#[allow(unused, shadow_unrelated, similar_names, unreadable_literal)] fn main() { let my_e = 2.7182; let almost_e = 2.718; diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 327fea254a8..94b53f80bb2 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -5,4 +5,6 @@ fn main() { let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); + let good_sci = 1.1234e1; + let bad_sci = 1.12345e1; } diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 4fcae9bf725..b16a58ec245 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -24,5 +24,11 @@ error: long literal lacking separators 7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); | ^^^^^^^^^^^ help: consider: `1.234_56_f32` -error: aborting due to 4 previous errors +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:9:19 + | +9 | let bad_sci = 1.12345e1; + | ^^^^^^^^^ help: consider: `1.123_45e1` + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 3045f432c7d14841f69d5ad24c353e9a1a61eb3c Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Sun, 4 Mar 2018 22:56:03 -0500 Subject: Fix #2496 --- clippy_lints/src/loops.rs | 3 ++- clippy_lints/src/utils/paths.rs | 2 ++ tests/ui/for_loop.rs | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ca1d987dbf2..085cbaf9b6b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1624,7 +1624,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_chain! { // a range index op if let ExprMethodCall(ref meth, _, ref args) = expr.node; - if meth.name == "index" || meth.name == "index_mut"; + if (meth.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX)) + || (meth.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); if !self.check(&args[1], &args[0], expr); then { return } } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 20244a19f4f..81c402ab49c 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -33,6 +33,8 @@ pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"]; +pub const INDEX: [&str; 3] = ["core", "ops", "Index"]; +pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"]; pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"]; pub const INTO: [&str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index d606e7a15fc..92f95e09d73 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -556,3 +556,18 @@ pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { dst[d + i] = dst[s + i]; } } + +mod issue_2496 { + pub trait Handle { + fn new_for_index(index: usize) -> Self; + fn index(&self) -> usize; + } + + pub fn test() -> H { + for x in 0..5 { + let next_handle = H::new_for_index(x); + println!("{}", next_handle.index()); + } + unimplemented!() + } +} -- cgit 1.4.1-3-g733a5 From 7b59557dcda15a352f9515faac32d9acb85f59bc Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 5 Mar 2018 14:31:37 +0900 Subject: Don't lint range syntax with var name `start` and `end` --- clippy_lints/src/redundant_field_names.rs | 34 +++++++++++++++++++++++++++++-- tests/ui/redundant_field_names.rs | 18 ++++++++++++++++ tests/ui/redundant_field_names.stderr | 8 ++++---- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index e4d113bd3de..587454f64eb 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,8 @@ +use syntax::ast::Name; use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_sugg, match_var}; +use utils::{match_qpath, match_var, span_lint_and_sugg}; +use utils::paths; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -36,10 +38,14 @@ impl LintPass for RedundantFieldNames { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprStruct(_, ref fields, _) = expr.node { + if let ExprStruct(ref path, ref fields, _) = expr.node { for field in fields { let name = field.name.node; + if is_range_struct_field(path, &name) { + continue; + } + if match_var(&field.expr, name) && !field.is_shorthand { span_lint_and_sugg ( cx, @@ -54,3 +60,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { } } } + +/// ```rust +/// let start = 0; +/// let _ = start..; +/// +/// let end = 0; +/// let _ = ..end; +/// +/// let _ = start..end; +/// ``` +fn is_range_struct_field(path: &QPath, name: &Name) -> bool { + match name.as_str().as_ref() { + "start" => { + match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE_FROM_STD) + || match_qpath(path, &paths::RANGE_INCLUSIVE_STD) + }, + "end" => { + match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE_TO_STD) + || match_qpath(path, &paths::RANGE_INCLUSIVE_STD) + || match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) + }, + _ => false, + } +} diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 0eb9bef45b5..4ffd0e4cc62 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,5 +1,6 @@ #![warn(redundant_field_names)] #![allow(unused_variables)] +#![feature(inclusive_range,inclusive_range_syntax)] mod foo { pub const BAR: u8 = 0; @@ -27,4 +28,21 @@ fn main() { buzz: fizz, //should be ok foo: foo::BAR, //should be ok }; + + // Range syntax + let (start, end) = (0, 0); + + let _ = start..; + let _ = ..end; + let _ = start..end; + + let _ = ..=end; + let _ = start..=end; + + // TODO: the followings shoule be linted + let _ = ::std::ops::RangeFrom { start: start }; + let _ = ::std::ops::RangeTo { end: end }; + let _ = ::std::ops::Range { start: start, end: end }; + let _ = ::std::ops::RangeInclusive { start: start, end: end }; + let _ = ::std::ops::RangeToInclusive { end: end }; } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index d6d752b93a3..443f30a9f50 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,15 +1,15 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:23:9 + --> $DIR/redundant_field_names.rs:24:9 | -23 | gender: gender, +24 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:24:9 + --> $DIR/redundant_field_names.rs:25:9 | -24 | age: age, +25 | age: age, | ^^^^^^^^ help: replace it with: `age` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 5b48b03375e11421490d23a7ea36ef05181e3842 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 5 Mar 2018 08:33:37 +0100 Subject: Typo --- tests/ui/redundant_field_names.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 4ffd0e4cc62..8a17ab0c9b6 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -39,7 +39,7 @@ fn main() { let _ = ..=end; let _ = start..=end; - // TODO: the followings shoule be linted + // TODO: the following should be linted let _ = ::std::ops::RangeFrom { start: start }; let _ = ::std::ops::RangeTo { end: end }; let _ = ::std::ops::Range { start: start, end: end }; -- cgit 1.4.1-3-g733a5 From cdb60c6547fd83f5c11019dbc88346694f1bee17 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 5 Mar 2018 17:30:07 +0900 Subject: Make `redundant_field_name` not care range expressions Hand-written `Range` struct family are treated normally. --- clippy_lints/src/redundant_field_names.rs | 33 +++----------------- clippy_lints/src/utils/mod.rs | 10 ++++++ tests/ui/redundant_field_names.rs | 18 ++++++----- tests/ui/redundant_field_names.stderr | 52 ++++++++++++++++++++++++++++--- 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 587454f64eb..885e1aa9f8d 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,8 +1,6 @@ -use syntax::ast::Name; use rustc::lint::*; use rustc::hir::*; -use utils::{match_qpath, match_var, span_lint_and_sugg}; -use utils::paths; +use utils::{is_range_expression, match_var, span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -42,7 +40,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { for field in fields { let name = field.name.node; - if is_range_struct_field(path, &name) { + // Do not care about range expressions. + // They could have redundant field name when desugared to structs. + // e.g. `start..end` is desugared to `Range { start: start, end: end }` + if is_range_expression(expr.span) { continue; } @@ -60,27 +61,3 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { } } } - -/// ```rust -/// let start = 0; -/// let _ = start..; -/// -/// let end = 0; -/// let _ = ..end; -/// -/// let _ = start..end; -/// ``` -fn is_range_struct_field(path: &QPath, name: &Name) -> bool { - match name.as_str().as_ref() { - "start" => { - match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE_FROM_STD) - || match_qpath(path, &paths::RANGE_INCLUSIVE_STD) - }, - "end" => { - match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE_TO_STD) - || match_qpath(path, &paths::RANGE_INCLUSIVE_STD) - || match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) - }, - _ => false, - } -} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c501dadeb79..2f2f0c04054 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -64,6 +64,16 @@ pub fn in_macro(span: Span) -> bool { }) } +/// Returns true if `expn_info` was expanded by range expressions. +pub fn is_range_expression(span: Span) -> bool { + span.ctxt().outer().expn_info().map_or(false, |info| { + match info.callee.format { + ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::DotFill) => true, + _ => false, + } + }) +} + /// Returns true if the macro that expanded the crate was outside of the /// current crate or was a /// compiler plugin. diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 8a17ab0c9b6..cb49283010b 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,6 +1,8 @@ #![warn(redundant_field_names)] #![allow(unused_variables)] -#![feature(inclusive_range,inclusive_range_syntax)] +#![feature(inclusive_range, inclusive_range_syntax)] + +use std::ops::{Range, RangeFrom, RangeTo, RangeInclusive, RangeToInclusive}; mod foo { pub const BAR: u8 = 0; @@ -29,7 +31,7 @@ fn main() { foo: foo::BAR, //should be ok }; - // Range syntax + // Range expressions let (start, end) = (0, 0); let _ = start..; @@ -39,10 +41,10 @@ fn main() { let _ = ..=end; let _ = start..=end; - // TODO: the following should be linted - let _ = ::std::ops::RangeFrom { start: start }; - let _ = ::std::ops::RangeTo { end: end }; - let _ = ::std::ops::Range { start: start, end: end }; - let _ = ::std::ops::RangeInclusive { start: start, end: end }; - let _ = ::std::ops::RangeToInclusive { end: end }; + // hand-written Range family structs are linted + let _ = RangeFrom { start: start }; + let _ = RangeTo { end: end }; + let _ = Range { start: start, end: end }; + let _ = RangeInclusive { start: start, end: end }; + let _ = RangeToInclusive { end: end }; } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 443f30a9f50..40315c6ffac 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,16 +1,58 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:24:9 + --> $DIR/redundant_field_names.rs:26:9 | -24 | gender: gender, +26 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:25:9 + --> $DIR/redundant_field_names.rs:27:9 | -25 | age: age, +27 | age: age, | ^^^^^^^^ help: replace it with: `age` -error: aborting due to 2 previous errors +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:45:25 + | +45 | let _ = RangeFrom { start: start }; + | ^^^^^^^^^^^^ help: replace it with: `start` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:46:23 + | +46 | let _ = RangeTo { end: end }; + | ^^^^^^^^ help: replace it with: `end` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:47:21 + | +47 | let _ = Range { start: start, end: end }; + | ^^^^^^^^^^^^ help: replace it with: `start` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:47:35 + | +47 | let _ = Range { start: start, end: end }; + | ^^^^^^^^ help: replace it with: `end` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:48:30 + | +48 | let _ = RangeInclusive { start: start, end: end }; + | ^^^^^^^^^^^^ help: replace it with: `start` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:48:44 + | +48 | let _ = RangeInclusive { start: start, end: end }; + | ^^^^^^^^ help: replace it with: `end` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:49:32 + | +49 | let _ = RangeToInclusive { end: end }; + | ^^^^^^^^ help: replace it with: `end` + +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From e13dcd26e3d3483276edef201556c50ca41f4910 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 5 Mar 2018 17:40:42 +0900 Subject: Unused variable is left --- clippy_lints/src/redundant_field_names.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 885e1aa9f8d..1f67dd80baa 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -36,7 +36,7 @@ impl LintPass for RedundantFieldNames { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprStruct(ref path, ref fields, _) = expr.node { + if let ExprStruct(_, ref fields, _) = expr.node { for field in fields { let name = field.name.node; -- cgit 1.4.1-3-g733a5 From 8e406760a4ee4bf0b0db5d0a14b8e5dca292d2d9 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 5 Mar 2018 18:20:27 +0900 Subject: Move call of `is_range_expression()` outside of blocks --- clippy_lints/src/redundant_field_names.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 1f67dd80baa..6775129f9df 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -36,17 +36,17 @@ impl LintPass for RedundantFieldNames { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + // Do not care about range expressions. + // They could have redundant field name when desugared to structs. + // e.g. `start..end` is desugared to `Range { start: start, end: end }` + if is_range_expression(expr.span) { + return; + } + if let ExprStruct(_, ref fields, _) = expr.node { for field in fields { let name = field.name.node; - // Do not care about range expressions. - // They could have redundant field name when desugared to structs. - // e.g. `start..end` is desugared to `Range { start: start, end: end }` - if is_range_expression(expr.span) { - continue; - } - if match_var(&field.expr, name) && !field.is_shorthand { span_lint_and_sugg ( cx, -- cgit 1.4.1-3-g733a5 From 1ea84c80c1cade1068fab4019f58086c3e159b1c Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Mon, 5 Mar 2018 22:20:28 +0100 Subject: lint: while immutable condition: refactor to use ExprUseVisitor --- clippy_lints/src/loops.rs | 73 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 51ccbc1297a..3e966daa837 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1399,14 +1399,14 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -struct MutateDelegate { +struct MutatePairDelegate { node_id_low: Option, node_id_high: Option, span_low: Option, span_high: Option, } -impl<'tcx> Delegate<'tcx> for MutateDelegate { +impl<'tcx> Delegate<'tcx> for MutatePairDelegate { fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) {} fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} @@ -1440,7 +1440,7 @@ impl<'tcx> Delegate<'tcx> for MutateDelegate { fn decl_without_init(&mut self, _: NodeId, _: Span) {} } -impl<'tcx> MutateDelegate { +impl<'tcx> MutatePairDelegate { fn mutation_span(&self) -> (Option, Option) { (self.span_low, self.span_high) } @@ -1499,7 +1499,7 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { } fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { - let mut delegate = MutateDelegate { + let mut delegate = MutatePairDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], span_low: None, @@ -2143,7 +2143,7 @@ fn path_name(e: &Expr) -> Option { fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, block: &'tcx Block, expr: &'tcx Expr) { let mut mut_var_visitor = MutableVarsVisitor { cx, - ids: HashSet::new(), + ids: HashMap::new(), skip: false, }; walk_expr(&mut mut_var_visitor, expr); @@ -2161,13 +2161,15 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } - let mut use_visitor = MutablyUsedVisitor { - cx, - ids: mut_var_visitor.ids, - any_used: false, + + let mut delegate = MutVarsDelegate { + mut_spans: mut_var_visitor.ids, }; - walk_block(&mut use_visitor, block); - if !use_visitor.any_used { + let def_id = def_id::DefId::local(block.hir_id.owner); + let region_scope_tree = &cx.tcx.region_scope_tree(def_id); + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(expr); + + if !delegate.mut_spans.iter().any(|(_, v)| v.is_some()) { span_lint( cx, WHILE_IMMUTABLE_CONDITION, @@ -2181,7 +2183,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b /// Stops analysis if a function call is found struct MutableVarsVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ids: HashSet, + ids: HashMap>, skip: bool, } @@ -2189,7 +2191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, &ex) { - self.ids.insert(node_id); + self.ids.insert(node_id, None); }, // If there is any fuction/method call… we just stop analysis @@ -2206,34 +2208,37 @@ impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { } } -/// checks within an expression/statement if any of the variables are used mutably -struct MutablyUsedVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, - ids: HashSet, - any_used: bool, +struct MutVarsDelegate { + mut_spans: HashMap>, } -impl<'a, 'tcx> Visitor<'tcx> for MutablyUsedVisitor<'a, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx Expr) { - if self.any_used { return; } - - match ex.node { - ExprAddrOf(MutMutable, ref p) | ExprAssign(ref p, _) | ExprAssignOp(_, ref p, _) => - if let Some(id) = check_for_mutability(self.cx, p) { - self.any_used = self.ids.contains(&id); - } - _ => walk_expr(self, ex) +impl<'tcx> MutVarsDelegate { + fn update(&mut self, cat: &'tcx Categorization, sp: Span) { + if let &Categorization::Local(id) = cat { + if let Some(span) = self.mut_spans.get_mut(&id) { + *span = Some(sp) + } } } +} + - fn visit_stmt(&mut self, s: &'tcx Stmt) { - match s.node { - StmtExpr(..) | StmtSemi (..) => walk_stmt(self, s), - _ => {} +impl<'tcx> Delegate<'tcx> for MutVarsDelegate { + fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) {} + + fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} + + fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) {} + + fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + if let ty::BorrowKind::MutBorrow = bk { + self.update(&cmt.cat, sp) } } - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None + fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { + self.update(&cmt.cat, sp) } + + fn decl_without_init(&mut self, _: NodeId, _: Span) {} } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From ed4535641bb4329d741dcbd162d8a7d7374a67db Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 6 Mar 2018 13:58:03 +0100 Subject: UnNeg and UnNot count as additional operations now --- clippy_lints/src/suspicious_trait_impl.rs | 23 ++++++++++++++--------- tests/ui/suspicious_arithmetic_impl.rs | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 682ab4d15ea..ecf8e83a86f 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -61,18 +61,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { use rustc::hir::BinOp_::*; if let hir::ExprBinary(binop, _, _) = expr.node { - // Check if the binary expression is part of another binary expression + // Check if the binary expression is part of another bi/unary expression // as a child node let mut parent_expr = cx.tcx.hir.get_parent_node(expr.id); while parent_expr != ast::CRATE_NODE_ID { - if_chain! { - if let hir::map::Node::NodeExpr(e) = cx.tcx.hir.get(parent_expr); - if let hir::ExprBinary(_, _, _) = e.node; - then { - return + if let hir::map::Node::NodeExpr(e) = cx.tcx.hir.get(parent_expr) { + match e.node { + hir::ExprBinary(..) + | hir::ExprUnary(hir::UnOp::UnNot, _) + | hir::ExprUnary(hir::UnOp::UnNeg, _) => return, + _ => {}, } } - parent_expr = cx.tcx.hir.get_parent_node(parent_expr); } // as a parent node @@ -180,8 +180,13 @@ struct BinaryExprVisitor { impl<'a, 'tcx: 'a> Visitor<'tcx> for BinaryExprVisitor { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if let hir::ExprBinary(_, _, _) = expr.node { - self.in_binary_expr = true; + match expr.node { + hir::ExprBinary(..) + | hir::ExprUnary(hir::UnOp::UnNot, _) + | hir::ExprUnary(hir::UnOp::UnNeg, _) => { + self.in_binary_expr = true + }, + _ => {}, } walk_expr(self, expr); diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 097627e1d7c..22233a4b154 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -45,6 +45,24 @@ impl Div for Foo { } } +struct Bar(i32); + +impl Add for Bar { + type Output = Bar; + + fn add(self, other: Self) -> Self { + Bar(self.0 & !other.0) // OK: UnNot part of BiExpr as child node + } +} + +impl Sub for Bar { + type Output = Bar; + + fn sub(self, other: Self) -> Self { + Bar(-(self.0 & other.0)) // OK: UnNeg part of BiExpr as parent node + } +} + fn main() {} fn do_nothing(x: u32) -> u32 { -- cgit 1.4.1-3-g733a5 From d55890a2b19d3dbdcc717a50ea40cb594d4fa841 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Tue, 6 Mar 2018 14:06:27 +0100 Subject: Increase unreadable_literal digits (fixes #1958) --- clippy_lints/src/literal_representation.rs | 2 +- tests/ui/unreadable_literal.rs | 6 +++--- tests/ui/unreadable_literal.stderr | 26 +++++++++++++------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 8b8d7903fed..c534ef327c2 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -375,7 +375,7 @@ impl LiteralDigitGrouping { if underscore_positions.is_empty() { // Check if literal needs underscores. - if digits.len() > 4 { + if digits.len() > 5 { Err(WarningType::UnreadableLiteral) } else { Ok(0) diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 94b53f80bb2..0ec757cfbcf 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -3,8 +3,8 @@ #[warn(unreadable_literal)] #[allow(unused_variables)] fn main() { - let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); - let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); + let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 65536, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); + let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); let good_sci = 1.1234e1; - let bad_sci = 1.12345e1; + let bad_sci = 1.123456e1; } diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index b16a58ec245..4b78e2e121b 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,34 +1,34 @@ error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:16 | -7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ help: consider: `0b1_0110_i64` +7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:29 + --> $DIR/unreadable_literal.rs:7:30 | -7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` +7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:50 + --> $DIR/unreadable_literal.rs:7:51 | -7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^ help: consider: `12_345_f32` +7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:61 + --> $DIR/unreadable_literal.rs:7:63 | -7 | let bad = (0b10110_i64, 0x12345678901_usize, 12345_f32, 1.23456_f32); - | ^^^^^^^^^^^ help: consider: `1.234_56_f32` +7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators --> $DIR/unreadable_literal.rs:9:19 | -9 | let bad_sci = 1.12345e1; - | ^^^^^^^^^ help: consider: `1.123_45e1` +9 | let bad_sci = 1.123456e1; + | ^^^^^^^^^^ help: consider: `1.123_456e1` error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 814827113e8cdffadb215de52fde349bace81610 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Tue, 6 Mar 2018 18:27:11 +0100 Subject: lint: immutable condition: add internally mutable test --- tests/ui/infinite_loop.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index d86e6c042b3..cc694583eec 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -94,8 +94,22 @@ fn used_immutable() { } } +use std::cell::Cell; + +fn maybe_i_mutate(i: &Cell) { unimplemented!() } + +fn internally_mutable() { + let b = Cell::new(true); + + while b.get() { // b cannot be silently coerced to `bool` + maybe_i_mutate(&b); + println!("OK - Method call within condition"); + } +} + fn main() { immutable_condition(); unused_var(); used_immutable(); + internally_mutable(); } -- cgit 1.4.1-3-g733a5 From ae5354e6ef610804ae46456df2c9001f65c8786c Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Wed, 7 Mar 2018 18:24:36 +0100 Subject: lint: while immutable condition: do not lint constants --- clippy_lints/src/loops.rs | 13 ++++++++++--- tests/ui/infinite_loop.rs | 17 +++++++++++++++++ tests/ui/infinite_loop.stderr | 16 ++++++++-------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7873240a95c..f476b960d88 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -22,6 +22,8 @@ use syntax::codemap::Span; use utils::sugg; use utils::const_to_u64; +use consts::constant; + use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; @@ -2142,6 +2144,11 @@ fn path_name(e: &Expr) -> Option { } fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, block: &'tcx Block, expr: &'tcx Expr) { + if constant(cx, cond).is_some() { + // A pure constant condition (e.g. while false) is not linted. + return; + } + let mut mut_var_visitor = MutableVarsVisitor { cx, ids: HashMap::new(), @@ -2152,12 +2159,12 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } - if mut_var_visitor.ids.len() == 0 { + if mut_var_visitor.ids.is_empty() { span_lint( cx, WHILE_IMMUTABLE_CONDITION, cond.span, - "all variables in condition are immutable. This might lead to infinite loops.", + "all variables in condition are immutable. This either leads to an infinite or to a never running loop.", ); return; } @@ -2175,7 +2182,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b cx, WHILE_IMMUTABLE_CONDITION, expr.span, - "Variable in the condition are not mutated in the loop body. This might lead to infinite loops.", + "Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.", ); } } diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index cc694583eec..560400f359d 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -94,6 +94,23 @@ fn used_immutable() { } } +const N: i32 = 5; +const B: bool = false; + +fn consts() { + while false { + println!("Constants are not linted"); + } + + while B { + println!("Constants are not linted"); + } + + while N > 0 { + println!("Constants are not linted"); + } +} + use std::cell::Cell; fn maybe_i_mutate(i: &Cell) { unimplemented!() } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index fba90823173..2addd4819e6 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,4 +1,4 @@ -error: all variables in condition are immutable. This might lead to infinite loops. +error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:10:11 | 10 | while y < 10 { @@ -6,19 +6,19 @@ error: all variables in condition are immutable. This might lead to infinite loo | = note: `-D while-immutable-condition` implied by `-D warnings` -error: all variables in condition are immutable. This might lead to infinite loops. +error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:15:11 | 15 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ -error: all variables in condition are immutable. This might lead to infinite loops. +error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:22:11 | 22 | while !cond { | ^^^^^ -error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:52:5 | 52 | / while i < 3 { @@ -27,7 +27,7 @@ error: Variable in the condition are not mutated in the loop body. This might le 55 | | } | |_____^ -error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:57:5 | 57 | / while i < 3 && j > 0 { @@ -35,7 +35,7 @@ error: Variable in the condition are not mutated in the loop body. This might le 59 | | } | |_____^ -error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:61:5 | 61 | / while i < 3 { @@ -45,7 +45,7 @@ error: Variable in the condition are not mutated in the loop body. This might le 65 | | } | |_____^ -error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:76:5 | 76 | / while i < 3 { @@ -54,7 +54,7 @@ error: Variable in the condition are not mutated in the loop body. This might le 79 | | } | |_____^ -error: Variable in the condition are not mutated in the loop body. This might lead to infinite loops. +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:81:5 | 81 | / while i < 3 { -- cgit 1.4.1-3-g733a5 From ed769a3bc4b39ebca5e4f5b9d8449c1cb8aa0cff Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Sun, 11 Mar 2018 13:57:28 +0900 Subject: Ignore all macros in redundant_field_names --- Cargo.toml | 1 + clippy_lints/src/redundant_field_names.rs | 4 ++-- tests/ui/redundant_field_names.rs | 8 +++++++ tests/ui/redundant_field_names.stderr | 36 +++++++++++++++---------------- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 802e7733985..36457023d92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = "1.0" +derive-new = "0.5" [features] debugging = [] diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 6775129f9df..75dedc6b801 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{is_range_expression, match_var, span_lint_and_sugg}; +use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -39,7 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { // Do not care about range expressions. // They could have redundant field name when desugared to structs. // e.g. `start..end` is desugared to `Range { start: start, end: end }` - if is_range_expression(expr.span) { + if in_macro(expr.span) || is_range_expression(expr.span) { return; } diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index cb49283010b..98b6e16c450 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -2,6 +2,9 @@ #![allow(unused_variables)] #![feature(inclusive_range, inclusive_range_syntax)] +#[macro_use] +extern crate derive_new; + use std::ops::{Range, RangeFrom, RangeTo, RangeInclusive, RangeToInclusive}; mod foo { @@ -16,6 +19,11 @@ struct Person { foo: u8, } +#[derive(new)] +pub struct S { + v: String, +} + fn main() { let gender: u8 = 42; let age = 0; diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 40315c6ffac..91db8a5f0d1 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,57 +1,57 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:26:9 + --> $DIR/redundant_field_names.rs:34:9 | -26 | gender: gender, +34 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:27:9 + --> $DIR/redundant_field_names.rs:35:9 | -27 | age: age, +35 | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:45:25 + --> $DIR/redundant_field_names.rs:53:25 | -45 | let _ = RangeFrom { start: start }; +53 | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:46:23 + --> $DIR/redundant_field_names.rs:54:23 | -46 | let _ = RangeTo { end: end }; +54 | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:47:21 + --> $DIR/redundant_field_names.rs:55:21 | -47 | let _ = Range { start: start, end: end }; +55 | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:47:35 + --> $DIR/redundant_field_names.rs:55:35 | -47 | let _ = Range { start: start, end: end }; +55 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:48:30 + --> $DIR/redundant_field_names.rs:56:30 | -48 | let _ = RangeInclusive { start: start, end: end }; +56 | let _ = RangeInclusive { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:48:44 + --> $DIR/redundant_field_names.rs:56:44 | -48 | let _ = RangeInclusive { start: start, end: end }; +56 | let _ = RangeInclusive { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:49:32 + --> $DIR/redundant_field_names.rs:57:32 | -49 | let _ = RangeToInclusive { end: end }; +57 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From d63716343538497c628122d54f4f57893594b9e0 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Sun, 11 Mar 2018 14:03:09 +0900 Subject: Fix comment --- clippy_lints/src/redundant_field_names.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 75dedc6b801..a63447575ef 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -36,9 +36,9 @@ impl LintPass for RedundantFieldNames { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - // Do not care about range expressions. - // They could have redundant field name when desugared to structs. - // e.g. `start..end` is desugared to `Range { start: start, end: end }` + // Ignore all macros including range expressions. + // They can have redundant field names when expanded. + // e.g. range expression `start..end` is desugared to `Range { start: start, end: end }` if in_macro(expr.span) || is_range_expression(expr.span) { return; } -- cgit 1.4.1-3-g733a5 From c5d82e05907320367834136783b22cc52f357826 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Sun, 11 Mar 2018 14:07:16 +0900 Subject: Remove duct dependency --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 802e7733985..98032e62223 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ regex = "0.2" [dev-dependencies] compiletest_rs = "0.3.7" -duct = "0.8.2" lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } -- cgit 1.4.1-3-g733a5 From f7b2578aea97c7cdafd09aa362a05aa78605fbfa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 13 Mar 2018 11:38:11 +0100 Subject: Update to rustc master --- clippy_lints/src/array_indexing.rs | 69 ++------ clippy_lints/src/bit_mask.rs | 30 +--- clippy_lints/src/consts.rs | 354 ++++++++++++++++++++++--------------- clippy_lints/src/enum_clike.rs | 53 +++--- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/identity_op.rs | 31 ++-- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/loops.rs | 41 ++--- clippy_lints/src/matches.rs | 72 +++----- clippy_lints/src/methods.rs | 16 +- clippy_lints/src/misc.rs | 64 +------ clippy_lints/src/neg_multiply.rs | 3 +- clippy_lints/src/ranges.rs | 17 +- clippy_lints/src/regex.rs | 20 +-- clippy_lints/src/types.rs | 85 ++------- clippy_lints/src/utils/mod.rs | 33 +++- clippy_lints/src/vec.rs | 11 +- clippy_lints/src/zero_div_zero.rs | 16 +- tests/ui/float_cmp.stderr | 64 +------ tests/ui/op_ref.stderr | 10 +- tests/ui/zero_div_zero.stderr | 2 +- 21 files changed, 398 insertions(+), 597 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 8949e4cc387..53d0d7cebaa 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,13 +1,9 @@ use rustc::lint::*; -use rustc::middle::const_val::ConstVal; use rustc::ty; -use rustc::ty::subst::Substs; -use rustc_const_eval::ConstContext; -use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; -use utils::const_to_u64; +use consts::{constant, Constant}; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. @@ -63,29 +59,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, size) = ty.sty { - let size = ConstInt::Usize( - ConstUsize::new(const_to_u64(size), cx.sess().target.usize_ty).expect("array size is invalid"), - ); - let parent_item = cx.tcx.hir.get_parent(e.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables); + let size = size.val.to_raw_bits().unwrap(); // Index is a constant uint - if let Ok(const_index) = constcx.eval(index) { - if let ConstVal::Integral(const_index) = const_index.val { - if size <= const_index { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); - } - - return; + if let Some((Constant::Int(const_index), _)) = constant(cx, index) { + if size <= const_index { + utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); } + + return; } // Index is a constant range if let Some(range) = higher::range(index) { - let start = range.start.map(|start| constcx.eval(start)).map(|v| v.ok()); - let end = range.end.map(|end| constcx.eval(end)).map(|v| v.ok()); + let start = range.start.map(|start| constant(cx, start).map(|(c, _)| c)); + let end = range.end.map(|end| constant(cx, end).map(|(c, _)| c)); if let Some((start, end)) = to_const_range(&start, &end, range.limits, size) { if start > size || end > size { @@ -114,43 +102,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { /// Returns an option containing a tuple with the start and end (exclusive) of /// the range. fn to_const_range( - start: &Option>, - end: &Option>, + start: &Option>, + end: &Option>, limits: RangeLimits, - array_size: ConstInt, -) -> Option<(ConstInt, ConstInt)> { + array_size: u128, +) -> Option<(u128, u128)> { let start = match *start { - Some(Some(&ty::Const { - val: ConstVal::Integral(x), - .. - })) => x, + Some(Some(Constant::Int(x))) => x, Some(_) => return None, - None => ConstInt::U8(0), + None => 0, }; let end = match *end { - Some(Some(&ty::Const { - val: ConstVal::Integral(x), - .. - })) => if limits == RangeLimits::Closed { - match x { - ConstInt::U8(_) => (x + ConstInt::U8(1)), - ConstInt::U16(_) => (x + ConstInt::U16(1)), - ConstInt::U32(_) => (x + ConstInt::U32(1)), - ConstInt::U64(_) => (x + ConstInt::U64(1)), - ConstInt::U128(_) => (x + ConstInt::U128(1)), - ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), - ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), - ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), - ConstInt::I8(_) => (x + ConstInt::I8(1)), - ConstInt::I16(_) => (x + ConstInt::I16(1)), - ConstInt::I32(_) => (x + ConstInt::I32(1)), - ConstInt::I64(_) => (x + ConstInt::I64(1)), - ConstInt::I128(_) => (x + ConstInt::I128(1)), - ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), - ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), - ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), - }.expect("such a big array is not realistic") + Some(Some(Constant::Int(x))) => if limits == RangeLimits::Closed { + x + 1 } else { x }, diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index f0ff27d4d63..7eb6477b269 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,11 +1,10 @@ use rustc::hir::*; -use rustc::hir::def::Def; use rustc::lint::*; -use rustc_const_eval::lookup_const_by_id; use syntax::ast::LitKind; use syntax::codemap::Span; use utils::{span_lint, span_lint_and_then}; use utils::sugg::Sugg; +use consts::{constant, Constant}; /// **What it does:** Checks for incompatible bit masks in comparisons. /// @@ -302,31 +301,8 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str } fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { - use rustc::ty::subst::Substs; - match lit.node { - ExprLit(ref lit_ptr) => { - if let LitKind::Int(value, _) = lit_ptr.node { - Some(value) // TODO: Handle sign - } else { - None - } - }, - ExprPath(ref qpath) => { - let def = cx.tables.qpath_def(qpath, lit.hir_id); - if let Def::Const(def_id) = def { - lookup_const_by_id(cx.tcx, cx.param_env.and((def_id, Substs::empty()))).and_then(|(l, _ty)| { - let body = if let Some(id) = cx.tcx.hir.as_local_node_id(l) { - cx.tcx.mir_const_qualif(def_id); - cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id)) - } else { - cx.tcx.extern_const_body(def_id).body - }; - fetch_int_literal(cx, &body.value) - }) - } else { - None - } - }, + match constant(cx, lit)?.0 { + Constant::Int(n) => Some(n), _ => None, } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index a99a56bc554..7c43cb668b3 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -2,19 +2,18 @@ use rustc::lint::LateContext; use rustc::hir::def::Def; -use rustc_const_eval::lookup_const_by_id; -use rustc_const_math::ConstInt; use rustc::hir::*; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::ty::subst::{Subst, Substs}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; use std::mem; use std::rc::Rc; -use syntax::ast::{FloatTy, LitKind, StrStyle}; +use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; -use utils::const_to_u64; +use rustc::middle::const_val::ConstVal; +use utils::{sext, unsext, clip}; #[derive(Debug, Copy, Clone)] pub enum FloatWidth { @@ -36,15 +35,17 @@ impl From for FloatWidth { #[derive(Debug, Clone)] pub enum Constant { /// a String "abc" - Str(String, StrStyle), + Str(String), /// a Binary String b"abc" Binary(Rc>), /// a single char 'a' Char(char), - /// an integer, third argument is whether the value is negated - Int(ConstInt), - /// a float with given type - Float(String, FloatWidth), + /// an integer's bit representation + Int(u128), + /// an f32 + F32(f32), + /// an f64 + F64(f64), /// true or false Bool(bool), /// an array of constants @@ -58,20 +59,21 @@ pub enum Constant { impl PartialEq for Constant { fn eq(&self, other: &Self) -> bool { match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, + (&Constant::Str(ref ls), &Constant::Str(ref rs)) => ls == rs, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(l), &Constant::Int(r)) => { - l.is_negative() == r.is_negative() && l.to_u128_unchecked() == r.to_u128_unchecked() + (&Constant::Int(l), &Constant::Int(r)) => l == r, + (&Constant::F64(l), &Constant::F64(r)) => { + // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have + // `Fw32 == Fw64` so don’t compare them + // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs + unsafe { mem::transmute::(l) == mem::transmute::(r) } }, - (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { + (&Constant::F32(l), &Constant::F32(r)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them - match (ls.parse::(), rs.parse::()) { - // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs - (Ok(l), Ok(r)) => unsafe { mem::transmute::(l) == mem::transmute::(r) }, - _ => false, - } + // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs + unsafe { mem::transmute::(l as f64) == mem::transmute::(r as f64) } }, (&Constant::Bool(l), &Constant::Bool(r)) => l == r, (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, @@ -87,9 +89,8 @@ impl Hash for Constant { H: Hasher, { match *self { - Constant::Str(ref s, ref k) => { + Constant::Str(ref s) => { s.hash(state); - k.hash(state); }, Constant::Binary(ref b) => { b.hash(state); @@ -98,14 +99,13 @@ impl Hash for Constant { c.hash(state); }, Constant::Int(i) => { - i.to_u128_unchecked().hash(state); - i.is_negative().hash(state); + i.hash(state); }, - Constant::Float(ref f, _) => { - // don’t use the width here because of PartialEq implementation - if let Ok(f) = f.parse::() { - unsafe { mem::transmute::(f) }.hash(state); - } + Constant::F32(f) => { + unsafe { mem::transmute::(f as f64) }.hash(state); + }, + Constant::F64(f) => { + unsafe { mem::transmute::(f) }.hash(state); }, Constant::Bool(b) => { b.hash(state); @@ -124,25 +124,11 @@ impl Hash for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => if l_sty == r_sty { - Some(ls.cmp(rs)) - } else { - None - }, + (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), - (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { - match (ls.parse::(), rs.parse::()) { - (Ok(ref l), Ok(ref r)) => { - match (l.partial_cmp(r), l.is_sign_positive() == r.is_sign_positive()) { - // Check for comparison of -0.0 and 0.0 - (Some(Ordering::Equal), false) => None, - (x, _) => x, - } - }, - _ => None, - } - }, + (&Constant::F64(l), &Constant::F64(r)) => l.partial_cmp(&r), + (&Constant::F32(l), &Constant::F32(r)) => l.partial_cmp(&r), (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => { l.partial_cmp(r) @@ -157,63 +143,25 @@ impl PartialOrd for Constant { } /// parse a `LitKind` to a `Constant` -#[allow(cast_possible_wrap)] -pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: Ty<'tcx>) -> Constant { +pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { use syntax::ast::*; - use syntax::ast::LitIntType::*; - use rustc::ty::util::IntTypeExt; - if let ty::TyAdt(adt, _) = ty.sty { - if adt.is_enum() { - ty = adt.repr.discr_type().to_ty(tcx) - } - } match *lit { - LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style), - LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), + LitKind::Str(ref is, _) => Constant::Str(is.to_string()), + LitKind::Byte(b) => Constant::Int(b as u128), LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(n, hint) => match (&ty.sty, hint) { - (&ty::TyInt(ity), _) | (_, Signed(ity)) => { - Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.isize_ty)) - }, - (&ty::TyUint(uty), _) | (_, Unsigned(uty)) => { - Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.usize_ty)) - }, + LitKind::Int(n, _) => Constant::Int(n), + LitKind::Float(ref is, _) | + LitKind::FloatUnsuffixed(ref is) => match ty.sty { + ty::TyFloat(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()), + ty::TyFloat(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()), _ => bug!(), }, - LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), - LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), LitKind::Bool(b) => Constant::Bool(b), } } -fn constant_not(o: &Constant) -> Option { - use self::Constant::*; - match *o { - Bool(b) => Some(Bool(!b)), - Int(value) => (!value).ok().map(Int), - _ => None, - } -} - -fn constant_negate(o: Constant) -> Option { - use self::Constant::*; - match o { - Int(value) => (-value).ok().map(Int), - Float(is, ty) => Some(Float(neg_float_str(&is), ty)), - _ => None, - } -} - -fn neg_float_str(s: &str) -> String { - if s.starts_with('-') { - s[1..].to_owned() - } else { - format!("-{}", s) - } -} - pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { tcx: lcx.tcx, @@ -255,19 +203,19 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id), ExprBlock(ref block) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), - ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tcx, self.tables.expr_ty(e))), + ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))), ExprArray(ref vec) => self.multi(vec).map(Constant::Vec), ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprRepeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::TyArray(_, n) => const_to_u64(n), + ty::TyArray(_, n) => n.val.to_raw_bits().expect("array length"), _ => span_bug!(e.span, "typeck error"), }; - self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) + self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64)) }, ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op { - UnNot => constant_not(&o), - UnNeg => constant_negate(o), + UnNot => self.constant_not(&o, self.tables.expr_ty(e)), + UnNeg => self.constant_negate(o, self.tables.expr_ty(e)), UnDeref => Some(o), }), ExprBinary(op, ref left, ref right) => self.binop(op, left, right), @@ -276,6 +224,42 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } + fn constant_not(&self, o: &Constant, ty: ty::Ty) -> Option { + use self::Constant::*; + match *o { + Bool(b) => Some(Bool(!b)), + Int(value) => { + let mut value = !value; + match ty.sty { + ty::TyInt(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), + ty::TyUint(ity) => Some(Int(clip(self.tcx, value, ity))), + _ => None, + } + }, + _ => None, + } + } + + fn constant_negate(&self, o: Constant, ty: ty::Ty) -> Option { + use self::Constant::*; + match o { + Int(value) => { + let ity = match ty.sty { + ty::TyInt(ity) => ity, + _ => return None, + }; + // sign extend + let value = sext(self.tcx, value, ity); + let value = value.checked_neg()?; + // clear unused bits + Some(Int(unsext(self.tcx, value, ity))) + }, + F32(f) => Some(F32(-f)), + F64(f) => Some(F64(-f)), + _ => None, + } + } + /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part fn multi(&mut self, vec: &[Expr]) -> Option> { @@ -295,27 +279,18 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } else { substs.subst(self.tcx, self.substs) }; - let param_env = self.param_env.and((def_id, substs)); - if let Some((def_id, substs)) = lookup_const_by_id(self.tcx, param_env) { - let mut cx = Self { - tcx: self.tcx, - tables: self.tcx.typeck_tables_of(def_id), - needed_resolution: false, - substs: substs, - param_env: param_env.param_env, - }; - let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - self.tcx.mir_const_qualif(def_id); - self.tcx.hir.body(self.tcx.hir.body_owned_by(id)) - } else { - self.tcx.extern_const_body(def_id).body - }; - let ret = cx.expr(&body.value); - if ret.is_some() { - self.needed_resolution = true; - } - return ret; + let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs)?; + let gid = GlobalId { + instance, + promoted: None, + }; + use rustc::mir::interpret::GlobalId; + let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; + let ret = miri_to_const(self.tcx, result); + if ret.is_some() { + self.needed_resolution = true; } + return ret; }, _ => {}, } @@ -344,36 +319,127 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option { - let l = if let Some(l) = self.expr(left) { - l - } else { - return None; - }; + let l = self.expr(left)?; let r = self.expr(right); - match (op.node, l, r) { - (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), - (BiSub, Constant::Int(l), Some(Constant::Int(r))) => (l - r).ok().map(Constant::Int), - (BiMul, Constant::Int(l), Some(Constant::Int(r))) => (l * r).ok().map(Constant::Int), - (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int), - (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), - (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), - (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), - (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), - (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), - (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), - (BiBitAnd, Constant::Int(l), Some(Constant::Int(r))) => (l & r).ok().map(Constant::Int), - (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), - (BiBitOr, Constant::Int(l), Some(Constant::Int(r))) => (l | r).ok().map(Constant::Int), - (BiShl, Constant::Int(l), Some(Constant::Int(r))) => (l << r).ok().map(Constant::Int), - (BiShr, Constant::Int(l), Some(Constant::Int(r))) => (l >> r).ok().map(Constant::Int), - (BiEq, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l == r)), - (BiNe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l != r)), - (BiLt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l < r)), - (BiLe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l <= r)), - (BiGe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l >= r)), - (BiGt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l > r)), + match (l, r) { + (Constant::Int(l), Some(Constant::Int(r))) => { + match self.tables.expr_ty(left).sty { + ty::TyInt(ity) => { + let l = sext(self.tcx, l, ity); + let r = sext(self.tcx, r, ity); + let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); + match op.node { + BiAdd => l.checked_add(r).map(zext), + BiSub => l.checked_sub(r).map(zext), + BiMul => l.checked_mul(r).map(zext), + BiDiv if r != 0 => l.checked_div(r).map(zext), + BiRem if r != 0 => l.checked_rem(r).map(zext), + BiShr => l.checked_shr(r as u128 as u32).map(zext), + BiShl => l.checked_shl(r as u128 as u32).map(zext), + BiBitXor => Some(zext(l ^ r)), + BiBitOr => Some(zext(l | r)), + BiBitAnd => Some(zext(l & r)), + BiEq => Some(Constant::Bool(l == r)), + BiNe => Some(Constant::Bool(l != r)), + BiLt => Some(Constant::Bool(l < r)), + BiLe => Some(Constant::Bool(l <= r)), + BiGe => Some(Constant::Bool(l >= r)), + BiGt => Some(Constant::Bool(l > r)), + _ => None, + } + } + ty::TyUint(_) => { + match op.node { + BiAdd => l.checked_add(r).map(Constant::Int), + BiSub => l.checked_sub(r).map(Constant::Int), + BiMul => l.checked_mul(r).map(Constant::Int), + BiDiv => l.checked_div(r).map(Constant::Int), + BiRem => l.checked_rem(r).map(Constant::Int), + BiShr => l.checked_shr(r as u32).map(Constant::Int), + BiShl => l.checked_shl(r as u32).map(Constant::Int), + BiBitXor => Some(Constant::Int(l ^ r)), + BiBitOr => Some(Constant::Int(l | r)), + BiBitAnd => Some(Constant::Int(l & r)), + BiEq => Some(Constant::Bool(l == r)), + BiNe => Some(Constant::Bool(l != r)), + BiLt => Some(Constant::Bool(l < r)), + BiLe => Some(Constant::Bool(l <= r)), + BiGe => Some(Constant::Bool(l >= r)), + BiGt => Some(Constant::Bool(l > r)), + _ => None, + } + }, + _ => None, + } + }, + (Constant::F32(l), Some(Constant::F32(r))) => match op.node { + BiAdd => Some(Constant::F32(l + r)), + BiSub => Some(Constant::F32(l - r)), + BiMul => Some(Constant::F32(l * r)), + BiDiv => Some(Constant::F32(l / r)), + BiRem => Some(Constant::F32(l * r)), + BiEq => Some(Constant::Bool(l == r)), + BiNe => Some(Constant::Bool(l != r)), + BiLt => Some(Constant::Bool(l < r)), + BiLe => Some(Constant::Bool(l <= r)), + BiGe => Some(Constant::Bool(l >= r)), + BiGt => Some(Constant::Bool(l > r)), + _ => None, + }, + (Constant::F64(l), Some(Constant::F64(r))) => match op.node { + BiAdd => Some(Constant::F64(l + r)), + BiSub => Some(Constant::F64(l - r)), + BiMul => Some(Constant::F64(l * r)), + BiDiv => Some(Constant::F64(l / r)), + BiRem => Some(Constant::F64(l * r)), + BiEq => Some(Constant::Bool(l == r)), + BiNe => Some(Constant::Bool(l != r)), + BiLt => Some(Constant::Bool(l < r)), + BiLe => Some(Constant::Bool(l <= r)), + BiGe => Some(Constant::Bool(l >= r)), + BiGt => Some(Constant::Bool(l > r)), + _ => None, + }, + (l, r) => match (op.node, l, r) { + (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), + (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), + (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), + (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), + (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), + (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), + _ => None, + }, + } + } +} + +pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { + use rustc::mir::interpret::{Value, PrimVal}; + match result.val { + ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => match result.ty.sty { + ty::TyBool => Some(Constant::Bool(b == 1)), + ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)), + ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), + ty::TyFloat(FloatTy::F64) => Some(Constant::F64(f64::from_bits(b as u64))), + // FIXME: implement other conversion + _ => None, + }, + ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty { + ty::TyRef(_, tam) => match tam.ty.sty { + ty::TyStr => { + let alloc = tcx + .interpret_interner + .get_alloc(ptr.alloc_id) + .unwrap(); + let offset = ptr.offset as usize; + let n = n as usize; + String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str) + }, + _ => None, + }, _ => None, } + // FIXME: implement other conversions + _ => None, } } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index c65cf92590a..90ed34808a9 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -2,13 +2,14 @@ //! don't fit into an `i32` use rustc::lint::*; -use rustc::middle::const_val::ConstVal; -use rustc_const_math::*; use rustc::hir::*; -use rustc::ty; -use rustc::traits::Reveal; +use rustc::{ty, traits}; use rustc::ty::subst::Substs; +use syntax::ast::{IntTy, UintTy}; use utils::span_lint; +use consts::{Constant, miri_to_const}; +use rustc::ty::util::IntTypeExt; +use rustc::mir::interpret::GlobalId; /// **What it does:** Checks for C-like enumerations that are /// `repr(isize/usize)` and have values that don't fit into an `i32`. @@ -43,36 +44,46 @@ impl LintPass for UnportableVariant { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { #[allow(cast_possible_truncation, cast_sign_loss)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if cx.tcx.data_layout.pointer_size.bits() != 64 { + return; + } if let ItemEnum(ref def, _) = item.node { for var in &def.variants { let variant = &var.node; if let Some(body_id) = variant.disr_expr { - let expr = &cx.tcx.hir.body(body_id).value; + let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); let did = cx.tcx.hir.body_owner_def_id(body_id); - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); - let bad = match cx.tcx - .at(expr.span) - .const_eval(param_env.and((did, substs))) - { - Ok(&ty::Const { - val: ConstVal::Integral(Usize(Us64(i))), - .. - }) => u64::from(i as u32) != i, - Ok(&ty::Const { - val: ConstVal::Integral(Isize(Is64(i))), - .. - }) => i64::from(i as i32) != i, - _ => false, + let instance = ty::Instance::new(did, substs); + let cid = GlobalId { + instance, + promoted: None }; - if bad { + let constant = cx.tcx.const_eval(param_env.and(cid)).ok(); + if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { + let mut ty = cx.tcx.type_of(did); + if let ty::TyAdt(adt, _) = ty.sty { + if adt.is_enum() { + ty = adt.repr.discr_type().to_ty(cx.tcx); + } + } + match ty.sty { + ty::TyInt(IntTy::Isize) => { + let val = ((val as i128) << 64) >> 64; + if val <= i32::max_value() as i128 && val >= i32::min_value() as i128 { + continue; + } + } + ty::TyUint(UintTy::Usize) if val > u32::max_value() as u128 => {}, + _ => continue, + } span_lint( cx, ENUM_CLIKE_UNPORTABLE_VARIANT, var.span, "Clike enum variant discriminant is not portable to 32-bit targets", ); - } + }; } } } diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index dd8f029501f..a601d91a185 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { fn check(cx: &LateContext, e: &Expr, span: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { - if v.to_u128_unchecked() == 0 { + if v == 0 { span_lint( cx, ERASING_OP, diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index e1d84a07439..717245ec0f5 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,9 +1,9 @@ use consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; -use rustc_const_math::ConstInt; use syntax::codemap::Span; -use utils::{in_macro, snippet, span_lint}; +use utils::{in_macro, snippet, span_lint, unsext, clip}; +use rustc::ty; /// **What it does:** Checks for identity operations, e.g. `x + 0`. /// @@ -58,29 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } -fn all_ones(v: &ConstInt) -> bool { - match *v { - ConstInt::I8(i) => i == !0, - ConstInt::I16(i) => i == !0, - ConstInt::I32(i) => i == !0, - ConstInt::I64(i) => i == !0, - ConstInt::I128(i) => i == !0, - ConstInt::U8(i) => i == !0, - ConstInt::U16(i) => i == !0, - ConstInt::U32(i) => i == !0, - ConstInt::U64(i) => i == !0, - ConstInt::U128(i) => i == !0, - _ => false, - } -} - #[allow(cast_possible_wrap)] fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { + let check = match cx.tables.expr_ty(e).sty { + ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity), + ty::TyUint(uty) => clip(cx.tcx, !0, uty), + _ => return, + }; if match m { - 0 => v.to_u128_unchecked() == 0, - -1 => all_ones(&v), - 1 => v.to_u128_unchecked() == 1, + 0 => v == 0, + -1 => v == check, + 1 => v == 1, _ => unreachable!(), } { span_lint( diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1b8ff2dc05..0034e28fac2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -10,6 +10,7 @@ #![feature(conservative_impl_trait)] #![feature(inclusive_range_syntax, range_contains)] #![feature(macro_vis_matcher)] +#![feature(dotdoteq_in_patterns)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] @@ -37,7 +38,6 @@ extern crate regex_syntax; extern crate quine_mc_cluskey; -extern crate rustc_const_eval; extern crate rustc_const_math; extern crate rustc_errors; extern crate rustc_plugin; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f476b960d88..a0f3db7b784 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -6,23 +6,19 @@ use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; -use rustc::middle::const_val::ConstVal; use rustc::middle::region; // use rustc::middle::region::CodeExtent; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::cmt; use rustc::ty::{self, Ty}; -use rustc::ty::subst::{Subst, Substs}; -use rustc_const_eval::ConstContext; +use rustc::ty::subst::Subst; use std::collections::{HashMap, HashSet}; use std::iter::{once, Iterator}; use syntax::ast; use syntax::codemap::Span; -use utils::sugg; -use utils::const_to_u64; - -use consts::constant; +use utils::{sugg, sext}; +use consts::{constant, Constant}; use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, @@ -1113,27 +1109,22 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx }) = higher::range(arg) { // ...and both sides are compile-time constant integers... - let parent_item = cx.tcx.hir.get_parent(arg.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables); - if let Ok(start_idx) = constcx.eval(start) { - if let Ok(end_idx) = constcx.eval(end) { + if let Some((start_idx, _)) = constant(cx, start) { + if let Some((end_idx, _)) = constant(cx, end) { // ...and the start index is greater than the end index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the // smaller value. + let ty = cx.tables.expr_ty(start); let (sup, eq) = match (start_idx, end_idx) { ( - &ty::Const { - val: ConstVal::Integral(start_idx), - .. - }, - &ty::Const { - val: ConstVal::Integral(end_idx), - .. - }, - ) => (start_idx > end_idx, start_idx == end_idx), + Constant::Int(start_idx), + Constant::Int(end_idx), + ) => (match ty.sty { + ty::TyInt(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), + ty::TyUint(_) => start_idx > end_idx, + _ => false, + }, start_idx == end_idx), _ => (false, false), }; @@ -1220,7 +1211,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { match cx.tables.expr_ty(&args[0]).sty { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. - ty::TypeVariants::TyArray(_, size) if const_to_u64(size) > 32 => (), + ty::TypeVariants::TyArray(_, size) if size.val.to_raw_bits().expect("array size") > 32 => (), _ => lint_iter_method(cx, args, arg, method_name), }; } else { @@ -1795,7 +1786,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0..=32).contains(const_to_u64(n)), + ty::TyArray(_, n) => (0..=32).contains(n.val.to_raw_bits().expect("array length")), _ => false, } } @@ -2249,4 +2240,4 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { } fn decl_without_init(&mut self, _: NodeId, _: Span) {} -} \ No newline at end of file +} diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 979f0806e52..b617f098e3e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,19 +1,15 @@ use rustc::hir::*; use rustc::lint::*; -use rustc::middle::const_val::ConstVal; use rustc::ty::{self, Ty}; -use rustc::ty::subst::Substs; -use rustc_const_eval::ConstContext; -use rustc_const_math::ConstInt; use std::cmp::Ordering; use std::collections::Bound; use syntax::ast::LitKind; -use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use utils::sugg::Sugg; +use consts::{constant, Constant}; /// **What it does:** Checks for matches with a single arm where an `if let` /// will usually suffice. @@ -343,7 +339,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr, arms: &'tcx [Arm]) { if arms.len() >= 2 && cx.tables.expr_ty(ex).is_integral() { - let ranges = all_ranges(cx, arms, ex.id); + let ranges = all_ranges(cx, arms); let type_ranges = type_ranges(&ranges); if !type_ranges.is_empty() { if let Some((start, end)) = overlapping(&type_ranges) { @@ -460,12 +456,7 @@ fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn all_ranges<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm], - id: NodeId, -) -> Vec>> { - let parent_item = cx.tcx.hir.get_parent(id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables); +) -> Vec> { arms.iter() .flat_map(|arm| { if let Arm { @@ -478,25 +469,19 @@ fn all_ranges<'a, 'tcx>( } else { [].iter() }.filter_map(|pat| { - if_chain! { - if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node; - if let Ok(lhs) = constcx.eval(lhs); - if let Ok(rhs) = constcx.eval(rhs); - then { - let rhs = match *range_end { - RangeEnd::Included => Bound::Included(rhs), - RangeEnd::Excluded => Bound::Excluded(rhs), - }; - return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); - } + if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node { + let lhs = constant(cx, lhs)?.0; + let rhs = constant(cx, rhs)?.0; + let rhs = match *range_end { + RangeEnd::Included => Bound::Included(rhs), + RangeEnd::Excluded => Bound::Excluded(rhs), + }; + return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); } - if_chain! { - if let PatKind::Lit(ref value) = pat.node; - if let Ok(value) = constcx.eval(value); - then { - return Some(SpannedRange { span: pat.span, node: (value, Bound::Included(value)) }); - } + if let PatKind::Lit(ref value) = pat.node { + let value = constant(cx, value)?.0; + return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); } None @@ -511,46 +496,31 @@ pub struct SpannedRange { pub node: (T, Bound), } -type TypedRanges = Vec>; +type TypedRanges = Vec>; /// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway /// and other types than /// `Uint` and `Int` probably don't make sense. -fn type_ranges(ranges: &[SpannedRange<&ty::Const>]) -> TypedRanges { +fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { ( - &ty::Const { - val: ConstVal::Integral(start), - .. - }, - Bound::Included(&ty::Const { - val: ConstVal::Integral(end), - .. - }), + Constant::Int(start), + Bound::Included(Constant::Int(end)), ) => Some(SpannedRange { span: range.span, node: (start, Bound::Included(end)), }), ( - &ty::Const { - val: ConstVal::Integral(start), - .. - }, - Bound::Excluded(&ty::Const { - val: ConstVal::Integral(end), - .. - }), + Constant::Int(start), + Bound::Excluded(Constant::Int(end)), ) => Some(SpannedRange { span: range.span, node: (start, Bound::Excluded(end)), }), ( - &ty::Const { - val: ConstVal::Integral(start), - .. - }, + Constant::Int(start), Bound::Unbounded, ) => Some(SpannedRange { span: range.span, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 57d93b44328..0e55d0f8a3a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,10 +1,7 @@ use rustc::hir; use rustc::lint::*; -use rustc::middle::const_val::ConstVal; use rustc::ty::{self, Ty}; use rustc::hir::def::Def; -use rustc::ty::subst::Substs; -use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; use std::iter; @@ -16,7 +13,7 @@ use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; -use utils::const_to_u64; +use consts::{constant, Constant}; #[derive(Clone)] pub struct Pass; @@ -1302,7 +1299,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option true, ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::TyAdt(..) => match_type(cx, ty, &paths::VEC), - ty::TyArray(_, size) => const_to_u64(size) < 32, + ty::TyArray(_, size) => size.val.to_raw_bits().expect("array length") < 32, ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => may_slice(cx, inner), _ => false, } @@ -1754,14 +1751,7 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & /// lint for length-1 `str`s for methods in `PATTERN_METHODS` fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { - let parent_item = cx.tcx.hir.get_parent(arg.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if let Ok(&ty::Const { - val: ConstVal::Str(r), - .. - }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) - { + if let Some((Constant::Str(r), _)) = constant(cx, arg) { if r.len() == 1 { let c = r.chars().next().unwrap(); let snip = snippet(cx, expr.span, ".."); diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 04cc488d562..172de7a15a5 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -2,18 +2,14 @@ use reexport::*; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; -use rustc::middle::const_val::ConstVal; use rustc::ty; -use rustc::ty::subst::Substs; -use rustc_const_eval::ConstContext; -use rustc_const_math::ConstFloat; use syntax::codemap::{ExpnFormat, Span}; use utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; use utils::sugg::Sugg; -use syntax::ast::{FloatTy, LitKind, CRATE_NODE_ID}; -use consts::constant; +use syntax::ast::{LitKind, CRATE_NODE_ID}; +use consts::{constant, Constant}; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -457,58 +453,10 @@ fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> } fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { - let parent_item = cx.tcx.hir.get_parent(expr.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr); - if let Ok(&ty::Const { - val: ConstVal::Float(val), - .. - }) = res - { - use std::cmp::Ordering; - match val.ty { - FloatTy::F32 => { - let zero = ConstFloat { - ty: FloatTy::F32, - bits: u128::from(0.0_f32.to_bits()), - }; - - let infinity = ConstFloat { - ty: FloatTy::F32, - bits: u128::from(::std::f32::INFINITY.to_bits()), - }; - - let neg_infinity = ConstFloat { - ty: FloatTy::F32, - bits: u128::from(::std::f32::NEG_INFINITY.to_bits()), - }; - - val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) - || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) - }, - FloatTy::F64 => { - let zero = ConstFloat { - ty: FloatTy::F64, - bits: u128::from(0.0_f64.to_bits()), - }; - - let infinity = ConstFloat { - ty: FloatTy::F64, - bits: u128::from(::std::f64::INFINITY.to_bits()), - }; - - let neg_infinity = ConstFloat { - ty: FloatTy::F64, - bits: u128::from(::std::f64::NEG_INFINITY.to_bits()), - }; - - val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) - || val.try_cmp(neg_infinity) == Ok(Ordering::Equal) - }, - } - } else { - false + match constant(cx, expr) { + Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), + Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), + _ => false, } } diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index e34136face9..2ac195f555b 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -47,8 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { if_chain! { if let ExprLit(ref l) = lit.node; - if let Constant::Int(ref ci) = consts::lit_to_constant(&l.node, cx.tcx, cx.tables.expr_ty(lit)); - if let Some(val) = ci.to_u64(); + if let Constant::Int(val) = consts::lit_to_constant(&l.node, cx.tables.expr_ty(lit)); if val == 1; if cx.tables.expr_ty(exp).is_integral(); then { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 39252ceed1c..c98df6464d4 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -94,16 +94,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { use consts::{constant, Constant}; - use rustc_const_math::ConstInt::Usize; - if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) { - if us.as_u64() == 0 { - span_lint( - cx, - ITERATOR_STEP_BY_ZERO, - expr.span, - "Iterator::step_by(0) will panic at runtime", - ); - } + if let Some((Constant::Int(0), _)) = constant(cx, &args[1]) { + span_lint( + cx, + ITERATOR_STEP_BY_ZERO, + expr.span, + "Iterator::step_by(0) will panic at runtime", + ); } } else if name == "zip" && args.len() == 2 { let iter = &args[0].node; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index bbb70e0cdea..c0d7e84ffb8 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,16 +1,12 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::*; -use rustc::ty; -use rustc::middle::const_val::ConstVal; -use rustc_const_eval::ConstContext; -use rustc::ty::subst::Substs; use std::collections::HashSet; use std::error::Error; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; -use syntax::symbol::InternedString; use utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; +use consts::{constant, Constant}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -146,17 +142,11 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { } } -fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option { - let parent_item = cx.tcx.hir.get_parent(e.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(e) { - Ok(&ty::Const { - val: ConstVal::Str(r), - .. - }) => Some(r), +fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option { + constant(cx, e).and_then(|(c, _)| match c { + Constant::Str(s) => Some(s), _ => None, - } + }) } fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ba79bf4407b..0e9d8bdfefd 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -5,19 +5,18 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::layout::LayoutOf; -use rustc::ty::subst::Substs; use rustc_typeck::hir_ty_to_ty; use std::cmp::Ordering; use std::collections::BTreeMap; use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; -use syntax::attr::IntType; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then}; + span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; use utils::paths; +use consts::{constant, Constant}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -1298,58 +1297,20 @@ fn detect_absurd_comparison<'a, 'tcx>( } fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option> { - use rustc::middle::const_val::ConstVal::*; - use rustc_const_math::*; - use rustc_const_eval::*; use types::ExtremeType::*; let ty = cx.tables.expr_ty(expr); - match ty.sty { - ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (), - _ => return None, - }; + let cv = constant(cx, expr)?.0; - let parent_item = cx.tcx.hir.get_parent(expr.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - let cv = match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) { - Ok(val) => val, - Err(_) => return None, - }; + let which = match (&ty.sty, cv) { + (&ty::TyBool, Constant::Bool(false)) | + (&ty::TyUint(_), Constant::Int(0)) => Minimum, + (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum, - let which = match (&ty.sty, cv.val) { - (&ty::TyBool, Bool(false)) | - (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MIN)))) | - (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MIN)))) | - (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | - (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | - (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | - (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | - (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) | - (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MIN)))) | - (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MIN)))) | - (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | - (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | - (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | - (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) | - (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum, - - (&ty::TyBool, Bool(true)) | - (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MAX)))) | - (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MAX)))) | - (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | - (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | - (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | - (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | - (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) | - (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MAX)))) | - (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MAX)))) | - (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | - (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | - (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | - (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) | - (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MAX))) => Maximum, + (&ty::TyBool, Constant::Bool(true)) => Maximum, + (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum, + (&ty::TyUint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum, _ => return None, }; @@ -1524,24 +1485,16 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( } } -#[allow(cast_possible_wrap)] fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option { - use rustc::middle::const_val::ConstVal::*; - use rustc_const_eval::ConstContext; - - let parent_item = cx.tcx.hir.get_parent(expr.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) { - Ok(val) => if let Integral(const_int) = val.val { - match const_int.int_type() { - IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), - IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), - } - } else { - None - }, - Err(_) => None, + let val = constant(cx, expr)?.0; + if let Constant::Int(const_int) = val { + match cx.tables.expr_ty(expr).sty { + ty::TyInt(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), + ty::TyUint(_) => Some(FullInt::U(const_int)), + _ => None, + } + } else { + None } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2f2f0c04054..b171bdf4030 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,7 +8,7 @@ use rustc::hir::map::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, layout}; use rustc_errors; use std::borrow::Cow; use std::env; @@ -276,14 +276,6 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { } } -pub fn const_to_u64(c: &ty::Const) -> u64 { - c.val - .to_const_int() - .expect("eddyb says this works") - .to_u64() - .expect("see previous expect") -} - /// Convenience function to get the `DefId` of a trait by path. pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option { let def = match path_to_def(cx, path) { @@ -1071,3 +1063,26 @@ pub fn get_arg_name(pat: &Pat) -> Option { _ => None, } } + +pub fn int_bits(tcx: TyCtxt, ity: ast::IntTy) -> u64 { + layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() +} + +/// Turn a constant int byte representation into an i128 +pub fn sext(tcx: TyCtxt, u: u128, ity: ast::IntTy) -> i128 { + let amt = 128 - int_bits(tcx, ity); + ((u as i128) << amt) >> amt +} + +/// clip unused bytes +pub fn unsext(tcx: TyCtxt, u: i128, ity: ast::IntTy) -> u128 { + let amt = 128 - int_bits(tcx, ity); + ((u as u128) << amt) >> amt +} + +/// clip unused bytes +pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 { + let bits = layout::Integer::from_attr(tcx, attr::IntType::UnsignedInt(ity)).size().bits(); + let amt = 128 - bits; + (u << amt) >> amt +} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index e1c226466f9..4762c730683 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,10 +1,9 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty::{self, Ty}; -use rustc::ty::subst::Substs; -use rustc_const_eval::ConstContext; use syntax::codemap::Span; use utils::{higher, is_copy, snippet, span_lint_and_sugg}; +use consts::constant; /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would /// be possible. @@ -67,13 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { - let parent_item = cx.tcx.hir.get_parent(len.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_item); - let substs = Substs::identity_for_item(cx.tcx, parent_def_id); - if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables) - .eval(len) - .is_ok() - { + if constant(cx, len).is_some() { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")) } else { return; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index efe23bcdc47..416ee155174 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,4 +1,4 @@ -use consts::{constant_simple, Constant, FloatWidth}; +use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use utils::span_help_and_lint; @@ -37,16 +37,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - if let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(cx, left); - if let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(cx, right); - if Ok(0.0) == lhs_value.parse(); - if Ok(0.0) == rhs_value.parse(); + if let Some(lhs_value) = constant_simple(cx, left); + if let Some(rhs_value) = constant_simple(cx, right); + if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value; + if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value; then { // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, // match the precision of the literals that are given. - let float_type = match (lhs_width, rhs_width) { - (FloatWidth::F64, _) - | (_, FloatWidth::F64) => "f64", + let float_type = match (lhs_value, rhs_value) { + (Constant::F64(_), _) + | (_, Constant::F64(_)) => "f64", _ => "f32" }; span_help_and_lint( diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index a764403d039..df404a1eec3 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,70 +1,10 @@ -error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:43:5 - | -43 | ONE == 1f32; - | ^^^^^^^^^^^ help: consider comparing them within some error: `(ONE - 1f32).abs() < error` - | - = note: `-D float-cmp` implied by `-D warnings` -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:43:5 - | -43 | ONE == 1f32; - | ^^^^^^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:44:5 - | -44 | ONE == 1.0 + 0.0; - | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE - (1.0 + 0.0)).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:44:5 - | -44 | ONE == 1.0 + 0.0; - | ^^^^^^^^^^^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:45:5 - | -45 | ONE + ONE == ZERO + ONE + ONE; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - (ZERO + ONE + ONE)).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:45:5 - | -45 | ONE + ONE == ZERO + ONE + ONE; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:46:5 - | -46 | ONE != 2.0; - | ^^^^^^^^^^ help: consider comparing them within some error: `(ONE - 2.0).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:46:5 - | -46 | ONE != 2.0; - | ^^^^^^^^^^ - -error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:48:5 - | -48 | twice(ONE) != ONE; - | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(ONE) - ONE).abs() < error` - | -note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:48:5 - | -48 | twice(ONE) != ONE; - | ^^^^^^^^^^^^^^^^^ - error: strict comparison of f32 or f64 --> $DIR/float_cmp.rs:49:5 | 49 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | + = note: `-D float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp.rs:49:5 | @@ -95,5 +35,5 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. 57 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index a4f7b3c6761..28223563db1 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -10,5 +10,13 @@ help: use the values directly 13 | let foo = 5 - 6; | -error: aborting due to previous error +error: taken reference of right operand + --> $DIR/op_ref.rs:21:8 + | +21 | if b < &a { + | ^^^^-- + | | + | help: use the right value directly: `a` + +error: aborting due to 2 previous errors diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index b81e59c07f1..bc2a70beffd 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -13,7 +13,7 @@ error: constant division of 0.0 with 0.0 will always result in NaN | ^^^^^^^^^ | = note: `-D zero-divided-by-zero` implied by `-D warnings` - = help: Consider using `std::f32::NAN` if you would like a constant representing NaN + = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:8:19 -- cgit 1.4.1-3-g733a5 From 21f387d27810edd4ec135cc307dccc6d8e55d48b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 13 Mar 2018 15:02:40 +0100 Subject: Update dependencies --- .gitignore | 1 + Cargo.toml | 3 +- clippy_lints/Cargo.toml | 10 ++--- clippy_lints/src/regex.rs | 109 ++++++++++++++++++++++++++++++---------------- src/main.rs | 8 ++-- tests/compile-test.rs | 2 +- tests/ui/regex.stderr | 64 +++++++++++++++------------ tests/versioncheck.rs | 4 +- 8 files changed, 123 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index 43552238725..6f472c418d2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ out Cargo.lock /target /clippy_lints/target +/clippy_workspace_tests/target # Generated by dogfood /target_recur/ diff --git a/Cargo.toml b/Cargo.toml index efaa00acd66..a256be6085b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,9 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.187", path = "clippy_lints" } # end automatic update -cargo_metadata = "0.2" +cargo_metadata = "0.5" regex = "0.2" +semver = "0.9" [dev-dependencies] compiletest_rs = "0.3.7" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index cee48c1514d..f8c93c9d7ed 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -16,18 +16,18 @@ license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] [dependencies] -itertools = "0.6.0" +itertools = "0.7" lazy_static = "1.0" matches = "0.1.2" quine-mc_cluskey = "0.2.2" -regex-syntax = "0.4.0" -semver = "0.6.0" +regex-syntax = "0.5.0" +semver = "0.9.0" serde = "1.0" serde_derive = "1.0" toml = "0.4" unicode-normalization = "0.1" -pulldown-cmark = "0.0.15" -url = "1.5.0" +pulldown-cmark = "0.1" +url = "1.7.0" if_chain = "0.1" [features] diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index bbb70e0cdea..f2c08944f50 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -6,7 +6,6 @@ use rustc::middle::const_val::ConstVal; use rustc_const_eval::ConstContext; use rustc::ty::subst::Substs; use std::collections::HashSet; -use std::error::Error; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; @@ -134,16 +133,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -#[allow(cast_possible_truncation)] -fn str_span(base: Span, s: &str, c: usize) -> Span { - let mut si = s.char_indices().skip(c); - - match (si.next(), si.next()) { - (Some((l, _)), Some((h, _))) => { - Span::new(base.lo() + BytePos(l as u32), base.lo() + BytePos(h as u32), base.ctxt()) - }, - _ => base, - } +fn str_span(base: Span, c: regex_syntax::ast::Span, offset: usize) -> Span { + let offset = offset as u32; + let end = base.lo() + BytePos(c.end.offset as u32 + offset); + let start = base.lo() + BytePos(c.start.offset as u32 + offset); + assert!(start <= end); + Span::new(start, end, base.ctxt()) } fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option { @@ -159,24 +154,30 @@ fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option Option<&'static str> { - use regex_syntax::Expr; - - match *s { - Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), - Expr::Literal { .. } => Some("consider using `str::contains`"), - Expr::Concat(ref exprs) => match exprs.len() { - 2 => match (&exprs[0], &exprs[1]) { - (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), - (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), - _ => None, - }, - 3 => if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { - Some("consider using `==` on `str`s") - } else { - None - }, +fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { + use regex_syntax::hir::HirKind::*; + use regex_syntax::hir::Anchor::*; + + let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| match *e.kind() { + Literal(_) => true, + _ => false, + }); + + match *s.kind() { + Empty | + Anchor(_) => Some("the regex is unlikely to be useful as it is"), + Literal(_) => Some("consider using `str::contains`"), + Alternation(ref exprs) => if exprs.iter().all(|e| e.kind().is_empty()) { + Some("the regex is unlikely to be useful as it is") + } else { + None + }, + Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) { + (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => Some("consider using `str::is_empty`"), + (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `==` on `str`s"), + (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"), + (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `str::ends_with`"), + _ if is_literal(exprs) => Some("consider using `str::contains`"), _ => None, }, _ => None, @@ -196,41 +197,73 @@ fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) } fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { - let builder = regex_syntax::ExprBuilder::new().unicode(utf8); + let mut parser = regex_syntax::ParserBuilder::new().unicode(utf8).build(); if let ExprLit(ref lit) = expr.node { if let LitKind::Str(ref r, style) = lit.node { let r = &r.as_str(); - let offset = if let StrStyle::Raw(n) = style { 1 + n } else { 0 }; - match builder.parse(r) { + let offset = if let StrStyle::Raw(n) = style { 2 + n } else { 1 }; + match parser.parse(r) { Ok(r) => if let Some(repl) = is_trivial_regex(&r) { span_help_and_lint( cx, TRIVIAL_REGEX, expr.span, "trivial regex", - &format!("consider using {}", repl), + repl, + ); + }, + Err(regex_syntax::Error::Parse(e)) => { + span_lint( + cx, + INVALID_REGEX, + str_span(expr.span, *e.span(), offset), + &format!("regex syntax error: {}", e.kind()), + ); + }, + Err(regex_syntax::Error::Translate(e)) => { + span_lint( + cx, + INVALID_REGEX, + str_span(expr.span, *e.span(), offset), + &format!("regex syntax error: {}", e.kind()), ); }, Err(e) => { span_lint( cx, INVALID_REGEX, - str_span(expr.span, r, e.position() + offset), - &format!("regex syntax error: {}", e.description()), + expr.span, + &format!("regex syntax error: {}", e), ); }, } } } else if let Some(r) = const_str(cx, expr) { - match builder.parse(&r) { + match parser.parse(&r) { Ok(r) => if let Some(repl) = is_trivial_regex(&r) { span_help_and_lint( cx, TRIVIAL_REGEX, expr.span, "trivial regex", - &format!("consider using {}", repl), + repl, + ); + }, + Err(regex_syntax::Error::Parse(e)) => { + span_lint( + cx, + INVALID_REGEX, + expr.span, + &format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()), + ); + }, + Err(regex_syntax::Error::Translate(e)) => { + span_lint( + cx, + INVALID_REGEX, + expr.span, + &format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()), ); }, Err(e) => { @@ -238,7 +271,7 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo cx, INVALID_REGEX, expr.span, - &format!("regex syntax error on position {}: {}", e.position(), e.description()), + &format!("regex syntax error: {}", e), ); }, } diff --git a/src/main.rs b/src/main.rs index 8fd485b9efa..ab2b3b9a4a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ use std::io::{self, Write}; extern crate cargo_metadata; -use std::path::Path; +use std::path::{Path, PathBuf}; const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. @@ -61,17 +61,19 @@ pub fn main() { let manifest_path_arg = std::env::args() .skip(2) - .find(|val| val.starts_with("--manifest-path=")); + .find(|val| val.starts_with("--manifest-path=")) + .map(|val| val["--manifest-path=".len()..].to_owned()); let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { metadata } else { + println!("{:?}", cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref))); let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); process::exit(101); }; let manifest_path = manifest_path_arg.map(|arg| { - Path::new(&arg["--manifest-path=".len()..]) + PathBuf::from(arg) .canonicalize() .expect("manifest path could not be canonicalized") }); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5bf1bd5d13b..5e059084da8 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -68,7 +68,7 @@ fn run_mode(dir: &'static str, mode: &'static str) { fn prepare_env() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); set_var("CLIPPY_TESTS", "true"); - set_var("RUST_BACKTRACE", "0"); + //set_var("RUST_BACKTRACE", "0"); } #[test] diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 58c6e47afb7..45b2b7a2280 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,60 +1,67 @@ -error: regex syntax error: empty alternate +error: trivial regex --> $DIR/regex.rs:16:45 | 16 | let pipe_in_wrong_position = Regex::new("|"); | ^^^ | - = note: `-D invalid-regex` implied by `-D warnings` + = note: `-D trivial-regex` implied by `-D warnings` + = help: the regex is unlikely to be useful as it is -error: regex syntax error: empty alternate +error: trivial regex --> $DIR/regex.rs:17:60 | 17 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ + | + = help: the regex is unlikely to be useful as it is -error: regex syntax error: invalid character class range - --> $DIR/regex.rs:18:40 +error: regex syntax error: invalid character class range, the start must be <= the end + --> $DIR/regex.rs:18:42 | 18 | let wrong_char_ranice = Regex::new("[z-a]"); - | ^^^^^^^ + | ^^^ + | + = note: `-D invalid-regex` implied by `-D warnings` -error: regex syntax error: invalid character class range - --> $DIR/regex.rs:19:35 +error: regex syntax error: invalid character class range, the start must be <= the end + --> $DIR/regex.rs:19:37 | 19 | let some_unicode = Regex::new("[é-è]"); - | ^^^^^^^ + | ^^^ -error: regex syntax error on position 0: unclosed parenthesis +error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:21:33 | 21 | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ -error: regex syntax error: empty alternate +error: trivial regex --> $DIR/regex.rs:23:53 | 23 | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ + | + = help: the regex is unlikely to be useful as it is -error: regex syntax error on position 0: unclosed parenthesis +error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:24:41 | 24 | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ -error: regex syntax error on position 0: unclosed parenthesis +error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:25:56 | 25 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ -error: regex syntax error on position 0: unclosed parenthesis +error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:40:9 | 40 | OPENING_PAREN, | ^^^^^^^^^^^^^ -error: regex syntax error on position 0: unclosed parenthesis +error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:44:9 | 44 | OPENING_PAREN, @@ -64,13 +71,13 @@ error: regex syntax error: unrecognized escape sequence --> $DIR/regex.rs:48:45 | 48 | let raw_string_error = Regex::new(r"[...//...]"); - | ^ + | ^^ error: regex syntax error: unrecognized escape sequence --> $DIR/regex.rs:49:46 | 49 | let raw_string_error = Regex::new(r#"[...//...]"#); - | ^ + | ^^ error: trivial regex --> $DIR/regex.rs:53:33 @@ -78,8 +85,7 @@ error: trivial regex 53 | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | - = note: `-D trivial-regex` implied by `-D warnings` - = help: consider using consider using `==` on `str`s + = help: consider using `==` on `str`s error: trivial regex --> $DIR/regex.rs:55:48 @@ -87,7 +93,7 @@ error: trivial regex 55 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | - = help: consider using consider using `==` on `str`s + = help: consider using `==` on `str`s error: trivial regex --> $DIR/regex.rs:57:42 @@ -95,7 +101,7 @@ error: trivial regex 57 | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | - = help: consider using consider using `str::starts_with` + = help: consider using `str::starts_with` error: trivial regex --> $DIR/regex.rs:59:40 @@ -103,7 +109,7 @@ error: trivial regex 59 | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | - = help: consider using consider using `str::ends_with` + = help: consider using `str::ends_with` error: trivial regex --> $DIR/regex.rs:61:39 @@ -111,7 +117,7 @@ error: trivial regex 61 | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | - = help: consider using consider using `str::contains` + = help: consider using `str::contains` error: trivial regex --> $DIR/regex.rs:63:39 @@ -119,7 +125,7 @@ error: trivial regex 63 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | - = help: consider using consider using `str::contains` + = help: consider using `str::contains` error: trivial regex --> $DIR/regex.rs:65:40 @@ -127,7 +133,7 @@ error: trivial regex 65 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | - = help: consider using consider using `str::contains` + = help: consider using `str::contains` error: trivial regex --> $DIR/regex.rs:68:36 @@ -135,7 +141,7 @@ error: trivial regex 68 | let trivial_empty = Regex::new(""); | ^^ | - = help: consider using the regex is unlikely to be useful as it is + = help: the regex is unlikely to be useful as it is error: trivial regex --> $DIR/regex.rs:70:36 @@ -143,7 +149,7 @@ error: trivial regex 70 | let trivial_empty = Regex::new("^"); | ^^^ | - = help: consider using the regex is unlikely to be useful as it is + = help: the regex is unlikely to be useful as it is error: trivial regex --> $DIR/regex.rs:72:36 @@ -151,7 +157,7 @@ error: trivial regex 72 | let trivial_empty = Regex::new("^$"); | ^^^^ | - = help: consider using consider using `str::is_empty` + = help: consider using `str::is_empty` error: trivial regex --> $DIR/regex.rs:74:44 @@ -159,7 +165,7 @@ error: trivial regex 74 | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | - = help: consider using consider using `str::is_empty` + = help: consider using `str::is_empty` error: aborting due to 23 previous errors diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index beea9ab7e64..6fe82ac792e 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -1,4 +1,6 @@ extern crate cargo_metadata; +extern crate semver; +use semver::VersionReq; #[test] fn check_that_clippy_lints_has_the_same_version_as_clippy() { @@ -8,7 +10,7 @@ fn check_that_clippy_lints_has_the_same_version_as_clippy() { assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); for package in &clippy_meta.packages[0].dependencies { if package.name == "clippy_lints" { - assert_eq!(clippy_lints_meta.packages[0].version, package.req[1..]); + assert_eq!(VersionReq::parse(&clippy_lints_meta.packages[0].version).unwrap(), package.req); return; } } -- cgit 1.4.1-3-g733a5 From fd6542d0de58aee89b7bad77df89af584284b21a Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 15 Mar 2018 10:25:40 +0100 Subject: Rustup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 90ed34808a9..5da6457edd1 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { for var in &def.variants { let variant = &var.node; if let Some(body_id) = variant.disr_expr { - let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); let did = cx.tcx.hir.body_owner_def_id(body_id); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); let instance = ty::Instance::new(did, substs); diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 21a7542e6c7..ca9044c6e8b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -205,7 +205,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let sugg = |db: &mut DiagnosticBuilder| { if let ty::TypeVariants::TyAdt(ref def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { - let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); if param_env.can_type_implement_copy(cx.tcx, ty, span).is_ok() { db.span_help(span, "consider marking this type as Copy"); } -- cgit 1.4.1-3-g733a5 From ca785afc31315966548e74edf380d250ebb0361b Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 15 Mar 2018 10:25:57 +0100 Subject: Update tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- tests/ui/builtin-type-shadow.stderr | 2 +- tests/ui/conf_bad_arg.stderr | 2 +- tests/ui/conf_bad_toml.stderr | 2 +- tests/ui/conf_bad_type.stderr | 2 +- tests/ui/conf_french_blacklisted_name.stderr | 2 +- tests/ui/conf_path_non_string.stderr | 2 +- tests/ui/conf_unknown_key.stderr | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 85595fb0233..5757a6ef390 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -19,4 +19,4 @@ error[E0308]: mismatched types error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr index 30a87e23275..094b7d49cb5 100644 --- a/tests/ui/conf_bad_arg.stderr +++ b/tests/ui/conf_bad_arg.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr index f01b5605a51..640b1c5e610 100644 --- a/tests/ui/conf_bad_toml.stderr +++ b/tests/ui/conf_bad_toml.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr index ea9cf0acdd8..f92b52ec032 100644 --- a/tests/ui/conf_bad_type.stderr +++ b/tests/ui/conf_bad_type.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr index d09ae43301c..214226ac2f9 100644 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ b/tests/ui/conf_french_blacklisted_name.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr index 6af3b595921..10b007b0de0 100644 --- a/tests/ui/conf_path_non_string.stderr +++ b/tests/ui/conf_path_non_string.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr index 80a60bd8f2e..d7ac055c517 100644 --- a/tests/ui/conf_unknown_key.stderr +++ b/tests/ui/conf_unknown_key.stderr @@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5 -- cgit 1.4.1-3-g733a5 From a54e4661b72a1aba8ddf4570cc0c19320f8ad333 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 15 Mar 2018 13:24:51 +0100 Subject: Fix warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/enum_clike.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 5da6457edd1..3abd42d37c9 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::hir::*; -use rustc::{ty, traits}; +use rustc::ty; use rustc::ty::subst::Substs; use syntax::ast::{IntTy, UintTy}; use utils::span_lint; -- cgit 1.4.1-3-g733a5 From 874992797330c201aa17eda4fd36c1f0dbd5060a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 16 Mar 2018 09:44:20 +0100 Subject: Rustup --- CHANGELOG.md | 5 + Cargo.toml | 4 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/types.rs | 2 +- tests/ui/array_indexing.rs | 2 +- tests/ui/copies.rs | 2 - tests/ui/copies.stderr | 334 +++++++++++++++++------------------ tests/ui/for_loop.rs | 2 +- tests/ui/no_effect.rs | 2 +- tests/ui/range.rs | 3 - tests/ui/range.stderr | 24 +-- tests/ui/range_plus_minus_one.rs | 2 - tests/ui/range_plus_minus_one.stderr | 28 +-- tests/ui/redundant_field_names.rs | 2 +- 15 files changed, 207 insertions(+), 209 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dd1fdbf09a..970b458e2a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.188 +* Rustup to *rustc 1.26.0-nightly (392645394 2018-03-15)* +* New lint: [`while_immutable_condition`] + ## 0.0.187 * Rustup to *rustc 1.26.0-nightly (322d7f7b9 2018-02-25)* * New lints: [`redundant_field_names`], [`suspicious_arithmetic_impl`], [`suspicious_op_assign_impl`] @@ -777,6 +781,7 @@ All notable changes to this project will be documented in this file. [`useless_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_transmute [`useless_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_vec [`verbose_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#verbose_bit_mask +[`while_immutable_condition`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_on_iterator [`wrong_pub_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_pub_self_convention diff --git a/Cargo.toml b/Cargo.toml index a256be6085b..09eb34bf5fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.187" +version = "0.0.188" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.187", path = "clippy_lints" } +clippy_lints = { version = "0.0.188", path = "clippy_lints" } # end automatic update cargo_metadata = "0.5" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index f8c93c9d7ed..38b4a0ea18c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.187" +version = "0.0.188" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0034e28fac2..5272fb0a48e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -519,9 +519,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, loops::UNUSED_COLLECT, + loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, - loops::WHILE_IMMUTABLE_CONDITION, map_clone::MAP_CLONE, matches::MATCH_AS_REF, matches::MATCH_BOOL, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 0e9d8bdfefd..251f0c588e8 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -531,7 +531,7 @@ fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { fn is_unit(ty: Ty) -> bool { match ty.sty { - ty::TyTuple(slice, _) if slice.is_empty() => true, + ty::TyTuple(slice) if slice.is_empty() => true, _ => false, } } diff --git a/tests/ui/array_indexing.rs b/tests/ui/array_indexing.rs index faafa9a7a0d..a01600edac7 100644 --- a/tests/ui/array_indexing.rs +++ b/tests/ui/array_indexing.rs @@ -1,4 +1,4 @@ -#![feature(inclusive_range_syntax, plugin)] +#![feature(plugin)] #![warn(indexing_slicing)] diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 0588c141103..65a565c68ec 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,5 +1,3 @@ -#![feature(dotdoteq_in_patterns, inclusive_range_syntax)] - #![allow(blacklisted_name, collapsible_if, cyclomatic_complexity, eq_op, needless_continue, needless_return, never_loop, no_effect, zero_divided_by_zero)] diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 5faf41b51e3..cce63280ce1 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,384 +1,384 @@ error: this `if` has identical blocks - --> $DIR/copies.rs:31:10 + --> $DIR/copies.rs:29:10 | -31 | else { //~ ERROR same body as `if` block +29 | else { //~ ERROR same body as `if` block | __________^ -32 | | Foo { bar: 42 }; -33 | | 0..10; -34 | | ..; +30 | | Foo { bar: 42 }; +31 | | 0..10; +32 | | ..; ... | -38 | | foo(); -39 | | } +36 | | foo(); +37 | | } | |_____^ | = note: `-D if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:22:13 + --> $DIR/copies.rs:20:13 | -22 | if true { +20 | if true { | _____________^ -23 | | Foo { bar: 42 }; -24 | | 0..10; -25 | | ..; +21 | | Foo { bar: 42 }; +22 | | 0..10; +23 | | ..; ... | -29 | | foo(); -30 | | } +27 | | foo(); +28 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:80:14 + --> $DIR/copies.rs:78:14 | -80 | _ => { //~ ERROR match arms have same body +78 | _ => { //~ ERROR match arms have same body | ______________^ -81 | | foo(); -82 | | let mut a = 42 + [23].len() as i32; -83 | | if true { +79 | | foo(); +80 | | let mut a = 42 + [23].len() as i32; +81 | | if true { ... | -87 | | a -88 | | } +85 | | a +86 | | } | |_________^ | = note: `-D match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:71:15 + --> $DIR/copies.rs:69:15 | -71 | 42 => { +69 | 42 => { | _______________^ -72 | | foo(); -73 | | let mut a = 42 + [23].len() as i32; -74 | | if true { +70 | | foo(); +71 | | let mut a = 42 + [23].len() as i32; +72 | | if true { ... | -78 | | a -79 | | } +76 | | a +77 | | } | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:71:15 + --> $DIR/copies.rs:69:15 | -71 | 42 => { +69 | 42 => { | _______________^ -72 | | foo(); -73 | | let mut a = 42 + [23].len() as i32; -74 | | if true { +70 | | foo(); +71 | | let mut a = 42 + [23].len() as i32; +72 | | if true { ... | -78 | | a -79 | | } +76 | | a +77 | | } | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:94:14 + --> $DIR/copies.rs:92:14 | -94 | _ => 0, //~ ERROR match arms have same body +92 | _ => 0, //~ ERROR match arms have same body | ^ | note: same as this - --> $DIR/copies.rs:92:19 + --> $DIR/copies.rs:90:19 | -92 | Abc::A => 0, +90 | Abc::A => 0, | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:92:19 + --> $DIR/copies.rs:90:19 | -92 | Abc::A => 0, +90 | Abc::A => 0, | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:104:10 + --> $DIR/copies.rs:102:10 | -104 | else { //~ ERROR same body as `if` block +102 | else { //~ ERROR same body as `if` block | __________^ -105 | | 42 -106 | | }; +103 | | 42 +104 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:101:21 + --> $DIR/copies.rs:99:21 | -101 | let _ = if true { +99 | let _ = if true { | _____________________^ -102 | | 42 -103 | | } +100 | | 42 +101 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:118:10 + --> $DIR/copies.rs:116:10 | -118 | else { //~ ERROR same body as `if` block +116 | else { //~ ERROR same body as `if` block | __________^ -119 | | for _ in &[42] { -120 | | let foo: &Option<_> = &Some::(42); -121 | | if true { +117 | | for _ in &[42] { +118 | | let foo: &Option<_> = &Some::(42); +119 | | if true { ... | -126 | | } -127 | | } +124 | | } +125 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:108:13 + --> $DIR/copies.rs:106:13 | -108 | if true { +106 | if true { | _____________^ -109 | | for _ in &[42] { -110 | | let foo: &Option<_> = &Some::(42); -111 | | if true { +107 | | for _ in &[42] { +108 | | let foo: &Option<_> = &Some::(42); +109 | | if true { ... | -116 | | } -117 | | } +114 | | } +115 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:140:10 + --> $DIR/copies.rs:138:10 | -140 | else { //~ ERROR same body as `if` block +138 | else { //~ ERROR same body as `if` block | __________^ -141 | | let bar = if true { -142 | | 42 -143 | | } +139 | | let bar = if true { +140 | | 42 +141 | | } ... | -149 | | bar + 1; -150 | | } +147 | | bar + 1; +148 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:129:13 + --> $DIR/copies.rs:127:13 | -129 | if true { +127 | if true { | _____________^ -130 | | let bar = if true { -131 | | 42 -132 | | } +128 | | let bar = if true { +129 | | 42 +130 | | } ... | -138 | | bar + 1; -139 | | } +136 | | bar + 1; +137 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:175:10 + --> $DIR/copies.rs:173:10 | -175 | else { //~ ERROR same body as `if` block +173 | else { //~ ERROR same body as `if` block | __________^ -176 | | if let Some(a) = Some(42) {} -177 | | } +174 | | if let Some(a) = Some(42) {} +175 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:172:13 + --> $DIR/copies.rs:170:13 | -172 | if true { +170 | if true { | _____________^ -173 | | if let Some(a) = Some(42) {} -174 | | } +171 | | if let Some(a) = Some(42) {} +172 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:182:10 + --> $DIR/copies.rs:180:10 | -182 | else { //~ ERROR same body as `if` block +180 | else { //~ ERROR same body as `if` block | __________^ -183 | | if let (1, .., 3) = (1, 2, 3) {} -184 | | } +181 | | if let (1, .., 3) = (1, 2, 3) {} +182 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:179:13 + --> $DIR/copies.rs:177:13 | -179 | if true { +177 | if true { | _____________^ -180 | | if let (1, .., 3) = (1, 2, 3) {} -181 | | } +178 | | if let (1, .., 3) = (1, 2, 3) {} +179 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:237:15 + --> $DIR/copies.rs:235:15 | -237 | 51 => foo(), //~ ERROR match arms have same body +235 | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:236:15 + --> $DIR/copies.rs:234:15 | -236 | 42 => foo(), +234 | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:236:15 + --> $DIR/copies.rs:234:15 | -236 | 42 => foo(), +234 | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:243:17 + --> $DIR/copies.rs:241:17 | -243 | None => 24, //~ ERROR match arms have same body +241 | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:242:20 + --> $DIR/copies.rs:240:20 | -242 | Some(_) => 24, +240 | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:242:20 + --> $DIR/copies.rs:240:20 | -242 | Some(_) => 24, +240 | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:265:28 + --> $DIR/copies.rs:263:28 | -265 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +263 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:264:28 + --> $DIR/copies.rs:262:28 | -264 | (Some(a), None) => bar(a), +262 | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:264:28 + --> $DIR/copies.rs:262:28 | -264 | (Some(a), None) => bar(a), +262 | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:271:26 + --> $DIR/copies.rs:269:26 | -271 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +269 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:270:26 + --> $DIR/copies.rs:268:26 | -270 | (Some(a), ..) => bar(a), +268 | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:270:26 + --> $DIR/copies.rs:268:26 | -270 | (Some(a), ..) => bar(a), +268 | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:277:20 + --> $DIR/copies.rs:275:20 | -277 | (.., 3) => 42, //~ ERROR match arms have same body +275 | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:276:23 + --> $DIR/copies.rs:274:23 | -276 | (1, .., 3) => 42, +274 | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:276:23 + --> $DIR/copies.rs:274:23 | -276 | (1, .., 3) => 42, +274 | (1, .., 3) => 42, | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:283:12 + --> $DIR/copies.rs:281:12 | -283 | } else { //~ ERROR same body as `if` block +281 | } else { //~ ERROR same body as `if` block | ____________^ -284 | | 0.0 -285 | | }; +282 | | 0.0 +283 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:281:21 + --> $DIR/copies.rs:279:21 | -281 | let _ = if true { +279 | let _ = if true { | _____________________^ -282 | | 0.0 -283 | | } else { //~ ERROR same body as `if` block +280 | | 0.0 +281 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:289:12 + --> $DIR/copies.rs:287:12 | -289 | } else { //~ ERROR same body as `if` block +287 | } else { //~ ERROR same body as `if` block | ____________^ -290 | | -0.0 -291 | | }; +288 | | -0.0 +289 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:287:21 + --> $DIR/copies.rs:285:21 | -287 | let _ = if true { +285 | let _ = if true { | _____________________^ -288 | | -0.0 -289 | | } else { //~ ERROR same body as `if` block +286 | | -0.0 +287 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:309:12 + --> $DIR/copies.rs:307:12 | -309 | } else { //~ ERROR same body as `if` block +307 | } else { //~ ERROR same body as `if` block | ____________^ -310 | | std::f32::NAN -311 | | }; +308 | | std::f32::NAN +309 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:307:21 + --> $DIR/copies.rs:305:21 | -307 | let _ = if true { +305 | let _ = if true { | _____________________^ -308 | | std::f32::NAN -309 | | } else { //~ ERROR same body as `if` block +306 | | std::f32::NAN +307 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:327:10 + --> $DIR/copies.rs:325:10 | -327 | else { //~ ERROR same body as `if` block +325 | else { //~ ERROR same body as `if` block | __________^ -328 | | try!(Ok("foo")); -329 | | } +326 | | try!(Ok("foo")); +327 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:324:13 + --> $DIR/copies.rs:322:13 | -324 | if true { +322 | if true { | _____________^ -325 | | try!(Ok("foo")); -326 | | } +323 | | try!(Ok("foo")); +324 | | } | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:353:13 + --> $DIR/copies.rs:351:13 | -353 | else if b { //~ ERROR ifs same condition +351 | else if b { //~ ERROR ifs same condition | ^ | = note: `-D ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:351:8 + --> $DIR/copies.rs:349:8 | -351 | if b { +349 | if b { | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:13 + --> $DIR/copies.rs:356:13 | -358 | else if a == 1 { //~ ERROR ifs same condition +356 | else if a == 1 { //~ ERROR ifs same condition | ^^^^^^ | note: same as this - --> $DIR/copies.rs:356:8 + --> $DIR/copies.rs:354:8 | -356 | if a == 1 { +354 | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:365:13 + --> $DIR/copies.rs:363:13 | -365 | else if 2*a == 1 { //~ ERROR ifs same condition +363 | else if 2*a == 1 { //~ ERROR ifs same condition | ^^^^^^^^ | note: same as this - --> $DIR/copies.rs:361:8 + --> $DIR/copies.rs:359:8 | -361 | if 2*a == 1 { +359 | if 2*a == 1 { | ^^^^^^^^ error: aborting due to 20 previous errors diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 92f95e09d73..0a8be4d938b 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin, inclusive_range_syntax, custom_attribute)] +#![feature(plugin, custom_attribute)] use std::collections::*; diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index a782063e391..d1e4bf2a2c7 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,4 +1,4 @@ -#![feature(plugin, box_syntax, inclusive_range_syntax)] +#![feature(plugin, box_syntax)] #![warn(no_effect, unnecessary_operation)] diff --git a/tests/ui/range.rs b/tests/ui/range.rs index d9db28c8513..611a324f6e3 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,7 +1,4 @@ #![feature(iterator_step_by)] -#![feature(inclusive_range_syntax)] - - struct NotARange; impl NotARange { diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index fc51f1a07f0..064429c337c 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,41 +1,41 @@ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:13:13 + --> $DIR/range.rs:10:13 | -13 | let _ = (0..1).step_by(0); +10 | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ | = note: `-D iterator-step-by-zero` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:17:13 + --> $DIR/range.rs:14:13 | -17 | let _ = (1..).step_by(0); +14 | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:18:13 + --> $DIR/range.rs:15:13 | -18 | let _ = (1..=2).step_by(0); +15 | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:21:13 + --> $DIR/range.rs:18:13 | -21 | let _ = x.step_by(0); +18 | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: It is more idiomatic to use v1.iter().enumerate() - --> $DIR/range.rs:29:14 + --> $DIR/range.rs:26:14 | -29 | let _x = v1.iter().zip(0..v1.len()); +26 | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D range-zip-with-len` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:33:13 + --> $DIR/range.rs:30:13 | -33 | let _ = v1.iter().step_by(2/3); +30 | let _ = v1.iter().step_by(2/3); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index dce81634876..31574a4aeed 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,5 +1,3 @@ -#![feature(inclusive_range_syntax)] - fn f() -> usize { 42 } diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 80dfcddbe05..1990300ef90 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,47 +1,47 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:12:14 + --> $DIR/range_plus_minus_one.rs:10:14 | -12 | for _ in 0..3+1 { } +10 | for _ in 0..3+1 { } | ^^^^^^ help: use: `0..=3` | = note: `-D range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:15:14 + --> $DIR/range_plus_minus_one.rs:13:14 | -15 | for _ in 0..1+5 { } +13 | for _ in 0..1+5 { } | ^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:18:14 + --> $DIR/range_plus_minus_one.rs:16:14 | -18 | for _ in 1..1+1 { } +16 | for _ in 1..1+1 { } | ^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:24:14 + --> $DIR/range_plus_minus_one.rs:22:14 | -24 | for _ in 0..(1+f()) { } +22 | for _ in 0..(1+f()) { } | ^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:28:13 + --> $DIR/range_plus_minus_one.rs:26:13 | -28 | let _ = ..=11-1; +26 | let _ = ..=11-1; | ^^^^^^^ help: use: `..11` | = note: `-D range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:29:13 + --> $DIR/range_plus_minus_one.rs:27:13 | -29 | let _ = ..=(11-1); +27 | let _ = ..=(11-1); | ^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:30:13 + --> $DIR/range_plus_minus_one.rs:28:13 | -30 | let _ = (f()+1)..(f()+1); +28 | let _ = (f()+1)..(f()+1); | ^^^^^^^^^^^^^^^^ help: use: `(f()+1)..=f()` error: aborting due to 7 previous errors diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 98b6e16c450..a14f0ef40a0 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,6 +1,6 @@ #![warn(redundant_field_names)] #![allow(unused_variables)] -#![feature(inclusive_range, inclusive_range_syntax)] +#![feature(inclusive_range, inclusive_range_fields)] #[macro_use] extern crate derive_new; -- cgit 1.4.1-3-g733a5 From cfb9b982c539a7392030a78321187fa83eee9ad9 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 15 Mar 2018 16:07:15 +0100 Subject: Apply clippy suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/booleans.rs | 6 +++--- clippy_lints/src/consts.rs | 16 ++++++++-------- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/doc.rs | 4 ++-- clippy_lints/src/entry.rs | 18 +++++++++--------- clippy_lints/src/enum_clike.rs | 4 ++-- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 8 ++++---- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/inline_fn_without_body.rs | 7 ++----- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/let_if_seq.rs | 6 +++--- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/literal_representation.rs | 18 +++++++++--------- clippy_lints/src/loops.rs | 16 ++++++++-------- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/mut_mut.rs | 4 ++-- clippy_lints/src/needless_continue.rs | 4 ++-- clippy_lints/src/needless_pass_by_value.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 6 +++--- clippy_lints/src/ptr.rs | 23 ++++++++++------------- clippy_lints/src/question_mark.rs | 8 ++++---- clippy_lints/src/types.rs | 8 ++++---- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/use_self.rs | 4 ++-- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 4 ++-- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 4 ++-- 35 files changed, 101 insertions(+), 107 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index d285e71bd16..a3d9d5cbba8 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -202,9 +202,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { }; let mut visitor = ExprVisitor { - assignee: assignee, + assignee, counter: 0, - cx: cx + cx }; walk_expr(&mut visitor, e); @@ -253,7 +253,7 @@ struct ExprVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, &expr) { + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) { self.counter += 1; } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 7eb6477b269..8989c5ca8cf 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -96,7 +96,7 @@ pub struct BitMask { impl BitMask { pub fn new(verbose_bit_mask_threshold: u64) -> Self { Self { - verbose_bit_mask_threshold: verbose_bit_mask_threshold, + verbose_bit_mask_threshold, } } } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 114ba5fa782..dd5bf968bb3 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -28,7 +28,7 @@ pub struct BlackListedName { impl BlackListedName { pub fn new(blacklist: Vec) -> Self { Self { - blacklist: blacklist, + blacklist, } } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index a89959d9506..0afb8a73dfe 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { } else { let mut visitor = ExVisitor { found_block: None, - cx: cx, + cx, }; walk_expr(&mut visitor, check); if let Some(block) = visitor.found_block { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 50afd1b1e4f..cec569ec061 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { _: Span, _: NodeId, ) { - NonminimalBoolVisitor { cx: cx }.visit_body(body) + NonminimalBoolVisitor { cx }.visit_body(body) } } @@ -261,8 +261,8 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { // The boolean part of the return indicates whether some simplifications have been applied. fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { let mut suggest_context = SuggestContext { - terminals: terminals, - cx: cx, + terminals, + cx, output: String::new(), simplified: false, }; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 7c43cb668b3..af0cd8b35d4 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -73,7 +73,7 @@ impl PartialEq for Constant { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs - unsafe { mem::transmute::(l as f64) == mem::transmute::(r as f64) } + unsafe { mem::transmute::(f64::from(l)) == mem::transmute::(f64::from(r)) } }, (&Constant::Bool(l), &Constant::Bool(r)) => l == r, (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, @@ -102,7 +102,7 @@ impl Hash for Constant { i.hash(state); }, Constant::F32(f) => { - unsafe { mem::transmute::(f as f64) }.hash(state); + unsafe { mem::transmute::(f64::from(f)) }.hash(state); }, Constant::F64(f) => { unsafe { mem::transmute::(f) }.hash(state); @@ -143,12 +143,12 @@ impl PartialOrd for Constant { } /// parse a `LitKind` to a `Constant` -pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { +pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { use syntax::ast::*; match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), - LitKind::Byte(b) => Constant::Int(b as u128), + LitKind::Byte(b) => Constant::Int(u128::from(b)), LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), @@ -177,7 +177,7 @@ pub fn constant_simple(lcx: &LateContext, e: &Expr) -> Option { constant(lcx, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } -/// Creates a ConstEvalLateContext from the given LateContext and TypeckTables +/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables` pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'cc ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> { ConstEvalLateContext { tcx: lcx.tcx, @@ -215,7 +215,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }, ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op { UnNot => self.constant_not(&o, self.tables.expr_ty(e)), - UnNeg => self.constant_negate(o, self.tables.expr_ty(e)), + UnNeg => self.constant_negate(&o, self.tables.expr_ty(e)), UnDeref => Some(o), }), ExprBinary(op, ref left, ref right) => self.binop(op, left, right), @@ -240,9 +240,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } - fn constant_negate(&self, o: Constant, ty: ty::Ty) -> Option { + fn constant_negate(&self, o: &Constant, ty: ty::Ty) -> Option { use self::Constant::*; - match o { + match *o { Int(value) => { let ity = match ty.sty { ty::TyInt(ity) => ity, diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index ede9dcb1fbd..751fc13292c 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -63,7 +63,7 @@ impl CyclomaticComplexity { divergence: 0, short_circuits: 0, returns: 0, - cx: cx, + cx, }; helper.visit_expr(expr); let CCHelper { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index ea8ecb91d0a..3e2c56f5fb9 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -39,7 +39,7 @@ pub struct Doc { impl Doc { pub fn new(valid_idents: Vec) -> Self { Self { - valid_idents: valid_idents, + valid_idents, } } } @@ -66,7 +66,7 @@ struct Parser<'a> { impl<'a> Parser<'a> { fn new(parser: pulldown_cmark::Parser<'a>) -> Self { - Self { parser: parser } + Self { parser } } } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index b86a4a43fb1..aeae5fc6ced 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -55,12 +55,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { }; let mut visitor = InsertVisitor { - cx: cx, + cx, span: expr.span, - ty: ty, - map: map, - key: key, - sole_expr: sole_expr, + ty, + map, + key, + sole_expr, }; walk_expr(&mut visitor, &**then_block); @@ -68,11 +68,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { } else if let Some(ref else_block) = *else_block { if let Some((ty, map, key)) = check_cond(cx, check) { let mut visitor = InsertVisitor { - cx: cx, + cx, span: expr.span, - ty: ty, - map: map, - key: key, + ty, + map, + key, sole_expr: false, }; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 3abd42d37c9..f1572043024 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -70,11 +70,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { match ty.sty { ty::TyInt(IntTy::Isize) => { let val = ((val as i128) << 64) >> 64; - if val <= i32::max_value() as i128 && val >= i32::min_value() as i128 { + if val <= i128::from(i32::max_value()) && val >= i128::from(i32::min_value()) { continue; } } - ty::TyUint(UintTy::Usize) if val > u32::max_value() as u128 => {}, + ty::TyUint(UintTy::Usize) if val > u128::from(u32::max_value()) => {}, _ => continue, } span_lint( diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index b72949a7381..4a5dc1cc286 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -107,7 +107,7 @@ impl EnumVariantNames { pub fn new(threshold: u64) -> Self { Self { modules: Vec::new(), - threshold: threshold, + threshold, } } } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index d4c91eab1c3..8cd0aaee9af 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ) { let fn_def_id = cx.tcx.hir.local_def_id(node_id); let mut v = EscapeDelegate { - cx: cx, + cx, set: NodeSet(), too_large_for_stack: self.too_large_for_stack, }; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 847aec41500..1ca15e4d24f 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -67,8 +67,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { if path.segments.len() == 1 { if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) { let mut visitor = ReadVisitor { - cx: cx, - var: var, + cx, + var, write_expr: expr, last_expr: expr, }; @@ -82,13 +82,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { - StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e), + StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), StmtDecl(ref d, _) => if let DeclLocal(ref local) = d.node { if let Local { init: Some(ref e), .. } = **local { - DivergenceVisitor { cx: cx }.visit_expr(e); + DivergenceVisitor { cx }.visit_expr(e); } }, } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 3df037f3329..4bf4aafcc4e 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -62,7 +62,7 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64) -> Self { Self { - threshold: threshold, + threshold, } } } @@ -156,7 +156,7 @@ impl<'a, 'tcx> Functions { if !raw_ptrs.is_empty() { let tables = cx.tcx.body_tables(body.id()); let mut v = DerefVisitor { - cx: cx, + cx, ptrs: raw_ptrs, tables, }; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 1bb9519d304..99b7812472a 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -37,11 +37,8 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - match item.node { - TraitItemKind::Method(_, TraitMethod::Required(_)) => { - check_attrs(cx, &item.name, &item.attrs); - }, - _ => {}, + if let TraitItemKind::Method(_, TraitMethod::Required(_)) = item.node { + check_attrs(cx, &item.name, &item.attrs); } } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index e13b771cf24..668e8e992ec 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -35,7 +35,7 @@ pub struct LargeEnumVariant { impl LargeEnumVariant { pub fn new(maximum_size_difference_allowed: u64) -> Self { Self { - maximum_size_difference_allowed: maximum_size_difference_allowed, + maximum_size_difference_allowed, } } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 34863208fde..257f619ec29 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -170,7 +170,7 @@ fn check_assign<'a, 'tcx>( if decl == local_id; then { let mut v = UsedVisitor { - cx: cx, + cx, id: decl, used: false, }; @@ -192,8 +192,8 @@ fn check_assign<'a, 'tcx>( fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: ast::NodeId, expr: &'tcx hir::Expr) -> bool { let mut v = UsedVisitor { - cx: cx, - id: id, + cx, + id, used: false, }; hir::intravisit::walk_expr(&mut v, expr); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 567b06a8ac1..f2381cc39eb 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -261,7 +261,7 @@ struct RefVisitor<'a, 'tcx: 'a> { impl<'v, 't> RefVisitor<'v, 't> { fn new(cx: &'v LateContext<'v, 't>) -> Self { Self { - cx: cx, + cx, lts: Vec::new(), abort: false, } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index c534ef327c2..b505a4c30a5 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -138,11 +138,11 @@ impl<'a> DigitInfo<'a> { let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; let (digits, suffix) = sans_prefix.split_at(suffix_start); return Self { - digits: digits, - radix: radix, - prefix: prefix, + digits, + radix, + prefix, suffix: Some(suffix), - float: float, + float, }; } last_d = d @@ -151,10 +151,10 @@ impl<'a> DigitInfo<'a> { // No suffix found Self { digits: sans_prefix, - radix: radix, - prefix: prefix, + radix, + prefix, suffix: None, - float: float, + float, } } @@ -426,7 +426,7 @@ impl EarlyLintPass for LiteralRepresentation { impl LiteralRepresentation { pub fn new(threshold: u64) -> Self { Self { - threshold: threshold, + threshold, } } fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { @@ -444,7 +444,7 @@ impl LiteralRepresentation { .filter(|&c| c != '_') .collect::() .parse::().unwrap(); - if val < self.threshold as u128 { + if val < u128::from(self.threshold) { return } let hex = format!("{:#X}", val); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a0f3db7b784..7bf814afa3d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -975,7 +975,7 @@ fn check_for_loop_range<'a, 'tcx>( // the var must be a single name if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { let mut visitor = VarVisitor { - cx: cx, + cx, var: canonical_id, indexed_mut: HashSet::new(), indexed_indirectly: HashMap::new(), @@ -1289,7 +1289,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( ) { // Look for variables that are incremented once per loop iteration. let mut visitor = IncrementVisitor { - cx: cx, + cx, states: HashMap::new(), depth: 0, done: false, @@ -1309,7 +1309,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( .filter(|&(_, v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { - cx: cx, + cx, end_expr: expr, var_id: *id, state: VarState::IncrOnce, @@ -1728,8 +1728,8 @@ fn is_iterator_used_after_while_let<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, it None => return false, }; let mut visitor = VarUsedAfterLoopVisitor { - cx: cx, - def_id: def_id, + cx, + def_id, iter_expr_id: iter_expr.id, past_while_let: false, var_used_after_while_let: false, @@ -2048,7 +2048,7 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { - id: id, + id, iterator: iter_name, nesting: Unknown, }; @@ -2189,7 +2189,7 @@ struct MutableVarsVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { - ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, &ex) { + ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) { self.ids.insert(node_id, None); }, @@ -2213,7 +2213,7 @@ struct MutVarsDelegate { impl<'tcx> MutVarsDelegate { fn update(&mut self, cat: &'tcx Categorization, sp: Span) { - if let &Categorization::Local(id) = cat { + if let Categorization::Local(id) = *cat { if let Some(span) = self.mut_spans.get_mut(&id) { *span = Some(sp) } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 0e55d0f8a3a..2c401bd4994 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -760,7 +760,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }, hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { let mut info = BinaryExprInfo { - expr: expr, + expr, chain: lhs, other: rhs, eq: op.node == hir::BiEq, diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index c12d3dde2be..ca1592271b3 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -33,13 +33,13 @@ impl LintPass for MutMut { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) { - intravisit::walk_block(&mut MutVisitor { cx: cx }, block); + intravisit::walk_block(&mut MutVisitor { cx }, block); } fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty) { use rustc::hir::intravisit::Visitor; - MutVisitor { cx: cx }.visit_ty(ty); + MutVisitor { cx }.visit_ty(ty); } } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index ccf9c62d93c..9c801ba7495 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -337,10 +337,10 @@ fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) { with_if_expr(stmt, |if_expr, cond, then_block, else_expr| { let data = &LintData { stmt_idx: i, - if_expr: if_expr, + if_expr, if_cond: cond, if_block: then_block, - else_expr: else_expr, + else_expr, block_stmts: &loop_block.stmts, }; if needless_continue_in_else(else_expr) { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ca9044c6e8b..b189fcbff4f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder| { - if let ty::TypeVariants::TyAdt(ref def, ..) = ty.sty { + if let ty::TypeVariants::TyAdt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { let param_env = ty::ParamEnv::empty(); if param_env.can_type_implement_copy(cx.tcx, ty, span).is_ok() { @@ -307,7 +307,7 @@ struct MovedVariablesCtxt<'a, 'tcx: 'a> { impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { Self { - cx: cx, + cx, moved_vars: HashSet::new(), spans_need_deref: HashMap::new(), } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 9ef55907ecd..a267900fcbb 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -267,7 +267,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { self.0.names.push(ExistingName { whitelist: get_whitelist(&interned_name).unwrap_or(&[]), interned: interned_name, - span: span, + span, len: count, }); } @@ -329,8 +329,8 @@ fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext, attrs: &[Attribute if !attr::contains_name(attrs, "test") { let mut visitor = SimilarNamesLocalVisitor { names: Vec::new(), - cx: cx, - lint: lint, + cx, + lint, single_char_names: Vec::new(), }; // initialize with function arguments diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 139b5883fb0..435812bf962 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -225,19 +225,16 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if let [ref inner] = *params.types; then { let replacement = snippet_opt(cx, inner.span); - match replacement { - Some(r) => { - span_lint_and_then( - cx, - PTR_ARG, - arg.span, - "using a reference to `Cow` is not recommended.", - |db| { - db.span_suggestion(arg.span, "change this to", "&".to_owned() + &r); - }, - ); - }, - None => (), + if let Some(r) = replacement { + span_lint_and_then( + cx, + PTR_ARG, + arg.span, + "using a reference to `Cow` is not recommended.", + |db| { + db.span_suggestion(arg.span, "change this to", "&".to_owned() + &r); + }, + ); } } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 4c01899936b..39fcc2b1b8f 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -55,7 +55,7 @@ impl QuestionMarkPass { if let ExprIf(ref if_expr, ref body, _) = expr.node; if let ExprMethodCall(ref segment, _, ref args) = if_expr.node; if segment.name == "is_none"; - if Self::expression_returns_none(cx, &body); + if Self::expression_returns_none(cx, body); if let Some(subject) = args.get(0); if Self::is_option(cx, subject); @@ -64,7 +64,7 @@ impl QuestionMarkPass { cx, QUESTION_MARK, expr.span, - &format!("this block may be rewritten with the `?` operator"), + "this block may be rewritten with the `?` operator", |db| { let receiver_str = &Sugg::hir(cx, subject, ".."); @@ -82,7 +82,7 @@ impl QuestionMarkPass { fn is_option(cx: &LateContext, expression: &Expr) -> bool { let expr_ty = cx.tables.expr_ty(expression); - return match_type(cx, expr_ty, &OPTION); + match_type(cx, expr_ty, &OPTION) } fn expression_returns_none(cx: &LateContext, expression: &Expr) -> bool { @@ -127,7 +127,7 @@ impl QuestionMarkPass { return Some(ret_expr.clone()); } - return None; + None } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 251f0c588e8..82a1799ffd8 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -985,7 +985,7 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { Self { - threshold: threshold, + threshold, } } } @@ -1241,7 +1241,7 @@ fn is_cast_between_fixed_and_target<'a, 'tcx>( return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty) } - return false; + false } fn detect_absurd_comparison<'a, 'tcx>( @@ -1315,8 +1315,8 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - _ => return None, }; Some(ExtremeExpr { - which: which, - expr: expr, + which, + expr, }) } diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 37e7c5e3bd4..ee708eb13ae 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { } let mut v = UnusedLabelVisitor { - cx: cx, + cx, labels: HashMap::new(), }; walk_fn(&mut v, kind, decl, body.id(), span, fn_id); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 8203377e465..a1390596cda 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -66,8 +66,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { }; if should_check { let visitor = &mut UseSelfVisitor { - item_path: item_path, - cx: cx, + item_path, + cx, }; for impl_item_ref in refs { visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index beae98f81f6..44e5e84c4a0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -274,7 +274,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { if let Ty_::TyPath(ref qp) = ty.node { println!(" if let Ty_::TyPath(ref {}) = {}.node;", qp_label, cast_ty); self.current = qp_label; - self.print_qpath(&qp); + self.print_qpath(qp); } self.current = cast_pat; self.visit_expr(expr); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index cad6ec532a6..e790184a7ab 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -24,7 +24,7 @@ pub struct SpanlessEq<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { Self { - cx: cx, + cx, ignore_fn: false, } } @@ -295,7 +295,7 @@ pub struct SpanlessHash<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { Self { - cx: cx, + cx, s: DefaultHasher::new(), } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 6e62f96749e..625ef63a3dc 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { } else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" { let mut collector = LintCollector { output: &mut self.registered_lints, - cx: cx, + cx, }; collector.visit_expr(&cx.tcx.hir.body(body_id).value); } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b171bdf4030..125602319f7 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -390,7 +390,7 @@ impl<'tcx> Visitor<'tcx> for ContainsName { /// check if an `Expr` contains a certain name pub fn contains_name(name: Name, expr: &Expr) -> bool { let mut cn = ContainsName { - name: name, + name, result: false, }; cn.visit_expr(expr); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index e18c1274498..4ca6e5cbf73 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -220,8 +220,8 @@ impl ParenHelper { /// Build a `ParenHelper`. fn new(paren: bool, wrapped: T) -> Self { Self { - paren: paren, - wrapped: wrapped, + paren, + wrapped, } } } -- cgit 1.4.1-3-g733a5 From 23bfa396a05564fb8e16db26bf5eb3c8d7e909b8 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 15 Mar 2018 16:08:49 +0100 Subject: Format code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- src/driver.rs | 4 +--- src/main.rs | 5 ++++- tests/compile-test.rs | 7 +++++-- tests/dogfood.rs | 9 ++++++--- tests/matches.rs | 13 +++++++------ tests/needless_continue_helpers.rs | 1 - tests/versioncheck.rs | 10 ++++++++-- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 7b7167cef70..78bccb74ab9 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -193,7 +193,5 @@ pub fn main() { } let mut ccc = ClippyCompilerCalls::new(clippy_enabled); - rustc_driver::run(move || { - rustc_driver::run_compiler(&args, &mut ccc, None, None) - }); + rustc_driver::run(move || rustc_driver::run_compiler(&args, &mut ccc, None, None)); } diff --git a/src/main.rs b/src/main.rs index ab2b3b9a4a0..95e1fc0c28c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,7 +67,10 @@ pub fn main() { let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { metadata } else { - println!("{:?}", cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref))); + println!( + "{:?}", + cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) + ); let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); process::exit(101); }; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5e059084da8..9b9820f2b52 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,7 +3,7 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::path::{PathBuf, Path}; +use std::path::{Path, PathBuf}; use std::env::{set_var, var}; fn clippy_driver_path() -> PathBuf { @@ -43,7 +43,10 @@ fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); + config.target_rustcflags = Some(format!( + "-L {0} -L {0}/deps -Dwarnings", + host_libs().display() + )); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 590027f8491..ed6451a3eb6 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -11,9 +11,12 @@ fn dogfood() { std::env::set_current_dir(root_dir.join(d)).unwrap(); let output = std::process::Command::new("cargo") .arg("run") - .arg("--bin").arg("cargo-clippy") - .arg("--manifest-path").arg(root_dir.join("Cargo.toml")) - .output().unwrap(); + .arg("--bin") + .arg("cargo-clippy") + .arg("--manifest-path") + .arg(root_dir.join("Cargo.toml")) + .output() + .unwrap(); println!("status: {}", output.status); println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); diff --git a/tests/matches.rs b/tests/matches.rs index 42d1154bf1a..8dfb8e42d6f 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -9,16 +9,17 @@ fn test_overlapping() { use clippy_lints::matches::overlapping; use syntax::codemap::DUMMY_SP; - let sp = |s, e| { - clippy_lints::matches::SpannedRange { - span: DUMMY_SP, - node: (s, e), - } + let sp = |s, e| clippy_lints::matches::SpannedRange { + span: DUMMY_SP, + node: (s, e), }; assert_eq!(None, overlapping::(&[])); assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))])); - assert_eq!(None, overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])); + assert_eq!( + None, + overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))]) + ); assert_eq!( None, overlapping(&[ diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 853f64b4698..588dc741d03 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -69,7 +69,6 @@ fn test_erode_from_front_no_brace() { assert_eq!(expected, got); } - #[test] #[cfg_attr(rustfmt, rustfmt_skip)] fn test_erode_block() { diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 6fe82ac792e..ff4af08a8a0 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -7,10 +7,16 @@ fn check_that_clippy_lints_has_the_same_version_as_clippy() { let clippy_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); let clippy_lints_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); - assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); + assert_eq!( + clippy_lints_meta.packages[0].version, + clippy_meta.packages[0].version + ); for package in &clippy_meta.packages[0].dependencies { if package.name == "clippy_lints" { - assert_eq!(VersionReq::parse(&clippy_lints_meta.packages[0].version).unwrap(), package.req); + assert_eq!( + VersionReq::parse(&clippy_lints_meta.packages[0].version).unwrap(), + package.req + ); return; } } -- cgit 1.4.1-3-g733a5 From 4c94dd238f9b5d6a186398fd51854937451e0656 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Fri, 16 Mar 2018 10:47:28 +0100 Subject: Fix BiRem for floats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index af0cd8b35d4..7ed2ac752e5 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -377,7 +377,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiSub => Some(Constant::F32(l - r)), BiMul => Some(Constant::F32(l * r)), BiDiv => Some(Constant::F32(l / r)), - BiRem => Some(Constant::F32(l * r)), + BiRem => Some(Constant::F32(l % r)), BiEq => Some(Constant::Bool(l == r)), BiNe => Some(Constant::Bool(l != r)), BiLt => Some(Constant::Bool(l < r)), @@ -391,7 +391,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BiSub => Some(Constant::F64(l - r)), BiMul => Some(Constant::F64(l * r)), BiDiv => Some(Constant::F64(l / r)), - BiRem => Some(Constant::F64(l * r)), + BiRem => Some(Constant::F64(l % r)), BiEq => Some(Constant::Bool(l == r)), BiNe => Some(Constant::Bool(l != r)), BiLt => Some(Constant::Bool(l < r)), -- cgit 1.4.1-3-g733a5 From c7770bf907222c0874c56d96a202a76b1df183fa Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Fri, 16 Mar 2018 11:09:05 +0100 Subject: Remove attributes for stable features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5272fb0a48e..d508a17a264 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,9 +8,8 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] -#![feature(inclusive_range_syntax, range_contains)] +#![feature(range_contains)] #![feature(macro_vis_matcher)] -#![feature(dotdoteq_in_patterns)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] -- cgit 1.4.1-3-g733a5 From 3b387eaabed1ed47503f44fd9fd54979b4024b64 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Fri, 16 Mar 2018 11:36:14 +0100 Subject: Allow float_cmp in consts lint code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mateusz Mikuła --- clippy_lints/src/consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 7ed2ac752e5..675342645b8 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,4 +1,5 @@ #![allow(cast_possible_truncation)] +#![allow(float_cmp)] use rustc::lint::LateContext; use rustc::hir::def::Def; -- cgit 1.4.1-3-g733a5 From 4fdc81dd7a3fb6a563c22d37db72b991cdbb403d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 17 Mar 2018 20:35:20 +0100 Subject: Check if the panic message was created by the assert-macro --- clippy_lints/src/panic.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 9430e59ac86..a768565518c 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -48,6 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(par) = string.as_str().find('{'); if string.as_str()[par..].contains('}'); if params[0].span.source_callee().is_none(); + if params[0].span.lo() != params[0].span.hi(); then { span_lint(cx, PANIC_PARAMS, params[0].span, "you probably are missing some parameter in your format string"); -- cgit 1.4.1-3-g733a5 From ad459184a311e4764072bec33f5cef95b63b838c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 17 Mar 2018 21:34:13 +0100 Subject: Don't lint comparison operators in arithmetic impls --- clippy_lints/src/suspicious_trait_impl.rs | 4 ++++ tests/ui/suspicious_arithmetic_impl.rs | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index ecf8e83a86f..2c3abc512bb 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -61,6 +61,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { use rustc::hir::BinOp_::*; if let hir::ExprBinary(binop, _, _) = expr.node { + match binop.node { + BiEq | BiLt | BiLe | BiNe | BiGe | BiGt => return, + _ => {}, + } // Check if the binary expression is part of another bi/unary expression // as a child node let mut parent_expr = cx.tcx.hir.get_parent_node(expr.id); diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 22233a4b154..d5982efe12f 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -59,7 +59,11 @@ impl Sub for Bar { type Output = Bar; fn sub(self, other: Self) -> Self { - Bar(-(self.0 & other.0)) // OK: UnNeg part of BiExpr as parent node + if self.0 <= other.0 { + Bar(-(self.0 & other.0)) // OK: UnNeg part of BiExpr as parent node + } else { + Bar(0) + } } } -- cgit 1.4.1-3-g733a5 From 4edd140e57cce900fa930e1439bab469f5bbce46 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 18 Mar 2018 13:26:57 +0100 Subject: Rustup --- clippy_lints/src/unsafe_removed_from_name.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 637df96180a..a238a9b9283 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -43,7 +43,7 @@ impl EarlyLintPass for UnsafeNameRemoval { fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { match use_tree.kind { - UseTreeKind::Simple(new_name) => { + UseTreeKind::Simple(Some(new_name)) => { let old_name = use_tree .prefix .segments @@ -52,6 +52,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { .identifier; unsafe_to_safe_check(old_name, new_name, cx, span); } + UseTreeKind::Simple(None) | UseTreeKind::Glob => {}, UseTreeKind::Nested(ref nested_use_tree) => { for &(ref use_tree, _) in nested_use_tree { -- cgit 1.4.1-3-g733a5 From 0fc1d8874c6c1b9ab677cb79b74f940370584a6c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 18 Mar 2018 15:41:39 +0100 Subject: Use rustc from latest merged PR instead of nightly --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 29879e44755..64f524a44e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,10 @@ install: - npm install remark-cli remark-lint script: + - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + - RUSTC_HEAD=`git ls-remote https://github.com/rust-lang/rust.git HEAD | tr -d ",." | tr " \t" "\n" | grep -e "HEAD" -v` + - rustup-toolchain-install-master $RUSTC_HEAD + - rustup default $RUSTC_HEAD - PATH=$PATH:./node_modules/.bin - remark -f README.md > /dev/null - set -e -- cgit 1.4.1-3-g733a5 From a592e373501a568c217a1df7baed5cc254499466 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 18 Mar 2018 18:38:49 +0100 Subject: undo accidental push to master --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 64f524a44e9..29879e44755 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,6 @@ install: - npm install remark-cli remark-lint script: - - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - - RUSTC_HEAD=`git ls-remote https://github.com/rust-lang/rust.git HEAD | tr -d ",." | tr " \t" "\n" | grep -e "HEAD" -v` - - rustup-toolchain-install-master $RUSTC_HEAD - - rustup default $RUSTC_HEAD - PATH=$PATH:./node_modules/.bin - remark -f README.md > /dev/null - set -e -- cgit 1.4.1-3-g733a5 From 47a706682cb5fd47b61fd8451c1a781c4f16c81e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Mar 2018 09:26:05 +0100 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- src/main.rs | 16 ++++++++++++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 970b458e2a8..452a08f6ed4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.189 +* Rustup to *rustc 1.26.0-nightly (5508b2714 2018-03-18)* + ## 0.0.188 * Rustup to *rustc 1.26.0-nightly (392645394 2018-03-15)* * New lint: [`while_immutable_condition`] diff --git a/Cargo.toml b/Cargo.toml index 09eb34bf5fd..65714e60746 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.188" +version = "0.0.189" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.188", path = "clippy_lints" } +clippy_lints = { version = "0.0.189", path = "clippy_lints" } # end automatic update cargo_metadata = "0.5" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 38b4a0ea18c..8a155957ed2 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.188" +version = "0.0.189" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/src/main.rs b/src/main.rs index 95e1fc0c28c..81933d5769a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,10 +59,18 @@ pub fn main() { return; } - let manifest_path_arg = std::env::args() + let mut manifest_path_arg = std::env::args() .skip(2) - .find(|val| val.starts_with("--manifest-path=")) - .map(|val| val["--manifest-path=".len()..].to_owned()); + .skip_while(|val| !val.starts_with("--manifest-path")); + let manifest_path_arg = manifest_path_arg.next().and_then(|val| { + if val == "--manifest-path" { + manifest_path_arg.next() + } else if val.starts_with("--manifest-path=") { + Some(val["--manifest-path=".len()..].to_owned()) + } else { + None + } + }); let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { metadata @@ -140,7 +148,7 @@ pub fn main() { for target in package.targets { let args = std::env::args() - .skip(2) + .skip(1) .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); -- cgit 1.4.1-3-g733a5 From 48027105dc48192010b596758524519c7999b658 Mon Sep 17 00:00:00 2001 From: Baelyk Date: Sat, 17 Mar 2018 00:58:56 -0500 Subject: Add suggestion to useless_format Resolves #2505 Suggests that you use `"foo".to_string()` instead of `format!("foo")`. --- clippy_lints/src/format.rs | 12 +++++++++--- tests/ui/format.stderr | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index dcafbc50d0c..d86e6839cfb 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; use utils::paths; -use utils::{is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, span_lint, walk_ptrs_ty}; +use utils::{is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -53,14 +53,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // and that the argument is a string if check_arg_is_display(cx, &args[1]); then { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); + let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); + span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { + db.span_suggestion(expr.span, "consider using .to_string()", sugg); + }); } } }, // `format!("foo")` expansion contains `match () { () => [], }` ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node { if tup.is_empty() { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); + let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); + span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { + db.span_suggestion(span, "consider using .to_string()", sugg); + }); } }, _ => (), diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 5f5bdc02a59..f08f0696e23 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -2,7 +2,7 @@ error: useless use of `format!` --> $DIR/format.rs:6:5 | 6 | format!("foo"); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: `-D useless-format` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 70d8f85e7edc591b6a78b5d68a39151c95a1bf20 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 21 Mar 2018 20:10:10 +0200 Subject: Minor refactoring (walk_ptrs_ty_depth) Replace `walk_ptrs_ty_depth` with `walk_ptrs_ty` when the depth value is ignored. --- clippy_lints/src/methods.rs | 8 ++++---- clippy_lints/src/open_options.rs | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 2c401bd4994..a9882bdfe0c 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1034,7 +1034,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(arg)); + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); if let ty::TyAdt(_, subst) = obj_ty.sty { let caller_type = if match_type(cx, obj_ty, &paths::RC) { @@ -1063,7 +1063,7 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { let arg = &args[1]; if let Some(arglists) = method_chain_args(arg, &["chars"]) { let target = &arglists[0][0]; - let (self_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(target)); + let self_ty = walk_ptrs_ty(cx.tables.expr_ty(target)); let ref_str = if self_ty.sty == ty::TyStr { "" } else if match_type(cx, self_ty, &paths::STRING) { @@ -1089,7 +1089,7 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { } fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(&args[0])); + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); if match_type(cx, obj_ty, &paths::STRING) { lint_string_extend(cx, expr, args); } @@ -1327,7 +1327,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option LateLintPass<'a, 'tcx> for NonSensical { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprMethodCall(ref path, _, ref arguments) = e.node { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(&arguments[0])); + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); if path.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); get_open_options(cx, &arguments[0], &mut options); @@ -63,7 +62,7 @@ enum OpenOption { fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { if let ExprMethodCall(ref path, _, ref arguments) = argument.node { - let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(&arguments[0])); + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); // Only proceed if this is a call on some object of type std::fs::OpenOptions if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { -- cgit 1.4.1-3-g733a5 From 2b68f007223a5ec773fb2e220f147debe225db23 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 23 Mar 2018 20:26:52 +0200 Subject: Add tests to ensure that issue #2420 is resolved The issue was probably fixed by ff32d5f7. Closes #2420. --- tests/ui/eq_op.rs | 6 ++++++ tests/ui/eq_op.stderr | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 70c932a6cdf..ef573b2b91a 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -89,6 +89,12 @@ fn main() { let z = x & &y; check_ignore_macro(); + + // named constants + const A: u32 = 10; + const B: u32 = 10; + const C: u32 = A / B; // ok, different named constants + const D: u32 = A / A; } macro_rules! check_if_named_foo { diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 46c0ac108cd..ccf36606208 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -204,5 +204,11 @@ error: taken reference of right operand | = note: `-D op-ref` implied by `-D warnings` -error: aborting due to 33 previous errors +error: equal expressions as operands to `/` + --> $DIR/eq_op.rs:97:20 + | +97 | const D: u32 = A / A; + | ^^^^^ + +error: aborting due to 34 previous errors -- cgit 1.4.1-3-g733a5 From bef1afac5b4e0c36c335fc804aebb8de00f3cff5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 25 Mar 2018 08:52:00 +0200 Subject: Undo a temporary fix for a cargo bug Fixes #2566 --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 81933d5769a..ff75388030e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -148,7 +148,7 @@ pub fn main() { for target in package.targets { let args = std::env::args() - .skip(1) + .skip(2) .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); -- cgit 1.4.1-3-g733a5 From cb9d1727fe3042018d1559be3790162224e449ca Mon Sep 17 00:00:00 2001 From: CYBAI Date: Sun, 25 Mar 2018 16:57:15 +0800 Subject: Update configuration for leading dot filename --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecf00f2fdba..8ccc148942d 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ if let Some(y) = x { println!("{:?}", y) } ## Configuration -Some lints can be configured in a `clippy.toml` file. It contains basic `variable = value` mapping eg. +Some lints can be configured in a TOML file named with `clippy.toml` or `.clippy.toml`. It contains basic `variable = value` mapping eg. ```toml blacklisted-names = ["toto", "tata", "titi"] -- cgit 1.4.1-3-g733a5 From 748ad9fb4bf2d19e240a9bee886a92c7b1954a00 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 25 Mar 2018 20:34:44 -0500 Subject: i128 is stable --- tests/ui/replace_consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 31c58b4bb4e..37c3f5f3885 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,4 +1,4 @@ -#![feature(integer_atomics, i128, i128_type)] +#![feature(integer_atomics)] #![allow(blacklisted_name)] #![deny(replace_consts)] use std::sync::atomic::*; -- cgit 1.4.1-3-g733a5 From a4d869ca76087ee8b8858b78371a015c317cd67a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 25 Mar 2018 20:35:23 -0500 Subject: i128 is stable --- clippy_lints/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bec46ba180c..a8475c3b54c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -2,8 +2,6 @@ #![feature(box_syntax)] #![feature(custom_attribute)] -#![feature(i128_type)] -#![feature(i128)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] -- cgit 1.4.1-3-g733a5 From f25d4fd2533a838b52c312b34c5657c3853b124c Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 25 Mar 2018 21:04:05 -0500 Subject: make it pass for now --- clippy_lints/src/lib.rs | 4 ++++ tests/ui/replace_consts.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a8475c3b54c..dd6199cfc17 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,6 +11,10 @@ #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] +// FIXME(mark-i-m) remove after i128 stablization merges +#![allow(stable_features)] +#![feature(i128, i128_type)] + #[macro_use] extern crate rustc; extern crate rustc_typeck; diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 37c3f5f3885..4bd9c1d7cae 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,6 +1,11 @@ #![feature(integer_atomics)] #![allow(blacklisted_name)] #![deny(replace_consts)] + +// FIXME(mark-i-m) remove after i128 stablization merges +#![allow(stable_features)] +#![feature(i128, i128_type)] + use std::sync::atomic::*; use std::sync::{ONCE_INIT, Once}; -- cgit 1.4.1-3-g733a5 From e2d7ef9972634e60b6cfa3d61c0751759b9358f1 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 25 Mar 2018 21:17:38 -0500 Subject: attempt fix stderr --- tests/ui/replace_consts.stderr | 176 ++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 106 deletions(-) diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index fb2e71db171..7bc7f30276b 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,7 +1,7 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:11:17 + --> $DIR/replace_consts.rs:16:17 | -11 | { let foo = ATOMIC_BOOL_INIT; }; +16 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here @@ -9,210 +9,174 @@ note: lint level defined here | 3 | #![deny(replace_consts)] | ^^^^^^^^^^^^^^ - error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:12:17 + --> $DIR/replace_consts.rs:17:17 | -12 | { let foo = ATOMIC_ISIZE_INIT; }; +17 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` - error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:13:17 + --> $DIR/replace_consts.rs:18:17 | -13 | { let foo = ATOMIC_I8_INIT; }; +18 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` - error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:14:17 + --> $DIR/replace_consts.rs:19:17 | -14 | { let foo = ATOMIC_I16_INIT; }; +19 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` - error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:15:17 + --> $DIR/replace_consts.rs:20:17 | -15 | { let foo = ATOMIC_I32_INIT; }; +20 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` - error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:16:17 + --> $DIR/replace_consts.rs:21:17 | -16 | { let foo = ATOMIC_I64_INIT; }; +21 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` - error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:17:17 + --> $DIR/replace_consts.rs:22:17 | -17 | { let foo = ATOMIC_USIZE_INIT; }; +22 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` - error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:18:17 + --> $DIR/replace_consts.rs:23:17 | -18 | { let foo = ATOMIC_U8_INIT; }; +23 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` - error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:19:17 + --> $DIR/replace_consts.rs:24:17 | -19 | { let foo = ATOMIC_U16_INIT; }; +24 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` - error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:20:17 + --> $DIR/replace_consts.rs:25:17 | -20 | { let foo = ATOMIC_U32_INIT; }; +25 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` - error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:21:17 + --> $DIR/replace_consts.rs:26:17 | -21 | { let foo = ATOMIC_U64_INIT; }; +26 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` - error: using `MIN` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:28:17 | -23 | { let foo = std::isize::MIN; }; +28 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:29:17 | -24 | { let foo = std::i8::MIN; }; +29 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:30:17 | -25 | { let foo = std::i16::MIN; }; +30 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:31:17 | -26 | { let foo = std::i32::MIN; }; +31 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:32:17 | -27 | { let foo = std::i64::MIN; }; +32 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:33:17 | -28 | { let foo = std::i128::MIN; }; +33 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:34:17 | -29 | { let foo = std::usize::MIN; }; +34 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:35:17 | -30 | { let foo = std::u8::MIN; }; +35 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:36:17 | -31 | { let foo = std::u16::MIN; }; +36 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:37:17 | -32 | { let foo = std::u32::MIN; }; +37 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:38:17 | -33 | { let foo = std::u64::MIN; }; +38 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:39:17 | -34 | { let foo = std::u128::MIN; }; +39 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:41:17 | -36 | { let foo = std::isize::MAX; }; +41 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:42:17 | -37 | { let foo = std::i8::MAX; }; +42 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:43:17 | -38 | { let foo = std::i16::MAX; }; +43 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:44:17 | -39 | { let foo = std::i32::MAX; }; +44 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:45:17 | -40 | { let foo = std::i64::MAX; }; +45 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:46:17 | -41 | { let foo = std::i128::MAX; }; +46 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:47:17 | -42 | { let foo = std::usize::MAX; }; +47 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:48:17 | -43 | { let foo = std::u8::MAX; }; +48 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:49:17 | -44 | { let foo = std::u16::MAX; }; +49 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:50:17 | -45 | { let foo = std::u32::MAX; }; +50 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:51:17 | -46 | { let foo = std::u64::MAX; }; +51 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` - error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:52:17 | -47 | { let foo = std::u128::MAX; }; +52 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` - error: aborting due to 35 previous errors - -- cgit 1.4.1-3-g733a5 From e9f6a7c72f6fccb6bd3ff7858d9cea9afcaa40d9 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 25 Mar 2018 21:26:10 -0500 Subject: whitespace --- tests/ui/replace_consts.stderr | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 7bc7f30276b..571bfc6e65b 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -9,174 +9,210 @@ note: lint level defined here | 3 | #![deny(replace_consts)] | ^^^^^^^^^^^^^^ + error: using `ATOMIC_ISIZE_INIT` --> $DIR/replace_consts.rs:17:17 | 17 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` + error: using `ATOMIC_I8_INIT` --> $DIR/replace_consts.rs:18:17 | 18 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` + error: using `ATOMIC_I16_INIT` --> $DIR/replace_consts.rs:19:17 | 19 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` + error: using `ATOMIC_I32_INIT` --> $DIR/replace_consts.rs:20:17 | 20 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` + error: using `ATOMIC_I64_INIT` --> $DIR/replace_consts.rs:21:17 | 21 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` + error: using `ATOMIC_USIZE_INIT` --> $DIR/replace_consts.rs:22:17 | 22 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` + error: using `ATOMIC_U8_INIT` --> $DIR/replace_consts.rs:23:17 | 23 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` + error: using `ATOMIC_U16_INIT` --> $DIR/replace_consts.rs:24:17 | 24 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` + error: using `ATOMIC_U32_INIT` --> $DIR/replace_consts.rs:25:17 | 25 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` + error: using `ATOMIC_U64_INIT` --> $DIR/replace_consts.rs:26:17 | 26 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` + error: using `MIN` --> $DIR/replace_consts.rs:28:17 | 28 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:29:17 | 29 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:30:17 | 30 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:31:17 | 31 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:32:17 | 32 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:33:17 | 33 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:34:17 | 34 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:35:17 | 35 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:36:17 | 36 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:37:17 | 37 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:38:17 | 38 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` + error: using `MIN` --> $DIR/replace_consts.rs:39:17 | 39 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` + error: using `MAX` --> $DIR/replace_consts.rs:41:17 | 41 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:42:17 | 42 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:43:17 | 43 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:44:17 | 44 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:45:17 | 45 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:46:17 | 46 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:47:17 | 47 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:48:17 | 48 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:49:17 | 49 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:50:17 | 50 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:51:17 | 51 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` + error: using `MAX` --> $DIR/replace_consts.rs:52:17 | 52 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` + error: aborting due to 35 previous errors + -- cgit 1.4.1-3-g733a5 From 1aaeb3f16bc4d843edee5dc2c10c9a5b50b78f79 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 26 Mar 2018 07:05:46 +0200 Subject: Update needless_lifetimes_impl_trait.rs --- tests/run-pass/needless_lifetimes_impl_trait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 0ebc1bf3c6c..8cf2287c0ea 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,5 +1,5 @@ - +#![allow(stable_features)] #![feature(conservative_impl_trait)] #![deny(needless_lifetimes)] #![allow(dead_code)] -- cgit 1.4.1-3-g733a5 From 034c81b76145a0514916f34713671b16f26988df Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 26 Mar 2018 21:57:42 +0200 Subject: Fix false positive in empty_line_after_outer_attribute `empty_line_after_outer_attribute` produced a false positive warning when deriving `Copy` and/or `Clone` for an item. It looks like the second point in [this comment][that_comment] is related, as the attribute that causes the false positive has a path of `rustc_copy_clone_marker`. Fixes #2475 [that_comment]: https://github.com/rust-lang/rust/issues/35900#issuecomment-245978831 --- clippy_lints/src/attrs.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 417ddbe8c12..38cc40d2e16 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -267,7 +267,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { return; } if attr.style == AttrStyle::Outer { - if !is_present_in_source(cx, attr.span) { + if attr.tokens.is_empty() || !is_present_in_source(cx, attr.span) { return; } diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index beaa98953da..16eb95abbcb 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -67,4 +67,16 @@ pub fn function() -> bool { true } +// This should not produce a warning +#[derive(Clone, Copy)] +pub enum FooFighter { + Bar1, + + Bar2, + + Bar3, + + Bar4 +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 85bcaad41278644f61155c749cd08a6ace12a8a6 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Mon, 26 Mar 2018 20:37:34 +0200 Subject: while_immutable_condition: fix handling of self --- clippy_lints/src/loops.rs | 61 +++++++++++++++++++++++-------------------- tests/ui/infinite_loop.rs | 27 +++++++++++++++++++ tests/ui/infinite_loop.stderr | 42 ++++++++++++++++++++--------- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7bf814afa3d..b3f20bfc654 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2140,7 +2140,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } - let mut mut_var_visitor = MutableVarsVisitor { + let mut mut_var_visitor = VarCollectorVisitor { cx, ids: HashMap::new(), skip: false, @@ -2150,25 +2150,14 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } - if mut_var_visitor.ids.is_empty() { - span_lint( - cx, - WHILE_IMMUTABLE_CONDITION, - cond.span, - "all variables in condition are immutable. This either leads to an infinite or to a never running loop.", - ); - return; - } - - let mut delegate = MutVarsDelegate { - mut_spans: mut_var_visitor.ids, + used_mutably: mut_var_visitor.ids, }; let def_id = def_id::DefId::local(block.hir_id.owner); let region_scope_tree = &cx.tcx.region_scope_tree(def_id); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(expr); - if !delegate.mut_spans.iter().any(|(_, v)| v.is_some()) { + if !delegate.used_mutably.iter().any(|(_, v)| *v) { span_lint( cx, WHILE_IMMUTABLE_CONDITION, @@ -2178,21 +2167,34 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b } } -/// Collects the set of mutable variable in an expression +/// Collects the set of variables in an expression /// Stops analysis if a function call is found -struct MutableVarsVisitor<'a, 'tcx: 'a> { +/// Note: In some cases such as `self`, there are no mutable annotation, +/// All variables definition IDs are collected +struct VarCollectorVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ids: HashMap>, + ids: HashMap, skip: bool, } -impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { +impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { + fn insert_def_id(&mut self, ex: &'tcx Expr) { + if_chain! { + if let ExprPath(ref qpath) = ex.node; + if let QPath::Resolved(None, _) = *qpath; + let def = self.cx.tables.qpath_def(qpath, ex.hir_id); + if let Def::Local(node_id) = def; + then { + self.ids.insert(node_id, false); + } + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { - ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) { - self.ids.insert(node_id, None); - }, - + ExprPath(_) => self.insert_def_id(ex), // If there is any fuction/method call… we just stop analysis ExprCall(..) | ExprMethodCall(..) => self.skip = true, @@ -2208,15 +2210,18 @@ impl<'a, 'tcx> Visitor<'tcx> for MutableVarsVisitor<'a, 'tcx> { } struct MutVarsDelegate { - mut_spans: HashMap>, + used_mutably: HashMap, } impl<'tcx> MutVarsDelegate { fn update(&mut self, cat: &'tcx Categorization, sp: Span) { - if let Categorization::Local(id) = *cat { - if let Some(span) = self.mut_spans.get_mut(&id) { - *span = Some(sp) - } + match *cat { + Categorization::Local(id) => + if let Some(used) = self.used_mutably.get_mut(&id) { + *used = true; + }, + Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp), + _ => {} } } } @@ -2236,7 +2241,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { } fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { - self.update(&cmt.cat, sp) + self.update(&cmt.cat, sp) } fn decl_without_init(&mut self, _: NodeId, _: Span) {} diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 560400f359d..30f86129803 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -124,9 +124,36 @@ fn internally_mutable() { } } +struct Counter { + count: usize, +} + +impl Counter { + fn inc(&mut self) { + self.count += 1; + } + + fn inc_n(&mut self, n: usize) { + while self.count < n { + self.inc(); + } + println!("OK - self borrowed mutably"); + } + + fn print_n(&self, n: usize) { + while self.count < n { + println!("KO - {} is not mutated", self.count); + } + } +} + fn main() { immutable_condition(); unused_var(); used_immutable(); internally_mutable(); + + let mut c = Counter { count: 0 }; + c.inc_n(5); + c.print_n(2); } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 2addd4819e6..ecb6ac58960 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,22 +1,30 @@ -error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:10:11 +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. + --> $DIR/infinite_loop.rs:10:5 | -10 | while y < 10 { - | ^^^^^^ +10 | / while y < 10 { +11 | | println!("KO - y is immutable"); +12 | | } + | |_____^ | = note: `-D while-immutable-condition` implied by `-D warnings` -error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:15:11 +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. + --> $DIR/infinite_loop.rs:15:5 | -15 | while y < 10 && x < 3 { - | ^^^^^^^^^^^^^^^ +15 | / while y < 10 && x < 3 { +16 | | let mut k = 1; +17 | | k += 2; +18 | | println!("KO - x and y immutable"); +19 | | } + | |_____^ -error: all variables in condition are immutable. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:22:11 +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. + --> $DIR/infinite_loop.rs:22:5 | -22 | while !cond { - | ^^^^^ +22 | / while !cond { +23 | | println!("KO - cond immutable"); +24 | | } + | |_____^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:52:5 @@ -63,5 +71,13 @@ error: Variable in the condition are not mutated in the loop body. This either l 84 | | } | |_____^ -error: aborting due to 8 previous errors +error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. + --> $DIR/infinite_loop.rs:144:9 + | +144 | / while self.count < n { +145 | | println!("KO - {} is not mutated", self.count); +146 | | } + | |_________^ + +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 737247e50e3709e0b040120dc7604362548bf8a7 Mon Sep 17 00:00:00 2001 From: Karim Snj Date: Mon, 26 Mar 2018 23:24:57 +0200 Subject: while_immutable_condition: limit suggestion span to condition --- clippy_lints/src/loops.rs | 2 +- tests/ui/infinite_loop.stderr | 79 +++++++++++++++---------------------------- 2 files changed, 28 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b3f20bfc654..eaef31b2892 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2161,7 +2161,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b span_lint( cx, WHILE_IMMUTABLE_CONDITION, - expr.span, + cond.span, "Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.", ); } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index ecb6ac58960..67648dc9110 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,83 +1,58 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:10:5 + --> $DIR/infinite_loop.rs:10:11 | -10 | / while y < 10 { -11 | | println!("KO - y is immutable"); -12 | | } - | |_____^ +10 | while y < 10 { + | ^^^^^^ | = note: `-D while-immutable-condition` implied by `-D warnings` error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:15:5 + --> $DIR/infinite_loop.rs:15:11 | -15 | / while y < 10 && x < 3 { -16 | | let mut k = 1; -17 | | k += 2; -18 | | println!("KO - x and y immutable"); -19 | | } - | |_____^ +15 | while y < 10 && x < 3 { + | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:22:5 + --> $DIR/infinite_loop.rs:22:11 | -22 | / while !cond { -23 | | println!("KO - cond immutable"); -24 | | } - | |_____^ +22 | while !cond { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:52:5 + --> $DIR/infinite_loop.rs:52:11 | -52 | / while i < 3 { -53 | | j = 3; -54 | | println!("KO - i not mentionned"); -55 | | } - | |_____^ +52 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:57:5 + --> $DIR/infinite_loop.rs:57:11 | -57 | / while i < 3 && j > 0 { -58 | | println!("KO - i and j not mentionned"); -59 | | } - | |_____^ +57 | while i < 3 && j > 0 { + | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:61:5 + --> $DIR/infinite_loop.rs:61:11 | -61 | / while i < 3 { -62 | | let mut i = 5; -63 | | fn_mutref(&mut i); -64 | | println!("KO - shadowed"); -65 | | } - | |_____^ +61 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:76:5 + --> $DIR/infinite_loop.rs:76:11 | -76 | / while i < 3 { -77 | | fn_constref(&i); -78 | | println!("KO - const reference"); -79 | | } - | |_____^ +76 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:81:5 + --> $DIR/infinite_loop.rs:81:11 | -81 | / while i < 3 { -82 | | fn_val(i); -83 | | println!("KO - passed by value"); -84 | | } - | |_____^ +81 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:144:9 + --> $DIR/infinite_loop.rs:144:15 | -144 | / while self.count < n { -145 | | println!("KO - {} is not mutated", self.count); -146 | | } - | |_________^ +144 | while self.count < n { + | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From d458f22d89eff815b2a0f2cf3d1655d393b26714 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 25 Mar 2018 17:23:31 +0200 Subject: Fix check of immutable condition in closure --- clippy_lints/src/loops.rs | 19 ++++++++++++++++++- tests/ui/infinite_loop.rs | 12 ++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index eaef31b2892..94adb4d03a3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2150,8 +2150,20 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } + if mut_var_visitor.ids.is_empty() { + span_lint( + cx, + WHILE_IMMUTABLE_CONDITION, + cond.span, + "all variables in condition are immutable. This either leads to an infinite or to a never running loop.", + ); + return; + } + + let mut delegate = MutVarsDelegate { used_mutably: mut_var_visitor.ids, + skip: false, }; let def_id = def_id::DefId::local(block.hir_id.owner); let region_scope_tree = &cx.tcx.region_scope_tree(def_id); @@ -2194,7 +2206,10 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { - ExprPath(_) => self.insert_def_id(ex), + ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) { + self.ids.insert(node_id, false); + }, + // If there is any fuction/method call… we just stop analysis ExprCall(..) | ExprMethodCall(..) => self.skip = true, @@ -2211,6 +2226,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { struct MutVarsDelegate { used_mutably: HashMap, + skip: bool, } impl<'tcx> MutVarsDelegate { @@ -2220,6 +2236,7 @@ impl<'tcx> MutVarsDelegate { if let Some(used) = self.used_mutably.get_mut(&id) { *used = true; }, + Categorization::Upvar(_) => skip = true, Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp), _ => {} } diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 30f86129803..4029f9a9b29 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,9 +1,13 @@ + + + fn fn_val(i: i32) -> i32 { unimplemented!() } fn fn_constref(i: &i32) -> i32 { unimplemented!() } fn fn_mutref(i: &mut i32) { unimplemented!() } fn fooi() -> i32 { unimplemented!() } fn foob() -> bool { unimplemented!() } +#[allow(many_single_char_names)] fn immutable_condition() { // Should warn when all vars mentionned are immutable let y = 0; @@ -43,6 +47,14 @@ fn immutable_condition() { println!("OK - Fn call results may vary"); } + let mut a = 0; + let mut c = move || { + while a < 5 { + a += 1; + println!("OK - a is mutable"); + } + }; + c(); } fn unused_var() { -- cgit 1.4.1-3-g733a5 From 7d290751321f9dcaa91cf4a925e7d68d3ce68817 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 26 Mar 2018 12:32:21 +0200 Subject: Skip the mutation in while body case for closures --- clippy_lints/src/loops.rs | 38 +++++++++++++++++++------------------- tests/ui/infinite_loop.stderr | 36 ++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 94adb4d03a3..a76b46a1bcb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -347,7 +347,9 @@ declare_lint! { /// **Why is this bad?** If the condition is unchanged, entering the body of the loop /// will lead to an infinite loop. /// -/// **Known problems:** None +/// **Known problems:** If the `while`-loop is in a closure, the check for mutation of the +/// condition variables in the body can cause false negatives. For example when only `Upvar` `a` is +/// in the condition and only `Upvar` `b` gets mutated in the body, the lint will not trigger. /// /// **Example:** /// ```rust @@ -2150,17 +2152,6 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b return; } - if mut_var_visitor.ids.is_empty() { - span_lint( - cx, - WHILE_IMMUTABLE_CONDITION, - cond.span, - "all variables in condition are immutable. This either leads to an infinite or to a never running loop.", - ); - return; - } - - let mut delegate = MutVarsDelegate { used_mutably: mut_var_visitor.ids, skip: false, @@ -2169,6 +2160,9 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b let region_scope_tree = &cx.tcx.region_scope_tree(def_id); ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(expr); + if delegate.skip { + return; + } if !delegate.used_mutably.iter().any(|(_, v)| *v) { span_lint( cx, @@ -2195,9 +2189,13 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { if let ExprPath(ref qpath) = ex.node; if let QPath::Resolved(None, _) = *qpath; let def = self.cx.tables.qpath_def(qpath, ex.hir_id); - if let Def::Local(node_id) = def; then { - self.ids.insert(node_id, false); + match def { + Def::Local(node_id) | Def::Upvar(node_id, ..) => { + self.ids.insert(node_id, false); + }, + _ => {}, + } } } } @@ -2206,10 +2204,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { - ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) { - self.ids.insert(node_id, false); - }, - + ExprPath(_) => self.insert_def_id(ex), // If there is any fuction/method call… we just stop analysis ExprCall(..) | ExprMethodCall(..) => self.skip = true, @@ -2236,7 +2231,12 @@ impl<'tcx> MutVarsDelegate { if let Some(used) = self.used_mutably.get_mut(&id) { *used = true; }, - Categorization::Upvar(_) => skip = true, + Categorization::Upvar(_) => { + //FIXME: This causes false negatives. We can't get the `NodeId` from + //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the + //`while`-body, not just the ones in the condition. + self.skip = true + }, Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp), _ => {} } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 67648dc9110..0bf14bb723b 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,57 +1,57 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:10:11 + --> $DIR/infinite_loop.rs:14:11 | -10 | while y < 10 { +14 | while y < 10 { | ^^^^^^ | = note: `-D while-immutable-condition` implied by `-D warnings` error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:15:11 + --> $DIR/infinite_loop.rs:19:11 | -15 | while y < 10 && x < 3 { +19 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:22:11 + --> $DIR/infinite_loop.rs:26:11 | -22 | while !cond { +26 | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:52:11 + --> $DIR/infinite_loop.rs:64:11 | -52 | while i < 3 { +64 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:57:11 + --> $DIR/infinite_loop.rs:69:11 | -57 | while i < 3 && j > 0 { +69 | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:61:11 + --> $DIR/infinite_loop.rs:73:11 | -61 | while i < 3 { +73 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:76:11 + --> $DIR/infinite_loop.rs:88:11 | -76 | while i < 3 { +88 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:81:11 + --> $DIR/infinite_loop.rs:93:11 | -81 | while i < 3 { +93 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:144:15 + --> $DIR/infinite_loop.rs:156:15 | -144 | while self.count < n { +156 | while self.count < n { | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 546d2fec29c46615686bf2f7e356bc637a410d89 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 26 Mar 2018 07:48:32 +0200 Subject: Fix enum_glob_use false positives Closes #2397. This checks the def of the `ItemUse` path instead of checking the capitalization of the path segements. It was noted that this def would sometimes be `Def::Mod` instead of `Def::Enum` but it seems correct now. --- clippy_lints/src/enum_glob_use.rs | 21 +++++++++------------ tests/ui/enum_glob_use.rs | 6 ++++++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index c00cdc07f84..8a0d03d2ae9 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -1,6 +1,7 @@ //! lint on `use`ing all variants of an enum use rustc::hir::*; +use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use syntax::ast::NodeId; use syntax::codemap::Span; @@ -12,8 +13,7 @@ use utils::span_lint; /// an enumeration variant, rather than importing variants. /// /// **Known problems:** Old-style enumerations that prefix the variants are -/// still around. May cause problems with modules that are not snake_case (see -/// [#2397](https://github.com/rust-lang-nursery/rust-clippy/issues/2397)) +/// still around. /// /// **Example:** /// ```rust @@ -48,16 +48,13 @@ impl EnumGlobUse { return; // re-exports are fine } if let ItemUse(ref path, UseKind::Glob) = item.node { - // FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;` - // extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an - // `Enum` - // if let Def::Enum(_) = path.def { - if path.segments - .last() - .and_then(|seg| seg.name.as_str().chars().next()) - .map_or(false, char::is_uppercase) - { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); + if let Def::Enum(_) = path.def { + span_lint( + cx, + ENUM_GLOB_USE, + item.span, + "don't use glob imports for enum variants", + ); } } } diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 76d0d29bb53..efb37fbe49d 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -23,4 +23,10 @@ mod tests { use super::*; } +#[allow(non_snake_case)] +mod CamelCaseName { +} + +use CamelCaseName::*; + fn main() {} -- cgit 1.4.1-3-g733a5 From 96d5af36f87c9b4ca09a9aec4a49154404264501 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 27 Mar 2018 12:14:46 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/utils/conf.rs | 2 +- src/main.rs | 6 +++--- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 452a08f6ed4..f8c91e6903d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.190 +* Fix a bunch of intermittent cargo bugs + ## 0.0.189 * Rustup to *rustc 1.26.0-nightly (5508b2714 2018-03-18)* diff --git a/Cargo.toml b/Cargo.toml index 65714e60746..24b3ff975b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.189" +version = "0.0.190" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.189", path = "clippy_lints" } +clippy_lints = { version = "0.0.190", path = "clippy_lints" } # end automatic update cargo_metadata = "0.5" regex = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 8a155957ed2..e8d08082d4d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.189" +version = "0.0.190" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 9f40713f6e4..58e71705011 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -186,7 +186,7 @@ pub fn lookup_conf_file() -> io::Result> { /// Possible filename to search for. const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"]; - let mut current = try!(env::current_dir()); + let mut current = path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); loop { for config_file_name in &CONFIG_FILE_NAMES { diff --git a/src/main.rs b/src/main.rs index ff75388030e..e5d78c35d0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,10 +115,10 @@ pub fn main() { }) .collect(); - let current_dir = std::env::current_dir() - .expect("could not read current directory") + let current_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR") + .expect("CARGO_MANIFEST_DIR not set")) .canonicalize() - .expect("current directory cannot be canonicalized"); + .expect("manifest directory cannot be canonicalized"); let mut current_path: &Path = ¤t_dir; -- cgit 1.4.1-3-g733a5 From 9b10c4be8cb5850fbb52b55f876e9095ca61e088 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 27 Mar 2018 13:00:02 +0200 Subject: Undo current_dir -> CARGO_MANIFEST_DIR move --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index e5d78c35d0b..98201af7e27 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,8 +115,8 @@ pub fn main() { }) .collect(); - let current_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR") - .expect("CARGO_MANIFEST_DIR not set")) + let current_dir = std::env::current_dir() + .expect("CARGO_MANIFEST_DIR not set") .canonicalize() .expect("manifest directory cannot be canonicalized"); -- cgit 1.4.1-3-g733a5 From ef9fdbb8a9a3321a0d2261a0b6a013c23e2f669b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 27 Mar 2018 17:13:55 +0200 Subject: Implementation + move one lint --- clippy_lints/src/approx_const.rs | 4 +-- clippy_lints/src/lib.rs | 29 ++++++++++++++++++- util/update_lints.py | 60 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 36f3579e548..d15b48ce2d1 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -26,9 +26,9 @@ use utils::span_lint; /// ```rust /// let x = 3.14; /// ``` -declare_lint! { +declare_clippy_lint! { pub APPROX_CONSTANT, - Warn, + correctness, "the approximate of a known float constant (in `std::fXX::consts`)" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d9a19ac1e76..6d6b1fe0b8c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -66,6 +66,21 @@ macro_rules! declare_restriction_lint { }; } +macro_rules! declare_clippy_lint { + { pub $name:tt, style, $description:tt } => { + declare_lint! { pub $name, Warn, $description } + }; + { pub $name:tt, correctness, $description:tt } => { + declare_lint! { pub $name, Deny, $description } + }; + { pub $name:tt, complexity, $description:tt } => { + declare_lint! { pub $name, Warn, $description } + }; + { pub $name:tt, perf, $description:tt } => { + declare_lint! { pub $name, Warn, $description } + }; +} + pub mod consts; #[macro_use] pub mod utils; @@ -442,7 +457,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ]); reg.register_lint_group("clippy", vec![ - approx_const::APPROX_CONSTANT, array_indexing::OUT_OF_BOUNDS_INDEXING, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, @@ -641,6 +655,19 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); + + reg.register_lint_group("clippy_style", vec![ + ]); + + reg.register_lint_group("clippy_complexity", vec![ + ]); + + reg.register_lint_group("clippy_correctness", vec![ + approx_const::APPROX_CONSTANT, + ]); + + reg.register_lint_group("clippy_perf", vec![ + ]); } // only exists to let the dogfood integration test works. diff --git a/util/update_lints.py b/util/update_lints.py index 6c08f575d05..0f9c3479439 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -27,12 +27,19 @@ declare_restriction_lint_re = re.compile(r''' " (?P(?:[^"\\]+|\\.)*) " \s* [})] ''', re.VERBOSE | re.DOTALL) +declare_clippy_lint_re = re.compile(r''' + declare_clippy_lint! \s* [{(] \s* + pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* + (?P[a-z_]+) \s*,\s* + " (?P(?:[^"\\]+|\\.)*) " \s* [})] +''', re.VERBOSE | re.DOTALL) + nl_escape_re = re.compile(r'\\\n\s*') docs_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' -def collect(lints, deprecated_lints, restriction_lints, fn): +def collect(lints, deprecated_lints, restriction_lints, clippy_lints, fn): """Collect all lints from a file. Adds entries to the lints list as `(module, name, level, desc)`. @@ -61,6 +68,15 @@ def collect(lints, deprecated_lints, restriction_lints, fn): match.group('name').lower(), "allow", desc.replace('\\"', '"'))) + + for match in declare_clippy_lint_re.finditer(code): + # remove \-newline escapes from description string + desc = nl_escape_re.sub('', match.group('desc')) + cat = match.group('cat') + clippy_lints[cat].append((os.path.splitext(os.path.basename(fn))[0], + match.group('name').lower(), + "allow", + desc.replace('\\"', '"'))) def gen_group(lints, levels=None): @@ -130,6 +146,12 @@ def main(print_only=False, check=False): lints = [] deprecated_lints = [] restriction_lints = [] + clippy_lints = { + "correctness": [], + "style": [], + "complexity": [], + "perf": [], + } # check directory if not os.path.isfile('clippy_lints/src/lib.rs'): @@ -139,7 +161,7 @@ def main(print_only=False, check=False): # collect all lints from source files for fn in os.listdir('clippy_lints/src'): if fn.endswith('.rs'): - collect(lints, deprecated_lints, restriction_lints, + collect(lints, deprecated_lints, restriction_lints, clippy_lints, os.path.join('clippy_lints', 'src', fn)) # determine version @@ -152,8 +174,10 @@ def main(print_only=False, check=False): print('Error: version not found in Cargo.toml!') return + all_lints = lints + restriction_lints + clippy_lints['perf'] + clippy_lints['correctness'] + clippy_lints['style'] + clippy_lints['complexity'] + if print_only: - sys.stdout.writelines(gen_table(lints + restriction_lints)) + sys.stdout.writelines(gen_table(all_lints)) return # update the lint counter in README.md @@ -161,7 +185,7 @@ def main(print_only=False, check=False): 'README.md', r'^\[There are \d+ lints included in this crate\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)$', "", lambda: ['[There are %d lints included in this crate](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)\n' % - (len(lints) + len(restriction_lints))], + (len(all_lints))], write_back=not check) # update the links in the CHANGELOG @@ -170,7 +194,7 @@ def main(print_only=False, check=False): "", "", lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], docs_link) for l in - sorted(lints + restriction_lints + deprecated_lints, + sorted(all_lints + deprecated_lints, key=lambda l: l[1])], replace_start=False, write_back=not check) @@ -190,7 +214,7 @@ def main(print_only=False, check=False): # update the `pub mod` list changed |= replace_region( 'clippy_lints/src/lib.rs', r'begin lints modules', r'end lints modules', - lambda: gen_mods(lints + restriction_lints), + lambda: gen_mods(all_lints), replace_start=False, write_back=not check) # same for "clippy" lint collection @@ -199,6 +223,30 @@ def main(print_only=False, check=False): lambda: gen_group(lints, levels=('warn', 'deny')), replace_start=False, write_back=not check) + # same for "clippy_style" lint collection + changed |= replace_region( + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_style"', r'\]\);', + lambda: gen_group(clippy_lints['style']), + replace_start=False, write_back=not check) + + # same for "clippy_correctness" lint collection + changed |= replace_region( + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_correctness"', r'\]\);', + lambda: gen_group(clippy_lints['correctness']), + replace_start=False, write_back=not check) + + # same for "clippy_complexity" lint collection + changed |= replace_region( + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_complexity"', r'\]\);', + lambda: gen_group(clippy_lints['complexity']), + replace_start=False, write_back=not check) + + # same for "clippy_perf" lint collection + changed |= replace_region( + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_perf"', r'\]\);', + lambda: gen_group(clippy_lints['perf']), + replace_start=False, write_back=not check) + # same for "deprecated" lint collection changed |= replace_region( 'clippy_lints/src/lib.rs', r'let mut store', r'end deprecated lints', -- cgit 1.4.1-3-g733a5 From 66a98d2658997ad8ede2939e68222bd4df626718 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 28 Mar 2018 11:50:17 +0200 Subject: Use cargo check instead of cargo rustc --- src/driver.rs | 5 ++++- src/main.rs | 18 +++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 78bccb74ab9..73746798601 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -186,10 +186,13 @@ pub fn main() { let clippy_enabled = env::var("CLIPPY_TESTS") .ok() .map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=metadata"); + || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + if let Ok(extra_args) = env::var("CLIPPY_ARGS") { + args.extend(extra_args.split("__CLIPPY_HACKERY__").filter(|s| !s.is_empty()).map(str::to_owned)); + } } let mut ccc = ClippyCompilerCalls::new(clippy_enabled); diff --git a/src/main.rs b/src/main.rs index 98201af7e27..598d129dec2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -175,23 +175,22 @@ pub fn main() { } } -fn process(old_args: I) -> Result<(), i32> +fn process(mut old_args: I) -> Result<(), i32> where I: Iterator, { - let mut args = vec!["rustc".to_owned()]; + let mut args = vec!["check".to_owned()]; let mut found_dashes = false; - for arg in old_args { + for arg in old_args.by_ref() { found_dashes |= arg == "--"; + if found_dashes { + break; + } args.push(arg); } - if !found_dashes { - args.push("--".to_owned()); - } - args.push("--emit=metadata".to_owned()); - args.push("--cfg".to_owned()); - args.push(r#"feature="cargo-clippy""#.to_owned()); + + let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect(); let mut path = std::env::current_exe() .expect("current executable path invalid") @@ -202,6 +201,7 @@ where let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) + .env("CLIPPY_ARGS", clippy_args) .spawn() .expect("could not run cargo") .wait() -- cgit 1.4.1-3-g733a5 From d6344c47e3bf8e1c1bc4dea52841d0a1f83b4fa4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 28 Mar 2018 15:24:26 +0200 Subject: Categorize all the lints! --- clippy_lints/src/arithmetic.rs | 6 +- clippy_lints/src/array_indexing.rs | 7 +- clippy_lints/src/assign_ops.rs | 11 +- clippy_lints/src/attrs.rs | 16 +- clippy_lints/src/bit_mask.rs | 12 +- clippy_lints/src/blacklisted_name.rs | 4 +- clippy_lints/src/block_in_if_condition.rs | 8 +- clippy_lints/src/booleans.rs | 8 +- clippy_lints/src/bytecount.rs | 4 +- clippy_lints/src/collapsible_if.rs | 4 +- clippy_lints/src/const_static_lifetime.rs | 4 +- clippy_lints/src/copies.rs | 12 +- clippy_lints/src/cyclomatic_complexity.rs | 4 +- clippy_lints/src/derive.rs | 10 +- clippy_lints/src/doc.rs | 4 +- clippy_lints/src/double_comparison.rs | 4 +- clippy_lints/src/double_parens.rs | 5 +- clippy_lints/src/drop_forget_ref.rs | 16 +- clippy_lints/src/else_if_without_else.rs | 3 +- clippy_lints/src/empty_enum.rs | 4 +- clippy_lints/src/entry.rs | 4 +- clippy_lints/src/enum_clike.rs | 4 +- clippy_lints/src/enum_glob_use.rs | 4 +- clippy_lints/src/enum_variants.rs | 16 +- clippy_lints/src/eq_op.rs | 8 +- clippy_lints/src/erasing_op.rs | 4 +- clippy_lints/src/escape.rs | 4 +- clippy_lints/src/eta_reduction.rs | 4 +- clippy_lints/src/eval_order_dependence.rs | 8 +- clippy_lints/src/explicit_write.rs | 4 +- clippy_lints/src/fallible_impl_from.rs | 5 +- clippy_lints/src/format.rs | 4 +- clippy_lints/src/formatting.rs | 12 +- clippy_lints/src/functions.rs | 8 +- clippy_lints/src/identity_conversion.rs | 4 +- clippy_lints/src/identity_op.rs | 4 +- .../src/if_let_redundant_pattern_matching.rs | 4 +- clippy_lints/src/if_not_else.rs | 4 +- clippy_lints/src/infinite_iter.rs | 8 +- clippy_lints/src/inline_fn_without_body.rs | 4 +- clippy_lints/src/int_plus_one.rs | 4 +- clippy_lints/src/invalid_ref.rs | 4 +- clippy_lints/src/items_after_statements.rs | 4 +- clippy_lints/src/large_enum_variant.rs | 4 +- clippy_lints/src/len_zero.rs | 8 +- clippy_lints/src/let_if_seq.rs | 4 +- clippy_lints/src/lib.rs | 234 ++++++++++----------- clippy_lints/src/lifetimes.rs | 8 +- clippy_lints/src/literal_representation.rs | 15 +- clippy_lints/src/loops.rs | 84 ++++---- clippy_lints/src/map_clone.rs | 4 +- clippy_lints/src/matches.rs | 28 +-- clippy_lints/src/mem_forget.rs | 4 +- clippy_lints/src/methods.rs | 117 ++++++----- clippy_lints/src/minmax.rs | 4 +- clippy_lints/src/misc.rs | 39 ++-- clippy_lints/src/misc_early.rs | 32 +-- clippy_lints/src/missing_doc.rs | 4 +- clippy_lints/src/mut_mut.rs | 4 +- clippy_lints/src/mut_reference.rs | 4 +- clippy_lints/src/mutex_atomic.rs | 8 +- clippy_lints/src/needless_bool.rs | 8 +- clippy_lints/src/needless_borrow.rs | 4 +- clippy_lints/src/needless_borrowed_ref.rs | 4 +- clippy_lints/src/needless_continue.rs | 4 +- clippy_lints/src/needless_pass_by_value.rs | 4 +- clippy_lints/src/needless_update.rs | 4 +- clippy_lints/src/neg_multiply.rs | 4 +- clippy_lints/src/new_without_default.rs | 8 +- clippy_lints/src/no_effect.rs | 8 +- clippy_lints/src/non_expressive_names.rs | 12 +- clippy_lints/src/ok_if_let.rs | 4 +- clippy_lints/src/open_options.rs | 4 +- clippy_lints/src/overflow_check_conditional.rs | 4 +- clippy_lints/src/panic.rs | 4 +- clippy_lints/src/partialeq_ne_impl.rs | 4 +- clippy_lints/src/precedence.rs | 4 +- clippy_lints/src/print.rs | 16 +- clippy_lints/src/ptr.rs | 12 +- clippy_lints/src/question_mark.rs | 4 +- clippy_lints/src/ranges.rs | 16 +- clippy_lints/src/redundant_field_names.rs | 4 +- clippy_lints/src/reference.rs | 4 +- clippy_lints/src/regex.rs | 12 +- clippy_lints/src/replace_consts.rs | 4 +- clippy_lints/src/returns.rs | 8 +- clippy_lints/src/serde_api.rs | 6 +- clippy_lints/src/shadow.rs | 12 +- clippy_lints/src/strings.rs | 15 +- clippy_lints/src/suspicious_trait_impl.rs | 8 +- clippy_lints/src/swap.rs | 8 +- clippy_lints/src/temporary_assignment.rs | 4 +- clippy_lints/src/transmute.rs | 36 ++-- clippy_lints/src/types.rs | 72 +++---- clippy_lints/src/unicode.rs | 12 +- clippy_lints/src/unsafe_removed_from_name.rs | 4 +- clippy_lints/src/unused_io_amount.rs | 4 +- clippy_lints/src/unused_label.rs | 4 +- clippy_lints/src/use_self.rs | 4 +- clippy_lints/src/utils/author.rs | 4 +- clippy_lints/src/utils/inspector.rs | 4 +- clippy_lints/src/utils/internal_lints.rs | 8 +- clippy_lints/src/vec.rs | 4 +- clippy_lints/src/zero_div_zero.rs | 4 +- tests/ui/lint_pass.rs | 4 +- util/lintlib.py | 82 +++++--- util/update_lints.py | 81 ++----- 107 files changed, 708 insertions(+), 716 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index a551ebf046b..501f49363dd 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -15,8 +15,9 @@ use utils::span_lint; /// ```rust /// a + 1 /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub INTEGER_ARITHMETIC, + restriction, "any integer arithmetic statement" } @@ -31,8 +32,9 @@ declare_restriction_lint! { /// ```rust /// a + 1.0 /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub FLOAT_ARITHMETIC, + restriction, "any floating-point arithmetic statement" } diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 53d0d7cebaa..4563a58f7ab 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -19,9 +19,9 @@ use consts::{constant, Constant}; /// x[9]; /// &x[2..9]; /// ``` -declare_lint! { +declare_clippy_lint! { pub OUT_OF_BOUNDS_INDEXING, - Deny, + correctness, "out of bounds constant indexing" } @@ -39,8 +39,9 @@ declare_lint! { /// x[2]; /// &x[0..2]; /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub INDEXING_SLICING, + restriction, "indexing/slicing usage" } diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index a3d9d5cbba8..da4b0d6a437 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -18,8 +18,9 @@ use utils::{higher, sugg}; /// ```rust /// a += 1; /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub ASSIGN_OPS, + restriction, "any compound assignment operation" } @@ -37,9 +38,9 @@ declare_restriction_lint! { /// ... /// a = a + b; /// ``` -declare_lint! { +declare_clippy_lint! { pub ASSIGN_OP_PATTERN, - Warn, + style, "assigning the result of an operation on a variable to that same variable" } @@ -57,9 +58,9 @@ declare_lint! { /// ... /// a += a + b; /// ``` -declare_lint! { +declare_clippy_lint! { pub MISREFACTORED_ASSIGN_OP, - Warn, + complexity, "having a variable on both sides of an assign op" } diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 38cc40d2e16..340d82dfa61 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -29,9 +29,9 @@ use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snip /// #[inline(always)] /// fn not_quite_hot_code(..) { ... } /// ``` -declare_lint! { +declare_clippy_lint! { pub INLINE_ALWAYS, - Warn, + pedantic, "use of `#[inline(always)]`" } @@ -53,9 +53,9 @@ declare_lint! { /// #[allow(unused_import)] /// use foo::bar; /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_ATTRIBUTE, - Warn, + correctness, "use of lint attributes on `extern crate` items" } @@ -72,9 +72,9 @@ declare_lint! { /// #[deprecated(since = "forever")] /// fn something_else(..) { ... } /// ``` -declare_lint! { +declare_clippy_lint! { pub DEPRECATED_SEMVER, - Warn, + correctness, "use of `#[deprecated(since = \"x\")]` where x is not semver" } @@ -103,9 +103,9 @@ declare_lint! { /// #[inline(always)] /// fn this_is_fine_too(..) { ... } /// ``` -declare_lint! { +declare_clippy_lint! { pub EMPTY_LINE_AFTER_OUTER_ATTR, - Warn, + style, "empty line after outer attribute" } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 8989c5ca8cf..b6adbf1bd86 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -36,9 +36,9 @@ use consts::{constant, Constant}; /// ```rust /// if (x & 1 == 2) { … } /// ``` -declare_lint! { +declare_clippy_lint! { pub BAD_BIT_MASK, - Warn, + correctness, "expressions of the form `_ & mask == select` that will only ever return `true` or `false`" } @@ -64,9 +64,9 @@ declare_lint! { /// ```rust /// if (x | 1 > 3) { … } /// ``` -declare_lint! { +declare_clippy_lint! { pub INEFFECTIVE_BIT_MASK, - Warn, + correctness, "expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`" } @@ -82,9 +82,9 @@ declare_lint! { /// ```rust /// x & 0x1111 == 0 /// ``` -declare_lint! { +declare_clippy_lint! { pub VERBOSE_BIT_MASK, - Warn, + style, "expressions where a bit mask is less readable than the corresponding method call" } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index dd5bf968bb3..d06e1240b06 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -14,9 +14,9 @@ use utils::span_lint; /// ```rust /// let foo = 3.14; /// ``` -declare_lint! { +declare_clippy_lint! { pub BLACKLISTED_NAME, - Warn, + style, "usage of a blacklisted/placeholder name" } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 0afb8a73dfe..2fd385228b2 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -15,9 +15,9 @@ use utils::*; /// ```rust /// if { true } .. /// ``` -declare_lint! { +declare_clippy_lint! { pub BLOCK_IN_IF_CONDITION_EXPR, - Warn, + style, "braces that can be eliminated in conditions, e.g. `if { true } ...`" } @@ -34,9 +34,9 @@ declare_lint! { /// // or /// if somefunc(|x| { x == 47 }) .. /// ``` -declare_lint! { +declare_clippy_lint! { pub BLOCK_IN_IF_CONDITION_STMT, - Warn, + style, "complex blocks in conditions, e.g. `if { let x = true; x } ...`" } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index cec569ec061..0fa2c2ac96f 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -20,9 +20,9 @@ use utils::{in_macro, snippet_opt, span_lint_and_then, SpanlessEq}; /// if a && true // should be: if a /// if !(a == b) // should be: if a != b /// ``` -declare_lint! { +declare_clippy_lint! { pub NONMINIMAL_BOOL, - Allow, + complexity, "boolean expressions that can be written more concisely" } @@ -38,9 +38,9 @@ declare_lint! { /// if a && b || a { ... } /// ``` /// The `b` is unnecessary, the expression is equivalent to `if a`. -declare_lint! { +declare_clippy_lint! { pub LOGIC_BUG, - Warn, + correctness, "boolean expressions that contain terminals which can be eliminated" } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 886834e3981..278decc2ebd 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -20,9 +20,9 @@ use utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, /// ```rust /// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead /// ``` -declare_lint! { +declare_clippy_lint! { pub NAIVE_BYTECOUNT, - Warn, + perf, "use of naive `.filter(|&x| x == y).count()` to count byte values" } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index fa0d7de6676..20a5e606dbf 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -62,9 +62,9 @@ use utils::sugg::Sugg; /// … /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub COLLAPSIBLE_IF, - Warn, + style, "`if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`)" } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 66a1634ebce..38fcf514626 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -18,9 +18,9 @@ use utils::{in_macro, snippet, span_lint_and_then}; /// ```rust /// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...] /// ``` -declare_lint! { +declare_clippy_lint! { pub CONST_STATIC_LIFETIME, - Warn, + style, "Using explicit `'static` lifetime for constants when elision rules would allow omitting them." } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index d41ea5849a8..1434a1437f0 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -33,9 +33,9 @@ use utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_an /// … /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub IFS_SAME_COND, - Warn, + correctness, "consecutive `ifs` with the same condition" } @@ -54,9 +54,9 @@ declare_lint! { /// 42 /// }; /// ``` -declare_lint! { +declare_clippy_lint! { pub IF_SAME_THEN_ELSE, - Warn, + correctness, "if with the same *then* and *else* blocks" } @@ -95,9 +95,9 @@ declare_lint! { /// Quz => quz(), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_SAME_ARMS, - Warn, + pedantic, "`match` with identical arm bodies" } diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 751fc13292c..139936554a1 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -19,9 +19,9 @@ use utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitSt /// complexity. /// /// **Example:** No. You'll see it when you get the warning. -declare_lint! { +declare_clippy_lint! { pub CYCLOMATIC_COMPLEXITY, - Warn, + complexity, "functions that should be split up into multiple functions" } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 8702ec1e716..b505e52c95b 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -28,9 +28,9 @@ use utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; /// ... /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub DERIVE_HASH_XOR_EQ, - Warn, + correctness, "deriving `Hash` but implementing `PartialEq` explicitly" } @@ -43,7 +43,7 @@ declare_lint! { /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]` /// gets you. /// -/// **Known problems:** None. +/// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925 /// /// **Example:** /// ```rust @@ -54,9 +54,9 @@ declare_lint! { /// .. /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub EXPL_IMPL_CLONE_ON_COPY, - Warn, + pedantic, "implementing `Clone` explicitly on `Copy` types" } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 3e2c56f5fb9..1439c23f0fa 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -25,9 +25,9 @@ use url::Url; /// // ^ `foo_bar` and `that::other::module::foo` should be ticked. /// fn doit(foo_bar) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub DOC_MARKDOWN, - Warn, + pedantic, "presence of `_`, `::` or camel-case outside backticks in documentation" } diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index a4124883fcb..06d0cf1d09e 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -23,9 +23,9 @@ use utils::{snippet, span_lint_and_sugg, SpanlessEq}; /// ```rust /// x <= y /// ``` -declare_lint! { +declare_clippy_lint! { pub DOUBLE_COMPARISONS, - Deny, + complexity, "unnecessary double comparisons that can be simplified" } diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index be5e056d5df..2b81e1db257 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -14,8 +14,9 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass} /// foo((0)) /// ((1, 2)) /// ``` -declare_lint! { - pub DOUBLE_PARENS, Warn, +declare_clippy_lint! { + pub DOUBLE_PARENS, + complexity, "Warn on unnecessary double parentheses" } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index c523c569a68..7acc7805f82 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -20,9 +20,9 @@ use utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; /// still locked /// operation_that_requires_mutex_to_be_unlocked(); /// ``` -declare_lint! { +declare_clippy_lint! { pub DROP_REF, - Warn, + correctness, "calls to `std::mem::drop` with a reference instead of an owned value" } @@ -41,9 +41,9 @@ declare_lint! { /// let x = Box::new(1); /// std::mem::forget(&x) // Should have been forget(x), x will still be dropped /// ``` -declare_lint! { +declare_clippy_lint! { pub FORGET_REF, - Warn, + correctness, "calls to `std::mem::forget` with a reference instead of an owned value" } @@ -62,9 +62,9 @@ declare_lint! { /// std::mem::drop(x) // A copy of x is passed to the function, leaving the /// original unaffected /// ``` -declare_lint! { +declare_clippy_lint! { pub DROP_COPY, - Warn, + correctness, "calls to `std::mem::drop` with a value that implements Copy" } @@ -89,9 +89,9 @@ declare_lint! { /// std::mem::forget(x) // A copy of x is passed to the function, leaving the /// original unaffected /// ``` -declare_lint! { +declare_clippy_lint! { pub FORGET_COPY, - Warn, + correctness, "calls to `std::mem::forget` with a value that implements Copy" } diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index b354fe70596..bceed1c2168 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -32,8 +32,9 @@ use utils::{in_external_macro, span_lint_and_sugg}; /// // we don't care about zero /// } /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub ELSE_IF_WITHOUT_ELSE, + restriction, "if expression with an `else if`, but without a final `else` branch" } diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 67a4b8d4030..1641c4d444b 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -16,9 +16,9 @@ use utils::span_lint_and_then; /// ```rust /// enum Test {} /// ``` -declare_lint! { +declare_clippy_lint! { pub EMPTY_ENUM, - Allow, + pedantic, "enum with no variants" } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index aeae5fc6ced..d67b3a010cf 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -24,9 +24,9 @@ use utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ /// ```rust /// m.entry(k).or_insert(v); /// ``` -declare_lint! { +declare_clippy_lint! { pub MAP_ENTRY, - Warn, + perf, "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index f1572043024..da3586af262 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -27,9 +27,9 @@ use rustc::mir::interpret::GlobalId; /// Y = 0 /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub ENUM_CLIKE_UNPORTABLE_VARIANT, - Warn, + correctness, "C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" } diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 8a0d03d2ae9..0718a6b3679 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -19,9 +19,9 @@ use utils::span_lint; /// ```rust /// use std::cmp::Ordering::*; /// ``` -declare_lint! { +declare_clippy_lint! { pub ENUM_GLOB_USE, - Allow, + pedantic, "use items that import all variants of an enum" } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 4a5dc1cc286..c2e246a71fa 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -22,9 +22,9 @@ use utils::{camel_case_from, camel_case_until, in_macro}; /// HummingbirdCake, /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub ENUM_VARIANT_NAMES, - Warn, + style, "enums where all variants share a prefix/postfix" } @@ -43,9 +43,9 @@ declare_lint! { /// HummingbirdCake, /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub PUB_ENUM_VARIANT_NAMES, - Allow, + pedantic, "enums where all variants share a prefix/postfix" } @@ -62,9 +62,9 @@ declare_lint! { /// struct BlackForestCake; /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub STUTTER, - Allow, + pedantic, "type names prefixed/postfixed with their containing module's name" } @@ -92,9 +92,9 @@ declare_lint! { /// ... /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MODULE_INCEPTION, - Warn, + style, "modules that have the same name as their parent module" } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index d62b937f52f..cce20a58da8 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -17,9 +17,9 @@ use utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_l /// ```rust /// x + 1 == x + 1 /// ``` -declare_lint! { +declare_clippy_lint! { pub EQ_OP, - Warn, + correctness, "equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" } @@ -35,9 +35,9 @@ declare_lint! { /// ```rust /// &x == y /// ``` -declare_lint! { +declare_clippy_lint! { pub OP_REF, - Warn, + style, "taking a reference to satisfy the type constraints on `==`" } diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index a601d91a185..9cd4f3ada3b 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -16,9 +16,9 @@ use utils::{in_macro, span_lint}; /// ```rust /// 0 / x; 0 * x; x & 0 /// ``` -declare_lint! { +declare_clippy_lint! { pub ERASING_OP, - Warn, + correctness, "using erasing operations, e.g. `x * 0` or `y & 0`" } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 8cd0aaee9af..8c3127085fa 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -32,9 +32,9 @@ pub struct Pass { /// println!("{}", *x); /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub BOXED_LOCAL, - Warn, + perf, "using `Box` where unnecessary" } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 0710689c3d4..cb1122486f3 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -22,9 +22,9 @@ pub struct EtaPass; /// ``` /// where `foo(_)` is a plain function that takes the exact argument type of /// `x`. -declare_lint! { +declare_clippy_lint! { pub REDUNDANT_CLOSURE, - Warn, + style, "redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)" } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 1ca15e4d24f..d034104a609 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -21,9 +21,9 @@ use utils::{get_parent_expr, span_lint, span_note_and_lint}; /// let a = {x = 1; 1} + x; /// // Unclear whether a is 1 or 2. /// ``` -declare_lint! { +declare_clippy_lint! { pub EVAL_ORDER_DEPENDENCE, - Warn, + complexity, "whether a variable read occurs before a write depends on sub-expression evaluation order" } @@ -43,9 +43,9 @@ declare_lint! { /// let x = (a, b, c, panic!()); /// // can simply be replaced by `panic!()` /// ``` -declare_lint! { +declare_clippy_lint! { pub DIVERGING_SUB_EXPRESSION, - Warn, + complexity, "whether an expression contains a diverging sub expression" } diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 7ea96cabfac..bad5bbd8422 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -15,9 +15,9 @@ use utils::opt_def_id; /// // this would be clearer as `eprintln!("foo: {:?}", bar);` /// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); /// ``` -declare_lint! { +declare_clippy_lint! { pub EXPLICIT_WRITE, - Warn, + complexity, "using the `write!()` family of functions instead of the `print!()` family \ of functions, when using the latter would work" } diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 5b9830ad0ab..dd37a6725d2 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -20,8 +20,9 @@ use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; /// } /// } /// ``` -declare_lint! { - pub FALLIBLE_IMPL_FROM, Allow, +declare_clippy_lint! { + pub FALLIBLE_IMPL_FROM, + nursery, "Warn on impls of `From<..>` that contain `panic!()` or `unwrap()`" } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index d86e6839cfb..7136eff3274 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -21,9 +21,9 @@ use utils::{is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, sn /// format!("foo") /// format!("{}", foo) /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_FORMAT, - Warn, + complexity, "useless use of `format!`" } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index e016fa3d595..ff40839637b 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -15,9 +15,9 @@ use syntax::ptr::P; /// ```rust,ignore /// a =- 42; // confusing, should it be `a -= 42` or `a = -42`? /// ``` -declare_lint! { +declare_clippy_lint! { pub SUSPICIOUS_ASSIGNMENT_FORMATTING, - Warn, + style, "suspicious formatting of `*=`, `-=` or `!=`" } @@ -41,9 +41,9 @@ declare_lint! { /// if bar { // this is the `else` block of the previous `if`, but should it be? /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SUSPICIOUS_ELSE_FORMATTING, - Warn, + style, "suspicious formatting of `else if`" } @@ -61,9 +61,9 @@ declare_lint! { /// -4, -5, -6 /// ]; /// ``` -declare_lint! { +declare_clippy_lint! { pub POSSIBLE_MISSING_COMMA, - Warn, + style, "possible missing comma in array" } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 4bf4aafcc4e..719708d6d18 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -22,9 +22,9 @@ use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: /// f32) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub TOO_MANY_ARGUMENTS, - Warn, + style, "functions with too many arguments" } @@ -48,9 +48,9 @@ declare_lint! { /// ```rust /// pub fn foo(x: *const u8) { println!("{}", unsafe { *x }); } /// ``` -declare_lint! { +declare_clippy_lint! { pub NOT_UNSAFE_PTR_ARG_DEREF, - Warn, + correctness, "public functions dereferencing raw pointer arguments but not marked `unsafe`" } diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index d64f352d7f1..8132ce73944 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -15,9 +15,9 @@ use utils::{opt_def_id, paths, resolve_node}; /// // format!() returns a `String` /// let s: String = format!("hello").into(); /// ``` -declare_lint! { +declare_clippy_lint! { pub IDENTITY_CONVERSION, - Warn, + complexity, "using always-identical `Into`/`From` conversions" } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 717245ec0f5..c6b4f9f1af3 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -16,9 +16,9 @@ use rustc::ty; /// ```rust /// x / 1 + 0 * 1 - 0 | 0 /// ``` -declare_lint! { +declare_clippy_lint! { pub IDENTITY_OP, - Warn, + complexity, "using identity operations, e.g. `x + 0` or `y / 1`" } diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 27f41c0e698..2465c5351bd 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -28,9 +28,9 @@ use utils::{match_qpath, paths, snippet, span_lint_and_then}; /// if Some(42).is_some() {} /// ``` /// -declare_lint! { +declare_clippy_lint! { pub IF_LET_REDUNDANT_PATTERN_MATCHING, - Warn, + style, "use the proper utility function avoiding an `if let`" } diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index d7d98351647..ea264bf5186 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -31,9 +31,9 @@ use utils::{in_external_macro, span_help_and_lint}; /// a() /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub IF_NOT_ELSE, - Allow, + pedantic, "`if` branches that could be swapped so no negation operation is necessary on the condition" } diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 3a5bcdc78d4..238970d4a9f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -13,9 +13,9 @@ use utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span /// ```rust /// repeat(1_u8).iter().collect::>() /// ``` -declare_lint! { +declare_clippy_lint! { pub INFINITE_ITER, - Warn, + correctness, "infinite iteration" } @@ -31,9 +31,9 @@ declare_lint! { /// ```rust /// [0..].iter().zip(infinite_iter.take_while(|x| x > 5)) /// ``` -declare_lint! { +declare_clippy_lint! { pub MAYBE_INFINITE_ITER, - Allow, + pedantic, "possible infinite iteration" } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 99b7812472a..243498d2d4e 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -20,9 +20,9 @@ use utils::sugg::DiagnosticBuilderExt; /// fn name(&self) -> &'static str; /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub INLINE_FN_WITHOUT_BODY, - Warn, + complexity, "use of `#[inline]` on trait methods without bodies" } diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 6e74547b75f..42fb8440ac8 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -22,9 +22,9 @@ use utils::{snippet_opt, span_lint_and_then}; /// ```rust /// x > y /// ``` -declare_lint! { +declare_clippy_lint! { pub INT_PLUS_ONE, - Allow, + complexity, "instead of using x >= y + 1, use x > y" } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 6e6b0392a90..037f07be1d7 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -13,9 +13,9 @@ use utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; /// ```rust /// let bad_ref: &usize = std::mem::zeroed(); /// ``` -declare_lint! { +declare_clippy_lint! { pub INVALID_REF, - Warn, + correctness, "creation of invalid reference" } diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 2aabecabff0..f39f60f079c 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -26,9 +26,9 @@ use utils::{in_macro, span_lint}; /// foo(); // prints "foo" /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub ITEMS_AFTER_STATEMENTS, - Allow, + pedantic, "blocks where an item comes after a statement" } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 668e8e992ec..fd3d9714b86 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -21,9 +21,9 @@ use rustc::ty::layout::LayoutOf; /// B([i32; 8000]), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub LARGE_ENUM_VARIANT, - Warn, + perf, "large size difference between variants on an enum" } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 4499f41fc1d..df3239ee1c7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -22,9 +22,9 @@ use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, wal /// ```rust /// if x.len() == 0 { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub LEN_ZERO, - Warn, + style, "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ could be used instead" } @@ -46,9 +46,9 @@ declare_lint! { /// pub fn len(&self) -> usize { .. } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub LEN_WITHOUT_IS_EMPTY, - Warn, + style, "traits or impls with a public `len` method but no corresponding `is_empty` method" } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 257f619ec29..15230ddf7e4 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -44,9 +44,9 @@ use utils::{snippet, span_lint_and_then}; /// None /// }; /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_LET_IF_SEQ, - Warn, + style, "unidiomatic `let mut` declaration followed by initialization in `if`" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d6b1fe0b8c..045b7c02905 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -60,12 +60,6 @@ extern crate url; #[macro_use] extern crate if_chain; -macro_rules! declare_restriction_lint { - { pub $name:tt, $description:tt } => { - declare_lint! { pub $name, Allow, $description } - }; -} - macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { declare_lint! { pub $name, Warn, $description } @@ -79,6 +73,18 @@ macro_rules! declare_clippy_lint { { pub $name:tt, perf, $description:tt } => { declare_lint! { pub $name, Warn, $description } }; + { pub $name:tt, pedantic, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; + { pub $name:tt, restriction, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; + { pub $name:tt, nursery, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; + { pub $name:tt, internal, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; } pub mod consts; @@ -407,45 +413,36 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ]); reg.register_lint_group("clippy_pedantic", vec![ - booleans::NONMINIMAL_BOOL, + attrs::INLINE_ALWAYS, + copies::MATCH_SAME_ARMS, + derive::EXPL_IMPL_CLONE_ON_COPY, + doc::DOC_MARKDOWN, empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, - fallible_impl_from::FALLIBLE_IMPL_FROM, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, - int_plus_one::INT_PLUS_ONE, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, - mem_forget::MEM_FORGET, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, - methods::OPTION_UNWRAP_USED, methods::RESULT_MAP_UNWRAP_OR_ELSE, - methods::RESULT_UNWRAP_USED, - methods::WRONG_PUB_SELF_CONVENTION, misc::USED_UNDERSCORE_BINDING, misc_early::UNSEPARATED_LITERAL_SUFFIX, - missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, mut_mut::MUT_MUT, mutex_atomic::MUTEX_INTEGER, + needless_continue::NEEDLESS_CONTINUE, non_expressive_names::SIMILAR_NAMES, - print::PRINT_STDOUT, - print::USE_DEBUG, - ranges::RANGE_PLUS_ONE, replace_consts::REPLACE_CONSTS, - shadow::SHADOW_REUSE, - shadow::SHADOW_SAME, - shadow::SHADOW_UNRELATED, - strings::STRING_ADD, strings::STRING_ADD_ASSIGN, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, types::CAST_PRECISION_LOSS, types::CAST_SIGN_LOSS, types::INVALID_UPCAST_COMPARISONS, + types::LINKEDLIST, unicode::NON_ASCII_LITERAL, unicode::UNICODE_NOT_NFC, use_self::USE_SELF, @@ -457,66 +454,29 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ]); reg.register_lint_group("clippy", vec![ - array_indexing::OUT_OF_BOUNDS_INDEXING, + ]); + + reg.register_lint_group("clippy_style", vec![ assign_ops::ASSIGN_OP_PATTERN, - assign_ops::MISREFACTORED_ASSIGN_OP, - attrs::DEPRECATED_SEMVER, attrs::EMPTY_LINE_AFTER_OUTER_ATTR, - attrs::INLINE_ALWAYS, - attrs::USELESS_ATTRIBUTE, - bit_mask::BAD_BIT_MASK, - bit_mask::INEFFECTIVE_BIT_MASK, bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, - booleans::LOGIC_BUG, - bytecount::NAIVE_BYTECOUNT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, - copies::IF_SAME_THEN_ELSE, - copies::IFS_SAME_COND, - copies::MATCH_SAME_ARMS, - cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, - derive::DERIVE_HASH_XOR_EQ, - derive::EXPL_IMPL_CLONE_ON_COPY, - doc::DOC_MARKDOWN, - double_comparison::DOUBLE_COMPARISONS, - double_parens::DOUBLE_PARENS, - drop_forget_ref::DROP_COPY, - drop_forget_ref::DROP_REF, - drop_forget_ref::FORGET_COPY, - drop_forget_ref::FORGET_REF, - entry::MAP_ENTRY, - enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, - eq_op::EQ_OP, eq_op::OP_REF, - erasing_op::ERASING_OP, - escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, - eval_order_dependence::DIVERGING_SUB_EXPRESSION, - eval_order_dependence::EVAL_ORDER_DEPENDENCE, - explicit_write::EXPLICIT_WRITE, - format::USELESS_FORMAT, formatting::POSSIBLE_MISSING_COMMA, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, - functions::NOT_UNSAFE_PTR_ARG_DEREF, functions::TOO_MANY_ARGUMENTS, - identity_conversion::IDENTITY_CONVERSION, - identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, - infinite_iter::INFINITE_ITER, - inline_fn_without_body::INLINE_FN_WITHOUT_BODY, - invalid_ref::INVALID_REF, - large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, - lifetimes::NEEDLESS_LIFETIMES, - lifetimes::UNUSED_LIFETIMES, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, @@ -525,20 +485,13 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::EXPLICIT_INTO_ITER_LOOP, loops::EXPLICIT_ITER_LOOP, loops::FOR_KV_MAP, - loops::FOR_LOOP_OVER_OPTION, - loops::FOR_LOOP_OVER_RESULT, - loops::ITER_NEXT_LOOP, loops::MANUAL_MEMCPY, - loops::MUT_RANGE_BOUND, loops::NEEDLESS_RANGE_LOOP, loops::NEVER_LOOP, - loops::REVERSE_RANGE_LOOP, loops::UNUSED_COLLECT, - loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, map_clone::MAP_CLONE, - matches::MATCH_AS_REF, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, @@ -546,12 +499,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { matches::SINGLE_MATCH, methods::CHARS_LAST_CMP, methods::CHARS_NEXT_CMP, - methods::CLONE_DOUBLE_REF, - methods::CLONE_ON_COPY, methods::FILTER_NEXT, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, - methods::ITER_NTH, methods::ITER_SKIP_NEXT, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, @@ -559,19 +509,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::OR_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, - methods::SINGLE_CHAR_PATTERN, methods::STRING_EXTEND_CHARS, - methods::TEMPORARY_CSTRING_AS_PTR, methods::UNNECESSARY_FOLD, - methods::USELESS_ASREF, methods::WRONG_SELF_CONVENTION, - minmax::MIN_MAX, - misc::CMP_NAN, - misc::CMP_OWNED, - misc::FLOAT_CMP, - misc::MODULO_ONE, misc::REDUNDANT_PATTERN, - misc::SHORT_CIRCUIT_STATEMENT, misc::TOPLEVEL_REF_ARG, misc::ZERO_PTR, misc_early::BUILTIN_TYPE_SHADOW, @@ -580,50 +521,70 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc_early::MIXED_CASE_HEX_LITERALS, misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, - misc_early::ZERO_PREFIXED_LITERAL, mut_reference::UNNECESSARY_MUT_PASSED, - mutex_atomic::MUTEX_ATOMIC, needless_bool::BOOL_COMPARISON, - needless_bool::NEEDLESS_BOOL, - needless_borrow::NEEDLESS_BORROW, - needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, - needless_continue::NEEDLESS_CONTINUE, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, - needless_update::NEEDLESS_UPDATE, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, - no_effect::NO_EFFECT, - no_effect::UNNECESSARY_OPERATION, non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, - open_options::NONSENSICAL_OPEN_OPTIONS, - overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic::PANIC_PARAMS, - partialeq_ne_impl::PARTIALEQ_NE_IMPL, - precedence::PRECEDENCE, print::PRINT_WITH_NEWLINE, print::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, - ptr::MUT_FROM_REF, ptr::PTR_ARG, question_mark::QUESTION_MARK, - ranges::ITERATOR_STEP_BY_ZERO, ranges::RANGE_MINUS_ONE, - ranges::RANGE_ZIP_WITH_LEN, redundant_field_names::REDUNDANT_FIELD_NAMES, - reference::DEREF_ADDROF, - regex::INVALID_REGEX, regex::REGEX_MACRO, regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, - serde_api::SERDE_API_MISUSE, strings::STRING_LIT_AS_BYTES, - suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, - suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, - swap::ALMOST_SWAPPED, + types::IMPLICIT_HASHER, + types::LET_UNIT_VALUE, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + ]); + + reg.register_lint_group("clippy_complexity", vec![ + assign_ops::MISREFACTORED_ASSIGN_OP, + booleans::NONMINIMAL_BOOL, + cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + double_comparison::DOUBLE_COMPARISONS, + double_parens::DOUBLE_PARENS, + eval_order_dependence::DIVERGING_SUB_EXPRESSION, + eval_order_dependence::EVAL_ORDER_DEPENDENCE, + explicit_write::EXPLICIT_WRITE, + format::USELESS_FORMAT, + identity_conversion::IDENTITY_CONVERSION, + identity_op::IDENTITY_OP, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, + int_plus_one::INT_PLUS_ONE, + lifetimes::NEEDLESS_LIFETIMES, + lifetimes::UNUSED_LIFETIMES, + loops::FOR_LOOP_OVER_OPTION, + loops::FOR_LOOP_OVER_RESULT, + loops::ITER_NEXT_LOOP, + loops::MUT_RANGE_BOUND, + matches::MATCH_AS_REF, + methods::CLONE_ON_COPY, + methods::USELESS_ASREF, + misc::FLOAT_CMP, + misc::SHORT_CIRCUIT_STATEMENT, + misc_early::ZERO_PREFIXED_LITERAL, + needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, + needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, + needless_update::NEEDLESS_UPDATE, + no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, + partialeq_ne_impl::PARTIALEQ_NE_IMPL, + precedence::PRECEDENCE, + ranges::RANGE_ZIP_WITH_LEN, + reference::DEREF_ADDROF, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, @@ -634,39 +595,76 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_INT_TO_FLOAT, transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, - transmute::WRONG_TRANSMUTE, - types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, types::CAST_LOSSLESS, types::CHAR_LIT_AS_U8, - types::IMPLICIT_HASHER, - types::LET_UNIT_VALUE, - types::LINKEDLIST, types::OPTION_OPTION, types::TYPE_COMPLEXITY, types::UNIT_ARG, - types::UNIT_CMP, types::UNNECESSARY_CAST, - unicode::ZERO_WIDTH_SPACE, - unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, - unused_io_amount::UNUSED_IO_AMOUNT, unused_label::UNUSED_LABEL, - vec::USELESS_VEC, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); - reg.register_lint_group("clippy_style", vec![ - ]); - - reg.register_lint_group("clippy_complexity", vec![ - ]); - reg.register_lint_group("clippy_correctness", vec![ approx_const::APPROX_CONSTANT, + array_indexing::OUT_OF_BOUNDS_INDEXING, + attrs::DEPRECATED_SEMVER, + attrs::USELESS_ATTRIBUTE, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + booleans::LOGIC_BUG, + copies::IF_SAME_THEN_ELSE, + copies::IFS_SAME_COND, + derive::DERIVE_HASH_XOR_EQ, + drop_forget_ref::DROP_COPY, + drop_forget_ref::DROP_REF, + drop_forget_ref::FORGET_COPY, + drop_forget_ref::FORGET_REF, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, + eq_op::EQ_OP, + erasing_op::ERASING_OP, + functions::NOT_UNSAFE_PTR_ARG_DEREF, + infinite_iter::INFINITE_ITER, + invalid_ref::INVALID_REF, + loops::REVERSE_RANGE_LOOP, + loops::WHILE_IMMUTABLE_CONDITION, + methods::CLONE_DOUBLE_REF, + methods::TEMPORARY_CSTRING_AS_PTR, + minmax::MIN_MAX, + misc::CMP_NAN, + misc::MODULO_ONE, + open_options::NONSENSICAL_OPEN_OPTIONS, + ptr::MUT_FROM_REF, + ranges::ITERATOR_STEP_BY_ZERO, + regex::INVALID_REGEX, + serde_api::SERDE_API_MISUSE, + suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, + suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, + swap::ALMOST_SWAPPED, + transmute::WRONG_TRANSMUTE, + types::ABSURD_EXTREME_COMPARISONS, + types::UNIT_CMP, + unicode::ZERO_WIDTH_SPACE, + unused_io_amount::UNUSED_IO_AMOUNT, ]); reg.register_lint_group("clippy_perf", vec![ + bytecount::NAIVE_BYTECOUNT, + entry::MAP_ENTRY, + escape::BOXED_LOCAL, + large_enum_variant::LARGE_ENUM_VARIANT, + methods::ITER_NTH, + methods::SINGLE_CHAR_PATTERN, + misc::CMP_OWNED, + mutex_atomic::MUTEX_ATOMIC, + vec::USELESS_VEC, + ]); + + reg.register_lint_group("clippy_nursery", vec![ + fallible_impl_from::FALLIBLE_IMPL_FROM, + ranges::RANGE_PLUS_ONE, ]); } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index f2381cc39eb..5fe76112e52 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -22,9 +22,9 @@ use syntax::symbol::keywords; /// ```rust /// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_LIFETIMES, - Warn, + complexity, "using explicit lifetimes for references in function arguments when elision rules \ would allow omitting them" } @@ -42,9 +42,9 @@ declare_lint! { /// ```rust /// fn unused_lifetime<'a>(x: u8) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub UNUSED_LIFETIMES, - Warn, + complexity, "unused lifetimes in function definitions" } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index b505a4c30a5..89396ebd5b3 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -18,9 +18,9 @@ use utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; /// ```rust /// 61864918973511 /// ``` -declare_lint! { +declare_clippy_lint! { pub UNREADABLE_LITERAL, - Warn, + style, "long integer literal without underscores" } @@ -37,9 +37,9 @@ declare_lint! { /// ```rust /// 618_64_9189_73_511 /// ``` -declare_lint! { +declare_clippy_lint! { pub INCONSISTENT_DIGIT_GROUPING, - Warn, + style, "integer literals with digits grouped inconsistently" } @@ -56,9 +56,9 @@ declare_lint! { /// ```rust /// 6186491_8973511 /// ``` -declare_lint! { +declare_clippy_lint! { pub LARGE_DIGIT_GROUPS, - Warn, + style, "grouping digits into groups that are too large" } @@ -74,8 +74,9 @@ declare_lint! { /// `255` => `0xFF` /// `65_535` => `0xFFFF` /// `4_042_322_160` => `0xF0F0_F0F0` -declare_restriction_lint! { +declare_clippy_lint! { pub DECIMAL_LITERAL_REPRESENTATION, + restriction, "using decimal representation when hexadecimal would be better" } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a76b46a1bcb..48b77be662b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -38,9 +38,9 @@ use utils::paths; /// dst[i + 64] = src[i]; /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MANUAL_MEMCPY, - Warn, + style, "manually copying items between slices" } @@ -58,9 +58,9 @@ declare_lint! { /// println!("{}", vec[i]); /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_RANGE_LOOP, - Warn, + style, "for-looping over a range of indices where an iterator over items would do" } @@ -77,9 +77,9 @@ declare_lint! { /// // with `y` a `Vec` or slice: /// for x in y.iter() { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub EXPLICIT_ITER_LOOP, - Warn, + style, "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } @@ -95,9 +95,9 @@ declare_lint! { /// // with `y` a `Vec` or slice: /// for x in y.into_iter() { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub EXPLICIT_INTO_ITER_LOOP, - Warn, + style, "for-looping over `_.into_iter()` when `_` would do" } @@ -117,9 +117,9 @@ declare_lint! { /// ```rust /// for x in y.next() { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub ITER_NEXT_LOOP, - Warn, + complexity, "for-looping over `_.next()` which is probably not intended" } @@ -139,9 +139,9 @@ declare_lint! { /// ```rust /// if let Some(x) = option { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub FOR_LOOP_OVER_OPTION, - Warn, + complexity, "for-looping over an `Option`, which is more clearly expressed as an `if let`" } @@ -161,9 +161,9 @@ declare_lint! { /// ```rust /// if let Ok(x) = result { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub FOR_LOOP_OVER_RESULT, - Warn, + complexity, "for-looping over a `Result`, which is more clearly expressed as an `if let`" } @@ -189,9 +189,9 @@ declare_lint! { /// // .. do something with x /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub WHILE_LET_LOOP, - Warn, + style, "`loop { if let { ... } else break }`, which can be written as a `while let` loop" } @@ -207,9 +207,9 @@ declare_lint! { /// ```rust /// vec.iter().map(|x| /* some operation returning () */).collect::>(); /// ``` -declare_lint! { +declare_clippy_lint! { pub UNUSED_COLLECT, - Warn, + style, "`collect()`ing an iterator without using the result; this is usually better \ written as a for loop" } @@ -230,9 +230,9 @@ declare_lint! { /// ```rust /// for x in 5..10-5 { .. } // oops, stray `-` /// ``` -declare_lint! { +declare_clippy_lint! { pub REVERSE_RANGE_LOOP, - Warn, + correctness, "iteration over an empty range, such as `10..0` or `5..5`" } @@ -250,9 +250,9 @@ declare_lint! { /// for i in 0..v.len() { foo(v[i]); /// for i in 0..v.len() { bar(i, v[i]); } /// ``` -declare_lint! { +declare_clippy_lint! { pub EXPLICIT_COUNTER_LOOP, - Warn, + style, "for-looping with an explicit counter when `_.enumerate()` would do" } @@ -268,9 +268,9 @@ declare_lint! { /// ```rust /// loop {} /// ``` -declare_lint! { +declare_clippy_lint! { pub EMPTY_LOOP, - Warn, + style, "empty `loop {}`, which should block or sleep" } @@ -285,9 +285,9 @@ declare_lint! { /// ```rust /// while let Some(val) = iter() { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub WHILE_LET_ON_ITERATOR, - Warn, + style, "using a while-let loop instead of a for loop on an iterator" } @@ -309,9 +309,9 @@ declare_lint! { /// ```rust /// for k in map.keys() { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub FOR_KV_MAP, - Warn, + style, "looping on a map using `iter` when `keys` or `values` would do" } @@ -327,17 +327,29 @@ declare_lint! { /// ```rust /// loop { ..; break; } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEVER_LOOP, - Warn, + style, "any loop that will always `break` or `return`" } -/// TODO: add documentation - -declare_lint! { +/// **What it does:** Checks for loops which have a range bound that is a mutable variable +/// +/// **Why is this bad?** One might think that modifying the mutable variable changes the loop bounds +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let mut foo = 42; +/// for i in 0..foo { +/// foo -= 1; +/// println!("{}", i); // prints numbers from 0 to 42, not 0 to 21 +/// } +/// ``` +declare_clippy_lint! { pub MUT_RANGE_BOUND, - Warn, + complexity, "for loop over a range where one of the bounds is a mutable variable" } @@ -358,9 +370,9 @@ declare_lint! { /// println!("let me loop forever!"); /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub WHILE_IMMUTABLE_CONDITION, - Warn, + correctness, "variables used within while expression are not mutated in the body" } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4eeaf675c88..23d3c8d433d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -18,9 +18,9 @@ use utils::{get_arg_name, is_adjusted, iter_input_pats, match_qpath, match_trait /// ```rust /// x.map(|e| e.clone()); /// ``` -declare_lint! { +declare_clippy_lint! { pub MAP_CLONE, - Warn, + style, "using `.map(|x| x.clone())` to clone an iterator or option's contents" } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b617f098e3e..67971998477 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -25,9 +25,9 @@ use consts::{constant, Constant}; /// _ => () /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SINGLE_MATCH, - Warn, + style, "a match statement with a single nontrivial arm (i.e. where the other arm \ is `_ => {}`) instead of `if let`" } @@ -46,9 +46,9 @@ declare_lint! { /// _ => bar(other_ref), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SINGLE_MATCH_ELSE, - Allow, + pedantic, "a match statement with a two arms where the second arm's pattern is a wildcard \ instead of `if let`" } @@ -70,9 +70,9 @@ declare_lint! { /// _ => frob(&x), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_REF_PATS, - Warn, + style, "a match or `if let` with all arms prefixed with `&` instead of deref-ing the match expression" } @@ -91,9 +91,9 @@ declare_lint! { /// false => bar(), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_BOOL, - Warn, + style, "a match on a boolean expression instead of an `if..else` block" } @@ -113,9 +113,9 @@ declare_lint! { /// _ => (), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_OVERLAPPING_ARM, - Warn, + style, "a match with overlapping arms" } @@ -135,9 +135,9 @@ declare_lint! { /// Err(_) => panic!("err"), /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_WILD_ERR_ARM, - Warn, + style, "a match with `Err(_)` arm and take drastic actions" } @@ -156,9 +156,9 @@ declare_lint! { /// Some(ref v) => Some(v), /// }; /// ``` -declare_lint! { +declare_clippy_lint! { pub MATCH_AS_REF, - Warn, + complexity, "a match on an Option value instead of using `as_ref()` or `as_mut`" } diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 103dbb72229..603fbef3421 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -14,9 +14,9 @@ use utils::{match_def_path, opt_def_id, paths, span_lint}; /// ```rust /// mem::forget(Rc::new(55))) /// ``` -declare_lint! { +declare_clippy_lint! { pub MEM_FORGET, - Allow, + restriction, "`mem::forget` usage on `Drop` types, likely to cause memory leaks" } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index a9882bdfe0c..abce4c2d5fb 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -31,9 +31,9 @@ pub struct Pass; /// ```rust /// x.unwrap() /// ``` -declare_lint! { +declare_clippy_lint! { pub OPTION_UNWRAP_USED, - Allow, + restriction, "using `Option.unwrap()`, which should at least get a better message using `expect()`" } @@ -53,9 +53,9 @@ declare_lint! { /// ```rust /// x.unwrap() /// ``` -declare_lint! { +declare_clippy_lint! { pub RESULT_UNWRAP_USED, - Allow, + restriction, "using `Result.unwrap()`, which might be better handled" } @@ -79,9 +79,9 @@ declare_lint! { /// fn add(&self, other: &X) -> X { .. } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SHOULD_IMPLEMENT_TRAIT, - Warn, + style, "defining a method that should be implementing a std trait" } @@ -108,9 +108,9 @@ declare_lint! { /// fn as_str(self) -> &str { .. } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub WRONG_SELF_CONVENTION, - Warn, + style, "defining a method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention" } @@ -130,9 +130,9 @@ declare_lint! { /// pub fn as_str(self) -> &str { .. } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub WRONG_PUB_SELF_CONVENTION, - Allow, + restriction, "defining a public method named with an established prefix (like \"into_\") that takes \ `self` with the wrong convention" } @@ -142,15 +142,15 @@ declare_lint! { /// **Why is this bad?** Because you usually call `expect()` on the `Result` /// directly to get a better error message. /// -/// **Known problems:** None. +/// **Known problems:** The error type needs to implement `Debug` /// /// **Example:** /// ```rust /// x.ok().expect("why did I do this again?") /// ``` -declare_lint! { +declare_clippy_lint! { pub OK_EXPECT, - Warn, + style, "using `ok().expect()`, which gives worse error messages than \ calling `expect` directly on the Result" } @@ -166,9 +166,9 @@ declare_lint! { /// ```rust /// x.map(|a| a + 1).unwrap_or(0) /// ``` -declare_lint! { +declare_clippy_lint! { pub OPTION_MAP_UNWRAP_OR, - Allow, + pedantic, "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ `map_or(a, f)`" } @@ -184,9 +184,9 @@ declare_lint! { /// ```rust /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` -declare_lint! { +declare_clippy_lint! { pub OPTION_MAP_UNWRAP_OR_ELSE, - Allow, + pedantic, "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ `map_or_else(g, f)`" } @@ -202,9 +202,9 @@ declare_lint! { /// ```rust /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` -declare_lint! { +declare_clippy_lint! { pub RESULT_MAP_UNWRAP_OR_ELSE, - Allow, + pedantic, "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ `.ok().map_or_else(g, f)`" } @@ -220,9 +220,9 @@ declare_lint! { /// ```rust /// opt.map_or(None, |a| a + 1) /// ``` -declare_lint! { +declare_clippy_lint! { pub OPTION_MAP_OR_NONE, - Warn, + style, "using `Option.map_or(None, f)`, which is more succinctly expressed as \ `and_then(f)`" } @@ -238,9 +238,9 @@ declare_lint! { /// ```rust /// iter.filter(|x| x == 0).next() /// ``` -declare_lint! { +declare_clippy_lint! { pub FILTER_NEXT, - Warn, + style, "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" } @@ -257,9 +257,9 @@ declare_lint! { /// ```rust /// iter.filter(|x| x == 0).map(|x| x * 2) /// ``` -declare_lint! { +declare_clippy_lint! { pub FILTER_MAP, - Allow, + pedantic, "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ usually be written as a single method call" } @@ -276,9 +276,9 @@ declare_lint! { /// ```rust /// iter.find(|x| x == 0).is_some() /// ``` -declare_lint! { +declare_clippy_lint! { pub SEARCH_IS_SOME, - Warn, + style, "using an iterator search followed by `is_some()`, which is more succinctly \ expressed as a call to `any()`" } @@ -295,9 +295,9 @@ declare_lint! { /// ```rust /// name.chars().next() == Some('_') /// ``` -declare_lint! { +declare_clippy_lint! { pub CHARS_NEXT_CMP, - Warn, + style, "using `.chars().next()` to check if a string starts with a char" } @@ -323,9 +323,9 @@ declare_lint! { /// ```rust /// foo.unwrap_or_default() /// ``` -declare_lint! { +declare_clippy_lint! { pub OR_FUN_CALL, - Warn, + style, "using any `*or` method with a function call, which suggests `*or_else`" } @@ -340,9 +340,9 @@ declare_lint! { /// ```rust /// 42u64.clone() /// ``` -declare_lint! { +declare_clippy_lint! { pub CLONE_ON_COPY, - Warn, + complexity, "using `clone` on a `Copy` type" } @@ -358,8 +358,9 @@ declare_lint! { /// ```rust /// x.clone() /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub CLONE_ON_REF_PTR, + restriction, "using 'clone' on a ref-counted pointer" } @@ -379,9 +380,9 @@ declare_restriction_lint! { /// println!("{:p} {:p}",*y, z); // prints out the same pointer /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub CLONE_DOUBLE_REF, - Warn, + correctness, "using `clone` on `&&T`" } @@ -399,9 +400,9 @@ declare_lint! { /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEW_RET_NO_SELF, - Warn, + style, "not returning `Self` in a `new` method" } @@ -415,9 +416,9 @@ declare_lint! { /// /// **Example:** /// `_.split("x")` could be `_.split('x') -declare_lint! { +declare_clippy_lint! { pub SINGLE_CHAR_PATTERN, - Warn, + perf, "using a single-character str where a char could be used, e.g. \ `_.split(\"x\")`" } @@ -444,9 +445,9 @@ declare_lint! { /// call_some_ffi_func(c_str.as_ptr()); /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub TEMPORARY_CSTRING_AS_PTR, - Warn, + correctness, "getting the inner pointer of a temporary `CString`" } @@ -470,9 +471,9 @@ declare_lint! { /// let bad_vec = some_vec.get(3); /// let bad_slice = &some_vec[..].get(3); /// ``` -declare_lint! { +declare_clippy_lint! { pub ITER_NTH, - Warn, + perf, "using `.iter().nth()` on a standard library type with O(1) element access" } @@ -494,9 +495,9 @@ declare_lint! { /// let bad_vec = some_vec.iter().nth(3); /// let bad_slice = &some_vec[..].iter().nth(3); /// ``` -declare_lint! { +declare_clippy_lint! { pub ITER_SKIP_NEXT, - Warn, + style, "using `.skip(x).next()` on an iterator" } @@ -520,9 +521,9 @@ declare_lint! { /// let last = some_vec[3]; /// some_vec[0] = 1; /// ``` -declare_lint! { +declare_clippy_lint! { pub GET_UNWRAP, - Warn, + style, "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead" } @@ -549,9 +550,9 @@ declare_lint! { /// s.push_str(abc); /// s.push_str(&def)); /// ``` -declare_lint! { +declare_clippy_lint! { pub STRING_EXTEND_CHARS, - Warn, + style, "using `x.extend(s.chars())` where s is a `&str` or `String`" } @@ -572,9 +573,9 @@ declare_lint! { /// let s = [1,2,3,4,5]; /// let s2 : Vec = s.to_vec(); /// ``` -declare_lint! { +declare_clippy_lint! { pub ITER_CLONED_COLLECT, - Warn, + style, "using `.cloned().collect()` on slice to create a `Vec`" } @@ -590,9 +591,9 @@ declare_lint! { /// ```rust /// name.chars().last() == Some('_') || name.chars().next_back() == Some('-') /// ``` -declare_lint! { +declare_clippy_lint! { pub CHARS_LAST_CMP, - Warn, + style, "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char" } @@ -613,9 +614,9 @@ declare_lint! { /// let x: &[i32] = &[1,2,3,4,5]; /// do_stuff(x); /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_ASREF, - Warn, + complexity, "using `as_ref` where the types before and after the call are the same" } @@ -636,9 +637,9 @@ declare_lint! { /// ```rust /// let _ = (0..3).any(|x| x > 2); /// ``` -declare_lint! { +declare_clippy_lint! { pub UNNECESSARY_FOLD, - Warn, + style, "using `fold` when a more succinct alternative exists" } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index b5b844e199e..8c19f627f53 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -18,9 +18,9 @@ use utils::{match_def_path, opt_def_id, paths, span_lint}; /// ``` /// It will always be equal to `0`. Probably the author meant to clamp the value /// between 0 and 100, but has erroneously swapped `min` and `max`. -declare_lint! { +declare_clippy_lint! { pub MIN_MAX, - Warn, + correctness, "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 172de7a15a5..538a3eaaefd 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -31,9 +31,9 @@ use consts::{constant, Constant}; /// ```rust /// fn foo(ref x: u8) -> bool { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub TOPLEVEL_REF_ARG, - Warn, + style, "an entire binding declared as `ref`, in a function argument or a `let` statement" } @@ -48,9 +48,9 @@ declare_lint! { /// ```rust /// x == NAN /// ``` -declare_lint! { +declare_clippy_lint! { pub CMP_NAN, - Deny, + correctness, "comparisons to NAN, which will always return false, probably not intended" } @@ -70,9 +70,9 @@ declare_lint! { /// y == 1.23f64 /// y != x // where both are floats /// ``` -declare_lint! { +declare_clippy_lint! { pub FLOAT_CMP, - Warn, + complexity, "using `==` or `!=` on float values instead of comparing difference with an epsilon" } @@ -89,9 +89,9 @@ declare_lint! { /// ```rust /// x.to_owned() == y /// ``` -declare_lint! { +declare_clippy_lint! { pub CMP_OWNED, - Warn, + perf, "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`" } @@ -108,9 +108,9 @@ declare_lint! { /// ```rust /// x % 1 /// ``` -declare_lint! { +declare_clippy_lint! { pub MODULO_ONE, - Warn, + correctness, "taking a number modulo 1, which always returns 0" } @@ -128,9 +128,9 @@ declare_lint! { /// y @ _ => (), // easier written as `y`, /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub REDUNDANT_PATTERN, - Warn, + style, "using `name @ _` in a pattern" } @@ -150,9 +150,9 @@ declare_lint! { /// let y = _x + 1; // Here we are using `_x`, even though it has a leading /// // underscore. We should rename `_x` to `x` /// ``` -declare_lint! { +declare_clippy_lint! { pub USED_UNDERSCORE_BINDING, - Allow, + pedantic, "using a binding which is prefixed with an underscore" } @@ -170,9 +170,9 @@ declare_lint! { /// ```rust /// f() && g(); // We should write `if f() { g(); }`. /// ``` -declare_lint! { +declare_clippy_lint! { pub SHORT_CIRCUIT_STATEMENT, - Warn, + complexity, "using a short circuit boolean condition as a statement" } @@ -188,9 +188,9 @@ declare_lint! { /// ```rust /// 0 as *const u32 /// ``` -declare_lint! { +declare_clippy_lint! { pub ZERO_PTR, - Warn, + style, "using 0 as *{const, mut} T" } @@ -210,8 +210,9 @@ declare_lint! { /// const ONE == 1.00f64 /// x == ONE // where both are floats /// ``` -declare_restriction_lint! { +declare_clippy_lint! { pub FLOAT_CMP_CONST, + restriction, "using `==` or `!=` on float constants instead of comparing difference with an epsilon" } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 8ac0c4bf098..0331c976377 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -17,9 +17,9 @@ use utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_li /// ```rust /// let { a: _, b: ref b, c: _ } = .. /// ``` -declare_lint! { +declare_clippy_lint! { pub UNNEEDED_FIELD_PATTERN, - Warn, + style, "struct fields bound to a wildcard instead of using `..`" } @@ -34,9 +34,9 @@ declare_lint! { /// ```rust /// fn foo(a: i32, _a: i32) {} /// ``` -declare_lint! { +declare_clippy_lint! { pub DUPLICATE_UNDERSCORE_ARGUMENT, - Warn, + style, "function arguments having names which only differ by an underscore" } @@ -52,9 +52,9 @@ declare_lint! { /// ```rust /// (|| 42)() /// ``` -declare_lint! { +declare_clippy_lint! { pub REDUNDANT_CLOSURE_CALL, - Warn, + style, "throwaway closures called in the expression they are defined" } @@ -69,9 +69,9 @@ declare_lint! { /// ```rust /// --x; /// ``` -declare_lint! { +declare_clippy_lint! { pub DOUBLE_NEG, - Warn, + style, "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++" } @@ -86,9 +86,9 @@ declare_lint! { /// ```rust /// let y = 0x1a9BAcD; /// ``` -declare_lint! { +declare_clippy_lint! { pub MIXED_CASE_HEX_LITERALS, - Warn, + style, "hex literals whose letter digits are not consistently upper- or lowercased" } @@ -103,9 +103,9 @@ declare_lint! { /// ```rust /// let y = 123832i32; /// ``` -declare_lint! { +declare_clippy_lint! { pub UNSEPARATED_LITERAL_SUFFIX, - Allow, + pedantic, "literals whose suffix is not separated by an underscore" } @@ -141,9 +141,9 @@ declare_lint! { /// ``` /// /// prints `83` (as `83 == 0o123` while `123 == 0o173`). -declare_lint! { +declare_clippy_lint! { pub ZERO_PREFIXED_LITERAL, - Warn, + complexity, "integer literals starting with `0`" } @@ -162,9 +162,9 @@ declare_lint! { /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub BUILTIN_TYPE_SHADOW, - Warn, + style, "shadowing a builtin type" } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 82df78ec234..6a83417157b 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -35,9 +35,9 @@ use utils::in_macro; /// This lint fixes that. /// /// **Known problems:** None. -declare_lint! { +declare_clippy_lint! { pub MISSING_DOCS_IN_PRIVATE_ITEMS, - Allow, + restriction, "detects missing documentation for public and private members" } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index ca1592271b3..13c1c930a05 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -16,9 +16,9 @@ use utils::{higher, in_external_macro, span_lint}; /// ```rust /// let x = &mut &mut y; /// ``` -declare_lint! { +declare_clippy_lint! { pub MUT_MUT, - Allow, + pedantic, "usage of double-mut refs, e.g. `&mut &mut ...`" } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 63ccc77a03d..5e60ff624a1 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -16,9 +16,9 @@ use utils::span_lint; /// ```rust /// my_vec.push(&mut value) /// ``` -declare_lint! { +declare_clippy_lint! { pub UNNECESSARY_MUT_PASSED, - Warn, + style, "an argument passed as a mutable reference although the callee only demands an \ immutable reference" } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 3a1ecfbefc7..77af0be0ec8 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -22,9 +22,9 @@ use utils::{match_type, paths, span_lint}; /// ```rust /// let x = Mutex::new(&y); /// ``` -declare_lint! { +declare_clippy_lint! { pub MUTEX_ATOMIC, - Warn, + perf, "using a mutex where an atomic value could be used instead" } @@ -42,9 +42,9 @@ declare_lint! { /// ```rust /// let x = Mutex::new(0usize); /// ``` -declare_lint! { +declare_clippy_lint! { pub MUTEX_INTEGER, - Allow, + pedantic, "using a mutex for an integer type" } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index bc93190cd09..393e0ec110c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -24,9 +24,9 @@ use utils::sugg::Sugg; /// ```rust /// if x { false } else { true } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_BOOL, - Warn, + complexity, "if-statements with plain booleans in the then- and else-clause, e.g. \ `if p { true } else { false }`" } @@ -42,9 +42,9 @@ declare_lint! { /// ```rust /// if x == true { } // could be `if x { }` /// ``` -declare_lint! { +declare_clippy_lint! { pub BOOL_COMPARISON, - Warn, + style, "comparing a variable to a boolean, e.g. `if x == true`" } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index b1388864bdc..a5d89cbcb73 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -20,9 +20,9 @@ use utils::{in_macro, snippet_opt, span_lint_and_then}; /// ```rust /// let x: &i32 = &&&&&&5; /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_BORROW, - Warn, + complexity, "taking a reference that is going to be automatically dereferenced" } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index f0e5db6d404..35eb599a527 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -42,9 +42,9 @@ use utils::{in_macro, snippet, span_lint_and_then}; /// reference and /// de-referenced. /// As such, it could just be |a| a.is_empty() -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_BORROWED_REFERENCE, - Warn, + complexity, "taking a needless borrowed reference" } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 9c801ba7495..162cfc7e77f 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -93,9 +93,9 @@ use utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline /// // Do something useful /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_CONTINUE, - Warn, + pedantic, "`continue` statements that can be replaced by a rearrangement of code" } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index b189fcbff4f..02048c39265 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -39,9 +39,9 @@ use std::borrow::Cow; /// assert_eq!(v.len(), 42); /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_PASS_BY_VALUE, - Warn, + style, "functions taking arguments by value, but not consuming them in its body" } diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 5512a2092b4..fe75bfaf24c 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -15,9 +15,9 @@ use utils::span_lint; /// ```rust /// Point { x: 1, y: 0, ..zero_point } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_UPDATE, - Warn, + complexity, "using `Foo { ..base }` when there are no missing fields" } diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 2ac195f555b..5ddd0d409e3 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -15,9 +15,9 @@ use utils::span_lint; /// ```rust /// x * -1 /// ``` -declare_lint! { +declare_clippy_lint! { pub NEG_MULTIPLY, - Warn, + style, "multiplying integers with -1" } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 5f237095115..54b00081973 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -42,9 +42,9 @@ use utils::sugg::DiagnosticBuilderExt; /// ``` /// /// You can also have `new()` call `Default::default()`. -declare_lint! { +declare_clippy_lint! { pub NEW_WITHOUT_DEFAULT, - Warn, + style, "`fn new() -> Self` method without `Default` implementation" } @@ -72,9 +72,9 @@ declare_lint! { /// ``` /// /// Just prepend `#[derive(Default)]` before the `struct` definition. -declare_lint! { +declare_clippy_lint! { pub NEW_WITHOUT_DEFAULT_DERIVE, - Warn, + style, "`fn new() -> Self` without `#[derive]`able `Default` implementation" } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index a1139ff7464..1847761416b 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -16,9 +16,9 @@ use std::ops::Deref; /// ```rust /// 0; /// ``` -declare_lint! { +declare_clippy_lint! { pub NO_EFFECT, - Warn, + complexity, "statements with no effect" } @@ -34,9 +34,9 @@ declare_lint! { /// ```rust /// compute_array()[0]; /// ``` -declare_lint! { +declare_clippy_lint! { pub UNNECESSARY_OPERATION, - Warn, + complexity, "outer expressions with no effect" } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index a267900fcbb..057ed157382 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -18,9 +18,9 @@ use utils::{in_macro, span_lint, span_lint_and_then}; /// let checked_exp = something; /// let checked_expr = something_else; /// ``` -declare_lint! { +declare_clippy_lint! { pub SIMILAR_NAMES, - Allow, + pedantic, "similarly named items and bindings" } @@ -36,9 +36,9 @@ declare_lint! { /// ```rust /// let (a, b, c, d, e, f, g) = (...); /// ``` -declare_lint! { +declare_clippy_lint! { pub MANY_SINGLE_CHAR_NAMES, - Warn, + style, "too many single character bindings" } @@ -56,9 +56,9 @@ declare_lint! { /// let ___1 = 1; /// let __1___2 = 11; /// ``` -declare_lint! { +declare_clippy_lint! { pub JUST_UNDERSCORES_AND_DIGITS, - Warn, + style, "unclear name" } diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index b79e90f910b..286ed4b4d48 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -26,9 +26,9 @@ use utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub IF_LET_SOME_RESULT, - Warn, + style, "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead" } diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 248990f4f37..9ab22560093 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -16,9 +16,9 @@ use utils::{match_type, paths, span_lint, walk_ptrs_ty}; /// ```rust /// OpenOptions::new().read(true).truncate(true) /// ``` -declare_lint! { +declare_clippy_lint! { pub NONSENSICAL_OPEN_OPTIONS, - Warn, + correctness, "nonsensical combination of options for opening a file" } diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 4177f4a3e73..986206a1986 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -13,9 +13,9 @@ use utils::span_lint; /// ```rust /// a + b < a /// ``` -declare_lint! { +declare_clippy_lint! { pub OVERFLOW_CHECK_CONDITIONAL, - Warn, + complexity, "overflow checks inspired by C which are likely to panic" } diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index a768565518c..bbb62a778b5 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -17,9 +17,9 @@ use utils::{is_direct_expn_of, match_def_path, opt_def_id, paths, resolve_node, /// ```rust /// panic!("This `panic!` is probably missing a parameter there: {}"); /// ``` -declare_lint! { +declare_clippy_lint! { pub PANIC_PARAMS, - Warn, + style, "missing parameters in `panic!` calls" } diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 22dc43eb6c5..787aee71843 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -20,9 +20,9 @@ use utils::{is_automatically_derived, span_lint}; /// fn ne(&self, other: &Foo) -> bool { !(self == other) } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub PARTIALEQ_NE_IMPL, - Warn, + complexity, "re-implementing `PartialEq::ne`" } diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 5d56a927bc0..90e418f0687 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -20,9 +20,9 @@ use utils::{in_macro, snippet, span_lint_and_sugg}; /// **Example:** /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 -declare_lint! { +declare_clippy_lint! { pub PRECEDENCE, - Warn, + complexity, "operations where precedence may be unclear" } diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 451b27033ea..7413ab2ac63 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -19,9 +19,9 @@ use utils::{opt_def_id, paths}; /// ```rust /// println!(""); /// ``` -declare_lint! { +declare_clippy_lint! { pub PRINTLN_EMPTY_STRING, - Warn, + style, "using `print!()` with a format string that ends in a newline" } @@ -38,9 +38,9 @@ declare_lint! { /// ```rust /// print!("Hello {}!\n", name); /// ``` -declare_lint! { +declare_clippy_lint! { pub PRINT_WITH_NEWLINE, - Warn, + style, "using `print!()` with a format string that ends in a newline" } @@ -56,9 +56,9 @@ declare_lint! { /// ```rust /// println!("Hello world!"); /// ``` -declare_lint! { +declare_clippy_lint! { pub PRINT_STDOUT, - Allow, + restriction, "printing on stdout" } @@ -72,9 +72,9 @@ declare_lint! { /// ```rust /// println!("{:?}", foo); /// ``` -declare_lint! { +declare_clippy_lint! { pub USE_DEBUG, - Allow, + restriction, "use of `Debug`-based formatting" } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 435812bf962..17f46f78baa 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -42,9 +42,9 @@ use utils::ptr::get_spans; /// ```rust /// fn foo(&Vec) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub PTR_ARG, - Warn, + style, "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ instead, respectively" } @@ -61,9 +61,9 @@ declare_lint! { /// ```rust /// if x == ptr::null { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub CMP_NULL, - Warn, + style, "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead." } @@ -86,9 +86,9 @@ declare_lint! { /// ```rust /// fn foo(&Foo) -> &mut Bar { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub MUT_FROM_REF, - Warn, + correctness, "fns that create mutable refs from immutable ref args" } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 39fcc2b1b8f..9478d874c69 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -25,9 +25,9 @@ use utils::paths::*; /// ```rust /// option?; /// ``` -declare_lint!{ +declare_clippy_lint!{ pub QUESTION_MARK, - Warn, + style, "checks for expressions that could be replaced by the question mark operator" } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c98df6464d4..5a5dfe04d01 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -18,9 +18,9 @@ use utils::sugg::Sugg; /// ```rust /// for x in (5..5).step_by(0) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub ITERATOR_STEP_BY_ZERO, - Warn, + correctness, "using `Iterator::step_by(0)`, which produces an infinite iterator" } @@ -35,9 +35,9 @@ declare_lint! { /// ```rust /// x.iter().zip(0..x.len()) /// ``` -declare_lint! { +declare_clippy_lint! { pub RANGE_ZIP_WITH_LEN, - Warn, + complexity, "zipping iterator with a range when `enumerate()` would do" } @@ -53,9 +53,9 @@ declare_lint! { /// ```rust /// for x..(y+1) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub RANGE_PLUS_ONE, - Allow, + nursery, "`x..(y+1)` reads better as `x..=y`" } @@ -71,9 +71,9 @@ declare_lint! { /// ```rust /// for x..=(y-1) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub RANGE_MINUS_ONE, - Warn, + style, "`x..=(y-1)` reads better as `x..y`" } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index a63447575ef..5e24361f1d1 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -20,9 +20,9 @@ use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; /// /// let foo = Foo{ bar: bar } /// ``` -declare_lint! { +declare_clippy_lint! { pub REDUNDANT_FIELD_NAMES, - Warn, + style, "checks for fields in struct literals where shorthands could be used" } diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index fce3c6ad285..0d4332b4a7d 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -15,9 +15,9 @@ use utils::{snippet, span_lint_and_sugg}; /// let a = f(*&mut b); /// let c = *&d; /// ``` -declare_lint! { +declare_clippy_lint! { pub DEREF_ADDROF, - Warn, + complexity, "use of `*&` or `*&mut` in an expression" } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 93ba3f0e8e7..556ee72d995 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -19,9 +19,9 @@ use consts::{constant, Constant}; /// ```rust /// Regex::new("|") /// ``` -declare_lint! { +declare_clippy_lint! { pub INVALID_REGEX, - Deny, + correctness, "invalid regular expressions" } @@ -38,9 +38,9 @@ declare_lint! { /// ```rust /// Regex::new("^foobar") /// ``` -declare_lint! { +declare_clippy_lint! { pub TRIVIAL_REGEX, - Warn, + style, "trivial regular expressions" } @@ -57,9 +57,9 @@ declare_lint! { /// ```rust /// regex!("foo|bar") /// ``` -declare_lint! { +declare_clippy_lint! { pub REGEX_MACRO, - Warn, + style, "use of `regex!(_)` instead of `Regex::new(_)`" } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 511dbf7a40f..0677cb087d6 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -20,9 +20,9 @@ use utils::{match_def_path, span_lint_and_sugg}; /// ```rust /// static FOO: AtomicIsize = AtomicIsize::new(0); /// ``` -declare_lint! { +declare_clippy_lint! { pub REPLACE_CONSTS, - Allow, + pedantic, "Lint usages of standard library `const`s that could be replaced by `const fn`s" } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 98027885ccf..62038262de4 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -17,9 +17,9 @@ use utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_ /// ```rust /// fn foo(x: usize) { return x; } /// ``` -declare_lint! { +declare_clippy_lint! { pub NEEDLESS_RETURN, - Warn, + style, "using a return statement like `return expr;` where an expression would suffice" } @@ -35,9 +35,9 @@ declare_lint! { /// ```rust /// { let x = ..; x } /// ``` -declare_lint! { +declare_clippy_lint! { pub LET_AND_RETURN, - Warn, + style, "creating a let-binding and then immediately returning it like `let x = expr; x` at \ the end of a block" } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 0ea24a33393..588e22b7cb1 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -5,15 +5,15 @@ use utils::{get_trait_def_id, paths, span_lint}; /// **What it does:** Checks for mis-uses of the serde API. /// /// **Why is this bad?** Serde is very finnicky about how its API should be -/// used, but the type system can't be used to enforce it (yet). +/// used, but the type system can't be used to enforce it (yet?). /// /// **Known problems:** None. /// /// **Example:** Implementing `Visitor::visit_string` but not /// `Visitor::visit_str`. -declare_lint! { +declare_clippy_lint! { pub SERDE_API_MISUSE, - Warn, + correctness, "various things that will negatively affect your serde experience" } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 92ac65b5abc..8330bb7015b 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -20,9 +20,9 @@ use utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, /// ```rust /// let x = &x; /// ``` -declare_lint! { +declare_clippy_lint! { pub SHADOW_SAME, - Allow, + restriction, "rebinding a name to itself, e.g. `let mut x = &mut x`" } @@ -41,9 +41,9 @@ declare_lint! { /// ```rust /// let x = x + 1; /// ``` -declare_lint! { +declare_clippy_lint! { pub SHADOW_REUSE, - Allow, + restriction, "rebinding a name to an expression that re-uses the original value, e.g. \ `let x = x + 1`" } @@ -64,9 +64,9 @@ declare_lint! { /// ```rust /// let x = y; let x = z; // shadows the earlier binding /// ``` -declare_lint! { +declare_clippy_lint! { pub SHADOW_UNRELATED, - Allow, + restriction, "rebinding a name without even using the original value" } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index b7c671c0c48..823ed1be351 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -8,7 +8,8 @@ use utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint /// `let`!). /// /// **Why is this bad?** It's not really bad, but some people think that the -/// `.push_str(_)` method is more readable. +/// `.push_str(_)` method is more readable. Also creates a new heap allocation and throws +/// away the old one. /// /// **Known problems:** None. /// @@ -18,9 +19,9 @@ use utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint /// let mut x = "Hello".to_owned(); /// x = x + ", World"; /// ``` -declare_lint! { +declare_clippy_lint! { pub STRING_ADD_ASSIGN, - Allow, + pedantic, "using `x = x + ..` where x is a `String` instead of `push_str()`" } @@ -46,9 +47,9 @@ declare_lint! { /// let x = "Hello".to_owned(); /// x + ", World" /// ``` -declare_lint! { +declare_clippy_lint! { pub STRING_ADD, - Allow, + restriction, "using `x + ..` where x is a `String` instead of `push_str()`" } @@ -64,9 +65,9 @@ declare_lint! { /// ```rust /// let bs = "a byte string".as_bytes(); /// ``` -declare_lint! { +declare_clippy_lint! { pub STRING_LIT_AS_BYTES, - Warn, + style, "calling `as_bytes` on a string literal instead of using a byte string literal" } diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 2c3abc512bb..2c322ce6b5e 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -21,9 +21,9 @@ use utils::{get_trait_def_id, span_lint}; /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SUSPICIOUS_ARITHMETIC_IMPL, - Warn, + correctness, "suspicious use of operators in impl of arithmetic trait" } @@ -42,9 +42,9 @@ declare_lint! { /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub SUSPICIOUS_OP_ASSIGN_IMPL, - Warn, + correctness, "suspicious use of operators in impl of OpAssign trait" } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 25fc666d3e1..47ac45578be 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -17,9 +17,9 @@ use utils::sugg::Sugg; /// b = a; /// a = t; /// ``` -declare_lint! { +declare_clippy_lint! { pub MANUAL_SWAP, - Warn, + complexity, "manual swap of two variables" } @@ -34,9 +34,9 @@ declare_lint! { /// a = b; /// b = a; /// ``` -declare_lint! { +declare_clippy_lint! { pub ALMOST_SWAPPED, - Warn, + correctness, "`foo = bar; bar = foo` sequence" } diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 877321255c1..459549f1e58 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -15,9 +15,9 @@ use utils::span_lint; /// ```rust /// (0, 0).0 = 1 /// ``` -declare_lint! { +declare_clippy_lint! { pub TEMPORARY_ASSIGNMENT, - Warn, + complexity, "assignments to temporaries" } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2be5f4764f4..00d6c310c69 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -19,9 +19,9 @@ use utils::{opt_def_id, sugg}; /// ```rust /// let ptr: *const T = core::intrinsics::transmute('x')` /// ``` -declare_lint! { +declare_clippy_lint! { pub WRONG_TRANSMUTE, - Warn, + correctness, "transmutes that are confusing at best, undefined behaviour at worst and always useless" } @@ -37,9 +37,9 @@ declare_lint! { /// ```rust /// core::intrinsics::transmute(t) // where the result type is the same as `t`'s /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_TRANSMUTE, - Warn, + complexity, "transmutes that have the same to and from types or could be a cast/coercion" } @@ -55,9 +55,9 @@ declare_lint! { /// core::intrinsics::transmute(t)` // where the result type is the same as /// `*t` or `&t`'s /// ``` -declare_lint! { +declare_clippy_lint! { pub CROSSPOINTER_TRANSMUTE, - Warn, + complexity, "transmutes that have to or from types that are a pointer to the other" } @@ -73,9 +73,9 @@ declare_lint! { /// // can be written: /// let _: &T = &*p; /// ``` -declare_lint! { +declare_clippy_lint! { pub TRANSMUTE_PTR_TO_REF, - Warn, + complexity, "transmutes from a pointer to a reference type" } @@ -100,9 +100,9 @@ declare_lint! { /// // should be: /// let _ = std::char::from_u32(x).unwrap(); /// ``` -declare_lint! { +declare_clippy_lint! { pub TRANSMUTE_INT_TO_CHAR, - Warn, + complexity, "transmutes from an integer to a `char`" } @@ -127,9 +127,9 @@ declare_lint! { /// // should be: /// let _ = std::str::from_utf8(b).unwrap(); /// ``` -declare_lint! { +declare_clippy_lint! { pub TRANSMUTE_BYTES_TO_STR, - Warn, + complexity, "transmutes from a `&[u8]` to a `&str`" } @@ -145,9 +145,9 @@ declare_lint! { /// // should be: /// let _: bool = x != 0; /// ``` -declare_lint! { +declare_clippy_lint! { pub TRANSMUTE_INT_TO_BOOL, - Warn, + complexity, "transmutes from an integer to a `bool`" } @@ -163,9 +163,9 @@ declare_lint! { /// // should be: /// let _: f32 = f32::from_bits(x); /// ``` -declare_lint! { +declare_clippy_lint! { pub TRANSMUTE_INT_TO_FLOAT, - Warn, + complexity, "transmutes from an integer to a float" } @@ -180,9 +180,9 @@ declare_lint! { /// // u32 is 32-bit aligned; u8 is 8-bit aligned /// let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; /// ``` -declare_lint! { +declare_clippy_lint! { pub MISALIGNED_TRANSMUTE, - Warn, + complexity, "transmutes to a potentially less-aligned type" } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 82a1799ffd8..ba7d4bbbe0f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -44,9 +44,9 @@ pub struct TypePass; /// values: Vec, /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub BOX_VEC, - Warn, + complexity, "usage of `Box>`, vector elements are already on the heap" } @@ -64,9 +64,9 @@ declare_lint! { /// fn x() -> Option> { /// None /// } -declare_lint! { +declare_clippy_lint! { pub OPTION_OPTION, - Warn, + complexity, "usage of `Option>`" } @@ -99,9 +99,9 @@ declare_lint! { /// ```rust /// let x = LinkedList::new(); /// ``` -declare_lint! { +declare_clippy_lint! { pub LINKEDLIST, - Warn, + pedantic, "usage of LinkedList, usually a vector is faster, or a more specialized data \ structure like a VecDeque" } @@ -123,9 +123,9 @@ declare_lint! { /// ```rust /// fn foo(bar: &T) { ... } /// ``` -declare_lint! { +declare_clippy_lint! { pub BORROWED_BOX, - Warn, + complexity, "a borrow of a boxed type" } @@ -353,9 +353,9 @@ pub struct LetPass; /// ```rust /// let x = { 1; }; /// ``` -declare_lint! { +declare_clippy_lint! { pub LET_UNIT_VALUE, - Warn, + style, "creating a let binding to a value of unit type, which usually can't be used afterwards" } @@ -409,9 +409,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass { /// ```rust /// { foo(); bar(); baz(); } /// ``` -declare_lint! { +declare_clippy_lint! { pub UNIT_CMP, - Warn, + correctness, "comparing unit values" } @@ -464,9 +464,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { /// baz(a); /// }) /// ``` -declare_lint! { +declare_clippy_lint! { pub UNIT_ARG, - Warn, + complexity, "passing unit to a function" } @@ -563,9 +563,9 @@ pub struct CastPass; /// ```rust /// let x = u64::MAX; x as f64 /// ``` -declare_lint! { +declare_clippy_lint! { pub CAST_PRECISION_LOSS, - Allow, + pedantic, "casts that cause loss of precision, e.g. `x as f32` where `x: u64`" } @@ -584,9 +584,9 @@ declare_lint! { /// let y: i8 = -1; /// y as u128 // will return 18446744073709551615 /// ``` -declare_lint! { +declare_clippy_lint! { pub CAST_SIGN_LOSS, - Allow, + pedantic, "casts from signed types to unsigned types, e.g. `x as u32` where `x: i32`" } @@ -604,9 +604,9 @@ declare_lint! { /// ```rust /// fn as_u8(x: u64) -> u8 { x as u8 } /// ``` -declare_lint! { +declare_clippy_lint! { pub CAST_POSSIBLE_TRUNCATION, - Allow, + pedantic, "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, \ or `x as i32` where `x: f32`" } @@ -628,9 +628,9 @@ declare_lint! { /// ```rust /// u32::MAX as i32 // will yield a value of `-1` /// ``` -declare_lint! { +declare_clippy_lint! { pub CAST_POSSIBLE_WRAP, - Allow, + pedantic, "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` \ and `x > i32::MAX`" } @@ -657,9 +657,9 @@ declare_lint! { /// ```rust /// fn as_u64(x: u8) -> u64 { u64::from(x) } /// ``` -declare_lint! { +declare_clippy_lint! { pub CAST_LOSSLESS, - Warn, + complexity, "casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8`" } @@ -673,9 +673,9 @@ declare_lint! { /// ```rust /// let _ = 2i32 as i32 /// ``` -declare_lint! { +declare_clippy_lint! { pub UNNECESSARY_CAST, - Warn, + complexity, "cast to the same type, e.g. `x as i32` where `x: i32`" } @@ -971,9 +971,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { /// ```rust /// struct Foo { inner: Rc>>> } /// ``` -declare_lint! { +declare_clippy_lint! { pub TYPE_COMPLEXITY, - Warn, + complexity, "usage of very complex types that might be better factored into `type` definitions" } @@ -1143,9 +1143,9 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { /// ```rust /// b'x' /// ``` -declare_lint! { +declare_clippy_lint! { pub CHAR_LIT_AS_U8, - Warn, + complexity, "casting a character literal to u8" } @@ -1198,9 +1198,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { /// vec.len() <= 0 /// 100 > std::i32::MAX /// ``` -declare_lint! { +declare_clippy_lint! { pub ABSURD_EXTREME_COMPARISONS, - Warn, + correctness, "a comparison with a maximum or minimum value that is always true or false" } @@ -1374,9 +1374,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { /// ```rust /// let x : u8 = ...; (x as u32) > 300 /// ``` -declare_lint! { +declare_clippy_lint! { pub INVALID_UPCAST_COMPARISONS, - Allow, + pedantic, "a comparison involving an upcast which is always true or false" } @@ -1599,9 +1599,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { /// /// pub foo(map: &mut HashMap) { .. } /// ``` -declare_lint! { +declare_clippy_lint! { pub IMPLICIT_HASHER, - Warn, + style, "missing generalization over different hashers" } diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index c045c870810..21c6b521153 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -14,9 +14,9 @@ use utils::{is_allowed, snippet, span_help_and_lint}; /// /// **Example:** You don't see it, but there may be a zero-width space /// somewhere in this text. -declare_lint! { +declare_clippy_lint! { pub ZERO_WIDTH_SPACE, - Deny, + correctness, "using a zero-width space in a string literal, which is confusing" } @@ -34,9 +34,9 @@ declare_lint! { /// ```rust /// let x = "Hä?" /// ``` -declare_lint! { +declare_clippy_lint! { pub NON_ASCII_LITERAL, - Allow, + pedantic, "using any literal non-ASCII chars in a string literal instead of \ using the `\\u` escape" } @@ -52,9 +52,9 @@ declare_lint! { /// /// **Example:** You may not see it, but “à” and “à” aren't the same string. The /// former when escaped is actually `"a\u{300}"` while the latter is `"\u{e0}"`. -declare_lint! { +declare_clippy_lint! { pub UNICODE_NOT_NFC, - Allow, + pedantic, "using a unicode literal not in NFC normal form (see \ [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index a238a9b9283..f852784545c 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -19,9 +19,9 @@ use utils::span_lint; /// extern crate crossbeam; /// use crossbeam::{spawn_unsafe as spawn}; /// ``` -declare_lint! { +declare_clippy_lint! { pub UNSAFE_REMOVED_FROM_NAME, - Warn, + style, "`unsafe` removed from API names on import" } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1af63c56107..0c28e9e74ec 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -23,9 +23,9 @@ use utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; /// Ok(()) /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub UNUSED_IO_AMOUNT, - Deny, + correctness, "unused written/read amount" } diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index ee708eb13ae..b009420bdb6 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -21,9 +21,9 @@ use utils::{in_macro, span_lint}; /// if i > 4 { continue } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub UNUSED_LABEL, - Warn, + complexity, "unused labels" } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index a1390596cda..86ce57ca0bd 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -32,9 +32,9 @@ use syntax_pos::symbol::keywords::SelfType; /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub USE_SELF, - Allow, + pedantic, "Unnecessary structure name repetition whereas `Self` is applicable" } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 44e5e84c4a0..2684e3999ab 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -38,9 +38,9 @@ use std::collections::HashMap; /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub LINT_AUTHOR, - Warn, + style, // ok, this is not a style lint, but it's also a noop without the appropriate attribute "helper for writing lints" } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 9ade2778e0c..cc98df941e8 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -24,9 +24,9 @@ use syntax::attr; /// visibility inherited from outer item /// extern crate dylib source: "/path/to/foo.so" /// ``` -declare_lint! { +declare_clippy_lint! { pub DEEP_CODE_INSPECTION, - Warn, + style, // not a style lint, but essentially a noop without the appropriate attribute "helper to dump info about code" } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 625ef63a3dc..666db3e0692 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -15,9 +15,9 @@ use std::collections::{HashMap, HashSet}; /// **Known problems:** None. /// /// **Example:** Wrong ordering of the util::paths constants. -declare_lint! { +declare_clippy_lint! { pub CLIPPY_LINTS_INTERNAL, - Allow, + internal, "various things that will negatively affect your clippy experience" } @@ -45,9 +45,9 @@ declare_lint! { /// } /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub LINT_WITHOUT_LINT_PASS, - Warn, + internal, "declaring a lint without associating it in a LintPass" } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 4762c730683..c98cd8719f1 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -16,9 +16,9 @@ use consts::constant; /// ```rust,ignore /// foo(&vec![1, 2]) /// ``` -declare_lint! { +declare_clippy_lint! { pub USELESS_VEC, - Warn, + perf, "useless `vec!`" } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 416ee155174..16c12702c6c 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -14,9 +14,9 @@ use utils::span_help_and_lint; /// ```rust /// 0.0f32 / 0.0 /// ``` -declare_lint! { +declare_clippy_lint! { pub ZERO_DIVIDED_BY_ZERO, - Warn, + complexity, "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" } diff --git a/tests/ui/lint_pass.rs b/tests/ui/lint_pass.rs index 29c93e745b3..275be4ea1eb 100644 --- a/tests/ui/lint_pass.rs +++ b/tests/ui/lint_pass.rs @@ -8,8 +8,8 @@ use rustc::lint::{LintPass, LintArray}; -declare_lint! { GOOD_LINT, Warn, "good lint" } -declare_lint! { MISSING_LINT, Warn, "missing lint" } +declare_clippy_lint! { GOOD_LINT, style, "good lint" } +declare_clippy_lint! { MISSING_LINT, style, "missing lint" } pub struct Pass; diff --git a/util/lintlib.py b/util/lintlib.py index 190bce5e2f3..1fddcbdc3fa 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -12,14 +12,27 @@ Config = collections.namedtuple('Config', 'name ty doc default') lintname_re = re.compile(r'''pub\s+([A-Z_][A-Z_0-9]*)''') level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''') +group_re = re.compile(r'''([a-z_][a-z_0-9]+)''') conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) confvar_re = re.compile( r'''/// Lint: (\w+). (.*).*\n\s*\([^,]+,\s+"([^"]+)",\s+([^=\)]+)=>\s+(.*)\),''', re.MULTILINE) +lint_levels = { + "correctness": 'Deny', + "style": 'Warn', + "complexity": 'Warn', + "perf": 'Warn', + "restriction": 'Allow', + "pedantic": 'Allow', + "nursery": 'Allow', +} def parse_lints(lints, filepath): last_comment = [] comment = True + clippy = False + deprecated = False + name = "" with open(filepath) as fp: for line in fp: @@ -29,43 +42,54 @@ def parse_lints(lints, filepath): elif line.startswith("///"): last_comment.append(line[3:]) elif line.startswith("declare_lint!"): + import sys + print "don't use `declare_lint!` in clippy, use `declare_clippy_lint!` instead" + sys.exit(42) + elif line.startswith("declare_clippy_lint!"): comment = False deprecated = False - restriction = False - elif line.startswith("declare_restriction_lint!"): - comment = False - deprecated = False - restriction = True + clippy = True + name = "" elif line.startswith("declare_deprecated_lint!"): comment = False deprecated = True + clippy = False else: last_comment = [] if not comment: - m = lintname_re.search(line) - if m: - name = m.group(1).lower() - - if deprecated: - level = "Deprecated" - elif restriction: - level = "Allow" - else: - while True: - m = level_re.search(line) - if m: - level = m.group(0) - break - line = next(fp) - - log.info("found %s with level %s in %s", - name, level, filepath) - lints.append(Lint(name, level, last_comment, filepath)) - last_comment = [] - comment = True - if "}" in line: - log.warn("Warning: missing Lint-Name in %s", filepath) - comment = True + if name: + g = group_re.search(line) + if g: + group = g.group(1).lower() + level = lint_levels[group] + log.info("found %s with level %s in %s", + name, level, filepath) + lints.append(Lint(name, level, last_comment, filepath, group)) + last_comment = [] + comment = True + else: + m = lintname_re.search(line) + if m: + name = m.group(1).lower() + + if deprecated: + level = "Deprecated" + else: + while True: + m = level_re.search(line) + if m: + level = m.group(0) + break + line = next(fp) + if not clippy: + log.info("found %s with level %s in %s", + name, level, filepath) + lints.append(Lint(name, level, last_comment, filepath, "deprecated")) + last_comment = [] + comment = True + if "}" in line: + log.warn("Warning: missing Lint-Name in %s", filepath) + comment = True def parse_configs(path): diff --git a/util/update_lints.py b/util/update_lints.py index 0f9c3479439..6c89e5fd0e0 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -8,25 +8,12 @@ import os import re import sys -declare_lint_re = re.compile(r''' - declare_lint! \s* [{(] \s* - pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* - (?PForbid|Deny|Warn|Allow) \s*,\s* - " (?P(?:[^"\\]+|\\.)*) " \s* [})] -''', re.VERBOSE | re.DOTALL) - declare_deprecated_lint_re = re.compile(r''' declare_deprecated_lint! \s* [{(] \s* pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* " (?P(?:[^"\\]+|\\.)*) " \s* [})] ''', re.VERBOSE | re.DOTALL) -declare_restriction_lint_re = re.compile(r''' - declare_restriction_lint! \s* [{(] \s* - pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* - " (?P(?:[^"\\]+|\\.)*) " \s* [})] -''', re.VERBOSE | re.DOTALL) - declare_clippy_lint_re = re.compile(r''' declare_clippy_lint! \s* [{(] \s* pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* @@ -39,20 +26,13 @@ nl_escape_re = re.compile(r'\\\n\s*') docs_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' -def collect(lints, deprecated_lints, restriction_lints, clippy_lints, fn): +def collect(lints, deprecated_lints, clippy_lints, fn): """Collect all lints from a file. Adds entries to the lints list as `(module, name, level, desc)`. """ with open(fn) as fp: code = fp.read() - for match in declare_lint_re.finditer(code): - # remove \-newline escapes from description string - desc = nl_escape_re.sub('', match.group('desc')) - lints.append((os.path.splitext(os.path.basename(fn))[0], - match.group('name').lower(), - match.group('level').lower(), - desc.replace('\\"', '"'))) for match in declare_deprecated_lint_re.finditer(code): # remove \-newline escapes from description string @@ -60,14 +40,6 @@ def collect(lints, deprecated_lints, restriction_lints, clippy_lints, fn): deprecated_lints.append((os.path.splitext(os.path.basename(fn))[0], match.group('name').lower(), desc.replace('\\"', '"'))) - - for match in declare_restriction_lint_re.finditer(code): - # remove \-newline escapes from description string - desc = nl_escape_re.sub('', match.group('desc')) - restriction_lints.append((os.path.splitext(os.path.basename(fn))[0], - match.group('name').lower(), - "allow", - desc.replace('\\"', '"'))) for match in declare_clippy_lint_re.finditer(code): # remove \-newline escapes from description string @@ -145,12 +117,14 @@ def replace_region(fn, region_start, region_end, callback, def main(print_only=False, check=False): lints = [] deprecated_lints = [] - restriction_lints = [] clippy_lints = { "correctness": [], "style": [], "complexity": [], "perf": [], + "restriction": [], + "pedantic": [], + "nursery": [], } # check directory @@ -161,7 +135,7 @@ def main(print_only=False, check=False): # collect all lints from source files for fn in os.listdir('clippy_lints/src'): if fn.endswith('.rs'): - collect(lints, deprecated_lints, restriction_lints, clippy_lints, + collect(lints, deprecated_lints, clippy_lints, os.path.join('clippy_lints', 'src', fn)) # determine version @@ -174,7 +148,9 @@ def main(print_only=False, check=False): print('Error: version not found in Cargo.toml!') return - all_lints = lints + restriction_lints + clippy_lints['perf'] + clippy_lints['correctness'] + clippy_lints['style'] + clippy_lints['complexity'] + all_lints = lints + for _, value in clippy_lints.iteritems(): + all_lints += value if print_only: sys.stdout.writelines(gen_table(all_lints)) @@ -223,29 +199,12 @@ def main(print_only=False, check=False): lambda: gen_group(lints, levels=('warn', 'deny')), replace_start=False, write_back=not check) - # same for "clippy_style" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_style"', r'\]\);', - lambda: gen_group(clippy_lints['style']), - replace_start=False, write_back=not check) - - # same for "clippy_correctness" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_correctness"', r'\]\);', - lambda: gen_group(clippy_lints['correctness']), - replace_start=False, write_back=not check) - - # same for "clippy_complexity" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_complexity"', r'\]\);', - lambda: gen_group(clippy_lints['complexity']), - replace_start=False, write_back=not check) - - # same for "clippy_perf" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_perf"', r'\]\);', - lambda: gen_group(clippy_lints['perf']), - replace_start=False, write_back=not check) + for key, value in clippy_lints.iteritems(): + # same for "clippy_*" lint collections + changed |= replace_region( + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_' + key + r'"', r'\]\);', + lambda: gen_group(value), + replace_start=False, write_back=not check) # same for "deprecated" lint collection changed |= replace_region( @@ -254,18 +213,6 @@ def main(print_only=False, check=False): replace_start=False, write_back=not check) - # same for "clippy_pedantic" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_pedantic"', r'\]\);', - lambda: gen_group(lints, levels=('allow',)), - replace_start=False, write_back=not check) - - # same for "clippy_restrictions" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_restrictions"', - r'\]\);', lambda: gen_group(restriction_lints), - replace_start=False, write_back=not check) - if check and changed: print('Please run util/update_lints.py to regenerate lints lists.') return 1 -- cgit 1.4.1-3-g733a5 From eafb9fe8df7bd387bae9eaa6c221a1a96b848111 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 28 Mar 2018 23:49:32 +0200 Subject: Update test suite --- README.md | 2 +- clippy_lints/src/lib.rs | 207 ++++++++++++++++++++++++++++- tests/ui/absurd-extreme-comparisons.stderr | 2 +- tests/ui/bit_masks.stderr | 2 +- tests/ui/cstring.stderr | 2 +- tests/ui/derive.rs | 2 +- tests/ui/derive.stderr | 2 +- tests/ui/dlist.rs | 2 +- tests/ui/double_comparison.stderr | 2 +- tests/ui/infinite_loop.stderr | 2 +- tests/ui/invalid_ref.stderr | 2 +- tests/ui/lint_pass.rs | 24 ---- tests/ui/lint_pass.stderr | 10 -- tests/ui/matches.rs | 2 +- tests/ui/matches.stderr | 10 +- tests/ui/methods.rs | 2 +- tests/ui/shadow.rs | 2 +- tests/ui/suspicious_arithmetic_impl.stderr | 2 +- tests/ui/unnecessary_clone.stderr | 2 +- tests/ui/zero_div_zero.stderr | 2 +- util/update_lints.py | 30 +++-- 21 files changed, 253 insertions(+), 60 deletions(-) delete mode 100644 tests/ui/lint_pass.rs delete mode 100644 tests/ui/lint_pass.stderr diff --git a/README.md b/README.md index 8ccc148942d..c5c327497da 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 208 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 248 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 045b7c02905..75aa4dfb418 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -401,15 +401,26 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); - reg.register_lint_group("clippy_restrictions", vec![ + reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, literal_representation::DECIMAL_LITERAL_REPRESENTATION, + mem_forget::MEM_FORGET, methods::CLONE_ON_REF_PTR, + methods::OPTION_UNWRAP_USED, + methods::RESULT_UNWRAP_USED, + methods::WRONG_PUB_SELF_CONVENTION, misc::FLOAT_CMP_CONST, + missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + print::PRINT_STDOUT, + print::USE_DEBUG, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, + strings::STRING_ADD, ]); reg.register_lint_group("clippy_pedantic", vec![ @@ -454,6 +465,200 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ]); reg.register_lint_group("clippy", vec![ + approx_const::APPROX_CONSTANT, + array_indexing::OUT_OF_BOUNDS_INDEXING, + assign_ops::ASSIGN_OP_PATTERN, + assign_ops::MISREFACTORED_ASSIGN_OP, + attrs::DEPRECATED_SEMVER, + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, + attrs::USELESS_ATTRIBUTE, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + bit_mask::VERBOSE_BIT_MASK, + blacklisted_name::BLACKLISTED_NAME, + block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, + block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, + booleans::LOGIC_BUG, + booleans::NONMINIMAL_BOOL, + bytecount::NAIVE_BYTECOUNT, + collapsible_if::COLLAPSIBLE_IF, + const_static_lifetime::CONST_STATIC_LIFETIME, + copies::IF_SAME_THEN_ELSE, + copies::IFS_SAME_COND, + cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + derive::DERIVE_HASH_XOR_EQ, + double_comparison::DOUBLE_COMPARISONS, + double_parens::DOUBLE_PARENS, + drop_forget_ref::DROP_COPY, + drop_forget_ref::DROP_REF, + drop_forget_ref::FORGET_COPY, + drop_forget_ref::FORGET_REF, + entry::MAP_ENTRY, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, + enum_variants::ENUM_VARIANT_NAMES, + enum_variants::MODULE_INCEPTION, + eq_op::EQ_OP, + eq_op::OP_REF, + erasing_op::ERASING_OP, + escape::BOXED_LOCAL, + eta_reduction::REDUNDANT_CLOSURE, + eval_order_dependence::DIVERGING_SUB_EXPRESSION, + eval_order_dependence::EVAL_ORDER_DEPENDENCE, + explicit_write::EXPLICIT_WRITE, + format::USELESS_FORMAT, + formatting::POSSIBLE_MISSING_COMMA, + formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, + formatting::SUSPICIOUS_ELSE_FORMATTING, + functions::NOT_UNSAFE_PTR_ARG_DEREF, + functions::TOO_MANY_ARGUMENTS, + identity_conversion::IDENTITY_CONVERSION, + identity_op::IDENTITY_OP, + if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + infinite_iter::INFINITE_ITER, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, + int_plus_one::INT_PLUS_ONE, + invalid_ref::INVALID_REF, + large_enum_variant::LARGE_ENUM_VARIANT, + len_zero::LEN_WITHOUT_IS_EMPTY, + len_zero::LEN_ZERO, + let_if_seq::USELESS_LET_IF_SEQ, + lifetimes::NEEDLESS_LIFETIMES, + lifetimes::UNUSED_LIFETIMES, + literal_representation::INCONSISTENT_DIGIT_GROUPING, + literal_representation::LARGE_DIGIT_GROUPS, + literal_representation::UNREADABLE_LITERAL, + loops::EMPTY_LOOP, + loops::EXPLICIT_COUNTER_LOOP, + loops::EXPLICIT_INTO_ITER_LOOP, + loops::EXPLICIT_ITER_LOOP, + loops::FOR_KV_MAP, + loops::FOR_LOOP_OVER_OPTION, + loops::FOR_LOOP_OVER_RESULT, + loops::ITER_NEXT_LOOP, + loops::MANUAL_MEMCPY, + loops::MUT_RANGE_BOUND, + loops::NEEDLESS_RANGE_LOOP, + loops::NEVER_LOOP, + loops::REVERSE_RANGE_LOOP, + loops::UNUSED_COLLECT, + loops::WHILE_IMMUTABLE_CONDITION, + loops::WHILE_LET_LOOP, + loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, + matches::MATCH_AS_REF, + matches::MATCH_BOOL, + matches::MATCH_OVERLAPPING_ARM, + matches::MATCH_REF_PATS, + matches::MATCH_WILD_ERR_ARM, + matches::SINGLE_MATCH, + methods::CHARS_LAST_CMP, + methods::CHARS_NEXT_CMP, + methods::CLONE_DOUBLE_REF, + methods::CLONE_ON_COPY, + methods::FILTER_NEXT, + methods::GET_UNWRAP, + methods::ITER_CLONED_COLLECT, + methods::ITER_NTH, + methods::ITER_SKIP_NEXT, + methods::NEW_RET_NO_SELF, + methods::OK_EXPECT, + methods::OPTION_MAP_OR_NONE, + methods::OR_FUN_CALL, + methods::SEARCH_IS_SOME, + methods::SHOULD_IMPLEMENT_TRAIT, + methods::SINGLE_CHAR_PATTERN, + methods::STRING_EXTEND_CHARS, + methods::TEMPORARY_CSTRING_AS_PTR, + methods::UNNECESSARY_FOLD, + methods::USELESS_ASREF, + methods::WRONG_SELF_CONVENTION, + minmax::MIN_MAX, + misc::CMP_NAN, + misc::CMP_OWNED, + misc::FLOAT_CMP, + misc::MODULO_ONE, + misc::REDUNDANT_PATTERN, + misc::SHORT_CIRCUIT_STATEMENT, + misc::TOPLEVEL_REF_ARG, + misc::ZERO_PTR, + misc_early::BUILTIN_TYPE_SHADOW, + misc_early::DOUBLE_NEG, + misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, + misc_early::MIXED_CASE_HEX_LITERALS, + misc_early::REDUNDANT_CLOSURE_CALL, + misc_early::UNNEEDED_FIELD_PATTERN, + misc_early::ZERO_PREFIXED_LITERAL, + mut_reference::UNNECESSARY_MUT_PASSED, + mutex_atomic::MUTEX_ATOMIC, + needless_bool::BOOL_COMPARISON, + needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, + needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, + needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, + needless_update::NEEDLESS_UPDATE, + neg_multiply::NEG_MULTIPLY, + new_without_default::NEW_WITHOUT_DEFAULT, + new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, + no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, + non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, + non_expressive_names::MANY_SINGLE_CHAR_NAMES, + ok_if_let::IF_LET_SOME_RESULT, + open_options::NONSENSICAL_OPEN_OPTIONS, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, + panic::PANIC_PARAMS, + partialeq_ne_impl::PARTIALEQ_NE_IMPL, + precedence::PRECEDENCE, + print::PRINT_WITH_NEWLINE, + print::PRINTLN_EMPTY_STRING, + ptr::CMP_NULL, + ptr::MUT_FROM_REF, + ptr::PTR_ARG, + question_mark::QUESTION_MARK, + ranges::ITERATOR_STEP_BY_ZERO, + ranges::RANGE_MINUS_ONE, + ranges::RANGE_ZIP_WITH_LEN, + redundant_field_names::REDUNDANT_FIELD_NAMES, + reference::DEREF_ADDROF, + regex::INVALID_REGEX, + regex::REGEX_MACRO, + regex::TRIVIAL_REGEX, + returns::LET_AND_RETURN, + returns::NEEDLESS_RETURN, + serde_api::SERDE_API_MISUSE, + strings::STRING_LIT_AS_BYTES, + suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, + suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, + swap::ALMOST_SWAPPED, + swap::MANUAL_SWAP, + temporary_assignment::TEMPORARY_ASSIGNMENT, + transmute::CROSSPOINTER_TRANSMUTE, + transmute::MISALIGNED_TRANSMUTE, + transmute::TRANSMUTE_BYTES_TO_STR, + transmute::TRANSMUTE_INT_TO_BOOL, + transmute::TRANSMUTE_INT_TO_CHAR, + transmute::TRANSMUTE_INT_TO_FLOAT, + transmute::TRANSMUTE_PTR_TO_REF, + transmute::USELESS_TRANSMUTE, + transmute::WRONG_TRANSMUTE, + types::ABSURD_EXTREME_COMPARISONS, + types::BORROWED_BOX, + types::BOX_VEC, + types::CAST_LOSSLESS, + types::CHAR_LIT_AS_U8, + types::IMPLICIT_HASHER, + types::LET_UNIT_VALUE, + types::OPTION_OPTION, + types::TYPE_COMPLEXITY, + types::UNIT_ARG, + types::UNIT_CMP, + types::UNNECESSARY_CAST, + unicode::ZERO_WIDTH_SPACE, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + unused_io_amount::UNUSED_IO_AMOUNT, + unused_label::UNUSED_LABEL, + vec::USELESS_VEC, + zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); reg.register_lint_group("clippy_style", vec![ diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 2b1e9ad66fe..72b2f7a3942 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -141,7 +141,7 @@ error: <-comparison of unit values detected. This will always be false 31 | () < {}; | ^^^^^^^ | - = note: `-D unit-cmp` implied by `-D warnings` + = note: #[deny(unit_cmp)] on by default error: aborting due to 18 previous errors diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 6aad98ff528..e1a4a42914c 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -12,7 +12,7 @@ error: this operation will always return zero. This is likely not the intended o 12 | x & 0 == 0; | ^^^^^ | - = note: `-D erasing-op` implied by `-D warnings` + = note: #[deny(erasing_op)] on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:15:5 diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 973f26a96db..0e90f696357 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -4,7 +4,7 @@ error: you are getting the inner pointer of a temporary `CString` 7 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` + = note: #[deny(temporary_cstring_as_ptr)] on by default = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime --> $DIR/cstring.rs:7:5 diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 6440f73f31b..f43b8c382a4 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,9 +1,9 @@ - #![feature(untagged_unions)] #![allow(dead_code)] +#![warn(expl_impl_clone_on_copy)] use std::hash::{Hash, Hasher}; diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index ffeed948ba5..cbe3fe1029d 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -4,7 +4,7 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly 17 | #[derive(Hash)] | ^^^^ | - = note: `-D derive-hash-xor-eq` implied by `-D warnings` + = note: #[deny(derive_hash_xor_eq)] on by default note: `PartialEq` implemented here --> $DIR/derive.rs:20:1 | diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 217a564742c..59f0d3fe39b 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -2,7 +2,7 @@ #![feature(associated_type_defaults)] -#![warn(clippy)] +#![warn(linkedlist)] #![allow(dead_code, needless_pass_by_value)] extern crate alloc; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index a97b0a246af..73dd8d02877 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -4,7 +4,7 @@ error: This binary expression can be simplified 4 | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` | - = note: #[deny(double_comparisons)] on by default + = note: `-D double-comparisons` implied by `-D warnings` error: This binary expression can be simplified --> $DIR/double_comparison.rs:7:8 diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 0bf14bb723b..d24fd925e6d 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -4,7 +4,7 @@ error: Variable in the condition are not mutated in the loop body. This either l 14 | while y < 10 { | ^^^^^^ | - = note: `-D while-immutable-condition` implied by `-D warnings` + = note: #[deny(while_immutable_condition)] on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:19:11 diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 420fed01744..f8420738526 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -4,7 +4,7 @@ error: reference to zeroed memory 27 | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | - = note: `-D invalid-ref` implied by `-D warnings` + = note: #[deny(invalid_ref)] on by default = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory diff --git a/tests/ui/lint_pass.rs b/tests/ui/lint_pass.rs deleted file mode 100644 index 275be4ea1eb..00000000000 --- a/tests/ui/lint_pass.rs +++ /dev/null @@ -1,24 +0,0 @@ - -#![feature(rustc_private)] -#![feature(macro_vis_matcher)] - -#![warn(lint_without_lint_pass)] - -#[macro_use] extern crate rustc; - -use rustc::lint::{LintPass, LintArray}; - -declare_clippy_lint! { GOOD_LINT, style, "good lint" } -declare_clippy_lint! { MISSING_LINT, style, "missing lint" } - -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array![GOOD_LINT] - } -} - -fn main() { - let _ = MISSING_LINT; -} diff --git a/tests/ui/lint_pass.stderr b/tests/ui/lint_pass.stderr deleted file mode 100644 index 2f9a6813b96..00000000000 --- a/tests/ui/lint_pass.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: the lint `MISSING_LINT` is not added to any `LintPass` - --> $DIR/lint_pass.rs:12:1 - | -12 | declare_lint! { MISSING_LINT, Warn, "missing lint" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D lint-without-lint-pass` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 67a901f65b2..8b1ee1fdcd2 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -4,7 +4,7 @@ #![warn(clippy)] #![allow(unused, if_let_redundant_pattern_matching)] -#![warn(single_match_else)] +#![warn(single_match_else, match_same_arms)] use std::borrow::Cow; diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 5b4c222e6dc..ab207eb32de 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -56,6 +56,14 @@ error: you seem to be trying to use match for destructuring a single pattern. Co 78 | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` +error: this boolean expression can be simplified + --> $DIR/matches.rs:117:11 + | +117 | match test && test { + | ^^^^^^^^^^^^ help: try: `test` + | + = note: `-D nonminimal-bool` implied by `-D warnings` + error: you seem to be trying to match on a boolean expression --> $DIR/matches.rs:96:5 | @@ -461,5 +469,5 @@ error: use as_mut() instead 329 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 37 previous errors +error: aborting due to 38 previous errors diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 4afab4c8be6..65cac8ec4ff 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,7 +1,7 @@ #![feature(const_fn)] -#![warn(clippy, clippy_pedantic)] +#![warn(clippy, clippy_pedantic, option_unwrap_used)] #![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value)] diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index fbe695a7657..79c1030d48b 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,7 +1,7 @@ -#![warn(clippy, clippy_pedantic)] +#![warn(clippy, clippy_pedantic, shadow_same, shadow_reuse, shadow_unrelated)] #![allow(unused_parens, unused_variables, missing_docs_in_private_items)] fn id(x: T) -> T { x } diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 9d5086e5497..8130b1cb31a 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -12,7 +12,7 @@ error: Suspicious use of binary operator in `AddAssign` impl 20 | *self = *self - other; | ^ | - = note: `-D suspicious-op-assign-impl` implied by `-D warnings` + = note: #[deny(suspicious_op_assign_impl)] on by default error: aborting due to 2 previous errors diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 486d2e350f2..3c1ce908022 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -62,7 +62,7 @@ error: using `clone` on a double-reference; this will copy the reference instead 55 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | - = note: `-D clone-double-ref` implied by `-D warnings` + = note: #[deny(clone_double_ref)] on by default help: try dereferencing it | 55 | let z: &Vec<_> = &(*y).clone(); diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index bc2a70beffd..f1788fc9ec5 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -4,7 +4,7 @@ error: equal expressions as operands to `/` 7 | let nan = 0.0 / 0.0; | ^^^^^^^^^ | - = note: `-D eq-op` implied by `-D warnings` + = note: #[deny(eq_op)] on by default error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:7:15 diff --git a/util/update_lints.py b/util/update_lints.py index 6c89e5fd0e0..58caa5dac0d 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -26,7 +26,7 @@ nl_escape_re = re.compile(r'\\\n\s*') docs_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' -def collect(lints, deprecated_lints, clippy_lints, fn): +def collect(deprecated_lints, clippy_lints, fn): """Collect all lints from a file. Adds entries to the lints list as `(module, name, level, desc)`. @@ -88,6 +88,8 @@ def replace_region(fn, region_start, region_end, callback, with open(fn) as fp: lines = list(fp) + found = False + # replace old region with new region new_lines = [] in_old_region = False @@ -102,9 +104,13 @@ def replace_region(fn, region_start, region_end, callback, new_lines.append(line) # old region starts here in_old_region = True + found = True else: new_lines.append(line) + if not found: + print "regex " + region_start + " not found" + # write back to file if write_back: with open(fn, 'w') as fp: @@ -115,7 +121,6 @@ def replace_region(fn, region_start, region_end, callback, def main(print_only=False, check=False): - lints = [] deprecated_lints = [] clippy_lints = { "correctness": [], @@ -135,7 +140,7 @@ def main(print_only=False, check=False): # collect all lints from source files for fn in os.listdir('clippy_lints/src'): if fn.endswith('.rs'): - collect(lints, deprecated_lints, clippy_lints, + collect(deprecated_lints, clippy_lints, os.path.join('clippy_lints', 'src', fn)) # determine version @@ -148,7 +153,16 @@ def main(print_only=False, check=False): print('Error: version not found in Cargo.toml!') return - all_lints = lints + all_lints = [] + clippy_lint_groups = [ + "correctness", + "style", + "complexity", + "perf", + ] + clippy_lint_list = [] + for x in clippy_lint_groups: + clippy_lint_list += clippy_lints[x] for _, value in clippy_lints.iteritems(): all_lints += value @@ -159,8 +173,8 @@ def main(print_only=False, check=False): # update the lint counter in README.md changed = replace_region( 'README.md', - r'^\[There are \d+ lints included in this crate\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)$', "", - lambda: ['[There are %d lints included in this crate](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)\n' % + r'^\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)$', "", + lambda: ['[There are %d lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)\n' % (len(all_lints))], write_back=not check) @@ -193,10 +207,10 @@ def main(print_only=False, check=False): lambda: gen_mods(all_lints), replace_start=False, write_back=not check) - # same for "clippy" lint collection + # same for "clippy_*" lint collections changed |= replace_region( 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', - lambda: gen_group(lints, levels=('warn', 'deny')), + lambda: gen_group(clippy_lint_list), replace_start=False, write_back=not check) for key, value in clippy_lints.iteritems(): -- cgit 1.4.1-3-g733a5 From 8db845c189ebce88f4f29d426fb6cb6ae8478b64 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Wed, 28 Mar 2018 23:17:48 +0100 Subject: Delete all code for handling manifest path Now that we're using cargo check, we can stop needing to find out the manifest path ourselves. Instead, we can delegate to cargo check, which is perfectly capable of working out for itself what needs to be built. This fixes #1707 and #2518. Note that this PR will change the output. We will no longer output `bin: foo` before each crate. This a bit unfortunate. However, given that we're now going to be building in parallel (which is *much* faster), I think this is acceptable - we'll be no worse than cargo itself. --- Cargo.toml | 2 +- src/main.rs | 127 ++---------------------------------------------------------- 2 files changed, 4 insertions(+), 125 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 24b3ff975b1..a28e5c50929 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,11 +39,11 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.190", path = "clippy_lints" } # end automatic update -cargo_metadata = "0.5" regex = "0.2" semver = "0.9" [dev-dependencies] +cargo_metadata = "0.5" compiletest_rs = "0.3.7" lazy_static = "1.0" serde_derive = "1.0" diff --git a/src/main.rs b/src/main.rs index 598d129dec2..5bdbaf1bc80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,14 +3,6 @@ #![feature(rustc_private)] #![allow(unknown_lints, missing_docs_in_private_items)] -use std::collections::HashMap; -use std::process; -use std::io::{self, Write}; - -extern crate cargo_metadata; - -use std::path::{Path, PathBuf}; - const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. Usage: @@ -18,11 +10,9 @@ Usage: Common options: -h, --help Print this message - --features Features to compile for the package -V, --version Print version info and exit - --all Run over all packages in the current workspace -Other options are the same as `cargo rustc`. +Other options are the same as `cargo check`. To allow or deny a lint from the command line you can use `cargo clippy --` with: @@ -59,119 +49,8 @@ pub fn main() { return; } - let mut manifest_path_arg = std::env::args() - .skip(2) - .skip_while(|val| !val.starts_with("--manifest-path")); - let manifest_path_arg = manifest_path_arg.next().and_then(|val| { - if val == "--manifest-path" { - manifest_path_arg.next() - } else if val.starts_with("--manifest-path=") { - Some(val["--manifest-path=".len()..].to_owned()) - } else { - None - } - }); - - let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { - metadata - } else { - println!( - "{:?}", - cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) - ); - let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); - process::exit(101); - }; - - let manifest_path = manifest_path_arg.map(|arg| { - PathBuf::from(arg) - .canonicalize() - .expect("manifest path could not be canonicalized") - }); - - let packages = if std::env::args().any(|a| a == "--all") { - metadata.packages - } else { - let package_index = { - if let Some(manifest_path) = manifest_path { - metadata.packages.iter().position(|package| { - let package_manifest_path = Path::new(&package.manifest_path) - .canonicalize() - .expect("package manifest path could not be canonicalized"); - package_manifest_path == manifest_path - }) - } else { - let package_manifest_paths: HashMap<_, _> = metadata - .packages - .iter() - .enumerate() - .map(|(i, package)| { - let package_manifest_path = Path::new(&package.manifest_path) - .parent() - .expect("could not find parent directory of package manifest") - .canonicalize() - .expect("package directory cannot be canonicalized"); - (package_manifest_path, i) - }) - .collect(); - - let current_dir = std::env::current_dir() - .expect("CARGO_MANIFEST_DIR not set") - .canonicalize() - .expect("manifest directory cannot be canonicalized"); - - let mut current_path: &Path = ¤t_dir; - - // This gets the most-recent parent (the one that takes the fewest `cd ..`s to - // reach). - loop { - if let Some(&package_index) = package_manifest_paths.get(current_path) { - break Some(package_index); - } else { - // We'll never reach the filesystem root, because to get to this point in the - // code - // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to - // unwrap the current path's parent. - current_path = current_path - .parent() - .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display())); - } - } - } - }.expect("could not find matching package"); - - vec![metadata.packages.remove(package_index)] - }; - - for package in packages { - let manifest_path = package.manifest_path; - - for target in package.targets { - let args = std::env::args() - .skip(2) - .filter(|a| a != "--all" && !a.starts_with("--manifest-path=")); - - let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args); - if let Some(first) = target.kind.get(0) { - if target.kind.len() > 1 || first.ends_with("lib") { - println!("lib: {}", target.name); - if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { - std::process::exit(code); - } - } else if ["bin", "example", "test", "bench"].contains(&&**first) { - println!("{}: {}", first, target.name); - if let Err(code) = process( - vec![format!("--{}", first), target.name] - .into_iter() - .chain(args), - ) { - std::process::exit(code); - } - } - } else { - panic!("badly formatted cargo metadata: target::kind is an empty array"); - } - } + if let Err(code) = process(std::env::args().skip(2)) { + std::process::exit(code); } } -- cgit 1.4.1-3-g733a5 From 82e771d7dcabc86434c47e1ee461c62d30d91289 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 29 Mar 2018 13:04:52 +0200 Subject: Document lint groups --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index c5c327497da..bdd2c7dcb02 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g [There are 248 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: + +* `clippy` (everything that has no false positives) +* `clippy_pedantic` (everything) +* `clippy_style` (code that should be written in a more idiomatic way) +* `complexity` (code that does something simple but in a complex way) +* `perf` (code that can be written in a faster way) +* **`correctness`** (code that is just outright wrong or very very useless) + More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! Table of contents: -- cgit 1.4.1-3-g733a5 From b75618206cec71bd87ff7b07f0a8698ee854a2d1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 29 Mar 2018 13:02:12 +0200 Subject: Move RangeArgument --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 81c402ab49c..9dc4998dfc5 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -57,7 +57,7 @@ pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; -pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["alloc", "range", "RangeArgument"]; +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBound"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; -- cgit 1.4.1-3-g733a5 From c1bbc173da5c2b41565d7465c848bac4409c226e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 29 Mar 2018 13:41:53 +0200 Subject: Address review comments --- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/lib.rs | 43 ++++++++++++++++-------------- clippy_lints/src/loops.rs | 16 +++++------ clippy_lints/src/methods.rs | 18 ++++++------- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/print.rs | 6 ++--- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- tests/ui/never_loop.stderr | 2 +- 15 files changed, 54 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index ff40839637b..1ab13a825da 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -63,7 +63,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub POSSIBLE_MISSING_COMMA, - style, + correctness, "possible missing comma in array" } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 719708d6d18..cb359daba44 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -24,7 +24,7 @@ use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// ``` declare_clippy_lint! { pub TOO_MANY_ARGUMENTS, - style, + complexity, "functions with too many arguments" } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 243498d2d4e..af7de542a91 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -22,7 +22,7 @@ use utils::sugg::DiagnosticBuilderExt; /// ``` declare_clippy_lint! { pub INLINE_FN_WITHOUT_BODY, - complexity, + correctness, "use of `#[inline]` on trait methods without bodies" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 75aa4dfb418..187b1fcee82 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -85,6 +85,9 @@ macro_rules! declare_clippy_lint { { pub $name:tt, internal, $description:tt } => { declare_lint! { pub $name, Allow, $description } }; + { pub $name:tt, internal_warn, $description:tt } => { + declare_lint! { pub $name, Warn, $description } + }; } pub mod consts; @@ -443,7 +446,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc::USED_UNDERSCORE_BINDING, misc_early::UNSEPARATED_LITERAL_SUFFIX, mut_mut::MUT_MUT, - mutex_atomic::MUTEX_INTEGER, needless_continue::NEEDLESS_CONTINUE, non_expressive_names::SIMILAR_NAMES, replace_consts::REPLACE_CONSTS, @@ -674,10 +676,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::MODULE_INCEPTION, eq_op::OP_REF, eta_reduction::REDUNDANT_CLOSURE, - formatting::POSSIBLE_MISSING_COMMA, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, - functions::TOO_MANY_ARGUMENTS, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, @@ -686,15 +686,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, - loops::EXPLICIT_COUNTER_LOOP, loops::EXPLICIT_INTO_ITER_LOOP, loops::EXPLICIT_ITER_LOOP, loops::FOR_KV_MAP, - loops::MANUAL_MEMCPY, loops::NEEDLESS_RANGE_LOOP, - loops::NEVER_LOOP, - loops::UNUSED_COLLECT, - loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, map_clone::MAP_CLONE, matches::MATCH_BOOL, @@ -703,16 +698,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { matches::MATCH_WILD_ERR_ARM, matches::SINGLE_MATCH, methods::CHARS_LAST_CMP, - methods::CHARS_NEXT_CMP, - methods::FILTER_NEXT, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, methods::ITER_SKIP_NEXT, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, methods::OPTION_MAP_OR_NONE, - methods::OR_FUN_CALL, - methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::STRING_EXTEND_CHARS, methods::UNNECESSARY_FOLD, @@ -724,10 +715,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc_early::DOUBLE_NEG, misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::MIXED_CASE_HEX_LITERALS, - misc_early::REDUNDANT_CLOSURE_CALL, misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, - needless_bool::BOOL_COMPARISON, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, @@ -763,22 +752,25 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { eval_order_dependence::EVAL_ORDER_DEPENDENCE, explicit_write::EXPLICIT_WRITE, format::USELESS_FORMAT, + functions::TOO_MANY_ARGUMENTS, identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, - inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, lifetimes::NEEDLESS_LIFETIMES, lifetimes::UNUSED_LIFETIMES, - loops::FOR_LOOP_OVER_OPTION, - loops::FOR_LOOP_OVER_RESULT, - loops::ITER_NEXT_LOOP, + loops::EXPLICIT_COUNTER_LOOP, loops::MUT_RANGE_BOUND, + loops::WHILE_LET_LOOP, matches::MATCH_AS_REF, + methods::CHARS_NEXT_CMP, methods::CLONE_ON_COPY, + methods::FILTER_NEXT, + methods::SEARCH_IS_SOME, methods::USELESS_ASREF, - misc::FLOAT_CMP, misc::SHORT_CIRCUIT_STATEMENT, + misc_early::REDUNDANT_CLOSURE_CALL, misc_early::ZERO_PREFIXED_LITERAL, + needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_borrow::NEEDLESS_BORROW, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, @@ -801,7 +793,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, types::BORROWED_BOX, - types::BOX_VEC, types::CAST_LOSSLESS, types::CHAR_LIT_AS_U8, types::OPTION_OPTION, @@ -830,15 +821,22 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, eq_op::EQ_OP, erasing_op::ERASING_OP, + formatting::POSSIBLE_MISSING_COMMA, functions::NOT_UNSAFE_PTR_ARG_DEREF, infinite_iter::INFINITE_ITER, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, invalid_ref::INVALID_REF, + loops::FOR_LOOP_OVER_OPTION, + loops::FOR_LOOP_OVER_RESULT, + loops::ITER_NEXT_LOOP, + loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, loops::WHILE_IMMUTABLE_CONDITION, methods::CLONE_DOUBLE_REF, methods::TEMPORARY_CSTRING_AS_PTR, minmax::MIN_MAX, misc::CMP_NAN, + misc::FLOAT_CMP, misc::MODULO_ONE, open_options::NONSENSICAL_OPEN_OPTIONS, ptr::MUT_FROM_REF, @@ -860,15 +858,20 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { entry::MAP_ENTRY, escape::BOXED_LOCAL, large_enum_variant::LARGE_ENUM_VARIANT, + loops::MANUAL_MEMCPY, + loops::UNUSED_COLLECT, methods::ITER_NTH, + methods::OR_FUN_CALL, methods::SINGLE_CHAR_PATTERN, misc::CMP_OWNED, mutex_atomic::MUTEX_ATOMIC, + types::BOX_VEC, vec::USELESS_VEC, ]); reg.register_lint_group("clippy_nursery", vec![ fallible_impl_from::FALLIBLE_IMPL_FROM, + mutex_atomic::MUTEX_INTEGER, ranges::RANGE_PLUS_ONE, ]); } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 48b77be662b..6f04940ae31 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -40,7 +40,7 @@ use utils::paths; /// ``` declare_clippy_lint! { pub MANUAL_MEMCPY, - style, + perf, "manually copying items between slices" } @@ -119,7 +119,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub ITER_NEXT_LOOP, - complexity, + correctness, "for-looping over `_.next()` which is probably not intended" } @@ -141,7 +141,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub FOR_LOOP_OVER_OPTION, - complexity, + correctness, "for-looping over an `Option`, which is more clearly expressed as an `if let`" } @@ -163,7 +163,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub FOR_LOOP_OVER_RESULT, - complexity, + correctness, "for-looping over a `Result`, which is more clearly expressed as an `if let`" } @@ -191,7 +191,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub WHILE_LET_LOOP, - style, + complexity, "`loop { if let { ... } else break }`, which can be written as a `while let` loop" } @@ -209,7 +209,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub UNUSED_COLLECT, - style, + perf, "`collect()`ing an iterator without using the result; this is usually better \ written as a for loop" } @@ -252,7 +252,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub EXPLICIT_COUNTER_LOOP, - style, + complexity, "for-looping with an explicit counter when `_.enumerate()` would do" } @@ -329,7 +329,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub NEVER_LOOP, - style, + correctness, "any loop that will always `break` or `return`" } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index abce4c2d5fb..50de299ca7d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -160,7 +160,7 @@ declare_clippy_lint! { /// **Why is this bad?** Readability, this can be written more concisely as /// `_.map_or(_, _)`. /// -/// **Known problems:** None. +/// **Known problems:** The order of the arguments is not in execution order /// /// **Example:** /// ```rust @@ -178,7 +178,7 @@ declare_clippy_lint! { /// **Why is this bad?** Readability, this can be written more concisely as /// `_.map_or_else(_, _)`. /// -/// **Known problems:** None. +/// **Known problems:** The order of the arguments is not in execution order. /// /// **Example:** /// ```rust @@ -214,7 +214,7 @@ declare_clippy_lint! { /// **Why is this bad?** Readability, this can be written more concisely as /// `_.and_then(_)`. /// -/// **Known problems:** None. +/// **Known problems:** The order of the arguments is not in execution order. /// /// **Example:** /// ```rust @@ -240,7 +240,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub FILTER_NEXT, - style, + complexity, "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" } @@ -278,7 +278,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub SEARCH_IS_SOME, - style, + complexity, "using an iterator search followed by `is_some()`, which is more succinctly \ expressed as a call to `any()`" } @@ -297,7 +297,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub CHARS_NEXT_CMP, - style, + complexity, "using `.chars().next()` to check if a string starts with a char" } @@ -325,7 +325,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub OR_FUN_CALL, - style, + perf, "using any `*or` method with a function call, which suggests `*or_else`" } @@ -347,8 +347,8 @@ declare_clippy_lint! { } /// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer, -/// (Rc, Arc, rc::Weak, or sync::Weak), and suggests calling Clone on -/// the corresponding trait instead. +/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified +/// function syntax instead (e.g. `Rc::clone(foo)`). /// /// **Why is this bad?**: Calling '.clone()' on an Rc, Arc, or Weak /// can obscure the fact that only the pointer is being cloned, not the underlying diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 538a3eaaefd..e9b6865f0c9 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -72,7 +72,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub FLOAT_CMP, - complexity, + correctness, "using `==` or `!=` on float values instead of comparing difference with an epsilon" } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 0331c976377..3f3ba6487de 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -54,7 +54,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub REDUNDANT_CLOSURE_CALL, - style, + complexity, "throwaway closures called in the expression they are defined" } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 77af0be0ec8..b879d76e65c 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub MUTEX_INTEGER, - pedantic, + nursery, "using a mutex for an integer type" } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 393e0ec110c..e88d76656eb 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub BOOL_COMPARISON, - style, + complexity, "comparing a variable to a boolean, e.g. `if x == true`" } diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 7413ab2ac63..6d9880e1335 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -8,7 +8,7 @@ use syntax_pos::Span; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; use utils::{opt_def_id, paths}; -/// **What it does:** This lint warns when you using `println!("")` to +/// **What it does:** This lint warns when you use `println!("")` to /// print a newline. /// /// **Why is this bad?** You should use `println!()`, which is simpler. @@ -22,10 +22,10 @@ use utils::{opt_def_id, paths}; declare_clippy_lint! { pub PRINTLN_EMPTY_STRING, style, - "using `print!()` with a format string that ends in a newline" + "using `println!(\"\")` with an empty string" } -/// **What it does:** This lint warns when you using `print!()` with a format +/// **What it does:** This lint warns when you use `print!()` with a format /// string that /// ends in a newline. /// diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ba7d4bbbe0f..16a1142efb7 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -46,7 +46,7 @@ pub struct TypePass; /// ``` declare_clippy_lint! { pub BOX_VEC, - complexity, + perf, "usage of `Box>`, vector elements are already on the heap" } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 2684e3999ab..192d6671bcb 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -40,7 +40,7 @@ use std::collections::HashMap; /// ``` declare_clippy_lint! { pub LINT_AUTHOR, - style, // ok, this is not a style lint, but it's also a noop without the appropriate attribute + internal_warn, "helper for writing lints" } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index cc98df941e8..e8d07fbed0d 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -26,7 +26,7 @@ use syntax::attr; /// ``` declare_clippy_lint! { pub DEEP_CODE_INSPECTION, - style, // not a style lint, but essentially a noop without the appropriate attribute + internal_warn, "helper to dump info about code" } diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 83c10c9b193..664be379e35 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -10,7 +10,7 @@ error: this loop never actually loops 13 | | } | |_____^ | - = note: `-D never-loop` implied by `-D warnings` + = note: #[deny(never_loop)] on by default error: this loop never actually loops --> $DIR/never_loop.rs:28:5 -- cgit 1.4.1-3-g733a5 From 83748f5e484c9b76db08080d56da55c31288874a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 30 Mar 2018 10:35:51 +0200 Subject: Rustup to rustc 1.26.0-nightly (ae544ee1c 2018-03-29) --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 9dc4998dfc5..eecae8b230b 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -57,7 +57,7 @@ pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; -pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBound"]; +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; -- cgit 1.4.1-3-g733a5 From 1d5dc3d180cb6f89cbe727b73d45df6582999a38 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 30 Mar 2018 10:38:35 +0200 Subject: Update changelog for 0.191 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c91e6903d..aa32e773e90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.191 +* Rustup to *rustc 1.26.0-nightly (ae544ee1c 2018-03-29)* +* Lint audit; categorize lints as style, correctness, complexity, pedantic, nursery, restriction. + ## 0.0.190 * Fix a bunch of intermittent cargo bugs -- cgit 1.4.1-3-g733a5 From b09e11540421fb32bafa380eedbda945b81cc171 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 30 Mar 2018 10:38:42 +0200 Subject: Bump to 0.191 --- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a28e5c50929..546f180a083 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.190" +version = "0.0.191" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.190", path = "clippy_lints" } +clippy_lints = { version = "0.0.191", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e8d08082d4d..bb29cfd3a01 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.190" +version = "0.0.191" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From b7929cafe188b691a8e41021d3883d1a93dbb313 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 29 Mar 2018 21:14:53 +0200 Subject: Fix false positive in empty_line_after_outer_attr Before, when you had a block comment between an attribute and the following item like this: ```rust \#[crate_type = "lib"] /* */ pub struct Rust; ``` It would cause a false positive on the lint, because there is an empty line inside the block comment. This makes sure that basic block comments are detected and removed from the snippet that was created before. --- clippy_lints/src/attrs.rs | 4 +++- clippy_lints/src/utils/mod.rs | 34 ++++++++++++++++++++++++++++ tests/ui/empty_line_after_outer_attribute.rs | 7 ++++++ tests/without_block_comments.rs | 20 ++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/without_block_comments.rs diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 340d82dfa61..1de64683e88 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; +use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, without_block_comments}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -276,6 +276,8 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { let lines = snippet.split('\n').collect::>(); + let lines = without_block_comments(lines); + if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { span_lint( cx, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 125602319f7..e3202eed679 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1086,3 +1086,37 @@ pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 { let amt = 128 - bits; (u << amt) >> amt } + +/// Remove block comments from the given Vec of lines +/// +/// # Examples +/// +/// ```rust,ignore +/// without_block_comments(vec!["/*", "foo", "*/"]); +/// // => vec![] +/// +/// without_block_comments(vec!["bar", "/*", "foo", "*/"]); +/// // => vec!["bar"] +/// ``` +pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { + let mut without = vec![]; + + // naive approach for block comments + let mut inside_comment = false; + + for line in lines.into_iter() { + if line.contains("/*") { + inside_comment = true; + continue; + } else if line.contains("*/") { + inside_comment = false; + continue; + } + + if !inside_comment { + without.push(line); + } + } + + without +} diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 16eb95abbcb..99e55b2760d 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -79,4 +79,11 @@ pub enum FooFighter { Bar4 } +// This should not produce a warning because there is a comment in between +#[crate_type = "lib"] +/* + +*/ +pub struct S; + fn main() { } diff --git a/tests/without_block_comments.rs b/tests/without_block_comments.rs new file mode 100644 index 00000000000..525a357bdc7 --- /dev/null +++ b/tests/without_block_comments.rs @@ -0,0 +1,20 @@ +extern crate clippy_lints; +use clippy_lints::utils::without_block_comments; + +#[test] +fn test_lines_without_block_comments() { + let result = without_block_comments(vec!["/*", "", "*/"]); + println!("result: {:?}", result); + assert!(result.is_empty()); + + let result = without_block_comments( + vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""] + ); + assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); + + let result = without_block_comments(vec!["/* rust", "", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["foo", "bar", "baz"]); + assert_eq!(result, vec!["foo", "bar", "baz"]); +} -- cgit 1.4.1-3-g733a5 From bb4af196beb20d485b2b56dff8fa023f6ee00a56 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 30 Mar 2018 11:28:37 +0200 Subject: Move empty_line_after_outer_attribute to nursery From the clippy side it's difficult to detect empty lines between an attributes and the following item because empty lines and comments are not part of the AST. The parsing currently works for basic cases but is not perfect and can cause false positives. Maybe libsyntax 2.0 will fix some of the problems around attributes but comments will probably be never part of the AST so we would still have to do some manual parsing. --- clippy_lints/src/attrs.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 1de64683e88..553a98f682d 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -85,7 +85,11 @@ declare_clippy_lint! { /// If it was meant to be an outer attribute, then the following item /// should not be separated by empty lines. /// -/// **Known problems:** None +/// **Known problems:** Can cause false positives. +/// +/// From the clippy side it's difficult to detect empty lines between an attributes and the +/// following item because empty lines and comments are not part of the AST. The parsing +/// currently works for basic cases but is not perfect. /// /// **Example:** /// ```rust @@ -105,7 +109,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub EMPTY_LINE_AFTER_OUTER_ATTR, - style, + nursery, "empty line after outer attribute" } -- cgit 1.4.1-3-g733a5 From db1ec446160ef990675082f3208616de3157a91f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 30 Mar 2018 12:36:30 +0200 Subject: Handle nested block comments --- clippy_lints/src/utils/mod.rs | 9 ++++----- tests/ui/empty_line_after_outer_attribute.rs | 7 ++++++- tests/without_block_comments.rs | 9 +++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e3202eed679..e3a7fc851b1 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1101,19 +1101,18 @@ pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 { pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { let mut without = vec![]; - // naive approach for block comments - let mut inside_comment = false; + let mut nest_level = 0; for line in lines.into_iter() { if line.contains("/*") { - inside_comment = true; + nest_level += 1; continue; } else if line.contains("*/") { - inside_comment = false; + nest_level -= 1; continue; } - if !inside_comment { + if nest_level == 0 { without.push(line); } } diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 99e55b2760d..30063dac0a4 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -79,11 +79,16 @@ pub enum FooFighter { Bar4 } -// This should not produce a warning because there is a comment in between +// This should not produce a warning because the empty line is inside a block comment #[crate_type = "lib"] /* */ pub struct S; +// This should not produce a warning +#[crate_type = "lib"] +/* test */ +pub struct T; + fn main() { } diff --git a/tests/without_block_comments.rs b/tests/without_block_comments.rs index 525a357bdc7..375df057544 100644 --- a/tests/without_block_comments.rs +++ b/tests/without_block_comments.rs @@ -15,6 +15,15 @@ fn test_lines_without_block_comments() { let result = without_block_comments(vec!["/* rust", "", "*/"]); assert!(result.is_empty()); + let result = without_block_comments(vec!["/* one-line comment */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); + assert!(result.is_empty()); + let result = without_block_comments(vec!["foo", "bar", "baz"]); assert_eq!(result, vec!["foo", "bar", "baz"]); } -- cgit 1.4.1-3-g733a5 From 2a52527a463f3e96e38d2eba3ece1bb56d970f5c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 31 Mar 2018 17:53:24 +0200 Subject: Fix lintlib script --- util/lintlib.py | 60 ++++++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/util/lintlib.py b/util/lintlib.py index 1fddcbdc3fa..c28177e1062 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -7,12 +7,11 @@ import collections import logging as log log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s') -Lint = collections.namedtuple('Lint', 'name level doc sourcefile') +Lint = collections.namedtuple('Lint', 'name level doc sourcefile group') Config = collections.namedtuple('Config', 'name ty doc default') lintname_re = re.compile(r'''pub\s+([A-Z_][A-Z_0-9]*)''') -level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''') -group_re = re.compile(r'''([a-z_][a-z_0-9]+)''') +group_re = re.compile(r'''\s*([a-z_][a-z_0-9]+)''') conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) confvar_re = re.compile( r'''/// Lint: (\w+). (.*).*\n\s*\([^,]+,\s+"([^"]+)",\s+([^=\)]+)=>\s+(.*)\),''', re.MULTILINE) @@ -27,6 +26,7 @@ lint_levels = { "nursery": 'Allow', } + def parse_lints(lints, filepath): last_comment = [] comment = True @@ -57,36 +57,30 @@ def parse_lints(lints, filepath): else: last_comment = [] if not comment: - if name: - g = group_re.search(line) - if g: - group = g.group(1).lower() - level = lint_levels[group] - log.info("found %s with level %s in %s", - name, level, filepath) - lints.append(Lint(name, level, last_comment, filepath, group)) - last_comment = [] - comment = True - else: - m = lintname_re.search(line) - if m: - name = m.group(1).lower() - - if deprecated: - level = "Deprecated" - else: - while True: - m = level_re.search(line) - if m: - level = m.group(0) - break - line = next(fp) - if not clippy: - log.info("found %s with level %s in %s", - name, level, filepath) - lints.append(Lint(name, level, last_comment, filepath, "deprecated")) - last_comment = [] - comment = True + m = lintname_re.search(line) + + if m: + name = m.group(1).lower() + line = next(fp) + + if deprecated: + level = "Deprecated" + group = "deprecated" + else: + while True: + g = group_re.search(line) + if g: + group = g.group(1).lower() + level = lint_levels[group] + break + line = next(fp) + + log.info("found %s with level %s in %s", + name, level, filepath) + lints.append(Lint(name, level, last_comment, filepath, group)) + last_comment = [] + comment = True + if "}" in line: log.warn("Warning: missing Lint-Name in %s", filepath) comment = True -- cgit 1.4.1-3-g733a5 From 1ab96db7915f36bae5e1ad645861ef910b79904d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 1 Apr 2018 09:28:53 +0200 Subject: Make dogfood test output to seperate directory This commit makes `cargo clippy` output the build artifacts to a separate directory if the `CLIPPY_DOGFOOD` env var is set. This should prevent dogfood builds from interfering with regular builds. This should help with issue #2595. --- src/main.rs | 17 +++++++++++++++++ tests/dogfood.rs | 1 + 2 files changed, 18 insertions(+) diff --git a/src/main.rs b/src/main.rs index 5bdbaf1bc80..0baeab7338e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,10 +77,27 @@ where if cfg!(windows) { path.set_extension("exe"); } + + let mut extra_envs = vec![]; + if let Ok(_) = std::env::var("CLIPPY_DOGFOOD") { + let target_dir = std::env::var("CARGO_MANIFEST_DIR") + .map(|m| { + std::path::PathBuf::from(m) + .join("target") + .join("dogfood") + .to_string_lossy() + .into_owned() + }) + .unwrap_or("clippy_dogfood".to_string()); + + extra_envs.push(("CARGO_TARGET_DIR", target_dir)); + }; + let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) .env("CLIPPY_ARGS", clippy_args) + .envs(extra_envs) .spawn() .expect("could not run cargo") .wait() diff --git a/tests/dogfood.rs b/tests/dogfood.rs index ed6451a3eb6..a2d4da9a1ca 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -15,6 +15,7 @@ fn dogfood() { .arg("cargo-clippy") .arg("--manifest-path") .arg(root_dir.join("Cargo.toml")) + .env("CLIPPY_DOGFOOD", "true") .output() .unwrap(); println!("status: {}", output.status); -- cgit 1.4.1-3-g733a5 From 609dd47410cac010a9a73e96a4b7237793d73ad5 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 1 Apr 2018 10:17:48 +0200 Subject: Fix clippy warnings from last commit --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0baeab7338e..5cc6fd674eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ where } let mut extra_envs = vec![]; - if let Ok(_) = std::env::var("CLIPPY_DOGFOOD") { + if std::env::var("CLIPPY_DOGFOOD").is_ok() { let target_dir = std::env::var("CARGO_MANIFEST_DIR") .map(|m| { std::path::PathBuf::from(m) @@ -88,7 +88,7 @@ where .to_string_lossy() .into_owned() }) - .unwrap_or("clippy_dogfood".to_string()); + .unwrap_or_else(|_| "clippy_dogfood".to_string()); extra_envs.push(("CARGO_TARGET_DIR", target_dir)); }; -- cgit 1.4.1-3-g733a5 From 872db029cf8e85ec130af0ba9bf851ee347c3b14 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 1 Apr 2018 15:31:25 +0200 Subject: Improve CONTRIBUTING.md * Incremental compilation is on by default * Restructured the label overview to go from easy to more difficult labels. --- CONTRIBUTING.md | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 61e5cd67936..ebdb88a3ba9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,41 +15,41 @@ High level approach: All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. -Some issues are easier than others. The [good first issue](https://github.com/rust-lang-nursery/rust-clippy/labels/good%20first%20issue) +Some issues are easier than others. The [`good first issue`](https://github.com/rust-lang-nursery/rust-clippy/labels/good%20first%20issue) label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! -Issues marked [T-AST](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) involve simple +Issues marked [`T-AST`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) involve simple matching of the syntax tree structure, and are generally easier than -[T-middle](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues, which involve types +[`T-middle`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues, which involve types and resolved paths. -Issues marked [E-medium](https://github.com/rust-lang-nursery/rust-clippy/labels/E-medium) are generally -pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified -as `E-medium`, since they might be somewhat involved code wise, but not difficult per-se. - -[Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer -to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of -`LintPass` with one or more of its default methods overridden. See the existing lints for examples -of this. - -T-AST issues will generally need you to match against a predefined syntax structure. To figure out +[`T-AST`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST docs](http://manishearth.github.io/rust-internals-docs/syntax/ast/). Usually the lint will end up to be a nested series of matches and ifs, [like so](https://github.com/rust-lang-nursery/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). -T-middle issues can be more involved and require verifying types. The +[`E-medium`](https://github.com/rust-lang-nursery/rust-clippy/labels/E-medium) issues are generally +pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified +as `E-medium`, since they might be somewhat involved code wise, but not difficult per-se. + +[`T-middle`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues can +be more involved and require verifying types. The [`ty`](http://manishearth.github.io/rust-internals-docs/rustc/ty) module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. ### Writing code -Compiling clippy can take almost a minute or more depending on your machine. -You can set the environment flag `CARGO_INCREMENTAL=1` to cut down that time to -almost a third on average, depending on the influence your change has. +Compiling clippy from scratch can take almost a minute or more depending on your machine. +However, since Rust 1.24.0 incremental compilation is enabled by default and compile times for small changes should be quick. + +[Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer +to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of +`LintPass` with one or more of its default methods overridden. See the existing lints for examples +of this. Please document your lint with a doc comment akin to the following: @@ -61,8 +61,13 @@ Please document your lint with a doc comment akin to the following: /// **Known problems:** None. (Or describe where it could go wrong.) /// /// **Example:** +/// /// ```rust -/// Insert a short example if you have one. +/// // Bad +/// Insert a short example of code that triggers the lint +/// +/// // Good +/// Insert a short example of improved code that doesn't trigger the lint /// ``` ``` @@ -80,12 +85,6 @@ If you don't want to wait for all tests to finish, you can also execute a single TESTNAME=ui/empty_line_after_outer_attr cargo test --test compile-test ``` -And you can also combine this with `CARGO_INCREMENTAL`: - -```bash -CARGO_INCREMENTAL=1 TESTNAME=ui/doc cargo test --test compile-test -``` - ### Testing manually Manually testing against an example file is useful if you have added some -- cgit 1.4.1-3-g733a5 From 62220abfa65b9d961f23da998ec94d3727477957 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sun, 1 Apr 2018 19:28:07 +0100 Subject: Add implementation and tests for literal checking in print/println format args --- clippy_lints/src/print.rs | 65 ++++++++++++++++++++++++++- tests/ui/print_literal.rs | 32 ++++++++++++++ tests/ui/print_literal.stderr | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 tests/ui/print_literal.rs create mode 100644 tests/ui/print_literal.stderr diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 6d9880e1335..a52d76e81da 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -78,12 +78,28 @@ declare_clippy_lint! { "use of `Debug`-based formatting" } +/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args. +/// +/// **Why is this bad?** Using literals as `println!` args is inefficient +/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary +/// (i.e., just put the literal in the format string) +/// +/// **Example:** +/// ```rust +/// println!("{}", "foo"); +/// ``` +declare_lint! { + pub PRINT_LITERAL, + Allow, + "printing a literal with a format string" +} + #[derive(Copy, Clone, Debug)] pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, USE_DEBUG) + lint_array!(PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, USE_DEBUG, PRINT_LITERAL) } } @@ -107,6 +123,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); + // Check for literals in the print!/println! args + // Also, ensure the format string is `{}` with no special options, like `{:X}` + check_print_args_for_literal(cx, args); + if_chain! { // ensure we're calling Arguments::new_v1 if args.len() == 1; @@ -146,6 +166,49 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } +// Check for literals in print!/println! args +// ensuring the format string for the literal is `DISPLAY_FMT_METHOD` +// e.g., `println!("... {} ...", "foo")` +// ^ literal in `println!` +fn check_print_args_for_literal<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + args: &HirVec +) { + if_chain! { + if args.len() == 1; + if let ExprCall(_, ref args_args) = args[0].node; + if args_args.len() > 1; + if let ExprAddrOf(_, ref match_expr) = args_args[1].node; + if let ExprMatch(ref matchee, ref arms, _) = match_expr.node; + if let ExprTup(ref tup) = matchee.node; + if arms.len() == 1; + if let ExprArray(ref arm_body_exprs) = arms[0].body.node; + then { + // it doesn't matter how many args there are in the `print!`/`println!`, + // if there's one literal, we should warn the user + for (idx, tup_arg) in tup.iter().enumerate() { + if_chain! { + // first, make sure we're dealing with a literal (i.e., an ExprLit) + if let ExprAddrOf(_, ref tup_val) = tup_arg.node; + if let ExprLit(_) = tup_val.node; + + // next, check the corresponding match arm body to ensure + // this is "{}", or DISPLAY_FMT_METHOD + if let ExprCall(_, ref body_args) = arm_body_exprs[idx].node; + if body_args.len() == 2; + if let ExprPath(ref body_qpath) = body_args[1].node; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD) || + match_def_path(cx.tcx, fun_def_id, &paths::DEBUG_FMT_METHOD); + then { + span_lint(cx, PRINT_LITERAL, tup_val.span, "printing a literal with an empty format string"); + } + } + } + } + } +} + // Check for print!("... \n", ...). fn check_print<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs new file mode 100644 index 00000000000..c803294ab0a --- /dev/null +++ b/tests/ui/print_literal.rs @@ -0,0 +1,32 @@ + + +#![warn(print_literal)] + +fn main() { + // these should be fine + print!("Hello"); + println!("Hello"); + let world = "world"; + println!("Hello {}", world); + println!("3 in hex is {:X}", 3); + + // these should throw warnings + print!("Hello {}", "world"); + println!("Hello {} {}", world, "world"); + println!("Hello {}", "world"); + println!("10 / 4 is {}", 2.5); + println!("2 + 1 = {}", 3); + println!("2 + 1 = {:.4}", 3); + println!("2 + 1 = {:5.4}", 3); + println!("Debug test {:?}", "hello, world"); + + // positional args don't change the fact + // that we're using a literal -- this should + // throw a warning + println!("{0} {1}", "hello", "world"); + println!("{1} {0}", "hello", "world"); + + // named args shouldn't change anything either + println!("{foo} {bar}", foo="hello", bar="world"); + println!("{bar} {foo}", foo="hello", bar="world"); +} diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr new file mode 100644 index 00000000000..982be7dc537 --- /dev/null +++ b/tests/ui/print_literal.stderr @@ -0,0 +1,100 @@ +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:14:24 + | +14 | print!("Hello {}", "world"); + | ^^^^^^^ + | + = note: `-D print-literal` implied by `-D warnings` + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:15:36 + | +15 | println!("Hello {} {}", world, "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:16:26 + | +16 | println!("Hello {}", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:17:30 + | +17 | println!("10 / 4 is {}", 2.5); + | ^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:18:28 + | +18 | println!("2 + 1 = {}", 3); + | ^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:19:31 + | +19 | println!("2 + 1 = {:.4}", 3); + | ^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:20:32 + | +20 | println!("2 + 1 = {:5.4}", 3); + | ^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:21:33 + | +21 | println!("Debug test {:?}", "hello, world"); + | ^^^^^^^^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:26:25 + | +26 | println!("{0} {1}", "hello", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:26:34 + | +26 | println!("{0} {1}", "hello", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:27:25 + | +27 | println!("{1} {0}", "hello", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:27:34 + | +27 | println!("{1} {0}", "hello", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:30:33 + | +30 | println!("{foo} {bar}", foo="hello", bar="world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:30:46 + | +30 | println!("{foo} {bar}", foo="hello", bar="world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:31:33 + | +31 | println!("{bar} {foo}", foo="hello", bar="world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:31:46 + | +31 | println!("{bar} {foo}", foo="hello", bar="world"); + | ^^^^^^^ + +error: aborting due to 16 previous errors + -- cgit 1.4.1-3-g733a5 From ddd75fbfec53f32df3611e56924d65154dee24a5 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Mon, 2 Apr 2018 00:24:25 +0100 Subject: Add #![allow(print_literal)] to other test/ui/print_*.rs tests --- tests/ui/format.rs | 2 +- tests/ui/print.rs | 1 + tests/ui/print.stderr | 32 ++++++++++++++++---------------- tests/ui/print_with_newline.rs | 1 + tests/ui/print_with_newline.stderr | 4 ++-- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/ui/format.rs b/tests/ui/format.rs index e9379d0a05b..5e18b74bb2c 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,5 +1,5 @@ - +#![allow(print_literal)] #![warn(useless_format)] fn main() { diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 91304d961a7..786398cfe5e 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,5 +1,6 @@ +#![allow(print_literal)] #![warn(print_stdout, use_debug)] use std::fmt::{Debug, Display, Formatter, Result}; diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 789e1218b78..457ed38a1b5 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,53 +1,53 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:12:27 + --> $DIR/print.rs:13:27 | -12 | write!(f, "{:?}", 43.1415) +13 | write!(f, "{:?}", 43.1415) | ^^^^^^^ | = note: `-D use-debug` implied by `-D warnings` error: use of `println!` - --> $DIR/print.rs:24:5 + --> $DIR/print.rs:25:5 | -24 | println!("Hello"); +25 | println!("Hello"); | ^^^^^^^^^^^^^^^^^^ | = note: `-D print-stdout` implied by `-D warnings` error: use of `print!` - --> $DIR/print.rs:25:5 + --> $DIR/print.rs:26:5 | -25 | print!("Hello"); +26 | print!("Hello"); | ^^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:27:5 + --> $DIR/print.rs:28:5 | -27 | print!("Hello {}", "World"); +28 | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:29:5 + --> $DIR/print.rs:30:5 | -29 | print!("Hello {:?}", "World"); +30 | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:29:26 + --> $DIR/print.rs:30:26 | -29 | print!("Hello {:?}", "World"); +30 | print!("Hello {:?}", "World"); | ^^^^^^^ error: use of `print!` - --> $DIR/print.rs:31:5 + --> $DIR/print.rs:32:5 | -31 | print!("Hello {:#?}", "#orld"); +32 | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:31:27 + --> $DIR/print.rs:32:27 | -31 | print!("Hello {:#?}", "#orld"); +32 | print!("Hello {:#?}", "#orld"); | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 5cc50dea810..5445c862096 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,5 +1,6 @@ +#![allow(print_literal)] #![warn(print_with_newline)] fn main() { diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 4f32d1b2a2d..5f2013e728e 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,7 +1,7 @@ error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:6:5 + --> $DIR/print_with_newline.rs:7:5 | -6 | print!("Hello/n"); +7 | print!("Hello/n"); | ^^^^^^^^^^^^^^^^^^ | = note: `-D print-with-newline` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 511aa654d70c2a04cc50d21be8c25bd120e3b027 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Mon, 2 Apr 2018 00:25:57 +0100 Subject: Change declare_lint! to declare_clippy_lint! --- clippy_lints/src/print.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index a52d76e81da..5dce94a721e 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -88,9 +88,9 @@ declare_clippy_lint! { /// ```rust /// println!("{}", "foo"); /// ``` -declare_lint! { +declare_clippy_lint! { pub PRINT_LITERAL, - Allow, + style, "printing a literal with a format string" } -- cgit 1.4.1-3-g733a5 From 6397131f8a2ebef377a62094a02c2e8637cb9aca Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 06:22:10 +0200 Subject: Fix clippy warning Allow `many_single_char_names` on `SpanlessHash::hash_expr`. Each variable has a small scope and the method is readable. --- clippy_lints/src/utils/hir_utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index e790184a7ab..1f96ec2b237 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -316,6 +316,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { b.rules.hash(&mut self.s); } + #[allow(many_single_char_names)] pub fn hash_expr(&mut self, e: &Expr) { if let Some(e) = constant_simple(self.cx, e) { return e.hash(&mut self.s); -- cgit 1.4.1-3-g733a5 From 57af95b6f5d8126bf967022e182b1973e2771d38 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 06:34:11 +0200 Subject: Fix clippy warning Fix `option_option` warning on `to_const_range` by taking the entire range as an parameter instead of the start and end. --- clippy_lints/src/array_indexing.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 4563a58f7ab..1b21cf8c5ff 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -3,6 +3,7 @@ use rustc::ty; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; +use utils::higher::Range; use consts::{constant, Constant}; /// **What it does:** Checks for out of bounds array indexing with a constant @@ -73,10 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Index is a constant range if let Some(range) = higher::range(index) { - let start = range.start.map(|start| constant(cx, start).map(|(c, _)| c)); - let end = range.end.map(|end| constant(cx, end).map(|(c, _)| c)); - - if let Some((start, end)) = to_const_range(&start, &end, range.limits, size) { + if let Some((start, end)) = to_const_range(cx, range, size) { if start > size || end > size { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); } @@ -102,20 +100,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { /// Returns an option containing a tuple with the start and end (exclusive) of /// the range. -fn to_const_range( - start: &Option>, - end: &Option>, - limits: RangeLimits, - array_size: u128, -) -> Option<(u128, u128)> { - let start = match *start { +fn to_const_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, range: Range, array_size: u128) -> Option<(u128, u128)> { + let s = range.start.map(|expr| constant(cx, expr).map(|(c, _)| c)); + let start = match s { Some(Some(Constant::Int(x))) => x, Some(_) => return None, None => 0, }; - let end = match *end { - Some(Some(Constant::Int(x))) => if limits == RangeLimits::Closed { + let e = range.end.map(|expr| constant(cx, expr).map(|(c, _)| c)); + let end = match e { + Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { x + 1 } else { x -- cgit 1.4.1-3-g733a5 From 89cb0531462da0e6cc116b4b5ef86de908654447 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 06:42:30 +0200 Subject: Fix clippy warning Fix cyclomatic_complexity warning on `check_expr` by allowing it. This is preferable to increasing the threshold every time the method changes. --- clippy_lints/src/methods.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 50de299ca7d..29e8a9a82b1 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -680,9 +680,7 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - #[allow(unused_attributes)] - // ^ required because `cyclomatic_complexity` attribute shows up as unused - #[cyclomatic_complexity = "30"] + #[allow(cyclomatic_complexity)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if in_macro(expr.span) { return; -- cgit 1.4.1-3-g733a5 From fcabbeb251bedabce6b45b8c4db6ec15e6002b82 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 06:57:14 +0200 Subject: Fix clippy warning Fix too_many_arguments on `check_general_case` by allowing it. I can't see a sensible way of grouping the parameters. --- clippy_lints/src/methods.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 29e8a9a82b1..423be2106d1 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -887,6 +887,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: } /// Check for `*or(foo())`. + #[allow(too_many_arguments)] fn check_general_case( cx: &LateContext, name: &str, -- cgit 1.4.1-3-g733a5 From e91404bcc3908f7ff4ea82003cd21230e4d34acd Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 07:35:13 +0200 Subject: Fix clippy warning --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e3a7fc851b1..f71de382cad 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1103,7 +1103,7 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { let mut nest_level = 0; - for line in lines.into_iter() { + for line in lines { if line.contains("/*") { nest_level += 1; continue; -- cgit 1.4.1-3-g733a5 From add4434ee37d8ee87df63852cf86f02d4c3992a1 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 2 Apr 2018 09:28:08 +0200 Subject: Support non-unicode paths for dogfood test --- src/main.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5cc6fd674eb..aac5e97f311 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,26 +78,29 @@ where path.set_extension("exe"); } - let mut extra_envs = vec![]; - if std::env::var("CLIPPY_DOGFOOD").is_ok() { - let target_dir = std::env::var("CARGO_MANIFEST_DIR") - .map(|m| { - std::path::PathBuf::from(m) - .join("target") - .join("dogfood") - .to_string_lossy() - .into_owned() - }) - .unwrap_or_else(|_| "clippy_dogfood".to_string()); - - extra_envs.push(("CARGO_TARGET_DIR", target_dir)); - }; + let target_dir = std::env::var_os("CLIPPY_DOGFOOD") + .map(|_| { + std::env::var_os("CARGO_MANIFEST_DIR").map_or_else( + || { + let mut fallback = std::ffi::OsString::new(); + fallback.push("clippy_dogfood"); + fallback + }, + |d| { + std::path::PathBuf::from(d) + .join("target") + .join("dogfood") + .into_os_string() + }, + ) + }) + .map(|p| ("CARGO_TARGET_DIR", p)); let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) .env("CLIPPY_ARGS", clippy_args) - .envs(extra_envs) + .envs(target_dir) .spawn() .expect("could not run cargo") .wait() -- cgit 1.4.1-3-g733a5 From fe8ba21962652e91a556fde596a19b6903c0000a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 2 Apr 2018 11:13:02 +0200 Subject: Readme: Explain nightly install and clippy update --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bdd2c7dcb02..f3320b0e260 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,12 @@ as an included feature during build. All of these options are detailed below. As a general rule clippy will only work with the *latest* Rust nightly for now. +To install Rust nightly, the recommended way is to use [rustup](https://rustup.rs/): + +```terminal +rustup install nightly +``` + ### As a cargo subcommand (`cargo clippy`) One way to use clippy is by installing clippy through cargo as a cargo @@ -48,6 +54,13 @@ cargo +nightly install clippy Now you can run clippy by invoking `cargo +nightly clippy`. +To update the subcommand together with the latest nightly use the [rust-update](rust-update) script or run: + +```terminal +rustup update nightly +cargo +nightly install --force clippy +``` + In case you are not using rustup, you need to set the environment flag `SYSROOT` during installation so clippy knows where to find `librustc` and similar crates. @@ -191,7 +204,7 @@ You can add options to `allow`/`warn`/`deny`: Note: `deny` produces errors instead of warnings. For convenience, `cargo clippy` automatically defines a `cargo-clippy` -features. This lets you set lints level and compile with or without clippy +feature. This lets you set lint levels and compile with or without clippy transparently: ```rust -- cgit 1.4.1-3-g733a5 From b1b0b36cc0385bd43c2b56d45eb00272f72cda23 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 2 Apr 2018 14:38:28 +0200 Subject: Document the author lint --- CONTRIBUTING.md | 40 ++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/author.rs | 7 +++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebdb88a3ba9..c9f760209c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,6 +51,44 @@ to lint-writing, though it does get into advanced stuff. Most lints consist of a `LintPass` with one or more of its default methods overridden. See the existing lints for examples of this. + +#### Author lint + +There is also the internal `author` lint to generate clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. + +Create a new UI test with the pattern you want to match: + +```rust +// ./tests/ui/my_lint.rs + +// The custom_attribute needs to be enabled for the author lint to work +#![feature(plugin, custom_attribute)] + +fn main() { + #[clippy(author)] + let arr: [i32; 1] = [7]; // Replace line with the code you want to match +} +``` + +Now you run `TESTNAME=ui/my_lint cargo test --test compile-test` to produce +the file with the generated code: + +```rust +// ./tests/ui/my_lint.stdout + +if_chain! { + if let Expr_::ExprArray(ref elements) = stmt.node; + if elements.len() == 1; + if let Expr_::ExprLit(ref lit) = elements[0].node; + if let LitKind::Int(7, _) = lit.node; + then { + // report your lint here + } +} +``` + +#### Documentation + Please document your lint with a doc comment akin to the following: ```rust @@ -71,6 +109,8 @@ Please document your lint with a doc comment akin to the following: /// ``` ``` +Once your lint is merged it will show up in the [lint list](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) + ### Running test suite Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 192d6671bcb..9d708d637c3 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -14,6 +14,7 @@ use std::collections::HashMap; /// /// **Example:** /// ```rust +/// // ./tests/ui/my_lint.rs /// fn foo() { /// // detect the following pattern /// #[clippy(author)] @@ -24,9 +25,11 @@ use std::collections::HashMap; /// } /// ``` /// -/// prints +/// Running `TESTNAME=ui/my_lint cargo test --test compile-test` will produce +/// a `./tests/ui/new_lint.stdout` file with the generated code: /// -/// ``` +/// ```rust +/// // ./tests/ui/new_lint.stdout /// if_chain!{ /// if let Expr_::ExprIf(ref cond, ref then, None) = item.node, /// if let Expr_::ExprBinary(BinOp::Eq, ref left, ref right) = cond.node, -- cgit 1.4.1-3-g733a5 From d504290839c2c6736b9a6d1f97ac8f4d48467341 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Mon, 2 Apr 2018 20:32:46 +0100 Subject: Add edge case with env! arg to test and known problems --- clippy_lints/src/print.rs | 3 ++ tests/ui/print_literal.rs | 6 ++++ tests/ui/print_literal.stderr | 74 +++++++++++++++++++++++-------------------- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 5dce94a721e..ddfe6d68f4a 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -84,6 +84,9 @@ declare_clippy_lint! { /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary /// (i.e., just put the literal in the format string) /// +/// **Known problems:** Will also warn with macro calls as arguments that expand to literals +/// -- e.g., `println!("{}", env!("FOO"))`. +/// /// **Example:** /// ```rust /// println!("{}", "foo"); diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index c803294ab0a..d920e6fa3d2 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -10,6 +10,12 @@ fn main() { println!("Hello {}", world); println!("3 in hex is {:X}", 3); + // this in theory shouldn't yield a warning, + // but at present time, it's a known edge case + // that isn't handled (because we can't expand + // `println!` and not `env!`) + println!("foo: {}", env!("BAR")); + // these should throw warnings print!("Hello {}", "world"); println!("Hello {} {}", world, "world"); diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 982be7dc537..8adeedfc8bd 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,100 +1,106 @@ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:14:24 + --> $DIR/print_literal.rs:17:25 | -14 | print!("Hello {}", "world"); - | ^^^^^^^ +17 | println!("foo: {}", env!("BAR")); + | ^^^^^^^^^^^ | = note: `-D print-literal` implied by `-D warnings` error: printing a literal with an empty format string - --> $DIR/print_literal.rs:15:36 + --> $DIR/print_literal.rs:20:24 + | +20 | print!("Hello {}", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:21:36 | -15 | println!("Hello {} {}", world, "world"); +21 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:16:26 + --> $DIR/print_literal.rs:22:26 | -16 | println!("Hello {}", "world"); +22 | println!("Hello {}", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:17:30 + --> $DIR/print_literal.rs:23:30 | -17 | println!("10 / 4 is {}", 2.5); +23 | println!("10 / 4 is {}", 2.5); | ^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:18:28 + --> $DIR/print_literal.rs:24:28 | -18 | println!("2 + 1 = {}", 3); +24 | println!("2 + 1 = {}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:19:31 + --> $DIR/print_literal.rs:25:31 | -19 | println!("2 + 1 = {:.4}", 3); +25 | println!("2 + 1 = {:.4}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:20:32 + --> $DIR/print_literal.rs:26:32 | -20 | println!("2 + 1 = {:5.4}", 3); +26 | println!("2 + 1 = {:5.4}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:21:33 + --> $DIR/print_literal.rs:27:33 | -21 | println!("Debug test {:?}", "hello, world"); +27 | println!("Debug test {:?}", "hello, world"); | ^^^^^^^^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:26:25 + --> $DIR/print_literal.rs:32:25 | -26 | println!("{0} {1}", "hello", "world"); +32 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:26:34 + --> $DIR/print_literal.rs:32:34 | -26 | println!("{0} {1}", "hello", "world"); +32 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:27:25 + --> $DIR/print_literal.rs:33:25 | -27 | println!("{1} {0}", "hello", "world"); +33 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:27:34 + --> $DIR/print_literal.rs:33:34 | -27 | println!("{1} {0}", "hello", "world"); +33 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:30:33 + --> $DIR/print_literal.rs:36:33 | -30 | println!("{foo} {bar}", foo="hello", bar="world"); +36 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:30:46 + --> $DIR/print_literal.rs:36:46 | -30 | println!("{foo} {bar}", foo="hello", bar="world"); +36 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:31:33 + --> $DIR/print_literal.rs:37:33 | -31 | println!("{bar} {foo}", foo="hello", bar="world"); +37 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:31:46 + --> $DIR/print_literal.rs:37:46 | -31 | println!("{bar} {foo}", foo="hello", bar="world"); +37 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From fa8161ba2e36cd5ca6e17bf2b09c4307e7e4e2eb Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Mon, 2 Apr 2018 21:31:41 +0100 Subject: Revert adding env! to tests --- tests/ui/print_literal.rs | 6 ---- tests/ui/print_literal.stderr | 74 ++++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index d920e6fa3d2..c803294ab0a 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -10,12 +10,6 @@ fn main() { println!("Hello {}", world); println!("3 in hex is {:X}", 3); - // this in theory shouldn't yield a warning, - // but at present time, it's a known edge case - // that isn't handled (because we can't expand - // `println!` and not `env!`) - println!("foo: {}", env!("BAR")); - // these should throw warnings print!("Hello {}", "world"); println!("Hello {} {}", world, "world"); diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 8adeedfc8bd..982be7dc537 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,106 +1,100 @@ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:17:25 + --> $DIR/print_literal.rs:14:24 | -17 | println!("foo: {}", env!("BAR")); - | ^^^^^^^^^^^ +14 | print!("Hello {}", "world"); + | ^^^^^^^ | = note: `-D print-literal` implied by `-D warnings` error: printing a literal with an empty format string - --> $DIR/print_literal.rs:20:24 - | -20 | print!("Hello {}", "world"); - | ^^^^^^^ - -error: printing a literal with an empty format string - --> $DIR/print_literal.rs:21:36 + --> $DIR/print_literal.rs:15:36 | -21 | println!("Hello {} {}", world, "world"); +15 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:22:26 + --> $DIR/print_literal.rs:16:26 | -22 | println!("Hello {}", "world"); +16 | println!("Hello {}", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:23:30 + --> $DIR/print_literal.rs:17:30 | -23 | println!("10 / 4 is {}", 2.5); +17 | println!("10 / 4 is {}", 2.5); | ^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:24:28 + --> $DIR/print_literal.rs:18:28 | -24 | println!("2 + 1 = {}", 3); +18 | println!("2 + 1 = {}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:25:31 + --> $DIR/print_literal.rs:19:31 | -25 | println!("2 + 1 = {:.4}", 3); +19 | println!("2 + 1 = {:.4}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:26:32 + --> $DIR/print_literal.rs:20:32 | -26 | println!("2 + 1 = {:5.4}", 3); +20 | println!("2 + 1 = {:5.4}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:27:33 + --> $DIR/print_literal.rs:21:33 | -27 | println!("Debug test {:?}", "hello, world"); +21 | println!("Debug test {:?}", "hello, world"); | ^^^^^^^^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:32:25 + --> $DIR/print_literal.rs:26:25 | -32 | println!("{0} {1}", "hello", "world"); +26 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:32:34 + --> $DIR/print_literal.rs:26:34 | -32 | println!("{0} {1}", "hello", "world"); +26 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:33:25 + --> $DIR/print_literal.rs:27:25 | -33 | println!("{1} {0}", "hello", "world"); +27 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:33:34 + --> $DIR/print_literal.rs:27:34 | -33 | println!("{1} {0}", "hello", "world"); +27 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:36:33 + --> $DIR/print_literal.rs:30:33 | -36 | println!("{foo} {bar}", foo="hello", bar="world"); +30 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:36:46 + --> $DIR/print_literal.rs:30:46 | -36 | println!("{foo} {bar}", foo="hello", bar="world"); +30 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:37:33 + --> $DIR/print_literal.rs:31:33 | -37 | println!("{bar} {foo}", foo="hello", bar="world"); +31 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:37:46 + --> $DIR/print_literal.rs:31:46 | -37 | println!("{bar} {foo}", foo="hello", bar="world"); +31 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From 6fc9d90b60f613fb272b1ea3d8c87e86fcc19332 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 3 Apr 2018 06:22:42 +0200 Subject: Re-enable dogfood test on Windows This should work now that dogfood uses a separate output directory. --- tests/dogfood.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index a2d4da9a1ca..a586d89ca4f 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -3,9 +3,6 @@ fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() { return; } - if cfg!(windows) { - return; - } let root_dir = std::env::current_dir().unwrap(); for d in &[".", "clippy_lints"] { std::env::set_current_dir(root_dir.join(d)).unwrap(); -- cgit 1.4.1-3-g733a5 From 35125d370f788d4c8c44751434592d7e8e841462 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Mon, 2 Apr 2018 23:11:47 -0700 Subject: Move `set -e` to before the deploy I _think_ this might be why the deploy script crashing isn't causing the release to fail (see #2600) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 29879e44755..069336c6964 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,9 +50,9 @@ script: after_success: | #!/bin/bash if [ $(uname) == Linux ]; then - ./.github/deploy.sh - # trigger rebuild of the clippy-service, to keep it up to date with clippy itself set -e + ./.github/deploy.sh + # trigger rebuild of the clippy-service, to keep it up to date with clippy itself if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_REPO_SLUG" == "Manishearth/rust-clippy" ] && [ "$TRAVIS_BRANCH" == "master" ] && -- cgit 1.4.1-3-g733a5 From cecfdeab196f30cf12bfa757e3e15ce9e3417689 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 3 Apr 2018 16:41:30 +0200 Subject: Don't trigger while_immutable_condition for mutable fields of tuples/structs --- clippy_lints/src/loops.rs | 12 ++++++------ tests/ui/infinite_loop.rs | 6 ++++++ tests/ui/infinite_loop.stderr | 24 ++++++++++++------------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6f04940ae31..9a6b7627b47 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2237,7 +2237,7 @@ struct MutVarsDelegate { } impl<'tcx> MutVarsDelegate { - fn update(&mut self, cat: &'tcx Categorization, sp: Span) { + fn update(&mut self, cat: &'tcx Categorization) { match *cat { Categorization::Local(id) => if let Some(used) = self.used_mutably.get_mut(&id) { @@ -2249,7 +2249,7 @@ impl<'tcx> MutVarsDelegate { //`while`-body, not just the ones in the condition. self.skip = true }, - Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp), + Categorization::Deref(ref cmt, _) | Categorization::Interior(ref cmt, _) => self.update(&cmt.cat), _ => {} } } @@ -2263,14 +2263,14 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { - self.update(&cmt.cat, sp) + self.update(&cmt.cat) } } - fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { - self.update(&cmt.cat, sp) + fn mutate(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: MutateMode) { + self.update(&cmt.cat) } fn decl_without_init(&mut self, _: NodeId, _: Span) {} diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 4029f9a9b29..353d34134eb 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -55,6 +55,12 @@ fn immutable_condition() { } }; c(); + + let mut tup = (0, 0); + while tup.0 < 5 { + tup.0 += 1; + println!("OK - tup.0 gets mutated") + } } fn unused_var() { diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index d24fd925e6d..26ec9582fb4 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -19,39 +19,39 @@ error: Variable in the condition are not mutated in the loop body. This either l | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:64:11 + --> $DIR/infinite_loop.rs:70:11 | -64 | while i < 3 { +70 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:69:11 + --> $DIR/infinite_loop.rs:75:11 | -69 | while i < 3 && j > 0 { +75 | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:73:11 + --> $DIR/infinite_loop.rs:79:11 | -73 | while i < 3 { +79 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:88:11 + --> $DIR/infinite_loop.rs:94:11 | -88 | while i < 3 { +94 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:93:11 + --> $DIR/infinite_loop.rs:99:11 | -93 | while i < 3 { +99 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:156:15 + --> $DIR/infinite_loop.rs:162:15 | -156 | while self.count < n { +162 | while self.count < n { | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From c170e8640349657c054c16132be37417c9289948 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 3 Apr 2018 19:05:33 -0700 Subject: new internals docs --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9f760209c0..b57cb4845e3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ and resolved paths. [`T-AST`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an example of the structure and compare with the -[nodes in the AST docs](http://manishearth.github.io/rust-internals-docs/syntax/ast/). Usually +[nodes in the AST docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast). Usually the lint will end up to be a nested series of matches and ifs, [like so](https://github.com/rust-lang-nursery/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). -- cgit 1.4.1-3-g733a5 From a8bb8925cbb8a3374e5a58dc988e7010583a6e91 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 4 Apr 2018 07:08:35 +0200 Subject: Fix clippy warning --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index aac5e97f311..057a585e3d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,7 @@ fn show_help() { #[allow(print_stdout)] fn show_version() { - println!("{}", env!("CARGO_PKG_VERSION")); + println!(env!("CARGO_PKG_VERSION")); } pub fn main() { -- cgit 1.4.1-3-g733a5 From 1c73db172a59ff4e34b3bc636614029401e66a7a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 3 Apr 2018 22:47:27 -0700 Subject: fix other instance of internals docs --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b57cb4845e3..16e1696706e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,7 +37,7 @@ as `E-medium`, since they might be somewhat involved code wise, but not difficul [`T-middle`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues can be more involved and require verifying types. The -[`ty`](http://manishearth.github.io/rust-internals-docs/rustc/ty) module contains a +[`ty`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty) module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. -- cgit 1.4.1-3-g733a5 From c7aa8b0458eb0f36e72df5126602d9a8723ad53c Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Wed, 4 Apr 2018 19:49:55 +0200 Subject: Add missing `clippy_` prefix to lint groups in Readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f3320b0e260..03ee1262a9c 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ We have a bunch of lint categories to allow you to choose how much clippy is sup * `clippy` (everything that has no false positives) * `clippy_pedantic` (everything) * `clippy_style` (code that should be written in a more idiomatic way) -* `complexity` (code that does something simple but in a complex way) -* `perf` (code that can be written in a faster way) -* **`correctness`** (code that is just outright wrong or very very useless) +* `clippy_complexity` (code that does something simple but in a complex way) +* `clippy_perf` (code that can be written in a faster way) +* **`clippy_correctness`** (code that is just outright wrong or very very useless) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! -- cgit 1.4.1-3-g733a5 From 51336711d357e9f93d0b3074658c2d8da6d960c3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 4 Apr 2018 17:56:44 -0700 Subject: Remove uses of ExprKind::Inplace --- clippy_lints/src/utils/sugg.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4ca6e5cbf73..c12c5be2d00 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -98,7 +98,6 @@ impl<'a> Sugg<'a> { ast::ExprKind::Closure(..) | ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | - ast::ExprKind::InPlace(..) | ast::ExprKind::Unary(..) | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), ast::ExprKind::Block(..) | @@ -308,7 +307,6 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { AssocOp::ShiftLeft | AssocOp::ShiftRight | AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), - AssocOp::Inplace => format!("in ({}) {}", lhs, rhs), AssocOp::Assign => format!("{} = {}", lhs, rhs), AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), AssocOp::As => format!("{} as {}", lhs, rhs), @@ -350,7 +348,7 @@ fn associativity(op: &AssocOp) -> Associativity { use syntax::util::parser::AssocOp::*; match *op { - Inplace | Assign | AssignOp(_) => Associativity::Right, + Assign | AssignOp(_) => Associativity::Right, Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, Divide | Equal | -- cgit 1.4.1-3-g733a5 From d71f918616783b25b4023e98356f13ceab1bebcd Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 4 Apr 2018 17:59:54 -0700 Subject: Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa32e773e90..eb3370e1788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.192 +* Rustup to *rustc 1.27.0-nightly (fb44b4c0e 2018-04-04)* +* New lint: [`print_literal`] + ## 0.0.191 * Rustup to *rustc 1.26.0-nightly (ae544ee1c 2018-03-29)* * Lint audit; categorize lints as style, correctness, complexity, pedantic, nursery, restriction. @@ -711,6 +715,7 @@ All notable changes to this project will be documented in this file. [`partialeq_ne_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#partialeq_ne_impl [`possible_missing_comma`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence +[`print_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_literal [`print_stdout`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_stdout [`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline [`println_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#println_empty_string -- cgit 1.4.1-3-g733a5 From 20466940295f0893dbcb9798a790394bd9070b7d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 4 Apr 2018 18:00:21 -0700 Subject: Bump version to 0.0.192 --- Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 546f180a083..0c478510f25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.191" +version = "0.0.192" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.191", path = "clippy_lints" } +clippy_lints = { version = "0.0.192", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/README.md b/README.md index 03ee1262a9c..260691faa00 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 248 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 249 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index bb29cfd3a01..389bf008056 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.191" +version = "0.0.192" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 187b1fcee82..8b8da64eaea 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -472,7 +472,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_SEMVER, - attrs::EMPTY_LINE_AFTER_OUTER_ATTR, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, @@ -611,6 +610,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, + print::PRINT_LITERAL, print::PRINT_WITH_NEWLINE, print::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, @@ -665,7 +665,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_style", vec![ assign_ops::ASSIGN_OP_PATTERN, - attrs::EMPTY_LINE_AFTER_OUTER_ATTR, bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, @@ -725,6 +724,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic::PANIC_PARAMS, + print::PRINT_LITERAL, print::PRINT_WITH_NEWLINE, print::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, @@ -870,6 +870,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ]); reg.register_lint_group("clippy_nursery", vec![ + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, ranges::RANGE_PLUS_ONE, -- cgit 1.4.1-3-g733a5 From ab281184497fcf79508e6c19c4214f8ebada20cb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 4 Apr 2018 18:56:21 -0700 Subject: Fix driver dogfood bug --- src/driver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index 73746798601..711b2e6fbd9 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -126,7 +126,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { #[allow(print_stdout)] fn show_version() { - println!("{}", env!("CARGO_PKG_VERSION")); + println!(env!("CARGO_PKG_VERSION"); } pub fn main() { -- cgit 1.4.1-3-g733a5 From d9508ba99d282d2be14842f5f88f47a54067f006 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Thu, 5 Apr 2018 04:13:14 +0200 Subject: typo --- tests/ui/collapsible_if.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 3c5c38525fe..de22352e311 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -41,7 +41,7 @@ fn main() { } } - // Collaspe `else { if .. }` to `else if ..` + // Collapse `else { if .. }` to `else if ..` if x == "hello" { print!("Hello "); } else { -- cgit 1.4.1-3-g733a5 From 399488079b1930c7cb9a779230d6e87e07f686da Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 4 Apr 2018 19:15:21 -0700 Subject: argh --- src/driver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index 711b2e6fbd9..4e3852d416a 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -126,7 +126,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { #[allow(print_stdout)] fn show_version() { - println!(env!("CARGO_PKG_VERSION"); + println!(env!("CARGO_PKG_VERSION")); } pub fn main() { -- cgit 1.4.1-3-g733a5 From ff98e3f9f50ca14e2fe96da0b36f6ac05476970a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 5 Apr 2018 07:52:26 +0200 Subject: Fix useless_format false positive with macros Clippy was issuing a warning when `format!` was used inside a macro. That's a problem because macros have different syntax and can be outside the control of the user. This skips the `useless_format` check if the `format!` call is inside a macro. --- clippy_lints/src/format.rs | 5 ++++- tests/ui/format.rs | 9 +++++++++ tests/ui/format.stderr | 12 ++++++------ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 7136eff3274..2b5b79db980 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; use utils::paths; -use utils::{is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; +use utils::{in_macro, is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -39,6 +39,9 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let Some(span) = is_expn_of(expr.span, "format") { + if in_macro(span) { + return; + } match expr.node { // `format!("{}", foo)` expansion ExprCall(ref fun, ref args) => { diff --git a/tests/ui/format.rs b/tests/ui/format.rs index e9379d0a05b..ac97bd24ea1 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -2,6 +2,12 @@ #![warn(useless_format)] +struct Foo(pub String); + +macro_rules! foo { + ($($t:tt)*) => (Foo(format!($($t)*))) +} + fn main() { format!("foo"); @@ -31,4 +37,7 @@ fn main() { println!("foo {}", "foo"); println!("{}", 42); println!("foo {}", 42); + + // A format! inside a macro should not trigger a warning + foo!("should not warn"); } diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index f08f0696e23..8c36d9a830c 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,10 +1,10 @@ error: useless use of `format!` - --> $DIR/format.rs:6:5 - | -6 | format!("foo"); - | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` - | - = note: `-D useless-format` implied by `-D warnings` + --> $DIR/format.rs:12:5 + | +12 | format!("foo"); + | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` + | + = note: `-D useless-format` implied by `-D warnings` error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 2fd671e4bd26e1c2ebef6fe3a0ce6194ffc14182 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 5 Apr 2018 17:59:35 +0200 Subject: Move ref cow tests This commit moves the ref cow tests from needless_borrow.rs to ptr_arg.rs where all the other PTR_ARG tests are. --- tests/ui/needless_borrow.rs | 9 --------- tests/ui/needless_borrow.stderr | 10 +--------- tests/ui/ptr_arg.rs | 12 ++++++++++-- tests/ui/ptr_arg.stderr | 8 +++++++- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 088d33b875f..99500cd0746 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -51,12 +51,3 @@ fn issue_1432() { let _ = v.iter().filter(|&a| a.is_empty()); } - -#[allow(dead_code)] -fn test_cow_with_ref(c: &Cow<[i32]>) { -} - -#[allow(dead_code)] -fn test_cow(c: Cow<[i32]>) { - let _c = c; -} diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index e319efa939c..fde38508b32 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -38,13 +38,5 @@ error: this pattern creates a reference to a reference 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` -error: using a reference to `Cow` is not recommended. - --> $DIR/needless_borrow.rs:56:25 - | -56 | fn test_cow_with_ref(c: &Cow<[i32]>) { - | ^^^^^^^^^^^ help: change this to: `&[i32]` - | - = note: `-D ptr-arg` implied by `-D warnings` - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 14b26e16847..ce572be7ad8 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,8 +1,8 @@ - - #![allow(unused, many_single_char_names)] #![warn(ptr_arg)] +use std::borrow::Cow; + fn do_vec(x: &Vec) { //Nothing here } @@ -67,3 +67,11 @@ fn false_positive_capacity_too(x: &String) -> String { x.clone() } +#[allow(dead_code)] +fn test_cow_with_ref(c: &Cow<[i32]>) { +} + +#[allow(dead_code)] +fn test_cow(c: Cow<[i32]>) { + let _c = c; +} diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index bf8608111cf..a29e393baa1 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -76,5 +76,11 @@ help: change `y.as_str()` to 62 | let c = y; | ^ -error: aborting due to 6 previous errors +error: using a reference to `Cow` is not recommended. + --> $DIR/ptr_arg.rs:71:25 + | +71 | fn test_cow_with_ref(c: &Cow<[i32]>) { + | ^^^^^^^^^^^ help: change this to: `&[i32]` + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 641f0685d075d9b4d719656805ca51465461aad1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 5 Apr 2018 21:18:38 +0200 Subject: Split up some single_match UI tests This moves only the single_match tests over to the new file. --- tests/ui/matches.rs | 66 ------- tests/ui/matches.stderr | 435 +++++++++++++++++++------------------------ tests/ui/single_match.rs | 71 +++++++ tests/ui/single_match.stderr | 49 +++++ 4 files changed, 314 insertions(+), 307 deletions(-) create mode 100644 tests/ui/single_match.rs create mode 100644 tests/ui/single_match.stderr diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 8b1ee1fdcd2..92e771e393c 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -6,11 +6,6 @@ #![allow(unused, if_let_redundant_pattern_matching)] #![warn(single_match_else, match_same_arms)] -use std::borrow::Cow; - -enum Foo { Bar, Baz(u8) } -use Foo::*; - enum ExprNode { ExprAddrOf, Butterflies, @@ -29,67 +24,6 @@ fn unwrap_addr() -> Option<&'static ExprNode> { } } -fn single_match(){ - let x = Some(1u8); - - match x { - Some(y) => { println!("{:?}", y); } - _ => () - }; - - let z = (1u8,1u8); - match z { - (2...3, 7...9) => dummy(), - _ => {} - }; - - // Not linted (pattern guards used) - match x { - Some(y) if y == 0 => println!("{:?}", y), - _ => () - } - - // Not linted (no block with statements in the single arm) - match z { - (2...3, 7...9) => println!("{:?}", z), - _ => println!("nope"), - } -} - -fn single_match_know_enum() { - let x = Some(1u8); - let y : Result<_, i8> = Ok(1i8); - - match x { - Some(y) => dummy(), - None => () - }; - - match y { - Ok(y) => dummy(), - Err(..) => () - }; - - let c = Cow::Borrowed(""); - - match c { - Cow::Borrowed(..) => dummy(), - Cow::Owned(..) => (), - }; - - let z = Foo::Bar; - // no warning - match z { - Bar => println!("42"), - Baz(_) => (), - } - - match z { - Baz(_) => println!("42"), - Bar => (), - } -} - fn match_bool() { let test: bool = true; diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index ab207eb32de..aedf7864624 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,473 +1,426 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:26:5 + --> $DIR/matches.rs:21:5 | -26 | / match ExprNode::Butterflies { -27 | | ExprNode::ExprAddrOf => Some(&NODE), -28 | | _ => { let x = 5; None }, -29 | | } +21 | / match ExprNode::Butterflies { +22 | | ExprNode::ExprAddrOf => Some(&NODE), +23 | | _ => { let x = 5; None }, +24 | | } | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` | = note: `-D single-match-else` implied by `-D warnings` -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:35:5 - | -35 | / match x { -36 | | Some(y) => { println!("{:?}", y); } -37 | | _ => () -38 | | }; - | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y); }` - | - = note: `-D single-match` implied by `-D warnings` - -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:41:5 - | -41 | / match z { -42 | | (2...3, 7...9) => dummy(), -43 | | _ => {} -44 | | }; - | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` - -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:63:5 - | -63 | / match x { -64 | | Some(y) => dummy(), -65 | | None => () -66 | | }; - | |_____^ help: try this: `if let Some(y) = x { dummy() }` - -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:68:5 +error: this boolean expression can be simplified + --> $DIR/matches.rs:51:11 | -68 | / match y { -69 | | Ok(y) => dummy(), -70 | | Err(..) => () -71 | | }; - | |_____^ help: try this: `if let Ok(y) = y { dummy() }` - -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:75:5 +51 | match test && test { + | ^^^^^^^^^^^^ help: try: `test` | -75 | / match c { -76 | | Cow::Borrowed(..) => dummy(), -77 | | Cow::Owned(..) => (), -78 | | }; - | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` - -error: this boolean expression can be simplified - --> $DIR/matches.rs:117:11 - | -117 | match test && test { - | ^^^^^^^^^^^^ help: try: `test` - | - = note: `-D nonminimal-bool` implied by `-D warnings` + = note: `-D nonminimal-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:96:5 + --> $DIR/matches.rs:30:5 | -96 | / match test { -97 | | true => 0, -98 | | false => 42, -99 | | }; +30 | / match test { +31 | | true => 0, +32 | | false => 42, +33 | | }; | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` | = note: `-D match-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:102:5 - | -102 | / match option == 1 { -103 | | true => 1, -104 | | false => 0, -105 | | }; - | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` + --> $DIR/matches.rs:36:5 + | +36 | / match option == 1 { +37 | | true => 1, +38 | | false => 0, +39 | | }; + | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:107:5 - | -107 | / match test { -108 | | true => (), -109 | | false => { println!("Noooo!"); } -110 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` + --> $DIR/matches.rs:41:5 + | +41 | / match test { +42 | | true => (), +43 | | false => { println!("Noooo!"); } +44 | | }; + | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:112:5 - | -112 | / match test { -113 | | false => { println!("Noooo!"); } -114 | | _ => (), -115 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` + --> $DIR/matches.rs:46:5 + | +46 | / match test { +47 | | false => { println!("Noooo!"); } +48 | | _ => (), +49 | | }; + | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:117:5 - | -117 | / match test && test { -118 | | false => { println!("Noooo!"); } -119 | | _ => (), -120 | | }; - | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` + --> $DIR/matches.rs:51:5 + | +51 | / match test && test { +52 | | false => { println!("Noooo!"); } +53 | | _ => (), +54 | | }; + | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` error: equal expressions as operands to `&&` - --> $DIR/matches.rs:117:11 - | -117 | match test && test { - | ^^^^^^^^^^^^ - | - = note: `-D eq-op` implied by `-D warnings` + --> $DIR/matches.rs:51:11 + | +51 | match test && test { + | ^^^^^^^^^^^^ + | + = note: `-D eq-op` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:122:5 - | -122 | / match test { -123 | | false => { println!("Noooo!"); } -124 | | true => { println!("Yes!"); } -125 | | }; - | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` + --> $DIR/matches.rs:56:5 + | +56 | / match test { +57 | | false => { println!("Noooo!"); } +58 | | true => { println!("Yes!"); } +59 | | }; + | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:138:9 - | -138 | / match v { -139 | | &Some(v) => println!("{:?}", v), -140 | | &None => println!("none"), -141 | | } - | |_________^ - | - = note: `-D match-ref-pats` implied by `-D warnings` + --> $DIR/matches.rs:72:9 + | +72 | / match v { +73 | | &Some(v) => println!("{:?}", v), +74 | | &None => println!("none"), +75 | | } + | |_________^ + | + = note: `-D match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression - | -138 | match *v { -139 | Some(v) => println!("{:?}", v), -140 | None => println!("none"), - | + | +72 | match *v { +73 | Some(v) => println!("{:?}", v), +74 | None => println!("none"), + | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:148:5 - | -148 | / match tup { -149 | | &(v, 1) => println!("{}", v), -150 | | _ => println!("none"), -151 | | } - | |_____^ + --> $DIR/matches.rs:82:5 + | +82 | / match tup { +83 | | &(v, 1) => println!("{}", v), +84 | | _ => println!("none"), +85 | | } + | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression - | -148 | match *tup { -149 | (v, 1) => println!("{}", v), - | + | +82 | match *tup { +83 | (v, 1) => println!("{}", v), + | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:154:5 - | -154 | / match &w { -155 | | &Some(v) => println!("{:?}", v), -156 | | &None => println!("none"), -157 | | } - | |_____^ + --> $DIR/matches.rs:88:5 + | +88 | / match &w { +89 | | &Some(v) => println!("{:?}", v), +90 | | &None => println!("none"), +91 | | } + | |_____^ help: try - | -154 | match w { -155 | Some(v) => println!("{:?}", v), -156 | None => println!("none"), - | + | +88 | match w { +89 | Some(v) => println!("{:?}", v), +90 | None => println!("none"), + | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:165:5 + --> $DIR/matches.rs:99:5 | -165 | / if let &None = a { -166 | | println!("none"); -167 | | } +99 | / if let &None = a { +100 | | println!("none"); +101 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -165 | if let None = *a { +99 | if let None = *a { | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:170:5 + --> $DIR/matches.rs:104:5 | -170 | / if let &None = &b { -171 | | println!("none"); -172 | | } +104 | / if let &None = &b { +105 | | println!("none"); +106 | | } | |_____^ help: try | -170 | if let None = b { +104 | if let None = b { | error: some ranges overlap - --> $DIR/matches.rs:179:9 + --> $DIR/matches.rs:113:9 | -179 | 0 ... 10 => println!("0 ... 10"), +113 | 0 ... 10 => println!("0 ... 10"), | ^^^^^^^^ | = note: `-D match-overlapping-arm` implied by `-D warnings` note: overlaps with this - --> $DIR/matches.rs:180:9 + --> $DIR/matches.rs:114:9 | -180 | 0 ... 11 => println!("0 ... 11"), +114 | 0 ... 11 => println!("0 ... 11"), | ^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:185:9 + --> $DIR/matches.rs:119:9 | -185 | 0 ... 5 => println!("0 ... 5"), +119 | 0 ... 5 => println!("0 ... 5"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:187:9 + --> $DIR/matches.rs:121:9 | -187 | FOO ... 11 => println!("0 ... 11"), +121 | FOO ... 11 => println!("0 ... 11"), | ^^^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:193:9 + --> $DIR/matches.rs:127:9 | -193 | 0 ... 5 => println!("0 ... 5"), +127 | 0 ... 5 => println!("0 ... 5"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:192:9 + --> $DIR/matches.rs:126:9 | -192 | 2 => println!("2"), +126 | 2 => println!("2"), | ^ error: some ranges overlap - --> $DIR/matches.rs:199:9 + --> $DIR/matches.rs:133:9 | -199 | 0 ... 2 => println!("0 ... 2"), +133 | 0 ... 2 => println!("0 ... 2"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:198:9 + --> $DIR/matches.rs:132:9 | -198 | 2 => println!("2"), +132 | 2 => println!("2"), | ^ error: some ranges overlap - --> $DIR/matches.rs:222:9 + --> $DIR/matches.rs:156:9 | -222 | 0 .. 11 => println!("0 .. 11"), +156 | 0 .. 11 => println!("0 .. 11"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:223:9 + --> $DIR/matches.rs:157:9 | -223 | 0 ... 11 => println!("0 ... 11"), +157 | 0 ... 11 => println!("0 ... 11"), | ^^^^^^^^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:240:9 + --> $DIR/matches.rs:174:9 | -240 | Err(_) => panic!("err") +174 | Err(_) => panic!("err") | ^^^^^^ | = note: `-D match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:239:18 + --> $DIR/matches.rs:173:18 | -239 | Ok(_) => println!("ok"), +173 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:238:18 + --> $DIR/matches.rs:172:18 | -238 | Ok(3) => println!("ok"), +172 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:238:18 + --> $DIR/matches.rs:172:18 | -238 | Ok(3) => println!("ok"), +172 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:246:9 + --> $DIR/matches.rs:180:9 | -246 | Err(_) => {panic!()} +180 | Err(_) => {panic!()} | ^^^^^^ | = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:245:18 + --> $DIR/matches.rs:179:18 | -245 | Ok(_) => println!("ok"), +179 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:244:18 + --> $DIR/matches.rs:178:18 | -244 | Ok(3) => println!("ok"), +178 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:244:18 + --> $DIR/matches.rs:178:18 | -244 | Ok(3) => println!("ok"), +178 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:252:9 + --> $DIR/matches.rs:186:9 | -252 | Err(_) => {panic!();} +186 | Err(_) => {panic!();} | ^^^^^^ | = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:251:18 + --> $DIR/matches.rs:185:18 | -251 | Ok(_) => println!("ok"), +185 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:250:18 + --> $DIR/matches.rs:184:18 | -250 | Ok(3) => println!("ok"), +184 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:250:18 + --> $DIR/matches.rs:184:18 | -250 | Ok(3) => println!("ok"), +184 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:258:18 + --> $DIR/matches.rs:192:18 | -258 | Ok(_) => println!("ok"), +192 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:257:18 + --> $DIR/matches.rs:191:18 | -257 | Ok(3) => println!("ok"), +191 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:257:18 + --> $DIR/matches.rs:191:18 | -257 | Ok(3) => println!("ok"), +191 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:265:18 + --> $DIR/matches.rs:199:18 | -265 | Ok(_) => println!("ok"), +199 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:264:18 + --> $DIR/matches.rs:198:18 | -264 | Ok(3) => println!("ok"), +198 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:264:18 + --> $DIR/matches.rs:198:18 | -264 | Ok(3) => println!("ok"), +198 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:271:18 + --> $DIR/matches.rs:205:18 | -271 | Ok(_) => println!("ok"), +205 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:270:18 + --> $DIR/matches.rs:204:18 | -270 | Ok(3) => println!("ok"), +204 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:270:18 + --> $DIR/matches.rs:204:18 | -270 | Ok(3) => println!("ok"), +204 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:277:18 + --> $DIR/matches.rs:211:18 | -277 | Ok(_) => println!("ok"), +211 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:276:18 + --> $DIR/matches.rs:210:18 | -276 | Ok(3) => println!("ok"), +210 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:276:18 + --> $DIR/matches.rs:210:18 | -276 | Ok(3) => println!("ok"), +210 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:298:29 + --> $DIR/matches.rs:232:29 | -298 | (Ok(_), Some(x)) => println!("ok {}", x), +232 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:297:29 + --> $DIR/matches.rs:231:29 | -297 | (Ok(x), Some(_)) => println!("ok {}", x), +231 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:297:29 + --> $DIR/matches.rs:231:29 | -297 | (Ok(x), Some(_)) => println!("ok {}", x), +231 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:313:18 + --> $DIR/matches.rs:247:18 | -313 | Ok(_) => println!("ok"), +247 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:312:18 + --> $DIR/matches.rs:246:18 | -312 | Ok(3) => println!("ok"), +246 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:312:18 + --> $DIR/matches.rs:246:18 | -312 | Ok(3) => println!("ok"), +246 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:320:33 + --> $DIR/matches.rs:254:33 | -320 | let borrowed: Option<&()> = match owned { +254 | let borrowed: Option<&()> = match owned { | _________________________________^ -321 | | None => None, -322 | | Some(ref v) => Some(v), -323 | | }; +255 | | None => None, +256 | | Some(ref v) => Some(v), +257 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:326:39 + --> $DIR/matches.rs:260:39 | -326 | let borrow_mut: Option<&mut ()> = match mut_owned { +260 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -327 | | None => None, -328 | | Some(ref mut v) => Some(v), -329 | | }; +261 | | None => None, +262 | | Some(ref mut v) => Some(v), +263 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 38 previous errors +error: aborting due to 33 previous errors diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs new file mode 100644 index 00000000000..b064eed5711 --- /dev/null +++ b/tests/ui/single_match.rs @@ -0,0 +1,71 @@ +#![warn(single_match)] + +fn dummy() { +} + +fn single_match(){ + let x = Some(1u8); + + match x { + Some(y) => { println!("{:?}", y); } + _ => () + }; + + let z = (1u8,1u8); + match z { + (2...3, 7...9) => dummy(), + _ => {} + }; + + // Not linted (pattern guards used) + match x { + Some(y) if y == 0 => println!("{:?}", y), + _ => () + } + + // Not linted (no block with statements in the single arm) + match z { + (2...3, 7...9) => println!("{:?}", z), + _ => println!("nope"), + } +} + +enum Foo { Bar, Baz(u8) } +use Foo::*; +use std::borrow::Cow; + +fn single_match_know_enum() { + let x = Some(1u8); + let y : Result<_, i8> = Ok(1i8); + + match x { + Some(y) => dummy(), + None => () + }; + + match y { + Ok(y) => dummy(), + Err(..) => () + }; + + let c = Cow::Borrowed(""); + + match c { + Cow::Borrowed(..) => dummy(), + Cow::Owned(..) => (), + }; + + let z = Foo::Bar; + // no warning + match z { + Bar => println!("42"), + Baz(_) => (), + } + + match z { + Baz(_) => println!("42"), + Bar => (), + } +} + +fn main() { } diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr new file mode 100644 index 00000000000..d77211bc126 --- /dev/null +++ b/tests/ui/single_match.stderr @@ -0,0 +1,49 @@ +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:9:5 + | +9 | / match x { +10 | | Some(y) => { println!("{:?}", y); } +11 | | _ => () +12 | | }; + | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y); }` + | + = note: `-D single-match` implied by `-D warnings` + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:15:5 + | +15 | / match z { +16 | | (2...3, 7...9) => dummy(), +17 | | _ => {} +18 | | }; + | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:41:5 + | +41 | / match x { +42 | | Some(y) => dummy(), +43 | | None => () +44 | | }; + | |_____^ help: try this: `if let Some(y) = x { dummy() }` + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:46:5 + | +46 | / match y { +47 | | Ok(y) => dummy(), +48 | | Err(..) => () +49 | | }; + | |_____^ help: try this: `if let Ok(y) = y { dummy() }` + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:53:5 + | +53 | / match c { +54 | | Cow::Borrowed(..) => dummy(), +55 | | Cow::Owned(..) => (), +56 | | }; + | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` + +error: aborting due to 5 previous errors + -- cgit 1.4.1-3-g733a5 From fe8068c41b4f35e57bda1c5aec092dce4ea2071c Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 7 Apr 2018 07:22:23 +0200 Subject: Fix compilation for nightly 2018-04-06 Breakages for introduced by rust pull request 'AST: Give spans to all identifies' - rust-lang/rust/pull#49154 Closes #2639 --- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/misc_early.rs | 12 ++++++------ clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/returns.rs | 6 +++--- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 553a98f682d..c822c59deeb 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { if_chain! { if let NestedMetaItemKind::MetaItem(ref mi) = item.node; if let MetaItemKind::NameValue(ref lit) = mi.node; - if mi.name() == "since"; + if mi.ident.name == "since"; then { check_semver(cx, item.span, lit); } @@ -328,7 +328,7 @@ fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { if let NestedMetaItemKind::MetaItem(ref mi) = nmi.node { - mi.is_word() && mi.name() == expected + mi.is_word() && mi.ident.name == expected } else { false } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 38fcf514626..2ff7fa9e3ab 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -56,7 +56,7 @@ impl StaticConst { span_lint_and_then( cx, CONST_STATIC_LIFETIME, - lifetime.span, + lifetime.ident.span, "Constants have by default a `'static` lifetime", |db| { db.span_suggestion(ty.span, "consider removing `'static`", sugg); diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c2e246a71fa..e769c2acc4b 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -119,7 +119,7 @@ impl LintPass for EnumVariantNames { } fn var2str(var: &Variant) -> InternedString { - var.node.name.name.as_str() + var.node.ident.name.as_str() } /// Returns the number of chars that match from the start diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 3f3ba6487de..9ff7bbe4aba 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -195,7 +195,7 @@ impl EarlyLintPass for MiscEarly { span_lint( cx, BUILTIN_TYPE_SHADOW, - ty.span, + ty.ident.span, &format!("This generic shadows the built-in type `{}`", name), ); } @@ -209,7 +209,7 @@ impl EarlyLintPass for MiscEarly { let type_name = npat.segments .last() .expect("A path must have at least one segment") - .identifier + .ident .name; for field in pfields { @@ -267,8 +267,8 @@ impl EarlyLintPass for MiscEarly { let mut registered_names: HashMap = HashMap::new(); for arg in &decl.inputs { - if let PatKind::Ident(_, sp_ident, None) = arg.pat.node { - let arg_name = sp_ident.node.to_string(); + if let PatKind::Ident(_, ident, None) = arg.pat.node { + let arg_name = ident.name.to_string(); if arg_name.starts_with('_') { if let Some(correspondence) = registered_names.get(&arg_name[1..]) { @@ -328,13 +328,13 @@ impl EarlyLintPass for MiscEarly { if let StmtKind::Local(ref local) = w[0].node; if let Option::Some(ref t) = local.init; if let ExprKind::Closure(_, _, _, _, _) = t.node; - if let PatKind::Ident(_, sp_ident, _) = local.pat.node; + if let PatKind::Ident(_, ident, _) = local.pat.node; if let StmtKind::Semi(ref second) = w[1].node; if let ExprKind::Assign(_, ref call) = second.node; if let ExprKind::Call(ref closure, _) = call.node; if let ExprKind::Path(_, ref path) = closure.node; then { - if sp_ident.node == (&path.segments[0]).identifier { + if ident == (&path.segments[0]).ident { span_lint( cx, REDUNDANT_CLOSURE_CALL, diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 057ed157382..394bc4bcfbc 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -104,7 +104,7 @@ struct SimilarNamesNameVisitor<'a: 'b, 'tcx: 'a, 'b>(&'b mut SimilarNamesLocalVi impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.node { - PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), + PatKind::Ident(_, ident, _) => self.check_name(ident.span, ident.name), PatKind::Struct(_, ref fields, _) => for field in fields { if !field.node.is_shorthand { self.visit_pat(&field.node.pat); diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 62038262de4..5e5e93783d3 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::ast; -use syntax::codemap::{Span, Spanned}; +use syntax::codemap::Span; use syntax::visit::FnKind; use utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; @@ -112,9 +112,9 @@ impl ReturnPass { if local.ty.is_none(); if !local.attrs.iter().any(attr_is_cfg); if let Some(ref initexpr) = local.init; - if let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node; + if let ast::PatKind::Ident(_, ident, _) = local.pat.node; if let ast::ExprKind::Path(_, ref path) = retexpr.node; - if match_path_ast(path, &[&id.name.as_str()]); + if match_path_ast(path, &[&ident.name.as_str()]); if !in_external_macro(cx, initexpr.span); then { span_note_and_lint(cx, diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index f852784545c..8ecc95fb72c 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -49,7 +49,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { .segments .last() .expect("use paths cannot be empty") - .identifier; + .ident; unsafe_to_safe_check(old_name, new_name, cx, span); } UseTreeKind::Simple(None) | diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 9d708d637c3..7aeaa710443 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -471,7 +471,7 @@ fn has_attr(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { attr.check_name("clippy") && attr.meta_item_list().map_or(false, |list| { list.len() == 1 && match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", + ast::NestedMetaItemKind::MetaItem(ref it) => it.ident.name == "author", ast::NestedMetaItemKind::Literal(_) => false, } }) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 58e71705011..607082e8ad2 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -13,7 +13,7 @@ pub fn file_from_args( args: &[codemap::Spanned], ) -> Result, (&'static str, codemap::Span)> { for arg in args.iter().filter_map(|a| a.meta_item()) { - if arg.name() == "conf_file" { + if arg.ident.name == "conf_file" { return match arg.node { ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { Err(("`conf_file` must be a named value", arg.span)) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index f71de382cad..bfb6160d3cd 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -237,7 +237,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { .iter() .rev() .zip(segments.iter().rev()) - .all(|(a, b)| a.identifier.name == *b) + .all(|(a, b)| a.ident.name == *b) } /// Get the definition associated to a path. -- cgit 1.4.1-3-g733a5 From 4b3326efd06818f9d0e1dcf5c247a588ded7c8f6 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Fri, 6 Apr 2018 22:44:25 -0700 Subject: Fix docs to match behavior --- clippy_lints/src/derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index b505e52c95b..0c544c69d09 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -6,7 +6,7 @@ use utils::paths; use utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` -/// explicitly. +/// explicitly or vice versa. /// /// **Why is this bad?** The implementation of these traits must agree (for /// example for use with `HashMap`) so it’s probably a bad idea to use a -- cgit 1.4.1-3-g733a5 From 5abe34832d80feca118b09aac3077200c3092763 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 7 Apr 2018 10:23:27 +0200 Subject: Split up match_bool UI tests --- tests/ui/match_bool.rs | 44 ++++++ tests/ui/match_bool.stderr | 74 +++++++++ tests/ui/matches.rs | 42 ----- tests/ui/matches.stderr | 378 ++++++++++++++++++--------------------------- 4 files changed, 271 insertions(+), 267 deletions(-) create mode 100644 tests/ui/match_bool.rs create mode 100644 tests/ui/match_bool.stderr diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs new file mode 100644 index 00000000000..07efe2c6808 --- /dev/null +++ b/tests/ui/match_bool.rs @@ -0,0 +1,44 @@ +fn match_bool() { + let test: bool = true; + + match test { + true => 0, + false => 42, + }; + + let option = 1; + match option == 1 { + true => 1, + false => 0, + }; + + match test { + true => (), + false => { println!("Noooo!"); } + }; + + match test { + false => { println!("Noooo!"); } + _ => (), + }; + + match test && test { + false => { println!("Noooo!"); } + _ => (), + }; + + match test { + false => { println!("Noooo!"); } + true => { println!("Yes!"); } + }; + + // Not linted + match option { + 1 ... 10 => 1, + 11 ... 20 => 2, + _ => 3, + }; +} + +fn main() { +} diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr new file mode 100644 index 00000000000..89378f438b0 --- /dev/null +++ b/tests/ui/match_bool.stderr @@ -0,0 +1,74 @@ +error: this boolean expression can be simplified + --> $DIR/match_bool.rs:25:11 + | +25 | match test && test { + | ^^^^^^^^^^^^ help: try: `test` + | + = note: `-D nonminimal-bool` implied by `-D warnings` + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:4:5 + | +4 | / match test { +5 | | true => 0, +6 | | false => 42, +7 | | }; + | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` + | + = note: `-D match-bool` implied by `-D warnings` + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:10:5 + | +10 | / match option == 1 { +11 | | true => 1, +12 | | false => 0, +13 | | }; + | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:15:5 + | +15 | / match test { +16 | | true => (), +17 | | false => { println!("Noooo!"); } +18 | | }; + | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:20:5 + | +20 | / match test { +21 | | false => { println!("Noooo!"); } +22 | | _ => (), +23 | | }; + | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:25:5 + | +25 | / match test && test { +26 | | false => { println!("Noooo!"); } +27 | | _ => (), +28 | | }; + | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` + +error: equal expressions as operands to `&&` + --> $DIR/match_bool.rs:25:11 + | +25 | match test && test { + | ^^^^^^^^^^^^ + | + = note: #[deny(eq_op)] on by default + +error: you seem to be trying to match on a boolean expression + --> $DIR/match_bool.rs:30:5 + | +30 | / match test { +31 | | false => { println!("Noooo!"); } +32 | | true => { println!("Yes!"); } +33 | | }; + | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 92e771e393c..e339aeb9c6a 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -24,48 +24,6 @@ fn unwrap_addr() -> Option<&'static ExprNode> { } } -fn match_bool() { - let test: bool = true; - - match test { - true => 0, - false => 42, - }; - - let option = 1; - match option == 1 { - true => 1, - false => 0, - }; - - match test { - true => (), - false => { println!("Noooo!"); } - }; - - match test { - false => { println!("Noooo!"); } - _ => (), - }; - - match test && test { - false => { println!("Noooo!"); } - _ => (), - }; - - match test { - false => { println!("Noooo!"); } - true => { println!("Yes!"); } - }; - - // Not linted - match option { - 1 ... 10 => 1, - 11 ... 20 => 2, - _ => 3, - }; -} - fn ref_pats() { { let v = &Some(0); diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index aedf7864624..cc43cdb25fc 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -9,418 +9,346 @@ error: you seem to be trying to use match for destructuring a single pattern. Co | = note: `-D single-match-else` implied by `-D warnings` -error: this boolean expression can be simplified - --> $DIR/matches.rs:51:11 - | -51 | match test && test { - | ^^^^^^^^^^^^ help: try: `test` - | - = note: `-D nonminimal-bool` implied by `-D warnings` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:30:5 - | -30 | / match test { -31 | | true => 0, -32 | | false => 42, -33 | | }; - | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` - | - = note: `-D match-bool` implied by `-D warnings` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:36:5 - | -36 | / match option == 1 { -37 | | true => 1, -38 | | false => 0, -39 | | }; - | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:41:5 - | -41 | / match test { -42 | | true => (), -43 | | false => { println!("Noooo!"); } -44 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:46:5 - | -46 | / match test { -47 | | false => { println!("Noooo!"); } -48 | | _ => (), -49 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:51:5 - | -51 | / match test && test { -52 | | false => { println!("Noooo!"); } -53 | | _ => (), -54 | | }; - | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` - -error: equal expressions as operands to `&&` - --> $DIR/matches.rs:51:11 - | -51 | match test && test { - | ^^^^^^^^^^^^ - | - = note: `-D eq-op` implied by `-D warnings` - -error: you seem to be trying to match on a boolean expression - --> $DIR/matches.rs:56:5 - | -56 | / match test { -57 | | false => { println!("Noooo!"); } -58 | | true => { println!("Yes!"); } -59 | | }; - | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` - error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:72:9 + --> $DIR/matches.rs:30:9 | -72 | / match v { -73 | | &Some(v) => println!("{:?}", v), -74 | | &None => println!("none"), -75 | | } +30 | / match v { +31 | | &Some(v) => println!("{:?}", v), +32 | | &None => println!("none"), +33 | | } | |_________^ | = note: `-D match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -72 | match *v { -73 | Some(v) => println!("{:?}", v), -74 | None => println!("none"), +30 | match *v { +31 | Some(v) => println!("{:?}", v), +32 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:82:5 + --> $DIR/matches.rs:40:5 | -82 | / match tup { -83 | | &(v, 1) => println!("{}", v), -84 | | _ => println!("none"), -85 | | } +40 | / match tup { +41 | | &(v, 1) => println!("{}", v), +42 | | _ => println!("none"), +43 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -82 | match *tup { -83 | (v, 1) => println!("{}", v), +40 | match *tup { +41 | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:88:5 + --> $DIR/matches.rs:46:5 | -88 | / match &w { -89 | | &Some(v) => println!("{:?}", v), -90 | | &None => println!("none"), -91 | | } +46 | / match &w { +47 | | &Some(v) => println!("{:?}", v), +48 | | &None => println!("none"), +49 | | } | |_____^ help: try | -88 | match w { -89 | Some(v) => println!("{:?}", v), -90 | None => println!("none"), +46 | match w { +47 | Some(v) => println!("{:?}", v), +48 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:99:5 - | -99 | / if let &None = a { -100 | | println!("none"); -101 | | } - | |_____^ + --> $DIR/matches.rs:57:5 + | +57 | / if let &None = a { +58 | | println!("none"); +59 | | } + | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression - | -99 | if let None = *a { - | + | +57 | if let None = *a { + | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:104:5 - | -104 | / if let &None = &b { -105 | | println!("none"); -106 | | } - | |_____^ + --> $DIR/matches.rs:62:5 + | +62 | / if let &None = &b { +63 | | println!("none"); +64 | | } + | |_____^ help: try - | -104 | if let None = b { - | + | +62 | if let None = b { + | error: some ranges overlap - --> $DIR/matches.rs:113:9 - | -113 | 0 ... 10 => println!("0 ... 10"), - | ^^^^^^^^ - | - = note: `-D match-overlapping-arm` implied by `-D warnings` + --> $DIR/matches.rs:71:9 + | +71 | 0 ... 10 => println!("0 ... 10"), + | ^^^^^^^^ + | + = note: `-D match-overlapping-arm` implied by `-D warnings` note: overlaps with this - --> $DIR/matches.rs:114:9 - | -114 | 0 ... 11 => println!("0 ... 11"), - | ^^^^^^^^ + --> $DIR/matches.rs:72:9 + | +72 | 0 ... 11 => println!("0 ... 11"), + | ^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:119:9 - | -119 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ - | + --> $DIR/matches.rs:77:9 + | +77 | 0 ... 5 => println!("0 ... 5"), + | ^^^^^^^ + | note: overlaps with this - --> $DIR/matches.rs:121:9 - | -121 | FOO ... 11 => println!("0 ... 11"), - | ^^^^^^^^^^ + --> $DIR/matches.rs:79:9 + | +79 | FOO ... 11 => println!("0 ... 11"), + | ^^^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:127:9 - | -127 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ - | + --> $DIR/matches.rs:85:9 + | +85 | 0 ... 5 => println!("0 ... 5"), + | ^^^^^^^ + | note: overlaps with this - --> $DIR/matches.rs:126:9 - | -126 | 2 => println!("2"), - | ^ + --> $DIR/matches.rs:84:9 + | +84 | 2 => println!("2"), + | ^ error: some ranges overlap - --> $DIR/matches.rs:133:9 - | -133 | 0 ... 2 => println!("0 ... 2"), - | ^^^^^^^ - | + --> $DIR/matches.rs:91:9 + | +91 | 0 ... 2 => println!("0 ... 2"), + | ^^^^^^^ + | note: overlaps with this - --> $DIR/matches.rs:132:9 - | -132 | 2 => println!("2"), - | ^ + --> $DIR/matches.rs:90:9 + | +90 | 2 => println!("2"), + | ^ error: some ranges overlap - --> $DIR/matches.rs:156:9 + --> $DIR/matches.rs:114:9 | -156 | 0 .. 11 => println!("0 .. 11"), +114 | 0 .. 11 => println!("0 .. 11"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:157:9 + --> $DIR/matches.rs:115:9 | -157 | 0 ... 11 => println!("0 ... 11"), +115 | 0 ... 11 => println!("0 ... 11"), | ^^^^^^^^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:174:9 + --> $DIR/matches.rs:132:9 | -174 | Err(_) => panic!("err") +132 | Err(_) => panic!("err") | ^^^^^^ | = note: `-D match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:173:18 + --> $DIR/matches.rs:131:18 | -173 | Ok(_) => println!("ok"), +131 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:172:18 + --> $DIR/matches.rs:130:18 | -172 | Ok(3) => println!("ok"), +130 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:172:18 + --> $DIR/matches.rs:130:18 | -172 | Ok(3) => println!("ok"), +130 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:180:9 + --> $DIR/matches.rs:138:9 | -180 | Err(_) => {panic!()} +138 | Err(_) => {panic!()} | ^^^^^^ | = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:179:18 + --> $DIR/matches.rs:137:18 | -179 | Ok(_) => println!("ok"), +137 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:178:18 + --> $DIR/matches.rs:136:18 | -178 | Ok(3) => println!("ok"), +136 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:178:18 + --> $DIR/matches.rs:136:18 | -178 | Ok(3) => println!("ok"), +136 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:186:9 + --> $DIR/matches.rs:144:9 | -186 | Err(_) => {panic!();} +144 | Err(_) => {panic!();} | ^^^^^^ | = note: to remove this warning, match each error seperately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:185:18 + --> $DIR/matches.rs:143:18 | -185 | Ok(_) => println!("ok"), +143 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:184:18 + --> $DIR/matches.rs:142:18 | -184 | Ok(3) => println!("ok"), +142 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:184:18 + --> $DIR/matches.rs:142:18 | -184 | Ok(3) => println!("ok"), +142 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:192:18 + --> $DIR/matches.rs:150:18 | -192 | Ok(_) => println!("ok"), +150 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:191:18 + --> $DIR/matches.rs:149:18 | -191 | Ok(3) => println!("ok"), +149 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:191:18 + --> $DIR/matches.rs:149:18 | -191 | Ok(3) => println!("ok"), +149 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:199:18 + --> $DIR/matches.rs:157:18 | -199 | Ok(_) => println!("ok"), +157 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:198:18 + --> $DIR/matches.rs:156:18 | -198 | Ok(3) => println!("ok"), +156 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:198:18 + --> $DIR/matches.rs:156:18 | -198 | Ok(3) => println!("ok"), +156 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:205:18 + --> $DIR/matches.rs:163:18 | -205 | Ok(_) => println!("ok"), +163 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:204:18 + --> $DIR/matches.rs:162:18 | -204 | Ok(3) => println!("ok"), +162 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:204:18 + --> $DIR/matches.rs:162:18 | -204 | Ok(3) => println!("ok"), +162 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:211:18 + --> $DIR/matches.rs:169:18 | -211 | Ok(_) => println!("ok"), +169 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:210:18 + --> $DIR/matches.rs:168:18 | -210 | Ok(3) => println!("ok"), +168 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:210:18 + --> $DIR/matches.rs:168:18 | -210 | Ok(3) => println!("ok"), +168 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:232:29 + --> $DIR/matches.rs:190:29 | -232 | (Ok(_), Some(x)) => println!("ok {}", x), +190 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:231:29 + --> $DIR/matches.rs:189:29 | -231 | (Ok(x), Some(_)) => println!("ok {}", x), +189 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:231:29 + --> $DIR/matches.rs:189:29 | -231 | (Ok(x), Some(_)) => println!("ok {}", x), +189 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:247:18 + --> $DIR/matches.rs:205:18 | -247 | Ok(_) => println!("ok"), +205 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:246:18 + --> $DIR/matches.rs:204:18 | -246 | Ok(3) => println!("ok"), +204 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:246:18 + --> $DIR/matches.rs:204:18 | -246 | Ok(3) => println!("ok"), +204 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:254:33 + --> $DIR/matches.rs:212:33 | -254 | let borrowed: Option<&()> = match owned { +212 | let borrowed: Option<&()> = match owned { | _________________________________^ -255 | | None => None, -256 | | Some(ref v) => Some(v), -257 | | }; +213 | | None => None, +214 | | Some(ref v) => Some(v), +215 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:260:39 + --> $DIR/matches.rs:218:39 | -260 | let borrow_mut: Option<&mut ()> = match mut_owned { +218 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -261 | | None => None, -262 | | Some(ref mut v) => Some(v), -263 | | }; +219 | | None => None, +220 | | Some(ref mut v) => Some(v), +221 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 33 previous errors +error: aborting due to 25 previous errors -- cgit 1.4.1-3-g733a5 From 90e7d93d6cb333fea13383aa34d93b4fde7fbffc Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 7 Apr 2018 12:52:18 +0200 Subject: Fix nonminimal_bool false positive It was checking any is_ok, is_err, is_some, is_none method for negation but it should only perform the check for the built-in types, not custom types. --- clippy_lints/src/booleans.rs | 7 +++++- tests/ui/booleans.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ tests/ui/booleans.stderr | 26 +++++++++++++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 0fa2c2ac96f..c8478c47a35 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; use syntax::util::ThinVec; -use utils::{in_macro, snippet_opt, span_lint_and_then, SpanlessEq}; +use utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -185,6 +185,11 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { + let type_of_receiver = self.cx.tables.expr_ty(&args[0]); + if !match_type(self.cx, type_of_receiver, &paths::OPTION) && + !match_type(self.cx, type_of_receiver, &paths::RESULT) { + return None; + } METHODS_WITH_NEGATION .iter().cloned() .flat_map(|(a, b)| vec![(a, b), (b, a)]) diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 0898de105af..78e876e5182 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -57,3 +57,60 @@ fn methods_with_negation() { let _ = (!c ^ c) || !a.is_some(); let _ = !c ^ c || !a.is_some(); } + +// Simplified versions of https://github.com/rust-lang-nursery/rust-clippy/issues/2638 +// nonminimal_bool should only check the built-in Result and Some type, not +// any other types like the following. +enum CustomResultOk { Ok, Err(E) } +enum CustomResultErr { Ok, Err(E) } +enum CustomSomeSome { Some(T), None } +enum CustomSomeNone { Some(T), None } + +impl CustomResultOk { + pub fn is_ok(&self) -> bool { true } +} + +impl CustomResultErr { + pub fn is_err(&self) -> bool { true } +} + +impl CustomSomeSome { + pub fn is_some(&self) -> bool { true } +} + +impl CustomSomeNone { + pub fn is_none(&self) -> bool { true } +} + +fn dont_warn_for_custom_methods_with_negation() { + let res = CustomResultOk::Err("Error"); + // Should not warn and suggest 'is_err()' because the type does not + // implement is_err(). + if !res.is_ok() { } + + let res = CustomResultErr::Err("Error"); + // Should not warn and suggest 'is_ok()' because the type does not + // implement is_ok(). + if !res.is_err() { } + + let res = CustomSomeSome::Some("thing"); + // Should not warn and suggest 'is_none()' because the type does not + // implement is_none(). + if !res.is_some() { } + + let res = CustomSomeNone::Some("thing"); + // Should not warn and suggest 'is_some()' because the type does not + // implement is_some(). + if !res.is_none() { } +} + +// Only Built-in Result and Some types should suggest the negated alternative +fn warn_for_built_in_methods_with_negation() { + let res: Result = Ok(1); + if !res.is_ok() { } + if !res.is_err() { } + + let res = Some(1); + if !res.is_some() { } + if !res.is_none() { } +} diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index c88a7a7be60..f1996e8a26e 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -175,5 +175,29 @@ error: this boolean expression can be simplified 58 | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` -error: aborting due to 21 previous errors +error: this boolean expression can be simplified + --> $DIR/booleans.rs:110:8 + | +110 | if !res.is_ok() { } + | ^^^^^^^^^^^^ help: try: `res.is_err()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:111:8 + | +111 | if !res.is_err() { } + | ^^^^^^^^^^^^^ help: try: `res.is_ok()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:114:8 + | +114 | if !res.is_some() { } + | ^^^^^^^^^^^^^^ help: try: `res.is_none()` + +error: this boolean expression can be simplified + --> $DIR/booleans.rs:115:8 + | +115 | if !res.is_none() { } + | ^^^^^^^^^^^^^^ help: try: `res.is_some()` + +error: aborting due to 25 previous errors -- cgit 1.4.1-3-g733a5 From fad826f9661e321f74ce2d837103114271b132d1 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 7 Apr 2018 22:18:51 +0200 Subject: allow invalid UTF-8 in bytes Regexes --- clippy_lints/src/regex.rs | 5 +++- tests/ui/regex.rs | 1 + tests/ui/regex.stderr | 60 +++++++++++++++++++++++------------------------ 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 556ee72d995..26c1e2b244e 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -187,7 +187,10 @@ fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) } fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { - let mut parser = regex_syntax::ParserBuilder::new().unicode(utf8).build(); + let mut parser = regex_syntax::ParserBuilder::new() + .unicode(utf8) + .allow_invalid_utf8(!utf8) + .build(); if let ExprLit(ref lit) = expr.node { if let LitKind::Str(ref r, style) = lit.node { diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 37c98027fcc..b80aaa2df32 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -34,6 +34,7 @@ fn syntax_error() { let bset = BRegexSet::new(&[ r"[a-z]+@[a-z]+\.(com|org|net)", r"[a-z]+\.(com|org|net)", + r".", // regression test ]); let set_error = RegexSet::new(&[ diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 45b2b7a2280..39c360583e7 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -56,113 +56,113 @@ error: regex syntax error on position 0: unclosed group | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:40:9 + --> $DIR/regex.rs:41:9 | -40 | OPENING_PAREN, +41 | OPENING_PAREN, | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:44:9 + --> $DIR/regex.rs:45:9 | -44 | OPENING_PAREN, +45 | OPENING_PAREN, | ^^^^^^^^^^^^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:48:45 + --> $DIR/regex.rs:49:45 | -48 | let raw_string_error = Regex::new(r"[...//...]"); +49 | let raw_string_error = Regex::new(r"[...//...]"); | ^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:49:46 + --> $DIR/regex.rs:50:46 | -49 | let raw_string_error = Regex::new(r#"[...//...]"#); +50 | let raw_string_error = Regex::new(r#"[...//...]"#); | ^^ error: trivial regex - --> $DIR/regex.rs:53:33 + --> $DIR/regex.rs:54:33 | -53 | let trivial_eq = Regex::new("^foobar$"); +54 | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:55:48 + --> $DIR/regex.rs:56:48 | -55 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); +56 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:57:42 + --> $DIR/regex.rs:58:42 | -57 | let trivial_starts_with = Regex::new("^foobar"); +58 | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:59:40 + --> $DIR/regex.rs:60:40 | -59 | let trivial_ends_with = Regex::new("foobar$"); +60 | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:61:39 + --> $DIR/regex.rs:62:39 | -61 | let trivial_contains = Regex::new("foobar"); +62 | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:63:39 + --> $DIR/regex.rs:64:39 | -63 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); +64 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:65:40 + --> $DIR/regex.rs:66:40 | -65 | let trivial_backslash = Regex::new("a/.b"); +66 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:68:36 + --> $DIR/regex.rs:69:36 | -68 | let trivial_empty = Regex::new(""); +69 | let trivial_empty = Regex::new(""); | ^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:70:36 + --> $DIR/regex.rs:71:36 | -70 | let trivial_empty = Regex::new("^"); +71 | let trivial_empty = Regex::new("^"); | ^^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:72:36 + --> $DIR/regex.rs:73:36 | -72 | let trivial_empty = Regex::new("^$"); +73 | let trivial_empty = Regex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:74:44 + --> $DIR/regex.rs:75:44 | -74 | let binary_trivial_empty = BRegex::new("^$"); +75 | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` -- cgit 1.4.1-3-g733a5 From d7129919172d3f4df4e985d377b5ade41a345e9f Mon Sep 17 00:00:00 2001 From: Evan Simmons Date: Wed, 4 Apr 2018 20:46:39 -0700 Subject: New lints for write! / writeln! macros. --- clippy_lints/src/lib.rs | 21 +- clippy_lints/src/print.rs | 292 ----------------------- clippy_lints/src/utils/paths.rs | 1 + clippy_lints/src/write.rs | 437 +++++++++++++++++++++++++++++++++++ tests/ui/print.rs | 2 +- tests/ui/write_literal.rs | 35 +++ tests/ui/write_literal.stderr | 100 ++++++++ tests/ui/write_with_newline.rs | 25 ++ tests/ui/write_with_newline.stderr | 28 +++ tests/ui/writeln_empty_string.rs | 16 ++ tests/ui/writeln_empty_string.stderr | 10 + 11 files changed, 663 insertions(+), 304 deletions(-) delete mode 100644 clippy_lints/src/print.rs create mode 100644 clippy_lints/src/write.rs create mode 100644 tests/ui/write_literal.rs create mode 100644 tests/ui/write_literal.stderr create mode 100644 tests/ui/write_with_newline.rs create mode 100644 tests/ui/write_with_newline.stderr create mode 100644 tests/ui/writeln_empty_string.rs create mode 100644 tests/ui/writeln_empty_string.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8b8da64eaea..64661b1f545 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -10,7 +10,6 @@ #![feature(macro_vis_matcher)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] - // FIXME(mark-i-m) remove after i128 stablization merges #![allow(stable_features)] #![feature(i128, i128_type)] @@ -172,7 +171,6 @@ pub mod overflow_check_conditional; pub mod panic; pub mod partialeq_ne_impl; pub mod precedence; -pub mod print; pub mod ptr; pub mod question_mark; pub mod ranges; @@ -195,6 +193,7 @@ pub mod unused_io_amount; pub mod unused_label; pub mod use_self; pub mod vec; +pub mod write; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -343,7 +342,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box print::Pass); + reg.register_late_lint_pass(box write::Pass); reg.register_late_lint_pass(box vec::Pass); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold: conf.single_char_binding_names_threshold, @@ -418,8 +417,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::WRONG_PUB_SELF_CONVENTION, misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, - print::PRINT_STDOUT, - print::USE_DEBUG, + write::PRINT_STDOUT, + write::USE_DEBUG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, @@ -610,9 +609,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, - print::PRINT_LITERAL, - print::PRINT_WITH_NEWLINE, - print::PRINTLN_EMPTY_STRING, + write::PRINT_LITERAL, + write::PRINT_WITH_NEWLINE, + write::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, ptr::MUT_FROM_REF, ptr::PTR_ARG, @@ -724,9 +723,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic::PANIC_PARAMS, - print::PRINT_LITERAL, - print::PRINT_WITH_NEWLINE, - print::PRINTLN_EMPTY_STRING, + write::PRINT_LITERAL, + write::PRINT_WITH_NEWLINE, + write::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs deleted file mode 100644 index ddfe6d68f4a..00000000000 --- a/clippy_lints/src/print.rs +++ /dev/null @@ -1,292 +0,0 @@ -use std::ops::Deref; -use rustc::hir::*; -use rustc::hir::map::Node::{NodeImplItem, NodeItem}; -use rustc::lint::*; -use syntax::ast::LitKind; -use syntax::symbol::InternedString; -use syntax_pos::Span; -use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; -use utils::{opt_def_id, paths}; - -/// **What it does:** This lint warns when you use `println!("")` to -/// print a newline. -/// -/// **Why is this bad?** You should use `println!()`, which is simpler. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// println!(""); -/// ``` -declare_clippy_lint! { - pub PRINTLN_EMPTY_STRING, - style, - "using `println!(\"\")` with an empty string" -} - -/// **What it does:** This lint warns when you use `print!()` with a format -/// string that -/// ends in a newline. -/// -/// **Why is this bad?** You should use `println!()` instead, which appends the -/// newline. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// print!("Hello {}!\n", name); -/// ``` -declare_clippy_lint! { - pub PRINT_WITH_NEWLINE, - style, - "using `print!()` with a format string that ends in a newline" -} - -/// **What it does:** Checks for printing on *stdout*. The purpose of this lint -/// is to catch debugging remnants. -/// -/// **Why is this bad?** People often print on *stdout* while debugging an -/// application and might forget to remove those prints afterward. -/// -/// **Known problems:** Only catches `print!` and `println!` calls. -/// -/// **Example:** -/// ```rust -/// println!("Hello world!"); -/// ``` -declare_clippy_lint! { - pub PRINT_STDOUT, - restriction, - "printing on stdout" -} - -/// **What it does:** Checks for use of `Debug` formatting. The purpose of this -/// lint is to catch debugging remnants. -/// -/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate -/// debugging Rust code. It should not be used in in user-facing output. -/// -/// **Example:** -/// ```rust -/// println!("{:?}", foo); -/// ``` -declare_clippy_lint! { - pub USE_DEBUG, - restriction, - "use of `Debug`-based formatting" -} - -/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args. -/// -/// **Why is this bad?** Using literals as `println!` args is inefficient -/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary -/// (i.e., just put the literal in the format string) -/// -/// **Known problems:** Will also warn with macro calls as arguments that expand to literals -/// -- e.g., `println!("{}", env!("FOO"))`. -/// -/// **Example:** -/// ```rust -/// println!("{}", "foo"); -/// ``` -declare_clippy_lint! { - pub PRINT_LITERAL, - style, - "printing a literal with a format string" -} - -#[derive(Copy, Clone, Debug)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, USE_DEBUG, PRINT_LITERAL) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_chain! { - if let ExprCall(ref fun, ref args) = expr.node; - if let ExprPath(ref qpath) = fun.node; - if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); - then { - - // Search for `std::io::_print(..)` which is unique in a - // `print!` expansion. - if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { - if let Some(span) = is_expn_of(expr.span, "print") { - // `println!` uses `print!`. - let (span, name) = match is_expn_of(span, "println") { - Some(span) => (span, "println"), - None => (span, "print"), - }; - - span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - - // Check for literals in the print!/println! args - // Also, ensure the format string is `{}` with no special options, like `{:X}` - check_print_args_for_literal(cx, args); - - if_chain! { - // ensure we're calling Arguments::new_v1 - if args.len() == 1; - if let ExprCall(ref args_fun, ref args_args) = args[0].node; - if let ExprPath(ref qpath) = args_fun.node; - if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); - if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1); - if args_args.len() == 2; - if let ExprAddrOf(_, ref match_expr) = args_args[1].node; - if let ExprMatch(ref args, _, _) = match_expr.node; - if let ExprTup(ref args) = args.node; - if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); - then { - match name { - "print" => check_print(cx, span, args, fmtstr, fmtlen), - "println" => check_println(cx, span, fmtstr, fmtlen), - _ => (), - } - } - } - } - } - // Search for something like - // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` - else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { - if let ExprPath(ref qpath) = args[1].node { - if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) - && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() { - span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); - } - } - } - } - } - } - } -} - -// Check for literals in print!/println! args -// ensuring the format string for the literal is `DISPLAY_FMT_METHOD` -// e.g., `println!("... {} ...", "foo")` -// ^ literal in `println!` -fn check_print_args_for_literal<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - args: &HirVec -) { - if_chain! { - if args.len() == 1; - if let ExprCall(_, ref args_args) = args[0].node; - if args_args.len() > 1; - if let ExprAddrOf(_, ref match_expr) = args_args[1].node; - if let ExprMatch(ref matchee, ref arms, _) = match_expr.node; - if let ExprTup(ref tup) = matchee.node; - if arms.len() == 1; - if let ExprArray(ref arm_body_exprs) = arms[0].body.node; - then { - // it doesn't matter how many args there are in the `print!`/`println!`, - // if there's one literal, we should warn the user - for (idx, tup_arg) in tup.iter().enumerate() { - if_chain! { - // first, make sure we're dealing with a literal (i.e., an ExprLit) - if let ExprAddrOf(_, ref tup_val) = tup_arg.node; - if let ExprLit(_) = tup_val.node; - - // next, check the corresponding match arm body to ensure - // this is "{}", or DISPLAY_FMT_METHOD - if let ExprCall(_, ref body_args) = arm_body_exprs[idx].node; - if body_args.len() == 2; - if let ExprPath(ref body_qpath) = body_args[1].node; - if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD) || - match_def_path(cx.tcx, fun_def_id, &paths::DEBUG_FMT_METHOD); - then { - span_lint(cx, PRINT_LITERAL, tup_val.span, "printing a literal with an empty format string"); - } - } - } - } - } -} - -// Check for print!("... \n", ...). -fn check_print<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - span: Span, - args: &HirVec, - fmtstr: InternedString, - fmtlen: usize, -) { - if_chain! { - // check the final format string part - if let Some('\n') = fmtstr.chars().last(); - - // "foo{}bar" is made into two strings + one argument, - // if the format string starts with `{}` (eg. "{}foo"), - // the string array is prepended an empty string "". - // We only want to check the last string after any `{}`: - if args.len() < fmtlen; - then { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `print!()` with a format string that ends in a \ - newline, consider using `println!()` instead"); - } - } -} - -/// Check for println!("") -fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) { - if_chain! { - // check that the string is empty - if fmtlen == 1; - if fmtstr.deref() == "\n"; - - // check the presence of that string - if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); - if snippet.contains("\"\""); - then { - span_lint_and_sugg( - cx, - PRINT_WITH_NEWLINE, - span, - "using `println!(\"\")`", - "replace it with", - "println!()".to_string(), - ); - } - } -} - -fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { - let map = &cx.tcx.hir; - - // `fmt` method - if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { - // `Debug` impl - if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { - if let ItemImpl(_, _, _, _, Some(ref tr), _, _) = item.node { - return match_path(&tr.path, &["Debug"]); - } - } - } - - false -} - -/// Returns the slice of format string parts in an `Arguments::new_v1` call. -fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(InternedString, usize)> { - if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; // &["…", "…", …] - if let ExprArray(ref exprs) = expr.node; - if let Some(expr) = exprs.last(); - if let ExprLit(ref lit) = expr.node; - if let LitKind::Str(ref lit, _) = lit.node; - then { - return Some((lit.as_str(), exprs.len())); - } - } - None -} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index eecae8b230b..8f823c12cf3 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -26,6 +26,7 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; +pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs new file mode 100644 index 00000000000..0531c14cba8 --- /dev/null +++ b/clippy_lints/src/write.rs @@ -0,0 +1,437 @@ +use rustc::hir::map::Node::{NodeImplItem, NodeItem}; +use rustc::hir::*; +use rustc::lint::*; +use std::ops::Deref; +use syntax::ast::LitKind; +use syntax::ptr; +use syntax::symbol::InternedString; +use syntax_pos::Span; +use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; +use utils::{opt_def_id, paths}; + +/// **What it does:** This lint warns when you use `println!("")` to +/// print a newline. +/// +/// **Why is this bad?** You should use `println!()`, which is simpler. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// println!(""); +/// ``` +declare_clippy_lint! { + pub PRINTLN_EMPTY_STRING, + style, + "using `println!(\"\")` with an empty string" +} + +/// **What it does:** This lint warns when you use `print!()` with a format +/// string that +/// ends in a newline. +/// +/// **Why is this bad?** You should use `println!()` instead, which appends the +/// newline. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// print!("Hello {}!\n", name); +/// ``` +declare_clippy_lint! { + pub PRINT_WITH_NEWLINE, + style, + "using `print!()` with a format string that ends in a newline" +} + +/// **What it does:** Checks for printing on *stdout*. The purpose of this lint +/// is to catch debugging remnants. +/// +/// **Why is this bad?** People often print on *stdout* while debugging an +/// application and might forget to remove those prints afterward. +/// +/// **Known problems:** Only catches `print!` and `println!` calls. +/// +/// **Example:** +/// ```rust +/// println!("Hello world!"); +/// ``` +declare_clippy_lint! { + pub PRINT_STDOUT, + restriction, + "printing on stdout" +} + +/// **What it does:** Checks for use of `Debug` formatting. The purpose of this +/// lint is to catch debugging remnants. +/// +/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate +/// debugging Rust code. It should not be used in in user-facing output. +/// +/// **Example:** +/// ```rust +/// println!("{:?}", foo); +/// ``` +declare_clippy_lint! { + pub USE_DEBUG, + restriction, + "use of `Debug`-based formatting" +} + +/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args. +/// +/// **Why is this bad?** Using literals as `println!` args is inefficient +/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary +/// (i.e., just put the literal in the format string) +/// +/// **Known problems:** Will also warn with macro calls as arguments that expand to literals +/// -- e.g., `println!("{}", env!("FOO"))`. +/// +/// **Example:** +/// ```rust +/// println!("{}", "foo"); +/// ``` +declare_clippy_lint! { + pub PRINT_LITERAL, + style, + "printing a literal with a format string" +} + +/// **What it does:** This lint warns when you use `writeln!(buf, "")` to +/// print a newline. +/// +/// **Why is this bad?** You should use `writeln!(buf)`, which is simpler. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// writeln!(""); +/// ``` +declare_clippy_lint! { + pub WRITELN_EMPTY_STRING, + style, + "using `writeln!(\"\")` with an empty string" +} + +/// **What it does:** This lint warns when you use `write!()` with a format +/// string that +/// ends in a newline. +/// +/// **Why is this bad?** You should use `writeln!()` instead, which appends the +/// newline. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// write!(buf, "Hello {}!\n", name); +/// ``` +declare_clippy_lint! { + pub WRITE_WITH_NEWLINE, + style, + "using `write!()` with a format string that ends in a newline" +} + +/// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args. +/// +/// **Why is this bad?** Using literals as `writeln!` args is inefficient +/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary +/// (i.e., just put the literal in the format string) +/// +/// **Known problems:** Will also warn with macro calls as arguments that expand to literals +/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`. +/// +/// **Example:** +/// ```rust +/// writeln!(buf, "{}", "foo"); +/// ``` +declare_clippy_lint! { + pub WRITE_LITERAL, + style, + "writing a literal with a format string" +} + +#[derive(Copy, Clone, Debug)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!( + PRINT_WITH_NEWLINE, + PRINTLN_EMPTY_STRING, + PRINT_STDOUT, + USE_DEBUG, + PRINT_LITERAL, + WRITE_WITH_NEWLINE, + WRITELN_EMPTY_STRING, + WRITE_LITERAL + ) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + match expr.node { + // print!() + ExprCall(ref fun, ref args) => { + if_chain! { + if let ExprPath(ref qpath) = fun.node; + if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); + then { + check_print_variants(cx, expr, fun_id, args); + } + } + }, + // write!() + ExprMethodCall(ref fun, _, ref args) => { + if fun.name == "write_fmt" { + check_write_variants(cx, expr, args); + } + }, + _ => (), + } + } +} + +fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, write_args: &ptr::P<[Expr]>) { + // `writeln!` uses `write!`. + if let Some(span) = is_expn_of(expr.span, "write") { + let (span, name) = match is_expn_of(span, "writeln") { + Some(span) => (span, "writeln"), + None => (span, "write"), + }; + + if_chain! { + // ensure we're calling Arguments::new_v1 or Arguments::new_v1_formatted + if write_args.len() == 2; + if let ExprCall(ref args_fun, ref args_args) = write_args[1].node; + if let ExprPath(ref qpath) = args_fun.node; + if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); + if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1) || + match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); + then { + // Check for literals in the write!/writeln! args + check_fmt_args_for_literal(cx, args_args, |span| { + span_lint(cx, WRITE_LITERAL, span, "writing a literal with an empty format string"); + }); + + if_chain! { + if args_args.len() >= 2; + if let ExprAddrOf(_, ref match_expr) = args_args[1].node; + if let ExprMatch(ref args, _, _) = match_expr.node; + if let ExprTup(ref args) = args.node; + if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); + then { + match name { + "write" => if has_newline_end(args, fmtstr, fmtlen) { + span_lint(cx, WRITE_WITH_NEWLINE, span, + "using `write!()` with a format string that ends in a \ + newline, consider using `writeln!()` instead"); + }, + "writeln" => if has_empty_arg(cx, span, fmtstr, fmtlen) { + span_lint_and_sugg( + cx, + WRITE_WITH_NEWLINE, + span, + "using `writeln!(v, \"\")`", + "replace it with", + "writeln!(v)".to_string(), + ); + }, + _ => (), + } + } + } + } + } + } +} + +fn check_print_variants<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, + fun_id: def_id::DefId, + args: &ptr::P<[Expr]>, +) { + // Search for `std::io::_print(..)` which is unique in a + // `print!` expansion. + if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { + if let Some(span) = is_expn_of(expr.span, "print") { + // `println!` uses `print!`. + let (span, name) = match is_expn_of(span, "println") { + Some(span) => (span, "println"), + None => (span, "print"), + }; + + span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); + + if_chain! { + // ensure we're calling Arguments::new_v1 + if args.len() == 1; + if let ExprCall(ref args_fun, ref args_args) = args[0].node; + then { + // Check for literals in the print!/println! args + check_fmt_args_for_literal(cx, args_args, |span| { + span_lint(cx, PRINT_LITERAL, span, "printing a literal with an empty format string"); + }); + + if_chain! { + if let ExprPath(ref qpath) = args_fun.node; + if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); + if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1); + if args_args.len() == 2; + if let ExprAddrOf(_, ref match_expr) = args_args[1].node; + if let ExprMatch(ref args, _, _) = match_expr.node; + if let ExprTup(ref args) = args.node; + if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); + then { + match name { + "print" => + if has_newline_end(args, fmtstr, fmtlen) { + span_lint(cx, PRINT_WITH_NEWLINE, span, + "using `print!()` with a format string that ends in a \ + newline, consider using `println!()` instead"); + }, + "println" => + if has_empty_arg(cx, span, fmtstr, fmtlen) { + span_lint_and_sugg( + cx, + PRINT_WITH_NEWLINE, + span, + "using `println!(\"\")`", + "replace it with", + "println!()".to_string(), + ); + }, + _ => (), + } + } + } + } + } + } + } + // Search for something like + // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` + else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { + if let ExprPath(ref qpath) = args[1].node { + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) + && is_expn_of(expr.span, "panic").is_none() + { + span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } + } + } + } +} + +// Check for literals in write!/writeln! and print!/println! args +// ensuring the format string for the literal is `DISPLAY_FMT_METHOD` +// e.g., `writeln!(buf, "... {} ...", "foo")` +// ^ literal in `writeln!` +// e.g., `println!("... {} ...", "foo")` +// ^ literal in `println!` +fn check_fmt_args_for_literal<'a, 'tcx, F>(cx: &LateContext<'a, 'tcx>, args: &HirVec, lint_fn: F) +where + F: Fn(Span), +{ + if_chain! { + if args.len() > 1; + if let ExprAddrOf(_, ref match_expr) = args[1].node; + if let ExprMatch(ref matchee, ref arms, _) = match_expr.node; + if let ExprTup(ref tup) = matchee.node; + if arms.len() == 1; + if let ExprArray(ref arm_body_exprs) = arms[0].body.node; + then { + // it doesn't matter how many args there are in the `write!`/`writeln!`, + // if there's one literal, we should warn the user + for (idx, tup_arg) in tup.iter().enumerate() { + if_chain! { + // first, make sure we're dealing with a literal (i.e., an ExprLit) + if let ExprAddrOf(_, ref tup_val) = tup_arg.node; + if let ExprLit(_) = tup_val.node; + + // next, check the corresponding match arm body to ensure + // this is "{}", or DISPLAY_FMT_METHOD + if let ExprCall(_, ref body_args) = arm_body_exprs[idx].node; + if body_args.len() == 2; + if let ExprPath(ref body_qpath) = body_args[1].node; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD) || + match_def_path(cx.tcx, fun_def_id, &paths::DEBUG_FMT_METHOD); + then { + lint_fn(tup_val.span); + } + } + } + } + } +} + +/// Check for fmtstr = "... \n" +fn has_newline_end(args: &HirVec, fmtstr: InternedString, fmtlen: usize) -> bool { + if_chain! { + // check the final format string part + if let Some('\n') = fmtstr.chars().last(); + + // "foo{}bar" is made into two strings + one argument, + // if the format string starts with `{}` (eg. "{}foo"), + // the string array is prepended an empty string "". + // We only want to check the last string after any `{}`: + if args.len() < fmtlen; + then { + return true + } + } + false +} + +/// Check for writeln!(v, "") / println!("") +fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) -> bool { + if_chain! { + // check that the string is empty + if fmtlen == 1; + if fmtstr.deref() == "\n"; + + // check the presence of that string + if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); + if snippet.contains("\"\""); + then { + return true + } + } + false +} + +/// Returns the slice of format string parts in an `Arguments::new_v1` call. +fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(InternedString, usize)> { + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; // &["…", "…", …] + if let ExprArray(ref exprs) = expr.node; + if let Some(expr) = exprs.last(); + if let ExprLit(ref lit) = expr.node; + if let LitKind::Str(ref lit, _) = lit.node; + then { + return Some((lit.as_str(), exprs.len())); + } + } + None +} + +fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { + let map = &cx.tcx.hir; + + // `fmt` method + if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { + // `Debug` impl + if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { + if let ItemImpl(_, _, _, _, Some(ref tr), _, _) = item.node { + return match_path(&tr.path, &["Debug"]); + } + } + } + false +} diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 786398cfe5e..8719a691d43 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,6 +1,6 @@ -#![allow(print_literal)] +#![allow(print_literal, write_literal)] #![warn(print_stdout, use_debug)] use std::fmt::{Debug, Display, Formatter, Result}; diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs new file mode 100644 index 00000000000..dd3a869eb4e --- /dev/null +++ b/tests/ui/write_literal.rs @@ -0,0 +1,35 @@ +#![allow(unused_must_use)] +#![warn(write_literal)] + +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should be fine + write!(&mut v, "Hello"); + writeln!(&mut v, "Hello"); + let world = "world"; + writeln!(&mut v, "Hello {}", world); + writeln!(&mut v, "3 in hex is {:X}", 3); + + // These should throw warnings + write!(&mut v, "Hello {}", "world"); + writeln!(&mut v, "Hello {} {}", world, "world"); + writeln!(&mut v, "Hello {}", "world"); + writeln!(&mut v, "10 / 4 is {}", 2.5); + writeln!(&mut v, "2 + 1 = {}", 3); + writeln!(&mut v, "2 + 1 = {:.4}", 3); + writeln!(&mut v, "2 + 1 = {:5.4}", 3); + writeln!(&mut v, "Debug test {:?}", "hello, world"); + + // positional args don't change the fact + // that we're using a literal -- this should + // throw a warning + writeln!(&mut v, "{0} {1}", "hello", "world"); + writeln!(&mut v, "{1} {0}", "hello", "world"); + + // named args shouldn't change anything either + writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); +} diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr new file mode 100644 index 00000000000..9c068f1332d --- /dev/null +++ b/tests/ui/write_literal.stderr @@ -0,0 +1,100 @@ +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:17:32 + | +17 | write!(&mut v, "Hello {}", "world"); + | ^^^^^^^ + | + = note: `-D write-literal` implied by `-D warnings` + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:18:44 + | +18 | writeln!(&mut v, "Hello {} {}", world, "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:19:34 + | +19 | writeln!(&mut v, "Hello {}", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:20:38 + | +20 | writeln!(&mut v, "10 / 4 is {}", 2.5); + | ^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:21:36 + | +21 | writeln!(&mut v, "2 + 1 = {}", 3); + | ^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:22:39 + | +22 | writeln!(&mut v, "2 + 1 = {:.4}", 3); + | ^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:23:40 + | +23 | writeln!(&mut v, "2 + 1 = {:5.4}", 3); + | ^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:24:41 + | +24 | writeln!(&mut v, "Debug test {:?}", "hello, world"); + | ^^^^^^^^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:29:33 + | +29 | writeln!(&mut v, "{0} {1}", "hello", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:29:42 + | +29 | writeln!(&mut v, "{0} {1}", "hello", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:30:33 + | +30 | writeln!(&mut v, "{1} {0}", "hello", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:30:42 + | +30 | writeln!(&mut v, "{1} {0}", "hello", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:33:43 + | +33 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:33:58 + | +33 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:34:43 + | +34 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:34:58 + | +34 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs new file mode 100644 index 00000000000..0427bd3ec04 --- /dev/null +++ b/tests/ui/write_with_newline.rs @@ -0,0 +1,25 @@ +#![allow(write_literal)] +#![warn(write_with_newline)] + +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should fail + write!(&mut v, "Hello\n"); + write!(&mut v, "Hello {}\n", "world"); + write!(&mut v, "Hello {} {}\n\n", "world", "#2"); + write!(&mut v, "{}\n", 1265); + + // These should be fine + write!(&mut v, ""); + write!(&mut v, "Hello"); + writeln!(&mut v, "Hello"); + writeln!(&mut v, "Hello\n"); + writeln!(&mut v, "Hello {}\n", "world"); + write!(&mut v, "Issue\n{}", 1265); + write!(&mut v, "{}", 1265); + write!(&mut v, "\n{}", 1275); + +} diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr new file mode 100644 index 00000000000..37f03afb016 --- /dev/null +++ b/tests/ui/write_with_newline.stderr @@ -0,0 +1,28 @@ +error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead + --> $DIR/write_with_newline.rs:10:5 + | +10 | write!(&mut v, "Hello/n"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D write-with-newline` implied by `-D warnings` + +error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead + --> $DIR/write_with_newline.rs:11:5 + | +11 | write!(&mut v, "Hello {}/n", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead + --> $DIR/write_with_newline.rs:12:5 + | +12 | write!(&mut v, "Hello {} {}/n/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead + --> $DIR/write_with_newline.rs:13:5 + | +13 | write!(&mut v, "{}/n", 1265); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs new file mode 100644 index 00000000000..c7092eb8c4b --- /dev/null +++ b/tests/ui/writeln_empty_string.rs @@ -0,0 +1,16 @@ +#![allow(unused_must_use)] +#![warn(writeln_empty_string)] +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // This should fail + writeln!(&mut v, ""); + + // These should be fine + writeln!(&mut v); + writeln!(&mut v, " "); + write!(&mut v, ""); + +} diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr new file mode 100644 index 00000000000..e20aad779d9 --- /dev/null +++ b/tests/ui/writeln_empty_string.stderr @@ -0,0 +1,10 @@ +error: using `writeln!(v, "")` + --> $DIR/writeln_empty_string.rs:9:5 + | +9 | writeln!(&mut v, ""); + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` + | + = note: `-D write-with-newline` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 0692b2bb926a12a01cd4f7362092385498ebd0d0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 8 Apr 2018 10:55:42 +0200 Subject: Temporarily disable the needless_borrow lint --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/needless_borrow.rs | 2 +- tests/run-pass/needless_borrow_fp.rs | 10 ++++++++++ tests/ui/eta.rs | 2 +- tests/ui/needless_borrow.rs | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 tests/run-pass/needless_borrow_fp.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 64661b1f545..603054711a0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -592,7 +592,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { mutex_atomic::MUTEX_ATOMIC, needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, - needless_borrow::NEEDLESS_BORROW, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, needless_update::NEEDLESS_UPDATE, @@ -771,7 +770,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc_early::ZERO_PREFIXED_LITERAL, needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, - needless_borrow::NEEDLESS_BORROW, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_update::NEEDLESS_UPDATE, no_effect::NO_EFFECT, @@ -872,6 +870,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, + needless_borrow::NEEDLESS_BORROW, ranges::RANGE_PLUS_ONE, ]); } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index a5d89cbcb73..4a6d825130f 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -22,7 +22,7 @@ use utils::{in_macro, snippet_opt, span_lint_and_then}; /// ``` declare_clippy_lint! { pub NEEDLESS_BORROW, - complexity, + nursery, "taking a reference that is going to be automatically dereferenced" } diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs new file mode 100644 index 00000000000..9dc508006ed --- /dev/null +++ b/tests/run-pass/needless_borrow_fp.rs @@ -0,0 +1,10 @@ +#[deny(clippy)] + +#[derive(Debug)] +pub enum Error { + Type( + &'static str, + ), +} + +fn main() {} diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 0ff02a0b2cc..e6fad3bb777 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,7 +1,7 @@ #![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value)] -#![warn(redundant_closure)] +#![warn(redundant_closure, needless_borrow)] fn main() { let a = Some(1u8).map(|a| foo(a)); diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 99500cd0746..491194e83b1 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -5,7 +5,7 @@ fn x(y: &i32) -> i32 { *y } -#[warn(clippy)] +#[warn(clippy, needless_borrow)] #[allow(unused_variables)] fn main() { let a = 5; @@ -42,7 +42,7 @@ trait Trait {} impl<'a> Trait for &'a str {} fn h(_: &Trait) {} - +#[warn(needless_borrow)] #[allow(dead_code)] fn issue_1432() { let mut v = Vec::::new(); -- cgit 1.4.1-3-g733a5 From 4015395888308a4496f6931e66c492f672e3663f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 8 Apr 2018 11:13:07 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb3370e1788..fede68081bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.193 +* Rustup to *rustc 1.27.0-nightly (eeea94c11 2018-04-06)* + ## 0.0.192 * Rustup to *rustc 1.27.0-nightly (fb44b4c0e 2018-04-04)* * New lint: [`print_literal`] diff --git a/Cargo.toml b/Cargo.toml index 0c478510f25..f84375c0135 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.192" +version = "0.0.193" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.192", path = "clippy_lints" } +clippy_lints = { version = "0.0.193", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 389bf008056..7bf7f601de3 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.192" +version = "0.0.193" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From b46a3e53240bd09b67e99b9db859cf797758cdf6 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Tue, 10 Apr 2018 12:23:41 +0200 Subject: Add lint groups to doc export --- util/export.py | 1 + 1 file changed, 1 insertion(+) diff --git a/util/export.py b/util/export.py index 0607c864259..5419624d48e 100755 --- a/util/export.py +++ b/util/export.py @@ -18,6 +18,7 @@ This lint has the following configuration variables: def parse_lint_def(lint): lint_dict = {} lint_dict['id'] = lint.name + lint_dict['group'] = lint.group lint_dict['level'] = lint.level lint_dict['docs'] = {} -- cgit 1.4.1-3-g733a5 From c43a8921bba39b5a59aec351914b9b6f65b92b83 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Tue, 10 Apr 2018 12:24:00 +0200 Subject: Docs: Reorganize layout a bit and show lint groups --- util/gh-pages/index.html | 75 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 2cac5c6bcde..6892857af4e 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -11,8 +11,17 @@ @@ -23,7 +32,7 @@ @@ -40,7 +49,8 @@
-
+

Lint levels

+
-
+
+
+

Lint groups

+
+ +
+
+
+
+
+
Filter: @@ -63,22 +86,27 @@
+ ng-repeat="lint in data | filter:byLevels | filter:byGroups | filter:search | orderBy:'id' track by lint.id" on-finish-render="ngRepeatFinished">
- -

- {{lint.id}} +
+ {{lint.id}} + +
+ +
+ {{lint.group}} - Allow - Warn - Deny - Deprecated + Allow + Warn + Deny + Deprecated - + +

@@ -95,7 +123,7 @@
- + Fork me on Github @@ -166,6 +194,11 @@ return $scope.levels[lint.level]; }; + $scope.groups = {}; + $scope.byGroups = function (lint) { + return $scope.groups[lint.group]; + }; + // Get data $scope.open = {}; $scope.loading = true; @@ -181,6 +214,12 @@ $scope.data = data; $scope.loading = false; + // Initialize lint groups (the same structure is also used to enable filtering) + $scope.groups = data.reduce(function (result, val) { + result[val.group] = true; + return result; + }, {}); + scrollToLintByURL($scope); }) .error(function (data) { -- cgit 1.4.1-3-g733a5 From ba1be0d53b1236ab03219f49ca86df89f44418f6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Apr 2018 13:50:44 +0200 Subject: Explain nursery lints fixes #2652 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 260691faa00..9635a5838a2 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ We have a bunch of lint categories to allow you to choose how much clippy is sup * `clippy` (everything that has no false positives) * `clippy_pedantic` (everything) +* `clippy_nursery` (new lints that aren't quite ready yet) * `clippy_style` (code that should be written in a more idiomatic way) * `clippy_complexity` (code that does something simple but in a complex way) * `clippy_perf` (code that can be written in a faster way) -- cgit 1.4.1-3-g733a5 From 8fbeaa81d8c25cdf3c8eca34f287762d73b23a41 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 11 Apr 2018 08:07:21 +0200 Subject: Debug deployment script issues This prints some more information during the docs deployment. --- .github/deploy.sh | 6 +++--- .travis.yml | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index 8f6abc93ecf..17eb35b4649 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -18,16 +18,16 @@ SHA=$(git rev-parse --verify HEAD) git checkout $TARGET_BRANCH ) -# Remove the current doc for master +echo "Removing the current docs for master" rm -rf out/master/ || exit 0 -# Make the doc for master +echo "Making the docs for master" mkdir out/master/ cp util/gh-pages/index.html out/master python ./util/export.py out/master/lints.json -# Save the doc for the current tag and point current/ to it if [ -n "$TRAVIS_TAG" ]; then + echo "Save the doc for the current tag ($TRAVIS_TAG) and point current/ to it" cp -r out/master "out/$TRAVIS_TAG" rm -f out/current ln -s "$TRAVIS_TAG" out/current diff --git a/.travis.yml b/.travis.yml index 069336c6964..3a187b7b22e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,8 @@ before_install: command curl -sSL https://rvm.io/mpapis.asc | gpg --import - rvm get stable fi + - echo "TRAVIS_BRANCH:" + - echo $TRAVIS_BRANCH install: - . $HOME/.nvm/nvm.sh -- cgit 1.4.1-3-g733a5 From bdba9c14e752ef6af7df34b9d300ed432087d5c5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 11 Apr 2018 08:23:02 +0200 Subject: Add set -x for debugging --- .github/deploy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/deploy.sh b/.github/deploy.sh index 17eb35b4649..aa76f8f4e41 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -2,6 +2,7 @@ # Automatically deploy on gh-pages set -e +set -x SOURCE_BRANCH="master" TARGET_BRANCH="gh-pages" -- cgit 1.4.1-3-g733a5 From d8cf11cdf276982011a132b12561ae456c414326 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 11 Apr 2018 08:47:40 +0200 Subject: Fix travis.yml For some reason #2659 was an invalid .travis.yml and this reverts that part of the commit that changes the .travis.yml. It resulted in travis not starting jobs. There should be a travis build again for this PR. --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a187b7b22e..069336c6964 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,6 @@ before_install: command curl -sSL https://rvm.io/mpapis.asc | gpg --import - rvm get stable fi - - echo "TRAVIS_BRANCH:" - - echo $TRAVIS_BRANCH install: - . $HOME/.nvm/nvm.sh -- cgit 1.4.1-3-g733a5 From c6bc6823258b3ce1a675f9ed4e80ff3268c82e97 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Wed, 11 Apr 2018 02:17:59 -0700 Subject: Fix misaligned_transmute lint This is done by adding two new lints: cast_ptr_alignment and transmute_ptr_to_ptr. These will replace misaligned_transmute. --- clippy_lints/src/lib.rs | 4 ++++ clippy_lints/src/transmute.rs | 54 ++++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/types.rs | 37 ++++++++++++++++++++++++++++- clippy_lints/src/utils/sugg.rs | 14 +++++++++++ tests/ui/cast_alignment.rs | 19 +++++++++++++++ tests/ui/cast_alignment.stderr | 16 +++++++++++++ tests/ui/transmute.rs | 21 +++++++++++++++- tests/ui/transmute.stderr | 28 +++++++++++++++++++++- 8 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 tests/ui/cast_alignment.rs create mode 100644 tests/ui/cast_alignment.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 187b1fcee82..a9ebd4dfd3e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -641,12 +641,14 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, transmute::TRANSMUTE_PTR_TO_REF, + transmute::TRANSMUTE_PTR_TO_PTR, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, types::CAST_LOSSLESS, + types::CAST_PTR_ALIGNMENT, types::CHAR_LIT_AS_U8, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, @@ -791,6 +793,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, transmute::TRANSMUTE_PTR_TO_REF, + transmute::TRANSMUTE_PTR_TO_PTR, transmute::USELESS_TRANSMUTE, types::BORROWED_BOX, types::CAST_LOSSLESS, @@ -848,6 +851,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { swap::ALMOST_SWAPPED, transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, + types::CAST_PTR_ALIGNMENT, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 00d6c310c69..7b591a58328 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -186,6 +186,33 @@ declare_clippy_lint! { "transmutes to a potentially less-aligned type" } +/// **What it does:** Checks for transmutes from a pointer to a pointer, or +/// from a reference to a reference. +/// +/// **Why is this bad?** Transmutes are dangerous, and these can instead be +/// written as casts. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let ptr = &1u32 as *const u32; +/// unsafe { +/// // pointer-to-pointer transmute +/// let _: *const f32 = std::mem::transmute(ptr); +/// // ref-ref transmute +/// let _: &f32 = std::mem::transmute(&1u32); +/// } +/// // These can be respectively written: +/// let _ = ptr as *const f32 +/// let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) }; +/// ``` +declare_clippy_lint! { + pub TRANSMUTE_PTR_TO_PTR, + complexity, + "transmutes from a pointer to a reference type" +} + pub struct Transmute; impl LintPass for Transmute { @@ -193,6 +220,7 @@ impl LintPass for Transmute { lint_array!( CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, + TRANSMUTE_PTR_TO_PTR, USELESS_TRANSMUTE, WRONG_TRANSMUTE, TRANSMUTE_INT_TO_CHAR, @@ -363,9 +391,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); } ) + } else { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a reference to a reference", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(*ref_from)).as_ty(cx.tcx.mk_ptr(*ref_to)); + let sugg = if ref_to.mutbl == Mutability::MutMutable { + sugg_paren.mut_addr_deref() + } else { + sugg_paren.addr_deref() + }; + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ) } } }, + (&ty::TyRawPtr(_), &ty::TyRawPtr(to_ty)) => span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a pointer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ), (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => { span_lint_and_then( cx, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 16a1142efb7..9034badd5c5 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -679,6 +679,25 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } +/// **What it does:** Checks for casts from a more-strictly-aligned pointer to a +/// less-strictly-aligned pointer +/// +/// **Why is this bad?** Dereferencing the resulting pointer is undefined +/// behavior. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _ = (&1u8 as *const u8) as *const u16; +/// let _ = (&mut 1u8 as *mut u8) as *mut u16; +/// ``` +declare_clippy_lint! { + pub CAST_PTR_ALIGNMENT, + correctness, + "cast from a pointer to a less-strictly-aligned pointer" +} + /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { @@ -871,7 +890,8 @@ impl LintPass for CastPass { CAST_POSSIBLE_TRUNCATION, CAST_POSSIBLE_WRAP, CAST_LOSSLESS, - UNNECESSARY_CAST + UNNECESSARY_CAST, + CAST_PTR_ALIGNMENT ) } } @@ -955,6 +975,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { }, } } + if_chain!{ + if let ty::TyRawPtr(from_ptr_ty) = &cast_from.sty; + if let ty::TyRawPtr(to_ptr_ty) = &cast_to.sty; + if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi()); + if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi()); + if from_align < to_align; + then { + span_lint( + cx, + CAST_PTR_ALIGNMENT, + expr.span, + &format!("casting from `{}` to a less-strictly-aligned pointer (`{}`)", cast_from, cast_to) + ); + } + } } } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4ca6e5cbf73..bd48774a5ca 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -161,6 +161,20 @@ impl<'a> Sugg<'a> { make_unop("*", self) } + /// Convenience method to create the `&*` suggestion. Currently this + /// is needed because `sugg.deref().addr()` produces an unnecessary set of + /// parentheses around the deref. + pub fn addr_deref(self) -> Sugg<'static> { + make_unop("&*", self) + } + + /// Convenience method to create the `&mut *` suggestion. Currently + /// this is needed because `sugg.deref().mut_addr()` produces an unnecessary + /// set of parentheses around the deref. + pub fn mut_addr_deref(self) -> Sugg<'static> { + make_unop("&mut *", self) + } + /// Convenience method to create the `..` or `...` /// suggestion. pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs new file mode 100644 index 00000000000..4985a90bdf5 --- /dev/null +++ b/tests/ui/cast_alignment.rs @@ -0,0 +1,19 @@ +//! Test casts for alignment issues + +#[warn(cast_ptr_alignment)] +#[allow(no_effect, unnecessary_operation, cast_lossless)] +fn main() { + /* These should be warned against */ + + // cast to more-strictly-aligned type + (&1u8 as *const u8) as *const u16; + (&mut 1u8 as *mut u8) as *mut u16; + + /* These should be okay */ + + // not a pointer type + 1u8 as u16; + // cast to less-strictly-aligned type + (&1u16 as *const u16) as *const u8; + (&mut 1u16 as *mut u16) as *mut u8; +} diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr new file mode 100644 index 00000000000..d4fdb5becf9 --- /dev/null +++ b/tests/ui/cast_alignment.stderr @@ -0,0 +1,16 @@ +error: casting from `*const u8` to a less-strictly-aligned pointer (`*const u16`) + --> $DIR/cast_alignment.rs:9:5 + | +9 | (&1u8 as *const u8) as *const u16; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D cast-ptr-alignment` implied by `-D warnings` + +error: casting from `*mut u8` to a less-strictly-aligned pointer (`*mut u16`) + --> $DIR/cast_alignment.rs:10:5 + | +10 | (&mut 1u8 as *mut u8) as *mut u16; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 48b89c33ab9..3ff444b3865 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -16,7 +16,7 @@ fn my_vec() -> MyVec { vec![] } -#[allow(needless_lifetimes)] +#[allow(needless_lifetimes, transmute_ptr_to_ptr)] #[warn(useless_transmute)] unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a T = core::intrinsics::transmute(t); @@ -147,4 +147,23 @@ fn misaligned_transmute() { let _: [u8; 4] = unsafe { std::mem::transmute(0u32) }; // ok (alignment-wise) } +#[warn(transmute_ptr_to_ptr)] +fn transmute_ptr_to_ptr() { + let ptr = &1u32 as *const u32; + let mut_ptr = &mut 1u32 as *mut u32; + unsafe { + // pointer-to-pointer transmutes; bad + let _: *const f32 = std::mem::transmute(ptr); + let _: *mut f32 = std::mem::transmute(mut_ptr); + // ref-ref transmutes; bad + let _: &f32 = std::mem::transmute(&1u32); + let _: &mut f32 = std::mem::transmute(&mut 1u32); + } + // These should be fine + let _ = ptr as *const f32; + let _ = mut_ptr as *mut f32; + let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; + let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; +} + fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 74bbf95d525..f7090f0dca3 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -212,5 +212,31 @@ error: transmute from `[u8; 4]` to a less-aligned type (`u32`) | = note: `-D misaligned-transmute` implied by `-D warnings` -error: aborting due to 33 previous errors +error: transmute from a pointer to a pointer + --> $DIR/transmute.rs:156:29 + | +156 | let _: *const f32 = std::mem::transmute(ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` + | + = note: `-D transmute-ptr-to-ptr` implied by `-D warnings` + +error: transmute from a pointer to a pointer + --> $DIR/transmute.rs:157:27 + | +157 | let _: *mut f32 = std::mem::transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` + +error: transmute from a reference to a reference + --> $DIR/transmute.rs:159:23 + | +159 | let _: &f32 = std::mem::transmute(&1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` + +error: transmute from a reference to a reference + --> $DIR/transmute.rs:160:27 + | +160 | let _: &mut f32 = std::mem::transmute(&mut 1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` + +error: aborting due to 37 previous errors -- cgit 1.4.1-3-g733a5 From b77d74030b193c5d188d2191ece074b0898a3996 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Wed, 11 Apr 2018 02:50:04 -0700 Subject: Deprecate misaligned_transmute --- clippy_lints/src/deprecated_lints.rs | 11 +++++++++++ clippy_lints/src/lib.rs | 6 ++++-- clippy_lints/src/transmute.rs | 31 ------------------------------- tests/ui/deprecated.rs | 2 ++ tests/ui/deprecated.stderr | 8 +++++++- tests/ui/transmute.rs | 7 ------- tests/ui/transmute.stderr | 26 +++++++++----------------- 7 files changed, 33 insertions(+), 58 deletions(-) diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index e51d7cc6d38..1edeb30560c 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -71,3 +71,14 @@ declare_deprecated_lint! { pub STRING_TO_STRING, "using `string::to_string` is common even today and specialization will likely happen soon" } + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This lint should never have applied to non-pointer types, as transmuting +/// between non-pointer types of differing alignment is well-defined behavior (it's semantically +/// equivalent to a memcpy). This lint has thus been refactored into two separate lints: +/// cast_ptr_alignment and transmute_ptr_to_ptr. +declare_deprecated_lint! { + pub MISALIGNED_TRANSMUTE, + "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr" +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a9ebd4dfd3e..190d65be86e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -277,6 +277,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { "string_to_string", "using `string::to_string` is common even today and specialization will likely happen soon", ); + store.register_removed( + "misaligned_transmute", + "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); @@ -635,7 +639,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, - transmute::MISALIGNED_TRANSMUTE, transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, @@ -787,7 +790,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, - transmute::MISALIGNED_TRANSMUTE, transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 7b591a58328..68321e7bd5e 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,7 +1,6 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; -use rustc::ty::layout::LayoutOf; use std::borrow::Cow; use syntax::ast; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; @@ -169,23 +168,6 @@ declare_clippy_lint! { "transmutes from an integer to a float" } -/// **What it does:** Checks for transmutes to a potentially less-aligned type. -/// -/// **Why is this bad?** This might result in undefined behavior. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// // u32 is 32-bit aligned; u8 is 8-bit aligned -/// let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; -/// ``` -declare_clippy_lint! { - pub MISALIGNED_TRANSMUTE, - complexity, - "transmutes to a potentially less-aligned type" -} - /// **What it does:** Checks for transmutes from a pointer to a pointer, or /// from a reference to a reference. /// @@ -227,7 +209,6 @@ impl LintPass for Transmute { TRANSMUTE_BYTES_TO_STR, TRANSMUTE_INT_TO_BOOL, TRANSMUTE_INT_TO_FLOAT, - MISALIGNED_TRANSMUTE ) } } @@ -248,18 +229,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), - _ if cx.layout_of(from_ty).ok().map(|a| a.align.abi()) - < cx.layout_of(to_ty).ok().map(|a| a.align.abi()) - => span_lint( - cx, - MISALIGNED_TRANSMUTE, - e.span, - &format!( - "transmute from `{}` to a less-aligned type (`{}`)", - from_ty, - to_ty, - ) - ), (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( cx, USELESS_TRANSMUTE, diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 0598e174e50..f456c417223 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -9,4 +9,6 @@ #[warn(unstable_as_mut_slice)] +#[warn(misaligned_transmute)] + fn main() {} diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 7d5d594cfa1..aa62ccbd0e5 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -24,5 +24,11 @@ error: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been 10 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: lint misaligned_transmute has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr + --> $DIR/deprecated.rs:12:8 + | +12 | #[warn(misaligned_transmute)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 3ff444b3865..7c5e3f03d13 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -140,13 +140,6 @@ fn bytes_to_str(b: &[u8], mb: &mut [u8]) { let _: &mut str = unsafe { std::mem::transmute(mb) }; } -#[warn(misaligned_transmute)] -fn misaligned_transmute() { - let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err - let _: u32 = unsafe { std::mem::transmute(0f32) }; // ok (alignment-wise) - let _: [u8; 4] = unsafe { std::mem::transmute(0u32) }; // ok (alignment-wise) -} - #[warn(transmute_ptr_to_ptr)] fn transmute_ptr_to_ptr() { let ptr = &1u32 as *const u32; diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index f7090f0dca3..a343a8a9cb5 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -204,39 +204,31 @@ error: transmute from a `&mut [u8]` to a `&mut str` 140 | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: transmute from `[u8; 4]` to a less-aligned type (`u32`) - --> $DIR/transmute.rs:145:27 - | -145 | let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D misaligned-transmute` implied by `-D warnings` - error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:156:29 + --> $DIR/transmute.rs:149:29 | -156 | let _: *const f32 = std::mem::transmute(ptr); +149 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | = note: `-D transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:157:27 + --> $DIR/transmute.rs:150:27 | -157 | let _: *mut f32 = std::mem::transmute(mut_ptr); +150 | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:159:23 + --> $DIR/transmute.rs:152:23 | -159 | let _: &f32 = std::mem::transmute(&1u32); +152 | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:160:27 + --> $DIR/transmute.rs:153:27 | -160 | let _: &mut f32 = std::mem::transmute(&mut 1u32); +153 | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` -error: aborting due to 37 previous errors +error: aborting due to 36 previous errors -- cgit 1.4.1-3-g733a5 From 6ae617b31348e6397b581a7b5f1c66d30d335024 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 12 Apr 2018 08:21:03 +0200 Subject: Fix useless_format false negative Closes #2546 --- clippy_lints/src/format.rs | 62 +++++++++++++++++++++++++++++++++++----------- tests/ui/format.rs | 12 ++++++--- tests/ui/format.stderr | 50 ++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 2b5b79db980..bce0eff2fc5 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -2,8 +2,9 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; +use syntax_pos::Span; use utils::paths; -use utils::{in_macro, is_expn_of, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; +use utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -43,20 +44,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } match expr.node { + // `format!("{}", foo)` expansion ExprCall(ref fun, ref args) => { if_chain! { if let ExprPath(ref qpath) = fun.node; - if args.len() == 2; + if args.len() == 3; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1); - // ensure the format string is `"{..}"` with only one argument and no text - if check_static_str(&args[0]); - // ensure the format argument is `{}` ie. Display with no fancy option - // and that the argument is a string - if check_arg_is_display(cx, &args[1]); + if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); + if check_single_piece(&args[0]); + if let Some(format_arg) = get_single_string_arg(cx, &args[1]); + if check_unformatted(&args[2]); then { - let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); + let sugg = format!("{}.to_string()", snippet(cx, format_arg, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { db.span_suggestion(expr.span, "consider using .to_string()", sugg); }); @@ -79,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } /// Checks if the expressions matches `&[""]` -fn check_static_str(expr: &Expr) -> bool { +fn check_single_piece(expr: &Expr) -> bool { if_chain! { if let ExprAddrOf(_, ref expr) = expr.node; // &[""] if let ExprArray(ref exprs) = expr.node; // [""] @@ -96,15 +96,17 @@ fn check_static_str(expr: &Expr) -> bool { /// Checks if the expressions matches /// ```rust,ignore -/// &match (&42,) { +/// &match (&"arg",) { /// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, /// ::std::fmt::Display::fmt)], /// } /// ``` -fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { +/// and that type of `__arg0` is `&str` or `String` +/// then returns the span of first element of the matched tuple +fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option { if_chain! { if let ExprAddrOf(_, ref expr) = expr.node; - if let ExprMatch(_, ref arms, _) = expr.node; + if let ExprMatch(ref match_expr, ref arms, _) = expr.node; if arms.len() == 1; if arms[0].pats.len() == 1; if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node; @@ -118,8 +120,40 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); + if ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING) { + if let ExprTup(ref values) = match_expr.node { + return Some(values[0].span); + } + } + } + } + + None +} - return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING); +/// Checks if the expression matches +/// ```rust,ignore +/// &[_ { +/// format: _ { +/// width: _::Implied, +/// ... +/// }, +/// ..., +/// }] +/// ``` +fn check_unformatted(expr: &Expr) -> bool { + if_chain! { + if let ExprAddrOf(_, ref expr) = expr.node; + if let ExprArray(ref exprs) = expr.node; + if exprs.len() == 1; + if let ExprStruct(_, ref fields, _) = exprs[0].node; + if let Some(format_field) = fields.iter().filter(|f| f.name.node == "format").next(); + if let ExprStruct(_, ref fields, _) = format_field.expr.node; + if let Some(align_field) = fields.iter().filter(|f| f.name.node == "width").next(); + if let ExprPath(ref qpath) = align_field.expr.node; + if last_path_segment(qpath).name == "Implied"; + then { + return true; } } diff --git a/tests/ui/format.rs b/tests/ui/format.rs index cf5d1d29482..783c6ea095d 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -12,15 +12,19 @@ fn main() { format!("foo"); format!("{}", "foo"); - format!("{:?}", "foo"); // we only want to warn about `{}` - format!("{:+}", "foo"); // we only want to warn about `{}` + format!("{:?}", "foo"); // don't warn about debug + format!("{:8}", "foo"); + format!("{:+}", "foo"); // warn when the format makes no difference + format!("{:<}", "foo"); // warn when the format makes no difference format!("foo {}", "bar"); format!("{} bar", "foo"); let arg: String = "".to_owned(); format!("{}", arg); - format!("{:?}", arg); // we only want to warn about `{}` - format!("{:+}", arg); // we only want to warn about `{}` + format!("{:?}", arg); // don't warn about debug + format!("{:8}", arg); + format!("{:+}", arg); // warn when the format makes no difference + format!("{:<}", arg); // warn when the format makes no difference format!("foo {}", arg); format!("{} bar", arg); diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 8c36d9a830c..fa5c740c551 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -6,5 +6,53 @@ error: useless use of `format!` | = note: `-D useless-format` implied by `-D warnings` -error: aborting due to previous error +error: useless use of `format!` + --> $DIR/format.rs:14:5 + | +14 | format!("{}", "foo"); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:17:5 + | +17 | format!("{:+}", "foo"); // warn when the format makes no difference + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:18:5 + | +18 | format!("{:<}", "foo"); // warn when the format makes no difference + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:23:5 + | +23 | format!("{}", arg); + | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:26:5 + | +26 | format!("{:+}", arg); // warn when the format makes no difference + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:27:5 + | +27 | format!("{:<}", arg); // warn when the format makes no difference + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From c7ad71ccf2a805529d18cf45a09bd3196994a488 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 12 Apr 2018 08:50:42 +0200 Subject: Fix clippy warnings --- clippy_lints/src/format.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index bce0eff2fc5..25cff794fd8 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -147,9 +147,9 @@ fn check_unformatted(expr: &Expr) -> bool { if let ExprArray(ref exprs) = expr.node; if exprs.len() == 1; if let ExprStruct(_, ref fields, _) = exprs[0].node; - if let Some(format_field) = fields.iter().filter(|f| f.name.node == "format").next(); + if let Some(format_field) = fields.iter().find(|f| f.name.node == "format"); if let ExprStruct(_, ref fields, _) = format_field.expr.node; - if let Some(align_field) = fields.iter().filter(|f| f.name.node == "width").next(); + if let Some(align_field) = fields.iter().find(|f| f.name.node == "width"); if let ExprPath(ref qpath) = align_field.expr.node; if last_path_segment(qpath).name == "Implied"; then { -- cgit 1.4.1-3-g733a5 From dfde407f0d81b2155a6354fa8ddc5a5ad0d7c2b6 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 12 Apr 2018 22:16:43 +0200 Subject: Move unnecessary_fold UI tests to separate file --- tests/ui/methods.rs | 39 --------------------------------------- tests/ui/methods.stderr | 38 +++----------------------------------- tests/ui/unnecessary_fold.rs | 40 ++++++++++++++++++++++++++++++++++++++++ tests/ui/unnecessary_fold.stderr | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 74 deletions(-) create mode 100644 tests/ui/unnecessary_fold.rs create mode 100644 tests/ui/unnecessary_fold.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 65cac8ec4ff..9e253655833 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -385,45 +385,6 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -/// Calls which should trigger the `UNNECESSARY_FOLD` lint -fn unnecessary_fold() { - // Can be replaced by .any - let _ = (0..3).fold(false, |acc, x| acc || x > 2); - // Can be replaced by .all - let _ = (0..3).fold(true, |acc, x| acc && x > 2); - // Can be replaced by .sum - let _ = (0..3).fold(0, |acc, x| acc + x); - // Can be replaced by .product - let _ = (0..3).fold(1, |acc, x| acc * x); -} - -/// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` -fn unnecessary_fold_span_for_multi_element_chain() { - let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); -} - -/// Calls which should not trigger the `UNNECESSARY_FOLD` lint -fn unnecessary_fold_should_ignore() { - let _ = (0..3).fold(true, |acc, x| acc || x > 2); - let _ = (0..3).fold(false, |acc, x| acc && x > 2); - let _ = (0..3).fold(1, |acc, x| acc + x); - let _ = (0..3).fold(0, |acc, x| acc * x); - let _ = (0..3).fold(0, |acc, x| 1 + acc + x); - - // We only match against an accumulator on the left - // hand side. We could lint for .sum and .product when - // it's on the right, but don't for now (and this wouldn't - // be valid if we extended the lint to cover arbitrary numeric - // types). - let _ = (0..3).fold(false, |acc, x| x > 2 || acc); - let _ = (0..3).fold(true, |acc, x| x > 2 && acc); - let _ = (0..3).fold(0, |acc, x| x + acc); - let _ = (0..3).fold(1, |acc, x| x * acc); - - let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); - let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); -} - #[allow(similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 42cf3d3cbc5..1dd1ddc3caa 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -493,45 +493,13 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 382 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:391:19 - | -391 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` - | - = note: `-D unnecessary-fold` implied by `-D warnings` - -error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:393:19 - | -393 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` - -error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:395:19 - | -395 | let _ = (0..3).fold(0, |acc, x| acc + x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` - -error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:397:19 - | -397 | let _ = (0..3).fold(1, |acc, x| acc * x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` - -error: this `.fold` can be written more succinctly using another method - --> $DIR/methods.rs:402:34 - | -402 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` - error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:430:13 + --> $DIR/methods.rs:391:13 | -430 | let _ = opt.unwrap(); +391 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -error: aborting due to 71 previous errors +error: aborting due to 66 previous errors diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs new file mode 100644 index 00000000000..62198e21ef7 --- /dev/null +++ b/tests/ui/unnecessary_fold.rs @@ -0,0 +1,40 @@ +/// Calls which should trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold() { + // Can be replaced by .any + let _ = (0..3).fold(false, |acc, x| acc || x > 2); + // Can be replaced by .all + let _ = (0..3).fold(true, |acc, x| acc && x > 2); + // Can be replaced by .sum + let _ = (0..3).fold(0, |acc, x| acc + x); + // Can be replaced by .product + let _ = (0..3).fold(1, |acc, x| acc * x); +} + +/// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` +fn unnecessary_fold_span_for_multi_element_chain() { + let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +} + +/// Calls which should not trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold_should_ignore() { + let _ = (0..3).fold(true, |acc, x| acc || x > 2); + let _ = (0..3).fold(false, |acc, x| acc && x > 2); + let _ = (0..3).fold(1, |acc, x| acc + x); + let _ = (0..3).fold(0, |acc, x| acc * x); + let _ = (0..3).fold(0, |acc, x| 1 + acc + x); + + // We only match against an accumulator on the left + // hand side. We could lint for .sum and .product when + // it's on the right, but don't for now (and this wouldn't + // be valid if we extended the lint to cover arbitrary numeric + // types). + let _ = (0..3).fold(false, |acc, x| x > 2 || acc); + let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + let _ = (0..3).fold(0, |acc, x| x + acc); + let _ = (0..3).fold(1, |acc, x| x * acc); + + let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); + let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); +} + +fn main() {} diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr new file mode 100644 index 00000000000..8bc4b8244bd --- /dev/null +++ b/tests/ui/unnecessary_fold.stderr @@ -0,0 +1,34 @@ +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:4:19 + | +4 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` + | + = note: `-D unnecessary-fold` implied by `-D warnings` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:6:19 + | +6 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:8:19 + | +8 | let _ = (0..3).fold(0, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:10:19 + | +10 | let _ = (0..3).fold(1, |acc, x| acc * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:15:34 + | +15 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` + +error: aborting due to 5 previous errors + -- cgit 1.4.1-3-g733a5 From 0995e923f0c038a2be43cd55e3adf852a1160529 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 13 Apr 2018 20:54:42 +0200 Subject: Run remark-lint on all markdown files in root --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 069336c6964..077a17e0bac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ install: script: - PATH=$PATH:./node_modules/.bin - - remark -f README.md > /dev/null + - remark -f *.md > /dev/null - set -e - cargo build --features debugging - cargo test --features debugging -- cgit 1.4.1-3-g733a5 From 01faa906d2d9d9e1919a3045625f06e671e7eac6 Mon Sep 17 00:00:00 2001 From: Stefano Probst Date: Sat, 14 Apr 2018 11:35:52 +0200 Subject: Fix Markdown link syntax in lint doc Currently this link is wrong rendered. See https://rust-lang-nursery.github.io/rust-clippy/v0.0.193/index.html#iter_next_loop --- clippy_lints/src/loops.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 9a6b7627b47..561940f9e77 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -108,8 +108,7 @@ declare_clippy_lint! { /// implements `IntoIterator`, so that possibly one value will be iterated, /// leading to some hard to find bugs. No one will want to write such code /// [except to win an Underhanded Rust -/// Contest](https://www.reddit. -/// com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). +/// Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr). /// /// **Known problems:** None. /// -- cgit 1.4.1-3-g733a5 From a9c8d1bd906c30b1c491801e9063c400c378db0b Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 15 Apr 2018 04:48:14 +0200 Subject: Fix compilation for nightly 2018-04-15 This only fixes compilation and the build. It's possible that the `author` and `inspector` lints are broken but there are no failing tests. Closes #2667 --- clippy_lints/src/loops.rs | 1 - clippy_lints/src/no_effect.rs | 2 -- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/temporary_assignment.rs | 4 ++-- clippy_lints/src/utils/author.rs | 8 -------- clippy_lints/src/utils/hir_utils.rs | 8 -------- clippy_lints/src/utils/inspector.rs | 6 ------ clippy_lints/src/utils/sugg.rs | 2 -- 8 files changed, 3 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 561940f9e77..cfef1e85b94 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -602,7 +602,6 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprCast(ref e, _) | ExprType(ref e, _) | ExprField(ref e, _) | - ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprStruct(_, _, Some(ref e)) | ExprRepeat(ref e, _) => never_loop_expr(e, main_loop_id), diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 1847761416b..2765c1b2ee0 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -56,7 +56,6 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { Expr_::ExprType(ref inner, _) | Expr_::ExprUnary(_, ref inner) | Expr_::ExprField(ref inner, _) | - Expr_::ExprTupField(ref inner, _) | Expr_::ExprAddrOf(_, ref inner) | Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), Expr_::ExprStruct(_, ref fields, ref base) => { @@ -143,7 +142,6 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), Expr_::ExprStruct(_, ref fields, ref base) => if has_drop(cx, expr) { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 8330bb7015b..b7e79a06327 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -306,7 +306,7 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: return; } match expr.node { - ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { + ExprUnary(_, ref e) | ExprField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { check_expr(cx, e, bindings) }, ExprBlock(ref block) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 459549f1e58..49f079f8cd6 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField}; +use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup}; use utils::is_adjusted; use utils::span_lint; @@ -41,7 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { - ExprField(ref base, _) | ExprTupField(ref base, _) => if is_temporary(base) && !is_adjusted(cx, base) { + ExprField(ref base, _) => if is_temporary(base) && !is_adjusted(cx, base) { span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); }, _ => (), diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 7aeaa710443..8e81d9440b0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -371,14 +371,6 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = obj_pat; self.visit_expr(object); }, - Expr_::ExprTupField(ref object, ref field_id) => { - let obj_pat = self.next("object"); - let field_id_pat = self.next("field_id"); - println!("TupField(ref {}, ref {}) = {};", obj_pat, field_id_pat, current); - println!(" if {}.node == {}", field_id_pat, field_id.node); - self.current = obj_pat; - self.visit_expr(object); - }, Expr_::ExprIndex(ref object, ref index) => { let object_pat = self.next("object"); let index_pat = self.next("index"); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 1f96ec2b237..780d8339c27 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -131,7 +131,6 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { && over(lf, rf, |l, r| self.eq_field(l, r)) }, (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), - (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprArray(ref l), &ExprArray(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { @@ -496,13 +495,6 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_exprs(tup); }, - ExprTupField(ref le, li) => { - let c: fn(_, _) -> _ = ExprTupField; - c.hash(&mut self.s); - - self.hash_expr(le); - li.node.hash(&mut self.s); - }, ExprType(ref e, ref _ty) => { let c: fn(_, _) -> _ = ExprType; c.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index e8d07fbed0d..ac38227c302 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -274,12 +274,6 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}struct expr:", ind); print_expr(cx, e, indent + 1); }, - hir::ExprTupField(ref e, ref idx) => { - println!("{}TupField", ind); - println!("{}field index: {}", ind, idx.node); - println!("{}tuple expr:", ind); - print_expr(cx, e, indent + 1); - }, hir::ExprIndex(ref arr, ref idx) => { println!("{}Index", ind); println!("{}array expr:", ind); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 526cadb435d..a9e5a3222ac 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -69,7 +69,6 @@ impl<'a> Sugg<'a> { hir::ExprRet(..) | hir::ExprStruct(..) | hir::ExprTup(..) | - hir::ExprTupField(..) | hir::ExprWhile(..) => Sugg::NonParen(snippet), hir::ExprAssign(..) => Sugg::BinOp(AssocOp::Assign, snippet), hir::ExprAssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), @@ -121,7 +120,6 @@ impl<'a> Sugg<'a> { ast::ExprKind::Struct(..) | ast::ExprKind::Try(..) | ast::ExprKind::Tup(..) | - ast::ExprKind::TupField(..) | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), -- cgit 1.4.1-3-g733a5 From d171e8987e7c4c6900f8593c9bb3c5b7eb420e85 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 15 Apr 2018 05:20:30 +0200 Subject: Fix clippy error --- clippy_lints/src/temporary_assignment.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 49f079f8cd6..fe1012aa98c 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -40,11 +40,10 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprAssign(ref target, _) = expr.node { - match target.node { - ExprField(ref base, _) => if is_temporary(base) && !is_adjusted(cx, base) { + if let ExprField(ref base, _) = target.node { + if is_temporary(base) && !is_adjusted(cx, base) { span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - }, - _ => (), + } } } } -- cgit 1.4.1-3-g733a5 From e5ecbb55ee68370c629215e077ced565c0925d22 Mon Sep 17 00:00:00 2001 From: Phil Turnbull Date: Mon, 16 Jan 2017 15:40:50 -0500 Subject: Lint `Option.map(f)` where f returns nil --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/map_nil_fn.rs | 91 ++++++++++++++++++++++++++++++++++++++++ tests/compile-fail/map_nil_fn.rs | 42 +++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 clippy_lints/src/map_nil_fn.rs create mode 100644 tests/compile-fail/map_nil_fn.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index fede68081bb..14438edcb98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -705,6 +705,7 @@ All notable changes to this project will be documented in this file. [`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options [`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect +[`option_map_nil_fn`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_nil_fn [`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref [`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3b2251b9021..755fc26bc9b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -145,6 +145,7 @@ pub mod lifetimes; pub mod literal_representation; pub mod loops; pub mod map_clone; +pub mod map_nil_fn; pub mod matches; pub mod mem_forget; pub mod methods; @@ -405,6 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); + reg.register_late_lint_pass(box map_nil_fn::Pass); reg.register_lint_group("clippy_restriction", vec![ @@ -441,6 +443,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, + map_nil_fn::OPTION_MAP_NIL_FN, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs new file mode 100644 index 00000000000..0fd2c176a64 --- /dev/null +++ b/clippy_lints/src/map_nil_fn.rs @@ -0,0 +1,91 @@ +use rustc::hir; +use rustc::lint::*; +use rustc::ty; +use utils::{in_macro, match_type, method_chain_args, snippet, span_lint_and_then}; +use utils::paths; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for usage of `Option.map(f)` where f is a nil +/// function +/// +/// **Why is this bad?** Readability, this can be written more clearly with +/// an if statement +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x : Option<&str> = do_stuff(); +/// x.map(log_err_msg); +/// ``` +/// The correct use would be: +/// ```rust +/// let x : Option<&str> = do_stuff(); +/// if let Some(msg) = x { +/// log_err_msg(msg) +/// } +/// ``` +declare_lint! { + pub OPTION_MAP_NIL_FN, + Allow, + "using `Option.map(f)`, where f is a nil function" +} + + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(OPTION_MAP_NIL_FN) + } +} + +fn is_nil_function(cx: &LateContext, expr: &hir::Expr) -> bool { + let ty = cx.tables.expr_ty(expr); + + if let ty::TyFnDef(_, _, bare) = ty.sty { + if let Some(fn_type) = cx.tcx.no_late_bound_regions(&bare.sig) { + return fn_type.output().is_nil(); + } + } + false +} + +fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { + let var_arg = &map_args[0]; + let fn_arg = &map_args[1]; + + if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + return; + } + + let suggestion = if is_nil_function(cx, fn_arg) { + format!("if let Some(...) = {0} {{ {1}(...) }}", + snippet(cx, var_arg.span, "_"), + snippet(cx, fn_arg.span, "_")) + } else { + return; + }; + + span_lint_and_then(cx, + OPTION_MAP_NIL_FN, + expr.span, + "called `map(f)` on an Option value where `f` is a nil function", + |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { + if in_macro(cx, stmt.span) { + return; + } + + if let hir::StmtSemi(ref expr, _) = stmt.node { + if let hir::ExprMethodCall(_, _, _) = expr.node { + if let Some(arglists) = method_chain_args(expr, &["map"]) { + lint_map_nil_fn(cx, stmt, expr, arglists[0]); + } + } + } + } +} diff --git a/tests/compile-fail/map_nil_fn.rs b/tests/compile-fail/map_nil_fn.rs new file mode 100644 index 00000000000..0338216c578 --- /dev/null +++ b/tests/compile-fail/map_nil_fn.rs @@ -0,0 +1,42 @@ +#![feature(plugin)] +#![feature(const_fn)] +#![plugin(clippy)] + +#![deny(clippy_pedantic)] +#![allow(unused, missing_docs_in_private_items)] + +fn do_nothing(_: T) {} + +fn plus_one(value: usize) -> usize { + value + 1 +} + +struct HasOption { + field: Option, +} + +impl HasOption { + fn do_option_nothing(self: &HasOption, value: usize) {} + + fn do_option_plus_one(self: &HasOption, value: usize) -> usize { + value + 1 + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn main() { + let x = HasOption { field: Some(10) }; + + x.field.map(plus_one); + let _ : Option<()> = x.field.map(do_nothing); + + x.field.map(do_nothing); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil function + //~| HELP try this + //~| SUGGESTION if let Some(...) = x.field { do_nothing(...) } + + x.field.map(do_nothing); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil function + //~| HELP try this + //~| SUGGESTION if let Some(...) = x.field { do_nothing(...) } +} -- cgit 1.4.1-3-g733a5 From 302f5d05f57b4debbe2890f7ebabbedb2059737f Mon Sep 17 00:00:00 2001 From: Phil Turnbull Date: Sun, 22 Jan 2017 12:45:45 -0500 Subject: Lint `Option.map(f)` where f never returns --- clippy_lints/src/map_nil_fn.rs | 2 +- tests/compile-fail/map_nil_fn.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index 0fd2c176a64..9502c5d0563 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -45,7 +45,7 @@ fn is_nil_function(cx: &LateContext, expr: &hir::Expr) -> bool { if let ty::TyFnDef(_, _, bare) = ty.sty { if let Some(fn_type) = cx.tcx.no_late_bound_regions(&bare.sig) { - return fn_type.output().is_nil(); + return fn_type.output().is_nil() || fn_type.output().is_never(); } } false diff --git a/tests/compile-fail/map_nil_fn.rs b/tests/compile-fail/map_nil_fn.rs index 0338216c578..03f77c50034 100644 --- a/tests/compile-fail/map_nil_fn.rs +++ b/tests/compile-fail/map_nil_fn.rs @@ -7,6 +7,10 @@ fn do_nothing(_: T) {} +fn diverge(_: T) -> ! { + panic!() +} + fn plus_one(value: usize) -> usize { value + 1 } @@ -39,4 +43,9 @@ fn main() { //~^ ERROR called `map(f)` on an Option value where `f` is a nil function //~| HELP try this //~| SUGGESTION if let Some(...) = x.field { do_nothing(...) } + + x.field.map(diverge); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil function + //~| HELP try this + //~| SUGGESTION if let Some(...) = x.field { diverge(...) } } -- cgit 1.4.1-3-g733a5 From 30f2480fd879359f8773d5c29807130c3a489785 Mon Sep 17 00:00:00 2001 From: Phil Turnbull Date: Sun, 22 Jan 2017 13:36:50 -0500 Subject: Lint closures that return nil --- clippy_lints/src/map_nil_fn.rs | 127 +++++++++++++++++++++++++++++++++------ tests/compile-fail/map_nil_fn.rs | 84 ++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index 9502c5d0563..4423aeece6f 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -1,24 +1,26 @@ use rustc::hir; use rustc::lint::*; use rustc::ty; -use utils::{in_macro, match_type, method_chain_args, snippet, span_lint_and_then}; +use std::borrow::Cow; +use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use utils::paths; #[derive(Clone)] pub struct Pass; /// **What it does:** Checks for usage of `Option.map(f)` where f is a nil -/// function +/// function or closure /// /// **Why is this bad?** Readability, this can be written more clearly with /// an if statement /// -/// **Known problems:** None. +/// **Known problems:** Closures with multiple statements are not handled /// /// **Example:** /// ```rust /// let x : Option<&str> = do_stuff(); /// x.map(log_err_msg); +/// x.map(|msg| log_err_msg(format_msg(msg))) /// ``` /// The correct use would be: /// ```rust @@ -26,11 +28,14 @@ pub struct Pass; /// if let Some(msg) = x { /// log_err_msg(msg) /// } +/// if let Some(msg) = x { +/// log_err_msg(format_msg(msg)) +/// } /// ``` declare_lint! { pub OPTION_MAP_NIL_FN, Allow, - "using `Option.map(f)`, where f is a nil function" + "using `Option.map(f)`, where f is a nil function or closure" } @@ -40,17 +45,94 @@ impl LintPass for Pass { } } +fn is_nil_type(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyTuple(slice) => slice.is_empty(), + ty::TyNever => true, + _ => false, + } +} + fn is_nil_function(cx: &LateContext, expr: &hir::Expr) -> bool { let ty = cx.tables.expr_ty(expr); if let ty::TyFnDef(_, _, bare) = ty.sty { if let Some(fn_type) = cx.tcx.no_late_bound_regions(&bare.sig) { - return fn_type.output().is_nil() || fn_type.output().is_never(); + return is_nil_type(fn_type.output()); } } false } +fn is_nil_expression(cx: &LateContext, expr: &hir::Expr) -> bool { + is_nil_type(cx.tables.expr_ty(expr)) +} + +// The expression inside a closure may or may not have surrounding braces and +// semicolons, which causes problems when generating a suggestion. Given an +// expression that evaluates to '()' or '!', recursively remove useless braces +// and semi-colons until is suitable for including in the suggestion template +fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option> { + if !is_nil_expression(cx, expr) { + return None; + } + + match expr.node { + hir::ExprCall(_, _) | + hir::ExprMethodCall(_, _, _) => { + // Calls can't be reduced any more + Some(snippet(cx, expr.span, "_")) + }, + hir::ExprBlock(ref block) => { + match (&block.stmts[..], block.expr.as_ref()) { + (&[], Some(inner_expr)) => { + // Reduce `{ X }` to `X` + reduce_nil_expression(cx, inner_expr) + }, + (&[ref inner_stmt], None) => { + // Reduce `{ X; }` to `X` or `X;` + match inner_stmt.node { + hir::StmtDecl(ref d, _) => Some(snippet(cx, d.span, "_")), + hir::StmtExpr(ref e, _) => Some(snippet(cx, e.span, "_")), + hir::StmtSemi(ref e, _) => { + if is_nil_expression(cx, e) { + // `X` returns nil so we can strip the + // semicolon and reduce further + reduce_nil_expression(cx, e) + } else { + // `X` doesn't return nil so it needs a + // trailing semicolon + Some(snippet(cx, inner_stmt.span, "_")) + } + }, + } + }, + _ => None, + } + }, + _ => None, + } +} + +fn reduce_nil_closure<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'a hir::Expr +) -> Option<(Cow<'a, str>, Cow<'a, str>)> { + if let hir::ExprClosure(_, ref decl, inner_expr_id, _) = expr.node { + let body = cx.tcx.map.body(inner_expr_id); + + if_let_chain! {[ + decl.inputs.len() == 1, + let Some(binding) = iter_input_pats(&decl, body).next(), + let Some(expr_snippet) = reduce_nil_expression(cx, &body.value), + ], { + let binding_snippet = snippet(cx, binding.pat.span, "_"); + return Some((binding_snippet, expr_snippet)); + }} + } + None +} + fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { let var_arg = &map_args[0]; let fn_arg = &map_args[1]; @@ -59,19 +141,30 @@ fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_arg return; } - let suggestion = if is_nil_function(cx, fn_arg) { - format!("if let Some(...) = {0} {{ {1}(...) }}", - snippet(cx, var_arg.span, "_"), - snippet(cx, fn_arg.span, "_")) - } else { - return; - }; + if is_nil_function(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a nil function"; + let suggestion = format!("if let Some(...) = {0} {{ {1}(...) }}", + snippet(cx, var_arg.span, "_"), + snippet(cx, fn_arg.span, "_")); - span_lint_and_then(cx, - OPTION_MAP_NIL_FN, - expr.span, - "called `map(f)` on an Option value where `f` is a nil function", - |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + span_lint_and_then(cx, + OPTION_MAP_NIL_FN, + expr.span, + msg, + |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + } else if let Some((binding_snippet, expr_snippet)) = reduce_nil_closure(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a nil closure"; + let suggestion = format!("if let Some({0}) = {1} {{ {2} }}", + binding_snippet, + snippet(cx, var_arg.span, "_"), + expr_snippet); + + span_lint_and_then(cx, + OPTION_MAP_NIL_FN, + expr.span, + msg, + |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/tests/compile-fail/map_nil_fn.rs b/tests/compile-fail/map_nil_fn.rs index 03f77c50034..5ac3913466a 100644 --- a/tests/compile-fail/map_nil_fn.rs +++ b/tests/compile-fail/map_nil_fn.rs @@ -48,4 +48,88 @@ fn main() { //~^ ERROR called `map(f)` on an Option value where `f` is a nil function //~| HELP try this //~| SUGGESTION if let Some(...) = x.field { diverge(...) } + + let captured = 10; + if let Some(value) = x.field { do_nothing(value + captured) }; + let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); + + x.field.map(|value| x.do_option_nothing(value + captured)); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { x.do_option_nothing(value + captured) } + + x.field.map(|value| { x.do_option_plus_one(value + captured); }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { x.do_option_plus_one(value + captured); } + + + x.field.map(|value| do_nothing(value + captured)); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } + + x.field.map(|value| { do_nothing(value + captured) }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } + + x.field.map(|value| { do_nothing(value + captured); }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } + + x.field.map(|value| { { do_nothing(value + captured); } }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } + + + x.field.map(|value| diverge(value + captured)); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } + + x.field.map(|value| { diverge(value + captured) }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } + + x.field.map(|value| { diverge(value + captured); }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } + + x.field.map(|value| { { diverge(value + captured); } }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } + + + x.field.map(|value| plus_one(value + captured)); + x.field.map(|value| { plus_one(value + captured) }); + x.field.map(|value| { let y = plus_one(value + captured); }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { let y = plus_one(value + captured); } + + x.field.map(|value| { plus_one(value + captured); }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { plus_one(value + captured); } + + x.field.map(|value| { { plus_one(value + captured); } }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { plus_one(value + captured); } + + + x.field.map(|ref value| { do_nothing(value + captured) }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(ref value) = x.field { do_nothing(value + captured) } + + + // closures with multiple statements are not linted: + x.field.map(|value| { do_nothing(value); do_nothing(value) }); } -- cgit 1.4.1-3-g733a5 From 2f52d1d568913f32a6bd24affeeb5ec594061a3c Mon Sep 17 00:00:00 2001 From: Phil Turnbull Date: Sun, 22 Jan 2017 16:42:57 -0500 Subject: Return Spans instead of Cow<&str>'s --- clippy_lints/src/map_nil_fn.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index 4423aeece6f..4c85b3d8e7f 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::ty; -use std::borrow::Cow; +use syntax::codemap::Span; use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use utils::paths; @@ -72,7 +72,7 @@ fn is_nil_expression(cx: &LateContext, expr: &hir::Expr) -> bool { // semicolons, which causes problems when generating a suggestion. Given an // expression that evaluates to '()' or '!', recursively remove useless braces // and semi-colons until is suitable for including in the suggestion template -fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option> { +fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { if !is_nil_expression(cx, expr) { return None; } @@ -81,7 +81,7 @@ fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { // Calls can't be reduced any more - Some(snippet(cx, expr.span, "_")) + Some(expr.span) }, hir::ExprBlock(ref block) => { match (&block.stmts[..], block.expr.as_ref()) { @@ -92,8 +92,8 @@ fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { // Reduce `{ X; }` to `X` or `X;` match inner_stmt.node { - hir::StmtDecl(ref d, _) => Some(snippet(cx, d.span, "_")), - hir::StmtExpr(ref e, _) => Some(snippet(cx, e.span, "_")), + hir::StmtDecl(ref d, _) => Some(d.span), + hir::StmtExpr(ref e, _) => Some(e.span), hir::StmtSemi(ref e, _) => { if is_nil_expression(cx, e) { // `X` returns nil so we can strip the @@ -102,7 +102,7 @@ fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option(cx: &LateContext, expr: &'a hir::Expr) -> Option( - cx: &LateContext<'a, 'tcx>, - expr: &'a hir::Expr -) -> Option<(Cow<'a, str>, Cow<'a, str>)> { +fn reduce_nil_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(Span, Span)> { if let hir::ExprClosure(_, ref decl, inner_expr_id, _) = expr.node { let body = cx.tcx.map.body(inner_expr_id); if_let_chain! {[ decl.inputs.len() == 1, let Some(binding) = iter_input_pats(&decl, body).next(), - let Some(expr_snippet) = reduce_nil_expression(cx, &body.value), + let Some(expr_span) = reduce_nil_expression(cx, &body.value), ], { - let binding_snippet = snippet(cx, binding.pat.span, "_"); - return Some((binding_snippet, expr_snippet)); + return Some((binding.pat.span, expr_span)) }} } None @@ -152,12 +148,12 @@ fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_arg expr.span, msg, |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); - } else if let Some((binding_snippet, expr_snippet)) = reduce_nil_closure(cx, fn_arg) { + } else if let Some((binding_span, expr_span)) = reduce_nil_closure(cx, fn_arg) { let msg = "called `map(f)` on an Option value where `f` is a nil closure"; let suggestion = format!("if let Some({0}) = {1} {{ {2} }}", - binding_snippet, + snippet(cx, binding_span, "_"), snippet(cx, var_arg.span, "_"), - expr_snippet); + snippet(cx, expr_span, "_")); span_lint_and_then(cx, OPTION_MAP_NIL_FN, -- cgit 1.4.1-3-g733a5 From d0bdfe5ce303ded6b499e60bf4e4d4756b85939f Mon Sep 17 00:00:00 2001 From: Phil Turnbull Date: Sun, 22 Jan 2017 20:57:17 -0500 Subject: Handle non-trivial nil closures `reduce_nil_closure` mixed together a) 'is this a nil closure?' and b) 'can it be reduced to a simple expression?'. Split the logic into two functions so we can still generate a basic warning when the closure can't be simplified. --- clippy_lints/src/map_nil_fn.rs | 25 ++++++++++++++++--------- clippy_lints/src/misc.rs | 22 ++++++++++++---------- tests/compile-fail/map_nil_fn.rs | 9 ++++++++- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index 4c85b3d8e7f..cc998ad00ee 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -14,7 +14,7 @@ pub struct Pass; /// **Why is this bad?** Readability, this can be written more clearly with /// an if statement /// -/// **Known problems:** Closures with multiple statements are not handled +/// **Known problems:** None. /// /// **Example:** /// ```rust @@ -114,16 +114,17 @@ fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(Span, Span)> { +fn nil_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { if let hir::ExprClosure(_, ref decl, inner_expr_id, _) = expr.node { let body = cx.tcx.map.body(inner_expr_id); + let body_expr = &body.value; if_let_chain! {[ decl.inputs.len() == 1, + is_nil_expression(cx, body_expr), let Some(binding) = iter_input_pats(&decl, body).next(), - let Some(expr_span) = reduce_nil_expression(cx, &body.value), ], { - return Some((binding.pat.span, expr_span)) + return Some((binding, body_expr)) }} } None @@ -148,12 +149,18 @@ fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_arg expr.span, msg, |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); - } else if let Some((binding_span, expr_span)) = reduce_nil_closure(cx, fn_arg) { + } else if let Some((binding, closure_expr)) = nil_closure(cx, fn_arg) { let msg = "called `map(f)` on an Option value where `f` is a nil closure"; - let suggestion = format!("if let Some({0}) = {1} {{ {2} }}", - snippet(cx, binding_span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, expr_span, "_")); + let suggestion = if let Some(expr_span) = reduce_nil_expression(cx, closure_expr) { + format!("if let Some({0}) = {1} {{ {2} }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, expr_span, "_")) + } else { + format!("if let Some({0}) = {1} {{ ... }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")) + }; span_lint_and_then(cx, OPTION_MAP_NIL_FN, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e9b6865f0c9..ba2c20db087 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -432,16 +432,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { - path.segments.last().map(|seg| { - if seg.name == "NAN" { - span_lint( - cx, - CMP_NAN, - expr.span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", - ); - } - }); + if let Some(seg) = path.segments.last() { + path.segments.last().map(|seg| { + if seg.name == "NAN" { + span_lint( + cx, + CMP_NAN, + expr.span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", + ); + } + }); + } } } diff --git a/tests/compile-fail/map_nil_fn.rs b/tests/compile-fail/map_nil_fn.rs index 5ac3913466a..b580e53c9d8 100644 --- a/tests/compile-fail/map_nil_fn.rs +++ b/tests/compile-fail/map_nil_fn.rs @@ -130,6 +130,13 @@ fn main() { //~| SUGGESTION if let Some(ref value) = x.field { do_nothing(value + captured) } - // closures with multiple statements are not linted: x.field.map(|value| { do_nothing(value); do_nothing(value) }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { ... } + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure + //~| HELP try this + //~| SUGGESTION if let Some(value) = x.field { ... } } -- cgit 1.4.1-3-g733a5 From 991a30237a5cb8d711e8545a8d6ea93ccae9ad5c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 8 Apr 2018 09:48:49 +0200 Subject: Make it compile again --- clippy_lints/src/map_nil_fn.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index cc998ad00ee..13ac1fe2294 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -56,8 +56,8 @@ fn is_nil_type(ty: ty::Ty) -> bool { fn is_nil_function(cx: &LateContext, expr: &hir::Expr) -> bool { let ty = cx.tables.expr_ty(expr); - if let ty::TyFnDef(_, _, bare) = ty.sty { - if let Some(fn_type) = cx.tcx.no_late_bound_regions(&bare.sig) { + if let ty::TyFnDef(id, _) = ty.sty { + if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { return is_nil_type(fn_type.output()); } } @@ -115,17 +115,18 @@ fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { - if let hir::ExprClosure(_, ref decl, inner_expr_id, _) = expr.node { - let body = cx.tcx.map.body(inner_expr_id); + if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { + let body = cx.tcx.hir.body(inner_expr_id); let body_expr = &body.value; - if_let_chain! {[ - decl.inputs.len() == 1, - is_nil_expression(cx, body_expr), - let Some(binding) = iter_input_pats(&decl, body).next(), - ], { - return Some((binding, body_expr)) - }} + if_chain! { + if decl.inputs.len() == 1; + if is_nil_expression(cx, body_expr); + if let Some(binding) = iter_input_pats(&decl, body).next(); + then { + return Some((binding, body_expr)); + } + } } None } @@ -172,7 +173,7 @@ fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_arg impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { - if in_macro(cx, stmt.span) { + if in_macro(stmt.span) { return; } -- cgit 1.4.1-3-g733a5 From ca60e8a2a0c59b53c12efa9b1011cac99185aa59 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 8 Apr 2018 10:41:51 +0200 Subject: Cleanup misc::check_nan This was a bit messed up after a bigger rebase. --- clippy_lints/src/misc.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index ba2c20db087..797a871d72b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -433,16 +433,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { if let Some(seg) = path.segments.last() { - path.segments.last().map(|seg| { - if seg.name == "NAN" { - span_lint( - cx, - CMP_NAN, - expr.span, - "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", + if seg.name == "NAN" { + span_lint( + cx, + CMP_NAN, + expr.span, + "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", ); - } - }); + } } } } -- cgit 1.4.1-3-g733a5 From fbd71f901fc8ea324fdf3cf75f35e4ce587425ec Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 9 Apr 2018 07:54:08 +0200 Subject: Use declare_clippy_lint and 'complexity' category --- clippy_lints/src/map_nil_fn.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs index 13ac1fe2294..b72c0a01eda 100644 --- a/clippy_lints/src/map_nil_fn.rs +++ b/clippy_lints/src/map_nil_fn.rs @@ -32,9 +32,9 @@ pub struct Pass; /// log_err_msg(format_msg(msg)) /// } /// ``` -declare_lint! { +declare_clippy_lint! { pub OPTION_MAP_NIL_FN, - Allow, + complexity, "using `Option.map(f)`, where f is a nil function or closure" } -- cgit 1.4.1-3-g733a5 From a3ff21f4d6a957e337e46d43da4e7f45d80e1504 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 9 Apr 2018 08:19:40 +0200 Subject: Rename lint to option_map_unit_fn Rust does not have nil. --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/map_nil_fn.rs | 188 -------------------------------- clippy_lints/src/option_map_unit_fn.rs | 191 +++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 192 deletions(-) delete mode 100644 clippy_lints/src/map_nil_fn.rs create mode 100644 clippy_lints/src/option_map_unit_fn.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 14438edcb98..0065ae1a0af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -705,7 +705,7 @@ All notable changes to this project will be documented in this file. [`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options [`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect -[`option_map_nil_fn`]: https://github.com/Manishearth/rust-clippy/wiki#option_map_nil_fn +[`option_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unit_fn [`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref [`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 755fc26bc9b..87781e4e5f7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -145,7 +145,7 @@ pub mod lifetimes; pub mod literal_representation; pub mod loops; pub mod map_clone; -pub mod map_nil_fn; +pub mod option_map_unit_fn; pub mod matches; pub mod mem_forget; pub mod methods; @@ -406,7 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); - reg.register_late_lint_pass(box map_nil_fn::Pass); + reg.register_late_lint_pass(box option_map_unit_fn::Pass); reg.register_lint_group("clippy_restriction", vec![ @@ -443,7 +443,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, - map_nil_fn::OPTION_MAP_NIL_FN, + option_map_unit_fn::OPTION_MAP_UNIT_FN, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, diff --git a/clippy_lints/src/map_nil_fn.rs b/clippy_lints/src/map_nil_fn.rs deleted file mode 100644 index b72c0a01eda..00000000000 --- a/clippy_lints/src/map_nil_fn.rs +++ /dev/null @@ -1,188 +0,0 @@ -use rustc::hir; -use rustc::lint::*; -use rustc::ty; -use syntax::codemap::Span; -use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; -use utils::paths; - -#[derive(Clone)] -pub struct Pass; - -/// **What it does:** Checks for usage of `Option.map(f)` where f is a nil -/// function or closure -/// -/// **Why is this bad?** Readability, this can be written more clearly with -/// an if statement -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let x : Option<&str> = do_stuff(); -/// x.map(log_err_msg); -/// x.map(|msg| log_err_msg(format_msg(msg))) -/// ``` -/// The correct use would be: -/// ```rust -/// let x : Option<&str> = do_stuff(); -/// if let Some(msg) = x { -/// log_err_msg(msg) -/// } -/// if let Some(msg) = x { -/// log_err_msg(format_msg(msg)) -/// } -/// ``` -declare_clippy_lint! { - pub OPTION_MAP_NIL_FN, - complexity, - "using `Option.map(f)`, where f is a nil function or closure" -} - - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(OPTION_MAP_NIL_FN) - } -} - -fn is_nil_type(ty: ty::Ty) -> bool { - match ty.sty { - ty::TyTuple(slice) => slice.is_empty(), - ty::TyNever => true, - _ => false, - } -} - -fn is_nil_function(cx: &LateContext, expr: &hir::Expr) -> bool { - let ty = cx.tables.expr_ty(expr); - - if let ty::TyFnDef(id, _) = ty.sty { - if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { - return is_nil_type(fn_type.output()); - } - } - false -} - -fn is_nil_expression(cx: &LateContext, expr: &hir::Expr) -> bool { - is_nil_type(cx.tables.expr_ty(expr)) -} - -// The expression inside a closure may or may not have surrounding braces and -// semicolons, which causes problems when generating a suggestion. Given an -// expression that evaluates to '()' or '!', recursively remove useless braces -// and semi-colons until is suitable for including in the suggestion template -fn reduce_nil_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { - if !is_nil_expression(cx, expr) { - return None; - } - - match expr.node { - hir::ExprCall(_, _) | - hir::ExprMethodCall(_, _, _) => { - // Calls can't be reduced any more - Some(expr.span) - }, - hir::ExprBlock(ref block) => { - match (&block.stmts[..], block.expr.as_ref()) { - (&[], Some(inner_expr)) => { - // Reduce `{ X }` to `X` - reduce_nil_expression(cx, inner_expr) - }, - (&[ref inner_stmt], None) => { - // Reduce `{ X; }` to `X` or `X;` - match inner_stmt.node { - hir::StmtDecl(ref d, _) => Some(d.span), - hir::StmtExpr(ref e, _) => Some(e.span), - hir::StmtSemi(ref e, _) => { - if is_nil_expression(cx, e) { - // `X` returns nil so we can strip the - // semicolon and reduce further - reduce_nil_expression(cx, e) - } else { - // `X` doesn't return nil so it needs a - // trailing semicolon - Some(inner_stmt.span) - } - }, - } - }, - _ => None, - } - }, - _ => None, - } -} - -fn nil_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { - if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { - let body = cx.tcx.hir.body(inner_expr_id); - let body_expr = &body.value; - - if_chain! { - if decl.inputs.len() == 1; - if is_nil_expression(cx, body_expr); - if let Some(binding) = iter_input_pats(&decl, body).next(); - then { - return Some((binding, body_expr)); - } - } - } - None -} - -fn lint_map_nil_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { - let var_arg = &map_args[0]; - let fn_arg = &map_args[1]; - - if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { - return; - } - - if is_nil_function(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a nil function"; - let suggestion = format!("if let Some(...) = {0} {{ {1}(...) }}", - snippet(cx, var_arg.span, "_"), - snippet(cx, fn_arg.span, "_")); - - span_lint_and_then(cx, - OPTION_MAP_NIL_FN, - expr.span, - msg, - |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); - } else if let Some((binding, closure_expr)) = nil_closure(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a nil closure"; - let suggestion = if let Some(expr_span) = reduce_nil_expression(cx, closure_expr) { - format!("if let Some({0}) = {1} {{ {2} }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, expr_span, "_")) - } else { - format!("if let Some({0}) = {1} {{ ... }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")) - }; - - span_lint_and_then(cx, - OPTION_MAP_NIL_FN, - expr.span, - msg, - |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { - if in_macro(stmt.span) { - return; - } - - if let hir::StmtSemi(ref expr, _) = stmt.node { - if let hir::ExprMethodCall(_, _, _) = expr.node { - if let Some(arglists) = method_chain_args(expr, &["map"]) { - lint_map_nil_fn(cx, stmt, expr, arglists[0]); - } - } - } - } -} diff --git a/clippy_lints/src/option_map_unit_fn.rs b/clippy_lints/src/option_map_unit_fn.rs new file mode 100644 index 00000000000..df3c78a344b --- /dev/null +++ b/clippy_lints/src/option_map_unit_fn.rs @@ -0,0 +1,191 @@ +use rustc::hir; +use rustc::lint::*; +use rustc::ty; +use syntax::codemap::Span; +use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; +use utils::paths; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for usage of `Option.map(f)` where f is a function +/// or closure that returns the unit type. +/// +/// **Why is this bad?** Readability, this can be written more clearly with +/// an if statement +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// let x : Option<&str> = do_stuff(); +/// x.map(log_err_msg); +/// x.map(|msg| log_err_msg(format_msg(msg))) +/// ``` +/// +/// The correct use would be: +/// +/// ```rust +/// let x : Option<&str> = do_stuff(); +/// if let Some(msg) = x { +/// log_err_msg(msg) +/// } +/// if let Some(msg) = x { +/// log_err_msg(format_msg(msg)) +/// } +/// ``` +declare_clippy_lint! { + pub OPTION_MAP_UNIT_FN, + complexity, + "using `Option.map(f)`, where f is a function or closure that returns ()" +} + + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(OPTION_MAP_UNIT_FN) + } +} + +fn is_unit_type(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyTuple(slice) => slice.is_empty(), + ty::TyNever => true, + _ => false, + } +} + +fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool { + let ty = cx.tables.expr_ty(expr); + + if let ty::TyFnDef(id, _) = ty.sty { + if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { + return is_unit_type(fn_type.output()); + } + } + false +} + +fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool { + is_unit_type(cx.tables.expr_ty(expr)) +} + +/// The expression inside a closure may or may not have surrounding braces and +/// semicolons, which causes problems when generating a suggestion. Given an +/// expression that evaluates to '()' or '!', recursively remove useless braces +/// and semi-colons until is suitable for including in the suggestion template +fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { + if !is_unit_expression(cx, expr) { + return None; + } + + match expr.node { + hir::ExprCall(_, _) | + hir::ExprMethodCall(_, _, _) => { + // Calls can't be reduced any more + Some(expr.span) + }, + hir::ExprBlock(ref block) => { + match (&block.stmts[..], block.expr.as_ref()) { + (&[], Some(inner_expr)) => { + // Reduce `{ X }` to `X` + reduce_unit_expression(cx, inner_expr) + }, + (&[ref inner_stmt], None) => { + // Reduce `{ X; }` to `X` or `X;` + match inner_stmt.node { + hir::StmtDecl(ref d, _) => Some(d.span), + hir::StmtExpr(ref e, _) => Some(e.span), + hir::StmtSemi(ref e, _) => { + if is_unit_expression(cx, e) { + // `X` returns unit so we can strip the + // semicolon and reduce further + reduce_unit_expression(cx, e) + } else { + // `X` doesn't return unit so it needs a + // trailing semicolon + Some(inner_stmt.span) + } + }, + } + }, + _ => None, + } + }, + _ => None, + } +} + +fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { + if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { + let body = cx.tcx.hir.body(inner_expr_id); + let body_expr = &body.value; + + if_chain! { + if decl.inputs.len() == 1; + if is_unit_expression(cx, body_expr); + if let Some(binding) = iter_input_pats(&decl, body).next(); + then { + return Some((binding, body_expr)); + } + } + } + None +} + +fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { + let var_arg = &map_args[0]; + let fn_arg = &map_args[1]; + + if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + return; + } + + if is_unit_function(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a unit function"; + let suggestion = format!("if let Some(...) = {0} {{ {1}(...) }}", + snippet(cx, var_arg.span, "_"), + snippet(cx, fn_arg.span, "_")); + + span_lint_and_then(cx, + OPTION_MAP_UNIT_FN, + expr.span, + msg, + |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a unit closure"; + let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { + format!("if let Some({0}) = {1} {{ {2} }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, expr_span, "_")) + } else { + format!("if let Some({0}) = {1} {{ ... }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")) + }; + + span_lint_and_then(cx, + OPTION_MAP_UNIT_FN, + expr.span, + msg, + |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { + if in_macro(stmt.span) { + return; + } + + if let hir::StmtSemi(ref expr, _) = stmt.node { + if let hir::ExprMethodCall(_, _, _) = expr.node { + if let Some(arglists) = method_chain_args(expr, &["map"]) { + lint_map_unit_fn(cx, stmt, expr, arglists[0]); + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From bcc335fc9cb56aaef9f824322f1288c149ac9afd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 9 Apr 2018 08:20:46 +0200 Subject: Move test to new UI test system --- tests/compile-fail/map_nil_fn.rs | 142 --------------------------------- tests/ui/option_map_unit_fn.rs | 81 +++++++++++++++++++ tests/ui/option_map_unit_fn.stderr | 156 +++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 142 deletions(-) delete mode 100644 tests/compile-fail/map_nil_fn.rs create mode 100644 tests/ui/option_map_unit_fn.rs create mode 100644 tests/ui/option_map_unit_fn.stderr diff --git a/tests/compile-fail/map_nil_fn.rs b/tests/compile-fail/map_nil_fn.rs deleted file mode 100644 index b580e53c9d8..00000000000 --- a/tests/compile-fail/map_nil_fn.rs +++ /dev/null @@ -1,142 +0,0 @@ -#![feature(plugin)] -#![feature(const_fn)] -#![plugin(clippy)] - -#![deny(clippy_pedantic)] -#![allow(unused, missing_docs_in_private_items)] - -fn do_nothing(_: T) {} - -fn diverge(_: T) -> ! { - panic!() -} - -fn plus_one(value: usize) -> usize { - value + 1 -} - -struct HasOption { - field: Option, -} - -impl HasOption { - fn do_option_nothing(self: &HasOption, value: usize) {} - - fn do_option_plus_one(self: &HasOption, value: usize) -> usize { - value + 1 - } -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn main() { - let x = HasOption { field: Some(10) }; - - x.field.map(plus_one); - let _ : Option<()> = x.field.map(do_nothing); - - x.field.map(do_nothing); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil function - //~| HELP try this - //~| SUGGESTION if let Some(...) = x.field { do_nothing(...) } - - x.field.map(do_nothing); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil function - //~| HELP try this - //~| SUGGESTION if let Some(...) = x.field { do_nothing(...) } - - x.field.map(diverge); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil function - //~| HELP try this - //~| SUGGESTION if let Some(...) = x.field { diverge(...) } - - let captured = 10; - if let Some(value) = x.field { do_nothing(value + captured) }; - let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); - - x.field.map(|value| x.do_option_nothing(value + captured)); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { x.do_option_nothing(value + captured) } - - x.field.map(|value| { x.do_option_plus_one(value + captured); }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { x.do_option_plus_one(value + captured); } - - - x.field.map(|value| do_nothing(value + captured)); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } - - x.field.map(|value| { do_nothing(value + captured) }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } - - x.field.map(|value| { do_nothing(value + captured); }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } - - x.field.map(|value| { { do_nothing(value + captured); } }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { do_nothing(value + captured) } - - - x.field.map(|value| diverge(value + captured)); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } - - x.field.map(|value| { diverge(value + captured) }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } - - x.field.map(|value| { diverge(value + captured); }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } - - x.field.map(|value| { { diverge(value + captured); } }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { diverge(value + captured) } - - - x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| { plus_one(value + captured) }); - x.field.map(|value| { let y = plus_one(value + captured); }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { let y = plus_one(value + captured); } - - x.field.map(|value| { plus_one(value + captured); }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { plus_one(value + captured); } - - x.field.map(|value| { { plus_one(value + captured); } }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { plus_one(value + captured); } - - - x.field.map(|ref value| { do_nothing(value + captured) }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(ref value) = x.field { do_nothing(value + captured) } - - - x.field.map(|value| { do_nothing(value); do_nothing(value) }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { ... } - - x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - //~^ ERROR called `map(f)` on an Option value where `f` is a nil closure - //~| HELP try this - //~| SUGGESTION if let Some(value) = x.field { ... } -} diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs new file mode 100644 index 00000000000..97182764e0d --- /dev/null +++ b/tests/ui/option_map_unit_fn.rs @@ -0,0 +1,81 @@ +#![warn(option_map_unit_fn)] +#![allow(unused)] + +fn do_nothing(_: T) {} + +fn diverge(_: T) -> ! { + panic!() +} + +fn plus_one(value: usize) -> usize { + value + 1 +} + +struct HasOption { + field: Option, +} + +impl HasOption { + fn do_option_nothing(self: &Self, value: usize) {} + + fn do_option_plus_one(self: &Self, value: usize) -> usize { + value + 1 + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn main() { + let x = HasOption { field: Some(10) }; + + x.field.map(plus_one); + let _ : Option<()> = x.field.map(do_nothing); + + x.field.map(do_nothing); + + x.field.map(do_nothing); + + x.field.map(diverge); + + let captured = 10; + if let Some(value) = x.field { do_nothing(value + captured) }; + let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); + + x.field.map(|value| x.do_option_nothing(value + captured)); + + x.field.map(|value| { x.do_option_plus_one(value + captured); }); + + + x.field.map(|value| do_nothing(value + captured)); + + x.field.map(|value| { do_nothing(value + captured) }); + + x.field.map(|value| { do_nothing(value + captured); }); + + x.field.map(|value| { { do_nothing(value + captured); } }); + + + x.field.map(|value| diverge(value + captured)); + + x.field.map(|value| { diverge(value + captured) }); + + x.field.map(|value| { diverge(value + captured); }); + + x.field.map(|value| { { diverge(value + captured); } }); + + + x.field.map(|value| plus_one(value + captured)); + x.field.map(|value| { plus_one(value + captured) }); + x.field.map(|value| { let y = plus_one(value + captured); }); + + x.field.map(|value| { plus_one(value + captured); }); + + x.field.map(|value| { { plus_one(value + captured); } }); + + + x.field.map(|ref value| { do_nothing(value + captured) }); + + + x.field.map(|value| { do_nothing(value); do_nothing(value) }); + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +} diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr new file mode 100644 index 00000000000..ee0945d9503 --- /dev/null +++ b/tests/ui/option_map_unit_fn.stderr @@ -0,0 +1,156 @@ +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:33:5 + | +33 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(...) = x.field { do_nothing(...) }` + | + = note: `-D option-map-unit-fn` implied by `-D warnings` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:35:5 + | +35 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(...) = x.field { do_nothing(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:37:5 + | +37 | x.field.map(diverge); + | ^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(...) = x.field { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:43:5 + | +43 | x.field.map(|value| x.do_option_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:45:5 + | +45 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:48:5 + | +48 | x.field.map(|value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:50:5 + | +50 | x.field.map(|value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:52:5 + | +52 | x.field.map(|value| { do_nothing(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:54:5 + | +54 | x.field.map(|value| { { do_nothing(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:57:5 + | +57 | x.field.map(|value| diverge(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:59:5 + | +59 | x.field.map(|value| { diverge(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:61:5 + | +61 | x.field.map(|value| { diverge(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:63:5 + | +63 | x.field.map(|value| { { diverge(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:68:5 + | +68 | x.field.map(|value| { let y = plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:70:5 + | +70 | x.field.map(|value| { plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:72:5 + | +72 | x.field.map(|value| { { plus_one(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:75:5 + | +75 | x.field.map(|ref value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:78:5 + | +78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:80:5 + | +80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: aborting due to 19 previous errors + -- cgit 1.4.1-3-g733a5 From db60c67c5be3b7f2ceb24ba96c4eecb5015ec09b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 9 Apr 2018 08:33:57 +0200 Subject: Allow new lint in ui/eta.rs --- tests/ui/eta.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index e6fad3bb777..be84f44bfb1 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,6 +1,6 @@ -#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value)] +#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value, option_map_unit_fn)] #![warn(redundant_closure, needless_borrow)] fn main() { -- cgit 1.4.1-3-g733a5 From 7de707fdba126dfb1bea7c97ef5e18c9a879b799 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 10 Apr 2018 22:13:58 +0200 Subject: Remove further semicolon reduction --- clippy_lints/src/option_map_unit_fn.rs | 12 +----------- tests/ui/option_map_unit_fn.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/option_map_unit_fn.rs b/clippy_lints/src/option_map_unit_fn.rs index df3c78a344b..b383f54993c 100644 --- a/clippy_lints/src/option_map_unit_fn.rs +++ b/clippy_lints/src/option_map_unit_fn.rs @@ -97,17 +97,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option Some(d.span), hir::StmtExpr(ref e, _) => Some(e.span), - hir::StmtSemi(ref e, _) => { - if is_unit_expression(cx, e) { - // `X` returns unit so we can strip the - // semicolon and reduce further - reduce_unit_expression(cx, e) - } else { - // `X` doesn't return unit so it needs a - // trailing semicolon - Some(inner_stmt.span) - } - }, + hir::StmtSemi(_, _) => Some(inner_stmt.span), } }, _ => None, diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index ee0945d9503..84dedf9cd60 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -62,7 +62,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure 52 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:54:5 @@ -70,7 +70,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure 54 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:57:5 @@ -94,7 +94,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure 61 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:63:5 @@ -102,7 +102,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure 63 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:68:5 -- cgit 1.4.1-3-g733a5 From d87385b4065d3fd319b5c61e9e2719325eb87f0e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 15 Apr 2018 11:35:20 +0200 Subject: Use approximate_suggestion for non-reducible closures --- clippy_lints/src/option_map_unit_fn.rs | 52 +++++++++++++++++++++++----------- tests/ui/option_map_unit_fn.rs | 8 ++++++ tests/ui/option_map_unit_fn.stderr | 24 +++++++++++++++- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/option_map_unit_fn.rs b/clippy_lints/src/option_map_unit_fn.rs index b383f54993c..799576d01b0 100644 --- a/clippy_lints/src/option_map_unit_fn.rs +++ b/clippy_lints/src/option_map_unit_fn.rs @@ -89,18 +89,27 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { match (&block.stmts[..], block.expr.as_ref()) { (&[], Some(inner_expr)) => { - // Reduce `{ X }` to `X` + // If block only contains an expression, + // reduce `{ X }` to `X` reduce_unit_expression(cx, inner_expr) }, (&[ref inner_stmt], None) => { - // Reduce `{ X; }` to `X` or `X;` + // If block only contains statements, + // reduce `{ X; }` to `X` or `X;` match inner_stmt.node { hir::StmtDecl(ref d, _) => Some(d.span), hir::StmtExpr(ref e, _) => Some(e.span), hir::StmtSemi(_, _) => Some(inner_stmt.span), } }, - _ => None, + _ => { + // For closures that contain multiple statements + // it's difficult to get a correct suggestion span + // for all cases (multi-line closures specifically) + // + // We do not attempt to build a suggestion for those right now. + None + } } }, _ => None, @@ -142,25 +151,36 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar OPTION_MAP_UNIT_FN, expr.span, msg, - |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + |db| { db.span_approximate_suggestion(stmt.span, "try this", suggestion); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = "called `map(f)` on an Option value where `f` is a unit closure"; + + enum Suggestion { + Full(String), + Approx(String) + } + let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { - format!("if let Some({0}) = {1} {{ {2} }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, expr_span, "_")) + Suggestion::Full( + format!("if let Some({0}) = {1} {{ {2} }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, expr_span, "_")) + ) } else { - format!("if let Some({0}) = {1} {{ ... }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")) + Suggestion::Approx( + format!("if let Some({0}) = {1} {{ ... }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")) + ) }; - span_lint_and_then(cx, - OPTION_MAP_UNIT_FN, - expr.span, - msg, - |db| { db.span_suggestion(stmt.span, "try this", suggestion); }); + span_lint_and_then(cx, OPTION_MAP_UNIT_FN, expr.span, msg, |db| { + match suggestion { + Suggestion::Full(sugg) => db.span_suggestion(stmt.span, "try this", sugg), + Suggestion::Approx(sugg) => db.span_approximate_suggestion(stmt.span, "try this", sugg), + }; + }); } } diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index 97182764e0d..595f65d2bbb 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -78,4 +78,12 @@ fn main() { x.field.map(|value| { do_nothing(value); do_nothing(value) }); x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + + // Suggestion for the let block should be `{ ... }` as it's too difficult to build a + // proper suggestion for these cases + x.field.map(|value| { + do_nothing(value); + do_nothing(value) + }); + x.field.map(|value| { do_nothing(value); do_nothing(value); }); } diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 84dedf9cd60..10320a5a920 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -152,5 +152,27 @@ error: called `map(f)` on an Option value where `f` is a unit closure | | | help: try this: `if let Some(value) = x.field { ... }` -error: aborting due to 19 previous errors +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:84:5 + | +84 | x.field.map(|value| { + | _____^ + | |_____| + | || +85 | || do_nothing(value); +86 | || do_nothing(value) +87 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/option_map_unit_fn.rs:88:5 + | +88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: aborting due to 21 previous errors -- cgit 1.4.1-3-g733a5 From d54f70f1f6ae6fa571117e3db30040620e2890a1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 15 Apr 2018 11:37:35 +0200 Subject: Generate let binding variable name for some cases Given a map call like `x.field.map ...` the suggestion will contain: `if let Some(x_field) ...` Given a map call like `x.map ...` the suggestion will contain: `if let Some(_x) ...` Otherwise it will suggest: `if let Some(_) ...` --- clippy_lints/src/option_map_unit_fn.rs | 17 +++++++++++++- tests/ui/option_map_unit_fn.rs | 9 ++++++++ tests/ui/option_map_unit_fn.stderr | 42 ++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/option_map_unit_fn.rs b/clippy_lints/src/option_map_unit_fn.rs index 799576d01b0..abbeaabbdb2 100644 --- a/clippy_lints/src/option_map_unit_fn.rs +++ b/clippy_lints/src/option_map_unit_fn.rs @@ -133,6 +133,20 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op None } +/// Builds a name for the let binding variable (var_arg) +/// +/// `x.field` => `x_field` +/// `y` => `_y` +/// +/// Anything else will return `_`. +fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { + match &var_arg.node { + hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), + hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")), + _ => "_".to_string() + } +} + fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { let var_arg = &map_args[0]; let fn_arg = &map_args[1]; @@ -143,7 +157,8 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar if is_unit_function(cx, fn_arg) { let msg = "called `map(f)` on an Option value where `f` is a unit function"; - let suggestion = format!("if let Some(...) = {0} {{ {1}(...) }}", + let suggestion = format!("if let Some({0}) = {1} {{ {2}(...) }}", + let_binding_name(cx, var_arg), snippet(cx, var_arg.span, "_"), snippet(cx, fn_arg.span, "_")); diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index 595f65d2bbb..d9cfc62a51f 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -86,4 +86,13 @@ fn main() { do_nothing(value) }); x.field.map(|value| { do_nothing(value); do_nothing(value); }); + + // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let variable name for them + Some(42).map(diverge); + "12".parse::().ok().map(diverge); + Some(plus_one(1)).map(do_nothing); + + // Should suggest `if let Some(_y) ...` to not override the existing foo variable + let y = Some(42); + y.map(do_nothing); } diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 10320a5a920..bd19fe05329 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -4,7 +4,7 @@ error: called `map(f)` on an Option value where `f` is a unit function 33 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(...) = x.field { do_nothing(...) }` + | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` | = note: `-D option-map-unit-fn` implied by `-D warnings` @@ -14,7 +14,7 @@ error: called `map(f)` on an Option value where `f` is a unit function 35 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(...) = x.field { do_nothing(...) }` + | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function --> $DIR/option_map_unit_fn.rs:37:5 @@ -22,7 +22,7 @@ error: called `map(f)` on an Option value where `f` is a unit function 37 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(...) = x.field { diverge(...) }` + | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:43:5 @@ -164,7 +164,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure 87 | || }); | ||______^- help: try this: `if let Some(value) = x.field { ... }` | |_______| - | + | error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:88:5 @@ -174,5 +174,37 @@ error: called `map(f)` on an Option value where `f` is a unit closure | | | help: try this: `if let Some(value) = x.field { ... }` -error: aborting due to 21 previous errors +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:91:5 + | +91 | Some(42).map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(42) { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:92:5 + | +92 | "12".parse::().ok().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:93:5 + | +93 | Some(plus_one(1)).map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/option_map_unit_fn.rs:97:5 + | +97 | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_y) = y { do_nothing(...) }` + +error: aborting due to 25 previous errors -- cgit 1.4.1-3-g733a5 From 8307a899e994cf87821547b40ed67dae38a81bee Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 15 Apr 2018 12:30:38 +0200 Subject: Rename option_map_unit_fn to map_unit_fn --- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/map_unit_fn.rs | 216 +++++++++++++++++++++++++++++++++ clippy_lints/src/option_map_unit_fn.rs | 216 --------------------------------- tests/ui/map_unit_fn.stderr | 210 ++++++++++++++++++++++++++++++++ tests/ui/option_map_unit_fn.rs | 6 +- tests/ui/option_map_unit_fn.stderr | 106 ++++++++-------- 6 files changed, 486 insertions(+), 274 deletions(-) create mode 100644 clippy_lints/src/map_unit_fn.rs delete mode 100644 clippy_lints/src/option_map_unit_fn.rs create mode 100644 tests/ui/map_unit_fn.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 87781e4e5f7..afad923a35a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -145,7 +145,7 @@ pub mod lifetimes; pub mod literal_representation; pub mod loops; pub mod map_clone; -pub mod option_map_unit_fn; +pub mod map_unit_fn; pub mod matches; pub mod mem_forget; pub mod methods; @@ -406,7 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); - reg.register_late_lint_pass(box option_map_unit_fn::Pass); + reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_lint_group("clippy_restriction", vec![ @@ -443,7 +443,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, - option_map_unit_fn::OPTION_MAP_UNIT_FN, + map_unit_fn::OPTION_MAP_UNIT_FN, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs new file mode 100644 index 00000000000..97ff1141986 --- /dev/null +++ b/clippy_lints/src/map_unit_fn.rs @@ -0,0 +1,216 @@ +use rustc::hir; +use rustc::lint::*; +use rustc::ty; +use syntax::codemap::Span; +use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; +use utils::paths; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for usage of `Option.map(f)` where f is a function +/// or closure that returns the unit type. +/// +/// **Why is this bad?** Readability, this can be written more clearly with +/// an if statement +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// let x: Option<&str> = do_stuff(); +/// x.map(log_err_msg); +/// x.map(|msg| log_err_msg(format_msg(msg))) +/// ``` +/// +/// The correct use would be: +/// +/// ```rust +/// let x: Option<&str> = do_stuff(); +/// if let Some(msg) = x { +/// log_err_msg(msg) +/// } +/// if let Some(msg) = x { +/// log_err_msg(format_msg(msg)) +/// } +/// ``` +declare_clippy_lint! { + pub OPTION_MAP_UNIT_FN, + complexity, + "using `Option.map(f)`, where f is a function or closure that returns ()" +} + + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(OPTION_MAP_UNIT_FN) + } +} + +fn is_unit_type(ty: ty::Ty) -> bool { + match ty.sty { + ty::TyTuple(slice) => slice.is_empty(), + ty::TyNever => true, + _ => false, + } +} + +fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool { + let ty = cx.tables.expr_ty(expr); + + if let ty::TyFnDef(id, _) = ty.sty { + if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { + return is_unit_type(fn_type.output()); + } + } + false +} + +fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool { + is_unit_type(cx.tables.expr_ty(expr)) +} + +/// The expression inside a closure may or may not have surrounding braces and +/// semicolons, which causes problems when generating a suggestion. Given an +/// expression that evaluates to '()' or '!', recursively remove useless braces +/// and semi-colons until is suitable for including in the suggestion template +fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { + if !is_unit_expression(cx, expr) { + return None; + } + + match expr.node { + hir::ExprCall(_, _) | + hir::ExprMethodCall(_, _, _) => { + // Calls can't be reduced any more + Some(expr.span) + }, + hir::ExprBlock(ref block) => { + match (&block.stmts[..], block.expr.as_ref()) { + (&[], Some(inner_expr)) => { + // If block only contains an expression, + // reduce `{ X }` to `X` + reduce_unit_expression(cx, inner_expr) + }, + (&[ref inner_stmt], None) => { + // If block only contains statements, + // reduce `{ X; }` to `X` or `X;` + match inner_stmt.node { + hir::StmtDecl(ref d, _) => Some(d.span), + hir::StmtExpr(ref e, _) => Some(e.span), + hir::StmtSemi(_, _) => Some(inner_stmt.span), + } + }, + _ => { + // For closures that contain multiple statements + // it's difficult to get a correct suggestion span + // for all cases (multi-line closures specifically) + // + // We do not attempt to build a suggestion for those right now. + None + } + } + }, + _ => None, + } +} + +fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { + if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { + let body = cx.tcx.hir.body(inner_expr_id); + let body_expr = &body.value; + + if_chain! { + if decl.inputs.len() == 1; + if is_unit_expression(cx, body_expr); + if let Some(binding) = iter_input_pats(&decl, body).next(); + then { + return Some((binding, body_expr)); + } + } + } + None +} + +/// Builds a name for the let binding variable (var_arg) +/// +/// `x.field` => `x_field` +/// `y` => `_y` +/// +/// Anything else will return `_`. +fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { + match &var_arg.node { + hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), + hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")), + _ => "_".to_string() + } +} + +fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { + let var_arg = &map_args[0]; + let fn_arg = &map_args[1]; + + if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + return; + } + + if is_unit_function(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a unit function"; + let suggestion = format!("if let Some({0}) = {1} {{ {2}(...) }}", + let_binding_name(cx, var_arg), + snippet(cx, var_arg.span, "_"), + snippet(cx, fn_arg.span, "_")); + + span_lint_and_then(cx, + OPTION_MAP_UNIT_FN, + expr.span, + msg, + |db| { db.span_approximate_suggestion(stmt.span, "try this", suggestion); }); + } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { + let msg = "called `map(f)` on an Option value where `f` is a unit closure"; + + enum Suggestion { + Full(String), + Approx(String) + } + + let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { + Suggestion::Full( + format!("if let Some({0}) = {1} {{ {2} }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, expr_span, "_")) + ) + } else { + Suggestion::Approx( + format!("if let Some({0}) = {1} {{ ... }}", + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")) + ) + }; + + span_lint_and_then(cx, OPTION_MAP_UNIT_FN, expr.span, msg, |db| { + match suggestion { + Suggestion::Full(sugg) => db.span_suggestion(stmt.span, "try this", sugg), + Suggestion::Approx(sugg) => db.span_approximate_suggestion(stmt.span, "try this", sugg), + }; + }); + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { + if in_macro(stmt.span) { + return; + } + + if let hir::StmtSemi(ref expr, _) = stmt.node { + if let hir::ExprMethodCall(_, _, _) = expr.node { + if let Some(arglists) = method_chain_args(expr, &["map"]) { + lint_map_unit_fn(cx, stmt, expr, arglists[0]); + } + } + } + } +} diff --git a/clippy_lints/src/option_map_unit_fn.rs b/clippy_lints/src/option_map_unit_fn.rs deleted file mode 100644 index abbeaabbdb2..00000000000 --- a/clippy_lints/src/option_map_unit_fn.rs +++ /dev/null @@ -1,216 +0,0 @@ -use rustc::hir; -use rustc::lint::*; -use rustc::ty; -use syntax::codemap::Span; -use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; -use utils::paths; - -#[derive(Clone)] -pub struct Pass; - -/// **What it does:** Checks for usage of `Option.map(f)` where f is a function -/// or closure that returns the unit type. -/// -/// **Why is this bad?** Readability, this can be written more clearly with -/// an if statement -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ```rust -/// let x : Option<&str> = do_stuff(); -/// x.map(log_err_msg); -/// x.map(|msg| log_err_msg(format_msg(msg))) -/// ``` -/// -/// The correct use would be: -/// -/// ```rust -/// let x : Option<&str> = do_stuff(); -/// if let Some(msg) = x { -/// log_err_msg(msg) -/// } -/// if let Some(msg) = x { -/// log_err_msg(format_msg(msg)) -/// } -/// ``` -declare_clippy_lint! { - pub OPTION_MAP_UNIT_FN, - complexity, - "using `Option.map(f)`, where f is a function or closure that returns ()" -} - - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(OPTION_MAP_UNIT_FN) - } -} - -fn is_unit_type(ty: ty::Ty) -> bool { - match ty.sty { - ty::TyTuple(slice) => slice.is_empty(), - ty::TyNever => true, - _ => false, - } -} - -fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool { - let ty = cx.tables.expr_ty(expr); - - if let ty::TyFnDef(id, _) = ty.sty { - if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { - return is_unit_type(fn_type.output()); - } - } - false -} - -fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool { - is_unit_type(cx.tables.expr_ty(expr)) -} - -/// The expression inside a closure may or may not have surrounding braces and -/// semicolons, which causes problems when generating a suggestion. Given an -/// expression that evaluates to '()' or '!', recursively remove useless braces -/// and semi-colons until is suitable for including in the suggestion template -fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { - if !is_unit_expression(cx, expr) { - return None; - } - - match expr.node { - hir::ExprCall(_, _) | - hir::ExprMethodCall(_, _, _) => { - // Calls can't be reduced any more - Some(expr.span) - }, - hir::ExprBlock(ref block) => { - match (&block.stmts[..], block.expr.as_ref()) { - (&[], Some(inner_expr)) => { - // If block only contains an expression, - // reduce `{ X }` to `X` - reduce_unit_expression(cx, inner_expr) - }, - (&[ref inner_stmt], None) => { - // If block only contains statements, - // reduce `{ X; }` to `X` or `X;` - match inner_stmt.node { - hir::StmtDecl(ref d, _) => Some(d.span), - hir::StmtExpr(ref e, _) => Some(e.span), - hir::StmtSemi(_, _) => Some(inner_stmt.span), - } - }, - _ => { - // For closures that contain multiple statements - // it's difficult to get a correct suggestion span - // for all cases (multi-line closures specifically) - // - // We do not attempt to build a suggestion for those right now. - None - } - } - }, - _ => None, - } -} - -fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { - if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { - let body = cx.tcx.hir.body(inner_expr_id); - let body_expr = &body.value; - - if_chain! { - if decl.inputs.len() == 1; - if is_unit_expression(cx, body_expr); - if let Some(binding) = iter_input_pats(&decl, body).next(); - then { - return Some((binding, body_expr)); - } - } - } - None -} - -/// Builds a name for the let binding variable (var_arg) -/// -/// `x.field` => `x_field` -/// `y` => `_y` -/// -/// Anything else will return `_`. -fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { - match &var_arg.node { - hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), - hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")), - _ => "_".to_string() - } -} - -fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { - let var_arg = &map_args[0]; - let fn_arg = &map_args[1]; - - if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { - return; - } - - if is_unit_function(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a unit function"; - let suggestion = format!("if let Some({0}) = {1} {{ {2}(...) }}", - let_binding_name(cx, var_arg), - snippet(cx, var_arg.span, "_"), - snippet(cx, fn_arg.span, "_")); - - span_lint_and_then(cx, - OPTION_MAP_UNIT_FN, - expr.span, - msg, - |db| { db.span_approximate_suggestion(stmt.span, "try this", suggestion); }); - } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a unit closure"; - - enum Suggestion { - Full(String), - Approx(String) - } - - let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { - Suggestion::Full( - format!("if let Some({0}) = {1} {{ {2} }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, expr_span, "_")) - ) - } else { - Suggestion::Approx( - format!("if let Some({0}) = {1} {{ ... }}", - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")) - ) - }; - - span_lint_and_then(cx, OPTION_MAP_UNIT_FN, expr.span, msg, |db| { - match suggestion { - Suggestion::Full(sugg) => db.span_suggestion(stmt.span, "try this", sugg), - Suggestion::Approx(sugg) => db.span_approximate_suggestion(stmt.span, "try this", sugg), - }; - }); - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { - if in_macro(stmt.span) { - return; - } - - if let hir::StmtSemi(ref expr, _) = stmt.node { - if let hir::ExprMethodCall(_, _, _) = expr.node { - if let Some(arglists) = method_chain_args(expr, &["map"]) { - lint_map_unit_fn(cx, stmt, expr, arglists[0]); - } - } - } - } -} diff --git a/tests/ui/map_unit_fn.stderr b/tests/ui/map_unit_fn.stderr new file mode 100644 index 00000000000..c4ee0ce9238 --- /dev/null +++ b/tests/ui/map_unit_fn.stderr @@ -0,0 +1,210 @@ +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:33:5 + | +33 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` + | + = note: `-D option-map-unit-fn` implied by `-D warnings` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:35:5 + | +35 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:37:5 + | +37 | x.field.map(diverge); + | ^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(x_field) = x.field { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:43:5 + | +43 | x.field.map(|value| x.do_option_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:45:5 + | +45 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:48:5 + | +48 | x.field.map(|value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:50:5 + | +50 | x.field.map(|value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:52:5 + | +52 | x.field.map(|value| { do_nothing(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:54:5 + | +54 | x.field.map(|value| { { do_nothing(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:57:5 + | +57 | x.field.map(|value| diverge(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:59:5 + | +59 | x.field.map(|value| { diverge(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:61:5 + | +61 | x.field.map(|value| { diverge(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:63:5 + | +63 | x.field.map(|value| { { diverge(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:68:5 + | +68 | x.field.map(|value| { let y = plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:70:5 + | +70 | x.field.map(|value| { plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:72:5 + | +72 | x.field.map(|value| { { plus_one(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:75:5 + | +75 | x.field.map(|ref value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:78:5 + | +78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:80:5 + | +80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:84:5 + | +84 | x.field.map(|value| { + | _____^ + | |_____| + | || +85 | || do_nothing(value); +86 | || do_nothing(value) +87 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Option value where `f` is a unit closure + --> $DIR/map_unit_fn.rs:88:5 + | +88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:91:5 + | +91 | Some(42).map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(42) { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:92:5 + | +92 | "12".parse::().ok().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:93:5 + | +93 | Some(plus_one(1)).map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` + +error: called `map(f)` on an Option value where `f` is a unit function + --> $DIR/map_unit_fn.rs:97:5 + | +97 | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_y) = y { do_nothing(...) }` + +error: aborting due to 25 previous errors + diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index d9cfc62a51f..06531e29032 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -23,8 +23,7 @@ impl HasOption { } } -#[cfg_attr(rustfmt, rustfmt_skip)] -fn main() { +fn option_map_unit_fn() { let x = HasOption { field: Some(10) }; x.field.map(plus_one); @@ -96,3 +95,6 @@ fn main() { let y = Some(42); y.map(do_nothing); } + +fn main() { +} diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index bd19fe05329..3ca57a65b3f 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:33:5 + --> $DIR/option_map_unit_fn.rs:32:5 | -33 | x.field.map(do_nothing); +32 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` @@ -9,199 +9,199 @@ error: called `map(f)` on an Option value where `f` is a unit function = note: `-D option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:35:5 + --> $DIR/option_map_unit_fn.rs:34:5 | -35 | x.field.map(do_nothing); +34 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:37:5 + --> $DIR/option_map_unit_fn.rs:36:5 | -37 | x.field.map(diverge); +36 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:43:5 + --> $DIR/option_map_unit_fn.rs:42:5 | -43 | x.field.map(|value| x.do_option_nothing(value + captured)); +42 | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:45:5 + --> $DIR/option_map_unit_fn.rs:44:5 | -45 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); +44 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:48:5 + --> $DIR/option_map_unit_fn.rs:47:5 | -48 | x.field.map(|value| do_nothing(value + captured)); +47 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:50:5 + --> $DIR/option_map_unit_fn.rs:49:5 | -50 | x.field.map(|value| { do_nothing(value + captured) }); +49 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:52:5 + --> $DIR/option_map_unit_fn.rs:51:5 | -52 | x.field.map(|value| { do_nothing(value + captured); }); +51 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:54:5 + --> $DIR/option_map_unit_fn.rs:53:5 | -54 | x.field.map(|value| { { do_nothing(value + captured); } }); +53 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:57:5 + --> $DIR/option_map_unit_fn.rs:56:5 | -57 | x.field.map(|value| diverge(value + captured)); +56 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:59:5 + --> $DIR/option_map_unit_fn.rs:58:5 | -59 | x.field.map(|value| { diverge(value + captured) }); +58 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:61:5 + --> $DIR/option_map_unit_fn.rs:60:5 | -61 | x.field.map(|value| { diverge(value + captured); }); +60 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:63:5 + --> $DIR/option_map_unit_fn.rs:62:5 | -63 | x.field.map(|value| { { diverge(value + captured); } }); +62 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:68:5 + --> $DIR/option_map_unit_fn.rs:67:5 | -68 | x.field.map(|value| { let y = plus_one(value + captured); }); +67 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:70:5 + --> $DIR/option_map_unit_fn.rs:69:5 | -70 | x.field.map(|value| { plus_one(value + captured); }); +69 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:72:5 + --> $DIR/option_map_unit_fn.rs:71:5 | -72 | x.field.map(|value| { { plus_one(value + captured); } }); +71 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:75:5 + --> $DIR/option_map_unit_fn.rs:74:5 | -75 | x.field.map(|ref value| { do_nothing(value + captured) }); +74 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:78:5 + --> $DIR/option_map_unit_fn.rs:77:5 | -78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +77 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:80:5 + --> $DIR/option_map_unit_fn.rs:79:5 | -80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +79 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:84:5 + --> $DIR/option_map_unit_fn.rs:83:5 | -84 | x.field.map(|value| { +83 | x.field.map(|value| { | _____^ | |_____| | || -85 | || do_nothing(value); -86 | || do_nothing(value) -87 | || }); +84 | || do_nothing(value); +85 | || do_nothing(value) +86 | || }); | ||______^- help: try this: `if let Some(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:88:5 + --> $DIR/option_map_unit_fn.rs:87:5 | -88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +87 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:91:5 + --> $DIR/option_map_unit_fn.rs:90:5 | -91 | Some(42).map(diverge); +90 | Some(42).map(diverge); | ^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:92:5 + --> $DIR/option_map_unit_fn.rs:91:5 | -92 | "12".parse::().ok().map(diverge); +91 | "12".parse::().ok().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:93:5 + --> $DIR/option_map_unit_fn.rs:92:5 | -93 | Some(plus_one(1)).map(do_nothing); +92 | Some(plus_one(1)).map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:97:5 + --> $DIR/option_map_unit_fn.rs:96:5 | -97 | y.map(do_nothing); +96 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_y) = y { do_nothing(...) }` -- cgit 1.4.1-3-g733a5 From 4f4e20c561b223027e47183e58c4ec17f406d809 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 15 Apr 2018 13:00:12 +0200 Subject: Also lint Result.map for unit returns --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 1 + clippy_lints/src/map_unit_fn.rs | 77 ++++++++++++--- tests/ui/result_map_unit_fn.rs | 102 +++++++++++++++++++ tests/ui/result_map_unit_fn.stderr | 194 +++++++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+), 16 deletions(-) create mode 100644 tests/ui/result_map_unit_fn.rs create mode 100644 tests/ui/result_map_unit_fn.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0065ae1a0af..f66c0086894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -705,7 +705,7 @@ All notable changes to this project will be documented in this file. [`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options [`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect -[`option_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unit_fn +[`map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_unit_fn [`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref [`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index afad923a35a..ea8478c373b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -444,6 +444,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, map_unit_fn::OPTION_MAP_UNIT_FN, + map_unit_fn::RESULT_MAP_UNIT_FN, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 97ff1141986..c3fc19699ea 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -41,10 +41,43 @@ declare_clippy_lint! { "using `Option.map(f)`, where f is a function or closure that returns ()" } +/// **What it does:** Checks for usage of `Result.map(f)` where f is a function +/// or closure that returns the unit type. +/// +/// **Why is this bad?** Readability, this can be written more clearly with +/// an if statement +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// let x: Result<&str, &str> = do_stuff(); +/// x.map(log_err_msg); +/// x.map(|msg| log_err_msg(format_msg(msg))) +/// ``` +/// +/// The correct use would be: +/// +/// ```rust +/// let x: Result<&str, &str> = do_stuff(); +/// if let Ok(msg) = x { +/// log_err_msg(msg) +/// } +/// if let Ok(msg) = x { +/// log_err_msg(format_msg(msg)) +/// } +/// ``` +declare_clippy_lint! { + pub RESULT_MAP_UNIT_FN, + complexity, + "using `Result.map(f)`, where f is a function or closure that returns ()" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(OPTION_MAP_UNIT_FN) + lint_array!(OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN) } } @@ -147,28 +180,40 @@ fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { } } +fn suggestion_msg(function_type: &str, map_type: &str) -> String { + format!( + "called `map(f)` on an {0} value where `f` is a unit {1}", + map_type, + function_type + ) +} + fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { let var_arg = &map_args[0]; let fn_arg = &map_args[1]; - if !match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { - return; - } + let (map_type, variant, lint) = + if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + ("Option", "Some", OPTION_MAP_UNIT_FN) + } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) { + ("Result", "Ok", RESULT_MAP_UNIT_FN) + } else { + return + }; if is_unit_function(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a unit function"; - let suggestion = format!("if let Some({0}) = {1} {{ {2}(...) }}", + let msg = suggestion_msg("function", map_type); + let suggestion = format!("if let {0}({1}) = {2} {{ {3}(...) }}", + variant, let_binding_name(cx, var_arg), snippet(cx, var_arg.span, "_"), snippet(cx, fn_arg.span, "_")); - span_lint_and_then(cx, - OPTION_MAP_UNIT_FN, - expr.span, - msg, - |db| { db.span_approximate_suggestion(stmt.span, "try this", suggestion); }); + span_lint_and_then(cx, lint, expr.span, &msg, |db| { + db.span_approximate_suggestion(stmt.span, "try this", suggestion); + }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { - let msg = "called `map(f)` on an Option value where `f` is a unit closure"; + let msg = suggestion_msg("closure", map_type); enum Suggestion { Full(String), @@ -177,20 +222,22 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { Suggestion::Full( - format!("if let Some({0}) = {1} {{ {2} }}", + format!("if let {0}({1}) = {2} {{ {3} }}", + variant, snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_"), snippet(cx, expr_span, "_")) ) } else { Suggestion::Approx( - format!("if let Some({0}) = {1} {{ ... }}", + format!("if let {0}({1}) = {2} {{ ... }}", + variant, snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_")) ) }; - span_lint_and_then(cx, OPTION_MAP_UNIT_FN, expr.span, msg, |db| { + span_lint_and_then(cx, lint, expr.span, &msg, |db| { match suggestion { Suggestion::Full(sugg) => db.span_suggestion(stmt.span, "try this", sugg), Suggestion::Approx(sugg) => db.span_approximate_suggestion(stmt.span, "try this", sugg), diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs new file mode 100644 index 00000000000..8f3c1579987 --- /dev/null +++ b/tests/ui/result_map_unit_fn.rs @@ -0,0 +1,102 @@ +#![warn(result_map_unit_fn)] +#![allow(unused)] + +fn do_nothing(_: T) {} + +fn diverge(_: T) -> ! { + panic!() +} + +fn plus_one(value: usize) -> usize { + value + 1 +} + +struct HasResult { + field: Result, +} + +impl HasResult { + fn do_result_nothing(self: &Self, value: usize) {} + + fn do_result_plus_one(self: &Self, value: usize) -> usize { + value + 1 + } +} + +fn result_map_unit_fn() { + let x = HasResult { field: Ok(10) }; + + x.field.map(plus_one); + let _ : Result<(), usize> = x.field.map(do_nothing); + + x.field.map(do_nothing); + + x.field.map(do_nothing); + + x.field.map(diverge); + + let captured = 10; + if let Ok(value) = x.field { do_nothing(value + captured) }; + let _ : Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); + + x.field.map(|value| x.do_result_nothing(value + captured)); + + x.field.map(|value| { x.do_result_plus_one(value + captured); }); + + + x.field.map(|value| do_nothing(value + captured)); + + x.field.map(|value| { do_nothing(value + captured) }); + + x.field.map(|value| { do_nothing(value + captured); }); + + x.field.map(|value| { { do_nothing(value + captured); } }); + + + x.field.map(|value| diverge(value + captured)); + + x.field.map(|value| { diverge(value + captured) }); + + x.field.map(|value| { diverge(value + captured); }); + + x.field.map(|value| { { diverge(value + captured); } }); + + + x.field.map(|value| plus_one(value + captured)); + x.field.map(|value| { plus_one(value + captured) }); + x.field.map(|value| { let y = plus_one(value + captured); }); + + x.field.map(|value| { plus_one(value + captured); }); + + x.field.map(|value| { { plus_one(value + captured); } }); + + + x.field.map(|ref value| { do_nothing(value + captured) }); + + + x.field.map(|value| { do_nothing(value); do_nothing(value) }); + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + + // Suggestion for the let block should be `{ ... }` as it's too difficult to build a + // proper suggestion for these cases + x.field.map(|value| { + do_nothing(value); + do_nothing(value) + }); + x.field.map(|value| { do_nothing(value); do_nothing(value); }); + + // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let variable name for them + let res: Result = Ok(42).map(diverge); + "12".parse::().map(diverge); + + let res: Result<(), usize> = Ok(plus_one(1)).map(do_nothing); + + // Should suggest `if let Ok(_y) ...` to not override the existing foo variable + let y: Result = Ok(42); + y.map(do_nothing); +} + +fn main() { +} + diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr new file mode 100644 index 00000000000..199f5e7cf97 --- /dev/null +++ b/tests/ui/result_map_unit_fn.stderr @@ -0,0 +1,194 @@ +error: called `map(f)` on an Result value where `f` is a unit function + --> $DIR/result_map_unit_fn.rs:32:5 + | +32 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` + | + = note: `-D result-map-unit-fn` implied by `-D warnings` + +error: called `map(f)` on an Result value where `f` is a unit function + --> $DIR/result_map_unit_fn.rs:34:5 + | +34 | x.field.map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` + +error: called `map(f)` on an Result value where `f` is a unit function + --> $DIR/result_map_unit_fn.rs:36:5 + | +36 | x.field.map(diverge); + | ^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:42:5 + | +42 | x.field.map(|value| x.do_result_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:44:5 + | +44 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:47:5 + | +47 | x.field.map(|value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:49:5 + | +49 | x.field.map(|value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:51:5 + | +51 | x.field.map(|value| { do_nothing(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:53:5 + | +53 | x.field.map(|value| { { do_nothing(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:56:5 + | +56 | x.field.map(|value| diverge(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:58:5 + | +58 | x.field.map(|value| { diverge(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:60:5 + | +60 | x.field.map(|value| { diverge(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:62:5 + | +62 | x.field.map(|value| { { diverge(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:67:5 + | +67 | x.field.map(|value| { let y = plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:69:5 + | +69 | x.field.map(|value| { plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:71:5 + | +71 | x.field.map(|value| { { plus_one(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:74:5 + | +74 | x.field.map(|ref value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:77:5 + | +77 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:79:5 + | +79 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:83:5 + | +83 | x.field.map(|value| { + | _____^ + | |_____| + | || +84 | || do_nothing(value); +85 | || do_nothing(value) +86 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:87:5 + | +87 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` + +error: called `map(f)` on an Result value where `f` is a unit function + --> $DIR/result_map_unit_fn.rs:91:5 + | +91 | "12".parse::().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` + +error: called `map(f)` on an Result value where `f` is a unit function + --> $DIR/result_map_unit_fn.rs:97:5 + | +97 | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_y) = y { do_nothing(...) }` + +error: aborting due to 23 previous errors + -- cgit 1.4.1-3-g733a5 From d175c797e5299ba530460a619a4c34d9a818b187 Mon Sep 17 00:00:00 2001 From: "MSI\\Stew's Laptop" Date: Mon, 9 Apr 2018 00:07:47 -0400 Subject: fixing error message for empty println macro --- .gitignore | 3 ++- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/write.rs | 17 ++++++++++------- tests/ui/println_empty_string.rs | 4 ++++ tests/ui/println_empty_string.stderr | 10 ++++++++-- tests/ui/writeln_empty_string.stderr | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 6f472c418d2..3c8f96c0f6f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,6 @@ util/gh-pages/lints.json *.rs.bk helper.txt - +*.iml .vscode +.idea diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 1439c23f0fa..5f6c15e222d 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -12,7 +12,7 @@ use url::Url; /// /// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and /// camel-case probably indicates some code which should be included between -/// ticks. `_` can also be used for empasis in markdown, this lint tries to +/// ticks. `_` can also be used for emphasis in markdown, this lint tries to /// consider that. /// /// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0531c14cba8..4773aab27da 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -230,11 +230,11 @@ fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, "using `write!()` with a format string that ends in a \ newline, consider using `writeln!()` instead"); }, - "writeln" => if has_empty_arg(cx, span, fmtstr, fmtlen) { + "writeln" => if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) { span_lint_and_sugg( cx, WRITE_WITH_NEWLINE, - span, + final_span, "using `writeln!(v, \"\")`", "replace it with", "writeln!(v)".to_string(), @@ -295,11 +295,11 @@ fn check_print_variants<'a, 'tcx>( newline, consider using `println!()` instead"); }, "println" => - if has_empty_arg(cx, span, fmtstr, fmtlen) { + if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) { span_lint_and_sugg( cx, PRINT_WITH_NEWLINE, - span, + final_span, "using `println!(\"\")`", "replace it with", "println!()".to_string(), @@ -390,7 +390,7 @@ fn has_newline_end(args: &HirVec, fmtstr: InternedString, fmtlen: usize) - } /// Check for writeln!(v, "") / println!("") -fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) -> bool { +fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) -> Option { if_chain! { // check that the string is empty if fmtlen == 1; @@ -400,10 +400,13 @@ fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: Inter if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); if snippet.contains("\"\""); then { - return true + if snippet.ends_with(';') { + return Some(cx.sess().codemap().span_until_char(span, ';')); + } + return Some(span) } } - false + None } /// Returns the slice of format string parts in an `Arguments::new_v1` call. diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 82495f1b39d..9df348050ad 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -1,4 +1,8 @@ fn main() { println!(); println!(""); + + match "a" { + _ => println!(""), + } } diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index f70b056e562..1148a4496a5 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -2,9 +2,15 @@ error: using `println!("")` --> $DIR/println_empty_string.rs:3:5 | 3 | println!(""); - | ^^^^^^^^^^^^^ help: replace it with: `println!()` + | ^^^^^^^^^^^^ help: replace it with: `println!()` | = note: `-D print-with-newline` implied by `-D warnings` -error: aborting due to previous error +error: using `println!("")` + --> $DIR/println_empty_string.rs:6:14 + | +6 | _ => println!(""), + | ^^^^^^^^^^^^ help: replace it with: `println!()` + +error: aborting due to 2 previous errors diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index e20aad779d9..b4649384865 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -2,7 +2,7 @@ error: using `writeln!(v, "")` --> $DIR/writeln_empty_string.rs:9:5 | 9 | writeln!(&mut v, ""); - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` + | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` | = note: `-D write-with-newline` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 9dc9487567e7e1be7319c190401135d174ff35a8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 15 Apr 2018 15:01:48 +0200 Subject: Version bump --- CHANGELOG.md | 9 +++++++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 26 ++++++++++++++++---------- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fede68081bb..8995604e1bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.194 +* Rustup to *rustc 1.27.0-nightly (bd40cbbe1 2018-04-14)* +* New lints: [`cast_ptr_alignment`], [`transmute_ptr_to_ptr`], [`write_literal`], [`write_with_newline`], [`writeln_empty_string`] + ## 0.0.193 * Rustup to *rustc 1.27.0-nightly (eeea94c11 2018-04-06)* @@ -571,6 +575,7 @@ All notable changes to this project will be documented in this file. [`cast_possible_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_truncation [`cast_possible_wrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_wrap [`cast_precision_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_precision_loss +[`cast_ptr_alignment`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_ptr_alignment [`cast_sign_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_sign_loss [`char_lit_as_u8`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#char_lit_as_u8 [`chars_last_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_last_cmp @@ -769,6 +774,7 @@ All notable changes to this project will be documented in this file. [`transmute_int_to_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_bool [`transmute_int_to_char`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_char [`transmute_int_to_float`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_float +[`transmute_ptr_to_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity @@ -802,6 +808,9 @@ All notable changes to this project will be documented in this file. [`while_immutable_condition`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_on_iterator +[`write_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_literal +[`write_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_with_newline +[`writeln_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#writeln_empty_string [`wrong_pub_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_pub_self_convention [`wrong_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_self_convention [`wrong_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_transmute diff --git a/Cargo.toml b/Cargo.toml index f84375c0135..71d22cc015e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.193" +version = "0.0.194" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.193", path = "clippy_lints" } +clippy_lints = { version = "0.0.194", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/README.md b/README.md index 9635a5838a2..0555c17fd1d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 249 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 253 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7bf7f601de3..c74b841eb86 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.193" +version = "0.0.194" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3b2251b9021..7e0a692c2da 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -421,12 +421,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::WRONG_PUB_SELF_CONVENTION, misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, - write::PRINT_STDOUT, - write::USE_DEBUG, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, strings::STRING_ADD, + write::PRINT_STDOUT, + write::USE_DEBUG, ]); reg.register_lint_group("clippy_pedantic", vec![ @@ -612,9 +612,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { panic::PANIC_PARAMS, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, - write::PRINT_LITERAL, - write::PRINT_WITH_NEWLINE, - write::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, ptr::MUT_FROM_REF, ptr::PTR_ARG, @@ -641,8 +638,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, - transmute::TRANSMUTE_PTR_TO_REF, transmute::TRANSMUTE_PTR_TO_PTR, + transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, @@ -663,6 +660,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { unused_io_amount::UNUSED_IO_AMOUNT, unused_label::UNUSED_LABEL, vec::USELESS_VEC, + write::PRINT_LITERAL, + write::PRINT_WITH_NEWLINE, + write::PRINTLN_EMPTY_STRING, + write::WRITE_LITERAL, + write::WRITE_WITH_NEWLINE, + write::WRITELN_EMPTY_STRING, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); @@ -727,9 +730,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic::PANIC_PARAMS, - write::PRINT_LITERAL, - write::PRINT_WITH_NEWLINE, - write::PRINTLN_EMPTY_STRING, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, @@ -743,6 +743,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + write::PRINT_LITERAL, + write::PRINT_WITH_NEWLINE, + write::PRINTLN_EMPTY_STRING, + write::WRITE_LITERAL, + write::WRITE_WITH_NEWLINE, + write::WRITELN_EMPTY_STRING, ]); reg.register_lint_group("clippy_complexity", vec![ @@ -791,8 +797,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, - transmute::TRANSMUTE_PTR_TO_REF, transmute::TRANSMUTE_PTR_TO_PTR, + transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, types::BORROWED_BOX, types::CAST_LOSSLESS, -- cgit 1.4.1-3-g733a5 From 26b9911e079cc1e8fa076ff704ab4785f02aa53d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 15 Apr 2018 15:37:11 +0200 Subject: Refactor out enum and address nits --- clippy_lints/src/map_unit_fn.rs | 52 ++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index c3fc19699ea..7defccf4697 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -8,11 +8,11 @@ use utils::paths; #[derive(Clone)] pub struct Pass; -/// **What it does:** Checks for usage of `Option.map(f)` where f is a function +/// **What it does:** Checks for usage of `option.map(f)` where f is a function /// or closure that returns the unit type. /// /// **Why is this bad?** Readability, this can be written more clearly with -/// an if statement +/// an if let statement /// /// **Known problems:** None. /// @@ -38,14 +38,14 @@ pub struct Pass; declare_clippy_lint! { pub OPTION_MAP_UNIT_FN, complexity, - "using `Option.map(f)`, where f is a function or closure that returns ()" + "using `option.map(f)`, where f is a function or closure that returns ()" } -/// **What it does:** Checks for usage of `Result.map(f)` where f is a function +/// **What it does:** Checks for usage of `result.map(f)` where f is a function /// or closure that returns the unit type. /// /// **Why is this bad?** Readability, this can be written more clearly with -/// an if statement +/// an if let statement /// /// **Known problems:** None. /// @@ -71,7 +71,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub RESULT_MAP_UNIT_FN, complexity, - "using `Result.map(f)`, where f is a function or closure that returns ()" + "using `result.map(f)`, where f is a function or closure that returns ()" } @@ -215,33 +215,21 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); - enum Suggestion { - Full(String), - Approx(String) - } - - let suggestion = if let Some(expr_span) = reduce_unit_expression(cx, closure_expr) { - Suggestion::Full( - format!("if let {0}({1}) = {2} {{ {3} }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, expr_span, "_")) - ) - } else { - Suggestion::Approx( - format!("if let {0}({1}) = {2} {{ ... }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")) - ) - }; - span_lint_and_then(cx, lint, expr.span, &msg, |db| { - match suggestion { - Suggestion::Full(sugg) => db.span_suggestion(stmt.span, "try this", sugg), - Suggestion::Approx(sugg) => db.span_approximate_suggestion(stmt.span, "try this", sugg), - }; + if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) { + let suggestion = format!("if let {0}({1}) = {2} {{ {3} }}", + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, reduced_expr_span, "_")); + db.span_suggestion(stmt.span, "try this", suggestion); + } else { + let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")); + db.span_approximate_suggestion(stmt.span, "try this", suggestion); + } }); } } -- cgit 1.4.1-3-g733a5 From fe426b7c51d00bbd17cd243fc9cdaf8899c4f0fe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 17 Apr 2018 08:33:22 +0200 Subject: Add intro and mention IRC in CONTRIBUTING.md This is partly taken from the [rustfmt CONTRIBUTING.md][contrib]. [contrib]: https://github.com/rust-lang-nursery/rustfmt/blob/master/Contributing.md --- CONTRIBUTING.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16e1696706e..0a312a545d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,13 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lints! +Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how +you can contribute and how to get started. +If you have any questions about contributing or need help with anything, feel free to ask questions on issues or +visit the `#clippy` IRC channel on `irc.mozilla.org`. + +All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). + ## Getting started High level approach: @@ -56,7 +63,7 @@ of this. There is also the internal `author` lint to generate clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. -Create a new UI test with the pattern you want to match: +First, create a new UI test file in the `tests/ui/` directory with the pattern you want to match: ```rust // ./tests/ui/my_lint.rs @@ -71,7 +78,7 @@ fn main() { ``` Now you run `TESTNAME=ui/my_lint cargo test --test compile-test` to produce -the file with the generated code: +a `.stdout` file with the generated code: ```rust // ./tests/ui/my_lint.stdout @@ -87,6 +94,8 @@ if_chain! { } ``` +If the command was executed successfully, you can copy the code over to where you are implementing your lint. + #### Documentation Please document your lint with a doc comment akin to the following: @@ -140,17 +149,10 @@ enabled as a plugin: ## Contributions -Clippy welcomes contributions from everyone. - Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will be reviewed by a core contributor (someone with permission to land patches) and either landed in the main tree or given feedback for changes that would be required. All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/) -## Conduct - -We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). - - -- cgit 1.4.1-3-g733a5 From f786a3694927755bc6a2e2721c1f6186d253866c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 17 Apr 2018 10:52:25 +0200 Subject: Rustup --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cfef1e85b94..515bd8976b9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1798,7 +1798,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0..=32).contains(n.val.to_raw_bits().expect("array length")), + ty::TyArray(_, n) => (0..=32).contains(&n.val.to_raw_bits().expect("array length")), _ => false, } } -- cgit 1.4.1-3-g733a5 From a854874e6a089f67a658a4f5bb4b0d7150535573 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 18 Apr 2018 20:25:43 +0200 Subject: Fix latest nightly breakage I'm not sure if there are better ways to use the RwLock API, though. But it seems to work. --- clippy_lints/src/loops.rs | 2 +- src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cfef1e85b94..515bd8976b9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1798,7 +1798,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0..=32).contains(n.val.to_raw_bits().expect("array length")), + ty::TyArray(_, n) => (0..=32).contains(&n.val.to_raw_bits().expect("array length")), _ => false, } } diff --git a/src/lib.rs b/src/lib.rs index 8f0c6a63207..f8682884a50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ extern crate clippy_lints; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - if let Ok(lint_store) = reg.sess.lint_store.try_borrow() { + reg.sess.lint_store.with_read_lock(|lint_store| { for (lint, _, _) in lint_store.get_lint_groups() { if lint == "clippy" { reg.sess @@ -21,7 +21,7 @@ pub fn plugin_registrar(reg: &mut Registry) { return; } } - } + }); clippy_lints::register_plugins(reg); } -- cgit 1.4.1-3-g733a5 From c5b39a5917ffc0f1349b6e414fa3b874fdcf8429 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 19 Apr 2018 08:30:07 +0200 Subject: Version bump --- CHANGELOG.md | 6 +++++- Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 6 ++++-- clippy_lints/src/regex.rs | 4 ++-- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d69de69996..27420e47238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.195 +* Rustup to *rustc 1.27.0-nightly (ac3c2288f 2018-04-18)* + ## 0.0.194 * Rustup to *rustc 1.27.0-nightly (bd40cbbe1 2018-04-14)* * New lints: [`cast_ptr_alignment`], [`transmute_ptr_to_ptr`], [`write_literal`], [`write_with_newline`], [`writeln_empty_string`] @@ -710,9 +713,9 @@ All notable changes to this project will be documented in this file. [`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options [`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect -[`map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_unit_fn [`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref [`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none +[`option_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or [`option_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else [`option_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_option @@ -741,6 +744,7 @@ All notable changes to this project will be documented in this file. [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts +[`result_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used [`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop diff --git a/Cargo.toml b/Cargo.toml index 71d22cc015e..9efa7031005 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.194" +version = "0.0.195" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.194", path = "clippy_lints" } +clippy_lints = { version = "0.0.195", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/README.md b/README.md index 0555c17fd1d..d0ba8b0948a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 253 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 255 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index c74b841eb86..17c1c25669f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.194" +version = "0.0.195" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bdbdff92d3c..890d7a6e22e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -443,8 +443,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, - map_unit_fn::OPTION_MAP_UNIT_FN, - map_unit_fn::RESULT_MAP_UNIT_FN, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, @@ -553,6 +551,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, map_clone::MAP_CLONE, + map_unit_fn::OPTION_MAP_UNIT_FN, + map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, @@ -774,6 +774,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::EXPLICIT_COUNTER_LOOP, loops::MUT_RANGE_BOUND, loops::WHILE_LET_LOOP, + map_unit_fn::OPTION_MAP_UNIT_FN, + map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, methods::CHARS_NEXT_CMP, methods::CLONE_ON_COPY, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 26c1e2b244e..20ccc6ccfcc 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -129,8 +129,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn str_span(base: Span, c: regex_syntax::ast::Span, offset: usize) -> Span { - let offset = offset as u32; +fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { + let offset = u32::from(offset); let end = base.lo() + BytePos(c.end.offset as u32 + offset); let start = base.lo() + BytePos(c.start.offset as u32 + offset); assert!(start <= end); -- cgit 1.4.1-3-g733a5 From 5bfb306b4b13339443f8e6898833f29db0c8cce9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 21 Apr 2018 11:42:28 +0200 Subject: Explain how Clippy works --- CONTRIBUTING.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a312a545d2..6a9f749e65a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -147,6 +147,55 @@ enabled as a plugin: #![plugin(clippy)] ``` +### How Clippy works + +Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. + +[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them with the rustc plugin registry. For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this: + +```rust +// ./clippy_lints/src/lib.rs + +// ... +pub mod else_if_without_else; +// ... + +pub fn register_plugins(reg: &mut rustc_plugin::Registry) { + // ... + reg.register_early_lint_pass(box else_if_without_else::ElseIfWithoutElse); + // ... + + reg.register_lint_group("clippy_restriction", vec![ + // ... + else_if_without_else::ELSE_IF_WITHOUT_ELSE, + // ... + ]); +} +``` + +The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. +Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. + +```rust +// ./clippy_lints/src/else_if_without_else.rs + +use rustc::lint::*; + +// ... + +pub struct ElseIfWithoutElse; + +// ... + +impl EarlyLintPass for ElseIfWithoutElse { + // ... the functions needed, to make the lint work +} +``` + +The difference between `EarlyLintPass` and `LateLintPass` is that the methods of the `EarlyLintPass` trait only provide AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information via the `LateContext` parameter. + +That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. + ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will @@ -156,3 +205,14 @@ main tree or given feedback for changes that would be required. All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/) + +[main_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/src/lib.rs#L14 +[lint_crate]: https://github.com/rust-lang-nursery/rust-clippy/tree/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src +[lint_crate_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/lib.rs +[else_if_without_else]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/else_if_without_else.rs +[compiler_plugin]: https://doc.rust-lang.org/unstable-book/language-features/plugin.html#lint-plugins +[plugin_registry]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html +[reg_early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_early_lint_pass +[reg_late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_late_lint_pass +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html -- cgit 1.4.1-3-g733a5 From 8ccaa83e90f3520ae919c206eed92121f603763f Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sat, 21 Apr 2018 19:23:59 +0100 Subject: Add more tests to print_ and write_literal Also, move precision, width, and debug fmt tests to 'should pass' --- tests/ui/print_literal.rs | 13 ++++++++++--- tests/ui/write_literal.rs | 21 ++++++++++++++------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index c803294ab0a..272e1c168d3 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -9,16 +9,23 @@ fn main() { let world = "world"; println!("Hello {}", world); println!("3 in hex is {:X}", 3); + println!("2 + 1 = {:.4}", 3); + println!("2 + 1 = {:5.4}", 3); + println!("Debug test {:?}", "hello, world"); + println!("{0:8} {1:>8}", "hello", "world"); + println!("{1:8} {0:>8}", "hello", "world"); + println!("{foo:8} {bar:>8}", foo="hello", bar="world"); + println!("{bar:8} {foo:>8}", foo="hello", bar="world"); + println!("{number:>width$}", number=1, width=6); + println!("{number:>0width$}", number=1, width=6); // these should throw warnings + println!("{} of {:b} people know binary, the other half doesn't", 1, 2); print!("Hello {}", "world"); println!("Hello {} {}", world, "world"); println!("Hello {}", "world"); println!("10 / 4 is {}", 2.5); println!("2 + 1 = {}", 3); - println!("2 + 1 = {:.4}", 3); - println!("2 + 1 = {:5.4}", 3); - println!("Debug test {:?}", "hello, world"); // positional args don't change the fact // that we're using a literal -- this should diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index dd3a869eb4e..b09640a18eb 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -6,22 +6,29 @@ use std::io::Write; fn main() { let mut v = Vec::new(); - // These should be fine + // these should be fine write!(&mut v, "Hello"); writeln!(&mut v, "Hello"); let world = "world"; writeln!(&mut v, "Hello {}", world); writeln!(&mut v, "3 in hex is {:X}", 3); + writeln!(&mut v, "2 + 1 = {:.4}", 3); + writeln!(&mut v, "2 + 1 = {:5.4}", 3); + writeln!(&mut v, "Debug test {:?}", "hello, world"); + writeln!(&mut v, "{0:8} {1:>8}", "hello", "world"); + writeln!(&mut v, "{1:8} {0:>8}", "hello", "world"); + writeln!(&mut v, "{foo:8} {bar:>8}", foo="hello", bar="world"); + writeln!(&mut v, "{bar:8} {foo:>8}", foo="hello", bar="world"); + writeln!(&mut v, "{number:>width$}", number=1, width=6); + writeln!(&mut v, "{number:>0width$}", number=1, width=6); - // These should throw warnings + // these should throw warnings + writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); write!(&mut v, "Hello {}", "world"); writeln!(&mut v, "Hello {} {}", world, "world"); writeln!(&mut v, "Hello {}", "world"); writeln!(&mut v, "10 / 4 is {}", 2.5); writeln!(&mut v, "2 + 1 = {}", 3); - writeln!(&mut v, "2 + 1 = {:.4}", 3); - writeln!(&mut v, "2 + 1 = {:5.4}", 3); - writeln!(&mut v, "Debug test {:?}", "hello, world"); // positional args don't change the fact // that we're using a literal -- this should @@ -30,6 +37,6 @@ fn main() { writeln!(&mut v, "{1} {0}", "hello", "world"); // named args shouldn't change anything either - writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); + writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); } -- cgit 1.4.1-3-g733a5 From 54c0edcfe85e7811a8501b34dc2f8fbe9b8acb51 Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sat, 21 Apr 2018 19:24:55 +0100 Subject: Add smaller check_unformatted to write.rs and fix precision,width,align false positive --- clippy_lints/src/write.rs | 61 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 4773aab27da..67c72bd9859 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -7,7 +7,7 @@ use syntax::ptr; use syntax::symbol::InternedString; use syntax_pos::Span; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; -use utils::{opt_def_id, paths}; +use utils::{opt_def_id, paths, last_path_segment}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -266,7 +266,6 @@ fn check_print_variants<'a, 'tcx>( }; span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - if_chain! { // ensure we're calling Arguments::new_v1 if args.len() == 1; @@ -339,7 +338,9 @@ where F: Fn(Span), { if_chain! { - if args.len() > 1; + if args.len() >= 2; + + // the match statement if let ExprAddrOf(_, ref match_expr) = args[1].node; if let ExprMatch(ref matchee, ref arms, _) = match_expr.node; if let ExprTup(ref tup) = matchee.node; @@ -355,15 +356,31 @@ where if let ExprLit(_) = tup_val.node; // next, check the corresponding match arm body to ensure - // this is "{}", or DISPLAY_FMT_METHOD + // this is DISPLAY_FMT_METHOD if let ExprCall(_, ref body_args) = arm_body_exprs[idx].node; if body_args.len() == 2; if let ExprPath(ref body_qpath) = body_args[1].node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD) || - match_def_path(cx.tcx, fun_def_id, &paths::DEBUG_FMT_METHOD); + if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { - lint_fn(tup_val.span); + if args.len() == 2 { + lint_fn(tup_val.span); + } + + // ensure the format str has no options (e.g., width, precision, alignment, etc.) + // and is just "{}" + if_chain! { + if args.len() == 3; + if let ExprAddrOf(_, ref format_expr) = args[2].node; + if let ExprArray(ref format_exprs) = format_expr.node; + if format_exprs.len() >= 1; + if let ExprStruct(_, ref fields, _) = format_exprs[idx].node; + if let Some(format_field) = fields.iter().find(|f| f.name.node == "format"); + if check_unformatted(&format_field.expr); + then { + lint_fn(tup_val.span); + } + } } } } @@ -438,3 +455,33 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { } false } + +/// Checks if the expression matches +/// ```rust,ignore +/// &[_ { +/// format: _ { +/// width: _::Implied, +/// ... +/// }, +/// ..., +/// }] +/// ``` +pub fn check_unformatted(format_field: &Expr) -> bool { + if_chain! { + if let ExprStruct(_, ref fields, _) = format_field.node; + if let Some(width_field) = fields.iter().find(|f| f.name.node == "width"); + if let ExprPath(ref qpath) = width_field.expr.node; + if last_path_segment(qpath).name == "Implied"; + if let Some(align_field) = fields.iter().find(|f| f.name.node == "align"); + if let ExprPath(ref qpath) = align_field.expr.node; + if last_path_segment(qpath).name == "Unknown"; + if let Some(precision_field) = fields.iter().find(|f| f.name.node == "precision"); + if let ExprPath(ref qpath_precision) = precision_field.expr.node; + if last_path_segment(qpath_precision).name == "Implied"; + then { + return true; + } + } + + false +} -- cgit 1.4.1-3-g733a5 From a317bc9d233cee39027e20d8e9d898757699babf Mon Sep 17 00:00:00 2001 From: Michael Recachinas Date: Sat, 21 Apr 2018 19:50:49 +0100 Subject: Update stderrs for print and write_literal --- tests/ui/print_literal.stderr | 80 +++++++++++++++++---------------------- tests/ui/write_literal.stderr | 88 +++++++++++++++++++------------------------ 2 files changed, 72 insertions(+), 96 deletions(-) diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 982be7dc537..d1e4b49cbdd 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,100 +1,88 @@ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:14:24 + --> $DIR/print_literal.rs:23:71 | -14 | print!("Hello {}", "world"); - | ^^^^^^^ +23 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); + | ^ | = note: `-D print-literal` implied by `-D warnings` error: printing a literal with an empty format string - --> $DIR/print_literal.rs:15:36 + --> $DIR/print_literal.rs:24:24 | -15 | println!("Hello {} {}", world, "world"); +24 | print!("Hello {}", "world"); + | ^^^^^^^ + +error: printing a literal with an empty format string + --> $DIR/print_literal.rs:25:36 + | +25 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:16:26 + --> $DIR/print_literal.rs:26:26 | -16 | println!("Hello {}", "world"); +26 | println!("Hello {}", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:17:30 + --> $DIR/print_literal.rs:27:30 | -17 | println!("10 / 4 is {}", 2.5); +27 | println!("10 / 4 is {}", 2.5); | ^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:18:28 + --> $DIR/print_literal.rs:28:28 | -18 | println!("2 + 1 = {}", 3); +28 | println!("2 + 1 = {}", 3); | ^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:19:31 - | -19 | println!("2 + 1 = {:.4}", 3); - | ^ - -error: printing a literal with an empty format string - --> $DIR/print_literal.rs:20:32 - | -20 | println!("2 + 1 = {:5.4}", 3); - | ^ - -error: printing a literal with an empty format string - --> $DIR/print_literal.rs:21:33 - | -21 | println!("Debug test {:?}", "hello, world"); - | ^^^^^^^^^^^^^^ - -error: printing a literal with an empty format string - --> $DIR/print_literal.rs:26:25 + --> $DIR/print_literal.rs:33:25 | -26 | println!("{0} {1}", "hello", "world"); +33 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:26:34 + --> $DIR/print_literal.rs:33:34 | -26 | println!("{0} {1}", "hello", "world"); +33 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:27:25 + --> $DIR/print_literal.rs:34:25 | -27 | println!("{1} {0}", "hello", "world"); +34 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:27:34 + --> $DIR/print_literal.rs:34:34 | -27 | println!("{1} {0}", "hello", "world"); +34 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:30:33 + --> $DIR/print_literal.rs:37:33 | -30 | println!("{foo} {bar}", foo="hello", bar="world"); +37 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:30:46 + --> $DIR/print_literal.rs:37:46 | -30 | println!("{foo} {bar}", foo="hello", bar="world"); +37 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:31:33 + --> $DIR/print_literal.rs:38:33 | -31 | println!("{bar} {foo}", foo="hello", bar="world"); +38 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: printing a literal with an empty format string - --> $DIR/print_literal.rs:31:46 + --> $DIR/print_literal.rs:38:46 | -31 | println!("{bar} {foo}", foo="hello", bar="world"); +38 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 9c068f1332d..323a83e244a 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,100 +1,88 @@ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:17:32 + --> $DIR/write_literal.rs:26:79 | -17 | write!(&mut v, "Hello {}", "world"); - | ^^^^^^^ +26 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); + | ^ | = note: `-D write-literal` implied by `-D warnings` error: writing a literal with an empty format string - --> $DIR/write_literal.rs:18:44 + --> $DIR/write_literal.rs:27:32 | -18 | writeln!(&mut v, "Hello {} {}", world, "world"); +27 | write!(&mut v, "Hello {}", "world"); + | ^^^^^^^ + +error: writing a literal with an empty format string + --> $DIR/write_literal.rs:28:44 + | +28 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:19:34 + --> $DIR/write_literal.rs:29:34 | -19 | writeln!(&mut v, "Hello {}", "world"); +29 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:20:38 + --> $DIR/write_literal.rs:30:38 | -20 | writeln!(&mut v, "10 / 4 is {}", 2.5); +30 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:21:36 + --> $DIR/write_literal.rs:31:36 | -21 | writeln!(&mut v, "2 + 1 = {}", 3); +31 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:22:39 - | -22 | writeln!(&mut v, "2 + 1 = {:.4}", 3); - | ^ - -error: writing a literal with an empty format string - --> $DIR/write_literal.rs:23:40 - | -23 | writeln!(&mut v, "2 + 1 = {:5.4}", 3); - | ^ - -error: writing a literal with an empty format string - --> $DIR/write_literal.rs:24:41 - | -24 | writeln!(&mut v, "Debug test {:?}", "hello, world"); - | ^^^^^^^^^^^^^^ - -error: writing a literal with an empty format string - --> $DIR/write_literal.rs:29:33 + --> $DIR/write_literal.rs:36:33 | -29 | writeln!(&mut v, "{0} {1}", "hello", "world"); +36 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:29:42 + --> $DIR/write_literal.rs:36:42 | -29 | writeln!(&mut v, "{0} {1}", "hello", "world"); +36 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:30:33 + --> $DIR/write_literal.rs:37:33 | -30 | writeln!(&mut v, "{1} {0}", "hello", "world"); +37 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:30:42 + --> $DIR/write_literal.rs:37:42 | -30 | writeln!(&mut v, "{1} {0}", "hello", "world"); +37 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:33:43 + --> $DIR/write_literal.rs:40:41 | -33 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); + | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:33:58 + --> $DIR/write_literal.rs:40:54 | -33 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); + | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:34:43 + --> $DIR/write_literal.rs:41:41 | -34 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); + | ^^^^^^^ error: writing a literal with an empty format string - --> $DIR/write_literal.rs:34:58 + --> $DIR/write_literal.rs:41:54 | -34 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); + | ^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 1969d423a7d80ccae2fa28693f3a78091f053832 Mon Sep 17 00:00:00 2001 From: Brad Gibson Date: Mon, 23 Apr 2018 10:59:53 -0700 Subject: Corrected messaging to warn against less- to more-strictly align types, rather than the other way around. No logic changes required. --- clippy_lints/src/types.rs | 10 +++++----- tests/ui/cast_alignment.stderr | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9034badd5c5..90f42eba135 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -679,10 +679,10 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } -/// **What it does:** Checks for casts from a more-strictly-aligned pointer to a -/// less-strictly-aligned pointer +/// **What it does:** Checks for casts from a less-strictly-aligned pointer to a +/// more-strictly-aligned pointer /// -/// **Why is this bad?** Dereferencing the resulting pointer is undefined +/// **Why is this bad?** Dereferencing the resulting pointer may be undefined /// behavior. /// /// **Known problems:** None. @@ -695,7 +695,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub CAST_PTR_ALIGNMENT, correctness, - "cast from a pointer to a less-strictly-aligned pointer" + "cast from a pointer to a more-strictly-aligned pointer" } /// Returns the size in bits of an integral type. @@ -986,7 +986,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { cx, CAST_PTR_ALIGNMENT, expr.span, - &format!("casting from `{}` to a less-strictly-aligned pointer (`{}`)", cast_from, cast_to) + &format!("casting from `{}` to a more-strictly-aligned pointer (`{}`)", cast_from, cast_to) ); } } diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index d4fdb5becf9..d9fffdd33f1 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,4 +1,4 @@ -error: casting from `*const u8` to a less-strictly-aligned pointer (`*const u16`) +error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) --> $DIR/cast_alignment.rs:9:5 | 9 | (&1u8 as *const u8) as *const u16; @@ -6,7 +6,7 @@ error: casting from `*const u8` to a less-strictly-aligned pointer (`*const u16` | = note: `-D cast-ptr-alignment` implied by `-D warnings` -error: casting from `*mut u8` to a less-strictly-aligned pointer (`*mut u16`) +error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) --> $DIR/cast_alignment.rs:10:5 | 10 | (&mut 1u8 as *mut u8) as *mut u16; -- cgit 1.4.1-3-g733a5 From 3c38a36d5a655fa40a953c234b027d6bbbb430da Mon Sep 17 00:00:00 2001 From: Joe Clay <27cupsofcoffee@gmail.com> Date: Thu, 19 Apr 2018 20:34:31 +0100 Subject: Implement lint for destructuring tuple structs with a let and a match (closes #2671) --- clippy_lints/src/infallible_destructuring_match.rs | 79 ++++++++++++++++++++ clippy_lints/src/lib.rs | 4 ++ tests/ui/infallible_destructuring_match.rs | 83 ++++++++++++++++++++++ tests/ui/infallible_destructuring_match.stderr | 28 ++++++++ 4 files changed, 194 insertions(+) create mode 100644 clippy_lints/src/infallible_destructuring_match.rs create mode 100644 tests/ui/infallible_destructuring_match.rs create mode 100644 tests/ui/infallible_destructuring_match.stderr diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs new file mode 100644 index 00000000000..a2b3846b986 --- /dev/null +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -0,0 +1,79 @@ +use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; +use rustc::hir::*; +use rustc::lint::*; + +/// **What it does:** Checks for matches being used to destructure a single-variant enum +/// or tuple struct where a `let` will suffice. +/// +/// **Why is this bad?** Just readability – `let` doesn't nest, whereas a `match` does. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// enum Wrapper { +/// Data(i32), +/// } +/// +/// let wrapper = Wrapper::Data(42); +/// +/// let data = match wrapper { +/// Wrapper::Data(i) => i, +/// }; +/// ``` +/// +/// The correct use would be: +/// ```rust +/// enum Wrapper { +/// Data(i32), +/// } +/// +/// let wrapper = Wrapper::Data(42); +/// let Wrapper::Data(data) = wrapper; +/// ``` +declare_clippy_lint! { + pub INFALLIBLE_DESTRUCTURING_MATCH, + style, + "a match statement with a single infallible arm instead of a `let`" +} + +#[derive(Copy, Clone, Default)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(INFALLIBLE_DESTRUCTURING_MATCH) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) { + if_chain! { + if let Some(ref expr) = local.init; + if let Expr_::ExprMatch(ref target, ref arms, MatchSource::Normal) = expr.node; + if arms.len() == 1 && arms[0].pats.len() == 1 && arms[0].guard.is_none(); + if let PatKind::TupleStruct(QPath::Resolved(None, ref variant_name), ref args, _) = arms[0].pats[0].node; + if args.len() == 1; + if let Some(arg) = get_arg_name(&args[0]); + let body = remove_blocks(&arms[0].body); + if match_var(body, arg); + + then { + span_lint_and_sugg( + cx, + INFALLIBLE_DESTRUCTURING_MATCH, + local.span, + "you seem to be trying to use match to destructure a single infallible pattern. \ + Consider using `let`", + "try this", + format!( + "let {}({}) = {};", + snippet(cx, variant_name.span, ".."), + snippet(cx, local.pat.span, ".."), + snippet(cx, target.span, ".."), + ), + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bdbdff92d3c..33dd352b657 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -133,6 +133,7 @@ pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; +pub mod infallible_destructuring_match; pub mod infinite_iter; pub mod inline_fn_without_body; pub mod int_plus_one; @@ -407,6 +408,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); reg.register_late_lint_pass(box map_unit_fn::Pass); + reg.register_late_lint_pass(box infallible_destructuring_match::Pass); reg.register_lint_group("clippy_restriction", vec![ @@ -522,6 +524,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, infinite_iter::INFINITE_ITER, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, @@ -688,6 +691,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs new file mode 100644 index 00000000000..270272261b5 --- /dev/null +++ b/tests/ui/infallible_destructuring_match.rs @@ -0,0 +1,83 @@ +#![feature(exhaustive_patterns)] +#![allow(let_and_return)] + +enum SingleVariantEnum { + Variant(i32), +} + +struct TupleStruct(i32); + +enum EmptyEnum {} + +fn infallible_destructuring_match_enum() { + let wrapper = SingleVariantEnum::Variant(0); + + // This should lint! + let data = match wrapper { + SingleVariantEnum::Variant(i) => i, + }; + + // This shouldn't! + let data = match wrapper { + SingleVariantEnum::Variant(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + SingleVariantEnum::Variant(i) => -1, + }; + + let SingleVariantEnum::Variant(data) = wrapper; +} + +fn infallible_destructuring_match_struct() { + let wrapper = TupleStruct(0); + + // This should lint! + let data = match wrapper { + TupleStruct(i) => i, + }; + + // This shouldn't! + let data = match wrapper { + TupleStruct(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + TupleStruct(i) => -1, + }; + + let TupleStruct(data) = wrapper; +} + +fn never_enum() { + let wrapper: Result = Ok(23); + + // This should lint! + let data = match wrapper { + Ok(i) => i, + }; + + // This shouldn't! + let data = match wrapper { + Ok(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + Ok(i) => -1, + }; + + let Ok(data) = wrapper; +} + +impl EmptyEnum { + fn match_on(&self) -> ! { + // The lint shouldn't pick this up, as `let` won't work here! + let data = match *self {}; + data + } +} + +fn main() {} diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr new file mode 100644 index 00000000000..8ee73bbfde8 --- /dev/null +++ b/tests/ui/infallible_destructuring_match.stderr @@ -0,0 +1,28 @@ +error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` + --> $DIR/infallible_destructuring_match.rs:16:5 + | +16 | / let data = match wrapper { +17 | | SingleVariantEnum::Variant(i) => i, +18 | | }; + | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` + | + = note: `-D infallible-destructuring-match` implied by `-D warnings` + +error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` + --> $DIR/infallible_destructuring_match.rs:37:5 + | +37 | / let data = match wrapper { +38 | | TupleStruct(i) => i, +39 | | }; + | |______^ help: try this: `let TupleStruct(data) = wrapper;` + +error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` + --> $DIR/infallible_destructuring_match.rs:58:5 + | +58 | / let data = match wrapper { +59 | | Ok(i) => i, +60 | | }; + | |______^ help: try this: `let Ok(data) = wrapper;` + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From f0e09d43c9047c846ae8361d1652ac5406c3cf3d Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Tue, 17 Apr 2018 17:13:19 -0700 Subject: Make cast_ptr_alignment ignore c_void --- clippy_lints/src/types.rs | 7 ++++++- clippy_lints/src/utils/paths.rs | 2 ++ tests/ui/cast_alignment.rs | 7 +++++++ tests/ui/cast_alignment.stderr | 16 ++++++++-------- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 90f42eba135..69c37bb6305 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -13,7 +13,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, - multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, + match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; use utils::paths; use consts::{constant, Constant}; @@ -981,6 +981,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi()); if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi()); if from_align < to_align; + // with c_void, we inherently need to trust the user + if ! ( + match_type(cx, from_ptr_ty.ty, &paths::C_VOID) + || match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC) + ); then { span_lint( cx, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 8f823c12cf3..fbc3cc303a8 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -20,6 +20,8 @@ pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; +pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"]; +pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 4985a90bdf5..32e2f93169e 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -1,5 +1,9 @@ //! Test casts for alignment issues +#![feature(libc)] + +extern crate libc; + #[warn(cast_ptr_alignment)] #[allow(no_effect, unnecessary_operation, cast_lossless)] fn main() { @@ -16,4 +20,7 @@ fn main() { // cast to less-strictly-aligned type (&1u16 as *const u16) as *const u8; (&mut 1u16 as *mut u16) as *mut u8; + // For c_void, we should trust the user. See #2677 + (&1u32 as *const u32 as *const std::os::raw::c_void) as *const u32; + (&1u32 as *const u32 as *const libc::c_void) as *const u32; } diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index d9fffdd33f1..42df78a37a6 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,15 +1,15 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:9:5 - | -9 | (&1u8 as *const u8) as *const u16; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D cast-ptr-alignment` implied by `-D warnings` + --> $DIR/cast_alignment.rs:13:5 + | +13 | (&1u8 as *const u8) as *const u16; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:10:5 + --> $DIR/cast_alignment.rs:14:5 | -10 | (&mut 1u8 as *mut u8) as *mut u16; +14 | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 36233789d473cf10e235b12b9421f8ed94f0ca26 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 24 Apr 2018 21:04:43 +0200 Subject: Mention util/update_lints.py --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a9f749e65a..afb57610914 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -175,6 +175,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. +It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/update_lints.py` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time. ```rust // ./clippy_lints/src/else_if_without_else.rs -- cgit 1.4.1-3-g733a5 From 9b14ad493b54a336d1b48f9caec46a4bc37bf629 Mon Sep 17 00:00:00 2001 From: Evan Simmons Date: Thu, 12 Apr 2018 17:42:57 -0700 Subject: New excessive precision lint for floats --- clippy_lints/src/excessive_precision.rs | 141 ++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 4 + tests/ui/approx_const.rs | 2 +- tests/ui/approx_const.stderr | 4 +- tests/ui/excessive_precision.rs | 52 ++++++++++++ tests/ui/excessive_precision.stderr | 100 ++++++++++++++++++++++ 6 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/excessive_precision.rs create mode 100644 tests/ui/excessive_precision.rs create mode 100644 tests/ui/excessive_precision.stderr diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs new file mode 100644 index 00000000000..b96ae18828e --- /dev/null +++ b/clippy_lints/src/excessive_precision.rs @@ -0,0 +1,141 @@ +use rustc::hir; +use rustc::lint::*; +use rustc::ty::TypeVariants; +use std::f32; +use std::f64; +use std::fmt; +use syntax::ast::*; +use syntax_pos::symbol::Symbol; +use utils::span_lint_and_sugg; + +/// **What it does:** Checks for float literals with a precision greater +/// than that supported by the underlying type +/// +/// **Why is this bad?** Rust will truncate the literal silently. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// // Bad +/// Insert a short example of code that triggers the lint +/// let v: f32 = 0.123_456_789_9; +/// println!("{}", v); // 0.123_456_789 +/// +/// // Good +/// Insert a short example of improved code that doesn't trigger the lint +/// let v: f64 = 0.123_456_789_9; +/// println!("{}", v); // 0.123_456_789_9 +/// ``` +declare_clippy_lint! { + pub EXCESSIVE_PRECISION, + style, + "excessive precision for float literal" +} + +pub struct ExcessivePrecision; + +impl LintPass for ExcessivePrecision { + fn get_lints(&self) -> LintArray { + lint_array!(EXCESSIVE_PRECISION) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + if_chain! { + let ty = cx.tables.expr_ty(expr); + if let TypeVariants::TyFloat(ref fty) = ty.sty; + if let hir::ExprLit(ref lit) = expr.node; + if let LitKind::Float(ref sym, _) | LitKind::FloatUnsuffixed(ref sym) = lit.node; + if let Some(sugg) = self.check(sym, fty); + then { + span_lint_and_sugg( + cx, + EXCESSIVE_PRECISION, + expr.span, + "float has excessive precision", + "consider changing the type or truncating it to", + sugg, + ); + } + } + } +} + +impl ExcessivePrecision { + // None if nothing to lint, Some(suggestion) if lint neccessary + fn check(&self, sym: &Symbol, fty: &FloatTy) -> Option { + let max = max_digits(fty); + let sym_str = sym.as_str(); + let formatter = FloatFormat::new(&sym_str); + let digits = count_digits(&sym_str); + // Try to bail out if the float is for sure fine. + // If its within the 2 decimal digits of being out of precision we + // check if the parsed representation is the same as the string + // since we'll need the truncated string anyway. + if digits > max as usize { + let sr = match *fty { + FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), + FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), + }; + // We know this will parse since we are in LatePass + let s = sr.unwrap(); + + if sym_str == s { + None + } else { + Some(s) + } + } else { + None + } + } +} + +fn max_digits(fty: &FloatTy) -> u32 { + match fty { + FloatTy::F32 => f32::DIGITS, + FloatTy::F64 => f64::DIGITS, + } +} + +fn count_digits(s: &str) -> usize { + s.chars() + .filter(|c| *c != '-' || *c != '.') + .take_while(|c| *c != 'e' || *c != 'E') + .fold(0, |count, c| { + // leading zeros + if c == '0' && count == 0 { + count + } else { + count + 1 + } + }) +} + +enum FloatFormat { + LowerExp, + UpperExp, + Normal, +} +impl FloatFormat { + fn new(s: &str) -> Self { + s.chars() + .find_map(|x| match x { + 'e' => Some(FloatFormat::LowerExp), + 'E' => Some(FloatFormat::UpperExp), + _ => None, + }) + .unwrap_or(FloatFormat::Normal) + } + fn format(&self, f: T) -> String + where T: fmt::UpperExp + fmt::LowerExp + fmt::Display { + match self { + FloatFormat::LowerExp => format!("{:e}", f), + FloatFormat::UpperExp => format!("{:E}", f), + FloatFormat::Normal => format!("{}", f), + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 890d7a6e22e..25a2038bdd0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -13,6 +13,8 @@ // FIXME(mark-i-m) remove after i128 stablization merges #![allow(stable_features)] #![feature(i128, i128_type)] +#![feature(iterator_find_map)] + #[macro_use] extern crate rustc; @@ -124,6 +126,7 @@ pub mod erasing_op; pub mod escape; pub mod eta_reduction; pub mod eval_order_dependence; +pub mod excessive_precision; pub mod explicit_write; pub mod fallible_impl_from; pub mod format; @@ -294,6 +297,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold)); reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); reg.register_late_lint_pass(box enum_clike::UnportableVariant); + reg.register_late_lint_pass(box excessive_precision::ExcessivePrecision); reg.register_late_lint_pass(box bit_mask::BitMask::new(conf.verbose_bit_mask_threshold)); reg.register_late_lint_pass(box ptr::PointerPass); reg.register_late_lint_pass(box needless_bool::NeedlessBool); diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 394aa9d1eb3..d353d9075d4 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -42,7 +42,7 @@ fn main() { let my_ln_2 = 0.6931471805599453; let no_ln_2 = 0.693; - let my_log10_e = 0.43429448190325182; + let my_log10_e = 0.4342944819032518; let no_log10_e = 0.434; let my_log2_e = 1.4426950408889634; diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index dda28433d7a..e5d2ba29605 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -87,8 +87,8 @@ error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it d error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly --> $DIR/approx_const.rs:45:22 | -45 | let my_log10_e = 0.43429448190325182; - | ^^^^^^^^^^^^^^^^^^^ +45 | let my_log10_e = 0.4342944819032518; + | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly --> $DIR/approx_const.rs:48:21 diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs new file mode 100644 index 00000000000..d209367cc3b --- /dev/null +++ b/tests/ui/excessive_precision.rs @@ -0,0 +1,52 @@ +#![feature(plugin, custom_attribute)] +#![warn(excessive_precision)] +#![allow(print_literal)] + +fn main() { + // TODO add prefix tests + // Consts + const GOOD32_SUF: f32 = 0.123_456_f32; + const GOOD32: f32 = 0.123_456; + const GOOD32_SM: f32 = 0.000_000_000_1; + const GOOD64: f64 = 0.123_456_789_012; + const GOOD64_SM: f32 = 0.000_000_000_000_000_1; + + const BAD32_1: f32 = 0.123_456_789_f32; + const BAD32_2: f32 = 0.123_456_789; + const BAD32_3: f32 = 0.100_000_000_000_1; + + const BAD64_1: f64 = 0.123_456_789_012_345_67f64; + const BAD64_2: f64 = 0.123_456_789_012_345_67; + const BAD64_3: f64 = 0.100_000_000_000_000_000_1; + + // Literal + println!("{}", 8.888_888_888_888_888_888_888); + + // TODO add inferred type tests for f32 + // TODO add tests cases exactly on the edge + // Locals + let good32: f32 = 0.123_456_f32; + let good32_2: f32 = 0.123_456; + + let good64: f64 = 0.123_456_789_012f64; + let good64: f64 = 0.123_456_789_012; + let good64_2 = 0.123_456_789_012; + + let bad32_1: f32 = 1.123_456_789_f32; + let bad32_2: f32 = 1.123_456_789; + + let bad64_1: f64 = 0.123_456_789_012_345_67f64; + let bad64_2: f64 = 0.123_456_789_012_345_67; + let bad64_3 = 0.123_456_789_012_345_67; + + // TODO Vectors / nested vectors + let vec32: Vec = vec![0.123_456_789]; + let vec64: Vec = vec![0.123_456_789_123_456_789]; + + // Exponential float notation + let good_e32: f32 = 1e-10; + let bad_e32: f32 = 1.123_456_788_888e-10; + + let good_bige32: f32 = 1E-10; + let bad_bige32: f32 = 1.123_456_788_888E-10; +} diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr new file mode 100644 index 00000000000..de022afb512 --- /dev/null +++ b/tests/ui/excessive_precision.stderr @@ -0,0 +1,100 @@ +error: float has excessive precision + --> $DIR/excessive_precision.rs:14:26 + | +14 | const BAD32_1: f32 = 0.123_456_789_f32; + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` + | + = note: `-D excessive-precision` implied by `-D warnings` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:15:26 + | +15 | const BAD32_2: f32 = 0.123_456_789; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:16:26 + | +16 | const BAD32_3: f32 = 0.100_000_000_000_1; + | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:18:26 + | +18 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:19:26 + | +19 | const BAD64_2: f64 = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:20:26 + | +20 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:23:20 + | +23 | println!("{}", 8.888_888_888_888_888_888_888); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.88888888888889` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:35:24 + | +35 | let bad32_1: f32 = 1.123_456_789_f32; + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:36:24 + | +36 | let bad32_2: f32 = 1.123_456_789; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:38:24 + | +38 | let bad64_1: f64 = 0.123_456_789_012_345_67f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:39:24 + | +39 | let bad64_2: f64 = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:40:19 + | +40 | let bad64_3 = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:43:32 + | +43 | let vec32: Vec = vec![0.123_456_789]; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:44:32 + | +44 | let vec64: Vec = vec![0.123_456_789_123_456_789]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678912345678` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:48:24 + | +48 | let bad_e32: f32 = 1.123_456_788_888e-10; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568e-10` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:51:27 + | +51 | let bad_bige32: f32 = 1.123_456_788_888E-10; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568E-10` + +error: aborting due to 16 previous errors + -- cgit 1.4.1-3-g733a5 From f327f261130d090c7eb0b924237f5e321d680399 Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 02:31:36 -0400 Subject: Fix missing line comment in doc_markdown example rustfmt [wrapped the line](https://github.com/rust-lang-nursery/rust-clippy/commit/b25b6b3355efa33c797f4a37afb2f516531ad581#diff-561823671726302d969756ded53a13a7L22), so we need a second `///` --- clippy_lints/src/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 5f6c15e222d..10043df9cbf 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -21,7 +21,7 @@ use url::Url; /// **Examples:** /// ```rust /// /// Do something with the foo_bar parameter. See also -/// that::other::module::foo. +/// /// that::other::module::foo. /// // ^ `foo_bar` and `that::other::module::foo` should be ticked. /// fn doit(foo_bar) { .. } /// ``` -- cgit 1.4.1-3-g733a5 From 8ad5cb61708823ea15598bf5d7b42cc29693e8cb Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 02:37:40 -0400 Subject: Fix missing line comment in crosspointer_transmute example --- clippy_lints/src/transmute.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 68321e7bd5e..7f367e43732 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -52,7 +52,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// core::intrinsics::transmute(t)` // where the result type is the same as -/// `*t` or `&t`'s +/// // `*t` or `&t`'s /// ``` declare_clippy_lint! { pub CROSSPOINTER_TRANSMUTE, -- cgit 1.4.1-3-g733a5 From 7f0f8acb42e8dcec9336967201f0b2c64cf8c2ec Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 02:39:14 -0400 Subject: Fix missing line comment in drop_ref example --- clippy_lints/src/drop_forget_ref.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 7acc7805f82..086dd2e20a8 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -17,7 +17,7 @@ use utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; /// ```rust /// let mut lock_guard = mutex.lock(); /// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex -/// still locked +/// // still locked /// operation_that_requires_mutex_to_be_unlocked(); /// ``` declare_clippy_lint! { -- cgit 1.4.1-3-g733a5 From 78b141d937610e6a2bb345057d205bb9f9a2b980 Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 02:40:19 -0400 Subject: Fix missing line comments in {drop,forget}_copy examples --- clippy_lints/src/drop_forget_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 086dd2e20a8..007accc7fbf 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -60,7 +60,7 @@ declare_clippy_lint! { /// ```rust /// let x:i32 = 42; // i32 implements Copy /// std::mem::drop(x) // A copy of x is passed to the function, leaving the -/// original unaffected +/// // original unaffected /// ``` declare_clippy_lint! { pub DROP_COPY, @@ -87,7 +87,7 @@ declare_clippy_lint! { /// ```rust /// let x:i32 = 42; // i32 implements Copy /// std::mem::forget(x) // A copy of x is passed to the function, leaving the -/// original unaffected +/// // original unaffected /// ``` declare_clippy_lint! { pub FORGET_COPY, -- cgit 1.4.1-3-g733a5 From c9c649b315555c1aa8371599898625184f6d3d83 Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 02:43:16 -0400 Subject: Remove extraneous `'s in {wrong,crosspointer}_transmute examples --- clippy_lints/src/transmute.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 7f367e43732..63ea96bbcea 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -16,7 +16,7 @@ use utils::{opt_def_id, sugg}; /// /// **Example:** /// ```rust -/// let ptr: *const T = core::intrinsics::transmute('x')` +/// let ptr: *const T = core::intrinsics::transmute('x') /// ``` declare_clippy_lint! { pub WRONG_TRANSMUTE, @@ -51,7 +51,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// core::intrinsics::transmute(t)` // where the result type is the same as +/// core::intrinsics::transmute(t) // where the result type is the same as /// // `*t` or `&t`'s /// ``` declare_clippy_lint! { -- cgit 1.4.1-3-g733a5 From cc7d66aa9cae2fb9c97d534cb9244d98f5d67a0d Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Fri, 27 Apr 2018 14:00:43 +0200 Subject: rustup --- CHANGELOG.md | 2 + README.md | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/lib.rs | 3 + clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- mini-macro/src/lib.rs | 2 +- tests/ui/infallible_destructuring_match.rs | 2 +- tests/ui/result_map_unit_fn.rs | 1 + tests/ui/result_map_unit_fn.stderr | 98 +++++++++++++++--------------- 10 files changed, 61 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27420e47238..650c2a9d893 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -615,6 +615,7 @@ All notable changes to this project will be documented in this file. [`eq_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eq_op [`erasing_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#erasing_op [`eval_order_dependence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eval_order_dependence +[`excessive_precision`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#excessive_precision [`expl_impl_clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_into_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_into_iter_loop @@ -644,6 +645,7 @@ All notable changes to this project will be documented in this file. [`inconsistent_digit_grouping`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask +[`infallible_destructuring_match`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infallible_destructuring_match [`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter [`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always [`inline_fn_without_body`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_fn_without_body diff --git a/README.md b/README.md index d0ba8b0948a..208aa550882 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 255 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 257 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index cb359daba44..83c9c0f1d1a 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -5,7 +5,7 @@ use rustc::ty; use rustc::hir::def::Def; use std::collections::HashSet; use syntax::ast; -use syntax::abi::Abi; +use rustc_target::spec::abi::Abi; use syntax::codemap::Span; use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c2b0895942f..a952f5081f4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -19,6 +19,7 @@ #[macro_use] extern crate rustc; extern crate rustc_typeck; +extern crate rustc_target; extern crate syntax; extern crate syntax_pos; @@ -516,6 +517,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { eta_reduction::REDUNDANT_CLOSURE, eval_order_dependence::DIVERGING_SUB_EXPRESSION, eval_order_dependence::EVAL_ORDER_DEPENDENCE, + excessive_precision::EXCESSIVE_PRECISION, explicit_write::EXPLICIT_WRITE, format::USELESS_FORMAT, formatting::POSSIBLE_MISSING_COMMA, @@ -692,6 +694,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::MODULE_INCEPTION, eq_op::OP_REF, eta_reduction::REDUNDANT_CLOSURE, + excessive_precision::EXCESSIVE_PRECISION, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 02048c39265..944f20fe99d 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -6,7 +6,7 @@ use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; -use syntax::abi::Abi; +use rustc_target::spec::abi::Abi; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bfb6160d3cd..39df3698064 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,7 +8,7 @@ use rustc::hir::map::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, layout}; +use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}}; use rustc_errors; use std::borrow::Cow; use std::env; diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 3caf85103b5..9f88de62677 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro)] +#![feature(proc_macro, proc_macro_non_items)] extern crate proc_macro; use proc_macro::{TokenStream, quote}; diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 270272261b5..6f3d7a3ff2b 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,4 +1,4 @@ -#![feature(exhaustive_patterns)] +#![feature(exhaustive_patterns, never_type)] #![allow(let_and_return)] enum SingleVariantEnum { diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index 8f3c1579987..dd163439d78 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -1,3 +1,4 @@ +#![feature(never_type)] #![warn(result_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 199f5e7cf97..9ec24a7e97b 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:32:5 + --> $DIR/result_map_unit_fn.rs:33:5 | -32 | x.field.map(do_nothing); +33 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -9,183 +9,183 @@ error: called `map(f)` on an Result value where `f` is a unit function = note: `-D result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:34:5 + --> $DIR/result_map_unit_fn.rs:35:5 | -34 | x.field.map(do_nothing); +35 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:36:5 + --> $DIR/result_map_unit_fn.rs:37:5 | -36 | x.field.map(diverge); +37 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:42:5 + --> $DIR/result_map_unit_fn.rs:43:5 | -42 | x.field.map(|value| x.do_result_nothing(value + captured)); +43 | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:44:5 + --> $DIR/result_map_unit_fn.rs:45:5 | -44 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); +45 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:47:5 + --> $DIR/result_map_unit_fn.rs:48:5 | -47 | x.field.map(|value| do_nothing(value + captured)); +48 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:49:5 + --> $DIR/result_map_unit_fn.rs:50:5 | -49 | x.field.map(|value| { do_nothing(value + captured) }); +50 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:51:5 + --> $DIR/result_map_unit_fn.rs:52:5 | -51 | x.field.map(|value| { do_nothing(value + captured); }); +52 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:53:5 + --> $DIR/result_map_unit_fn.rs:54:5 | -53 | x.field.map(|value| { { do_nothing(value + captured); } }); +54 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:56:5 + --> $DIR/result_map_unit_fn.rs:57:5 | -56 | x.field.map(|value| diverge(value + captured)); +57 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:58:5 + --> $DIR/result_map_unit_fn.rs:59:5 | -58 | x.field.map(|value| { diverge(value + captured) }); +59 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:60:5 + --> $DIR/result_map_unit_fn.rs:61:5 | -60 | x.field.map(|value| { diverge(value + captured); }); +61 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:62:5 + --> $DIR/result_map_unit_fn.rs:63:5 | -62 | x.field.map(|value| { { diverge(value + captured); } }); +63 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:67:5 + --> $DIR/result_map_unit_fn.rs:68:5 | -67 | x.field.map(|value| { let y = plus_one(value + captured); }); +68 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:69:5 + --> $DIR/result_map_unit_fn.rs:70:5 | -69 | x.field.map(|value| { plus_one(value + captured); }); +70 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:71:5 + --> $DIR/result_map_unit_fn.rs:72:5 | -71 | x.field.map(|value| { { plus_one(value + captured); } }); +72 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:74:5 + --> $DIR/result_map_unit_fn.rs:75:5 | -74 | x.field.map(|ref value| { do_nothing(value + captured) }); +75 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:77:5 + --> $DIR/result_map_unit_fn.rs:78:5 | -77 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:79:5 + --> $DIR/result_map_unit_fn.rs:80:5 | -79 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:83:5 + --> $DIR/result_map_unit_fn.rs:84:5 | -83 | x.field.map(|value| { +84 | x.field.map(|value| { | _____^ | |_____| | || -84 | || do_nothing(value); -85 | || do_nothing(value) -86 | || }); +85 | || do_nothing(value); +86 | || do_nothing(value) +87 | || }); | ||______^- help: try this: `if let Ok(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:87:5 + --> $DIR/result_map_unit_fn.rs:88:5 | -87 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:91:5 + --> $DIR/result_map_unit_fn.rs:92:5 | -91 | "12".parse::().map(diverge); +92 | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:97:5 + --> $DIR/result_map_unit_fn.rs:98:5 | -97 | y.map(do_nothing); +98 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_y) = y { do_nothing(...) }` -- cgit 1.4.1-3-g733a5 From 6f47cb1102d8d92ed07d65eac342992a50bdf197 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 27 Apr 2018 08:52:16 +0200 Subject: Add TOC to contribution instructions Also changed some headings and re-ordered the paragraphs in the testing guide. (I used [vim-markdown-toc](https://github.com/mzlogin/vim-markdown-toc) to generate it automatically.) --- CONTRIBUTING.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index afb57610914..d8089675ead 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,16 @@ visit the `#clippy` IRC channel on `irc.mozilla.org`. All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). +* [Getting started](#getting-started) + * [Finding something to fix/improve](#finding-something-to-fiximprove) +* [Writing code](#writing-code) + * [Author lint](#author-lint) + * [Documentation](#documentation) + * [Running test suite](#running-test-suite) + * [Testing manually](#testing-manually) + * [How Clippy works](#how-clippy-works) +* [Contributions](#contributions) + ## Getting started High level approach: @@ -48,7 +58,7 @@ be more involved and require verifying types. The lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. -### Writing code +## Writing code Compiling clippy from scratch can take almost a minute or more depending on your machine. However, since Rust 1.24.0 incremental compilation is enabled by default and compile times for small changes should be quick. @@ -59,7 +69,7 @@ to lint-writing, though it does get into advanced stuff. Most lints consist of a of this. -#### Author lint +### Author lint There is also the internal `author` lint to generate clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. @@ -96,7 +106,7 @@ if_chain! { If the command was executed successfully, you can copy the code over to where you are implementing your lint. -#### Documentation +### Documentation Please document your lint with a doc comment akin to the following: @@ -122,11 +132,7 @@ Once your lint is merged it will show up in the [lint list](https://rust-lang-nu ### Running test suite -Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. -Of course there's little sense in writing the output yourself or copying it around. -Therefore you can simply run `tests/ui/update-all-references.sh` (after running -`cargo test`) and check whether the output looks as you expect with `git diff`. Commit all -`*.stderr` files, too. +Use `cargo test` to run the whole testsuite. If you don't want to wait for all tests to finish, you can also execute a single test file by using `TESTNAME` to specify the test to run: @@ -134,6 +140,12 @@ If you don't want to wait for all tests to finish, you can also execute a single TESTNAME=ui/empty_line_after_outer_attr cargo test --test compile-test ``` +Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. +Of course there's little sense in writing the output yourself or copying it around. +Therefore you should use `tests/ui/update-all-references.sh` (after running +`cargo test`) and check whether the output looks as you expect with `git diff`. Commit all +`*.stderr` files, too. + ### Testing manually Manually testing against an example file is useful if you have added some -- cgit 1.4.1-3-g733a5 From 3373fa97e216f8d06157cebc38920b98e05cc08f Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 27 Apr 2018 18:45:14 -0400 Subject: Add third variant to {pub_,}enum_variant_names examples The default value for `enum-variant-name-threshold` is 3, so the old examples (which only have two enum variants) don't actually trigger the lint by default. --- clippy_lints/src/enum_variants.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index e769c2acc4b..ef6d99e551d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -20,6 +20,7 @@ use utils::{camel_case_from, camel_case_until, in_macro}; /// enum Cake { /// BlackForestCake, /// HummingbirdCake, +/// BattenbergCake, /// } /// ``` declare_clippy_lint! { @@ -41,6 +42,7 @@ declare_clippy_lint! { /// enum Cake { /// BlackForestCake, /// HummingbirdCake, +/// BattenbergCake, /// } /// ``` declare_clippy_lint! { -- cgit 1.4.1-3-g733a5 From 1712e18b775cb1618c17c9b029d0493c59929ce3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 28 Apr 2018 12:56:31 +0200 Subject: Rustup to latest nightly Due to https://github.com/rust-lang/rust/pull/48995 and https://github.com/rust-lang/rust/pull/49894 --- clippy_lints/src/copies.rs | 6 +++--- clippy_lints/src/enum_variants.rs | 6 +++--- clippy_lints/src/non_expressive_names.rs | 4 ++-- clippy_lints/src/unsafe_removed_from_name.rs | 4 ++-- clippy_lints/src/unused_label.rs | 4 ++-- clippy_lints/src/utils/internal_lints.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 4 ++-- clippy_lints/src/write.rs | 8 ++++---- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 1434a1437f0..5cbf7d03191 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -3,7 +3,7 @@ use rustc::ty::Ty; use rustc::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax::util::small_vector::SmallVector; use utils::{SpanlessEq, SpanlessHash}; use utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; @@ -262,8 +262,8 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { } /// Return the list of bindings in a pattern. -fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { - fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { +fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { + fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { match pat.node { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), PatKind::TupleStruct(_, ref pats, _) => for pat in pats { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index e769c2acc4b..860cd69303e 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Span; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use utils::{span_help_and_lint, span_lint}; use utils::{camel_case_from, camel_case_until, in_macro}; @@ -99,7 +99,7 @@ declare_clippy_lint! { } pub struct EnumVariantNames { - modules: Vec<(InternedString, String)>, + modules: Vec<(LocalInternedString, String)>, threshold: u64, } @@ -118,7 +118,7 @@ impl LintPass for EnumVariantNames { } } -fn var2str(var: &Variant) -> InternedString { +fn var2str(var: &Variant) -> LocalInternedString { var.node.ident.name.as_str() } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 394bc4bcfbc..022591329b5 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::codemap::Span; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax::ast::*; use syntax::attr; use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; @@ -73,7 +73,7 @@ impl LintPass for NonExpressiveNames { } struct ExistingName { - interned: InternedString, + interned: LocalInternedString, span: Span, len: usize, whitelist: &'static [&'static str], diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 8ecc95fb72c..ff460e50d8c 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Span; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use utils::span_lint; /// **What it does:** Checks for imports that remove "unsafe" from an item's @@ -75,6 +75,6 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, spa } } -fn contains_unsafe(name: &InternedString) -> bool { +fn contains_unsafe(name: &LocalInternedString) -> bool { name.contains("Unsafe") || name.contains("unsafe") } diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index b009420bdb6..7e3f31d76c0 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visit use std::collections::HashMap; use syntax::ast; use syntax::codemap::Span; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use utils::{in_macro, span_lint}; /// **What it does:** Checks for unused labels. @@ -30,7 +30,7 @@ declare_clippy_lint! { pub struct UnusedLabel; struct UnusedLabelVisitor<'a, 'tcx: 'a> { - labels: HashMap, + labels: HashMap, cx: &'a LateContext<'a, 'tcx>, } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 666db3e0692..5c9500afa46 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use utils::{match_qpath, paths, span_lint}; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax::ast::{Crate as AstCrate, ItemKind, Name, NodeId}; use syntax::codemap::Span; use std::collections::{HashMap, HashSet}; @@ -76,7 +76,7 @@ impl EarlyLintPass for Clippy { .find(|item| item.ident.name == "paths") { if let ItemKind::Mod(ref paths_mod) = paths.node { - let mut last_name: Option = None; + let mut last_name: Option = None; for item in &paths_mod.items { let name = item.ident.name.as_str(); if let Some(ref last_name) = last_name { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 39df3698064..6701ad00722 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -116,7 +116,7 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { use syntax::symbol; struct AbsolutePathBuffer { - names: Vec, + names: Vec, } impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { @@ -302,7 +302,7 @@ pub fn implements_trait<'a, 'tcx>( cx.tcx .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); cx.tcx.infer_ctxt().enter(|infcx| { - traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) + traits::SelectionContext::new(&infcx).infcx().predicate_must_hold(&obligation) }) } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 67c72bd9859..9a32d4e696c 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use std::ops::Deref; use syntax::ast::LitKind; use syntax::ptr; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax_pos::Span; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; use utils::{opt_def_id, paths, last_path_segment}; @@ -389,7 +389,7 @@ where } /// Check for fmtstr = "... \n" -fn has_newline_end(args: &HirVec, fmtstr: InternedString, fmtlen: usize) -> bool { +fn has_newline_end(args: &HirVec, fmtstr: LocalInternedString, fmtlen: usize) -> bool { if_chain! { // check the final format string part if let Some('\n') = fmtstr.chars().last(); @@ -407,7 +407,7 @@ fn has_newline_end(args: &HirVec, fmtstr: InternedString, fmtlen: usize) - } /// Check for writeln!(v, "") / println!("") -fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: InternedString, fmtlen: usize) -> Option { +fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: LocalInternedString, fmtlen: usize) -> Option { if_chain! { // check that the string is empty if fmtlen == 1; @@ -427,7 +427,7 @@ fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: Inter } /// Returns the slice of format string parts in an `Arguments::new_v1` call. -fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(InternedString, usize)> { +fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(LocalInternedString, usize)> { if_chain! { if let ExprAddrOf(_, ref expr) = expr.node; // &["…", "…", …] if let ExprArray(ref exprs) = expr.node; -- cgit 1.4.1-3-g733a5 From 7de706b34b4ff04f58a2a5c3f72a7b0cab3488f6 Mon Sep 17 00:00:00 2001 From: Yusuf Simonson Date: Mon, 30 Apr 2018 06:20:39 +0700 Subject: Lint for multiple versions of dependencies --- README.md | 1 + clippy_lints/Cargo.toml | 1 + clippy_lints/src/lib.rs | 10 ++++ clippy_lints/src/multiple_crate_versions.rs | 72 +++++++++++++++++++++++++++++ util/lintlib.py | 1 + util/update_lints.py | 1 + 6 files changed, 86 insertions(+) create mode 100644 clippy_lints/src/multiple_crate_versions.rs diff --git a/README.md b/README.md index 208aa550882..50c2bd95b7f 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ We have a bunch of lint categories to allow you to choose how much clippy is sup * `clippy_style` (code that should be written in a more idiomatic way) * `clippy_complexity` (code that does something simple but in a complex way) * `clippy_perf` (code that can be written in a faster way) +* `clippy_cargo` (checks against the cargo manifest) * **`clippy_correctness`** (code that is just outright wrong or very very useless) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 17c1c25669f..e17aa75cdf5 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -16,6 +16,7 @@ license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] [dependencies] +cargo_metadata = "0.5" itertools = "0.7" lazy_static = "1.0" matches = "0.1.2" diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a952f5081f4..0a500f9ad6e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -16,6 +16,7 @@ #![feature(iterator_find_map)] +extern crate cargo_metadata; #[macro_use] extern crate rustc; extern crate rustc_typeck; @@ -81,6 +82,9 @@ macro_rules! declare_clippy_lint { { pub $name:tt, restriction, $description:tt } => { declare_lint! { pub $name, Allow, $description } }; + { pub $name:tt, cargo, $description:tt } => { + declare_lint! { pub $name, Allow, $description } + }; { pub $name:tt, nursery, $description:tt } => { declare_lint! { pub $name, Allow, $description } }; @@ -158,6 +162,7 @@ pub mod minmax; pub mod misc; pub mod misc_early; pub mod missing_doc; +pub mod multiple_crate_versions; pub mod mut_mut; pub mod mut_reference; pub mod mutex_atomic; @@ -412,6 +417,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); + reg.register_early_lint_pass(box multiple_crate_versions::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_late_lint_pass(box infallible_destructuring_match::Pass); @@ -895,6 +901,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { vec::USELESS_VEC, ]); + reg.register_lint_group("clippy_cargo", vec![ + multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, + ]); + reg.register_lint_group("clippy_nursery", vec![ attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs new file mode 100644 index 00000000000..d347270236d --- /dev/null +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -0,0 +1,72 @@ +//! lint on multiple versions of a crate being used + +use rustc::lint::*; +use syntax::ast::*; + +use cargo_metadata; +use itertools::Itertools; + +/// **What it does:** Checks to see if multiple versions of a crate are being +/// used. +/// +/// **Why is this bad?** This bloats the size of targets, and can lead to +/// confusing error messages when structs or traits are used interchangeably +/// between different versions of a crate. +/// +/// **Known problems:** Because this can be caused purely by the dependencies +/// themselves, it's not always possible to fix this issue. +/// +/// **Example:** +/// ```toml +/// # This will pull in both winapi v0.3.4 and v0.2.8, triggering a warning. +/// [dependencies] +/// ctrlc = "3.1.0" +/// ansi_term = "0.11.0" +/// ``` +declare_clippy_lint! { + pub MULTIPLE_CRATE_VERSIONS, + cargo, + "multiple versions of the same crate being used" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(MULTIPLE_CRATE_VERSIONS) + } +} + +impl EarlyLintPass for Pass { + fn check_crate(&mut self, cx: &EarlyContext, krate: &Crate) { + let metadata = match cargo_metadata::metadata_deps(None, true) { + Ok(metadata) => metadata, + Err(_) => { + cx.span_lint( + MULTIPLE_CRATE_VERSIONS, + krate.span, + "could not read cargo metadata" + ); + + return; + } + }; + + let mut packages = metadata.packages; + packages.sort_by(|a, b| a.name.cmp(&b.name)); + + for (name, group) in &packages.into_iter().group_by(|p| p.name.clone()) { + let group: Vec = group.collect(); + + if group.len() > 1 { + let versions = group.into_iter().map(|p| p.version).join(", "); + + cx.span_lint( + MULTIPLE_CRATE_VERSIONS, + krate.span, + &format!("multiple versions for dependency `{}`: {}", name, versions), + ); + } + } + } +} diff --git a/util/lintlib.py b/util/lintlib.py index c28177e1062..4323ef5c3e7 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -24,6 +24,7 @@ lint_levels = { "restriction": 'Allow', "pedantic": 'Allow', "nursery": 'Allow', + "cargo": 'Allow', } diff --git a/util/update_lints.py b/util/update_lints.py index 58caa5dac0d..692599886a9 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -129,6 +129,7 @@ def main(print_only=False, check=False): "perf": [], "restriction": [], "pedantic": [], + "cargo": [], "nursery": [], } -- cgit 1.4.1-3-g733a5 From c7ff9334a63e2669204b1ee35e49886d8f0b90e1 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 1 May 2018 17:10:25 +0100 Subject: Fixed build for latest nightly --- clippy_lints/src/map_unit_fn.rs | 25 ++++++++++++++++--------- clippy_lints/src/utils/mod.rs | 10 +++++----- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 7defccf4697..fb8814d6d87 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::ty; +use rustc_errors::{Applicability}; use syntax::codemap::Span; use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use utils::paths; @@ -210,7 +211,10 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar snippet(cx, fn_arg.span, "_")); span_lint_and_then(cx, lint, expr.span, &msg, |db| { - db.span_approximate_suggestion(stmt.span, "try this", suggestion); + db.span_suggestion_with_applicability(stmt.span, + "try this", + suggestion, + Applicability::Unspecified); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); @@ -218,17 +222,20 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar span_lint_and_then(cx, lint, expr.span, &msg, |db| { if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) { let suggestion = format!("if let {0}({1}) = {2} {{ {3} }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, reduced_expr_span, "_")); + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, reduced_expr_span, "_")); db.span_suggestion(stmt.span, "try this", suggestion); } else { let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")); - db.span_approximate_suggestion(stmt.span, "try this", suggestion); + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_")); + db.span_suggestion_with_applicability(stmt.span, + "try this", + suggestion, + Applicability::Unspecified); } }); } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6701ad00722..79e319cfc68 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,7 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}}; -use rustc_errors; +use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; use std::mem; @@ -645,12 +645,12 @@ pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: I) where I: IntoIterator, { - let sugg = rustc_errors::CodeSuggestion { + let sugg = CodeSuggestion { substitutions: vec![ - rustc_errors::Substitution { + Substitution { parts: sugg.into_iter() .map(|(span, snippet)| { - rustc_errors::SubstitutionPart { + SubstitutionPart { snippet, span, } @@ -660,7 +660,7 @@ where ], msg: help_msg, show_code_when_inline: true, - approximate: false, + applicability: Applicability::Unspecified, }; db.suggestions.push(sugg); } -- cgit 1.4.1-3-g733a5 From 5d36edc90d26f2021a3a9d579066c0190aa8facf Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 1 May 2018 15:01:28 +0200 Subject: Prevent crash when macro is in different file This was caused by a macro in a different file. The `target.span` was be in the file of the macro definition and the `item.span` in the file of the calling code. --- clippy_lints/src/types.rs | 6 +++++- tests/auxiliary/test_macro.rs | 11 +++++++++++ tests/ui/implicit_hasher.rs | 7 +++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/auxiliary/test_macro.rs diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 69c37bb6305..ffc49722aad 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -12,7 +12,7 @@ use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; -use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, +use utils::{comparisons, differing_macro_contexts, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; use utils::paths; @@ -1714,6 +1714,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { vis.visit_ty(ty); for target in &vis.found { + if differing_macro_contexts(item.span, target.span()) { + return; + } + let generics_suggestion_span = generics.span.substitute_dummy({ let pos = snippet_opt(cx, item.span.until(target.span())) .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))) diff --git a/tests/auxiliary/test_macro.rs b/tests/auxiliary/test_macro.rs new file mode 100644 index 00000000000..624ca892add --- /dev/null +++ b/tests/auxiliary/test_macro.rs @@ -0,0 +1,11 @@ +pub trait A {} + +macro_rules! __implicit_hasher_test_macro { + (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => { + __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) ); + }; + + (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => { + impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { } + }; +} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index c93f858b5ca..c8b9f74bb32 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -83,4 +83,11 @@ macro_rules! gen { gen!(impl); gen!(fn bar); +// When the macro is in a different file, the suggestion spans can't be combined properly +// and should not cause an ICE +// See #2707 +#[macro_use] +#[path = "../auxiliary/test_macro.rs"] pub mod test_macro; +__implicit_hasher_test_macro!(impl for HashMap where V: test_macro::A); + fn main() {} -- cgit 1.4.1-3-g733a5 From e94ec44ab332c737cb761b650aeb519793774df9 Mon Sep 17 00:00:00 2001 From: Cyril Plisko Date: Tue, 1 May 2018 20:33:32 +0300 Subject: Simplify some internal code Addresses #2709 --- clippy_lints/src/utils/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6701ad00722..00b9fa37c15 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -301,9 +301,7 @@ pub fn implements_trait<'a, 'tcx>( let obligation = cx.tcx .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); - cx.tcx.infer_ctxt().enter(|infcx| { - traits::SelectionContext::new(&infcx).infcx().predicate_must_hold(&obligation) - }) + cx.tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold(&obligation)) } /// Check whether this type implements Drop. -- cgit 1.4.1-3-g733a5 From 8f1a98ff08f2729874bfbdeee643b86764d5ae03 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 3 May 2018 10:56:02 +0200 Subject: remove unused crate import --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a952f5081f4..bfb7bb8e333 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -41,7 +41,6 @@ extern crate regex_syntax; extern crate quine_mc_cluskey; -extern crate rustc_const_math; extern crate rustc_errors; extern crate rustc_plugin; -- cgit 1.4.1-3-g733a5 From c7ce6c07b1eea0606be94d607881df87c1c7c13c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 3 May 2018 15:52:44 +0200 Subject: Rustup field -> method transition of ..= --- clippy_lints/src/utils/higher.rs | 19 +++++++++++++------ clippy_lints/src/utils/paths.rs | 2 ++ tests/ui/no_effect.stderr | 8 +------- tests/ui/redundant_field_names.rs | 4 ++-- tests/ui/redundant_field_names.stderr | 14 +------------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 091261ffbec..011d2f7b8a2 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -69,6 +69,19 @@ pub fn range(expr: &hir::Expr) -> Option { None } }, + hir::ExprCall(ref path, ref args) => if let hir::ExprPath(ref path) = path.node { + if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) { + Some(Range { + start: Some(&args[0]), + end: Some(&args[1]), + limits: ast::RangeLimits::Closed, + }) + } else { + None + } + } else { + None + }, hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { @@ -77,12 +90,6 @@ pub fn range(expr: &hir::Expr) -> Option { end: None, limits: ast::RangeLimits::HalfOpen, }) - } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { - Some(Range { - start: Some(get_field("start", fields)?), - end: Some(get_field("end", fields)?), - limits: ast::RangeLimits::Closed, - }) } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { Some(Range { start: Some(get_field("start", fields)?), diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index fbc3cc303a8..a1cb6670bc5 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -66,7 +66,9 @@ pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; pub const RANGE_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeInclusive"]; +pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"]; pub const RANGE_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeInclusive"]; +pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"]; pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"]; pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"]; pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"]; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 64c0267a8b8..7ff0425ebb9 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -108,12 +108,6 @@ error: statement with no effect 76 | 5..6; | ^^^^^ -error: statement with no effect - --> $DIR/no_effect.rs:77:5 - | -77 | 5..=6; - | ^^^^^^ - error: statement with no effect --> $DIR/no_effect.rs:78:5 | @@ -278,5 +272,5 @@ error: statement can be reduced 116 | FooString { s: String::from("blah"), }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` -error: aborting due to 46 previous errors +error: aborting due to 45 previous errors diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index a14f0ef40a0..095ac7c0cc1 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,6 +1,6 @@ #![warn(redundant_field_names)] #![allow(unused_variables)] -#![feature(inclusive_range, inclusive_range_fields)] +#![feature(inclusive_range, inclusive_range_fields, inclusive_range_methods)] #[macro_use] extern crate derive_new; @@ -53,6 +53,6 @@ fn main() { let _ = RangeFrom { start: start }; let _ = RangeTo { end: end }; let _ = Range { start: start, end: end }; - let _ = RangeInclusive { start: start, end: end }; + let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end: end }; } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 91db8a5f0d1..d757f1871a7 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -36,23 +36,11 @@ error: redundant field names in struct initialization 55 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:56:30 - | -56 | let _ = RangeInclusive { start: start, end: end }; - | ^^^^^^^^^^^^ help: replace it with: `start` - -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:56:44 - | -56 | let _ = RangeInclusive { start: start, end: end }; - | ^^^^^^^^ help: replace it with: `end` - error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:57:32 | 57 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 00b549ad40e0588be0439b58b7796b530bb691d6 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 3 May 2018 23:28:02 +0100 Subject: Fixed build for latest nightly (again) --- clippy_lints/src/attrs.rs | 66 +++++++++++++++--------------- clippy_lints/src/doc.rs | 4 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 9 +--- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- 9 files changed, 42 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c822c59deeb..bc345347dc6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -125,14 +125,14 @@ impl LintPass for AttrPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { if let Some(ref items) = attr.meta_item_list() { - if items.is_empty() || attr.name().map_or(true, |n| n != "deprecated") { + if items.is_empty() || attr.name() != "deprecated" { return; } for item in items { if_chain! { if let NestedMetaItemKind::MetaItem(ref mi) = item.node; if let MetaItemKind::NameValue(ref lit) = mi.node; - if mi.ident.name == "since"; + if mi.name() == "since"; then { check_semver(cx, item.span, lit); } @@ -149,40 +149,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { ItemExternCrate(_) | ItemUse(_, _) => { for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { - if let Some(name) = attr.name() { - match &*name.as_str() { - "allow" | "warn" | "deny" | "forbid" => { - // whitelist `unused_imports` and `deprecated` - for lint in lint_list { - if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { - if let ItemUse(_, _) = item.node { - return; - } + match &*attr.name().as_str() { + "allow" | "warn" | "deny" | "forbid" => { + // whitelist `unused_imports` and `deprecated` + for lint in lint_list { + if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { + if let ItemUse(_, _) = item.node { + return; } } - let line_span = last_line_of_span(cx, attr.span); + } + let line_span = last_line_of_span(cx, attr.span); - if let Some(mut sugg) = snippet_opt(cx, line_span) { - if sugg.contains("#[") { - span_lint_and_then( - cx, - USELESS_ATTRIBUTE, - line_span, - "useless lint attribute", - |db| { - sugg = sugg.replacen("#[", "#![", 1); - db.span_suggestion( - line_span, - "if you just forgot a `!`, use", - sugg, - ); - }, - ); - } + if let Some(mut sugg) = snippet_opt(cx, line_span) { + if sugg.contains("#[") { + span_lint_and_then( + cx, + USELESS_ATTRIBUTE, + line_span, + "useless lint attribute", + |db| { + sugg = sugg.replacen("#[", "#![", 1); + db.span_suggestion( + line_span, + "if you just forgot a `!`, use", + sugg, + ); + }, + ); } - }, - _ => {}, - } + } + }, + _ => {}, } } } @@ -294,7 +292,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { } if let Some(ref values) = attr.meta_item_list() { - if values.len() != 1 || attr.name().map_or(true, |n| n != "inline") { + if values.len() != 1 || attr.name() != "inline" { continue; } if is_word(&values[0], "always") { @@ -328,7 +326,7 @@ fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { if let NestedMetaItemKind::MetaItem(ref mi) = nmi.node { - mi.is_word() && mi.ident.name == expected + mi.is_word() && mi.name() == expected } else { false } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 10043df9cbf..840dd4b045f 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -150,9 +150,9 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a spans.extend_from_slice(¤t_spans); doc.push_str(¤t); } - } else if let Some(name) = attr.name() { + } else { // ignore mix of sugared and non-sugared doc - if name == "doc" { + if attr.name() == "doc" { return; } } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index af7de542a91..1679833873b 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) { for attr in attrs { - if attr.name().map_or(true, |n| n != "inline") { + if attr.name() == "inline" { continue; } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 6a83417157b..d9a6463641e 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -84,7 +84,7 @@ impl MissingDoc { let has_doc = attrs .iter() - .any(|a| a.is_value_str() && a.name().map_or(false, |n| n == "doc")); + .any(|a| a.is_value_str() && a.name() == "doc"); if !has_doc { cx.span_lint( MISSING_DOCS_IN_PRIVATE_ITEMS, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 944f20fe99d..dc78f428ef9 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -77,13 +77,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { return; } for a in attrs { - if_chain! { - if a.meta_item_list().is_some(); - if let Some(name) = a.name(); - if name == "proc_macro_derive"; - then { - return; - } + if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" { + return; } } }, diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 5e5e93783d3..ae77dd7b4a8 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -149,5 +149,5 @@ impl EarlyLintPass for ReturnPass { } fn attr_is_cfg(attr: &ast::Attribute) -> bool { - attr.meta_item_list().is_some() && attr.name().map_or(false, |n| n == "cfg") + attr.meta_item_list().is_some() && attr.name() == "cfg" } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8e81d9440b0..fccb47817e0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -463,7 +463,7 @@ fn has_attr(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { attr.check_name("clippy") && attr.meta_item_list().map_or(false, |list| { list.len() == 1 && match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.ident.name == "author", + ast::NestedMetaItemKind::MetaItem(ref it) => it.name() == "author", ast::NestedMetaItemKind::Literal(_) => false, } }) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 607082e8ad2..58e71705011 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -13,7 +13,7 @@ pub fn file_from_args( args: &[codemap::Spanned], ) -> Result, (&'static str, codemap::Span)> { for arg in args.iter().filter_map(|a| a.meta_item()) { - if arg.ident.name == "conf_file" { + if arg.name() == "conf_file" { return match arg.node { ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { Err(("`conf_file` must be a named value", arg.span)) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 79e319cfc68..65ea11c55f3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -743,7 +743,7 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' continue; } if let Some(ref value) = attr.value_str() { - if attr.name().map_or(false, |n| n == name) { + if attr.name() == name { if let Ok(value) = FromStr::from_str(&value.as_str()) { attr::mark_used(attr); f(value) -- cgit 1.4.1-3-g733a5 From 8c9bb8960811ca77e7a1f4fb2f1a036131ff6d94 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 4 May 2018 10:17:30 +0200 Subject: Update inline_fn_without_body.rs --- clippy_lints/src/inline_fn_without_body.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 1679833873b..34196a1728f 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) { for attr in attrs { - if attr.name() == "inline" { + if attr.name() != "inline" { continue; } -- cgit 1.4.1-3-g733a5 From 9ce6fb34ca249388def66d183a844d3dabaefc94 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 4 May 2018 12:59:45 +0200 Subject: Satisfy dogfood --- clippy_lints/src/doc.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 840dd4b045f..7d3e812c9c5 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -150,11 +150,9 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a spans.extend_from_slice(¤t_spans); doc.push_str(¤t); } - } else { + } else if attr.name() == "doc" { // ignore mix of sugared and non-sugared doc - if attr.name() == "doc" { - return; - } + return; } } -- cgit 1.4.1-3-g733a5 From a27baecbdfdcb9d4772b5e136ed96b878c126bb4 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 4 May 2018 14:23:53 +0200 Subject: Link with https instead of http The old link caused a mixed content warning on crates.io. This should be fixed now. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50c2bd95b7f..e31b73933da 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy) -[![Current Version](http://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) +[![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -- cgit 1.4.1-3-g733a5 From 642baa91cfb38cd1b30799b27dcf49f2d9f4f6fa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 4 May 2018 15:54:56 +0200 Subject: Version bump --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 650c2a9d893..540d388f810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.196 +* Rustup to *rustc 1.27.0-nightly (e82261dfb 2018-05-03)* + ## 0.0.195 * Rustup to *rustc 1.27.0-nightly (ac3c2288f 2018-04-18)* @@ -689,6 +692,7 @@ All notable changes to this project will be documented in this file. [`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception [`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one +[`multiple_crate_versions`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#multiple_crate_versions [`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref [`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut [`mut_range_bound`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_range_bound diff --git a/Cargo.toml b/Cargo.toml index 9efa7031005..b05a19df202 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.195" +version = "0.0.196" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.195", path = "clippy_lints" } +clippy_lints = { version = "0.0.196", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/README.md b/README.md index 50c2bd95b7f..d011048dad4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 257 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 258 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e17aa75cdf5..db9947f072a 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.195" +version = "0.0.196" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From d4b536f540308c52242c9519ff10fda03a08ce61 Mon Sep 17 00:00:00 2001 From: Evan Simmons Date: Wed, 2 May 2018 11:40:52 -0700 Subject: Fix 1x..x.0 false positive, pretty suggestion --- clippy_lints/src/excessive_precision.rs | 29 +++++++- clippy_lints/src/literal_representation.rs | 6 +- tests/ui/excessive_precision.rs | 35 ++++++---- tests/ui/excessive_precision.stderr | 106 ++++++++++++++++------------- 4 files changed, 108 insertions(+), 68 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index b96ae18828e..553476f63c9 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -69,13 +69,16 @@ impl ExcessivePrecision { fn check(&self, sym: &Symbol, fty: &FloatTy) -> Option { let max = max_digits(fty); let sym_str = sym.as_str(); - let formatter = FloatFormat::new(&sym_str); - let digits = count_digits(&sym_str); + if dot_zero_exclusion(&sym_str) { + return None + } // Try to bail out if the float is for sure fine. // If its within the 2 decimal digits of being out of precision we // check if the parsed representation is the same as the string // since we'll need the truncated string anyway. + let digits = count_digits(&sym_str); if digits > max as usize { + let formatter = FloatFormat::new(&sym_str); let sr = match *fty { FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), @@ -86,7 +89,8 @@ impl ExcessivePrecision { if sym_str == s { None } else { - Some(s) + let di = super::literal_representation::DigitInfo::new(&s, true); + Some(di.grouping_hint()) } } else { None @@ -94,6 +98,23 @@ impl ExcessivePrecision { } } +/// Should we exclude the float because it has a .0 suffix +/// Ex 1_000_000_000.0 +fn dot_zero_exclusion(s: &str) -> bool { + if let Some(after_dec) = s.split('.').nth(1) { + let mut decpart = after_dec + .chars() + .take_while(|c| *c != 'e' || *c != 'E'); + + match decpart.next() { + Some('0') => decpart.count() == 0, + _ => false, + } + } else { + false + } +} + fn max_digits(fty: &FloatTy) -> u32 { match fty { FloatTy::F32 => f32::DIGITS, @@ -101,7 +122,9 @@ fn max_digits(fty: &FloatTy) -> u32 { } } +/// Counts the digits excluding leading zeros fn count_digits(s: &str) -> usize { + // Note that s does not contain the f32/64 suffix s.chars() .filter(|c| *c != '-' || *c != '.') .take_while(|c| *c != 'e' || *c != 'E') diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 89396ebd5b3..6c2351d43dd 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -81,7 +81,7 @@ declare_clippy_lint! { } #[derive(Debug, PartialEq)] -enum Radix { +pub(super) enum Radix { Binary, Octal, Decimal, @@ -99,7 +99,7 @@ impl Radix { } #[derive(Debug)] -struct DigitInfo<'a> { +pub(super) struct DigitInfo<'a> { /// Characters of a literal between the radix prefix and type suffix. pub digits: &'a str, /// Which radix the literal was represented in. @@ -160,7 +160,7 @@ impl<'a> DigitInfo<'a> { } /// Returns digits grouped in a sensible way. - fn grouping_hint(&self) -> String { + pub fn grouping_hint(&self) -> String { let group_size = self.radix.suggest_grouping(); if self.digits.contains('.') { let mut parts = self.digits.split('.'); diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index d209367cc3b..47e73aa0bcd 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -3,45 +3,50 @@ #![allow(print_literal)] fn main() { - // TODO add prefix tests // Consts - const GOOD32_SUF: f32 = 0.123_456_f32; const GOOD32: f32 = 0.123_456; const GOOD32_SM: f32 = 0.000_000_000_1; + const GOOD32_DOT: f32 = 10_000_000_000.0; + const GOOD32_EDGE: f32 = 1.000_000_8; const GOOD64: f64 = 0.123_456_789_012; const GOOD64_SM: f32 = 0.000_000_000_000_000_1; + const GOOD64_DOT: f32 = 10_000_000_000_000_000.0; const BAD32_1: f32 = 0.123_456_789_f32; const BAD32_2: f32 = 0.123_456_789; const BAD32_3: f32 = 0.100_000_000_000_1; + const BAD32_EDGE: f32 = 1.000_000_9; const BAD64_1: f64 = 0.123_456_789_012_345_67f64; const BAD64_2: f64 = 0.123_456_789_012_345_67; const BAD64_3: f64 = 0.100_000_000_000_000_000_1; - // Literal + // Literal as param println!("{}", 8.888_888_888_888_888_888_888); - // TODO add inferred type tests for f32 - // TODO add tests cases exactly on the edge + // // TODO add inferred type tests for f32 // Locals let good32: f32 = 0.123_456_f32; let good32_2: f32 = 0.123_456; - let good64: f64 = 0.123_456_789_012f64; let good64: f64 = 0.123_456_789_012; - let good64_2 = 0.123_456_789_012; + let good64_suf: f64 = 0.123_456_789_012f64; + let good64_inf = 0.123_456_789_012; - let bad32_1: f32 = 1.123_456_789_f32; - let bad32_2: f32 = 1.123_456_789; + let bad32: f32 = 1.123_456_789; + let bad32_suf: f32 = 1.123_456_789_f32; + let bad32_inf = 1.123_456_789_f32; - let bad64_1: f64 = 0.123_456_789_012_345_67f64; - let bad64_2: f64 = 0.123_456_789_012_345_67; - let bad64_3 = 0.123_456_789_012_345_67; + let bad64: f64 = 0.123_456_789_012_345_67; + let bad64_suf: f64 = 0.123_456_789_012_345_67f64; + let bad64_inf = 0.123_456_789_012_345_67; - // TODO Vectors / nested vectors - let vec32: Vec = vec![0.123_456_789]; - let vec64: Vec = vec![0.123_456_789_123_456_789]; + // Vectors + let good_vec32: Vec = vec![0.123_456]; + let good_vec64: Vec = vec![0.123_456_789]; + + let bad_vec32: Vec = vec![0.123_456_789]; + let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; // Exponential float notation let good_e32: f32 = 1e-10; diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index de022afb512..a167deac038 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,100 +1,112 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:14:26 + --> $DIR/excessive_precision.rs:15:26 | -14 | const BAD32_1: f32 = 0.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` +15 | const BAD32_1: f32 = 0.123_456_789_f32; + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` | = note: `-D excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:15:26 + --> $DIR/excessive_precision.rs:16:26 | -15 | const BAD32_2: f32 = 0.123_456_789; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` +16 | const BAD32_2: f32 = 0.123_456_789; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:16:26 + --> $DIR/excessive_precision.rs:17:26 | -16 | const BAD32_3: f32 = 0.100_000_000_000_1; +17 | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:18:26 + --> $DIR/excessive_precision.rs:18:29 | -18 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` +18 | const BAD32_EDGE: f32 = 1.000_000_9; + | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:19:26 + --> $DIR/excessive_precision.rs:20:26 | -19 | const BAD64_2: f64 = 0.123_456_789_012_345_67; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` +20 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:20:26 + --> $DIR/excessive_precision.rs:21:26 | -20 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; +21 | const BAD64_2: f64 = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:22:26 + | +22 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:23:20 + --> $DIR/excessive_precision.rs:25:20 + | +25 | println!("{}", 8.888_888_888_888_888_888_888); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` + +error: float has excessive precision + --> $DIR/excessive_precision.rs:36:22 | -23 | println!("{}", 8.888_888_888_888_888_888_888); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.88888888888889` +36 | let bad32: f32 = 1.123_456_789; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:35:24 + --> $DIR/excessive_precision.rs:37:26 | -35 | let bad32_1: f32 = 1.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568` +37 | let bad32_suf: f32 = 1.123_456_789_f32; + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:36:24 + --> $DIR/excessive_precision.rs:38:21 | -36 | let bad32_2: f32 = 1.123_456_789; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568` +38 | let bad32_inf = 1.123_456_789_f32; + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:38:24 + --> $DIR/excessive_precision.rs:40:22 | -38 | let bad64_1: f64 = 0.123_456_789_012_345_67f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` +40 | let bad64: f64 = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:39:24 + --> $DIR/excessive_precision.rs:41:26 | -39 | let bad64_2: f64 = 0.123_456_789_012_345_67; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` +41 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:40:19 + --> $DIR/excessive_precision.rs:42:21 | -40 | let bad64_3 = 0.123_456_789_012_345_67; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566` +42 | let bad64_inf = 0.123_456_789_012_345_67; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:43:32 + --> $DIR/excessive_precision.rs:48:36 | -43 | let vec32: Vec = vec![0.123_456_789]; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679` +48 | let bad_vec32: Vec = vec![0.123_456_789]; + | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:44:32 + --> $DIR/excessive_precision.rs:49:36 | -44 | let vec64: Vec = vec![0.123_456_789_123_456_789]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678912345678` +49 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:24 + --> $DIR/excessive_precision.rs:53:24 | -48 | let bad_e32: f32 = 1.123_456_788_888e-10; - | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568e-10` +53 | let bad_e32: f32 = 1.123_456_788_888e-10; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:51:27 + --> $DIR/excessive_precision.rs:56:27 | -51 | let bad_bige32: f32 = 1.123_456_788_888E-10; - | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568E-10` +56 | let bad_bige32: f32 = 1.123_456_788_888E-10; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` -error: aborting due to 16 previous errors +error: aborting due to 18 previous errors -- cgit 1.4.1-3-g733a5 From 1477f348582ee6a55ecb9fc00e1cd5c14f5c3c90 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 6 May 2018 14:05:41 +0200 Subject: Fixes compilation for rust nightly 2018-05-05 Closes #2725 --- clippy_lints/src/escape.rs | 12 ++++++------ clippy_lints/src/loops.rs | 22 +++++++++++----------- clippy_lints/src/needless_pass_by_value.rs | 24 ++++++++++++------------ 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 8c3127085fa..795ef2f9925 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -3,7 +3,7 @@ use rustc::hir::intravisit as visit; use rustc::hir::map::Node::{NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; -use rustc::middle::mem_categorization::{cmt, Categorization}; +use rustc::middle::mem_categorization::{cmt_, Categorization}; use rustc::ty::{self, Ty}; use rustc::ty::layout::LayoutOf; use rustc::util::nodemap::NodeSet; @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { + fn consume(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) { if let Categorization::Local(lid) = cmt.cat { if let Move(DirectRefMove) = mode { // moved out or in. clearly can't be localized @@ -94,8 +94,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } } - fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} - fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { + fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} + fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) { let map = &self.cx.tcx.hir; if map.is_argument(consume_pat.id) { // Skip closure arguments @@ -135,7 +135,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } } - fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { + fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { match loan_cause { // x.foo() @@ -157,7 +157,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } fn decl_without_init(&mut self, _: NodeId, _: Span) {} - fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} + fn mutate(&mut self, _: NodeId, _: Span, _: &cmt_<'tcx>, _: MutateMode) {} } impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 515bd8976b9..df5e4b885bc 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -10,7 +10,7 @@ use rustc::middle::region; // use rustc::middle::region::CodeExtent; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::Categorization; -use rustc::middle::mem_categorization::cmt; +use rustc::middle::mem_categorization::cmt_; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use std::collections::{HashMap, HashSet}; @@ -1412,13 +1412,13 @@ struct MutatePairDelegate { } impl<'tcx> Delegate<'tcx> for MutatePairDelegate { - fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: NodeId, _: Span, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} + fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} - fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) {} + fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { if let Categorization::Local(id) = cmt.cat { if Some(id) == self.node_id_low { @@ -1431,7 +1431,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate { } } - fn mutate(&mut self, _: NodeId, sp: Span, cmt: cmt<'tcx>, _: MutateMode) { + fn mutate(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: MutateMode) { if let Categorization::Local(id) = cmt.cat { if Some(id) == self.node_id_low { self.span_low = Some(sp) @@ -2255,19 +2255,19 @@ impl<'tcx> MutVarsDelegate { impl<'tcx> Delegate<'tcx> for MutVarsDelegate { - fn consume(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: NodeId, _: Span, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} + fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} - fn consume_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: ConsumeMode) {} + fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { self.update(&cmt.cat) } } - fn mutate(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: MutateMode) { + fn mutate(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: MutateMode) { self.update(&cmt.cat) } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index dc78f428ef9..d2836ffc2d6 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -308,7 +308,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { } } - fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt<'tcx>) { + fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: &mc::cmt_<'tcx>) { let cmt = unwrap_downcast_or_interior(cmt); if let mc::Categorization::Local(vid) = cmt.cat { @@ -316,7 +316,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { } } - fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) { + fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: &mc::cmt_<'tcx>) { let cmt = unwrap_downcast_or_interior(cmt); if let mc::Categorization::Local(vid) = cmt.cat { @@ -367,13 +367,13 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { - fn consume(&mut self, consume_id: NodeId, consume_span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { + fn consume(&mut self, consume_id: NodeId, consume_span: Span, cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move(_) = mode { self.move_common(consume_id, consume_span, cmt); } } - fn matched_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>, mode: euv::MatchMode) { + fn matched_pat(&mut self, matched_pat: &Pat, cmt: &mc::cmt_<'tcx>, mode: euv::MatchMode) { if let euv::MatchMode::MovingMatch = mode { self.move_common(matched_pat.id, matched_pat.span, cmt); } else { @@ -381,27 +381,27 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { } } - fn consume_pat(&mut self, consume_pat: &Pat, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { + fn consume_pat(&mut self, consume_pat: &Pat, cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move(_) = mode { self.move_common(consume_pat.id, consume_pat.span, cmt); } } - fn borrow(&mut self, _: NodeId, _: Span, _: mc::cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, _: euv::LoanCause) {} + fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, _: euv::LoanCause) {} - fn mutate(&mut self, _: NodeId, _: Span, _: mc::cmt<'tcx>, _: euv::MutateMode) {} + fn mutate(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: euv::MutateMode) {} fn decl_without_init(&mut self, _: NodeId, _: Span) {} } -fn unwrap_downcast_or_interior(mut cmt: mc::cmt) -> mc::cmt { +fn unwrap_downcast_or_interior<'a, 'tcx>(mut cmt: &'a mc::cmt_<'tcx>) -> mc::cmt_<'tcx> { loop { - match cmt.cat.clone() { - mc::Categorization::Downcast(c, _) | mc::Categorization::Interior(c, _) => { + match cmt.cat { + mc::Categorization::Downcast(ref c, _) | mc::Categorization::Interior(ref c, _) => { cmt = c; }, - _ => return cmt, + _ => return (*cmt).clone(), } - } + }; } -- cgit 1.4.1-3-g733a5 From e7a6b3e613ba7adf2b3e3bceec66846598fa7374 Mon Sep 17 00:00:00 2001 From: NiekGr Date: Sat, 5 May 2018 15:01:51 +0200 Subject: Update len_zero to handle comparisions with one I have added test cases for comparisons with zero and one. While implementing handling of one, incorrect handlings of zero were also fixed. fixes rust-lang-nursery/rust-clippy/#2554 --- clippy_lints/src/len_zero.rs | 63 ++++++++++++++++++++++------------ tests/ui/len_zero.rs | 73 ++++++++++++++++++++++++++++++---------- tests/ui/len_zero.stderr | 80 +++++++++++++++++++++++++++++++++----------- 3 files changed, 158 insertions(+), 58 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index df3239ee1c7..09b3da1e99c 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,7 +1,7 @@ -use rustc::lint::*; use rustc::hir::def_id::DefId; -use rustc::ty; use rustc::hir::*; +use rustc::lint::*; +use rustc::ty; use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; @@ -81,8 +81,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { match cmp { - BiEq => check_cmp(cx, expr.span, left, right, ""), - BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + BiEq => { + check_cmp(cx, expr.span, left, right, "", 0); // len == 0 + check_cmp(cx, expr.span, right, left, "", 0); // 0 == len + }, + BiNe => { + check_cmp(cx, expr.span, left, right, "!", 0); // len != 0 + check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len + }, + BiGt => { + check_cmp(cx, expr.span, left, right, "!", 0); // len > 0 + check_cmp(cx, expr.span, right, left, "", 1); // 1 > len + }, + BiLt => { + check_cmp(cx, expr.span, left, right, "", 1); // len < 1 + check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len + }, + BiGe => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1 + BiLe => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len _ => (), } } @@ -168,40 +184,45 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { cx, LEN_WITHOUT_IS_EMPTY, item.span, - &format!("item `{}` has a public `len` method but {} `is_empty` method", ty, is_empty), + &format!( + "item `{}` has a public `len` method but {} `is_empty` method", + ty, is_empty + ), ); } } } -fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) { - // check if we are in an is_empty() method - if let Some(name) = get_item_name(cx, left) { - if name == "is_empty" { - return; +fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) { + if let (&ExprMethodCall(ref method_path, _, ref args), &ExprLit(ref lit)) = (&method.node, &lit.node) { + // check if we are in an is_empty() method + if let Some(name) = get_item_name(cx, method) { + if name == "is_empty" { + return; + } } - } - match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method_path, _, ref args)) | - (&ExprMethodCall(ref method_path, _, ref args), &ExprLit(ref lit)) => { - check_len_zero(cx, span, method_path.name, args, lit, op) - }, - _ => (), + + check_len(cx, span, method_path.name, args, lit, op, compare_to) } } -fn check_len_zero(cx: &LateContext, span: Span, name: Name, args: &[Expr], lit: &Lit, op: &str) { +fn check_len(cx: &LateContext, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) { if let Spanned { - node: LitKind::Int(0, _), + node: LitKind::Int(lit, _), .. } = *lit { - if name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { + // check if length is compared to the specified number + if lit != u128::from(compare_to) { + return; + } + + if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint_and_sugg( cx, LEN_ZERO, span, - "length comparison to zero", + &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), "using `is_empty` is more concise", format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")), ); diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index aba1dd3055a..2e71c2761fa 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,6 +1,3 @@ - - - #![warn(len_without_is_empty, len_zero)] #![allow(dead_code, unused)] @@ -12,7 +9,8 @@ impl PubOne { } } -impl PubOne { // A second impl for this struct - the error span shouldn't mention this +impl PubOne { + // A second impl for this struct - the error span shouldn't mention this pub fn irrelevant(self: &Self) -> bool { false } @@ -39,7 +37,8 @@ impl PubAllowed { struct NotPubOne; impl NotPubOne { - pub fn len(self: &Self) -> isize { // no error, len is pub but `NotPubOne` is not exported anyway + pub fn len(self: &Self) -> isize { + // no error, len is pub but `NotPubOne` is not exported anyway 1 } } @@ -47,7 +46,8 @@ impl NotPubOne { struct One; impl One { - fn len(self: &Self) -> isize { // no error, len is private, see #1085 + fn len(self: &Self) -> isize { + // no error, len is private, see #1085 1 } } @@ -120,7 +120,7 @@ impl HasWrongIsEmpty { 1 } - pub fn is_empty(self: &Self, x : u32) -> bool { + pub fn is_empty(self: &Self, x: u32) -> bool { false } } @@ -129,28 +129,28 @@ pub trait Empty { fn is_empty(&self) -> bool; } -pub trait InheritingEmpty: Empty { //must not trigger LEN_WITHOUT_IS_EMPTY +pub trait InheritingEmpty: Empty { + //must not trigger LEN_WITHOUT_IS_EMPTY fn len(&self) -> isize; } - - fn main() { let x = [1, 2]; if x.len() == 0 { println!("This should not happen!"); } - if "".len() == 0 { - } + if "".len() == 0 {} let y = One; - if y.len() == 0 { //no error because One does not have .is_empty() + if y.len() == 0 { + //no error because One does not have .is_empty() println!("This should not happen either!"); } - let z : &TraitsToo = &y; - if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method + let z: &TraitsToo = &y; + if z.len() > 0 { + //no error, because TraitsToo has no .is_empty() method println!("Nor should this!"); } @@ -164,6 +164,43 @@ fn main() { if has_is_empty.len() > 0 { println!("Or this!"); } + if has_is_empty.len() < 1 { + println!("Or this!"); + } + if has_is_empty.len() >= 1 { + println!("Or this!"); + } + if has_is_empty.len() > 1 { + // no error + println!("This can happen."); + } + if has_is_empty.len() <= 1 { + // no error + println!("This can happen."); + } + if 0 == has_is_empty.len() { + println!("Or this!"); + } + if 0 != has_is_empty.len() { + println!("Or this!"); + } + if 0 < has_is_empty.len() { + println!("Or this!"); + } + if 1 <= has_is_empty.len() { + println!("Or this!"); + } + if 1 > has_is_empty.len() { + println!("Or this!"); + } + if 1 < has_is_empty.len() { + // no error + println!("This can happen."); + } + if 1 >= has_is_empty.len() { + // no error + println!("This can happen."); + } assert!(!has_is_empty.is_empty()); let with_is_empty: &WithIsEmpty = &Wither; @@ -173,14 +210,14 @@ fn main() { assert!(!with_is_empty.is_empty()); let has_wrong_is_empty = HasWrongIsEmpty; - if has_wrong_is_empty.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() + if has_wrong_is_empty.len() == 0 { + //no error as HasWrongIsEmpty does not have .is_empty() println!("Or this!"); } } fn test_slice(b: &[u8]) { - if b.len() != 0 { - } + if b.len() != 0 {} } // this used to ICE diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 6e3cf1b3ca1..a04185bc63f 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,11 +1,11 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:9:1 + --> $DIR/len_zero.rs:6:1 | -9 | / impl PubOne { -10 | | pub fn len(self: &Self) -> isize { -11 | | 1 -12 | | } -13 | | } +6 | / impl PubOne { +7 | | pub fn len(self: &Self) -> isize { +8 | | 1 +9 | | } +10 | | } | |_^ | = note: `-D len-without-is-empty` implied by `-D warnings` @@ -43,17 +43,17 @@ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:140:8 + --> $DIR/len_zero.rs:139:8 | -140 | if x.len() == 0 { +139 | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `x.is_empty()` | = note: `-D len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:144:8 + --> $DIR/len_zero.rs:143:8 | -144 | if "".len() == 0 { +143 | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is more concise: `"".is_empty()` error: length comparison to zero @@ -74,25 +74,67 @@ error: length comparison to zero 164 | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` -error: length comparison to zero +error: length comparison to one + --> $DIR/len_zero.rs:167:8 + | +167 | if has_is_empty.len() < 1 { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + +error: length comparison to one --> $DIR/len_zero.rs:170:8 | -170 | if with_is_empty.len() == 0 { +170 | if has_is_empty.len() >= 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:181:8 + | +181 | if 0 == has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:184:8 + | +184 | if 0 != has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:187:8 + | +187 | if 0 < has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + +error: length comparison to one + --> $DIR/len_zero.rs:190:8 + | +190 | if 1 <= has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + +error: length comparison to one + --> $DIR/len_zero.rs:193:8 + | +193 | if 1 > has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:207:8 + | +207 | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:182:8 + --> $DIR/len_zero.rs:220:8 | -182 | if b.len() != 0 { +220 | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:189:1 + --> $DIR/len_zero.rs:226:1 | -189 | / pub trait DependsOnFoo: Foo { -190 | | fn len(&mut self) -> usize; -191 | | } +226 | / pub trait DependsOnFoo: Foo { +227 | | fn len(&mut self) -> usize; +228 | | } | |_^ -error: aborting due to 12 previous errors +error: aborting due to 19 previous errors -- cgit 1.4.1-3-g733a5 From e456241f18227c7eb8d78a45daa66c756a9b65e7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 7 May 2018 10:00:58 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 540d388f810..e27e76ef7da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.197 +* Rustup to *rustc 1.27.0-nightly (428ea5f6b 2018-05-06)* + ## 0.0.196 * Rustup to *rustc 1.27.0-nightly (e82261dfb 2018-05-03)* diff --git a/Cargo.toml b/Cargo.toml index b05a19df202..72a47d725e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.196" +version = "0.0.197" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.196", path = "clippy_lints" } +clippy_lints = { version = "0.0.197", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index db9947f072a..8e0e2633c4f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.196" +version = "0.0.197" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From c0a0ddd638dacac7123a0c3f5c3e3488dc0fb8ca Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 7 May 2018 21:01:23 +0200 Subject: Add rustc version check to build script --- .gitignore | 3 ++ Cargo.toml | 4 +++ build.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ min_version.txt | 7 +++++ 4 files changed, 105 insertions(+) create mode 100644 min_version.txt diff --git a/.gitignore b/.gitignore index 3c8f96c0f6f..5c665bebd04 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ helper.txt *.iml .vscode .idea + +# Used by the Clippy build script +min_version.txt diff --git a/Cargo.toml b/Cargo.toml index 72a47d725e2..1a924bc7cf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,5 +51,9 @@ clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = "1.0" derive-new = "0.5" +[build-dependencies] +rustc_version = "0.2.2" +ansi_term = "0.11" + [features] debugging = [] diff --git a/build.rs b/build.rs index 1c930c1b2c9..c13eed1f585 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,99 @@ +//! This build script ensures that clippy is not compiled with an +//! incompatible version of rust. It will panic with a descriptive +//! error message instead. +//! +//! We specifially want to ensure that clippy is only built with a +//! rustc version that is newer or equal to the one specified in the +//! `min_version.txt` file. +//! +//! `min_version.txt` is in the repo but also in the `.gitignore` to +//! make sure that it is not updated manually by accident. Only CI +//! should update that file. +//! +//! This build script was originally taken from the Rocket web framework: +//! https://github.com/SergioBenitez/Rocket + +extern crate rustc_version; +extern crate ansi_term; + use std::env; +use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; +use ansi_term::Colour::Red; fn main() { + let string = include_str!("min_version.txt"); + let min_version_meta = version_meta_for(string) + .expect("Could not parse version string in min_version.txt"); + let current_version_meta = version_meta() + .expect("Could not retrieve current rustc version information from ENV"); + + let min_version = min_version_meta.clone().semver; + let min_date_str = min_version_meta.clone().commit_date + .expect("min_version.txt does not contain a rustc commit date"); + + let current_version = current_version_meta.clone().semver; + let current_date_str = current_version_meta.clone().commit_date + .expect("current rustc version information does not contain a rustc commit date"); + + let print_version_err = |version: &Version, date: &str| { + eprintln!("> {} {}. {} {}.\n", + "Installed rustc version is:", + format!("{} ({})", version, date), + "Minimum required rustc version:", + format!("{} ({})", min_version, min_date_str)); + }; + + if !correct_channel(¤t_version_meta) { + eprintln!("\n{} {}", + Red.bold().paint("error:"), + "clippy requires a nightly version of Rust."); + print_version_err(¤t_version, &*current_date_str); + eprintln!("{}{}{}", + "See the README (", + "https://github.com/rust-lang-nursery/rust-clippy#usage", + ") for more information."); + panic!("Aborting compilation due to incompatible compiler.") + } + + let current_date = str_to_ymd(¤t_date_str).unwrap(); + let min_date = str_to_ymd(&min_date_str).unwrap(); + + if current_date < min_date { + eprintln!("\n{} {}", + Red.bold().paint("error:"), + "clippy does not support this version of rustc nightly."); + eprintln!("> {}{}{}", + "Use `", + "rustup update", + "` or your preferred method to update Rust."); + print_version_err(¤t_version, &*current_date_str); + panic!("Aborting compilation due to incompatible compiler.") + } + // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); // Don't rebuild even if nothing changed println!("cargo:rerun-if-changed=build.rs"); } + +fn correct_channel(version_meta: &VersionMeta) -> bool { + match version_meta.channel { + Channel::Stable | Channel::Beta => { + false + }, + Channel::Nightly | Channel::Dev => { + true + } + } +} + +/// Convert a string of %Y-%m-%d to a single u32 maintaining ordering. +fn str_to_ymd(ymd: &str) -> Option { + let ymd: Vec = ymd.split("-").filter_map(|s| s.parse::().ok()).collect(); + if ymd.len() != 3 { + return None + } + + let (y, m, d) = (ymd[0], ymd[1], ymd[2]); + Some((y << 9) | (m << 5) | d) +} diff --git a/min_version.txt b/min_version.txt new file mode 100644 index 00000000000..b901c8ec520 --- /dev/null +++ b/min_version.txt @@ -0,0 +1,7 @@ +rustc 1.27.0-nightly (e82261dfb 2018-05-03) +binary: rustc +commit-hash: e82261dfbb5feaa2d28d2b138f4aabb2aa52c94b +commit-date: 2018-05-03 +host: x86_64-unknown-linux-gnu +release: 1.27.0-nightly +LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From c6e35eae534e827f864f9b95d9c65aec078ac998 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 8 May 2018 17:16:01 +0200 Subject: Check that we don't treat any type but a range type as a range --- clippy_lints/src/array_indexing.rs | 4 ++-- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/loops.rs | 8 ++++---- clippy_lints/src/ranges.rs | 6 +++--- clippy_lints/src/utils/higher.rs | 33 +++++++++++++++++++++++++++++++-- tests/run-pass/ice-2727.rs | 5 +++++ 6 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 tests/run-pass/ice-2727.rs diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 1b21cf8c5ff..e07804468e1 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { } // Index is a constant range - if let Some(range) = higher::range(index) { + if let Some(range) = higher::range(cx, index) { if let Some((start, end)) = to_const_range(cx, range, size) { if start > size || end > size { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { } } - if let Some(range) = higher::range(index) { + if let Some(range) = higher::range(cx, index) { // Full ranges are always valid if range.start.is_none() && range.end.is_none() { return; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 238970d4a9f..a2eea346743 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { } else { Finite }, - ExprStruct(..) => higher::range(expr) + ExprStruct(..) => higher::range(cx, expr) .map_or(false, |r| r.end.is_none()) .into(), _ => Finite, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index df5e4b885bc..87ea98533c3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -888,7 +888,7 @@ fn detect_manual_memcpy<'a, 'tcx>( start: Some(start), ref end, limits, - }) = higher::range(arg) + }) = higher::range(cx, arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.node { @@ -982,7 +982,7 @@ fn check_for_loop_range<'a, 'tcx>( start: Some(start), ref end, limits, - }) = higher::range(arg) + }) = higher::range(cx, arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { @@ -1118,7 +1118,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx start: Some(start), end: Some(end), limits, - }) = higher::range(arg) + }) = higher::range(cx, arg) { // ...and both sides are compile-time constant integers... if let Some((start_idx, _)) = constant(cx, start) { @@ -1456,7 +1456,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { start: Some(start), end: Some(end), .. - }) = higher::range(arg) + }) = higher::range(cx, arg) { let mut_ids = vec![ check_for_mutability(cx, start), diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 5a5dfe04d01..bc1ffc57003 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter; if iter_path.name == "iter"; // range expression in .zip() call: 0..x.len() - if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg); + if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); if is_integer_literal(start, 0); // .len() call if let ExprMethodCall(ref len_path, _, ref len_args) = end.node; @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // exclusive range plus one: x..(y+1) if_chain! { - if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(expr); + if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr); if let Some(y) = y_plus_one(end); then { span_lint_and_then( @@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // inclusive range minus one: x..=(y-1) if_chain! { - if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr); + if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr); if let Some(y) = y_minus_one(end); then { span_lint_and_then( diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 011d2f7b8a2..9a4fcd45d8a 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -3,7 +3,7 @@ #![deny(missing_docs_in_private_items)] -use rustc::hir; +use rustc::{hir, ty}; use rustc::lint::LateContext; use syntax::ast; use utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; @@ -44,7 +44,36 @@ pub struct Range<'a> { } /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. -pub fn range(expr: &hir::Expr) -> Option { +pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option> { + + let def_path = match cx.tables.expr_ty(expr).sty { + ty::TyAdt(def, _) => cx.tcx.def_path(def.did), + _ => return None, + }; + + // sanity checks for std::ops::RangeXXXX + if def_path.data.len() != 3 { + return None; + } + if def_path.data.get(0)?.data.as_interned_str() != "ops" { + return None; + } + if def_path.data.get(1)?.data.as_interned_str() != "range" { + return None; + } + let type_name = def_path.data.get(2)?.data.as_interned_str(); + let range_types = [ + "RangeFrom", + "RangeFull", + "RangeInclusive", + "Range", + "RangeTo", + "RangeToInclusive", + ]; + if !range_types.contains(&&*type_name.as_str()) { + return None; + } + /// Find the field named `name` in the field. Always return `Some` for /// convenience. fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { diff --git a/tests/run-pass/ice-2727.rs b/tests/run-pass/ice-2727.rs new file mode 100644 index 00000000000..79c6f1c55db --- /dev/null +++ b/tests/run-pass/ice-2727.rs @@ -0,0 +1,5 @@ +pub fn f(new: fn()) { + new(); +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From db4e7ac725689c3006a2817f373fb6ce9e64d29f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 6 May 2018 17:26:47 +0200 Subject: panic_params: don't lint escaped squigglies --- clippy_lints/src/panic.rs | 8 ++++---- tests/ui/panic.rs | 13 +++++++++++++ tests/ui/panic.stderr | 8 +++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index bbb62a778b5..a6691db8678 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -10,8 +10,7 @@ use utils::{is_direct_expn_of, match_def_path, opt_def_id, paths, resolve_node, /// is not a format string and used literally. So while `format!("{}")` will /// fail to compile, `panic!("{}")` will not. /// -/// **Known problems:** Should you want to use curly brackets in `panic!` -/// without any parameter, this lint will warn. +/// **Known problems:** None. /// /// **Example:** /// ```rust @@ -45,8 +44,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprLit(ref lit) = params[0].node; if is_direct_expn_of(expr.span, "panic").is_some(); if let LitKind::Str(ref string, _) = lit.node; - if let Some(par) = string.as_str().find('{'); - if string.as_str()[par..].contains('}'); + let string = string.as_str().replace("{{", "").replace("}}", ""); + if let Some(par) = string.find('{'); + if string[par..].contains('}'); if params[0].span.source_callee().is_none(); if params[0].span.lo() != params[0].span.hi(); then { diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs index f621a5f636d..d833d2651a5 100644 --- a/tests/ui/panic.rs +++ b/tests/ui/panic.rs @@ -11,6 +11,8 @@ fn missing() { } else { assert!(true, "here be missing values: {}"); } + + panic!("{{{this}}}"); } fn ok_single() { @@ -41,6 +43,16 @@ fn ok_nomsg() { assert!(if 1 == ONE { ONE == 1 } else { false }); } +fn ok_escaped() { + panic!("{{ why should this not be ok? }}"); + panic!(" or {{ that ?"); + panic!(" or }} this ?"); + panic!(" {or {{ that ?"); + panic!(" }or }} this ?"); + panic!("{{ test }"); + panic!("{case }}"); +} + fn main() { missing(); ok_single(); @@ -48,4 +60,5 @@ fn main() { ok_bracket(); ok_inner(); ok_nomsg(); + ok_escaped(); } diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index 25113ed80b6..165c33cacb7 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -18,5 +18,11 @@ error: you probably are missing some parameter in your format string 12 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: you probably are missing some parameter in your format string + --> $DIR/panic.rs:15:12 + | +15 | panic!("{{{this}}}"); + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 033b5f975b1403ea3cff424e0f3b89b7017dc214 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 9 May 2018 15:31:52 +0200 Subject: Remove removed rustfmt options Closes #2738 --- rustfmt.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 205b7d897d3..6776a88294c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,4 @@ max_width = 120 comment_width = 100 -fn_call_width = 80 match_block_trailing_comma = true -closure_block_indent_threshold = 0 wrap_comments = true -- cgit 1.4.1-3-g733a5 From 665cf9622107144ad2b6415d1ff5d81999d42ae3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 11 May 2018 08:37:48 +0200 Subject: Rustup to 2018-05-11 --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/loops.rs | 16 ++++++++-------- clippy_lints/src/map_clone.rs | 4 ++-- clippy_lints/src/methods.rs | 12 ++++++------ clippy_lints/src/mut_mut.rs | 6 ++---- clippy_lints/src/mut_reference.rs | 6 ++---- clippy_lints/src/needless_borrow.rs | 8 ++++---- clippy_lints/src/ptr.rs | 6 ++---- clippy_lints/src/transmute.rs | 30 +++++++++++++++++------------- clippy_lints/src/utils/mod.rs | 4 ++-- clippy_lints/src/vec.rs | 4 ++-- 11 files changed, 48 insertions(+), 50 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 675342645b8..3668f523293 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -426,7 +426,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' _ => None, }, ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty { - ty::TyRef(_, tam) => match tam.ty.sty { + ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx .interpret_interner diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 87ea98533c3..50e6e4c3b3f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -743,7 +743,7 @@ struct FixedOffsetVar { fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { let is_slice = match ty.sty { - ty::TyRef(_, ref subty) => is_slice_like(cx, subty.ty), + ty::TyRef(_, subty, _) => is_slice_like(cx, subty), ty::TySlice(..) | ty::TyArray(..) => true, _ => false, }; @@ -1365,9 +1365,9 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ref tam) => match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), - (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), + ty::TyRef(_, ty, mutbl) => match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", ty, mutbl), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", ty, MutImmutable), _ => return, }, _ => return, @@ -1705,8 +1705,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { for expr in args { let ty = self.cx.tables.expr_ty_adjusted(expr); self.prefer_mutable = false; - if let ty::TyRef(_, mutbl) = ty.sty { - if mutbl.mutbl == MutMutable { + if let ty::TyRef(_, _, mutbl) = ty.sty { + if mutbl == MutMutable { self.prefer_mutable = true; } } @@ -1717,8 +1717,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { self.prefer_mutable = false; - if let ty::TyRef(_, mutbl) = ty.sty { - if mutbl.mutbl == MutMutable { + if let ty::TyRef(_, _, mutbl) = ty.sty { + if mutbl == MutMutable { self.prefer_mutable = true; } } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 23d3c8d433d..3a473ba4775 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -51,8 +51,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 { // the argument is not an &mut T - if let ty::TyRef(_, tam) = ty.sty { - if tam.mutbl == MutImmutable { + if let ty::TyRef(_, _, mutbl) = ty.sty { + if mutbl == MutImmutable { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ using `.cloned()`", type_name), diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 423be2106d1..212310a0f2a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -749,7 +749,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match self_ty.sty { - ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { + ty::TyRef(_, ty, _) if ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { if method_call.name == method && args.len() > pos { lint_single_char_pattern(cx, expr, &args[pos]); } @@ -967,8 +967,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: /// Checks for the `CLONE_ON_COPY` lint. fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) { let ty = cx.tables.expr_ty(expr); - if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty { - if let ty::TyRef(_, ty::TypeAndMut { ty: innermost, .. }) = inner.sty { + if let ty::TyRef(_, inner, _) = arg_ty.sty { + if let ty::TyRef(_, innermost, _) = inner.sty { span_lint_and_then( cx, CLONE_DOUBLE_REF, @@ -978,7 +978,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { let mut ty = innermost; let mut n = 0; - while let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = ty.sty { + while let ty::TyRef(_, inner, _) = ty.sty { ty = inner; n += 1; } @@ -1300,7 +1300,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option may_slice(cx, ty.boxed_ty()), ty::TyAdt(..) => match_type(cx, ty, &paths::VEC), ty::TyArray(_, size) => size.val.to_raw_bits().expect("array length") < 32, - ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => may_slice(cx, inner), + ty::TyRef(_, inner, _) => may_slice(cx, inner), _ => false, } } @@ -1315,7 +1315,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option sugg::Sugg::hir_opt(cx, expr), ty::TyAdt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => if may_slice(cx, inner) { + ty::TyRef(_, inner, _) => if may_slice(cx, inner) { sugg::Sugg::hir_opt(cx, expr) } else { None diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 13c1c930a05..129f022606a 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -72,10 +72,8 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { ); } else if let ty::TyRef( _, - ty::TypeAndMut { - mutbl: hir::MutMutable, - .. - }, + _, + _, ) = self.cx.tables.expr_ty(e).sty { span_lint( diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 5e60ff624a1..a59909c48c8 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -63,10 +63,8 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ match parameter.sty { ty::TyRef( _, - ty::TypeAndMut { - mutbl: MutImmutable, - .. - }, + _, + _, ) | ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 4a6d825130f..7fdef19f183 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -77,11 +77,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } if_chain! { if let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node; - if let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty; - if tam.mutbl == MutImmutable; - if let ty::TyRef(_, ref tam) = tam.ty.sty; + if let ty::TyRef(_, tam, mutbl) = cx.tables.pat_ty(pat).sty; + if mutbl == MutImmutable; + if let ty::TyRef(_, _, mutbl) = tam.sty; // only lint immutable refs, because borrowed `&mut T` cannot be moved out - if tam.mutbl == MutImmutable; + if mutbl == MutImmutable; then { span_lint_and_then( cx, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 17f46f78baa..fb9369c78a0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -152,10 +152,8 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { if let ty::TyRef( _, - ty::TypeAndMut { - ty, - mutbl: MutImmutable, - }, + ty, + _ ) = ty.sty { if match_type(cx, ty, &paths::VEC) { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 63ea96bbcea..4ee0a77f549 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -229,16 +229,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), - (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( + (&ty::TyRef(_, rty, rty_mutbl), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( cx, USELESS_TRANSMUTE, e.span, "transmute from a reference to a pointer", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = if ptr_ty == rty { + let rty_and_mut = ty::TypeAndMut { ty: rty, mutbl: rty_mutbl }; + + let sugg = if ptr_ty == rty_and_mut { arg.as_ty(to_ty) } else { - arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) + arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) }; db.span_suggestion(e.span, "try", sugg.to_string()); @@ -284,7 +286,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { to_ty ), ), - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty)) => span_lint_and_then( + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty, mutbl)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, e.span, @@ -296,16 +298,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ), |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_ref_ty.mutbl == Mutability::MutMutable { + let (deref, cast) = if mutbl == Mutability::MutMutable { ("&mut *", "*mut") } else { ("&*", "*const") }; - let arg = if from_pty.ty == to_ref_ty.ty { + let arg = if from_pty.ty == to_ref_ty { arg } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty.ty))) + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) }; db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); @@ -331,13 +333,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => { + (&ty::TyRef(_, ty_from, from_mutbl), &ty::TyRef(_, ty_to, to_mutbl)) => { if_chain! { - if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ref_from.ty.sty, &ref_to.ty.sty); + if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ty_from.sty, &ty_to.sty); if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty; - if ref_from.mutbl == ref_to.mutbl; + if from_mutbl == to_mutbl; then { - let postfix = if ref_from.mutbl == Mutability::MutMutable { + let postfix = if from_mutbl == Mutability::MutMutable { "_mut" } else { "" @@ -367,8 +369,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, "transmute from a reference to a reference", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(*ref_from)).as_ty(cx.tcx.mk_ptr(*ref_to)); - let sugg = if ref_to.mutbl == Mutability::MutMutable { + let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, mutbl: from_mutbl }; + let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl }; + let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(ty_from_and_mut)).as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + let sugg = if to_mutbl == Mutability::MutMutable { sugg_paren.mut_addr_deref() } else { sugg_paren.addr_deref() diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9234926d534..bc50eb2ac20 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -674,7 +674,7 @@ pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: Ty) -> Ty { match ty.sty { - ty::TyRef(_, ref tm) => walk_ptrs_ty(tm.ty), + ty::TyRef(_, ty, _) => walk_ptrs_ty(ty), _ => ty, } } @@ -684,7 +684,7 @@ pub fn walk_ptrs_ty(ty: Ty) -> Ty { pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) { fn inner(ty: Ty, depth: usize) -> (Ty, usize) { match ty.sty { - ty::TyRef(_, ref tm) => inner(tm.ty, depth + 1), + ty::TyRef(_, ty, _) => inner(ty, depth + 1), _ => (ty, depth), } } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index c98cd8719f1..d5ed4cb712d 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -35,8 +35,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_chain! { - if let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty; - if let ty::TySlice(..) = ty.ty.sty; + if let ty::TyRef(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty; + if let ty::TySlice(..) = ty.sty; if let ExprAddrOf(_, ref addressee) = expr.node; if let Some(vec_args) = higher::vec_macro(cx, addressee); then { -- cgit 1.4.1-3-g733a5 From 39c0f575f2b291d683639afe4b016394d5c242bd Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 May 2018 09:50:29 +0200 Subject: Reintroduce the lost (im)mutability checks --- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 129f022606a..501959e0f62 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } else if let ty::TyRef( _, _, - _, + hir::MutMutable, ) = self.cx.tables.expr_ty(e).sty { span_lint( diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index a59909c48c8..1184433c4dd 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -64,7 +64,7 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ ty::TyRef( _, _, - _, + MutImmutable, ) | ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index fb9369c78a0..240b93e5729 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -153,7 +153,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if let ty::TyRef( _, ty, - _ + MutImmutable ) = ty.sty { if match_type(cx, ty, &paths::VEC) { -- cgit 1.4.1-3-g733a5 From 6baca22e27a58bf493fe4c2b509a899fbe8d46c4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 May 2018 09:56:57 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e27e76ef7da..6bde6136f51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.198 +* Rustup to *rustc 1.27.0-nightly (acd3871ba 2018-05-10)* + ## 0.0.197 * Rustup to *rustc 1.27.0-nightly (428ea5f6b 2018-05-06)* diff --git a/Cargo.toml b/Cargo.toml index 1a924bc7cf1..03d56de37cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.197" +version = "0.0.198" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.197", path = "clippy_lints" } +clippy_lints = { version = "0.0.198", path = "clippy_lints" } # end automatic update regex = "0.2" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 8e0e2633c4f..2b647359618 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.197" +version = "0.0.198" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index b901c8ec520..a2e0b6f1933 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.27.0-nightly (e82261dfb 2018-05-03) +rustc 1.27.0-nightly (acd3871ba 2018-05-10) binary: rustc -commit-hash: e82261dfbb5feaa2d28d2b138f4aabb2aa52c94b -commit-date: 2018-05-03 +commit-hash: acd3871ba17316419c644e17547887787628ec2f +commit-date: 2018-05-10 host: x86_64-unknown-linux-gnu release: 1.27.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From d5b5ba6b9f3c0a66ecca7f70c83987f2f86f8ebb Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 11 May 2018 16:32:05 +0700 Subject: Update to regex 1 (and regex-syntax 0.6). --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 03d56de37cd..083565d344b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.198", path = "clippy_lints" } # end automatic update -regex = "0.2" +regex = "1" semver = "0.9" [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 2b647359618..cc5d36ff1f2 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -21,7 +21,7 @@ itertools = "0.7" lazy_static = "1.0" matches = "0.1.2" quine-mc_cluskey = "0.2.2" -regex-syntax = "0.5.0" +regex-syntax = "0.6" semver = "0.9.0" serde = "1.0" serde_derive = "1.0" -- cgit 1.4.1-3-g733a5 From 654ff185881b6f5ab7048ed2b0c02227323fe0df Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 May 2018 11:32:56 +0200 Subject: deprecate clippy-as-a-plugin --- README.md | 91 --------------------------------------------------------------- 1 file changed, 91 deletions(-) diff --git a/README.md b/README.md index da49a3837c6..3263b74b5a9 100644 --- a/README.md +++ b/README.md @@ -71,44 +71,6 @@ similar crates. SYSROOT=/path/to/rustc/sysroot cargo install clippy ``` -### Optional dependency - -In some cases you might want to include clippy in your project directly, as an -optional dependency. To do this, just modify `Cargo.toml`: - -```toml -[dependencies] -clippy = { version = "*", optional = true } -``` - -And, in your `main.rs` or `lib.rs`, add these lines: - -```rust -#![cfg_attr(feature="clippy", feature(plugin))] -#![cfg_attr(feature="clippy", plugin(clippy))] -``` - -Then build by enabling the feature: `cargo +nightly build --features "clippy"`. - -Instead of adding the `cfg_attr` attributes you can also run clippy on demand: -`cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy` -(the `-Z no trans`, while not necessary, will stop the compilation process after -typechecking (and lints) have completed, which can significantly reduce the runtime). - -Alternatively, to only run clippy when testing: - -```toml -[dev-dependencies] -clippy = { version = "*" } -``` - -and add to `main.rs` or `lib.rs`: - -``` -#![cfg_attr(test, feature(plugin))] -#![cfg_attr(test, plugin(clippy))] -``` - ### Running clippy from the command line without installing it To have cargo compile your crate with clippy without clippy installation and without needing `#![plugin(clippy)]` @@ -121,53 +83,6 @@ cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml *[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* Be sure that clippy was compiled with the same version of rustc that cargo invokes here! -### As a Compiler Plugin - -*Note:* This is not a recommended installation method. - -Since stable Rust is backwards compatible, you should be able to -compile your stable programs with nightly Rust with clippy plugged in to -circumvent this. - -Add in your `Cargo.toml`: - -```toml -[dependencies] -clippy = "*" -``` - -You then need to add `#![feature(plugin)]` and `#![plugin(clippy)]` to the top -of your crate entry point (`main.rs` or `lib.rs`). - -Sample `main.rs`: - -```rust -#![feature(plugin)] - -#![plugin(clippy)] - - -fn main(){ - let x = Some(1u8); - match x { - Some(y) => println!("{:?}", y), - _ => () - } -} -``` - -Produces this warning: - -```terminal -src/main.rs:8:5: 11:6 warning: you seem to be trying to use match for destructuring a single type. Consider using `if let`, #[warn(single_match)] on by default -src/main.rs:8 match x { -src/main.rs:9 Some(y) => println!("{:?}", y), -src/main.rs:10 _ => () -src/main.rs:11 } -src/main.rs:8:5: 11:6 help: Try -if let Some(y) = x { println!("{:?}", y) } -``` - ## Configuration Some lints can be configured in a TOML file named with `clippy.toml` or `.clippy.toml`. It contains basic `variable = value` mapping eg. @@ -180,12 +95,6 @@ cyclomatic-complexity-threshold = 30 See the [list of lints](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the meaning of the variables. -You can also specify the path to the configuration file with: - -```rust -#![plugin(clippy(conf_file="path/to/clippy's/configuration"))] -``` - To deactivate the “for further information visit *lint-link*” message you can define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. -- cgit 1.4.1-3-g733a5 From fd8a1d20ccad8a2dd7b95a9a9a6fe94048a74d5f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 May 2018 13:20:39 +0200 Subject: Remove all mention and testing of #[plugin(clippy)] and warn if used --- CONTRIBUTING.md | 8 +----- README.md | 2 +- src/lib.rs | 7 +++-- tests/auxiliary/conf_french_blacklisted_name.toml | 1 - tests/auxiliary/conf_unknown_key.toml | 6 ---- tests/auxiliary/conf_whitelisted.toml | 3 -- tests/cc_seme.rs | 28 ------------------- tests/conf_whitelisted.rs | 2 -- tests/ice_exacte_size.rs | 17 ------------ tests/issue-825.rs | 15 ---------- tests/mut_mut_macro.rs | 31 --------------------- tests/run-pass/cc_seme.rs | 27 ++++++++++++++++++ tests/run-pass/ice_exacte_size.rs | 17 ++++++++++++ tests/run-pass/issue-825.rs | 13 +++++++++ tests/run-pass/mut_mut_macro.rs | 32 ++++++++++++++++++++++ tests/run-pass/used_underscore_binding_macro.rs | 20 ++++++++++++++ tests/run-pass/whitelist/clippy.toml | 3 ++ tests/run-pass/whitelist/conf_whitelisted.rs | 1 + tests/ui/bad_toml/clippy.toml | 2 ++ tests/ui/bad_toml/conf_bad_toml.rs | 6 ++++ tests/ui/bad_toml/conf_bad_toml.stderr | 0 tests/ui/bad_toml_type/clippy.toml | 1 + tests/ui/bad_toml_type/conf_bad_type.rs | 6 ++++ tests/ui/bad_toml_type/conf_bad_type.stderr | 0 tests/ui/conf_bad_arg.rs | 6 ---- tests/ui/conf_bad_arg.stderr | 11 -------- tests/ui/conf_bad_toml.rs | 6 ---- tests/ui/conf_bad_toml.stderr | 11 -------- tests/ui/conf_bad_toml.toml | 2 -- tests/ui/conf_bad_type.rs | 6 ---- tests/ui/conf_bad_type.stderr | 11 -------- tests/ui/conf_bad_type.toml | 1 - tests/ui/conf_french_blacklisted_name.rs | 23 ---------------- tests/ui/conf_french_blacklisted_name.stderr | 11 -------- tests/ui/conf_path_non_string.rs | 5 ---- tests/ui/conf_path_non_string.stderr | 11 -------- tests/ui/conf_unknown_key.rs | 6 ---- tests/ui/conf_unknown_key.stderr | 11 -------- tests/ui/cyclomatic_complexity.rs | 2 +- tests/ui/cyclomatic_complexity_attr_used.rs | 2 +- tests/ui/diverging_sub_expression.rs | 2 +- tests/ui/dlist.rs | 2 +- tests/ui/enum_variants.rs | 2 +- tests/ui/escape_analysis.rs | 2 +- tests/ui/excessive_precision.rs | 2 +- tests/ui/for_loop.rs | 2 +- tests/ui/mut_mut.rs | 4 +-- tests/ui/new_without_default.rs | 2 +- tests/ui/no_effect.rs | 2 +- tests/ui/toml_blacklist/clippy.toml | 1 + .../toml_blacklist/conf_french_blacklisted_name.rs | 23 ++++++++++++++++ .../conf_french_blacklisted_name.stderr | 0 tests/ui/toml_unknown_key/clippy.toml | 6 ++++ tests/ui/toml_unknown_key/conf_unknown_key.rs | 6 ++++ tests/ui/toml_unknown_key/conf_unknown_key.stderr | 0 tests/ui/trailing_zeros.rs | 2 +- tests/used_underscore_binding_macro.rs | 18 ------------ 57 files changed, 183 insertions(+), 266 deletions(-) delete mode 100644 tests/auxiliary/conf_french_blacklisted_name.toml delete mode 100644 tests/auxiliary/conf_unknown_key.toml delete mode 100644 tests/auxiliary/conf_whitelisted.toml delete mode 100644 tests/cc_seme.rs delete mode 100644 tests/conf_whitelisted.rs delete mode 100644 tests/ice_exacte_size.rs delete mode 100644 tests/issue-825.rs delete mode 100644 tests/mut_mut_macro.rs create mode 100644 tests/run-pass/cc_seme.rs create mode 100644 tests/run-pass/ice_exacte_size.rs create mode 100644 tests/run-pass/issue-825.rs create mode 100644 tests/run-pass/mut_mut_macro.rs create mode 100644 tests/run-pass/used_underscore_binding_macro.rs create mode 100644 tests/run-pass/whitelist/clippy.toml create mode 100644 tests/run-pass/whitelist/conf_whitelisted.rs create mode 100644 tests/ui/bad_toml/clippy.toml create mode 100644 tests/ui/bad_toml/conf_bad_toml.rs create mode 100644 tests/ui/bad_toml/conf_bad_toml.stderr create mode 100644 tests/ui/bad_toml_type/clippy.toml create mode 100644 tests/ui/bad_toml_type/conf_bad_type.rs create mode 100644 tests/ui/bad_toml_type/conf_bad_type.stderr delete mode 100644 tests/ui/conf_bad_arg.rs delete mode 100644 tests/ui/conf_bad_arg.stderr delete mode 100644 tests/ui/conf_bad_toml.rs delete mode 100644 tests/ui/conf_bad_toml.stderr delete mode 100644 tests/ui/conf_bad_toml.toml delete mode 100644 tests/ui/conf_bad_type.rs delete mode 100644 tests/ui/conf_bad_type.stderr delete mode 100644 tests/ui/conf_bad_type.toml delete mode 100644 tests/ui/conf_french_blacklisted_name.rs delete mode 100644 tests/ui/conf_french_blacklisted_name.stderr delete mode 100644 tests/ui/conf_path_non_string.rs delete mode 100644 tests/ui/conf_path_non_string.stderr delete mode 100644 tests/ui/conf_unknown_key.rs delete mode 100644 tests/ui/conf_unknown_key.stderr create mode 100644 tests/ui/toml_blacklist/clippy.toml create mode 100644 tests/ui/toml_blacklist/conf_french_blacklisted_name.rs create mode 100644 tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr create mode 100644 tests/ui/toml_unknown_key/clippy.toml create mode 100644 tests/ui/toml_unknown_key/conf_unknown_key.rs create mode 100644 tests/ui/toml_unknown_key/conf_unknown_key.stderr delete mode 100644 tests/used_underscore_binding_macro.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8089675ead..41812c89f9e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -151,13 +151,7 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running Manually testing against an example file is useful if you have added some `println!`s and test suite output becomes unreadable. To try clippy with your local modifications, run `cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the -working copy root. Your test file, here `input.rs`, needs to have clippy -enabled as a plugin: - -```rust -#![feature(plugin)] -#![plugin(clippy)] -``` +working copy root. ### How Clippy works diff --git a/README.md b/README.md index 3263b74b5a9..9472156ec98 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ SYSROOT=/path/to/rustc/sysroot cargo install clippy ### Running clippy from the command line without installing it -To have cargo compile your crate with clippy without clippy installation and without needing `#![plugin(clippy)]` +To have cargo compile your crate with clippy without clippy installation in your code, you can use: ```terminal diff --git a/src/lib.rs b/src/lib.rs index f8682884a50..e69323255e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,10 +14,11 @@ extern crate clippy_lints; pub fn plugin_registrar(reg: &mut Registry) { reg.sess.lint_store.with_read_lock(|lint_store| { for (lint, _, _) in lint_store.get_lint_groups() { + reg.sess + .struct_warn("the clippy plugin is being deprecated, please use cargo clippy or rls with the clippy feature") + .emit(); if lint == "clippy" { - reg.sess - .struct_warn("running cargo clippy on a crate that also imports the clippy plugin") - .emit(); + // cargo clippy run on a crate that also uses the plugin return; } } diff --git a/tests/auxiliary/conf_french_blacklisted_name.toml b/tests/auxiliary/conf_french_blacklisted_name.toml deleted file mode 100644 index 6abe5a3bbc2..00000000000 --- a/tests/auxiliary/conf_french_blacklisted_name.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/auxiliary/conf_unknown_key.toml b/tests/auxiliary/conf_unknown_key.toml deleted file mode 100644 index 554b87cc50b..00000000000 --- a/tests/auxiliary/conf_unknown_key.toml +++ /dev/null @@ -1,6 +0,0 @@ -# that one is an error -foobar = 42 - -# that one is white-listed -[third-party] -clippy-feature = "nightly" diff --git a/tests/auxiliary/conf_whitelisted.toml b/tests/auxiliary/conf_whitelisted.toml deleted file mode 100644 index 9f87de20baf..00000000000 --- a/tests/auxiliary/conf_whitelisted.toml +++ /dev/null @@ -1,3 +0,0 @@ -# this is ignored by Clippy, but allowed for other tools like clippy-service -[third-party] -clippy-feature = "nightly" diff --git a/tests/cc_seme.rs b/tests/cc_seme.rs deleted file mode 100644 index c81b32c54bc..00000000000 --- a/tests/cc_seme.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#[allow(dead_code)] -enum Baz { - One, - Two, -} - -struct Test { - t: Option, - b: Baz, -} - -fn main() { - use Baz::*; - let x = Test { t: Some(0), b: One }; - - match x { - Test { t: Some(_), b: One } => unreachable!(), - Test { - t: Some(42), - b: Two, - } => unreachable!(), - Test { t: None, .. } => unreachable!(), - Test { .. } => unreachable!(), - } -} diff --git a/tests/conf_whitelisted.rs b/tests/conf_whitelisted.rs deleted file mode 100644 index 10a7d3e72d7..00000000000 --- a/tests/conf_whitelisted.rs +++ /dev/null @@ -1,2 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy(conf_file = "./auxiliary/conf_whitelisted.toml"))] diff --git a/tests/ice_exacte_size.rs b/tests/ice_exacte_size.rs deleted file mode 100644 index eeab3a2bec5..00000000000 --- a/tests/ice_exacte_size.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] -#![deny(clippy)] - -#[allow(dead_code)] -struct Foo; - -impl Iterator for Foo { - type Item = (); - - fn next(&mut self) -> Option<()> { - let _ = self.len() == 0; - unimplemented!() - } -} - -impl ExactSizeIterator for Foo {} diff --git a/tests/issue-825.rs b/tests/issue-825.rs deleted file mode 100644 index f806c2c6fde..00000000000 --- a/tests/issue-825.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] -#![allow(warnings)] - -// this should compile in a reasonable amount of time -fn rust_type_id(name: &str) { - if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] - || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] - || "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] - { - unreachable!(); - } -} - -fn main() {} diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs deleted file mode 100644 index a6473b0f909..00000000000 --- a/tests/mut_mut_macro.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] -#![deny(mut_mut, zero_ptr, cmp_nan)] -#![allow(dead_code)] - -#[macro_use] -extern crate lazy_static; - -use std::collections::HashMap; - -// ensure that we don't suggest `is_nan` and `is_null` inside constants -// FIXME: once const fn is stable, suggest these functions again in constants -const BAA: *const i32 = 0 as *const i32; -static mut BAR: *const i32 = BAA; -static mut FOO: *const i32 = 0 as *const i32; -static mut BUH: bool = 42.0 < std::f32::NAN; - -#[allow(unused_variables, unused_mut)] -fn main() { - lazy_static! { - static ref MUT_MAP : HashMap = { - let mut m = HashMap::new(); - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert_eq!(*MUT_COUNT, 1); - // FIXME: don't lint in array length, requires `check_body` - //let _ = [""; (42.0 < std::f32::NAN) as usize]; -} diff --git a/tests/run-pass/cc_seme.rs b/tests/run-pass/cc_seme.rs new file mode 100644 index 00000000000..1539d3c61bc --- /dev/null +++ b/tests/run-pass/cc_seme.rs @@ -0,0 +1,27 @@ +#[allow(dead_code)] +enum Baz { + One, + Two, +} + +struct Test { + t: Option, + b: Baz, +} + +fn main() { } + +pub fn foo() { + use Baz::*; + let x = Test { t: Some(0), b: One }; + + match x { + Test { t: Some(_), b: One } => unreachable!(), + Test { + t: Some(42), + b: Two, + } => unreachable!(), + Test { t: None, .. } => unreachable!(), + Test { .. } => unreachable!(), + } +} diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs new file mode 100644 index 00000000000..914153c64ff --- /dev/null +++ b/tests/run-pass/ice_exacte_size.rs @@ -0,0 +1,17 @@ +#![deny(clippy)] + +#[allow(dead_code)] +struct Foo; + +impl Iterator for Foo { + type Item = (); + + fn next(&mut self) -> Option<()> { + let _ = self.len() == 0; + unimplemented!() + } +} + +impl ExactSizeIterator for Foo {} + +fn main() {} diff --git a/tests/run-pass/issue-825.rs b/tests/run-pass/issue-825.rs new file mode 100644 index 00000000000..79df259eadb --- /dev/null +++ b/tests/run-pass/issue-825.rs @@ -0,0 +1,13 @@ +#![allow(warnings)] + +// this should compile in a reasonable amount of time +fn rust_type_id(name: &str) { + if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] + || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] + || "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + { + unreachable!(); + } +} + +fn main() {} diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs new file mode 100644 index 00000000000..2b916c025d3 --- /dev/null +++ b/tests/run-pass/mut_mut_macro.rs @@ -0,0 +1,32 @@ +#![deny(mut_mut, zero_ptr, cmp_nan)] +#![allow(dead_code)] + +// compiletest + extern crates doesn't work together +//#[macro_use] +//extern crate lazy_static; + +//use std::collections::HashMap; + +// ensure that we don't suggest `is_nan` and `is_null` inside constants +// FIXME: once const fn is stable, suggest these functions again in constants +const BAA: *const i32 = 0 as *const i32; +static mut BAR: *const i32 = BAA; +static mut FOO: *const i32 = 0 as *const i32; +static mut BUH: bool = 42.0 < std::f32::NAN; + +#[allow(unused_variables, unused_mut)] +fn main() { + /* + lazy_static! { + static ref MUT_MAP : HashMap = { + let mut m = HashMap::new(); + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert_eq!(*MUT_COUNT, 1); + */ + // FIXME: don't lint in array length, requires `check_body` + //let _ = [""; (42.0 < std::f32::NAN) as usize]; +} diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs new file mode 100644 index 00000000000..c9c77257c0e --- /dev/null +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -0,0 +1,20 @@ + + + +#[macro_use] +extern crate serde_derive; + +/// Test that we do not lint for unused underscores in a `MacroAttribute` +/// expansion +#[deny(used_underscore_binding)] +#[derive(Deserialize)] +struct MacroAttributesTest { + _foo: u32, +} + +#[test] +fn macro_attributes_test() { + let _ = MacroAttributesTest { _foo: 0 }; +} + +fn main() {} diff --git a/tests/run-pass/whitelist/clippy.toml b/tests/run-pass/whitelist/clippy.toml new file mode 100644 index 00000000000..9f87de20baf --- /dev/null +++ b/tests/run-pass/whitelist/clippy.toml @@ -0,0 +1,3 @@ +# this is ignored by Clippy, but allowed for other tools like clippy-service +[third-party] +clippy-feature = "nightly" diff --git a/tests/run-pass/whitelist/conf_whitelisted.rs b/tests/run-pass/whitelist/conf_whitelisted.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/run-pass/whitelist/conf_whitelisted.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui/bad_toml/clippy.toml b/tests/ui/bad_toml/clippy.toml new file mode 100644 index 00000000000..823e01a33b9 --- /dev/null +++ b/tests/ui/bad_toml/clippy.toml @@ -0,0 +1,2 @@ +fn this_is_obviously(not: a, toml: file) { +} diff --git a/tests/ui/bad_toml/conf_bad_toml.rs b/tests/ui/bad_toml/conf_bad_toml.rs new file mode 100644 index 00000000000..325688ac7da --- /dev/null +++ b/tests/ui/bad_toml/conf_bad_toml.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file + + + + +fn main() {} diff --git a/tests/ui/bad_toml/conf_bad_toml.stderr b/tests/ui/bad_toml/conf_bad_toml.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/bad_toml_type/clippy.toml b/tests/ui/bad_toml_type/clippy.toml new file mode 100644 index 00000000000..168675394d7 --- /dev/null +++ b/tests/ui/bad_toml_type/clippy.toml @@ -0,0 +1 @@ +blacklisted-names = 42 diff --git a/tests/ui/bad_toml_type/conf_bad_type.rs b/tests/ui/bad_toml_type/conf_bad_type.rs new file mode 100644 index 00000000000..f97f5802b13 --- /dev/null +++ b/tests/ui/bad_toml_type/conf_bad_type.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` + + + + +fn main() {} diff --git a/tests/ui/bad_toml_type/conf_bad_type.stderr b/tests/ui/bad_toml_type/conf_bad_type.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/conf_bad_arg.rs b/tests/ui/conf_bad_arg.rs deleted file mode 100644 index b988fdb1385..00000000000 --- a/tests/ui/conf_bad_arg.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: `conf_file` must be a named value - - -#![plugin(clippy(conf_file))] - -fn main() {} diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr deleted file mode 100644 index 094b7d49cb5..00000000000 --- a/tests/ui/conf_bad_arg.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_bad_arg.rs:4:1 - | -4 | #![plugin(clippy(conf_file))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_bad_toml.rs b/tests/ui/conf_bad_toml.rs deleted file mode 100644 index a2ce7ecc519..00000000000 --- a/tests/ui/conf_bad_toml.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file - - -#![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] - -fn main() {} diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr deleted file mode 100644 index 640b1c5e610..00000000000 --- a/tests/ui/conf_bad_toml.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_bad_toml.rs:4:1 - | -4 | #![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_bad_toml.toml b/tests/ui/conf_bad_toml.toml deleted file mode 100644 index 823e01a33b9..00000000000 --- a/tests/ui/conf_bad_toml.toml +++ /dev/null @@ -1,2 +0,0 @@ -fn this_is_obviously(not: a, toml: file) { -} diff --git a/tests/ui/conf_bad_type.rs b/tests/ui/conf_bad_type.rs deleted file mode 100644 index cb18bfb8c90..00000000000 --- a/tests/ui/conf_bad_type.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` - - -#![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] - -fn main() {} diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr deleted file mode 100644 index f92b52ec032..00000000000 --- a/tests/ui/conf_bad_type.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_bad_type.rs:4:1 - | -4 | #![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_bad_type.toml b/tests/ui/conf_bad_type.toml deleted file mode 100644 index 168675394d7..00000000000 --- a/tests/ui/conf_bad_type.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = 42 diff --git a/tests/ui/conf_french_blacklisted_name.rs b/tests/ui/conf_french_blacklisted_name.rs deleted file mode 100644 index dbe6d85e5d2..00000000000 --- a/tests/ui/conf_french_blacklisted_name.rs +++ /dev/null @@ -1,23 +0,0 @@ - -#![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] - -#![allow(dead_code)] -#![allow(single_match)] -#![allow(unused_variables)] -#![warn(blacklisted_name)] - -fn test(toto: ()) {} - -fn main() { - let toto = 42; - let tata = 42; - let titi = 42; - - let tatab = 42; - let tatatataic = 42; - - match (42, Some(1337), Some(0)) { - (toto, Some(tata), titi @ Some(_)) => (), - _ => (), - } -} diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr deleted file mode 100644 index 214226ac2f9..00000000000 --- a/tests/ui/conf_french_blacklisted_name.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_french_blacklisted_name.rs:2:1 - | -2 | #![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_path_non_string.rs b/tests/ui/conf_path_non_string.rs deleted file mode 100644 index 8d1f01358fc..00000000000 --- a/tests/ui/conf_path_non_string.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(attr_literals)] - -#![plugin(clippy(conf_file=42))] - -fn main() {} diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr deleted file mode 100644 index 10b007b0de0..00000000000 --- a/tests/ui/conf_path_non_string.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_path_non_string.rs:3:1 - | -3 | #![plugin(clippy(conf_file=42))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conf_unknown_key.rs b/tests/ui/conf_unknown_key.rs deleted file mode 100644 index 437d0f9d8b0..00000000000 --- a/tests/ui/conf_unknown_key.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file: unknown key `foobar` - - -#![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] - -fn main() {} diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr deleted file mode 100644 index d7ac055c517..00000000000 --- a/tests/ui/conf_unknown_key.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597) - --> $DIR/conf_unknown_key.rs:4:1 - | -4 | #![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(plugin)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 0f5726e1ad7..1afae69c186 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,4 +1,4 @@ -#![feature(plugin, custom_attribute)] +#![feature(custom_attribute)] #![allow(clippy)] #![warn(cyclomatic_complexity)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index 5284d60a524..f3895c7e3ab 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,4 +1,4 @@ -#![feature(plugin, custom_attribute)] +#![feature(custom_attribute)] #![warn(cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index d2aea93a77d..b89a2f1bcaf 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,4 +1,4 @@ -#![feature(plugin, never_type)] +#![feature(never_type)] #![warn(diverging_sub_expression)] #![allow(match_same_arms, logic_bug)] diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 59f0d3fe39b..a4fab5735e2 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -1,4 +1,4 @@ -#![feature(plugin, alloc)] +#![feature(alloc)] #![feature(associated_type_defaults)] diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 3be01427134..222c76c25b7 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,4 +1,4 @@ -#![feature(plugin, non_ascii_idents)] +#![feature(non_ascii_idents)] #![warn(clippy, pub_enum_variant_names)] diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index b99534d05e1..7a888f01914 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -1,4 +1,4 @@ -#![feature(plugin, box_syntax)] +#![feature(box_syntax)] #![allow(warnings, clippy)] diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 47e73aa0bcd..25b6555715f 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,4 +1,4 @@ -#![feature(plugin, custom_attribute)] +#![feature(custom_attribute)] #![warn(excessive_precision)] #![allow(print_literal)] diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 0a8be4d938b..1f879c5843e 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin, custom_attribute)] +#![feature(custom_attribute)] use std::collections::*; diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 54176cd6d55..658ae18466f 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -4,8 +4,8 @@ #![allow(unused, no_effect, unnecessary_operation)] #![warn(mut_mut)] -//#![plugin(regex_macros)] -//extern crate regex; + + fn fun(x : &mut &mut u32) -> bool { **x > 0 diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index e618bf1c231..c06c9f9e962 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,4 +1,4 @@ -#![feature(plugin, const_fn)] +#![feature(const_fn)] #![allow(dead_code)] diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index d1e4bf2a2c7..54028cd8b2b 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,4 +1,4 @@ -#![feature(plugin, box_syntax)] +#![feature(box_syntax)] #![warn(no_effect, unnecessary_operation)] diff --git a/tests/ui/toml_blacklist/clippy.toml b/tests/ui/toml_blacklist/clippy.toml new file mode 100644 index 00000000000..6abe5a3bbc2 --- /dev/null +++ b/tests/ui/toml_blacklist/clippy.toml @@ -0,0 +1 @@ +blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs new file mode 100644 index 00000000000..1f1a8ee91a1 --- /dev/null +++ b/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs @@ -0,0 +1,23 @@ + + + +#![allow(dead_code)] +#![allow(single_match)] +#![allow(unused_variables)] +#![warn(blacklisted_name)] + +fn test(toto: ()) {} + +fn main() { + let toto = 42; + let tata = 42; + let titi = 42; + + let tatab = 42; + let tatatataic = 42; + + match (42, Some(1337), Some(0)) { + (toto, Some(tata), titi @ Some(_)) => (), + _ => (), + } +} diff --git a/tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/toml_unknown_key/clippy.toml b/tests/ui/toml_unknown_key/clippy.toml new file mode 100644 index 00000000000..554b87cc50b --- /dev/null +++ b/tests/ui/toml_unknown_key/clippy.toml @@ -0,0 +1,6 @@ +# that one is an error +foobar = 42 + +# that one is white-listed +[third-party] +clippy-feature = "nightly" diff --git a/tests/ui/toml_unknown_key/conf_unknown_key.rs b/tests/ui/toml_unknown_key/conf_unknown_key.rs new file mode 100644 index 00000000000..bfa804558bb --- /dev/null +++ b/tests/ui/toml_unknown_key/conf_unknown_key.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: unknown key `foobar` + + + + +fn main() {} diff --git a/tests/ui/toml_unknown_key/conf_unknown_key.stderr b/tests/ui/toml_unknown_key/conf_unknown_key.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 6a7b6b05e70..d915a0bed09 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,4 +1,4 @@ -#![feature(plugin, custom_attribute, stmt_expr_attributes)] +#![feature(custom_attribute, stmt_expr_attributes)] #![allow(unused_parens)] diff --git a/tests/used_underscore_binding_macro.rs b/tests/used_underscore_binding_macro.rs deleted file mode 100644 index b323cb5d25b..00000000000 --- a/tests/used_underscore_binding_macro.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(plugin)] -#![plugin(clippy)] - -#[macro_use] -extern crate serde_derive; - -/// Test that we do not lint for unused underscores in a `MacroAttribute` -/// expansion -#[deny(used_underscore_binding)] -#[derive(Deserialize)] -struct MacroAttributesTest { - _foo: u32, -} - -#[test] -fn macro_attributes_test() { - let _ = MacroAttributesTest { _foo: 0 }; -} -- cgit 1.4.1-3-g733a5 From 22bef4ce28d7fcf24bd3637cf241bad18c623909 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 11 May 2018 19:05:34 +0200 Subject: Patterns, locals and matches for author lint --- .gitignore | 2 + clippy_lints/src/utils/author.rs | 181 ++++++++++++++++++++++++++++++++++++++- tests/ui/author.stdout | 7 +- tests/ui/author/for_loop.rs | 8 ++ tests/ui/author/for_loop.stdout | 60 +++++++++++++ tests/ui/author/matches.rs | 13 +++ tests/ui/author/matches.stderr | 15 ++++ tests/ui/author/matches.stout | 38 ++++++++ tests/ui/for_loop.rs | 2 +- tests/ui/for_loop.stderr | 6 +- tests/ui/for_loop.stdout | 20 ----- 11 files changed, 323 insertions(+), 29 deletions(-) create mode 100644 tests/ui/author/for_loop.rs create mode 100644 tests/ui/author/for_loop.stdout create mode 100644 tests/ui/author/matches.rs create mode 100644 tests/ui/author/matches.stderr create mode 100644 tests/ui/author/matches.stout delete mode 100644 tests/ui/for_loop.stdout diff --git a/.gitignore b/.gitignore index 5c665bebd04..5ca1e06a5e5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,12 @@ out # Compiled files *.o +*.d *.so *.rlib *.dll *.pyc +*.rmeta # Executables *.exe diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index fccb47817e0..2f53b7a579e 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::{Expr, Expr_, QPath, Ty_}; +use rustc::hir::{Expr, Expr_, QPath, Ty_, Pat, PatKind, BindingAnnotation, StmtSemi, StmtExpr, StmtDecl, Decl_, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use syntax::ast::{self, Attribute, LitKind, DUMMY_NODE_ID}; use std::collections::HashMap; @@ -322,10 +322,29 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = body_pat; self.visit_block(body); }, - Expr_::ExprMatch(ref _expr, ref _arms, desugaring) => { + Expr_::ExprMatch(ref expr, ref arms, desugaring) => { let des = desugaring_name(desugaring); - println!("Match(ref expr, ref arms, {}) = {};", des, current); - println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); + let expr_pat = self.next("expr"); + let arms_pat = self.next("arms"); + println!("Match(ref {}, ref {}, {}) = {};", expr_pat, arms_pat, des, current); + self.current = expr_pat; + self.visit_expr(expr); + println!(" if {}.len() == {};", arms_pat, arms.len()); + for (i, arm) in arms.iter().enumerate() { + self.current = format!("{}[{}].body", arms_pat, i); + self.visit_expr(&arm.body); + if let Some(ref guard) = arm.guard { + let guard_pat = self.next("guard"); + println!(" if let Some(ref {}) = {}[{}].guard", guard_pat, arms_pat, i); + self.current = guard_pat; + self.visit_expr(guard); + } + println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len()); + for (j, pat) in arm.pats.iter().enumerate() { + self.current = format!("{}[{}].pats[{}]", arms_pat, i, j); + self.visit_pat(pat); + } + } }, Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current); @@ -454,6 +473,160 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } + fn visit_pat(&mut self, pat: &Pat) { + print!(" if let PatKind::"); + let current = format!("{}.node", self.current); + match pat.node { + PatKind::Wild => println!("Wild = {};", current), + PatKind::Binding(anno, _, name, ref sub) => { + let anno_pat = match anno { + BindingAnnotation::Unannotated => "BindingAnnotation::Unannotated", + BindingAnnotation::Mutable => "BindingAnnotation::Mutable", + BindingAnnotation::Ref => "BindingAnnotation::Ref", + BindingAnnotation::RefMut => "BindingAnnotation::RefMut", + }; + let name_pat = self.next("name"); + if let Some(ref sub) = *sub { + let sub_pat = self.next("sub"); + println!("Binding({}, _, {}, Some(ref {})) = {};", anno_pat, name_pat, sub_pat, current); + self.current = sub_pat; + self.visit_pat(sub); + } else { + println!("Binding({}, _, {}, None) = {};", anno_pat, name_pat, current); + } + println!(" if {}.node.as_str() == \"{}\";", name_pat, name.node.as_str()); + } + PatKind::Struct(ref path, ref fields, ignore) => { + let path_pat = self.next("path"); + let fields_pat = self.next("fields"); + println!("Struct(ref {}, ref {}, {}) = {};", path_pat, fields_pat, ignore, current); + self.current = path_pat; + self.print_qpath(path); + println!(" if {}.len() == {};", fields_pat, fields.len()); + println!(" // unimplemented: field checks"); + } + PatKind::TupleStruct(ref path, ref fields, skip_pos) => { + let path_pat = self.next("path"); + let fields_pat = self.next("fields"); + println!("TupleStruct(ref {}, ref {}, {:?}) = {};", path_pat, fields_pat, skip_pos, current); + self.current = path_pat; + self.print_qpath(path); + println!(" if {}.len() == {};", fields_pat, fields.len()); + println!(" // unimplemented: field checks"); + }, + PatKind::Path(ref path) => { + let path_pat = self.next("path"); + println!("Path(ref {}) = {};", path_pat, current); + self.current = path_pat; + self.print_qpath(path); + } + PatKind::Tuple(ref fields, skip_pos) => { + let fields_pat = self.next("fields"); + println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current); + println!(" if {}.len() == {};", fields_pat, fields.len()); + println!(" // unimplemented: field checks"); + } + PatKind::Box(ref pat) => { + let pat_pat = self.next("pat"); + println!("Box(ref {}) = {};", pat_pat, current); + self.current = pat_pat; + self.visit_pat(pat); + }, + PatKind::Ref(ref pat, muta) => { + let pat_pat = self.next("pat"); + println!("Ref(ref {}, Mutability::{:?}) = {};", pat_pat, muta, current); + self.current = pat_pat; + self.visit_pat(pat); + }, + PatKind::Lit(ref lit_expr) => { + let lit_expr_pat = self.next("lit_expr"); + println!("Lit(ref {}) = {}", lit_expr_pat, current); + self.current = lit_expr_pat; + self.visit_expr(lit_expr); + } + PatKind::Range(ref start, ref end, end_kind) => { + let start_pat = self.next("start"); + let end_pat = self.next("end"); + println!("Range(ref {}, ref {}, RangeEnd::{:?}) = {};", start_pat, end_pat, end_kind, current); + self.current = start_pat; + self.visit_expr(start); + self.current = end_pat; + self.visit_expr(end); + } + PatKind::Slice(ref start, ref middle, ref end) => { + let start_pat = self.next("start"); + let end_pat = self.next("end"); + if let Some(ref middle) = middle { + let middle_pat = self.next("middle"); + println!("Slice(ref {}, Some(ref {}), ref {}) = {};", start_pat, middle_pat, end_pat, current); + self.current = middle_pat; + self.visit_pat(middle); + } else { + println!("Slice(ref {}, None, ref {}) = {};", start_pat, end_pat, current); + } + println!(" if {}.len() == {};", start_pat, start.len()); + for (i, pat) in start.iter().enumerate() { + self.current = format!("{}[{}]", start_pat, i); + self.visit_pat(pat); + } + println!(" if {}.len() == {};", end_pat, end.len()); + for (i, pat) in end.iter().enumerate() { + self.current = format!("{}[{}]", end_pat, i); + self.visit_pat(pat); + } + } + } + } + + fn visit_stmt(&mut self, s: &Stmt) { + print!(" if let Stmt_::"); + let current = format!("{}.node", self.current); + match s.node { + // Could be an item or a local (let) binding: + StmtDecl(ref decl, _) => { + let decl_pat = self.next("decl"); + println!("StmtDecl(ref {}, _) = {}", decl_pat, current); + print!(" if let Decl_::"); + let current = format!("{}.node", decl_pat); + match decl.node { + // A local (let) binding: + Decl_::DeclLocal(ref local) => { + let local_pat = self.next("local"); + println!("DeclLocal(ref {}) = {};", local_pat, current); + if let Some(ref init) = local.init { + let init_pat = self.next("init"); + println!(" if let Some(ref {}) = {}.init", init_pat, local_pat); + self.current = init_pat; + self.visit_expr(init); + } + self.current = format!("{}.pat", local_pat); + self.visit_pat(&local.pat); + }, + // An item binding: + Decl_::DeclItem(_) => { + println!("DeclItem(item_id) = {};", current); + }, + } + } + + // Expr without trailing semi-colon (must have unit type): + StmtExpr(ref e, _) => { + let e_pat = self.next("e"); + println!("StmtExpr(ref {}, _) = {}", e_pat, current); + self.current = e_pat; + self.visit_expr(e); + }, + + // Expr with trailing semi-colon (may have any type): + StmtSemi(ref e, _) => { + let e_pat = self.next("e"); + println!("StmtSemi(ref {}, _) = {}", e_pat, current); + self.current = e_pat; + self.visit_expr(e); + }, + } + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index 0efb3e8b272..a55b48985ad 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -1,9 +1,14 @@ if_chain! { - if let Expr_::ExprCast(ref expr, ref cast_ty) = stmt.node; + if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let Decl_::DeclLocal(ref local) = decl.node; + if let Some(ref init) = local.init + if let Expr_::ExprCast(ref expr, ref cast_ty) = init.node; if let Ty_::TyPath(ref qp) = cast_ty.node; if match_qpath(qp, &["char"]); if let Expr_::ExprLit(ref lit) = expr.node; if let LitKind::Int(69, _) = lit.node; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.node; + if name.node.as_str() == "x"; then { // report your lint here } diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs new file mode 100644 index 00000000000..657bf51bf80 --- /dev/null +++ b/tests/ui/author/for_loop.rs @@ -0,0 +1,8 @@ +#![feature(custom_attribute)] + +fn main() { + #[clippy(author)] + for y in 0..10 { + let z = y; + } +} diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout new file mode 100644 index 00000000000..af6b5a4ec33 --- /dev/null +++ b/tests/ui/author/for_loop.stdout @@ -0,0 +1,60 @@ +if_chain! { + if let Expr_::ExprBlock(ref block) = expr.node; + if let Stmt_::StmtDecl(ref decl, _) = block.node + if let Decl_::DeclLocal(ref local) = decl.node; + if let Some(ref init) = local.init + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; + if let Expr_::ExprCall(ref func, ref args) = expr.node; + // unimplemented: `ExprCall` is not further destructured at the moment + if arms.len() == 1; + if let Expr_::ExprLoop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; + if let Stmt_::StmtDecl(ref decl1, _) = body.node + if let Decl_::DeclLocal(ref local1) = decl1.node; + if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; + if name.node.as_str() == "__next"; + if let Stmt_::StmtExpr(ref e, _) = local1.pat.node + if let Expr_::ExprMatch(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; + if let Expr_::ExprCall(ref func, ref args) = expr1.node; + // unimplemented: `ExprCall` is not further destructured at the moment + if arms1.len() == 2; + if let Expr_::ExprAssign(ref target, ref value) = arms1[0].body.node; + if let Expr_::ExprPath(ref path) = target.node; + if match_qpath(path, &["__next"]); + if let Expr_::ExprPath(ref path1) = value.node; + if match_qpath(path1, &["val"]); + if arms1[0].pats.len() == 1; + if let PatKind::TupleStruct(ref path2, ref fields, None) = arms1[0].pats[0].node; + if match_qpath(path2, &["{{root}}", "std", "option", "Option", "Some"]); + if fields.len() == 1; + // unimplemented: field checks + if let Expr_::ExprBreak(ref destination, None) = arms1[1].body.node; + if arms1[1].pats.len() == 1; + if let PatKind::Path(ref path3) = arms1[1].pats[0].node; + if match_qpath(path3, &["{{root}}", "std", "option", "Option", "None"]); + if let Stmt_::StmtDecl(ref decl2, _) = path3.node + if let Decl_::DeclLocal(ref local2) = decl2.node; + if let Some(ref init1) = local2.init + if let Expr_::ExprPath(ref path4) = init1.node; + if match_qpath(path4, &["__next"]); + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local2.pat.node; + if name1.node.as_str() == "y"; + if let Stmt_::StmtExpr(ref e1, _) = local2.pat.node + if let Expr_::ExprBlock(ref block1) = e1.node; + if let Stmt_::StmtDecl(ref decl3, _) = block1.node + if let Decl_::DeclLocal(ref local3) = decl3.node; + if let Some(ref init2) = local3.init + if let Expr_::ExprPath(ref path5) = init2.node; + if match_qpath(path5, &["y"]); + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local3.pat.node; + if name2.node.as_str() == "z"; + if arms[0].pats.len() == 1; + if let PatKind::Binding(BindingAnnotation::Mutable, _, name3, None) = arms[0].pats[0].node; + if name3.node.as_str() == "iter"; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name4, None) = local.pat.node; + if name4.node.as_str() == "_result"; + if let Expr_::ExprPath(ref path6) = local.pat.node; + if match_qpath(path6, &["_result"]); + then { + // report your lint here + } +} diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs new file mode 100644 index 00000000000..f426302da09 --- /dev/null +++ b/tests/ui/author/matches.rs @@ -0,0 +1,13 @@ +#![feature(custom_attribute)] + +fn main() { + #[clippy(author)] + let a = match 42 { + 16 => 5, + 17 => { + let x = 3; + x + }, + _ => 1, + }; +} diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr new file mode 100644 index 00000000000..c4f69b10df7 --- /dev/null +++ b/tests/ui/author/matches.stderr @@ -0,0 +1,15 @@ +error: returning the result of a let binding from a block. Consider returning the expression directly. + --> $DIR/matches.rs:9:13 + | +9 | x + | ^ + | + = note: `-D let-and-return` implied by `-D warnings` +note: this expression can be directly returned + --> $DIR/matches.rs:8:21 + | +8 | let x = 3; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/author/matches.stout b/tests/ui/author/matches.stout new file mode 100644 index 00000000000..db7de5a2ca5 --- /dev/null +++ b/tests/ui/author/matches.stout @@ -0,0 +1,38 @@ +if_chain! { + if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let Decl_::DeclLocal(ref local) = decl.node; + if let Some(ref init) = local.init + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::Normal) = init.node; + if let Expr_::ExprLit(ref lit) = expr.node; + if let LitKind::Int(42, _) = lit.node; + if arms.len() == 3; + if let Expr_::ExprLit(ref lit1) = arms[0].body.node; + if let LitKind::Int(5, _) = lit1.node; + if arms[0].pats.len() == 1; + if let PatKind::Lit(ref lit_expr) = arms[0].pats[0].node + if let Expr_::ExprLit(ref lit2) = lit_expr.node; + if let LitKind::Int(16, _) = lit2.node; + if let Expr_::ExprBlock(ref block) = arms[1].body.node; + if let Stmt_::StmtDecl(ref decl1, _) = block.node + if let Decl_::DeclLocal(ref local1) = decl1.node; + if let Some(ref init1) = local1.init + if let Expr_::ExprLit(ref lit3) = init1.node; + if let LitKind::Int(3, _) = lit3.node; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local1.pat.node; + if name.node.as_str() == "x"; + if let Expr_::ExprPath(ref path) = local1.pat.node; + if match_qpath(path, &["x"]); + if arms[1].pats.len() == 1; + if let PatKind::Lit(ref lit_expr1) = arms[1].pats[0].node + if let Expr_::ExprLit(ref lit4) = lit_expr1.node; + if let LitKind::Int(17, _) = lit4.node; + if let Expr_::ExprLit(ref lit5) = arms[2].body.node; + if let LitKind::Int(1, _) = lit5.node; + if arms[2].pats.len() == 1; + if let PatKind::Wild = arms[2].pats[0].node; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.node; + if name1.node.as_str() == "a"; + then { + // report your lint here + } +} diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 0a8be4d938b..99ac7e4c019 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -14,7 +14,7 @@ fn for_loop_over_option_and_result() { let v = vec![0, 1, 2]; // check FOR_LOOP_OVER_OPTION lint - #[clippy(author)]for x in option { + for x in option { println!("{}", x); } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 261a403de57..34b3527fbae 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,8 +1,8 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:17:31 + --> $DIR/for_loop.rs:17:14 | -17 | #[clippy(author)]for x in option { - | ^^^^^^ +17 | for x in option { + | ^^^^^^ | = note: `-D for-loop-over-option` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` diff --git a/tests/ui/for_loop.stdout b/tests/ui/for_loop.stdout deleted file mode 100644 index ce4186fa6a1..00000000000 --- a/tests/ui/for_loop.stdout +++ /dev/null @@ -1,20 +0,0 @@ -if_chain! { - if let Expr_::ExprBlock(ref block) = stmt.node; - if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; - // unimplemented: `ExprMatch` is not further destructured at the moment - if let Expr_::ExprPath(ref path) = block.node; - if match_qpath(path, &["_result"]); - then { - // report your lint here - } -} -if_chain! { - if let Expr_::ExprBlock(ref block) = expr.node; - if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; - // unimplemented: `ExprMatch` is not further destructured at the moment - if let Expr_::ExprPath(ref path) = block.node; - if match_qpath(path, &["_result"]); - then { - // report your lint here - } -} -- cgit 1.4.1-3-g733a5 From fa0d9c578219bbb0d931221ee258fb603e24e940 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 12 May 2018 10:33:35 +0200 Subject: Explain how to debug and fix nightly build failures --- CONTRIBUTING.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8089675ead..69bc3546ba0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,7 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Running test suite](#running-test-suite) * [Testing manually](#testing-manually) * [How Clippy works](#how-clippy-works) + * [Fixing nightly build failures](#fixing-nightly-build-failures) * [Contributions](#contributions) ## Getting started @@ -209,6 +210,17 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. +### Fixing nightly build failures + +Clippy will sometimes break with new nightly version releases. This is expected because Clippy still depends on nightly Rust. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in rust. + +In order to find out why Clippy does not work properly with a new nightly version, you can use the [rust-toolstate commit history][toolstate_commit_history]. +You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. + +The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. + +Fixing nightly build failures is also a good way to learn about actual rustc internals. + ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will @@ -229,3 +241,5 @@ All code in this repository is under the [Mozilla Public License, 2.0](https://w [reg_late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_late_lint_pass [early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html [late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html +[toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master +[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/6ce0459f6bfa7c528ae1886492a3e0b5ef0ee547 -- cgit 1.4.1-3-g733a5 From 26b48bbdfc7aa1e8d4d10b13e7b63e981704f932 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 13 May 2018 10:44:57 +0200 Subject: Rustup to 2018-05-13 --- clippy_lints/src/array_indexing.rs | 2 +- clippy_lints/src/consts.rs | 8 ++++---- clippy_lints/src/loops.rs | 8 ++++---- clippy_lints/src/methods.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index e07804468e1..b51a9209c4c 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, size) = ty.sty { - let size = size.val.to_raw_bits().unwrap(); + let size = size.assert_usize(cx.tcx).unwrap().into(); // Index is a constant uint if let Some((Constant::Int(const_index), _)) = constant(cx, index) { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 3668f523293..a078fde4790 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -209,7 +209,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprRepeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::TyArray(_, n) => n.val.to_raw_bits().expect("array length"), + ty::TyArray(_, n) => n.assert_usize(self.tcx).expect("array length"), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64)) @@ -415,9 +415,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use rustc::mir::interpret::{Value, PrimVal}; + use rustc::mir::interpret::{PrimVal, ConstValue}; match result.val { - ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => match result.ty.sty { + ConstVal::Value(ConstValue::ByVal(PrimVal::Bytes(b))) => match result.ty.sty { ty::TyBool => Some(Constant::Bool(b == 1)), ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)), ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), @@ -425,7 +425,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' // FIXME: implement other conversion _ => None, }, - ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty { + ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty { ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 50e6e4c3b3f..a7ca0d27e17 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1223,7 +1223,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { match cx.tables.expr_ty(&args[0]).sty { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. - ty::TypeVariants::TyArray(_, size) if size.val.to_raw_bits().expect("array size") > 32 => (), + ty::TypeVariants::TyArray(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), _ => lint_iter_method(cx, args, arg, method_name), }; } else { @@ -1784,7 +1784,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tables.expr_ty(e); - is_iterable_array(ty) || + is_iterable_array(ty, cx) || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::HASHMAP) || @@ -1795,10 +1795,10 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { match_type(cx, ty, &paths::BTREESET) } -fn is_iterable_array(ty: Ty) -> bool { +fn is_iterable_array(ty: Ty, cx: &LateContext) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0..=32).contains(&n.val.to_raw_bits().expect("array length")), + ty::TyArray(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")), _ => false, } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 212310a0f2a..c7702e6bced 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1299,7 +1299,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option true, ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::TyAdt(..) => match_type(cx, ty, &paths::VEC), - ty::TyArray(_, size) => size.val.to_raw_bits().expect("array length") < 32, + ty::TyArray(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, ty::TyRef(_, inner, _) => may_slice(cx, inner), _ => false, } -- cgit 1.4.1-3-g733a5 From a8d7e5a1f231a80a5d6a86de97ff705c64ef4c3e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 13 May 2018 11:16:07 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bde6136f51..1cb596d81d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.199 +* Rustup to *rustc 1.27.0-nightly (ff2ac35db 2018-05-12)* + ## 0.0.198 * Rustup to *rustc 1.27.0-nightly (acd3871ba 2018-05-10)* diff --git a/Cargo.toml b/Cargo.toml index 083565d344b..a200a6710ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.198" +version = "0.0.199" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.198", path = "clippy_lints" } +clippy_lints = { version = "0.0.199", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index cc5d36ff1f2..284f7e75c19 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.198" +version = "0.0.199" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index a2e0b6f1933..9d1de5e2c79 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.27.0-nightly (acd3871ba 2018-05-10) +rustc 1.27.0-nightly (ff2ac35db 2018-05-12) binary: rustc -commit-hash: acd3871ba17316419c644e17547887787628ec2f -commit-date: 2018-05-10 +commit-hash: ff2ac35db93a80b2de5daa4f280bf1503d62c164 +commit-date: 2018-05-12 host: x86_64-unknown-linux-gnu release: 1.27.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 364f42d78d5227c6d31360a4fe6ba3503256133a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 13 May 2018 10:11:52 +0200 Subject: Fix build script for dev channel --- build.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/build.rs b/build.rs index c13eed1f585..913f7b4ee89 100644 --- a/build.rs +++ b/build.rs @@ -21,6 +21,15 @@ use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMet use ansi_term::Colour::Red; fn main() { + check_rustc_version(); + + // Forward the profile to the main compilation + println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + // Don't rebuild even if nothing changed + println!("cargo:rerun-if-changed=build.rs"); +} + +fn check_rustc_version() { let string = include_str!("min_version.txt"); let min_version_meta = version_meta_for(string) .expect("Could not parse version string in min_version.txt"); @@ -31,6 +40,12 @@ fn main() { let min_date_str = min_version_meta.clone().commit_date .expect("min_version.txt does not contain a rustc commit date"); + // Dev channel (rustc built from git) does not have any date or commit information in rustc -vV + // `current_version_meta.commit_date` would crash, so we return early here. + if current_version_meta.channel == Channel::Dev { + return + } + let current_version = current_version_meta.clone().semver; let current_date_str = current_version_meta.clone().commit_date .expect("current rustc version information does not contain a rustc commit date"); @@ -69,11 +84,6 @@ fn main() { print_version_err(¤t_version, &*current_date_str); panic!("Aborting compilation due to incompatible compiler.") } - - // Forward the profile to the main compilation - println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); - // Don't rebuild even if nothing changed - println!("cargo:rerun-if-changed=build.rs"); } fn correct_channel(version_meta: &VersionMeta) -> bool { -- cgit 1.4.1-3-g733a5 From ecf4f5128f00128fb856798592203146d864e203 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 13 May 2018 13:47:54 +0200 Subject: Fix two typos --- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 5cbf7d03191..1a8c0c28e8e 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -170,7 +170,7 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { } } -/// Implementation if `MATCH_SAME_ARMS`. +/// Implementation of `MATCH_SAME_ARMS`. fn lint_match_arms(cx: &LateContext, expr: &Expr) { if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { let hash = |&(_, arm): &(usize, &Arm)| -> u64 { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index b7e79a06327..ab085606e29 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -55,7 +55,7 @@ declare_clippy_lint! { /// **Why is this bad?** Name shadowing can hurt readability, especially in /// large code bases, because it is easy to lose track of the active binding at /// any place in the code. This can be alleviated by either giving more specific -/// names to bindings ore introducing more scopes to contain the bindings. +/// names to bindings or introducing more scopes to contain the bindings. /// /// **Known problems:** This lint, as the other shadowing related lints, /// currently only catches very simple patterns. -- cgit 1.4.1-3-g733a5 From 2c2e7f4d5fa110e9ba9c9f0c48433fd580d45628 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 14 May 2018 04:34:11 -0400 Subject: Update for rust-lang/rust#50536 Fixes #2757 --- clippy_lints/src/needless_pass_by_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index d2836ffc2d6..39ed5cb424a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if let ty::TypeVariants::TyAdt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { let param_env = ty::ParamEnv::empty(); - if param_env.can_type_implement_copy(cx.tcx, ty, span).is_ok() { + if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { db.span_help(span, "consider marking this type as Copy"); } } -- cgit 1.4.1-3-g733a5 From c658fc8cbcd1f199edd445a49cb43139ebdc5f02 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 14 May 2018 11:29:22 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb596d81d4..52ffa50dc69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.200 +* Rustup to *rustc 1.27.0-nightly (9fae15374 2018-05-13)* + ## 0.0.199 * Rustup to *rustc 1.27.0-nightly (ff2ac35db 2018-05-12)* diff --git a/Cargo.toml b/Cargo.toml index a200a6710ee..328a057a737 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.199" +version = "0.0.200" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.199", path = "clippy_lints" } +clippy_lints = { version = "0.0.200", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 284f7e75c19..a77d6c6652d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.199" +version = "0.0.200" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index 9d1de5e2c79..664dbfe9e46 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.27.0-nightly (ff2ac35db 2018-05-12) +rustc 1.27.0-nightly (9fae15374 2018-05-13) binary: rustc -commit-hash: ff2ac35db93a80b2de5daa4f280bf1503d62c164 -commit-date: 2018-05-12 +commit-hash: 9fae1537462bb10fd17d07816efc17cfe4786806 +commit-date: 2018-05-13 host: x86_64-unknown-linux-gnu release: 1.27.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 1af2f20da64121a1e90a70ff635cba439bfea6e1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 14 May 2018 12:11:56 -0500 Subject: include contributing.md blurb from https://github.com/hashicorp/vault/blob/master/CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b62ccbd93d3..f4f243151ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,8 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lints! +**First**: if you're unsure or afraid of _anything_, just ask or submit the issue or pull request anyway. You won't be yelled at for giving it your best effort. The worst that can happen is that you'll be politely asked to change something. We appreciate any sort of contributions, and don't want a wall of rules to get in the way of that. + Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how you can contribute and how to get started. If you have any questions about contributing or need help with anything, feel free to ask questions on issues or -- cgit 1.4.1-3-g733a5 From cc9122777ba2e6904b0c2bfdae90e2a70673b4f7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 09:10:35 +0200 Subject: Add integration tests --- .travis.yml | 30 ++++++++++++++---------------- ci/base-tests.sh | 15 +++++++++++++++ ci/integration-tests.sh | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 ci/base-tests.sh create mode 100755 ci/integration-tests.sh diff --git a/.travis.yml b/.travis.yml index 077a17e0bac..77dc8fc4b19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,23 +29,21 @@ install: - nvm use stable - npm install remark-cli remark-lint +matrix: + include: + - env: INTEGRATION=rust-lang/cargo + - env: INTEGRATION=rust-lang-nursery/rand + allow_failures: + - env: INTEGRATION=rust-lang/cargo + - env: INTEGRATION=rust-lang-nursery/rand + script: - - PATH=$PATH:./node_modules/.bin - - remark -f *.md > /dev/null - - set -e - - cargo build --features debugging - - cargo test --features debugging - - mkdir -p ~/rust/cargo/bin - - cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy - - cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver - - PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy - - cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. - - cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. - - cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. - - cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../.. - - PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy - - cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../.. - - set +e + - | + if [ -z ${INTEGRATION} ]; then + ./ci/base-tests.sh + else + ./ci/integration-tests.sh + fi after_success: | #!/bin/bash diff --git a/ci/base-tests.sh b/ci/base-tests.sh new file mode 100644 index 00000000000..fc01ce05b3b --- /dev/null +++ b/ci/base-tests.sh @@ -0,0 +1,15 @@ +PATH=$PATH:./node_modules/.bin +remark -f *.md > /dev/null +set -e +cargo build --features debugging +cargo test --features debugging +mkdir -p ~/rust/cargo/bin +cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy +cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver +PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy +cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. +cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. +cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. +cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../.. +PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy +cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../.. diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh new file mode 100755 index 00000000000..c6c2a4a4d58 --- /dev/null +++ b/ci/integration-tests.sh @@ -0,0 +1,24 @@ +cargo install --force + +echo "Running integration test for crate ${INTEGRATION}" + +git clone https://github.com/${INTEGRATION}.git + +function check() { + cargo clippy --all &> clippy_output + cat clippy_output + ! cat clippy_output | grep -q "internal error" + if [[ $? != 0 ]]; then + return 1 + fi +} + +case ${INTEGRATION} in + rust-lang/cargo) + check + ;; + *) + cd ${INTEGRATION} + check + ;; +esac -- cgit 1.4.1-3-g733a5 From 4abd4a12b77952061c59c900ba40ddeec0915dbe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 09:17:55 +0200 Subject: Make sure base tests are executed, too :hammer: --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 77dc8fc4b19..60f1b6961c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ install: matrix: include: + - env: BASE_TESTS=true # runs the base tests - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand allow_failures: -- cgit 1.4.1-3-g733a5 From 9e6dc8d2d51907f3ddf26b01257830e3c3ccec64 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 18:55:21 +0200 Subject: Add exec bit, add set -ex to ci test files --- .github/deploy.sh | 3 +-- .travis.yml | 2 +- ci/base-tests.sh | 1 + ci/integration-tests.sh | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) mode change 100644 => 100755 ci/base-tests.sh diff --git a/.github/deploy.sh b/.github/deploy.sh index aa76f8f4e41..1d206e61167 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -1,8 +1,7 @@ #!/bin/bash # Automatically deploy on gh-pages -set -e -set -x +set -ex SOURCE_BRANCH="master" TARGET_BRANCH="gh-pages" diff --git a/.travis.yml b/.travis.yml index 60f1b6961c7..22dc2f572ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ script: after_success: | #!/bin/bash if [ $(uname) == Linux ]; then - set -e + set -ex ./.github/deploy.sh # trigger rebuild of the clippy-service, to keep it up to date with clippy itself if [ "$TRAVIS_PULL_REQUEST" == "false" ] && diff --git a/ci/base-tests.sh b/ci/base-tests.sh old mode 100644 new mode 100755 index fc01ce05b3b..e72bd155cec --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,3 +1,4 @@ +set -ex PATH=$PATH:./node_modules/.bin remark -f *.md > /dev/null set -e diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index c6c2a4a4d58..cfe5c1417b4 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,3 +1,4 @@ +set -ex cargo install --force echo "Running integration test for crate ${INTEGRATION}" -- cgit 1.4.1-3-g733a5 From dd0ed5dccc93c9395bf5d9490ac49f7764069de1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 19:21:57 +0200 Subject: Clone into checkout directory and cd into it --- ci/integration-tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index cfe5c1417b4..577fec96db7 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -3,7 +3,8 @@ cargo install --force echo "Running integration test for crate ${INTEGRATION}" -git clone https://github.com/${INTEGRATION}.git +git clone --depth=1 https://github.com/${INTEGRATION}.git checkout +cd checkout function check() { cargo clippy --all &> clippy_output @@ -19,7 +20,6 @@ case ${INTEGRATION} in check ;; *) - cd ${INTEGRATION} check ;; esac -- cgit 1.4.1-3-g733a5 From 3314c5fda7925fe14e1e64bbdcd064a8e6f90a11 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 19:54:30 +0200 Subject: No -e in integration_tests Because that makes the script stop early and not print any clippy error output. --- ci/base-tests.sh | 1 - ci/integration-tests.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index e72bd155cec..daec740212d 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,7 +1,6 @@ set -ex PATH=$PATH:./node_modules/.bin remark -f *.md > /dev/null -set -e cargo build --features debugging cargo test --features debugging mkdir -p ~/rust/cargo/bin diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 577fec96db7..61a3348f04f 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,4 +1,4 @@ -set -ex +set -x cargo install --force echo "Running integration test for crate ${INTEGRATION}" -- cgit 1.4.1-3-g733a5 From 569c138333ba41f66172f0c6ceb0d475e2623730 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 16 May 2018 20:08:46 +0200 Subject: s/internal error/internal compiler error/ --- ci/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 61a3348f04f..2fe15179b5f 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -9,7 +9,7 @@ cd checkout function check() { cargo clippy --all &> clippy_output cat clippy_output - ! cat clippy_output | grep -q "internal error" + ! cat clippy_output | grep -q "internal compiler error" if [[ $? != 0 ]]; then return 1 fi -- cgit 1.4.1-3-g733a5 From f0c823a85ec85b6d52a41beb79497a413fae0d45 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 17 May 2018 11:21:15 +0200 Subject: Rustup to 2018-05-16 --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 4 ++-- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/copies.rs | 4 ++-- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/let_if_seq.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/loops.rs | 7 +++---- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/matches.rs | 6 +++--- clippy_lints/src/needless_bool.rs | 4 ++-- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/no_effect.rs | 4 ++-- clippy_lints/src/panic.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 6 +++--- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/mod.rs | 6 +++--- 25 files changed, 40 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index bc345347dc6..b1cd096bc13 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -243,7 +243,7 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool { match expr.node { - ExprBlock(ref block) => is_relevant_block(tcx, tables, block), + ExprBlock(ref block, _) => is_relevant_block(tcx, tables, block), ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), ExprRet(None) | ExprBreak(_, None) => false, ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 2fd385228b2..5db217d8228 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { if let ExprClosure(_, _, eid, _, _) = expr.node { let body = self.cx.tcx.hir.body(eid); let ex = &body.value; - if matches!(ex.node, ExprBlock(_)) { + if matches!(ex.node, ExprBlock(_, _)) { self.found_block = Some(ex); return; } @@ -78,7 +78,7 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprIf(ref check, ref then, _) = expr.node { - if let ExprBlock(ref block) = check.node { + if let ExprBlock(ref block, _) = check.node { if block.rules == DefaultBlock { if block.stmts.is_empty() { if let Some(ref ex) = block.expr { diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 278decc2ebd..0c024d2bd05 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -99,7 +99,7 @@ fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool { fn get_path_name(expr: &Expr) -> Option { match expr.node { ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprBlock(ref b) => if b.stmts.is_empty() { + ExprBlock(ref b, _) => if b.stmts.is_empty() { b.expr.as_ref().and_then(|p| get_path_name(p)) } else { None diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 20a5e606dbf..240623475c8 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -101,7 +101,7 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) { fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { if_chain! { - if let ast::ExprKind::Block(ref block) = else_.node; + if let ast::ExprKind::Block(ref block, _) = else_.node; if let Some(else_) = expr_block(block); if !in_macro(else_.span); then { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index a078fde4790..3b178b02563 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -202,7 +202,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { pub fn expr(&mut self, e: &Expr) -> Option { match e.node { ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id), - ExprBlock(ref block) => self.block(block), + ExprBlock(ref block, _) => self.block(block), ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))), ExprArray(ref vec) => self.multi(vec).map(Constant::Vec), diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 1a8c0c28e8e..35c87beecef 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -238,7 +238,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { while let ExprIf(ref cond, ref then_expr, ref else_expr) = expr.node { conds.push(&**cond); - if let ExprBlock(ref block) = then_expr.node { + if let ExprBlock(ref block, _) = then_expr.node { blocks.push(block); } else { panic!("ExprIf node is not an ExprBlock"); @@ -253,7 +253,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { // final `else {..}` if !blocks.is_empty() { - if let ExprBlock(ref block) = expr.node { + if let ExprBlock(ref block, _) = expr.node { blocks.push(&**block); } } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index d67b3a010cf..a85b26f7a6a 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = { - else_block.is_none() && if let ExprBlock(ref then_block) = then_block.node { + else_block.is_none() && if let ExprBlock(ref then_block, _) = then_block.node { (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 } else { true diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index a2eea346743..c1ae714b115 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -160,7 +160,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { } Finite }, - ExprBlock(ref block) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), + ExprBlock(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), ExprCall(ref path, _) => if let ExprPath(ref qpath) = path.node { match_qpath(qpath, &paths::REPEAT).into() diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 15230ddf7e4..df7a1f29637 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -71,14 +71,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if let hir::StmtExpr(ref if_, _) = expr.node; if let hir::ExprIf(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); - if let hir::ExprBlock(ref then) = then.node; + if let hir::ExprBlock(ref then, _) = then.node; if let Some(value) = check_assign(cx, canonical_id, &*then); if !used_in_expr(cx, canonical_id, value); then { let span = stmt.span.to(if_.span); let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { - if let hir::ExprBlock(ref else_) = else_.node { + if let hir::ExprBlock(ref else_, _) = else_.node { if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) } else if let Some(ref default) = decl.init { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 5fe76112e52..01177c36be9 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -296,13 +296,13 @@ impl<'v, 't> RefVisitor<'v, 't> { match self.cx.tables.qpath_def(qpath, hir_id) { Def::TyAlias(def_id) | Def::Struct(def_id) => { let generics = self.cx.tcx.generics_of(def_id); - for _ in generics.regions.as_slice() { + for _ in generics.params.as_slice() { self.record(&None); } }, Def::Trait(def_id) => { let trait_def = self.cx.tcx.trait_def(def_id); - for _ in &self.cx.tcx.generics_of(trait_def.def_id).regions { + for _ in &self.cx.tcx.generics_of(trait_def.def_id).params { self.record(&None); } }, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a7ca0d27e17..ea5ef3be478 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -638,10 +638,9 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { combine_seq(e, arms) } }, - ExprBlock(ref b) => never_loop_block(b, main_loop_id), + ExprBlock(ref b, _) => never_loop_block(b, main_loop_id), ExprAgain(d) => { let id = d.target_id - .opt_id() .expect("target id can only be missing in the presence of compilation errors"); if id == *main_loop_id { NeverLoopResult::MayContinueMainLoop @@ -849,7 +848,7 @@ fn get_indexed_assignments<'a, 'tcx>( } } - if let Expr_::ExprBlock(ref b) = body.node { + if let Expr_::ExprBlock(ref b, _) = body.node { let Block { ref stmts, ref expr, @@ -1842,7 +1841,7 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, - ExprBlock(ref b) => match extract_first_expr(b) { + ExprBlock(ref b, _) => match extract_first_expr(b) { Some(subexpr) => is_simple_break_expr(subexpr), None => false, }, diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index fb8814d6d87..ca98d145b0c 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -120,7 +120,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { + hir::ExprBlock(ref block, _) => { match (&block.stmts[..], block.expr.as_ref()) { (&[], Some(inner_expr)) => { // If block only contains an expression, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 67971998477..be68e9b1a2f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -205,7 +205,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { let els = remove_blocks(&arms[1].body); let els = if is_unit_expr(els) { None - } else if let ExprBlock(_) = els.node { + } else if let ExprBlock(_, _) = els.node { // matches with blocks that contain statements are prettier as `if let + else` Some(els) } else { @@ -365,7 +365,7 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { if_chain! { if path_str == "Err"; if inner.iter().any(|pat| pat.node == PatKind::Wild); - if let ExprBlock(ref block) = arm.body.node; + if let ExprBlock(ref block, _) = arm.body.node; if is_panic_block(block); then { // `Err(_)` arm with `panic!` found @@ -534,7 +534,7 @@ fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { fn is_unit_expr(expr: &Expr) -> bool { match expr.node { ExprTup(ref v) if v.is_empty() => true, - ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true, + ExprBlock(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true, _ => false, } } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index e88d76656eb..a15ec77eb28 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { hint, ); }; - if let ExprBlock(ref then_block) = then_block.node { + if let ExprBlock(ref then_block, _) = then_block.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { span_lint( @@ -199,7 +199,7 @@ fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { - ExprBlock(ref block) => fetch_bool_block(block), + ExprBlock(ref block, _) => fetch_bool_block(block), ExprLit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { Expression::Bool(value) } else { diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 162cfc7e77f..2e483411ec6 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -173,7 +173,7 @@ impl EarlyLintPass for NeedlessContinue { /// fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { match else_expr.node { - ast::ExprKind::Block(ref else_block) => is_first_block_stmt_continue(else_block), + ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block), ast::ExprKind::Continue(_) => true, _ => false, } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 2765c1b2ee0..7b51b477201 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -75,7 +75,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } else { false }, - Expr_::ExprBlock(ref block) => { + Expr_::ExprBlock(ref block, _) => { block.stmts.is_empty() && if let Some(ref expr) = block.expr { has_no_effect(cx, expr) } else { @@ -169,7 +169,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { + Expr_::ExprBlock(ref block, _) => { if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| { match block.rules { diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index a6691db8678..bd44b8d9b03 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -34,7 +34,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprBlock(ref block) = expr.node; + if let ExprBlock(ref block, _) = expr.node; if let Some(ref ex) = block.expr; if let ExprCall(ref fun, ref params) = ex.node; if params.len() == 2; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 9478d874c69..fa6d2efd572 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -87,7 +87,7 @@ impl QuestionMarkPass { fn expression_returns_none(cx: &LateContext, expression: &Expr) -> bool { match expression.node { - ExprBlock(ref block) => { + ExprBlock(ref block, _) => { if let Some(return_expression) = Self::return_expression(block) { return Self::expression_returns_none(cx, &return_expression); } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index ae77dd7b4a8..e91944382c5 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -69,7 +69,7 @@ impl ReturnPass { } }, // a whole block? check it! - ast::ExprKind::Block(ref block) => { + ast::ExprKind::Block(ref block, _) => { self.check_block_return(cx, block); }, // an if/if let expr, check both exprs diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index ab085606e29..7bdeb0a666d 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -309,7 +309,7 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: ExprUnary(_, ref e) | ExprField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { check_expr(cx, e, bindings) }, - ExprBlock(ref block) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), + ExprBlock(ref block, _) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), // ExprCall // ExprMethodCall ExprArray(ref v) | ExprTup(ref v) => for e in v { @@ -364,7 +364,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), - ExprBlock(ref block) => { + ExprBlock(ref block, _) => { block.stmts.is_empty() && block .expr diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 823ed1be351..1625346852e 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -123,7 +123,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), - ExprBlock(ref block) => { + ExprBlock(ref block, _) => { block.stmts.is_empty() && block .expr diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 2f53b7a579e..d3a0d5b2c9e 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -356,7 +356,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = sub_pat; self.visit_expr(sub); }, - Expr_::ExprBlock(ref block) => { + Expr_::ExprBlock(ref block, _) => { let block_pat = self.next("block"); println!("Block(ref {}) = {};", block_pat, current); self.current = block_pat; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 780d8339c27..63e7757b12e 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), + (&ExprBlock(ref l, _), &ExprBlock(ref r, _)) => self.eq_block(l, r), (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { @@ -353,8 +353,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(l); self.hash_expr(r); }, - ExprBlock(ref b) => { - let c: fn(_) -> _ = ExprBlock; + ExprBlock(ref b, _) => { + let c: fn(_, _) -> _ = ExprBlock; c.hash(&mut self.s); self.hash_block(b); }, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ac38227c302..b5bb3fd2e21 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -250,7 +250,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}Yield", ind); print_expr(cx, sub, indent + 1); }, - hir::ExprBlock(_) => { + hir::ExprBlock(_, _) => { println!("{}Block", ind); }, hir::ExprAssign(ref lhs, ref rhs) => { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bc50eb2ac20..e656ea5cba2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -444,7 +444,7 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( ) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); let string = option.unwrap_or_default(); - if let ExprBlock(_) = expr.node { + if let ExprBlock(_, _) = expr.node { Cow::Owned(format!("{}{}", code, string)) } else if string.is_empty() { Cow::Owned(format!("{{ {} }}", code)) @@ -529,7 +529,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI node: ImplItemKind::Method(_, eid), .. }) => match cx.tcx.hir.body(eid).value.node { - ExprBlock(ref block) => Some(block), + ExprBlock(ref block, _) => Some(block), _ => None, }, _ => None, @@ -934,7 +934,7 @@ pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return /// themselves. pub fn remove_blocks(expr: &Expr) -> &Expr { - if let ExprBlock(ref block) = expr.node { + if let ExprBlock(ref block, _) = expr.node { if block.stmts.is_empty() { if let Some(ref expr) = block.expr { remove_blocks(expr) -- cgit 1.4.1-3-g733a5 From c0bf3a46968e9f19e5f3aad563d03a2d222a320b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 17 May 2018 11:40:12 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52ffa50dc69..68995649add 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.201 +* Rustup to *rustc 1.27.0-nightly (2f2a11dfc 2018-05-16)* + ## 0.0.200 * Rustup to *rustc 1.27.0-nightly (9fae15374 2018-05-13)* diff --git a/Cargo.toml b/Cargo.toml index 328a057a737..09e90d336fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.200" +version = "0.0.201" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.200", path = "clippy_lints" } +clippy_lints = { version = "0.0.201", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a77d6c6652d..d4ac329afe7 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.200" +version = "0.0.201" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index 664dbfe9e46..b983ba61ed0 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.27.0-nightly (9fae15374 2018-05-13) +rustc 1.27.0-nightly (2f2a11dfc 2018-05-16) binary: rustc -commit-hash: 9fae1537462bb10fd17d07816efc17cfe4786806 -commit-date: 2018-05-13 +commit-hash: 2f2a11dfc436fc0f401b595f22ed043c46dbebe7 +commit-date: 2018-05-16 host: x86_64-unknown-linux-gnu release: 1.27.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 21e783d3b605354ec508b3395e7d3429b4b24075 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 12 May 2018 13:41:03 +0200 Subject: Add run-pass tests for SpanlessEq/SpanlessHash ICE --- tests/run-pass/ice-1782.rs | 17 +++++++++++++++++ tests/run-pass/ice-2499.rs | 24 ++++++++++++++++++++++++ tests/run-pass/ice-2594.rs | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/run-pass/ice-1782.rs create mode 100644 tests/run-pass/ice-2499.rs create mode 100644 tests/run-pass/ice-2594.rs diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs new file mode 100644 index 00000000000..fcd3e7cf530 --- /dev/null +++ b/tests/run-pass/ice-1782.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, unused_variables)] + +/// Should not trigger an ICE in `SpanlessEq` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/1782 + +use std::{mem, ptr}; + +fn spanless_eq_ice() { + let txt = "something"; + match txt { + "something" => unsafe { ptr::write(ptr::null_mut() as *mut u32, mem::transmute::<[u8; 4], _>([0, 0, 0, 255])) }, + _ => unsafe { ptr::write(ptr::null_mut() as *mut u32, mem::transmute::<[u8; 4], _>([13, 246, 24, 255])) }, + } +} + +fn main() {} diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs new file mode 100644 index 00000000000..d012d548f20 --- /dev/null +++ b/tests/run-pass/ice-2499.rs @@ -0,0 +1,24 @@ +#![allow(dead_code)] + +/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2499 + +fn f(s: &[u8]) -> bool { + let t = s[0] as char; + + match t { + 'E' | 'W' => {} + 'T' => if &s[0..(0 + 4)] != &['0' as u8; 4] { + return false; + } else { + return true; + }, + _ => { + return false; + } + } + true +} + +fn main() {} diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs new file mode 100644 index 00000000000..7cd30b6d946 --- /dev/null +++ b/tests/run-pass/ice-2594.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, unused_variables)] + +/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2594 + +fn spanless_hash_ice() { + let txt = "something"; + let empty_header: [u8; 1] = [1; 1]; + + match txt { + "something" => { + let mut headers = [empty_header; 1]; + } + "" => (), + _ => (), + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 6eb07cc5b699a28f479012f5271ef9da2f60a6a3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 13 May 2018 13:16:31 +0200 Subject: Fix ICE for issue 2594 --- clippy_lints/src/array_indexing.rs | 6 +++--- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/consts.rs | 10 +++++----- clippy_lints/src/copies.rs | 4 ++-- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/loops.rs | 6 +++--- clippy_lints/src/matches.rs | 6 +++--- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/minmax.rs | 6 +++--- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/hir_utils.rs | 13 ++++++++++--- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/zero_div_zero.rs | 4 ++-- 17 files changed, 42 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index b51a9209c4c..b5a42f03e9a 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { let size = size.assert_usize(cx.tcx).unwrap().into(); // Index is a constant uint - if let Some((Constant::Int(const_index), _)) = constant(cx, index) { + if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) { if size <= const_index { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); } @@ -101,14 +101,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { /// Returns an option containing a tuple with the start and end (exclusive) of /// the range. fn to_const_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, range: Range, array_size: u128) -> Option<(u128, u128)> { - let s = range.start.map(|expr| constant(cx, expr).map(|(c, _)| c)); + let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let start = match s { Some(Some(Constant::Int(x))) => x, Some(_) => return None, None => 0, }; - let e = range.end.map(|expr| constant(cx, expr).map(|(c, _)| c)); + let e = range.end.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let end = match e { Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { x + 1 diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index b6adbf1bd86..4f38fb92831 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -301,7 +301,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str } fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { - match constant(cx, lit)?.0 { + match constant(cx, cx.tables, lit)?.0 { Constant::Int(n) => Some(n), _ => None, } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 3b178b02563..bc57be94cdb 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -163,10 +163,10 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { } } -pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { +pub fn constant<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { tcx: lcx.tcx, - tables: lcx.tables, + tables, param_env: lcx.param_env, needed_resolution: false, substs: lcx.tcx.intern_substs(&[]), @@ -174,12 +174,12 @@ pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } -pub fn constant_simple(lcx: &LateContext, e: &Expr) -> Option { - constant(lcx, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) +pub fn constant_simple<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option { + constant(lcx, tables, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables` -pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'cc ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> { +pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> { ConstEvalLateContext { tcx: lcx.tcx, tables, diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 35c87beecef..80601fa92fa 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -151,7 +151,7 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 { - let mut h = SpanlessHash::new(cx); + let mut h = SpanlessHash::new(cx, cx.tables); h.hash_expr(expr); h.finish() }; @@ -174,7 +174,7 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { fn lint_match_arms(cx: &LateContext, expr: &Expr) { if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { let hash = |&(_, arm): &(usize, &Arm)| -> u64 { - let mut h = SpanlessHash::new(cx); + let mut h = SpanlessHash::new(cx, cx.tables); h.hash_expr(&arm.body); h.finish() }; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 9cd4f3ada3b..ae6e078ddae 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { } fn check(cx: &LateContext, e: &Expr, span: Span) { - if let Some(Constant::Int(v)) = constant_simple(cx, e) { + if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { if v == 0 { span_lint( cx, diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index c6b4f9f1af3..24e5f823a35 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { #[allow(cast_possible_wrap)] fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(Constant::Int(v)) = constant_simple(cx, e) { + if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { let check = match cx.tables.expr_ty(e).sty { ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity), ty::TyUint(uty) => clip(cx.tcx, !0, uty), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ea5ef3be478..b0f39937668 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1120,8 +1120,8 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx }) = higher::range(cx, arg) { // ...and both sides are compile-time constant integers... - if let Some((start_idx, _)) = constant(cx, start) { - if let Some((end_idx, _)) = constant(cx, end) { + if let Some((start_idx, _)) = constant(cx, cx.tables, start) { + if let Some((end_idx, _)) = constant(cx, cx.tables, end) { // ...and the start index is greater than the end index, // this loop will never run. This is often confusing for developers // who think that this will iterate from the larger value to the @@ -2146,7 +2146,7 @@ fn path_name(e: &Expr) -> Option { } fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, block: &'tcx Block, expr: &'tcx Expr) { - if constant(cx, cond).is_some() { + if constant(cx, cx.tables, cond).is_some() { // A pure constant condition (e.g. while false) is not linted. return; } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index be68e9b1a2f..b593c330503 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -470,8 +470,8 @@ fn all_ranges<'a, 'tcx>( [].iter() }.filter_map(|pat| { if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node { - let lhs = constant(cx, lhs)?.0; - let rhs = constant(cx, rhs)?.0; + let lhs = constant(cx, cx.tables, lhs)?.0; + let rhs = constant(cx, cx.tables, rhs)?.0; let rhs = match *range_end { RangeEnd::Included => Bound::Included(rhs), RangeEnd::Excluded => Bound::Excluded(rhs), @@ -480,7 +480,7 @@ fn all_ranges<'a, 'tcx>( } if let PatKind::Lit(ref value) = pat.node { - let value = constant(cx, value)?.0; + let value = constant(cx, cx.tables, value)?.0; return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index c7702e6bced..4c80fdb01c5 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1751,7 +1751,7 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & /// lint for length-1 `str`s for methods in `PATTERN_METHODS` fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { - if let Some((Constant::Str(r), _)) = constant(cx, arg) { + if let Some((Constant::Str(r), _)) = constant(cx, cx.tables, arg) { if r.len() == 1 { let c = r.chars().next().unwrap(); let snip = snippet(cx, expr.span, ".."); diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 8c19f627f53..289c5c77ff3 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -81,14 +81,14 @@ fn fetch_const<'a>(cx: &LateContext, args: &'a [Expr], m: MinMax) -> Option<(Min if args.len() != 2 { return None; } - if let Some(c) = constant_simple(cx, &args[0]) { - if constant_simple(cx, &args[1]).is_none() { + if let Some(c) = constant_simple(cx, cx.tables, &args[0]) { + if constant_simple(cx, cx.tables, &args[1]).is_none() { // otherwise ignore Some((m, c, &args[1])) } else { None } - } else if let Some(c) = constant_simple(cx, &args[1]) { + } else if let Some(c) = constant_simple(cx, cx.tables, &args[1]) { Some((m, c, &args[0])) } else { None diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 797a871d72b..0ecd0ac1895 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -446,7 +446,7 @@ fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { } fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { - if let Some((_, res)) = constant(cx, expr) { + if let Some((_, res)) = constant(cx, cx.tables, expr) { res } else { false @@ -454,7 +454,7 @@ fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> } fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { - match constant(cx, expr) { + match constant(cx, cx.tables, expr) { Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), _ => false, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index bc1ffc57003..5d13b3e1ae6 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { use consts::{constant, Constant}; - if let Some((Constant::Int(0), _)) = constant(cx, &args[1]) { + if let Some((Constant::Int(0), _)) = constant(cx, cx.tables, &args[1]) { span_lint( cx, ITERATOR_STEP_BY_ZERO, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 20ccc6ccfcc..522c2b9ac29 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -138,7 +138,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { } fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option { - constant(cx, e).and_then(|(c, _)| match c { + constant(cx, cx.tables, e).and_then(|(c, _)| match c { Constant::Str(s) => Some(s), _ => None, }) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ffc49722aad..168086d574a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1341,7 +1341,7 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - let ty = cx.tables.expr_ty(expr); - let cv = constant(cx, expr)?.0; + let cv = constant(cx, cx.tables, expr)?.0; let which = match (&ty.sty, cv) { (&ty::TyBool, Constant::Bool(false)) | @@ -1526,7 +1526,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( } fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option { - let val = constant(cx, expr)?.0; + let val = constant(cx, cx.tables, expr)?.0; if let Constant::Int(const_int) = val { match cx.tables.expr_ty(expr).sty { ty::TyInt(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 63e7757b12e..faf61f4ed9c 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,6 +1,7 @@ use consts::{constant_simple, constant_context}; use rustc::lint::*; use rustc::hir::*; +use rustc::ty::{TypeckTables}; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; use syntax::ast::Name; @@ -16,6 +17,7 @@ use utils::differing_macro_contexts; pub struct SpanlessEq<'a, 'tcx: 'a> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'a, 'tcx>, + tables: &'a TypeckTables<'tcx>, /// If is true, never consider as equal expressions containing function /// calls. ignore_fn: bool, @@ -25,6 +27,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { Self { cx, + tables: cx.tables, ignore_fn: false, } } @@ -32,6 +35,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn ignore_fn(self) -> Self { Self { cx: self.cx, + tables: self.cx.tables, ignore_fn: true, } } @@ -64,7 +68,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { return false; } - if let (Some(l), Some(r)) = (constant_simple(self.cx, left), constant_simple(self.cx, right)) { + if let (Some(l), Some(r)) = (constant_simple(self.cx, self.tables, left), constant_simple(self.cx, self.tables, right)) { if l == r { return true; } @@ -288,13 +292,15 @@ where pub struct SpanlessHash<'a, 'tcx: 'a> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'a, 'tcx>, + tables: &'a TypeckTables<'tcx>, s: DefaultHasher, } impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { - pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + pub fn new(cx: &'a LateContext<'a, 'tcx>, tables: &'a TypeckTables<'tcx>) -> Self { Self { cx, + tables, s: DefaultHasher::new(), } } @@ -317,7 +323,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { #[allow(many_single_char_names)] pub fn hash_expr(&mut self, e: &Expr) { - if let Some(e) = constant_simple(self.cx, e) { + if let Some(e) = constant_simple(self.cx, self.tables, e) { return e.hash(&mut self.s); } @@ -461,6 +467,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprRepeat; c.hash(&mut self.s); self.hash_expr(e); + self.tables = self.cx.tcx.body_tables(l_id); self.hash_expr(&self.cx.tcx.hir.body(l_id).value); }, ExprRet(ref e) => { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index d5ed4cb712d..6aff0ebc9f7 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { - if constant(cx, len).is_some() { + if constant(cx, cx.tables, len).is_some() { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")) } else { return; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 16c12702c6c..fc28815c70e 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -37,8 +37,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - if let Some(lhs_value) = constant_simple(cx, left); - if let Some(rhs_value) = constant_simple(cx, right); + if let Some(lhs_value) = constant_simple(cx, cx.tables, left); + if let Some(rhs_value) = constant_simple(cx, cx.tables, right); if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value; if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value; then { -- cgit 1.4.1-3-g733a5 From ed885dc2b320e26f47b15ef50f442e4e40cce954 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 17 May 2018 20:17:21 +0200 Subject: Fix ICE for issues 2767, 2499, 1782 --- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 43 +++++++++++++++++++++++------------ tests/run-pass/ice-2499.rs | 4 ++-- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 06d0cf1d09e..1ccc5708185 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> DoubleComparisonPass { } _ => return, }; - let spanless_eq = SpanlessEq::new(cx).ignore_fn(); + let mut spanless_eq = SpanlessEq::new(cx).ignore_fn(); if !(spanless_eq.eq_expr(&llhs, &rlhs) && spanless_eq.eq_expr(&lrhs, &rrhs)) { return; } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index faf61f4ed9c..7d9945cdddc 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } /// Check whether two statements are the same. - pub fn eq_stmt(&self, left: &Stmt, right: &Stmt) -> bool { + pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { match (&left.node, &right.node) { (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { @@ -58,12 +58,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } /// Check whether two blocks are the same. - pub fn eq_block(&self, left: &Block, right: &Block) -> bool { + pub fn eq_block(&mut self, left: &Block, right: &Block) -> bool { over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + pub fn eq_expr(&mut self, left: &Expr, right: &Expr) -> bool { if self.ignore_fn && differing_macro_contexts(left.span, right.span) { return false; } @@ -144,20 +144,20 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_exprs(&self, left: &P<[Expr]>, right: &P<[Expr]>) -> bool { + fn eq_exprs(&mut self, left: &P<[Expr]>, right: &P<[Expr]>) -> bool { over(left, right, |l, r| self.eq_expr(l, r)) } - fn eq_field(&self, left: &Field, right: &Field) -> bool { + fn eq_field(&mut self, left: &Field, right: &Field) -> bool { left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr) } - fn eq_lifetime(&self, left: &Lifetime, right: &Lifetime) -> bool { + fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool { left.name == right.name } /// Check whether two patterns are the same. - pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool { + pub fn eq_pat(&mut self, left: &Pat, right: &Pat) -> bool { match (&left.node, &right.node) { (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { @@ -184,7 +184,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_qpath(&self, left: &QPath, right: &QPath) -> bool { + fn eq_qpath(&mut self, left: &QPath, right: &QPath) -> bool { match (left, right) { (&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => { both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath) @@ -196,12 +196,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_path(&self, left: &Path, right: &Path) -> bool { + fn eq_path(&mut self, left: &Path, right: &Path) -> bool { left.is_global() == right.is_global() && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) } - fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { + fn eq_path_parameters(&mut self, left: &PathParameters, right: &PathParameters) -> bool { if !(left.parenthesized || right.parenthesized) { over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) @@ -218,7 +218,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_path_segment(&self, left: &PathSegment, right: &PathSegment) -> bool { + fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene if left.name.as_str() != right.name.as_str() { @@ -231,12 +231,23 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { + fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyArray(ref lt, ll_id), &TyArray(ref rt, rl_id)) => { - self.eq_ty(lt, rt) - && self.eq_expr(&self.cx.tcx.hir.body(ll_id).value, &self.cx.tcx.hir.body(rl_id).value) + let full_table = self.tables; + + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id)); + self.tables = self.cx.tcx.body_tables(ll_id); + let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id).value); + + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id)); + self.tables = self.cx.tcx.body_tables(rl_id); + let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id).value); + + let eq_ty = self.eq_ty(lt, rt); + self.tables = full_table; + eq_ty && ll == rl }, (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { @@ -249,7 +260,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_type_binding(&self, left: &TypeBinding, right: &TypeBinding) -> bool { + fn eq_type_binding(&mut self, left: &TypeBinding, right: &TypeBinding) -> bool { left.name == right.name && self.eq_ty(&left.ty, &right.ty) } } @@ -467,8 +478,10 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprRepeat; c.hash(&mut self.s); self.hash_expr(e); + let full_table = self.tables; self.tables = self.cx.tcx.body_tables(l_id); self.hash_expr(&self.cx.tcx.hir.body(l_id).value); + self.tables = full_table; }, ExprRet(ref e) => { let c: fn(_) -> _ = ExprRet; diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index d012d548f20..01deb7abfc1 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +#![allow(dead_code, char_lit_as_u8, needless_bool)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` /// @@ -9,7 +9,7 @@ fn f(s: &[u8]) -> bool { match t { 'E' | 'W' => {} - 'T' => if &s[0..(0 + 4)] != &['0' as u8; 4] { + 'T' => if s[0..4] != ['0' as u8; 4] { return false; } else { return true; -- cgit 1.4.1-3-g733a5 From 8509a0f83983484f94e403c4b54281dbc0d9c30b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 17 May 2018 21:40:04 +0200 Subject: Add more crates for integration tests --- .travis.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.travis.yml b/.travis.yml index 22dc2f572ae..0ae91b5efb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,9 +34,27 @@ matrix: - env: BASE_TESTS=true # runs the base tests - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand + - env: INTEGRATION=rust-lang-nursery/stdsimd + - env: INTEGRATION=rust-lang-nursery/rustfmt + - env: INTEGRATION=rust-lang-nursery/futures-rs + - env: INTEGRATION=rust-lang-nursery/failure + - env: INTEGRATION=rust-lang-nursery/log + - env: INTEGRATION=rust-lang-nursery/chalk + - env: INTEGRATION=chronotope/chrono + - env: INTEGRATION=serde-rs/serde + - env: INTEGRATION=Geal/nom allow_failures: - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand + - env: INTEGRATION=rust-lang-nursery/stdsimd + - env: INTEGRATION=rust-lang-nursery/rustfmt + - env: INTEGRATION=rust-lang-nursery/futures-rs + - env: INTEGRATION=rust-lang-nursery/failure + - env: INTEGRATION=rust-lang-nursery/log + - env: INTEGRATION=rust-lang-nursery/chalk + - env: INTEGRATION=chronotope/chrono + - env: INTEGRATION=serde-rs/serde + - env: INTEGRATION=Geal/nom script: - | -- cgit 1.4.1-3-g733a5 From b4482ce3814eb2d4cbd45bee6ded40f31e03117d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 17 May 2018 21:40:23 +0200 Subject: Make build output cleaner --- ci/base-tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index daec740212d..37c13fe069e 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -13,3 +13,4 @@ cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy - cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../.. PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../.. +set +x -- cgit 1.4.1-3-g733a5 From 4a460ab6c3d04a9dafb8b4b7b25436df0770d090 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 17 May 2018 22:06:25 +0200 Subject: Use full backtrace --- ci/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 2fe15179b5f..e786ac06104 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -7,7 +7,7 @@ git clone --depth=1 https://github.com/${INTEGRATION}.git checkout cd checkout function check() { - cargo clippy --all &> clippy_output + RUST_BACKTRACE=full cargo clippy --all &> clippy_output cat clippy_output ! cat clippy_output | grep -q "internal compiler error" if [[ $? != 0 ]]; then -- cgit 1.4.1-3-g733a5 From ee96249d32be40cc4924e54415876705afc79c22 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 18 May 2018 18:43:21 +0200 Subject: Add hyper to integration tests Because it was failing before: https://github.com/rust-lang/rust/issues/49643 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0ae91b5efb6..f81fd9f41c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,7 @@ matrix: - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom + - env: INTEGRATION=hyperium/hyper allow_failures: - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand @@ -55,6 +56,7 @@ matrix: - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom + - env: INTEGRATION=hyperium/hyper script: - | -- cgit 1.4.1-3-g733a5 From df1b7c5f198b569b7da37511b635994758380320 Mon Sep 17 00:00:00 2001 From: utam0k Date: Sat, 19 May 2018 14:29:20 +0900 Subject: Rename trans to codegen --- src/driver.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 4e3852d416a..2be29df5a54 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -9,11 +9,11 @@ extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_plugin; -extern crate rustc_trans_utils; +extern crate rustc_codegen_utils; extern crate syntax; use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use rustc_trans_utils::trans_crate::TransCrate; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::session::{config, Session}; use rustc::session::config::{ErrorOutputType, Input}; use std::path::PathBuf; @@ -60,7 +60,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { } fn late_callback( &mut self, - trans_crate: &TransCrate, + trans_crate: &CodegenBackend, matches: &getopts::Matches, sess: &Session, crate_stores: &rustc::middle::cstore::CrateStore, -- cgit 1.4.1-3-g733a5 From ebe0b0eed596243a2839867363cb31d93f0b9754 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 19 May 2018 13:01:26 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68995649add..99460d21218 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.202 +* Rustup to *rustc 1.28.0-nightly (952f344cd 2018-05-18)* + ## 0.0.201 * Rustup to *rustc 1.27.0-nightly (2f2a11dfc 2018-05-16)* diff --git a/Cargo.toml b/Cargo.toml index 09e90d336fc..71d4ec04ab1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.201" +version = "0.0.202" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.201", path = "clippy_lints" } +clippy_lints = { version = "0.0.202", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d4ac329afe7..4eb34910a40 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.201" +version = "0.0.202" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index b983ba61ed0..e56c97afb12 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.27.0-nightly (2f2a11dfc 2018-05-16) +rustc 1.28.0-nightly (952f344cd 2018-05-18) binary: rustc -commit-hash: 2f2a11dfc436fc0f401b595f22ed043c46dbebe7 -commit-date: 2018-05-16 +commit-hash: 952f344cdc0bca58d9f6c54dcfbae0890246e886 +commit-date: 2018-05-18 host: x86_64-unknown-linux-gnu -release: 1.27.0-nightly +release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From e0df4ccfc5ba76347cc3eb427bbe5d932f61ecee Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 19 May 2018 14:04:57 +0200 Subject: Use the new scoped tool attributes --- CONTRIBUTING.md | 6 +---- clippy_lints/src/lib.rs | 1 - clippy_lints/src/utils/author.rs | 16 ++++------- clippy_lints/src/utils/inspector.rs | 4 +-- clippy_lints/src/utils/mod.rs | 28 +++++++++++-------- tests/ui/author.rs | 4 +-- tests/ui/author/for_loop.rs | 4 +-- tests/ui/author/matches.rs | 4 +-- tests/ui/cyclomatic_complexity.rs | 42 ++++++++++++++--------------- tests/ui/cyclomatic_complexity_attr_used.rs | 4 +-- tests/ui/excessive_precision.rs | 2 +- tests/ui/for_loop.rs | 2 +- tests/ui/trailing_zeros.rs | 4 +-- tests/ui/trailing_zeros.stderr | 2 +- 14 files changed, 59 insertions(+), 64 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f4f243151ee..09f4f34b98d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,12 +80,8 @@ First, create a new UI test file in the `tests/ui/` directory with the pattern y ```rust // ./tests/ui/my_lint.rs - -// The custom_attribute needs to be enabled for the author lint to work -#![feature(plugin, custom_attribute)] - fn main() { - #[clippy(author)] + #[clippy::author] let arr: [i32; 1] = [7]; // Replace line with the code you want to match } ``` diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 821093735df..7864e90c196 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,7 +1,6 @@ // error-pattern:cargo-clippy #![feature(box_syntax)] -#![feature(custom_attribute)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index d3a0d5b2c9e..dd43a0d2177 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -7,8 +7,9 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::{Expr, Expr_, QPath, Ty_, Pat, PatKind, BindingAnnotation, StmtSemi, StmtExpr, StmtDecl, Decl_, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use syntax::ast::{self, Attribute, LitKind, DUMMY_NODE_ID}; +use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; use std::collections::HashMap; +use utils::get_attr; /// **What it does:** Generates clippy code that detects the offending pattern /// @@ -17,10 +18,10 @@ use std::collections::HashMap; /// // ./tests/ui/my_lint.rs /// fn foo() { /// // detect the following pattern -/// #[clippy(author)] +/// #[clippy::author] /// if x == 42 { /// // but ignore everything from here on -/// #![clippy(author = "ignore")] +/// #![clippy::author = "ignore"] /// } /// } /// ``` @@ -633,14 +634,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } fn has_attr(attrs: &[Attribute]) -> bool { - attrs.iter().any(|attr| { - attr.check_name("clippy") && attr.meta_item_list().map_or(false, |list| { - list.len() == 1 && match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.name() == "author", - ast::NestedMetaItemKind::Literal(_) => false, - } - }) - }) + get_attr(attrs, "author").count() > 0 } fn desugaring_name(des: hir::MatchSource) -> String { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b5bb3fd2e21..10a9a3a03c1 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::print; use syntax::ast::Attribute; -use syntax::attr; +use utils::get_attr; /// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` /// attribute @@ -136,7 +136,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn has_attr(attrs: &[Attribute]) -> bool { - attr::contains_name(attrs, "clippy_dump") + get_attr(attrs, "dump").count() > 0 } fn print_decl(cx: &LateContext, decl: &hir::Decl) { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e656ea5cba2..d5c7796fac6 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -735,20 +735,26 @@ impl LimitStack { } } -fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { - for attr in attrs { - if attr.is_sugared_doc { - continue; +pub fn get_attr<'a>(attrs: &'a [ast::Attribute], name: &'static str) -> impl Iterator { + attrs.iter().filter_map(move |attr| { + if attr.path.segments.len() == 2 && attr.path.segments[0].ident.to_string() == "clippy" && attr.path.segments[1].ident.to_string() == name { + Some(attr) + } else { + None } + }) +} + +fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { + for attr in get_attr(attrs, name) { if let Some(ref value) = attr.value_str() { - if attr.name() == name { - if let Ok(value) = FromStr::from_str(&value.as_str()) { - attr::mark_used(attr); - f(value) - } else { - sess.span_err(attr.span, "not a number"); - } + if let Ok(value) = FromStr::from_str(&value.as_str()) { + f(value) + } else { + sess.span_err(attr.span, "not a number"); } + } else { + sess.span_err(attr.span, "bad clippy attribute"); } } } diff --git a/tests/ui/author.rs b/tests/ui/author.rs index 3a819872bc5..eec26bcce3c 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -1,7 +1,7 @@ -#![feature(plugin, custom_attribute)] +#![feature(tool_attributes)] fn main() { - #[clippy(author)] + #[clippy::author] let x: char = 0x45 as char; } diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index 657bf51bf80..5faf440676d 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -1,7 +1,7 @@ -#![feature(custom_attribute)] +#![feature(tool_attributes)] fn main() { - #[clippy(author)] + #[clippy::author] for y in 0..10 { let z = y; } diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs index f426302da09..e6bf229103f 100644 --- a/tests/ui/author/matches.rs +++ b/tests/ui/author/matches.rs @@ -1,7 +1,7 @@ -#![feature(custom_attribute)] +#![feature(tool_attributes)] fn main() { - #[clippy(author)] + #[clippy::author] let a = match 42 { 16 => 5, 17 => { diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 1afae69c186..3214505ba1e 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,4 +1,4 @@ -#![feature(custom_attribute)] +#![feature(tool_attributes)] #![allow(clippy)] #![warn(cyclomatic_complexity)] @@ -88,7 +88,7 @@ fn main() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn kaboom() { let n = 0; 'a: for i in 0..20 { @@ -134,17 +134,17 @@ fn bloo() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn lots_of_short_circuits() -> bool { true && false && true && false && true && false && true } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn lots_of_short_circuits2() -> bool { true || false || true || false || true || false || true } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn baa() { let x = || match 99 { 0 => 0, @@ -162,7 +162,7 @@ fn baa() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn bar() { match 99 { 0 => println!("hi"), @@ -171,7 +171,7 @@ fn bar() { } #[test] -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] /// Tests are usually complex but simple at the same time. `cyclomatic_complexity` used to give /// lots of false-positives in tests. fn dont_warn_on_tests() { @@ -181,7 +181,7 @@ fn dont_warn_on_tests() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barr() { match 99 { 0 => println!("hi"), @@ -191,7 +191,7 @@ fn barr() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barr2() { match 99 { 0 => println!("hi"), @@ -207,7 +207,7 @@ fn barr2() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barrr() { match 99 { 0 => println!("hi"), @@ -217,7 +217,7 @@ fn barrr() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barrr2() { match 99 { 0 => println!("hi"), @@ -233,7 +233,7 @@ fn barrr2() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barrrr() { match 99 { 0 => println!("hi"), @@ -243,7 +243,7 @@ fn barrrr() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn barrrr2() { match 99 { 0 => println!("hi"), @@ -259,7 +259,7 @@ fn barrrr2() { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn cake() { if 4 == 5 { println!("yea"); @@ -270,7 +270,7 @@ fn cake() { } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] pub fn read_file(input_path: &str) -> String { use std::fs::File; use std::io::{Read, Write}; @@ -301,7 +301,7 @@ pub fn read_file(input_path: &str) -> String { enum Void {} -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn void(void: Void) { if true { match void { @@ -309,13 +309,13 @@ fn void(void: Void) { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn mcarton_sees_all() { panic!("meh"); panic!("möh"); } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn try() -> Result { match 5 { 5 => Ok(5), @@ -323,7 +323,7 @@ fn try() -> Result { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn try_again() -> Result { let _ = try!(Ok(42)); let _ = try!(Ok(43)); @@ -339,7 +339,7 @@ fn try_again() -> Result { } } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn early() -> Result { return Ok(5); return Ok(5); @@ -352,7 +352,7 @@ fn early() -> Result { return Ok(5); } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn early_ret() -> i32 { let a = if true { 42 } else { return 0; }; let a = if a < 99 { 42 } else { return 0; }; diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index f3895c7e3ab..50b19f9d7ba 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,4 +1,4 @@ -#![feature(custom_attribute)] +#![feature(tool_attributes)] #![warn(cyclomatic_complexity)] #![warn(unused)] @@ -7,7 +7,7 @@ fn main() { kaboom(); } -#[cyclomatic_complexity = "0"] +#[clippy::cyclomatic_complexity = "0"] fn kaboom() { if 42 == 43 { panic!(); diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 25b6555715f..c17639aaf04 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,4 +1,4 @@ -#![feature(custom_attribute)] + #![warn(excessive_precision)] #![allow(print_literal)] diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index ce776d4d91c..e28a8f1e178 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(custom_attribute)] + use std::collections::*; diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index d915a0bed09..5494e780628 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,10 +1,10 @@ -#![feature(custom_attribute, stmt_expr_attributes)] +#![feature(stmt_expr_attributes, tool_attributes)] #![allow(unused_parens)] fn main() { let x: i32 = 42; - let _ = #[clippy(author)] (x & 0b1111 == 0); // suggest trailing_zeros + let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros let _ = x & 0b1_1111 == 0; // suggest trailing_zeros let _ = x & 0b1_1010 == 0; // do not lint let _ = x & 1 == 0; // do not lint diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 91e4d59da98..47b46be9ba8 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -1,7 +1,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:7:31 | -7 | let _ = #[clippy(author)] (x & 0b1111 == 0); // suggest trailing_zeros +7 | let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` | = note: `-D verbose-bit-mask` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From cd03c6ee2ea84efe14f3ca16cec89649a9dcd429 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 19 May 2018 17:02:08 +0200 Subject: Add rls to integration tests --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0ae91b5efb6..1dfb8e494d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ matrix: - env: INTEGRATION=rust-lang-nursery/failure - env: INTEGRATION=rust-lang-nursery/log - env: INTEGRATION=rust-lang-nursery/chalk + - env: INTEGRATION=rust-lang-nursery/rls - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom @@ -52,6 +53,7 @@ matrix: - env: INTEGRATION=rust-lang-nursery/failure - env: INTEGRATION=rust-lang-nursery/log - env: INTEGRATION=rust-lang-nursery/chalk + - env: INTEGRATION=rust-lang-nursery/rls - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom -- cgit 1.4.1-3-g733a5 From b60ffa780d0c18c754b03ad8dd745fc3e19f11d6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 19 May 2018 18:49:57 +0200 Subject: Stop compilation after linting --- src/driver.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/driver.rs b/src/driver.rs index 2be29df5a54..61afb6ea2f4 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -118,6 +118,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { } old(state); }); + + control.compilation_done.stop = Compilation::Stop; } control -- cgit 1.4.1-3-g733a5 From 7b715583d459597b6565184701327b9d6636c522 Mon Sep 17 00:00:00 2001 From: Cyril Plisko Date: Sun, 20 May 2018 09:20:01 +0300 Subject: rustup to nightly 2018-05-19 clippy_lints does not compile: non-primitive cast: `rustc_target::abi::Size` as `usize` Fixes #2780 --- clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index bc57be94cdb..841c6171740 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -432,7 +432,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' .interpret_interner .get_alloc(ptr.alloc_id) .unwrap(); - let offset = ptr.offset as usize; + let offset = ptr.offset.bytes() as usize; let n = n as usize; String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str) }, -- cgit 1.4.1-3-g733a5 From 0bf96259f1650286365f10fb316ef39755466b4c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 20 May 2018 10:02:29 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99460d21218..acfa4d2aad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.203 +* Rustup to *rustc 1.28.0-nightly (a3085756e 2018-05-19)* + ## 0.0.202 * Rustup to *rustc 1.28.0-nightly (952f344cd 2018-05-18)* diff --git a/Cargo.toml b/Cargo.toml index 71d4ec04ab1..214c7e2b295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.202" +version = "0.0.203" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.202", path = "clippy_lints" } +clippy_lints = { version = "0.0.203", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 4eb34910a40..ddc907d7f00 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.202" +version = "0.0.203" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index e56c97afb12..c28edfb6391 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (952f344cd 2018-05-18) +rustc 1.28.0-nightly (a3085756e 2018-05-19) binary: rustc -commit-hash: 952f344cdc0bca58d9f6c54dcfbae0890246e886 -commit-date: 2018-05-18 +commit-hash: a3085756edf66459109c4b07948b08fe3e78bc3b +commit-date: 2018-05-19 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 0a368b467e65e4a3aa8462cbda5beb78e8f622e4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 20 May 2018 14:09:39 +0200 Subject: Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index acfa4d2aad0..6fc3a6b5ddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## 0.0.203 * Rustup to *rustc 1.28.0-nightly (a3085756e 2018-05-19)* +* clippy attributes are now of the form `clippy::cyclomatic_complexity` instead of `clippy(cyclomatic_complexity)` ## 0.0.202 * Rustup to *rustc 1.28.0-nightly (952f344cd 2018-05-18)* -- cgit 1.4.1-3-g733a5 From 74be5632a38723a7a72e67a55dfb0738a341c95c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 21 May 2018 17:45:48 +0200 Subject: Fix chrono crash due to empty param_env --- clippy_lints/src/needless_pass_by_value.rs | 3 +-- tests/run-pass/ice-2760.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/run-pass/ice-2760.rs diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 39ed5cb424a..51085408d20 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -200,8 +200,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let sugg = |db: &mut DiagnosticBuilder| { if let ty::TypeVariants::TyAdt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { - let param_env = ty::ParamEnv::empty(); - if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { + if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { db.span_help(span, "consider marking this type as Copy"); } } diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs new file mode 100644 index 00000000000..01ca6d42a94 --- /dev/null +++ b/tests/run-pass/ice-2760.rs @@ -0,0 +1,19 @@ +#![allow(unused_variables, blacklisted_name, needless_pass_by_value, dead_code)] + +// This should not compile-fail with: +// +// error[E0277]: the trait bound `T: Foo` is not satisfied +// +// See https://github.com/rust-lang-nursery/rust-clippy/issues/2760 + +trait Foo { + type Bar; +} + +struct Baz { + bar: T::Bar, +} + +fn take(baz: Baz) {} + +fn main() {} -- cgit 1.4.1-3-g733a5 From cef63469511659473a97c1234efee4169ae673d0 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 21 May 2018 18:59:42 +0200 Subject: Remove most allow_failures The removed ones work fine now, only cargo and rls are failing currently. --- .travis.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2891ed9220..51dbb5f4987 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,18 +47,7 @@ matrix: - env: INTEGRATION=hyperium/hyper allow_failures: - env: INTEGRATION=rust-lang/cargo - - env: INTEGRATION=rust-lang-nursery/rand - - env: INTEGRATION=rust-lang-nursery/stdsimd - - env: INTEGRATION=rust-lang-nursery/rustfmt - - env: INTEGRATION=rust-lang-nursery/futures-rs - - env: INTEGRATION=rust-lang-nursery/failure - - env: INTEGRATION=rust-lang-nursery/log - - env: INTEGRATION=rust-lang-nursery/chalk - env: INTEGRATION=rust-lang-nursery/rls - - env: INTEGRATION=chronotope/chrono - - env: INTEGRATION=serde-rs/serde - - env: INTEGRATION=Geal/nom - - env: INTEGRATION=hyperium/hyper script: - | -- cgit 1.4.1-3-g733a5 From 3c6503eb4b24897e9317b4af2faaf6b603be32dd Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Tue, 22 May 2018 10:21:42 +0200 Subject: Format code --- build.rs | 76 ++++++++++++++++++++------------------ clippy_lints/src/approx_const.rs | 5 +-- clippy_lints/src/arithmetic.rs | 26 ++++++------- clippy_lints/src/array_indexing.rs | 6 +-- clippy_lints/src/assign_ops.rs | 74 ++++++++++++++++++++----------------- clippy_lints/src/attrs.rs | 27 +++++++------- src/driver.rs | 27 +++++++------- src/lib.rs | 4 +- tests/compile-test.rs | 7 +--- tests/versioncheck.rs | 5 +-- tests/without_block_comments.rs | 6 +-- 11 files changed, 134 insertions(+), 129 deletions(-) diff --git a/build.rs b/build.rs index 913f7b4ee89..1481f460fc3 100644 --- a/build.rs +++ b/build.rs @@ -13,12 +13,12 @@ //! This build script was originally taken from the Rocket web framework: //! https://github.com/SergioBenitez/Rocket -extern crate rustc_version; extern crate ansi_term; +extern crate rustc_version; -use std::env; -use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; use ansi_term::Colour::Red; +use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; +use std::env; fn main() { check_rustc_version(); @@ -31,42 +31,48 @@ fn main() { fn check_rustc_version() { let string = include_str!("min_version.txt"); - let min_version_meta = version_meta_for(string) - .expect("Could not parse version string in min_version.txt"); - let current_version_meta = version_meta() - .expect("Could not retrieve current rustc version information from ENV"); + let min_version_meta = version_meta_for(string).expect("Could not parse version string in min_version.txt"); + let current_version_meta = version_meta().expect("Could not retrieve current rustc version information from ENV"); let min_version = min_version_meta.clone().semver; - let min_date_str = min_version_meta.clone().commit_date + let min_date_str = min_version_meta + .clone() + .commit_date .expect("min_version.txt does not contain a rustc commit date"); // Dev channel (rustc built from git) does not have any date or commit information in rustc -vV // `current_version_meta.commit_date` would crash, so we return early here. if current_version_meta.channel == Channel::Dev { - return + return; } let current_version = current_version_meta.clone().semver; - let current_date_str = current_version_meta.clone().commit_date + let current_date_str = current_version_meta + .clone() + .commit_date .expect("current rustc version information does not contain a rustc commit date"); let print_version_err = |version: &Version, date: &str| { - eprintln!("> {} {}. {} {}.\n", - "Installed rustc version is:", - format!("{} ({})", version, date), - "Minimum required rustc version:", - format!("{} ({})", min_version, min_date_str)); + eprintln!( + "> {} {}. {} {}.\n", + "Installed rustc version is:", + format!("{} ({})", version, date), + "Minimum required rustc version:", + format!("{} ({})", min_version, min_date_str) + ); }; if !correct_channel(¤t_version_meta) { - eprintln!("\n{} {}", - Red.bold().paint("error:"), - "clippy requires a nightly version of Rust."); + eprintln!( + "\n{} {}", + Red.bold().paint("error:"), + "clippy requires a nightly version of Rust." + ); print_version_err(¤t_version, &*current_date_str); - eprintln!("{}{}{}", - "See the README (", - "https://github.com/rust-lang-nursery/rust-clippy#usage", - ") for more information."); + eprintln!( + "{}{}{}", + "See the README (", "https://github.com/rust-lang-nursery/rust-clippy#usage", ") for more information." + ); panic!("Aborting compilation due to incompatible compiler.") } @@ -74,13 +80,15 @@ fn check_rustc_version() { let min_date = str_to_ymd(&min_date_str).unwrap(); if current_date < min_date { - eprintln!("\n{} {}", - Red.bold().paint("error:"), - "clippy does not support this version of rustc nightly."); - eprintln!("> {}{}{}", - "Use `", - "rustup update", - "` or your preferred method to update Rust."); + eprintln!( + "\n{} {}", + Red.bold().paint("error:"), + "clippy does not support this version of rustc nightly." + ); + eprintln!( + "> {}{}{}", + "Use `", "rustup update", "` or your preferred method to update Rust." + ); print_version_err(¤t_version, &*current_date_str); panic!("Aborting compilation due to incompatible compiler.") } @@ -88,12 +96,8 @@ fn check_rustc_version() { fn correct_channel(version_meta: &VersionMeta) -> bool { match version_meta.channel { - Channel::Stable | Channel::Beta => { - false - }, - Channel::Nightly | Channel::Dev => { - true - } + Channel::Stable | Channel::Beta => false, + Channel::Nightly | Channel::Dev => true, } } @@ -101,7 +105,7 @@ fn correct_channel(version_meta: &VersionMeta) -> bool { fn str_to_ymd(ymd: &str) -> Option { let ymd: Vec = ymd.split("-").filter_map(|s| s.parse::().ok()).collect(); if ymd.len() != 3 { - return None + return None; } let (y, m, d) = (ymd[0], ymd[1], ymd[2]); diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index d15b48ce2d1..20b9c279277 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,5 +1,5 @@ -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; @@ -90,8 +90,7 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &symbol::Symbol, module: &s &format!( "approximate value of `{}::consts::{}` found. \ Consider using it directly", - module, - &name + module, &name ), ); return; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 501f49363dd..835555f42f8 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -57,19 +57,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd | - hir::BiOr | - hir::BiBitAnd | - hir::BiBitOr | - hir::BiBitXor | - hir::BiShl | - hir::BiShr | - hir::BiEq | - hir::BiLt | - hir::BiLe | - hir::BiNe | - hir::BiGe | - hir::BiGt => return, + hir::BiAnd + | hir::BiOr + | hir::BiBitAnd + | hir::BiBitOr + | hir::BiBitXor + | hir::BiShl + | hir::BiShr + | hir::BiEq + | hir::BiLt + | hir::BiLe + | hir::BiNe + | hir::BiGe + | hir::BiGt => return, _ => (), } let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index b5a42f03e9a..010f07ab8d2 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,10 +1,10 @@ +use consts::{constant, Constant}; +use rustc::hir; use rustc::lint::*; use rustc::ty; -use rustc::hir; use syntax::ast::RangeLimits; -use utils::{self, higher}; use utils::higher::Range; -use consts::{constant, Constant}; +use utils::{self, higher}; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index da4b0d6a437..7b4000485bd 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -95,24 +95,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { MISREFACTORED_ASSIGN_OP, expr.span, "variable appears on both sides of an assignment operation", - |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) - { - let a = &sugg::Sugg::hir(cx, assignee, ".."); - let r = &sugg::Sugg::hir(cx, rhs, ".."); - let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); - db.span_suggestion( - expr.span, - &format!("Did you mean {} = {} {} {} or {}? Consider replacing it with", - snip_a, snip_a, op.node.as_str(), snip_r, - long), - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r) - ); - db.span_suggestion( - expr.span, - "or", - long - ); + |db| { + if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) + { + let a = &sugg::Sugg::hir(cx, assignee, ".."); + let r = &sugg::Sugg::hir(cx, rhs, ".."); + let long = + format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); + db.span_suggestion( + expr.span, + &format!( + "Did you mean {} = {} {} {} or {}? Consider replacing it with", + snip_a, + snip_a, + op.node.as_str(), + snip_r, + long + ), + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + ); + db.span_suggestion(expr.span, "or", long); + } }, ); }; @@ -189,14 +193,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { ASSIGN_OP_PATTERN, expr.span, "manual implementation of an assign operation", - |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) - { - db.span_suggestion( - expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - ); + |db| { + if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + db.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + ); + } }, ); } @@ -205,7 +211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let mut visitor = ExprVisitor { assignee, counter: 0, - cx + cx, }; walk_expr(&mut visitor, e); @@ -218,13 +224,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // a = b commutative_op a if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { match op.node { - hir::BiAdd | - hir::BiMul | - hir::BiAnd | - hir::BiOr | - hir::BiBitXor | - hir::BiBitAnd | - hir::BiBitOr => { + hir::BiAdd + | hir::BiMul + | hir::BiAnd + | hir::BiOr + | hir::BiBitXor + | hir::BiBitAnd + | hir::BiBitOr => { lint(assignee, l); }, _ => {}, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index b1cd096bc13..936b5e75ff6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,13 +1,16 @@ //! checks for attributes use reexport::*; -use rustc::lint::*; use rustc::hir::*; +use rustc::lint::*; use rustc::ty::{self, TyCtxt}; use semver::Version; -use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, without_block_comments}; +use utils::{ + in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, + without_block_comments, +}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -118,7 +121,12 @@ pub struct AttrPass; impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { - lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, EMPTY_LINE_AFTER_OUTER_ATTR) + lint_array!( + INLINE_ALWAYS, + DEPRECATED_SEMVER, + USELESS_ATTRIBUTE, + EMPTY_LINE_AFTER_OUTER_ATTR + ) } } @@ -170,11 +178,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { "useless lint attribute", |db| { sugg = sugg.replacen("#[", "#![", 1); - db.span_suggestion( - line_span, - "if you just forgot a `!`, use", - sugg, - ); + db.span_suggestion(line_span, "if you just forgot a `!`, use", sugg); }, ); } @@ -234,10 +238,7 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), } } else { - block - .expr - .as_ref() - .map_or(false, |e| is_relevant_expr(tcx, tables, e)) + block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) } } diff --git a/src/driver.rs b/src/driver.rs index 61afb6ea2f4..a88d6e5c26d 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -6,16 +6,16 @@ extern crate clippy_lints; extern crate getopts; extern crate rustc; +extern crate rustc_codegen_utils; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_plugin; -extern crate rustc_codegen_utils; extern crate syntax; -use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc::session::{config, Session}; use rustc::session::config::{ErrorOutputType, Input}; +use rustc::session::{config, Session}; +use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; use std::path::PathBuf; use std::process::Command; use syntax::ast; @@ -43,8 +43,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType, ) -> Compilation { - self.default - .early_callback(matches, sopts, cfg, descriptions, output) + self.default.early_callback(matches, sopts, cfg, descriptions, output) } fn no_input( &mut self, @@ -55,8 +54,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry, ) -> Option<(Input, Option)> { - self.default - .no_input(matches, sopts, cfg, odir, ofile, descriptions) + self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions) } fn late_callback( &mut self, @@ -118,7 +116,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { } old(state); }); - + control.compilation_done.stop = Compilation::Stop; } @@ -185,15 +183,18 @@ pub fn main() { // this check ensures that dependencies are built but not linted and the final // crate is // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS") - .ok() - .map_or(false, |val| val == "true") + let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); if let Ok(extra_args) = env::var("CLIPPY_ARGS") { - args.extend(extra_args.split("__CLIPPY_HACKERY__").filter(|s| !s.is_empty()).map(str::to_owned)); + args.extend( + extra_args + .split("__CLIPPY_HACKERY__") + .filter(|s| !s.is_empty()) + .map(str::to_owned), + ); } } diff --git a/src/lib.rs b/src/lib.rs index e69323255e8..193be97161f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.sess.lint_store.with_read_lock(|lint_store| { for (lint, _, _) in lint_store.get_lint_groups() { reg.sess - .struct_warn("the clippy plugin is being deprecated, please use cargo clippy or rls with the clippy feature") + .struct_warn( + "the clippy plugin is being deprecated, please use cargo clippy or rls with the clippy feature", + ) .emit(); if lint == "clippy" { // cargo clippy run on a crate that also uses the plugin diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 9b9820f2b52..b965dceb774 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,8 +3,8 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::path::{Path, PathBuf}; use std::env::{set_var, var}; +use std::path::{Path, PathBuf}; fn clippy_driver_path() -> PathBuf { if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { @@ -43,10 +43,7 @@ fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!( - "-L {0} -L {0}/deps -Dwarnings", - host_libs().display() - )); + config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index ff4af08a8a0..25b0ceefae7 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -7,10 +7,7 @@ fn check_that_clippy_lints_has_the_same_version_as_clippy() { let clippy_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); let clippy_lints_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); - assert_eq!( - clippy_lints_meta.packages[0].version, - clippy_meta.packages[0].version - ); + assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); for package in &clippy_meta.packages[0].dependencies { if package.name == "clippy_lints" { assert_eq!( diff --git a/tests/without_block_comments.rs b/tests/without_block_comments.rs index 375df057544..730c5cb128f 100644 --- a/tests/without_block_comments.rs +++ b/tests/without_block_comments.rs @@ -7,9 +7,7 @@ fn test_lines_without_block_comments() { println!("result: {:?}", result); assert!(result.is_empty()); - let result = without_block_comments( - vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""] - ); + let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); let result = without_block_comments(vec!["/* rust", "", "*/"]); @@ -18,7 +16,7 @@ fn test_lines_without_block_comments() { let result = without_block_comments(vec!["/* one-line comment */"]); assert!(result.is_empty()); - let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); + let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); assert!(result.is_empty()); let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); -- cgit 1.4.1-3-g733a5 From a1c44e966e75913624ef5dbeda5fed4fa0e499ba Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Tue, 22 May 2018 15:45:14 +0200 Subject: Update to nightly 2018-05-22 Fixes #2788 --- clippy_lints/src/assign_ops.rs | 2 +- clippy_lints/src/consts.rs | 6 +++--- clippy_lints/src/enum_clike.rs | 4 ++-- clippy_lints/src/eq_op.rs | 10 +++++----- clippy_lints/src/misc.rs | 6 +++--- clippy_lints/src/needless_pass_by_value.rs | 6 +++++- clippy_lints/src/shadow.rs | 6 +++--- clippy_lints/src/utils/hir_utils.rs | 30 +++++++++++++++--------------- clippy_lints/src/utils/inspector.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 4 ++-- 10 files changed, 41 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 7b4000485bd..fae2897762e 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -174,7 +174,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { op.node, cx, ty, - rty, + rty.into(), Add: BiAdd, Sub: BiSub, Mul: BiMul, diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 841c6171740..3e803c11b1a 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -429,9 +429,9 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx - .interpret_interner - .get_alloc(ptr.alloc_id) - .unwrap(); + .alloc_map + .lock() + .unwrap_memory(ptr.alloc_id); let offset = ptr.offset.bytes() as usize; let n = n as usize; String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index da3586af262..37c0e1ef0c1 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -50,9 +50,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { if let ItemEnum(ref def, _) = item.node { for var in &def.variants { let variant = &var.node; - if let Some(body_id) = variant.disr_expr { + if let Some(ref anon_const) = variant.disr_expr { let param_env = ty::ParamEnv::empty(); - let did = cx.tcx.hir.body_owner_def_id(body_id); + let did = cx.tcx.hir.body_owner_def_id(anon_const.body); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); let instance = ty::Instance::new(did, substs); let cid = GlobalId { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index cce20a58da8..ca441aa9a93 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -90,7 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { let lcpy = is_copy(cx, lty); let rcpy = is_copy(cx, rty); // either operator autorefs or both args are copyable - if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty]) { + if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) { span_lint_and_then( cx, OP_REF, @@ -106,12 +106,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { ); }, ) - } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) { + } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion(left.span, "use the left value directly", lsnip); }) - } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) { + } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { span_lint_and_then( cx, OP_REF, @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { (&ExprAddrOf(_, ref l), _) => { let lty = cx.tables.expr_ty(l); let lcpy = is_copy(cx, lty); - if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) { + if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion(left.span, "use the left value directly", lsnip); @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { (_, &ExprAddrOf(_, ref r)) => { let rty = cx.tables.expr_ty(r); let rcpy = is_copy(cx, rty); - if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) { + if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); db.span_suggestion(right.span, "use the right value directly", rsnip); diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 0ecd0ac1895..080a2716fb7 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -495,13 +495,13 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { // *arg impls PartialEq if !arg_ty .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty])) + .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])) // arg impls PartialEq<*other> && !other_ty .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty])) + .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])) // arg impls PartialEq - && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) + && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]) { return; } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 51085408d20..907f9cb85fe 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -175,7 +175,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), - &t.skip_binder().input_types().skip(1).collect::>(), + &t.skip_binder() + .input_types() + .skip(1) + .map(|ty| ty.into()) + .collect::>(), ) }), ) diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 7bdeb0a666d..05a6650aec5 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -348,15 +348,15 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut Vec<(Name, Span)>) { match ty.node { TySlice(ref sty) => check_ty(cx, sty, bindings), - TyArray(ref fty, body_id) => { + TyArray(ref fty, ref anon_const) => { check_ty(cx, fty, bindings); - check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings); + check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings); }, TyPtr(MutTy { ty: ref mty, .. }) | TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), TyTup(ref tup) => for t in tup { check_ty(cx, t, bindings) }, - TyTypeof(body_id) => check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings), + TyTypeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings), _ => (), } } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 7d9945cdddc..deaa796aa05 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -120,11 +120,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) }, - (&ExprRepeat(ref le, ll_id), &ExprRepeat(ref re, rl_id)) => { - let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id)); - let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id).value); - let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id)); - let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id).value); + (&ExprRepeat(ref le, ref ll_id), &ExprRepeat(ref re, ref rl_id)) => { + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); + let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id.body).value); + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); + let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id.body).value); self.eq_expr(le, re) && ll == rl }, @@ -234,16 +234,16 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyArray(ref lt, ll_id), &TyArray(ref rt, rl_id)) => { + (&TyArray(ref lt, ref ll_id), &TyArray(ref rt, ref rl_id)) => { let full_table = self.tables; - let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id)); - self.tables = self.cx.tcx.body_tables(ll_id); - let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id).value); + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); + self.tables = self.cx.tcx.body_tables(ll_id.body); + let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id.body).value); - let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id)); - self.tables = self.cx.tcx.body_tables(rl_id); - let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id).value); + let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); + self.tables = self.cx.tcx.body_tables(rl_id.body); + let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id.body).value); let eq_ty = self.eq_ty(lt, rt); self.tables = full_table; @@ -474,13 +474,13 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_name(&path.name); self.hash_exprs(args); }, - ExprRepeat(ref e, l_id) => { + ExprRepeat(ref e, ref l_id) => { let c: fn(_, _) -> _ = ExprRepeat; c.hash(&mut self.s); self.hash_expr(e); let full_table = self.tables; - self.tables = self.cx.tcx.body_tables(l_id); - self.hash_expr(&self.cx.tcx.hir.body(l_id).value); + self.tables = self.cx.tcx.body_tables(l_id.body); + self.hash_expr(&self.cx.tcx.hir.body(l_id.body).value); self.tables = full_table; }, ExprRet(ref e) => { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 10a9a3a03c1..6c3d8bc2989 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -330,12 +330,12 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, base, indent + 1); } }, - hir::ExprRepeat(ref val, body_id) => { + hir::ExprRepeat(ref val, ref anon_const) => { println!("{}Repeat", ind); println!("{}value:", ind); print_expr(cx, val, indent + 1); println!("{}repeat count:", ind); - print_expr(cx, &cx.tcx.hir.body(body_id).value, indent + 1); + print_expr(cx, &cx.tcx.hir.body(anon_const.body).value, indent + 1); }, } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d5c7796fac6..86af4e8625f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,7 +8,7 @@ use rustc::hir::map::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}}; +use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; @@ -295,7 +295,7 @@ pub fn implements_trait<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, trait_id: DefId, - ty_params: &[Ty<'tcx>], + ty_params: &[Kind<'tcx>], ) -> bool { let ty = cx.tcx.erase_regions(&ty); let obligation = -- cgit 1.4.1-3-g733a5 From e7a3e03c6e7dd2c342847adec6b3531324195d31 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 23 May 2018 16:38:19 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- min_version.txt | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fc3a6b5ddc..3deece4229b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.204 +* Rustup to *rustc 1.28.0-nightly (71e87be38 2018-05-22)* + ## 0.0.203 * Rustup to *rustc 1.28.0-nightly (a3085756e 2018-05-19)* * clippy attributes are now of the form `clippy::cyclomatic_complexity` instead of `clippy(cyclomatic_complexity)` diff --git a/Cargo.toml b/Cargo.toml index 214c7e2b295..67631ebcc17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.203" +version = "0.0.204" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.203", path = "clippy_lints" } +clippy_lints = { version = "0.0.204", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ddc907d7f00..813efd9ba5c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.203" +version = "0.0.204" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/min_version.txt b/min_version.txt index c28edfb6391..0c27e9607eb 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (a3085756e 2018-05-19) +rustc 1.28.0-nightly (71e87be38 2018-05-22) binary: rustc -commit-hash: a3085756edf66459109c4b07948b08fe3e78bc3b -commit-date: 2018-05-19 +commit-hash: 71e87be381bd6020645d925c579fa7367167d3d8 +commit-date: 2018-05-22 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 77794e91e219b85663cf693d35f677e564151420 Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Wed, 23 May 2018 16:43:05 +0200 Subject: Create lint for unimplemented!() --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/panic.rs | 56 ++++++++++++++++++++++++++++++++++++----------- tests/ui/panic.rs | 7 +++++- tests/ui/panic.stderr | 11 +++++++++- 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3deece4229b..9e233837be4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -815,6 +815,7 @@ All notable changes to this project will be documented in this file. [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity [`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc +[`unimplemented`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unimplemented [`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast diff --git a/README.md b/README.md index 9472156ec98..50661501477 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 258 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 259 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7864e90c196..9dd9a364be7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -627,6 +627,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic::PANIC_PARAMS, + panic::UNIMPLEMENTED, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, ptr::CMP_NULL, @@ -749,6 +750,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic::PANIC_PARAMS, + panic::UNIMPLEMENTED, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index bd44b8d9b03..7f1b6775bab 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,8 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; +use syntax::ptr::P; +use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// @@ -22,12 +23,28 @@ declare_clippy_lint! { "missing parameters in `panic!` calls" } +/// **What it does:** Checks for usage of `unimplemented!`. +/// +/// **Why is this bad?** This macro should not be present in production code +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// unimplemented!(); +/// ``` +declare_clippy_lint! { + pub UNIMPLEMENTED, + style, + "`unimplemented!` should not be present in production code" +} + #[allow(missing_copy_implementations)] pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(PANIC_PARAMS) + lint_array!(PANIC_PARAMS, UNIMPLEMENTED) } } @@ -37,22 +54,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprBlock(ref block, _) = expr.node; if let Some(ref ex) = block.expr; if let ExprCall(ref fun, ref params) = ex.node; - if params.len() == 2; if let ExprPath(ref qpath) = fun.node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); - if let ExprLit(ref lit) = params[0].node; - if is_direct_expn_of(expr.span, "panic").is_some(); - if let LitKind::Str(ref string, _) = lit.node; - let string = string.as_str().replace("{{", "").replace("}}", ""); - if let Some(par) = string.find('{'); - if string[par..].contains('}'); - if params[0].span.source_callee().is_none(); - if params[0].span.lo() != params[0].span.hi(); + if params.len() == 2; then { - span_lint(cx, PANIC_PARAMS, params[0].span, - "you probably are missing some parameter in your format string"); + if is_expn_of(expr.span, "unimplemented").is_some() { + span_lint(cx, UNIMPLEMENTED, expr.span, + "`unimplemented` should not be present in production code"); + } else { + match_panic(params, expr, cx); + } } } } } + +fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { + if_chain! { + if let ExprLit(ref lit) = params[0].node; + if is_direct_expn_of(expr.span, "panic").is_some(); + if let LitKind::Str(ref string, _) = lit.node; + let string = string.as_str().replace("{{", "").replace("}}", ""); + if let Some(par) = string.find('{'); + if string[par..].contains('}'); + if params[0].span.source_callee().is_none(); + if params[0].span.lo() != params[0].span.hi(); + then { + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); + } + } +} diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs index d833d2651a5..56d06f23904 100644 --- a/tests/ui/panic.rs +++ b/tests/ui/panic.rs @@ -1,7 +1,7 @@ -#![warn(panic_params)] +#![warn(panic_params, unimplemented)] fn missing() { if true { @@ -53,6 +53,10 @@ fn ok_escaped() { panic!("{case }}"); } +fn unimplemented() { + unimplemented!(); +} + fn main() { missing(); ok_single(); @@ -61,4 +65,5 @@ fn main() { ok_inner(); ok_nomsg(); ok_escaped(); + unimplemented(); } diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr index 165c33cacb7..786a20c031b 100644 --- a/tests/ui/panic.stderr +++ b/tests/ui/panic.stderr @@ -24,5 +24,14 @@ error: you probably are missing some parameter in your format string 15 | panic!("{{{this}}}"); | ^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: `unimplemented` should not be present in production code + --> $DIR/panic.rs:57:5 + | +57 | unimplemented!(); + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D unimplemented` implied by `-D warnings` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 88c3c2f1c2b47862656c71973dc356422d03ba8b Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Thu, 24 May 2018 08:59:54 +0200 Subject: Rename panic files to panic_unimplemented --- clippy_lints/src/lib.rs | 12 ++--- clippy_lints/src/panic.rs | 88 --------------------------------- clippy_lints/src/panic_unimplemented.rs | 88 +++++++++++++++++++++++++++++++++ tests/ui/panic.rs | 69 -------------------------- tests/ui/panic.stderr | 37 -------------- tests/ui/panic_unimplemented.rs | 69 ++++++++++++++++++++++++++ tests/ui/panic_unimplemented.stderr | 37 ++++++++++++++ 7 files changed, 200 insertions(+), 200 deletions(-) delete mode 100644 clippy_lints/src/panic.rs create mode 100644 clippy_lints/src/panic_unimplemented.rs delete mode 100644 tests/ui/panic.rs delete mode 100644 tests/ui/panic.stderr create mode 100644 tests/ui/panic_unimplemented.rs create mode 100644 tests/ui/panic_unimplemented.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9dd9a364be7..1f9b2512d3b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -177,7 +177,7 @@ pub mod non_expressive_names; pub mod ok_if_let; pub mod open_options; pub mod overflow_check_conditional; -pub mod panic; +pub mod panic_unimplemented; pub mod partialeq_ne_impl; pub mod precedence; pub mod ptr; @@ -352,7 +352,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack}); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); - reg.register_late_lint_pass(box panic::Pass); + reg.register_late_lint_pass(box panic_unimplemented::Pass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); @@ -626,8 +626,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ok_if_let::IF_LET_SOME_RESULT, open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, - panic::PANIC_PARAMS, - panic::UNIMPLEMENTED, + panic_unimplemented::PANIC_PARAMS, + panic_unimplemented::UNIMPLEMENTED, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, ptr::CMP_NULL, @@ -749,8 +749,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, - panic::PANIC_PARAMS, - panic::UNIMPLEMENTED, + panic_unimplemented::PANIC_PARAMS, + panic_unimplemented::UNIMPLEMENTED, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs deleted file mode 100644 index 7f1b6775bab..00000000000 --- a/clippy_lints/src/panic.rs +++ /dev/null @@ -1,88 +0,0 @@ -use rustc::hir::*; -use rustc::lint::*; -use syntax::ast::LitKind; -use syntax::ptr::P; -use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; - -/// **What it does:** Checks for missing parameters in `panic!`. -/// -/// **Why is this bad?** Contrary to the `format!` family of macros, there are -/// two forms of `panic!`: if there are no parameters given, the first argument -/// is not a format string and used literally. So while `format!("{}")` will -/// fail to compile, `panic!("{}")` will not. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// panic!("This `panic!` is probably missing a parameter there: {}"); -/// ``` -declare_clippy_lint! { - pub PANIC_PARAMS, - style, - "missing parameters in `panic!` calls" -} - -/// **What it does:** Checks for usage of `unimplemented!`. -/// -/// **Why is this bad?** This macro should not be present in production code -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// unimplemented!(); -/// ``` -declare_clippy_lint! { - pub UNIMPLEMENTED, - style, - "`unimplemented!` should not be present in production code" -} - -#[allow(missing_copy_implementations)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(PANIC_PARAMS, UNIMPLEMENTED) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_chain! { - if let ExprBlock(ref block, _) = expr.node; - if let Some(ref ex) = block.expr; - if let ExprCall(ref fun, ref params) = ex.node; - if let ExprPath(ref qpath) = fun.node; - if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); - if params.len() == 2; - then { - if is_expn_of(expr.span, "unimplemented").is_some() { - span_lint(cx, UNIMPLEMENTED, expr.span, - "`unimplemented` should not be present in production code"); - } else { - match_panic(params, expr, cx); - } - } - } - } -} - -fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { - if_chain! { - if let ExprLit(ref lit) = params[0].node; - if is_direct_expn_of(expr.span, "panic").is_some(); - if let LitKind::Str(ref string, _) = lit.node; - let string = string.as_str().replace("{{", "").replace("}}", ""); - if let Some(par) = string.find('{'); - if string[par..].contains('}'); - if params[0].span.source_callee().is_none(); - if params[0].span.lo() != params[0].span.hi(); - then { - span_lint(cx, PANIC_PARAMS, params[0].span, - "you probably are missing some parameter in your format string"); - } - } -} diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs new file mode 100644 index 00000000000..7f1b6775bab --- /dev/null +++ b/clippy_lints/src/panic_unimplemented.rs @@ -0,0 +1,88 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::ast::LitKind; +use syntax::ptr::P; +use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; + +/// **What it does:** Checks for missing parameters in `panic!`. +/// +/// **Why is this bad?** Contrary to the `format!` family of macros, there are +/// two forms of `panic!`: if there are no parameters given, the first argument +/// is not a format string and used literally. So while `format!("{}")` will +/// fail to compile, `panic!("{}")` will not. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// panic!("This `panic!` is probably missing a parameter there: {}"); +/// ``` +declare_clippy_lint! { + pub PANIC_PARAMS, + style, + "missing parameters in `panic!` calls" +} + +/// **What it does:** Checks for usage of `unimplemented!`. +/// +/// **Why is this bad?** This macro should not be present in production code +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// unimplemented!(); +/// ``` +declare_clippy_lint! { + pub UNIMPLEMENTED, + style, + "`unimplemented!` should not be present in production code" +} + +#[allow(missing_copy_implementations)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(PANIC_PARAMS, UNIMPLEMENTED) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprBlock(ref block, _) = expr.node; + if let Some(ref ex) = block.expr; + if let ExprCall(ref fun, ref params) = ex.node; + if let ExprPath(ref qpath) = fun.node; + if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); + if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); + if params.len() == 2; + then { + if is_expn_of(expr.span, "unimplemented").is_some() { + span_lint(cx, UNIMPLEMENTED, expr.span, + "`unimplemented` should not be present in production code"); + } else { + match_panic(params, expr, cx); + } + } + } + } +} + +fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { + if_chain! { + if let ExprLit(ref lit) = params[0].node; + if is_direct_expn_of(expr.span, "panic").is_some(); + if let LitKind::Str(ref string, _) = lit.node; + let string = string.as_str().replace("{{", "").replace("}}", ""); + if let Some(par) = string.find('{'); + if string[par..].contains('}'); + if params[0].span.source_callee().is_none(); + if params[0].span.lo() != params[0].span.hi(); + then { + span_lint(cx, PANIC_PARAMS, params[0].span, + "you probably are missing some parameter in your format string"); + } + } +} diff --git a/tests/ui/panic.rs b/tests/ui/panic.rs deleted file mode 100644 index 56d06f23904..00000000000 --- a/tests/ui/panic.rs +++ /dev/null @@ -1,69 +0,0 @@ - - - -#![warn(panic_params, unimplemented)] - -fn missing() { - if true { - panic!("{}"); - } else if false { - panic!("{:?}"); - } else { - assert!(true, "here be missing values: {}"); - } - - panic!("{{{this}}}"); -} - -fn ok_single() { - panic!("foo bar"); -} - -fn ok_inner() { - // Test for #768 - assert!("foo bar".contains(&format!("foo {}", "bar"))); -} - -fn ok_multiple() { - panic!("{}", "This is {ok}"); -} - -fn ok_bracket() { - match 42 { - 1337 => panic!("{so is this"), - 666 => panic!("so is this}"), - _ => panic!("}so is that{"), - } -} - -const ONE : u32= 1; - -fn ok_nomsg() { - assert!({ 1 == ONE }); - assert!(if 1 == ONE { ONE == 1 } else { false }); -} - -fn ok_escaped() { - panic!("{{ why should this not be ok? }}"); - panic!(" or {{ that ?"); - panic!(" or }} this ?"); - panic!(" {or {{ that ?"); - panic!(" }or }} this ?"); - panic!("{{ test }"); - panic!("{case }}"); -} - -fn unimplemented() { - unimplemented!(); -} - -fn main() { - missing(); - ok_single(); - ok_multiple(); - ok_bracket(); - ok_inner(); - ok_nomsg(); - ok_escaped(); - unimplemented(); -} diff --git a/tests/ui/panic.stderr b/tests/ui/panic.stderr deleted file mode 100644 index 786a20c031b..00000000000 --- a/tests/ui/panic.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error: you probably are missing some parameter in your format string - --> $DIR/panic.rs:8:16 - | -8 | panic!("{}"); - | ^^^^ - | - = note: `-D panic-params` implied by `-D warnings` - -error: you probably are missing some parameter in your format string - --> $DIR/panic.rs:10:16 - | -10 | panic!("{:?}"); - | ^^^^^^ - -error: you probably are missing some parameter in your format string - --> $DIR/panic.rs:12:23 - | -12 | assert!(true, "here be missing values: {}"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you probably are missing some parameter in your format string - --> $DIR/panic.rs:15:12 - | -15 | panic!("{{{this}}}"); - | ^^^^^^^^^^^^ - -error: `unimplemented` should not be present in production code - --> $DIR/panic.rs:57:5 - | -57 | unimplemented!(); - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D unimplemented` implied by `-D warnings` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -error: aborting due to 5 previous errors - diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs new file mode 100644 index 00000000000..56d06f23904 --- /dev/null +++ b/tests/ui/panic_unimplemented.rs @@ -0,0 +1,69 @@ + + + +#![warn(panic_params, unimplemented)] + +fn missing() { + if true { + panic!("{}"); + } else if false { + panic!("{:?}"); + } else { + assert!(true, "here be missing values: {}"); + } + + panic!("{{{this}}}"); +} + +fn ok_single() { + panic!("foo bar"); +} + +fn ok_inner() { + // Test for #768 + assert!("foo bar".contains(&format!("foo {}", "bar"))); +} + +fn ok_multiple() { + panic!("{}", "This is {ok}"); +} + +fn ok_bracket() { + match 42 { + 1337 => panic!("{so is this"), + 666 => panic!("so is this}"), + _ => panic!("}so is that{"), + } +} + +const ONE : u32= 1; + +fn ok_nomsg() { + assert!({ 1 == ONE }); + assert!(if 1 == ONE { ONE == 1 } else { false }); +} + +fn ok_escaped() { + panic!("{{ why should this not be ok? }}"); + panic!(" or {{ that ?"); + panic!(" or }} this ?"); + panic!(" {or {{ that ?"); + panic!(" }or }} this ?"); + panic!("{{ test }"); + panic!("{case }}"); +} + +fn unimplemented() { + unimplemented!(); +} + +fn main() { + missing(); + ok_single(); + ok_multiple(); + ok_bracket(); + ok_inner(); + ok_nomsg(); + ok_escaped(); + unimplemented(); +} diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr new file mode 100644 index 00000000000..534bfbae89b --- /dev/null +++ b/tests/ui/panic_unimplemented.stderr @@ -0,0 +1,37 @@ +error: you probably are missing some parameter in your format string + --> $DIR/panic_unimplemented.rs:8:16 + | +8 | panic!("{}"); + | ^^^^ + | + = note: `-D panic-params` implied by `-D warnings` + +error: you probably are missing some parameter in your format string + --> $DIR/panic_unimplemented.rs:10:16 + | +10 | panic!("{:?}"); + | ^^^^^^ + +error: you probably are missing some parameter in your format string + --> $DIR/panic_unimplemented.rs:12:23 + | +12 | assert!(true, "here be missing values: {}"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: you probably are missing some parameter in your format string + --> $DIR/panic_unimplemented.rs:15:12 + | +15 | panic!("{{{this}}}"); + | ^^^^^^^^^^^^ + +error: `unimplemented` should not be present in production code + --> $DIR/panic_unimplemented.rs:57:5 + | +57 | unimplemented!(); + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D unimplemented` implied by `-D warnings` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 5 previous errors + -- cgit 1.4.1-3-g733a5 From dc8d29be4ac405e61b6c403b0ea09809e55b8efa Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Thu, 24 May 2018 16:30:26 +0200 Subject: Allow unimplemented in other tests --- tests/run-pass/ice_exacte_size.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index 914153c64ff..d99734810f5 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -6,6 +6,7 @@ struct Foo; impl Iterator for Foo { type Item = (); + #[allow(unimplemented)] fn next(&mut self) -> Option<()> { let _ = self.len() == 0; unimplemented!() -- cgit 1.4.1-3-g733a5 From 1f10dd26069d94488bbcb9669e4b60c66e295c60 Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Thu, 24 May 2018 19:26:04 +0200 Subject: Fix note on macro outside current crate. Changed group to restricted --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/panic_unimplemented.rs | 18 ++++++++++++++++-- tests/run-pass/ice_exacte_size.rs | 1 - tests/ui/panic_unimplemented.rs | 2 ++ tests/ui/panic_unimplemented.stderr | 5 ++--- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1f9b2512d3b..aaf2ef5738c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -434,6 +434,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::WRONG_PUB_SELF_CONVENTION, misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, @@ -627,7 +628,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { open_options::NONSENSICAL_OPEN_OPTIONS, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, panic_unimplemented::PANIC_PARAMS, - panic_unimplemented::UNIMPLEMENTED, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, ptr::CMP_NULL, @@ -750,7 +750,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, panic_unimplemented::PANIC_PARAMS, - panic_unimplemented::UNIMPLEMENTED, ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 7f1b6775bab..b257f5b3b94 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; use syntax::ptr::P; +use syntax::ext::quote::rt::Span; use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. @@ -35,7 +36,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub UNIMPLEMENTED, - style, + restriction, "`unimplemented!` should not be present in production code" } @@ -60,7 +61,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if params.len() == 2; then { if is_expn_of(expr.span, "unimplemented").is_some() { - span_lint(cx, UNIMPLEMENTED, expr.span, + let span = get_outer_span(expr); + span_lint(cx, UNIMPLEMENTED, span, "`unimplemented` should not be present in production code"); } else { match_panic(params, expr, cx); @@ -70,6 +72,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } +fn get_outer_span(expr: &Expr) -> Span { + if_chain! { + if let Some(first) = expr.span.ctxt().outer().expn_info(); + if let Some(second) = first.call_site.ctxt().outer().expn_info(); + then { + second.call_site + } else { + expr.span + } + } +} + fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { if_chain! { if let ExprLit(ref lit) = params[0].node; diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index d99734810f5..914153c64ff 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -6,7 +6,6 @@ struct Foo; impl Iterator for Foo { type Item = (); - #[allow(unimplemented)] fn next(&mut self) -> Option<()> { let _ = self.len() == 0; unimplemented!() diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 56d06f23904..33050633f7f 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -54,7 +54,9 @@ fn ok_escaped() { } fn unimplemented() { + let a = 2; unimplemented!(); + let b = a + 2; } fn main() { diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index 534bfbae89b..3bf5589c468 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -25,13 +25,12 @@ error: you probably are missing some parameter in your format string | ^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panic_unimplemented.rs:57:5 + --> $DIR/panic_unimplemented.rs:58:5 | -57 | unimplemented!(); +58 | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | = note: `-D unimplemented` implied by `-D warnings` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 391562706de61db09222e06d613a42d641b318f6 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 25 May 2018 08:11:15 +0200 Subject: Don't run deploy script in integration tests The deploy.sh was causing random integration tests to fail, possibly due to multiple jobs trying to push to the same repo/branch at the same time? The error message is: +git push git@github.com:rust-lang-nursery/rust-clippy.git gh-pages Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts. To github.com:rust-lang-nursery/rust-clippy.git ! [rejected] gh-pages -> gh-pages (fetch first) error: failed to push some refs to 'git@github.com:rust-lang-nursery/rust-clippy.git' hint: Updates were rejected because the re The travis log is always truncated in similar ways. Some examples: * https://travis-ci.org/rust-lang-nursery/rust-clippy/jobs/383325083#L1076-L1082 * https://travis-ci.org/rust-lang-nursery/rust-clippy/jobs/382711561#L2768-L2773 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c2891ed9220..301612b154e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,9 @@ after_success: | #!/bin/bash if [ $(uname) == Linux ]; then set -ex - ./.github/deploy.sh + if [ -z ${INTEGRATION} ]; then + ./.github/deploy.sh + fi # trigger rebuild of the clippy-service, to keep it up to date with clippy itself if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_REPO_SLUG" == "Manishearth/rust-clippy" ] && -- cgit 1.4.1-3-g733a5 From 2999be64bcc3d10eac2d0e719294547018f4e43d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 25 May 2018 08:35:04 +0200 Subject: Add some output to make log reading easier --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 301612b154e..41424b39c80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,6 +74,8 @@ after_success: | set -ex if [ -z ${INTEGRATION} ]; then ./.github/deploy.sh + else + echo "Not deploying, because we're in an integration test run" fi # trigger rebuild of the clippy-service, to keep it up to date with clippy itself if [ "$TRAVIS_PULL_REQUEST" == "false" ] && -- cgit 1.4.1-3-g733a5 From fc008aa14c59a0b0cb0a1e60fe836f83019a722a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 26 May 2018 10:23:34 +0200 Subject: Rustup --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/consts.rs | 6 +++--- clippy_lints/src/lib.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 6 +++--- min_version.txt | 6 +++--- tests/ui/lifetimes.rs | 2 +- tests/ui/unused_lt.rs | 2 +- tests/ui/unused_lt.stderr | 2 +- 10 files changed, 21 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e233837be4..ff95dc72b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.205 +* Rustup to *rustc 1.28.0-nightly (990d8aa74 2018-05-25)* +* Rename `unused_lifetimes` to `extra_unused_lifetimes` because of naming conflict with new rustc lint + ## 0.0.204 * Rustup to *rustc 1.28.0-nightly (71e87be38 2018-05-22)* diff --git a/Cargo.toml b/Cargo.toml index 67631ebcc17..9d49b89440e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.204" +version = "0.0.205" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.204", path = "clippy_lints" } +clippy_lints = { version = "0.0.205", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 813efd9ba5c..a02cad5b181 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.204" +version = "0.0.205" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 3e803c11b1a..d02836441e1 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -415,9 +415,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use rustc::mir::interpret::{PrimVal, ConstValue}; + use rustc::mir::interpret::{Scalar, ConstValue}; match result.val { - ConstVal::Value(ConstValue::ByVal(PrimVal::Bytes(b))) => match result.ty.sty { + ConstVal::Value(ConstValue::Scalar(Scalar::Bits{ bits: b, ..})) => match result.ty.sty { ty::TyBool => Some(Constant::Bool(b == 1)), ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)), ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), @@ -425,7 +425,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' // FIXME: implement other conversion _ => None, }, - ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty { + ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. })) => match result.ty.sty { ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index aaf2ef5738c..efba3b69577 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -543,7 +543,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, lifetimes::NEEDLESS_LIFETIMES, - lifetimes::UNUSED_LIFETIMES, + lifetimes::EXTRA_UNUSED_LIFETIMES, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, @@ -786,7 +786,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_op::IDENTITY_OP, int_plus_one::INT_PLUS_ONE, lifetimes::NEEDLESS_LIFETIMES, - lifetimes::UNUSED_LIFETIMES, + lifetimes::EXTRA_UNUSED_LIFETIMES, loops::EXPLICIT_COUNTER_LOOP, loops::MUT_RANGE_BOUND, loops::WHILE_LET_LOOP, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 01177c36be9..3804823ae5a 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -43,7 +43,7 @@ declare_clippy_lint! { /// fn unused_lifetime<'a>(x: u8) { .. } /// ``` declare_clippy_lint! { - pub UNUSED_LIFETIMES, + pub EXTRA_UNUSED_LIFETIMES, complexity, "unused lifetimes in function definitions" } @@ -53,7 +53,7 @@ pub struct LifetimePass; impl LintPass for LifetimePass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_LIFETIMES, UNUSED_LIFETIMES) + lint_array!(NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES) } } @@ -431,7 +431,7 @@ fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx walk_fn_decl(&mut checker, func); for &v in checker.map.values() { - span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); + span_lint(cx, EXTRA_UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); } } diff --git a/min_version.txt b/min_version.txt index 0c27e9607eb..55f113ccd9d 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (71e87be38 2018-05-22) +rustc 1.28.0-nightly (990d8aa74 2018-05-25) binary: rustc -commit-hash: 71e87be381bd6020645d925c579fa7367167d3d8 -commit-date: 2018-05-22 +commit-hash: 990d8aa743b1dda3cc0f68fe09524486261812c6 +commit-date: 2018-05-25 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index dce9c23da68..1f6aeaafcf1 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -1,7 +1,7 @@ -#![warn(needless_lifetimes, unused_lifetimes)] +#![warn(needless_lifetimes, extra_unused_lifetimes)] #![allow(dead_code, needless_pass_by_value)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 91bca47eb12..198730d87f3 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,7 +1,7 @@ #![allow(unused, dead_code, needless_lifetimes, needless_pass_by_value)] -#![warn(unused_lifetimes)] +#![warn(extra_unused_lifetimes)] fn empty() { diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index b1fcebe6eed..f01dfda7013 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -4,7 +4,7 @@ error: this lifetime isn't used in the function definition 16 | fn unused_lt<'a>(x: u8) { | ^^ | - = note: `-D unused-lifetimes` implied by `-D warnings` + = note: `-D extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition --> $DIR/unused_lt.rs:20:25 -- cgit 1.4.1-3-g733a5 From 78b8d5cf1a358a6856d9ee3fcad0dbc5e3f291d1 Mon Sep 17 00:00:00 2001 From: Reiner Dolp Date: Sun, 27 May 2018 16:16:41 +0200 Subject: running update lints script --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff95dc72b70..fe0211c9c66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -654,6 +654,7 @@ All notable changes to this project will be documented in this file. [`explicit_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_iter_loop [`explicit_write`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extend_from_slice +[`extra_unused_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extra_unused_lifetimes [`fallible_impl_from`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fallible_impl_from [`filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_map [`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next @@ -835,7 +836,6 @@ All notable changes to this project will be documented in this file. [`unused_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_collect [`unused_io_amount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_io_amount [`unused_label`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_label -[`unused_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_lifetimes [`use_debug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#used_underscore_binding diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efba3b69577..9ef0901c350 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -542,8 +542,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, - lifetimes::NEEDLESS_LIFETIMES, lifetimes::EXTRA_UNUSED_LIFETIMES, + lifetimes::NEEDLESS_LIFETIMES, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, @@ -785,8 +785,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, int_plus_one::INT_PLUS_ONE, - lifetimes::NEEDLESS_LIFETIMES, lifetimes::EXTRA_UNUSED_LIFETIMES, + lifetimes::NEEDLESS_LIFETIMES, loops::EXPLICIT_COUNTER_LOOP, loops::MUT_RANGE_BOUND, loops::WHILE_LET_LOOP, -- cgit 1.4.1-3-g733a5 From 5379fc1b2804b647946b4a5d485db6c9579e4f55 Mon Sep 17 00:00:00 2001 From: François Mockers Date: Sun, 27 May 2018 23:59:07 +0200 Subject: better parsing of condition in while loop for mutability allow condition to be a block: by calling visit_expr of the visitor directly on the condition instead of walk_expr on the whole expression, we bypass the match to ExprWhile that calls visit_expr on the condition and visit_block on the body. This allow to re-enable visit_block in the visitor, as it won't be called on the while body allow condition to use static variables: maintain a list of static variables used, and if they are mutable --- clippy_lints/src/loops.rs | 11 +++++++---- tests/run-pass/issues_loop_mut_cond.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/run-pass/issues_loop_mut_cond.rs diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b0f39937668..c8f1d3edaeb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2154,9 +2154,10 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b let mut mut_var_visitor = VarCollectorVisitor { cx, ids: HashMap::new(), + def_ids: HashMap::new(), skip: false, }; - walk_expr(&mut mut_var_visitor, expr); + mut_var_visitor.visit_expr(cond); if mut_var_visitor.skip { return; } @@ -2172,7 +2173,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b if delegate.skip { return; } - if !delegate.used_mutably.iter().any(|(_, v)| *v) { + if !(delegate.used_mutably.iter().any(|(_, v)| *v) || mut_var_visitor.def_ids.iter().any(|(_, v)| *v)) { span_lint( cx, WHILE_IMMUTABLE_CONDITION, @@ -2189,6 +2190,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b struct VarCollectorVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, ids: HashMap, + def_ids: HashMap, skip: bool, } @@ -2203,6 +2205,9 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { Def::Local(node_id) | Def::Upvar(node_id, ..) => { self.ids.insert(node_id, false); }, + Def::Static(def_id, mutable) => { + self.def_ids.insert(def_id, mutable); + }, _ => {}, } } @@ -2221,8 +2226,6 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { } } - fn visit_block(&mut self, _b: &'tcx Block) {} - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs new file mode 100644 index 00000000000..6ecd40b99b1 --- /dev/null +++ b/tests/run-pass/issues_loop_mut_cond.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] + +/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2596 +pub fn loop_on_block_condition(u: &mut isize) { + while { *u < 0 } { + *u += 1; + } +} + +/// https://github.com/rust-lang-nursery/rust-clippy/issues/2584 +fn loop_with_unsafe_condition(ptr: *const u8) { + let mut len = 0; + while unsafe { *ptr.offset(len) } != 0 { + len += 1; + } +} + +/// https://github.com/rust-lang-nursery/rust-clippy/issues/2710 +static mut RUNNING: bool = true; +fn loop_on_static_condition() { + unsafe { + while RUNNING { + RUNNING = false; + } + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From ceea20153c00d9a04206fe5c9331ca61baf3ee6c Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Mon, 28 May 2018 09:50:25 +0200 Subject: Refactored nested if lets to if_chain! macro --- clippy_lints/src/reference.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 0d4332b4a7d..ffdb02216dc 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -38,8 +38,10 @@ fn without_parens(mut e: &Expr) -> &Expr { impl EarlyLintPass for Pass { fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) { - if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node { - if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node { + if_chain! { + if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node; + if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node; + then { span_lint_and_sugg( cx, DEREF_ADDROF, -- cgit 1.4.1-3-g733a5 From 1931f533960924e2ef0ec106ed1b38f4d2e326e0 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Mon, 28 May 2018 10:03:27 +0200 Subject: Removed stable feature flags --- clippy_lints/src/lib.rs | 3 - tests/run-pass/needless_lifetimes_impl_trait.rs | 2 - tests/ui/replace_consts.rs | 4 - tests/ui/replace_consts.stderr | 140 ++++++++++++------------ 4 files changed, 70 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efba3b69577..4cf9a699865 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -4,14 +4,11 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] -#![feature(conservative_impl_trait)] #![feature(range_contains)] #![feature(macro_vis_matcher)] #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] -// FIXME(mark-i-m) remove after i128 stablization merges #![allow(stable_features)] -#![feature(i128, i128_type)] #![feature(iterator_find_map)] diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 8cf2287c0ea..700215baa64 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,6 +1,4 @@ -#![allow(stable_features)] -#![feature(conservative_impl_trait)] #![deny(needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 4bd9c1d7cae..71d4ea98e07 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -2,10 +2,6 @@ #![allow(blacklisted_name)] #![deny(replace_consts)] -// FIXME(mark-i-m) remove after i128 stablization merges -#![allow(stable_features)] -#![feature(i128, i128_type)] - use std::sync::atomic::*; use std::sync::{ONCE_INIT, Once}; diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 571bfc6e65b..0a9d5f4ab75 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,7 +1,7 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:16:17 + --> $DIR/replace_consts.rs:12:17 | -16 | { let foo = ATOMIC_BOOL_INIT; }; +12 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here @@ -11,207 +11,207 @@ note: lint level defined here | ^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:17:17 + --> $DIR/replace_consts.rs:13:17 | -17 | { let foo = ATOMIC_ISIZE_INIT; }; +13 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:18:17 + --> $DIR/replace_consts.rs:14:17 | -18 | { let foo = ATOMIC_I8_INIT; }; +14 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:19:17 + --> $DIR/replace_consts.rs:15:17 | -19 | { let foo = ATOMIC_I16_INIT; }; +15 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:20:17 + --> $DIR/replace_consts.rs:16:17 | -20 | { let foo = ATOMIC_I32_INIT; }; +16 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:21:17 + --> $DIR/replace_consts.rs:17:17 | -21 | { let foo = ATOMIC_I64_INIT; }; +17 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:22:17 + --> $DIR/replace_consts.rs:18:17 | -22 | { let foo = ATOMIC_USIZE_INIT; }; +18 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:19:17 | -23 | { let foo = ATOMIC_U8_INIT; }; +19 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:20:17 | -24 | { let foo = ATOMIC_U16_INIT; }; +20 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:21:17 | -25 | { let foo = ATOMIC_U32_INIT; }; +21 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:22:17 | -26 | { let foo = ATOMIC_U64_INIT; }; +22 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:24:17 | -28 | { let foo = std::isize::MIN; }; +24 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:25:17 | -29 | { let foo = std::i8::MIN; }; +25 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:26:17 | -30 | { let foo = std::i16::MIN; }; +26 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:27:17 | -31 | { let foo = std::i32::MIN; }; +27 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:28:17 | -32 | { let foo = std::i64::MIN; }; +28 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:29:17 | -33 | { let foo = std::i128::MIN; }; +29 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:30:17 | -34 | { let foo = std::usize::MIN; }; +30 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:31:17 | -35 | { let foo = std::u8::MIN; }; +31 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:32:17 | -36 | { let foo = std::u16::MIN; }; +32 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:33:17 | -37 | { let foo = std::u32::MIN; }; +33 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:34:17 | -38 | { let foo = std::u64::MIN; }; +34 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:35:17 | -39 | { let foo = std::u128::MIN; }; +35 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:37:17 | -41 | { let foo = std::isize::MAX; }; +37 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:38:17 | -42 | { let foo = std::i8::MAX; }; +38 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:39:17 | -43 | { let foo = std::i16::MAX; }; +39 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:40:17 | -44 | { let foo = std::i32::MAX; }; +40 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:41:17 | -45 | { let foo = std::i64::MAX; }; +41 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:42:17 | -46 | { let foo = std::i128::MAX; }; +42 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:43:17 | -47 | { let foo = std::usize::MAX; }; +43 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:44:17 | -48 | { let foo = std::u8::MAX; }; +44 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:45:17 | -49 | { let foo = std::u16::MAX; }; +45 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:46:17 | -50 | { let foo = std::u32::MAX; }; +46 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:51:17 + --> $DIR/replace_consts.rs:47:17 | -51 | { let foo = std::u64::MAX; }; +47 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:52:17 + --> $DIR/replace_consts.rs:48:17 | -52 | { let foo = std::u128::MAX; }; +48 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors -- cgit 1.4.1-3-g733a5 From 8b679176fade98d8908f3950506f53b3a5b27910 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Mon, 28 May 2018 09:29:02 +0200 Subject: Added lint for unnecessary references --- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/reference.rs | 50 +++++++++++++++++++++++++++++++++++++++++ tests/ui/unnecessary_ref.rs | 12 ++++++++++ tests/ui/unnecessary_ref.stderr | 14 ++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 tests/ui/unnecessary_ref.rs create mode 100644 tests/ui/unnecessary_ref.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efba3b69577..c3e9c4bf86f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -391,6 +391,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass); reg.register_late_lint_pass(box partialeq_ne_impl::Pass); reg.register_early_lint_pass(box reference::Pass); + reg.register_early_lint_pass(box reference::DerefPass); reg.register_early_lint_pass(box double_parens::DoubleParens); reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount); reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); @@ -812,6 +813,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { precedence::PRECEDENCE, ranges::RANGE_ZIP_WITH_LEN, reference::DEREF_ADDROF, + reference::REF_IN_DEREF, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, transmute::CROSSPOINTER_TRANSMUTE, diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 0d4332b4a7d..765be0bdf36 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -52,3 +52,53 @@ impl EarlyLintPass for Pass { } } } + +/// **What it does:** Checks for references in expressions that use +/// auto dereference. +/// +/// **Why is this bad?** The reference is a no-op and is automatically +/// dereferenced by the compiler and makes the code less clear. +/// +/// **Example:** +/// ```rust +/// struct Point(u32, u32); +/// let point = Foo(30, 20); +/// let x = (&point).x; +/// ``` +declare_clippy_lint! { + pub REF_IN_DEREF, + complexity, + "Use of reference in auto dereference expression." +} + +pub struct DerefPass; + +impl LintPass for DerefPass { + fn get_lints(&self) -> LintArray { + lint_array!(REF_IN_DEREF) + } +} + +impl EarlyLintPass for DerefPass { + fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) { + if_chain! { + if let ExprKind::Field(ref object, ref field_name) = e.node; + if let ExprKind::Paren(ref parened) = object.node; + if let ExprKind::AddrOf(_, ref inner) = parened.node; + then { + span_lint_and_sugg( + cx, + REF_IN_DEREF, + object.span, + "Creating a reference that is immediately dereferenced.", + "try this", + format!( + "{}.{}", + snippet(cx, inner.span, "_"), + snippet(cx, field_name.span, "_") + ) + ); + } + } + } +} diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs new file mode 100644 index 00000000000..53b970dfa72 --- /dev/null +++ b/tests/ui/unnecessary_ref.rs @@ -0,0 +1,12 @@ +#![feature(tool_attributes)] +#![feature(stmt_expr_attributes)] + +struct Outer { + inner: u32, +} + +#[deny(ref_in_deref)] +fn main() { + let outer = Outer { inner: 0 }; + let inner = (&outer).inner; +} diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr new file mode 100644 index 00000000000..ffc65084afa --- /dev/null +++ b/tests/ui/unnecessary_ref.stderr @@ -0,0 +1,14 @@ +error: Creating a reference that is immediately dereferenced. + --> $DIR/unnecessary_ref.rs:11:17 + | +11 | let inner = (&outer).inner; + | ^^^^^^^^ help: try this: `outer.inner` + | +note: lint level defined here + --> $DIR/unnecessary_ref.rs:8:8 + | +8 | #[deny(ref_in_deref)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 2033a1eb0ed66eb6f742e30187715fa25d97bb56 Mon Sep 17 00:00:00 2001 From: Terry Raimondo Date: Mon, 28 May 2018 13:55:27 +0200 Subject: unreadable_literal: Fills hexadecimal values with 0 to allow grouping (c.f #2300) --- clippy_lints/src/literal_representation.rs | 8 +++- tests/ui/literals.rs | 8 +++- tests/ui/literals.stderr | 74 +++++++++++++++++++----------- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 6c2351d43dd..b40ddca5cbf 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -193,7 +193,7 @@ impl<'a> DigitInfo<'a> { self.suffix.unwrap_or("") ) } else { - let hint = self.digits + let mut hint = self.digits .chars() .rev() .filter(|&c| c != '_') @@ -203,6 +203,12 @@ impl<'a> DigitInfo<'a> { .rev() .collect::>() .join("_"); + // Forces hexadecimal values to be grouped by 4 being filled with zeroes (e.g 0x00ab_cdef) + let nb_digits_to_fill = self.digits.len() % 4; + if self.radix == Radix::Hexadecimal && nb_digits_to_fill != 0 { + let filled_digits = format!("{:0>1$}", &hint[..nb_digits_to_fill], 4); + hint = format!("{}{}", filled_digits, &hint[nb_digits_to_fill..]); + } format!( "{}{}{}", self.prefix.unwrap_or(""), diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index c11adc0b090..7be11072b0b 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -1,5 +1,3 @@ - - #![warn(mixed_case_hex_literals)] #![warn(unseparated_literal_suffix)] #![warn(zero_prefixed_literal)] @@ -31,4 +29,10 @@ fn main() { let ok11 = 0o123; let ok12 = 0b10_1010; + + let ok6 = 0xab_abcd; + let ok7 = 0xBAFE_BAFE; + let fail9 = 0xabcdef; + let fail10 = 0xBAFEBAFE; + let fail11 = 0xabcdeff; } diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 92540b73462..703adbfd280 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,90 +1,110 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:14:17 + --> $DIR/literals.rs:12:17 | -14 | let fail1 = 0xabCD; +12 | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:15:17 + --> $DIR/literals.rs:13:17 | -15 | let fail2 = 0xabCD_u32; +13 | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:16:17 + --> $DIR/literals.rs:14:17 | -16 | let fail2 = 0xabCD_isize; +14 | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:17:27 + --> $DIR/literals.rs:15:27 | -17 | let fail_multi_zero = 000_123usize; +15 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:17:27 + --> $DIR/literals.rs:15:27 | -17 | let fail_multi_zero = 000_123usize; +15 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -17 | let fail_multi_zero = 123usize; +15 | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -17 | let fail_multi_zero = 0o123usize; +15 | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:22:17 + --> $DIR/literals.rs:20:17 | -22 | let fail3 = 1234i32; +20 | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:23:17 + --> $DIR/literals.rs:21:17 | -23 | let fail4 = 1234u32; +21 | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:24:17 + --> $DIR/literals.rs:22:17 | -24 | let fail5 = 1234isize; +22 | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:25:17 + --> $DIR/literals.rs:23:17 | -25 | let fail6 = 1234usize; +23 | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:26:17 + --> $DIR/literals.rs:24:17 | -26 | let fail7 = 1.5f32; +24 | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:30:17 + --> $DIR/literals.rs:28:17 | -30 | let fail8 = 0123; +28 | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -30 | let fail8 = 123; +28 | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -30 | let fail8 = 0o123; +28 | let fail8 = 0o123; | ^^^^^ -error: aborting due to 11 previous errors +error: long literal lacking separators + --> $DIR/literals.rs:35:17 + | +35 | let fail9 = 0xabcdef; + | ^^^^^^^^ help: consider: `0x00ab_cdef` + | + = note: `-D unreadable-literal` implied by `-D warnings` + +error: long literal lacking separators + --> $DIR/literals.rs:36:18 + | +36 | let fail10 = 0xBAFEBAFE; + | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` + +error: long literal lacking separators + --> $DIR/literals.rs:37:18 + | +37 | let fail11 = 0xabcdeff; + | ^^^^^^^^^ help: consider: `0x0abc_deff` + +error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From b81fd202a05b3b32f1194c93861a3321086fa354 Mon Sep 17 00:00:00 2001 From: Terry Raimondo Date: Mon, 28 May 2018 14:12:20 +0200 Subject: Add tests Fix tests --- clippy_lints/src/literal_representation.rs | 5 ++--- tests/ui/literals.rs | 10 ++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index b40ddca5cbf..dacfd7c8983 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -204,10 +204,9 @@ impl<'a> DigitInfo<'a> { .collect::>() .join("_"); // Forces hexadecimal values to be grouped by 4 being filled with zeroes (e.g 0x00ab_cdef) - let nb_digits_to_fill = self.digits.len() % 4; + let nb_digits_to_fill = self.digits.chars().filter(|&c| c != '_').collect::>().len() % 4; if self.radix == Radix::Hexadecimal && nb_digits_to_fill != 0 { - let filled_digits = format!("{:0>1$}", &hint[..nb_digits_to_fill], 4); - hint = format!("{}{}", filled_digits, &hint[nb_digits_to_fill..]); + hint = format!("{:0>4}{}", &hint[..nb_digits_to_fill], &hint[nb_digits_to_fill..]); } format!( "{}{}{}", diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 7be11072b0b..581fbbb70c9 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -30,9 +30,15 @@ fn main() { let ok11 = 0o123; let ok12 = 0b10_1010; - let ok6 = 0xab_abcd; - let ok7 = 0xBAFE_BAFE; + let ok13 = 0xab_abcd; + let ok14 = 0xBAFE_BAFE; + let ok15 = 0xab_cabc_abca_bcab_cabc; + let ok16 = 0xFE_BAFE_ABAB_ABCD; + let ok17 = 0x123_4567_8901_usize; + let fail9 = 0xabcdef; let fail10 = 0xBAFEBAFE; let fail11 = 0xabcdeff; + let fail12 = 0xabcabcabcabcabcabc; + let fail13 = 0x1_23456_78901_usize; } -- cgit 1.4.1-3-g733a5 From ed011c45c4fd9177934e14ed48e1bac0a10ee891 Mon Sep 17 00:00:00 2001 From: Terry Raimondo Date: Mon, 28 May 2018 14:43:44 +0200 Subject: Update other tests --- tests/ui/large_digit_groups.stderr | 2 +- tests/ui/literals.stderr | 28 +++++++++++++++++++++------- tests/ui/unreadable_literal.stderr | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 284c5ecf339..f2e6a62d13c 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -10,7 +10,7 @@ error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:31 | 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:54 diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 703adbfd280..6f6ea75df10 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -87,24 +87,38 @@ help: if you mean to use an octal constant, use `0o` | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:35:17 + --> $DIR/literals.rs:39:17 | -35 | let fail9 = 0xabcdef; +39 | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | = note: `-D unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:36:18 + --> $DIR/literals.rs:40:18 | -36 | let fail10 = 0xBAFEBAFE; +40 | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:37:18 + --> $DIR/literals.rs:41:18 | -37 | let fail11 = 0xabcdeff; +41 | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` -error: aborting due to 14 previous errors +error: long literal lacking separators + --> $DIR/literals.rs:42:18 + | +42 | let fail12 = 0xabcabcabcabcabcabc; + | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` + +error: digit groups should be smaller + --> $DIR/literals.rs:43:18 + | +43 | let fail13 = 0x1_23456_78901_usize; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` + | + = note: `-D large-digit-groups` implied by `-D warnings` + +error: aborting due to 16 previous errors diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 4b78e2e121b..cffcad1eef7 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -10,7 +10,7 @@ error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:30 | 7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x123_4567_8901_usize` + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:51 -- cgit 1.4.1-3-g733a5 From e86268e67ff9cdca4a5f465a1017965be8f207df Mon Sep 17 00:00:00 2001 From: Andrea Lattuada Date: Sun, 27 May 2018 15:45:01 +0200 Subject: Add support for ExprCall in clippy::author --- clippy_lints/src/utils/author.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index dd43a0d2177..1f802bb4733 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -210,9 +210,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(element); } }, - Expr_::ExprCall(ref _func, ref _args) => { - println!("Call(ref func, ref args) = {};", current); - println!(" // unimplemented: `ExprCall` is not further destructured at the moment"); + Expr_::ExprCall(ref func, ref args) => { + let func_pat = self.next("func"); + let args_pat = self.next("args"); + println!("Call(ref {}, ref {}) = {};", func_pat, args_pat, current); + self.current = func_pat; + self.visit_expr(func); + println!(" if {}.len() == {};", args_pat, args.len()); + for (i, arg) in args.iter().enumerate() { + self.current = format!("{}[{}]", args_pat, i); + self.visit_expr(arg); + } }, Expr_::ExprMethodCall(ref _method_name, ref _generics, ref _args) => { println!("MethodCall(ref method_name, ref generics, ref args) = {};", current); -- cgit 1.4.1-3-g733a5 From bc1de58d2652bc85b9f588ef12262ff1bb734e49 Mon Sep 17 00:00:00 2001 From: Andrea Lattuada Date: Sun, 27 May 2018 16:04:28 +0200 Subject: Test for ExprCall in clippy::author --- tests/ui/author/call.rs | 6 ++++++ tests/ui/author/call.stdout | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 tests/ui/author/call.rs create mode 100644 tests/ui/author/call.stdout diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs new file mode 100755 index 00000000000..8d085112f3b --- /dev/null +++ b/tests/ui/author/call.rs @@ -0,0 +1,6 @@ +#![feature(tool_attributes)] + +fn main() { + #[clippy::author] + let _ = ::std::cmp::min(3, 4); +} diff --git a/tests/ui/author/call.stdout b/tests/ui/author/call.stdout new file mode 100644 index 00000000000..3e06bf9ace8 --- /dev/null +++ b/tests/ui/author/call.stdout @@ -0,0 +1,17 @@ +if_chain! { + if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let Decl_::DeclLocal(ref local) = decl.node; + if let Some(ref init) = local.init + if let Expr_::ExprCall(ref func, ref args) = init.node; + if let Expr_::ExprPath(ref path) = func.node; + if match_qpath(path, &["{{root}}", "std", "cmp", "min"]); + if args.len() == 2; + if let Expr_::ExprLit(ref lit) = args[0].node; + if let LitKind::Int(3, _) = lit.node; + if let Expr_::ExprLit(ref lit1) = args[1].node; + if let LitKind::Int(4, _) = lit1.node; + if let PatKind::Wild = local.pat.node; + then { + // report your lint here + } +} -- cgit 1.4.1-3-g733a5 From 5db444dfed6dd8cd3a00c62d95ae7ebb6f60e22a Mon Sep 17 00:00:00 2001 From: Andrea Lattuada Date: Mon, 28 May 2018 14:50:41 +0200 Subject: author tests: update for_loop.stdout file --- tests/ui/author/for_loop.stdout | 49 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index af6b5a4ec33..69bc6d7a025 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -5,7 +5,13 @@ if_chain! { if let Some(ref init) = local.init if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; if let Expr_::ExprCall(ref func, ref args) = expr.node; - // unimplemented: `ExprCall` is not further destructured at the moment + if let Expr_::ExprPath(ref path) = func.node; + if match_qpath(path, &["{{root}}", "std", "iter", "IntoIterator", "into_iter"]); + if args.len() == 1; + if let Expr_::ExprStruct(ref path1, ref fields, None) = args[0].node; + if match_qpath(path1, &["{{root}}", "std", "ops", "Range"]); + if fields.len() == 2; + // unimplemented: field checks if arms.len() == 1; if let Expr_::ExprLoop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; if let Stmt_::StmtDecl(ref decl1, _) = body.node @@ -14,28 +20,33 @@ if_chain! { if name.node.as_str() == "__next"; if let Stmt_::StmtExpr(ref e, _) = local1.pat.node if let Expr_::ExprMatch(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; - if let Expr_::ExprCall(ref func, ref args) = expr1.node; - // unimplemented: `ExprCall` is not further destructured at the moment + if let Expr_::ExprCall(ref func1, ref args1) = expr1.node; + if let Expr_::ExprPath(ref path2) = func1.node; + if match_qpath(path2, &["{{root}}", "std", "iter", "Iterator", "next"]); + if args1.len() == 1; + if let Expr_::ExprAddrOf(MutMutable, ref inner) = args1[0].node; + if let Expr_::ExprPath(ref path3) = inner.node; + if match_qpath(path3, &["iter"]); if arms1.len() == 2; if let Expr_::ExprAssign(ref target, ref value) = arms1[0].body.node; - if let Expr_::ExprPath(ref path) = target.node; - if match_qpath(path, &["__next"]); - if let Expr_::ExprPath(ref path1) = value.node; - if match_qpath(path1, &["val"]); + if let Expr_::ExprPath(ref path4) = target.node; + if match_qpath(path4, &["__next"]); + if let Expr_::ExprPath(ref path5) = value.node; + if match_qpath(path5, &["val"]); if arms1[0].pats.len() == 1; - if let PatKind::TupleStruct(ref path2, ref fields, None) = arms1[0].pats[0].node; - if match_qpath(path2, &["{{root}}", "std", "option", "Option", "Some"]); - if fields.len() == 1; + if let PatKind::TupleStruct(ref path6, ref fields1, None) = arms1[0].pats[0].node; + if match_qpath(path6, &["{{root}}", "std", "option", "Option", "Some"]); + if fields1.len() == 1; // unimplemented: field checks if let Expr_::ExprBreak(ref destination, None) = arms1[1].body.node; if arms1[1].pats.len() == 1; - if let PatKind::Path(ref path3) = arms1[1].pats[0].node; - if match_qpath(path3, &["{{root}}", "std", "option", "Option", "None"]); - if let Stmt_::StmtDecl(ref decl2, _) = path3.node + if let PatKind::Path(ref path7) = arms1[1].pats[0].node; + if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); + if let Stmt_::StmtDecl(ref decl2, _) = path7.node if let Decl_::DeclLocal(ref local2) = decl2.node; if let Some(ref init1) = local2.init - if let Expr_::ExprPath(ref path4) = init1.node; - if match_qpath(path4, &["__next"]); + if let Expr_::ExprPath(ref path8) = init1.node; + if match_qpath(path8, &["__next"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local2.pat.node; if name1.node.as_str() == "y"; if let Stmt_::StmtExpr(ref e1, _) = local2.pat.node @@ -43,8 +54,8 @@ if_chain! { if let Stmt_::StmtDecl(ref decl3, _) = block1.node if let Decl_::DeclLocal(ref local3) = decl3.node; if let Some(ref init2) = local3.init - if let Expr_::ExprPath(ref path5) = init2.node; - if match_qpath(path5, &["y"]); + if let Expr_::ExprPath(ref path9) = init2.node; + if match_qpath(path9, &["y"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local3.pat.node; if name2.node.as_str() == "z"; if arms[0].pats.len() == 1; @@ -52,8 +63,8 @@ if_chain! { if name3.node.as_str() == "iter"; if let PatKind::Binding(BindingAnnotation::Unannotated, _, name4, None) = local.pat.node; if name4.node.as_str() == "_result"; - if let Expr_::ExprPath(ref path6) = local.pat.node; - if match_qpath(path6, &["_result"]); + if let Expr_::ExprPath(ref path10) = local.pat.node; + if match_qpath(path10, &["_result"]); then { // report your lint here } -- cgit 1.4.1-3-g733a5 From cf8f3796578b5423d9465ff0d1e8327668753cca Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Mon, 28 May 2018 23:31:55 +0700 Subject: Add lint on cast Fn to numerical. --- clippy_lints/src/types.rs | 16 ++++++++++++++++ tests/ui/types_fn_to_int.rs | 10 ++++++++++ tests/ui/types_fn_to_int.stderr | 10 ++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tests/ui/types_fn_to_int.rs create mode 100644 tests/ui/types_fn_to_int.stderr diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 168086d574a..f5cbcfb6b00 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -975,6 +975,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { }, } } + + match &cast_from.sty { + ty::TyFnDef(..) | + ty::TyFnPtr(..) => { + if cast_to.is_numeric() && cast_to.sty != ty::TyUint(UintTy::Usize){ + span_lint( + cx, + UNNECESSARY_CAST, + expr.span, + "casting Fn not to usize may truncate the value", + ); + } + } + _ => () + } + if_chain!{ if let ty::TyRawPtr(from_ptr_ty) = &cast_from.sty; if let ty::TyRawPtr(to_ptr_ty) = &cast_to.sty; diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs new file mode 100644 index 00000000000..250307e54b7 --- /dev/null +++ b/tests/ui/types_fn_to_int.rs @@ -0,0 +1,10 @@ +#![feature(tool_attributes)] +enum Foo { + A(usize), + B +} + +fn main() { + let x = Foo::A; + let y = x as i32; +} diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr new file mode 100644 index 00000000000..dffcf008302 --- /dev/null +++ b/tests/ui/types_fn_to_int.stderr @@ -0,0 +1,10 @@ +error: casting Fn not to usize may truncate the value + --> $DIR/types_fn_to_int.rs:9:13 + | +9 | let y = x as i32; + | ^^^^^^^^ + | + = note: `-D unnecessary-cast` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 01be53f92939df92ac7cb48d8b2a9713744e7b6e Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Mon, 28 May 2018 23:49:38 +0700 Subject: Little fix for test --- tests/ui/types_fn_to_int.rs | 1 - tests/ui/types_fn_to_int.stderr | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs index 250307e54b7..fadedcef9f2 100644 --- a/tests/ui/types_fn_to_int.rs +++ b/tests/ui/types_fn_to_int.rs @@ -1,4 +1,3 @@ -#![feature(tool_attributes)] enum Foo { A(usize), B diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index dffcf008302..519b7763386 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -1,7 +1,7 @@ error: casting Fn not to usize may truncate the value - --> $DIR/types_fn_to_int.rs:9:13 + --> $DIR/types_fn_to_int.rs:8:13 | -9 | let y = x as i32; +8 | let y = x as i32; | ^^^^^^^^ | = note: `-D unnecessary-cast` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 8ed8ee895aab89add6101233e3cbceb19f7d6d79 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Tue, 29 May 2018 10:56:58 +0200 Subject: Update to nightly 2018-05-28 --- clippy_lints/src/format.rs | 4 +- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/misc.rs | 4 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/shadow.rs | 4 +- clippy_lints/src/utils/author.rs | 4 +- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 8 +- clippy_lints/src/utils/inspector.rs | 8 +- clippy_lints/src/utils/sugg.rs | 4 +- clippy_lints/src/write.rs | 8 +- tests/ui/for_loop.stderr | 36 ++++---- tests/ui/implicit_hasher.stderr | 32 +++---- tests/ui/matches.stderr | 4 +- tests/ui/needless_pass_by_value.rs | 9 +- tests/ui/needless_pass_by_value.stderr | 144 +++++++++++++++--------------- tests/ui/needless_range_loop.stderr | 6 +- tests/ui/op_ref.stderr | 2 +- 18 files changed, 141 insertions(+), 144 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 25cff794fd8..f418681cfb2 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -147,9 +147,9 @@ fn check_unformatted(expr: &Expr) -> bool { if let ExprArray(ref exprs) = expr.node; if exprs.len() == 1; if let ExprStruct(_, ref fields, _) = exprs[0].node; - if let Some(format_field) = fields.iter().find(|f| f.name.node == "format"); + if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); if let ExprStruct(_, ref fields, _) = format_field.expr.node; - if let Some(align_field) = fields.iter().find(|f| f.name.node == "width"); + if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width"); if let ExprPath(ref qpath) = align_field.expr.node; if last_path_segment(qpath).name == "Implied"; then { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 05902614df7..1e75d42dd61 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -10,13 +10,13 @@ #![recursion_limit = "256"] #![allow(stable_features)] #![feature(iterator_find_map)] - +#![feature(macro_at_most_once_rep)] extern crate cargo_metadata; #[macro_use] extern crate rustc; -extern crate rustc_typeck; extern crate rustc_target; +extern crate rustc_typeck; extern crate syntax; extern crate syntax_pos; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 080a2716fb7..2654def1385 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -392,8 +392,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { None } }, - ExprField(_, spanned) => { - let name = spanned.node.as_str(); + ExprField(_, ident) => { + let name = ident.as_str(); if name.starts_with('_') && !name.starts_with("__") { Some(name) } else { diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 5e24361f1d1..a0465f21105 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { if let ExprStruct(_, ref fields, _) = expr.node { for field in fields { - let name = field.name.node; + let name = field.ident.name; if match_var(&field.expr, name) && !field.is_shorthand { span_lint_and_sugg ( diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 05a6650aec5..59f18d21534 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -187,10 +187,10 @@ fn check_pat<'a, 'tcx>( PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init { if let ExprStruct(_, ref efields, _) = init_struct.node { for field in pfields { - let name = field.node.name; + let name = field.node.ident.name; let efield = efields .iter() - .find(|f| f.name.node == name) + .find(|f| f.ident.name == name) .map(|f| &*f.expr); check_pat(cx, &field.node.pat, efield, span, bindings); } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index dd43a0d2177..79fde40b448 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -383,11 +383,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, - Expr_::ExprField(ref object, ref field_name) => { + Expr_::ExprField(ref object, ref field_ident) => { let obj_pat = self.next("object"); let field_name_pat = self.next("field_name"); println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current); - println!(" if {}.node.as_str() == {:?}", field_name_pat, field_name.node.as_str()); + println!(" if {}.node.as_str() == {:?}", field_name_pat, field_ident.name.as_str()); self.current = obj_pat; self.visit_expr(object); }, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 9a4fcd45d8a..5a20bfc8143 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -77,7 +77,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O /// Find the field named `name` in the field. Always return `Some` for /// convenience. fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { - let expr = &fields.iter().find(|field| field.name.node == name)?.expr; + let expr = &fields.iter().find(|field| field.ident.name == name)?.expr; Some(expr) } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index deaa796aa05..0b70d61da1f 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) | (&ExprType(ref lx, ref lt), &ExprType(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), (&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => { - l_f_ident.node == r_f_ident.node && self.eq_expr(l_f_exp, r_f_exp) + l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { @@ -149,7 +149,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } fn eq_field(&mut self, left: &Field, right: &Field) -> bool { - left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr) + left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr) } fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool { @@ -419,7 +419,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprField; c.hash(&mut self.s); self.hash_expr(e); - self.hash_name(&f.node); + self.hash_name(&f.name); }, ExprIndex(ref a, ref i) => { let c: fn(_, _) -> _ = ExprIndex; @@ -502,7 +502,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_qpath(path); for f in fields { - self.hash_name(&f.name.node); + self.hash_name(&f.ident.name); self.hash_expr(&f.expr); } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 6c3d8bc2989..03682a19725 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -268,9 +268,9 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprField(ref e, ref name) => { + hir::ExprField(ref e, ref ident) => { println!("{}Field", ind); - println!("{}field name: {}", ind, name.node); + println!("{}field name: {}", ind, ident.name); println!("{}struct expr:", ind); print_expr(cx, e, indent + 1); }, @@ -322,7 +322,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}Struct", ind); println!("{}path: {:?}", ind, path); for field in fields { - println!("{}field \"{}\":", ind, field.name.node); + println!("{}field \"{}\":", ind, field.ident.name); print_expr(cx, &field.expr, indent + 1); } if let Some(ref base) = *base { @@ -433,7 +433,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { println!("{}ignore leftover fields: {}", ind, ignore); println!("{}fields:", ind); for field in fields { - println!("{} field name: {}", ind, field.node.name); + println!("{} field name: {}", ind, field.node.ident.name); if field.node.is_shorthand { println!("{} in shorthand notation", ind); } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index a9e5a3222ac..e7f63bb9a72 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -97,6 +97,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::Closure(..) | ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | + ast::ExprKind::ObsoleteInPlace(..) | ast::ExprKind::Unary(..) | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), ast::ExprKind::Block(..) | @@ -320,6 +321,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { AssocOp::ShiftRight | AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), AssocOp::Assign => format!("{} = {}", lhs, rhs), + AssocOp::ObsoleteInPlace => format!("in ({}) {}", lhs, rhs), AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), AssocOp::As => format!("{} as {}", lhs, rhs), AssocOp::DotDot => format!("{}..{}", lhs, rhs), @@ -360,7 +362,7 @@ fn associativity(op: &AssocOp) -> Associativity { use syntax::util::parser::AssocOp::*; match *op { - Assign | AssignOp(_) => Associativity::Right, + ObsoleteInPlace | Assign | AssignOp(_) => Associativity::Right, Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, Divide | Equal | diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 9a32d4e696c..fdd4f8ced9a 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -375,7 +375,7 @@ where if let ExprArray(ref format_exprs) = format_expr.node; if format_exprs.len() >= 1; if let ExprStruct(_, ref fields, _) = format_exprs[idx].node; - if let Some(format_field) = fields.iter().find(|f| f.name.node == "format"); + if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); if check_unformatted(&format_field.expr); then { lint_fn(tup_val.span); @@ -469,13 +469,13 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { pub fn check_unformatted(format_field: &Expr) -> bool { if_chain! { if let ExprStruct(_, ref fields, _) = format_field.node; - if let Some(width_field) = fields.iter().find(|f| f.name.node == "width"); + if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width"); if let ExprPath(ref qpath) = width_field.expr.node; if last_path_segment(qpath).name == "Implied"; - if let Some(align_field) = fields.iter().find(|f| f.name.node == "align"); + if let Some(align_field) = fields.iter().find(|f| f.ident.name == "align"); if let ExprPath(ref qpath) = align_field.expr.node; if last_path_segment(qpath).name == "Unknown"; - if let Some(precision_field) = fields.iter().find(|f| f.name.node == "precision"); + if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision"); if let ExprPath(ref qpath_precision) = precision_field.expr.node; if last_path_segment(qpath_precision).name == "Implied"; then { diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 34b3527fbae..582ca84b133 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -78,7 +78,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 86 | for in &vec { - | + | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:95:14 @@ -88,7 +88,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 95 | for in &vec { - | + | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. --> $DIR/for_loop.rs:100:14 @@ -98,7 +98,7 @@ error: the loop variable `j` is only used to index `STATIC`. help: consider using an iterator | 100 | for in STATIC.iter().take(4) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:104:14 @@ -108,7 +108,7 @@ error: the loop variable `j` is only used to index `CONST`. help: consider using an iterator | 104 | for in CONST.iter().take(4) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:108:14 @@ -118,7 +118,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 108 | for (i, ) in vec.iter().enumerate() { - | + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. --> $DIR/for_loop.rs:116:14 @@ -128,7 +128,7 @@ error: the loop variable `i` is only used to index `vec2`. help: consider using an iterator | 116 | for in vec2.iter().take(vec.len()) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:120:14 @@ -138,7 +138,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 120 | for in vec.iter().skip(5) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:124:14 @@ -148,7 +148,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 124 | for in vec.iter().take(MAX_LEN) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:128:14 @@ -158,7 +158,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 128 | for in vec.iter().take(MAX_LEN + 1) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:132:14 @@ -168,7 +168,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 132 | for in vec.iter().take(10).skip(5) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:136:14 @@ -178,7 +178,7 @@ error: the loop variable `i` is only used to index `vec`. help: consider using an iterator | 136 | for in vec.iter().take(10 + 1).skip(5) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:140:14 @@ -188,7 +188,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 140 | for (i, ) in vec.iter().enumerate().skip(5) { - | + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:144:14 @@ -198,7 +198,7 @@ error: the loop variable `i` is used to index `vec` help: consider using an iterator | 144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { - | + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run --> $DIR/for_loop.rs:148:14 @@ -384,7 +384,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 385 | for v in m.values() { - | + | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:390:19 @@ -394,7 +394,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 390 | for v in (*m).values() { - | + | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:398:19 @@ -404,7 +404,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 398 | for v in m.values_mut() { - | + | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values --> $DIR/for_loop.rs:403:19 @@ -414,7 +414,7 @@ error: you seem to want to iterate on a map's values help: use the corresponding method | 403 | for v in (*m).values_mut() { - | + | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys --> $DIR/for_loop.rs:409:24 @@ -424,7 +424,7 @@ error: you seem to want to iterate on a map's keys help: use the corresponding method | 409 | for k in rm.keys() { - | + | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:462:14 diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index cdba5372b3c..f41ce40519f 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -8,11 +8,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 11 | impl Foo for HashMap { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:20:36 @@ -22,11 +22,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 20 | impl Foo for (HashMap,) { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:25:19 @@ -36,11 +36,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 25 | impl Foo for HashMap { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:43:32 @@ -50,11 +50,11 @@ error: impl for `HashSet` should be generalized over different hashers help: consider adding a type parameter | 43 | impl Foo for HashSet { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ help: ...and use generic constructor | 45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:48:19 @@ -64,11 +64,11 @@ error: impl for `HashSet` should be generalized over different hashers help: consider adding a type parameter | 48 | impl Foo for HashSet { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:23 @@ -78,7 +78,7 @@ error: parameter of type `HashMap` should be generalized over different hashers help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:65:53 @@ -88,7 +88,7 @@ error: parameter of type `HashSet` should be generalized over different hashers help: consider adding a type parameter | 65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:70:43 @@ -101,11 +101,11 @@ error: impl for `HashMap` should be generalized over different hashers help: consider adding a type parameter | 70 | impl Foo for HashMap { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | 72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) - | + | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:33 @@ -118,7 +118,7 @@ error: parameter of type `HashMap` should be generalized over different hashers help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:78:63 @@ -131,7 +131,7 @@ error: parameter of type `HashSet` should be generalized over different hashers help: consider adding a type parameter | 78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index cc43cdb25fc..e0afc939b42 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -65,7 +65,7 @@ error: you don't need to add `&` to all patterns help: instead of prefixing all patterns with `&`, you can dereference the expression | 57 | if let None = *a { - | + | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns --> $DIR/matches.rs:62:5 @@ -77,7 +77,7 @@ error: you don't need to add `&` to both the expression and the patterns help: try | 62 | if let None = b { - | + | ^^^^ ^ error: some ranges overlap --> $DIR/matches.rs:71:9 diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 3459d3820b7..322df0b8798 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -1,11 +1,6 @@ - - - #![warn(needless_pass_by_value)] #![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names, option_option)] -#![feature(collections_range)] - use std::borrow::Borrow; use std::convert::AsRef; @@ -116,8 +111,8 @@ trait FalsePositive { extern "C" fn ext(x: String) -> usize { x.len() } // whitelist RangeArgument -fn range>(range: T) { - let _ = range.start(); +fn range>(range: T) { + let _ = range.start_bound(); } struct CopyWrapper(u32); diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 469c16fa3d5..2fef0595cb3 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,187 +1,187 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:14:23 - | -14 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { - | ^^^^^^ help: consider changing the type to: `&[T]` - | - = note: `-D needless-pass-by-value` implied by `-D warnings` + --> $DIR/needless_pass_by_value.rs:9:23 + | +9 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { + | ^^^^^^ help: consider changing the type to: `&[T]` + | + = note: `-D needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:28:11 + --> $DIR/needless_pass_by_value.rs:23:11 | -28 | fn bar(x: String, y: Wrapper) { +23 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:28:22 + --> $DIR/needless_pass_by_value.rs:23:22 | -28 | fn bar(x: String, y: Wrapper) { +23 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:34:71 + --> $DIR/needless_pass_by_value.rs:29:71 | -34 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +29 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:46:18 + --> $DIR/needless_pass_by_value.rs:41:18 | -46 | fn test_match(x: Option>, y: Option>) { +41 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -46 | fn test_match(x: &Option>, y: Option>) { -47 | match *x { +41 | fn test_match(x: &Option>, y: Option>) { +42 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:59:24 + --> $DIR/needless_pass_by_value.rs:54:24 | -59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +54 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:59:36 + --> $DIR/needless_pass_by_value.rs:54:36 | -59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +54 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead | -59 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -60 | let Wrapper(s) = z; // moved -61 | let Wrapper(ref t) = *y; // not moved -62 | let Wrapper(_) = *y; // still not moved +54 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +55 | let Wrapper(s) = z; // moved +56 | let Wrapper(ref t) = *y; // not moved +57 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:49 + --> $DIR/needless_pass_by_value.rs:70:49 | -75 | fn test_blanket_ref(_foo: T, _serializable: S) {} +70 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:77:18 + --> $DIR/needless_pass_by_value.rs:72:18 | -77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:77:29 + --> $DIR/needless_pass_by_value.rs:72:29 | -77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -77 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +72 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -79 | let _ = t.to_string(); +74 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:77:40 + --> $DIR/needless_pass_by_value.rs:72:40 | -77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:77:53 + --> $DIR/needless_pass_by_value.rs:72:53 | -77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -77 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +72 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -81 | let _ = v.to_owned(); +76 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:89:12 + --> $DIR/needless_pass_by_value.rs:84:12 | -89 | s: String, +84 | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:90:12 + --> $DIR/needless_pass_by_value.rs:85:12 | -90 | t: String, +85 | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:102:13 - | -102 | _u: U, - | ^ help: consider taking a reference instead: `&U` + --> $DIR/needless_pass_by_value.rs:97:13 + | +97 | _u: U, + | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:103:13 - | -103 | _s: Self, - | ^^^^ help: consider taking a reference instead: `&Self` + --> $DIR/needless_pass_by_value.rs:98:13 + | +98 | _s: Self, + | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:125:24 + --> $DIR/needless_pass_by_value.rs:120:24 | -125 | fn bar_copy(x: u32, y: CopyWrapper) { +120 | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:118:1 | -123 | struct CopyWrapper(u32); +118 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:29 + --> $DIR/needless_pass_by_value.rs:126:29 | -131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:118:1 | -123 | struct CopyWrapper(u32); +118 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:45 + --> $DIR/needless_pass_by_value.rs:126:45 | -131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:118:1 | -123 | struct CopyWrapper(u32); +118 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -131 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { -132 | let CopyWrapper(s) = z; // moved -133 | let CopyWrapper(ref t) = *y; // not moved -134 | let CopyWrapper(_) = *y; // still not moved +126 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { +127 | let CopyWrapper(s) = z; // moved +128 | let CopyWrapper(ref t) = *y; // not moved +129 | let CopyWrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:61 + --> $DIR/needless_pass_by_value.rs:126:61 | -131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:118:1 | -123 | struct CopyWrapper(u32); +118 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -131 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { -132 | let CopyWrapper(s) = *z; // moved +126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { +127 | let CopyWrapper(s) = *z; // moved | error: aborting due to 20 previous errors diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 84ccd5d4620..c394469c17b 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -8,7 +8,7 @@ error: the loop variable `i` is only used to index `ns`. help: consider using an iterator | 8 | for in ns.iter().take(10).skip(3) { - | + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `ms`. --> $DIR/needless_range_loop.rs:29:14 @@ -18,7 +18,7 @@ error: the loop variable `i` is only used to index `ms`. help: consider using an iterator | 29 | for in &mut ms { - | + | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `ms`. --> $DIR/needless_range_loop.rs:35:14 @@ -28,7 +28,7 @@ error: the loop variable `i` is only used to index `ms`. help: consider using an iterator | 35 | for in &mut ms { - | + | ^^^^^^ ^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 28223563db1..4a6ff6fe6dc 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -8,7 +8,7 @@ error: needlessly taken reference of both operands help: use the values directly | 13 | let foo = 5 - 6; - | + | ^ ^ error: taken reference of right operand --> $DIR/op_ref.rs:21:8 -- cgit 1.4.1-3-g733a5 From ce229b2025117812caf4b9da062aca4c8b35240e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 29 May 2018 11:58:58 +0200 Subject: Version bump --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 1 + clippy_lints/src/redundant_field_names.rs | 10 +++++----- clippy_lints/src/write.rs | 2 +- min_version.txt | 6 +++--- 8 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0211c9c66..85488816bcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.206 +* Rustup to *rustc 1.28.0-nightly (5bf68db6e 2018-05-28)* + ## 0.0.205 * Rustup to *rustc 1.28.0-nightly (990d8aa74 2018-05-25)* * Rename `unused_lifetimes` to `extra_unused_lifetimes` because of naming conflict with new rustc lint @@ -778,6 +781,7 @@ All notable changes to this project will be documented in this file. [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern +[`ref_in_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ref_in_deref [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts [`result_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unit_fn diff --git a/Cargo.toml b/Cargo.toml index 9d49b89440e..db3ce525952 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.205" +version = "0.0.206" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -37,7 +37,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.205", path = "clippy_lints" } +clippy_lints = { version = "0.0.206", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/README.md b/README.md index 50661501477..5c90646bf9f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 259 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 260 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a02cad5b181..52c6e7706b1 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.205" +version = "0.0.206" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1e75d42dd61..01bfdc28c95 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -637,6 +637,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ranges::RANGE_ZIP_WITH_LEN, redundant_field_names::REDUNDANT_FIELD_NAMES, reference::DEREF_ADDROF, + reference::REF_IN_DEREF, regex::INVALID_REGEX, regex::REGEX_MACRO, regex::TRIVIAL_REGEX, diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index a0465f21105..11ee6024a89 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -4,20 +4,20 @@ use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. -/// +/// /// **Why is this bad?** If the field and variable names are the same, /// the field name is redundant. -/// +/// /// **Known problems:** None. -/// +/// /// **Example:** /// ```rust /// let bar: u8 = 123; -/// +/// /// struct Foo { /// bar: u8, /// } -/// +/// /// let foo = Foo{ bar: bar } /// ``` declare_clippy_lint! { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index fdd4f8ced9a..d54bbc88408 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -365,7 +365,7 @@ where then { if args.len() == 2 { lint_fn(tup_val.span); - } + } // ensure the format str has no options (e.g., width, precision, alignment, etc.) // and is just "{}" diff --git a/min_version.txt b/min_version.txt index 55f113ccd9d..6b2be5640c8 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (990d8aa74 2018-05-25) +rustc 1.28.0-nightly (5bf68db6e 2018-05-28) binary: rustc -commit-hash: 990d8aa743b1dda3cc0f68fe09524486261812c6 -commit-date: 2018-05-25 +commit-hash: 5bf68db6ecda0dd4788311a41b5c763d35597c96 +commit-date: 2018-05-28 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From f97c38de9427b43a9afce37debd7c46cd184869d Mon Sep 17 00:00:00 2001 From: Mikael Zayenz Lagerkvist Date: Tue, 29 May 2018 13:17:37 +0200 Subject: avoid op-ref in macros Avoid running op-ref inspection in macros since the macro may be invoked in many different types of contexts. Solves #2818 and incidentally avoids #2689. --- clippy_lints/src/eq_op.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index ca441aa9a93..af372cfcbef 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -53,7 +53,10 @@ impl LintPass for EqOp { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) && !in_macro(e.span) { + if in_macro(e.span) { + return; + } + if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { span_lint( cx, EQ_OP, -- cgit 1.4.1-3-g733a5 From a338fa9b9538cf8079d084db155feb03c6f88ce7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 29 May 2018 14:45:10 +0200 Subject: Fix dogfood --- clippy_lints/src/misc_early.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 9ff7bbe4aba..068febe1672 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -334,7 +334,7 @@ impl EarlyLintPass for MiscEarly { if let ExprKind::Call(ref closure, _) = call.node; if let ExprKind::Path(_, ref path) = closure.node; then { - if ident == (&path.segments[0]).ident { + if ident == path.segments[0].ident { span_lint( cx, REDUNDANT_CLOSURE_CALL, -- cgit 1.4.1-3-g733a5 From 3a41e0172c013d8e2842b05db91d5cb3c745590e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 29 May 2018 14:51:16 +0200 Subject: Remove unused define_conf-macro definitions --- clippy_lints/src/utils/conf.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 58e71705011..27b7bdaf85e 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -113,29 +113,6 @@ macro_rules! define_Conf { // hack to convert tts (TY $ty: ty) => { $ty }; - // how to read the value? - (CONV i64, $value: expr) => { $value.as_integer() }; - (CONV u64, $value: expr) => { - $value.as_integer() - .iter() - .filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }) - .next() - }; - (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; - (CONV Vec, $value: expr) => {{ - let slice = $value.as_array(); - - if let Some(slice) = slice { - if slice.iter().any(|v| v.as_str().is_none()) { - None - } else { - Some(slice.iter().map(|v| v.as_str().expect("already checked").to_owned()).collect()) - } - } else { - None - } - }}; - // provide a nicer syntax to declare the default value of `Vec` variables (DEFAULT Vec, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; (DEFAULT $ty: ty, $e: expr) => { $e }; -- cgit 1.4.1-3-g733a5 From f6e0388e089669e89e162f1040cde048d34f52a4 Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Tue, 29 May 2018 22:56:38 +0700 Subject: Change lint type to unique and add the suggestion. --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/types.rs | 28 ++++++++++++++++++++++++---- tests/ui/types_fn_to_int.stderr | 8 ++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efba3b69577..96fa907ecb4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -673,6 +673,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::UNIT_ARG, types::UNIT_CMP, types::UNNECESSARY_CAST, + types::FN_TO_NUMERIC_CAST, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, unused_io_amount::UNUSED_IO_AMOUNT, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f5cbcfb6b00..9c33b91789a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -679,6 +679,23 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } +/// **What it does:** Checks for casts function pointer to the numeric type. +/// +/// **Why is this bad?** Cast pointer not to usize truncate value. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn test_fn() -> i16; +/// let _ = test_fn as i32 +/// ``` +declare_clippy_lint! { + pub FN_TO_NUMERIC_CAST, + correctness, + "cast function pointer to the numeric type" +} + /// **What it does:** Checks for casts from a less-strictly-aligned pointer to a /// more-strictly-aligned pointer /// @@ -891,7 +908,8 @@ impl LintPass for CastPass { CAST_POSSIBLE_WRAP, CAST_LOSSLESS, UNNECESSARY_CAST, - CAST_PTR_ALIGNMENT + CAST_PTR_ALIGNMENT, + FN_TO_NUMERIC_CAST ) } } @@ -980,11 +998,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { ty::TyFnDef(..) | ty::TyFnPtr(..) => { if cast_to.is_numeric() && cast_to.sty != ty::TyUint(UintTy::Usize){ - span_lint( + span_lint_and_sugg( cx, - UNNECESSARY_CAST, + FN_TO_NUMERIC_CAST, expr.span, - "casting Fn not to usize may truncate the value", + &format!("casting a Fn to {} may truncate the function address value.", cast_to), + "if you need address of function, use cast to `usize` instead:", + format!("{} as usize", &snippet(cx, ex.span, "x")) ); } } diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index 519b7763386..8f0b2c64523 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -1,10 +1,14 @@ -error: casting Fn not to usize may truncate the value +error: casting a Fn to i32 may truncate the function address value. --> $DIR/types_fn_to_int.rs:8:13 | 8 | let y = x as i32; | ^^^^^^^^ | - = note: `-D unnecessary-cast` implied by `-D warnings` + = note: #[deny(fn_to_numeric_cast)] on by default +help: if you need address of function, use cast to `usize` instead: + | +8 | let y = x as usize; + | ^^^^^^^^^^ error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 2a606b522063533868d2f10da2d0b6f2fb7d0062 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Mon, 14 May 2018 12:24:31 -0500 Subject: Don't lint lifetime-only transmutes --- clippy_lints/src/transmute.rs | 39 +++++++++++++++++++++------------------ tests/ui/transmute.rs | 8 +++++++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 4ee0a77f549..cd9f5f75471 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -192,7 +192,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub TRANSMUTE_PTR_TO_PTR, complexity, - "transmutes from a pointer to a reference type" + "transmutes from a pointer to a pointer / a reference to a reference" } pub struct Transmute; @@ -363,23 +363,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } ) } else { - span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_PTR, - e.span, - "transmute from a reference to a reference", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, mutbl: from_mutbl }; - let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl }; - let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(ty_from_and_mut)).as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); - let sugg = if to_mutbl == Mutability::MutMutable { - sugg_paren.mut_addr_deref() - } else { - sugg_paren.addr_deref() - }; - db.span_suggestion(e.span, "try", sugg.to_string()); - }, - ) + // In this case they differ only in lifetime + if ty_from != ty_to { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a reference to a reference", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, mutbl: from_mutbl }; + let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl }; + let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(ty_from_and_mut)).as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + let sugg = if to_mutbl == Mutability::MutMutable { + sugg_paren.mut_addr_deref() + } else { + sugg_paren.addr_deref() + }; + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ) + } } } }, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 7c5e3f03d13..ff389ad20a8 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -152,11 +152,17 @@ fn transmute_ptr_to_ptr() { let _: &f32 = std::mem::transmute(&1u32); let _: &mut f32 = std::mem::transmute(&mut 1u32); } - // These should be fine + // These should be fine: + // Recommendations for solving the above; if these break we need to update + // those suggestions let _ = ptr as *const f32; let _ = mut_ptr as *mut f32; let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; + // This is just modifying the lifetime, and is one of the recommended uses + // of transmute + let n = 1u32; + let _ = unsafe { std::mem::transmute::<&'_ u32, &'static u32>(&n) }; } fn main() { } -- cgit 1.4.1-3-g733a5 From 96b11a58887cbfb4b7b249d27228d49cc494fdfa Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Tue, 22 May 2018 17:18:56 -0700 Subject: Test that we allow non-static lifetime transmutes --- tests/ui/transmute.rs | 19 +++++++++++++++---- tests/ui/transmute.stderr | 16 ++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index ff389ad20a8..17740d50afe 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -140,6 +140,21 @@ fn bytes_to_str(b: &[u8], mb: &mut [u8]) { let _: &mut str = unsafe { std::mem::transmute(mb) }; } +// Make sure we can modify lifetimes, which is one of the recommended uses +// of transmute + +// Make sure we can do static lifetime transmutes +#[warn(transmute_ptr_to_ptr)] +unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T { + std::mem::transmute::<&'a T, &'static T>(t) +} + +// Make sure we can do non-static lifetime transmutes +#[warn(transmute_ptr_to_ptr)] +unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T { + std::mem::transmute::<&'a T, &'b T>(t) +} + #[warn(transmute_ptr_to_ptr)] fn transmute_ptr_to_ptr() { let ptr = &1u32 as *const u32; @@ -159,10 +174,6 @@ fn transmute_ptr_to_ptr() { let _ = mut_ptr as *mut f32; let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; - // This is just modifying the lifetime, and is one of the recommended uses - // of transmute - let n = 1u32; - let _ = unsafe { std::mem::transmute::<&'_ u32, &'static u32>(&n) }; } fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index a343a8a9cb5..3685e3ea2bf 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -205,29 +205,29 @@ error: transmute from a `&mut [u8]` to a `&mut str` | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:149:29 + --> $DIR/transmute.rs:164:29 | -149 | let _: *const f32 = std::mem::transmute(ptr); +164 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | = note: `-D transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:150:27 + --> $DIR/transmute.rs:165:27 | -150 | let _: *mut f32 = std::mem::transmute(mut_ptr); +165 | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:152:23 + --> $DIR/transmute.rs:167:23 | -152 | let _: &f32 = std::mem::transmute(&1u32); +167 | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:153:27 + --> $DIR/transmute.rs:168:27 | -153 | let _: &mut f32 = std::mem::transmute(&mut 1u32); +168 | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: aborting due to 36 previous errors -- cgit 1.4.1-3-g733a5 From 8134863c13c13d790a30bc9998693d3f3ea7f23d Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 24 May 2018 20:02:42 -0700 Subject: Fix behavior with generic lifetime parameters --- clippy_lints/src/transmute.rs | 48 ++++++++++++++++++++++++++++++++++++++++--- tests/ui/transmute.rs | 24 ++++++++++++++++++++-- tests/ui/transmute.stderr | 30 +++++++++++++++++++-------- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index cd9f5f75471..8d14576767f 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,7 +1,8 @@ use rustc::lint::*; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Ty, walk::TypeWalker}; use rustc::hir::*; use std::borrow::Cow; +use std::mem; use syntax::ast; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::{opt_def_id, sugg}; @@ -363,8 +364,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } ) } else { - // In this case they differ only in lifetime - if ty_from != ty_to { + if !differ_only_in_lifetime_params(from_ty, to_ty) { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, @@ -448,6 +448,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } +/// Returns true if `type1` and `type2` are the same type except for their lifetime parameters +fn differ_only_in_lifetime_params(type1: Ty, type2: Ty) -> bool { + use rustc::ty::TypeVariants::*; + if TypeWalker::new(type1).count() != TypeWalker::new(type2).count() { + return false; + } + TypeWalker::new(type1) + .zip(TypeWalker::new(type2)) + .all(|(t1, t2)| { + match (&t1.sty, &t2.sty) { + // types with generic parameters which can contain lifetimes + (TyAdt(_, sub1), TyAdt(_, sub2)) + | (TyFnDef(_, sub1), TyFnDef(_, sub2)) + | (TyAnon(_, sub1), TyAnon(_, sub2)) + => { + // Iterate over generic parameters, which are either Lifetimes or Types. + // Here we only need to check that they are the same type of thing, because + // if they are both Lifetimes then we don't care about their equality, and if + // they are both Types, we will check their equality later in the type walk. + sub1.iter().count() == sub2.iter().count() + && sub1.iter().zip(sub2.iter()).all(|(k1, k2)| { + mem::discriminant(&k1.unpack()) == mem::discriminant(&k2.unpack()) + }) + } + // types without subtypes: check that the types are equal + (TyBool, TyBool) + | (TyChar, TyChar) + | (TyInt(_), TyInt(_)) + | (TyUint(_), TyUint(_)) + | (TyFloat(_), TyFloat(_)) + | (TyForeign(_), TyForeign(_)) + | (TyStr, TyStr) + | (TyNever, TyNever) + | (TyInfer(_), TyInfer(_)) + => t1.sty == t2.sty, + // types with subtypes: return true for now if they are the same sort of type. + // we will check their subtypes later + (sty1, sty2) => mem::discriminant(sty1) == mem::discriminant(sty2) + } + }) +} + /// Get the snippet of `Bar` in `…::transmute`. If that snippet is /// not available , use /// the type's `ToString` implementation. In weird cases it could lead to types diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 17740d50afe..54e1734e141 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -155,6 +155,14 @@ unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T { std::mem::transmute::<&'a T, &'b T>(t) } +struct LifetimeParam<'a> { + s: &'a str, +} + +struct GenericParam { + t: T, +} + #[warn(transmute_ptr_to_ptr)] fn transmute_ptr_to_ptr() { let ptr = &1u32 as *const u32; @@ -165,15 +173,27 @@ fn transmute_ptr_to_ptr() { let _: *mut f32 = std::mem::transmute(mut_ptr); // ref-ref transmutes; bad let _: &f32 = std::mem::transmute(&1u32); + let _: &f64 = std::mem::transmute(&1f32); + // ^ this test is here because both f32 and f64 are the same TypeVariant, but they are not + // the same type let _: &mut f32 = std::mem::transmute(&mut 1u32); + let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); } - // These should be fine: - // Recommendations for solving the above; if these break we need to update + + // these are recommendations for solving the above; if these lint we need to update // those suggestions let _ = ptr as *const f32; let _ = mut_ptr as *mut f32; let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; + + // transmute internal lifetimes, should not lint + let s = "hello world".to_owned(); + let lp = LifetimeParam { s: &s }; + let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) }; + let _: &GenericParam<&LifetimeParam<'static>> = unsafe { + std::mem::transmute(&GenericParam { t: &lp}) + }; } fn main() { } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 3685e3ea2bf..abed5065c0a 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -205,30 +205,42 @@ error: transmute from a `&mut [u8]` to a `&mut str` | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:164:29 + --> $DIR/transmute.rs:172:29 | -164 | let _: *const f32 = std::mem::transmute(ptr); +172 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | = note: `-D transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:165:27 + --> $DIR/transmute.rs:173:27 | -165 | let _: *mut f32 = std::mem::transmute(mut_ptr); +173 | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:167:23 + --> $DIR/transmute.rs:175:23 | -167 | let _: &f32 = std::mem::transmute(&1u32); +175 | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:168:27 + --> $DIR/transmute.rs:176:23 | -168 | let _: &mut f32 = std::mem::transmute(&mut 1u32); +176 | let _: &f64 = std::mem::transmute(&1f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` + +error: transmute from a reference to a reference + --> $DIR/transmute.rs:179:27 + | +179 | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` -error: aborting due to 36 previous errors +error: transmute from a reference to a reference + --> $DIR/transmute.rs:180:37 + | +180 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` + +error: aborting due to 38 previous errors -- cgit 1.4.1-3-g733a5 From 9118cd633e177be88a32f2017c98af71fe2080bf Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Mon, 28 May 2018 22:12:42 -0700 Subject: Simplify lifetime-differences-only detection Now instead of reinventing the wheel with differ_only_in_lifetimes(), we use TyCtxt's erase_regions() --- clippy_lints/src/transmute.rs | 47 ++----------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 8d14576767f..21debc347d0 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,8 +1,7 @@ use rustc::lint::*; -use rustc::ty::{self, Ty, walk::TypeWalker}; +use rustc::ty::{self, Ty}; use rustc::hir::*; use std::borrow::Cow; -use std::mem; use syntax::ast; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::{opt_def_id, sugg}; @@ -364,7 +363,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } ) } else { - if !differ_only_in_lifetime_params(from_ty, to_ty) { + if cx.tcx.erase_regions(&from_ty) != cx.tcx.erase_regions(&to_ty) { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, @@ -448,48 +447,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } -/// Returns true if `type1` and `type2` are the same type except for their lifetime parameters -fn differ_only_in_lifetime_params(type1: Ty, type2: Ty) -> bool { - use rustc::ty::TypeVariants::*; - if TypeWalker::new(type1).count() != TypeWalker::new(type2).count() { - return false; - } - TypeWalker::new(type1) - .zip(TypeWalker::new(type2)) - .all(|(t1, t2)| { - match (&t1.sty, &t2.sty) { - // types with generic parameters which can contain lifetimes - (TyAdt(_, sub1), TyAdt(_, sub2)) - | (TyFnDef(_, sub1), TyFnDef(_, sub2)) - | (TyAnon(_, sub1), TyAnon(_, sub2)) - => { - // Iterate over generic parameters, which are either Lifetimes or Types. - // Here we only need to check that they are the same type of thing, because - // if they are both Lifetimes then we don't care about their equality, and if - // they are both Types, we will check their equality later in the type walk. - sub1.iter().count() == sub2.iter().count() - && sub1.iter().zip(sub2.iter()).all(|(k1, k2)| { - mem::discriminant(&k1.unpack()) == mem::discriminant(&k2.unpack()) - }) - } - // types without subtypes: check that the types are equal - (TyBool, TyBool) - | (TyChar, TyChar) - | (TyInt(_), TyInt(_)) - | (TyUint(_), TyUint(_)) - | (TyFloat(_), TyFloat(_)) - | (TyForeign(_), TyForeign(_)) - | (TyStr, TyStr) - | (TyNever, TyNever) - | (TyInfer(_), TyInfer(_)) - => t1.sty == t2.sty, - // types with subtypes: return true for now if they are the same sort of type. - // we will check their subtypes later - (sty1, sty2) => mem::discriminant(sty1) == mem::discriminant(sty2) - } - }) -} - /// Get the snippet of `Bar` in `…::transmute`. If that snippet is /// not available , use /// the type's `ToString` implementation. In weird cases it could lead to types -- cgit 1.4.1-3-g733a5 From 44f4ea6dbf4039e0d837370b598cb8413043ea9b Mon Sep 17 00:00:00 2001 From: François Mockers Date: Tue, 29 May 2018 02:17:55 +0200 Subject: adding to pedantic a lint that check for multiple inherent implementations --- clippy_lints/src/inherent_impl.rs | 95 +++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ tests/ui/impl.rs | 36 +++++++++++++++ tests/ui/impl.stderr | 35 +++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 clippy_lints/src/inherent_impl.rs create mode 100644 tests/ui/impl.rs create mode 100644 tests/ui/impl.stderr diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs new file mode 100644 index 00000000000..fb01f46949d --- /dev/null +++ b/clippy_lints/src/inherent_impl.rs @@ -0,0 +1,95 @@ +//! lint on inherent implementations + +use rustc::hir::*; +use rustc::lint::*; +use std::collections::HashMap; +use std::default::Default; +use syntax_pos::Span; + +/// **What it does:** Checks for multiple inherent implementations of a struct +/// +/// **Why is this bad?** Splitting the implementation of a type makes the code harder to navigate. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// struct X; +/// impl X { +/// fn one() {} +/// } +/// impl X { +/// fn other() {} +/// } +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// struct X; +/// impl X { +/// fn one() {} +/// fn other() {} +/// } +/// ``` +declare_clippy_lint! { + pub MULTIPLE_INHERENT_IMPL, + pedantic, + "Multiple inherent impl that could be grouped" +} + +pub struct Pass { + impls: HashMap, +} + +impl Default for Pass { + fn default() -> Self { + Pass { impls: HashMap::new() } + } +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(MULTIPLE_INHERENT_IMPL) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if let Item_::ItemImpl(_, _, _, ref generics, None, _, _) = item.node { + // Remember for each inherent implementation encoutered its span and generics + self.impls + .insert(item.hir_id.owner_def_id(), (item.span, generics.clone())); + } + } + + fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx Crate) { + if let Some(item) = krate.items.values().nth(0) { + // Retrieve all inherent implementations from the crate, grouped by type + for impls in cx + .tcx + .crate_inherent_impls(item.hir_id.owner_def_id().krate) + .inherent_impls + .values() + { + // Filter out implementations that have generic params (type or lifetime) + let mut impl_spans = impls + .iter() + .filter_map(|impl_def| self.impls.get(impl_def)) + .filter(|(_, generics)| generics.params.len() == 0) + .map(|(span, _)| span); + if let Some(initial_span) = impl_spans.nth(0) { + impl_spans.for_each(|additional_span| { + cx.span_lint_note( + MULTIPLE_INHERENT_IMPL, + *additional_span, + "Multiple implementations of this structure", + *initial_span, + "First implementation here", + ) + }) + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 01bfdc28c95..3b00e4fba48 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -138,6 +138,7 @@ pub mod if_let_redundant_pattern_matching; pub mod if_not_else; pub mod infallible_destructuring_match; pub mod infinite_iter; +pub mod inherent_impl; pub mod inline_fn_without_body; pub mod int_plus_one; pub mod invalid_ref; @@ -416,6 +417,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box multiple_crate_versions::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_late_lint_pass(box infallible_destructuring_match::Pass); + reg.register_late_lint_pass(box inherent_impl::Pass::default()); reg.register_lint_group("clippy_restriction", vec![ @@ -452,6 +454,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, + inherent_impl::MULTIPLE_INHERENT_IMPL, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs new file mode 100644 index 00000000000..9e10dbade4e --- /dev/null +++ b/tests/ui/impl.rs @@ -0,0 +1,36 @@ +#![allow(dead_code)] +#![warn(multiple_inherent_impl)] + +struct MyStruct; + +impl MyStruct { + fn first() {} +} + +impl MyStruct { + fn second() {} +} + +impl<'a> MyStruct { + fn lifetimed() {} +} + +mod submod { + struct MyStruct; + impl MyStruct { + fn other() {} + } + + impl super::MyStruct { + fn third() {} + } +} + +use std::fmt; +impl fmt::Debug for MyStruct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "MyStruct {{ }}") + } +} + +fn main() {} diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr new file mode 100644 index 00000000000..95e627cd509 --- /dev/null +++ b/tests/ui/impl.stderr @@ -0,0 +1,35 @@ +error: Multiple implementations of this structure + --> $DIR/impl.rs:10:1 + | +10 | / impl MyStruct { +11 | | fn second() {} +12 | | } + | |_^ + | + = note: `-D multiple-inherent-impl` implied by `-D warnings` +note: First implementation here + --> $DIR/impl.rs:6:1 + | +6 | / impl MyStruct { +7 | | fn first() {} +8 | | } + | |_^ + +error: Multiple implementations of this structure + --> $DIR/impl.rs:24:5 + | +24 | / impl super::MyStruct { +25 | | fn third() {} +26 | | } + | |_____^ + | +note: First implementation here + --> $DIR/impl.rs:6:1 + | +6 | / impl MyStruct { +7 | | fn first() {} +8 | | } + | |_^ + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 6a7204f32a288cfe4913d53c762efaccecf372c3 Mon Sep 17 00:00:00 2001 From: François Mockers Date: Tue, 29 May 2018 03:27:53 +0200 Subject: only install remark if not on an integration build to avoid ddosing npm --- .travis.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2d7d46abca3..1e5544b2ed7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,10 +24,13 @@ before_install: fi install: - - . $HOME/.nvm/nvm.sh - - nvm install stable - - nvm use stable - - npm install remark-cli remark-lint + - | + if [ -z ${INTEGRATION} ]; then + . $HOME/.nvm/nvm.sh + nvm install stable + nvm use stable + npm install remark-cli remark-lint + fi matrix: include: -- cgit 1.4.1-3-g733a5 From d372f1674d4b7bdd7f265154de997f7e8aa8fed2 Mon Sep 17 00:00:00 2001 From: François Mockers Date: Tue, 29 May 2018 10:19:16 +0200 Subject: move lint to restriction group --- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index fb01f46949d..637ea917a8f 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -34,7 +34,7 @@ use syntax_pos::Span; /// ``` declare_clippy_lint! { pub MULTIPLE_INHERENT_IMPL, - pedantic, + restriction, "Multiple inherent impl that could be grouped" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3b00e4fba48..d979d7afd11 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -426,6 +426,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, + inherent_impl::MULTIPLE_INHERENT_IMPL, literal_representation::DECIMAL_LITERAL_REPRESENTATION, mem_forget::MEM_FORGET, methods::CLONE_ON_REF_PTR, @@ -454,7 +455,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, - inherent_impl::MULTIPLE_INHERENT_IMPL, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, -- cgit 1.4.1-3-g733a5 From e4b2a97401f0139751f926fd1479898494b20a80 Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Wed, 30 May 2018 07:55:48 +0700 Subject: weird thing --- clippy_lints/src/types.rs | 5 +++-- tests/ui/types_fn_to_int.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9c33b91789a..940a360ca18 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1002,8 +1002,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { cx, FN_TO_NUMERIC_CAST, expr.span, - &format!("casting a Fn to {} may truncate the function address value.", cast_to), - "if you need address of function, use cast to `usize` instead:", + &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), + // &format!("if you need address of function, use cast zz `usize`:"), + &format!("if you need the address of the function, z consider:"), format!("{} as usize", &snippet(cx, ex.span, "x")) ); } diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs index fadedcef9f2..f37a82f0d71 100644 --- a/tests/ui/types_fn_to_int.rs +++ b/tests/ui/types_fn_to_int.rs @@ -3,7 +3,16 @@ enum Foo { B } +fn bar() -> i32 { + 0i32 +} + fn main() { let x = Foo::A; let y = x as i32; + + let z = bar as u32; + + //let c = || {0i32}; + //let ac = c as u32; } -- cgit 1.4.1-3-g733a5 From b69520f5fd1309741445fe069edca9e4b1e6d48c Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Wed, 30 May 2018 11:48:46 +0700 Subject: Fixes for suggestion message, tests and lint explanation. --- clippy_lints/src/types.rs | 7 +++---- tests/ui/types_fn_to_int.rs | 3 --- tests/ui/types_fn_to_int.stderr | 34 ++++++++++++++++++++++------------ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 940a360ca18..fc65ebcc147 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -679,9 +679,9 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } -/// **What it does:** Checks for casts function pointer to the numeric type. +/// **What it does:** Checks for casts of a function pointer to a numeric type except `usize`. /// -/// **Why is this bad?** Cast pointer not to usize truncate value. +/// **Why is this bad?** Casting a function pointer to something other than `usize` could truncate the address value. /// /// **Known problems:** None. /// @@ -1003,8 +1003,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { FN_TO_NUMERIC_CAST, expr.span, &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), - // &format!("if you need address of function, use cast zz `usize`:"), - &format!("if you need the address of the function, z consider:"), + "if you need the address of the function, consider :", format!("{} as usize", &snippet(cx, ex.span, "x")) ); } diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs index f37a82f0d71..0cce6579813 100644 --- a/tests/ui/types_fn_to_int.rs +++ b/tests/ui/types_fn_to_int.rs @@ -12,7 +12,4 @@ fn main() { let y = x as i32; let z = bar as u32; - - //let c = || {0i32}; - //let ac = c as u32; } diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index 8f0b2c64523..d5e8ad8bbb2 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -1,14 +1,24 @@ -error: casting a Fn to i32 may truncate the function address value. - --> $DIR/types_fn_to_int.rs:8:13 - | -8 | let y = x as i32; - | ^^^^^^^^ - | - = note: #[deny(fn_to_numeric_cast)] on by default -help: if you need address of function, use cast to `usize` instead: - | -8 | let y = x as usize; - | ^^^^^^^^^^ +error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. + --> $DIR/types_fn_to_int.rs:12:13 + | +12 | let y = x as i32; + | ^^^^^^^^ + | + = note: #[deny(fn_to_numeric_cast)] on by default +help: if you need the address of the function, consider : + | +12 | let y = x as usize; + | ^^^^^^^^^^ -error: aborting due to previous error +error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. + --> $DIR/types_fn_to_int.rs:14:13 + | +14 | let z = bar as u32; + | ^^^^^^^^^^ +help: if you need the address of the function, consider : + | +14 | let z = bar as usize; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 26f3feb9809953740c9883c3cf8ea60734093b06 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Wed, 30 May 2018 10:05:06 +0200 Subject: Add rust_2018_preview feature and fix rustfmt annotation --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/new_without_default.rs | 2 +- src/lib.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1e75d42dd61..07f66f84b18 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,6 +11,7 @@ #![allow(stable_features)] #![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] +#![feature(rust_2018_preview)] extern crate cargo_metadata; #[macro_use] diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 54b00081973..a6a63e6aa05 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } fn create_new_without_default_suggest_msg(ty: Ty) -> String { - #[rustfmt_skip] + #[cfg_attr(rustfmt, rustfmt_skip)] format!( "impl Default for {} {{ fn default() -> Self {{ diff --git a/src/lib.rs b/src/lib.rs index 193be97161f..61e5c104bef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] +#![feature(rust_2018_preview)] #![feature(rustc_private)] #![feature(macro_vis_matcher)] #![allow(unknown_lints)] -- cgit 1.4.1-3-g733a5 From 424a33720d61e1cdc0f8886000d4549857a6ee55 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Wed, 30 May 2018 10:15:50 +0200 Subject: Run rustfix --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/array_indexing.rs | 6 +++--- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/bit_mask.rs | 6 +++--- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/collapsible_if.rs | 4 ++-- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/copies.rs | 4 ++-- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/entry.rs | 4 ++-- clippy_lints/src/enum_clike.rs | 4 ++-- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 4 ++-- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/erasing_op.rs | 4 ++-- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/explicit_write.rs | 4 ++-- clippy_lints/src/fallible_impl_from.rs | 4 ++-- clippy_lints/src/format.rs | 4 ++-- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/identity_conversion.rs | 4 ++-- clippy_lints/src/identity_op.rs | 4 ++-- .../src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 4 ++-- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/invalid_ref.rs | 2 +- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/literal_representation.rs | 2 +- clippy_lints/src/loops.rs | 10 +++++----- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 4 ++-- clippy_lints/src/matches.rs | 8 ++++---- clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 8 ++++---- clippy_lints/src/minmax.rs | 4 ++-- clippy_lints/src/misc.rs | 8 ++++---- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_bool.rs | 4 ++-- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 4 ++-- clippy_lints/src/needless_update.rs | 2 +- clippy_lints/src/neg_multiply.rs | 4 ++-- clippy_lints/src/new_without_default.rs | 6 +++--- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- clippy_lints/src/overflow_check_conditional.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/precedence.rs | 2 +- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/question_mark.rs | 6 +++--- clippy_lints/src/ranges.rs | 8 ++++---- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 4 ++-- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/strings.rs | 6 +++--- clippy_lints/src/suspicious_trait_impl.rs | 4 ++-- clippy_lints/src/swap.rs | 4 ++-- clippy_lints/src/temporary_assignment.rs | 4 ++-- clippy_lints/src/transmute.rs | 4 ++-- clippy_lints/src/types.rs | 22 +++++++++++----------- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/conf.rs | 4 ++-- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 4 ++-- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 2 +- clippy_lints/src/vec.rs | 4 ++-- clippy_lints/src/write.rs | 4 ++-- clippy_lints/src/zero_div_zero.rs | 4 ++-- 112 files changed, 182 insertions(+), 182 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 20b9c279277..704546a1eb3 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 835555f42f8..ff32fcb7843 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use syntax::codemap::Span; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for plain integer arithmetic. /// diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 010f07ab8d2..6002960fe2c 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,10 +1,10 @@ -use consts::{constant, Constant}; +use crate::consts::{constant, Constant}; use rustc::hir; use rustc::lint::*; use rustc::ty; use syntax::ast::RangeLimits; -use utils::higher::Range; -use utils::{self, higher}; +use crate::utils::higher::Range; +use crate::utils::{self, higher}; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index fae2897762e..44398a9710f 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -2,8 +2,8 @@ use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::ast; -use utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; -use utils::{higher, sugg}; +use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; +use crate::utils::{higher, sugg}; /// **What it does:** Checks for compound assignment operations (`+=` and /// similar). @@ -145,7 +145,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { $($trait_name:ident:$full_trait_name:ident),+) => { match $op { $(hir::$full_trait_name => { - let [krate, module] = ::utils::paths::OPS_MODULE; + let [krate, module] = crate::utils::paths::OPS_MODULE; let path = [krate, module, concat!(stringify!($trait_name), "Assign")]; let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { trait_id diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 936b5e75ff6..04ef9d00215 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,13 +1,13 @@ //! checks for attributes -use reexport::*; +use crate::reexport::*; use rustc::hir::*; use rustc::lint::*; use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{ +use crate::utils::{ in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, without_block_comments, }; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 4f38fb92831..f77b61bf280 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -2,9 +2,9 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::Span; -use utils::{span_lint, span_lint_and_then}; -use utils::sugg::Sugg; -use consts::{constant, Constant}; +use crate::utils::{span_lint, span_lint_and_then}; +use crate::utils::sugg::Sugg; +use crate::consts::{constant, Constant}; /// **What it does:** Checks for incompatible bit masks in comparisons. /// diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index d06e1240b06..f1e8be4dba9 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for usage of blacklisted names for variables, such /// as `foo`. diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 5db217d8228..5f484341186 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use utils::*; +use crate::utils::*; /// **What it does:** Checks for `if` conditions that use blocks to contain an /// expression. diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index c8478c47a35..c814c1abcd1 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; use syntax::util::ThinVec; -use utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq}; +use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 0c024d2bd05..165c46164bb 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; use syntax::ast::{Name, UintTy}; -use utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, +use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for naive byte counts diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 240623475c8..786148f6eec 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -15,8 +15,8 @@ use rustc::lint::*; use syntax::ast; -use utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; -use utils::sugg::Sugg; +use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; +use crate::utils::sugg::Sugg; /// **What it does:** Checks for nested `if` statements which can be collapsed /// by `&&`-combining their conditions and for `else { if ... }` expressions diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 2ff7fa9e3ab..bde5ee4dc8b 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,6 +1,6 @@ use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use utils::{in_macro, snippet, span_lint_and_then}; +use crate::utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d02836441e1..c700af1e6e3 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -14,7 +14,7 @@ use std::rc::Rc; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; use rustc::middle::const_val::ConstVal; -use utils::{sext, unsext, clip}; +use crate::utils::{sext, unsext, clip}; #[derive(Debug, Copy, Clone)] pub enum FloatWidth { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 80601fa92fa..abbc4681166 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -5,8 +5,8 @@ use std::collections::HashMap; use std::collections::hash_map::Entry; use syntax::symbol::LocalInternedString; use syntax::util::small_vector::SmallVector; -use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; +use crate::utils::{SpanlessEq, SpanlessHash}; +use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for consecutive `if`s with the same condition. /// diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 139936554a1..ea5f5cf9b58 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -8,7 +8,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, NodeId}; use syntax::codemap::Span; -use utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; +use crate::utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; /// **What it does:** Checks for methods with high cyclomatic complexity. /// diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 0c544c69d09..364c019c486 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; -use utils::paths; -use utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; +use crate::utils::paths; +use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly or vice versa. diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 7d3e812c9c5..dfd59af9adb 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast; use syntax::codemap::{BytePos, Span}; use syntax_pos::Pos; -use utils::span_lint; +use crate::utils::span_lint; use url::Url; /// **What it does:** Checks for the presence of `_`, `::` or camel-case words diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 1ccc5708185..ba398c82064 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Span; -use utils::{snippet, span_lint_and_sugg, SpanlessEq}; +use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; /// **What it does:** Checks for double comparions that could be simpified to a single expression. /// diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 007accc7fbf..eb271a899c4 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; +use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index bceed1c2168..96c215df405 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{in_external_macro, span_lint_and_sugg}; +use crate::utils::{in_external_macro, span_lint_and_sugg}; /// **What it does:** Checks for usage of if expressions with an `else if` branch, /// but without a final `else` branch. diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 1641c4d444b..3265338ce12 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::span_lint_and_then; +use crate::utils::span_lint_and_then; /// **What it does:** Checks for `enum`s with no variants. /// diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index a85b26f7a6a..24e1b2d8387 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -2,8 +2,8 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::codemap::Span; -use utils::SpanlessEq; -use utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; +use crate::utils::SpanlessEq; +use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap` /// or `BTreeMap`. diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 37c0e1ef0c1..f191150f3e7 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -6,8 +6,8 @@ use rustc::hir::*; use rustc::ty; use rustc::ty::subst::Substs; use syntax::ast::{IntTy, UintTy}; -use utils::span_lint; -use consts::{Constant, miri_to_const}; +use crate::utils::span_lint; +use crate::consts::{Constant, miri_to_const}; use rustc::ty::util::IntTypeExt; use rustc::mir::interpret::GlobalId; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 0718a6b3679..943a5406b54 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -5,7 +5,7 @@ use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use syntax::ast::NodeId; use syntax::codemap::Span; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for `use Enum::*`. /// diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 163a9a0474f..f11edbeefa3 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -4,8 +4,8 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; -use utils::{span_help_and_lint, span_lint}; -use utils::{camel_case_from, camel_case_until, in_macro}; +use crate::utils::{span_help_and_lint, span_lint}; +use crate::utils::{camel_case_from, camel_case_until, in_macro}; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index ca441aa9a93..51b64afa6ea 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; +use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index ae6e078ddae..faf297fd5b2 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,8 +1,8 @@ -use consts::{constant_simple, Constant}; +use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Span; -use utils::{in_macro, span_lint}; +use crate::utils::{in_macro, span_lint}; /// **What it does:** Checks for erasing operations, e.g. `x * 0`. /// diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 795ef2f9925..9482c3782d4 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -9,7 +9,7 @@ use rustc::ty::layout::LayoutOf; use rustc::util::nodemap::NodeSet; use syntax::ast::NodeId; use syntax::codemap::Span; -use utils::span_lint; +use crate::utils::span_lint; pub struct Pass { pub too_large_for_stack: u64, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index cb1122486f3..30ea9f2446a 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; +use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; #[allow(missing_copy_implementations)] pub struct EtaPass; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d034104a609..e58dbdd2289 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::ty; use rustc::lint::*; use syntax::ast; -use utils::{get_parent_expr, span_lint, span_note_and_lint}; +use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; /// **What it does:** Checks for a read and a write to the same variable where /// whether the read occurs before or after the write depends on the evaluation diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 553476f63c9..9915c87c407 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -6,7 +6,7 @@ use std::f64; use std::fmt; use syntax::ast::*; use syntax_pos::symbol::Symbol; -use utils::span_lint_and_sugg; +use crate::utils::span_lint_and_sugg; /// **What it does:** Checks for float literals with a precision greater /// than that supported by the underlying type diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index bad5bbd8422..feff746ba0c 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{is_expn_of, match_def_path, resolve_node, span_lint}; -use utils::opt_def_id; +use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; +use crate::utils::opt_def_id; /// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be /// replaced with `(e)print!()` / `(e)println!()` diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index dd37a6725d2..33611a90c4d 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir; use rustc::ty; use syntax_pos::Span; -use utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of}; -use utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; +use crate::utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of}; +use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` /// diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index f418681cfb2..072b68d6beb 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -3,8 +3,8 @@ use rustc::lint::*; use rustc::ty; use syntax::ast::LitKind; use syntax_pos::Span; -use utils::paths; -use utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; +use crate::utils::paths; +use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 1ab13a825da..8008bb3ed66 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::ast; -use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; +use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use syntax::ptr::P; /// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 83c9c0f1d1a..536f4dd4772 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -7,7 +7,7 @@ use std::collections::HashSet; use syntax::ast; use rustc_target::spec::abi::Abi; use syntax::codemap::Span; -use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; +use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// **What it does:** Checks for functions with too many parameters. /// diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 8132ce73944..d8b8e8f073b 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,8 +1,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::NodeId; -use utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; -use utils::{opt_def_id, paths, resolve_node}; +use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; +use crate::utils::{opt_def_id, paths, resolve_node}; /// **What it does:** Checks for always-identical `Into`/`From` conversions. /// diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 24e5f823a35..e983e5746a1 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,8 +1,8 @@ -use consts::{constant_simple, Constant}; +use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Span; -use utils::{in_macro, snippet, span_lint, unsext, clip}; +use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; use rustc::ty; /// **What it does:** Checks for identity operations, e.g. `x + 0`. diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 2465c5351bd..63b4a2b2837 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{match_qpath, paths, snippet, span_lint_and_then}; +use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; /// **What it does:*** Lint for redundant pattern matching over `Result` or /// `Option` diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index ea264bf5186..22ca1a61c9b 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{in_external_macro, span_help_and_lint}; +use crate::utils::{in_external_macro, span_help_and_lint}; /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an /// else branch. diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index c1ae714b115..cb31c1cd044 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; +use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 34196a1728f..ab50ea6f131 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -3,8 +3,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::{Attribute, Name}; -use utils::span_lint_and_then; -use utils::sugg::DiagnosticBuilderExt; +use crate::utils::span_lint_and_then; +use crate::utils::sugg::DiagnosticBuilderExt; /// **What it does:** Checks for `#[inline]` on trait methods without bodies /// diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 42fb8440ac8..8daf3d296c7 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{snippet_opt, span_lint_and_then}; +use crate::utils::{snippet_opt, span_lint_and_then}; /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block /// diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 037f07be1d7..0ebdda9ec88 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; +use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. /// diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index f39f60f079c..685c91c0457 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use syntax::ast::*; -use utils::{in_macro, span_lint}; +use crate::utils::{in_macro, span_lint}; /// **What it does:** Checks for items declared after some statement in a block. /// diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index fd3d9714b86..ca136f06aec 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then}; +use crate::utils::{snippet_opt, span_lint_and_then}; use rustc::ty::layout::LayoutOf; /// **What it does:** Checks for large size differences between variants on diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 09b3da1e99c..fe9eb2e2d38 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -5,7 +5,7 @@ use rustc::ty; use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; -use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for getting the length of something via `.len()` /// just to compare to zero, and suggests using `.is_empty()` where applicable. diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index df7a1f29637..b114a285f97 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::BindingAnnotation; use rustc::hir::def::Def; use syntax::ast; -use utils::{snippet, span_lint_and_then}; +use crate::utils::{snippet, span_lint_and_then}; /// **What it does:** Checks for variable declarations immediately followed by a /// conditional affectation. diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 3804823ae5a..42f8da7c96c 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,11 +1,11 @@ -use reexport::*; +use crate::reexport::*; use rustc::lint::*; use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::*; use std::collections::{HashMap, HashSet}; use syntax::codemap::Span; -use utils::{in_external_macro, last_path_segment, span_lint}; +use crate::utils::{in_external_macro, last_path_segment, span_lint}; use syntax::symbol::keywords; /// **What it does:** Checks for lifetime annotations which can be removed by diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 6c2351d43dd..61b3e7a139c 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax_pos; -use utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; +use crate::utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index c8f1d3edaeb..4d312b79818 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use reexport::*; +use crate::reexport::*; use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id; @@ -17,13 +17,13 @@ use std::collections::{HashMap, HashSet}; use std::iter::{once, Iterator}; use syntax::ast; use syntax::codemap::Span; -use utils::{sugg, sext}; -use consts::{constant, Constant}; +use crate::utils::{sugg, sext}; +use crate::consts::{constant, Constant}; -use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, +use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; -use utils::paths; +use crate::utils::paths; /// **What it does:** Checks for for-loops that manually copy items between /// slices that could be optimized by having a memcpy. diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 3a473ba4775..23c5434a750 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{get_arg_name, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, +use crate::utils::{get_arg_name, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** Checks for mapping `clone()` over an iterator. diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index ca98d145b0c..a1f4b70a4dc 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -3,8 +3,8 @@ use rustc::lint::*; use rustc::ty; use rustc_errors::{Applicability}; use syntax::codemap::Span; -use utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; -use utils::paths; +use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; +use crate::utils::paths; #[derive(Clone)] pub struct Pass; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b593c330503..8ab0482bacf 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -5,11 +5,11 @@ use std::cmp::Ordering; use std::collections::Bound; use syntax::ast::LitKind; use syntax::codemap::Span; -use utils::paths; -use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, +use crate::utils::paths; +use crate::utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; -use utils::sugg::Sugg; -use consts::{constant, Constant}; +use crate::utils::sugg::Sugg; +use crate::consts::{constant, Constant}; /// **What it does:** Checks for matches with a single arm where an `if let` /// will usually suffice. diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 603fbef3421..816c1bb6fbf 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::{Expr, ExprCall, ExprPath}; -use utils::{match_def_path, opt_def_id, paths, span_lint}; +use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is /// `Drop`. diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4c80fdb01c5..461efb27f28 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -7,13 +7,13 @@ use std::fmt; use std::iter; use syntax::ast; use syntax::codemap::{Span, BytePos}; -use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, +use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; -use utils::paths; -use utils::sugg; -use consts::{constant, Constant}; +use crate::utils::paths; +use crate::utils::sugg; +use crate::consts::{constant, Constant}; #[derive(Clone)] pub struct Pass; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 289c5c77ff3..8c511d8f0ad 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,8 +1,8 @@ -use consts::{constant_simple, Constant}; +use crate::consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use std::cmp::{Ordering, PartialOrd}; -use utils::{match_def_path, opt_def_id, paths, span_lint}; +use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// used to clamp values, but switched so that the result is constant. diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 2654def1385..a1cb1910e20 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,15 +1,15 @@ -use reexport::*; +use crate::reexport::*; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::ty; use syntax::codemap::{ExpnFormat, Span}; -use utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, +use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; -use utils::sugg::Sugg; +use crate::utils::sugg::Sugg; use syntax::ast::{LitKind, CRATE_NODE_ID}; -use consts::{constant, Constant}; +use crate::consts::{constant, Constant}; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 9ff7bbe4aba..2596916a3e1 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,7 +4,7 @@ use std::char; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; +use crate::utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index d9a6463641e..94d1ab0ae12 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -24,7 +24,7 @@ use rustc::ty; use syntax::ast; use syntax::attr; use syntax::codemap::Span; -use utils::in_macro; +use crate::utils::in_macro; /// **What it does:** Warns if there is missing doc for any documentable item /// (public or private). diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 501959e0f62..26837313a06 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -2,7 +2,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::*; use rustc::ty; -use utils::{higher, in_external_macro, span_lint}; +use crate::utils::{higher, in_external_macro, span_lint}; /// **What it does:** Checks for instances of `mut mut` references. /// diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 1184433c4dd..4537f279b1e 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use rustc::hir::*; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Detects giving a mutable reference to a function that only /// requires an immutable reference. diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index b879d76e65c..e5679bb7ba5 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -6,7 +6,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; -use utils::{match_type, paths, span_lint}; +use crate::utils::{match_type, paths, span_lint}; /// **What it does:** Checks for usages of `Mutex` where an atomic will do. /// diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index a15ec77eb28..885cb4b72cb 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,8 +6,8 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; -use utils::{snippet, span_lint, span_lint_and_sugg}; -use utils::sugg::Sugg; +use crate::utils::{snippet, span_lint, span_lint_and_sugg}; +use crate::utils::sugg::Sugg; /// **What it does:** Checks for expressions of the form `if c { true } else { /// false }` diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 7fdef19f183..84d5292d8c5 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; -use utils::{in_macro, snippet_opt, span_lint_and_then}; +use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 35eb599a527..91cc01891a9 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; -use utils::{in_macro, snippet, span_lint_and_then}; +use crate::utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for useless borrowed references. /// diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 2e483411ec6..4f6a8d9e2cb 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -32,7 +32,7 @@ use syntax::ast; use syntax::codemap::{original_sp, DUMMY_SP}; use std::borrow::Cow; -use utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; +use crate::utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; /// **What it does:** The lint checks for `if`-statements appearing in loops /// that contain a `continue` statement in either their main blocks or their diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 907f9cb85fe..36f5eaa8e18 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -10,9 +10,9 @@ use rustc_target::spec::abi::Abi; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; -use utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, +use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet, snippet_opt, span_lint_and_then}; -use utils::ptr::get_spans; +use crate::utils::ptr::get_spans; use std::collections::{HashMap, HashSet}; use std::borrow::Cow; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index fe75bfaf24c..87b92a53dd0 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; use rustc::hir::{Expr, ExprStruct}; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for needlessly including a base struct on update /// when all fields are changed anyway. diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 5ddd0d409e3..efcc1695eb6 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -2,8 +2,8 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::{Span, Spanned}; -use consts::{self, Constant}; -use utils::span_lint; +use crate::consts::{self, Constant}; +use crate::utils::span_lint; /// **What it does:** Checks for multiplication by -1 as a form of negation. /// diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index a6a63e6aa05..8df4577650f 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -3,9 +3,9 @@ use rustc::hir; use rustc::lint::*; use rustc::ty::{self, Ty}; use syntax::codemap::Span; -use utils::paths; -use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; -use utils::sugg::DiagnosticBuilderExt; +use crate::utils::paths; +use crate::utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; +use crate::utils::sugg::DiagnosticBuilderExt; /// **What it does:** Checks for types with a `fn new() -> Self` method and no /// implementation of diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 7b51b477201..8d351f87421 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; -use utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; +use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 022591329b5..69a02b0c50d 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -4,7 +4,7 @@ use syntax::symbol::LocalInternedString; use syntax::ast::*; use syntax::attr; use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; -use utils::{in_macro, span_lint, span_lint_and_then}; +use crate::utils::{in_macro, span_lint, span_lint_and_then}; /// **What it does:** Checks for names that are very similar and thus confusing. /// diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 286ed4b4d48..a2573b91f96 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; +use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 9ab22560093..142447ee345 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -2,7 +2,7 @@ use rustc::hir::{Expr, ExprLit, ExprMethodCall}; use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; -use utils::{match_type, paths, span_lint, walk_ptrs_ty}; +use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; /// **What it does:** Checks for duplicate open options as well as combinations /// that make no sense. diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 986206a1986..3a95471d0a2 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Detects classic underflow/overflow checks. /// diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index b257f5b3b94..f00a15dd401 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use syntax::ast::LitKind; use syntax::ptr::P; use syntax::ext::quote::rt::Span; -use utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; +use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 787aee71843..1d80b78558b 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{is_automatically_derived, span_lint}; +use crate::utils::{is_automatically_derived, span_lint}; /// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. /// diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 90e418f0687..7f5dd2abc0e 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{in_macro, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro, snippet, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 240b93e5729..2d5330f7b6b 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -9,8 +9,8 @@ use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; -use utils::ptr::get_spans; +use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; +use crate::utils::ptr::get_spans; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless the references are mutable. It will also suggest you diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index fa6d2efd572..ab98eef36e6 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,11 +1,11 @@ use rustc::lint::*; use rustc::hir::*; use rustc::hir::def::Def; -use utils::sugg::Sugg; +use crate::utils::sugg::Sugg; use syntax::ptr::P; -use utils::{match_def_path, match_type, span_lint_and_then}; -use utils::paths::*; +use crate::utils::{match_def_path, match_type, span_lint_and_then}; +use crate::utils::paths::*; /// **What it does:** Checks for expressions that could be replaced by the question mark operator /// diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 5d13b3e1ae6..4947479115e 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -2,9 +2,9 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::RangeLimits; use syntax::codemap::Spanned; -use utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; -use utils::{get_trait_def_id, higher, implements_trait}; -use utils::sugg::Sugg; +use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; +use crate::utils::{get_trait_def_id, higher, implements_trait}; +use crate::utils::sugg::Sugg; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -93,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { - use consts::{constant, Constant}; + use crate::consts::{constant, Constant}; if let Some((Constant::Int(0), _)) = constant(cx, cx.tables, &args[1]) { span_lint( cx, diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index a0465f21105..5b2aec47ca4 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; +use crate::utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 4b173a58563..d8179816236 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,6 +1,6 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::*; -use utils::{snippet, span_lint_and_sugg}; +use crate::utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. /// diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 522c2b9ac29..6395125578c 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -4,8 +4,8 @@ use rustc::lint::*; use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; -use utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; -use consts::{constant, Constant}; +use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; +use crate::consts::{constant, Constant}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 0677cb087d6..d6d9125a49c 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::def::Def; -use utils::{match_def_path, span_lint_and_sugg}; +use crate::utils::{match_def_path, span_lint_and_sugg}; /// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and /// `uX/iX::MIN/MAX`. diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index e91944382c5..73fbc172c10 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; +use crate::utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for return statements at the end of a block. /// diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 588e22b7cb1..a56a05470f2 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{get_trait_def_id, paths, span_lint}; +use crate::utils::{get_trait_def_id, paths, span_lint}; /// **What it does:** Checks for mis-uses of the serde API. /// diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 59f18d21534..12ba6970675 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,10 +1,10 @@ -use reexport::*; +use crate::reexport::*; use rustc::lint::*; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; use syntax::codemap::Span; -use utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, span_lint_and_then}; +use crate::utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, span_lint_and_then}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 1625346852e..5b4a2d1f504 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,8 +1,8 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Spanned; -use utils::SpanlessEq; -use utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::SpanlessEq; +use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -146,7 +146,7 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use syntax::ast::LitKind; - use utils::{in_macro, snippet}; + use crate::utils::{in_macro, snippet}; if let ExprMethodCall(ref path, _, ref args) = e.node { if path.name == "as_bytes" { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 2c322ce6b5e..bd7a8f7c761 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast; -use utils::{get_trait_def_id, span_lint}; +use crate::utils::{get_trait_def_id, span_lint}; /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g. /// subtracting elements in an Add impl. @@ -149,7 +149,7 @@ fn check_binop<'a>( expected_ops: &[hir::BinOp_], ) -> Option<&'a str> { let mut trait_ids = vec![]; - let [krate, module] = ::utils::paths::OPS_MODULE; + let [krate, module] = crate::utils::paths::OPS_MODULE; for t in traits { let path = [krate, module, t]; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 47ac45578be..8de4638d13d 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,8 +1,8 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; -use utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; -use utils::sugg::Sugg; +use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; +use crate::utils::sugg::Sugg; /// **What it does:** Checks for manual swapping. /// diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index fe1012aa98c..cd13ab0d51f 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup}; -use utils::is_adjusted; -use utils::span_lint; +use crate::utils::is_adjusted; +use crate::utils::span_lint; /// **What it does:** Checks for construction of a structure or tuple just to /// assign a value in it. diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 4ee0a77f549..cf553b397ce 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -3,8 +3,8 @@ use rustc::ty::{self, Ty}; use rustc::hir::*; use std::borrow::Cow; use syntax::ast; -use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; -use utils::{opt_def_id, sugg}; +use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; +use crate::utils::{opt_def_id, sugg}; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 168086d574a..2e2f35d4cd1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,4 +1,4 @@ -use reexport::*; +use crate::reexport::*; use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; @@ -12,11 +12,11 @@ use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; -use utils::{comparisons, differing_macro_contexts, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, +use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; -use utils::paths; -use consts::{constant, Constant}; +use crate::utils::paths; +use crate::consts::{constant, Constant}; /// Handles all the linting of funky types #[allow(missing_copy_implementations)] @@ -1290,9 +1290,9 @@ fn detect_absurd_comparison<'a, 'tcx>( lhs: &'tcx Expr, rhs: &'tcx Expr, ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { - use types::ExtremeType::*; - use types::AbsurdComparisonResult::*; - use utils::comparisons::*; + use crate::types::ExtremeType::*; + use crate::types::AbsurdComparisonResult::*; + use crate::utils::comparisons::*; // absurd comparison only makes sense on primitive types // primitive types don't implement comparison operators with each other @@ -1337,7 +1337,7 @@ fn detect_absurd_comparison<'a, 'tcx>( } fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option> { - use types::ExtremeType::*; + use crate::types::ExtremeType::*; let ty = cx.tables.expr_ty(expr); @@ -1362,8 +1362,8 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - use types::ExtremeType::*; - use types::AbsurdComparisonResult::*; + use crate::types::ExtremeType::*; + use crate::types::AbsurdComparisonResult::*; if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { @@ -1562,7 +1562,7 @@ fn upcast_comparison_bounds_err<'a, 'tcx>( rhs: &'tcx Expr, invert: bool, ) { - use utils::comparisons::*; + use crate::utils::comparisons::*; if let Some((lb, ub)) = lhs_bounds { if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 21c6b521153..0cb192e89b2 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; -use utils::{is_allowed, snippet, span_help_and_lint}; +use crate::utils::{is_allowed, snippet, span_help_and_lint}; /// **What it does:** Checks for the Unicode zero-width space in the code. /// diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index ff460e50d8c..85cf97a97f3 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; -use utils::span_lint; +use crate::utils::span_lint; /// **What it does:** Checks for imports that remove "unsafe" from an item's /// name. diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 0c28e9e74ec..1ef20e4a46c 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; +use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; /// **What it does:** Checks for unused written/read amount. /// diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 7e3f31d76c0..c7a33ab33b2 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use syntax::ast; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; -use utils::{in_macro, span_lint}; +use crate::utils::{in_macro, span_lint}; /// **What it does:** Checks for unused labels. /// diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 86ce57ca0bd..581a8d47677 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; -use utils::{in_macro, span_lint_and_then}; +use crate::utils::{in_macro, span_lint_and_then}; use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfType; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 79fde40b448..93ddd0ad07b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -9,7 +9,7 @@ use rustc::hir::{Expr, Expr_, QPath, Ty_, Pat, PatKind, BindingAnnotation, StmtS use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; use std::collections::HashMap; -use utils::get_attr; +use crate::utils::get_attr; /// **What it does:** Generates clippy code that detects the offending pattern /// diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 58e71705011..3fde026a2e0 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -96,8 +96,8 @@ macro_rules! define_Conf { -> Result { type T = define_Conf!(TY $($ty)+); Ok(T::deserialize(deserializer).unwrap_or_else(|e| { - ::utils::conf::ERRORS.lock().expect("no threading here") - .push(::utils::conf::Error::Toml(e.to_string())); + crate::utils::conf::ERRORS.lock().expect("no threading here") + .push(crate::utils::conf::Error::Toml(e.to_string())); super::$rust_name() })) } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 5a20bfc8143..69f1792012a 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::{hir, ty}; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; +use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 0b70d61da1f..15df7b72a8d 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,4 +1,4 @@ -use consts::{constant_simple, constant_context}; +use crate::consts::{constant_simple, constant_context}; use rustc::lint::*; use rustc::hir::*; use rustc::ty::{TypeckTables}; @@ -6,7 +6,7 @@ use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; use syntax::ast::Name; use syntax::ptr::P; -use utils::differing_macro_contexts; +use crate::utils::differing_macro_contexts; /// Type used to check whether two ast are the same. This is different from the /// operator diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 03682a19725..0b2f157d2b3 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir; use rustc::hir::print; use syntax::ast::Attribute; -use utils::get_attr; +use crate::utils::get_attr; /// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` /// attribute diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 5c9500afa46..1de0975ab42 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use utils::{match_qpath, paths, span_lint}; +use crate::utils::{match_qpath, paths, span_lint}; use syntax::symbol::LocalInternedString; use syntax::ast::{Crate as AstCrate, ItemKind, Name, NodeId}; use syntax::codemap::Span; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 86af4e8625f..4a30b134a69 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,4 +1,4 @@ -use reexport::*; +use crate::reexport::*; use rustc::hir; use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 7782fb8bc76..dd286a69547 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::LateContext; use syntax::ast::Name; use syntax::codemap::Span; -use utils::{get_pat_name, match_var, snippet}; +use crate::utils::{get_pat_name, match_var, snippet}; pub fn get_spans( cx: &LateContext, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index e7f63bb9a72..6add947cf9e 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -14,7 +14,7 @@ use syntax::parse::token; use syntax::print::pprust::token_to_string; use syntax::util::parser::AssocOp; use syntax::ast; -use utils::{higher, snippet, snippet_opt}; +use crate::utils::{higher, snippet, snippet_opt}; use syntax_pos::{BytePos, Pos}; /// A helper type to build suggestion correctly handling parenthesis. diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 6aff0ebc9f7..0d8997f4f36 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -2,8 +2,8 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty::{self, Ty}; use syntax::codemap::Span; -use utils::{higher, is_copy, snippet, span_lint_and_sugg}; -use consts::constant; +use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; +use crate::consts::constant; /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would /// be possible. diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index fdd4f8ced9a..2258735ca95 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -6,8 +6,8 @@ use syntax::ast::LitKind; use syntax::ptr; use syntax::symbol::LocalInternedString; use syntax_pos::Span; -use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; -use utils::{opt_def_id, paths, last_path_segment}; +use crate::utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; +use crate::utils::{opt_def_id, paths, last_path_segment}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index fc28815c70e..aaba0184845 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,7 +1,7 @@ -use consts::{constant_simple, Constant}; +use crate::consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; -use utils::span_help_and_lint; +use crate::utils::span_help_and_lint; /// **What it does:** Checks for `0.0 / 0.0`. /// -- cgit 1.4.1-3-g733a5 From 551c02ecbf22d1d06e39ac6b80c56df312eda944 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Wed, 30 May 2018 10:18:52 +0200 Subject: Upgrade to edition 2018 --- Cargo.toml | 3 +++ clippy_lints/Cargo.toml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9d49b89440e..ff74e204198 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy" version = "0.0.205" @@ -15,6 +17,7 @@ license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] build = "build.rs" +edition = "2018" [badges] travis-ci = { repository = "rust-lang-nursery/rust-clippy" } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index a02cad5b181..3d7f3d02003 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy_lints" # begin automatic update @@ -14,6 +16,7 @@ repository = "https://github.com/rust-lang-nursery/rust-clippy" readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] +edition = "2018" [dependencies] cargo_metadata = "0.5" -- cgit 1.4.1-3-g733a5 From cc8c52c961d273eed81753b75cab8cc83baa4387 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Wed, 30 May 2018 11:20:34 +0200 Subject: Update integration test --- ci/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index e786ac06104..28785f633c3 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,5 +1,5 @@ set -x -cargo install --force +cargo install --force --path . echo "Running integration test for crate ${INTEGRATION}" -- cgit 1.4.1-3-g733a5 From e6811b9c26726fa5c001c45c76b53137cf1570a3 Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Wed, 30 May 2018 16:55:03 +0700 Subject: Fix 'help' message --- clippy_lints/src/types.rs | 2 +- tests/ui/types_fn_to_int.stderr | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index fc65ebcc147..0fe5f24f8d4 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1003,7 +1003,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { FN_TO_NUMERIC_CAST, expr.span, &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), - "if you need the address of the function, consider :", + "if you need the address of the function, consider", format!("{} as usize", &snippet(cx, ex.span, "x")) ); } diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index d5e8ad8bbb2..a3a1abcc681 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -2,23 +2,15 @@ error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function --> $DIR/types_fn_to_int.rs:12:13 | 12 | let y = x as i32; - | ^^^^^^^^ + | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` | = note: #[deny(fn_to_numeric_cast)] on by default -help: if you need the address of the function, consider : - | -12 | let y = x as usize; - | ^^^^^^^^^^ error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. --> $DIR/types_fn_to_int.rs:14:13 | 14 | let z = bar as u32; - | ^^^^^^^^^^ -help: if you need the address of the function, consider : - | -14 | let z = bar as usize; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 3244d122fdfea854f44c2b04457ea49e01c1013e Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Wed, 30 May 2018 20:29:00 +0200 Subject: Get compile-test tests for configuration working --- tests/compile-test.rs | 40 +++++++++++++++-- tests/ui-toml/bad_toml/clippy.toml | 2 + tests/ui-toml/bad_toml/conf_bad_toml.rs | 6 +++ tests/ui-toml/bad_toml/conf_bad_toml.stderr | 4 ++ tests/ui-toml/bad_toml_type/clippy.toml | 1 + tests/ui-toml/bad_toml_type/conf_bad_type.rs | 6 +++ tests/ui-toml/bad_toml_type/conf_bad_type.stderr | 4 ++ tests/ui-toml/toml_blacklist/clippy.toml | 1 + .../toml_blacklist/conf_french_blacklisted_name.rs | 23 ++++++++++ .../conf_french_blacklisted_name.stderr | 46 ++++++++++++++++++++ tests/ui-toml/toml_unknown_key/clippy.toml | 6 +++ tests/ui-toml/toml_unknown_key/conf_unknown_key.rs | 6 +++ .../toml_unknown_key/conf_unknown_key.stderr | 4 ++ tests/ui-toml/update-all-references.sh | 28 ++++++++++++ tests/ui-toml/update-references.sh | 50 ++++++++++++++++++++++ tests/ui/bad_toml/clippy.toml | 2 - tests/ui/bad_toml/conf_bad_toml.rs | 6 --- tests/ui/bad_toml/conf_bad_toml.stderr | 0 tests/ui/bad_toml_type/clippy.toml | 1 - tests/ui/bad_toml_type/conf_bad_type.rs | 6 --- tests/ui/bad_toml_type/conf_bad_type.stderr | 0 tests/ui/toml_blacklist/clippy.toml | 1 - .../toml_blacklist/conf_french_blacklisted_name.rs | 23 ---------- .../conf_french_blacklisted_name.stderr | 0 tests/ui/toml_unknown_key/clippy.toml | 6 --- tests/ui/toml_unknown_key/conf_unknown_key.rs | 6 --- tests/ui/toml_unknown_key/conf_unknown_key.stderr | 0 27 files changed, 224 insertions(+), 54 deletions(-) create mode 100644 tests/ui-toml/bad_toml/clippy.toml create mode 100644 tests/ui-toml/bad_toml/conf_bad_toml.rs create mode 100644 tests/ui-toml/bad_toml/conf_bad_toml.stderr create mode 100644 tests/ui-toml/bad_toml_type/clippy.toml create mode 100644 tests/ui-toml/bad_toml_type/conf_bad_type.rs create mode 100644 tests/ui-toml/bad_toml_type/conf_bad_type.stderr create mode 100644 tests/ui-toml/toml_blacklist/clippy.toml create mode 100644 tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs create mode 100644 tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr create mode 100644 tests/ui-toml/toml_unknown_key/clippy.toml create mode 100644 tests/ui-toml/toml_unknown_key/conf_unknown_key.rs create mode 100644 tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr create mode 100755 tests/ui-toml/update-all-references.sh create mode 100755 tests/ui-toml/update-references.sh delete mode 100644 tests/ui/bad_toml/clippy.toml delete mode 100644 tests/ui/bad_toml/conf_bad_toml.rs delete mode 100644 tests/ui/bad_toml/conf_bad_toml.stderr delete mode 100644 tests/ui/bad_toml_type/clippy.toml delete mode 100644 tests/ui/bad_toml_type/conf_bad_type.rs delete mode 100644 tests/ui/bad_toml_type/conf_bad_type.stderr delete mode 100644 tests/ui/toml_blacklist/clippy.toml delete mode 100644 tests/ui/toml_blacklist/conf_french_blacklisted_name.rs delete mode 100644 tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr delete mode 100644 tests/ui/toml_unknown_key/clippy.toml delete mode 100644 tests/ui/toml_unknown_key/conf_unknown_key.rs delete mode 100644 tests/ui/toml_unknown_key/conf_unknown_key.stderr diff --git a/tests/compile-test.rs b/tests/compile-test.rs index b965dceb774..ff594f7a464 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,6 +3,9 @@ extern crate compiletest_rs as compiletest; extern crate test; +use std::ffi::OsStr; +use std::fs; +use std::error::Error; use std::env::{set_var, var}; use std::path::{Path, PathBuf}; @@ -30,7 +33,7 @@ fn rustc_lib_path() -> PathBuf { option_env!("RUSTC_LIB_PATH").unwrap().into() } -fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { +fn config(mode: &str, dir: &str) -> compiletest::Config { let mut config = compiletest::Config::default(); let cfg_mode = mode.parse().expect("Invalid mode"); @@ -61,8 +64,38 @@ fn config(dir: &'static str, mode: &'static str) -> compiletest::Config { config } -fn run_mode(dir: &'static str, mode: &'static str) { - compiletest::run_tests(&config(dir, mode)); +fn run_mode(mode: &str, dir: &str) { + compiletest::run_tests(&config(mode, dir)); +} + +fn run_ui_toml() -> Result<(), Box> { + let base = PathBuf::from("tests/ui-toml/").canonicalize()?; + for dir in fs::read_dir(&base)? { + let dir = dir?; + if !dir.file_type()?.is_dir() { + continue; + } + let dir_path = dir.path(); + set_var("CARGO_MANIFEST_DIR", &dir_path); + let config = config("ui", "ui-toml"); + for file in fs::read_dir(&dir_path)? { + let file = file?; + let file_path = file.path(); + if !file.file_type()?.is_file() { + continue; + } + if file_path.extension() != Some(OsStr::new("rs")) { + continue; + } + let paths = compiletest::common::TestPaths { + file: file_path, + base: base.clone(), + relative_dir: dir_path.file_name().unwrap().into(), + }; + compiletest::runtest::run(config.clone(), &paths); + } + } + Ok(()) } fn prepare_env() { @@ -76,4 +109,5 @@ fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); + run_ui_toml().unwrap(); } diff --git a/tests/ui-toml/bad_toml/clippy.toml b/tests/ui-toml/bad_toml/clippy.toml new file mode 100644 index 00000000000..823e01a33b9 --- /dev/null +++ b/tests/ui-toml/bad_toml/clippy.toml @@ -0,0 +1,2 @@ +fn this_is_obviously(not: a, toml: file) { +} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs new file mode 100644 index 00000000000..325688ac7da --- /dev/null +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file + + + + +fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/tests/ui-toml/bad_toml/conf_bad_toml.stderr new file mode 100644 index 00000000000..85b3ef8612e --- /dev/null +++ b/tests/ui-toml/bad_toml/conf_bad_toml.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file `$DIR/clippy.toml`: expected an equals, found an identifier at line 1 + +error: aborting due to previous error + diff --git a/tests/ui-toml/bad_toml_type/clippy.toml b/tests/ui-toml/bad_toml_type/clippy.toml new file mode 100644 index 00000000000..168675394d7 --- /dev/null +++ b/tests/ui-toml/bad_toml_type/clippy.toml @@ -0,0 +1 @@ +blacklisted-names = 42 diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs new file mode 100644 index 00000000000..f97f5802b13 --- /dev/null +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` + + + + +fn main() {} diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr new file mode 100644 index 00000000000..efd02bcbb6e --- /dev/null +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file `$DIR/clippy.toml`: invalid type: integer `42`, expected a sequence + +error: aborting due to previous error + diff --git a/tests/ui-toml/toml_blacklist/clippy.toml b/tests/ui-toml/toml_blacklist/clippy.toml new file mode 100644 index 00000000000..6abe5a3bbc2 --- /dev/null +++ b/tests/ui-toml/toml_blacklist/clippy.toml @@ -0,0 +1 @@ +blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs new file mode 100644 index 00000000000..1f1a8ee91a1 --- /dev/null +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -0,0 +1,23 @@ + + + +#![allow(dead_code)] +#![allow(single_match)] +#![allow(unused_variables)] +#![warn(blacklisted_name)] + +fn test(toto: ()) {} + +fn main() { + let toto = 42; + let tata = 42; + let titi = 42; + + let tatab = 42; + let tatatataic = 42; + + match (42, Some(1337), Some(0)) { + (toto, Some(tata), titi @ Some(_)) => (), + _ => (), + } +} diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr new file mode 100644 index 00000000000..b2b0f26b140 --- /dev/null +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -0,0 +1,46 @@ +error: use of a blacklisted/placeholder name `toto` + --> $DIR/conf_french_blacklisted_name.rs:9:9 + | +9 | fn test(toto: ()) {} + | ^^^^ + | + = note: `-D blacklisted-name` implied by `-D warnings` + +error: use of a blacklisted/placeholder name `toto` + --> $DIR/conf_french_blacklisted_name.rs:12:9 + | +12 | let toto = 42; + | ^^^^ + +error: use of a blacklisted/placeholder name `tata` + --> $DIR/conf_french_blacklisted_name.rs:13:9 + | +13 | let tata = 42; + | ^^^^ + +error: use of a blacklisted/placeholder name `titi` + --> $DIR/conf_french_blacklisted_name.rs:14:9 + | +14 | let titi = 42; + | ^^^^ + +error: use of a blacklisted/placeholder name `toto` + --> $DIR/conf_french_blacklisted_name.rs:20:10 + | +20 | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: use of a blacklisted/placeholder name `tata` + --> $DIR/conf_french_blacklisted_name.rs:20:21 + | +20 | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: use of a blacklisted/placeholder name `titi` + --> $DIR/conf_french_blacklisted_name.rs:20:28 + | +20 | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/clippy.toml b/tests/ui-toml/toml_unknown_key/clippy.toml new file mode 100644 index 00000000000..554b87cc50b --- /dev/null +++ b/tests/ui-toml/toml_unknown_key/clippy.toml @@ -0,0 +1,6 @@ +# that one is an error +foobar = 42 + +# that one is white-listed +[third-party] +clippy-feature = "nightly" diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs new file mode 100644 index 00000000000..bfa804558bb --- /dev/null +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -0,0 +1,6 @@ +// error-pattern: error reading Clippy's configuration file: unknown key `foobar` + + + + +fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr new file mode 100644 index 00000000000..61e03774e32 --- /dev/null +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `third-party` + +error: aborting due to previous error + diff --git a/tests/ui-toml/update-all-references.sh b/tests/ui-toml/update-all-references.sh new file mode 100755 index 00000000000..acc38f15fbd --- /dev/null +++ b/tests/ui-toml/update-all-references.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright 2015 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# A script to update the references for all tests. The idea is that +# you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. You then +# run this script, which will copy those files over. If you find +# yourself manually editing a foo.stderr file, you're doing it wrong. +# +# See all `update-references.sh`, if you just want to update a single test. + +if [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "usage: $0" +fi + +BUILD_DIR=$PWD/target/debug/test_build_base +MY_DIR=$(dirname $0) +cd $MY_DIR +find . -name '*.rs' | xargs ./update-references.sh $BUILD_DIR diff --git a/tests/ui-toml/update-references.sh b/tests/ui-toml/update-references.sh new file mode 100755 index 00000000000..aa99d35f7aa --- /dev/null +++ b/tests/ui-toml/update-references.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Copyright 2015 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# A script to update the references for particular tests. The idea is +# that you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. This +# script will then copy that output and replace the "expected output" +# files. You can then commit the changes. +# +# If you find yourself manually editing a foo.stderr file, you're +# doing it wrong. + +if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then + echo "usage: $0 " + echo "" + echo "For example:" + echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs" +fi + +MYDIR=$(dirname $0) + +BUILD_DIR="$1" +shift + +while [[ "$1" != "" ]]; do + STDERR_NAME="${1/%.rs/.stderr}" + STDOUT_NAME="${1/%.rs/.stdout}" + shift + if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ + ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then + echo updating $MYDIR/$STDOUT_NAME + cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME + fi + if [ -f $BUILD_DIR/$STDERR_NAME ] && \ + ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then + echo updating $MYDIR/$STDERR_NAME + cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME + fi +done + + diff --git a/tests/ui/bad_toml/clippy.toml b/tests/ui/bad_toml/clippy.toml deleted file mode 100644 index 823e01a33b9..00000000000 --- a/tests/ui/bad_toml/clippy.toml +++ /dev/null @@ -1,2 +0,0 @@ -fn this_is_obviously(not: a, toml: file) { -} diff --git a/tests/ui/bad_toml/conf_bad_toml.rs b/tests/ui/bad_toml/conf_bad_toml.rs deleted file mode 100644 index 325688ac7da..00000000000 --- a/tests/ui/bad_toml/conf_bad_toml.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file - - - - -fn main() {} diff --git a/tests/ui/bad_toml/conf_bad_toml.stderr b/tests/ui/bad_toml/conf_bad_toml.stderr deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/ui/bad_toml_type/clippy.toml b/tests/ui/bad_toml_type/clippy.toml deleted file mode 100644 index 168675394d7..00000000000 --- a/tests/ui/bad_toml_type/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = 42 diff --git a/tests/ui/bad_toml_type/conf_bad_type.rs b/tests/ui/bad_toml_type/conf_bad_type.rs deleted file mode 100644 index f97f5802b13..00000000000 --- a/tests/ui/bad_toml_type/conf_bad_type.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` - - - - -fn main() {} diff --git a/tests/ui/bad_toml_type/conf_bad_type.stderr b/tests/ui/bad_toml_type/conf_bad_type.stderr deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/ui/toml_blacklist/clippy.toml b/tests/ui/toml_blacklist/clippy.toml deleted file mode 100644 index 6abe5a3bbc2..00000000000 --- a/tests/ui/toml_blacklist/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs deleted file mode 100644 index 1f1a8ee91a1..00000000000 --- a/tests/ui/toml_blacklist/conf_french_blacklisted_name.rs +++ /dev/null @@ -1,23 +0,0 @@ - - - -#![allow(dead_code)] -#![allow(single_match)] -#![allow(unused_variables)] -#![warn(blacklisted_name)] - -fn test(toto: ()) {} - -fn main() { - let toto = 42; - let tata = 42; - let titi = 42; - - let tatab = 42; - let tatatataic = 42; - - match (42, Some(1337), Some(0)) { - (toto, Some(tata), titi @ Some(_)) => (), - _ => (), - } -} diff --git a/tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui/toml_blacklist/conf_french_blacklisted_name.stderr deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/ui/toml_unknown_key/clippy.toml b/tests/ui/toml_unknown_key/clippy.toml deleted file mode 100644 index 554b87cc50b..00000000000 --- a/tests/ui/toml_unknown_key/clippy.toml +++ /dev/null @@ -1,6 +0,0 @@ -# that one is an error -foobar = 42 - -# that one is white-listed -[third-party] -clippy-feature = "nightly" diff --git a/tests/ui/toml_unknown_key/conf_unknown_key.rs b/tests/ui/toml_unknown_key/conf_unknown_key.rs deleted file mode 100644 index bfa804558bb..00000000000 --- a/tests/ui/toml_unknown_key/conf_unknown_key.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern: error reading Clippy's configuration file: unknown key `foobar` - - - - -fn main() {} diff --git a/tests/ui/toml_unknown_key/conf_unknown_key.stderr b/tests/ui/toml_unknown_key/conf_unknown_key.stderr deleted file mode 100644 index e69de29bb2d..00000000000 -- cgit 1.4.1-3-g733a5 From edcb8f6976457b4a42a1788a908ff19bc93c6632 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Wed, 30 May 2018 21:26:09 +0200 Subject: Use compiletest::make_tests to allow it to setup the output folders --- tests/compile-test.rs | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index ff594f7a464..236cce0dbb7 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,9 +3,9 @@ extern crate compiletest_rs as compiletest; extern crate test; +use std::io; use std::ffi::OsStr; use std::fs; -use std::error::Error; use std::env::{set_var, var}; use std::path::{Path, PathBuf}; @@ -33,7 +33,7 @@ fn rustc_lib_path() -> PathBuf { option_env!("RUSTC_LIB_PATH").unwrap().into() } -fn config(mode: &str, dir: &str) -> compiletest::Config { +fn config(mode: &str, dir: PathBuf) -> compiletest::Config { let mut config = compiletest::Config::default(); let cfg_mode = mode.parse().expect("Invalid mode"); @@ -59,25 +59,25 @@ fn config(mode: &str, dir: &str) -> compiletest::Config { path.push("target/debug/test_build_base"); path }; - config.src_base = PathBuf::from(format!("tests/{}", dir)); + config.src_base = dir; config.rustc_path = clippy_driver_path(); config } -fn run_mode(mode: &str, dir: &str) { +fn run_mode(mode: &str, dir: PathBuf) { compiletest::run_tests(&config(mode, dir)); } -fn run_ui_toml() -> Result<(), Box> { - let base = PathBuf::from("tests/ui-toml/").canonicalize()?; - for dir in fs::read_dir(&base)? { +fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec) -> Result { + let mut result = true; + let opts = compiletest::test_opts(config); + for dir in fs::read_dir(&config.src_base)? { let dir = dir?; if !dir.file_type()?.is_dir() { continue; } let dir_path = dir.path(); set_var("CARGO_MANIFEST_DIR", &dir_path); - let config = config("ui", "ui-toml"); for file in fs::read_dir(&dir_path)? { let file = file?; let file_path = file.path(); @@ -89,13 +89,34 @@ fn run_ui_toml() -> Result<(), Box> { } let paths = compiletest::common::TestPaths { file: file_path, - base: base.clone(), + base: config.src_base.clone(), relative_dir: dir_path.file_name().unwrap().into(), }; - compiletest::runtest::run(config.clone(), &paths); + let test_name = compiletest::make_test_name(&config, &paths); + let index = tests.iter() + .position(|test| test.desc.name == test_name) + .expect("The test should be in there"); + result &= test::run_tests_console( + &opts, + vec![tests.swap_remove(index)])?; + } + } + Ok(result) +} + +fn run_ui_toml() { + let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap(); + let config = config("ui", path); + let tests = compiletest::make_tests(&config); + + let res = run_ui_toml_tests(&config, tests); + match res { + Ok(true) => {} + Ok(false) => panic!("Some tests failed"), + Err(e) => { + println!("I/O failure during tests: {:?}", e); } } - Ok(()) } fn prepare_env() { @@ -107,7 +128,7 @@ fn prepare_env() { #[test] fn compile_test() { prepare_env(); - run_mode("run-pass", "run-pass"); - run_mode("ui", "ui"); - run_ui_toml().unwrap(); + run_mode("run-pass", "tests/run-pass".into()); + run_mode("ui", "tests/ui".into()); + run_ui_toml(); } -- cgit 1.4.1-3-g733a5 From ded2576957e69599073df0c05b5dea7405b36a94 Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Thu, 31 May 2018 09:00:13 +0700 Subject: Add one more test --- tests/ui/types_fn_to_int.rs | 1 + tests/ui/types_fn_to_int.stderr | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs index 0cce6579813..927f2149f30 100644 --- a/tests/ui/types_fn_to_int.rs +++ b/tests/ui/types_fn_to_int.rs @@ -10,6 +10,7 @@ fn bar() -> i32 { fn main() { let x = Foo::A; let y = x as i32; + let y1 = Foo::A as i32; let z = bar as u32; } diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index a3a1abcc681..0643230470d 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -6,11 +6,17 @@ error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function | = note: #[deny(fn_to_numeric_cast)] on by default +error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. + --> $DIR/types_fn_to_int.rs:13:14 + | +13 | let y1 = Foo::A as i32; + | ^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` + error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:14:13 + --> $DIR/types_fn_to_int.rs:15:13 | -14 | let z = bar as u32; +15 | let z = bar as u32; | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 24ab207671b0ac61c3b2008f9557a56cd4191efc Mon Sep 17 00:00:00 2001 From: Victor Korkin Date: Fri, 1 Jun 2018 23:08:11 +0700 Subject: Divide FN_TO_NUMERIC lint into two. FN_TO_NUMERIC_CAST_WITH_TRUNCATION is correctness check FN_TO_NUMERIC_CAST is only style check --- clippy_lints/src/types.rs | 56 ++++++++++++++++++++++++++-------- tests/ui/types_fn_to_int.rs | 14 ++++++--- tests/ui/types_fn_to_int.stderr | 66 ++++++++++++++++++++++++++++++++++------- 3 files changed, 109 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 0fe5f24f8d4..c309503ee38 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -679,9 +679,9 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } -/// **What it does:** Checks for casts of a function pointer to a numeric type except `usize`. +/// **What it does:** Checks for casts of a function pointer to a numeric type not enough to store address. /// -/// **Why is this bad?** Casting a function pointer to something other than `usize` could truncate the address value. +/// **Why is this bad?** Casting a function pointer to not eligable type could truncate the address value. /// /// **Known problems:** None. /// @@ -691,8 +691,25 @@ declare_clippy_lint! { /// let _ = test_fn as i32 /// ``` declare_clippy_lint! { - pub FN_TO_NUMERIC_CAST, + pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, correctness, + "cast function pointer to the numeric type with value truncation" +} + +/// **What it does:** Checks for casts of a function pointer to a numeric type except `usize`. +/// +/// **Why is this bad?** Casting a function pointer to something other than `usize` is not a good style. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn test_fn() -> i16; +/// let _ = test_fn as i128 +/// ``` +declare_clippy_lint! { + pub FN_TO_NUMERIC_CAST, + style, "cast function pointer to the numeric type" } @@ -909,7 +926,8 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, - FN_TO_NUMERIC_CAST + FN_TO_NUMERIC_CAST, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, ) } } @@ -998,14 +1016,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { ty::TyFnDef(..) | ty::TyFnPtr(..) => { if cast_to.is_numeric() && cast_to.sty != ty::TyUint(UintTy::Usize){ - span_lint_and_sugg( - cx, - FN_TO_NUMERIC_CAST, - expr.span, - &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), - "if you need the address of the function, consider", - format!("{} as usize", &snippet(cx, ex.span, "x")) - ); + let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); + let pointer_nbits = cx.tcx.data_layout.pointer_size.bits(); + if to_nbits < pointer_nbits || (to_nbits == pointer_nbits && cast_to.is_signed()) { + span_lint_and_sugg( + cx, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + expr.span, + &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), + "if you need the address of the function, consider", + format!("{} as usize", &snippet(cx, ex.span, "x")) + ); + } else { + span_lint_and_sugg( + cx, + FN_TO_NUMERIC_CAST, + expr.span, + &format!("casting a `{}` to `{}` is bad style.", cast_from, cast_to), + "if you need the address of the function, consider", + format!("{} as usize", &snippet(cx, ex.span, "x")) + ); + + }; } } _ => () diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs index 927f2149f30..8387586c3e9 100644 --- a/tests/ui/types_fn_to_int.rs +++ b/tests/ui/types_fn_to_int.rs @@ -9,8 +9,14 @@ fn bar() -> i32 { fn main() { let x = Foo::A; - let y = x as i32; - let y1 = Foo::A as i32; - - let z = bar as u32; + let _y = x as i32; + let _y1 = Foo::A as i32; + let _y = x as u32; + let _z = bar as u32; + let _y = bar as i64; + let _y = bar as u64; + let _z = Foo::A as i128; + let _z = Foo::A as u128; + let _z = bar as i128; + let _z = bar as u128; } diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index 0643230470d..bbdf4ce2e70 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -1,22 +1,66 @@ error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:12:13 + --> $DIR/types_fn_to_int.rs:12:14 | -12 | let y = x as i32; - | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` +12 | let _y = x as i32; + | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` | - = note: #[deny(fn_to_numeric_cast)] on by default + = note: #[deny(fn_to_numeric_cast_with_truncation)] on by default error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:13:14 + --> $DIR/types_fn_to_int.rs:13:15 | -13 | let y1 = Foo::A as i32; - | ^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` +13 | let _y1 = Foo::A as i32; + | ^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` + +error: casting a `fn(usize) -> Foo {Foo::A}` to `u32` may truncate the function address value. + --> $DIR/types_fn_to_int.rs:14:14 + | +14 | let _y = x as u32; + | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:15:13 + --> $DIR/types_fn_to_int.rs:15:14 + | +15 | let _z = bar as u32; + | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` + +error: casting a `fn() -> i32 {bar}` to `i64` may truncate the function address value. + --> $DIR/types_fn_to_int.rs:16:14 + | +16 | let _y = bar as i64; + | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` + +error: casting a `fn() -> i32 {bar}` to `u64` is bad style. + --> $DIR/types_fn_to_int.rs:17:14 + | +17 | let _y = bar as u64; + | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` + | + = note: `-D fn-to-numeric-cast` implied by `-D warnings` + +error: casting a `fn(usize) -> Foo {Foo::A}` to `i128` is bad style. + --> $DIR/types_fn_to_int.rs:18:14 + | +18 | let _z = Foo::A as i128; + | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` + +error: casting a `fn(usize) -> Foo {Foo::A}` to `u128` is bad style. + --> $DIR/types_fn_to_int.rs:19:14 + | +19 | let _z = Foo::A as u128; + | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` + +error: casting a `fn() -> i32 {bar}` to `i128` is bad style. + --> $DIR/types_fn_to_int.rs:20:14 + | +20 | let _z = bar as i128; + | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` + +error: casting a `fn() -> i32 {bar}` to `u128` is bad style. + --> $DIR/types_fn_to_int.rs:21:14 | -15 | let z = bar as u32; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` +21 | let _z = bar as u128; + | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` -error: aborting due to 3 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 1c6c79f92cad0c0e062ba1ef1d291f140e326cb3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 08:59:10 +0200 Subject: Version bump --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/utils/inspector.rs | 4 ++-- min_version.txt | 6 +++--- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85488816bcb..aefb32a346a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.207 +* Rustup to *rustc 1.28.0-nightly (4ecf12bf0 2018-06-02)* + ## 0.0.206 * Rustup to *rustc 1.28.0-nightly (5bf68db6e 2018-05-28)* @@ -726,6 +729,7 @@ All notable changes to this project will be documented in this file. [`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception [`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one [`multiple_crate_versions`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#multiple_crate_versions +[`multiple_inherent_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#multiple_inherent_impl [`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref [`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut [`mut_range_bound`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_range_bound diff --git a/Cargo.toml b/Cargo.toml index feafb83f3c5..e2be104f684 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.206" +version = "0.0.207" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.206", path = "clippy_lints" } +clippy_lints = { version = "0.0.207", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/README.md b/README.md index 5c90646bf9f..150f821b5f4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 260 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 261 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index b3e45129d80..4797c60096b 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.206" +version = "0.0.207" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 0b2f157d2b3..cab9adc7b0c 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { println!("impl item `{}`", item.name); match item.vis { hir::Visibility::Public => println!("public"), - hir::Visibility::Crate => println!("visible crate wide"), + hir::Visibility::Crate(_) => println!("visible crate wide"), hir::Visibility::Restricted { ref path, .. } => println!( "visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false)) @@ -345,7 +345,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("item `{}`", item.name); match item.vis { hir::Visibility::Public => println!("public"), - hir::Visibility::Crate => println!("visible crate wide"), + hir::Visibility::Crate(_) => println!("visible crate wide"), hir::Visibility::Restricted { ref path, .. } => println!( "visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false)) diff --git a/min_version.txt b/min_version.txt index 6b2be5640c8..3e55bb8c208 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (5bf68db6e 2018-05-28) +rustc 1.28.0-nightly (4ecf12bf0 2018-06-02) binary: rustc -commit-hash: 5bf68db6ecda0dd4788311a41b5c763d35597c96 -commit-date: 2018-05-28 +commit-hash: 4ecf12bf0eb8386626ccdb5f721a7183ccc4eba6 +commit-date: 2018-06-02 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 2c1451817cf2db427c4947c6a122917e35e05a8a Mon Sep 17 00:00:00 2001 From: Terry Raimondo Date: Sun, 3 Jun 2018 12:26:50 +0200 Subject: Compute digits vec only once --- clippy_lints/src/literal_representation.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index dacfd7c8983..e5d855c10aa 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -193,18 +193,19 @@ impl<'a> DigitInfo<'a> { self.suffix.unwrap_or("") ) } else { - let mut hint = self.digits + let filtered_digits_vec = self.digits .chars() - .rev() .filter(|&c| c != '_') - .collect::>() + .rev() + .collect::>(); + let mut hint = filtered_digits_vec .chunks(group_size) .map(|chunk| chunk.into_iter().rev().collect()) .rev() .collect::>() .join("_"); // Forces hexadecimal values to be grouped by 4 being filled with zeroes (e.g 0x00ab_cdef) - let nb_digits_to_fill = self.digits.chars().filter(|&c| c != '_').collect::>().len() % 4; + let nb_digits_to_fill = filtered_digits_vec.len() % 4; if self.radix == Radix::Hexadecimal && nb_digits_to_fill != 0 { hint = format!("{:0>4}{}", &hint[..nb_digits_to_fill], &hint[nb_digits_to_fill..]); } -- cgit 1.4.1-3-g733a5 From 6d51559f62f8814661a81ab4177fbcde18933390 Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Fri, 1 Jun 2018 11:58:40 +0200 Subject: Added lint to avoid negated comparisions on partially ordered types. --- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 95 +++++++++++++++++++++++++++ tests/ui/neg_cmp_op_on_partial_ord.rs | 59 +++++++++++++++++ tests/ui/neg_cmp_op_on_partial_ord.stderr | 28 ++++++++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/neg_cmp_op_on_partial_ord.rs create mode 100644 tests/ui/neg_cmp_op_on_partial_ord.rs create mode 100644 tests/ui/neg_cmp_op_on_partial_ord.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4aa0b3e89ae..612cde8a6aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -169,6 +169,7 @@ pub mod needless_borrowed_ref; pub mod needless_continue; pub mod needless_pass_by_value; pub mod needless_update; +pub mod neg_cmp_op_on_partial_ord; pub mod neg_multiply; pub mod new_without_default; pub mod no_effect; @@ -419,7 +420,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_late_lint_pass(box infallible_destructuring_match::Pass); reg.register_late_lint_pass(box inherent_impl::Pass::default()); - + reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -501,6 +502,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { booleans::LOGIC_BUG, booleans::NONMINIMAL_BOOL, bytecount::NAIVE_BYTECOUNT, + neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, copies::IF_SAME_THEN_ELSE, diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs new file mode 100644 index 00000000000..139808f4393 --- /dev/null +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -0,0 +1,95 @@ +use rustc::hir::*; +use rustc::lint::*; + +use crate::utils; + +const ORD: [&str; 3] = ["core", "cmp", "Ord"]; +const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; + +/// **What it does:** +/// Checks for the usage of negated comparision operators on types which only implement +/// `PartialOrd` (e.g. `f64`). +/// +/// **Why is this bad?** +/// These operators make it easy to forget that the underlying types actually allow not only three +/// potential Orderings (Less, Equal, Greater) but also a forth one (Uncomparable). Escpeccially if +/// the operator based comparision result is negated it is easy to miss that fact. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// use core::cmp::Ordering; +/// +/// // Bad +/// let a = 1.0; +/// let b = std::f64::NAN; +/// +/// let _not_less_or_equal = !(a <= b); +/// +/// // Good +/// let a = 1.0; +/// let b = std::f64::NAN; +/// +/// let _not_less_or_equal = match a.partial_cmp(&b) { +/// None | Some(Ordering::Greater) => true, +/// _ => false, +/// }; +/// ``` +declare_lint! { + pub NEG_CMP_OP_ON_PARTIAL_ORD, Warn, + "The use of negated comparision operators on partially orded types may produce confusing code." +} + +pub struct NoNegCompOpForPartialOrd; + +impl LintPass for NoNegCompOpForPartialOrd { + fn get_lints(&self) -> LintArray { + lint_array!(NEG_CMP_OP_ON_PARTIAL_ORD) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { + + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + + if let Expr_::ExprUnary(UnOp::UnNot, ref inner) = expr.node; + if let Expr_::ExprBinary(ref op, ref left, _) = inner.node; + if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node; + + then { + + let ty = cx.tables.expr_ty(left); + + let implements_ord = { + if let Some(id) = utils::get_trait_def_id(cx, &ORD) { + utils::implements_trait(cx, ty, id, &[]) + } else { + return; + } + }; + + let implements_partial_ord = { + if let Some(id) = utils::get_trait_def_id(cx, &PARTIAL_ORD) { + utils::implements_trait(cx, ty, id, &[]) + } else { + return; + } + }; + + if implements_partial_ord && !implements_ord { + cx.span_lint( + NEG_CMP_OP_ON_PARTIAL_ORD, + expr.span, + "The use of negated comparision operators on partially orded\ + types produces code that is hard to read and refactor. Please\ + consider to use the partial_cmp() instead, to make it clear\ + that the two values could be incomparable." + ) + } + } + } + } +} diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs new file mode 100644 index 00000000000..daf059040a0 --- /dev/null +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -0,0 +1,59 @@ +/// This test case utilizes `f64` an easy example for `PartialOrd` only types +/// but the lint itself actually validates any expression where the left +/// operand implements `PartialOrd` but not `Ord`. + +use std::cmp::Ordering; + +#[allow(nonminimal_bool)] +#[warn(neg_cmp_op_on_partial_ord)] +fn main() { + + let a_value = 1.0; + let another_value = 7.0; + + // --- Bad --- + + + // Not Less but potentially Greater, Equal or Uncomparable. + let _not_less = !(a_value < another_value); + + // Not Less or Equal but potentially Greater or Uncomparable. + let _not_less_or_equal = !(a_value <= another_value); + + // Not Greater but potentially Less, Equal or Uncomparable. + let _not_greater = !(a_value > another_value); + + // Not Greater or Equal but potentially Less or Uncomparable. + let _not_greater_or_equal = !(a_value >= another_value); + + + // --- Good --- + + + let _not_less = match a_value.partial_cmp(&another_value) { + None | Some(Ordering::Greater) | Some(Ordering::Equal) => true, + _ => false, + }; + let _not_less_or_equal = match a_value.partial_cmp(&another_value) { + None | Some(Ordering::Greater) => true, + _ => false, + }; + let _not_greater = match a_value.partial_cmp(&another_value) { + None | Some(Ordering::Less) | Some(Ordering::Equal) => true, + _ => false, + }; + let _not_greater_or_equal = match a_value.partial_cmp(&another_value) { + None | Some(Ordering::Less) => true, + _ => false, + }; + + + // --- Should not trigger --- + + + let _ = a_value < another_value; + let _ = a_value <= another_value; + let _ = a_value > another_value; + let _ = a_value >= another_value; +} + diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr new file mode 100644 index 00000000000..0402cfd86e8 --- /dev/null +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -0,0 +1,28 @@ +error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. + --> $DIR/neg_cmp_op_on_partial_ord.rs:18:21 + | +18 | let _not_less = !(a_value < another_value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D neg-cmp-op-on-partial-ord` implied by `-D warnings` + +error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. + --> $DIR/neg_cmp_op_on_partial_ord.rs:21:30 + | +21 | let _not_less_or_equal = !(a_value <= another_value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. + --> $DIR/neg_cmp_op_on_partial_ord.rs:24:24 + | +24 | let _not_greater = !(a_value > another_value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. + --> $DIR/neg_cmp_op_on_partial_ord.rs:27:33 + | +27 | let _not_greater_or_equal = !(a_value >= another_value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 86304d8dde8b2771812663a94973396eb3c06cae Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Fri, 1 Jun 2018 13:40:41 +0200 Subject: Use declare_clippy_lint instead of declare_lint. --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 139808f4393..24d18ed24e6 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -37,8 +37,9 @@ const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; /// _ => false, /// }; /// ``` -declare_lint! { - pub NEG_CMP_OP_ON_PARTIAL_ORD, Warn, +declare_clippy_lint! { + pub NEG_CMP_OP_ON_PARTIAL_ORD, + complexity, "The use of negated comparision operators on partially orded types may produce confusing code." } -- cgit 1.4.1-3-g733a5 From 09ea75bee91976cf42e9db52f1eacf826c23d928 Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Fri, 1 Jun 2018 14:40:53 +0200 Subject: Fixed spelling and indentation issues in neg_cmp_op_on_partial_ord related files. --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 6 +++--- tests/ui/neg_cmp_op_on_partial_ord.rs | 6 +++--- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 24d18ed24e6..6b89ded8255 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -84,9 +84,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { cx.span_lint( NEG_CMP_OP_ON_PARTIAL_ORD, expr.span, - "The use of negated comparision operators on partially orded\ - types produces code that is hard to read and refactor. Please\ - consider to use the partial_cmp() instead, to make it clear\ + "The use of negated comparision operators on partially orded \ + types produces code that is hard to read and refactor. Please \ + consider to use the `partial_cmp` instead, to make it clear \ that the two values could be incomparable." ) } diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index daf059040a0..f7fa09550e9 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -32,7 +32,7 @@ fn main() { let _not_less = match a_value.partial_cmp(&another_value) { None | Some(Ordering::Greater) | Some(Ordering::Equal) => true, - _ => false, + _ => false, }; let _not_less_or_equal = match a_value.partial_cmp(&another_value) { None | Some(Ordering::Greater) => true, @@ -40,11 +40,11 @@ fn main() { }; let _not_greater = match a_value.partial_cmp(&another_value) { None | Some(Ordering::Less) | Some(Ordering::Equal) => true, - _ => false, + _ => false, }; let _not_greater_or_equal = match a_value.partial_cmp(&another_value) { None | Some(Ordering::Less) => true, - _ => false, + _ => false, }; diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 0402cfd86e8..5f0c240b459 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,4 +1,4 @@ -error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. +error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:18:21 | 18 | let _not_less = !(a_value < another_value); @@ -6,19 +6,19 @@ error: The use of negated comparision operators on partially ordedtypes produces | = note: `-D neg-cmp-op-on-partial-ord` implied by `-D warnings` -error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. +error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:21:30 | 21 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. +error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:24:24 | 24 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparision operators on partially ordedtypes produces code that is hard to read and refactor. Pleaseconsider to use the partial_cmp() instead, to make it clearthat the two values could be incomparable. +error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:27:33 | 27 | let _not_greater_or_equal = !(a_value >= another_value); -- cgit 1.4.1-3-g733a5 From 80728a22015846f28d32d5b759d04ccf048cdf9b Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Fri, 1 Jun 2018 15:13:53 +0200 Subject: Reduced scope of `nonminimal_bool` so that it doesn't evaluate only partially orded types. --- clippy_lints/src/booleans.rs | 25 ++++++++++++++++++++++++- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 9 +++------ clippy_lints/src/utils/paths.rs | 2 ++ tests/ui/neg_cmp_op_on_partial_ord.rs | 1 - tests/ui/neg_cmp_op_on_partial_ord.stderr | 16 ++++++++-------- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index c814c1abcd1..8816d50c5c2 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; use syntax::util::ThinVec; -use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq}; +use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -122,6 +122,12 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { + + match implements_ord(self.cx, lhs) { + Some(true) => (), + _ => continue, + }; + let mk_expr = |op| { Expr { id: DUMMY_NODE_ID, @@ -174,6 +180,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { fn simplify_not(&self, expr: &Expr) -> Option { match expr.node { ExprBinary(binop, ref lhs, ref rhs) => { + + match implements_ord(self.cx, lhs) { + Some(true) => (), + _ => return None, + }; + match binop.node { BiEq => Some(" != "), BiNe => Some(" == "), @@ -444,3 +456,14 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { NestedVisitorMap::None } } + + +fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> Option { + let ty = cx.tables.expr_ty(expr); + + return if let Some(id) = get_trait_def_id(cx, &paths::ORD) { + Some(implements_trait(cx, ty, id, &[])) + } else { + None + }; +} diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 6b89ded8255..8e70d0eeba0 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,10 +1,7 @@ use rustc::hir::*; use rustc::lint::*; -use crate::utils; - -const ORD: [&str; 3] = ["core", "cmp", "Ord"]; -const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; +use crate::utils::{self, paths}; /// **What it does:** /// Checks for the usage of negated comparision operators on types which only implement @@ -65,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { let ty = cx.tables.expr_ty(left); let implements_ord = { - if let Some(id) = utils::get_trait_def_id(cx, &ORD) { + if let Some(id) = utils::get_trait_def_id(cx, &paths::ORD) { utils::implements_trait(cx, ty, id, &[]) } else { return; @@ -73,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { }; let implements_partial_ord = { - if let Some(id) = utils::get_trait_def_id(cx, &PARTIAL_ORD) { + if let Some(id) = utils::get_trait_def_id(cx, &paths::PARTIAL_ORD) { utils::implements_trait(cx, ty, id, &[]) } else { return; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index a1cb6670bc5..ab62346ea7e 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -57,6 +57,8 @@ pub const OPS_MODULE: [&str; 2] = ["core", "ops"]; pub const OPTION: [&str; 3] = ["core", "option", "Option"]; pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"]; pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; +pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; +pub const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index f7fa09550e9..214d627ba30 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -4,7 +4,6 @@ use std::cmp::Ordering; -#[allow(nonminimal_bool)] #[warn(neg_cmp_op_on_partial_ord)] fn main() { diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 5f0c240b459..5067ece8705 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,27 +1,27 @@ error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:18:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:17:21 | -18 | let _not_less = !(a_value < another_value); +17 | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:21:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:20:30 | -21 | let _not_less_or_equal = !(a_value <= another_value); +20 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:24:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:23:24 | -24 | let _not_greater = !(a_value > another_value); +23 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:27:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:26:33 | -27 | let _not_greater_or_equal = !(a_value >= another_value); +26 | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 28f735bb26706af3dddc7fa52ea4122a408cb023 Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Sun, 3 Jun 2018 18:46:11 +0200 Subject: Cleaned implements_ord helper function in boolean lint file. --- clippy_lints/src/booleans.rs | 24 +++++++++--------------- tests/ui/booleans.rs | 10 ++++++++++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 8816d50c5c2..0a453618e19 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -123,10 +123,9 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { - match implements_ord(self.cx, lhs) { - Some(true) => (), - _ => continue, - }; + if !implements_ord(self.cx, lhs) { + continue; + } let mk_expr = |op| { Expr { @@ -181,10 +180,9 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { match expr.node { ExprBinary(binop, ref lhs, ref rhs) => { - match implements_ord(self.cx, lhs) { - Some(true) => (), - _ => return None, - }; + if !implements_ord(self.cx, lhs) { + return None; + } match binop.node { BiEq => Some(" != "), @@ -458,12 +456,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } -fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> Option { +fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> bool { let ty = cx.tables.expr_ty(expr); - - return if let Some(id) = get_trait_def_id(cx, &paths::ORD) { - Some(implements_trait(cx, ty, id, &[])) - } else { - None - }; + get_trait_def_id(cx, &paths::ORD) + .map_or(false, |id| implements_trait(cx, ty, id, &[])) } diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 78e876e5182..9daf15d378c 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -114,3 +114,13 @@ fn warn_for_built_in_methods_with_negation() { if !res.is_some() { } if !res.is_none() { } } + +#[allow(neg_cmp_op_on_partial_ord)] +fn dont_warn_for_negated_partial_ord_comparision() { + let a: f64 = unimplemented!(); + let b: f64 = unimplemented!(); + let _ = !(a < b); + let _ = !(a <= b); + let _ = !(a > b); + let _ = !(a >= b); +} -- cgit 1.4.1-3-g733a5 From 05c1ccebaff84e978c17abcbd9c68b33d1d96e44 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Mon, 28 May 2018 21:00:45 +0200 Subject: Warn if non-trivial work is done inside .expect - added tests for common usages of format and as_str arguments to expect - added tests for usages of Option and Result types - given performance impact of passing non literal expressions to expect, added to perf group --- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/methods.rs | 70 +++++++++++++++++++++++++++++++++++++++++ tests/ui/methods.rs | 29 +++++++++++++++++ tests/ui/methods.stderr | 76 ++++++++++++++++++++++++++++++--------------- 4 files changed, 152 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 612cde8a6aa..70adaa273eb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -590,6 +590,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::OK_EXPECT, methods::OPTION_MAP_OR_NONE, methods::OR_FUN_CALL, + methods::EXPECT_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, @@ -899,6 +900,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { loops::UNUSED_COLLECT, methods::ITER_NTH, methods::OR_FUN_CALL, + methods::EXPECT_FUN_CALL, methods::SINGLE_CHAR_PATTERN, misc::CMP_OWNED, mutex_atomic::MUTEX_ATOMIC, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 461efb27f28..553198ae446 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -329,6 +329,32 @@ declare_clippy_lint! { "using any `*or` method with a function call, which suggests `*or_else`" } +/// **What it does:** Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`, +/// etc., and suggests to use `unwrap_or_else` instead +/// +/// **Why is this bad?** The function will always be called. +/// +/// **Known problems:** If the function has side-effects, not calling it will +/// change the semantic of the program, but you shouldn't rely on that anyway. +/// +/// **Example:** +/// ```rust +/// foo.expect(&format("Err {}: {}", err_code, err_msg)) +/// ``` +/// or +/// ```rust +/// foo.expect(format("Err {}: {}", err_code, err_msg).as_str()) +/// ``` +/// this can instead be written: +/// ```rust +/// foo.unwrap_or_else(|_| panic!(&format("Err {}: {}", err_code, err_msg))) +/// ``` +declare_clippy_lint! { + pub EXPECT_FUN_CALL, + perf, + "using any `expect` method with a function call" +} + /// **What it does:** Checks for usage of `.clone()` on a `Copy` type. /// /// **Why is this bad?** The only reason `Copy` types implement `Clone` is for @@ -657,6 +683,7 @@ impl LintPass for Pass { RESULT_MAP_UNWRAP_OR_ELSE, OPTION_MAP_OR_NONE, OR_FUN_CALL, + EXPECT_FUN_CALL, CHARS_NEXT_CMP, CHARS_LAST_CMP, CLONE_ON_COPY, @@ -741,6 +768,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } lint_or_fun_call(cx, expr, *method_span, &method_call.name.as_str(), args); + lint_expect_fun_call(cx, expr, *method_span, &method_call.name.as_str(), args); let self_ty = cx.tables.expr_ty_adjusted(&args[0]); if args.len() == 1 && method_call.name == "clone" { @@ -964,6 +992,48 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: } } +/// Checks for the `EXPECT_FUN_CALL` lint. +fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { + #[allow(too_many_arguments)] + fn check_general_case( + cx: &LateContext, + name: &str, + method_span: Span, + arg: &hir::Expr, + span: Span, + ) { + if name != "expect" { + return; + } + + // don't lint for constant values + let owner_def = cx.tcx.hir.get_parent_did(arg.id); + let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); + if promotable { + return; + } + + let sugg: Cow<_> = snippet(cx, arg.span, ".."); + let span_replace_word = method_span.with_hi(span.hi()); + + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else(|_| panic!({}))", sugg), + ); + } + + if args.len() == 2 { + match args[1].node { + hir::ExprLit(_) => {}, + _ => check_general_case(cx, name, method_span, &args[1], expr.span), + } + } +} + /// Checks for the `CLONE_ON_COPY` lint. fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) { let ty = cx.tables.expr_ty(expr); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 9e253655833..04e3ec13b86 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -342,6 +342,35 @@ fn or_fun_call() { let _ = stringy.unwrap_or("".to_owned()); } +/// Checks implementation of the `EXPECT_FUN_CALL` lint +fn expect_fun_call() { + let with_some = Some("value"); + with_some.expect("error"); + + let with_none: Option = None; + with_none.expect("error"); + + let error_code = 123_i32; + let with_none_and_format: Option = None; + with_none_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_none_and_as_str: Option = None; + with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + let with_ok: Result<(), ()> = Ok(()); + with_ok.expect("error"); + + let with_err: Result<(), ()> = Err(()); + with_err.expect("error"); + + let error_code = 123_i32; + let with_err_and_format: Result<(), ()> = Err(()); + with_err_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_err_and_as_str: Result<(), ()> = Err(()); + with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +} + /// Checks implementation of `ITER_NTH` lint fn iter_nth() { let mut some_vec = vec![0, 1, 2, 3]; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 1dd1ddc3caa..2fe374f3541 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -423,83 +423,109 @@ error: use of `unwrap_or` followed by a function call 342 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` +error: use of `expect` followed by a function call + --> $DIR/methods.rs:355:26 + | +355 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(&format!("Error {}: fake error", error_code)))` + | + = note: `-D expect-fun-call` implied by `-D warnings` + +error: use of `expect` followed by a function call + --> $DIR/methods.rs:358:26 + | +358 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` + +error: use of `expect` followed by a function call + --> $DIR/methods.rs:368:25 + | +368 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(&format!("Error {}: fake error", error_code)))` + +error: use of `expect` followed by a function call + --> $DIR/methods.rs:371:25 + | +371 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` + error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:353:23 + --> $DIR/methods.rs:382:23 | -353 | let bad_vec = some_vec.iter().nth(3); +382 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:354:26 + --> $DIR/methods.rs:383:26 | -354 | let bad_slice = &some_vec[..].iter().nth(3); +383 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:355:31 + --> $DIR/methods.rs:384:31 | -355 | let bad_boxed_slice = boxed_slice.iter().nth(3); +384 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:356:29 + --> $DIR/methods.rs:385:29 | -356 | let bad_vec_deque = some_vec_deque.iter().nth(3); +385 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:361:23 + --> $DIR/methods.rs:390:23 | -361 | let bad_vec = some_vec.iter_mut().nth(3); +390 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:364:26 + --> $DIR/methods.rs:393:26 | -364 | let bad_slice = &some_vec[..].iter_mut().nth(3); +393 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:367:29 + --> $DIR/methods.rs:396:29 | -367 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +396 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:379:13 + --> $DIR/methods.rs:408:13 | -379 | let _ = some_vec.iter().skip(42).next(); +408 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:380:13 + --> $DIR/methods.rs:409:13 | -380 | let _ = some_vec.iter().cycle().skip(42).next(); +409 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:381:13 + --> $DIR/methods.rs:410:13 | -381 | let _ = (1..10).skip(10).next(); +410 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:382:14 + --> $DIR/methods.rs:411:14 | -382 | let _ = &some_vec[..].iter().skip(3).next(); +411 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:391:13 + --> $DIR/methods.rs:420:13 | -391 | let _ = opt.unwrap(); +420 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -error: aborting due to 66 previous errors +error: aborting due to 70 previous errors -- cgit 1.4.1-3-g733a5 From 2b36017bada5f179d3b6d7b57df0559ba5eeb25b Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Tue, 29 May 2018 09:29:48 +0200 Subject: Removing unnecessary allow --- clippy_lints/src/methods.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 553198ae446..b3c4bad251b 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -994,7 +994,6 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { - #[allow(too_many_arguments)] fn check_general_case( cx: &LateContext, name: &str, -- cgit 1.4.1-3-g733a5 From fe8c9d596543955e0513b239669916b55693dff4 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Tue, 29 May 2018 09:46:14 +0200 Subject: Ensuring correct lint message is output for Option and Result type --- clippy_lints/src/methods.rs | 11 +++++++++-- tests/ui/methods.stderr | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index b3c4bad251b..696bd02cf55 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -998,6 +998,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n cx: &LateContext, name: &str, method_span: Span, + self_expr: &hir::Expr, arg: &hir::Expr, span: Span, ) { @@ -1005,6 +1006,12 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n return; } + let self_ty = cx.tables.expr_ty(self_expr); + let closure = match match_type(cx, self_ty, &paths::OPTION) { + true => "||", + false => "|_|", + }; + // don't lint for constant values let owner_def = cx.tcx.hir.get_parent_did(arg.id); let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); @@ -1021,14 +1028,14 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n span_replace_word, &format!("use of `{}` followed by a function call", name), "try this", - format!("unwrap_or_else(|_| panic!({}))", sugg), + format!("unwrap_or_else({} panic!({}))", closure, sugg), ); } if args.len() == 2 { match args[1].node { hir::ExprLit(_) => {}, - _ => check_general_case(cx, name, method_span, &args[1], expr.span), + _ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span), } } } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 2fe374f3541..f3c608cb715 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -427,7 +427,7 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:355:26 | 355 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(&format!("Error {}: fake error", error_code)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(&format!("Error {}: fake error", error_code)))` | = note: `-D expect-fun-call` implied by `-D warnings` @@ -435,7 +435,7 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:358:26 | 358 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))` error: use of `expect` followed by a function call --> $DIR/methods.rs:368:25 -- cgit 1.4.1-3-g733a5 From 1ead12c5004cf54c3f0469a19909bf49321926f7 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Tue, 29 May 2018 10:20:18 +0200 Subject: Adding handling and tests for custom type with implemented expect method --- clippy_lints/src/methods.rs | 17 ++++++++---- tests/ui/methods.rs | 19 ++++++++++++++ tests/ui/methods.stderr | 64 ++++++++++++++++++++++----------------------- 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 696bd02cf55..38413c5aa4d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1006,11 +1006,13 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n return; } - let self_ty = cx.tables.expr_ty(self_expr); - let closure = match match_type(cx, self_ty, &paths::OPTION) { - true => "||", - false => "|_|", - }; + let self_type = cx.tables.expr_ty(self_expr); + let known_types = &[&paths::OPTION, &paths::RESULT]; + + // if not a known type, return early + if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { + return; + } // don't lint for constant values let owner_def = cx.tcx.hir.get_parent_did(arg.id); @@ -1019,6 +1021,11 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n return; } + let closure = match match_type(cx, self_type, &paths::OPTION) { + true => "||", + false => "|_|", + }; + let sugg: Cow<_> = snippet(cx, arg.span, ".."); let span_replace_word = method_span.with_hi(span.hi()); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 04e3ec13b86..b04c008ba23 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -344,6 +344,16 @@ fn or_fun_call() { /// Checks implementation of the `EXPECT_FUN_CALL` lint fn expect_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Self { Foo } + + fn expect(&self, msg: &str) { + panic!("{}", msg) + } + } + let with_some = Some("value"); with_some.expect("error"); @@ -369,6 +379,15 @@ fn expect_fun_call() { let with_err_and_as_str: Result<(), ()> = Err(()); with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + let with_dummy_type = Foo::new(); + with_dummy_type.expect("another test string"); + + let with_dummy_type_and_format = Foo::new(); + with_dummy_type_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_dummy_type_and_as_str = Foo::new(); + with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); } /// Checks implementation of `ITER_NTH` lint diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index f3c608cb715..65b5589a9c1 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -424,105 +424,105 @@ error: use of `unwrap_or` followed by a function call | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: use of `expect` followed by a function call - --> $DIR/methods.rs:355:26 + --> $DIR/methods.rs:365:26 | -355 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); +365 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(&format!("Error {}: fake error", error_code)))` | = note: `-D expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/methods.rs:358:26 + --> $DIR/methods.rs:368:26 | -358 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +368 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:368:25 + --> $DIR/methods.rs:378:25 | -368 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); +378 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(&format!("Error {}: fake error", error_code)))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:371:25 + --> $DIR/methods.rs:381:25 | -371 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +381 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:382:23 + --> $DIR/methods.rs:401:23 | -382 | let bad_vec = some_vec.iter().nth(3); +401 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:383:26 + --> $DIR/methods.rs:402:26 | -383 | let bad_slice = &some_vec[..].iter().nth(3); +402 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:384:31 + --> $DIR/methods.rs:403:31 | -384 | let bad_boxed_slice = boxed_slice.iter().nth(3); +403 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:385:29 + --> $DIR/methods.rs:404:29 | -385 | let bad_vec_deque = some_vec_deque.iter().nth(3); +404 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:390:23 + --> $DIR/methods.rs:409:23 | -390 | let bad_vec = some_vec.iter_mut().nth(3); +409 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:393:26 + --> $DIR/methods.rs:412:26 | -393 | let bad_slice = &some_vec[..].iter_mut().nth(3); +412 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:396:29 + --> $DIR/methods.rs:415:29 | -396 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +415 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:408:13 + --> $DIR/methods.rs:427:13 | -408 | let _ = some_vec.iter().skip(42).next(); +427 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:409:13 + --> $DIR/methods.rs:428:13 | -409 | let _ = some_vec.iter().cycle().skip(42).next(); +428 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:410:13 + --> $DIR/methods.rs:429:13 | -410 | let _ = (1..10).skip(10).next(); +429 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:411:14 + --> $DIR/methods.rs:430:14 | -411 | let _ = &some_vec[..].iter().skip(3).next(); +430 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:420:13 + --> $DIR/methods.rs:439:13 | -420 | let _ = opt.unwrap(); +439 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 32404741c67a3262143e1f00f9fb31c86e684444 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Mon, 4 Jun 2018 19:19:01 +0100 Subject: Replacing match block with if block as conditional was boolean --- clippy_lints/src/methods.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 38413c5aa4d..aad2f090886 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1021,10 +1021,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n return; } - let closure = match match_type(cx, self_type, &paths::OPTION) { - true => "||", - false => "|_|", - }; + let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; let sugg: Cow<_> = snippet(cx, arg.span, ".."); let span_replace_word = method_span.with_hi(span.hi()); -- cgit 1.4.1-3-g733a5 From 451fd5feb9d68c0c9a130b5d36ae73bae06c4200 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Tue, 5 Jun 2018 21:15:08 +0100 Subject: Extracting arguments to format to pass directly to panic when appropriate --- clippy_lints/src/methods.rs | 40 +++++++++++++++++++++++++++++++++++++++- tests/ui/methods.stderr | 4 ++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index aad2f090886..d9c0f5950c0 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1022,9 +1022,47 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; + let span_replace_word = method_span.with_hi(span.hi()); + + if let hir::ExprAddrOf(_, ref addr_of) = arg.node { + if let hir::ExprCall(ref _inner_fun, ref inner_args) = addr_of.node { + // TODO: check if inner_fun is call to format! + if inner_args.len() == 1 { + if let hir::ExprCall(_, ref format_args) = inner_args[0].node { + let args_len = format_args.len(); + let args: Vec = format_args + .into_iter() + .take(args_len - 1) + .map(|a| { + if let hir::ExprAddrOf(_, ref format_arg) = a.node { + if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node { + if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node { + return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); + } + } + }; + snippet(cx, a.span, "..").into_owned() + }) + .collect(); + + let sugg = args.join(", "); + + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} panic!({}))", closure, sugg), + ); + + return; + } + } + } + } let sugg: Cow<_> = snippet(cx, arg.span, ".."); - let span_replace_word = method_span.with_hi(span.hi()); span_lint_and_sugg( cx, diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 65b5589a9c1..edf081aaa47 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -427,7 +427,7 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:365:26 | 365 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(&format!("Error {}: fake error", error_code)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D expect-fun-call` implied by `-D warnings` @@ -441,7 +441,7 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:378:25 | 378 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(&format!("Error {}: fake error", error_code)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/methods.rs:381:25 -- cgit 1.4.1-3-g733a5 From e67d2b26635e7c03346a331ba52703a78a1986aa Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Wed, 6 Jun 2018 16:53:11 +0100 Subject: Added check to ensure format macro only being handled, refactored extraction and checks to smaller functions. --- clippy_lints/src/methods.rs | 84 ++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d9c0f5950c0..7d65193b1aa 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -7,8 +7,8 @@ use std::fmt; use std::iter; use syntax::ast; use syntax::codemap::{Span, BytePos}; -use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, - iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, +use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self, + is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use crate::utils::paths; @@ -994,6 +994,34 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { + fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { + if let hir::ExprAddrOf(_, ref addr_of) = arg.node { + if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node { + if let Some(_) = is_expn_of(inner_fun.span, "format") { + if inner_args.len() == 1 { + if let hir::ExprCall(_, ref format_args) = inner_args[0].node { + return Some(format_args); + } + } + } + } + } + + None + } + + fn generate_format_arg_snippet(cx: &LateContext, a: &hir::Expr) -> String { + if let hir::ExprAddrOf(_, ref format_arg) = a.node { + if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node { + if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node { + return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); + } + } + }; + + snippet(cx, a.span, "..").into_owned() + } + fn check_general_case( cx: &LateContext, name: &str, @@ -1024,42 +1052,26 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; let span_replace_word = method_span.with_hi(span.hi()); - if let hir::ExprAddrOf(_, ref addr_of) = arg.node { - if let hir::ExprCall(ref _inner_fun, ref inner_args) = addr_of.node { - // TODO: check if inner_fun is call to format! - if inner_args.len() == 1 { - if let hir::ExprCall(_, ref format_args) = inner_args[0].node { - let args_len = format_args.len(); - let args: Vec = format_args - .into_iter() - .take(args_len - 1) - .map(|a| { - if let hir::ExprAddrOf(_, ref format_arg) = a.node { - if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node { - if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node { - return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); - } - } - }; - snippet(cx, a.span, "..").into_owned() - }) - .collect(); - - let sugg = args.join(", "); + if let Some(format_args) = extract_format_args(arg) { + let args_len = format_args.len(); + let args: Vec = format_args + .into_iter() + .take(args_len - 1) + .map(|a| generate_format_arg_snippet(cx, a)) + .collect(); - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("unwrap_or_else({} panic!({}))", closure, sugg), - ); + let sugg = args.join(", "); - return; - } - } - } + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} panic!({}))", closure, sugg), + ); + + return; } let sugg: Cow<_> = snippet(cx, arg.span, ".."); -- cgit 1.4.1-3-g733a5 From 9c73f7ff18d413cb014acba7b1786044b4e00c70 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Wed, 6 Jun 2018 17:13:31 +0100 Subject: Amending use of Some with discarded value to use is_some --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 7d65193b1aa..9a93354af29 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -997,7 +997,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { if let hir::ExprAddrOf(_, ref addr_of) = arg.node { if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node { - if let Some(_) = is_expn_of(inner_fun.span, "format") { + if is_expn_of(inner_fun.span, "format").is_some() { if inner_args.len() == 1 { if let hir::ExprCall(_, ref format_args) = inner_args[0].node { return Some(format_args); -- cgit 1.4.1-3-g733a5 From e70632215e8cb6272599b1d07bfc0712f8a0d70a Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Wed, 6 Jun 2018 20:38:13 +0100 Subject: Combining if statements per lint warnings on build --- clippy_lints/src/methods.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9a93354af29..aafc612b512 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -997,11 +997,9 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { if let hir::ExprAddrOf(_, ref addr_of) = arg.node { if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node { - if is_expn_of(inner_fun.span, "format").is_some() { - if inner_args.len() == 1 { - if let hir::ExprCall(_, ref format_args) = inner_args[0].node { - return Some(format_args); - } + if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { + if let hir::ExprCall(_, ref format_args) = inner_args[0].node { + return Some(format_args); } } } -- cgit 1.4.1-3-g733a5 From 17aff1d774b11ef68c122c995b1d2b238ff5fb04 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 18 May 2018 22:56:25 +0200 Subject: Fix cargo late bound region mismatch ICE --- clippy_lints/src/utils/mod.rs | 6 +++++- tests/run-pass/ice-2774.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/run-pass/ice-2774.rs diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4a30b134a69..a49464b021a 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,7 +8,7 @@ use rustc::hir::map::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; +use rustc::ty::{self, Binder, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; @@ -869,10 +869,14 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t } /// Check if two types are the same. +/// +/// This discards any lifetime annotations, too. // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for // <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + let a = cx.tcx.erase_late_bound_regions(&Binder::bind(a)); + let b = cx.tcx.erase_late_bound_regions(&Binder::bind(b)); cx.tcx .infer_ctxt() .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs new file mode 100644 index 00000000000..c6d9bb4a276 --- /dev/null +++ b/tests/run-pass/ice-2774.rs @@ -0,0 +1,31 @@ +use std::collections::HashSet; + +// See https://github.com/rust-lang-nursery/rust-clippy/issues/2774 + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Bar { + foo: Foo, +} + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Foo {} + +#[allow(implicit_hasher)] +// This should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { + let mut foos = HashSet::new(); + foos.extend( + bars.iter().map(|b| &b.foo) + ); +} + +#[allow(implicit_hasher)] +// Also this should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { + let mut foos = HashSet::new(); + foos.extend( + bars.iter().map(|b| &b.foo) + ); +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From e3fd348cd4417a920faa35f1ccbe7bf1702222b1 Mon Sep 17 00:00:00 2001 From: Chris West Date: Thu, 7 Jun 2018 17:47:11 +0100 Subject: Tiny typo in rust-update script --- rust-update | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-update b/rust-update index a987bbe94ff..d065319c736 100755 --- a/rust-update +++ b/rust-update @@ -2,7 +2,7 @@ if [ "$1" = '-h' ] ; then echo 'Updates rustc & clippy' - echo 'It first checks if clippy would compile at currentl nightly and if so, it updates.' + echo 'It first checks if clippy would compile at current nightly and if so, it updates.' echo 'Options:' echo '-h: This help message' echo '-f: Skips the check and just updates' -- cgit 1.4.1-3-g733a5 From 52deb3b0863558315b57b801804820254d4eaa4e Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 7 Jun 2018 19:16:41 +0200 Subject: Prepare for upcoming breakage --- src/driver.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index a88d6e5c26d..217bcca45de 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -21,14 +21,14 @@ use std::process::Command; use syntax::ast; struct ClippyCompilerCalls { - default: RustcDefaultCalls, + default: Box, run_lints: bool, } impl ClippyCompilerCalls { fn new(run_lints: bool) -> Self { Self { - default: RustcDefaultCalls, + default: Box::new(RustcDefaultCalls), run_lints, } } @@ -69,8 +69,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { self.default .late_callback(trans_crate, matches, sess, crate_stores, input, odir, ofile) } - fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut control = self.default.build_controller(sess, matches); + fn build_controller(self: Box, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { + let mut control = self.default.clone().build_controller(sess, matches); if self.run_lints { let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); @@ -198,6 +198,6 @@ pub fn main() { } } - let mut ccc = ClippyCompilerCalls::new(clippy_enabled); - rustc_driver::run(move || rustc_driver::run_compiler(&args, &mut ccc, None, None)); + let ccc = ClippyCompilerCalls::new(clippy_enabled); + rustc_driver::run(move || rustc_driver::run_compiler(&args, Box::new(ccc), None, None)); } -- cgit 1.4.1-3-g733a5 From 3693a4ea53d15d268d74bc9773daa8702ea2d5ba Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 7 Jun 2018 19:16:50 +0200 Subject: Formatting --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/array_indexing.rs | 4 ++-- clippy_lints/src/assign_ops.rs | 4 ++-- tests/compile-test.rs | 15 +++++++-------- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 704546a1eb3..0288176f436 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,9 +1,9 @@ +use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::*; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; -use crate::utils::span_lint; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index ff32fcb7843..a9ccc336a19 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,7 +1,7 @@ +use crate::utils::span_lint; use rustc::hir; use rustc::lint::*; use syntax::codemap::Span; -use crate::utils::span_lint; /// **What it does:** Checks for plain integer arithmetic. /// diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 6002960fe2c..77aa5e83425 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,10 +1,10 @@ use crate::consts::{constant, Constant}; +use crate::utils::higher::Range; +use crate::utils::{self, higher}; use rustc::hir; use rustc::lint::*; use rustc::ty; use syntax::ast::RangeLimits; -use crate::utils::higher::Range; -use crate::utils::{self, higher}; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 44398a9710f..ba405610c90 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,9 +1,9 @@ +use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; +use crate::utils::{higher, sugg}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::ast; -use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; -use crate::utils::{higher, sugg}; /// **What it does:** Checks for compound assignment operations (`+=` and /// similar). diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 236cce0dbb7..da5c5bd3227 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,10 +3,10 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::io; +use std::env::{set_var, var}; use std::ffi::OsStr; use std::fs; -use std::env::{set_var, var}; +use std::io; use std::path::{Path, PathBuf}; fn clippy_driver_path() -> PathBuf { @@ -93,12 +93,11 @@ fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec {} + Ok(true) => {}, Ok(false) => panic!("Some tests failed"), Err(e) => { println!("I/O failure during tests: {:?}", e); - } + }, } } -- cgit 1.4.1-3-g733a5 From b45fb35ec4cff21d027fa25dd31b5045867ccf03 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 7 Jun 2018 22:03:15 +0200 Subject: Cleanup of driver code --- src/driver.rs | 158 +++++++++++++++++----------------------------------------- 1 file changed, 46 insertions(+), 112 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 217bcca45de..830c8985660 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -12,117 +12,8 @@ extern crate rustc_errors; extern crate rustc_plugin; extern crate syntax; -use rustc::session::config::{ErrorOutputType, Input}; -use rustc::session::{config, Session}; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use std::path::PathBuf; +use rustc_driver::{driver::CompileController, Compilation}; use std::process::Command; -use syntax::ast; - -struct ClippyCompilerCalls { - default: Box, - run_lints: bool, -} - -impl ClippyCompilerCalls { - fn new(run_lints: bool) -> Self { - Self { - default: Box::new(RustcDefaultCalls), - run_lints, - } - } -} - -impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { - fn early_callback( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - descriptions: &rustc_errors::registry::Registry, - output: ErrorOutputType, - ) -> Compilation { - self.default.early_callback(matches, sopts, cfg, descriptions, output) - } - fn no_input( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - odir: &Option, - ofile: &Option, - descriptions: &rustc_errors::registry::Registry, - ) -> Option<(Input, Option)> { - self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions) - } - fn late_callback( - &mut self, - trans_crate: &CodegenBackend, - matches: &getopts::Matches, - sess: &Session, - crate_stores: &rustc::middle::cstore::CrateStore, - input: &Input, - odir: &Option, - ofile: &Option, - ) -> Compilation { - self.default - .late_callback(trans_crate, matches, sess, crate_stores, input, odir, ofile) - } - fn build_controller(self: Box, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut control = self.default.clone().build_controller(sess, matches); - - if self.run_lints { - let old = std::mem::replace(&mut control.after_parse.callback, box |_| {}); - control.after_parse.callback = Box::new(move |state| { - { - let mut registry = rustc_plugin::registry::Registry::new( - state.session, - state - .krate - .as_ref() - .expect( - "at this compilation stage \ - the crate must be parsed", - ) - .span, - ); - registry.args_hidden = Some(Vec::new()); - clippy_lints::register_plugins(&mut registry); - - let rustc_plugin::registry::Registry { - early_lint_passes, - late_lint_passes, - lint_groups, - llvm_passes, - attributes, - .. - } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } - - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); - } - - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - } - old(state); - }); - - control.compilation_done.stop = Compilation::Stop; - } - - control - } -} #[allow(print_stdout)] fn show_version() { @@ -198,6 +89,49 @@ pub fn main() { } } - let ccc = ClippyCompilerCalls::new(clippy_enabled); - rustc_driver::run(move || rustc_driver::run_compiler(&args, Box::new(ccc), None, None)); + let mut controller = CompileController::basic(); + if clippy_enabled { + controller.after_parse.callback = Box::new(move |state| { + let mut registry = rustc_plugin::registry::Registry::new( + state.session, + state + .krate + .as_ref() + .expect( + "at this compilation stage \ + the crate must be parsed", + ) + .span, + ); + registry.args_hidden = Some(Vec::new()); + clippy_lints::register_plugins(&mut registry); + + let rustc_plugin::registry::Registry { + early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + .. + } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } + + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } + + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + }); + } + controller.compilation_done.stop = Compilation::Stop; + + rustc_driver::run_compiler(&args, Box::new(controller), None, None); } -- cgit 1.4.1-3-g733a5 From 81821acd59a051b5fb0b6e6dc9eeac894c92d758 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Mon, 28 May 2018 00:02:38 +0200 Subject: Implement lint that checks for unidiomatic `unwrap()` (fixes #1770) This checks for things like if x.is_some() { x.unwrap() } which should be written using `if let` or `match` instead. In the process I moved some logic to determine which variables are mutated in an expression to utils/usage.rs. --- clippy_lints/src/lib.rs | 4 + clippy_lints/src/loops.rs | 83 ++++------------ clippy_lints/src/unwrap.rs | 176 ++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/utils/usage.rs | 82 ++++++++++++++++ tests/ui/checked_unwrap.rs | 73 ++++++++++++++ tests/ui/checked_unwrap.stderr | 207 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 560 insertions(+), 66 deletions(-) create mode 100644 clippy_lints/src/unwrap.rs create mode 100644 clippy_lints/src/utils/usage.rs create mode 100644 tests/ui/checked_unwrap.rs create mode 100644 tests/ui/checked_unwrap.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f4bf3c44711..c4dfc1f0168 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -200,6 +200,7 @@ pub mod unicode; pub mod unsafe_removed_from_name; pub mod unused_io_amount; pub mod unused_label; +pub mod unwrap; pub mod use_self; pub mod vec; pub mod write; @@ -421,6 +422,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box infallible_destructuring_match::Pass); reg.register_late_lint_pass(box inherent_impl::Pass::default()); reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); + reg.register_late_lint_pass(box unwrap::Pass); + reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -837,6 +840,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::UNIT_ARG, types::UNNECESSARY_CAST, unused_label::UNUSED_LABEL, + unwrap::UNNECESSARY_UNWRAP, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 4d312b79818..20b10db0d66 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -18,6 +18,7 @@ use std::iter::{once, Iterator}; use syntax::ast; use syntax::codemap::Span; use crate::utils::{sugg, sext}; +use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, @@ -504,8 +505,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } // check for while loops which conditions never change - if let ExprWhile(ref cond, ref block, _) = expr.node { - check_infinite_loop(cx, cond, block, expr); + if let ExprWhile(ref cond, _, _) = expr.node { + check_infinite_loop(cx, cond, expr); } } @@ -2145,35 +2146,30 @@ fn path_name(e: &Expr) -> Option { None } -fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, block: &'tcx Block, expr: &'tcx Expr) { +fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, expr: &'tcx Expr) { if constant(cx, cx.tables, cond).is_some() { // A pure constant condition (e.g. while false) is not linted. return; } - let mut mut_var_visitor = VarCollectorVisitor { + let mut var_visitor = VarCollectorVisitor { cx, - ids: HashMap::new(), + ids: HashSet::new(), def_ids: HashMap::new(), skip: false, }; - mut_var_visitor.visit_expr(cond); - if mut_var_visitor.skip { + var_visitor.visit_expr(cond); + if var_visitor.skip { return; } - - let mut delegate = MutVarsDelegate { - used_mutably: mut_var_visitor.ids, - skip: false, + let used_in_condition = &var_visitor.ids; + let no_cond_variable_mutated = if let Some(used_mutably) = mutated_variables(expr, cx) { + used_in_condition.is_disjoint(&used_mutably) + } else { + return }; - let def_id = def_id::DefId::local(block.hir_id.owner); - let region_scope_tree = &cx.tcx.region_scope_tree(def_id); - ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(expr); - - if delegate.skip { - return; - } - if !(delegate.used_mutably.iter().any(|(_, v)| *v) || mut_var_visitor.def_ids.iter().any(|(_, v)| *v)) { + let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v); + if no_cond_variable_mutated && !mutable_static_in_cond { span_lint( cx, WHILE_IMMUTABLE_CONDITION, @@ -2189,7 +2185,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b /// All variables definition IDs are collected struct VarCollectorVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ids: HashMap, + ids: HashSet, def_ids: HashMap, skip: bool, } @@ -2203,7 +2199,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { then { match def { Def::Local(node_id) | Def::Upvar(node_id, ..) => { - self.ids.insert(node_id, false); + self.ids.insert(node_id); }, Def::Static(def_id, mutable) => { self.def_ids.insert(def_id, mutable); @@ -2230,48 +2226,3 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { NestedVisitorMap::None } } - -struct MutVarsDelegate { - used_mutably: HashMap, - skip: bool, -} - -impl<'tcx> MutVarsDelegate { - fn update(&mut self, cat: &'tcx Categorization) { - match *cat { - Categorization::Local(id) => - if let Some(used) = self.used_mutably.get_mut(&id) { - *used = true; - }, - Categorization::Upvar(_) => { - //FIXME: This causes false negatives. We can't get the `NodeId` from - //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the - //`while`-body, not just the ones in the condition. - self.skip = true - }, - Categorization::Deref(ref cmt, _) | Categorization::Interior(ref cmt, _) => self.update(&cmt.cat), - _ => {} - } - } -} - - -impl<'tcx> Delegate<'tcx> for MutVarsDelegate { - fn consume(&mut self, _: NodeId, _: Span, _: &cmt_<'tcx>, _: ConsumeMode) {} - - fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} - - fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} - - fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { - if let ty::BorrowKind::MutBorrow = bk { - self.update(&cmt.cat) - } - } - - fn mutate(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: MutateMode) { - self.update(&cmt.cat) - } - - fn decl_without_init(&mut self, _: NodeId, _: Span) {} -} diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs new file mode 100644 index 00000000000..6d209acef39 --- /dev/null +++ b/clippy_lints/src/unwrap.rs @@ -0,0 +1,176 @@ +use rustc::lint::*; + +use rustc::hir::intravisit::*; +use rustc::hir::*; +use syntax::ast::NodeId; +use syntax::codemap::Span; +use crate::utils::{in_macro, match_type, paths, usage::is_potentially_mutated}; + +/// **What it does:** Checks for calls of unwrap[_err]() that cannot fail. +/// +/// **Why is this bad?** Using `if let` or `match` is more idiomatic. +/// +/// **Known problems:** Limitations of the borrow checker might make unwrap() necessary sometimes? +/// +/// **Example:** +/// ```rust +/// if option.is_some() { +/// do_something_with(option.unwrap()) +/// } +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// if let Some(value) = option { +/// do_something_with(value) +/// } +/// ``` +declare_clippy_lint! { + pub UNNECESSARY_UNWRAP, + complexity, + "checks for calls of unwrap[_err]() that cannot fail" +} + +pub struct Pass; + +/// Visitor that keeps track of which variables are unwrappable. +struct UnwrappableVariablesVisitor<'a, 'tcx: 'a> { + unwrappables: Vec>, + cx: &'a LateContext<'a, 'tcx>, +} +/// Contains information about whether a variable can be unwrapped. +#[derive(Copy, Clone, Debug)] +struct UnwrapInfo<'tcx> { + /// The variable that is checked + ident: &'tcx Path, + /// The check, like `x.is_ok()` + check: &'tcx Expr, + /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`). + safe_to_unwrap: bool, +} + +/// Collects the information about unwrappable variables from an if condition +/// The `invert` argument tells us whether the condition is negated. +fn collect_unwrap_info<'a, 'tcx: 'a>( + cx: &'a LateContext<'a, 'tcx>, + expr: &'tcx Expr, + invert: bool, +) -> Vec> { + if let Expr_::ExprBinary(op, left, right) = &expr.node { + match (invert, op.node) { + (false, BinOp_::BiAnd) | (false, BinOp_::BiBitAnd) | (true, BinOp_::BiOr) | (true, BinOp_::BiBitOr) => { + let mut unwrap_info = collect_unwrap_info(cx, left, invert); + unwrap_info.append(&mut collect_unwrap_info(cx, right, invert)); + return unwrap_info; + }, + _ => (), + } + } else if let Expr_::ExprUnary(UnNot, expr) = &expr.node { + return collect_unwrap_info(cx, expr, !invert); + } else { + if_chain! { + if let Expr_::ExprMethodCall(method_name, _, args) = &expr.node; + if let Expr_::ExprPath(QPath::Resolved(None, path)) = &args[0].node; + let ty = cx.tables.expr_ty(&args[0]); + if match_type(cx, ty, &paths::OPTION) || match_type(cx, ty, &paths::RESULT); + let name = method_name.name.as_str(); + if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name); + then { + assert!(args.len() == 1); + let unwrappable = match name.as_ref() { + "is_some" | "is_ok" => true, + "is_err" | "is_none" => false, + _ => unreachable!(), + }; + let safe_to_unwrap = unwrappable != invert; + return vec![UnwrapInfo { ident: path, check: expr, safe_to_unwrap }]; + } + } + } + Vec::new() +} + +impl<'a, 'tcx: 'a> UnwrappableVariablesVisitor<'a, 'tcx> { + fn visit_branch(&mut self, cond: &'tcx Expr, branch: &'tcx Expr, else_branch: bool) { + let prev_len = self.unwrappables.len(); + for unwrap_info in collect_unwrap_info(self.cx, cond, else_branch) { + if is_potentially_mutated(unwrap_info.ident, cond, self.cx) + || is_potentially_mutated(unwrap_info.ident, branch, self.cx) + { + // if the variable is mutated, we don't know whether it can be unwrapped: + continue; + } + self.unwrappables.push(unwrap_info); + } + walk_expr(self, branch); + self.unwrappables.truncate(prev_len); + } +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if let Expr_::ExprIf(cond, then, els) = &expr.node { + walk_expr(self, cond); + self.visit_branch(cond, then, false); + if let Some(els) = els { + self.visit_branch(cond, els, true); + } + } else { + // find `unwrap[_err]()` calls: + if_chain! { + if let Expr_::ExprMethodCall(ref method_name, _, ref args) = expr.node; + if let Expr_::ExprPath(QPath::Resolved(None, ref path)) = args[0].node; + if ["unwrap", "unwrap_err"].contains(&&*method_name.name.as_str()); + let call_to_unwrap = method_name.name == "unwrap"; + if let Some(unwrappable) = self.unwrappables.iter() + .find(|u| u.ident.def == path.def && call_to_unwrap == u.safe_to_unwrap); + then { + self.cx.span_lint_note( + UNNECESSARY_UNWRAP, + expr.span, + &format!("You checked before that `{}()` cannot fail. \ + Instead of checking and unwrapping, it's better to use `if let` or `match`.", + method_name.name), + unwrappable.check.span, + "the check is happening here", + ); + } + } + walk_expr(self, expr); + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + } +} + +impl<'a> LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(UNNECESSARY_UNWRAP) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl, + body: &'tcx Body, + span: Span, + fn_id: NodeId, + ) { + if in_macro(span) { + return; + } + + let mut v = UnwrappableVariablesVisitor { + cx, + unwrappables: Vec::new(), + }; + + walk_fn(&mut v, kind, decl, body.id(), span, fn_id); + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a49464b021a..6c3f0c25a3e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -32,6 +32,7 @@ pub mod inspector; pub mod internal_lints; pub mod author; pub mod ptr; +pub mod usage; pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>; diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs new file mode 100644 index 00000000000..6d75dfb486d --- /dev/null +++ b/clippy_lints/src/utils/usage.rs @@ -0,0 +1,82 @@ +use rustc::lint::*; + +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::cmt_; +use rustc::middle::mem_categorization::Categorization; +use rustc::ty; +use std::collections::HashSet; +use syntax::ast::NodeId; +use syntax::codemap::Span; + +/// Returns a set of mutated local variable ids or None if mutations could not be determined. +pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { + let mut delegate = MutVarsDelegate { + used_mutably: HashSet::new(), + skip: false, + }; + let def_id = def_id::DefId::local(expr.hir_id.owner); + let region_scope_tree = &cx.tcx.region_scope_tree(def_id); + ExprUseVisitor::new(&mut delegate, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).walk_expr(expr); + + if delegate.skip { + return None; + } + Some(delegate.used_mutably) +} + +pub fn is_potentially_mutated<'a, 'tcx: 'a>( + variable: &'tcx Path, + expr: &'tcx Expr, + cx: &'a LateContext<'a, 'tcx>, +) -> bool { + let id = match variable.def { + Def::Local(id) | Def::Upvar(id, ..) => id, + _ => return true, + }; + mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&id)) +} + +struct MutVarsDelegate { + used_mutably: HashSet, + skip: bool, +} + +impl<'tcx> MutVarsDelegate { + fn update(&mut self, cat: &'tcx Categorization) { + match *cat { + Categorization::Local(id) => { + self.used_mutably.insert(id); + }, + Categorization::Upvar(_) => { + //FIXME: This causes false negatives. We can't get the `NodeId` from + //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the + //`while`-body, not just the ones in the condition. + self.skip = true + }, + Categorization::Deref(ref cmt, _) | Categorization::Interior(ref cmt, _) => self.update(&cmt.cat), + _ => {}, + } + } +} + +impl<'tcx> Delegate<'tcx> for MutVarsDelegate { + fn consume(&mut self, _: NodeId, _: Span, _: &cmt_<'tcx>, _: ConsumeMode) {} + + fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} + + fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} + + fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + if let ty::BorrowKind::MutBorrow = bk { + self.update(&cmt.cat) + } + } + + fn mutate(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: MutateMode) { + self.update(&cmt.cat) + } + + fn decl_without_init(&mut self, _: NodeId, _: Span) {} +} diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs new file mode 100644 index 00000000000..75a5a2a2baa --- /dev/null +++ b/tests/ui/checked_unwrap.rs @@ -0,0 +1,73 @@ +fn main() { + let x = Some(()); + if x.is_some() { + x.unwrap(); + } + if x.is_none() { + // nothing to do here + } else { + x.unwrap(); + } + let mut x: Result<(), ()> = Ok(()); + if x.is_ok() { + x.unwrap(); + } else { + x.unwrap_err(); + } + if x.is_err() { + x.unwrap_err(); + } else { + x.unwrap(); + } + if x.is_ok() { + x = Err(()); + x.unwrap(); + } else { + x = Ok(()); + x.unwrap_err(); + } +} + +fn test_complex_conditions() { + let x: Result<(), ()> = Ok(()); + let y: Result<(), ()> = Ok(()); + if x.is_ok() && y.is_err() { + x.unwrap(); + y.unwrap_err(); + } else { + // not clear whether unwrappable: + x.unwrap_err(); + y.unwrap(); + } + + if x.is_ok() || y.is_ok() { + // not clear whether unwrappable: + x.unwrap(); + y.unwrap(); + } else { + x.unwrap_err(); + y.unwrap_err(); + } + let z: Result<(), ()> = Ok(()); + if x.is_ok() && !(y.is_ok() || z.is_err()) { + x.unwrap(); + y.unwrap_err(); + z.unwrap(); + } + if x.is_ok() || !(y.is_ok() && z.is_err()) { + // not clear what's unwrappable + } else { + x.unwrap_err(); + y.unwrap(); + z.unwrap_err(); + } +} + +fn test_nested() { + fn nested() { + let x = Some(()); + if x.is_some() { + x.unwrap(); + } + } +} diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr new file mode 100644 index 00000000000..337950f2e66 --- /dev/null +++ b/tests/ui/checked_unwrap.stderr @@ -0,0 +1,207 @@ +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:4:9 + | +4 | x.unwrap(); + | ^^^^^^^^^^ + | + = note: `-D unnecessary-unwrap` implied by `-D warnings` +note: the check is happening here + --> $DIR/checked_unwrap.rs:3:8 + | +3 | if x.is_some() { + | ^^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:9:9 + | +9 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:6:8 + | +6 | if x.is_none() { + | ^^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:13:9 + | +13 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:12:8 + | +12 | if x.is_ok() { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:15:9 + | +15 | x.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:12:8 + | +12 | if x.is_ok() { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:18:9 + | +18 | x.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:17:8 + | +17 | if x.is_err() { + | ^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:20:9 + | +20 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:17:8 + | +17 | if x.is_err() { + | ^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:35:9 + | +35 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:34:8 + | +34 | if x.is_ok() && y.is_err() { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:36:9 + | +36 | y.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:34:21 + | +34 | if x.is_ok() && y.is_err() { + | ^^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:48:9 + | +48 | x.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:43:8 + | +43 | if x.is_ok() || y.is_ok() { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:49:9 + | +49 | y.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:43:21 + | +43 | if x.is_ok() || y.is_ok() { + | ^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:53:9 + | +53 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:52:8 + | +52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:54:9 + | +54 | y.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:52:23 + | +52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | ^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:55:9 + | +55 | z.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:52:36 + | +52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | ^^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:60:9 + | +60 | x.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:57:8 + | +57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:61:9 + | +61 | y.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:57:23 + | +57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:62:9 + | +62 | z.unwrap_err(); + | ^^^^^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:57:36 + | +57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/checked_unwrap.rs:70:13 + | +70 | x.unwrap(); + | ^^^^^^^^^^ + | +note: the check is happening here + --> $DIR/checked_unwrap.rs:69:12 + | +69 | if x.is_some() { + | ^^^^^^^^^^^ + +error: aborting due to 17 previous errors + -- cgit 1.4.1-3-g733a5 From 54826cf72e409ab32d56778ada783657171730a6 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Fri, 8 Jun 2018 05:55:11 +0200 Subject: Address review comments. --- clippy_lints/src/unwrap.rs | 10 +- tests/ui/checked_unwrap.rs | 2 + tests/ui/checked_unwrap.stderr | 222 ++++++++++++++++------------------------- 3 files changed, 92 insertions(+), 142 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6d209acef39..db840c79a29 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,10 +1,10 @@ use rustc::lint::*; +use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use rustc::hir::intravisit::*; use rustc::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; -use crate::utils::{in_macro, match_type, paths, usage::is_potentially_mutated}; /// **What it does:** Checks for calls of unwrap[_err]() that cannot fail. /// @@ -28,7 +28,7 @@ use crate::utils::{in_macro, match_type, paths, usage::is_potentially_mutated}; /// ``` declare_clippy_lint! { pub UNNECESSARY_UNWRAP, - complexity, + nursery, "checks for calls of unwrap[_err]() that cannot fail" } @@ -126,14 +126,14 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { if let Some(unwrappable) = self.unwrappables.iter() .find(|u| u.ident.def == path.def && call_to_unwrap == u.safe_to_unwrap); then { - self.cx.span_lint_note( + span_lint_and_then( + self.cx, UNNECESSARY_UNWRAP, expr.span, &format!("You checked before that `{}()` cannot fail. \ Instead of checking and unwrapping, it's better to use `if let` or `match`.", method_name.name), - unwrappable.check.span, - "the check is happening here", + |db| { db.span_label(unwrappable.check.span, "the check is happening here"); }, ); } } diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index 75a5a2a2baa..fec52940614 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,3 +1,5 @@ +#![deny(unnecessary_unwrap)] + fn main() { let x = Some(()); if x.is_some() { diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index 337950f2e66..bfa5ec08f2e 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,207 +1,155 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:4:9 + --> $DIR/checked_unwrap.rs:6:9 | -4 | x.unwrap(); +5 | if x.is_some() { + | ----------- the check is happening here +6 | x.unwrap(); | ^^^^^^^^^^ | - = note: `-D unnecessary-unwrap` implied by `-D warnings` -note: the check is happening here - --> $DIR/checked_unwrap.rs:3:8 +note: lint level defined here + --> $DIR/checked_unwrap.rs:1:9 | -3 | if x.is_some() { - | ^^^^^^^^^^^ +1 | #![deny(unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:9:9 - | -9 | x.unwrap(); - | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:6:8 - | -6 | if x.is_none() { - | ^^^^^^^^^^^ + --> $DIR/checked_unwrap.rs:11:9 + | +8 | if x.is_none() { + | ----------- the check is happening here +... +11 | x.unwrap(); + | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:13:9 + --> $DIR/checked_unwrap.rs:15:9 | -13 | x.unwrap(); +14 | if x.is_ok() { + | --------- the check is happening here +15 | x.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:12:8 - | -12 | if x.is_ok() { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:15:9 + --> $DIR/checked_unwrap.rs:17:9 | -15 | x.unwrap_err(); +14 | if x.is_ok() { + | --------- the check is happening here +... +17 | x.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:12:8 - | -12 | if x.is_ok() { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:18:9 + --> $DIR/checked_unwrap.rs:20:9 | -18 | x.unwrap_err(); +19 | if x.is_err() { + | ---------- the check is happening here +20 | x.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:17:8 - | -17 | if x.is_err() { - | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:20:9 + --> $DIR/checked_unwrap.rs:22:9 | -20 | x.unwrap(); +19 | if x.is_err() { + | ---------- the check is happening here +... +22 | x.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:17:8 - | -17 | if x.is_err() { - | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:35:9 + --> $DIR/checked_unwrap.rs:37:9 | -35 | x.unwrap(); +36 | if x.is_ok() && y.is_err() { + | --------- the check is happening here +37 | x.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:34:8 - | -34 | if x.is_ok() && y.is_err() { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:36:9 + --> $DIR/checked_unwrap.rs:38:9 | -36 | y.unwrap_err(); +36 | if x.is_ok() && y.is_err() { + | ---------- the check is happening here +37 | x.unwrap(); +38 | y.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:34:21 - | -34 | if x.is_ok() && y.is_err() { - | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:48:9 + --> $DIR/checked_unwrap.rs:50:9 | -48 | x.unwrap_err(); +45 | if x.is_ok() || y.is_ok() { + | --------- the check is happening here +... +50 | x.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:43:8 - | -43 | if x.is_ok() || y.is_ok() { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:49:9 + --> $DIR/checked_unwrap.rs:51:9 | -49 | y.unwrap_err(); +45 | if x.is_ok() || y.is_ok() { + | --------- the check is happening here +... +51 | y.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:43:21 - | -43 | if x.is_ok() || y.is_ok() { - | ^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:53:9 + --> $DIR/checked_unwrap.rs:55:9 | -53 | x.unwrap(); +54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | --------- the check is happening here +55 | x.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:52:8 - | -52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:54:9 + --> $DIR/checked_unwrap.rs:56:9 | -54 | y.unwrap_err(); +54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | --------- the check is happening here +55 | x.unwrap(); +56 | y.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:52:23 - | -52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { - | ^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:55:9 + --> $DIR/checked_unwrap.rs:57:9 | -55 | z.unwrap(); +54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | ---------- the check is happening here +... +57 | z.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:52:36 - | -52 | if x.is_ok() && !(y.is_ok() || z.is_err()) { - | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:60:9 + --> $DIR/checked_unwrap.rs:62:9 | -60 | x.unwrap_err(); +59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | --------- the check is happening here +... +62 | x.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:57:8 - | -57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { - | ^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:61:9 + --> $DIR/checked_unwrap.rs:63:9 | -61 | y.unwrap(); +59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | --------- the check is happening here +... +63 | y.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:57:23 - | -57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { - | ^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:62:9 + --> $DIR/checked_unwrap.rs:64:9 | -62 | z.unwrap_err(); +59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ---------- the check is happening here +... +64 | z.unwrap_err(); | ^^^^^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:57:36 - | -57 | if x.is_ok() || !(y.is_ok() && z.is_err()) { - | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:70:13 + --> $DIR/checked_unwrap.rs:72:13 | -70 | x.unwrap(); +71 | if x.is_some() { + | ----------- the check is happening here +72 | x.unwrap(); | ^^^^^^^^^^ - | -note: the check is happening here - --> $DIR/checked_unwrap.rs:69:12 - | -69 | if x.is_some() { - | ^^^^^^^^^^^ error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From 7b2fa2077fa48826fa98fab4402de0c5037de065 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 18 Mar 2018 22:27:15 +0200 Subject: Add duration_subsec lint Closes #2543 --- clippy_lints/src/duration_subsec.rs | 64 +++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/duration_subsec.rs | 26 +++++++++++++++ tests/ui/duration_subsec.stderr | 28 ++++++++++++++++ tests/ui/duration_subsec.stdout | 0 6 files changed, 122 insertions(+) create mode 100644 clippy_lints/src/duration_subsec.rs create mode 100644 tests/ui/duration_subsec.rs create mode 100644 tests/ui/duration_subsec.stderr create mode 100644 tests/ui/duration_subsec.stdout diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs new file mode 100644 index 00000000000..de75276ada7 --- /dev/null +++ b/clippy_lints/src/duration_subsec.rs @@ -0,0 +1,64 @@ +use rustc::hir::*; +use rustc::lint::*; +use syntax::codemap::Spanned; + +use crate::consts::{constant, Constant}; +use crate::utils::paths; +use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; + +/// **What it does:** Checks for calculation of subsecond microseconds or milliseconds from +/// `Duration::subsec_nanos()`. +/// +/// **Why is this bad?** It's more concise to call `Duration::subsec_micros()` or +/// `Duration::subsec_millis()`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let dur = Duration::new(5, 0); +/// let _micros = dur.subsec_nanos() / 1_000; +/// let _millis = dur.subsec_nanos() / 1_000_000; +/// ``` +declare_lint! { + pub DURATION_SUBSEC, + Warn, + "checks for `dur.subsec_nanos() / 1_000` or `dur.subsec_nanos() / 1_000_000`" +} + +#[derive(Copy, Clone)] +pub struct DurationSubsec; + +impl LintPass for DurationSubsec { + fn get_lints(&self) -> LintArray { + lint_array!(DURATION_SUBSEC) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprBinary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node; + if let ExprMethodCall(ref method_path, _ , ref args) = left.node; + if method_path.name == "subsec_nanos"; + if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); + if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); + then { + let suggested_fn = match divisor { + 1_000 => "subsec_micros", + 1_000_000 => "subsec_millis", + _ => return, + }; + + span_lint_and_sugg( + cx, + DURATION_SUBSEC, + expr.span, + &format!("Calling `{}()` is more concise than this calculation", suggested_fn), + "try", + format!("{}.{}()", snippet(cx, args[0].span, "_"), suggested_fn), + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c4dfc1f0168..8188dd87836 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -116,6 +116,7 @@ pub mod doc; pub mod double_comparison; pub mod double_parens; pub mod drop_forget_ref; +pub mod duration_subsec; pub mod else_if_without_else; pub mod empty_enum; pub mod entry; @@ -423,6 +424,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box inherent_impl::Pass::default()); reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); reg.register_late_lint_pass(box unwrap::Pass); + reg.register_late_lint_pass(box duration_subsec::DurationSubsec); reg.register_lint_group("clippy_restriction", vec![ @@ -518,6 +520,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { drop_forget_ref::DROP_REF, drop_forget_ref::FORGET_COPY, drop_forget_ref::FORGET_REF, + duration_subsec::DURATION_SUBSEC, entry::MAP_ENTRY, enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index ab62346ea7e..5af1a151c8c 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -27,6 +27,7 @@ pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; +pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs new file mode 100644 index 00000000000..5b87d69646e --- /dev/null +++ b/tests/ui/duration_subsec.rs @@ -0,0 +1,26 @@ +#![warn(duration_subsec)] + +use std::time::Duration; + +fn main() { + let dur = Duration::new(5, 0); + + let bad_micros = dur.subsec_nanos() / 1_000; + let good_micros = dur.subsec_micros(); + assert_eq!(bad_micros, good_micros); + + let bad_millis = dur.subsec_nanos() / 1_000_000; + let good_millis = dur.subsec_millis(); + assert_eq!(bad_millis, good_millis); + + // Handle refs + let _ = (&dur).subsec_nanos() / 1_000; + + // Handle constants + const NANOS_IN_MICRO: u32 = 1_000; + let _ = dur.subsec_nanos() / NANOS_IN_MICRO; + + // Other literals aren't linted + let _ = dur.subsec_nanos() / 699; + +} diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr new file mode 100644 index 00000000000..f77aa2172aa --- /dev/null +++ b/tests/ui/duration_subsec.stderr @@ -0,0 +1,28 @@ +error: Calling `subsec_micros()` is more concise than this calculation + --> $DIR/duration_subsec.rs:8:22 + | +8 | let bad_micros = dur.subsec_nanos() / 1_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` + | + = note: `-D duration-subsec` implied by `-D warnings` + +error: Calling `subsec_millis()` is more concise than this calculation + --> $DIR/duration_subsec.rs:12:22 + | +12 | let bad_millis = dur.subsec_nanos() / 1_000_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` + +error: Calling `subsec_micros()` is more concise than this calculation + --> $DIR/duration_subsec.rs:17:13 + | +17 | let _ = (&dur).subsec_nanos() / 1_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` + +error: Calling `subsec_micros()` is more concise than this calculation + --> $DIR/duration_subsec.rs:21:13 + | +21 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/duration_subsec.stdout b/tests/ui/duration_subsec.stdout new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From b0d364cb3e4e646591c5b3e84595415ba295fa0f Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 9 Jun 2018 11:04:21 +0200 Subject: duration_subsec: fix declaration; correctly classify --- clippy_lints/src/duration_subsec.rs | 4 ++-- clippy_lints/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index de75276ada7..fced237b66f 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -20,9 +20,9 @@ use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; /// let _micros = dur.subsec_nanos() / 1_000; /// let _millis = dur.subsec_nanos() / 1_000_000; /// ``` -declare_lint! { +declare_clippy_lint! { pub DURATION_SUBSEC, - Warn, + complexity, "checks for `dur.subsec_nanos() / 1_000` or `dur.subsec_nanos() / 1_000_000`" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8188dd87836..553a41c066c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -789,6 +789,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, + duration_subsec::DURATION_SUBSEC, eval_order_dependence::DIVERGING_SUB_EXPRESSION, eval_order_dependence::EVAL_ORDER_DEPENDENCE, explicit_write::EXPLICIT_WRITE, -- cgit 1.4.1-3-g733a5 From 8fe90e41d05cf92b4bcc35055c4a825342d4eae4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 10 Jun 2018 06:22:07 +0200 Subject: Publish preparation --- CHANGELOG.md | 6 +++++- README.md | 2 +- clippy_lints/src/lib.rs | 10 +++++++--- min_version.txt | 6 +++--- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aefb32a346a..56160aa587a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. ## 0.0.207 -* Rustup to *rustc 1.28.0-nightly (4ecf12bf0 2018-06-02)* +* Rustup to *rustc 1.28.0-nightly (2a0062974 2018-06-09)* ## 0.0.206 * Rustup to *rustc 1.28.0-nightly (5bf68db6e 2018-05-28)* @@ -667,6 +667,8 @@ All notable changes to this project will be documented in this file. [`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const +[`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast +[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result @@ -745,6 +747,7 @@ All notable changes to this project will be documented in this file. [`needless_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_range_loop [`needless_return`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_return [`needless_update`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_update +[`neg_cmp_op_on_partial_ord`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord [`neg_multiply`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#neg_multiply [`never_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#never_loop [`new_ret_no_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_ret_no_self @@ -835,6 +838,7 @@ All notable changes to this project will be documented in this file. [`unnecessary_fold`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation +[`unnecessary_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unneeded_field_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unneeded_field_pattern [`unreadable_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unreadable_literal [`unsafe_removed_from_name`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unsafe_removed_from_name diff --git a/README.md b/README.md index 150f821b5f4..305e0ba86b8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 261 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 265 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c4dfc1f0168..64dd7196128 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -505,7 +505,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { booleans::LOGIC_BUG, booleans::NONMINIMAL_BOOL, bytecount::NAIVE_BYTECOUNT, - neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, copies::IF_SAME_THEN_ELSE, @@ -624,6 +623,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, needless_update::NEEDLESS_UPDATE, + neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, @@ -674,6 +674,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::CAST_LOSSLESS, types::CAST_PTR_ALIGNMENT, types::CHAR_LIT_AS_U8, + types::FN_TO_NUMERIC_CAST, + types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::OPTION_OPTION, @@ -681,7 +683,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::UNIT_ARG, types::UNIT_CMP, types::UNNECESSARY_CAST, - types::FN_TO_NUMERIC_CAST, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, unused_io_amount::UNUSED_IO_AMOUNT, @@ -769,6 +770,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, + types::FN_TO_NUMERIC_CAST, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, @@ -814,6 +816,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { needless_bool::NEEDLESS_BOOL, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_update::NEEDLESS_UPDATE, + neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, no_effect::NO_EFFECT, no_effect::UNNECESSARY_OPERATION, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, @@ -840,7 +843,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { types::UNIT_ARG, types::UNNECESSARY_CAST, unused_label::UNUSED_LABEL, - unwrap::UNNECESSARY_UNWRAP, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); @@ -890,6 +892,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::CAST_PTR_ALIGNMENT, + types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, @@ -921,6 +924,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, ranges::RANGE_PLUS_ONE, + unwrap::UNNECESSARY_UNWRAP, ]); } diff --git a/min_version.txt b/min_version.txt index 3e55bb8c208..8feb513faca 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (4ecf12bf0 2018-06-02) +rustc 1.28.0-nightly (2a0062974 2018-06-09) binary: rustc -commit-hash: 4ecf12bf0eb8386626ccdb5f721a7183ccc4eba6 -commit-date: 2018-06-02 +commit-hash: 2a0062974a5225847fc43d5522c4dc3718173fe5 +commit-date: 2018-06-09 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From c6fb47331a3396a11d4e552f6afb176c7833c1a4 Mon Sep 17 00:00:00 2001 From: Donald Robertson Date: Mon, 11 Jun 2018 14:17:40 +0100 Subject: Updating docs to reflect more recent changes to expect_fun_call lint --- clippy_lints/src/methods.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index aafc612b512..d2bad6f58be 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -347,7 +347,11 @@ declare_clippy_lint! { /// ``` /// this can instead be written: /// ```rust -/// foo.unwrap_or_else(|_| panic!(&format("Err {}: {}", err_code, err_msg))) +/// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg)) +/// ``` +/// or +/// ```rust +/// foo.unwrap_or_else(|_| panic!(format("Err {}: {}", err_code, err_msg).as_str())) /// ``` declare_clippy_lint! { pub EXPECT_FUN_CALL, -- cgit 1.4.1-3-g733a5 From 725e9621d0ea1f07ad75d5f26193dfba72ee73b2 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 12 Jun 2018 08:25:10 +0200 Subject: duration_subsec: Add check for `subsec_micros` --- clippy_lints/src/duration_subsec.rs | 17 ++++++++--------- tests/ui/duration_subsec.rs | 11 ++++++----- tests/ui/duration_subsec.stderr | 30 ++++++++++++++++++------------ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index fced237b66f..5f34803c813 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -6,11 +6,11 @@ use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; -/// **What it does:** Checks for calculation of subsecond microseconds or milliseconds from -/// `Duration::subsec_nanos()`. +/// **What it does:** Checks for calculation of subsecond microseconds or milliseconds +/// from other `Duration` methods. /// /// **Why is this bad?** It's more concise to call `Duration::subsec_micros()` or -/// `Duration::subsec_millis()`. +/// `Duration::subsec_millis()` than to calculate them. /// /// **Known problems:** None. /// @@ -23,7 +23,7 @@ use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; declare_clippy_lint! { pub DURATION_SUBSEC, complexity, - "checks for `dur.subsec_nanos() / 1_000` or `dur.subsec_nanos() / 1_000_000`" + "checks for calculation of subsecond microseconds or milliseconds" } #[derive(Copy, Clone)] @@ -40,16 +40,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { if_chain! { if let ExprBinary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node; if let ExprMethodCall(ref method_path, _ , ref args) = left.node; - if method_path.name == "subsec_nanos"; if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); then { - let suggested_fn = match divisor { - 1_000 => "subsec_micros", - 1_000_000 => "subsec_millis", + let suggested_fn = match (method_path.name.as_str().as_ref(), divisor) { + ("subsec_micros", 1_000) => "subsec_millis", + ("subsec_nanos", 1_000) => "subsec_micros", + ("subsec_nanos", 1_000_000) => "subsec_millis", _ => return, }; - span_lint_and_sugg( cx, DURATION_SUBSEC, diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 5b87d69646e..8c75c5f2fcd 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -5,14 +5,16 @@ use std::time::Duration; fn main() { let dur = Duration::new(5, 0); + let bad_millis_1 = dur.subsec_micros() / 1_000; + let bad_millis_2 = dur.subsec_nanos() / 1_000_000; + let good_millis = dur.subsec_millis(); + assert_eq!(bad_millis_1, good_millis); + assert_eq!(bad_millis_2, good_millis); + let bad_micros = dur.subsec_nanos() / 1_000; let good_micros = dur.subsec_micros(); assert_eq!(bad_micros, good_micros); - let bad_millis = dur.subsec_nanos() / 1_000_000; - let good_millis = dur.subsec_millis(); - assert_eq!(bad_millis, good_millis); - // Handle refs let _ = (&dur).subsec_nanos() / 1_000; @@ -22,5 +24,4 @@ fn main() { // Other literals aren't linted let _ = dur.subsec_nanos() / 699; - } diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index f77aa2172aa..a1aacec3a75 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,28 +1,34 @@ -error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:8:22 +error: Calling `subsec_millis()` is more concise than this calculation + --> $DIR/duration_subsec.rs:8:24 | -8 | let bad_micros = dur.subsec_nanos() / 1_000; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` +8 | let bad_millis_1 = dur.subsec_micros() / 1_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` | = note: `-D duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:12:22 + --> $DIR/duration_subsec.rs:9:24 + | +9 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` + +error: Calling `subsec_micros()` is more concise than this calculation + --> $DIR/duration_subsec.rs:14:22 | -12 | let bad_millis = dur.subsec_nanos() / 1_000_000; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` +14 | let bad_micros = dur.subsec_nanos() / 1_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:17:13 + --> $DIR/duration_subsec.rs:19:13 | -17 | let _ = (&dur).subsec_nanos() / 1_000; +19 | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:21:13 + --> $DIR/duration_subsec.rs:23:13 | -21 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; +23 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 23404287fcb0fd63093d7ef98e6e2bf844b37287 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Fri, 8 Jun 2018 18:12:01 +0200 Subject: Implement lint checking for `unwrap`s that will always panic. --- clippy_lints/src/unwrap.rs | 52 +++++++-- tests/ui/checked_unwrap.rs | 72 ++++++++---- tests/ui/checked_unwrap.stderr | 260 ++++++++++++++++++++++++++++++++--------- 3 files changed, 297 insertions(+), 87 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index db840c79a29..8c11f027db6 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -32,6 +32,27 @@ declare_clippy_lint! { "checks for calls of unwrap[_err]() that cannot fail" } +/// **What it does:** Checks for calls of unwrap[_err]() that will always fail. +/// +/// **Why is this bad?** If panicking is desired, an explicit `panic!()` should be used. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// if option.is_none() { +/// do_something_with(option.unwrap()) +/// } +/// ``` +/// +/// This code will always panic. The if condition should probably be inverted. +/// ``` +declare_clippy_lint! { + pub PANICKING_UNWRAP, + nursery, + "checks for calls of unwrap[_err]() that will always fail" +} + pub struct Pass; /// Visitor that keeps track of which variables are unwrappable. @@ -124,17 +145,28 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { if ["unwrap", "unwrap_err"].contains(&&*method_name.name.as_str()); let call_to_unwrap = method_name.name == "unwrap"; if let Some(unwrappable) = self.unwrappables.iter() - .find(|u| u.ident.def == path.def && call_to_unwrap == u.safe_to_unwrap); + .find(|u| u.ident.def == path.def); then { - span_lint_and_then( - self.cx, - UNNECESSARY_UNWRAP, - expr.span, - &format!("You checked before that `{}()` cannot fail. \ - Instead of checking and unwrapping, it's better to use `if let` or `match`.", - method_name.name), - |db| { db.span_label(unwrappable.check.span, "the check is happening here"); }, - ); + if call_to_unwrap == unwrappable.safe_to_unwrap { + span_lint_and_then( + self.cx, + UNNECESSARY_UNWRAP, + expr.span, + &format!("You checked before that `{}()` cannot fail. \ + Instead of checking and unwrapping, it's better to use `if let` or `match`.", + method_name.name), + |db| { db.span_label(unwrappable.check.span, "the check is happening here"); }, + ); + } else { + span_lint_and_then( + self.cx, + UNNECESSARY_UNWRAP, + expr.span, + &format!("This call to `{}()` will always panic.", + method_name.name), + |db| { db.span_label(unwrappable.check.span, "because of this check"); }, + ); + } } } walk_expr(self, expr); diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index fec52940614..893e2db0433 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,32 +1,41 @@ #![deny(unnecessary_unwrap)] +#![allow(if_same_then_else)] fn main() { let x = Some(()); if x.is_some() { - x.unwrap(); + x.unwrap(); // unnecessary + } else { + x.unwrap(); // will panic } if x.is_none() { - // nothing to do here + x.unwrap(); // will panic } else { - x.unwrap(); + x.unwrap(); // unnecessary } let mut x: Result<(), ()> = Ok(()); if x.is_ok() { - x.unwrap(); + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic } else { - x.unwrap_err(); + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary } if x.is_err() { - x.unwrap_err(); + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary } else { - x.unwrap(); + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic } if x.is_ok() { x = Err(()); - x.unwrap(); + x.unwrap(); // not unnecessary because of mutation of x + // it will always panic but the lint is not smart enoguh to see this (it only checks if conditions). } else { x = Ok(()); - x.unwrap_err(); + x.unwrap_err(); // not unnecessary because of mutation of x + // it will always panic but the lint is not smart enoguh to see this (it only checks if conditions). } } @@ -34,34 +43,49 @@ fn test_complex_conditions() { let x: Result<(), ()> = Ok(()); let y: Result<(), ()> = Ok(()); if x.is_ok() && y.is_err() { - x.unwrap(); - y.unwrap_err(); + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic + y.unwrap(); // will panic + y.unwrap_err(); // unnecessary } else { - // not clear whether unwrappable: + // not statically determinable whether any of the following will always succeed or always fail: + x.unwrap(); x.unwrap_err(); y.unwrap(); + y.unwrap_err(); } if x.is_ok() || y.is_ok() { - // not clear whether unwrappable: + // not statically determinable whether any of the following will always succeed or always fail: x.unwrap(); y.unwrap(); } else { - x.unwrap_err(); - y.unwrap_err(); + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary + y.unwrap(); // will panic + y.unwrap_err(); // unnecessary } let z: Result<(), ()> = Ok(()); if x.is_ok() && !(y.is_ok() || z.is_err()) { - x.unwrap(); - y.unwrap_err(); - z.unwrap(); + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic + y.unwrap(); // will panic + y.unwrap_err(); // unnecessary + z.unwrap(); // unnecessary + z.unwrap_err(); // will panic } if x.is_ok() || !(y.is_ok() && z.is_err()) { - // not clear what's unwrappable - } else { - x.unwrap_err(); + // not statically determinable whether any of the following will always succeed or always fail: + x.unwrap(); y.unwrap(); - z.unwrap_err(); + z.unwrap(); + } else { + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary + y.unwrap(); // unnecessary + y.unwrap_err(); // will panic + z.unwrap(); // will panic + z.unwrap_err(); // unnecessary } } @@ -69,7 +93,9 @@ fn test_nested() { fn nested() { let x = Some(()); if x.is_some() { - x.unwrap(); + x.unwrap(); // unnecessary + } else { + x.unwrap(); // will panic } } } diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index bfa5ec08f2e..28e0df8920a 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,9 +1,9 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:6:9 + --> $DIR/checked_unwrap.rs:7:9 | -5 | if x.is_some() { +6 | if x.is_some() { | ----------- the check is happening here -6 | x.unwrap(); +7 | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here @@ -12,144 +12,296 @@ note: lint level defined here 1 | #![deny(unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^ +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:9:9 + | +6 | if x.is_some() { + | ----------- because of this check +... +9 | x.unwrap(); // will panic + | ^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:12:9 + | +11 | if x.is_none() { + | ----------- because of this check +12 | x.unwrap(); // will panic + | ^^^^^^^^^^ + error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:11:9 + --> $DIR/checked_unwrap.rs:14:9 | -8 | if x.is_none() { +11 | if x.is_none() { | ----------- the check is happening here ... -11 | x.unwrap(); +14 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:15:9 + --> $DIR/checked_unwrap.rs:18:9 | -14 | if x.is_ok() { +17 | if x.is_ok() { | --------- the check is happening here -15 | x.unwrap(); +18 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:19:9 + | +17 | if x.is_ok() { + | --------- because of this check +18 | x.unwrap(); // unnecessary +19 | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:21:9 + | +17 | if x.is_ok() { + | --------- because of this check +... +21 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:17:9 + --> $DIR/checked_unwrap.rs:22:9 | -14 | if x.is_ok() { +17 | if x.is_ok() { | --------- the check is happening here ... -17 | x.unwrap_err(); +22 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:25:9 + | +24 | if x.is_err() { + | ---------- because of this check +25 | x.unwrap(); // will panic + | ^^^^^^^^^^ + error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:20:9 + --> $DIR/checked_unwrap.rs:26:9 | -19 | if x.is_err() { +24 | if x.is_err() { | ---------- the check is happening here -20 | x.unwrap_err(); +25 | x.unwrap(); // will panic +26 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:22:9 + --> $DIR/checked_unwrap.rs:28:9 | -19 | if x.is_err() { +24 | if x.is_err() { | ---------- the check is happening here ... -22 | x.unwrap(); +28 | x.unwrap(); // unnecessary | ^^^^^^^^^^ +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:29:9 + | +24 | if x.is_err() { + | ---------- because of this check +... +29 | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:37:9 + --> $DIR/checked_unwrap.rs:46:9 | -36 | if x.is_ok() && y.is_err() { +45 | if x.is_ok() && y.is_err() { | --------- the check is happening here -37 | x.unwrap(); +46 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:47:9 + | +45 | if x.is_ok() && y.is_err() { + | --------- because of this check +46 | x.unwrap(); // unnecessary +47 | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:48:9 + | +45 | if x.is_ok() && y.is_err() { + | ---------- because of this check +... +48 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:38:9 + --> $DIR/checked_unwrap.rs:49:9 | -36 | if x.is_ok() && y.is_err() { +45 | if x.is_ok() && y.is_err() { | ---------- the check is happening here -37 | x.unwrap(); -38 | y.unwrap_err(); +... +49 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:63:9 + | +58 | if x.is_ok() || y.is_ok() { + | --------- because of this check +... +63 | x.unwrap(); // will panic + | ^^^^^^^^^^ + error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:50:9 + --> $DIR/checked_unwrap.rs:64:9 | -45 | if x.is_ok() || y.is_ok() { +58 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -50 | x.unwrap_err(); +64 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:65:9 + | +58 | if x.is_ok() || y.is_ok() { + | --------- because of this check +... +65 | y.unwrap(); // will panic + | ^^^^^^^^^^ + error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:51:9 + --> $DIR/checked_unwrap.rs:66:9 | -45 | if x.is_ok() || y.is_ok() { +58 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -51 | y.unwrap_err(); +66 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:55:9 + --> $DIR/checked_unwrap.rs:70:9 | -54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -55 | x.unwrap(); +70 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:71:9 + | +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | --------- because of this check +70 | x.unwrap(); // unnecessary +71 | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:72:9 + | +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | --------- because of this check +... +72 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:56:9 + --> $DIR/checked_unwrap.rs:73:9 | -54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -55 | x.unwrap(); -56 | y.unwrap_err(); +... +73 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:57:9 + --> $DIR/checked_unwrap.rs:74:9 | -54 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here ... -57 | z.unwrap(); +74 | z.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:75:9 + | +69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { + | ---------- because of this check +... +75 | z.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:83:9 + | +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | --------- because of this check +... +83 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:62:9 + --> $DIR/checked_unwrap.rs:84:9 | -59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -62 | x.unwrap_err(); +84 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:63:9 + --> $DIR/checked_unwrap.rs:85:9 | -59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -63 | y.unwrap(); +85 | y.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/checked_unwrap.rs:86:9 + | +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | --------- because of this check +... +86 | y.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:87:9 + | +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ---------- because of this check +... +87 | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:64:9 + --> $DIR/checked_unwrap.rs:88:9 | -59 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here ... -64 | z.unwrap_err(); +88 | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:72:13 + --> $DIR/checked_unwrap.rs:96:13 | -71 | if x.is_some() { +95 | if x.is_some() { | ----------- the check is happening here -72 | x.unwrap(); +96 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/checked_unwrap.rs:98:13 + | +95 | if x.is_some() { + | ----------- because of this check +... +98 | x.unwrap(); // will panic | ^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 34 previous errors -- cgit 1.4.1-3-g733a5 From 0c6730d85133598e95c534bf1d514b941aa65299 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Fri, 8 Jun 2018 18:25:31 +0200 Subject: Update known problems. --- clippy_lints/src/unwrap.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 8c11f027db6..3694c48a39f 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -36,7 +36,8 @@ declare_clippy_lint! { /// /// **Why is this bad?** If panicking is desired, an explicit `panic!()` should be used. /// -/// **Known problems:** None. +/// **Known problems:** This lint only checks `if` conditions not assignments. +/// So something like `let x: Option<()> = None; x.unwrap();` will not be recognized. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 8682858e2cdddc483b7652f87e1eb45686b70e61 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Fri, 8 Jun 2018 20:38:39 +0200 Subject: Categorize the unwrap lints correctly. --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/unwrap.rs | 4 ++-- tests/ui/checked_unwrap.rs | 2 +- tests/ui/checked_unwrap.stderr | 12 +++++++++--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e49cc0cec28..f00146ea5b8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -926,6 +926,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, ranges::RANGE_PLUS_ONE, + unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 3694c48a39f..877dc67681c 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } else { span_lint_and_then( self.cx, - UNNECESSARY_UNWRAP, + PANICKING_UNWRAP, expr.span, &format!("This call to `{}()` will always panic.", method_name.name), @@ -181,7 +181,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { impl<'a> LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(UNNECESSARY_UNWRAP) + lint_array!(PANICKING_UNWRAP, UNNECESSARY_UNWRAP) } } diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index 893e2db0433..c3d4b8de08b 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,4 +1,4 @@ -#![deny(unnecessary_unwrap)] +#![deny(panicking_unwrap, unnecessary_unwrap)] #![allow(if_same_then_else)] fn main() { diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index 28e0df8920a..1b46ceb5fa8 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -7,10 +7,10 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and u | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:1:9 + --> $DIR/checked_unwrap.rs:1:27 | -1 | #![deny(unnecessary_unwrap)] - | ^^^^^^^^^^^^^^^^^^ +1 | #![deny(panicking_unwrap, unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:9:9 @@ -20,6 +20,12 @@ error: This call to `unwrap()` will always panic. ... 9 | x.unwrap(); // will panic | ^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/checked_unwrap.rs:1:9 + | +1 | #![deny(panicking_unwrap, unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:12:9 -- cgit 1.4.1-3-g733a5 From 35d1b19a037138db3e00243c8bd84b5e719df73f Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Sat, 9 Jun 2018 12:15:52 +0200 Subject: Fix markdown. --- clippy_lints/src/unwrap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 877dc67681c..6feecb94d02 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -6,7 +6,7 @@ use rustc::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; -/// **What it does:** Checks for calls of unwrap[_err]() that cannot fail. +/// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail. /// /// **Why is this bad?** Using `if let` or `match` is more idiomatic. /// @@ -32,7 +32,7 @@ declare_clippy_lint! { "checks for calls of unwrap[_err]() that cannot fail" } -/// **What it does:** Checks for calls of unwrap[_err]() that will always fail. +/// **What it does:** Checks for calls of `unwrap[_err]()` that will always fail. /// /// **Why is this bad?** If panicking is desired, an explicit `panic!()` should be used. /// -- cgit 1.4.1-3-g733a5 From 817da4c00a3a113dd806ae80c7d76aee219fa7f6 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Tue, 12 Jun 2018 15:03:22 +0200 Subject: Fix documentation --- clippy_lints/src/unwrap.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6feecb94d02..7355b38fd6b 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -47,7 +47,6 @@ declare_clippy_lint! { /// ``` /// /// This code will always panic. The if condition should probably be inverted. -/// ``` declare_clippy_lint! { pub PANICKING_UNWRAP, nursery, -- cgit 1.4.1-3-g733a5 From 4866309f9d570319b3f0f28793a3aac3e3b107c5 Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Thu, 14 Jun 2018 08:57:27 +0100 Subject: Add default_trait_access lint --- clippy_lints/src/default_trait_access.rs | 63 ++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 4 ++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/default_trait_access.rs | 39 ++++++++++++++++++++ tests/ui/default_trait_access.stderr | 34 +++++++++++++++++ tests/ui/default_trait_access.stdout | 0 6 files changed, 141 insertions(+) create mode 100644 clippy_lints/src/default_trait_access.rs create mode 100644 tests/ui/default_trait_access.rs create mode 100644 tests/ui/default_trait_access.stderr create mode 100644 tests/ui/default_trait_access.stdout diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs new file mode 100644 index 00000000000..0222f896e28 --- /dev/null +++ b/clippy_lints/src/default_trait_access.rs @@ -0,0 +1,63 @@ +use rustc::hir::*; +use rustc::lint::*; + +use crate::utils::{match_def_path, opt_def_id, paths, span_lint_and_sugg}; + + +/// **What it does:** Checks for literal calls to `Default::default()`. +/// +/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is +/// being gotten than the generic `Default`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// // Bad +/// let s: String = Default::default(); +/// +/// // Good +/// let s = String::default(); +/// ``` +declare_clippy_lint! { + pub DEFAULT_TRAIT_ACCESS, + style, + "checks for literal calls to Default::default()" +} + +#[derive(Copy, Clone)] +pub struct DefaultTraitAccess; + +impl LintPass for DefaultTraitAccess { + fn get_lints(&self) -> LintArray { + lint_array!(DEFAULT_TRAIT_ACCESS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprCall(ref path, ..) = expr.node; + if let ExprPath(ref qpath) = path.node; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); + if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); + then { + match qpath { + QPath::Resolved(..) => { + // TODO: Work out a way to put "whatever the imported way of referencing + // this type in this file" rather than a fully-qualified type. + let replacement = format!("{}::default()", cx.tables.expr_ty(expr)); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("Calling {} is more clear than this expression", replacement), + "try", + replacement); + }, + QPath::TypeRelative(..) => {}, + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 52145341400..80c02db081e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -111,6 +111,7 @@ pub mod collapsible_if; pub mod const_static_lifetime; pub mod copies; pub mod cyclomatic_complexity; +pub mod default_trait_access; pub mod derive; pub mod doc; pub mod double_comparison; @@ -425,6 +426,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); reg.register_late_lint_pass(box unwrap::Pass); reg.register_late_lint_pass(box duration_subsec::DurationSubsec); + reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); reg.register_lint_group("clippy_restriction", vec![ @@ -512,6 +514,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + default_trait_access::DEFAULT_TRAIT_ACCESS, derive::DERIVE_HASH_XOR_EQ, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, @@ -709,6 +712,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, + default_trait_access::DEFAULT_TRAIT_ACCESS, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, eq_op::OP_REF, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 5af1a151c8c..7606f4f8471 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -24,6 +24,7 @@ pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"]; pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; +pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs new file mode 100644 index 00000000000..9db875ee305 --- /dev/null +++ b/tests/ui/default_trait_access.rs @@ -0,0 +1,39 @@ +#![warn(default_trait_access)] + +use std::default::Default as D2; +use std::string; +use std::default; + +fn main() { + let s1: String = Default::default(); + + let s2 = String::default(); + + let s3: String = D2::default(); + + let s4: String = std::default::Default::default(); + + let s5 = string::String::default(); + + let s6: String = default::Default::default(); + + let s7 = std::string::String::default(); + + let s8: String = DefaultFactory::make_t_badly(); + + let s9: String = DefaultFactory::make_t_nicely(); + + println!("[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", s1, s2, s3, s4, s5, s6, s7, s8, s9); +} + +struct DefaultFactory; + +impl DefaultFactory { + pub fn make_t_badly() -> T { + Default::default() + } + + pub fn make_t_nicely() -> T { + T::default() + } +} diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr new file mode 100644 index 00000000000..b2cb49e6c80 --- /dev/null +++ b/tests/ui/default_trait_access.stderr @@ -0,0 +1,34 @@ +error: Calling std::string::String::default() is more clear than this expression + --> $DIR/default_trait_access.rs:8:22 + | +8 | let s1: String = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` + | + = note: `-D default-trait-access` implied by `-D warnings` + +error: Calling std::string::String::default() is more clear than this expression + --> $DIR/default_trait_access.rs:12:22 + | +12 | let s3: String = D2::default(); + | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` + +error: Calling std::string::String::default() is more clear than this expression + --> $DIR/default_trait_access.rs:14:22 + | +14 | let s4: String = std::default::Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` + +error: Calling std::string::String::default() is more clear than this expression + --> $DIR/default_trait_access.rs:18:22 + | +18 | let s6: String = default::Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` + +error: Calling T::default() is more clear than this expression + --> $DIR/default_trait_access.rs:33:9 + | +33 | Default::default() + | ^^^^^^^^^^^^^^^^^^ help: try: `T::default()` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/default_trait_access.stdout b/tests/ui/default_trait_access.stdout new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From e38c109ae7536a9f9f788cd4acd2cd41e3064730 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 14 Jun 2018 22:50:07 +0200 Subject: Lint printing was broken --- util/update_lints.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/util/update_lints.py b/util/update_lints.py index 692599886a9..77c23160e8a 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -40,7 +40,7 @@ def collect(deprecated_lints, clippy_lints, fn): deprecated_lints.append((os.path.splitext(os.path.basename(fn))[0], match.group('name').lower(), desc.replace('\\"', '"'))) - + for match in declare_clippy_lint_re.finditer(code): # remove \-newline escapes from description string desc = nl_escape_re.sub('', match.group('desc')) @@ -51,10 +51,8 @@ def collect(deprecated_lints, clippy_lints, fn): desc.replace('\\"', '"'))) -def gen_group(lints, levels=None): +def gen_group(lints): """Write lint group (list of all lints in the form module::NAME).""" - if levels: - lints = [tup for tup in lints if tup[2] in levels] for (module, name, _, _) in sorted(lints): yield ' %s::%s,\n' % (module, name.upper()) @@ -168,7 +166,19 @@ def main(print_only=False, check=False): all_lints += value if print_only: - sys.stdout.writelines(gen_table(all_lints)) + print_clippy_lint_groups = [ + "correctness", + "style", + "complexity", + "perf", + "pedantic", + "nursery", + "restriction" + ] + for group in print_clippy_lint_groups: + sys.stdout.write('\n## ' + group + '\n') + for (_, name, _, descr) in sorted(clippy_lints[x]): + sys.stdout.write('* [' + name + '](https://rust-lang-nursery.github.io/rust-clippy/master/index.html#' + name + ') (' + descr + ')\n') return # update the lint counter in README.md -- cgit 1.4.1-3-g733a5 From d3124731b7f0d0b87a5803452427318b10041fe6 Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Thu, 14 Jun 2018 23:13:12 +0100 Subject: Fix some existing test expectations --- tests/ui/implicit_hasher.rs | 8 +- tests/ui/methods.rs | 3 +- tests/ui/methods.stderr | 374 ++++++++++++++++++++++---------------------- 3 files changed, 193 insertions(+), 192 deletions(-) diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index c8b9f74bb32..49df39ca71b 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -30,12 +30,12 @@ impl Foo for HashMap { impl Foo for HashMap { fn make() -> (Self, Self) { - (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + (HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default())) } } impl Foo for HashMap { fn make() -> (Self, Self) { - (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) + (HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default())) } } @@ -53,12 +53,12 @@ impl Foo for HashSet { impl Foo for HashSet { fn make() -> (Self, Self) { - (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + (HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default())) } } impl Foo for HashSet { fn make() -> (Self, Self) { - (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) + (HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default())) } } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index b04c008ba23..b42cc1f75b7 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -3,7 +3,8 @@ #![warn(clippy, clippy_pedantic, option_unwrap_used)] #![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, - new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value)] + new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value, + default_trait_access)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index edf081aaa47..01ec0895fb0 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,528 +1,528 @@ error: unnecessary structure name repetition - --> $DIR/methods.rs:20:29 + --> $DIR/methods.rs:21:29 | -20 | pub fn add(self, other: T) -> T { self } +21 | pub fn add(self, other: T) -> T { self } | ^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:20:35 + --> $DIR/methods.rs:21:35 | -20 | pub fn add(self, other: T) -> T { self } +21 | pub fn add(self, other: T) -> T { self } | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:24:25 + --> $DIR/methods.rs:25:25 | -24 | fn eq(&self, other: T) -> bool { true } // no error, private function +25 | fn eq(&self, other: T) -> bool { true } // no error, private function | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:26:26 + --> $DIR/methods.rs:27:26 | -26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:26:33 + --> $DIR/methods.rs:27:33 | -26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref +27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:27:21 + --> $DIR/methods.rs:28:21 | -27 | fn div(self) -> T { self } // no error, different #arguments +28 | fn div(self) -> T { self } // no error, different #arguments | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:28:25 + --> $DIR/methods.rs:29:25 | -28 | fn rem(self, other: T) { } // no error, wrong return type +29 | fn rem(self, other: T) { } // no error, wrong return type | ^ help: use the applicable keyword: `Self` error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:20:5 + --> $DIR/methods.rs:21:5 | -20 | pub fn add(self, other: T) -> T { self } +21 | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:31:17 + --> $DIR/methods.rs:32:17 | -31 | fn into_u16(&self) -> u16 { 0 } +32 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:33:21 + --> $DIR/methods.rs:34:21 | -33 | fn to_something(self) -> u32 { 0 } +34 | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:35:12 + --> $DIR/methods.rs:36:12 | -35 | fn new(self) {} +36 | fn new(self) {} | ^^^^ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:35:5 + --> $DIR/methods.rs:36:5 | -35 | fn new(self) {} +36 | fn new(self) {} | ^^^^^^^^^^^^^^^ | = note: `-D new-ret-no-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/methods.rs:79:24 + --> $DIR/methods.rs:80:24 | -79 | fn new() -> Option> { None } +80 | fn new() -> Option> { None } | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:83:19 + --> $DIR/methods.rs:84:19 | -83 | type Output = T; +84 | type Output = T; | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:84:25 + --> $DIR/methods.rs:85:25 | -84 | fn mul(self, other: T) -> T { self } // no error, obviously +85 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:84:31 + --> $DIR/methods.rs:85:31 | -84 | fn mul(self, other: T) -> T { self } // no error, obviously +85 | fn mul(self, other: T) -> T { self } // no error, obviously | ^ help: use the applicable keyword: `Self` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:103:13 + --> $DIR/methods.rs:104:13 | -103 | let _ = opt.map(|x| x + 1) +104 | let _ = opt.map(|x| x + 1) | _____________^ -104 | | -105 | | .unwrap_or(0); // should lint even though this call is on a separate line +105 | | +106 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | = note: `-D option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:107:13 + --> $DIR/methods.rs:108:13 | -107 | let _ = opt.map(|x| { +108 | let _ = opt.map(|x| { | _____________^ -108 | | x + 1 -109 | | } -110 | | ).unwrap_or(0); +109 | | x + 1 +110 | | } +111 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:111:13 + --> $DIR/methods.rs:112:13 | -111 | let _ = opt.map(|x| x + 1) +112 | let _ = opt.map(|x| x + 1) | _____________^ -112 | | .unwrap_or({ -113 | | 0 -114 | | }); +113 | | .unwrap_or({ +114 | | 0 +115 | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:116:13 + --> $DIR/methods.rs:117:13 | -116 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); +117 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:118:13 + --> $DIR/methods.rs:119:13 | -118 | let _ = opt.map(|x| { +119 | let _ = opt.map(|x| { | _____________^ -119 | | Some(x + 1) -120 | | } -121 | | ).unwrap_or(None); +120 | | Some(x + 1) +121 | | } +122 | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:122:13 + --> $DIR/methods.rs:123:13 | -122 | let _ = opt +123 | let _ = opt | _____________^ -123 | | .map(|x| Some(x + 1)) -124 | | .unwrap_or(None); +124 | | .map(|x| Some(x + 1)) +125 | | .unwrap_or(None); | |________________________^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:130:13 + --> $DIR/methods.rs:131:13 | -130 | let _ = opt.map(|x| x + 1) +131 | let _ = opt.map(|x| x + 1) | _____________^ -131 | | -132 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +132 | | +133 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:134:13 + --> $DIR/methods.rs:135:13 | -134 | let _ = opt.map(|x| { +135 | let _ = opt.map(|x| { | _____________^ -135 | | x + 1 -136 | | } -137 | | ).unwrap_or_else(|| 0); +136 | | x + 1 +137 | | } +138 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:138:13 + --> $DIR/methods.rs:139:13 | -138 | let _ = opt.map(|x| x + 1) +139 | let _ = opt.map(|x| x + 1) | _____________^ -139 | | .unwrap_or_else(|| -140 | | 0 -141 | | ); +140 | | .unwrap_or_else(|| +141 | | 0 +142 | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:147:13 + --> $DIR/methods.rs:148:13 | -147 | let _ = opt.map_or(None, |x| Some(x + 1)); +148 | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | = note: `-D option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:149:13 + --> $DIR/methods.rs:150:13 | -149 | let _ = opt.map_or(None, |x| { +150 | let _ = opt.map_or(None, |x| { | _____________^ -150 | | Some(x + 1) -151 | | } -152 | | ); +151 | | Some(x + 1) +152 | | } +153 | | ); | |_________________^ help: try using and_then instead | -149 | let _ = opt.and_then(|x| { -150 | Some(x + 1) -151 | }); +150 | let _ = opt.and_then(|x| { +151 | Some(x + 1) +152 | }); | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:162:13 + --> $DIR/methods.rs:163:13 | -162 | let _ = res.map(|x| x + 1) +163 | let _ = res.map(|x| x + 1) | _____________^ -163 | | -164 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line +164 | | +165 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | |_____________________________________^ | = note: `-D result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:166:13 + --> $DIR/methods.rs:167:13 | -166 | let _ = res.map(|x| { +167 | let _ = res.map(|x| { | _____________^ -167 | | x + 1 -168 | | } -169 | | ).unwrap_or_else(|e| 0); +168 | | x + 1 +169 | | } +170 | | ).unwrap_or_else(|e| 0); | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:170:13 + --> $DIR/methods.rs:171:13 | -170 | let _ = res.map(|x| x + 1) +171 | let _ = res.map(|x| x + 1) | _____________^ -171 | | .unwrap_or_else(|e| -172 | | 0 -173 | | ); +172 | | .unwrap_or_else(|e| +173 | | 0 +174 | | ); | |_________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:199:24 + --> $DIR/methods.rs:200:24 | -199 | fn filter(self) -> IteratorFalsePositives { +200 | fn filter(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:203:22 + --> $DIR/methods.rs:204:22 | -203 | fn next(self) -> IteratorFalsePositives { +204 | fn next(self) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/methods.rs:223:32 + --> $DIR/methods.rs:224:32 | -223 | fn skip(self, _: usize) -> IteratorFalsePositives { +224 | fn skip(self, _: usize) -> IteratorFalsePositives { | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:233:13 + --> $DIR/methods.rs:234:13 | -233 | let _ = v.iter().filter(|&x| *x < 0).next(); +234 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:236:13 + --> $DIR/methods.rs:237:13 | -236 | let _ = v.iter().filter(|&x| { +237 | let _ = v.iter().filter(|&x| { | _____________^ -237 | | *x < 0 -238 | | } -239 | | ).next(); +238 | | *x < 0 +239 | | } +240 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:251:13 + --> $DIR/methods.rs:252:13 | -251 | let _ = v.iter().find(|&x| *x < 0).is_some(); +252 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:254:13 + --> $DIR/methods.rs:255:13 | -254 | let _ = v.iter().find(|&x| { +255 | let _ = v.iter().find(|&x| { | _____________^ -255 | | *x < 0 -256 | | } -257 | | ).is_some(); +256 | | *x < 0 +257 | | } +258 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:260:13 + --> $DIR/methods.rs:261:13 | -260 | let _ = v.iter().position(|&x| x < 0).is_some(); +261 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:263:13 + --> $DIR/methods.rs:264:13 | -263 | let _ = v.iter().position(|&x| { +264 | let _ = v.iter().position(|&x| { | _____________^ -264 | | x < 0 -265 | | } -266 | | ).is_some(); +265 | | x < 0 +266 | | } +267 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:269:13 + --> $DIR/methods.rs:270:13 | -269 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +270 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:272:13 + --> $DIR/methods.rs:273:13 | -272 | let _ = v.iter().rposition(|&x| { +273 | let _ = v.iter().rposition(|&x| { | _____________^ -273 | | x < 0 -274 | | } -275 | | ).is_some(); +274 | | x < 0 +275 | | } +276 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:289:21 + --> $DIR/methods.rs:290:21 | -289 | fn new() -> Foo { Foo } +290 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:307:22 + --> $DIR/methods.rs:308:22 | -307 | with_constructor.unwrap_or(make()); +308 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:310:5 + --> $DIR/methods.rs:311:5 | -310 | with_new.unwrap_or(Vec::new()); +311 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:313:21 + --> $DIR/methods.rs:314:21 | -313 | with_const_args.unwrap_or(Vec::with_capacity(12)); +314 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:316:14 + --> $DIR/methods.rs:317:14 | -316 | with_err.unwrap_or(make()); +317 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:319:19 + --> $DIR/methods.rs:320:19 | -319 | with_err_args.unwrap_or(Vec::with_capacity(12)); +320 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:322:5 + --> $DIR/methods.rs:323:5 | -322 | with_default_trait.unwrap_or(Default::default()); +323 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:325:5 + --> $DIR/methods.rs:326:5 | -325 | with_default_type.unwrap_or(u64::default()); +326 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:328:14 + --> $DIR/methods.rs:329:14 | -328 | with_vec.unwrap_or(vec![]); +329 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:333:21 + --> $DIR/methods.rs:334:21 | -333 | without_default.unwrap_or(Foo::new()); +334 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:336:19 + --> $DIR/methods.rs:337:19 | -336 | map.entry(42).or_insert(String::new()); +337 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:339:21 + --> $DIR/methods.rs:340:21 | -339 | btree.entry(42).or_insert(String::new()); +340 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:342:21 + --> $DIR/methods.rs:343:21 | -342 | let _ = stringy.unwrap_or("".to_owned()); +343 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: use of `expect` followed by a function call - --> $DIR/methods.rs:365:26 + --> $DIR/methods.rs:366:26 | -365 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); +366 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/methods.rs:368:26 + --> $DIR/methods.rs:369:26 | -368 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +369 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:378:25 + --> $DIR/methods.rs:379:25 | -378 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); +379 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:381:25 + --> $DIR/methods.rs:382:25 | -381 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +382 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:401:23 + --> $DIR/methods.rs:402:23 | -401 | let bad_vec = some_vec.iter().nth(3); +402 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:402:26 + --> $DIR/methods.rs:403:26 | -402 | let bad_slice = &some_vec[..].iter().nth(3); +403 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:403:31 + --> $DIR/methods.rs:404:31 | -403 | let bad_boxed_slice = boxed_slice.iter().nth(3); +404 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:404:29 + --> $DIR/methods.rs:405:29 | -404 | let bad_vec_deque = some_vec_deque.iter().nth(3); +405 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:409:23 + --> $DIR/methods.rs:410:23 | -409 | let bad_vec = some_vec.iter_mut().nth(3); +410 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:412:26 + --> $DIR/methods.rs:413:26 | -412 | let bad_slice = &some_vec[..].iter_mut().nth(3); +413 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:415:29 + --> $DIR/methods.rs:416:29 | -415 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +416 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:427:13 + --> $DIR/methods.rs:428:13 | -427 | let _ = some_vec.iter().skip(42).next(); +428 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:428:13 + --> $DIR/methods.rs:429:13 | -428 | let _ = some_vec.iter().cycle().skip(42).next(); +429 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:429:13 + --> $DIR/methods.rs:430:13 | -429 | let _ = (1..10).skip(10).next(); +430 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:430:14 + --> $DIR/methods.rs:431:14 | -430 | let _ = &some_vec[..].iter().skip(3).next(); +431 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:439:13 + --> $DIR/methods.rs:440:13 | -439 | let _ = opt.unwrap(); +440 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 00a0efc5665d9be2e64c9b703bf22f64b84487a5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 15 Jun 2018 00:19:19 -0700 Subject: Doc fix syntax --- clippy_lints/src/if_let_redundant_pattern_matching.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 63b4a2b2837..92b2bab3ba8 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; -/// **What it does:*** Lint for redundant pattern matching over `Result` or +/// **What it does:** Lint for redundant pattern matching over `Result` or /// `Option` /// /// **Why is this bad?** It's more concise and clear to just use the proper -- cgit 1.4.1-3-g733a5 From 0c231128467514141a28cd51d4ecabe1431dd8b1 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 15 Jun 2018 00:20:46 -0700 Subject: More doc fixes --- clippy_lints/src/unwrap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index db840c79a29..1d346b0bba7 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -6,7 +6,7 @@ use rustc::hir::*; use syntax::ast::NodeId; use syntax::codemap::Span; -/// **What it does:** Checks for calls of unwrap[_err]() that cannot fail. +/// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail. /// /// **Why is this bad?** Using `if let` or `match` is more idiomatic. /// -- cgit 1.4.1-3-g733a5 From 7547a4ddef11f0b08ce2b92032012bf34872e4fd Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sun, 27 May 2018 14:32:03 +0200 Subject: New Lint: Pass small trivially copyable objects by value Fixes #1680 Hardcoded for 64-bit "trivial" size for now --- clippy_lints/src/lib.rs | 4 + clippy_lints/src/trivially_copy_pass_by_ref.rs | 116 +++++++++++++++++++++++++ tests/ui/clone_on_copy_mut.rs | 1 + tests/ui/eta.rs | 2 +- tests/ui/infinite_iter.rs | 2 +- tests/ui/infinite_loop.rs | 2 +- tests/ui/lifetimes.rs | 2 +- tests/ui/mut_from_ref.rs | 2 +- tests/ui/mut_reference.rs | 2 +- tests/ui/needless_borrow.rs | 2 +- tests/ui/trivially_copy_pass_by_ref.rs | 57 ++++++++++++ tests/ui/trivially_copy_pass_by_ref.stderr | 82 +++++++++++++++++ tests/ui/unused_lt.rs | 2 +- tests/ui/wrong_self_convention.rs | 2 +- 14 files changed, 269 insertions(+), 9 deletions(-) create mode 100644 clippy_lints/src/trivially_copy_pass_by_ref.rs create mode 100644 tests/ui/trivially_copy_pass_by_ref.rs create mode 100644 tests/ui/trivially_copy_pass_by_ref.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 52145341400..56521d440aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -196,6 +196,7 @@ pub mod suspicious_trait_impl; pub mod swap; pub mod temporary_assignment; pub mod transmute; +pub mod trivially_copy_pass_by_ref; pub mod types; pub mod unicode; pub mod unsafe_removed_from_name; @@ -399,6 +400,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); + reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( conf.literal_representation_threshold @@ -672,6 +674,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, + trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, types::BOX_VEC, @@ -916,6 +919,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SINGLE_CHAR_PATTERN, misc::CMP_OWNED, mutex_atomic::MUTEX_ATOMIC, + trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, types::BOX_VEC, vec::USELESS_VEC, ]); diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs new file mode 100644 index 00000000000..30b5f65cc8c --- /dev/null +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -0,0 +1,116 @@ +use rustc::hir::*; +use rustc::hir::map::*; +use rustc::hir::intravisit::FnKind; +use rustc::lint::*; +use rustc::ty::TypeVariants; +use rustc_target::spec::abi::Abi; +use rustc_target::abi::LayoutOf; +use syntax::ast::NodeId; +use syntax_pos::Span; +use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet}; + +/// **What it does:** Checks for functions taking arguments by reference, where +/// the argument type is `Copy` and small enough to be more efficient to always +/// pass by value. +/// +/// **Why is this bad?** In many calling conventions instances of structs will +/// be passed through registers if they fit into two or less general purpose +/// registers. +/// +/// **Example:** +/// ```rust +/// fn foo(v: &u32) { +/// assert_eq!(v, 42); +/// } +/// // should be +/// fn foo(v: u32) { +/// assert_eq!(v, 42); +/// } +/// ``` +declare_clippy_lint! { + pub TRIVIALLY_COPY_PASS_BY_REF, + perf, + "functions taking small copyable arguments by reference" +} + +pub struct TriviallyCopyPassByRef; + +impl LintPass for TriviallyCopyPassByRef { + fn get_lints(&self) -> LintArray { + lint_array![TRIVIALLY_COPY_PASS_BY_REF] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl, + body: &'tcx Body, + span: Span, + node_id: NodeId, + ) { + if in_macro(span) { + return; + } + + match kind { + FnKind::ItemFn(.., abi, _, attrs) => { + if abi != Abi::Rust { + return; + } + for a in attrs { + if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" { + return; + } + } + }, + FnKind::Method(..) => (), + _ => return, + } + + // Exclude non-inherent impls + if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | + ItemTrait(..)) + { + return; + } + } + + let fn_def_id = cx.tcx.hir.local_def_id(node_id); + + let fn_sig = cx.tcx.fn_sig(fn_def_id); + let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); + + for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { + // All spans generated from a proc-macro invocation are the same... + if span == input.span { + return; + } + + if_chain! { + if let TypeVariants::TyRef(_, ty, Mutability::MutImmutable) = ty.sty; + if is_copy(cx, ty); + if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); + if size < 16; + if let Ty_::TyRptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; + then { + let value_type = if is_self(arg) { + "self".into() + } else { + snippet(cx, decl_ty.span, "_").into() + }; + span_lint_and_sugg( + cx, + TRIVIALLY_COPY_PASS_BY_REF, + input.span, + "this argument is passed by reference, but would be more efficient if passed by value", + "consider passing by value instead", + value_type); + } + } + } + } +} diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 5bfa256623b..5b491573c3f 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -5,6 +5,7 @@ pub fn dec_read_dec(i: &mut i32) -> i32 { ret } +#[allow(trivially_copy_pass_by_ref)] pub fn minus_1(i: &i32) -> i32 { dec_read_dec(&mut i.clone()) } diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index be84f44bfb1..6e0b6f8cacd 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,6 +1,6 @@ -#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value, option_map_unit_fn)] +#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value, option_map_unit_fn, trivially_copy_pass_by_ref)] #![warn(redundant_closure, needless_borrow)] fn main() { diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 08596ff2016..2e2ccd9f1ae 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,7 +1,7 @@ #![feature(iterator_for_each)] use std::iter::repeat; - +#[allow(trivially_copy_pass_by_ref)] fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } #[allow(maybe_infinite_iter)] diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 353d34134eb..aa4f8b53f6c 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,4 +1,4 @@ - +#![allow(trivially_copy_pass_by_ref)] fn fn_val(i: i32) -> i32 { unimplemented!() } diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 1f6aeaafcf1..d2de1cb8ed8 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -2,7 +2,7 @@ #![warn(needless_lifetimes, extra_unused_lifetimes)] -#![allow(dead_code, needless_pass_by_value)] +#![allow(dead_code, needless_pass_by_value, trivially_copy_pass_by_ref)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 9e757155260..3fc464083c4 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,6 +1,6 @@ -#![allow(unused)] +#![allow(unused, trivially_copy_pass_by_ref)] #![warn(mut_from_ref)] struct Foo; diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index ac40bf2a186..34185f6a9c2 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,7 +1,7 @@ -#![allow(unused_variables)] +#![allow(unused_variables, trivially_copy_pass_by_ref)] fn takes_an_immutable_reference(a: &i32) {} fn takes_a_mutable_reference(a: &mut i32) {} diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 491194e83b1..b086f0214a9 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; - +#[allow(trivially_copy_pass_by_ref)] fn x(y: &i32) -> i32 { *y } diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs new file mode 100644 index 00000000000..aba4aa5ea32 --- /dev/null +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -0,0 +1,57 @@ +#![allow(many_single_char_names, blacklisted_name)] + +#[derive(Copy, Clone)] +struct Foo(u32); + +#[derive(Copy, Clone)] +struct Bar([u8; 24]); + +type Baz = u32; + +fn good(a: &mut u32, b: u32, c: &Bar) { +} + +fn bad(x: &u32, y: &Foo, z: &Baz) { +} + +impl Foo { + fn good(self, a: &mut u32, b: u32, c: &Bar) { + } + + fn good2(&mut self) { + } + + fn bad(&self, x: &u32, y: &Foo, z: &Baz) { + } + + fn bad2(x: &u32, y: &Foo, z: &Baz) { + } +} + +impl AsRef for Foo { + fn as_ref(&self) -> &u32 { + &self.0 + } +} + +impl Bar { + fn good(&self, a: &mut u32, b: u32, c: &Bar) { + } + + fn bad2(x: &u32, y: &Foo, z: &Baz) { + } +} + +fn main() { + let (mut foo, bar) = (Foo(0), Bar([0; 24])); + let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0); + good(&mut a, b, &c); + bad(&x, &y, &z); + foo.good(&mut a, b, &c); + foo.good2(); + foo.bad(&x, &y, &z); + Foo::bad2(&x, &y, &z); + bar.good(&mut a, b, &c); + Bar::bad2(&x, &y, &z); + foo.as_ref(); +} diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr new file mode 100644 index 00000000000..c6ab968a7c5 --- /dev/null +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -0,0 +1,82 @@ +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:14:11 + | +14 | fn bad(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `u32` + | + = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:14:20 + | +14 | fn bad(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Foo` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:14:29 + | +14 | fn bad(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Baz` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:24:12 + | +24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { + | ^^^^^ help: consider passing by value instead: `self` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:24:22 + | +24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `u32` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:24:31 + | +24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Foo` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:24:40 + | +24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Baz` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:27:16 + | +27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `u32` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:27:25 + | +27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Foo` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:27:34 + | +27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Baz` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:41:16 + | +41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `u32` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:41:25 + | +41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Foo` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:41:34 + | +41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { + | ^^^^ help: consider passing by value instead: `Baz` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 198730d87f3..8b166a34d29 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,6 +1,6 @@ -#![allow(unused, dead_code, needless_lifetimes, needless_pass_by_value)] +#![allow(unused, dead_code, needless_lifetimes, needless_pass_by_value, trivially_copy_pass_by_ref)] #![warn(extra_unused_lifetimes)] fn empty() { diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index bef87e2bb01..07a93d6889b 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -3,7 +3,7 @@ #![warn(wrong_self_convention)] #![warn(wrong_pub_self_convention)] -#![allow(dead_code)] +#![allow(dead_code, trivially_copy_pass_by_ref)] fn main() {} -- cgit 1.4.1-3-g733a5 From 700ece5648a61516f0ed883cb2876363e3caedbc Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sun, 27 May 2018 16:04:45 +0200 Subject: Allow configuring the trivial copy size limit --- clippy_lints/src/lib.rs | 5 +++- clippy_lints/src/trivially_copy_pass_by_ref.rs | 32 ++++++++++++++++++++-- clippy_lints/src/utils/conf.rs | 2 ++ tests/ui-toml/toml_trivially_copy/clippy.toml | 1 + tests/ui-toml/toml_trivially_copy/test.rs | 19 +++++++++++++ tests/ui-toml/toml_trivially_copy/test.stderr | 16 +++++++++++ .../toml_unknown_key/conf_unknown_key.stderr | 2 +- tests/ui/useless_asref.rs | 2 +- 8 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 tests/ui-toml/toml_trivially_copy/clippy.toml create mode 100644 tests/ui-toml/toml_trivially_copy/test.rs create mode 100644 tests/ui-toml/toml_trivially_copy/test.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 56521d440aa..bac479deda6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -400,7 +400,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); - reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef); + reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef::new( + conf.trivial_copy_size_limit, + ®.sess.target, + )); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( conf.literal_representation_threshold diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 30b5f65cc8c..4c8d0c9dab8 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,8 +1,11 @@ +use std::cmp; + use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::ty::TypeVariants; +use rustc::session::config::Config as SessionConfig; use rustc_target::spec::abi::Abi; use rustc_target::abi::LayoutOf; use syntax::ast::NodeId; @@ -17,6 +20,14 @@ use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet}; /// be passed through registers if they fit into two or less general purpose /// registers. /// +/// **Known problems:** This lint is target register size dependent, it is +/// limited to 32-bit to try and reduce portability problems between 32 and +/// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit +/// will be different. +/// +/// The configuration option `trivial_copy_size_limit` can be set to override +/// this limit for a project. +/// /// **Example:** /// ```rust /// fn foo(v: &u32) { @@ -33,7 +44,24 @@ declare_clippy_lint! { "functions taking small copyable arguments by reference" } -pub struct TriviallyCopyPassByRef; +pub struct TriviallyCopyPassByRef { + limit: u64, +} + +impl TriviallyCopyPassByRef { + pub fn new(limit: Option, target: &SessionConfig) -> Self { + let limit = limit.unwrap_or_else(|| { + let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64; + // Cap the calculated bit width at 32-bits to reduce + // portability problems between 32 and 64-bit targets + let bit_width = cmp::min(bit_width, 32); + let byte_width = bit_width / 8; + // Use a limit of 2 times the register bit width + byte_width * 2 + }); + Self { limit } + } +} impl LintPass for TriviallyCopyPassByRef { fn get_lints(&self) -> LintArray { @@ -94,7 +122,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { if let TypeVariants::TyRef(_, ty, Mutability::MutImmutable) = ty.sty; if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); - if size < 16; + if size <= self.limit; if let Ty_::TyRptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; then { let value_type = if is_self(arg) { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 99504d76906..d3c7d901323 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -156,6 +156,8 @@ define_Conf! { (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals (literal_representation_threshold, "literal_representation_threshold", 16384 => u64), + /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. + (trivial_copy_size_limit, "trivial_copy_size_limit", None => Option), } /// Search for the configuration file. diff --git a/tests/ui-toml/toml_trivially_copy/clippy.toml b/tests/ui-toml/toml_trivially_copy/clippy.toml new file mode 100644 index 00000000000..3b96f1fd000 --- /dev/null +++ b/tests/ui-toml/toml_trivially_copy/clippy.toml @@ -0,0 +1 @@ +trivial-copy-size-limit = 2 diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs new file mode 100644 index 00000000000..bee092a5765 --- /dev/null +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -0,0 +1,19 @@ +#![allow(many_single_char_names)] + +#[derive(Copy, Clone)] +struct Foo(u8); + +#[derive(Copy, Clone)] +struct Bar(u32); + +fn good(a: &mut u32, b: u32, c: &Bar, d: &u32) { +} + +fn bad(x: &u16, y: &Foo) { +} + +fn main() { + let (mut a, b, c, d, x, y) = (0, 0, Bar(0), 0, 0, Foo(0)); + good(&mut a, b, &c, &d); + bad(&x, &y); +} diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr new file mode 100644 index 00000000000..2d36c47c5da --- /dev/null +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -0,0 +1,16 @@ +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/test.rs:12:11 + | +12 | fn bad(x: &u16, y: &Foo) { + | ^^^^ help: consider passing by value instead: `u16` + | + = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/test.rs:12:20 + | +12 | fn bad(x: &u16, y: &Foo) { + | ^^^^ help: consider passing by value instead: `Foo` + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 61e03774e32..05a04fb377a 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `third-party` +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `third-party` error: aborting due to previous error diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 8599d67c767..7508cdc7b43 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,5 +1,5 @@ #![deny(useless_asref)] - +#![allow(trivially_copy_pass_by_ref)] use std::fmt::Debug; struct FakeAsRef; -- cgit 1.4.1-3-g733a5 From 621fdcc3bcea3828cd25ee0801c39bc9c2bbafce Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Thu, 31 May 2018 20:15:48 +0200 Subject: Dogfood new trivially_copy_pass_by_ref lint --- clippy_lints/src/approx_const.rs | 8 +++---- clippy_lints/src/attrs.rs | 8 +++---- clippy_lints/src/bit_mask.rs | 34 ++++++++++++++-------------- clippy_lints/src/eq_op.rs | 4 ++-- clippy_lints/src/excessive_precision.rs | 10 ++++---- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/inline_fn_without_body.rs | 4 ++-- clippy_lints/src/literal_representation.rs | 26 ++++++++++----------- clippy_lints/src/loops.rs | 20 ++++++++-------- clippy_lints/src/methods.rs | 16 ++++++------- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 8 +++---- clippy_lints/src/types.rs | 10 ++++---- clippy_lints/src/unsafe_removed_from_name.rs | 8 +++---- clippy_lints/src/utils/hir_utils.rs | 20 ++++++++-------- 15 files changed, 91 insertions(+), 91 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 0288176f436..d3741d78801 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -71,14 +71,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { match lit.node { - LitKind::Float(ref s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), - LitKind::Float(ref s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), - LitKind::FloatUnsuffixed(ref s) => check_known_consts(cx, e, s, "f{32, 64}"), + LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), + LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), + LitKind::FloatUnsuffixed(s) => check_known_consts(cx, e, s, "f{32, 64}"), _ => (), } } -fn check_known_consts(cx: &LateContext, e: &Expr, s: &symbol::Symbol, module: &str) { +fn check_known_consts(cx: &LateContext, e: &Expr, s: symbol::Symbol, module: &str) { let s = s.as_str(); if s.parse::().is_ok() { for &(constant, name, min_digits) in KNOWN_CONSTS { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 04ef9d00215..46ec02a3473 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if is_relevant_item(cx.tcx, item) { - check_attrs(cx, item.span, &item.name, &item.attrs) + check_attrs(cx, item.span, item.name, &item.attrs) } match item.node { ItemExternCrate(_) | ItemUse(_, _) => { @@ -195,13 +195,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if is_relevant_impl(cx.tcx, item) { - check_attrs(cx, item.span, &item.name, &item.attrs) + check_attrs(cx, item.span, item.name, &item.attrs) } } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if is_relevant_trait(cx.tcx, item) { - check_attrs(cx, item.span, &item.name, &item.attrs) + check_attrs(cx, item.span, item.name, &item.attrs) } } } @@ -260,7 +260,7 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool } } -fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) { if in_macro(span) { return; } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index f77b61bf280..9f548b9e320 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -112,9 +112,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { if let ExprBinary(ref cmp, ref left, ref right) = e.node { if cmp.node.is_comparison() { if let Some(cmp_opt) = fetch_int_literal(cx, right) { - check_compare(cx, left, cmp.node, cmp_opt, &e.span) + check_compare(cx, left, cmp.node, cmp_opt, e.span) } else if let Some(cmp_val) = fetch_int_literal(cx, left) { - check_compare(cx, right, invert_cmp(cmp.node), cmp_val, &e.span) + check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span) } } } @@ -156,7 +156,7 @@ fn invert_cmp(cmp: BinOp_) -> BinOp_ { } -fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: &Span) { +fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: Span) { if let ExprBinary(ref op, ref left, ref right) = bit_op.node { if op.node != BiBitAnd && op.node != BiBitOr { return; @@ -167,7 +167,7 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u12 } } -fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: &Span) { +fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: Span) { match cmp_op { BiEq | BiNe => match bit_op { BiBitAnd => if mask_value & cmp_value != cmp_value { @@ -175,7 +175,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ & {}` can never be equal to `{}`", mask_value, @@ -184,13 +184,13 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: ); } } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, BiBitOr => if mask_value | cmp_value != cmp_value { span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ | {}` can never be equal to `{}`", mask_value, @@ -205,7 +205,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ & {}` will always be lower than `{}`", mask_value, @@ -213,13 +213,13 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: ), ); } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, BiBitOr => if mask_value >= cmp_value { span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ | {}` will never be lower than `{}`", mask_value, @@ -227,9 +227,9 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: ), ); } else { - check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); + check_ineffective_lt(cx, span, mask_value, cmp_value, "|"); }, - BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), + BiBitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"), _ => (), }, BiLe | BiGt => match bit_op { @@ -237,7 +237,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ & {}` will never be higher than `{}`", mask_value, @@ -245,13 +245,13 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: ), ); } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, BiBitOr => if mask_value > cmp_value { span_lint( cx, BAD_BIT_MASK, - *span, + span, &format!( "incompatible bit mask: `_ | {}` will always be higher than `{}`", mask_value, @@ -259,9 +259,9 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: ), ); } else { - check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); + check_ineffective_gt(cx, span, mask_value, cmp_value, "|"); }, - BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), + BiBitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"), _ => (), }, _ => (), diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index fff146434d6..19761fbe864 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -52,7 +52,7 @@ impl LintPass for EqOp { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprBinary(ref op, ref left, ref right) = e.node { + if let ExprBinary(op, ref left, ref right) = e.node { if in_macro(e.span) { return; } @@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { } -fn is_valid_operator(op: &BinOp) -> bool { +fn is_valid_operator(op: BinOp) -> bool { match op.node { BiSub | BiDiv | BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, _ => false, diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 9915c87c407..c33a3b50185 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -46,9 +46,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if_chain! { let ty = cx.tables.expr_ty(expr); - if let TypeVariants::TyFloat(ref fty) = ty.sty; + if let TypeVariants::TyFloat(fty) = ty.sty; if let hir::ExprLit(ref lit) = expr.node; - if let LitKind::Float(ref sym, _) | LitKind::FloatUnsuffixed(ref sym) = lit.node; + if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node; if let Some(sugg) = self.check(sym, fty); then { span_lint_and_sugg( @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { impl ExcessivePrecision { // None if nothing to lint, Some(suggestion) if lint neccessary - fn check(&self, sym: &Symbol, fty: &FloatTy) -> Option { + fn check(&self, sym: Symbol, fty: FloatTy) -> Option { let max = max_digits(fty); let sym_str = sym.as_str(); if dot_zero_exclusion(&sym_str) { @@ -79,7 +79,7 @@ impl ExcessivePrecision { let digits = count_digits(&sym_str); if digits > max as usize { let formatter = FloatFormat::new(&sym_str); - let sr = match *fty { + let sr = match fty { FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), }; @@ -115,7 +115,7 @@ fn dot_zero_exclusion(s: &str) -> bool { } } -fn max_digits(fty: &FloatTy) -> u32 { +fn max_digits(fty: FloatTy) -> u32 { match fty { FloatTy::F32 => f32::DIGITS, FloatTy::F64 => f64::DIGITS, diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 536f4dd4772..904d0b1d245 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } impl<'a, 'tcx> Functions { - fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { + fn check_arg_number(self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { let args = decl.inputs.len() as u64; if args > self.threshold { span_lint( @@ -139,7 +139,7 @@ impl<'a, 'tcx> Functions { } fn check_raw_ptr( - &self, + self, cx: &LateContext<'a, 'tcx>, unsafety: hir::Unsafety, decl: &'tcx hir::FnDecl, diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index ab50ea6f131..1325ad66857 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -38,12 +38,12 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if let TraitItemKind::Method(_, TraitMethod::Required(_)) = item.node { - check_attrs(cx, &item.name, &item.attrs); + check_attrs(cx, item.name, &item.attrs); } } } -fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext, name: Name, attrs: &[Attribute]) { for attr in attrs { if attr.name() != "inline" { continue; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 51ca236026c..09b66b872e9 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -227,12 +227,12 @@ enum WarningType { } impl WarningType { - pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { - match *self { + pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: syntax_pos::Span) { + match self { WarningType::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, - *span, + span, "long literal lacking separators", "consider", grouping_hint.to_owned(), @@ -240,7 +240,7 @@ impl WarningType { WarningType::LargeDigitGroups => span_lint_and_sugg( cx, LARGE_DIGIT_GROUPS, - *span, + span, "digit groups should be smaller", "consider", grouping_hint.to_owned(), @@ -248,7 +248,7 @@ impl WarningType { WarningType::InconsistentDigitGrouping => span_lint_and_sugg( cx, INCONSISTENT_DIGIT_GROUPING, - *span, + span, "digits grouped inconsistently by underscores", "consider", grouping_hint.to_owned(), @@ -256,7 +256,7 @@ impl WarningType { WarningType::DecimalRepresentation => span_lint_and_sugg( cx, DECIMAL_LITERAL_REPRESENTATION, - *span, + span, "integer literal has a better hexadecimal representation", "consider", grouping_hint.to_owned(), @@ -291,7 +291,7 @@ impl EarlyLintPass for LiteralDigitGrouping { } impl LiteralDigitGrouping { - fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext, lit: &Lit) { match lit.node { LitKind::Int(..) => { // Lint integral literals. @@ -302,7 +302,7 @@ impl LiteralDigitGrouping { then { let digit_info = DigitInfo::new(&src, false); let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { - warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + warning_type.display(&digit_info.grouping_hint(), cx, lit.span) }); } } @@ -337,15 +337,15 @@ impl LiteralDigitGrouping { if !consistent { WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), cx, - &lit.span); + lit.span); } }) .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, - &lit.span)); + lit.span)); } }) - .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, &lit.span)); + .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, lit.span)); } } }, @@ -436,7 +436,7 @@ impl LiteralRepresentation { threshold, } } - fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext, lit: &Lit) { // Lint integral literals. if_chain! { if let LitKind::Int(..) = lit.node; @@ -457,7 +457,7 @@ impl LiteralRepresentation { let hex = format!("{:#X}", val); let digit_info = DigitInfo::new(&hex[..], false); let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { - warning_type.display(&digit_info.grouping_hint(), cx, &lit.span) + warning_type.display(&digit_info.grouping_hint(), cx, lit.span) }); } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 20b10db0d66..cfea6053fac 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -412,7 +412,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { - match never_loop_block(block, &expr.id) { + match never_loop_block(block, expr.id) { NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), @@ -575,7 +575,7 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult } } -fn never_loop_block(block: &Block, main_loop_id: &NodeId) -> NeverLoopResult { +fn never_loop_block(block: &Block, main_loop_id: NodeId) -> NeverLoopResult { let stmts = block.stmts.iter().map(stmt_to_expr); let expr = once(block.expr.as_ref().map(|p| &**p)); let mut iter = stmts.chain(expr).filter_map(|e| e); @@ -596,7 +596,7 @@ fn decl_to_expr(decl: &Decl) -> Option<&Expr> { } } -fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { +fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { match expr.node { ExprBox(ref e) | ExprUnary(_, ref e) | @@ -643,7 +643,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { ExprAgain(d) => { let id = d.target_id .expect("target id can only be missing in the presence of compilation errors"); - if id == *main_loop_id { + if id == main_loop_id { NeverLoopResult::MayContinueMainLoop } else { NeverLoopResult::AlwaysBreak @@ -668,17 +668,17 @@ fn never_loop_expr(expr: &Expr, main_loop_id: &NodeId) -> NeverLoopResult { } } -fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { +fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { es.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_seq) } -fn never_loop_expr_all<'a, T: Iterator>(es: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { +fn never_loop_expr_all<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { es.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_both) } -fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, main_loop_id: &NodeId) -> NeverLoopResult { +fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, main_loop_id: NodeId) -> NeverLoopResult { e.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::AlwaysBreak, combine_branches) } @@ -1032,7 +1032,7 @@ fn check_for_loop_range<'a, 'tcx>( }; let take = if let Some(end) = *end { - if is_len_call(end, &indexed) { + if is_len_call(end, indexed) { "".to_owned() } else { match limits { @@ -1096,14 +1096,14 @@ fn check_for_loop_range<'a, 'tcx>( } } -fn is_len_call(expr: &Expr, var: &Name) -> bool { +fn is_len_call(expr: &Expr, var: Name) -> bool { if_chain! { if let ExprMethodCall(ref method, _, ref len_args) = expr.node; if len_args.len() == 1; if method.name == "len"; if let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node; if path.segments.len() == 1; - if path.segments[0].name == *var; + if path.segments[0].name == var; then { return true; } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d2bad6f58be..6d93e5bbd09 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -2079,8 +2079,8 @@ impl SelfKind { } } - fn description(&self) -> &'static str { - match *self { + fn description(self) -> &'static str { + match self { SelfKind::Value => "self by value", SelfKind::Ref => "self by reference", SelfKind::RefMut => "self by mutable reference", @@ -2164,13 +2164,13 @@ enum OutType { } impl OutType { - fn matches(&self, ty: &hir::FunctionRetTy) -> bool { + fn matches(self, ty: &hir::FunctionRetTy) -> bool { match (self, ty) { - (&OutType::Unit, &hir::DefaultReturn(_)) => true, - (&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, - (&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, - (&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, - (&OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)), + (OutType::Unit, &hir::DefaultReturn(_)) => true, + (OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, + (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, + (OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, + (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)), _ => false, } } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 1108cfcaf52..fcd88f9f219 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -349,7 +349,7 @@ impl EarlyLintPass for MiscEarly { } impl MiscEarly { - fn check_lit(&self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext, lit: &Lit) { if_chain! { if let LitKind::Int(value, ..) = lit.node; if let Some(src) = snippet_opt(cx, lit.span); diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index bd7a8f7c761..e3ccfec4685 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { if let Some(impl_trait) = check_binop( cx, expr, - &binop.node, + binop.node, &["Add", "Sub", "Mul", "Div"], &[BiAdd, BiSub, BiMul, BiDiv], ) { @@ -110,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { if let Some(impl_trait) = check_binop( cx, expr, - &binop.node, + binop.node, &[ "AddAssign", "SubAssign", @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_binop<'a>( cx: &LateContext, expr: &hir::Expr, - binop: &hir::BinOp_, + binop: hir::BinOp_, traits: &[&'a str], expected_ops: &[hir::BinOp_], ) -> Option<&'a str> { @@ -169,7 +169,7 @@ fn check_binop<'a>( if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.def.def_id()); - if *binop != expected_ops[idx]; + if binop != expected_ops[idx]; then{ return Some(traits[idx]) } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index a71d47e4085..0888aef89fe 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1606,12 +1606,12 @@ fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) } } -fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { +fn err_upcast_comparison(cx: &LateContext, span: Span, expr: &Expr, always: bool) { if let ExprCast(ref cast_val, _) = expr.node { span_lint( cx, INVALID_UPCAST_COMPARISONS, - *span, + span, &format!( "because of the numeric bounds on `{}` prior to casting, this expression is always {}", snippet(cx, cast_val.span, "the expression"), @@ -1623,7 +1623,7 @@ fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: boo fn upcast_comparison_bounds_err<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - span: &Span, + span: Span, rel: comparisons::Rel, lhs_bounds: Option<(FullInt, FullInt)>, lhs: &'tcx Expr, @@ -1684,8 +1684,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); - upcast_comparison_bounds_err(cx, &expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); - upcast_comparison_bounds_err(cx, &expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); + upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); + upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); } } } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 85cf97a97f3..56a8377d7dd 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -36,12 +36,12 @@ impl LintPass for UnsafeNameRemoval { impl EarlyLintPass for UnsafeNameRemoval { fn check_item(&mut self, cx: &EarlyContext, item: &Item) { if let ItemKind::Use(ref use_tree) = item.node { - check_use_tree(use_tree, cx, &item.span); + check_use_tree(use_tree, cx, item.span); } } } -fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { +fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: Span) { match use_tree.kind { UseTreeKind::Simple(Some(new_name)) => { let old_name = use_tree @@ -62,14 +62,14 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { } } -fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: &Span) { +fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: Span) { let old_str = old_name.name.as_str(); let new_str = new_name.name.as_str(); if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { span_lint( cx, UNSAFE_REMOVED_FROM_NAME, - *span, + span, &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str), ); } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 15df7b72a8d..ddac8bd3835 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -349,7 +349,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprAgain; c.hash(&mut self.s); if let Some(i) = i.label { - self.hash_name(&i.name); + self.hash_name(i.name); } }, ExprYield(ref e) => { @@ -386,7 +386,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprBreak; c.hash(&mut self.s); if let Some(i) = i.label { - self.hash_name(&i.name); + self.hash_name(i.name); } if let Some(ref j) = *j { self.hash_expr(&*j); @@ -419,7 +419,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprField; c.hash(&mut self.s); self.hash_expr(e); - self.hash_name(&f.name); + self.hash_name(f.name); }, ExprIndex(ref a, ref i) => { let c: fn(_, _) -> _ = ExprIndex; @@ -450,7 +450,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { - self.hash_name(&i.name); + self.hash_name(i.name); } }, ExprMatch(ref e, ref arms, ref s) => { @@ -471,7 +471,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { ExprMethodCall(ref path, ref _tys, ref args) => { let c: fn(_, _, _) -> _ = ExprMethodCall; c.hash(&mut self.s); - self.hash_name(&path.name); + self.hash_name(path.name); self.hash_exprs(args); }, ExprRepeat(ref e, ref l_id) => { @@ -502,7 +502,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_qpath(path); for f in fields { - self.hash_name(&f.ident.name); + self.hash_name(f.ident.name); self.hash_expr(&f.expr); } @@ -541,7 +541,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(cond); self.hash_block(b); if let Some(l) = l { - self.hash_name(&l.name); + self.hash_name(l.name); } }, } @@ -553,7 +553,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { } } - pub fn hash_name(&mut self, n: &Name) { + pub fn hash_name(&mut self, n: Name) { n.as_str().hash(&mut self.s); } @@ -563,7 +563,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_path(path); }, QPath::TypeRelative(_, ref path) => { - self.hash_name(&path.name); + self.hash_name(path.name); }, } // self.cx.tables.qpath_def(p, id).hash(&mut self.s); @@ -572,7 +572,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn hash_path(&mut self, p: &Path) { p.is_global().hash(&mut self.s); for p in &p.segments { - self.hash_name(&p.name); + self.hash_name(p.name); } } -- cgit 1.4.1-3-g733a5 From 45bab501e182860c9088c3d1eafcd596cfd0dd22 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 15 Jun 2018 17:45:41 +0200 Subject: Fix typo in lint dump script --- util/update_lints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_lints.py b/util/update_lints.py index 77c23160e8a..6ee14cfcb12 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -177,7 +177,7 @@ def main(print_only=False, check=False): ] for group in print_clippy_lint_groups: sys.stdout.write('\n## ' + group + '\n') - for (_, name, _, descr) in sorted(clippy_lints[x]): + for (_, name, _, descr) in sorted(clippy_lints[group]): sys.stdout.write('* [' + name + '](https://rust-lang-nursery.github.io/rust-clippy/master/index.html#' + name + ') (' + descr + ')\n') return -- cgit 1.4.1-3-g733a5 From 7a32c289319bb376d47e7a9f83057f82e1d4fda0 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 16 Jun 2018 18:33:11 +0200 Subject: Fix #2741 --- clippy_lints/src/minmax.rs | 33 ++++++++++++++++++++++++++++----- tests/ui/min_max.rs | 3 +++ tests/ui/min_max.stderr | 8 ++++---- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 8c511d8f0ad..1e390b0d896 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,8 +1,9 @@ use crate::consts::{constant_simple, Constant}; -use rustc::lint::*; +use crate::utils::{match_def_path, opt_def_id, paths, sext, span_lint}; use rustc::hir::*; +use rustc::lint::*; +use rustc::ty::{self, TyCtxt}; use std::cmp::{Ordering, PartialOrd}; -use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// used to clamp values, but switched so that the result is constant. @@ -36,14 +37,22 @@ impl LintPass for MinMaxPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { - if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { + if let Some((inner_max, inner_c, ie)) = min_max(cx, oe) { if outer_max == inner_max { return; } - match (outer_max, outer_c.partial_cmp(&inner_c)) { + match ( + outer_max, + const_partial_cmp(cx.tcx, &outer_c, &inner_c, &cx.tables.expr_ty(ie).sty), + ) { (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { - span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); + span_lint( + cx, + MIN_MAX, + expr.span, + "this min/max combination leads to constant result", + ); }, } } @@ -51,6 +60,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { } } +// Constant::partial_cmp incorrectly orders signed integers +fn const_partial_cmp(tcx: TyCtxt, a: &Constant, b: &Constant, expr_ty: &ty::TypeVariants) -> Option { + match *expr_ty { + ty::TyInt(int_ty) => { + if let (&Constant::Int(a), &Constant::Int(b)) = (a, b) { + Some(sext(tcx, a, int_ty).cmp(&sext(tcx, b, int_ty))) + } else { + None + } + }, + _ => a.partial_cmp(&b), + } +} + #[derive(PartialEq, Eq, Debug)] enum MinMax { Min, diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 1199206e42c..9b29f73b2ac 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -23,6 +23,9 @@ fn main() { min(1, max(LARGE, x)); // no error, we don't lookup consts here + let y = 2isize; + min(max(y, -1), 3); + let s; s = "Hello"; diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index de4c4e16fa0..b8ea183fcc9 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -31,15 +31,15 @@ error: this min/max combination leads to constant result | ^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:29:5 + --> $DIR/min_max.rs:32:5 | -29 | min("Apple", max("Zoo", s)); +32 | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:30:5 + --> $DIR/min_max.rs:33:5 | -30 | max(min(s, "Apple"), "Zoo"); +33 | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 8625cfb9889adae936c326f4ec7a6ce270d707cc Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Mon, 18 Jun 2018 09:55:59 +0200 Subject: Version bump --- CHANGELOG.md | 6 ++++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 4 ++-- clippy_lints/src/unsafe_removed_from_name.rs | 4 ++-- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56160aa587a..2f4c1d0046a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.208 +* Rustup to *rustc 1.28.0-nightly (86a8f1a63 2018-06-17)* + ## 0.0.207 * Rustup to *rustc 1.28.0-nightly (2a0062974 2018-06-09)* @@ -643,6 +646,7 @@ All notable changes to this project will be documented in this file. [`drop_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_copy [`drop_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_ref [`duplicate_underscore_argument`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duplicate_underscore_argument +[`duration_subsec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duration_subsec [`else_if_without_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum [`empty_line_after_outer_attr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr @@ -654,6 +658,7 @@ All notable changes to this project will be documented in this file. [`erasing_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#erasing_op [`eval_order_dependence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eval_order_dependence [`excessive_precision`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#excessive_precision +[`expect_fun_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expect_fun_call [`expl_impl_clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_into_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_into_iter_loop @@ -829,6 +834,7 @@ All notable changes to this project will be documented in this file. [`transmute_ptr_to_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref [`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex +[`trivially_copy_pass_by_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity [`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc [`unimplemented`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unimplemented diff --git a/Cargo.toml b/Cargo.toml index e2be104f684..1bb86b08cae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.207" +version = "0.0.208" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.207", path = "clippy_lints" } +clippy_lints = { version = "0.0.208", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/README.md b/README.md index 305e0ba86b8..3cda0c97182 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 265 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 268 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 4797c60096b..e1dc29b533f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.207" +version = "0.0.208" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bac479deda6..31649c30db8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -591,6 +591,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::CHARS_NEXT_CMP, methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, + methods::EXPECT_FUN_CALL, methods::FILTER_NEXT, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, @@ -600,7 +601,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::OK_EXPECT, methods::OPTION_MAP_OR_NONE, methods::OR_FUN_CALL, - methods::EXPECT_FUN_CALL, methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, @@ -916,9 +916,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { large_enum_variant::LARGE_ENUM_VARIANT, loops::MANUAL_MEMCPY, loops::UNUSED_COLLECT, + methods::EXPECT_FUN_CALL, methods::ITER_NTH, methods::OR_FUN_CALL, - methods::EXPECT_FUN_CALL, methods::SINGLE_CHAR_PATTERN, misc::CMP_OWNED, mutex_atomic::MUTEX_ATOMIC, diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 56a8377d7dd..a1f31770ec0 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -43,7 +43,7 @@ impl EarlyLintPass for UnsafeNameRemoval { fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: Span) { match use_tree.kind { - UseTreeKind::Simple(Some(new_name)) => { + UseTreeKind::Simple(Some(new_name), ..) => { let old_name = use_tree .prefix .segments @@ -52,7 +52,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: Span) { .ident; unsafe_to_safe_check(old_name, new_name, cx, span); } - UseTreeKind::Simple(None) | + UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {}, UseTreeKind::Nested(ref nested_use_tree) => { for &(ref use_tree, _) in nested_use_tree { -- cgit 1.4.1-3-g733a5 From d3b862f9d75c09f98815928054a5e5d470535211 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Jun 2018 10:48:24 +0200 Subject: Bump min_version.txt --- min_version.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/min_version.txt b/min_version.txt index 8feb513faca..f14456b1e1c 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (2a0062974 2018-06-09) +rustc 1.28.0-nightly (86a8f1a63 2018-06-17) binary: rustc -commit-hash: 2a0062974a5225847fc43d5522c4dc3718173fe5 -commit-date: 2018-06-09 +commit-hash: 86a8f1a6374dd558ebdafe061e61720a73ae732c +commit-date: 2018-06-17 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From b24d75313ebda42104cf60977d03748976da8c40 Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Sun, 17 Jun 2018 22:58:08 +0100 Subject: Exclude generated code --- clippy_lints/src/default_trait_access.rs | 23 +++++++----- clippy_lints/src/utils/mod.rs | 14 +++++++ tests/ui/default_trait_access.rs | 63 +++++++++++++++++++++++++++++++- tests/ui/default_trait_access.stderr | 28 +++++++++++--- 4 files changed, 113 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 0222f896e28..d96ed8db786 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,7 +1,8 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::ty::TypeVariants; -use crate::utils::{match_def_path, opt_def_id, paths, span_lint_and_sugg}; +use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; /// **What it does:** Checks for literal calls to `Default::default()`. @@ -38,6 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { if let ExprCall(ref path, ..) = expr.node; + if !any_parent_is_automatically_derived(cx.tcx, expr.id); if let ExprPath(ref qpath) = path.node; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); @@ -46,14 +48,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { QPath::Resolved(..) => { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. - let replacement = format!("{}::default()", cx.tables.expr_ty(expr)); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("Calling {} is more clear than this expression", replacement), - "try", - replacement); + let expr_ty = cx.tables.expr_ty(expr); + if let TypeVariants::TyAdt(..) = expr_ty.sty { + let replacement = format!("{}::default()", expr_ty); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("Calling {} is more clear than this expression", replacement), + "try", + replacement); + } }, QPath::TypeRelative(..) => {}, } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6c3f0c25a3e..fd82b2b44d9 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1128,3 +1128,17 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { without } + +pub fn any_parent_is_automatically_derived(tcx: TyCtxt, node: NodeId) -> bool { + let map = &tcx.hir; + let mut prev_enclosing_node = None; + let mut enclosing_node = node; + while Some(enclosing_node) != prev_enclosing_node { + if is_automatically_derived(map.attrs(enclosing_node)) { + return true; + } + prev_enclosing_node = Some(enclosing_node); + enclosing_node = map.get_parent(enclosing_node); + } + false +} diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 9db875ee305..675e64246fa 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -23,7 +23,45 @@ fn main() { let s9: String = DefaultFactory::make_t_nicely(); - println!("[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", s1, s2, s3, s4, s5, s6, s7, s8, s9); + let s10 = DerivedDefault::default(); + + let s11: GenericDerivedDefault = Default::default(); + + let s12 = GenericDerivedDefault::::default(); + + let s13 = TupleDerivedDefault::default(); + + let s14: TupleDerivedDefault = Default::default(); + + let s15: ArrayDerivedDefault = Default::default(); + + let s16 = ArrayDerivedDefault::default(); + + let s17: TupleStructDerivedDefault = Default::default(); + + let s18 = TupleStructDerivedDefault::default(); + + println!( + "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]", + s1, + s2, + s3, + s4, + s5, + s6, + s7, + s8, + s9, + s10, + s11, + s12, + s13, + s14, + s15, + s16, + s17, + s18, + ); } struct DefaultFactory; @@ -37,3 +75,26 @@ impl DefaultFactory { T::default() } } + +#[derive(Debug, Default)] +struct DerivedDefault { + pub s: String, +} + +#[derive(Debug, Default)] +struct GenericDerivedDefault { + pub s: T, +} + +#[derive(Debug, Default)] +struct TupleDerivedDefault { + pub s: (String, String), +} + +#[derive(Debug, Default)] +struct ArrayDerivedDefault { + pub s: [String; 10], +} + +#[derive(Debug, Default)] +struct TupleStructDerivedDefault(String); diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index b2cb49e6c80..8bb4731035a 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -24,11 +24,29 @@ error: Calling std::string::String::default() is more clear than this expression 18 | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: Calling T::default() is more clear than this expression - --> $DIR/default_trait_access.rs:33:9 +error: Calling GenericDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:28:46 | -33 | Default::default() - | ^^^^^^^^^^^^^^^^^^ help: try: `T::default()` +28 | let s11: GenericDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` -error: aborting due to 5 previous errors +error: Calling TupleDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:34:36 + | +34 | let s14: TupleDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` + +error: Calling ArrayDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:36:36 + | +36 | let s15: ArrayDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` + +error: Calling TupleStructDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:40:42 + | +40 | let s17: TupleStructDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 0f83c68698db709dfcc64bd9eef22feabde945c9 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 19 Jun 2018 07:37:09 +0200 Subject: Replace `Constant::partial_cmp` --- clippy_lints/src/consts.rs | 31 +++++++++++++++++++++---------- clippy_lints/src/minmax.rs | 21 +++------------------ 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index c700af1e6e3..36417cd0877 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -122,21 +122,32 @@ impl Hash for Constant { } } -impl PartialOrd for Constant { - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { +impl Constant { + pub fn partial_cmp(tcx: TyCtxt, cmp_type: &ty::TypeVariants, left: &Self, right: &Self) -> Option { + match (left, right) { (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), - (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), + (&Constant::Int(l), &Constant::Int(r)) => { + if let ty::TyInt(int_ty) = *cmp_type { + Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))) + } else { + Some(l.cmp(&r)) + } + }, (&Constant::F64(l), &Constant::F64(r)) => l.partial_cmp(&r), (&Constant::F32(l), &Constant::F32(r)) => l.partial_cmp(&r), (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => { - l.partial_cmp(r) - }, - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => match lv.partial_cmp(rv) { - Some(Equal) => Some(ls.cmp(rs)), - x => x, + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l + .iter() + .zip(r.iter()) + .map(|(li, ri)| Constant::partial_cmp(tcx, cmp_type, li, ri)) + .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { + match Constant::partial_cmp(tcx, cmp_type, lv, rv) { + Some(Equal) => Some(ls.cmp(rs)), + x => x, + } }, _ => None, // TODO: Are there any useful inter-type orderings? } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 1e390b0d896..4be2b9f5227 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,9 +1,8 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{match_def_path, opt_def_id, paths, sext, span_lint}; +use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::*; use rustc::lint::*; -use rustc::ty::{self, TyCtxt}; -use std::cmp::{Ordering, PartialOrd}; +use std::cmp::Ordering; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// used to clamp values, but switched so that the result is constant. @@ -43,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { } match ( outer_max, - const_partial_cmp(cx.tcx, &outer_c, &inner_c, &cx.tables.expr_ty(ie).sty), + Constant::partial_cmp(cx.tcx, &cx.tables.expr_ty(ie).sty, &outer_c, &inner_c), ) { (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { @@ -60,20 +59,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { } } -// Constant::partial_cmp incorrectly orders signed integers -fn const_partial_cmp(tcx: TyCtxt, a: &Constant, b: &Constant, expr_ty: &ty::TypeVariants) -> Option { - match *expr_ty { - ty::TyInt(int_ty) => { - if let (&Constant::Int(a), &Constant::Int(b)) = (a, b) { - Some(sext(tcx, a, int_ty).cmp(&sext(tcx, b, int_ty))) - } else { - None - } - }, - _ => a.partial_cmp(&b), - } -} - #[derive(PartialEq, Eq, Debug)] enum MinMax { Min, -- cgit 1.4.1-3-g733a5 From 7d672888fe192290c31b626a393dd14ec1865fbc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 09:56:37 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lifetimes.rs | 10 ++++++---- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/utils/inspector.rs | 3 +++ clippy_lints/src/utils/mod.rs | 1 + min_version.txt | 6 +++--- 8 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f4c1d0046a..96a1e7e5acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.209 +* Rustup to *rustc 1.28.0-nightly (523097979 2018-06-18)* + ## 0.0.208 * Rustup to *rustc 1.28.0-nightly (86a8f1a63 2018-06-17)* diff --git a/Cargo.toml b/Cargo.toml index 1bb86b08cae..de2db9604a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.208" +version = "0.0.209" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.208", path = "clippy_lints" } +clippy_lints = { version = "0.0.209", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e1dc29b533f..be46cda4975 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.208" +version = "0.0.209" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 42f8da7c96c..e4599631076 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -327,10 +327,12 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); }, - TyImplTraitExistential(ref exist_ty, _) => { - for bound in &exist_ty.bounds { - if let RegionTyParamBound(_) = *bound { - self.record(&None); + TyImplTraitExistential(exist_ty_id, _, _) => { + if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node { + for bound in &exist_ty.bounds { + if let RegionTyParamBound(_) = *bound { + self.record(&None); + } } } } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 94d1ab0ae12..ebb3869f48c 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -143,6 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemGlobalAsm(..) => "an assembly blob", hir::ItemTy(..) => "a type alias", hir::ItemUnion(..) => "a union", + hir::ItemExistential(..) => "an existential type", hir::ItemExternCrate(..) | hir::ItemForeignMod(..) | hir::ItemImpl(..) | diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index cab9adc7b0c..46b65cf39b6 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -380,6 +380,9 @@ fn print_item(cx: &LateContext, item: &hir::Item) { hir::ItemTy(..) => { println!("type alias for {:?}", cx.tcx.type_of(did)); }, + hir::ItemExistential(..) => { + println!("existential type with real type {:?}", cx.tcx.type_of(did)); + }, hir::ItemEnum(..) => { println!("enum definition of type {:?}", cx.tcx.type_of(did)); }, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6c3f0c25a3e..02391cde61d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -981,6 +981,7 @@ pub fn opt_def_id(def: Def) -> Option { Def::Const(id) | Def::AssociatedConst(id) | Def::Macro(id, ..) | + Def::Existential(id) | Def::GlobalAsm(id) => Some(id), Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, diff --git a/min_version.txt b/min_version.txt index f14456b1e1c..7971ed2b327 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (86a8f1a63 2018-06-17) +rustc 1.28.0-nightly (523097979 2018-06-18) binary: rustc -commit-hash: 86a8f1a6374dd558ebdafe061e61720a73ae732c -commit-date: 2018-06-17 +commit-hash: 5230979794db209de492b3f7cc688020b72bc7c6 +commit-date: 2018-06-18 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From ce1800d5998f92f27ba3415d584a621c01db309d Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Tue, 19 Jun 2018 21:25:38 +0800 Subject: Check lifetimes in Fn traits in generic bounds. Add tests. --- clippy_lints/src/lifetimes.rs | 5 +++++ tests/ui/lifetimes.rs | 4 ++++ tests/ui/lifetimes.stderr | 28 ++++++++++++++-------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index e4599631076..f84d942e1c9 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -103,6 +103,11 @@ fn check_fn_inner<'a, 'tcx>( let mut bounds_lts = Vec::new(); for typ in generics.ty_params() { for bound in &typ.bounds { + let mut visitor = RefVisitor::new(cx); + walk_ty_param_bound(&mut visitor, bound); + if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { + return; + } if let TraitTyParamBound(ref trait_ref, _) = *bound { let params = &trait_ref .trait_ref diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index d2de1cb8ed8..3ddf70144f2 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -53,6 +53,10 @@ fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> { unreachable!() } +fn fn_bound_3<'a, F: FnOnce(&'a ())>(x: &'a (), f: F) {} // no error, referenced + +fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(x: &'a (), f: F) {} // no error, referenced + struct X { x: u8, } diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 23b353d13d2..1d974831750 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -45,45 +45,45 @@ error: explicit lifetimes given in parameter types where they could be elided | |__________________^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:61:5 + --> $DIR/lifetimes.rs:65:5 | -61 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } +65 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:65:5 + --> $DIR/lifetimes.rs:69:5 | -65 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } +69 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:81:1 + --> $DIR/lifetimes.rs:85:1 | -81 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } +85 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:101:1 + --> $DIR/lifetimes.rs:105:1 | -101 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } +105 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:105:1 + --> $DIR/lifetimes.rs:109:1 | -105 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } +109 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:116:1 + --> $DIR/lifetimes.rs:120:1 | -116 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } +120 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:120:1 + --> $DIR/lifetimes.rs:124:1 | -120 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } +124 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 5b57b5fc61fda228a8fb9f3cccecdc01dddf8480 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Tue, 19 Jun 2018 23:12:17 +0800 Subject: Add notes for test examples. --- tests/ui/lifetimes.rs | 16 ++++++++++++++-- tests/ui/lifetimes.stderr | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 3ddf70144f2..0322d42e81f 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -53,9 +53,21 @@ fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> { unreachable!() } -fn fn_bound_3<'a, F: FnOnce(&'a ())>(x: &'a (), f: F) {} // no error, referenced +fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { // no error, see below + f(x); +} + +fn fn_bound_3_cannot_elide() { + let x = 42; + let p = &x; + let mut q = &x; + fn_bound_3(p, |y| q = y); // this will fail if we elides lifetimes of `fn_bound_3` +} -fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(x: &'a (), f: F) {} // no error, referenced +// no error, multiple input refs +fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () { + if cond { x } else { f() } +} struct X { x: u8, diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 1d974831750..b69438af9f8 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -45,45 +45,45 @@ error: explicit lifetimes given in parameter types where they could be elided | |__________________^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:65:5 + --> $DIR/lifetimes.rs:77:5 | -65 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } +77 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:69:5 + --> $DIR/lifetimes.rs:81:5 | -69 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } +81 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:85:1 + --> $DIR/lifetimes.rs:97:1 | -85 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } +97 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:105:1 + --> $DIR/lifetimes.rs:117:1 | -105 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } +117 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:109:1 + --> $DIR/lifetimes.rs:121:1 | -109 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } +121 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:120:1 + --> $DIR/lifetimes.rs:132:1 | -120 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } +132 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:124:1 + --> $DIR/lifetimes.rs:136:1 | -124 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } +136 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 7af0c678559ef75e9ec6359ec3e05d76dfc355f5 Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Tue, 22 May 2018 21:56:02 -0700 Subject: Extend `indexing_slicing` lint Hey there clippy team! I've made some assumptions in this PR and I'm not at all certain they'll look like the right approach to you. I'm looking forward to any feedback or revision requests you have, thanks! Prior to this commit the `indexing_slicing` lint was limited to indexing/slicing operations on arrays. This meant that the scope of a really useful lint didn't include vectors. In order to include vectors in the `indexing_slicing` lint a few steps were taken. The `array_indexing.rs` source file in `clippy_lints` was renamed to `indexing_slicing.rs` to more accurately reflect the lint's new scope. The `OUT_OF_BOUNDS_INDEXING` lint persists through these changes so if we can know that a constant index or slice on an array is in bounds no lint is triggered. The `array_indexing` tests in the `tests/ui` directory were also extended and moved to `indexing_slicing.rs` and `indexing_slicing.stderr`. The `indexing_slicing` lint was moved to the `clippy_pedantic` lint group. A specific "Consider using" string was added to each of the `indexing_slicing` lint reports. At least one of the test scenarios might look peculiar and I'll leave it up to y'all to decide if it's palatable. It's the result of indexing the array `x` after `let x = [1, 2, 3, 4];` ``` error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)`instead --> $DIR/indexing_slicing.rs:23:6 | 23 | &x[0..][..3]; | ^^^^^^^^^^^ ``` The error string reports only on the second half's range-to, because the range-from is in bounds! Again, thanks for taking a look. Closes #2536 --- clippy_lints/src/array_indexing.rs | 168 +++++++++++++++++++++-------- clippy_lints/src/lib.rs | 4 +- tests/ui/array_indexing.rs | 21 +++- tests/ui/array_indexing.stderr | 216 +++++++++++++++++++++++++++---------- 4 files changed, 302 insertions(+), 107 deletions(-) diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 77aa5e83425..e7bb590e60d 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,3 +1,5 @@ +//! lint on indexing and slicing operations + use crate::consts::{constant, Constant}; use crate::utils::higher::Range; use crate::utils::{self, higher}; @@ -16,9 +18,14 @@ use syntax::ast::RangeLimits; /// **Example:** /// ```rust /// let x = [1,2,3,4]; -/// ... +/// +/// // Bad /// x[9]; /// &x[2..9]; +/// +/// // Good +/// x[0]; +/// x[3]; /// ``` declare_clippy_lint! { pub OUT_OF_BOUNDS_INDEXING, @@ -26,19 +33,29 @@ declare_clippy_lint! { "out of bounds constant indexing" } -/// **What it does:** Checks for usage of indexing or slicing. +/// **What it does:** Checks for usage of indexing or slicing. Does not report +/// if we can tell that the indexing or slicing operations on an array are in +/// bounds. /// -/// **Why is this bad?** Usually, this can be safely allowed. However, in some -/// domains such as kernel development, a panic can cause the whole operating -/// system to crash. +/// **Why is this bad?** Indexing and slicing can panic at runtime and there are +/// safe alternatives. /// /// **Known problems:** Hopefully none. /// /// **Example:** /// ```rust -/// ... +/// let x = vec![0; 5]; +/// // Bad /// x[2]; -/// &x[0..2]; +/// &x[2..100]; +/// &x[2..]; +/// &x[..100]; +/// +/// // Good +/// x.get(2) +/// x.get(2..100) +/// x.get(2..) +/// x.get(..100) /// ``` declare_clippy_lint! { pub INDEXING_SLICING, @@ -47,52 +64,105 @@ declare_clippy_lint! { } #[derive(Copy, Clone)] -pub struct ArrayIndexing; +pub struct IndexingSlicingPass; -impl LintPass for ArrayIndexing { +impl LintPass for IndexingSlicingPass { fn get_lints(&self) -> LintArray { lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) { - if let hir::ExprIndex(ref array, ref index) = e.node { - // Array with known size can be checked statically - let ty = cx.tables.expr_ty(array); - if let ty::TyArray(_, size) = ty.sty { - let size = size.assert_usize(cx.tcx).unwrap().into(); - - // Index is a constant uint - if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) { - if size <= const_index { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprIndex(ref a, ref b) = &expr.node { + match &b.node { + // Both ExprStruct and ExprPath require this approach's checks + // on the `range` returned by `higher::range(cx, b)`. + // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. + // ExprPath handles &x[..] and x[var] + ExprStruct(_, _, _) | ExprPath(_) => { + if let Some(range) = higher::range(cx, b) { + let ty = cx.tables.expr_ty(a); + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant range. + if let Some((start, end)) = to_const_range(cx, range, size) { + if start > size || end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + } else { + // Range is in bounds, ok. + return; + } + } + } + match (range.start, range.end) { + (None, Some(_)) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(..n)`or `.get_mut(..n)` instead", + ); + } + (Some(_), None) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(n..)` or .get_mut(n..)` instead", + ); + } + (Some(_), Some(_)) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(n..m)` or `.get_mut(n..m)` instead", + ); + } + (None, None) => (), + } + } else { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "indexing may panic. Consider using `.get(n)` or \ + `.get_mut(n)` instead", + ); } - - return; } - - // Index is a constant range - if let Some(range) = higher::range(cx, index) { - if let Some((start, end)) = to_const_range(cx, range, size) { - if start > size || end > size { - utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds"); + ExprLit(_) => { + // [n] + let ty = cx.tables.expr_ty(a); + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant uint. + if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, b) { + if size <= const_index { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "const index is out of bounds", + ); + } + // Else index is in bounds, ok. } - return; + } else { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "indexing may panic. Consider using `.get(n)` or \ + `.get_mut(n)` instead", + ); } } - } - - if let Some(range) = higher::range(cx, index) { - // Full ranges are always valid - if range.start.is_none() && range.end.is_none() { - return; - } - - // Impossible to know if indexing or slicing is correct - utils::span_lint(cx, INDEXING_SLICING, e.span, "slicing may panic"); - } else { - utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic"); + _ => (), } } } @@ -100,15 +170,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { /// Returns an option containing a tuple with the start and end (exclusive) of /// the range. -fn to_const_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, range: Range, array_size: u128) -> Option<(u128, u128)> { - let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); +fn to_const_range<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + range: Range, + array_size: u128, +) -> Option<(u128, u128)> { + let s = range + .start + .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let start = match s { Some(Some(Constant::Int(x))) => x, Some(_) => return None, None => 0, }; - let e = range.end.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); + let e = range + .end + .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let end = match e { Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { x + 1 diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a2f2ae8ab0c..bd89b37dc3a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -355,8 +355,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ); reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack}); reg.register_early_lint_pass(box misc_early::MiscEarly); - reg.register_late_lint_pass(box array_indexing::ArrayIndexing); - reg.register_late_lint_pass(box panic_unimplemented::Pass); + reg.register_late_lint_pass(box array_indexing::IndexingSlicingPass); + reg.register_late_lint_pass(box panic::Pass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); diff --git a/tests/ui/array_indexing.rs b/tests/ui/array_indexing.rs index a01600edac7..2437df96bd1 100644 --- a/tests/ui/array_indexing.rs +++ b/tests/ui/array_indexing.rs @@ -1,18 +1,26 @@ #![feature(plugin)] - - #![warn(indexing_slicing)] #![warn(out_of_bounds_indexing)] #![allow(no_effect, unnecessary_operation)] fn main() { - let x = [1,2,3,4]; + let x = [1, 2, 3, 4]; + let index: usize = 1; + let index_from: usize = 2; + let index_to: usize = 3; + x[index]; + &x[index_from..index_to]; + &x[index_from..][..index_to]; + &x[index..]; + &x[..index]; x[0]; x[3]; x[4]; x[1 << 3]; &x[1..5]; + &x[1..][..5]; &x[0..3]; + &x[0..][..3]; &x[0..=4]; &x[..=4]; &x[..]; @@ -42,4 +50,11 @@ fn main() { &empty[..0]; &empty[1..]; &empty[..4]; + + let v = vec![0; 5]; + v[0]; + v[10]; + &v[10..100]; + &v[10..]; + &v[..100]; } diff --git a/tests/ui/array_indexing.stderr b/tests/ui/array_indexing.stderr index d730b012932..14ef73155a0 100644 --- a/tests/ui/array_indexing.stderr +++ b/tests/ui/array_indexing.stderr @@ -1,120 +1,222 @@ +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/array_indexing.rs:11:5 + | +11 | x[index]; + | ^^^^^^^^ + | + = note: `-D indexing-slicing` implied by `-D warnings` + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/array_indexing.rs:12:6 + | +12 | &x[index_from..index_to]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:13:6 + | +13 | &x[index_from..][..index_to]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/array_indexing.rs:13:6 + | +13 | &x[index_from..][..index_to]; + | ^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/array_indexing.rs:14:6 + | +14 | &x[index..]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:15:6 + | +15 | &x[..index]; + | ^^^^^^^^^^ + error: const index is out of bounds - --> $DIR/array_indexing.rs:12:5 + --> $DIR/array_indexing.rs:18:5 | -12 | x[4]; +18 | x[4]; | ^^^^ | = note: `-D out-of-bounds-indexing` implied by `-D warnings` -error: const index is out of bounds - --> $DIR/array_indexing.rs:13:5 +error: range is out of bounds + --> $DIR/array_indexing.rs:20:6 | -13 | x[1 << 3]; - | ^^^^^^^^^ +20 | &x[1..5]; + | ^^^^^^^ -error: range is out of bounds - --> $DIR/array_indexing.rs:14:6 +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/array_indexing.rs:20:6 | -14 | &x[1..5]; +20 | &x[1..5]; | ^^^^^^^ -error: range is out of bounds - --> $DIR/array_indexing.rs:16:6 +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:21:6 | -16 | &x[0..=4]; - | ^^^^^^^^ +21 | &x[1..][..5]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:23:6 + | +23 | &x[0..][..3]; + | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:17:6 + --> $DIR/array_indexing.rs:25:6 | -17 | &x[..=4]; +25 | &x[..=4]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:25:6 + | +25 | &x[..=4]; | ^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:21:6 + --> $DIR/array_indexing.rs:29:6 | -21 | &x[5..]; +29 | &x[5..]; | ^^^^^^ -error: range is out of bounds - --> $DIR/array_indexing.rs:23:6 +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/array_indexing.rs:29:6 | -23 | &x[..5]; +29 | &x[5..]; | ^^^^^^ -error: indexing may panic - --> $DIR/array_indexing.rs:26:5 +error: range is out of bounds + --> $DIR/array_indexing.rs:31:6 | -26 | y[0]; - | ^^^^ +31 | &x[..5]; + | ^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:31:6 | - = note: `-D indexing-slicing` implied by `-D warnings` +31 | &x[..5]; + | ^^^^^^ -error: slicing may panic - --> $DIR/array_indexing.rs:27:6 +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/array_indexing.rs:34:5 | -27 | &y[1..2]; - | ^^^^^^^ +34 | y[0]; + | ^^^^ -error: slicing may panic - --> $DIR/array_indexing.rs:29:6 +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/array_indexing.rs:35:6 | -29 | &y[0..=4]; - | ^^^^^^^^ +35 | &y[1..2]; + | ^^^^^^^ -error: slicing may panic - --> $DIR/array_indexing.rs:30:6 +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:38:6 | -30 | &y[..=4]; +38 | &y[..=4]; | ^^^^^^^ error: const index is out of bounds - --> $DIR/array_indexing.rs:33:5 + --> $DIR/array_indexing.rs:41:5 | -33 | empty[0]; +41 | empty[0]; | ^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:34:6 + --> $DIR/array_indexing.rs:42:6 | -34 | &empty[1..5]; +42 | &empty[1..5]; | ^^^^^^^^^^^ -error: range is out of bounds - --> $DIR/array_indexing.rs:35:6 +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/array_indexing.rs:42:6 | -35 | &empty[0..=4]; - | ^^^^^^^^^^^^ +42 | &empty[1..5]; + | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:36:6 + --> $DIR/array_indexing.rs:44:6 | -36 | &empty[..=4]; +44 | &empty[..=4]; | ^^^^^^^^^^^ -error: range is out of bounds - --> $DIR/array_indexing.rs:40:6 +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:44:6 | -40 | &empty[0..=0]; - | ^^^^^^^^^^^^ +44 | &empty[..=4]; + | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:41:6 + --> $DIR/array_indexing.rs:49:6 | -41 | &empty[..=0]; +49 | &empty[..=0]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:49:6 + | +49 | &empty[..=0]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:43:6 + --> $DIR/array_indexing.rs:51:6 | -43 | &empty[1..]; +51 | &empty[1..]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/array_indexing.rs:51:6 + | +51 | &empty[1..]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/array_indexing.rs:44:6 + --> $DIR/array_indexing.rs:52:6 + | +52 | &empty[..4]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:52:6 + | +52 | &empty[..4]; + | ^^^^^^^^^^ + +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/array_indexing.rs:55:5 + | +55 | v[0]; + | ^^^^ + +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/array_indexing.rs:56:5 | -44 | &empty[..4]; +56 | v[10]; + | ^^^^^ + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/array_indexing.rs:57:6 + | +57 | &v[10..100]; | ^^^^^^^^^^ -error: aborting due to 19 previous errors +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/array_indexing.rs:58:6 + | +58 | &v[10..]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/array_indexing.rs:59:6 + | +59 | &v[..100]; + | ^^^^^^^^ + +error: aborting due to 36 previous errors -- cgit 1.4.1-3-g733a5 From 5b759efa4c9702aa095f1564e9cfa76046abf2b1 Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Tue, 22 May 2018 22:02:07 -0700 Subject: Rename instances of `array_indexing` This commit renames instances of `array_indexing` to `indexing_slicing` and moves the `indexing_slicing` lint to the `clippy_pedantic` group. The justification for this commit's changes are detailed in the previous commit's message. --- clippy_lints/src/array_indexing.rs | 201 ------------------------------- clippy_lints/src/indexing_slicing.rs | 201 +++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 15 ++- tests/ui/array_indexing.rs | 60 ---------- tests/ui/array_indexing.stderr | 222 ----------------------------------- tests/ui/indexing_slicing.rs | 60 ++++++++++ tests/ui/indexing_slicing.stderr | 222 +++++++++++++++++++++++++++++++++++ 7 files changed, 490 insertions(+), 491 deletions(-) delete mode 100644 clippy_lints/src/array_indexing.rs create mode 100644 clippy_lints/src/indexing_slicing.rs delete mode 100644 tests/ui/array_indexing.rs delete mode 100644 tests/ui/array_indexing.stderr create mode 100644 tests/ui/indexing_slicing.rs create mode 100644 tests/ui/indexing_slicing.stderr diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs deleted file mode 100644 index e7bb590e60d..00000000000 --- a/clippy_lints/src/array_indexing.rs +++ /dev/null @@ -1,201 +0,0 @@ -//! lint on indexing and slicing operations - -use crate::consts::{constant, Constant}; -use crate::utils::higher::Range; -use crate::utils::{self, higher}; -use rustc::hir; -use rustc::lint::*; -use rustc::ty; -use syntax::ast::RangeLimits; - -/// **What it does:** Checks for out of bounds array indexing with a constant -/// index. -/// -/// **Why is this bad?** This will always panic at runtime. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// ```rust -/// let x = [1,2,3,4]; -/// -/// // Bad -/// x[9]; -/// &x[2..9]; -/// -/// // Good -/// x[0]; -/// x[3]; -/// ``` -declare_clippy_lint! { - pub OUT_OF_BOUNDS_INDEXING, - correctness, - "out of bounds constant indexing" -} - -/// **What it does:** Checks for usage of indexing or slicing. Does not report -/// if we can tell that the indexing or slicing operations on an array are in -/// bounds. -/// -/// **Why is this bad?** Indexing and slicing can panic at runtime and there are -/// safe alternatives. -/// -/// **Known problems:** Hopefully none. -/// -/// **Example:** -/// ```rust -/// let x = vec![0; 5]; -/// // Bad -/// x[2]; -/// &x[2..100]; -/// &x[2..]; -/// &x[..100]; -/// -/// // Good -/// x.get(2) -/// x.get(2..100) -/// x.get(2..) -/// x.get(..100) -/// ``` -declare_clippy_lint! { - pub INDEXING_SLICING, - restriction, - "indexing/slicing usage" -} - -#[derive(Copy, Clone)] -pub struct IndexingSlicingPass; - -impl LintPass for IndexingSlicingPass { - fn get_lints(&self) -> LintArray { - lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprIndex(ref a, ref b) = &expr.node { - match &b.node { - // Both ExprStruct and ExprPath require this approach's checks - // on the `range` returned by `higher::range(cx, b)`. - // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. - // ExprPath handles &x[..] and x[var] - ExprStruct(_, _, _) | ExprPath(_) => { - if let Some(range) = higher::range(cx, b) { - let ty = cx.tables.expr_ty(a); - if let ty::TyArray(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - // Index is a constant range. - if let Some((start, end)) = to_const_range(cx, range, size) { - if start > size || end > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - } else { - // Range is in bounds, ok. - return; - } - } - } - match (range.start, range.end) { - (None, Some(_)) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(..n)`or `.get_mut(..n)` instead", - ); - } - (Some(_), None) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(n..)` or .get_mut(n..)` instead", - ); - } - (Some(_), Some(_)) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(n..m)` or `.get_mut(n..m)` instead", - ); - } - (None, None) => (), - } - } else { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "indexing may panic. Consider using `.get(n)` or \ - `.get_mut(n)` instead", - ); - } - } - ExprLit(_) => { - // [n] - let ty = cx.tables.expr_ty(a); - if let ty::TyArray(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - // Index is a constant uint. - if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, b) { - if size <= const_index { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "const index is out of bounds", - ); - } - // Else index is in bounds, ok. - } - } else { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "indexing may panic. Consider using `.get(n)` or \ - `.get_mut(n)` instead", - ); - } - } - _ => (), - } - } - } -} - -/// Returns an option containing a tuple with the start and end (exclusive) of -/// the range. -fn to_const_range<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - range: Range, - array_size: u128, -) -> Option<(u128, u128)> { - let s = range - .start - .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); - let start = match s { - Some(Some(Constant::Int(x))) => x, - Some(_) => return None, - None => 0, - }; - - let e = range - .end - .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); - let end = match e { - Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { - x + 1 - } else { - x - }, - Some(_) => return None, - None => array_size, - }; - - Some((start, end)) -} diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs new file mode 100644 index 00000000000..d7f2a37c5fe --- /dev/null +++ b/clippy_lints/src/indexing_slicing.rs @@ -0,0 +1,201 @@ +//! lint on indexing and slicing operations + +use crate::consts::{constant, Constant}; +use crate::utils::higher::Range; +use crate::utils::{self, higher}; +use rustc::hir::*; +use rustc::lint::*; +use rustc::ty; +use syntax::ast::RangeLimits; + +/// **What it does:** Checks for out of bounds array indexing with a constant +/// index. +/// +/// **Why is this bad?** This will always panic at runtime. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust +/// let x = [1,2,3,4]; +/// +/// // Bad +/// x[9]; +/// &x[2..9]; +/// +/// // Good +/// x[0]; +/// x[3]; +/// ``` +declare_clippy_lint! { + pub OUT_OF_BOUNDS_INDEXING, + correctness, + "out of bounds constant indexing" +} + +/// **What it does:** Checks for usage of indexing or slicing. Does not report +/// if we can tell that the indexing or slicing operations on an array are in +/// bounds. +/// +/// **Why is this bad?** Indexing and slicing can panic at runtime and there are +/// safe alternatives. +/// +/// **Known problems:** Hopefully none. +/// +/// **Example:** +/// ```rust +/// let x = vec![0; 5]; +/// // Bad +/// x[2]; +/// &x[2..100]; +/// &x[2..]; +/// &x[..100]; +/// +/// // Good +/// x.get(2) +/// x.get(2..100) +/// x.get(2..) +/// x.get(..100) +/// ``` +declare_clippy_lint! { + pub INDEXING_SLICING, + restriction, + "indexing/slicing usage" +} + +#[derive(Copy, Clone)] +pub struct IndexingSlicingPass; + +impl LintPass for IndexingSlicingPass { + fn get_lints(&self) -> LintArray { + lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprIndex(ref a, ref b) = &expr.node { + match &b.node { + // Both ExprStruct and ExprPath require this approach's checks + // on the `range` returned by `higher::range(cx, b)`. + // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. + // ExprPath handles &x[..] and x[var] + ExprStruct(_, _, _) | ExprPath(_) => { + if let Some(range) = higher::range(cx, b) { + let ty = cx.tables.expr_ty(a); + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant range. + if let Some((start, end)) = to_const_range(cx, range, size) { + if start > size || end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + } else { + // Range is in bounds, ok. + return; + } + } + } + match (range.start, range.end) { + (None, Some(_)) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(..n)`or `.get_mut(..n)` instead", + ); + } + (Some(_), None) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(n..)` or .get_mut(n..)` instead", + ); + } + (Some(_), Some(_)) => { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "slicing may panic. Consider using \ + `.get(n..m)` or `.get_mut(n..m)` instead", + ); + } + (None, None) => (), + } + } else { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "indexing may panic. Consider using `.get(n)` or \ + `.get_mut(n)` instead", + ); + } + } + ExprLit(_) => { + // [n] + let ty = cx.tables.expr_ty(a); + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant uint. + if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, b) { + if size <= const_index { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "const index is out of bounds", + ); + } + // Else index is in bounds, ok. + } + } else { + cx.span_lint( + INDEXING_SLICING, + expr.span, + "indexing may panic. Consider using `.get(n)` or \ + `.get_mut(n)` instead", + ); + } + } + _ => (), + } + } + } +} + +/// Returns an option containing a tuple with the start and end (exclusive) of +/// the range. +fn to_const_range<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + range: Range, + array_size: u128, +) -> Option<(u128, u128)> { + let s = range + .start + .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); + let start = match s { + Some(Some(Constant::Int(x))) => x, + Some(_) => return None, + None => 0, + }; + + let e = range + .end + .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); + let end = match e { + Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { + x + 1 + } else { + x + }, + Some(_) => return None, + None => array_size, + }; + + Some((start, end)) +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bd89b37dc3a..e261fe417f7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -6,7 +6,7 @@ #![feature(stmt_expr_attributes)] #![feature(range_contains)] #![feature(macro_vis_matcher)] -#![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] +#![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] #![allow(stable_features)] #![feature(iterator_find_map)] @@ -99,7 +99,6 @@ pub mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; pub mod arithmetic; -pub mod array_indexing; pub mod assign_ops; pub mod attrs; pub mod bit_mask; @@ -139,6 +138,7 @@ pub mod identity_conversion; pub mod identity_op; pub mod if_let_redundant_pattern_matching; pub mod if_not_else; +pub mod indexing_slicing; pub mod infallible_destructuring_match; pub mod infinite_iter; pub mod inherent_impl; @@ -355,8 +355,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ); reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack}); reg.register_early_lint_pass(box misc_early::MiscEarly); - reg.register_late_lint_pass(box array_indexing::IndexingSlicingPass); - reg.register_late_lint_pass(box panic::Pass); + reg.register_late_lint_pass(box panic_unimplemented::Pass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); @@ -432,12 +431,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unwrap::Pass); reg.register_late_lint_pass(box duration_subsec::DurationSubsec); reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); - + reg.register_late_lint_pass(box indexing_slicing::IndexingSlicingPass); reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, - array_indexing::INDEXING_SLICING, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, inherent_impl::MULTIPLE_INHERENT_IMPL, @@ -468,6 +466,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, + indexing_slicing::INDEXING_SLICING, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, @@ -500,7 +499,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, - array_indexing::OUT_OF_BOUNDS_INDEXING, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_SEMVER, @@ -863,7 +862,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_correctness", vec![ approx_const::APPROX_CONSTANT, - array_indexing::OUT_OF_BOUNDS_INDEXING, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, diff --git a/tests/ui/array_indexing.rs b/tests/ui/array_indexing.rs deleted file mode 100644 index 2437df96bd1..00000000000 --- a/tests/ui/array_indexing.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![feature(plugin)] -#![warn(indexing_slicing)] -#![warn(out_of_bounds_indexing)] -#![allow(no_effect, unnecessary_operation)] - -fn main() { - let x = [1, 2, 3, 4]; - let index: usize = 1; - let index_from: usize = 2; - let index_to: usize = 3; - x[index]; - &x[index_from..index_to]; - &x[index_from..][..index_to]; - &x[index..]; - &x[..index]; - x[0]; - x[3]; - x[4]; - x[1 << 3]; - &x[1..5]; - &x[1..][..5]; - &x[0..3]; - &x[0..][..3]; - &x[0..=4]; - &x[..=4]; - &x[..]; - &x[1..]; - &x[4..]; - &x[5..]; - &x[..4]; - &x[..5]; - - let y = &x; - y[0]; - &y[1..2]; - &y[..]; - &y[0..=4]; - &y[..=4]; - - let empty: [i8; 0] = []; - empty[0]; - &empty[1..5]; - &empty[0..=4]; - &empty[..=4]; - &empty[..]; - &empty[0..]; - &empty[0..0]; - &empty[0..=0]; - &empty[..=0]; - &empty[..0]; - &empty[1..]; - &empty[..4]; - - let v = vec![0; 5]; - v[0]; - v[10]; - &v[10..100]; - &v[10..]; - &v[..100]; -} diff --git a/tests/ui/array_indexing.stderr b/tests/ui/array_indexing.stderr deleted file mode 100644 index 14ef73155a0..00000000000 --- a/tests/ui/array_indexing.stderr +++ /dev/null @@ -1,222 +0,0 @@ -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/array_indexing.rs:11:5 - | -11 | x[index]; - | ^^^^^^^^ - | - = note: `-D indexing-slicing` implied by `-D warnings` - -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/array_indexing.rs:12:6 - | -12 | &x[index_from..index_to]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:13:6 - | -13 | &x[index_from..][..index_to]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/array_indexing.rs:13:6 - | -13 | &x[index_from..][..index_to]; - | ^^^^^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/array_indexing.rs:14:6 - | -14 | &x[index..]; - | ^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:15:6 - | -15 | &x[..index]; - | ^^^^^^^^^^ - -error: const index is out of bounds - --> $DIR/array_indexing.rs:18:5 - | -18 | x[4]; - | ^^^^ - | - = note: `-D out-of-bounds-indexing` implied by `-D warnings` - -error: range is out of bounds - --> $DIR/array_indexing.rs:20:6 - | -20 | &x[1..5]; - | ^^^^^^^ - -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/array_indexing.rs:20:6 - | -20 | &x[1..5]; - | ^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:21:6 - | -21 | &x[1..][..5]; - | ^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:23:6 - | -23 | &x[0..][..3]; - | ^^^^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:25:6 - | -25 | &x[..=4]; - | ^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:25:6 - | -25 | &x[..=4]; - | ^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:29:6 - | -29 | &x[5..]; - | ^^^^^^ - -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/array_indexing.rs:29:6 - | -29 | &x[5..]; - | ^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:31:6 - | -31 | &x[..5]; - | ^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:31:6 - | -31 | &x[..5]; - | ^^^^^^ - -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/array_indexing.rs:34:5 - | -34 | y[0]; - | ^^^^ - -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/array_indexing.rs:35:6 - | -35 | &y[1..2]; - | ^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:38:6 - | -38 | &y[..=4]; - | ^^^^^^^ - -error: const index is out of bounds - --> $DIR/array_indexing.rs:41:5 - | -41 | empty[0]; - | ^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:42:6 - | -42 | &empty[1..5]; - | ^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/array_indexing.rs:42:6 - | -42 | &empty[1..5]; - | ^^^^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:44:6 - | -44 | &empty[..=4]; - | ^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:44:6 - | -44 | &empty[..=4]; - | ^^^^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:49:6 - | -49 | &empty[..=0]; - | ^^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:49:6 - | -49 | &empty[..=0]; - | ^^^^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:51:6 - | -51 | &empty[1..]; - | ^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/array_indexing.rs:51:6 - | -51 | &empty[1..]; - | ^^^^^^^^^^ - -error: range is out of bounds - --> $DIR/array_indexing.rs:52:6 - | -52 | &empty[..4]; - | ^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:52:6 - | -52 | &empty[..4]; - | ^^^^^^^^^^ - -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/array_indexing.rs:55:5 - | -55 | v[0]; - | ^^^^ - -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/array_indexing.rs:56:5 - | -56 | v[10]; - | ^^^^^ - -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/array_indexing.rs:57:6 - | -57 | &v[10..100]; - | ^^^^^^^^^^ - -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/array_indexing.rs:58:6 - | -58 | &v[10..]; - | ^^^^^^^ - -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/array_indexing.rs:59:6 - | -59 | &v[..100]; - | ^^^^^^^^ - -error: aborting due to 36 previous errors - diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs new file mode 100644 index 00000000000..2437df96bd1 --- /dev/null +++ b/tests/ui/indexing_slicing.rs @@ -0,0 +1,60 @@ +#![feature(plugin)] +#![warn(indexing_slicing)] +#![warn(out_of_bounds_indexing)] +#![allow(no_effect, unnecessary_operation)] + +fn main() { + let x = [1, 2, 3, 4]; + let index: usize = 1; + let index_from: usize = 2; + let index_to: usize = 3; + x[index]; + &x[index_from..index_to]; + &x[index_from..][..index_to]; + &x[index..]; + &x[..index]; + x[0]; + x[3]; + x[4]; + x[1 << 3]; + &x[1..5]; + &x[1..][..5]; + &x[0..3]; + &x[0..][..3]; + &x[0..=4]; + &x[..=4]; + &x[..]; + &x[1..]; + &x[4..]; + &x[5..]; + &x[..4]; + &x[..5]; + + let y = &x; + y[0]; + &y[1..2]; + &y[..]; + &y[0..=4]; + &y[..=4]; + + let empty: [i8; 0] = []; + empty[0]; + &empty[1..5]; + &empty[0..=4]; + &empty[..=4]; + &empty[..]; + &empty[0..]; + &empty[0..0]; + &empty[0..=0]; + &empty[..=0]; + &empty[..0]; + &empty[1..]; + &empty[..4]; + + let v = vec![0; 5]; + v[0]; + v[10]; + &v[10..100]; + &v[10..]; + &v[..100]; +} diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr new file mode 100644 index 00000000000..30231a31d19 --- /dev/null +++ b/tests/ui/indexing_slicing.stderr @@ -0,0 +1,222 @@ +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/indexing_slicing.rs:11:5 + | +11 | x[index]; + | ^^^^^^^^ + | + = note: `-D indexing-slicing` implied by `-D warnings` + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/indexing_slicing.rs:12:6 + | +12 | &x[index_from..index_to]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:13:6 + | +13 | &x[index_from..][..index_to]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/indexing_slicing.rs:13:6 + | +13 | &x[index_from..][..index_to]; + | ^^^^^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/indexing_slicing.rs:14:6 + | +14 | &x[index..]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:15:6 + | +15 | &x[..index]; + | ^^^^^^^^^^ + +error: const index is out of bounds + --> $DIR/indexing_slicing.rs:18:5 + | +18 | x[4]; + | ^^^^ + | + = note: `-D out-of-bounds-indexing` implied by `-D warnings` + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:20:6 + | +20 | &x[1..5]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/indexing_slicing.rs:20:6 + | +20 | &x[1..5]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:21:6 + | +21 | &x[1..][..5]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:23:6 + | +23 | &x[0..][..3]; + | ^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:25:6 + | +25 | &x[..=4]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:25:6 + | +25 | &x[..=4]; + | ^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:29:6 + | +29 | &x[5..]; + | ^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/indexing_slicing.rs:29:6 + | +29 | &x[5..]; + | ^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:31:6 + | +31 | &x[..5]; + | ^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:31:6 + | +31 | &x[..5]; + | ^^^^^^ + +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/indexing_slicing.rs:34:5 + | +34 | y[0]; + | ^^^^ + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/indexing_slicing.rs:35:6 + | +35 | &y[1..2]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:38:6 + | +38 | &y[..=4]; + | ^^^^^^^ + +error: const index is out of bounds + --> $DIR/indexing_slicing.rs:41:5 + | +41 | empty[0]; + | ^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:42:6 + | +42 | &empty[1..5]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/indexing_slicing.rs:42:6 + | +42 | &empty[1..5]; + | ^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:44:6 + | +44 | &empty[..=4]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:44:6 + | +44 | &empty[..=4]; + | ^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:49:6 + | +49 | &empty[..=0]; + | ^^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:49:6 + | +49 | &empty[..=0]; + | ^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:51:6 + | +51 | &empty[1..]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/indexing_slicing.rs:51:6 + | +51 | &empty[1..]; + | ^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:52:6 + | +52 | &empty[..4]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:52:6 + | +52 | &empty[..4]; + | ^^^^^^^^^^ + +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/indexing_slicing.rs:55:5 + | +55 | v[0]; + | ^^^^ + +error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead + --> $DIR/indexing_slicing.rs:56:5 + | +56 | v[10]; + | ^^^^^ + +error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead + --> $DIR/indexing_slicing.rs:57:6 + | +57 | &v[10..100]; + | ^^^^^^^^^^ + +error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead + --> $DIR/indexing_slicing.rs:58:6 + | +58 | &v[10..]; + | ^^^^^^^ + +error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead + --> $DIR/indexing_slicing.rs:59:6 + | +59 | &v[..100]; + | ^^^^^^^^ + +error: aborting due to 36 previous errors + -- cgit 1.4.1-3-g733a5 From a7c0ff3fa676aaa3e6d27a413c302abb0eba9805 Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Wed, 13 Jun 2018 23:28:57 +0000 Subject: This commit represents an attempt to address changes requested in the process of reviewing PR #2790. The changes reflected in this commit are as follows: - Revised `IndexingSlicingPass` struct name to IndexingSlicing for consistency with the rest of the code base. - Revised match arm condition to use `(..)` shorthand in favor of `(_, _, _)`. - Restored a couple telling variable names. - Calls to `cx.span_lint` were revised to use `utils::span_help_and_lint`. - Took a stab at refactoring some generalizable calls to `utils::span_help_and_lint` to minimize duplicate code. - Revised INDEXING_SLICING declaration to pedantic rather than restriction. - Added `&x[0..].get(..3)` to the test cases. --- clippy_lints/src/indexing_slicing.rs | 76 ++++++------- clippy_lints/src/lib.rs | 2 +- tests/ui/indexing_slicing.rs | 1 + tests/ui/indexing_slicing.stderr | 199 ++++++++++++++++++++++------------- 4 files changed, 164 insertions(+), 114 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index d7f2a37c5fe..1f2c7755eee 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -59,30 +59,30 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub INDEXING_SLICING, - restriction, + pedantic, "indexing/slicing usage" } #[derive(Copy, Clone)] -pub struct IndexingSlicingPass; +pub struct IndexingSlicing; -impl LintPass for IndexingSlicingPass { +impl LintPass for IndexingSlicing { fn get_lints(&self) -> LintArray { lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprIndex(ref a, ref b) = &expr.node { - match &b.node { + if let ExprIndex(ref array, ref index) = &expr.node { + match &index.node { // Both ExprStruct and ExprPath require this approach's checks - // on the `range` returned by `higher::range(cx, b)`. + // on the `range` returned by `higher::range(cx, index)`. // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. // ExprPath handles &x[..] and x[var] - ExprStruct(_, _, _) | ExprPath(_) => { - if let Some(range) = higher::range(cx, b) { - let ty = cx.tables.expr_ty(a); + ExprStruct(..) | ExprPath(..) => { + if let Some(range) = higher::range(cx, index) { + let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); // Index is a constant range. @@ -100,49 +100,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { } } } + + let help_msg; match (range.start, range.end) { (None, Some(_)) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(..n)`or `.get_mut(..n)` instead", - ); + help_msg = "Consider using `.get(..n)`or `.get_mut(..n)` instead"; } (Some(_), None) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(n..)` or .get_mut(n..)` instead", - ); + help_msg = "Consider using `.get(n..)` or .get_mut(n..)` instead"; } (Some(_), Some(_)) => { - cx.span_lint( - INDEXING_SLICING, - expr.span, - "slicing may panic. Consider using \ - `.get(n..m)` or `.get_mut(n..m)` instead", - ); + help_msg = + "Consider using `.get(n..m)` or `.get_mut(n..m)` instead"; } - (None, None) => (), + (None, None) => return, // [..] is ok } + + utils::span_help_and_lint( + cx, + INDEXING_SLICING, + expr.span, + "slicing may panic.", + help_msg, + ); } else { - cx.span_lint( + utils::span_help_and_lint( + cx, INDEXING_SLICING, expr.span, - "indexing may panic. Consider using `.get(n)` or \ - `.get_mut(n)` instead", + "indexing may panic.", + "Consider using `.get(n)` or `.get_mut(n)` instead", ); } } - ExprLit(_) => { + ExprLit(..) => { // [n] - let ty = cx.tables.expr_ty(a); + let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); // Index is a constant uint. - if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, b) { + if let Some((Constant::Int(const_index), _)) = + constant(cx, cx.tables, index) + { if size <= const_index { utils::span_lint( cx, @@ -154,11 +153,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicingPass { // Else index is in bounds, ok. } } else { - cx.span_lint( + utils::span_help_and_lint( + cx, INDEXING_SLICING, expr.span, - "indexing may panic. Consider using `.get(n)` or \ - `.get_mut(n)` instead", + "indexing may panic.", + "Consider using `.get(n)` or `.get_mut(n)` instead", ); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e261fe417f7..621b21429a9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -431,7 +431,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unwrap::Pass); reg.register_late_lint_pass(box duration_subsec::DurationSubsec); reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); - reg.register_late_lint_pass(box indexing_slicing::IndexingSlicingPass); + reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing); reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 2437df96bd1..913063b8dd5 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -21,6 +21,7 @@ fn main() { &x[1..][..5]; &x[0..3]; &x[0..][..3]; + &x[0..].get(..3); // Ok &x[0..=4]; &x[..=4]; &x[..]; diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 30231a31d19..642817d9e94 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,40 +1,51 @@ -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead +error: indexing may panic. --> $DIR/indexing_slicing.rs:11:5 | 11 | x[index]; | ^^^^^^^^ | = note: `-D indexing-slicing` implied by `-D warnings` + = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:12:6 | 12 | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:13:6 | 13 | &x[index_from..][..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:13:6 | 13 | &x[index_from..][..index_to]; | ^^^^^^^^^^^^^^^ + | + = help: Consider using `.get(n..)` or .get_mut(n..)` instead -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:14:6 | 14 | &x[index..]; | ^^^^^^^^^^ + | + = help: Consider using `.get(n..)` or .get_mut(n..)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:15:6 | 15 | &x[..index]; | ^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: const index is out of bounds --> $DIR/indexing_slicing.rs:18:5 @@ -50,173 +61,211 @@ error: range is out of bounds 20 | &x[1..5]; | ^^^^^^^ -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:20:6 | 20 | &x[1..5]; | ^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:21:6 | 21 | &x[1..][..5]; | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead +error: slicing may panic. --> $DIR/indexing_slicing.rs:23:6 | 23 | &x[0..][..3]; | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:25:6 + --> $DIR/indexing_slicing.rs:26:6 | -25 | &x[..=4]; +26 | &x[..=4]; | ^^^^^^^ -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:25:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:26:6 | -25 | &x[..=4]; +26 | &x[..=4]; | ^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:29:6 + --> $DIR/indexing_slicing.rs:30:6 | -29 | &x[5..]; +30 | &x[5..]; | ^^^^^^ -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/indexing_slicing.rs:29:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:30:6 | -29 | &x[5..]; +30 | &x[5..]; | ^^^^^^ + | + = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:31:6 + --> $DIR/indexing_slicing.rs:32:6 | -31 | &x[..5]; +32 | &x[..5]; | ^^^^^^ -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:31:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:32:6 | -31 | &x[..5]; +32 | &x[..5]; | ^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/indexing_slicing.rs:34:5 +error: indexing may panic. + --> $DIR/indexing_slicing.rs:35:5 | -34 | y[0]; +35 | y[0]; | ^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/indexing_slicing.rs:35:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:36:6 | -35 | &y[1..2]; +36 | &y[1..2]; | ^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:38:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:39:6 | -38 | &y[..=4]; +39 | &y[..=4]; | ^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: const index is out of bounds - --> $DIR/indexing_slicing.rs:41:5 + --> $DIR/indexing_slicing.rs:42:5 | -41 | empty[0]; +42 | empty[0]; | ^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:42:6 + --> $DIR/indexing_slicing.rs:43:6 | -42 | &empty[1..5]; +43 | &empty[1..5]; | ^^^^^^^^^^^ -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/indexing_slicing.rs:42:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:43:6 | -42 | &empty[1..5]; +43 | &empty[1..5]; | ^^^^^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:44:6 + --> $DIR/indexing_slicing.rs:45:6 | -44 | &empty[..=4]; +45 | &empty[..=4]; | ^^^^^^^^^^^ -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:44:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:45:6 | -44 | &empty[..=4]; +45 | &empty[..=4]; | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:49:6 + --> $DIR/indexing_slicing.rs:50:6 | -49 | &empty[..=0]; +50 | &empty[..=0]; | ^^^^^^^^^^^ -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:49:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:50:6 | -49 | &empty[..=0]; +50 | &empty[..=0]; | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:51:6 + --> $DIR/indexing_slicing.rs:52:6 | -51 | &empty[1..]; +52 | &empty[1..]; | ^^^^^^^^^^ -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/indexing_slicing.rs:51:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:52:6 | -51 | &empty[1..]; +52 | &empty[1..]; | ^^^^^^^^^^ + | + = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:52:6 + --> $DIR/indexing_slicing.rs:53:6 | -52 | &empty[..4]; +53 | &empty[..4]; | ^^^^^^^^^^ -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:52:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:53:6 | -52 | &empty[..4]; +53 | &empty[..4]; | ^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/indexing_slicing.rs:55:5 +error: indexing may panic. + --> $DIR/indexing_slicing.rs:56:5 | -55 | v[0]; +56 | v[0]; | ^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: indexing may panic. Consider using `.get(n)` or `.get_mut(n)` instead - --> $DIR/indexing_slicing.rs:56:5 +error: indexing may panic. + --> $DIR/indexing_slicing.rs:57:5 | -56 | v[10]; +57 | v[10]; | ^^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: slicing may panic. Consider using `.get(n..m)` or `.get_mut(n..m)` instead - --> $DIR/indexing_slicing.rs:57:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:58:6 | -57 | &v[10..100]; +58 | &v[10..100]; | ^^^^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead -error: slicing may panic. Consider using `.get(n..)` or .get_mut(n..)` instead - --> $DIR/indexing_slicing.rs:58:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:59:6 | -58 | &v[10..]; +59 | &v[10..]; | ^^^^^^^ + | + = help: Consider using `.get(n..)` or .get_mut(n..)` instead -error: slicing may panic. Consider using `.get(..n)`or `.get_mut(..n)` instead - --> $DIR/indexing_slicing.rs:59:6 +error: slicing may panic. + --> $DIR/indexing_slicing.rs:60:6 | -59 | &v[..100]; +60 | &v[..100]; | ^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: aborting due to 36 previous errors -- cgit 1.4.1-3-g733a5 From 8b59542acc9901a6568731541baa9f623c1991b3 Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Thu, 14 Jun 2018 16:41:56 +0000 Subject: Second pass at addressing changes requested The changes reflected in this commit (requested in PR #2790) are as follows: - Extended `INDEXING_SLICING` documentation to include the array type so that it is clearer when indexing operations are allowed. - Variable `ty` defined identically in multiple scopes was moved to an outer scope so it's only defined once. - Added a missing return statement to ensure only one lint is triggered by a scenario. - Prettified match statement with a `let` clause. (I learned something new!) - Added `&x[5..].iter().map(|x| 2 * x).collect::>()` and `&x[2..].iter().map(|x| 2 * x).collect::>()` to the test cases. The first _should trigger the lint/stderr_ and the second _should not_. --- clippy_lints/src/indexing_slicing.rs | 55 ++++++++++----- tests/ui/indexing_slicing.rs | 2 + tests/ui/indexing_slicing.stderr | 130 +++++++++-------------------------- 3 files changed, 70 insertions(+), 117 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 1f2c7755eee..01f9f45c589 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -34,7 +34,7 @@ declare_clippy_lint! { } /// **What it does:** Checks for usage of indexing or slicing. Does not report -/// if we can tell that the indexing or slicing operations on an array are in +/// on arrays if we can tell that the indexing or slicing operations are in /// bounds. /// /// **Why is this bad?** Indexing and slicing can panic at runtime and there are @@ -44,7 +44,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust +/// // Vector /// let x = vec![0; 5]; +/// /// // Bad /// x[2]; /// &x[2..100]; @@ -52,10 +54,29 @@ declare_clippy_lint! { /// &x[..100]; /// /// // Good -/// x.get(2) -/// x.get(2..100) -/// x.get(2..) -/// x.get(..100) +/// x.get(2); +/// x.get(2..100); +/// x.get(2..); +/// x.get(..100); +/// +/// // Array +/// let y = [0, 1, 2, 3]; +/// +/// // Bad +/// y[10]; +/// &y[10..100]; +/// &y[10..]; +/// &y[..100]; +/// +/// // Good +/// y[2]; +/// &y[2..]; +/// &y[..2]; +/// &y[0..3]; +/// y.get(10); +/// y.get(10..100); +/// y.get(10..); +/// y.get(..100); /// ``` declare_clippy_lint! { pub INDEXING_SLICING, @@ -75,6 +96,7 @@ impl LintPass for IndexingSlicing { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprIndex(ref array, ref index) = &expr.node { + let ty = cx.tables.expr_ty(array); match &index.node { // Both ExprStruct and ExprPath require this approach's checks // on the `range` returned by `higher::range(cx, index)`. @@ -82,7 +104,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { // ExprPath handles &x[..] and x[var] ExprStruct(..) | ExprPath(..) => { if let Some(range) = higher::range(cx, index) { - let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); // Index is a constant range. @@ -94,27 +115,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { expr.span, "range is out of bounds", ); - } else { - // Range is in bounds, ok. - return; - } + } // Else range is in bounds, ok. + + return; } } - let help_msg; - match (range.start, range.end) { + let help_msg = match (range.start, range.end) { (None, Some(_)) => { - help_msg = "Consider using `.get(..n)`or `.get_mut(..n)` instead"; + "Consider using `.get(..n)`or `.get_mut(..n)` instead" } (Some(_), None) => { - help_msg = "Consider using `.get(n..)` or .get_mut(n..)` instead"; + "Consider using `.get(n..)` or .get_mut(n..)` instead" } (Some(_), Some(_)) => { - help_msg = - "Consider using `.get(n..m)` or `.get_mut(n..m)` instead"; + "Consider using `.get(n..m)` or `.get_mut(n..m)` instead" } - (None, None) => return, // [..] is ok - } + (None, None) => return, // [..] is ok. + }; utils::span_help_and_lint( cx, @@ -135,7 +153,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { } ExprLit(..) => { // [n] - let ty = cx.tables.expr_ty(array); if let ty::TyArray(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); // Index is a constant uint. diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 913063b8dd5..a22c9034346 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -30,6 +30,8 @@ fn main() { &x[5..]; &x[..4]; &x[..5]; + &x[5..].iter().map(|x| 2 * x).collect::>(); + &x[2..].iter().map(|x| 2 * x).collect::>(); // Ok let y = &x; y[0]; diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 642817d9e94..605a96e8b8c 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -61,14 +61,6 @@ error: range is out of bounds 20 | &x[1..5]; | ^^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:20:6 - | -20 | &x[1..5]; - | ^^^^^^^ - | - = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead - error: slicing may panic. --> $DIR/indexing_slicing.rs:21:6 | @@ -91,181 +83,123 @@ error: range is out of bounds 26 | &x[..=4]; | ^^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:26:6 - | -26 | &x[..=4]; - | ^^^^^^^ - | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead - error: range is out of bounds --> $DIR/indexing_slicing.rs:30:6 | 30 | &x[5..]; | ^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:30:6 - | -30 | &x[5..]; - | ^^^^^^ - | - = help: Consider using `.get(n..)` or .get_mut(n..)` instead - error: range is out of bounds --> $DIR/indexing_slicing.rs:32:6 | 32 | &x[..5]; | ^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:32:6 +error: range is out of bounds + --> $DIR/indexing_slicing.rs:33:6 | -32 | &x[..5]; +33 | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^^^^^^ - | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:35:5 + --> $DIR/indexing_slicing.rs:37:5 | -35 | y[0]; +37 | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:36:6 + --> $DIR/indexing_slicing.rs:38:6 | -36 | &y[1..2]; +38 | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:39:6 + --> $DIR/indexing_slicing.rs:41:6 | -39 | &y[..=4]; +41 | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: const index is out of bounds - --> $DIR/indexing_slicing.rs:42:5 + --> $DIR/indexing_slicing.rs:44:5 | -42 | empty[0]; +44 | empty[0]; | ^^^^^^^^ -error: range is out of bounds - --> $DIR/indexing_slicing.rs:43:6 - | -43 | &empty[1..5]; - | ^^^^^^^^^^^ - -error: slicing may panic. - --> $DIR/indexing_slicing.rs:43:6 - | -43 | &empty[1..5]; - | ^^^^^^^^^^^ - | - = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead - error: range is out of bounds --> $DIR/indexing_slicing.rs:45:6 | -45 | &empty[..=4]; +45 | &empty[1..5]; | ^^^^^^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:45:6 - | -45 | &empty[..=4]; - | ^^^^^^^^^^^ - | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead - error: range is out of bounds - --> $DIR/indexing_slicing.rs:50:6 - | -50 | &empty[..=0]; - | ^^^^^^^^^^^ - -error: slicing may panic. - --> $DIR/indexing_slicing.rs:50:6 + --> $DIR/indexing_slicing.rs:47:6 | -50 | &empty[..=0]; +47 | &empty[..=4]; | ^^^^^^^^^^^ - | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds --> $DIR/indexing_slicing.rs:52:6 | -52 | &empty[1..]; - | ^^^^^^^^^^ - -error: slicing may panic. - --> $DIR/indexing_slicing.rs:52:6 - | -52 | &empty[1..]; - | ^^^^^^^^^^ - | - = help: Consider using `.get(n..)` or .get_mut(n..)` instead +52 | &empty[..=0]; + | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:53:6 + --> $DIR/indexing_slicing.rs:54:6 | -53 | &empty[..4]; +54 | &empty[1..]; | ^^^^^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:53:6 +error: range is out of bounds + --> $DIR/indexing_slicing.rs:55:6 | -53 | &empty[..4]; +55 | &empty[..4]; | ^^^^^^^^^^ - | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:56:5 + --> $DIR/indexing_slicing.rs:58:5 | -56 | v[0]; +58 | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:57:5 + --> $DIR/indexing_slicing.rs:59:5 | -57 | v[10]; +59 | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:58:6 + --> $DIR/indexing_slicing.rs:60:6 | -58 | &v[10..100]; +60 | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:59:6 + --> $DIR/indexing_slicing.rs:61:6 | -59 | &v[10..]; +61 | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:60:6 + --> $DIR/indexing_slicing.rs:62:6 | -60 | &v[..100]; +62 | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: aborting due to 36 previous errors +error: aborting due to 28 previous errors -- cgit 1.4.1-3-g733a5 From 4ec439bef0124a01dd71ea0d5f441066690f33ec Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Thu, 14 Jun 2018 20:04:37 +0000 Subject: Revisiting indexing_slicing test cases This commit contains a few changes. In an attempt to clarify which test cases should and should not produce stderr it became clear that some cases were being handled incorrectly. In order to address these test cases, a minor re-factor was made to the linting logic itself. The re-factor was driven by edge case handling including a need for additional match conditions for `ExprCall` (`&x[0..=4]`) and `ExprBinary` (`x[1 << 3]`). Rather than attempt to account for each potential `Expr*` the code was re-factored into simply "if ranged index" and an "otherwise" conditions. --- clippy_lints/src/indexing_slicing.rs | 133 ++++++++++------------- tests/ui/indexing_slicing.rs | 52 +++++---- tests/ui/indexing_slicing.stderr | 202 +++++++++++++++++++++++------------ 3 files changed, 220 insertions(+), 167 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 01f9f45c589..b4e6414195e 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,8 +1,9 @@ //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; +use crate::utils; +use crate::utils::higher; use crate::utils::higher::Range; -use crate::utils::{self, higher}; use rustc::hir::*; use rustc::lint::*; use rustc::ty; @@ -97,89 +98,65 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprIndex(ref array, ref index) = &expr.node { let ty = cx.tables.expr_ty(array); - match &index.node { - // Both ExprStruct and ExprPath require this approach's checks - // on the `range` returned by `higher::range(cx, index)`. - // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. - // ExprPath handles &x[..] and x[var] - ExprStruct(..) | ExprPath(..) => { - if let Some(range) = higher::range(cx, index) { - if let ty::TyArray(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - // Index is a constant range. - if let Some((start, end)) = to_const_range(cx, range, size) { - if start > size || end > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - } // Else range is in bounds, ok. - - return; - } + if let Some(range) = higher::range(cx, index) { + // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant range. + if let Some((start, end)) = to_const_range(cx, range, size) { + if start > size || end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); } - - let help_msg = match (range.start, range.end) { - (None, Some(_)) => { - "Consider using `.get(..n)`or `.get_mut(..n)` instead" - } - (Some(_), None) => { - "Consider using `.get(n..)` or .get_mut(n..)` instead" - } - (Some(_), Some(_)) => { - "Consider using `.get(n..m)` or `.get_mut(n..m)` instead" - } - (None, None) => return, // [..] is ok. - }; - - utils::span_help_and_lint( - cx, - INDEXING_SLICING, - expr.span, - "slicing may panic.", - help_msg, - ); - } else { - utils::span_help_and_lint( - cx, - INDEXING_SLICING, - expr.span, - "indexing may panic.", - "Consider using `.get(n)` or `.get_mut(n)` instead", - ); + return; } } - ExprLit(..) => { - // [n] - if let ty::TyArray(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - // Index is a constant uint. - if let Some((Constant::Int(const_index), _)) = - constant(cx, cx.tables, index) - { - if size <= const_index { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "const index is out of bounds", - ); - } - // Else index is in bounds, ok. + + let help_msg = match (range.start, range.end) { + (None, Some(_)) => "Consider using `.get(..n)`or `.get_mut(..n)` instead", + (Some(_), None) => "Consider using `.get(n..)` or .get_mut(n..)` instead", + (Some(_), Some(_)) => "Consider using `.get(n..m)` or `.get_mut(n..m)` instead", + (None, None) => return, // [..] is ok. + }; + + utils::span_help_and_lint( + cx, + INDEXING_SLICING, + expr.span, + "slicing may panic.", + help_msg, + ); + } else { + // Catchall non-range index, i.e. [n] or [n << m] + if let ty::TyArray(_, s) = ty.sty { + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + // Index is a constant uint. + if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) { + if size <= const_index { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "const index is out of bounds", + ); } - } else { - utils::span_help_and_lint( - cx, - INDEXING_SLICING, - expr.span, - "indexing may panic.", - "Consider using `.get(n)` or `.get_mut(n)` instead", - ); + // Else index is in bounds, ok. + + return; } } - _ => (), + + utils::span_help_and_lint( + cx, + INDEXING_SLICING, + expr.span, + "indexing may panic.", + "Consider using `.get(n)` or `.get_mut(n)` instead", + ); } } } diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index a22c9034346..16174afb106 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -9,55 +9,63 @@ fn main() { let index_from: usize = 2; let index_to: usize = 3; x[index]; - &x[index_from..index_to]; - &x[index_from..][..index_to]; &x[index..]; &x[..index]; - x[0]; - x[3]; + &x[index_from..index_to]; + &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. x[4]; x[1 << 3]; - &x[1..5]; - &x[1..][..5]; - &x[0..3]; - &x[0..][..3]; - &x[0..].get(..3); // Ok - &x[0..=4]; &x[..=4]; - &x[..]; - &x[1..]; - &x[4..]; + &x[1..5]; + &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. &x[5..]; - &x[..4]; &x[..5]; &x[5..].iter().map(|x| 2 * x).collect::>(); - &x[2..].iter().map(|x| 2 * x).collect::>(); // Ok + &x[0..=4]; + &x[0..][..3]; + &x[1..][..5]; + + &x[4..]; // Ok, should not produce stderr. + &x[..4]; // Ok, should not produce stderr. + &x[..]; // Ok, should not produce stderr. + &x[1..]; // Ok, should not produce stderr. + &x[2..].iter().map(|x| 2 * x).collect::>(); // Ok, should not produce stderr. + &x[0..].get(..3); // Ok, should not produce stderr. + x[0]; // Ok, should not produce stderr. + x[3]; // Ok, should not produce stderr. + &x[0..3]; // Ok, should not produce stderr. let y = &x; y[0]; &y[1..2]; - &y[..]; &y[0..=4]; &y[..=4]; + &y[..]; // Ok, should not produce stderr. + let empty: [i8; 0] = []; empty[0]; &empty[1..5]; &empty[0..=4]; &empty[..=4]; - &empty[..]; - &empty[0..]; - &empty[0..0]; - &empty[0..=0]; - &empty[..=0]; - &empty[..0]; &empty[1..]; &empty[..4]; + &empty[0..=0]; + &empty[..=0]; + + &empty[0..]; // Ok, should not produce stderr. + &empty[0..0]; // Ok, should not produce stderr. + &empty[..0]; // Ok, should not produce stderr. + &empty[..]; // Ok, should not produce stderr. let v = vec![0; 5]; v[0]; v[10]; + v[1 << 3]; &v[10..100]; + &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. &v[10..]; &v[..100]; + + &v[..]; // Ok, should not produce stderr. } diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 605a96e8b8c..c9aefe0349a 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -10,109 +10,135 @@ error: indexing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:12:6 | -12 | &x[index_from..index_to]; - | ^^^^^^^^^^^^^^^^^^^^^^^ +12 | &x[index..]; + | ^^^^^^^^^^ | - = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead + = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. --> $DIR/indexing_slicing.rs:13:6 | -13 | &x[index_from..][..index_to]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +13 | &x[..index]; + | ^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:13:6 + --> $DIR/indexing_slicing.rs:14:6 | -13 | &x[index_from..][..index_to]; - | ^^^^^^^^^^^^^^^ +14 | &x[index_from..index_to]; + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: Consider using `.get(n..)` or .get_mut(n..)` instead + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:14:6 + --> $DIR/indexing_slicing.rs:15:6 | -14 | &x[index..]; - | ^^^^^^^^^^ +15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: Consider using `.get(n..)` or .get_mut(n..)` instead + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. --> $DIR/indexing_slicing.rs:15:6 | -15 | &x[..index]; - | ^^^^^^^^^^ +15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. + | ^^^^^^^^^^^^^^^ | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead + = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: const index is out of bounds - --> $DIR/indexing_slicing.rs:18:5 + --> $DIR/indexing_slicing.rs:16:5 | -18 | x[4]; +16 | x[4]; | ^^^^ | = note: `-D out-of-bounds-indexing` implied by `-D warnings` +error: const index is out of bounds + --> $DIR/indexing_slicing.rs:17:5 + | +17 | x[1 << 3]; + | ^^^^^^^^^ + error: range is out of bounds - --> $DIR/indexing_slicing.rs:20:6 + --> $DIR/indexing_slicing.rs:18:6 | -20 | &x[1..5]; +18 | &x[..=4]; | ^^^^^^^ -error: slicing may panic. - --> $DIR/indexing_slicing.rs:21:6 - | -21 | &x[1..][..5]; - | ^^^^^^^^^^^ +error: range is out of bounds + --> $DIR/indexing_slicing.rs:19:6 | - = help: Consider using `.get(..n)`or `.get_mut(..n)` instead +19 | &x[1..5]; + | ^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:23:6 + --> $DIR/indexing_slicing.rs:20:6 | -23 | &x[0..][..3]; - | ^^^^^^^^^^^ +20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. + | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:26:6 + --> $DIR/indexing_slicing.rs:20:6 | -26 | &x[..=4]; - | ^^^^^^^ +20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. + | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:30:6 + --> $DIR/indexing_slicing.rs:21:6 | -30 | &x[5..]; +21 | &x[5..]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:32:6 + --> $DIR/indexing_slicing.rs:22:6 | -32 | &x[..5]; +22 | &x[..5]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:33:6 + --> $DIR/indexing_slicing.rs:23:6 | -33 | &x[5..].iter().map(|x| 2 * x).collect::>(); +23 | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^^^^^^ +error: range is out of bounds + --> $DIR/indexing_slicing.rs:24:6 + | +24 | &x[0..=4]; + | ^^^^^^^^ + +error: slicing may panic. + --> $DIR/indexing_slicing.rs:25:6 + | +25 | &x[0..][..3]; + | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead + +error: slicing may panic. + --> $DIR/indexing_slicing.rs:26:6 + | +26 | &x[1..][..5]; + | ^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead + error: indexing may panic. - --> $DIR/indexing_slicing.rs:37:5 + --> $DIR/indexing_slicing.rs:39:5 | -37 | y[0]; +39 | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:38:6 + --> $DIR/indexing_slicing.rs:40:6 | -38 | &y[1..2]; +40 | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead @@ -120,86 +146,128 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:41:6 | -41 | &y[..=4]; +41 | &y[0..=4]; + | ^^^^^^^^ + | + = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead + +error: slicing may panic. + --> $DIR/indexing_slicing.rs:42:6 + | +42 | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: const index is out of bounds - --> $DIR/indexing_slicing.rs:44:5 + --> $DIR/indexing_slicing.rs:47:5 | -44 | empty[0]; +47 | empty[0]; | ^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:45:6 + --> $DIR/indexing_slicing.rs:48:6 | -45 | &empty[1..5]; +48 | &empty[1..5]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:47:6 + --> $DIR/indexing_slicing.rs:49:6 | -47 | &empty[..=4]; - | ^^^^^^^^^^^ +49 | &empty[0..=4]; + | ^^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:52:6 + --> $DIR/indexing_slicing.rs:50:6 | -52 | &empty[..=0]; +50 | &empty[..=4]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:54:6 + --> $DIR/indexing_slicing.rs:51:6 | -54 | &empty[1..]; +51 | &empty[1..]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:55:6 + --> $DIR/indexing_slicing.rs:52:6 | -55 | &empty[..4]; +52 | &empty[..4]; | ^^^^^^^^^^ +error: range is out of bounds + --> $DIR/indexing_slicing.rs:53:6 + | +53 | &empty[0..=0]; + | ^^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:54:6 + | +54 | &empty[..=0]; + | ^^^^^^^^^^^ + error: indexing may panic. - --> $DIR/indexing_slicing.rs:58:5 + --> $DIR/indexing_slicing.rs:62:5 | -58 | v[0]; +62 | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:59:5 + --> $DIR/indexing_slicing.rs:63:5 | -59 | v[10]; +63 | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead +error: indexing may panic. + --> $DIR/indexing_slicing.rs:64:5 + | +64 | v[1 << 3]; + | ^^^^^^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead + error: slicing may panic. - --> $DIR/indexing_slicing.rs:60:6 + --> $DIR/indexing_slicing.rs:65:6 | -60 | &v[10..100]; +65 | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:61:6 + --> $DIR/indexing_slicing.rs:66:6 + | +66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. + | ^^^^^^^^^^^^^^ + | + = help: Consider using `.get(..n)`or `.get_mut(..n)` instead + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:66:6 + | +66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. + | ^^^^^^^ + +error: slicing may panic. + --> $DIR/indexing_slicing.rs:67:6 | -61 | &v[10..]; +67 | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:62:6 + --> $DIR/indexing_slicing.rs:68:6 | -62 | &v[..100]; +68 | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: aborting due to 28 previous errors +error: aborting due to 38 previous errors -- cgit 1.4.1-3-g733a5 From e63f5dfedbb004afc6e9ca303b12f1c8f8cbea0d Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Fri, 15 Jun 2018 15:54:38 +0000 Subject: Add tests that index with a `const` value. In this commit tests were added to ensure that tests with a `const` index behaved as expected. In order to minimize the changes to the test's corresponding `stderr`, the tests were appended to the end of the file. --- tests/ui/indexing_slicing.rs | 11 +++++++++++ tests/ui/indexing_slicing.stderr | 24 +++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 16174afb106..301658415d6 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -68,4 +68,15 @@ fn main() { &v[..100]; &v[..]; // Ok, should not produce stderr. + + // + // Continue tests at end function to minimize the changes to this file's corresponding stderr. + // + + const N: usize = 15; // Out of bounds + const M: usize = 3; // In bounds + x[N]; + x[M]; // Ok, should not produce stderr. + v[N]; + v[M]; } diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index c9aefe0349a..2546d62bfc6 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -269,5 +269,27 @@ error: slicing may panic. | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: aborting due to 38 previous errors +error: const index is out of bounds + --> $DIR/indexing_slicing.rs:78:5 + | +78 | x[N]; + | ^^^^ + +error: indexing may panic. + --> $DIR/indexing_slicing.rs:80:5 + | +80 | v[N]; + | ^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead + +error: indexing may panic. + --> $DIR/indexing_slicing.rs:81:5 + | +81 | v[M]; + | ^^^^ + | + = help: Consider using `.get(n)` or `.get_mut(n)` instead + +error: aborting due to 41 previous errors -- cgit 1.4.1-3-g733a5 From c479b3bc2856a2c2362cd17b95e28caaaffe0908 Mon Sep 17 00:00:00 2001 From: Shea Newton Date: Tue, 19 Jun 2018 21:30:43 +0000 Subject: Removing lint for constant `usize` array indexing This commit removes the logic in this PR that linted out-of-bounds constant `usize` indexing on arrays. That case is already handled by rustc's `const_err` lint. Beyond removing the linting logic, the test file and its associated stderr were updated to verify that const `usize` indexing operations on arrays are no longer handled by this `indexing_slicing` lint. --- clippy_lints/src/indexing_slicing.rs | 24 ++++++------------------ tests/ui/indexing_slicing.rs | 8 ++++---- tests/ui/indexing_slicing.stderr | 30 +++--------------------------- 3 files changed, 13 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index b4e6414195e..7dd72a5383c 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -34,9 +34,9 @@ declare_clippy_lint! { "out of bounds constant indexing" } -/// **What it does:** Checks for usage of indexing or slicing. Does not report -/// on arrays if we can tell that the indexing or slicing operations are in -/// bounds. +/// **What it does:** Checks for usage of indexing or slicing. Arrays are special cased, this lint +/// does report on arrays if we can tell that slicing operations are in bounds and does not +/// lint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint. /// /// **Why is this bad?** Indexing and slicing can panic at runtime and there are /// safe alternatives. @@ -64,13 +64,11 @@ declare_clippy_lint! { /// let y = [0, 1, 2, 3]; /// /// // Bad -/// y[10]; /// &y[10..100]; /// &y[10..]; /// &y[..100]; /// /// // Good -/// y[2]; /// &y[2..]; /// &y[..2]; /// &y[0..3]; @@ -132,20 +130,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { ); } else { // Catchall non-range index, i.e. [n] or [n << m] - if let ty::TyArray(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + if let ty::TyArray(..) = ty.sty { // Index is a constant uint. - if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) { - if size <= const_index { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "const index is out of bounds", - ); - } - // Else index is in bounds, ok. - + if let Some(..) = constant(cx, cx.tables, index) { + // Let rustc's `const_err` lint handle constant `usize` indexing on arrays. return; } } diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 301658415d6..e39dc92367c 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -13,8 +13,8 @@ fn main() { &x[..index]; &x[index_from..index_to]; &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. - x[4]; - x[1 << 3]; + x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. &x[..=4]; &x[1..5]; &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. @@ -44,7 +44,7 @@ fn main() { &y[..]; // Ok, should not produce stderr. let empty: [i8; 0] = []; - empty[0]; + empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. &empty[1..5]; &empty[0..=4]; &empty[..=4]; @@ -75,7 +75,7 @@ fn main() { const N: usize = 15; // Out of bounds const M: usize = 3; // In bounds - x[N]; + x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. x[M]; // Ok, should not produce stderr. v[N]; v[M]; diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 2546d62bfc6..ee11dce6d1c 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -47,25 +47,13 @@ error: slicing may panic. | = help: Consider using `.get(n..)` or .get_mut(n..)` instead -error: const index is out of bounds - --> $DIR/indexing_slicing.rs:16:5 - | -16 | x[4]; - | ^^^^ - | - = note: `-D out-of-bounds-indexing` implied by `-D warnings` - -error: const index is out of bounds - --> $DIR/indexing_slicing.rs:17:5 - | -17 | x[1 << 3]; - | ^^^^^^^^^ - error: range is out of bounds --> $DIR/indexing_slicing.rs:18:6 | 18 | &x[..=4]; | ^^^^^^^ + | + = note: `-D out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds --> $DIR/indexing_slicing.rs:19:6 @@ -159,12 +147,6 @@ error: slicing may panic. | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: const index is out of bounds - --> $DIR/indexing_slicing.rs:47:5 - | -47 | empty[0]; - | ^^^^^^^^ - error: range is out of bounds --> $DIR/indexing_slicing.rs:48:6 | @@ -269,12 +251,6 @@ error: slicing may panic. | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: const index is out of bounds - --> $DIR/indexing_slicing.rs:78:5 - | -78 | x[N]; - | ^^^^ - error: indexing may panic. --> $DIR/indexing_slicing.rs:80:5 | @@ -291,5 +267,5 @@ error: indexing may panic. | = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: aborting due to 41 previous errors +error: aborting due to 37 previous errors -- cgit 1.4.1-3-g733a5 From 0b7dcdf6e723c06429408f1eef9bfc60a47b533e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 20 Jun 2018 07:12:50 +0200 Subject: No more allowed failures in integration tests They have all been working for some time now. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1e5544b2ed7..97f31b18684 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,6 @@ matrix: - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom - env: INTEGRATION=hyperium/hyper - allow_failures: - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rls -- cgit 1.4.1-3-g733a5 From fedd3ef71182e0502c74ec9fa1e3b11a66832141 Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Wed, 20 Jun 2018 11:07:41 +0200 Subject: Allows neg_cmp_op_on_partial_ord for external macros (fixes #2856). The macro always negates the result of the given comparison in its internal check which automatically triggered the lint. As its an external macro there was no chance to do anything about it which lead to a white listing of all external macros to prevent further issues. --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 6 ++++-- tests/ui/neg_cmp_op_on_partial_ord.rs | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 8e70d0eeba0..013bab69d79 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; -use crate::utils::{self, paths}; +use crate::utils::{self, paths, span_lint, in_external_macro}; /// **What it does:** /// Checks for the usage of negated comparision operators on types which only implement @@ -53,6 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { + if !in_external_macro(cx, expr.span); if let Expr_::ExprUnary(UnOp::UnNot, ref inner) = expr.node; if let Expr_::ExprBinary(ref op, ref left, _) = inner.node; if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node; @@ -78,7 +79,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { }; if implements_partial_ord && !implements_ord { - cx.span_lint( + span_lint( + cx, NEG_CMP_OP_ON_PARTIAL_ORD, expr.span, "The use of negated comparision operators on partially orded \ diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 214d627ba30..483972bb41b 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -1,6 +1,6 @@ -/// This test case utilizes `f64` an easy example for `PartialOrd` only types -/// but the lint itself actually validates any expression where the left -/// operand implements `PartialOrd` but not `Ord`. +//! This test case utilizes `f64` an easy example for `PartialOrd` only types +//! but the lint itself actually validates any expression where the left +//! operand implements `PartialOrd` but not `Ord`. use std::cmp::Ordering; @@ -54,5 +54,14 @@ fn main() { let _ = a_value <= another_value; let _ = a_value > another_value; let _ = a_value >= another_value; -} + // --- regression tests --- + + // Issue 2856: False positive on assert!() + // + // The macro always negates the result of the given comparision in its + // internal check which automatically triggered the lint. As it's an + // external macro there was no chance to do anything about it which lead + // to a whitelisting of all external macros. + assert!(a_value < another_value); +} -- cgit 1.4.1-3-g733a5 From 0f848576e9495560ee1d4a066ad37047d22624b9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 20:37:22 +0200 Subject: Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3cda0c97182..b5bd7516b2a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in clippy. Please leave your thoughts on the RFC PR. + # rust-clippy [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) -- cgit 1.4.1-3-g733a5 From 5be00bcd1835145ff71ec3539c2bf849da0e37ed Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Thu, 21 Jun 2018 05:20:14 +0100 Subject: Ensure a non-zero value is returned by clippy if compilation fails --- src/driver.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 830c8985660..419f61f860b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -13,7 +13,7 @@ extern crate rustc_plugin; extern crate syntax; use rustc_driver::{driver::CompileController, Compilation}; -use std::process::Command; +use std::process::{exit, Command}; #[allow(print_stdout)] fn show_version() { @@ -133,5 +133,10 @@ pub fn main() { } controller.compilation_done.stop = Compilation::Stop; - rustc_driver::run_compiler(&args, Box::new(controller), None, None); + if rustc_driver::run_compiler(&args, Box::new(controller), None, None) + .0 + .is_err() + { + exit(101); + } } -- cgit 1.4.1-3-g733a5 From 50027405c3647d922b79d50ce68c241b0e9fbdbc Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 30 Mar 2018 00:12:19 +0200 Subject: Link to correct AppVeyor project in Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b5bd7516b2a..588e4b74d23 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in # rust-clippy [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) -[![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy) +[![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) [![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) -- cgit 1.4.1-3-g733a5 From 6224e19b80dbf5d8060d80161b128105bbf02ed1 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 21 Jun 2018 14:43:13 +0200 Subject: Check for arguments before accessing the first arg --- clippy_lints/src/map_clone.rs | 3 ++- tests/run-pass/issue-2862.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/run-pass/issue-2862.rs diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 23c5434a750..2befba5767d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -36,7 +36,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ExprClosure(_, ref decl, closure_eid, _, _) => { let body = cx.tcx.hir.body(closure_eid); let closure_expr = remove_blocks(&body.value); - let ty = cx.tables.pat_ty(&body.arguments[0].pat); if_chain! { // nothing special in the argument, besides reference bindings // (e.g. .map(|&x| x) ) @@ -45,6 +44,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // the method is being called on a known type (option or iterator) if let Some(type_name) = get_type_name(cx, expr, &args[0]); then { + // We know that body.arguments is not empty at this point + let ty = cx.tables.pat_ty(&body.arguments[0].pat); // look for derefs, for .map(|x| *x) if only_derefs(cx, &*closure_expr, arg_ident) && // .cloned() only removes one level of indirection, don't lint on more diff --git a/tests/run-pass/issue-2862.rs b/tests/run-pass/issue-2862.rs new file mode 100644 index 00000000000..b35df667f27 --- /dev/null +++ b/tests/run-pass/issue-2862.rs @@ -0,0 +1,14 @@ +pub trait FooMap { + fn map B>(&self, f: F) -> B; +} + +impl FooMap for bool { + fn map B>(&self, f: F) -> B { + f() + } +} + +fn main() { + let a = true; + a.map(|| false); +} -- cgit 1.4.1-3-g733a5 From 88b7603b167dd7cbd03522e37ad9f7dec18cae23 Mon Sep 17 00:00:00 2001 From: kennytm Date: Wed, 6 Jun 2018 23:20:22 +0800 Subject: Lint against const items which are interior mutable. Fix #1560. --- clippy_lints/src/lib.rs | 6 + clippy_lints/src/non_copy_const.rs | 268 ++++++++++++++++++++++++++++++++++++ tests/ui/non_copy_const.rs | 147 ++++++++++++++++++++ tests/ui/non_copy_const.stderr | 275 +++++++++++++++++++++++++++++++++++++ 4 files changed, 696 insertions(+) create mode 100644 clippy_lints/src/non_copy_const.rs create mode 100644 tests/ui/non_copy_const.rs create mode 100644 tests/ui/non_copy_const.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 621b21429a9..99692de03aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -175,6 +175,7 @@ pub mod neg_cmp_op_on_partial_ord; pub mod neg_multiply; pub mod new_without_default; pub mod no_effect; +pub mod non_copy_const; pub mod non_expressive_names; pub mod ok_if_let; pub mod open_options; @@ -432,6 +433,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box duration_subsec::DurationSubsec); reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing); + reg.register_late_lint_pass(box non_copy_const::NonCopyConst); reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -640,6 +642,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, no_effect::NO_EFFECT, no_effect::UNNECESSARY_OPERATION, + non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, + non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, @@ -895,6 +899,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { misc::CMP_NAN, misc::FLOAT_CMP, misc::MODULO_ONE, + non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, + non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, open_options::NONSENSICAL_OPEN_OPTIONS, ptr::MUT_FROM_REF, ranges::ITERATOR_STEP_BY_ZERO, diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs new file mode 100644 index 00000000000..5fcf54bc015 --- /dev/null +++ b/clippy_lints/src/non_copy_const.rs @@ -0,0 +1,268 @@ +//! Checks for uses of const which the type is not Freeze (Cell-free). +//! +//! This lint is **deny** by default. + +use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; +use rustc::hir::*; +use rustc::hir::def::Def; +use rustc::ty::{self, TyRef, TypeFlags}; +use rustc::ty::adjustment::Adjust; +use rustc_errors::Applicability; +use rustc_typeck::hir_ty_to_ty; +use syntax_pos::{DUMMY_SP, Span}; +use std::ptr; +use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then}; + +/// **What it does:** Checks for declaration of `const` items which is interior +/// mutable (e.g. contains a `Cell`, `Mutex`, `AtomicXxxx` etc). +/// +/// **Why is this bad?** Consts are copied everywhere they are referenced, i.e. +/// every time you refer to the const a fresh instance of the `Cell` or `Mutex` +/// or `AtomicXxxx` will be created, which defeats the whole purpose of using +/// these types in the first place. +/// +/// The `const` should better be replaced by a `static` item if a global +/// variable is wanted, or replaced by a `const fn` if a constructor is wanted. +/// +/// **Known problems:** A "non-constant" const item is a legacy way to supply an +/// initialized value to downstream `static` items (e.g. the +/// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit, +/// and this lint should be suppressed. +/// +/// **Example:** +/// ```rust +/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize}; +/// +/// // Bad. +/// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); +/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged +/// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct +/// +/// // Good. +/// static STATIC_ATOM: AtomicUsize = AtomicUsize::new(15); +/// STATIC_ATOM.store(9, SeqCst); +/// assert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance +/// ``` +declare_clippy_lint! { + pub DECLARE_INTERIOR_MUTABLE_CONST, + correctness, + "declaring const with interior mutability" +} + +/// **What it does:** Checks if `const` items which is interior mutable (e.g. +/// contains a `Cell`, `Mutex`, `AtomicXxxx` etc) has been borrowed directly. +/// +/// **Why is this bad?** Consts are copied everywhere they are referenced, i.e. +/// every time you refer to the const a fresh instance of the `Cell` or `Mutex` +/// or `AtomicXxxx` will be created, which defeats the whole purpose of using +/// these types in the first place. +/// +/// The `const` value should be stored inside a `static` item. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize}; +/// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); +/// +/// // Bad. +/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged +/// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct +/// +/// // Good. +/// static STATIC_ATOM: AtomicUsize = CONST_ATOM; +/// STATIC_ATOM.store(9, SeqCst); +/// assert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance +/// ``` +declare_clippy_lint! { + pub BORROW_INTERIOR_MUTABLE_CONST, + correctness, + "referencing const with interior mutability" +} + +#[derive(Copy, Clone)] +enum Source { + Item { + item: Span, + }, + Assoc { + item: Span, + ty: Span, + }, + Expr { + expr: Span, + }, +} + +impl Source { + fn lint(&self) -> (&'static Lint, &'static str, Span) { + match self { + Source::Item { item } | Source::Assoc { item, .. } => ( + DECLARE_INTERIOR_MUTABLE_CONST, + "a const item should never be interior mutable", + *item, + ), + Source::Expr { expr } => ( + BORROW_INTERIOR_MUTABLE_CONST, + "a const item with interior mutability should not be borrowed", + *expr, + ), + } + } +} + +fn verify_ty_bound<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + ty: ty::Ty<'tcx>, + source: Source, +) { + if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) { + // an UnsafeCell is !Copy, and an UnsafeCell is also the only type which + // is !Freeze, thus if our type is Copy we can be sure it must be Freeze + // as well. + return; + } + + let (lint, msg, span) = source.lint(); + span_lint_and_then(cx, lint, span, msg, |db| { + if in_macro(span) { + return; // Don't give suggestions into macros. + } + match source { + Source::Item { .. } => { + let const_kw_span = span.from_inner_byte_pos(0, 5); + db.span_suggestion_with_applicability( + const_kw_span, + "make this a static item", + "static".to_string(), + Applicability::MachineApplicable, + ); + } + Source::Assoc { ty: ty_span, .. } => { + if ty.flags.contains(TypeFlags::HAS_FREE_LOCAL_NAMES) { + db.span_help(ty_span, &format!("consider requiring `{}` to be `Copy`", ty)); + } + } + Source::Expr { .. } => { + db.help( + "assign this const to a local or static variable, and use the variable here", + ); + } + } + }); +} + + +pub struct NonCopyConst; + +impl LintPass for NonCopyConst { + fn get_lints(&self) -> LintArray { + lint_array!(DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item) { + if let ItemConst(hir_ty, ..) = &it.node { + let ty = hir_ty_to_ty(cx.tcx, hir_ty); + verify_ty_bound(cx, ty, Source::Item { item: it.span }); + } + } + + fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx TraitItem) { + if let TraitItemKind::Const(hir_ty, ..) = &trait_item.node { + let ty = hir_ty_to_ty(cx.tcx, hir_ty); + verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: trait_item.span }); + } + } + + fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem) { + if let ImplItemKind::Const(hir_ty, ..) = &impl_item.node { + let item_node_id = cx.tcx.hir.get_parent_node(impl_item.id); + let item = cx.tcx.hir.expect_item(item_node_id); + // ensure the impl is an inherent impl. + if let ItemImpl(_, _, _, _, None, _, _) = item.node { + let ty = hir_ty_to_ty(cx.tcx, hir_ty); + verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: impl_item.span }); + } + } + } + + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprPath(qpath) = &expr.node { + // Only lint if we use the const item inside a function. + if in_constant(cx, expr.id) { + return; + } + + // make sure it is a const item. + match cx.tables.qpath_def(qpath, expr.hir_id) { + Def::Const(_) | Def::AssociatedConst(_) => {}, + _ => return, + }; + + // climb up to resolve any field access and explicit referencing. + let mut cur_expr = expr; + let mut dereferenced_expr = expr; + let mut needs_check_adjustment = true; + loop { + let parent_id = cx.tcx.hir.get_parent_node(cur_expr.id); + if parent_id == cur_expr.id { + break; + } + if let Some(map::NodeExpr(parent_expr)) = cx.tcx.hir.find(parent_id) { + match &parent_expr.node { + ExprAddrOf(..) => { + // `&e` => `e` must be referenced + needs_check_adjustment = false; + } + ExprField(..) => { + dereferenced_expr = parent_expr; + needs_check_adjustment = true; + } + ExprIndex(e, _) if ptr::eq(&**e, cur_expr) => { + // `e[i]` => desugared to `*Index::index(&e, i)`, + // meaning `e` must be referenced. + // no need to go further up since a method call is involved now. + needs_check_adjustment = false; + break; + } + ExprUnary(UnDeref, _) => { + // `*e` => desugared to `*Deref::deref(&e)`, + // meaning `e` must be referenced. + // no need to go further up since a method call is involved now. + needs_check_adjustment = false; + break; + } + _ => break, + } + cur_expr = parent_expr; + } else { + break; + } + } + + let ty = if !needs_check_adjustment { + cx.tables.expr_ty(dereferenced_expr) + } else { + let adjustments = cx.tables.expr_adjustments(dereferenced_expr); + if let Some(i) = adjustments.iter().position(|adj| match adj.kind { + Adjust::Borrow(_) | Adjust::Deref(_) => true, + _ => false, + }) { + if i == 0 { + cx.tables.expr_ty(dereferenced_expr) + } else { + adjustments[i - 1].target + } + } else { + // No borrow adjustments = the entire const is moved. + return; + } + }; + + verify_ty_bound(cx, ty, Source::Expr { expr: expr.span }); + } + } +} diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs new file mode 100644 index 00000000000..d7391577d23 --- /dev/null +++ b/tests/ui/non_copy_const.rs @@ -0,0 +1,147 @@ +#![feature(const_string_new, const_vec_new)] +#![allow(ref_in_deref, dead_code)] + +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; +use std::cell::Cell; +use std::sync::Once; +use std::borrow::Cow; +use std::fmt::Display; + +const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +//~^ ERROR interior mutable + +macro_rules! declare_const { + ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; +} +declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable + +// const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492. + +const INTEGER: u8 = 8; +const STRING: String = String::new(); +const STR: &str = "012345"; +const COW: Cow = Cow::Borrowed("abcdef"); +//^ note: a const item of Cow is used in the `postgres` package. + +const NO_ANN: &Display = &70; + +static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING); +//^ there should be no lints on this line + +#[allow(declare_interior_mutable_const)] +const ONCE_INIT: Once = Once::new(); + +trait Trait: Copy { + type NonCopyType; + + const ATOMIC: AtomicUsize; //~ ERROR interior mutable + const INTEGER: u64; + const STRING: String; + const SELF: Self; // (no error) + const INPUT: T; + //~^ ERROR interior mutable + //~| HELP consider requiring `T` to be `Copy` + const ASSOC: Self::NonCopyType; + //~^ ERROR interior mutable + //~| HELP consider requiring `>::NonCopyType` to be `Copy` + + const AN_INPUT: T = Self::INPUT; + //~^ ERROR interior mutable + //~| ERROR consider requiring `T` to be `Copy` + declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable +} + +trait Trait2 { + type CopyType: Copy; + + const SELF_2: Self; + //~^ ERROR interior mutable + //~| HELP consider requiring `Self` to be `Copy` + const ASSOC_2: Self::CopyType; // (no error) +} + +// we don't lint impl of traits, because an impl has no power to change the interface. +impl Trait for u64 { + type NonCopyType = u16; + + const ATOMIC: AtomicUsize = AtomicUsize::new(9); + const INTEGER: u64 = 10; + const STRING: String = String::new(); + const SELF: Self = 11; + const INPUT: u32 = 12; + const ASSOC: Self::NonCopyType = 13; +} + +struct Local(T, U); + +impl, U: Trait2> Local { + const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable + const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy"); + const T_SELF: T = T::SELF_2; + const U_SELF: U = U::SELF_2; + //~^ ERROR interior mutable + //~| HELP consider requiring `U` to be `Copy` + const T_ASSOC: T::NonCopyType = T::ASSOC; + //~^ ERROR interior mutable + //~| HELP consider requiring `>::NonCopyType` to be `Copy` + const U_ASSOC: U::CopyType = U::ASSOC_2; +} + +fn main() { + ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability + assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + + ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability + assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability + + let _once = ONCE_INIT; + let _once_ref = &ONCE_INIT; //~ ERROR interior mutability + let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability + let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability + let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability + let _atomic_into_inner = ATOMIC.into_inner(); + // these should be all fine. + let _twice = (ONCE_INIT, ONCE_INIT); + let _ref_twice = &(ONCE_INIT, ONCE_INIT); + let _ref_once = &(ONCE_INIT, ONCE_INIT).0; + let _array_twice = [ONCE_INIT, ONCE_INIT]; + let _ref_array_twice = &[ONCE_INIT, ONCE_INIT]; + let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0]; + + // referencing projection is still bad. + let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability + let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability + let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability + let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability + let _ = &*ATOMIC_TUPLE.1; //~ ERROR interior mutability + let _ = &ATOMIC_TUPLE.2; + let _ = (&&&&ATOMIC_TUPLE).0; + let _ = (&&&&ATOMIC_TUPLE).2; + let _ = ATOMIC_TUPLE.0; + let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + let _ = ATOMIC_TUPLE.1.into_iter(); + let _ = ATOMIC_TUPLE.2; + let _ = &{ATOMIC_TUPLE}; + + CELL.set(2); //~ ERROR interior mutability + assert_eq!(CELL.get(), 6); //~ ERROR interior mutability + + assert_eq!(INTEGER, 8); + assert!(STRING.is_empty()); + + let a = ATOMIC; + a.store(4, Ordering::SeqCst); + assert_eq!(a.load(Ordering::SeqCst), 4); + + STATIC_TUPLE.0.store(3, Ordering::SeqCst); + assert_eq!(STATIC_TUPLE.0.load(Ordering::SeqCst), 3); + assert!(STATIC_TUPLE.1.is_empty()); + + u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability + assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability + + assert_eq!(NO_ANN.to_string(), "70"); // should never lint this. +} diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr new file mode 100644 index 00000000000..388c7fabab0 --- /dev/null +++ b/tests/ui/non_copy_const.stderr @@ -0,0 +1,275 @@ +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:10:1 + | +10 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: make this a static item: `static` + | + = note: #[deny(declare_interior_mutable_const)] on by default + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:11:1 + | +11 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: make this a static item: `static` + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:12:1 + | +12 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: make this a static item: `static` + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:16:42 + | +16 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; + | ^^^^^^^^^^^^^^^^^^^^^^ +17 | } +18 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable + | ------------------------------------------ in this macro invocation + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:39:5 + | +39 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:43:5 + | +43 | const INPUT: T; + | ^^^^^^^^^^^^^^^ + | +help: consider requiring `T` to be `Copy` + --> $DIR/non_copy_const.rs:43:18 + | +43 | const INPUT: T; + | ^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:46:5 + | +46 | const ASSOC: Self::NonCopyType; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider requiring `>::NonCopyType` to be `Copy` + --> $DIR/non_copy_const.rs:46:18 + | +46 | const ASSOC: Self::NonCopyType; + | ^^^^^^^^^^^^^^^^^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:50:5 + | +50 | const AN_INPUT: T = Self::INPUT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider requiring `T` to be `Copy` + --> $DIR/non_copy_const.rs:50:21 + | +50 | const AN_INPUT: T = Self::INPUT; + | ^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:16:42 + | +16 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; + | ^^^^^^^^^^^^^^^^^^^^^^ +... +53 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable + | ----------------------------------------------- in this macro invocation + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:59:5 + | +59 | const SELF_2: Self; + | ^^^^^^^^^^^^^^^^^^^ + | +help: consider requiring `Self` to be `Copy` + --> $DIR/non_copy_const.rs:59:19 + | +59 | const SELF_2: Self; + | ^^^^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:80:5 + | +80 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:83:5 + | +83 | const U_SELF: U = U::SELF_2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider requiring `U` to be `Copy` + --> $DIR/non_copy_const.rs:83:19 + | +83 | const U_SELF: U = U::SELF_2; + | ^ + +error: a const item should never be interior mutable + --> $DIR/non_copy_const.rs:86:5 + | +86 | const T_ASSOC: T::NonCopyType = T::ASSOC; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider requiring `>::NonCopyType` to be `Copy` + --> $DIR/non_copy_const.rs:86:20 + | +86 | const T_ASSOC: T::NonCopyType = T::ASSOC; + | ^^^^^^^^^^^^^^ + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:93:5 + | +93 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^ + | + = note: #[deny(borrow_interior_mutable_const)] on by default + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:94:16 + | +94 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + | ^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:96:5 + | +96 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:97:16 + | +97 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:100:22 + | +100 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:101:25 + | +101 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:102:27 + | +102 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:103:26 + | +103 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:114:14 + | +114 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:115:14 + | +115 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:116:19 + | +116 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:117:14 + | +117 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:118:13 + | +118 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:124:13 + | +124 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:129:5 + | +129 | CELL.set(2); //~ ERROR interior mutability + | ^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:130:16 + | +130 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability + | ^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:143:5 + | +143 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a const item with interior mutability should not be borrowed + --> $DIR/non_copy_const.rs:144:16 + | +144 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability + | ^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: aborting due to 31 previous errors + -- cgit 1.4.1-3-g733a5 From d9a80d2f84458dda53d31f627b27aa9b9b2bc39b Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sun, 24 Jun 2018 15:32:40 +0200 Subject: Resolve field, struct and function renaming Addresses the errors produced by (re)moving, merging or renaming structs, fields and methods by rust-lang/rust#48149 and rust-lang/rust#51580 --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/functions.rs | 12 +++--- clippy_lints/src/lifetimes.rs | 57 ++++++++++++++------------ clippy_lints/src/loops.rs | 2 +- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/methods.rs | 47 +++++++++++---------- clippy_lints/src/misc_early.rs | 10 ++--- clippy_lints/src/needless_pass_by_value.rs | 6 +-- clippy_lints/src/new_without_default.rs | 7 +++- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/ptr.rs | 6 +-- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 4 +- clippy_lints/src/types.rs | 17 ++++---- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 10 ++--- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 2 +- 22 files changed, 106 insertions(+), 94 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 46ec02a3473..c861e4ee4e2 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -207,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { - if let ItemFn(_, _, _, _, _, eid) = item.node { + if let ItemFn(_, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) } else { true diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index e58dbdd2289..d773289263e 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr) { match e.node { - ExprAgain(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e), + ExprContinue(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e), ExprCall(ref func, _) => { let typ = self.cx.tables.expr_ty(func); match typ.sty { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 904d0b1d245..554c983d7c5 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -92,8 +92,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { }; let unsafety = match kind { - hir::intravisit::FnKind::ItemFn(_, _, unsafety, _, _, _, _) => unsafety, - hir::intravisit::FnKind::Method(_, sig, _, _) => sig.unsafety, + hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety, + hir::intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety, hir::intravisit::FnKind::Closure(_) => return, }; @@ -101,8 +101,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { if !is_impl { // don't lint extern functions decls, it's not their fault either match kind { - hir::intravisit::FnKind::Method(_, &hir::MethodSig { abi: Abi::Rust, .. }, _, _) | - hir::intravisit::FnKind::ItemFn(_, _, _, _, Abi::Rust, _, _) => self.check_arg_number(cx, decl, span), + hir::intravisit::FnKind::Method(_, &hir::MethodSig { header: hir::FnHeader { abi: Abi::Rust, .. }, .. }, _, _) | + hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => self.check_arg_number(cx, decl, span), _ => {}, } } @@ -113,13 +113,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { if let hir::TraitItemKind::Method(ref sig, ref eid) = item.node { // don't lint extern functions decls, it's not their fault - if sig.abi == Abi::Rust { + if sig.header.abi == Abi::Rust { self.check_arg_number(cx, &sig.decl, item.span); } if let hir::TraitMethod::Provided(eid) = *eid { let body = cx.tcx.hir.body(eid); - self.check_raw_ptr(cx, sig.unsafety, &sig.decl, body, item.id); + self.check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.id); } } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index f84d942e1c9..b0fd62089ba 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -59,7 +59,7 @@ impl LintPass for LifetimePass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemFn(ref decl, _, _, _, ref generics, id) = item.node { + if let ItemFn(ref decl, _, ref generics, id) = item.node { check_fn_inner(cx, decl, Some(id), generics, item.span); } } @@ -101,32 +101,35 @@ fn check_fn_inner<'a, 'tcx>( } let mut bounds_lts = Vec::new(); - for typ in generics.ty_params() { - for bound in &typ.bounds { - let mut visitor = RefVisitor::new(cx); - walk_ty_param_bound(&mut visitor, bound); - if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { - return; - } - if let TraitTyParamBound(ref trait_ref, _) = *bound { - let params = &trait_ref - .trait_ref - .path - .segments - .last() - .expect("a path must have at least one segment") - .parameters; - if let Some(ref params) = *params { - for bound in ¶ms.lifetimes { - if bound.name.name() != "'static" && !bound.is_elided() { - return; + generics.params.iter().for_each(|param| match param.kind { + GenericParamKind::Lifetime { .. } => {}, + GenericParamKind::Type { .. } => { + for bound in ¶m.bounds { + let mut visitor = RefVisitor::new(cx); + walk_param_bound(&mut visitor, bound); + if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { + return; + } + if let GenericBound::Trait(ref trait_ref, _) = *bound { + let params = &trait_ref + .trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .args; + if let Some(ref params) = *params { + for bound in ¶ms.lifetimes { + if bound.name.name() != "'static" && !bound.is_elided() { + return; + } + bounds_lts.push(bound); } - bounds_lts.push(bound); } } } - } - } + }, + }); if could_use_elision(cx, decl, body, &generics.params, bounds_lts) { span_lint( cx, @@ -295,7 +298,7 @@ impl<'v, 't> RefVisitor<'v, 't> { } fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { - if let Some(ref last_path_segment) = last_path_segment(qpath).parameters { + if let Some(ref last_path_segment) = last_path_segment(qpath).args { if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { @@ -335,7 +338,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyImplTraitExistential(exist_ty_id, _, _) => { if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node { for bound in &exist_ty.bounds { - if let RegionTyParamBound(_) = *bound { + if let GenericBound::Outlives(_) = *bound { self.record(&None); } } @@ -377,7 +380,7 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & let allowed_lts = allowed_lts_from(&pred.bound_generic_params); // now walk the bounds for bound in pred.bounds.iter() { - walk_ty_param_bound(&mut visitor, bound); + walk_param_bound(&mut visitor, bound); } // and check that all lifetimes are allowed match visitor.into_vec() { @@ -418,7 +421,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { // don't want to spuriously remove them // `'b` in `'a: 'b` is useless unless used elsewhere in // a non-lifetime bound - if param.is_type_param() { + if let GenericParamKind::Type { .. } = param.kind { walk_generic_param(self, param) } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cfea6053fac..8808de9025d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -640,7 +640,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { } }, ExprBlock(ref b, _) => never_loop_block(b, main_loop_id), - ExprAgain(d) => { + ExprContinue(d) => { let id = d.target_id .expect("target id can only be missing in the presence of compilation errors"); if id == main_loop_id { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 2befba5767d..97c2522d2ce 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -104,7 +104,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { let arg_segment = [ PathSegment { name: id, - parameters: None, + args: None, infer_types: true, }, ]; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 6d93e5bbd09..2fe56bcdce1 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -7,7 +7,7 @@ use std::fmt; use std::iter; use syntax::ast; use syntax::codemap::{Span, BytePos}; -use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self, +use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; @@ -336,7 +336,7 @@ declare_clippy_lint! { /// /// **Known problems:** If the function has side-effects, not calling it will /// change the semantic of the program, but you shouldn't rely on that anyway. -/// +/// /// **Example:** /// ```rust /// foo.expect(&format("Err {}: {}", err_code, err_msg)) @@ -1020,7 +1020,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } } }; - + snippet(cx, a.span, "..").into_owned() } @@ -1077,7 +1077,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } let sugg: Cow<_> = snippet(cx, arg.span, ".."); - + span_lint_and_sugg( cx, EXPECT_FUN_CALL, @@ -2091,26 +2091,29 @@ impl SelfKind { fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { single_segment_ty(ty).map_or(false, |seg| { - generics.ty_params().any(|param| { - param.name == seg.name && param.bounds.iter().any(|bound| { - if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { - let path = &ptr.trait_ref.path; - match_path(path, name) && path.segments.last().map_or(false, |s| { - if let Some(ref params) = s.parameters { - if params.parenthesized { - false + generics.params.iter().any(|param| match param.kind { + hir::GenericParamKind::Type { .. } => { + param.name.name() == seg.name && param.bounds.iter().any(|bound| { + if let hir::GenericBound::Trait(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path(path, name) && path.segments.last().map_or(false, |s| { + if let Some(ref params) = s.args { + if params.parenthesized { + false + } else { + params.types.len() == 1 + && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) + } } else { - params.types.len() == 1 - && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) + false } - } else { - false - } - }) - } else { - false - } - }) + }) + } else { + false + } + }) + }, + _ => false, }) }) } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index fcd88f9f219..94247e64b10 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -189,13 +189,13 @@ impl LintPass for MiscEarly { impl EarlyLintPass for MiscEarly { fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) { for param in &gen.params { - if let GenericParam::Type(ref ty) = *param { - let name = ty.ident.name.as_str(); + if let GenericParamKind::Type { .. } = param.kind { + let name = param.ident.name.as_str(); if constants::BUILTIN_TYPES.contains(&&*name) { span_lint( cx, BUILTIN_TYPE_SHADOW, - ty.ident.span, + param.ident.span, &format!("This generic shadows the built-in type `{}`", name), ); } @@ -296,7 +296,7 @@ impl EarlyLintPass for MiscEarly { } match expr.node { ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, _, ref decl, ref block, _) = closure.node { + if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node { span_lint_and_then( cx, REDUNDANT_CLOSURE_CALL, @@ -327,7 +327,7 @@ impl EarlyLintPass for MiscEarly { if_chain! { if let StmtKind::Local(ref local) = w[0].node; if let Option::Some(ref t) = local.init; - if let ExprKind::Closure(_, _, _, _, _) = t.node; + if let ExprKind::Closure(..) = t.node; if let PatKind::Ident(_, ident, _) = local.pat.node; if let StmtKind::Semi(ref second) = w[1].node; if let ExprKind::Assign(_, ref call) = second.node; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 36f5eaa8e18..7a250f93db5 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -72,8 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } match kind { - FnKind::ItemFn(.., abi, _, attrs) => { - if abi != Abi::Rust { + FnKind::ItemFn(.., header, _, attrs) => { + if header.abi != Abi::Rust { return; } for a in attrs { @@ -218,7 +218,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if let TyPath(QPath::Resolved(_, ref path)) = input.node; if let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") - .and_then(|ps| ps.parameters.as_ref()) + .and_then(|ps| ps.args.as_ref()) .map(|params| ¶ms.types[0]); then { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 8df4577650f..adc91bacdef 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -99,11 +99,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { let name = impl_item.name; let id = impl_item.id; - if sig.constness == hir::Constness::Const { + if sig.header.constness == hir::Constness::Const { // can't be implemented by default return; } - if impl_item.generics.params.iter().any(|gen| gen.is_type_param()) { + if impl_item.generics.params.iter().any(|gen| match gen.kind { + hir::GenericParamKind::Type { .. } => true, + _ => false + }) { // when the result of `new()` depends on a type parameter we should not require // an // impl of `Default` diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 69a02b0c50d..b49e3f87ec9 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node { + if let ItemKind::Fn(ref decl, _, _, ref blk) = item.node { do_check(self, cx, &item.attrs, decl, blk); } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2d5330f7b6b..fcd56c28218 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -103,7 +103,7 @@ impl LintPass for PointerPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemFn(ref decl, _, _, _, _, body_id) = item.node { + if let ItemFn(ref decl, _, _, body_id) = item.node { check_fn(cx, decl, item.id, Some(body_id)); } } @@ -160,7 +160,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< let mut ty_snippet = None; if_chain! { if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node; - if let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last(); + if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last(); if parameters.types.len() == 1; then { ty_snippet = snippet_opt(cx, parameters.types[0].span); @@ -218,7 +218,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if let TyPath(ref path) = ty.node; if let QPath::Resolved(None, ref pp) = *path; if let [ref bx] = *pp.segments; - if let Some(ref params) = bx.parameters; + if let Some(ref params) = bx.args; if !params.parenthesized; if let [ref inner] = *params.types; then { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index ace42c2fecd..2b27ed22c47 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -455,7 +455,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String { let seg = last_path_segment(path); if_chain! { - if let Some(ref params) = seg.parameters; + if let Some(ref params) = seg.args; if !params.parenthesized; if let Some(to_ty) = params.types.get(1); if let TyRptr(_, ref to_ty) = to_ty.node; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 4c8d0c9dab8..8d0ddbec988 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -84,8 +84,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } match kind { - FnKind::ItemFn(.., abi, _, attrs) => { - if abi != Abi::Rust { + FnKind::ItemFn(.., header, _, attrs) => { + if header.abi != Abi::Rust { return; } for a in attrs { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 0888aef89fe..70625724040 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -180,7 +180,7 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool { let last = last_path_segment(qpath); if_chain! { - if let Some(ref params) = last.parameters; + if let Some(ref params) = last.args; if !params.parenthesized; if let Some(ty) = params.types.get(0); if let TyPath(ref qpath) = ty.node; @@ -244,7 +244,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); for ty in p.segments.iter().flat_map(|seg| { - seg.parameters + seg.args .as_ref() .map_or_else(|| [].iter(), |params| params.types.iter()) }) { @@ -252,7 +252,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } }, QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| { - seg.parameters + seg.args .as_ref() .map_or_else(|| [].iter(), |params| params.types.iter()) }) { @@ -260,7 +260,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); - if let Some(ref params) = seg.parameters { + if let Some(ref params) = seg.args { for ty in params.types.iter() { check_ty(cx, ty, is_local); } @@ -288,7 +288,7 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti if Some(def_id) == cx.tcx.lang_items().owned_box(); if let QPath::Resolved(None, ref path) = *qpath; if let [ref bx] = *path.segments; - if let Some(ref params) = bx.parameters; + if let Some(ref params) = bx.args; if !params.parenthesized; if let [ref inner] = *params.types; then { @@ -1208,7 +1208,10 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyTraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds .iter() - .any(|bound| bound.bound_generic_params.iter().any(|gen| gen.is_lifetime_param())); + .any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind { + GenericParamKind::Lifetime { .. } => true, + _ => false, + })); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) @@ -1859,7 +1862,7 @@ impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node { - let params = &path.segments.last().as_ref()?.parameters.as_ref()?.types; + let params = &path.segments.last().as_ref()?.args.as_ref()?.types; let params_len = params.len(); let ty = hir_ty_to_ty(cx.tcx, hir_ty); diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index c7a33ab33b2..ca300032675 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.label { + hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label { self.labels.remove(&label.name.as_str()); }, hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 581a8d47677..035471e4520 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if let ItemImpl(.., ref item_type, ref refs) = item.node; if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node; then { - let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters; + let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; let should_check = if let Some(ref params) = *parameters { !params.parenthesized && params.lifetimes.len() == 0 } else { diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e10fa60a38b..df6a06bc478 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -432,7 +432,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } // FIXME: implement label printing }, - Expr_::ExprAgain(ref _destination) => { + Expr_::ExprContinue(ref _destination) => { let destination_pat = self.next("destination"); println!("Again(ref {}) = {};", destination_pat, current); // FIXME: implement label printing diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index ddac8bd3835..1cfb5a82f72 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), - (&ExprAgain(li), &ExprAgain(ri)) => { + (&ExprContinue(li), &ExprContinue(ri)) => { both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str()) }, (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), @@ -201,7 +201,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) } - fn eq_path_parameters(&mut self, left: &PathParameters, right: &PathParameters) -> bool { + fn eq_path_parameters(&mut self, left: &GenericArgs, right: &GenericArgs) -> bool { if !(left.parenthesized || right.parenthesized) { over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) && over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) @@ -224,7 +224,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { if left.name.as_str() != right.name.as_str() { return false; } - match (&left.parameters, &right.parameters) { + match (&left.args, &right.args) { (&None, &None) => true, (&Some(ref l), &Some(ref r)) => self.eq_path_parameters(l, r), _ => false, @@ -345,8 +345,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { m.hash(&mut self.s); self.hash_expr(e); }, - ExprAgain(i) => { - let c: fn(_) -> _ = ExprAgain; + ExprContinue(i) => { + let c: fn(_) -> _ = ExprContinue; c.hash(&mut self.s); if let Some(i) = i.label { self.hash_name(i.name); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 46b65cf39b6..9d92147048c 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -300,7 +300,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprAgain(_) => println!("{}Again", ind), + hir::ExprContinue(_) => println!("{}Again", ind), hir::ExprRet(ref e) => { println!("{}Ret", ind); if let Some(ref e) = *e { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 612fdfafe3b..3adc65a2543 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -524,7 +524,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI match node { Node::NodeBlock(block) => Some(block), Node::NodeItem(&Item { - node: ItemFn(_, _, _, _, _, eid), + node: ItemFn(_, _, _, eid), .. }) | Node::NodeImplItem(&ImplItem { node: ImplItemKind::Method(_, eid), diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 6add947cf9e..9482cc6bc0e 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -52,7 +52,7 @@ impl<'a> Sugg<'a> { hir::ExprIf(..) | hir::ExprUnary(..) | hir::ExprMatch(..) => Sugg::MaybeParen(snippet), - hir::ExprAgain(..) | + hir::ExprContinue(..) | hir::ExprYield(..) | hir::ExprArray(..) | hir::ExprBlock(..) | -- cgit 1.4.1-3-g733a5 From c83fd39e0e4a8e9262fc31823303df7bcb522720 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sun, 24 Jun 2018 23:42:52 +0200 Subject: Resolve conflicts produced by GenericArgs Addresses the move/zip of Lifetimes and Types vectors from hir::PathParameters into the args vector of GenericArgs --- clippy_lints/src/lifetimes.rs | 35 +++++++++++++++++++----------- clippy_lints/src/methods.rs | 10 +++++++-- clippy_lints/src/needless_pass_by_value.rs | 5 ++++- clippy_lints/src/ptr.rs | 12 +++++++--- clippy_lints/src/transmute.rs | 5 ++++- clippy_lints/src/types.rs | 31 +++++++++++++++++++++----- clippy_lints/src/use_self.rs | 5 ++++- clippy_lints/src/utils/hir_utils.rs | 11 ++++++++-- clippy_lints/src/utils/sugg.rs | 1 + 9 files changed, 86 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index b0fd62089ba..7e22fda4006 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -119,12 +119,15 @@ fn check_fn_inner<'a, 'tcx>( .expect("a path must have at least one segment") .args; if let Some(ref params) = *params { - for bound in ¶ms.lifetimes { - if bound.name.name() != "'static" && !bound.is_elided() { - return; - } - bounds_lts.push(bound); - } + params.args.iter().for_each(|param| match param { + GenericArg::Lifetime(bound) => { + if bound.name.name() != "'static" && !bound.is_elided() { + return; + } + bounds_lts.push(bound); + }, + _ => {}, + }); } } } @@ -233,9 +236,9 @@ fn could_use_elision<'a, 'tcx: 'a>( fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { let mut allowed_lts = HashSet::new(); for par in named_generics.iter() { - if let GenericParam::Lifetime(ref lt) = *par { - if lt.bounds.is_empty() { - allowed_lts.insert(RefLt::Named(lt.lifetime.name.name())); + if let GenericParamKind::Lifetime { .. } = par.kind { + if par.bounds.is_empty() { + allowed_lts.insert(RefLt::Named(par.name.name())); } } } @@ -299,7 +302,11 @@ impl<'v, 't> RefVisitor<'v, 't> { fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { if let Some(ref last_path_segment) = last_path_segment(qpath).args { - if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { + if !last_path_segment.parenthesized + && !last_path_segment.args.iter().any(|arg| match arg { + GenericArg::Lifetime(_) => true, + GenericArg::Type(_) => false, + }) { let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { Def::TyAlias(def_id) | Def::Struct(def_id) => { @@ -431,9 +438,11 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { } fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) { - let hs = generics - .lifetimes() - .map(|lt| (lt.lifetime.name.name(), lt.lifetime.span)) + let hs = generics.params.iter() + .filter_map(|par| match par.kind { + GenericParamKind::Lifetime { .. } => Some((par.name.name(), par.span)), + _ => None, + }) .collect(); let mut checker = LifetimeChecker { map: hs }; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 2fe56bcdce1..b5e1780fd0c 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -2101,8 +2101,14 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener if params.parenthesized { false } else { - params.types.len() == 1 - && (is_self_ty(¶ms.types[0]) || is_ty(&*params.types[0], self_ty)) + // FIXME(flip1995): messy, improve if there is a better option + // in the compiler + let types: Vec<_> = params.args.iter().filter_map(|arg| match arg { + hir::GenericArg::Type(ty) => Some(ty), + _ => None, + }).collect(); + types.len() == 1 + && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty)) } } else { false diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7a250f93db5..03a45bc1847 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -219,7 +219,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if let Some(elem_ty) = path.segments.iter() .find(|seg| seg.name == "Vec") .and_then(|ps| ps.args.as_ref()) - .map(|params| ¶ms.types[0]); + .map(|params| params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }).unwrap()); then { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); db.span_suggestion(input.span, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index fcd56c28218..78a07eddd4e 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -161,9 +161,14 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if_chain! { if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node; if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last(); - if parameters.types.len() == 1; then { - ty_snippet = snippet_opt(cx, parameters.types[0].span); + let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }).collect(); + if types.len() == 1 { + ty_snippet = snippet_opt(cx, types[0].span); + } } }; if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { @@ -220,7 +225,8 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if let [ref bx] = *pp.segments; if let Some(ref params) = bx.args; if !params.parenthesized; - if let [ref inner] = *params.types; + if let [ref inner] = *params.args; + if let GenericArg::Type(inner) = inner; then { let replacement = snippet_opt(cx, inner.span); if let Some(r) = replacement { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2b27ed22c47..c2e981979a1 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -457,7 +457,10 @@ fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String { if_chain! { if let Some(ref params) = seg.args; if !params.parenthesized; - if let Some(to_ty) = params.types.get(1); + if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }).nth(1); if let TyRptr(_, ref to_ty) = to_ty.node; then { return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 70625724040..ee5611a50a1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -182,7 +182,10 @@ fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool if_chain! { if let Some(ref params) = last.args; if !params.parenthesized; - if let Some(ty) = params.types.get(0); + if let Some(ty) = params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }); if let TyPath(ref qpath) = ty.node; if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id))); if match_def_path(cx.tcx, did, path); @@ -246,7 +249,11 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { for ty in p.segments.iter().flat_map(|seg| { seg.args .as_ref() - .map_or_else(|| [].iter(), |params| params.types.iter()) + .map_or_else(|| [].iter(), |params| params.args.iter()) + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }) }) { check_ty(cx, ty, is_local); } @@ -254,14 +261,21 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| { seg.args .as_ref() - .map_or_else(|| [].iter(), |params| params.types.iter()) + .map_or_else(|| [].iter(), |params| params.args.iter()) + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }) }) { check_ty(cx, ty, is_local); }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); if let Some(ref params) = seg.args { - for ty in params.types.iter() { + for ty in params.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }) { check_ty(cx, ty, is_local); } } @@ -290,7 +304,8 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti if let [ref bx] = *path.segments; if let Some(ref params) = bx.args; if !params.parenthesized; - if let [ref inner] = *params.types; + if let [ref inner] = *params.args; + if let GenericArg::Type(inner) = inner; then { if is_any_trait(inner) { // Ignore `Box` types, see #1884 for details. @@ -1862,7 +1877,11 @@ impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node { - let params = &path.segments.last().as_ref()?.args.as_ref()?.types; + let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()? + .args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }).collect(); let params_len = params.len(); let ty = hir_ty_to_ty(cx.tcx, hir_ty); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 035471e4520..170db6ceabb 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -60,7 +60,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; let should_check = if let Some(ref params) = *parameters { - !params.parenthesized && params.lifetimes.len() == 0 + !params.parenthesized && !params.args.iter().any(|arg| match arg { + GenericArg::Lifetime(_) => true, + GenericArg::Type(_) => false, + }) } else { true }; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 1cfb5a82f72..ee6b004dc6c 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -152,6 +152,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr) } + fn eq_generic_arg(&mut self, left: &GenericArg, right: &GenericArg) -> bool { + match (left, right) { + (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => self.eq_lifetime(l_lt, r_lt), + (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), + _ => false, + } + } + fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool { left.name == right.name } @@ -203,8 +211,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_path_parameters(&mut self, left: &GenericArgs, right: &GenericArgs) -> bool { if !(left.parenthesized || right.parenthesized) { - over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) - && over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) + over(&left.args, &right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) } else if left.parenthesized && right.parenthesized { over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 9482cc6bc0e..eb2197a5891 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -100,6 +100,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::ObsoleteInPlace(..) | ast::ExprKind::Unary(..) | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), + ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::Break(..) | ast::ExprKind::Call(..) | -- cgit 1.4.1-3-g733a5 From 535c16879111b7e6e3d55f43e469a8cccb6dbe05 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 25 Jun 2018 02:06:57 +0200 Subject: Fix the tests that got broken by the fixes --- clippy_lints/src/lifetimes.rs | 60 ++++++++++++++++++++++--------------------- clippy_lints/src/ptr.rs | 6 +++-- clippy_lints/src/types.rs | 6 +++-- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7e22fda4006..1c063464fcc 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -101,38 +101,40 @@ fn check_fn_inner<'a, 'tcx>( } let mut bounds_lts = Vec::new(); - generics.params.iter().for_each(|param| match param.kind { - GenericParamKind::Lifetime { .. } => {}, - GenericParamKind::Type { .. } => { - for bound in ¶m.bounds { - let mut visitor = RefVisitor::new(cx); - walk_param_bound(&mut visitor, bound); - if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { - return; - } - if let GenericBound::Trait(ref trait_ref, _) = *bound { - let params = &trait_ref - .trait_ref - .path - .segments - .last() - .expect("a path must have at least one segment") - .args; - if let Some(ref params) = *params { - params.args.iter().for_each(|param| match param { - GenericArg::Lifetime(bound) => { - if bound.name.name() != "'static" && !bound.is_elided() { - return; - } - bounds_lts.push(bound); - }, - _ => {}, - }); + let types = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Type { .. } => Some(param), + GenericParamKind::Lifetime { .. } => None, + }); + for typ in types { + for bound in &typ.bounds { + let mut visitor = RefVisitor::new(cx); + walk_param_bound(&mut visitor, bound); + if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { + return; + } + if let GenericBound::Trait(ref trait_ref, _) = *bound { + let params = &trait_ref + .trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .args; + if let Some(ref params) = *params { + let lifetimes = params.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + GenericArg::Type(_) => None, + }); + for bound in lifetimes { + if bound.name.name() != "'static" && !bound.is_elided() { + return; + } + bounds_lts.push(bound); } } } - }, - }); + } + } if could_use_elision(cx, decl, body, &generics.params, bounds_lts) { span_lint( cx, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 78a07eddd4e..68cecc8de67 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -225,8 +225,10 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if let [ref bx] = *pp.segments; if let Some(ref params) = bx.args; if !params.parenthesized; - if let [ref inner] = *params.args; - if let GenericArg::Type(inner) = inner; + if let Some(inner) = params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }); then { let replacement = snippet_opt(cx, inner.span); if let Some(r) = replacement { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ee5611a50a1..887e9f12712 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -304,8 +304,10 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti if let [ref bx] = *path.segments; if let Some(ref params) = bx.args; if !params.parenthesized; - if let [ref inner] = *params.args; - if let GenericArg::Type(inner) = inner; + if let Some(inner) = params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }); then { if is_any_trait(inner) { // Ignore `Box` types, see #1884 for details. -- cgit 1.4.1-3-g733a5 From 203ad28021ddad978285f2533bdb678bed05f2e3 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 25 Jun 2018 11:53:00 +0200 Subject: resolve merge of NameAndSpan and ExpnInfo rust-lang/rust#51726 --- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/utils/mod.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a1cb1910e20..414e507a55b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -558,7 +558,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool { .ctxt() .outer() .expn_info() - .map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_))) + .map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_))) } /// Test whether `def` is a variable defined outside a macro. diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3adc65a2543..ae8ffcf2fce 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -57,7 +57,7 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().map_or(false, |info| { - match info.callee.format { + match info.format { // don't treat range expressions desugared to structs as "in_macro" ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, _ => true, @@ -68,7 +68,7 @@ pub fn in_macro(span: Span) -> bool { /// Returns true if `expn_info` was expanded by range expressions. pub fn is_range_expression(span: Span) -> bool { span.ctxt().outer().expn_info().map_or(false, |info| { - match info.callee.format { + match info.format { ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::DotFill) => true, _ => false, } @@ -84,12 +84,12 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { /// this after other checks have already happened. fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool { // no ExpnInfo = no macro - if let ExpnFormat::MacroAttribute(..) = info.callee.format { + if let ExpnFormat::MacroAttribute(..) = info.format { // these are all plugins return true; } // no span for the callee = external macro - info.callee.span.map_or(true, |span| { + info.def_site.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion cx.sess() .codemap() @@ -768,7 +768,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { let span_name_span = span.ctxt() .outer() .expn_info() - .map(|ei| (ei.callee.name(), ei.call_site)); + .map(|ei| (ei.format.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => return Some(new_span), @@ -791,7 +791,7 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { let span_name_span = span.ctxt() .outer() .expn_info() - .map(|ei| (ei.callee.name(), ei.call_site)); + .map(|ei| (ei.format.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => Some(new_span), -- cgit 1.4.1-3-g733a5 From 9f8624e5bf6f4feb99ebe0d62b83a30c9e2747c4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 25 Jun 2018 18:18:50 +0200 Subject: Version bump --- CHANGELOG.md | 5 +++++ Cargo.toml | 4 ++-- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/lib.rs | 4 ++-- min_version.txt | 6 +++--- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a1e7e5acd..22c043d876d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.210 +* Rustup to *rustc 1.28.0-nightly (01cc982e9 2018-06-24)* + ## 0.0.209 * Rustup to *rustc 1.28.0-nightly (523097979 2018-06-18)* @@ -638,6 +641,7 @@ All notable changes to this project will be documented in this file. [`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity [`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation +[`default_trait_access`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#default_trait_access [`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof [`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq @@ -778,6 +782,7 @@ All notable changes to this project will be documented in this file. [`out_of_bounds_indexing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#overflow_check_conditional [`panic_params`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panic_params +[`panicking_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panicking_unwrap [`partialeq_ne_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#partialeq_ne_impl [`possible_missing_comma`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence diff --git a/Cargo.toml b/Cargo.toml index de2db9604a2..b7cfcb68065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.209" +version = "0.0.210" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.209", path = "clippy_lints" } +clippy_lints = { version = "0.0.210", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/README.md b/README.md index 588e4b74d23..f836183786a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 268 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 270 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index be46cda4975..1f62b479ba7 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.209" +version = "0.0.210" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 621b21429a9..34799635884 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -499,7 +499,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy", vec![ approx_const::APPROX_CONSTANT, - indexing_slicing::OUT_OF_BOUNDS_INDEXING, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_SEMVER, @@ -549,6 +548,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, infinite_iter::INFINITE_ITER, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, @@ -862,7 +862,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_correctness", vec![ approx_const::APPROX_CONSTANT, - indexing_slicing::OUT_OF_BOUNDS_INDEXING, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, @@ -880,6 +879,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { erasing_op::ERASING_OP, formatting::POSSIBLE_MISSING_COMMA, functions::NOT_UNSAFE_PTR_ARG_DEREF, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, infinite_iter::INFINITE_ITER, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, invalid_ref::INVALID_REF, diff --git a/min_version.txt b/min_version.txt index 7971ed2b327..612b03e54db 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (523097979 2018-06-18) +rustc 1.28.0-nightly (01cc982e9 2018-06-24) binary: rustc -commit-hash: 5230979794db209de492b3f7cc688020b72bc7c6 -commit-date: 2018-06-18 +commit-hash: 01cc982e936120acb0424e41de14e42ba2d88c6f +commit-date: 2018-06-24 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 9f24b9d4b36797c99a9040434fbaa895cba414d4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 25 Jun 2018 11:39:48 -0700 Subject: Move default_trait_access to pedantic --- clippy_lints/src/default_trait_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index d96ed8db786..30dcafc2daf 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -22,7 +22,7 @@ use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_ /// ``` declare_clippy_lint! { pub DEFAULT_TRAIT_ACCESS, - style, + pedantic, "checks for literal calls to Default::default()" } -- cgit 1.4.1-3-g733a5 From a6601f2d02389dbde250c2538b4482fa4613efab Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Mon, 25 Jun 2018 20:50:20 +0200 Subject: Enable rust_2018_idioms warning --- build.rs | 3 --- clippy_lints/src/copies.rs | 6 ++--- clippy_lints/src/lib.rs | 35 ++++-------------------------- clippy_lints/src/literal_representation.rs | 18 +++++++-------- clippy_lints/src/utils/conf.rs | 11 +++++++++- src/driver.rs | 12 ++-------- src/lib.rs | 4 +--- 7 files changed, 29 insertions(+), 60 deletions(-) diff --git a/build.rs b/build.rs index 1481f460fc3..241c8579a48 100644 --- a/build.rs +++ b/build.rs @@ -13,9 +13,6 @@ //! This build script was originally taken from the Rocket web framework: //! https://github.com/SergioBenitez/Rocket -extern crate ansi_term; -extern crate rustc_version; - use ansi_term::Colour::Red; use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; use std::env; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index abbc4681166..2e2489cbb4a 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -134,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { /// Implementation of `IF_SAME_THEN_ELSE`. fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { - let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; + let eq: &dyn Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same_sequenced(blocks, eq) { span_note_and_lint( @@ -150,13 +150,13 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { - let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 { + let hash: &dyn Fn(&&Expr) -> u64 = &|expr| -> u64 { let mut h = SpanlessHash::new(cx, cx.tables); h.hash_expr(expr); h.finish() }; - let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; + let eq: &dyn Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; if let Some((i, j)) = search_same(conds, hash, eq) { span_note_and_lint( diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 34799635884..43fcd786773 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -12,50 +12,23 @@ #![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] #![feature(rust_2018_preview)] +#![warn(rust_2018_idioms)] -extern crate cargo_metadata; #[macro_use] extern crate rustc; -extern crate rustc_target; -extern crate rustc_typeck; -extern crate syntax; -extern crate syntax_pos; -extern crate toml; - -// for unicode nfc normalization - -extern crate unicode_normalization; - -// for semver check in attrs.rs - -extern crate semver; - -// for regex checking - -extern crate regex_syntax; - -// for finding minimal boolean expressions - -extern crate quine_mc_cluskey; - -extern crate rustc_errors; -extern crate rustc_plugin; +use toml; +use rustc_plugin; #[macro_use] extern crate matches as matches_macro; -extern crate serde; #[macro_use] extern crate serde_derive; #[macro_use] extern crate lazy_static; -extern crate itertools; -extern crate pulldown_cmark; -extern crate url; - #[macro_use] extern crate if_chain; @@ -211,7 +184,7 @@ pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` mod reexport { - pub use syntax::ast::{Name, NodeId}; + crate use syntax::ast::{Name, NodeId}; } #[cfg_attr(rustfmt, rustfmt_skip)] diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 09b66b872e9..9b6c30f7f4c 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -90,7 +90,7 @@ pub(super) enum Radix { impl Radix { /// Return a reasonable digit group size for this radix. - pub fn suggest_grouping(&self) -> usize { + crate fn suggest_grouping(&self) -> usize { match *self { Radix::Binary | Radix::Hexadecimal => 4, Radix::Octal | Radix::Decimal => 3, @@ -101,19 +101,19 @@ impl Radix { #[derive(Debug)] pub(super) struct DigitInfo<'a> { /// Characters of a literal between the radix prefix and type suffix. - pub digits: &'a str, + crate digits: &'a str, /// Which radix the literal was represented in. - pub radix: Radix, + crate radix: Radix, /// The radix prefix, if present. - pub prefix: Option<&'a str>, + crate prefix: Option<&'a str>, /// The type suffix, including preceding underscore if present. - pub suffix: Option<&'a str>, + crate suffix: Option<&'a str>, /// True for floating-point literals. - pub float: bool, + crate float: bool, } impl<'a> DigitInfo<'a> { - pub fn new(lit: &'a str, float: bool) -> Self { + crate fn new(lit: &'a str, float: bool) -> Self { // Determine delimiter for radix prefix, if present, and radix. let radix = if lit.starts_with("0x") { Radix::Hexadecimal @@ -160,7 +160,7 @@ impl<'a> DigitInfo<'a> { } /// Returns digits grouped in a sensible way. - pub fn grouping_hint(&self) -> String { + crate fn grouping_hint(&self) -> String { let group_size = self.radix.suggest_grouping(); if self.digits.contains('.') { let mut parts = self.digits.split('.'); @@ -227,7 +227,7 @@ enum WarningType { } impl WarningType { - pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: syntax_pos::Span) { + crate fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: syntax_pos::Span) { match self { WarningType::UnreadableLiteral => span_lint_and_sugg( cx, diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index d3c7d901323..05abdd2f13c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -76,6 +76,15 @@ lazy_static! { macro_rules! define_Conf { ($(#[$doc: meta] ($rust_name: ident, $rust_name_str: expr, $default: expr => $($ty: tt)+),)+) => { pub use self::helpers::Conf; + // FIXME(mati865): remove #[allow(rust_2018_idioms)] when it's fixed: + // + // warning: `extern crate` is not idiomatic in the new edition + // --> src/utils/conf.rs:82:22 + // | + // 82 | #[derive(Deserialize)] + // | ^^^^^^^^^^^ help: convert it to a `use` + // + #[allow(rust_2018_idioms)] mod helpers { /// Type used to store lint configuration. #[derive(Deserialize)] @@ -92,7 +101,7 @@ macro_rules! define_Conf { mod $rust_name { use serde; use serde::Deserialize; - pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) + crate fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { type T = define_Conf!(TY $($ty)+); Ok(T::deserialize(deserializer).unwrap_or_else(|e| { diff --git a/src/driver.rs b/src/driver.rs index 419f61f860b..585edcd82a6 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -3,16 +3,8 @@ #![feature(rustc_private)] #![allow(unknown_lints, missing_docs_in_private_items)] -extern crate clippy_lints; -extern crate getopts; -extern crate rustc; -extern crate rustc_codegen_utils; -extern crate rustc_driver; -extern crate rustc_errors; -extern crate rustc_plugin; -extern crate syntax; - -use rustc_driver::{driver::CompileController, Compilation}; +use rustc_driver::{self, driver::CompileController, Compilation}; +use rustc_plugin; use std::process::{exit, Command}; #[allow(print_stdout)] diff --git a/src/lib.rs b/src/lib.rs index 61e5c104bef..6ff15e2cd89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,10 @@ #![feature(macro_vis_matcher)] #![allow(unknown_lints)] #![allow(missing_docs_in_private_items)] +#![warn(rust_2018_idioms)] -extern crate rustc_plugin; use rustc_plugin::Registry; -extern crate clippy_lints; - #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.sess.lint_store.with_read_lock(|lint_store| { -- cgit 1.4.1-3-g733a5 From 1036df5699ef7f0010b336a0909f9ab5ebe8a7ec Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Mon, 25 Jun 2018 21:22:53 +0200 Subject: Fix clippy_lints doc-tests --- clippy_lints/src/needless_continue.rs | 10 +++++----- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 4f6a8d9e2cb..3258bcd069a 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -2,7 +2,7 @@ //! //! For example, the lint would catch //! -//! ``` +//! ```ignore //! while condition() { //! update_condition(); //! if x { @@ -16,7 +16,7 @@ //! //! And suggest something like this: //! -//! ``` +//! ```ignore //! while condition() { //! update_condition(); //! if x { @@ -365,7 +365,7 @@ fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) { /// /// is transformed to /// -/// ``` +/// ```ignore /// { /// let x = 5; /// ``` @@ -388,7 +388,7 @@ pub fn erode_from_back(s: &str) -> String { /// any number of opening braces are eaten, followed by any number of newlines. /// e.g., the string /// -/// ``` +/// ```ignore /// { /// something(); /// inside_a_block(); @@ -397,7 +397,7 @@ pub fn erode_from_back(s: &str) -> String { /// /// is transformed to /// -/// ``` +/// ```ignore /// something(); /// inside_a_block(); /// } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index ab98eef36e6..d2d9b22d212 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -43,7 +43,7 @@ impl LintPass for QuestionMarkPass { impl QuestionMarkPass { /// Check if the given expression on the given context matches the following structure: /// - /// ``` + /// ```ignore /// if option.is_none() { /// return None; /// } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ae8ffcf2fce..faecdba357f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -612,7 +612,7 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( /// These suggestions can be parsed by rustfix to allow it to automatically fix your code. /// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > 2)"`. /// -/// ``` +/// ```ignore /// error: This `.fold` can be more succinctly expressed as `.any` /// --> $DIR/methods.rs:390:13 /// | -- cgit 1.4.1-3-g733a5 From df3b9cc350d7a54b6aefcad278bda6563881a9c5 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Mon, 25 Jun 2018 21:28:23 +0200 Subject: Format the code --- clippy_lints/src/attrs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c861e4ee4e2..ebf1af52d22 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,16 +1,16 @@ //! checks for attributes use crate::reexport::*; +use crate::utils::{ + in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, + without_block_comments, +}; use rustc::hir::*; use rustc::lint::*; use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use crate::utils::{ - in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, - without_block_comments, -}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. -- cgit 1.4.1-3-g733a5 From b2fb01f23b96a6d5a0204a66998cf005edef5403 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 22 Jun 2018 16:20:26 +0200 Subject: Use utils::opt_def_id() instead of def_id() to prevent ICE --- clippy_lints/src/fallible_impl_from.rs | 7 ++++--- tests/run-pass/ice-2865.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/run-pass/ice-2865.rs diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 33611a90c4d..7e05712aa1a 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir; use rustc::ty; use syntax_pos::Span; -use crate::utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of}; +use crate::utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of, opt_def_id}; use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` @@ -65,8 +65,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it if_chain! { if let ExprCall(ref func_expr, _) = expr.node; if let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node; - if match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC) || - match_def_path(self.tcx, path.def.def_id(), &BEGIN_PANIC_FMT); + if let Some(path_def_id) = opt_def_id(path.def); + if match_def_path(self.tcx, path_def_id, &BEGIN_PANIC) || + match_def_path(self.tcx, path_def_id, &BEGIN_PANIC_FMT); if is_expn_of(expr.span, "unreachable").is_none(); then { self.result.push(expr.span); diff --git a/tests/run-pass/ice-2865.rs b/tests/run-pass/ice-2865.rs new file mode 100644 index 00000000000..430de25a29d --- /dev/null +++ b/tests/run-pass/ice-2865.rs @@ -0,0 +1,13 @@ +#[allow(dead_code)] +struct Ice { + size: String +} + +impl<'a> From for Ice { + fn from(_: String) -> Self { + let text = || "iceberg".to_string(); + Self { size: text() } + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 536e7c8f381aa26ab39cd3f4df858876f2bf0026 Mon Sep 17 00:00:00 2001 From: Alex Vermillion Date: Tue, 26 Jun 2018 20:22:36 -0500 Subject: Removed placeholder doc-comments There were comments instructing someone to insert an example, but an example was already present --- clippy_lints/src/excessive_precision.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index c33a3b50185..aa648003c0c 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -19,12 +19,10 @@ use crate::utils::span_lint_and_sugg; /// /// ```rust /// // Bad -/// Insert a short example of code that triggers the lint /// let v: f32 = 0.123_456_789_9; /// println!("{}", v); // 0.123_456_789 /// /// // Good -/// Insert a short example of improved code that doesn't trigger the lint /// let v: f64 = 0.123_456_789_9; /// println!("{}", v); // 0.123_456_789_9 /// ``` -- cgit 1.4.1-3-g733a5 From b7d95f486b87a60be2f8c90ddb25dc79d90a9b45 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 28 Jun 2018 13:33:11 +0200 Subject: Fix warnings --- clippy_lints/src/misc_early.rs | 4 ++-- clippy_lints/src/non_copy_const.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 94247e64b10..96a3250d272 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -371,8 +371,8 @@ impl MiscEarly { let mut seen = (false, false); for ch in src.chars() { match ch { - 'a' ... 'f' => seen.0 = true, - 'A' ... 'F' => seen.1 = true, + 'a' ..= 'f' => seen.0 = true, + 'A' ..= 'F' => seen.1 = true, 'i' | 'u' => break, // start of suffix already _ => () } diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 5fcf54bc015..47c84fec6ae 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -5,7 +5,7 @@ use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; use rustc::hir::*; use rustc::hir::def::Def; -use rustc::ty::{self, TyRef, TypeFlags}; +use rustc::ty::{self, TypeFlags}; use rustc::ty::adjustment::Adjust; use rustc_errors::Applicability; use rustc_typeck::hir_ty_to_ty; -- cgit 1.4.1-3-g733a5 From 48cb6e273ea49e85b6baa209e0123a2bbd6d15c2 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Thu, 28 Jun 2018 15:46:58 +0200 Subject: Rustup --- clippy_lints/src/attrs.rs | 4 +-- clippy_lints/src/blacklisted_name.rs | 6 ++-- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/bytecount.rs | 8 ++--- clippy_lints/src/copies.rs | 4 +-- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/entry.rs | 4 +-- clippy_lints/src/enum_variants.rs | 4 +-- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/explicit_write.rs | 4 +-- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/identity_conversion.rs | 2 +- clippy_lints/src/infinite_iter.rs | 10 +++--- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/len_zero.rs | 10 +++--- clippy_lints/src/let_if_seq.rs | 4 +-- clippy_lints/src/lifetimes.rs | 18 +++++------ clippy_lints/src/loops.rs | 52 +++++++++++++++--------------- clippy_lints/src/map_clone.rs | 14 ++++---- clippy_lints/src/matches.rs | 6 ++-- clippy_lints/src/methods.rs | 22 ++++++------- clippy_lints/src/misc.rs | 8 ++--- clippy_lints/src/misc_early.rs | 4 +-- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 6 ++-- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/open_options.rs | 4 +-- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 6 ++-- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 8 ++--- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/swap.rs | 4 +-- clippy_lints/src/types.rs | 10 +++--- clippy_lints/src/unused_io_amount.rs | 4 +-- clippy_lints/src/unused_label.rs | 4 +-- clippy_lints/src/unwrap.rs | 10 +++--- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 10 +++--- clippy_lints/src/utils/hir_utils.rs | 28 ++++++++-------- clippy_lints/src/utils/inspector.rs | 10 +++--- clippy_lints/src/utils/internal_lints.rs | 4 +-- clippy_lints/src/utils/mod.rs | 32 +++++++++++------- clippy_lints/src/utils/ptr.rs | 4 +-- clippy_lints/src/write.rs | 8 ++--- 48 files changed, 186 insertions(+), 178 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index ebf1af52d22..b9d8976b28b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -195,13 +195,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if is_relevant_impl(cx.tcx, item) { - check_attrs(cx, item.span, item.name, &item.attrs) + check_attrs(cx, item.span, item.ident.name, &item.attrs) } } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if is_relevant_trait(cx.tcx, item) { - check_attrs(cx, item.span, item.name, &item.attrs) + check_attrs(cx, item.span, item.ident.name, &item.attrs) } } } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index f1e8be4dba9..29660399233 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -41,13 +41,13 @@ impl LintPass for BlackListedName { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { - if let PatKind::Binding(_, _, ref ident, _) = pat.node { - if self.blacklist.iter().any(|s| ident.node == *s) { + if let PatKind::Binding(_, _, ident, _) = pat.node { + if self.blacklist.iter().any(|s| ident.name == *s) { span_lint( cx, BLACKLISTED_NAME, ident.span, - &format!("use of a blacklisted/placeholder name `{}`", ident.node), + &format!("use of a blacklisted/placeholder name `{}`", ident.name), ); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 0a453618e19..b541bfc6b2f 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { METHODS_WITH_NEGATION .iter().cloned() .flat_map(|(a, b)| vec![(a, b), (b, a)]) - .find(|&(a, _)| a == path.name.as_str()) + .find(|&(a, _)| a == path.ident.as_str()) .and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method))) }, _ => None, diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 165c46164bb..6f2ea320f93 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -39,10 +39,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_chain! { if let ExprMethodCall(ref count, _, ref count_args) = expr.node; - if count.name == "count"; + if count.ident.name == "count"; if count_args.len() == 1; if let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node; - if filter.name == "filter"; + if filter.ident.name == "filter"; if filter_args.len() == 2; if let ExprClosure(_, _, body_id, _, _) = filter_args[1].node; then { @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { } let haystack = if let ExprMethodCall(ref path, _, ref args) = filter_args[0].node { - let p = path.name; + let p = path.ident.name; if (p == "iter" || p == "iter_mut") && args.len() == 1 { &args[0] } else { @@ -104,7 +104,7 @@ fn get_path_name(expr: &Expr) -> Option { } else { None }, - ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), + ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), _ => None, } } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 2e2489cbb4a..430ff59cd4d 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -269,8 +269,8 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap for pat in pats { bindings_impl(cx, pat, map); }, - PatKind::Binding(_, _, ref ident, ref as_pat) => { - if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { + PatKind::Binding(_, _, ident, ref as_pat) => { + if let Entry::Vacant(v) = map.entry(ident.as_str()) { v.insert(cx.tables.pat_ty(pat)); } if let Some(ref as_pat) = *as_pat { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 5f34803c813..16b94d24b16 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); then { - let suggested_fn = match (method_path.name.as_str().as_ref(), divisor) { + let suggested_fn = match (method_path.ident.as_str().as_ref(), divisor) { ("subsec_micros", 1_000) => "subsec_millis", ("subsec_nanos", 1_000) => "subsec_micros", ("subsec_nanos", 1_000_000) => "subsec_millis", diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 24e1b2d8387..13c75f39bb8 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -90,7 +90,7 @@ fn check_cond<'a, 'tcx, 'b>( if_chain! { if let ExprMethodCall(ref path, _, ref params) = check.node; if params.len() >= 2; - if path.name == "contains_key"; + if path.ident.name == "contains_key"; if let ExprAddrOf(_, ref key) = params[1].node; then { let map = ¶ms[0]; @@ -125,7 +125,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { if_chain! { if let ExprMethodCall(ref path, _, ref params) = expr.node; if params.len() == 3; - if path.name == "insert"; + if path.ident.name == "insert"; if get_item_name(self.cx, self.map) == get_item_name(self.cx, ¶ms[0]); if SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]); then { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index f11edbeefa3..a200383b41d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -121,7 +121,7 @@ impl LintPass for EnumVariantNames { } fn var2str(var: &Variant) -> LocalInternedString { - var.node.ident.name.as_str() + var.node.ident.as_str() } /// Returns the number of chars that match from the start @@ -245,7 +245,7 @@ impl EarlyLintPass for EnumVariantNames { } fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - let item_name = item.ident.name.as_str(); + let item_name = item.ident.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); if !in_macro(item.span) { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 30ea9f2446a..e924ba6bdbb 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -78,7 +78,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { // If it's a proper path, it can't be a local variable return; } - if p.segments[0].name != ident.node { + if p.segments[0].ident.name != ident.name { // The two idents should be the same return; } diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index feff746ba0c..7c741100bde 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -36,12 +36,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_chain! { // match call to unwrap if let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node; - if unwrap_fun.name == "unwrap"; + if unwrap_fun.ident.name == "unwrap"; // match call to write_fmt if unwrap_args.len() > 0; if let ExprMethodCall(ref write_fun, _, ref write_args) = unwrap_args[0].node; - if write_fun.name == "write_fmt"; + if write_fun.ident.name == "write_fmt"; // match calls to std::io::stdout() / std::io::stderr () if write_args.len() > 0; if let ExprCall(ref dest_fun, _) = write_args[0].node; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 7e05712aa1a..64cdc05b44d 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -93,7 +93,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it for impl_item in impl_items { if_chain! { - if impl_item.name == "from"; + if impl_item.ident.name == "from"; if let ImplItemKind::Method(_, body_id) = cx.tcx.hir.impl_item(impl_item.id).node; then { diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 072b68d6beb..890fe51819a 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -151,7 +151,7 @@ fn check_unformatted(expr: &Expr) -> bool { if let ExprStruct(_, ref fields, _) = format_field.expr.node; if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width"); if let ExprPath(ref qpath) = align_field.expr.node; - if last_path_segment(qpath).name == "Implied"; + if last_path_segment(qpath).ident.name == "Implied"; then { return true; } diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index d8b8e8f073b..2effb8bd8db 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { }, ExprMethodCall(ref name, .., ref args) => { - if match_trait_method(cx, e, &paths::INTO[..]) && &*name.name.as_str() == "into" { + if match_trait_method(cx, e, &paths::INTO[..]) && &*name.ident.as_str() == "into" { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index cb31c1cd044..8f6d499329f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -143,7 +143,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { ExprMethodCall(ref method, _, ref args) => { for &(name, len, heuristic, cap) in HEURISTICS.iter() { - if method.name == name && args.len() == len { + if method.ident.name == name && args.len() == len { return (match heuristic { Always => Infinite, First => is_infinite(cx, &args[0]), @@ -152,7 +152,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { }).and(cap); } } - if method.name == "flat_map" && args.len() == 2 { + if method.ident.name == "flat_map" && args.len() == 2 { if let ExprClosure(_, _, body_id, _, _) = args[1].node { let body = cx.tcx.hir.body(body_id); return is_infinite(cx, &body.value); @@ -207,16 +207,16 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { ExprMethodCall(ref method, _, ref args) => { for &(name, len) in COMPLETING_METHODS.iter() { - if method.name == name && args.len() == len { + if method.ident.name == name && args.len() == len { return is_infinite(cx, &args[0]); } } for &(name, len) in POSSIBLY_COMPLETING_METHODS.iter() { - if method.name == name && args.len() == len { + if method.ident.name == name && args.len() == len { return MaybeInfinite.and(is_infinite(cx, &args[0])); } } - if method.name == "last" && args.len() == 1 { + if method.ident.name == "last" && args.len() == 1 { let not_double_ended = get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR) .map_or(false, |id| !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[])); if not_double_ended { diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 1325ad66857..8dab9fbd12f 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -38,7 +38,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if let TraitItemKind::Method(_, TraitMethod::Required(_)) = item.node { - check_attrs(cx, item.name, &item.attrs); + check_attrs(cx, item.ident.name, &item.attrs); } } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index fe9eb2e2d38..33930ab58db 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { - item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { let did = cx.tcx.hir.local_def_id(item.id.node_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 @@ -135,7 +135,7 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai .iter() .flat_map(|&i| cx.tcx.associated_items(i)) .any(|i| { - i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.name == "is_empty" + i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.ident.name == "is_empty" && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); @@ -155,7 +155,7 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool { - item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { let did = cx.tcx.hir.local_def_id(item.id.node_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 @@ -202,7 +202,7 @@ fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, } } - check_len(cx, span, method_path.name, args, lit, op, compare_to) + check_len(cx, span, method_path.ident.name, args, lit, op, compare_to) } } @@ -235,7 +235,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// Get an `AssociatedItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool { if let ty::AssociatedKind::Method = item.kind { - if item.name == "is_empty" { + if item.ident.name == "is_empty" { let sig = cx.tcx.fn_sig(item.def_id); let ty = sig.skip_binder(); ty.inputs().len() == 1 diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index b114a285f97..4e0d3de799e 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if let Some(expr) = it.peek(); if let hir::StmtDecl(ref decl, _) = stmt.node; if let hir::DeclLocal(ref decl) = decl.node; - if let hir::PatKind::Binding(mode, canonical_id, ref name, None) = decl.pat.node; + if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node; if let hir::StmtExpr(ref if_, _) = expr.node; if let hir::ExprIf(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); @@ -106,7 +106,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { let sug = format!( "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", mut=mutability, - name=name.node, + name=ident.name, cond=snippet(cx, cond.span, "_"), then=if then.stmts.len() > 1 { " ..;" } else { "" }, else=if default_multi_stmts { " ..;" } else { "" }, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 1c063464fcc..efa50a8f743 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -126,7 +126,7 @@ fn check_fn_inner<'a, 'tcx>( GenericArg::Type(_) => None, }); for bound in lifetimes { - if bound.name.name() != "'static" && !bound.is_elided() { + if bound.name.ident().name != "'static" && !bound.is_elided() { return; } bounds_lts.push(bound); @@ -240,7 +240,7 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { for par in named_generics.iter() { if let GenericParamKind::Lifetime { .. } = par.kind { if par.bounds.is_empty() { - allowed_lts.insert(RefLt::Named(par.name.name())); + allowed_lts.insert(RefLt::Named(par.name.ident().name)); } } } @@ -251,8 +251,8 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { fn lts_from_bounds<'a, T: Iterator>(mut vec: Vec, bounds_lts: T) -> Vec { for lt in bounds_lts { - if lt.name.name() != "'static" { - vec.push(RefLt::Named(lt.name.name())); + if lt.name.ident().name != "'static" { + vec.push(RefLt::Named(lt.name.ident().name)); } } @@ -282,12 +282,12 @@ impl<'v, 't> RefVisitor<'v, 't> { fn record(&mut self, lifetime: &Option) { if let Some(ref lt) = *lifetime { - if lt.name.name() == "'static" { + if lt.name.ident().name == "'static" { self.lts.push(RefLt::Static); } else if lt.is_elided() { self.lts.push(RefLt::Unnamed); } else { - self.lts.push(RefLt::Named(lt.name.name())); + self.lts.push(RefLt::Named(lt.name.ident().name)); } } else { self.lts.push(RefLt::Unnamed); @@ -421,7 +421,7 @@ struct LifetimeChecker { impl<'tcx> Visitor<'tcx> for LifetimeChecker { // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - self.map.remove(&lifetime.name.name()); + self.map.remove(&lifetime.name.ident().name); } fn visit_generic_param(&mut self, param: &'tcx GenericParam) { @@ -442,7 +442,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) { let hs = generics.params.iter() .filter_map(|par| match par.kind { - GenericParamKind::Lifetime { .. } => Some((par.name.name(), par.span)), + GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), _ => None, }) .collect(); @@ -463,7 +463,7 @@ struct BodyLifetimeChecker { impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - if lifetime.name.name() != keywords::Invalid.name() && lifetime.name.name() != "'static" { + if lifetime.name.ident().name != keywords::Invalid.name() && lifetime.name.ident().name != "'static" { self.lifetimes_used_in_body = true; } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8808de9025d..8b7032893d8 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -485,8 +485,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); - if method_path.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) - && lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) + if method_path.ident.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) + && lhs_constructor.ident.name == "Some" && !is_refutable(cx, &pat_args[0]) && !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0]) { @@ -513,7 +513,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if let ExprMethodCall(ref method, _, ref args) = expr.node { - if args.len() == 1 && method.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { + if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { span_lint( cx, UNUSED_COLLECT, @@ -811,7 +811,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( ) -> Option { if_chain! { if let ExprMethodCall(ref method, _, ref args) = expr.node; - if method.name == "clone"; + if method.ident.name == "clone"; if args.len() == 1; if let Some(arg) = args.get(0); then { @@ -907,7 +907,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { if_chain! { if let ExprMethodCall(ref method, _, ref len_args) = end.node; - if method.name == "len"; + if method.ident.name == "len"; if len_args.len() == 1; if let Some(arg) = len_args.get(0); if snippet(cx, arg.span, "??") == var_name; @@ -985,7 +985,7 @@ fn check_for_loop_range<'a, 'tcx>( }) = higher::range(cx, arg) { // the var must be a single name - if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node { + if let PatKind::Binding(_, canonical_id, ident, _) = pat.node { let mut visitor = VarVisitor { cx, var: canonical_id, @@ -1058,13 +1058,13 @@ fn check_for_loop_range<'a, 'tcx>( cx, NEEDLESS_RANGE_LOOP, expr.span, - &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), + &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed), |db| { multispan_sugg( db, "consider using an iterator".to_string(), vec![ - (pat.span, format!("({}, )", ident.node)), + (pat.span, format!("({}, )", ident.name)), (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, take, skip)), ], ); @@ -1081,7 +1081,7 @@ fn check_for_loop_range<'a, 'tcx>( cx, NEEDLESS_RANGE_LOOP, expr.span, - &format!("the loop variable `{}` is only used to index `{}`.", ident.node, indexed), + &format!("the loop variable `{}` is only used to index `{}`.", ident.name, indexed), |db| { multispan_sugg( db, @@ -1100,10 +1100,10 @@ fn is_len_call(expr: &Expr, var: Name) -> bool { if_chain! { if let ExprMethodCall(ref method, _, ref len_args) = expr.node; if len_args.len() == 1; - if method.name == "len"; + if method.ident.name == "len"; if let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node; if path.segments.len() == 1; - if path.segments[0].name == var; + if path.segments[0].ident.name == var; then { return true; } @@ -1206,7 +1206,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { if let ExprMethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { - let method_name = &*method.name.as_str(); + let method_name = &*method.ident.as_str(); // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x if method_name == "iter" || method_name == "iter_mut" { if is_ref_iterable_type(cx, &args[0]) { @@ -1520,9 +1520,9 @@ fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { match *pat { PatKind::Wild => true, - PatKind::Binding(_, _, ident, None) if ident.node.as_str().starts_with('_') => { + PatKind::Binding(_, _, ident, None) if ident.as_str().starts_with('_') => { let mut visitor = UsedVisitor { - var: ident.node, + var: ident.name, used: false, }; walk_expr(&mut visitor, body); @@ -1615,7 +1615,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if indexed_indirectly || index_used_directly { if self.prefer_mutable { - self.indexed_mut.insert(seqvar.segments[0].name); + self.indexed_mut.insert(seqvar.segments[0].ident.name); } let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { @@ -1626,19 +1626,19 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].name, Some(extent)); + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); } if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].name, Some(extent)); + self.indexed_directly.insert(seqvar.segments[0].ident.name, Some(extent)); } return false; // no need to walk further *on the variable* } Def::Static(..) | Def::Const(..) => { if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].name, None); + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); } if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].name, None); + self.indexed_directly.insert(seqvar.segments[0].ident.name, None); } return false; // no need to walk further *on the variable* } @@ -1656,8 +1656,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_chain! { // a range index op if let ExprMethodCall(ref meth, _, ref args) = expr.node; - if (meth.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX)) - || (meth.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); + if (meth.ident.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX)) + || (meth.ident.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); if !self.check(&args[1], &args[0], expr); then { return } } @@ -1681,7 +1681,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { self.nonindex = true; } else { // not the correct variable, but still a variable - self.referenced.insert(path.segments[0].name); + self.referenced.insert(path.segments[0].ident.name); } } } @@ -1933,8 +1933,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { // Look for declarations of the variable if let DeclLocal(ref local) = decl.node { if local.pat.id == self.var_id { - if let PatKind::Binding(_, _, ref ident, _) = local.pat.node { - self.name = Some(ident.node); + if let PatKind::Binding(_, _, ident, _) = local.pat.node { + self.name = Some(ident.name); self.state = if let Some(ref init) = local.init { if is_integer_literal(init, 0) { @@ -2123,7 +2123,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } if let PatKind::Binding(_, _, span_name, _) = pat.node { - if self.iterator == span_name.node { + if self.iterator == span_name.name { self.nesting = RuledOut; return; } @@ -2140,7 +2140,7 @@ fn path_name(e: &Expr) -> Option { if let ExprPath(QPath::Resolved(_, ref path)) = e.node { let segments = &path.segments; if segments.len() == 1 { - return Some(segments[0].name); + return Some(segments[0].ident.name); } }; None diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 97c2522d2ce..5ea873e31e1 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use crate::utils::{get_arg_name, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, +use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** Checks for mapping `clone()` over an iterator. @@ -31,7 +31,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // call to .map() if let ExprMethodCall(ref method, _, ref args) = expr.node { - if method.name == "map" && args.len() == 2 { + if method.ident.name == "map" && args.len() == 2 { match args[1].node { ExprClosure(_, ref decl, closure_eid, _, _) => { let body = cx.tcx.hir.body(closure_eid); @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // nothing special in the argument, besides reference bindings // (e.g. .map(|&x| x) ) if let Some(first_arg) = iter_input_pats(decl, body).next(); - if let Some(arg_ident) = get_arg_name(&first_arg.pat); + if let Some(arg_ident) = get_arg_ident(&first_arg.pat); // the method is being called on a known type (option or iterator) if let Some(type_name) = get_type_name(cx, expr, &args[0]); then { @@ -63,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } // explicit clone() calls ( .map(|x| x.clone()) ) else if let ExprMethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.name == "clone" && + if clone_call.ident.name == "clone" && clone_args.len() == 1 && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && expr_eq_name(&clone_args[0], arg_ident) @@ -98,12 +98,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { +fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprPath(QPath::Resolved(None, ref path)) => { let arg_segment = [ PathSegment { - name: id, + ident: id, args: None, infer_types: true, }, @@ -124,7 +124,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s } } -fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { +fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), _ => expr_eq_name(expr, id), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 8ab0482bacf..207343c92c6 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -270,7 +270,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: } print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) }, - PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None) => ident.node.to_string(), + PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None) => ident.to_string(), PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), _ => return, }; @@ -552,14 +552,14 @@ fn is_ref_some_arm(arm: &Arm) -> Option { if_chain! { if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pats[0].node; if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); - if let PatKind::Binding(rb, _, ref ident, _) = pats[0].node; + if let PatKind::Binding(rb, _, ident, _) = pats[0].node; if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; if let ExprCall(ref e, ref args) = remove_blocks(&arm.body).node; if let ExprPath(ref some_path) = e.node; if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; if let ExprPath(ref qpath) = args[0].node; if let &QPath::Resolved(_, ref path2) = qpath; - if path2.segments.len() == 1 && ident.node == path2.segments[0].name; + if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; then { return Some(rb) } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index b5e1780fd0c..71f9dc8e03f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -771,18 +771,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_unnecessary_fold(cx, expr, arglists[0]); } - lint_or_fun_call(cx, expr, *method_span, &method_call.name.as_str(), args); - lint_expect_fun_call(cx, expr, *method_span, &method_call.name.as_str(), args); + lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); + lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); let self_ty = cx.tables.expr_ty_adjusted(&args[0]); - if args.len() == 1 && method_call.name == "clone" { + if args.len() == 1 && method_call.ident.name == "clone" { lint_clone_on_copy(cx, expr, &args[0], self_ty); lint_clone_on_ref_ptr(cx, expr, &args[0]); } match self_ty.sty { ty::TyRef(_, ty, _) if ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { - if method_call.name == method && args.len() > pos { + if method_call.ident.name == method && args.len() > pos { lint_single_char_pattern(cx, expr, &args[pos]); } }, @@ -806,7 +806,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if in_external_macro(cx, implitem.span) { return; } - let name = implitem.name; + let name = implitem.ident.name; let parent = cx.tcx.hir.get_parent(implitem.id); let item = cx.tcx.hir.expect_item(parent); if_chain! { @@ -890,7 +890,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: if name == "unwrap_or" { if let hir::ExprPath(ref qpath) = fun.node { - let path = &*last_path_segment(qpath).name.as_str(); + let path = &*last_path_segment(qpath).ident.as_str(); if ["default", "new"].contains(&path) { let arg_ty = cx.tables.expr_ty(arg); @@ -1438,7 +1438,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option( if arg_char.len() == 1; if let hir::ExprPath(ref qpath) = fun.node; if let Some(segment) = single_segment_path(qpath); - if segment.name == "Some"; + if segment.ident.name == "Some"; then { let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); @@ -2093,7 +2093,7 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener single_segment_ty(ty).map_or(false, |seg| { generics.params.iter().any(|param| match param.kind { hir::GenericParamKind::Type { .. } => { - param.name.name() == seg.name && param.bounds.iter().any(|bound| { + param.name.ident().name == seg.ident.name && param.bounds.iter().any(|bound| { if let hir::GenericBound::Trait(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; match_path(path, name) && path.segments.last().map_or(false, |s| { @@ -2132,8 +2132,8 @@ fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { ) => ty_path .segments .iter() - .map(|seg| seg.name) - .eq(self_ty_path.segments.iter().map(|seg| seg.name)), + .map(|seg| seg.ident.name) + .eq(self_ty_path.segments.iter().map(|seg| seg.ident.name)), _ => false, } } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 414e507a55b..697f15bdd1d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -379,7 +379,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } let binding = match expr.node { ExprPath(ref qpath) => { - let binding = last_path_segment(qpath).name.as_str(); + let binding = last_path_segment(qpath).ident.as_str(); if binding.starts_with('_') && !binding.starts_with("__") && binding != "_result" && // FIXME: #944 @@ -417,13 +417,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { - if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node { + if let PatKind::Binding(_, _, ident, Some(ref right)) = pat.node { if right.node == PatKind::Wild { span_lint( cx, REDUNDANT_PATTERN, pat.span, - &format!("the `{} @ _` pattern can be written as just `{}`", ident.node, ident.node), + &format!("the `{} @ _` pattern can be written as just `{}`", ident.name, ident.name), ); } } @@ -433,7 +433,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { if let Some(seg) = path.segments.last() { - if seg.name == "NAN" { + if seg.ident.name == "NAN" { span_lint( cx, CMP_NAN, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 96a3250d272..87e4d343ab4 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -190,7 +190,7 @@ impl EarlyLintPass for MiscEarly { fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) { for param in &gen.params { if let GenericParamKind::Type { .. } = param.kind { - let name = param.ident.name.as_str(); + let name = param.ident.as_str(); if constants::BUILTIN_TYPES.contains(&&*name) { span_lint( cx, @@ -268,7 +268,7 @@ impl EarlyLintPass for MiscEarly { for arg in &decl.inputs { if let PatKind::Ident(_, ident, None) = arg.pat.node { - let arg_name = ident.name.to_string(); + let arg_name = ident.to_string(); if arg_name.starts_with('_') { if let Some(correspondence) = registered_names.get(&arg_name[1..]) { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 4537f279b1e..4e9c5c815cc 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); let substs = cx.tables.node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); - check_arguments(cx, arguments, method_type, &path.name.as_str()) + check_arguments(cx, arguments, method_type, &path.ident.as_str()) }, _ => (), } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 03a45bc1847..bdef092b533 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -152,8 +152,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Ignore `self`s. if idx == 0 { - if let PatKind::Binding(_, _, name, ..) = arg.pat.node { - if name.node.as_str() == "self" { + if let PatKind::Binding(_, _, ident, ..) = arg.pat.node { + if ident.as_str() == "self" { continue; } } @@ -217,7 +217,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); if let TyPath(QPath::Resolved(_, ref path)) = input.node; if let Some(elem_ty) = path.segments.iter() - .find(|seg| seg.name == "Vec") + .find(|seg| seg.ident.name == "Vec") .and_then(|ps| ps.args.as_ref()) .map(|params| params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index adc91bacdef..3f7cbaa6ca1 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { - let name = impl_item.name; + let name = impl_item.ident.name; let id = impl_item.id; if sig.header.constness == hir::Constness::Const { // can't be implemented by default diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 142447ee345..fbece822659 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprMethodCall(ref path, _, ref arguments) = e.node { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); - if path.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { + if path.ident.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); get_open_options(cx, &arguments[0], &mut options); check_open_options(cx, &options, e.span); @@ -87,7 +87,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp _ => Argument::Unknown, }; - match &*path.name.as_str() { + match &*path.ident.as_str() { "create" => { options.push((OpenOption::Create, argument_option)); }, diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 1d80b78558b..1d9260e2aa7 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if trait_ref.path.def.def_id() == eq_trait; then { for impl_item in impl_items { - if impl_item.name == "ne" { + if impl_item.ident.name == "ne" { span_lint(cx, PARTIALEQ_NE_IMPL, impl_item.span, diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index d2d9b22d212..d12f6ddd15a 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -54,7 +54,7 @@ impl QuestionMarkPass { if_chain! { if let ExprIf(ref if_expr, ref body, _) = expr.node; if let ExprMethodCall(ref segment, _, ref args) = if_expr.node; - if segment.name == "is_none"; + if segment.ident.name == "is_none"; if Self::expression_returns_none(cx, body); if let Some(subject) = args.get(0); if Self::is_option(cx, subject); diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 4947479115e..6ec624d26e9 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -89,7 +89,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprMethodCall(ref path, _, ref args) = expr.node { - let name = path.name.as_str(); + let name = path.ident.as_str(); // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { @@ -108,13 +108,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_chain! { // .iter() call if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter; - if iter_path.name == "iter"; + if iter_path.ident.name == "iter"; // range expression in .zip() call: 0..x.len() if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); if is_integer_literal(start, 0); // .len() call if let ExprMethodCall(ref len_path, _, ref len_args) = end.node; - if len_path.name == "len" && len_args.len() == 1; + if len_path.ident.name == "len" && len_args.len() == 1; // .iter() and .len() called on same Path if let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; if let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 73fbc172c10..03a5d58a3ee 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -114,7 +114,7 @@ impl ReturnPass { if let Some(ref initexpr) = local.init; if let ast::PatKind::Ident(_, ident, _) = local.pat.node; if let ast::ExprKind::Path(_, ref path) = retexpr.node; - if match_path_ast(path, &[&ident.name.as_str()]); + if match_path_ast(path, &[&ident.as_str()]); if !in_external_macro(cx, initexpr.span); then { span_note_and_lint(cx, diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index a56a05470f2..a4bdd89a037 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde { let mut seen_str = None; let mut seen_string = None; for item in items { - match &*item.name.as_str() { + match &*item.ident.as_str() { "visit_str" => seen_str = Some(item.span), "visit_string" => seen_string = Some(item.span), _ => {}, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 12ba6970675..d37023e4f8c 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -100,7 +100,7 @@ fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tc let mut bindings = Vec::new(); for arg in iter_input_pats(decl, body) { if let PatKind::Binding(_, _, ident, _) = arg.pat.node { - bindings.push((ident.node, ident.span)) + bindings.push((ident.name, ident.span)) } } check_expr(cx, &body.value, &mut bindings); @@ -164,8 +164,8 @@ fn check_pat<'a, 'tcx>( ) { // TODO: match more stuff / destructuring match pat.node { - PatKind::Binding(_, _, ref ident, ref inner) => { - let name = ident.node; + PatKind::Binding(_, _, ident, ref inner) => { + let name = ident.name; if is_binding(cx, pat.hir_id) { let mut new_binding = true; for tup in bindings.iter_mut() { @@ -378,5 +378,5 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - !path.is_global() && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() + !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str() } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 5b4a2d1f504..62cd5de68f0 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { use crate::utils::{in_macro, snippet}; if let ExprMethodCall(ref path, _, ref args) = e.node { - if path.name == "as_bytes" { + if path.ident.name == "as_bytes" { if let ExprLit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) { diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 8de4638d13d..1037a1bc632 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -64,7 +64,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if let StmtDecl(ref tmp, _) = w[0].node; if let DeclLocal(ref tmp) = tmp.node; if let Some(ref tmp_init) = tmp.init; - if let PatKind::Binding(_, _, ref tmp_name, None) = tmp.pat.node; + if let PatKind::Binding(_, _, ident, None) = tmp.pat.node; // foo() = bar(); if let StmtSemi(ref first, _) = w[1].node; @@ -76,7 +76,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node; if rhs2.segments.len() == 1; - if tmp_name.node.as_str() == rhs2.segments[0].name.as_str(); + if ident.as_str() == rhs2.segments[0].ident.as_str(); if SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1); if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2); then { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 887e9f12712..61d496c1f0d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -317,7 +317,7 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti let ltopt = if lt.is_elided() { "".to_owned() } else { - format!("{} ", lt.name.name().as_str()) + format!("{} ", lt.name.ident().name.as_str()) }; let mutopt = if mut_ty.mutbl == Mutability::MutMutable { "mut " @@ -1993,10 +1993,10 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' } if match_path(ty_path, &paths::HASHMAP) { - if method.name == "new" { + if method.ident.name == "new" { self.suggestions .insert(e.span, "HashMap::default()".to_string()); - } else if method.name == "with_capacity" { + } else if method.ident.name == "with_capacity" { self.suggestions.insert( e.span, format!( @@ -2006,10 +2006,10 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' ); } } else if match_path(ty_path, &paths::HASHSET) { - if method.name == "new" { + if method.ident.name == "new" { self.suggestions .insert(e.span, "HashSet::default()".to_string()); - } else if method.name == "with_capacity" { + } else if method.ident.name == "with_capacity" { self.suggestions.insert( e.span, format!( diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1ef20e4a46c..316415d73ad 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } }, - hir::ExprMethodCall(ref path, _, ref args) => match &*path.name.as_str() { + hir::ExprMethodCall(ref path, _, ref args) => match &*path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { check_method_call(cx, &args[0], expr); }, @@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_method_call(cx: &LateContext, call: &hir::Expr, expr: &hir::Expr) { if let hir::ExprMethodCall(ref path, _, _) = call.node { - let symbol = &*path.name.as_str(); + let symbol = &*path.ident.as_str(); if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" { span_lint( cx, diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index ca300032675..5c5550ed30f 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -70,10 +70,10 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label { - self.labels.remove(&label.name.as_str()); + self.labels.remove(&label.ident.as_str()); }, hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { - self.labels.insert(label.name.as_str(), expr.span); + self.labels.insert(label.ident.as_str(), expr.span); }, _ => (), } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 7355b38fd6b..b8e34cc66e1 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -95,7 +95,7 @@ fn collect_unwrap_info<'a, 'tcx: 'a>( if let Expr_::ExprPath(QPath::Resolved(None, path)) = &args[0].node; let ty = cx.tables.expr_ty(&args[0]); if match_type(cx, ty, &paths::OPTION) || match_type(cx, ty, &paths::RESULT); - let name = method_name.name.as_str(); + let name = method_name.ident.as_str(); if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name); then { assert!(args.len() == 1); @@ -142,8 +142,8 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { if_chain! { if let Expr_::ExprMethodCall(ref method_name, _, ref args) = expr.node; if let Expr_::ExprPath(QPath::Resolved(None, ref path)) = args[0].node; - if ["unwrap", "unwrap_err"].contains(&&*method_name.name.as_str()); - let call_to_unwrap = method_name.name == "unwrap"; + if ["unwrap", "unwrap_err"].contains(&&*method_name.ident.as_str()); + let call_to_unwrap = method_name.ident.name == "unwrap"; if let Some(unwrappable) = self.unwrappables.iter() .find(|u| u.ident.def == path.def); then { @@ -154,7 +154,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { expr.span, &format!("You checked before that `{}()` cannot fail. \ Instead of checking and unwrapping, it's better to use `if let` or `match`.", - method_name.name), + method_name.ident.name), |db| { db.span_label(unwrappable.check.span, "the check is happening here"); }, ); } else { @@ -163,7 +163,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { PANICKING_UNWRAP, expr.span, &format!("This call to `{}()` will always panic.", - method_name.name), + method_name.ident.name), |db| { db.span_label(unwrappable.check.span, "because of this check"); }, ); } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 170db6ceabb..10b69852ba5 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -88,7 +88,7 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) { - if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).name != SelfType.name() { + if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfType.name() { span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); }); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index df6a06bc478..520c30b03c0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -395,7 +395,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let obj_pat = self.next("object"); let field_name_pat = self.next("field_name"); println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current); - println!(" if {}.node.as_str() == {:?}", field_name_pat, field_ident.name.as_str()); + println!(" if {}.node.as_str() == {:?}", field_name_pat, field_ident.as_str()); self.current = obj_pat; self.visit_expr(object); }, @@ -487,7 +487,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let current = format!("{}.node", self.current); match pat.node { PatKind::Wild => println!("Wild = {};", current), - PatKind::Binding(anno, _, name, ref sub) => { + PatKind::Binding(anno, _, ident, ref sub) => { let anno_pat = match anno { BindingAnnotation::Unannotated => "BindingAnnotation::Unannotated", BindingAnnotation::Mutable => "BindingAnnotation::Mutable", @@ -503,7 +503,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } else { println!("Binding({}, _, {}, None) = {};", anno_pat, name_pat, current); } - println!(" if {}.node.as_str() == \"{}\";", name_pat, name.node.as_str()); + println!(" if {}.node.as_str() == \"{}\";", name_pat, ident.as_str()); } PatKind::Struct(ref path, ref fields, ignore) => { let path_pat = self.next("path"); @@ -671,7 +671,7 @@ fn print_path(path: &QPath, first: &mut bool) { } else { print!(", "); } - print!("{:?}", segment.name.as_str()); + print!("{:?}", segment.ident.as_str()); }, QPath::TypeRelative(ref ty, ref segment) => match ty.node { hir::Ty_::TyPath(ref inner_path) => { @@ -681,7 +681,7 @@ fn print_path(path: &QPath, first: &mut bool) { } else { print!(", "); } - print!("{:?}", segment.name.as_str()); + print!("{:?}", segment.ident.as_str()); }, ref other => print!("/* unimplemented: {:?}*/", other), }, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index ee6b004dc6c..f95fb046b49 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -77,7 +77,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), (&ExprContinue(li), &ExprContinue(ri)) => { - both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str()) + both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) }, (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { @@ -91,7 +91,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }) }, (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => { - both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str()) + both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), @@ -109,7 +109,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprLoop(ref lb, ref ll, ref lls), &ExprLoop(ref rb, ref rl, ref rls)) => { - lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { @@ -138,7 +138,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprArray(ref l), &ExprArray(ref r)) => self.eq_exprs(l, r), (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str()) + self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, _ => false, } @@ -172,7 +172,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs }, (&PatKind::Binding(ref lb, _, ref li, ref lp), &PatKind::Binding(ref rb, _, ref ri, ref rp)) => { - lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) + lb == rb && li.name.as_str() == ri.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) }, (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r), (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), @@ -228,7 +228,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene - if left.name.as_str() != right.name.as_str() { + if left.ident.as_str() != right.ident.as_str() { return false; } match (&left.args, &right.args) { @@ -268,7 +268,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } fn eq_type_binding(&mut self, left: &TypeBinding, right: &TypeBinding) -> bool { - left.name == right.name && self.eq_ty(&left.ty, &right.ty) + left.ident.name == right.ident.name && self.eq_ty(&left.ty, &right.ty) } } @@ -356,7 +356,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprContinue; c.hash(&mut self.s); if let Some(i) = i.label { - self.hash_name(i.name); + self.hash_name(i.ident.name); } }, ExprYield(ref e) => { @@ -393,7 +393,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprBreak; c.hash(&mut self.s); if let Some(i) = i.label { - self.hash_name(i.name); + self.hash_name(i.ident.name); } if let Some(ref j) = *j { self.hash_expr(&*j); @@ -457,7 +457,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { - self.hash_name(i.name); + self.hash_name(i.ident.name); } }, ExprMatch(ref e, ref arms, ref s) => { @@ -478,7 +478,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { ExprMethodCall(ref path, ref _tys, ref args) => { let c: fn(_, _, _) -> _ = ExprMethodCall; c.hash(&mut self.s); - self.hash_name(path.name); + self.hash_name(path.ident.name); self.hash_exprs(args); }, ExprRepeat(ref e, ref l_id) => { @@ -548,7 +548,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(cond); self.hash_block(b); if let Some(l) = l { - self.hash_name(l.name); + self.hash_name(l.ident.name); } }, } @@ -570,7 +570,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_path(path); }, QPath::TypeRelative(_, ref path) => { - self.hash_name(path.name); + self.hash_name(path.ident.name); }, } // self.cx.tables.qpath_def(p, id).hash(&mut self.s); @@ -579,7 +579,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn hash_path(&mut self, p: &Path) { p.is_global().hash(&mut self.s); for p in &p.segments { - self.hash_name(p.name); + self.hash_name(p.ident.name); } } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 9d92147048c..b23464c80de 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if !has_attr(&item.attrs) { return; } - println!("impl item `{}`", item.name); + println!("impl item `{}`", item.ident.name); match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate(_) => println!("visible crate wide"), @@ -181,7 +181,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { }, hir::ExprMethodCall(ref path, _, ref args) => { println!("{}MethodCall", ind); - println!("{}method name: {}", ind, path.name); + println!("{}method name: {}", ind, path.ident.name); for arg in args { print_expr(cx, arg, indent + 1); } @@ -268,7 +268,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprField(ref e, ref ident) => { + hir::ExprField(ref e, ident) => { println!("{}Field", ind); println!("{}field name: {}", ind, ident.name); println!("{}struct expr:", ind); @@ -417,10 +417,10 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { println!("{}+", ind); match pat.node { hir::PatKind::Wild => println!("{}Wild", ind), - hir::PatKind::Binding(ref mode, _, ref name, ref inner) => { + hir::PatKind::Binding(ref mode, _, ident, ref inner) => { println!("{}Binding", ind); println!("{}mode: {:?}", ind, mode); - println!("{}name: {}", ind, name.node); + println!("{}name: {}", ind, ident.name); if let Some(ref inner) = *inner { println!("{}inner:", ind); print_pat(cx, inner, indent + 1); diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 1de0975ab42..b1b65698eb9 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -78,7 +78,7 @@ impl EarlyLintPass for Clippy { if let ItemKind::Mod(ref paths_mod) = paths.node { let mut last_name: Option = None; for item in &paths_mod.items { - let name = item.ident.name.as_str(); + let name = item.ident.as_str(); if let Some(ref last_name) = last_name { if **last_name > *name { span_lint( @@ -196,7 +196,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _: NodeId) { if path.segments.len() == 1 { - self.output.insert(path.segments[0].name); + self.output.insert(path.segments[0].ident.name); } } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index faecdba357f..6765d9afb66 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -175,7 +175,7 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// Check if an expression references a variable of the given name. pub fn match_var(expr: &Expr, var: Name) -> bool { if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { - if path.segments.len() == 1 && path.segments[0].name == var { + if path.segments.len() == 1 && path.segments[0].ident.name == var { return true; } } @@ -212,7 +212,7 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { QPath::TypeRelative(ref ty, ref segment) => match ty.node { TyPath(ref inner_path) => { !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) - && segment.name == segments[segments.len() - 1] + && segment.ident.name == segments[segments.len() - 1] }, _ => false, }, @@ -224,7 +224,7 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { .iter() .rev() .zip(segments.iter().rev()) - .all(|(a, b)| a.name == *b) + .all(|(a, b)| a.ident.name == *b) } /// Match a `Path` against a slice of segment string literals, e.g. @@ -331,7 +331,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option first if let ExprMethodCall(ref path, _, ref args) = current.node { - if path.name == *method_name { + if path.ident.name == *method_name { if args.iter().any(|e| in_macro(e.span)) { return None; } @@ -353,9 +353,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option Option { let parent_id = cx.tcx.hir.get_parent(expr.id); match cx.tcx.hir.find(parent_id) { - Some(Node::NodeItem(&Item { ref name, .. })) | - Some(Node::NodeTraitItem(&TraitItem { ref name, .. })) | - Some(Node::NodeImplItem(&ImplItem { ref name, .. })) => Some(*name), + Some(Node::NodeItem(&Item { ref name, .. })) => Some(*name), + Some(Node::NodeTraitItem(&TraitItem { ident, .. })) | + Some(Node::NodeImplItem(&ImplItem { ident, .. })) => Some(ident.name), _ => None, } } @@ -363,8 +363,8 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option { /// Get the name of a `Pat`, if any pub fn get_pat_name(pat: &Pat) -> Option { match pat.node { - PatKind::Binding(_, _, ref spname, _) => Some(spname.node), - PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), + PatKind::Binding(_, _, ref spname, _) => Some(spname.name), + PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), _ => None, } @@ -431,7 +431,7 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { let file_map_and_line = cx.sess().codemap().lookup_line(span.lo()).unwrap(); let line_no = file_map_and_line.line; - let line_start = &file_map_and_line.fm.lines.clone().into_inner()[line_no]; + let line_start = &file_map_and_line.fm.lines[line_no]; Span::new(*line_start, span.hi(), span.ctxt()) } @@ -990,7 +990,7 @@ pub fn opt_def_id(def: Def) -> Option { pub fn is_self(slf: &Arg) -> bool { if let PatKind::Binding(_, _, name, _) = slf.pat.node { - name.node == keywords::SelfValue.name() + name.name == keywords::SelfValue.name() } else { false } @@ -1068,12 +1068,20 @@ pub fn is_allowed(cx: &LateContext, lint: &'static Lint, id: NodeId) -> bool { pub fn get_arg_name(pat: &Pat) -> Option { match pat.node { - PatKind::Binding(_, _, name, None) => Some(name.node), + PatKind::Binding(_, _, ident, None) => Some(ident.name), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } } +pub fn get_arg_ident(pat: &Pat) -> Option { + match pat.node { + PatKind::Binding(_, _, ident, None) => Some(ident), + PatKind::Ref(ref subpat, _) => get_arg_ident(subpat), + _ => None, + } +} + pub fn int_bits(tcx: TyCtxt, ity: ast::IntTy) -> u64 { layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() } diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index dd286a69547..09ec90ac63f 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -56,12 +56,12 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { } if let ExprMethodCall(ref seg, _, ref args) = expr.node { if args.len() == 1 && match_var(&args[0], self.name) { - if seg.name == "capacity" { + if seg.ident.name == "capacity" { self.abort = true; return; } for &(fn_name, suffix) in self.replace { - if seg.name == fn_name { + if seg.ident.name == fn_name { self.spans .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix)); return; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 274dd952f09..86c95dbcc56 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }, // write!() ExprMethodCall(ref fun, _, ref args) => { - if fun.name == "write_fmt" { + if fun.ident.name == "write_fmt" { check_write_variants(cx, expr, args); } }, @@ -471,13 +471,13 @@ pub fn check_unformatted(format_field: &Expr) -> bool { if let ExprStruct(_, ref fields, _) = format_field.node; if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width"); if let ExprPath(ref qpath) = width_field.expr.node; - if last_path_segment(qpath).name == "Implied"; + if last_path_segment(qpath).ident.name == "Implied"; if let Some(align_field) = fields.iter().find(|f| f.ident.name == "align"); if let ExprPath(ref qpath) = align_field.expr.node; - if last_path_segment(qpath).name == "Unknown"; + if last_path_segment(qpath).ident.name == "Unknown"; if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision"); if let ExprPath(ref qpath_precision) = precision_field.expr.node; - if last_path_segment(qpath_precision).name == "Implied"; + if last_path_segment(qpath_precision).ident.name == "Implied"; then { return true; } -- cgit 1.4.1-3-g733a5 From a24f77f65a60d689f2fde255f680bdf6ee87f065 Mon Sep 17 00:00:00 2001 From: Mateusz Mikuła Date: Fri, 29 Jun 2018 09:55:20 +0200 Subject: Bump the version --- CHANGELOG.md | 2 ++ README.md | 2 +- clippy_lints/src/lib.rs | 3 +-- min_version.txt | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22c043d876d..43e723e51fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -617,6 +617,7 @@ All notable changes to this project will be documented in this file. [`block_in_if_condition_expr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_expr [`block_in_if_condition_stmt`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt [`bool_comparison`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#bool_comparison +[`borrow_interior_mutable_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const [`borrowed_box`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#borrowed_box [`box_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#box_vec [`boxed_local`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#boxed_local @@ -641,6 +642,7 @@ All notable changes to this project will be documented in this file. [`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity [`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation +[`declare_interior_mutable_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#declare_interior_mutable_const [`default_trait_access`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#default_trait_access [`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof diff --git a/README.md b/README.md index f836183786a..05496fc1ccc 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 270 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 272 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9fc020b6819..28827387b9d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -434,6 +434,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_lint_group("clippy_pedantic", vec![ attrs::INLINE_ALWAYS, copies::MATCH_SAME_ARMS, + default_trait_access::DEFAULT_TRAIT_ACCESS, derive::EXPL_IMPL_CLONE_ON_COPY, doc::DOC_MARKDOWN, empty_enum::EMPTY_ENUM, @@ -492,7 +493,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, - default_trait_access::DEFAULT_TRAIT_ACCESS, derive::DERIVE_HASH_XOR_EQ, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, @@ -694,7 +694,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, - default_trait_access::DEFAULT_TRAIT_ACCESS, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, eq_op::OP_REF, diff --git a/min_version.txt b/min_version.txt index 612b03e54db..bd6a57973fc 100644 --- a/min_version.txt +++ b/min_version.txt @@ -1,7 +1,7 @@ -rustc 1.28.0-nightly (01cc982e9 2018-06-24) +rustc 1.28.0-nightly (e3bf634e0 2018-06-28) binary: rustc -commit-hash: 01cc982e936120acb0424e41de14e42ba2d88c6f -commit-date: 2018-06-24 +commit-hash: e3bf634e060bc2f8665878288bcea02008ca346e +commit-date: 2018-06-28 host: x86_64-unknown-linux-gnu release: 1.28.0-nightly LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From b4b6e6558e3ccd5ef11758297dc064acceb15ef2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 29 Jun 2018 10:22:01 +0200 Subject: Version bump --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43e723e51fd..a341424ef5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.211 +* Rustup to *rustc 1.28.0-nightly (e3bf634e0 2018-06-28)* + ## 0.0.210 * Rustup to *rustc 1.28.0-nightly (01cc982e9 2018-06-24)* diff --git a/Cargo.toml b/Cargo.toml index b7cfcb68065..72d2d8cc6ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.210" +version = "0.0.211" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.210", path = "clippy_lints" } +clippy_lints = { version = "0.0.211", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 1f62b479ba7..e7ad3b1b759 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.210" +version = "0.0.211" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 949f0d9c72e901a001acd9c82bca6339be3b6b0e Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 29 Jun 2018 16:55:26 +0200 Subject: Fix badly mangled lint message for neg-cmp-op-on-partial-ord --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 16 ++++++++-------- tests/ui/booleans.rs | 2 +- tests/ui/neg_cmp_op_on_partial_ord.rs | 4 ++-- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 013bab69d79..cae88263111 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -4,20 +4,20 @@ use rustc::lint::*; use crate::utils::{self, paths, span_lint, in_external_macro}; /// **What it does:** -/// Checks for the usage of negated comparision operators on types which only implement +/// Checks for the usage of negated comparison operators on types which only implement /// `PartialOrd` (e.g. `f64`). /// /// **Why is this bad?** /// These operators make it easy to forget that the underlying types actually allow not only three -/// potential Orderings (Less, Equal, Greater) but also a forth one (Uncomparable). Escpeccially if -/// the operator based comparision result is negated it is easy to miss that fact. +/// potential Orderings (Less, Equal, Greater) but also a forth one (Uncomparable). This is +/// especially easy to miss if the operator based comparison result is negated. /// /// **Known problems:** None. /// /// **Example:** /// /// ```rust -/// use core::cmp::Ordering; +/// use std::cmp::Ordering; /// /// // Bad /// let a = 1.0; @@ -37,7 +37,7 @@ use crate::utils::{self, paths, span_lint, in_external_macro}; declare_clippy_lint! { pub NEG_CMP_OP_ON_PARTIAL_ORD, complexity, - "The use of negated comparision operators on partially orded types may produce confusing code." + "The use of negated comparison operators on partially ordered types may produce confusing code." } pub struct NoNegCompOpForPartialOrd; @@ -83,10 +83,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { cx, NEG_CMP_OP_ON_PARTIAL_ORD, expr.span, - "The use of negated comparision operators on partially orded \ + "The use of negated comparison operators on partially ordered \ types produces code that is hard to read and refactor. Please \ - consider to use the `partial_cmp` instead, to make it clear \ - that the two values could be incomparable." + consider using the `partial_cmp` method instead, to make it \ + clear that the two values could be incomparable." ) } } diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 9daf15d378c..fc16c12af28 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -116,7 +116,7 @@ fn warn_for_built_in_methods_with_negation() { } #[allow(neg_cmp_op_on_partial_ord)] -fn dont_warn_for_negated_partial_ord_comparision() { +fn dont_warn_for_negated_partial_ord_comparison() { let a: f64 = unimplemented!(); let b: f64 = unimplemented!(); let _ = !(a < b); diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 483972bb41b..e739908bc28 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -59,9 +59,9 @@ fn main() { // Issue 2856: False positive on assert!() // - // The macro always negates the result of the given comparision in its + // The macro always negates the result of the given comparison in its // internal check which automatically triggered the lint. As it's an - // external macro there was no chance to do anything about it which lead + // external macro there was no chance to do anything about it which led // to a whitelisting of all external macros. assert!(a_value < another_value); } diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 5067ece8705..ccd30561100 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,4 +1,4 @@ -error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. +error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:17:21 | 17 | let _not_less = !(a_value < another_value); @@ -6,19 +6,19 @@ error: The use of negated comparision operators on partially orded types produce | = note: `-D neg-cmp-op-on-partial-ord` implied by `-D warnings` -error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. +error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:20:30 | 20 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. +error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:23:24 | 23 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparision operators on partially orded types produces code that is hard to read and refactor. Please consider to use the `partial_cmp` instead, to make it clear that the two values could be incomparable. +error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:26:33 | 26 | let _not_greater_or_equal = !(a_value >= another_value); -- cgit 1.4.1-3-g733a5 From dfd9e10a2a0213e99435438e7cffdc930c8464ad Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 1 Jul 2018 11:58:29 +0200 Subject: Use slightly neater check for static lifetimes --- clippy_lints/src/lifetimes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index efa50a8f743..3fbbb4daee8 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -126,7 +126,7 @@ fn check_fn_inner<'a, 'tcx>( GenericArg::Type(_) => None, }); for bound in lifetimes { - if bound.name.ident().name != "'static" && !bound.is_elided() { + if bound.name != LifetimeName::Static && !bound.is_elided() { return; } bounds_lts.push(bound); @@ -251,7 +251,7 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { fn lts_from_bounds<'a, T: Iterator>(mut vec: Vec, bounds_lts: T) -> Vec { for lt in bounds_lts { - if lt.name.ident().name != "'static" { + if lt.name != LifetimeName::Static { vec.push(RefLt::Named(lt.name.ident().name)); } } @@ -282,7 +282,7 @@ impl<'v, 't> RefVisitor<'v, 't> { fn record(&mut self, lifetime: &Option) { if let Some(ref lt) = *lifetime { - if lt.name.ident().name == "'static" { + if lt.name == LifetimeName::Static { self.lts.push(RefLt::Static); } else if lt.is_elided() { self.lts.push(RefLt::Unnamed); -- cgit 1.4.1-3-g733a5 From 63041d070b72b37c07fe3c0764f82ae3c3606028 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 1 Jul 2018 13:36:14 +0200 Subject: Rustup --- clippy_lints/src/consts.rs | 5 ++--- clippy_lints/src/utils/paths.rs | 16 ++++++++-------- tests/ui/dlist.rs | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 36417cd0877..6fc6637900d 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -13,7 +13,6 @@ use std::mem; use std::rc::Rc; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; -use rustc::middle::const_val::ConstVal; use crate::utils::{sext, unsext, clip}; #[derive(Debug, Copy, Clone)] @@ -428,7 +427,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { use rustc::mir::interpret::{Scalar, ConstValue}; match result.val { - ConstVal::Value(ConstValue::Scalar(Scalar::Bits{ bits: b, ..})) => match result.ty.sty { + ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { ty::TyBool => Some(Constant::Bool(b == 1)), ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)), ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), @@ -436,7 +435,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' // FIXME: implement other conversion _ => None, }, - ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. })) => match result.ty.sty { + ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty { ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 7606f4f8471..4d89f8ddffb 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -2,18 +2,18 @@ //! about. pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; -pub const ARC: [&str; 3] = ["alloc", "arc", "Arc"]; +pub const ARC: [&str; 3] = ["alloc", "sync", "Arc"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; -pub const BINARY_HEAP: [&str; 3] = ["alloc", "binary_heap", "BinaryHeap"]; +pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BOX: [&str; 3] = ["std", "boxed", "Box"]; pub const BOX_NEW: [&str; 4] = ["std", "boxed", "Box", "new"]; -pub const BTREEMAP: [&str; 4] = ["alloc", "btree", "map", "BTreeMap"]; -pub const BTREEMAP_ENTRY: [&str; 4] = ["alloc", "btree", "map", "Entry"]; -pub const BTREESET: [&str; 4] = ["alloc", "btree", "set", "BTreeSet"]; +pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"]; +pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"]; +pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; pub const CLONE: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; @@ -47,7 +47,7 @@ pub const IO_PRINT: [&str; 4] = ["std", "io", "stdio", "_print"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; -pub const LINKED_LIST: [&str; 3] = ["alloc", "linked_list", "LinkedList"]; +pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 2] = ["lint", "Lint"]; pub const LINT_ARRAY: [&str; 2] = ["lint", "LintArray"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; @@ -101,7 +101,7 @@ pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; -pub const VEC_DEQUE: [&str; 3] = ["alloc", "vec_deque", "VecDeque"]; +pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; -pub const WEAK_ARC: [&str; 3] = ["alloc", "arc", "Weak"]; +pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index a4fab5735e2..1318ed78717 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -6,7 +6,7 @@ #![allow(dead_code, needless_pass_by_value)] extern crate alloc; -use alloc::linked_list::LinkedList; +use alloc::collections::linked_list::LinkedList; trait Foo { type Baz = LinkedList; -- cgit 1.4.1-3-g733a5 From 41972f89dcb99819191ffbf2381430e63e9d916d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 2 Jul 2018 10:16:55 +0200 Subject: HACK: make sure clippy builds the same deps as cargo and rls --- Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 72d2d8cc6ba..dea7f3644c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,12 @@ clippy_lints = { version = "0.0.211", path = "clippy_lints" } regex = "1" semver = "0.9" +# Not actually needed right now but required to make sure that clippy/ and cargo build +# with the same set of features in rust-lang/rust +num-traits = "0.2" # enable the default feature +winapi = "0.3" +backtrace = "0.3" + [dev-dependencies] cargo_metadata = "0.5" compiletest_rs = "0.3.7" -- cgit 1.4.1-3-g733a5 From 141f79f8440229f705f47f06c47b46a44d65584b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 2 Jul 2018 19:07:12 +0200 Subject: Rustup --- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/utils/inspector.rs | 20 ++++++++++---------- clippy_lints/src/utils/internal_lints.rs | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 943a5406b54..9a0263f2f68 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { impl EnumGlobUse { fn lint_item(&self, cx: &LateContext, item: &Item) { - if item.vis == Visibility::Public { + if item.vis.node == VisibilityKind::Public { return; // re-exports are fine } if let ItemUse(ref path, UseKind::Glob) = item.node { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 71f9dc8e03f..1d1d0ef8faa 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -840,7 +840,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { .iter() .any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); then { - let lint = if item.vis == hir::Visibility::Public { + let lint = if item.vis.node == hir::VisibilityKind::Public { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b23464c80de..ccc4c9df6e7 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -51,14 +51,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } println!("impl item `{}`", item.ident.name); - match item.vis { - hir::Visibility::Public => println!("public"), - hir::Visibility::Crate(_) => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => println!( + match item.vis.node { + hir::VisibilityKind::Public => println!("public"), + hir::VisibilityKind::Crate(_) => println!("visible crate wide"), + hir::VisibilityKind::Restricted { ref path, .. } => println!( "visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false)) ), - hir::Visibility::Inherited => println!("visibility inherited from outer item"), + hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"), } if item.defaultness.is_default() { println!("default"); @@ -343,14 +343,14 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { fn print_item(cx: &LateContext, item: &hir::Item) { let did = cx.tcx.hir.local_def_id(item.id); println!("item `{}`", item.name); - match item.vis { - hir::Visibility::Public => println!("public"), - hir::Visibility::Crate(_) => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => println!( + match item.vis.node { + hir::VisibilityKind::Public => println!("public"), + hir::VisibilityKind::Crate(_) => println!("visible crate wide"), + hir::VisibilityKind::Restricted { ref path, .. } => println!( "visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false)) ), - hir::Visibility::Inherited => println!("visibility inherited from outer item"), + hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"), } match item.node { hir::ItemExternCrate(ref _renamed_from) => { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index b1b65698eb9..f0e3961600c 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { if let ItemStatic(ref ty, MutImmutable, body_id) = item.node { if is_lint_ref_type(ty) { self.declared_lints.insert(item.name, item.span); - } else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" { + } else if is_lint_array_type(ty) && item.vis.node == VisibilityKind::Inherited && item.name == "ARRAY" { let mut collector = LintCollector { output: &mut self.registered_lints, cx, -- cgit 1.4.1-3-g733a5 From 547d9ca120a29a546453319cad2c87f0f924703a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 3 Jul 2018 10:52:59 +0200 Subject: Rustup --- clippy_lints/src/escape.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 9482c3782d4..c718e1f417c 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -108,7 +108,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { return; } if let Categorization::Rvalue(..) = cmt.cat { - if let Some(NodeStmt(st)) = map.find(map.get_parent_node(cmt.id)) { + let id = map.hir_to_node_id(cmt.hir_id); + if let Some(NodeStmt(st)) = map.find(map.get_parent_node(id)) { if let StmtDecl(ref decl, _) = st.node { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { -- cgit 1.4.1-3-g733a5 From 7c4ec40346591755b5401bf95a048974542c43bc Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 4 Jul 2018 10:51:04 +0200 Subject: add missing_inline lint When turned on, the lint warns on all exported functions, methods, trait methods (default impls, impls), that are not `#[inline]`. Closes #1503. --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 3 + clippy_lints/src/missing_inline.rs | 171 +++++++++++++++++++++++++++++++++++++ tests/ui/missing_inline.rs | 72 ++++++++++++++++ tests/ui/missing_inline.stderr | 40 +++++++++ 6 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/missing_inline.rs create mode 100644 tests/ui/missing_inline.rs create mode 100644 tests/ui/missing_inline.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a341424ef5e..2b2d2082a7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -744,6 +744,7 @@ All notable changes to this project will be documented in this file. [`misaligned_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misaligned_transmute [`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items +[`missing_inline_in_public_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception [`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one diff --git a/README.md b/README.md index 05496fc1ccc..f2121e13ffd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 272 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 273 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 28827387b9d..9d0a0c3741b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -134,6 +134,7 @@ pub mod minmax; pub mod misc; pub mod misc_early; pub mod missing_doc; +pub mod missing_inline; pub mod multiple_crate_versions; pub mod mut_mut; pub mod mut_reference; @@ -364,6 +365,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box let_if_seq::LetIfSeq); reg.register_late_lint_pass(box eval_order_dependence::EvalOrderDependence); reg.register_late_lint_pass(box missing_doc::MissingDoc::new()); + reg.register_late_lint_pass(box missing_inline::MissingInline::new()); reg.register_late_lint_pass(box ok_if_let::Pass); reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass); reg.register_late_lint_pass(box partialeq_ne_impl::Pass); @@ -422,6 +424,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::WRONG_PUB_SELF_CONVENTION, misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs new file mode 100644 index 00000000000..ddd44ba7fa1 --- /dev/null +++ b/clippy_lints/src/missing_inline.rs @@ -0,0 +1,171 @@ +// Copyright 2012-2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// + +use rustc::hir; +use rustc::lint::*; +use syntax::ast; +use syntax::codemap::Span; + +/// **What it does:** it lints if an exported function, method, trait method with default impl, +/// or trait method impl is not `#[inline]`. +/// +/// **Why is this bad?** In general, it is not. Functions can be inlined across +/// crates when that's profitable as long as any form of LTO is used. When LTO is disabled, +/// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates +/// might intend for most of the methods in their public API to be able to be inlined across +/// crates even when LTO is disabled. For these types of crates, enabling this lint might make sense. +/// It allows the crate to require all exported methods to be `#[inline]` by default, and then opt +/// out for specific methods where this might not make sense. +/// +/// **Known problems:** None. +declare_clippy_lint! { + pub MISSING_INLINE_IN_PUBLIC_ITEMS, + restriction, + "detects missing #[inline] attribute for public callables (functions, trait methods, methods...)" +} + +pub struct MissingInline {} + +impl ::std::default::Default for MissingInline { + fn default() -> Self { + Self::new() + } +} + +impl MissingInline { + pub fn new() -> Self { + Self {} + } + + fn check_missing_inline_attrs(&self, cx: &LateContext, + attrs: &[ast::Attribute], sp: Span, desc: &'static str) { + // If we're building a test harness, FIXME: is this relevant? + // if cx.sess().opts.test { + // return; + // } + + let has_inline = attrs + .iter() + .any(|a| a.name() == "inline" ); + if !has_inline { + cx.span_lint( + MISSING_INLINE_IN_PUBLIC_ITEMS, + sp, + &format!("missing `#[inline]` for {}", desc), + ); + } + } +} + +impl LintPass for MissingInline { + fn get_lints(&self) -> LintArray { + lint_array![MISSING_INLINE_IN_PUBLIC_ITEMS] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) { + if !cx.access_levels.is_exported(it.id) { + return; + } + match it.node { + hir::ItemFn(..) => { + // ignore main() + if it.name == "main" { + let def_id = cx.tcx.hir.local_def_id(it.id); + let def_key = cx.tcx.hir.def_key(def_id); + if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { + return; + } + } + let desc = "a function"; + self.check_missing_inline_attrs(cx, &it.attrs, it.span, desc); + }, + hir::ItemTrait(ref _is_auto, ref _unsafe, ref _generics, + ref _bounds, ref trait_items) => { + for tit in trait_items { + let tit_ = cx.tcx.hir.trait_item(tit.id); + match tit_.node { + hir::TraitItemKind::Const(..) | + hir::TraitItemKind::Type(..) => {}, + hir::TraitItemKind::Method(..) => { + if tit.defaultness.has_value() { + // trait method with default body needs inline in case + // an impl is not provided + let desc = "a default trait method"; + let item = cx.tcx.hir.expect_trait_item(tit.id.node_id); + self.check_missing_inline_attrs(cx, &item.attrs, + item.span, desc); + } + }, + } + } + } + hir::ItemConst(..) | + hir::ItemEnum(..) | + hir::ItemMod(..) | + hir::ItemStatic(..) | + hir::ItemStruct(..) | + hir::ItemTraitAlias(..) | + hir::ItemGlobalAsm(..) | + hir::ItemTy(..) | + hir::ItemUnion(..) | + hir::ItemExistential(..) | + hir::ItemExternCrate(..) | + hir::ItemForeignMod(..) | + hir::ItemImpl(..) | + hir::ItemUse(..) => {}, + }; + } + + fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { + use rustc::ty::{TraitContainer, ImplContainer}; + + // If the item being implemented is not exported, then we don't need #[inline] + if !cx.access_levels.is_exported(impl_item.id) { + return; + } + + let def_id = cx.tcx.hir.local_def_id(impl_item.id); + match cx.tcx.associated_item(def_id).container { + TraitContainer(cid) => { + let n = cx.tcx.hir.as_local_node_id(cid); + if n.is_some() { + if !cx.access_levels.is_exported(n.unwrap()) { + // If a trait is being implemented for an item, and the + // trait is not exported, we don't need #[inline] + return; + } + } + }, + ImplContainer(cid) => { + if cx.tcx.impl_trait_ref(cid).is_some() { + let trait_ref = cx.tcx.impl_trait_ref(cid).unwrap(); + let n = cx.tcx.hir.as_local_node_id(trait_ref.def_id); + if n.is_some() { + if !cx.access_levels.is_exported(n.unwrap()) { + // If a trait is being implemented for an item, and the + // trait is not exported, we don't need #[inline] + return; + } + } + } + }, + } + + let desc = match impl_item.node { + hir::ImplItemKind::Method(..) => "a method", + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Type(_) => return, + }; + self.check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); + } +} diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs new file mode 100644 index 00000000000..5dc473ef09d --- /dev/null +++ b/tests/ui/missing_inline.rs @@ -0,0 +1,72 @@ +/* This file incorporates work covered by the following copyright and + * permission notice: + * Copyright 2013 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 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ +#![warn(missing_inline_in_public_items)] + +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. +#![allow(dead_code, non_snake_case)] + +type Typedef = String; +pub type PubTypedef = String; + +struct Foo {} // ok +pub struct PubFoo { } // ok +enum FooE {} // ok +pub enum PubFooE {} // ok + +mod module {} // ok +pub mod pub_module {} // ok + +fn foo() {} +pub fn pub_foo() {} // missing #[inline] +#[inline] pub fn pub_foo_inline() {} // ok +#[inline(always)] pub fn pub_foo_inline_always() {} // ok + +#[allow(missing_inline_in_public_items)] +pub fn pub_foo_no_inline() {} +fn main() {} + +trait Bar { + fn Bar_a(); // ok + fn Bar_b() {} // ok +} + +pub trait PubBar { + fn PubBar_a(); // ok + fn PubBar_b() {} // missing #[inline] + #[inline] fn PubBar_c() {} // ok +} + +// none of these need inline because Foo is not exported +impl PubBar for Foo { + fn PubBar_a() {} // ok + fn PubBar_b() {} // ok + fn PubBar_c() {} // ok +} + +// all of these need inline because PubFoo is exported +impl PubBar for PubFoo { + fn PubBar_a() {} // missing #[inline] + fn PubBar_b() {} // missing #[inline] + fn PubBar_c() {} // missing #[inline] +} + +// do not need inline because Foo is not exported +impl Foo { + fn FooImpl() {} // ok +} + +// need inline because PubFoo is exported +impl PubFoo { + pub fn PubFooImpl() {} // missing #[inline] +} diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr new file mode 100644 index 00000000000..fe343742708 --- /dev/null +++ b/tests/ui/missing_inline.stderr @@ -0,0 +1,40 @@ +error: missing `#[inline]` for a function + --> $DIR/missing_inline.rs:31:1 + | +31 | pub fn pub_foo() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D missing-inline-in-public-items` implied by `-D warnings` + +error: missing `#[inline]` for a default trait method + --> $DIR/missing_inline.rs:46:5 + | +46 | fn PubBar_b() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^ + +error: missing `#[inline]` for a method + --> $DIR/missing_inline.rs:59:5 + | +59 | fn PubBar_a() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^ + +error: missing `#[inline]` for a method + --> $DIR/missing_inline.rs:60:5 + | +60 | fn PubBar_b() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^ + +error: missing `#[inline]` for a method + --> $DIR/missing_inline.rs:61:5 + | +61 | fn PubBar_c() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^ + +error: missing `#[inline]` for a method + --> $DIR/missing_inline.rs:71:5 + | +71 | pub fn PubFooImpl() {} // missing #[inline] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From 999a00bf5e70ac2be1af21feb02ec8af02a5d2d3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 4 Jul 2018 15:32:55 +0200 Subject: address reviews --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/missing_inline.rs | 73 ++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9d0a0c3741b..98258189701 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -365,7 +365,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box let_if_seq::LetIfSeq); reg.register_late_lint_pass(box eval_order_dependence::EvalOrderDependence); reg.register_late_lint_pass(box missing_doc::MissingDoc::new()); - reg.register_late_lint_pass(box missing_inline::MissingInline::new()); + reg.register_late_lint_pass(box missing_inline::MissingInline); reg.register_late_lint_pass(box ok_if_let::Pass); reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass); reg.register_late_lint_pass(box partialeq_ne_impl::Pass); diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index ddd44ba7fa1..ba4c7678d6c 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -26,32 +26,50 @@ use syntax::codemap::Span; /// out for specific methods where this might not make sense. /// /// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// pub fn foo() {} // missing #[inline] +/// fn ok() {} // ok +/// #[inline] pub fn bar() {} // ok +/// #[inline(always)] pub fn baz() {} // ok +/// +/// pub trait Bar { +/// fn bar(); // ok +/// fn def_bar() {} // missing #[inline] +/// } +/// +/// struct Baz; +/// impl Baz { +/// fn priv() {} // ok +/// } +/// +/// impl Bar for Baz { +/// fn bar() {} // ok - Baz is not exported +/// } +/// +/// pub struct PubBaz; +/// impl PubBaz { +/// fn priv() {} // ok +/// pub not_ptriv() {} // missing #[inline] +/// } +/// +/// impl Bar for PubBaz { +/// fn bar() {} // missing #[inline] +/// fn def_bar() {} // missing #[inline] +/// } +/// ``` declare_clippy_lint! { pub MISSING_INLINE_IN_PUBLIC_ITEMS, restriction, "detects missing #[inline] attribute for public callables (functions, trait methods, methods...)" } -pub struct MissingInline {} - -impl ::std::default::Default for MissingInline { - fn default() -> Self { - Self::new() - } -} +pub struct MissingInline; impl MissingInline { - pub fn new() -> Self { - Self {} - } - fn check_missing_inline_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { - // If we're building a test harness, FIXME: is this relevant? - // if cx.sess().opts.test { - // return; - // } - let has_inline = attrs .iter() .any(|a| a.name() == "inline" ); @@ -91,6 +109,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }, hir::ItemTrait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, ref trait_items) => { + // note: we need to check if the trait is exported so we can't use + // `LateLintPass::check_trait_item` here. for tit in trait_items { let tit_ = cx.tcx.hir.trait_item(tit.id); match tit_.node { @@ -134,12 +154,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { return; } + let desc = match impl_item.node { + hir::ImplItemKind::Method(..) => "a method", + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Type(_) => return, + }; + let def_id = cx.tcx.hir.local_def_id(impl_item.id); match cx.tcx.associated_item(def_id).container { TraitContainer(cid) => { - let n = cx.tcx.hir.as_local_node_id(cid); - if n.is_some() { - if !cx.access_levels.is_exported(n.unwrap()) { + if let Some(n) = cx.tcx.hir.as_local_node_id(cid) { + if !cx.access_levels.is_exported(n) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; @@ -149,9 +174,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { ImplContainer(cid) => { if cx.tcx.impl_trait_ref(cid).is_some() { let trait_ref = cx.tcx.impl_trait_ref(cid).unwrap(); - let n = cx.tcx.hir.as_local_node_id(trait_ref.def_id); - if n.is_some() { - if !cx.access_levels.is_exported(n.unwrap()) { + if let Some(n) = cx.tcx.hir.as_local_node_id(trait_ref.def_id) { + if !cx.access_levels.is_exported(n) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; @@ -161,11 +185,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }, } - let desc = match impl_item.node { - hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(_) => return, - }; self.check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); } } -- cgit 1.4.1-3-g733a5 From 14cbdf2607faafd608ea94234456c509e058e291 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 4 Jul 2018 16:39:52 +0200 Subject: do not apply lint to executable crate type --- clippy_lints/src/missing_inline.rs | 26 ++++++++++++++++++-------- tests/ui/missing_inline.rs | 4 ++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index ba4c7678d6c..5d17c921cc0 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -83,6 +83,17 @@ impl MissingInline { } } +fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool { + use rustc::session::config::CrateType; + + cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| { + match t { + CrateType::CrateTypeExecutable => true, + _ => false, + } + }) +} + impl LintPass for MissingInline { fn get_lints(&self) -> LintArray { lint_array![MISSING_INLINE_IN_PUBLIC_ITEMS] @@ -91,19 +102,15 @@ impl LintPass for MissingInline { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) { + if is_executable(cx) { + return; + } + if !cx.access_levels.is_exported(it.id) { return; } match it.node { hir::ItemFn(..) => { - // ignore main() - if it.name == "main" { - let def_id = cx.tcx.hir.local_def_id(it.id); - let def_key = cx.tcx.hir.def_key(def_id); - if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { - return; - } - } let desc = "a function"; self.check_missing_inline_attrs(cx, &it.attrs, it.span, desc); }, @@ -148,6 +155,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { use rustc::ty::{TraitContainer, ImplContainer}; + if is_executable(cx) { + return; + } // If the item being implemented is not exported, then we don't need #[inline] if !cx.access_levels.is_exported(impl_item.id) { diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 5dc473ef09d..38f59033071 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -11,7 +11,7 @@ * except according to those terms. */ #![warn(missing_inline_in_public_items)] - +#![crate_type = "dylib"] // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. #![allow(dead_code, non_snake_case)] @@ -34,13 +34,13 @@ pub fn pub_foo() {} // missing #[inline] #[allow(missing_inline_in_public_items)] pub fn pub_foo_no_inline() {} -fn main() {} trait Bar { fn Bar_a(); // ok fn Bar_b() {} // ok } + pub trait PubBar { fn PubBar_a(); // ok fn PubBar_b() {} // missing #[inline] -- cgit 1.4.1-3-g733a5 From 3fec3b47b637fddaa796e89576798a4fa5b5fbff Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 5 Jul 2018 01:53:40 +0200 Subject: refactor function --- clippy_lints/src/missing_inline.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 5d17c921cc0..7b13aee9a55 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -67,19 +67,17 @@ declare_clippy_lint! { pub struct MissingInline; -impl MissingInline { - fn check_missing_inline_attrs(&self, cx: &LateContext, - attrs: &[ast::Attribute], sp: Span, desc: &'static str) { - let has_inline = attrs - .iter() - .any(|a| a.name() == "inline" ); - if !has_inline { - cx.span_lint( - MISSING_INLINE_IN_PUBLIC_ITEMS, - sp, - &format!("missing `#[inline]` for {}", desc), - ); - } +fn check_missing_inline_attrs(cx: &LateContext, + attrs: &[ast::Attribute], sp: Span, desc: &'static str) { + let has_inline = attrs + .iter() + .any(|a| a.name() == "inline" ); + if !has_inline { + cx.span_lint( + MISSING_INLINE_IN_PUBLIC_ITEMS, + sp, + &format!("missing `#[inline]` for {}", desc), + ); } } @@ -112,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { match it.node { hir::ItemFn(..) => { let desc = "a function"; - self.check_missing_inline_attrs(cx, &it.attrs, it.span, desc); + check_missing_inline_attrs(cx, &it.attrs, it.span, desc); }, hir::ItemTrait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, ref trait_items) => { @@ -129,7 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { // an impl is not provided let desc = "a default trait method"; let item = cx.tcx.hir.expect_trait_item(tit.id.node_id); - self.check_missing_inline_attrs(cx, &item.attrs, + check_missing_inline_attrs(cx, &item.attrs, item.span, desc); } }, @@ -195,6 +193,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }, } - self.check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); + check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); } } -- cgit 1.4.1-3-g733a5 From d95d6516b4aef52b3556bd61afe33e9f37bcd2df Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 5 Jul 2018 11:37:50 +0100 Subject: Consistently call it "Clippy", not clippy or rust-clippy As per discussion on the Clippy 1.0 RFC --- CONTRIBUTING.md | 8 ++++---- PUBLISH.md | 2 +- README.md | 30 +++++++++++++++--------------- build.rs | 8 ++++---- util/lintlib.py | 2 +- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09f4f34b98d..d29aa80160c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to rust-clippy +# Contributing to Clippy Hello fellow Rustacean! Great to see your interest in compiler internals and lints! @@ -63,7 +63,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us ## Writing code -Compiling clippy from scratch can take almost a minute or more depending on your machine. +Compiling Clippy from scratch can take almost a minute or more depending on your machine. However, since Rust 1.24.0 incremental compilation is enabled by default and compile times for small changes should be quick. [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer @@ -74,7 +74,7 @@ of this. ### Author lint -There is also the internal `author` lint to generate clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. +There is also the internal `author` lint to generate Clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. First, create a new UI test file in the `tests/ui/` directory with the pattern you want to match: @@ -148,7 +148,7 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running ### Testing manually Manually testing against an example file is useful if you have added some -`println!`s and test suite output becomes unreadable. To try clippy with your +`println!`s and test suite output becomes unreadable. To try Clippy with your local modifications, run `cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. diff --git a/PUBLISH.md b/PUBLISH.md index a9496d5b414..b85605dc3b3 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -1,4 +1,4 @@ -Steps to publish a new clippy version +Steps to publish a new Clippy version - Bump `package.version` in `./Cargo.toml` (no need to manually bump `dependencies.clippy_lints.version`). - Write a changelog entry. diff --git a/README.md b/README.md index f2121e13ffd..5bd3981260e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in clippy. Please leave your thoughts on the RFC PR. +We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in Clippy. Please leave your thoughts on the RFC PR. -# rust-clippy +# Clippy [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) @@ -11,7 +11,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g [There are 273 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) -We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you: +We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: * `clippy` (everything that has no false positives) * `clippy_pedantic` (everything) @@ -33,11 +33,11 @@ Table of contents: ## Usage Since this is a tool for helping the developer of a library or application -write better code, it is recommended not to include clippy as a hard dependency. +write better code, it is recommended not to include Clippy as a hard dependency. Options include using it as an optional dependency, as a cargo subcommand, or as an included feature during build. All of these options are detailed below. -As a general rule clippy will only work with the *latest* Rust nightly for now. +As a general rule Clippy will only work with the *latest* Rust nightly for now. To install Rust nightly, the recommended way is to use [rustup](https://rustup.rs/): @@ -47,7 +47,7 @@ rustup install nightly ### As a cargo subcommand (`cargo clippy`) -One way to use clippy is by installing clippy through cargo as a cargo +One way to use Clippy is by installing Clippy through cargo as a cargo subcommand. ```terminal @@ -56,7 +56,7 @@ cargo +nightly install clippy (The `+nightly` is not necessary if your default `rustup` install is nightly) -Now you can run clippy by invoking `cargo +nightly clippy`. +Now you can run Clippy by invoking `cargo +nightly clippy`. To update the subcommand together with the latest nightly use the [rust-update](rust-update) script or run: @@ -66,16 +66,16 @@ cargo +nightly install --force clippy ``` In case you are not using rustup, you need to set the environment flag -`SYSROOT` during installation so clippy knows where to find `librustc` and +`SYSROOT` during installation so Clippy knows where to find `librustc` and similar crates. ```terminal SYSROOT=/path/to/rustc/sysroot cargo install clippy ``` -### Running clippy from the command line without installing it +### Running Clippy from the command line without installing it -To have cargo compile your crate with clippy without clippy installation +To have cargo compile your crate with Clippy without Clippy installation in your code, you can use: ```terminal @@ -83,7 +83,7 @@ cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` *[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* -Be sure that clippy was compiled with the same version of rustc that cargo invokes here! +Be sure that Clippy was compiled with the same version of rustc that cargo invokes here! ## Configuration @@ -117,7 +117,7 @@ You can add options to `allow`/`warn`/`deny`: Note: `deny` produces errors instead of warnings. For convenience, `cargo clippy` automatically defines a `cargo-clippy` -feature. This lets you set lint levels and compile with or without clippy +feature. This lets you set lint levels and compile with or without Clippy transparently: ```rust @@ -126,12 +126,12 @@ transparently: ## Updating rustc -Sometimes, rustc moves forward without clippy catching up. Therefore updating -rustc may leave clippy a non-functional state until we fix the resulting +Sometimes, rustc moves forward without Clippy catching up. Therefore updating +rustc may leave Clippy a non-functional state until we fix the resulting breakage. You can use the [rust-update](rust-update) script to update rustc only if -clippy would also update correctly. +Clippy would also update correctly. ## License diff --git a/build.rs b/build.rs index 241c8579a48..9d05678f718 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,8 @@ -//! This build script ensures that clippy is not compiled with an +//! This build script ensures that Clippy is not compiled with an //! incompatible version of rust. It will panic with a descriptive //! error message instead. //! -//! We specifially want to ensure that clippy is only built with a +//! We specifially want to ensure that Clippy is only built with a //! rustc version that is newer or equal to the one specified in the //! `min_version.txt` file. //! @@ -63,7 +63,7 @@ fn check_rustc_version() { eprintln!( "\n{} {}", Red.bold().paint("error:"), - "clippy requires a nightly version of Rust." + "Clippy requires a nightly version of Rust." ); print_version_err(¤t_version, &*current_date_str); eprintln!( @@ -80,7 +80,7 @@ fn check_rustc_version() { eprintln!( "\n{} {}", Red.bold().paint("error:"), - "clippy does not support this version of rustc nightly." + "Clippy does not support this version of rustc nightly." ); eprintln!( "> {}{}{}", diff --git a/util/lintlib.py b/util/lintlib.py index 4323ef5c3e7..00826805e16 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -44,7 +44,7 @@ def parse_lints(lints, filepath): last_comment.append(line[3:]) elif line.startswith("declare_lint!"): import sys - print "don't use `declare_lint!` in clippy, use `declare_clippy_lint!` instead" + print "don't use `declare_lint!` in Clippy, use `declare_clippy_lint!` instead" sys.exit(42) elif line.startswith("declare_clippy_lint!"): comment = False -- cgit 1.4.1-3-g733a5 From 28daee4c919dd88772847ec5240eb850bb0dcbf3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 3 Jul 2018 18:23:21 +0200 Subject: Rustup --- Cargo.toml | 34 +++++++++++++++++++++++++++++++++- clippy_lints/src/lifetimes.rs | 21 ++++++++++++++------- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dea7f3644c7..2dd71828136 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,41 @@ semver = "0.9" # Not actually needed right now but required to make sure that clippy/ and cargo build # with the same set of features in rust-lang/rust num-traits = "0.2" # enable the default feature -winapi = "0.3" backtrace = "0.3" +# keep in sync with `cargo`'s `Cargo.toml' +[target.'cfg(windows)'.dependencies.winapi] +version = "0.3" +features = [ + # keep in sync with `cargo`'s `Cargo.toml' + "handleapi", + "jobapi", + "jobapi2", + "minwindef", + "ntdef", + "ntstatus", + "processenv", + "processthreadsapi", + "psapi", + "synchapi", + "winerror", + "winbase", + "wincon", + "winnt", + # no idea where these come from + "lmcons", + "minschannel", + "minwinbase", + "ntsecapi", + "profileapi", + "schannel", + "securitybaseapi", + "synchapi", + "sysinfoapi", + "timezoneapi", + "wincrypt", +] + [dev-dependencies] cargo_metadata = "0.5" compiletest_rs = "0.3.7" diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index efa50a8f743..605182c007a 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -342,16 +342,23 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { self.record(&None); }, TyPath(ref path) => { - self.collect_anonymous_lifetimes(path, ty); - }, - TyImplTraitExistential(exist_ty_id, _, _) => { - if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node { - for bound in &exist_ty.bounds { - if let GenericBound::Outlives(_) = *bound { - self.record(&None); + if let QPath::Resolved(_, ref path) = *path { + if let Def::Existential(def_id) = path.def { + let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap(); + if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node { + for bound in &exist_ty.bounds { + if let GenericBound::Outlives(_) = *bound { + self.record(&None); + } + } + } else { + unreachable!() } + walk_ty(self, ty); + return; } } + self.collect_anonymous_lifetimes(path, ty); } TyTraitObject(ref bounds, ref lt) => { if !lt.is_elided() { -- cgit 1.4.1-3-g733a5 From 6d9d3bac1dd73641a145534b32d5454815a573c0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Jul 2018 11:16:36 +1200 Subject: Add some more winapi features --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 2dd71828136..d0f1ebdd1da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,9 @@ features = [ "wincon", "winnt", # no idea where these come from + "basetsd", "lmcons", + "memoryapi", "minschannel", "minwinbase", "ntsecapi", -- cgit 1.4.1-3-g733a5 From d914106d871050f84f465fc906b9b7b431d828ce Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 6 Jul 2018 23:23:19 -0700 Subject: Bump to 0.0.212 --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b2d2082a7a..34f826527bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.212 +* Rustup to *rustc 1.29.0-nightly (e06c87544 2018-07-06)* + ## 0.0.211 * Rustup to *rustc 1.28.0-nightly (e3bf634e0 2018-06-28)* diff --git a/Cargo.toml b/Cargo.toml index d0f1ebdd1da..7c9fe251237 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["edition"] [package] name = "clippy" -version = "0.0.211" +version = "0.0.212" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -40,7 +40,7 @@ path = "src/driver.rs" [dependencies] # begin automatic update -clippy_lints = { version = "0.0.211", path = "clippy_lints" } +clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e7ad3b1b759..3015dc40685 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -3,7 +3,7 @@ cargo-features = ["edition"] [package] name = "clippy_lints" # begin automatic update -version = "0.0.211" +version = "0.0.212" # end automatic update authors = [ "Manish Goregaokar ", -- cgit 1.4.1-3-g733a5 From 60af4a8e13a054e177461a75d254aff11cc482a3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 8 Jul 2018 08:03:11 +0200 Subject: Remove duplication in missing_inline --- clippy_lints/src/missing_inline.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 7b13aee9a55..6987eaa71d9 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -169,28 +169,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }; let def_id = cx.tcx.hir.local_def_id(impl_item.id); - match cx.tcx.associated_item(def_id).container { - TraitContainer(cid) => { - if let Some(n) = cx.tcx.hir.as_local_node_id(cid) { - if !cx.access_levels.is_exported(n) { - // If a trait is being implemented for an item, and the - // trait is not exported, we don't need #[inline] - return; - } - } - }, - ImplContainer(cid) => { - if cx.tcx.impl_trait_ref(cid).is_some() { - let trait_ref = cx.tcx.impl_trait_ref(cid).unwrap(); - if let Some(n) = cx.tcx.hir.as_local_node_id(trait_ref.def_id) { - if !cx.access_levels.is_exported(n) { - // If a trait is being implemented for an item, and the - // trait is not exported, we don't need #[inline] - return; - } - } + let trait_def_id = match cx.tcx.associated_item(def_id).container { + TraitContainer(cid) => Some(cid), + ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id), + }; + + if let Some(trait_def_id) = trait_def_id { + if let Some(n) = cx.tcx.hir.as_local_node_id(trait_def_id) { + if !cx.access_levels.is_exported(n) { + // If a trait is being implemented for an item, and the + // trait is not exported, we don't need #[inline] + return; } - }, + } } check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); -- cgit 1.4.1-3-g733a5 From 40151d91af6539087383038e0cc95ea7ce3b9b91 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 11 Jul 2018 07:59:37 +0200 Subject: Add rust-toolchain file Using `nightly` means that the latest available nightly version will be used when cd'ing to a clippy checkout. --- PUBLISH.md | 1 + rust-toolchain | 1 + 2 files changed, 2 insertions(+) create mode 100644 rust-toolchain diff --git a/PUBLISH.md b/PUBLISH.md index b85605dc3b3..749eae97304 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -2,6 +2,7 @@ Steps to publish a new Clippy version - Bump `package.version` in `./Cargo.toml` (no need to manually bump `dependencies.clippy_lints.version`). - Write a changelog entry. +- If a nightly update is needed, update `min_version.txt` using `rustc -vV > min_version.txt` - Run `./pre_publish.sh` - Review and commit all changed files - `git push` diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000000..bf867e0ae5b --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly -- cgit 1.4.1-3-g733a5 From 1e9f076254c0f451997bfa8ee028b2d0e8436a92 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 15 Jul 2018 00:00:27 +0200 Subject: Ignore spans when comparing expressions --- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- .../src/if_let_redundant_pattern_matching.rs | 18 ++++++++------ clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/map_clone.rs | 10 ++++---- clippy_lints/src/matches.rs | 13 +++++++--- clippy_lints/src/methods.rs | 20 +++++++++------- clippy_lints/src/misc.rs | 6 ++--- clippy_lints/src/misc_early.rs | 11 +++++---- clippy_lints/src/overflow_check_conditional.rs | 7 +++--- clippy_lints/src/ranges.rs | 4 ++-- clippy_lints/src/utils/hir_utils.rs | 28 +++++++++++++++++----- clippy_lints/src/utils/internal_lints.rs | 14 ++++++----- 13 files changed, 86 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 9a0263f2f68..e90dc6f693a 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { impl EnumGlobUse { fn lint_item(&self, cx: &LateContext, item: &Item) { - if item.vis.node == VisibilityKind::Public { + if item.vis.node.is_pub() { return; // re-exports are fine } if let ItemUse(ref path, UseKind::Glob) = item.node { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index a200383b41d..d272cab0a0d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -262,7 +262,7 @@ impl EarlyLintPass for EnumVariantNames { ); } } - if item.vis.node == VisibilityKind::Public { + if item.vis.node.is_pub() { let matching = partial_match(mod_camel, &item_camel); let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 92b2bab3ba8..78b21478d88 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -48,13 +48,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { if arms[0].pats.len() == 1 { let good_method = match arms[0].pats[0].node { - PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => { - if match_qpath(path, &paths::RESULT_OK) { - "is_ok()" - } else if match_qpath(path, &paths::RESULT_ERR) { - "is_err()" - } else if match_qpath(path, &paths::OPTION_SOME) { - "is_some()" + PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { + if let PatKind::Wild = pats[0].node { + if match_qpath(path, &paths::RESULT_OK) { + "is_ok()" + } else if match_qpath(path, &paths::RESULT_ERR) { + "is_err()" + } else if match_qpath(path, &paths::OPTION_SOME) { + "is_some()" + } else { + return; + } } else { return; } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8b7032893d8..963a8da49cb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -23,7 +23,7 @@ use crate::consts::{constant, Constant}; use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, - span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; + span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq}; use crate::utils::paths; /// **What it does:** Checks for for-loops that manually copy items between @@ -1955,7 +1955,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if self.state == VarState::DontWarn { return; } - if expr == self.end_expr { + if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) { self.past_loop = true; return; } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 5ea873e31e1..0d58732f24d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::ty; use syntax::ast; use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, - paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; + paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if clone_call.ident.name == "clone" && clone_args.len() == 1 && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(&clone_args[0], arg_ident) + expr_eq_name(cx, &clone_args[0], arg_ident) { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ @@ -98,7 +98,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool { +fn expr_eq_name(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprPath(QPath::Resolved(None, ref path)) => { let arg_segment = [ @@ -108,7 +108,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool { infer_types: true, }, ]; - !path.is_global() && path.segments[..] == arg_segment + !path.is_global() && SpanlessEq::new(cx).eq_path_segments(&path.segments[..], &arg_segment) }, _ => false, } @@ -127,7 +127,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), - _ => expr_eq_name(expr, id), + _ => expr_eq_name(cx, expr, id), } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 207343c92c6..a14c6a0d8b9 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -221,7 +221,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { - if arms[1].pats[0].node == PatKind::Wild { + if is_wild(&arms[1].pats[0]) { report_single_match_single_pattern(cx, ex, arms, expr, els); } } @@ -265,7 +265,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: let path = match arms[1].pats[0].node { PatKind::TupleStruct(ref path, ref inner, _) => { // contains any non wildcard patterns? e.g. Err(err) - if inner.iter().any(|pat| pat.node != PatKind::Wild) { + if !inner.iter().all(is_wild) { return; } print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) @@ -356,6 +356,13 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr, } } +fn is_wild(pat: &impl std::ops::Deref) -> bool { + match pat.node { + PatKind::Wild => true, + _ => false, + } +} + fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); if match_type(cx, ex_ty, &paths::RESULT) { @@ -364,7 +371,7 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)); if_chain! { if path_str == "Err"; - if inner.iter().any(|pat| pat.node == PatKind::Wild); + if inner.iter().any(is_wild); if let ExprBlock(ref block, _) = arm.body.node; if is_panic_block(block); then { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 1d1d0ef8faa..ca739558e62 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -10,7 +10,7 @@ use syntax::codemap::{Span, BytePos}; use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, - span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; + span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; use crate::utils::paths; use crate::utils::sugg; use crate::consts::{constant, Constant}; @@ -820,8 +820,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if name == method_name && sig.decl.inputs.len() == n_args && - out_type.matches(&sig.decl.output) && - self_kind.matches(first_arg_ty, first_arg, self_ty, false, &implitem.generics) { + out_type.matches(cx, &sig.decl.output) && + self_kind.matches(cx, first_arg_ty, first_arg, self_ty, false, &implitem.generics) { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); @@ -838,9 +838,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if conv.check(&name.as_str()); if !self_kinds .iter() - .any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); + .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); then { - let lint = if item.vis.node == hir::VisibilityKind::Public { + let lint = if item.vis.node.is_pub() { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION @@ -2030,6 +2030,7 @@ enum SelfKind { impl SelfKind { fn matches( self, + cx: &LateContext, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, @@ -2047,7 +2048,7 @@ impl SelfKind { // `Self`, `&mut Self`, // and `Box`, including the equivalent types with `Foo`. - let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty; + let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty); if is_self(arg) { match self { SelfKind::Value => is_actually_self(ty), @@ -2173,12 +2174,13 @@ enum OutType { } impl OutType { - fn matches(self, ty: &hir::FunctionRetTy) -> bool { + fn matches(self, cx: &LateContext, ty: &hir::FunctionRetTy) -> bool { + let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyTup(vec![].into())); match (self, ty) { (OutType::Unit, &hir::DefaultReturn(_)) => true, - (OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true, + (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, - (OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true, + (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)), _ => false, } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 697f15bdd1d..4fc65b2f89a 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -6,7 +6,7 @@ use rustc::ty; use syntax::codemap::{ExpnFormat, Span}; use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, - span_lint_and_then, walk_ptrs_ty}; + span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; use syntax::ast::{LitKind, CRATE_NODE_ID}; use crate::consts::{constant, Constant}; @@ -418,7 +418,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(_, _, ident, Some(ref right)) = pat.node { - if right.node == PatKind::Wild { + if let PatKind::Wild = right.node { span_lint( cx, REDUNDANT_PATTERN, @@ -542,7 +542,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), _ => is_used(cx, parent), } } else { diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 87e4d343ab4..e527a05c851 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -213,7 +213,7 @@ impl EarlyLintPass for MiscEarly { .name; for field in pfields { - if field.node.pat.node == PatKind::Wild { + if let PatKind::Wild = field.node.pat.node { wilds += 1; } } @@ -231,14 +231,15 @@ impl EarlyLintPass for MiscEarly { let mut normal = vec![]; for field in pfields { - if field.node.pat.node != PatKind::Wild { - if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { + match field.node.pat.node { + PatKind::Wild => {}, + _ => if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { normal.push(n); - } + }, } } for field in pfields { - if field.node.pat.node == PatKind::Wild { + if let PatKind::Wild = field.node.pat.node { wilds -= 1; if wilds > 0 { span_lint( diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 3a95471d0a2..c5b0c977956 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use crate::utils::span_lint; +use crate::utils::{span_lint, SpanlessEq}; /// **What it does:** Detects classic underflow/overflow checks. /// @@ -31,13 +31,14 @@ impl LintPass for OverflowCheckConditional { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r); if_chain! { if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node; if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node; if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node; - if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0]; + if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); then { @@ -62,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node; - if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0]; + if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); then { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 6ec624d26e9..c0fac47b34e 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use syntax::ast::RangeLimits; use syntax::codemap::Spanned; use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; -use crate::utils::{get_trait_def_id, higher, implements_trait}; +use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::sugg::Sugg; /// **What it does:** Checks for calling `.step_by(0)` on iterators, @@ -118,7 +118,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // .iter() and .len() called on same Path if let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; if let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node; - if iter_path.segments == len_path.segments; + if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments); then { span_lint(cx, RANGE_ZIP_WITH_LEN, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index f95fb046b49..1f6092789e5 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }) }, (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { - !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) + !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) }, (&ExprRepeat(ref le, ref ll_id), &ExprRepeat(ref re, ref rl_id)) => { let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); @@ -225,7 +225,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool { + pub fn eq_path_segments(&mut self, left: &[PathSegment], right: &[PathSegment]) -> bool { + left.len() == right.len() && left.iter().zip(right).all(|(l, r)| self.eq_path_segment(l, r)) + } + + pub fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene if left.ident.as_str() != right.ident.as_str() { @@ -238,8 +242,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } - fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { - match (&left.node, &right.node) { + pub fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { + self.eq_ty_kind(&left.node, &right.node) + } + + pub fn eq_ty_kind(&mut self, left: &Ty_, right: &Ty_) -> bool { + match (left, right) { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyArray(ref lt, ref ll_id), &TyArray(ref rt, ref rl_id)) => { let full_table = self.tables; @@ -336,7 +344,12 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } - b.rules.hash(&mut self.s); + match b.rules { + BlockCheckMode::DefaultBlock => 0, + BlockCheckMode::UnsafeBlock(_) => 1, + BlockCheckMode::PushUnsafeBlock(_) => 2, + BlockCheckMode::PopUnsafeBlock(_) => 3, + }.hash(&mut self.s); } #[allow(many_single_char_names)] @@ -419,7 +432,10 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { ExprClosure(cap, _, eid, _, _) => { let c: fn(_, _, _, _, _) -> _ = ExprClosure; c.hash(&mut self.s); - cap.hash(&mut self.s); + match cap { + CaptureClause::CaptureByValue => 0, + CaptureClause::CaptureByRef => 1, + }.hash(&mut self.s); self.hash_expr(&self.cx.tcx.hir.body(eid).value); }, ExprField(ref e, ref f) => { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index f0e3961600c..ef26b77ea1a 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -120,12 +120,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { if let ItemStatic(ref ty, MutImmutable, body_id) = item.node { if is_lint_ref_type(ty) { self.declared_lints.insert(item.name, item.span); - } else if is_lint_array_type(ty) && item.vis.node == VisibilityKind::Inherited && item.name == "ARRAY" { - let mut collector = LintCollector { - output: &mut self.registered_lints, - cx, - }; - collector.visit_expr(&cx.tcx.hir.body(body_id).value); + } else if is_lint_array_type(ty) && item.name == "ARRAY" { + if let VisibilityKind::Inherited = item.vis.node { + let mut collector = LintCollector { + output: &mut self.registered_lints, + cx, + }; + collector.visit_expr(&cx.tcx.hir.body(body_id).value); + } } } } -- cgit 1.4.1-3-g733a5 From 5e085e43104f6748a9717bb78de8b634712638b4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 15 Jul 2018 02:04:23 +0200 Subject: Remove use of ty_to_def_id --- clippy_lints/src/len_zero.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 33930ab58db..c1ec7a16296 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -258,11 +258,10 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::TyDynamic(..) => cx.tcx - .associated_items(ty.ty_to_def_id().expect("trait impl not found")) + ty::TyDynamic(ref tt, ..) => cx.tcx + .associated_items(tt.principal().expect("trait impl not found").def_id()) .any(|item| is_is_empty(cx, &item)), - ty::TyProjection(_) => ty.ty_to_def_id() - .map_or(false, |id| has_is_empty_impl(cx, id)), + ty::TyProjection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did), ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true, _ => false, -- cgit 1.4.1-3-g733a5 From b90fc5edfa4b8f1954f29a47f1e124d1ed29c767 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 14 Jul 2018 12:18:50 +0200 Subject: Fix #2894 --- clippy_lints/src/use_self.rs | 117 +++++++++++++++++++++++++++++++++++++++---- tests/ui/methods.rs | 2 +- tests/ui/methods.stderr | 94 +--------------------------------- tests/ui/use_self.rs | 114 +++++++++++++++++++++++++++++++++++++++++ tests/ui/use_self.stderr | 92 +++++++++++++++++++++++++++++----- 5 files changed, 303 insertions(+), 116 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 10b69852ba5..f8d6c48390b 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,8 +1,10 @@ -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::*; -use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; use crate::utils::{in_macro, span_lint_and_then}; +use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; use syntax::ast::NodeId; +use syntax::symbol::keywords; use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a @@ -49,13 +51,93 @@ impl LintPass for UseSelf { const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; +fn span_use_self_lint(cx: &LateContext, path: &Path) { + span_lint_and_then(cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { + db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); + }); +} + +struct TraitImplTyVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + type_walker: ty::walk::TypeWalker<'tcx>, +} + +impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { + fn visit_ty(&mut self, t: &'tcx Ty) { + let trait_ty = self.type_walker.next(); + if let TyPath(QPath::Resolved(_, path)) = &t.node { + let impl_is_self_ty = if let def::Def::SelfTy(..) = path.def { + true + } else { + false + }; + if !impl_is_self_ty { + let trait_is_self_ty = if let Some(ty::TyParam(ty::ParamTy { name, .. })) = trait_ty.map(|ty| &ty.sty) { + *name == keywords::SelfType.name().as_str() + } else { + false + }; + if trait_is_self_ty { + span_use_self_lint(self.cx, path); + } + } + } + walk_ty(self, t) + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +fn check_trait_method_impl_decl<'a, 'tcx: 'a>( + cx: &'a LateContext<'a, 'tcx>, + impl_item: &ImplItem, + impl_decl: &'tcx FnDecl, + impl_trait_ref: &ty::TraitRef, +) { + let trait_method = cx + .tcx + .associated_items(impl_trait_ref.def_id) + .find(|assoc_item| { + assoc_item.kind == ty::AssociatedKind::Method + && cx + .tcx + .hygienic_eq(impl_item.ident, assoc_item.ident, impl_trait_ref.def_id) + }) + .expect("impl method matches a trait method"); + + let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); + let trait_method_sig = cx.tcx.erase_late_bound_regions(&trait_method_sig); + + let output_ty = if let FunctionRetTy::Return(ty) = &impl_decl.output { + Some(&**ty) + } else { + None + }; + + for (impl_ty, trait_ty) in impl_decl + .inputs + .iter() + .chain(output_ty) + .zip(trait_method_sig.inputs_and_output) + { + let mut visitor = TraitImplTyVisitor { + cx, + type_walker: trait_ty.walk(), + }; + + visitor.visit_ty(&impl_ty); + } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if in_macro(item.span) { return; } if_chain! { - if let ItemImpl(.., ref item_type, ref refs) = item.node; + if let ItemImpl(.., item_type, refs) = &item.node; if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; @@ -67,13 +149,32 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { } else { true }; + if should_check { let visitor = &mut UseSelfVisitor { item_path, cx, }; - for impl_item_ref in refs { - visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id)); + let impl_def_id = cx.tcx.hir.local_def_id(item.id); + let impl_trait_ref = cx.tcx.impl_trait_ref(impl_def_id); + + if let Some(impl_trait_ref) = impl_trait_ref { + for impl_item_ref in refs { + let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); + if let ImplItemKind::Method(MethodSig{ decl: impl_decl, .. }, impl_body_id) + = &impl_item.node { + check_trait_method_impl_decl(cx, impl_item, impl_decl, &impl_trait_ref); + let body = cx.tcx.hir.body(*impl_body_id); + visitor.visit_body(body); + } else { + visitor.visit_impl_item(impl_item); + } + } + } else { + for impl_item_ref in refs { + let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); + visitor.visit_impl_item(impl_item); + } } } } @@ -89,9 +190,7 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) { if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfType.name() { - span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { - db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); - }); + span_use_self_lint(self.cx, path); } walk_path(self, path); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index b42cc1f75b7..7f0da364c7a 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -4,7 +4,7 @@ #![warn(clippy, clippy_pedantic, option_unwrap_used)] #![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value, - default_trait_access)] + default_trait_access, use_self)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 01ec0895fb0..12665244b9d 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,47 +1,3 @@ -error: unnecessary structure name repetition - --> $DIR/methods.rs:21:29 - | -21 | pub fn add(self, other: T) -> T { self } - | ^ help: use the applicable keyword: `Self` - | - = note: `-D use-self` implied by `-D warnings` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:21:35 - | -21 | pub fn add(self, other: T) -> T { self } - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:25:25 - | -25 | fn eq(&self, other: T) -> bool { true } // no error, private function - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:27:26 - | -27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:27:33 - | -27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:28:21 - | -28 | fn div(self) -> T { self } // no error, different #arguments - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:29:25 - | -29 | fn rem(self, other: T) { } // no error, wrong return type - | ^ help: use the applicable keyword: `Self` - error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name --> $DIR/methods.rs:21:5 | @@ -78,30 +34,6 @@ error: methods called `new` usually return `Self` | = note: `-D new-ret-no-self` implied by `-D warnings` -error: unnecessary structure name repetition - --> $DIR/methods.rs:80:24 - | -80 | fn new() -> Option> { None } - | ^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:84:19 - | -84 | type Output = T; - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:85:25 - | -85 | fn mul(self, other: T) -> T { self } // no error, obviously - | ^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:85:31 - | -85 | fn mul(self, other: T) -> T { self } // no error, obviously - | ^ help: use the applicable keyword: `Self` - error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead --> $DIR/methods.rs:104:13 | @@ -251,24 +183,6 @@ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done mor 174 | | ); | |_________________^ -error: unnecessary structure name repetition - --> $DIR/methods.rs:200:24 - | -200 | fn filter(self) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:204:22 - | -204 | fn next(self) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - -error: unnecessary structure name repetition - --> $DIR/methods.rs:224:32 - | -224 | fn skip(self, _: usize) -> IteratorFalsePositives { - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` - error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. --> $DIR/methods.rs:234:13 | @@ -343,12 +257,6 @@ error: called `is_some()` after searching an `Iterator` with rposition. This is 276 | | ).is_some(); | |______________________________^ -error: unnecessary structure name repetition - --> $DIR/methods.rs:290:21 - | -290 | fn new() -> Foo { Foo } - | ^^^ help: use the applicable keyword: `Self` - error: use of `unwrap_or` followed by a function call --> $DIR/methods.rs:308:22 | @@ -527,5 +435,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D option-unwrap-used` implied by `-D warnings` -error: aborting due to 70 previous errors +error: aborting due to 55 previous errors diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index b12900b7691..e3133b0a7a1 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -3,6 +3,7 @@ #![warn(use_self)] #![allow(dead_code)] #![allow(should_implement_trait)] +#![allow(boxed_local)] fn main() {} @@ -66,3 +67,116 @@ mod lifetimes { } } } + +mod traits { + + #![cfg_attr(feature = "cargo-clippy", allow(boxed_local))] + + trait SelfTrait { + fn refs(p1: &Self) -> &Self; + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self; + fn mut_refs(p1: &mut Self) -> &mut Self; + fn nested(p1: Box, p2: (&u8, &Self)); + fn vals(r: Self) -> Self; + } + + #[derive(Default)] + struct Bad; + + impl SelfTrait for Bad { + fn refs(p1: &Bad) -> &Bad { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + p1 + } + + fn mut_refs(p1: &mut Bad) -> &mut Bad { + p1 + } + + fn nested(_p1: Box, _p2: (&u8, &Bad)) { + } + + fn vals(_: Bad) -> Bad { + Bad::default() + } + } + + #[derive(Default)] + struct Good; + + impl SelfTrait for Good { + fn refs(p1: &Self) -> &Self { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + p1 + } + + fn mut_refs(p1: &mut Self) -> &mut Self { + p1 + } + + fn nested(_p1: Box, _p2: (&u8, &Self)) { + } + + fn vals(_: Self) -> Self { + Self::default() + } + } + + trait NameTrait { + fn refs(p1: &u8) -> &u8; + fn ref_refs<'a>(p1: &'a &'a u8) -> &'a &'a u8; + fn mut_refs(p1: &mut u8) -> &mut u8; + fn nested(p1: Box, p2: (&u8, &u8)); + fn vals(p1: u8) -> u8; + } + + // Using `Self` instead of the type name is OK + impl NameTrait for u8 { + fn refs(p1: &Self) -> &Self { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + p1 + } + + fn mut_refs(p1: &mut Self) -> &mut Self { + p1 + } + + fn nested(_p1: Box, _p2: (&Self, &Self)) { + } + + fn vals(_: Self) -> Self { + Self::default() + } + } + + // Check that self arg isn't linted + impl Clone for Good { + fn clone(&self) -> Self { + // Note: Not linted and it wouldn't be valid + // because "can't use `Self` as a constructor` + Good + } + } +} + +mod issue2894 { + trait IntoBytes { + fn into_bytes(&self) -> Vec; + } + + // This should not be linted + impl IntoBytes for u8 { + fn into_bytes(&self) -> Vec { + vec![*self] + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index bfd334335d8..ede95126f86 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,40 +1,106 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:21 + --> $DIR/use_self.rs:15:21 | -14 | fn new() -> Foo { +15 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:15:13 + --> $DIR/use_self.rs:16:13 | -15 | Foo {} +16 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:17:22 + --> $DIR/use_self.rs:18:22 | -17 | fn test() -> Foo { +18 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:18:13 + --> $DIR/use_self.rs:19:13 | -18 | Foo::new() +19 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:25 + --> $DIR/use_self.rs:24:25 | -23 | fn default() -> Foo { +24 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:13 + --> $DIR/use_self.rs:25:13 | -24 | Foo::new() +25 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` -error: aborting due to 6 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:87:22 + | +87 | fn refs(p1: &Bad) -> &Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:87:31 + | +87 | fn refs(p1: &Bad) -> &Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:91:37 + | +91 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:91:53 + | +91 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:95:30 + | +95 | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:95:43 + | +95 | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:99:28 + | +99 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:99:46 + | +99 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:102:20 + | +102 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:102:28 + | +102 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:103:13 + | +103 | Bad::default() + | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From 1bd17e4fa2ba4bad31c15c50300c32235a715223 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 12 Jul 2018 15:30:57 +0800 Subject: ExprKind --- CONTRIBUTING.md | 6 +- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/arithmetic.rs | 4 +- clippy_lints/src/assign_ops.rs | 8 +- clippy_lints/src/attrs.rs | 8 +- clippy_lints/src/bit_mask.rs | 12 +- clippy_lints/src/block_in_if_condition.rs | 8 +- clippy_lints/src/booleans.rs | 22 +-- clippy_lints/src/bytecount.rs | 16 +- clippy_lints/src/consts.rs | 20 +-- clippy_lints/src/copies.rs | 12 +- clippy_lints/src/cyclomatic_complexity.rs | 10 +- clippy_lints/src/default_trait_access.rs | 4 +- clippy_lints/src/double_comparison.rs | 4 +- clippy_lints/src/drop_forget_ref.rs | 4 +- clippy_lints/src/duration_subsec.rs | 4 +- clippy_lints/src/entry.rs | 12 +- clippy_lints/src/eq_op.rs | 10 +- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eta_reduction.rs | 8 +- clippy_lints/src/eval_order_dependence.rs | 40 ++--- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/explicit_write.rs | 8 +- clippy_lints/src/fallible_impl_from.rs | 4 +- clippy_lints/src/format.rs | 34 ++--- clippy_lints/src/functions.rs | 8 +- clippy_lints/src/identity_conversion.rs | 10 +- clippy_lints/src/identity_op.rs | 2 +- .../src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infallible_destructuring_match.rs | 2 +- clippy_lints/src/infinite_iter.rs | 18 +-- clippy_lints/src/invalid_ref.rs | 4 +- clippy_lints/src/len_zero.rs | 4 +- clippy_lints/src/let_if_seq.rs | 12 +- clippy_lints/src/loops.rs | 152 +++++++++---------- clippy_lints/src/map_clone.rs | 12 +- clippy_lints/src/map_unit_fn.rs | 14 +- clippy_lints/src/matches.rs | 22 +-- clippy_lints/src/mem_forget.rs | 6 +- clippy_lints/src/methods.rs | 48 +++--- clippy_lints/src/minmax.rs | 4 +- clippy_lints/src/misc.rs | 22 +-- clippy_lints/src/mut_mut.rs | 4 +- clippy_lints/src/mut_reference.rs | 6 +- clippy_lints/src/needless_bool.rs | 16 +- clippy_lints/src/needless_borrow.rs | 4 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/needless_update.rs | 4 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 12 +- clippy_lints/src/neg_multiply.rs | 10 +- clippy_lints/src/no_effect.rs | 56 +++---- clippy_lints/src/non_copy_const.rs | 10 +- clippy_lints/src/ok_if_let.rs | 4 +- clippy_lints/src/open_options.rs | 8 +- clippy_lints/src/overflow_check_conditional.rs | 20 +-- clippy_lints/src/panic_unimplemented.rs | 8 +- clippy_lints/src/ptr.rs | 6 +- clippy_lints/src/question_mark.rs | 12 +- clippy_lints/src/ranges.rs | 14 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/regex.rs | 10 +- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/shadow.rs | 30 ++-- clippy_lints/src/strings.rs | 14 +- clippy_lints/src/suspicious_trait_impl.rs | 14 +- clippy_lints/src/swap.rs | 14 +- clippy_lints/src/temporary_assignment.rs | 8 +- clippy_lints/src/transmute.rs | 4 +- clippy_lints/src/types.rs | 32 ++-- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 10 +- clippy_lints/src/unused_label.rs | 4 +- clippy_lints/src/unwrap.rs | 14 +- clippy_lints/src/utils/author.rs | 76 +++++----- clippy_lints/src/utils/higher.rs | 58 +++---- clippy_lints/src/utils/hir_utils.rs | 168 ++++++++++----------- clippy_lints/src/utils/inspector.rs | 60 ++++---- clippy_lints/src/utils/mod.rs | 18 +-- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 58 +++---- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/write.rs | 66 ++++---- clippy_lints/src/zero_div_zero.rs | 2 +- tests/ui/author.stdout | 4 +- tests/ui/author/call.stdout | 8 +- tests/ui/author/for_loop.stdout | 38 ++--- tests/ui/author/matches.stout | 18 +-- tests/ui/trailing_zeros.stdout | 10 +- 90 files changed, 777 insertions(+), 777 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d29aa80160c..293418416a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,9 +93,9 @@ a `.stdout` file with the generated code: // ./tests/ui/my_lint.stdout if_chain! { - if let Expr_::ExprArray(ref elements) = stmt.node; + if let ExprKind::Array(ref elements) = stmt.node; if elements.len() == 1; - if let Expr_::ExprLit(ref lit) = elements[0].node; + if let ExprKind::Lit(ref lit) = elements[0].node; if let LitKind::Int(7, _) = lit.node; then { // report your lint here @@ -179,7 +179,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ``` The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. -Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. +Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/update_lints.py` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time. ```rust diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index d3741d78801..13e1dbe3c0a 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -63,7 +63,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprLit(ref lit) = e.node { + if let ExprKind::Lit(ref lit) = e.node { check_lit(cx, lit, e); } } diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index a9ccc336a19..3f15f955e19 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { return; } match expr.node { - hir::ExprBinary(ref op, ref l, ref r) => { + hir::ExprKind::Binary(ref op, ref l, ref r) => { match op.node { hir::BiAnd | hir::BiOr @@ -81,7 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { self.span = Some(expr.span); } }, - hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { + hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => { let ty = cx.tables.expr_ty(arg); if ty.is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index ba405610c90..15871cdfe02 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -76,7 +76,7 @@ impl LintPass for AssignOps { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprAssignOp(op, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| { let lhs = &sugg::Sugg::hir(cx, lhs, ".."); let rhs = &sugg::Sugg::hir(cx, rhs, ".."); @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)), ); }); - if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { + if let hir::ExprKind::Binary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| { span_lint_and_then( @@ -131,8 +131,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } } }, - hir::ExprAssign(ref assignee, ref e) => { - if let hir::ExprBinary(op, ref l, ref r) = e.node { + hir::ExprKind::Assign(ref assignee, ref e) => { + if let hir::ExprKind::Binary(op, ref l, ref r) = e.node { #[allow(cyclomatic_complexity)] let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { let ty = cx.tables.expr_ty(assignee); diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index b9d8976b28b..4418ba63070 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -244,10 +244,10 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool { match expr.node { - ExprBlock(ref block, _) => is_relevant_block(tcx, tables, block), - ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), - ExprRet(None) | ExprBreak(_, None) => false, - ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { + ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block), + ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e), + ExprKind::Ret(None) | ExprKind::Break(_, None) => false, + ExprKind::Call(ref path_expr, _) => if let ExprKind::Path(ref qpath) = path_expr.node { if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) { !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) } else { diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 9f548b9e320..0558ad36b34 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -109,7 +109,7 @@ impl LintPass for BitMask { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprBinary(ref cmp, ref left, ref right) = e.node { + if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { if cmp.node.is_comparison() { if let Some(cmp_opt) = fetch_int_literal(cx, right) { check_compare(cx, left, cmp.node, cmp_opt, e.span) @@ -119,13 +119,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { } } if_chain! { - if let Expr_::ExprBinary(ref op, ref left, ref right) = e.node; + if let ExprKind::Binary(ref op, ref left, ref right) = e.node; if BinOp_::BiEq == op.node; - if let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node; + if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node; if BinOp_::BiBitAnd == op1.node; - if let Expr_::ExprLit(ref lit) = right1.node; + if let ExprKind::Lit(ref lit) = right1.node; if let LitKind::Int(n, _) = lit.node; - if let Expr_::ExprLit(ref lit1) = right.node; + if let ExprKind::Lit(ref lit1) = right.node; if let LitKind::Int(0, _) = lit1.node; if n.leading_zeros() == n.count_zeros(); if n > u128::from(self.verbose_bit_mask_threshold); @@ -157,7 +157,7 @@ fn invert_cmp(cmp: BinOp_) -> BinOp_ { fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: Span) { - if let ExprBinary(ref op, ref left, ref right) = bit_op.node { + if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node { if op.node != BiBitAnd && op.node != BiBitOr { return; } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 5f484341186..94e17290b6a 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -56,10 +56,10 @@ struct ExVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if let ExprClosure(_, _, eid, _, _) = expr.node { + if let ExprKind::Closure(_, _, eid, _, _) = expr.node { let body = self.cx.tcx.hir.body(eid); let ex = &body.value; - if matches!(ex.node, ExprBlock(_, _)) { + if matches!(ex.node, ExprKind::Block(_, _)) { self.found_block = Some(ex); return; } @@ -77,8 +77,8 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprIf(ref check, ref then, _) = expr.node { - if let ExprBlock(ref block, _) = check.node { + if let ExprKind::If(ref check, ref then, _) = expr.node { + if let ExprKind::Block(ref block, _) = check.node { if block.rules == DefaultBlock { if block.stmts.is_empty() { if let Some(ref ex) = block.expr { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index b541bfc6b2f..c6d0942a877 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -86,7 +86,7 @@ struct Hir2Qmm<'a, 'tcx: 'a, 'v> { impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec) -> Result, String> { for a in a { - if let ExprBinary(binop, ref lhs, ref rhs) = a.node { + if let ExprKind::Binary(binop, ref lhs, ref rhs) = a.node { if binop.node == op { v = self.extract(op, &[lhs, rhs], v)?; continue; @@ -101,13 +101,13 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { // prevent folding of `cfg!` macros and the like if !in_macro(e.span) { match e.node { - ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprBinary(binop, ref lhs, ref rhs) => match binop.node { + ExprKind::Unary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), + ExprKind::Binary(binop, ref lhs, ref rhs) => match binop.node { BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), _ => (), }, - ExprLit(ref lit) => match lit.node { + ExprKind::Lit(ref lit) => match lit.node { LitKind::Bool(true) => return Ok(Bool::True), LitKind::Bool(false) => return Ok(Bool::False), _ => (), @@ -121,8 +121,8 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { return Ok(Bool::Term(n as u8)); } let negated = match e.node { - ExprBinary(binop, ref lhs, ref rhs) => { - + ExprKind::Binary(binop, ref lhs, ref rhs) => { + if !implements_ord(self.cx, lhs) { continue; } @@ -133,7 +133,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { hir_id: DUMMY_HIR_ID, span: DUMMY_SP, attrs: ThinVec::new(), - node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()), } }; match binop.node { @@ -178,7 +178,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { fn simplify_not(&self, expr: &Expr) -> Option { match expr.node { - ExprBinary(binop, ref lhs, ref rhs) => { + ExprKind::Binary(binop, ref lhs, ref rhs) => { if !implements_ord(self.cx, lhs) { return None; @@ -194,7 +194,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { _ => None, }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, - ExprMethodCall(ref path, _, ref args) if args.len() == 1 => { + ExprKind::MethodCall(ref path, _, ref args) if args.len() == 1 => { let type_of_receiver = self.cx.tables.expr_ty(&args[0]); if !match_type(self.cx, type_of_receiver, &paths::OPTION) && !match_type(self.cx, type_of_receiver, &paths::RESULT) { @@ -441,8 +441,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { return; } match e.node { - ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), - ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { + ExprKind::Binary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), + ExprKind::Unary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { self.bool_expr(e); } else { walk_expr(self, e); diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 6f2ea320f93..e60fbbbe51d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -38,19 +38,19 @@ impl LintPass for ByteCount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_chain! { - if let ExprMethodCall(ref count, _, ref count_args) = expr.node; + if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node; if count.ident.name == "count"; if count_args.len() == 1; - if let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node; + if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node; if filter.ident.name == "filter"; if filter_args.len() == 2; - if let ExprClosure(_, _, body_id, _, _) = filter_args[1].node; + if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node; then { let body = cx.tcx.hir.body(body_id); if_chain! { if body.arguments.len() == 1; if let Some(argname) = get_pat_name(&body.arguments[0].pat); - if let ExprBinary(ref op, ref l, ref r) = body.value.node; + if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node; if op.node == BiEq; if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { return; } - let haystack = if let ExprMethodCall(ref path, _, ref args) = + let haystack = if let ExprKind::MethodCall(ref path, _, ref args) = filter_args[0].node { let p = path.ident.name; if (p == "iter" || p == "iter_mut") && args.len() == 1 { @@ -98,13 +98,13 @@ fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool { fn get_path_name(expr: &Expr) -> Option { match expr.node { - ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprBlock(ref b, _) => if b.stmts.is_empty() { + ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e), + ExprKind::Block(ref b, _) => if b.stmts.is_empty() { b.expr.as_ref().and_then(|p| get_path_name(p)) } else { None }, - ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), + ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), _ => None, } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 6fc6637900d..8e0e60193bb 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -211,25 +211,25 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr) -> Option { match e.node { - ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id), - ExprBlock(ref block, _) => self.block(block), - ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), - ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))), - ExprArray(ref vec) => self.multi(vec).map(Constant::Vec), - ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), - ExprRepeat(ref value, _) => { + ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id), + ExprKind::Block(ref block, _) => self.block(block), + ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), + ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))), + ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec), + ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), + ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { ty::TyArray(_, n) => n.assert_usize(self.tcx).expect("array length"), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64)) }, - ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op { + ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op { UnNot => self.constant_not(&o, self.tables.expr_ty(e)), UnNeg => self.constant_negate(&o, self.tables.expr_ty(e)), UnDeref => Some(o), }), - ExprBinary(op, ref left, ref right) => self.binop(op, left, right), + ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right), // TODO: add other expressions _ => None, } @@ -279,7 +279,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { .collect::>() } - /// lookup a possibly constant expression from a ExprPath + /// lookup a possibly constant expression from a ExprKind::Path fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { let def = self.tables.qpath_def(qpath, id); match def { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 430ff59cd4d..9e9a641ce27 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -115,7 +115,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { if !in_macro(expr.span) { // skip ifs directly in else, it will be checked in the parent if if let Some(&Expr { - node: ExprIf(_, _, Some(ref else_expr)), + node: ExprKind::If(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { @@ -172,7 +172,7 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { /// Implementation of `MATCH_SAME_ARMS`. fn lint_match_arms(cx: &LateContext, expr: &Expr) { - if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node { + if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.node { let hash = |&(_, arm): &(usize, &Arm)| -> u64 { let mut h = SpanlessHash::new(cx, cx.tables); h.hash_expr(&arm.body); @@ -236,12 +236,12 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { let mut conds = SmallVector::new(); let mut blocks: SmallVector<&Block> = SmallVector::new(); - while let ExprIf(ref cond, ref then_expr, ref else_expr) = expr.node { + while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.node { conds.push(&**cond); - if let ExprBlock(ref block, _) = then_expr.node { + if let ExprKind::Block(ref block, _) = then_expr.node { blocks.push(block); } else { - panic!("ExprIf node is not an ExprBlock"); + panic!("ExprKind::If node is not an ExprKind::Block"); } if let Some(ref else_expr) = *else_expr { @@ -253,7 +253,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { // final `else {..}` if !blocks.is_empty() { - if let ExprBlock(ref block, _) = expr.node { + if let ExprKind::Block(ref block, _) = expr.node { blocks.push(&**block); } } diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index ea5f5cf9b58..33dbf1afc89 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -147,14 +147,14 @@ struct CCHelper<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr) { match e.node { - ExprMatch(_, ref arms, _) => { + ExprKind::Match(_, ref arms, _) => { walk_expr(self, e); let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); if arms_n > 1 { self.match_arms += arms_n - 2; } }, - ExprCall(ref callee, _) => { + ExprKind::Call(ref callee, _) => { walk_expr(self, e); let ty = self.cx.tables.node_id_to_type(callee.hir_id); match ty.sty { @@ -167,15 +167,15 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { _ => (), } }, - ExprClosure(.., _) => (), - ExprBinary(op, _, _) => { + ExprKind::Closure(.., _) => (), + ExprKind::Binary(op, _, _) => { walk_expr(self, e); match op.node { BiAnd | BiOr => self.short_circuits += 1, _ => (), } }, - ExprRet(_) => self.returns += 1, + ExprKind::Ret(_) => self.returns += 1, _ => walk_expr(self, e), } } diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 30dcafc2daf..900dabc9650 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -38,9 +38,9 @@ impl LintPass for DefaultTraitAccess { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprCall(ref path, ..) = expr.node; + if let ExprKind::Call(ref path, ..) = expr.node; if !any_parent_is_automatically_derived(cx.tcx, expr.id); - if let ExprPath(ref qpath) = path.node; + if let ExprKind::Path(ref qpath) = path.node; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); then { diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index ba398c82064..7681cc7225f 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> DoubleComparisonPass { span: Span, ) { let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) { - (ExprBinary(lb, llhs, lrhs), ExprBinary(rb, rlhs, rrhs)) => { + (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) } _ => return, @@ -78,7 +78,7 @@ impl<'a, 'tcx> DoubleComparisonPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisonPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprBinary(ref kind, ref lhs, ref rhs) = expr.node { + if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.node { self.check_binop(cx, kind.node, lhs, rhs, expr.span); } } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index eb271a899c4..b0625e10d76 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -116,8 +116,8 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprCall(ref path, ref args) = expr.node; - if let ExprPath(ref qpath) = path.node; + if let ExprKind::Call(ref path, ref args) = expr.node; + if let ExprKind::Path(ref qpath) = path.node; if args.len() == 1; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); then { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 16b94d24b16..b3f8279c943 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -38,8 +38,8 @@ impl LintPass for DurationSubsec { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprBinary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node; - if let ExprMethodCall(ref method_path, _ , ref args) = left.node; + if let ExprKind::Binary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node; + if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.node; if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); then { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 13c75f39bb8..f29c2d1bb6d 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -41,13 +41,13 @@ impl LintPass for HashMapLint { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprIf(ref check, ref then_block, ref else_block) = expr.node { - if let ExprUnary(UnOp::UnNot, ref check) = check.node { + if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.node { + if let ExprKind::Unary(UnOp::UnNot, ref check) = check.node { if let Some((ty, map, key)) = check_cond(cx, check) { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = { - else_block.is_none() && if let ExprBlock(ref then_block, _) = then_block.node { + else_block.is_none() && if let ExprKind::Block(ref then_block, _) = then_block.node { (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 } else { true @@ -88,10 +88,10 @@ fn check_cond<'a, 'tcx, 'b>( check: &'b Expr, ) -> Option<(&'static str, &'b Expr, &'b Expr)> { if_chain! { - if let ExprMethodCall(ref path, _, ref params) = check.node; + if let ExprKind::MethodCall(ref path, _, ref params) = check.node; if params.len() >= 2; if path.ident.name == "contains_key"; - if let ExprAddrOf(_, ref key) = params[1].node; + if let ExprKind::AddrOf(_, ref key) = params[1].node; then { let map = ¶ms[0]; let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map)); @@ -123,7 +123,7 @@ struct InsertVisitor<'a, 'tcx: 'a, 'b> { impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { fn visit_expr(&mut self, expr: &'tcx Expr) { if_chain! { - if let ExprMethodCall(ref path, _, ref params) = expr.node; + if let ExprKind::MethodCall(ref path, _, ref params) = expr.node; if params.len() == 3; if path.ident.name == "insert"; if get_item_name(self.cx, self.map) == get_item_name(self.cx, ¶ms[0]); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 19761fbe864..7c4c09893d3 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -52,7 +52,7 @@ impl LintPass for EqOp { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprBinary(op, ref left, ref right) = e.node { + if let ExprKind::Binary(op, ref left, ref right) = e.node { if in_macro(e.span) { return; } @@ -85,9 +85,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { #[allow(match_same_arms)] match (&left.node, &right.node) { // do not suggest to dereference literals - (&ExprLit(..), _) | (_, &ExprLit(..)) => {}, + (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {}, // &foo == &bar - (&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => { + (&ExprKind::AddrOf(_, ref l), &ExprKind::AddrOf(_, ref r)) => { let lty = cx.tables.expr_ty(l); let rty = cx.tables.expr_ty(r); let lcpy = is_copy(cx, lty); @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { } }, // &foo == bar - (&ExprAddrOf(_, ref l), _) => { + (&ExprKind::AddrOf(_, ref l), _) => { let lty = cx.tables.expr_ty(l); let lcpy = is_copy(cx, lty); if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { } }, // foo == &bar - (_, &ExprAddrOf(_, ref r)) => { + (_, &ExprKind::AddrOf(_, ref r)) => { let rty = cx.tables.expr_ty(r); let rcpy = is_copy(cx, rty); if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index faf297fd5b2..c14aafbd417 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { if in_macro(e.span) { return; } - if let ExprBinary(ref cmp, ref left, ref right) = e.node { + if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { match cmp.node { BiMul | BiBitAnd => { check(cx, left, e.span); diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index c718e1f417c..70055b13f9b 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let StmtDecl(ref decl, _) = st.node { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { - if let ExprBox(..) = ex.node { + if let ExprKind::Box(..) = ex.node { if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { // let x = box (...) self.set.insert(consume_pat.id); diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index e924ba6bdbb..87f0e64caaf 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -37,7 +37,7 @@ impl LintPass for EtaPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { - ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => for arg in args { + ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args { check_closure(cx, arg) }, _ => (), @@ -46,10 +46,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { } fn check_closure(cx: &LateContext, expr: &Expr) { - if let ExprClosure(_, ref decl, eid, _, _) = expr.node { + if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node { let body = cx.tcx.hir.body(eid); let ex = &body.value; - if let ExprCall(ref caller, ref args) = ex.node { + if let ExprKind::Call(ref caller, ref args) = ex.node { if args.len() != decl.inputs.len() { // Not the same number of arguments, there // is no way the closure is the same as the function @@ -73,7 +73,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { for (a1, a2) in iter_input_pats(decl, body).zip(args) { if let PatKind::Binding(_, _, ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? - if let ExprPath(QPath::Resolved(None, ref p)) = a2.node { + if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node { if p.segments.len() != 1 { // If it's a proper path, it can't be a local variable return; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d773289263e..ebbffc66808 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Find a write to a local variable. match expr.node { - ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node { + ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => if let ExprKind::Path(ref qpath) = lhs.node { if let QPath::Resolved(_, ref path) = *qpath { if path.segments.len() == 1 { if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) { @@ -102,8 +102,8 @@ struct DivergenceVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { fn maybe_walk_expr(&mut self, e: &'tcx Expr) { match e.node { - ExprClosure(.., _) => {}, - ExprMatch(ref e, ref arms, _) => { + ExprKind::Closure(.., _) => {}, + ExprKind::Match(ref e, ref arms, _) => { self.visit_expr(e); for arm in arms { if let Some(ref guard) = arm.guard { @@ -124,8 +124,8 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr) { match e.node { - ExprContinue(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e), - ExprCall(ref func, _) => { + ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e), + ExprKind::Call(ref func, _) => { let typ = self.cx.tables.expr_ty(func); match typ.sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { @@ -137,7 +137,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { _ => {}, } }, - ExprMethodCall(..) => { + ExprKind::MethodCall(..) => { let borrowed_table = self.cx.tables; if borrowed_table.expr_ty(e).is_never() { self.report_diverging_sub_expr(e); @@ -218,17 +218,17 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St } match expr.node { - ExprArray(_) | - ExprTup(_) | - ExprMethodCall(..) | - ExprCall(_, _) | - ExprAssign(_, _) | - ExprIndex(_, _) | - ExprRepeat(_, _) | - ExprStruct(_, _, _) => { + ExprKind::Array(_) | + ExprKind::Tup(_) | + ExprKind::MethodCall(..) | + ExprKind::Call(_, _) | + ExprKind::Assign(_, _) | + ExprKind::Index(_, _) | + ExprKind::Repeat(_, _) | + ExprKind::Struct(_, _, _) => { walk_expr(vis, expr); }, - ExprBinary(op, _, _) | ExprAssignOp(op, _, _) => { + ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => { if op.node == BiAnd || op.node == BiOr { // x && y and x || y always evaluate x first, so these are // strictly sequenced. @@ -236,7 +236,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St walk_expr(vis, expr); } }, - ExprClosure(_, _, _, _, _) => { + ExprKind::Closure(_, _, _, _, _) => { // Either // // * `var` is defined in the closure body, in which case we've @@ -297,7 +297,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { } match expr.node { - ExprPath(ref qpath) => { + ExprKind::Path(ref qpath) => { if_chain! { if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; @@ -320,7 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { // We're about to descend a closure. Since we don't know when (or // if) the closure will be evaluated, any reads in it might not // occur here (or ever). Like above, bail to avoid false positives. - ExprClosure(_, _, _, _, _) | + ExprKind::Closure(_, _, _, _, _) | // We want to avoid a false positive when a variable name occurs // only to have its address taken, so we stop here. Technically, @@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { // ``` // // TODO: fix this - ExprAddrOf(_, _) => { + ExprKind::AddrOf(_, _) => { return; } _ => {} @@ -348,7 +348,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { /// Returns true if `expr` is the LHS of an assignment, like `expr = ...`. fn is_in_assignment_position(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprAssign(ref lhs, _) = parent.node { + if let ExprKind::Assign(ref lhs, _) = parent.node { return lhs.id == expr.id; } } diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index aa648003c0c..24bbf669205 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { if_chain! { let ty = cx.tables.expr_ty(expr); if let TypeVariants::TyFloat(fty) = ty.sty; - if let hir::ExprLit(ref lit) = expr.node; + if let hir::ExprKind::Lit(ref lit) = expr.node; if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node; if let Some(sugg) = self.check(sym, fty); then { diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 7c741100bde..019d21f81e0 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -35,17 +35,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { // match call to unwrap - if let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node; + if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node; if unwrap_fun.ident.name == "unwrap"; // match call to write_fmt if unwrap_args.len() > 0; - if let ExprMethodCall(ref write_fun, _, ref write_args) = + if let ExprKind::MethodCall(ref write_fun, _, ref write_args) = unwrap_args[0].node; if write_fun.ident.name == "write_fmt"; // match calls to std::io::stdout() / std::io::stderr () if write_args.len() > 0; - if let ExprCall(ref dest_fun, _) = write_args[0].node; - if let ExprPath(ref qpath) = dest_fun.node; + if let ExprKind::Call(ref dest_fun, _) = write_args[0].node; + if let ExprKind::Path(ref qpath) = dest_fun.node; if let Some(dest_fun_id) = opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id)); if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 64cdc05b44d..62e2ba7a2de 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -63,8 +63,8 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it fn visit_expr(&mut self, expr: &'tcx Expr) { // check for `begin_panic` if_chain! { - if let ExprCall(ref func_expr, _) = expr.node; - if let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node; + if let ExprKind::Call(ref func_expr, _) = expr.node; + if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.node; if let Some(path_def_id) = opt_def_id(path.def); if match_def_path(self.tcx, path_def_id, &BEGIN_PANIC) || match_def_path(self.tcx, path_def_id, &BEGIN_PANIC_FMT); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 890fe51819a..e88f0386893 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -46,9 +46,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { // `format!("{}", foo)` expansion - ExprCall(ref fun, ref args) => { + ExprKind::Call(ref fun, ref args) => { if_chain! { - if let ExprPath(ref qpath) = fun.node; + if let ExprKind::Path(ref qpath) = fun.node; if args.len() == 3; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }, // `format!("foo")` expansion contains `match () { () => [], }` - ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node { + ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node { if tup.is_empty() { let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { @@ -81,10 +81,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { /// Checks if the expressions matches `&[""]` fn check_single_piece(expr: &Expr) -> bool { if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; // &[""] - if let ExprArray(ref exprs) = expr.node; // [""] + if let ExprKind::AddrOf(_, ref expr) = expr.node; // &[""] + if let ExprKind::Array(ref exprs) = expr.node; // [""] if exprs.len() == 1; - if let ExprLit(ref lit) = exprs[0].node; + if let ExprKind::Lit(ref lit) = exprs[0].node; if let LitKind::Str(ref lit, _) = lit.node; then { return lit.as_str().is_empty(); @@ -105,23 +105,23 @@ fn check_single_piece(expr: &Expr) -> bool { /// then returns the span of first element of the matched tuple fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option { if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; - if let ExprMatch(ref match_expr, ref arms, _) = expr.node; + if let ExprKind::AddrOf(_, ref expr) = expr.node; + if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node; if arms.len() == 1; if arms[0].pats.len() == 1; if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node; if pat.len() == 1; - if let ExprArray(ref exprs) = arms[0].body.node; + if let ExprKind::Array(ref exprs) = arms[0].body.node; if exprs.len() == 1; - if let ExprCall(_, ref args) = exprs[0].node; + if let ExprKind::Call(_, ref args) = exprs[0].node; if args.len() == 2; - if let ExprPath(ref qpath) = args[1].node; + if let ExprKind::Path(ref qpath) = args[1].node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); if ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING) { - if let ExprTup(ref values) = match_expr.node { + if let ExprKind::Tup(ref values) = match_expr.node { return Some(values[0].span); } } @@ -143,14 +143,14 @@ fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option { /// ``` fn check_unformatted(expr: &Expr) -> bool { if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; - if let ExprArray(ref exprs) = expr.node; + if let ExprKind::AddrOf(_, ref expr) = expr.node; + if let ExprKind::Array(ref exprs) = expr.node; if exprs.len() == 1; - if let ExprStruct(_, ref fields, _) = exprs[0].node; + if let ExprKind::Struct(_, ref fields, _) = exprs[0].node; if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); - if let ExprStruct(_, ref fields, _) = format_field.expr.node; + if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node; if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width"); - if let ExprPath(ref qpath) = align_field.expr.node; + if let ExprKind::Path(ref qpath) = align_field.expr.node; if last_path_segment(qpath).ident.name == "Implied"; then { return true; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 554c983d7c5..75ebd9eaece 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -184,7 +184,7 @@ struct DerefVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprCall(ref f, ref args) => { + hir::ExprKind::Call(ref f, ref args) => { let ty = self.tables.expr_ty(f); if type_is_unsafe_function(self.cx, ty) { @@ -193,7 +193,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } } }, - hir::ExprMethodCall(_, _, ref args) => { + hir::ExprKind::MethodCall(_, _, ref args) => { let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id(); let base_type = self.cx.tcx.type_of(def_id); @@ -203,7 +203,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } } }, - hir::ExprUnary(hir::UnDeref, ref ptr) => self.check_arg(ptr), + hir::ExprKind::Unary(hir::UnDeref, ref ptr) => self.check_arg(ptr), _ => (), } @@ -216,7 +216,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr) { - if let hir::ExprPath(ref qpath) = ptr.node { + if let hir::ExprKind::Path(ref qpath) = ptr.node { if let Def::Local(id) = self.cx.tables.qpath_def(qpath, ptr.hir_id) { if self.ptrs.contains(&id) { span_lint( diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 2effb8bd8db..32ae8bcb29f 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -43,19 +43,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { } match e.node { - ExprMatch(_, ref arms, MatchSource::TryDesugar) => { + ExprKind::Match(_, ref arms, MatchSource::TryDesugar) => { let e = match arms[0].body.node { - ExprRet(Some(ref e)) | ExprBreak(_, Some(ref e)) => e, + ExprKind::Ret(Some(ref e)) | ExprKind::Break(_, Some(ref e)) => e, _ => return, }; - if let ExprCall(_, ref args) = e.node { + if let ExprKind::Call(_, ref args) = e.node { self.try_desugar_arm.push(args[0].id); } else { return; } }, - ExprMethodCall(ref name, .., ref args) => { + ExprKind::MethodCall(ref name, .., ref args) => { if match_trait_method(cx, e, &paths::INTO[..]) && &*name.ident.as_str() == "into" { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { } }, - ExprCall(ref path, ref args) => if let ExprPath(ref qpath) = path.node { + ExprKind::Call(ref path, ref args) => if let ExprKind::Path(ref qpath) = path.node { if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) { if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) { let a = cx.tables.expr_ty(e); diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index e983e5746a1..95dea6fc6d2 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { if in_macro(e.span) { return; } - if let ExprBinary(ref cmp, ref left, ref right) = e.node { + if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { match cmp.node { BiAdd | BiBitOr | BiBitXor => { check(cx, left, 0, e.span, right.span); diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 78b21478d88..17dcf571fbf 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -45,7 +45,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { + if let ExprKind::Match(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { if arms[0].pats.len() == 1 { let good_method = match arms[0].pats[0].node { PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 7dd72a5383c..8176408e720 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -94,7 +94,7 @@ impl LintPass for IndexingSlicing { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprIndex(ref array, ref index) = &expr.node { + if let ExprKind::Index(ref array, ref index) = &expr.node { let ty = cx.tables.expr_ty(array); if let Some(range) = higher::range(cx, index) { // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index a2b3846b986..9abd9754d67 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) { if_chain! { if let Some(ref expr) = local.init; - if let Expr_::ExprMatch(ref target, ref arms, MatchSource::Normal) = expr.node; + if let ExprKind::Match(ref target, ref arms, MatchSource::Normal) = expr.node; if arms.len() == 1 && arms[0].pats.len() == 1 && arms[0].guard.is_none(); if let PatKind::TupleStruct(QPath::Resolved(None, ref variant_name), ref args, _) = arms[0].pats[0].node; if args.len() == 1; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 8f6d499329f..a979486945a 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -141,7 +141,7 @@ static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { - ExprMethodCall(ref method, _, ref args) => { + ExprKind::MethodCall(ref method, _, ref args) => { for &(name, len, heuristic, cap) in HEURISTICS.iter() { if method.ident.name == name && args.len() == len { return (match heuristic { @@ -153,21 +153,21 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { } } if method.ident.name == "flat_map" && args.len() == 2 { - if let ExprClosure(_, _, body_id, _, _) = args[1].node { + if let ExprKind::Closure(_, _, body_id, _, _) = args[1].node { let body = cx.tcx.hir.body(body_id); return is_infinite(cx, &body.value); } } Finite }, - ExprBlock(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), - ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), - ExprCall(ref path, _) => if let ExprPath(ref qpath) = path.node { + ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), + ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e), + ExprKind::Call(ref path, _) => if let ExprKind::Path(ref qpath) = path.node { match_qpath(qpath, &paths::REPEAT).into() } else { Finite }, - ExprStruct(..) => higher::range(cx, expr) + ExprKind::Struct(..) => higher::range(cx, expr) .map_or(false, |r| r.end.is_none()) .into(), _ => Finite, @@ -205,7 +205,7 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { match expr.node { - ExprMethodCall(ref method, _, ref args) => { + ExprKind::MethodCall(ref method, _, ref args) => { for &(name, len) in COMPLETING_METHODS.iter() { if method.ident.name == name && args.len() == len { return is_infinite(cx, &args[0]); @@ -224,11 +224,11 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { } } }, - ExprBinary(op, ref l, ref r) => if op.node.is_comparison() { + ExprKind::Binary(op, ref l, ref r) => if op.node.is_comparison() { return is_infinite(cx, l) .and(is_infinite(cx, r)) .and(MaybeInfinite); - }, // TODO: ExprLoop + Match + }, // TODO: ExprKind::Loop + Match _ => (), } Finite diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 0ebdda9ec88..255efa74165 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -35,8 +35,8 @@ impl LintPass for InvalidRef { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprCall(ref path, ref args) = expr.node; - if let ExprPath(ref qpath) = path.node; + if let ExprKind::Call(ref path, ref args) = expr.node; + if let ExprKind::Path(ref qpath) = path.node; if args.len() == 0; if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index c1ec7a16296..17164c6c56a 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { return; } - if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { + if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { match cmp { BiEq => { check_cmp(cx, expr.span, left, right, "", 0); // len == 0 @@ -194,7 +194,7 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { } fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) { - if let (&ExprMethodCall(ref method_path, _, ref args), &ExprLit(ref lit)) = (&method.node, &lit.node) { + if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { if name == "is_empty" { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 4e0d3de799e..44f197f7333 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -69,16 +69,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if let hir::DeclLocal(ref decl) = decl.node; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node; if let hir::StmtExpr(ref if_, _) = expr.node; - if let hir::ExprIf(ref cond, ref then, ref else_) = if_.node; + if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); - if let hir::ExprBlock(ref then, _) = then.node; + if let hir::ExprKind::Block(ref then, _) = then.node; if let Some(value) = check_assign(cx, canonical_id, &*then); if !used_in_expr(cx, canonical_id, value); then { let span = stmt.span.to(if_.span); let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { - if let hir::ExprBlock(ref else_, _) = else_.node { + if let hir::ExprKind::Block(ref else_, _) = else_.node { if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) } else if let Some(ref default) = decl.init { @@ -140,7 +140,7 @@ struct UsedVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if_chain! { - if let hir::ExprPath(ref qpath) = expr.node; + if let hir::ExprKind::Path(ref qpath) = expr.node; if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); if self.id == local_id; then { @@ -164,8 +164,8 @@ fn check_assign<'a, 'tcx>( if block.expr.is_none(); if let Some(expr) = block.stmts.iter().last(); if let hir::StmtSemi(ref expr, _) = expr.node; - if let hir::ExprAssign(ref var, ref value) = expr.node; - if let hir::ExprPath(ref qpath) = var.node; + if let hir::ExprKind::Assign(ref var, ref value) = expr.node; + if let hir::ExprKind::Path(ref qpath) = var.node; if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id); if decl == local_id; then { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 963a8da49cb..7dd7263551d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -411,7 +411,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { - ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => { + ExprKind::While(_, ref block, _) | ExprKind::Loop(ref block, _, _) => { match never_loop_block(block, expr.id) { NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), @@ -424,7 +424,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for `loop { if let {} else break }` that could be `while let` // (also matches an explicit "match" instead of "if let") // (even if the "match" or "if let" is used for declaration) - if let ExprLoop(ref block, _, LoopSource::Loop) = expr.node { + if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.node { // also check for empty `loop {}` statements if block.stmts.is_empty() && block.expr.is_none() { span_lint( @@ -440,7 +440,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let inner_stmt_expr = extract_expr_from_first_stmt(block); // or extract the first expression (if any) from the block if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) { - if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { + if let ExprKind::Match(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { @@ -476,11 +476,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } - if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { + if let ExprKind::Match(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; if let ( &PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args), + &ExprKind::MethodCall(ref method_path, _, ref method_args), ) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; @@ -505,14 +505,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } // check for while loops which conditions never change - if let ExprWhile(ref cond, _, _) = expr.node { + if let ExprKind::While(ref cond, _, _) = expr.node { check_infinite_loop(cx, cond, expr); } } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { if let StmtSemi(ref expr, _) = stmt.node { - if let ExprMethodCall(ref method, _, ref args) = expr.node { + if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { span_lint( cx, @@ -598,39 +598,39 @@ fn decl_to_expr(decl: &Decl) -> Option<&Expr> { fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { match expr.node { - ExprBox(ref e) | - ExprUnary(_, ref e) | - ExprCast(ref e, _) | - ExprType(ref e, _) | - ExprField(ref e, _) | - ExprAddrOf(_, ref e) | - ExprStruct(_, _, Some(ref e)) | - ExprRepeat(ref e, _) => never_loop_expr(e, main_loop_id), - ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => { + ExprKind::Box(ref e) | + ExprKind::Unary(_, ref e) | + ExprKind::Cast(ref e, _) | + ExprKind::Type(ref e, _) | + ExprKind::Field(ref e, _) | + ExprKind::AddrOf(_, ref e) | + ExprKind::Struct(_, _, Some(ref e)) | + ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id), + ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => { never_loop_expr_all(&mut es.iter(), main_loop_id) }, - ExprCall(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), - ExprBinary(_, ref e1, ref e2) | - ExprAssign(ref e1, ref e2) | - ExprAssignOp(_, ref e1, ref e2) | - ExprIndex(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), - ExprIf(ref e, ref e2, ref e3) => { + ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), + ExprKind::Binary(_, ref e1, ref e2) | + ExprKind::Assign(ref e1, ref e2) | + ExprKind::AssignOp(_, ref e1, ref e2) | + ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), + ExprKind::If(ref e, ref e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); combine_seq(e1, combine_branches(e2, e3)) }, - ExprLoop(ref b, _, _) => { + ExprKind::Loop(ref b, _, _) => { // Break can come from the inner loop so remove them. absorb_break(&never_loop_block(b, main_loop_id)) }, - ExprWhile(ref e, ref b, _) => { + ExprKind::While(ref e, ref b, _) => { let e = never_loop_expr(e, main_loop_id); let result = never_loop_block(b, main_loop_id); // Break can come from the inner loop so remove them. combine_seq(e, absorb_break(&result)) }, - ExprMatch(ref e, ref arms, _) => { + ExprKind::Match(ref e, ref arms, _) => { let e = never_loop_expr(e, main_loop_id); if arms.is_empty() { e @@ -639,8 +639,8 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { combine_seq(e, arms) } }, - ExprBlock(ref b, _) => never_loop_block(b, main_loop_id), - ExprContinue(d) => { + ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id), + ExprKind::Continue(d) => { let id = d.target_id .expect("target id can only be missing in the presence of compilation errors"); if id == main_loop_id { @@ -649,22 +649,22 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { NeverLoopResult::AlwaysBreak } }, - ExprBreak(_, _) => { + ExprKind::Break(_, _) => { NeverLoopResult::AlwaysBreak }, - ExprRet(ref e) => { + ExprKind::Ret(ref e) => { if let Some(ref e) = *e { combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) } else { NeverLoopResult::AlwaysBreak } }, - ExprStruct(_, _, None) | - ExprYield(_) | - ExprClosure(_, _, _, _, _) | - ExprInlineAsm(_, _, _) | - ExprPath(_) | - ExprLit(_) => NeverLoopResult::Otherwise, + ExprKind::Struct(_, _, None) | + ExprKind::Yield(_) | + ExprKind::Closure(_, _, _, _, _) | + ExprKind::InlineAsm(_, _, _) | + ExprKind::Path(_) | + ExprKind::Lit(_) => NeverLoopResult::Otherwise, } } @@ -701,7 +701,7 @@ fn check_for_loop<'a, 'tcx>( fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool { if_chain! { - if let ExprPath(ref qpath) = expr.node; + if let ExprKind::Path(ref qpath) = expr.node; if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; if let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id); @@ -754,23 +754,23 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option { match e.node { - ExprLit(ref l) => match l.node { + ExprKind::Lit(ref l) => match l.node { ast::LitKind::Int(x, _ty) => Some(x.to_string()), _ => None, }, - ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), + ExprKind::Path(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), _ => None, } } - if let ExprIndex(ref seqexpr, ref idx) = expr.node { + if let ExprKind::Index(ref seqexpr, ref idx) = expr.node { let ty = cx.tables.expr_ty(seqexpr); if !is_slice_like(cx, ty) { return None; } let offset = match idx.node { - ExprBinary(op, ref lhs, ref rhs) => match op.node { + ExprKind::Binary(op, ref lhs, ref rhs) => match op.node { BinOp_::BiAdd => { let offset_opt = if same_var(cx, lhs, var) { extract_offset(cx, rhs, var) @@ -785,7 +785,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, }, - ExprPath(..) => if same_var(cx, idx, var) { + ExprKind::Path(..) => if same_var(cx, idx, var) { Some(Offset::positive("0".into())) } else { None @@ -810,7 +810,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( var: ast::NodeId, ) -> Option { if_chain! { - if let ExprMethodCall(ref method, _, ref args) = expr.node; + if let ExprKind::MethodCall(ref method, _, ref args) = expr.node; if method.ident.name == "clone"; if args.len() == 1; if let Some(arg) = args.get(0); @@ -832,7 +832,7 @@ fn get_indexed_assignments<'a, 'tcx>( e: &Expr, var: ast::NodeId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { - if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { + if let ExprKind::Assign(ref lhs, ref rhs) = e.node { match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) { (Some(offset_left), Some(offset_right)) => { // Source and destination must be different @@ -849,7 +849,7 @@ fn get_indexed_assignments<'a, 'tcx>( } } - if let Expr_::ExprBlock(ref b, _) = body.node { + if let ExprKind::Block(ref b, _) = body.node { let Block { ref stmts, ref expr, @@ -906,7 +906,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { if_chain! { - if let ExprMethodCall(ref method, _, ref len_args) = end.node; + if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node; if method.ident.name == "len"; if len_args.len() == 1; if let Some(arg) = len_args.get(0); @@ -1098,10 +1098,10 @@ fn check_for_loop_range<'a, 'tcx>( fn is_len_call(expr: &Expr, var: Name) -> bool { if_chain! { - if let ExprMethodCall(ref method, _, ref len_args) = expr.node; + if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.node; if len_args.len() == 1; if method.ident.name == "len"; - if let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node; + if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].node; if path.segments.len() == 1; if path.segments[0].ident.name == var; then { @@ -1203,7 +1203,7 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used - if let ExprMethodCall(ref method, _, ref args) = arg.node { + if let ExprKind::MethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments if args.len() == 1 { let method_name = &*method.ident.as_str(); @@ -1377,7 +1377,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( MutMutable => "_mut", }; let arg = match arg.node { - ExprAddrOf(_, ref expr) => &**expr, + ExprKind::AddrOf(_, ref expr) => &**expr, _ => arg, }; @@ -1483,7 +1483,7 @@ fn mut_warn_with_span(cx: &LateContext, span: Option) { fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { if_chain! { - if let ExprPath(ref qpath) = bound.node; + if let ExprKind::Path(ref qpath) = bound.node; if let QPath::Resolved(None, _) = *qpath; then { let def = cx.tables.qpath_def(qpath, bound.hir_id); @@ -1598,7 +1598,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { fn check(&mut self, idx: &'tcx Expr, seqexpr: &'tcx Expr, expr: &'tcx Expr) -> bool { if_chain! { // the indexed container is referenced by a name - if let ExprPath(ref seqpath) = seqexpr.node; + if let ExprKind::Path(ref seqpath) = seqexpr.node; if let QPath::Resolved(None, ref seqvar) = *seqpath; if seqvar.segments.len() == 1; then { @@ -1655,7 +1655,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { if_chain! { // a range index op - if let ExprMethodCall(ref meth, _, ref args) = expr.node; + if let ExprKind::MethodCall(ref meth, _, ref args) = expr.node; if (meth.ident.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX)) || (meth.ident.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); if !self.check(&args[1], &args[0], expr); @@ -1664,14 +1664,14 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_chain! { // an index op - if let ExprIndex(ref seqexpr, ref idx) = expr.node; + if let ExprKind::Index(ref seqexpr, ref idx) = expr.node; if !self.check(idx, seqexpr, expr); then { return } } if_chain! { // directly using a variable - if let ExprPath(ref qpath) = expr.node; + if let ExprKind::Path(ref qpath) = expr.node; if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); @@ -1687,20 +1687,20 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } let old = self.prefer_mutable; match expr.node { - ExprAssignOp(_, ref lhs, ref rhs) | - ExprAssign(ref lhs, ref rhs) => { + ExprKind::AssignOp(_, ref lhs, ref rhs) | + ExprKind::Assign(ref lhs, ref rhs) => { self.prefer_mutable = true; self.visit_expr(lhs); self.prefer_mutable = false; self.visit_expr(rhs); }, - ExprAddrOf(mutbl, ref expr) => { + ExprKind::AddrOf(mutbl, ref expr) => { if mutbl == MutMutable { self.prefer_mutable = true; } self.visit_expr(expr); }, - ExprCall(ref f, ref args) => { + ExprKind::Call(ref f, ref args) => { self.visit_expr(f); for expr in args { let ty = self.cx.tables.expr_ty_adjusted(expr); @@ -1713,7 +1713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { self.visit_expr(expr); } }, - ExprMethodCall(_, _, ref args) => { + ExprKind::MethodCall(_, _, ref args) => { let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { self.prefer_mutable = false; @@ -1841,8 +1841,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { /// passed expression. The expression may be within a block. fn is_simple_break_expr(expr: &Expr) -> bool { match expr.node { - ExprBreak(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, - ExprBlock(ref b, _) => match extract_first_expr(b) { + ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, + ExprKind::Block(ref b, _) => match extract_first_expr(b) { Some(subexpr) => is_simple_break_expr(subexpr), None => false, }, @@ -1882,7 +1882,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { let state = self.states.entry(def_id).or_insert(VarState::Initial); match parent.node { - ExprAssignOp(op, ref lhs, ref rhs) => { + ExprKind::AssignOp(op, ref lhs, ref rhs) => { if lhs.id == expr.id { if op.node == BiAdd && is_integer_literal(rhs, 1) { *state = match *state { @@ -1895,8 +1895,8 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { } } }, - ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, - ExprAddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn, + ExprKind::Assign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn, + ExprKind::AddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn, _ => (), } } @@ -1969,17 +1969,17 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if var_def_id(self.cx, expr) == Some(self.var_id) { if let Some(parent) = get_parent_expr(self.cx, expr) { match parent.node { - ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => { + ExprKind::AssignOp(_, ref lhs, _) if lhs.id == expr.id => { self.state = VarState::DontWarn; }, - ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => { + ExprKind::Assign(ref lhs, ref rhs) if lhs.id == expr.id => { self.state = if is_integer_literal(rhs, 0) && self.depth == 0 { VarState::Warn } else { VarState::DontWarn } }, - ExprAddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn, + ExprKind::AddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn, _ => (), } } @@ -2005,7 +2005,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { } fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { - if let ExprPath(ref qpath) = expr.node { + if let ExprKind::Path(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.hir_id); if let Def::Local(node_id) = path_res { return Some(node_id); @@ -2016,14 +2016,14 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { fn is_loop(expr: &Expr) -> bool { match expr.node { - ExprLoop(..) | ExprWhile(..) => true, + ExprKind::Loop(..) | ExprKind::While(..) => true, _ => false, } } fn is_conditional(expr: &Expr) -> bool { match expr.node { - ExprIf(..) | ExprMatch(..) => true, + ExprKind::If(..) | ExprKind::Match(..) => true, _ => false, } } @@ -2053,7 +2053,7 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool } match cx.tcx.hir.find(parent) { Some(NodeExpr(expr)) => match expr.node { - ExprLoop(..) | ExprWhile(..) => { + ExprKind::Loop(..) | ExprKind::While(..) => { return true; }, _ => (), @@ -2111,7 +2111,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { + ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => if match_var(path, self.iterator) { self.nesting = RuledOut; }, _ => walk_expr(self, expr), @@ -2137,7 +2137,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { } fn path_name(e: &Expr) -> Option { - if let ExprPath(QPath::Resolved(_, ref path)) = e.node { + if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.node { let segments = &path.segments; if segments.len() == 1 { return Some(segments[0].ident.name); @@ -2193,7 +2193,7 @@ struct VarCollectorVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { fn insert_def_id(&mut self, ex: &'tcx Expr) { if_chain! { - if let ExprPath(ref qpath) = ex.node; + if let ExprKind::Path(ref qpath) = ex.node; if let QPath::Resolved(None, _) = *qpath; let def = self.cx.tables.qpath_def(qpath, ex.hir_id); then { @@ -2214,9 +2214,9 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { - ExprPath(_) => self.insert_def_id(ex), + ExprKind::Path(_) => self.insert_def_id(ex), // If there is any fuction/method call… we just stop analysis - ExprCall(..) | ExprMethodCall(..) => self.skip = true, + ExprKind::Call(..) | ExprKind::MethodCall(..) => self.skip = true, _ => walk_expr(self, ex), } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 0d58732f24d..01ce702c17c 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -30,10 +30,10 @@ pub struct Pass; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // call to .map() - if let ExprMethodCall(ref method, _, ref args) = expr.node { + if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if method.ident.name == "map" && args.len() == 2 { match args[1].node { - ExprClosure(_, ref decl, closure_eid, _, _) => { + ExprKind::Closure(_, ref decl, closure_eid, _, _) => { let body = cx.tcx.hir.body(closure_eid); let closure_expr = remove_blocks(&body.value); if_chain! { @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprMethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { + else if let ExprKind::MethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { if clone_call.ident.name == "clone" && clone_args.len() == 1 && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && @@ -77,7 +77,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } }, - ExprPath(ref path) => if match_qpath(path, &paths::CLONE) { + ExprKind::Path(ref path) => if match_qpath(path, &paths::CLONE) { let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); span_help_and_lint( cx, @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn expr_eq_name(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { match expr.node { - ExprPath(QPath::Resolved(None, ref path)) => { + ExprKind::Path(QPath::Resolved(None, ref path)) => { let arg_segment = [ PathSegment { ident: id, @@ -126,7 +126,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { match expr.node { - ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), + ExprKind::Unary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), _ => expr_eq_name(cx, expr, id), } } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index a1f4b70a4dc..598160bb3ef 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -115,12 +115,12 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { + hir::ExprKind::Call(_, _) | + hir::ExprKind::MethodCall(_, _, _) => { // Calls can't be reduced any more Some(expr.span) }, - hir::ExprBlock(ref block, _) => { + hir::ExprKind::Block(ref block, _) => { match (&block.stmts[..], block.expr.as_ref()) { (&[], Some(inner_expr)) => { // If block only contains an expression, @@ -151,7 +151,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { - if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node { + if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.node { let body = cx.tcx.hir.body(inner_expr_id); let body_expr = &body.value; @@ -175,8 +175,8 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op /// Anything else will return `_`. fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { match &var_arg.node { - hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), - hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")), + hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), + hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")), _ => "_".to_string() } } @@ -248,7 +248,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let hir::StmtSemi(ref expr, _) = stmt.node { - if let hir::ExprMethodCall(_, _, _) = expr.node { + if let hir::ExprKind::MethodCall(_, _, _) = expr.node { if let Some(arglists) = method_chain_args(expr, &["map"]) { lint_map_unit_fn(cx, stmt, expr, arglists[0]); } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index a14c6a0d8b9..c82d156462d 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -184,14 +184,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { if in_external_macro(cx, expr.span) { return; } - if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node { + if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.node { check_single_match(cx, ex, arms, expr); check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); check_wild_err_arm(cx, ex, arms); check_match_as_ref(cx, ex, arms, expr); } - if let ExprMatch(ref ex, ref arms, _) = expr.node { + if let ExprKind::Match(ref ex, ref arms, _) = expr.node { check_match_ref_pats(cx, ex, arms, expr); } } @@ -205,7 +205,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { let els = remove_blocks(&arms[1].body); let els = if is_unit_expr(els) { None - } else if let ExprBlock(_, _) = els.node { + } else if let ExprKind::Block(_, _) = els.node { // matches with blocks that contain statements are prettier as `if let + else` Some(els) } else { @@ -294,7 +294,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 { // no guards let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node { - if let ExprLit(ref lit) = arm_bool.node { + if let ExprKind::Lit(ref lit) = arm_bool.node { match lit.node { LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)), @@ -372,7 +372,7 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { if_chain! { if path_str == "Err"; if inner.iter().any(is_wild); - if let ExprBlock(ref block, _) = arm.body.node; + if let ExprKind::Block(ref block, _) = arm.body.node; if is_panic_block(block); then { // `Err(_)` arm with `panic!` found @@ -406,7 +406,7 @@ fn is_panic_block(block: &Block) -> bool { fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if has_only_ref_pats(arms) { let mut suggs = Vec::new(); - let (title, msg) = if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { + let (title, msg) = if let ExprKind::AddrOf(Mutability::MutImmutable, ref inner) = ex.node { suggs.push((ex.span, Sugg::hir(cx, inner, "..").to_string())); ( "you don't need to add `&` to both the expression and the patterns", @@ -540,8 +540,8 @@ fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { fn is_unit_expr(expr: &Expr) -> bool { match expr.node { - ExprTup(ref v) if v.is_empty() => true, - ExprBlock(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true, + ExprKind::Tup(ref v) if v.is_empty() => true, + ExprKind::Block(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true, _ => false, } } @@ -561,10 +561,10 @@ fn is_ref_some_arm(arm: &Arm) -> Option { if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); if let PatKind::Binding(rb, _, ident, _) = pats[0].node; if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; - if let ExprCall(ref e, ref args) = remove_blocks(&arm.body).node; - if let ExprPath(ref some_path) = e.node; + if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).node; + if let ExprKind::Path(ref some_path) = e.node; if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; - if let ExprPath(ref qpath) = args[0].node; + if let ExprKind::Path(ref qpath) = args[0].node; if let &QPath::Resolved(_, ref path2) = qpath; if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; then { diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 816c1bb6fbf..11cf8a9a791 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::hir::{Expr, ExprCall, ExprPath}; +use rustc::hir::{Expr, ExprKind}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is @@ -30,8 +30,8 @@ impl LintPass for MemForget { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(ref qpath) = path_expr.node { + if let ExprKind::Call(ref path_expr, ref args) = e.node { + if let ExprKind::Path(ref qpath) = path_expr.node { if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) { if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.tables.expr_ty(&args[0]); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index ca739558e62..ee7658334b3 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -718,7 +718,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match expr.node { - hir::ExprMethodCall(ref method_call, ref method_span, ref args) => { + hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { // Chain calls // GET_UNWRAP needs to be checked before general `UNWRAP` lints if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) { @@ -789,7 +789,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => (), } }, - hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { + hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { let mut info = BinaryExprInfo { expr, chain: lhs, @@ -889,7 +889,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: } if name == "unwrap_or" { - if let hir::ExprPath(ref qpath) = fun.node { + if let hir::ExprKind::Path(ref qpath) = fun.node { let path = &*last_path_segment(qpath).ident.as_str(); if ["default", "new"].contains(&path) { @@ -982,13 +982,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: if args.len() == 2 { match args[1].node { - hir::ExprCall(ref fun, ref or_args) => { + hir::ExprKind::Call(ref fun, ref or_args) => { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span); } }, - hir::ExprMethodCall(_, span, ref or_args) => { + hir::ExprKind::MethodCall(_, span, ref or_args) => { check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span) }, _ => {}, @@ -999,10 +999,10 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { - if let hir::ExprAddrOf(_, ref addr_of) = arg.node { - if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node { + if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node { + if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node { if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { - if let hir::ExprCall(_, ref format_args) = inner_args[0].node { + if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { return Some(format_args); } } @@ -1013,9 +1013,9 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } fn generate_format_arg_snippet(cx: &LateContext, a: &hir::Expr) -> String { - if let hir::ExprAddrOf(_, ref format_arg) = a.node { - if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node { - if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node { + if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { + if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { + if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); } } @@ -1090,7 +1090,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n if args.len() == 2 { match args[1].node { - hir::ExprLit(_) => {}, + hir::ExprKind::Lit(_) => {}, _ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span), } } @@ -1133,9 +1133,9 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t match cx.tcx.hir.get(parent) { hir::map::NodeExpr(parent) => match parent.node { // &*x is a nop, &x.clone() is not - hir::ExprAddrOf(..) | + hir::ExprKind::AddrOf(..) | // (*x).func() is useless, x.clone().func() can work in case func borrows mutably - hir::ExprMethodCall(..) => return, + hir::ExprKind::MethodCall(..) => return, _ => {}, } hir::map::NodeStmt(stmt) => { @@ -1229,9 +1229,9 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { if_chain! { - if let hir::ExprCall(ref fun, ref args) = new.node; + if let hir::ExprKind::Call(ref fun, ref args) = new.node; if args.len() == 1; - if let hir::ExprPath(ref path) = fun.node; + if let hir::ExprKind::Path(ref path) = fun.node; if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); then { @@ -1280,12 +1280,12 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E if_chain! { // Extract the body of the closure passed to fold - if let hir::ExprClosure(_, _, body_id, _, _) = fold_args[2].node; + if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node; let closure_body = cx.tcx.hir.body(body_id); let closure_expr = remove_blocks(&closure_body.value); // Check if the closure body is of the form `acc some_expr(x)` - if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; + if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; if bin_op.node == op; // Extract the names of the two arguments to the closure @@ -1329,7 +1329,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E // Check if the first argument to .fold is a suitable literal match fold_args[1].node { - hir::ExprLit(ref lit) => { + hir::ExprKind::Lit(ref lit) => { match lit.node { ast::LitKind::Bool(false) => check_fold_with_op( cx, fold_args, hir::BinOp_::BiOr, "any", true @@ -1437,7 +1437,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option( fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { // check if the first non-self argument to map_or() is None - let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node { + let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].node { match_qpath(qpath, &paths::OPTION_NONE) } else { false @@ -1790,9 +1790,9 @@ fn lint_chars_cmp<'a, 'tcx>( ) -> bool { if_chain! { if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprCall(ref fun, ref arg_char) = info.other.node; + if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.node; if arg_char.len() == 1; - if let hir::ExprPath(ref qpath) = fun.node; + if let hir::ExprKind::Path(ref qpath) = fun.node; if let Some(segment) = single_segment_path(qpath); if segment.ident.name == "Some"; then { @@ -1844,7 +1844,7 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( ) -> bool { if_chain! { if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprLit(ref lit) = info.other.node; + if let hir::ExprKind::Lit(ref lit) = info.other.node; if let ast::LitKind::Char(c) = lit.node; then { span_lint_and_sugg( diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 4be2b9f5227..fa2c9fda731 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -66,8 +66,8 @@ enum MinMax { } fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { - if let ExprCall(ref path, ref args) = expr.node { - if let ExprPath(ref qpath) = path.node { + if let ExprKind::Call(ref path, ref args) = expr.node { + if let ExprKind::Path(ref qpath) = path.node { opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)).and_then(|def_id| { if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { fetch_const(cx, args, MinMax::Min) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 4fc65b2f89a..f701f957031 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -304,7 +304,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }; if_chain! { if let StmtSemi(ref expr, _) = s.node; - if let Expr_::ExprBinary(ref binop, ref a, ref b) = expr.node; + if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node; if binop.node == BiAnd || binop.node == BiOr; if let Some(sugg) = Sugg::hir_opt(cx, a); then { @@ -323,17 +323,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { - ExprCast(ref e, ref ty) => { + ExprKind::Cast(ref e, ref ty) => { check_cast(cx, expr.span, e, ty); return; }, - ExprBinary(ref cmp, ref left, ref right) => { + ExprKind::Binary(ref cmp, ref left, ref right) => { let op = cmp.node; if op.is_comparison() { - if let ExprPath(QPath::Resolved(_, ref path)) = left.node { + if let ExprKind::Path(QPath::Resolved(_, ref path)) = left.node { check_nan(cx, path, expr); } - if let ExprPath(QPath::Resolved(_, ref path)) = right.node { + if let ExprKind::Path(QPath::Resolved(_, ref path)) = right.node { check_nan(cx, path, expr); } check_to_owned(cx, left, right); @@ -378,7 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } let binding = match expr.node { - ExprPath(ref qpath) => { + ExprKind::Path(ref qpath) => { let binding = last_path_segment(qpath).ident.as_str(); if binding.starts_with('_') && !binding.starts_with("__") && @@ -392,7 +392,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { None } }, - ExprField(_, ident) => { + ExprKind::Field(_, ident) => { let name = ident.as_str(); if name.starts_with('_') && !name.starts_with("__") { Some(name) @@ -467,14 +467,14 @@ fn is_float(cx: &LateContext, expr: &Expr) -> bool { fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { let (arg_ty, snip) = match expr.node { - ExprMethodCall(.., ref args) if args.len() == 1 => { + ExprKind::MethodCall(.., ref args) if args.len() == 1 => { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { (cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, "..")) } else { return; } }, - ExprCall(ref path, ref v) if v.len() == 1 => if let ExprPath(ref path) = path.node { + ExprKind::Call(ref path, ref v) if v.len() == 1 => if let ExprKind::Path(ref path) = path.node { if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) } else { @@ -542,7 +542,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), + ExprKind::Assign(_, ref rhs) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), _ => is_used(cx, parent), } } else { @@ -572,7 +572,7 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { if_chain! { if let TyPtr(MutTy { mutbl, .. }) = ty.node; - if let ExprLit(ref lit) = e.node; + if let ExprKind::Lit(ref lit) = e.node; if let LitKind::Int(value, ..) = lit.node; if value == 0; if !in_constant(cx, e.id); diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 26837313a06..fa8bb73f21c 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -62,8 +62,8 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { // Let's ignore the generated code. intravisit::walk_expr(self, arg); intravisit::walk_expr(self, body); - } else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node { - if let hir::ExprAddrOf(hir::MutMutable, _) = e.node { + } else if let hir::ExprKind::AddrOf(hir::MutMutable, ref e) = expr.node { + if let hir::ExprKind::AddrOf(hir::MutMutable, _) = e.node { span_lint( self.cx, MUT_MUT, diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 4e9c5c815cc..b4d6652a65a 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -36,7 +36,7 @@ impl LintPass for UnnecessaryMutPassed { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { match e.node { - ExprCall(ref fn_expr, ref arguments) => if let ExprPath(ref path) = fn_expr.node { + ExprKind::Call(ref fn_expr, ref arguments) => if let ExprKind::Path(ref path) = fn_expr.node { check_arguments( cx, arguments, @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), ); }, - ExprMethodCall(ref path, _, ref arguments) => { + ExprKind::MethodCall(ref path, _, ref arguments) => { let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); let substs = cx.tables.node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); @@ -69,7 +69,7 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. - }) => if let ExprAddrOf(MutMutable, _) = argument.node { + }) => if let ExprKind::AddrOf(MutMutable, _) = argument.node { span_lint( cx, UNNECESSARY_MUT_PASSED, diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 885cb4b72cb..03c602bc234 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -60,7 +60,7 @@ impl LintPass for NeedlessBool { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; - if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node { + if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node { let reduce = |ret, not| { let snip = Sugg::hir(cx, pred, ""); let snip = if not { !snip } else { snip }; @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { hint, ); }; - if let ExprBlock(ref then_block, _) = then_block.node { + if let ExprKind::Block(ref then_block, _) = then_block.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { span_lint( @@ -105,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { _ => (), } } else { - panic!("IfExpr 'then' node is not an ExprBlock"); + panic!("IfExpr 'then' node is not an ExprKind::Block"); } } } @@ -123,7 +123,7 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; - if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { + if let ExprKind::Binary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { let hint = snippet(cx, right_side.span, "..").into_owned(); @@ -185,7 +185,7 @@ fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), (&[ref e], None) => if let StmtSemi(ref e, _) = e.node { - if let ExprRet(_) = e.node { + if let ExprKind::Ret(_) = e.node { fetch_bool_expr(&**e) } else { Expression::Other @@ -199,13 +199,13 @@ fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { - ExprBlock(ref block, _) => fetch_bool_block(block), - ExprLit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { + ExprKind::Block(ref block, _) => fetch_bool_block(block), + ExprKind::Lit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { Expression::Bool(value) } else { Expression::Other }, - ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { + ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) { Expression::Bool(value) => Expression::RetBool(value), _ => Expression::Other, }, diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 84d5292d8c5..90e41bc6f68 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind}; +use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if in_macro(e.span) { return; } - if let ExprAddrOf(MutImmutable, ref inner) = e.node { + if let ExprKind::AddrOf(MutImmutable, ref inner) = e.node { if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty { for adj3 in cx.tables.expr_adjustments(e).windows(3) { if let [Adjustment { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index bdef092b533..cedc3fdfd28 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -339,7 +339,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { match node { map::Node::NodeExpr(e) => { // `match` and `if let` - if let ExprMatch(ref c, ..) = e.node { + if let ExprKind::Match(ref c, ..) = e.node { self.spans_need_deref .entry(vid) .or_insert_with(HashSet::new) diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 87b92a53dd0..9c670c1a5b3 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::hir::{Expr, ExprStruct}; +use rustc::hir::{Expr, ExprKind}; use crate::utils::span_lint; /// **What it does:** Checks for needlessly including a base struct on update @@ -32,7 +32,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { + if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tables.expr_ty(expr); if let ty::TyAdt(def, _) = ty.sty { if fields.len() == def.non_enum_variant().fields.len() { diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 013bab69d79..2eb63c264fd 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -18,20 +18,20 @@ use crate::utils::{self, paths, span_lint, in_external_macro}; /// /// ```rust /// use core::cmp::Ordering; -/// +/// /// // Bad /// let a = 1.0; /// let b = std::f64::NAN; -/// +/// /// let _not_less_or_equal = !(a <= b); /// /// // Good /// let a = 1.0; /// let b = std::f64::NAN; -/// +/// /// let _not_less_or_equal = match a.partial_cmp(&b) { /// None | Some(Ordering::Greater) => true, -/// _ => false, +/// _ => false, /// }; /// ``` declare_clippy_lint! { @@ -54,8 +54,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { if_chain! { if !in_external_macro(cx, expr.span); - if let Expr_::ExprUnary(UnOp::UnNot, ref inner) = expr.node; - if let Expr_::ExprBinary(ref op, ref left, _) = inner.node; + if let ExprKind::Unary(UnOp::UnNot, ref inner) = expr.node; + if let ExprKind::Binary(ref op, ref left, _) = inner.node; if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node; then { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index efcc1695eb6..70cc9eecf6e 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -33,11 +33,11 @@ impl LintPass for NegMultiply { #[allow(match_same_arms)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { + if let ExprKind::Binary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { match (&l.node, &r.node) { - (&ExprUnary(..), &ExprUnary(..)) => (), - (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), - (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), + (&ExprKind::Unary(..), &ExprKind::Unary(..)) => (), + (&ExprKind::Unary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), + (_, &ExprKind::Unary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l), _ => (), } } @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { if_chain! { - if let ExprLit(ref l) = lit.node; + if let ExprKind::Lit(ref l) = lit.node; if let Constant::Int(val) = consts::lit_to_constant(&l.node, cx.tables.expr_ty(lit)); if val == 1; if cx.tables.expr_ty(exp).is_integral(); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 8d351f87421..fea0a83b444 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,6 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; -use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; +use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; @@ -45,26 +45,26 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { return false; } match expr.node { - Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) => true, - Expr_::ExprPath(..) => !has_drop(cx, expr), - Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => { + ExprKind::Lit(..) | ExprKind::Closure(.., _) => true, + ExprKind::Path(..) => !has_drop(cx, expr), + ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => { has_no_effect(cx, a) && has_no_effect(cx, b) }, - Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), - Expr_::ExprRepeat(ref inner, _) | - Expr_::ExprCast(ref inner, _) | - Expr_::ExprType(ref inner, _) | - Expr_::ExprUnary(_, ref inner) | - Expr_::ExprField(ref inner, _) | - Expr_::ExprAddrOf(_, ref inner) | - Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), - Expr_::ExprStruct(_, ref fields, ref base) => { + ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), + ExprKind::Repeat(ref inner, _) | + ExprKind::Cast(ref inner, _) | + ExprKind::Type(ref inner, _) | + ExprKind::Unary(_, ref inner) | + ExprKind::Field(ref inner, _) | + ExprKind::AddrOf(_, ref inner) | + ExprKind::Box(ref inner) => has_no_effect(cx, inner), + ExprKind::Struct(_, ref fields, ref base) => { !has_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { Some(ref base) => has_no_effect(cx, base), None => true, } }, - Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { + ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { @@ -75,7 +75,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } else { false }, - Expr_::ExprBlock(ref block, _) => { + ExprKind::Block(ref block, _) => { block.stmts.is_empty() && if let Some(ref expr) = block.expr { has_no_effect(cx, expr) } else { @@ -132,19 +132,19 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option Some(vec![&**a, &**b]), - Expr_::ExprBinary(ref binop, ref a, ref b) if binop.node != BiAnd && binop.node != BiOr => { + ExprKind::Index(ref a, ref b) => Some(vec![&**a, &**b]), + ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BiAnd && binop.node != BiOr => { Some(vec![&**a, &**b]) }, - Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => Some(v.iter().collect()), - Expr_::ExprRepeat(ref inner, _) | - Expr_::ExprCast(ref inner, _) | - Expr_::ExprType(ref inner, _) | - Expr_::ExprUnary(_, ref inner) | - Expr_::ExprField(ref inner, _) | - Expr_::ExprAddrOf(_, ref inner) | - Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => if has_drop(cx, expr) { + ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()), + ExprKind::Repeat(ref inner, _) | + ExprKind::Cast(ref inner, _) | + ExprKind::Type(ref inner, _) | + ExprKind::Unary(_, ref inner) | + ExprKind::Field(ref inner, _) | + ExprKind::AddrOf(_, ref inner) | + ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), + ExprKind::Struct(_, ref fields, ref base) => if has_drop(cx, expr) { None } else { Some( @@ -156,7 +156,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option if let Expr_::ExprPath(ref qpath) = callee.node { + ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) @@ -169,7 +169,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { + ExprKind::Block(ref block, _) => { if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| { match block.rules { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 47c84fec6ae..4e3142e4517 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -190,7 +190,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { } fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprPath(qpath) = &expr.node { + if let ExprKind::Path(qpath) = &expr.node { // Only lint if we use the const item inside a function. if in_constant(cx, expr.id) { return; @@ -213,22 +213,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { } if let Some(map::NodeExpr(parent_expr)) = cx.tcx.hir.find(parent_id) { match &parent_expr.node { - ExprAddrOf(..) => { + ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced needs_check_adjustment = false; } - ExprField(..) => { + ExprKind::Field(..) => { dereferenced_expr = parent_expr; needs_check_adjustment = true; } - ExprIndex(e, _) if ptr::eq(&**e, cur_expr) => { + ExprKind::Index(e, _) if ptr::eq(&**e, cur_expr) => { // `e[i]` => desugared to `*Index::index(&e, i)`, // meaning `e` must be referenced. // no need to go further up since a method call is involved now. needs_check_adjustment = false; break; } - ExprUnary(UnDeref, _) => { + ExprKind::Unary(UnDeref, _) => { // `*e` => desugared to `*Deref::deref(&e)`, // meaning `e` must be referenced. // no need to go further up since a method call is involved now. diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index a2573b91f96..0a1399075e0 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -44,9 +44,9 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { //begin checking variables - if let ExprMatch(ref op, ref body, ref source) = expr.node; //test if expr is a match + if let ExprKind::Match(ref op, ref body, ref source) = expr.node; //test if expr is a match if let MatchSource::IfLetDesugar { .. } = *source; //test if it is an If Let - if let ExprMethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result.ok() + if let ExprKind::MethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result.ok() if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node; //get operation if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index fbece822659..b4559969ac2 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,4 +1,4 @@ -use rustc::hir::{Expr, ExprLit, ExprMethodCall}; +use rustc::hir::{Expr, ExprKind}; use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; @@ -33,7 +33,7 @@ impl LintPass for NonSensical { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprMethodCall(ref path, _, ref arguments) = e.node { + if let ExprKind::MethodCall(ref path, _, ref arguments) = e.node { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); if path.ident.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); @@ -61,13 +61,13 @@ enum OpenOption { } fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { - if let ExprMethodCall(ref path, _, ref arguments) = argument.node { + if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.node { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); // Only proceed if this is a call on some object of type std::fs::OpenOptions if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { let argument_option = match arguments[1].node { - ExprLit(ref span) => { + ExprKind::Lit(ref span) => { if let Spanned { node: LitKind::Bool(lit), .. diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index c5b0c977956..4e63fc2f7fc 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -33,11 +33,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r); if_chain! { - if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node; - if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node; + if let ExprKind::Binary(ref op, ref first, ref second) = expr.node; + if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = first.node; + if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.node; + if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.node; + if let ExprKind::Path(QPath::Resolved(_, ref path3)) = second.node; if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); @@ -58,11 +58,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { } if_chain! { - if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node; - if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node; - if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node; + if let ExprKind::Binary(ref op, ref first, ref second) = expr.node; + if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = second.node; + if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.node; + if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.node; + if let ExprKind::Path(QPath::Resolved(_, ref path3)) = first.node; if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index f00a15dd401..24cf6544f6a 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -52,10 +52,10 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprBlock(ref block, _) = expr.node; + if let ExprKind::Block(ref block, _) = expr.node; if let Some(ref ex) = block.expr; - if let ExprCall(ref fun, ref params) = ex.node; - if let ExprPath(ref qpath) = fun.node; + if let ExprKind::Call(ref fun, ref params) = ex.node; + if let ExprKind::Path(ref qpath) = fun.node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); if params.len() == 2; @@ -86,7 +86,7 @@ fn get_outer_span(expr: &Expr) -> Span { fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { if_chain! { - if let ExprLit(ref lit) = params[0].node; + if let ExprKind::Lit(ref lit) = params[0].node; if is_direct_expn_of(expr.span, "panic").is_some(); if let LitKind::Str(ref string, _) = lit.node; let string = string.as_str().replace("{{", "").replace("}}", ""); diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 68cecc8de67..a2c204dd149 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprBinary(ref op, ref l, ref r) = expr.node { + if let ExprKind::Binary(ref op, ref l, ref r) = expr.node { if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) { span_lint( cx, @@ -281,9 +281,9 @@ fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> { } fn is_null_path(expr: &Expr) -> bool { - if let ExprCall(ref pathexp, ref args) = expr.node { + if let ExprKind::Call(ref pathexp, ref args) = expr.node { if args.is_empty() { - if let ExprPath(ref path) = pathexp.node { + if let ExprKind::Path(ref path) = pathexp.node { return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT); } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index d12f6ddd15a..e6d231af148 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -52,8 +52,8 @@ impl QuestionMarkPass { /// If it matches, it will suggest to use the question mark operator instead fn check_is_none_and_early_return_none(cx: &LateContext, expr: &Expr) { if_chain! { - if let ExprIf(ref if_expr, ref body, _) = expr.node; - if let ExprMethodCall(ref segment, _, ref args) = if_expr.node; + if let ExprKind::If(ref if_expr, ref body, _) = expr.node; + if let ExprKind::MethodCall(ref segment, _, ref args) = if_expr.node; if segment.ident.name == "is_none"; if Self::expression_returns_none(cx, body); if let Some(subject) = args.get(0); @@ -87,17 +87,17 @@ impl QuestionMarkPass { fn expression_returns_none(cx: &LateContext, expression: &Expr) -> bool { match expression.node { - ExprBlock(ref block, _) => { + ExprKind::Block(ref block, _) => { if let Some(return_expression) = Self::return_expression(block) { return Self::expression_returns_none(cx, &return_expression); } false }, - ExprRet(Some(ref expr)) => { + ExprKind::Ret(Some(ref expr)) => { Self::expression_returns_none(cx, expr) }, - ExprPath(ref qp) => { + ExprKind::Path(ref qp) => { if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { return match_def_path(cx.tcx, def_id, &OPTION_NONE); } @@ -114,7 +114,7 @@ impl QuestionMarkPass { if block.stmts.len() == 1; if let Some(expr) = block.stmts.iter().last(); if let StmtSemi(ref expr, _) = expr.node; - if let ExprRet(ref ret_expr) = expr.node; + if let ExprKind::Ret(ref ret_expr) = expr.node; if let &Some(ref ret_expr) = ret_expr; then { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c0fac47b34e..e33e112f051 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -88,7 +88,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprMethodCall(ref path, _, ref args) = expr.node { + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node { let name = path.ident.as_str(); // Range with step_by(0). @@ -107,17 +107,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let zip_arg = &args[1]; if_chain! { // .iter() call - if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter; + if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter; if iter_path.ident.name == "iter"; // range expression in .zip() call: 0..x.len() if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); if is_integer_literal(start, 0); // .len() call - if let ExprMethodCall(ref len_path, _, ref len_args) = end.node; + if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node; if len_path.ident.name == "len" && len_args.len() == 1; // .iter() and .len() called on same Path - if let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; - if let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node; + if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; + if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node; if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments); then { span_lint(cx, @@ -184,7 +184,7 @@ fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { fn y_plus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprBinary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { + ExprKind::Binary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { Some(rhs) } else if is_integer_literal(rhs, 1) { Some(lhs) @@ -197,7 +197,7 @@ fn y_plus_one(expr: &Expr) -> Option<&Expr> { fn y_minus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprBinary(Spanned { node: BiSub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), + ExprKind::Binary(Spanned { node: BiSub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), _ => None, } } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index e63e978e26b..d179bffd59a 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { return; } - if let ExprStruct(_, ref fields, _) = expr.node { + if let ExprKind::Struct(_, ref fields, _) = expr.node { for field in fields { let name = field.ident.name; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 6395125578c..fbead26a03b 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -108,8 +108,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprCall(ref fun, ref args) = expr.node; - if let ExprPath(ref qpath) = fun.node; + if let ExprKind::Call(ref fun, ref args) = expr.node; + if let ExprKind::Path(ref qpath) = fun.node; if args.len() == 1; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, fun.hir_id)); then { @@ -176,8 +176,8 @@ fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: bool) { if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; - if let ExprArray(ref exprs) = expr.node; + if let ExprKind::AddrOf(_, ref expr) = expr.node; + if let ExprKind::Array(ref exprs) = expr.node; then { for expr in exprs { check_regex(cx, expr, utf8); @@ -192,7 +192,7 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo .allow_invalid_utf8(!utf8) .build(); - if let ExprLit(ref lit) = expr.node { + if let ExprKind::Lit(ref lit) = expr.node { if let LitKind::Str(ref r, style) = lit.node { let r = &r.as_str(); let offset = if let StrStyle::Raw(n) = style { 2 + n } else { 1 }; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index d6d9125a49c..f149e324877 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -37,7 +37,7 @@ impl LintPass for ReplaceConsts { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if_chain! { - if let hir::ExprPath(ref qp) = expr.node; + if let hir::ExprKind::Path(ref qp) = expr.node; if let Def::Const(def_id) = cx.tables.qpath_def(qp, expr.hir_id); then { for &(const_path, repl_snip) in REPLACEMENTS { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index d37023e4f8c..cbcdbf73e33 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -185,7 +185,7 @@ fn check_pat<'a, 'tcx>( } }, PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init { - if let ExprStruct(_, ref efields, _) = init_struct.node { + if let ExprKind::Struct(_, ref efields, _) = init_struct.node { for field in pfields { let name = field.node.ident.name; let efield = efields @@ -205,7 +205,7 @@ fn check_pat<'a, 'tcx>( } }, PatKind::Tuple(ref inner, _) => if let Some(init_tup) = init { - if let ExprTup(ref tup) = init_tup.node { + if let ExprKind::Tup(ref tup) = init_tup.node { for (i, p) in inner.iter().enumerate() { check_pat(cx, p, Some(&tup[i]), p.span, bindings); } @@ -220,7 +220,7 @@ fn check_pat<'a, 'tcx>( } }, PatKind::Box(ref inner) => if let Some(initp) = init { - if let ExprBox(ref inner_init) = initp.node { + if let ExprKind::Box(ref inner_init) = initp.node { check_pat(cx, inner, Some(&**inner_init), span, bindings); } else { check_pat(cx, inner, init, span, bindings); @@ -306,27 +306,27 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: return; } match expr.node { - ExprUnary(_, ref e) | ExprField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { + ExprKind::Unary(_, ref e) | ExprKind::Field(ref e, _) | ExprKind::AddrOf(_, ref e) | ExprKind::Box(ref e) => { check_expr(cx, e, bindings) }, - ExprBlock(ref block, _) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), - // ExprCall - // ExprMethodCall - ExprArray(ref v) | ExprTup(ref v) => for e in v { + ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings), + // ExprKind::Call + // ExprKind::MethodCall + ExprKind::Array(ref v) | ExprKind::Tup(ref v) => for e in v { check_expr(cx, e, bindings) }, - ExprIf(ref cond, ref then, ref otherwise) => { + ExprKind::If(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); check_expr(cx, &**then, bindings); if let Some(ref o) = *otherwise { check_expr(cx, o, bindings); } }, - ExprWhile(ref cond, ref block, _) => { + ExprKind::While(ref cond, ref block, _) => { check_expr(cx, cond, bindings); check_block(cx, block, bindings); }, - ExprMatch(ref init, ref arms, _) => { + ExprKind::Match(ref init, ref arms, _) => { check_expr(cx, init, bindings); let len = bindings.len(); for arm in arms { @@ -363,16 +363,16 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { - ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), - ExprBlock(ref block, _) => { + ExprKind::Box(ref inner) | ExprKind::AddrOf(_, ref inner) => is_self_shadow(name, inner), + ExprKind::Block(ref block, _) => { block.stmts.is_empty() && block .expr .as_ref() .map_or(false, |e| is_self_shadow(name, e)) }, - ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), - ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path), + ExprKind::Unary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), + ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path), _ => false, } } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 62cd5de68f0..fb9becbd43b 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -82,12 +82,12 @@ impl LintPass for StringAdd { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { + if let ExprKind::Binary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { if is_string(cx, left) { if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) { let parent = get_parent_expr(cx, e); if let Some(p) = parent { - if let ExprAssign(ref target, _) = p.node { + if let ExprKind::Assign(ref target, _) = p.node { // avoid duplicate matches if SpanlessEq::new(cx).eq_expr(target, left) { return; @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { "you added something to a string. Consider using `String::push_str()` instead", ); } - } else if let ExprAssign(ref target, ref src) = e.node { + } else if let ExprKind::Assign(ref target, ref src) = e.node { if is_string(cx, target) && is_add(cx, src, target) { span_lint( cx, @@ -122,8 +122,8 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), - ExprBlock(ref block, _) => { + ExprKind::Binary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), + ExprKind::Block(ref block, _) => { block.stmts.is_empty() && block .expr @@ -148,9 +148,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { use syntax::ast::LitKind; use crate::utils::{in_macro, snippet}; - if let ExprMethodCall(ref path, _, ref args) = e.node { + if let ExprKind::MethodCall(ref path, _, ref args) = e.node { if path.ident.name == "as_bytes" { - if let ExprLit(ref lit) = args[0].node { + if let ExprKind::Lit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) { span_lint_and_sugg( diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index e3ccfec4685..a3342591a1b 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -60,7 +60,7 @@ impl LintPass for SuspiciousImpl { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { use rustc::hir::BinOp_::*; - if let hir::ExprBinary(binop, _, _) = expr.node { + if let hir::ExprKind::Binary(binop, _, _) = expr.node { match binop.node { BiEq | BiLt | BiLe | BiNe | BiGe | BiGt => return, _ => {}, @@ -71,9 +71,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { while parent_expr != ast::CRATE_NODE_ID { if let hir::map::Node::NodeExpr(e) = cx.tcx.hir.get(parent_expr) { match e.node { - hir::ExprBinary(..) - | hir::ExprUnary(hir::UnOp::UnNot, _) - | hir::ExprUnary(hir::UnOp::UnNeg, _) => return, + hir::ExprKind::Binary(..) + | hir::ExprKind::Unary(hir::UnOp::UnNot, _) + | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => return, _ => {}, } } @@ -185,9 +185,9 @@ struct BinaryExprVisitor { impl<'a, 'tcx: 'a> Visitor<'tcx> for BinaryExprVisitor { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBinary(..) - | hir::ExprUnary(hir::UnOp::UnNot, _) - | hir::ExprUnary(hir::UnOp::UnNeg, _) => { + hir::ExprKind::Binary(..) + | hir::ExprKind::Unary(hir::UnOp::UnNot, _) + | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => { self.in_binary_expr = true }, _ => {}, diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 1037a1bc632..7a124e59a6e 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -68,12 +68,12 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { // foo() = bar(); if let StmtSemi(ref first, _) = w[1].node; - if let ExprAssign(ref lhs1, ref rhs1) = first.node; + if let ExprKind::Assign(ref lhs1, ref rhs1) = first.node; // bar() = t; if let StmtSemi(ref second, _) = w[2].node; - if let ExprAssign(ref lhs2, ref rhs2) = second.node; - if let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node; + if let ExprKind::Assign(ref lhs2, ref rhs2) = second.node; + if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.node; if rhs2.segments.len() == 1; if ident.as_str() == rhs2.segments[0].ident.as_str(); @@ -85,8 +85,8 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { lhs1: &'a Expr, lhs2: &'a Expr, ) -> Option<(&'a Expr, &'a Expr, &'a Expr)> { - if let ExprIndex(ref lhs1, ref idx1) = lhs1.node { - if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { + if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.node { + if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.node { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); @@ -148,8 +148,8 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) { if let StmtSemi(ref first, _) = w[0].node; if let StmtSemi(ref second, _) = w[1].node; if !differing_macro_contexts(first.span, second.span); - if let ExprAssign(ref lhs0, ref rhs0) = first.node; - if let ExprAssign(ref lhs1, ref rhs1) = second.node; + if let ExprKind::Assign(ref lhs0, ref rhs0) = first.node; + if let ExprKind::Assign(ref lhs1, ref rhs1) = second.node; if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1); if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0); then { diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index cd13ab0d51f..008ab56bda8 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup}; +use rustc::hir::{Expr, ExprKind}; use crate::utils::is_adjusted; use crate::utils::span_lint; @@ -23,7 +23,7 @@ declare_clippy_lint! { fn is_temporary(expr: &Expr) -> bool { match expr.node { - ExprStruct(..) | ExprTup(..) => true, + ExprKind::Struct(..) | ExprKind::Tup(..) => true, _ => false, } } @@ -39,8 +39,8 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprAssign(ref target, _) = expr.node { - if let ExprField(ref base, _) = target.node { + if let ExprKind::Assign(ref target, _) = expr.node { + if let ExprKind::Field(ref base, _) = target.node { if is_temporary(base) && !is_adjusted(cx, base) { span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index c2e981979a1..9d3055c3e63 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -215,8 +215,8 @@ impl LintPass for Transmute { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(ref qpath) = path_expr.node { + if let ExprKind::Call(ref path_expr, ref args) = e.node { + if let ExprKind::Path(ref qpath) = path_expr.node { if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) { if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { let from_ty = cx.tables.expr_ty(&args[0]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 61d496c1f0d..6c7c62c741a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -446,7 +446,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { if in_macro(expr.span) { return; } - if let ExprBinary(ref cmp, ref left, _) = expr.node { + if let ExprKind::Binary(ref cmp, ref left, _) = expr.node { let op = cmp.node; if op.is_comparison() && is_unit(cx.tables.expr_ty(left)) { let result = match op { @@ -501,7 +501,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { return; } match expr.node { - ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => { + ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => { for arg in args { if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { let map = &cx.tcx.hir; @@ -539,7 +539,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { use syntax_pos::hygiene::CompilerDesugaringKind; - if let ExprCall(ref callee, _) = expr.node { + if let ExprKind::Call(ref callee, _) = expr.node { callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark) } else { false @@ -555,7 +555,7 @@ fn is_unit(ty: Ty) -> bool { fn is_unit_literal(expr: &Expr) -> bool { match expr.node { - ExprTup(ref slice) if slice.is_empty() => true, + ExprKind::Tup(ref slice) if slice.is_empty() => true, _ => false, } } @@ -812,7 +812,7 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t } fn should_strip_parens(op: &Expr, snip: &str) -> bool { - if let ExprBinary(_, _, _) = op.node { + if let ExprKind::Binary(_, _, _) = op.node { if snip.starts_with('(') && snip.ends_with(')') { return true; } @@ -951,9 +951,9 @@ impl LintPass for CastPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprCast(ref ex, _) = expr.node { + if let ExprKind::Cast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); - if let ExprLit(ref lit) = ex.node { + if let ExprKind::Lit(ref lit) = ex.node { use syntax::ast::{LitIntType, LitKind}; match lit.node { LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, @@ -1289,8 +1289,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { use syntax::ast::{LitKind, UintTy}; - if let ExprCast(ref e, _) = expr.node { - if let ExprLit(ref l) = e.node { + if let ExprKind::Cast(ref e, _) = expr.node { + if let ExprKind::Lit(ref l) = e.node { if let LitKind::Char(_) = l.node { if ty::TyUint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(expr.span) { let msg = "casting character literal to u8. `char`s \ @@ -1362,7 +1362,7 @@ fn is_cast_between_fixed_and_target<'a, 'tcx>( expr: &'tcx Expr ) -> bool { - if let ExprCast(ref cast_exp, _) = expr.node { + if let ExprKind::Cast(ref cast_exp, _) = expr.node { let precast_ty = cx.tables.expr_ty(cast_exp); let cast_ty = cx.tables.expr_ty(expr); @@ -1453,7 +1453,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { use crate::types::ExtremeType::*; use crate::types::AbsurdComparisonResult::*; - if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node { if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { if !in_macro(expr.span) { let msg = "this comparison involving the minimum or maximum element for this \ @@ -1564,7 +1564,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( use syntax::ast::{IntTy, UintTy}; use std::*; - if let ExprCast(ref cast_exp, _) = expr.node { + if let ExprKind::Cast(ref cast_exp, _) = expr.node { let pre_cast_ty = cx.tables.expr_ty(cast_exp); let cast_ty = cx.tables.expr_ty(expr); // if it's a cast from i32 to u32 wrapping will invalidate all these checks @@ -1627,7 +1627,7 @@ fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) } fn err_upcast_comparison(cx: &LateContext, span: Span, expr: &Expr, always: bool) { - if let ExprCast(ref cast_val, _) = expr.node { + if let ExprKind::Cast(ref cast_val, _) = expr.node { span_lint( cx, INVALID_UPCAST_COMPARISONS, @@ -1693,7 +1693,7 @@ fn upcast_comparison_bounds_err<'a, 'tcx>( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { + if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node { let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { val @@ -1984,8 +1984,8 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' fn visit_expr(&mut self, e: &'tcx Expr) { if_chain! { - if let ExprCall(ref fun, ref args) = e.node; - if let ExprPath(QPath::TypeRelative(ref ty, ref method)) = fun.node; + if let ExprKind::Call(ref fun, ref args) = e.node; + if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.node; if let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node; then { if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 0cb192e89b2..ddd9db9eda3 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -71,7 +71,7 @@ impl LintPass for Unicode { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unicode { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprLit(ref lit) = expr.node { + if let ExprKind::Lit(ref lit) = expr.node { if let LitKind::Str(_, _) = lit.node { check_str(cx, lit.span, expr.id) } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 316415d73ad..e699253efaa 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -45,9 +45,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { }; match expr.node { - hir::ExprMatch(ref res, _, _) if is_try(expr).is_some() => { - if let hir::ExprCall(ref func, ref args) = res.node { - if let hir::ExprPath(ref path) = func.node { + hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => { + if let hir::ExprKind::Call(ref func, ref args) = res.node { + if let hir::ExprKind::Path(ref path) = func.node { if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { check_method_call(cx, &args[0], expr); } @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } }, - hir::ExprMethodCall(ref path, _, ref args) => match &*path.ident.as_str() { + hir::ExprKind::MethodCall(ref path, _, ref args) => match &*path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { check_method_call(cx, &args[0], expr); }, @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } fn check_method_call(cx: &LateContext, call: &hir::Expr, expr: &hir::Expr) { - if let hir::ExprMethodCall(ref path, _, _) = call.node { + if let hir::ExprKind::MethodCall(ref path, _, _) = call.node { let symbol = &*path.ident.as_str(); if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" { span_lint( diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 5c5550ed30f..0ae956b9443 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -69,10 +69,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label { + hir::ExprKind::Break(destination, _) | hir::ExprKind::Continue(destination) => if let Some(label) = destination.label { self.labels.remove(&label.ident.as_str()); }, - hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { + hir::ExprKind::Loop(_, Some(label), _) | hir::ExprKind::While(_, _, Some(label)) => { self.labels.insert(label.ident.as_str(), expr.span); }, _ => (), diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index b8e34cc66e1..f9faa3b48f7 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -78,7 +78,7 @@ fn collect_unwrap_info<'a, 'tcx: 'a>( expr: &'tcx Expr, invert: bool, ) -> Vec> { - if let Expr_::ExprBinary(op, left, right) = &expr.node { + if let ExprKind::Binary(op, left, right) = &expr.node { match (invert, op.node) { (false, BinOp_::BiAnd) | (false, BinOp_::BiBitAnd) | (true, BinOp_::BiOr) | (true, BinOp_::BiBitOr) => { let mut unwrap_info = collect_unwrap_info(cx, left, invert); @@ -87,12 +87,12 @@ fn collect_unwrap_info<'a, 'tcx: 'a>( }, _ => (), } - } else if let Expr_::ExprUnary(UnNot, expr) = &expr.node { + } else if let ExprKind::Unary(UnNot, expr) = &expr.node { return collect_unwrap_info(cx, expr, !invert); } else { if_chain! { - if let Expr_::ExprMethodCall(method_name, _, args) = &expr.node; - if let Expr_::ExprPath(QPath::Resolved(None, path)) = &args[0].node; + if let ExprKind::MethodCall(method_name, _, args) = &expr.node; + if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].node; let ty = cx.tables.expr_ty(&args[0]); if match_type(cx, ty, &paths::OPTION) || match_type(cx, ty, &paths::RESULT); let name = method_name.ident.as_str(); @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> UnwrappableVariablesVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if let Expr_::ExprIf(cond, then, els) = &expr.node { + if let ExprKind::If(cond, then, els) = &expr.node { walk_expr(self, cond); self.visit_branch(cond, then, false); if let Some(els) = els { @@ -140,8 +140,8 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } else { // find `unwrap[_err]()` calls: if_chain! { - if let Expr_::ExprMethodCall(ref method_name, _, ref args) = expr.node; - if let Expr_::ExprPath(QPath::Resolved(None, ref path)) = args[0].node; + if let ExprKind::MethodCall(ref method_name, _, ref args) = expr.node; + if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].node; if ["unwrap", "unwrap_err"].contains(&&*method_name.ident.as_str()); let call_to_unwrap = method_name.ident.name == "unwrap"; if let Some(unwrappable) = self.unwrappables.iter() diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 520c30b03c0..42beb971bef 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::{Expr, Expr_, QPath, Ty_, Pat, PatKind, BindingAnnotation, StmtSemi, StmtExpr, StmtDecl, Decl_, Stmt}; +use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; use std::collections::HashMap; @@ -32,10 +32,10 @@ use crate::utils::get_attr; /// ```rust /// // ./tests/ui/new_lint.stdout /// if_chain!{ -/// if let Expr_::ExprIf(ref cond, ref then, None) = item.node, -/// if let Expr_::ExprBinary(BinOp::Eq, ref left, ref right) = cond.node, -/// if let Expr_::ExprPath(ref path) = left.node, -/// if let Expr_::ExprLit(ref lit) = right.node, +/// if let ExprKind::If(ref cond, ref then, None) = item.node, +/// if let ExprKind::Binary(BinOp::Eq, ref left, ref right) = cond.node, +/// if let ExprKind::Path(ref path) = left.node, +/// if let ExprKind::Lit(ref lit) = right.node, /// if let LitKind::Int(42, _) = lit.node, /// then { /// // report your lint here @@ -192,16 +192,16 @@ struct PrintVisitor { impl<'tcx> Visitor<'tcx> for PrintVisitor { fn visit_expr(&mut self, expr: &Expr) { - print!(" if let Expr_::Expr"); + print!(" if let ExprKind::"); let current = format!("{}.node", self.current); match expr.node { - Expr_::ExprBox(ref inner) => { + ExprKind::Box(ref inner) => { let inner_pat = self.next("inner"); println!("Box(ref {}) = {};", inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, - Expr_::ExprArray(ref elements) => { + ExprKind::Array(ref elements) => { let elements_pat = self.next("elements"); println!("Array(ref {}) = {};", elements_pat, current); println!(" if {}.len() == {};", elements_pat, elements.len()); @@ -210,7 +210,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(element); } }, - Expr_::ExprCall(ref func, ref args) => { + ExprKind::Call(ref func, ref args) => { let func_pat = self.next("func"); let args_pat = self.next("args"); println!("Call(ref {}, ref {}) = {};", func_pat, args_pat, current); @@ -222,11 +222,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(arg); } }, - Expr_::ExprMethodCall(ref _method_name, ref _generics, ref _args) => { + ExprKind::MethodCall(ref _method_name, ref _generics, ref _args) => { println!("MethodCall(ref method_name, ref generics, ref args) = {};", current); - println!(" // unimplemented: `ExprMethodCall` is not further destructured at the moment"); + println!(" // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment"); }, - Expr_::ExprTup(ref elements) => { + ExprKind::Tup(ref elements) => { let elements_pat = self.next("elements"); println!("Tup(ref {}) = {};", elements_pat, current); println!(" if {}.len() == {};", elements_pat, elements.len()); @@ -235,7 +235,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(element); } }, - Expr_::ExprBinary(ref op, ref left, ref right) => { + ExprKind::Binary(ref op, ref left, ref right) => { let op_pat = self.next("op"); let left_pat = self.next("left"); let right_pat = self.next("right"); @@ -246,13 +246,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = right_pat; self.visit_expr(right); }, - Expr_::ExprUnary(ref op, ref inner) => { + ExprKind::Unary(ref op, ref inner) => { let inner_pat = self.next("inner"); println!("Unary(UnOp::{:?}, ref {}) = {};", op, inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, - Expr_::ExprLit(ref lit) => { + ExprKind::Lit(ref lit) => { let lit_pat = self.next("lit"); println!("Lit(ref {}) = {};", lit_pat, current); match lit.node { @@ -277,7 +277,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, } }, - Expr_::ExprCast(ref expr, ref ty) => { + ExprKind::Cast(ref expr, ref ty) => { let cast_pat = self.next("expr"); let cast_ty = self.next("cast_ty"); let qp_label = self.next("qp"); @@ -291,13 +291,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = cast_pat; self.visit_expr(expr); }, - Expr_::ExprType(ref expr, ref _ty) => { + ExprKind::Type(ref expr, ref _ty) => { let cast_pat = self.next("expr"); println!("Type(ref {}, _) = {};", cast_pat, current); self.current = cast_pat; self.visit_expr(expr); }, - Expr_::ExprIf(ref cond, ref then, ref opt_else) => { + ExprKind::If(ref cond, ref then, ref opt_else) => { let cond_pat = self.next("cond"); let then_pat = self.next("then"); if let Some(ref else_) = *opt_else { @@ -313,7 +313,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = then_pat; self.visit_expr(then); }, - Expr_::ExprWhile(ref cond, ref body, _) => { + ExprKind::While(ref cond, ref body, _) => { let cond_pat = self.next("cond"); let body_pat = self.next("body"); let label_pat = self.next("label"); @@ -323,7 +323,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = body_pat; self.visit_block(body); }, - Expr_::ExprLoop(ref body, _, desugaring) => { + ExprKind::Loop(ref body, _, desugaring) => { let body_pat = self.next("body"); let des = loop_desugaring_name(desugaring); let label_pat = self.next("label"); @@ -331,7 +331,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = body_pat; self.visit_block(body); }, - Expr_::ExprMatch(ref expr, ref arms, desugaring) => { + ExprKind::Match(ref expr, ref arms, desugaring) => { let des = desugaring_name(desugaring); let expr_pat = self.next("expr"); let arms_pat = self.next("arms"); @@ -355,23 +355,23 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } }, - Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { + ExprKind::Closure(ref _capture_clause, ref _func, _, _, _) => { println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current); - println!(" // unimplemented: `ExprClosure` is not further destructured at the moment"); + println!(" // unimplemented: `ExprKind::Closure` is not further destructured at the moment"); }, - Expr_::ExprYield(ref sub) => { + ExprKind::Yield(ref sub) => { let sub_pat = self.next("sub"); println!("Yield(ref sub) = {};", current); self.current = sub_pat; self.visit_expr(sub); }, - Expr_::ExprBlock(ref block, _) => { + ExprKind::Block(ref block, _) => { let block_pat = self.next("block"); println!("Block(ref {}) = {};", block_pat, current); self.current = block_pat; self.visit_block(block); }, - Expr_::ExprAssign(ref target, ref value) => { + ExprKind::Assign(ref target, ref value) => { let target_pat = self.next("target"); let value_pat = self.next("value"); println!("Assign(ref {}, ref {}) = {};", target_pat, value_pat, current); @@ -380,7 +380,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, - Expr_::ExprAssignOp(ref op, ref target, ref value) => { + ExprKind::AssignOp(ref op, ref target, ref value) => { let op_pat = self.next("op"); let target_pat = self.next("target"); let value_pat = self.next("value"); @@ -391,7 +391,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, - Expr_::ExprField(ref object, ref field_ident) => { + ExprKind::Field(ref object, ref field_ident) => { let obj_pat = self.next("object"); let field_name_pat = self.next("field_name"); println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current); @@ -399,7 +399,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = obj_pat; self.visit_expr(object); }, - Expr_::ExprIndex(ref object, ref index) => { + ExprKind::Index(ref object, ref index) => { let object_pat = self.next("object"); let index_pat = self.next("index"); println!("Index(ref {}, ref {}) = {};", object_pat, index_pat, current); @@ -408,19 +408,19 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = index_pat; self.visit_expr(index); }, - Expr_::ExprPath(ref path) => { + ExprKind::Path(ref path) => { let path_pat = self.next("path"); println!("Path(ref {}) = {};", path_pat, current); self.current = path_pat; self.print_qpath(path); }, - Expr_::ExprAddrOf(mutability, ref inner) => { + ExprKind::AddrOf(mutability, ref inner) => { let inner_pat = self.next("inner"); println!("AddrOf({:?}, ref {}) = {};", mutability, inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, - Expr_::ExprBreak(ref _destination, ref opt_value) => { + ExprKind::Break(ref _destination, ref opt_value) => { let destination_pat = self.next("destination"); if let Some(ref value) = *opt_value { let value_pat = self.next("value"); @@ -432,12 +432,12 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } // FIXME: implement label printing }, - Expr_::ExprContinue(ref _destination) => { + ExprKind::Continue(ref _destination) => { let destination_pat = self.next("destination"); println!("Again(ref {}) = {};", destination_pat, current); // FIXME: implement label printing }, - Expr_::ExprRet(ref opt_value) => if let Some(ref value) = *opt_value { + ExprKind::Ret(ref opt_value) => if let Some(ref value) = *opt_value { let value_pat = self.next("value"); println!("Ret(Some(ref {})) = {};", value_pat, current); self.current = value_pat; @@ -445,11 +445,11 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } else { println!("Ret(None) = {};", current); }, - Expr_::ExprInlineAsm(_, ref _input, ref _output) => { + ExprKind::InlineAsm(_, ref _input, ref _output) => { println!("InlineAsm(_, ref input, ref output) = {};", current); - println!(" // unimplemented: `ExprInlineAsm` is not further destructured at the moment"); + println!(" // unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); }, - Expr_::ExprStruct(ref path, ref fields, ref opt_base) => { + ExprKind::Struct(ref path, ref fields, ref opt_base) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); if let Some(ref base) = *opt_base { @@ -472,7 +472,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" // unimplemented: field checks"); }, // FIXME: compute length (needs type info) - Expr_::ExprRepeat(ref value, _) => { + ExprKind::Repeat(ref value, _) => { let value_pat = self.next("value"); println!("Repeat(ref {}, _) = {};", value_pat, current); println!("// unimplemented: repeat count check"); diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 69f1792012a..74f476f55e3 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -11,24 +11,24 @@ use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, r /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { match op { - hir::BiEq => ast::BinOpKind::Eq, - hir::BiGe => ast::BinOpKind::Ge, - hir::BiGt => ast::BinOpKind::Gt, - hir::BiLe => ast::BinOpKind::Le, - hir::BiLt => ast::BinOpKind::Lt, - hir::BiNe => ast::BinOpKind::Ne, - hir::BiOr => ast::BinOpKind::Or, - hir::BiAdd => ast::BinOpKind::Add, - hir::BiAnd => ast::BinOpKind::And, - hir::BiBitAnd => ast::BinOpKind::BitAnd, - hir::BiBitOr => ast::BinOpKind::BitOr, - hir::BiBitXor => ast::BinOpKind::BitXor, - hir::BiDiv => ast::BinOpKind::Div, - hir::BiMul => ast::BinOpKind::Mul, - hir::BiRem => ast::BinOpKind::Rem, - hir::BiShl => ast::BinOpKind::Shl, - hir::BiShr => ast::BinOpKind::Shr, - hir::BiSub => ast::BinOpKind::Sub, + hir::BinOpKind::Eq => ast::BinOpKind::Eq, + hir::BinOpKind::Ge => ast::BinOpKind::Ge, + hir::BinOpKind::Gt => ast::BinOpKind::Gt, + hir::BinOpKind::Le => ast::BinOpKind::Le, + hir::BinOpKind::Lt => ast::BinOpKind::Lt, + hir::BinOpKind::Ne => ast::BinOpKind::Ne, + hir::BinOpKind::Or => ast::BinOpKind::Or, + hir::BinOpKind::Add => ast::BinOpKind::Add, + hir::BinOpKind::And => ast::BinOpKind::And, + hir::BinOpKind::BitAnd => ast::BinOpKind::BitAnd, + hir::BinOpKind::BitOr => ast::BinOpKind::BitOr, + hir::BinOpKind::BitXor => ast::BinOpKind::BitXor, + hir::BinOpKind::Div => ast::BinOpKind::Div, + hir::BinOpKind::Mul => ast::BinOpKind::Mul, + hir::BinOpKind::Rem => ast::BinOpKind::Rem, + hir::BinOpKind::Shl => ast::BinOpKind::Shl, + hir::BinOpKind::Shr => ast::BinOpKind::Shr, + hir::BinOpKind::Sub => ast::BinOpKind::Sub, } } @@ -87,7 +87,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O // `#[no_std]`. Testing both instead of resolving the paths. match expr.node { - hir::ExprPath(ref path) => { + hir::ExprKind::Path(ref path) => { if match_qpath(path, &paths::RANGE_FULL_STD) || match_qpath(path, &paths::RANGE_FULL) { Some(Range { start: None, @@ -98,7 +98,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O None } }, - hir::ExprCall(ref path, ref args) => if let hir::ExprPath(ref path) = path.node { + hir::ExprKind::Call(ref path, ref args) => if let hir::ExprKind::Path(ref path) = path.node { if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) { Some(Range { start: Some(&args[0]), @@ -111,7 +111,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O } else { None }, - hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) + hir::ExprKind::Struct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { Some(Range { @@ -156,7 +156,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { if_chain! { if let hir::DeclLocal(ref loc) = decl.node; if let Some(ref expr) = loc.init; - if let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node; + if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.node; then { return true; } @@ -185,10 +185,10 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { /// `for pat in arg { body }` becomes `(pat, arg, body)`. pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { if_chain! { - if let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node; - if let hir::ExprCall(_, ref iterargs) = iterexpr.node; + if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node; + if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.node; if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(); - if let hir::ExprLoop(ref block, _, _) = arms[0].body.node; + if let hir::ExprKind::Loop(ref block, _, _) = arms[0].body.node; if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; if let hir::StmtDecl(ref decl, _) = let_stmt.node; @@ -213,8 +213,8 @@ pub enum VecArgs<'a> { /// from `vec!`. pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option> { if_chain! { - if let hir::ExprCall(ref fun, ref args) = expr.node; - if let hir::ExprPath(ref path) = fun.node; + if let hir::ExprKind::Call(ref fun, ref args) = expr.node; + if let hir::ExprKind::Path(ref path) = fun.node; if is_expn_of(fun.span, "vec").is_some(); if let Some(fun_def_id) = opt_def_id(resolve_node(cx, path, fun.hir_id)); then { @@ -225,8 +225,8 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option SpanlessEq<'a, 'tcx> { } match (&left.node, &right.node) { - (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), - (&ExprContinue(li), &ExprContinue(ri)) => { + (&ExprKind::AddrOf(l_mut, ref le), &ExprKind::AddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), + (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) }, - (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), - (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { + (&ExprKind::Assign(ref ll, ref lr), &ExprKind::Assign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), + (&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprBlock(ref l, _), &ExprBlock(ref r, _)) => self.eq_block(l, r), - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + (&ExprKind::Block(ref l, _), &ExprKind::Block(ref r, _)) => self.eq_block(l, r), + (&ExprKind::Binary(l_op, ref ll, ref lr), &ExprKind::Binary(r_op, ref rl, ref rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, - (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => { + (&ExprKind::Break(li, ref le), &ExprKind::Break(ri, ref re)) => { both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) && both(le, re, |l, r| self.eq_expr(l, r)) }, - (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), - (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { + (&ExprKind::Box(ref l), &ExprKind::Box(ref r)) => self.eq_expr(l, r), + (&ExprKind::Call(ref l_fun, ref l_args), &ExprKind::Call(ref r_fun, ref r_args)) => { !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, - (&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) | - (&ExprType(ref lx, ref lt), &ExprType(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), - (&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => { + (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) | + (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), + (&ExprKind::Field(ref l_f_exp, ref l_f_ident), &ExprKind::Field(ref r_f_exp, ref r_f_ident)) => { l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, - (&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), - (&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => { + (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), + (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => { self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r)) }, - (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprLoop(ref lb, ref ll, ref lls), &ExprLoop(ref rb, ref rl, ref rls)) => { + (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node, + (&ExprKind::Loop(ref lb, ref ll, ref lls), &ExprKind::Loop(ref rb, ref rl, ref rls)) => { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, - (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { + (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) }) }, - (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { + (&ExprKind::MethodCall(ref l_path, _, ref l_args), &ExprKind::MethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) }, - (&ExprRepeat(ref le, ref ll_id), &ExprRepeat(ref re, ref rl_id)) => { + (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => { let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id.body).value); let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); @@ -128,16 +128,16 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_expr(le, re) && ll == rl }, - (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), - (&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r), - (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { + (&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), + (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r), + (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => { self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_field(l, r)) }, - (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), - (&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), - (&ExprArray(ref l), &ExprArray(ref r)) => self.eq_exprs(l, r), - (&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => { + (&ExprKind::Tup(ref l_tup), &ExprKind::Tup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), + (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), + (&ExprKind::Array(ref l), &ExprKind::Array(ref r)) => self.eq_exprs(l, r), + (&ExprKind::While(ref lc, ref lb, ref ll), &ExprKind::While(ref rc, ref rb, ref rl)) => { self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, _ => false, @@ -359,51 +359,51 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { } match e.node { - ExprAddrOf(m, ref e) => { - let c: fn(_, _) -> _ = ExprAddrOf; + ExprKind::AddrOf(m, ref e) => { + let c: fn(_, _) -> _ = ExprKind::AddrOf; c.hash(&mut self.s); m.hash(&mut self.s); self.hash_expr(e); }, - ExprContinue(i) => { - let c: fn(_) -> _ = ExprContinue; + ExprKind::Continue(i) => { + let c: fn(_) -> _ = ExprKind::Continue; c.hash(&mut self.s); if let Some(i) = i.label { self.hash_name(i.ident.name); } }, - ExprYield(ref e) => { - let c: fn(_) -> _ = ExprYield; + ExprKind::Yield(ref e) => { + let c: fn(_) -> _ = ExprKind::Yield; c.hash(&mut self.s); self.hash_expr(e); }, - ExprAssign(ref l, ref r) => { - let c: fn(_, _) -> _ = ExprAssign; + ExprKind::Assign(ref l, ref r) => { + let c: fn(_, _) -> _ = ExprKind::Assign; c.hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); }, - ExprAssignOp(ref o, ref l, ref r) => { - let c: fn(_, _, _) -> _ = ExprAssignOp; + ExprKind::AssignOp(ref o, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprKind::AssignOp; c.hash(&mut self.s); o.hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); }, - ExprBlock(ref b, _) => { - let c: fn(_, _) -> _ = ExprBlock; + ExprKind::Block(ref b, _) => { + let c: fn(_, _) -> _ = ExprKind::Block; c.hash(&mut self.s); self.hash_block(b); }, - ExprBinary(op, ref l, ref r) => { - let c: fn(_, _, _) -> _ = ExprBinary; + ExprKind::Binary(op, ref l, ref r) => { + let c: fn(_, _, _) -> _ = ExprKind::Binary; c.hash(&mut self.s); op.node.hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); }, - ExprBreak(i, ref j) => { - let c: fn(_, _) -> _ = ExprBreak; + ExprKind::Break(i, ref j) => { + let c: fn(_, _) -> _ = ExprKind::Break; c.hash(&mut self.s); if let Some(i) = i.label { self.hash_name(i.ident.name); @@ -412,25 +412,25 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(&*j); } }, - ExprBox(ref e) => { - let c: fn(_) -> _ = ExprBox; + ExprKind::Box(ref e) => { + let c: fn(_) -> _ = ExprKind::Box; c.hash(&mut self.s); self.hash_expr(e); }, - ExprCall(ref fun, ref args) => { - let c: fn(_, _) -> _ = ExprCall; + ExprKind::Call(ref fun, ref args) => { + let c: fn(_, _) -> _ = ExprKind::Call; c.hash(&mut self.s); self.hash_expr(fun); self.hash_exprs(args); }, - ExprCast(ref e, ref _ty) => { - let c: fn(_, _) -> _ = ExprCast; + ExprKind::Cast(ref e, ref _ty) => { + let c: fn(_, _) -> _ = ExprKind::Cast; c.hash(&mut self.s); self.hash_expr(e); // TODO: _ty }, - ExprClosure(cap, _, eid, _, _) => { - let c: fn(_, _, _, _, _) -> _ = ExprClosure; + ExprKind::Closure(cap, _, eid, _, _) => { + let c: fn(_, _, _, _, _) -> _ = ExprKind::Closure; c.hash(&mut self.s); match cap { CaptureClause::CaptureByValue => 0, @@ -438,24 +438,24 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { }.hash(&mut self.s); self.hash_expr(&self.cx.tcx.hir.body(eid).value); }, - ExprField(ref e, ref f) => { - let c: fn(_, _) -> _ = ExprField; + ExprKind::Field(ref e, ref f) => { + let c: fn(_, _) -> _ = ExprKind::Field; c.hash(&mut self.s); self.hash_expr(e); self.hash_name(f.name); }, - ExprIndex(ref a, ref i) => { - let c: fn(_, _) -> _ = ExprIndex; + ExprKind::Index(ref a, ref i) => { + let c: fn(_, _) -> _ = ExprKind::Index; c.hash(&mut self.s); self.hash_expr(a); self.hash_expr(i); }, - ExprInlineAsm(..) => { - let c: fn(_, _, _) -> _ = ExprInlineAsm; + ExprKind::InlineAsm(..) => { + let c: fn(_, _, _) -> _ = ExprKind::InlineAsm; c.hash(&mut self.s); }, - ExprIf(ref cond, ref t, ref e) => { - let c: fn(_, _, _) -> _ = ExprIf; + ExprKind::If(ref cond, ref t, ref e) => { + let c: fn(_, _, _) -> _ = ExprKind::If; c.hash(&mut self.s); self.hash_expr(cond); self.hash_expr(&**t); @@ -463,21 +463,21 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, - ExprLit(ref l) => { - let c: fn(_) -> _ = ExprLit; + ExprKind::Lit(ref l) => { + let c: fn(_) -> _ = ExprKind::Lit; c.hash(&mut self.s); l.hash(&mut self.s); }, - ExprLoop(ref b, ref i, _) => { - let c: fn(_, _, _) -> _ = ExprLoop; + ExprKind::Loop(ref b, ref i, _) => { + let c: fn(_, _, _) -> _ = ExprKind::Loop; c.hash(&mut self.s); self.hash_block(b); if let Some(i) = *i { self.hash_name(i.ident.name); } }, - ExprMatch(ref e, ref arms, ref s) => { - let c: fn(_, _, _) -> _ = ExprMatch; + ExprKind::Match(ref e, ref arms, ref s) => { + let c: fn(_, _, _) -> _ = ExprKind::Match; c.hash(&mut self.s); self.hash_expr(e); @@ -491,14 +491,14 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { s.hash(&mut self.s); }, - ExprMethodCall(ref path, ref _tys, ref args) => { - let c: fn(_, _, _) -> _ = ExprMethodCall; + ExprKind::MethodCall(ref path, ref _tys, ref args) => { + let c: fn(_, _, _) -> _ = ExprKind::MethodCall; c.hash(&mut self.s); self.hash_name(path.ident.name); self.hash_exprs(args); }, - ExprRepeat(ref e, ref l_id) => { - let c: fn(_, _) -> _ = ExprRepeat; + ExprKind::Repeat(ref e, ref l_id) => { + let c: fn(_, _) -> _ = ExprKind::Repeat; c.hash(&mut self.s); self.hash_expr(e); let full_table = self.tables; @@ -506,20 +506,20 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(&self.cx.tcx.hir.body(l_id.body).value); self.tables = full_table; }, - ExprRet(ref e) => { - let c: fn(_) -> _ = ExprRet; + ExprKind::Ret(ref e) => { + let c: fn(_) -> _ = ExprKind::Ret; c.hash(&mut self.s); if let Some(ref e) = *e { self.hash_expr(e); } }, - ExprPath(ref qpath) => { - let c: fn(_) -> _ = ExprPath; + ExprKind::Path(ref qpath) => { + let c: fn(_) -> _ = ExprKind::Path; c.hash(&mut self.s); self.hash_qpath(qpath); }, - ExprStruct(ref path, ref fields, ref expr) => { - let c: fn(_, _, _) -> _ = ExprStruct; + ExprKind::Struct(ref path, ref fields, ref expr) => { + let c: fn(_, _, _) -> _ = ExprKind::Struct; c.hash(&mut self.s); self.hash_qpath(path); @@ -533,32 +533,32 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, - ExprTup(ref tup) => { - let c: fn(_) -> _ = ExprTup; + ExprKind::Tup(ref tup) => { + let c: fn(_) -> _ = ExprKind::Tup; c.hash(&mut self.s); self.hash_exprs(tup); }, - ExprType(ref e, ref _ty) => { - let c: fn(_, _) -> _ = ExprType; + ExprKind::Type(ref e, ref _ty) => { + let c: fn(_, _) -> _ = ExprKind::Type; c.hash(&mut self.s); self.hash_expr(e); // TODO: _ty }, - ExprUnary(lop, ref le) => { - let c: fn(_, _) -> _ = ExprUnary; + ExprKind::Unary(lop, ref le) => { + let c: fn(_, _) -> _ = ExprKind::Unary; c.hash(&mut self.s); lop.hash(&mut self.s); self.hash_expr(le); }, - ExprArray(ref v) => { - let c: fn(_) -> _ = ExprArray; + ExprKind::Array(ref v) => { + let c: fn(_) -> _ = ExprKind::Array; c.hash(&mut self.s); self.hash_exprs(v); }, - ExprWhile(ref cond, ref b, l) => { - let c: fn(_, _, _) -> _ = ExprWhile; + ExprKind::While(ref cond, ref b, l) => { + let c: fn(_, _, _) -> _ = ExprKind::While; c.hash(&mut self.s); self.hash_expr(cond); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ccc4c9df6e7..3143da08da9 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -160,17 +160,17 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}ty: {}", ind, cx.tables.expr_ty(expr)); println!("{}adjustments: {:?}", ind, cx.tables.adjustments().get(expr.hir_id)); match expr.node { - hir::ExprBox(ref e) => { + hir::ExprKind::Box(ref e) => { println!("{}Box", ind); print_expr(cx, e, indent + 1); }, - hir::ExprArray(ref v) => { + hir::ExprKind::Array(ref v) => { println!("{}Array", ind); for e in v { print_expr(cx, e, indent + 1); } }, - hir::ExprCall(ref func, ref args) => { + hir::ExprKind::Call(ref func, ref args) => { println!("{}Call", ind); println!("{}function:", ind); print_expr(cx, func, indent + 1); @@ -179,20 +179,20 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, arg, indent + 1); } }, - hir::ExprMethodCall(ref path, _, ref args) => { + hir::ExprKind::MethodCall(ref path, _, ref args) => { println!("{}MethodCall", ind); println!("{}method name: {}", ind, path.ident.name); for arg in args { print_expr(cx, arg, indent + 1); } }, - hir::ExprTup(ref v) => { + hir::ExprKind::Tup(ref v) => { println!("{}Tup", ind); for e in v { print_expr(cx, e, indent + 1); } }, - hir::ExprBinary(op, ref lhs, ref rhs) => { + hir::ExprKind::Binary(op, ref lhs, ref rhs) => { println!("{}Binary", ind); println!("{}op: {:?}", ind, op.node); println!("{}lhs:", ind); @@ -200,26 +200,26 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprUnary(op, ref inner) => { + hir::ExprKind::Unary(op, ref inner) => { println!("{}Unary", ind); println!("{}op: {:?}", ind, op); print_expr(cx, inner, indent + 1); }, - hir::ExprLit(ref lit) => { + hir::ExprKind::Lit(ref lit) => { println!("{}Lit", ind); println!("{}{:?}", ind, lit); }, - hir::ExprCast(ref e, ref target) => { + hir::ExprKind::Cast(ref e, ref target) => { println!("{}Cast", ind); print_expr(cx, e, indent + 1); println!("{}target type: {:?}", ind, target); }, - hir::ExprType(ref e, ref target) => { + hir::ExprKind::Type(ref e, ref target) => { println!("{}Type", ind); print_expr(cx, e, indent + 1); println!("{}target type: {:?}", ind, target); }, - hir::ExprIf(ref e, _, ref els) => { + hir::ExprKind::If(ref e, _, ref els) => { println!("{}If", ind); println!("{}condition:", ind); print_expr(cx, e, indent + 1); @@ -228,39 +228,39 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, els, indent + 1); } }, - hir::ExprWhile(ref cond, _, _) => { + hir::ExprKind::While(ref cond, _, _) => { println!("{}While", ind); println!("{}condition:", ind); print_expr(cx, cond, indent + 1); }, - hir::ExprLoop(..) => { + hir::ExprKind::Loop(..) => { println!("{}Loop", ind); }, - hir::ExprMatch(ref cond, _, ref source) => { + hir::ExprKind::Match(ref cond, _, ref source) => { println!("{}Match", ind); println!("{}condition:", ind); print_expr(cx, cond, indent + 1); println!("{}source: {:?}", ind, source); }, - hir::ExprClosure(ref clause, _, _, _, _) => { + hir::ExprKind::Closure(ref clause, _, _, _, _) => { println!("{}Closure", ind); println!("{}clause: {:?}", ind, clause); }, - hir::ExprYield(ref sub) => { + hir::ExprKind::Yield(ref sub) => { println!("{}Yield", ind); print_expr(cx, sub, indent + 1); }, - hir::ExprBlock(_, _) => { + hir::ExprKind::Block(_, _) => { println!("{}Block", ind); }, - hir::ExprAssign(ref lhs, ref rhs) => { + hir::ExprKind::Assign(ref lhs, ref rhs) => { println!("{}Assign", ind); println!("{}lhs:", ind); print_expr(cx, lhs, indent + 1); println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprAssignOp(ref binop, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(ref binop, ref lhs, ref rhs) => { println!("{}AssignOp", ind); println!("{}op: {:?}", ind, binop.node); println!("{}lhs:", ind); @@ -268,46 +268,46 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprField(ref e, ident) => { + hir::ExprKind::Field(ref e, ident) => { println!("{}Field", ind); println!("{}field name: {}", ind, ident.name); println!("{}struct expr:", ind); print_expr(cx, e, indent + 1); }, - hir::ExprIndex(ref arr, ref idx) => { + hir::ExprKind::Index(ref arr, ref idx) => { println!("{}Index", ind); println!("{}array expr:", ind); print_expr(cx, arr, indent + 1); println!("{}index expr:", ind); print_expr(cx, idx, indent + 1); }, - hir::ExprPath(hir::QPath::Resolved(ref ty, ref path)) => { + hir::ExprKind::Path(hir::QPath::Resolved(ref ty, ref path)) => { println!("{}Resolved Path, {:?}", ind, ty); println!("{}path: {:?}", ind, path); }, - hir::ExprPath(hir::QPath::TypeRelative(ref ty, ref seg)) => { + hir::ExprKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => { println!("{}Relative Path, {:?}", ind, ty); println!("{}seg: {:?}", ind, seg); }, - hir::ExprAddrOf(ref muta, ref e) => { + hir::ExprKind::AddrOf(ref muta, ref e) => { println!("{}AddrOf", ind); println!("mutability: {:?}", muta); print_expr(cx, e, indent + 1); }, - hir::ExprBreak(_, ref e) => { + hir::ExprKind::Break(_, ref e) => { println!("{}Break", ind); if let Some(ref e) = *e { print_expr(cx, e, indent + 1); } }, - hir::ExprContinue(_) => println!("{}Again", ind), - hir::ExprRet(ref e) => { + hir::ExprKind::Continue(_) => println!("{}Again", ind), + hir::ExprKind::Ret(ref e) => { println!("{}Ret", ind); if let Some(ref e) = *e { print_expr(cx, e, indent + 1); } }, - hir::ExprInlineAsm(_, ref input, ref output) => { + hir::ExprKind::InlineAsm(_, ref input, ref output) => { println!("{}InlineAsm", ind); println!("{}inputs:", ind); for e in input { @@ -318,7 +318,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprStruct(ref path, ref fields, ref base) => { + hir::ExprKind::Struct(ref path, ref fields, ref base) => { println!("{}Struct", ind); println!("{}path: {:?}", ind, path); for field in fields { @@ -330,7 +330,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, base, indent + 1); } }, - hir::ExprRepeat(ref val, ref anon_const) => { + hir::ExprKind::Repeat(ref val, ref anon_const) => { println!("{}Repeat", ind); println!("{}value:", ind); print_expr(cx, val, indent + 1); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6765d9afb66..20993fd0452 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -174,7 +174,7 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// Check if an expression references a variable of the given name. pub fn match_var(expr: &Expr, var: Name) -> bool { - if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { + if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.node { if path.segments.len() == 1 && path.segments[0].ident.name == var { return true; } @@ -330,7 +330,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option first - if let ExprMethodCall(ref path, _, ref args) = current.node { + if let ExprKind::MethodCall(ref path, _, ref args) = current.node { if path.ident.name == *method_name { if args.iter().any(|e| in_macro(e.span)) { return None; @@ -435,7 +435,7 @@ pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { Span::new(*line_start, span.hi(), span.ctxt()) } -/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`. +/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. /// Also takes an `Option` which can be put inside the braces. pub fn expr_block<'a, 'b, T: LintContext<'b>>( cx: &T, @@ -445,7 +445,7 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( ) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); let string = option.unwrap_or_default(); - if let ExprBlock(_, _) = expr.node { + if let ExprKind::Block(_, _) = expr.node { Cow::Owned(format!("{}{}", code, string)) } else if string.is_empty() { Cow::Owned(format!("{{ {} }}", code)) @@ -530,7 +530,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI node: ImplItemKind::Method(_, eid), .. }) => match cx.tcx.hir.body(eid).value.node { - ExprBlock(ref block, _) => Some(block), + ExprKind::Block(ref block, _) => Some(block), _ => None, }, _ => None, @@ -695,7 +695,7 @@ pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) { /// Check whether the given expression is a constant literal of the given value. pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { // FIXME: use constant folding - if let ExprLit(ref spanned) = expr.node { + if let ExprKind::Lit(ref spanned) = expr.node { if let LitKind::Int(v, _) = spanned.node { return v == value; } @@ -945,7 +945,7 @@ pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return /// themselves. pub fn remove_blocks(expr: &Expr) -> &Expr { - if let ExprBlock(ref block, _) = expr.node { + if let ExprKind::Block(ref block, _) = expr.node { if block.stmts.is_empty() { if let Some(ref expr) = block.expr { remove_blocks(expr) @@ -1020,7 +1020,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pats[0].node; if match_qpath(path, &paths::RESULT_OK[1..]); if let PatKind::Binding(_, defid, _, None) = pat[0].node; - if let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node; + if let ExprKind::Path(QPath::Resolved(None, ref path)) = arm.body.node; if let Def::Local(lid) = path.def; if lid == defid; then { @@ -1038,7 +1038,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } } - if let ExprMatch(_, ref arms, ref source) = expr.node { + if let ExprKind::Match(_, ref arms, ref source) = expr.node { // desugared from a `?` operator if let MatchSource::TryDesugar = *source { return Some(expr); diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 09ec90ac63f..4275345d395 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { if self.abort { return; } - if let ExprMethodCall(ref seg, _, ref args) = expr.node { + if let ExprKind::MethodCall(ref seg, _, ref args) = expr.node { if args.len() == 1 && match_var(&args[0], self.name) { if seg.ident.name == "capacity" { self.abort = true; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index eb2197a5891..46c14f846ab 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -46,35 +46,35 @@ impl<'a> Sugg<'a> { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); match expr.node { - hir::ExprAddrOf(..) | - hir::ExprBox(..) | - hir::ExprClosure(.., _) | - hir::ExprIf(..) | - hir::ExprUnary(..) | - hir::ExprMatch(..) => Sugg::MaybeParen(snippet), - hir::ExprContinue(..) | - hir::ExprYield(..) | - hir::ExprArray(..) | - hir::ExprBlock(..) | - hir::ExprBreak(..) | - hir::ExprCall(..) | - hir::ExprField(..) | - hir::ExprIndex(..) | - hir::ExprInlineAsm(..) | - hir::ExprLit(..) | - hir::ExprLoop(..) | - hir::ExprMethodCall(..) | - hir::ExprPath(..) | - hir::ExprRepeat(..) | - hir::ExprRet(..) | - hir::ExprStruct(..) | - hir::ExprTup(..) | - hir::ExprWhile(..) => Sugg::NonParen(snippet), - hir::ExprAssign(..) => Sugg::BinOp(AssocOp::Assign, snippet), - hir::ExprAssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), - hir::ExprBinary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), - hir::ExprCast(..) => Sugg::BinOp(AssocOp::As, snippet), - hir::ExprType(..) => Sugg::BinOp(AssocOp::Colon, snippet), + hir::ExprKind::AddrOf(..) | + hir::ExprKind::Box(..) | + hir::ExprKind::Closure(.., _) | + hir::ExprKind::If(..) | + hir::ExprKind::Unary(..) | + hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet), + hir::ExprKind::Continue(..) | + hir::ExprKind::Yield(..) | + hir::ExprKind::Array(..) | + hir::ExprKind::Block(..) | + hir::ExprKind::Break(..) | + hir::ExprKind::Call(..) | + hir::ExprKind::Field(..) | + hir::ExprKind::Index(..) | + hir::ExprKind::InlineAsm(..) | + hir::ExprKind::Lit(..) | + hir::ExprKind::Loop(..) | + hir::ExprKind::MethodCall(..) | + hir::ExprKind::Path(..) | + hir::ExprKind::Repeat(..) | + hir::ExprKind::Ret(..) | + hir::ExprKind::Struct(..) | + hir::ExprKind::Tup(..) | + hir::ExprKind::While(..) => Sugg::NonParen(snippet), + hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), + hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), + hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), + hir::ExprKind::Cast(..) => Sugg::BinOp(AssocOp::As, snippet), + hir::ExprKind::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet), } }) } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 0d8997f4f36..39ab77c3afa 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_chain! { if let ty::TyRef(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty; if let ty::TySlice(..) = ty.sty; - if let ExprAddrOf(_, ref addressee) = expr.node; + if let ExprKind::AddrOf(_, ref addressee) = expr.node; if let Some(vec_args) = higher::vec_macro(cx, addressee); then { check_vec_macro(cx, &vec_args, expr.span); diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 86c95dbcc56..0adbb36b5ff 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -175,9 +175,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { // print!() - ExprCall(ref fun, ref args) => { + ExprKind::Call(ref fun, ref args) => { if_chain! { - if let ExprPath(ref qpath) = fun.node; + if let ExprKind::Path(ref qpath) = fun.node; if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); then { check_print_variants(cx, expr, fun_id, args); @@ -185,7 +185,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }, // write!() - ExprMethodCall(ref fun, _, ref args) => { + ExprKind::MethodCall(ref fun, _, ref args) => { if fun.ident.name == "write_fmt" { check_write_variants(cx, expr, args); } @@ -206,8 +206,8 @@ fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, if_chain! { // ensure we're calling Arguments::new_v1 or Arguments::new_v1_formatted if write_args.len() == 2; - if let ExprCall(ref args_fun, ref args_args) = write_args[1].node; - if let ExprPath(ref qpath) = args_fun.node; + if let ExprKind::Call(ref args_fun, ref args_args) = write_args[1].node; + if let ExprKind::Path(ref qpath) = args_fun.node; if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1) || match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); @@ -219,9 +219,9 @@ fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, if_chain! { if args_args.len() >= 2; - if let ExprAddrOf(_, ref match_expr) = args_args[1].node; - if let ExprMatch(ref args, _, _) = match_expr.node; - if let ExprTup(ref args) = args.node; + if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node; + if let ExprKind::Match(ref args, _, _) = match_expr.node; + if let ExprKind::Tup(ref args) = args.node; if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); then { match name { @@ -269,7 +269,7 @@ fn check_print_variants<'a, 'tcx>( if_chain! { // ensure we're calling Arguments::new_v1 if args.len() == 1; - if let ExprCall(ref args_fun, ref args_args) = args[0].node; + if let ExprKind::Call(ref args_fun, ref args_args) = args[0].node; then { // Check for literals in the print!/println! args check_fmt_args_for_literal(cx, args_args, |span| { @@ -277,13 +277,13 @@ fn check_print_variants<'a, 'tcx>( }); if_chain! { - if let ExprPath(ref qpath) = args_fun.node; + if let ExprKind::Path(ref qpath) = args_fun.node; if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1); if args_args.len() == 2; - if let ExprAddrOf(_, ref match_expr) = args_args[1].node; - if let ExprMatch(ref args, _, _) = match_expr.node; - if let ExprTup(ref args) = args.node; + if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node; + if let ExprKind::Match(ref args, _, _) = match_expr.node; + if let ExprKind::Tup(ref args) = args.node; if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); then { match name { @@ -315,7 +315,7 @@ fn check_print_variants<'a, 'tcx>( // Search for something like // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { - if let ExprPath(ref qpath) = args[1].node { + if let ExprKind::Path(ref qpath) = args[1].node { if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() @@ -341,25 +341,25 @@ where if args.len() >= 2; // the match statement - if let ExprAddrOf(_, ref match_expr) = args[1].node; - if let ExprMatch(ref matchee, ref arms, _) = match_expr.node; - if let ExprTup(ref tup) = matchee.node; + if let ExprKind::AddrOf(_, ref match_expr) = args[1].node; + if let ExprKind::Match(ref matchee, ref arms, _) = match_expr.node; + if let ExprKind::Tup(ref tup) = matchee.node; if arms.len() == 1; - if let ExprArray(ref arm_body_exprs) = arms[0].body.node; + if let ExprKind::Array(ref arm_body_exprs) = arms[0].body.node; then { // it doesn't matter how many args there are in the `write!`/`writeln!`, // if there's one literal, we should warn the user for (idx, tup_arg) in tup.iter().enumerate() { if_chain! { - // first, make sure we're dealing with a literal (i.e., an ExprLit) - if let ExprAddrOf(_, ref tup_val) = tup_arg.node; - if let ExprLit(_) = tup_val.node; + // first, make sure we're dealing with a literal (i.e., an ExprKind::Lit) + if let ExprKind::AddrOf(_, ref tup_val) = tup_arg.node; + if let ExprKind::Lit(_) = tup_val.node; // next, check the corresponding match arm body to ensure // this is DISPLAY_FMT_METHOD - if let ExprCall(_, ref body_args) = arm_body_exprs[idx].node; + if let ExprKind::Call(_, ref body_args) = arm_body_exprs[idx].node; if body_args.len() == 2; - if let ExprPath(ref body_qpath) = body_args[1].node; + if let ExprKind::Path(ref body_qpath) = body_args[1].node; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { @@ -371,10 +371,10 @@ where // and is just "{}" if_chain! { if args.len() == 3; - if let ExprAddrOf(_, ref format_expr) = args[2].node; - if let ExprArray(ref format_exprs) = format_expr.node; + if let ExprKind::AddrOf(_, ref format_expr) = args[2].node; + if let ExprKind::Array(ref format_exprs) = format_expr.node; if format_exprs.len() >= 1; - if let ExprStruct(_, ref fields, _) = format_exprs[idx].node; + if let ExprKind::Struct(_, ref fields, _) = format_exprs[idx].node; if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); if check_unformatted(&format_field.expr); then { @@ -429,10 +429,10 @@ fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: Local /// Returns the slice of format string parts in an `Arguments::new_v1` call. fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(LocalInternedString, usize)> { if_chain! { - if let ExprAddrOf(_, ref expr) = expr.node; // &["…", "…", …] - if let ExprArray(ref exprs) = expr.node; + if let ExprKind::AddrOf(_, ref expr) = expr.node; // &["…", "…", …] + if let ExprKind::Array(ref exprs) = expr.node; if let Some(expr) = exprs.last(); - if let ExprLit(ref lit) = expr.node; + if let ExprKind::Lit(ref lit) = expr.node; if let LitKind::Str(ref lit, _) = lit.node; then { return Some((lit.as_str(), exprs.len())); @@ -468,15 +468,15 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { /// ``` pub fn check_unformatted(format_field: &Expr) -> bool { if_chain! { - if let ExprStruct(_, ref fields, _) = format_field.node; + if let ExprKind::Struct(_, ref fields, _) = format_field.node; if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width"); - if let ExprPath(ref qpath) = width_field.expr.node; + if let ExprKind::Path(ref qpath) = width_field.expr.node; if last_path_segment(qpath).ident.name == "Implied"; if let Some(align_field) = fields.iter().find(|f| f.ident.name == "align"); - if let ExprPath(ref qpath) = align_field.expr.node; + if let ExprKind::Path(ref qpath) = align_field.expr.node; if last_path_segment(qpath).ident.name == "Unknown"; if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision"); - if let ExprPath(ref qpath_precision) = precision_field.expr.node; + if let ExprKind::Path(ref qpath_precision) = precision_field.expr.node; if last_path_segment(qpath_precision).ident.name == "Implied"; then { return true; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index aaba0184845..d77950bddc0 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // check for instances of 0.0/0.0 if_chain! { - if let ExprBinary(ref op, ref left, ref right) = expr.node; + if let ExprKind::Binary(ref op, ref left, ref right) = expr.node; if let BinOp_::BiDiv = op.node; // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index a55b48985ad..9ef1333a0e1 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -2,10 +2,10 @@ if_chain! { if let Stmt_::StmtDecl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init - if let Expr_::ExprCast(ref expr, ref cast_ty) = init.node; + if let ExprKind::Cast(ref expr, ref cast_ty) = init.node; if let Ty_::TyPath(ref qp) = cast_ty.node; if match_qpath(qp, &["char"]); - if let Expr_::ExprLit(ref lit) = expr.node; + if let ExprKind::Lit(ref lit) = expr.node; if let LitKind::Int(69, _) = lit.node; if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.node; if name.node.as_str() == "x"; diff --git a/tests/ui/author/call.stdout b/tests/ui/author/call.stdout index 3e06bf9ace8..fe90d66ad04 100644 --- a/tests/ui/author/call.stdout +++ b/tests/ui/author/call.stdout @@ -2,13 +2,13 @@ if_chain! { if let Stmt_::StmtDecl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init - if let Expr_::ExprCall(ref func, ref args) = init.node; - if let Expr_::ExprPath(ref path) = func.node; + if let ExprKind::Call(ref func, ref args) = init.node; + if let ExprKind::Path(ref path) = func.node; if match_qpath(path, &["{{root}}", "std", "cmp", "min"]); if args.len() == 2; - if let Expr_::ExprLit(ref lit) = args[0].node; + if let ExprKind::Lit(ref lit) = args[0].node; if let LitKind::Int(3, _) = lit.node; - if let Expr_::ExprLit(ref lit1) = args[1].node; + if let ExprKind::Lit(ref lit1) = args[1].node; if let LitKind::Int(4, _) = lit1.node; if let PatKind::Wild = local.pat.node; then { diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index 69bc6d7a025..dc506b22798 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -1,60 +1,60 @@ if_chain! { - if let Expr_::ExprBlock(ref block) = expr.node; + if let ExprKind::Block(ref block) = expr.node; if let Stmt_::StmtDecl(ref decl, _) = block.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init - if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; - if let Expr_::ExprCall(ref func, ref args) = expr.node; - if let Expr_::ExprPath(ref path) = func.node; + if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; + if let ExprKind::Call(ref func, ref args) = expr.node; + if let ExprKind::Path(ref path) = func.node; if match_qpath(path, &["{{root}}", "std", "iter", "IntoIterator", "into_iter"]); if args.len() == 1; - if let Expr_::ExprStruct(ref path1, ref fields, None) = args[0].node; + if let ExprKind::Struct(ref path1, ref fields, None) = args[0].node; if match_qpath(path1, &["{{root}}", "std", "ops", "Range"]); if fields.len() == 2; // unimplemented: field checks if arms.len() == 1; - if let Expr_::ExprLoop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; + if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; if let Stmt_::StmtDecl(ref decl1, _) = body.node if let Decl_::DeclLocal(ref local1) = decl1.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; if name.node.as_str() == "__next"; if let Stmt_::StmtExpr(ref e, _) = local1.pat.node - if let Expr_::ExprMatch(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; - if let Expr_::ExprCall(ref func1, ref args1) = expr1.node; - if let Expr_::ExprPath(ref path2) = func1.node; + if let ExprKind::Match(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; + if let ExprKind::Call(ref func1, ref args1) = expr1.node; + if let ExprKind::Path(ref path2) = func1.node; if match_qpath(path2, &["{{root}}", "std", "iter", "Iterator", "next"]); if args1.len() == 1; - if let Expr_::ExprAddrOf(MutMutable, ref inner) = args1[0].node; - if let Expr_::ExprPath(ref path3) = inner.node; + if let ExprKind::AddrOf(MutMutable, ref inner) = args1[0].node; + if let ExprKind::Path(ref path3) = inner.node; if match_qpath(path3, &["iter"]); if arms1.len() == 2; - if let Expr_::ExprAssign(ref target, ref value) = arms1[0].body.node; - if let Expr_::ExprPath(ref path4) = target.node; + if let ExprKind::Assign(ref target, ref value) = arms1[0].body.node; + if let ExprKind::Path(ref path4) = target.node; if match_qpath(path4, &["__next"]); - if let Expr_::ExprPath(ref path5) = value.node; + if let ExprKind::Path(ref path5) = value.node; if match_qpath(path5, &["val"]); if arms1[0].pats.len() == 1; if let PatKind::TupleStruct(ref path6, ref fields1, None) = arms1[0].pats[0].node; if match_qpath(path6, &["{{root}}", "std", "option", "Option", "Some"]); if fields1.len() == 1; // unimplemented: field checks - if let Expr_::ExprBreak(ref destination, None) = arms1[1].body.node; + if let ExprKind::Break(ref destination, None) = arms1[1].body.node; if arms1[1].pats.len() == 1; if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); if let Stmt_::StmtDecl(ref decl2, _) = path7.node if let Decl_::DeclLocal(ref local2) = decl2.node; if let Some(ref init1) = local2.init - if let Expr_::ExprPath(ref path8) = init1.node; + if let ExprKind::Path(ref path8) = init1.node; if match_qpath(path8, &["__next"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local2.pat.node; if name1.node.as_str() == "y"; if let Stmt_::StmtExpr(ref e1, _) = local2.pat.node - if let Expr_::ExprBlock(ref block1) = e1.node; + if let ExprKind::Block(ref block1) = e1.node; if let Stmt_::StmtDecl(ref decl3, _) = block1.node if let Decl_::DeclLocal(ref local3) = decl3.node; if let Some(ref init2) = local3.init - if let Expr_::ExprPath(ref path9) = init2.node; + if let ExprKind::Path(ref path9) = init2.node; if match_qpath(path9, &["y"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local3.pat.node; if name2.node.as_str() == "z"; @@ -63,7 +63,7 @@ if_chain! { if name3.node.as_str() == "iter"; if let PatKind::Binding(BindingAnnotation::Unannotated, _, name4, None) = local.pat.node; if name4.node.as_str() == "_result"; - if let Expr_::ExprPath(ref path10) = local.pat.node; + if let ExprKind::Path(ref path10) = local.pat.node; if match_qpath(path10, &["_result"]); then { // report your lint here diff --git a/tests/ui/author/matches.stout b/tests/ui/author/matches.stout index db7de5a2ca5..f314f7b2e25 100644 --- a/tests/ui/author/matches.stout +++ b/tests/ui/author/matches.stout @@ -2,31 +2,31 @@ if_chain! { if let Stmt_::StmtDecl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init - if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::Normal) = init.node; - if let Expr_::ExprLit(ref lit) = expr.node; + if let ExprKind::Match(ref expr, ref arms, MatchSource::Normal) = init.node; + if let ExprKind::Lit(ref lit) = expr.node; if let LitKind::Int(42, _) = lit.node; if arms.len() == 3; - if let Expr_::ExprLit(ref lit1) = arms[0].body.node; + if let ExprKind::Lit(ref lit1) = arms[0].body.node; if let LitKind::Int(5, _) = lit1.node; if arms[0].pats.len() == 1; if let PatKind::Lit(ref lit_expr) = arms[0].pats[0].node - if let Expr_::ExprLit(ref lit2) = lit_expr.node; + if let ExprKind::Lit(ref lit2) = lit_expr.node; if let LitKind::Int(16, _) = lit2.node; - if let Expr_::ExprBlock(ref block) = arms[1].body.node; + if let ExprKind::Block(ref block) = arms[1].body.node; if let Stmt_::StmtDecl(ref decl1, _) = block.node if let Decl_::DeclLocal(ref local1) = decl1.node; if let Some(ref init1) = local1.init - if let Expr_::ExprLit(ref lit3) = init1.node; + if let ExprKind::Lit(ref lit3) = init1.node; if let LitKind::Int(3, _) = lit3.node; if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local1.pat.node; if name.node.as_str() == "x"; - if let Expr_::ExprPath(ref path) = local1.pat.node; + if let ExprKind::Path(ref path) = local1.pat.node; if match_qpath(path, &["x"]); if arms[1].pats.len() == 1; if let PatKind::Lit(ref lit_expr1) = arms[1].pats[0].node - if let Expr_::ExprLit(ref lit4) = lit_expr1.node; + if let ExprKind::Lit(ref lit4) = lit_expr1.node; if let LitKind::Int(17, _) = lit4.node; - if let Expr_::ExprLit(ref lit5) = arms[2].body.node; + if let ExprKind::Lit(ref lit5) = arms[2].body.node; if let LitKind::Int(1, _) = lit5.node; if arms[2].pats.len() == 1; if let PatKind::Wild = arms[2].pats[0].node; diff --git a/tests/ui/trailing_zeros.stdout b/tests/ui/trailing_zeros.stdout index 145c102ed95..b8f408ae29a 100644 --- a/tests/ui/trailing_zeros.stdout +++ b/tests/ui/trailing_zeros.stdout @@ -1,13 +1,13 @@ if_chain! { - if let Expr_::ExprBinary(ref op, ref left, ref right) = expr.node; + if let ExprKind::Binary(ref op, ref left, ref right) = expr.node; if BinOp_::BiEq == op.node; - if let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node; + if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node; if BinOp_::BiBitAnd == op1.node; - if let Expr_::ExprPath(ref path) = left1.node; + if let ExprKind::Path(ref path) = left1.node; if match_qpath(path, &["x"]); - if let Expr_::ExprLit(ref lit) = right1.node; + if let ExprKind::Lit(ref lit) = right1.node; if let LitKind::Int(15, _) = lit.node; - if let Expr_::ExprLit(ref lit1) = right.node; + if let ExprKind::Lit(ref lit1) = right.node; if let LitKind::Int(0, _) = lit1.node; then { // report your lint here -- cgit 1.4.1-3-g733a5 From 5d4102ee786dea507dc42e1c4968b959767abdbd Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 12 Jul 2018 15:50:09 +0800 Subject: BinOpKind --- clippy_lints/src/arithmetic.rs | 26 +++--- clippy_lints/src/assign_ops.rs | 46 +++++----- clippy_lints/src/bit_mask.rs | 48 +++++----- clippy_lints/src/booleans.rs | 32 +++---- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/consts.rs | 120 ++++++++++++------------- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/double_comparison.rs | 10 +-- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/eq_op.rs | 28 +++--- clippy_lints/src/erasing_op.rs | 4 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/identity_op.rs | 10 +-- clippy_lints/src/len_zero.rs | 12 +-- clippy_lints/src/loops.rs | 6 +- clippy_lints/src/methods.rs | 14 +-- clippy_lints/src/misc.rs | 8 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/overflow_check_conditional.rs | 16 ++-- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/ranges.rs | 4 +- clippy_lints/src/strings.rs | 4 +- clippy_lints/src/suspicious_trait_impl.rs | 12 +-- clippy_lints/src/types.rs | 4 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/utils/author.rs | 4 +- clippy_lints/src/utils/comparisons.rs | 16 ++-- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 26 ++++-- clippy_lints/src/utils/sugg.rs | 24 ++--- clippy_lints/src/zero_div_zero.rs | 2 +- tests/ui/suspicious_arithmetic_impl.rs | 6 +- tests/ui/trailing_zeros.stdout | 4 +- 36 files changed, 260 insertions(+), 248 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 3f15f955e19..0ab7a338863 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -57,19 +57,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { match expr.node { hir::ExprKind::Binary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd - | hir::BiOr - | hir::BiBitAnd - | hir::BiBitOr - | hir::BiBitXor - | hir::BiShl - | hir::BiShr - | hir::BiEq - | hir::BiLt - | hir::BiLe - | hir::BiNe - | hir::BiGe - | hir::BiGt => return, + hir::BinOpKind::And + | hir::BinOpKind::Or + | hir::BinOpKind::BitAnd + | hir::BinOpKind::BitOr + | hir::BinOpKind::BitXor + | hir::BinOpKind::Shl + | hir::BinOpKind::Shr + | hir::BinOpKind::Eq + | hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ne + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt => return, _ => (), } let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 15871cdfe02..53b4904fa96 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -175,18 +175,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { cx, ty, rty.into(), - Add: BiAdd, - Sub: BiSub, - Mul: BiMul, - Div: BiDiv, - Rem: BiRem, - And: BiAnd, - Or: BiOr, - BitAnd: BiBitAnd, - BitOr: BiBitOr, - BitXor: BiBitXor, - Shr: BiShr, - Shl: BiShl + Add: BinOpKind::Add, + Sub: BinOpKind::Sub, + Mul: BinOpKind::Mul, + Div: BinOpKind::Div, + Rem: BinOpKind::Rem, + And: BinOpKind::And, + Or: BinOpKind::Or, + BitAnd: BinOpKind::BitAnd, + BitOr: BinOpKind::BitOr, + BitXor: BinOpKind::BitXor, + Shr: BinOpKind::Shr, + Shl: BinOpKind::Shl ) { span_lint_and_then( cx, @@ -224,13 +224,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // a = b commutative_op a if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { match op.node { - hir::BiAdd - | hir::BiMul - | hir::BiAnd - | hir::BiOr - | hir::BiBitXor - | hir::BiBitAnd - | hir::BiBitOr => { + hir::BinOpKind::Add + | hir::BinOpKind::Mul + | hir::BinOpKind::And + | hir::BinOpKind::Or + | hir::BinOpKind::BitXor + | hir::BinOpKind::BitAnd + | hir::BinOpKind::BitOr => { lint(assignee, l); }, _ => {}, @@ -244,11 +244,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } } -fn is_commutative(op: hir::BinOp_) -> bool { - use rustc::hir::BinOp_::*; +fn is_commutative(op: hir::BinOpKind) -> bool { + use rustc::hir::BinOpKind::*; match op { - BiAdd | BiMul | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr | BiEq | BiNe => true, - BiSub | BiDiv | BiRem | BiShl | BiShr | BiLt | BiLe | BiGe | BiGt => false, + Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, + Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, } } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 0558ad36b34..25d5e4d4db1 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -120,9 +120,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { } if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = e.node; - if BinOp_::BiEq == op.node; + if BinOpKind::Eq == op.node; if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node; - if BinOp_::BiBitAnd == op1.node; + if BinOpKind::BitAnd == op1.node; if let ExprKind::Lit(ref lit) = right1.node; if let LitKind::Int(n, _) = lit.node; if let ExprKind::Lit(ref lit1) = right.node; @@ -143,22 +143,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { } } -fn invert_cmp(cmp: BinOp_) -> BinOp_ { +fn invert_cmp(cmp: BinOpKind) -> BinOpKind { match cmp { - BiEq => BiEq, - BiNe => BiNe, - BiLt => BiGt, - BiGt => BiLt, - BiLe => BiGe, - BiGe => BiLe, - _ => BiOr, // Dummy + BinOpKind::Eq => BinOpKind::Eq, + BinOpKind::Ne => BinOpKind::Ne, + BinOpKind::Lt => BinOpKind::Gt, + BinOpKind::Gt => BinOpKind::Lt, + BinOpKind::Le => BinOpKind::Ge, + BinOpKind::Ge => BinOpKind::Le, + _ => BinOpKind::Or, // Dummy } } -fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: Span) { +fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node { - if op.node != BiBitAnd && op.node != BiBitOr { + if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { return; } fetch_int_literal(cx, right) @@ -167,10 +167,10 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u12 } } -fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: Span) { +fn check_bit_mask(cx: &LateContext, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) { match cmp_op { - BiEq | BiNe => match bit_op { - BiBitAnd => if mask_value & cmp_value != cmp_value { + BinOpKind::Eq | BinOpKind::Ne => match bit_op { + BinOpKind::BitAnd => if mask_value & cmp_value != cmp_value { if cmp_value != 0 { span_lint( cx, @@ -186,7 +186,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, - BiBitOr => if mask_value | cmp_value != cmp_value { + BinOpKind::BitOr => if mask_value | cmp_value != cmp_value { span_lint( cx, BAD_BIT_MASK, @@ -200,8 +200,8 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: }, _ => (), }, - BiLt | BiGe => match bit_op { - BiBitAnd => if mask_value < cmp_value { + BinOpKind::Lt | BinOpKind::Ge => match bit_op { + BinOpKind::BitAnd => if mask_value < cmp_value { span_lint( cx, BAD_BIT_MASK, @@ -215,7 +215,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, - BiBitOr => if mask_value >= cmp_value { + BinOpKind::BitOr => if mask_value >= cmp_value { span_lint( cx, BAD_BIT_MASK, @@ -229,11 +229,11 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else { check_ineffective_lt(cx, span, mask_value, cmp_value, "|"); }, - BiBitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"), + BinOpKind::BitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"), _ => (), }, - BiLe | BiGt => match bit_op { - BiBitAnd => if mask_value <= cmp_value { + BinOpKind::Le | BinOpKind::Gt => match bit_op { + BinOpKind::BitAnd => if mask_value <= cmp_value { span_lint( cx, BAD_BIT_MASK, @@ -247,7 +247,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); }, - BiBitOr => if mask_value > cmp_value { + BinOpKind::BitOr => if mask_value > cmp_value { span_lint( cx, BAD_BIT_MASK, @@ -261,7 +261,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } else { check_ineffective_gt(cx, span, mask_value, cmp_value, "|"); }, - BiBitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"), + BinOpKind::BitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"), _ => (), }, _ => (), diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index c6d0942a877..e23978ebc1d 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -84,7 +84,7 @@ struct Hir2Qmm<'a, 'tcx: 'a, 'v> { } impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { - fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec) -> Result, String> { + fn extract(&mut self, op: BinOpKind, a: &[&'v Expr], mut v: Vec) -> Result, String> { for a in a { if let ExprKind::Binary(binop, ref lhs, ref rhs) = a.node { if binop.node == op { @@ -103,8 +103,8 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { match e.node { ExprKind::Unary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), ExprKind::Binary(binop, ref lhs, ref rhs) => match binop.node { - BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), - BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + BinOpKind::Or => return Ok(Bool::Or(self.extract(BinOpKind::Or, &[lhs, rhs], Vec::new())?)), + BinOpKind::And => return Ok(Bool::And(self.extract(BinOpKind::And, &[lhs, rhs], Vec::new())?)), _ => (), }, ExprKind::Lit(ref lit) => match lit.node { @@ -137,12 +137,12 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } }; match binop.node { - BiEq => mk_expr(BiNe), - BiNe => mk_expr(BiEq), - BiGt => mk_expr(BiLe), - BiGe => mk_expr(BiLt), - BiLt => mk_expr(BiGe), - BiLe => mk_expr(BiGt), + BinOpKind::Eq => mk_expr(BinOpKind::Ne), + BinOpKind::Ne => mk_expr(BinOpKind::Eq), + BinOpKind::Gt => mk_expr(BinOpKind::Le), + BinOpKind::Ge => mk_expr(BinOpKind::Lt), + BinOpKind::Lt => mk_expr(BinOpKind::Ge), + BinOpKind::Le => mk_expr(BinOpKind::Gt), _ => continue, } }, @@ -185,12 +185,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } match binop.node { - BiEq => Some(" != "), - BiNe => Some(" == "), - BiLt => Some(" >= "), - BiGt => Some(" <= "), - BiLe => Some(" > "), - BiGe => Some(" < "), + BinOpKind::Eq => Some(" != "), + BinOpKind::Ne => Some(" == "), + BinOpKind::Lt => Some(" >= "), + BinOpKind::Gt => Some(" <= "), + BinOpKind::Le => Some(" > "), + BinOpKind::Ge => Some(" < "), _ => None, }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, @@ -441,7 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { return; } match e.node { - ExprKind::Binary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), + ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => self.bool_expr(e), ExprKind::Unary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { self.bool_expr(e); } else { diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index e60fbbbe51d..aaa924e95b1 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { if body.arguments.len() == 1; if let Some(argname) = get_pat_name(&body.arguments[0].pat); if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node; - if op.node == BiEq; + if op.node == BinOpKind::Eq; if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])), &paths::SLICE_ITER); diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 8e0e60193bb..d7323337f24 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -340,43 +340,43 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { let r = sext(self.tcx, r, ity); let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); match op.node { - BiAdd => l.checked_add(r).map(zext), - BiSub => l.checked_sub(r).map(zext), - BiMul => l.checked_mul(r).map(zext), - BiDiv if r != 0 => l.checked_div(r).map(zext), - BiRem if r != 0 => l.checked_rem(r).map(zext), - BiShr => l.checked_shr(r as u128 as u32).map(zext), - BiShl => l.checked_shl(r as u128 as u32).map(zext), - BiBitXor => Some(zext(l ^ r)), - BiBitOr => Some(zext(l | r)), - BiBitAnd => Some(zext(l & r)), - BiEq => Some(Constant::Bool(l == r)), - BiNe => Some(Constant::Bool(l != r)), - BiLt => Some(Constant::Bool(l < r)), - BiLe => Some(Constant::Bool(l <= r)), - BiGe => Some(Constant::Bool(l >= r)), - BiGt => Some(Constant::Bool(l > r)), + BinOpKind::Add => l.checked_add(r).map(zext), + BinOpKind::Sub => l.checked_sub(r).map(zext), + BinOpKind::Mul => l.checked_mul(r).map(zext), + BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), + BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), + BinOpKind::Shr => l.checked_shr(r as u128 as u32).map(zext), + BinOpKind::Shl => l.checked_shl(r as u128 as u32).map(zext), + BinOpKind::BitXor => Some(zext(l ^ r)), + BinOpKind::BitOr => Some(zext(l | r)), + BinOpKind::BitAnd => Some(zext(l & r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, } } ty::TyUint(_) => { match op.node { - BiAdd => l.checked_add(r).map(Constant::Int), - BiSub => l.checked_sub(r).map(Constant::Int), - BiMul => l.checked_mul(r).map(Constant::Int), - BiDiv => l.checked_div(r).map(Constant::Int), - BiRem => l.checked_rem(r).map(Constant::Int), - BiShr => l.checked_shr(r as u32).map(Constant::Int), - BiShl => l.checked_shl(r as u32).map(Constant::Int), - BiBitXor => Some(Constant::Int(l ^ r)), - BiBitOr => Some(Constant::Int(l | r)), - BiBitAnd => Some(Constant::Int(l & r)), - BiEq => Some(Constant::Bool(l == r)), - BiNe => Some(Constant::Bool(l != r)), - BiLt => Some(Constant::Bool(l < r)), - BiLe => Some(Constant::Bool(l <= r)), - BiGe => Some(Constant::Bool(l >= r)), - BiGt => Some(Constant::Bool(l > r)), + BinOpKind::Add => l.checked_add(r).map(Constant::Int), + BinOpKind::Sub => l.checked_sub(r).map(Constant::Int), + BinOpKind::Mul => l.checked_mul(r).map(Constant::Int), + BinOpKind::Div => l.checked_div(r).map(Constant::Int), + BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), + BinOpKind::Shr => l.checked_shr(r as u32).map(Constant::Int), + BinOpKind::Shl => l.checked_shl(r as u32).map(Constant::Int), + BinOpKind::BitXor => Some(Constant::Int(l ^ r)), + BinOpKind::BitOr => Some(Constant::Int(l | r)), + BinOpKind::BitAnd => Some(Constant::Int(l & r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, } }, @@ -384,40 +384,40 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } }, (Constant::F32(l), Some(Constant::F32(r))) => match op.node { - BiAdd => Some(Constant::F32(l + r)), - BiSub => Some(Constant::F32(l - r)), - BiMul => Some(Constant::F32(l * r)), - BiDiv => Some(Constant::F32(l / r)), - BiRem => Some(Constant::F32(l % r)), - BiEq => Some(Constant::Bool(l == r)), - BiNe => Some(Constant::Bool(l != r)), - BiLt => Some(Constant::Bool(l < r)), - BiLe => Some(Constant::Bool(l <= r)), - BiGe => Some(Constant::Bool(l >= r)), - BiGt => Some(Constant::Bool(l > r)), + BinOpKind::Add => Some(Constant::F32(l + r)), + BinOpKind::Sub => Some(Constant::F32(l - r)), + BinOpKind::Mul => Some(Constant::F32(l * r)), + BinOpKind::Div => Some(Constant::F32(l / r)), + BinOpKind::Rem => Some(Constant::F32(l % r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, (Constant::F64(l), Some(Constant::F64(r))) => match op.node { - BiAdd => Some(Constant::F64(l + r)), - BiSub => Some(Constant::F64(l - r)), - BiMul => Some(Constant::F64(l * r)), - BiDiv => Some(Constant::F64(l / r)), - BiRem => Some(Constant::F64(l % r)), - BiEq => Some(Constant::Bool(l == r)), - BiNe => Some(Constant::Bool(l != r)), - BiLt => Some(Constant::Bool(l < r)), - BiLe => Some(Constant::Bool(l <= r)), - BiGe => Some(Constant::Bool(l >= r)), - BiGt => Some(Constant::Bool(l > r)), + BinOpKind::Add => Some(Constant::F64(l + r)), + BinOpKind::Sub => Some(Constant::F64(l - r)), + BinOpKind::Mul => Some(Constant::F64(l * r)), + BinOpKind::Div => Some(Constant::F64(l / r)), + BinOpKind::Rem => Some(Constant::F64(l % r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, (l, r) => match (op.node, l, r) { - (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), - (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), - (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), - (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), - (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), + (BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)), + (BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)), + (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => Some(r), + (BinOpKind::BitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), + (BinOpKind::BitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), + (BinOpKind::BitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), _ => None, }, } diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 33dbf1afc89..b1b667d046c 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { ExprKind::Binary(op, _, _) => { walk_expr(self, e); match op.node { - BiAnd | BiOr => self.short_circuits += 1, + BinOpKind::And | BinOpKind::Or => self.short_circuits += 1, _ => (), } }, diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 7681cc7225f..e2ea5723a98 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx> DoubleComparisonPass { fn check_binop( &self, cx: &LateContext<'a, 'tcx>, - op: BinOp_, + op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span, @@ -67,10 +67,10 @@ impl<'a, 'tcx> DoubleComparisonPass { }} } match (op, lkind, rkind) { - (BiOr, BiEq, BiLt) | (BiOr, BiLt, BiEq) => lint_double_comparison!(<=), - (BiOr, BiEq, BiGt) | (BiOr, BiGt, BiEq) => lint_double_comparison!(>=), - (BiOr, BiLt, BiGt) | (BiOr, BiGt, BiLt) => lint_double_comparison!(!=), - (BiAnd, BiLe, BiGe) | (BiAnd, BiGe, BiLe) => lint_double_comparison!(==), + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => lint_double_comparison!(<=), + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => lint_double_comparison!(>=), + (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => lint_double_comparison!(!=), + (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => lint_double_comparison!(==), _ => (), }; } diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index b3f8279c943..d374973e35b 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -38,7 +38,7 @@ impl LintPass for DurationSubsec { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprKind::Binary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node; + if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.node; if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.node; if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 7c4c09893d3..f58b499d806 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -66,20 +66,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { return; } let (trait_id, requires_ref) = match op.node { - BiAdd => (cx.tcx.lang_items().add_trait(), false), - BiSub => (cx.tcx.lang_items().sub_trait(), false), - BiMul => (cx.tcx.lang_items().mul_trait(), false), - BiDiv => (cx.tcx.lang_items().div_trait(), false), - BiRem => (cx.tcx.lang_items().rem_trait(), false), + BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false), + BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false), + BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false), + BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false), + BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false), // don't lint short circuiting ops - BiAnd | BiOr => return, - BiBitXor => (cx.tcx.lang_items().bitxor_trait(), false), - BiBitAnd => (cx.tcx.lang_items().bitand_trait(), false), - BiBitOr => (cx.tcx.lang_items().bitor_trait(), false), - BiShl => (cx.tcx.lang_items().shl_trait(), false), - BiShr => (cx.tcx.lang_items().shr_trait(), false), - BiNe | BiEq => (cx.tcx.lang_items().eq_trait(), true), - BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items().ord_trait(), true), + BinOpKind::And | BinOpKind::Or => return, + BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false), + BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false), + BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false), + BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false), + BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false), + BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true), + BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => (cx.tcx.lang_items().ord_trait(), true), }; if let Some(trait_id) = trait_id { #[allow(match_same_arms)] @@ -159,7 +159,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { fn is_valid_operator(op: BinOp) -> bool { match op.node { - BiSub | BiDiv | BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, + BinOpKind::Sub | BinOpKind::Div | BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge | BinOpKind::Ne | BinOpKind::And | BinOpKind::Or | BinOpKind::BitXor | BinOpKind::BitAnd | BinOpKind::BitOr => true, _ => false, } } diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index c14aafbd417..acede5d1a13 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -38,11 +38,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { } if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { match cmp.node { - BiMul | BiBitAnd => { + BinOpKind::Mul | BinOpKind::BitAnd => { check(cx, left, e.span); check(cx, right, e.span); }, - BiDiv => check(cx, left, e.span), + BinOpKind::Div => check(cx, left, e.span), _ => (), } } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index ebbffc66808..250ae92ea59 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -229,7 +229,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St walk_expr(vis, expr); }, ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => { - if op.node == BiAnd || op.node == BiOr { + if op.node == BinOpKind::And || op.node == BinOpKind::Or { // x && y and x || y always evaluate x first, so these are // strictly sequenced. } else { diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 95dea6fc6d2..92e07401818 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -38,17 +38,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { match cmp.node { - BiAdd | BiBitOr | BiBitXor => { + BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { check(cx, left, 0, e.span, right.span); check(cx, right, 0, e.span, left.span); }, - BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), - BiMul => { + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => check(cx, right, 0, e.span, left.span), + BinOpKind::Mul => { check(cx, left, 1, e.span, right.span); check(cx, right, 1, e.span, left.span); }, - BiDiv => check(cx, right, 1, e.span, left.span), - BiBitAnd => { + BinOpKind::Div => check(cx, right, 1, e.span, left.span), + BinOpKind::BitAnd => { check(cx, left, -1, e.span, right.span); check(cx, right, -1, e.span, left.span); }, diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 17164c6c56a..3b73e78d1a7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -81,24 +81,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node { match cmp { - BiEq => { + BinOpKind::Eq => { check_cmp(cx, expr.span, left, right, "", 0); // len == 0 check_cmp(cx, expr.span, right, left, "", 0); // 0 == len }, - BiNe => { + BinOpKind::Ne => { check_cmp(cx, expr.span, left, right, "!", 0); // len != 0 check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len }, - BiGt => { + BinOpKind::Gt => { check_cmp(cx, expr.span, left, right, "!", 0); // len > 0 check_cmp(cx, expr.span, right, left, "", 1); // 1 > len }, - BiLt => { + BinOpKind::Lt => { check_cmp(cx, expr.span, left, right, "", 1); // len < 1 check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len }, - BiGe => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1 - BiLe => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len + BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1 + BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len _ => (), } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7dd7263551d..5095ddfda25 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -771,7 +771,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: let offset = match idx.node { ExprKind::Binary(op, ref lhs, ref rhs) => match op.node { - BinOp_::BiAdd => { + BinOpKindAdd => { let offset_opt = if same_var(cx, lhs, var) { extract_offset(cx, rhs, var) } else if same_var(cx, rhs, var) { @@ -782,7 +782,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: offset_opt.map(Offset::positive) }, - BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), + BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, }, ExprKind::Path(..) => if same_var(cx, idx, var) { @@ -1884,7 +1884,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { match parent.node { ExprKind::AssignOp(op, ref lhs, ref rhs) => { if lhs.id == expr.id { - if op.node == BiAdd && is_integer_literal(rhs, 1) { + if op.node == BinOpKind::Add && is_integer_literal(rhs, 1) { *state = match *state { VarState::Initial if self.depth == 0 => VarState::IncrOnce, _ => VarState::DontWarn, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index ee7658334b3..d1740081e67 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -789,12 +789,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => (), } }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => { + hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { expr, chain: lhs, other: rhs, - eq: op.node == hir::BiEq, + eq: op.node == hir::BinOpKind::Eq, }; lint_binary_expr_with_method_call(cx, &mut info); }, @@ -1274,7 +1274,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E fn check_fold_with_op( cx: &LateContext, fold_args: &[hir::Expr], - op: hir::BinOp_, + op: hir::BinOpKind, replacement_method_name: &str, replacement_has_args: bool) { @@ -1332,16 +1332,16 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E hir::ExprKind::Lit(ref lit) => { match lit.node { ast::LitKind::Bool(false) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiOr, "any", true + cx, fold_args, hir::BinOpKind::Or, "any", true ), ast::LitKind::Bool(true) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiAnd, "all", true + cx, fold_args, hir::BinOpKind::And, "all", true ), ast::LitKind::Int(0, _) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiAdd, "sum", false + cx, fold_args, hir::BinOpKindAdd, "sum", false ), ast::LitKind::Int(1, _) => check_fold_with_op( - cx, fold_args, hir::BinOp_::BiMul, "product", false + cx, fold_args, hir::BinOpKind::Mul, "product", false ), _ => return } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index f701f957031..f8f8aae46f8 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -305,7 +305,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_chain! { if let StmtSemi(ref expr, _) = s.node; if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node; - if binop.node == BiAnd || binop.node == BiOr; + if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; if let Some(sugg) = Sugg::hir_opt(cx, a); then { span_lint_and_then(cx, @@ -313,7 +313,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { s.span, "boolean short circuit operator in statement may be clearer using an explicit test", |db| { - let sugg = if binop.node == BiOr { !sugg } else { sugg }; + let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; db.span_suggestion(s.span, "replace it with", format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, ".."))); }); @@ -339,7 +339,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { check_to_owned(cx, left, right); check_to_owned(cx, right, left); } - if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { + if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { if is_allowed(cx, left) || is_allowed(cx, right) { return; } @@ -367,7 +367,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ); db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); }); - } else if op == BiRem && is_integer_literal(right, 1) { + } else if op == BinOpKind::Rem && is_integer_literal(right, 1) { span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } }, diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 03c602bc234..db019bdce88 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -123,7 +123,7 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; - if let ExprKind::Binary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node { + if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { let hint = snippet(cx, right_side.span, "..").into_owned(); diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 2eb63c264fd..e0374b80dd8 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { if !in_external_macro(cx, expr.span); if let ExprKind::Unary(UnOp::UnNot, ref inner) = expr.node; if let ExprKind::Binary(ref op, ref left, _) = inner.node; - if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node; + if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node; then { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 70cc9eecf6e..e30ac8695dc 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -33,7 +33,7 @@ impl LintPass for NegMultiply { #[allow(match_same_arms)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Binary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node { + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref l, ref r) = e.node { match (&l.node, &r.node) { (&ExprKind::Unary(..), &ExprKind::Unary(..)) => (), (&ExprKind::Unary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index fea0a83b444..7dc2ab734dc 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -133,7 +133,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option Some(vec![&**a, &**b]), - ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BiAnd && binop.node != BiOr => { + ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => { Some(vec![&**a, &**b]) }, ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()), diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 4e63fc2f7fc..4887edea2f3 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -42,14 +42,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); then { - if let BinOp_::BiLt = op.node { - if let BinOp_::BiAdd = op2.node { + if let BinOpKind::Lt = op.node { + if let BinOpKindAdd = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } } - if let BinOp_::BiGt = op.node { - if let BinOp_::BiSub = op2.node { + if let BinOpKind::Gt = op.node { + if let BinOpKind::Sub = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); } @@ -67,14 +67,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { if cx.tables.expr_ty(ident1).is_integral(); if cx.tables.expr_ty(ident2).is_integral(); then { - if let BinOp_::BiGt = op.node { - if let BinOp_::BiAdd = op2.node { + if let BinOpKind::Gt = op.node { + if let BinOpKindAdd = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } } - if let BinOp_::BiLt = op.node { - if let BinOp_::BiSub = op2.node { + if let BinOpKind::Lt = op.node { + if let BinOpKind::Sub = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C underflow conditions that will fail in Rust."); } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a2c204dd149..2ecdf983e6b 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Binary(ref op, ref l, ref r) = expr.node { - if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) { + if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) { span_lint( cx, CMP_NULL, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index e33e112f051..2fb3bf5182c 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -184,7 +184,7 @@ fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { fn y_plus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprKind::Binary(Spanned { node: BiAdd, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { + ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { Some(rhs) } else if is_integer_literal(rhs, 1) { Some(lhs) @@ -197,7 +197,7 @@ fn y_plus_one(expr: &Expr) -> Option<&Expr> { fn y_minus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprKind::Binary(Spanned { node: BiSub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), + ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), _ => None, } } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index fb9becbd43b..40f5c66ce15 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -82,7 +82,7 @@ impl LintPass for StringAdd { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Binary(Spanned { node: BiAdd, .. }, ref left, _) = e.node { + if let ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) = e.node { if is_string(cx, left) { if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) { let parent = get_parent_expr(cx, e); @@ -122,7 +122,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { match src.node { - ExprKind::Binary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), + ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprKind::Block(ref block, _) => { block.stmts.is_empty() && block diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index a3342591a1b..ce2ef951a43 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -59,10 +59,10 @@ impl LintPass for SuspiciousImpl { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - use rustc::hir::BinOp_::*; + use rustc::hir::BinOpKind::*; if let hir::ExprKind::Binary(binop, _, _) = expr.node { match binop.node { - BiEq | BiLt | BiLe | BiNe | BiGe | BiGt => return, + BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt => return, _ => {}, } // Check if the binary expression is part of another bi/unary expression @@ -94,7 +94,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { expr, binop.node, &["Add", "Sub", "Mul", "Div"], - &[BiAdd, BiSub, BiMul, BiDiv], + &[BinOpKind::Add, BinOpKind::Sub, BinOpKind::Mul, BinOpKind::Div], ) { span_lint( cx, @@ -124,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { "ShrAssign", ], &[ - BiAdd, BiSub, BiMul, BiDiv, BiBitAnd, BiBitOr, BiBitXor, BiRem, BiShl, BiShr + BinOpKind::Add, BinOpKind::Sub, BinOpKind::Mul, BinOpKind::Div, BinOpKind::BitAnd, BinOpKind::BitOr, BinOpKind::BitXor, BinOpKind::Rem, BinOpKind::Shl, BinOpKind::Shr ], ) { span_lint( @@ -144,9 +144,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_binop<'a>( cx: &LateContext, expr: &hir::Expr, - binop: hir::BinOp_, + binop: hir::BinOpKind, traits: &[&'a str], - expected_ops: &[hir::BinOp_], + expected_ops: &[hir::BinOpKind], ) -> Option<&'a str> { let mut trait_ids = vec![]; let [krate, module] = crate::utils::paths::OPS_MODULE; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6c7c62c741a..5b88c517abb 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -450,7 +450,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { let op = cmp.node; if op.is_comparison() && is_unit(cx.tables.expr_ty(left)) { let result = match op { - BiEq | BiLe | BiGe => "true", + BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true", _ => "false", }; span_lint( @@ -1374,7 +1374,7 @@ fn is_cast_between_fixed_and_target<'a, 'tcx>( fn detect_absurd_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - op: BinOp_, + op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f9faa3b48f7..fcc3c2f68c1 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -80,7 +80,7 @@ fn collect_unwrap_info<'a, 'tcx: 'a>( ) -> Vec> { if let ExprKind::Binary(op, left, right) = &expr.node { match (invert, op.node) { - (false, BinOp_::BiAnd) | (false, BinOp_::BiBitAnd) | (true, BinOp_::BiOr) | (true, BinOp_::BiBitOr) => { + (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { let mut unwrap_info = collect_unwrap_info(cx, left, invert); unwrap_info.append(&mut collect_unwrap_info(cx, right, invert)); return unwrap_info; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 42beb971bef..2ea3636f15a 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -240,7 +240,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let left_pat = self.next("left"); let right_pat = self.next("right"); println!("Binary(ref {}, ref {}, ref {}) = {};", op_pat, left_pat, right_pat, current); - println!(" if BinOp_::{:?} == {}.node;", op.node, op_pat); + println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat); self.current = left_pat; self.visit_expr(left); self.current = right_pat; @@ -385,7 +385,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let target_pat = self.next("target"); let value_pat = self.next("value"); println!("AssignOp(ref {}, ref {}, ref {}) = {};", op_pat, target_pat, value_pat, current); - println!(" if BinOp_::{:?} == {}.node;", op.node, op_pat); + println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat); self.current = target_pat; self.visit_expr(target); self.current = value_pat; diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index 5cb9b50a79d..35f41d400ad 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -2,7 +2,7 @@ #![deny(missing_docs_in_private_items)] -use rustc::hir::{BinOp_, Expr}; +use rustc::hir::{BinOpKind, Expr}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] /// Represent a normalized comparison operator. @@ -19,14 +19,14 @@ pub enum Rel { /// Put the expression in the form `lhs < rhs`, `lhs <= rhs`, `lhs == rhs` or /// `lhs != rhs`. -pub fn normalize_comparison<'a>(op: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(Rel, &'a Expr, &'a Expr)> { +pub fn normalize_comparison<'a>(op: BinOpKind, lhs: &'a Expr, rhs: &'a Expr) -> Option<(Rel, &'a Expr, &'a Expr)> { match op { - BinOp_::BiLt => Some((Rel::Lt, lhs, rhs)), - BinOp_::BiLe => Some((Rel::Le, lhs, rhs)), - BinOp_::BiGt => Some((Rel::Lt, rhs, lhs)), - BinOp_::BiGe => Some((Rel::Le, rhs, lhs)), - BinOp_::BiEq => Some((Rel::Eq, rhs, lhs)), - BinOp_::BiNe => Some((Rel::Ne, rhs, lhs)), + BinOpKind::Lt => Some((Rel::Lt, lhs, rhs)), + BinOpKind::Le => Some((Rel::Le, lhs, rhs)), + BinOpKind::Gt => Some((Rel::Lt, rhs, lhs)), + BinOpKind::Ge => Some((Rel::Le, rhs, lhs)), + BinOpKind::Eq => Some((Rel::Eq, rhs, lhs)), + BinOpKind::Ne => Some((Rel::Ne, rhs, lhs)), _ => None, } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 74f476f55e3..75b7fd9e2fe 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -9,7 +9,7 @@ use syntax::ast; use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; /// Convert a hir binary operator to the corresponding `ast` type. -pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { +pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind { match op { hir::BinOpKind::Eq => ast::BinOpKind::Eq, hir::BinOpKind::Ge => ast::BinOpKind::Ge, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 6d3d1eeb9fe..5ff847a53b4 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -280,14 +280,26 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } -fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> { +fn swap_binop<'a>(binop: BinOpKind, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOpKind, &'a Expr, &'a Expr)> { match binop { - BiAdd | BiMul | BiBitXor | BiBitAnd | BiEq | BiNe | BiBitOr => Some((binop, rhs, lhs)), - BiLt => Some((BiGt, rhs, lhs)), - BiLe => Some((BiGe, rhs, lhs)), - BiGe => Some((BiLe, rhs, lhs)), - BiGt => Some((BiLt, rhs, lhs)), - BiShl | BiShr | BiRem | BiSub | BiDiv | BiAnd | BiOr => None, + BinOpKind::Add | + BinOpKind::Mul | + BinOpKind::Eq | + BinOpKind::Ne | + BinOpKind::BitAnd | + BinOpKind::BitXor | + BinOpKind::BitOr => Some((binop, rhs, lhs)), + BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), + BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), + BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), + BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), + BinOpKind::Shl | + BinOpKind::Shr | + BinOpKind::Rem | + BinOpKind::Sub | + BinOpKind::Div | + BinOpKind::And | + BinOpKind::Or => None, } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 46c14f846ab..27362bd9be9 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -382,21 +382,21 @@ fn associativity(op: &AssocOp) -> Associativity { /// Convert a `hir::BinOp` to the corresponding assigning binary operator. fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use rustc::hir::BinOp_::*; + use rustc::hir::BinOpKind::*; use syntax::parse::token::BinOpToken::*; AssocOp::AssignOp(match op.node { - BiAdd => Plus, - BiBitAnd => And, - BiBitOr => Or, - BiBitXor => Caret, - BiDiv => Slash, - BiMul => Star, - BiRem => Percent, - BiShl => Shl, - BiShr => Shr, - BiSub => Minus, - BiAnd | BiEq | BiGe | BiGt | BiLe | BiLt | BiNe | BiOr => panic!("This operator does not exist"), + BinOpKind::Add => Plus, + BinOpKind::BitAnd => And, + BinOpKind::BitOr => Or, + BinOpKind::BitXor => Caret, + BinOpKind::Div => Slash, + BinOpKind::Mul => Star, + BinOpKind::Rem => Percent, + BinOpKind::Shl => Shl, + BinOpKind::Shr => Shr, + BinOpKind::Sub => Minus, + BinOpKind::And | BinOpKind::Eq | BinOpKind::Ge | BinOpKind::Gt | BinOpKind::Le | BinOpKind::Lt | BinOpKind::Ne | BinOpKind::Or => panic!("This operator does not exist"), }) } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index d77950bddc0..5232d5714f1 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for instances of 0.0/0.0 if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = expr.node; - if let BinOp_::BiDiv = op.node; + if let BinOpKind::Div = op.node; // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index d5982efe12f..9f6fce2495a 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -25,7 +25,7 @@ impl Mul for Foo { type Output = Foo; fn mul(self, other: Foo) -> Foo { - Foo(self.0 * other.0 % 42) // OK: BiRem part of BiExpr as parent node + Foo(self.0 * other.0 % 42) // OK: BinOpKind::Rem part of BiExpr as parent node } } @@ -33,7 +33,7 @@ impl Sub for Foo { type Output = Foo; fn sub(self, other: Self) -> Self { - Foo(self.0 * other.0 - 42) // OK: BiMul part of BiExpr as child node + Foo(self.0 * other.0 - 42) // OK: BinOpKind::Mul part of BiExpr as child node } } @@ -41,7 +41,7 @@ impl Div for Foo { type Output = Foo; fn div(self, other: Self) -> Self { - Foo(do_nothing(self.0 + other.0) / 42) // OK: BiAdd part of BiExpr as child node + Foo(do_nothing(self.0 + other.0) / 42) // OK: BinOpKind::Add part of BiExpr as child node } } diff --git a/tests/ui/trailing_zeros.stdout b/tests/ui/trailing_zeros.stdout index b8f408ae29a..b311604c0c8 100644 --- a/tests/ui/trailing_zeros.stdout +++ b/tests/ui/trailing_zeros.stdout @@ -1,8 +1,8 @@ if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = expr.node; - if BinOp_::BiEq == op.node; + if BinOpKind::Eq == op.node; if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node; - if BinOp_::BiBitAnd == op1.node; + if BinOpKind::BitAnd == op1.node; if let ExprKind::Path(ref path) = left1.node; if match_qpath(path, &["x"]); if let ExprKind::Lit(ref lit) = right1.node; -- cgit 1.4.1-3-g733a5 From 12ded030b684ef7222ce1bc3b91ad456012bcdd0 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 12 Jul 2018 16:03:06 +0800 Subject: TyKind --- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/methods.rs | 12 ++++++------ clippy_lints/src/misc.rs | 2 +- clippy_lints/src/mut_mut.rs | 4 ++-- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/ptr.rs | 8 ++++---- clippy_lints/src/shadow.rs | 10 +++++----- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/types.rs | 22 +++++++++++----------- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 6 +++--- clippy_lints/src/utils/hir_utils.rs | 16 ++++++++-------- clippy_lints/src/utils/internal_lints.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 6 +++--- tests/ui/author.stdout | 2 +- 18 files changed, 55 insertions(+), 55 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 75ebd9eaece..8a480a0286e 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -168,7 +168,7 @@ impl<'a, 'tcx> Functions { } fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { - if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) { + if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) { Some(id) } else { None diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index c6bf264ff38..7ef477baa65 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -338,10 +338,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty) { match ty.node { - TyRptr(ref lt, _) if lt.is_elided() => { + TyKind::Rptr(ref lt, _) if lt.is_elided() => { self.record(&None); }, - TyPath(ref path) => { + TyKind::Path(ref path) => { if let QPath::Resolved(_, ref path) = *path { if let Def::Existential(def_id) = path.def { let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap(); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d1740081e67..e2a1ee44f2c 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -2057,7 +2057,7 @@ impl SelfKind { return true; } match ty.node { - hir::TyRptr(_, ref mt_ty) => { + hir::TyKind::Rptr(_, ref mt_ty) => { let mutability_match = if self == SelfKind::Ref { mt_ty.mutbl == hir::MutImmutable } else { @@ -2128,8 +2128,8 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { match (&ty.node, &self_ty.node) { ( - &hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), - &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path)), + &hir::TyKind::Path(hir::QPath::Resolved(_, ref ty_path)), + &hir::TyKind::Path(hir::QPath::Resolved(_, ref self_ty_path)), ) => ty_path .segments .iter() @@ -2140,7 +2140,7 @@ fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { } fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> { - if let hir::TyPath(ref path) = ty.node { + if let hir::TyKind::Path(ref path) = ty.node { single_segment_path(path) } else { None @@ -2181,14 +2181,14 @@ impl OutType { (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, - (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)), + (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)), _ => false, } } } fn is_bool(ty: &hir::Ty) -> bool { - if let hir::TyPath(ref p) = ty.node { + if let hir::TyKind::Path(ref p) = ty.node { match_qpath(p, &["bool"]) } else { false diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index f8f8aae46f8..64443301dfc 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -571,7 +571,7 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { if_chain! { - if let TyPtr(MutTy { mutbl, .. }) = ty.node; + if let TyKind::Ptr(MutTy { mutbl, .. }) = ty.node; if let ExprKind::Lit(ref lit) = e.node; if let LitKind::Int(value, ..) = lit.node; if value == 0; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index fa8bb73f21c..ef08e60c4ef 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyRptr( + if let hir::TyKind::Rptr( _, hir::MutTy { ty: ref pty, @@ -95,7 +95,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { }, ) = ty.node { - if let hir::TyRptr( + if let hir::TyKind::Rptr( _, hir::MutTy { mutbl: hir::MutMutable, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index cedc3fdfd28..a4f8f585223 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if match_type(cx, ty, &paths::VEC); if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); - if let TyPath(QPath::Resolved(_, ref path)) = input.node; + if let TyKind::Path(QPath::Resolved(_, ref path)) = input.node; if let Some(elem_ty) = path.segments.iter() .find(|seg| seg.ident.name == "Vec") .and_then(|ps| ps.args.as_ref()) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2ecdf983e6b..bc3bc27f5d9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -159,7 +159,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< if match_type(cx, ty, &paths::VEC) { let mut ty_snippet = None; if_chain! { - if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node; + if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node; if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last(); then { let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg { @@ -219,8 +219,8 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< } } else if match_type(cx, ty, &paths::COW) { if_chain! { - if let TyRptr(_, MutTy { ref ty, ..} ) = arg.node; - if let TyPath(ref path) = ty.node; + if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.node; + if let TyKind::Path(ref path) = ty.node; if let QPath::Resolved(None, ref pp) = *path; if let [ref bx] = *pp.segments; if let Some(ref params) = bx.args; @@ -273,7 +273,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option< } fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> { - if let Ty_::TyRptr(ref lt, ref m) = ty.node { + if let TyKind::Rptr(ref lt, ref m) = ty.node { Some((lt, m.mutbl, ty.span)) } else { None diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index cbcdbf73e33..23971395c2f 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -347,16 +347,16 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut Vec<(Name, Span)>) { match ty.node { - TySlice(ref sty) => check_ty(cx, sty, bindings), - TyArray(ref fty, ref anon_const) => { + TyKind::Slice(ref sty) => check_ty(cx, sty, bindings), + TyKind::Array(ref fty, ref anon_const) => { check_ty(cx, fty, bindings); check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings); }, - TyPtr(MutTy { ty: ref mty, .. }) | TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => for t in tup { + TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyKind::Tup(ref tup) => for t in tup { check_ty(cx, t, bindings) }, - TyTypeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings), + TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings), _ => (), } } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 7a124e59a6e..55ad4f40e10 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -90,7 +90,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); - if matches!(ty.sty, ty::TySlice(_)) || + if matches!(ty.sty, ty::TyKind::Slice(_)) || matches!(ty.sty, ty::TyArray(_, _)) || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 9d3055c3e63..9914ab0e8db 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -461,7 +461,7 @@ fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String { GenericArg::Type(ty) => Some(ty), GenericArg::Lifetime(_) => None, }).nth(1); - if let TyRptr(_, ref to_ty) = to_ty.node; + if let TyKind::Rptr(_, ref to_ty) = to_ty.node; then { return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); } diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8d0ddbec988..e8ee73520ef 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.limit; - if let Ty_::TyRptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; + if let TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; then { let value_type = if is_self(arg) { "self".into() diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5b88c517abb..98889aaa33c 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -186,7 +186,7 @@ fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool GenericArg::Type(ty) => Some(ty), GenericArg::Lifetime(_) => None, }); - if let TyPath(ref qpath) = ty.node; + if let TyKind::Path(ref qpath) = ty.node; if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id))); if match_def_path(cx.tcx, did, path); then { @@ -206,7 +206,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { return; } match ast_ty.node { - TyPath(ref qpath) if !is_local => { + TyKind::Path(ref qpath) if !is_local => { let hir_id = cx.tcx.hir.node_to_hir_id(ast_ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { @@ -282,10 +282,10 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { }, } }, - TyRptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty), + TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty), // recurse - TySlice(ref ty) | TyArray(ref ty, _) | TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), - TyTup(ref tys) => for ty in tys { + TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), + TyKind::Tup(ref tys) => for ty in tys { check_ty(cx, ty, is_local); }, _ => {}, @@ -294,7 +294,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { match mut_ty.ty.node { - TyPath(ref qpath) => { + TyKind::Path(ref qpath) => { let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if_chain! { @@ -1214,13 +1214,13 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { let (add_score, sub_nest) = match ty.node { // _, &x and *x have only small overhead; don't mess with nesting level - TyInfer | TyPtr(..) | TyRptr(..) => (1, 0), + TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0), // the "normal" components of a type: named types, arrays/tuples - TyPath(..) | TySlice(..) | TyTup(..) | TyArray(..) => (10 * self.nest, 1), + TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), // function types bring a lot of overhead - TyBareFn(..) => (50 * self.nest, 1), + TyKind::BareFn(..) => (50 * self.nest, 1), TyTraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds @@ -1878,7 +1878,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { - if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node { + if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node { let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()? .args.iter().filter_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), @@ -1986,7 +1986,7 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' if_chain! { if let ExprKind::Call(ref fun, ref args) = e.node; if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.node; - if let TyPath(QPath::Resolved(None, ref ty_path)) = ty.node; + if let TyKind::Path(QPath::Resolved(None, ref ty_path)) = ty.node; then { if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { return; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 10b69852ba5..1af8fe83e8b 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { } if_chain! { if let ItemImpl(.., ref item_type, ref refs) = item.node; - if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node; + if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.node; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; let should_check = if let Some(ref params) = *parameters { diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 2ea3636f15a..a20901b1504 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -283,8 +283,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let qp_label = self.next("qp"); println!("Cast(ref {}, ref {}) = {};", cast_pat, cast_ty, current); - if let Ty_::TyPath(ref qp) = ty.node { - println!(" if let Ty_::TyPath(ref {}) = {}.node;", qp_label, cast_ty); + if let TyKind::Path(ref qp) = ty.node { + println!(" if let TyKind::Path(ref {}) = {}.node;", qp_label, cast_ty); self.current = qp_label; self.print_qpath(qp); } @@ -674,7 +674,7 @@ fn print_path(path: &QPath, first: &mut bool) { print!("{:?}", segment.ident.as_str()); }, QPath::TypeRelative(ref ty, ref segment) => match ty.node { - hir::Ty_::TyPath(ref inner_path) => { + hir::TyKind::Path(ref inner_path) => { print_path(inner_path, first); if *first { *first = false; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 5ff847a53b4..4fec24b3489 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -246,10 +246,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_ty_kind(&left.node, &right.node) } - pub fn eq_ty_kind(&mut self, left: &Ty_, right: &Ty_) -> bool { + pub fn eq_ty_kind(&mut self, left: &TyKind, right: &TyKind) -> bool { match (left, right) { - (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyArray(ref lt, ref ll_id), &TyArray(ref rt, ref rl_id)) => { + (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec), + (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => { let full_table = self.tables; let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); @@ -264,13 +264,13 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.tables = full_table; eq_ty && ll == rl }, - (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), - (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { + (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), + (&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) }, - (&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, r), - (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), - (&TyInfer, &TyInfer) => true, + (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r), + (&TyKind::Tup(ref l), &TyKind::Tup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), + (&TyKind::Infer, &TyKind::Infer) => true, _ => false, } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index ef26b77ea1a..10d46d8894e 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -162,7 +162,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { - if let TyRptr( + if let TyKind::Rptr( _, MutTy { ty: ref inner, @@ -170,7 +170,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool { }, ) = ty.node { - if let TyPath(ref path) = inner.node { + if let TyKind::Path(ref path) = inner.node { return match_qpath(path, &paths::LINT); } } @@ -179,7 +179,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool { fn is_lint_array_type(ty: &Ty) -> bool { - if let TyPath(ref path) = ty.node { + if let TyKind::Path(ref path) = ty.node { match_qpath(path, &paths::LINT_ARRAY) } else { false diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 20993fd0452..8a94ae34382 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -210,7 +210,7 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { match *path { QPath::Resolved(_, ref path) => match_path(path, segments), QPath::TypeRelative(ref ty, ref segment) => match ty.node { - TyPath(ref inner_path) => { + TyKind::Path(ref inner_path) => { !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && segment.ident.name == segments[segments.len() - 1] }, @@ -667,7 +667,7 @@ where /// Return the base type for HIR references and pointers. pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { match ty.node { - TyPtr(ref mut_ty) | TyRptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), _ => ty, } } @@ -998,7 +998,7 @@ pub fn is_self(slf: &Arg) -> bool { pub fn is_self_ty(slf: &hir::Ty) -> bool { if_chain! { - if let TyPath(ref qp) = slf.node; + if let TyKind::Path(ref qp) = slf.node; if let QPath::Resolved(None, ref path) = *qp; if let Def::SelfTy(..) = path.def; then { diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index 9ef1333a0e1..10b7348b4b5 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -3,7 +3,7 @@ if_chain! { if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Cast(ref expr, ref cast_ty) = init.node; - if let Ty_::TyPath(ref qp) = cast_ty.node; + if let TyKind::Path(ref qp) = cast_ty.node; if match_qpath(qp, &["char"]); if let ExprKind::Lit(ref lit) = expr.node; if let LitKind::Int(69, _) = lit.node; -- cgit 1.4.1-3-g733a5 From 8cf463fe935c9bf63c1eb4faae8fe2a081206cee Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 12 Jul 2018 16:53:53 +0800 Subject: StmtKind --- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 8 ++++---- clippy_lints/src/let_if_seq.rs | 6 +++--- clippy_lints/src/loops.rs | 16 ++++++++-------- clippy_lints/src/map_unit_fn.rs | 10 +++++----- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/swap.rs | 10 +++++----- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/utils/author.rs | 12 ++++++------ clippy_lints/src/utils/higher.rs | 4 ++-- clippy_lints/src/utils/hir_utils.rs | 16 ++++++++-------- clippy_lints/src/utils/inspector.rs | 4 ++-- tests/ui/author.stdout | 2 +- tests/ui/author/call.stdout | 2 +- tests/ui/author/for_loop.stdout | 12 ++++++------ tests/ui/author/matches.stout | 4 ++-- 23 files changed, 66 insertions(+), 66 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4418ba63070..0523e4d4680 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -234,8 +234,8 @@ fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool { fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { match stmt.node { - StmtDecl(_, _) => true, - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), + StmtKind::Decl(_, _) => true, + StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => is_relevant_expr(tcx, tables, expr), } } else { block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 70055b13f9b..0ca6808b12d 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let Categorization::Rvalue(..) = cmt.cat { let id = map.hir_to_node_id(cmt.hir_id); if let Some(NodeStmt(st)) = map.find(map.get_parent_node(id)) { - if let StmtDecl(ref decl, _) = st.node { + if let StmtKind::Decl(ref decl, _) = st.node { if let DeclLocal(ref loc) = decl.node { if let Some(ref ex) = loc.init { if let ExprKind::Box(..) = ex.node { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 250ae92ea59..d2ac597b6c5 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -82,8 +82,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { - StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), - StmtDecl(ref d, _) => if let DeclLocal(ref local) = d.node { + StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), + StmtKind::Decl(ref d, _) => if let DeclLocal(ref local) = d.node { if let Local { init: Some(ref e), .. } = **local @@ -262,8 +262,8 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly { match stmt.node { - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => check_expr(vis, expr), - StmtDecl(ref decl, _) => { + StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => check_expr(vis, expr), + StmtKind::Decl(ref decl, _) => { // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. let local = match decl.node { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 44f197f7333..8661e9eec90 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -65,10 +65,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { while let Some(stmt) = it.next() { if_chain! { if let Some(expr) = it.peek(); - if let hir::StmtDecl(ref decl, _) = stmt.node; + if let hir::StmtKind::Decl(ref decl, _) = stmt.node; if let hir::DeclLocal(ref decl) = decl.node; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node; - if let hir::StmtExpr(ref if_, _) = expr.node; + if let hir::StmtKind::Expr(ref if_, _) = expr.node; if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); if let hir::ExprKind::Block(ref then, _) = then.node; @@ -163,7 +163,7 @@ fn check_assign<'a, 'tcx>( if_chain! { if block.expr.is_none(); if let Some(expr) = block.stmts.iter().last(); - if let hir::StmtSemi(ref expr, _) = expr.node; + if let hir::StmtKind::Semi(ref expr, _) = expr.node; if let hir::ExprKind::Assign(ref var, ref value) = expr.node; if let hir::ExprKind::Path(ref qpath) = var.node; if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 5095ddfda25..936d4f6f4cd 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -511,7 +511,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { - if let StmtSemi(ref expr, _) = stmt.node { + if let StmtKind::Semi(ref expr, _) = stmt.node { if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { span_lint( @@ -584,8 +584,8 @@ fn never_loop_block(block: &Block, main_loop_id: NodeId) -> NeverLoopResult { fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { match stmt.node { - StmtSemi(ref e, ..) | StmtExpr(ref e, ..) => Some(e), - StmtDecl(ref d, ..) => decl_to_expr(d), + StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e), + StmtKind::Decl(ref d, ..) => decl_to_expr(d), } } @@ -859,8 +859,8 @@ fn get_indexed_assignments<'a, 'tcx>( stmts .iter() .map(|stmt| match stmt.node { - Stmt_::StmtDecl(..) => None, - Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + StmtKind::Decl(..) => None, + StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)), }) .chain( expr.as_ref() @@ -1809,7 +1809,7 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { if block.stmts.is_empty() { return None; } - if let StmtDecl(ref decl, _) = block.stmts[0].node { + if let StmtKind::Decl(ref decl, _) = block.stmts[0].node { if let DeclLocal(ref local) = decl.node { if let Some(ref expr) = local.init { Some(expr) @@ -1829,8 +1829,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), None if !block.stmts.is_empty() => match block.stmts[0].node { - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), - StmtDecl(..) => None, + StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => Some(expr), + StmtKind::Decl(..) => None, }, _ => None, } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 598160bb3ef..8df573e4c72 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::ty; -use rustc_errors::{Applicability}; +use rustc_errors::Applicability; use syntax::codemap::Span; use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use crate::utils::paths; @@ -131,9 +131,9 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option Some(d.span), - hir::StmtExpr(ref e, _) => Some(e.span), - hir::StmtSemi(_, _) => Some(inner_stmt.span), + hir::StmtKind::Decl(ref d, _) => Some(d.span), + hir::StmtKind::Expr(ref e, _) => Some(e.span), + hir::StmtKind::Semi(_, _) => Some(inner_stmt.span), } }, _ => { @@ -247,7 +247,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } - if let hir::StmtSemi(ref expr, _) = stmt.node { + if let hir::StmtKind::Semi(ref expr, _) = stmt.node { if let hir::ExprKind::MethodCall(_, _, _) = expr.node { if let Some(arglists) = method_chain_args(expr, &["map"]) { lint_map_unit_fn(cx, stmt, expr, arglists[0]); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index e2a1ee44f2c..d341dc21779 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1139,7 +1139,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t _ => {}, } hir::map::NodeStmt(stmt) => { - if let hir::StmtDecl(ref decl, _) = stmt.node { + if let hir::StmtKind::Decl(ref decl, _) = stmt.node { if let hir::DeclLocal(ref loc) = decl.node { if let hir::PatKind::Ref(..) = loc.pat.node { // let ref y = *x borrows x, let ref y = x.clone() does not diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 64443301dfc..c76ece55e2b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -269,7 +269,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) { if_chain! { - if let StmtDecl(ref d, _) = s.node; + if let StmtKind::Decl(ref d, _) = s.node; if let DeclLocal(ref l) = d.node; if let PatKind::Binding(an, _, i, None) = l.pat.node; if let Some(ref init) = l.init; @@ -303,7 +303,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }; if_chain! { - if let StmtSemi(ref expr, _) = s.node; + if let StmtKind::Semi(ref expr, _) = s.node; if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node; if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; if let Some(sugg) = Sugg::hir_opt(cx, a); diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index db019bdce88..2fd5ff9a246 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -184,7 +184,7 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), - (&[ref e], None) => if let StmtSemi(ref e, _) = e.node { + (&[ref e], None) => if let StmtKind::Semi(ref e, _) = e.node { if let ExprKind::Ret(_) = e.node { fetch_bool_expr(&**e) } else { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index a4f8f585223..5a44431e1a3 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -350,7 +350,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { map::Node::NodeStmt(s) => { // `let = x;` if_chain! { - if let StmtDecl(ref decl, _) = s.node; + if let StmtKind::Decl(ref decl, _) = s.node; if let DeclLocal(ref local) = decl.node; then { self.spans_need_deref diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 7dc2ab734dc..5180ff34877 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -97,7 +97,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { - if let StmtSemi(ref expr, _) = stmt.node { + if let StmtKind::Semi(ref expr, _) = stmt.node { if has_no_effect(cx, expr) { span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); } else if let Some(reduced) = reduce_expression(cx, expr) { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index e6d231af148..b8e7a2646c4 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -113,7 +113,7 @@ impl QuestionMarkPass { if_chain! { if block.stmts.len() == 1; if let Some(expr) = block.stmts.iter().last(); - if let StmtSemi(ref expr, _) = expr.node; + if let StmtKind::Semi(ref expr, _) = expr.node; if let ExprKind::Ret(ref ret_expr) = expr.node; if let &Some(ref ret_expr) = ret_expr; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 23971395c2f..d400e5bf7a7 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -110,8 +110,8 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding let len = bindings.len(); for stmt in &block.stmts { match stmt.node { - StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), + StmtKind::Decl(ref decl, _) => check_decl(cx, decl, bindings), + StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => check_expr(cx, e, bindings), } } if let Some(ref o) = block.expr { diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 55ad4f40e10..6ce7b480250 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -61,17 +61,17 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { for w in block.stmts.windows(3) { if_chain! { // let t = foo(); - if let StmtDecl(ref tmp, _) = w[0].node; + if let StmtKind::Decl(ref tmp, _) = w[0].node; if let DeclLocal(ref tmp) = tmp.node; if let Some(ref tmp_init) = tmp.init; if let PatKind::Binding(_, _, ident, None) = tmp.pat.node; // foo() = bar(); - if let StmtSemi(ref first, _) = w[1].node; + if let StmtKind::Semi(ref first, _) = w[1].node; if let ExprKind::Assign(ref lhs1, ref rhs1) = first.node; // bar() = t; - if let StmtSemi(ref second, _) = w[2].node; + if let StmtKind::Semi(ref second, _) = w[2].node; if let ExprKind::Assign(ref lhs2, ref rhs2) = second.node; if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.node; if rhs2.segments.len() == 1; @@ -145,8 +145,8 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { fn check_suspicious_swap(cx: &LateContext, block: &Block) { for w in block.stmts.windows(2) { if_chain! { - if let StmtSemi(ref first, _) = w[0].node; - if let StmtSemi(ref second, _) = w[1].node; + if let StmtKind::Semi(ref first, _) = w[0].node; + if let StmtKind::Semi(ref second, _) = w[1].node; if !differing_macro_contexts(first.span, second.span); if let ExprKind::Assign(ref lhs0, ref rhs0) = first.node; if let ExprKind::Assign(ref lhs1, ref rhs1) = second.node; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index e699253efaa..649a1033371 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -40,7 +40,7 @@ impl LintPass for UnusedIoAmount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { - hir::StmtSemi(ref expr, _) | hir::StmtExpr(ref expr, _) => &**expr, + hir::StmtKind::Semi(ref expr, _) | hir::StmtKind::Expr(ref expr, _) => &**expr, _ => return, }; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index a20901b1504..eccb8e53583 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -592,9 +592,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let current = format!("{}.node", self.current); match s.node { // Could be an item or a local (let) binding: - StmtDecl(ref decl, _) => { + StmtKind::Decl(ref decl, _) => { let decl_pat = self.next("decl"); - println!("StmtDecl(ref {}, _) = {}", decl_pat, current); + println!("StmtKind::Decl(ref {}, _) = {}", decl_pat, current); print!(" if let Decl_::"); let current = format!("{}.node", decl_pat); match decl.node { @@ -619,17 +619,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } // Expr without trailing semi-colon (must have unit type): - StmtExpr(ref e, _) => { + StmtKind::Expr(ref e, _) => { let e_pat = self.next("e"); - println!("StmtExpr(ref {}, _) = {}", e_pat, current); + println!("StmtKind::Expr(ref {}, _) = {}", e_pat, current); self.current = e_pat; self.visit_expr(e); }, // Expr with trailing semi-colon (may have any type): - StmtSemi(ref e, _) => { + StmtKind::Semi(ref e, _) => { let e_pat = self.next("e"); - println!("StmtSemi(ref {}, _) = {}", e_pat, current); + println!("StmtKind::Semi(ref {}, _) = {}", e_pat, current); self.current = e_pat; self.visit_expr(e); }, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 75b7fd9e2fe..72b39000ce5 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -191,9 +191,9 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> if let hir::ExprKind::Loop(ref block, _, _) = arms[0].body.node; if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; - if let hir::StmtDecl(ref decl, _) = let_stmt.node; + if let hir::StmtKind::Decl(ref decl, _) = let_stmt.node; if let hir::DeclLocal(ref decl) = decl.node; - if let hir::StmtExpr(ref expr, _) = body.node; + if let hir::StmtKind::Expr(ref expr, _) = body.node; then { return Some((&*decl.pat, &iterargs[0], expr)); } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 4fec24b3489..2cec0b2da08 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -43,14 +43,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two statements are the same. pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { match (&left.node, &right.node) { - (&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => { + (&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => { if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) } else { false } }, - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => { + (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _)) | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => { self.eq_expr(l, r) }, _ => false, @@ -613,8 +613,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn hash_stmt(&mut self, b: &Stmt) { match b.node { - StmtDecl(ref decl, _) => { - let c: fn(_, _) -> _ = StmtDecl; + StmtKind::Decl(ref decl, _) => { + let c: fn(_, _) -> _ = StmtKind::Decl; c.hash(&mut self.s); if let DeclLocal(ref local) = decl.node { @@ -623,13 +623,13 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { } } }, - StmtExpr(ref expr, _) => { - let c: fn(_, _) -> _ = StmtExpr; + StmtKind::Expr(ref expr, _) => { + let c: fn(_, _) -> _ = StmtKind::Expr; c.hash(&mut self.s); self.hash_expr(expr); }, - StmtSemi(ref expr, _) => { - let c: fn(_, _) -> _ = StmtSemi; + StmtKind::Semi(ref expr, _) => { + let c: fn(_, _) -> _ = StmtKind::Semi; c.hash(&mut self.s); self.hash_expr(expr); }, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 3143da08da9..1faab372028 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -122,8 +122,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } match stmt.node { - hir::StmtDecl(ref decl, _) => print_decl(cx, decl), - hir::StmtExpr(ref e, _) | hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), + hir::StmtKind::Decl(ref decl, _) => print_decl(cx, decl), + hir::StmtKind::Expr(ref e, _) | hir::StmtKind::Semi(ref e, _) => print_expr(cx, e, 0), } } // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index 10b7348b4b5..4b97e546ad3 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -1,5 +1,5 @@ if_chain! { - if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let StmtKind::Decl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Cast(ref expr, ref cast_ty) = init.node; diff --git a/tests/ui/author/call.stdout b/tests/ui/author/call.stdout index fe90d66ad04..c04909c78dd 100644 --- a/tests/ui/author/call.stdout +++ b/tests/ui/author/call.stdout @@ -1,5 +1,5 @@ if_chain! { - if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let StmtKind::Decl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Call(ref func, ref args) = init.node; diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index dc506b22798..7c2213b9c49 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -1,6 +1,6 @@ if_chain! { if let ExprKind::Block(ref block) = expr.node; - if let Stmt_::StmtDecl(ref decl, _) = block.node + if let StmtKind::Decl(ref decl, _) = block.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; @@ -14,11 +14,11 @@ if_chain! { // unimplemented: field checks if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; - if let Stmt_::StmtDecl(ref decl1, _) = body.node + if let StmtKind::Decl(ref decl1, _) = body.node if let Decl_::DeclLocal(ref local1) = decl1.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; if name.node.as_str() == "__next"; - if let Stmt_::StmtExpr(ref e, _) = local1.pat.node + if let StmtKind::Expr(ref e, _) = local1.pat.node if let ExprKind::Match(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; if let ExprKind::Call(ref func1, ref args1) = expr1.node; if let ExprKind::Path(ref path2) = func1.node; @@ -42,16 +42,16 @@ if_chain! { if arms1[1].pats.len() == 1; if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); - if let Stmt_::StmtDecl(ref decl2, _) = path7.node + if let StmtKind::Decl(ref decl2, _) = path7.node if let Decl_::DeclLocal(ref local2) = decl2.node; if let Some(ref init1) = local2.init if let ExprKind::Path(ref path8) = init1.node; if match_qpath(path8, &["__next"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local2.pat.node; if name1.node.as_str() == "y"; - if let Stmt_::StmtExpr(ref e1, _) = local2.pat.node + if let StmtKind::Expr(ref e1, _) = local2.pat.node if let ExprKind::Block(ref block1) = e1.node; - if let Stmt_::StmtDecl(ref decl3, _) = block1.node + if let StmtKind::Decl(ref decl3, _) = block1.node if let Decl_::DeclLocal(ref local3) = decl3.node; if let Some(ref init2) = local3.init if let ExprKind::Path(ref path9) = init2.node; diff --git a/tests/ui/author/matches.stout b/tests/ui/author/matches.stout index f314f7b2e25..63d669d4a7d 100644 --- a/tests/ui/author/matches.stout +++ b/tests/ui/author/matches.stout @@ -1,5 +1,5 @@ if_chain! { - if let Stmt_::StmtDecl(ref decl, _) = stmt.node + if let StmtKind::Decl(ref decl, _) = stmt.node if let Decl_::DeclLocal(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Match(ref expr, ref arms, MatchSource::Normal) = init.node; @@ -13,7 +13,7 @@ if_chain! { if let ExprKind::Lit(ref lit2) = lit_expr.node; if let LitKind::Int(16, _) = lit2.node; if let ExprKind::Block(ref block) = arms[1].body.node; - if let Stmt_::StmtDecl(ref decl1, _) = block.node + if let StmtKind::Decl(ref decl1, _) = block.node if let Decl_::DeclLocal(ref local1) = decl1.node; if let Some(ref init1) = local1.init if let ExprKind::Lit(ref lit3) = init1.node; -- cgit 1.4.1-3-g733a5 From 8e929946fdf1151736fbad530d96aeb624f8e884 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 12 Jul 2018 16:55:41 +0800 Subject: DeclKind --- clippy_lints/src/utils/author.rs | 4 ++-- tests/ui/author.stdout | 2 +- tests/ui/author/call.stdout | 2 +- tests/ui/author/for_loop.stdout | 8 ++++---- tests/ui/author/matches.stout | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index eccb8e53583..e61367fb0b6 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -599,7 +599,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let current = format!("{}.node", decl_pat); match decl.node { // A local (let) binding: - Decl_::DeclLocal(ref local) => { + DeclKind::Local(ref local) => { let local_pat = self.next("local"); println!("DeclLocal(ref {}) = {};", local_pat, current); if let Some(ref init) = local.init { @@ -612,7 +612,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_pat(&local.pat); }, // An item binding: - Decl_::DeclItem(_) => { + DeclKind::Item(_) => { println!("DeclItem(item_id) = {};", current); }, } diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index 4b97e546ad3..b06fb1d21e3 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -1,6 +1,6 @@ if_chain! { if let StmtKind::Decl(ref decl, _) = stmt.node - if let Decl_::DeclLocal(ref local) = decl.node; + if let DeclKind::Local(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Cast(ref expr, ref cast_ty) = init.node; if let TyKind::Path(ref qp) = cast_ty.node; diff --git a/tests/ui/author/call.stdout b/tests/ui/author/call.stdout index c04909c78dd..1c25708fb48 100644 --- a/tests/ui/author/call.stdout +++ b/tests/ui/author/call.stdout @@ -1,6 +1,6 @@ if_chain! { if let StmtKind::Decl(ref decl, _) = stmt.node - if let Decl_::DeclLocal(ref local) = decl.node; + if let DeclKind::Local(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Call(ref func, ref args) = init.node; if let ExprKind::Path(ref path) = func.node; diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index 7c2213b9c49..b99e8e0ade5 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -1,7 +1,7 @@ if_chain! { if let ExprKind::Block(ref block) = expr.node; if let StmtKind::Decl(ref decl, _) = block.node - if let Decl_::DeclLocal(ref local) = decl.node; + if let DeclKind::Local(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; if let ExprKind::Call(ref func, ref args) = expr.node; @@ -15,7 +15,7 @@ if_chain! { if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; if let StmtKind::Decl(ref decl1, _) = body.node - if let Decl_::DeclLocal(ref local1) = decl1.node; + if let DeclKind::Local(ref local1) = decl1.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; if name.node.as_str() == "__next"; if let StmtKind::Expr(ref e, _) = local1.pat.node @@ -43,7 +43,7 @@ if_chain! { if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); if let StmtKind::Decl(ref decl2, _) = path7.node - if let Decl_::DeclLocal(ref local2) = decl2.node; + if let DeclKind::Local(ref local2) = decl2.node; if let Some(ref init1) = local2.init if let ExprKind::Path(ref path8) = init1.node; if match_qpath(path8, &["__next"]); @@ -52,7 +52,7 @@ if_chain! { if let StmtKind::Expr(ref e1, _) = local2.pat.node if let ExprKind::Block(ref block1) = e1.node; if let StmtKind::Decl(ref decl3, _) = block1.node - if let Decl_::DeclLocal(ref local3) = decl3.node; + if let DeclKind::Local(ref local3) = decl3.node; if let Some(ref init2) = local3.init if let ExprKind::Path(ref path9) = init2.node; if match_qpath(path9, &["y"]); diff --git a/tests/ui/author/matches.stout b/tests/ui/author/matches.stout index 63d669d4a7d..94b25aefabe 100644 --- a/tests/ui/author/matches.stout +++ b/tests/ui/author/matches.stout @@ -1,6 +1,6 @@ if_chain! { if let StmtKind::Decl(ref decl, _) = stmt.node - if let Decl_::DeclLocal(ref local) = decl.node; + if let DeclKind::Local(ref local) = decl.node; if let Some(ref init) = local.init if let ExprKind::Match(ref expr, ref arms, MatchSource::Normal) = init.node; if let ExprKind::Lit(ref lit) = expr.node; @@ -14,7 +14,7 @@ if_chain! { if let LitKind::Int(16, _) = lit2.node; if let ExprKind::Block(ref block) = arms[1].body.node; if let StmtKind::Decl(ref decl1, _) = block.node - if let Decl_::DeclLocal(ref local1) = decl1.node; + if let DeclKind::Local(ref local1) = decl1.node; if let Some(ref init1) = local1.init if let ExprKind::Lit(ref lit3) = init1.node; if let LitKind::Int(3, _) = lit3.node; -- cgit 1.4.1-3-g733a5 From 6992937002ee9217be90832569a0b37cb6980916 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 16 Jul 2018 15:07:39 +0200 Subject: Update for hir renamings in rustc --- clippy_lints/src/assign_ops.rs | 30 ++++++++++---------- clippy_lints/src/attrs.rs | 6 ++-- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 4 +-- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 4 +-- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lifetimes.rs | 6 ++-- clippy_lints/src/loops.rs | 8 +++--- clippy_lints/src/methods.rs | 8 +++--- clippy_lints/src/misc.rs | 4 +-- clippy_lints/src/missing_doc.rs | 32 +++++++++++----------- clippy_lints/src/missing_inline.rs | 32 +++++++++++----------- clippy_lints/src/needless_pass_by_value.rs | 6 ++-- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/non_copy_const.rs | 4 +-- clippy_lints/src/overflow_check_conditional.rs | 4 +-- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/ptr.rs | 4 +-- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 29 ++++++++++++++++---- clippy_lints/src/swap.rs | 4 +-- clippy_lints/src/trivially_copy_pass_by_ref.rs | 4 +-- clippy_lints/src/types.rs | 14 +++++----- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 14 +++++----- clippy_lints/src/utils/higher.rs | 6 ++-- clippy_lints/src/utils/hir_utils.rs | 4 +-- clippy_lints/src/utils/inspector.rs | 38 +++++++++++++------------- clippy_lints/src/utils/internal_lints.rs | 3 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 32 ++++++++++++++-------- clippy_lints/src/write.rs | 2 +- 41 files changed, 181 insertions(+), 153 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 53b4904fa96..272b6c5a84d 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -142,9 +142,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { $cx:expr, $ty:expr, $rty:expr, - $($trait_name:ident:$full_trait_name:ident),+) => { + $($trait_name:ident),+) => { match $op { - $(hir::$full_trait_name => { + $(hir::BinOpKind::$trait_name => { let [krate, module] = crate::utils::paths::OPS_MODULE; let path = [krate, module, concat!(stringify!($trait_name), "Assign")]; let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { @@ -159,7 +159,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if_chain! { if parent_impl != ast::CRATE_NODE_ID; if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); - if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = + if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if trait_ref.path.def.def_id() == trait_id; then { return; } @@ -175,18 +175,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { cx, ty, rty.into(), - Add: BinOpKind::Add, - Sub: BinOpKind::Sub, - Mul: BinOpKind::Mul, - Div: BinOpKind::Div, - Rem: BinOpKind::Rem, - And: BinOpKind::And, - Or: BinOpKind::Or, - BitAnd: BinOpKind::BitAnd, - BitOr: BinOpKind::BitOr, - BitXor: BinOpKind::BitXor, - Shr: BinOpKind::Shr, - Shl: BinOpKind::Shl + Add, + Sub, + Mul, + Div, + Rem, + And, + Or, + BitAnd, + BitOr, + BitXor, + Shr, + Shl ) { span_lint_and_then( cx, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 0523e4d4680..5d5e2f964b0 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { check_attrs(cx, item.span, item.name, &item.attrs) } match item.node { - ItemExternCrate(_) | ItemUse(_, _) => { + ItemKind::ExternCrate(_) | ItemKind::Use(_, _) => { for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { match &*attr.name().as_str() { @@ -162,7 +162,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { // whitelist `unused_imports` and `deprecated` for lint in lint_list { if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { - if let ItemUse(_, _) = item.node { + if let ItemKind::Use(_, _) = item.node { return; } } @@ -207,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { - if let ItemFn(_, _, _, eid) = item.node { + if let ItemKind::Fn(_, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) } else { true diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 364c019c486..0d0eb27fb7d 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -70,7 +70,7 @@ impl LintPass for Derive { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node { + if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node { let ty = cx.tcx.type_of(cx.tcx.hir.local_def_id(item.id)); let is_automatically_derived = is_automatically_derived(&*item.attrs); diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 3265338ce12..1ca32cf2263 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -34,7 +34,7 @@ impl LintPass for EmptyEnum { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { fn check_item(&mut self, cx: &LateContext, item: &Item) { let did = cx.tcx.hir.local_def_id(item.id); - if let ItemEnum(..) = item.node { + if let ItemKind::Enum(..) = item.node { let ty = cx.tcx.type_of(did); let adt = ty.ty_adt_def() .expect("already checked whether this is an enum"); diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index f191150f3e7..6584bc6ffa9 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; } - if let ItemEnum(ref def, _) = item.node { + if let ItemKind::Enum(ref def, _) = item.node { for var in &def.variants { let variant = &var.node; if let Some(ref anon_const) = variant.disr_expr { diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index e90dc6f693a..042a96a21c8 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -47,7 +47,7 @@ impl EnumGlobUse { if item.vis.node.is_pub() { return; // re-exports are fine } - if let ItemUse(ref path, UseKind::Glob) = item.node { + if let ItemKind::Use(ref path, UseKind::Glob) = item.node { if let Def::Enum(_) = path.def { span_lint( cx, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 0ca6808b12d..a03dc7b6269 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { let id = map.hir_to_node_id(cmt.hir_id); if let Some(NodeStmt(st)) = map.find(map.get_parent_node(id)) { if let StmtKind::Decl(ref decl, _) = st.node { - if let DeclLocal(ref loc) = decl.node { + if let DeclKind::Local(ref loc) = decl.node { if let Some(ref ex) = loc.init { if let ExprKind::Box(..) = ex.node { if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d2ac597b6c5..58436bd897b 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), - StmtKind::Decl(ref d, _) => if let DeclLocal(ref local) = d.node { + StmtKind::Decl(ref d, _) => if let DeclKind::Local(ref local) = d.node { if let Local { init: Some(ref e), .. } = **local @@ -267,7 +267,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. let local = match decl.node { - DeclLocal(ref local) => Some(local), + DeclKind::Local(ref local) => Some(local), _ => None, }; local diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 62e2ba7a2de..1ea000d3611 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { // check for `impl From for ..` let impl_def_id = cx.tcx.hir.local_def_id(item.id); if_chain! { - if let hir::ItemImpl(.., ref impl_items) = item.node; + if let hir::ItemKind::Impl(.., ref impl_items) = item.node; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); if match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT); then { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 8a480a0286e..16438092315 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { use rustc::hir::map::Node::*; let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { - matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _)) + matches!(item.node, hir::ItemKind::Impl(_, _, _, _, Some(_), _, _)) } else { false }; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 637ea917a8f..9fb9a162cde 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -56,7 +56,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let Item_::ItemImpl(_, _, _, ref generics, None, _, _) = item.node { + if let ItemKind::Impl(_, _, _, ref generics, None, _, _) = item.node { // Remember for each inherent implementation encoutered its span and generics self.impls .insert(item.hir_id.owner_def_id(), (item.span, generics.clone())); diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index ca136f06aec..926e3a3033f 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -49,7 +49,7 @@ impl LintPass for LargeEnumVariant { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { fn check_item(&mut self, cx: &LateContext, item: &Item) { let did = cx.tcx.hir.local_def_id(item.id); - if let ItemEnum(ref def, _) = item.node { + if let ItemKind::Enum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); let adt = ty.ty_adt_def() .expect("already checked whether this is an enum"); diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 3b73e78d1a7..bd02eb5c81f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -68,8 +68,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } match item.node { - ItemTrait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), - ItemImpl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), + ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), + ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items), _ => (), } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 8661e9eec90..a72e09f9fdf 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if_chain! { if let Some(expr) = it.peek(); if let hir::StmtKind::Decl(ref decl, _) = stmt.node; - if let hir::DeclLocal(ref decl) = decl.node; + if let hir::DeclKind::Local(ref decl) = decl.node; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node; if let hir::StmtKind::Expr(ref if_, _) = expr.node; if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7ef477baa65..1b371a8141e 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -59,7 +59,7 @@ impl LintPass for LifetimePass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemFn(ref decl, _, ref generics, id) = item.node { + if let ItemKind::Fn(ref decl, _, ref generics, id) = item.node { check_fn_inner(cx, decl, Some(id), generics, item.span); } } @@ -345,7 +345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { if let QPath::Resolved(_, ref path) = *path { if let Def::Existential(def_id) = path.def { let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap(); - if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node { + if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node { for bound in &exist_ty.bounds { if let GenericBound::Outlives(_) = *bound { self.record(&None); @@ -360,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { } self.collect_anonymous_lifetimes(path, ty); } - TyTraitObject(ref bounds, ref lt) => { + TyKind::TraitObject(ref bounds, ref lt) => { if !lt.is_elided() { self.abort = true; } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 936d4f6f4cd..e7da7bde30f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -591,7 +591,7 @@ fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { fn decl_to_expr(decl: &Decl) -> Option<&Expr> { match decl.node { - DeclLocal(ref local) => local.init.as_ref().map(|p| &**p), + DeclKind::Local(ref local) => local.init.as_ref().map(|p| &**p), _ => None, } } @@ -771,7 +771,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: let offset = match idx.node { ExprKind::Binary(op, ref lhs, ref rhs) => match op.node { - BinOpKindAdd => { + BinOpKind::Add => { let offset_opt = if same_var(cx, lhs, var) { extract_offset(cx, rhs, var) } else if same_var(cx, rhs, var) { @@ -1810,7 +1810,7 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { return None; } if let StmtKind::Decl(ref decl, _) = block.stmts[0].node { - if let DeclLocal(ref local) = decl.node { + if let DeclKind::Local(ref local) = decl.node { if let Some(ref expr) = local.init { Some(expr) } else { @@ -1931,7 +1931,7 @@ struct InitializeVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn visit_decl(&mut self, decl: &'tcx Decl) { // Look for declarations of the variable - if let DeclLocal(ref local) = decl.node { + if let DeclKind::Local(ref local) = decl.node { if local.pat.id == self.var_id { if let PatKind::Binding(_, _, ident, _) = local.pat.node { self.name = Some(ident.name); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index d341dc21779..26a0b66094f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -813,7 +813,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; if let Some(first_arg_ty) = sig.decl.inputs.get(0); if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); - if let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node; + if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node; then { if cx.access_levels.is_exported(implitem.id) { // check missing trait implementations @@ -1140,7 +1140,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } hir::map::NodeStmt(stmt) => { if let hir::StmtKind::Decl(ref decl, _) = stmt.node { - if let hir::DeclLocal(ref loc) = decl.node { + if let hir::DeclKind::Local(ref loc) = decl.node { if let hir::PatKind::Ref(..) = loc.pat.node { // let ref y = *x borrows x, let ref y = x.clone() does not return; @@ -1338,7 +1338,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E cx, fold_args, hir::BinOpKind::And, "all", true ), ast::LitKind::Int(0, _) => check_fold_with_op( - cx, fold_args, hir::BinOpKindAdd, "sum", false + cx, fold_args, hir::BinOpKind::Add, "sum", false ), ast::LitKind::Int(1, _) => check_fold_with_op( cx, fold_args, hir::BinOpKind::Mul, "product", false @@ -2175,7 +2175,7 @@ enum OutType { impl OutType { fn matches(self, cx: &LateContext, ty: &hir::FunctionRetTy) -> bool { - let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyTup(vec![].into())); + let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into())); match (self, ty) { (OutType::Unit, &hir::DefaultReturn(_)) => true, (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c76ece55e2b..c5440420fc1 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) { if_chain! { if let StmtKind::Decl(ref d, _) = s.node; - if let DeclLocal(ref l) = d.node; + if let DeclKind::Local(ref l) = d.node; if let PatKind::Binding(an, _, i, None) = l.pat.node; if let Some(ref init) = l.init; then { @@ -520,7 +520,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { let parent_impl = cx.tcx.hir.get_parent(parent_fn); if parent_impl != CRATE_NODE_ID { if let map::NodeItem(item) = cx.tcx.hir.get(parent_impl) { - if let ItemImpl(.., Some(ref trait_ref), _, _) = item.node { + if let ItemKind::Impl(.., Some(ref trait_ref), _, _) = item.node { if trait_ref.path.def.def_id() == partial_eq_trait_id { // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise // we go into diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index ebb3869f48c..eb4dfe8ba1c 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -122,9 +122,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) { let desc = match it.node { - hir::ItemConst(..) => "a constant", - hir::ItemEnum(..) => "an enum", - hir::ItemFn(..) => { + hir::ItemKind::Const(..) => "a constant", + hir::ItemKind::Enum(..) => "an enum", + hir::ItemKind::Fn(..) => { // ignore main() if it.name == "main" { let def_id = cx.tcx.hir.local_def_id(it.id); @@ -135,19 +135,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } "a function" }, - hir::ItemMod(..) => "a module", - hir::ItemStatic(..) => "a static", - hir::ItemStruct(..) => "a struct", - hir::ItemTrait(..) => "a trait", - hir::ItemTraitAlias(..) => "a trait alias", - hir::ItemGlobalAsm(..) => "an assembly blob", - hir::ItemTy(..) => "a type alias", - hir::ItemUnion(..) => "a union", - hir::ItemExistential(..) => "an existential type", - hir::ItemExternCrate(..) | - hir::ItemForeignMod(..) | - hir::ItemImpl(..) | - hir::ItemUse(..) => return, + hir::ItemKind::Mod(..) => "a module", + hir::ItemKind::Static(..) => "a static", + hir::ItemKind::Struct(..) => "a struct", + hir::ItemKind::Trait(..) => "a trait", + hir::ItemKind::TraitAlias(..) => "a trait alias", + hir::ItemKind::GlobalAsm(..) => "an assembly blob", + hir::ItemKind::Ty(..) => "a type alias", + hir::ItemKind::Union(..) => "a union", + hir::ItemKind::Existential(..) => "an existential type", + hir::ItemKind::ExternCrate(..) | + hir::ItemKind::ForeignMod(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::Use(..) => return, }; self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc); diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 6987eaa71d9..0ca1c53d696 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -108,11 +108,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { return; } match it.node { - hir::ItemFn(..) => { + hir::ItemKind::Fn(..) => { let desc = "a function"; check_missing_inline_attrs(cx, &it.attrs, it.span, desc); }, - hir::ItemTrait(ref _is_auto, ref _unsafe, ref _generics, + hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, ref trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. @@ -134,20 +134,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { } } } - hir::ItemConst(..) | - hir::ItemEnum(..) | - hir::ItemMod(..) | - hir::ItemStatic(..) | - hir::ItemStruct(..) | - hir::ItemTraitAlias(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) | - hir::ItemUnion(..) | - hir::ItemExistential(..) | - hir::ItemExternCrate(..) | - hir::ItemForeignMod(..) | - hir::ItemImpl(..) | - hir::ItemUse(..) => {}, + hir::ItemKind::Const(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Mod(..) | + hir::ItemKind::Static(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::TraitAlias(..) | + hir::ItemKind::GlobalAsm(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::ExternCrate(..) | + hir::ItemKind::ForeignMod(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::Use(..) => {}, }; } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 5a44431e1a3..fa0586c1548 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -88,8 +88,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Exclude non-inherent impls if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { - if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | - ItemTrait(..)) + if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | + ItemKind::Trait(..)) { return; } @@ -351,7 +351,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { // `let = x;` if_chain! { if let StmtKind::Decl(ref decl, _) = s.node; - if let DeclLocal(ref local) = decl.node; + if let DeclKind::Local(ref local) = decl.node; then { self.spans_need_deref .entry(vid) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 3f7cbaa6ca1..6be340a99f4 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -89,7 +89,7 @@ impl LintPass for NewWithoutDefault { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { - if let hir::ItemImpl(_, _, _, _, None, _, ref items) = item.node { + if let hir::ItemKind::Impl(_, _, _, _, None, _, ref items) = item.node { for assoc_item in items { if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind { let impl_item = cx.tcx.hir.impl_item(assoc_item.id); diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 4e3142e4517..981451947bf 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -164,7 +164,7 @@ impl LintPass for NonCopyConst { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item) { - if let ItemConst(hir_ty, ..) = &it.node { + if let ItemKind::Const(hir_ty, ..) = &it.node { let ty = hir_ty_to_ty(cx.tcx, hir_ty); verify_ty_bound(cx, ty, Source::Item { item: it.span }); } @@ -182,7 +182,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { let item_node_id = cx.tcx.hir.get_parent_node(impl_item.id); let item = cx.tcx.hir.expect_item(item_node_id); // ensure the impl is an inherent impl. - if let ItemImpl(_, _, _, _, None, _, _) = item.node { + if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node { let ty = hir_ty_to_ty(cx.tcx, hir_ty); verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: impl_item.span }); } diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 4887edea2f3..8783055b31e 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { if cx.tables.expr_ty(ident2).is_integral(); then { if let BinOpKind::Lt = op.node { - if let BinOpKindAdd = op2.node { + if let BinOpKind::Add = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { if cx.tables.expr_ty(ident2).is_integral(); then { if let BinOpKind::Gt = op.node { - if let BinOpKindAdd = op2.node { + if let BinOpKind::Add = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, "You are trying to use classic C overflow conditions that will fail in Rust."); } diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 1d9260e2aa7..2d283b96f86 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -38,7 +38,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if_chain! { - if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node; + if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node; if !is_automatically_derived(&*item.attrs); if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); if trait_ref.path.def.def_id() == eq_trait; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index bc3bc27f5d9..22804764d8a 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -103,7 +103,7 @@ impl LintPass for PointerPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemFn(ref decl, _, _, body_id) = item.node { + if let ItemKind::Fn(ref decl, _, _, body_id) = item.node { check_fn(cx, decl, item.id, Some(body_id)); } } @@ -111,7 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if let ImplItemKind::Method(ref sig, body_id) = item.node { if let Some(NodeItem(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) { - if let ItemImpl(_, _, _, _, Some(_), _, _) = it.node { + if let ItemKind::Impl(_, _, _, _, Some(_), _, _) = it.node { return; // ignore trait impls } } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index a4bdd89a037..55c51307e04 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -29,7 +29,7 @@ impl LintPass for Serde { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref items) = item.node { + if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref items) = item.node { let did = trait_ref.path.def.def_id(); if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) { if did == visit_did { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index d400e5bf7a7..cc08e1ee816 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -127,7 +127,7 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: if higher::is_from_for_desugar(decl) { return; } - if let DeclLocal(ref local) = decl.node { + if let DeclKind::Local(ref local) = decl.node { let Local { ref pat, ref ty, diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index ce2ef951a43..10db53cc782 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -59,10 +59,15 @@ impl LintPass for SuspiciousImpl { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - use rustc::hir::BinOpKind::*; if let hir::ExprKind::Binary(binop, _, _) = expr.node { match binop.node { - BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt => return, + | hir::BinOpKind::Eq + | hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ne + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt + => return, _ => {}, } // Check if the binary expression is part of another bi/unary expression @@ -94,7 +99,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { expr, binop.node, &["Add", "Sub", "Mul", "Div"], - &[BinOpKind::Add, BinOpKind::Sub, BinOpKind::Mul, BinOpKind::Div], + &[ + hir::BinOpKind::Add, + hir::BinOpKind::Sub, + hir::BinOpKind::Mul, + hir::BinOpKind::Div, + ], ) { span_lint( cx, @@ -124,7 +134,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { "ShrAssign", ], &[ - BinOpKind::Add, BinOpKind::Sub, BinOpKind::Mul, BinOpKind::Div, BinOpKind::BitAnd, BinOpKind::BitOr, BinOpKind::BitXor, BinOpKind::Rem, BinOpKind::Shl, BinOpKind::Shr + hir::BinOpKind::Add, + hir::BinOpKind::Sub, + hir::BinOpKind::Mul, + hir::BinOpKind::Div, + hir::BinOpKind::BitAnd, + hir::BinOpKind::BitOr, + hir::BinOpKind::BitXor, + hir::BinOpKind::Rem, + hir::BinOpKind::Shl, + hir::BinOpKind::Shr, ], ) { span_lint( @@ -167,7 +186,7 @@ fn check_binop<'a>( if_chain! { if parent_impl != ast::CRATE_NODE_ID; if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); - if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; + if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.def.def_id()); if binop != expected_ops[idx]; then{ diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 6ce7b480250..dfcc9c39348 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -62,7 +62,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if_chain! { // let t = foo(); if let StmtKind::Decl(ref tmp, _) = w[0].node; - if let DeclLocal(ref tmp) = tmp.node; + if let DeclKind::Local(ref tmp) = tmp.node; if let Some(ref tmp_init) = tmp.init; if let PatKind::Binding(_, _, ident, None) = tmp.pat.node; @@ -90,7 +90,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); - if matches!(ty.sty, ty::TyKind::Slice(_)) || + if matches!(ty.sty, ty::TySlice(_)) || matches!(ty.sty, ty::TyArray(_, _)) || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) { diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index e8ee73520ef..18c85cd05ab 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -100,8 +100,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { // Exclude non-inherent impls if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { - if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | - ItemTrait(..)) + if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | + ItemKind::Trait(..)) { return; } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 98889aaa33c..ae4f579a6f2 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { // skip trait implementations, see #605 if let Some(map::NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) { - if let ItemImpl(_, _, _, _, Some(..), _, _) = item.node { + if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { return; } } @@ -343,7 +343,7 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti // Returns true if given type is `Any` trait. fn is_any_trait(t: &hir::Ty) -> bool { if_chain! { - if let TyTraitObject(ref traits, _) = t.node; + if let TyKind::TraitObject(ref traits, _) = t.node; if traits.len() >= 1; // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. @@ -377,7 +377,7 @@ declare_clippy_lint! { } fn check_let_unit(cx: &LateContext, decl: &Decl) { - if let DeclLocal(ref local) = decl.node { + if let DeclKind::Local(ref local) = decl.node { if is_unit(cx.tables.pat_ty(&local.pat)) { if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { return; @@ -1141,7 +1141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { match item.node { - ItemStatic(ref ty, _, _) | ItemConst(ref ty, _) => self.check_type(cx, ty), + ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty), // functions, enums, structs, impls and traits are covered _ => (), } @@ -1222,7 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { // function types bring a lot of overhead TyKind::BareFn(..) => (50 * self.nest, 1), - TyTraitObject(ref param_bounds, _) => { + TyKind::TraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds .iter() .any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind { @@ -1797,7 +1797,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { } match item.node { - ItemImpl(_, _, _, ref generics, _, ref ty, ref items) => { + ItemKind::Impl(_, _, _, ref generics, _, ref ty, ref items) => { let mut vis = ImplicitHasherTypeVisitor::new(cx); vis.visit_ty(ty); @@ -1829,7 +1829,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { ); } }, - ItemFn(ref decl, .., ref generics, body_id) => { + ItemKind::Fn(ref decl, .., ref generics, body_id) => { let body = cx.tcx.hir.body(body_id); for ty in &decl.inputs { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 1af8fe83e8b..230d5fdca2c 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { return; } if_chain! { - if let ItemImpl(.., ref item_type, ref refs) = item.node; + if let ItemKind::Impl(.., ref item_type, ref refs) = item.node; if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.node; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e61367fb0b6..9a848c8a805 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -588,20 +588,20 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } fn visit_stmt(&mut self, s: &Stmt) { - print!(" if let Stmt_::"); + print!(" if let StmtKind::"); let current = format!("{}.node", self.current); match s.node { // Could be an item or a local (let) binding: StmtKind::Decl(ref decl, _) => { let decl_pat = self.next("decl"); - println!("StmtKind::Decl(ref {}, _) = {}", decl_pat, current); - print!(" if let Decl_::"); + println!("Decl(ref {}, _) = {}", decl_pat, current); + print!(" if let DeclKind::"); let current = format!("{}.node", decl_pat); match decl.node { // A local (let) binding: DeclKind::Local(ref local) => { let local_pat = self.next("local"); - println!("DeclLocal(ref {}) = {};", local_pat, current); + println!("Local(ref {}) = {};", local_pat, current); if let Some(ref init) = local.init { let init_pat = self.next("init"); println!(" if let Some(ref {}) = {}.init", init_pat, local_pat); @@ -613,7 +613,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, // An item binding: DeclKind::Item(_) => { - println!("DeclItem(item_id) = {};", current); + println!("Item(item_id) = {};", current); }, } } @@ -621,7 +621,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { // Expr without trailing semi-colon (must have unit type): StmtKind::Expr(ref e, _) => { let e_pat = self.next("e"); - println!("StmtKind::Expr(ref {}, _) = {}", e_pat, current); + println!("Expr(ref {}, _) = {}", e_pat, current); self.current = e_pat; self.visit_expr(e); }, @@ -629,7 +629,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { // Expr with trailing semi-colon (may have any type): StmtKind::Semi(ref e, _) => { let e_pat = self.next("e"); - println!("StmtKind::Semi(ref {}, _) = {}", e_pat, current); + println!("Semi(ref {}, _) = {}", e_pat, current); self.current = e_pat; self.visit_expr(e); }, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 72b39000ce5..3f0243a91c0 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -154,7 +154,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // } // ``` if_chain! { - if let hir::DeclLocal(ref loc) = decl.node; + if let hir::DeclKind::Local(ref loc) = decl.node; if let Some(ref expr) = loc.init; if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.node; then { @@ -171,7 +171,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // } // ``` if_chain! { - if let hir::DeclLocal(ref loc) = decl.node; + if let hir::DeclKind::Local(ref loc) = decl.node; if let hir::LocalSource::ForLoopDesugar = loc.source; then { return true; @@ -192,7 +192,7 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; if let hir::StmtKind::Decl(ref decl, _) = let_stmt.node; - if let hir::DeclLocal(ref decl) = decl.node; + if let hir::DeclKind::Local(ref decl) = decl.node; if let hir::StmtKind::Expr(ref expr, _) = body.node; then { return Some((&*decl.pat, &iterargs[0], expr)); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2cec0b2da08..2c5995f1327 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { match (&left.node, &right.node) { (&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => { - if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) { + if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) { both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) } else { false @@ -617,7 +617,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = StmtKind::Decl; c.hash(&mut self.s); - if let DeclLocal(ref local) = decl.node { + if let DeclKind::Local(ref local) = decl.node { if let Some(ref init) = local.init { self.hash_expr(init); } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 1faab372028..b2b99da3c59 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -141,7 +141,7 @@ fn has_attr(attrs: &[Attribute]) -> bool { fn print_decl(cx: &LateContext, decl: &hir::Decl) { match decl.node { - hir::DeclLocal(ref local) => { + hir::DeclKind::Local(ref local) => { println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); println!("pattern:"); print_pat(cx, &local.pat, 0); @@ -150,7 +150,7 @@ fn print_decl(cx: &LateContext, decl: &hir::Decl) { print_expr(cx, e, 0); } }, - hir::DeclItem(_) => println!("item decl"), + hir::DeclKind::Item(_) => println!("item decl"), } } @@ -353,7 +353,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"), } match item.node { - hir::ItemExternCrate(ref _renamed_from) => { + hir::ItemKind::ExternCrate(ref _renamed_from) => { let def_id = cx.tcx.hir.local_def_id(item.id); if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(def_id) { let source = cx.tcx.used_crate_source(crate_id); @@ -367,32 +367,32 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("weird extern crate without a crate id"); } }, - hir::ItemUse(ref path, ref kind) => println!("{:?}, {:?}", path, kind), - hir::ItemStatic(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)), - hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)), - hir::ItemFn(..) => { + hir::ItemKind::Use(ref path, ref kind) => println!("{:?}, {:?}", path, kind), + hir::ItemKind::Static(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)), + hir::ItemKind::Const(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)), + hir::ItemKind::Fn(..) => { let item_ty = cx.tcx.type_of(did); println!("function of type {:#?}", item_ty); }, - hir::ItemMod(..) => println!("module"), - hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi), - hir::ItemGlobalAsm(ref asm) => println!("global asm: {:?}", asm), - hir::ItemTy(..) => { + hir::ItemKind::Mod(..) => println!("module"), + hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi), + hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm), + hir::ItemKind::Ty(..) => { println!("type alias for {:?}", cx.tcx.type_of(did)); }, - hir::ItemExistential(..) => { + hir::ItemKind::Existential(..) => { println!("existential type with real type {:?}", cx.tcx.type_of(did)); }, - hir::ItemEnum(..) => { + hir::ItemKind::Enum(..) => { println!("enum definition of type {:?}", cx.tcx.type_of(did)); }, - hir::ItemStruct(..) => { + hir::ItemKind::Struct(..) => { println!("struct definition of type {:?}", cx.tcx.type_of(did)); }, - hir::ItemUnion(..) => { + hir::ItemKind::Union(..) => { println!("union definition of type {:?}", cx.tcx.type_of(did)); }, - hir::ItemTrait(..) => { + hir::ItemKind::Trait(..) => { println!("trait decl"); if cx.tcx.trait_is_auto(did) { println!("trait is auto"); @@ -400,13 +400,13 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("trait is not auto"); } }, - hir::ItemTraitAlias(..) => { + hir::ItemKind::TraitAlias(..) => { println!("trait alias"); } - hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => { + hir::ItemKind::Impl(_, _, _, _, Some(ref _trait_ref), _, _) => { println!("trait impl"); }, - hir::ItemImpl(_, _, _, _, None, _, _) => { + hir::ItemKind::Impl(_, _, _, _, None, _, _) => { println!("impl"); }, } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 10d46d8894e..a348df83a9d 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::hir::*; +use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::utils::{match_qpath, paths, span_lint}; use syntax::symbol::LocalInternedString; @@ -117,7 +118,7 @@ impl LintPass for LintWithoutLintPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemStatic(ref ty, MutImmutable, body_id) = item.node { + if let hir::ItemKind::Static(ref ty, MutImmutable, body_id) = item.node { if is_lint_ref_type(ty) { self.declared_lints.insert(item.name, item.span); } else if is_lint_array_type(ty) && item.name == "ARRAY" { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8a94ae34382..c38a925efed 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -524,7 +524,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI match node { Node::NodeBlock(block) => Some(block), Node::NodeItem(&Item { - node: ItemFn(_, _, _, eid), + node: ItemKind::Fn(_, _, _, eid), .. }) | Node::NodeImplItem(&ImplItem { node: ImplItemKind::Method(_, eid), diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 27362bd9be9..ff9424289c5 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -382,21 +382,29 @@ fn associativity(op: &AssocOp) -> Associativity { /// Convert a `hir::BinOp` to the corresponding assigning binary operator. fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use rustc::hir::BinOpKind::*; use syntax::parse::token::BinOpToken::*; AssocOp::AssignOp(match op.node { - BinOpKind::Add => Plus, - BinOpKind::BitAnd => And, - BinOpKind::BitOr => Or, - BinOpKind::BitXor => Caret, - BinOpKind::Div => Slash, - BinOpKind::Mul => Star, - BinOpKind::Rem => Percent, - BinOpKind::Shl => Shl, - BinOpKind::Shr => Shr, - BinOpKind::Sub => Minus, - BinOpKind::And | BinOpKind::Eq | BinOpKind::Ge | BinOpKind::Gt | BinOpKind::Le | BinOpKind::Lt | BinOpKind::Ne | BinOpKind::Or => panic!("This operator does not exist"), + hir::BinOpKind::Add => Plus, + hir::BinOpKind::BitAnd => And, + hir::BinOpKind::BitOr => Or, + hir::BinOpKind::BitXor => Caret, + hir::BinOpKind::Div => Slash, + hir::BinOpKind::Mul => Star, + hir::BinOpKind::Rem => Percent, + hir::BinOpKind::Shl => Shl, + hir::BinOpKind::Shr => Shr, + hir::BinOpKind::Sub => Minus, + + | hir::BinOpKind::And + | hir::BinOpKind::Eq + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt + | hir::BinOpKind::Le + | hir::BinOpKind::Lt + | hir::BinOpKind::Ne + | hir::BinOpKind::Or + => panic!("This operator does not exist"), }) } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0adbb36b5ff..556d128bca7 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -448,7 +448,7 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { // `Debug` impl if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { - if let ItemImpl(_, _, _, _, Some(ref tr), _, _) = item.node { + if let ItemKind::Impl(_, _, _, _, Some(ref tr), _, _) = item.node { return match_path(&tr.path, &["Debug"]); } } -- cgit 1.4.1-3-g733a5 From 8f61a792f4f54f24adf9a8cb7824bfdb259c50ef Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 16 Jul 2018 15:43:30 +0200 Subject: Update test output to changes in rustc --- tests/ui/deprecated.stderr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index aa62ccbd0e5..6bbc0aebf9c 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -1,4 +1,4 @@ -error: lint str_to_string has been removed: using `str::to_string` is common even today and specialization will likely happen soon +error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:4:8 | 4 | #[warn(str_to_string)] @@ -6,25 +6,25 @@ error: lint str_to_string has been removed: using `str::to_string` is common eve | = note: `-D renamed-and-removed-lints` implied by `-D warnings` -error: lint string_to_string has been removed: using `string::to_string` is common even today and specialization will likely happen soon +error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:6:8 | 6 | #[warn(string_to_string)] | ^^^^^^^^^^^^^^^^ -error: lint unstable_as_slice has been removed: `Vec::as_slice` has been stabilized in 1.7 +error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` --> $DIR/deprecated.rs:8:8 | 8 | #[warn(unstable_as_slice)] | ^^^^^^^^^^^^^^^^^ -error: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been stabilized in 1.7 +error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` --> $DIR/deprecated.rs:10:8 | 10 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ -error: lint misaligned_transmute has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr +error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` --> $DIR/deprecated.rs:12:8 | 12 | #[warn(misaligned_transmute)] -- cgit 1.4.1-3-g733a5 From 29cae6263b442ae291e2d8422172a25be092d510 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 16 Jul 2018 13:05:02 -0700 Subject: Update readme for new clippy install method --- README.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 5bd3981260e..353b28897a5 100644 --- a/README.md +++ b/README.md @@ -35,44 +35,45 @@ Table of contents: Since this is a tool for helping the developer of a library or application write better code, it is recommended not to include Clippy as a hard dependency. Options include using it as an optional dependency, as a cargo subcommand, or -as an included feature during build. All of these options are detailed below. +as an included feature during build. These options are detailed below. -As a general rule Clippy will only work with the *latest* Rust nightly for now. +### As a cargo subcommand (`cargo clippy`) -To install Rust nightly, the recommended way is to use [rustup](https://rustup.rs/): +One way to use Clippy is by installing Clippy through rustup as a cargo +subcommand. -```terminal -rustup install nightly -``` +#### Step 1: Install rustup -### As a cargo subcommand (`cargo clippy`) +You can install [rustup](http://rustup.rs/) on supported platforms. This will help +us install clippy and its dependencies. -One way to use Clippy is by installing Clippy through cargo as a cargo -subcommand. +If you already have rustup installed, update to ensure you have the latest +rustup and compiler: ```terminal -cargo +nightly install clippy +rustup update ``` -(The `+nightly` is not necessary if your default `rustup` install is nightly) +#### Step 2: Install nightly toolchain -Now you can run Clippy by invoking `cargo +nightly clippy`. +As a general rule Clippy will only work with the *latest* Rust nightly for now. -To update the subcommand together with the latest nightly use the [rust-update](rust-update) script or run: +To install Rust nightly with [rustup](https://rustup.rs/): ```terminal -rustup update nightly -cargo +nightly install --force clippy +rustup install nightly ``` -In case you are not using rustup, you need to set the environment flag -`SYSROOT` during installation so Clippy knows where to find `librustc` and -similar crates. +#### Step 3: Install clippy + +Once you have rustup and the nightly toolchain installed, run the following command: ```terminal -SYSROOT=/path/to/rustc/sysroot cargo install clippy +rustup component add clippy-preview --toolchain=nightly ``` +Now you can run Clippy by invoking `cargo +nightly clippy`. + ### Running Clippy from the command line without installing it To have cargo compile your crate with Clippy without Clippy installation -- cgit 1.4.1-3-g733a5 From a43f8cf819c067b5bb646622f135e310eba02af5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 16 Jul 2018 13:39:38 -0700 Subject: some readme clarifications --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 353b28897a5..41eacdba1a4 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ rustup update #### Step 2: Install nightly toolchain -As a general rule Clippy will only work with the *latest* Rust nightly for now. +Rustup integration is still new, you will need a relatively new nightly (2018-07-15 or later). To install Rust nightly with [rustup](https://rustup.rs/): @@ -72,7 +72,8 @@ Once you have rustup and the nightly toolchain installed, run the following comm rustup component add clippy-preview --toolchain=nightly ``` -Now you can run Clippy by invoking `cargo +nightly clippy`. +Now you can run Clippy by invoking `cargo +nightly clippy`. If nightly is your +default toolchain in rustup, `cargo clippy` will work fine. ### Running Clippy from the command line without installing it -- cgit 1.4.1-3-g733a5 From e58eb520a45cd3843eb7cfa96980be8da7f65fa2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 16 Jul 2018 13:55:32 -0700 Subject: Fix travis build by removing cargo-clippy --- ci/base-tests.sh | 1 + ci/integration-tests.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 37c13fe069e..4b304f6f2a6 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -6,6 +6,7 @@ cargo test --features debugging mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver +rm ~/.cargo/bin/cargo-clippy PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 28785f633c3..a989b261ac7 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,4 +1,5 @@ set -x +rm ~/.cargo/bin/cargo-clippy cargo install --force --path . echo "Running integration test for crate ${INTEGRATION}" -- cgit 1.4.1-3-g733a5 From 3246a1f5c0ecd85e53f9d2564305a3f7f063064e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 16 Jul 2018 16:29:09 -0700 Subject: Update mini-macro post proc macro stabilization https://github.com/rust-lang/rust/pull/52081 stabilized proc macros, but quote is still unstable, so you need to explicitly enable that feature. --- mini-macro/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 9f88de62677..3417e603c12 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro, proc_macro_non_items)] +#![feature(use_extern_macros, proc_macro_quote, proc_macro_non_items)] extern crate proc_macro; use proc_macro::{TokenStream, quote}; -- cgit 1.4.1-3-g733a5 From 5bb52c486967abed8f5f1de74f66d9c3a17a789f Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 17 Jul 2018 08:20:49 +0200 Subject: Fix use_self regressions --- clippy_lints/src/use_self.rs | 51 ++++++++++++++---------- tests/ui/use_self.rs | 25 +++++++++--- tests/ui/use_self.stderr | 94 ++++++++++++++++++++++++++------------------ 3 files changed, 105 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 82dc0fd2b8a..a4450acea09 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -4,7 +4,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; use syntax::ast::NodeId; -use syntax::symbol::keywords; use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a @@ -58,26 +57,29 @@ fn span_use_self_lint(cx: &LateContext, path: &Path) { } struct TraitImplTyVisitor<'a, 'tcx: 'a> { + item_path: &'a Path, cx: &'a LateContext<'a, 'tcx>, - type_walker: ty::walk::TypeWalker<'tcx>, + trait_type_walker: ty::walk::TypeWalker<'tcx>, + impl_type_walker: ty::walk::TypeWalker<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &'tcx Ty) { - let trait_ty = self.type_walker.next(); + let trait_ty = self.trait_type_walker.next(); + let impl_ty = self.impl_type_walker.next(); + if let TyKind::Path(QPath::Resolved(_, path)) = &t.node { - let impl_is_self_ty = if let def::Def::SelfTy(..) = path.def { - true - } else { - false - }; - if !impl_is_self_ty { - let trait_is_self_ty = if let Some(ty::TyParam(ty::ParamTy { name, .. })) = trait_ty.map(|ty| &ty.sty) { - *name == keywords::SelfType.name().as_str() + if self.item_path.def == path.def { + let is_self_ty = if let def::Def::SelfTy(..) = path.def { + true } else { false }; - if trait_is_self_ty { + + if !is_self_ty && impl_ty != trait_ty { + // The implementation and trait types don't match which means that + // the concrete type was specified by the implementation but + // it didn't use `Self` span_use_self_lint(self.cx, path); } } @@ -92,6 +94,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { fn check_trait_method_impl_decl<'a, 'tcx: 'a>( cx: &'a LateContext<'a, 'tcx>, + item_path: &'a Path, impl_item: &ImplItem, impl_decl: &'tcx FnDecl, impl_trait_ref: &ty::TraitRef, @@ -110,24 +113,30 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); let trait_method_sig = cx.tcx.erase_late_bound_regions(&trait_method_sig); + let impl_method_def_id = cx.tcx.hir.local_def_id(impl_item.id); + let impl_method_sig = cx.tcx.fn_sig(impl_method_def_id); + let impl_method_sig = cx.tcx.erase_late_bound_regions(&impl_method_sig); + let output_ty = if let FunctionRetTy::Return(ty) = &impl_decl.output { Some(&**ty) } else { None }; - for (impl_ty, trait_ty) in impl_decl - .inputs - .iter() - .chain(output_ty) - .zip(trait_method_sig.inputs_and_output) - { + for (impl_decl_ty, (impl_ty, trait_ty)) in impl_decl.inputs.iter().chain(output_ty).zip( + impl_method_sig + .inputs_and_output + .iter() + .zip(trait_method_sig.inputs_and_output), + ) { let mut visitor = TraitImplTyVisitor { cx, - type_walker: trait_ty.walk(), + item_path, + trait_type_walker: trait_ty.walk(), + impl_type_walker: impl_ty.walk(), }; - visitor.visit_ty(&impl_ty); + visitor.visit_ty(&impl_decl_ty); } } @@ -163,7 +172,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); if let ImplItemKind::Method(MethodSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.node { - check_trait_method_impl_decl(cx, impl_item, impl_decl, &impl_trait_ref); + check_trait_method_impl_decl(cx, item_path, impl_item, impl_decl, &impl_trait_ref); let body = cx.tcx.hir.body(*impl_body_id); visitor.visit_body(body); } else { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index e3133b0a7a1..689c9d68d12 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,10 +1,6 @@ - - #![warn(use_self)] #![allow(dead_code)] #![allow(should_implement_trait)] -#![allow(boxed_local)] - fn main() {} @@ -68,9 +64,10 @@ mod lifetimes { } } +#[allow(boxed_local)] mod traits { - #![cfg_attr(feature = "cargo-clippy", allow(boxed_local))] + use std::ops::Mul; trait SelfTrait { fn refs(p1: &Self) -> &Self; @@ -104,6 +101,14 @@ mod traits { } } + impl Mul for Bad { + type Output = Bad; + + fn mul(self, rhs: Bad) -> Bad { + rhs + } + } + #[derive(Default)] struct Good; @@ -128,6 +133,14 @@ mod traits { } } + impl Mul for Good { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + rhs + } + } + trait NameTrait { fn refs(p1: &u8) -> &u8; fn ref_refs<'a>(p1: &'a &'a u8) -> &'a &'a u8; @@ -162,7 +175,7 @@ mod traits { impl Clone for Good { fn clone(&self) -> Self { // Note: Not linted and it wouldn't be valid - // because "can't use `Self` as a constructor` + // because "can't use `Self` as a constructor`" Good } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index ede95126f86..89936101252 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,106 +1,124 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:15:21 + --> $DIR/use_self.rs:11:21 | -15 | fn new() -> Foo { +11 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:16:13 + --> $DIR/use_self.rs:12:13 | -16 | Foo {} +12 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:18:22 + --> $DIR/use_self.rs:14:22 | -18 | fn test() -> Foo { +14 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:19:13 + --> $DIR/use_self.rs:15:13 | -19 | Foo::new() +15 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:25 + --> $DIR/use_self.rs:20:25 | -24 | fn default() -> Foo { +20 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:25:13 + --> $DIR/use_self.rs:21:13 | -25 | Foo::new() +21 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:87:22 + --> $DIR/use_self.rs:84:22 | -87 | fn refs(p1: &Bad) -> &Bad { +84 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:87:31 + --> $DIR/use_self.rs:84:31 | -87 | fn refs(p1: &Bad) -> &Bad { +84 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:91:37 + --> $DIR/use_self.rs:88:37 | -91 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { +88 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:91:53 + --> $DIR/use_self.rs:88:53 | -91 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { +88 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:95:30 + --> $DIR/use_self.rs:92:30 | -95 | fn mut_refs(p1: &mut Bad) -> &mut Bad { +92 | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:95:43 + --> $DIR/use_self.rs:92:43 | -95 | fn mut_refs(p1: &mut Bad) -> &mut Bad { +92 | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:28 + --> $DIR/use_self.rs:96:28 | -99 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +96 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:46 + --> $DIR/use_self.rs:96:46 | -99 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +96 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:102:20 + --> $DIR/use_self.rs:99:20 + | +99 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:99:28 + | +99 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:100:13 | -102 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` +100 | Bad::default() + | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:102:28 + --> $DIR/use_self.rs:105:23 | -102 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` +105 | type Output = Bad; + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:103:13 + --> $DIR/use_self.rs:107:27 | -103 | Bad::default() - | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` +107 | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:107:35 + | +107 | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 17 previous errors +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From a05c9b63ce49923fba2709ab7e04be7077a01543 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 18 Jul 2018 07:57:50 +0200 Subject: use_self: Simplify spanning --- clippy_lints/src/use_self.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index a4450acea09..d5aaaa81c03 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,4 +1,4 @@ -use crate::utils::{in_macro, span_lint_and_then}; +use crate::utils::{in_macro, span_lint_and_sugg}; use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -51,9 +51,14 @@ impl LintPass for UseSelf { const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; fn span_use_self_lint(cx: &LateContext, path: &Path) { - span_lint_and_then(cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| { - db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned()); - }); + span_lint_and_sugg( + cx, + USE_SELF, + path.span, + "unnecessary structure name repetition", + "use the applicable keyword", + "Self".to_owned(), + ); } struct TraitImplTyVisitor<'a, 'tcx: 'a> { -- cgit 1.4.1-3-g733a5 From c05adc545cff45449d40b1c72070ada7db5fc953 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 18 Jul 2018 20:24:37 -0700 Subject: Temporarily allow macro_use_extern_crate --- clippy_lints/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 98258189701..367a103602d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -13,6 +13,7 @@ #![feature(macro_at_most_once_rep)] #![feature(rust_2018_preview)] #![warn(rust_2018_idioms)] +#![allow(macro_use_extern_crate)] #[macro_use] extern crate rustc; -- cgit 1.4.1-3-g733a5 From 2c65e7c83504e2bc01b493c97ff04c57a69636a0 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Thu, 19 Jul 2018 14:12:47 +0800 Subject: Improve website panel heading experience --- util/gh-pages/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 6892857af4e..0088ecc3d89 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -14,6 +14,9 @@ .form-inline .checkbox { margin-right: 0.6em } + .panel-heading { pointer: cursor; } + .panel-heading:hover { background-color: #eee; } + .panel-title { display: flex; } .panel-title .label { display: inline-block; } -- cgit 1.4.1-3-g733a5 From c1745cde82c7f20bff3b7cd8411834af6df25d14 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 00:02:08 -0700 Subject: Remove import of serde --- clippy_lints/src/lib.rs | 3 --- clippy_lints/src/utils/conf.rs | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 367a103602d..7eaa1de3c06 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -24,9 +24,6 @@ use rustc_plugin; #[macro_use] extern crate matches as matches_macro; -#[macro_use] -extern crate serde_derive; - #[macro_use] extern crate lazy_static; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 05abdd2f13c..e18245c3f98 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -7,7 +7,6 @@ use std::io::Read; use syntax::{ast, codemap}; use toml; use std::sync::Mutex; - /// Get the configuration file from arguments. pub fn file_from_args( args: &[codemap::Spanned], @@ -86,10 +85,10 @@ macro_rules! define_Conf { // #[allow(rust_2018_idioms)] mod helpers { + use serde_derive::Deserialize; /// Type used to store lint configuration. #[derive(Deserialize)] - #[serde(rename_all="kebab-case")] - #[serde(deny_unknown_fields)] + #[serde(rename_all="kebab-case", deny_unknown_fields)] pub struct Conf { $(#[$doc] #[serde(default=$rust_name_str)] #[serde(with=$rust_name_str)] pub $rust_name: define_Conf!(TY $($ty)+),)+ -- cgit 1.4.1-3-g733a5 From 00ba67a12b9cb725c2308c5d3f8f70528878610c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 00:11:15 -0700 Subject: Remove import of lazy_static --- clippy_lints/src/lib.rs | 3 --- clippy_lints/src/utils/conf.rs | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7eaa1de3c06..02e92f1f407 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -24,9 +24,6 @@ use rustc_plugin; #[macro_use] extern crate matches as matches_macro; -#[macro_use] -extern crate lazy_static; - #[macro_use] extern crate if_chain; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index e18245c3f98..52b34916627 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -2,11 +2,13 @@ #![deny(missing_docs_in_private_items)] +use lazy_static::lazy_static; use std::{env, fmt, fs, io, path}; use std::io::Read; use syntax::{ast, codemap}; use toml; use std::sync::Mutex; + /// Get the configuration file from arguments. pub fn file_from_args( args: &[codemap::Spanned], -- cgit 1.4.1-3-g733a5 From 5d74e2096b1335fe4a913b7ffbdac5bbdc6c8f5a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 00:53:23 -0700 Subject: Remove import of rustc --- clippy_lints/src/approx_const.rs | 1 + clippy_lints/src/arithmetic.rs | 1 + clippy_lints/src/assign_ops.rs | 1 + clippy_lints/src/attrs.rs | 1 + clippy_lints/src/bit_mask.rs | 1 + clippy_lints/src/blacklisted_name.rs | 1 + clippy_lints/src/block_in_if_condition.rs | 1 + clippy_lints/src/booleans.rs | 1 + clippy_lints/src/bytecount.rs | 1 + clippy_lints/src/collapsible_if.rs | 1 + clippy_lints/src/const_static_lifetime.rs | 1 + clippy_lints/src/consts.rs | 1 + clippy_lints/src/copies.rs | 1 + clippy_lints/src/cyclomatic_complexity.rs | 1 + clippy_lints/src/default_trait_access.rs | 1 + clippy_lints/src/derive.rs | 1 + clippy_lints/src/doc.rs | 1 + clippy_lints/src/double_comparison.rs | 1 + clippy_lints/src/double_parens.rs | 1 + clippy_lints/src/drop_forget_ref.rs | 1 + clippy_lints/src/duration_subsec.rs | 1 + clippy_lints/src/else_if_without_else.rs | 1 + clippy_lints/src/empty_enum.rs | 1 + clippy_lints/src/entry.rs | 1 + clippy_lints/src/enum_clike.rs | 1 + clippy_lints/src/enum_glob_use.rs | 1 + clippy_lints/src/enum_variants.rs | 1 + clippy_lints/src/eq_op.rs | 1 + clippy_lints/src/erasing_op.rs | 1 + clippy_lints/src/escape.rs | 1 + clippy_lints/src/eta_reduction.rs | 1 + clippy_lints/src/eval_order_dependence.rs | 1 + clippy_lints/src/excessive_precision.rs | 1 + clippy_lints/src/explicit_write.rs | 1 + clippy_lints/src/fallible_impl_from.rs | 1 + clippy_lints/src/format.rs | 1 + clippy_lints/src/formatting.rs | 1 + clippy_lints/src/functions.rs | 1 + clippy_lints/src/identity_conversion.rs | 1 + clippy_lints/src/identity_op.rs | 1 + clippy_lints/src/if_let_redundant_pattern_matching.rs | 1 + clippy_lints/src/if_not_else.rs | 1 + clippy_lints/src/indexing_slicing.rs | 1 + clippy_lints/src/infallible_destructuring_match.rs | 1 + clippy_lints/src/infinite_iter.rs | 1 + clippy_lints/src/inherent_impl.rs | 1 + clippy_lints/src/inline_fn_without_body.rs | 1 + clippy_lints/src/int_plus_one.rs | 1 + clippy_lints/src/invalid_ref.rs | 1 + clippy_lints/src/items_after_statements.rs | 1 + clippy_lints/src/large_enum_variant.rs | 1 + clippy_lints/src/len_zero.rs | 1 + clippy_lints/src/let_if_seq.rs | 1 + clippy_lints/src/lib.rs | 3 --- clippy_lints/src/lifetimes.rs | 1 + clippy_lints/src/literal_representation.rs | 1 + clippy_lints/src/loops.rs | 1 + clippy_lints/src/map_clone.rs | 1 + clippy_lints/src/map_unit_fn.rs | 1 + clippy_lints/src/matches.rs | 1 + clippy_lints/src/mem_forget.rs | 1 + clippy_lints/src/methods.rs | 1 + clippy_lints/src/minmax.rs | 1 + clippy_lints/src/misc.rs | 1 + clippy_lints/src/misc_early.rs | 1 + clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/missing_inline.rs | 1 + clippy_lints/src/multiple_crate_versions.rs | 1 + clippy_lints/src/mut_mut.rs | 1 + clippy_lints/src/mut_reference.rs | 1 + clippy_lints/src/mutex_atomic.rs | 1 + clippy_lints/src/needless_bool.rs | 1 + clippy_lints/src/needless_borrow.rs | 1 + clippy_lints/src/needless_borrowed_ref.rs | 1 + clippy_lints/src/needless_continue.rs | 1 + clippy_lints/src/needless_pass_by_value.rs | 1 + clippy_lints/src/needless_update.rs | 1 + clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 1 + clippy_lints/src/neg_multiply.rs | 1 + clippy_lints/src/new_without_default.rs | 1 + clippy_lints/src/no_effect.rs | 1 + clippy_lints/src/non_copy_const.rs | 1 + clippy_lints/src/non_expressive_names.rs | 1 + clippy_lints/src/ok_if_let.rs | 1 + clippy_lints/src/open_options.rs | 1 + clippy_lints/src/overflow_check_conditional.rs | 1 + clippy_lints/src/panic_unimplemented.rs | 1 + clippy_lints/src/partialeq_ne_impl.rs | 1 + clippy_lints/src/precedence.rs | 1 + clippy_lints/src/ptr.rs | 1 + clippy_lints/src/question_mark.rs | 1 + clippy_lints/src/ranges.rs | 1 + clippy_lints/src/redundant_field_names.rs | 1 + clippy_lints/src/reference.rs | 1 + clippy_lints/src/regex.rs | 1 + clippy_lints/src/replace_consts.rs | 1 + clippy_lints/src/returns.rs | 1 + clippy_lints/src/serde_api.rs | 1 + clippy_lints/src/shadow.rs | 1 + clippy_lints/src/strings.rs | 1 + clippy_lints/src/suspicious_trait_impl.rs | 1 + clippy_lints/src/swap.rs | 1 + clippy_lints/src/temporary_assignment.rs | 1 + clippy_lints/src/transmute.rs | 1 + clippy_lints/src/trivially_copy_pass_by_ref.rs | 1 + clippy_lints/src/types.rs | 1 + clippy_lints/src/unicode.rs | 1 + clippy_lints/src/unsafe_removed_from_name.rs | 1 + clippy_lints/src/unused_io_amount.rs | 1 + clippy_lints/src/unused_label.rs | 1 + clippy_lints/src/unwrap.rs | 1 + clippy_lints/src/use_self.rs | 1 + clippy_lints/src/utils/author.rs | 1 + clippy_lints/src/utils/inspector.rs | 1 + clippy_lints/src/utils/internal_lints.rs | 1 + clippy_lints/src/vec.rs | 1 + clippy_lints/src/write.rs | 1 + clippy_lints/src/zero_div_zero.rs | 1 + 118 files changed, 117 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 13e1dbe3c0a..b9de43762e0 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,6 +1,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 0ab7a338863..b3d78d2d13f 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,6 +1,7 @@ use crate::utils::span_lint; use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; /// **What it does:** Checks for plain integer arithmetic. diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 272b6c5a84d..5acdf8172e6 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -3,6 +3,7 @@ use crate::utils::{higher, sugg}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; /// **What it does:** Checks for compound assignment operations (`+=` and diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 5d5e2f964b0..c19f075cea3 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,6 +7,7 @@ use crate::utils::{ }; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 25d5e4d4db1..e772042f0a6 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::LitKind; use syntax::codemap::Span; use crate::utils::{span_lint, span_lint_and_then}; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 29660399233..cfec01d14ae 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint; diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 94e17290b6a..7d4d667da9a 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::utils::*; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index e23978ebc1d..7d627f49836 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index aaa924e95b1..f27961783e7 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast::{Name, UintTy}; use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 786148f6eec..a2d280e75e3 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -13,6 +13,7 @@ //! This lint is **warn** by default use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index bde5ee4dc8b..8bb209a6490 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,5 +1,6 @@ use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use crate::utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d7323337f24..878ad276343 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -2,6 +2,7 @@ #![allow(float_cmp)] use rustc::lint::LateContext; +use rustc::{span_bug, bug}; use rustc::hir::def::Def; use rustc::hir::*; use rustc::ty::{self, Ty, TyCtxt, Instance}; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 9e9a641ce27..c0830c5ea31 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::Ty; use rustc::hir::*; use std::collections::HashMap; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index b1b667d046c..c397ca7824e 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -2,6 +2,7 @@ use rustc::cfg::CFG; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::ty; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 900dabc9650..915386757f0 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::TypeVariants; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 0d0eb27fb7d..02816ce9e4e 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index dfd59af9adb..a298137976b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,6 +1,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::codemap::{BytePos, Span}; use syntax_pos::Pos; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index e2ea5723a98..434ccb69921 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 2b81e1db257..2617eab0aa7 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,5 +1,6 @@ use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_lint, lint_array}; /// **What it does:** Checks for unnecessary double parentheses. /// diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index b0625e10d76..8fb01d79a1e 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::*; use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index d374973e35b..4679ce15871 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Spanned; use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 96c215df405..b8406904821 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,6 +1,7 @@ //! lint on if expressions with an else if, but without a final else branch use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{in_external_macro, span_lint_and_sugg}; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 1ca32cf2263..803ba34a865 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,6 +1,7 @@ //! lint when there is an enum with no variants use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index f29c2d1bb6d..8f731e992ab 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 6584bc6ffa9..62cbead1929 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -2,6 +2,7 @@ //! don't fit into an `i32` use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::ty; use rustc::ty::subst::Substs; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 042a96a21c8..10cf497725c 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -3,6 +3,7 @@ use rustc::hir::*; use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use syntax::ast::NodeId; use syntax::codemap::Span; use crate::utils::span_lint; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index d272cab0a0d..6a14638057a 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,6 +1,7 @@ //! lint on enum variants that are prefixed or suffixed by the same characters use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index f58b499d806..dfbc3b12633 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index acede5d1a13..102769a375e 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,6 +1,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index a03dc7b6269..ff5c85b6009 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::hir::intravisit as visit; use rustc::hir::map::Node::{NodeExpr, NodeStmt}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt_, Categorization}; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 87f0e64caaf..7b6623ed29b 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::*; use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 58436bd897b..33f6295a23b 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -2,6 +2,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 24bbf669205..a1c4484a2e5 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,5 +1,6 @@ use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::TypeVariants; use std::f32; use std::f64; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 019d21f81e0..554d52d4499 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; use crate::utils::opt_def_id; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 1ea000d3611..b6136708e18 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::ty; use syntax_pos::Span; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index e88f0386893..31ae3eb0fec 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast::LitKind; use syntax_pos::Span; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 8008bb3ed66..784461c23ee 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use syntax::ptr::P; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 16438092315..f58a91bc211 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,6 +1,7 @@ use rustc::hir::intravisit; use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::def::Def; use std::collections::HashSet; diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 32ae8bcb29f..a0705f62544 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::NodeId; use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 92e07401818..3a8a366890a 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,6 +1,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; use rustc::ty; diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 17dcf571fbf..bc97584a23d 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 22ca1a61c9b..eea83ca6b88 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -2,6 +2,7 @@ //! on the condition use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{in_external_macro, span_help_and_lint}; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 8176408e720..aaea60f2c05 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -6,6 +6,7 @@ use crate::utils::higher; use crate::utils::higher::Range; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast::RangeLimits; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 9abd9754d67..0f1ccddb3c4 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -1,6 +1,7 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; /// **What it does:** Checks for matches being used to destructure a single-variant enum /// or tuple struct where a `let` will suffice. diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index a979486945a..3f461a07ab2 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 9fb9a162cde..fc06af81574 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::collections::HashMap; use std::default::Default; use syntax_pos::Span; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 8dab9fbd12f..b308e3ca81f 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,6 +1,7 @@ //! checks for `#[inline]` on trait methods without bodies use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::{Attribute, Name}; use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 8daf3d296c7..490d06f259f 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,6 +1,7 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 255efa74165..8fd097edafd 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::*; use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 685c91c0457..61eaa7bea6e 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,6 +1,7 @@ //! lint when items are used after statements use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 926e3a3033f..f29e5040354 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,6 +1,7 @@ //! lint when there is a large size difference between variants on an enum use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{snippet_opt, span_lint_and_then}; use rustc::ty::layout::LayoutOf; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index bd02eb5c81f..e3ff60d30a2 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,6 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index a72e09f9fdf..dd8d1d175cc 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::BindingAnnotation; use rustc::hir::def::Def; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 02e92f1f407..ac52c82b602 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -15,9 +15,6 @@ #![warn(rust_2018_idioms)] #![allow(macro_use_extern_crate)] -#[macro_use] -extern crate rustc; - use toml; use rustc_plugin; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 1b371a8141e..edd144d8de4 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,5 +1,6 @@ use crate::reexport::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::*; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9b6c30f7f4c..2788258a0cd 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -2,6 +2,7 @@ //! floating-point literal expressions. use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax_pos; use crate::utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e7da7bde30f..f975df6001e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -6,6 +6,7 @@ use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::middle::region; // use rustc::middle::region::CodeExtent; use rustc::middle::expr_use_visitor::*; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 01ce702c17c..40bb2364935 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::ty; use syntax::ast; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 8df573e4c72..99df6a41eef 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,5 +1,6 @@ use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc_errors::Applicability; use syntax::codemap::Span; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index c82d156462d..82ed199e0cb 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use std::cmp::Ordering; use std::collections::Bound; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 11cf8a9a791..88c24458646 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::{Expr, ExprKind}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 26a0b66094f..f878102a52e 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,5 +1,6 @@ use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::hir::def::Def; use std::borrow::Cow; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index fa2c9fda731..498f9ef4743 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -2,6 +2,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::cmp::Ordering; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c5440420fc1..c517d4a44ee 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -2,6 +2,7 @@ use crate::reexport::*; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::codemap::{ExpnFormat, Span}; use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index e527a05c851..a5ee070d900 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::collections::HashMap; use std::char; use syntax::ast::*; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index eb4dfe8ba1c..750fdfde506 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -20,6 +20,7 @@ use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast; use syntax::attr; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 0ca1c53d696..a07c8329a73 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -11,6 +11,7 @@ use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::codemap::Span; diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index d347270236d..b484488b106 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,6 +1,7 @@ //! lint on multiple versions of a crate being used use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use cargo_metadata; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index ef08e60c4ef..f3918f542df 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use crate::utils::{higher, in_external_macro, span_lint}; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index b4d6652a65a..de4c5444440 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use rustc::hir::*; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index e5679bb7ba5..2448cd84d7c 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -3,6 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 2fd5ff9a246..559aa74f9a2 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,6 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 90e41bc6f68..728ca969ac5 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -3,6 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 91cc01891a9..ebefcfcca16 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,6 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use crate::utils::{in_macro, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 3258bcd069a..0b955bbfdff 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -28,6 +28,7 @@ //! //! This lint is **warn** by default. use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::codemap::{original_sp, DUMMY_SP}; use std::borrow::Cow; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index fa0586c1548..6b961eedeb7 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; use rustc::middle::expr_use_visitor as euv; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 9c670c1a5b3..52c4c6e5237 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::{Expr, ExprKind}; use crate::utils::span_lint; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index e0374b80dd8..fd2266c8614 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{self, paths, span_lint, in_external_macro}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index e30ac8695dc..0a12217e8d0 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::{Span, Spanned}; use crate::consts::{self, Constant}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 6be340a99f4..80c92042687 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,6 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use syntax::codemap::Span; use crate::utils::paths; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 5180ff34877..dc83b29854c 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 981451947bf..f2c9210aae4 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -3,6 +3,7 @@ //! This lint is **deny** by default. use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::def::Def; use rustc::ty::{self, TypeFlags}; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index b49e3f87ec9..8f21523f404 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; use syntax::ast::*; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 0a1399075e0..6a21807b90b 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index b4559969ac2..06b48b9eeac 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,5 +1,6 @@ use rustc::hir::{Expr, ExprKind}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 8783055b31e..0ae400879da 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{span_lint, SpanlessEq}; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 24cf6544f6a..2edcef5bcda 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::LitKind; use syntax::ptr::P; use syntax::ext::quote::rt::Span; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 2d283b96f86..e001bbebd3c 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{is_automatically_derived, span_lint}; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 7f5dd2abc0e..76ea9c5ade6 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::codemap::Spanned; use crate::utils::{in_macro, snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 22804764d8a..5093819db5f 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -5,6 +5,7 @@ use rustc::hir::*; use rustc::hir::map::NodeItem; use rustc::hir::QPath; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b8e7a2646c4..9ede9afebd7 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::def::Def; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 2fb3bf5182c..03bf7be4285 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::RangeLimits; use syntax::codemap::Spanned; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index d179bffd59a..4f28d36e2a8 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index d8179816236..6baa6174563 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,5 +1,6 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index fbead26a03b..114a14bdf96 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,6 +1,7 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index f149e324877..5f5957b0209 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::def::Def; use crate::utils::{match_def_path, span_lint_and_sugg}; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 03a5d58a3ee..29d50d87fb8 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::codemap::Span; use syntax::visit::FnKind; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 55c51307e04..ce326ea72ca 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{get_trait_def_id, paths, span_lint}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index cc08e1ee816..563530c1ae7 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,5 +1,6 @@ use crate::reexport::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 40f5c66ce15..fa8102308d8 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::codemap::Spanned; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 10db53cc782..704ad04325d 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index dfcc9c39348..d8bf6e567f6 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty; use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 008ab56bda8..56e705ad0a7 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::{Expr, ExprKind}; use crate::utils::is_adjusted; use crate::utils::span_lint; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 9914ab0e8db..7abf5fdcc92 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::hir::*; use std::borrow::Cow; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 18c85cd05ab..57d9ddf3955 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -4,6 +4,7 @@ use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::TypeVariants; use rustc::session::config::Config as SessionConfig; use rustc_target::spec::abi::Abi; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ae4f579a6f2..df14eb15957 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -3,6 +3,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::layout::LayoutOf; use rustc_typeck::hir_ty_to_ty; diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index ddd9db9eda3..c4a795bfacb 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::Span; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index a1f31770ec0..a6cab892324 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::codemap::Span; use syntax::symbol::LocalInternedString; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 649a1033371..e4dac731cf2 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 0ae956b9443..1681a303fd3 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use std::collections::HashMap; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index fcc3c2f68c1..4f7e9e9c0a1 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use rustc::hir::intravisit::*; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 230d5fdca2c..3b677379298 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,4 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; use crate::utils::{in_macro, span_lint_and_then}; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 9a848c8a805..4310325475a 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -4,6 +4,7 @@ #![allow(print_stdout, use_debug)] use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b2b99da3c59..969e3414f17 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -3,6 +3,7 @@ //! checks for attributes use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::print; use syntax::ast::Attribute; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index a348df83a9d..3d43d595def 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,4 +1,5 @@ use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 39ab77c3afa..68caa5b4494 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,5 +1,6 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use syntax::codemap::Span; use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 556d128bca7..5112ad86ff0 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,6 +1,7 @@ use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::hir::*; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use std::ops::Deref; use syntax::ast::LitKind; use syntax::ptr; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 5232d5714f1..0b1b3a41305 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,5 +1,6 @@ use crate::consts::{constant_simple, Constant}; use rustc::lint::*; +use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::span_help_and_lint; -- cgit 1.4.1-3-g733a5 From c7676356b88b58a6eaab192a094baab239de7137 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 00:24:19 -0700 Subject: Remove import of matches --- clippy_lints/src/block_in_if_condition.rs | 1 + clippy_lints/src/functions.rs | 1 + clippy_lints/src/items_after_statements.rs | 1 + clippy_lints/src/lib.rs | 2 -- clippy_lints/src/lifetimes.rs | 1 + clippy_lints/src/methods.rs | 1 + clippy_lints/src/misc.rs | 1 + clippy_lints/src/needless_pass_by_value.rs | 1 + clippy_lints/src/swap.rs | 1 + clippy_lints/src/trivially_copy_pass_by_ref.rs | 1 + clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/utils/sugg.rs | 1 + 12 files changed, 11 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 7d4d667da9a..f57a3571b57 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,3 +1,4 @@ +use matches::matches; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index f58a91bc211..d9f50d652d3 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,3 +1,4 @@ +use matches::matches; use rustc::hir::intravisit; use rustc::hir; use rustc::lint::*; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 61eaa7bea6e..1d0382748ee 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,5 +1,6 @@ //! lint when items are used after statements +use matches::matches; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ac52c82b602..6b6df849001 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -18,8 +18,6 @@ use toml; use rustc_plugin; -#[macro_use] -extern crate matches as matches_macro; #[macro_use] extern crate if_chain; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index edd144d8de4..7762c4d1cb5 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,4 +1,5 @@ use crate::reexport::*; +use matches::matches; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use rustc::hir::def::Def; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f878102a52e..30c2941efe4 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,3 +1,4 @@ +use matches::matches; use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c517d4a44ee..34afa1585ac 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,4 +1,5 @@ use crate::reexport::*; +use matches::matches; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 6b961eedeb7..3300c9f23fb 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,3 +1,4 @@ +use matches::matches; use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index d8bf6e567f6..e76cf78f8d1 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,3 +1,4 @@ +use matches::matches; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 57d9ddf3955..8d2b21058cf 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,5 +1,6 @@ use std::cmp; +use matches::matches; use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c38a925efed..1888321827d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,4 +1,5 @@ use crate::reexport::*; +use matches::matches; use rustc::hir; use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index ff9424289c5..c7e1e59f063 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -3,6 +3,7 @@ // currently ignores lifetimes and generics #![allow(use_self)] +use matches::matches; use rustc::hir; use rustc::lint::{EarlyContext, LateContext, LintContext}; use rustc_errors; -- cgit 1.4.1-3-g733a5 From ac77a26b8a03582d072989b6af7889902bd7428a Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 19 Jul 2018 13:44:26 +0200 Subject: Skip useless_attribute lint on allow(unused_imports) on extern crate items with macro_use --- clippy_lints/src/attrs.rs | 44 ++++++++++++++++++++++++++++++------------- tests/ui/useless_attribute.rs | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 5d5e2f964b0..367968cfe65 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -39,22 +39,31 @@ declare_clippy_lint! { } /// **What it does:** Checks for `extern crate` and `use` items annotated with -/// lint attributes +/// lint attributes. +/// +/// This lint whitelists `#[allow(unused_imports)]` and `#[allow(deprecated)]` on +/// `use` items and `#[allow(unused_imports)]` on `extern crate` items with a +/// `#[macro_use]` attribute. /// /// **Why is this bad?** Lint attributes have no effect on crate imports. Most -/// likely a `!` was -/// forgotten +/// likely a `!` was forgotten. /// -/// **Known problems:** Technically one might allow `unused_import` on a `use` -/// item, -/// but it's easier to remove the unused item. +/// **Known problems:** None. /// /// **Example:** /// ```rust +/// // Bad /// #[deny(dead_code)] /// extern crate foo; -/// #[allow(unused_import)] +/// #[forbid(dead_code)] /// use foo::bar; +/// +/// // Ok +/// #[allow(unused_imports)] +/// use foo::baz; +/// #[allow(unused_imports)] +/// #[macro_use] +/// extern crate baz; /// ``` declare_clippy_lint! { pub USELESS_ATTRIBUTE, @@ -154,17 +163,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { check_attrs(cx, item.span, item.name, &item.attrs) } match item.node { - ItemKind::ExternCrate(_) | ItemKind::Use(_, _) => { + ItemKind::ExternCrate(..) | ItemKind::Use(..) => { + let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use"); + for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { match &*attr.name().as_str() { "allow" | "warn" | "deny" | "forbid" => { - // whitelist `unused_imports` and `deprecated` + // whitelist `unused_imports` and `deprecated` for `use` items + // and `unused_imports` for `extern crate` items with `macro_use` for lint in lint_list { - if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { - if let ItemKind::Use(_, _) = item.node { - return; - } + match item.node { + ItemKind::Use(..) => if is_word(lint, "unused_imports") + || is_word(lint, "deprecated") { + return + }, + ItemKind::ExternCrate(..) => if is_word(lint, "unused_imports") + && skip_unused_imports { + return + }, + _ => {}, } } let line_span = last_line_of_span(cx, attr.span); diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 217e886c8be..68c7d2007a6 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -6,6 +6,8 @@ #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] +#[allow(unused_imports)] +#[macro_use] extern crate clippy_lints; // don't lint on unused_import for `use` items -- cgit 1.4.1-3-g733a5 From 988b552337ff779dadb9158ff4b1497f44be31e8 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 19 Jul 2018 14:14:12 +0200 Subject: Remove duplication of the cargo and rls repos from travis --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97f31b18684..c6bd67ae0f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,6 @@ matrix: - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom - env: INTEGRATION=hyperium/hyper - - env: INTEGRATION=rust-lang/cargo - - env: INTEGRATION=rust-lang-nursery/rls script: - | -- cgit 1.4.1-3-g733a5 From 4d2c838a325b2285a4ed41126eb9bad4a9605d37 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Fri, 20 Jul 2018 03:59:07 +0100 Subject: Update to nightly --- clippy_lints/src/missing_doc.rs | 1 + clippy_lints/src/missing_inline.rs | 3 ++- clippy_lints/src/utils/inspector.rs | 1 + clippy_lints/src/utils/mod.rs | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index eb4dfe8ba1c..7ccee73d83d 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -177,6 +177,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ImplItemKind::Const(..) => "an associated constant", hir::ImplItemKind::Method(..) => "a method", hir::ImplItemKind::Type(_) => "an associated type", + hir::ImplItemKind::Existential(_) => "an existential type", }; self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc); } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 0ca1c53d696..20252393f35 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -165,7 +165,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let desc = match impl_item.node { hir::ImplItemKind::Method(..) => "a method", hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(_) => return, + hir::ImplItemKind::Type(_) | + hir::ImplItemKind::Existential(_) => return, }; let def_id = cx.tcx.hir.local_def_id(impl_item.id); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b2b99da3c59..2e0f8431850 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -70,6 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }, hir::ImplItemKind::Method(..) => println!("method"), hir::ImplItemKind::Type(_) => println!("associated type"), + hir::ImplItemKind::Existential(_) => println!("existential type"), } } // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c38a925efed..10a57e147b9 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -982,6 +982,7 @@ pub fn opt_def_id(def: Def) -> Option { Def::AssociatedConst(id) | Def::Macro(id, ..) | Def::Existential(id) | + Def::AssociatedExistential(id) | Def::GlobalAsm(id) => Some(id), Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, -- cgit 1.4.1-3-g733a5 From 5918a3fc1ef4e524055c5810c1a49446c07cbffc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 01:00:54 -0700 Subject: Remove import of if_chain --- clippy_lints/src/assign_ops.rs | 1 + clippy_lints/src/attrs.rs | 1 + clippy_lints/src/bit_mask.rs | 1 + clippy_lints/src/bytecount.rs | 1 + clippy_lints/src/collapsible_if.rs | 1 + clippy_lints/src/default_trait_access.rs | 1 + clippy_lints/src/derive.rs | 1 + clippy_lints/src/drop_forget_ref.rs | 1 + clippy_lints/src/duration_subsec.rs | 1 + clippy_lints/src/entry.rs | 1 + clippy_lints/src/eval_order_dependence.rs | 1 + clippy_lints/src/excessive_precision.rs | 1 + clippy_lints/src/explicit_write.rs | 1 + clippy_lints/src/fallible_impl_from.rs | 1 + clippy_lints/src/format.rs | 1 + clippy_lints/src/infallible_destructuring_match.rs | 1 + clippy_lints/src/invalid_ref.rs | 1 + clippy_lints/src/let_if_seq.rs | 1 + clippy_lints/src/lib.rs | 3 --- clippy_lints/src/literal_representation.rs | 1 + clippy_lints/src/loops.rs | 1 + clippy_lints/src/map_clone.rs | 1 + clippy_lints/src/map_unit_fn.rs | 1 + clippy_lints/src/matches.rs | 1 + clippy_lints/src/methods.rs | 1 + clippy_lints/src/misc.rs | 1 + clippy_lints/src/misc_early.rs | 1 + clippy_lints/src/needless_borrow.rs | 1 + clippy_lints/src/needless_borrowed_ref.rs | 1 + clippy_lints/src/needless_pass_by_value.rs | 1 + clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 1 + clippy_lints/src/neg_multiply.rs | 1 + clippy_lints/src/new_without_default.rs | 1 + clippy_lints/src/ok_if_let.rs | 1 + clippy_lints/src/overflow_check_conditional.rs | 1 + clippy_lints/src/panic_unimplemented.rs | 1 + clippy_lints/src/partialeq_ne_impl.rs | 1 + clippy_lints/src/ptr.rs | 1 + clippy_lints/src/question_mark.rs | 1 + clippy_lints/src/ranges.rs | 1 + clippy_lints/src/reference.rs | 1 + clippy_lints/src/regex.rs | 1 + clippy_lints/src/replace_consts.rs | 1 + clippy_lints/src/returns.rs | 1 + clippy_lints/src/suspicious_trait_impl.rs | 1 + clippy_lints/src/swap.rs | 1 + clippy_lints/src/transmute.rs | 1 + clippy_lints/src/trivially_copy_pass_by_ref.rs | 1 + clippy_lints/src/types.rs | 1 + clippy_lints/src/unwrap.rs | 1 + clippy_lints/src/use_self.rs | 1 + clippy_lints/src/utils/higher.rs | 1 + clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/vec.rs | 1 + clippy_lints/src/write.rs | 1 + clippy_lints/src/zero_div_zero.rs | 1 + 56 files changed, 55 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 5acdf8172e6..c2d0ccd1534 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -4,6 +4,7 @@ use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast; /// **What it does:** Checks for compound assignment operations (`+=` and diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c19f075cea3..9d8b8a7f9e6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -8,6 +8,7 @@ use crate::utils::{ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index e772042f0a6..2e4e60c412a 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast::LitKind; use syntax::codemap::Span; use crate::utils::{span_lint, span_lint_and_then}; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index f27961783e7..f66c376c864 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use syntax::ast::{Name, UintTy}; use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index a2d280e75e3..b7793519602 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -14,6 +14,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast; use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 915386757f0..4078237e8aa 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::TypeVariants; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 02816ce9e4e..0689ef25c20 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 8fb01d79a1e..071afde986a 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use rustc::hir::*; use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 4679ce15871..517befa7790 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::codemap::Spanned; use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 8f731e992ab..26ee6be5796 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -2,6 +2,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::codemap::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 33f6295a23b..b0295d2e7d4 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -3,6 +3,7 @@ use rustc::hir::*; use rustc::ty; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast; use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index a1c4484a2e5..28819077f9b 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::TypeVariants; use std::f32; use std::f64; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 554d52d4499..22e6834ee88 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; use crate::utils::opt_def_id; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index b6136708e18..18c3d807f1a 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir; use rustc::ty; use syntax_pos::Span; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 31ae3eb0fec..668ef3dbf6e 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use syntax::ast::LitKind; use syntax_pos::Span; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 0f1ccddb3c4..8b8cb32deb1 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -2,6 +2,7 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_an use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; /// **What it does:** Checks for matches being used to destructure a single-variant enum /// or tuple struct where a `let` will suffice. diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 8fd097edafd..b529cb3ac38 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use rustc::hir::*; use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index dd8d1d175cc..57ca5eff955 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir; use rustc::hir::BindingAnnotation; use rustc::hir::def::Def; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6b6df849001..1c4c4ef18ff 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -19,9 +19,6 @@ use toml; use rustc_plugin; -#[macro_use] -extern crate if_chain; - macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { declare_lint! { pub $name, Warn, $description } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 2788258a0cd..bb5a923eaf9 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -3,6 +3,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast::*; use syntax_pos; use crate::utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f975df6001e..86580c27cff 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,6 +7,7 @@ use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_st use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::middle::region; // use rustc::middle::region::CodeExtent; use rustc::middle::expr_use_visitor::*; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 40bb2364935..0c427c5ffe4 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use rustc::ty; use syntax::ast; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 99df6a41eef..bd5613d0b48 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; use syntax::codemap::Span; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 82ed199e0cb..65c360922b2 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use std::cmp::Ordering; use std::collections::Bound; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 30c2941efe4..3ebad1d705b 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -2,6 +2,7 @@ use matches::matches; use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::def::Def; use std::borrow::Cow; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 34afa1585ac..a32c95e9672 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -4,6 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use syntax::codemap::{ExpnFormat, Span}; use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index a5ee070d900..5bf7d5f3404 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use std::collections::HashMap; use std::char; use syntax::ast::*; diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 728ca969ac5..7986b43919c 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -4,6 +4,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index ebefcfcca16..1679a9007b4 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -4,6 +4,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use crate::utils::{in_macro, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 3300c9f23fb..7463ea2d9c3 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -4,6 +4,7 @@ use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; use rustc::middle::expr_use_visitor as euv; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index fd2266c8614..70a47674d9f 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use crate::utils::{self, paths, span_lint, in_external_macro}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 0a12217e8d0..96f2e58f3be 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::codemap::{Span, Spanned}; use crate::consts::{self, Constant}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 80c92042687..a2192710292 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -2,6 +2,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use syntax::codemap::Span; use crate::utils::paths; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 6a21807b90b..2a7f71c7145 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 0ae400879da..5714bdb521c 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use crate::utils::{span_lint, SpanlessEq}; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 2edcef5bcda..e8dfca24c57 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast::LitKind; use syntax::ptr::P; use syntax::ext::quote::rt::Span; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index e001bbebd3c..675d014c527 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use crate::utils::{is_automatically_derived, span_lint}; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 5093819db5f..167ce84f803 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -6,6 +6,7 @@ use rustc::hir::map::NodeItem; use rustc::hir::QPath; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 9ede9afebd7..b2d53e124ff 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use rustc::hir::def::Def; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 03bf7be4285..9525ea014a9 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use syntax::ast::RangeLimits; use syntax::codemap::Spanned; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 6baa6174563..27aca6f4bf1 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,6 +1,7 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use crate::utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 114a14bdf96..39b7888dcc6 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -2,6 +2,7 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::codemap::{BytePos, Span}; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 5f5957b0209..b9a4c6ebb19 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir; use rustc::hir::def::Def; use crate::utils::{match_def_path, span_lint_and_sugg}; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 29d50d87fb8..2bfc1e7d107 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use syntax::ast; use syntax::codemap::Span; use syntax::visit::FnKind; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 704ad04325d..bd0f6dc68dc 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index e76cf78f8d1..4278d6d74ac 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -2,6 +2,7 @@ use matches::matches; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty; use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 7abf5fdcc92..aa964e4558f 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::*; use std::borrow::Cow; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8d2b21058cf..b6fd8db5157 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -6,6 +6,7 @@ use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::TypeVariants; use rustc::session::config::Config as SessionConfig; use rustc_target::spec::abi::Abi; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index df14eb15957..2921b502c1f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -4,6 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::layout::LayoutOf; use rustc_typeck::hir_ty_to_ty; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 4f7e9e9c0a1..6cafcaeffe9 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use rustc::hir::intravisit::*; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 3b677379298..2ea4497a0d1 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,5 +1,6 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; use crate::utils::{in_macro, span_lint_and_then}; diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 3f0243a91c0..d63a2dae802 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -3,6 +3,7 @@ #![deny(missing_docs_in_private_items)] +use if_chain::if_chain; use rustc::{hir, ty}; use rustc::lint::LateContext; use syntax::ast; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 1888321827d..64840a39fe1 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,5 +1,6 @@ use crate::reexport::*; use matches::matches; +use if_chain::if_chain; use rustc::hir; use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 68caa5b4494..a58d73f86da 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,6 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::ty::{self, Ty}; use syntax::codemap::Span; use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 5112ad86ff0..0f0bd64cb61 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -2,6 +2,7 @@ use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use std::ops::Deref; use syntax::ast::LitKind; use syntax::ptr; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 0b1b3a41305..7c8af7880ba 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,6 +1,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; +use if_chain::if_chain; use rustc::hir::*; use crate::utils::span_help_and_lint; -- cgit 1.4.1-3-g733a5 From 3c2b54870e5da61d7a30d9d17d5346fe7eda7218 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Jul 2018 01:06:29 -0700 Subject: Remove warning --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1c4c4ef18ff..8ff0e1852c3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -13,7 +13,6 @@ #![feature(macro_at_most_once_rep)] #![feature(rust_2018_preview)] #![warn(rust_2018_idioms)] -#![allow(macro_use_extern_crate)] use toml; use rustc_plugin; -- cgit 1.4.1-3-g733a5 From 2a37a62686e35ca9331dae0bc4efe3ea41d717e8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 20 Jul 2018 00:47:24 -0700 Subject: Update dependencies --- clippy_lints/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 3015dc40685..5c3af20bde8 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -21,8 +21,8 @@ edition = "2018" [dependencies] cargo_metadata = "0.5" itertools = "0.7" -lazy_static = "1.0" -matches = "0.1.2" +lazy_static = "1.0.2" +matches = "0.1.7" quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" semver = "0.9.0" @@ -32,7 +32,7 @@ toml = "0.4" unicode-normalization = "0.1" pulldown-cmark = "0.1" url = "1.7.0" -if_chain = "0.1" +if_chain = "0.1.3" [features] debugging = [] -- cgit 1.4.1-3-g733a5 From 2fa85d86e0cbd5fc0c17d1cbcca2005454b86cd4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Jul 2018 22:50:04 +0200 Subject: Rustup --- clippy_lints/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8ff0e1852c3..119ec0470d3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -20,34 +20,34 @@ use rustc_plugin; macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { - declare_lint! { pub $name, Warn, $description } + declare_lint! { pub $name, Warn, $description, report_in_external_macro } }; { pub $name:tt, correctness, $description:tt } => { - declare_lint! { pub $name, Deny, $description } + declare_lint! { pub $name, Deny, $description, report_in_external_macro } }; { pub $name:tt, complexity, $description:tt } => { - declare_lint! { pub $name, Warn, $description } + declare_lint! { pub $name, Warn, $description, report_in_external_macro } }; { pub $name:tt, perf, $description:tt } => { - declare_lint! { pub $name, Warn, $description } + declare_lint! { pub $name, Warn, $description, report_in_external_macro } }; { pub $name:tt, pedantic, $description:tt } => { - declare_lint! { pub $name, Allow, $description } + declare_lint! { pub $name, Allow, $description, report_in_external_macro } }; { pub $name:tt, restriction, $description:tt } => { - declare_lint! { pub $name, Allow, $description } + declare_lint! { pub $name, Allow, $description, report_in_external_macro } }; { pub $name:tt, cargo, $description:tt } => { - declare_lint! { pub $name, Allow, $description } + declare_lint! { pub $name, Allow, $description, report_in_external_macro } }; { pub $name:tt, nursery, $description:tt } => { - declare_lint! { pub $name, Allow, $description } + declare_lint! { pub $name, Allow, $description, report_in_external_macro } }; { pub $name:tt, internal, $description:tt } => { - declare_lint! { pub $name, Allow, $description } + declare_lint! { pub $name, Allow, $description, report_in_external_macro } }; { pub $name:tt, internal_warn, $description:tt } => { - declare_lint! { pub $name, Warn, $description } + declare_lint! { pub $name, Warn, $description, report_in_external_macro } }; } -- cgit 1.4.1-3-g733a5 From 8085ed733fefeaf37aca0a39da93344326de5d57 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 21 Jul 2018 12:36:01 +0200 Subject: Don't invent new magic keywords --- clippy_lints/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 119ec0470d3..1f31b24b443 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -20,34 +20,34 @@ use rustc_plugin; macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, correctness, $description:tt } => { - declare_lint! { pub $name, Deny, $description, report_in_external_macro } + declare_lint! { pub $name, Deny, $description, report_in_external_macro: true } }; { pub $name:tt, complexity, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, perf, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, pedantic, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, restriction, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, cargo, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, nursery, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, internal, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, internal_warn, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } }; } -- cgit 1.4.1-3-g733a5 From 26eea10ec170a1cb1ab1db38dbc87d8abc88ac58 Mon Sep 17 00:00:00 2001 From: Wim Date: Sat, 21 Jul 2018 18:05:02 +0200 Subject: Add known problem for redundant_closure lint Documenting https://github.com/rust-lang-nursery/rust-clippy/issues/1439 until it gets fixed. --- clippy_lints/src/eta_reduction.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 7b6623ed29b..b11bbfcdc2e 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -15,7 +15,11 @@ pub struct EtaPass; /// **Why is this bad?** Needlessly creating a closure adds code for no benefit /// and gives the optimizer more work. /// -/// **Known problems:** None. +/// **Known problems:** If creating the closure inside the closure has a side- +/// effect then moving the closure creation out will change when that side- +/// effect runs. +/// See https://github.com/rust-lang-nursery/rust-clippy/issues/1439 for more +/// details. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From ff0e5f967fde38242a1f2bf852082d2e105fc29c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 23 Jul 2018 00:19:07 +0200 Subject: Rewrite the print/write macro checks as a PreExpansionPass --- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/write.rs | 434 +++++++++++------------------------ src/driver.rs | 1 + tests/ui/excessive_precision.rs | 2 +- tests/ui/excessive_precision.stderr | 6 +- tests/ui/matches.stderr | 19 +- tests/ui/non_expressive_names.stderr | 22 +- tests/ui/print.stderr | 30 ++- tests/ui/print_literal.stderr | 28 +-- tests/ui/print_with_newline.stderr | 22 +- tests/ui/println_empty_string.stderr | 2 +- tests/ui/write_literal.stderr | 28 +-- tests/ui/write_with_newline.stderr | 8 +- tests/ui/writeln_empty_string.stderr | 2 +- 14 files changed, 251 insertions(+), 359 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1f31b24b443..53a37f23fa4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -16,6 +16,7 @@ use toml; use rustc_plugin; +use rustc; macro_rules! declare_clippy_lint { @@ -175,6 +176,10 @@ mod reexport { crate use syntax::ast::{Name, NodeId}; } +pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore) { + store.register_pre_expansion_pass(Some(session), box write::Pass); +} + #[cfg_attr(rustfmt, rustfmt_skip)] pub fn register_plugins(reg: &mut rustc_plugin::Registry) { let conf = match utils::conf::file_from_args(reg.args()) { @@ -320,7 +325,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box write::Pass); reg.register_late_lint_pass(box vec::Pass); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold: conf.single_char_binding_names_threshold, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0f0bd64cb61..c4b5a9ccefc 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,15 +1,9 @@ -use rustc::hir::map::Node::{NodeImplItem, NodeItem}; -use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use if_chain::if_chain; -use std::ops::Deref; -use syntax::ast::LitKind; -use syntax::ptr; -use syntax::symbol::LocalInternedString; -use syntax_pos::Span; -use crate::utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg}; -use crate::utils::{opt_def_id, paths, last_path_segment}; +use syntax::ast::*; +use syntax::tokenstream::{ThinTokenStream, TokenStream}; +use syntax::parse::{token, parser}; +use crate::utils::{span_lint, span_lint_and_sugg}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -173,317 +167,149 @@ impl LintPass for Pass { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - match expr.node { - // print!() - ExprKind::Call(ref fun, ref args) => { - if_chain! { - if let ExprKind::Path(ref qpath) = fun.node; - if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); - then { - check_print_variants(cx, expr, fun_id, args); - } - } - }, - // write!() - ExprKind::MethodCall(ref fun, _, ref args) => { - if fun.ident.name == "write_fmt" { - check_write_variants(cx, expr, args); - } - }, - _ => (), - } - } -} - -fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, write_args: &ptr::P<[Expr]>) { - // `writeln!` uses `write!`. - if let Some(span) = is_expn_of(expr.span, "write") { - let (span, name) = match is_expn_of(span, "writeln") { - Some(span) => (span, "writeln"), - None => (span, "write"), - }; - - if_chain! { - // ensure we're calling Arguments::new_v1 or Arguments::new_v1_formatted - if write_args.len() == 2; - if let ExprKind::Call(ref args_fun, ref args_args) = write_args[1].node; - if let ExprKind::Path(ref qpath) = args_fun.node; - if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); - if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1) || - match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); - then { - // Check for literals in the write!/writeln! args - check_fmt_args_for_literal(cx, args_args, |span| { - span_lint(cx, WRITE_LITERAL, span, "writing a literal with an empty format string"); - }); - - if_chain! { - if args_args.len() >= 2; - if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node; - if let ExprKind::Match(ref args, _, _) = match_expr.node; - if let ExprKind::Tup(ref args) = args.node; - if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); - then { - match name { - "write" => if has_newline_end(args, fmtstr, fmtlen) { - span_lint(cx, WRITE_WITH_NEWLINE, span, - "using `write!()` with a format string that ends in a \ - newline, consider using `writeln!()` instead"); - }, - "writeln" => if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) { - span_lint_and_sugg( - cx, - WRITE_WITH_NEWLINE, - final_span, - "using `writeln!(v, \"\")`", - "replace it with", - "writeln!(v)".to_string(), - ); - }, - _ => (), - } - } +impl EarlyLintPass for Pass { + fn check_mac(&mut self, cx: &EarlyContext, mac: &Mac) { + if mac.node.path == "println" { + span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`"); + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { + if fmtstr == "" { + span_lint_and_sugg( + cx, + PRINTLN_EMPTY_STRING, + mac.span, + "using `println!(\"\")`", + "replace it with", + "println!()".to_string(), + ); } } - } - } -} - -fn check_print_variants<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr, - fun_id: def_id::DefId, - args: &ptr::P<[Expr]>, -) { - // Search for `std::io::_print(..)` which is unique in a - // `print!` expansion. - if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) { - if let Some(span) = is_expn_of(expr.span, "print") { - // `println!` uses `print!`. - let (span, name) = match is_expn_of(span, "println") { - Some(span) => (span, "println"), - None => (span, "print"), - }; - - span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name)); - if_chain! { - // ensure we're calling Arguments::new_v1 - if args.len() == 1; - if let ExprKind::Call(ref args_fun, ref args_args) = args[0].node; - then { - // Check for literals in the print!/println! args - check_fmt_args_for_literal(cx, args_args, |span| { - span_lint(cx, PRINT_LITERAL, span, "printing a literal with an empty format string"); - }); - - if_chain! { - if let ExprKind::Path(ref qpath) = args_fun.node; - if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)); - if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1); - if args_args.len() == 2; - if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node; - if let ExprKind::Match(ref args, _, _) = match_expr.node; - if let ExprKind::Tup(ref args) = args.node; - if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]); - then { - match name { - "print" => - if has_newline_end(args, fmtstr, fmtlen) { - span_lint(cx, PRINT_WITH_NEWLINE, span, - "using `print!()` with a format string that ends in a \ - newline, consider using `println!()` instead"); - }, - "println" => - if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) { - span_lint_and_sugg( - cx, - PRINT_WITH_NEWLINE, - final_span, - "using `println!(\"\")`", - "replace it with", - "println!()".to_string(), - ); - }, - _ => (), - } - } - } + } else if mac.node.path == "print" { + span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { + if fmtstr.ends_with("\\n") { + span_lint(cx, PRINT_WITH_NEWLINE, mac.span, + "using `print!()` with a format string that ends in a \ + newline, consider using `println!()` instead"); } } - } - } - // Search for something like - // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` - else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { - if let ExprKind::Path(ref qpath) = args[1].node { - if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) - && is_expn_of(expr.span, "panic").is_none() - { - span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); + } else if mac.node.path == "write" { + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) { + if fmtstr.ends_with("\\n") { + span_lint(cx, WRITE_WITH_NEWLINE, mac.span, + "using `write!()` with a format string that ends in a \ + newline, consider using `writeln!()` instead"); } } - } - } -} - -// Check for literals in write!/writeln! and print!/println! args -// ensuring the format string for the literal is `DISPLAY_FMT_METHOD` -// e.g., `writeln!(buf, "... {} ...", "foo")` -// ^ literal in `writeln!` -// e.g., `println!("... {} ...", "foo")` -// ^ literal in `println!` -fn check_fmt_args_for_literal<'a, 'tcx, F>(cx: &LateContext<'a, 'tcx>, args: &HirVec, lint_fn: F) -where - F: Fn(Span), -{ - if_chain! { - if args.len() >= 2; - - // the match statement - if let ExprKind::AddrOf(_, ref match_expr) = args[1].node; - if let ExprKind::Match(ref matchee, ref arms, _) = match_expr.node; - if let ExprKind::Tup(ref tup) = matchee.node; - if arms.len() == 1; - if let ExprKind::Array(ref arm_body_exprs) = arms[0].body.node; - then { - // it doesn't matter how many args there are in the `write!`/`writeln!`, - // if there's one literal, we should warn the user - for (idx, tup_arg) in tup.iter().enumerate() { - if_chain! { - // first, make sure we're dealing with a literal (i.e., an ExprKind::Lit) - if let ExprKind::AddrOf(_, ref tup_val) = tup_arg.node; - if let ExprKind::Lit(_) = tup_val.node; - - // next, check the corresponding match arm body to ensure - // this is DISPLAY_FMT_METHOD - if let ExprKind::Call(_, ref body_args) = arm_body_exprs[idx].node; - if body_args.len() == 2; - if let ExprKind::Path(ref body_qpath) = body_args[1].node; - if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); - then { - if args.len() == 2 { - lint_fn(tup_val.span); - } - - // ensure the format str has no options (e.g., width, precision, alignment, etc.) - // and is just "{}" - if_chain! { - if args.len() == 3; - if let ExprKind::AddrOf(_, ref format_expr) = args[2].node; - if let ExprKind::Array(ref format_exprs) = format_expr.node; - if format_exprs.len() >= 1; - if let ExprKind::Struct(_, ref fields, _) = format_exprs[idx].node; - if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); - if check_unformatted(&format_field.expr); - then { - lint_fn(tup_val.span); - } - } - } + } else if mac.node.path == "writeln" { + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) { + if fmtstr == "" { + span_lint_and_sugg( + cx, + WRITELN_EMPTY_STRING, + mac.span, + "using `writeln!(v, \"\")`", + "replace it with", + "writeln!(v)".to_string(), + ); } } } } } -/// Check for fmtstr = "... \n" -fn has_newline_end(args: &HirVec, fmtstr: LocalInternedString, fmtlen: usize) -> bool { - if_chain! { - // check the final format string part - if let Some('\n') = fmtstr.chars().last(); - - // "foo{}bar" is made into two strings + one argument, - // if the format string starts with `{}` (eg. "{}foo"), - // the string array is prepended an empty string "". - // We only want to check the last string after any `{}`: - if args.len() < fmtlen; - then { - return true - } +fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option { + let tts = TokenStream::from(tts.clone()); + let mut parser = parser::Parser::new( + &cx.sess.parse_sess, + tts, + None, + false, + false, + ); + if is_write { + // skip the initial write target + parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; + // might be `writeln!(foo)` + parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?; } - false -} - -/// Check for writeln!(v, "") / println!("") -fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: LocalInternedString, fmtlen: usize) -> Option { - if_chain! { - // check that the string is empty - if fmtlen == 1; - if fmtstr.deref() == "\n"; - - // check the presence of that string - if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); - if snippet.contains("\"\""); - then { - if snippet.ends_with(';') { - return Some(cx.sess().codemap().span_until_char(span, ';')); - } - return Some(span) + let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string(); + use fmt_macros::*; + let tmp = fmtstr.clone(); + let mut args = vec![]; + let mut fmt_parser = Parser::new(&tmp, None); + while let Some(piece) = fmt_parser.next() { + if !fmt_parser.errors.is_empty() { + return None; } - } - None -} - -/// Returns the slice of format string parts in an `Arguments::new_v1` call. -fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(LocalInternedString, usize)> { - if_chain! { - if let ExprKind::AddrOf(_, ref expr) = expr.node; // &["…", "…", …] - if let ExprKind::Array(ref exprs) = expr.node; - if let Some(expr) = exprs.last(); - if let ExprKind::Lit(ref lit) = expr.node; - if let LitKind::Str(ref lit, _) = lit.node; - then { - return Some((lit.as_str(), exprs.len())); - } - } - None -} - -fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool { - let map = &cx.tcx.hir; - - // `fmt` method - if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { - // `Debug` impl - if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { - if let ItemKind::Impl(_, _, _, _, Some(ref tr), _, _) = item.node { - return match_path(&tr.path, &["Debug"]); + if let Piece::NextArgument(arg) = piece { + if arg.format.ty == "?" { + // FIXME: modify rustc's fmt string parser to give us the current span + span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting"); } + args.push(arg); } } - false -} - -/// Checks if the expression matches -/// ```rust,ignore -/// &[_ { -/// format: _ { -/// width: _::Implied, -/// ... -/// }, -/// ..., -/// }] -/// ``` -pub fn check_unformatted(format_field: &Expr) -> bool { - if_chain! { - if let ExprKind::Struct(_, ref fields, _) = format_field.node; - if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width"); - if let ExprKind::Path(ref qpath) = width_field.expr.node; - if last_path_segment(qpath).ident.name == "Implied"; - if let Some(align_field) = fields.iter().find(|f| f.ident.name == "align"); - if let ExprKind::Path(ref qpath) = align_field.expr.node; - if last_path_segment(qpath).ident.name == "Unknown"; - if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision"); - if let ExprKind::Path(ref qpath_precision) = precision_field.expr.node; - if last_path_segment(qpath_precision).ident.name == "Implied"; - then { - return true; + let lint = if is_write { + WRITE_LITERAL + } else { + PRINT_LITERAL + }; + let mut idx = 0; + loop { + if !parser.eat(&token::Comma) { + assert!(parser.eat(&token::Eof)); + return Some(fmtstr); + } + let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; + const SIMPLE: FormatSpec = FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }; + match &expr.node { + ExprKind::Lit(_) => { + let mut all_simple = true; + let mut seen = false; + for arg in &args { + match arg.position { + | ArgumentImplicitlyIs(n) + | ArgumentIs(n) + => if n == idx { + all_simple &= arg.format == SIMPLE; + seen = true; + }, + ArgumentNamed(_) => {}, + } + } + if all_simple && seen { + span_lint(cx, lint, expr.span, "literal with an empty format string"); + } + idx += 1; + }, + ExprKind::Assign(lhs, rhs) => { + if let ExprKind::Path(_, p) = &lhs.node { + let mut all_simple = true; + let mut seen = false; + for arg in &args { + match arg.position { + | ArgumentImplicitlyIs(_) + | ArgumentIs(_) + => {}, + ArgumentNamed(name) => if *p == name { + seen = true; + all_simple &= arg.format == SIMPLE; + }, + } + } + if all_simple && seen { + span_lint(cx, lint, rhs.span, "literal with an empty format string"); + } + } + }, + _ => idx += 1, } } - - false } diff --git a/src/driver.rs b/src/driver.rs index 585edcd82a6..e9e81bb88e3 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -118,6 +118,7 @@ pub fn main() { for (name, to) in lint_groups { ls.register_group(Some(sess), true, name, to); } + clippy_lints::register_pre_expansion_lints(sess, &mut ls); sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); sess.plugin_attributes.borrow_mut().extend(attributes); diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index c17639aaf04..88f24d27dbc 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -22,7 +22,7 @@ fn main() { const BAD64_3: f64 = 0.100_000_000_000_000_000_1; // Literal as param - println!("{}", 8.888_888_888_888_888_888_888); + println!("{:?}", 8.888_888_888_888_888_888_888); // // TODO add inferred type tests for f32 // Locals diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index a167deac038..295846e9d7e 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -43,10 +43,10 @@ error: float has excessive precision | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:25:20 + --> $DIR/excessive_precision.rs:25:22 | -25 | println!("{}", 8.888_888_888_888_888_888_888); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` +25 | println!("{:?}", 8.888_888_888_888_888_888_888); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision --> $DIR/excessive_precision.rs:36:22 diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index e0afc939b42..6554b6d3449 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -26,6 +26,23 @@ help: instead of prefixing all patterns with `&`, you can dereference the expres 32 | None => println!("none"), | +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/matches.rs:40:5 + | +40 | / match tup { +41 | | &(v, 1) => println!("{}", v), +42 | | _ => println!("none"), +43 | | } + | |_____^ +help: try this + | +40 | if let &(v, 1) = tup { +41 | # [ cfg ( not ( stage0 ) ) ] { +42 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; } # [ +43 | cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( $ ( $ arg ) * ) ) } } else { +44 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; } + | + error: you don't need to add `&` to all patterns --> $DIR/matches.rs:40:5 | @@ -350,5 +367,5 @@ error: use as_mut() instead 221 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 4b95a1a9e70..c63b493db8d 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,3 +1,23 @@ +error: using `println!("")` + --> $DIR/non_expressive_names.rs:60:14 + | +60 | _ => println!(""), + | ^^^^^^^^^^^^ help: replace it with: `println!()` + | + = note: `-D println-empty-string` implied by `-D warnings` + +error: using `println!("")` + --> $DIR/non_expressive_names.rs:128:18 + | +128 | 1 => println!(""), + | ^^^^^^^^^^^^ help: replace it with: `println!()` + +error: using `println!("")` + --> $DIR/non_expressive_names.rs:132:18 + | +132 | 1 => println!(""), + | ^^^^^^^^^^^^ help: replace it with: `println!()` + error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:18:9 | @@ -167,5 +187,5 @@ error: consider choosing a more descriptive name 151 | let __1___2 = 12; | ^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 457ed38a1b5..f2d2afd9bf7 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,16 +1,22 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:13:27 + --> $DIR/print.rs:13:19 | 13 | write!(f, "{:?}", 43.1415) - | ^^^^^^^ + | ^^^^^^ | = note: `-D use-debug` implied by `-D warnings` +error: use of `Debug`-based formatting + --> $DIR/print.rs:20:19 + | +20 | write!(f, "{:?}", 42.718) + | ^^^^^^ + error: use of `println!` --> $DIR/print.rs:25:5 | 25 | println!("Hello"); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = note: `-D print-stdout` implied by `-D warnings` @@ -18,37 +24,37 @@ error: use of `print!` --> $DIR/print.rs:26:5 | 26 | print!("Hello"); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:28:5 | 28 | print!("Hello {}", "World"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:30:5 | 30 | print!("Hello {:?}", "World"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:30:26 + --> $DIR/print.rs:30:12 | 30 | print!("Hello {:?}", "World"); - | ^^^^^^^ + | ^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:32:5 | 32 | print!("Hello {:#?}", "#orld"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:32:27 + --> $DIR/print.rs:32:12 | 32 | print!("Hello {:#?}", "#orld"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index d1e4b49cbdd..39e0387cb5e 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,4 +1,4 @@ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:23:71 | 23 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); @@ -6,79 +6,79 @@ error: printing a literal with an empty format string | = note: `-D print-literal` implied by `-D warnings` -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:24:24 | 24 | print!("Hello {}", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:25:36 | 25 | println!("Hello {} {}", world, "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:26:26 | 26 | println!("Hello {}", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:27:30 | 27 | println!("10 / 4 is {}", 2.5); | ^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:28:28 | 28 | println!("2 + 1 = {}", 3); | ^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:33:25 | 33 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:33:34 | 33 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:34:25 | 34 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:34:34 | 34 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:37:33 | 37 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:37:46 | 37 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:38:33 | 38 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -error: printing a literal with an empty format string +error: literal with an empty format string --> $DIR/print_literal.rs:38:46 | 38 | println!("{bar} {foo}", foo="hello", bar="world"); diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 5f2013e728e..181f16b5cb7 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -2,9 +2,27 @@ error: using `print!()` with a format string that ends in a newline, consider us --> $DIR/print_with_newline.rs:7:5 | 7 | print!("Hello/n"); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = note: `-D print-with-newline` implied by `-D warnings` -error: aborting due to previous error +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:8:5 + | +8 | print!("Hello {}/n", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:9:5 + | +9 | print!("Hello {} {}/n/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead + --> $DIR/print_with_newline.rs:10:5 + | +10 | print!("{}/n", 1265); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 1148a4496a5..cff3f988052 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -4,7 +4,7 @@ error: using `println!("")` 3 | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` | - = note: `-D print-with-newline` implied by `-D warnings` + = note: `-D println-empty-string` implied by `-D warnings` error: using `println!("")` --> $DIR/println_empty_string.rs:6:14 diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 323a83e244a..70855ef8187 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,4 +1,4 @@ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:26:79 | 26 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); @@ -6,79 +6,79 @@ error: writing a literal with an empty format string | = note: `-D write-literal` implied by `-D warnings` -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:27:32 | 27 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:28:44 | 28 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:29:34 | 29 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:30:38 | 30 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:31:36 | 31 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:36:33 | 36 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:36:42 | 36 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:37:33 | 37 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:37:42 | 37 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:40:41 | 40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:40:54 | 40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:41:41 | 41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -error: writing a literal with an empty format string +error: literal with an empty format string --> $DIR/write_literal.rs:41:54 | 41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 37f03afb016..7bb9b99731f 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -2,7 +2,7 @@ error: using `write!()` with a format string that ends in a newline, consider us --> $DIR/write_with_newline.rs:10:5 | 10 | write!(&mut v, "Hello/n"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D write-with-newline` implied by `-D warnings` @@ -10,19 +10,19 @@ error: using `write!()` with a format string that ends in a newline, consider us --> $DIR/write_with_newline.rs:11:5 | 11 | write!(&mut v, "Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:12:5 | 12 | write!(&mut v, "Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:13:5 | 13 | write!(&mut v, "{}/n", 1265); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index b4649384865..16a8e0a203d 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -4,7 +4,7 @@ error: using `writeln!(v, "")` 9 | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` | - = note: `-D write-with-newline` implied by `-D warnings` + = note: `-D writeln-empty-string` implied by `-D warnings` error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 58459abd0cbc998c6c3544ec43b94d4371d8782d Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Mon, 23 Jul 2018 18:33:47 +1000 Subject: Allow pass by reference if we return a reference Currently this code will trigger `trivally_copy_pass_by_ref`: ``` struct OuterStruct { field: [u8; 8], } fn return_inner(outer: &OuterStruct) -> &[u8] { &outer.field } ``` If we change the `outer` to be pass-by-value it will not live long enough for us to return the reference. The above example is trivial but I've hit this in real code that either returns a reference to either the argument or in to `self`. This suppresses the `trivally_copy_pass_by_ref` lint if we return a reference and it has the same lifetime as the argument. This will likely miss complex cases with multiple lifetimes bounded by each other but it should cover the majority of cases with little effort. --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 11 +++++- tests/ui/trivially_copy_pass_by_ref.rs | 11 ++++++ tests/ui/trivially_copy_pass_by_ref.stderr | 52 +++++++++++++------------- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index b6fd8db5157..e0eb464596b 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -115,6 +115,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); + // Use lifetimes to determine if we're returning a reference to the argument. In that case + // we can't switch to pass-by-value as the argument will not live long enough. + let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty { + Some(output_lt) + } else { + None + }; + for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { // All spans generated from a proc-macro invocation are the same... if span == input.span { @@ -122,7 +130,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } if_chain! { - if let TypeVariants::TyRef(_, ty, Mutability::MutImmutable) = ty.sty; + if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty; + if Some(input_lt) != output_lt; if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.limit; diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index aba4aa5ea32..c6773add244 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -11,6 +11,15 @@ type Baz = u32; fn good(a: &mut u32, b: u32, c: &Bar) { } +fn good_return_implicit_lt_ref(foo: &Foo) -> &u32 { + &foo.0 +} + +#[allow(needless_lifetimes)] +fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { + &foo.0 +} + fn bad(x: &u32, y: &Foo, z: &Baz) { } @@ -46,6 +55,8 @@ fn main() { let (mut foo, bar) = (Foo(0), Bar([0; 24])); let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0); good(&mut a, b, &c); + good_return_implicit_lt_ref(&y); + good_return_explicit_lt_ref(&y); bad(&x, &y, &z); foo.good(&mut a, b, &c); foo.good2(); diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index c6ab968a7c5..db25cc5a020 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:14:11 + --> $DIR/trivially_copy_pass_by_ref.rs:23:11 | -14 | fn bad(x: &u32, y: &Foo, z: &Baz) { +23 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:14:20 + --> $DIR/trivially_copy_pass_by_ref.rs:23:20 | -14 | fn bad(x: &u32, y: &Foo, z: &Baz) { +23 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:14:29 + --> $DIR/trivially_copy_pass_by_ref.rs:23:29 | -14 | fn bad(x: &u32, y: &Foo, z: &Baz) { +23 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:24:12 + --> $DIR/trivially_copy_pass_by_ref.rs:33:12 | -24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:24:22 + --> $DIR/trivially_copy_pass_by_ref.rs:33:22 | -24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:24:31 + --> $DIR/trivially_copy_pass_by_ref.rs:33:31 | -24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:24:40 + --> $DIR/trivially_copy_pass_by_ref.rs:33:40 | -24 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:27:16 + --> $DIR/trivially_copy_pass_by_ref.rs:36:16 | -27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:27:25 + --> $DIR/trivially_copy_pass_by_ref.rs:36:25 | -27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:27:34 + --> $DIR/trivially_copy_pass_by_ref.rs:36:34 | -27 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:41:16 + --> $DIR/trivially_copy_pass_by_ref.rs:50:16 | -41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:41:25 + --> $DIR/trivially_copy_pass_by_ref.rs:50:25 | -41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:41:34 + --> $DIR/trivially_copy_pass_by_ref.rs:50:34 | -41 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 89a4558056914dc5e4e709a18039e843c8b5e566 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Mon, 23 Jul 2018 19:33:52 +1000 Subject: Add Known Problem for multiple lifetimes --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index e0eb464596b..d27f4f061cb 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -31,6 +31,12 @@ use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet}; /// The configuration option `trivial_copy_size_limit` can be set to override /// this limit for a project. /// +/// This lint attempts to allow passing arguments by reference if a reference +/// to that argument is returned. This is implemented by comparing the lifetime +/// of the argument and return value for equality. However, this can cause +/// false positives in cases involving multiple lifetimes that are bounded by +/// each other. +/// /// **Example:** /// ```rust /// fn foo(v: &u32) { -- cgit 1.4.1-3-g733a5 From 7c74c3e5080dd6312e552b77dc0e667140ee4897 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Mon, 23 Jul 2018 19:37:41 +1000 Subject: Wrap comment at 80 columns --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index d27f4f061cb..6a048b19213 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -121,8 +121,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); - // Use lifetimes to determine if we're returning a reference to the argument. In that case - // we can't switch to pass-by-value as the argument will not live long enough. + // Use lifetimes to determine if we're returning a reference to the + // argument. In that case we can't switch to pass-by-value as the + // argument will not live long enough. let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty { Some(output_lt) } else { -- cgit 1.4.1-3-g733a5 From afd91248eda02cf2968e4e02c77b6c10ecd3fd4f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 23 Jul 2018 13:01:12 +0200 Subject: Rustup --- clippy_lints/src/approx_const.rs | 4 +- clippy_lints/src/attrs.rs | 16 +++--- clippy_lints/src/bit_mask.rs | 10 ++-- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/collapsible_if.rs | 8 +-- clippy_lints/src/const_static_lifetime.rs | 4 +- clippy_lints/src/consts.rs | 6 +-- clippy_lints/src/copies.rs | 6 +-- clippy_lints/src/cyclomatic_complexity.rs | 4 +- clippy_lints/src/doc.rs | 12 ++--- clippy_lints/src/double_parens.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 6 +-- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 4 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 4 +- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/formatting.rs | 12 ++--- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infinite_iter.rs | 4 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 8 +-- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 20 ++++---- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/literal_representation.rs | 10 ++-- clippy_lints/src/loops.rs | 28 +++++----- clippy_lints/src/map_clone.rs | 6 +-- clippy_lints/src/map_unit_fn.rs | 14 ++--- clippy_lints/src/matches.rs | 16 +++--- clippy_lints/src/methods.rs | 76 ++++++++++++++-------------- clippy_lints/src/minmax.rs | 4 +- clippy_lints/src/misc.rs | 12 ++--- clippy_lints/src/misc_early.rs | 12 ++--- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_continue.rs | 10 ++-- clippy_lints/src/needless_pass_by_value.rs | 4 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/no_effect.rs | 4 +- clippy_lints/src/non_expressive_names.rs | 6 +-- clippy_lints/src/open_options.rs | 4 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/precedence.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/question_mark.rs | 6 +-- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/reference.rs | 4 +- clippy_lints/src/returns.rs | 12 ++--- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/strings.rs | 4 +- clippy_lints/src/suspicious_trait_impl.rs | 2 +- clippy_lints/src/swap.rs | 6 +-- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/types.rs | 44 ++++++++-------- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 6 +-- clippy_lints/src/unused_io_amount.rs | 4 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/inspector.rs | 8 +-- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 54 ++++++++++---------- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 18 +++---- clippy_lints/src/utils/usage.rs | 4 +- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/write.rs | 4 +- src/lib.rs | 2 +- 81 files changed, 292 insertions(+), 292 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index b9de43762e0..cd2444ff31f 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { +fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) { match lit.node { LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), @@ -79,7 +79,7 @@ fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) { } } -fn check_known_consts(cx: &LateContext, e: &Expr, s: symbol::Symbol, module: &str) { +fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) { let s = s.as_str(); if s.parse::().is_ok() { for &(constant, name, min_digits) in KNOWN_CONSTS { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 6d4d333a8cb..3d25f524afd 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -226,7 +226,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } -fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { +fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool { if let ItemKind::Fn(_, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) } else { @@ -234,14 +234,14 @@ fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { } } -fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool { +fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool { match item.node { ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value), _ => false, } } -fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool { +fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool { match item.node { TraitItemKind::Method(_, TraitMethod::Required(_)) => true, TraitItemKind::Method(_, TraitMethod::Provided(eid)) => { @@ -251,7 +251,7 @@ fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool { } } -fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool { +fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { match stmt.node { StmtKind::Decl(_, _) => true, @@ -262,7 +262,7 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b } } -fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool { +fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool { match expr.node { ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block), ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e), @@ -280,7 +280,7 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool } } -fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attribute]) { if in_macro(span) { return; } @@ -331,7 +331,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) { } } -fn check_semver(cx: &LateContext, span: Span, lit: &Lit) { +fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) { if let LitKind::Str(ref is, _) = lit.node { if Version::parse(&is.as_str()).is_ok() { return; @@ -358,7 +358,7 @@ fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { // sources that the user has no control over. // For some reason these attributes don't have any expansion info on them, so // we have to check it this way until there is a better way. -fn is_present_in_source(cx: &LateContext, span: Span) -> bool { +fn is_present_in_source(cx: &LateContext<'_, '_>, span: Span) -> bool { if let Some(snippet) = snippet_opt(cx, span) { if snippet.is_empty() { return false; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 2e4e60c412a..249ebbde2f7 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -158,7 +158,7 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } -fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) { +fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node { if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { return; @@ -169,7 +169,7 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: } } -fn check_bit_mask(cx: &LateContext, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) { +fn check_bit_mask(cx: &LateContext<'_, '_>, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) { match cmp_op { BinOpKind::Eq | BinOpKind::Ne => match bit_op { BinOpKind::BitAnd => if mask_value & cmp_value != cmp_value { @@ -270,7 +270,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOpKind, cmp_op: BinOpKind, mask_v } } -fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { +fn check_ineffective_lt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) { if c.is_power_of_two() && m < c { span_lint( cx, @@ -286,7 +286,7 @@ fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str } } -fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { +fn check_ineffective_gt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) { if (c + 1).is_power_of_two() && m <= c { span_lint( cx, @@ -302,7 +302,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str } } -fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { +fn fetch_int_literal(cx: &LateContext<'_, '_>, lit: &Expr) -> Option { match constant(cx, cx.tables, lit)?.0 { Constant::Int(n) => Some(n), _ => None, diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 7d627f49836..f1596476bfd 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } // The boolean part of the return indicates whether some simplifications have been applied. -fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { +fn suggest(cx: &LateContext<'_, '_>, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) { let mut suggest_context = SuggestContext { terminals, cx, diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index f66c376c864..2d4279d3cc1 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -38,7 +38,7 @@ impl LintPass for ByteCount { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { - fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) { if_chain! { if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node; if count.ident.name == "count"; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index b7793519602..2771006aad3 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -80,14 +80,14 @@ impl LintPass for CollapsibleIf { } impl EarlyLintPass for CollapsibleIf { - fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { if !in_macro(expr.span) { check_if(cx, expr) } } } -fn check_if(cx: &EarlyContext, expr: &ast::Expr) { +fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { match expr.node { ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ { check_collapsible_maybe_if_let(cx, else_); @@ -101,7 +101,7 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) { } } -fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { +fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { if_chain! { if let ast::ExprKind::Block(ref block, _) = else_.node; if let Some(else_) = expr_block(block); @@ -122,7 +122,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { } } -fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { +fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { if_chain! { if let Some(inner) = expr_block(then); if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node; diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 8bb209a6490..1af0741d67f 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -35,7 +35,7 @@ impl LintPass for StaticConst { impl StaticConst { // Recursively visit types - fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext) { + fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>) { match ty.node { // Be careful of nested structures (arrays and tuples) TyKind::Array(ref ty, _) => { @@ -79,7 +79,7 @@ impl StaticConst { } impl EarlyLintPass for StaticConst { - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if !in_macro(item.span) { // Match only constants... if let ItemKind::Const(ref var_type, _) = item.node { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 878ad276343..84167553a54 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -123,7 +123,7 @@ impl Hash for Constant { } impl Constant { - pub fn partial_cmp(tcx: TyCtxt, cmp_type: &ty::TypeVariants, left: &Self, right: &Self) -> Option { + pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TypeVariants<'_>, left: &Self, right: &Self) -> Option { match (left, right) { (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), @@ -236,7 +236,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } - fn constant_not(&self, o: &Constant, ty: ty::Ty) -> Option { + fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option { use self::Constant::*; match *o { Bool(b) => Some(Bool(!b)), @@ -252,7 +252,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } - fn constant_negate(&self, o: &Constant, ty: ty::Ty) -> Option { + fn constant_negate(&self, o: &Constant, ty: ty::Ty<'_>) -> Option { use self::Constant::*; match *o { Int(value) => { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index c0830c5ea31..5709526c600 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -134,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { } /// Implementation of `IF_SAME_THEN_ELSE`. -fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { +fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block]) { let eq: &dyn Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; if let Some((i, j)) = search_same_sequenced(blocks, eq) { @@ -150,7 +150,7 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { } /// Implementation of `IFS_SAME_COND`. -fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { +fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) { let hash: &dyn Fn(&&Expr) -> u64 = &|expr| -> u64 { let mut h = SpanlessHash::new(cx, cx.tables); h.hash_expr(expr); @@ -172,7 +172,7 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) { } /// Implementation of `MATCH_SAME_ARMS`. -fn lint_match_arms(cx: &LateContext, expr: &Expr) { +fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.node { let hash = |&(_, arm): &(usize, &Arm)| -> u64 { let mut h = SpanlessHash::new(cx, cx.tables); diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index c397ca7824e..d66e6f2849b 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -187,7 +187,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { #[cfg(feature = "debugging")] #[allow(too_many_arguments)] -fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) { +fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) { span_bug!( span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ @@ -201,7 +201,7 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, re } #[cfg(not(feature = "debugging"))] #[allow(too_many_arguments)] -fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) { +fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) { if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) { cx.sess().span_note_without_error( span, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index a298137976b..2b11e8fa77d 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -52,11 +52,11 @@ impl LintPass for Doc { } impl EarlyLintPass for Doc { - fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { check_attrs(cx, &self.valid_idents, &krate.attrs); } - fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { check_attrs(cx, &self.valid_idents, &item.attrs); } } @@ -139,7 +139,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( panic!("not a doc-comment: {}", comment); } -pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) { +pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'a [ast::Attribute]) { let mut doc = String::new(); let mut spans = vec![]; @@ -186,7 +186,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a } fn check_doc<'a, Events: Iterator)>>( - cx: &EarlyContext, + cx: &EarlyContext<'_>, valid_idents: &[String], docs: Events, spans: &[(usize, Span)], @@ -232,7 +232,7 @@ fn check_doc<'a, Events: Iterator)>>( } } -fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span) { +fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) { for word in text.split_whitespace() { // Trim punctuation as in `some comment (see foo::bar).` // ^^ @@ -255,7 +255,7 @@ fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span } } -fn check_word(cx: &EarlyContext, word: &str, span: Span) { +fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) { /// Checks if a string is camel-case, ie. contains at least two uppercase /// letter (`Clippy` is /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 2617eab0aa7..abd5666385d 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -31,7 +31,7 @@ impl LintPass for DoubleParens { } impl EarlyLintPass for DoubleParens { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { match expr.node { ExprKind::Paren(ref in_paren) => match in_paren.node { ExprKind::Paren(_) | ExprKind::Tup(_) => { diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index b8406904821..d3560434a31 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -49,7 +49,7 @@ impl LintPass for ElseIfWithoutElse { } impl EarlyLintPass for ElseIfWithoutElse { - fn check_expr(&mut self, cx: &EarlyContext, mut item: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) { if in_external_macro(cx, item.span) { return; } diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 803ba34a865..f95ae32d561 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -33,7 +33,7 @@ impl LintPass for EmptyEnum { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { - fn check_item(&mut self, cx: &LateContext, item: &Item) { + fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { let did = cx.tcx.hir.local_def_id(item.id); if let ItemKind::Enum(..) = item.node { let ty = cx.tcx.type_of(did); diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 10cf497725c..6f8afc710de 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { } impl EnumGlobUse { - fn lint_item(&self, cx: &LateContext, item: &Item) { + fn lint_item(&self, cx: &LateContext<'_, '_>, item: &Item) { if item.vis.node.is_pub() { return; // re-exports are fine } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 6a14638057a..16c9212e5db 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -149,7 +149,7 @@ fn partial_rmatch(post: &str, name: &str) -> usize { // FIXME: #600 #[allow(while_let_on_iterator)] fn check_variant( - cx: &EarlyContext, + cx: &EarlyContext<'_>, threshold: u64, def: &EnumDef, item_name: &str, @@ -240,12 +240,12 @@ fn to_camel_case(item_name: &str) -> String { } impl EarlyLintPass for EnumVariantNames { - fn check_item_post(&mut self, _cx: &EarlyContext, _item: &Item) { + fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) { let last = self.modules.pop(); assert!(last.is_some()); } - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { let item_name = item.ident.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 102769a375e..4960a48b3c8 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { } } -fn check(cx: &LateContext, e: &Expr, span: Span) { +fn check(cx: &LateContext<'_, '_>, e: &Expr, span: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { if v == 0 { span_lint( diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index ff5c85b6009..ebbc2c34811 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -39,7 +39,7 @@ declare_clippy_lint! { "using `Box` where unnecessary" } -fn is_non_trait_box(ty: Ty) -> bool { +fn is_non_trait_box(ty: Ty<'_>) -> bool { ty.is_box() && !ty.boxed_ty().is_trait() } @@ -137,7 +137,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } } - fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { + fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { match loan_cause { // x.foo() diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 7b6623ed29b..2071628a6cf 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { } } -fn check_closure(cx: &LateContext, expr: &Expr) { +fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node { let body = cx.tcx.hir.body(eid); let ex = &body.value; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index b0295d2e7d4..7ccf8c31569 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { /// logical operators are considered to have a defined evaluation order. /// /// When such a read is found, the lint is triggered. -fn check_for_unsequenced_reads(vis: &mut ReadVisitor) { +fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { let map = &vis.cx.tcx.hir; let mut cur_id = vis.write_expr.id; loop { @@ -348,7 +348,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { } /// Returns true if `expr` is the LHS of an assignment, like `expr = ...`. -fn is_in_assignment_position(cx: &LateContext, expr: &Expr) -> bool { +fn is_in_assignment_position(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { if let ExprKind::Assign(ref lhs, _) = parent.node { return lhs.id == expr.id; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 18c3d807f1a..3db644911d7 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -128,7 +128,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it } } -fn match_type(tcx: ty::TyCtxt, ty: ty::Ty, path: &[&str]) -> bool { +fn match_type(tcx: ty::TyCtxt<'_, '_, '_>, ty: ty::Ty<'_>, path: &[&str]) -> bool { match ty.sty { ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path), _ => false, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 668ef3dbf6e..80fc4c3acfe 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -105,7 +105,7 @@ fn check_single_piece(expr: &Expr) -> bool { /// ``` /// and that type of `__arg0` is `&str` or `String` /// then returns the span of first element of the matched tuple -fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option { +fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { if_chain! { if let ExprKind::AddrOf(_, ref expr) = expr.node; if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 784461c23ee..60001c792c0 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -83,7 +83,7 @@ impl LintPass for Formatting { } impl EarlyLintPass for Formatting { - fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { for w in block.stmts.windows(2) { match (&w[0].node, &w[1].node) { (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) | @@ -95,7 +95,7 @@ impl EarlyLintPass for Formatting { } } - fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { check_assign(cx, expr); check_else_if(cx, expr); check_array(cx, expr); @@ -103,7 +103,7 @@ impl EarlyLintPass for Formatting { } /// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint. -fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { +fn check_assign(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node { if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(lhs.span) { let eq_span = lhs.span.between(rhs.span); @@ -132,7 +132,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { } /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`. -fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { +fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) { // this will be a span from the closing ‘}’ of the “then” block (excluding) to @@ -164,7 +164,7 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { } /// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array -fn check_array(cx: &EarlyContext, expr: &ast::Expr) { +fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let ast::ExprKind::Array(ref array) = expr.node { for element in array { if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node { @@ -190,7 +190,7 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) { } /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. -fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) { +fn check_consecutive_ifs(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) { if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() && unsugar_if(second).is_some() { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index d9f50d652d3..8903766c330 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } impl<'a, 'tcx> Functions { - fn check_arg_number(self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { + fn check_arg_number(self, cx: &LateContext<'_, '_>, decl: &hir::FnDecl, span: Span) { let args = decl.inputs.len() as u64; if args > self.threshold { span_lint( diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 3a8a366890a..23b34362171 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } #[allow(cast_possible_wrap)] -fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { +fn check(cx: &LateContext<'_, '_>, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { let check = match cx.tables.expr_ty(e).sty { ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity), diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index eea83ca6b88..915bc28f751 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -47,7 +47,7 @@ impl LintPass for IfNotElse { } impl EarlyLintPass for IfNotElse { - fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { if in_external_macro(cx, item.span) { return; } diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index aaea60f2c05..677f59d32cc 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { /// the range. fn to_const_range<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - range: Range, + range: Range<'_>, array_size: u128, ) -> Option<(u128, u128)> { let s = range diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 3f461a07ab2..eaa93cb62f8 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -140,7 +140,7 @@ static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[ ("scan", 3, First, MaybeInfinite), ]; -fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { +fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { match expr.node { ExprKind::MethodCall(ref method, _, ref args) => { for &(name, len, heuristic, cap) in HEURISTICS.iter() { @@ -204,7 +204,7 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[ ("product", 1), ]; -fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { +fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { match expr.node { ExprKind::MethodCall(ref method, _, ref args) => { for &(name, len) in COMPLETING_METHODS.iter() { diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index b308e3ca81f..70f88a76f45 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn check_attrs(cx: &LateContext, name: Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) { for attr in attrs { if attr.name() != "inline" { continue; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 490d06f259f..9b6fc579a31 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -61,7 +61,7 @@ impl IntPlusOne { false } - fn check_binop(&self, cx: &EarlyContext, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { + fn check_binop(&self, cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { @@ -127,7 +127,7 @@ impl IntPlusOne { fn generate_recommendation( &self, - cx: &EarlyContext, + cx: &EarlyContext<'_>, binop: BinOpKind, node: &Expr, other_side: &Expr, @@ -150,7 +150,7 @@ impl IntPlusOne { None } - fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: String) { + fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation); }); @@ -158,7 +158,7 @@ impl IntPlusOne { } impl EarlyLintPass for IntPlusOne { - fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node { if let Some(ref rec) = self.check_binop(cx, kind.node, lhs, rhs) { self.emit_warning(cx, item, rec.clone()); diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 1d0382748ee..07ef086d694 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -43,7 +43,7 @@ impl LintPass for ItemsAfterStatements { } impl EarlyLintPass for ItemsAfterStatements { - fn check_block(&mut self, cx: &EarlyContext, item: &Block) { + fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) { if in_macro(item.span) { return; } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index f29e5040354..2c03b6b5f68 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -48,7 +48,7 @@ impl LintPass for LargeEnumVariant { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { - fn check_item(&mut self, cx: &LateContext, item: &Item) { + fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { let did = cx.tcx.hir.local_def_id(item.id); if let ItemKind::Enum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index e3ff60d30a2..b73f912fad5 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -106,8 +106,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } } -fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) { - fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { +fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) { + fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool { item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { let did = cx.tcx.hir.local_def_id(item.id.node_id); @@ -119,7 +119,7 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai } // fill the set with current and super traits - fn fill_trait_set(traitt: DefId, set: &mut HashSet, cx: &LateContext) { + fn fill_trait_set(traitt: DefId, set: &mut HashSet, cx: &LateContext<'_, '_>) { if set.insert(traitt) { for supertrait in ::rustc::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); @@ -154,8 +154,8 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai } } -fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { - fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool { +fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) { + fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool { item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { let did = cx.tcx.hir.local_def_id(item.id.node_id); @@ -194,7 +194,7 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { } } -fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) { +fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) { if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { @@ -207,7 +207,7 @@ fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, } } -fn check_len(cx: &LateContext, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) { +fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) { if let Spanned { node: LitKind::Int(lit, _), .. @@ -232,9 +232,9 @@ fn check_len(cx: &LateContext, span: Span, method_name: Name, args: &[Expr], lit } /// Check if this type has an `is_empty` method. -fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { +fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { /// Get an `AssociatedItem` and return true if it matches `is_empty(self)`. - fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool { + fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool { if let ty::AssociatedKind::Method = item.kind { if item.ident.name == "is_empty" { let sig = cx.tcx.fn_sig(item.def_id); @@ -249,7 +249,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { } /// Check the inherent impl's items for an `is_empty(self)` method. - fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { + fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool { cx.tcx.inherent_impls(id).iter().any(|imp| { cx.tcx .associated_items(*imp) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 53a37f23fa4..b08449d2beb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -181,7 +181,7 @@ pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &m } #[cfg_attr(rustfmt, rustfmt_skip)] -pub fn register_plugins(reg: &mut rustc_plugin::Registry) { +pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { let conf = match utils::conf::file_from_args(reg.args()) { Ok(file_name) => { // if the user specified a file, it must exist, otherwise default to `clippy.toml` but diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index bb5a923eaf9..383bba2d4bd 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -229,7 +229,7 @@ enum WarningType { } impl WarningType { - crate fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: syntax_pos::Span) { + crate fn display(&self, grouping_hint: &str, cx: &EarlyContext<'_>, span: syntax_pos::Span) { match self { WarningType::UnreadableLiteral => span_lint_and_sugg( cx, @@ -281,7 +281,7 @@ impl LintPass for LiteralDigitGrouping { } impl EarlyLintPass for LiteralDigitGrouping { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } @@ -293,7 +293,7 @@ impl EarlyLintPass for LiteralDigitGrouping { } impl LiteralDigitGrouping { - fn check_lit(self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { match lit.node { LitKind::Int(..) => { // Lint integral literals. @@ -421,7 +421,7 @@ impl LintPass for LiteralRepresentation { } impl EarlyLintPass for LiteralRepresentation { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } @@ -438,7 +438,7 @@ impl LiteralRepresentation { threshold, } } - fn check_lit(self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { // Lint integral literals. if_chain! { if let LitKind::Int(..) = lit.node; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 86580c27cff..23830c566df 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -743,7 +743,7 @@ struct FixedOffsetVar { offset: Offset, } -fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { +fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { let is_slice = match ty.sty { ty::TyRef(_, subty, _) => is_slice_like(cx, subty), ty::TySlice(..) | ty::TyArray(..) => true, @@ -1185,7 +1185,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx } } -fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &str) { +fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) { let object = snippet(cx, args[0].span, "_"); let muta = if method_name == "iter_mut" { "mut " @@ -1203,7 +1203,7 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s ) } -fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { +fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Expr) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used if let ExprKind::MethodCall(ref method, _, ref args) = arg.node { // just the receiver, no arguments @@ -1258,7 +1258,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { } /// Check for `for` loops over `Option`s and `Results` -fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { +fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) { let ty = cx.tables.expr_ty(arg); if match_type(cx, ty, &paths::OPTION) { span_help_and_lint( @@ -1420,7 +1420,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate { fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { if let Categorization::Local(id) = cmt.cat { if Some(id) == self.node_id_low { @@ -1453,7 +1453,7 @@ impl<'tcx> MutatePairDelegate { } } -fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { +fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr, body: &Expr) { if let Some(higher::Range { start: Some(start), end: Some(end), @@ -1472,7 +1472,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) { } } -fn mut_warn_with_span(cx: &LateContext, span: Option) { +fn mut_warn_with_span(cx: &LateContext<'_, '_>, span: Option) { if let Some(sp) = span { span_lint( cx, @@ -1483,7 +1483,7 @@ fn mut_warn_with_span(cx: &LateContext, span: Option) { } } -fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { +fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option { if_chain! { if let ExprKind::Path(ref qpath) = bound.node; if let QPath::Resolved(None, _) = *qpath; @@ -1505,7 +1505,7 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option { None } -fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { +fn check_for_mutation(cx: &LateContext<'_, '_>, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { let mut delegate = MutatePairDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], @@ -1782,7 +1782,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> { /// Return true if the type of expr is one that provides `IntoIterator` impls /// for `&T` and `&mut T`, such as `Vec`. #[cfg_attr(rustfmt, rustfmt_skip)] -fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { +fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tables.expr_ty(e); @@ -1797,7 +1797,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { match_type(cx, ty, &paths::BTREESET) } -fn is_iterable_array(ty: Ty, cx: &LateContext) -> bool { +fn is_iterable_array(ty: Ty<'_>, cx: &LateContext<'_, '_>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { ty::TyArray(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")), @@ -2006,7 +2006,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { } } -fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { +fn var_def_id(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { if let ExprKind::Path(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.hir_id); if let Def::Local(node_id) = path_res { @@ -2030,7 +2030,7 @@ fn is_conditional(expr: &Expr) -> bool { } } -fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool { +fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr, iter_expr: &Expr) -> bool { if_chain! { if let Some(loop_block) = get_enclosing_block(cx, match_expr.id); if let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)); @@ -2041,7 +2041,7 @@ fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool { false } -fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool { +fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr, iter_expr: &Expr) -> bool { let mut id = loop_expr.id; let iter_name = if let Some(name) = path_name(iter_expr) { name diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 0c427c5ffe4..d8b14db605f 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn expr_eq_name(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { +fn expr_eq_name(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprKind::Path(QPath::Resolved(None, ref path)) => { let arg_segment = [ @@ -116,7 +116,7 @@ fn expr_eq_name(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { } } -fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> { +fn get_type_name(cx: &LateContext<'_, '_>, expr: &Expr, arg: &Expr) -> Option<&'static str> { if match_trait_method(cx, expr, &paths::ITERATOR) { Some("iterator") } else if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(arg)), &paths::OPTION) { @@ -126,7 +126,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s } } -fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool { +fn only_derefs(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { match expr.node { ExprKind::Unary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), _ => expr_eq_name(cx, expr, id), diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index bd5613d0b48..6ccf8daa71d 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -84,7 +84,7 @@ impl LintPass for Pass { } } -fn is_unit_type(ty: ty::Ty) -> bool { +fn is_unit_type(ty: ty::Ty<'_>) -> bool { match ty.sty { ty::TyTuple(slice) => slice.is_empty(), ty::TyNever => true, @@ -92,7 +92,7 @@ fn is_unit_type(ty: ty::Ty) -> bool { } } -fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool { +fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool { let ty = cx.tables.expr_ty(expr); if let ty::TyFnDef(id, _) = ty.sty { @@ -103,7 +103,7 @@ fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool { false } -fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool { +fn is_unit_expression(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool { is_unit_type(cx.tables.expr_ty(expr)) } @@ -111,7 +111,7 @@ fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool { /// semicolons, which causes problems when generating a suggestion. Given an /// expression that evaluates to '()' or '!', recursively remove useless braces /// and semi-colons until is suitable for including in the suggestion template -fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option { +fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> Option { if !is_unit_expression(cx, expr) { return None; } @@ -175,7 +175,7 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op /// `y` => `_y` /// /// Anything else will return `_`. -fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String { +fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr) -> String { match &var_arg.node { hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")), @@ -191,7 +191,7 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { ) } -fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { +fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { let var_arg = &map_args[0]; let fn_arg = &map_args[1]; @@ -244,7 +244,7 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt) { if in_macro(stmt.span) { return; } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 65c360922b2..10d4d94cb91 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -200,7 +200,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { } #[cfg_attr(rustfmt, rustfmt_skip)] -fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { +fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() { @@ -222,13 +222,13 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } -fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { +fn check_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { if is_wild(&arms[1].pats[0]) { report_single_match_single_pattern(cx, ex, arms, expr, els); } } -fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { +fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { @@ -252,7 +252,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], ); } -fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty, els: Option<&Expr>) { +fn check_single_match_opt_like(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty<'_>, els: Option<&Expr>) { // list of candidate Enums we know will never get any more members let candidates = &[ (&paths::COW, "Borrowed"), @@ -284,7 +284,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: } } -fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { +fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool if cx.tables.expr_ty(ex).sty == ty::TyBool { span_lint_and_then( @@ -365,7 +365,7 @@ fn is_wild(pat: &impl std::ops::Deref) -> bool { } } -fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) { +fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); if match_type(cx, ex_ty, &paths::RESULT) { for arm in arms { @@ -405,7 +405,7 @@ fn is_panic_block(block: &Block) -> bool { } } -fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { +fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { if has_only_ref_pats(arms) { let mut suggs = Vec::new(); let (title, msg) = if let ExprKind::AddrOf(Mutability::MutImmutable, ref inner) = ex.node { @@ -436,7 +436,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) } } -fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { +fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 3ebad1d705b..c1ae61dd271 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -876,10 +876,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } /// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { +fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. fn check_unwrap_or_default( - cx: &LateContext, + cx: &LateContext<'_, '_>, name: &str, fun: &hir::Expr, self_expr: &hir::Expr, @@ -924,7 +924,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: /// Check for `*or(foo())`. #[allow(too_many_arguments)] fn check_general_case( - cx: &LateContext, + cx: &LateContext<'_, '_>, name: &str, method_span: Span, fun_span: Span, @@ -967,7 +967,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: return; } - let sugg: Cow<_> = match (fn_has_arguments, !or_has_args) { + let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) { (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), (false, true) => snippet(cx, fun_span, ".."), @@ -1000,7 +1000,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: } /// Checks for the `EXPECT_FUN_CALL` lint. -fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { +fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node { if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node { @@ -1015,7 +1015,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n None } - fn generate_format_arg_snippet(cx: &LateContext, a: &hir::Expr) -> String { + fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String { if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { @@ -1028,7 +1028,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } fn check_general_case( - cx: &LateContext, + cx: &LateContext<'_, '_>, name: &str, method_span: Span, self_expr: &hir::Expr, @@ -1079,7 +1079,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n return; } - let sugg: Cow<_> = snippet(cx, arg.span, ".."); + let sugg: Cow<'_, _> = snippet(cx, arg.span, ".."); span_lint_and_sugg( cx, @@ -1100,7 +1100,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n } /// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) { +fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty<'_>) { let ty = cx.tables.expr_ty(expr); if let ty::TyRef(_, inner, _) = arg_ty.sty { if let ty::TyRef(_, innermost, _) = inner.sty { @@ -1168,7 +1168,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } } -fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { +fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); if let ty::TyAdt(_, subst) = obj_ty.sty { @@ -1194,7 +1194,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { } -fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { +fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { let arg = &args[1]; if let Some(arglists) = method_chain_args(arg, &["chars"]) { let target = &arglists[0][0]; @@ -1223,14 +1223,14 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { } } -fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { +fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); if match_type(cx, obj_ty, &paths::STRING) { lint_string_extend(cx, expr, args); } } -fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { +fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { if_chain! { if let hir::ExprKind::Call(ref fun, ref args) = new.node; if args.len() == 1; @@ -1251,7 +1251,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr } } -fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) { +fn lint_iter_cloned_collect(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr]) { if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { @@ -1265,7 +1265,7 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir } } -fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) { +fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: &[hir::Expr]) { // Check that this is a call to Iterator::fold rather than just some function called fold if !match_trait_method(cx, expr, &paths::ITERATOR) { return; @@ -1275,7 +1275,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E "Expected fold_args to have three entries - the receiver, the initial value and the closure"); fn check_fold_with_op( - cx: &LateContext, + cx: &LateContext<'_, '_>, fold_args: &[hir::Expr], op: hir::BinOpKind, replacement_method_name: &str, @@ -1353,7 +1353,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E }; } -fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { +fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { "slice" @@ -1377,7 +1377,7 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is ); } -fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { +fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap, // because they do not implement `IndexMut` let expr_ty = cx.tables.expr_ty(&get_args[0]); @@ -1416,7 +1416,7 @@ fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], i ); } -fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) { +fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) { // lint if caller of skip is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { span_lint( @@ -1428,8 +1428,8 @@ fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) { } } -fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option> { - fn may_slice(cx: &LateContext, ty: Ty) -> bool { +fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Option> { + fn may_slice(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { match ty.sty { ty::TySlice(_) => true, ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), @@ -1461,7 +1461,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); let mess = if match_type(cx, obj_ty, &paths::OPTION) { @@ -1489,7 +1489,7 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { } /// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) { +fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) { // lint if the caller of `ok()` is a `Result` if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT) { let result_type = cx.tables.expr_ty(&ok_args[0]); @@ -1507,7 +1507,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) { } /// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { +fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { // lint if the caller of `map()` is an `Option` if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { // get snippets for args to map() and unwrap_or() @@ -1765,7 +1765,7 @@ struct BinaryExprInfo<'a> { } /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. -fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, info: &mut BinaryExprInfo) { +fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut BinaryExprInfo<'_>) { macro_rules! lint_with_both_lhs_and_rhs { ($func:ident, $cx:expr, $info:ident) => { if !$func($cx, $info) { @@ -1784,9 +1784,9 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. -fn lint_chars_cmp<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - info: &BinaryExprInfo, +fn lint_chars_cmp( + cx: &LateContext<'_, '_>, + info: &BinaryExprInfo<'_>, chain_methods: &[&str], lint: &'static Lint, suggest: &str, @@ -1824,12 +1824,12 @@ fn lint_chars_cmp<'a, 'tcx>( } /// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { +fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") } /// Checks for the `CHARS_LAST_CMP` lint. -fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { +fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") { true } else { @@ -1840,7 +1840,7 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. fn lint_chars_cmp_with_unwrap<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - info: &BinaryExprInfo, + info: &BinaryExprInfo<'_>, chain_methods: &[&str], lint: &'static Lint, suggest: &str, @@ -1871,12 +1871,12 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( } /// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. -fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { +fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") } /// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. -fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool { +fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { true } else { @@ -1907,7 +1907,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi } /// Checks for the `USELESS_ASREF` lint. -fn lint_asref(cx: &LateContext, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) { +fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) { // when we get here, we've already checked that the call name is "as_ref" or "as_mut" // check if the call is to the actual `AsRef` or `AsMut` trait if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { @@ -1931,7 +1931,7 @@ fn lint_asref(cx: &LateContext, expr: &hir::Expr, call_name: &str, as_ref_args: } /// Given a `Result` type, return its error type (`E`). -fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option> { +fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { if let ty::TyAdt(_, substs) = ty.sty { if match_type(cx, ty, &paths::RESULT) { substs.types().nth(1) @@ -2033,7 +2033,7 @@ enum SelfKind { impl SelfKind { fn matches( self, - cx: &LateContext, + cx: &LateContext<'_, '_>, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, @@ -2160,7 +2160,7 @@ impl Convention { } impl fmt::Display for Convention { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { Convention::Eq(this) => this.fmt(f), Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), @@ -2177,7 +2177,7 @@ enum OutType { } impl OutType { - fn matches(self, cx: &LateContext, ty: &hir::FunctionRetTy) -> bool { + fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy) -> bool { let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into())); match (self, ty) { (OutType::Unit, &hir::DefaultReturn(_)) => true, diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 498f9ef4743..bc573841cc8 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -66,7 +66,7 @@ enum MinMax { Max, } -fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { +fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { if let ExprKind::Call(ref path, ref args) = expr.node { if let ExprKind::Path(ref qpath) = path.node { opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)).and_then(|def_id| { @@ -86,7 +86,7 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' } } -fn fetch_const<'a>(cx: &LateContext, args: &'a [Expr], m: MinMax) -> Option<(MinMax, Constant, &'a Expr)> { +fn fetch_const<'a>(cx: &LateContext<'_, '_>, args: &'a [Expr], m: MinMax) -> Option<(MinMax, Constant, &'a Expr)> { if args.len() != 2 { return None; } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a32c95e9672..b01d24a1ad3 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -433,7 +433,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) { +fn check_nan(cx: &LateContext<'_, '_>, path: &Path, expr: &Expr) { if !in_constant(cx, expr.id) { if let Some(seg) = path.segments.last() { if seg.ident.name == "NAN" { @@ -464,11 +464,11 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { } } -fn is_float(cx: &LateContext, expr: &Expr) -> bool { +fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::TyFloat(_)) } -fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { +fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { let (arg_ty, snip) = match expr.node { ExprKind::MethodCall(.., ref args) if args.len() == 1 => { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { @@ -542,7 +542,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { /// Heuristic to see if an expression is used. Should be compatible with /// `unused_variables`'s idea /// of what it means for an expression to be "used". -fn is_used(cx: &LateContext, expr: &Expr) -> bool { +fn is_used(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.node { ExprKind::Assign(_, ref rhs) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), @@ -565,14 +565,14 @@ fn in_attributes_expansion(expr: &Expr) -> bool { } /// Test whether `def` is a variable defined outside a macro. -fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { +fn non_macro_local(cx: &LateContext<'_, '_>, def: &def::Def) -> bool { match *def { def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir.span(id)), _ => false, } } -fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { +fn check_cast(cx: &LateContext<'_, '_>, span: Span, e: &Expr, ty: &Ty) { if_chain! { if let TyKind::Ptr(MutTy { mutbl, .. }) = ty.node; if let ExprKind::Lit(ref lit) = e.node; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 5bf7d5f3404..5d2b3914f84 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -189,7 +189,7 @@ impl LintPass for MiscEarly { } impl EarlyLintPass for MiscEarly { - fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) { + fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { for param in &gen.params { if let GenericParamKind::Type { .. } = param.kind { let name = param.ident.as_str(); @@ -205,7 +205,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) { + fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; let type_name = npat.segments @@ -266,7 +266,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, decl: &FnDecl, _: Span, _: NodeId) { let mut registered_names: HashMap = HashMap::new(); for arg in &decl.inputs { @@ -293,7 +293,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_external_macro(cx, expr.span) { return; } @@ -325,7 +325,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_block(&mut self, cx: &EarlyContext, block: &Block) { + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { for w in block.stmts.windows(2) { if_chain! { if let StmtKind::Local(ref local) = w[0].node; @@ -352,7 +352,7 @@ impl EarlyLintPass for MiscEarly { } impl MiscEarly { - fn check_lit(self, cx: &EarlyContext, lit: &Lit) { + fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { if_chain! { if let LitKind::Int(value, ..) = lit.node; if let Some(src) = snippet_opt(cx, lit.span); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index e921c541be2..fe2bbbdb9af 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -67,7 +67,7 @@ impl MissingDoc { .expect("empty doc_hidden_stack") } - fn check_missing_docs_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { + fn check_missing_docs_attrs(&self, cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. if cx.sess().opts.test { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index cc57e771064..e19ec4da67e 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -68,7 +68,7 @@ declare_clippy_lint! { pub struct MissingInline; -fn check_missing_inline_attrs(cx: &LateContext, +fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { let has_inline = attrs .iter() diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index b484488b106..d4246045506 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -39,7 +39,7 @@ impl LintPass for Pass { } impl EarlyLintPass for Pass { - fn check_crate(&mut self, cx: &EarlyContext, krate: &Crate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { let metadata = match cargo_metadata::metadata_deps(None, true) { Ok(metadata) => metadata, Err(_) => { diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 2448cd84d7c..50ef9f268f2 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { } } -fn get_atomic_name(ty: Ty) -> Option<(&'static str)> { +fn get_atomic_name(ty: Ty<'_>) -> Option<(&'static str)> { match ty.sty { ty::TyBool => Some("AtomicBool"), ty::TyUint(_) => Some("AtomicUsize"), diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 0b955bbfdff..60ab0eaae02 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -110,7 +110,7 @@ impl LintPass for NeedlessContinue { } impl EarlyLintPass for NeedlessContinue { - fn check_expr(&mut self, ctx: &EarlyContext, expr: &ast::Expr) { + fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) { if !in_macro(expr.span) { check_and_warn(ctx, expr); } @@ -265,7 +265,7 @@ const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving block, like so:\n"; -fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: LintType) { +fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) { // snip is the whole *help* message that appears after the warning. // message is the warning message. // expr is the expression which the lint warning message refers to. @@ -284,7 +284,7 @@ fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: L span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); } -fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str) -> String { +fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); let if_code = format!("if {} {{\n continue;\n}}\n", cond_code); @@ -301,7 +301,7 @@ fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext, data: &'a L ret } -fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str) -> String { +fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); let mut if_code = format!("if {} {{\n", cond_code); @@ -332,7 +332,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext, data: &'a ret } -fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) { +fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { with_loop_block(expr, |loop_block| { for (i, stmt) in loop_block.stmts.iter().enumerate() { with_if_expr(stmt, |if_expr, cond, then_block, else_expr| { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7463ea2d9c3..82e85f3453a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } // Dereference suggestion - let sugg = |db: &mut DiagnosticBuilder| { + let sugg = |db: &mut DiagnosticBuilder<'_>| { if let ty::TypeVariants::TyAdt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { @@ -396,7 +396,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { } } - fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, _: euv::LoanCause) {} + fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, _: euv::LoanCause) {} fn mutate(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: euv::MutateMode) {} diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 96f2e58f3be..c056ff46178 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { } } -fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { +fn check_mul(cx: &LateContext<'_, '_>, span: Span, lit: &Expr, exp: &Expr) { if_chain! { if let ExprKind::Lit(ref l) = lit.node; if let Constant::Int(val) = consts::lit_to_constant(&l.node, cx.tables.expr_ty(lit)); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index a2192710292..49e4e966e18 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } } -fn create_new_without_default_suggest_msg(ty: Ty) -> String { +fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String { #[cfg_attr(rustfmt, rustfmt_skip)] format!( "impl Default for {} {{ diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index dc83b29854c..cacb5d6a9ff 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -41,7 +41,7 @@ declare_clippy_lint! { "outer expressions with no effect" } -fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { +fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { if in_macro(expr.span) { return false; } @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } -fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option> { +fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option> { if in_macro(expr.span) { return None; } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 8f21523f404..e9688262c2a 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -312,13 +312,13 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { } impl EarlyLintPass for NonExpressiveNames { - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if let ItemKind::Fn(ref decl, _, _, ref blk) = item.node { do_check(self, cx, &item.attrs, decl, blk); } } - fn check_impl_item(&mut self, cx: &EarlyContext, item: &ImplItem) { + fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &ImplItem) { if let ImplItemKind::Method(ref sig, ref blk) = item.node { do_check(self, cx, &item.attrs, &sig.decl, blk); } @@ -326,7 +326,7 @@ impl EarlyLintPass for NonExpressiveNames { } -fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { +fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { if !attr::contains_name(attrs, "test") { let mut visitor = SimilarNamesLocalVisitor { names: Vec::new(), diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 06b48b9eeac..effeb88d0cf 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -61,7 +61,7 @@ enum OpenOption { Append, } -fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { +fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) { if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.node { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); @@ -112,7 +112,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp } } -fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) { +fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument)], span: Span) { let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, false, false, false, false); diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index e8dfca24c57..e603773f7ba 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -86,7 +86,7 @@ fn get_outer_span(expr: &Expr) -> Span { } } -fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) { +fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext<'_, '_>) { if_chain! { if let ExprKind::Lit(ref lit) = params[0].node; if is_direct_expn_of(expr.span, "panic").is_some(); diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 76ea9c5ade6..6a0f4f147b7 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -37,7 +37,7 @@ impl LintPass for Precedence { } impl EarlyLintPass for Precedence { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_macro(expr.span) { return; } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 167ce84f803..ea2d07df455 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } } -fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option) { +fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option) { let fn_def_id = cx.tcx.hir.local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); let fn_ty = sig.skip_binder(); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b2d53e124ff..630dd1b57be 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -52,7 +52,7 @@ impl QuestionMarkPass { /// ``` /// /// If it matches, it will suggest to use the question mark operator instead - fn check_is_none_and_early_return_none(cx: &LateContext, expr: &Expr) { + fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr) { if_chain! { if let ExprKind::If(ref if_expr, ref body, _) = expr.node; if let ExprKind::MethodCall(ref segment, _, ref args) = if_expr.node; @@ -81,13 +81,13 @@ impl QuestionMarkPass { } } - fn is_option(cx: &LateContext, expression: &Expr) -> bool { + fn is_option(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { let expr_ty = cx.tables.expr_ty(expression); match_type(cx, expr_ty, &OPTION) } - fn expression_returns_none(cx: &LateContext, expression: &Expr) -> bool { + fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { match expression.node { ExprKind::Block(ref block, _) => { if let Some(return_expression) = Self::return_expression(block) { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 9525ea014a9..fd303bb6ab4 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { +fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { // No need for walk_ptrs_ty here because step_by moves self, so it // can't be called on a borrowed range. let ty = cx.tables.expr_ty_adjusted(expr); diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 27aca6f4bf1..f349f46d926 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -39,7 +39,7 @@ fn without_parens(mut e: &Expr) -> &Expr { } impl EarlyLintPass for Pass { - fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node; if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node; @@ -84,7 +84,7 @@ impl LintPass for DerefPass { } impl EarlyLintPass for DerefPass { - fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { if let ExprKind::Field(ref object, ref field_name) = e.node; if let ExprKind::Paren(ref parened) = object.node; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 2bfc1e7d107..e4973cadc61 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -49,7 +49,7 @@ pub struct ReturnPass; impl ReturnPass { // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &EarlyContext, block: &ast::Block) { + fn check_block_return(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { if let Some(stmt) = block.stmts.last() { match stmt.node { ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { @@ -61,7 +61,7 @@ impl ReturnPass { } // Check a the final expression in a block if it's a return. - fn check_final_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr, span: Option) { + fn check_final_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr, span: Option) { match expr.node { // simple return is always "bad" ast::ExprKind::Ret(Some(ref inner)) => { @@ -89,7 +89,7 @@ impl ReturnPass { } } - fn emit_return_lint(&mut self, cx: &EarlyContext, ret_span: Span, inner_span: Span) { + fn emit_return_lint(&mut self, cx: &EarlyContext<'_>, ret_span: Span, inner_span: Span) { if in_external_macro(cx, inner_span) || in_macro(inner_span) { return; } @@ -101,7 +101,7 @@ impl ReturnPass { } // Check for "let x = EXPR; x" - fn check_let_return(&mut self, cx: &EarlyContext, block: &ast::Block) { + fn check_let_return(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { let mut it = block.stmts.iter(); // we need both a let-binding stmt and an expr @@ -138,14 +138,14 @@ impl LintPass for ReturnPass { } impl EarlyLintPass for ReturnPass { - fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: &ast::FnDecl, _: Span, _: ast::NodeId) { match kind { FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), FnKind::Closure(body) => self.check_final_expr(cx, body, Some(body.span)), } } - fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { self.check_let_return(cx, block); } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 563530c1ae7..1b29e53b754 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -148,7 +148,7 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: } } -fn is_binding(cx: &LateContext, pat_id: HirId) -> bool { +fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { let var_ty = cx.tables.node_id_to_type(pat_id); match var_ty.sty { ty::TyAdt(..) => false, diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index fa8102308d8..a13f864c5ce 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -117,11 +117,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { } } -fn is_string(cx: &LateContext, e: &Expr) -> bool { +fn is_string(cx: &LateContext<'_, '_>, e: &Expr) -> bool { match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(e)), &paths::STRING) } -fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { +fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool { match src.node { ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprKind::Block(ref block, _) => { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index bd0f6dc68dc..b0a8a2d0061 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { } fn check_binop<'a>( - cx: &LateContext, + cx: &LateContext<'_, '_>, expr: &hir::Expr, binop: hir::BinOpKind, traits: &[&'a str], diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 4278d6d74ac..38369d05676 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap { } /// Implementation of the `MANUAL_SWAP` lint. -fn check_manual_swap(cx: &LateContext, block: &Block) { +fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { for w in block.stmts.windows(3) { if_chain! { // let t = foo(); @@ -84,7 +84,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2); then { fn check_for_slice<'a>( - cx: &LateContext, + cx: &LateContext<'_, '_>, lhs1: &'a Expr, lhs2: &'a Expr, ) -> Option<(&'a Expr, &'a Expr, &'a Expr)> { @@ -145,7 +145,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { } /// Implementation of the `ALMOST_SWAPPED` lint. -fn check_suspicious_swap(cx: &LateContext, block: &Block) { +fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { for w in block.stmts.windows(2) { if_chain! { if let StmtKind::Semi(ref first, _) = w[0].node; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index aa964e4558f..403aeb47402 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -454,7 +454,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { /// the type's `ToString` implementation. In weird cases it could lead to types /// with invalid `'_` /// lifetime, but it should be rare. -fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String { +fn get_type_snippet(cx: &LateContext<'_, '_>, path: &QPath, to_ref_ty: Ty<'_>) -> String { let seg = last_path_segment(path); if_chain! { if let Some(ref params) = seg.args; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 2921b502c1f..d3932f411d1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -138,7 +138,7 @@ impl LintPass for TypePass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { + fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { // skip trait implementations, see #605 if let Some(map::NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) { if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { @@ -149,11 +149,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { check_fn_decl(cx, decl); } - fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) { + fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &StructField) { check_ty(cx, &field.ty, false); } - fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &TraitItem) { match item.node { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false), TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl), @@ -161,14 +161,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { } } - fn check_local(&mut self, cx: &LateContext, local: &Local) { + fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local) { if let Some(ref ty) = local.ty { check_ty(cx, ty, true); } } } -fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { +fn check_fn_decl(cx: &LateContext<'_, '_>, decl: &FnDecl) { for input in &decl.inputs { check_ty(cx, input, false); } @@ -179,7 +179,7 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { } /// Check if `qpath` has last segment with type parameter matching `path` -fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool { +fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) -> bool { let last = last_path_segment(qpath); if_chain! { if let Some(ref params) = last.args; @@ -203,7 +203,7 @@ fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool /// /// The parameter `is_local` distinguishes the context of the type; types from /// local bindings should only be checked for the `BORROWED_BOX` lint. -fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { +fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { if in_macro(ast_ty.span) { return; } @@ -294,7 +294,7 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } } -fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { +fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { match mut_ty.ty.node { TyKind::Path(ref qpath) => { let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id); @@ -378,7 +378,7 @@ declare_clippy_lint! { "creating a let binding to a value of unit type, which usually can't be used afterwards" } -fn check_let_unit(cx: &LateContext, decl: &Decl) { +fn check_let_unit(cx: &LateContext<'_, '_>, decl: &Decl) { if let DeclKind::Local(ref local) = decl.node { if is_unit(cx.tables.pat_ty(&local.pat)) { if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { @@ -548,7 +548,7 @@ fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { } } -fn is_unit(ty: Ty) -> bool { +fn is_unit(ty: Ty<'_>) -> bool { match ty.sty { ty::TyTuple(slice) if slice.is_empty() => true, _ => false, @@ -753,7 +753,7 @@ declare_clippy_lint! { /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant -fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { +fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { match typ.sty { ty::TyInt(i) => match i { IntTy::Isize => tcx.data_layout.pointer_size.bits(), @@ -775,14 +775,14 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { } } -fn is_isize_or_usize(typ: Ty) -> bool { +fn is_isize_or_usize(typ: Ty<'_>) -> bool { match typ.sty { ty::TyInt(IntTy::Isize) | ty::TyUint(UintTy::Usize) => true, _ => false, } } -fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to_f64: bool) { +fn span_precision_loss_lint(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty<'_>, cast_to_f64: bool) { let mantissa_nbits = if cast_to_f64 { 52 } else { 23 }; let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; let arch_dependent_str = "on targets with 64-bit wide pointers "; @@ -822,7 +822,7 @@ fn should_strip_parens(op: &Expr, snip: &str) -> bool { false } -fn span_lossless_lint(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { +fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { // Do not suggest using From in consts/statics until it is valid to do so (see #2267). if in_constant(cx, expr.id) { return } // The suggestion is to use a function call, so if the original expression @@ -854,7 +854,7 @@ enum ArchSuffix { None, } -fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to: Ty) { +fn check_truncation_and_wrapping(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); @@ -925,7 +925,7 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c } } -fn check_lossless(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_to: Ty) { +fn check_lossless(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); @@ -1183,7 +1183,7 @@ impl<'a, 'tcx> TypeComplexityPass { } } - fn check_type(&self, cx: &LateContext, ty: &hir::Ty) { + fn check_type(&self, cx: &LateContext<'_, '_>, ty: &hir::Ty) { if in_macro(ty.span) { return; } @@ -1562,7 +1562,7 @@ impl Ord for FullInt { } -fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { +fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> { use syntax::ast::{IntTy, UintTy}; use std::*; @@ -1628,7 +1628,7 @@ fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) } } -fn err_upcast_comparison(cx: &LateContext, span: Span, expr: &Expr, always: bool) { +fn err_upcast_comparison(cx: &LateContext<'_, '_>, span: Span, expr: &Expr, always: bool) { if let ExprKind::Cast(ref cast_val, _) = expr.node { span_lint( cx, @@ -1750,11 +1750,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { fn suggestion<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - db: &mut DiagnosticBuilder, + db: &mut DiagnosticBuilder<'_>, generics_span: Span, generics_suggestion_span: Span, - target: &ImplicitHasherType, - vis: ImplicitHasherConstructorVisitor, + target: &ImplicitHasherType<'_>, + vis: ImplicitHasherConstructorVisitor<'_, '_, '_>, ) { let generics_snip = snippet(cx, generics_span, ""); // trim `<` `>` diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index c4a795bfacb..0549e774fb5 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -94,7 +94,7 @@ fn escape>(s: T) -> String { result } -fn check_str(cx: &LateContext, span: Span, id: NodeId) { +fn check_str(cx: &LateContext<'_, '_>, span: Span, id: NodeId) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { span_help_and_lint( diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index a6cab892324..2f8b3ab836d 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -35,14 +35,14 @@ impl LintPass for UnsafeNameRemoval { } impl EarlyLintPass for UnsafeNameRemoval { - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if let ItemKind::Use(ref use_tree) = item.node { check_use_tree(use_tree, cx, item.span); } } } -fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: Span) { +fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) { match use_tree.kind { UseTreeKind::Simple(Some(new_name), ..) => { let old_name = use_tree @@ -63,7 +63,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: Span) { } } -fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: Span) { +fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, span: Span) { let old_str = old_name.name.as_str(); let new_str = new_name.name.as_str(); if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index e4dac731cf2..a9a7e102ab2 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -39,7 +39,7 @@ impl LintPass for UnusedIoAmount { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { - fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { let expr = match s.node { hir::StmtKind::Semi(ref expr, _) | hir::StmtKind::Expr(ref expr, _) => &**expr, _ => return, @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } } -fn check_method_call(cx: &LateContext, call: &hir::Expr, expr: &hir::Expr) { +fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr, expr: &hir::Expr) { if let hir::ExprKind::MethodCall(ref path, _, _) = call.node { let symbol = &*path.ident.as_str(); if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 52b34916627..a27013344d8 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -52,7 +52,7 @@ pub enum Error { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { Error::Io(ref err) => err.fmt(f), Error::Toml(ref err) => err.fmt(f), diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d63a2dae802..3931f6c55f9 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -212,7 +212,7 @@ pub enum VecArgs<'a> { /// Returns the arguments of the `vec!` macro if this expression was expanded /// from `vec!`. -pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option> { +pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr) -> Option> { if_chain! { if let hir::ExprKind::Call(ref fun, ref args) = expr.node; if let hir::ExprKind::Path(ref path) = fun.node; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 55233510495..b6c241a6825 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -141,7 +141,7 @@ fn has_attr(attrs: &[Attribute]) -> bool { get_attr(attrs, "dump").count() > 0 } -fn print_decl(cx: &LateContext, decl: &hir::Decl) { +fn print_decl(cx: &LateContext<'_, '_>, decl: &hir::Decl) { match decl.node { hir::DeclKind::Local(ref local) => { println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); @@ -156,7 +156,7 @@ fn print_decl(cx: &LateContext, decl: &hir::Decl) { } } -fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { +fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); println!("{}ty: {}", ind, cx.tables.expr_ty(expr)); @@ -342,7 +342,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { } } -fn print_item(cx: &LateContext, item: &hir::Item) { +fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { let did = cx.tcx.hir.local_def_id(item.id); println!("item `{}`", item.name); match item.vis.node { @@ -414,7 +414,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { } } -fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { +fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); match pat.node { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 3d43d595def..32aee099177 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -64,7 +64,7 @@ impl LintPass for Clippy { } impl EarlyLintPass for Clippy { - fn check_crate(&mut self, cx: &EarlyContext, krate: &AstCrate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) { if let Some(utils) = krate .module .items diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bdf486a45ab..8e83b8d81f2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -48,7 +48,7 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { rhs.ctxt() != lhs.ctxt() } -pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { +pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir.get_parent(id); match cx.tcx.hir.body_owner_kind(parent_id) { hir::BodyOwnerKind::Fn => false, @@ -115,7 +115,7 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { /// ``` /// /// See also the `paths` module. -pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { +pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool { use syntax::symbol; struct AbsolutePathBuffer { @@ -145,7 +145,7 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { } /// Check if type is struct, enum or union type with given def path. -pub fn match_type(cx: &LateContext, ty: Ty, path: &[&str]) -> bool { +pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.sty { ty::TyAdt(adt, _) => match_def_path(cx.tcx, adt.did, path), _ => false, @@ -153,7 +153,7 @@ pub fn match_type(cx: &LateContext, ty: Ty, path: &[&str]) -> bool { } /// Check if the method call given in `expr` belongs to given type. -pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { +pub fn match_impl_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool { let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; let trt_id = cx.tcx.impl_of_method(method_call.def_id()); if let Some(trt_id) = trt_id { @@ -164,7 +164,7 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { } /// Check if the method call given in `expr` belongs to given trait. -pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { +pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool { let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; let trt_id = cx.tcx.trait_of_item(method_call.def_id()); if let Some(trt_id) = trt_id { @@ -244,7 +244,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { } /// Get the definition associated to a path. -pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { +pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option { let crates = cx.tcx.crates(); let krate = crates .iter() @@ -280,7 +280,7 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { } /// Convenience function to get the `DefId` of a trait by path. -pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option { +pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option { let def = match path_to_def(cx, path) { Some(def) => def, None => return None, @@ -308,7 +308,7 @@ pub fn implements_trait<'a, 'tcx>( } /// Check whether this type implements Drop. -pub fn has_drop(cx: &LateContext, expr: &Expr) -> bool { +pub fn has_drop(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let struct_ty = cx.tables.expr_ty(expr); match struct_ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), @@ -317,7 +317,7 @@ pub fn has_drop(cx: &LateContext, expr: &Expr) -> bool { } /// Resolve the definition of a node from its `HirId`. -pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: HirId) -> def::Def { +pub fn resolve_node(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> def::Def { cx.tables.qpath_def(qpath, id) } @@ -352,7 +352,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option Option { +pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { let parent_id = cx.tcx.hir.get_parent(expr.id); match cx.tcx.hir.find(parent_id) { Some(Node::NodeItem(&Item { ref name, .. })) => Some(*name), @@ -458,13 +458,13 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( /// Trim indentation from a multiline string with possibility of ignoring the /// first line. -pub fn trim_multiline(s: Cow, ignore_first: bool) -> Cow { +pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool) -> Cow<'_, str> { let s_space = trim_multiline_inner(s, ignore_first, ' '); let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); trim_multiline_inner(s_tab, ignore_first, ' ') } -fn trim_multiline_inner(s: Cow, ignore_first: bool, ch: char) -> Cow { +fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_, str> { let x = s.lines() .skip(ignore_first as usize) .filter_map(|l| { @@ -502,7 +502,7 @@ fn trim_multiline_inner(s: Cow, ignore_first: bool, ch: char) -> Cow { } /// Get a parent expressions if any – this is useful to constrain a lint. -pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { +pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c Expr> { let map = &cx.tcx.hir; let node_id: NodeId = e.id; let parent_id: NodeId = map.get_parent_node(node_id); @@ -642,7 +642,7 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( /// appear once per /// replacement. In human-readable format though, it only appears once before /// the whole suggestion. -pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: I) +pub fn multispan_sugg(db: &mut DiagnosticBuilder<'_>, help_msg: String, sugg: I) where I: IntoIterator, { @@ -675,7 +675,7 @@ pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { } /// Return the base type for references and raw pointers. -pub fn walk_ptrs_ty(ty: Ty) -> Ty { +pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> { match ty.sty { ty::TyRef(_, ty, _) => walk_ptrs_ty(ty), _ => ty, @@ -684,8 +684,8 @@ pub fn walk_ptrs_ty(ty: Ty) -> Ty { /// Return the base type for references and raw pointers, and count reference /// depth. -pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) { - fn inner(ty: Ty, depth: usize) -> (Ty, usize) { +pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { + fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) { match ty.sty { ty::TyRef(_, ty, _) => inner(ty, depth + 1), _ => (ty, depth), @@ -705,7 +705,7 @@ pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { false } -pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool { +pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool { cx.tables.adjustments().get(e.hir_id).is_some() } @@ -898,15 +898,15 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { } /// Return whether a pattern is refutable. -pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { - fn is_enum_variant(cx: &LateContext, qpath: &QPath, id: HirId) -> bool { +pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool { + fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool { matches!( cx.tables.qpath_def(qpath, id), def::Def::Variant(..) | def::Def::VariantCtor(..) ) } - fn are_refutable<'a, I: Iterator>(cx: &LateContext, mut i: I) -> bool { + fn are_refutable<'a, I: Iterator>(cx: &LateContext<'_, '_>, mut i: I) -> bool { i.any(|pat| is_refutable(cx, pat)) } @@ -1065,7 +1065,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { /// Returns true if the lint is allowed in the current context /// /// Useful for skipping long running code when it's unnecessary -pub fn is_allowed(cx: &LateContext, lint: &'static Lint, id: NodeId) -> bool { +pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: NodeId) -> bool { cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } @@ -1085,24 +1085,24 @@ pub fn get_arg_ident(pat: &Pat) -> Option { } } -pub fn int_bits(tcx: TyCtxt, ity: ast::IntTy) -> u64 { +pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 { layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() } /// Turn a constant int byte representation into an i128 -pub fn sext(tcx: TyCtxt, u: u128, ity: ast::IntTy) -> i128 { +pub fn sext(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } /// clip unused bytes -pub fn unsext(tcx: TyCtxt, u: i128, ity: ast::IntTy) -> u128 { +pub fn unsext(tcx: TyCtxt<'_, '_, '_>, u: i128, ity: ast::IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); ((u as u128) << amt) >> amt } /// clip unused bytes -pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 { +pub fn clip(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::UintTy) -> u128 { let bits = layout::Integer::from_attr(tcx, attr::IntType::UnsignedInt(ity)).size().bits(); let amt = 128 - bits; (u << amt) >> amt @@ -1141,7 +1141,7 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { without } -pub fn any_parent_is_automatically_derived(tcx: TyCtxt, node: NodeId) -> bool { +pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: NodeId) -> bool { let map = &tcx.hir; let mut prev_enclosing_node = None; let mut enclosing_node = node; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 4275345d395..1a20eb01015 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -7,7 +7,7 @@ use syntax::codemap::Span; use crate::utils::{get_pat_name, match_var, snippet}; pub fn get_spans( - cx: &LateContext, + cx: &LateContext<'_, '_>, opt_body_id: Option, idx: usize, replacements: &'static [(&'static str, &'static str)], diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index c7e1e59f063..91fd5ec874a 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -32,8 +32,8 @@ pub enum Sugg<'a> { /// Literal constant `1`, for convenience. pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); -impl<'a> Display for Sugg<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { +impl Display for Sugg<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { match *self { Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) | Sugg::BinOp(_, ref s) => s.fmt(f), } @@ -43,7 +43,7 @@ impl<'a> Display for Sugg<'a> { #[allow(wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. - pub fn hir_opt(cx: &LateContext, expr: &hir::Expr) -> Option { + pub fn hir_opt(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); match expr.node { @@ -82,12 +82,12 @@ impl<'a> Sugg<'a> { /// Convenience function around `hir_opt` for suggestions with a default /// text. - pub fn hir(cx: &LateContext, expr: &hir::Expr, default: &'a str) -> Self { + pub fn hir(cx: &LateContext<'_, '_>, expr: &hir::Expr, default: &'a str) -> Self { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } /// Prepare a suggestion from an expression. - pub fn ast(cx: &EarlyContext, expr: &ast::Expr, default: &'a str) -> Self { + pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self { use syntax::ast::RangeLimits; let snippet = snippet(cx, expr.span, default); @@ -241,7 +241,7 @@ impl ParenHelper { } impl Display for ParenHelper { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { if self.paren { write!(f, "({})", self.wrapped) } else { @@ -255,7 +255,7 @@ impl Display for ParenHelper { /// For convenience, the operator is taken as a string because all unary /// operators have the same /// precedence. -pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> { +pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> { Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into()) } @@ -264,7 +264,7 @@ pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> { /// Precedence of shift operator relative to other arithmetic operation is /// often confusing so /// parenthesis will always be added for a mix of these. -pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { +pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> { /// Whether the operator is a shift operator `<<` or `>>`. fn is_shift(op: &AssocOp) -> bool { matches!(*op, AssocOp::ShiftLeft | AssocOp::ShiftRight) @@ -335,7 +335,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { } /// Convinience wrapper arround `make_assoc` and `AssocOp::from_ast_binop`. -pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { +pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> { make_assoc(AssocOp::from_ast_binop(op), lhs, rhs) } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 6d75dfb486d..43e492bfb4e 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -44,7 +44,7 @@ struct MutVarsDelegate { } impl<'tcx> MutVarsDelegate { - fn update(&mut self, cat: &'tcx Categorization) { + fn update(&mut self, cat: &'tcx Categorization<'_>) { match *cat { Categorization::Local(id) => { self.used_mutably.insert(id); @@ -68,7 +68,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) { + fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, bk: ty::BorrowKind, _: LoanCause) { if let ty::BorrowKind::MutBorrow = bk { self.update(&cmt.cat) } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index a58d73f86da..cea3307a827 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -94,7 +94,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA } /// Return the item type of the vector (ie. the `T` in `Vec`). -fn vec_type(ty: Ty) -> Ty { +fn vec_type(ty: Ty<'_>) -> Ty<'_> { if let ty::TyAdt(_, substs) = ty.sty { substs.type_at(0) } else { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c4b5a9ccefc..a019e23a301 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -168,7 +168,7 @@ impl LintPass for Pass { } impl EarlyLintPass for Pass { - fn check_mac(&mut self, cx: &EarlyContext, mac: &Mac) { + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) { if mac.node.path == "println" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`"); if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { @@ -261,7 +261,7 @@ fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Op return Some(fmtstr); } let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; - const SIMPLE: FormatSpec = FormatSpec { + const SIMPLE: FormatSpec<'_> = FormatSpec { fill: None, align: AlignUnknown, flags: 0, diff --git a/src/lib.rs b/src/lib.rs index 6ff15e2cd89..1123c968006 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ use rustc_plugin::Registry; #[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { +pub fn plugin_registrar(reg: &mut Registry<'_>) { reg.sess.lint_store.with_read_lock(|lint_store| { for (lint, _, _) in lint_store.get_lint_groups() { reg.sess -- cgit 1.4.1-3-g733a5 From 6ad7a92ff87a007912e0d9803fd6b80fddbdb965 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 Jul 2018 08:39:18 +0100 Subject: Expand on misrefactored_assign_op known problems --- clippy_lints/src/assign_ops.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index c2d0ccd1534..d61515d533f 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -51,8 +51,10 @@ declare_clippy_lint! { /// **Why is this bad?** Most likely these are bugs where one meant to write `a /// op= b`. /// -/// **Known problems:** Someone might actually mean `a op= a op b`, but that -/// should rather be written as `a = (2 * a) op b` where applicable. +/// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have +/// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both. +/// If `a op= a op b` is really the correct behaviour then +/// rewrite it as `a = (2 * a) op b` as it's less confusing. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 70f5bb1ff6f0eed2f7699fb3cee48775042b8dfb Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 Jul 2018 09:26:28 +0100 Subject: Tweak misrefactored_assign_op's known problems wording --- clippy_lints/src/assign_ops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index d61515d533f..1ce690abcfe 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -53,8 +53,8 @@ declare_clippy_lint! { /// /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both. -/// If `a op= a op b` is really the correct behaviour then -/// rewrite it as `a = (2 * a) op b` as it's less confusing. +/// If `a op= a op b` is really the correct behaviour it should be +/// written as `a = a op a op b` as it's less confusing. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From b1fa7b91baed3d2d5e46584701c9828d3a1f160d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 Jul 2018 07:49:39 +0100 Subject: Delegate utils::in_external_macro to rustc::lint::in_external_macro --- clippy_lints/src/utils/mod.rs | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8e83b8d81f2..91bb73a9bf4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -19,7 +19,7 @@ use std::str::FromStr; use std::rc::Rc; use syntax::ast::{self, LitKind}; use syntax::attr; -use syntax::codemap::{CompilerDesugaringKind, ExpnFormat, ExpnInfo, Span, DUMMY_SP}; +use syntax::codemap::{CompilerDesugaringKind, ExpnFormat, Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; use syntax::symbol::keywords; @@ -78,33 +78,9 @@ pub fn is_range_expression(span: Span) -> bool { } /// Returns true if the macro that expanded the crate was outside of the -/// current crate or was a -/// compiler plugin. +/// current crate or was a compiler plugin. pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { - /// Invokes `in_macro` with the expansion info of the given span slightly - /// heavy, try to use - /// this after other checks have already happened. - fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool { - // no ExpnInfo = no macro - if let ExpnFormat::MacroAttribute(..) = info.format { - // these are all plugins - return true; - } - // no span for the callee = external macro - info.def_site.map_or(true, |span| { - // no snippet = external macro or compiler-builtin expansion - cx.sess() - .codemap() - .span_to_snippet(span) - .ok() - .map_or(true, |code| !code.starts_with("macro_rules")) - }) - } - - span.ctxt() - .outer() - .expn_info() - .map_or(false, |info| in_macro_ext(cx, &info)) + ::rustc::lint::in_external_macro(cx.sess(), span) } /// Check if a `DefId`'s path matches the given absolute type path usage. -- cgit 1.4.1-3-g733a5 From a1cce2d06a1bcde6d8af7319b21772312e1b6579 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 Jul 2018 07:55:38 +0100 Subject: Inline utils::in_external_macro --- clippy_lints/src/else_if_without_else.rs | 4 ++-- clippy_lints/src/if_not_else.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 4 ++-- clippy_lints/src/literal_representation.rs | 6 +++--- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/matches.rs | 4 ++-- clippy_lints/src/methods.rs | 4 ++-- clippy_lints/src/misc_early.rs | 4 ++-- clippy_lints/src/mut_mut.rs | 4 ++-- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 ++-- clippy_lints/src/new_without_default.rs | 4 ++-- clippy_lints/src/returns.rs | 6 +++--- clippy_lints/src/shadow.rs | 8 ++++---- clippy_lints/src/types.rs | 8 ++++---- clippy_lints/src/utils/mod.rs | 6 ------ 15 files changed, 34 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index d3560434a31..39404bbafcc 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; -use crate::utils::{in_external_macro, span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; /// **What it does:** Checks for usage of if expressions with an `else if` branch, /// but without a final `else` branch. @@ -50,7 +50,7 @@ impl LintPass for ElseIfWithoutElse { impl EarlyLintPass for ElseIfWithoutElse { fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) { - if in_external_macro(cx, item.span) { + if in_external_macro(cx.sess(), item.span) { return; } diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 915bc28f751..fea3069f37d 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -5,7 +5,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; -use crate::utils::{in_external_macro, span_help_and_lint}; +use crate::utils::span_help_and_lint; /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an /// else branch. @@ -48,7 +48,7 @@ impl LintPass for IfNotElse { impl EarlyLintPass for IfNotElse { fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { - if in_external_macro(cx, item.span) { + if in_external_macro(cx.sess(), item.span) { return; } if let ExprKind::If(ref cond, _, Some(ref els)) = item.node { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7762c4d1cb5..cf7a016231e 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -7,7 +7,7 @@ use rustc::hir::*; use rustc::hir::intravisit::*; use std::collections::{HashMap, HashSet}; use syntax::codemap::Span; -use crate::utils::{in_external_macro, last_path_segment, span_lint}; +use crate::utils::{last_path_segment, span_lint}; use syntax::symbol::keywords; /// **What it does:** Checks for lifetime annotations which can be removed by @@ -98,7 +98,7 @@ fn check_fn_inner<'a, 'tcx>( generics: &'tcx Generics, span: Span, ) { - if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { + if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, &generics.where_clause) { return; } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 383bba2d4bd..45f9af49a15 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -6,7 +6,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast::*; use syntax_pos; -use crate::utils::{in_external_macro, snippet_opt, span_lint_and_sugg}; +use crate::utils::{snippet_opt, span_lint_and_sugg}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -282,7 +282,7 @@ impl LintPass for LiteralDigitGrouping { impl EarlyLintPass for LiteralDigitGrouping { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } @@ -422,7 +422,7 @@ impl LintPass for LiteralRepresentation { impl EarlyLintPass for LiteralRepresentation { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 23830c566df..b95bc01c013 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -23,7 +23,7 @@ use crate::utils::{sugg, sext}; use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; -use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, +use crate::utils::{get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq}; use crate::utils::paths; @@ -450,7 +450,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_simple_break_expr(&arms[1].body) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 10d4d94cb91..c7452f0027e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -8,7 +8,7 @@ use std::collections::Bound; use syntax::ast::LitKind; use syntax::codemap::Span; use crate::utils::paths; -use crate::utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, +use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; @@ -183,7 +183,7 @@ impl LintPass for MatchPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.node { diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index c1ae61dd271..28ff303fc83 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -10,7 +10,7 @@ use std::fmt; use std::iter; use syntax::ast; use syntax::codemap::{Span, BytePos}; -use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self, +use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; @@ -806,7 +806,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) { - if in_external_macro(cx, implitem.span) { + if in_external_macro(cx.sess(), implitem.span) { return; } let name = implitem.ident.name; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 5d2b3914f84..9b8e0743f39 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -6,7 +6,7 @@ use std::char; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use crate::utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; +use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -294,7 +294,7 @@ impl EarlyLintPass for MiscEarly { } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } match expr.node { diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index f3918f542df..0413f1ab603 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -3,7 +3,7 @@ use rustc::hir::intravisit; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use rustc::ty; -use crate::utils::{higher, in_external_macro, span_lint}; +use crate::utils::{higher, span_lint}; /// **What it does:** Checks for instances of `mut mut` references. /// @@ -50,7 +50,7 @@ pub struct MutVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if in_external_macro(self.cx, expr.span) { + if in_external_macro(self.cx.sess(), expr.span) { return; } diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 70a47674d9f..42be6ec664e 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use crate::utils::{self, paths, span_lint, in_external_macro}; +use crate::utils::{self, paths, span_lint}; /// **What it does:** /// Checks for the usage of negated comparision operators on types which only implement @@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if !in_external_macro(cx, expr.span); + if !in_external_macro(cx.sess(), expr.span); if let ExprKind::Unary(UnOp::UnNot, ref inner) = expr.node; if let ExprKind::Binary(ref op, ref left, _) = inner.node; if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 49e4e966e18..eeb131959e9 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc::ty::{self, Ty}; use syntax::codemap::Span; use crate::utils::paths; -use crate::utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then}; +use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; use crate::utils::sugg::DiagnosticBuilderExt; /// **What it does:** Checks for types with a `fn new() -> Self` method and no @@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { for assoc_item in items { if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind { let impl_item = cx.tcx.hir.impl_item(assoc_item.id); - if in_external_macro(cx, impl_item.span) { + if in_external_macro(cx.sess(), impl_item.span) { return; } if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index e4973cadc61..0ede1bc9727 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -5,7 +5,7 @@ use syntax::ast; use syntax::codemap::Span; use syntax::visit::FnKind; -use crate::utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; +use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for return statements at the end of a block. /// @@ -90,7 +90,7 @@ impl ReturnPass { } fn emit_return_lint(&mut self, cx: &EarlyContext<'_>, ret_span: Span, inner_span: Span) { - if in_external_macro(cx, inner_span) || in_macro(inner_span) { + if in_external_macro(cx.sess(), inner_span) || in_macro(inner_span) { return; } span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { @@ -117,7 +117,7 @@ impl ReturnPass { if let ast::PatKind::Ident(_, ident, _) = local.pat.node; if let ast::ExprKind::Path(_, ref path) = retexpr.node; if match_path_ast(path, &[&ident.as_str()]); - if !in_external_macro(cx, initexpr.span); + if !in_external_macro(cx.sess(), initexpr.span); then { span_note_and_lint(cx, LET_AND_RETURN, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 1b29e53b754..aab578d6344 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; use syntax::codemap::Span; -use crate::utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, span_lint_and_then}; +use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. @@ -90,7 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: Span, _: NodeId, ) { - if in_external_macro(cx, body.value.span) { + if in_external_macro(cx.sess(), body.value.span) { return; } check_fn(cx, decl, body); @@ -122,7 +122,7 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding } fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, decl.span) { + if in_external_macro(cx.sess(), decl.span) { return; } if higher::is_from_for_desugar(decl) { @@ -303,7 +303,7 @@ fn lint_shadow<'a, 'tcx: 'a>( } fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx.sess(), expr.span) { return; } match expr.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d3932f411d1..d016afb4908 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -14,7 +14,7 @@ use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; -use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, +use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_macro, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; use crate::utils::paths; @@ -381,7 +381,7 @@ declare_clippy_lint! { fn check_let_unit(cx: &LateContext<'_, '_>, decl: &Decl) { if let DeclKind::Local(ref local) = decl.node { if is_unit(cx.tables.pat_ty(&local.pat)) { - if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { + if in_external_macro(cx.sess(), decl.span) || in_macro(local.pat.span) { return; } if higher::is_from_for_desugar(decl) { @@ -959,7 +959,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { use syntax::ast::{LitIntType, LitKind}; match lit.node { LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, - _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { + _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) { span_lint( cx, UNNECESSARY_CAST, @@ -969,7 +969,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { }, } } - if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) { + if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 91bb73a9bf4..0b2103ca7ea 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -77,12 +77,6 @@ pub fn is_range_expression(span: Span) -> bool { }) } -/// Returns true if the macro that expanded the crate was outside of the -/// current crate or was a compiler plugin. -pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { - ::rustc::lint::in_external_macro(cx.sess(), span) -} - /// Check if a `DefId`'s path matches the given absolute type path usage. /// /// # Examples -- cgit 1.4.1-3-g733a5 From 137f944315f44aace073549d8e61d800350bf16a Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 25 Jul 2018 06:34:29 +0200 Subject: Fix warnings --- clippy_lints/src/use_self.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 82a571b0caf..8c633423cf6 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -52,7 +52,7 @@ impl LintPass for UseSelf { const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; -fn span_use_self_lint(cx: &LateContext, path: &Path) { +fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { span_lint_and_sugg( cx, USE_SELF, @@ -104,7 +104,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( item_path: &'a Path, impl_item: &ImplItem, impl_decl: &'tcx FnDecl, - impl_trait_ref: &ty::TraitRef, + impl_trait_ref: &ty::TraitRef<'_>, ) { let trait_method = cx .tcx -- cgit 1.4.1-3-g733a5 From 0961c692fae6164086c9c8e21d9e8de253399d8b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 23 Jul 2018 07:29:53 +0200 Subject: s/wiki/lint list/ --- CHANGELOG.md | 6 +++--- util/update_lints.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34f826527bb..48585df0603 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -507,7 +507,7 @@ All notable changes to this project will be documented in this file. ## 0.0.74 — 2016-06-07 * Fix bug with `cargo-clippy` JSON parsing * Add the `CLIPPY_DISABLE_DOCS_LINKS` environment variable to deactivate the - “for further information visit *wiki-link*” message. + “for further information visit *lint-link*” message. ## 0.0.73 — 2016-06-05 * Fix false positives in [`useless_let_if_seq`] @@ -612,7 +612,7 @@ All notable changes to this project will be documented in this file. [`AsRef`]: https://doc.rust-lang.org/std/convert/trait.AsRef.html [configuration file]: ./rust-clippy#configuration - + [`absurd_extreme_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant @@ -894,4 +894,4 @@ All notable changes to this project will be documented in this file. [`zero_prefixed_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_prefixed_literal [`zero_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_ptr [`zero_width_space`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_width_space - + diff --git a/util/update_lints.py b/util/update_lints.py index 6ee14cfcb12..70d49f940ee 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -192,8 +192,8 @@ def main(print_only=False, check=False): # update the links in the CHANGELOG changed |= replace_region( 'CHANGELOG.md', - "", - "", + "", + "", lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], docs_link) for l in sorted(all_lints + deprecated_lints, key=lambda l: l[1])], -- cgit 1.4.1-3-g733a5 From 13353111dadc932c52a63ca8c243f1dd8fce9a7a Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Wed, 25 Jul 2018 14:54:09 +0200 Subject: Add known problem to `needless_borrow` lint The `needless_borrow` lint is temporarily disabled because of some false positives it causes in combination with the `derive` macro. However the documentation does not explain these issues, but instead lists `Known problems: None`. To make it clear why this lint is currently not enabled, a description of the false positives caused by this lint has been added to the `Known problems` section. --- clippy_lints/src/needless_borrow.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 7986b43919c..cb2c572743d 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -16,12 +16,23 @@ use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; /// **Why is this bad?** Suggests that the receiver of the expression borrows /// the expression. /// -/// **Known problems:** None. -/// /// **Example:** /// ```rust /// let x: &i32 = &&&&&&5; /// ``` +/// +/// **Known problems:** This will cause false positives in code generated by `derive`. +/// For instance in the following snippet: +/// ```rust +/// #[derive(Debug)] +/// pub enum Error { +/// Type( +/// &'static str, +/// ), +/// } +/// ``` +/// A warning will be emitted that `&'static str` should be replaced with `&'static str`, +/// however there is nothing that can or should be done to fix this. declare_clippy_lint! { pub NEEDLESS_BORROW, nursery, -- cgit 1.4.1-3-g733a5 From 2665f1066238e46a91ace101b9010e272fc8dfe7 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 25 Jul 2018 20:02:52 +0200 Subject: fix a bunch of typos found by codespell --- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/sugg.rs | 2 +- tests/ui/checked_unwrap.rs | 4 ++-- tests/ui/for_loop.rs | 2 +- tests/ui/infinite_loop.rs | 8 ++++---- tests/ui/matches.stderr | 6 +++--- util/gh-pages/versions.html | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 28819077f9b..2c673fdfe3f 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { } impl ExcessivePrecision { - // None if nothing to lint, Some(suggestion) if lint neccessary + // None if nothing to lint, Some(suggestion) if lint necessary fn check(&self, sym: Symbol, fty: FloatTy) -> Option { let max = max_digits(fty); let sym_str = sym.as_str(); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b95bc01c013..85a9c13ff35 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2217,7 +2217,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr) { match ex.node { ExprKind::Path(_) => self.insert_def_id(ex), - // If there is any fuction/method call… we just stop analysis + // If there is any function/method call… we just stop analysis ExprKind::Call(..) | ExprKind::MethodCall(..) => self.skip = true, _ => walk_expr(self, ex), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index c7452f0027e..6bdcd004134 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -383,7 +383,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { arm.pats[0].span, "Err(_) will match all errors, maybe not a good idea", arm.pats[0].span, - "to remove this warning, match each error seperately \ + "to remove this warning, match each error separately \ or use unreachable macro"); } } diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 02007e2de43..f53e2cb0cce 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -11,7 +11,7 @@ use crate::utils::{self, paths, span_lint}; /// /// **Why is this bad?** /// These operators make it easy to forget that the underlying types actually allow not only three -/// potential Orderings (Less, Equal, Greater) but also a forth one (Uncomparable). This is +/// potential Orderings (Less, Equal, Greater) but also a fourth one (Uncomparable). This is /// especially easy to miss if the operator based comparison result is negated. /// /// **Known problems:** None. diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d016afb4908..7b3f6f20fc7 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -700,7 +700,7 @@ declare_clippy_lint! { /// **What it does:** Checks for casts of a function pointer to a numeric type not enough to store address. /// -/// **Why is this bad?** Casting a function pointer to not eligable type could truncate the address value. +/// **Why is this bad?** Casting a function pointer to not eligible type could truncate the address value. /// /// **Known problems:** None. /// diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 91fd5ec874a..11187559bf6 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -334,7 +334,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> Sugg::BinOp(op, sugg.into()) } -/// Convinience wrapper arround `make_assoc` and `AssocOp::from_ast_binop`. +/// Convenience wrapper around `make_assoc` and `AssocOp::from_ast_binop`. pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> { make_assoc(AssocOp::from_ast_binop(op), lhs, rhs) } diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index c3d4b8de08b..2b5118fa814 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -31,11 +31,11 @@ fn main() { if x.is_ok() { x = Err(()); x.unwrap(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enoguh to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). } else { x = Ok(()); x.unwrap_err(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enoguh to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). } } diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index e28a8f1e178..bc0c3172bf0 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -389,7 +389,7 @@ fn main() { let m: Rc> = Rc::new(HashMap::new()); for (_, v) in &*m { let _v = v; - // Here the `*` is not actually necesarry, but the test tests that we don't + // Here the `*` is not actually necessary, but the test tests that we don't // suggest // `in *m.values()` as we used to } diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index aa4f8b53f6c..9e801911602 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -9,7 +9,7 @@ fn foob() -> bool { unimplemented!() } #[allow(many_single_char_names)] fn immutable_condition() { - // Should warn when all vars mentionned are immutable + // Should warn when all vars mentioned are immutable let y = 0; while y < 10 { println!("KO - y is immutable"); @@ -69,11 +69,11 @@ fn unused_var() { while i < 3 { j = 3; - println!("KO - i not mentionned"); + println!("KO - i not mentioned"); } while i < 3 && j > 0 { - println!("KO - i and j not mentionned"); + println!("KO - i and j not mentioned"); } while i < 3 { @@ -84,7 +84,7 @@ fn unused_var() { while i < 3 && j > 0 { i = 5; - println!("OK - i in cond and mentionned"); + println!("OK - i in cond and mentioned"); } } diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 6554b6d3449..5bfc3271c45 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -164,7 +164,7 @@ error: Err(_) will match all errors, maybe not a good idea | ^^^^^^ | = note: `-D match-wild-err-arm` implied by `-D warnings` - = note: to remove this warning, match each error seperately or use unreachable macro + = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies --> $DIR/matches.rs:131:18 @@ -191,7 +191,7 @@ error: Err(_) will match all errors, maybe not a good idea 138 | Err(_) => {panic!()} | ^^^^^^ | - = note: to remove this warning, match each error seperately or use unreachable macro + = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies --> $DIR/matches.rs:137:18 @@ -217,7 +217,7 @@ error: Err(_) will match all errors, maybe not a good idea 144 | Err(_) => {panic!();} | ^^^^^^ | - = note: to remove this warning, match each error seperately or use unreachable macro + = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies --> $DIR/matches.rs:143:18 diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index 310a3873691..5678ebec722 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -14,7 +14,7 @@
-- cgit 1.4.1-3-g733a5 From f52dd2b8f7555bf197101214361614bd0eaf00a5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 25 Jul 2018 22:49:25 +0200 Subject: Further automate pre_publish.sh --- pre_publish.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pre_publish.sh b/pre_publish.sh index aca17b968a8..d8a9105c67e 100755 --- a/pre_publish.sh +++ b/pre_publish.sh @@ -17,7 +17,13 @@ git commit -m "Bump the version" set +e +echo "Running \`cargo fmt\`.." + cd clippy_lints && cargo fmt -- --write-mode=overwrite && cd .. cargo fmt -- --write-mode=overwrite -echo "remember to add a git tag and running 'cargo test' before committing the rustfmt changes" +echo "Running tests to make sure \`cargo fmt\` did not break anything.." + +cargo test + +echo "If the tests passed, review and commit the formatting changes and remember to add a git tag." -- cgit 1.4.1-3-g733a5 From bf3f976a4373eb541cf292f341f03ad2b6e6982a Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Wed, 25 Jul 2018 17:31:17 -0400 Subject: Fix regression in print_literal --- clippy_lints/src/write.rs | 32 +++++++++++++++++--------------- tests/ui/print_literal.rs | 1 + tests/ui/write_literal.rs | 1 + 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index a019e23a301..0b52981bfa5 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -290,22 +290,24 @@ fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Op idx += 1; }, ExprKind::Assign(lhs, rhs) => { - if let ExprKind::Path(_, p) = &lhs.node { - let mut all_simple = true; - let mut seen = false; - for arg in &args { - match arg.position { - | ArgumentImplicitlyIs(_) - | ArgumentIs(_) - => {}, - ArgumentNamed(name) => if *p == name { - seen = true; - all_simple &= arg.format == SIMPLE; - }, + if let ExprKind::Lit(_) = rhs.node { + if let ExprKind::Path(_, p) = &lhs.node { + let mut all_simple = true; + let mut seen = false; + for arg in &args { + match arg.position { + | ArgumentImplicitlyIs(_) + | ArgumentIs(_) + => {}, + ArgumentNamed(name) => if *p == name { + seen = true; + all_simple &= arg.format == SIMPLE; + }, + } + } + if all_simple && seen { + span_lint(cx, lint, rhs.span, "literal with an empty format string"); } - } - if all_simple && seen { - span_lint(cx, lint, rhs.span, "literal with an empty format string"); } } }, diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 272e1c168d3..620349bab33 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -8,6 +8,7 @@ fn main() { println!("Hello"); let world = "world"; println!("Hello {}", world); + println!("Hello {world}", world=world); println!("3 in hex is {:X}", 3); println!("2 + 1 = {:.4}", 3); println!("2 + 1 = {:5.4}", 3); diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index b09640a18eb..fe1f83a2790 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -11,6 +11,7 @@ fn main() { writeln!(&mut v, "Hello"); let world = "world"; writeln!(&mut v, "Hello {}", world); + writeln!(&mut v, "Hello {world}", world); writeln!(&mut v, "3 in hex is {:X}", 3); writeln!(&mut v, "2 + 1 = {:.4}", 3); writeln!(&mut v, "2 + 1 = {:5.4}", 3); -- cgit 1.4.1-3-g733a5 From 457b76cedfd542f05813b4fe51feec93235dd223 Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Wed, 25 Jul 2018 17:51:04 -0400 Subject: Update line numbers --- tests/ui/print_literal.stderr | 28 ++++++++++++++-------------- tests/ui/write_literal.stderr | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 39e0387cb5e..eb0940881e9 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,7 +1,7 @@ error: literal with an empty format string --> $DIR/print_literal.rs:23:71 | -23 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); +24 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D print-literal` implied by `-D warnings` @@ -9,79 +9,79 @@ error: literal with an empty format string error: literal with an empty format string --> $DIR/print_literal.rs:24:24 | -24 | print!("Hello {}", "world"); +25 | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:25:36 | -25 | println!("Hello {} {}", world, "world"); +26 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:26:26 | -26 | println!("Hello {}", "world"); +27 | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:27:30 | -27 | println!("10 / 4 is {}", 2.5); +28 | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string --> $DIR/print_literal.rs:28:28 | -28 | println!("2 + 1 = {}", 3); +29 | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string --> $DIR/print_literal.rs:33:25 | -33 | println!("{0} {1}", "hello", "world"); +34 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:33:34 | -33 | println!("{0} {1}", "hello", "world"); +34 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:34:25 | -34 | println!("{1} {0}", "hello", "world"); +35 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:34:34 | -34 | println!("{1} {0}", "hello", "world"); +35 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:37:33 | -37 | println!("{foo} {bar}", foo="hello", bar="world"); +38 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:37:46 | -37 | println!("{foo} {bar}", foo="hello", bar="world"); +38 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:38:33 | -38 | println!("{bar} {foo}", foo="hello", bar="world"); +39 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:38:46 | -38 | println!("{bar} {foo}", foo="hello", bar="world"); +39 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 70855ef8187..83dd70e4c18 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,7 +1,7 @@ error: literal with an empty format string --> $DIR/write_literal.rs:26:79 | -26 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); +27 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D write-literal` implied by `-D warnings` @@ -9,79 +9,79 @@ error: literal with an empty format string error: literal with an empty format string --> $DIR/write_literal.rs:27:32 | -27 | write!(&mut v, "Hello {}", "world"); +28 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:28:44 | -28 | writeln!(&mut v, "Hello {} {}", world, "world"); +29 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:29:34 | -29 | writeln!(&mut v, "Hello {}", "world"); +30 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:30:38 | -30 | writeln!(&mut v, "10 / 4 is {}", 2.5); +31 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string --> $DIR/write_literal.rs:31:36 | -31 | writeln!(&mut v, "2 + 1 = {}", 3); +32 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string --> $DIR/write_literal.rs:36:33 | -36 | writeln!(&mut v, "{0} {1}", "hello", "world"); +37 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:36:42 | -36 | writeln!(&mut v, "{0} {1}", "hello", "world"); +37 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:37:33 | -37 | writeln!(&mut v, "{1} {0}", "hello", "world"); +38 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:37:42 | -37 | writeln!(&mut v, "{1} {0}", "hello", "world"); +38 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:40:41 | -40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:40:54 | -40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:41:41 | -41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:41:54 | -41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 5446e73de6d9294c1a7a398a7508f9c44a388500 Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Wed, 25 Jul 2018 18:00:19 -0400 Subject: And the ones annotating the source file name. --- tests/ui/print_literal.stderr | 28 ++++++++++++++-------------- tests/ui/write_literal.stderr | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index eb0940881e9..cada26c6142 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,5 +1,5 @@ error: literal with an empty format string - --> $DIR/print_literal.rs:23:71 + --> $DIR/print_literal.rs:24:71 | 24 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ @@ -7,79 +7,79 @@ error: literal with an empty format string = note: `-D print-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/print_literal.rs:24:24 + --> $DIR/print_literal.rs:25:24 | 25 | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:25:36 + --> $DIR/print_literal.rs:26:36 | 26 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:26:26 + --> $DIR/print_literal.rs:27:26 | 27 | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:27:30 + --> $DIR/print_literal.rs:28:30 | 28 | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:28:28 + --> $DIR/print_literal.rs:29:28 | 29 | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/print_literal.rs:33:25 + --> $DIR/print_literal.rs:34:25 | 34 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:33:34 + --> $DIR/print_literal.rs:34:34 | 34 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:34:25 + --> $DIR/print_literal.rs:35:25 | 35 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:34:34 + --> $DIR/print_literal.rs:35:34 | 35 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:37:33 + --> $DIR/print_literal.rs:38:33 | 38 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:37:46 + --> $DIR/print_literal.rs:38:46 | 38 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:38:33 + --> $DIR/print_literal.rs:39:33 | 39 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:38:46 + --> $DIR/print_literal.rs:39:46 | 39 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 83dd70e4c18..d2e8ca94ed8 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,5 +1,5 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:26:79 + --> $DIR/write_literal.rs:27:79 | 27 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ @@ -7,79 +7,79 @@ error: literal with an empty format string = note: `-D write-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/write_literal.rs:27:32 + --> $DIR/write_literal.rs:28:32 | 28 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:28:44 + --> $DIR/write_literal.rs:29:44 | 29 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:29:34 + --> $DIR/write_literal.rs:30:34 | 30 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:30:38 + --> $DIR/write_literal.rs:31:38 | 31 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:31:36 + --> $DIR/write_literal.rs:32:36 | 32 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/write_literal.rs:36:33 + --> $DIR/write_literal.rs:37:33 | 37 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:36:42 + --> $DIR/write_literal.rs:37:42 | 37 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:37:33 + --> $DIR/write_literal.rs:38:33 | 38 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:37:42 + --> $DIR/write_literal.rs:38:42 | 38 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:40:41 + --> $DIR/write_literal.rs:41:41 | 41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:40:54 + --> $DIR/write_literal.rs:41:54 | 41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:41 + --> $DIR/write_literal.rs:42:41 | 42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:54 + --> $DIR/write_literal.rs:42:54 | 42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ -- cgit 1.4.1-3-g733a5 From 9b11be72c0fbc830291ab02b94470f7e95e84382 Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Wed, 25 Jul 2018 18:14:11 -0400 Subject: Fix copy-paste error --- tests/ui/write_literal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index fe1f83a2790..48dfcd0ea3e 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -11,7 +11,7 @@ fn main() { writeln!(&mut v, "Hello"); let world = "world"; writeln!(&mut v, "Hello {}", world); - writeln!(&mut v, "Hello {world}", world); + writeln!(&mut v, "Hello {world}", world=world); writeln!(&mut v, "3 in hex is {:X}", 3); writeln!(&mut v, "2 + 1 = {:.4}", 3); writeln!(&mut v, "2 + 1 = {:5.4}", 3); -- cgit 1.4.1-3-g733a5 From d7ddb2abba435aae10d4357ae299876795749265 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 28 Jul 2018 10:42:21 +0200 Subject: Add `use_self` comment --- clippy_lints/src/use_self.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 8c633423cf6..79da4c7d288 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -130,6 +130,10 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( None }; + // `impl_decl_ty` (of type `hir::Ty`) represents the type declared in the signature. + // `impl_ty` (of type `ty:TyS`) is the concrete type that the compiler has determined for + // that declaration. We use `impl_decl_ty` to see if the type was declared as `Self` + // and use `impl_ty` to check its concrete type. for (impl_decl_ty, (impl_ty, trait_ty)) in impl_decl.inputs.iter().chain(output_ty).zip( impl_method_sig .inputs_and_output -- cgit 1.4.1-3-g733a5 From 946340acfea9eda0c3405ecd6cf59bb274c00fb2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 28 Jul 2018 11:51:46 +0200 Subject: Fix ICE with 'while let (..) = x.iter()' --- clippy_lints/src/loops.rs | 14 ++++++++++---- tests/ui/while_loop.rs | 9 +++++++++ tests/ui/while_loop.stderr | 8 +++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b95bc01c013..023a8277827 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -488,12 +488,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); if method_path.ident.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) - && lhs_constructor.ident.name == "Some" && !is_refutable(cx, &pat_args[0]) - && !is_iterator_used_after_while_let(cx, iter_expr) - && !is_nested(cx, expr, &method_args[0]) + && lhs_constructor.ident.name == "Some" && ( + pat_args.is_empty() + || !is_refutable(cx, &pat_args[0]) + && !is_iterator_used_after_while_let(cx, iter_expr) + && !is_nested(cx, expr, &method_args[0])) { let iterator = snippet(cx, method_args[0].span, "_"); - let loop_var = snippet(cx, pat_args[0].span, "_"); + let loop_var = if pat_args.is_empty() { + "_".to_string() + } else { + snippet(cx, pat_args[0].span, "_").into_owned() + }; span_lint_and_sugg( cx, WHILE_LET_ON_ITERATOR, diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index b4c3eb0f58e..23a9ce80eb1 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -201,4 +201,13 @@ fn refutable() { while let Some(&value) = values.iter().next() { values.remove(&value); } + + // This should not cause an ICE and suggest: + // + // for _ in values.iter() {} + // + // See #2965 + while let Some(..) = values.iter().next() { + values.remove(&1); + } } diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index e495fefbdd8..d2b50b61e90 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -105,5 +105,11 @@ error: this loop could be written as a `for` loop 183 | while let Some(v) = y.next() { // use a for loop here | ^^^^^^^^ help: try: `for v in y { .. }` -error: aborting due to 11 previous errors +error: this loop could be written as a `for` loop + --> $DIR/while_loop.rs:210:26 + | +210 | while let Some(..) = values.iter().next() { + | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` + +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From be8863836e40d621fb15d72d0b919b4dc08bbb36 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 28 Jul 2018 13:54:49 +0200 Subject: CONTRIBUTING: mention discord channel. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 293418416a2..232752c2025 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lin Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how you can contribute and how to get started. If you have any questions about contributing or need help with anything, feel free to ask questions on issues or -visit the `#clippy` IRC channel on `irc.mozilla.org`. +visit the `#clippy` IRC channel on `irc.mozilla.org` or meet us in `#wg-clippy` on [Discord](https://discord.gg/rust-lang). All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). -- cgit 1.4.1-3-g733a5 From e0214397bdf0d48b7dcd520cd075d3a22092d823 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 27 Jul 2018 15:36:13 +0200 Subject: travis: run tests of external projects with --all-targets --all-features -- --cap-lints warn --- ci/base-tests.sh | 2 +- ci/integration-tests.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 4b304f6f2a6..69cd5abd925 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -7,7 +7,7 @@ mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver rm ~/.cargo/bin/cargo-clippy -PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy +PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- --cap-lints warn -D clippy cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index a989b261ac7..67ace0b5c88 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -8,9 +8,9 @@ git clone --depth=1 https://github.com/${INTEGRATION}.git checkout cd checkout function check() { - RUST_BACKTRACE=full cargo clippy --all &> clippy_output + RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn &> clippy_output cat clippy_output - ! cat clippy_output | grep -q "internal compiler error" + ! cat clippy_output | grep -q "internal compiler error\|query stack during panic" if [[ $? != 0 ]]; then return 1 fi -- cgit 1.4.1-3-g733a5 From a2343bfe7f2bcf1eba034a3a151a7a3a23c4ccc8 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 28 Jul 2018 12:14:35 +0200 Subject: integration tests: add more clippy warnings for greater coverage integration/base tests: add a few code comments --- ci/base-tests.sh | 9 ++++++++- ci/integration-tests.sh | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 69cd5abd925..13b652c0f7d 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,17 +1,24 @@ set -ex + +echo "Running clippy base tests" + PATH=$PATH:./node_modules/.bin remark -f *.md > /dev/null +# build clippy in debug mode and run tests cargo build --features debugging cargo test --features debugging mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver rm ~/.cargo/bin/cargo-clippy -PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- --cap-lints warn -D clippy +# run clippy on its own codebase... +PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy +# ... and some test directories cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../.. +# test --manifest-path PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../.. set +x diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 67ace0b5c88..ac0d2f1614b 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -8,7 +8,8 @@ git clone --depth=1 https://github.com/${INTEGRATION}.git checkout cd checkout function check() { - RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn &> clippy_output +# run clippy on a project, try to be verbose and trigger as many warnings as possible for greater coverage + RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn -W clippy_pedantic -W clippy_nursery &> clippy_output cat clippy_output ! cat clippy_output | grep -q "internal compiler error\|query stack during panic" if [[ $? != 0 ]]; then -- cgit 1.4.1-3-g733a5 From 0ea1afab3ae798c9337a51cde450c8363290afed Mon Sep 17 00:00:00 2001 From: Andrew Audibert Date: Sun, 29 Jul 2018 21:02:05 -0700 Subject: Lint using identity into_iter conversion --- clippy_lints/src/identity_conversion.rs | 14 ++++++++++++-- tests/ui/identity_conversion.rs | 3 +++ tests/ui/identity_conversion.stderr | 26 +++++++++++++++++++------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index a0705f62544..cf05583d85e 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -5,7 +5,7 @@ use syntax::ast::NodeId; use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; use crate::utils::{opt_def_id, paths, resolve_node}; -/// **What it does:** Checks for always-identical `Into`/`From` conversions. +/// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions. /// /// **Why is this bad?** Redundant code. /// @@ -19,7 +19,7 @@ use crate::utils::{opt_def_id, paths, resolve_node}; declare_clippy_lint! { pub IDENTITY_CONVERSION, complexity, - "using always-identical `Into`/`From` conversions" + "using always-identical `Into`/`From`/`IntoIter` conversions" } #[derive(Default)] @@ -67,6 +67,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { }); } } + if match_trait_method(cx, e, &paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" { + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + if same_tys(cx, a, b) { + let sugg = snippet(cx, args[0].span, "").into_owned(); + span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { + db.span_suggestion(e.span, "consider removing `.into_iter()`", sugg); + }); + } + } }, ExprKind::Call(ref path, ref args) => if let ExprKind::Path(ref qpath) = path.node { diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index d254b746d79..9ab81f1b1cb 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -32,9 +32,12 @@ fn main() { { let _: String = "foo".into(); let _ = String::from("foo"); + let _ = "".lines().into_iter(); } let _: String = "foo".to_string().into(); let _: String = From::from("foo".to_string()); let _ = String::from("foo".to_string()); + let _ = "".lines().into_iter(); + let _ = vec![1, 2, 3].into_iter().into_iter(); } diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 1ae3f229dd8..f7993d69c50 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -23,22 +23,34 @@ error: identical conversion | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:37:21 + --> $DIR/identity_conversion.rs:38:21 | -37 | let _: String = "foo".to_string().into(); +38 | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:38:21 + --> $DIR/identity_conversion.rs:39:21 | -38 | let _: String = From::from("foo".to_string()); +39 | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:39:13 + --> $DIR/identity_conversion.rs:40:13 | -39 | let _ = String::from("foo".to_string()); +40 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -error: aborting due to 6 previous errors +error: identical conversion + --> $DIR/identity_conversion.rs:41:13 + | +41 | let _ = "".lines().into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` + +error: identical conversion + --> $DIR/identity_conversion.rs:42:13 + | +42 | let _ = vec![1, 2, 3].into_iter().into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 9c53b1560cf5fdbd899df2696b40ca548c67dd53 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 31 Jul 2018 07:45:05 +0200 Subject: Fix unused_mut warning --- clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 84167553a54..d116ffafeac 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -241,7 +241,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match *o { Bool(b) => Some(Bool(!b)), Int(value) => { - let mut value = !value; + let value = !value; match ty.sty { ty::TyInt(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), ty::TyUint(ity) => Some(Int(clip(self.tcx, value, ity))), -- cgit 1.4.1-3-g733a5 From 74fcf7de4a4a1d650621835a8c9dd7342fbbe17d Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Tue, 31 Jul 2018 12:20:32 +0200 Subject: single_char_pattern: lint only on the argument span --- clippy_lints/src/methods.rs | 9 ++++---- tests/ui/single_char_pattern.rs | 2 ++ tests/ui/single_char_pattern.stderr | 44 +++++++++++++++++++++---------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 28ff303fc83..6850ef2f81d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1889,18 +1889,17 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi if let Some((Constant::Str(r), _)) = constant(cx, cx.tables, arg) { if r.len() == 1 { let c = r.chars().next().unwrap(); - let snip = snippet(cx, expr.span, ".."); + let snip = snippet(cx, arg.span, ".."); let hint = snip.replace( &format!("\"{}\"", c.escape_default()), &format!("'{}'", c.escape_default())); - span_lint_and_then( + span_lint_and_sugg( cx, SINGLE_CHAR_PATTERN, arg.span, "single-character string constant used as pattern", - |db| { - db.span_suggestion(expr.span, "try using a char instead", hint); - }, + "try using a char instead", + hint, ); } } diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 4f940c74896..73d00857415 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -40,4 +40,6 @@ fn main() { let h = HashSet::::new(); h.contains("X"); // should not warn + + x.replace(";", ",").split(","); // issue #2978 } diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 82d06ca90ac..1e7e9cf78cf 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -2,7 +2,7 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:5:13 | 5 | x.split("x"); - | --------^^^- help: try using a char instead: `x.split('x')` + | ^^^ help: try using a char instead: `'x'` | = note: `-D single-char-pattern` implied by `-D warnings` @@ -10,103 +10,109 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:22:16 | 22 | x.contains("x"); - | -----------^^^- help: try using a char instead: `x.contains('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:23:19 | 23 | x.starts_with("x"); - | --------------^^^- help: try using a char instead: `x.starts_with('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:24:17 | 24 | x.ends_with("x"); - | ------------^^^- help: try using a char instead: `x.ends_with('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:25:12 | 25 | x.find("x"); - | -------^^^- help: try using a char instead: `x.find('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:26:13 | 26 | x.rfind("x"); - | --------^^^- help: try using a char instead: `x.rfind('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:27:14 | 27 | x.rsplit("x"); - | ---------^^^- help: try using a char instead: `x.rsplit('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:28:24 | 28 | x.split_terminator("x"); - | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:29:25 | 29 | x.rsplit_terminator("x"); - | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:30:17 | 30 | x.splitn(0, "x"); - | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:31:18 | 31 | x.rsplitn(0, "x"); - | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:32:15 | 32 | x.matches("x"); - | ----------^^^- help: try using a char instead: `x.matches('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:33:16 | 33 | x.rmatches("x"); - | -----------^^^- help: try using a char instead: `x.rmatches('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:34:21 | 34 | x.match_indices("x"); - | ----------------^^^- help: try using a char instead: `x.match_indices('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:35:22 | 35 | x.rmatch_indices("x"); - | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:36:25 | 36 | x.trim_left_matches("x"); - | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:37:26 | 37 | x.trim_right_matches("x"); - | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:39:13 | 39 | x.split("/n"); - | --------^^^^- help: try using a char instead: `x.split('/n')` + | ^^^^ help: try using a char instead: `'/n'` -error: aborting due to 18 previous errors +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:44:31 + | +44 | x.replace(";", ",").split(","); // issue #2978 + | ^^^ help: try using a char instead: `','` + +error: aborting due to 19 previous errors -- cgit 1.4.1-3-g733a5 From 98dbce4fe4a6f63a4d1f9e2fdd6b2752ed097af4 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 1 Aug 2018 06:32:36 +0200 Subject: Fix E0502 warnings Fixes #2982 --- clippy_lints/src/lib.rs | 4 +++- clippy_lints/src/utils/hir_utils.rs | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b08449d2beb..4a23de3b8fd 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -366,9 +366,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); + + let target = ®.sess.target; reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef::new( conf.trivial_copy_size_limit, - ®.sess.target, + target, )); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2c5995f1327..57486b30d34 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -448,7 +448,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { CaptureClause::CaptureByValue => 0, CaptureClause::CaptureByRef => 1, }.hash(&mut self.s); - self.hash_expr(&self.cx.tcx.hir.body(eid).value); + let value = &self.cx.tcx.hir.body(eid).value; + self.hash_expr(value); }, ExprKind::Field(ref e, ref f) => { let c: fn(_, _) -> _ = ExprKind::Field; @@ -515,7 +516,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); let full_table = self.tables; self.tables = self.cx.tcx.body_tables(l_id.body); - self.hash_expr(&self.cx.tcx.hir.body(l_id.body).value); + let value = &self.cx.tcx.hir.body(l_id.body).value; + self.hash_expr(value); self.tables = full_table; }, ExprKind::Ret(ref e) => { -- cgit 1.4.1-3-g733a5 From 3851c0e22bbc6fe2508c6eff87d70da73ae4b1bc Mon Sep 17 00:00:00 2001 From: Andrew Audibert Date: Tue, 31 Jul 2018 23:53:45 -0700 Subject: Address build warning --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 6850ef2f81d..33c532e1729 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1885,7 +1885,7 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & } /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { +fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { if let Some((Constant::Str(r), _)) = constant(cx, cx.tables, arg) { if r.len() == 1 { let c = r.chars().next().unwrap(); -- cgit 1.4.1-3-g733a5 From c27cdcaf71fb9bb10d3da2ecd9e9d2def741ef9f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Aug 2018 21:33:33 -0700 Subject: Switch strategies for how rustc's workspace is unioned See rust-lang/rust#52919 for more details. --- Cargo.toml | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7c9fe251237..5b690040902 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,46 +45,6 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } regex = "1" semver = "0.9" -# Not actually needed right now but required to make sure that clippy/ and cargo build -# with the same set of features in rust-lang/rust -num-traits = "0.2" # enable the default feature -backtrace = "0.3" - -# keep in sync with `cargo`'s `Cargo.toml' -[target.'cfg(windows)'.dependencies.winapi] -version = "0.3" -features = [ - # keep in sync with `cargo`'s `Cargo.toml' - "handleapi", - "jobapi", - "jobapi2", - "minwindef", - "ntdef", - "ntstatus", - "processenv", - "processthreadsapi", - "psapi", - "synchapi", - "winerror", - "winbase", - "wincon", - "winnt", - # no idea where these come from - "basetsd", - "lmcons", - "memoryapi", - "minschannel", - "minwinbase", - "ntsecapi", - "profileapi", - "schannel", - "securitybaseapi", - "synchapi", - "sysinfoapi", - "timezoneapi", - "wincrypt", -] - [dev-dependencies] cargo_metadata = "0.5" compiletest_rs = "0.3.7" @@ -94,6 +54,11 @@ clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = "1.0" derive-new = "0.5" +# A noop dependency that changes in the Rust repository, it's a bit of a hack. +# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` +# for more information. +rustc-workspace-hack = "1.0.0" + [build-dependencies] rustc_version = "0.2.2" ansi_term = "0.11" -- cgit 1.4.1-3-g733a5 From 534d546c8102706d1b23de3cd060686b40a33151 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 2 Aug 2018 08:56:53 +0200 Subject: Fix #2979 --- clippy_lints/src/methods.rs | 19 ++++++++++++++---- tests/ui/methods.rs | 4 ++++ tests/ui/methods.stderr | 48 ++++++++++++++++++++++----------------------- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 33c532e1729..760c1a39bdd 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1047,10 +1047,21 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: return; } - // don't lint for constant values - let owner_def = cx.tcx.hir.get_parent_did(arg.id); - let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); - if promotable { + fn is_call(node: &hir::ExprKind) -> bool { + match node { + hir::ExprKind::AddrOf(_, expr) => { + is_call(&expr.node) + }, + hir::ExprKind::Call(..) + | hir::ExprKind::MethodCall(..) + // These variants are debatable or require further examination + | hir::ExprKind::If(..) + | hir::ExprKind::Match(..) => true, + _ => false, + } + } + + if !is_call(&arg.node) { return; } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 7f0da364c7a..220b08caaf7 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -389,6 +389,10 @@ fn expect_fun_call() { let with_dummy_type_and_as_str = Foo::new(); with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + //Issue #2979 - this should not lint + let msg = "bar"; + Some("foo").expect(msg); } /// Checks implementation of `ITER_NTH` lint diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 12665244b9d..a3b67bf9f6d 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -358,79 +358,79 @@ error: use of `expect` followed by a function call | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:402:23 + --> $DIR/methods.rs:406:23 | -402 | let bad_vec = some_vec.iter().nth(3); +406 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:403:26 + --> $DIR/methods.rs:407:26 | -403 | let bad_slice = &some_vec[..].iter().nth(3); +407 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:404:31 + --> $DIR/methods.rs:408:31 | -404 | let bad_boxed_slice = boxed_slice.iter().nth(3); +408 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:405:29 + --> $DIR/methods.rs:409:29 | -405 | let bad_vec_deque = some_vec_deque.iter().nth(3); +409 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:410:23 + --> $DIR/methods.rs:414:23 | -410 | let bad_vec = some_vec.iter_mut().nth(3); +414 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:413:26 + --> $DIR/methods.rs:417:26 | -413 | let bad_slice = &some_vec[..].iter_mut().nth(3); +417 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:416:29 + --> $DIR/methods.rs:420:29 | -416 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +420 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:428:13 + --> $DIR/methods.rs:432:13 | -428 | let _ = some_vec.iter().skip(42).next(); +432 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:429:13 + --> $DIR/methods.rs:433:13 | -429 | let _ = some_vec.iter().cycle().skip(42).next(); +433 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:430:13 + --> $DIR/methods.rs:434:13 | -430 | let _ = (1..10).skip(10).next(); +434 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:431:14 + --> $DIR/methods.rs:435:14 | -431 | let _ = &some_vec[..].iter().skip(3).next(); +435 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:440:13 + --> $DIR/methods.rs:444:13 | -440 | let _ = opt.unwrap(); +444 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 08d6b3d2f60e30eafafc4886202cd8221187cc98 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Thu, 2 Aug 2018 17:57:49 +1000 Subject: Allow pass by ref when returning ADT with ref This is a follow-up to #2951 that extends the logic to allow for returning references inside structs/enums/unions. This was a simple oversight in the first version and it's surprisingly easy to handle. --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 10 ++--- tests/ui/trivially_copy_pass_by_ref.rs | 17 +++++++++ tests/ui/trivially_copy_pass_by_ref.stderr | 52 +++++++++++++------------- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 6a048b19213..a01a1c5ae31 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -124,10 +124,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { // Use lifetimes to determine if we're returning a reference to the // argument. In that case we can't switch to pass-by-value as the // argument will not live long enough. - let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty { - Some(output_lt) - } else { - None + let output_lts = match fn_sig.output().sty { + TypeVariants::TyRef(output_lt, _, _) => vec![output_lt], + TypeVariants::TyAdt(_, substs) => substs.regions().collect(), + _ => vec![], }; for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { if_chain! { if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty; - if Some(input_lt) != output_lt; + if !output_lts.contains(&input_lt); if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.limit; diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index c6773add244..9b905e8d628 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -6,6 +6,10 @@ struct Foo(u32); #[derive(Copy, Clone)] struct Bar([u8; 24]); +struct FooRef<'a> { + foo: &'a Foo, +} + type Baz = u32; fn good(a: &mut u32, b: u32, c: &Bar) { @@ -20,6 +24,19 @@ fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { &foo.0 } +fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { + FooRef { + foo, + } +} + +#[allow(needless_lifetimes)] +fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> { + FooRef { + foo, + } +} + fn bad(x: &u32, y: &Foo, z: &Baz) { } diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index db25cc5a020..757b6b4c9a9 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:11 + --> $DIR/trivially_copy_pass_by_ref.rs:40:11 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:20 + --> $DIR/trivially_copy_pass_by_ref.rs:40:20 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:29 + --> $DIR/trivially_copy_pass_by_ref.rs:40:29 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:12 + --> $DIR/trivially_copy_pass_by_ref.rs:50:12 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:22 + --> $DIR/trivially_copy_pass_by_ref.rs:50:22 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:31 + --> $DIR/trivially_copy_pass_by_ref.rs:50:31 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:40 + --> $DIR/trivially_copy_pass_by_ref.rs:50:40 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:16 + --> $DIR/trivially_copy_pass_by_ref.rs:53:16 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:25 + --> $DIR/trivially_copy_pass_by_ref.rs:53:25 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:34 + --> $DIR/trivially_copy_pass_by_ref.rs:53:34 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:16 + --> $DIR/trivially_copy_pass_by_ref.rs:67:16 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:25 + --> $DIR/trivially_copy_pass_by_ref.rs:67:25 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:34 + --> $DIR/trivially_copy_pass_by_ref.rs:67:34 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 1afb7e895b1c3dc028cdaf2972eef760eb934992 Mon Sep 17 00:00:00 2001 From: reujab Date: Thu, 2 Aug 2018 11:52:46 -0400 Subject: removed colon --- clippy_lints/src/methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 33c532e1729..9a6d3df3088 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -383,7 +383,7 @@ declare_clippy_lint! { /// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified /// function syntax instead (e.g. `Rc::clone(foo)`). /// -/// **Why is this bad?**: Calling '.clone()' on an Rc, Arc, or Weak +/// **Why is this bad?** Calling '.clone()' on an Rc, Arc, or Weak /// can obscure the fact that only the pointer is being cloned, not the underlying /// data. /// -- cgit 1.4.1-3-g733a5 From f43d0e53b2f572b5509424d267556d185c2d80e2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 2 Aug 2018 10:06:03 -0700 Subject: Make indexing_slicing a restriction lint (fixes #2933) --- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 677f59d32cc..2ad31de0a17 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -80,7 +80,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub INDEXING_SLICING, - pedantic, + restriction, "indexing/slicing usage" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4a23de3b8fd..31a28c2a063 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -407,6 +407,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { arithmetic::INTEGER_ARITHMETIC, assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, + indexing_slicing::INDEXING_SLICING, inherent_impl::MULTIPLE_INHERENT_IMPL, literal_representation::DECIMAL_LITERAL_REPRESENTATION, mem_forget::MEM_FORGET, @@ -437,7 +438,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, - indexing_slicing::INDEXING_SLICING, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, -- cgit 1.4.1-3-g733a5 From 40349b23ea1730f9a5ef4056edf4854908073a48 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Aug 2018 13:00:14 -0700 Subject: Fix breakage from rust-lang/rust#52949 --- clippy_lints/src/redundant_field_names.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 20 ++------------------ 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 4f28d36e2a8..27f890ccd90 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use rustc::hir::*; -use crate::utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg}; +use crate::utils::{in_macro, match_var, span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { // Ignore all macros including range expressions. // They can have redundant field names when expanded. // e.g. range expression `start..end` is desugared to `Range { start: start, end: end }` - if in_macro(expr.span) || is_range_expression(expr.span) { + if in_macro(expr.span) { return; } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0b2103ca7ea..a8c20ef4fa3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -19,7 +19,7 @@ use std::str::FromStr; use std::rc::Rc; use syntax::ast::{self, LitKind}; use syntax::attr; -use syntax::codemap::{CompilerDesugaringKind, ExpnFormat, Span, DUMMY_SP}; +use syntax::codemap::{Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; use syntax::symbol::keywords; @@ -58,23 +58,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { - span.ctxt().outer().expn_info().map_or(false, |info| { - match info.format { - // don't treat range expressions desugared to structs as "in_macro" - ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, - _ => true, - } - }) -} - -/// Returns true if `expn_info` was expanded by range expressions. -pub fn is_range_expression(span: Span) -> bool { - span.ctxt().outer().expn_info().map_or(false, |info| { - match info.format { - ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::DotFill) => true, - _ => false, - } - }) + span.ctxt().outer().expn_info().is_some() } /// Check if a `DefId`'s path matches the given absolute type path usage. -- cgit 1.4.1-3-g733a5 From 12f2d61fa97fd963b2612f5a7cf918aa838203df Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 30 May 2018 18:24:44 +0200 Subject: Replace cfg_attr(rustfmt... thingies --- clippy_lints/src/lib.rs | 3 ++- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/methods.rs | 6 +++--- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- tests/needless_continue_helpers.rs | 12 +++++++----- tests/trim_multiline.rs | 6 ++++-- 8 files changed, 20 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 31a28c2a063..478b9055125 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,6 +11,7 @@ #![allow(stable_features)] #![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] +#![feature(tool_attributes)] #![feature(rust_2018_preview)] #![warn(rust_2018_idioms)] @@ -180,7 +181,7 @@ pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &m store.register_pre_expansion_pass(Some(session), box write::Pass); } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { let conf = match utils::conf::file_from_args(reg.args()) { Ok(file_name) => { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index db449d7c6a2..61c35dc33b0 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1787,7 +1787,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> { /// Return true if the type of expr is one that provides `IntoIterator` impls /// for `&T` and `&mut T`, such as `Vec`. -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6bdcd004134..c12389a0a1f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -199,7 +199,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { } } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9a6d3df3088..45e0795e9d2 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1955,7 +1955,7 @@ enum Convention { StartsWith(&'static str), } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ (Convention::Eq("new"), &[SelfKind::No]), (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), @@ -1965,7 +1965,7 @@ const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ (Convention::StartsWith("to_"), &[SelfKind::Ref]), ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), @@ -1999,7 +1999,7 @@ const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] const PATTERN_METHODS: [(&str, usize); 17] = [ ("contains", 1), ("starts_with", 1), diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index eeb131959e9..f731b376474 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] format!( "impl Default for {} {{ fn default() -> Self {{ diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index e9688262c2a..08d10d8e454 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -89,7 +89,7 @@ struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> { // this list contains lists of names that are allowed to be similar // the assumption is that no name is ever contained in multiple lists. -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] const WHITELIST: &[&[&str]] = &[ &["parsed", "parser"], &["lhs", "rhs"], diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 588dc741d03..f608ef1ad02 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,3 +1,5 @@ +#![feature(tool_attributes)] + // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. @@ -5,7 +7,7 @@ extern crate clippy_lints; use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_erode_from_back() { let input = "\ { @@ -23,7 +25,7 @@ fn test_erode_from_back() { } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_erode_from_back_no_brace() { let input = "\ let x = 5; @@ -35,7 +37,7 @@ let y = something(); } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_erode_from_front() { let input = " { @@ -54,7 +56,7 @@ fn test_erode_from_front() { } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_erode_from_front_no_brace() { let input = " something(); @@ -70,7 +72,7 @@ fn test_erode_from_front_no_brace() { } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_erode_block() { let input = " diff --git a/tests/trim_multiline.rs b/tests/trim_multiline.rs index d6de36bfca7..a61eee40928 100644 --- a/tests/trim_multiline.rs +++ b/tests/trim_multiline.rs @@ -1,3 +1,5 @@ +#![feature(tool_attributes)] + /// test the multiline-trim function extern crate clippy_lints; @@ -13,7 +15,7 @@ fn test_single_line() { } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_block() { assert_eq!("\ if x { @@ -38,7 +40,7 @@ if x { } #[test] -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn test_empty_line() { assert_eq!("\ if x { -- cgit 1.4.1-3-g733a5 From ae6ea849240436f83ac0ca74f22d03bb35891f26 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Aug 2018 14:14:48 -0700 Subject: Fix tests from 40349b23ea --- tests/ui/matches.stderr | 10 +--------- tests/ui/redundant_field_names.stderr | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 5bfc3271c45..61c13056cca 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -33,15 +33,7 @@ error: you seem to be trying to use match for destructuring a single pattern. Co 41 | | &(v, 1) => println!("{}", v), 42 | | _ => println!("none"), 43 | | } - | |_____^ -help: try this - | -40 | if let &(v, 1) = tup { -41 | # [ cfg ( not ( stage0 ) ) ] { -42 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; } # [ -43 | cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( $ ( $ arg ) * ) ) } } else { -44 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; } - | + | |_____^ help: try this: `if let &(v, 1) = tup { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; } else { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; }` error: you don't need to add `&` to all patterns --> $DIR/matches.rs:40:5 diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index d757f1871a7..4f706d1fe08 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -12,6 +12,36 @@ error: redundant field names in struct initialization 35 | age: age, | ^^^^^^^^ help: replace it with: `age` +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:45:13 + | +45 | let _ = start..; + | ^^^^^ help: replace it with: `start` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:46:15 + | +46 | let _ = ..end; + | ^^^ help: replace it with: `end` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:47:13 + | +47 | let _ = start..end; + | ^^^^^ help: replace it with: `start` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:47:20 + | +47 | let _ = start..end; + | ^^^ help: replace it with: `end` + +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:49:16 + | +49 | let _ = ..=end; + | ^^^ help: replace it with: `end` + error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:53:25 | @@ -42,5 +72,5 @@ error: redundant field names in struct initialization 57 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` -error: aborting due to 7 previous errors +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From 8ef759e0273ad97f1acbb1ea9f94322aa2a20147 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Aug 2018 18:08:22 -0700 Subject: Fix fallout from rust-lang/rust#52841 --- clippy_lints/src/utils/mod.rs | 3 ++- tests/ui/author/for_loop.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a8c20ef4fa3..0bb06fce593 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -941,7 +941,8 @@ pub fn opt_def_id(def: Def) -> Option { Def::AssociatedExistential(id) | Def::GlobalAsm(id) => Some(id), - Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, + Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | + Def::ToolMod | Def::NonMacroAttr | Def::Err => None, } } diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index 5faf440676d..026aee4746d 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] +#![feature(tool_attributes, stmt_expr_attributes)] fn main() { #[clippy::author] -- cgit 1.4.1-3-g733a5 From 55672e7e496118ec2c59a4190464b7837d3dcfa4 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 3 Aug 2018 10:19:29 +0200 Subject: Fix single_char_pattern lint for escaped chars --- clippy_lints/src/methods.rs | 5 +---- tests/ui/single_char_pattern.rs | 1 + tests/ui/single_char_pattern.stderr | 8 +++++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9a6d3df3088..bbf1f984d31 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1888,11 +1888,8 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { if let Some((Constant::Str(r), _)) = constant(cx, cx.tables, arg) { if r.len() == 1 { - let c = r.chars().next().unwrap(); let snip = snippet(cx, arg.span, ".."); - let hint = snip.replace( - &format!("\"{}\"", c.escape_default()), - &format!("'{}'", c.escape_default())); + let hint = format!("'{}'", &snip[1..snip.len() - 1]); span_lint_and_sugg( cx, SINGLE_CHAR_PATTERN, diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 73d00857415..577a0e27090 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -42,4 +42,5 @@ fn main() { h.contains("X"); // should not warn x.replace(";", ",").split(","); // issue #2978 + x.starts_with("\x03"); // issue #2996 } diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 1e7e9cf78cf..044b4909a37 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -114,5 +114,11 @@ error: single-character string constant used as pattern 44 | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` -error: aborting due to 19 previous errors +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:45:19 + | +45 | x.starts_with("/x03"); // issue #2996 + | ^^^^^^ help: try using a char instead: `'/x03'` + +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From 0ff762f7cd89b3e3c93e971e392f7cac84ac4730 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 3 Aug 2018 10:14:25 -0700 Subject: Rustup to 59fa6bd6c --- clippy_lints/src/consts.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d116ffafeac..7bccdd7778b 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -426,7 +426,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use rustc::mir::interpret::{Scalar, ConstValue}; + use rustc::mir::interpret::{Scalar, ScalarMaybeUndef, ConstValue}; match result.val { ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { ty::TyBool => Some(Constant::Bool(b == 1)), @@ -436,7 +436,9 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' // FIXME: implement other conversion _ => None, }, - ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty { + ConstValue::ScalarPair(Scalar::Ptr(ptr), + ScalarMaybeUndef::Scalar( + Scalar::Bits { bits: n, .. })) => match result.ty.sty { ty::TyRef(_, tam, _) => match tam.sty { ty::TyStr => { let alloc = tcx -- cgit 1.4.1-3-g733a5 From 99dcc70dcdd8760cb5c4de56f3701920339b6f29 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 5 Aug 2018 09:35:08 +1200 Subject: Fix error in `CrateType` in latest Rust --- clippy_lints/src/missing_inline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index e19ec4da67e..e80a0a1d8c3 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -87,7 +87,7 @@ fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool { cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| { match t { - CrateType::CrateTypeExecutable => true, + CrateType::Executable => true, _ => false, } }) -- cgit 1.4.1-3-g733a5 From ffce3c77e4e1dd997b1713e0c2bf151e612fc313 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 6 Aug 2018 08:20:50 +0200 Subject: Fix #3000 --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 40 ++++++++++++++----------------- tests/ui/redundant_field_names.stderr | 32 +------------------------ tests/ui/trivially_copy_pass_by_ref.rs | 2 +- 4 files changed, 21 insertions(+), 55 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 31a28c2a063..5b6b362fdfc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -178,6 +178,7 @@ mod reexport { pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore) { store.register_pre_expansion_pass(Some(session), box write::Pass); + store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); } #[cfg_attr(rustfmt, rustfmt_skip)] @@ -390,7 +391,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); - reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); reg.register_early_lint_pass(box multiple_crate_versions::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_late_lint_pass(box infallible_destructuring_match::Pass); diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 27f890ccd90..c5cf35edabe 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use rustc::hir::*; -use crate::utils::{in_macro, match_var, span_lint_and_sugg}; +use syntax::ast::*; +use crate::utils::{span_lint_and_sugg}; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -35,28 +35,24 @@ impl LintPass for RedundantFieldNames { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - // Ignore all macros including range expressions. - // They can have redundant field names when expanded. - // e.g. range expression `start..end` is desugared to `Range { start: start, end: end }` - if in_macro(expr.span) { - return; - } - +impl EarlyLintPass for RedundantFieldNames { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::Struct(_, ref fields, _) = expr.node { for field in fields { - let name = field.ident.name; - - if match_var(&field.expr, name) && !field.is_shorthand { - span_lint_and_sugg ( - cx, - REDUNDANT_FIELD_NAMES, - field.span, - "redundant field names in struct initialization", - "replace it with", - name.to_string() - ); + if field.is_shorthand { + continue; + } + if let ExprKind::Path(None, path) = &field.expr.node { + if path.segments.len() == 1 && path.segments[0].ident == field.ident { + span_lint_and_sugg ( + cx, + REDUNDANT_FIELD_NAMES, + field.span, + "redundant field names in struct initialization", + "replace it with", + field.ident.to_string() + ); + } } } } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 4f706d1fe08..d757f1871a7 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -12,36 +12,6 @@ error: redundant field names in struct initialization 35 | age: age, | ^^^^^^^^ help: replace it with: `age` -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:45:13 - | -45 | let _ = start..; - | ^^^^^ help: replace it with: `start` - -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:46:15 - | -46 | let _ = ..end; - | ^^^ help: replace it with: `end` - -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:47:13 - | -47 | let _ = start..end; - | ^^^^^ help: replace it with: `start` - -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:47:20 - | -47 | let _ = start..end; - | ^^^ help: replace it with: `end` - -error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:49:16 - | -49 | let _ = ..=end; - | ^^^ help: replace it with: `end` - error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:53:25 | @@ -72,5 +42,5 @@ error: redundant field names in struct initialization 57 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 9b905e8d628..a1a1de1e439 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,4 +1,4 @@ -#![allow(many_single_char_names, blacklisted_name)] +#![allow(many_single_char_names, blacklisted_name, redundant_field_names)] #[derive(Copy, Clone)] struct Foo(u32); -- cgit 1.4.1-3-g733a5 From 1a310bfdf74be9e140c21d4e88a7ce726fa4a6b4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 6 Aug 2018 15:10:48 +0200 Subject: Remove #[allow(rust_2018_idioms)] workaround --- clippy_lints/src/utils/conf.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index a27013344d8..c1ac058a83e 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -77,15 +77,6 @@ lazy_static! { macro_rules! define_Conf { ($(#[$doc: meta] ($rust_name: ident, $rust_name_str: expr, $default: expr => $($ty: tt)+),)+) => { pub use self::helpers::Conf; - // FIXME(mati865): remove #[allow(rust_2018_idioms)] when it's fixed: - // - // warning: `extern crate` is not idiomatic in the new edition - // --> src/utils/conf.rs:82:22 - // | - // 82 | #[derive(Deserialize)] - // | ^^^^^^^^^^^ help: convert it to a `use` - // - #[allow(rust_2018_idioms)] mod helpers { use serde_derive::Deserialize; /// Type used to store lint configuration. -- cgit 1.4.1-3-g733a5 From 7a5ede677b7642f098fd5fd69272c742d13e4ea4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 6 Aug 2018 15:42:08 +0200 Subject: Use Option::map_or --- clippy_lints/src/mem_forget.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 88c24458646..80130de15d7 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -37,10 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.tables.expr_ty(&args[0]); - if match forgot_ty.ty_adt_def() { - Some(def) => def.has_dtor(cx.tcx), - _ => false, - } { + if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } } -- cgit 1.4.1-3-g733a5 From a3d7698fd95977df3cdd551bc0f078aabcae20f9 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 7 Aug 2018 05:37:11 +0200 Subject: Fix #2971 --- clippy_lints/src/identity_conversion.rs | 2 +- tests/ui/identity_conversion.rs | 1 + tests/ui/identity_conversion.stderr | 14 ++++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index cf05583d85e..1909f2f8ff4 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { - let sugg = snippet(cx, args[0].span, "").into_owned(); + let sugg = snippet(cx, args[0].span.source_callsite(), "").into_owned(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { db.span_suggestion(e.span, &sugg_msg, sugg); diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 9ab81f1b1cb..8f5bd12bc9f 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -38,6 +38,7 @@ fn main() { let _: String = "foo".to_string().into(); let _: String = From::from("foo".to_string()); let _ = String::from("foo".to_string()); + let _ = String::from(format!("A: {:04}", 123)); let _ = "".lines().into_iter(); let _ = vec![1, 2, 3].into_iter().into_iter(); } diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index f7993d69c50..7083b96e16f 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -43,14 +43,20 @@ error: identical conversion error: identical conversion --> $DIR/identity_conversion.rs:41:13 | -41 | let _ = "".lines().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` +41 | let _ = String::from(format!("A: {:04}", 123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion --> $DIR/identity_conversion.rs:42:13 | -42 | let _ = vec![1, 2, 3].into_iter().into_iter(); +42 | let _ = "".lines().into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` + +error: identical conversion + --> $DIR/identity_conversion.rs:43:13 + | +43 | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 73e097e9f123cae64b276290985f65f21c766217 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 7 Aug 2018 00:05:09 -0700 Subject: Fix the build after https://github.com/rust-lang/rust/pull/53016 In-band lifetimes are no longer in the edition, so update the one place that was using them. --- clippy_lints/src/write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0b52981bfa5..d8bbf0098d2 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -217,7 +217,7 @@ impl EarlyLintPass for Pass { } } -fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option { +fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option { let tts = TokenStream::from(tts.clone()); let mut parser = parser::Parser::new( &cx.sess.parse_sess, -- cgit 1.4.1-3-g733a5 From 328fea3e0d491f5251062bf3aa9eb8ee2a21c55a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 7 Aug 2018 16:34:17 +0200 Subject: Rustup --- clippy_lints/src/utils/mod.rs | 4 ++-- tests/ui/infinite_iter.rs | 2 +- tests/ui/range.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0bb06fce593..0cacf81f860 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -938,8 +938,8 @@ pub fn opt_def_id(def: Def) -> Option { Def::AssociatedConst(id) | Def::Macro(id, ..) | Def::Existential(id) | - Def::AssociatedExistential(id) | - Def::GlobalAsm(id) => Some(id), + Def::AssociatedExistential(id) + => Some(id), Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::ToolMod | Def::NonMacroAttr | Def::Err => None, diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 2e2ccd9f1ae..a7841416671 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,4 +1,4 @@ -#![feature(iterator_for_each)] + use std::iter::repeat; #[allow(trivially_copy_pass_by_ref)] diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 611a324f6e3..7291fd5d5d3 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,4 +1,4 @@ -#![feature(iterator_step_by)] + struct NotARange; impl NotARange { -- cgit 1.4.1-3-g733a5 From 550ff84ecdb16bfb059fe0fab69e6788890a5bbb Mon Sep 17 00:00:00 2001 From: Evan Simmons Date: Tue, 7 Aug 2018 12:01:10 -0800 Subject: Allow print/write with multiple newlines --- clippy_lints/src/write.rs | 12 ++++++------ tests/ui/print_with_newline.rs | 5 ++++- tests/ui/print_with_newline.stderr | 12 ++++++------ tests/ui/write_with_newline.rs | 6 ++++-- tests/ui/write_with_newline.stderr | 12 ++++++------ 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d8bbf0098d2..ca987eb0bae 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub PRINT_WITH_NEWLINE, style, - "using `print!()` with a format string that ends in a newline" + "using `print!()` with a format string that ends in a single newline" } /// **What it does:** Checks for printing on *stdout*. The purpose of this lint @@ -127,7 +127,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub WRITE_WITH_NEWLINE, style, - "using `write!()` with a format string that ends in a newline" + "using `write!()` with a format string that ends in a single newline" } /// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args. @@ -186,18 +186,18 @@ impl EarlyLintPass for Pass { } else if mac.node.path == "print" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { - if fmtstr.ends_with("\\n") { + if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { span_lint(cx, PRINT_WITH_NEWLINE, mac.span, "using `print!()` with a format string that ends in a \ - newline, consider using `println!()` instead"); + single newline, consider using `println!()` instead"); } } } else if mac.node.path == "write" { if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) { - if fmtstr.ends_with("\\n") { + if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { span_lint(cx, WRITE_WITH_NEWLINE, mac.span, "using `write!()` with a format string that ends in a \ - newline, consider using `writeln!()` instead"); + single newline, consider using `writeln!()` instead"); } } } else if mac.node.path == "writeln" { diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 5445c862096..906fa987d17 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -6,7 +6,7 @@ fn main() { print!("Hello\n"); print!("Hello {}\n", "world"); - print!("Hello {} {}\n\n", "world", "#2"); + print!("Hello {} {}\n", "world", "#2"); print!("{}\n", 1265); // these are all fine @@ -18,4 +18,7 @@ fn main() { print!("Issue\n{}", 1265); print!("{}", 1265); print!("\n{}", 1275); + print!("\n\n"); + print!("like eof\n\n"); + print!("Hello {} {}\n\n", "world", "#2"); } diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 181f16b5cb7..58413a9b4a9 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,4 +1,4 @@ -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead +error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:7:5 | 7 | print!("Hello/n"); @@ -6,19 +6,19 @@ error: using `print!()` with a format string that ends in a newline, consider us | = note: `-D print-with-newline` implied by `-D warnings` -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead +error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:8:5 | 8 | print!("Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead +error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:9:5 | -9 | print!("Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +9 | print!("Hello {} {}/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead +error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:10:5 | 10 | print!("{}/n", 1265); diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 0427bd3ec04..8badbd65726 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -9,7 +9,7 @@ fn main() { // These should fail write!(&mut v, "Hello\n"); write!(&mut v, "Hello {}\n", "world"); - write!(&mut v, "Hello {} {}\n\n", "world", "#2"); + write!(&mut v, "Hello {} {}\n", "world", "#2"); write!(&mut v, "{}\n", 1265); // These should be fine @@ -21,5 +21,7 @@ fn main() { write!(&mut v, "Issue\n{}", 1265); write!(&mut v, "{}", 1265); write!(&mut v, "\n{}", 1275); - + write!(&mut v, "\n\n"); + write!(&mut v, "like eof\n\n"); + write!(&mut v, "Hello {} {}\n\n", "world", "#2"); } diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 7bb9b99731f..a8a6039f3e1 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,4 +1,4 @@ -error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead +error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:10:5 | 10 | write!(&mut v, "Hello/n"); @@ -6,19 +6,19 @@ error: using `write!()` with a format string that ends in a newline, consider us | = note: `-D write-with-newline` implied by `-D warnings` -error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead +error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:11:5 | 11 | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead +error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:12:5 | -12 | write!(&mut v, "Hello {} {}/n/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +12 | write!(&mut v, "Hello {} {}/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead +error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:13:5 | 13 | write!(&mut v, "{}/n", 1265); -- cgit 1.4.1-3-g733a5 From b109e1033476390f95c728d674909ef90f0ff0ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 8 Aug 2018 18:00:23 +1200 Subject: Fix build --- clippy_lints/src/use_self.rs | 3 +-- clippy_lints/src/utils/internal_lints.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 79da4c7d288..eb2b4e801eb 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -5,7 +5,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; use rustc::{declare_lint, lint_array}; -use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a @@ -208,7 +207,7 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { - fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) { + fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfType.name() { span_use_self_lint(self.cx, path); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 32aee099177..226817c8e51 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -5,7 +5,7 @@ use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::utils::{match_qpath, paths, span_lint}; use syntax::symbol::LocalInternedString; -use syntax::ast::{Crate as AstCrate, ItemKind, Name, NodeId}; +use syntax::ast::{Crate as AstCrate, ItemKind, Name}; use syntax::codemap::Span; use std::collections::{HashMap, HashSet}; @@ -198,7 +198,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { walk_expr(self, expr); } - fn visit_path(&mut self, path: &'tcx Path, _: NodeId) { + fn visit_path(&mut self, path: &'tcx Path, _: HirId) { if path.segments.len() == 1 { self.output.insert(path.segments[0].ident.name); } -- cgit 1.4.1-3-g733a5 From 99a087bea59c8f808b5485c6113edf9ce774e94a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 8 Aug 2018 13:18:25 +0200 Subject: Update to rustc master --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0cacf81f860..32a891c8cbb 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -942,7 +942,7 @@ pub fn opt_def_id(def: Def) -> Option { => Some(id), Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | - Def::ToolMod | Def::NonMacroAttr | Def::Err => None, + Def::ToolMod | Def::NonMacroAttr{..} | Def::Err => None, } } -- cgit 1.4.1-3-g733a5 From 9bb68b84ab55a808d64a7889fe90b70cdfa07e1e Mon Sep 17 00:00:00 2001 From: David Vo Date: Thu, 9 Aug 2018 17:29:22 +1000 Subject: lintlib: Use Python 3 compatible print Ref: #2882 --- util/lintlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/lintlib.py b/util/lintlib.py index 00826805e16..c386a94b18b 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -44,7 +44,7 @@ def parse_lints(lints, filepath): last_comment.append(line[3:]) elif line.startswith("declare_lint!"): import sys - print "don't use `declare_lint!` in Clippy, use `declare_clippy_lint!` instead" + print("don't use `declare_lint!` in Clippy, use `declare_clippy_lint!` instead") sys.exit(42) elif line.startswith("declare_clippy_lint!"): comment = False -- cgit 1.4.1-3-g733a5 From ed1667b7bc0d49fef8cfff75fea22c60c545a233 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 9 Aug 2018 09:41:32 +0200 Subject: Version checks are useless now that we ride the trains --- Cargo.toml | 4 --- build.rs | 87 --------------------------------------------------------- min_version.txt | 7 ----- 3 files changed, 98 deletions(-) delete mode 100644 min_version.txt diff --git a/Cargo.toml b/Cargo.toml index 5b690040902..798b713a07f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,9 +59,5 @@ derive-new = "0.5" # for more information. rustc-workspace-hack = "1.0.0" -[build-dependencies] -rustc_version = "0.2.2" -ansi_term = "0.11" - [features] debugging = [] diff --git a/build.rs b/build.rs index 9d05678f718..3b9f217c884 100644 --- a/build.rs +++ b/build.rs @@ -13,98 +13,11 @@ //! This build script was originally taken from the Rocket web framework: //! https://github.com/SergioBenitez/Rocket -use ansi_term::Colour::Red; -use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; use std::env; fn main() { - check_rustc_version(); - // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); // Don't rebuild even if nothing changed println!("cargo:rerun-if-changed=build.rs"); } - -fn check_rustc_version() { - let string = include_str!("min_version.txt"); - let min_version_meta = version_meta_for(string).expect("Could not parse version string in min_version.txt"); - let current_version_meta = version_meta().expect("Could not retrieve current rustc version information from ENV"); - - let min_version = min_version_meta.clone().semver; - let min_date_str = min_version_meta - .clone() - .commit_date - .expect("min_version.txt does not contain a rustc commit date"); - - // Dev channel (rustc built from git) does not have any date or commit information in rustc -vV - // `current_version_meta.commit_date` would crash, so we return early here. - if current_version_meta.channel == Channel::Dev { - return; - } - - let current_version = current_version_meta.clone().semver; - let current_date_str = current_version_meta - .clone() - .commit_date - .expect("current rustc version information does not contain a rustc commit date"); - - let print_version_err = |version: &Version, date: &str| { - eprintln!( - "> {} {}. {} {}.\n", - "Installed rustc version is:", - format!("{} ({})", version, date), - "Minimum required rustc version:", - format!("{} ({})", min_version, min_date_str) - ); - }; - - if !correct_channel(¤t_version_meta) { - eprintln!( - "\n{} {}", - Red.bold().paint("error:"), - "Clippy requires a nightly version of Rust." - ); - print_version_err(¤t_version, &*current_date_str); - eprintln!( - "{}{}{}", - "See the README (", "https://github.com/rust-lang-nursery/rust-clippy#usage", ") for more information." - ); - panic!("Aborting compilation due to incompatible compiler.") - } - - let current_date = str_to_ymd(¤t_date_str).unwrap(); - let min_date = str_to_ymd(&min_date_str).unwrap(); - - if current_date < min_date { - eprintln!( - "\n{} {}", - Red.bold().paint("error:"), - "Clippy does not support this version of rustc nightly." - ); - eprintln!( - "> {}{}{}", - "Use `", "rustup update", "` or your preferred method to update Rust." - ); - print_version_err(¤t_version, &*current_date_str); - panic!("Aborting compilation due to incompatible compiler.") - } -} - -fn correct_channel(version_meta: &VersionMeta) -> bool { - match version_meta.channel { - Channel::Stable | Channel::Beta => false, - Channel::Nightly | Channel::Dev => true, - } -} - -/// Convert a string of %Y-%m-%d to a single u32 maintaining ordering. -fn str_to_ymd(ymd: &str) -> Option { - let ymd: Vec = ymd.split("-").filter_map(|s| s.parse::().ok()).collect(); - if ymd.len() != 3 { - return None; - } - - let (y, m, d) = (ymd[0], ymd[1], ymd[2]); - Some((y << 9) | (m << 5) | d) -} diff --git a/min_version.txt b/min_version.txt deleted file mode 100644 index bd6a57973fc..00000000000 --- a/min_version.txt +++ /dev/null @@ -1,7 +0,0 @@ -rustc 1.28.0-nightly (e3bf634e0 2018-06-28) -binary: rustc -commit-hash: e3bf634e060bc2f8665878288bcea02008ca346e -commit-date: 2018-06-28 -host: x86_64-unknown-linux-gnu -release: 1.28.0-nightly -LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 14207503a80083e2b4ea6eabada46fbc8db27682 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 9 Aug 2018 09:41:32 +0200 Subject: Version checks are useless now that we ride the trains --- Cargo.toml | 4 --- build.rs | 87 --------------------------------------------------------- min_version.txt | 7 ----- 3 files changed, 98 deletions(-) delete mode 100644 min_version.txt diff --git a/Cargo.toml b/Cargo.toml index 5b690040902..798b713a07f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,9 +59,5 @@ derive-new = "0.5" # for more information. rustc-workspace-hack = "1.0.0" -[build-dependencies] -rustc_version = "0.2.2" -ansi_term = "0.11" - [features] debugging = [] diff --git a/build.rs b/build.rs index 9d05678f718..3b9f217c884 100644 --- a/build.rs +++ b/build.rs @@ -13,98 +13,11 @@ //! This build script was originally taken from the Rocket web framework: //! https://github.com/SergioBenitez/Rocket -use ansi_term::Colour::Red; -use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; use std::env; fn main() { - check_rustc_version(); - // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); // Don't rebuild even if nothing changed println!("cargo:rerun-if-changed=build.rs"); } - -fn check_rustc_version() { - let string = include_str!("min_version.txt"); - let min_version_meta = version_meta_for(string).expect("Could not parse version string in min_version.txt"); - let current_version_meta = version_meta().expect("Could not retrieve current rustc version information from ENV"); - - let min_version = min_version_meta.clone().semver; - let min_date_str = min_version_meta - .clone() - .commit_date - .expect("min_version.txt does not contain a rustc commit date"); - - // Dev channel (rustc built from git) does not have any date or commit information in rustc -vV - // `current_version_meta.commit_date` would crash, so we return early here. - if current_version_meta.channel == Channel::Dev { - return; - } - - let current_version = current_version_meta.clone().semver; - let current_date_str = current_version_meta - .clone() - .commit_date - .expect("current rustc version information does not contain a rustc commit date"); - - let print_version_err = |version: &Version, date: &str| { - eprintln!( - "> {} {}. {} {}.\n", - "Installed rustc version is:", - format!("{} ({})", version, date), - "Minimum required rustc version:", - format!("{} ({})", min_version, min_date_str) - ); - }; - - if !correct_channel(¤t_version_meta) { - eprintln!( - "\n{} {}", - Red.bold().paint("error:"), - "Clippy requires a nightly version of Rust." - ); - print_version_err(¤t_version, &*current_date_str); - eprintln!( - "{}{}{}", - "See the README (", "https://github.com/rust-lang-nursery/rust-clippy#usage", ") for more information." - ); - panic!("Aborting compilation due to incompatible compiler.") - } - - let current_date = str_to_ymd(¤t_date_str).unwrap(); - let min_date = str_to_ymd(&min_date_str).unwrap(); - - if current_date < min_date { - eprintln!( - "\n{} {}", - Red.bold().paint("error:"), - "Clippy does not support this version of rustc nightly." - ); - eprintln!( - "> {}{}{}", - "Use `", "rustup update", "` or your preferred method to update Rust." - ); - print_version_err(¤t_version, &*current_date_str); - panic!("Aborting compilation due to incompatible compiler.") - } -} - -fn correct_channel(version_meta: &VersionMeta) -> bool { - match version_meta.channel { - Channel::Stable | Channel::Beta => false, - Channel::Nightly | Channel::Dev => true, - } -} - -/// Convert a string of %Y-%m-%d to a single u32 maintaining ordering. -fn str_to_ymd(ymd: &str) -> Option { - let ymd: Vec = ymd.split("-").filter_map(|s| s.parse::().ok()).collect(); - if ymd.len() != 3 { - return None; - } - - let (y, m, d) = (ymd[0], ymd[1], ymd[2]); - Some((y << 9) | (m << 5) | d) -} diff --git a/min_version.txt b/min_version.txt deleted file mode 100644 index bd6a57973fc..00000000000 --- a/min_version.txt +++ /dev/null @@ -1,7 +0,0 @@ -rustc 1.28.0-nightly (e3bf634e0 2018-06-28) -binary: rustc -commit-hash: e3bf634e060bc2f8665878288bcea02008ca346e -commit-date: 2018-06-28 -host: x86_64-unknown-linux-gnu -release: 1.28.0-nightly -LLVM version: 6.0 -- cgit 1.4.1-3-g733a5 From 66ca3954ec25e201826556ddec94bfd103332fea Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 11 Aug 2018 23:07:04 +0200 Subject: fix 2 clippy warnings --- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/non_copy_const.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 23b34362171..8a58f2681d6 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { fn check(cx: &LateContext<'_, '_>, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { let check = match cx.tables.expr_ty(e).sty { - ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity), + ty::TyInt(ity) => unsext(cx.tcx, -1_i128, ity), ty::TyUint(uty) => clip(cx.tcx, !0, uty), _ => return, }; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index f2c9210aae4..119b4c2d861 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -244,9 +244,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { } } - let ty = if !needs_check_adjustment { - cx.tables.expr_ty(dereferenced_expr) - } else { + let ty = if needs_check_adjustment { let adjustments = cx.tables.expr_adjustments(dereferenced_expr); if let Some(i) = adjustments.iter().position(|adj| match adj.kind { Adjust::Borrow(_) | Adjust::Deref(_) => true, @@ -261,6 +259,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { // No borrow adjustments = the entire const is moved. return; } + } else { + cx.tables.expr_ty(dereferenced_expr) }; verify_ty_bound(cx, ty, Source::Expr { expr: expr.span }); -- cgit 1.4.1-3-g733a5 From 88d693918ff1874b6cfb7fbc9e2cd9bff389b96f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 12 Aug 2018 00:16:03 +0200 Subject: docs: add more suggestions on how to fix clippy findings to the online lint list. --- clippy_lints/src/len_zero.rs | 6 ++++++ clippy_lints/src/loops.rs | 8 ++++++++ clippy_lints/src/matches.rs | 9 +++++++++ clippy_lints/src/methods.rs | 4 ++-- clippy_lints/src/redundant_field_names.rs | 4 ++++ clippy_lints/src/returns.rs | 15 ++++++++++++++- clippy_lints/src/shadow.rs | 4 ++++ clippy_lints/src/write.rs | 8 ++++++++ 8 files changed, 55 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b73f912fad5..081450516bb 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -22,6 +22,12 @@ use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_su /// **Example:** /// ```rust /// if x.len() == 0 { .. } +/// if y.len() != 0 { .. } +/// ``` +/// instead use +/// ```rust +/// if x.len().is_empty() { .. } +/// if !y.len().is_empty() { .. } /// ``` declare_clippy_lint! { pub LEN_ZERO, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 61c35dc33b0..6d3134d2206 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -80,6 +80,10 @@ declare_clippy_lint! { /// // with `y` a `Vec` or slice: /// for x in y.iter() { .. } /// ``` +/// can be rewritten to +/// ```rust +/// for x in &y { .. } +/// ``` declare_clippy_lint! { pub EXPLICIT_ITER_LOOP, style, @@ -98,6 +102,10 @@ declare_clippy_lint! { /// // with `y` a `Vec` or slice: /// for x in y.into_iter() { .. } /// ``` +/// can be rewritten to +/// ```rust +/// for x in y { .. } +/// ``` declare_clippy_lint! { pub EXPLICIT_INTO_ITER_LOOP, style, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index c12389a0a1f..d42355f89f4 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -93,6 +93,15 @@ declare_clippy_lint! { /// false => bar(), /// } /// ``` +/// Use if/else instead: +/// ```rust +/// let condition: bool = true; +/// if condition { +/// foo(); +/// } else { +/// bar(); +/// } +/// ``` declare_clippy_lint! { pub MATCH_BOOL, style, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 25a8e73dd03..69df7f2a1c5 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -448,7 +448,7 @@ declare_clippy_lint! { /// **Known problems:** Does not catch multi-byte unicode characters. /// /// **Example:** -/// `_.split("x")` could be `_.split('x') +/// `_.split("x")` could be `_.split('x')` declare_clippy_lint! { pub SINGLE_CHAR_PATTERN, perf, @@ -468,7 +468,7 @@ declare_clippy_lint! { /// ```rust,ignore /// let c_str = CString::new("foo").unwrap().as_ptr(); /// unsafe { -/// call_some_ffi_func(c_str); +/// call_some_ffi_func(c_str); /// } /// ``` /// Here `c_str` point to a freed address. The correct use would be: diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index c5cf35edabe..ba8b11e55df 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -21,6 +21,10 @@ use crate::utils::{span_lint_and_sugg}; /// /// let foo = Foo{ bar: bar } /// ``` +/// the last line can be simplified to +/// ```rust +/// let foo = Foo{ bar } +/// ``` declare_clippy_lint! { pub REDUNDANT_FIELD_NAMES, style, diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 0ede1bc9727..b2202fb1eff 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -19,6 +19,10 @@ use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, sp /// ```rust /// fn foo(x: usize) { return x; } /// ``` +/// simplify to +/// ```rust +/// fn foo(x: usize) { x } +/// ``` declare_clippy_lint! { pub NEEDLESS_RETURN, style, @@ -35,7 +39,16 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// { let x = ..; x } +/// fn foo() -> String { +/// let x = String::new(); +/// x +///} +/// ``` +/// instead, use +/// ``` +/// fn foo() -> String { +/// String::new() +///} /// ``` declare_clippy_lint! { pub LET_AND_RETURN, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index aab578d6344..a6645e19f02 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -42,6 +42,10 @@ declare_clippy_lint! { /// ```rust /// let x = x + 1; /// ``` +/// use different variable name: +/// ```rust +/// let y = x + 1; +/// ``` declare_clippy_lint! { pub SHADOW_REUSE, restriction, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d8bbf0098d2..915ba832833 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -35,6 +35,10 @@ declare_clippy_lint! { /// ```rust /// print!("Hello {}!\n", name); /// ``` +/// use println!() instead +/// ```rust +/// println!("Hello {}!", name); +/// ``` declare_clippy_lint! { pub PRINT_WITH_NEWLINE, style, @@ -88,6 +92,10 @@ declare_clippy_lint! { /// ```rust /// println!("{}", "foo"); /// ``` +/// use the literal without formatting: +/// ```rust +/// println!("foo"); +/// ``` declare_clippy_lint! { pub PRINT_LITERAL, style, -- cgit 1.4.1-3-g733a5 From 7ded77fe7d771fae5eb862e14005a5aac4871405 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 12 Aug 2018 11:33:44 +0200 Subject: update_lints.py: port another print to print() for python3 compatibility. --- util/update_lints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/update_lints.py b/util/update_lints.py index 70d49f940ee..abc8e5dee98 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -107,7 +107,7 @@ def replace_region(fn, region_start, region_end, callback, new_lines.append(line) if not found: - print "regex " + region_start + " not found" + print("regex " + region_start + " not found") # write back to file if write_back: -- cgit 1.4.1-3-g733a5 From 8fc425b67681e4beaf0c34dc802f56c7b97bf658 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 10 Aug 2018 18:58:23 +0100 Subject: Add an internal lint for FxHashMap/FxHashSet --- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/utils/internal_lints.rs | 46 +++++++++++++++++++++++++++++++- tests/ui/fxhash.rs | 16 +++++++++++ tests/ui/fxhash.stderr | 40 +++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/ui/fxhash.rs create mode 100644 tests/ui/fxhash.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e0ef87938f9..82f974b724f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -266,6 +266,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box serde_api::Serde); reg.register_early_lint_pass(box utils::internal_lints::Clippy); reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); + reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::new()); reg.register_late_lint_pass(box utils::inspector::Pass); reg.register_late_lint_pass(box utils::author::Pass); reg.register_late_lint_pass(box types::TypePass); @@ -467,6 +468,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_lint_group("clippy_internal", vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::LINT_WITHOUT_LINT_PASS, + utils::internal_lints::DEFAULT_HASH_TYPES, ]); reg.register_lint_group("clippy", vec![ diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 226817c8e51..2e948ee6077 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -3,9 +3,10 @@ use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc_data_structures::fx::FxHashMap; use crate::utils::{match_qpath, paths, span_lint}; use syntax::symbol::LocalInternedString; -use syntax::ast::{Crate as AstCrate, ItemKind, Name}; +use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use syntax::codemap::Span; use std::collections::{HashMap, HashSet}; @@ -54,6 +55,18 @@ declare_clippy_lint! { } +/// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet" +/// and recommends the FxHash* variants. +/// +/// **Why is this bad?** The FxHash variants have better performance +/// and we don't need any collision prevention in clippy. +declare_clippy_lint! { + pub DEFAULT_HASH_TYPES, + internal, + "forbid HashMap and HashSet and suggest the FxHash* variants" +} + + #[derive(Copy, Clone)] pub struct Clippy; @@ -207,3 +220,34 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { NestedVisitorMap::All(&self.cx.tcx.hir) } } + + + +pub struct DefaultHashTypes { + map: FxHashMap, +} + +impl DefaultHashTypes { + pub fn new() -> Self { + let mut map = FxHashMap::default(); + map.insert("HashMap".to_owned(), "FxHashMap".to_owned()); + map.insert("HashSet".to_owned(), "FxHashSet".to_owned()); + Self { map } + } +} + +impl LintPass for DefaultHashTypes { + fn get_lints(&self) -> LintArray { + lint_array!(DEFAULT_HASH_TYPES) + } +} + +impl EarlyLintPass for DefaultHashTypes { + fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { + let ident_string = ident.to_string(); + if let Some(replace) = self.map.get(&ident_string) { + let msg = format!("Prefer {} over {}, it has better performance and we don't need any collision prevention in clippy", replace, ident_string); + cx.span_lint(DEFAULT_HASH_TYPES, ident.span, &msg); + } + } +} diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs new file mode 100644 index 00000000000..c6ed9436a51 --- /dev/null +++ b/tests/ui/fxhash.rs @@ -0,0 +1,16 @@ +#![warn(default_hash_types)] +#![feature(rustc_private)] + +extern crate rustc_data_structures; + +use std::collections::{HashMap, HashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; + +fn main() { + let _map: HashMap = HashMap::default(); + let _set: HashSet = HashSet::default(); + + // test that the lint doesn't also match the Fx variants themselves 😂 + let _fx_map: FxHashMap = FxHashMap::default(); + let _fx_set: FxHashSet = FxHashSet::default(); +} diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr new file mode 100644 index 00000000000..dc08ab88bac --- /dev/null +++ b/tests/ui/fxhash.stderr @@ -0,0 +1,40 @@ +error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:6:24 + | +6 | use std::collections::{HashMap, HashSet}; + | ^^^^^^^ + | + = note: `-D default-hash-types` implied by `-D warnings` + +error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:6:33 + | +6 | use std::collections::{HashMap, HashSet}; + | ^^^^^^^ + +error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:10:15 + | +10 | let _map: HashMap = HashMap::default(); + | ^^^^^^^ + +error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:10:41 + | +10 | let _map: HashMap = HashMap::default(); + | ^^^^^^^ + +error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:11:15 + | +11 | let _set: HashSet = HashSet::default(); + | ^^^^^^^ + +error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy + --> $DIR/fxhash.rs:11:33 + | +11 | let _set: HashSet = HashSet::default(); + | ^^^^^^^ + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From 1812707d39a9ec62581509638f438cb48e2af13f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 13 Aug 2018 08:23:07 +0100 Subject: Use utils::span_lint_and_sugg in default_hash_types --- clippy_lints/src/utils/internal_lints.rs | 4 ++-- tests/ui/fxhash.stderr | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 2e948ee6077..0da3ad83b84 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_data_structures::fx::FxHashMap; -use crate::utils::{match_qpath, paths, span_lint}; +use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg}; use syntax::symbol::LocalInternedString; use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use syntax::codemap::Span; @@ -247,7 +247,7 @@ impl EarlyLintPass for DefaultHashTypes { let ident_string = ident.to_string(); if let Some(replace) = self.map.get(&ident_string) { let msg = format!("Prefer {} over {}, it has better performance and we don't need any collision prevention in clippy", replace, ident_string); - cx.span_lint(DEFAULT_HASH_TYPES, ident.span, &msg); + span_lint_and_sugg(cx, DEFAULT_HASH_TYPES, ident.span, &msg, "use", replace.to_owned()); } } } diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index dc08ab88bac..5e90f84f1db 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -2,7 +2,7 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't nee --> $DIR/fxhash.rs:6:24 | 6 | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashMap` | = note: `-D default-hash-types` implied by `-D warnings` @@ -10,31 +10,31 @@ error: Prefer FxHashSet over HashSet, it has better performance and we don't nee --> $DIR/fxhash.rs:6:33 | 6 | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:10:15 | 10 | let _map: HashMap = HashMap::default(); - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:10:41 | 10 | let _map: HashMap = HashMap::default(); - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:11:15 | 11 | let _set: HashSet = HashSet::default(); - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:11:33 | 11 | let _set: HashSet = HashSet::default(); - | ^^^^^^^ + | ^^^^^^^ help: use: `FxHashSet` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 160b41dae358e0ec81973db686a0278037211fdb Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Thu, 9 Aug 2018 14:14:12 -0500 Subject: deprecate assign_ops lint --- clippy_lints/src/assign_ops.rs | 31 +------- clippy_lints/src/deprecated_lints.rs | 10 +++ clippy_lints/src/lib.rs | 5 +- tests/ui/assign_ops.rs | 24 +----- tests/ui/assign_ops.stderr | 140 ++++++++--------------------------- 5 files changed, 46 insertions(+), 164 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 1ce690abcfe..7d4f4e7cbc3 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -7,25 +7,6 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; -/// **What it does:** Checks for compound assignment operations (`+=` and -/// similar). -/// -/// **Why is this bad?** Projects with many developers from languages without -/// those operations may find them unreadable and not worth their weight. -/// -/// **Known problems:** Types implementing `OpAssign` don't necessarily -/// implement `Op`. -/// -/// **Example:** -/// ```rust -/// a += 1; -/// ``` -declare_clippy_lint! { - pub ASSIGN_OPS, - restriction, - "any compound assignment operation" -} - /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` /// patterns. /// @@ -73,7 +54,7 @@ pub struct AssignOps; impl LintPass for AssignOps { fn get_lints(&self) -> LintArray { - lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP) + lint_array!(ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP) } } @@ -81,16 +62,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { match expr.node { hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { - span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| { - let lhs = &sugg::Sugg::hir(cx, lhs, ".."); - let rhs = &sugg::Sugg::hir(cx, rhs, ".."); - - db.span_suggestion( - expr.span, - "replace it with", - format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)), - ); - }); if let hir::ExprKind::Binary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| { diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 1edeb30560c..983f347c56f 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -82,3 +82,13 @@ declare_deprecated_lint! { pub MISALIGNED_TRANSMUTE, "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr" } + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This lint is too subjective, not having a good reason for being in clippy. +/// Additionally, compound assignment operators may be overloaded separately from their non-assigning +/// counterparts, so this lint may suggest a change in behavior or the code may not compile. +declare_deprecated_lint! { + pub ASSIGN_OPS, + "using compound assignment operators (e.g. `+=`) is harmless" +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e0ef87938f9..66abacdf6e8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -261,6 +261,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { "misaligned_transmute", "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", ); + store.register_removed( + "assign_ops", + "using compound assignment operators (e.g. `+=`) is harmless", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); @@ -406,7 +410,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, - assign_ops::ASSIGN_OPS, else_if_without_else::ELSE_IF_WITHOUT_ELSE, indexing_slicing::INDEXING_SLICING, inherent_impl::MULTIPLE_INHERENT_IMPL, diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 2b49f2146ba..7332b41fa0b 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,28 +1,6 @@ - - - -#[warn(assign_ops)] -#[allow(unused_assignments)] -fn main() { - let mut i = 1i32; - i += 2; - i += 2 + 17; - i -= 6; - i -= 2 - 1; - i *= 5; - i *= 1+5; - i /= 32; - i /= 32 | 5; - i /= 32 / 5; - i %= 42; - i >>= i; - i <<= 9 + 6 - 7; - i += 1 << 5; -} - #[allow(dead_code, unused_assignments)] #[warn(assign_op_pattern)] -fn bla() { +fn main() { let mut a = 5; a = a + 1; a = 1 + a; diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 2123507e2ef..826dacc53a9 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,138 +1,58 @@ -error: assign operation detected - --> $DIR/assign_ops.rs:8:5 +error: manual implementation of an assign operation + --> $DIR/assign_ops.rs:5:5 | -8 | i += 2; - | ^^^^^^ help: replace it with: `i = i + 2` +5 | a = a + 1; + | ^^^^^^^^^ help: replace it with: `a += 1` | - = note: `-D assign-ops` implied by `-D warnings` - -error: assign operation detected - --> $DIR/assign_ops.rs:9:5 - | -9 | i += 2 + 17; - | ^^^^^^^^^^^ help: replace it with: `i = i + 2 + 17` - -error: assign operation detected - --> $DIR/assign_ops.rs:10:5 - | -10 | i -= 6; - | ^^^^^^ help: replace it with: `i = i - 6` - -error: assign operation detected - --> $DIR/assign_ops.rs:11:5 - | -11 | i -= 2 - 1; - | ^^^^^^^^^^ help: replace it with: `i = i - (2 - 1)` - -error: assign operation detected - --> $DIR/assign_ops.rs:12:5 - | -12 | i *= 5; - | ^^^^^^ help: replace it with: `i = i * 5` - -error: assign operation detected - --> $DIR/assign_ops.rs:13:5 - | -13 | i *= 1+5; - | ^^^^^^^^ help: replace it with: `i = i * (1+5)` - -error: assign operation detected - --> $DIR/assign_ops.rs:14:5 - | -14 | i /= 32; - | ^^^^^^^ help: replace it with: `i = i / 32` - -error: assign operation detected - --> $DIR/assign_ops.rs:15:5 - | -15 | i /= 32 | 5; - | ^^^^^^^^^^^ help: replace it with: `i = i / (32 | 5)` - -error: assign operation detected - --> $DIR/assign_ops.rs:16:5 - | -16 | i /= 32 / 5; - | ^^^^^^^^^^^ help: replace it with: `i = i / (32 / 5)` - -error: assign operation detected - --> $DIR/assign_ops.rs:17:5 - | -17 | i %= 42; - | ^^^^^^^ help: replace it with: `i = i % 42` - -error: assign operation detected - --> $DIR/assign_ops.rs:18:5 - | -18 | i >>= i; - | ^^^^^^^ help: replace it with: `i = i >> i` - -error: assign operation detected - --> $DIR/assign_ops.rs:19:5 - | -19 | i <<= 9 + 6 - 7; - | ^^^^^^^^^^^^^^^ help: replace it with: `i = i << (9 + 6 - 7)` - -error: assign operation detected - --> $DIR/assign_ops.rs:20:5 - | -20 | i += 1 << 5; - | ^^^^^^^^^^^ help: replace it with: `i = i + (1 << 5)` + = note: `-D assign-op-pattern` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:27:5 - | -27 | a = a + 1; - | ^^^^^^^^^ help: replace it with: `a += 1` - | - = note: `-D assign-op-pattern` implied by `-D warnings` - -error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:28:5 - | -28 | a = 1 + a; - | ^^^^^^^^^ help: replace it with: `a += 1` + --> $DIR/assign_ops.rs:6:5 + | +6 | a = 1 + a; + | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:29:5 - | -29 | a = a - 1; - | ^^^^^^^^^ help: replace it with: `a -= 1` + --> $DIR/assign_ops.rs:7:5 + | +7 | a = a - 1; + | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:30:5 - | -30 | a = a * 99; - | ^^^^^^^^^^ help: replace it with: `a *= 99` + --> $DIR/assign_ops.rs:8:5 + | +8 | a = a * 99; + | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:31:5 - | -31 | a = 42 * a; - | ^^^^^^^^^^ help: replace it with: `a *= 42` + --> $DIR/assign_ops.rs:9:5 + | +9 | a = 42 * a; + | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:32:5 + --> $DIR/assign_ops.rs:10:5 | -32 | a = a / 2; +10 | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:33:5 + --> $DIR/assign_ops.rs:11:5 | -33 | a = a % 5; +11 | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:34:5 + --> $DIR/assign_ops.rs:12:5 | -34 | a = a & 1; +12 | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:40:5 + --> $DIR/assign_ops.rs:18:5 | -40 | s = s + "bla"; +18 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` -error: aborting due to 22 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From a1f8e129fd24d9d596faf7502c3e6e39906b212b Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 14 Aug 2018 07:27:56 +0200 Subject: Add a test to ensure that #2799 is fixed Closes #2799 --- tests/ui/redundant_field_names.rs | 3 +++ tests/ui/redundant_field_names.stderr | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 095ac7c0cc1..dc8548754d2 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -49,6 +49,9 @@ fn main() { let _ = ..=end; let _ = start..=end; + // Issue #2799 + let _: Vec<_> = (start..end).collect(); + // hand-written Range family structs are linted let _ = RangeFrom { start: start }; let _ = RangeTo { end: end }; diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index d757f1871a7..5821baf4c85 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -13,33 +13,33 @@ error: redundant field names in struct initialization | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:53:25 + --> $DIR/redundant_field_names.rs:56:25 | -53 | let _ = RangeFrom { start: start }; +56 | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:54:23 + --> $DIR/redundant_field_names.rs:57:23 | -54 | let _ = RangeTo { end: end }; +57 | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:55:21 + --> $DIR/redundant_field_names.rs:58:21 | -55 | let _ = Range { start: start, end: end }; +58 | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:55:35 + --> $DIR/redundant_field_names.rs:58:35 | -55 | let _ = Range { start: start, end: end }; +58 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:57:32 + --> $DIR/redundant_field_names.rs:60:32 | -57 | let _ = RangeToInclusive { end: end }; +60 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 22ff5a3ef11202b6c21462d8d7dfbeeae31a12ed Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 14 Aug 2018 09:25:09 +0100 Subject: Avoid new_without_default_derive in DefaultHashTypes --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 82f974b724f..77c1c5c1499 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -266,7 +266,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box serde_api::Serde); reg.register_early_lint_pass(box utils::internal_lints::Clippy); reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); - reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::new()); + reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::default()); reg.register_late_lint_pass(box utils::inspector::Pass); reg.register_late_lint_pass(box utils::author::Pass); reg.register_late_lint_pass(box types::TypePass); diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 0da3ad83b84..260ced14cb4 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -228,7 +228,7 @@ pub struct DefaultHashTypes { } impl DefaultHashTypes { - pub fn new() -> Self { + pub fn default() -> Self { let mut map = FxHashMap::default(); map.insert("HashMap".to_owned(), "FxHashMap".to_owned()); map.insert("HashSet".to_owned(), "FxHashSet".to_owned()); -- cgit 1.4.1-3-g733a5 From 7933d445d1d24014afbd49840b46d3aab15cf34a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 9 Aug 2018 17:26:22 +0100 Subject: Move shadow_unrelated to pedantic --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- tests/ui/methods.stderr | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e0ef87938f9..0981c01892e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -422,7 +422,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, - shadow::SHADOW_UNRELATED, strings::STRING_ADD, write::PRINT_STDOUT, write::USE_DEBUG, @@ -452,6 +451,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { needless_continue::NEEDLESS_CONTINUE, non_expressive_names::SIMILAR_NAMES, replace_consts::REPLACE_CONSTS, + shadow::SHADOW_UNRELATED, strings::STRING_ADD_ASSIGN, types::CAST_POSSIBLE_TRUNCATION, types::CAST_POSSIBLE_WRAP, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index a6645e19f02..f04d7bf9867 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -71,7 +71,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub SHADOW_UNRELATED, - restriction, + pedantic, "rebinding a name without even using the original value" } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index a3b67bf9f6d..bf529ce9465 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -331,6 +331,24 @@ error: use of `unwrap_or` followed by a function call 343 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` +error: `error_code` is shadowed by `123_i32` + --> $DIR/methods.rs:377:9 + | +377 | let error_code = 123_i32; + | ^^^^^^^^^^ + | + = note: `-D shadow-unrelated` implied by `-D warnings` +note: initialization happens here + --> $DIR/methods.rs:377:22 + | +377 | let error_code = 123_i32; + | ^^^^^^^ +note: previous binding is here + --> $DIR/methods.rs:364:9 + | +364 | let error_code = 123_i32; + | ^^^^^^^^^^ + error: use of `expect` followed by a function call --> $DIR/methods.rs:366:26 | @@ -435,5 +453,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D option-unwrap-used` implied by `-D warnings` -error: aborting due to 55 previous errors +error: aborting due to 56 previous errors -- cgit 1.4.1-3-g733a5 From bac76afb5a7885de19bfd9e6191fe8e2a29bd74d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 14 Aug 2018 11:26:28 -0700 Subject: Rustup to rustc 1.30.0-nightly (23f09bbed 2018-08-14) --- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/copies.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f1596476bfd..ef6f71f6831 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; -use syntax::util::ThinVec; +use rustc_data_structures::thin_vec::ThinVec; use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait}; /// **What it does:** Checks for boolean expressions that can be written more diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 5709526c600..49518d1bb4e 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; use syntax::symbol::LocalInternedString; -use syntax::util::small_vector::SmallVector; +use rustc_data_structures::small_vec::OneVector; use crate::utils::{SpanlessEq, SpanlessHash}; use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; @@ -233,9 +233,9 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { /// sequence of `if/else`. /// Eg. would return `([a, b], [c, d, e])` for the expression /// `if a { c } else if b { d } else { e }`. -fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { - let mut conds = SmallVector::new(); - let mut blocks: SmallVector<&Block> = SmallVector::new(); +fn if_sequence(mut expr: &Expr) -> (OneVector<&Expr>, OneVector<&Block>) { + let mut conds = OneVector::new(); + let mut blocks: OneVector<&Block> = OneVector::new(); while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.node { conds.push(&**cond); -- cgit 1.4.1-3-g733a5 From bbd67c9b78f41ddead23fd03ea5d8d613cb96b45 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 15 Aug 2018 08:11:07 +0200 Subject: Fix #2927 --- clippy_lints/src/lib.rs | 32 +++++++++++++++++------------- clippy_lints/src/non_expressive_names.rs | 9 ++++----- src/driver.rs | 6 ++++-- src/lib.rs | 3 ++- tests/ui/non_expressive_names.rs | 7 ++++++- tests/ui/non_expressive_names.stderr | 34 +++++++------------------------- 6 files changed, 41 insertions(+), 50 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9776287cc75..680ff2c9600 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -173,18 +173,14 @@ pub mod write; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` +use crate::utils::conf::Conf; + mod reexport { crate use syntax::ast::{Name, NodeId}; } -pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore) { - store.register_pre_expansion_pass(Some(session), box write::Pass); - store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); -} - -#[rustfmt::skip] -pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { - let conf = match utils::conf::file_from_args(reg.args()) { +pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { + match utils::conf::file_from_args(reg.args()) { Ok(file_name) => { // if the user specified a file, it must exist, otherwise default to `clippy.toml` but // do not require the file to exist @@ -226,8 +222,19 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { .emit(); toml::from_str("").expect("we never error on empty config files") } - }; + } +} +pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore, conf: &Conf) { + store.register_pre_expansion_pass(Some(session), box write::Pass); + store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); + store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold: conf.single_char_binding_names_threshold, + }); +} + +#[rustfmt::skip] +pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { let mut store = reg.sess.lint_store.borrow_mut(); store.register_removed( "should_assert_eq", @@ -329,9 +336,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box vec::Pass); - reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold: conf.single_char_binding_names_threshold, - }); reg.register_late_lint_pass(box drop_forget_ref::Pass); reg.register_late_lint_pass(box empty_enum::EmptyEnum); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); @@ -347,9 +351,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) { reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); - reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names)); + reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone())); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); - reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents)); + reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_forget::MemForget); diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 08d10d8e454..3401fbca171 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -5,7 +5,7 @@ use syntax::symbol::LocalInternedString; use syntax::ast::*; use syntax::attr; use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; -use crate::utils::{in_macro, span_lint, span_lint_and_then}; +use crate::utils::{span_lint, span_lint_and_then}; /// **What it does:** Checks for names that are very similar and thus confusing. /// @@ -147,9 +147,6 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } } fn check_name(&mut self, span: Span, name: Name) { - if in_macro(span) { - return; - } let interned_name = name.as_str(); if interned_name.chars().any(char::is_uppercase) { return; @@ -309,6 +306,9 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { fn visit_item(&mut self, _: &Item) { // do not recurse into inner items } + fn visit_mac(&mut self, _mac: &Mac) { + // do not check macs + } } impl EarlyLintPass for NonExpressiveNames { @@ -323,7 +323,6 @@ impl EarlyLintPass for NonExpressiveNames { do_check(self, cx, &item.attrs, &sig.decl, blk); } } - } fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { diff --git a/src/driver.rs b/src/driver.rs index e9e81bb88e3..659287daed5 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -96,7 +96,9 @@ pub fn main() { .span, ); registry.args_hidden = Some(Vec::new()); - clippy_lints::register_plugins(&mut registry); + + let conf = clippy_lints::read_conf(®istry); + clippy_lints::register_plugins(&mut registry, &conf); let rustc_plugin::registry::Registry { early_lint_passes, @@ -118,7 +120,7 @@ pub fn main() { for (name, to) in lint_groups { ls.register_group(Some(sess), true, name, to); } - clippy_lints::register_pre_expansion_lints(sess, &mut ls); + clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); sess.plugin_attributes.borrow_mut().extend(attributes); diff --git a/src/lib.rs b/src/lib.rs index 1123c968006..c2363fef907 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,8 @@ pub fn plugin_registrar(reg: &mut Registry<'_>) { } }); - clippy_lints::register_plugins(reg); + let conf = clippy_lints::read_conf(reg); + clippy_lints::register_plugins(reg, &conf); } // only exists to let the dogfood integration test works. diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 19f0889a92c..7149bf8f3e7 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,7 +1,7 @@ #![warn(clippy,similar_names)] -#![allow(unused)] +#![allow(unused, println_empty_string)] struct Foo { @@ -142,6 +142,11 @@ fn underscores_and_numbers() { let _1_ok= 1; } +fn issue2927() { + let args = 1; + format!("{:?}", 2); +} + struct Bar; impl Bar { diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index c63b493db8d..b4927e69e67 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,23 +1,3 @@ -error: using `println!("")` - --> $DIR/non_expressive_names.rs:60:14 - | -60 | _ => println!(""), - | ^^^^^^^^^^^^ help: replace it with: `println!()` - | - = note: `-D println-empty-string` implied by `-D warnings` - -error: using `println!("")` - --> $DIR/non_expressive_names.rs:128:18 - | -128 | 1 => println!(""), - | ^^^^^^^^^^^^ help: replace it with: `println!()` - -error: using `println!("")` - --> $DIR/non_expressive_names.rs:132:18 - | -132 | 1 => println!(""), - | ^^^^^^^^^^^^ help: replace it with: `println!()` - error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:18:9 | @@ -170,22 +150,22 @@ error: consider choosing a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:149:13 + --> $DIR/non_expressive_names.rs:154:13 | -149 | let _1 = 1; +154 | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:150:13 + --> $DIR/non_expressive_names.rs:155:13 | -150 | let ____1 = 1; +155 | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:151:13 + --> $DIR/non_expressive_names.rs:156:13 | -151 | let __1___2 = 12; +156 | let __1___2 = 12; | ^^^^^^^ -error: aborting due to 20 previous errors +error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From 1c681b6ab63fabae44f28c1cb6dfb31319d27d77 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 16 Aug 2018 07:13:52 +0200 Subject: fix-2927: Update formatting --- clippy_lints/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 680ff2c9600..3de7c6de979 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -179,6 +179,14 @@ mod reexport { crate use syntax::ast::{Name, NodeId}; } +pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore, conf: &Conf) { + store.register_pre_expansion_pass(Some(session), box write::Pass); + store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); + store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold: conf.single_char_binding_names_threshold, + }); +} + pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { match utils::conf::file_from_args(reg.args()) { Ok(file_name) => { @@ -225,14 +233,6 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { } } -pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore, conf: &Conf) { - store.register_pre_expansion_pass(Some(session), box write::Pass); - store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); - store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold: conf.single_char_binding_names_threshold, - }); -} - #[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { let mut store = reg.sess.lint_store.borrow_mut(); -- cgit 1.4.1-3-g733a5 From 6cb94630fb6220240730e2bed8d82f80a107696d Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Thu, 16 Aug 2018 18:20:06 +0200 Subject: WIP of #3016 for hardocded suggestion for writeln on empty string --- clippy_lints/src/write.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index e8c7225041f..9b0b25f3921 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -179,7 +179,7 @@ impl EarlyLintPass for Pass { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) { if mac.node.path == "println" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`"); - if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 { if fmtstr == "" { span_lint_and_sugg( cx, @@ -193,7 +193,7 @@ impl EarlyLintPass for Pass { } } else if mac.node.path == "print" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); - if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) { + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 { if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { span_lint(cx, PRINT_WITH_NEWLINE, mac.span, "using `print!()` with a format string that ends in a \ @@ -201,7 +201,7 @@ impl EarlyLintPass for Pass { } } } else if mac.node.path == "write" { - if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) { + if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 { if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { span_lint(cx, WRITE_WITH_NEWLINE, mac.span, "using `write!()` with a format string that ends in a \ @@ -209,15 +209,16 @@ impl EarlyLintPass for Pass { } } } else if mac.node.path == "writeln" { - if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) { + let check_tts = check_tts(cx, &mac.node.tts, true); + if let Some(fmtstr) = check_tts.0 { if fmtstr == "" { span_lint_and_sugg( cx, WRITELN_EMPTY_STRING, mac.span, - "using `writeln!(v, \"\")`", + format!("using `writeln!({}, \"\")`", check_tts.1).as_str(), "replace it with", - "writeln!(v)".to_string(), + format!("using `writeln!({})`", check_tts.1), ); } } @@ -225,7 +226,7 @@ impl EarlyLintPass for Pass { } } -fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option { +fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { let tts = TokenStream::from(tts.clone()); let mut parser = parser::Parser::new( &cx.sess.parse_sess, @@ -234,12 +235,14 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - false, false, ); - if is_write { - // skip the initial write target - parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; - // might be `writeln!(foo)` - parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?; - } + // skip the initial write target + let expr: Option = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { + Some(p) => Some(p.into_vec().0), + None => None, + }; + // might be `writeln!(foo)` + parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?; + let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string(); use fmt_macros::*; let tmp = fmtstr.clone(); @@ -247,7 +250,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let mut fmt_parser = Parser::new(&tmp, None); while let Some(piece) = fmt_parser.next() { if !fmt_parser.errors.is_empty() { - return None; + return (None, expr); } if let Piece::NextArgument(arg) = piece { if arg.format.ty == "?" { @@ -266,7 +269,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - loop { if !parser.eat(&token::Comma) { assert!(parser.eat(&token::Eof)); - return Some(fmtstr); + return (Some(fmtstr), expr); } let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; const SIMPLE: FormatSpec<'_> = FormatSpec { -- cgit 1.4.1-3-g733a5 From 76321d3300e0047351fafdfd8e93a15b5a0c1065 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 19 Aug 2018 19:06:53 -0700 Subject: codemap -> source_map https://github.com/rust-lang/rust/pull/52953 --- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/methods.rs | 4 ++-- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early.rs | 4 ++-- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- clippy_lints/src/precedence.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/utils/conf.rs | 6 +++--- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 6 +++--- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 8 ++++---- clippy_lints/src/utils/usage.rs | 2 +- clippy_lints/src/vec.rs | 2 +- tests/matches.rs | 2 +- 52 files changed, 61 insertions(+), 61 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index b3d78d2d13f..90f72d3d184 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Span; +use syntax::source_map::Span; /// **What it does:** Checks for plain integer arithmetic. /// diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 3d25f524afd..9804d3a0f07 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -12,7 +12,7 @@ use if_chain::if_chain; use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; -use syntax::codemap::Span; +use syntax::source_map::Span; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 249ebbde2f7..12de4faa753 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast::LitKind; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{span_lint, span_lint_and_then}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ef6f71f6831..eda6a045cba 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -3,7 +3,7 @@ use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; -use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; +use syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; use rustc_data_structures::thin_vec::ThinVec; use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait}; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index d66e6f2849b..67cd37bee37 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -7,7 +7,7 @@ use rustc::hir::*; use rustc::ty; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, NodeId}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 0689ef25c20..5aeca29f6d8 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -3,7 +3,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 2b11e8fa77d..12128eda258 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -3,7 +3,7 @@ use pulldown_cmark; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use syntax_pos::Pos; use crate::utils::span_lint; use url::Url; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 434ccb69921..013a75e6457 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 517befa7790..ef5d18f081a 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use crate::consts::{constant, Constant}; use crate::utils::paths; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 26ee6be5796..142a099f539 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -3,7 +3,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 6f8afc710de..90cc1716cc1 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -5,7 +5,7 @@ use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::NodeId; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::span_lint; /// **What it does:** Checks for `use Enum::*`. diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 16c9212e5db..ca38d497df4 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::symbol::LocalInternedString; use crate::utils::{span_help_and_lint, span_lint}; use crate::utils::{camel_case_from, camel_case_until, in_macro}; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 4960a48b3c8..2976700428c 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -2,7 +2,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{in_macro, span_lint}; /// **What it does:** Checks for erasing operations, e.g. `x * 0`. diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index ebbc2c34811..2cd2a46cbab 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -9,7 +9,7 @@ use rustc::ty::{self, Ty}; use rustc::ty::layout::LayoutOf; use rustc::util::nodemap::NodeSet; use syntax::ast::NodeId; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::span_lint; pub struct Pass { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 8903766c330..b86e3332188 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -8,7 +8,7 @@ use rustc::hir::def::Def; use std::collections::HashSet; use syntax::ast; use rustc_target::spec::abi::Abi; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// **What it does:** Checks for functions with too many parameters. diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 8a58f2681d6..939039e93ca 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -2,7 +2,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; use rustc::ty; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 081450516bb..ce063518880 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -5,7 +5,7 @@ use rustc::{declare_lint, lint_array}; use rustc::ty; use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; -use syntax::codemap::{Span, Spanned}; +use syntax::source_map::{Span, Spanned}; use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for getting the length of something via `.len()` diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index cf7a016231e..d8e6a43f864 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -6,7 +6,7 @@ use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::*; use std::collections::{HashMap, HashSet}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{last_path_segment, span_lint}; use syntax::symbol::keywords; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6d3134d2206..3dacb3cd422 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -18,7 +18,7 @@ use rustc::ty::subst::Subst; use std::collections::{HashMap, HashSet}; use std::iter::{once, Iterator}; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{sugg, sext}; use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 6ccf8daa71d..7cbed82d5c7 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -4,7 +4,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use crate::utils::paths; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index d42355f89f4..84ab72777e4 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -6,7 +6,7 @@ use rustc::ty::{self, Ty}; use std::cmp::Ordering; use std::collections::Bound; use syntax::ast::LitKind; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::paths; use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 69df7f2a1c5..ceb1307dfed 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -9,7 +9,7 @@ use std::borrow::Cow; use std::fmt; use std::iter; use syntax::ast; -use syntax::codemap::{Span, BytePos}; +use syntax::source_map::{Span, BytePos}; use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, @@ -1311,7 +1311,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: then { // Span containing `.fold(...)` - let next_point = cx.sess().codemap().next_point(fold_args[0].span); + let next_point = cx.sess().source_map().next_point(fold_args[0].span); let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1)); let sugg = if replacement_has_args { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index b01d24a1ad3..fc9b72ba949 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; -use syntax::codemap::{ExpnFormat, Span}; +use syntax::source_map::{ExpnFormat, Span}; use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 9b8e0743f39..6c82fa58e8d 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use std::collections::HashMap; use std::char; use syntax::ast::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::visit::FnKind; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; @@ -235,7 +235,7 @@ impl EarlyLintPass for MiscEarly { for field in pfields { match field.node.pat.node { PatKind::Wild => {}, - _ => if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) { + _ => if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { normal.push(n); }, } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index fe2bbbdb9af..9735799d136 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -24,7 +24,7 @@ use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast; use syntax::attr; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::in_macro; /// **What it does:** Warns if there is missing doc for any documentable item diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index e80a0a1d8c3..8e2b08b5152 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -13,7 +13,7 @@ use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; /// **What it does:** it lints if an exported function, method, trait method with default impl, /// or trait method impl is not `#[inline]`. diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 559aa74f9a2..19d860dab36 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::LitKind; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use crate::utils::{snippet, span_lint, span_lint_and_sugg}; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 60ab0eaae02..0c9b354035f 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -30,7 +30,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast; -use syntax::codemap::{original_sp, DUMMY_SP}; +use syntax::source_map::{original_sp, DUMMY_SP}; use std::borrow::Cow; use crate::utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index c056ff46178..2b0c021ea03 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use syntax::codemap::{Span, Spanned}; +use syntax::source_map::{Span, Spanned}; use crate::consts::{self, Constant}; use crate::utils::span_lint; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index f731b376474..77b945f48fd 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::paths; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; use crate::utils::sugg::DiagnosticBuilderExt; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 3401fbca171..acfa341ed1f 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::symbol::LocalInternedString; use syntax::ast::*; use syntax::attr; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index effeb88d0cf..ac399e238b6 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -2,7 +2,7 @@ use rustc::hir::{Expr, ExprKind}; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::LitKind; -use syntax::codemap::{Span, Spanned}; +use syntax::source_map::{Span, Spanned}; use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; /// **What it does:** Checks for duplicate open options as well as combinations diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 6a0f4f147b7..c4e802adaee 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use crate::utils::{in_macro, snippet, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index ea2d07df455..cbf17138137 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -9,7 +9,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use syntax::ast::NodeId; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax_pos::MultiSpan; use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; use crate::utils::ptr::get_spans; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index fd303bb6ab4..27620ede5b0 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -3,7 +3,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use syntax::ast::RangeLimits; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 39b7888dcc6..4553b08e747 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -5,7 +5,7 @@ use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index b2202fb1eff..8125cc4153b 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::visit::FnKind; use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index f04d7bf9867..f5c25737993 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -4,7 +4,7 @@ use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; /// **What it does:** Checks for bindings that shadow other bindings already in diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index a13f864c5ce..d66163984aa 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 7b3f6f20fc7..3b311847795 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -12,7 +12,7 @@ use std::cmp::Ordering; use std::collections::BTreeMap; use std::borrow::Cow; use syntax::ast::{FloatTy, IntTy, UintTy}; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::errors::DiagnosticBuilder; use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_macro, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 0549e774fb5..2768efca88e 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; -use syntax::codemap::Span; +use syntax::source_map::Span; use unicode_normalization::UnicodeNormalization; use crate::utils::{is_allowed, snippet, span_help_and_lint}; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 2f8b3ab836d..37a5836f153 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use syntax::ast::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::symbol::LocalInternedString; use crate::utils::span_lint; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 1681a303fd3..04b4fcabdd8 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -4,7 +4,7 @@ use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use std::collections::HashMap; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::symbol::LocalInternedString; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6cafcaeffe9..2a557ed8e43 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -6,7 +6,7 @@ use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_po use rustc::hir::intravisit::*; use rustc::hir::*; use syntax::ast::NodeId; -use syntax::codemap::Span; +use syntax::source_map::Span; /// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail. /// diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index c1ac058a83e..1567bd9ffb6 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -5,14 +5,14 @@ use lazy_static::lazy_static; use std::{env, fmt, fs, io, path}; use std::io::Read; -use syntax::{ast, codemap}; +use syntax::{ast, source_map}; use toml; use std::sync::Mutex; /// Get the configuration file from arguments. pub fn file_from_args( - args: &[codemap::Spanned], -) -> Result, (&'static str, codemap::Span)> { + args: &[source_map::Spanned], +) -> Result, (&'static str, source_map::Span)> { for arg in args.iter().filter_map(|a| a.meta_item()) { if arg.name() == "conf_file" { return match arg.node { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 260ced14cb4..6df41f1cd41 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg}; use syntax::symbol::LocalInternedString; use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; -use syntax::codemap::Span; +use syntax::source_map::Span; use std::collections::{HashMap, HashSet}; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 32a891c8cbb..0182ae6a1a0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -19,7 +19,7 @@ use std::str::FromStr; use std::rc::Rc; use syntax::ast::{self, LitKind}; use syntax::attr; -use syntax::codemap::{Span, DUMMY_SP}; +use syntax::source_map::{Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; use syntax::symbol::keywords; @@ -365,7 +365,7 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) /// Convert a span to a code snippet. Returns `None` if not available. pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { - cx.sess().codemap().span_to_snippet(span).ok() + cx.sess().source_map().span_to_snippet(span).ok() } /// Convert a span (from a block) to a code snippet if available, otherwise use @@ -385,7 +385,7 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' /// Returns a new Span that covers the full last line of the given Span pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { - let file_map_and_line = cx.sess().codemap().lookup_line(span.lo()).unwrap(); + let file_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); let line_no = file_map_and_line.line; let line_start = &file_map_and_line.fm.lines[line_no]; Span::new(*line_start, span.hi(), span.ctxt()) diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 1a20eb01015..16a03f8f99c 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::LateContext; use syntax::ast::Name; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{get_pat_name, match_var, snippet}; pub fn get_spans( diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 11187559bf6..d513fb8bced 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -10,7 +10,7 @@ use rustc_errors; use std::borrow::Cow; use std::fmt::Display; use std; -use syntax::codemap::{CharPos, Span}; +use syntax::source_map::{CharPos, Span}; use syntax::parse::token; use syntax::print::pprust::token_to_string; use syntax::util::parser::AssocOp; @@ -432,7 +432,7 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// Return the indentation before `span` if there are nothing but `[ \t]` /// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { - let lo = cx.sess().codemap().lookup_char_pos(span.lo()); + let lo = cx.sess().source_map().lookup_char_pos(span.lo()); if let Some(line) = lo.file .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { @@ -524,8 +524,8 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) { let mut remove_span = item; - let hi = cx.sess().codemap().next_point(remove_span).hi(); - let fmpos = cx.sess().codemap().lookup_byte_offset(hi); + let hi = cx.sess().source_map().next_point(remove_span).hi(); + let fmpos = cx.sess().source_map().lookup_byte_offset(hi); if let Some(ref src) = fmpos.fm.src { let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 43e492bfb4e..95199b9f208 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -8,7 +8,7 @@ use rustc::middle::mem_categorization::Categorization; use rustc::ty; use std::collections::HashSet; use syntax::ast::NodeId; -use syntax::codemap::Span; +use syntax::source_map::Span; /// Returns a set of mutated local variable ids or None if mutations could not be determined. pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index cea3307a827..9e0cd06134b 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; -use syntax::codemap::Span; +use syntax::source_map::Span; use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; use crate::consts::constant; diff --git a/tests/matches.rs b/tests/matches.rs index 8dfb8e42d6f..c79e233cc81 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -7,7 +7,7 @@ use std::collections::Bound; #[test] fn test_overlapping() { use clippy_lints::matches::overlapping; - use syntax::codemap::DUMMY_SP; + use syntax::source_map::DUMMY_SP; let sp = |s, e| clippy_lints::matches::SpannedRange { span: DUMMY_SP, -- cgit 1.4.1-3-g733a5 From a7bea134d30577fa6f1f722cc27e5873c5869962 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 19 Aug 2018 19:07:31 -0700 Subject: Remove implied rust_2018 feature We are already on the edition and this feature is implied. --- clippy_lints/src/lib.rs | 1 - mini-macro/src/lib.rs | 2 +- src/lib.rs | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3de7c6de979..76649d8a145 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -12,7 +12,6 @@ #![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] #![feature(tool_attributes)] -#![feature(rust_2018_preview)] #![warn(rust_2018_idioms)] use toml; diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 3417e603c12..8a19dc2c4e5 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(use_extern_macros, proc_macro_quote, proc_macro_non_items)] +#![feature(proc_macro_quote, proc_macro_non_items)] extern crate proc_macro; use proc_macro::{TokenStream, quote}; diff --git a/src/lib.rs b/src/lib.rs index c2363fef907..e6aaff1b2a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] -#![feature(rust_2018_preview)] #![feature(rustc_private)] #![feature(macro_vis_matcher)] #![allow(unknown_lints)] -- cgit 1.4.1-3-g733a5 From 3015987f279b414eea37d719c8e35ed2d8d7704a Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Mon, 20 Aug 2018 14:03:13 +0200 Subject: #3016 [WIP] Implement feedback and suggestions --- clippy_lints/src/write.rs | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 9b0b25f3921..3c912756d2d 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -3,7 +3,7 @@ use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::tokenstream::{ThinTokenStream, TokenStream}; use syntax::parse::{token, parser}; -use crate::utils::{span_lint, span_lint_and_sugg}; +use crate::utils::{span_lint, span_lint_and_sugg, snippet}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -212,13 +212,15 @@ impl EarlyLintPass for Pass { let check_tts = check_tts(cx, &mac.node.tts, true); if let Some(fmtstr) = check_tts.0 { if fmtstr == "" { + let suggestion = check_tts.1.map_or("v", |expr| snippet(cx, expr.span, "v").into_owned().as_str()); + span_lint_and_sugg( cx, WRITELN_EMPTY_STRING, mac.span, - format!("using `writeln!({}, \"\")`", check_tts.1).as_str(), + format!("using writeln!({}, \"\")", suggestion).as_str(), "replace it with", - format!("using `writeln!({})`", check_tts.1), + format!("writeln!({})", "v"), ); } } @@ -235,15 +237,23 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - false, false, ); - // skip the initial write target - let expr: Option = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { - Some(p) => Some(p.into_vec().0), - None => None, - }; - // might be `writeln!(foo)` - parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?; + let mut expr: Option = None; + if is_write { + // skip the initial write target + expr = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { + Some(p) => Some(p.and_then(|expr| expr)), + None => return (None, None), + }; + // might be `writeln!(foo)` + if let None = parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok() { + return (None, expr); + } + } - let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string(); + let fmtstr = match parser.parse_str().map_err(|mut err| err.cancel()).ok() { + Some(token) => token.0.to_string(), + None => return (None, expr), + }; use fmt_macros::*; let tmp = fmtstr.clone(); let mut args = vec![]; @@ -271,7 +281,10 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - assert!(parser.eat(&token::Eof)); return (Some(fmtstr), expr); } - let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?; + let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { + Some(expr) => expr, + None => return (Some(fmtstr), None), + }; const SIMPLE: FormatSpec<'_> = FormatSpec { fill: None, align: AlignUnknown, @@ -280,7 +293,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - width: CountImplied, ty: "", }; - match &expr.node { + match &token_expr.node { ExprKind::Lit(_) => { let mut all_simple = true; let mut seen = false; @@ -296,7 +309,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - } } if all_simple && seen { - span_lint(cx, lint, expr.span, "literal with an empty format string"); + span_lint(cx, lint, token_expr.span, "literal with an empty format string"); } idx += 1; }, -- cgit 1.4.1-3-g733a5 From c292b8078302a47dc47f6e772be3fb8f887dbf7a Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Mon, 20 Aug 2018 15:33:43 +0200 Subject: #3016 Add feedback and implement test for fixed hardcoded suggestion --- clippy_lints/src/write.rs | 26 +++++++++++++------------- tests/ui/writeln_empty_string.rs | 5 ++++- tests/ui/writeln_empty_string.stderr | 12 +++++++++--- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 3c912756d2d..2231715c8d2 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -3,6 +3,7 @@ use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::tokenstream::{ThinTokenStream, TokenStream}; use syntax::parse::{token, parser}; +use std::borrow::Cow; use crate::utils::{span_lint, span_lint_and_sugg, snippet}; /// **What it does:** This lint warns when you use `println!("")` to @@ -212,7 +213,7 @@ impl EarlyLintPass for Pass { let check_tts = check_tts(cx, &mac.node.tts, true); if let Some(fmtstr) = check_tts.0 { if fmtstr == "" { - let suggestion = check_tts.1.map_or("v", |expr| snippet(cx, expr.span, "v").into_owned().as_str()); + let suggestion = check_tts.1.map_or(Cow::Borrowed("v"), |expr| snippet(cx, expr.span, "v")); span_lint_and_sugg( cx, @@ -220,7 +221,7 @@ impl EarlyLintPass for Pass { mac.span, format!("using writeln!({}, \"\")", suggestion).as_str(), "replace it with", - format!("writeln!({})", "v"), + format!("writeln!({})", suggestion), ); } } @@ -239,20 +240,19 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - ); let mut expr: Option = None; if is_write { - // skip the initial write target - expr = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { - Some(p) => Some(p.and_then(|expr| expr)), - None => return (None, None), + expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { + Ok(p) => Some(p.into_inner()), + Err(_) => return (None, None), }; // might be `writeln!(foo)` - if let None = parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok() { + if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() { return (None, expr); } } - let fmtstr = match parser.parse_str().map_err(|mut err| err.cancel()).ok() { - Some(token) => token.0.to_string(), - None => return (None, expr), + let fmtstr = match parser.parse_str().map_err(|mut err| err.cancel()) { + Ok(token) => token.0.to_string(), + Err(_) => return (None, expr), }; use fmt_macros::*; let tmp = fmtstr.clone(); @@ -281,9 +281,9 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - assert!(parser.eat(&token::Eof)); return (Some(fmtstr), expr); } - let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()).ok() { - Some(expr) => expr, - None => return (Some(fmtstr), None), + let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { + Ok(expr) => expr, + Err(_) => return (Some(fmtstr), None), }; const SIMPLE: FormatSpec<'_> = FormatSpec { fill: None, diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index c7092eb8c4b..faccfd8291c 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -5,9 +5,12 @@ use std::io::Write; fn main() { let mut v = Vec::new(); - // This should fail + // These should fail writeln!(&mut v, ""); + let mut suggestion = Vec::new(); + writeln!(&mut suggestion, ""); + // These should be fine writeln!(&mut v); writeln!(&mut v, " "); diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 16a8e0a203d..8bfec673c4a 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,10 +1,16 @@ -error: using `writeln!(v, "")` +error: using writeln!(&mut v, "") --> $DIR/writeln_empty_string.rs:9:5 | 9 | writeln!(&mut v, ""); - | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` + | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` | = note: `-D writeln-empty-string` implied by `-D warnings` -error: aborting due to previous error +error: using writeln!(&mut suggestion, "") + --> $DIR/writeln_empty_string.rs:12:5 + | +12 | writeln!(&mut suggestion, ""); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 76f7bfcefd6c7ad16b01864a3e616eb66fbfae2f Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Mon, 20 Aug 2018 15:50:15 +0200 Subject: #3016 Add backticks for the msg --- clippy_lints/src/write.rs | 2 +- tests/ui/writeln_empty_string.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 2231715c8d2..97fe12f2330 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -219,7 +219,7 @@ impl EarlyLintPass for Pass { cx, WRITELN_EMPTY_STRING, mac.span, - format!("using writeln!({}, \"\")", suggestion).as_str(), + format!("using `writeln!({}, \"\")`", suggestion).as_str(), "replace it with", format!("writeln!({})", suggestion), ); diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 8bfec673c4a..7bb6350ecd2 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,4 +1,4 @@ -error: using writeln!(&mut v, "") +error: using `writeln!(&mut v, "")` --> $DIR/writeln_empty_string.rs:9:5 | 9 | writeln!(&mut v, ""); @@ -6,7 +6,7 @@ error: using writeln!(&mut v, "") | = note: `-D writeln-empty-string` implied by `-D warnings` -error: using writeln!(&mut suggestion, "") +error: using `writeln!(&mut suggestion, "")` --> $DIR/writeln_empty_string.rs:12:5 | 12 | writeln!(&mut suggestion, ""); -- cgit 1.4.1-3-g733a5 From f8a38140a07a681f2e87bfedd0e48fe18cb6b3e6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Mar 2018 10:48:26 +0100 Subject: Try running appveyor on master instead of nightly --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 32ea8c62a2d..1674932d543 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,6 +17,10 @@ install: - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin + - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + - rustup-toolchain-install-master -f -n master + - rustup default master + - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V - cargo -V -- cgit 1.4.1-3-g733a5 From d6af6886e7bbed5cdfb54e7c8a880404f5bc8532 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Jul 2018 10:33:46 +0200 Subject: Keep the rustc master install in the travis file so we can use `travis_retry` --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index c6bd67ae0f3..e8a3b9a9c77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,6 +50,9 @@ matrix: - env: INTEGRATION=hyperium/hyper script: + - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + - travis_retry rustup-toolchain-install-master -f -n master + - rustup default master - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh -- cgit 1.4.1-3-g733a5 From f969cf2cb665c567fc852244a0e6e12af9020cf5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Jul 2018 16:22:28 +0200 Subject: Remove rust-toolchain file in CI --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index e8a3b9a9c77..1e48719b2b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,6 +50,7 @@ matrix: - env: INTEGRATION=hyperium/hyper script: + - rm rust-toolchain - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - travis_retry rustup-toolchain-install-master -f -n master - rustup default master diff --git a/appveyor.yml b/appveyor.yml index 1674932d543..07bbbcab54c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,6 +13,7 @@ environment: install: - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% + - del rust-toolchain - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin -- cgit 1.4.1-3-g733a5 From efeed9aefc172315fd840d27514069f7c0d27329 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 22 Aug 2018 17:47:54 +0200 Subject: Remove unused code --- appveyor.yml | 6 ------ util/dogfood.sh | 5 ----- 2 files changed, 11 deletions(-) delete mode 100755 util/dogfood.sh diff --git a/appveyor.yml b/appveyor.yml index 07bbbcab54c..e43750c30a6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,8 @@ environment: PROJECT_NAME: rust-clippy matrix: #- TARGET: i686-pc-windows-gnu - # MSYS2_BITS: 32 #- TARGET: i686-pc-windows-msvc - # MSYS2_BITS: 32 #- TARGET: x86_64-pc-windows-gnu - # MSYS2_BITS: 64 - TARGET: x86_64-pc-windows-msvc MSYS2_BITS: 64 @@ -31,9 +28,6 @@ test_script: - set RUST_BACKTRACE=1 - cargo build --features debugging - cargo test --features debugging - #- copy target\debug\cargo-clippy.exe C:\Users\appveyor\.cargo\bin\ - #- cargo clippy -- -D clippy - #- cd clippy_lints && cargo clippy -- -D clippy && cd .. notifications: - provider: Email diff --git a/util/dogfood.sh b/util/dogfood.sh deleted file mode 100755 index 358fc46c8db..00000000000 --- a/util/dogfood.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -rm -rf target*/*so -cargo build --lib && cp -R target target_recur && cargo rustc --lib -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy || exit 1 -rm -rf target_recur - -- cgit 1.4.1-3-g733a5 From 97a9332014ddcebdd1ec60b42b669e101c707985 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 22 Aug 2018 18:07:39 +0200 Subject: Remove MinGW from CI --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e43750c30a6..9db787cf41e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,15 +6,12 @@ environment: #- TARGET: i686-pc-windows-msvc #- TARGET: x86_64-pc-windows-gnu - TARGET: x86_64-pc-windows-msvc - MSYS2_BITS: 64 install: - - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% - del rust-toolchain - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin - - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master -f -n master - rustup default master -- cgit 1.4.1-3-g733a5 From 205db6f68600d76a9b81029d9a62e9d0df5c96a3 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 22 Aug 2018 18:08:52 +0200 Subject: Add LD_LIBRARY_PATH and GITHUB_TOKEN --- .travis.yml | 12 ++++++++---- appveyor.yml | 13 +++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1e48719b2b6..08fdf2fb6d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,10 +50,14 @@ matrix: - env: INTEGRATION=hyperium/hyper script: - - rm rust-toolchain - - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - - travis_retry rustup-toolchain-install-master -f -n master - - rustup default master + - | + if [ -n "$GITHUB_TOKEN" ]; then + rm rust-toolchain + cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + travis_retry rustup-toolchain-install-master -f -n master --github-token $GITHUB_TOKEN + rustup default master + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + fi - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh diff --git a/appveyor.yml b/appveyor.yml index 9db787cf41e..94f9500ab85 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,14 +8,15 @@ environment: - TARGET: x86_64-pc-windows-msvc install: - - del rust-toolchain - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin - - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - - rustup-toolchain-install-master -f -n master - - rustup default master - - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + # https://support.microsoft.com/en-us/help/2524009/error-running-command-shell-scripts-that-include-parentheses + - if defined GITHUB_TOKEN del rust-toolchain + - if defined GITHUB_TOKEN (cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed") + - if defined GITHUB_TOKEN rustup-toolchain-install-master -f -n master --github-token %GITHUB_TOKEN% + - if defined GITHUB_TOKEN rustup default master + - if defined GITHUB_TOKEN set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V - cargo -V -- cgit 1.4.1-3-g733a5 From 712d2d4fa106e9713f9578e120439892efed289b Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 22 Aug 2018 23:34:52 +0200 Subject: rustup, fix breakage introduced by https://github.com/rust-lang/rust/pull/53581 --- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/consts.rs | 32 +++++++++--------- clippy_lints/src/cyclomatic_complexity.rs | 4 +-- clippy_lints/src/default_trait_access.rs | 4 +-- clippy_lints/src/derive.rs | 8 ++--- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/enum_clike.rs | 6 ++-- clippy_lints/src/eta_reduction.rs | 4 +-- clippy_lints/src/eval_order_dependence.rs | 4 +-- clippy_lints/src/excessive_precision.rs | 4 +-- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/identity_op.rs | 4 +-- clippy_lints/src/indexing_slicing.rs | 4 +-- clippy_lints/src/invalid_ref.rs | 2 +- clippy_lints/src/len_zero.rs | 8 ++--- clippy_lints/src/loops.rs | 18 +++++----- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 6 ++-- clippy_lints/src/matches.rs | 4 +-- clippy_lints/src/methods.rs | 34 +++++++++---------- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mut_reference.rs | 6 ++-- clippy_lints/src/mutex_atomic.rs | 14 ++++---- clippy_lints/src/needless_borrow.rs | 6 ++-- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/needless_update.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/swap.rs | 4 +-- clippy_lints/src/transmute.rs | 40 +++++++++++----------- clippy_lints/src/trivially_copy_pass_by_ref.rs | 11 +++--- clippy_lints/src/types.rs | 46 +++++++++++++------------- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/mod.rs | 10 +++--- clippy_lints/src/vec.rs | 6 ++-- 38 files changed, 158 insertions(+), 157 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 2d4279d3cc1..6d086c13ff8 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { _ => { return; } } }; - if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { + if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty { return; } let haystack = if let ExprKind::MethodCall(ref path, _, ref args) = diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 7bccdd7778b..ff189d6e893 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -123,12 +123,12 @@ impl Hash for Constant { } impl Constant { - pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TypeVariants<'_>, left: &Self, right: &Self) -> Option { + pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TyKind<'_>, left: &Self, right: &Self) -> Option { match (left, right) { (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), (&Constant::Int(l), &Constant::Int(r)) => { - if let ty::TyInt(int_ty) = *cmp_type { + if let ty::Int(int_ty) = *cmp_type { Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))) } else { Some(l.cmp(&r)) @@ -166,8 +166,8 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, _) | LitKind::FloatUnsuffixed(ref is) => match ty.sty { - ty::TyFloat(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()), - ty::TyFloat(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()), + ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()), + ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()), _ => bug!(), }, LitKind::Bool(b) => Constant::Bool(b), @@ -220,7 +220,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::TyArray(_, n) => n.assert_usize(self.tcx).expect("array length"), + ty::Array(_, n) => n.assert_usize(self.tcx).expect("array length"), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64)) @@ -243,8 +243,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { Int(value) => { let value = !value; match ty.sty { - ty::TyInt(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), - ty::TyUint(ity) => Some(Int(clip(self.tcx, value, ity))), + ty::Int(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), + ty::Uint(ity) => Some(Int(clip(self.tcx, value, ity))), _ => None, } }, @@ -257,7 +257,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match *o { Int(value) => { let ity = match ty.sty { - ty::TyInt(ity) => ity, + ty::Int(ity) => ity, _ => return None, }; // sign extend @@ -336,7 +336,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match (l, r) { (Constant::Int(l), Some(Constant::Int(r))) => { match self.tables.expr_ty(left).sty { - ty::TyInt(ity) => { + ty::Int(ity) => { let l = sext(self.tcx, l, ity); let r = sext(self.tcx, r, ity); let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); @@ -360,7 +360,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { _ => None, } } - ty::TyUint(_) => { + ty::Uint(_) => { match op.node { BinOpKind::Add => l.checked_add(r).map(Constant::Int), BinOpKind::Sub => l.checked_sub(r).map(Constant::Int), @@ -429,18 +429,18 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' use rustc::mir::interpret::{Scalar, ScalarMaybeUndef, ConstValue}; match result.val { ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { - ty::TyBool => Some(Constant::Bool(b == 1)), - ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)), - ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), - ty::TyFloat(FloatTy::F64) => Some(Constant::F64(f64::from_bits(b as u64))), + ty::Bool => Some(Constant::Bool(b == 1)), + ty::Uint(_) | ty::Int(_) => Some(Constant::Int(b)), + ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), + ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(b as u64))), // FIXME: implement other conversion _ => None, }, ConstValue::ScalarPair(Scalar::Ptr(ptr), ScalarMaybeUndef::Scalar( Scalar::Bits { bits: n, .. })) => match result.ty.sty { - ty::TyRef(_, tam, _) => match tam.sty { - ty::TyStr => { + ty::Ref(_, tam, _) => match tam.sty { + ty::Str => { let alloc = tcx .alloc_map .lock() diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 67cd37bee37..93074eadd65 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -159,9 +159,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { walk_expr(self, e); let ty = self.cx.tables.node_id_to_type(callee.hir_id); match ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let sig = ty.fn_sig(self.cx.tcx); - if sig.skip_binder().output().sty == ty::TyNever { + if sig.skip_binder().output().sty == ty::Never { self.divergence += 1; } }, diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 4078237e8aa..f01e106df26 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use rustc::ty::TypeVariants; +use rustc::ty::TyKind; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. let expr_ty = cx.tables.expr_ty(expr); - if let TypeVariants::TyAdt(..) = expr_ty.sty { + if let TyKind::Adt(..) = expr_ty.sty { let replacement = format!("{}::default()", expr_ty); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 5aeca29f6d8..e3abfe93810 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -141,18 +141,18 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref } match ty.sty { - ty::TyAdt(def, _) if def.is_union() => return, + ty::Adt(def, _) if def.is_union() => return, // Some types are not Clone by default but could be cloned “by hand” if necessary - ty::TyAdt(def, substs) => for variant in &def.variants { + ty::Adt(def, substs) => for variant in &def.variants { for field in &variant.fields { - if let ty::TyFnDef(..) = field.ty(cx.tcx, substs).sty { + if let ty::FnDef(..) = field.ty(cx.tcx, substs).sty { return; } } for subst in substs { if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { - if let ty::TyParam(_) = subst.sty { + if let ty::Param(_) = subst.sty { return; } } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 071afde986a..1e6189e3839 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let arg = &args[0]; let arg_ty = cx.tables.expr_ty(arg); - if let ty::TyRef(..) = arg_ty.sty { + if let ty::Ref(..) = arg_ty.sty { if match_def_path(cx.tcx, def_id, &paths::DROP) { lint = DROP_REF; msg = DROP_REF_SUMMARY.to_string(); diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 62cbead1929..2551f624cb1 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -63,19 +63,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let constant = cx.tcx.const_eval(param_env.and(cid)).ok(); if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { let mut ty = cx.tcx.type_of(did); - if let ty::TyAdt(adt, _) = ty.sty { + if let ty::Adt(adt, _) = ty.sty { if adt.is_enum() { ty = adt.repr.discr_type().to_ty(cx.tcx); } } match ty.sty { - ty::TyInt(IntTy::Isize) => { + ty::Int(IntTy::Isize) => { let val = ((val as i128) << 64) >> 64; if val <= i128::from(i32::max_value()) && val >= i128::from(i32::min_value()) { continue; } } - ty::TyUint(UintTy::Usize) if val > u128::from(u32::max_value()) => {}, + ty::Uint(UintTy::Usize) if val > u128::from(u32::max_value()) => {}, _ => continue, } span_lint( diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 0e9532276f3..260cca76c8c 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -67,9 +67,9 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { let fn_ty = cx.tables.expr_ty(caller); match fn_ty.sty { // Is it an unsafe function? They don't implement the closure traits - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let sig = fn_ty.fn_sig(cx.tcx); - if sig.skip_binder().unsafety == Unsafety::Unsafe || sig.skip_binder().output().sty == ty::TyNever { + if sig.skip_binder().unsafety == Unsafety::Unsafe || sig.skip_binder().output().sty == ty::Never { return; } }, diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 7ccf8c31569..9ddc3ddbfe7 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -130,9 +130,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { ExprKind::Call(ref func, _) => { let typ = self.cx.tables.expr_ty(func); match typ.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let sig = typ.fn_sig(self.cx.tcx); - if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&sig).output().sty { + if let ty::Never = self.cx.tcx.erase_late_bound_regions(&sig).output().sty { self.report_diverging_sub_expr(e); } }, diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 2c673fdfe3f..52af7e129ab 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -2,7 +2,7 @@ use rustc::hir; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use rustc::ty::TypeVariants; +use rustc::ty::TyKind; use std::f32; use std::f64; use std::fmt; @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if_chain! { let ty = cx.tables.expr_ty(expr); - if let TypeVariants::TyFloat(fty) = ty.sty; + if let TyKind::Float(fty) = ty.sty; if let hir::ExprKind::Lit(ref lit) = expr.node; if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node; if let Some(sugg) = self.check(sym, fty); diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 3db644911d7..22f6df65506 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -130,7 +130,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it fn match_type(tcx: ty::TyCtxt<'_, '_, '_>, ty: ty::Ty<'_>, path: &[&str]) -> bool { match ty.sty { - ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path), + ty::Adt(adt, _) => match_def_path(tcx, adt.did, path), _ => false, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 80fc4c3acfe..4f83caa43dd 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -122,7 +122,7 @@ fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); - if ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING) { + if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) { if let ExprKind::Tup(ref values) = match_expr.node { return Some(values[0].span); } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 939039e93ca..31e955dc570 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -63,8 +63,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { fn check(cx: &LateContext<'_, '_>, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { let check = match cx.tables.expr_ty(e).sty { - ty::TyInt(ity) => unsext(cx.tcx, -1_i128, ity), - ty::TyUint(uty) => clip(cx.tcx, !0, uty), + ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), + ty::Uint(uty) => clip(cx.tcx, !0, uty), _ => return, }; if match m { diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 2ad31de0a17..9ec9c9f83b4 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { let ty = cx.tables.expr_ty(array); if let Some(range) = higher::range(cx, index) { // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] - if let ty::TyArray(_, s) = ty.sty { + if let ty::Array(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); // Index is a constant range. if let Some((start, end)) = to_const_range(cx, range, size) { @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { ); } else { // Catchall non-range index, i.e. [n] or [n << m] - if let ty::TyArray(..) = ty.sty { + if let ty::Array(..) = ty.sty { // Index is a constant uint. if let Some(..) = constant(cx, cx.tables, index) { // Let rustc's `const_err` lint handle constant `usize` indexing on arrays. diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index b529cb3ac38..9c7d4626e0a 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { if let ExprKind::Call(ref path, ref args) = expr.node; if let ExprKind::Path(ref qpath) = path.node; if args.len() == 0; - if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty; + if let ty::Ref(..) = cx.tables.expr_ty(expr).sty; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); then { let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index ce063518880..2fb4c691ce8 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -265,12 +265,12 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::TyDynamic(ref tt, ..) => cx.tcx + ty::Dynamic(ref tt, ..) => cx.tcx .associated_items(tt.principal().expect("trait impl not found").def_id()) .any(|item| is_is_empty(cx, &item)), - ty::TyProjection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), - ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did), - ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true, + ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), + ty::Adt(id, _) => has_is_empty_impl(cx, id.did), + ty::Array(..) | ty::Slice(..) | ty::Str => true, _ => false, } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3dacb3cd422..973b706801a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -759,8 +759,8 @@ struct FixedOffsetVar { fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { let is_slice = match ty.sty { - ty::TyRef(_, subty, _) => is_slice_like(cx, subty), - ty::TySlice(..) | ty::TyArray(..) => true, + ty::Ref(_, subty, _) => is_slice_like(cx, subty), + ty::Slice(..) | ty::Array(..) => true, _ => false, }; @@ -1149,8 +1149,8 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Constant::Int(start_idx), Constant::Int(end_idx), ) => (match ty.sty { - ty::TyInt(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), - ty::TyUint(_) => start_idx > end_idx, + ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), + ty::Uint(_) => start_idx > end_idx, _ => false, }, start_idx == end_idx), _ => (false, false), @@ -1239,7 +1239,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex match cx.tables.expr_ty(&args[0]).sty { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. - ty::TypeVariants::TyArray(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), + ty::TyKind::Array(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), _ => lint_iter_method(cx, args, arg, method_name), }; } else { @@ -1381,7 +1381,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ty, mutbl) => match (&pat[0].node, &pat[1].node) { + ty::Ref(_, ty, mutbl) => match (&pat[0].node, &pat[1].node) { (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", ty, mutbl), (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", ty, MutImmutable), _ => return, @@ -1721,7 +1721,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { for expr in args { let ty = self.cx.tables.expr_ty_adjusted(expr); self.prefer_mutable = false; - if let ty::TyRef(_, _, mutbl) = ty.sty { + if let ty::Ref(_, _, mutbl) = ty.sty { if mutbl == MutMutable { self.prefer_mutable = true; } @@ -1733,7 +1733,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id(); for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { self.prefer_mutable = false; - if let ty::TyRef(_, _, mutbl) = ty.sty { + if let ty::Ref(_, _, mutbl) = ty.sty { if mutbl == MutMutable { self.prefer_mutable = true; } @@ -1814,7 +1814,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool { fn is_iterable_array(ty: Ty<'_>, cx: &LateContext<'_, '_>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::TyArray(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")), + ty::Array(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")), _ => false, } } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index d8b14db605f..c570f0b32bf 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 { // the argument is not an &mut T - if let ty::TyRef(_, _, mutbl) = ty.sty { + if let ty::Ref(_, _, mutbl) = ty.sty { if mutbl == MutImmutable { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 7cbed82d5c7..eff00896c7f 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -86,8 +86,8 @@ impl LintPass for Pass { fn is_unit_type(ty: ty::Ty<'_>) -> bool { match ty.sty { - ty::TyTuple(slice) => slice.is_empty(), - ty::TyNever => true, + ty::Tuple(slice) => slice.is_empty(), + ty::Never => true, _ => false, } } @@ -95,7 +95,7 @@ fn is_unit_type(ty: ty::Ty<'_>) -> bool { fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool { let ty = cx.tables.expr_ty(expr); - if let ty::TyFnDef(id, _) = ty.sty { + if let ty::FnDef(id, _) = ty.sty { if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { return is_unit_type(fn_type.output()); } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 84ab72777e4..691d61f55ba 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -224,7 +224,7 @@ fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & return; }; let ty = cx.tables.expr_ty(ex); - if ty.sty != ty::TyBool || is_allowed(cx, MATCH_BOOL, ex.id) { + if ty.sty != ty::Bool || is_allowed(cx, MATCH_BOOL, ex.id) { check_single_match_single_pattern(cx, ex, arms, expr, els); check_single_match_opt_like(cx, ex, arms, expr, ty, els); } @@ -295,7 +295,7 @@ fn check_single_match_opt_like(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm] fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { // type of expression == bool - if cx.tables.expr_ty(ex).sty == ty::TyBool { + if cx.tables.expr_ty(ex).sty == ty::Bool { span_lint_and_then( cx, MATCH_BOOL, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index ceb1307dfed..1c31c414d2b 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -784,7 +784,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match self_ty.sty { - ty::TyRef(_, ty, _) if ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { + ty::Ref(_, ty, _) if ty.sty == ty::Str => for &(method, pos) in &PATTERN_METHODS { if method_call.ident.name == method && args.len() > pos { lint_single_char_pattern(cx, expr, &args[pos]); } @@ -1113,8 +1113,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: /// Checks for the `CLONE_ON_COPY` lint. fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty<'_>) { let ty = cx.tables.expr_ty(expr); - if let ty::TyRef(_, inner, _) = arg_ty.sty { - if let ty::TyRef(_, innermost, _) = inner.sty { + if let ty::Ref(_, inner, _) = arg_ty.sty { + if let ty::Ref(_, innermost, _) = inner.sty { span_lint_and_then( cx, CLONE_DOUBLE_REF, @@ -1124,7 +1124,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { let mut ty = innermost; let mut n = 0; - while let ty::TyRef(_, inner, _) = ty.sty { + while let ty::Ref(_, inner, _) = ty.sty { ty = inner; n += 1; } @@ -1142,7 +1142,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if is_copy(cx, ty) { let snip; if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - if let ty::TyRef(..) = cx.tables.expr_ty(arg).sty { + if let ty::Ref(..) = cx.tables.expr_ty(arg).sty { let parent = cx.tcx.hir.get_parent_node(expr.id); match cx.tcx.hir.get(parent) { hir::map::NodeExpr(parent) => match parent.node { @@ -1182,7 +1182,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); - if let ty::TyAdt(_, subst) = obj_ty.sty { + if let ty::Adt(_, subst) = obj_ty.sty { let caller_type = if match_type(cx, obj_ty, &paths::RC) { "Rc" } else if match_type(cx, obj_ty, &paths::ARC) { @@ -1210,7 +1210,7 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E if let Some(arglists) = method_chain_args(arg, &["chars"]) { let target = &arglists[0][0]; let self_ty = walk_ptrs_ty(cx.tables.expr_ty(target)); - let ref_str = if self_ty.sty == ty::TyStr { + let ref_str = if self_ty.sty == ty::Str { "" } else if match_type(cx, self_ty, &paths::STRING) { "&" @@ -1442,11 +1442,11 @@ fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) { fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Option> { fn may_slice(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { match ty.sty { - ty::TySlice(_) => true, - ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::TyAdt(..) => match_type(cx, ty, &paths::VEC), - ty::TyArray(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, - ty::TyRef(_, inner, _) => may_slice(cx, inner), + ty::Slice(_) => true, + ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) => match_type(cx, ty, &paths::VEC), + ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, + ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, } } @@ -1459,9 +1459,9 @@ fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Op } } else { match ty.sty { - ty::TySlice(_) => sugg::Sugg::hir_opt(cx, expr), - ty::TyAdt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::TyRef(_, inner, _) => if may_slice(cx, inner) { + ty::Slice(_) => sugg::Sugg::hir_opt(cx, expr), + ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), + ty::Ref(_, inner, _) => if may_slice(cx, inner) { sugg::Sugg::hir_opt(cx, expr) } else { None @@ -1812,7 +1812,7 @@ fn lint_chars_cmp( then { let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); - if self_ty.sty != ty::TyStr { + if self_ty.sty != ty::Str { return false; } @@ -1939,7 +1939,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { - if let ty::TyAdt(_, substs) = ty.sty { + if let ty::Adt(_, substs) = ty.sty { if match_type(cx, ty, &paths::RESULT) { substs.types().nth(1) } else { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index fc9b72ba949..a43c60f111f 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -465,7 +465,7 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { } fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { - matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::TyFloat(_)) + matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::Float(_)) } fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 0413f1ab603..d8561241001 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { expr.span, "generally you want to avoid `&mut &mut _` if possible", ); - } else if let ty::TyRef( + } else if let ty::Ref( _, _, hir::MutMutable, diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index de4c5444440..02a80a19e79 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -58,16 +58,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], type_definition: Ty<'tcx>, name: &str) { match type_definition.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - ty::TyRef( + ty::Ref( _, _, MutImmutable, ) | - ty::TyRawPtr(ty::TypeAndMut { + ty::RawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => if let ExprKind::AddrOf(MutMutable, _) = argument.node { diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 50ef9f268f2..8b56526f495 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -60,7 +60,7 @@ pub struct MutexAtomic; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let ty = cx.tables.expr_ty(expr); - if let ty::TyAdt(_, subst) = ty.sty { + if let ty::Adt(_, subst) = ty.sty { if match_type(cx, ty, &paths::MUTEX) { let mutex_param = subst.type_at(0); if let Some(atomic_name) = get_atomic_name(mutex_param) { @@ -70,8 +70,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { atomic_name ); match mutex_param.sty { - ty::TyUint(t) if t != ast::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::TyInt(t) if t != ast::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Uint(t) if t != ast::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Int(t) if t != ast::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } @@ -82,10 +82,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { fn get_atomic_name(ty: Ty<'_>) -> Option<(&'static str)> { match ty.sty { - ty::TyBool => Some("AtomicBool"), - ty::TyUint(_) => Some("AtomicUsize"), - ty::TyInt(_) => Some("AtomicIsize"), - ty::TyRawPtr(_) => Some("AtomicPtr"), + ty::Bool => Some("AtomicBool"), + ty::Uint(_) => Some("AtomicUsize"), + ty::Int(_) => Some("AtomicIsize"), + ty::RawPtr(_) => Some("AtomicPtr"), _ => None, } } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index cb2c572743d..ae931e58326 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { return; } if let ExprKind::AddrOf(MutImmutable, ref inner) = e.node { - if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty { + if let ty::Ref(..) = cx.tables.expr_ty(inner).sty { for adj3 in cx.tables.expr_adjustments(e).windows(3) { if let [Adjustment { kind: Adjust::Deref(_), @@ -90,9 +90,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } if_chain! { if let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node; - if let ty::TyRef(_, tam, mutbl) = cx.tables.pat_ty(pat).sty; + if let ty::Ref(_, tam, mutbl) = cx.tables.pat_ty(pat).sty; if mutbl == MutImmutable; - if let ty::TyRef(_, _, mutbl) = tam.sty; + if let ty::Ref(_, _, mutbl) = tam.sty; // only lint immutable refs, because borrowed `&mut T` cannot be moved out if mutbl == MutImmutable; then { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 82e85f3453a..c93cda55724 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -205,7 +205,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder<'_>| { - if let ty::TypeVariants::TyAdt(def, ..) = ty.sty { + if let ty::TyKind::Adt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { db.span_help(span, "consider marking this type as Copy"); diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 52c4c6e5237..90a1ee14a6d 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tables.expr_ty(expr); - if let ty::TyAdt(def, _) = ty.sty { + if let ty::Adt(def, _) = ty.sty { if fields.len() == def.non_enum_variant().fields.len() { span_lint( cx, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 77b945f48fd..224326b3d17 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -169,7 +169,7 @@ fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String { fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option { match ty.sty { - ty::TyAdt(adt_def, substs) if adt_def.is_struct() => { + ty::Adt(adt_def, substs) if adt_def.is_struct() => { for field in adt_def.all_fields() { let f_ty = field.ty(cx.tcx, substs); if !implements_trait(cx, f_ty, default_trait_id, &[]) { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index cbf17138137..b040bd91f8d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -152,7 +152,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: let fn_ty = sig.skip_binder(); for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { - if let ty::TyRef( + if let ty::Ref( _, ty, MutImmutable diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index f5c25737993..cc4aa129870 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -155,7 +155,7 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { let var_ty = cx.tables.node_id_to_type(pat_id); match var_ty.sty { - ty::TyAdt(..) => false, + ty::Adt(..) => false, _ => true, } } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 38369d05676..8b10396443f 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -93,8 +93,8 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1)); - if matches!(ty.sty, ty::TySlice(_)) || - matches!(ty.sty, ty::TyArray(_, _)) || + if matches!(ty.sty, ty::Slice(_)) || + matches!(ty.sty, ty::Array(_, _)) || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) { return Some((lhs1, idx1, idx2)); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 403aeb47402..28c5971e852 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), - (&ty::TyRef(_, rty, rty_mutbl), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( + (&ty::Ref(_, rty, rty_mutbl), &ty::RawPtr(ptr_ty)) => span_lint_and_then( cx, USELESS_TRANSMUTE, e.span, @@ -248,7 +248,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg.to_string()); }, ), - (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => { + (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => { span_lint_and_then( cx, USELESS_TRANSMUTE, @@ -259,16 +259,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }, ) }, - (&ty::TyFloat(_), &ty::TyRef(..)) | - (&ty::TyFloat(_), &ty::TyRawPtr(_)) | - (&ty::TyChar, &ty::TyRef(..)) | - (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint( + (&ty::Float(_), &ty::Ref(..)) | + (&ty::Float(_), &ty::RawPtr(_)) | + (&ty::Char, &ty::Ref(..)) | + (&ty::Char, &ty::RawPtr(_)) => span_lint( cx, WRONG_TRANSMUTE, e.span, &format!("transmute from a `{}` to a pointer", from_ty), ), - (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + (&ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { to_ty ), ), - (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + (_, &ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -288,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { to_ty ), ), - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty, mutbl)) => span_lint_and_then( + (&ty::RawPtr(from_pty), &ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, e.span, @@ -315,16 +315,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); }, ), - (&ty::TyInt(ast::IntTy::I32), &ty::TyChar) | - (&ty::TyUint(ast::UintTy::U32), &ty::TyChar) => span_lint_and_then( + (&ty::Int(ast::IntTy::I32), &ty::Char) | + (&ty::Uint(ast::UintTy::U32), &ty::Char) => span_lint_and_then( cx, TRANSMUTE_INT_TO_CHAR, e.span, &format!("transmute from a `{}` to a `char`", from_ty), |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::TyInt(_) = from_ty.sty { - arg.as_ty(ty::TyUint(ast::UintTy::U32)) + let arg = if let ty::Int(_) = from_ty.sty { + arg.as_ty(ty::Uint(ast::UintTy::U32)) } else { arg }; @@ -335,10 +335,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::TyRef(_, ty_from, from_mutbl), &ty::TyRef(_, ty_to, to_mutbl)) => { + (&ty::Ref(_, ty_from, from_mutbl), &ty::Ref(_, ty_to, to_mutbl)) => { if_chain! { - if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ty_from.sty, &ty_to.sty); - if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty; + if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.sty, &ty_to.sty); + if let ty::Uint(ast::UintTy::U8) = slice_ty.sty; if from_mutbl == to_mutbl; then { let postfix = if from_mutbl == Mutability::MutMutable { @@ -387,7 +387,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } }, - (&ty::TyRawPtr(_), &ty::TyRawPtr(to_ty)) => span_lint_and_then( + (&ty::RawPtr(_), &ty::RawPtr(to_ty)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, e.span, @@ -397,7 +397,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg.to_string()); }, ), - (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) | (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => { + (&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_BOOL, @@ -414,7 +414,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }, ) }, - (&ty::TyInt(_), &ty::TyFloat(_)) | (&ty::TyUint(_), &ty::TyFloat(_)) => { + (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, @@ -422,7 +422,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::TyInt(int_ty) = from_ty.sty { + let arg = if let ty::Int(int_ty) = from_ty.sty { arg.as_ty(format!( "u{}", int_ty diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index a01a1c5ae31..d88a970db75 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,13 +1,14 @@ use std::cmp; use matches::matches; +use rustc::hir; use rustc::hir::*; use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; -use rustc::ty::TypeVariants; +use rustc::ty::TyKind; use rustc::session::config::Config as SessionConfig; use rustc_target::spec::abi::Abi; use rustc_target::abi::LayoutOf; @@ -125,8 +126,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { // argument. In that case we can't switch to pass-by-value as the // argument will not live long enough. let output_lts = match fn_sig.output().sty { - TypeVariants::TyRef(output_lt, _, _) => vec![output_lt], - TypeVariants::TyAdt(_, substs) => substs.regions().collect(), + TyKind::Ref(output_lt, _, _) => vec![output_lt], + TyKind::Adt(_, substs) => substs.regions().collect(), _ => vec![], }; @@ -137,12 +138,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } if_chain! { - if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty; + if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty; if !output_lts.contains(&input_lt); if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.limit; - if let TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; + if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; then { let value_type = if is_self(arg) { "self".into() diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3b311847795..024aba7e85e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -550,7 +550,7 @@ fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { fn is_unit(ty: Ty<'_>) -> bool { match ty.sty { - ty::TyTuple(slice) if slice.is_empty() => true, + ty::Tuple(slice) if slice.is_empty() => true, _ => false, } } @@ -755,7 +755,7 @@ declare_clippy_lint! { /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { match typ.sty { - ty::TyInt(i) => match i { + ty::Int(i) => match i { IntTy::Isize => tcx.data_layout.pointer_size.bits(), IntTy::I8 => 8, IntTy::I16 => 16, @@ -763,7 +763,7 @@ fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { IntTy::I64 => 64, IntTy::I128 => 128, }, - ty::TyUint(i) => match i { + ty::Uint(i) => match i { UintTy::Usize => tcx.data_layout.pointer_size.bits(), UintTy::U8 => 8, UintTy::U16 => 16, @@ -777,7 +777,7 @@ fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { fn is_isize_or_usize(typ: Ty<'_>) -> bool { match typ.sty { - ty::TyInt(IntTy::Isize) | ty::TyUint(UintTy::Usize) => true, + ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => true, _ => false, } } @@ -973,7 +973,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { match (cast_from.is_integral(), cast_to.is_integral()) { (true, false) => { let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); - let to_nbits = if let ty::TyFloat(FloatTy::F32) = cast_to.sty { + let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.sty { 32 } else { 64 @@ -1014,7 +1014,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { check_lossless(cx, expr, ex, cast_from, cast_to); }, (false, false) => { - if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) + if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { span_lint( cx, @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { "casting f64 to f32 may truncate the value", ); } - if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) + if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) { span_lossless_lint(cx, expr, ex, cast_from, cast_to); } @@ -1032,9 +1032,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } match &cast_from.sty { - ty::TyFnDef(..) | - ty::TyFnPtr(..) => { - if cast_to.is_numeric() && cast_to.sty != ty::TyUint(UintTy::Usize){ + ty::FnDef(..) | + ty::FnPtr(..) => { + if cast_to.is_numeric() && cast_to.sty != ty::Uint(UintTy::Usize){ let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); let pointer_nbits = cx.tcx.data_layout.pointer_size.bits(); if to_nbits < pointer_nbits || (to_nbits == pointer_nbits && cast_to.is_signed()) { @@ -1063,8 +1063,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } if_chain!{ - if let ty::TyRawPtr(from_ptr_ty) = &cast_from.sty; - if let ty::TyRawPtr(to_ptr_ty) = &cast_to.sty; + if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; + if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi()); if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi()); if from_align < to_align; @@ -1294,7 +1294,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { if let ExprKind::Cast(ref e, _) = expr.node { if let ExprKind::Lit(ref l) = e.node { if let LitKind::Char(_) = l.node { - if ty::TyUint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(expr.span) { + if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(expr.span) { let msg = "casting character literal to u8. `char`s \ are 4 bytes wide in rust, so casting to u8 \ truncates them"; @@ -1434,13 +1434,13 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - let cv = constant(cx, cx.tables, expr)?.0; let which = match (&ty.sty, cv) { - (&ty::TyBool, Constant::Bool(false)) | - (&ty::TyUint(_), Constant::Int(0)) => Minimum, - (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum, + (&ty::Bool, Constant::Bool(false)) | + (&ty::Uint(_), Constant::Int(0)) => Minimum, + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum, - (&ty::TyBool, Constant::Bool(true)) => Maximum, - (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum, - (&ty::TyUint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum, + (&ty::Bool, Constant::Bool(true)) => Maximum, + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum, + (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum, _ => return None, }; @@ -1574,7 +1574,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> return None; } match pre_cast_ty.sty { - ty::TyInt(int_ty) => Some(match int_ty { + ty::Int(int_ty) => Some(match int_ty { IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), IntTy::I16 => ( FullInt::S(i128::from(i16::min_value())), @@ -1591,7 +1591,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }), - ty::TyUint(uint_ty) => Some(match uint_ty { + ty::Uint(uint_ty) => Some(match uint_ty { UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), UintTy::U16 => ( FullInt::U(u128::from(u16::min_value())), @@ -1619,8 +1619,8 @@ fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) let val = constant(cx, cx.tables, expr)?.0; if let Constant::Int(const_int) = val { match cx.tables.expr_ty(expr).sty { - ty::TyInt(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), - ty::TyUint(_) => Some(FullInt::U(const_int)), + ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), + ty::Uint(_) => Some(FullInt::U(const_int)), _ => None, } } else { diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 3931f6c55f9..65d58c4e55b 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -48,7 +48,7 @@ pub struct Range<'a> { pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option> { let def_path = match cx.tables.expr_ty(expr).sty { - ty::TyAdt(def, _) => cx.tcx.def_path(def.did), + ty::Adt(def, _) => cx.tcx.def_path(def.did), _ => return None, }; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0182ae6a1a0..b753f8072d0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -101,7 +101,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> /// Check if type is struct, enum or union type with given def path. pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.sty { - ty::TyAdt(adt, _) => match_def_path(cx.tcx, adt.did, path), + ty::Adt(adt, _) => match_def_path(cx.tcx, adt.did, path), _ => false, } } @@ -631,7 +631,7 @@ pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> { match ty.sty { - ty::TyRef(_, ty, _) => walk_ptrs_ty(ty), + ty::Ref(_, ty, _) => walk_ptrs_ty(ty), _ => ty, } } @@ -641,7 +641,7 @@ pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> { pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) { match ty.sty { - ty::TyRef(_, ty, _) => inner(ty, depth + 1), + ty::Ref(_, ty, _) => inner(ty, depth + 1), _ => (ty, depth), } } @@ -842,7 +842,7 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) /// Return whether the given type is an `unsafe` function. pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, + ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, _ => false, } } @@ -927,7 +927,7 @@ pub fn opt_def_id(def: Def) -> Option { Def::TyAlias(id) | Def::AssociatedTy(id) | Def::TyParam(id) | - Def::TyForeign(id) | + Def::ForeignTy(id) | Def::Struct(id) | Def::StructCtor(id, ..) | Def::Union(id) | diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 9e0cd06134b..f86ce5ab786 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -37,8 +37,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_chain! { - if let ty::TyRef(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty; - if let ty::TySlice(..) = ty.sty; + if let ty::Ref(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty; + if let ty::Slice(..) = ty.sty; if let ExprKind::AddrOf(_, ref addressee) = expr.node; if let Some(vec_args) = higher::vec_macro(cx, addressee); then { @@ -95,7 +95,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA /// Return the item type of the vector (ie. the `T` in `Vec`). fn vec_type(ty: Ty<'_>) -> Ty<'_> { - if let ty::TyAdt(_, substs) = ty.sty { + if let ty::Adt(_, substs) = ty.sty { substs.type_at(0) } else { panic!("The type of `vec!` is a not a struct?"); -- cgit 1.4.1-3-g733a5 From 37099ae0348b1fc8d369f30df7887d775b5a1b99 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 23 Aug 2018 15:36:07 +0200 Subject: Remove now stable tool_attributes feature --- clippy_lints/src/lib.rs | 2 -- tests/needless_continue_helpers.rs | 2 +- tests/trim_multiline.rs | 2 +- tests/ui/author.rs | 2 +- tests/ui/author/call.rs | 2 +- tests/ui/author/for_loop.rs | 2 +- tests/ui/cyclomatic_complexity.rs | 2 +- tests/ui/cyclomatic_complexity_attr_used.rs | 2 +- tests/ui/trailing_zeros.rs | 2 +- 9 files changed, 8 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 76649d8a145..c8e5aabc00a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,10 +8,8 @@ #![feature(macro_vis_matcher)] #![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] -#![allow(stable_features)] #![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] -#![feature(tool_attributes)] #![warn(rust_2018_idioms)] use toml; diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index f608ef1ad02..2f6f5c0a81c 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. diff --git a/tests/trim_multiline.rs b/tests/trim_multiline.rs index a61eee40928..a0db2e59a29 100644 --- a/tests/trim_multiline.rs +++ b/tests/trim_multiline.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + /// test the multiline-trim function extern crate clippy_lints; diff --git a/tests/ui/author.rs b/tests/ui/author.rs index eec26bcce3c..e8a04bb7b13 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + fn main() { diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs index 8d085112f3b..c3e9846e21c 100755 --- a/tests/ui/author/call.rs +++ b/tests/ui/author/call.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + fn main() { #[clippy::author] diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index 026aee4746d..b3dec876535 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes, stmt_expr_attributes)] +#![feature(stmt_expr_attributes)] fn main() { #[clippy::author] diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 3214505ba1e..7166ed25948 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + #![allow(clippy)] #![warn(cyclomatic_complexity)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index 50b19f9d7ba..dbd4e438a12 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,4 +1,4 @@ -#![feature(tool_attributes)] + #![warn(cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 5494e780628..58c04d292bc 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,4 +1,4 @@ -#![feature(stmt_expr_attributes, tool_attributes)] +#![feature(stmt_expr_attributes)] #![allow(unused_parens)] -- cgit 1.4.1-3-g733a5 From 8ab16b678c0473b29d034cad5ab1fccb1b35944e Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 23 Aug 2018 13:12:27 +0200 Subject: remove macro_vis_matcher feature gate since it is stable now. Warning was: warning: the feature `macro_vis_matcher` has been stable since 1.29.0 and no longer requires an attribute to enable --> src/lib.rs:4:12 | 4 | #![feature(macro_vis_matcher)] | ^^^^^^^^^^^^^^^^^ | = note: #[warn(stable_features)] on by default --- clippy_lints/src/lib.rs | 1 - src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c8e5aabc00a..6064601fd80 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -5,7 +5,6 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] -#![feature(macro_vis_matcher)] #![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(iterator_find_map)] diff --git a/src/lib.rs b/src/lib.rs index e6aaff1b2a9..1525dbda4ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] -#![feature(macro_vis_matcher)] #![allow(unknown_lints)] #![allow(missing_docs_in_private_items)] #![warn(rust_2018_idioms)] -- cgit 1.4.1-3-g733a5 From 6a0703664b5f57b797a44d9552d660ec4177611b Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 23 Aug 2018 08:38:41 -0700 Subject: Remove incorrect note from string_add_assign docs The docs claim that `String::push_str` is better than `String::add` because `String::add` allocates a new string and drops the old one, but this is not true. In fact, `add` reuses the existing string and grows it only if its capacity is exceeded, exactly like `push_str`. Their performance is identical since `add` is just a wrapper for `push_str`: ``` fn add(mut self, other: &str) -> String { self.push_str(other); self } ``` https://github.com/rust-lang/rust/blob/35bf1ae25799a4e62131159f052e0a3cbd27c960/src/liballoc/string.rs#L1922-L1925 --- clippy_lints/src/strings.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index d66163984aa..1b6f65046a0 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -9,8 +9,7 @@ use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, sp /// `let`!). /// /// **Why is this bad?** It's not really bad, but some people think that the -/// `.push_str(_)` method is more readable. Also creates a new heap allocation and throws -/// away the old one. +/// `.push_str(_)` method is more readable. /// /// **Known problems:** None. /// -- cgit 1.4.1-3-g733a5 From c98987f39016cdceca56cdbe2bfac758d460b8d2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 23 Aug 2018 21:41:30 +0200 Subject: fix clippy breakage due to https://github.com/rust-lang/rust/pull/52602 --- clippy_lints/src/utils/sugg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d513fb8bced..3d587a72eec 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -105,7 +105,6 @@ impl<'a> Sugg<'a> { ast::ExprKind::Block(..) | ast::ExprKind::Break(..) | ast::ExprKind::Call(..) | - ast::ExprKind::Catch(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Yield(..) | ast::ExprKind::Field(..) | @@ -122,6 +121,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::Ret(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Try(..) | + ast::ExprKind::TryBlock(..) | ast::ExprKind::Tup(..) | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | -- cgit 1.4.1-3-g733a5 From afdf3500600b27b1a54ac54e042eb4370d796837 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Tue, 17 Jul 2018 19:22:55 +0200 Subject: Add copy_iterator lint (#1534) --- clippy_lints/src/copy_iterator.rs | 57 +++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 +++ tests/ui/copy_iterator.rs | 23 ++++++++++++++++ tests/ui/copy_iterator.stderr | 17 ++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 clippy_lints/src/copy_iterator.rs create mode 100644 tests/ui/copy_iterator.rs create mode 100644 tests/ui/copy_iterator.stderr diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs new file mode 100644 index 00000000000..ac0c2ed32c6 --- /dev/null +++ b/clippy_lints/src/copy_iterator.rs @@ -0,0 +1,57 @@ +use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; +use rustc::hir::{Item, ItemKind}; +use rustc::lint::*; +use rustc::{declare_lint, lint_array}; + +/// **What it does:** Checks for types that implement `Copy` as well as +/// `Iterator`. +/// +/// **Why is this bad?** Implicit copies can be confusing when working with +/// iterator combinators. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// #[derive(Copy, Clone)] +/// struct Countdown(u8); +/// +/// impl Iterator for Countdown { +/// // ... +/// } +/// +/// let a: Vec<_> = my_iterator.take(1).collect(); +/// let b: Vec<_> = my_iterator.collect(); +/// ``` +declare_clippy_lint! { + pub COPY_ITERATOR, + pedantic, + "implementing `Iterator` on a `Copy` type" +} + +pub struct CopyIterator; + +impl LintPass for CopyIterator { + fn get_lints(&self) -> LintArray { + lint_array![COPY_ITERATOR] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node { + let ty = cx.tcx.type_of(cx.tcx.hir.local_def_id(item.id)); + + if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) { + span_note_and_lint( + cx, + COPY_ITERATOR, + item.span, + "you are implementing `Iterator` on a `Copy` type", + item.span, + "consider implementing `IntoIterator` instead", + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6064601fd80..ee2f0ca5406 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -66,6 +66,7 @@ pub mod bytecount; pub mod collapsible_if; pub mod const_static_lifetime; pub mod copies; +pub mod copy_iterator; pub mod cyclomatic_complexity; pub mod default_trait_access; pub mod derive; @@ -338,6 +339,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box types::InvalidUpcastComparisons); reg.register_late_lint_pass(box regex::Pass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); + reg.register_late_lint_pass(box copy_iterator::CopyIterator); reg.register_late_lint_pass(box format::Pass); reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); @@ -431,6 +433,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy_pedantic", vec![ attrs::INLINE_ALWAYS, copies::MATCH_SAME_ARMS, + copy_iterator::COPY_ITERATOR, default_trait_access::DEFAULT_TRAIT_ACCESS, derive::EXPL_IMPL_CLONE_ON_COPY, doc::DOC_MARKDOWN, diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs new file mode 100644 index 00000000000..1b65cc4f8cc --- /dev/null +++ b/tests/ui/copy_iterator.rs @@ -0,0 +1,23 @@ +#![warn(copy_iterator)] + +#[derive(Copy, Clone)] +struct Countdown(u8); + +impl Iterator for Countdown { + type Item = u8; + + fn next(&mut self) -> Option { + self.0.checked_sub(1).map(|c| { + self.0 = c; + c + }) + } +} + +fn main() { + let my_iterator = Countdown(5); + let a: Vec<_> = my_iterator.take(1).collect(); + assert_eq!(a.len(), 1); + let b: Vec<_> = my_iterator.collect(); + assert_eq!(b.len(), 5); +} diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr new file mode 100644 index 00000000000..f520156b01e --- /dev/null +++ b/tests/ui/copy_iterator.stderr @@ -0,0 +1,17 @@ +error: you are implementing `Iterator` on a `Copy` type + --> $DIR/copy_iterator.rs:6:1 + | +6 | / impl Iterator for Countdown { +7 | | type Item = u8; +8 | | +9 | | fn next(&mut self) -> Option { +... | +14 | | } +15 | | } + | |_^ + | + = note: `-D copy-iterator` implied by `-D warnings` + = note: consider implementing `IntoIterator` instead + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 2224fbb5f7df9f80e91dd86e1732c4ef8e5ab58f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 24 Aug 2018 18:14:49 +0200 Subject: deps: update cargo_metadata from 0.5 to 0.6. --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5b690040902..5ee7e609af2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ regex = "1" semver = "0.9" [dev-dependencies] -cargo_metadata = "0.5" +cargo_metadata = "0.6" compiletest_rs = "0.3.7" lazy_static = "1.0" serde_derive = "1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 5c3af20bde8..b168f86f56a 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -19,7 +19,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2018" [dependencies] -cargo_metadata = "0.5" +cargo_metadata = "0.6" itertools = "0.7" lazy_static = "1.0.2" matches = "0.1.7" -- cgit 1.4.1-3-g733a5 From f7be2a041658ca7ba00d75ea0524a88772e00eee Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 24 Aug 2018 18:41:49 +0200 Subject: add how-to example for std::mem::transmute() usage instead of manual swap --- clippy_lints/src/swap.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 8b10396443f..14c8e94d30c 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -20,6 +20,10 @@ use crate::utils::sugg::Sugg; /// b = a; /// a = t; /// ``` +/// Use std::mem::swap(): +/// ```rust +/// std::mem::swap(&mut a, &mut b); +/// ``` declare_clippy_lint! { pub MANUAL_SWAP, complexity, -- cgit 1.4.1-3-g733a5 From 45ceecc79ccf6f6e1718c4e0b358c2268865b43e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 25 Aug 2018 14:49:56 +0200 Subject: Fix #3078 --- clippy_lints/src/non_expressive_names.rs | 3 +++ tests/ui/non_expressive_names.rs | 7 +++++++ tests/ui/non_expressive_names.stderr | 12 ++++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index acfa341ed1f..daccc4bde03 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -114,6 +114,9 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { _ => walk_pat(self, pat), } } + fn visit_mac(&mut self, _mac: &Mac) { + // do not check macs + } } fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 7149bf8f3e7..bf0aea5c450 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -147,6 +147,13 @@ fn issue2927() { format!("{:?}", 2); } +fn issue3078() { + match "a" { + stringify!(a) => {}, + _ => {} + } +} + struct Bar; impl Bar { diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index b4927e69e67..667b631fb93 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -150,21 +150,21 @@ error: consider choosing a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:154:13 + --> $DIR/non_expressive_names.rs:161:13 | -154 | let _1 = 1; +161 | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:155:13 + --> $DIR/non_expressive_names.rs:162:13 | -155 | let ____1 = 1; +162 | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:156:13 + --> $DIR/non_expressive_names.rs:163:13 | -156 | let __1___2 = 12; +163 | let __1___2 = 12; | ^^^^^^^ error: aborting due to 17 previous errors -- cgit 1.4.1-3-g733a5 From 6256ad05bac1f708298f827fdfa7b54042961294 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 25 Aug 2018 22:35:06 +0200 Subject: fix-3078: verify test case Check the crash test case by commenting out the fix --- clippy_lints/src/non_expressive_names.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index daccc4bde03..f92538cd097 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -114,9 +114,11 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { _ => walk_pat(self, pat), } } + /* fn visit_mac(&mut self, _mac: &Mac) { // do not check macs } + */ } fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { -- cgit 1.4.1-3-g733a5 From cc87dc753987c580d05cdc24ef06d7d0ac43ced2 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 26 Aug 2018 10:57:04 +0200 Subject: Move some range lints to complexity Recategorize `range_plus_one` and `range_minus_one` to `complexity`. This moves `range_plus_one` out of the nursery as the inclusive range syntax is now stable. Both are moved to `complexity` as it is more consistent with other lints such as `int_plus_one`. --- clippy_lints/src/lib.rs | 5 +++-- clippy_lints/src/ranges.rs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index da6db4cfe45..af87655e65c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -635,6 +635,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { question_mark::QUESTION_MARK, ranges::ITERATOR_STEP_BY_ZERO, ranges::RANGE_MINUS_ONE, + ranges::RANGE_PLUS_ONE, ranges::RANGE_ZIP_WITH_LEN, redundant_field_names::REDUNDANT_FIELD_NAMES, reference::DEREF_ADDROF, @@ -756,7 +757,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ptr::CMP_NULL, ptr::PTR_ARG, question_mark::QUESTION_MARK, - ranges::RANGE_MINUS_ONE, redundant_field_names::REDUNDANT_FIELD_NAMES, regex::REGEX_MACRO, regex::TRIVIAL_REGEX, @@ -816,6 +816,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, + ranges::RANGE_MINUS_ONE, + ranges::RANGE_PLUS_ONE, ranges::RANGE_ZIP_WITH_LEN, reference::DEREF_ADDROF, reference::REF_IN_DEREF, @@ -921,7 +923,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, - ranges::RANGE_PLUS_ONE, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 27620ede5b0..ba25e50d7c0 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -57,7 +57,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub RANGE_PLUS_ONE, - nursery, + complexity, "`x..(y+1)` reads better as `x..=y`" } @@ -75,7 +75,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub RANGE_MINUS_ONE, - style, + complexity, "`x..=(y-1)` reads better as `x..y`" } -- cgit 1.4.1-3-g733a5 From eef3ffab35cd91f343e32af340050ddfb70a7dd7 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 26 Aug 2018 11:11:47 +0200 Subject: Remove `iterator_find_map` feature attribute Closes #3083 --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index da6db4cfe45..a48452f1a2c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -7,7 +7,6 @@ #![feature(range_contains)] #![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)] #![recursion_limit = "256"] -#![feature(iterator_find_map)] #![feature(macro_at_most_once_rep)] #![warn(rust_2018_idioms)] -- cgit 1.4.1-3-g733a5 From 95fedd22731e1fbd3c3f75ef8fef06b929738819 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 26 Aug 2018 11:18:44 +0200 Subject: Revert "Fix E0502 warnings" This reverts commit 98dbce4fe4a6f63a4d1f9e2fdd6b2752ed097af4. The compiler no longer emits the warnings in #2982 with the original code. --- clippy_lints/src/lib.rs | 4 +--- clippy_lints/src/utils/hir_utils.rs | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index da6db4cfe45..03ac199bf14 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -375,11 +375,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); reg.register_late_lint_pass(box explicit_write::Pass); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); - - let target = ®.sess.target; reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef::new( conf.trivial_copy_size_limit, - target, + ®.sess.target, )); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 57486b30d34..2c5995f1327 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -448,8 +448,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { CaptureClause::CaptureByValue => 0, CaptureClause::CaptureByRef => 1, }.hash(&mut self.s); - let value = &self.cx.tcx.hir.body(eid).value; - self.hash_expr(value); + self.hash_expr(&self.cx.tcx.hir.body(eid).value); }, ExprKind::Field(ref e, ref f) => { let c: fn(_, _) -> _ = ExprKind::Field; @@ -516,8 +515,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); let full_table = self.tables; self.tables = self.cx.tcx.body_tables(l_id.body); - let value = &self.cx.tcx.hir.body(l_id.body).value; - self.hash_expr(value); + self.hash_expr(&self.cx.tcx.hir.body(l_id.body).value); self.tables = full_table; }, ExprKind::Ret(ref e) => { -- cgit 1.4.1-3-g733a5 From caa59e2e277128767023cfe867f54dae943af6ca Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 26 Aug 2018 15:49:08 +0200 Subject: Use the compilers exit code computation instead of rolling our own --- src/driver.rs | 216 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 107 insertions(+), 109 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 659287daed5..6854ccbbddc 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -13,125 +13,123 @@ fn show_version() { } pub fn main() { - use std::env; + exit(rustc_driver::run(move || { + use std::env; - if std::env::args().any(|a| a == "--version" || a == "-V") { - show_version(); - return; - } + if std::env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } - let sys_root = option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); - if orig_args.len() <= 1 { - std::process::exit(1); - } - if orig_args[1] == "rustc" { - // we still want to be able to invoke it normally though - orig_args.remove(1); - } - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() - } else { - orig_args - .clone() - .into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + if orig_args[1] == "rustc" { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; - // this check ensures that dependencies are built but not linted and the final - // crate is - // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); + // this check ensures that dependencies are built but not linted and the final + // crate is + // linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") + || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); - if clippy_enabled { - args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); - if let Ok(extra_args) = env::var("CLIPPY_ARGS") { - args.extend( - extra_args - .split("__CLIPPY_HACKERY__") - .filter(|s| !s.is_empty()) - .map(str::to_owned), - ); + if clippy_enabled { + args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + if let Ok(extra_args) = env::var("CLIPPY_ARGS") { + args.extend( + extra_args + .split("__CLIPPY_HACKERY__") + .filter(|s| !s.is_empty()) + .map(str::to_owned), + ); + } } - } - let mut controller = CompileController::basic(); - if clippy_enabled { - controller.after_parse.callback = Box::new(move |state| { - let mut registry = rustc_plugin::registry::Registry::new( - state.session, - state - .krate - .as_ref() - .expect( - "at this compilation stage \ - the crate must be parsed", - ) - .span, - ); - registry.args_hidden = Some(Vec::new()); + let mut controller = CompileController::basic(); + if clippy_enabled { + controller.after_parse.callback = Box::new(move |state| { + let mut registry = rustc_plugin::registry::Registry::new( + state.session, + state + .krate + .as_ref() + .expect( + "at this compilation stage \ + the crate must be parsed", + ) + .span, + ); + registry.args_hidden = Some(Vec::new()); - let conf = clippy_lints::read_conf(®istry); - clippy_lints::register_plugins(&mut registry, &conf); + let conf = clippy_lints::read_conf(®istry); + clippy_lints::register_plugins(&mut registry, &conf); - let rustc_plugin::registry::Registry { - early_lint_passes, - late_lint_passes, - lint_groups, - llvm_passes, - attributes, - .. - } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } + let rustc_plugin::registry::Registry { + early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + .. + } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); - } - clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); + for (name, to) in lint_groups { + ls.register_group(Some(sess), true, name, to); + } + clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - }); - } - controller.compilation_done.stop = Compilation::Stop; + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + }); + } + controller.compilation_done.stop = Compilation::Stop; - if rustc_driver::run_compiler(&args, Box::new(controller), None, None) - .0 - .is_err() - { - exit(101); - } + let args = args; + rustc_driver::run_compiler(&args, Box::new(controller), None, None) + }) as i32) } -- cgit 1.4.1-3-g733a5 From fc31dc01def04c1db782c4e6ed0457f9047dfcdf Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 27 Aug 2018 17:35:30 +0200 Subject: docs: make example in new_without_default lint syntax highlighted --- clippy_lints/src/new_without_default.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 224326b3d17..820e76f886e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -21,7 +21,7 @@ use crate::utils::sugg::DiagnosticBuilderExt; /// /// **Example:** /// -/// ```rust,ignore +/// ```rust /// struct Foo(Bar); /// /// impl Foo { @@ -63,7 +63,7 @@ declare_clippy_lint! { /// /// **Example:** /// -/// ```rust,ignore +/// ```rust /// struct Foo; /// /// impl Foo { -- cgit 1.4.1-3-g733a5 From 350036a0c7bd64bd49049f1864a575fad9216677 Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Mon, 27 Aug 2018 23:22:07 +0100 Subject: default_trait_access skips ::default() This includes the type name, so is clear, and may be necessary. There doesn't seem to be an obviously cleaner way to pull out the literal text of the named type here. Fixes #2879 --- clippy_lints/src/default_trait_access.rs | 7 +++++++ tests/ui/default_trait_access.rs | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index f01e106df26..d3598a5bdaa 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -48,6 +48,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { then { match qpath { QPath::Resolved(..) => { + if let ExprKind::Call(ref method, ref _args) = expr.node { + if format!("{:?}", method).contains(" as Default>") { + return + } + } + + // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. let expr_ty = cx.tables.expr_ty(expr); diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 675e64246fa..eba024353f9 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -41,8 +41,10 @@ fn main() { let s18 = TupleStructDerivedDefault::default(); + let s19 = ::default(); + println!( - "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]", + "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}], [{:?}]", s1, s2, s3, @@ -61,6 +63,7 @@ fn main() { s16, s17, s18, + s19, ); } -- cgit 1.4.1-3-g733a5 From 340500ede595d0498bf8f13fd489d5c5478fa48d Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Tue, 28 Aug 2018 10:24:21 +0800 Subject: Fix typo for panel cursor --- util/gh-pages/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 0088ecc3d89..656a7341257 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -14,7 +14,7 @@ .form-inline .checkbox { margin-right: 0.6em } - .panel-heading { pointer: cursor; } + .panel-heading { cursor: pointer; } .panel-heading:hover { background-color: #eee; } .panel-title { display: flex; } -- cgit 1.4.1-3-g733a5 From d99cea0f16633556871a59500c610782b07233b9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 28 Aug 2018 13:13:42 +0200 Subject: Update imports and rustup --- CONTRIBUTING.md | 2 +- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/assign_ops.rs | 4 ++-- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/copy_iterator.rs | 2 +- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/default_trait_access.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 7 +++---- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 8 ++++---- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 6 ++---- clippy_lints/src/identity_conversion.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infallible_destructuring_match.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/inherent_impl.rs | 14 ++++++++++---- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/invalid_ref.rs | 2 +- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/literal_representation.rs | 2 +- clippy_lints/src/loops.rs | 15 +++++++-------- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 6 +++--- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/missing_doc.rs | 7 ++++--- clippy_lints/src/missing_inline.rs | 6 ++++-- clippy_lints/src/multiple_crate_versions.rs | 9 ++++++--- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 9 ++++----- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 ++-- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- clippy_lints/src/overflow_check_conditional.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/precedence.rs | 2 +- clippy_lints/src/ptr.rs | 5 ++--- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 6 +++--- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 5 ++--- clippy_lints/src/types.rs | 6 +++--- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 16 ++++++++-------- clippy_lints/src/utils/usage.rs | 2 +- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/write.rs | 2 +- clippy_lints/src/zero_div_zero.rs | 2 +- 111 files changed, 164 insertions(+), 159 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 232752c2025..7de4f850c1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -185,7 +185,7 @@ It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerate ```rust // ./clippy_lints/src/else_if_without_else.rs -use rustc::lint::*; +use rustc::lint::{EarlyLintPass, LintArray, LintPass}; // ... diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index cd2444ff31f..fe00d325f77 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 90f72d3d184..209963e0688 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Span; diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 7d4f4e7cbc3..28fd96e3aac 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -2,7 +2,7 @@ use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_an use crate::utils::{higher, sugg}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; @@ -133,7 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // the crate node is the only one that is not in the map if_chain! { if parent_impl != ast::CRATE_NODE_ID; - if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); + if let hir::Node::Item(item) = cx.tcx.hir.get(parent_impl); if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if trait_ref.path.def.def_id() == trait_id; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 9804d3a0f07..66144706816 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -6,7 +6,7 @@ use crate::utils::{ without_block_comments, }; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, TyCtxt}; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 12de4faa753..86788fded05 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast::LitKind; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index cfec01d14ae..e5af0789064 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 6d086c13ff8..5c9b571c78c 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 2771006aad3..09fcf47c920 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -12,7 +12,7 @@ //! //! This lint is **warn** by default -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 49518d1bb4e..42788e77d6e 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty::Ty; use rustc::hir::*; diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index ac0c2ed32c6..031b088bf9e 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,6 +1,6 @@ use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use rustc::hir::{Item, ItemKind}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; /// **What it does:** Checks for types that implement `Copy` as well as diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 93074eadd65..ee53fca9f70 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -1,7 +1,7 @@ //! calculate cyclomatic complexity and warn about overly complex functions use rustc::cfg::CFG; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::ty; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index f01e106df26..09c60760076 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index e3abfe93810..9df2e257b1e 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 12128eda258..957ede66698 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use pulldown_cmark; -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::source_map::{BytePos, Span}; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 013a75e6457..70dc532e55b 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -1,7 +1,7 @@ //! Lint on unnecessary double comparisons. Some examples: use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Span; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 1e6189e3839..5aca7d734e2 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index ef5d18f081a..77d3014d9fd 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::Spanned; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 39404bbafcc..1259b49d93a 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,6 +1,6 @@ //! lint on if expressions with an else if, but without a final else branch -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index f95ae32d561..86f9fbdba9b 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,6 +1,6 @@ //! lint when there is an enum with no variants -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 142a099f539..46ef16ddc73 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::Span; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 2551f624cb1..2402cfde5b3 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -1,7 +1,7 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::ty; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index ca38d497df4..51277516571 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,6 +1,6 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, Lint}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index dfbc3b12633..a08d9f39382 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 2976700428c..e6d70b22fde 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,6 +1,6 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Span; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 2cd2a46cbab..3c61509d1f7 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,7 +1,6 @@ use rustc::hir::*; use rustc::hir::intravisit as visit; -use rustc::hir::map::Node::{NodeExpr, NodeStmt}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt_, Categorization}; @@ -100,7 +99,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { let map = &self.cx.tcx.hir; if map.is_argument(consume_pat.id) { // Skip closure arguments - if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { + if let Some(Node::Expr(..)) = map.find(map.get_parent_node(consume_pat.id)) { return; } if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { @@ -110,7 +109,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } if let Categorization::Rvalue(..) = cmt.cat { let id = map.hir_to_node_id(cmt.hir_id); - if let Some(NodeStmt(st)) = map.find(map.get_parent_node(id)) { + if let Some(Node::Stmt(st)) = map.find(map.get_parent_node(id)) { if let StmtKind::Decl(ref decl, _) = st.node { if let DeclKind::Local(ref loc) = decl.node { if let Some(ref ex) = loc.init { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 260cca76c8c..f60785662dd 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::*; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 9ddc3ddbfe7..f1c31d095e1 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,7 +1,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; @@ -189,9 +189,9 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { }; let stop_early = match parent_node { - map::Node::NodeExpr(expr) => check_expr(vis, expr), - map::Node::NodeStmt(stmt) => check_stmt(vis, stmt), - map::Node::NodeItem(_) => { + Node::Expr(expr) => check_expr(vis, expr), + Node::Stmt(stmt) => check_stmt(vis, stmt), + Node::Item(_) => { // We reached the top of the function, stop. break; }, diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 52af7e129ab..df540cad931 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,5 +1,5 @@ use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 22e6834ee88..f0cee563a2e 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 22f6df65506..f541abee8a7 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 4f83caa43dd..f967b9ce58e 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 60001c792c0..2f46891e6a1 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast; use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index b86e3332188..2f076dc1f6e 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,7 +1,7 @@ use matches::matches; use rustc::hir::intravisit; use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty; use rustc::hir::def::Def; @@ -85,9 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { span: Span, nodeid: ast::NodeId, ) { - use rustc::hir::map::Node::*; - - let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { + let is_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { matches!(item.node, hir::ItemKind::Impl(_, _, _, _, Some(_), _, _)) } else { false diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 1909f2f8ff4..3fa30dee988 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::NodeId; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 31e955dc570..b0c290ffc0e 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,6 +1,6 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Span; use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index bc97584a23d..f1b8aadef67 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index fea3069f37d..153bfbb9779 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,7 +1,7 @@ //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 9ec9c9f83b4..01a659473c1 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -5,7 +5,7 @@ use crate::utils; use crate::utils::higher; use crate::utils::higher::Range; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast::RangeLimits; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 8b8cb32deb1..a085f32ed84 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -1,6 +1,6 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index eaa93cb62f8..d42a2380ec4 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index fc06af81574..46dbb5bc39f 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -1,11 +1,12 @@ //! lint on inherent implementations use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use std::collections::HashMap; use std::default::Default; use syntax_pos::Span; +use crate::utils::span_lint_and_then; /// **What it does:** Checks for multiple inherent implementations of a struct /// @@ -81,12 +82,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { .map(|(span, _)| span); if let Some(initial_span) = impl_spans.nth(0) { impl_spans.for_each(|additional_span| { - cx.span_lint_note( + span_lint_and_then( + cx, MULTIPLE_INHERENT_IMPL, *additional_span, "Multiple implementations of this structure", - *initial_span, - "First implementation here", + |db| { + db.span_note( + *initial_span, + "First implementation here", + ); + }, ) }) } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 70f88a76f45..b879d734929 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,6 +1,6 @@ //! checks for `#[inline]` on trait methods without bodies -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::{Attribute, Name}; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 9b6fc579a31..086567ac531 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,6 +1,6 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 9c7d4626e0a..58f1575abb6 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 07ef086d694..2ea6c0e0447 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,7 +1,7 @@ //! lint when items are used after statements use matches::matches; -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 2c03b6b5f68..3e49f866170 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,6 +1,6 @@ //! lint when there is a large size difference between variants on an enum -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 2fb4c691ce8..e14f3bc24b7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,6 +1,6 @@ use rustc::hir::def_id::DefId; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty; use std::collections::HashSet; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 57ca5eff955..494efc22538 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index d8e6a43f864..7da62b9d458 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,6 +1,6 @@ use crate::reexport::*; use matches::matches; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::*; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 45f9af49a15..9437b243cbb 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -1,7 +1,7 @@ //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast::*; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 973b706801a..988256ab29e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -4,8 +4,7 @@ use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; -use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::middle::region; @@ -1330,7 +1329,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( let parent_scope = map.get_enclosing_scope(expr.id) .and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { - if let NodeBlock(block) = map.get(parent_id) { + if let Node::Block(block) = map.get(parent_id) { for (id, _) in visitor .states .iter() @@ -1506,7 +1505,7 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option bool { fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr, iter_expr: &Expr) -> bool { if_chain! { if let Some(loop_block) = get_enclosing_block(cx, match_expr.id); - if let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)); + if let Some(Node::Expr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)); then { return is_loop_nested(cx, loop_expr, iter_expr) } @@ -2068,13 +2067,13 @@ fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr, iter_expr: &Expr) return false; } match cx.tcx.hir.find(parent) { - Some(NodeExpr(expr)) => match expr.node { + Some(Node::Expr(expr)) => match expr.node { ExprKind::Loop(..) | ExprKind::While(..) => { return true; }, _ => (), }, - Some(NodeBlock(block)) => { + Some(Node::Block(block)) => { let mut block_visitor = LoopNestVisitor { id, iterator: iter_name, @@ -2085,7 +2084,7 @@ fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr, iter_expr: &Expr) return false; } }, - Some(NodeStmt(_)) => (), + Some(Node::Stmt(_)) => (), _ => { return false; }, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index c570f0b32bf..bd304db2dd5 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index eff00896c7f..2376b1a2b48 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,5 +1,5 @@ use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 691d61f55ba..6dc16e623a4 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 80130de15d7..76df98727f9 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::{Expr, ExprKind}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 1c31c414d2b..3bc1282fa15 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,6 +1,6 @@ use matches::matches; use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, Lint, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; @@ -1145,14 +1145,14 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if let ty::Ref(..) = cx.tables.expr_ty(arg).sty { let parent = cx.tcx.hir.get_parent_node(expr.id); match cx.tcx.hir.get(parent) { - hir::map::NodeExpr(parent) => match parent.node { + hir::Node::Expr(parent) => match parent.node { // &*x is a nop, &x.clone() is not hir::ExprKind::AddrOf(..) | // (*x).func() is useless, x.clone().func() can work in case func borrows mutably hir::ExprKind::MethodCall(..) => return, _ => {}, } - hir::map::NodeStmt(stmt) => { + hir::Node::Stmt(stmt) => { if let hir::StmtKind::Decl(ref decl, _) = stmt.node { if let hir::DeclKind::Local(ref loc) = decl.node { if let hir::PatKind::Ref(..) = loc.pat.node { diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index bc573841cc8..b187c28def6 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use std::cmp::Ordering; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a43c60f111f..7fab12bd9d9 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -2,7 +2,7 @@ use crate::reexport::*; use matches::matches; use rustc::hir::*; use rustc::hir::intravisit::FnKind; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; @@ -522,7 +522,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { let parent_fn = cx.tcx.hir.get_parent(expr.id); let parent_impl = cx.tcx.hir.get_parent(parent_fn); if parent_impl != CRATE_NODE_ID { - if let map::NodeItem(item) = cx.tcx.hir.get(parent_impl) { + if let Node::Item(item) = cx.tcx.hir.get(parent_impl) { if let ItemKind::Impl(.., Some(ref trait_ref), _, _) = item.node { if trait_ref.path.def.def_id() == partial_eq_trait_id { // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 6c82fa58e8d..4edb6a9133a 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use std::collections::HashMap; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 9735799d136..339ab757702 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -19,13 +19,13 @@ // use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; use rustc::{declare_lint, lint_array}; use rustc::ty; use syntax::ast; use syntax::attr; use syntax::source_map::Span; -use crate::utils::in_macro; +use crate::utils::{span_lint, in_macro}; /// **What it does:** Warns if there is missing doc for any documentable item /// (public or private). @@ -87,7 +87,8 @@ impl MissingDoc { .iter() .any(|a| a.is_value_str() && a.name() == "doc"); if !has_doc { - cx.span_lint( + span_lint( + cx, MISSING_DOCS_IN_PRIVATE_ITEMS, sp, &format!("missing documentation for {}", desc), diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 8e2b08b5152..c0f12bd3f7e 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -10,10 +10,11 @@ // use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::source_map::Span; +use crate::utils::span_lint; /// **What it does:** it lints if an exported function, method, trait method with default impl, /// or trait method impl is not `#[inline]`. @@ -74,7 +75,8 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, .iter() .any(|a| a.name() == "inline" ); if !has_inline { - cx.span_lint( + span_lint( + cx, MISSING_INLINE_IN_PUBLIC_ITEMS, sp, &format!("missing `#[inline]` for {}", desc), diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index d4246045506..78458843ffc 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,8 +1,9 @@ //! lint on multiple versions of a crate being used -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; +use crate::utils::span_lint; use cargo_metadata; use itertools::Itertools; @@ -43,7 +44,8 @@ impl EarlyLintPass for Pass { let metadata = match cargo_metadata::metadata_deps(None, true) { Ok(metadata) => metadata, Err(_) => { - cx.span_lint( + span_lint( + cx, MULTIPLE_CRATE_VERSIONS, krate.span, "could not read cargo metadata" @@ -62,7 +64,8 @@ impl EarlyLintPass for Pass { if group.len() > 1 { let versions = group.into_iter().map(|p| p.version).join(", "); - cx.span_lint( + span_lint( + cx, MULTIPLE_CRATE_VERSIONS, krate.span, &format!("multiple versions for dependency `{}`: {}", name, versions), diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index d8561241001..5c8a2648a18 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,6 +1,6 @@ use rustc::hir; use rustc::hir::intravisit; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use rustc::ty; use crate::utils::{higher, span_lint}; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 02a80a19e79..5b562f3dd34 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 19d860dab36..90b38440a83 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -2,7 +2,7 @@ //! //! This lint is **warn** by default -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::LitKind; diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index ae931e58326..b8ac425fd59 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -2,7 +2,7 @@ //! //! This lint is **warn** by default -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 1679a9007b4..d5a16f2122f 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -2,7 +2,7 @@ //! //! This lint is **warn** by default -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 0c9b354035f..e5f01847ed1 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -27,7 +27,7 @@ //! ``` //! //! This lint is **warn** by default. -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast; use syntax::source_map::{original_sp, DUMMY_SP}; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c93cda55724..06baf895c93 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,8 +1,7 @@ use matches::matches; use rustc::hir::*; -use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, RegionKind, TypeFoldable}; @@ -90,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } // Exclude non-inherent impls - if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | ItemKind::Trait(..)) { @@ -340,7 +339,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { if let Some(node) = self.cx.tcx.hir.find(id) { match node { - map::Node::NodeExpr(e) => { + Node::Expr(e) => { // `match` and `if let` if let ExprKind::Match(ref c, ..) = e.node { self.spans_need_deref @@ -350,7 +349,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { } }, - map::Node::NodeStmt(s) => { + Node::Stmt(s) => { // `let = x;` if_chain! { if let StmtKind::Decl(ref decl, _) = s.node; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index f53e2cb0cce..bec875d16d6 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; @@ -20,7 +20,7 @@ use crate::utils::{self, paths, span_lint}; /// /// ```rust /// use std::cmp::Ordering; -/// +/// /// // Bad /// let a = 1.0; /// let b = std::f64::NAN; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 2b0c021ea03..5246e62aecb 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::{Span, Spanned}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 820e76f886e..4dd2ea98399 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,6 +1,6 @@ use rustc::hir::def_id::DefId; use rustc::hir; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 119b4c2d861..c2692f88187 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { if parent_id == cur_expr.id { break; } - if let Some(map::NodeExpr(parent_expr)) = cx.tcx.hir.find(parent_id) { + if let Some(Node::Expr(parent_expr)) = cx.tcx.hir.find(parent_id) { match &parent_expr.node { ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index acfa341ed1f..14aba635c1a 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LintArray, LintPass, EarlyContext, EarlyLintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 2a7f71c7145..52eb86a0bc0 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index ac399e238b6..bfb88449fba 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,5 +1,5 @@ use rustc::hir::{Expr, ExprKind}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::LitKind; use syntax::source_map::{Span, Spanned}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 5714bdb521c..cb230bc9fc5 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index e603773f7ba..e21c0718612 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast::LitKind; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 675d014c527..fe93a8bbe99 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index c4e802adaee..42bbe687832 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Spanned; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index b040bd91f8d..cedb6e0b26b 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -2,9 +2,8 @@ use std::borrow::Cow; use rustc::hir::*; -use rustc::hir::map::NodeItem; use rustc::hir::QPath; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; @@ -112,7 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if let ImplItemKind::Method(ref sig, body_id) = item.node { - if let Some(NodeItem(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) { + if let Some(Node::Item(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) { if let ItemKind::Impl(_, _, _, _, Some(_), _, _) = it.node { return; // ignore trait impls } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 630dd1b57be..cb98ecd3dec 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index ba25e50d7c0..bef4532bbe5 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index ba8b11e55df..3021ef2dc47 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use crate::utils::{span_lint_and_sugg}; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index f349f46d926..f5bc03c6d6e 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,5 +1,5 @@ use syntax::ast::{Expr, ExprKind, UnOp}; -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use crate::utils::{snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 4553b08e747..5fe37e16484 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,6 +1,6 @@ use regex_syntax; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use std::collections::HashSet; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index b9a4c6ebb19..093ad0358bc 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 8125cc4153b..694433a8b92 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use syntax::ast; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index ce326ea72ca..41d8b1f7d24 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use crate::utils::{get_trait_def_id, paths, span_lint}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index cc4aa129870..4964b7e79ef 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,5 +1,5 @@ use crate::reexport::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::FnKind; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index d66163984aa..2b915f46175 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::source_map::Spanned; use crate::utils::SpanlessEq; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index b0a8a2d0061..7e0684e7f16 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir; @@ -76,7 +76,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { // as a child node let mut parent_expr = cx.tcx.hir.get_parent_node(expr.id); while parent_expr != ast::CRATE_NODE_ID { - if let hir::map::Node::NodeExpr(e) = cx.tcx.hir.get(parent_expr) { + if let hir::Node::Expr(e) = cx.tcx.hir.get(parent_expr) { match e.node { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot, _) @@ -187,7 +187,7 @@ fn check_binop<'a>( if_chain! { if parent_impl != ast::CRATE_NODE_ID; - if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl); + if let hir::Node::Item(item) = cx.tcx.hir.get(parent_impl); if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.def.def_id()); if binop != expected_ops[idx]; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 14c8e94d30c..7fd72cbea32 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,6 +1,6 @@ use matches::matches; use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 28c5971e852..9fe22b7dafc 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index d88a970db75..8f417861ca9 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -3,9 +3,8 @@ use std::cmp; use matches::matches; use rustc::hir; use rustc::hir::*; -use rustc::hir::map::*; use rustc::hir::intravisit::FnKind; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; @@ -109,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } // Exclude non-inherent impls - if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | ItemKind::Trait(..)) { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 024aba7e85e..a38d232d3e1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2,7 +2,7 @@ use crate::reexport::*; use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; @@ -140,7 +140,7 @@ impl LintPass for TypePass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { // skip trait implementations, see #605 - if let Some(map::NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) { + if let Some(hir::Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) { if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { return; } @@ -514,7 +514,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { if !is_questionmark_desugar_marked_call(expr) { if_chain!{ let opt_parent_node = map.find(map.get_parent_node(expr.id)); - if let Some(hir::map::NodeExpr(parent_expr)) = opt_parent_node; + if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; if is_questionmark_desugar_marked_call(parent_expr); then {} else { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 2768efca88e..4e5c9a94424 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 37a5836f153..753ee40be7f 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index a9a7e102ab2..e388ca93888 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir; use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 04b4fcabdd8..1fd143d6d03 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 2a557ed8e43..0435db93ee6 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 4310325475a..f45ec75aedc 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -3,7 +3,7 @@ #![allow(print_stdout, use_debug)] -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 57486b30d34..30c6db977f7 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,5 +1,5 @@ use crate::consts::{constant_simple, constant_context}; -use rustc::lint::*; +use rustc::lint::LateContext; use rustc::hir::*; use rustc::ty::{TypeckTables}; use std::hash::{Hash, Hasher}; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b6c241a6825..73c86d8bf67 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -2,7 +2,7 @@ //! checks for attributes -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir; use rustc::hir::print; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 6df41f1cd41..39a3d9b3b74 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass}; use rustc::{declare_lint, lint_array}; use rustc::hir::*; use rustc::hir; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b753f8072d0..976161a40a9 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -6,7 +6,7 @@ use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::Def; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc::hir::map::Node; +use rustc::hir::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; @@ -309,9 +309,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option, expr: &Expr) -> Option { let parent_id = cx.tcx.hir.get_parent(expr.id); match cx.tcx.hir.find(parent_id) { - Some(Node::NodeItem(&Item { ref name, .. })) => Some(*name), - Some(Node::NodeTraitItem(&TraitItem { ident, .. })) | - Some(Node::NodeImplItem(&ImplItem { ident, .. })) => Some(ident.name), + Some(Node::Item(&Item { ref name, .. })) => Some(*name), + Some(Node::TraitItem(&TraitItem { ident, .. })) | + Some(Node::ImplItem(&ImplItem { ident, .. })) => Some(ident.name), _ => None, } } @@ -464,7 +464,7 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c return None; } map.find(parent_id).and_then(|node| { - if let Node::NodeExpr(parent) = node { + if let Node::Expr(parent) = node { Some(parent) } else { None @@ -478,11 +478,11 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI .and_then(|enclosing_id| map.find(enclosing_id)); if let Some(node) = enclosing_node { match node { - Node::NodeBlock(block) => Some(block), - Node::NodeItem(&Item { + Node::Block(block) => Some(block), + Node::Item(&Item { node: ItemKind::Fn(_, _, _, eid), .. - }) | Node::NodeImplItem(&ImplItem { + }) | Node::ImplItem(&ImplItem { node: ImplItemKind::Method(_, eid), .. }) => match cx.tcx.hir.body(eid).value.node { diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 95199b9f208..2661bc945f3 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::LateContext; use rustc::hir::def::Def; use rustc::hir::*; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index f86ce5ab786..8e49a3d4326 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 97fe12f2330..bc9fa09c932 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,4 +1,4 @@ -use rustc::lint::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use syntax::ast::*; use syntax::tokenstream::{ThinTokenStream, TokenStream}; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 7c8af7880ba..77bc4802742 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,5 +1,5 @@ use crate::consts::{constant_simple, Constant}; -use rustc::lint::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; -- cgit 1.4.1-3-g733a5 From 05f637cf88a4555ac8e521811feb6c598c5dbee1 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 28 Aug 2018 21:32:20 -0500 Subject: Make clippy_lints::{utils,consts} modules private, remove unused items. --- ci/base-tests.sh | 1 + clippy_lints/src/consts.rs | 16 ---- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/utils/camel_case.rs | 114 +++++++++++++++++++++++++ clippy_lints/src/utils/conf.rs | 15 ---- clippy_lints/src/utils/mod.rs | 161 ++++++++++++++++++----------------- clippy_lints/src/utils/paths.rs | 9 -- clippy_lints/src/utils/sugg.rs | 9 -- tests/camel_case.rs | 50 ----------- tests/trim_multiline.rs | 57 ------------- tests/without_block_comments.rs | 27 ------ 11 files changed, 201 insertions(+), 262 deletions(-) create mode 100644 clippy_lints/src/utils/camel_case.rs delete mode 100644 tests/camel_case.rs delete mode 100644 tests/trim_multiline.rs delete mode 100644 tests/without_block_comments.rs diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 13b652c0f7d..f7c3342fe38 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -7,6 +7,7 @@ remark -f *.md > /dev/null # build clippy in debug mode and run tests cargo build --features debugging cargo test --features debugging +cd clippy_lints && cargo test && cd .. mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index ff189d6e893..cf3ea0414da 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -16,22 +16,6 @@ use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; use crate::utils::{sext, unsext, clip}; -#[derive(Debug, Copy, Clone)] -pub enum FloatWidth { - F32, - F64, - Any, -} - -impl From for FloatWidth { - fn from(ty: FloatTy) -> Self { - match ty { - FloatTy::F32 => FloatWidth::F32, - FloatTy::F64 => FloatWidth::F64, - } - } -} - /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] pub enum Constant { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 84db58b8971..7aa41e80126 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -48,9 +48,9 @@ macro_rules! declare_clippy_lint { }; } -pub mod consts; +mod consts; #[macro_use] -pub mod utils; +mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; diff --git a/clippy_lints/src/utils/camel_case.rs b/clippy_lints/src/utils/camel_case.rs new file mode 100644 index 00000000000..e8a8d510fe5 --- /dev/null +++ b/clippy_lints/src/utils/camel_case.rs @@ -0,0 +1,114 @@ +/// Return the index of the character after the first camel-case component of +/// `s`. +pub fn camel_case_until(s: &str) -> usize { + let mut iter = s.char_indices(); + if let Some((_, first)) = iter.next() { + if !first.is_uppercase() { + return 0; + } + } else { + return 0; + } + let mut up = true; + let mut last_i = 0; + for (i, c) in iter { + if up { + if c.is_lowercase() { + up = false; + } else { + return last_i; + } + } else if c.is_uppercase() { + up = true; + last_i = i; + } else if !c.is_lowercase() { + return i; + } + } + if up { + last_i + } else { + s.len() + } +} + +/// Return index of the last camel-case component of `s`. +pub fn camel_case_from(s: &str) -> usize { + let mut iter = s.char_indices().rev(); + if let Some((_, first)) = iter.next() { + if !first.is_lowercase() { + return s.len(); + } + } else { + return s.len(); + } + let mut down = true; + let mut last_i = s.len(); + for (i, c) in iter { + if down { + if c.is_uppercase() { + down = false; + last_i = i; + } else if !c.is_lowercase() { + return last_i; + } + } else if c.is_lowercase() { + down = true; + } else { + return last_i; + } + } + last_i +} + +#[cfg(test)] +mod test { + use super::{camel_case_from, camel_case_until}; + + #[test] + fn from_full() { + assert_eq!(camel_case_from("AbcDef"), 0); + assert_eq!(camel_case_from("Abc"), 0); + } + + #[test] + fn from_partial() { + assert_eq!(camel_case_from("abcDef"), 3); + assert_eq!(camel_case_from("aDbc"), 1); + } + + #[test] + fn from_not() { + assert_eq!(camel_case_from("AbcDef_"), 7); + assert_eq!(camel_case_from("AbcDD"), 5); + } + + #[test] + fn from_caps() { + assert_eq!(camel_case_from("ABCD"), 4); + } + + #[test] + fn until_full() { + assert_eq!(camel_case_until("AbcDef"), 6); + assert_eq!(camel_case_until("Abc"), 3); + } + + #[test] + fn until_not() { + assert_eq!(camel_case_until("abcDef"), 0); + assert_eq!(camel_case_until("aDbc"), 0); + } + + #[test] + fn until_partial() { + assert_eq!(camel_case_until("AbcDef_"), 6); + assert_eq!(camel_case_until("CallTypeC"), 8); + assert_eq!(camel_case_until("AbcDD"), 3); + } + + #[test] + fn until_caps() { + assert_eq!(camel_case_until("ABCD"), 0); + } +} \ No newline at end of file diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 1567bd9ffb6..f910080c229 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -38,17 +38,6 @@ pub enum Error { Io(io::Error), /// Not valid toml or doesn't fit the expected conf format Toml(String), - /// Type error. - Type( - /// The name of the key. - &'static str, - /// The expected type. - &'static str, - /// The type we got instead. - &'static str, - ), - /// There is an unknown key is the file. - UnknownKey(String), } impl fmt::Display for Error { @@ -56,10 +45,6 @@ impl fmt::Display for Error { match *self { Error::Io(ref err) => err.fmt(f), Error::Toml(ref err) => err.fmt(f), - Error::Type(key, expected, got) => { - write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) - }, - Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 976161a40a9..650ea373d97 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -21,9 +21,11 @@ use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::source_map::{Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; -use syntax::ptr::P; use syntax::symbol::keywords; +mod camel_case; +pub use self::camel_case::{camel_case_from, camel_case_until}; + pub mod comparisons; pub mod conf; pub mod constants; @@ -37,8 +39,6 @@ pub mod ptr; pub mod usage; pub use self::hir_utils::{SpanlessEq, SpanlessHash}; -pub type MethodArgs = HirVec>; - pub mod higher; /// Returns true if the two spans come from differing expansions (i.e. one is @@ -106,17 +106,6 @@ pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { } } -/// Check if the method call given in `expr` belongs to given type. -pub fn match_impl_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool { - let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; - let trt_id = cx.tcx.impl_of_method(method_call.def_id()); - if let Some(trt_id) = trt_id { - match_def_path(cx.tcx, trt_id, path) - } else { - false - } -} - /// Check if the method call given in `expr` belongs to given trait. pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool { let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; @@ -755,69 +744,6 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { } } -/// Return the index of the character after the first camel-case component of -/// `s`. -pub fn camel_case_until(s: &str) -> usize { - let mut iter = s.char_indices(); - if let Some((_, first)) = iter.next() { - if !first.is_uppercase() { - return 0; - } - } else { - return 0; - } - let mut up = true; - let mut last_i = 0; - for (i, c) in iter { - if up { - if c.is_lowercase() { - up = false; - } else { - return last_i; - } - } else if c.is_uppercase() { - up = true; - last_i = i; - } else if !c.is_lowercase() { - return i; - } - } - if up { - last_i - } else { - s.len() - } -} - -/// Return index of the last camel-case component of `s`. -pub fn camel_case_from(s: &str) -> usize { - let mut iter = s.char_indices().rev(); - if let Some((_, first)) = iter.next() { - if !first.is_lowercase() { - return s.len(); - } - } else { - return s.len(); - } - let mut down = true; - let mut last_i = s.len(); - for (i, c) in iter { - if down { - if c.is_uppercase() { - down = false; - last_i = i; - } else if !c.is_lowercase() { - return last_i; - } - } else if c.is_lowercase() { - down = true; - } else { - return last_i; - } - } - last_i -} - /// Convenience function to get the return type of a function pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'tcx> { let fn_def_id = cx.tcx.hir.local_def_id(fn_item); @@ -1109,3 +1035,84 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: NodeId } false } + +#[cfg(test)] +mod test { + use super::{trim_multiline, without_block_comments}; + + #[test] + fn test_trim_multiline_single_line() { + assert_eq!("", trim_multiline("".into(), false)); + assert_eq!("...", trim_multiline("...".into(), false)); + assert_eq!("...", trim_multiline(" ...".into(), false)); + assert_eq!("...", trim_multiline("\t...".into(), false)); + assert_eq!("...", trim_multiline("\t\t...".into(), false)); + } + + #[test] + #[rustfmt::skip] + fn test_trim_multiline_block() { + assert_eq!("\ + if x { + y + } else { + z + }", trim_multiline(" if x { + y + } else { + z + }".into(), false)); + assert_eq!("\ + if x { + \ty + } else { + \tz + }", trim_multiline(" if x { + \ty + } else { + \tz + }".into(), false)); + } + + #[test] + #[rustfmt::skip] + fn test_trim_multiline_empty_line() { + assert_eq!("\ + if x { + y + + } else { + z + }", trim_multiline(" if x { + y + + } else { + z + }".into(), false)); + } + + #[test] + fn test_without_block_comments_lines_without_block_comments() { + let result = without_block_comments(vec!["/*", "", "*/"]); + println!("result: {:?}", result); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); + assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); + + let result = without_block_comments(vec!["/* rust", "", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* one-line comment */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["foo", "bar", "baz"]); + assert_eq!(result, vec!["foo", "bar", "baz"]); + } +} \ No newline at end of file diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 4d89f8ddffb..3c03645cc1b 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -9,8 +9,6 @@ pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; -pub const BOX: [&str; 3] = ["std", "boxed", "Box"]; -pub const BOX_NEW: [&str; 4] = ["std", "boxed", "Box", "new"]; pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"]; pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"]; pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; @@ -22,16 +20,13 @@ pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"]; pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; -pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; -pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; -pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; @@ -43,7 +38,6 @@ pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"]; pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"]; pub const INTO: [&str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; -pub const IO_PRINT: [&str; 4] = ["std", "io", "stdio", "_print"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; @@ -69,9 +63,7 @@ pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeInclusive"]; pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"]; -pub const RANGE_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeInclusive"]; pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"]; pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"]; pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"]; @@ -81,7 +73,6 @@ pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -pub const REGEX_BYTES: [&str; 3] = ["regex", "re_bytes", "Regex"]; pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 3d587a72eec..a02e0144791 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -175,15 +175,6 @@ impl<'a> Sugg<'a> { make_unop("&mut *", self) } - /// Convenience method to create the `..` or `...` - /// suggestion. - pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { - match limit { - ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end), - ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end), - } - } - /// Add parenthesis to any expression that might need them. Suitable to the /// `self` argument of /// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`). diff --git a/tests/camel_case.rs b/tests/camel_case.rs deleted file mode 100644 index b7efbde6596..00000000000 --- a/tests/camel_case.rs +++ /dev/null @@ -1,50 +0,0 @@ -extern crate clippy_lints; - -use clippy_lints::utils::{camel_case_from, camel_case_until}; - -#[test] -fn from_full() { - assert_eq!(camel_case_from("AbcDef"), 0); - assert_eq!(camel_case_from("Abc"), 0); -} - -#[test] -fn from_partial() { - assert_eq!(camel_case_from("abcDef"), 3); - assert_eq!(camel_case_from("aDbc"), 1); -} - -#[test] -fn from_not() { - assert_eq!(camel_case_from("AbcDef_"), 7); - assert_eq!(camel_case_from("AbcDD"), 5); -} - -#[test] -fn from_caps() { - assert_eq!(camel_case_from("ABCD"), 4); -} - -#[test] -fn until_full() { - assert_eq!(camel_case_until("AbcDef"), 6); - assert_eq!(camel_case_until("Abc"), 3); -} - -#[test] -fn until_not() { - assert_eq!(camel_case_until("abcDef"), 0); - assert_eq!(camel_case_until("aDbc"), 0); -} - -#[test] -fn until_partial() { - assert_eq!(camel_case_until("AbcDef_"), 6); - assert_eq!(camel_case_until("CallTypeC"), 8); - assert_eq!(camel_case_until("AbcDD"), 3); -} - -#[test] -fn until_caps() { - assert_eq!(camel_case_until("ABCD"), 0); -} diff --git a/tests/trim_multiline.rs b/tests/trim_multiline.rs deleted file mode 100644 index a0db2e59a29..00000000000 --- a/tests/trim_multiline.rs +++ /dev/null @@ -1,57 +0,0 @@ - - -/// test the multiline-trim function -extern crate clippy_lints; - -use clippy_lints::utils::trim_multiline; - -#[test] -fn test_single_line() { - assert_eq!("", trim_multiline("".into(), false)); - assert_eq!("...", trim_multiline("...".into(), false)); - assert_eq!("...", trim_multiline(" ...".into(), false)); - assert_eq!("...", trim_multiline("\t...".into(), false)); - assert_eq!("...", trim_multiline("\t\t...".into(), false)); -} - -#[test] -#[rustfmt::skip] -fn test_block() { - assert_eq!("\ -if x { - y -} else { - z -}", trim_multiline(" if x { - y - } else { - z - }".into(), false)); - assert_eq!("\ -if x { -\ty -} else { -\tz -}", trim_multiline(" if x { - \ty - } else { - \tz - }".into(), false)); -} - -#[test] -#[rustfmt::skip] -fn test_empty_line() { - assert_eq!("\ -if x { - y - -} else { - z -}", trim_multiline(" if x { - y - - } else { - z - }".into(), false)); -} diff --git a/tests/without_block_comments.rs b/tests/without_block_comments.rs deleted file mode 100644 index 730c5cb128f..00000000000 --- a/tests/without_block_comments.rs +++ /dev/null @@ -1,27 +0,0 @@ -extern crate clippy_lints; -use clippy_lints::utils::without_block_comments; - -#[test] -fn test_lines_without_block_comments() { - let result = without_block_comments(vec!["/*", "", "*/"]); - println!("result: {:?}", result); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); - assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); - - let result = without_block_comments(vec!["/* rust", "", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* one-line comment */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["foo", "bar", "baz"]); - assert_eq!(result, vec!["foo", "bar", "baz"]); -} -- cgit 1.4.1-3-g733a5 From 5ebae01c1eb7beafb455d432bd4d4f8f612ead2a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 27 Aug 2018 09:49:54 -0400 Subject: New lint: Suggest `ptr.add([usize])` over `ptr.offset([usize] as isize)`. First part of #3047. --- clippy_lints/src/lib.rs | 4 + clippy_lints/src/ptr_offset_with_cast.rs | 130 +++++++++++++++++++++++++++++++ tests/ui/ptr_offset_with_cast.rs | 14 ++++ tests/ui/ptr_offset_with_cast.stderr | 10 +++ 4 files changed, 158 insertions(+) create mode 100644 clippy_lints/src/ptr_offset_with_cast.rs create mode 100644 tests/ui/ptr_offset_with_cast.rs create mode 100644 tests/ui/ptr_offset_with_cast.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 84db58b8971..ccb849a0c06 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -142,6 +142,7 @@ pub mod panic_unimplemented; pub mod partialeq_ne_impl; pub mod precedence; pub mod ptr; +pub mod ptr_offset_with_cast; pub mod question_mark; pub mod ranges; pub mod redundant_field_names; @@ -408,6 +409,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing); reg.register_late_lint_pass(box non_copy_const::NonCopyConst); + reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_lint_group("clippy_restriction", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -631,6 +633,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ptr::CMP_NULL, ptr::MUT_FROM_REF, ptr::PTR_ARG, + ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, question_mark::QUESTION_MARK, ranges::ITERATOR_STEP_BY_ZERO, ranges::RANGE_MINUS_ONE, @@ -755,6 +758,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { panic_unimplemented::PANIC_PARAMS, ptr::CMP_NULL, ptr::PTR_ARG, + ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, question_mark::QUESTION_MARK, redundant_field_names::REDUNDANT_FIELD_NAMES, regex::REGEX_MACRO, diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs new file mode 100644 index 00000000000..4a6bc8215ef --- /dev/null +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -0,0 +1,130 @@ +use rustc::{declare_lint, hir, lint, lint_array, ty}; +use syntax::ast; +use crate::utils; + +/// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an +/// `isize`. +/// +/// **Why is this bad?** If we’re always increasing the pointer address, we can avoid the numeric +/// cast by using the `add` method instead. +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let vec = vec![b'a', b'b', b'c']; +/// let ptr = vec.as_ptr(); +/// let offset = 1_usize; +/// +/// unsafe { ptr.offset(offset as isize); } +/// ``` +/// +/// Could be written: +/// +/// ```rust +/// let vec = vec![b'a', b'b', b'c']; +/// let ptr = vec.as_ptr(); +/// let offset = 1_usize; +/// +/// unsafe { ptr.add(offset); } +/// ``` +declare_clippy_lint! { + pub PTR_OFFSET_WITH_CAST, + style, + "uneeded pointer offset cast" +} + +#[derive(Copy, Clone, Debug)] +pub struct Pass; + +impl lint::LintPass for Pass { + fn get_lints(&self) -> lint::LintArray { + lint_array!(PTR_OFFSET_WITH_CAST) + } +} + +impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + // Check if the expressions is a ptr.offset method call + let [receiver_expr, arg_expr] = match expr_as_ptr_offset_call(cx, expr) { + Some(call_arg) => call_arg, + None => return, + }; + + // Check if the parameter to ptr.offset is a cast from usize to isize + let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) { + Some(cast_lhs_expr) => cast_lhs_expr, + None => return, + }; + + utils::span_lint_and_sugg( + cx, + PTR_OFFSET_WITH_CAST, + expr.span, + "use of `offset` with a `usize` casted to an `isize`", + "try", + build_suggestion(cx, receiver_expr, cast_lhs_expr), + ); + } +} + +// If the given expression is a cast from a usize, return the lhs of the cast +fn expr_as_cast_from_usize<'a, 'tcx>( + cx: &lint::LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, +) -> Option<&'tcx hir::Expr> { + if let hir::ExprKind::Cast(ref cast_lhs_expr, _) = expr.node { + if is_expr_ty_usize(cx, &cast_lhs_expr) { + return Some(cast_lhs_expr); + } + } + None +} + +// If the given expression is a ptr::offset method call, return the receiver and the arg of the +// method call. +fn expr_as_ptr_offset_call<'a, 'tcx>( + cx: &lint::LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, +) -> Option<[&'tcx hir::Expr; 2]> { + if let hir::ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node { + if path_segment.ident.name == "offset" && is_expr_ty_raw_ptr(cx, &args[0]) { + return Some([&args[0], &args[1]]); + } + } + None +} + +// Is the type of the expression a usize? +fn is_expr_ty_usize<'a, 'tcx>( + cx: &lint::LateContext<'a, 'tcx>, + expr: &hir::Expr, +) -> bool { + cx.tables.expr_ty(expr).sty == ty::TyKind::Uint(ast::UintTy::Usize) +} + +// Is the type of the expression a raw pointer? +fn is_expr_ty_raw_ptr<'a, 'tcx>( + cx: &lint::LateContext<'a, 'tcx>, + expr: &hir::Expr, +) -> bool { + if let ty::RawPtr(..) = cx.tables.expr_ty(expr).sty { + true + } else { + false + } +} + +fn build_suggestion<'a, 'tcx>( + cx: &lint::LateContext<'a, 'tcx>, + receiver_expr: &hir::Expr, + cast_lhs_expr: &hir::Expr, +) -> String { + match ( + utils::snippet_opt(cx, receiver_expr.span), + utils::snippet_opt(cx, cast_lhs_expr.span) + ) { + (Some(receiver), Some(cast_lhs)) => format!("{}.add({})", receiver, cast_lhs), + _ => String::new(), + } +} diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs new file mode 100644 index 00000000000..947021aaf8e --- /dev/null +++ b/tests/ui/ptr_offset_with_cast.rs @@ -0,0 +1,14 @@ +fn main() { + let vec = vec![b'a', b'b', b'c']; + let ptr = vec.as_ptr(); + + let offset_u8 = 1_u8; + let offset_usize = 1_usize; + let offset_isize = 1_isize; + + unsafe { + ptr.offset(offset_usize as isize); + ptr.offset(offset_isize as isize); + ptr.offset(offset_u8 as isize); + } +} diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr new file mode 100644 index 00000000000..1658f5f5366 --- /dev/null +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -0,0 +1,10 @@ +error: use of `offset` with a `usize` casted to an `isize` + --> $DIR/ptr_offset_with_cast.rs:10:9 + | +10 | ptr.offset(offset_usize as isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` + | + = note: `-D ptr-offset-with-cast` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From feb3e9fd5f8b24bcbe1a470b65dac66acb265721 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:02:26 -0500 Subject: switch lint from 'style' to 'complexity' --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ccb849a0c06..7d429ce4923 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -758,7 +758,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { panic_unimplemented::PANIC_PARAMS, ptr::CMP_NULL, ptr::PTR_ARG, - ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, question_mark::QUESTION_MARK, redundant_field_names::REDUNDANT_FIELD_NAMES, regex::REGEX_MACRO, @@ -819,6 +818,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, partialeq_ne_impl::PARTIALEQ_NE_IMPL, precedence::PRECEDENCE, + ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, ranges::RANGE_MINUS_ONE, ranges::RANGE_PLUS_ONE, ranges::RANGE_ZIP_WITH_LEN, diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 4a6bc8215ef..9c8382e43f2 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -30,7 +30,7 @@ use crate::utils; /// ``` declare_clippy_lint! { pub PTR_OFFSET_WITH_CAST, - style, + complexity, "uneeded pointer offset cast" } -- cgit 1.4.1-3-g733a5 From a7c1ea96c4a6dc3c6614331124200ac4c5588b6b Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:03:50 -0500 Subject: tweak comment --- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 9c8382e43f2..756f8dfe2e5 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { None => return, }; - // Check if the parameter to ptr.offset is a cast from usize to isize + // Check if the argument to ptr.offset is a cast from usize let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) { Some(cast_lhs_expr) => cast_lhs_expr, None => return, -- cgit 1.4.1-3-g733a5 From a48a6ef10f76b02a88927198f4e06d7e81b89027 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:07:23 -0500 Subject: utilize cx.tcx.types.usize --- clippy_lints/src/ptr_offset_with_cast.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 756f8dfe2e5..af9989a161c 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,5 +1,4 @@ use rustc::{declare_lint, hir, lint, lint_array, ty}; -use syntax::ast; use crate::utils; /// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an @@ -100,7 +99,7 @@ fn is_expr_ty_usize<'a, 'tcx>( cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr, ) -> bool { - cx.tables.expr_ty(expr).sty == ty::TyKind::Uint(ast::UintTy::Usize) + cx.tables.expr_ty(expr) == cx.tcx.types.usize } // Is the type of the expression a raw pointer? -- cgit 1.4.1-3-g733a5 From f7d1ef90a04ad40148dc0db4ccf739e8178b11b1 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:08:59 -0500 Subject: utilize .is_unsafe_ptr --- clippy_lints/src/ptr_offset_with_cast.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index af9989a161c..75451565510 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,4 +1,4 @@ -use rustc::{declare_lint, hir, lint, lint_array, ty}; +use rustc::{declare_lint, hir, lint, lint_array}; use crate::utils; /// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an @@ -107,11 +107,7 @@ fn is_expr_ty_raw_ptr<'a, 'tcx>( cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr, ) -> bool { - if let ty::RawPtr(..) = cx.tables.expr_ty(expr).sty { - true - } else { - false - } + cx.tables.expr_ty(expr).is_unsafe_ptr() } fn build_suggestion<'a, 'tcx>( -- cgit 1.4.1-3-g733a5 From 61c20c148e926310f011895693f88cafb5a26539 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:12:22 -0500 Subject: if no suggestion, dont add suggestion --- clippy_lints/src/ptr_offset_with_cast.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 75451565510..5fb31c4aefb 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -56,14 +56,13 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { None => return, }; - utils::span_lint_and_sugg( - cx, - PTR_OFFSET_WITH_CAST, - expr.span, - "use of `offset` with a `usize` casted to an `isize`", - "try", - build_suggestion(cx, receiver_expr, cast_lhs_expr), - ); + let msg = "use of `offset` with a `usize` casted to an `isize`"; + if let Some(sugg) = build_suggestion(cx, receiver_expr, cast_lhs_expr) { + utils::span_lint_and_sugg(cx, PTR_OFFSET_WITH_CAST, expr.span, msg, "try", sugg); + } else { + utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, msg); + } + } } @@ -114,12 +113,12 @@ fn build_suggestion<'a, 'tcx>( cx: &lint::LateContext<'a, 'tcx>, receiver_expr: &hir::Expr, cast_lhs_expr: &hir::Expr, -) -> String { +) -> Option { match ( utils::snippet_opt(cx, receiver_expr.span), utils::snippet_opt(cx, cast_lhs_expr.span) ) { - (Some(receiver), Some(cast_lhs)) => format!("{}.add({})", receiver, cast_lhs), - _ => String::new(), + (Some(receiver), Some(cast_lhs)) => Some(format!("{}.add({})", receiver, cast_lhs)), + _ => None, } } -- cgit 1.4.1-3-g733a5 From 2fa7351c1e0ca482ae13ca969be5975f1603a2b1 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:40:00 -0500 Subject: suggest wrapping_offset as well --- clippy_lints/src/ptr_offset_with_cast.rs | 58 +++++++++++++++++++++++++------- tests/ui/ptr_offset_with_cast.rs | 4 +++ tests/ui/ptr_offset_with_cast.stderr | 8 ++++- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 5fb31c4aefb..20934573f09 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,5 +1,6 @@ use rustc::{declare_lint, hir, lint, lint_array}; use crate::utils; +use std::fmt; /// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an /// `isize`. @@ -44,23 +45,23 @@ impl lint::LintPass for Pass { impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - // Check if the expressions is a ptr.offset method call - let [receiver_expr, arg_expr] = match expr_as_ptr_offset_call(cx, expr) { + // Check if the expressions is a ptr.offset or ptr.wrapping_offset method call + let (receiver_expr, arg_expr, method) = match expr_as_ptr_offset_call(cx, expr) { Some(call_arg) => call_arg, None => return, }; - // Check if the argument to ptr.offset is a cast from usize + // Check if the argument to the method call is a cast from usize let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) { Some(cast_lhs_expr) => cast_lhs_expr, None => return, }; - let msg = "use of `offset` with a `usize` casted to an `isize`"; - if let Some(sugg) = build_suggestion(cx, receiver_expr, cast_lhs_expr) { - utils::span_lint_and_sugg(cx, PTR_OFFSET_WITH_CAST, expr.span, msg, "try", sugg); + let msg = format!("use of `{}` with a `usize` casted to an `isize`", method); + if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) { + utils::span_lint_and_sugg(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg, "try", sugg); } else { - utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, msg); + utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); } } @@ -79,15 +80,20 @@ fn expr_as_cast_from_usize<'a, 'tcx>( None } -// If the given expression is a ptr::offset method call, return the receiver and the arg of the -// method call. +// If the given expression is a ptr::offset or ptr::wrapping_offset method call, return the +// receiver, the arg of the method call, and the method. fn expr_as_ptr_offset_call<'a, 'tcx>( cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, -) -> Option<[&'tcx hir::Expr; 2]> { +) -> Option<(&'tcx hir::Expr, &'tcx hir::Expr, Method)> { if let hir::ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node { - if path_segment.ident.name == "offset" && is_expr_ty_raw_ptr(cx, &args[0]) { - return Some([&args[0], &args[1]]); + if is_expr_ty_raw_ptr(cx, &args[0]) { + if path_segment.ident.name == "offset" { + return Some((&args[0], &args[1], Method::Offset)); + } + if path_segment.ident.name == "wrapping_offset" { + return Some((&args[0], &args[1], Method::WrappingOffset)); + } } } None @@ -111,6 +117,7 @@ fn is_expr_ty_raw_ptr<'a, 'tcx>( fn build_suggestion<'a, 'tcx>( cx: &lint::LateContext<'a, 'tcx>, + method: Method, receiver_expr: &hir::Expr, cast_lhs_expr: &hir::Expr, ) -> Option { @@ -118,7 +125,32 @@ fn build_suggestion<'a, 'tcx>( utils::snippet_opt(cx, receiver_expr.span), utils::snippet_opt(cx, cast_lhs_expr.span) ) { - (Some(receiver), Some(cast_lhs)) => Some(format!("{}.add({})", receiver, cast_lhs)), + (Some(receiver), Some(cast_lhs)) => { + Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs)) + }, _ => None, } } + +enum Method { + Offset, + WrappingOffset, +} + +impl Method { + fn suggestion(&self) -> &'static str { + match *self { + Method::Offset => "add", + Method::WrappingOffset => "wrapping_add", + } + } +} + +impl fmt::Display for Method { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Method::Offset => write!(f, "offset"), + Method::WrappingOffset => write!(f, "wrapping_offset"), + } + } +} \ No newline at end of file diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 947021aaf8e..4549f960ca0 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -10,5 +10,9 @@ fn main() { ptr.offset(offset_usize as isize); ptr.offset(offset_isize as isize); ptr.offset(offset_u8 as isize); + + ptr.wrapping_offset(offset_usize as isize); + ptr.wrapping_offset(offset_isize as isize); + ptr.wrapping_offset(offset_u8 as isize); } } diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index 1658f5f5366..16bbf328b33 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -6,5 +6,11 @@ error: use of `offset` with a `usize` casted to an `isize` | = note: `-D ptr-offset-with-cast` implied by `-D warnings` -error: aborting due to previous error +error: use of `wrapping_offset` with a `usize` casted to an `isize` + --> $DIR/ptr_offset_with_cast.rs:14:9 + | +14 | ptr.wrapping_offset(offset_usize as isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 2a486528ee13c861679c62a5451f7118591c3531 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:42:43 -0500 Subject: utilize carrier --- clippy_lints/src/ptr_offset_with_cast.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 20934573f09..08ae92d255e 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -121,15 +121,9 @@ fn build_suggestion<'a, 'tcx>( receiver_expr: &hir::Expr, cast_lhs_expr: &hir::Expr, ) -> Option { - match ( - utils::snippet_opt(cx, receiver_expr.span), - utils::snippet_opt(cx, cast_lhs_expr.span) - ) { - (Some(receiver), Some(cast_lhs)) => { - Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs)) - }, - _ => None, - } + let receiver = utils::snippet_opt(cx, receiver_expr.span)?; + let cast_lhs = utils::snippet_opt(cx, cast_lhs_expr.span)?; + Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs)) } enum Method { -- cgit 1.4.1-3-g733a5 From 9a8f206662d63d0218e7f8318c8ddbfccca6bfa8 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:43:40 -0500 Subject: eof newline --- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 08ae92d255e..f8e35f84db1 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -147,4 +147,4 @@ impl fmt::Display for Method { Method::WrappingOffset => write!(f, "wrapping_offset"), } } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From d5534ca9db4f18a707ee7bc3edc1eb70647dca3b Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 07:46:03 -0500 Subject: bring back sugg::range --- clippy_lints/src/utils/sugg.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index a02e0144791..8b1b8a31ac2 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -175,6 +175,16 @@ impl<'a> Sugg<'a> { make_unop("&mut *", self) } + /// Convenience method to create the `..` or `...` + /// suggestion. + #[allow(dead_code)] + pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { + match limit { + ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end), + ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end), + } + } + /// Add parenthesis to any expression that might need them. Suitable to the /// `self` argument of /// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`). -- cgit 1.4.1-3-g733a5 From 6445a5d79d642d38ea2efba3e8c08cf87ba40920 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 08:01:05 -0500 Subject: derive copy/clone --- clippy_lints/src/ptr_offset_with_cast.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index f8e35f84db1..7f34aca27f0 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -126,6 +126,7 @@ fn build_suggestion<'a, 'tcx>( Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs)) } +#[derive(Copy, Clone)] enum Method { Offset, WrappingOffset, -- cgit 1.4.1-3-g733a5 From 53928d53673303a2147eccb34918234886ac0e26 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 08:27:32 -0500 Subject: clippy suggestion --- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 7f34aca27f0..6f589a7d1d7 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -133,7 +133,7 @@ enum Method { } impl Method { - fn suggestion(&self) -> &'static str { + fn suggestion(self) -> &'static str { match *self { Method::Offset => "add", Method::WrappingOffset => "wrapping_add", -- cgit 1.4.1-3-g733a5 From f42442b6e07a8eafc711d708bb70d6065b4f8c5d Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 29 Aug 2018 08:59:38 -0500 Subject: dont deref --- clippy_lints/src/ptr_offset_with_cast.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 6f589a7d1d7..9f475473c61 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -134,7 +134,7 @@ enum Method { impl Method { fn suggestion(self) -> &'static str { - match *self { + match self { Method::Offset => "add", Method::WrappingOffset => "wrapping_add", } @@ -143,7 +143,7 @@ impl Method { impl fmt::Display for Method { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { + match self { Method::Offset => write!(f, "offset"), Method::WrappingOffset => write!(f, "wrapping_offset"), } -- cgit 1.4.1-3-g733a5 From 392235d6e1eec4ab67dd4c14169f134b0ef49118 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 28 Jul 2018 17:34:24 +0200 Subject: Switch to tool_lints --- clippy_lints/src/lib.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7d429ce4923..87a906ad83d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -17,34 +17,34 @@ use rustc; macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, correctness, $description:tt } => { - declare_lint! { pub $name, Deny, $description, report_in_external_macro: true } + declare_lint! { pub $name, Deny, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, complexity, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, perf, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, pedantic, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, restriction, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, cargo, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, nursery, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, internal, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true } + declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } }; { pub $name:tt, internal_warn, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true } + declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } }; } @@ -411,7 +411,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box non_copy_const::NonCopyConst); reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); - reg.register_lint_group("clippy_restriction", vec![ + reg.register_lint_group("clippy::restriction", vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, @@ -434,7 +434,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { write::USE_DEBUG, ]); - reg.register_lint_group("clippy_pedantic", vec![ + reg.register_lint_group("clippy::pedantic", vec![ attrs::INLINE_ALWAYS, copies::MATCH_SAME_ARMS, copy_iterator::COPY_ITERATOR, @@ -472,13 +472,13 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { use_self::USE_SELF, ]); - reg.register_lint_group("clippy_internal", vec![ + reg.register_lint_group("clippy::internal", vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::LINT_WITHOUT_LINT_PASS, utils::internal_lints::DEFAULT_HASH_TYPES, ]); - reg.register_lint_group("clippy", vec![ + reg.register_lint_group("clippy::all", vec![ approx_const::APPROX_CONSTANT, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, @@ -693,7 +693,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); - reg.register_lint_group("clippy_style", vec![ + reg.register_lint_group("clippy::style", vec![ assign_ops::ASSIGN_OP_PATTERN, bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, @@ -777,7 +777,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { write::WRITELN_EMPTY_STRING, ]); - reg.register_lint_group("clippy_complexity", vec![ + reg.register_lint_group("clippy::complexity", vec![ assign_ops::MISREFACTORED_ASSIGN_OP, booleans::NONMINIMAL_BOOL, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, @@ -845,7 +845,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); - reg.register_lint_group("clippy_correctness", vec![ + reg.register_lint_group("clippy::correctness", vec![ approx_const::APPROX_CONSTANT, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, @@ -899,7 +899,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unused_io_amount::UNUSED_IO_AMOUNT, ]); - reg.register_lint_group("clippy_perf", vec![ + reg.register_lint_group("clippy::perf", vec![ bytecount::NAIVE_BYTECOUNT, entry::MAP_ENTRY, escape::BOXED_LOCAL, @@ -917,11 +917,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { vec::USELESS_VEC, ]); - reg.register_lint_group("clippy_cargo", vec![ + reg.register_lint_group("clippy::cargo", vec![ multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, ]); - reg.register_lint_group("clippy_nursery", vec![ + reg.register_lint_group("clippy::nursery", vec![ attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, -- cgit 1.4.1-3-g733a5 From 8c07772dbb817114f338692188dd7733bcd741cb Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sun, 29 Jul 2018 11:04:40 +0200 Subject: Switch to declare_tool_lint macro --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/assign_ops.rs | 2 +- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/default_trait_access.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/double_parens.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/identity_conversion.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- .../src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infallible_destructuring_match.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/invalid_ref.rs | 2 +- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lib.rs | 20 ++++++++++---------- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/literal_representation.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/mem_forget.rs | 2 +- clippy_lints/src/methods.rs | 2 +- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/needless_update.rs | 2 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- clippy_lints/src/overflow_check_conditional.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/precedence.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 2 +- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/temporary_assignment.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 6 +++--- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/write.rs | 2 +- clippy_lints/src/zero_div_zero.rs | 2 +- 117 files changed, 128 insertions(+), 128 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index fe00d325f77..99b9e79463a 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 209963e0688..fa48b2b5506 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Span; /// **What it does:** Checks for plain integer arithmetic. diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 28fd96e3aac..5a27f6a2c36 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -3,7 +3,7 @@ use crate::utils::{higher, sugg}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 66144706816..034c2cc241a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use crate::utils::{ }; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, TyCtxt}; use semver::Version; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 86788fded05..ecac7f8250b 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast::LitKind; use syntax::source_map::Span; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index e5af0789064..97749e6f997 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint; diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index f57a3571b57..752d640fa9e 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,6 +1,6 @@ use matches::matches; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::utils::*; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index eda6a045cba..f867dc56c3c 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::*; use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 5c9b571c78c..ddc017c27df 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use syntax::ast::{Name, UintTy}; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 09fcf47c920..55cc94f399f 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -13,7 +13,7 @@ //! This lint is **warn** by default use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast; diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 1af0741d67f..83dd4c0509e 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,6 +1,6 @@ use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use crate::utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 42788e77d6e..8f1823be15a 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty::Ty; use rustc::hir::*; use std::collections::HashMap; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index ee53fca9f70..6195db7b482 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -2,7 +2,7 @@ use rustc::cfg::CFG; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::ty; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 09c60760076..cb79883372a 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 9df2e257b1e..2a26cca21ac 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::*; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 957ede66698..2db950b3365 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast; use syntax::source_map::{BytePos, Span}; use syntax_pos::Pos; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 70dc532e55b..1f38be4d7b7 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Span; use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index abd5666385d..42d6720d96c 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,6 +1,6 @@ use syntax::ast::*; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for unnecessary double parentheses. /// diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 5aca7d734e2..be804780ff5 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use rustc::hir::*; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 77d3014d9fd..5853983dcf0 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::Spanned; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 1259b49d93a..1c026713a5d 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,7 +1,7 @@ //! lint on if expressions with an else if, but without a final else branch use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::span_lint_and_sugg; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 86f9fbdba9b..195a78a89e5 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,7 +1,7 @@ //! lint when there is an enum with no variants use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 46ef16ddc73..8a2fcbaea46 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::Span; use crate::utils::SpanlessEq; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 2402cfde5b3..3a7f884b784 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -2,7 +2,7 @@ //! don't fit into an `i32` use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::ty; use rustc::ty::subst::Substs; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 90cc1716cc1..042a4765e2b 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::NodeId; use syntax::source_map::Span; use crate::utils::span_lint; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 51277516571..85b133cbd03 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,7 +1,7 @@ //! lint on enum variants that are prefixed or suffixed by the same characters use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, Lint}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index a08d9f39382..de1b5b77e6e 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index e6d70b22fde..5b61a9fd883 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Span; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 3c61509d1f7..282149f81f9 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::hir::intravisit as visit; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt_, Categorization}; use rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index f60785662dd..c4ffc70dbfd 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use rustc::hir::*; use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index f1c31d095e1..72abbddf141 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -2,7 +2,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast; use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index df540cad931..e5809371e83 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,6 +1,6 @@ use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; use std::f32; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index f0cee563a2e..77c6c1a4ad7 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; use crate::utils::opt_def_id; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index f541abee8a7..88eb880311e 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir; use rustc::ty; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index f967b9ce58e..c10d554660a 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use syntax::ast::LitKind; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 2f46891e6a1..8b20aeed108 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast; use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use syntax::ptr::P; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 2f076dc1f6e..c170b0a1e15 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -2,7 +2,7 @@ use matches::matches; use rustc::hir::intravisit; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use rustc::hir::def::Def; use std::collections::HashSet; diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 3fa30dee988..6adf2cd6814 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use syntax::ast::NodeId; use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index b0c290ffc0e..bb3741088cf 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Span; use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; use rustc::ty; diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index f1b8aadef67..253d295567c 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 153bfbb9779..3bfde1fd20d 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -2,7 +2,7 @@ //! on the condition use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::span_help_and_lint; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 01a659473c1..bca4844aae7 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -6,7 +6,7 @@ use crate::utils::higher; use crate::utils::higher::Range; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use syntax::ast::RangeLimits; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index a085f32ed84..208f2ec5379 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -1,7 +1,7 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; /// **What it does:** Checks for matches being used to destructure a single-variant enum diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index d42a2380ec4..bb33c48fc3f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 46dbb5bc39f..4ca812e56bd 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use std::collections::HashMap; use std::default::Default; use syntax_pos::Span; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index b879d734929..4dcc4ed473d 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,7 +1,7 @@ //! checks for `#[inline]` on trait methods without bodies use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use syntax::ast::{Attribute, Name}; use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 086567ac531..b640eff2c5d 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,7 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 58f1575abb6..34a8939e104 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use rustc::hir::*; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 2ea6c0e0447..9fe70882c86 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -2,7 +2,7 @@ use matches::matches; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 3e49f866170..63201bb2e45 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,7 +1,7 @@ //! lint when there is a large size difference between variants on an enum use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use crate::utils::{snippet_opt, span_lint_and_then}; use rustc::ty::layout::LayoutOf; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index e14f3bc24b7..4c9c219828d 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,7 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use std::collections::HashSet; use syntax::ast::{Lit, LitKind, Name}; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 494efc22538..8b4e2b0dec8 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir; use rustc::hir::BindingAnnotation; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 87a906ad83d..32c3dca6357 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -17,34 +17,34 @@ use rustc; macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, correctness, $description:tt } => { - declare_lint! { pub $name, Deny, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Deny, $description, report_in_external_macro: true } }; { pub $name:tt, complexity, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, perf, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } }; { pub $name:tt, pedantic, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, restriction, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, cargo, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, nursery, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, internal, $description:tt } => { - declare_lint! { pub $name, Allow, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { pub $name:tt, internal_warn, $description:tt } => { - declare_lint! { pub $name, Warn, $description, report_in_external_macro: true, clippy } + declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } }; } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7da62b9d458..beec9bac940 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,7 +1,7 @@ use crate::reexport::*; use matches::matches; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::*; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9437b243cbb..dcffba80b3b 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -2,7 +2,7 @@ //! floating-point literal expressions. use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast::*; use syntax_pos; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 988256ab29e..51e6327e728 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -5,7 +5,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::middle::region; // use rustc::middle::region::CodeExtent; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index bd304db2dd5..1a501b39eb5 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use rustc::ty; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 2376b1a2b48..90f149a1c01 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,6 +1,6 @@ use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6dc16e623a4..3ecf5d3b5b8 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use std::cmp::Ordering; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 76df98727f9..8a56dccad2d 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::{Expr, ExprKind}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 3bc1282fa15..4f6cb64dd4f 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,7 +1,7 @@ use matches::matches; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, Lint, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::def::Def; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index b187c28def6..bbbc022f08d 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -2,7 +2,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use std::cmp::Ordering; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 7fab12bd9d9..302af13630b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -3,7 +3,7 @@ use matches::matches; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use syntax::source_map::{ExpnFormat, Span}; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 4edb6a9133a..c00b3d93c47 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use std::collections::HashMap; use std::char; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 339ab757702..f56a8fcd8b5 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -20,7 +20,7 @@ use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use syntax::ast; use syntax::attr; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c0f12bd3f7e..bf88caa6ab9 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -11,7 +11,7 @@ use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast; use syntax::source_map::Span; use crate::utils::span_lint; diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 78458843ffc..a2ed6a1dea1 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,7 +1,7 @@ //! lint on multiple versions of a crate being used use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::span_lint; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 5c8a2648a18..ea3d68dfc83 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use crate::utils::{higher, span_lint}; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 5b562f3dd34..97287aa833f 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use rustc::hir::*; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 8b56526f495..cb400ee4ee3 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 90b38440a83..5b9a479c1fc 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use syntax::ast::LitKind; use syntax::source_map::Spanned; diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index b8ac425fd59..a194cb2c61b 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; use rustc::ty; diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index d5a16f2122f..4905dbc8e6b 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use crate::utils::{in_macro, snippet, span_lint_and_then}; diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index e5f01847ed1..e14cd0fea89 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -28,7 +28,7 @@ //! //! This lint is **warn** by default. use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast; use syntax::source_map::{original_sp, DUMMY_SP}; use std::borrow::Cow; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 06baf895c93..340fa4d0ee0 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -2,7 +2,7 @@ use matches::matches; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::traits; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 90a1ee14a6d..dccb7f2e037 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use rustc::hir::{Expr, ExprKind}; use crate::utils::span_lint; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index bec875d16d6..db61ea375c3 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::utils::{self, paths, span_lint}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 5246e62aecb..8df33b1e99a 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::source_map::{Span, Spanned}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 4dd2ea98399..493e8d0f4ce 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,7 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use syntax::source_map::Span; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index cacb5d6a9ff..09a27330750 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index c2692f88187..deb088d3ea4 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -3,7 +3,7 @@ //! This lint is **deny** by default. use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir::def::Def; use rustc::ty::{self, TypeFlags}; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 14aba635c1a..0b0fe28a90b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,5 +1,5 @@ use rustc::lint::{LintArray, LintPass, EarlyContext, EarlyLintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; use syntax::ast::*; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 52eb86a0bc0..651ed44110f 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index bfb88449fba..b5459059e90 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,6 +1,6 @@ use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::LitKind; use syntax::source_map::{Span, Spanned}; use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index cb230bc9fc5..d33ef5e05d6 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use crate::utils::{span_lint, SpanlessEq}; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index e21c0718612..7a7fa3c456d 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast::LitKind; use syntax::ptr::P; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index fe93a8bbe99..8b2e5f9c356 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use crate::utils::{is_automatically_derived, span_lint}; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 42bbe687832..0978a6b7d94 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Spanned; use crate::utils::{in_macro, snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index cedb6e0b26b..94bbfb0e5b9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use rustc::hir::*; use rustc::hir::QPath; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use syntax::ast::NodeId; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index cb98ecd3dec..3134f14b194 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use rustc::hir::def::Def; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index bef4532bbe5..95fd14162ac 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use syntax::ast::RangeLimits; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 3021ef2dc47..579d2ad1423 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use crate::utils::{span_lint_and_sugg}; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index f5bc03c6d6e..98de8989597 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,6 +1,6 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::utils::{snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 5fe37e16484..6ac40c5a1d2 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,7 +1,7 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 093ad0358bc..aaea8b6dd0e 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir; use rustc::hir::def::Def; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 694433a8b92..ddc0a9719a8 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use syntax::ast; use syntax::source_map::Span; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 41d8b1f7d24..0f09988c250 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use crate::utils::{get_trait_def_id, paths, span_lint}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 4964b7e79ef..d552c01679a 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,6 +1,6 @@ use crate::reexport::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 2b915f46175..b306c18f531 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::source_map::Spanned; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 7e0684e7f16..9f9b279a6c5 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 7fd72cbea32..9ae6ec48383 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,7 +1,7 @@ use matches::matches; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty; use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 56e705ad0a7..cb922302964 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::{Expr, ExprKind}; use crate::utils::is_adjusted; use crate::utils::span_lint; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 9fe22b7dafc..6e82bee277f 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc::hir::*; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8f417861ca9..70a93e7f78a 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -5,7 +5,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::TyKind; use rustc::session::config::Config as SessionConfig; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index a38d232d3e1..81842421fa3 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::ty::layout::LayoutOf; diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 4e5c9a94424..01c4cd83ce0 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; use syntax::source_map::Span; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 753ee40be7f..7ef235e9297 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index e388ca93888..c5507fcaca4 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 1fd143d6d03..71d9520c05b 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use std::collections::HashMap; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 0435db93ee6..a1d24f64300 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index eb2b4e801eb..550f88c895e 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax_pos::symbol::keywords::SelfType; /// **What it does:** Checks for unnecessary repetition of structure name when a diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index f45ec75aedc..fe8123d288d 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -4,7 +4,7 @@ #![allow(print_stdout, use_debug)] use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 73c86d8bf67..12b4f55e432 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -3,7 +3,7 @@ //! checks for attributes use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use rustc::hir::print; use syntax::ast::Attribute; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 39a3d9b3b74..7b2d2f15996 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; @@ -149,13 +149,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate) { for (lint_name, &lint_span) in &self.declared_lints { - // When using the `declare_lint!` macro, the original `lint_span`'s + // When using the `declare_tool_lint!` macro, the original `lint_span`'s // file points to "". // `compiletest-rs` thinks that's an error in a different file and // just ignores it. This causes the test in compile-fail/lint_pass // not able to capture the error. // Therefore, we need to climb the macro expansion tree and find the - // actual span that invoked `declare_lint!`: + // actual span that invoked `declare_tool_lint!`: let lint_span = lint_span .ctxt() .outer() diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 8e49a3d4326..4cbefc29b9c 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::ty::{self, Ty}; use syntax::source_map::Span; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index bc9fa09c932..5d32157238b 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,5 +1,5 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::tokenstream::{ThinTokenStream, TokenStream}; use syntax::parse::{token, parser}; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 77bc4802742..73c9e64d2cb 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,6 +1,6 @@ use crate::consts::{constant_simple, Constant}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use rustc::hir::*; use crate::utils::span_help_and_lint; -- cgit 1.4.1-3-g733a5 From 83baf8f5fe32fab5dc5e0190cf16ca1d281d4fd5 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 28 Jul 2018 17:35:24 +0200 Subject: Adapt documentation to the tool_lints --- CONTRIBUTING.md | 2 +- README.md | 32 ++++++++++++-------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7de4f850c1c..3d1385244a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -170,7 +170,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box else_if_without_else::ElseIfWithoutElse); // ... - reg.register_lint_group("clippy_restriction", vec![ + reg.register_lint_group("clippy::restriction", vec![ // ... else_if_without_else::ELSE_IF_WITHOUT_ELSE, // ... diff --git a/README.md b/README.md index 41eacdba1a4..98f712c28d8 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,14 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -* `clippy` (everything that has no false positives) -* `clippy_pedantic` (everything) -* `clippy_nursery` (new lints that aren't quite ready yet) -* `clippy_style` (code that should be written in a more idiomatic way) -* `clippy_complexity` (code that does something simple but in a complex way) -* `clippy_perf` (code that can be written in a faster way) -* `clippy_cargo` (checks against the cargo manifest) -* **`clippy_correctness`** (code that is just outright wrong or very very useless) +* `clippy::all` (everything that has no false positives) +* `clippy::pedantic` (everything) +* `clippy::nursery` (new lints that aren't quite ready yet) +* `clippy::style` (code that should be written in a more idiomatic way) +* `clippy::complexity` (code that does something simple but in a complex way) +* `clippy::perf` (code that can be written in a faster way) +* `clippy::cargo` (checks against the cargo manifest) +* **`clippy::correctness`** (code that is just outright wrong or very very useless) More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! @@ -106,26 +106,18 @@ define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. You can add options to `allow`/`warn`/`deny`: -* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy)]`) +* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`) -* all lints using both the `clippy` and `clippy_pedantic` lint groups (`#![deny(clippy)]`, - `#![deny(clippy_pedantic)]`). Note that `clippy_pedantic` contains some very aggressive +* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`, + `#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive lints prone to false positives. -* only some lints (`#![deny(single_match, box_vec)]`, etc) +* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc) * `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc Note: `deny` produces errors instead of warnings. -For convenience, `cargo clippy` automatically defines a `cargo-clippy` -feature. This lets you set lint levels and compile with or without Clippy -transparently: - -```rust -#[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] -``` - ## Updating rustc Sometimes, rustc moves forward without Clippy catching up. Therefore updating -- cgit 1.4.1-3-g733a5 From bb49b31254e0bf5ad973a1d0548fc877614b9e30 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 28 Jul 2018 17:35:41 +0200 Subject: Adapt scripts to the tool_lints --- util/dogfood.sh | 2 +- util/update_lints.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/util/dogfood.sh b/util/dogfood.sh index 358fc46c8db..bebe0e82a7f 100755 --- a/util/dogfood.sh +++ b/util/dogfood.sh @@ -1,5 +1,5 @@ #!/bin/sh rm -rf target*/*so -cargo build --lib && cp -R target target_recur && cargo rustc --lib -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy || exit 1 +cargo build --lib && cp -R target target_recur && cargo rustc --lib -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy::pedantic -Dclippy::all || exit 1 rm -rf target_recur diff --git a/util/update_lints.py b/util/update_lints.py index abc8e5dee98..ea7b992abb7 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -218,16 +218,16 @@ def main(print_only=False, check=False): lambda: gen_mods(all_lints), replace_start=False, write_back=not check) - # same for "clippy_*" lint collections + # same for "clippy::*" lint collections changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy::all"', r'\]\);', lambda: gen_group(clippy_lint_list), replace_start=False, write_back=not check) for key, value in clippy_lints.iteritems(): - # same for "clippy_*" lint collections + # same for "clippy::*" lint collections changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy_' + key + r'"', r'\]\);', + 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy::' + key + r'"', r'\]\);', lambda: gen_group(value), replace_start=False, write_back=not check) -- cgit 1.4.1-3-g733a5 From 1b6f6051a8b62f966d28d63fe3c3637a29c410a4 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 28 Jul 2018 17:34:52 +0200 Subject: Adapt ui-tests to the tool_lints --- tests/ui/absurd-extreme-comparisons.rs | 8 ++++---- tests/ui/approx_const.rs | 6 +++--- tests/ui/arithmetic.rs | 6 +++--- tests/ui/assign_ops.rs | 4 +++- tests/ui/assign_ops2.rs | 4 ++-- tests/ui/attrs.rs | 4 ++-- tests/ui/bit_masks.rs | 10 +++++----- tests/ui/blacklisted_name.rs | 6 +++--- tests/ui/block_in_if_condition.rs | 10 +++++----- tests/ui/bool_comparison.rs | 4 ++-- tests/ui/booleans.rs | 14 +++++++------- tests/ui/borrow_box.rs | 6 +++--- tests/ui/box_vec.rs | 8 ++++---- tests/ui/builtin-type-shadow.rs | 4 ++-- tests/ui/bytecount.rs | 4 ++-- tests/ui/cast.rs | 18 +++++++++--------- tests/ui/cast_alignment.rs | 6 ++++-- tests/ui/cast_lossless_float.rs | 8 +++++--- tests/ui/cast_lossless_integer.rs | 8 ++++---- tests/ui/cast_size.rs | 6 ++++-- tests/ui/char_lit_as_u8.rs | 4 ++-- tests/ui/checked_unwrap.rs | 6 ++++-- tests/ui/clone_on_copy_mut.rs | 4 +++- tests/ui/cmp_nan.rs | 6 +++--- tests/ui/cmp_null.rs | 4 ++-- tests/ui/cmp_owned.rs | 6 +++--- tests/ui/collapsible_if.rs | 4 ++-- tests/ui/complex_types.rs | 6 +++--- tests/ui/copies.rs | 14 ++++++++------ tests/ui/copy_iterator.rs | 4 +++- tests/ui/cstring.rs | 4 +++- tests/ui/cyclomatic_complexity.rs | 8 ++++---- tests/ui/cyclomatic_complexity_attr_used.rs | 4 ++-- tests/ui/decimal_literal_representation.rs | 4 ++-- tests/ui/default_trait_access.rs | 4 +++- tests/ui/derive.rs | 4 ++-- tests/ui/diverging_sub_expression.rs | 10 ++++++---- tests/ui/dlist.rs | 6 ++++-- tests/ui/doc.rs | 6 ++++-- tests/ui/double_neg.rs | 4 ++-- tests/ui/double_parens.rs | 4 ++-- tests/ui/drop_forget_copy.rs | 6 +++--- tests/ui/drop_forget_ref.rs | 6 +++--- tests/ui/duplicate_underscore_argument.rs | 4 ++-- tests/ui/duration_subsec.rs | 4 +++- tests/ui/else_if_without_else.rs | 6 ++++-- tests/ui/empty_enum.rs | 4 ++-- tests/ui/empty_line_after_outer_attribute.rs | 4 ++-- tests/ui/entry.rs | 6 +++--- tests/ui/enum_glob_use.rs | 6 +++--- tests/ui/enum_variants.rs | 6 ++++-- tests/ui/enums_clike.rs | 4 +++- tests/ui/eq_op.rs | 10 +++++----- tests/ui/erasing_op.rs | 6 +++--- tests/ui/eta.rs | 6 +++--- tests/ui/eval_order_dependence.rs | 6 +++--- tests/ui/excessive_precision.rs | 6 +++--- tests/ui/explicit_write.rs | 4 +++- tests/ui/fallible_impl_from.rs | 4 +++- tests/ui/filter_methods.rs | 6 +++--- tests/ui/float_cmp.rs | 6 +++--- tests/ui/float_cmp_const.rs | 10 +++++----- tests/ui/for_loop.rs | 24 ++++++++++++------------ tests/ui/format.rs | 6 +++--- tests/ui/formatting.rs | 8 ++++---- tests/ui/functions.rs | 4 ++-- tests/ui/fxhash.rs | 4 +++- tests/ui/identity_conversion.rs | 6 ++++-- tests/ui/identity_op.rs | 6 +++--- tests/ui/if_let_redundant_pattern_matching.rs | 6 +++--- tests/ui/if_not_else.rs | 6 +++--- tests/ui/impl.rs | 4 +++- tests/ui/inconsistent_digit_grouping.rs | 4 ++-- tests/ui/indexing_slicing.rs | 8 +++++--- tests/ui/infallible_destructuring_match.rs | 4 +++- tests/ui/infinite_iter.rs | 10 +++++----- tests/ui/infinite_loop.rs | 6 ++++-- tests/ui/inline_fn_without_body.rs | 6 +++--- tests/ui/int_plus_one.rs | 6 +++--- tests/ui/invalid_upcast_comparisons.rs | 6 +++--- tests/ui/issue_2356.rs | 4 +++- tests/ui/item_after_statement.rs | 4 ++-- tests/ui/large_digit_groups.rs | 4 ++-- tests/ui/large_enum_variant.rs | 4 ++-- tests/ui/len_zero.rs | 6 ++++-- tests/ui/let_if_seq.rs | 6 +++--- tests/ui/let_return.rs | 6 +++--- tests/ui/let_unit.rs | 4 ++-- tests/ui/lifetimes.rs | 6 +++--- tests/ui/literals.rs | 8 +++++--- tests/ui/map_clone.rs | 6 +++--- tests/ui/matches.rs | 8 ++++---- tests/ui/mem_forget.rs | 6 +++--- tests/ui/methods.rs | 14 +++++++------- tests/ui/min_max.rs | 4 ++-- tests/ui/missing-doc.rs | 22 ++++++++++++---------- tests/ui/missing_inline.rs | 6 ++++-- tests/ui/module_inception.rs | 6 +++--- tests/ui/modulo_one.rs | 6 +++--- tests/ui/mut_from_ref.rs | 6 +++--- tests/ui/mut_mut.rs | 6 +++--- tests/ui/mut_reference.rs | 6 +++--- tests/ui/mutex_atomic.rs | 6 +++--- tests/ui/needless_bool.rs | 18 +++++++++--------- tests/ui/needless_borrow.rs | 8 +++++--- tests/ui/needless_borrowed_ref.rs | 4 ++-- tests/ui/needless_continue.rs | 4 ++-- tests/ui/needless_pass_by_value.rs | 6 ++++-- tests/ui/needless_pass_by_value_proc_macro.rs | 4 ++-- tests/ui/needless_return.rs | 4 ++-- tests/ui/needless_update.rs | 6 +++--- tests/ui/neg_cmp_op_on_partial_ord.rs | 4 +++- tests/ui/neg_multiply.rs | 6 +++--- tests/ui/never_loop.rs | 6 +++--- tests/ui/new_without_default.rs | 4 +++- tests/ui/no_effect.rs | 8 +++++--- tests/ui/non_copy_const.rs | 6 ++++-- tests/ui/non_expressive_names.rs | 6 +++--- tests/ui/ok_if_let.rs | 4 ++-- tests/ui/op_ref.rs | 4 ++-- tests/ui/open_options.rs | 4 ++-- tests/ui/option_map_unit_fn.rs | 4 +++- tests/ui/overflow_check_conditional.rs | 6 +++--- tests/ui/panic_unimplemented.rs | 4 ++-- tests/ui/patterns.rs | 4 ++-- tests/ui/precedence.rs | 8 ++++---- tests/ui/print.rs | 6 +++--- tests/ui/print_literal.rs | 4 ++-- tests/ui/print_with_newline.rs | 6 +++--- tests/ui/ptr_arg.rs | 6 ++++-- tests/ui/range.rs | 4 ++-- tests/ui/range_plus_minus_one.rs | 4 +++- tests/ui/redundant_closure_call.rs | 4 ++-- tests/ui/redundant_field_names.rs | 4 +++- tests/ui/reference.rs | 10 +++++----- tests/ui/regex.rs | 4 ++-- tests/ui/replace_consts.rs | 6 ++++-- tests/ui/result_map_unit_fn.rs | 4 +++- tests/ui/serde.rs | 4 ++-- tests/ui/shadow.rs | 6 +++--- tests/ui/short_circuit_statement.rs | 4 ++-- tests/ui/single_char_pattern.rs | 4 +++- tests/ui/single_match.rs | 4 +++- tests/ui/starts_ends_with.rs | 6 ++++-- tests/ui/strings.rs | 12 ++++++------ tests/ui/stutter.rs | 4 ++-- tests/ui/suspicious_arithmetic_impl.rs | 4 ++-- tests/ui/swap.rs | 6 +++--- tests/ui/temporary_assignment.rs | 4 ++-- tests/ui/toplevel_ref_arg.rs | 4 ++-- tests/ui/transmute.rs | 26 +++++++++++++------------- tests/ui/transmute_64bit.rs | 4 +++- tests/ui/trivially_copy_pass_by_ref.rs | 8 +++++--- tests/ui/unicode.rs | 8 ++++---- tests/ui/unit_arg.rs | 6 ++++-- tests/ui/unit_cmp.rs | 6 +++--- tests/ui/unnecessary_clone.rs | 6 ++++-- tests/ui/unnecessary_ref.rs | 4 +++- tests/ui/unneeded_field_pattern.rs | 4 ++-- tests/ui/unreadable_literal.rs | 4 ++-- tests/ui/unsafe_removed_from_name.rs | 4 ++-- tests/ui/unused_io_amount.rs | 4 ++-- tests/ui/unused_labels.rs | 6 +++--- tests/ui/unused_lt.rs | 6 +++--- tests/ui/unwrap_or.rs | 3 ++- tests/ui/use_self.rs | 8 +++++--- tests/ui/used_underscore_binding.rs | 8 ++++---- tests/ui/useless_asref.rs | 8 +++++--- tests/ui/useless_attribute.rs | 4 ++-- tests/ui/vec.rs | 6 +++--- tests/ui/while_loop.rs | 8 ++++---- tests/ui/write_literal.rs | 4 +++- tests/ui/write_with_newline.rs | 6 ++++-- tests/ui/writeln_empty_string.rs | 4 +++- tests/ui/wrong_self_convention.rs | 10 +++++----- tests/ui/zero_div_zero.rs | 4 ++-- 176 files changed, 597 insertions(+), 486 deletions(-) diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index 8c036e6c072..d08c8008ec9 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(absurd_extreme_comparisons)] -#![allow(unused, eq_op, no_effect, unnecessary_operation, needless_pass_by_value)] +#![warn(clippy::absurd_extreme_comparisons)] +#![allow(unused, clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::needless_pass_by_value)] fn main() { const Z: u32 = 0; @@ -27,7 +27,7 @@ fn main() { b >= true; false > b; u > 0; // ok - // this is handled by unit_cmp + // this is handled by clippy::unit_cmp () < {}; } diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index d353d9075d4..46ca2fbfb57 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[warn(approx_constant)] -#[allow(unused, shadow_unrelated, similar_names, unreadable_literal)] +#[warn(clippy::approx_constant)] +#[allow(unused, clippy::shadow_unrelated, clippy::similar_names, clippy::unreadable_literal)] fn main() { let my_e = 2.7182; let almost_e = 2.718; diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 7ed71b59707..e7aa9a18b8a 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(integer_arithmetic, float_arithmetic)] -#![allow(unused, shadow_reuse, shadow_unrelated, no_effect, unnecessary_operation)] +#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] +#![allow(unused, clippy::shadow_reuse, clippy::shadow_unrelated, clippy::no_effect, clippy::unnecessary_operation)] fn main() { let i = 1i32; 1 + i; diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 7332b41fa0b..765dbb67990 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #[allow(dead_code, unused_assignments)] -#[warn(assign_op_pattern)] +#[warn(clippy::assign_op_pattern)] fn main() { let mut a = 5; a = a + 1; diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 2d3adc2a661..c3f5083bb1f 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #[allow(unused_assignments)] -#[warn(misrefactored_assign_op, assign_op_pattern)] +#[warn(clippy::misrefactored_assign_op, clippy::assign_op_pattern)] fn main() { let mut a = 5; a += a + 1; diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index eb27b833ade..b1f0ca640aa 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(inline_always, deprecated_semver)] +#![warn(clippy::inline_always, clippy::deprecated_semver)] #[inline(always)] fn test_attr_lint() { diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index 4843b4eba0d..4111f344b66 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -1,11 +1,11 @@ - +#![feature(tool_lints)] const THREE_BITS : i64 = 7; const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; -#[warn(bad_bit_mask)] -#[allow(ineffective_bit_mask, identity_op, no_effect, unnecessary_operation)] +#[warn(clippy::bad_bit_mask)] +#[allow(clippy::ineffective_bit_mask, clippy::identity_op, clippy::no_effect, clippy::unnecessary_operation)] fn main() { let x = 5; @@ -44,8 +44,8 @@ fn main() { ineffective(); } -#[warn(ineffective_bit_mask)] -#[allow(bad_bit_mask, no_effect, unnecessary_operation)] +#[warn(clippy::ineffective_bit_mask)] +#[allow(clippy::bad_bit_mask, clippy::no_effect, clippy::unnecessary_operation)] fn ineffective() { let x = 5; diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index 7baeb7bb75c..4e2e5388c98 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![allow(dead_code, similar_names, single_match, toplevel_ref_arg, unused_mut, unused_variables)] -#![warn(blacklisted_name)] +#![allow(dead_code, clippy::similar_names, clippy::single_match, clippy::toplevel_ref_arg, unused_mut, unused_variables)] +#![warn(clippy::blacklisted_name)] fn test(foo: ()) {} diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index 9e65a127af2..dd0e5503437 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,10 +1,10 @@ +#![feature(tool_lints)] - -#![warn(block_in_if_condition_expr)] -#![warn(block_in_if_condition_stmt)] -#![allow(unused, let_and_return)] -#![warn(nonminimal_bool)] +#![warn(clippy::block_in_if_condition_expr)] +#![warn(clippy::block_in_if_condition_stmt)] +#![allow(unused, clippy::let_and_return)] +#![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index f05b9894fea..144f9f4c631 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[warn(bool_comparison)] +#[warn(clippy::bool_comparison)] fn main() { let x = true; if x == true { "yes" } else { "no" }; diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index fc16c12af28..eaa686c9a90 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] +#![warn(clippy::nonminimal_bool, clippy::logic_bug)] -#![warn(nonminimal_bool, logic_bug)] - -#[allow(unused, many_single_char_names)] +#[allow(unused, clippy::many_single_char_names)] fn main() { let a: bool = unimplemented!(); let b: bool = unimplemented!(); @@ -23,7 +23,7 @@ fn main() { let _ = !(!a && b); } -#[allow(unused, many_single_char_names)] +#[allow(unused, clippy::many_single_char_names)] fn equality_stuff() { let a: i32 = unimplemented!(); let b: i32 = unimplemented!(); @@ -39,7 +39,7 @@ fn equality_stuff() { let _ = a != b || !(a != b || c == d); } -#[allow(unused, many_single_char_names)] +#[allow(unused, clippy::many_single_char_names)] fn methods_with_negation() { let a: Option = unimplemented!(); let b: Result = unimplemented!(); @@ -59,7 +59,7 @@ fn methods_with_negation() { } // Simplified versions of https://github.com/rust-lang-nursery/rust-clippy/issues/2638 -// nonminimal_bool should only check the built-in Result and Some type, not +// clippy::nonminimal_bool should only check the built-in Result and Some type, not // any other types like the following. enum CustomResultOk { Ok, Err(E) } enum CustomResultErr { Ok, Err(E) } @@ -115,7 +115,7 @@ fn warn_for_built_in_methods_with_negation() { if !res.is_none() { } } -#[allow(neg_cmp_op_on_partial_ord)] +#[allow(clippy::neg_cmp_op_on_partial_ord)] fn dont_warn_for_negated_partial_ord_comparison() { let a: f64 = unimplemented!(); let b: f64 = unimplemented!(); diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index 394b810ed86..216dbebda67 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![deny(borrowed_box)] -#![allow(blacklisted_name)] +#![deny(clippy::borrowed_box)] +#![allow(clippy::blacklisted_name)] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index 75b3b62643e..bc5e8361d8b 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![allow(boxed_local, needless_pass_by_value)] -#![allow(blacklisted_name)] +#![warn(clippy::all)] +#![allow(clippy::boxed_local, clippy::needless_pass_by_value)] +#![allow(clippy::blacklisted_name)] macro_rules! boxit { ($init:expr, $x:ty) => { diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index 4c4f5cbd3fe..56892fc9483 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(builtin_type_shadow)] +#![warn(clippy::builtin_type_shadow)] fn foo(a: u32) -> u32 { 42 diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index fc94667d968..7211284e4a0 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[deny(naive_bytecount)] +#[deny(clippy::naive_bytecount)] fn main() { let x = vec![0_u8; 16]; diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 833e5a55780..0668b16ff32 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,17 +1,17 @@ +#![feature(tool_lints)] - -#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)] -#[allow(no_effect, unnecessary_operation)] +#[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { - // Test cast_precision_loss + // Test clippy::cast_precision_loss 1i32 as f32; 1i64 as f32; 1i64 as f64; 1u32 as f32; 1u64 as f32; 1u64 as f64; - // Test cast_possible_truncation + // Test clippy::cast_possible_truncation 1f32 as i32; 1f32 as u32; 1f64 as f32; @@ -19,17 +19,17 @@ fn main() { 1i32 as u8; 1f64 as isize; 1f64 as usize; - // Test cast_possible_wrap + // Test clippy::cast_possible_wrap 1u8 as i8; 1u16 as i16; 1u32 as i32; 1u64 as i64; 1usize as isize; - // Test cast_lossless with casts from floating-point types + // Test clippy::cast_lossless with casts from floating-point types 1.0f32 as f64; - // Test cast_lossless with an expression wrapped in parens + // Test clippy::cast_lossless with an expression wrapped in parens (1u8 + 1u8) as u16; - // Test cast_sign_loss + // Test clippy::cast_sign_loss 1i32 as u32; 1isize as usize; // Extra checks for *size diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 32e2f93169e..1f7606de649 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -1,11 +1,13 @@ +#![feature(tool_lints)] + //! Test casts for alignment issues #![feature(libc)] extern crate libc; -#[warn(cast_ptr_alignment)] -#[allow(no_effect, unnecessary_operation, cast_lossless)] +#[warn(clippy::cast_ptr_alignment)] +#[allow(clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] fn main() { /* These should be warned against */ diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index 9e61059b630..437c4b67120 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,7 +1,9 @@ -#[warn(cast_lossless)] -#[allow(no_effect, unnecessary_operation)] +#![feature(tool_lints)] + +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { - // Test cast_lossless with casts to floating-point types + // Test clippy::cast_lossless with casts to floating-point types 1i8 as f32; 1i8 as f64; 1u8 as f32; diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 5f89d057c33..e06e653c6f5 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,8 +1,8 @@ - -#[warn(cast_lossless)] -#[allow(no_effect, unnecessary_operation)] +#![feature(tool_lints)] +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { - // Test cast_lossless with casts to integer types + // Test clippy::cast_lossless with casts to integer types 1i8 as i16; 1i8 as i32; 1i8 as i64; diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index d0bef860c70..4c72f57165c 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,5 +1,7 @@ -#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)] -#[allow(no_effect, unnecessary_operation)] +#![feature(tool_lints)] + +#[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { // Casting from *size 1isize as i8; diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index c69181c7649..f9937ede351 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(char_lit_as_u8)] +#![warn(clippy::char_lit_as_u8)] #![allow(unused_variables)] fn main() { let c = 'a' as u8; diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index 2b5118fa814..b3979245d36 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,5 +1,7 @@ -#![deny(panicking_unwrap, unnecessary_unwrap)] -#![allow(if_same_then_else)] +#![feature(tool_lints)] + +#![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +#![allow(clippy::if_same_then_else)] fn main() { let x = Some(()); diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 5b491573c3f..77dffc67670 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + pub fn dec_read_dec(i: &mut i32) -> i32 { *i -= 1; let ret = *i; @@ -5,7 +7,7 @@ pub fn dec_read_dec(i: &mut i32) -> i32 { ret } -#[allow(trivially_copy_pass_by_ref)] +#[allow(clippy::trivially_copy_pass_by_ref)] pub fn minus_1(i: &i32) -> i32 { dec_read_dec(&mut i.clone()) } diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index 71dfdd43da7..fdebb7da18a 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[warn(cmp_nan)] -#[allow(float_cmp, no_effect, unnecessary_operation)] +#[warn(clippy::cmp_nan)] +#[allow(clippy::float_cmp, clippy::no_effect, clippy::unnecessary_operation)] fn main() { let x = 5f32; x == std::f32::NAN; diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 0f463bcfc30..e10b3e104ec 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(cmp_null)] +#![warn(clippy::cmp_null)] #![allow(unused_mut)] use std::ptr; diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 36d3140d246..713975c4404 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[warn(cmp_owned)] -#[allow(unnecessary_operation)] +#[warn(clippy::cmp_owned)] +#[allow(clippy::unnecessary_operation)] fn main() { fn with_to_string(x : &str) { x != "foo".to_string(); diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index de22352e311..d40be631933 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[warn(collapsible_if)] +#[warn(clippy::collapsible_if)] fn main() { let x = "hello"; let y = "world"; diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index 7719a7a8632..a6875793c83 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![allow(unused, needless_pass_by_value)] +#![warn(clippy::all)] +#![allow(unused, clippy::needless_pass_by_value)] #![feature(associated_type_defaults)] type Alias = Vec>>; // no warning here diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 65a565c68ec..064c7fc1c59 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,5 +1,7 @@ -#![allow(blacklisted_name, collapsible_if, cyclomatic_complexity, eq_op, needless_continue, - needless_return, never_loop, no_effect, zero_divided_by_zero)] +#![feature(tool_lints)] + +#![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, + clippy::needless_return, clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero)] fn bar(_: T) {} fn foo() -> bool { unimplemented!() } @@ -14,8 +16,8 @@ pub enum Abc { C, } -#[warn(if_same_then_else)] -#[warn(match_same_arms)] +#[warn(clippy::if_same_then_else)] +#[warn(clippy::match_same_arms)] fn if_same_then_else() -> Result<&'static str, ()> { if true { Foo { bar: 42 }; @@ -340,8 +342,8 @@ fn if_same_then_else() -> Result<&'static str, ()> { } } -#[warn(ifs_same_cond)] -#[allow(if_same_then_else)] // all empty blocks +#[warn(clippy::ifs_same_cond)] +#[allow(clippy::if_same_then_else)] // all empty blocks fn ifs_same_cond() { let a = 0; let b = false; diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index 1b65cc4f8cc..5ccb9910c1e 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -1,4 +1,6 @@ -#![warn(copy_iterator)] +#![feature(tool_lints)] + +#![warn(clippy::copy_iterator)] #[derive(Copy, Clone)] struct Countdown(u8); diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index 8b7b0b66bc6..e68874d5409 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -1,6 +1,8 @@ +#![feature(tool_lints)] + fn main() {} -#[allow(result_unwrap_used)] +#[allow(clippy::result_unwrap_used)] fn temporary_cstring() { use std::ffi::CString; diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 7166ed25948..84e2a1b6583 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(clippy)] -#![warn(cyclomatic_complexity)] +#![allow(clippy::all)] +#![warn(clippy::cyclomatic_complexity)] #![allow(unused)] fn main() { @@ -172,7 +172,7 @@ fn bar() { #[test] #[clippy::cyclomatic_complexity = "0"] -/// Tests are usually complex but simple at the same time. `cyclomatic_complexity` used to give +/// Tests are usually complex but simple at the same time. `clippy::cyclomatic_complexity` used to give /// lots of false-positives in tests. fn dont_warn_on_tests() { match 99 { diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index dbd4e438a12..fd8be25e670 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(cyclomatic_complexity)] +#![warn(clippy::cyclomatic_complexity)] #![warn(unused)] fn main() { diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index 5463b8957f3..472ea618571 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[warn(decimal_literal_representation)] +#[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] fn main() { let good = ( // Hex: diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 675e64246fa..ba8886cd6a4 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,4 +1,6 @@ -#![warn(default_trait_access)] +#![feature(tool_lints)] + +#![warn(clippy::default_trait_access)] use std::default::Default as D2; use std::string; diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index f43b8c382a4..ae54c0290bc 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,9 +1,9 @@ - +#![feature(tool_lints)] #![feature(untagged_unions)] #![allow(dead_code)] -#![warn(expl_impl_clone_on_copy)] +#![warn(clippy::expl_impl_clone_on_copy)] use std::hash::{Hash, Hasher}; diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index b89a2f1bcaf..a8284dca326 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,9 +1,11 @@ +#![feature(tool_lints)] + #![feature(never_type)] -#![warn(diverging_sub_expression)] -#![allow(match_same_arms, logic_bug)] +#![warn(clippy::diverging_sub_expression)] +#![allow(clippy::match_same_arms, clippy::logic_bug)] -#[allow(empty_loop)] +#[allow(clippy::empty_loop)] fn diverge() -> ! { loop {} } struct A; @@ -12,7 +14,7 @@ impl A { fn foo(&self) -> ! { diverge() } } -#[allow(unused_variables, unnecessary_operation, short_circuit_statement)] +#[allow(unused_variables, clippy::unnecessary_operation, clippy::short_circuit_statement)] fn main() { let b = true; b || diverge(); diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 1318ed78717..395ff217497 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -1,9 +1,11 @@ +#![feature(tool_lints)] + #![feature(alloc)] #![feature(associated_type_defaults)] -#![warn(linkedlist)] -#![allow(dead_code, needless_pass_by_value)] +#![warn(clippy::linkedlist)] +#![allow(dead_code, clippy::needless_pass_by_value)] extern crate alloc; use alloc::collections::linked_list::LinkedList; diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 45e25409b12..d48007a9347 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -1,9 +1,11 @@ +#![feature(tool_lints)] + //! This file tests for the DOC_MARKDOWN lint #![allow(dead_code)] -#![warn(doc_markdown)] +#![warn(clippy::doc_markdown)] /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun @@ -50,7 +52,7 @@ fn test_units() { } /// This test has [a link_with_underscores][chunked-example] inside it. See #823. -/// See also [the issue tracker](https://github.com/rust-lang-nursery/rust-clippy/search?q=doc_markdown&type=Issues) +/// See also [the issue tracker](https://github.com/rust-lang-nursery/rust-clippy/search?q=clippy::doc_markdown&type=Issues) /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. /// It can also be [inline_link2]. /// diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index 641e334fd16..0ec13900f99 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[warn(double_neg)] +#[warn(clippy::double_neg)] fn main() { let x = 1; -x; diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index 19d17732867..8d81ee16fe9 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(double_parens)] +#![warn(clippy::double_parens)] #![allow(dead_code)] fn dummy_fn(_: T) {} diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 9fef06b0ede..aa70490f8ab 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(drop_copy, forget_copy)] -#![allow(toplevel_ref_arg, drop_ref, forget_ref, unused_mut)] +#![warn(clippy::drop_copy, clippy::forget_copy)] +#![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)] use std::mem::{drop, forget}; use std::vec::Vec; diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index e8ab6a0d5d1..bb4781db71b 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(drop_ref, forget_ref)] -#![allow(toplevel_ref_arg, similar_names, needless_pass_by_value)] +#![warn(clippy::drop_ref, clippy::forget_ref)] +#![allow(clippy::toplevel_ref_arg, clippy::similar_names, clippy::needless_pass_by_value)] use std::mem::{drop, forget}; diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index df00f56aa62..e54920c1b56 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(duplicate_underscore_argument)] +#![warn(clippy::duplicate_underscore_argument)] #[allow(dead_code, unused)] fn join_the_dark_side(darth: i32, _darth: i32) {} diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 8c75c5f2fcd..d732a0228d5 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,4 +1,6 @@ -#![warn(duration_subsec)] +#![feature(tool_lints)] + +#![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 4f019819eff..3776aecf54f 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -1,5 +1,7 @@ -#![warn(clippy)] -#![warn(else_if_without_else)] +#![feature(tool_lints)] + +#![warn(clippy::all)] +#![warn(clippy::else_if_without_else)] fn bla1() -> bool { unimplemented!() } fn bla2() -> bool { unimplemented!() } diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index c6e6946de86..3398b71eead 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #![allow(dead_code)] -#![warn(empty_enum)] +#![warn(clippy::empty_enum)] enum Empty {} diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 30063dac0a4..c46a0496a73 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,5 +1,5 @@ - -#![warn(empty_line_after_outer_attr)] +#![feature(tool_lints)] +#![warn(clippy::empty_line_after_outer_attr)] // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index ccbc7038f13..955b0a6e917 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] +#![allow(unused, clippy::needless_pass_by_value)] -#![allow(unused, needless_pass_by_value)] - -#![warn(map_entry)] +#![warn(clippy::map_entry)] use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index efb37fbe49d..47082f8f3e6 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy, clippy_pedantic)] -#![allow(unused_imports, dead_code, missing_docs_in_private_items)] +#![warn(clippy::all, clippy::pedantic)] +#![allow(unused_imports, dead_code, clippy::missing_docs_in_private_items)] use std::cmp::Ordering::*; diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 222c76c25b7..4ddb7207a30 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,6 +1,8 @@ +#![feature(tool_lints)] + #![feature(non_ascii_idents)] -#![warn(clippy, pub_enum_variant_names)] +#![warn(clippy::all, clippy::pub_enum_variant_names)] enum FakeCallType { CALL, CREATE @@ -93,7 +95,7 @@ pub enum PubSeall { WithOut, } -#[allow(pub_enum_variant_names)] +#[allow(clippy::pub_enum_variant_names)] mod allowed { pub enum PubAllowed { SomeThis, diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index 618603683e8..8212f12b3db 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -1,7 +1,9 @@ +#![feature(tool_lints)] + // ignore-x86 -#![warn(clippy)] +#![warn(clippy::all)] #![allow(unused)] diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index ef573b2b91a..a88866436dd 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,10 +1,10 @@ +#![feature(tool_lints)] - -#[warn(eq_op)] -#[allow(identity_op, double_parens, many_single_char_names)] -#[allow(no_effect, unused_variables, unnecessary_operation, short_circuit_statement)] -#[warn(nonminimal_bool)] +#[warn(clippy::eq_op)] +#[allow(clippy::identity_op, clippy::double_parens, clippy::many_single_char_names)] +#[allow(clippy::no_effect, unused_variables, clippy::unnecessary_operation, clippy::short_circuit_statement)] +#[warn(clippy::nonminimal_bool)] fn main() { // simple values and comparisons 1 == 1; diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index e5143146f26..02745ac5d91 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[allow(no_effect)] -#[warn(erasing_op)] +#[allow(clippy::no_effect)] +#[warn(clippy::erasing_op)] fn main() { let x: u8 = 0; diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 6e0b6f8cacd..4dd46f20e76 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(unknown_lints, unused, no_effect, redundant_closure_call, many_single_char_names, needless_pass_by_value, option_map_unit_fn, trivially_copy_pass_by_ref)] -#![warn(redundant_closure, needless_borrow)] +#![allow(unknown_lints, unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::redundant_closure, clippy::needless_borrow)] fn main() { let a = Some(1u8).map(|a| foo(a)); diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index e7ccb190d2c..b240dde06f8 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[warn(eval_order_dependence)] -#[allow(unused_assignments, unused_variables, many_single_char_names, no_effect, dead_code, blacklisted_name)] +#[warn(clippy::eval_order_dependence)] +#[allow(unused_assignments, unused_variables, clippy::many_single_char_names, clippy::no_effect, dead_code, clippy::blacklisted_name)] fn main() { let mut x = 0; let a = { x = 1; 1 } + x; diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 88f24d27dbc..b44364d6beb 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,6 +1,6 @@ - -#![warn(excessive_precision)] -#![allow(print_literal)] +#![feature(tool_lints)] +#![warn(clippy::excessive_precision)] +#![allow(clippy::print_literal)] fn main() { // Consts diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 71992123ceb..9d6d13c84c5 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -1,4 +1,6 @@ -#![warn(explicit_write)] +#![feature(tool_lints)] + +#![warn(clippy::explicit_write)] fn stdout() -> String { diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index db118919071..5e33cca59fa 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -1,4 +1,6 @@ -#![deny(fallible_impl_from)] +#![feature(tool_lints)] + +#![deny(clippy::fallible_impl_from)] // docs example struct Foo(i32); diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index 29230c48ea3..d7a50a58838 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(clippy, clippy_pedantic)] -#![allow(missing_docs_in_private_items)] +#![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::missing_docs_in_private_items)] fn main() { let _: Vec<_> = vec![5; 6].into_iter() diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 9dd9ea9b04d..d5b02fb706f 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(float_cmp)] -#![allow(unused, no_effect, unnecessary_operation, cast_lossless)] +#![warn(clippy::float_cmp)] +#![allow(unused, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] use std::ops::Add; diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index adf2ab70368..279400604a2 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] - -#![warn(float_cmp_const)] -#![allow(float_cmp)] -#![allow(unused, no_effect, unnecessary_operation)] +#![warn(clippy::float_cmp_const)] +#![allow(clippy::float_cmp)] +#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] const ONE: f32 = 1.0; const TWO: f32 = 2.0; @@ -36,7 +36,7 @@ fn main() { ONE != ::std::f32::INFINITY; ONE == ::std::f32::NEG_INFINITY; - // no errors, but will warn float_cmp if '#![allow(float_cmp)]' above is removed + // no errors, but will warn clippy::float_cmp if '#![allow(float_cmp)]' above is removed let w = 1.1; v == w; v != w; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index bc0c3172bf0..39eee64883c 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ - +#![feature(tool_lints)] use std::collections::*; @@ -7,7 +7,7 @@ use std::rc::Rc; static STATIC: [usize; 4] = [0, 1, 8, 16]; const CONST: [usize; 4] = [0, 1, 8, 16]; -#[warn(clippy)] +#[warn(clippy::all)] fn for_loop_over_option_and_result() { let option = Some(1); let result = option.ok_or("x not found"); @@ -27,7 +27,7 @@ fn for_loop_over_option_and_result() { println!("{}", x); } - // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call + // make sure LOOP_OVER_NEXT lint takes clippy::precedence when next() is the last call // in the chain for x in v.iter().next() { println!("{}", x); @@ -73,11 +73,11 @@ impl Unrelated { } } -#[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, - explicit_counter_loop, for_kv_map)] -#[warn(unused_collect)] -#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] -#[allow(many_single_char_names, unused_variables)] +#[warn(clippy::needless_range_loop, clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, clippy::reverse_range_loop, + clippy::explicit_counter_loop, clippy::for_kv_map)] +#[warn(clippy::unused_collect)] +#[allow(clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, clippy::cyclomatic_complexity, clippy::similar_names)] +#[allow(clippy::many_single_char_names, unused_variables)] fn main() { const MAX_LEN: usize = 42; @@ -429,7 +429,7 @@ fn main() { } } -#[allow(used_underscore_binding)] +#[allow(clippy::used_underscore_binding)] fn test_for_kv_map() { let m: HashMap = HashMap::new(); @@ -456,7 +456,7 @@ fn partition(v: &mut [T]) -> usize { const LOOP_OFFSET: usize = 5000; -#[warn(needless_range_loop)] +#[warn(clippy::needless_range_loop)] pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { // plain manual memcpy for i in 0..src.len() { @@ -542,14 +542,14 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { } } -#[warn(needless_range_loop)] +#[warn(clippy::needless_range_loop)] pub fn manual_clone(src: &[String], dst: &mut [String]) { for i in 0..src.len() { dst[i] = src[i].clone(); } } -#[warn(needless_range_loop)] +#[warn(clippy::needless_range_loop)] pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { // Same source and destination - don't trigger lint for i in 0..dst.len() { diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 783c6ea095d..8f31d92ac3c 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,6 +1,6 @@ - -#![allow(print_literal)] -#![warn(useless_format)] +#![feature(tool_lints)] +#![allow(clippy::print_literal)] +#![warn(clippy::useless_format)] struct Foo(pub String); diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 20b1c1655a7..74d42f08f5a 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -1,11 +1,11 @@ +#![feature(tool_lints)] - -#![warn(clippy)] +#![warn(clippy::all)] #![allow(unused_variables)] #![allow(unused_assignments)] -#![allow(if_same_then_else)] -#![allow(deref_addrof)] +#![allow(clippy::if_same_then_else)] +#![allow(clippy::deref_addrof)] fn foo() -> bool { true } diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 5688c471d86..ab5ce5b06d8 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy)] +#![warn(clippy::all)] #![allow(dead_code)] #![allow(unused_unsafe)] diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs index c6ed9436a51..1376b9442b6 100644 --- a/tests/ui/fxhash.rs +++ b/tests/ui/fxhash.rs @@ -1,4 +1,6 @@ -#![warn(default_hash_types)] +#![feature(tool_lints)] + +#![warn(clippy::default_hash_types)] #![feature(rustc_private)] extern crate rustc_data_structures; diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 8f5bd12bc9f..b9ad8d06ad5 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -1,4 +1,6 @@ -#![deny(identity_conversion)] +#![feature(tool_lints)] + +#![deny(clippy::identity_conversion)] fn test_generic(val: T) -> T { let _ = T::from(val); @@ -28,7 +30,7 @@ fn main() { let _: String = "foo".into(); let _: String = From::from("foo"); let _ = String::from("foo"); - #[allow(identity_conversion)] + #[allow(clippy::identity_conversion)] { let _: String = "foo".into(); let _ = String::from("foo"); diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 1ed9f974d43..ae8c66faa41 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -1,12 +1,12 @@ - +#![feature(tool_lints)] const ONE : i64 = 1; const NEG_ONE : i64 = -1; const ZERO : i64 = 0; -#[allow(eq_op, no_effect, unnecessary_operation, double_parens)] -#[warn(identity_op)] +#[allow(clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::double_parens)] +#[warn(clippy::identity_op)] fn main() { let x = 0; diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs index 0963caa62e2..90265853f00 100644 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ b/tests/ui/if_let_redundant_pattern_matching.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![warn(if_let_redundant_pattern_matching)] +#![warn(clippy::all)] +#![warn(clippy::if_let_redundant_pattern_matching)] fn main() { diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index 9436af70cb8..bb16e16700b 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![warn(if_not_else)] +#![warn(clippy::all)] +#![warn(clippy::if_not_else)] fn bla() -> bool { unimplemented!() } diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 9e10dbade4e..7da0e04e59e 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![allow(dead_code)] -#![warn(multiple_inherent_impl)] +#![warn(clippy::multiple_inherent_impl)] struct MyStruct; diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index ed6dc06edb1..056d8761109 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#[warn(inconsistent_digit_grouping)] +#[warn(clippy::inconsistent_digit_grouping)] #[allow(unused_variables)] fn main() { let good = (123, 1_234, 1_2345_6789, 123_f32, 1_234.12_f32, 1_234.123_4_f32, 1.123_456_7_f32); diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index e39dc92367c..b9f1c4a4a5d 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -1,7 +1,9 @@ +#![feature(tool_lints)] + #![feature(plugin)] -#![warn(indexing_slicing)] -#![warn(out_of_bounds_indexing)] -#![allow(no_effect, unnecessary_operation)] +#![warn(clippy::indexing_slicing)] +#![warn(clippy::out_of_bounds_indexing)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { let x = [1, 2, 3, 4]; diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 6f3d7a3ff2b..b3e2835d72f 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![feature(exhaustive_patterns, never_type)] -#![allow(let_and_return)] +#![allow(clippy::let_and_return)] enum SingleVariantEnum { Variant(i32), diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index a7841416671..44fa934aa26 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,11 +1,11 @@ - +#![feature(tool_lints)] use std::iter::repeat; -#[allow(trivially_copy_pass_by_ref)] +#[allow(clippy::trivially_copy_pass_by_ref)] fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } -#[allow(maybe_infinite_iter)] -#[deny(infinite_iter)] +#[allow(clippy::maybe_infinite_iter)] +#[deny(clippy::infinite_iter)] fn infinite_iters() { repeat(0_u8).collect::>(); // infinite iter (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter @@ -19,7 +19,7 @@ fn infinite_iters() { (0..).next(); // iterator is not exhausted } -#[deny(maybe_infinite_iter)] +#[deny(clippy::maybe_infinite_iter)] fn potential_infinite_iters() { (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 9e801911602..9449a295e3a 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,4 +1,6 @@ -#![allow(trivially_copy_pass_by_ref)] +#![feature(tool_lints)] + +#![allow(clippy::trivially_copy_pass_by_ref)] fn fn_val(i: i32) -> i32 { unimplemented!() } @@ -7,7 +9,7 @@ fn fn_mutref(i: &mut i32) { unimplemented!() } fn fooi() -> i32 { unimplemented!() } fn foob() -> bool { unimplemented!() } -#[allow(many_single_char_names)] +#[allow(clippy::many_single_char_names)] fn immutable_condition() { // Should warn when all vars mentioned are immutable let y = 0; diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 76e50e56780..830da6d1124 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(inline_fn_without_body)] -#![allow(inline_always)] +#![warn(clippy::inline_fn_without_body)] +#![allow(clippy::inline_always)] trait Foo { #[inline] diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index a9e059f4a3e..1eb0e49290f 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[allow(no_effect, unnecessary_operation)] -#[warn(int_plus_one)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#[warn(clippy::int_plus_one)] fn main() { let x = 1i32; let y = 0i32; diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 5bf0bfdcb98..0a700518f8f 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(invalid_upcast_comparisons)] -#![allow(unused, eq_op, no_effect, unnecessary_operation, cast_lossless)] +#![warn(clippy::invalid_upcast_comparisons)] +#![allow(unused, clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] fn mk_value() -> T { unimplemented!() } diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index d4cefb0f1e3..398e0d1d1f0 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -1,4 +1,6 @@ -#![deny(while_let_on_iterator)] +#![feature(tool_lints)] + +#![deny(clippy::while_let_on_iterator)] use std::iter::Iterator; diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index 710a1adca56..9626a59ed02 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(items_after_statements)] +#![warn(clippy::items_after_statements)] fn ok() { fn foo() { println!("foo"); } diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 5d0fb11dbea..af569ea7566 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#[warn(large_digit_groups)] +#[warn(clippy::large_digit_groups)] #[allow(unused_variables)] fn main() { let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index aaf3e2924b3..cd1772ad1d1 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,9 +1,9 @@ - +#![feature(tool_lints)] #![allow(dead_code)] #![allow(unused_variables)] -#![warn(large_enum_variant)] +#![warn(clippy::large_enum_variant)] enum LargeEnum { A(i32), diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 2e71c2761fa..b188db5186e 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,4 +1,6 @@ -#![warn(len_without_is_empty, len_zero)] +#![feature(tool_lints)] + +#![warn(clippy::len_without_is_empty, clippy::len_zero)] #![allow(dead_code, unused)] pub struct PubOne; @@ -19,7 +21,7 @@ impl PubOne { // Identical to PubOne, but with an allow attribute on the impl complaining len pub struct PubAllowed; -#[allow(len_without_is_empty)] +#[allow(clippy::len_without_is_empty)] impl PubAllowed { pub fn len(self: &Self) -> isize { 1 diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 564a67d2c8e..102b72f3e25 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![allow(unused_variables, unused_assignments, similar_names, blacklisted_name)] -#![warn(useless_let_if_seq)] +#![allow(unused_variables, unused_assignments, clippy::similar_names, clippy::blacklisted_name)] +#![warn(clippy::useless_let_if_seq)] fn f() -> bool { true } fn g(x: i32) -> i32 { x + 1 } diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index 1083603b2d6..9b584d6e293 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #![allow(unused)] -#![warn(let_and_return)] +#![warn(clippy::let_and_return)] fn test() -> i32 { let _y = 0; // no warning @@ -37,7 +37,7 @@ fn test_nowarn_3() -> (i32, i32) { } fn test_nowarn_4() -> i32 { - // this should technically warn, but not b/c of let_and_return, but b/c of useless type + // this should technically warn, but not b/c of clippy::let_and_return, but b/c of useless type let x: i32 = 5; x } diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 032dc85f2cd..187ff9d1358 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(let_unit_value)] +#![warn(clippy::let_unit_value)] #![allow(unused_variables)] macro_rules! let_and_return { diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 0322d42e81f..aa5640f4e22 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(needless_lifetimes, extra_unused_lifetimes)] -#![allow(dead_code, needless_pass_by_value, trivially_copy_pass_by_ref)] +#![warn(clippy::needless_lifetimes, clippy::extra_unused_lifetimes)] +#![allow(dead_code, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 581fbbb70c9..d45da257ad4 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -1,6 +1,8 @@ -#![warn(mixed_case_hex_literals)] -#![warn(unseparated_literal_suffix)] -#![warn(zero_prefixed_literal)] +#![feature(tool_lints)] + +#![warn(clippy::mixed_case_hex_literals)] +#![warn(clippy::unseparated_literal_suffix)] +#![warn(clippy::zero_prefixed_literal)] #![allow(dead_code)] fn main() { diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index f11d21d2dfa..90c95be2c1c 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] +#![warn(clippy::map_clone)] -#![warn(map_clone)] - -#![allow(clone_on_copy, unused)] +#![allow(clippy::clone_on_copy, unused)] use std::ops::Deref; diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index e339aeb9c6a..92befb25a7e 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,10 +1,10 @@ - +#![feature(tool_lints)] #![feature(exclusive_range_pattern)] -#![warn(clippy)] -#![allow(unused, if_let_redundant_pattern_matching)] -#![warn(single_match_else, match_same_arms)] +#![warn(clippy::all)] +#![allow(unused, clippy::if_let_redundant_pattern_matching)] +#![warn(clippy::single_match_else, clippy::match_same_arms)] enum ExprNode { ExprAddrOf, diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 991a402e207..96d333a7170 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -1,4 +1,4 @@ - +#![feature(tool_lints)] @@ -8,8 +8,8 @@ use std::rc::Rc; use std::mem::forget as forgetSomething; use std::mem as memstuff; -#[warn(mem_forget)] -#[allow(forget_copy)] +#[warn(clippy::mem_forget)] +#[allow(clippy::forget_copy)] fn main() { let five: i32 = 5; forgetSomething(five); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 220b08caaf7..37f4cb2f71e 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,10 +1,10 @@ - +#![feature(tool_lints)] #![feature(const_fn)] -#![warn(clippy, clippy_pedantic, option_unwrap_used)] -#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, - new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value, - default_trait_access, use_self)] +#![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] +#![allow(clippy::blacklisted_name, unused, clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, + clippy::new_without_default_derive, clippy::missing_docs_in_private_items, clippy::needless_pass_by_value, + clippy::default_trait_access, clippy::use_self)] use std::collections::BTreeMap; use std::collections::HashMap; @@ -42,7 +42,7 @@ struct Lt<'a> { impl<'a> Lt<'a> { // The lifetime is different, but that’s irrelevant, see #734 - #[allow(needless_lifetimes)] + #[allow(clippy::needless_lifetimes)] pub fn new<'b>(s: &'b str) -> Lt<'b> { unimplemented!() } } @@ -438,7 +438,7 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -#[allow(similar_names)] +#[allow(clippy::similar_names)] fn main() { let opt = Some(0); let _ = opt.unwrap(); diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 9b29f73b2ac..9866933f9fe 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy)] +#![warn(clippy::all)] use std::cmp::{min, max}; use std::cmp::min as my_min; diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index cbd6439d47e..6968adb312b 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + /* This file incorporates work covered by the following copyright and * permission notice: * Copyright 2013 The Rust Project Developers. See the COPYRIGHT @@ -13,7 +15,7 @@ -#![warn(missing_docs_in_private_items)] +#![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. @@ -36,7 +38,7 @@ pub struct PubFoo { b: isize, } -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] pub struct PubFoo2 { pub a: isize, pub c: isize, @@ -49,7 +51,7 @@ pub mod pub_module_no_dox {} pub fn foo() {} pub fn foo2() {} fn foo3() {} -#[allow(missing_docs_in_private_items)] pub fn foo4() {} +#[allow(clippy::missing_docs_in_private_items)] pub fn foo4() {} /// dox pub trait A { @@ -59,7 +61,7 @@ pub trait A { fn foo_with_impl(&self) {} } -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] trait B { fn foo(&self); fn foo_with_impl(&self) {} @@ -70,7 +72,7 @@ pub trait C { fn foo_with_impl(&self) {} } -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] pub trait D { fn dummy(&self) { } } @@ -98,10 +100,10 @@ impl PubFoo { /// dox pub fn foo1() {} fn foo2() {} - #[allow(missing_docs_in_private_items)] pub fn foo3() {} + #[allow(clippy::missing_docs_in_private_items)] pub fn foo3() {} } -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] trait F { fn a(); fn b(&self); @@ -146,7 +148,7 @@ pub enum PubBaz2 { }, } -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] pub enum PubBaz3 { PubBaz3A { b: isize @@ -160,7 +162,7 @@ pub fn baz() {} const FOO: u32 = 0; /// dox pub const FOO1: u32 = 0; -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] pub const FOO2: u32 = 0; #[doc(hidden)] pub const FOO3: u32 = 0; @@ -170,7 +172,7 @@ pub const FOO4: u32 = 0; static BAR: u32 = 0; /// dox pub static BAR1: u32 = 0; -#[allow(missing_docs_in_private_items)] +#[allow(clippy::missing_docs_in_private_items)] pub static BAR2: u32 = 0; #[doc(hidden)] pub static BAR3: u32 = 0; diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 38f59033071..7fbb01c6d2b 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + /* This file incorporates work covered by the following copyright and * permission notice: * Copyright 2013 The Rust Project Developers. See the COPYRIGHT @@ -10,7 +12,7 @@ * option. This file may not be copied, modified, or distributed * except according to those terms. */ -#![warn(missing_inline_in_public_items)] +#![warn(clippy::missing_inline_in_public_items)] #![crate_type = "dylib"] // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. @@ -32,7 +34,7 @@ pub fn pub_foo() {} // missing #[inline] #[inline] pub fn pub_foo_inline() {} // ok #[inline(always)] pub fn pub_foo_inline_always() {} // ok -#[allow(missing_inline_in_public_items)] +#[allow(clippy::missing_inline_in_public_items)] pub fn pub_foo_no_inline() {} trait Bar { diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index 77bd446c569..b6917020ea2 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(module_inception)] +#![warn(clippy::module_inception)] mod foo { mod bar { @@ -16,7 +16,7 @@ mod foo { // No warning. See . mod bar { - #[allow(module_inception)] + #[allow(clippy::module_inception)] mod bar { } } diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index 847ea1d9ab6..7dcec04baf9 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(modulo_one)] -#![allow(no_effect, unnecessary_operation)] +#![warn(clippy::modulo_one)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { 10 % 1; diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 3fc464083c4..b75fa92f098 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(unused, trivially_copy_pass_by_ref)] -#![warn(mut_from_ref)] +#![allow(unused, clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::mut_from_ref)] struct Foo; diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 658ae18466f..4656d27648f 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![allow(unused, no_effect, unnecessary_operation)] -#![warn(mut_mut)] +#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] +#![warn(clippy::mut_mut)] diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index 34185f6a9c2..38b0e25e07c 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(unused_variables, trivially_copy_pass_by_ref)] +#![allow(unused_variables, clippy::trivially_copy_pass_by_ref)] fn takes_an_immutable_reference(a: &i32) {} fn takes_a_mutable_reference(a: &mut i32) {} @@ -16,7 +16,7 @@ impl MyStruct { } } -#[warn(unnecessary_mut_passed)] +#[warn(clippy::unnecessary_mut_passed)] fn main() { // Functions takes_an_immutable_reference(&mut 42); diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index 96502738456..3eefbb97ab8 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![warn(mutex_integer)] +#![warn(clippy::all)] +#![warn(clippy::mutex_integer)] fn main() { use std::sync::Mutex; diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 1213539c827..4e6f65ed0dd 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] +#![warn(clippy::needless_bool)] -#![warn(needless_bool)] - -#[allow(if_same_then_else)] +#[allow(clippy::if_same_then_else)] fn main() { let x = true; let y = false; @@ -20,32 +20,32 @@ fn main() { bool_ret6(x, x); } -#[allow(if_same_then_else, needless_return)] +#[allow(clippy::if_same_then_else, clippy::needless_return)] fn bool_ret(x: bool) -> bool { if x { return true } else { return true }; } -#[allow(if_same_then_else, needless_return)] +#[allow(clippy::if_same_then_else, clippy::needless_return)] fn bool_ret2(x: bool) -> bool { if x { return false } else { return false }; } -#[allow(needless_return)] +#[allow(clippy::needless_return)] fn bool_ret3(x: bool) -> bool { if x { return true } else { return false }; } -#[allow(needless_return)] +#[allow(clippy::needless_return)] fn bool_ret5(x: bool, y: bool) -> bool { if x && y { return true } else { return false }; } -#[allow(needless_return)] +#[allow(clippy::needless_return)] fn bool_ret4(x: bool) -> bool { if x { return false } else { return true }; } -#[allow(needless_return)] +#[allow(clippy::needless_return)] fn bool_ret6(x: bool, y: bool) -> bool { if x && y { return false } else { return true }; } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index b086f0214a9..61384c43fa9 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,11 +1,13 @@ +#![feature(tool_lints)] + use std::borrow::Cow; -#[allow(trivially_copy_pass_by_ref)] +#[allow(clippy::trivially_copy_pass_by_ref)] fn x(y: &i32) -> i32 { *y } -#[warn(clippy, needless_borrow)] +#[warn(clippy::all, clippy::needless_borrow)] #[allow(unused_variables)] fn main() { let a = 5; @@ -42,7 +44,7 @@ trait Trait {} impl<'a> Trait for &'a str {} fn h(_: &Trait) {} -#[warn(needless_borrow)] +#[warn(clippy::needless_borrow)] #[allow(dead_code)] fn issue_1432() { let mut v = Vec::::new(); diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 75ffa211180..000ecd32da4 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#[warn(needless_borrowed_reference)] +#[warn(clippy::needless_borrowed_reference)] #[allow(unused_variables)] fn main() { let mut v = Vec::::new(); diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 3574b0fb3fd..4fe523e48de 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -1,4 +1,4 @@ - +#![feature(tool_lints)] macro_rules! zero { @@ -9,7 +9,7 @@ macro_rules! nonzero { ($x:expr) => (!zero!($x)); } -#[warn(needless_continue)] +#[warn(clippy::needless_continue)] fn main() { let mut i = 1; while i < 10 { diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 322df0b8798..783386fab01 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -1,5 +1,7 @@ -#![warn(needless_pass_by_value)] -#![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names, option_option)] +#![feature(tool_lints)] + +#![warn(clippy::needless_pass_by_value)] +#![allow(dead_code, clippy::single_match, clippy::if_let_redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)] use std::borrow::Borrow; use std::convert::AsRef; diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 652e11fee9d..6b1305fa2d8 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,7 +1,7 @@ - +#![feature(tool_lints)] #![crate_type = "proc-macro"] -#![warn(needless_pass_by_value)] +#![warn(clippy::needless_pass_by_value)] extern crate proc_macro; diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 4739ded7b7e..a834563eca3 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(needless_return)] +#![warn(clippy::needless_return)] fn test_end_of_fn() -> bool { if true { diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 35d5730dda1..675c60e2477 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(needless_update)] -#![allow(no_effect)] +#![warn(clippy::needless_update)] +#![allow(clippy::no_effect)] struct S { pub a: i32, diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index e739908bc28..3a472bf6995 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -1,10 +1,12 @@ +#![feature(tool_lints)] + //! This test case utilizes `f64` an easy example for `PartialOrd` only types //! but the lint itself actually validates any expression where the left //! operand implements `PartialOrd` but not `Ord`. use std::cmp::Ordering; -#[warn(neg_cmp_op_on_partial_ord)] +#[warn(clippy::neg_cmp_op_on_partial_ord)] fn main() { let a_value = 1.0; diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 367d2d5edfb..b1a1879a3fc 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(neg_multiply)] -#![allow(no_effect, unnecessary_operation)] +#![warn(clippy::neg_multiply)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] use std::ops::Mul; diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 20500126662..bb6d76b06cd 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,10 +1,10 @@ +#![feature(tool_lints)] - -#![allow(single_match, unused_assignments, unused_variables, while_immutable_condition)] +#![allow(clippy::single_match, unused_assignments, unused_variables, clippy::while_immutable_condition)] fn test1() { let mut x = 0; - loop { // never_loop + loop { // clippy::never_loop x += 1; if x == 1 { return diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index c06c9f9e962..bf63e9336e5 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,8 +1,10 @@ +#![feature(tool_lints)] + #![feature(const_fn)] #![allow(dead_code)] -#![warn(new_without_default, new_without_default_derive)] +#![warn(clippy::new_without_default, clippy::new_without_default_derive)] pub struct Foo; diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 54028cd8b2b..2913ecdbf59 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,11 +1,13 @@ +#![feature(tool_lints)] + #![feature(box_syntax)] -#![warn(no_effect, unnecessary_operation)] +#![warn(clippy::no_effect, clippy::unnecessary_operation)] #![allow(dead_code)] #![allow(path_statements)] -#![allow(deref_addrof)] -#![allow(redundant_field_names)] +#![allow(clippy::deref_addrof)] +#![allow(clippy::redundant_field_names)] #![feature(untagged_unions)] struct Unit; diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index d7391577d23..4e086333b0c 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![feature(const_string_new, const_vec_new)] -#![allow(ref_in_deref, dead_code)] +#![allow(clippy::ref_in_deref, dead_code)] use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; use std::cell::Cell; @@ -30,7 +32,7 @@ const NO_ANN: &Display = &70; static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING); //^ there should be no lints on this line -#[allow(declare_interior_mutable_const)] +#[allow(clippy::declare_interior_mutable_const)] const ONCE_INIT: Once = Once::new(); trait Trait: Copy { diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 7149bf8f3e7..7b5db015d77 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy,similar_names)] -#![allow(unused, println_empty_string)] +#![warn(clippy::all,clippy::similar_names)] +#![allow(unused, clippy::println_empty_string)] struct Foo { diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index fdc01bcc7bc..46d85bb9cd0 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(if_let_some_result)] +#![warn(clippy::if_let_some_result)] fn str_to_int(x: &str) -> i32 { if let Some(y) = x.parse().ok() { diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index 9eb697571b6..a85a2c8bb51 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(unused_variables, blacklisted_name)] +#![allow(unused_variables, clippy::blacklisted_name)] use std::collections::HashSet; diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 514808d41f1..38b3dd7e49d 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,9 +1,9 @@ - +#![feature(tool_lints)] use std::fs::OpenOptions; #[allow(unused_must_use)] -#[warn(nonsensical_open_options)] +#[warn(clippy::nonsensical_open_options)] fn main() { OpenOptions::new().read(true).truncate(true).open("foo.txt"); OpenOptions::new().append(true).truncate(true).open("foo.txt"); diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index 06531e29032..e86cc99c522 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -1,4 +1,6 @@ -#![warn(option_map_unit_fn)] +#![feature(tool_lints)] + +#![warn(clippy::option_map_unit_fn)] #![allow(unused)] fn do_nothing(_: T) {} diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index 889c339c8fd..5c3cc5b08a9 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![allow(many_single_char_names)] -#![warn(overflow_check_conditional)] +#![allow(clippy::many_single_char_names)] +#![warn(clippy::overflow_check_conditional)] fn main() { let a: u32 = 1; diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 33050633f7f..693dc921be3 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(panic_params, unimplemented)] +#![warn(clippy::panic_params, clippy::unimplemented)] fn missing() { if true { diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 65e319e2f88..70f86afbacb 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,7 +1,7 @@ - +#![feature(tool_lints)] #![allow(unused)] -#![warn(clippy)] +#![warn(clippy::all)] fn main() { let v = Some(true); diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index aacd90cdf92..95476dd4f51 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] - -#[warn(precedence)] -#[allow(identity_op)] -#[allow(eq_op)] +#[warn(clippy::precedence)] +#[allow(clippy::identity_op)] +#[allow(clippy::eq_op)] macro_rules! trip { ($a:expr) => { diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 8719a691d43..cee3e700036 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(print_literal, write_literal)] -#![warn(print_stdout, use_debug)] +#![allow(clippy::print_literal, clippy::write_literal)] +#![warn(clippy::print_stdout, clippy::use_debug)] use std::fmt::{Debug, Display, Formatter, Result}; diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 620349bab33..46b91d40f8c 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(print_literal)] +#![warn(clippy::print_literal)] fn main() { // these should be fine diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 906fa987d17..5efee5abfc8 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(print_literal)] -#![warn(print_with_newline)] +#![allow(clippy::print_literal)] +#![warn(clippy::print_with_newline)] fn main() { print!("Hello\n"); diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index ce572be7ad8..e76221355ae 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,5 +1,7 @@ -#![allow(unused, many_single_char_names)] -#![warn(ptr_arg)] +#![feature(tool_lints)] + +#![allow(unused, clippy::many_single_char_names)] +#![warn(clippy::ptr_arg)] use std::borrow::Cow; diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 7291fd5d5d3..df3ce12689b 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,11 +1,11 @@ - +#![feature(tool_lints)] struct NotARange; impl NotARange { fn step_by(&self, _: u32) {} } -#[warn(iterator_step_by_zero, range_zip_with_len)] +#[warn(clippy::iterator_step_by_zero, clippy::range_zip_with_len)] fn main() { let _ = (0..1).step_by(0); // No warning for non-zero step diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 31574a4aeed..12a1312de36 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,8 +1,10 @@ +#![feature(tool_lints)] + fn f() -> usize { 42 } -#[warn(range_plus_one)] +#[warn(clippy::range_plus_one)] fn main() { for _ in 0..2 { } for _ in 0..=2 { } diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index ab3897bc315..b09ed9a3574 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(redundant_closure_call)] +#![warn(clippy::redundant_closure_call)] fn main() { let a = (|| 42)(); diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index dc8548754d2..b379aa661cb 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,4 +1,6 @@ -#![warn(redundant_field_names)] +#![feature(tool_lints)] + +#![warn(clippy::redundant_field_names)] #![allow(unused_variables)] #![feature(inclusive_range, inclusive_range_fields, inclusive_range_methods)] diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index 0bd000082e8..97a0030a99a 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -1,4 +1,4 @@ - +#![feature(tool_lints)] fn get_number() -> usize { @@ -9,9 +9,9 @@ fn get_reference(n : &usize) -> &usize { n } -#[allow(many_single_char_names, double_parens)] +#[allow(clippy::many_single_char_names, clippy::double_parens)] #[allow(unused_variables)] -#[warn(deref_addrof)] +#[warn(clippy::deref_addrof)] fn main() { let a = 10; let aref = &a; @@ -38,7 +38,7 @@ fn main() { let b = **&aref; //This produces a suggestion of 'let b = *&a;' which - //will trigger the 'deref_addrof' lint again + //will trigger the 'clippy::deref_addrof' lint again let b = **&&a; { @@ -48,7 +48,7 @@ fn main() { { //This produces a suggestion of 'let y = *&mut x' which - //will trigger the 'deref_addrof' lint again + //will trigger the 'clippy::deref_addrof' lint again let mut x = 10; let y = **&mut &mut x; } diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index b80aaa2df32..e3837e104f4 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #![allow(unused)] -#![warn(invalid_regex, trivial_regex, regex_macro)] +#![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_macro)] extern crate regex; diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 71d4ea98e07..8420b368d3d 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,6 +1,8 @@ +#![feature(tool_lints)] + #![feature(integer_atomics)] -#![allow(blacklisted_name)] -#![deny(replace_consts)] +#![allow(clippy::blacklisted_name)] +#![deny(clippy::replace_consts)] use std::sync::atomic::*; use std::sync::{ONCE_INIT, Once}; diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index dd163439d78..8cac6a9c827 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![feature(never_type)] -#![warn(result_map_unit_fn)] +#![warn(clippy::result_map_unit_fn)] #![allow(unused)] fn do_nothing(_: T) {} diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index 792ebc9b0ea..65c2c344da7 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(serde_api_misuse)] +#![warn(clippy::serde_api_misuse)] #![allow(dead_code)] extern crate serde; diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 79c1030d48b..c73acf5c5dd 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(clippy, clippy_pedantic, shadow_same, shadow_reuse, shadow_unrelated)] -#![allow(unused_parens, unused_variables, missing_docs_in_private_items)] +#![warn(clippy::all, clippy::pedantic, clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] +#![allow(unused_parens, unused_variables, clippy::missing_docs_in_private_items)] fn id(x: T) -> T { x } diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index 0f5773623be..e9cb8e4ad8c 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(short_circuit_statement)] +#![warn(clippy::short_circuit_statement)] fn main() { f() && g(); diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 577a0e27090..147f974b999 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + use std::collections::HashSet; fn main() { @@ -9,7 +11,7 @@ fn main() { let y = "x"; x.split(y); // Not yet testing for multi-byte characters - // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_clippy::single_char_pattern` // should have done this but produced an ICE // // We may not want to suggest changing these anyway diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index b064eed5711..c0c82adafb5 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,4 +1,6 @@ -#![warn(single_match)] +#![feature(tool_lints)] + +#![warn(clippy::single_match)] fn dummy() { } diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index d47c8a5b076..adea56cf9a2 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,8 +1,10 @@ +#![feature(tool_lints)] + #![allow(dead_code)] fn main() {} -#[allow(unnecessary_operation)] +#[allow(clippy::unnecessary_operation)] fn starts_with() { "".chars().next() == Some(' '); Some(' ') != "".chars().next(); @@ -30,7 +32,7 @@ fn chars_cmp_with_unwrap() { } } -#[allow(unnecessary_operation)] +#[allow(clippy::unnecessary_operation)] fn ends_with() { "".chars().last() == Some(' '); Some(' ') != "".chars().last(); diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 66d24a3c070..86819e3fd5c 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#[warn(string_add)] -#[allow(string_add_assign)] +#[warn(clippy::string_add)] +#[allow(clippy::string_add_assign)] fn add_only() { // ignores assignment distinction let mut x = "".to_owned(); @@ -16,7 +16,7 @@ fn add_only() { // ignores assignment distinction assert_eq!(&x, &z); } -#[warn(string_add_assign)] +#[warn(clippy::string_add_assign)] fn add_assign_only() { let mut x = "".to_owned(); @@ -30,7 +30,7 @@ fn add_assign_only() { assert_eq!(&x, &z); } -#[warn(string_add, string_add_assign)] +#[warn(clippy::string_add, clippy::string_add_assign)] fn both() { let mut x = "".to_owned(); @@ -45,7 +45,7 @@ fn both() { } #[allow(dead_code, unused_variables)] -#[warn(string_lit_as_bytes)] +#[warn(clippy::string_lit_as_bytes)] fn str_lit_as_bytes() { let bs = "hello there".as_bytes(); diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index 761339b0a8e..de67bb1aff5 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(stutter)] +#![warn(clippy::stutter)] #![allow(dead_code)] mod foo { diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 9f6fce2495a..04e235c690b 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(suspicious_arithmetic_impl)] +#![warn(clippy::suspicious_arithmetic_impl)] use std::ops::{Add, AddAssign, Mul, Sub, Div}; #[derive(Copy, Clone)] diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index d1d12641c46..377319e8faa 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(clippy)] -#![allow(blacklisted_name, unused_assignments)] +#![warn(clippy::all)] +#![allow(clippy::blacklisted_name, unused_assignments)] struct Foo(u32); diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 8f25aad72bb..1d0cffcfc0a 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(temporary_assignment)] +#![warn(clippy::temporary_assignment)] use std::ops::{Deref, DerefMut}; diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index a0d6dd2dabd..86eb7fa5565 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(clippy)] +#![warn(clippy::all)] #![allow(unused)] fn the_answer(ref mut x: u8) { diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 54e1734e141..34d50da11ca 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,4 +1,4 @@ - +#![feature(tool_lints)] #![allow(dead_code)] @@ -16,8 +16,8 @@ fn my_vec() -> MyVec { vec![] } -#[allow(needless_lifetimes, transmute_ptr_to_ptr)] -#[warn(useless_transmute)] +#[allow(clippy::needless_lifetimes, clippy::transmute_ptr_to_ptr)] +#[warn(clippy::useless_transmute)] unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a T = core::intrinsics::transmute(t); @@ -30,7 +30,7 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: *const U = core::intrinsics::transmute(t); } -#[warn(transmute_ptr_to_ref)] +#[warn(clippy::transmute_ptr_to_ref)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); let _: &T = &*p; @@ -54,7 +54,7 @@ unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*(om as *const T); } -#[warn(transmute_ptr_to_ref)] +#[warn(clippy::transmute_ptr_to_ref)] fn issue1231() { struct Foo<'a, T: 'a> { bar: &'a T, @@ -70,7 +70,7 @@ fn issue1231() { unsafe { std::mem::transmute::<_, Bar>(raw) }; } -#[warn(useless_transmute)] +#[warn(clippy::useless_transmute)] fn useless() { unsafe { let _: Vec = core::intrinsics::transmute(my_vec()); @@ -101,7 +101,7 @@ fn useless() { struct Usize(usize); -#[warn(crosspointer_transmute)] +#[warn(clippy::crosspointer_transmute)] fn crosspointer() { let mut int: Usize = Usize(0); let int_const_ptr: *const Usize = &int as *const Usize; @@ -118,18 +118,18 @@ fn crosspointer() { } } -#[warn(transmute_int_to_char)] +#[warn(clippy::transmute_int_to_char)] fn int_to_char() { let _: char = unsafe { std::mem::transmute(0_u32) }; let _: char = unsafe { std::mem::transmute(0_i32) }; } -#[warn(transmute_int_to_bool)] +#[warn(clippy::transmute_int_to_bool)] fn int_to_bool() { let _: bool = unsafe { std::mem::transmute(0_u8) }; } -#[warn(transmute_int_to_float)] +#[warn(clippy::transmute_int_to_float)] fn int_to_float() { let _: f32 = unsafe { std::mem::transmute(0_u32) }; let _: f32 = unsafe { std::mem::transmute(0_i32) }; @@ -144,13 +144,13 @@ fn bytes_to_str(b: &[u8], mb: &mut [u8]) { // of transmute // Make sure we can do static lifetime transmutes -#[warn(transmute_ptr_to_ptr)] +#[warn(clippy::transmute_ptr_to_ptr)] unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T { std::mem::transmute::<&'a T, &'static T>(t) } // Make sure we can do non-static lifetime transmutes -#[warn(transmute_ptr_to_ptr)] +#[warn(clippy::transmute_ptr_to_ptr)] unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T { std::mem::transmute::<&'a T, &'b T>(t) } @@ -163,7 +163,7 @@ struct GenericParam { t: T, } -#[warn(transmute_ptr_to_ptr)] +#[warn(clippy::transmute_ptr_to_ptr)] fn transmute_ptr_to_ptr() { let ptr = &1u32 as *const u32; let mut_ptr = &mut 1u32 as *mut u32; diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 65240c80a48..539b403cff9 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,9 +1,11 @@ +#![feature(tool_lints)] + //ignore-x86 //no-ignore-x86_64 -#[warn(wrong_transmute)] +#[warn(clippy::wrong_transmute)] fn main() { unsafe { let _: *const usize = std::mem::transmute(6.0f64); diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index a1a1de1e439..e3dbe510a47 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,4 +1,6 @@ -#![allow(many_single_char_names, blacklisted_name, redundant_field_names)] +#![feature(tool_lints)] + +#![allow(clippy::many_single_char_names, clippy::blacklisted_name, clippy::redundant_field_names)] #[derive(Copy, Clone)] struct Foo(u32); @@ -19,7 +21,7 @@ fn good_return_implicit_lt_ref(foo: &Foo) -> &u32 { &foo.0 } -#[allow(needless_lifetimes)] +#[allow(clippy::needless_lifetimes)] fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { &foo.0 } @@ -30,7 +32,7 @@ fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { } } -#[allow(needless_lifetimes)] +#[allow(clippy::needless_lifetimes)] fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> { FooRef { foo, diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 5bb0e7edfed..b997d6d3f14 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,19 +1,19 @@ +#![feature(tool_lints)] - -#[warn(zero_width_space)] +#[warn(clippy::zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); print!("This\u{200B}is\u{200B}fine"); } -#[warn(unicode_not_nfc)] +#[warn(clippy::unicode_not_nfc)] fn canon() { print!("̀àh?"); print!("a\u{0300}h?"); // also okay } -#[warn(non_ascii_literal)] +#[warn(clippy::non_ascii_literal)] fn uni() { print!("Üben!"); print!("\u{DC}ben!"); // this is okay diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 8f290446b5e..2f743f227b8 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,5 +1,7 @@ -#![warn(unit_arg)] -#![allow(no_effect)] +#![feature(tool_lints)] + +#![warn(clippy::unit_arg)] +#![allow(clippy::no_effect)] use std::fmt::Debug; diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index 2b6d757845f..bd79d0f8189 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(unit_cmp)] -#![allow(no_effect, unnecessary_operation)] +#![warn(clippy::unit_cmp)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] #[derive(PartialEq)] pub struct ContainsUnit(()); // should be fine diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 96166ed4f13..7a2fc4ac1f6 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -1,4 +1,6 @@ -#![warn(clone_on_ref_ptr)] +#![feature(tool_lints)] + +#![warn(clippy::clone_on_ref_ptr)] #![allow(unused)] use std::collections::HashSet; @@ -40,7 +42,7 @@ fn clone_on_ref_ptr() { sync::Weak::clone(&arc_weak); let x = Arc::new(SomeImpl); - let _: Arc = x.clone(); + let _: Arc = x.clone(); } fn clone_on_copy_generic(t: T) { diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 53b970dfa72..afc920832ce 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + #![feature(tool_attributes)] #![feature(stmt_expr_attributes)] @@ -5,7 +7,7 @@ struct Outer { inner: u32, } -#[deny(ref_in_deref)] +#[deny(clippy::ref_in_deref)] fn main() { let outer = Outer { inner: 0 }; let inner = (&outer).inner; diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 8c960602264..88b91235df6 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![warn(unneeded_field_pattern)] +#![warn(clippy::unneeded_field_pattern)] #[allow(dead_code, unused)] struct Foo { diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 0ec757cfbcf..df3539e38e8 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#[warn(unreadable_literal)] +#[warn(clippy::unreadable_literal)] #[allow(unused_variables)] fn main() { let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 65536, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index 29f34d31a8e..41b98975d53 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #![allow(unused_imports)] #![allow(dead_code)] -#![warn(unsafe_removed_from_name)] +#![warn(clippy::unsafe_removed_from_name)] use std::cell::{UnsafeCell as TotallySafeCell}; diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index ea72c1b1b70..53bcbce9dbf 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #![allow(dead_code)] -#![warn(unused_io_amount)] +#![warn(clippy::unused_io_amount)] use std::io; diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index 115121dc275..b76fcad1699 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![allow(dead_code, items_after_statements, never_loop)] -#![warn(unused_label)] +#![allow(dead_code, clippy::items_after_statements, clippy::never_loop)] +#![warn(clippy::unused_label)] fn unused_label() { 'label: for i in 1..2 { diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 8b166a34d29..e5c5e893504 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,7 +1,7 @@ +#![feature(tool_lints)] - -#![allow(unused, dead_code, needless_lifetimes, needless_pass_by_value, trivially_copy_pass_by_ref)] -#![warn(extra_unused_lifetimes)] +#![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::extra_unused_lifetimes)] fn empty() { diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index 79e3900fef0..682c42dc935 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -1,4 +1,5 @@ -#![warn(clippy)] +#![feature(tool_lints)] +#![warn(clippy::all)] fn main() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 689c9d68d12..8d18d848ae0 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,6 +1,8 @@ -#![warn(use_self)] +#![feature(tool_lints)] + +#![warn(clippy::use_self)] #![allow(dead_code)] -#![allow(should_implement_trait)] +#![allow(clippy::should_implement_trait)] fn main() {} @@ -64,7 +66,7 @@ mod lifetimes { } } -#[allow(boxed_local)] +#[allow(clippy::boxed_local)] mod traits { use std::ops::Mul; diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index 60a2c4e8b4c..c1e1c9af5db 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] +#![warn(clippy::all)] -#![warn(clippy)] - -#![allow(blacklisted_name)] -#![warn(used_underscore_binding)] +#![allow(clippy::blacklisted_name)] +#![warn(clippy::used_underscore_binding)] macro_rules! test_macro { () => {{ diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 7508cdc7b43..52994566e09 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,10 +1,12 @@ -#![deny(useless_asref)] -#![allow(trivially_copy_pass_by_ref)] +#![feature(tool_lints)] + +#![deny(clippy::useless_asref)] +#![allow(clippy::trivially_copy_pass_by_ref)] use std::fmt::Debug; struct FakeAsRef; -#[allow(should_implement_trait)] +#[allow(clippy::should_implement_trait)] impl FakeAsRef { fn as_ref(&self) -> &Self { self } } diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 68c7d2007a6..300fcfa2b70 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(useless_attribute)] +#![warn(clippy::useless_attribute)] #[allow(dead_code, unused_extern_crates)] #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 23e43872454..78a49f2580a 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,13 +1,13 @@ +#![feature(tool_lints)] - -#![warn(useless_vec)] +#![warn(clippy::useless_vec)] #[derive(Debug)] struct NonCopy; fn on_slice(_: &[u8]) {} -#[allow(ptr_arg)] +#[allow(clippy::ptr_arg)] fn on_vec(_: &Vec) {} struct Line { diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 23a9ce80eb1..0b8691d57b4 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -1,8 +1,8 @@ +#![feature(tool_lints)] - -#![warn(while_let_loop, empty_loop, while_let_on_iterator)] -#![allow(dead_code, never_loop, unused, cyclomatic_complexity)] +#![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)] +#![allow(dead_code, clippy::never_loop, unused, clippy::cyclomatic_complexity)] fn main() { let y = Some(true); @@ -184,7 +184,7 @@ fn refutable() { } } - // should not trigger while_let_loop lint because break passes an expression + // should not trigger clippy::while_let_loop lint because break passes an expression let a = Some(10); let b = loop { if let Some(c) = a { diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 48dfcd0ea3e..5ef4c15f409 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![allow(unused_must_use)] -#![warn(write_literal)] +#![warn(clippy::write_literal)] use std::io::Write; diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 8badbd65726..e060459a411 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -1,5 +1,7 @@ -#![allow(write_literal)] -#![warn(write_with_newline)] +#![feature(tool_lints)] + +#![allow(clippy::write_literal)] +#![warn(clippy::write_with_newline)] use std::io::Write; diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index faccfd8291c..81dfdcdc0d0 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -1,5 +1,7 @@ +#![feature(tool_lints)] + #![allow(unused_must_use)] -#![warn(writeln_empty_string)] +#![warn(clippy::writeln_empty_string)] use std::io::Write; fn main() { diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 07a93d6889b..1e718c1c648 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,9 +1,9 @@ +#![feature(tool_lints)] - -#![warn(wrong_self_convention)] -#![warn(wrong_pub_self_convention)] -#![allow(dead_code, trivially_copy_pass_by_ref)] +#![warn(clippy::wrong_self_convention)] +#![warn(clippy::wrong_pub_self_convention)] +#![allow(dead_code, clippy::trivially_copy_pass_by_ref)] fn main() {} @@ -26,7 +26,7 @@ impl Foo { pub fn to_i64(self) {} pub fn from_i64(self) {} // check whether the lint can be allowed at the function level - #[allow(wrong_self_convention)] + #[allow(clippy::wrong_self_convention)] pub fn from_cake(self) {} fn as_x>(_: F) { } diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index 65e1e239980..7927e8b8ac7 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -1,8 +1,8 @@ - +#![feature(tool_lints)] #[allow(unused_variables)] -#[warn(zero_divided_by_zero)] +#[warn(clippy::zero_divided_by_zero)] fn main() { let nan = 0.0 / 0.0; let f64_nan = 0.0 / 0.0f64; -- cgit 1.4.1-3-g733a5 From e9af09c27490a9f5f264c4cf2a673272eb67b66d Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 1 Aug 2018 16:30:44 +0200 Subject: Adapt the *.stderr files of the ui-tests to the tool_lints --- tests/ui/absurd-extreme-comparisons.stderr | 4 +- tests/ui/approx_const.stderr | 2 +- tests/ui/arithmetic.stderr | 4 +- tests/ui/assign_ops.stderr | 46 +-- tests/ui/assign_ops2.stderr | 2 +- tests/ui/attrs.stderr | 4 +- tests/ui/author/matches.stderr | 2 +- tests/ui/bit_masks.stderr | 6 +- tests/ui/blacklisted_name.stderr | 2 +- tests/ui/block_in_if_condition.stderr | 6 +- tests/ui/bool_comparison.stderr | 2 +- tests/ui/booleans.stderr | 4 +- tests/ui/borrow_box.stderr | 4 +- tests/ui/box_vec.stderr | 2 +- tests/ui/builtin-type-shadow.stderr | 2 +- tests/ui/bytecount.stderr | 4 +- tests/ui/cast.stderr | 12 +- tests/ui/cast_alignment.stderr | 10 +- tests/ui/cast_lossless_float.stderr | 50 ++-- tests/ui/cast_lossless_integer.stderr | 2 +- tests/ui/cast_size.stderr | 92 +++--- tests/ui/char_lit_as_u8.stderr | 2 +- tests/ui/checked_unwrap.stderr | 240 +++++++-------- tests/ui/cmp_nan.stderr | 2 +- tests/ui/cmp_null.stderr | 2 +- tests/ui/cmp_owned.stderr | 2 +- tests/ui/collapsible_if.stderr | 2 +- tests/ui/complex_types.stderr | 2 +- tests/ui/const_static_lifetime.stderr | 2 +- tests/ui/copies.stderr | 340 +++++++++++----------- tests/ui/copy_iterator.stderr | 16 +- tests/ui/cstring.stderr | 10 +- tests/ui/cyclomatic_complexity.stderr | 2 +- tests/ui/cyclomatic_complexity_attr_used.stderr | 2 +- tests/ui/decimal_literal_representation.stderr | 2 +- tests/ui/default_trait_access.stderr | 40 +-- tests/ui/derive.stderr | 4 +- tests/ui/diverging_sub_expression.stderr | 26 +- tests/ui/dlist.stderr | 26 +- tests/ui/doc.stderr | 138 ++++----- tests/ui/double_comparison.stderr | 2 +- tests/ui/double_neg.stderr | 2 +- tests/ui/double_parens.stderr | 2 +- tests/ui/drop_forget_copy.stderr | 4 +- tests/ui/drop_forget_ref.stderr | 4 +- tests/ui/duplicate_underscore_argument.stderr | 2 +- tests/ui/duration_subsec.stderr | 32 +- tests/ui/else_if_without_else.stderr | 18 +- tests/ui/empty_enum.stderr | 2 +- tests/ui/empty_line_after_outer_attribute.stderr | 2 +- tests/ui/entry.stderr | 2 +- tests/ui/enum_glob_use.stderr | 2 +- tests/ui/enum_variants.stderr | 92 +++--- tests/ui/enums_clike.stderr | 34 +-- tests/ui/eq_op.stderr | 6 +- tests/ui/erasing_op.stderr | 2 +- tests/ui/eta.stderr | 4 +- tests/ui/eval_order_dependence.stderr | 2 +- tests/ui/excessive_precision.stderr | 2 +- tests/ui/explicit_write.stderr | 26 +- tests/ui/fallible_impl_from.stderr | 100 +++---- tests/ui/filter_methods.stderr | 2 +- tests/ui/float_cmp.stderr | 2 +- tests/ui/float_cmp_const.stderr | 2 +- tests/ui/for_loop.stderr | 24 +- tests/ui/format.stderr | 2 +- tests/ui/formatting.stderr | 6 +- tests/ui/functions.stderr | 4 +- tests/ui/fxhash.stderr | 26 +- tests/ui/get_unwrap.stderr | 2 +- tests/ui/identity_conversion.stderr | 42 +-- tests/ui/identity_op.stderr | 2 +- tests/ui/if_let_redundant_pattern_matching.stderr | 2 +- tests/ui/if_not_else.stderr | 2 +- tests/ui/impl.stderr | 34 +-- tests/ui/implicit_hasher.stderr | 2 +- tests/ui/inconsistent_digit_grouping.stderr | 2 +- tests/ui/indexing_slicing.stderr | 152 +++++----- tests/ui/infallible_destructuring_match.stderr | 26 +- tests/ui/infinite_iter.stderr | 10 +- tests/ui/infinite_loop.stderr | 42 +-- tests/ui/inline_fn_without_body.stderr | 2 +- tests/ui/int_plus_one.stderr | 2 +- tests/ui/invalid_ref.stderr | 2 +- tests/ui/invalid_upcast_comparisons.stderr | 2 +- tests/ui/issue_2356.stderr | 10 +- tests/ui/item_after_statement.stderr | 2 +- tests/ui/large_digit_groups.stderr | 2 +- tests/ui/large_enum_variant.stderr | 2 +- tests/ui/len_zero.stderr | 116 ++++---- tests/ui/let_if_seq.stderr | 2 +- tests/ui/let_return.stderr | 2 +- tests/ui/let_unit.stderr | 2 +- tests/ui/lifetimes.stderr | 2 +- tests/ui/literals.stderr | 82 +++--- tests/ui/map_clone.stderr | 2 +- tests/ui/match_bool.stderr | 6 +- tests/ui/matches.stderr | 12 +- tests/ui/mem_forget.stderr | 2 +- tests/ui/methods.stderr | 30 +- tests/ui/min_max.stderr | 2 +- tests/ui/missing-doc.stderr | 216 +++++++------- tests/ui/missing_inline.stderr | 26 +- tests/ui/module_inception.stderr | 2 +- tests/ui/modulo_one.stderr | 2 +- tests/ui/mut_from_ref.stderr | 2 +- tests/ui/mut_mut.stderr | 2 +- tests/ui/mut_range_bound.stderr | 2 +- tests/ui/mut_reference.stderr | 2 +- tests/ui/mutex_atomic.stderr | 4 +- tests/ui/needless_bool.stderr | 2 +- tests/ui/needless_borrow.stderr | 28 +- tests/ui/needless_borrowed_ref.stderr | 2 +- tests/ui/needless_continue.stderr | 2 +- tests/ui/needless_pass_by_value.stderr | 140 ++++----- tests/ui/needless_range_loop.stderr | 2 +- tests/ui/needless_return.stderr | 2 +- tests/ui/needless_update.stderr | 2 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 18 +- tests/ui/neg_multiply.stderr | 2 +- tests/ui/never_loop.stderr | 4 +- tests/ui/new_without_default.stderr | 30 +- tests/ui/no_effect.stderr | 192 ++++++------ tests/ui/non_copy_const.stderr | 158 +++++----- tests/ui/non_expressive_names.stderr | 6 +- tests/ui/ok_expect.stderr | 2 +- tests/ui/ok_if_let.stderr | 2 +- tests/ui/op_ref.stderr | 2 +- tests/ui/open_options.stderr | 2 +- tests/ui/option_map_unit_fn.stderr | 108 +++---- tests/ui/option_option.stderr | 2 +- tests/ui/overflow_check_conditional.stderr | 2 +- tests/ui/panic_unimplemented.stderr | 4 +- tests/ui/partialeq_ne_impl.stderr | 2 +- tests/ui/patterns.stderr | 2 +- tests/ui/precedence.stderr | 2 +- tests/ui/print.stderr | 4 +- tests/ui/print_literal.stderr | 2 +- tests/ui/print_with_newline.stderr | 2 +- tests/ui/println_empty_string.stderr | 2 +- tests/ui/ptr_arg.stderr | 50 ++-- tests/ui/question_mark.stderr | 2 +- tests/ui/range.stderr | 4 +- tests/ui/range_plus_minus_one.stderr | 32 +- tests/ui/redundant_closure_call.stderr | 2 +- tests/ui/redundant_field_names.stderr | 30 +- tests/ui/reference.stderr | 2 +- tests/ui/regex.stderr | 4 +- tests/ui/replace_consts.stderr | 146 +++++----- tests/ui/result_map_unit_fn.stderr | 108 +++---- tests/ui/serde.stderr | 2 +- tests/ui/shadow.stderr | 6 +- tests/ui/short_circuit_statement.stderr | 2 +- tests/ui/single_char_pattern.stderr | 82 +++--- tests/ui/single_match.stderr | 52 ++-- tests/ui/starts_ends_with.stderr | 56 ++-- tests/ui/string_extend.stderr | 2 +- tests/ui/strings.stderr | 8 +- tests/ui/stutter.stderr | 2 +- tests/ui/suspicious_arithmetic_impl.stderr | 4 +- tests/ui/swap.stderr | 4 +- tests/ui/temporary_assignment.stderr | 2 +- tests/ui/toplevel_ref_arg.stderr | 2 +- tests/ui/trailing_zeros.stderr | 2 +- tests/ui/transmute.stderr | 16 +- tests/ui/transmute_64bit.stderr | 16 +- tests/ui/trivially_copy_pass_by_ref.stderr | 54 ++-- tests/ui/types.stderr | 2 +- tests/ui/types_fn_to_int.stderr | 4 +- tests/ui/unicode.stderr | 6 +- tests/ui/unit_arg.stderr | 44 +-- tests/ui/unit_cmp.stderr | 2 +- tests/ui/unnecessary_clone.stderr | 56 ++-- tests/ui/unnecessary_fold.stderr | 2 +- tests/ui/unnecessary_ref.stderr | 10 +- tests/ui/unneeded_field_pattern.stderr | 2 +- tests/ui/unreadable_literal.stderr | 2 +- tests/ui/unsafe_removed_from_name.stderr | 2 +- tests/ui/unused_io_amount.stderr | 2 +- tests/ui/unused_labels.stderr | 2 +- tests/ui/unused_lt.stderr | 2 +- tests/ui/unwrap_or.stderr | 14 +- tests/ui/use_self.stderr | 90 +++--- tests/ui/used_underscore_binding.stderr | 2 +- tests/ui/useless_asref.stderr | 50 ++-- tests/ui/useless_attribute.stderr | 2 +- tests/ui/vec.stderr | 2 +- tests/ui/while_loop.stderr | 6 +- tests/ui/write_literal.stderr | 58 ++-- tests/ui/write_with_newline.stderr | 18 +- tests/ui/writeln_empty_string.stderr | 16 +- tests/ui/wrong_self_convention.stderr | 2 +- tests/ui/zero_div_zero.stderr | 4 +- tests/ui/zero_ptr.stderr | 2 +- 194 files changed, 2109 insertions(+), 2109 deletions(-) diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 72b2f7a3942..2e5ebec7573 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -4,7 +4,7 @@ error: this comparison involving the minimum or maximum element for this type co 10 | u <= 0; | ^^^^^^ | - = note: `-D absurd-extreme-comparisons` implied by `-D warnings` + = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings` = help: because 0 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false @@ -141,7 +141,7 @@ error: <-comparison of unit values detected. This will always be false 31 | () < {}; | ^^^^^^^ | - = note: #[deny(unit_cmp)] on by default + = note: #[deny(clippy::unit_cmp)] on by default error: aborting due to 18 previous errors diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index e5d2ba29605..3ff016b9c40 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -4,7 +4,7 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it dire 7 | let my_e = 2.7182; | ^^^^^^ | - = note: `-D approx-constant` implied by `-D warnings` + = note: `-D clippy::approx-constant` implied by `-D warnings` error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly --> $DIR/approx_const.rs:8:20 diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index ad4a02e2190..ee7a594fa15 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -4,7 +4,7 @@ error: integer arithmetic detected 8 | 1 + i; | ^^^^^ | - = note: `-D integer-arithmetic` implied by `-D warnings` + = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected --> $DIR/arithmetic.rs:9:5 @@ -37,7 +37,7 @@ error: floating-point arithmetic detected 23 | f * 2.0; | ^^^^^^^ | - = note: `-D float-arithmetic` implied by `-D warnings` + = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected --> $DIR/arithmetic.rs:25:5 diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 826dacc53a9..fe7ccff7805 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,57 +1,57 @@ error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:5:5 + --> $DIR/assign_ops.rs:7:5 | -5 | a = a + 1; +7 | a = a + 1; | ^^^^^^^^^ help: replace it with: `a += 1` | - = note: `-D assign-op-pattern` implied by `-D warnings` + = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:6:5 + --> $DIR/assign_ops.rs:8:5 | -6 | a = 1 + a; +8 | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:7:5 + --> $DIR/assign_ops.rs:9:5 | -7 | a = a - 1; +9 | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:8:5 - | -8 | a = a * 99; - | ^^^^^^^^^^ help: replace it with: `a *= 99` + --> $DIR/assign_ops.rs:10:5 + | +10 | a = a * 99; + | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:9:5 - | -9 | a = 42 * a; - | ^^^^^^^^^^ help: replace it with: `a *= 42` + --> $DIR/assign_ops.rs:11:5 + | +11 | a = 42 * a; + | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:10:5 + --> $DIR/assign_ops.rs:12:5 | -10 | a = a / 2; +12 | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:11:5 + --> $DIR/assign_ops.rs:13:5 | -11 | a = a % 5; +13 | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:12:5 + --> $DIR/assign_ops.rs:14:5 | -12 | a = a & 1; +14 | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:18:5 + --> $DIR/assign_ops.rs:20:5 | -18 | s = s + "bla"; +20 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: aborting due to 9 previous errors diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 2858af1f8c0..93528e50577 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -4,7 +4,7 @@ error: variable appears on both sides of an assignment operation 8 | a += a + 1; | ^^^^^^^^^^ | - = note: `-D misrefactored-assign-op` implied by `-D warnings` + = note: `-D clippy::misrefactored-assign-op` implied by `-D warnings` help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with | 8 | a += 1; diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index f743399a606..6b6ecd675b3 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -4,7 +4,7 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usuall 6 | #[inline(always)] | ^^^^^^^^^^^^^^^^^ | - = note: `-D inline-always` implied by `-D warnings` + = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version --> $DIR/attrs.rs:27:14 @@ -12,7 +12,7 @@ error: the since field must contain a semver-compliant version 27 | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ | - = note: `-D deprecated-semver` implied by `-D warnings` + = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version --> $DIR/attrs.rs:30:14 diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr index c4f69b10df7..46618fe4065 100644 --- a/tests/ui/author/matches.stderr +++ b/tests/ui/author/matches.stderr @@ -4,7 +4,7 @@ error: returning the result of a let binding from a block. Consider returning th 9 | x | ^ | - = note: `-D let-and-return` implied by `-D warnings` + = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned --> $DIR/matches.rs:8:21 | diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index e1a4a42914c..dcf3f241b4b 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -4,7 +4,7 @@ error: &-masking with zero 12 | x & 0 == 0; | ^^^^^^^^^^ | - = note: `-D bad-bit-mask` implied by `-D warnings` + = note: `-D clippy::bad-bit-mask` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome --> $DIR/bit_masks.rs:12:5 @@ -12,7 +12,7 @@ error: this operation will always return zero. This is likely not the intended o 12 | x & 0 == 0; | ^^^^^ | - = note: #[deny(erasing_op)] on by default + = note: #[deny(clippy::erasing_op)] on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:15:5 @@ -86,7 +86,7 @@ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared 52 | x | 1 > 3; | ^^^^^^^^^ | - = note: `-D ineffective-bit-mask` implied by `-D warnings` + = note: `-D clippy::ineffective-bit-mask` implied by `-D warnings` error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly --> $DIR/bit_masks.rs:53:5 diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 68fbe27a01e..472401d5ed6 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -4,7 +4,7 @@ error: use of a blacklisted/placeholder name `foo` 7 | fn test(foo: ()) {} | ^^^ | - = note: `-D blacklisted-name` implied by `-D warnings` + = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `foo` --> $DIR/blacklisted_name.rs:10:9 diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index 4b7d12598ec..41f1e9c1681 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -8,7 +8,7 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; inste 33 | | } { | |_____^ | - = note: `-D block-in-if-condition-stmt` implied by `-D warnings` + = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` = help: try let res = { let x = 3; @@ -24,7 +24,7 @@ error: omit braces around single expression condition 41 | if { true } { | ^^^^^^^^ | - = note: `-D block-in-if-condition-expr` implied by `-D warnings` + = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` = help: try if true { 6 @@ -48,7 +48,7 @@ error: this boolean expression can be simplified 67 | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` | - = note: `-D nonminimal-bool` implied by `-D warnings` + = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: aborting due to 5 previous errors diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 4436980bc11..2fcde94367a 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -4,7 +4,7 @@ error: equality checks against true are unnecessary 7 | if x == true { "yes" } else { "no" }; | ^^^^^^^^^ help: try simplifying it as shown: `x` | - = note: `-D bool-comparison` implied by `-D warnings` + = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation --> $DIR/bool_comparison.rs:8:8 diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index f1996e8a26e..45e371025ef 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -4,7 +4,7 @@ error: this boolean expression contains a logic bug 12 | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | - = note: `-D logic-bug` implied by `-D warnings` + = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:12:18 | @@ -17,7 +17,7 @@ error: this boolean expression can be simplified 14 | let _ = !true; | ^^^^^ help: try: `false` | - = note: `-D nonminimal-bool` implied by `-D warnings` + = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified --> $DIR/booleans.rs:15:13 diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 2cf0ea79626..1098c7785e2 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -7,8 +7,8 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` note: lint level defined here --> $DIR/borrow_box.rs:4:9 | -4 | #![deny(borrowed_box)] - | ^^^^^^^^^^^^ +4 | #![deny(clippy::borrowed_box)] + | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` --> $DIR/borrow_box.rs:14:14 diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index 254d0771386..b90bb5e2a4e 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -4,7 +4,7 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` 17 | pub fn test(foo: Box>) { | ^^^^^^^^^^^^^^ | - = note: `-D box-vec` implied by `-D warnings` + = note: `-D clippy::box-vec` implied by `-D warnings` = help: `Vec` is already on the heap, `Box>` makes an extra allocation. error: aborting due to previous error diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 5757a6ef390..78924ebf9cf 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -4,7 +4,7 @@ error: This generic shadows the built-in type `u32` 5 | fn foo(a: u32) -> u32 { | ^^^ | - = note: `-D builtin-type-shadow` implied by `-D warnings` + = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types --> $DIR/builtin-type-shadow.rs:6:5 diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 307edecfde1..0564d6a0b60 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -7,8 +7,8 @@ error: You appear to be counting bytes the naive way note: lint level defined here --> $DIR/bytecount.rs:4:8 | -4 | #[deny(naive_bytecount)] - | ^^^^^^^^^^^^^^^ +4 | #[deny(clippy::naive_bytecount)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way --> $DIR/bytecount.rs:10:13 diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 0a008cb68bb..2578c49893f 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -4,7 +4,7 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f 8 | 1i32 as f32; | ^^^^^^^^^^^ | - = note: `-D cast-precision-loss` implied by `-D warnings` + = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast.rs:9:5 @@ -42,7 +42,7 @@ error: casting f32 to i32 may truncate the value 15 | 1f32 as i32; | ^^^^^^^^^^^ | - = note: `-D cast-possible-truncation` implied by `-D warnings` + = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value --> $DIR/cast.rs:16:5 @@ -56,7 +56,7 @@ error: casting f32 to u32 may lose the sign of the value 16 | 1f32 as u32; | ^^^^^^^^^^^ | - = note: `-D cast-sign-loss` implied by `-D warnings` + = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value --> $DIR/cast.rs:17:5 @@ -106,7 +106,7 @@ error: casting u8 to i8 may wrap around the value 23 | 1u8 as i8; | ^^^^^^^^^ | - = note: `-D cast-possible-wrap` implied by `-D warnings` + = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value --> $DIR/cast.rs:24:5 @@ -138,7 +138,7 @@ error: casting f32 to f64 may become silently lossy if types change 29 | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` | - = note: `-D cast-lossless` implied by `-D warnings` + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting u8 to u16 may become silently lossy if types change --> $DIR/cast.rs:31:5 @@ -164,7 +164,7 @@ error: casting to the same type is unnecessary (`i32` -> `i32`) 37 | 1i32 as i32; | ^^^^^^^^^^^ | - = note: `-D unnecessary-cast` implied by `-D warnings` + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) --> $DIR/cast.rs:38:5 diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 42df78a37a6..d03d727a89c 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,15 +1,15 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:13:5 + --> $DIR/cast_alignment.rs:15:5 | -13 | (&1u8 as *const u8) as *const u16; +15 | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D cast-ptr-alignment` implied by `-D warnings` + = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:14:5 + --> $DIR/cast_alignment.rs:16:5 | -14 | (&mut 1u8 as *mut u8) as *mut u16; +16 | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index a60f838fae8..9025633a141 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,63 +1,63 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:5:5 + --> $DIR/cast_lossless_float.rs:7:5 | -5 | 1i8 as f32; +7 | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` | - = note: `-D cast-lossless` implied by `-D warnings` + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:6:5 + --> $DIR/cast_lossless_float.rs:8:5 | -6 | 1i8 as f64; +8 | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:7:5 + --> $DIR/cast_lossless_float.rs:9:5 | -7 | 1u8 as f32; +9 | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:8:5 - | -8 | 1u8 as f64; - | ^^^^^^^^^^ help: try: `f64::from(1u8)` + --> $DIR/cast_lossless_float.rs:10:5 + | +10 | 1u8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:9:5 - | -9 | 1i16 as f32; - | ^^^^^^^^^^^ help: try: `f32::from(1i16)` + --> $DIR/cast_lossless_float.rs:11:5 + | +11 | 1i16 as f32; + | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:10:5 + --> $DIR/cast_lossless_float.rs:12:5 | -10 | 1i16 as f64; +12 | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:11:5 + --> $DIR/cast_lossless_float.rs:13:5 | -11 | 1u16 as f32; +13 | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:12:5 + --> $DIR/cast_lossless_float.rs:14:5 | -12 | 1u16 as f64; +14 | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:13:5 + --> $DIR/cast_lossless_float.rs:15:5 | -13 | 1i32 as f64; +15 | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:14:5 + --> $DIR/cast_lossless_float.rs:16:5 | -14 | 1u32 as f64; +16 | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` error: aborting due to 10 previous errors diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index 19d6176193c..9640e1e18fa 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -4,7 +4,7 @@ error: casting i8 to i16 may become silently lossy if types change 6 | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` | - = note: `-D cast-lossless` implied by `-D warnings` + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:7:5 diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index 1c4b12bcebf..1797e2e367f 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,123 +1,123 @@ error: casting isize to i8 may truncate the value - --> $DIR/cast_size.rs:5:5 + --> $DIR/cast_size.rs:7:5 | -5 | 1isize as i8; +7 | 1isize as i8; | ^^^^^^^^^^^^ | - = note: `-D cast-possible-truncation` implied by `-D warnings` + = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:6:5 + --> $DIR/cast_size.rs:8:5 | -6 | 1isize as f64; +8 | 1isize as f64; | ^^^^^^^^^^^^^ | - = note: `-D cast-precision-loss` implied by `-D warnings` + = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:7:5 + --> $DIR/cast_size.rs:9:5 | -7 | 1usize as f64; +9 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:8:5 - | -8 | 1isize as f32; - | ^^^^^^^^^^^^^ + --> $DIR/cast_size.rs:10:5 + | +10 | 1isize as f32; + | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:9:5 - | -9 | 1usize as f32; - | ^^^^^^^^^^^^^ + --> $DIR/cast_size.rs:11:5 + | +11 | 1usize as f32; + | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:10:5 + --> $DIR/cast_size.rs:12:5 | -10 | 1isize as i32; +12 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast_size.rs:11:5 + --> $DIR/cast_size.rs:13:5 | -11 | 1isize as u32; +13 | 1isize as u32; | ^^^^^^^^^^^^^ | - = note: `-D cast-sign-loss` implied by `-D warnings` + = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:11:5 + --> $DIR/cast_size.rs:13:5 | -11 | 1isize as u32; +13 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:12:5 + --> $DIR/cast_size.rs:14:5 | -12 | 1usize as u32; +14 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:13:5 + --> $DIR/cast_size.rs:15:5 | -13 | 1usize as i32; +15 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:13:5 + --> $DIR/cast_size.rs:15:5 | -13 | 1usize as i32; +15 | 1usize as i32; | ^^^^^^^^^^^^^ | - = note: `-D cast-possible-wrap` implied by `-D warnings` + = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:15:5 + --> $DIR/cast_size.rs:17:5 | -15 | 1i64 as isize; +17 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast_size.rs:16:5 + --> $DIR/cast_size.rs:18:5 | -16 | 1i64 as usize; +18 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:16:5 + --> $DIR/cast_size.rs:18:5 | -16 | 1i64 as usize; +18 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:17:5 + --> $DIR/cast_size.rs:19:5 | -17 | 1u64 as isize; +19 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:17:5 + --> $DIR/cast_size.rs:19:5 | -17 | 1u64 as isize; +19 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:18:5 + --> $DIR/cast_size.rs:20:5 | -18 | 1u64 as usize; +20 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:19:5 + --> $DIR/cast_size.rs:21:5 | -19 | 1u32 as isize; +21 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast_size.rs:22:5 + --> $DIR/cast_size.rs:24:5 | -22 | 1i32 as usize; +24 | 1i32 as usize; | ^^^^^^^^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index fcf038fe002..f6ea10d5731 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -4,7 +4,7 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so cas 7 | let c = 'a' as u8; | ^^^^^^^^^ | - = note: `-D char-lit-as-u8` implied by `-D warnings` + = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` = help: Consider using a byte literal instead: b'a' diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index 1b46ceb5fa8..4508ce442fa 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,313 +1,313 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:7:9 + --> $DIR/checked_unwrap.rs:9:9 | -6 | if x.is_some() { +8 | if x.is_some() { | ----------- the check is happening here -7 | x.unwrap(); // unnecessary +9 | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:1:27 + --> $DIR/checked_unwrap.rs:3:35 | -1 | #![deny(panicking_unwrap, unnecessary_unwrap)] - | ^^^^^^^^^^^^^^^^^^ +3 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:9:9 - | -6 | if x.is_some() { - | ----------- because of this check + --> $DIR/checked_unwrap.rs:11:9 + | +8 | if x.is_some() { + | ----------- because of this check ... -9 | x.unwrap(); // will panic - | ^^^^^^^^^^ - | +11 | x.unwrap(); // will panic + | ^^^^^^^^^^ + | note: lint level defined here - --> $DIR/checked_unwrap.rs:1:9 - | -1 | #![deny(panicking_unwrap, unnecessary_unwrap)] - | ^^^^^^^^^^^^^^^^ + --> $DIR/checked_unwrap.rs:3:9 + | +3 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:12:9 + --> $DIR/checked_unwrap.rs:14:9 | -11 | if x.is_none() { +13 | if x.is_none() { | ----------- because of this check -12 | x.unwrap(); // will panic +14 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:14:9 + --> $DIR/checked_unwrap.rs:16:9 | -11 | if x.is_none() { +13 | if x.is_none() { | ----------- the check is happening here ... -14 | x.unwrap(); // unnecessary +16 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:18:9 + --> $DIR/checked_unwrap.rs:20:9 | -17 | if x.is_ok() { +19 | if x.is_ok() { | --------- the check is happening here -18 | x.unwrap(); // unnecessary +20 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:19:9 + --> $DIR/checked_unwrap.rs:21:9 | -17 | if x.is_ok() { +19 | if x.is_ok() { | --------- because of this check -18 | x.unwrap(); // unnecessary -19 | x.unwrap_err(); // will panic +20 | x.unwrap(); // unnecessary +21 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:21:9 + --> $DIR/checked_unwrap.rs:23:9 | -17 | if x.is_ok() { +19 | if x.is_ok() { | --------- because of this check ... -21 | x.unwrap(); // will panic +23 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:22:9 + --> $DIR/checked_unwrap.rs:24:9 | -17 | if x.is_ok() { +19 | if x.is_ok() { | --------- the check is happening here ... -22 | x.unwrap_err(); // unnecessary +24 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:25:9 + --> $DIR/checked_unwrap.rs:27:9 | -24 | if x.is_err() { +26 | if x.is_err() { | ---------- because of this check -25 | x.unwrap(); // will panic +27 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:26:9 + --> $DIR/checked_unwrap.rs:28:9 | -24 | if x.is_err() { +26 | if x.is_err() { | ---------- the check is happening here -25 | x.unwrap(); // will panic -26 | x.unwrap_err(); // unnecessary +27 | x.unwrap(); // will panic +28 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:28:9 + --> $DIR/checked_unwrap.rs:30:9 | -24 | if x.is_err() { +26 | if x.is_err() { | ---------- the check is happening here ... -28 | x.unwrap(); // unnecessary +30 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:29:9 + --> $DIR/checked_unwrap.rs:31:9 | -24 | if x.is_err() { +26 | if x.is_err() { | ---------- because of this check ... -29 | x.unwrap_err(); // will panic +31 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:46:9 + --> $DIR/checked_unwrap.rs:48:9 | -45 | if x.is_ok() && y.is_err() { +47 | if x.is_ok() && y.is_err() { | --------- the check is happening here -46 | x.unwrap(); // unnecessary +48 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:47:9 + --> $DIR/checked_unwrap.rs:49:9 | -45 | if x.is_ok() && y.is_err() { +47 | if x.is_ok() && y.is_err() { | --------- because of this check -46 | x.unwrap(); // unnecessary -47 | x.unwrap_err(); // will panic +48 | x.unwrap(); // unnecessary +49 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:48:9 + --> $DIR/checked_unwrap.rs:50:9 | -45 | if x.is_ok() && y.is_err() { +47 | if x.is_ok() && y.is_err() { | ---------- because of this check ... -48 | y.unwrap(); // will panic +50 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:49:9 + --> $DIR/checked_unwrap.rs:51:9 | -45 | if x.is_ok() && y.is_err() { +47 | if x.is_ok() && y.is_err() { | ---------- the check is happening here ... -49 | y.unwrap_err(); // unnecessary +51 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:63:9 + --> $DIR/checked_unwrap.rs:65:9 | -58 | if x.is_ok() || y.is_ok() { +60 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -63 | x.unwrap(); // will panic +65 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:64:9 + --> $DIR/checked_unwrap.rs:66:9 | -58 | if x.is_ok() || y.is_ok() { +60 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -64 | x.unwrap_err(); // unnecessary +66 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:65:9 + --> $DIR/checked_unwrap.rs:67:9 | -58 | if x.is_ok() || y.is_ok() { +60 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -65 | y.unwrap(); // will panic +67 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:66:9 + --> $DIR/checked_unwrap.rs:68:9 | -58 | if x.is_ok() || y.is_ok() { +60 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -66 | y.unwrap_err(); // unnecessary +68 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:70:9 + --> $DIR/checked_unwrap.rs:72:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -70 | x.unwrap(); // unnecessary +72 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:71:9 + --> $DIR/checked_unwrap.rs:73:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check -70 | x.unwrap(); // unnecessary -71 | x.unwrap_err(); // will panic +72 | x.unwrap(); // unnecessary +73 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:72:9 + --> $DIR/checked_unwrap.rs:74:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check ... -72 | y.unwrap(); // will panic +74 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:73:9 + --> $DIR/checked_unwrap.rs:75:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here ... -73 | y.unwrap_err(); // unnecessary +75 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:74:9 + --> $DIR/checked_unwrap.rs:76:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here ... -74 | z.unwrap(); // unnecessary +76 | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:75:9 + --> $DIR/checked_unwrap.rs:77:9 | -69 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check ... -75 | z.unwrap_err(); // will panic +77 | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:83:9 + --> $DIR/checked_unwrap.rs:85:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -83 | x.unwrap(); // will panic +85 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:84:9 + --> $DIR/checked_unwrap.rs:86:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -84 | x.unwrap_err(); // unnecessary +86 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:85:9 + --> $DIR/checked_unwrap.rs:87:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -85 | y.unwrap(); // unnecessary +87 | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:86:9 + --> $DIR/checked_unwrap.rs:88:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -86 | y.unwrap_err(); // will panic +88 | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:87:9 + --> $DIR/checked_unwrap.rs:89:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check ... -87 | z.unwrap(); // will panic +89 | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:88:9 + --> $DIR/checked_unwrap.rs:90:9 | -77 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here ... -88 | z.unwrap_err(); // unnecessary +90 | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:96:13 + --> $DIR/checked_unwrap.rs:98:13 | -95 | if x.is_some() { +97 | if x.is_some() { | ----------- the check is happening here -96 | x.unwrap(); // unnecessary +98 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:98:13 - | -95 | if x.is_some() { - | ----------- because of this check + --> $DIR/checked_unwrap.rs:100:13 + | +97 | if x.is_some() { + | ----------- because of this check ... -98 | x.unwrap(); // will panic - | ^^^^^^^^^^ +100 | x.unwrap(); // will panic + | ^^^^^^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 46f3d3d57e0..7f636e6b534 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -4,7 +4,7 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead 8 | x == std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ | - = note: `-D cmp-nan` implied by `-D warnings` + = note: `-D clippy::cmp-nan` implied by `-D warnings` error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:9:5 diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 481a4d0f942..55050d2a320 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -4,7 +4,7 @@ error: Comparing with null is better expressed by the .is_null() method 11 | if p == ptr::null() { | ^^^^^^^^^^^^^^^^ | - = note: `-D cmp-null` implied by `-D warnings` + = note: `-D clippy::cmp-null` implied by `-D warnings` error: Comparing with null is better expressed by the .is_null() method --> $DIR/cmp_null.rs:16:8 diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index d40fb4b8add..2691c12eab1 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -4,7 +4,7 @@ error: this creates an owned instance just for comparison 8 | x != "foo".to_string(); | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` | - = note: `-D cmp-owned` implied by `-D warnings` + = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:10:9 diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 69f2013c1dc..a447fab7b6e 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -8,7 +8,7 @@ error: this if statement can be collapsed 12 | | } | |_____^ | - = note: `-D collapsible-if` implied by `-D warnings` + = note: `-D clippy::collapsible-if` implied by `-D warnings` help: try | 8 | if x == "hello" && y == "world" { diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 829a22c233f..1c9106c0c21 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -4,7 +4,7 @@ error: very complex type used. Consider factoring parts into `type` definitions 9 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D type-complexity` implied by `-D warnings` + = note: `-D clippy::type-complexity` implied by `-D warnings` error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:10:12 diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index db33744c7a9..db6c4d9444f 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -4,7 +4,7 @@ error: Constants have by default a `'static` lifetime 4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` | - = note: `-D const-static-lifetime` implied by `-D warnings` + = note: `-D clippy::const-static-lifetime` implied by `-D warnings` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:8:21 diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index cce63280ce1..febd34603c9 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,384 +1,384 @@ error: this `if` has identical blocks - --> $DIR/copies.rs:29:10 + --> $DIR/copies.rs:31:10 | -29 | else { //~ ERROR same body as `if` block +31 | else { //~ ERROR same body as `if` block | __________^ -30 | | Foo { bar: 42 }; -31 | | 0..10; -32 | | ..; +32 | | Foo { bar: 42 }; +33 | | 0..10; +34 | | ..; ... | -36 | | foo(); -37 | | } +38 | | foo(); +39 | | } | |_____^ | - = note: `-D if-same-then-else` implied by `-D warnings` + = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:20:13 + --> $DIR/copies.rs:22:13 | -20 | if true { +22 | if true { | _____________^ -21 | | Foo { bar: 42 }; -22 | | 0..10; -23 | | ..; +23 | | Foo { bar: 42 }; +24 | | 0..10; +25 | | ..; ... | -27 | | foo(); -28 | | } +29 | | foo(); +30 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:78:14 + --> $DIR/copies.rs:80:14 | -78 | _ => { //~ ERROR match arms have same body +80 | _ => { //~ ERROR match arms have same body | ______________^ -79 | | foo(); -80 | | let mut a = 42 + [23].len() as i32; -81 | | if true { +81 | | foo(); +82 | | let mut a = 42 + [23].len() as i32; +83 | | if true { ... | -85 | | a -86 | | } +87 | | a +88 | | } | |_________^ | - = note: `-D match-same-arms` implied by `-D warnings` + = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:69:15 + --> $DIR/copies.rs:71:15 | -69 | 42 => { +71 | 42 => { | _______________^ -70 | | foo(); -71 | | let mut a = 42 + [23].len() as i32; -72 | | if true { +72 | | foo(); +73 | | let mut a = 42 + [23].len() as i32; +74 | | if true { ... | -76 | | a -77 | | } +78 | | a +79 | | } | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:69:15 + --> $DIR/copies.rs:71:15 | -69 | 42 => { +71 | 42 => { | _______________^ -70 | | foo(); -71 | | let mut a = 42 + [23].len() as i32; -72 | | if true { +72 | | foo(); +73 | | let mut a = 42 + [23].len() as i32; +74 | | if true { ... | -76 | | a -77 | | } +78 | | a +79 | | } | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:92:14 + --> $DIR/copies.rs:94:14 | -92 | _ => 0, //~ ERROR match arms have same body +94 | _ => 0, //~ ERROR match arms have same body | ^ | note: same as this - --> $DIR/copies.rs:90:19 + --> $DIR/copies.rs:92:19 | -90 | Abc::A => 0, +92 | Abc::A => 0, | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:90:19 + --> $DIR/copies.rs:92:19 | -90 | Abc::A => 0, +92 | Abc::A => 0, | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:102:10 + --> $DIR/copies.rs:104:10 | -102 | else { //~ ERROR same body as `if` block +104 | else { //~ ERROR same body as `if` block | __________^ -103 | | 42 -104 | | }; +105 | | 42 +106 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:99:21 + --> $DIR/copies.rs:101:21 | -99 | let _ = if true { +101 | let _ = if true { | _____________________^ -100 | | 42 -101 | | } +102 | | 42 +103 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:116:10 + --> $DIR/copies.rs:118:10 | -116 | else { //~ ERROR same body as `if` block +118 | else { //~ ERROR same body as `if` block | __________^ -117 | | for _ in &[42] { -118 | | let foo: &Option<_> = &Some::(42); -119 | | if true { +119 | | for _ in &[42] { +120 | | let foo: &Option<_> = &Some::(42); +121 | | if true { ... | -124 | | } -125 | | } +126 | | } +127 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:106:13 + --> $DIR/copies.rs:108:13 | -106 | if true { +108 | if true { | _____________^ -107 | | for _ in &[42] { -108 | | let foo: &Option<_> = &Some::(42); -109 | | if true { +109 | | for _ in &[42] { +110 | | let foo: &Option<_> = &Some::(42); +111 | | if true { ... | -114 | | } -115 | | } +116 | | } +117 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:138:10 + --> $DIR/copies.rs:140:10 | -138 | else { //~ ERROR same body as `if` block +140 | else { //~ ERROR same body as `if` block | __________^ -139 | | let bar = if true { -140 | | 42 -141 | | } +141 | | let bar = if true { +142 | | 42 +143 | | } ... | -147 | | bar + 1; -148 | | } +149 | | bar + 1; +150 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:127:13 + --> $DIR/copies.rs:129:13 | -127 | if true { +129 | if true { | _____________^ -128 | | let bar = if true { -129 | | 42 -130 | | } +130 | | let bar = if true { +131 | | 42 +132 | | } ... | -136 | | bar + 1; -137 | | } +138 | | bar + 1; +139 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:173:10 + --> $DIR/copies.rs:175:10 | -173 | else { //~ ERROR same body as `if` block +175 | else { //~ ERROR same body as `if` block | __________^ -174 | | if let Some(a) = Some(42) {} -175 | | } +176 | | if let Some(a) = Some(42) {} +177 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:170:13 + --> $DIR/copies.rs:172:13 | -170 | if true { +172 | if true { | _____________^ -171 | | if let Some(a) = Some(42) {} -172 | | } +173 | | if let Some(a) = Some(42) {} +174 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:180:10 + --> $DIR/copies.rs:182:10 | -180 | else { //~ ERROR same body as `if` block +182 | else { //~ ERROR same body as `if` block | __________^ -181 | | if let (1, .., 3) = (1, 2, 3) {} -182 | | } +183 | | if let (1, .., 3) = (1, 2, 3) {} +184 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:177:13 + --> $DIR/copies.rs:179:13 | -177 | if true { +179 | if true { | _____________^ -178 | | if let (1, .., 3) = (1, 2, 3) {} -179 | | } +180 | | if let (1, .., 3) = (1, 2, 3) {} +181 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:235:15 + --> $DIR/copies.rs:237:15 | -235 | 51 => foo(), //~ ERROR match arms have same body +237 | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:234:15 + --> $DIR/copies.rs:236:15 | -234 | 42 => foo(), +236 | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:234:15 + --> $DIR/copies.rs:236:15 | -234 | 42 => foo(), +236 | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:241:17 + --> $DIR/copies.rs:243:17 | -241 | None => 24, //~ ERROR match arms have same body +243 | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:240:20 + --> $DIR/copies.rs:242:20 | -240 | Some(_) => 24, +242 | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:240:20 + --> $DIR/copies.rs:242:20 | -240 | Some(_) => 24, +242 | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:263:28 + --> $DIR/copies.rs:265:28 | -263 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +265 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:262:28 + --> $DIR/copies.rs:264:28 | -262 | (Some(a), None) => bar(a), +264 | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:262:28 + --> $DIR/copies.rs:264:28 | -262 | (Some(a), None) => bar(a), +264 | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:269:26 + --> $DIR/copies.rs:271:26 | -269 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +271 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:268:26 + --> $DIR/copies.rs:270:26 | -268 | (Some(a), ..) => bar(a), +270 | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:268:26 + --> $DIR/copies.rs:270:26 | -268 | (Some(a), ..) => bar(a), +270 | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:275:20 + --> $DIR/copies.rs:277:20 | -275 | (.., 3) => 42, //~ ERROR match arms have same body +277 | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:274:23 + --> $DIR/copies.rs:276:23 | -274 | (1, .., 3) => 42, +276 | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:274:23 + --> $DIR/copies.rs:276:23 | -274 | (1, .., 3) => 42, +276 | (1, .., 3) => 42, | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:281:12 + --> $DIR/copies.rs:283:12 | -281 | } else { //~ ERROR same body as `if` block +283 | } else { //~ ERROR same body as `if` block | ____________^ -282 | | 0.0 -283 | | }; +284 | | 0.0 +285 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:279:21 + --> $DIR/copies.rs:281:21 | -279 | let _ = if true { +281 | let _ = if true { | _____________________^ -280 | | 0.0 -281 | | } else { //~ ERROR same body as `if` block +282 | | 0.0 +283 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:287:12 + --> $DIR/copies.rs:289:12 | -287 | } else { //~ ERROR same body as `if` block +289 | } else { //~ ERROR same body as `if` block | ____________^ -288 | | -0.0 -289 | | }; +290 | | -0.0 +291 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:285:21 + --> $DIR/copies.rs:287:21 | -285 | let _ = if true { +287 | let _ = if true { | _____________________^ -286 | | -0.0 -287 | | } else { //~ ERROR same body as `if` block +288 | | -0.0 +289 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:307:12 + --> $DIR/copies.rs:309:12 | -307 | } else { //~ ERROR same body as `if` block +309 | } else { //~ ERROR same body as `if` block | ____________^ -308 | | std::f32::NAN -309 | | }; +310 | | std::f32::NAN +311 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:305:21 + --> $DIR/copies.rs:307:21 | -305 | let _ = if true { +307 | let _ = if true { | _____________________^ -306 | | std::f32::NAN -307 | | } else { //~ ERROR same body as `if` block +308 | | std::f32::NAN +309 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:325:10 + --> $DIR/copies.rs:327:10 | -325 | else { //~ ERROR same body as `if` block +327 | else { //~ ERROR same body as `if` block | __________^ -326 | | try!(Ok("foo")); -327 | | } +328 | | try!(Ok("foo")); +329 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:322:13 + --> $DIR/copies.rs:324:13 | -322 | if true { +324 | if true { | _____________^ -323 | | try!(Ok("foo")); -324 | | } +325 | | try!(Ok("foo")); +326 | | } | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:351:13 + --> $DIR/copies.rs:353:13 | -351 | else if b { //~ ERROR ifs same condition +353 | else if b { //~ ERROR ifs same condition | ^ | - = note: `-D ifs-same-cond` implied by `-D warnings` + = note: `-D clippy::ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:349:8 + --> $DIR/copies.rs:351:8 | -349 | if b { +351 | if b { | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:356:13 + --> $DIR/copies.rs:358:13 | -356 | else if a == 1 { //~ ERROR ifs same condition +358 | else if a == 1 { //~ ERROR ifs same condition | ^^^^^^ | note: same as this - --> $DIR/copies.rs:354:8 + --> $DIR/copies.rs:356:8 | -354 | if a == 1 { +356 | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:363:13 + --> $DIR/copies.rs:365:13 | -363 | else if 2*a == 1 { //~ ERROR ifs same condition +365 | else if 2*a == 1 { //~ ERROR ifs same condition | ^^^^^^^^ | note: same as this - --> $DIR/copies.rs:359:8 + --> $DIR/copies.rs:361:8 | -359 | if 2*a == 1 { +361 | if 2*a == 1 { | ^^^^^^^^ error: aborting due to 20 previous errors diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr index f520156b01e..9a06a52d4bb 100644 --- a/tests/ui/copy_iterator.stderr +++ b/tests/ui/copy_iterator.stderr @@ -1,16 +1,16 @@ error: you are implementing `Iterator` on a `Copy` type - --> $DIR/copy_iterator.rs:6:1 + --> $DIR/copy_iterator.rs:8:1 | -6 | / impl Iterator for Countdown { -7 | | type Item = u8; -8 | | -9 | | fn next(&mut self) -> Option { +8 | / impl Iterator for Countdown { +9 | | type Item = u8; +10 | | +11 | | fn next(&mut self) -> Option { ... | -14 | | } -15 | | } +16 | | } +17 | | } | |_^ | - = note: `-D copy-iterator` implied by `-D warnings` + = note: `-D clippy::copy-iterator` implied by `-D warnings` = note: consider implementing `IntoIterator` instead error: aborting due to previous error diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 0e90f696357..2b2b51de6ae 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,15 +1,15 @@ error: you are getting the inner pointer of a temporary `CString` - --> $DIR/cstring.rs:7:5 + --> $DIR/cstring.rs:9:5 | -7 | CString::new("foo").unwrap().as_ptr(); +9 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[deny(temporary_cstring_as_ptr)] on by default + = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/cstring.rs:7:5 + --> $DIR/cstring.rs:9:5 | -7 | CString::new("foo").unwrap().as_ptr(); +9 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index 43676762d6c..ff93f21e3ae 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -10,7 +10,7 @@ error: the function has a cyclomatic complexity of 28 89 | | } | |_^ | - = note: `-D cyclomatic-complexity` implied by `-D warnings` + = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index e671b34393b..f8342f0d9e5 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -10,7 +10,7 @@ error: the function has a cyclomatic complexity of 3 17 | | } | |_^ | - = note: `-D cyclomatic-complexity` implied by `-D warnings` + = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: aborting due to previous error diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index baed3c41180..343936bb7a2 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -4,7 +4,7 @@ error: integer literal has a better hexadecimal representation 18 | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` | - = note: `-D decimal-literal-representation` implied by `-D warnings` + = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:19:9 diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index 8bb4731035a..e3c263e7732 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,51 +1,51 @@ error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:8:22 - | -8 | let s1: String = Default::default(); - | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` - | - = note: `-D default-trait-access` implied by `-D warnings` + --> $DIR/default_trait_access.rs:10:22 + | +10 | let s1: String = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` + | + = note: `-D clippy::default-trait-access` implied by `-D warnings` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:12:22 + --> $DIR/default_trait_access.rs:14:22 | -12 | let s3: String = D2::default(); +14 | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:14:22 + --> $DIR/default_trait_access.rs:16:22 | -14 | let s4: String = std::default::Default::default(); +16 | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:18:22 + --> $DIR/default_trait_access.rs:20:22 | -18 | let s6: String = default::Default::default(); +20 | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling GenericDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:28:46 + --> $DIR/default_trait_access.rs:30:46 | -28 | let s11: GenericDerivedDefault = Default::default(); +30 | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: Calling TupleDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:34:36 + --> $DIR/default_trait_access.rs:36:36 | -34 | let s14: TupleDerivedDefault = Default::default(); +36 | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: Calling ArrayDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:36:36 + --> $DIR/default_trait_access.rs:38:36 | -36 | let s15: ArrayDerivedDefault = Default::default(); +38 | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: Calling TupleStructDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:40:42 + --> $DIR/default_trait_access.rs:42:42 | -40 | let s17: TupleStructDerivedDefault = Default::default(); +42 | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` error: aborting due to 8 previous errors diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index cbe3fe1029d..fa706f22b90 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -4,7 +4,7 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly 17 | #[derive(Hash)] | ^^^^ | - = note: #[deny(derive_hash_xor_eq)] on by default + = note: #[deny(clippy::derive_hash_xor_eq)] on by default note: `PartialEq` implemented here --> $DIR/derive.rs:20:1 | @@ -49,7 +49,7 @@ error: you are implementing `Clone` explicitly on a `Copy` type 43 | | } | |_^ | - = note: `-D expl-impl-clone-on-copy` implied by `-D warnings` + = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:41:1 | diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 0d7b1ca6fd6..8e86a7734dc 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,39 +1,39 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:18:10 + --> $DIR/diverging_sub_expression.rs:20:10 | -18 | b || diverge(); +20 | b || diverge(); | ^^^^^^^^^ | - = note: `-D diverging-sub-expression` implied by `-D warnings` + = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:19:10 + --> $DIR/diverging_sub_expression.rs:21:10 | -19 | b || A.foo(); +21 | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:28:26 + --> $DIR/diverging_sub_expression.rs:30:26 | -28 | 6 => true || return, +30 | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:29:26 + --> $DIR/diverging_sub_expression.rs:31:26 | -29 | 7 => true || continue, +31 | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:32:26 + --> $DIR/diverging_sub_expression.rs:34:26 | -32 | 3 => true || diverge(), +34 | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:37:26 + --> $DIR/diverging_sub_expression.rs:39:26 | -37 | _ => true || break, +39 | _ => true || break, | ^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index de0422e17ed..5322075208c 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -1,48 +1,48 @@ error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:12:16 + --> $DIR/dlist.rs:14:16 | -12 | type Baz = LinkedList; +14 | type Baz = LinkedList; | ^^^^^^^^^^^^^^ | - = note: `-D linkedlist` implied by `-D warnings` + = note: `-D clippy::linkedlist` implied by `-D warnings` = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:13:12 + --> $DIR/dlist.rs:15:12 | -13 | fn foo(LinkedList); +15 | fn foo(LinkedList); | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:14:24 + --> $DIR/dlist.rs:16:24 | -14 | const BAR : Option>; +16 | const BAR : Option>; | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:25:15 + --> $DIR/dlist.rs:27:15 | -25 | fn foo(_: LinkedList) {} +27 | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:28:39 + --> $DIR/dlist.rs:30:39 | -28 | pub fn test(my_favourite_linked_list: LinkedList) { +30 | pub fn test(my_favourite_linked_list: LinkedList) { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:32:29 + --> $DIR/dlist.rs:34:29 | -32 | pub fn test_ret() -> Option> { +34 | pub fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index f38678e89aa..c781f36db7a 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -1,183 +1,183 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation - --> $DIR/doc.rs:1:29 + --> $DIR/doc.rs:3:29 | -1 | //! This file tests for the DOC_MARKDOWN lint +3 | //! This file tests for the DOC_MARKDOWN lint | ^^^^^^^^^^^^ | - = note: `-D doc-markdown` implied by `-D warnings` + = note: `-D clippy::doc-markdown` implied by `-D warnings` error: you should put `foo_bar` between ticks in the documentation - --> $DIR/doc.rs:8:9 - | -8 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) - | ^^^^^^^ + --> $DIR/doc.rs:10:9 + | +10 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) + | ^^^^^^^ error: you should put `foo::bar` between ticks in the documentation - --> $DIR/doc.rs:8:51 - | -8 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) - | ^^^^^^^^ + --> $DIR/doc.rs:10:51 + | +10 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) + | ^^^^^^^^ error: you should put `Foo::some_fun` between ticks in the documentation - --> $DIR/doc.rs:9:84 - | -9 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun - | ^^^^^^^^^^^^^ + --> $DIR/doc.rs:11:84 + | +11 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun + | ^^^^^^^^^^^^^ error: you should put `a::global:path` between ticks in the documentation - --> $DIR/doc.rs:11:15 + --> $DIR/doc.rs:13:15 | -11 | /// Here be ::a::global:path. +13 | /// Here be ::a::global:path. | ^^^^^^^^^^^^^^ error: you should put `NotInCodeBlock` between ticks in the documentation - --> $DIR/doc.rs:12:22 + --> $DIR/doc.rs:14:22 | -12 | /// That's not code ~NotInCodeBlock~. +14 | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:13:5 + --> $DIR/doc.rs:15:5 | -13 | /// be_sure_we_got_to_the_end_of_it +15 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:27:5 + --> $DIR/doc.rs:29:5 | -27 | /// be_sure_we_got_to_the_end_of_it +29 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:34:5 + --> $DIR/doc.rs:36:5 | -34 | /// be_sure_we_got_to_the_end_of_it +36 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:48:5 + --> $DIR/doc.rs:50:5 | -48 | /// be_sure_we_got_to_the_end_of_it +50 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:52:22 + --> $DIR/doc.rs:54:22 | -52 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. +54 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:55:21 + --> $DIR/doc.rs:57:21 | -55 | /// It can also be [inline_link2]. +57 | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:65:5 + --> $DIR/doc.rs:67:5 | -65 | /// be_sure_we_got_to_the_end_of_it +67 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:73:8 + --> $DIR/doc.rs:75:8 | -73 | /// ## CamelCaseThing +75 | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:76:7 + --> $DIR/doc.rs:78:7 | -76 | /// # CamelCaseThing +78 | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:78:22 + --> $DIR/doc.rs:80:22 | -78 | /// Not a title #897 CamelCaseThing +80 | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:79:5 + --> $DIR/doc.rs:81:5 | -79 | /// be_sure_we_got_to_the_end_of_it +81 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:86:5 + --> $DIR/doc.rs:88:5 | -86 | /// be_sure_we_got_to_the_end_of_it +88 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:99:5 - | -99 | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:101:5 + | +101 | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:110:42 + --> $DIR/doc.rs:112:42 | -110 | /** E.g. serialization of an empty list: FooBar +112 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:115:5 + --> $DIR/doc.rs:117:5 | -115 | And BarQuz too. +117 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:116:1 + --> $DIR/doc.rs:118:1 | -116 | be_sure_we_got_to_the_end_of_it +118 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:121:42 + --> $DIR/doc.rs:123:42 | -121 | /** E.g. serialization of an empty list: FooBar +123 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:126:5 + --> $DIR/doc.rs:128:5 | -126 | And BarQuz too. +128 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:127:1 + --> $DIR/doc.rs:129:1 | -127 | be_sure_we_got_to_the_end_of_it +129 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:138:5 + --> $DIR/doc.rs:140:5 | -138 | /// be_sure_we_got_to_the_end_of_it +140 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:165:13 + --> $DIR/doc.rs:167:13 | -165 | /// Not ok: http://www.unicode.org +167 | /// Not ok: http://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:166:13 + --> $DIR/doc.rs:168:13 | -166 | /// Not ok: https://www.unicode.org +168 | /// Not ok: https://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:167:13 + --> $DIR/doc.rs:169:13 | -167 | /// Not ok: http://www.unicode.org/ +169 | /// Not ok: http://www.unicode.org/ | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:168:13 + --> $DIR/doc.rs:170:13 | -168 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +170 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 30 previous errors diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 73dd8d02877..e6a0e976414 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -4,7 +4,7 @@ error: This binary expression can be simplified 4 | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` | - = note: `-D double-comparisons` implied by `-D warnings` + = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified --> $DIR/double_comparison.rs:7:8 diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index fd4da8820a2..02202dbd63c 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -4,7 +4,7 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usual 9 | --x; | ^^^ | - = note: `-D double-neg` implied by `-D warnings` + = note: `-D clippy::double-neg` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index a77b08528c4..a6a29eeb063 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -4,7 +4,7 @@ error: Consider removing unnecessary double parentheses 16 | ((0)) | ^^^^^ | - = note: `-D double-parens` implied by `-D warnings` + = note: `-D clippy::double-parens` implied by `-D warnings` error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:20:14 diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index 3ea7bf9735a..043067fe8af 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -4,7 +4,7 @@ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a c 33 | drop(s1); | ^^^^^^^^ | - = note: `-D drop-copy` implied by `-D warnings` + = note: `-D clippy::drop-copy` implied by `-D warnings` note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:33:10 | @@ -41,7 +41,7 @@ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting 39 | forget(s1); | ^^^^^^^^^^ | - = note: `-D forget-copy` implied by `-D warnings` + = note: `-D clippy::forget-copy` implied by `-D warnings` note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:39:12 | diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 1654fdd2861..227918f5917 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -4,7 +4,7 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dro 12 | drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^ | - = note: `-D drop-ref` implied by `-D warnings` + = note: `-D clippy::drop-ref` implied by `-D warnings` note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:12:10 | @@ -17,7 +17,7 @@ error: calls to `std::mem::forget` with a reference instead of an owned value. F 13 | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | - = note: `-D forget-ref` implied by `-D warnings` + = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:13:12 | diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index c926f57f154..70714534653 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -4,7 +4,7 @@ error: `darth` already exists, having another argument having almost the same na 7 | fn join_the_dark_side(darth: i32, _darth: i32) {} | ^^^^^ | - = note: `-D duplicate-underscore-argument` implied by `-D warnings` + = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index a1aacec3a75..c23b041a80a 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,33 +1,33 @@ error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:8:24 - | -8 | let bad_millis_1 = dur.subsec_micros() / 1_000; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` - | - = note: `-D duration-subsec` implied by `-D warnings` + --> $DIR/duration_subsec.rs:10:24 + | +10 | let bad_millis_1 = dur.subsec_micros() / 1_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` + | + = note: `-D clippy::duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:9:24 - | -9 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` + --> $DIR/duration_subsec.rs:11:24 + | +11 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:14:22 + --> $DIR/duration_subsec.rs:16:22 | -14 | let bad_micros = dur.subsec_nanos() / 1_000; +16 | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:19:13 + --> $DIR/duration_subsec.rs:21:13 | -19 | let _ = (&dur).subsec_nanos() / 1_000; +21 | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:23:13 + --> $DIR/duration_subsec.rs:25:13 | -23 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; +25 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: aborting due to 5 previous errors diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index b8a5031fbcf..a352546ce9f 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,21 +1,21 @@ error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:39:12 + --> $DIR/else_if_without_else.rs:41:12 | -39 | } else if bla2() { //~ ERROR else if without else +41 | } else if bla2() { //~ ERROR else if without else | ____________^ -40 | | println!("else if"); -41 | | } +42 | | println!("else if"); +43 | | } | |_____^ help: add an `else` block here | - = note: `-D else-if-without-else` implied by `-D warnings` + = note: `-D clippy::else-if-without-else` implied by `-D warnings` error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:47:12 + --> $DIR/else_if_without_else.rs:49:12 | -47 | } else if bla3() { //~ ERROR else if without else +49 | } else if bla3() { //~ ERROR else if without else | ____________^ -48 | | println!("else if 2"); -49 | | } +50 | | println!("else if 2"); +51 | | } | |_____^ help: add an `else` block here error: aborting due to 2 previous errors diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index ca377cee822..f198793fed4 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -4,7 +4,7 @@ error: enum with no variants 7 | enum Empty {} | ^^^^^^^^^^^^^ | - = note: `-D empty-enum` implied by `-D warnings` + = note: `-D clippy::empty-enum` implied by `-D warnings` help: consider using the uninhabited type `!` or a wrapper around it --> $DIR/empty_enum.rs:7:1 | diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index 7c9c7b8f349..7bcec54a600 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -7,7 +7,7 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a 8 | | fn with_one_newline_and_comment() { assert!(true) } | |_ | - = note: `-D empty-line-after-outer-attr` implied by `-D warnings` + = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:17:1 diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 09c4a882280..cffe8b23235 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -4,7 +4,7 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` 13 | if !m.contains_key(&k) { m.insert(k, v); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k).or_insert(v)` | - = note: `-D map-entry` implied by `-D warnings` + = note: `-D clippy::map-entry` implied by `-D warnings` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:17:5 diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 2d53618c1b1..bb1d19e41b2 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -4,7 +4,7 @@ error: don't use glob imports for enum variants 6 | use std::cmp::Ordering::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D enum-glob-use` implied by `-D warnings` + = note: `-D clippy::enum-glob-use` implied by `-D warnings` error: don't use glob imports for enum variants --> $DIR/enum_glob_use.rs:12:1 diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index e33e29ec78e..bd083e7e069 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,100 +1,100 @@ error: Variant name ends with the enum's name - --> $DIR/enum_variants.rs:14:5 + --> $DIR/enum_variants.rs:16:5 | -14 | cFoo, +16 | cFoo, | ^^^^ | - = note: `-D enum-variant-names` implied by `-D warnings` + = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:25:5 + --> $DIR/enum_variants.rs:27:5 | -25 | FoodGood, +27 | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:26:5 + --> $DIR/enum_variants.rs:28:5 | -26 | FoodMiddle, +28 | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:27:5 + --> $DIR/enum_variants.rs:29:5 | -27 | FoodBad, +29 | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:24:1 + --> $DIR/enum_variants.rs:26:1 | -24 | / enum Food { -25 | | FoodGood, -26 | | FoodMiddle, -27 | | FoodBad, -28 | | } +26 | / enum Food { +27 | | FoodGood, +28 | | FoodMiddle, +29 | | FoodBad, +30 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:34:1 + --> $DIR/enum_variants.rs:36:1 | -34 | / enum BadCallType { -35 | | CallTypeCall, -36 | | CallTypeCreate, -37 | | CallTypeDestroy, -38 | | } +36 | / enum BadCallType { +37 | | CallTypeCall, +38 | | CallTypeCreate, +39 | | CallTypeDestroy, +40 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:45:1 + --> $DIR/enum_variants.rs:47:1 | -45 | / enum Consts { -46 | | ConstantInt, -47 | | ConstantCake, -48 | | ConstantLie, -49 | | } +47 | / enum Consts { +48 | | ConstantInt, +49 | | ConstantCake, +50 | | ConstantLie, +51 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:78:1 + --> $DIR/enum_variants.rs:80:1 | -78 | / enum Seallll { -79 | | WithOutCake, -80 | | WithOutTea, -81 | | WithOut, -82 | | } +80 | / enum Seallll { +81 | | WithOutCake, +82 | | WithOutTea, +83 | | WithOut, +84 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:84:1 + --> $DIR/enum_variants.rs:86:1 | -84 | / enum NonCaps { -85 | | Prefix的, -86 | | PrefixTea, -87 | | PrefixCake, -88 | | } +86 | / enum NonCaps { +87 | | Prefix的, +88 | | PrefixTea, +89 | | PrefixCake, +90 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:90:1 + --> $DIR/enum_variants.rs:92:1 | -90 | / pub enum PubSeall { -91 | | WithOutCake, -92 | | WithOutTea, -93 | | WithOut, -94 | | } +92 | / pub enum PubSeall { +93 | | WithOutCake, +94 | | WithOutTea, +95 | | WithOut, +96 | | } | |_^ | - = note: `-D pub-enum-variant-names` implied by `-D warnings` + = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` = help: remove the prefixes and use full paths to the variants instead of glob imports error: aborting due to 10 previous errors diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index d6a137c6fe4..cccf4ed030c 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -1,51 +1,51 @@ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:10:5 + --> $DIR/enums_clike.rs:12:5 | -10 | X = 0x1_0000_0000, +12 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ | - = note: `-D enum-clike-unportable-variant` implied by `-D warnings` + = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:17:5 + --> $DIR/enums_clike.rs:19:5 | -17 | X = 0x1_0000_0000, +19 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:20:5 + --> $DIR/enums_clike.rs:22:5 | -20 | A = 0xFFFF_FFFF, +22 | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:27:5 + --> $DIR/enums_clike.rs:29:5 | -27 | Z = 0xFFFF_FFFF, +29 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:28:5 + --> $DIR/enums_clike.rs:30:5 | -28 | A = 0x1_0000_0000, +30 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:30:5 + --> $DIR/enums_clike.rs:32:5 | -30 | C = (std::i32::MIN as isize) - 1, +32 | C = (std::i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:36:5 + --> $DIR/enums_clike.rs:38:5 | -36 | Z = 0xFFFF_FFFF, +38 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:37:5 + --> $DIR/enums_clike.rs:39:5 | -37 | A = 0x1_0000_0000, +39 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index ccf36606208..ad0c8d8ecd7 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -4,7 +4,7 @@ error: this boolean expression can be simplified 37 | true && true; | ^^^^^^^^^^^^ help: try: `true` | - = note: `-D nonminimal-bool` implied by `-D warnings` + = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified --> $DIR/eq_op.rs:39:5 @@ -42,7 +42,7 @@ error: equal expressions as operands to `==` 10 | 1 == 1; | ^^^^^^ | - = note: `-D eq-op` implied by `-D warnings` + = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` --> $DIR/eq_op.rs:11:5 @@ -202,7 +202,7 @@ error: taken reference of right operand | | | help: use the right value directly: `y` | - = note: `-D op-ref` implied by `-D warnings` + = note: `-D clippy::op-ref` implied by `-D warnings` error: equal expressions as operands to `/` --> $DIR/eq_op.rs:97:20 diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 310c41c541b..18486ab4781 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -4,7 +4,7 @@ error: this operation will always return zero. This is likely not the intended o 9 | x * 0; | ^^^^^ | - = note: `-D erasing-op` implied by `-D warnings` + = note: `-D clippy::erasing-op` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:10:5 diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 5dca265c2a4..89543d6af0c 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -4,7 +4,7 @@ error: redundant closure found 7 | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` | - = note: `-D redundant-closure` implied by `-D warnings` + = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found --> $DIR/eta.rs:8:10 @@ -24,7 +24,7 @@ error: this expression borrows a reference that is immediately dereferenced by t 11 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` | - = note: `-D needless-borrow` implied by `-D warnings` + = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found --> $DIR/eta.rs:18:27 diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index 2e01a167c01..3caba829be4 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -4,7 +4,7 @@ error: unsequenced read of a variable 8 | let a = { x = 1; 1 } + x; | ^ | - = note: `-D eval-order-dependence` implied by `-D warnings` + = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order --> $DIR/eval_order_dependence.rs:8:15 | diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 295846e9d7e..bb0546cdcc6 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -4,7 +4,7 @@ error: float has excessive precision 15 | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` | - = note: `-D excessive-precision` implied by `-D warnings` + = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision --> $DIR/excessive_precision.rs:16:26 diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 7a2a0c66f23..fb14120b16d 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,39 +1,39 @@ error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:16:9 + --> $DIR/explicit_write.rs:18:9 | -16 | write!(std::io::stdout(), "test").unwrap(); +18 | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D explicit-write` implied by `-D warnings` + = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:17:9 + --> $DIR/explicit_write.rs:19:9 | -17 | write!(std::io::stderr(), "test").unwrap(); +19 | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead - --> $DIR/explicit_write.rs:18:9 + --> $DIR/explicit_write.rs:20:9 | -18 | writeln!(std::io::stdout(), "test").unwrap(); +20 | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead - --> $DIR/explicit_write.rs:19:9 + --> $DIR/explicit_write.rs:21:9 | -19 | writeln!(std::io::stderr(), "test").unwrap(); +21 | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:20:9 + --> $DIR/explicit_write.rs:22:9 | -20 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); +22 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:21:9 + --> $DIR/explicit_write.rs:23:9 | -21 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); +23 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index c8af77ecab3..4dbc7879d31 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -1,91 +1,91 @@ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:5:1 - | -5 | / impl From for Foo { -6 | | fn from(s: String) -> Self { -7 | | Foo(s.parse().unwrap()) -8 | | } -9 | | } - | |_^ - | + --> $DIR/fallible_impl_from.rs:7:1 + | +7 | / impl From for Foo { +8 | | fn from(s: String) -> Self { +9 | | Foo(s.parse().unwrap()) +10 | | } +11 | | } + | |_^ + | note: lint level defined here - --> $DIR/fallible_impl_from.rs:1:9 - | -1 | #![deny(fallible_impl_from)] - | ^^^^^^^^^^^^^^^^^^ - = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. + --> $DIR/fallible_impl_from.rs:3:9 + | +3 | #![deny(clippy::fallible_impl_from)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:7:13 - | -7 | Foo(s.parse().unwrap()) - | ^^^^^^^^^^^^^^^^^^ + --> $DIR/fallible_impl_from.rs:9:13 + | +9 | Foo(s.parse().unwrap()) + | ^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:28:1 + --> $DIR/fallible_impl_from.rs:30:1 | -28 | / impl From for Invalid { -29 | | fn from(i: usize) -> Invalid { -30 | | if i != 42 { -31 | | panic!(); +30 | / impl From for Invalid { +31 | | fn from(i: usize) -> Invalid { +32 | | if i != 42 { +33 | | panic!(); ... | -34 | | } -35 | | } +36 | | } +37 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:31:13 + --> $DIR/fallible_impl_from.rs:33:13 | -31 | panic!(); +33 | panic!(); | ^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:37:1 + --> $DIR/fallible_impl_from.rs:39:1 | -37 | / impl From> for Invalid { -38 | | fn from(s: Option) -> Invalid { -39 | | let s = s.unwrap(); -40 | | if !s.is_empty() { +39 | / impl From> for Invalid { +40 | | fn from(s: Option) -> Invalid { +41 | | let s = s.unwrap(); +42 | | if !s.is_empty() { ... | -46 | | } -47 | | } +48 | | } +49 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:39:17 + --> $DIR/fallible_impl_from.rs:41:17 | -39 | let s = s.unwrap(); +41 | let s = s.unwrap(); | ^^^^^^^^^^ -40 | if !s.is_empty() { -41 | panic!(42); +42 | if !s.is_empty() { +43 | panic!(42); | ^^^^^^^^^^^ -42 | } else if s.parse::().unwrap() != 42 { +44 | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -43 | panic!("{:?}", s); +45 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:55:1 + --> $DIR/fallible_impl_from.rs:57:1 | -55 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { -56 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -57 | | if s.parse::().ok().unwrap() != 42 { -58 | | panic!("{:?}", s); +57 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +58 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +59 | | if s.parse::().ok().unwrap() != 42 { +60 | | panic!("{:?}", s); ... | -61 | | } -62 | | } +63 | | } +64 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:57:12 + --> $DIR/fallible_impl_from.rs:59:12 | -57 | if s.parse::().ok().unwrap() != 42 { +59 | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -58 | panic!("{:?}", s); +60 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index cec03a47bfd..1fde70601aa 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -7,7 +7,7 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expre 10 | | .map(|x| x * 2) | |_____________________________________________^ | - = note: `-D filter-map` implied by `-D warnings` + = note: `-D clippy::filter-map` implied by `-D warnings` error: called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. --> $DIR/filter_methods.rs:13:21 diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index df404a1eec3..598ebf33668 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -4,7 +4,7 @@ error: strict comparison of f32 or f64 49 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | - = note: `-D float-cmp` implied by `-D warnings` + = note: `-D clippy::float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp.rs:49:5 | diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index 6367ec73c96..14083979511 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -4,7 +4,7 @@ error: strict comparison of f32 or f64 constant 17 | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | - = note: `-D float-cmp-const` implied by `-D warnings` + = note: `-D clippy::float-cmp-const` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:17:5 | diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 582ca84b133..732dc2ab448 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -4,7 +4,7 @@ error: for loop over `option`, which is an `Option`. This is more readably writt 17 | for x in option { | ^^^^^^ | - = note: `-D for-loop-over-option` implied by `-D warnings` + = note: `-D clippy::for-loop-over-option` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. @@ -13,7 +13,7 @@ error: for loop over `result`, which is a `Result`. This is more readably writte 22 | for x in result { | ^^^^^^ | - = note: `-D for-loop-over-result` implied by `-D warnings` + = note: `-D clippy::for-loop-over-result` implied by `-D warnings` = help: consider replacing `for x in result` with `if let Ok(x) = result` error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. @@ -30,7 +30,7 @@ error: you are iterating over `Iterator::next()` which is an Option; this will c 32 | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ | - = note: `-D iter-next-loop` implied by `-D warnings` + = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. --> $DIR/for_loop.rs:37:14 @@ -57,7 +57,7 @@ error: this loop never actually loops 56 | | } | |_____^ | - = note: `-D never-loop` implied by `-D warnings` + = note: `-D clippy::never-loop` implied by `-D warnings` error: this loop never actually loops --> $DIR/for_loop.rs:59:5 @@ -74,7 +74,7 @@ error: the loop variable `i` is only used to index `vec`. 86 | for i in 0..vec.len() { | ^^^^^^^^^^^^ | - = note: `-D needless-range-loop` implied by `-D warnings` + = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | 86 | for in &vec { @@ -206,7 +206,7 @@ error: this range is empty so this for loop will never run 148 | for i in 10..0 { | ^^^^^ | - = note: `-D reverse-range-loop` implied by `-D warnings` + = note: `-D clippy::reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | 148 | for i in (0..10).rev() { @@ -270,7 +270,7 @@ error: it is more idiomatic to loop over references to containers instead of usi 215 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | - = note: `-D explicit-iter-loop` implied by `-D warnings` + = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:217:15 @@ -284,7 +284,7 @@ error: it is more idiomatic to loop over containers instead of using explicit it 220 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | - = note: `-D explicit-into-iter-loop` implied by `-D warnings` + = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:223:15 @@ -358,7 +358,7 @@ error: you are collect()ing an iterator and throwing away the result. Consider u 264 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D unused-collect` implied by `-D warnings` + = note: `-D clippy::unused-collect` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators --> $DIR/for_loop.rs:269:15 @@ -366,7 +366,7 @@ error: the variable `_index` is used as a loop counter. Consider using `for (_in 269 | for _v in &vec { | ^^^^ | - = note: `-D explicit-counter-loop` implied by `-D warnings` + = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators --> $DIR/for_loop.rs:275:15 @@ -380,7 +380,7 @@ error: you seem to want to iterate on a map's values 385 | for (_, v) in &m { | ^^ | - = note: `-D for-kv-map` implied by `-D warnings` + = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method | 385 | for v in m.values() { @@ -432,7 +432,7 @@ error: it looks like you're manually copying between slices 462 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | - = note: `-D manual-memcpy` implied by `-D warnings` + = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:467:14 diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index fa5c740c551..ca6ef905396 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -4,7 +4,7 @@ error: useless use of `format!` 12 | format!("foo"); | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | - = note: `-D useless-format` implied by `-D warnings` + = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` --> $DIR/format.rs:14:5 diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 266de262ea0..d9fee73660c 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -4,7 +4,7 @@ error: this looks like an `else if` but the `else` is missing 15 | } if foo() { | ^ | - = note: `-D suspicious-else-formatting` implied by `-D warnings` + = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing @@ -50,7 +50,7 @@ error: this looks like you are trying to use `.. -= ..`, but you really are doin 71 | a =- 35; | ^^^^ | - = note: `-D suspicious-assignment-formatting` implied by `-D warnings` + = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` @@ -75,7 +75,7 @@ error: possibly missing a comma here 84 | -1, -2, -3 // <= no comma here | ^ | - = note: `-D possible-missing-comma` implied by `-D warnings` + = note: `-D clippy::possible-missing-comma` implied by `-D warnings` = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 0a97748954f..c2f7b76aab4 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -5,7 +5,7 @@ error: this function has too many arguments (8/7) 12 | | } | |_^ | - = note: `-D too-many-arguments` implied by `-D warnings` + = note: `-D clippy::too-many-arguments` implied by `-D warnings` error: this function has too many arguments (8/7) --> $DIR/functions.rs:19:5 @@ -25,7 +25,7 @@ error: this public function dereferences a raw pointer but is not marked `unsafe 37 | println!("{}", unsafe { *p }); | ^ | - = note: `-D not-unsafe-ptr-arg-deref` implied by `-D warnings` + = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:38:35 diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index 5e90f84f1db..869a315c9eb 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -1,39 +1,39 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:6:24 + --> $DIR/fxhash.rs:8:24 | -6 | use std::collections::{HashMap, HashSet}; +8 | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashMap` | - = note: `-D default-hash-types` implied by `-D warnings` + = note: `-D clippy::default-hash-types` implied by `-D warnings` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:6:33 + --> $DIR/fxhash.rs:8:33 | -6 | use std::collections::{HashMap, HashSet}; +8 | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:10:15 + --> $DIR/fxhash.rs:12:15 | -10 | let _map: HashMap = HashMap::default(); +12 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:10:41 + --> $DIR/fxhash.rs:12:41 | -10 | let _map: HashMap = HashMap::default(); +12 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:11:15 + --> $DIR/fxhash.rs:13:15 | -11 | let _set: HashSet = HashSet::default(); +13 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:11:33 + --> $DIR/fxhash.rs:13:33 | -11 | let _set: HashSet = HashSet::default(); +13 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: aborting due to 6 previous errors diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index b5ada862531..63f6603c821 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -4,7 +4,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co 27 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | - = note: `-D get-unwrap` implied by `-D warnings` + = note: `-D clippy::get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:28:17 diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 7083b96e16f..ffcd3649ad6 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,61 +1,61 @@ error: identical conversion - --> $DIR/identity_conversion.rs:4:13 + --> $DIR/identity_conversion.rs:6:13 | -4 | let _ = T::from(val); +6 | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: lint level defined here - --> $DIR/identity_conversion.rs:1:9 + --> $DIR/identity_conversion.rs:3:9 | -1 | #![deny(identity_conversion)] - | ^^^^^^^^^^^^^^^^^^^ +3 | #![deny(clippy::identity_conversion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion - --> $DIR/identity_conversion.rs:5:5 + --> $DIR/identity_conversion.rs:7:5 | -5 | val.into() +7 | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion - --> $DIR/identity_conversion.rs:17:22 + --> $DIR/identity_conversion.rs:19:22 | -17 | let _: i32 = 0i32.into(); +19 | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:38:21 + --> $DIR/identity_conversion.rs:40:21 | -38 | let _: String = "foo".to_string().into(); +40 | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:39:21 + --> $DIR/identity_conversion.rs:41:21 | -39 | let _: String = From::from("foo".to_string()); +41 | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:40:13 + --> $DIR/identity_conversion.rs:42:13 | -40 | let _ = String::from("foo".to_string()); +42 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:41:13 + --> $DIR/identity_conversion.rs:43:13 | -41 | let _ = String::from(format!("A: {:04}", 123)); +43 | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion - --> $DIR/identity_conversion.rs:42:13 + --> $DIR/identity_conversion.rs:44:13 | -42 | let _ = "".lines().into_iter(); +44 | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion - --> $DIR/identity_conversion.rs:43:13 + --> $DIR/identity_conversion.rs:45:13 | -43 | let _ = vec![1, 2, 3].into_iter().into_iter(); +45 | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: aborting due to 9 previous errors diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 45f579ce832..e494250c019 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -4,7 +4,7 @@ error: the operation is ineffective. Consider reducing it to `x` 13 | x + 0; | ^^^^^ | - = note: `-D identity-op` implied by `-D warnings` + = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:14:5 diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index e7bfd0275d8..9046625855c 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -4,7 +4,7 @@ error: redundant pattern matching, consider using `is_ok()` 9 | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` | - = note: `-D if-let-redundant-pattern-matching` implied by `-D warnings` + = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` --> $DIR/if_let_redundant_pattern_matching.rs:11:12 diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index b920ef3b625..9682f6dc18f 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -8,7 +8,7 @@ error: Unnecessary boolean `not` operation 13 | | } | |_____^ | - = note: `-D if-not-else` implied by `-D warnings` + = note: `-D clippy::if-not-else` implied by `-D warnings` = help: remove the `!` and swap the blocks of the if/else error: Unnecessary `!=` operation diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index 95e627cd509..13d4a76558d 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,34 +1,34 @@ error: Multiple implementations of this structure - --> $DIR/impl.rs:10:1 + --> $DIR/impl.rs:12:1 | -10 | / impl MyStruct { -11 | | fn second() {} -12 | | } +12 | / impl MyStruct { +13 | | fn second() {} +14 | | } | |_^ | - = note: `-D multiple-inherent-impl` implied by `-D warnings` + = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` note: First implementation here - --> $DIR/impl.rs:6:1 + --> $DIR/impl.rs:8:1 | -6 | / impl MyStruct { -7 | | fn first() {} -8 | | } +8 | / impl MyStruct { +9 | | fn first() {} +10 | | } | |_^ error: Multiple implementations of this structure - --> $DIR/impl.rs:24:5 + --> $DIR/impl.rs:26:5 | -24 | / impl super::MyStruct { -25 | | fn third() {} -26 | | } +26 | / impl super::MyStruct { +27 | | fn third() {} +28 | | } | |_____^ | note: First implementation here - --> $DIR/impl.rs:6:1 + --> $DIR/impl.rs:8:1 | -6 | / impl MyStruct { -7 | | fn first() {} -8 | | } +8 | / impl MyStruct { +9 | | fn first() {} +10 | | } | |_^ error: aborting due to 2 previous errors diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index f41ce40519f..5bb6f11b2a7 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -4,7 +4,7 @@ error: impl for `HashMap` should be generalized over different hashers 11 | impl Foo for HashMap { | ^^^^^^^^^^^^^ | - = note: `-D implicit-hasher` implied by `-D warnings` + = note: `-D clippy::implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | 11 | impl Foo for HashMap { diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 4d30529d820..51eeca2b864 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -4,7 +4,7 @@ error: digits grouped inconsistently by underscores 7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` | - = note: `-D inconsistent-digit-grouping` implied by `-D warnings` + = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:7:26 diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index ee11dce6d1c..3f09a6516e0 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,268 +1,268 @@ error: indexing may panic. - --> $DIR/indexing_slicing.rs:11:5 + --> $DIR/indexing_slicing.rs:13:5 | -11 | x[index]; +13 | x[index]; | ^^^^^^^^ | - = note: `-D indexing-slicing` implied by `-D warnings` + = note: `-D clippy::indexing-slicing` implied by `-D warnings` = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:12:6 + --> $DIR/indexing_slicing.rs:14:6 | -12 | &x[index..]; +14 | &x[index..]; | ^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:13:6 + --> $DIR/indexing_slicing.rs:15:6 | -13 | &x[..index]; +15 | &x[..index]; | ^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:14:6 + --> $DIR/indexing_slicing.rs:16:6 | -14 | &x[index_from..index_to]; +16 | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:17:6 | -15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +17 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:17:6 | -15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +17 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:18:6 + --> $DIR/indexing_slicing.rs:20:6 | -18 | &x[..=4]; +20 | &x[..=4]; | ^^^^^^^ | - = note: `-D out-of-bounds-indexing` implied by `-D warnings` + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds - --> $DIR/indexing_slicing.rs:19:6 + --> $DIR/indexing_slicing.rs:21:6 | -19 | &x[1..5]; +21 | &x[1..5]; | ^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:20:6 + --> $DIR/indexing_slicing.rs:22:6 | -20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +22 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:20:6 + --> $DIR/indexing_slicing.rs:22:6 | -20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +22 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:21:6 + --> $DIR/indexing_slicing.rs:23:6 | -21 | &x[5..]; +23 | &x[5..]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:22:6 + --> $DIR/indexing_slicing.rs:24:6 | -22 | &x[..5]; +24 | &x[..5]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:23:6 + --> $DIR/indexing_slicing.rs:25:6 | -23 | &x[5..].iter().map(|x| 2 * x).collect::>(); +25 | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:24:6 + --> $DIR/indexing_slicing.rs:26:6 | -24 | &x[0..=4]; +26 | &x[0..=4]; | ^^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:25:6 + --> $DIR/indexing_slicing.rs:27:6 | -25 | &x[0..][..3]; +27 | &x[0..][..3]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:26:6 + --> $DIR/indexing_slicing.rs:28:6 | -26 | &x[1..][..5]; +28 | &x[1..][..5]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:39:5 + --> $DIR/indexing_slicing.rs:41:5 | -39 | y[0]; +41 | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:40:6 + --> $DIR/indexing_slicing.rs:42:6 | -40 | &y[1..2]; +42 | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:41:6 + --> $DIR/indexing_slicing.rs:43:6 | -41 | &y[0..=4]; +43 | &y[0..=4]; | ^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:42:6 + --> $DIR/indexing_slicing.rs:44:6 | -42 | &y[..=4]; +44 | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:48:6 + --> $DIR/indexing_slicing.rs:50:6 | -48 | &empty[1..5]; +50 | &empty[1..5]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:49:6 + --> $DIR/indexing_slicing.rs:51:6 | -49 | &empty[0..=4]; +51 | &empty[0..=4]; | ^^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:50:6 + --> $DIR/indexing_slicing.rs:52:6 | -50 | &empty[..=4]; +52 | &empty[..=4]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:51:6 + --> $DIR/indexing_slicing.rs:53:6 | -51 | &empty[1..]; +53 | &empty[1..]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:52:6 + --> $DIR/indexing_slicing.rs:54:6 | -52 | &empty[..4]; +54 | &empty[..4]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:53:6 + --> $DIR/indexing_slicing.rs:55:6 | -53 | &empty[0..=0]; +55 | &empty[0..=0]; | ^^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:54:6 + --> $DIR/indexing_slicing.rs:56:6 | -54 | &empty[..=0]; +56 | &empty[..=0]; | ^^^^^^^^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:62:5 + --> $DIR/indexing_slicing.rs:64:5 | -62 | v[0]; +64 | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:63:5 + --> $DIR/indexing_slicing.rs:65:5 | -63 | v[10]; +65 | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:64:5 + --> $DIR/indexing_slicing.rs:66:5 | -64 | v[1 << 3]; +66 | v[1 << 3]; | ^^^^^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:65:6 + --> $DIR/indexing_slicing.rs:67:6 | -65 | &v[10..100]; +67 | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:66:6 + --> $DIR/indexing_slicing.rs:68:6 | -66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +68 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:66:6 + --> $DIR/indexing_slicing.rs:68:6 | -66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +68 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:67:6 + --> $DIR/indexing_slicing.rs:69:6 | -67 | &v[10..]; +69 | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:68:6 + --> $DIR/indexing_slicing.rs:70:6 | -68 | &v[..100]; +70 | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:80:5 + --> $DIR/indexing_slicing.rs:82:5 | -80 | v[N]; +82 | v[N]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:81:5 + --> $DIR/indexing_slicing.rs:83:5 | -81 | v[M]; +83 | v[M]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index 8ee73bbfde8..6e26741fc87 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,27 +1,27 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:16:5 + --> $DIR/infallible_destructuring_match.rs:18:5 | -16 | / let data = match wrapper { -17 | | SingleVariantEnum::Variant(i) => i, -18 | | }; +18 | / let data = match wrapper { +19 | | SingleVariantEnum::Variant(i) => i, +20 | | }; | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` | - = note: `-D infallible-destructuring-match` implied by `-D warnings` + = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:37:5 + --> $DIR/infallible_destructuring_match.rs:39:5 | -37 | / let data = match wrapper { -38 | | TupleStruct(i) => i, -39 | | }; +39 | / let data = match wrapper { +40 | | TupleStruct(i) => i, +41 | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:58:5 + --> $DIR/infallible_destructuring_match.rs:60:5 | -58 | / let data = match wrapper { -59 | | Ok(i) => i, -60 | | }; +60 | / let data = match wrapper { +61 | | Ok(i) => i, +62 | | }; | |______^ help: try this: `let Ok(data) = wrapper;` error: aborting due to 3 previous errors diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index f79db778488..c3d67bdfde3 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -4,7 +4,7 @@ error: you are collect()ing an iterator and throwing away the result. Consider u 10 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D unused-collect` implied by `-D warnings` + = note: `-D clippy::unused-collect` implied by `-D warnings` error: infinite iteration detected --> $DIR/infinite_iter.rs:10:5 @@ -15,8 +15,8 @@ error: infinite iteration detected note: lint level defined here --> $DIR/infinite_iter.rs:8:8 | -8 | #[deny(infinite_iter)] - | ^^^^^^^^^^^^^ +8 | #[deny(clippy::infinite_iter)] + | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected --> $DIR/infinite_iter.rs:11:5 @@ -57,8 +57,8 @@ error: possible infinite iteration detected note: lint level defined here --> $DIR/infinite_iter.rs:22:8 | -22 | #[deny(maybe_infinite_iter)] - | ^^^^^^^^^^^^^^^^^^^ +22 | #[deny(clippy::maybe_infinite_iter)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:25:5 diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 26ec9582fb4..edbe4937425 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,57 +1,57 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:14:11 + --> $DIR/infinite_loop.rs:16:11 | -14 | while y < 10 { +16 | while y < 10 { | ^^^^^^ | - = note: #[deny(while_immutable_condition)] on by default + = note: #[deny(clippy::while_immutable_condition)] on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:19:11 + --> $DIR/infinite_loop.rs:21:11 | -19 | while y < 10 && x < 3 { +21 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:26:11 + --> $DIR/infinite_loop.rs:28:11 | -26 | while !cond { +28 | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:70:11 + --> $DIR/infinite_loop.rs:72:11 | -70 | while i < 3 { +72 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:75:11 + --> $DIR/infinite_loop.rs:77:11 | -75 | while i < 3 && j > 0 { +77 | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:79:11 + --> $DIR/infinite_loop.rs:81:11 | -79 | while i < 3 { +81 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:94:11 + --> $DIR/infinite_loop.rs:96:11 | -94 | while i < 3 { +96 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:99:11 - | -99 | while i < 3 { - | ^^^^^ + --> $DIR/infinite_loop.rs:101:11 + | +101 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:162:15 + --> $DIR/infinite_loop.rs:164:15 | -162 | while self.count < n { +164 | while self.count < n { | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 2b466b68610..a9a52b19053 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -6,7 +6,7 @@ error: use of `#[inline]` on trait method `default_inline` which has no body 9 | | fn default_inline(); | |____- help: remove | - = note: `-D inline-fn-without-body` implied by `-D warnings` + = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body --> $DIR/inline_fn_without_body.rs:11:5 diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index deecaffa1cf..12d7000dcfa 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -4,7 +4,7 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` 10 | x >= y + 1; | ^^^^^^^^^^ | - = note: `-D int-plus-one` implied by `-D warnings` + = note: `-D clippy::int-plus-one` implied by `-D warnings` help: change `>= y + 1` to `> y` as shown | 10 | x > y; diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index f8420738526..1ca825dd94c 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -4,7 +4,7 @@ error: reference to zeroed memory 27 | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | - = note: #[deny(invalid_ref)] on by default + = note: #[deny(clippy::invalid_ref)] on by default = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index eb46802899e..ce6d1dfa1ae 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -4,7 +4,7 @@ error: because of the numeric bounds on `u8` prior to casting, this expression i 16 | (u8 as u32) > 300; | ^^^^^^^^^^^^^^^^^ | - = note: `-D invalid-upcast-comparisons` implied by `-D warnings` + = note: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:17:5 diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr index 4b82a0a7565..fe2d9d45b77 100644 --- a/tests/ui/issue_2356.stderr +++ b/tests/ui/issue_2356.stderr @@ -1,14 +1,14 @@ error: this loop could be written as a `for` loop - --> $DIR/issue_2356.rs:15:29 + --> $DIR/issue_2356.rs:17:29 | -15 | while let Some(e) = it.next() { +17 | while let Some(e) = it.next() { | ^^^^^^^^^ help: try: `for e in it { .. }` | note: lint level defined here - --> $DIR/issue_2356.rs:1:9 + --> $DIR/issue_2356.rs:3:9 | -1 | #![deny(while_let_on_iterator)] - | ^^^^^^^^^^^^^^^^^^^^^ +3 | #![deny(clippy::while_let_on_iterator)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index ec1296caf83..6d20899b5ec 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -4,7 +4,7 @@ error: adding items after statements is confusing, since items exist from the st 12 | fn foo() { println!("foo"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D items-after-statements` implied by `-D warnings` + = note: `-D clippy::items-after-statements` implied by `-D warnings` error: adding items after statements is confusing, since items exist from the start of the scope --> $DIR/item_after_statement.rs:17:5 diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index f2e6a62d13c..b322ded9cfb 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -4,7 +4,7 @@ error: digit groups should be smaller 7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | - = note: `-D large-digit-groups` implied by `-D warnings` + = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:7:31 diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 5e938337bc0..af42f905458 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -4,7 +4,7 @@ error: large size difference between variants 10 | B([i32; 8000]), | ^^^^^^^^^^^^^^ | - = note: `-D large-enum-variant` implied by `-D warnings` + = note: `-D clippy::large-enum-variant` implied by `-D warnings` help: consider boxing the large fields to reduce the total size of the enum | 10 | B(Box<[i32; 8000]>), diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index a04185bc63f..49e365e6c21 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,139 +1,139 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:6:1 + --> $DIR/len_zero.rs:8:1 | -6 | / impl PubOne { -7 | | pub fn len(self: &Self) -> isize { -8 | | 1 -9 | | } -10 | | } +8 | / impl PubOne { +9 | | pub fn len(self: &Self) -> isize { +10 | | 1 +11 | | } +12 | | } | |_^ | - = note: `-D len-without-is-empty` implied by `-D warnings` + = note: `-D clippy::len-without-is-empty` implied by `-D warnings` error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:55:1 + --> $DIR/len_zero.rs:57:1 | -55 | / pub trait PubTraitsToo { -56 | | fn len(self: &Self) -> isize; -57 | | } +57 | / pub trait PubTraitsToo { +58 | | fn len(self: &Self) -> isize; +59 | | } | |_^ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:89:1 + --> $DIR/len_zero.rs:91:1 | -89 | / impl HasIsEmpty { -90 | | pub fn len(self: &Self) -> isize { -91 | | 1 -92 | | } +91 | / impl HasIsEmpty { +92 | | pub fn len(self: &Self) -> isize { +93 | | 1 +94 | | } ... | -96 | | } -97 | | } +98 | | } +99 | | } | |_^ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:118:1 + --> $DIR/len_zero.rs:120:1 | -118 | / impl HasWrongIsEmpty { -119 | | pub fn len(self: &Self) -> isize { -120 | | 1 -121 | | } +120 | / impl HasWrongIsEmpty { +121 | | pub fn len(self: &Self) -> isize { +122 | | 1 +123 | | } ... | -125 | | } -126 | | } +127 | | } +128 | | } | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:139:8 + --> $DIR/len_zero.rs:141:8 | -139 | if x.len() == 0 { +141 | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `x.is_empty()` | - = note: `-D len-zero` implied by `-D warnings` + = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:143:8 + --> $DIR/len_zero.rs:145:8 | -143 | if "".len() == 0 {} +145 | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is more concise: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:158:8 + --> $DIR/len_zero.rs:160:8 | -158 | if has_is_empty.len() == 0 { +160 | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:161:8 + --> $DIR/len_zero.rs:163:8 | -161 | if has_is_empty.len() != 0 { +163 | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:164:8 + --> $DIR/len_zero.rs:166:8 | -164 | if has_is_empty.len() > 0 { +166 | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:167:8 + --> $DIR/len_zero.rs:169:8 | -167 | if has_is_empty.len() < 1 { +169 | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:170:8 + --> $DIR/len_zero.rs:172:8 | -170 | if has_is_empty.len() >= 1 { +172 | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:181:8 + --> $DIR/len_zero.rs:183:8 | -181 | if 0 == has_is_empty.len() { +183 | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:184:8 + --> $DIR/len_zero.rs:186:8 | -184 | if 0 != has_is_empty.len() { +186 | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:187:8 + --> $DIR/len_zero.rs:189:8 | -187 | if 0 < has_is_empty.len() { +189 | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:190:8 + --> $DIR/len_zero.rs:192:8 | -190 | if 1 <= has_is_empty.len() { +192 | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:193:8 + --> $DIR/len_zero.rs:195:8 | -193 | if 1 > has_is_empty.len() { +195 | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:207:8 + --> $DIR/len_zero.rs:209:8 | -207 | if with_is_empty.len() == 0 { +209 | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:220:8 + --> $DIR/len_zero.rs:222:8 | -220 | if b.len() != 0 {} +222 | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:226:1 + --> $DIR/len_zero.rs:228:1 | -226 | / pub trait DependsOnFoo: Foo { -227 | | fn len(&mut self) -> usize; -228 | | } +228 | / pub trait DependsOnFoo: Foo { +229 | | fn len(&mut self) -> usize; +230 | | } | |_^ error: aborting due to 19 previous errors diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index b912373f95c..7b4c78003ab 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -7,7 +7,7 @@ error: `if _ { .. } else { .. }` is an expression 60 | | } | |_____^ help: it is more idiomatic to write: `let foo = if f() { 42 } else { 0 };` | - = note: `-D useless-let-if-seq` implied by `-D warnings` + = note: `-D clippy::useless-let-if-seq` implied by `-D warnings` = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index 459b2eafa26..dad628bc912 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -4,7 +4,7 @@ error: returning the result of a let binding from a block. Consider returning th 10 | x | ^ | - = note: `-D let-and-return` implied by `-D warnings` + = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned --> $DIR/let_return.rs:9:13 | diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index da579ec80f3..f6f5d3f7dcc 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -4,7 +4,7 @@ error: this let-binding has unit value. Consider omitting `let _x =` 14 | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D let-unit-value` implied by `-D warnings` + = note: `-D clippy::let-unit-value` implied by `-D warnings` error: this let-binding has unit value. Consider omitting `let _a =` --> $DIR/let_unit.rs:18:9 diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index b69438af9f8..42fb01b7580 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -4,7 +4,7 @@ error: explicit lifetimes given in parameter types where they could be elided 7 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D needless-lifetimes` implied by `-D warnings` + = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided --> $DIR/lifetimes.rs:9:1 diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 6f6ea75df10..40399e498ab 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,124 +1,124 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:12:17 + --> $DIR/literals.rs:14:17 | -12 | let fail1 = 0xabCD; +14 | let fail1 = 0xabCD; | ^^^^^^ | - = note: `-D mixed-case-hex-literals` implied by `-D warnings` + = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:13:17 + --> $DIR/literals.rs:15:17 | -13 | let fail2 = 0xabCD_u32; +15 | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:14:17 + --> $DIR/literals.rs:16:17 | -14 | let fail2 = 0xabCD_isize; +16 | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:15:27 + --> $DIR/literals.rs:17:27 | -15 | let fail_multi_zero = 000_123usize; +17 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | - = note: `-D unseparated-literal-suffix` implied by `-D warnings` + = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:15:27 + --> $DIR/literals.rs:17:27 | -15 | let fail_multi_zero = 000_123usize; +17 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | - = note: `-D zero-prefixed-literal` implied by `-D warnings` + = note: `-D clippy::zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -15 | let fail_multi_zero = 123usize; +17 | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -15 | let fail_multi_zero = 0o123usize; +17 | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:20:17 + --> $DIR/literals.rs:22:17 | -20 | let fail3 = 1234i32; +22 | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:21:17 + --> $DIR/literals.rs:23:17 | -21 | let fail4 = 1234u32; +23 | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:22:17 + --> $DIR/literals.rs:24:17 | -22 | let fail5 = 1234isize; +24 | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:23:17 + --> $DIR/literals.rs:25:17 | -23 | let fail6 = 1234usize; +25 | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:24:17 + --> $DIR/literals.rs:26:17 | -24 | let fail7 = 1.5f32; +26 | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:28:17 + --> $DIR/literals.rs:30:17 | -28 | let fail8 = 0123; +30 | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -28 | let fail8 = 123; +30 | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -28 | let fail8 = 0o123; +30 | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:39:17 + --> $DIR/literals.rs:41:17 | -39 | let fail9 = 0xabcdef; +41 | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | - = note: `-D unreadable-literal` implied by `-D warnings` + = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:40:18 + --> $DIR/literals.rs:42:18 | -40 | let fail10 = 0xBAFEBAFE; +42 | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:41:18 + --> $DIR/literals.rs:43:18 | -41 | let fail11 = 0xabcdeff; +43 | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/literals.rs:42:18 + --> $DIR/literals.rs:44:18 | -42 | let fail12 = 0xabcabcabcabcabcabc; +44 | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller - --> $DIR/literals.rs:43:18 + --> $DIR/literals.rs:45:18 | -43 | let fail13 = 0x1_23456_78901_usize; +45 | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | - = note: `-D large-digit-groups` implied by `-D warnings` + = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: aborting due to 16 previous errors diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index c29f3791851..afad65b0071 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -4,7 +4,7 @@ error: you seem to be using .map() to clone the contents of an iterator, conside 12 | x.iter().map(|y| y.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D map-clone` implied by `-D warnings` + = note: `-D clippy::map-clone` implied by `-D warnings` = help: try x.iter().cloned() diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 89378f438b0..7ef6f714f3a 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -4,7 +4,7 @@ error: this boolean expression can be simplified 25 | match test && test { | ^^^^^^^^^^^^ help: try: `test` | - = note: `-D nonminimal-bool` implied by `-D warnings` + = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:4:5 @@ -15,7 +15,7 @@ error: you seem to be trying to match on a boolean expression 7 | | }; | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` | - = note: `-D match-bool` implied by `-D warnings` + = note: `-D clippy::match-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:10:5 @@ -59,7 +59,7 @@ error: equal expressions as operands to `&&` 25 | match test && test { | ^^^^^^^^^^^^ | - = note: #[deny(eq_op)] on by default + = note: #[deny(clippy::eq_op)] on by default error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:30:5 diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 61c13056cca..6f1a067382a 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -7,7 +7,7 @@ error: you seem to be trying to use match for destructuring a single pattern. Co 24 | | } | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` | - = note: `-D single-match-else` implied by `-D warnings` + = note: `-D clippy::single-match-else` implied by `-D warnings` error: you don't need to add `&` to all patterns --> $DIR/matches.rs:30:9 @@ -18,7 +18,7 @@ error: you don't need to add `&` to all patterns 33 | | } | |_________^ | - = note: `-D match-ref-pats` implied by `-D warnings` + = note: `-D clippy::match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | 30 | match *v { @@ -94,7 +94,7 @@ error: some ranges overlap 71 | 0 ... 10 => println!("0 ... 10"), | ^^^^^^^^ | - = note: `-D match-overlapping-arm` implied by `-D warnings` + = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this --> $DIR/matches.rs:72:9 | @@ -155,7 +155,7 @@ error: Err(_) will match all errors, maybe not a good idea 132 | Err(_) => panic!("err") | ^^^^^^ | - = note: `-D match-wild-err-arm` implied by `-D warnings` + = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies @@ -164,7 +164,7 @@ error: this `match` has identical arm bodies 131 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | - = note: `-D match-same-arms` implied by `-D warnings` + = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this --> $DIR/matches.rs:130:18 | @@ -347,7 +347,7 @@ error: use as_ref() instead 215 | | }; | |_____^ help: try this: `owned.as_ref()` | - = note: `-D match-as-ref` implied by `-D warnings` + = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead --> $DIR/matches.rs:218:39 diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 6e7a44694e1..1f43d9f360a 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -4,7 +4,7 @@ error: usage of mem::forget on Drop type 18 | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D mem-forget` implied by `-D warnings` + = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of mem::forget on Drop type --> $DIR/mem_forget.rs:21:5 diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index bf529ce9465..3189f375647 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -4,7 +4,7 @@ error: defining a method called `add` on this type; consider implementing the `s 21 | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D should-implement-trait` implied by `-D warnings` + = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/methods.rs:32:17 @@ -12,7 +12,7 @@ error: methods called `into_*` usually take self by value; consider choosing a l 32 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | - = note: `-D wrong-self-convention` implied by `-D warnings` + = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name --> $DIR/methods.rs:34:21 @@ -32,7 +32,7 @@ error: methods called `new` usually return `Self` 36 | fn new(self) {} | ^^^^^^^^^^^^^^^ | - = note: `-D new-ret-no-self` implied by `-D warnings` + = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead --> $DIR/methods.rs:104:13 @@ -43,7 +43,7 @@ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more di 106 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | - = note: `-D option-map-unwrap-or` implied by `-D warnings` + = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead @@ -104,7 +104,7 @@ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done mo 133 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | - = note: `-D option-map-unwrap-or-else` implied by `-D warnings` + = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead @@ -133,7 +133,7 @@ error: called `map_or(None, f)` on an Option value. This can be done more direct 148 | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | - = note: `-D option-map-or-none` implied by `-D warnings` + = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead --> $DIR/methods.rs:150:13 @@ -160,7 +160,7 @@ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done mor 165 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | |_____________________________________^ | - = note: `-D result-map-unwrap-or-else` implied by `-D warnings` + = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead @@ -189,7 +189,7 @@ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expre 234 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D filter-next` implied by `-D warnings` + = note: `-D clippy::filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. @@ -208,7 +208,7 @@ error: called `is_some()` after searching an `Iterator` with find. This is more 252 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D search-is-some` implied by `-D warnings` + = note: `-D clippy::search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. @@ -263,7 +263,7 @@ error: use of `unwrap_or` followed by a function call 308 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` | - = note: `-D or-fun-call` implied by `-D warnings` + = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` --> $DIR/methods.rs:311:5 @@ -337,7 +337,7 @@ error: `error_code` is shadowed by `123_i32` 377 | let error_code = 123_i32; | ^^^^^^^^^^ | - = note: `-D shadow-unrelated` implied by `-D warnings` + = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here --> $DIR/methods.rs:377:22 | @@ -355,7 +355,7 @@ error: use of `expect` followed by a function call 366 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | - = note: `-D expect-fun-call` implied by `-D warnings` + = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call --> $DIR/methods.rs:369:26 @@ -381,7 +381,7 @@ error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more 406 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D iter-nth` implied by `-D warnings` + = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable --> $DIR/methods.rs:407:26 @@ -425,7 +425,7 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed 432 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D iter-skip-next` implied by `-D warnings` + = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` --> $DIR/methods.rs:433:13 @@ -451,7 +451,7 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca 444 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | - = note: `-D option-unwrap-used` implied by `-D warnings` + = note: `-D clippy::option-unwrap-used` implied by `-D warnings` error: aborting due to 56 previous errors diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index b8ea183fcc9..e89542a2ddc 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -4,7 +4,7 @@ error: this min/max combination leads to constant result 15 | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ | - = note: `-D min-max` implied by `-D warnings` + = note: `-D clippy::min-max` implied by `-D warnings` error: this min/max combination leads to constant result --> $DIR/min_max.rs:16:5 diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index 54834f9021c..ebc4c5aca43 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -1,267 +1,267 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:26:1 + --> $DIR/missing-doc.rs:28:1 | -26 | type Typedef = String; +28 | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D missing-docs-in-private-items` implied by `-D warnings` + = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:27:1 + --> $DIR/missing-doc.rs:29:1 | -27 | pub type PubTypedef = String; +29 | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:29:1 + --> $DIR/missing-doc.rs:31:1 | -29 | / struct Foo { -30 | | a: isize, -31 | | b: isize, -32 | | } +31 | / struct Foo { +32 | | a: isize, +33 | | b: isize, +34 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:30:5 + --> $DIR/missing-doc.rs:32:5 | -30 | a: isize, +32 | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:31:5 + --> $DIR/missing-doc.rs:33:5 | -31 | b: isize, +33 | b: isize, | ^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:34:1 + --> $DIR/missing-doc.rs:36:1 | -34 | / pub struct PubFoo { -35 | | pub a: isize, -36 | | b: isize, -37 | | } +36 | / pub struct PubFoo { +37 | | pub a: isize, +38 | | b: isize, +39 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:35:5 + --> $DIR/missing-doc.rs:37:5 | -35 | pub a: isize, +37 | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:36:5 + --> $DIR/missing-doc.rs:38:5 | -36 | b: isize, +38 | b: isize, | ^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:45:1 + --> $DIR/missing-doc.rs:47:1 | -45 | mod module_no_dox {} +47 | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:46:1 + --> $DIR/missing-doc.rs:48:1 | -46 | pub mod pub_module_no_dox {} +48 | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:50:1 + --> $DIR/missing-doc.rs:52:1 | -50 | pub fn foo2() {} +52 | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:51:1 + --> $DIR/missing-doc.rs:53:1 | -51 | fn foo3() {} +53 | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for a trait - --> $DIR/missing-doc.rs:68:1 + --> $DIR/missing-doc.rs:70:1 | -68 | / pub trait C { -69 | | fn foo(&self); -70 | | fn foo_with_impl(&self) {} -71 | | } +70 | / pub trait C { +71 | | fn foo(&self); +72 | | fn foo_with_impl(&self) {} +73 | | } | |_^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:69:5 + --> $DIR/missing-doc.rs:71:5 | -69 | fn foo(&self); +71 | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:70:5 + --> $DIR/missing-doc.rs:72:5 | -70 | fn foo_with_impl(&self) {} +72 | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:80:5 + --> $DIR/missing-doc.rs:82:5 | -80 | type AssociatedType; +82 | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:81:5 + --> $DIR/missing-doc.rs:83:5 | -81 | type AssociatedTypeDef = Self; +83 | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:92:5 + --> $DIR/missing-doc.rs:94:5 | -92 | pub fn foo() {} +94 | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:93:5 + --> $DIR/missing-doc.rs:95:5 | -93 | fn bar() {} +95 | fn bar() {} | ^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:97:5 + --> $DIR/missing-doc.rs:99:5 | -97 | pub fn foo() {} +99 | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:100:5 + --> $DIR/missing-doc.rs:102:5 | -100 | fn foo2() {} +102 | fn foo2() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:126:1 + --> $DIR/missing-doc.rs:128:1 | -126 | / enum Baz { -127 | | BazA { -128 | | a: isize, -129 | | b: isize -130 | | }, -131 | | BarB -132 | | } +128 | / enum Baz { +129 | | BazA { +130 | | a: isize, +131 | | b: isize +132 | | }, +133 | | BarB +134 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:127:5 + --> $DIR/missing-doc.rs:129:5 | -127 | / BazA { -128 | | a: isize, -129 | | b: isize -130 | | }, +129 | / BazA { +130 | | a: isize, +131 | | b: isize +132 | | }, | |_____^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:128:9 + --> $DIR/missing-doc.rs:130:9 | -128 | a: isize, +130 | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:129:9 + --> $DIR/missing-doc.rs:131:9 | -129 | b: isize +131 | b: isize | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:131:5 + --> $DIR/missing-doc.rs:133:5 | -131 | BarB +133 | BarB | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:134:1 + --> $DIR/missing-doc.rs:136:1 | -134 | / pub enum PubBaz { -135 | | PubBazA { -136 | | a: isize, -137 | | }, -138 | | } +136 | / pub enum PubBaz { +137 | | PubBazA { +138 | | a: isize, +139 | | }, +140 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:135:5 + --> $DIR/missing-doc.rs:137:5 | -135 | / PubBazA { -136 | | a: isize, -137 | | }, +137 | / PubBazA { +138 | | a: isize, +139 | | }, | |_____^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:136:9 + --> $DIR/missing-doc.rs:138:9 | -136 | a: isize, +138 | a: isize, | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:160:1 + --> $DIR/missing-doc.rs:162:1 | -160 | const FOO: u32 = 0; +162 | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:167:1 + --> $DIR/missing-doc.rs:169:1 | -167 | pub const FOO4: u32 = 0; +169 | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:170:1 + --> $DIR/missing-doc.rs:172:1 | -170 | static BAR: u32 = 0; +172 | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:177:1 + --> $DIR/missing-doc.rs:179:1 | -177 | pub static BAR4: u32 = 0; +179 | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:180:1 + --> $DIR/missing-doc.rs:182:1 | -180 | / mod internal_impl { -181 | | /// dox -182 | | pub fn documented() {} -183 | | pub fn undocumented1() {} +182 | / mod internal_impl { +183 | | /// dox +184 | | pub fn documented() {} +185 | | pub fn undocumented1() {} ... | -192 | | } -193 | | } +194 | | } +195 | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:183:5 + --> $DIR/missing-doc.rs:185:5 | -183 | pub fn undocumented1() {} +185 | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:184:5 + --> $DIR/missing-doc.rs:186:5 | -184 | pub fn undocumented2() {} +186 | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:185:5 + --> $DIR/missing-doc.rs:187:5 | -185 | fn undocumented3() {} +187 | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:190:9 + --> $DIR/missing-doc.rs:192:9 | -190 | pub fn also_undocumented1() {} +192 | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:191:9 + --> $DIR/missing-doc.rs:193:9 | -191 | fn also_undocumented2() {} +193 | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 39 previous errors diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index fe343742708..3609c9101b7 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -1,39 +1,39 @@ error: missing `#[inline]` for a function - --> $DIR/missing_inline.rs:31:1 + --> $DIR/missing_inline.rs:33:1 | -31 | pub fn pub_foo() {} // missing #[inline] +33 | pub fn pub_foo() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^ | - = note: `-D missing-inline-in-public-items` implied by `-D warnings` + = note: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` error: missing `#[inline]` for a default trait method - --> $DIR/missing_inline.rs:46:5 + --> $DIR/missing_inline.rs:48:5 | -46 | fn PubBar_b() {} // missing #[inline] +48 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:59:5 + --> $DIR/missing_inline.rs:61:5 | -59 | fn PubBar_a() {} // missing #[inline] +61 | fn PubBar_a() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:60:5 + --> $DIR/missing_inline.rs:62:5 | -60 | fn PubBar_b() {} // missing #[inline] +62 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:61:5 + --> $DIR/missing_inline.rs:63:5 | -61 | fn PubBar_c() {} // missing #[inline] +63 | fn PubBar_c() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:71:5 + --> $DIR/missing_inline.rs:73:5 | -71 | pub fn PubFooImpl() {} // missing #[inline] +73 | pub fn PubFooImpl() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index c9d3319db1b..43f9666f78d 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -6,7 +6,7 @@ error: module has the same name as its containing module 9 | | } | |_________^ | - = note: `-D module-inception` implied by `-D warnings` + = note: `-D clippy::module-inception` implied by `-D warnings` error: module has the same name as its containing module --> $DIR/module_inception.rs:12:5 diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index ccfca7154e0..5d42c3e0a29 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -4,7 +4,7 @@ error: any number modulo 1 will be 0 7 | 10 % 1; | ^^^^^^ | - = note: `-D modulo-one` implied by `-D warnings` + = note: `-D clippy::modulo-one` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index a7cbc0b7a09..0f5baa2d27e 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -4,7 +4,7 @@ error: mutable borrow from immutable input(s) 9 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^^^^ | - = note: `-D mut-from-ref` implied by `-D warnings` + = note: `-D clippy::mut-from-ref` implied by `-D warnings` note: immutable borrow here --> $DIR/mut_from_ref.rs:9:29 | diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index d1f05ea8091..88bd2f729af 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -4,7 +4,7 @@ error: generally you want to avoid `&mut &mut _` if possible 10 | fn fun(x : &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ | - = note: `-D mut-mut` implied by `-D warnings` + = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:24:17 diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index d7be7ae1e6f..fece9610697 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -4,7 +4,7 @@ error: attempt to mutate range bound within loop; note that the range of the loo 18 | for i in 0..m { m = 5; } // warning | ^^^^^ | - = note: `-D mut-range-bound` implied by `-D warnings` + = note: `-D clippy::mut-range-bound` implied by `-D warnings` error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:23:22 diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 73df19bf158..ee62e264767 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -4,7 +4,7 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable 22 | takes_an_immutable_reference(&mut 42); | ^^^^^^^ | - = note: `-D unnecessary-mut-passed` implied by `-D warnings` + = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` error: The function/method `as_ptr` doesn't need a mutable reference --> $DIR/mut_reference.rs:24:12 diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 354f9891c17..2df58889a47 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -4,7 +4,7 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want th 9 | Mutex::new(true); | ^^^^^^^^^^^^^^^^ | - = note: `-D mutex-atomic` implied by `-D warnings` + = note: `-D clippy::mutex-atomic` implied by `-D warnings` error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:10:5 @@ -36,7 +36,7 @@ error: Consider using an AtomicUsize instead of a Mutex here. If you just want t 15 | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ | - = note: `-D mutex-integer` implied by `-D warnings` + = note: `-D clippy::mutex-integer` implied by `-D warnings` error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:16:5 diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index 63e0632445f..dd132bc671e 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -4,7 +4,7 @@ error: this if-then-else expression will always return true 9 | if x { true } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D needless-bool` implied by `-D warnings` + = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false --> $DIR/needless_bool.rs:10:5 diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index fde38508b32..c720dff5d29 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,41 +1,41 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:13:15 + --> $DIR/needless_borrow.rs:15:15 | -13 | let c = x(&&a); +15 | let c = x(&&a); | ^^^ help: change this to: `&a` | - = note: `-D needless-borrow` implied by `-D warnings` + = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:20:17 + --> $DIR/needless_borrow.rs:22:17 | -20 | if let Some(ref cake) = Some(&5) {} +22 | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:27:15 + --> $DIR/needless_borrow.rs:29:15 | -27 | 46 => &&a, +29 | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:49:34 + --> $DIR/needless_borrow.rs:51:34 | -49 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +51 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` + = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:50:30 + --> $DIR/needless_borrow.rs:52:30 | -50 | let _ = v.iter().filter(|&ref a| a.is_empty()); +52 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:50:31 + --> $DIR/needless_borrow.rs:52:31 | -50 | let _ = v.iter().filter(|&ref a| a.is_empty()); +52 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` error: aborting due to 6 previous errors diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 2a8cf4348d3..3113b887b05 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -4,7 +4,7 @@ error: this pattern takes a reference on something that is being de-referenced 8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` + = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrowed_ref.rs:13:17 diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 3e0368892a4..7cfaf89d6e0 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -8,7 +8,7 @@ error: This else block is redundant. 28 | | } | |_________^ | - = note: `-D needless-continue` implied by `-D warnings` + = note: `-D clippy::needless-continue` implied by `-D warnings` = help: Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so: if i % 2 == 0 && i % 3 == 0 { println!("{}", i); diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 2fef0595cb3..9cb5e6e48cd 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,187 +1,187 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:9:23 - | -9 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { - | ^^^^^^ help: consider changing the type to: `&[T]` - | - = note: `-D needless-pass-by-value` implied by `-D warnings` + --> $DIR/needless_pass_by_value.rs:11:23 + | +11 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { + | ^^^^^^ help: consider changing the type to: `&[T]` + | + = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:23:11 + --> $DIR/needless_pass_by_value.rs:25:11 | -23 | fn bar(x: String, y: Wrapper) { +25 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:23:22 + --> $DIR/needless_pass_by_value.rs:25:22 | -23 | fn bar(x: String, y: Wrapper) { +25 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:29:71 + --> $DIR/needless_pass_by_value.rs:31:71 | -29 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +31 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:41:18 + --> $DIR/needless_pass_by_value.rs:43:18 | -41 | fn test_match(x: Option>, y: Option>) { +43 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -41 | fn test_match(x: &Option>, y: Option>) { -42 | match *x { +43 | fn test_match(x: &Option>, y: Option>) { +44 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:54:24 + --> $DIR/needless_pass_by_value.rs:56:24 | -54 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +56 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:54:36 + --> $DIR/needless_pass_by_value.rs:56:36 | -54 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +56 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead | -54 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -55 | let Wrapper(s) = z; // moved -56 | let Wrapper(ref t) = *y; // not moved -57 | let Wrapper(_) = *y; // still not moved +56 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +57 | let Wrapper(s) = z; // moved +58 | let Wrapper(ref t) = *y; // not moved +59 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:70:49 + --> $DIR/needless_pass_by_value.rs:72:49 | -70 | fn test_blanket_ref(_foo: T, _serializable: S) {} +72 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:72:18 + --> $DIR/needless_pass_by_value.rs:74:18 | -72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:72:29 + --> $DIR/needless_pass_by_value.rs:74:29 | -72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -72 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +74 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -74 | let _ = t.to_string(); +76 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:72:40 + --> $DIR/needless_pass_by_value.rs:74:40 | -72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:72:53 + --> $DIR/needless_pass_by_value.rs:74:53 | -72 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -72 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +74 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -76 | let _ = v.to_owned(); +78 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:84:12 + --> $DIR/needless_pass_by_value.rs:86:12 | -84 | s: String, +86 | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:85:12 + --> $DIR/needless_pass_by_value.rs:87:12 | -85 | t: String, +87 | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:97:13 + --> $DIR/needless_pass_by_value.rs:99:13 | -97 | _u: U, +99 | _u: U, | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:98:13 - | -98 | _s: Self, - | ^^^^ help: consider taking a reference instead: `&Self` + --> $DIR/needless_pass_by_value.rs:100:13 + | +100 | _s: Self, + | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:120:24 + --> $DIR/needless_pass_by_value.rs:122:24 | -120 | fn bar_copy(x: u32, y: CopyWrapper) { +122 | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:118:1 + --> $DIR/needless_pass_by_value.rs:120:1 | -118 | struct CopyWrapper(u32); +120 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:126:29 + --> $DIR/needless_pass_by_value.rs:128:29 | -126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:118:1 + --> $DIR/needless_pass_by_value.rs:120:1 | -118 | struct CopyWrapper(u32); +120 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:126:45 + --> $DIR/needless_pass_by_value.rs:128:45 | -126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:118:1 + --> $DIR/needless_pass_by_value.rs:120:1 | -118 | struct CopyWrapper(u32); +120 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -126 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { -127 | let CopyWrapper(s) = z; // moved -128 | let CopyWrapper(ref t) = *y; // not moved -129 | let CopyWrapper(_) = *y; // still not moved +128 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { +129 | let CopyWrapper(s) = z; // moved +130 | let CopyWrapper(ref t) = *y; // not moved +131 | let CopyWrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:126:61 + --> $DIR/needless_pass_by_value.rs:128:61 | -126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:118:1 + --> $DIR/needless_pass_by_value.rs:120:1 | -118 | struct CopyWrapper(u32); +120 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -126 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { -127 | let CopyWrapper(s) = *z; // moved +128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { +129 | let CopyWrapper(s) = *z; // moved | error: aborting due to 20 previous errors diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index c394469c17b..1954a8240b2 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -4,7 +4,7 @@ error: the loop variable `i` is only used to index `ns`. 8 | for i in 3..10 { | ^^^^^ | - = note: `-D needless-range-loop` implied by `-D warnings` + = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | 8 | for in ns.iter().take(10).skip(3) { diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 42dc6e6594c..094fe3642a2 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -4,7 +4,7 @@ error: unneeded return statement 11 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` | - = note: `-D needless-return` implied by `-D warnings` + = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded return statement --> $DIR/needless_return.rs:15:5 diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index 3e509870d00..acc51198497 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -4,7 +4,7 @@ error: struct update has no effect, all the fields in the struct have already be 16 | S { a: 1, b: 1, ..base }; | ^^^^ | - = note: `-D needless-update` implied by `-D warnings` + = note: `-D clippy::needless-update` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index ccd30561100..5fd4ab9ba48 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,27 +1,27 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:17:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:19:21 | -17 | let _not_less = !(a_value < another_value); +19 | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D neg-cmp-op-on-partial-ord` implied by `-D warnings` + = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:20:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:22:30 | -20 | let _not_less_or_equal = !(a_value <= another_value); +22 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:23:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:25:24 | -23 | let _not_greater = !(a_value > another_value); +25 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:26:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:28:33 | -26 | let _not_greater_or_equal = !(a_value >= another_value); +28 | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 1d52ba16eae..ba59fdb8940 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -4,7 +4,7 @@ error: Negation by multiplying with -1 30 | x * -1; | ^^^^^^ | - = note: `-D neg-multiply` implied by `-D warnings` + = note: `-D clippy::neg-multiply` implied by `-D warnings` error: Negation by multiplying with -1 --> $DIR/neg_multiply.rs:32:5 diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 664be379e35..3d1235964d1 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,7 +1,7 @@ error: this loop never actually loops --> $DIR/never_loop.rs:7:5 | -7 | / loop { // never_loop +7 | / loop { // clippy::never_loop 8 | | x += 1; 9 | | if x == 1 { 10 | | return @@ -10,7 +10,7 @@ error: this loop never actually loops 13 | | } | |_____^ | - = note: #[deny(never_loop)] on by default + = note: #[deny(clippy::never_loop)] on by default error: this loop never actually loops --> $DIR/never_loop.rs:28:5 diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 335e60404fa..11ece5e8708 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,39 +1,39 @@ error: you should consider deriving a `Default` implementation for `Foo` - --> $DIR/new_without_default.rs:10:5 + --> $DIR/new_without_default.rs:12:5 | -10 | pub fn new() -> Foo { Foo } +12 | pub fn new() -> Foo { Foo } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D new-without-default-derive` implied by `-D warnings` + = note: `-D clippy::new-without-default-derive` implied by `-D warnings` help: try this | -7 | #[derive(Default)] +9 | #[derive(Default)] | error: you should consider deriving a `Default` implementation for `Bar` - --> $DIR/new_without_default.rs:16:5 + --> $DIR/new_without_default.rs:18:5 | -16 | pub fn new() -> Self { Bar } +18 | pub fn new() -> Self { Bar } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this | -13 | #[derive(Default)] +15 | #[derive(Default)] | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> $DIR/new_without_default.rs:64:5 + --> $DIR/new_without_default.rs:66:5 | -64 | pub fn new() -> LtKo<'c> { unimplemented!() } +66 | pub fn new() -> LtKo<'c> { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D new-without-default` implied by `-D warnings` + = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | -63 | impl Default for LtKo<'c> { -64 | fn default() -> Self { -65 | Self::new() -66 | } -67 | } +65 | impl Default for LtKo<'c> { +66 | fn default() -> Self { +67 | Self::new() +68 | } +69 | } | error: aborting due to 3 previous errors diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 7ff0425ebb9..2429d934ca1 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,275 +1,275 @@ error: statement with no effect - --> $DIR/no_effect.rs:59:5 + --> $DIR/no_effect.rs:61:5 | -59 | 0; +61 | 0; | ^^ | - = note: `-D no-effect` implied by `-D warnings` + = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:60:5 + --> $DIR/no_effect.rs:62:5 | -60 | s2; +62 | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:61:5 + --> $DIR/no_effect.rs:63:5 | -61 | Unit; +63 | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:62:5 + --> $DIR/no_effect.rs:64:5 | -62 | Tuple(0); +64 | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:63:5 + --> $DIR/no_effect.rs:65:5 | -63 | Struct { field: 0 }; +65 | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:64:5 + --> $DIR/no_effect.rs:66:5 | -64 | Struct { ..s }; +66 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:65:5 + --> $DIR/no_effect.rs:67:5 | -65 | Union { a: 0 }; +67 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:66:5 + --> $DIR/no_effect.rs:68:5 | -66 | Enum::Tuple(0); +68 | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:67:5 + --> $DIR/no_effect.rs:69:5 | -67 | Enum::Struct { field: 0 }; +69 | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:68:5 + --> $DIR/no_effect.rs:70:5 | -68 | 5 + 6; +70 | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:69:5 + --> $DIR/no_effect.rs:71:5 | -69 | *&42; +71 | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:70:5 + --> $DIR/no_effect.rs:72:5 | -70 | &6; +72 | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:73:5 | -71 | (5, 6, 7); +73 | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:74:5 | -72 | box 42; +74 | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:73:5 + --> $DIR/no_effect.rs:75:5 | -73 | ..; +75 | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:76:5 | -74 | 5..; +76 | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:77:5 | -75 | ..5; +77 | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:78:5 | -76 | 5..6; +78 | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:80:5 | -78 | [42, 55]; +80 | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:81:5 | -79 | [42, 55][1]; +81 | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:82:5 | -80 | (42, 55).1; +82 | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:83:5 | -81 | [42; 55]; +83 | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:84:5 | -82 | [42; 55][13]; +84 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:86:5 | -84 | || x += 5; +86 | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:88:5 | -86 | FooString { s: s }; +88 | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: statement can be reduced - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:99:5 | -97 | Tuple(get_number()); +99 | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | - = note: `-D unnecessary-operation` implied by `-D warnings` + = note: `-D clippy::unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/no_effect.rs:98:5 - | -98 | Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + --> $DIR/no_effect.rs:100:5 + | +100 | Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:99:5 - | -99 | Struct { ..get_struct() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` + --> $DIR/no_effect.rs:101:5 + | +101 | Struct { ..get_struct() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:102:5 | -100 | Enum::Tuple(get_number()); +102 | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:103:5 | -101 | Enum::Struct { field: get_number() }; +103 | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:104:5 | -102 | 5 + get_number(); +104 | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:105:5 | -103 | *&get_number(); +105 | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:106:5 | -104 | &get_number(); +106 | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:107:5 | -105 | (5, 6, get_number()); +107 | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:108:5 | -106 | box get_number(); +108 | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:109:5 | -107 | get_number()..; +109 | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:110:5 | -108 | ..get_number(); +110 | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:111:5 | -109 | 5..get_number(); +111 | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:112:5 | -110 | [42, get_number()]; +112 | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:113:5 | -111 | [42, 55][get_number() as usize]; +113 | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:114:5 | -112 | (42, get_number()).1; +114 | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:115:5 | -113 | [get_number(); 55]; +115 | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:116:5 | -114 | [42; 55][get_number() as usize]; +116 | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:117:5 | -115 | {get_number()}; +117 | {get_number()}; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:118:5 | -116 | FooString { s: String::from("blah"), }; +118 | FooString { s: String::from("blah"), }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` error: aborting due to 45 previous errors diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 388c7fabab0..7f164595b59 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -1,272 +1,272 @@ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:10:1 + --> $DIR/non_copy_const.rs:12:1 | -10 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +12 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` | - = note: #[deny(declare_interior_mutable_const)] on by default + = note: #[deny(clippy::declare_interior_mutable_const)] on by default error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:11:1 + --> $DIR/non_copy_const.rs:13:1 | -11 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +13 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:12:1 + --> $DIR/non_copy_const.rs:14:1 | -12 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +14 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:16:42 + --> $DIR/non_copy_const.rs:18:42 | -16 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; +18 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; | ^^^^^^^^^^^^^^^^^^^^^^ -17 | } -18 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +19 | } +20 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:39:5 + --> $DIR/non_copy_const.rs:41:5 | -39 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +41 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:43:5 + --> $DIR/non_copy_const.rs:45:5 | -43 | const INPUT: T; +45 | const INPUT: T; | ^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:43:18 + --> $DIR/non_copy_const.rs:45:18 | -43 | const INPUT: T; +45 | const INPUT: T; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:46:5 + --> $DIR/non_copy_const.rs:48:5 | -46 | const ASSOC: Self::NonCopyType; +48 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:46:18 + --> $DIR/non_copy_const.rs:48:18 | -46 | const ASSOC: Self::NonCopyType; +48 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:50:5 + --> $DIR/non_copy_const.rs:52:5 | -50 | const AN_INPUT: T = Self::INPUT; +52 | const AN_INPUT: T = Self::INPUT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:50:21 + --> $DIR/non_copy_const.rs:52:21 | -50 | const AN_INPUT: T = Self::INPUT; +52 | const AN_INPUT: T = Self::INPUT; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:16:42 + --> $DIR/non_copy_const.rs:18:42 | -16 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; +18 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; | ^^^^^^^^^^^^^^^^^^^^^^ ... -53 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable +55 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable | ----------------------------------------------- in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:59:5 + --> $DIR/non_copy_const.rs:61:5 | -59 | const SELF_2: Self; +61 | const SELF_2: Self; | ^^^^^^^^^^^^^^^^^^^ | help: consider requiring `Self` to be `Copy` - --> $DIR/non_copy_const.rs:59:19 + --> $DIR/non_copy_const.rs:61:19 | -59 | const SELF_2: Self; +61 | const SELF_2: Self; | ^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:80:5 + --> $DIR/non_copy_const.rs:82:5 | -80 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable +82 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:83:5 + --> $DIR/non_copy_const.rs:85:5 | -83 | const U_SELF: U = U::SELF_2; +85 | const U_SELF: U = U::SELF_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `U` to be `Copy` - --> $DIR/non_copy_const.rs:83:19 + --> $DIR/non_copy_const.rs:85:19 | -83 | const U_SELF: U = U::SELF_2; +85 | const U_SELF: U = U::SELF_2; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:86:5 + --> $DIR/non_copy_const.rs:88:5 | -86 | const T_ASSOC: T::NonCopyType = T::ASSOC; +88 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:86:20 + --> $DIR/non_copy_const.rs:88:20 | -86 | const T_ASSOC: T::NonCopyType = T::ASSOC; +88 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^ error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:93:5 + --> $DIR/non_copy_const.rs:95:5 | -93 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability +95 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ | - = note: #[deny(borrow_interior_mutable_const)] on by default + = note: #[deny(clippy::borrow_interior_mutable_const)] on by default = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:94:16 + --> $DIR/non_copy_const.rs:96:16 | -94 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability +96 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:96:5 + --> $DIR/non_copy_const.rs:98:5 | -96 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability +98 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:97:16 + --> $DIR/non_copy_const.rs:99:16 | -97 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability +99 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:100:22 + --> $DIR/non_copy_const.rs:102:22 | -100 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability +102 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:101:25 + --> $DIR/non_copy_const.rs:103:25 | -101 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability +103 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:102:27 + --> $DIR/non_copy_const.rs:104:27 | -102 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability +104 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:103:26 + --> $DIR/non_copy_const.rs:105:26 | -103 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability +105 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:114:14 + --> $DIR/non_copy_const.rs:116:14 | -114 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability +116 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:115:14 + --> $DIR/non_copy_const.rs:117:14 | -115 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability +117 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:116:19 + --> $DIR/non_copy_const.rs:118:19 | -116 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability +118 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:117:14 + --> $DIR/non_copy_const.rs:119:14 | -117 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +119 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:118:13 + --> $DIR/non_copy_const.rs:120:13 | -118 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability +120 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:124:13 + --> $DIR/non_copy_const.rs:126:13 | -124 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +126 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:129:5 + --> $DIR/non_copy_const.rs:131:5 | -129 | CELL.set(2); //~ ERROR interior mutability +131 | CELL.set(2); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:130:16 + --> $DIR/non_copy_const.rs:132:16 | -130 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability +132 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:143:5 + --> $DIR/non_copy_const.rs:145:5 | -143 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability +145 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:144:16 + --> $DIR/non_copy_const.rs:146:16 | -144 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability +146 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index b4927e69e67..b1dd62ed87c 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -4,7 +4,7 @@ error: binding's name is too similar to existing binding 18 | let bpple: i32; | ^^^^^ | - = note: `-D similar-names` implied by `-D warnings` + = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here --> $DIR/non_expressive_names.rs:16:9 | @@ -109,7 +109,7 @@ error: 5th binding whose name is just one char 120 | let e: i32; | ^ | - = note: `-D many-single-char-names` implied by `-D warnings` + = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char --> $DIR/non_expressive_names.rs:123:17 @@ -135,7 +135,7 @@ error: consider choosing a more descriptive name 139 | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ | - = note: `-D just-underscores-and-digits` implied by `-D warnings` + = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:140:9 diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index da2d3b9500f..7c158b5207b 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -4,7 +4,7 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly 14 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D ok-expect` implied by `-D warnings` + = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:20:5 diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index e1371d924eb..eac49032ed8 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -8,7 +8,7 @@ error: Matching on `Some` with `ok()` is redundant 11 | | } | |_____^ | - = note: `-D if-let-some-result` implied by `-D warnings` + = note: `-D clippy::if-let-some-result` implied by `-D warnings` = help: Consider matching on `Ok(y)` and removing the call to `ok` instead error: aborting due to previous error diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 4a6ff6fe6dc..398e3a6e9e6 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -4,7 +4,7 @@ error: needlessly taken reference of both operands 13 | let foo = &5 - &6; | ^^^^^^^ | - = note: `-D op-ref` implied by `-D warnings` + = note: `-D clippy::op-ref` implied by `-D warnings` help: use the values directly | 13 | let foo = 5 - 6; diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index f0d41904152..64ad667a4c7 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -4,7 +4,7 @@ error: file opened with "truncate" and "read" 8 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D nonsensical-open-options` implied by `-D warnings` + = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` error: file opened with "append" and "truncate" --> $DIR/open_options.rs:9:5 diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 3ca57a65b3f..77fe24d2696 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,207 +1,207 @@ error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:32:5 + --> $DIR/option_map_unit_fn.rs:34:5 | -32 | x.field.map(do_nothing); +34 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` | - = note: `-D option-map-unit-fn` implied by `-D warnings` + = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:34:5 + --> $DIR/option_map_unit_fn.rs:36:5 | -34 | x.field.map(do_nothing); +36 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:36:5 + --> $DIR/option_map_unit_fn.rs:38:5 | -36 | x.field.map(diverge); +38 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:42:5 + --> $DIR/option_map_unit_fn.rs:44:5 | -42 | x.field.map(|value| x.do_option_nothing(value + captured)); +44 | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:44:5 + --> $DIR/option_map_unit_fn.rs:46:5 | -44 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); +46 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:47:5 + --> $DIR/option_map_unit_fn.rs:49:5 | -47 | x.field.map(|value| do_nothing(value + captured)); +49 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:49:5 + --> $DIR/option_map_unit_fn.rs:51:5 | -49 | x.field.map(|value| { do_nothing(value + captured) }); +51 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:51:5 + --> $DIR/option_map_unit_fn.rs:53:5 | -51 | x.field.map(|value| { do_nothing(value + captured); }); +53 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:53:5 + --> $DIR/option_map_unit_fn.rs:55:5 | -53 | x.field.map(|value| { { do_nothing(value + captured); } }); +55 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:56:5 + --> $DIR/option_map_unit_fn.rs:58:5 | -56 | x.field.map(|value| diverge(value + captured)); +58 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:58:5 + --> $DIR/option_map_unit_fn.rs:60:5 | -58 | x.field.map(|value| { diverge(value + captured) }); +60 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:60:5 + --> $DIR/option_map_unit_fn.rs:62:5 | -60 | x.field.map(|value| { diverge(value + captured); }); +62 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:62:5 + --> $DIR/option_map_unit_fn.rs:64:5 | -62 | x.field.map(|value| { { diverge(value + captured); } }); +64 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:67:5 + --> $DIR/option_map_unit_fn.rs:69:5 | -67 | x.field.map(|value| { let y = plus_one(value + captured); }); +69 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:69:5 + --> $DIR/option_map_unit_fn.rs:71:5 | -69 | x.field.map(|value| { plus_one(value + captured); }); +71 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:71:5 + --> $DIR/option_map_unit_fn.rs:73:5 | -71 | x.field.map(|value| { { plus_one(value + captured); } }); +73 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:74:5 + --> $DIR/option_map_unit_fn.rs:76:5 | -74 | x.field.map(|ref value| { do_nothing(value + captured) }); +76 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:77:5 + --> $DIR/option_map_unit_fn.rs:79:5 | -77 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +79 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:79:5 + --> $DIR/option_map_unit_fn.rs:81:5 | -79 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +81 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:83:5 + --> $DIR/option_map_unit_fn.rs:85:5 | -83 | x.field.map(|value| { +85 | x.field.map(|value| { | _____^ | |_____| | || -84 | || do_nothing(value); -85 | || do_nothing(value) -86 | || }); +86 | || do_nothing(value); +87 | || do_nothing(value) +88 | || }); | ||______^- help: try this: `if let Some(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:87:5 + --> $DIR/option_map_unit_fn.rs:89:5 | -87 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +89 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:90:5 + --> $DIR/option_map_unit_fn.rs:92:5 | -90 | Some(42).map(diverge); +92 | Some(42).map(diverge); | ^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:91:5 + --> $DIR/option_map_unit_fn.rs:93:5 | -91 | "12".parse::().ok().map(diverge); +93 | "12".parse::().ok().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:92:5 + --> $DIR/option_map_unit_fn.rs:94:5 | -92 | Some(plus_one(1)).map(do_nothing); +94 | Some(plus_one(1)).map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:96:5 + --> $DIR/option_map_unit_fn.rs:98:5 | -96 | y.map(do_nothing); +98 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_y) = y { do_nothing(...) }` diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 19e00efae71..4341857cce0 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -4,7 +4,7 @@ error: consider using `Option` instead of `Option>` or a custom enu 1 | fn input(_: Option>) { | ^^^^^^^^^^^^^^^^^^ | - = note: `-D option-option` implied by `-D warnings` + = note: `-D clippy::option-option` implied by `-D warnings` error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:4:16 diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index adf353a1c4b..9659e352af1 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -4,7 +4,7 @@ error: You are trying to use classic C overflow conditions that will fail in Rus 11 | if a + b < a { | ^^^^^^^^^ | - = note: `-D overflow-check-conditional` implied by `-D warnings` + = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:14:5 diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index 3bf5589c468..c5ce42f4c54 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -4,7 +4,7 @@ error: you probably are missing some parameter in your format string 8 | panic!("{}"); | ^^^^ | - = note: `-D panic-params` implied by `-D warnings` + = note: `-D clippy::panic-params` implied by `-D warnings` error: you probably are missing some parameter in your format string --> $DIR/panic_unimplemented.rs:10:16 @@ -30,7 +30,7 @@ error: `unimplemented` should not be present in production code 58 | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | - = note: `-D unimplemented` implied by `-D warnings` + = note: `-D clippy::unimplemented` implied by `-D warnings` error: aborting due to 5 previous errors diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index 5e536cc51d2..773bed8fd8e 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -4,7 +4,7 @@ error: re-implementing `PartialEq::ne` is unnecessary 10 | fn ne(&self, _: &Foo) -> bool { false } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D partialeq-ne-impl` implied by `-D warnings` + = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 59bce3a9a8f..ce8aab7e627 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -4,7 +4,7 @@ error: the `y @ _` pattern can be written as just `y` 10 | y @ _ => (), | ^^^^^ | - = note: `-D redundant-pattern` implied by `-D warnings` + = note: `-D clippy::redundant-pattern` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 92c1364746e..5ec1732ee56 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -4,7 +4,7 @@ error: operator precedence can trip the unwary 18 | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` | - = note: `-D precedence` implied by `-D warnings` + = note: `-D clippy::precedence` implied by `-D warnings` error: operator precedence can trip the unwary --> $DIR/precedence.rs:19:5 diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index f2d2afd9bf7..92a2f2f9627 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -4,7 +4,7 @@ error: use of `Debug`-based formatting 13 | write!(f, "{:?}", 43.1415) | ^^^^^^ | - = note: `-D use-debug` implied by `-D warnings` + = note: `-D clippy::use-debug` implied by `-D warnings` error: use of `Debug`-based formatting --> $DIR/print.rs:20:19 @@ -18,7 +18,7 @@ error: use of `println!` 25 | println!("Hello"); | ^^^^^^^^^^^^^^^^^ | - = note: `-D print-stdout` implied by `-D warnings` + = note: `-D clippy::print-stdout` implied by `-D warnings` error: use of `print!` --> $DIR/print.rs:26:5 diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index cada26c6142..bd13f5d1730 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -4,7 +4,7 @@ error: literal with an empty format string 24 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | - = note: `-D print-literal` implied by `-D warnings` + = note: `-D clippy::print-literal` implied by `-D warnings` error: literal with an empty format string --> $DIR/print_literal.rs:25:24 diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 58413a9b4a9..12c4ecb2f3e 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -4,7 +4,7 @@ error: using `print!()` with a format string that ends in a single newline, cons 7 | print!("Hello/n"); | ^^^^^^^^^^^^^^^^^ | - = note: `-D print-with-newline` implied by `-D warnings` + = note: `-D clippy::print-with-newline` implied by `-D warnings` error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:8:5 diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index cff3f988052..96d15838400 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -4,7 +4,7 @@ error: using `println!("")` 3 | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` | - = note: `-D println-empty-string` implied by `-D warnings` + = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` --> $DIR/println_empty_string.rs:6:14 diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index a29e393baa1..6c16443f524 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,85 +1,85 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:6:14 + --> $DIR/ptr_arg.rs:8:14 | -6 | fn do_vec(x: &Vec) { +8 | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` | - = note: `-D ptr-arg` implied by `-D warnings` + = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:14:14 + --> $DIR/ptr_arg.rs:16:14 | -14 | fn do_str(x: &String) { +16 | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:27:18 + --> $DIR/ptr_arg.rs:29:18 | -27 | fn do_vec(x: &Vec); +29 | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:40:14 + --> $DIR/ptr_arg.rs:42:14 | -40 | fn cloned(x: &Vec) -> Vec { +42 | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ help: change this to | -40 | fn cloned(x: &[u8]) -> Vec { +42 | fn cloned(x: &[u8]) -> Vec { | ^^^^^ help: change `x.clone()` to | -41 | let e = x.to_owned(); +43 | let e = x.to_owned(); | ^^^^^^^^^^^^ help: change `x.clone()` to | -46 | x.to_owned() +48 | x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:49:18 + --> $DIR/ptr_arg.rs:51:18 | -49 | fn str_cloned(x: &String) -> String { +51 | fn str_cloned(x: &String) -> String { | ^^^^^^^ help: change this to | -49 | fn str_cloned(x: &str) -> String { +51 | fn str_cloned(x: &str) -> String { | ^^^^ help: change `x.clone()` to | -50 | let a = x.to_string(); +52 | let a = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -51 | let b = x.to_string(); +53 | let b = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -56 | x.to_string() +58 | x.to_string() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:59:44 + --> $DIR/ptr_arg.rs:61:44 | -59 | fn false_positive_capacity(x: &Vec, y: &String) { +61 | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ help: change this to | -59 | fn false_positive_capacity(x: &Vec, y: &str) { +61 | fn false_positive_capacity(x: &Vec, y: &str) { | ^^^^ help: change `y.clone()` to | -61 | let b = y.to_string(); +63 | let b = y.to_string(); | ^^^^^^^^^^^^^ help: change `y.as_str()` to | -62 | let c = y; +64 | let c = y; | ^ error: using a reference to `Cow` is not recommended. - --> $DIR/ptr_arg.rs:71:25 + --> $DIR/ptr_arg.rs:73:25 | -71 | fn test_cow_with_ref(c: &Cow<[i32]>) { +73 | fn test_cow_with_ref(c: &Cow<[i32]>) { | ^^^^^^^^^^^ help: change this to: `&[i32]` error: aborting due to 7 previous errors diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index e97b1869824..68c0e5e381a 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -7,7 +7,7 @@ error: this block may be rewritten with the `?` operator 4 | | } | |_____^ help: replace_it_with: `a?;` | - = note: `-D question-mark` implied by `-D warnings` + = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:37:3 diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 064429c337c..651ff266c1a 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -4,7 +4,7 @@ error: Iterator::step_by(0) will panic at runtime 10 | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ | - = note: `-D iterator-step-by-zero` implied by `-D warnings` + = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:14:13 @@ -30,7 +30,7 @@ error: It is more idiomatic to use v1.iter().enumerate() 26 | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D range-zip-with-len` implied by `-D warnings` + = note: `-D clippy::range-zip-with-len` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:30:13 diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 1990300ef90..083c153addb 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,47 +1,47 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:10:14 + --> $DIR/range_plus_minus_one.rs:12:14 | -10 | for _ in 0..3+1 { } +12 | for _ in 0..3+1 { } | ^^^^^^ help: use: `0..=3` | - = note: `-D range-plus-one` implied by `-D warnings` + = note: `-D clippy::range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:13:14 + --> $DIR/range_plus_minus_one.rs:15:14 | -13 | for _ in 0..1+5 { } +15 | for _ in 0..1+5 { } | ^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:16:14 + --> $DIR/range_plus_minus_one.rs:18:14 | -16 | for _ in 1..1+1 { } +18 | for _ in 1..1+1 { } | ^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:22:14 + --> $DIR/range_plus_minus_one.rs:24:14 | -22 | for _ in 0..(1+f()) { } +24 | for _ in 0..(1+f()) { } | ^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:26:13 + --> $DIR/range_plus_minus_one.rs:28:13 | -26 | let _ = ..=11-1; +28 | let _ = ..=11-1; | ^^^^^^^ help: use: `..11` | - = note: `-D range-minus-one` implied by `-D warnings` + = note: `-D clippy::range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:27:13 + --> $DIR/range_plus_minus_one.rs:29:13 | -27 | let _ = ..=(11-1); +29 | let _ = ..=(11-1); | ^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:28:13 + --> $DIR/range_plus_minus_one.rs:30:13 | -28 | let _ = (f()+1)..(f()+1); +30 | let _ = (f()+1)..(f()+1); | ^^^^^^^^^^^^^^^^ help: use: `(f()+1)..=f()` error: aborting due to 7 previous errors diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index d2b5616a481..e4d490743ad 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -4,7 +4,7 @@ error: Closure called just once immediately after it was declared 15 | i = closure(); | ^^^^^^^^^^^^^ | - = note: `-D redundant-closure-call` implied by `-D warnings` + = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:18:2 diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 5821baf4c85..457fe7d3c6c 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,45 +1,45 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:34:9 + --> $DIR/redundant_field_names.rs:36:9 | -34 | gender: gender, +36 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | - = note: `-D redundant-field-names` implied by `-D warnings` + = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:35:9 + --> $DIR/redundant_field_names.rs:37:9 | -35 | age: age, +37 | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:56:25 + --> $DIR/redundant_field_names.rs:58:25 | -56 | let _ = RangeFrom { start: start }; +58 | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:57:23 + --> $DIR/redundant_field_names.rs:59:23 | -57 | let _ = RangeTo { end: end }; +59 | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:21 + --> $DIR/redundant_field_names.rs:60:21 | -58 | let _ = Range { start: start, end: end }; +60 | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:35 + --> $DIR/redundant_field_names.rs:60:35 | -58 | let _ = Range { start: start, end: end }; +60 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:32 + --> $DIR/redundant_field_names.rs:62:32 | -60 | let _ = RangeToInclusive { end: end }; +62 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 7 previous errors diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 741c0cc1038..13e0da98795 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -4,7 +4,7 @@ error: immediately dereferencing a reference 19 | let b = *&a; | ^^^ help: try this: `a` | - = note: `-D deref-addrof` implied by `-D warnings` + = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference --> $DIR/reference.rs:21:13 diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 39c360583e7..fd8fecb1139 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -4,7 +4,7 @@ error: trivial regex 16 | let pipe_in_wrong_position = Regex::new("|"); | ^^^ | - = note: `-D trivial-regex` implied by `-D warnings` + = note: `-D clippy::trivial-regex` implied by `-D warnings` = help: the regex is unlikely to be useful as it is error: trivial regex @@ -21,7 +21,7 @@ error: regex syntax error: invalid character class range, the start must be <= t 18 | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ | - = note: `-D invalid-regex` implied by `-D warnings` + = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end --> $DIR/regex.rs:19:37 diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 0a9d5f4ab75..fb9c9414c85 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,217 +1,217 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:12:17 + --> $DIR/replace_consts.rs:14:17 | -12 | { let foo = ATOMIC_BOOL_INIT; }; +14 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:3:9 + --> $DIR/replace_consts.rs:5:9 | -3 | #![deny(replace_consts)] - | ^^^^^^^^^^^^^^ +5 | #![deny(clippy::replace_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:13:17 + --> $DIR/replace_consts.rs:15:17 | -13 | { let foo = ATOMIC_ISIZE_INIT; }; +15 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:14:17 + --> $DIR/replace_consts.rs:16:17 | -14 | { let foo = ATOMIC_I8_INIT; }; +16 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:15:17 + --> $DIR/replace_consts.rs:17:17 | -15 | { let foo = ATOMIC_I16_INIT; }; +17 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:16:17 + --> $DIR/replace_consts.rs:18:17 | -16 | { let foo = ATOMIC_I32_INIT; }; +18 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:17:17 + --> $DIR/replace_consts.rs:19:17 | -17 | { let foo = ATOMIC_I64_INIT; }; +19 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:18:17 + --> $DIR/replace_consts.rs:20:17 | -18 | { let foo = ATOMIC_USIZE_INIT; }; +20 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:19:17 + --> $DIR/replace_consts.rs:21:17 | -19 | { let foo = ATOMIC_U8_INIT; }; +21 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:20:17 + --> $DIR/replace_consts.rs:22:17 | -20 | { let foo = ATOMIC_U16_INIT; }; +22 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:21:17 + --> $DIR/replace_consts.rs:23:17 | -21 | { let foo = ATOMIC_U32_INIT; }; +23 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:22:17 + --> $DIR/replace_consts.rs:24:17 | -22 | { let foo = ATOMIC_U64_INIT; }; +24 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:26:17 | -24 | { let foo = std::isize::MIN; }; +26 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:27:17 | -25 | { let foo = std::i8::MIN; }; +27 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:28:17 | -26 | { let foo = std::i16::MIN; }; +28 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:29:17 | -27 | { let foo = std::i32::MIN; }; +29 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:30:17 | -28 | { let foo = std::i64::MIN; }; +30 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:31:17 | -29 | { let foo = std::i128::MIN; }; +31 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:32:17 | -30 | { let foo = std::usize::MIN; }; +32 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:33:17 | -31 | { let foo = std::u8::MIN; }; +33 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:34:17 | -32 | { let foo = std::u16::MIN; }; +34 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:35:17 | -33 | { let foo = std::u32::MIN; }; +35 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:36:17 | -34 | { let foo = std::u64::MIN; }; +36 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:37:17 | -35 | { let foo = std::u128::MIN; }; +37 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:39:17 | -37 | { let foo = std::isize::MAX; }; +39 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:40:17 | -38 | { let foo = std::i8::MAX; }; +40 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:41:17 | -39 | { let foo = std::i16::MAX; }; +41 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:42:17 | -40 | { let foo = std::i32::MAX; }; +42 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:43:17 | -41 | { let foo = std::i64::MAX; }; +43 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:44:17 | -42 | { let foo = std::i128::MAX; }; +44 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:45:17 | -43 | { let foo = std::usize::MAX; }; +45 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:46:17 | -44 | { let foo = std::u8::MAX; }; +46 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:47:17 | -45 | { let foo = std::u16::MAX; }; +47 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:48:17 | -46 | { let foo = std::u32::MAX; }; +48 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:49:17 | -47 | { let foo = std::u64::MAX; }; +49 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:50:17 | -48 | { let foo = std::u128::MAX; }; +50 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 9ec24a7e97b..5fba1a0d7ad 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,194 +1,194 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:33:5 + --> $DIR/result_map_unit_fn.rs:35:5 | -33 | x.field.map(do_nothing); +35 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` | - = note: `-D result-map-unit-fn` implied by `-D warnings` + = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:35:5 + --> $DIR/result_map_unit_fn.rs:37:5 | -35 | x.field.map(do_nothing); +37 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:37:5 + --> $DIR/result_map_unit_fn.rs:39:5 | -37 | x.field.map(diverge); +39 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:43:5 + --> $DIR/result_map_unit_fn.rs:45:5 | -43 | x.field.map(|value| x.do_result_nothing(value + captured)); +45 | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:45:5 + --> $DIR/result_map_unit_fn.rs:47:5 | -45 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); +47 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:48:5 + --> $DIR/result_map_unit_fn.rs:50:5 | -48 | x.field.map(|value| do_nothing(value + captured)); +50 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:50:5 + --> $DIR/result_map_unit_fn.rs:52:5 | -50 | x.field.map(|value| { do_nothing(value + captured) }); +52 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:52:5 + --> $DIR/result_map_unit_fn.rs:54:5 | -52 | x.field.map(|value| { do_nothing(value + captured); }); +54 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:54:5 + --> $DIR/result_map_unit_fn.rs:56:5 | -54 | x.field.map(|value| { { do_nothing(value + captured); } }); +56 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:57:5 + --> $DIR/result_map_unit_fn.rs:59:5 | -57 | x.field.map(|value| diverge(value + captured)); +59 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:59:5 + --> $DIR/result_map_unit_fn.rs:61:5 | -59 | x.field.map(|value| { diverge(value + captured) }); +61 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:61:5 + --> $DIR/result_map_unit_fn.rs:63:5 | -61 | x.field.map(|value| { diverge(value + captured); }); +63 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:63:5 + --> $DIR/result_map_unit_fn.rs:65:5 | -63 | x.field.map(|value| { { diverge(value + captured); } }); +65 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:68:5 + --> $DIR/result_map_unit_fn.rs:70:5 | -68 | x.field.map(|value| { let y = plus_one(value + captured); }); +70 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:70:5 + --> $DIR/result_map_unit_fn.rs:72:5 | -70 | x.field.map(|value| { plus_one(value + captured); }); +72 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:72:5 + --> $DIR/result_map_unit_fn.rs:74:5 | -72 | x.field.map(|value| { { plus_one(value + captured); } }); +74 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:75:5 + --> $DIR/result_map_unit_fn.rs:77:5 | -75 | x.field.map(|ref value| { do_nothing(value + captured) }); +77 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:78:5 + --> $DIR/result_map_unit_fn.rs:80:5 | -78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +80 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:80:5 + --> $DIR/result_map_unit_fn.rs:82:5 | -80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +82 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:84:5 + --> $DIR/result_map_unit_fn.rs:86:5 | -84 | x.field.map(|value| { +86 | x.field.map(|value| { | _____^ | |_____| | || -85 | || do_nothing(value); -86 | || do_nothing(value) -87 | || }); +87 | || do_nothing(value); +88 | || do_nothing(value) +89 | || }); | ||______^- help: try this: `if let Ok(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:88:5 + --> $DIR/result_map_unit_fn.rs:90:5 | -88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +90 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:92:5 + --> $DIR/result_map_unit_fn.rs:94:5 | -92 | "12".parse::().map(diverge); +94 | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:98:5 - | -98 | y.map(do_nothing); - | ^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(_y) = y { do_nothing(...) }` + --> $DIR/result_map_unit_fn.rs:100:5 + | +100 | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_y) = y { do_nothing(...) }` error: aborting due to 23 previous errors diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index 58667e0f820..cce839a0d94 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -8,7 +8,7 @@ error: you should not implement `visit_string` without also implementing `visit_ 43 | | } | |_____^ | - = note: `-D serde-api-misuse` implied by `-D warnings` + = note: `-D clippy::serde-api-misuse` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 0eb5e5b2a2b..311177e25b4 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -4,7 +4,7 @@ error: `x` is shadowed by itself in `&mut x` 13 | let x = &mut x; | ^^^^^^^^^^^^^^^ | - = note: `-D shadow-same` implied by `-D warnings` + = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here --> $DIR/shadow.rs:12:13 | @@ -41,7 +41,7 @@ error: `x` is shadowed by `{ *x + 1 }` which reuses the original value 16 | let x = { *x + 1 }; | ^ | - = note: `-D shadow-reuse` implied by `-D warnings` + = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: initialization happens here --> $DIR/shadow.rs:16:13 | @@ -110,7 +110,7 @@ error: `x` is shadowed by `y` 21 | let x = y; | ^ | - = note: `-D shadow-unrelated` implied by `-D warnings` + = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here --> $DIR/shadow.rs:21:13 | diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index 7697cbd1c64..bef497c33a0 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -4,7 +4,7 @@ error: boolean short circuit operator in statement may be clearer using an expli 7 | f() && g(); | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` | - = note: `-D short-circuit-statement` implied by `-D warnings` + = note: `-D clippy::short-circuit-statement` implied by `-D warnings` error: boolean short circuit operator in statement may be clearer using an explicit test --> $DIR/short_circuit_statement.rs:8:5 diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 044b4909a37..78355612717 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,123 +1,123 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:5:13 + --> $DIR/single_char_pattern.rs:7:13 | -5 | x.split("x"); +7 | x.split("x"); | ^^^ help: try using a char instead: `'x'` | - = note: `-D single-char-pattern` implied by `-D warnings` + = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:22:16 + --> $DIR/single_char_pattern.rs:24:16 | -22 | x.contains("x"); +24 | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:23:19 + --> $DIR/single_char_pattern.rs:25:19 | -23 | x.starts_with("x"); +25 | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:24:17 + --> $DIR/single_char_pattern.rs:26:17 | -24 | x.ends_with("x"); +26 | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:25:12 + --> $DIR/single_char_pattern.rs:27:12 | -25 | x.find("x"); +27 | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:26:13 + --> $DIR/single_char_pattern.rs:28:13 | -26 | x.rfind("x"); +28 | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:27:14 + --> $DIR/single_char_pattern.rs:29:14 | -27 | x.rsplit("x"); +29 | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:28:24 + --> $DIR/single_char_pattern.rs:30:24 | -28 | x.split_terminator("x"); +30 | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:29:25 + --> $DIR/single_char_pattern.rs:31:25 | -29 | x.rsplit_terminator("x"); +31 | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:30:17 + --> $DIR/single_char_pattern.rs:32:17 | -30 | x.splitn(0, "x"); +32 | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:31:18 + --> $DIR/single_char_pattern.rs:33:18 | -31 | x.rsplitn(0, "x"); +33 | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:32:15 + --> $DIR/single_char_pattern.rs:34:15 | -32 | x.matches("x"); +34 | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:16 + --> $DIR/single_char_pattern.rs:35:16 | -33 | x.rmatches("x"); +35 | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:21 + --> $DIR/single_char_pattern.rs:36:21 | -34 | x.match_indices("x"); +36 | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:22 + --> $DIR/single_char_pattern.rs:37:22 | -35 | x.rmatch_indices("x"); +37 | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:25 + --> $DIR/single_char_pattern.rs:38:25 | -36 | x.trim_left_matches("x"); +38 | x.trim_left_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:26 + --> $DIR/single_char_pattern.rs:39:26 | -37 | x.trim_right_matches("x"); +39 | x.trim_right_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:13 + --> $DIR/single_char_pattern.rs:41:13 | -39 | x.split("/n"); +41 | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:44:31 + --> $DIR/single_char_pattern.rs:46:31 | -44 | x.replace(";", ",").split(","); // issue #2978 +46 | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:19 + --> $DIR/single_char_pattern.rs:47:19 | -45 | x.starts_with("/x03"); // issue #2996 +47 | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` error: aborting due to 20 previous errors diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index d77211bc126..20d8fed25fd 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,48 +1,48 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:9:5 + --> $DIR/single_match.rs:11:5 | -9 | / match x { -10 | | Some(y) => { println!("{:?}", y); } -11 | | _ => () -12 | | }; +11 | / match x { +12 | | Some(y) => { println!("{:?}", y); } +13 | | _ => () +14 | | }; | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y); }` | - = note: `-D single-match` implied by `-D warnings` + = note: `-D clippy::single-match` implied by `-D warnings` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:15:5 + --> $DIR/single_match.rs:17:5 | -15 | / match z { -16 | | (2...3, 7...9) => dummy(), -17 | | _ => {} -18 | | }; +17 | / match z { +18 | | (2...3, 7...9) => dummy(), +19 | | _ => {} +20 | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:41:5 + --> $DIR/single_match.rs:43:5 | -41 | / match x { -42 | | Some(y) => dummy(), -43 | | None => () -44 | | }; +43 | / match x { +44 | | Some(y) => dummy(), +45 | | None => () +46 | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:46:5 + --> $DIR/single_match.rs:48:5 | -46 | / match y { -47 | | Ok(y) => dummy(), -48 | | Err(..) => () -49 | | }; +48 | / match y { +49 | | Ok(y) => dummy(), +50 | | Err(..) => () +51 | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:53:5 + --> $DIR/single_match.rs:55:5 | -53 | / match c { -54 | | Cow::Borrowed(..) => dummy(), -55 | | Cow::Owned(..) => (), -56 | | }; +55 | / match c { +56 | | Cow::Borrowed(..) => dummy(), +57 | | Cow::Owned(..) => (), +58 | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: aborting due to 5 previous errors diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index 7d73f201b69..b3fb444b562 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,77 +1,77 @@ error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:7:5 + --> $DIR/starts_ends_with.rs:9:5 | -7 | "".chars().next() == Some(' '); +9 | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | - = note: `-D chars-next-cmp` implied by `-D warnings` + = note: `-D clippy::chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:8:5 - | -8 | Some(' ') != "".chars().next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` + --> $DIR/starts_ends_with.rs:10:5 + | +10 | Some(' ') != "".chars().next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:13:8 + --> $DIR/starts_ends_with.rs:15:8 | -13 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +15 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:16:8 + --> $DIR/starts_ends_with.rs:18:8 | -16 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +18 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | - = note: `-D chars-last-cmp` implied by `-D warnings` + = note: `-D clippy::chars-last-cmp` implied by `-D warnings` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:19:8 + --> $DIR/starts_ends_with.rs:21:8 | -19 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +21 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:22:8 + --> $DIR/starts_ends_with.rs:24:8 | -22 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +24 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:25:8 + --> $DIR/starts_ends_with.rs:27:8 | -25 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +27 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:28:8 + --> $DIR/starts_ends_with.rs:30:8 | -28 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +30 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:35:5 + --> $DIR/starts_ends_with.rs:37:5 | -35 | "".chars().last() == Some(' '); +37 | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:36:5 + --> $DIR/starts_ends_with.rs:38:5 | -36 | Some(' ') != "".chars().last(); +38 | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:37:5 + --> $DIR/starts_ends_with.rs:39:5 | -37 | "".chars().next_back() == Some(' '); +39 | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:38:5 + --> $DIR/starts_ends_with.rs:40:5 | -38 | Some(' ') != "".chars().next_back(); +40 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: aborting due to 12 previous errors diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 4be2037ad31..32e3482699c 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -4,7 +4,7 @@ error: calling `.extend(_.chars())` 16 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | - = note: `-D string-extend-chars` implied by `-D warnings` + = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:19:5 diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index d098ce9df5e..258920e2652 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -4,7 +4,7 @@ error: manual implementation of an assign operation 10 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` | - = note: `-D assign-op-pattern` implied by `-D warnings` + = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead --> $DIR/strings.rs:10:13 @@ -12,7 +12,7 @@ error: you added something to a string. Consider using `String::push_str()` inst 10 | x = x + "."; | ^^^^^^^ | - = note: `-D string-add` implied by `-D warnings` + = note: `-D clippy::string-add` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead --> $DIR/strings.rs:14:13 @@ -26,7 +26,7 @@ error: you assigned the result of adding something to this string. Consider usin 24 | x = x + "."; | ^^^^^^^^^^^ | - = note: `-D string-add-assign` implied by `-D warnings` + = note: `-D clippy::string-add-assign` implied by `-D warnings` error: manual implementation of an assign operation --> $DIR/strings.rs:24:9 @@ -58,7 +58,7 @@ error: calling `as_bytes()` on a string literal 50 | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` | - = note: `-D string-lit-as-bytes` implied by `-D warnings` + = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal --> $DIR/strings.rs:55:18 diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index 25e857991b8..3cc0be39567 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -4,7 +4,7 @@ error: item name starts with its containing module's name 8 | pub fn foo_bar() {} | ^^^^^^^^^^^^^^^^^^^ | - = note: `-D stutter` implied by `-D warnings` + = note: `-D clippy::stutter` implied by `-D warnings` error: item name ends with its containing module's name --> $DIR/stutter.rs:9:5 diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 8130b1cb31a..0f396c3a560 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -4,7 +4,7 @@ error: Suspicious use of binary operator in `Add` impl 14 | Foo(self.0 - other.0) | ^ | - = note: `-D suspicious-arithmetic-impl` implied by `-D warnings` + = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` error: Suspicious use of binary operator in `AddAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:20:23 @@ -12,7 +12,7 @@ error: Suspicious use of binary operator in `AddAssign` impl 20 | *self = *self - other; | ^ | - = note: #[deny(suspicious_op_assign_impl)] on by default + = note: #[deny(clippy::suspicious_op_assign_impl)] on by default error: aborting due to 2 previous errors diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index a01ec375e63..67d4fd8a14b 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -6,7 +6,7 @@ error: this looks like you are swapping elements of `foo` manually 13 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` | - = note: `-D manual-swap` implied by `-D warnings` + = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually --> $DIR/swap.rs:20:5 @@ -53,7 +53,7 @@ error: this looks like you are trying to swap `a` and `b` 45 | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | - = note: `-D almost-swapped` implied by `-D warnings` + = note: `-D clippy::almost-swapped` implied by `-D warnings` = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `c.0` and `a` diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 979720c914d..38379d8bd20 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -4,7 +4,7 @@ error: assignment to temporary 29 | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D temporary-assignment` implied by `-D warnings` + = note: `-D clippy::temporary-assignment` implied by `-D warnings` error: assignment to temporary --> $DIR/temporary_assignment.rs:30:5 diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index f360e85329f..f3fe563f294 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -4,7 +4,7 @@ error: `ref` directly on a function argument is ignored. Consider using a refere 7 | fn the_answer(ref mut x: u8) { | ^^^^^^^^^ | - = note: `-D toplevel-ref-arg` implied by `-D warnings` + = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead --> $DIR/toplevel_ref_arg.rs:18:7 diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 47b46be9ba8..477f42c28f4 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -4,7 +4,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` 7 | let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` | - = note: `-D verbose-bit-mask` implied by `-D warnings` + = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:8:13 diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index abed5065c0a..4340c16b97c 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -4,7 +4,7 @@ error: transmute from a type (`&'a T`) to itself 22 | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D useless-transmute` implied by `-D warnings` + = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer --> $DIR/transmute.rs:26:23 @@ -30,7 +30,7 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) 35 | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` | - = note: `-D transmute-ptr-to-ref` implied by `-D warnings` + = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) --> $DIR/transmute.rs:38:21 @@ -134,7 +134,7 @@ error: transmute from a type (`*const Usize`) to the type that it points to (`Us 111 | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D crosspointer-transmute` implied by `-D warnings` + = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) --> $DIR/transmute.rs:113:24 @@ -160,7 +160,7 @@ error: transmute from a `u32` to a `char` 123 | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` | - = note: `-D transmute-int-to-char` implied by `-D warnings` + = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` --> $DIR/transmute.rs:124:28 @@ -174,7 +174,7 @@ error: transmute from a `u8` to a `bool` 129 | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` | - = note: `-D transmute-int-to-bool` implied by `-D warnings` + = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` --> $DIR/transmute.rs:134:27 @@ -182,7 +182,7 @@ error: transmute from a `u32` to a `f32` 134 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` | - = note: `-D transmute-int-to-float` implied by `-D warnings` + = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` --> $DIR/transmute.rs:135:27 @@ -196,7 +196,7 @@ error: transmute from a `&[u8]` to a `&str` 139 | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` | - = note: `-D transmute-bytes-to-str` implied by `-D warnings` + = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` --> $DIR/transmute.rs:140:32 @@ -210,7 +210,7 @@ error: transmute from a pointer to a pointer 172 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | - = note: `-D transmute-ptr-to-ptr` implied by `-D warnings` + = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer --> $DIR/transmute.rs:173:27 diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index 3a6a6e73f57..e86908655a8 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,15 +1,15 @@ error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:9:31 - | -9 | let _: *const usize = std::mem::transmute(6.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D wrong-transmute` implied by `-D warnings` + --> $DIR/transmute_64bit.rs:11:31 + | +11 | let _: *const usize = std::mem::transmute(6.0f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::wrong-transmute` implied by `-D warnings` error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:11:29 + --> $DIR/transmute_64bit.rs:13:29 | -11 | let _: *mut usize = std::mem::transmute(6.0f64); +13 | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 757b6b4c9a9..2db627dd9b1 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:40:11 + --> $DIR/trivially_copy_pass_by_ref.rs:42:11 | -40 | fn bad(x: &u32, y: &Foo, z: &Baz) { +42 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | - = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` + = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:40:20 + --> $DIR/trivially_copy_pass_by_ref.rs:42:20 | -40 | fn bad(x: &u32, y: &Foo, z: &Baz) { +42 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:40:29 + --> $DIR/trivially_copy_pass_by_ref.rs:42:29 | -40 | fn bad(x: &u32, y: &Foo, z: &Baz) { +42 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:12 + --> $DIR/trivially_copy_pass_by_ref.rs:52:12 | -50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:22 + --> $DIR/trivially_copy_pass_by_ref.rs:52:22 | -50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:31 + --> $DIR/trivially_copy_pass_by_ref.rs:52:31 | -50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:40 + --> $DIR/trivially_copy_pass_by_ref.rs:52:40 | -50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:53:16 + --> $DIR/trivially_copy_pass_by_ref.rs:55:16 | -53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:53:25 + --> $DIR/trivially_copy_pass_by_ref.rs:55:25 | -53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:53:34 + --> $DIR/trivially_copy_pass_by_ref.rs:55:34 | -53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:16 + --> $DIR/trivially_copy_pass_by_ref.rs:69:16 | -67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:25 + --> $DIR/trivially_copy_pass_by_ref.rs:69:25 | -67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:34 + --> $DIR/trivially_copy_pass_by_ref.rs:69:34 | -67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index b41bff7a9b0..e2f75162867 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -4,7 +4,7 @@ error: casting i32 to i64 may become silently lossy if types change 9 | let c_i64 : i64 = c as i64; | ^^^^^^^^ help: try: `i64::from(c)` | - = note: `-D cast-lossless` implied by `-D warnings` + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr index bbdf4ce2e70..a06809b9bfd 100644 --- a/tests/ui/types_fn_to_int.stderr +++ b/tests/ui/types_fn_to_int.stderr @@ -4,7 +4,7 @@ error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function 12 | let _y = x as i32; | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` | - = note: #[deny(fn_to_numeric_cast_with_truncation)] on by default + = note: #[deny(clippy::fn_to_numeric_cast_with_truncation)] on by default error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. --> $DIR/types_fn_to_int.rs:13:15 @@ -36,7 +36,7 @@ error: casting a `fn() -> i32 {bar}` to `u64` is bad style. 17 | let _y = bar as u64; | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` | - = note: `-D fn-to-numeric-cast` implied by `-D warnings` + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` error: casting a `fn(usize) -> Foo {Foo::A}` to `i128` is bad style. --> $DIR/types_fn_to_int.rs:18:14 diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 9e99a44bb60..b0e567fc212 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -4,7 +4,7 @@ error: zero-width space detected 6 | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D zero-width-space` implied by `-D warnings` + = note: `-D clippy::zero-width-space` implied by `-D warnings` = help: Consider replacing the string with: ""Here >/u{200B}< is a ZWS, and /u{200B}another"" @@ -14,7 +14,7 @@ error: non-nfc unicode sequence detected 12 | print!("̀àh?"); | ^^^^^ | - = note: `-D unicode-not-nfc` implied by `-D warnings` + = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` = help: Consider replacing the string with: ""̀àh?"" @@ -24,7 +24,7 @@ error: literal non-ASCII character detected 18 | print!("Üben!"); | ^^^^^^^ | - = note: `-D non-ascii-literal` implied by `-D warnings` + = note: `-D clippy::non-ascii-literal` implied by `-D warnings` = help: Consider replacing the string with: ""/u{dc}ben!"" diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index ca48f39263b..e1845c0c0ea 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,67 +1,67 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:23:9 + --> $DIR/unit_arg.rs:25:9 | -23 | foo({}); +25 | foo({}); | ^^ | - = note: `-D unit-arg` implied by `-D warnings` + = note: `-D clippy::unit-arg` implied by `-D warnings` help: if you intended to pass a unit value, use a unit literal instead | -23 | foo(()); +25 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:24:9 + --> $DIR/unit_arg.rs:26:9 | -24 | foo({ 1; }); +26 | foo({ 1; }); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -24 | foo(()); +26 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:25:9 + --> $DIR/unit_arg.rs:27:9 | -25 | foo(foo(1)); +27 | foo(foo(1)); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -25 | foo(()); +27 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:26:9 + --> $DIR/unit_arg.rs:28:9 | -26 | foo({ +28 | foo({ | _________^ -27 | | foo(1); -28 | | foo(2); -29 | | }); +29 | | foo(1); +30 | | foo(2); +31 | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -26 | foo(()); +28 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:30:10 + --> $DIR/unit_arg.rs:32:10 | -30 | foo3({}, 2, 2); +32 | foo3({}, 2, 2); | ^^ help: if you intended to pass a unit value, use a unit literal instead | -30 | foo3((), 2, 2); +32 | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:32:11 + --> $DIR/unit_arg.rs:34:11 | -32 | b.bar({ 1; }); +34 | b.bar({ 1; }); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -32 | b.bar(()); +34 | b.bar(()); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 51ad3fca947..a85eb32841f 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -4,7 +4,7 @@ error: ==-comparison of unit values detected. This will always be true 16 | if { true; } == { false; } { | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D unit-cmp` implied by `-D warnings` + = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false --> $DIR/unit_cmp.rs:19:8 diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 3c1ce908022..b2985f84b04 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,84 +1,84 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:16:5 + --> $DIR/unnecessary_clone.rs:18:5 | -16 | 42.clone(); +18 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | - = note: `-D clone-on-copy` implied by `-D warnings` + = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:20:5 + --> $DIR/unnecessary_clone.rs:22:5 | -20 | (&42).clone(); +22 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:30:5 + --> $DIR/unnecessary_clone.rs:32:5 | -30 | rc.clone(); +32 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | - = note: `-D clone-on-ref-ptr` implied by `-D warnings` + = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:33:5 + --> $DIR/unnecessary_clone.rs:35:5 | -33 | arc.clone(); +35 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:36:5 + --> $DIR/unnecessary_clone.rs:38:5 | -36 | rcweak.clone(); +38 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:39:5 + --> $DIR/unnecessary_clone.rs:41:5 | -39 | arc_weak.clone(); +41 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:43:29 + --> $DIR/unnecessary_clone.rs:45:29 | -43 | let _: Arc = x.clone(); +45 | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:47:5 + --> $DIR/unnecessary_clone.rs:49:5 | -47 | t.clone(); +49 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:49:5 + --> $DIR/unnecessary_clone.rs:51:5 | -49 | Some(t).clone(); +51 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:55:22 + --> $DIR/unnecessary_clone.rs:57:22 | -55 | let z: &Vec<_> = y.clone(); +57 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | - = note: #[deny(clone_double_ref)] on by default + = note: #[deny(clippy::clone_double_ref)] on by default help: try dereferencing it | -55 | let z: &Vec<_> = &(*y).clone(); +57 | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -55 | let z: &Vec<_> = &std::vec::Vec::clone(y); +57 | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:62:27 + --> $DIR/unnecessary_clone.rs:64:27 | -62 | let v2 : Vec = v.iter().cloned().collect(); +64 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D iter-cloned-collect` implied by `-D warnings` + = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: aborting due to 11 previous errors diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 8bc4b8244bd..e72f671b67e 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -4,7 +4,7 @@ error: this `.fold` can be written more succinctly using another method 4 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | - = note: `-D unnecessary-fold` implied by `-D warnings` + = note: `-D clippy::unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:6:19 diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index ffc65084afa..d27ba26f349 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,14 +1,14 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:11:17 + --> $DIR/unnecessary_ref.rs:13:17 | -11 | let inner = (&outer).inner; +13 | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer.inner` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:8:8 + --> $DIR/unnecessary_ref.rs:10:8 | -8 | #[deny(ref_in_deref)] - | ^^^^^^^^^^^^ +10 | #[deny(clippy::ref_in_deref)] + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 7e4c3a6cb9c..40aa4f524fe 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -4,7 +4,7 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead 17 | Foo { a: _, b: 0, .. } => {} | ^^^^ | - = note: `-D unneeded-field-pattern` implied by `-D warnings` + = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` = help: Try with `Foo { b: 0, .. }` error: All the struct fields are matched to a wildcard pattern, consider using `..`. diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index cffcad1eef7..516b6ccc595 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -4,7 +4,7 @@ error: long literal lacking separators 7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | - = note: `-D unreadable-literal` implied by `-D warnings` + = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators --> $DIR/unreadable_literal.rs:7:30 diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 93f2ddd533f..2b014ca5863 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -4,7 +4,7 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell 7 | use std::cell::{UnsafeCell as TotallySafeCell}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D unsafe-removed-from-name` implied by `-D warnings` + = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` --> $DIR/unsafe_removed_from_name.rs:9:1 diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 5114d375fff..48a5751579c 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -4,7 +4,7 @@ error: handle written amount returned or use `Write::write_all` instead 11 | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D unused-io-amount` implied by `-D warnings` + = note: `-D clippy::unused-io-amount` implied by `-D warnings` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index 19c91e2a6a3..d35ca41a1a1 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -6,7 +6,7 @@ error: unused label `'label` 10 | | } | |_____^ | - = note: `-D unused-label` implied by `-D warnings` + = note: `-D clippy::unused-label` implied by `-D warnings` error: unused label `'a` --> $DIR/unused_labels.rs:21:5 diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index f01dfda7013..4cad611c2a1 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -4,7 +4,7 @@ error: this lifetime isn't used in the function definition 16 | fn unused_lt<'a>(x: u8) { | ^^ | - = note: `-D extra-unused-lifetimes` implied by `-D warnings` + = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition --> $DIR/unused_lt.rs:20:25 diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index e4704dd0e43..42c72090ca5 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,16 +1,16 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:4:47 + --> $DIR/unwrap_or.rs:5:47 | -4 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); +5 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` | - = note: `-D or-fun-call` implied by `-D warnings` + = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:9:10 - | -9 | .unwrap_or("Fail".to_string()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` + --> $DIR/unwrap_or.rs:10:10 + | +10 | .unwrap_or("Fail".to_string()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 89936101252..cf673e166d8 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,123 +1,123 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:11:21 + --> $DIR/use_self.rs:13:21 | -11 | fn new() -> Foo { +13 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | - = note: `-D use-self` implied by `-D warnings` + = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:12:13 + --> $DIR/use_self.rs:14:13 | -12 | Foo {} +14 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:22 + --> $DIR/use_self.rs:16:22 | -14 | fn test() -> Foo { +16 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:15:13 + --> $DIR/use_self.rs:17:13 | -15 | Foo::new() +17 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:20:25 + --> $DIR/use_self.rs:22:25 | -20 | fn default() -> Foo { +22 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:21:13 + --> $DIR/use_self.rs:23:13 | -21 | Foo::new() +23 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:84:22 + --> $DIR/use_self.rs:86:22 | -84 | fn refs(p1: &Bad) -> &Bad { +86 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:84:31 + --> $DIR/use_self.rs:86:31 | -84 | fn refs(p1: &Bad) -> &Bad { +86 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:88:37 + --> $DIR/use_self.rs:90:37 | -88 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { +90 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:88:53 + --> $DIR/use_self.rs:90:53 | -88 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { +90 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:92:30 + --> $DIR/use_self.rs:94:30 | -92 | fn mut_refs(p1: &mut Bad) -> &mut Bad { +94 | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:92:43 + --> $DIR/use_self.rs:94:43 | -92 | fn mut_refs(p1: &mut Bad) -> &mut Bad { +94 | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:28 + --> $DIR/use_self.rs:98:28 | -96 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +98 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:46 + --> $DIR/use_self.rs:98:46 | -96 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +98 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:20 - | -99 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:101:20 + | +101 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:28 - | -99 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:101:28 + | +101 | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:13 + --> $DIR/use_self.rs:102:13 | -100 | Bad::default() +102 | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:105:23 + --> $DIR/use_self.rs:107:23 | -105 | type Output = Bad; +107 | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:107:27 + --> $DIR/use_self.rs:109:27 | -107 | fn mul(self, rhs: Bad) -> Bad { +109 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:107:35 + --> $DIR/use_self.rs:109:35 | -107 | fn mul(self, rhs: Bad) -> Bad { +109 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: aborting due to 20 previous errors diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 712f81c1b6f..a1bb57a50a5 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -4,7 +4,7 @@ error: used binding `_foo` which is prefixed with an underscore. A leading under 17 | _foo + 1 | ^^^^ | - = note: `-D used-underscore-binding` implied by `-D warnings` + = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:22:20 diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 875d830a353..6247fb27a79 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,73 +1,73 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:31:18 + --> $DIR/useless_asref.rs:33:18 | -31 | foo_rstr(rstr.as_ref()); +33 | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here - --> $DIR/useless_asref.rs:1:9 + --> $DIR/useless_asref.rs:3:9 | -1 | #![deny(useless_asref)] - | ^^^^^^^^^^^^^ +3 | #![deny(clippy::useless_asref)] + | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:33:20 + --> $DIR/useless_asref.rs:35:20 | -33 | foo_rslice(rslice.as_ref()); +35 | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:37:21 + --> $DIR/useless_asref.rs:39:21 | -37 | foo_mrslice(mrslice.as_mut()); +39 | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:39:20 + --> $DIR/useless_asref.rs:41:20 | -39 | foo_rslice(mrslice.as_ref()); +41 | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:46:20 + --> $DIR/useless_asref.rs:48:20 | -46 | foo_rslice(rrrrrslice.as_ref()); +48 | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:48:18 + --> $DIR/useless_asref.rs:50:18 | -48 | foo_rstr(rrrrrstr.as_ref()); +50 | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:53:21 + --> $DIR/useless_asref.rs:55:21 | -53 | foo_mrslice(mrrrrrslice.as_mut()); +55 | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:55:20 + --> $DIR/useless_asref.rs:57:20 | -55 | foo_rslice(mrrrrrslice.as_ref()); +57 | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:58:16 + --> $DIR/useless_asref.rs:60:16 | -58 | foo_rrrrmr((&&&&MoreRef).as_ref()); +60 | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:104:13 + --> $DIR/useless_asref.rs:106:13 | -104 | foo_mrt(mrt.as_mut()); +106 | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:106:12 + --> $DIR/useless_asref.rs:108:12 | -106 | foo_rt(mrt.as_ref()); +108 | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` error: aborting due to 11 previous errors diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 84b81e56107..59f1aaffb3f 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -4,7 +4,7 @@ error: useless lint attribute 5 | #[allow(dead_code, unused_extern_crates)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code, unused_extern_crates)]` | - = note: `-D useless-attribute` implied by `-D warnings` + = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute --> $DIR/useless_attribute.rs:6:1 diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 6a47eb5b064..b9541e58c77 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -4,7 +4,7 @@ error: useless use of `vec!` 24 | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` | - = note: `-D useless-vec` implied by `-D warnings` + = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` --> $DIR/vec.rs:27:14 diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index d2b50b61e90..cc309e37946 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -10,7 +10,7 @@ error: this loop could be written as a `while let` loop 15 | | } | |_____^ help: try: `while let Some(_x) = y { .. }` | - = note: `-D while-let-loop` implied by `-D warnings` + = note: `-D clippy::while-let-loop` implied by `-D warnings` error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:22:5 @@ -65,7 +65,7 @@ error: this loop could be written as a `for` loop 68 | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` | - = note: `-D while-let-on-iterator` implied by `-D warnings` + = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop --> $DIR/while_loop.rs:73:25 @@ -97,7 +97,7 @@ error: empty `loop {}` detected. You may want to either use `panic!()` or add `s 123 | loop {} | ^^^^^^^ | - = note: `-D empty-loop` implied by `-D warnings` + = note: `-D clippy::empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop --> $DIR/while_loop.rs:183:29 diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index d2e8ca94ed8..644f6f15b42 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,87 +1,87 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:27:79 + --> $DIR/write_literal.rs:29:79 | -27 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); +29 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | - = note: `-D write-literal` implied by `-D warnings` + = note: `-D clippy::write-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/write_literal.rs:28:32 + --> $DIR/write_literal.rs:30:32 | -28 | write!(&mut v, "Hello {}", "world"); +30 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:29:44 + --> $DIR/write_literal.rs:31:44 | -29 | writeln!(&mut v, "Hello {} {}", world, "world"); +31 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:30:34 + --> $DIR/write_literal.rs:32:34 | -30 | writeln!(&mut v, "Hello {}", "world"); +32 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:31:38 + --> $DIR/write_literal.rs:33:38 | -31 | writeln!(&mut v, "10 / 4 is {}", 2.5); +33 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:32:36 + --> $DIR/write_literal.rs:34:36 | -32 | writeln!(&mut v, "2 + 1 = {}", 3); +34 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/write_literal.rs:37:33 + --> $DIR/write_literal.rs:39:33 | -37 | writeln!(&mut v, "{0} {1}", "hello", "world"); +39 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:37:42 + --> $DIR/write_literal.rs:39:42 | -37 | writeln!(&mut v, "{0} {1}", "hello", "world"); +39 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:38:33 + --> $DIR/write_literal.rs:40:33 | -38 | writeln!(&mut v, "{1} {0}", "hello", "world"); +40 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:38:42 + --> $DIR/write_literal.rs:40:42 | -38 | writeln!(&mut v, "{1} {0}", "hello", "world"); +40 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:41 + --> $DIR/write_literal.rs:43:41 | -41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +43 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:54 + --> $DIR/write_literal.rs:43:54 | -41 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +43 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:42:41 + --> $DIR/write_literal.rs:44:41 | -42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +44 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:42:54 + --> $DIR/write_literal.rs:44:54 | -42 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +44 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index a8a6039f3e1..c8617b4939a 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,27 +1,27 @@ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:10:5 + --> $DIR/write_with_newline.rs:12:5 | -10 | write!(&mut v, "Hello/n"); +12 | write!(&mut v, "Hello/n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D write-with-newline` implied by `-D warnings` + = note: `-D clippy::write-with-newline` implied by `-D warnings` error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:11:5 + --> $DIR/write_with_newline.rs:13:5 | -11 | write!(&mut v, "Hello {}/n", "world"); +13 | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:12:5 + --> $DIR/write_with_newline.rs:14:5 | -12 | write!(&mut v, "Hello {} {}/n", "world", "#2"); +14 | write!(&mut v, "Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:13:5 + --> $DIR/write_with_newline.rs:15:5 | -13 | write!(&mut v, "{}/n", 1265); +15 | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 7bb6350ecd2..ef1e9b3d36e 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,15 +1,15 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:9:5 - | -9 | writeln!(&mut v, ""); - | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` - | - = note: `-D writeln-empty-string` implied by `-D warnings` + --> $DIR/writeln_empty_string.rs:11:5 + | +11 | writeln!(&mut v, ""); + | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` + | + = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:12:5 + --> $DIR/writeln_empty_string.rs:14:5 | -12 | writeln!(&mut suggestion, ""); +14 | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` error: aborting due to 2 previous errors diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index 216fd0bb82b..4a6e5e0ab22 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -4,7 +4,7 @@ error: methods called `from_*` usually take no self; consider choosing a less am 21 | fn from_i32(self) {} | ^^^^ | - = note: `-D wrong-self-convention` implied by `-D warnings` + = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:27:21 diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index f1788fc9ec5..a5e86883d25 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -4,7 +4,7 @@ error: equal expressions as operands to `/` 7 | let nan = 0.0 / 0.0; | ^^^^^^^^^ | - = note: #[deny(eq_op)] on by default + = note: #[deny(clippy::eq_op)] on by default error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:7:15 @@ -12,7 +12,7 @@ error: constant division of 0.0 with 0.0 will always result in NaN 7 | let nan = 0.0 / 0.0; | ^^^^^^^^^ | - = note: `-D zero-divided-by-zero` implied by `-D warnings` + = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 5155dc401bd..b5e279eaa3a 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -4,7 +4,7 @@ error: `0 as *const _` detected. Consider using `ptr::null()` 6 | let x = 0 as *const usize; | ^^^^^^^^^^^^^^^^^ | - = note: `-D zero-ptr` implied by `-D warnings` + = note: `-D clippy::zero-ptr` implied by `-D warnings` error: `0 as *mut _` detected. Consider using `ptr::null_mut()` --> $DIR/zero_ptr.rs:7:13 -- cgit 1.4.1-3-g733a5 From ea43fedf9e111e904205ba5ebaa9ef8d9ff8f96c Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 30 Jul 2018 11:33:44 +0200 Subject: Adapt run-pass tests to the tool_lints --- tests/run-pass/associated-constant-ice.rs | 3 --- tests/run-pass/enum-glob-import-crate.rs | 4 ++-- tests/run-pass/ice-1588.rs | 4 ++-- tests/run-pass/ice-1969.rs | 4 ++-- tests/run-pass/ice-2499.rs | 4 +++- tests/run-pass/ice-2760.rs | 5 ++++- tests/run-pass/ice-2774.rs | 6 ++++-- tests/run-pass/ice-700.rs | 4 ++-- tests/run-pass/ice_exacte_size.rs | 4 +++- tests/run-pass/if_same_then_else.rs | 4 +++- tests/run-pass/match_same_arms_const.rs | 4 +++- tests/run-pass/mut_mut_macro.rs | 4 +++- tests/run-pass/needless_borrow_fp.rs | 4 +++- tests/run-pass/needless_lifetimes_impl_trait.rs | 3 ++- tests/run-pass/regressions.rs | 4 ++-- tests/run-pass/single-match-else.rs | 4 ++-- tests/run-pass/used_underscore_binding_macro.rs | 5 +++-- 17 files changed, 43 insertions(+), 27 deletions(-) diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs index 744de9bcf38..2c5c90683cc 100644 --- a/tests/run-pass/associated-constant-ice.rs +++ b/tests/run-pass/associated-constant-ice.rs @@ -1,6 +1,3 @@ - - - pub trait Trait { const CONSTANT: u8; } diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index 21ed2dbf991..6014558a184 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![deny(clippy)] +#![deny(clippy::all)] #![allow(unused_imports)] use std::*; diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index 780df523511..fcda3814e4a 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![allow(clippy)] +#![allow(clippy::all)] fn main() { match 1 { diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 29633982848..43d6bd8bfbc 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![allow(clippy)] +#![allow(clippy::all)] fn main() { } diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index 01deb7abfc1..c6793a78529 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -1,4 +1,6 @@ -#![allow(dead_code, char_lit_as_u8, needless_bool)] +#![feature(tool_lints)] + +#![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` /// diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index 01ca6d42a94..2e9c6d527c4 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -1,4 +1,7 @@ -#![allow(unused_variables, blacklisted_name, needless_pass_by_value, dead_code)] +#![feature(tool_lints)] + +#![allow(unused_variables, clippy::blacklisted_name, + clippy::needless_pass_by_value, dead_code)] // This should not compile-fail with: // diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index c6d9bb4a276..6b14a2b5e03 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] + use std::collections::HashSet; // See https://github.com/rust-lang-nursery/rust-clippy/issues/2774 @@ -10,7 +12,7 @@ pub struct Bar { #[derive(Eq, PartialEq, Debug, Hash)] pub struct Foo {} -#[allow(implicit_hasher)] +#[allow(clippy::implicit_hasher)] // This should not cause a 'cannot relate bound region' ICE pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { let mut foos = HashSet::new(); @@ -19,7 +21,7 @@ pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { ); } -#[allow(implicit_hasher)] +#[allow(clippy::implicit_hasher)] // Also this should not cause a 'cannot relate bound region' ICE pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { let mut foos = HashSet::new(); diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index a1e3a6756e9..3992af2c280 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![deny(clippy)] +#![deny(clippy::all)] fn core() {} diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index 914153c64ff..3d25aa50499 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -1,4 +1,6 @@ -#![deny(clippy)] +#![feature(tool_lints)] + +#![deny(clippy::all)] #[allow(dead_code)] struct Foo; diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs index eb14ce80756..b7536e25028 100644 --- a/tests/run-pass/if_same_then_else.rs +++ b/tests/run-pass/if_same_then_else.rs @@ -1,4 +1,6 @@ -#![deny(if_same_then_else)] +#![feature(tool_lints)] + +#![deny(clippy::if_same_then_else)] fn main() {} diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs index 08acc2bc4d8..59b939f3e01 100644 --- a/tests/run-pass/match_same_arms_const.rs +++ b/tests/run-pass/match_same_arms_const.rs @@ -1,4 +1,6 @@ -#![deny(match_same_arms)] +#![feature(tool_lints)] + +#![deny(clippy::match_same_arms)] const PRICE_OF_SWEETS: u32 = 5; const PRICE_OF_KINDNESS: u32 = 0; diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index 2b916c025d3..bfb9cfc7170 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -1,4 +1,6 @@ -#![deny(mut_mut, zero_ptr, cmp_nan)] +#![feature(tool_lints)] + +#![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] #![allow(dead_code)] // compiletest + extern crates doesn't work together diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs index 9dc508006ed..204968e48d0 100644 --- a/tests/run-pass/needless_borrow_fp.rs +++ b/tests/run-pass/needless_borrow_fp.rs @@ -1,4 +1,6 @@ -#[deny(clippy)] +#![feature(tool_lints)] + +#[deny(clippy::all)] #[derive(Debug)] pub enum Error { diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 700215baa64..f727b2547e3 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,5 +1,6 @@ +#![feature(tool_lints)] -#![deny(needless_lifetimes)] +#![deny(clippy::needless_lifetimes)] #![allow(dead_code)] trait Foo {} diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index d5e343c56c2..aa4e16d3949 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![allow(blacklisted_name)] +#![allow(clippy::blacklisted_name)] pub fn foo(bar: *const u8) { println!("{:#p}", bar); diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index b8fa7294dcd..379a98fc3ec 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -1,6 +1,6 @@ +#![feature(tool_lints)] - -#![warn(single_match_else)] +#![warn(clippy::single_match_else)] fn main() { let n = match (42, 43) { diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index c9c77257c0e..73f48a96e77 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -1,12 +1,13 @@ +#![feature(tool_lints)] - +#![allow(clippy::useless_attribute)] //issue #2910 #[macro_use] extern crate serde_derive; /// Test that we do not lint for unused underscores in a `MacroAttribute` /// expansion -#[deny(used_underscore_binding)] +#[deny(clippy::used_underscore_binding)] #[derive(Deserialize)] struct MacroAttributesTest { _foo: u32, -- cgit 1.4.1-3-g733a5 From cfd4c538d462f640013a6bb6b7f1663e82447e1f Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 1 Aug 2018 22:38:04 +0200 Subject: Adapt ui-toml-tests to the tool_lints --- tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs | 6 +++--- .../ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr | 2 +- tests/ui-toml/toml_trivially_copy/test.rs | 3 ++- tests/ui-toml/toml_trivially_copy/test.stderr | 10 +++++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs index 1f1a8ee91a1..fe533f521d0 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -1,10 +1,10 @@ - +#![feature(tool_lints)] #![allow(dead_code)] -#![allow(single_match)] +#![allow(clippy::single_match)] #![allow(unused_variables)] -#![warn(blacklisted_name)] +#![warn(clippy::blacklisted_name)] fn test(toto: ()) {} diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr index b2b0f26b140..4229b711b0d 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -4,7 +4,7 @@ error: use of a blacklisted/placeholder name `toto` 9 | fn test(toto: ()) {} | ^^^^ | - = note: `-D blacklisted-name` implied by `-D warnings` + = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `toto` --> $DIR/conf_french_blacklisted_name.rs:12:9 diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index bee092a5765..074ca064ab5 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,4 +1,5 @@ -#![allow(many_single_char_names)] +#![feature(tool_lints)] +#![allow(clippy::many_single_char_names)] #[derive(Copy, Clone)] struct Foo(u8); diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index 2d36c47c5da..cf2f15a68e6 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,15 +1,15 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:12:11 + --> $DIR/test.rs:13:11 | -12 | fn bad(x: &u16, y: &Foo) { +13 | fn bad(x: &u16, y: &Foo) { | ^^^^ help: consider passing by value instead: `u16` | - = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` + = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:12:20 + --> $DIR/test.rs:13:20 | -12 | fn bad(x: &u16, y: &Foo) { +13 | fn bad(x: &u16, y: &Foo) { | ^^^^ help: consider passing by value instead: `Foo` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From f3bb161f0e634f45ce1c189baaf0d3d6cc651cec Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 1 Aug 2018 22:48:41 +0200 Subject: Adapt codebase to the tool_lints --- clippy_lints/src/assign_ops.rs | 2 +- clippy_lints/src/booleans.rs | 6 +++--- clippy_lints/src/consts.rs | 3 +-- clippy_lints/src/cyclomatic_complexity.rs | 4 ++-- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/lib.rs | 5 +++-- clippy_lints/src/methods.rs | 4 ++-- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/comparisons.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/constants.rs | 2 +- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/sugg.rs | 6 ++---- src/driver.rs | 5 +++-- src/lib.rs | 3 ++- src/main.rs | 7 ++++--- 25 files changed, 39 insertions(+), 38 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 5a27f6a2c36..9a1808345a5 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { }, hir::ExprKind::Assign(ref assignee, ref e) => { if let hir::ExprKind::Binary(op, ref l, ref r) = e.node { - #[allow(cyclomatic_complexity)] + #[allow(clippy::cyclomatic_complexity)] let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { let ty = cx.tables.expr_ty(assignee); let rty = cx.tables.expr_ty(rhs); diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f867dc56c3c..3d3fa7b5e73 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } for (n, expr) in self.terminals.iter().enumerate() { if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { - #[allow(cast_possible_truncation)] + #[allow(clippy::cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } let negated = match e.node { @@ -150,14 +150,14 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { _ => continue, }; if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { - #[allow(cast_possible_truncation)] + #[allow(clippy::cast_possible_truncation)] return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); } } let n = self.terminals.len(); self.terminals.push(e); if n < 32 { - #[allow(cast_possible_truncation)] + #[allow(clippy::cast_possible_truncation)] Ok(Bool::Term(n as u8)) } else { Err("too many literals".to_owned()) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index ff189d6e893..b126215c049 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,5 +1,4 @@ -#![allow(cast_possible_truncation)] -#![allow(float_cmp)] +#![allow(clippy::float_cmp)] use rustc::lint::LateContext; use rustc::{span_bug, bug}; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 6195db7b482..c975e31cec9 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { } #[cfg(feature = "debugging")] -#[allow(too_many_arguments)] +#[allow(clippy::too_many_arguments)] fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) { span_bug!( span, @@ -200,7 +200,7 @@ fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: ); } #[cfg(not(feature = "debugging"))] -#[allow(too_many_arguments)] +#[allow(clippy::too_many_arguments)] fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) { if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) { cx.sess().span_note_without_error( diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 2db950b3365..4d603570ebe 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -86,7 +86,7 @@ impl<'a> Iterator for Parser<'a> { /// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we /// need to keep track of /// the spans but this function is inspired from the later. -#[allow(cast_possible_truncation)] +#[allow(clippy::cast_possible_truncation)] pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(usize, Span)>) { // one-line comments lose their prefix const ONELINERS: &[&str] = &["///!", "///", "//!", "//"]; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 3a7f884b784..0271fee8a3c 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -43,7 +43,7 @@ impl LintPass for UnportableVariant { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { - #[allow(cast_possible_truncation, cast_sign_loss)] + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 85b133cbd03..56b99aa9449 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -147,7 +147,7 @@ fn partial_rmatch(post: &str, name: &str) -> usize { } // FIXME: #600 -#[allow(while_let_on_iterator)] +#[allow(clippy::while_let_on_iterator)] fn check_variant( cx: &EarlyContext<'_>, threshold: u64, diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index de1b5b77e6e..b6b34204480 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => (cx.tcx.lang_items().ord_trait(), true), }; if let Some(trait_id) = trait_id { - #[allow(match_same_arms)] + #[allow(clippy::match_same_arms)] match (&left.node, &right.node) { // do not suggest to dereference literals (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {}, diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index bb3741088cf..052275d7a45 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } -#[allow(cast_possible_wrap)] +#[allow(clippy::cast_possible_wrap)] fn check(cx: &LateContext<'_, '_>, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { let check = match cx.tables.expr_ty(e).sty { diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index b640eff2c5d..f94461b75a5 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -53,7 +53,7 @@ enum Side { } impl IntPlusOne { - #[allow(cast_sign_loss)] + #[allow(clippy::cast_sign_loss)] fn check_lit(&self, lit: &Lit, target_value: i128) -> bool { if let LitKind::Int(value, ..) = lit.node { return value == (target_value as u128); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 32c3dca6357..f1a89c3d46b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -5,9 +5,10 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] -#![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)] +#![allow(unknown_lints, clippy::shadow_reuse, clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] +#![feature(tool_lints)] #![warn(rust_2018_idioms)] use toml; @@ -933,7 +934,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { // only exists to let the dogfood integration test works. // Don't run clippy as an executable directly -#[allow(dead_code, print_stdout)] +#[allow(dead_code, clippy::print_stdout)] fn main() { panic!("Please use the cargo-clippy executable"); } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 4f6cb64dd4f..f428a498b4d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -714,7 +714,7 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - #[allow(cyclomatic_complexity)] + #[allow(clippy::cyclomatic_complexity)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if in_macro(expr.span) { return; @@ -922,7 +922,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa } /// Check for `*or(foo())`. - #[allow(too_many_arguments)] + #[allow(clippy::too_many_arguments)] fn check_general_case( cx: &LateContext<'_, '_>, name: &str, diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 8df33b1e99a..93a83fe97ba 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -32,7 +32,7 @@ impl LintPass for NegMultiply { } } -#[allow(match_same_arms)] +#[allow(clippy::match_same_arms)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref l, ref r) = e.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 81842421fa3..400a06c061e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1525,7 +1525,7 @@ enum FullInt { } impl FullInt { - #[allow(cast_sign_loss)] + #[allow(clippy::cast_sign_loss)] fn cmp_s_u(s: i128, u: u128) -> Ordering { if s < 0 { Ordering::Less @@ -1744,7 +1744,7 @@ impl LintPass for ImplicitHasher { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { - #[allow(cast_possible_truncation)] + #[allow(clippy::cast_possible_truncation)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { use syntax_pos::BytePos; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index fe8123d288d..fb131b9086a 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -1,7 +1,7 @@ //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -#![allow(print_stdout, use_debug)] +#![allow(clippy::print_stdout, clippy::use_debug)] use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index 35f41d400ad..31e20f37e20 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -1,6 +1,6 @@ //! Utility functions about comparison operators. -#![deny(missing_docs_in_private_items)] +#![deny(clippy::missing_docs_in_private_items)] use rustc::hir::{BinOpKind, Expr}; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 1567bd9ffb6..47b71ae524f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -1,6 +1,6 @@ //! Read configurations files. -#![deny(missing_docs_in_private_items)] +#![deny(clippy::missing_docs_in_private_items)] use lazy_static::lazy_static; use std::{env, fmt, fs, io, path}; diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index f59716268a0..b63be9b86c8 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -1,6 +1,6 @@ //! This module contains some useful constants. -#![deny(missing_docs_in_private_items)] +#![deny(clippy::missing_docs_in_private_items)] /// List of the built-in types names. /// diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 65d58c4e55b..42b37568a99 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -1,7 +1,7 @@ //! This module contains functions for retrieve the original AST from lowered //! `hir`. -#![deny(missing_docs_in_private_items)] +#![deny(clippy::missing_docs_in_private_items)] use if_chain::if_chain; use rustc::{hir, ty}; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 30c6db977f7..93d73ca707e 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { }.hash(&mut self.s); } - #[allow(many_single_char_names)] + #[allow(clippy::many_single_char_names)] pub fn hash_expr(&mut self, e: &Expr) { if let Some(e) = constant_simple(self.cx, self.tables, e) { return e.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 12b4f55e432..b9a0435eb35 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -1,4 +1,4 @@ -#![allow(print_stdout, use_debug)] +#![allow(clippy::print_stdout, clippy::use_debug)] //! checks for attributes diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 3d587a72eec..4239b24d817 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -1,7 +1,5 @@ //! Contains utility functions to generate suggestions. -#![deny(missing_docs_in_private_items)] -// currently ignores lifetimes and generics -#![allow(use_self)] +#![deny(clippy::missing_docs_in_private_items)] use matches::matches; use rustc::hir; @@ -40,7 +38,7 @@ impl Display for Sugg<'_> { } } -#[allow(wrong_self_convention)] // ok, because of the function `as_ty` method +#[allow(clippy::wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. pub fn hir_opt(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { diff --git a/src/driver.rs b/src/driver.rs index 6854ccbbddc..6885c2aed2b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,13 +1,14 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] -#![allow(unknown_lints, missing_docs_in_private_items)] +#![feature(tool_lints)] +#![allow(unknown_lints, clippy::missing_docs_in_private_items)] use rustc_driver::{self, driver::CompileController, Compilation}; use rustc_plugin; use std::process::{exit, Command}; -#[allow(print_stdout)] +#[allow(clippy::print_stdout)] fn show_version() { println!(env!("CARGO_PKG_VERSION")); } diff --git a/src/lib.rs b/src/lib.rs index 1525dbda4ee..a7167ac10de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] +#![feature(tool_lints)] #![allow(unknown_lints)] -#![allow(missing_docs_in_private_items)] +#![allow(clippy::missing_docs_in_private_items)] #![warn(rust_2018_idioms)] use rustc_plugin::Registry; diff --git a/src/main.rs b/src/main.rs index 057a585e3d7..12c07f60a11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] -#![allow(unknown_lints, missing_docs_in_private_items)] +#![feature(tool_lints)] +#![allow(unknown_lints, clippy::missing_docs_in_private_items)] const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. @@ -28,12 +29,12 @@ it to allow or deny lints from the code, eg.: #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] "#; -#[allow(print_stdout)] +#[allow(clippy::print_stdout)] fn show_help() { println!("{}", CARGO_CLIPPY_HELP); } -#[allow(print_stdout)] +#[allow(clippy::print_stdout)] fn show_version() { println!(env!("CARGO_PKG_VERSION")); } -- cgit 1.4.1-3-g733a5 From d1f2f0c34cd6062bc43e88f11b06369e08af4af6 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Tue, 28 Aug 2018 11:27:17 +0200 Subject: Fix some rebase fallout --- clippy_lints/src/copy_iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 031b088bf9e..596e83bc539 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,7 +1,7 @@ use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use rustc::hir::{Item, ItemKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for types that implement `Copy` as well as /// `Iterator`. -- cgit 1.4.1-3-g733a5 From daa4f0ad34f79a91a6ae27fec6d56dd95e6feac2 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Tue, 28 Aug 2018 14:16:31 +0200 Subject: Implement backwards compatibility changes introduced by rust-lang/rust#53762 --- clippy_lints/src/lib.rs | 20 ++++++++++---------- src/driver.rs | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f1a89c3d46b..19d31d6fc0f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -412,7 +412,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box non_copy_const::NonCopyConst); reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); - reg.register_lint_group("clippy::restriction", vec![ + reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, @@ -435,7 +435,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { write::USE_DEBUG, ]); - reg.register_lint_group("clippy::pedantic", vec![ + reg.register_lint_group("clippy::pedantic", Some("clippy_pedantic"), vec![ attrs::INLINE_ALWAYS, copies::MATCH_SAME_ARMS, copy_iterator::COPY_ITERATOR, @@ -473,13 +473,13 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { use_self::USE_SELF, ]); - reg.register_lint_group("clippy::internal", vec![ + reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::LINT_WITHOUT_LINT_PASS, utils::internal_lints::DEFAULT_HASH_TYPES, ]); - reg.register_lint_group("clippy::all", vec![ + reg.register_lint_group("clippy::all", Some("clippy"), vec![ approx_const::APPROX_CONSTANT, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, @@ -694,7 +694,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); - reg.register_lint_group("clippy::style", vec![ + reg.register_lint_group("clippy::style", Some("clippy_style"), vec![ assign_ops::ASSIGN_OP_PATTERN, bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, @@ -778,7 +778,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { write::WRITELN_EMPTY_STRING, ]); - reg.register_lint_group("clippy::complexity", vec![ + reg.register_lint_group("clippy::complexity", Some("clippy_complexity"), vec![ assign_ops::MISREFACTORED_ASSIGN_OP, booleans::NONMINIMAL_BOOL, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, @@ -846,7 +846,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); - reg.register_lint_group("clippy::correctness", vec![ + reg.register_lint_group("clippy::correctness", Some("clippy_correctness"), vec![ approx_const::APPROX_CONSTANT, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, @@ -900,7 +900,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unused_io_amount::UNUSED_IO_AMOUNT, ]); - reg.register_lint_group("clippy::perf", vec![ + reg.register_lint_group("clippy::perf", Some("clippy_perf"), vec![ bytecount::NAIVE_BYTECOUNT, entry::MAP_ENTRY, escape::BOXED_LOCAL, @@ -918,11 +918,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { vec::USELESS_VEC, ]); - reg.register_lint_group("clippy::cargo", vec![ + reg.register_lint_group("clippy::cargo", Some("clippy_cargo"), vec![ multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, ]); - reg.register_lint_group("clippy::nursery", vec![ + reg.register_lint_group("clippy::nursery", Some("clippy_nursery"), vec![ attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, diff --git a/src/driver.rs b/src/driver.rs index 6885c2aed2b..26ff846177b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -119,8 +119,8 @@ pub fn main() { ls.register_late_pass(Some(sess), true, pass); } - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); + for (name, (to, deprecated_name)) in lint_groups { + ls.register_group(Some(sess), true, name, deprecated_name, to); } clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); -- cgit 1.4.1-3-g733a5 From 559b2f871f9907eab4be3cc58e118ff37a5468d0 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 30 Aug 2018 07:33:53 +0200 Subject: Remove git diffing part Because we no bump versions --- pre_publish.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pre_publish.sh b/pre_publish.sh index d8a9105c67e..3602f671e3d 100755 --- a/pre_publish.sh +++ b/pre_publish.sh @@ -4,13 +4,6 @@ set -e ./util/update_lints.py -git status --short | sort | grep -v README.md | grep -v helper.txt | sort > helper.txt - -# abort if the files differ -diff "publish.files" "helper.txt" - -rm helper.txt - # add all changed files git add . git commit -m "Bump the version" -- cgit 1.4.1-3-g733a5 From 679bc32f46c912bb91fa32c8d3977f6423a40f80 Mon Sep 17 00:00:00 2001 From: daubaris Date: Thu, 30 Aug 2018 20:06:13 +0300 Subject: range_plus_one suggestion should not remove braces fix --- clippy_lints/src/ranges.rs | 17 ++++++++++++++--- tests/ui/range_plus_minus_one.stderr | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index bef4532bbe5..d86f264adda 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::*; use syntax::ast::RangeLimits; use syntax::source_map::Spanned; -use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then}; +use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt}; use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::sugg::Sugg; @@ -49,7 +49,10 @@ declare_clippy_lint! { /// **Why is this bad?** The code is more readable with an inclusive range /// like `x..=y`. /// -/// **Known problems:** None. +/// **Known problems:** Will add unnecessary pair of parentheses when the +/// expression is not wrapped in a pair but starts with a opening parenthesis +/// and ends with a closing one. +/// I.e: let _ = (f()+1)..(f()+1) results in let _ = ((f()+1)..(f()+1)). /// /// **Example:** /// ```rust @@ -145,9 +148,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); - db.span_suggestion(expr.span, + if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { + if is_wrapped.starts_with("(") && is_wrapped.ends_with(")") { + db.span_suggestion(expr.span, + "use", + format!("({}..={})", start, end)); + } else { + db.span_suggestion(expr.span, "use", format!("{}..={}", start, end)); + } + } }, ); } diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 1990300ef90..9b51176b7ca 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -42,7 +42,7 @@ error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:28:13 | 28 | let _ = (f()+1)..(f()+1); - | ^^^^^^^^^^^^^^^^ help: use: `(f()+1)..=f()` + | ^^^^^^^^^^^^^^^^ help: use: `((f()+1)..=f())` error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From daacac6b9700bc581c0aced4c4f17b30aa01d15d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 31 Aug 2018 06:10:30 +0200 Subject: Revert "fix-3078: verify test case" This reverts commit 6256ad05bac1f708298f827fdfa7b54042961294. --- clippy_lints/src/non_expressive_names.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index f92538cd097..daccc4bde03 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -114,11 +114,9 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { _ => walk_pat(self, pat), } } - /* fn visit_mac(&mut self, _mac: &Mac) { // do not check macs } - */ } fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { -- cgit 1.4.1-3-g733a5 From 20dfaf7842f239b513e577542314ded27b5aacc3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 31 Aug 2018 00:34:48 -0700 Subject: declare_lint -> declare_tool_lint --- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 9f475473c61..250a11dab88 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,4 +1,4 @@ -use rustc::{declare_lint, hir, lint, lint_array}; +use rustc::{declare_tool_lint, hir, lint, lint_array}; use crate::utils; use std::fmt; -- cgit 1.4.1-3-g733a5 From 9abf6fca9c7288cb3bb99c0f7627f94b7930ee98 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 31 Aug 2018 00:38:27 -0700 Subject: Fix ptr offset tests --- tests/ui/ptr_offset_with_cast.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index 16bbf328b33..214a39cdc11 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -4,7 +4,7 @@ error: use of `offset` with a `usize` casted to an `isize` 10 | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` | - = note: `-D ptr-offset-with-cast` implied by `-D warnings` + = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` --> $DIR/ptr_offset_with_cast.rs:14:9 -- cgit 1.4.1-3-g733a5 From 19157c02cb25fa2e1e2995793f4b7da5ef107317 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 2 Sep 2018 09:38:25 +0200 Subject: Fix #3112 --- clippy_lints/src/eval_order_dependence.rs | 4 +++- clippy_lints/src/shadow.rs | 4 +++- clippy_lints/src/utils/author.rs | 12 +++++++++--- clippy_lints/src/utils/hir_utils.rs | 20 ++++++++++++++++++-- clippy_lints/src/utils/inspector.rs | 13 ++++++++++++- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 72abbddf141..e3ae5607645 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -109,7 +109,9 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { self.visit_expr(e); for arm in arms { if let Some(ref guard) = arm.guard { - self.visit_expr(guard); + match guard { + Guard::If(if_expr) => self.visit_expr(if_expr), + } } // make sure top level arm expressions aren't linted self.maybe_walk_expr(&*arm.body); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index d552c01679a..1191723ba62 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -339,7 +339,9 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: check_pat(cx, pat, Some(&**init), pat.span, bindings); // This is ugly, but needed to get the right type if let Some(ref guard) = arm.guard { - check_expr(cx, guard, bindings); + match guard { + Guard::If(if_expr) => check_expr(cx, if_expr, bindings), + } } check_expr(cx, &arm.body, bindings); bindings.truncate(len); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index fb131b9086a..e2c809c0c7c 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -345,9 +345,15 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(&arm.body); if let Some(ref guard) = arm.guard { let guard_pat = self.next("guard"); - println!(" if let Some(ref {}) = {}[{}].guard", guard_pat, arms_pat, i); - self.current = guard_pat; - self.visit_expr(guard); + println!(" if let Some(ref {}) = {}[{}].guard;", guard_pat, arms_pat, i); + match guard { + hir::Guard::If(ref if_expr) => { + let if_expr_pat = self.next("expr"); + println!(" if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat); + self.current = if_expr_pat; + self.visit_expr(if_expr); + } + } } println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len()); for (j, pat) in arm.pats.iter().enumerate() { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 93d73ca707e..939b4f595e4 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r)) && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) }) }, @@ -152,6 +152,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr) } + fn eq_guard(&mut self, left: &Guard, right: &Guard) -> bool { + match (left, right) { + (Guard::If(l), Guard::If(r)) => self.eq_expr(l, r), + } + } + fn eq_generic_arg(&mut self, left: &GenericArg, right: &GenericArg) -> bool { match (left, right) { (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => self.eq_lifetime(l_lt, r_lt), @@ -497,7 +503,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { for arm in arms { // TODO: arm.pat? if let Some(ref e) = arm.guard { - self.hash_expr(e); + self.hash_guard(e); } self.hash_expr(&arm.body); } @@ -637,4 +643,14 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { }, } } + + pub fn hash_guard(&mut self, g: &Guard) { + match g { + Guard::If(ref expr) => { + let c: fn(_) -> _ = Guard::If; + c.hash(&mut self.s); + self.hash_expr(expr); + } + } + } } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b9a0435eb35..56b76fdc7b0 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let Some(ref guard) = arm.guard { println!("guard:"); - print_expr(cx, guard, 1); + print_guard(cx, guard, 1); } println!("body:"); print_expr(cx, &arm.body, 1); @@ -515,3 +515,14 @@ fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) { }, } } + +fn print_guard(cx: &LateContext<'_, '_>, guard: &hir::Guard, indent: usize) { + let ind = " ".repeat(indent); + println!("{}+", ind); + match guard { + hir::Guard::If(expr) => { + println!("{}If", ind); + print_expr(cx, expr, indent + 1); + } + } +} -- cgit 1.4.1-3-g733a5 From 273e11fcafa07287c19b28794dfd28ae9b09e7ff Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Sep 2018 11:31:39 +0200 Subject: Trigger rebuild for AppVeyor (and fix grammar) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98f712c28d8..69dba57f460 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Be sure that Clippy was compiled with the same version of rustc that cargo invok ## Configuration -Some lints can be configured in a TOML file named with `clippy.toml` or `.clippy.toml`. It contains basic `variable = value` mapping eg. +Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable = value` mapping eg. ```toml blacklisted-names = ["toto", "tata", "titi"] -- cgit 1.4.1-3-g733a5 From 368223a341059c235e44ead210788c0047a4e6ad Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Sun, 2 Sep 2018 23:37:28 +0100 Subject: Use types rather than strings --- clippy_lints/src/default_trait_access.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index d3598a5bdaa..83b824631bc 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -48,13 +48,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { then { match qpath { QPath::Resolved(..) => { - if let ExprKind::Call(ref method, ref _args) = expr.node { - if format!("{:?}", method).contains(" as Default>") { - return + if_chain! { + // Detect and ignore ::default() because these calls do + // explicitly name the type. + if let ExprKind::Call(ref method, ref _args) = expr.node; + if let ExprKind::Path(ref p) = method.node; + if let QPath::Resolved(ref ty, ref _path) = p; + if ty.is_some(); + then { + return; } } - // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. let expr_ty = cx.tables.expr_ty(expr); -- cgit 1.4.1-3-g733a5 From 939d842ea1a8732c86cbaed76e5283358e831efa Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Sun, 2 Sep 2018 23:42:07 +0100 Subject: Simplify --- clippy_lints/src/default_trait_access.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 83b824631bc..c8c4d6cb873 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -53,8 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { // explicitly name the type. if let ExprKind::Call(ref method, ref _args) = expr.node; if let ExprKind::Path(ref p) = method.node; - if let QPath::Resolved(ref ty, ref _path) = p; - if ty.is_some(); + if let QPath::Resolved(Some(_ty), _path) = p; then { return; } -- cgit 1.4.1-3-g733a5 From d6f01f3a6c16d2fc350c36fb704ef68277ef426e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 3 Sep 2018 13:57:50 +1200 Subject: Make `Conf::default` available Fixes RLS --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index adc4f76fef9..d0e8def2786 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -171,7 +171,7 @@ pub mod write; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` -use crate::utils::conf::Conf; +pub use crate::utils::conf::Conf; mod reexport { crate use syntax::ast::{Name, NodeId}; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index a7e73d85cf0..8ec889a9fb6 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -65,7 +65,7 @@ macro_rules! define_Conf { mod helpers { use serde_derive::Deserialize; /// Type used to store lint configuration. - #[derive(Deserialize)] + #[derive(Default, Deserialize)] #[serde(rename_all="kebab-case", deny_unknown_fields)] pub struct Conf { $(#[$doc] #[serde(default=$rust_name_str)] #[serde(with=$rust_name_str)] -- cgit 1.4.1-3-g733a5 From 79d81ac3e78a0e2d48b973550933460b67f483f8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 3 Sep 2018 09:12:06 +0530 Subject: Remove dependence of ci on github token --- .travis.yml | 5 ++--- appveyor.yml | 13 +++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 08fdf2fb6d8..8d76e10983e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,13 +51,12 @@ matrix: script: - | - if [ -n "$GITHUB_TOKEN" ]; then rm rust-toolchain cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - travis_retry rustup-toolchain-install-master -f -n master --github-token $GITHUB_TOKEN + RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') + travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH rustup default master export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - fi - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh diff --git a/appveyor.yml b/appveyor.yml index 94f9500ab85..f50d1e88a24 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,12 +11,13 @@ install: - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - # https://support.microsoft.com/en-us/help/2524009/error-running-command-shell-scripts-that-include-parentheses - - if defined GITHUB_TOKEN del rust-toolchain - - if defined GITHUB_TOKEN (cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed") - - if defined GITHUB_TOKEN rustup-toolchain-install-master -f -n master --github-token %GITHUB_TOKEN% - - if defined GITHUB_TOKEN rustup default master - - if defined GITHUB_TOKEN set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin + - git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}' >rustc-hash.txt + - set /p RUSTC_HASH= Date: Mon, 3 Sep 2018 08:03:05 +0200 Subject: Fix clippy -> clippy::all warning in CI --- ci/base-tests.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index f7c3342fe38..dee709ab4eb 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -13,13 +13,13 @@ cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver rm ~/.cargo/bin/cargo-clippy # run clippy on its own codebase... -PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy +PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy::all # ... and some test directories -cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd .. -cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. -cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../.. -cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../.. +cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. +cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. +cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. +cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../../.. # test --manifest-path -PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy -cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../.. +PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all +cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. set +x -- cgit 1.4.1-3-g733a5 From 779988303a252d6d55de9ca45b281ebe1c091aa3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 3 Sep 2018 00:19:59 -0700 Subject: iter conservation efforts: save the endangered .iter() and .into_iter() Make explicit_iter_loop and explicit_into_iter_loop allow-by-default, so that people can turn them on if they want to enforce that style; avoid presenting them as *the* idiomatic Rust style, rather than just *a* style. --- clippy_lints/src/lib.rs | 6 ++---- clippy_lints/src/loops.rs | 8 ++++---- tests/ui/for_loop.stderr | 26 +++++++++++++------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d0e8def2786..c49a70afa6f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -449,6 +449,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, + loops::EXPLICIT_INTO_ITER_LOOP, + loops::EXPLICIT_ITER_LOOP, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, methods::OPTION_MAP_UNWRAP_OR, @@ -546,8 +548,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, - loops::EXPLICIT_INTO_ITER_LOOP, - loops::EXPLICIT_ITER_LOOP, loops::FOR_KV_MAP, loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, @@ -718,8 +718,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, - loops::EXPLICIT_INTO_ITER_LOOP, - loops::EXPLICIT_ITER_LOOP, loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 51e6327e728..d12b2619c62 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -85,7 +85,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub EXPLICIT_ITER_LOOP, - style, + pedantic, "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" } @@ -107,7 +107,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub EXPLICIT_INTO_ITER_LOOP, - style, + pedantic, "for-looping over `_.into_iter()` when `_` would do" } @@ -1209,7 +1209,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_ cx, EXPLICIT_ITER_LOOP, arg.span, - "it is more idiomatic to loop over references to containers instead of using explicit \ + "it is more concise to loop over references to containers instead of using explicit \ iteration methods", "to write this more concisely, try", format!("&{}{}", muta, object), @@ -1247,7 +1247,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex cx, EXPLICIT_INTO_ITER_LOOP, arg.span, - "it is more idiomatic to loop over containers instead of using explicit \ + "it is more concise to loop over containers instead of using explicit \ iteration methods`", "to write this more concisely, try", object.to_string(), diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 732dc2ab448..bab7bdc77a4 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -264,7 +264,7 @@ error: this range is empty so this for loop will never run 193 | for i in (5 + 2)..(8 - 1) { | ^^^^^^^^^^^^^^^^ -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:215:15 | 215 | for _v in vec.iter() {} @@ -272,13 +272,13 @@ error: it is more idiomatic to loop over references to containers instead of usi | = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:217:15 | 217 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` -error: it is more idiomatic to loop over containers instead of using explicit iteration methods` +error: it is more concise to loop over containers instead of using explicit iteration methods` --> $DIR/for_loop.rs:220:15 | 220 | for _v in out_vec.into_iter() {} @@ -286,61 +286,61 @@ error: it is more idiomatic to loop over containers instead of using explicit it | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:223:15 | 223 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:228:15 | 228 | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:232:15 | 232 | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:237:15 | 237 | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:240:15 | 240 | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:243:15 | 243 | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:246:15 | 246 | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:249:15 | 249 | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:252:15 | 252 | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods +error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:255:15 | 255 | for _v in bs.iter() {} -- cgit 1.4.1-3-g733a5 From 41392079564d2fa7afd982db42e38429665d9e5e Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 3 Sep 2018 10:52:42 +0200 Subject: Update travis integration tests to tool_lints `clippy_pedantic` -> `clippy::pedantic` `clippy_nursery` -> `clippy::nursery` --- ci/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index ac0d2f1614b..18b91f6eae0 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -9,7 +9,7 @@ cd checkout function check() { # run clippy on a project, try to be verbose and trigger as many warnings as possible for greater coverage - RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn -W clippy_pedantic -W clippy_nursery &> clippy_output + RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn -W clippy::pedantic -W clippy::nursery &> clippy_output cat clippy_output ! cat clippy_output | grep -q "internal compiler error\|query stack during panic" if [[ $? != 0 ]]; then -- cgit 1.4.1-3-g733a5 From b825578a4a1049f0a29205e35c61f0f47e3ae6dc Mon Sep 17 00:00:00 2001 From: daubaris Date: Mon, 3 Sep 2018 18:24:38 +0300 Subject: backticks and testcase --- clippy_lints/src/ranges.rs | 2 +- tests/ui/range_plus_minus_one.rs | 1 + tests/ui/range_plus_minus_one.stderr | 10 ++++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c69a0943b17..db2fbbad876 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -52,7 +52,7 @@ declare_clippy_lint! { /// **Known problems:** Will add unnecessary pair of parentheses when the /// expression is not wrapped in a pair but starts with a opening parenthesis /// and ends with a closing one. -/// I.e: let _ = (f()+1)..(f()+1) results in let _ = ((f()+1)..(f()+1)). +/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..(f()+1))`. /// /// **Example:** /// ```rust diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 12a1312de36..1ee3637f266 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -27,6 +27,7 @@ fn main() { let _ = ..11-1; let _ = ..=11-1; let _ = ..=(11-1); + let _ = (1..11+1); let _ = (f()+1)..(f()+1); let mut vec: Vec<()> = std::vec::Vec::new(); diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 1c0d8906caa..3fe4e7ca073 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -41,8 +41,14 @@ error: an exclusive range would be more readable error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:30:13 | -28 | let _ = (f()+1)..(f()+1); +30 | let _ = (1..11+1); + | ^^^^^^^^^ help: use: `(1..=11)` + +error: an inclusive range would be more readable + --> $DIR/range_plus_minus_one.rs:31:13 + | +31 | let _ = (f()+1)..(f()+1); | ^^^^^^^^^^^^^^^^ help: use: `((f()+1)..=f())` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 2f0a99a3a47988a8ef34fa3c76564179445bae8f Mon Sep 17 00:00:00 2001 From: daubaris Date: Mon, 3 Sep 2018 23:01:28 +0300 Subject: fixed known problems expression --- clippy_lints/src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index db2fbbad876..22fcdf0fc0f 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -52,7 +52,7 @@ declare_clippy_lint! { /// **Known problems:** Will add unnecessary pair of parentheses when the /// expression is not wrapped in a pair but starts with a opening parenthesis /// and ends with a closing one. -/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..(f()+1))`. +/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 35f100b4f9a055a98973f2a2ac2e1eb5c5cfacff Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 17 Jul 2018 22:50:17 +0200 Subject: update_lints rewrite: Add structure and --print-only --- Cargo.toml | 6 ++ clippy_dev/.gitignore | 38 +++++++++ clippy_dev/Cargo.lock | 215 +++++++++++++++++++++++++++++++++++++++++++++++++ clippy_dev/Cargo.toml | 9 +++ clippy_dev/src/lib.rs | 144 +++++++++++++++++++++++++++++++++ clippy_dev/src/main.rs | 53 ++++++++++++ util/dev | 3 + util/update_lints.py | 15 +--- 8 files changed, 470 insertions(+), 13 deletions(-) create mode 100644 clippy_dev/.gitignore create mode 100644 clippy_dev/Cargo.lock create mode 100644 clippy_dev/Cargo.toml create mode 100644 clippy_dev/src/lib.rs create mode 100644 clippy_dev/src/main.rs create mode 100755 util/dev diff --git a/Cargo.toml b/Cargo.toml index d368b71d993..52f93820c48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,11 @@ name = "clippy-driver" test = false path = "src/driver.rs" +[[bin]] +name = "clippy-dev" +test = false +path = "src/main.rs" + [dependencies] # begin automatic update clippy_lints = { version = "0.0.212", path = "clippy_lints" } @@ -46,6 +51,7 @@ regex = "1" semver = "0.9" [dev-dependencies] +clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6" compiletest_rs = "0.3.7" lazy_static = "1.0" diff --git a/clippy_dev/.gitignore b/clippy_dev/.gitignore new file mode 100644 index 00000000000..5ca1e06a5e5 --- /dev/null +++ b/clippy_dev/.gitignore @@ -0,0 +1,38 @@ +# Used by Travis to be able to push: +/.github/deploy_key +out + +# Compiled files +*.o +*.d +*.so +*.rlib +*.dll +*.pyc +*.rmeta + +# Executables +*.exe + +# Generated by Cargo +Cargo.lock +/target +/clippy_lints/target +/clippy_workspace_tests/target + +# Generated by dogfood +/target_recur/ + +# gh pages docs +util/gh-pages/lints.json + +# rustfmt backups +*.rs.bk + +helper.txt +*.iml +.vscode +.idea + +# Used by the Clippy build script +min_version.txt diff --git a/clippy_dev/Cargo.lock b/clippy_dev/Cargo.lock new file mode 100644 index 00000000000..ad5c705c292 --- /dev/null +++ b/clippy_dev/Cargo.lock @@ -0,0 +1,215 @@ +[[package]] +name = "aho-corasick" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clippy_dev" +version = "0.0.1" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.42" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" +"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" +"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml new file mode 100644 index 00000000000..010380907af --- /dev/null +++ b/clippy_dev/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "clippy_dev" +version = "0.0.1" +authors = ["Philipp Hansch "] + +[dependencies] +clap = "~2.32" +regex = "1" +lazy_static = "1.0" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs new file mode 100644 index 00000000000..2a86de9cbaa --- /dev/null +++ b/clippy_dev/src/lib.rs @@ -0,0 +1,144 @@ +extern crate regex; +#[macro_use] +extern crate lazy_static; + +use regex::Regex; +use std::ffi::OsStr; +use std::fs; +use std::io::prelude::*; + +lazy_static! { + static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"declare_clippy_lint!\s*[\{(]\s*pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s*(?P[a-z_]+)\s*,\s*"(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]"#).unwrap(); + static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"declare_deprecated_lint!\s*[{(]\s*pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s*"(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]"#).unwrap(); + static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap(); + pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string(); +} + +#[derive(Clone, PartialEq, Debug)] +pub struct Lint { + pub name: String, + pub group: String, + pub desc: String, + pub deprecation: Option, + pub module: String, +} + +impl Lint { + pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Lint { + Lint { + name: name.to_lowercase(), + group: group.to_string(), + desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), + deprecation: deprecation.map(|d| d.to_string()), + module: module.to_string(), + } + } + + pub fn active_lints(lints: &[Lint]) -> Vec { + lints.iter().filter(|l| l.deprecation.is_none()).cloned().collect::>() + } + + pub fn in_lint_group(group: &str, lints: &[Lint]) -> Vec { + lints.iter().filter(|l| l.group == group).cloned().collect::>() + } +} + +pub fn collect_all() -> Vec { + let mut lints = vec![]; + for direntry in lint_files() { + lints.append(&mut collect_from_file(&direntry)); + } + lints +} + +fn collect_from_file(direntry: &fs::DirEntry) -> Vec { + let mut file = fs::File::open(direntry.path()).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + parse_contents(&content, direntry.path().file_stem().unwrap().to_str().unwrap()) +} + +fn parse_contents(content: &str, filename: &str) -> Vec { + let mut lints: Vec = DEC_CLIPPY_LINT_RE + .captures_iter(&content) + .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)) + .collect(); + let mut deprecated = DEC_DEPRECATED_LINT_RE + .captures_iter(&content) + .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)) + .collect(); + lints.append(&mut deprecated); + lints +} + +/// Collects all .rs files in the `clippy_lints/src` directory +fn lint_files() -> Vec { + let paths = fs::read_dir("../clippy_lints/src").unwrap(); + paths + .filter_map(|f| f.ok()) + .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) + .collect::>() +} + +#[test] +fn test_parse_contents() { + let result = parse_contents( + r#" +declare_clippy_lint! { + pub PTR_ARG, + style, + "really long \ + text" +} + +declare_clippy_lint!{ + pub DOC_MARKDOWN, + pedantic, + "single line" +} + +/// some doc comment +declare_deprecated_lint! { + pub SHOULD_ASSERT_EQ, + "`assert!()` will be more flexible with RFC 2011" +} + "#, + "module_name"); + + let expected = vec![ + Lint::new("ptr_arg", "style", "really long text", None, "module_name"), + Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), + Lint::new( + "should_assert_eq", + "Deprecated", + "`assert!()` will be more flexible with RFC 2011", + Some("`assert!()` will be more flexible with RFC 2011"), + "module_name" + ), + ]; + assert_eq!(expected, result); +} + +#[test] +fn test_active_lints() { + let lints = vec![ + Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), + Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") + ]; + let expected = vec![ + Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") + ]; + assert_eq!(expected, Lint::active_lints(&lints)); +} + +#[test] +fn test_in_lint_group() { + let lints = vec![ + Lint::new("ptr_arg", "style", "really long text", None, "module_name"), + Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), + ]; + let expected = vec![ + Lint::new("ptr_arg", "style", "really long text", None, "module_name") + ]; + assert_eq!(expected, Lint::in_lint_group("style", &lints)); +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs new file mode 100644 index 00000000000..7bf6eb01245 --- /dev/null +++ b/clippy_dev/src/main.rs @@ -0,0 +1,53 @@ +extern crate clap; +extern crate clippy_dev; +extern crate regex; + +use clap::{App, Arg, SubCommand}; +use clippy_dev::*; + +fn main() { + let matches = App::new("Clippy developer tooling") + .subcommand( + SubCommand::with_name("update_lints") + .about("Update the lint list") + .arg( + Arg::with_name("print-only") + .long("print-only") + .short("p") + .help("Print a table of lints to STDOUT. Does not modify any files."), + ) + ) + .get_matches(); + + if let Some(matches) = matches.subcommand_matches("update_lints") { + if matches.is_present("print-only") { + print_lints(); + } + } +} + +fn print_lints() { + let lint_list = collect_all(); + let print_clippy_lint_groups: [&str; 7] = [ + "correctness", + "style", + "complexity", + "perf", + "pedantic", + "nursery", + "restriction" + ]; + // We could use itertools' group_by to make this much more concise: + for group in &print_clippy_lint_groups { + println!("\n## {}", group); + + let mut group_lints = Lint::in_lint_group(group, &lint_list); + group_lints.sort_by(|a, b| a.name.cmp(&b.name)); + + for lint in group_lints { + if lint.deprecation.is_some() { continue; } + println!("* [{}]({}#{}) ({})", lint.name, clippy_dev::DOCS_LINK.clone(), lint.name, lint.desc); + } + } + println!("there are {} lints", Lint::active_lints(&lint_list).len()); +} diff --git a/util/dev b/util/dev new file mode 100755 index 00000000000..4fa6e69b752 --- /dev/null +++ b/util/dev @@ -0,0 +1,3 @@ +#!/bin/sh + +cd clippy_dev && cargo run -- $@ diff --git a/util/update_lints.py b/util/update_lints.py index ea7b992abb7..15242abd606 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -7,6 +7,7 @@ import os import re import sys +from subprocess import call declare_deprecated_lint_re = re.compile(r''' declare_deprecated_lint! \s* [{(] \s* @@ -166,19 +167,7 @@ def main(print_only=False, check=False): all_lints += value if print_only: - print_clippy_lint_groups = [ - "correctness", - "style", - "complexity", - "perf", - "pedantic", - "nursery", - "restriction" - ] - for group in print_clippy_lint_groups: - sys.stdout.write('\n## ' + group + '\n') - for (_, name, _, descr) in sorted(clippy_lints[group]): - sys.stdout.write('* [' + name + '](https://rust-lang-nursery.github.io/rust-clippy/master/index.html#' + name + ') (' + descr + ')\n') + call(["./util/dev", "update_lints", "--print-only"]) return # update the lint counter in README.md -- cgit 1.4.1-3-g733a5 From 502357df65eb026721b9c3bc5a71ea749bd0669e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 30 Aug 2018 07:57:11 +0200 Subject: cargo update in clippy_dev --- clippy_dev/Cargo.lock | 81 +++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/clippy_dev/Cargo.lock b/clippy_dev/Cargo.lock index ad5c705c292..8731a7c8668 100644 --- a/clippy_dev/Cargo.lock +++ b/clippy_dev/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "aho-corasick" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,17 +16,17 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -35,8 +35,8 @@ version = "2.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -48,26 +48,29 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lazy_static" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.42" +version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -85,14 +88,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -113,7 +116,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -128,11 +131,10 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -145,17 +147,9 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -164,8 +158,8 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "void" -version = "1.0.2" +name = "version_check" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -188,28 +182,27 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" +"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" -"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" -"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" -"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" +"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -- cgit 1.4.1-3-g733a5 From 70312430dd8c32c0f1adc9e6f24c18bd2dd7d9c7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 30 Aug 2018 07:57:54 +0200 Subject: Use insignificant whitespace mode for nice regex --- clippy_dev/src/lib.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 2a86de9cbaa..1431a0fc05d 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -8,8 +8,17 @@ use std::fs; use std::io::prelude::*; lazy_static! { - static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"declare_clippy_lint!\s*[\{(]\s*pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s*(?P[a-z_]+)\s*,\s*"(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]"#).unwrap(); - static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"declare_deprecated_lint!\s*[{(]\s*pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s*"(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]"#).unwrap(); + static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"(?x) + declare_clippy_lint!\s*[\{(]\s* + pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* + (?P[a-z_]+)\s*,\s* + "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] + "#).unwrap(); + static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"(?x) + declare_deprecated_lint!\s*[{(]\s* + pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* + "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] + "#).unwrap(); static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap(); pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string(); } -- cgit 1.4.1-3-g733a5 From 78d358b861442137182ea7871d1177c799fab7e8 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 30 Aug 2018 08:00:16 +0200 Subject: s/direntry/dir_entry --- clippy_dev/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 1431a0fc05d..e1de1bec57f 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -54,17 +54,17 @@ impl Lint { pub fn collect_all() -> Vec { let mut lints = vec![]; - for direntry in lint_files() { - lints.append(&mut collect_from_file(&direntry)); + for dir_entry in lint_files() { + lints.append(&mut collect_from_file(&dir_entry)); } lints } -fn collect_from_file(direntry: &fs::DirEntry) -> Vec { - let mut file = fs::File::open(direntry.path()).unwrap(); +fn collect_from_file(dir_entry: &fs::DirEntry) -> Vec { + let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); - parse_contents(&content, direntry.path().file_stem().unwrap().to_str().unwrap()) + parse_contents(&content, dir_entry.path().file_stem().unwrap().to_str().unwrap()) } fn parse_contents(content: &str, filename: &str) -> Vec { -- cgit 1.4.1-3-g733a5 From 586ef4ed7237b2290bb6365b038e8da59776533f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Sep 2018 09:45:13 +0200 Subject: Refactor to use into_group_map from Itertools --- clippy_dev/Cargo.lock | 16 ++++++++++++++++ clippy_dev/Cargo.toml | 1 + clippy_dev/src/lib.rs | 28 +++++++++++++++++++--------- clippy_dev/src/main.rs | 28 ++++++++++------------------ 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/clippy_dev/Cargo.lock b/clippy_dev/Cargo.lock index 8731a7c8668..2d94755bae3 100644 --- a/clippy_dev/Cargo.lock +++ b/clippy_dev/Cargo.lock @@ -48,10 +48,24 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itertools" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.1.0" @@ -187,6 +201,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 010380907af..503dd53aa20 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -5,5 +5,6 @@ authors = ["Philipp Hansch "] [dependencies] clap = "~2.32" +itertools = "0.7" regex = "1" lazy_static = "1.0" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index e1de1bec57f..8eabf3a97c0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,8 +1,11 @@ extern crate regex; #[macro_use] extern crate lazy_static; +extern crate itertools; use regex::Regex; +use itertools::Itertools; +use std::collections::HashMap; use std::ffi::OsStr; use std::fs; use std::io::prelude::*; @@ -47,8 +50,9 @@ impl Lint { lints.iter().filter(|l| l.deprecation.is_none()).cloned().collect::>() } - pub fn in_lint_group(group: &str, lints: &[Lint]) -> Vec { - lints.iter().filter(|l| l.group == group).cloned().collect::>() + /// Returns the lints in a HashMap, grouped by the different lint groups + pub fn by_lint_group(lints: &[Lint]) -> HashMap> { + lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map() } } @@ -141,13 +145,19 @@ fn test_active_lints() { } #[test] -fn test_in_lint_group() { +fn test_by_lint_group() { let lints = vec![ - Lint::new("ptr_arg", "style", "really long text", None, "module_name"), - Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), - ]; - let expected = vec![ - Lint::new("ptr_arg", "style", "really long text", None, "module_name") + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), + Lint::new("incorrect_match", "group1", "abc", None, "module_name"), ]; - assert_eq!(expected, Lint::in_lint_group("style", &lints)); + let mut expected: HashMap> = HashMap::new(); + expected.insert("group1".to_string(), vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + ]); + expected.insert("group2".to_string(), vec![ + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name") + ]); + assert_eq!(expected, Lint::by_lint_group(&lints)); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 7bf6eb01245..6b55a7b7bf4 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -28,26 +28,18 @@ fn main() { fn print_lints() { let lint_list = collect_all(); - let print_clippy_lint_groups: [&str; 7] = [ - "correctness", - "style", - "complexity", - "perf", - "pedantic", - "nursery", - "restriction" - ]; - // We could use itertools' group_by to make this much more concise: - for group in &print_clippy_lint_groups { - println!("\n## {}", group); - - let mut group_lints = Lint::in_lint_group(group, &lint_list); - group_lints.sort_by(|a, b| a.name.cmp(&b.name)); - - for lint in group_lints { - if lint.deprecation.is_some() { continue; } + let grouped_by_lint_group = Lint::by_lint_group(&lint_list); + + for (lint_group, mut lints) in grouped_by_lint_group { + if lint_group == "Deprecated" { continue; } + println!("\n## {}", lint_group); + + lints.sort_by(|a, b| a.name.cmp(&b.name)); + + for lint in lints { println!("* [{}]({}#{}) ({})", lint.name, clippy_dev::DOCS_LINK.clone(), lint.name, lint.desc); } } + println!("there are {} lints", Lint::active_lints(&lint_list).len()); } -- cgit 1.4.1-3-g733a5 From be995dc0e841cb2db46d7995958ba24bac91e1e2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Sep 2018 10:13:53 +0200 Subject: Run clippy on clippy_dev, too --- ci/base-tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index dee709ab4eb..b85ed4fab66 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -19,6 +19,7 @@ cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clip cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../../.. +cd clippy_dev && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. # test --manifest-path PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. -- cgit 1.4.1-3-g733a5 From 20318ebc22ea25bd6150e1c0a3657854d16accbf Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 3 Sep 2018 22:27:35 +0200 Subject: Cleanup old min_version stuff This cleans up a few leftover things after https://github.com/rust-lang-nursery/rust-clippy/pull/3018 --- PUBLISH.md | 1 - build.rs | 15 --------------- 2 files changed, 16 deletions(-) diff --git a/PUBLISH.md b/PUBLISH.md index 749eae97304..b85605dc3b3 100644 --- a/PUBLISH.md +++ b/PUBLISH.md @@ -2,7 +2,6 @@ Steps to publish a new Clippy version - Bump `package.version` in `./Cargo.toml` (no need to manually bump `dependencies.clippy_lints.version`). - Write a changelog entry. -- If a nightly update is needed, update `min_version.txt` using `rustc -vV > min_version.txt` - Run `./pre_publish.sh` - Review and commit all changed files - `git push` diff --git a/build.rs b/build.rs index 3b9f217c884..1c930c1b2c9 100644 --- a/build.rs +++ b/build.rs @@ -1,18 +1,3 @@ -//! This build script ensures that Clippy is not compiled with an -//! incompatible version of rust. It will panic with a descriptive -//! error message instead. -//! -//! We specifially want to ensure that Clippy is only built with a -//! rustc version that is newer or equal to the one specified in the -//! `min_version.txt` file. -//! -//! `min_version.txt` is in the repo but also in the `.gitignore` to -//! make sure that it is not updated manually by accident. Only CI -//! should update that file. -//! -//! This build script was originally taken from the Rocket web framework: -//! https://github.com/SergioBenitez/Rocket - use std::env; fn main() { -- cgit 1.4.1-3-g733a5 From 4050a689891c012c31175430349bb20cf3a739bc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 4 Sep 2018 09:12:50 +1200 Subject: Make `Default` do what `default` used to do --- clippy_lints/src/utils/conf.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 8ec889a9fb6..16e39ff13ea 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -3,6 +3,7 @@ #![deny(clippy::missing_docs_in_private_items)] use lazy_static::lazy_static; +use std::default::Default; use std::{env, fmt, fs, io, path}; use std::io::Read; use syntax::{ast, source_map}; @@ -65,7 +66,7 @@ macro_rules! define_Conf { mod helpers { use serde_derive::Deserialize; /// Type used to store lint configuration. - #[derive(Default, Deserialize)] + #[derive(Deserialize)] #[serde(rename_all="kebab-case", deny_unknown_fields)] pub struct Conf { $(#[$doc] #[serde(default=$rust_name_str)] #[serde(with=$rust_name_str)] @@ -146,6 +147,12 @@ define_Conf! { (trivial_copy_size_limit, "trivial_copy_size_limit", None => Option), } +impl Default for Conf { + fn default() -> Conf { + toml::from_str("").expect("we never error on empty config files") + } +} + /// Search for the configuration file. pub fn lookup_conf_file() -> io::Result> { /// Possible filename to search for. @@ -180,7 +187,7 @@ pub fn lookup_conf_file() -> io::Result> { /// /// Used internally for convenience fn default(errors: Vec) -> (Conf, Vec) { - (toml::from_str("").expect("we never error on empty config files"), errors) + (Conf::default(), errors) } /// Read the `toml` configuration file. -- cgit 1.4.1-3-g733a5 From fbc93c0166e60fc6e56e6597524aeec7d17cbc58 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Wed, 29 Aug 2018 23:01:24 -0400 Subject: Lint against needless uses of `collect()` Handles cases of `.collect().len()`, `.collect().is_empty()`, and `.collect().contains()`. This lint is intended to be generic enough to be added to at a later time with other similar patterns that could be optimized. Closes #3034 --- clippy_lints/src/lib.rs | 2 + clippy_lints/src/loops.rs | 88 +++++++++++++++++++++++++++++++++++++++ needless_collect | Bin 0 -> 4136344 bytes tests/ui/needless_collect.rs | 10 +++++ tests/ui/needless_collect.stderr | 22 ++++++++++ 5 files changed, 122 insertions(+) create mode 100755 needless_collect create mode 100644 tests/ui/needless_collect.rs create mode 100644 tests/ui/needless_collect.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c49a70afa6f..23fdbf648e3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -554,6 +554,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::ITER_NEXT_LOOP, loops::MANUAL_MEMCPY, loops::MUT_RANGE_BOUND, + loops::NEEDLESS_COLLECT, loops::NEEDLESS_RANGE_LOOP, loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, @@ -904,6 +905,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { escape::BOXED_LOCAL, large_enum_variant::LARGE_ENUM_VARIANT, loops::MANUAL_MEMCPY, + loops::NEEDLESS_COLLECT, loops::UNUSED_COLLECT, methods::EXPECT_FUN_CALL, methods::ITER_NTH, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d12b2619c62..dfe1a3ccb1f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -223,6 +223,27 @@ declare_clippy_lint! { written as a for loop" } +/// **What it does:** Checks for functions collecting an iterator when collect +/// is not needed. +/// +/// **Why is this bad?** `collect` causes the allocation of a new data structure, +/// when this allocation may not be needed. +/// +/// **Known problems:** +/// None +/// +/// **Example:** +/// ```rust +/// let len = iterator.collect::>().len(); +/// // should be +/// let len = iterator.count(); +/// ``` +declare_clippy_lint! { + pub NEEDLESS_COLLECT, + perf, + "collecting an iterator when collect is not needed" +} + /// **What it does:** Checks for loops over ranges `x..y` where both `x` and `y` /// are constant and `x` is greater or equal to `y`, unless the range is /// reversed or has a negative `.step_by(_)`. @@ -400,6 +421,7 @@ impl LintPass for Pass { FOR_LOOP_OVER_OPTION, WHILE_LET_LOOP, UNUSED_COLLECT, + NEEDLESS_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, @@ -523,6 +545,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprKind::While(ref cond, _, _) = expr.node { check_infinite_loop(cx, cond, expr); } + + check_needless_collect(expr, cx); } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { @@ -2241,3 +2265,67 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { NestedVisitorMap::None } } + +fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) { + if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { + if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node { + if chain_method.ident.name == "collect" && match_trait_method(cx, &args[0], &paths::ITERATOR) { + if method.ident.name == "len" { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + expr.span, + "you are collecting an iterator to check its length", + "consider replacing with", + generate_needless_collect_len_sugg(&args[0], cx), + ); + } + if method.ident.name == "is_empty" { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + expr.span, + "you are collecting an iterator to check if it is empty", + "consider replacing with", + generate_needless_collect_is_empty_sugg(&args[0], cx), + ); + } + if method.ident.name == "contains" { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + expr.span, + "you are collecting an iterator to check if contains an element", + "consider replacing with", + generate_needless_collect_contains_sugg(&args[0], &args[1], cx), + ); + } + } + } + } +} + +fn generate_needless_collect_len_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { + if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { + let iter = snippet(cx, args[0].span, "??"); + return format!("{}.count()", iter); + } + unreachable!(); +} + +fn generate_needless_collect_is_empty_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { + if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { + let iter = snippet(cx, args[0].span, "??"); + return format!("{}.any(|_| true)", iter); + } + unreachable!(); +} + +fn generate_needless_collect_contains_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, contains_arg: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { + if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { + let iter = snippet(cx, args[0].span, "??"); + let arg = snippet(cx, contains_arg.span, "??"); + return format!("{}.any(|&x| x == {})", iter, if arg.starts_with('&') { &arg[1..] } else { &arg }); + } + unreachable!(); +} diff --git a/needless_collect b/needless_collect new file mode 100755 index 00000000000..89054ecc66f Binary files /dev/null and b/needless_collect differ diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs new file mode 100644 index 00000000000..5da77755d39 --- /dev/null +++ b/tests/ui/needless_collect.rs @@ -0,0 +1,10 @@ +#[warn(clippy, needless_collect)] +#[allow(unused_variables, iter_cloned_collect)] +fn main() { + let sample = [1; 5]; + let len = sample.iter().collect::>().len(); + if sample.iter().collect::>().is_empty() { + // Empty + } + sample.iter().cloned().collect::>().contains(&1); +} diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr new file mode 100644 index 00000000000..b4e478c7eec --- /dev/null +++ b/tests/ui/needless_collect.stderr @@ -0,0 +1,22 @@ +error: you are collecting an iterator to check its length + --> $DIR/needless_collect.rs:5:15 + | +5 | let len = sample.iter().collect::>().len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().count()` + | + = note: `-D needless-collect` implied by `-D warnings` + +error: you are collecting an iterator to check if it is empty + --> $DIR/needless_collect.rs:6:8 + | +6 | if sample.iter().collect::>().is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().any(|_| true)` + +error: you are collecting an iterator to check if contains an element + --> $DIR/needless_collect.rs:9:5 + | +9 | sample.iter().cloned().collect::>().contains(&1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().cloned().any(|&x| x == 1)` + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From dfed9751bdcfb158c566819541db958162b69643 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Fri, 31 Aug 2018 18:14:33 -0400 Subject: Majority of PR changes --- clippy_lints/src/loops.rs | 104 +++++++++++++++++++-------------------- tests/ui/needless_collect.rs | 7 +++ tests/ui/needless_collect.stderr | 28 ++++++----- 3 files changed, 76 insertions(+), 63 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index dfe1a3ccb1f..3b886875de7 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -18,6 +18,7 @@ use std::collections::{HashMap, HashSet}; use std::iter::{once, Iterator}; use syntax::ast; use syntax::source_map::Span; +use syntax_pos::BytePos; use crate::utils::{sugg, sext}; use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; @@ -2269,63 +2270,62 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) { if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node { - if chain_method.ident.name == "collect" && match_trait_method(cx, &args[0], &paths::ITERATOR) { - if method.ident.name == "len" { - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - expr.span, - "you are collecting an iterator to check its length", - "consider replacing with", - generate_needless_collect_len_sugg(&args[0], cx), - ); - } - if method.ident.name == "is_empty" { - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - expr.span, - "you are collecting an iterator to check if it is empty", - "consider replacing with", - generate_needless_collect_is_empty_sugg(&args[0], cx), - ); - } - if method.ident.name == "contains" { - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - expr.span, - "you are collecting an iterator to check if contains an element", - "consider replacing with", - generate_needless_collect_contains_sugg(&args[0], &args[1], cx), - ); + if chain_method.ident.name == "collect" && + match_trait_method(cx, &args[0], &paths::ITERATOR) && + chain_method.args.is_some() { + let generic_args = chain_method.args.as_ref().unwrap(); + if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0) { + let ty = cx.tables.node_id_to_type(ty.hir_id); + if match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::VEC_DEQUE) || + match_type(cx, ty, &paths::BTREEMAP) || + match_type(cx, ty, &paths::HASHMAP) { + if method.ident.name == "len" { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + shorten_needless_collect_span(expr), + "you are collecting an iterator to check its length", + "consider replacing with", + ".count()".to_string(), + ); + } + if method.ident.name == "is_empty" { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + shorten_needless_collect_span(expr), + "you are collecting an iterator to check if it is empty", + "consider replacing with", + ".next().is_none()".to_string(), + ); + } + if method.ident.name == "contains" { + let contains_arg = snippet(cx, args[1].span, "??"); + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + shorten_needless_collect_span(expr), + "you are collecting an iterator to check if contains an element", + "consider replacing with", + format!( + ".any(|&x| x == {})", + if contains_arg.starts_with('&') { &contains_arg[1..] } else { &contains_arg } + ), + ); + } + } } } } } } -fn generate_needless_collect_len_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { - if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { - let iter = snippet(cx, args[0].span, "??"); - return format!("{}.count()", iter); - } - unreachable!(); -} - -fn generate_needless_collect_is_empty_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { - if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { - let iter = snippet(cx, args[0].span, "??"); - return format!("{}.any(|_| true)", iter); - } - unreachable!(); -} - -fn generate_needless_collect_contains_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, contains_arg: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { - if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { - let iter = snippet(cx, args[0].span, "??"); - let arg = snippet(cx, contains_arg.span, "??"); - return format!("{}.any(|&x| x == {})", iter, if arg.starts_with('&') { &arg[1..] } else { &arg }); +fn shorten_needless_collect_span(expr: &Expr) -> Span { + if let ExprKind::MethodCall(_, _, ref args) = expr.node { + if let ExprKind::MethodCall(_, ref span, _) = args[0].node { + return expr.span.with_lo(span.lo() - BytePos(1)); + } } - unreachable!(); + unreachable!() } diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 5da77755d39..1aff8ee9565 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,3 +1,5 @@ +use std::collections::{HashMap, HashSet, BTreeSet}; + #[warn(clippy, needless_collect)] #[allow(unused_variables, iter_cloned_collect)] fn main() { @@ -7,4 +9,9 @@ fn main() { // Empty } sample.iter().cloned().collect::>().contains(&1); + sample.iter().map(|x| (x, x)).collect::>().len(); + // Notice the `HashSet`--this should not be linted + sample.iter().collect::>().len(); + // Neither should this + sample.iter().collect::>().len(); } diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index b4e478c7eec..1eca733ea02 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,22 +1,28 @@ error: you are collecting an iterator to check its length - --> $DIR/needless_collect.rs:5:15 + --> $DIR/needless_collect.rs:7:28 | -5 | let len = sample.iter().collect::>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().count()` +7 | let len = sample.iter().collect::>().len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.count()` | = note: `-D needless-collect` implied by `-D warnings` error: you are collecting an iterator to check if it is empty - --> $DIR/needless_collect.rs:6:8 + --> $DIR/needless_collect.rs:8:21 | -6 | if sample.iter().collect::>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().any(|_| true)` +8 | if sample.iter().collect::>().is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.next().is_none()` error: you are collecting an iterator to check if contains an element - --> $DIR/needless_collect.rs:9:5 - | -9 | sample.iter().cloned().collect::>().contains(&1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().cloned().any(|&x| x == 1)` + --> $DIR/needless_collect.rs:11:27 + | +11 | sample.iter().cloned().collect::>().contains(&1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.any(|&x| x == 1)` + +error: you are collecting an iterator to check its length + --> $DIR/needless_collect.rs:12:34 + | +12 | sample.iter().map(|x| (x, x)).collect::>().len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.count()` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 061b2f3057515ecb49e147fa6f54d07fd988005c Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Fri, 31 Aug 2018 18:26:04 -0400 Subject: Apply applicability --- clippy_lints/src/loops.rs | 60 ++++++++++++++++++++++------------------ tests/ui/needless_collect.stderr | 16 +++++------ 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3b886875de7..0c737d94806 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -14,6 +14,7 @@ use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::cmt_; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; +use rustc_errors::Applicability; use std::collections::{HashMap, HashSet}; use std::iter::{once, Iterator}; use syntax::ast; @@ -2267,6 +2268,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { } } +const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; + fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) { if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node { @@ -2281,38 +2284,41 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> match_type(cx, ty, &paths::BTREEMAP) || match_type(cx, ty, &paths::HASHMAP) { if method.ident.name == "len" { - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - shorten_needless_collect_span(expr), - "you are collecting an iterator to check its length", - "consider replacing with", - ".count()".to_string(), - ); + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + ".count()".to_string(), + Applicability::MachineApplicable, + ); + }); } if method.ident.name == "is_empty" { - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - shorten_needless_collect_span(expr), - "you are collecting an iterator to check if it is empty", - "consider replacing with", - ".next().is_none()".to_string(), - ); + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + ".next().is_none()".to_string(), + Applicability::MachineApplicable, + ); + }); } if method.ident.name == "contains" { let contains_arg = snippet(cx, args[1].span, "??"); - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - shorten_needless_collect_span(expr), - "you are collecting an iterator to check if contains an element", - "consider replacing with", - format!( - ".any(|&x| x == {})", - if contains_arg.starts_with('&') { &contains_arg[1..] } else { &contains_arg } - ), - ); + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + format!( + ".any(|&x| x == {})", + if contains_arg.starts_with('&') { &contains_arg[1..] } else { &contains_arg } + ), + Applicability::MachineApplicable, + ); + }); } } } diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 1eca733ea02..c2dd0879fb8 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,28 +1,28 @@ -error: you are collecting an iterator to check its length +error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:7:28 | 7 | let len = sample.iter().collect::>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.count()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` | = note: `-D needless-collect` implied by `-D warnings` -error: you are collecting an iterator to check if it is empty +error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:8:21 | 8 | if sample.iter().collect::>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.next().is_none()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` -error: you are collecting an iterator to check if contains an element +error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:11:27 | 11 | sample.iter().cloned().collect::>().contains(&1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.any(|&x| x == 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` -error: you are collecting an iterator to check its length +error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:12:34 | 12 | sample.iter().map(|x| (x, x)).collect::>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `.count()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 48e6be42d7827210107f363e60dd86125c7b385e Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Mon, 3 Sep 2018 23:50:24 -0400 Subject: Rustup --- clippy_lints/src/loops.rs | 6 ++++-- tests/ui/needless_collect.rs | 6 ++++-- tests/ui/needless_collect.stderr | 22 +++++++++++----------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0c737d94806..3e1bce044e3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2328,8 +2328,10 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> } fn shorten_needless_collect_span(expr: &Expr) -> Span { - if let ExprKind::MethodCall(_, _, ref args) = expr.node { - if let ExprKind::MethodCall(_, ref span, _) = args[0].node { + if_chain! { + if let ExprKind::MethodCall(_, _, ref args) = expr.node; + if let ExprKind::MethodCall(_, ref span, _) = args[0].node; + then { return expr.span.with_lo(span.lo() - BytePos(1)); } } diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 1aff8ee9565..b001f20d527 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,7 +1,9 @@ +#![feature(tool_lints)] + use std::collections::{HashMap, HashSet, BTreeSet}; -#[warn(clippy, needless_collect)] -#[allow(unused_variables, iter_cloned_collect)] +#[warn(clippy::needless_collect)] +#[allow(unused_variables, clippy::iter_cloned_collect)] fn main() { let sample = [1; 5]; let len = sample.iter().collect::>().len(); diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index c2dd0879fb8..0124db3b975 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,27 +1,27 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:7:28 + --> $DIR/needless_collect.rs:9:28 | -7 | let len = sample.iter().collect::>().len(); +9 | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` | - = note: `-D needless-collect` implied by `-D warnings` + = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:8:21 - | -8 | if sample.iter().collect::>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` + --> $DIR/needless_collect.rs:10:21 + | +10 | if sample.iter().collect::>().is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:11:27 + --> $DIR/needless_collect.rs:13:27 | -11 | sample.iter().cloned().collect::>().contains(&1); +13 | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:12:34 + --> $DIR/needless_collect.rs:14:34 | -12 | sample.iter().map(|x| (x, x)).collect::>().len(); +14 | sample.iter().map(|x| (x, x)).collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From ed9cd1530d43484ff11c2f5cd9681d02ed83066a Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Mon, 3 Sep 2018 23:58:10 -0400 Subject: More if_chain --- clippy_lints/src/loops.rs | 98 +++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3e1bce044e3..8a12530cb0d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2271,56 +2271,54 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) { - if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { - if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node { - if chain_method.ident.name == "collect" && - match_trait_method(cx, &args[0], &paths::ITERATOR) && - chain_method.args.is_some() { - let generic_args = chain_method.args.as_ref().unwrap(); - if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0) { - let ty = cx.tables.node_id_to_type(ty.hir_id); - if match_type(cx, ty, &paths::VEC) || - match_type(cx, ty, &paths::VEC_DEQUE) || - match_type(cx, ty, &paths::BTREEMAP) || - match_type(cx, ty, &paths::HASHMAP) { - if method.ident.name == "len" { - let span = shorten_needless_collect_span(expr); - span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( - span, - "replace with", - ".count()".to_string(), - Applicability::MachineApplicable, - ); - }); - } - if method.ident.name == "is_empty" { - let span = shorten_needless_collect_span(expr); - span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( - span, - "replace with", - ".next().is_none()".to_string(), - Applicability::MachineApplicable, - ); - }); - } - if method.ident.name == "contains" { - let contains_arg = snippet(cx, args[1].span, "??"); - let span = shorten_needless_collect_span(expr); - span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( - span, - "replace with", - format!( - ".any(|&x| x == {})", - if contains_arg.starts_with('&') { &contains_arg[1..] } else { &contains_arg } - ), - Applicability::MachineApplicable, - ); - }); - } - } + if_chain! { + if let ExprKind::MethodCall(ref method, _, ref args) = expr.node; + if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node; + if chain_method.ident.name == "collect" && match_trait_method(cx, &args[0], &paths::ITERATOR); + if let Some(ref generic_args) = chain_method.args; + if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); + then { + let ty = cx.tables.node_id_to_type(ty.hir_id); + if match_type(cx, ty, &paths::VEC) || + match_type(cx, ty, &paths::VEC_DEQUE) || + match_type(cx, ty, &paths::BTREEMAP) || + match_type(cx, ty, &paths::HASHMAP) { + if method.ident.name == "len" { + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + ".count()".to_string(), + Applicability::MachineApplicable, + ); + }); + } + if method.ident.name == "is_empty" { + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + ".next().is_none()".to_string(), + Applicability::MachineApplicable, + ); + }); + } + if method.ident.name == "contains" { + let contains_arg = snippet(cx, args[1].span, "??"); + let span = shorten_needless_collect_span(expr); + span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { + db.span_suggestion_with_applicability( + span, + "replace with", + format!( + ".any(|&x| x == {})", + if contains_arg.starts_with('&') { &contains_arg[1..] } else { &contains_arg } + ), + Applicability::MachineApplicable, + ); + }); } } } -- cgit 1.4.1-3-g733a5 From f7d2aeefe89d20f6ddad190b6976fba8e3b22584 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Sat, 1 Sep 2018 11:07:18 -0400 Subject: Delete needless file --- needless_collect | Bin 4136344 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 needless_collect diff --git a/needless_collect b/needless_collect deleted file mode 100755 index 89054ecc66f..00000000000 Binary files a/needless_collect and /dev/null differ -- cgit 1.4.1-3-g733a5 From 009c29069c1cf188e6d1935292c288c22d57cc04 Mon Sep 17 00:00:00 2001 From: daubaris Date: Tue, 4 Sep 2018 18:56:48 +0300 Subject: switched to ticks for chars --- clippy_lints/src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 22fcdf0fc0f..f9cdffea79c 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { - if is_wrapped.starts_with("(") && is_wrapped.ends_with(")") { + if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { db.span_suggestion(expr.span, "use", format!("({}..={})", start, end)); -- cgit 1.4.1-3-g733a5 From 79bec036f8cd928e74e3c26d79daf94b4a30dea1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 5 Sep 2018 13:34:28 +0200 Subject: Return impl Iterator instead of Vec This makes the API of `lib.rs` a bit more flexible. --- clippy_dev/src/lib.rs | 26 +++++++++++++------------- clippy_dev/src/main.rs | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8eabf3a97c0..c499934346e 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -46,8 +46,9 @@ impl Lint { } } - pub fn active_lints(lints: &[Lint]) -> Vec { - lints.iter().filter(|l| l.deprecation.is_none()).cloned().collect::>() + /// Returns all non-deprecated lints + pub fn active_lints(lints: &[Lint]) -> impl Iterator { + lints.iter().filter(|l| l.deprecation.is_none()) } /// Returns the lints in a HashMap, grouped by the different lint groups @@ -56,22 +57,22 @@ impl Lint { } } -pub fn collect_all() -> Vec { +pub fn gather_all() -> impl Iterator { let mut lints = vec![]; for dir_entry in lint_files() { - lints.append(&mut collect_from_file(&dir_entry)); + lints.append(&mut gather_from_file(&dir_entry).collect()); } - lints + lints.into_iter() } -fn collect_from_file(dir_entry: &fs::DirEntry) -> Vec { +fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); parse_contents(&content, dir_entry.path().file_stem().unwrap().to_str().unwrap()) } -fn parse_contents(content: &str, filename: &str) -> Vec { +fn parse_contents(content: &str, filename: &str) -> impl Iterator { let mut lints: Vec = DEC_CLIPPY_LINT_RE .captures_iter(&content) .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)) @@ -81,21 +82,20 @@ fn parse_contents(content: &str, filename: &str) -> Vec { .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)) .collect(); lints.append(&mut deprecated); - lints + lints.into_iter() } /// Collects all .rs files in the `clippy_lints/src` directory -fn lint_files() -> Vec { +fn lint_files() -> impl Iterator { let paths = fs::read_dir("../clippy_lints/src").unwrap(); paths .filter_map(|f| f.ok()) .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) - .collect::>() } #[test] fn test_parse_contents() { - let result = parse_contents( + let result: Vec = parse_contents( r#" declare_clippy_lint! { pub PTR_ARG, @@ -116,7 +116,7 @@ declare_deprecated_lint! { "`assert!()` will be more flexible with RFC 2011" } "#, - "module_name"); + "module_name").collect(); let expected = vec![ Lint::new("ptr_arg", "style", "really long text", None, "module_name"), @@ -141,7 +141,7 @@ fn test_active_lints() { let expected = vec![ Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") ]; - assert_eq!(expected, Lint::active_lints(&lints)); + assert_eq!(expected, Lint::active_lints(&lints).cloned().collect::>()); } #[test] diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 6b55a7b7bf4..f45c52e2271 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -27,7 +27,7 @@ fn main() { } fn print_lints() { - let lint_list = collect_all(); + let lint_list = gather_all().collect::>(); let grouped_by_lint_group = Lint::by_lint_group(&lint_list); for (lint_group, mut lints) in grouped_by_lint_group { @@ -41,5 +41,5 @@ fn print_lints() { } } - println!("there are {} lints", Lint::active_lints(&lint_list).len()); + println!("there are {} lints", Lint::active_lints(&lint_list).count()); } -- cgit 1.4.1-3-g733a5 From 20836d3003050d4abd313eb9fda4dc8bb6bc7f9c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 5 Sep 2018 13:35:57 +0200 Subject: Remove duplicated .gitignore --- .gitignore | 4 +--- clippy_dev/.gitignore | 38 -------------------------------------- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 clippy_dev/.gitignore diff --git a/.gitignore b/.gitignore index 5ca1e06a5e5..5fd7f2fc1a0 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ Cargo.lock /target /clippy_lints/target /clippy_workspace_tests/target +/clippy_dev/target # Generated by dogfood /target_recur/ @@ -33,6 +34,3 @@ helper.txt *.iml .vscode .idea - -# Used by the Clippy build script -min_version.txt diff --git a/clippy_dev/.gitignore b/clippy_dev/.gitignore deleted file mode 100644 index 5ca1e06a5e5..00000000000 --- a/clippy_dev/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -# Used by Travis to be able to push: -/.github/deploy_key -out - -# Compiled files -*.o -*.d -*.so -*.rlib -*.dll -*.pyc -*.rmeta - -# Executables -*.exe - -# Generated by Cargo -Cargo.lock -/target -/clippy_lints/target -/clippy_workspace_tests/target - -# Generated by dogfood -/target_recur/ - -# gh pages docs -util/gh-pages/lints.json - -# rustfmt backups -*.rs.bk - -helper.txt -*.iml -.vscode -.idea - -# Used by the Clippy build script -min_version.txt -- cgit 1.4.1-3-g733a5 From 0f6d4228170af9287a76eb15245ec69253f7a687 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 5 Sep 2018 05:59:07 -0700 Subject: Added test case for ptr_arg --- tests/ui/ptr_arg.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index e76221355ae..7cd3c9f9c72 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -77,3 +77,10 @@ fn test_cow_with_ref(c: &Cow<[i32]>) { fn test_cow(c: Cow<[i32]>) { let _c = c; } + +trait Foo2 { + fn do_string(&self); +} + +// no error for &self references where self is of type String (#2293) +impl Foo2 for String { fn do_string(&self) {} } -- cgit 1.4.1-3-g733a5 From 38d287fecd385aa8f89cec1822f7f6a30bfd96cb Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Sun, 2 Sep 2018 23:07:55 +0200 Subject: Add lint for misstyped literal casting --- CHANGELOG.md | 3 ++ README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/literal_representation.rs | 85 ++++++++++++++++++++++++------ tests/ui/literals.rs | 11 ++++ tests/ui/literals.stderr | 60 ++++++++++++++++++++- 6 files changed, 145 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48585df0603..a2a83118ee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -645,6 +645,7 @@ All notable changes to this project will be documented in this file. [`cmp_owned`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_owned [`collapsible_if`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#collapsible_if [`const_static_lifetime`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#const_static_lifetime +[`copy_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#copy_iterator [`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity [`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation @@ -748,6 +749,7 @@ All notable changes to this project will be documented in this file. [`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_inline_in_public_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_inline_in_public_items +[`mistyped_literal_suffixes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception [`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one @@ -800,6 +802,7 @@ All notable changes to this project will be documented in this file. [`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline [`println_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#println_empty_string [`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg +[`ptr_offset_with_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`question_mark`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#question_mark [`range_minus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_minus_one diff --git a/README.md b/README.md index 98f712c28d8..c94b181cb03 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 273 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 275 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index adc4f76fef9..e668513c4a0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -543,6 +543,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { lifetimes::NEEDLESS_LIFETIMES, literal_representation::INCONSISTENT_DIGIT_GROUPING, literal_representation::LARGE_DIGIT_GROUPS, + literal_representation::MISTYPED_LITERAL_SUFFIXES, literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, loops::EXPLICIT_COUNTER_LOOP, @@ -869,6 +870,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { infinite_iter::INFINITE_ITER, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, invalid_ref::INVALID_REF, + literal_representation::MISTYPED_LITERAL_SUFFIXES, loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, loops::ITER_NEXT_LOOP, diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index dcffba80b3b..349878960f4 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -26,6 +26,26 @@ declare_clippy_lint! { "long integer literal without underscores" } +/// **What it does:** Warns for mistyped suffix in literals +/// +/// **Why is this bad?** This is most probably a typo +/// +/// **Known problems:** +/// - Recommends a signed suffix, even though the number might be too big and an unsigned +/// suffix is required +/// - Does not match on `_128` since that is a valid grouping for decimal and octal numbers +/// +/// **Example:** +/// +/// ```rust +/// 2_32 +/// ``` +declare_clippy_lint! { + pub MISTYPED_LITERAL_SUFFIXES, + correctness, + "mistyped literal suffix" +} + /// **What it does:** Warns if an integral or floating-point constant is /// grouped inconsistently with underscores. /// @@ -137,16 +157,22 @@ impl<'a> DigitInfo<'a> { let mut last_d = '\0'; for (d_idx, d) in sans_prefix.char_indices() { - if !float && (d == 'i' || d == 'u') || float && (d == 'f' || d == 'e' || d == 'E') { - let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; - let (digits, suffix) = sans_prefix.split_at(suffix_start); - return Self { - digits, - radix, - prefix, - suffix: Some(suffix), - float, - }; + let suffix_start = if last_d == '_' { + d_idx - 1 + } else { + d_idx + }; + let (digits, suffix) = sans_prefix.split_at(suffix_start); + if !float && (d == 'i' || d == 'u') || + float && (d == 'f' || d == 'e' || d == 'E') || + !float && is_mistyped_suffix(suffix) { + return Self { + digits, + radix, + prefix, + suffix: Some(suffix), + float, + }; } last_d = d } @@ -161,7 +187,7 @@ impl<'a> DigitInfo<'a> { } } - /// Returns digits grouped in a sensible way. + /// Returns literal formatted in a sensible way. crate fn grouping_hint(&self) -> String { let group_size = self.radix.suggest_grouping(); if self.digits.contains('.') { @@ -211,11 +237,18 @@ impl<'a> DigitInfo<'a> { if self.radix == Radix::Hexadecimal && nb_digits_to_fill != 0 { hint = format!("{:0>4}{}", &hint[..nb_digits_to_fill], &hint[nb_digits_to_fill..]); } + let suffix_hint = match self.suffix { + Some(suffix) if is_mistyped_suffix(suffix) => { + format!("_i{}", &suffix[1..]) + }, + Some(suffix) => suffix.to_string(), + None => String::new() + }; format!( "{}{}{}", self.prefix.unwrap_or(""), hint, - self.suffix.unwrap_or("") + suffix_hint ) } } @@ -226,11 +259,22 @@ enum WarningType { InconsistentDigitGrouping, LargeDigitGroups, DecimalRepresentation, + MistypedLiteralSuffix } impl WarningType { crate fn display(&self, grouping_hint: &str, cx: &EarlyContext<'_>, span: syntax_pos::Span) { match self { + WarningType::MistypedLiteralSuffix => { + span_lint_and_sugg( + cx, + MISTYPED_LITERAL_SUFFIXES, + span, + "mistyped literal suffix", + "did you mean to write", + grouping_hint.to_string() + ) + }, WarningType::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, @@ -303,7 +347,7 @@ impl LiteralDigitGrouping { if char::to_digit(firstch, 10).is_some(); then { let digit_info = DigitInfo::new(&src, false); - let _ = Self::do_lint(digit_info.digits).map_err(|warning_type| { + let _ = Self::do_lint(digit_info.digits, digit_info.suffix).map_err(|warning_type| { warning_type.display(&digit_info.grouping_hint(), cx, lit.span) }); } @@ -325,12 +369,12 @@ impl LiteralDigitGrouping { // Lint integral and fractional parts separately, and then check consistency of digit // groups if both pass. - let _ = Self::do_lint(parts[0]) + let _ = Self::do_lint(parts[0], None) .map(|integral_group_size| { if parts.len() > 1 { // Lint the fractional part of literal just like integral part, but reversed. let fractional_part = &parts[1].chars().rev().collect::(); - let _ = Self::do_lint(fractional_part) + let _ = Self::do_lint(fractional_part, None) .map(|fractional_group_size| { let consistent = Self::parts_consistent(integral_group_size, fractional_group_size, @@ -373,7 +417,12 @@ impl LiteralDigitGrouping { /// Performs lint on `digits` (no decimal point) and returns the group /// size on success or `WarningType` when emitting a warning. - fn do_lint(digits: &str) -> Result { + fn do_lint(digits: &str, suffix: Option<&str>) -> Result { + if let Some(suffix) = suffix { + if is_mistyped_suffix(suffix) { + return Err(WarningType::MistypedLiteralSuffix); + } + } // Grab underscore indices with respect to the units digit. let underscore_positions: Vec = digits .chars() @@ -504,3 +553,7 @@ impl LiteralRepresentation { Ok(()) } } + +fn is_mistyped_suffix(suffix: &str) -> bool { + ["_8", "_16", "_32", "_64"].contains(&suffix) +} diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index d45da257ad4..7a9efaeec84 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -43,4 +43,15 @@ fn main() { let fail11 = 0xabcdeff; let fail12 = 0xabcabcabcabcabcabc; let fail13 = 0x1_23456_78901_usize; + + let fail14 = 2_32; + let fail15 = 4_64; + let fail16 = 7_8; + let fail17 = 23_16; + let ok18 = 23_128; + let fail19 = 12_3456_21; + let fail20 = 2__8; + let fail21 = 4___16; + let fail22 = 3__4___23; + let fail23 = 3__16___23; } diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 40399e498ab..bd2d1f81831 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -120,5 +120,63 @@ error: digit groups should be smaller | = note: `-D clippy::large-digit-groups` implied by `-D warnings` -error: aborting due to 16 previous errors +error: mistyped literal suffix + --> $DIR/literals.rs:47:18 + | +47 | let fail14 = 2_32; + | ^^^^ help: did you mean to write: `2_i32` + | + = note: #[deny(clippy::mistyped_literal_suffixes)] on by default + +error: mistyped literal suffix + --> $DIR/literals.rs:48:18 + | +48 | let fail15 = 4_64; + | ^^^^ help: did you mean to write: `4_i64` + +error: mistyped literal suffix + --> $DIR/literals.rs:49:18 + | +49 | let fail16 = 7_8; + | ^^^ help: did you mean to write: `7_i8` + +error: mistyped literal suffix + --> $DIR/literals.rs:50:18 + | +50 | let fail17 = 23_16; + | ^^^^^ help: did you mean to write: `23_i16` + +error: digits grouped inconsistently by underscores + --> $DIR/literals.rs:52:18 + | +52 | let fail19 = 12_3456_21; + | ^^^^^^^^^^ help: consider: `12_345_621` + | + = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` + +error: mistyped literal suffix + --> $DIR/literals.rs:53:18 + | +53 | let fail20 = 2__8; + | ^^^^ help: did you mean to write: `2_i8` + +error: mistyped literal suffix + --> $DIR/literals.rs:54:18 + | +54 | let fail21 = 4___16; + | ^^^^^^ help: did you mean to write: `4_i16` + +error: digits grouped inconsistently by underscores + --> $DIR/literals.rs:55:18 + | +55 | let fail22 = 3__4___23; + | ^^^^^^^^^ help: consider: `3_423` + +error: digits grouped inconsistently by underscores + --> $DIR/literals.rs:56:18 + | +56 | let fail23 = 3__16___23; + | ^^^^^^^^^^ help: consider: `31_623` + +error: aborting due to 25 previous errors -- cgit 1.4.1-3-g733a5 From 554fe1ed5c4c33b100ada27810cd19ea8e18c3f0 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 00:45:57 +0200 Subject: remove "clippy::" lint prefix from lint name in doc url. Fixes #3132 --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 650ea373d97..ad033724fe1 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -499,7 +499,7 @@ impl<'a> DiagnosticWrapper<'a> { self.0.help(&format!( "for further information visit https://rust-lang-nursery.github.io/rust-clippy/v{}/index.html#{}", env!("CARGO_PKG_VERSION"), - lint.name_lower() + lint.name_lower().replacen("clippy::", "", 1) )); } } @@ -1115,4 +1115,4 @@ mod test { let result = without_block_comments(vec!["foo", "bar", "baz"]); assert_eq!(result, vec!["foo", "bar", "baz"]); } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 4b668159d2d790dce8868c36ed591394eeb2cf7c Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 5 Sep 2018 19:14:01 -0700 Subject: Closes #1219 false positive for explicit_counter_loop --- tests/ui/for_loop.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 39eee64883c..76bc96f91b7 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -571,3 +571,19 @@ mod issue_2496 { unimplemented!() } } + +mod issue_1219 { + // potential false positive for explicit_counter_loop + pub fn test() { + let thing = 5; + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + if ch == 'a' { + continue; + } + count += 1 + } + println!("{}", count); + } +} -- cgit 1.4.1-3-g733a5 From 4f7a260472d1722c8b2bf0771c875e69f3a2bf48 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 6 Sep 2018 07:01:56 +0200 Subject: driver: Improve check for rustc arg The rustc arg might not be exactly "rustc". It may be any path to a rustc executable (especially if the RUSTC environment variable is set when executing cargo). Rather check that it is a path with 'rustc' file stem. --- src/driver.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index 26ff846177b..267e460ad2e 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -6,6 +6,7 @@ use rustc_driver::{self, driver::CompileController, Compilation}; use rustc_plugin; +use std::path::Path; use std::process::{exit, Command}; #[allow(clippy::print_stdout)] @@ -47,7 +48,7 @@ pub fn main() { if orig_args.len() <= 1 { std::process::exit(1); } - if orig_args[1] == "rustc" { + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { // we still want to be able to invoke it normally though orig_args.remove(1); } -- cgit 1.4.1-3-g733a5 From de36d42e80864f40fb3075dc4e3389cfa0c113b2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 5 Sep 2018 20:32:26 +0200 Subject: More refactoring --- clippy_dev/src/lib.rs | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index c499934346e..998efb142cc 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -58,14 +58,10 @@ impl Lint { } pub fn gather_all() -> impl Iterator { - let mut lints = vec![]; - for dir_entry in lint_files() { - lints.append(&mut gather_from_file(&dir_entry).collect()); - } - lints.into_iter() + lint_files().flat_map(gather_from_file) } -fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator { +fn gather_from_file(dir_entry: fs::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); @@ -73,22 +69,20 @@ fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator { } fn parse_contents(content: &str, filename: &str) -> impl Iterator { - let mut lints: Vec = DEC_CLIPPY_LINT_RE - .captures_iter(&content) - .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)) - .collect(); - let mut deprecated = DEC_DEPRECATED_LINT_RE - .captures_iter(&content) - .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)) - .collect(); - lints.append(&mut deprecated); - lints.into_iter() + let lints = DEC_CLIPPY_LINT_RE + .captures_iter(content) + .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)); + let deprecated = DEC_DEPRECATED_LINT_RE + .captures_iter(content) + .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)); + // Removing the `.collect::>().into_iter()` causes some lifetime issues due to the map + lints.chain(deprecated).collect::>().into_iter() } /// Collects all .rs files in the `clippy_lints/src` directory fn lint_files() -> impl Iterator { - let paths = fs::read_dir("../clippy_lints/src").unwrap(); - paths + fs::read_dir("../clippy_lints/src") + .unwrap() .filter_map(|f| f.ok()) .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } -- cgit 1.4.1-3-g733a5 From 3bdc691a91e3a7ac05f808772c0fbc2370fff511 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 6 Sep 2018 08:19:09 +0200 Subject: Pass by ref instead of value --- clippy_dev/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 998efb142cc..a872ecf3feb 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -58,10 +58,10 @@ impl Lint { } pub fn gather_all() -> impl Iterator { - lint_files().flat_map(gather_from_file) + lint_files().flat_map(|f| gather_from_file(&f)) } -fn gather_from_file(dir_entry: fs::DirEntry) -> impl Iterator { +fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); -- cgit 1.4.1-3-g733a5 From 0a8ceaf8b0b343fb943fa18bbfa6a52a3ce93ec6 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 12:33:00 +0200 Subject: rustfmt clippy_lints/src/write.rs --- clippy_lints/src/write.rs | 52 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 5d32157238b..06a4f6cb39e 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,10 +1,10 @@ +use crate::utils::{snippet, span_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use std::borrow::Cow; use syntax::ast::*; +use syntax::parse::{parser, token}; use syntax::tokenstream::{ThinTokenStream, TokenStream}; -use syntax::parse::{token, parser}; -use std::borrow::Cow; -use crate::utils::{span_lint, span_lint_and_sugg, snippet}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -196,24 +196,34 @@ impl EarlyLintPass for Pass { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 { if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { - span_lint(cx, PRINT_WITH_NEWLINE, mac.span, - "using `print!()` with a format string that ends in a \ - single newline, consider using `println!()` instead"); + span_lint( + cx, + PRINT_WITH_NEWLINE, + mac.span, + "using `print!()` with a format string that ends in a \ + single newline, consider using `println!()` instead", + ); } } } else if mac.node.path == "write" { if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 { if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { - span_lint(cx, WRITE_WITH_NEWLINE, mac.span, - "using `write!()` with a format string that ends in a \ - single newline, consider using `writeln!()` instead"); + span_lint( + cx, + WRITE_WITH_NEWLINE, + mac.span, + "using `write!()` with a format string that ends in a \ + single newline, consider using `writeln!()` instead", + ); } } } else if mac.node.path == "writeln" { let check_tts = check_tts(cx, &mac.node.tts, true); if let Some(fmtstr) = check_tts.0 { if fmtstr == "" { - let suggestion = check_tts.1.map_or(Cow::Borrowed("v"), |expr| snippet(cx, expr.span, "v")); + let suggestion = check_tts + .1 + .map_or(Cow::Borrowed("v"), |expr| snippet(cx, expr.span, "v")); span_lint_and_sugg( cx, @@ -231,13 +241,7 @@ impl EarlyLintPass for Pass { fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { let tts = TokenStream::from(tts.clone()); - let mut parser = parser::Parser::new( - &cx.sess.parse_sess, - tts, - None, - false, - false, - ); + let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false); let mut expr: Option = None; if is_write { expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { @@ -270,11 +274,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - args.push(arg); } } - let lint = if is_write { - WRITE_LITERAL - } else { - PRINT_LITERAL - }; + let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL }; let mut idx = 0; loop { if !parser.eat(&token::Comma) { @@ -299,9 +299,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let mut seen = false; for arg in &args { match arg.position { - | ArgumentImplicitlyIs(n) - | ArgumentIs(n) - => if n == idx { + ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx { all_simple &= arg.format == SIMPLE; seen = true; }, @@ -320,9 +318,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let mut seen = false; for arg in &args { match arg.position { - | ArgumentImplicitlyIs(_) - | ArgumentIs(_) - => {}, + ArgumentImplicitlyIs(_) | ArgumentIs(_) => {}, ArgumentNamed(name) => if *p == name { seen = true; all_simple &= arg.format == SIMPLE; -- cgit 1.4.1-3-g733a5 From a0f56edfc316d642785efc5ccaf0d1c6c457b057 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 12:55:04 +0200 Subject: print_with_newline / write_with_newline: don't warn about string with several `\n`s in them. Fixes #3126 --- clippy_lints/src/write.rs | 10 ++++++++-- tests/ui/print_with_newline.rs | 2 ++ tests/ui/write_with_newline.rs | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 06a4f6cb39e..7ddae1c81c7 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -195,7 +195,10 @@ impl EarlyLintPass for Pass { } else if mac.node.path == "print" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 { - if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { + if fmtstr.ends_with("\\n") && + // don't warn about strings with several `\n`s (#3126) + fmtstr.matches("\\n").count() == 1 + { span_lint( cx, PRINT_WITH_NEWLINE, @@ -207,7 +210,10 @@ impl EarlyLintPass for Pass { } } else if mac.node.path == "write" { if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 { - if fmtstr.ends_with("\\n") && !fmtstr.ends_with("\\n\\n") { + if fmtstr.ends_with("\\n") && + // don't warn about strings with several `\n`s (#3126) + fmtstr.matches("\\n").count() == 1 + { span_lint( cx, WRITE_WITH_NEWLINE, diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 5efee5abfc8..c2c79c726e8 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -21,4 +21,6 @@ fn main() { print!("\n\n"); print!("like eof\n\n"); print!("Hello {} {}\n\n", "world", "#2"); + println!("\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + println!("\nbla\n\n"); // #3126 } diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index e060459a411..58e6002fa6a 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -26,4 +26,6 @@ fn main() { write!(&mut v, "\n\n"); write!(&mut v, "like eof\n\n"); write!(&mut v, "Hello {} {}\n\n", "world", "#2"); + writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + writeln!(&mut v, "\nbla\n\n"); // #3126 } -- cgit 1.4.1-3-g733a5 From 86679e230c5154f23e5efb37f0bdf5b753d227c3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 13:03:38 +0200 Subject: Cargo.toml: remove clippy-dev entry referencing src/main.rs as its main.rs. Resolves warning: warning: file found to be present in multiple build targets: ./src/main.rs --- Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52f93820c48..fb43e0100bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,11 +38,6 @@ name = "clippy-driver" test = false path = "src/driver.rs" -[[bin]] -name = "clippy-dev" -test = false -path = "src/main.rs" - [dependencies] # begin automatic update clippy_lints = { version = "0.0.212", path = "clippy_lints" } -- cgit 1.4.1-3-g733a5 From fa11aad92a20aaf64c1ee4f43015fba9b6d24b62 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 08:19:47 +0200 Subject: print git commit hash and commit date in version output clippy 0.0.212 (964fcbe0 2018-09-06) --- .gitignore | 1 + Cargo.toml | 4 +++ build.rs | 13 +++++-- ci/base-tests.sh | 2 ++ rustc_tools_util/Cargo.toml | 8 +++++ rustc_tools_util/src/lib.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 9 +++-- 7 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 rustc_tools_util/Cargo.toml create mode 100644 rustc_tools_util/src/lib.rs diff --git a/.gitignore b/.gitignore index 5fd7f2fc1a0..166cab60a58 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ Cargo.lock /clippy_lints/target /clippy_workspace_tests/target /clippy_dev/target +/rustc_tools_util/target # Generated by dogfood /target_recur/ diff --git a/Cargo.toml b/Cargo.toml index 52f93820c48..0b9ed1d8610 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" +rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } @@ -65,5 +66,8 @@ derive-new = "0.5" # for more information. rustc-workspace-hack = "1.0.0" +[build-dependencies] +rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} + [features] debugging = [] diff --git a/build.rs b/build.rs index 1c930c1b2c9..146a8dae745 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,15 @@ -use std::env; - fn main() { // Forward the profile to the main compilation - println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap()); // Don't rebuild even if nothing changed println!("cargo:rerun-if-changed=build.rs"); + // forward git repo hashes we build at + println!( + "cargo:rustc-env=GIT_HASH={}", + rustc_tools_util::get_commit_hash().unwrap_or_default() + ); + println!( + "cargo:rustc-env=COMMIT_DATE={}", + rustc_tools_util::get_commit_date().unwrap_or_default() + ); } diff --git a/ci/base-tests.sh b/ci/base-tests.sh index b85ed4fab66..94a810e4ef4 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -20,6 +20,8 @@ cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../../.. cd clippy_dev && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. +cd rustc_tools_util/ && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. + # test --manifest-path PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml new file mode 100644 index 00000000000..01dca0a65b0 --- /dev/null +++ b/rustc_tools_util/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["edition"] + +[package] +name = "rustc_tools_util" +version = "0.1.0" +authors = ["Matthias Krüger "] +edition = "2018" +[dependencies] diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs new file mode 100644 index 00000000000..20b598346f1 --- /dev/null +++ b/rustc_tools_util/src/lib.rs @@ -0,0 +1,82 @@ +#![feature(tool_lints)] + +use std::env; + +#[macro_export] +macro_rules! get_version_info { + () => {{ + let major = env!("CARGO_PKG_VERSION_MAJOR").parse::().unwrap(); + let minor = env!("CARGO_PKG_VERSION_MINOR").parse::().unwrap(); + let patch = env!("CARGO_PKG_VERSION_PATCH").parse::().unwrap(); + + let host_compiler = $crate::get_channel(); + let commit_hash = option_env!("GIT_HASH").map(|s| s.to_string()); + let commit_date = option_env!("COMMIT_DATE").map(|s| s.to_string()); + + VersionInfo { + major, + minor, + patch, + host_compiler, + commit_hash, + commit_date, + } + }}; +} + +// some code taken and adapted from RLS and cargo +pub struct VersionInfo { + pub major: u8, + pub minor: u8, + pub patch: u16, + pub host_compiler: Option, + pub commit_hash: Option, + pub commit_date: Option, +} + +impl std::fmt::Display for VersionInfo { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self.commit_hash { + Some(_) => { + write!( + f, + "clippy {}.{}.{} ({} {})", + self.major, + self.minor, + self.patch, + self.commit_hash.clone().unwrap_or_default().trim(), + self.commit_date.clone().unwrap_or_default().trim(), + )?; + }, + None => { + write!(f, "clippy {}.{}.{}", self.major, self.minor, self.patch)?; + }, + }; + Ok(()) + } +} + +pub fn get_channel() -> Option { + if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") { + Some(channel) + } else { + // we could ask ${RUSTC} -Vv and do some parsing and find out + Some(String::from("nightly")) + } +} + +pub fn get_commit_hash() -> Option { + std::process::Command::new("git") + .args(&["rev-parse", "--short", "HEAD"]) + .output() + .ok() + .and_then(|r| String::from_utf8(r.stdout).ok()) +} + +pub fn get_commit_date() -> Option { + std::process::Command::new("git") + .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) + .output() + .ok() + .and_then(|r| String::from_utf8(r.stdout).ok()) +} diff --git a/src/main.rs b/src/main.rs index 12c07f60a11..cf26549774c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ #![feature(tool_lints)] #![allow(unknown_lints, clippy::missing_docs_in_private_items)] +use rustc_tools_util::*; + const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. Usage: @@ -36,7 +38,8 @@ fn show_help() { #[allow(clippy::print_stdout)] fn show_version() { - println!(env!("CARGO_PKG_VERSION")); + let version_info = rustc_tools_util::get_version_info!(); + println!("{}", version_info); } pub fn main() { @@ -45,6 +48,7 @@ pub fn main() { show_help(); return; } + if std::env::args().any(|a| a == "--version" || a == "-V") { show_version(); return; @@ -94,8 +98,7 @@ where .into_os_string() }, ) - }) - .map(|p| ("CARGO_TARGET_DIR", p)); + }).map(|p| ("CARGO_TARGET_DIR", p)); let exit_status = std::process::Command::new("cargo") .args(&args) -- cgit 1.4.1-3-g733a5 From edfa9feac2d86b4c775c12b155b06efe1efe9d5a Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Thu, 6 Sep 2018 06:20:25 -0700 Subject: Corrected explicit_counter_loop missing lints if variable used after loop --- clippy_lints/src/loops.rs | 10 ++++------ tests/ui/for_loop.rs | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8a12530cb0d..6dfe0a7ec01 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1996,6 +1996,9 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if self.state == VarState::DontWarn { return; } + if self.past_loop { + return; + } if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) { self.past_loop = true; return; @@ -2024,12 +2027,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { _ => (), } } - - if self.past_loop { - self.state = VarState::DontWarn; - return; - } - } else if !self.past_loop && is_loop(expr) { + } else if is_loop(expr) { self.state = VarState::DontWarn; return; } else if is_conditional(expr) { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 76bc96f91b7..286ef190cbf 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -573,16 +573,45 @@ mod issue_2496 { } mod issue_1219 { - // potential false positive for explicit_counter_loop + #[warn(clippy::explicit_counter_loop)] pub fn test() { - let thing = 5; + // should not trigger the lint, because of the continue statement let text = "banana"; let mut count = 0; for ch in text.chars() { if ch == 'a' { continue; } - count += 1 + count += 1; + } + println!("{}", count); + + // should trigger the lint + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + if ch == 'a' { + println!("abc") + } + count += 1; + } + println!("{}", count); + + // should not trigger the lint + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + if ch == 'a' { + count += 1; + } + } + println!("{}", count); + + // should trigger the lint + let text = "banana"; + let mut count = 0; + for _ch in text.chars() { + count += 1; } println!("{}", count); } -- cgit 1.4.1-3-g733a5 From 986c772c24315cd3d9edc5d6820c95dceebd5eaa Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Thu, 6 Sep 2018 16:26:17 +0200 Subject: Reduce number of split_at calls --- clippy_lints/src/literal_representation.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 349878960f4..bff58ed5d33 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -155,6 +155,7 @@ impl<'a> DigitInfo<'a> { (Some(p), s) }; + let len = sans_prefix.len(); let mut last_d = '\0'; for (d_idx, d) in sans_prefix.char_indices() { let suffix_start = if last_d == '_' { @@ -162,10 +163,10 @@ impl<'a> DigitInfo<'a> { } else { d_idx }; - let (digits, suffix) = sans_prefix.split_at(suffix_start); if !float && (d == 'i' || d == 'u') || float && (d == 'f' || d == 'e' || d == 'E') || - !float && is_mistyped_suffix(suffix) { + !float && is_possible_suffix_index(&sans_prefix, suffix_start, len) { + let (digits, suffix) = sans_prefix.split_at(suffix_start); return Self { digits, radix, @@ -557,3 +558,8 @@ impl LiteralRepresentation { fn is_mistyped_suffix(suffix: &str) -> bool { ["_8", "_16", "_32", "_64"].contains(&suffix) } + +fn is_possible_suffix_index(lit: &str, idx: usize, len: usize) -> bool { + ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && + is_mistyped_suffix(lit.split_at(idx).1) +} -- cgit 1.4.1-3-g733a5 From 7bf8d8ba094d2376f468b1f1e3c98c90ee307ac5 Mon Sep 17 00:00:00 2001 From: "Michael A. Plikk" Date: Thu, 6 Sep 2018 17:19:38 +0200 Subject: Simplified boolean expression for checking literal suffixes --- clippy_lints/src/literal_representation.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index bff58ed5d33..304721886cc 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -163,9 +163,8 @@ impl<'a> DigitInfo<'a> { } else { d_idx }; - if !float && (d == 'i' || d == 'u') || - float && (d == 'f' || d == 'e' || d == 'E') || - !float && is_possible_suffix_index(&sans_prefix, suffix_start, len) { + if float && (d == 'f' || d == 'e' || d == 'E') || + !float && (d == 'i' || d == 'u' || is_possible_suffix_index(&sans_prefix, suffix_start, len)) { let (digits, suffix) = sans_prefix.split_at(suffix_start); return Self { digits, -- cgit 1.4.1-3-g733a5 From ce554267b816692204324b26441cee0f25877072 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 7 Sep 2018 05:32:56 -0700 Subject: Updated explicit_counter_loop tests based on discussion in #3135 --- clippy_lints/src/loops.rs | 10 ++++++---- tests/ui/for_loop.rs | 33 ++++++++++----------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6dfe0a7ec01..8a12530cb0d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1996,9 +1996,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if self.state == VarState::DontWarn { return; } - if self.past_loop { - return; - } if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) { self.past_loop = true; return; @@ -2027,7 +2024,12 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { _ => (), } } - } else if is_loop(expr) { + + if self.past_loop { + self.state = VarState::DontWarn; + return; + } + } else if !self.past_loop && is_loop(expr) { self.state = VarState::DontWarn; return; } else if is_conditional(expr) { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 286ef190cbf..029b6f7aa20 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -575,44 +575,31 @@ mod issue_2496 { mod issue_1219 { #[warn(clippy::explicit_counter_loop)] pub fn test() { - // should not trigger the lint, because of the continue statement - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - if ch == 'a' { - continue; - } - count += 1; - } - println!("{}", count); + // should not trigger the lint because variable is used after the loop #473 + let vec = vec![1,2,3]; + let mut index = 0; + for _v in &vec { index += 1 } + println!("index: {}", index); - // should trigger the lint + // should not trigger the lint because the count is conditional #1219 let text = "banana"; let mut count = 0; for ch in text.chars() { if ch == 'a' { - println!("abc") + continue; } count += 1; + println!("{}", count); } - println!("{}", count); - // should not trigger the lint + // should not trigger the lint because the count is conditional let text = "banana"; let mut count = 0; for ch in text.chars() { if ch == 'a' { count += 1; } + println!("{}", count); } - println!("{}", count); - - // should trigger the lint - let text = "banana"; - let mut count = 0; - for _ch in text.chars() { - count += 1; - } - println!("{}", count); } } -- cgit 1.4.1-3-g733a5 From fa3e3cb6eaa00ce61e3215d8f77eff965dfbbfaf Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 7 Sep 2018 17:18:00 +0200 Subject: Fix #3145 by removing assert --- clippy_lints/src/write.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 7ddae1c81c7..69d99cc60f4 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -284,7 +284,6 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let mut idx = 0; loop { if !parser.eat(&token::Comma) { - assert!(parser.eat(&token::Eof)); return (Some(fmtstr), expr); } let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { -- cgit 1.4.1-3-g733a5 From 90f7997771ca34e699f98c30d519711253c2c148 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 7 Sep 2018 17:18:47 +0200 Subject: Add regression test --- tests/ui/issue-3145.rs | 3 +++ tests/ui/issue-3145.stderr | 8 ++++++++ 2 files changed, 11 insertions(+) create mode 100644 tests/ui/issue-3145.rs create mode 100644 tests/ui/issue-3145.stderr diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs new file mode 100644 index 00000000000..f497d5550af --- /dev/null +++ b/tests/ui/issue-3145.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}" a); //~ERROR expected token: `,` +} diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr new file mode 100644 index 00000000000..e289df043a3 --- /dev/null +++ b/tests/ui/issue-3145.stderr @@ -0,0 +1,8 @@ +error: expected token: `,` + --> $DIR/issue-3145.rs:2:19 + | +2 | println!("{}" a); //~ERROR expected token: `,` + | ^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 202db3e09c27eb950abc498a2854b7e8ee7536b6 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 7 Sep 2018 18:03:03 +0200 Subject: rustc_tools_util: don't hardcode crate name --- rustc_tools_util/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 20b598346f1..b2ec9612290 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -8,6 +8,7 @@ macro_rules! get_version_info { let major = env!("CARGO_PKG_VERSION_MAJOR").parse::().unwrap(); let minor = env!("CARGO_PKG_VERSION_MINOR").parse::().unwrap(); let patch = env!("CARGO_PKG_VERSION_PATCH").parse::().unwrap(); + let crate_name = String::from(env!("CARGO_PKG_NAME")); let host_compiler = $crate::get_channel(); let commit_hash = option_env!("GIT_HASH").map(|s| s.to_string()); @@ -20,6 +21,7 @@ macro_rules! get_version_info { host_compiler, commit_hash, commit_date, + crate_name, } }}; } @@ -32,6 +34,7 @@ pub struct VersionInfo { pub host_compiler: Option, pub commit_hash: Option, pub commit_date: Option, + pub crate_name: String, } impl std::fmt::Display for VersionInfo { @@ -40,7 +43,8 @@ impl std::fmt::Display for VersionInfo { Some(_) => { write!( f, - "clippy {}.{}.{} ({} {})", + "{} {}.{}.{} ({} {})", + self.crate_name, self.major, self.minor, self.patch, @@ -49,7 +53,7 @@ impl std::fmt::Display for VersionInfo { )?; }, None => { - write!(f, "clippy {}.{}.{}", self.major, self.minor, self.patch)?; + write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?; }, }; Ok(()) -- cgit 1.4.1-3-g733a5 From a14155088bc3cb7fa8dee3484e37a3212265ed8c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 7 Sep 2018 19:06:02 +0200 Subject: rustc_tools_util: add test --- ci/base-tests.sh | 1 + rustc_tools_util/src/lib.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 94a810e4ef4..0d0a370feef 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -8,6 +8,7 @@ remark -f *.md > /dev/null cargo build --features debugging cargo test --features debugging cd clippy_lints && cargo test && cd .. +cd rustc_tools_util && cargo test && cd .. mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index b2ec9612290..aad9ee88fc7 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(test)] #![feature(tool_lints)] use std::env; @@ -84,3 +85,28 @@ pub fn get_commit_date() -> Option { .ok() .and_then(|r| String::from_utf8(r.stdout).ok()) } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_struct_local() { + let vi = get_version_info!(); + assert_eq!(vi.major, 0); + assert_eq!(vi.minor, 1); + assert_eq!(vi.patch, 0); + assert_eq!(vi.crate_name, "rustc_tools_util"); + // hard to make positive tests for these since they will always change + assert!(vi.commit_hash.is_none()); + assert!(vi.commit_date.is_none()); + } + + #[test] + fn test_display_local() { + let vi = get_version_info!(); + let fmt = format!("{}", vi); + assert_eq!(fmt, "rustc_tools_util 0.1.0"); + } + +} -- cgit 1.4.1-3-g733a5 From f6935be71e8f80461b1c349420950e407d0bfdc5 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 8 Sep 2018 01:32:40 +0200 Subject: clippy_lints: enable crate_visibility_modifier since it is used but no longer part of 2018 edition. Fixes build with https://github.com/rust-lang/rust/pull/53999 --- clippy_lints/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d082bd90971..0619b12cddd 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -10,6 +10,7 @@ #![feature(macro_at_most_once_rep)] #![feature(tool_lints)] #![warn(rust_2018_idioms)] +#![feature(crate_visibility_modifier)] use toml; use rustc_plugin; -- cgit 1.4.1-3-g733a5 From 53c262048c4d7cbffd32074f8037430ca803fbff Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 7 Sep 2018 19:58:19 -0700 Subject: Fix #1219 false positive for explicit_counter_loop --- clippy_lints/src/loops.rs | 3 +++ tests/ui/for_loop.rs | 11 +++++++++++ tests/ui/for_loop.stderr | 8 +++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8a12530cb0d..091b477e33b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1950,6 +1950,9 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { walk_expr(self, expr); self.depth -= 1; return; + } else if let ExprKind::Continue(_) = expr.node { + self.done = true; + return; } walk_expr(self, expr); } diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 029b6f7aa20..a53b9cd2874 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -601,5 +601,16 @@ mod issue_1219 { } println!("{}", count); } + + // should trigger the lint because the count is not conditional + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + if ch == 'a' { + continue; + } + println!("{}", count); + } } } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index bab7bdc77a4..bbd663dc852 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -487,5 +487,11 @@ error: it looks like you're manually copying between slices 547 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 59 previous errors +error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators + --> $DIR/for_loop.rs:608:19 + | +608 | for ch in text.chars() { + | ^^^^^^^^^^^^ + +error: aborting due to 60 previous errors -- cgit 1.4.1-3-g733a5 From 9168746c385776b4f76216de9a9884f4a6b3265f Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 7 Sep 2018 20:46:36 -0700 Subject: Corrected explicit_counter_loop behavior with nested loops --- clippy_lints/src/loops.rs | 3 +-- tests/ui/for_loop.rs | 22 ++++++++++++++++++++++ tests/ui/for_loop.stderr | 8 +++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 091b477e33b..6d9519911eb 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1942,8 +1942,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { } } } else if is_loop(expr) { - self.states.clear(); - self.done = true; + walk_expr(self, expr); return; } else if is_conditional(expr) { self.depth += 1; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index a53b9cd2874..55060b0769d 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -612,5 +612,27 @@ mod issue_1219 { } println!("{}", count); } + + // should trigger the lint because the count is not conditional + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + for i in 0..2 { + let _ = 123; + } + println!("{}", count); + } + + // should not trigger the lint because the count is incremented multiple times + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + for i in 0..2 { + count += 1; + } + println!("{}", count); + } } } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index bbd663dc852..d829147541e 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -493,5 +493,11 @@ error: the variable `count` is used as a loop counter. Consider using `for (coun 608 | for ch in text.chars() { | ^^^^^^^^^^^^ -error: aborting due to 60 previous errors +error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators + --> $DIR/for_loop.rs:619:19 + | +619 | for ch in text.chars() { + | ^^^^^^^^^^^^ + +error: aborting due to 61 previous errors -- cgit 1.4.1-3-g733a5 From 160959d27f144c23631592185b5100a7b7f17ca1 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 7 Sep 2018 22:19:12 +0200 Subject: add tests for #3057 and #2651 Fixes #3057 Fixes #2651 --- tests/ui/non_expressive_names.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index ce3dad391f3..e8b0021e301 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -164,3 +164,23 @@ impl Bar { let _1_ok= 1; } } + +// false positive similar_names (#3057, #2651) +// clippy claimed total_reg_src_size and total_size and +// numb_reg_src_checkouts and total_bin_size were similar +#[derive(Debug, Clone)] +pub(crate) struct DirSizes { + pub(crate) total_size: u64, + pub(crate) numb_bins: u64, + pub(crate) total_bin_size: u64, + pub(crate) total_reg_size: u64, + pub(crate) total_git_db_size: u64, + pub(crate) total_git_repos_bare_size: u64, + pub(crate) numb_git_repos_bare_repos: u64, + pub(crate) numb_git_checkouts: u64, + pub(crate) total_git_chk_size: u64, + pub(crate) total_reg_cache_size: u64, + pub(crate) total_reg_src_size: u64, + pub(crate) numb_reg_cache_entries: u64, + pub(crate) numb_reg_src_checkouts: u64, +} -- cgit 1.4.1-3-g733a5 From 43549ebbf88f46012f898ddd759ba1906c1c80c9 Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Sat, 8 Sep 2018 15:30:50 +0200 Subject: fixes #3151 by skipping the lint instead of crashing --- clippy_lints/src/types.rs | 9 ++++++--- tests/run-pass/ice-3151.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 tests/run-pass/ice-3151.rs diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 400a06c061e..6e629e4cd21 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1810,9 +1810,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { let generics_suggestion_span = generics.span.substitute_dummy({ let pos = snippet_opt(cx, item.span.until(target.span())) - .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))) - .expect("failed to create span for type arguments"); - Span::new(pos, pos, item.span.data().ctxt) + .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); + if let Some(pos) = pos { + Span::new(pos, pos, item.span.data().ctxt) + }else{ + return; + } }); let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); diff --git a/tests/run-pass/ice-3151.rs b/tests/run-pass/ice-3151.rs new file mode 100644 index 00000000000..5ee83dac7b3 --- /dev/null +++ b/tests/run-pass/ice-3151.rs @@ -0,0 +1,13 @@ +#[derive(Clone)] +pub struct HashMap { + hash_builder: S, + table: RawTable, +} + +#[derive(Clone)] +pub struct RawTable { + size: usize, + val: V +} + +fn main() {} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 61249b360e9aef29413516e07a57d3056648e9b3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Sep 2018 23:40:26 +0200 Subject: impl std::fmt::Debug for VersionInfo For clippy, this would print: VersionInfo { crate_name: "clippy", major: 0, minor: 0, patch: 212, commit_hash: "084be7ba", commit_date: "2018-09-09" } --- rustc_tools_util/src/lib.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index aad9ee88fc7..33e1d979dce 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -61,6 +61,30 @@ impl std::fmt::Display for VersionInfo { } } +impl std::fmt::Debug for VersionInfo { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!( + f, + "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}", + self.crate_name, self.major, self.minor, self.patch, + )?; + match self.commit_hash { + Some(_) => { + write!( + f, + ", commit_hash: \"{}\", commit_date: \"{}\" }}", + self.commit_hash.clone().unwrap_or_default().trim(), + self.commit_date.clone().unwrap_or_default().trim() + )?; + }, + None => { + write!(f, " }}")?; + }, + } + Ok(()) + } +} + pub fn get_channel() -> Option { if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") { Some(channel) @@ -105,8 +129,17 @@ mod test { #[test] fn test_display_local() { let vi = get_version_info!(); - let fmt = format!("{}", vi); - assert_eq!(fmt, "rustc_tools_util 0.1.0"); + assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0"); + } + + #[test] + fn test_debug_local() { + let vi = get_version_info!(); + let s = format!("{:?}", vi); + assert_eq!( + s, + "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }" + ); } } -- cgit 1.4.1-3-g733a5 From 404a09d61cf7bc8e5d4e92ae9052a4e10d2ff07d Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 10 Sep 2018 03:01:51 +0200 Subject: the cargo feature: edition 2018 is stabilized in current nightly --- Cargo.toml | 2 -- clippy_lints/Cargo.toml | 2 -- rustc_tools_util/Cargo.toml | 2 -- 3 files changed, 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b293f06713d..80ff21764a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "clippy" version = "0.0.212" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index b168f86f56a..d846ac44363 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "clippy_lints" # begin automatic update diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 01dca0a65b0..020de6c3393 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "rustc_tools_util" version = "0.1.0" -- cgit 1.4.1-3-g733a5 From d512c2bcce5d577a562452eb47628223f3b50e0d Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Mon, 10 Sep 2018 09:03:33 +0200 Subject: add spaces --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6e629e4cd21..cc04eb8eece 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1813,7 +1813,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); if let Some(pos) = pos { Span::new(pos, pos, item.span.data().ctxt) - }else{ + } else { return; } }); -- cgit 1.4.1-3-g733a5 From 3e4f7fc4c0ac5ab3269fcad996368b9c19ec92e6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 15:44:41 +0200 Subject: Don't use the old feature gate --- tests/ui/methods.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 37f4cb2f71e..7faa45b987d 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,5 +1,5 @@ #![feature(tool_lints)] -#![feature(const_fn)] + #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] #![allow(clippy::blacklisted_name, unused, clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, @@ -294,15 +294,15 @@ fn or_fun_call() { A(i32), } - const fn make_const(i: i32) -> i32 { i } + fn make() -> T { unimplemented!(); } let with_enum = Some(Enum::A(1)); with_enum.unwrap_or(Enum::A(5)); - let with_const_fn = Some(1); - with_const_fn.unwrap_or(make_const(5)); + let with_const_fn = Some(::std::time::Duration::from_secs(1)); + with_const_fn.unwrap_or(::std::time::Duration::from_secs(5)); let with_constructor = Some(vec![1]); with_constructor.unwrap_or(make()); -- cgit 1.4.1-3-g733a5 From 1128505fdd7fec09ee0ea170de51aa8f9ab92eb3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 16:02:17 +0200 Subject: Revert "the cargo feature: edition 2018 is stabilized in current nightly" This reverts commit 404a09d61cf7bc8e5d4e92ae9052a4e10d2ff07d. --- Cargo.toml | 2 ++ clippy_lints/Cargo.toml | 2 ++ rustc_tools_util/Cargo.toml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 80ff21764a5..b293f06713d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy" version = "0.0.212" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d846ac44363..b168f86f56a 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy_lints" # begin automatic update diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 020de6c3393..01dca0a65b0 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "rustc_tools_util" version = "0.1.0" -- cgit 1.4.1-3-g733a5 From 146b25e39b58265132c888b57df36ccb5df078c0 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 12 Sep 2018 01:33:28 +0200 Subject: Also run internal lints on the code base --- ci/base-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 0d0a370feef..ba408bbb5fc 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -14,7 +14,7 @@ cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver rm ~/.cargo/bin/cargo-clippy # run clippy on its own codebase... -PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy::all +PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy::all -D clippy::internal # ... and some test directories cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. -- cgit 1.4.1-3-g733a5 From cfa3c33b1d9421076d4fc78e289f41eb743cf546 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 12 Sep 2018 01:34:04 +0200 Subject: Fix lint_without_lint_pass lint --- clippy_lints/src/utils/paths.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 3c03645cc1b..0dea0462d89 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -42,8 +42,8 @@ pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; -pub const LINT: [&str; 2] = ["lint", "Lint"]; -pub const LINT_ARRAY: [&str; 2] = ["lint", "LintArray"]; +pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; +pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"]; pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"]; -- cgit 1.4.1-3-g733a5 From e28440d2e0ee9bc8a5ed81f1c757b16656ad7739 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Wed, 12 Sep 2018 01:34:52 +0200 Subject: Change Hash{Map, Set} to FxHash{Map, Set} --- clippy_dev/src/lib.rs | 2 ++ clippy_lints/src/copies.rs | 14 +++++++++----- clippy_lints/src/functions.rs | 6 +++--- clippy_lints/src/inherent_impl.rs | 6 +++--- clippy_lints/src/len_zero.rs | 6 +++--- clippy_lints/src/lifetimes.rs | 10 +++++----- clippy_lints/src/loops.rs | 30 +++++++++++++++--------------- clippy_lints/src/misc_early.rs | 4 ++-- clippy_lints/src/needless_pass_by_value.rs | 14 +++++++------- clippy_lints/src/regex.rs | 4 ++-- clippy_lints/src/types.rs | 2 ++ clippy_lints/src/unused_label.rs | 6 +++--- clippy_lints/src/utils/author.rs | 6 +++--- clippy_lints/src/utils/internal_lints.rs | 14 ++++---------- clippy_lints/src/utils/usage.rs | 8 ++++---- 15 files changed, 67 insertions(+), 65 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index a872ecf3feb..f10ad81d130 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(tool_lints)] +#![allow(clippy::default_hash_types)] extern crate regex; #[macro_use] extern crate lazy_static; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 8f1823be15a..01063d41ee8 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -2,8 +2,9 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc::ty::Ty; use rustc::hir::*; -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; use std::collections::hash_map::Entry; +use std::hash::BuildHasherDefault; use syntax::symbol::LocalInternedString; use rustc_data_structures::small_vec::OneVector; use crate::utils::{SpanlessEq, SpanlessHash}; @@ -263,8 +264,8 @@ fn if_sequence(mut expr: &Expr) -> (OneVector<&Expr>, OneVector<&Block>) { } /// Return the list of bindings in a pattern. -fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { - fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { +fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap> { + fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut FxHashMap>) { match pat.node { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), PatKind::TupleStruct(_, ref pats, _) => for pat in pats { @@ -299,7 +300,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> = HashMap::with_capacity(exprs.len()); + let mut map: FxHashMap<_, Vec<&_>> = FxHashMap::with_capacity_and_hasher( + exprs.len(), + BuildHasherDefault::default() + ); for expr in exprs { match map.entry(hash(expr)) { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index c170b0a1e15..ec9aa7a4fd3 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -5,7 +5,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc::ty; use rustc::hir::def::Def; -use std::collections::HashSet; +use rustc_data_structures::fx::FxHashSet; use syntax::ast; use rustc_target::spec::abi::Abi; use syntax::source_map::Span; @@ -151,7 +151,7 @@ impl<'a, 'tcx> Functions { let raw_ptrs = iter_input_pats(decl, body) .zip(decl.inputs.iter()) .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty)) - .collect::>(); + .collect::>(); if !raw_ptrs.is_empty() { let tables = cx.tcx.body_tables(body.id()); @@ -177,7 +177,7 @@ fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { struct DerefVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ptrs: HashSet, + ptrs: FxHashSet, tables: &'a ty::TypeckTables<'tcx>, } diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 4ca812e56bd..a78811c31e5 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; use std::default::Default; use syntax_pos::Span; use crate::utils::span_lint_and_then; @@ -41,12 +41,12 @@ declare_clippy_lint! { } pub struct Pass { - impls: HashMap, + impls: FxHashMap, } impl Default for Pass { fn default() -> Self { - Pass { impls: HashMap::new() } + Pass { impls: FxHashMap::default() } } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 4c9c219828d..a31add18a94 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc::ty; -use std::collections::HashSet; +use rustc_data_structures::fx::FxHashSet; use syntax::ast::{Lit, LitKind, Name}; use syntax::source_map::{Span, Spanned}; use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -125,7 +125,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items } // fill the set with current and super traits - fn fill_trait_set(traitt: DefId, set: &mut HashSet, cx: &LateContext<'_, '_>) { + fn fill_trait_set(traitt: DefId, set: &mut FxHashSet, cx: &LateContext<'_, '_>) { if set.insert(traitt) { for supertrait in ::rustc::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); @@ -134,7 +134,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items } if cx.access_levels.is_exported(visited_trait.id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { - let mut current_and_super_traits = HashSet::new(); + let mut current_and_super_traits = FxHashSet::default(); let visited_trait_def_id = cx.tcx.hir.local_def_id(visited_trait.id); fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index beec9bac940..5b04b829453 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -5,7 +5,7 @@ use rustc::{declare_tool_lint, lint_array}; use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::*; -use std::collections::{HashMap, HashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use syntax::source_map::Span; use crate::utils::{last_path_segment, span_lint}; use syntax::symbol::keywords; @@ -237,8 +237,8 @@ fn could_use_elision<'a, 'tcx: 'a>( } } -fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet { - let mut allowed_lts = HashSet::new(); +fn allowed_lts_from(named_generics: &[GenericParam]) -> FxHashSet { + let mut allowed_lts = FxHashSet::default(); for par in named_generics.iter() { if let GenericParamKind::Lifetime { .. } = par.kind { if par.bounds.is_empty() { @@ -263,7 +263,7 @@ fn lts_from_bounds<'a, T: Iterator>(mut vec: Vec, bo /// Number of unique lifetimes in the given vector. fn unique_lifetimes(lts: &[RefLt]) -> usize { - lts.iter().collect::>().len() + lts.iter().collect::>().len() } /// A visitor usable for `rustc_front::visit::walk_ty()`. @@ -424,7 +424,7 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & } struct LifetimeChecker { - map: HashMap, + map: FxHashMap, } impl<'tcx> Visitor<'tcx> for LifetimeChecker { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6d9519911eb..7240819646f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -15,7 +15,7 @@ use rustc::middle::mem_categorization::cmt_; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use rustc_errors::Applicability; -use std::collections::{HashMap, HashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::iter::{once, Iterator}; use syntax::ast; use syntax::source_map::Span; @@ -1030,10 +1030,10 @@ fn check_for_loop_range<'a, 'tcx>( let mut visitor = VarVisitor { cx, var: canonical_id, - indexed_mut: HashSet::new(), - indexed_indirectly: HashMap::new(), - indexed_directly: HashMap::new(), - referenced: HashSet::new(), + indexed_mut: FxHashSet::default(), + indexed_indirectly: FxHashMap::default(), + indexed_directly: FxHashMap::default(), + referenced: FxHashSet::default(), nonindex: false, prefer_mutable: false, }; @@ -1343,7 +1343,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // Look for variables that are incremented once per loop iteration. let mut visitor = IncrementVisitor { cx, - states: HashMap::new(), + states: FxHashMap::default(), depth: 0, done: false, }; @@ -1618,15 +1618,15 @@ struct VarVisitor<'a, 'tcx: 'a> { /// var name to look for as index var: ast::NodeId, /// indexed variables that are used mutably - indexed_mut: HashSet, + indexed_mut: FxHashSet, /// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global - indexed_indirectly: HashMap>, + indexed_indirectly: FxHashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` - indexed_directly: HashMap>, + indexed_directly: FxHashMap>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` - referenced: HashSet, + referenced: FxHashSet, /// has the loop variable been used in expressions other than the index of /// an index op? nonindex: bool, @@ -1906,7 +1906,7 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, // context reference - states: HashMap, // incremented variables + states: FxHashMap, // incremented variables depth: u32, // depth of conditional expressions done: bool, } @@ -2197,8 +2197,8 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e let mut var_visitor = VarCollectorVisitor { cx, - ids: HashSet::new(), - def_ids: HashMap::new(), + ids: FxHashSet::default(), + def_ids: FxHashMap::default(), skip: false, }; var_visitor.visit_expr(cond); @@ -2228,8 +2228,8 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e /// All variables definition IDs are collected struct VarCollectorVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - ids: HashSet, - def_ids: HashMap, + ids: FxHashSet, + def_ids: FxHashMap, skip: bool, } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index c00b3d93c47..35a232f7f32 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,7 +1,7 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; use if_chain::if_chain; -use std::collections::HashMap; use std::char; use syntax::ast::*; use syntax::source_map::Span; @@ -267,7 +267,7 @@ impl EarlyLintPass for MiscEarly { } fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, decl: &FnDecl, _: Span, _: NodeId) { - let mut registered_names: HashMap = HashMap::new(); + let mut registered_names: FxHashMap = FxHashMap::default(); for arg in &decl.inputs { if let PatKind::Ident(_, ident, None) = arg.pat.node { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 340fa4d0ee0..76eaf0dba24 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -9,13 +9,13 @@ use rustc::traits; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc_target::spec::abi::Abi; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet, snippet_opt, span_lint_and_then}; use crate::utils::ptr::get_spans; -use std::collections::{HashMap, HashSet}; use std::borrow::Cow; /// **What it does:** Checks for functions taking arguments by value, but not @@ -301,18 +301,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { struct MovedVariablesCtxt<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, - moved_vars: HashSet, + moved_vars: FxHashSet, /// Spans which need to be prefixed with `*` for dereferencing the /// suggested additional reference. - spans_need_deref: HashMap>, + spans_need_deref: FxHashMap>, } impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { Self { cx, - moved_vars: HashSet::new(), - spans_need_deref: HashMap::new(), + moved_vars: FxHashSet::default(), + spans_need_deref: FxHashMap::default(), } } @@ -344,7 +344,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { if let ExprKind::Match(ref c, ..) = e.node { self.spans_need_deref .entry(vid) - .or_insert_with(HashSet::new) + .or_insert_with(FxHashSet::default) .insert(c.span); } }, @@ -357,7 +357,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { then { self.spans_need_deref .entry(vid) - .or_insert_with(HashSet::new) + .or_insert_with(FxHashSet::default) .insert(local.init .as_ref() .map(|e| e.span) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 6ac40c5a1d2..b7409bfbc9f 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -2,8 +2,8 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; use if_chain::if_chain; -use std::collections::HashSet; use syntax::ast::{LitKind, NodeId, StrStyle}; use syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; @@ -67,7 +67,7 @@ declare_clippy_lint! { #[derive(Clone, Default)] pub struct Pass { - spans: HashSet, + spans: FxHashSet, last: Option, } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index cc04eb8eece..c0369df504a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,3 +1,5 @@ +#![allow(clippy::default_hash_types)] + use crate::reexport::*; use rustc::hir; use rustc::hir::*; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 71d9520c05b..ababaad294d 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -2,7 +2,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; use syntax::ast; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; @@ -31,7 +31,7 @@ declare_clippy_lint! { pub struct UnusedLabel; struct UnusedLabelVisitor<'a, 'tcx: 'a> { - labels: HashMap, + labels: FxHashMap, cx: &'a LateContext<'a, 'tcx>, } @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { let mut v = UnusedLabelVisitor { cx, - labels: HashMap::new(), + labels: FxHashMap::default(), }; walk_fn(&mut v, kind, decl, body.id(), span, fn_id); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e2c809c0c7c..541d5353daf 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -8,8 +8,8 @@ use rustc::{declare_tool_lint, lint_array}; use rustc::hir; use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; -use std::collections::HashMap; use crate::utils::get_attr; /// **What it does:** Generates clippy code that detects the offending pattern @@ -154,7 +154,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { impl PrintVisitor { fn new(s: &'static str) -> Self { Self { - ids: HashMap::new(), + ids: FxHashMap::default(), current: s.to_owned(), } } @@ -186,7 +186,7 @@ impl PrintVisitor { struct PrintVisitor { /// Fields are the current index that needs to be appended to pattern /// binding names - ids: HashMap<&'static str, usize>, + ids: FxHashMap<&'static str, usize>, /// the name that needs to be destructured current: String, } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 7b2d2f15996..f3b915c7ce1 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -3,12 +3,11 @@ use rustc::{declare_tool_lint, lint_array}; use rustc::hir::*; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg}; use syntax::symbol::LocalInternedString; use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use syntax::source_map::Span; -use std::collections::{HashMap, HashSet}; /// **What it does:** Checks for various things we like to keep tidy in clippy. @@ -114,12 +113,10 @@ impl EarlyLintPass for Clippy { } } - - #[derive(Clone, Debug, Default)] pub struct LintWithoutLintPass { - declared_lints: HashMap, - registered_lints: HashSet, + declared_lints: FxHashMap, + registered_lints: FxHashSet, } @@ -129,7 +126,6 @@ impl LintPass for LintWithoutLintPass { } } - impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let hir::ItemKind::Static(ref ty, MutImmutable, body_id) = item.node { @@ -202,7 +198,7 @@ fn is_lint_array_type(ty: &Ty) -> bool { } struct LintCollector<'a, 'tcx: 'a> { - output: &'a mut HashSet, + output: &'a mut FxHashSet, cx: &'a LateContext<'a, 'tcx>, } @@ -221,8 +217,6 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { } } - - pub struct DefaultHashTypes { map: FxHashMap, } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 2661bc945f3..ac18d04e454 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -6,14 +6,14 @@ use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::cmt_; use rustc::middle::mem_categorization::Categorization; use rustc::ty; -use std::collections::HashSet; +use rustc_data_structures::fx::FxHashSet; use syntax::ast::NodeId; use syntax::source_map::Span; /// Returns a set of mutated local variable ids or None if mutations could not be determined. -pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { +pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { let mut delegate = MutVarsDelegate { - used_mutably: HashSet::new(), + used_mutably: FxHashSet::default(), skip: false, }; let def_id = def_id::DefId::local(expr.hir_id.owner); @@ -39,7 +39,7 @@ pub fn is_potentially_mutated<'a, 'tcx: 'a>( } struct MutVarsDelegate { - used_mutably: HashSet, + used_mutably: FxHashSet, skip: bool, } -- cgit 1.4.1-3-g733a5 From 60e8da1647e9001efa760ce52997c95ff518b5ad Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Thu, 13 Sep 2018 11:51:58 +0800 Subject: Fix typo in examples. --- clippy_lints/src/methods.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f428a498b4d..f462c2eb63d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -342,11 +342,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// foo.expect(&format("Err {}: {}", err_code, err_msg)) +/// foo.expect(&format!("Err {}: {}", err_code, err_msg)) /// ``` /// or /// ```rust -/// foo.expect(format("Err {}: {}", err_code, err_msg).as_str()) +/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()) /// ``` /// this can instead be written: /// ```rust @@ -354,7 +354,7 @@ declare_clippy_lint! { /// ``` /// or /// ```rust -/// foo.unwrap_or_else(|_| panic!(format("Err {}: {}", err_code, err_msg).as_str())) +/// foo.unwrap_or_else(|_| panic!(format!("Err {}: {}", err_code, err_msg).as_str())) /// ``` declare_clippy_lint! { pub EXPECT_FUN_CALL, -- cgit 1.4.1-3-g733a5 From 4827ab978e50bbb553d1b35db5787657e97710c6 Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Thu, 13 Sep 2018 13:01:23 +0800 Subject: Remove a wrong suggestion. --- clippy_lints/src/methods.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f462c2eb63d..3d458343a50 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -352,10 +352,6 @@ declare_clippy_lint! { /// ```rust /// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg)) /// ``` -/// or -/// ```rust -/// foo.unwrap_or_else(|_| panic!(format!("Err {}: {}", err_code, err_msg).as_str())) -/// ``` declare_clippy_lint! { pub EXPECT_FUN_CALL, perf, -- cgit 1.4.1-3-g733a5 From 28424ecbfa2e644fb4661c7019346f46dd1eefd1 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 15:57:32 +0200 Subject: fix warnings about trivial casts, mostly {i,u}128 -> {i,u}128, such as "i128::min_value() as i128" --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 6f646e340a0..bcc85c31376 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -206,7 +206,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ty::Array(_, n) => n.assert_usize(self.tcx).expect("array length"), _ => span_bug!(e.span, "typeck error"), }; - self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64)) + self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) }, ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op { UnNot => self.constant_not(&o, self.tables.expr_ty(e)), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e7a8006e5ab..5f001901481 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -9,7 +9,7 @@ #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] #![feature(tool_lints)] -#![warn(rust_2018_idioms)] +#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] use toml; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index cc04eb8eece..66b6fe6170a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1588,7 +1588,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> FullInt::S(i128::from(i64::min_value())), FullInt::S(i128::from(i64::max_value())), ), - IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), + IntTy::I128 => (FullInt::S(i128::min_value()), FullInt::S(i128::max_value())), IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }), ty::Uint(uint_ty) => Some(match uint_ty { @@ -1605,7 +1605,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> FullInt::U(u128::from(u64::min_value())), FullInt::U(u128::from(u64::max_value())), ), - UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), + UintTy::U128 => (FullInt::U(u128::min_value()), FullInt::U(u128::max_value())), UintTy::Usize => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), }), _ => None, -- cgit 1.4.1-3-g733a5 From 49b1a8c77538ca0e559ee634d22712909d3f9bd6 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 13 Sep 2018 11:27:01 +0200 Subject: README: More detailed explanation of tool_lints cc #3164 --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2ccbf495ae..def88186087 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. ### Allowing/denying lints -You can add options to `allow`/`warn`/`deny`: +You can add options to your code to `allow`/`warn`/`deny` Clippy lints: * the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`) @@ -118,6 +118,21 @@ You can add options to `allow`/`warn`/`deny`: Note: `deny` produces errors instead of warnings. +Note: To use the new `clippy::lint_name` syntax, `#![feature(tool_lints)]` has to be activated +currently. If you want to compile your code with the stable toolchain you can use a `cfg_attr` to +activate the `tool_lints` feature: +```rust +#![cfg_attr(feature = "cargo-clippy", feature(tool_lints))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::lint_name))] +``` + +For this to work you have to use Clippy on the nightly toolchain: `cargo +nightly clippy`. If you +want to use Clippy with the stable toolchain, you can stick to the old unscoped method to +enable/disable Clippy lints until `tool_lints` are stable: +```rust +#![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))] +``` + ## Updating rustc Sometimes, rustc moves forward without Clippy catching up. Therefore updating -- cgit 1.4.1-3-g733a5 From c9c32a665e4f218b6fa8419590ceef1ef429caa1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 11 Sep 2018 20:29:00 +0200 Subject: Cleanup README for clippy-preview on stable With the 1.29 release, the `clippy-preview` component will be available on stable which means we don't need nightly/beta anymore. --- README.md | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index def88186087..25dbeaedcba 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ subcommand. #### Step 1: Install rustup You can install [rustup](http://rustup.rs/) on supported platforms. This will help -us install clippy and its dependencies. +us install Clippy and its dependencies. If you already have rustup installed, update to ensure you have the latest rustup and compiler: @@ -54,26 +54,15 @@ rustup and compiler: rustup update ``` -#### Step 2: Install nightly toolchain +#### Step 2: Install Clippy -Rustup integration is still new, you will need a relatively new nightly (2018-07-15 or later). - -To install Rust nightly with [rustup](https://rustup.rs/): +Once you have rustup and the latest stable release (at least Rust 1.29) installed, run the following command: ```terminal -rustup install nightly +rustup component add clippy-preview ``` -#### Step 3: Install clippy - -Once you have rustup and the nightly toolchain installed, run the following command: - -```terminal -rustup component add clippy-preview --toolchain=nightly -``` - -Now you can run Clippy by invoking `cargo +nightly clippy`. If nightly is your -default toolchain in rustup, `cargo clippy` will work fine. +Now you can run Clippy by invoking `cargo clippy`. ### Running Clippy from the command line without installing it @@ -133,15 +122,6 @@ enable/disable Clippy lints until `tool_lints` are stable: #![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))] ``` -## Updating rustc - -Sometimes, rustc moves forward without Clippy catching up. Therefore updating -rustc may leave Clippy a non-functional state until we fix the resulting -breakage. - -You can use the [rust-update](rust-update) script to update rustc only if -Clippy would also update correctly. - ## License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). -- cgit 1.4.1-3-g733a5 From c42cd6092673dd822fe483886c4c6bb9708dd2f1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 11 Sep 2018 20:35:41 +0200 Subject: Remove rust-update script We no longer need this as clippy is installed through rustup now. --- rust-update | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100755 rust-update diff --git a/rust-update b/rust-update deleted file mode 100755 index d065319c736..00000000000 --- a/rust-update +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -if [ "$1" = '-h' ] ; then - echo 'Updates rustc & clippy' - echo 'It first checks if clippy would compile at current nightly and if so, it updates.' - echo 'Options:' - echo '-h: This help message' - echo '-f: Skips the check and just updates' - exit -fi - -set -ex - -renice -n 10 -p $$ - -export CARGO_INCREMENTAL=0 -export RUSTFLAGS='-C target-cpu=native' - -try_out() { - export RUSTUP_HOME=$HOME/.rustup-attempt - test -d $RUSTUP_HOME || (rustup toolchain add nightly && rustup default nightly) - rustup update - cargo +nightly install --force clippy - unset RUSTUP_HOME - export RUSTUP_HOME -} - -[ "$1" = '-f' ] || try_out - -rustup update -cargo +nightly install --force clippy -- cgit 1.4.1-3-g733a5 From 86afd26a6eeb87cf081a65f22b8f79f16aa7da55 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 13 Sep 2018 18:31:39 +0200 Subject: Update ISSUE_TEMPLATE --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a19cb5d2c7c..15006a07b44 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,7 +1,7 @@ $DIR/useless_attribute.rs:5:1 | -5 | #[allow(dead_code, unused_extern_crates)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code, unused_extern_crates)]` +5 | #[allow(dead_code)] + | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` | = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute --> $DIR/useless_attribute.rs:6:1 | -6 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))` +6 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code))` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From c70bfb2cac8854fb63cd08e92256fde37112332c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Sep 2018 11:10:21 +0300 Subject: Revert "the cargo feature: edition 2018 is stabilized in current nightly" This reverts commit 404a09d61cf7bc8e5d4e92ae9052a4e10d2ff07d. --- Cargo.toml | 2 ++ clippy_lints/Cargo.toml | 2 ++ rustc_tools_util/Cargo.toml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 80ff21764a5..b293f06713d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy" version = "0.0.212" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index d846ac44363..b168f86f56a 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "clippy_lints" # begin automatic update diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 020de6c3393..01dca0a65b0 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition"] + [package] name = "rustc_tools_util" version = "0.1.0" -- cgit 1.4.1-3-g733a5 From aaeeaa5330258081a8463f0458e35b85df1beafb Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 14 Sep 2018 12:38:09 +0200 Subject: Add internal lint compiler_lint_functions --- clippy_lints/src/lib.rs | 6 ++- clippy_lints/src/utils/internal_lints.rs | 82 +++++++++++++++++++++++++++++--- clippy_lints/src/utils/paths.rs | 2 + 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3937e5cb9e9..ec00a13c0c6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -293,8 +293,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box serde_api::Serde); reg.register_early_lint_pass(box utils::internal_lints::Clippy); - reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); + reg.register_late_lint_pass(box utils::internal_lints::CompilerLintFunctions::new()); reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::default()); + reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); reg.register_late_lint_pass(box utils::inspector::Pass); reg.register_late_lint_pass(box utils::author::Pass); reg.register_late_lint_pass(box types::TypePass); @@ -494,8 +495,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, - utils::internal_lints::LINT_WITHOUT_LINT_PASS, + utils::internal_lints::COMPILER_LINT_FUNCTIONS, utils::internal_lints::DEFAULT_HASH_TYPES, + utils::internal_lints::LINT_WITHOUT_LINT_PASS, ]); reg.register_lint_group("clippy::all", Some("clippy"), vec![ diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 97a6922d35d..8b3e75159b2 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,14 +1,16 @@ -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; +use crate::utils::{ + match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, +}; +use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::*; +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg}; -use crate::syntax::symbol::LocalInternedString; use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use crate::syntax::source_map::Span; - +use crate::syntax::symbol::LocalInternedString; /// **What it does:** Checks for various things we like to keep tidy in clippy. /// @@ -65,6 +67,29 @@ declare_clippy_lint! { "forbid HashMap and HashSet and suggest the FxHash* variants" } +/// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*` +/// variant of the function. +/// +/// **Why is this bad?** The `utils::*` variants also add a link to the Clippy documentation to the +/// warning/error messages. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// Bad: +/// ```rust +/// cx.span_lint(LINT_NAME, "message"); +/// ``` +/// +/// Good: +/// ```rust +/// utils::span_lint(cx, LINT_NAME, "message"); +/// ``` +declare_clippy_lint! { + pub COMPILER_LINT_FUNCTIONS, + internal, + "usage of the lint functions of the compiler instead of the utils::* variant" +} #[derive(Copy, Clone)] pub struct Clippy; @@ -245,3 +270,48 @@ impl EarlyLintPass for DefaultHashTypes { } } } + +#[derive(Clone, Default)] +pub struct CompilerLintFunctions { + map: FxHashMap, +} + +impl CompilerLintFunctions { + pub fn new() -> Self { + let mut map = FxHashMap::default(); + map.insert("span_lint".to_string(), "utils::span_lint".to_string()); + map.insert("struct_span_lint".to_string(), "utils::span_lint".to_string()); + map.insert("lint".to_string(), "utils::span_lint".to_string()); + map.insert("span_lint_note".to_string(), "utils::span_note_and_lint".to_string()); + map.insert("span_lint_help".to_string(), "utils::span_help_and_lint".to_string()); + Self { map } + } +} + +impl LintPass for CompilerLintFunctions { + fn get_lints(&self) -> LintArray { + lint_array!(COMPILER_LINT_FUNCTIONS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + let fn_name = path.ident.as_str().to_string(); + if let Some(sugg) = self.map.get(&fn_name); + let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); + if match_type(cx, ty, &paths::EARLY_CONTEXT) + || match_type(cx, ty, &paths::LATE_CONTEXT); + then { + span_help_and_lint( + cx, + COMPILER_LINT_FUNCTIONS, + path.ident.span, + "usage of a compiler lint function", + &format!("Please use the Clippy variant of this function: `{}`", sugg), + ); + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0dea0462d89..85036108914 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -26,6 +26,7 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; +pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; @@ -41,6 +42,7 @@ pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; +pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; -- cgit 1.4.1-3-g733a5 From a4e1a90705259ebd4fb0f8e476366b07a1d6b669 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 14 Sep 2018 12:38:57 +0200 Subject: Fix warnings of compiler_lint_functions --- clippy_lints/src/double_parens.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 90aaea90d96..702931c0532 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,6 +1,7 @@ use crate::syntax::ast::*; -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::utils::span_lint; /// **What it does:** Checks for unnecessary double parentheses. /// @@ -35,20 +36,20 @@ impl EarlyLintPass for DoubleParens { match expr.node { ExprKind::Paren(ref in_paren) => match in_paren.node { ExprKind::Paren(_) | ExprKind::Tup(_) => { - cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); + span_lint(cx, DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); }, _ => {}, }, ExprKind::Call(_, ref params) => if params.len() == 1 { let param = ¶ms[0]; if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); + span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, ExprKind::MethodCall(_, ref params) => if params.len() == 2 { let param = ¶ms[1]; if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); + span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, _ => {}, -- cgit 1.4.1-3-g733a5 From 144281c53751422e026bb4a1036491e405a5364e Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 14 Sep 2018 12:39:15 +0200 Subject: Formatting --- clippy_lints/src/utils/internal_lints.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 8b3e75159b2..058f7ee2fab 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -25,7 +25,6 @@ declare_clippy_lint! { "various things that will negatively affect your clippy experience" } - /// **What it does:** Ensures every lint is associated to a `LintPass`. /// /// **Why is this bad?** The compiler only knows lints via a `LintPass`. Without @@ -55,7 +54,6 @@ declare_clippy_lint! { "declaring a lint without associating it in a LintPass" } - /// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet" /// and recommends the FxHash* variants. /// @@ -144,7 +142,6 @@ pub struct LintWithoutLintPass { registered_lints: FxHashSet, } - impl LintPass for LintWithoutLintPass { fn get_lints(&self) -> LintArray { lint_array!(LINT_WITHOUT_LINT_PASS) @@ -196,7 +193,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { } } - fn is_lint_ref_type(ty: &Ty) -> bool { if let TyKind::Rptr( _, @@ -213,7 +209,6 @@ fn is_lint_ref_type(ty: &Ty) -> bool { false } - fn is_lint_array_type(ty: &Ty) -> bool { if let TyKind::Path(ref path) = ty.node { match_qpath(path, &paths::LINT_ARRAY) @@ -249,8 +244,8 @@ pub struct DefaultHashTypes { impl DefaultHashTypes { pub fn default() -> Self { let mut map = FxHashMap::default(); - map.insert("HashMap".to_owned(), "FxHashMap".to_owned()); - map.insert("HashSet".to_owned(), "FxHashSet".to_owned()); + map.insert("HashMap".to_string(), "FxHashMap".to_string()); + map.insert("HashSet".to_string(), "FxHashSet".to_string()); Self { map } } } @@ -265,8 +260,17 @@ impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { let ident_string = ident.to_string(); if let Some(replace) = self.map.get(&ident_string) { - let msg = format!("Prefer {} over {}, it has better performance and we don't need any collision prevention in clippy", replace, ident_string); - span_lint_and_sugg(cx, DEFAULT_HASH_TYPES, ident.span, &msg, "use", replace.to_owned()); + let msg = format!("Prefer {} over {}, it has better performance \ + and we don't need any collision prevention in clippy", + replace, ident_string); + span_lint_and_sugg( + cx, + DEFAULT_HASH_TYPES, + ident.span, + &msg, + "use", + replace.to_string(), + ); } } } -- cgit 1.4.1-3-g733a5 From f3add4acb40faafda0f5727aaa2b9321eb97371a Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 21 Aug 2018 12:46:18 +0200 Subject: convert "".to_string() and "".to_owned() to String::new() --- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/loops.rs | 8 ++++---- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/ranges.rs | 4 ++-- clippy_lints/src/swap.rs | 4 ++-- clippy_lints/src/types.rs | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 21a77e2263f..da6e860e236 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -62,7 +62,7 @@ impl EarlyLintPass for ElseIfWithoutElse { els.span, "if expression with an `else if`, but without a final `else`", "add an `else` block here", - "".to_string() + String::new() ); } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7472700ddbc..3adc4302730 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -956,7 +956,7 @@ fn detect_manual_memcpy<'a, 'tcx>( return if offset.negate { format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) } else { - "".to_owned() + String::new() }; } } @@ -1067,14 +1067,14 @@ fn check_for_loop_range<'a, 'tcx>( let starts_at_zero = is_integer_literal(start, 0); let skip = if starts_at_zero { - "".to_owned() + String::new() } else { format!(".skip({})", snippet(cx, start.span, "..")) }; let take = if let Some(end) = *end { if is_len_call(end, indexed) { - "".to_owned() + String::new() } else { match limits { ast::RangeLimits::Closed => { @@ -1085,7 +1085,7 @@ fn check_for_loop_range<'a, 'tcx>( } } } else { - "".to_owned() + String::new() }; let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index f52d3ccf5a4..dcc4dca3929 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -287,7 +287,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let tyopt = if let Some(ref ty) = l.ty { format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_")) } else { - "".to_owned() + String::new() }; span_lint_and_then(cx, TOPLEVEL_REF_ARG, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 6616099eb9e..6292af92e26 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "an inclusive range would be more readable", |db| { - let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { @@ -175,7 +175,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "an exclusive range would be more readable", |db| { - let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string()); + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); db.span_suggestion(expr.span, "use", diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 1c409263499..c6668288a55 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -119,7 +119,7 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { snippet(cx, idx1.span, ".."), snippet(cx, idx2.span, ".."))) } else { - (false, "".to_owned(), "".to_owned()) + (false, String::new(), String::new()) } } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) { (true, format!(" `{}` and `{}`", first, second), @@ -169,7 +169,7 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { second.mut_addr().to_string(), ) } else { - ("".to_owned(), "".to_owned(), "".to_owned()) + (String::new(), String::new(), String::new()) }; let span = first.span.to(second.span); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 2766ea58d2d..857238e9002 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -319,7 +319,7 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: } let ltopt = if lt.is_elided() { - "".to_owned() + String::new() } else { format!("{} ", lt.name.ident().name.as_str()) }; -- cgit 1.4.1-3-g733a5 From 021748eb6a2fd86bd21e173cef04c19bdb456bb4 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 15 Sep 2018 11:25:40 +0200 Subject: Replace another occurrence of "".to_owned() --- clippy_lints/src/swap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index c6668288a55..cd3a7259aae 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -125,7 +125,7 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { (true, format!(" `{}` and `{}`", first, second), format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr())) } else { - (true, "".to_owned(), "".to_owned()) + (true, String::new(), String::new()) }; let span = w[0].span.to(second.span); -- cgit 1.4.1-3-g733a5 From 407ff8d6bef309fe258dd39c6c8d4456b046e97f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Sep 2018 13:37:21 +0300 Subject: Reintroduce `extern crate` for non-Cargo dependencies, in tests. --- tests/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/matches.rs b/tests/matches.rs index c79e233cc81..3b4910315f5 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -7,7 +7,7 @@ use std::collections::Bound; #[test] fn test_overlapping() { use clippy_lints::matches::overlapping; - use syntax::source_map::DUMMY_SP; + use crate::syntax::source_map::DUMMY_SP; let sp = |s, e| clippy_lints::matches::SpannedRange { span: DUMMY_SP, -- cgit 1.4.1-3-g733a5 From c78cf042ff89e53aec41a276e59ef2dfe429f33c Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 16 Sep 2018 13:07:40 +0200 Subject: Remove unneeded check for method call The check can be removed because the call to `method_chains_args` already performs this check. --- clippy_lints/src/map_unit_fn.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 096ef46555d..7187b79979f 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -250,10 +250,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let hir::StmtKind::Semi(ref expr, _) = stmt.node { - if let hir::ExprKind::MethodCall(_, _, _) = expr.node { - if let Some(arglists) = method_chain_args(expr, &["map"]) { - lint_map_unit_fn(cx, stmt, expr, arglists[0]); - } + if let Some(arglists) = method_chain_args(expr, &["map"]) { + lint_map_unit_fn(cx, stmt, expr, arglists[0]); } } } -- cgit 1.4.1-3-g733a5 From a8b681cc2c5b3bedf3474bdf579339f4f1249d23 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 17 Sep 2018 11:20:27 +0200 Subject: Fix c_void path This got changed in rust-lang/rust#53910 --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0dea0462d89..ff67d381ae7 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -18,7 +18,7 @@ pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; -pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"]; +pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"]; pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; -- cgit 1.4.1-3-g733a5 From c52b33decb561c2e8387f98ac59b351645368a7a Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 19 Sep 2018 07:04:38 +0200 Subject: Make travis check lint list --- ci/base-tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index ba408bbb5fc..2358c8fe2ed 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -9,6 +9,8 @@ cargo build --features debugging cargo test --features debugging cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. +# check that the lint lists are up-to-date +./util/update_lints.py -c mkdir -p ~/rust/cargo/bin cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver -- cgit 1.4.1-3-g733a5 From c06551aba7c078aadfb9c02bf86b1472d6bc4ac3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 19 Sep 2018 07:39:50 +0200 Subject: Update lint list --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2a83118ee8..82596edf30e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -764,6 +764,7 @@ All notable changes to this project will be documented in this file. [`needless_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_bool [`needless_borrow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrow [`needless_borrowed_reference`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrowed_reference +[`needless_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_continue [`needless_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_pass_by_value diff --git a/README.md b/README.md index 79cb35587f4..3d994b4ef85 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 275 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 276 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 9c50aa88105946a979afcfe0b2780195e73c2331 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 19 Sep 2018 21:12:51 +0200 Subject: Mention how to install master Rust in CONTRIBUTING --- CONTRIBUTING.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d1385244a6..fc5372bd7a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Running test suite](#running-test-suite) * [Testing manually](#testing-manually) * [How Clippy works](#how-clippy-works) - * [Fixing nightly build failures](#fixing-nightly-build-failures) + * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) * [Contributions](#contributions) ## Getting started @@ -202,16 +202,29 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. -### Fixing nightly build failures +### Fixing build failures caused by Rust -Clippy will sometimes break with new nightly version releases. This is expected because Clippy still depends on nightly Rust. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in rust. +Clippy will sometimes break because Clippy still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in rust. -In order to find out why Clippy does not work properly with a new nightly version, you can use the [rust-toolstate commit history][toolstate_commit_history]. +In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. -Fixing nightly build failures is also a good way to learn about actual rustc internals. +Fixing build failures caused by rustc changes is also a good way to learn about actual rustc internals. + +If you decide to make Clippy work again with a Rust commit that breaks Clippy, +you probably want to install the latest Rust from master locally and run Clippy +using that version of Rust. + +You can use [rustup-toolchain-install-master][rtim] to do that: + +``` +cargo install rustup-toolchain-install-master +rustup-toolchain-install-master -n master --force +rustup override set master +cargo test +``` ## Contributions @@ -235,3 +248,4 @@ All code in this repository is under the [Mozilla Public License, 2.0](https://w [late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html [toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master [toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/6ce0459f6bfa7c528ae1886492a3e0b5ef0ee547 +[rtim]: https://github.com/kennytm/rustup-toolchain-install-master -- cgit 1.4.1-3-g733a5 From 598df08d88efc816ec97dee9410ebd5a591e5850 Mon Sep 17 00:00:00 2001 From: Jay Kickliter Date: Sun, 16 Sep 2018 16:25:33 -0700 Subject: Add lint for `mem::replace(.., None)`. Suggest `Option::take()` as an alternative. --- clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/mem_replace.rs | 66 +++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/mem_replace.rs | 9 ++++++ tests/ui/mem_replace.stderr | 10 +++++++ 5 files changed, 89 insertions(+) create mode 100644 clippy_lints/src/mem_replace.rs create mode 100644 tests/ui/mem_replace.rs create mode 100644 tests/ui/mem_replace.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ec00a13c0c6..63204d1c387 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -133,6 +133,7 @@ pub mod map_clone; pub mod map_unit_fn; pub mod matches; pub mod mem_forget; +pub mod mem_replace; pub mod methods; pub mod minmax; pub mod misc; @@ -380,6 +381,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_forget::MemForget); + reg.register_late_lint_pass(box mem_replace::MemReplace); reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); reg.register_late_lint_pass(box assign_ops::AssignOps); reg.register_late_lint_pass(box let_if_seq::LetIfSeq); @@ -748,6 +750,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { matches::MATCH_REF_PATS, matches::MATCH_WILD_ERR_ARM, matches::SINGLE_MATCH, + mem_replace::MEM_REPLACE_OPTION_WITH_NONE, methods::CHARS_LAST_CMP, methods::GET_UNWRAP, methods::ITER_CLONED_COLLECT, diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs new file mode 100644 index 00000000000..41658cca3c7 --- /dev/null +++ b/clippy_lints/src/mem_replace.rs @@ -0,0 +1,66 @@ +use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::utils::{match_def_path, match_qpath, match_type, opt_def_id, paths, snippet, span_lint_and_sugg}; +use if_chain::if_chain; + +/// **What it does:** Checks for `mem::replace()` on an `Option` with +/// `None`. +/// +/// **Why is this bad?** `Option` already has the method `take()` for +/// taking its current value (Some(..) or None) and replacing it with +/// `None`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let an_option = Some(0); +/// let replaced = mem::replace(&mut an_option, None); +/// ``` +/// Is better expressed with: +/// ```rust +/// let an_option = Some(0); +/// let taken = an_option.take(); +/// ``` +declare_clippy_lint! { + pub MEM_REPLACE_OPTION_WITH_NONE, + style, + "replacing an `Option` with `None` instead of `take()`" +} + +pub struct MemReplace; + +impl LintPass for MemReplace { + fn get_lints(&self) -> LintArray { + lint_array![MEM_REPLACE_OPTION_WITH_NONE] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::Call(ref func, ref func_args) = expr.node; + if func_args.len() == 2; + if let ExprKind::Path(ref func_qpath) = func.node; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(func_qpath, func.hir_id)); + if match_def_path(cx.tcx, def_id, &paths::MEM_REPLACE); + if let ExprKind::AddrOf(MutMutable, ref replaced) = func_args[0].node; + if match_type(cx, cx.tables.expr_ty(replaced), &paths::OPTION); + if let ExprKind::Path(ref replacement_qpath) = func_args[1].node; + if match_qpath(replacement_qpath, &paths::OPTION_NONE); + if let ExprKind::Path(QPath::Resolved(None, ref replaced_path)) = replaced.node; + then { + let sugg = format!("{}.take()", snippet(cx, replaced_path.span, "")); + span_lint_and_sugg( + cx, + MEM_REPLACE_OPTION_WITH_NONE, + expr.span, + "replacing an `Option` with `None`", + "consider `Option::take()` instead", + sugg + ); + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 30475da7023..eb28cc7e179 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -47,6 +47,7 @@ pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "Link pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; +pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"]; pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"]; pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"]; diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs new file mode 100644 index 00000000000..14f586e71bf --- /dev/null +++ b/tests/ui/mem_replace.rs @@ -0,0 +1,9 @@ +#![feature(tool_lints)] +#![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] + +use std::mem; + +fn main() { + let mut an_option = Some(1); + let _ = mem::replace(&mut an_option, None); +} diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr new file mode 100644 index 00000000000..1ce9fc38093 --- /dev/null +++ b/tests/ui/mem_replace.stderr @@ -0,0 +1,10 @@ +error: replacing an `Option` with `None` + --> $DIR/mem_replace.rs:8:13 + | +8 | let _ = mem::replace(&mut an_option, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` + | + = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 1b6d739ce3826b4990c6899b89a362ee0faf676d Mon Sep 17 00:00:00 2001 From: Jay Kickliter Date: Tue, 18 Sep 2018 10:21:49 -0700 Subject: mem_replace: make examples compilable. --- clippy_lints/src/mem_replace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 41658cca3c7..f516fc5085c 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -15,12 +15,12 @@ use if_chain::if_chain; /// /// **Example:** /// ```rust -/// let an_option = Some(0); +/// let mut an_option = Some(0); /// let replaced = mem::replace(&mut an_option, None); /// ``` /// Is better expressed with: /// ```rust -/// let an_option = Some(0); +/// let mut an_option = Some(0); /// let taken = an_option.take(); /// ``` declare_clippy_lint! { -- cgit 1.4.1-3-g733a5 From 12c7bc1e585d0be7f9fd191dc084cd30ee344385 Mon Sep 17 00:00:00 2001 From: Jay Kickliter Date: Tue, 18 Sep 2018 10:28:58 -0700 Subject: mem_replace: apply update_lints tool. --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82596edf30e..a7b4c5921e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -744,6 +744,7 @@ All notable changes to this project will be documented in this file. [`match_wild_err_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_wild_err_arm [`maybe_infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#maybe_infinite_iter [`mem_forget`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_forget +[`mem_replace_option_with_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_replace_option_with_none [`min_max`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#min_max [`misaligned_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misaligned_transmute [`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op diff --git a/README.md b/README.md index 3d994b4ef85..0d18dcf6cb2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 276 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 277 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 63204d1c387..90094429a36 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -593,6 +593,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { matches::MATCH_REF_PATS, matches::MATCH_WILD_ERR_ARM, matches::SINGLE_MATCH, + mem_replace::MEM_REPLACE_OPTION_WITH_NONE, methods::CHARS_LAST_CMP, methods::CHARS_NEXT_CMP, methods::CLONE_DOUBLE_REF, -- cgit 1.4.1-3-g733a5 From 2f53aaa5bd663fb572f349ca31ad56c32e222977 Mon Sep 17 00:00:00 2001 From: Jay Kickliter Date: Tue, 18 Sep 2018 16:54:01 -0700 Subject: mem_replace: match on path. --- clippy_lints/src/mem_replace.rs | 29 +++++++++++++++++++++++------ tests/ui/mem_replace.rs | 2 ++ tests/ui/mem_replace.stderr | 8 +++++++- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index f516fc5085c..22460ccb5ea 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,7 +1,7 @@ use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::{match_def_path, match_qpath, match_type, opt_def_id, paths, snippet, span_lint_and_sugg}; +use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet, span_lint_and_sugg}; use if_chain::if_chain; /// **What it does:** Checks for `mem::replace()` on an `Option` with @@ -40,25 +40,42 @@ impl LintPass for MemReplace { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { + // Check that `expr` is a call to `mem::replace()` if let ExprKind::Call(ref func, ref func_args) = expr.node; if func_args.len() == 2; if let ExprKind::Path(ref func_qpath) = func.node; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(func_qpath, func.hir_id)); if match_def_path(cx.tcx, def_id, &paths::MEM_REPLACE); - if let ExprKind::AddrOf(MutMutable, ref replaced) = func_args[0].node; - if match_type(cx, cx.tables.expr_ty(replaced), &paths::OPTION); + + // Check that second argument is `Option::None` if let ExprKind::Path(ref replacement_qpath) = func_args[1].node; if match_qpath(replacement_qpath, &paths::OPTION_NONE); - if let ExprKind::Path(QPath::Resolved(None, ref replaced_path)) = replaced.node; + then { - let sugg = format!("{}.take()", snippet(cx, replaced_path.span, "")); + // Since this is a late pass (already type-checked), + // and we already know that the second argument is an + // `Option`, we do not need to check if the first + // argument's type. All that's left is to get + // replacee's path. + let replaced_path = match func_args[0].node { + ExprKind::AddrOf(MutMutable, ref replaced) => { + if let ExprKind::Path(QPath::Resolved(None, ref replaced_path)) = replaced.node { + replaced_path + } else { + return + } + }, + ExprKind::Path(QPath::Resolved(None, ref replaced_path)) => replaced_path, + _ => return, + }; + span_lint_and_sugg( cx, MEM_REPLACE_OPTION_WITH_NONE, expr.span, "replacing an `Option` with `None`", "consider `Option::take()` instead", - sugg + format!("{}.take()", snippet(cx, replaced_path.span, "")) ); } } diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 14f586e71bf..62df42ef2d2 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -6,4 +6,6 @@ use std::mem; fn main() { let mut an_option = Some(1); let _ = mem::replace(&mut an_option, None); + let an_option = &mut Some(1); + let _ = mem::replace(an_option, None); } diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 1ce9fc38093..8385fa3cb3c 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -6,5 +6,11 @@ error: replacing an `Option` with `None` | = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` -error: aborting due to previous error +error: replacing an `Option` with `None` + --> $DIR/mem_replace.rs:10:13 + | +10 | let _ = mem::replace(an_option, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 79cda3bb1ef7f4261bf0fb18bbb141127d31c5a5 Mon Sep 17 00:00:00 2001 From: Jay Kickliter Date: Wed, 19 Sep 2018 14:54:38 -0700 Subject: mem_replace: fix grammar. --- clippy_lints/src/mem_replace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 22460ccb5ea..fd22e3afe80 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { then { // Since this is a late pass (already type-checked), // and we already know that the second argument is an - // `Option`, we do not need to check if the first + // `Option`, we do not need to check the first // argument's type. All that's left is to get // replacee's path. let replaced_path = match func_args[0].node { -- cgit 1.4.1-3-g733a5 From f9511bfdc3753f22cfc33d53159bcd4226c307c2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 20 Sep 2018 06:56:13 +0200 Subject: s/rust/Rust, repeat 'Clippy' less --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc5372bd7a0..57260b17cf7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -204,16 +204,16 @@ That's why the `else_if_without_else` example uses the `register_early_lint_pass ### Fixing build failures caused by Rust -Clippy will sometimes break because Clippy still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in rust. +Clippy will sometimes break because it still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. -Fixing build failures caused by rustc changes is also a good way to learn about actual rustc internals. +Fixing build failures caused by rustc updates, can also be a good way to learn about rustc internals. -If you decide to make Clippy work again with a Rust commit that breaks Clippy, +If you decide to make Clippy work again with a Rust commit that breaks it, you probably want to install the latest Rust from master locally and run Clippy using that version of Rust. -- cgit 1.4.1-3-g733a5 From 2b57cec649013e5209d10c6b83ecc963b019c3e1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 20 Sep 2018 06:58:07 +0200 Subject: s/rustc/Rust/ --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 57260b17cf7..dda6ebb50d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -211,7 +211,7 @@ You will then have to look for the last commit that contains `test-pass -> build The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. -Fixing build failures caused by rustc updates, can also be a good way to learn about rustc internals. +Fixing build failures caused by Rust updates, can also be a good way to learn about Rust internals. If you decide to make Clippy work again with a Rust commit that breaks it, you probably want to install the latest Rust from master locally and run Clippy -- cgit 1.4.1-3-g733a5 From f72cfc2985d1db30d351e425ec7f45f6b0a328a5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 20 Sep 2018 07:10:23 +0200 Subject: Mention rustup component history --- CONTRIBUTING.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dda6ebb50d6..1341ca30ebd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -204,14 +204,15 @@ That's why the `else_if_without_else` example uses the `register_early_lint_pass ### Fixing build failures caused by Rust -Clippy will sometimes break because it still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. +Clippy will sometimes break because it still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals. In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. -Fixing build failures caused by Rust updates, can also be a good way to learn about Rust internals. +To check if Clippy is available for a specific target platform, you can check +the [rustup component history][rustup_component_history]. If you decide to make Clippy work again with a Rust commit that breaks it, you probably want to install the latest Rust from master locally and run Clippy @@ -249,3 +250,4 @@ All code in this repository is under the [Mozilla Public License, 2.0](https://w [toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master [toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/6ce0459f6bfa7c528ae1886492a3e0b5ef0ee547 [rtim]: https://github.com/kennytm/rustup-toolchain-install-master +[rustup_component_history]: https://mexus.github.io/rustup-components-history -- cgit 1.4.1-3-g733a5 From 92034e20c86bf3497b855dc3a756bfadae8ec006 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sat, 15 Sep 2018 19:14:08 +0300 Subject: Use span_suggestion_with_applicability instead of span_suggestion --- clippy_lints/src/assign_ops.rs | 14 +++++-- clippy_lints/src/attrs.rs | 8 +++- clippy_lints/src/bit_mask.rs | 8 +++- clippy_lints/src/booleans.rs | 4 +- clippy_lints/src/collapsible_if.rs | 7 +++- clippy_lints/src/const_static_lifetime.rs | 8 +++- clippy_lints/src/copies.rs | 3 +- clippy_lints/src/entry.rs | 15 ++++++- clippy_lints/src/eq_op.rs | 28 +++++++++++-- clippy_lints/src/eta_reduction.rs | 8 +++- clippy_lints/src/format.rs | 15 ++++++- clippy_lints/src/identity_conversion.rs | 22 ++++++++-- .../src/if_let_redundant_pattern_matching.rs | 4 +- clippy_lints/src/int_plus_one.rs | 8 +++- clippy_lints/src/large_enum_variant.rs | 4 +- clippy_lints/src/let_if_seq.rs | 10 +++-- clippy_lints/src/loops.rs | 3 +- clippy_lints/src/map_unit_fn.rs | 7 +++- clippy_lints/src/matches.rs | 8 +++- clippy_lints/src/methods.rs | 29 +++++++++++-- clippy_lints/src/misc.rs | 27 +++++++++--- clippy_lints/src/misc_early.rs | 14 +++++-- clippy_lints/src/needless_borrow.rs | 15 ++++++- clippy_lints/src/needless_borrowed_ref.rs | 8 +++- clippy_lints/src/needless_pass_by_value.rs | 23 ++++++++--- clippy_lints/src/ptr.rs | 28 ++++++++++--- clippy_lints/src/question_mark.rs | 4 +- clippy_lints/src/ranges.rs | 19 ++++++--- clippy_lints/src/returns.rs | 8 +++- clippy_lints/src/swap.rs | 18 ++++++-- clippy_lints/src/transmute.rs | 48 ++++++++++++++++++---- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 22 ++++++++-- 33 files changed, 367 insertions(+), 82 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index d50b72b19ac..5cf714bed86 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -6,6 +6,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::syntax::ast; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` /// patterns. @@ -78,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let r = &sugg::Sugg::hir(cx, rhs, ".."); let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); - db.span_suggestion( + db.span_suggestion_with_applicability( expr.span, &format!( "Did you mean {} = {} {} {} or {}? Consider replacing it with", @@ -89,8 +90,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { long ), format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + Applicability::Unspecified, ); - db.span_suggestion(expr.span, "or", long); + db.span_suggestion_with_applicability( + expr.span, + "or", + long, + Applicability::Unspecified, + ); } }, ); @@ -172,10 +179,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - db.span_suggestion( + db.span_suggestion_with_applicability( expr.span, "replace it with", format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + Applicability::Unspecified, ); } }, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 128a5ab147e..197aa88cbbe 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -13,6 +13,7 @@ use crate::rustc::ty::{self, TyCtxt}; use semver::Version; use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use crate::syntax::source_map::Span; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -203,7 +204,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { "useless lint attribute", |db| { sugg = sugg.replacen("#[", "#![", 1); - db.span_suggestion(line_span, "if you just forgot a `!`, use", sugg); + db.span_suggestion_with_applicability( + line_span, + "if you just forgot a `!`, use", + sugg, + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 93c6bee03bf..52c6d4c71dc 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -7,6 +7,7 @@ use crate::syntax::source_map::Span; use crate::utils::{span_lint, span_lint_and_then}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for incompatible bit masks in comparisons. /// @@ -138,7 +139,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { "bit mask could be simplified with a call to `trailing_zeros`", |db| { let sugg = Sugg::hir(cx, left1, "...").maybe_par(); - db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones())); + db.span_suggestion_with_applicability( + e.span, + "try", + format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index b2639330071..85f6eeb19ef 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -6,6 +6,7 @@ use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; use crate::rustc_data_structures::thin_vec::ThinVec; use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -390,10 +391,11 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { "this expression can be optimized out by applying boolean operations to the \ outer expression", ); - db.span_suggestion( + db.span_suggestion_with_applicability( e.span, "it would look like the following", suggest(self.cx, suggestion, &h2q.terminals).0, + Applicability::Unspecified, ); }, ); diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index a24436991e5..c139b0f0c1f 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -19,6 +19,7 @@ use crate::syntax::ast; use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; use crate::utils::sugg::Sugg; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for nested `if` statements which can be collapsed /// by `&&`-combining their conditions and for `else { if ... }` expressions @@ -133,11 +134,13 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { let lhs = Sugg::ast(cx, check, ".."); let rhs = Sugg::ast(cx, check_inner, ".."); - db.span_suggestion(expr.span, + db.span_suggestion_with_applicability(expr.span, "try", format!("if {} {}", lhs.and(&rhs), - snippet_block(cx, content.span, ".."))); + snippet_block(cx, content.span, "..")), + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 6daddb5fe13..92c609d9858 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -2,6 +2,7 @@ use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{in_macro, snippet, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// @@ -60,7 +61,12 @@ impl StaticConst { lifetime.ident.span, "Constants have by default a `'static` lifetime", |db| { - db.span_suggestion(ty.span, "consider removing `'static`", sugg); + db.span_suggestion_with_applicability( + ty.span, + "consider removing `'static`", + sugg, + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 76c8360be62..04a297e5e7e 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -202,7 +202,8 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { |db| { db.span_note(i.body.span, "same as this"); - // Note: this does not use `span_suggestion` on purpose: there is no clean way + // Note: this does not use `span_suggestion_with_applicability` on purpose: + // there is no clean way // to remove the other arm. Building a span and suggest to replace it to "" // makes an even more confusing error message. Also in order not to make up a // span for the whole pattern, the suggestion is only shown when there is only diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 167f5633b2e..be9af18c911 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -6,6 +6,7 @@ use if_chain::if_chain; use crate::syntax::source_map::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap` /// or `BTreeMap`. @@ -139,14 +140,24 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, params[1].span, ".."), snippet(self.cx, params[2].span, "..")); - db.span_suggestion(self.span, "consider using", help); + db.span_suggestion_with_applicability( + self.span, + "consider using", + help, + Applicability::Unspecified, + ); } else { let help = format!("{}.entry({})", snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, "..")); - db.span_suggestion(self.span, "consider using", help); + db.span_suggestion_with_applicability( + self.span, + "consider using", + help, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index d182faa1e5c..2ad04cd6fbe 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -2,6 +2,7 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, @@ -113,7 +114,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); - db.span_suggestion(left.span, "use the left value directly", lsnip); + db.span_suggestion_with_applicability( + left.span, + "use the left value directly", + lsnip, + Applicability::Unspecified, + ); }) } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { span_lint_and_then( @@ -123,7 +129,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { "needlessly taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); - db.span_suggestion(right.span, "use the right value directly", rsnip); + db.span_suggestion_with_applicability( + right.span, + "use the right value directly", + rsnip, + Applicability::Unspecified,); }, ) } @@ -135,7 +145,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); - db.span_suggestion(left.span, "use the left value directly", lsnip); + db.span_suggestion_with_applicability( + left.span, + "use the left value directly", + lsnip, + Applicability::Unspecified, + ); }) } }, @@ -146,7 +161,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); - db.span_suggestion(right.span, "use the right value directly", rsnip); + db.span_suggestion_with_applicability( + right.span, + "use the right value directly", + rsnip, + Applicability::Unspecified, + ); }) } }, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index e331f6adf3a..b40ff8b51cd 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -3,6 +3,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; use crate::rustc::hir::*; use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; +use crate::rustc_errors::Applicability; #[allow(missing_copy_implementations)] pub struct EtaPass; @@ -96,7 +97,12 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { } span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { if let Some(snippet) = snippet_opt(cx, caller.span) { - db.span_suggestion(expr.span, "remove closure as shown", snippet); + db.span_suggestion_with_applicability( + expr.span, + "remove closure as shown", + snippet, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index fbc3c750cde..868b7c19cef 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -7,6 +7,7 @@ use crate::syntax::ast::LitKind; use crate::syntax_pos::Span; use crate::utils::paths; use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -60,7 +61,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { then { let sugg = format!("{}.to_string()", snippet(cx, format_arg, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { - db.span_suggestion(expr.span, "consider using .to_string()", sugg); + db.span_suggestion_with_applicability( + expr.span, + "consider using .to_string()", + sugg, + Applicability::Unspecified, + ); }); } } @@ -70,7 +76,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if tup.is_empty() { let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { - db.span_suggestion(span, "consider using .to_string()", sugg); + db.span_suggestion_with_applicability( + span, + "consider using .to_string()", + sugg, + Applicability::Unspecified, + ); }); } }, diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 24b0d57d098..2a764ad73d4 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -4,6 +4,7 @@ use crate::rustc::hir::*; use crate::syntax::ast::NodeId; use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; use crate::utils::{opt_def_id, paths, resolve_node}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions. /// @@ -63,7 +64,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { if same_tys(cx, a, b) { let sugg = snippet(cx, args[0].span, "").into_owned(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion(e.span, "consider removing `.into()`", sugg); + db.span_suggestion_with_applicability( + e.span, + "consider removing `.into()`", + sugg, + Applicability::Unspecified, + ); }); } } @@ -73,7 +79,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { if same_tys(cx, a, b) { let sugg = snippet(cx, args[0].span, "").into_owned(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion(e.span, "consider removing `.into_iter()`", sugg); + db.span_suggestion_with_applicability( + e.span, + "consider removing `.into_iter()`", + sugg, + Applicability::Unspecified, + ); }); } } @@ -88,7 +99,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg = snippet(cx, args[0].span.source_callsite(), "").into_owned(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion(e.span, &sugg_msg, sugg); + db.span_suggestion_with_applicability( + e.span, + &sugg_msg, + sugg, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index c996c91b48b..64d088d2a99 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -2,6 +2,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Lint for redundant pattern matching over `Result` or /// `Option` @@ -77,10 +78,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { &format!("redundant pattern matching, consider using `{}`", good_method), |db| { let span = expr.span.with_hi(op.span.hi()); - db.span_suggestion( + db.span_suggestion_with_applicability( span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::Unspecified, ); }, ); diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 023a88e1ffa..4608ca696e1 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -2,6 +2,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::utils::{snippet_opt, span_lint_and_then}; @@ -152,7 +153,12 @@ impl IntPlusOne { fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { - db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation); + db.span_suggestion_with_applicability( + block.span, + "change `>= y + 1` to `> y` as shown", + recommendation, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 87f9804c1ae..8ff53e15c31 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -5,6 +5,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; use crate::utils::{snippet_opt, span_lint_and_then}; use crate::rustc::ty::layout::LayoutOf; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for large size differences between variants on /// `enum`s. @@ -96,11 +97,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { VariantData::Unit(_) => unreachable!(), }; if let Some(snip) = snippet_opt(cx, span) { - db.span_suggestion( + db.span_suggestion_with_applicability( span, "consider boxing the large fields to reduce the total size of the \ enum", format!("Box<{}>", snip), + Applicability::Unspecified, ); return; } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 10dc3cae8af..4947715e293 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -6,6 +6,7 @@ use crate::rustc::hir::BindingAnnotation; use crate::rustc::hir::def::Def; use crate::syntax::ast; use crate::utils::{snippet, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for variable declarations immediately followed by a /// conditional affectation. @@ -120,9 +121,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { span, "`if _ { .. } else { .. }` is an expression", |db| { - db.span_suggestion(span, - "it is more idiomatic to write", - sug); + db.span_suggestion_with_applicability( + span, + "it is more idiomatic to write", + sug, + Applicability::Unspecified, + ); if !mutability.is_empty() { db.note("you might not need `mut` at all"); } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3adc4302730..70608b9895f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1196,7 +1196,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx expr.span, "this range is empty so this for loop will never run", |db| { - db.span_suggestion( + db.span_suggestion_with_applicability( arg.span, "consider using the following if you are attempting to iterate over this \ range in reverse", @@ -1206,6 +1206,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx dots = dots, start = start_snippet ), + Applicability::Unspecified, ); }, ); diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 7187b79979f..5f592a722d1 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -228,7 +228,12 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_"), snippet(cx, reduced_expr_span, "_")); - db.span_suggestion(stmt.span, "try this", suggestion); + db.span_suggestion_with_applicability( + stmt.span, + "try this", + suggestion, + Applicability::Unspecified, + ); } else { let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", variant, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index a4c2681e359..7cc70cb0834 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -12,6 +12,7 @@ use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for matches with a single arm where an `if let` /// will usually suffice. @@ -339,7 +340,12 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex }; if let Some(sugg) = sugg { - db.span_suggestion(expr.span, "consider using an if/else expression", sugg); + db.span_suggestion_with_applicability( + expr.span, + "consider using an if/else expression", + sugg, + Applicability::Unspecified, + ); } } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 1e03503d313..f61995cf265 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -17,6 +17,7 @@ use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, i use crate::utils::paths; use crate::utils::sugg; use crate::consts::{constant, Constant}; +use crate::rustc_errors::Applicability; #[derive(Clone)] pub struct Pass; @@ -1127,8 +1128,18 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp let refs: String = iter::repeat('&').take(n + 1).collect(); let derefs: String = iter::repeat('*').take(n).collect(); let explicit = format!("{}{}::clone({})", refs, ty, snip); - db.span_suggestion(expr.span, "try dereferencing it", format!("{}({}{}).clone()", refs, derefs, snip.deref())); - db.span_suggestion(expr.span, "or try being explicit about what type to clone", explicit); + db.span_suggestion_with_applicability( + expr.span, + "try dereferencing it", + format!("{}({}{}).clone()", refs, derefs, snip.deref()), + Applicability::Unspecified, + ); + db.span_suggestion_with_applicability( + expr.span, + "or try being explicit about what type to clone", + explicit, + Applicability::Unspecified, + ); }, ); return; // don't report clone_on_copy @@ -1169,7 +1180,12 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp } span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { if let Some((text, snip)) = snip { - db.span_suggestion(expr.span, text, snip); + db.span_suggestion_with_applicability( + expr.span, + text, + snip, + Applicability::Unspecified, + ); } }); } @@ -1639,7 +1655,12 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { - db.span_suggestion(expr.span, "try using and_then instead", hint); + db.span_suggestion_with_applicability( + expr.span, + "try using and_then instead", + hint, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index dcc4dca3929..ac4e93f633a 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -13,6 +13,7 @@ use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant use crate::utils::sugg::Sugg; use crate::syntax::ast::{LitKind, CRATE_NODE_ID}; use crate::consts::{constant, Constant}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -294,12 +295,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { - db.span_suggestion(s.span, + db.span_suggestion_with_applicability(s.span, "try", format!("let {name}{tyopt} = {initref};", name=snippet(cx, i.span, "_"), tyopt=tyopt, - initref=initref)); + initref=initref), + Applicability::Unspecified, + ); } ); } @@ -317,8 +320,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "boolean short circuit operator in statement may be clearer using an explicit test", |db| { let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; - db.span_suggestion(s.span, "replace it with", - format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, ".."))); + db.span_suggestion_with_applicability( + s.span, + "replace it with", + format!("if {} {{ {}; }}", + sugg, + &snippet(cx, b.span, "..")), + Applicability::Unspecified, + ); }); } }; @@ -363,10 +372,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let lhs = Sugg::hir(cx, left, ".."); let rhs = Sugg::hir(cx, right, ".."); - db.span_suggestion( + db.span_suggestion_with_applicability( expr.span, "consider comparing them within some error", format!("({}).abs() < error", lhs - rhs), + Applicability::Unspecified, ); db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); }); @@ -534,7 +544,12 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } } } - db.span_suggestion(expr.span, "try", snip.to_string()); + db.span_suggestion_with_applicability( + expr.span, + "try", + snip.to_string(), + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 5a509802b61..c66fb5d6e47 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -7,6 +7,7 @@ use crate::syntax::ast::*; use crate::syntax::source_map::Span; use crate::syntax::visit::FnKind; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -307,7 +308,12 @@ impl EarlyLintPass for MiscEarly { "Try not to call a closure in the expression where it is declared.", |db| if decl.inputs.is_empty() { let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion(expr.span, "Try doing something like: ", hint); + db.span_suggestion_with_applicability( + expr.span, + "Try doing something like: ", + hint, + Applicability::Unspecified, + ); }, ); } @@ -392,15 +398,17 @@ impl MiscEarly { lit.span, "this is a decimal constant", |db| { - db.span_suggestion( + db.span_suggestion_with_applicability( lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion", src.trim_left_matches(|c| c == '_' || c == '0').to_string(), + Applicability::Unspecified, ); - db.span_suggestion( + db.span_suggestion_with_applicability( lit.span, "if you mean to use an octal constant, use `0o`", format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')), + Applicability::Unspecified, ); }); } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index ec53f76095f..11e1a99fd7f 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -9,6 +9,7 @@ use crate::rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, Pa use crate::rustc::ty; use crate::rustc::ty::adjustment::{Adjust, Adjustment}; use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. @@ -75,7 +76,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { by the compiler", |db| { if let Some(snippet) = snippet_opt(cx, inner.span) { - db.span_suggestion(e.span, "change this to", snippet); + db.span_suggestion_with_applicability( + e.span, + "change this to", + snippet, + Applicability::Unspecified, + ); } }, ); @@ -103,7 +109,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { "this pattern creates a reference to a reference", |db| { if let Some(snippet) = snippet_opt(cx, name.span) { - db.span_suggestion(pat.span, "change this to", snippet); + db.span_suggestion_with_applicability( + pat.span, + "change this to", + snippet, + Applicability::Unspecified, + ); } } ) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 2db9b9d165b..08ce0de21c6 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -7,6 +7,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use crate::utils::{in_macro, snippet, span_lint_and_then}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for useless borrowed references. /// @@ -77,7 +78,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { "this pattern takes a reference on something that is being de-referenced", |db| { let hint = snippet(cx, spanned_name.span, "..").into_owned(); - db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); + db.span_suggestion_with_applicability( + pat.span, + "try removing the `&ref` part and just keep", + hint, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index eb4cbe22f30..aa644e4c339 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -17,6 +17,7 @@ use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_sel snippet, snippet_opt, span_lint_and_then}; use crate::utils::ptr::get_spans; use std::borrow::Cow; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its @@ -227,19 +228,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { }).unwrap()); then { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); - db.span_suggestion(input.span, + db.span_suggestion_with_applicability( + input.span, "consider changing the type to", - slice_ty); + slice_ty, + Applicability::Unspecified, + ); for (span, suggestion) in clone_spans { - db.span_suggestion( + db.span_suggestion_with_applicability( span, &snippet_opt(cx, span) .map_or( "change the call to".into(), |x| Cow::from(format!("change `{}` to", x)), ), - suggestion.into() + suggestion.into(), + Applicability::Unspecified, ); } @@ -252,10 +257,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if match_type(cx, ty, &paths::STRING) { if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { - db.span_suggestion(input.span, "consider changing the type to", "&str".to_string()); + db.span_suggestion_with_applicability( + input.span, + "consider changing the type to", + "&str".to_string(), + Applicability::Unspecified, + ); for (span, suggestion) in clone_spans { - db.span_suggestion( + db.span_suggestion_with_applicability( span, &snippet_opt(cx, span) .map_or( @@ -263,6 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { |x| Cow::from(format!("change `{}` to", x)) ), suggestion.into(), + Applicability::Unspecified, ); } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 1aefc84cb49..f8d872cb4e6 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -12,6 +12,7 @@ use crate::syntax::source_map::Span; use crate::syntax_pos::MultiSpan; use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; use crate::utils::ptr::get_spans; +use crate::rustc_errors::Applicability; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless the references are mutable. It will also suggest you @@ -181,16 +182,22 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: with non-Vec-based slices.", |db| { if let Some(ref snippet) = ty_snippet { - db.span_suggestion(arg.span, "change this to", format!("&[{}]", snippet)); + db.span_suggestion_with_applicability( + arg.span, + "change this to", + format!("&[{}]", snippet), + Applicability::Unspecified, + ); } for (clonespan, suggestion) in spans { - db.span_suggestion( + db.span_suggestion_with_applicability( clonespan, &snippet_opt(cx, clonespan).map_or( "change the call to".into(), |x| Cow::Owned(format!("change `{}` to", x)), ), suggestion.into(), + Applicability::Unspecified, ); } }, @@ -204,15 +211,21 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do.", |db| { - db.span_suggestion(arg.span, "change this to", "&str".into()); + db.span_suggestion_with_applicability( + arg.span, + "change this to", + "&str".into(), + Applicability::Unspecified, + ); for (clonespan, suggestion) in spans { - db.span_suggestion_short( + db.span_suggestion_short_with_applicability( clonespan, &snippet_opt(cx, clonespan).map_or( "change the call to".into(), |x| Cow::Owned(format!("change `{}` to", x)), ), suggestion.into(), + Applicability::Unspecified, ); } }, @@ -239,7 +252,12 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: arg.span, "using a reference to `Cow` is not recommended.", |db| { - db.span_suggestion(arg.span, "change this to", "&".to_owned() + &r); + db.span_suggestion_with_applicability( + arg.span, + "change this to", + "&".to_owned() + &r, + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 93ea00cec77..f4920e52a71 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,6 +8,7 @@ use crate::syntax::ptr::P; use crate::utils::{match_def_path, match_type, span_lint_and_then}; use crate::utils::paths::*; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for expressions that could be replaced by the question mark operator /// @@ -70,10 +71,11 @@ impl QuestionMarkPass { |db| { let receiver_str = &Sugg::hir(cx, subject, ".."); - db.span_suggestion( + db.span_suggestion_with_applicability( expr.span, "replace_it_with", format!("{}?;", receiver_str), + Applicability::Unspecified, ); } ) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 6292af92e26..8ca0750684e 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -7,6 +7,7 @@ use crate::syntax::source_map::Spanned; use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt}; use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::sugg::Sugg; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -150,13 +151,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let end = Sugg::hir(cx, y, "y"); if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { - db.span_suggestion(expr.span, + db.span_suggestion_with_applicability(expr.span, "use", - format!("({}..={})", start, end)); + format!("({}..={})", start, end), + Applicability::Unspecified, + ); } else { - db.span_suggestion(expr.span, + db.span_suggestion_with_applicability(expr.span, "use", - format!("{}..={}", start, end)); + format!("{}..={}", start, end), + Applicability::Unspecified, + ); } } }, @@ -177,9 +182,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); - db.span_suggestion(expr.span, + db.span_suggestion_with_applicability(expr.span, "use", - format!("{}..{}", start, end)); + format!("{}..{}", start, end), + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 4aed77f43e1..34b7614e439 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -4,6 +4,7 @@ use if_chain::if_chain; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax::visit::FnKind; +use crate::rustc_errors::Applicability; use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; @@ -108,7 +109,12 @@ impl ReturnPass { } span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { - db.span_suggestion(ret_span, "remove `return` as shown", snippet); + db.span_suggestion_with_applicability( + ret_span, + "remove `return` as shown", + snippet, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index cd3a7259aae..8859d545194 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -6,6 +6,7 @@ use if_chain::if_chain; use crate::rustc::ty; use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for manual swapping. /// @@ -136,7 +137,12 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { &format!("this looks like you are swapping{} manually", what), |db| { if !sugg.is_empty() { - db.span_suggestion(span, "try", sugg); + db.span_suggestion_with_applicability( + span, + "try", + sugg, + Applicability::Unspecified, + ); if replace { db.note("or maybe you should use `std::mem::replace`?"); @@ -180,8 +186,14 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { &format!("this looks like you are trying to swap{}", what), |db| { if !what.is_empty() { - db.span_suggestion(span, "try", - format!("std::mem::swap({}, {})", lhs, rhs)); + db.span_suggestion_with_applicability( + span, + "try", + format!("std::mem::swap({}, {})", + lhs, + rhs), + Applicability::Unspecified, + ); db.note("or maybe you should use `std::mem::replace`?"); } }); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 84726e5ded3..cdd0260b4fe 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -7,6 +7,7 @@ use std::borrow::Cow; use crate::syntax::ast; use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use crate::utils::{opt_def_id, sugg}; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. @@ -245,7 +246,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) }; - db.span_suggestion(e.span, "try", sugg.to_string()); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => { @@ -255,7 +261,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, "transmute from an integer to a pointer", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + db.span_suggestion_with_applicability( + e.span, + "try", + arg.as_ty(&to_ty.to_string()).to_string(), + Applicability::Unspecified, + ); }, ) }, @@ -312,7 +323,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) }; - db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg::make_unop(deref, arg).to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(ast::IntTy::I32), &ty::Char) | @@ -328,10 +344,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion( + db.span_suggestion_with_applicability( e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string()), + Applicability::Unspecified, ); }, ), @@ -353,7 +370,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), |db| { - db.span_suggestion( + db.span_suggestion_with_applicability( e.span, "consider using", format!( @@ -361,6 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { postfix, snippet(cx, args[0].span, ".."), ), + Applicability::Unspecified, ); } ) @@ -380,7 +398,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { sugg_paren.addr_deref() }; - db.span_suggestion(e.span, "try", sugg.to_string()); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ) } @@ -394,7 +417,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { "transmute from a pointer to a pointer", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); - db.span_suggestion(e.span, "try", sugg.to_string()); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => { @@ -406,10 +434,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); let zero = sugg::Sugg::NonParen(Cow::from("0")); - db.span_suggestion( + db.span_suggestion_with_applicability( e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(), + Applicability::Unspecified, ); }, ) @@ -432,10 +461,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion( + db.span_suggestion_with_applicability( e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string()), + Applicability::Unspecified, ); }, ) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c113dd7e5a3..856fa80569f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -575,7 +575,7 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( sugg: String, ) { span_lint_and_then(cx, lint, sp, msg, |db| { - db.span_suggestion(sp, help, sugg); + db.span_suggestion_with_applicability(sp, help, sugg, Applicability::Unspecified); }); } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index f849cef093a..f7d8c1fc151 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -15,6 +15,7 @@ use crate::syntax::util::parser::AssocOp; use crate::syntax::ast; use crate::utils::{higher, snippet, snippet_opt}; use crate::syntax_pos::{BytePos, Pos}; +use crate::rustc_errors::Applicability; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -496,7 +497,12 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error if let Some(indent) = indentation(cx, item) { let span = item.with_hi(item.lo()); - self.span_suggestion(span, msg, format!("{}\n{}", attr, indent)); + self.span_suggestion_with_applicability( + span, + msg, + format!("{}\n{}", attr, indent), + Applicability::Unspecified, + ); } } @@ -517,7 +523,12 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error }) .collect::(); - self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent)); + self.span_suggestion_with_applicability( + span, + msg, + format!("{}\n{}", new_item, indent), + Applicability::Unspecified, + ); } } @@ -534,6 +545,11 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error } } - self.span_suggestion(remove_span, msg, String::new()); + self.span_suggestion_with_applicability( + remove_span, + msg, + String::new(), + Applicability::Unspecified, + ); } } -- cgit 1.4.1-3-g733a5 From d4c994e670dbf97b2f0858f54c5a75d64863f866 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sat, 15 Sep 2018 19:28:51 +0300 Subject: Supplement DiagnosticBuilderExt with Applicability --- clippy_lints/src/inline_fn_without_body.rs | 3 ++- clippy_lints/src/new_without_default.rs | 10 +++++++++- clippy_lints/src/utils/sugg.rs | 18 +++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 29492cf8c43..cedcdec1062 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -6,6 +6,7 @@ use crate::rustc::hir::*; use crate::syntax::ast::{Attribute, Name}; use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for `#[inline]` on trait methods without bodies /// @@ -56,7 +57,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) { attr.span, &format!("use of `#[inline]` on trait method `{}` which has no body", name), |db| { - db.suggest_remove_item(cx, attr.span, "remove"); + db.suggest_remove_item(cx, attr.span, "remove", Applicability::Unspecified); }, ); } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 131f73b7c61..0163849dd22 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -8,6 +8,7 @@ use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; use crate::utils::sugg::DiagnosticBuilderExt; +use crate::rustc_errors::Applicability; /// **What it does:** Checks for types with a `fn new() -> Self` method and no /// implementation of @@ -129,7 +130,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { impl_item.span, &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + db.suggest_item_with_attr( + cx, + sp, + "try this", + "#[derive(Default)]", + Applicability::Unspecified, + ); }); } else { span_lint_and_then( @@ -143,6 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { item.span, "try this", &create_new_without_default_suggest_msg(self_ty), + Applicability::Unspecified, ); }, ); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index f7d8c1fc151..0cdfd623f45 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -462,7 +462,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { /// ```rust,ignore /// db.suggest_item_with_attr(cx, item, "#[derive(Default)]"); /// ``` - fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D); + fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability); /// Suggest to add an item before another. /// @@ -476,7 +476,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { /// bar(); /// }"); /// ``` - fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str); + fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability); /// Suggest to completely remove an item. /// @@ -489,11 +489,11 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { /// ```rust,ignore /// db.suggest_remove_item(cx, item, "remove this") /// ``` - fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str); + fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability); } impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { - fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D) { + fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability) { if let Some(indent) = indentation(cx, item) { let span = item.with_hi(item.lo()); @@ -501,12 +501,12 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error span, msg, format!("{}\n{}", attr, indent), - Applicability::Unspecified, + applicability, ); } } - fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) { + fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability) { if let Some(indent) = indentation(cx, item) { let span = item.with_hi(item.lo()); @@ -527,12 +527,12 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error span, msg, format!("{}\n{}", new_item, indent), - Applicability::Unspecified, + applicability, ); } } - fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) { + fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) { let mut remove_span = item; let hi = cx.sess().source_map().next_point(remove_span).hi(); let fmpos = cx.sess().source_map().lookup_byte_offset(hi); @@ -549,7 +549,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error remove_span, msg, String::new(), - Applicability::Unspecified, + applicability, ); } } -- cgit 1.4.1-3-g733a5 From 3e853a632e7f7b14feda78a076058d2058cfdbb5 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sat, 15 Sep 2018 19:32:35 +0300 Subject: Add forgotten function: span_suggestion*s* to the previous refactoting --- clippy_lints/src/booleans.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 85f6eeb19ef..c00256842b6 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -418,7 +418,12 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", - |db| { db.span_suggestions(e.span, "try", suggestions); }, + |db| { db.span_suggestions_with_applicability( + e.span, + "try", + suggestions, + Applicability::Unspecified, + ); }, ); }; if improvements.is_empty() { -- cgit 1.4.1-3-g733a5 From 2781cac8397b5d814e9d2b703863c32d66ba31c3 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sun, 16 Sep 2018 22:01:26 +0300 Subject: Apply subset of "cargo fmt". --- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/attrs.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 5cf714bed86..89541dd7e33 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -93,11 +93,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { Applicability::Unspecified, ); db.span_suggestion_with_applicability( - expr.span, - "or", + expr.span, + "or", long, Applicability::Unspecified, - ); + ); } }, ); diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 197aa88cbbe..b04eaeaebc3 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -209,7 +209,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { "if you just forgot a `!`, use", sugg, Applicability::Unspecified, - ); + ); }, ); } -- cgit 1.4.1-3-g733a5 From 3eccccb367de1bc68835465cf3a38bc1a0311df9 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 18 Sep 2018 18:07:54 +0300 Subject: Fix indents --- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 6 ++-- clippy_lints/src/collapsible_if.rs | 17 +++++----- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/entry.rs | 20 ++++++------ clippy_lints/src/eq_op.rs | 33 ++++++++++---------- clippy_lints/src/eta_reduction.rs | 10 +++--- clippy_lints/src/format.rs | 20 ++++++------ clippy_lints/src/identity_conversion.rs | 30 +++++++++--------- clippy_lints/src/int_plus_one.rs | 10 +++--- clippy_lints/src/let_if_seq.rs | 10 +++--- clippy_lints/src/map_unit_fn.rs | 20 ++++++------ clippy_lints/src/matches.rs | 10 +++--- clippy_lints/src/methods.rs | 32 +++++++++---------- clippy_lints/src/misc.rs | 45 +++++++++++++++------------ clippy_lints/src/misc_early.rs | 10 +++--- clippy_lints/src/needless_borrow.rs | 20 ++++++------ clippy_lints/src/needless_borrowed_ref.rs | 10 +++--- clippy_lints/src/needless_pass_by_value.rs | 20 ++++++------ clippy_lints/src/new_without_default.rs | 12 +++---- clippy_lints/src/ptr.rs | 20 ++++++------ clippy_lints/src/ranges.rs | 33 +++++++++++--------- clippy_lints/src/returns.rs | 10 +++--- clippy_lints/src/swap.rs | 26 +++++++++------- clippy_lints/src/transmute.rs | 50 +++++++++++++++--------------- clippy_lints/src/utils/sugg.rs | 10 +++--- 26 files changed, 253 insertions(+), 235 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 52c6d4c71dc..d33bf670f6f 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), Applicability::Unspecified, - ); + ); }); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index c00256842b6..604e27f56ee 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -418,12 +418,14 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", - |db| { db.span_suggestions_with_applicability( + |db| { + db.span_suggestions_with_applicability( e.span, "try", suggestions, Applicability::Unspecified, - ); }, + ); + }, ); }; if improvements.is_empty() { diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index c139b0f0c1f..dcc0f65e3fc 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -134,13 +134,16 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { let lhs = Sugg::ast(cx, check, ".."); let rhs = Sugg::ast(cx, check_inner, ".."); - db.span_suggestion_with_applicability(expr.span, - "try", - format!("if {} {}", - lhs.and(&rhs), - snippet_block(cx, content.span, "..")), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + expr.span, + "try", + format!( + "if {} {}", + lhs.and(&rhs), + snippet_block(cx, content.span, ".."), + ), + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 92c609d9858..4edc84c9d09 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -66,7 +66,7 @@ impl StaticConst { "consider removing `'static`", sugg, Applicability::Unspecified, - ); + ); }, ); } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index be9af18c911..71203a247bf 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -141,11 +141,11 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, params[2].span, "..")); db.span_suggestion_with_applicability( - self.span, - "consider using", - help, - Applicability::Unspecified, - ); + self.span, + "consider using", + help, + Applicability::Unspecified, + ); } else { let help = format!("{}.entry({})", @@ -153,11 +153,11 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, params[1].span, "..")); db.span_suggestion_with_applicability( - self.span, - "consider using", - help, - Applicability::Unspecified, - ); + self.span, + "consider using", + help, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 2ad04cd6fbe..f71472653bf 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -115,11 +115,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion_with_applicability( - left.span, - "use the left value directly", - lsnip, - Applicability::Unspecified, - ); + left.span, + "use the left value directly", + lsnip, + Applicability::Unspecified, + ); }) } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { span_lint_and_then( @@ -133,7 +133,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { right.span, "use the right value directly", rsnip, - Applicability::Unspecified,); + Applicability::Unspecified, + ); }, ) } @@ -146,11 +147,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion_with_applicability( - left.span, - "use the left value directly", - lsnip, - Applicability::Unspecified, - ); + left.span, + "use the left value directly", + lsnip, + Applicability::Unspecified, + ); }) } }, @@ -162,11 +163,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); db.span_suggestion_with_applicability( - right.span, - "use the right value directly", - rsnip, - Applicability::Unspecified, - ); + right.span, + "use the right value directly", + rsnip, + Applicability::Unspecified, + ); }) } }, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index b40ff8b51cd..f18358121d6 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -98,11 +98,11 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { if let Some(snippet) = snippet_opt(cx, caller.span) { db.span_suggestion_with_applicability( - expr.span, - "remove closure as shown", - snippet, - Applicability::Unspecified, - ); + expr.span, + "remove closure as shown", + snippet, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 868b7c19cef..29dca4556a5 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -62,11 +62,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let sugg = format!("{}.to_string()", snippet(cx, format_arg, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { db.span_suggestion_with_applicability( - expr.span, - "consider using .to_string()", - sugg, - Applicability::Unspecified, - ); + expr.span, + "consider using .to_string()", + sugg, + Applicability::Unspecified, + ); }); } } @@ -77,11 +77,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { db.span_suggestion_with_applicability( - span, - "consider using .to_string()", - sugg, - Applicability::Unspecified, - ); + span, + "consider using .to_string()", + sugg, + Applicability::Unspecified, + ); }); } }, diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 2a764ad73d4..411d7511d88 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -65,11 +65,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg = snippet(cx, args[0].span, "").into_owned(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { db.span_suggestion_with_applicability( - e.span, - "consider removing `.into()`", - sugg, - Applicability::Unspecified, - ); + e.span, + "consider removing `.into()`", + sugg, + Applicability::Unspecified, + ); }); } } @@ -80,11 +80,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg = snippet(cx, args[0].span, "").into_owned(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { db.span_suggestion_with_applicability( - e.span, - "consider removing `.into_iter()`", - sugg, - Applicability::Unspecified, - ); + e.span, + "consider removing `.into_iter()`", + sugg, + Applicability::Unspecified, + ); }); } } @@ -100,11 +100,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { db.span_suggestion_with_applicability( - e.span, - &sugg_msg, - sugg, - Applicability::Unspecified, - ); + e.span, + &sugg_msg, + sugg, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 4608ca696e1..14566c4f02d 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -154,11 +154,11 @@ impl IntPlusOne { fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { db.span_suggestion_with_applicability( - block.span, - "change `>= y + 1` to `> y` as shown", - recommendation, - Applicability::Unspecified, - ); + block.span, + "change `>= y + 1` to `> y` as shown", + recommendation, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 4947715e293..bdeaeda7bc5 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -122,11 +122,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { "`if _ { .. } else { .. }` is an expression", |db| { db.span_suggestion_with_applicability( - span, - "it is more idiomatic to write", - sug, - Applicability::Unspecified, - ); + span, + "it is more idiomatic to write", + sug, + Applicability::Unspecified, + ); if !mutability.is_empty() { db.note("you might not need `mut` at all"); } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 5f592a722d1..f4d48e3ad9a 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -229,20 +229,22 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr snippet(cx, var_arg.span, "_"), snippet(cx, reduced_expr_span, "_")); db.span_suggestion_with_applicability( - stmt.span, - "try this", - suggestion, - Applicability::Unspecified, - ); + stmt.span, + "try this", + suggestion, + Applicability::Unspecified, + ); } else { let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", variant, snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_")); - db.span_suggestion_with_applicability(stmt.span, - "try this", - suggestion, - Applicability::Unspecified); + db.span_suggestion_with_applicability( + stmt.span, + "try this", + suggestion, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 7cc70cb0834..d8e11d68479 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -341,11 +341,11 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex if let Some(sugg) = sugg { db.span_suggestion_with_applicability( - expr.span, - "consider using an if/else expression", - sugg, - Applicability::Unspecified, - ); + expr.span, + "consider using an if/else expression", + sugg, + Applicability::Unspecified, + ); } } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index f61995cf265..5f8dc63ea57 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1129,17 +1129,17 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp let derefs: String = iter::repeat('*').take(n).collect(); let explicit = format!("{}{}::clone({})", refs, ty, snip); db.span_suggestion_with_applicability( - expr.span, - "try dereferencing it", - format!("{}({}{}).clone()", refs, derefs, snip.deref()), - Applicability::Unspecified, - ); + expr.span, + "try dereferencing it", + format!("{}({}{}).clone()", refs, derefs, snip.deref()), + Applicability::Unspecified, + ); db.span_suggestion_with_applicability( - expr.span, - "or try being explicit about what type to clone", - explicit, - Applicability::Unspecified, - ); + expr.span, + "or try being explicit about what type to clone", + explicit, + Applicability::Unspecified, + ); }, ); return; // don't report clone_on_copy @@ -1185,7 +1185,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp text, snip, Applicability::Unspecified, - ); + ); } }); } @@ -1656,11 +1656,11 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { db.span_suggestion_with_applicability( - expr.span, - "try using and_then instead", - hint, - Applicability::Unspecified, - ); + expr.span, + "try using and_then instead", + hint, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index ac4e93f633a..0f0c86bfeb2 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -295,14 +295,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { - db.span_suggestion_with_applicability(s.span, - "try", - format!("let {name}{tyopt} = {initref};", - name=snippet(cx, i.span, "_"), - tyopt=tyopt, - initref=initref), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + s.span, + "try", + format!( + "let {name}{tyopt} = {initref};", + name=snippet(cx, i.span, "_"), + tyopt=tyopt, + initref=initref, + ), + Applicability::Unspecified, + ); } ); } @@ -321,13 +324,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; db.span_suggestion_with_applicability( - s.span, - "replace it with", - format!("if {} {{ {}; }}", - sugg, - &snippet(cx, b.span, "..")), - Applicability::Unspecified, - ); + s.span, + "replace it with", + format!( + "if {} {{ {}; }}", + sugg, + &snippet(cx, b.span, ".."), + ), + Applicability::Unspecified, + ); }); } }; @@ -545,11 +550,11 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } } db.span_suggestion_with_applicability( - expr.span, - "try", - snip.to_string(), - Applicability::Unspecified, - ); + expr.span, + "try", + snip.to_string(), + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index c66fb5d6e47..07c363d6f24 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -309,11 +309,11 @@ impl EarlyLintPass for MiscEarly { |db| if decl.inputs.is_empty() { let hint = snippet(cx, block.span, "..").into_owned(); db.span_suggestion_with_applicability( - expr.span, - "Try doing something like: ", - hint, - Applicability::Unspecified, - ); + expr.span, + "Try doing something like: ", + hint, + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 11e1a99fd7f..1e0db1a0f9a 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -77,11 +77,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { |db| { if let Some(snippet) = snippet_opt(cx, inner.span) { db.span_suggestion_with_applicability( - e.span, - "change this to", - snippet, - Applicability::Unspecified, - ); + e.span, + "change this to", + snippet, + Applicability::Unspecified, + ); } }, ); @@ -110,11 +110,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { |db| { if let Some(snippet) = snippet_opt(cx, name.span) { db.span_suggestion_with_applicability( - pat.span, - "change this to", - snippet, - Applicability::Unspecified, - ); + pat.span, + "change this to", + snippet, + Applicability::Unspecified, + ); } } ) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 08ce0de21c6..fd275752506 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -79,11 +79,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { |db| { let hint = snippet(cx, spanned_name.span, "..").into_owned(); db.span_suggestion_with_applicability( - pat.span, - "try removing the `&ref` part and just keep", - hint, - Applicability::Unspecified, - ); + pat.span, + "try removing the `&ref` part and just keep", + hint, + Applicability::Unspecified, + ); }); } } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index aa644e4c339..980e2c28a34 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -229,11 +229,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { then { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); db.span_suggestion_with_applicability( - input.span, - "consider changing the type to", - slice_ty, - Applicability::Unspecified, - ); + input.span, + "consider changing the type to", + slice_ty, + Applicability::Unspecified, + ); for (span, suggestion) in clone_spans { db.span_suggestion_with_applicability( @@ -258,11 +258,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { db.span_suggestion_with_applicability( - input.span, - "consider changing the type to", - "&str".to_string(), - Applicability::Unspecified, - ); + input.span, + "consider changing the type to", + "&str".to_string(), + Applicability::Unspecified, + ); for (span, suggestion) in clone_spans { db.span_suggestion_with_applicability( diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 0163849dd22..bf5fbb8a7f5 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -131,12 +131,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), |db| { db.suggest_item_with_attr( - cx, - sp, - "try this", - "#[derive(Default)]", - Applicability::Unspecified, - ); + cx, + sp, + "try this", + "#[derive(Default)]", + Applicability::Unspecified, + ); }); } else { span_lint_and_then( diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f8d872cb4e6..86cb89f2de1 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -212,11 +212,11 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: "writing `&String` instead of `&str` involves a new object where a slice will do.", |db| { db.span_suggestion_with_applicability( - arg.span, - "change this to", - "&str".into(), - Applicability::Unspecified, - ); + arg.span, + "change this to", + "&str".into(), + Applicability::Unspecified, + ); for (clonespan, suggestion) in spans { db.span_suggestion_short_with_applicability( clonespan, @@ -253,11 +253,11 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: "using a reference to `Cow` is not recommended.", |db| { db.span_suggestion_with_applicability( - arg.span, - "change this to", - "&".to_owned() + &r, - Applicability::Unspecified, - ); + arg.span, + "change this to", + "&".to_owned() + &r, + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 8ca0750684e..71b68d97e40 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -151,17 +151,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let end = Sugg::hir(cx, y, "y"); if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { - db.span_suggestion_with_applicability(expr.span, - "use", - format!("({}..={})", start, end), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + expr.span, + "use", + format!("({}..={})", start, end), + Applicability::Unspecified, + ); } else { - db.span_suggestion_with_applicability(expr.span, - "use", - format!("{}..={}", start, end), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + expr.span, + "use", + format!("{}..={}", start, end), + Applicability::Unspecified, + ); } } }, @@ -182,11 +184,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); - db.span_suggestion_with_applicability(expr.span, - "use", - format!("{}..{}", start, end), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + expr.span, + "use", + format!("{}..{}", start, end), + Applicability::Unspecified, + ); }, ); } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 34b7614e439..f90d8659dbe 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -110,11 +110,11 @@ impl ReturnPass { span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { db.span_suggestion_with_applicability( - ret_span, - "remove `return` as shown", - snippet, - Applicability::Unspecified, - ); + ret_span, + "remove `return` as shown", + snippet, + Applicability::Unspecified, + ); } }); } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 8859d545194..5ca78957f08 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -138,11 +138,11 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { |db| { if !sugg.is_empty() { db.span_suggestion_with_applicability( - span, - "try", - sugg, - Applicability::Unspecified, - ); + span, + "try", + sugg, + Applicability::Unspecified, + ); if replace { db.note("or maybe you should use `std::mem::replace`?"); @@ -187,13 +187,15 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { |db| { if !what.is_empty() { db.span_suggestion_with_applicability( - span, - "try", - format!("std::mem::swap({}, {})", - lhs, - rhs), - Applicability::Unspecified, - ); + span, + "try", + format!( + "std::mem::swap({}, {})", + lhs, + rhs, + ), + Applicability::Unspecified, + ); db.note("or maybe you should use `std::mem::replace`?"); } }); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index cdd0260b4fe..69422056df5 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -247,11 +247,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }; db.span_suggestion_with_applicability( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => { @@ -262,11 +262,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { "transmute from an integer to a pointer", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { db.span_suggestion_with_applicability( - e.span, - "try", - arg.as_ty(&to_ty.to_string()).to_string(), - Applicability::Unspecified, - ); + e.span, + "try", + arg.as_ty(&to_ty.to_string()).to_string(), + Applicability::Unspecified, + ); }, ) }, @@ -324,11 +324,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }; db.span_suggestion_with_applicability( - e.span, - "try", - sugg::make_unop(deref, arg).to_string(), - Applicability::Unspecified, - ); + e.span, + "try", + sugg::make_unop(deref, arg).to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(ast::IntTy::I32), &ty::Char) | @@ -399,11 +399,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { sugg_paren.addr_deref() }; db.span_suggestion_with_applicability( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ) } @@ -418,11 +418,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); db.span_suggestion_with_applicability( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); }, ), (&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => { diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 0cdfd623f45..076907e4945 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -546,10 +546,10 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error } self.span_suggestion_with_applicability( - remove_span, - msg, - String::new(), - applicability, - ); + remove_span, + msg, + String::new(), + applicability, + ); } } -- cgit 1.4.1-3-g733a5 From 58729346bed9f7c15c461665202fab5b7ec628c8 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 18 Sep 2018 20:01:17 +0300 Subject: Fill in Applicability from review comments by @flip1995 --- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 4 ++++ clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/entry.rs | 4 ++-- clippy_lints/src/eq_op.rs | 8 ++++---- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/format.rs | 4 ++-- clippy_lints/src/identity_conversion.rs | 6 +++--- clippy_lints/src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/methods.rs | 6 +++--- clippy_lints/src/misc.rs | 8 ++++---- clippy_lints/src/misc_early.rs | 6 +++--- clippy_lints/src/needless_borrow.rs | 4 ++-- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/new_without_default.rs | 4 ++-- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 6 +++--- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/swap.rs | 2 +- 29 files changed, 52 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 89541dd7e33..a05a4d55010 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -90,13 +90,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { long ), format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::Unspecified, + Applicability::MachineApplicable, ); db.span_suggestion_with_applicability( expr.span, "or", long, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } }, @@ -183,7 +183,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { expr.span, "replace it with", format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } }, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index b04eaeaebc3..e192c3f2093 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { line_span, "if you just forgot a `!`, use", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, ); }, ); diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index d33bf670f6f..7151e8db9aa 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -143,7 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }); } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 604e27f56ee..1201b4a0c64 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -395,6 +395,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "it would look like the following", suggest(self.cx, suggestion, &h2q.terminals).0, + // nonminimal_bool can produce minimal but + // not human readable expressions (#3141) Applicability::Unspecified, ); }, @@ -423,6 +425,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "try", suggestions, + // nonminimal_bool can produce minimal but + // not human readable expressions (#3141) Applicability::Unspecified, ); }, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index dcc0f65e3fc..b0fb058116f 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -142,7 +142,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & lhs.and(&rhs), snippet_block(cx, content.span, ".."), ), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 4edc84c9d09..bb9829ad3c9 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -65,7 +65,7 @@ impl StaticConst { ty.span, "consider removing `'static`", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, //snippet ); }, ); diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 71203a247bf..965d425b43d 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { self.span, "consider using", help, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } else { @@ -156,7 +156,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { self.span, "consider using", help, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } }); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index f71472653bf..7b9f2568da9 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { left.span, "use the left value directly", lsnip, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }) } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { @@ -133,7 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { right.span, "use the right value directly", rsnip, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }, ) @@ -150,7 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { left.span, "use the left value directly", lsnip, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }) } @@ -166,7 +166,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { right.span, "use the right value directly", rsnip, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }) } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index f18358121d6..556f76af3a7 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -101,7 +101,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { expr.span, "remove closure as shown", snippet, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } }); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 29dca4556a5..2eb95ebffbf 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "consider using .to_string()", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, ); }); } @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span, "consider using .to_string()", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 411d7511d88..5b1bd0ada7b 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { e.span, "consider removing `.into()`", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { e.span, "consider removing `.into_iter()`", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } @@ -103,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { e.span, &sugg_msg, sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 64d088d2a99..c9fbf1b0775 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }, ); diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index cedcdec1062..881bebc2f60 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -57,7 +57,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) { attr.span, &format!("use of `#[inline]` on trait method `{}` which has no body", name), |db| { - db.suggest_remove_item(cx, attr.span, "remove", Applicability::Unspecified); + db.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable); }, ); } diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 14566c4f02d..69a19e2fb01 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -157,7 +157,7 @@ impl IntPlusOne { block.span, "change `>= y + 1` to `> y` as shown", recommendation, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 8ff53e15c31..c346585250a 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { "consider boxing the large fields to reduce the total size of the \ enum", format!("Box<{}>", snip), - Applicability::Unspecified, + Applicability::MachineApplicable, ); return; } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index bdeaeda7bc5..ede55ce3721 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { span, "it is more idiomatic to write", sug, - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); if !mutability.is_empty() { db.note("you might not need `mut` at all"); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 70608b9895f..2c05d9a198f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1206,7 +1206,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx dots = dots, start = start_snippet ), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }, ); diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index f4d48e3ad9a..40b81e6fdb8 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -232,7 +232,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr stmt.span, "try this", suggestion, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } else { let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index d8e11d68479..4c99aeae199 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -344,7 +344,7 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex expr.span, "consider using an if/else expression", sugg, - Applicability::Unspecified, + Applicability::MaybeIncorrect, // not sure ); } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 5f8dc63ea57..03e3d2628e8 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1132,13 +1132,13 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp expr.span, "try dereferencing it", format!("{}({}{}).clone()", refs, derefs, snip.deref()), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); db.span_suggestion_with_applicability( expr.span, "or try being explicit about what type to clone", explicit, - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }, ); @@ -1659,7 +1659,7 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, expr.span, "try using and_then instead", hint, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 0f0c86bfeb2..0fa05de2841 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -304,7 +304,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { tyopt=tyopt, initref=initref, ), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } ); @@ -331,7 +331,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { sugg, &snippet(cx, b.span, ".."), ), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } @@ -381,7 +381,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "consider comparing them within some error", format!("({}).abs() < error", lhs - rhs), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available."); }); @@ -553,7 +553,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { expr.span, "try", snip.to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }, ); diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 07c363d6f24..d3e1ca93784 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -312,7 +312,7 @@ impl EarlyLintPass for MiscEarly { expr.span, "Try doing something like: ", hint, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }, ); @@ -402,13 +402,13 @@ impl MiscEarly { lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion", src.trim_left_matches(|c| c == '_' || c == '0').to_string(), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); db.span_suggestion_with_applicability( lit.span, "if you mean to use an octal constant, use `0o`", format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }); } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 1e0db1a0f9a..8a676be99ea 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { e.span, "change this to", snippet, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } }, @@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { pat.span, "change this to", snippet, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index fd275752506..057a097f4b7 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { pat.span, "try removing the `&ref` part and just keep", hint, - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }); } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index bf5fbb8a7f5..e0b54620faf 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { sp, "try this", "#[derive(Default)]", - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }); } else { @@ -150,7 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { item.span, "try this", &create_new_without_default_suggest_msg(self_ty), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); }, ); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index f4920e52a71..ced0fe3ef50 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -75,7 +75,7 @@ impl QuestionMarkPass { expr.span, "replace_it_with", format!("{}?;", receiver_str), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } ) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 71b68d97e40..c60ed3842d4 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -155,14 +155,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "use", format!("({}..={})", start, end), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); } else { db.span_suggestion_with_applicability( expr.span, "use", format!("{}..={}", start, end), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); } } @@ -188,7 +188,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, "use", format!("{}..{}", start, end), - Applicability::Unspecified, + Applicability::MachineApplicable, // snippet ); }, ); diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index f90d8659dbe..9ab6b50ada6 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -113,7 +113,7 @@ impl ReturnPass { ret_span, "remove `return` as shown", snippet, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } }); diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 5ca78957f08..5de2f0e54a9 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -194,7 +194,7 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { lhs, rhs, ), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); db.note("or maybe you should use `std::mem::replace`?"); } -- cgit 1.4.1-3-g733a5 From 52fb7d461ea231310de16e721e3b850747f5cf41 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 18 Sep 2018 22:43:52 +0300 Subject: Applicability adjustment per additional comments --- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/matches.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index c346585250a..8ff53e15c31 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { "consider boxing the large fields to reduce the total size of the \ enum", format!("Box<{}>", snip), - Applicability::MachineApplicable, + Applicability::Unspecified, ); return; } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index ede55ce3721..53d13407be3 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { span, "it is more idiomatic to write", sug, - Applicability::MaybeIncorrect, + Applicability::HasPlaceholders, ); if !mutability.is_empty() { db.note("you might not need `mut` at all"); diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 4c99aeae199..c1a65e756a9 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -344,7 +344,7 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex expr.span, "consider using an if/else expression", sugg, - Applicability::MaybeIncorrect, // not sure + Applicability::HasPlaceholders, ); } } -- cgit 1.4.1-3-g733a5 From 987b34d09018e8f7c1b880bcb26e8483e6843869 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 20 Sep 2018 14:38:13 +0200 Subject: Another Applicability adjustment --- clippy_lints/src/large_enum_variant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 8ff53e15c31..e8982d92b56 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { "consider boxing the large fields to reduce the total size of the \ enum", format!("Box<{}>", snip), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); return; } -- cgit 1.4.1-3-g733a5 From 867ac98d386fdf0d79173a60f7c11b29e0dbdb38 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 22 Sep 2018 17:20:34 +0200 Subject: Fix double_parens false positive Closes #3206 --- clippy_lints/src/double_parens.rs | 7 ++++++- tests/ui/double_parens.rs | 6 ++++++ tests/ui/double_parens.stderr | 8 +++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 702931c0532..3b2ef4e8bb2 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,7 +1,8 @@ use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::span_lint; +use crate::utils::{in_macro, span_lint}; + /// **What it does:** Checks for unnecessary double parentheses. /// @@ -33,6 +34,10 @@ impl LintPass for DoubleParens { impl EarlyLintPass for DoubleParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if in_macro(expr.span) { + return; + } + match expr.node { ExprKind::Paren(ref in_paren) => match in_paren.node { ExprKind::Paren(_) | ExprKind::Tup(_) => { diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index 8d81ee16fe9..c217972fa6a 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -48,4 +48,10 @@ fn method_unit_ok(x: DummyStruct) { x.dummy_method(()); } +// Issue #3206 +fn inside_macro() { + assert_eq!((1, 2), (1, 2), "Error"); + assert_eq!(((1, 2)), (1, 2), "Error"); +} + fn main() {} diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index a6a29eeb063..3e38db730e0 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -30,5 +30,11 @@ error: Consider removing unnecessary double parentheses 32 | (()) | ^^^^ -error: aborting due to 5 previous errors +error: Consider removing unnecessary double parentheses + --> $DIR/double_parens.rs:54:16 + | +54 | assert_eq!(((1, 2)), (1, 2), "Error"); + | ^^^^^^^^ + +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 8e9f1a9d683a45a26ab6f4eeab2dfdec608ccef7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 22 Sep 2018 14:35:11 -0700 Subject: Mention `rustup self update` (fixes #3211) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3d994b4ef85..93e78b88484 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ rustup component add clippy-preview Now you can run Clippy by invoking `cargo clippy`. +If it says that it can't find the `clippy` subcommand, please run `rustup self update` + ### Running Clippy from the command line without installing it To have cargo compile your crate with Clippy without Clippy installation -- cgit 1.4.1-3-g733a5 From f2ecee36383736daa7ccf1152d0305fdd8af7661 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 23 Sep 2018 14:44:06 +0200 Subject: clippy_dev: port to edition 2018 --- clippy_dev/Cargo.toml | 3 +++ clippy_dev/src/lib.rs | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 503dd53aa20..519f78999b9 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -1,7 +1,10 @@ +cargo-features = ["edition"] + [package] name = "clippy_dev" version = "0.0.1" authors = ["Philipp Hansch "] +edition = "2018" [dependencies] clap = "~2.32" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index f10ad81d130..e5ce8580fa1 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,12 +1,9 @@ #![feature(tool_lints)] #![allow(clippy::default_hash_types)] -extern crate regex; -#[macro_use] -extern crate lazy_static; -extern crate itertools; -use regex::Regex; use itertools::Itertools; +use lazy_static::lazy_static; +use regex::Regex; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; -- cgit 1.4.1-3-g733a5 From de8d233b060f60a37b7fae82a36f7226892ac4e7 Mon Sep 17 00:00:00 2001 From: ms2300 Date: Wed, 12 Sep 2018 18:14:48 -0600 Subject: #3006 : Fixing for .get().unwrap().foo() --- clippy_lints/src/methods.rs | 2 +- tests/ui/get_unwrap.rs | 5 +++++ tests/ui/get_unwrap.stderr | 34 +++++++++++++++++++++++----------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 03e3d2628e8..32e6a83e535 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1431,7 +1431,7 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: ), "try this", format!( - "{}{}[{}]", + "({}{}[{}])", borrow_str, snippet(cx, get_args[0].span, "_"), snippet(cx, get_args[1].span, "_") diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index a10d4d18262..141233e0d8a 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -43,4 +43,9 @@ fn main() { *some_btreemap.get_mut(&1).unwrap() = 'b'; *false_positive.get_mut(0).unwrap() = 1; } + + { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` + let _ = some_vec.get(0..1).unwrap().to_vec(); + let _ = some_vec.get_mut(0..1).unwrap().to_vec(); + } } diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 63f6603c821..6b9a360f332 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -2,7 +2,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:27:17 | 27 | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&boxed_slice[1])` | = note: `-D clippy::get-unwrap` implied by `-D warnings` @@ -10,55 +10,67 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:28:17 | 28 | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_slice[0])` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:29:17 | 29 | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vec[0])` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:30:17 | 30 | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vecdeque[0])` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:31:17 | 31 | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_hashmap[&1])` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:32:17 | 32 | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_btreemap[&1])` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:37:10 | 37 | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut boxed_slice[0])` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:38:10 | 38 | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_slice[0])` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:39:10 | 39 | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vec[0])` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:40:10 | 40 | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vecdeque[0])` -error: aborting due to 10 previous errors +error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:48:17 + | +48 | let _ = some_vec.get(0..1).unwrap().to_vec(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vec[0..1])` + +error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:49:17 + | +49 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vec[0..1])` + +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From 523ba2a009c4257119870aea2204ce00c0b677ac Mon Sep 17 00:00:00 2001 From: ms2300 Date: Thu, 13 Sep 2018 02:36:13 -0600 Subject: Full fix of get unwrap issue --- clippy_lints/src/methods.rs | 17 ++++++++++++++--- tests/ui/get_unwrap.stderr | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 32e6a83e535..6bf57383a7a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1404,22 +1404,33 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap, // because they do not implement `IndexMut` let expr_ty = cx.tables.expr_ty(&get_args[0]); + let get_args_str = if get_args.len() > 1 { + snippet(cx, get_args[1].span, "_") + } else { + return; // not linting on a .get().unwrap() chain or variant + }; + let needs_ref; let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { + needs_ref = get_args_str.parse::().is_ok(); "slice" } else if match_type(cx, expr_ty, &paths::VEC) { + needs_ref = get_args_str.parse::().is_ok(); "Vec" } else if match_type(cx, expr_ty, &paths::VEC_DEQUE) { + needs_ref = get_args_str.parse::().is_ok(); "VecDeque" } else if !is_mut && match_type(cx, expr_ty, &paths::HASHMAP) { + needs_ref = true; "HashMap" } else if !is_mut && match_type(cx, expr_ty, &paths::BTREEMAP) { + needs_ref = true; "BTreeMap" } else { return; // caller is not a type that we want to lint }; let mut_str = if is_mut { "_mut" } else { "" }; - let borrow_str = if is_mut { "&mut " } else { "&" }; + let borrow_str = if !needs_ref { "" } else if is_mut { "&mut " } else { "&" }; span_lint_and_sugg( cx, GET_UNWRAP, @@ -1431,10 +1442,10 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: ), "try this", format!( - "({}{}[{}])", + "{}{}[{}]", borrow_str, snippet(cx, get_args[0].span, "_"), - snippet(cx, get_args[1].span, "_") + get_args_str ), ); } diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 6b9a360f332..669903da190 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -2,7 +2,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:27:17 | 27 | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&boxed_slice[1])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D clippy::get-unwrap` implied by `-D warnings` @@ -10,67 +10,67 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:28:17 | 28 | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_slice[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:29:17 | 29 | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vec[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:30:17 | 30 | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vecdeque[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:31:17 | 31 | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_hashmap[&1])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:32:17 | 32 | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_btreemap[&1])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:37:10 | 37 | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut boxed_slice[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:38:10 | 38 | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_slice[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:39:10 | 39 | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vec[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:40:10 | 40 | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vecdeque[0])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:48:17 | 48 | let _ = some_vec.get(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&some_vec[0..1])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:49:17 | 49 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&mut some_vec[0..1])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From ab71f0866323bac7255da8687a2850e1daddf816 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 23 Sep 2018 15:25:10 +0200 Subject: Fix single_char_pattern crash (#3204) This commit fixes the crash by removing constant checking from the lint. Closes #3204. --- clippy_lints/src/methods.rs | 8 +++++--- tests/ui/single_char_pattern.rs | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 03e3d2628e8..54df9809a3e 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -16,7 +16,6 @@ use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, i span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; use crate::utils::paths; use crate::utils::sugg; -use crate::consts::{constant, Constant}; use crate::rustc_errors::Applicability; #[derive(Clone)] @@ -1914,8 +1913,11 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & /// lint for length-1 `str`s for methods in `PATTERN_METHODS` fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { - if let Some((Constant::Str(r), _)) = constant(cx, cx.tables, arg) { - if r.len() == 1 { + if_chain! { + if let hir::ExprKind::Lit(lit) = &arg.node; + if let ast::LitKind::Str(r, _) = lit.node; + if r.as_str().len() == 1; + then { let snip = snippet(cx, arg.span, ".."); let hint = format!("'{}'", &snip[1..snip.len() - 1]); span_lint_and_sugg( diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 147f974b999..c4e88e9ee2b 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -45,4 +45,8 @@ fn main() { x.replace(";", ",").split(","); // issue #2978 x.starts_with("\x03"); // issue #2996 + + // Issue #3204 + const S: &str = "#"; + x.find(S); } -- cgit 1.4.1-3-g733a5 From 14feb3670f4e1e5ff759253b9dc86cfbb29ff8a5 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 21 Sep 2018 00:26:38 -0700 Subject: Lint for chaining flatten after map This change adds a lint to check for instances of `map(..).flatten()` that can be trivially shortened to `flat_map(..)` Closes #3196 --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 1 + clippy_lints/src/methods.rs | 73 +++++++++++++++++++++++++++++++++++++-------- tests/ui/map_flatten.rs | 7 +++++ tests/ui/map_flatten.stderr | 10 +++++++ 6 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 tests/ui/map_flatten.rs create mode 100644 tests/ui/map_flatten.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a7b4c5921e8..2bc4a8a8f91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -736,6 +736,7 @@ All notable changes to this project will be documented in this file. [`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone [`map_entry`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_entry +[`map_flatten`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_flatten [`match_as_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_bool [`match_overlapping_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_overlapping_arm diff --git a/README.md b/README.md index f7babe36ad9..eb1de06cce0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 277 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 90094429a36..3e25c79a7fd 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -473,6 +473,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::EXPLICIT_ITER_LOOP, matches::SINGLE_MATCH_ELSE, methods::FILTER_MAP, + methods::MAP_FLATTEN, methods::OPTION_MAP_UNWRAP_OR, methods::OPTION_MAP_UNWRAP_OR_ELSE, methods::RESULT_MAP_UNWRAP_OR_ELSE, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 54df9809a3e..5a9818a6b63 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,22 +1,24 @@ -use matches::matches; use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, Lint, LintContext}; +use crate::rustc::hir::def::Def; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; +use crate::rustc::ty::{self, Ty}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast; +use crate::syntax::source_map::{BytePos, Span}; +use crate::utils::paths; +use crate::utils::sugg; +use crate::utils::{ + get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, + iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, + match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, span_lint, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, +}; use if_chain::if_chain; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::hir::def::Def; +use matches::matches; use std::borrow::Cow; use std::fmt; use std::iter; -use crate::syntax::ast; -use crate::syntax::source_map::{Span, BytePos}; -use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, - is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, - match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet, - span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; -use crate::utils::paths; -use crate::utils::sugg; -use crate::rustc_errors::Applicability; #[derive(Clone)] pub struct Pass; @@ -247,6 +249,24 @@ declare_clippy_lint! { "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" } +/// **What it does:** Checks for usage of `_.map(_).flatten(_)`, +/// +/// **Why is this bad?** Readability, this can be written more concisely as a +/// single method call. +/// +/// **Known problems:** +/// +/// **Example:** +/// ```rust +/// iter.map(|x| x.iter()).flatten() +/// ``` +declare_clippy_lint! { + pub MAP_FLATTEN, + pedantic, + "using combinations of `flatten` and `map` which can usually be written as a \ + single method call" +} + /// **What it does:** Checks for usage of `_.filter(_).map(_)`, /// `_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar. /// @@ -698,6 +718,7 @@ impl LintPass for Pass { TEMPORARY_CSTRING_AS_PTR, FILTER_NEXT, FILTER_MAP, + MAP_FLATTEN, ITER_NTH, ITER_SKIP_NEXT, GET_UNWRAP, @@ -744,6 +765,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { lint_filter_map_flat_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "flatten"]) { + lint_map_flatten(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { @@ -1577,6 +1600,30 @@ fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hi } } +/// lint use of `map().flatten()` for `Iterators` +fn lint_map_flatten<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.map().flatten()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `map(..).flatten()` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)`"; + let self_snippet = snippet(cx, map_args[0].span, ".."); + let func_snippet = snippet(cx, map_args[1].span, ".."); + let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); + span_lint_and_then(cx, MAP_FLATTEN, expr.span, msg, |db| { + db.span_suggestion_with_applicability( + expr.span, + "try using flat_map instead", + hint, + Applicability::MachineApplicable, + ); + }); + } +} + /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s fn lint_map_unwrap_or_else<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs new file mode 100644 index 00000000000..c5cf24d9bb0 --- /dev/null +++ b/tests/ui/map_flatten.rs @@ -0,0 +1,7 @@ +#![feature(tool_lints)] +#![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::missing_docs_in_private_items)] + +fn main() { + let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); +} diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr new file mode 100644 index 00000000000..d4ce44490d1 --- /dev/null +++ b/tests/ui/map_flatten.stderr @@ -0,0 +1,10 @@ +error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` + --> $DIR/map_flatten.rs:6:21 + | +6 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` + | + = note: `-D clippy::map-flatten` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 2b4d9d55b84aee46faf10ad99fc005a528f2fc77 Mon Sep 17 00:00:00 2001 From: Hanaasagi Date: Tue, 25 Sep 2018 22:40:17 +0900 Subject: fix invalid travis-yaml in README --- README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index eb1de06cce0..100d7649678 100644 --- a/README.md +++ b/README.md @@ -83,18 +83,20 @@ Be sure that Clippy was compiled with the same version of rustc that cargo invok You can add Clippy to Travis CI in the same way you use it locally: ```yml -- rust: stable -- rust: beta - before_script: - - rustup component add clippy-preview - script: - - cargo clippy -# if you want the build job to fail when encountering warnings, use - - cargo clippy -- -D warnings -# in order to also check tests and none-default crate features, use - - cargo clippy --all-targets --all-features -- -D warnings - - cargo test - # etc. +language: rust +rust: + - stable + - beta +before_script: + - rustup component add clippy-preview +script: + - cargo clippy + # if you want the build job to fail when encountering warnings, use + - cargo clippy -- -D warnings + # in order to also check tests and none-default crate features, use + - cargo clippy --all-targets --all-features -- -D warnings + - cargo test + # etc. ``` ## Configuration -- cgit 1.4.1-3-g733a5 From f5ffac4fce524229e567b9b9f38925a49f35cd29 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 26 Sep 2018 06:52:36 +0200 Subject: Implement unnecesary_filter_map lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/methods.rs | 166 +++++++++++++++++++++++++++++++++++++++++++- tests/ui/methods.rs | 14 ++++ tests/ui/methods.stderr | 32 ++++++++- 6 files changed, 214 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bc4a8a8f91..c9bea1e8ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -864,6 +864,7 @@ All notable changes to this project will be documented in this file. [`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast +[`unnecessary_filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation diff --git a/README.md b/README.md index 100d7649678..b8684b38631 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 279 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3e25c79a7fd..9af4850b15c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -614,6 +614,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::SINGLE_CHAR_PATTERN, methods::STRING_EXTEND_CHARS, methods::TEMPORARY_CSTRING_AS_PTR, + methods::UNNECESSARY_FILTER_MAP, methods::UNNECESSARY_FOLD, methods::USELESS_ASREF, methods::WRONG_SELF_CONVENTION, @@ -829,6 +830,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::CLONE_ON_COPY, methods::FILTER_NEXT, methods::SEARCH_IS_SOME, + methods::UNNECESSARY_FILTER_MAP, methods::USELESS_ASREF, misc::SHORT_CIRCUIT_STATEMENT, misc_early::REDUNDANT_CLOSURE_CALL, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 5a9818a6b63..a0c9e34b861 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,5 +1,6 @@ use crate::rustc::hir; use crate::rustc::hir::def::Def; +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; use crate::rustc::ty::{self, Ty}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -8,6 +9,7 @@ use crate::syntax::ast; use crate::syntax::source_map::{BytePos, Span}; use crate::utils::paths; use crate::utils::sugg; +use crate::utils::usage::mutated_variables; use crate::utils::{ get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, @@ -692,6 +694,27 @@ declare_clippy_lint! { "using `fold` when a more succinct alternative exists" } + +/// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`. +/// +/// **Why is this bad?** Complexity +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None }); +/// ``` +/// This could be written as: +/// ```rust +/// let _ = (0..3).filter(|&x| x > 2); +/// ``` +declare_clippy_lint! { + pub UNNECESSARY_FILTER_MAP, + complexity, + "using `filter_map` when a more succinct alternative exists" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( @@ -725,7 +748,8 @@ impl LintPass for Pass { STRING_EXTEND_CHARS, ITER_CLONED_COLLECT, USELESS_ASREF, - UNNECESSARY_FOLD + UNNECESSARY_FOLD, + UNNECESSARY_FILTER_MAP ) } } @@ -791,6 +815,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_asref(cx, expr, "as_mut", arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { lint_unnecessary_fold(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map"]) { + unnecessary_filter_map::lint(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); @@ -1398,6 +1424,144 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: }; } +mod unnecessary_filter_map { + use super::*; + + pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { + + if !match_trait_method(cx, expr, &paths::ITERATOR) { + return; + } + + if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].node { + + let body = cx.tcx.hir.body(body_id); + let arg_id = body.arguments[0].pat.id; + let mutates_arg = match mutated_variables(&body.value, cx) { + Some(used_mutably) => used_mutably.contains(&arg_id), + None => true, + }; + + let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value); + + let mut return_visitor = ReturnVisitor::new(&cx, arg_id); + return_visitor.visit_expr(&body.value); + found_mapping |= return_visitor.found_mapping; + found_filtering |= return_visitor.found_filtering; + + if !found_filtering { + span_lint( + cx, + UNNECESSARY_FILTER_MAP, + expr.span, + "this `.filter_map` can be written more simply using `.map`", + ); + return; + } + + if !found_mapping && !mutates_arg { + span_lint( + cx, + UNNECESSARY_FILTER_MAP, + expr.span, + "this `.filter_map` can be written more simply using `.filter`", + ); + return; + } + } + } + + // returns (found_mapping, found_filtering) + fn check_expression<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId, expr: &'tcx hir::Expr) -> (bool, bool) { + match &expr.node { + hir::ExprKind::Call(ref func, ref args) => { + if_chain! { + if let hir::ExprKind::Path(ref path) = func.node; + then { + if match_qpath(path, &paths::OPTION_SOME) { + if_chain! { + if let hir::ExprKind::Path(path) = &args[0].node; + if let Def::Local(ref local) = cx.tables.qpath_def(path, args[0].hir_id); + then { + if arg_id == *local { + return (false, false) + } + } + } + return (true, false); + } else { + // We don't know. It might do anything. + return (true, true); + } + } + } + (true, true) + }, + hir::ExprKind::Block(ref block, _) => { + if let Some(expr) = &block.expr { + check_expression(cx, arg_id, &expr) + } else { + (false, false) + } + }, + // There must be an else_arm or there will be a type error + hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => { + let if_check = check_expression(cx, arg_id, if_arm); + let else_check = check_expression(cx, arg_id, else_arm); + (if_check.0 | else_check.0, if_check.1 | else_check.1) + }, + hir::ExprKind::Match(_, ref arms, _) => { + let mut found_mapping = false; + let mut found_filtering = false; + for arm in arms { + let (m, f) = check_expression(cx, arg_id, &arm.body); + found_mapping |= m; + found_filtering |= f; + } + (found_mapping, found_filtering) + }, + hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), + _ => (true, true) + } + } + + struct ReturnVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + arg_id: ast::NodeId, + // Found a non-None return that isn't Some(input) + found_mapping: bool, + // Found a return that isn't Some + found_filtering: bool, + } + + impl<'a, 'tcx: 'a> ReturnVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId) -> ReturnVisitor<'a, 'tcx> { + ReturnVisitor { + cx, + arg_id, + found_mapping: false, + found_filtering: false, + } + } + } + + impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if let hir::ExprKind::Ret(Some(expr)) = &expr.node { + let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr); + self.found_mapping |= found_mapping; + self.found_filtering |= found_filtering; + } else { + walk_expr(self, expr); + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + } +} + fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 7faa45b987d..111c6ce5a8c 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -443,3 +443,17 @@ fn main() { let opt = Some(0); let _ = opt.unwrap(); } + +/// Checks implementation of `UNNECESSARY_FILTER_MAP` lint +fn unnecessary_filter_map() { + let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); + let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + let _ = (0..4).filter_map(|x| match x { + 0 | 1 => None, + _ => Some(x), + }); + + let _ = (0..4).filter_map(|x| Some(x + 1)); + + let _ = (0..4).filter_map(i32::checked_abs); +} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 3189f375647..b006813e26d 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -453,5 +453,35 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 56 previous errors +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/methods.rs:449:13 + | +449 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` + +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/methods.rs:450:13 + | +450 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/methods.rs:451:13 + | +451 | let _ = (0..4).filter_map(|x| match x { + | _____________^ +452 | | 0 | 1 => None, +453 | | _ => Some(x), +454 | | }); + | |______^ + +error: this `.filter_map` can be written more simply using `.map` + --> $DIR/methods.rs:456:13 + | +456 | let _ = (0..4).filter_map(|x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 60 previous errors -- cgit 1.4.1-3-g733a5 From 41d3df7321480eedfa254fa892715f199f09dbc9 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 26 Sep 2018 12:32:20 +0200 Subject: tests: dogfood: extend to run with --all-features and clippy::internal enabled. Run it on rustc_tools_util and clippy_dev as well. --- tests/dogfood.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index a586d89ca4f..2ff4274a1a9 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -4,14 +4,16 @@ fn dogfood() { return; } let root_dir = std::env::current_dir().unwrap(); - for d in &[".", "clippy_lints"] { + for d in &[".", "clippy_lints", "rustc_tools_util", "clippy_dev"] { std::env::set_current_dir(root_dir.join(d)).unwrap(); let output = std::process::Command::new("cargo") .arg("run") .arg("--bin") .arg("cargo-clippy") + .arg("--all-features") .arg("--manifest-path") .arg(root_dir.join("Cargo.toml")) + .args(&["--", "-W clippy::internal"]) .env("CLIPPY_DOGFOOD", "true") .output() .unwrap(); -- cgit 1.4.1-3-g733a5 From fc35c20a0a45ae215ede9d9f5d6a05813604a5a4 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 26 Sep 2018 15:57:38 +0200 Subject: rustup fix breakage by https://github.com/rust-lang/rust/pull/53824 use smallvec crate instead of rustcs type alias. --- clippy_lints/Cargo.toml | 1 + clippy_lints/src/copies.rs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index b168f86f56a..15da5d65878 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -33,6 +33,7 @@ unicode-normalization = "0.1" pulldown-cmark = "0.1" url = "1.7.0" if_chain = "0.1.3" +smallvec = { version = "0.6.5", features = ["union"] } [features] debugging = [] diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 04a297e5e7e..26669d8c4c2 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -6,7 +6,7 @@ use crate::rustc_data_structures::fx::FxHashMap; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; use crate::syntax::symbol::LocalInternedString; -use crate::rustc_data_structures::small_vec::OneVector; +use smallvec::SmallVec; use crate::utils::{SpanlessEq, SpanlessHash}; use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; @@ -235,9 +235,9 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { /// sequence of `if/else`. /// Eg. would return `([a, b], [c, d, e])` for the expression /// `if a { c } else if b { d } else { e }`. -fn if_sequence(mut expr: &Expr) -> (OneVector<&Expr>, OneVector<&Block>) { - let mut conds = OneVector::new(); - let mut blocks: OneVector<&Block> = OneVector::new(); +fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>) { + let mut conds = SmallVec::new(); + let mut blocks: SmallVec<[&Block; 1]> = SmallVec::new(); while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.node { conds.push(&**cond); -- cgit 1.4.1-3-g733a5 From 2a31937cc997df21498e7649c1f170b5a145ae83 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 26 Sep 2018 11:32:05 +0200 Subject: fix all clippy::use_self pedantic warnings found in the codebase. cc #3172 --- clippy_dev/src/lib.rs | 8 ++++---- clippy_lints/src/consts.rs | 4 ++-- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index e5ce8580fa1..2f91c987cb1 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -35,8 +35,8 @@ pub struct Lint { } impl Lint { - pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Lint { - Lint { + pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self { + Self { name: name.to_lowercase(), group: group.to_string(), desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), @@ -46,12 +46,12 @@ impl Lint { } /// Returns all non-deprecated lints - pub fn active_lints(lints: &[Lint]) -> impl Iterator { + pub fn active_lints(lints: &[Self]) -> impl Iterator { lints.iter().filter(|l| l.deprecation.is_none()) } /// Returns the lints in a HashMap, grouped by the different lint groups - pub fn by_lint_group(lints: &[Lint]) -> HashMap> { + pub fn by_lint_group(lints: &[Self]) -> HashMap> { lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map() } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 43796004d0e..0690d6934e5 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -123,11 +123,11 @@ impl Constant { (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l .iter() .zip(r.iter()) - .map(|(li, ri)| Constant::partial_cmp(tcx, cmp_type, li, ri)) + .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) .find(|r| r.map_or(true, |o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { - match Constant::partial_cmp(tcx, cmp_type, lv, rv) { + match Self::partial_cmp(tcx, cmp_type, lv, rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, } diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 36336b86398..167259b7353 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -46,7 +46,7 @@ pub struct Pass { impl Default for Pass { fn default() -> Self { - Pass { impls: FxHashMap::default() } + Self { impls: FxHashMap::default() } } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 4a58ac2f760..d79a7743e0f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -148,7 +148,7 @@ define_Conf! { } impl Default for Conf { - fn default() -> Conf { + fn default() -> Self { toml::from_str("").expect("we never error on empty config files") } } -- cgit 1.4.1-3-g733a5 From 9fae4693f9d3a7f4e5784b81f726d22c7cd5cb2f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 26 Sep 2018 11:44:50 +0200 Subject: fix clippy::single-match-else and clippy::match_same_arms warnings in clippys codebase --- clippy_lints/src/duration_subsec.rs | 3 +-- clippy_lints/src/multiple_crate_versions.rs | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 8ac34d9daa3..709cbd27754 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -46,9 +46,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); then { let suggested_fn = match (method_path.ident.as_str().as_ref(), divisor) { - ("subsec_micros", 1_000) => "subsec_millis", + ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", ("subsec_nanos", 1_000) => "subsec_micros", - ("subsec_nanos", 1_000_000) => "subsec_millis", _ => return, }; span_lint_and_sugg( diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 2f6b08c5151..9c10a929d6f 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -41,18 +41,17 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { - let metadata = match cargo_metadata::metadata_deps(None, true) { - Ok(metadata) => metadata, - Err(_) => { - span_lint( - cx, - MULTIPLE_CRATE_VERSIONS, - krate.span, - "could not read cargo metadata" - ); + let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { + metadata + } else { + span_lint( + cx, + MULTIPLE_CRATE_VERSIONS, + krate.span, + "could not read cargo metadata" + ); - return; - } + return; }; let mut packages = metadata.packages; -- cgit 1.4.1-3-g733a5 From 4b4d758ce02591d2bb470a19926e3c315c18fef3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 27 Sep 2018 06:29:48 +0200 Subject: Fix warnings in clippy_lints --- clippy_lints/src/lifetimes.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index ee8517b76d7..62e308bb585 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -103,9 +103,9 @@ fn check_fn_inner<'a, 'tcx>( } let mut bounds_lts = Vec::new(); - let types = generics.params.iter().filter_map(|param| match param.kind { - GenericParamKind::Type { .. } => Some(param), - GenericParamKind::Lifetime { .. } => None, + let types = generics.params.iter().filter(|param| match param.kind { + GenericParamKind::Type { .. } => true, + GenericParamKind::Lifetime { .. } => false, }); for typ in types { for bound in &typ.bounds { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 856fa80569f..0011065db67 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -682,13 +682,10 @@ impl LimitStack { } pub fn get_attr<'a>(attrs: &'a [ast::Attribute], name: &'static str) -> impl Iterator { - attrs.iter().filter_map(move |attr| { - if attr.path.segments.len() == 2 && attr.path.segments[0].ident.to_string() == "clippy" && attr.path.segments[1].ident.to_string() == name { - Some(attr) - } else { - None - } - }) + attrs.iter().filter(move |attr| + attr.path.segments.len() == 2 && + attr.path.segments[0].ident.to_string() == "clippy" && + attr.path.segments[1].ident.to_string() == name) } fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { -- cgit 1.4.1-3-g733a5 From e7b820d62633be315497e4951b7bf916d7fcc1ca Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 27 Sep 2018 12:31:28 +0200 Subject: consistently gitignore all Cargo.lock files --- .gitignore | 2 +- clippy_dev/Cargo.lock | 224 -------------------------------------------------- 2 files changed, 1 insertion(+), 225 deletions(-) delete mode 100644 clippy_dev/Cargo.lock diff --git a/.gitignore b/.gitignore index 166cab60a58..f1f4fa4e242 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ out *.exe # Generated by Cargo -Cargo.lock +*Cargo.lock /target /clippy_lints/target /clippy_workspace_tests/target diff --git a/clippy_dev/Cargo.lock b/clippy_dev/Cargo.lock deleted file mode 100644 index 2d94755bae3..00000000000 --- a/clippy_dev/Cargo.lock +++ /dev/null @@ -1,224 +0,0 @@ -[[package]] -name = "aho-corasick" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clap" -version = "2.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clippy_dev" -version = "0.0.1" -dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "itertools" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "strsim" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "termion" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ucd-util" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "utf8-ranges" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" -"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -- cgit 1.4.1-3-g733a5 From db5c63b77ae022eae16d94fd63ff2d264e57c830 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 29 Sep 2018 13:57:04 +0200 Subject: Move tests into separate file --- tests/ui/methods.rs | 14 -------------- tests/ui/methods.stderr | 32 +------------------------------- tests/ui/unnecessary_filter_map.rs | 12 ++++++++++++ tests/ui/unnecessary_filter_map.stderr | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 tests/ui/unnecessary_filter_map.rs create mode 100644 tests/ui/unnecessary_filter_map.stderr diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 111c6ce5a8c..7faa45b987d 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -443,17 +443,3 @@ fn main() { let opt = Some(0); let _ = opt.unwrap(); } - -/// Checks implementation of `UNNECESSARY_FILTER_MAP` lint -fn unnecessary_filter_map() { - let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); - let _ = (0..4).filter_map(|x| match x { - 0 | 1 => None, - _ => Some(x), - }); - - let _ = (0..4).filter_map(|x| Some(x + 1)); - - let _ = (0..4).filter_map(i32::checked_abs); -} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index b006813e26d..3189f375647 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -453,35 +453,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/methods.rs:449:13 - | -449 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` - -error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/methods.rs:450:13 - | -450 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/methods.rs:451:13 - | -451 | let _ = (0..4).filter_map(|x| match x { - | _____________^ -452 | | 0 | 1 => None, -453 | | _ => Some(x), -454 | | }); - | |______^ - -error: this `.filter_map` can be written more simply using `.map` - --> $DIR/methods.rs:456:13 - | -456 | let _ = (0..4).filter_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 60 previous errors +error: aborting due to 56 previous errors diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs new file mode 100644 index 00000000000..dd6cdc5d39d --- /dev/null +++ b/tests/ui/unnecessary_filter_map.rs @@ -0,0 +1,12 @@ +fn main() { + let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); + let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + let _ = (0..4).filter_map(|x| match x { + 0 | 1 => None, + _ => Some(x), + }); + + let _ = (0..4).filter_map(|x| Some(x + 1)); + + let _ = (0..4).filter_map(i32::checked_abs); +} diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr new file mode 100644 index 00000000000..045802047d2 --- /dev/null +++ b/tests/ui/unnecessary_filter_map.stderr @@ -0,0 +1,32 @@ +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/unnecessary_filter_map.rs:2:13 + | +2 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` + +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/unnecessary_filter_map.rs:3:13 + | +3 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this `.filter_map` can be written more simply using `.filter` + --> $DIR/unnecessary_filter_map.rs:4:13 + | +4 | let _ = (0..4).filter_map(|x| match x { + | _____________^ +5 | | 0 | 1 => None, +6 | | _ => Some(x), +7 | | }); + | |______^ + +error: this `.filter_map` can be written more simply using `.map` + --> $DIR/unnecessary_filter_map.rs:9:13 + | +9 | let _ = (0..4).filter_map(|x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From efdc739dfc1babd93540bd2d36c91bf2f7d53502 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 29 Sep 2018 14:12:40 +0200 Subject: Move unnecessary_filter_map to a submodule --- clippy_lints/src/methods.rs | 2436 -------------------- clippy_lints/src/methods/mod.rs | 2298 ++++++++++++++++++ clippy_lints/src/methods/unnecessary_filter_map.rs | 146 ++ 3 files changed, 2444 insertions(+), 2436 deletions(-) delete mode 100644 clippy_lints/src/methods.rs create mode 100644 clippy_lints/src/methods/mod.rs create mode 100644 clippy_lints/src/methods/unnecessary_filter_map.rs diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs deleted file mode 100644 index a0c9e34b861..00000000000 --- a/clippy_lints/src/methods.rs +++ /dev/null @@ -1,2436 +0,0 @@ -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; -use crate::syntax::source_map::{BytePos, Span}; -use crate::utils::paths; -use crate::utils::sugg; -use crate::utils::usage::mutated_variables; -use crate::utils::{ - get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, - iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, - match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, span_lint, - span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, -}; -use if_chain::if_chain; -use matches::matches; -use std::borrow::Cow; -use std::fmt; -use std::iter; - -#[derive(Clone)] -pub struct Pass; - -/// **What it does:** Checks for `.unwrap()` calls on `Option`s. -/// -/// **Why is this bad?** Usually it is better to handle the `None` case, or to -/// at least call `.expect(_)` with a more helpful message. Still, for a lot of -/// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is -/// `Allow` by default. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// x.unwrap() -/// ``` -declare_clippy_lint! { - pub OPTION_UNWRAP_USED, - restriction, - "using `Option.unwrap()`, which should at least get a better message using `expect()`" -} - -/// **What it does:** Checks for `.unwrap()` calls on `Result`s. -/// -/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` -/// values. Normally, you want to implement more sophisticated error handling, -/// and propagate errors upwards with `try!`. -/// -/// Even if you want to panic on errors, not all `Error`s implement good -/// messages on display. Therefore it may be beneficial to look at the places -/// where they may get displayed. Activate this lint to do just that. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// x.unwrap() -/// ``` -declare_clippy_lint! { - pub RESULT_UNWRAP_USED, - restriction, - "using `Result.unwrap()`, which might be better handled" -} - -/// **What it does:** Checks for methods that should live in a trait -/// implementation of a `std` trait (see [llogiq's blog -/// post](http://llogiq.github.io/2015/07/30/traits.html) for further -/// information) instead of an inherent implementation. -/// -/// **Why is this bad?** Implementing the traits improve ergonomics for users of -/// the code, often with very little cost. Also people seeing a `mul(...)` -/// method -/// may expect `*` to work equally, so you should have good reason to disappoint -/// them. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// struct X; -/// impl X { -/// fn add(&self, other: &X) -> X { .. } -/// } -/// ``` -declare_clippy_lint! { - pub SHOULD_IMPLEMENT_TRAIT, - style, - "defining a method that should be implementing a std trait" -} - -/// **What it does:** Checks for methods with certain name prefixes and which -/// doesn't match how self is taken. The actual rules are: -/// -/// |Prefix |`self` taken | -/// |-------|----------------------| -/// |`as_` |`&self` or `&mut self`| -/// |`from_`| none | -/// |`into_`|`self` | -/// |`is_` |`&self` or none | -/// |`to_` |`&self` | -/// -/// **Why is this bad?** Consistency breeds readability. If you follow the -/// conventions, your users won't be surprised that they, e.g., need to supply a -/// mutable reference to a `as_..` function. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// impl X { -/// fn as_str(self) -> &str { .. } -/// } -/// ``` -declare_clippy_lint! { - pub WRONG_SELF_CONVENTION, - style, - "defining a method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" -} - -/// **What it does:** This is the same as -/// [`wrong_self_convention`](#wrong_self_convention), but for public items. -/// -/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). -/// -/// **Known problems:** Actually *renaming* the function may break clients if -/// the function is part of the public interface. In that case, be mindful of -/// the stability guarantees you've given your users. -/// -/// **Example:** -/// ```rust -/// impl X { -/// pub fn as_str(self) -> &str { .. } -/// } -/// ``` -declare_clippy_lint! { - pub WRONG_PUB_SELF_CONVENTION, - restriction, - "defining a public method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" -} - -/// **What it does:** Checks for usage of `ok().expect(..)`. -/// -/// **Why is this bad?** Because you usually call `expect()` on the `Result` -/// directly to get a better error message. -/// -/// **Known problems:** The error type needs to implement `Debug` -/// -/// **Example:** -/// ```rust -/// x.ok().expect("why did I do this again?") -/// ``` -declare_clippy_lint! { - pub OK_EXPECT, - style, - "using `ok().expect()`, which gives worse error messages than \ - calling `expect` directly on the Result" -} - -/// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.map_or(_, _)`. -/// -/// **Known problems:** The order of the arguments is not in execution order -/// -/// **Example:** -/// ```rust -/// x.map(|a| a + 1).unwrap_or(0) -/// ``` -declare_clippy_lint! { - pub OPTION_MAP_UNWRAP_OR, - pedantic, - "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ - `map_or(a, f)`" -} - -/// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.map_or_else(_, _)`. -/// -/// **Known problems:** The order of the arguments is not in execution order. -/// -/// **Example:** -/// ```rust -/// x.map(|a| a + 1).unwrap_or_else(some_function) -/// ``` -declare_clippy_lint! { - pub OPTION_MAP_UNWRAP_OR_ELSE, - pedantic, - "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`" -} - -/// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `result.ok().map_or_else(_, _)`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// x.map(|a| a + 1).unwrap_or_else(some_function) -/// ``` -declare_clippy_lint! { - pub RESULT_MAP_UNWRAP_OR_ELSE, - pedantic, - "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `.ok().map_or_else(g, f)`" -} - -/// **What it does:** Checks for usage of `_.map_or(None, _)`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.and_then(_)`. -/// -/// **Known problems:** The order of the arguments is not in execution order. -/// -/// **Example:** -/// ```rust -/// opt.map_or(None, |a| a + 1) -/// ``` -declare_clippy_lint! { - pub OPTION_MAP_OR_NONE, - style, - "using `Option.map_or(None, f)`, which is more succinctly expressed as \ - `and_then(f)`" -} - -/// **What it does:** Checks for usage of `_.filter(_).next()`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.find(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// iter.filter(|x| x == 0).next() -/// ``` -declare_clippy_lint! { - pub FILTER_NEXT, - complexity, - "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" -} - -/// **What it does:** Checks for usage of `_.map(_).flatten(_)`, -/// -/// **Why is this bad?** Readability, this can be written more concisely as a -/// single method call. -/// -/// **Known problems:** -/// -/// **Example:** -/// ```rust -/// iter.map(|x| x.iter()).flatten() -/// ``` -declare_clippy_lint! { - pub MAP_FLATTEN, - pedantic, - "using combinations of `flatten` and `map` which can usually be written as a \ - single method call" -} - -/// **What it does:** Checks for usage of `_.filter(_).map(_)`, -/// `_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar. -/// -/// **Why is this bad?** Readability, this can be written more concisely as a -/// single method call. -/// -/// **Known problems:** Often requires a condition + Option/Iterator creation -/// inside the closure. -/// -/// **Example:** -/// ```rust -/// iter.filter(|x| x == 0).map(|x| x * 2) -/// ``` -declare_clippy_lint! { - pub FILTER_MAP, - pedantic, - "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ - usually be written as a single method call" -} - -/// **What it does:** Checks for an iterator search (such as `find()`, -/// `position()`, or `rposition()`) followed by a call to `is_some()`. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.any(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// iter.find(|x| x == 0).is_some() -/// ``` -declare_clippy_lint! { - pub SEARCH_IS_SOME, - complexity, - "using an iterator search followed by `is_some()`, which is more succinctly \ - expressed as a call to `any()`" -} - -/// **What it does:** Checks for usage of `.chars().next()` on a `str` to check -/// if it starts with a given char. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.starts_with(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// name.chars().next() == Some('_') -/// ``` -declare_clippy_lint! { - pub CHARS_NEXT_CMP, - complexity, - "using `.chars().next()` to check if a string starts with a char" -} - -/// **What it does:** Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, -/// etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or -/// `unwrap_or_default` instead. -/// -/// **Why is this bad?** The function will always be called and potentially -/// allocate an object acting as the default. -/// -/// **Known problems:** If the function has side-effects, not calling it will -/// change the semantic of the program, but you shouldn't rely on that anyway. -/// -/// **Example:** -/// ```rust -/// foo.unwrap_or(String::new()) -/// ``` -/// this can instead be written: -/// ```rust -/// foo.unwrap_or_else(String::new) -/// ``` -/// or -/// ```rust -/// foo.unwrap_or_default() -/// ``` -declare_clippy_lint! { - pub OR_FUN_CALL, - perf, - "using any `*or` method with a function call, which suggests `*or_else`" -} - -/// **What it does:** Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`, -/// etc., and suggests to use `unwrap_or_else` instead -/// -/// **Why is this bad?** The function will always be called. -/// -/// **Known problems:** If the function has side-effects, not calling it will -/// change the semantic of the program, but you shouldn't rely on that anyway. -/// -/// **Example:** -/// ```rust -/// foo.expect(&format!("Err {}: {}", err_code, err_msg)) -/// ``` -/// or -/// ```rust -/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()) -/// ``` -/// this can instead be written: -/// ```rust -/// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg)) -/// ``` -declare_clippy_lint! { - pub EXPECT_FUN_CALL, - perf, - "using any `expect` method with a function call" -} - -/// **What it does:** Checks for usage of `.clone()` on a `Copy` type. -/// -/// **Why is this bad?** The only reason `Copy` types implement `Clone` is for -/// generics, not for using the `clone` method on a concrete type. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// 42u64.clone() -/// ``` -declare_clippy_lint! { - pub CLONE_ON_COPY, - complexity, - "using `clone` on a `Copy` type" -} - -/// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer, -/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified -/// function syntax instead (e.g. `Rc::clone(foo)`). -/// -/// **Why is this bad?** Calling '.clone()' on an Rc, Arc, or Weak -/// can obscure the fact that only the pointer is being cloned, not the underlying -/// data. -/// -/// **Example:** -/// ```rust -/// x.clone() -/// ``` -declare_clippy_lint! { - pub CLONE_ON_REF_PTR, - restriction, - "using 'clone' on a ref-counted pointer" -} - -/// **What it does:** Checks for usage of `.clone()` on an `&&T`. -/// -/// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of -/// cloning the underlying `T`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn main() { -/// let x = vec![1]; -/// let y = &&x; -/// let z = y.clone(); -/// println!("{:p} {:p}",*y, z); // prints out the same pointer -/// } -/// ``` -declare_clippy_lint! { - pub CLONE_DOUBLE_REF, - correctness, - "using `clone` on `&&T`" -} - -/// **What it does:** Checks for `new` not returning `Self`. -/// -/// **Why is this bad?** As a convention, `new` methods are used to make a new -/// instance of a type. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// impl Foo { -/// fn new(..) -> NotAFoo { -/// } -/// } -/// ``` -declare_clippy_lint! { - pub NEW_RET_NO_SELF, - style, - "not returning `Self` in a `new` method" -} - -/// **What it does:** Checks for string methods that receive a single-character -/// `str` as an argument, e.g. `_.split("x")`. -/// -/// **Why is this bad?** Performing these methods using a `char` is faster than -/// using a `str`. -/// -/// **Known problems:** Does not catch multi-byte unicode characters. -/// -/// **Example:** -/// `_.split("x")` could be `_.split('x')` -declare_clippy_lint! { - pub SINGLE_CHAR_PATTERN, - perf, - "using a single-character str where a char could be used, e.g. \ - `_.split(\"x\")`" -} - -/// **What it does:** Checks for getting the inner pointer of a temporary -/// `CString`. -/// -/// **Why is this bad?** The inner pointer of a `CString` is only valid as long -/// as the `CString` is alive. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust,ignore -/// let c_str = CString::new("foo").unwrap().as_ptr(); -/// unsafe { -/// call_some_ffi_func(c_str); -/// } -/// ``` -/// Here `c_str` point to a freed address. The correct use would be: -/// ```rust,ignore -/// let c_str = CString::new("foo").unwrap(); -/// unsafe { -/// call_some_ffi_func(c_str.as_ptr()); -/// } -/// ``` -declare_clippy_lint! { - pub TEMPORARY_CSTRING_AS_PTR, - correctness, - "getting the inner pointer of a temporary `CString`" -} - -/// **What it does:** Checks for use of `.iter().nth()` (and the related -/// `.iter_mut().nth()`) on standard library types with O(1) element access. -/// -/// **Why is this bad?** `.get()` and `.get_mut()` are more efficient and more -/// readable. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let bad_vec = some_vec.iter().nth(3); -/// let bad_slice = &some_vec[..].iter().nth(3); -/// ``` -/// The correct use would be: -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let bad_vec = some_vec.get(3); -/// let bad_slice = &some_vec[..].get(3); -/// ``` -declare_clippy_lint! { - pub ITER_NTH, - perf, - "using `.iter().nth()` on a standard library type with O(1) element access" -} - -/// **What it does:** Checks for use of `.skip(x).next()` on iterators. -/// -/// **Why is this bad?** `.nth(x)` is cleaner -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let bad_vec = some_vec.iter().skip(3).next(); -/// let bad_slice = &some_vec[..].iter().skip(3).next(); -/// ``` -/// The correct use would be: -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let bad_vec = some_vec.iter().nth(3); -/// let bad_slice = &some_vec[..].iter().nth(3); -/// ``` -declare_clippy_lint! { - pub ITER_SKIP_NEXT, - style, - "using `.skip(x).next()` on an iterator" -} - -/// **What it does:** Checks for use of `.get().unwrap()` (or -/// `.get_mut().unwrap`) on a standard library type which implements `Index` -/// -/// **Why is this bad?** Using the Index trait (`[]`) is more clear and more -/// concise. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let last = some_vec.get(3).unwrap(); -/// *some_vec.get_mut(0).unwrap() = 1; -/// ``` -/// The correct use would be: -/// ```rust -/// let some_vec = vec![0, 1, 2, 3]; -/// let last = some_vec[3]; -/// some_vec[0] = 1; -/// ``` -declare_clippy_lint! { - pub GET_UNWRAP, - style, - "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead" -} - -/// **What it does:** Checks for the use of `.extend(s.chars())` where s is a -/// `&str` or `String`. -/// -/// **Why is this bad?** `.push_str(s)` is clearer -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let abc = "abc"; -/// let def = String::from("def"); -/// let mut s = String::new(); -/// s.extend(abc.chars()); -/// s.extend(def.chars()); -/// ``` -/// The correct use would be: -/// ```rust -/// let abc = "abc"; -/// let def = String::from("def"); -/// let mut s = String::new(); -/// s.push_str(abc); -/// s.push_str(&def)); -/// ``` -declare_clippy_lint! { - pub STRING_EXTEND_CHARS, - style, - "using `x.extend(s.chars())` where s is a `&str` or `String`" -} - -/// **What it does:** Checks for the use of `.cloned().collect()` on slice to -/// create a `Vec`. -/// -/// **Why is this bad?** `.to_vec()` is clearer -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let s = [1,2,3,4,5]; -/// let s2 : Vec = s[..].iter().cloned().collect(); -/// ``` -/// The better use would be: -/// ```rust -/// let s = [1,2,3,4,5]; -/// let s2 : Vec = s.to_vec(); -/// ``` -declare_clippy_lint! { - pub ITER_CLONED_COLLECT, - style, - "using `.cloned().collect()` on slice to create a `Vec`" -} - -/// **What it does:** Checks for usage of `.chars().last()` or -/// `.chars().next_back()` on a `str` to check if it ends with a given char. -/// -/// **Why is this bad?** Readability, this can be written more concisely as -/// `_.ends_with(_)`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-') -/// ``` -declare_clippy_lint! { - pub CHARS_LAST_CMP, - style, - "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char" -} - -/// **What it does:** Checks for usage of `.as_ref()` or `.as_mut()` where the -/// types before and after the call are the same. -/// -/// **Why is this bad?** The call is unnecessary. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let x: &[i32] = &[1,2,3,4,5]; -/// do_stuff(x.as_ref()); -/// ``` -/// The correct use would be: -/// ```rust -/// let x: &[i32] = &[1,2,3,4,5]; -/// do_stuff(x); -/// ``` -declare_clippy_lint! { - pub USELESS_ASREF, - complexity, - "using `as_ref` where the types before and after the call are the same" -} - - -/// **What it does:** Checks for using `fold` when a more succinct alternative exists. -/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, -/// `sum` or `product`. -/// -/// **Why is this bad?** Readability. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let _ = (0..3).fold(false, |acc, x| acc || x > 2); -/// ``` -/// This could be written as: -/// ```rust -/// let _ = (0..3).any(|x| x > 2); -/// ``` -declare_clippy_lint! { - pub UNNECESSARY_FOLD, - style, - "using `fold` when a more succinct alternative exists" -} - - -/// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`. -/// -/// **Why is this bad?** Complexity -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None }); -/// ``` -/// This could be written as: -/// ```rust -/// let _ = (0..3).filter(|&x| x > 2); -/// ``` -declare_clippy_lint! { - pub UNNECESSARY_FILTER_MAP, - complexity, - "using `filter_map` when a more succinct alternative exists" -} - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - OPTION_UNWRAP_USED, - RESULT_UNWRAP_USED, - SHOULD_IMPLEMENT_TRAIT, - WRONG_SELF_CONVENTION, - WRONG_PUB_SELF_CONVENTION, - OK_EXPECT, - OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE, - RESULT_MAP_UNWRAP_OR_ELSE, - OPTION_MAP_OR_NONE, - OR_FUN_CALL, - EXPECT_FUN_CALL, - CHARS_NEXT_CMP, - CHARS_LAST_CMP, - CLONE_ON_COPY, - CLONE_ON_REF_PTR, - CLONE_DOUBLE_REF, - NEW_RET_NO_SELF, - SINGLE_CHAR_PATTERN, - SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR, - FILTER_NEXT, - FILTER_MAP, - MAP_FLATTEN, - ITER_NTH, - ITER_SKIP_NEXT, - GET_UNWRAP, - STRING_EXTEND_CHARS, - ITER_CLONED_COLLECT, - USELESS_ASREF, - UNNECESSARY_FOLD, - UNNECESSARY_FILTER_MAP - ) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - #[allow(clippy::cyclomatic_complexity)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - if in_macro(expr.span) { - return; - } - - match expr.node { - hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { - // Chain calls - // GET_UNWRAP needs to be checked before general `UNWRAP` lints - if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) { - lint_get_unwrap(cx, expr, arglists[0], false); - } else if let Some(arglists) = method_chain_args(expr, &["get_mut", "unwrap"]) { - lint_get_unwrap(cx, expr, arglists[0], true); - } else if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - lint_unwrap(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { - lint_ok_expect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { - lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { - lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map_or"]) { - lint_map_or_none(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { - lint_filter_next(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { - lint_filter_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "map"]) { - lint_filter_map_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "flat_map"]) { - lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { - lint_filter_map_flat_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "flatten"]) { - lint_map_flatten(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { - lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { - lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { - lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { - lint_extend(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { - lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); - } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { - lint_iter_nth(cx, expr, arglists[0], false); - } else if let Some(arglists) = method_chain_args(expr, &["iter_mut", "nth"]) { - lint_iter_nth(cx, expr, arglists[0], true); - } else if method_chain_args(expr, &["skip", "next"]).is_some() { - lint_iter_skip_next(cx, expr); - } else if let Some(arglists) = method_chain_args(expr, &["cloned", "collect"]) { - lint_iter_cloned_collect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["as_ref"]) { - lint_asref(cx, expr, "as_ref", arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { - lint_asref(cx, expr, "as_mut", arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { - lint_unnecessary_fold(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map"]) { - unnecessary_filter_map::lint(cx, expr, arglists[0]); - } - - lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); - lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); - - let self_ty = cx.tables.expr_ty_adjusted(&args[0]); - if args.len() == 1 && method_call.ident.name == "clone" { - lint_clone_on_copy(cx, expr, &args[0], self_ty); - lint_clone_on_ref_ptr(cx, expr, &args[0]); - } - - match self_ty.sty { - ty::Ref(_, ty, _) if ty.sty == ty::Str => for &(method, pos) in &PATTERN_METHODS { - if method_call.ident.name == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); - } - }, - _ => (), - } - }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { - let mut info = BinaryExprInfo { - expr, - chain: lhs, - other: rhs, - eq: op.node == hir::BinOpKind::Eq, - }; - lint_binary_expr_with_method_call(cx, &mut info); - }, - _ => (), - } - } - - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) { - if in_external_macro(cx.sess(), implitem.span) { - return; - } - let name = implitem.ident.name; - let parent = cx.tcx.hir.get_parent(implitem.id); - let item = cx.tcx.hir.expect_item(parent); - if_chain! { - if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; - if let Some(first_arg_ty) = sig.decl.inputs.get(0); - if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); - if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node; - then { - if cx.access_levels.is_exported(implitem.id) { - // check missing trait implementations - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { - if name == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(cx, &sig.decl.output) && - self_kind.matches(cx, first_arg_ty, first_arg, self_ty, false, &implitem.generics) { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); - } - } - } - - // check conventions w.r.t. conversion method names and predicates - let def_id = cx.tcx.hir.local_def_id(item.id); - let ty = cx.tcx.type_of(def_id); - let is_copy = is_copy(cx, ty); - for &(ref conv, self_kinds) in &CONVENTIONS { - if_chain! { - if conv.check(&name.as_str()); - if !self_kinds - .iter() - .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); - then { - let lint = if item.vis.node.is_pub() { - WRONG_PUB_SELF_CONVENTION - } else { - WRONG_SELF_CONVENTION - }; - span_lint(cx, - lint, - first_arg.pat.span, - &format!("methods called `{}` usually take {}; consider choosing a less \ - ambiguous name", - conv, - &self_kinds.iter() - .map(|k| k.description()) - .collect::>() - .join(" or "))); - } - } - } - - let ret_ty = return_ty(cx, implitem.id); - if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { - span_lint(cx, - NEW_RET_NO_SELF, - implitem.span, - "methods called `new` usually return `Self`"); - } - } - } - } -} - -/// Checks for the `OR_FUN_CALL` lint. -fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { - /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. - fn check_unwrap_or_default( - cx: &LateContext<'_, '_>, - name: &str, - fun: &hir::Expr, - self_expr: &hir::Expr, - arg: &hir::Expr, - or_has_args: bool, - span: Span, - ) -> bool { - if or_has_args { - return false; - } - - if name == "unwrap_or" { - if let hir::ExprKind::Path(ref qpath) = fun.node { - let path = &*last_path_segment(qpath).ident.as_str(); - - if ["default", "new"].contains(&path) { - let arg_ty = cx.tables.expr_ty(arg); - let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { - default_trait_id - } else { - return false; - }; - - if implements_trait(cx, arg_ty, default_trait_id, &[]) { - span_lint_and_sugg( - cx, - OR_FUN_CALL, - span, - &format!("use of `{}` followed by a call to `{}`", name, path), - "try this", - format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")), - ); - return true; - } - } - } - } - - false - } - - /// Check for `*or(foo())`. - #[allow(clippy::too_many_arguments)] - fn check_general_case( - cx: &LateContext<'_, '_>, - name: &str, - method_span: Span, - fun_span: Span, - self_expr: &hir::Expr, - arg: &hir::Expr, - or_has_args: bool, - span: Span, - ) { - // (path, fn_has_argument, methods, suffix) - let know_types: &[(&[_], _, &[_], _)] = &[ - (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&paths::RESULT, true, &["or", "unwrap_or"], "else"), - ]; - - // early check if the name is one we care about - if know_types.iter().all(|k| !k.2.contains(&name)) { - return; - } - - // don't lint for constant values - let owner_def = cx.tcx.hir.get_parent_did(arg.id); - let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); - if promotable { - return; - } - - let self_ty = cx.tables.expr_ty(self_expr); - - let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = - know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) - { - (fn_has_arguments, poss, suffix) - } else { - return; - }; - - if !poss.contains(&name) { - return; - } - - let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) { - (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), - (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), - (false, true) => snippet(cx, fun_span, ".."), - }; - let span_replace_word = method_span.with_hi(span.hi()); - span_lint_and_sugg( - cx, - OR_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("{}_{}({})", name, suffix, sugg), - ); - } - - if args.len() == 2 { - match args[1].node { - hir::ExprKind::Call(ref fun, ref or_args) => { - let or_has_args = !or_args.is_empty(); - if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { - check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span); - } - }, - hir::ExprKind::MethodCall(_, span, ref or_args) => { - check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span) - }, - _ => {}, - } - } -} - -/// Checks for the `EXPECT_FUN_CALL` lint. -fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { - fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { - if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node { - if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node { - if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { - if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { - return Some(format_args); - } - } - } - } - - None - } - - fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String { - if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { - if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { - if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { - return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); - } - } - }; - - snippet(cx, a.span, "..").into_owned() - } - - fn check_general_case( - cx: &LateContext<'_, '_>, - name: &str, - method_span: Span, - self_expr: &hir::Expr, - arg: &hir::Expr, - span: Span, - ) { - if name != "expect" { - return; - } - - let self_type = cx.tables.expr_ty(self_expr); - let known_types = &[&paths::OPTION, &paths::RESULT]; - - // if not a known type, return early - if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { - return; - } - - fn is_call(node: &hir::ExprKind) -> bool { - match node { - hir::ExprKind::AddrOf(_, expr) => { - is_call(&expr.node) - }, - hir::ExprKind::Call(..) - | hir::ExprKind::MethodCall(..) - // These variants are debatable or require further examination - | hir::ExprKind::If(..) - | hir::ExprKind::Match(..) => true, - _ => false, - } - } - - if !is_call(&arg.node) { - return; - } - - let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; - let span_replace_word = method_span.with_hi(span.hi()); - - if let Some(format_args) = extract_format_args(arg) { - let args_len = format_args.len(); - let args: Vec = format_args - .into_iter() - .take(args_len - 1) - .map(|a| generate_format_arg_snippet(cx, a)) - .collect(); - - let sugg = args.join(", "); - - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("unwrap_or_else({} panic!({}))", closure, sugg), - ); - - return; - } - - let sugg: Cow<'_, _> = snippet(cx, arg.span, ".."); - - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("unwrap_or_else({} panic!({}))", closure, sugg), - ); - } - - if args.len() == 2 { - match args[1].node { - hir::ExprKind::Lit(_) => {}, - _ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span), - } - } -} - -/// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty<'_>) { - let ty = cx.tables.expr_ty(expr); - if let ty::Ref(_, inner, _) = arg_ty.sty { - if let ty::Ref(_, innermost, _) = inner.sty { - span_lint_and_then( - cx, - CLONE_DOUBLE_REF, - expr.span, - "using `clone` on a double-reference; \ - this will copy the reference instead of cloning the inner type", - |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - let mut ty = innermost; - let mut n = 0; - while let ty::Ref(_, inner, _) = ty.sty { - ty = inner; - n += 1; - } - let refs: String = iter::repeat('&').take(n + 1).collect(); - let derefs: String = iter::repeat('*').take(n).collect(); - let explicit = format!("{}{}::clone({})", refs, ty, snip); - db.span_suggestion_with_applicability( - expr.span, - "try dereferencing it", - format!("{}({}{}).clone()", refs, derefs, snip.deref()), - Applicability::MaybeIncorrect, - ); - db.span_suggestion_with_applicability( - expr.span, - "or try being explicit about what type to clone", - explicit, - Applicability::MaybeIncorrect, - ); - }, - ); - return; // don't report clone_on_copy - } - } - - if is_copy(cx, ty) { - let snip; - if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - if let ty::Ref(..) = cx.tables.expr_ty(arg).sty { - let parent = cx.tcx.hir.get_parent_node(expr.id); - match cx.tcx.hir.get(parent) { - hir::Node::Expr(parent) => match parent.node { - // &*x is a nop, &x.clone() is not - hir::ExprKind::AddrOf(..) | - // (*x).func() is useless, x.clone().func() can work in case func borrows mutably - hir::ExprKind::MethodCall(..) => return, - _ => {}, - } - hir::Node::Stmt(stmt) => { - if let hir::StmtKind::Decl(ref decl, _) = stmt.node { - if let hir::DeclKind::Local(ref loc) = decl.node { - if let hir::PatKind::Ref(..) = loc.pat.node { - // let ref y = *x borrows x, let ref y = x.clone() does not - return; - } - } - } - }, - _ => {}, - } - snip = Some(("try dereferencing it", format!("{}", snippet.deref()))); - } else { - snip = Some(("try removing the `clone` call", format!("{}", snippet))); - } - } else { - snip = None; - } - span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { - if let Some((text, snip)) = snip { - db.span_suggestion_with_applicability( - expr.span, - text, - snip, - Applicability::Unspecified, - ); - } - }); - } -} - -fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr) { - let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); - - if let ty::Adt(_, subst) = obj_ty.sty { - let caller_type = if match_type(cx, obj_ty, &paths::RC) { - "Rc" - } else if match_type(cx, obj_ty, &paths::ARC) { - "Arc" - } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { - "Weak" - } else { - return; - }; - - span_lint_and_sugg( - cx, - CLONE_ON_REF_PTR, - expr.span, - "using '.clone()' on a ref-counted pointer", - "try this", - format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), - ); - } -} - - -fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { - let arg = &args[1]; - if let Some(arglists) = method_chain_args(arg, &["chars"]) { - let target = &arglists[0][0]; - let self_ty = walk_ptrs_ty(cx.tables.expr_ty(target)); - let ref_str = if self_ty.sty == ty::Str { - "" - } else if match_type(cx, self_ty, &paths::STRING) { - "&" - } else { - return; - }; - - span_lint_and_sugg( - cx, - STRING_EXTEND_CHARS, - expr.span, - "calling `.extend(_.chars())`", - "try this", - format!( - "{}.push_str({}{})", - snippet(cx, args[0].span, "_"), - ref_str, - snippet(cx, target.span, "_") - ), - ); - } -} - -fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { - let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); - if match_type(cx, obj_ty, &paths::STRING) { - lint_string_extend(cx, expr, args); - } -} - -fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { - if_chain! { - if let hir::ExprKind::Call(ref fun, ref args) = new.node; - if args.len() == 1; - if let hir::ExprKind::Path(ref path) = fun.node; - if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); - if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); - then { - span_lint_and_then( - cx, - TEMPORARY_CSTRING_AS_PTR, - expr.span, - "you are getting the inner pointer of a temporary `CString`", - |db| { - db.note("that pointer will be invalid outside this expression"); - db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); - }); - } - } -} - -fn lint_iter_cloned_collect(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) - && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() - { - span_lint( - cx, - ITER_CLONED_COLLECT, - expr.span, - "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable", - ); - } -} - -fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: &[hir::Expr]) { - // Check that this is a call to Iterator::fold rather than just some function called fold - if !match_trait_method(cx, expr, &paths::ITERATOR) { - return; - } - - assert!(fold_args.len() == 3, - "Expected fold_args to have three entries - the receiver, the initial value and the closure"); - - fn check_fold_with_op( - cx: &LateContext<'_, '_>, - fold_args: &[hir::Expr], - op: hir::BinOpKind, - replacement_method_name: &str, - replacement_has_args: bool) { - - if_chain! { - // Extract the body of the closure passed to fold - if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node; - let closure_body = cx.tcx.hir.body(body_id); - let closure_expr = remove_blocks(&closure_body.value); - - // Check if the closure body is of the form `acc some_expr(x)` - if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; - if bin_op.node == op; - - // Extract the names of the two arguments to the closure - if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); - if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); - - if match_var(&*left_expr, first_arg_ident); - if replacement_has_args || match_var(&*right_expr, second_arg_ident); - - then { - // Span containing `.fold(...)` - let next_point = cx.sess().source_map().next_point(fold_args[0].span); - let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1)); - - let sugg = if replacement_has_args { - format!( - ".{replacement}(|{s}| {r})", - replacement = replacement_method_name, - s = second_arg_ident, - r = snippet(cx, right_expr.span, "EXPR"), - ) - } else { - format!( - ".{replacement}()", - replacement = replacement_method_name, - ) - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_FOLD, - fold_span, - // TODO #2371 don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) - "this `.fold` can be written more succinctly using another method", - "try", - sugg, - ); - } - } - } - - // Check if the first argument to .fold is a suitable literal - match fold_args[1].node { - hir::ExprKind::Lit(ref lit) => { - match lit.node { - ast::LitKind::Bool(false) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Or, "any", true - ), - ast::LitKind::Bool(true) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::And, "all", true - ), - ast::LitKind::Int(0, _) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Add, "sum", false - ), - ast::LitKind::Int(1, _) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Mul, "product", false - ), - _ => return - } - } - _ => return - }; -} - -mod unnecessary_filter_map { - use super::*; - - pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { - - if !match_trait_method(cx, expr, &paths::ITERATOR) { - return; - } - - if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].node { - - let body = cx.tcx.hir.body(body_id); - let arg_id = body.arguments[0].pat.id; - let mutates_arg = match mutated_variables(&body.value, cx) { - Some(used_mutably) => used_mutably.contains(&arg_id), - None => true, - }; - - let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value); - - let mut return_visitor = ReturnVisitor::new(&cx, arg_id); - return_visitor.visit_expr(&body.value); - found_mapping |= return_visitor.found_mapping; - found_filtering |= return_visitor.found_filtering; - - if !found_filtering { - span_lint( - cx, - UNNECESSARY_FILTER_MAP, - expr.span, - "this `.filter_map` can be written more simply using `.map`", - ); - return; - } - - if !found_mapping && !mutates_arg { - span_lint( - cx, - UNNECESSARY_FILTER_MAP, - expr.span, - "this `.filter_map` can be written more simply using `.filter`", - ); - return; - } - } - } - - // returns (found_mapping, found_filtering) - fn check_expression<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId, expr: &'tcx hir::Expr) -> (bool, bool) { - match &expr.node { - hir::ExprKind::Call(ref func, ref args) => { - if_chain! { - if let hir::ExprKind::Path(ref path) = func.node; - then { - if match_qpath(path, &paths::OPTION_SOME) { - if_chain! { - if let hir::ExprKind::Path(path) = &args[0].node; - if let Def::Local(ref local) = cx.tables.qpath_def(path, args[0].hir_id); - then { - if arg_id == *local { - return (false, false) - } - } - } - return (true, false); - } else { - // We don't know. It might do anything. - return (true, true); - } - } - } - (true, true) - }, - hir::ExprKind::Block(ref block, _) => { - if let Some(expr) = &block.expr { - check_expression(cx, arg_id, &expr) - } else { - (false, false) - } - }, - // There must be an else_arm or there will be a type error - hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => { - let if_check = check_expression(cx, arg_id, if_arm); - let else_check = check_expression(cx, arg_id, else_arm); - (if_check.0 | else_check.0, if_check.1 | else_check.1) - }, - hir::ExprKind::Match(_, ref arms, _) => { - let mut found_mapping = false; - let mut found_filtering = false; - for arm in arms { - let (m, f) = check_expression(cx, arg_id, &arm.body); - found_mapping |= m; - found_filtering |= f; - } - (found_mapping, found_filtering) - }, - hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), - _ => (true, true) - } - } - - struct ReturnVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, - arg_id: ast::NodeId, - // Found a non-None return that isn't Some(input) - found_mapping: bool, - // Found a return that isn't Some - found_filtering: bool, - } - - impl<'a, 'tcx: 'a> ReturnVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId) -> ReturnVisitor<'a, 'tcx> { - ReturnVisitor { - cx, - arg_id, - found_mapping: false, - found_filtering: false, - } - } - } - - impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if let hir::ExprKind::Ret(Some(expr)) = &expr.node { - let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr); - self.found_mapping |= found_mapping; - self.found_filtering |= found_filtering; - } else { - walk_expr(self, expr); - } - } - - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - } -} - -fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { - let mut_str = if is_mut { "_mut" } else { "" }; - let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { - "slice" - } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC) { - "Vec" - } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { - "VecDeque" - } else { - return; // caller is not a type that we want to lint - }; - - span_lint( - cx, - ITER_NTH, - expr.span, - &format!( - "called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", - mut_str, - caller_type - ), - ); -} - -fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { - // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap, - // because they do not implement `IndexMut` - let expr_ty = cx.tables.expr_ty(&get_args[0]); - let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { - "slice" - } else if match_type(cx, expr_ty, &paths::VEC) { - "Vec" - } else if match_type(cx, expr_ty, &paths::VEC_DEQUE) { - "VecDeque" - } else if !is_mut && match_type(cx, expr_ty, &paths::HASHMAP) { - "HashMap" - } else if !is_mut && match_type(cx, expr_ty, &paths::BTREEMAP) { - "BTreeMap" - } else { - return; // caller is not a type that we want to lint - }; - - let mut_str = if is_mut { "_mut" } else { "" }; - let borrow_str = if is_mut { "&mut " } else { "&" }; - span_lint_and_sugg( - cx, - GET_UNWRAP, - expr.span, - &format!( - "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", - mut_str, - caller_type - ), - "try this", - format!( - "{}{}[{}]", - borrow_str, - snippet(cx, get_args[0].span, "_"), - snippet(cx, get_args[1].span, "_") - ), - ); -} - -fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) { - // lint if caller of skip is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - span_lint( - cx, - ITER_SKIP_NEXT, - expr.span, - "called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`", - ); - } -} - -fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Option> { - fn may_slice(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { - match ty.sty { - ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::Adt(..) => match_type(cx, ty, &paths::VEC), - ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, - ty::Ref(_, inner, _) => may_slice(cx, inner), - _ => false, - } - } - - if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.node { - if path.ident.name == "iter" && may_slice(cx, cx.tables.expr_ty(&args[0])) { - sugg::Sugg::hir_opt(cx, &args[0]).map(|sugg| sugg.addr()) - } else { - None - } - } else { - match ty.sty { - ty::Slice(_) => sugg::Sugg::hir_opt(cx, expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::Ref(_, inner, _) => if may_slice(cx, inner) { - sugg::Sugg::hir_opt(cx, expr) - } else { - None - }, - _ => None, - } - } -} - -/// lint use of `unwrap()` for `Option`s and `Result`s -fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { - let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); - - let mess = if match_type(cx, obj_ty, &paths::OPTION) { - Some((OPTION_UNWRAP_USED, "an Option", "None")) - } else if match_type(cx, obj_ty, &paths::RESULT) { - Some((RESULT_UNWRAP_USED, "a Result", "Err")) - } else { - None - }; - - if let Some((lint, kind, none_value)) = mess { - span_lint( - cx, - lint, - expr.span, - &format!( - "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ - using expect() to provide a better panic \ - message", - kind, - none_value - ), - ); - } -} - -/// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) { - // lint if the caller of `ok()` is a `Result` - if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT) { - let result_type = cx.tables.expr_ty(&ok_args[0]); - if let Some(error_type) = get_error_type(cx, result_type) { - if has_debug_impl(error_type, cx) { - span_lint( - cx, - OK_EXPECT, - expr.span, - "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`", - ); - } - } - } -} - -/// lint use of `map().unwrap_or()` for `Option`s -fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { - // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { - // get snippets for args to map() and unwrap_or() - let map_snippet = snippet(cx, map_args[1].span, ".."); - let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); - // lint message - // comparing the snippet from source to raw text ("None") below is safe - // because we already have checked the type. - let arg = if unwrap_snippet == "None" { - "None" - } else { - "a" - }; - let suggest = if unwrap_snippet == "None" { - "and_then(f)" - } else { - "map_or(a, f)" - }; - let msg = &format!( - "called `map(f).unwrap_or({})` on an Option value. \ - This can be done more directly by calling `{}` instead", - arg, - suggest - ); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or() have the same span - let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); - if same_span && !multiline { - let suggest = if unwrap_snippet == "None" { - format!("and_then({})", map_snippet) - } else { - format!("map_or({}, {})", unwrap_snippet, map_snippet) - }; - let note = format!( - "replace `map({}).unwrap_or({})` with `{}`", - map_snippet, - unwrap_snippet, - suggest - ); - span_note_and_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, ¬e); - } else if same_span && multiline { - span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); - }; - } -} - -/// lint use of `map().flatten()` for `Iterators` -fn lint_map_flatten<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - map_args: &'tcx [hir::Expr], -) { - // lint if caller of `.map().flatten()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `map(..).flatten()` on an `Iterator`. \ - This is more succinctly expressed by calling `.flat_map(..)`"; - let self_snippet = snippet(cx, map_args[0].span, ".."); - let func_snippet = snippet(cx, map_args[1].span, ".."); - let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); - span_lint_and_then(cx, MAP_FLATTEN, expr.span, msg, |db| { - db.span_suggestion_with_applicability( - expr.span, - "try using flat_map instead", - hint, - Applicability::MachineApplicable, - ); - }); - } -} - -/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s -fn lint_map_unwrap_or_else<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - map_args: &'tcx [hir::Expr], - unwrap_args: &'tcx [hir::Expr], -) { - // lint if the caller of `map()` is an `Option` - let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION); - let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT); - if is_option || is_result { - // lint message - let msg = if is_option { - "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ - `map_or_else(g, f)` instead" - } else { - "called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling \ - `ok().map_or_else(g, f)` instead" - }; - // get snippets for args to map() and unwrap_or_else() - let map_snippet = snippet(cx, map_args[1].span, ".."); - let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); - // lint, with note if neither arg is > 1 line and both map() and - // unwrap_or_else() have the same span - let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); - if same_span && !multiline { - span_note_and_lint( - cx, - if is_option { - OPTION_MAP_UNWRAP_OR_ELSE - } else { - RESULT_MAP_UNWRAP_OR_ELSE - }, - expr.span, - msg, - expr.span, - &format!( - "replace `map({0}).unwrap_or_else({1})` with `{2}map_or_else({1}, {0})`", - map_snippet, - unwrap_snippet, - if is_result { "ok()." } else { "" } - ), - ); - } else if same_span && multiline { - span_lint( - cx, - if is_option { - OPTION_MAP_UNWRAP_OR_ELSE - } else { - RESULT_MAP_UNWRAP_OR_ELSE - }, - expr.span, - msg, - ); - }; - } -} - -/// lint use of `_.map_or(None, _)` for `Option`s -fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { - if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { - // check if the first non-self argument to map_or() is None - let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].node { - match_qpath(qpath, &paths::OPTION_NONE) - } else { - false - }; - - if map_or_arg_is_none { - // lint message - let msg = "called `map_or(None, f)` on an Option value. This can be done more directly by calling \ - `and_then(f)` instead"; - let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); - let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); - let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); - span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { - db.span_suggestion_with_applicability( - expr.span, - "try using and_then instead", - hint, - Applicability::MachineApplicable, // snippet - ); - }); - } - } -} - -/// lint use of `filter().next()` for `Iterators` -fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) { - // lint if caller of `.filter().next()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \ - `.find(p)` instead."; - let filter_snippet = snippet(cx, filter_args[1].span, ".."); - if filter_snippet.lines().count() <= 1 { - // add note if not multi-line - span_note_and_lint( - cx, - FILTER_NEXT, - expr.span, - msg, - expr.span, - &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet), - ); - } else { - span_lint(cx, FILTER_NEXT, expr.span, msg); - } - } -} - -/// lint use of `filter().map()` for `Iterators` -fn lint_filter_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { - // lint if caller of `.filter().map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).map(q)` on an `Iterator`. \ - This is more succinctly expressed by calling `.filter_map(..)` instead."; - span_lint(cx, FILTER_MAP, expr.span, msg); - } -} - -/// lint use of `filter().map()` for `Iterators` -fn lint_filter_map_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { - // lint if caller of `.filter().map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ - This is more succinctly expressed by only calling `.filter_map(..)` instead."; - span_lint(cx, FILTER_MAP, expr.span, msg); - } -} - -/// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { - // lint if caller of `.filter().flat_map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ - This is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_MAP, expr.span, msg); - } -} - -/// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - _filter_args: &'tcx [hir::Expr], - _map_args: &'tcx [hir::Expr], -) { - // lint if caller of `.filter_map().flat_map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ - This is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning an empty Iterator."; - span_lint(cx, FILTER_MAP, expr.span, msg); - } -} - -/// lint searching an Iterator followed by `is_some()` -fn lint_search_is_some<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - search_method: &str, - search_args: &'tcx [hir::Expr], - is_some_args: &'tcx [hir::Expr], -) { - // lint if caller of search is an Iterator - if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { - let msg = format!( - "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ - expressed by calling `any()`.", - search_method - ); - let search_snippet = snippet(cx, search_args[1].span, ".."); - if search_snippet.lines().count() <= 1 { - // add note if not multi-line - span_note_and_lint( - cx, - SEARCH_IS_SOME, - expr.span, - &msg, - expr.span, - &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet), - ); - } else { - span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); - } - } -} - -/// Used for `lint_binary_expr_with_method_call`. -#[derive(Copy, Clone)] -struct BinaryExprInfo<'a> { - expr: &'a hir::Expr, - chain: &'a hir::Expr, - other: &'a hir::Expr, - eq: bool, -} - -/// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. -fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut BinaryExprInfo<'_>) { - macro_rules! lint_with_both_lhs_and_rhs { - ($func:ident, $cx:expr, $info:ident) => { - if !$func($cx, $info) { - ::std::mem::swap(&mut $info.chain, &mut $info.other); - if $func($cx, $info) { - return; - } - } - } - } - - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); -} - -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. -fn lint_chars_cmp( - cx: &LateContext<'_, '_>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.node; - if arg_char.len() == 1; - if let hir::ExprKind::Path(ref qpath) = fun.node; - if let Some(segment) = single_segment_path(qpath); - if segment.ident.name == "Some"; - then { - let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); - - if self_ty.sty != ty::Str { - return false; - } - - span_lint_and_sugg(cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}({})", - if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - suggest, - snippet(cx, arg_char[0].span, "_"))); - - return true; - } - } - - false -} - -/// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") -} - -/// Checks for the `CHARS_LAST_CMP` lint. -fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") { - true - } else { - lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_NEXT_CMP, "ends_with") - } -} - -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Lit(ref lit) = info.other.node; - if let ast::LitKind::Char(c) = lit.node; - then { - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}('{}')", - if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - suggest, - c) - ); - - return true; - } - } - - false -} - -/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. -fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") -} - -/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. -fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { - true - } else { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") - } -} - -/// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { - if_chain! { - if let hir::ExprKind::Lit(lit) = &arg.node; - if let ast::LitKind::Str(r, _) = lit.node; - if r.as_str().len() == 1; - then { - let snip = snippet(cx, arg.span, ".."); - let hint = format!("'{}'", &snip[1..snip.len() - 1]); - span_lint_and_sugg( - cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - "try using a char instead", - hint, - ); - } - } -} - -/// Checks for the `USELESS_ASREF` lint. -fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) { - // when we get here, we've already checked that the call name is "as_ref" or "as_mut" - // check if the call is to the actual `AsRef` or `AsMut` trait - if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { - // check if the type after `as_ref` or `as_mut` is the same as before - let recvr = &as_ref_args[0]; - let rcv_ty = cx.tables.expr_ty(recvr); - let res_ty = cx.tables.expr_ty(expr); - let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); - let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); - if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { - span_lint_and_sugg( - cx, - USELESS_ASREF, - expr.span, - &format!("this call to `{}` does nothing", call_name), - "try this", - snippet(cx, recvr.span, "_").into_owned(), - ); - } - } -} - -/// Given a `Result` type, return its error type (`E`). -fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { - if let ty::Adt(_, substs) = ty.sty { - if match_type(cx, ty, &paths::RESULT) { - substs.types().nth(1) - } else { - None - } - } else { - None - } -} - -/// This checks whether a given type is known to implement Debug. -fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { - match cx.tcx.lang_items().debug_trait() { - Some(debug) => implements_trait(cx, ty, debug, &[]), - None => false, - } -} - -enum Convention { - Eq(&'static str), - StartsWith(&'static str), -} - -#[rustfmt::skip] -const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ - (Convention::Eq("new"), &[SelfKind::No]), - (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), - (Convention::StartsWith("from_"), &[SelfKind::No]), - (Convention::StartsWith("into_"), &[SelfKind::Value]), - (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), - (Convention::StartsWith("to_"), &[SelfKind::Ref]), -]; - -#[rustfmt::skip] -const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ - ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), - ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), - ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), - ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), - ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), - ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), - ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), - ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), - ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), - ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), - ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), - ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), - ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), - ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), - ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), - ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), - ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), - ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), - ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), - ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), - ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), - ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), - ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), - ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), - ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), - ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), - ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), - ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), - ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), - ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), -]; - -#[rustfmt::skip] -const PATTERN_METHODS: [(&str, usize); 17] = [ - ("contains", 1), - ("starts_with", 1), - ("ends_with", 1), - ("find", 1), - ("rfind", 1), - ("split", 1), - ("rsplit", 1), - ("split_terminator", 1), - ("rsplit_terminator", 1), - ("splitn", 2), - ("rsplitn", 2), - ("matches", 1), - ("rmatches", 1), - ("match_indices", 1), - ("rmatch_indices", 1), - ("trim_left_matches", 1), - ("trim_right_matches", 1), -]; - - -#[derive(Clone, Copy, PartialEq, Debug)] -enum SelfKind { - Value, - Ref, - RefMut, - No, -} - -impl SelfKind { - fn matches( - self, - cx: &LateContext<'_, '_>, - ty: &hir::Ty, - arg: &hir::Arg, - self_ty: &hir::Ty, - allow_value_for_ref: bool, - generics: &hir::Generics, - ) -> bool { - // Self types in the HIR are desugared to explicit self types. So it will - // always be `self: - // SomeType`, - // where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if - // the impl is on `Foo`) - // Thus, we only need to test equality against the impl self type or if it is - // an explicit - // `Self`. Furthermore, the only possible types for `self: ` are `&Self`, - // `Self`, `&mut Self`, - // and `Box`, including the equivalent types with `Foo`. - - let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty); - if is_self(arg) { - match self { - SelfKind::Value => is_actually_self(ty), - SelfKind::Ref | SelfKind::RefMut => { - if allow_value_for_ref && is_actually_self(ty) { - return true; - } - match ty.node { - hir::TyKind::Rptr(_, ref mt_ty) => { - let mutability_match = if self == SelfKind::Ref { - mt_ty.mutbl == hir::MutImmutable - } else { - mt_ty.mutbl == hir::MutMutable - }; - is_actually_self(&mt_ty.ty) && mutability_match - }, - _ => false, - } - }, - _ => false, - } - } else { - match self { - SelfKind::Value => false, - SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT), - SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT), - SelfKind::No => true, - } - } - } - - fn description(self) -> &'static str { - match self { - SelfKind::Value => "self by value", - SelfKind::Ref => "self by reference", - SelfKind::RefMut => "self by mutable reference", - SelfKind::No => "no self", - } - } -} - -fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { - single_segment_ty(ty).map_or(false, |seg| { - generics.params.iter().any(|param| match param.kind { - hir::GenericParamKind::Type { .. } => { - param.name.ident().name == seg.ident.name && param.bounds.iter().any(|bound| { - if let hir::GenericBound::Trait(ref ptr, ..) = *bound { - let path = &ptr.trait_ref.path; - match_path(path, name) && path.segments.last().map_or(false, |s| { - if let Some(ref params) = s.args { - if params.parenthesized { - false - } else { - // FIXME(flip1995): messy, improve if there is a better option - // in the compiler - let types: Vec<_> = params.args.iter().filter_map(|arg| match arg { - hir::GenericArg::Type(ty) => Some(ty), - _ => None, - }).collect(); - types.len() == 1 - && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty)) - } - } else { - false - } - }) - } else { - false - } - }) - }, - _ => false, - }) - }) -} - -fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { - match (&ty.node, &self_ty.node) { - ( - &hir::TyKind::Path(hir::QPath::Resolved(_, ref ty_path)), - &hir::TyKind::Path(hir::QPath::Resolved(_, ref self_ty_path)), - ) => ty_path - .segments - .iter() - .map(|seg| seg.ident.name) - .eq(self_ty_path.segments.iter().map(|seg| seg.ident.name)), - _ => false, - } -} - -fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> { - if let hir::TyKind::Path(ref path) = ty.node { - single_segment_path(path) - } else { - None - } -} - -impl Convention { - fn check(&self, other: &str) -> bool { - match *self { - Convention::Eq(this) => this == other, - Convention::StartsWith(this) => other.starts_with(this) && this != other, - } - } -} - -impl fmt::Display for Convention { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match *self { - Convention::Eq(this) => this.fmt(f), - Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), - } - } -} - -#[derive(Clone, Copy)] -enum OutType { - Unit, - Bool, - Any, - Ref, -} - -impl OutType { - fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy) -> bool { - let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into())); - match (self, ty) { - (OutType::Unit, &hir::DefaultReturn(_)) => true, - (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, - (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, - (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, - (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)), - _ => false, - } - } -} - -fn is_bool(ty: &hir::Ty) -> bool { - if let hir::TyKind::Path(ref p) = ty.node { - match_qpath(p, &["bool"]) - } else { - false - } -} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs new file mode 100644 index 00000000000..828ef5b12bd --- /dev/null +++ b/clippy_lints/src/methods/mod.rs @@ -0,0 +1,2298 @@ +use crate::rustc::hir; +use crate::rustc::hir::def::Def; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; +use crate::rustc::ty::{self, Ty}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast; +use crate::syntax::source_map::{BytePos, Span}; +use crate::utils::paths; +use crate::utils::sugg; +use crate::utils::{ + get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, + iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, + match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, span_lint, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, +}; +use if_chain::if_chain; +use matches::matches; +use std::borrow::Cow; +use std::fmt; +use std::iter; + +mod unnecessary_filter_map; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for `.unwrap()` calls on `Option`s. +/// +/// **Why is this bad?** Usually it is better to handle the `None` case, or to +/// at least call `.expect(_)` with a more helpful message. Still, for a lot of +/// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is +/// `Allow` by default. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x.unwrap() +/// ``` +declare_clippy_lint! { + pub OPTION_UNWRAP_USED, + restriction, + "using `Option.unwrap()`, which should at least get a better message using `expect()`" +} + +/// **What it does:** Checks for `.unwrap()` calls on `Result`s. +/// +/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` +/// values. Normally, you want to implement more sophisticated error handling, +/// and propagate errors upwards with `try!`. +/// +/// Even if you want to panic on errors, not all `Error`s implement good +/// messages on display. Therefore it may be beneficial to look at the places +/// where they may get displayed. Activate this lint to do just that. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x.unwrap() +/// ``` +declare_clippy_lint! { + pub RESULT_UNWRAP_USED, + restriction, + "using `Result.unwrap()`, which might be better handled" +} + +/// **What it does:** Checks for methods that should live in a trait +/// implementation of a `std` trait (see [llogiq's blog +/// post](http://llogiq.github.io/2015/07/30/traits.html) for further +/// information) instead of an inherent implementation. +/// +/// **Why is this bad?** Implementing the traits improve ergonomics for users of +/// the code, often with very little cost. Also people seeing a `mul(...)` +/// method +/// may expect `*` to work equally, so you should have good reason to disappoint +/// them. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// struct X; +/// impl X { +/// fn add(&self, other: &X) -> X { .. } +/// } +/// ``` +declare_clippy_lint! { + pub SHOULD_IMPLEMENT_TRAIT, + style, + "defining a method that should be implementing a std trait" +} + +/// **What it does:** Checks for methods with certain name prefixes and which +/// doesn't match how self is taken. The actual rules are: +/// +/// |Prefix |`self` taken | +/// |-------|----------------------| +/// |`as_` |`&self` or `&mut self`| +/// |`from_`| none | +/// |`into_`|`self` | +/// |`is_` |`&self` or none | +/// |`to_` |`&self` | +/// +/// **Why is this bad?** Consistency breeds readability. If you follow the +/// conventions, your users won't be surprised that they, e.g., need to supply a +/// mutable reference to a `as_..` function. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl X { +/// fn as_str(self) -> &str { .. } +/// } +/// ``` +declare_clippy_lint! { + pub WRONG_SELF_CONVENTION, + style, + "defining a method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} + +/// **What it does:** This is the same as +/// [`wrong_self_convention`](#wrong_self_convention), but for public items. +/// +/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). +/// +/// **Known problems:** Actually *renaming* the function may break clients if +/// the function is part of the public interface. In that case, be mindful of +/// the stability guarantees you've given your users. +/// +/// **Example:** +/// ```rust +/// impl X { +/// pub fn as_str(self) -> &str { .. } +/// } +/// ``` +declare_clippy_lint! { + pub WRONG_PUB_SELF_CONVENTION, + restriction, + "defining a public method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" +} + +/// **What it does:** Checks for usage of `ok().expect(..)`. +/// +/// **Why is this bad?** Because you usually call `expect()` on the `Result` +/// directly to get a better error message. +/// +/// **Known problems:** The error type needs to implement `Debug` +/// +/// **Example:** +/// ```rust +/// x.ok().expect("why did I do this again?") +/// ``` +declare_clippy_lint! { + pub OK_EXPECT, + style, + "using `ok().expect()`, which gives worse error messages than \ + calling `expect` directly on the Result" +} + +/// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.map_or(_, _)`. +/// +/// **Known problems:** The order of the arguments is not in execution order +/// +/// **Example:** +/// ```rust +/// x.map(|a| a + 1).unwrap_or(0) +/// ``` +declare_clippy_lint! { + pub OPTION_MAP_UNWRAP_OR, + pedantic, + "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ + `map_or(a, f)`" +} + +/// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.map_or_else(_, _)`. +/// +/// **Known problems:** The order of the arguments is not in execution order. +/// +/// **Example:** +/// ```rust +/// x.map(|a| a + 1).unwrap_or_else(some_function) +/// ``` +declare_clippy_lint! { + pub OPTION_MAP_UNWRAP_OR_ELSE, + pedantic, + "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `map_or_else(g, f)`" +} + +/// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `result.ok().map_or_else(_, _)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// x.map(|a| a + 1).unwrap_or_else(some_function) +/// ``` +declare_clippy_lint! { + pub RESULT_MAP_UNWRAP_OR_ELSE, + pedantic, + "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `.ok().map_or_else(g, f)`" +} + +/// **What it does:** Checks for usage of `_.map_or(None, _)`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.and_then(_)`. +/// +/// **Known problems:** The order of the arguments is not in execution order. +/// +/// **Example:** +/// ```rust +/// opt.map_or(None, |a| a + 1) +/// ``` +declare_clippy_lint! { + pub OPTION_MAP_OR_NONE, + style, + "using `Option.map_or(None, f)`, which is more succinctly expressed as \ + `and_then(f)`" +} + +/// **What it does:** Checks for usage of `_.filter(_).next()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.find(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// iter.filter(|x| x == 0).next() +/// ``` +declare_clippy_lint! { + pub FILTER_NEXT, + complexity, + "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`" +} + +/// **What it does:** Checks for usage of `_.map(_).flatten(_)`, +/// +/// **Why is this bad?** Readability, this can be written more concisely as a +/// single method call. +/// +/// **Known problems:** +/// +/// **Example:** +/// ```rust +/// iter.map(|x| x.iter()).flatten() +/// ``` +declare_clippy_lint! { + pub MAP_FLATTEN, + pedantic, + "using combinations of `flatten` and `map` which can usually be written as a \ + single method call" +} + +/// **What it does:** Checks for usage of `_.filter(_).map(_)`, +/// `_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar. +/// +/// **Why is this bad?** Readability, this can be written more concisely as a +/// single method call. +/// +/// **Known problems:** Often requires a condition + Option/Iterator creation +/// inside the closure. +/// +/// **Example:** +/// ```rust +/// iter.filter(|x| x == 0).map(|x| x * 2) +/// ``` +declare_clippy_lint! { + pub FILTER_MAP, + pedantic, + "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ + usually be written as a single method call" +} + +/// **What it does:** Checks for an iterator search (such as `find()`, +/// `position()`, or `rposition()`) followed by a call to `is_some()`. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.any(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// iter.find(|x| x == 0).is_some() +/// ``` +declare_clippy_lint! { + pub SEARCH_IS_SOME, + complexity, + "using an iterator search followed by `is_some()`, which is more succinctly \ + expressed as a call to `any()`" +} + +/// **What it does:** Checks for usage of `.chars().next()` on a `str` to check +/// if it starts with a given char. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.starts_with(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// name.chars().next() == Some('_') +/// ``` +declare_clippy_lint! { + pub CHARS_NEXT_CMP, + complexity, + "using `.chars().next()` to check if a string starts with a char" +} + +/// **What it does:** Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, +/// etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or +/// `unwrap_or_default` instead. +/// +/// **Why is this bad?** The function will always be called and potentially +/// allocate an object acting as the default. +/// +/// **Known problems:** If the function has side-effects, not calling it will +/// change the semantic of the program, but you shouldn't rely on that anyway. +/// +/// **Example:** +/// ```rust +/// foo.unwrap_or(String::new()) +/// ``` +/// this can instead be written: +/// ```rust +/// foo.unwrap_or_else(String::new) +/// ``` +/// or +/// ```rust +/// foo.unwrap_or_default() +/// ``` +declare_clippy_lint! { + pub OR_FUN_CALL, + perf, + "using any `*or` method with a function call, which suggests `*or_else`" +} + +/// **What it does:** Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`, +/// etc., and suggests to use `unwrap_or_else` instead +/// +/// **Why is this bad?** The function will always be called. +/// +/// **Known problems:** If the function has side-effects, not calling it will +/// change the semantic of the program, but you shouldn't rely on that anyway. +/// +/// **Example:** +/// ```rust +/// foo.expect(&format!("Err {}: {}", err_code, err_msg)) +/// ``` +/// or +/// ```rust +/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()) +/// ``` +/// this can instead be written: +/// ```rust +/// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg)) +/// ``` +declare_clippy_lint! { + pub EXPECT_FUN_CALL, + perf, + "using any `expect` method with a function call" +} + +/// **What it does:** Checks for usage of `.clone()` on a `Copy` type. +/// +/// **Why is this bad?** The only reason `Copy` types implement `Clone` is for +/// generics, not for using the `clone` method on a concrete type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// 42u64.clone() +/// ``` +declare_clippy_lint! { + pub CLONE_ON_COPY, + complexity, + "using `clone` on a `Copy` type" +} + +/// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer, +/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified +/// function syntax instead (e.g. `Rc::clone(foo)`). +/// +/// **Why is this bad?** Calling '.clone()' on an Rc, Arc, or Weak +/// can obscure the fact that only the pointer is being cloned, not the underlying +/// data. +/// +/// **Example:** +/// ```rust +/// x.clone() +/// ``` +declare_clippy_lint! { + pub CLONE_ON_REF_PTR, + restriction, + "using 'clone' on a ref-counted pointer" +} + +/// **What it does:** Checks for usage of `.clone()` on an `&&T`. +/// +/// **Why is this bad?** Cloning an `&&T` copies the inner `&T`, instead of +/// cloning the underlying `T`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn main() { +/// let x = vec![1]; +/// let y = &&x; +/// let z = y.clone(); +/// println!("{:p} {:p}",*y, z); // prints out the same pointer +/// } +/// ``` +declare_clippy_lint! { + pub CLONE_DOUBLE_REF, + correctness, + "using `clone` on `&&T`" +} + +/// **What it does:** Checks for `new` not returning `Self`. +/// +/// **Why is this bad?** As a convention, `new` methods are used to make a new +/// instance of a type. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// impl Foo { +/// fn new(..) -> NotAFoo { +/// } +/// } +/// ``` +declare_clippy_lint! { + pub NEW_RET_NO_SELF, + style, + "not returning `Self` in a `new` method" +} + +/// **What it does:** Checks for string methods that receive a single-character +/// `str` as an argument, e.g. `_.split("x")`. +/// +/// **Why is this bad?** Performing these methods using a `char` is faster than +/// using a `str`. +/// +/// **Known problems:** Does not catch multi-byte unicode characters. +/// +/// **Example:** +/// `_.split("x")` could be `_.split('x')` +declare_clippy_lint! { + pub SINGLE_CHAR_PATTERN, + perf, + "using a single-character str where a char could be used, e.g. \ + `_.split(\"x\")`" +} + +/// **What it does:** Checks for getting the inner pointer of a temporary +/// `CString`. +/// +/// **Why is this bad?** The inner pointer of a `CString` is only valid as long +/// as the `CString` is alive. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap().as_ptr(); +/// unsafe { +/// call_some_ffi_func(c_str); +/// } +/// ``` +/// Here `c_str` point to a freed address. The correct use would be: +/// ```rust,ignore +/// let c_str = CString::new("foo").unwrap(); +/// unsafe { +/// call_some_ffi_func(c_str.as_ptr()); +/// } +/// ``` +declare_clippy_lint! { + pub TEMPORARY_CSTRING_AS_PTR, + correctness, + "getting the inner pointer of a temporary `CString`" +} + +/// **What it does:** Checks for use of `.iter().nth()` (and the related +/// `.iter_mut().nth()`) on standard library types with O(1) element access. +/// +/// **Why is this bad?** `.get()` and `.get_mut()` are more efficient and more +/// readable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.iter().nth(3); +/// let bad_slice = &some_vec[..].iter().nth(3); +/// ``` +/// The correct use would be: +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.get(3); +/// let bad_slice = &some_vec[..].get(3); +/// ``` +declare_clippy_lint! { + pub ITER_NTH, + perf, + "using `.iter().nth()` on a standard library type with O(1) element access" +} + +/// **What it does:** Checks for use of `.skip(x).next()` on iterators. +/// +/// **Why is this bad?** `.nth(x)` is cleaner +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.iter().skip(3).next(); +/// let bad_slice = &some_vec[..].iter().skip(3).next(); +/// ``` +/// The correct use would be: +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let bad_vec = some_vec.iter().nth(3); +/// let bad_slice = &some_vec[..].iter().nth(3); +/// ``` +declare_clippy_lint! { + pub ITER_SKIP_NEXT, + style, + "using `.skip(x).next()` on an iterator" +} + +/// **What it does:** Checks for use of `.get().unwrap()` (or +/// `.get_mut().unwrap`) on a standard library type which implements `Index` +/// +/// **Why is this bad?** Using the Index trait (`[]`) is more clear and more +/// concise. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let last = some_vec.get(3).unwrap(); +/// *some_vec.get_mut(0).unwrap() = 1; +/// ``` +/// The correct use would be: +/// ```rust +/// let some_vec = vec![0, 1, 2, 3]; +/// let last = some_vec[3]; +/// some_vec[0] = 1; +/// ``` +declare_clippy_lint! { + pub GET_UNWRAP, + style, + "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead" +} + +/// **What it does:** Checks for the use of `.extend(s.chars())` where s is a +/// `&str` or `String`. +/// +/// **Why is this bad?** `.push_str(s)` is clearer +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let abc = "abc"; +/// let def = String::from("def"); +/// let mut s = String::new(); +/// s.extend(abc.chars()); +/// s.extend(def.chars()); +/// ``` +/// The correct use would be: +/// ```rust +/// let abc = "abc"; +/// let def = String::from("def"); +/// let mut s = String::new(); +/// s.push_str(abc); +/// s.push_str(&def)); +/// ``` +declare_clippy_lint! { + pub STRING_EXTEND_CHARS, + style, + "using `x.extend(s.chars())` where s is a `&str` or `String`" +} + +/// **What it does:** Checks for the use of `.cloned().collect()` on slice to +/// create a `Vec`. +/// +/// **Why is this bad?** `.to_vec()` is clearer +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let s = [1,2,3,4,5]; +/// let s2 : Vec = s[..].iter().cloned().collect(); +/// ``` +/// The better use would be: +/// ```rust +/// let s = [1,2,3,4,5]; +/// let s2 : Vec = s.to_vec(); +/// ``` +declare_clippy_lint! { + pub ITER_CLONED_COLLECT, + style, + "using `.cloned().collect()` on slice to create a `Vec`" +} + +/// **What it does:** Checks for usage of `.chars().last()` or +/// `.chars().next_back()` on a `str` to check if it ends with a given char. +/// +/// **Why is this bad?** Readability, this can be written more concisely as +/// `_.ends_with(_)`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-') +/// ``` +declare_clippy_lint! { + pub CHARS_LAST_CMP, + style, + "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char" +} + +/// **What it does:** Checks for usage of `.as_ref()` or `.as_mut()` where the +/// types before and after the call are the same. +/// +/// **Why is this bad?** The call is unnecessary. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x: &[i32] = &[1,2,3,4,5]; +/// do_stuff(x.as_ref()); +/// ``` +/// The correct use would be: +/// ```rust +/// let x: &[i32] = &[1,2,3,4,5]; +/// do_stuff(x); +/// ``` +declare_clippy_lint! { + pub USELESS_ASREF, + complexity, + "using `as_ref` where the types before and after the call are the same" +} + + +/// **What it does:** Checks for using `fold` when a more succinct alternative exists. +/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, +/// `sum` or `product`. +/// +/// **Why is this bad?** Readability. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let _ = (0..3).fold(false, |acc, x| acc || x > 2); +/// ``` +/// This could be written as: +/// ```rust +/// let _ = (0..3).any(|x| x > 2); +/// ``` +declare_clippy_lint! { + pub UNNECESSARY_FOLD, + style, + "using `fold` when a more succinct alternative exists" +} + + +/// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`. +/// +/// **Why is this bad?** Complexity +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None }); +/// ``` +/// This could be written as: +/// ```rust +/// let _ = (0..3).filter(|&x| x > 2); +/// ``` +declare_clippy_lint! { + pub UNNECESSARY_FILTER_MAP, + complexity, + "using `filter_map` when a more succinct alternative exists" +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!( + OPTION_UNWRAP_USED, + RESULT_UNWRAP_USED, + SHOULD_IMPLEMENT_TRAIT, + WRONG_SELF_CONVENTION, + WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, + OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE, + RESULT_MAP_UNWRAP_OR_ELSE, + OPTION_MAP_OR_NONE, + OR_FUN_CALL, + EXPECT_FUN_CALL, + CHARS_NEXT_CMP, + CHARS_LAST_CMP, + CLONE_ON_COPY, + CLONE_ON_REF_PTR, + CLONE_DOUBLE_REF, + NEW_RET_NO_SELF, + SINGLE_CHAR_PATTERN, + SEARCH_IS_SOME, + TEMPORARY_CSTRING_AS_PTR, + FILTER_NEXT, + FILTER_MAP, + MAP_FLATTEN, + ITER_NTH, + ITER_SKIP_NEXT, + GET_UNWRAP, + STRING_EXTEND_CHARS, + ITER_CLONED_COLLECT, + USELESS_ASREF, + UNNECESSARY_FOLD, + UNNECESSARY_FILTER_MAP + ) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + #[allow(clippy::cyclomatic_complexity)] + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + if in_macro(expr.span) { + return; + } + + match expr.node { + hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { + // Chain calls + // GET_UNWRAP needs to be checked before general `UNWRAP` lints + if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) { + lint_get_unwrap(cx, expr, arglists[0], false); + } else if let Some(arglists) = method_chain_args(expr, &["get_mut", "unwrap"]) { + lint_get_unwrap(cx, expr, arglists[0], true); + } else if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + lint_unwrap(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { + lint_ok_expect(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { + lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { + lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map_or"]) { + lint_map_or_none(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { + lint_filter_next(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { + lint_filter_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "map"]) { + lint_filter_map_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter", "flat_map"]) { + lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { + lint_filter_map_flat_map(cx, expr, arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["map", "flatten"]) { + lint_map_flatten(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { + lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { + lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { + lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); + } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { + lint_extend(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { + lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); + } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { + lint_iter_nth(cx, expr, arglists[0], false); + } else if let Some(arglists) = method_chain_args(expr, &["iter_mut", "nth"]) { + lint_iter_nth(cx, expr, arglists[0], true); + } else if method_chain_args(expr, &["skip", "next"]).is_some() { + lint_iter_skip_next(cx, expr); + } else if let Some(arglists) = method_chain_args(expr, &["cloned", "collect"]) { + lint_iter_cloned_collect(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["as_ref"]) { + lint_asref(cx, expr, "as_ref", arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { + lint_asref(cx, expr, "as_mut", arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { + lint_unnecessary_fold(cx, expr, arglists[0]); + } else if let Some(arglists) = method_chain_args(expr, &["filter_map"]) { + unnecessary_filter_map::lint(cx, expr, arglists[0]); + } + + lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); + lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); + + let self_ty = cx.tables.expr_ty_adjusted(&args[0]); + if args.len() == 1 && method_call.ident.name == "clone" { + lint_clone_on_copy(cx, expr, &args[0], self_ty); + lint_clone_on_ref_ptr(cx, expr, &args[0]); + } + + match self_ty.sty { + ty::Ref(_, ty, _) if ty.sty == ty::Str => for &(method, pos) in &PATTERN_METHODS { + if method_call.ident.name == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); + } + }, + _ => (), + } + }, + hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { + let mut info = BinaryExprInfo { + expr, + chain: lhs, + other: rhs, + eq: op.node == hir::BinOpKind::Eq, + }; + lint_binary_expr_with_method_call(cx, &mut info); + }, + _ => (), + } + } + + fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) { + if in_external_macro(cx.sess(), implitem.span) { + return; + } + let name = implitem.ident.name; + let parent = cx.tcx.hir.get_parent(implitem.id); + let item = cx.tcx.hir.expect_item(parent); + if_chain! { + if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; + if let Some(first_arg_ty) = sig.decl.inputs.get(0); + if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); + if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node; + then { + if cx.access_levels.is_exported(implitem.id) { + // check missing trait implementations + for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + if name == method_name && + sig.decl.inputs.len() == n_args && + out_type.matches(cx, &sig.decl.output) && + self_kind.matches(cx, first_arg_ty, first_arg, self_ty, false, &implitem.generics) { + span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( + "defining a method called `{}` on this type; consider implementing \ + the `{}` trait or choosing a less ambiguous name", name, trait_name)); + } + } + } + + // check conventions w.r.t. conversion method names and predicates + let def_id = cx.tcx.hir.local_def_id(item.id); + let ty = cx.tcx.type_of(def_id); + let is_copy = is_copy(cx, ty); + for &(ref conv, self_kinds) in &CONVENTIONS { + if_chain! { + if conv.check(&name.as_str()); + if !self_kinds + .iter() + .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); + then { + let lint = if item.vis.node.is_pub() { + WRONG_PUB_SELF_CONVENTION + } else { + WRONG_SELF_CONVENTION + }; + span_lint(cx, + lint, + first_arg.pat.span, + &format!("methods called `{}` usually take {}; consider choosing a less \ + ambiguous name", + conv, + &self_kinds.iter() + .map(|k| k.description()) + .collect::>() + .join(" or "))); + } + } + } + + let ret_ty = return_ty(cx, implitem.id); + if name == "new" && + !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { + span_lint(cx, + NEW_RET_NO_SELF, + implitem.span, + "methods called `new` usually return `Self`"); + } + } + } + } +} + +/// Checks for the `OR_FUN_CALL` lint. +fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { + /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. + fn check_unwrap_or_default( + cx: &LateContext<'_, '_>, + name: &str, + fun: &hir::Expr, + self_expr: &hir::Expr, + arg: &hir::Expr, + or_has_args: bool, + span: Span, + ) -> bool { + if or_has_args { + return false; + } + + if name == "unwrap_or" { + if let hir::ExprKind::Path(ref qpath) = fun.node { + let path = &*last_path_segment(qpath).ident.as_str(); + + if ["default", "new"].contains(&path) { + let arg_ty = cx.tables.expr_ty(arg); + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { + default_trait_id + } else { + return false; + }; + + if implements_trait(cx, arg_ty, default_trait_id, &[]) { + span_lint_and_sugg( + cx, + OR_FUN_CALL, + span, + &format!("use of `{}` followed by a call to `{}`", name, path), + "try this", + format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")), + ); + return true; + } + } + } + } + + false + } + + /// Check for `*or(foo())`. + #[allow(clippy::too_many_arguments)] + fn check_general_case( + cx: &LateContext<'_, '_>, + name: &str, + method_span: Span, + fun_span: Span, + self_expr: &hir::Expr, + arg: &hir::Expr, + or_has_args: bool, + span: Span, + ) { + // (path, fn_has_argument, methods, suffix) + let know_types: &[(&[_], _, &[_], _)] = &[ + (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), + (&paths::RESULT, true, &["or", "unwrap_or"], "else"), + ]; + + // early check if the name is one we care about + if know_types.iter().all(|k| !k.2.contains(&name)) { + return; + } + + // don't lint for constant values + let owner_def = cx.tcx.hir.get_parent_did(arg.id); + let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); + if promotable { + return; + } + + let self_ty = cx.tables.expr_ty(self_expr); + + let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) = + know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) + { + (fn_has_arguments, poss, suffix) + } else { + return; + }; + + if !poss.contains(&name) { + return; + } + + let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) { + (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), + (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), + (false, true) => snippet(cx, fun_span, ".."), + }; + let span_replace_word = method_span.with_hi(span.hi()); + span_lint_and_sugg( + cx, + OR_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("{}_{}({})", name, suffix, sugg), + ); + } + + if args.len() == 2 { + match args[1].node { + hir::ExprKind::Call(ref fun, ref or_args) => { + let or_has_args = !or_args.is_empty(); + if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { + check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span); + } + }, + hir::ExprKind::MethodCall(_, span, ref or_args) => { + check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span) + }, + _ => {}, + } + } +} + +/// Checks for the `EXPECT_FUN_CALL` lint. +fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { + fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { + if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node { + if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node { + if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { + if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { + return Some(format_args); + } + } + } + } + + None + } + + fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String { + if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { + if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { + if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { + return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); + } + } + }; + + snippet(cx, a.span, "..").into_owned() + } + + fn check_general_case( + cx: &LateContext<'_, '_>, + name: &str, + method_span: Span, + self_expr: &hir::Expr, + arg: &hir::Expr, + span: Span, + ) { + if name != "expect" { + return; + } + + let self_type = cx.tables.expr_ty(self_expr); + let known_types = &[&paths::OPTION, &paths::RESULT]; + + // if not a known type, return early + if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { + return; + } + + fn is_call(node: &hir::ExprKind) -> bool { + match node { + hir::ExprKind::AddrOf(_, expr) => { + is_call(&expr.node) + }, + hir::ExprKind::Call(..) + | hir::ExprKind::MethodCall(..) + // These variants are debatable or require further examination + | hir::ExprKind::If(..) + | hir::ExprKind::Match(..) => true, + _ => false, + } + } + + if !is_call(&arg.node) { + return; + } + + let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; + let span_replace_word = method_span.with_hi(span.hi()); + + if let Some(format_args) = extract_format_args(arg) { + let args_len = format_args.len(); + let args: Vec = format_args + .into_iter() + .take(args_len - 1) + .map(|a| generate_format_arg_snippet(cx, a)) + .collect(); + + let sugg = args.join(", "); + + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} panic!({}))", closure, sugg), + ); + + return; + } + + let sugg: Cow<'_, _> = snippet(cx, arg.span, ".."); + + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} panic!({}))", closure, sugg), + ); + } + + if args.len() == 2 { + match args[1].node { + hir::ExprKind::Lit(_) => {}, + _ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span), + } + } +} + +/// Checks for the `CLONE_ON_COPY` lint. +fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty<'_>) { + let ty = cx.tables.expr_ty(expr); + if let ty::Ref(_, inner, _) = arg_ty.sty { + if let ty::Ref(_, innermost, _) = inner.sty { + span_lint_and_then( + cx, + CLONE_DOUBLE_REF, + expr.span, + "using `clone` on a double-reference; \ + this will copy the reference instead of cloning the inner type", + |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { + let mut ty = innermost; + let mut n = 0; + while let ty::Ref(_, inner, _) = ty.sty { + ty = inner; + n += 1; + } + let refs: String = iter::repeat('&').take(n + 1).collect(); + let derefs: String = iter::repeat('*').take(n).collect(); + let explicit = format!("{}{}::clone({})", refs, ty, snip); + db.span_suggestion_with_applicability( + expr.span, + "try dereferencing it", + format!("{}({}{}).clone()", refs, derefs, snip.deref()), + Applicability::MaybeIncorrect, + ); + db.span_suggestion_with_applicability( + expr.span, + "or try being explicit about what type to clone", + explicit, + Applicability::MaybeIncorrect, + ); + }, + ); + return; // don't report clone_on_copy + } + } + + if is_copy(cx, ty) { + let snip; + if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { + if let ty::Ref(..) = cx.tables.expr_ty(arg).sty { + let parent = cx.tcx.hir.get_parent_node(expr.id); + match cx.tcx.hir.get(parent) { + hir::Node::Expr(parent) => match parent.node { + // &*x is a nop, &x.clone() is not + hir::ExprKind::AddrOf(..) | + // (*x).func() is useless, x.clone().func() can work in case func borrows mutably + hir::ExprKind::MethodCall(..) => return, + _ => {}, + } + hir::Node::Stmt(stmt) => { + if let hir::StmtKind::Decl(ref decl, _) = stmt.node { + if let hir::DeclKind::Local(ref loc) = decl.node { + if let hir::PatKind::Ref(..) = loc.pat.node { + // let ref y = *x borrows x, let ref y = x.clone() does not + return; + } + } + } + }, + _ => {}, + } + snip = Some(("try dereferencing it", format!("{}", snippet.deref()))); + } else { + snip = Some(("try removing the `clone` call", format!("{}", snippet))); + } + } else { + snip = None; + } + span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { + if let Some((text, snip)) = snip { + db.span_suggestion_with_applicability( + expr.span, + text, + snip, + Applicability::Unspecified, + ); + } + }); + } +} + +fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr) { + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); + + if let ty::Adt(_, subst) = obj_ty.sty { + let caller_type = if match_type(cx, obj_ty, &paths::RC) { + "Rc" + } else if match_type(cx, obj_ty, &paths::ARC) { + "Arc" + } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { + "Weak" + } else { + return; + }; + + span_lint_and_sugg( + cx, + CLONE_ON_REF_PTR, + expr.span, + "using '.clone()' on a ref-counted pointer", + "try this", + format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), + ); + } +} + + +fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { + let arg = &args[1]; + if let Some(arglists) = method_chain_args(arg, &["chars"]) { + let target = &arglists[0][0]; + let self_ty = walk_ptrs_ty(cx.tables.expr_ty(target)); + let ref_str = if self_ty.sty == ty::Str { + "" + } else if match_type(cx, self_ty, &paths::STRING) { + "&" + } else { + return; + }; + + span_lint_and_sugg( + cx, + STRING_EXTEND_CHARS, + expr.span, + "calling `.extend(_.chars())`", + "try this", + format!( + "{}.push_str({}{})", + snippet(cx, args[0].span, "_"), + ref_str, + snippet(cx, target.span, "_") + ), + ); + } +} + +fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); + if match_type(cx, obj_ty, &paths::STRING) { + lint_string_extend(cx, expr, args); + } +} + +fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) { + if_chain! { + if let hir::ExprKind::Call(ref fun, ref args) = new.node; + if args.len() == 1; + if let hir::ExprKind::Path(ref path) = fun.node; + if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); + if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); + then { + span_lint_and_then( + cx, + TEMPORARY_CSTRING_AS_PTR, + expr.span, + "you are getting the inner pointer of a temporary `CString`", + |db| { + db.note("that pointer will be invalid outside this expression"); + db.span_help(unwrap.span, "assign the `CString` to a variable to extend its lifetime"); + }); + } + } +} + +fn lint_iter_cloned_collect(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr]) { + if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) + && derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() + { + span_lint( + cx, + ITER_CLONED_COLLECT, + expr.span, + "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ + more readable", + ); + } +} + +fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: &[hir::Expr]) { + // Check that this is a call to Iterator::fold rather than just some function called fold + if !match_trait_method(cx, expr, &paths::ITERATOR) { + return; + } + + assert!(fold_args.len() == 3, + "Expected fold_args to have three entries - the receiver, the initial value and the closure"); + + fn check_fold_with_op( + cx: &LateContext<'_, '_>, + fold_args: &[hir::Expr], + op: hir::BinOpKind, + replacement_method_name: &str, + replacement_has_args: bool) { + + if_chain! { + // Extract the body of the closure passed to fold + if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node; + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); + + // Check if the closure body is of the form `acc some_expr(x)` + if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node; + if bin_op.node == op; + + // Extract the names of the two arguments to the closure + if let Some(first_arg_ident) = get_arg_name(&closure_body.arguments[0].pat); + if let Some(second_arg_ident) = get_arg_name(&closure_body.arguments[1].pat); + + if match_var(&*left_expr, first_arg_ident); + if replacement_has_args || match_var(&*right_expr, second_arg_ident); + + then { + // Span containing `.fold(...)` + let next_point = cx.sess().source_map().next_point(fold_args[0].span); + let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1)); + + let sugg = if replacement_has_args { + format!( + ".{replacement}(|{s}| {r})", + replacement = replacement_method_name, + s = second_arg_ident, + r = snippet(cx, right_expr.span, "EXPR"), + ) + } else { + format!( + ".{replacement}()", + replacement = replacement_method_name, + ) + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_FOLD, + fold_span, + // TODO #2371 don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) + "this `.fold` can be written more succinctly using another method", + "try", + sugg, + ); + } + } + } + + // Check if the first argument to .fold is a suitable literal + match fold_args[1].node { + hir::ExprKind::Lit(ref lit) => { + match lit.node { + ast::LitKind::Bool(false) => check_fold_with_op( + cx, fold_args, hir::BinOpKind::Or, "any", true + ), + ast::LitKind::Bool(true) => check_fold_with_op( + cx, fold_args, hir::BinOpKind::And, "all", true + ), + ast::LitKind::Int(0, _) => check_fold_with_op( + cx, fold_args, hir::BinOpKind::Add, "sum", false + ), + ast::LitKind::Int(1, _) => check_fold_with_op( + cx, fold_args, hir::BinOpKind::Mul, "product", false + ), + _ => return + } + } + _ => return + }; +} + +fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) { + let mut_str = if is_mut { "_mut" } else { "" }; + let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { + "slice" + } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC) { + "Vec" + } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { + "VecDeque" + } else { + return; // caller is not a type that we want to lint + }; + + span_lint( + cx, + ITER_NTH, + expr.span, + &format!( + "called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", + mut_str, + caller_type + ), + ); +} + +fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { + // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap, + // because they do not implement `IndexMut` + let expr_ty = cx.tables.expr_ty(&get_args[0]); + let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { + "slice" + } else if match_type(cx, expr_ty, &paths::VEC) { + "Vec" + } else if match_type(cx, expr_ty, &paths::VEC_DEQUE) { + "VecDeque" + } else if !is_mut && match_type(cx, expr_ty, &paths::HASHMAP) { + "HashMap" + } else if !is_mut && match_type(cx, expr_ty, &paths::BTREEMAP) { + "BTreeMap" + } else { + return; // caller is not a type that we want to lint + }; + + let mut_str = if is_mut { "_mut" } else { "" }; + let borrow_str = if is_mut { "&mut " } else { "&" }; + span_lint_and_sugg( + cx, + GET_UNWRAP, + expr.span, + &format!( + "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", + mut_str, + caller_type + ), + "try this", + format!( + "{}{}[{}]", + borrow_str, + snippet(cx, get_args[0].span, "_"), + snippet(cx, get_args[1].span, "_") + ), + ); +} + +fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) { + // lint if caller of skip is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + span_lint( + cx, + ITER_SKIP_NEXT, + expr.span, + "called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`", + ); + } +} + +fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Option> { + fn may_slice(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { + match ty.sty { + ty::Slice(_) => true, + ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) => match_type(cx, ty, &paths::VEC), + ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, + ty::Ref(_, inner, _) => may_slice(cx, inner), + _ => false, + } + } + + if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.node { + if path.ident.name == "iter" && may_slice(cx, cx.tables.expr_ty(&args[0])) { + sugg::Sugg::hir_opt(cx, &args[0]).map(|sugg| sugg.addr()) + } else { + None + } + } else { + match ty.sty { + ty::Slice(_) => sugg::Sugg::hir_opt(cx, expr), + ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), + ty::Ref(_, inner, _) => if may_slice(cx, inner) { + sugg::Sugg::hir_opt(cx, expr) + } else { + None + }, + _ => None, + } + } +} + +/// lint use of `unwrap()` for `Option`s and `Result`s +fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { + let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); + + let mess = if match_type(cx, obj_ty, &paths::OPTION) { + Some((OPTION_UNWRAP_USED, "an Option", "None")) + } else if match_type(cx, obj_ty, &paths::RESULT) { + Some((RESULT_UNWRAP_USED, "a Result", "Err")) + } else { + None + }; + + if let Some((lint, kind, none_value)) = mess { + span_lint( + cx, + lint, + expr.span, + &format!( + "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ + using expect() to provide a better panic \ + message", + kind, + none_value + ), + ); + } +} + +/// lint use of `ok().expect()` for `Result`s +fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) { + // lint if the caller of `ok()` is a `Result` + if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT) { + let result_type = cx.tables.expr_ty(&ok_args[0]); + if let Some(error_type) = get_error_type(cx, result_type) { + if has_debug_impl(error_type, cx) { + span_lint( + cx, + OK_EXPECT, + expr.span, + "called `ok().expect()` on a Result value. You can call `expect` directly on the `Result`", + ); + } + } + } +} + +/// lint use of `map().unwrap_or()` for `Option`s +fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) { + // lint if the caller of `map()` is an `Option` + if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { + // get snippets for args to map() and unwrap_or() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint message + // comparing the snippet from source to raw text ("None") below is safe + // because we already have checked the type. + let arg = if unwrap_snippet == "None" { + "None" + } else { + "a" + }; + let suggest = if unwrap_snippet == "None" { + "and_then(f)" + } else { + "map_or(a, f)" + }; + let msg = &format!( + "called `map(f).unwrap_or({})` on an Option value. \ + This can be done more directly by calling `{}` instead", + arg, + suggest + ); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or() have the same span + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); + if same_span && !multiline { + let suggest = if unwrap_snippet == "None" { + format!("and_then({})", map_snippet) + } else { + format!("map_or({}, {})", unwrap_snippet, map_snippet) + }; + let note = format!( + "replace `map({}).unwrap_or({})` with `{}`", + map_snippet, + unwrap_snippet, + suggest + ); + span_note_and_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, ¬e); + } else if same_span && multiline { + span_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg); + }; + } +} + +/// lint use of `map().flatten()` for `Iterators` +fn lint_map_flatten<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.map().flatten()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `map(..).flatten()` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)`"; + let self_snippet = snippet(cx, map_args[0].span, ".."); + let func_snippet = snippet(cx, map_args[1].span, ".."); + let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); + span_lint_and_then(cx, MAP_FLATTEN, expr.span, msg, |db| { + db.span_suggestion_with_applicability( + expr.span, + "try using flat_map instead", + hint, + Applicability::MachineApplicable, + ); + }); + } +} + +/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s +fn lint_map_unwrap_or_else<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + map_args: &'tcx [hir::Expr], + unwrap_args: &'tcx [hir::Expr], +) { + // lint if the caller of `map()` is an `Option` + let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION); + let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT); + if is_option || is_result { + // lint message + let msg = if is_option { + "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ + `map_or_else(g, f)` instead" + } else { + "called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling \ + `ok().map_or_else(g, f)` instead" + }; + // get snippets for args to map() and unwrap_or_else() + let map_snippet = snippet(cx, map_args[1].span, ".."); + let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + // lint, with note if neither arg is > 1 line and both map() and + // unwrap_or_else() have the same span + let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; + let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); + if same_span && !multiline { + span_note_and_lint( + cx, + if is_option { + OPTION_MAP_UNWRAP_OR_ELSE + } else { + RESULT_MAP_UNWRAP_OR_ELSE + }, + expr.span, + msg, + expr.span, + &format!( + "replace `map({0}).unwrap_or_else({1})` with `{2}map_or_else({1}, {0})`", + map_snippet, + unwrap_snippet, + if is_result { "ok()." } else { "" } + ), + ); + } else if same_span && multiline { + span_lint( + cx, + if is_option { + OPTION_MAP_UNWRAP_OR_ELSE + } else { + RESULT_MAP_UNWRAP_OR_ELSE + }, + expr.span, + msg, + ); + }; + } +} + +/// lint use of `_.map_or(None, _)` for `Option`s +fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) { + if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { + // check if the first non-self argument to map_or() is None + let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].node { + match_qpath(qpath, &paths::OPTION_NONE) + } else { + false + }; + + if map_or_arg_is_none { + // lint message + let msg = "called `map_or(None, f)` on an Option value. This can be done more directly by calling \ + `and_then(f)` instead"; + let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); + let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); + let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); + span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { + db.span_suggestion_with_applicability( + expr.span, + "try using and_then instead", + hint, + Applicability::MachineApplicable, // snippet + ); + }); + } + } +} + +/// lint use of `filter().next()` for `Iterators` +fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) { + // lint if caller of `.filter().next()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \ + `.find(p)` instead."; + let filter_snippet = snippet(cx, filter_args[1].span, ".."); + if filter_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint( + cx, + FILTER_NEXT, + expr.span, + msg, + expr.span, + &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet), + ); + } else { + span_lint(cx, FILTER_NEXT, expr.span, msg); + } + } +} + +/// lint use of `filter().map()` for `Iterators` +fn lint_filter_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.filter().map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.filter_map(..)` instead."; + span_lint(cx, FILTER_MAP, expr.span, msg); + } +} + +/// lint use of `filter().map()` for `Iterators` +fn lint_filter_map_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.filter().map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter_map(p).map(q)` on an `Iterator`. \ + This is more succinctly expressed by only calling `.filter_map(..)` instead."; + span_lint(cx, FILTER_MAP, expr.span, msg); + } +} + +/// lint use of `filter().flat_map()` for `Iterators` +fn lint_filter_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.filter().flat_map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)` \ + and filtering by returning an empty Iterator."; + span_lint(cx, FILTER_MAP, expr.span, msg); + } +} + +/// lint use of `filter_map().flat_map()` for `Iterators` +fn lint_filter_map_flat_map<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + _filter_args: &'tcx [hir::Expr], + _map_args: &'tcx [hir::Expr], +) { + // lint if caller of `.filter_map().flat_map()` is an Iterator + if match_trait_method(cx, expr, &paths::ITERATOR) { + let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \ + This is more succinctly expressed by calling `.flat_map(..)` \ + and filtering by returning an empty Iterator."; + span_lint(cx, FILTER_MAP, expr.span, msg); + } +} + +/// lint searching an Iterator followed by `is_some()` +fn lint_search_is_some<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr, + search_method: &str, + search_args: &'tcx [hir::Expr], + is_some_args: &'tcx [hir::Expr], +) { + // lint if caller of search is an Iterator + if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { + let msg = format!( + "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ + expressed by calling `any()`.", + search_method + ); + let search_snippet = snippet(cx, search_args[1].span, ".."); + if search_snippet.lines().count() <= 1 { + // add note if not multi-line + span_note_and_lint( + cx, + SEARCH_IS_SOME, + expr.span, + &msg, + expr.span, + &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet), + ); + } else { + span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); + } + } +} + +/// Used for `lint_binary_expr_with_method_call`. +#[derive(Copy, Clone)] +struct BinaryExprInfo<'a> { + expr: &'a hir::Expr, + chain: &'a hir::Expr, + other: &'a hir::Expr, + eq: bool, +} + +/// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. +fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut BinaryExprInfo<'_>) { + macro_rules! lint_with_both_lhs_and_rhs { + ($func:ident, $cx:expr, $info:ident) => { + if !$func($cx, $info) { + ::std::mem::swap(&mut $info.chain, &mut $info.other); + if $func($cx, $info) { + return; + } + } + } + } + + lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); + lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); +} + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints. +fn lint_chars_cmp( + cx: &LateContext<'_, '_>, + info: &BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.node; + if arg_char.len() == 1; + if let hir::ExprKind::Path(ref qpath) = fun.node; + if let Some(segment) = single_segment_path(qpath); + if segment.ident.name == "Some"; + then { + let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); + + if self_ty.sty != ty::Str { + return false; + } + + span_lint_and_sugg(cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + snippet(cx, arg_char[0].span, "_"))); + + return true; + } + } + + false +} + +/// Checks for the `CHARS_NEXT_CMP` lint. +fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { + lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") +} + +/// Checks for the `CHARS_LAST_CMP` lint. +fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { + if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") { + true + } else { + lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_NEXT_CMP, "ends_with") + } +} + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. +fn lint_chars_cmp_with_unwrap<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + info: &BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Lit(ref lit) = info.other.node; + if let ast::LitKind::Char(c) = lit.node; + then { + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}('{}')", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + c) + ); + + return true; + } + } + + false +} + +/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. +fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { + lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") +} + +/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. +fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { + if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { + true + } else { + lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") + } +} + +/// lint for length-1 `str`s for methods in `PATTERN_METHODS` +fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { + if_chain! { + if let hir::ExprKind::Lit(lit) = &arg.node; + if let ast::LitKind::Str(r, _) = lit.node; + if r.as_str().len() == 1; + then { + let snip = snippet(cx, arg.span, ".."); + let hint = format!("'{}'", &snip[1..snip.len() - 1]); + span_lint_and_sugg( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + "try using a char instead", + hint, + ); + } + } +} + +/// Checks for the `USELESS_ASREF` lint. +fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) { + // when we get here, we've already checked that the call name is "as_ref" or "as_mut" + // check if the call is to the actual `AsRef` or `AsMut` trait + if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { + // check if the type after `as_ref` or `as_mut` is the same as before + let recvr = &as_ref_args[0]; + let rcv_ty = cx.tables.expr_ty(recvr); + let res_ty = cx.tables.expr_ty(expr); + let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); + let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); + if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { + span_lint_and_sugg( + cx, + USELESS_ASREF, + expr.span, + &format!("this call to `{}` does nothing", call_name), + "try this", + snippet(cx, recvr.span, "_").into_owned(), + ); + } + } +} + +/// Given a `Result` type, return its error type (`E`). +fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { + if let ty::Adt(_, substs) = ty.sty { + if match_type(cx, ty, &paths::RESULT) { + substs.types().nth(1) + } else { + None + } + } else { + None + } +} + +/// This checks whether a given type is known to implement Debug. +fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { + match cx.tcx.lang_items().debug_trait() { + Some(debug) => implements_trait(cx, ty, debug, &[]), + None => false, + } +} + +enum Convention { + Eq(&'static str), + StartsWith(&'static str), +} + +#[rustfmt::skip] +const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ + (Convention::Eq("new"), &[SelfKind::No]), + (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), + (Convention::StartsWith("from_"), &[SelfKind::No]), + (Convention::StartsWith("into_"), &[SelfKind::Value]), + (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), + (Convention::StartsWith("to_"), &[SelfKind::Ref]), +]; + +#[rustfmt::skip] +const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ + ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), + ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), + ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), + ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), + ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), + ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), + ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), + ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), + ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), + ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), + ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), + ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), + ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), + ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), + ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), + ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), + ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), + ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), + ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), + ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), + ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), + ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), + ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), + ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), + ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), + ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), + ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), + ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), +]; + +#[rustfmt::skip] +const PATTERN_METHODS: [(&str, usize); 17] = [ + ("contains", 1), + ("starts_with", 1), + ("ends_with", 1), + ("find", 1), + ("rfind", 1), + ("split", 1), + ("rsplit", 1), + ("split_terminator", 1), + ("rsplit_terminator", 1), + ("splitn", 2), + ("rsplitn", 2), + ("matches", 1), + ("rmatches", 1), + ("match_indices", 1), + ("rmatch_indices", 1), + ("trim_left_matches", 1), + ("trim_right_matches", 1), +]; + + +#[derive(Clone, Copy, PartialEq, Debug)] +enum SelfKind { + Value, + Ref, + RefMut, + No, +} + +impl SelfKind { + fn matches( + self, + cx: &LateContext<'_, '_>, + ty: &hir::Ty, + arg: &hir::Arg, + self_ty: &hir::Ty, + allow_value_for_ref: bool, + generics: &hir::Generics, + ) -> bool { + // Self types in the HIR are desugared to explicit self types. So it will + // always be `self: + // SomeType`, + // where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if + // the impl is on `Foo`) + // Thus, we only need to test equality against the impl self type or if it is + // an explicit + // `Self`. Furthermore, the only possible types for `self: ` are `&Self`, + // `Self`, `&mut Self`, + // and `Box`, including the equivalent types with `Foo`. + + let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty); + if is_self(arg) { + match self { + SelfKind::Value => is_actually_self(ty), + SelfKind::Ref | SelfKind::RefMut => { + if allow_value_for_ref && is_actually_self(ty) { + return true; + } + match ty.node { + hir::TyKind::Rptr(_, ref mt_ty) => { + let mutability_match = if self == SelfKind::Ref { + mt_ty.mutbl == hir::MutImmutable + } else { + mt_ty.mutbl == hir::MutMutable + }; + is_actually_self(&mt_ty.ty) && mutability_match + }, + _ => false, + } + }, + _ => false, + } + } else { + match self { + SelfKind::Value => false, + SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT), + SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT), + SelfKind::No => true, + } + } + } + + fn description(self) -> &'static str { + match self { + SelfKind::Value => "self by value", + SelfKind::Ref => "self by reference", + SelfKind::RefMut => "self by mutable reference", + SelfKind::No => "no self", + } + } +} + +fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { + single_segment_ty(ty).map_or(false, |seg| { + generics.params.iter().any(|param| match param.kind { + hir::GenericParamKind::Type { .. } => { + param.name.ident().name == seg.ident.name && param.bounds.iter().any(|bound| { + if let hir::GenericBound::Trait(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path(path, name) && path.segments.last().map_or(false, |s| { + if let Some(ref params) = s.args { + if params.parenthesized { + false + } else { + // FIXME(flip1995): messy, improve if there is a better option + // in the compiler + let types: Vec<_> = params.args.iter().filter_map(|arg| match arg { + hir::GenericArg::Type(ty) => Some(ty), + _ => None, + }).collect(); + types.len() == 1 + && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty)) + } + } else { + false + } + }) + } else { + false + } + }) + }, + _ => false, + }) + }) +} + +fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { + match (&ty.node, &self_ty.node) { + ( + &hir::TyKind::Path(hir::QPath::Resolved(_, ref ty_path)), + &hir::TyKind::Path(hir::QPath::Resolved(_, ref self_ty_path)), + ) => ty_path + .segments + .iter() + .map(|seg| seg.ident.name) + .eq(self_ty_path.segments.iter().map(|seg| seg.ident.name)), + _ => false, + } +} + +fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> { + if let hir::TyKind::Path(ref path) = ty.node { + single_segment_path(path) + } else { + None + } +} + +impl Convention { + fn check(&self, other: &str) -> bool { + match *self { + Convention::Eq(this) => this == other, + Convention::StartsWith(this) => other.starts_with(this) && this != other, + } + } +} + +impl fmt::Display for Convention { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match *self { + Convention::Eq(this) => this.fmt(f), + Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), + } + } +} + +#[derive(Clone, Copy)] +enum OutType { + Unit, + Bool, + Any, + Ref, +} + +impl OutType { + fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy) -> bool { + let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into())); + match (self, ty) { + (OutType::Unit, &hir::DefaultReturn(_)) => true, + (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, + (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, + (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, + (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)), + _ => false, + } + } +} + +fn is_bool(ty: &hir::Ty) -> bool { + if let hir::TyKind::Path(ref p) = ty.node { + match_qpath(p, &["bool"]) + } else { + false + } +} diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs new file mode 100644 index 00000000000..691c08ef0cc --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -0,0 +1,146 @@ +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::lint::LateContext; +use crate::rustc::hir; +use crate::rustc::hir::def::Def; +use crate::syntax::ast; +use crate::utils::{match_qpath, match_trait_method, span_lint}; +use crate::utils::paths; +use crate::utils::usage::mutated_variables; + +use if_chain::if_chain; + +use super::UNNECESSARY_FILTER_MAP; + +pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { + + if !match_trait_method(cx, expr, &paths::ITERATOR) { + return; + } + + if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].node { + + let body = cx.tcx.hir.body(body_id); + let arg_id = body.arguments[0].pat.id; + let mutates_arg = match mutated_variables(&body.value, cx) { + Some(used_mutably) => used_mutably.contains(&arg_id), + None => true, + }; + + let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value); + + let mut return_visitor = ReturnVisitor::new(&cx, arg_id); + return_visitor.visit_expr(&body.value); + found_mapping |= return_visitor.found_mapping; + found_filtering |= return_visitor.found_filtering; + + if !found_filtering { + span_lint( + cx, + UNNECESSARY_FILTER_MAP, + expr.span, + "this `.filter_map` can be written more simply using `.map`", + ); + return; + } + + if !found_mapping && !mutates_arg { + span_lint( + cx, + UNNECESSARY_FILTER_MAP, + expr.span, + "this `.filter_map` can be written more simply using `.filter`", + ); + return; + } + } +} + +// returns (found_mapping, found_filtering) +fn check_expression<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId, expr: &'tcx hir::Expr) -> (bool, bool) { + match &expr.node { + hir::ExprKind::Call(ref func, ref args) => { + if_chain! { + if let hir::ExprKind::Path(ref path) = func.node; + then { + if match_qpath(path, &paths::OPTION_SOME) { + if_chain! { + if let hir::ExprKind::Path(path) = &args[0].node; + if let Def::Local(ref local) = cx.tables.qpath_def(path, args[0].hir_id); + then { + if arg_id == *local { + return (false, false) + } + } + } + return (true, false); + } else { + // We don't know. It might do anything. + return (true, true); + } + } + } + (true, true) + }, + hir::ExprKind::Block(ref block, _) => { + if let Some(expr) = &block.expr { + check_expression(cx, arg_id, &expr) + } else { + (false, false) + } + }, + // There must be an else_arm or there will be a type error + hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => { + let if_check = check_expression(cx, arg_id, if_arm); + let else_check = check_expression(cx, arg_id, else_arm); + (if_check.0 | else_check.0, if_check.1 | else_check.1) + }, + hir::ExprKind::Match(_, ref arms, _) => { + let mut found_mapping = false; + let mut found_filtering = false; + for arm in arms { + let (m, f) = check_expression(cx, arg_id, &arm.body); + found_mapping |= m; + found_filtering |= f; + } + (found_mapping, found_filtering) + }, + hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), + _ => (true, true) + } +} + +struct ReturnVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + arg_id: ast::NodeId, + // Found a non-None return that isn't Some(input) + found_mapping: bool, + // Found a return that isn't Some + found_filtering: bool, +} + +impl<'a, 'tcx: 'a> ReturnVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId) -> ReturnVisitor<'a, 'tcx> { + ReturnVisitor { + cx, + arg_id, + found_mapping: false, + found_filtering: false, + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if let hir::ExprKind::Ret(Some(expr)) = &expr.node { + let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr); + self.found_mapping |= found_mapping; + self.found_filtering |= found_filtering; + } else { + walk_expr(self, expr); + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} -- cgit 1.4.1-3-g733a5 From 06f6b36025bd2b3f322cf1ba39a45fd9702ad260 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 29 Sep 2018 14:18:50 +0200 Subject: rustfmt --- clippy_lints/src/methods/unnecessary_filter_map.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 691c08ef0cc..0a3486df8bd 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,29 +1,27 @@ -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::LateContext; use crate::rustc::hir; use crate::rustc::hir::def::Def; +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::lint::LateContext; use crate::syntax::ast; -use crate::utils::{match_qpath, match_trait_method, span_lint}; use crate::utils::paths; use crate::utils::usage::mutated_variables; +use crate::utils::{match_qpath, match_trait_method, span_lint}; use if_chain::if_chain; use super::UNNECESSARY_FILTER_MAP; pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { - if !match_trait_method(cx, expr, &paths::ITERATOR) { return; } if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].node { - let body = cx.tcx.hir.body(body_id); let arg_id = body.arguments[0].pat.id; let mutates_arg = match mutated_variables(&body.value, cx) { - Some(used_mutably) => used_mutably.contains(&arg_id), - None => true, + Some(used_mutably) => used_mutably.contains(&arg_id), + None => true, }; let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value); @@ -56,7 +54,11 @@ pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr } // returns (found_mapping, found_filtering) -fn check_expression<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::NodeId, expr: &'tcx hir::Expr) -> (bool, bool) { +fn check_expression<'a, 'tcx: 'a>( + cx: &'a LateContext<'a, 'tcx>, + arg_id: ast::NodeId, + expr: &'tcx hir::Expr, +) -> (bool, bool) { match &expr.node { hir::ExprKind::Call(ref func, ref args) => { if_chain! { @@ -105,7 +107,7 @@ fn check_expression<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, arg_id: ast::No (found_mapping, found_filtering) }, hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), - _ => (true, true) + _ => (true, true), } } -- cgit 1.4.1-3-g733a5 From e25f884e6ff2e7031726b59852d57b6a0c433c12 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 29 Sep 2018 07:39:30 -0700 Subject: Fixes #3180, suppress excessive_precision lint for floats with no decimal part --- clippy_lints/src/excessive_precision.rs | 6 ++++-- tests/ui/excessive_precision.rs | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 6df88cdc6c3..0ae228d1dea 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -98,8 +98,9 @@ impl ExcessivePrecision { } } -/// Should we exclude the float because it has a .0 suffix +/// Should we exclude the float because it has a `.0` or `.` suffix /// Ex 1_000_000_000.0 +/// Ex 1_000_000_000. fn dot_zero_exclusion(s: &str) -> bool { if let Some(after_dec) = s.split('.').nth(1) { let mut decpart = after_dec @@ -108,7 +109,8 @@ fn dot_zero_exclusion(s: &str) -> bool { match decpart.next() { Some('0') => decpart.count() == 0, - _ => false, + Some(_) => false, + None => true, } } else { false diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index b44364d6beb..1b3412166d4 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -54,4 +54,7 @@ fn main() { let good_bige32: f32 = 1E-10; let bad_bige32: f32 = 1.123_456_788_888E-10; + + // Inferred type + let good_inferred: f32 = 1f32 * 1_000_000_000.; } -- cgit 1.4.1-3-g733a5 From 34693c0d6dc7c7004aa45f8a8b1ded6ecb36126a Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 29 Sep 2018 19:33:30 +0200 Subject: rustc_tools_util: remove test and tool_lints features, both are actually unused. Fixes build with beta. --- rustc_tools_util/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index bbe86be3c7c..09d80072d66 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -1,6 +1,3 @@ -#![feature(test)] -#![feature(tool_lints)] - use std::env; #[macro_export] -- cgit 1.4.1-3-g733a5 From f01fa227c0b37a5af343c0c8a074ffa6fb42210e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 30 Sep 2018 06:25:23 +0200 Subject: Fix update_lints.py for dir modules --- util/update_lints.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/util/update_lints.py b/util/update_lints.py index 15242abd606..b34dad73f70 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -46,7 +46,12 @@ def collect(deprecated_lints, clippy_lints, fn): # remove \-newline escapes from description string desc = nl_escape_re.sub('', match.group('desc')) cat = match.group('cat') - clippy_lints[cat].append((os.path.splitext(os.path.basename(fn))[0], + if cat in ('internal', 'internal_warn'): + continue + module_name = os.path.splitext(os.path.basename(fn))[0] + if module_name == 'mod': + module_name = os.path.basename(os.path.dirname(fn)) + clippy_lints[cat].append((module_name, match.group('name').lower(), "allow", desc.replace('\\"', '"'))) @@ -138,10 +143,11 @@ def main(print_only=False, check=False): return # collect all lints from source files - for fn in os.listdir('clippy_lints/src'): - if fn.endswith('.rs'): - collect(deprecated_lints, clippy_lints, - os.path.join('clippy_lints', 'src', fn)) + for root, dirs, files in os.walk('clippy_lints/src'): + for fn in files: + if fn.endswith('.rs'): + collect(deprecated_lints, clippy_lints, + os.path.join(root, fn)) # determine version with open('Cargo.toml') as fp: -- cgit 1.4.1-3-g733a5 From 7d996724df7d5d97f1bd69c46136bb2eb69d1651 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 30 Sep 2018 10:30:51 +0200 Subject: travis: sleep after putting out logs (try to fix truncated logs) --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8d76e10983e..f1273c0d4a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,8 +60,10 @@ script: - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh + sleep 5 else ./ci/integration-tests.sh + sleep 5 fi after_success: | -- cgit 1.4.1-3-g733a5 From 9bfe5285312ea405f8c9a165438f1429ac2b118b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Sep 2018 13:20:30 +0200 Subject: Remove clippy-service update from CI clippy-service hasn't been working for a long time now. --- .travis.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d76e10983e..58f00187256 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,20 +73,5 @@ after_success: | else echo "Not deploying, because we're in an integration test run" fi - # trigger rebuild of the clippy-service, to keep it up to date with clippy itself - if [ "$TRAVIS_PULL_REQUEST" == "false" ] && - [ "$TRAVIS_REPO_SLUG" == "Manishearth/rust-clippy" ] && - [ "$TRAVIS_BRANCH" == "master" ] && - [ "$TRAVIS_TOKEN_CLIPPY_SERVICE" != "" ] ; then - curl -s -X POST \ - -H "Content-Type: application/json" \ - -H "Accept: application/json" \ - -H "Travis-API-Version: 3" \ - -H "Authorization: token $TRAVIS_TOKEN_CLIPPY_SERVICE" \ - -d "{ \"request\": { \"branch\":\"master\" }}" \ - https://api.travis-ci.org/repo/gnunicorn%2Fclippy-service/requests - else - echo "Ignored" - fi set +e fi -- cgit 1.4.1-3-g733a5 From 91f7e22edf652e3676a31d6d4ee0d5e8f712716c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 30 Sep 2018 11:12:24 +0200 Subject: remove cargo edition 2018 feature gate. Rust and the cargo used to bootstrap was updated in https://github.com/rust-lang/rust/pull/54601 which now has the 2018 edition stabilized. --- Cargo.toml | 2 -- clippy_dev/Cargo.toml | 2 -- clippy_lints/Cargo.toml | 2 -- rustc_tools_util/Cargo.toml | 2 -- 4 files changed, 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b293f06713d..80ff21764a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "clippy" version = "0.0.212" diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 519f78999b9..d6057ba970c 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "clippy_dev" version = "0.0.1" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 15da5d65878..8907dd3659c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "clippy_lints" # begin automatic update diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 01dca0a65b0..020de6c3393 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] name = "rustc_tools_util" version = "0.1.0" -- cgit 1.4.1-3-g733a5 From b43d7e74e00360b659428d6fc01e14447bd5a9b4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 30 Sep 2018 11:28:35 +0200 Subject: Remove clippy-service token --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 58f00187256..7cefb9cb459 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,6 @@ sudo: false env: global: - # TRAVIS_TOKEN_CLIPPY_SERVICE - - secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI= - RUST_BACKTRACE=1 before_install: -- cgit 1.4.1-3-g733a5 From 14335f372bc1a46f1ae7cb6bf54f652d949a6652 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 30 Sep 2018 12:59:15 +0200 Subject: Disable dogfood until rust-lang-nursery/rustup.rs#1499 is merged --- tests/dogfood.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 2ff4274a1a9..ff7452c7c10 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,6 +1,6 @@ #[test] fn dogfood() { - if option_env!("RUSTC_TEST_SUITE").is_some() { + if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; } let root_dir = std::env::current_dir().unwrap(); -- cgit 1.4.1-3-g733a5 From eb5f146f1492cce356883905865f4bb9fc97d8ba Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 1 Oct 2018 22:33:20 +0200 Subject: Fix 'impossible case reached' ICE --- clippy_lints/src/needless_pass_by_value.rs | 9 ++++----- tests/ui/needless_pass_by_value.rs | 10 ++++++++++ tests/ui/needless_pass_by_value.stderr | 14 +++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 980e2c28a34..73d59d7a33c 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -174,15 +174,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| t.def_id() == borrow_trait), !preds.is_empty() && preds.iter().all(|t| { + let ty_params = &t.skip_binder().trait_ref.substs.iter().skip(1) + .cloned() + .collect::>(); implements_trait( cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), - &t.skip_binder() - .input_types() - .skip(1) - .map(|ty| ty.into()) - .collect::>(), + ty_params ) }), ) diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 783386fab01..31ad96942d6 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -134,4 +134,14 @@ fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { println!("{}", t); } +// The following 3 lines should not cause an ICE. See #2831 +trait Bar<'a, A> {} +impl<'b, T> Bar<'b, T> for T {} +fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} + +// Also this should not cause an ICE. See #2831 +trait Club<'a, A> {} +impl Club<'static, T> for T {} +fn more_fun(_item: impl Club<'static, i32>) {} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 9cb5e6e48cd..0d4a35363fb 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -184,5 +184,17 @@ help: consider taking a reference instead 129 | let CopyWrapper(s) = *z; // moved | -error: aborting due to 20 previous errors +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:140:40 + | +140 | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} + | ^ help: consider taking a reference instead: `&S` + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:145:20 + | +145 | fn more_fun(_item: impl Club<'static, i32>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` + +error: aborting due to 22 previous errors -- cgit 1.4.1-3-g733a5 From a930e778c2325c32bf94a580499b000455081e90 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 1 Oct 2018 22:03:07 +0200 Subject: Add dummy clippy crate for publishing --- clippy_dummy/Cargo.toml | 17 +++++++++++++++++ clippy_dummy/PUBLISH.md | 4 ++++ clippy_dummy/build.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ clippy_dummy/crates-readme.md | 9 +++++++++ clippy_dummy/src/main.rs | 3 +++ 5 files changed, 75 insertions(+) create mode 100644 clippy_dummy/Cargo.toml create mode 100644 clippy_dummy/PUBLISH.md create mode 100644 clippy_dummy/build.rs create mode 100644 clippy_dummy/crates-readme.md create mode 100644 clippy_dummy/src/main.rs diff --git a/clippy_dummy/Cargo.toml b/clippy_dummy/Cargo.toml new file mode 100644 index 00000000000..b9e3aa3bcdc --- /dev/null +++ b/clippy_dummy/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "clippy_dummy" # rename to clippy before publishing +version = "0.0.301" +authors = ["Manish Goregaokar "] +edition = "2018" +readme = "crates-readme.md" +description = "A bunch of helpful lints to avoid common pitfalls in Rust." +build = 'build.rs' + +repository = "https://github.com/rust-lang-nursery/rust-clippy" + +license = "MPL-2.0" +keywords = ["clippy", "lint", "plugin"] +categories = ["development-tools", "development-tools::cargo-plugins"] + +[build-dependencies] +term = "0.5.1" diff --git a/clippy_dummy/PUBLISH.md b/clippy_dummy/PUBLISH.md new file mode 100644 index 00000000000..535f11bd2ee --- /dev/null +++ b/clippy_dummy/PUBLISH.md @@ -0,0 +1,4 @@ +This is a dummy crate to publish to crates.io. It primarily exists to ensure that folks trying to install clippy from crates.io get redirected to the `rustup` technique. + +Before publishing, be sure to rename `clippy_dummy` to `clippy` in `Cargo.toml`, it has a different name to avoid workspace issues. + \ No newline at end of file diff --git a/clippy_dummy/build.rs b/clippy_dummy/build.rs new file mode 100644 index 00000000000..97902feff86 --- /dev/null +++ b/clippy_dummy/build.rs @@ -0,0 +1,42 @@ +extern crate term; + +fn main() { + if let Err(_) = foo() { + eprintln!("error: Clippy is no longer available via crates.io\n"); + eprintln!("help: please run `rustup component add clippy-preview` instead"); + } + std::process::exit(1); +} + +fn foo() -> Result<(), ()> { + let mut t = term::stderr().ok_or(())?; + + t.attr(term::Attr::Bold).map_err(|_| ())?; + t.fg(term::color::RED).map_err(|_| ())?; + write!(t, "\nerror: ").map_err(|_| ())?; + + + t.reset().map_err(|_| ())?; + t.fg(term::color::WHITE).map_err(|_| ())?; + writeln!(t, "Clippy is no longer available via crates.io\n").map_err(|_| ())?; + + + t.attr(term::Attr::Bold).map_err(|_| ())?; + t.fg(term::color::GREEN).map_err(|_| ())?; + write!(t, "help: ").map_err(|_| ())?; + + + t.reset().map_err(|_| ())?; + t.fg(term::color::WHITE).map_err(|_| ())?; + write!(t, "please run `").map_err(|_| ())?; + + t.attr(term::Attr::Bold).map_err(|_| ())?; + write!(t, "rustup component add clippy-preview").map_err(|_| ())?; + + t.reset().map_err(|_| ())?; + t.fg(term::color::WHITE).map_err(|_| ())?; + writeln!(t, "` instead").map_err(|_| ())?; + + t.reset().map_err(|_| ())?; + Ok(()) +} \ No newline at end of file diff --git a/clippy_dummy/crates-readme.md b/clippy_dummy/crates-readme.md new file mode 100644 index 00000000000..0035073549c --- /dev/null +++ b/clippy_dummy/crates-readme.md @@ -0,0 +1,9 @@ +Installing clippy via crates.io is deprecated. Please use the following: + +```terminal +rustup component add clippy-preview +``` + +on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary. + +See [the homepage](https://github.com/rust-lang-nursery/rust-clippy/#clippy) for more information \ No newline at end of file diff --git a/clippy_dummy/src/main.rs b/clippy_dummy/src/main.rs new file mode 100644 index 00000000000..a118834f1fd --- /dev/null +++ b/clippy_dummy/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + panic!("This shouldn't even compile") +} -- cgit 1.4.1-3-g733a5 From 6c1d6391ecf3d7f2ee6761dda1cd5595744550dc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 09:58:02 +0200 Subject: publish = false --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 80ff21764a5..d765e09deef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] build = "build.rs" edition = "2018" +publish = false [badges] travis-ci = { repository = "rust-lang-nursery/rust-clippy" } -- cgit 1.4.1-3-g733a5 From be1094bd8db7ed662206601c6917a8ee0d965803 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 10:35:26 +0200 Subject: ScalarMaybeUndef -> Scalar (Rustup to e812ca472a2a5284e9f15cd9af32285d7ff3fd39) --- clippy_lints/src/consts.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 0690d6934e5..4e09e039100 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -409,7 +409,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use crate::rustc::mir::interpret::{Scalar, ScalarMaybeUndef, ConstValue}; + use crate::rustc::mir::interpret::{Scalar, ConstValue}; match result.val { ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { ty::Bool => Some(Constant::Bool(b == 1)), @@ -420,8 +420,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' _ => None, }, ConstValue::ScalarPair(Scalar::Ptr(ptr), - ScalarMaybeUndef::Scalar( - Scalar::Bits { bits: n, .. })) => match result.ty.sty { + Scalar::Bits { bits: n, .. }) => match result.ty.sty { ty::Ref(_, tam, _) => match tam.sty { ty::Str => { let alloc = tcx -- cgit 1.4.1-3-g733a5 From b94238f5b38587174fb7d0c11f1569961e491330 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 10:39:51 +0200 Subject: Mention -A and -W in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b8684b38631..40ece34c6fa 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,8 @@ enable/disable Clippy lints until `tool_lints` are stable: #![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))] ``` +If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W lint_name` will run it with that enabled. On newer compilers you may need to use `clippy::lint_name` instead. + ## License Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). -- cgit 1.4.1-3-g733a5 From fffcd093b29a3fa4be22d3836f214cd810836c21 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 12:41:40 +0200 Subject: relicensing: Remove fn_to_numeric_cast, fn_to_numeric_cast_with_truncation This removes the code added in https://github.com/rust-lang-nursery/rust-clippy/pull/2814 --- clippy_lints/src/lib.rs | 4 --- clippy_lints/src/types.rs | 67 ----------------------------------------- tests/ui/types_fn_to_int.rs | 22 -------------- tests/ui/types_fn_to_int.stderr | 66 ---------------------------------------- 4 files changed, 159 deletions(-) delete mode 100644 tests/ui/types_fn_to_int.rs delete mode 100644 tests/ui/types_fn_to_int.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9af4850b15c..19564dbf9be 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -697,8 +697,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::CAST_LOSSLESS, types::CAST_PTR_ALIGNMENT, types::CHAR_LIT_AS_U8, - types::FN_TO_NUMERIC_CAST, - types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::OPTION_OPTION, @@ -791,7 +789,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, - types::FN_TO_NUMERIC_CAST, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, @@ -921,7 +918,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::CAST_PTR_ALIGNMENT, - types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 857238e9002..b98a0f88242 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -700,40 +700,6 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } -/// **What it does:** Checks for casts of a function pointer to a numeric type not enough to store address. -/// -/// **Why is this bad?** Casting a function pointer to not eligible type could truncate the address value. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn test_fn() -> i16; -/// let _ = test_fn as i32 -/// ``` -declare_clippy_lint! { - pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - correctness, - "cast function pointer to the numeric type with value truncation" -} - -/// **What it does:** Checks for casts of a function pointer to a numeric type except `usize`. -/// -/// **Why is this bad?** Casting a function pointer to something other than `usize` is not a good style. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn test_fn() -> i16; -/// let _ = test_fn as i128 -/// ``` -declare_clippy_lint! { - pub FN_TO_NUMERIC_CAST, - style, - "cast function pointer to the numeric type" -} - /// **What it does:** Checks for casts from a less-strictly-aligned pointer to a /// more-strictly-aligned pointer /// @@ -947,8 +913,6 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, - FN_TO_NUMERIC_CAST, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, ) } } @@ -1033,37 +997,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } } - match &cast_from.sty { - ty::FnDef(..) | - ty::FnPtr(..) => { - if cast_to.is_numeric() && cast_to.sty != ty::Uint(UintTy::Usize){ - let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); - let pointer_nbits = cx.tcx.data_layout.pointer_size.bits(); - if to_nbits < pointer_nbits || (to_nbits == pointer_nbits && cast_to.is_signed()) { - span_lint_and_sugg( - cx, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - expr.span, - &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), - "if you need the address of the function, consider", - format!("{} as usize", &snippet(cx, ex.span, "x")) - ); - } else { - span_lint_and_sugg( - cx, - FN_TO_NUMERIC_CAST, - expr.span, - &format!("casting a `{}` to `{}` is bad style.", cast_from, cast_to), - "if you need the address of the function, consider", - format!("{} as usize", &snippet(cx, ex.span, "x")) - ); - - }; - } - } - _ => () - } - if_chain!{ if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs deleted file mode 100644 index 8387586c3e9..00000000000 --- a/tests/ui/types_fn_to_int.rs +++ /dev/null @@ -1,22 +0,0 @@ -enum Foo { - A(usize), - B -} - -fn bar() -> i32 { - 0i32 -} - -fn main() { - let x = Foo::A; - let _y = x as i32; - let _y1 = Foo::A as i32; - let _y = x as u32; - let _z = bar as u32; - let _y = bar as i64; - let _y = bar as u64; - let _z = Foo::A as i128; - let _z = Foo::A as u128; - let _z = bar as i128; - let _z = bar as u128; -} diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr deleted file mode 100644 index a06809b9bfd..00000000000 --- a/tests/ui/types_fn_to_int.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:12:14 - | -12 | let _y = x as i32; - | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` - | - = note: #[deny(clippy::fn_to_numeric_cast_with_truncation)] on by default - -error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:13:15 - | -13 | let _y1 = Foo::A as i32; - | ^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:14:14 - | -14 | let _y = x as u32; - | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` - -error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:15:14 - | -15 | let _z = bar as u32; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `i64` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:16:14 - | -16 | let _y = bar as i64; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `u64` is bad style. - --> $DIR/types_fn_to_int.rs:17:14 - | -17 | let _y = bar as u64; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - | - = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `i128` is bad style. - --> $DIR/types_fn_to_int.rs:18:14 - | -18 | let _z = Foo::A as i128; - | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `u128` is bad style. - --> $DIR/types_fn_to_int.rs:19:14 - | -19 | let _z = Foo::A as u128; - | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn() -> i32 {bar}` to `i128` is bad style. - --> $DIR/types_fn_to_int.rs:20:14 - | -20 | let _z = bar as i128; - | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `u128` is bad style. - --> $DIR/types_fn_to_int.rs:21:14 - | -21 | let _z = bar as u128; - | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: aborting due to 10 previous errors - -- cgit 1.4.1-3-g733a5 From 057243f16b4f42337b6178a627dcf3ae4c09f056 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 12:51:38 +0200 Subject: relicensing: Remove map_clone This removes the code added in https://github.com/rust-lang-nursery/rust-clippy/pull/427 --- clippy_lints/src/lib.rs | 4 -- clippy_lints/src/map_clone.rs | 140 ------------------------------------------ tests/ui/map_clone.rs | 105 ------------------------------- tests/ui/map_clone.stderr | 102 ------------------------------ 4 files changed, 351 deletions(-) delete mode 100644 clippy_lints/src/map_clone.rs delete mode 100644 tests/ui/map_clone.rs delete mode 100644 tests/ui/map_clone.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 19564dbf9be..689dbfa7da9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -129,7 +129,6 @@ pub mod let_if_seq; pub mod lifetimes; pub mod literal_representation; pub mod loops; -pub mod map_clone; pub mod map_unit_fn; pub mod matches; pub mod mem_forget; @@ -346,7 +345,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); reg.register_late_lint_pass(box no_effect::Pass); - reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box temporary_assignment::Pass); reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass( @@ -585,7 +583,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, - map_clone::MAP_CLONE, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, @@ -745,7 +742,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, - map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs deleted file mode 100644 index 239602c6db5..00000000000 --- a/clippy_lints/src/map_clone.rs +++ /dev/null @@ -1,140 +0,0 @@ -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; -use crate::rustc::ty; -use crate::syntax::ast; -use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, - paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; - -/// **What it does:** Checks for mapping `clone()` over an iterator. -/// -/// **Why is this bad?** It makes the code less readable than using the -/// `.cloned()` adapter. -/// -/// **Known problems:** Sometimes `.cloned()` requires stricter trait -/// bound than `.map(|e| e.clone())` (which works because of the coercion). -/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498). -/// -/// **Example:** -/// ```rust -/// x.map(|e| e.clone()); -/// ``` -declare_clippy_lint! { - pub MAP_CLONE, - style, - "using `.map(|x| x.clone())` to clone an iterator or option's contents" -} - -#[derive(Copy, Clone)] -pub struct Pass; - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - // call to .map() - if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { - if method.ident.name == "map" && args.len() == 2 { - match args[1].node { - ExprKind::Closure(_, ref decl, closure_eid, _, _) => { - let body = cx.tcx.hir.body(closure_eid); - let closure_expr = remove_blocks(&body.value); - if_chain! { - // nothing special in the argument, besides reference bindings - // (e.g. .map(|&x| x) ) - if let Some(first_arg) = iter_input_pats(decl, body).next(); - if let Some(arg_ident) = get_arg_ident(&first_arg.pat); - // the method is being called on a known type (option or iterator) - if let Some(type_name) = get_type_name(cx, expr, &args[0]); - then { - // We know that body.arguments is not empty at this point - let ty = cx.tables.pat_ty(&body.arguments[0].pat); - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 - { - // the argument is not an &mut T - if let ty::Ref(_, _, mutbl) = ty.sty { - if mutbl == MutImmutable { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprKind::MethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.ident.name == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(cx, &clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - } - } - }, - ExprKind::Path(ref path) => if match_qpath(path, &paths::CLONE) { - let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint( - cx, - MAP_CLONE, - expr.span, - &format!( - "you seem to be using .map() to clone the contents of an \ - {}, consider using `.cloned()`", - type_name - ), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), - ); - }, - _ => (), - } - } - } - } -} - -fn expr_eq_name(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { - match expr.node { - ExprKind::Path(QPath::Resolved(None, ref path)) => { - let arg_segment = [ - PathSegment { - ident: id, - args: None, - infer_types: true, - }, - ]; - !path.is_global() && SpanlessEq::new(cx).eq_path_segments(&path.segments[..], &arg_segment) - }, - _ => false, - } -} - -fn get_type_name(cx: &LateContext<'_, '_>, expr: &Expr, arg: &Expr) -> Option<&'static str> { - if match_trait_method(cx, expr, &paths::ITERATOR) { - Some("iterator") - } else if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(arg)), &paths::OPTION) { - Some("Option") - } else { - None - } -} - -fn only_derefs(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { - match expr.node { - ExprKind::Unary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), - _ => expr_eq_name(cx, expr, id), - } -} - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_CLONE) - } -} diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs deleted file mode 100644 index 90c95be2c1c..00000000000 --- a/tests/ui/map_clone.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![feature(tool_lints)] - - -#![warn(clippy::map_clone)] - -#![allow(clippy::clone_on_copy, unused)] - -use std::ops::Deref; - -fn map_clone_iter() { - let x = [1,2,3]; - x.iter().map(|y| y.clone()); - - x.iter().map(|&y| y); - - x.iter().map(|y| *y); - - x.iter().map(|y| { y.clone() }); - - x.iter().map(|&y| { y }); - - x.iter().map(|y| { *y }); - - x.iter().map(Clone::clone); - -} - -fn map_clone_option() { - let x = Some(4); - x.as_ref().map(|y| y.clone()); - - x.as_ref().map(|&y| y); - - x.as_ref().map(|y| *y); - -} - -fn not_linted_option() { - let x = Some(5); - - // Not linted: other statements - x.as_ref().map(|y| { - println!("y: {}", y); - y.clone() - }); - - // Not linted: argument bindings - let x = Some((6, 7)); - x.map(|(y, _)| y.clone()); - - // Not linted: cloning something else - x.map(|y| y.0.clone()); - - // Not linted: no dereferences - x.map(|y| y); - - // Not linted: multiple dereferences - let _: Option<(i32, i32)> = x.as_ref().as_ref().map(|&&x| x); -} - -#[derive(Copy, Clone)] -struct Wrapper(T); -impl Wrapper { - fn map U>(self, f: F) -> Wrapper { - Wrapper(f(self.0)) - } -} - -fn map_clone_other() { - let eight = 8; - let x = Wrapper(&eight); - - // Not linted: not a linted type - x.map(|y| y.clone()); - x.map(|&y| y); - x.map(|y| *y); -} - -#[derive(Copy, Clone)] -struct UnusualDeref; -static NINE: i32 = 9; - -impl Deref for UnusualDeref { - type Target = i32; - fn deref(&self) -> &i32 { &NINE } -} - -fn map_clone_deref() { - let x = Some(UnusualDeref); - let _: Option = x.as_ref().map(|y| *y); - - - // Not linted: using deref conversion - let _: Option = x.map(|y| *y); - - // Not linted: using regular deref but also deref conversion - let _: Option = x.as_ref().map(|y| **y); -} - -// stuff that used to be a false positive -fn former_false_positive() { - vec![1].iter_mut().map(|x| *x); // #443 -} - -fn main() { } diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr deleted file mode 100644 index afad65b0071..00000000000 --- a/tests/ui/map_clone.stderr +++ /dev/null @@ -1,102 +0,0 @@ -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:12:5 - | -12 | x.iter().map(|y| y.clone()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::map-clone` implied by `-D warnings` - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:14:5 - | -14 | x.iter().map(|&y| y); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:16:5 - | -16 | x.iter().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:18:5 - | -18 | x.iter().map(|y| { y.clone() }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:20:5 - | -20 | x.iter().map(|&y| { y }); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:22:5 - | -22 | x.iter().map(|y| { *y }); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:24:5 - | -24 | x.iter().map(Clone::clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:30:5 - | -30 | x.as_ref().map(|y| y.clone()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:32:5 - | -32 | x.as_ref().map(|&y| y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:34:5 - | -34 | x.as_ref().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:90:35 - | -90 | let _: Option = x.as_ref().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: aborting due to 11 previous errors - -- cgit 1.4.1-3-g733a5 From f142098474fbe4d46bd20227ae318adf168302dc Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Mon, 1 Oct 2018 04:47:06 -0700 Subject: Correct false positive in wrong_self_convention lint for to_mut --- clippy_lints/src/methods/mod.rs | 18 ++++++++++-------- tests/ui/wrong_self_convention.rs | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2524152a120..e0d858bd270 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -882,12 +882,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ty = cx.tcx.type_of(def_id); let is_copy = is_copy(cx, ty); for &(ref conv, self_kinds) in &CONVENTIONS { - if_chain! { - if conv.check(&name.as_str()); + if conv.check(&name.as_str()) { if !self_kinds - .iter() - .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)); - then { + .iter() + .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)) { let lint = if item.vis.node.is_pub() { WRONG_PUB_SELF_CONVENTION } else { @@ -904,6 +902,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { .collect::>() .join(" or "))); } + + // Only check the first convention to match (CONVENTIONS should be listed from most to least specific) + break; } } @@ -1183,8 +1184,8 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp Applicability::MaybeIncorrect, ); db.span_suggestion_with_applicability( - expr.span, - "or try being explicit about what type to clone", + expr.span, + "or try being explicit about what type to clone", explicit, Applicability::MaybeIncorrect, ); @@ -2067,12 +2068,13 @@ enum Convention { } #[rustfmt::skip] -const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [ +const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [ (Convention::Eq("new"), &[SelfKind::No]), (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), (Convention::StartsWith("from_"), &[SelfKind::No]), (Convention::StartsWith("into_"), &[SelfKind::Value]), (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), + (Convention::Eq("to_mut"), &[SelfKind::RefMut]), (Convention::StartsWith("to_"), &[SelfKind::Ref]), ]; diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 1e718c1c648..2fb33d08619 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -59,4 +59,5 @@ impl Bar { fn is_(self) {} fn to_(self) {} fn from_(self) {} + fn to_mut(&mut self) {} } -- cgit 1.4.1-3-g733a5 From b36bb0a68d70f091dd03f209f41b614ff1f015d0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:13:43 +0200 Subject: Reimplement the `map_clone` lint from scratch --- CHANGELOG.md | 2 - README.md | 2 +- clippy_lints/src/lib.rs | 4 ++ clippy_lints/src/map_clone.rs | 100 ++++++++++++++++++++++++++++++++++++++++++ tests/ui/map_clone.rs | 9 ++++ tests/ui/map_clone.stderr | 22 ++++++++++ 6 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/map_clone.rs create mode 100644 tests/ui/map_clone.rs create mode 100644 tests/ui/map_clone.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bea1e8ef5..013a508cc76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -688,8 +688,6 @@ All notable changes to this project will be documented in this file. [`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const -[`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast -[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result diff --git a/README.md b/README.md index 40ece34c6fa..a2b61703a82 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 279 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 277 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 689dbfa7da9..8b1b626be44 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -129,6 +129,7 @@ pub mod let_if_seq; pub mod lifetimes; pub mod literal_representation; pub mod loops; +pub mod map_clone; pub mod map_unit_fn; pub mod matches; pub mod mem_forget; @@ -327,6 +328,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); reg.register_late_lint_pass(box methods::Pass); + reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); @@ -583,6 +585,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, @@ -742,6 +745,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs new file mode 100644 index 00000000000..ddbb55a26ff --- /dev/null +++ b/clippy_lints/src/map_clone.rs @@ -0,0 +1,100 @@ +use crate::rustc::hir; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::source_map::Span; +use crate::utils::paths; +use crate::utils::{ + in_macro, match_trait_method, match_type, + remove_blocks, snippet, + span_lint_and_sugg, +}; +use if_chain::if_chain; +use crate::syntax::ast::Ident; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests +/// `iterator.cloned()` instead +/// +/// **Why is this bad?** Readability, this can be written more concisely +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// let x = vec![42, 43]; +/// let y = x.iter(); +/// let z = y.map(|i| *i); +/// ``` +/// +/// The correct use would be: +/// +/// ```rust +/// let x = vec![42, 43]; +/// let y = x.iter(); +/// let z = y.cloned(); +/// ``` +declare_clippy_lint! { + pub MAP_CLONE, + style, + "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types" +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_CLONE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) { + if in_macro(e.span) { + return; + } + + if_chain! { + if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.node; + if args.len() == 2; + if method.ident.as_str() == "map"; + let ty = cx.tables.expr_ty(&args[0]); + if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); + if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node; + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); + then { + match closure_body.arguments[0].pat.node { + hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) = inner.node { + lint(cx, e.span, args[0].span, name, closure_expr); + }, + hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { + hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => lint(cx, e.span, args[0].span, name, inner), + hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" { + if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { + lint(cx, e.span, args[0].span, name, &obj[0]); + } + } + _ => {}, + }, + _ => {}, + } + } + } + } +} + +fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) { + if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node { + if path.segments.len() == 1 && path.segments[0].ident == name { + span_lint_and_sugg( + cx, + MAP_CLONE, + replace, + "You are using an explicit closure for cloning elements", + "Consider calling the dedicated `cloned` method", + format!("{}.cloned()", snippet(cx, root, "..")), + ) + } + } +} \ No newline at end of file diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs new file mode 100644 index 00000000000..11a5316a367 --- /dev/null +++ b/tests/ui/map_clone.rs @@ -0,0 +1,9 @@ +#![feature(tool_lints)] +#![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::missing_docs_in_private_items)] + +fn main() { + let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); +} diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr new file mode 100644 index 00000000000..e80983cdbf7 --- /dev/null +++ b/tests/ui/map_clone.stderr @@ -0,0 +1,22 @@ +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:6:22 + | +6 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` + | + = note: `-D clippy::map-clone` implied by `-D warnings` + +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:7:26 + | +7 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` + +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:8:23 + | +8 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From 696dc369df56e3a63ae7401959d0c1df0ff0296a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:17:56 +0200 Subject: FIx dogfood --- clippy_lints/src/map_clone.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index ddbb55a26ff..5c733eb4f7a 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -70,10 +70,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => lint(cx, e.span, args[0].span, name, inner), - hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" { - if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { - lint(cx, e.span, args[0].span, name, &obj[0]); - } + hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { + lint(cx, e.span, args[0].span, name, &obj[0]); } _ => {}, }, -- cgit 1.4.1-3-g733a5 From 913a5c9b56d367e5a042a7159a8fd340d1709c51 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:18:56 +0200 Subject: Trailing newline --- clippy_lints/src/map_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 5c733eb4f7a..e16a8af7641 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -95,4 +95,4 @@ fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: ) } } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From d18c7b272245f41cea9303ca62beb9ca64615251 Mon Sep 17 00:00:00 2001 From: mcarton Date: Tue, 2 Oct 2018 23:54:50 +0200 Subject: Add test for variable width in `USELESS_FORMAT` --- tests/ui/format.rs | 2 ++ tests/ui/format.stderr | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 8f31d92ac3c..1b467dae0cc 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -14,6 +14,7 @@ fn main() { format!("{}", "foo"); format!("{:?}", "foo"); // don't warn about debug format!("{:8}", "foo"); + format!("{:width$}", "foo", width = 8); format!("{:+}", "foo"); // warn when the format makes no difference format!("{:<}", "foo"); // warn when the format makes no difference format!("foo {}", "bar"); @@ -23,6 +24,7 @@ fn main() { format!("{}", arg); format!("{:?}", arg); // don't warn about debug format!("{:8}", arg); + format!("{:width$}", arg, width = 8); format!("{:+}", arg); // warn when the format makes no difference format!("{:<}", arg); // warn when the format makes no difference format!("foo {}", arg); diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index ca6ef905396..d77c99d90b8 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -15,41 +15,41 @@ error: useless use of `format!` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:17:5 + --> $DIR/format.rs:18:5 | -17 | format!("{:+}", "foo"); // warn when the format makes no difference +18 | format!("{:+}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:18:5 + --> $DIR/format.rs:19:5 | -18 | format!("{:<}", "foo"); // warn when the format makes no difference +19 | format!("{:<}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:23:5 + --> $DIR/format.rs:24:5 | -23 | format!("{}", arg); +24 | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:26:5 + --> $DIR/format.rs:28:5 | -26 | format!("{:+}", arg); // warn when the format makes no difference +28 | format!("{:+}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:27:5 + --> $DIR/format.rs:29:5 | -27 | format!("{:<}", arg); // warn when the format makes no difference +29 | format!("{:<}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -- cgit 1.4.1-3-g733a5 From 7eebd5b20c215c4baa98a1ac569e543712451c33 Mon Sep 17 00:00:00 2001 From: mcarton Date: Tue, 2 Oct 2018 23:55:25 +0200 Subject: Ignore `format!` with precision in `USELESS_FORMAT` --- clippy_lints/src/format.rs | 10 ++++++---- tests/ui/format.rs | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 2eb95ebffbf..2d40150bc8e 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -47,7 +47,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } match expr.node { - // `format!("{}", foo)` expansion ExprKind::Call(ref fun, ref args) => { if_chain! { @@ -162,9 +161,12 @@ fn check_unformatted(expr: &Expr) -> bool { if let ExprKind::Struct(_, ref fields, _) = exprs[0].node; if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format"); if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node; - if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width"); - if let ExprKind::Path(ref qpath) = align_field.expr.node; - if last_path_segment(qpath).ident.name == "Implied"; + if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width"); + if let ExprKind::Path(ref width_qpath) = width_field.expr.node; + if last_path_segment(width_qpath).ident.name == "Implied"; + if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision"); + if let ExprKind::Path(ref precision_path) = precision_field.expr.node; + if last_path_segment(precision_path).ident.name == "Implied"; then { return true; } diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 1b467dae0cc..0162f34c085 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -46,4 +46,10 @@ fn main() { // A format! inside a macro should not trigger a warning foo!("should not warn"); + + // precision on string means slicing without panicking on size: + format!("{:.1}", "foo"); // could be "foo"[..1] + format!("{:.10}", "foo"); // could not be "foo"[..10] + format!("{:.prec$}", "foo", prec = 1); + format!("{:.prec$}", "foo", prec = 10); } -- cgit 1.4.1-3-g733a5 From c43014794208963c4180a3c51ed06ec36d8a57b7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 3 Oct 2018 02:02:50 -0700 Subject: Fix push_item_path call (rustup to 4cf11765dc98536c6eedf33f2df7f72f6e161263) --- clippy_lints/src/utils/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0011065db67..fa3c72dbb7d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -72,6 +72,7 @@ pub fn in_macro(span: Span) -> bool { pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool { use crate::syntax::symbol; + #[derive(Debug)] struct AbsolutePathBuffer { names: Vec, } @@ -89,7 +90,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> let mut apb = AbsolutePathBuffer { names: vec![] }; - tcx.push_item_path(&mut apb, def_id); + tcx.push_item_path(&mut apb, def_id, false); apb.names.len() == path.len() && apb.names -- cgit 1.4.1-3-g733a5 From f42272102a97e2f57e4d02c3a5a1defa3c800970 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 3 Oct 2018 12:02:06 +0200 Subject: Reimplement the `fn_to_numeric_cast` lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/types.rs | 45 ++++++++++++++++++++++++++++++++++++++ tests/ui/fn_to_numeric_cast.rs | 49 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/ui/fn_to_numeric_cast.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 013a508cc76..2373cb87eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -688,6 +688,7 @@ All notable changes to this project will be documented in this file. [`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const +[`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result diff --git a/README.md b/README.md index a2b61703a82..f332a3f645d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 277 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8b1b626be44..b181a4c17ca 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -697,6 +697,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::CAST_LOSSLESS, types::CAST_PTR_ALIGNMENT, types::CHAR_LIT_AS_U8, + types::FN_TO_NUMERIC_CAST, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::OPTION_OPTION, @@ -789,6 +790,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, + types::FN_TO_NUMERIC_CAST, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b98a0f88242..5d26e477c82 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -719,6 +719,30 @@ declare_clippy_lint! { "cast from a pointer to a more-strictly-aligned pointer" } +/// **What it does:** Checks for casts of function pointers to something other than usize +/// +/// **Why is this bad?** +/// Depending on the system architechture, casting a function pointer to something other than +/// `usize` will result in incorrect pointer addresses. +/// `usize` will always be able to store the function pointer on the given architechture. +/// +/// **Example** +/// +/// ```rust +/// // Bad +/// fn fun() -> i32 {} +/// let a = fun as i64; +/// +/// // Good +/// fn fun2() -> i32 {} +/// let a = fun2 as usize; +/// ``` +declare_clippy_lint! { + pub FN_TO_NUMERIC_CAST, + style, + "casting a function pointer to a numeric type other than usize" +} + /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { @@ -913,6 +937,7 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, + FN_TO_NUMERIC_CAST ) } } @@ -921,6 +946,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Cast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); + lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to); if let ExprKind::Lit(ref lit) = ex.node { use crate::syntax::ast::{LitIntType, LitKind}; match lit.node { @@ -1021,6 +1047,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } } +fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty, cast_to: Ty) { + match cast_from.sty { + ty::FnDef(..) | ty::FnPtr(_) => { + let from_snippet = snippet(cx, cast_expr.span, "x"); + if cast_to.sty != ty::Uint(UintTy::Usize) { + span_lint_and_sugg( + cx, + FN_TO_NUMERIC_CAST, + expr.span, + &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to), + "try", + format!("{} as usize", from_snippet) + ); + } + }, + _ => {} + } +} + /// **What it does:** Checks for types used in structs, parameters and `let` /// declarations above a certain complexity threshold. /// diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs new file mode 100644 index 00000000000..d250af61847 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast.rs @@ -0,0 +1,49 @@ +#![feature(tool_lints)] + +#[warn(clippy::fn_to_numeric_cast)] + +fn foo() -> String { String::new() } + +fn test_function_to_numeric_cast() { + let _ = foo as i8; + let _ = foo as i16; + let _ = foo as i32; + let _ = foo as i64; + let _ = foo as i128; + let _ = foo as isize; + + let _ = foo as u8; + let _ = foo as u16; + let _ = foo as u32; + let _ = foo as u64; + let _ = foo as u128; + + // Casting to usize is OK and should not warn + let _ = foo as usize; +} + +fn test_function_var_to_numeric_cast() { + let abc: fn() -> String = foo; + + let _ = abc as i8; + let _ = abc as i16; + let _ = abc as i32; + let _ = abc as i64; + let _ = abc as i128; + let _ = abc as isize; + + let _ = abc as u8; + let _ = abc as u16; + let _ = abc as u32; + let _ = abc as u64; + let _ = abc as u128; + + // Casting to usize is OK and should not warn + let _ = abc as usize; +} + +fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 { + f as i32 +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 8695c2c34bf315f9cf62f1a1e276a8bcb8c693c7 Mon Sep 17 00:00:00 2001 From: O01eg Date: Wed, 3 Oct 2018 21:41:02 +0300 Subject: Allow to debug rustc_driver via logs. --- src/driver.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/driver.rs b/src/driver.rs index 99f8bc610ff..6c442e42d95 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -21,6 +21,7 @@ fn show_version() { } pub fn main() { + rustc_driver::init_rustc_env_logger(); exit(rustc_driver::run(move || { use std::env; -- cgit 1.4.1-3-g733a5 From 5173ed0c03ff2ce86c80654116e30e61519eb208 Mon Sep 17 00:00:00 2001 From: mcarton Date: Wed, 3 Oct 2018 20:59:59 +0200 Subject: Don't suggest `to_string().to_string` in USELESS_FORMAT --- clippy_lints/src/format.rs | 24 ++++++++++++++++++------ tests/ui/format.rs | 4 ++++ tests/ui/format.stderr | 18 +++++++++++++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 2d40150bc8e..30ad022f476 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -57,12 +57,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if check_single_piece(&args[0]); if let Some(format_arg) = get_single_string_arg(cx, &args[1]); if check_unformatted(&args[2]); + if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node; then { - let sugg = format!("{}.to_string()", snippet(cx, format_arg, "").into_owned()); + let (message, sugg) = if_chain! { + if let ExprKind::MethodCall(ref path, ref span, ref expr) = format_arg.node; + if path.ident.as_interned_str() == "to_string"; + then { + ("`to_string()` is enough", + snippet(cx, format_arg.span, "").to_string()) + } else { + ("consider using .to_string()", + format!("{}.to_string()", snippet(cx, format_arg.span, ""))) + } + }; + span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { db.span_suggestion_with_applicability( expr.span, - "consider using .to_string()", + message, sugg, Applicability::MachineApplicable, ); @@ -113,9 +125,9 @@ fn check_single_piece(expr: &Expr) -> bool { /// ::std::fmt::Display::fmt)], /// } /// ``` -/// and that type of `__arg0` is `&str` or `String` -/// then returns the span of first element of the matched tuple -fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { +/// and that the type of `__arg0` is `&str` or `String`, +/// then returns the span of first element of the matched tuple. +fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> { if_chain! { if let ExprKind::AddrOf(_, ref expr) = expr.node; if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node; @@ -134,7 +146,7 @@ fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) { if let ExprKind::Tup(ref values) = match_expr.node { - return Some(values[0].span); + return Some(&values[0]); } } } diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 0162f34c085..858c9fc8de5 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -52,4 +52,8 @@ fn main() { format!("{:.10}", "foo"); // could not be "foo"[..10] format!("{:.prec$}", "foo", prec = 1); format!("{:.prec$}", "foo", prec = 10); + + format!("{}", 42.to_string()); + let x = std::path::PathBuf::from("/bar/foo/qux"); + format!("{}", x.display().to_string()); } diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index d77c99d90b8..520c1b79433 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -54,5 +54,21 @@ error: useless use of `format!` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to 7 previous errors +error: useless use of `format!` + --> $DIR/format.rs:56:5 + | +56 | format!("{}", 42.to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: useless use of `format!` + --> $DIR/format.rs:58:5 + | +58 | format!("{}", x.display().to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From fd5ea0ddf71b68cc9994da3c809b6b2e17b7b483 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 4 Oct 2018 16:34:41 +0200 Subject: resolve build warnings in clippy_lints/src/format.rs --- clippy_lints/src/format.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 30ad022f476..7e2e355c251 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -4,7 +4,6 @@ use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::rustc::ty; use crate::syntax::ast::LitKind; -use crate::syntax_pos::Span; use crate::utils::paths; use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; use crate::rustc_errors::Applicability; @@ -60,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node; then { let (message, sugg) = if_chain! { - if let ExprKind::MethodCall(ref path, ref span, ref expr) = format_arg.node; + if let ExprKind::MethodCall(ref path, _, _) = format_arg.node; if path.ident.as_interned_str() == "to_string"; then { ("`to_string()` is enough", -- cgit 1.4.1-3-g733a5 From c1db71dd8c1c2b61e39bd34f28fb7b5b1c355d65 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 4 Oct 2018 16:58:51 +0200 Subject: make sure travis fails when clippy does not build. Fixes #3260 --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 948eb23fe83..8aff93d480a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,11 +57,9 @@ script: export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - | if [ -z ${INTEGRATION} ]; then - ./ci/base-tests.sh - sleep 5 + ./ci/base-tests.sh && sleep 5 else - ./ci/integration-tests.sh - sleep 5 + ./ci/integration-tests.sh && sleep 5 fi after_success: | -- cgit 1.4.1-3-g733a5 From 7adf24ebb04641941e47a0582e61461163f929f4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 18:09:09 +0200 Subject: Improve docs of fn_to_numeric_cast Closes #2980 --- clippy_lints/src/types.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5d26e477c82..f39a26db509 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -722,9 +722,12 @@ declare_clippy_lint! { /// **What it does:** Checks for casts of function pointers to something other than usize /// /// **Why is this bad?** -/// Depending on the system architechture, casting a function pointer to something other than -/// `usize` will result in incorrect pointer addresses. -/// `usize` will always be able to store the function pointer on the given architechture. +/// Casting a function pointer to anything other than usize/isize is not portable across +/// architectures, because you end up losing bits if the target type is too small or end up with a +/// bunch of extra bits that waste space and add more instructions to the final binary than +/// strictly necessary for the problem +/// +/// Casting to isize also doesn't make sense since there are no signed addresses. /// /// **Example** /// -- cgit 1.4.1-3-g733a5 From c0ab8b2531f273f0ce93dc64df83d936fc505604 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 21:44:16 +0200 Subject: Reimplement the `fn_to_numeric_cast_with_truncation` lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/types.rs | 40 +++++- tests/ui/fn_to_numeric_cast.rs | 2 +- tests/ui/fn_to_numeric_cast.stderr | 142 +++++++++++++++++++++ tests/ui/fn_to_numeric_cast_with_truncation.rs | 23 ++++ tests/ui/fn_to_numeric_cast_with_truncation.stderr | 40 ++++++ 8 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 tests/ui/fn_to_numeric_cast.stderr create mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.rs create mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2373cb87eed..c9bea1e8ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -689,6 +689,7 @@ All notable changes to this project will be documented in this file. [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const [`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast +[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result diff --git a/README.md b/README.md index f332a3f645d..40ece34c6fa 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 279 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b181a4c17ca..3779b09ecf3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -698,6 +698,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::CAST_PTR_ALIGNMENT, types::CHAR_LIT_AS_U8, types::FN_TO_NUMERIC_CAST, + types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::OPTION_OPTION, @@ -791,6 +792,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { returns::NEEDLESS_RETURN, strings::STRING_LIT_AS_BYTES, types::FN_TO_NUMERIC_CAST, + types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f39a26db509..d3aa8de825b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -746,6 +746,32 @@ declare_clippy_lint! { "casting a function pointer to a numeric type other than usize" } +/// **What it does:** Checks for casts of a function pointer to a numeric type not wide enough to +/// store address. +/// +/// **Why is this bad?** +/// Such a cast discards some bits of the function's address. If this is intended, it would be more +/// clearly expressed by casting to usize first, then casting the usize to the intended type (with +/// a comment) to perform the truncation. +/// +/// **Example** +/// +/// ```rust +/// // Bad +/// fn fn1() -> i16 { 1 }; +/// let _ = fn1 as i32; +/// +/// // Better: Cast to usize first, then comment with the reason for the truncation +/// fn fn2() -> i16 { 1 }; +/// let fn_ptr = fn2 as usize; +/// let fn_ptr_truncated = fn_ptr as i32; +/// ``` +declare_clippy_lint! { + pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + style, + "casting a function pointer to a numeric type not wide enough to store the address" +} + /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 { @@ -1054,7 +1080,19 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { let from_snippet = snippet(cx, cast_expr.span, "x"); - if cast_to.sty != ty::Uint(UintTy::Usize) { + + let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); + if to_nbits < cx.tcx.data_layout.pointer_size.bits() { + span_lint_and_sugg( + cx, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + expr.span, + &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to), + "try", + format!("{} as usize", from_snippet) + ); + + } else if cast_to.sty != ty::Uint(UintTy::Usize) { span_lint_and_sugg( cx, FN_TO_NUMERIC_CAST, diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index d250af61847..6d0fd3d8ab8 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,6 +1,6 @@ #![feature(tool_lints)] -#[warn(clippy::fn_to_numeric_cast)] +#![warn(clippy::fn_to_numeric_cast)] fn foo() -> String { String::new() } diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr new file mode 100644 index 00000000000..be8bc9058b4 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -0,0 +1,142 @@ +error: casting function pointer `foo` to `i8` + --> $DIR/fn_to_numeric_cast.rs:8:13 + | +8 | let _ = foo as i8; + | ^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + +error: casting function pointer `foo` to `i16` + --> $DIR/fn_to_numeric_cast.rs:9:13 + | +9 | let _ = foo as i16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i32` + --> $DIR/fn_to_numeric_cast.rs:10:13 + | +10 | let _ = foo as i32; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i64` + --> $DIR/fn_to_numeric_cast.rs:11:13 + | +11 | let _ = foo as i64; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i128` + --> $DIR/fn_to_numeric_cast.rs:12:13 + | +12 | let _ = foo as i128; + | ^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `isize` + --> $DIR/fn_to_numeric_cast.rs:13:13 + | +13 | let _ = foo as isize; + | ^^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u8` + --> $DIR/fn_to_numeric_cast.rs:15:13 + | +15 | let _ = foo as u8; + | ^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u16` + --> $DIR/fn_to_numeric_cast.rs:16:13 + | +16 | let _ = foo as u16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u32` + --> $DIR/fn_to_numeric_cast.rs:17:13 + | +17 | let _ = foo as u32; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u64` + --> $DIR/fn_to_numeric_cast.rs:18:13 + | +18 | let _ = foo as u64; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u128` + --> $DIR/fn_to_numeric_cast.rs:19:13 + | +19 | let _ = foo as u128; + | ^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `abc` to `i8` + --> $DIR/fn_to_numeric_cast.rs:28:13 + | +28 | let _ = abc as i8; + | ^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i16` + --> $DIR/fn_to_numeric_cast.rs:29:13 + | +29 | let _ = abc as i16; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i32` + --> $DIR/fn_to_numeric_cast.rs:30:13 + | +30 | let _ = abc as i32; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i64` + --> $DIR/fn_to_numeric_cast.rs:31:13 + | +31 | let _ = abc as i64; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i128` + --> $DIR/fn_to_numeric_cast.rs:32:13 + | +32 | let _ = abc as i128; + | ^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `isize` + --> $DIR/fn_to_numeric_cast.rs:33:13 + | +33 | let _ = abc as isize; + | ^^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u8` + --> $DIR/fn_to_numeric_cast.rs:35:13 + | +35 | let _ = abc as u8; + | ^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u16` + --> $DIR/fn_to_numeric_cast.rs:36:13 + | +36 | let _ = abc as u16; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u32` + --> $DIR/fn_to_numeric_cast.rs:37:13 + | +37 | let _ = abc as u32; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u64` + --> $DIR/fn_to_numeric_cast.rs:38:13 + | +38 | let _ = abc as u64; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u128` + --> $DIR/fn_to_numeric_cast.rs:39:13 + | +39 | let _ = abc as u128; + | ^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `f` to `i32` + --> $DIR/fn_to_numeric_cast.rs:46:5 + | +46 | f as i32 + | ^^^^^^^^ help: try: `f as usize` + +error: aborting due to 23 previous errors + diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs new file mode 100644 index 00000000000..82bbaec201f --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_with_truncation.rs @@ -0,0 +1,23 @@ +#![feature(tool_lints)] + +#![warn(clippy::fn_to_numeric_cast_with_truncation)] +#![allow(clippy::fn_to_numeric_cast)] + +fn foo() -> String { String::new() } + +fn test_fn_to_numeric_cast_with_truncation() { + let _ = foo as i8; + let _ = foo as i16; + let _ = foo as i32; + let _ = foo as u8; + let _ = foo as u16; + let _ = foo as u32; + + // TODO: Is it bad to have these tests? + // Running the tests on a different architechture will + // produce different results + let _ = foo as u64; + let _ = foo as i64; +} + +fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr new file mode 100644 index 00000000000..cae4b6fbd40 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_with_truncation.stderr @@ -0,0 +1,40 @@ +error: casting function pointer `foo` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:9:13 + | +9 | let _ = foo as i8; + | ^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` + +error: casting function pointer `foo` to `i16`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 + | +10 | let _ = foo as i16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i32`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13 + | +11 | let _ = foo as i32; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13 + | +12 | let _ = foo as u8; + | ^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13 + | +13 | let _ = foo as u16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u32`, which truncates the value + --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13 + | +14 | let _ = foo as u32; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: aborting due to 6 previous errors + -- cgit 1.4.1-3-g733a5 From 391d53db6657be45fb85835c3e042e2287035ece Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 21:59:30 +0200 Subject: Add hidden lifetime parameters to fix warning --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d3aa8de825b..a27bbb40e6e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1076,7 +1076,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } } -fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty, cast_to: Ty) { +fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { let from_snippet = snippet(cx, cast_expr.span, "x"); -- cgit 1.4.1-3-g733a5 From 8b3d2073fa8b1f48a27081944c1a7010a8d7b7b1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 22:26:54 +0200 Subject: Only run tests if pointer width is 64bit If the pointer width of the architechture is 32bit or something else, then the tests will most likely produce different results. --- tests/ui/fn_to_numeric_cast_with_truncation.rs | 8 ++++-- tests/ui/fn_to_numeric_cast_with_truncation.stderr | 32 +++++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs index 82bbaec201f..4ebde4e8c1d 100644 --- a/tests/ui/fn_to_numeric_cast_with_truncation.rs +++ b/tests/ui/fn_to_numeric_cast_with_truncation.rs @@ -1,3 +1,4 @@ +// only-64bit #![feature(tool_lints)] #![warn(clippy::fn_to_numeric_cast_with_truncation)] @@ -13,11 +14,12 @@ fn test_fn_to_numeric_cast_with_truncation() { let _ = foo as u16; let _ = foo as u32; - // TODO: Is it bad to have these tests? - // Running the tests on a different architechture will - // produce different results + // These should not lint, because because casting to these types + // does not truncate the function pointer address. let _ = foo as u64; let _ = foo as i64; + let _ = foo as u128; + let _ = foo as i128; } fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr index cae4b6fbd40..65c996814ca 100644 --- a/tests/ui/fn_to_numeric_cast_with_truncation.stderr +++ b/tests/ui/fn_to_numeric_cast_with_truncation.stderr @@ -1,39 +1,39 @@ error: casting function pointer `foo` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:9:13 - | -9 | let _ = foo as i8; - | ^^^^^^^^^ help: try: `foo as usize` - | - = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` + --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 + | +10 | let _ = foo as i8; + | ^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` error: casting function pointer `foo` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13 | -10 | let _ = foo as i16; +11 | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13 | -11 | let _ = foo as i32; +12 | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13 | -12 | let _ = foo as u8; +13 | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13 | -13 | let _ = foo as u16; +14 | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:15:13 | -14 | let _ = foo as u32; +15 | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 163780ee0b41de143ec06181026ef575a736de2f Mon Sep 17 00:00:00 2001 From: Joel Gallant Date: Thu, 4 Oct 2018 17:30:45 -0600 Subject: Solves #3222 by checking the BareFnTy Abi type --- clippy_lints/src/types.rs | 3 ++- tests/ui/complex_types.rs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 857238e9002..6f024e59610 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -16,6 +16,7 @@ use std::borrow::Cow; use crate::syntax::ast::{FloatTy, IntTy, UintTy}; use crate::syntax::source_map::Span; use crate::syntax::errors::DiagnosticBuilder; +use crate::rustc_target::spec::abi::Abi; use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_macro, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; @@ -1224,7 +1225,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), // function types bring a lot of overhead - TyKind::BareFn(..) => (50 * self.nest, 1), + TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), TyKind::TraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index a6875793c83..eac2c07c12e 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -40,5 +40,22 @@ fn test3() { let _y: Vec>> = vec![]; } +#[repr(C)] +struct D { + // should not warn, since we don't have control over the signature (#3222) + test4: extern "C" fn( + itself: &D, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, + h: usize, + i: usize, + ), +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 8407957ec64b94740f86d2079dc2d433f7f85e6a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 5 Oct 2018 07:49:08 +0200 Subject: Fix fn_to_numeric_cast UI tests This collapses both lint tests into one file. Somehow allowing the other lint in the respective files did not work correctly. Maybe that's fixed as part of fixing #3198. --- tests/ui/fn_to_numeric_cast.rs | 3 +- tests/ui/fn_to_numeric_cast.stderr | 126 +++++++++++---------- tests/ui/fn_to_numeric_cast_with_truncation.rs | 25 ---- tests/ui/fn_to_numeric_cast_with_truncation.stderr | 40 ------- 4 files changed, 66 insertions(+), 128 deletions(-) delete mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.rs delete mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.stderr diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 6d0fd3d8ab8..fc8aa19dcf0 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,6 +1,7 @@ +// only-64bit #![feature(tool_lints)] -#![warn(clippy::fn_to_numeric_cast)] +#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] fn foo() -> String { String::new() } diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index be8bc9058b4..29320f0d8ed 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -1,141 +1,143 @@ -error: casting function pointer `foo` to `i8` - --> $DIR/fn_to_numeric_cast.rs:8:13 +error: casting function pointer `foo` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:9:13 | -8 | let _ = foo as i8; +9 | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` | - = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` -error: casting function pointer `foo` to `i16` - --> $DIR/fn_to_numeric_cast.rs:9:13 - | -9 | let _ = foo as i16; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: casting function pointer `foo` to `i32` +error: casting function pointer `foo` to `i16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:10:13 | -10 | let _ = foo as i32; +10 | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `i64` +error: casting function pointer `foo` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:11:13 | -11 | let _ = foo as i64; +11 | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `i128` +error: casting function pointer `foo` to `i64` --> $DIR/fn_to_numeric_cast.rs:12:13 | -12 | let _ = foo as i128; +12 | let _ = foo as i64; + | ^^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + +error: casting function pointer `foo` to `i128` + --> $DIR/fn_to_numeric_cast.rs:13:13 + | +13 | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> $DIR/fn_to_numeric_cast.rs:13:13 + --> $DIR/fn_to_numeric_cast.rs:14:13 | -13 | let _ = foo as isize; +14 | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u8` - --> $DIR/fn_to_numeric_cast.rs:15:13 +error: casting function pointer `foo` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:16:13 | -15 | let _ = foo as u8; +16 | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u16` - --> $DIR/fn_to_numeric_cast.rs:16:13 +error: casting function pointer `foo` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:17:13 | -16 | let _ = foo as u16; +17 | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u32` - --> $DIR/fn_to_numeric_cast.rs:17:13 +error: casting function pointer `foo` to `u32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:18:13 | -17 | let _ = foo as u32; +18 | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> $DIR/fn_to_numeric_cast.rs:18:13 + --> $DIR/fn_to_numeric_cast.rs:19:13 | -18 | let _ = foo as u64; +19 | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> $DIR/fn_to_numeric_cast.rs:19:13 + --> $DIR/fn_to_numeric_cast.rs:20:13 | -19 | let _ = foo as u128; +20 | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `abc` to `i8` - --> $DIR/fn_to_numeric_cast.rs:28:13 +error: casting function pointer `abc` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:29:13 | -28 | let _ = abc as i8; +29 | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `i16` - --> $DIR/fn_to_numeric_cast.rs:29:13 +error: casting function pointer `abc` to `i16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:30:13 | -29 | let _ = abc as i16; +30 | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `i32` - --> $DIR/fn_to_numeric_cast.rs:30:13 +error: casting function pointer `abc` to `i32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:31:13 | -30 | let _ = abc as i32; +31 | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> $DIR/fn_to_numeric_cast.rs:31:13 + --> $DIR/fn_to_numeric_cast.rs:32:13 | -31 | let _ = abc as i64; +32 | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> $DIR/fn_to_numeric_cast.rs:32:13 + --> $DIR/fn_to_numeric_cast.rs:33:13 | -32 | let _ = abc as i128; +33 | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> $DIR/fn_to_numeric_cast.rs:33:13 + --> $DIR/fn_to_numeric_cast.rs:34:13 | -33 | let _ = abc as isize; +34 | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u8` - --> $DIR/fn_to_numeric_cast.rs:35:13 +error: casting function pointer `abc` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:36:13 | -35 | let _ = abc as u8; +36 | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u16` - --> $DIR/fn_to_numeric_cast.rs:36:13 +error: casting function pointer `abc` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:37:13 | -36 | let _ = abc as u16; +37 | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u32` - --> $DIR/fn_to_numeric_cast.rs:37:13 +error: casting function pointer `abc` to `u32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:38:13 | -37 | let _ = abc as u32; +38 | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> $DIR/fn_to_numeric_cast.rs:38:13 + --> $DIR/fn_to_numeric_cast.rs:39:13 | -38 | let _ = abc as u64; +39 | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> $DIR/fn_to_numeric_cast.rs:39:13 + --> $DIR/fn_to_numeric_cast.rs:40:13 | -39 | let _ = abc as u128; +40 | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `f` to `i32` - --> $DIR/fn_to_numeric_cast.rs:46:5 +error: casting function pointer `f` to `i32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:47:5 | -46 | f as i32 +47 | f as i32 | ^^^^^^^^ help: try: `f as usize` error: aborting due to 23 previous errors diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs deleted file mode 100644 index 4ebde4e8c1d..00000000000 --- a/tests/ui/fn_to_numeric_cast_with_truncation.rs +++ /dev/null @@ -1,25 +0,0 @@ -// only-64bit -#![feature(tool_lints)] - -#![warn(clippy::fn_to_numeric_cast_with_truncation)] -#![allow(clippy::fn_to_numeric_cast)] - -fn foo() -> String { String::new() } - -fn test_fn_to_numeric_cast_with_truncation() { - let _ = foo as i8; - let _ = foo as i16; - let _ = foo as i32; - let _ = foo as u8; - let _ = foo as u16; - let _ = foo as u32; - - // These should not lint, because because casting to these types - // does not truncate the function pointer address. - let _ = foo as u64; - let _ = foo as i64; - let _ = foo as u128; - let _ = foo as i128; -} - -fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr deleted file mode 100644 index 65c996814ca..00000000000 --- a/tests/ui/fn_to_numeric_cast_with_truncation.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error: casting function pointer `foo` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 - | -10 | let _ = foo as i8; - | ^^^^^^^^^ help: try: `foo as usize` - | - = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` - -error: casting function pointer `foo` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13 - | -11 | let _ = foo as i16; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: casting function pointer `foo` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13 - | -12 | let _ = foo as i32; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: casting function pointer `foo` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13 - | -13 | let _ = foo as u8; - | ^^^^^^^^^ help: try: `foo as usize` - -error: casting function pointer `foo` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13 - | -14 | let _ = foo as u16; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: casting function pointer `foo` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:15:13 - | -15 | let _ = foo as u32; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: aborting due to 6 previous errors - -- cgit 1.4.1-3-g733a5 From e5b388d8650c5b42c9e5ed1dae53ab3211878af0 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 5 Oct 2018 08:02:44 +0200 Subject: Fix util/export.py to include lints from methods --- util/lintlib.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/util/lintlib.py b/util/lintlib.py index c386a94b18b..1c49ab770d5 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -72,10 +72,13 @@ def parse_lints(lints, filepath): g = group_re.search(line) if g: group = g.group(1).lower() - level = lint_levels[group] + level = lint_levels.get(group, None) break line = next(fp) + if level is None: + continue + log.info("found %s with level %s in %s", name, level, filepath) lints.append(Lint(name, level, last_comment, filepath, group)) @@ -103,9 +106,11 @@ def parse_configs(path): def parse_all(path="clippy_lints/src"): lints = [] - for filename in os.listdir(path): - if filename.endswith(".rs"): - parse_lints(lints, os.path.join(path, filename)) + for root, dirs, files in os.walk(path): + for fn in files: + if fn.endswith('.rs'): + parse_lints(lints, os.path.join(root, fn)) + log.info("got %s lints", len(lints)) configs = parse_configs(path) -- cgit 1.4.1-3-g733a5 From a3dc01edcc2fa0b2afa4b16dc94ce833b39fb8a2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 5 Oct 2018 12:01:52 +0200 Subject: travis: reenable osx --- .travis.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8aff93d480a..6d44c7faa93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ rust: nightly os: - linux - # - osx # doesn't even start atm. Not sure what travis is up to. Disabling to reduce the noise + - osx sudo: false @@ -32,7 +32,10 @@ install: matrix: include: - - env: BASE_TESTS=true # runs the base tests + - os: osx # run base tests on both platforms + env: BASE_TESTS=true + - os: linux + env: BASE_TESTS=true - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand - env: INTEGRATION=rust-lang-nursery/stdsimd @@ -46,6 +49,10 @@ matrix: - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom - env: INTEGRATION=hyperium/hyper +# prevent these jobs with default env vars + exclude: + - os: linux + - os: osx script: - | -- cgit 1.4.1-3-g733a5 From cd842736d97477218553c56b4919f8c2618671a9 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 5 Oct 2018 15:52:51 +0200 Subject: mini-macro: fix tests with latest rustc (rename feature: proc_macro_non_items -> proc_macro_hygiene). --- mini-macro/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 8a19dc2c4e5..01cdc70c72a 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro_quote, proc_macro_non_items)] +#![feature(proc_macro_quote, proc_macro_hygiene)] extern crate proc_macro; use proc_macro::{TokenStream, quote}; @@ -8,4 +8,4 @@ pub fn mini_macro(_: TokenStream) -> TokenStream { quote!( #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } ) -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From cbde8201c5f5d56c3bea9aa328a61f71a805138f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 5 Oct 2018 13:26:39 -0700 Subject: Remove unused utils --- clippy_lints/src/utils/mod.rs | 8 -------- clippy_lints/src/utils/paths.rs | 1 - 2 files changed, 9 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index fa3c72dbb7d..6c963cf205b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -957,14 +957,6 @@ pub fn get_arg_name(pat: &Pat) -> Option { } } -pub fn get_arg_ident(pat: &Pat) -> Option { - match pat.node { - PatKind::Binding(_, _, ident, None) => Some(ident), - PatKind::Ref(ref subpat, _) => get_arg_ident(subpat), - _ => None, - } -} - pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 { layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index eb28cc7e179..f2f1a4db375 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -12,7 +12,6 @@ pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"]; pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"]; pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; -pub const CLONE: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; -- cgit 1.4.1-3-g733a5 From 53d41e5c504b8dd535c25aaf2f0008fa525cbb9d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 5 Oct 2018 13:41:40 -0700 Subject: Rustup for https://github.com/rust-lang/rust/pull/54741 --- clippy_lints/src/lifetimes.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 62e308bb585..dbd433bc909 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -344,23 +344,20 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { self.record(&None); }, TyKind::Path(ref path) => { - if let QPath::Resolved(_, ref path) = *path { - if let Def::Existential(def_id) = path.def { - let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap(); - if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node { - for bound in &exist_ty.bounds { - if let GenericBound::Outlives(_) = *bound { - self.record(&None); - } - } - } else { - unreachable!() + + self.collect_anonymous_lifetimes(path, ty); + } + TyKind::Def(item, _) => { + if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(item.id).node { + for bound in &exist_ty.bounds { + if let GenericBound::Outlives(_) = *bound { + self.record(&None); } - walk_ty(self, ty); - return; } + } else { + unreachable!() } - self.collect_anonymous_lifetimes(path, ty); + walk_ty(self, ty); } TyKind::TraitObject(ref bounds, ref lt) => { if !lt.is_elided() { -- cgit 1.4.1-3-g733a5 From 8db20929234eab062fa4890e5587b00c411c6360 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 5 Oct 2018 12:34:15 -0700 Subject: Document relicensing process --- COPYRIGHT | 7 + etc/relicense/RELICENSE_DOCUMENTATION.md | 33 +++++ etc/relicense/contributors.txt | 232 +++++++++++++++++++++++++++++++ etc/relicense/relicense_comments.txt | 227 ++++++++++++++++++++++++++++++ 4 files changed, 499 insertions(+) create mode 100644 COPYRIGHT create mode 100644 etc/relicense/RELICENSE_DOCUMENTATION.md create mode 100644 etc/relicense/contributors.txt create mode 100644 etc/relicense/relicense_comments.txt diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000000..a7112226318 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,7 @@ +Copyright 2018 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 or the MIT license +, at your +option. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. diff --git a/etc/relicense/RELICENSE_DOCUMENTATION.md b/etc/relicense/RELICENSE_DOCUMENTATION.md new file mode 100644 index 00000000000..b40f748e9d0 --- /dev/null +++ b/etc/relicense/RELICENSE_DOCUMENTATION.md @@ -0,0 +1,33 @@ +This repository was previously licensed under MPL-2.0, however in #3093 ([archive](http://web.archive.org/web/20181005185227/https://github.com/rust-lang-nursery/rust-clippy/issues/3093), [screenshot](https://user-images.githubusercontent.com/1617736/46573505-5b856880-c94b-11e8-9a14-981c889b4981.png)) we relicensed it to the Rust license (dual licensed as Apache v2 / MIT) + +At the time, the contributors were those listed in contributors.txt. + +We opened a bunch of issues asking for an explicit relicensing approval. Screenshots of all these issues at the time of relicensing are archived on GitHub. We also have saved Wayback Machine copies of these: + + - #3094 ([archive](http://web.archive.org/web/20181005191247/https://github.com/rust-lang-nursery/rust-clippy/issues/3094), [screenshot](https://user-images.githubusercontent.com/1617736/46573506-5b856880-c94b-11e8-8a44-51cb40bc16ee.png)) + - #3095 ([archive](http://web.archive.org/web/20181005184416/https://github.com/rust-lang-nursery/rust-clippy/issues/3095), [screenshot](https://user-images.githubusercontent.com/1617736/46573507-5c1dff00-c94b-11e8-912a-4bd6b5f838f5.png)) + - #3096 ([archive](http://web.archive.org/web/20181005184802/https://github.com/rust-lang-nursery/rust-clippy/issues/3096), [screenshot](https://user-images.githubusercontent.com/1617736/46573508-5c1dff00-c94b-11e8-9425-2464f7260ff0.png)) + - #3097 ([archive](http://web.archive.org/web/20181005184821/https://github.com/rust-lang-nursery/rust-clippy/issues/3097), [screenshot](https://user-images.githubusercontent.com/1617736/46573509-5c1dff00-c94b-11e8-8ba2-53f687984fe7.png)) + - #3098 ([archive](http://web.archive.org/web/20181005184900/https://github.com/rust-lang-nursery/rust-clippy/issues/3098), [screenshot](https://user-images.githubusercontent.com/1617736/46573510-5c1dff00-c94b-11e8-8f64-371698401c60.png)) + - #3099 ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3099), [screenshot](https://user-images.githubusercontent.com/1617736/46573511-5c1dff00-c94b-11e8-8e20-7d0eeb392b95.png)) + - #3100 ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3100), [screenshot](https://user-images.githubusercontent.com/1617736/46573512-5c1dff00-c94b-11e8-8a13-7d758ed3563d.png)) + - #3230 ([archive](http://web.archive.org/web/20181005184903/https://github.com/rust-lang-nursery/rust-clippy/issues/3230), [screenshot](https://user-images.githubusercontent.com/1617736/46573513-5cb69580-c94b-11e8-86b1-14ce82741e5c.png)) + +The usernames of commenters on these issues can be found in relicense_comments.txt + +There are a couple people in relicense_comments.txt who are not found in contributors.txt: + + - @EpocSquadron has [made minor text contributions to the README](https://github.com/rust-lang-nursery/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and doesn't count + - @JayKickliter [agreed to the relicense on their pull request](https://github.com/rust-lang-nursery/rust-clippy/pull/3195#issuecomment-423781016) ([archive](https://web.archive.org/web/20181005190730/https://github.com/rust-lang-nursery/rust-clippy/pull/3195), [screenshot](https://user-images.githubusercontent.com/1617736/46573514-5cb69580-c94b-11e8-8ffb-05a5bd02e2cc.png) +) + - @sanmai-NL's [contribution](https://github.com/rust-lang-nursery/rust-clippy/commits?author=sanmai-NL) is a minor one-word addition which doesn't count for copyright assignment + - @zmt00's [contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=zmt00) are minor typo fixes and don't count + - @VKlayd has [nonminor contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=VKlayd) which we rewrote (see below) + - @wartman4404 has [nonminor contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=wartman4404) which we rewrote (see below) + + +Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251 ([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251), [screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png) +) + +First, I (Manishearth) removed the lints they had added. I then documented at a high level what the lints did in #3251, asking for co-maintainers who had not seen the code for the lints to rewrite them. #2814 was rewritten by @phansch, and #427 was rewritten by @oli-obk, who did not recall having previously seen the code they were rewriting. + diff --git a/etc/relicense/contributors.txt b/etc/relicense/contributors.txt new file mode 100644 index 00000000000..e81ebf21484 --- /dev/null +++ b/etc/relicense/contributors.txt @@ -0,0 +1,232 @@ +0ndorio +0xbsec +17cupsofcoffee +Aaron1011 +Aaronepower +aaudiber +afck +alexcrichton +AlexEne +alexeyzab +alexheretic +alexreg +alusch +andersk +aochagavia +apasel422 +Arnavion +AtheMathmo +auscompgeek +AVerm +badboy +Baelyk +BenoitZugmeyer +bestouff +birkenfeld +bjgill +bkchr +Bobo1239 +bood +bootandy +b-r-u +budziq +CAD97 +Caemor +camsteffen +carols10cents +CBenoit +cesarb +cgm616 +chrisduerr +chrisvittal +chyvonomys +clarcharr +clippered +commandline +cramertj +csmoe +ctjhoa +cuviper +CYBAI +darArch +DarkEld3r +dashed +daubaris +d-dorazio +debris +dereckson +detrumi +devonhollowood +dtolnay +durka +dwijnand +eddyb +elliottneilclark +elpiel +ensch +EpicatSupercell +EpocSquadron +erickt +estk +etaoins +F001 +fanzier +FauxFaux +fhartwig +flip1995 +Fraser999 +Frederick888 +frewsxcv +gbip +gendx +gibfahn +gnieto +gnzlbg +goodmanjonathan +guido4000 +GuillaumeGomez +Hanaasagi +hdhoang +HMPerson1 +hobofan +iKevinY +illicitonion +imp +inrustwetrust +ishitatsuyuki +Jascha-N +jayhardee9 +JayKickliter +JDemler +jedisct1 +jmquigs +joelgallant +joeratt +josephDunne +JoshMcguigan +joshtriplett +jugglerchris +karyon +Keats +kennytm +Kha +killercup +kimsnj +KitFreddura +koivunej +kraai +kvikas +LaurentMazare +letheed +llogiq +lo48576 +lpesk +lucab +luisbg +lukasstevens +Machtan +MaloJaffre +Manishearth +marcusklaas +mark-i-m +martiansideofthemoon +martinlindhe +mathstuf +mati865 +matthiaskrgr +mattyhall +mbrubeck +mcarton +memoryleak47 +messense +michaelrutherford +mikerite +mipli +mockersf +montrivo +mrecachinas +Mrmaxmeier +mrmonday +ms2300 +Ms2ger +musoke +nathan +Nemo157 +NiekGr +niklasf +nrc +nweston +o01eg +ogham +oli-obk +ordovicia +pengowen123 +pgerber +phansch +philipturnbull +pickfire +pietro +PixelPirate +pizzaiter +PSeitz +Pyriphlegethon +pythonesque +quininer +Rantanen +rcoh +reiner-dolp +reujab +Robzz +samueltardieu +sanmai-NL +sanxiyn +scott-linder +scottmcm +scurest +senden9 +shahn +shepmaster +shnewto +shssoichiro +siiptuo +sinkuu +skade +sourcefrog +sourcejedi +steveklabnik +sunfishcode +sunjay +swgillespie +Techcable +terry90 +theemathas +thekidxp +theotherphil +TimNN +TomasKralCZ +tomprince +topecongiro +tspiteri +Twisol +U007D +uHOOCCOOHu +untitaker +upsuper +utaal +utam0k +vi +VKlayd +Vlad-Shcherbina +vorner +wafflespeanut +wartman4404 +waywardmonkeys +yaahallo +yangby-cryptape +yati-sagade +ykrivopalov +ysimonson +zayenz +zmanian +zmbush +zmt00 diff --git a/etc/relicense/relicense_comments.txt b/etc/relicense/relicense_comments.txt new file mode 100644 index 00000000000..52c25eb201f --- /dev/null +++ b/etc/relicense/relicense_comments.txt @@ -0,0 +1,227 @@ +0ndorio +0xbsec +17cupsofcoffee +Aaron1011 +Aaronepower +aaudiber +afck +alexcrichton +AlexEne +alexeyzab +alexheretic +alexreg +alusch +andersk +aochagavia +apasel422 +Arnavion +AtheMathmo +auscompgeek +AVerm +badboy +Baelyk +BenoitZugmeyer +bestouff +birkenfeld +bjgill +bkchr +Bobo1239 +bood +bootandy +b-r-u +budziq +CAD97 +Caemor +camsteffen +carols10cents +CBenoit +cesarb +cgm616 +chrisduerr +chrisvittal +chyvonomys +clarcharr +clippered +commandline +cramertj +csmoe +ctjhoa +cuviper +CYBAI +darArch +DarkEld3r +dashed +daubaris +d-dorazio +debris +dereckson +detrumi +devonhollowood +dtolnay +durka +dwijnand +eddyb +elliottneilclark +elpiel +ensch +EpicatSupercell +erickt +estk +etaoins +F001 +fanzier +FauxFaux +fhartwig +flip1995 +Fraser999 +Frederick888 +frewsxcv +gbip +gendx +gibfahn +gnieto +gnzlbg +goodmanjonathan +guido4000 +GuillaumeGomez +Hanaasagi +hdhoang +HMPerson1 +hobofan +iKevinY +illicitonion +imp +inrustwetrust +ishitatsuyuki +Jascha-N +jayhardee9 +JDemler +jedisct1 +jmquigs +joelgallant +joeratt +josephDunne +JoshMcguigan +joshtriplett +jugglerchris +karyon +Keats +kennytm +Kha +killercup +kimsnj +KitFreddura +koivunej +kraai +kvikas +LaurentMazare +letheed +llogiq +lo48576 +lpesk +lucab +luisbg +lukasstevens +Machtan +MaloJaffre +Manishearth +marcusklaas +mark-i-m +martiansideofthemoon +martinlindhe +mathstuf +mati865 +matthiaskrgr +mattyhall +mbrubeck +mcarton +memoryleak47 +messense +michaelrutherford +mikerite +mipli +mockersf +montrivo +mrecachinas +Mrmaxmeier +mrmonday +ms2300 +Ms2ger +musoke +nathan +Nemo157 +NiekGr +niklasf +nrc +nweston +o01eg +ogham +oli-obk +ordovicia +pengowen123 +pgerber +phansch +philipturnbull +pickfire +pietro +PixelPirate +pizzaiter +PSeitz +Pyriphlegethon +pythonesque +quininer +Rantanen +rcoh +reiner-dolp +reujab +Robzz +samueltardieu +sanxiyn +scott-linder +scottmcm +scurest +senden9 +shahn +shepmaster +shnewto +shssoichiro +siiptuo +sinkuu +skade +sourcefrog +sourcejedi +steveklabnik +sunfishcode +sunjay +swgillespie +Techcable +terry90 +theemathas +thekidxp +theotherphil +TimNN +TomasKralCZ +tommilligan +tomprince +topecongiro +tspiteri +Twisol +U007D +uHOOCCOOHu +untitaker +upsuper +utaal +utam0k +vi +Vlad-Shcherbina +vorner +wafflespeanut +waywardmonkeys +yaahallo +yangby-cryptape +yati-sagade +ykrivopalov +ysimonson +zayenz +zmanian +zmbush -- cgit 1.4.1-3-g733a5 From ca437e81a730e2b449b50e00f3bb7f3d381f327d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 5 Oct 2018 12:37:50 -0700 Subject: Relicense clippy Documentation on relicensing in previous commit Fixes #2885 Also fixes #3093, fixes #3094, fixes 3095, fixes #3096, fixes #3097, fixes #3098, fixes #3099, fixes #3100, fixes #3230 --- Cargo.toml | 2 +- LICENSE | 373 ------------------------------------------------ LICENSE-APACHE | 201 ++++++++++++++++++++++++++ LICENSE-MIT | 23 +++ README.md | 2 +- clippy_dummy/Cargo.toml | 6 +- 6 files changed, 229 insertions(+), 378 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT diff --git a/Cargo.toml b/Cargo.toml index d765e09deef..518c2caf671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ authors = [ description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang-nursery/rust-clippy" readme = "README.md" -license = "MPL-2.0" +license = "MIT/Apache-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] build = "build.rs" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index a612ad9813b..00000000000 --- a/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000000..16fe87b06e8 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 00000000000..31aa79387f2 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 40ece34c6fa..e429454cf28 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) [![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) -[![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) +[![License: MIT/Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. diff --git a/clippy_dummy/Cargo.toml b/clippy_dummy/Cargo.toml index b9e3aa3bcdc..b53e89071ce 100644 --- a/clippy_dummy/Cargo.toml +++ b/clippy_dummy/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "clippy_dummy" # rename to clippy before publishing -version = "0.0.301" +name = "clippy" # rename to clippy before publishing +version = "0.0.302" authors = ["Manish Goregaokar "] edition = "2018" readme = "crates-readme.md" @@ -9,7 +9,7 @@ build = 'build.rs' repository = "https://github.com/rust-lang-nursery/rust-clippy" -license = "MPL-2.0" +license = "MIT/Apache-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -- cgit 1.4.1-3-g733a5 From e9c025ea70f9297836d62e0f0c959b9359a8035a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 6 Oct 2018 09:18:06 -0700 Subject: Add license header to Rust files --- build.rs | 10 + clippy_dev/src/lib.rs | 10 + clippy_dev/src/main.rs | 10 + clippy_dummy/build.rs | 10 + clippy_dummy/src/main.rs | 10 + clippy_lints/src/approx_const.rs | 10 + clippy_lints/src/arithmetic.rs | 10 + clippy_lints/src/assign_ops.rs | 10 + clippy_lints/src/attrs.rs | 10 + clippy_lints/src/bit_mask.rs | 10 + clippy_lints/src/blacklisted_name.rs | 10 + clippy_lints/src/block_in_if_condition.rs | 10 + clippy_lints/src/booleans.rs | 10 + clippy_lints/src/bytecount.rs | 10 + clippy_lints/src/collapsible_if.rs | 10 + clippy_lints/src/const_static_lifetime.rs | 10 + clippy_lints/src/consts.rs | 10 + clippy_lints/src/copies.rs | 10 + clippy_lints/src/copy_iterator.rs | 10 + clippy_lints/src/cyclomatic_complexity.rs | 10 + clippy_lints/src/default_trait_access.rs | 10 + clippy_lints/src/deprecated_lints.rs | 10 + clippy_lints/src/derive.rs | 10 + clippy_lints/src/doc.rs | 10 + clippy_lints/src/double_comparison.rs | 10 + clippy_lints/src/double_parens.rs | 10 + clippy_lints/src/drop_forget_ref.rs | 10 + clippy_lints/src/duration_subsec.rs | 10 + clippy_lints/src/else_if_without_else.rs | 10 + clippy_lints/src/empty_enum.rs | 10 + clippy_lints/src/entry.rs | 10 + clippy_lints/src/enum_clike.rs | 10 + clippy_lints/src/enum_glob_use.rs | 10 + clippy_lints/src/enum_variants.rs | 10 + clippy_lints/src/eq_op.rs | 10 + clippy_lints/src/erasing_op.rs | 10 + clippy_lints/src/escape.rs | 10 + clippy_lints/src/eta_reduction.rs | 10 + clippy_lints/src/eval_order_dependence.rs | 10 + clippy_lints/src/excessive_precision.rs | 10 + clippy_lints/src/explicit_write.rs | 10 + clippy_lints/src/fallible_impl_from.rs | 10 + clippy_lints/src/format.rs | 10 + clippy_lints/src/formatting.rs | 10 + clippy_lints/src/functions.rs | 10 + clippy_lints/src/identity_conversion.rs | 10 + clippy_lints/src/identity_op.rs | 10 + .../src/if_let_redundant_pattern_matching.rs | 10 + clippy_lints/src/if_not_else.rs | 10 + clippy_lints/src/indexing_slicing.rs | 10 + clippy_lints/src/infallible_destructuring_match.rs | 10 + clippy_lints/src/infinite_iter.rs | 10 + clippy_lints/src/inherent_impl.rs | 10 + clippy_lints/src/inline_fn_without_body.rs | 10 + clippy_lints/src/int_plus_one.rs | 10 + clippy_lints/src/invalid_ref.rs | 10 + clippy_lints/src/items_after_statements.rs | 10 + clippy_lints/src/large_enum_variant.rs | 10 + clippy_lints/src/len_zero.rs | 10 + clippy_lints/src/let_if_seq.rs | 10 + clippy_lints/src/lib.rs | 10 + clippy_lints/src/lifetimes.rs | 10 + clippy_lints/src/literal_representation.rs | 10 + clippy_lints/src/loops.rs | 10 + clippy_lints/src/map_clone.rs | 10 + clippy_lints/src/map_unit_fn.rs | 10 + clippy_lints/src/matches.rs | 10 + clippy_lints/src/mem_forget.rs | 10 + clippy_lints/src/mem_replace.rs | 10 + clippy_lints/src/methods/mod.rs | 10 + clippy_lints/src/methods/unnecessary_filter_map.rs | 10 + clippy_lints/src/minmax.rs | 10 + clippy_lints/src/misc.rs | 10 + clippy_lints/src/misc_early.rs | 10 + clippy_lints/src/missing_doc.rs | 10 + clippy_lints/src/missing_inline.rs | 10 + clippy_lints/src/multiple_crate_versions.rs | 10 + clippy_lints/src/mut_mut.rs | 10 + clippy_lints/src/mut_reference.rs | 10 + clippy_lints/src/mutex_atomic.rs | 10 + clippy_lints/src/needless_bool.rs | 10 + clippy_lints/src/needless_borrow.rs | 10 + clippy_lints/src/needless_borrowed_ref.rs | 10 + clippy_lints/src/needless_continue.rs | 10 + clippy_lints/src/needless_pass_by_value.rs | 10 + clippy_lints/src/needless_update.rs | 10 + clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 10 + clippy_lints/src/neg_multiply.rs | 10 + clippy_lints/src/new_without_default.rs | 10 + clippy_lints/src/no_effect.rs | 10 + clippy_lints/src/non_copy_const.rs | 10 + clippy_lints/src/non_expressive_names.rs | 10 + clippy_lints/src/ok_if_let.rs | 10 + clippy_lints/src/open_options.rs | 10 + clippy_lints/src/overflow_check_conditional.rs | 10 + clippy_lints/src/panic_unimplemented.rs | 10 + clippy_lints/src/partialeq_ne_impl.rs | 10 + clippy_lints/src/precedence.rs | 10 + clippy_lints/src/ptr.rs | 10 + clippy_lints/src/ptr_offset_with_cast.rs | 10 + clippy_lints/src/question_mark.rs | 10 + clippy_lints/src/ranges.rs | 10 + clippy_lints/src/redundant_field_names.rs | 10 + clippy_lints/src/reference.rs | 10 + clippy_lints/src/regex.rs | 10 + clippy_lints/src/replace_consts.rs | 10 + clippy_lints/src/returns.rs | 10 + clippy_lints/src/serde_api.rs | 10 + clippy_lints/src/shadow.rs | 10 + clippy_lints/src/strings.rs | 10 + clippy_lints/src/suspicious_trait_impl.rs | 10 + clippy_lints/src/swap.rs | 10 + clippy_lints/src/temporary_assignment.rs | 10 + clippy_lints/src/transmute.rs | 10 + clippy_lints/src/trivially_copy_pass_by_ref.rs | 10 + clippy_lints/src/types.rs | 10 + clippy_lints/src/unicode.rs | 10 + clippy_lints/src/unsafe_removed_from_name.rs | 10 + clippy_lints/src/unused_io_amount.rs | 10 + clippy_lints/src/unused_label.rs | 10 + clippy_lints/src/unwrap.rs | 10 + clippy_lints/src/use_self.rs | 10 + clippy_lints/src/utils/author.rs | 10 + clippy_lints/src/utils/camel_case.rs | 10 + clippy_lints/src/utils/comparisons.rs | 10 + clippy_lints/src/utils/conf.rs | 10 + clippy_lints/src/utils/constants.rs | 10 + clippy_lints/src/utils/higher.rs | 10 + clippy_lints/src/utils/hir_utils.rs | 10 + clippy_lints/src/utils/inspector.rs | 10 + clippy_lints/src/utils/internal_lints.rs | 10 + clippy_lints/src/utils/mod.rs | 10 + clippy_lints/src/utils/paths.rs | 10 + clippy_lints/src/utils/ptr.rs | 10 + clippy_lints/src/utils/sugg.rs | 10 + clippy_lints/src/utils/usage.rs | 10 + clippy_lints/src/vec.rs | 10 + clippy_lints/src/write.rs | 10 + clippy_lints/src/zero_div_zero.rs | 10 + clippy_workspace_tests/src/main.rs | 10 + clippy_workspace_tests/subcrate/src/lib.rs | 10 + mini-macro/src/lib.rs | 10 + rustc_tools_util/src/lib.rs | 10 + src/driver.rs | 10 + src/lib.rs | 10 + src/main.rs | 10 + tests/auxiliary/test_macro.rs | 10 + tests/compile-test.rs | 10 + tests/dogfood.rs | 10 + tests/matches.rs | 10 + tests/needless_continue_helpers.rs | 10 + tests/run-pass/associated-constant-ice.rs | 10 + tests/run-pass/cc_seme.rs | 10 + tests/run-pass/enum-glob-import-crate.rs | 10 + tests/run-pass/ice-1588.rs | 10 + tests/run-pass/ice-1782.rs | 10 + tests/run-pass/ice-1969.rs | 10 + tests/run-pass/ice-2499.rs | 10 + tests/run-pass/ice-2594.rs | 10 + tests/run-pass/ice-2727.rs | 10 + tests/run-pass/ice-2760.rs | 10 + tests/run-pass/ice-2774.rs | 10 + tests/run-pass/ice-2865.rs | 10 + tests/run-pass/ice-3151.rs | 10 + tests/run-pass/ice-700.rs | 10 + tests/run-pass/ice_exacte_size.rs | 10 + tests/run-pass/if_same_then_else.rs | 10 + tests/run-pass/issue-2862.rs | 10 + tests/run-pass/issue-825.rs | 10 + tests/run-pass/issues_loop_mut_cond.rs | 10 + tests/run-pass/match_same_arms_const.rs | 10 + tests/run-pass/mut_mut_macro.rs | 10 + tests/run-pass/needless_borrow_fp.rs | 10 + tests/run-pass/needless_lifetimes_impl_trait.rs | 10 + tests/run-pass/procedural_macro.rs | 10 + tests/run-pass/regressions.rs | 10 + tests/run-pass/returns.rs | 10 + tests/run-pass/single-match-else.rs | 10 + tests/run-pass/used_underscore_binding_macro.rs | 10 + tests/run-pass/whitelist/conf_whitelisted.rs | 10 + tests/ui-toml/bad_toml/conf_bad_toml.rs | 10 + tests/ui-toml/bad_toml_type/conf_bad_type.rs | 10 + .../toml_blacklist/conf_french_blacklisted_name.rs | 10 + .../conf_french_blacklisted_name.stderr | 36 +-- tests/ui-toml/toml_trivially_copy/test.rs | 10 + tests/ui-toml/toml_trivially_copy/test.stderr | 8 +- tests/ui-toml/toml_unknown_key/conf_unknown_key.rs | 10 + tests/ui/absurd-extreme-comparisons.rs | 10 + tests/ui/absurd-extreme-comparisons.stderr | 72 ++--- tests/ui/approx_const.rs | 10 + tests/ui/approx_const.stderr | 88 +++--- tests/ui/arithmetic.rs | 10 + tests/ui/arithmetic.stderr | 58 ++-- tests/ui/assign_ops.rs | 10 + tests/ui/assign_ops.stderr | 52 +-- tests/ui/assign_ops2.rs | 10 + tests/ui/assign_ops2.stderr | 100 +++--- tests/ui/attrs.rs | 10 + tests/ui/attrs.stderr | 20 +- tests/ui/author.rs | 10 + tests/ui/author/call.rs | 10 + tests/ui/author/for_loop.rs | 10 + tests/ui/author/matches.rs | 10 + tests/ui/author/matches.stderr | 20 +- tests/ui/bit_masks.rs | 10 + tests/ui/bit_masks.stderr | 68 ++-- tests/ui/blacklisted_name.rs | 10 + tests/ui/blacklisted_name.stderr | 64 ++-- tests/ui/block_in_if_condition.rs | 10 + tests/ui/block_in_if_condition.stderr | 26 +- tests/ui/bool_comparison.rs | 10 + tests/ui/bool_comparison.stderr | 32 +- tests/ui/booleans.rs | 10 + tests/ui/booleans.stderr | 132 ++++---- tests/ui/borrow_box.rs | 10 + tests/ui/borrow_box.stderr | 30 +- tests/ui/box_vec.rs | 10 + tests/ui/box_vec.stderr | 4 +- tests/ui/builtin-type-shadow.rs | 10 + tests/ui/builtin-type-shadow.stderr | 30 +- tests/ui/bytecount.rs | 10 + tests/ui/bytecount.stderr | 26 +- tests/ui/cast.rs | 10 + tests/ui/cast.stderr | 124 ++++---- tests/ui/cast_alignment.rs | 10 + tests/ui/cast_alignment.stderr | 8 +- tests/ui/cast_lossless_float.rs | 10 + tests/ui/cast_lossless_float.stderr | 56 ++-- tests/ui/cast_lossless_integer.rs | 10 + tests/ui/cast_lossless_integer.stderr | 92 +++--- tests/ui/cast_size.rs | 10 + tests/ui/cast_size.stderr | 96 +++--- tests/ui/char_lit_as_u8.rs | 10 + tests/ui/char_lit_as_u8.stderr | 16 +- tests/ui/checked_unwrap.rs | 10 + tests/ui/checked_unwrap.stderr | 244 +++++++-------- tests/ui/clone_on_copy_impl.rs | 10 + tests/ui/clone_on_copy_mut.rs | 10 + tests/ui/cmp_nan.rs | 10 + tests/ui/cmp_nan.stderr | 60 ++-- tests/ui/cmp_null.rs | 10 + tests/ui/cmp_null.stderr | 8 +- tests/ui/cmp_owned.rs | 10 + tests/ui/cmp_owned.stderr | 32 +- tests/ui/collapsible_if.rs | 10 + tests/ui/collapsible_if.stderr | 286 ++++++++--------- tests/ui/complex_types.rs | 10 + tests/ui/complex_types.stderr | 68 ++-- tests/ui/const_static_lifetime.rs | 10 + tests/ui/const_static_lifetime.stderr | 64 ++-- tests/ui/copies.rs | 10 + tests/ui/copies.stderr | 348 ++++++++++----------- tests/ui/copy_iterator.rs | 10 + tests/ui/copy_iterator.stderr | 14 +- tests/ui/cstring.rs | 10 + tests/ui/cstring.stderr | 22 +- tests/ui/cyclomatic_complexity.rs | 10 + tests/ui/cyclomatic_complexity.stderr | 262 ++++++++-------- tests/ui/cyclomatic_complexity_attr_used.rs | 10 + tests/ui/cyclomatic_complexity_attr_used.stderr | 16 +- tests/ui/decimal_literal_representation.rs | 10 + tests/ui/decimal_literal_representation.stderr | 20 +- tests/ui/default_trait_access.rs | 10 + tests/ui/default_trait_access.stderr | 32 +- tests/ui/deprecated.rs | 10 + tests/ui/deprecated.stderr | 36 +-- tests/ui/derive.rs | 10 + tests/ui/derive.stderr | 92 +++--- tests/ui/diverging_sub_expression.rs | 10 + tests/ui/diverging_sub_expression.stderr | 24 +- tests/ui/dlist.rs | 10 + tests/ui/dlist.stderr | 24 +- tests/ui/doc.rs | 10 + tests/ui/doc.stderr | 128 ++++---- tests/ui/double_comparison.rs | 10 + tests/ui/double_comparison.stderr | 44 +-- tests/ui/double_neg.rs | 10 + tests/ui/double_neg.stderr | 12 +- tests/ui/double_parens.rs | 10 + tests/ui/double_parens.stderr | 24 +- tests/ui/drop_forget_copy.rs | 10 + tests/ui/drop_forget_copy.stderr | 48 +-- tests/ui/drop_forget_ref.rs | 10 + tests/ui/drop_forget_ref.stderr | 144 ++++----- tests/ui/duplicate_underscore_argument.rs | 10 + tests/ui/duplicate_underscore_argument.stderr | 12 +- tests/ui/duration_subsec.rs | 10 + tests/ui/duration_subsec.stderr | 20 +- tests/ui/else_if_without_else.rs | 10 + tests/ui/else_if_without_else.stderr | 16 +- tests/ui/empty_enum.rs | 10 + tests/ui/empty_enum.stderr | 20 +- tests/ui/empty_line_after_outer_attribute.rs | 10 + tests/ui/empty_line_after_outer_attribute.stderr | 60 ++-- tests/ui/entry.rs | 10 + tests/ui/entry.stderr | 28 +- tests/ui/enum_glob_use.rs | 10 + tests/ui/enum_glob_use.stderr | 16 +- tests/ui/enum_variants.rs | 10 + tests/ui/enum_variants.stderr | 106 +++---- tests/ui/enums_clike.rs | 10 + tests/ui/enums_clike.stderr | 32 +- tests/ui/eq_op.rs | 10 + tests/ui/eq_op.stderr | 140 ++++----- tests/ui/erasing_op.rs | 10 + tests/ui/erasing_op.stderr | 20 +- tests/ui/escape_analysis.rs | 10 + tests/ui/eta.rs | 10 + tests/ui/eta.stderr | 36 +-- tests/ui/eval_order_dependence.rs | 10 + tests/ui/eval_order_dependence.stderr | 44 +-- tests/ui/excessive_precision.rs | 10 + tests/ui/excessive_precision.stderr | 72 ++--- tests/ui/explicit_write.rs | 10 + tests/ui/explicit_write.stderr | 24 +- tests/ui/fallible_impl_from.rs | 10 + tests/ui/fallible_impl_from.stderr | 84 ++--- tests/ui/filter_methods.rs | 10 + tests/ui/filter_methods.stderr | 32 +- tests/ui/float_cmp.rs | 10 + tests/ui/float_cmp.stderr | 24 +- tests/ui/float_cmp_const.rs | 10 + tests/ui/float_cmp_const.stderr | 56 ++-- tests/ui/fn_to_numeric_cast.rs | 10 + tests/ui/fn_to_numeric_cast.stderr | 100 +++--- tests/ui/for_loop.rs | 10 + tests/ui/for_loop.stderr | 314 +++++++++---------- tests/ui/format.rs | 10 + tests/ui/format.stderr | 36 +-- tests/ui/formatting.rs | 10 + tests/ui/formatting.stderr | 46 +-- tests/ui/functions.rs | 10 + tests/ui/functions.stderr | 50 +-- tests/ui/fxhash.rs | 10 + tests/ui/fxhash.stderr | 36 +-- tests/ui/get_unwrap.rs | 10 + tests/ui/get_unwrap.stderr | 48 +-- tests/ui/identity_conversion.rs | 10 + tests/ui/identity_conversion.stderr | 54 ++-- tests/ui/identity_op.rs | 10 + tests/ui/identity_op.stderr | 32 +- tests/ui/if_let_redundant_pattern_matching.rs | 10 + tests/ui/if_let_redundant_pattern_matching.stderr | 24 +- tests/ui/if_not_else.rs | 10 + tests/ui/if_not_else.stderr | 24 +- tests/ui/impl.rs | 10 + tests/ui/impl.stderr | 32 +- tests/ui/implicit_hasher.rs | 10 + tests/ui/implicit_hasher.stderr | 78 ++--- tests/ui/inconsistent_digit_grouping.rs | 10 + tests/ui/inconsistent_digit_grouping.stderr | 44 +-- tests/ui/indexing_slicing.rs | 10 + tests/ui/indexing_slicing.stderr | 148 ++++----- tests/ui/infallible_destructuring_match.rs | 10 + tests/ui/infallible_destructuring_match.stderr | 24 +- tests/ui/infinite_iter.rs | 10 + tests/ui/infinite_iter.stderr | 64 ++-- tests/ui/infinite_loop.rs | 10 + tests/ui/infinite_loop.stderr | 40 +-- tests/ui/inline_fn_without_body.rs | 10 + tests/ui/inline_fn_without_body.stderr | 26 +- tests/ui/int_plus_one.rs | 10 + tests/ui/int_plus_one.stderr | 24 +- tests/ui/invalid_ref.rs | 10 + tests/ui/invalid_ref.stderr | 24 +- tests/ui/invalid_upcast_comparisons.rs | 10 + tests/ui/invalid_upcast_comparisons.stderr | 108 +++---- tests/ui/issue-3145.rs | 10 + tests/ui/issue-3145.stderr | 8 +- tests/ui/issue_2356.rs | 10 + tests/ui/issue_2356.stderr | 8 +- tests/ui/item_after_statement.rs | 10 + tests/ui/item_after_statement.stderr | 8 +- tests/ui/large_digit_groups.rs | 10 + tests/ui/large_digit_groups.stderr | 52 +-- tests/ui/large_enum_variant.rs | 10 + tests/ui/large_enum_variant.stderr | 42 +-- tests/ui/len_zero.rs | 10 + tests/ui/len_zero.stderr | 118 +++---- tests/ui/let_if_seq.rs | 10 + tests/ui/let_if_seq.stderr | 48 +-- tests/ui/let_return.rs | 10 + tests/ui/let_return.stderr | 16 +- tests/ui/let_unit.rs | 10 + tests/ui/let_unit.stderr | 8 +- tests/ui/lifetimes.rs | 10 + tests/ui/lifetimes.stderr | 76 ++--- tests/ui/literals.rs | 10 + tests/ui/literals.stderr | 108 +++---- tests/ui/map_clone.rs | 10 + tests/ui/map_clone.stderr | 28 +- tests/ui/map_flatten.rs | 10 + tests/ui/map_flatten.stderr | 12 +- tests/ui/match_bool.rs | 10 + tests/ui/match_bool.stderr | 76 ++--- tests/ui/matches.rs | 10 + tests/ui/matches.stderr | 276 ++++++++-------- tests/ui/mem_forget.rs | 10 + tests/ui/mem_forget.stderr | 12 +- tests/ui/mem_replace.rs | 10 + tests/ui/mem_replace.stderr | 16 +- tests/ui/methods.rs | 10 + tests/ui/methods.stderr | 326 +++++++++---------- tests/ui/min_max.rs | 10 + tests/ui/min_max.stderr | 28 +- tests/ui/missing-doc.rs | 10 + tests/ui/missing-doc.stderr | 226 ++++++------- tests/ui/missing_inline.rs | 10 + tests/ui/missing_inline.stderr | 24 +- tests/ui/module_inception.rs | 10 + tests/ui/module_inception.stderr | 24 +- tests/ui/modulo_one.rs | 10 + tests/ui/modulo_one.stderr | 12 +- tests/ui/mut_from_ref.rs | 10 + tests/ui/mut_from_ref.stderr | 52 +-- tests/ui/mut_mut.rs | 10 + tests/ui/mut_mut.stderr | 38 +-- tests/ui/mut_range_bound.rs | 10 + tests/ui/mut_range_bound.stderr | 20 +- tests/ui/mut_reference.rs | 10 + tests/ui/mut_reference.stderr | 12 +- tests/ui/mutex_atomic.rs | 10 + tests/ui/mutex_atomic.stderr | 36 +-- tests/ui/needless_bool.rs | 10 + tests/ui/needless_bool.stderr | 52 +-- tests/ui/needless_borrow.rs | 10 + tests/ui/needless_borrow.stderr | 24 +- tests/ui/needless_borrowed_ref.rs | 10 + tests/ui/needless_borrowed_ref.stderr | 24 +- tests/ui/needless_collect.rs | 10 + tests/ui/needless_collect.stderr | 24 +- tests/ui/needless_continue.rs | 10 + tests/ui/needless_continue.stderr | 22 +- tests/ui/needless_pass_by_value.rs | 10 + tests/ui/needless_pass_by_value.stderr | 140 ++++----- tests/ui/needless_pass_by_value_proc_macro.rs | 10 + tests/ui/needless_range_loop.rs | 10 + tests/ui/needless_range_loop.stderr | 30 +- tests/ui/needless_return.rs | 10 + tests/ui/needless_return.stderr | 32 +- tests/ui/needless_update.rs | 10 + tests/ui/needless_update.stderr | 4 +- tests/ui/neg_cmp_op_on_partial_ord.rs | 10 + tests/ui/neg_cmp_op_on_partial_ord.stderr | 16 +- tests/ui/neg_multiply.rs | 10 + tests/ui/neg_multiply.stderr | 8 +- tests/ui/never_loop.rs | 10 + tests/ui/never_loop.stderr | 106 +++---- tests/ui/new_without_default.rs | 10 + tests/ui/new_without_default.stderr | 26 +- tests/ui/no_effect.rs | 10 + tests/ui/no_effect.stderr | 188 +++++------ tests/ui/non_copy_const.rs | 10 + tests/ui/non_copy_const.stderr | 188 +++++------ tests/ui/non_expressive_names.rs | 10 + tests/ui/non_expressive_names.stderr | 112 +++---- tests/ui/ok_expect.rs | 10 + tests/ui/ok_expect.stderr | 20 +- tests/ui/ok_if_let.rs | 10 + tests/ui/ok_if_let.stderr | 12 +- tests/ui/op_ref.rs | 10 + tests/ui/op_ref.stderr | 10 +- tests/ui/open_options.rs | 10 + tests/ui/open_options.stderr | 40 +-- tests/ui/option_map_unit_fn.rs | 10 + tests/ui/option_map_unit_fn.stderr | 138 ++++---- tests/ui/option_option.rs | 10 + tests/ui/option_option.stderr | 52 +-- tests/ui/overflow_check_conditional.rs | 10 + tests/ui/overflow_check_conditional.stderr | 32 +- tests/ui/panic_unimplemented.rs | 10 + tests/ui/panic_unimplemented.stderr | 28 +- tests/ui/partialeq_ne_impl.rs | 10 + tests/ui/partialeq_ne_impl.stderr | 4 +- tests/ui/patterns.rs | 10 + tests/ui/patterns.stderr | 4 +- tests/ui/precedence.rs | 10 + tests/ui/precedence.stderr | 36 +-- tests/ui/print.rs | 10 + tests/ui/print.stderr | 36 +-- tests/ui/print_literal.rs | 10 + tests/ui/print_literal.stderr | 56 ++-- tests/ui/print_with_newline.rs | 10 + tests/ui/print_with_newline.stderr | 32 +- tests/ui/println_empty_string.rs | 10 + tests/ui/println_empty_string.stderr | 20 +- tests/ui/ptr_arg.rs | 10 + tests/ui/ptr_arg.stderr | 56 ++-- tests/ui/ptr_offset_with_cast.rs | 10 + tests/ui/ptr_offset_with_cast.stderr | 8 +- tests/ui/question_mark.rs | 10 + tests/ui/question_mark.stderr | 26 +- tests/ui/range.rs | 10 + tests/ui/range.stderr | 24 +- tests/ui/range_plus_minus_one.rs | 10 + tests/ui/range_plus_minus_one.stderr | 32 +- tests/ui/redundant_closure_call.rs | 10 + tests/ui/redundant_closure_call.stderr | 24 +- tests/ui/redundant_field_names.rs | 10 + tests/ui/redundant_field_names.stderr | 28 +- tests/ui/reference.rs | 10 + tests/ui/reference.stderr | 44 +-- tests/ui/regex.rs | 10 + tests/ui/regex.stderr | 92 +++--- tests/ui/replace_consts.rs | 10 + tests/ui/replace_consts.stderr | 144 ++++----- tests/ui/result_map_unit_fn.rs | 10 + tests/ui/result_map_unit_fn.stderr | 114 +++---- tests/ui/serde.rs | 10 + tests/ui/serde.stderr | 12 +- tests/ui/shadow.rs | 10 + tests/ui/shadow.stderr | 92 +++--- tests/ui/short_circuit_statement.rs | 10 + tests/ui/short_circuit_statement.stderr | 28 +- tests/ui/single_char_pattern.rs | 10 + tests/ui/single_char_pattern.stderr | 88 +++--- tests/ui/single_match.rs | 10 + tests/ui/single_match.stderr | 50 +-- tests/ui/starts_ends_with.rs | 10 + tests/ui/starts_ends_with.stderr | 56 ++-- tests/ui/string_extend.rs | 10 + tests/ui/string_extend.stderr | 12 +- tests/ui/strings.rs | 10 + tests/ui/strings.stderr | 44 +-- tests/ui/stutter.rs | 10 + tests/ui/stutter.stderr | 32 +- tests/ui/suspicious_arithmetic_impl.rs | 10 + tests/ui/suspicious_arithmetic_impl.stderr | 8 +- tests/ui/swap.rs | 10 + tests/ui/swap.stderr | 52 +-- tests/ui/temporary_assignment.rs | 10 + tests/ui/temporary_assignment.stderr | 8 +- tests/ui/toplevel_ref_arg.rs | 10 + tests/ui/toplevel_ref_arg.stderr | 28 +- tests/ui/trailing_zeros.rs | 10 + tests/ui/trailing_zeros.stderr | 20 +- tests/ui/transmute.rs | 10 + tests/ui/transmute.stderr | 160 +++++----- tests/ui/transmute_32bit.rs | 10 + tests/ui/transmute_64bit.rs | 10 + tests/ui/transmute_64bit.stderr | 8 +- tests/ui/trivially_copy_pass_by_ref.rs | 10 + tests/ui/trivially_copy_pass_by_ref.stderr | 52 +-- tests/ui/ty_fn_sig.rs | 10 + tests/ui/types.rs | 10 + tests/ui/types.stderr | 12 +- tests/ui/unicode.rs | 10 + tests/ui/unicode.stderr | 24 +- tests/ui/unit_arg.rs | 10 + tests/ui/unit_arg.stderr | 42 +-- tests/ui/unit_cmp.rs | 10 + tests/ui/unit_cmp.stderr | 8 +- tests/ui/unnecessary_clone.rs | 10 + tests/ui/unnecessary_clone.stderr | 48 +-- tests/ui/unnecessary_filter_map.rs | 10 + tests/ui/unnecessary_filter_map.stderr | 44 +-- tests/ui/unnecessary_fold.rs | 10 + tests/ui/unnecessary_fold.stderr | 36 +-- tests/ui/unnecessary_ref.rs | 10 + tests/ui/unnecessary_ref.stderr | 8 +- tests/ui/unneeded_field_pattern.rs | 10 + tests/ui/unneeded_field_pattern.stderr | 8 +- tests/ui/unreadable_literal.rs | 10 + tests/ui/unreadable_literal.stderr | 44 +-- tests/ui/unsafe_removed_from_name.rs | 10 + tests/ui/unsafe_removed_from_name.stderr | 24 +- tests/ui/unused_io_amount.rs | 10 + tests/ui/unused_io_amount.stderr | 24 +- tests/ui/unused_labels.rs | 10 + tests/ui/unused_labels.stderr | 20 +- tests/ui/unused_lt.rs | 10 + tests/ui/unused_lt.stderr | 12 +- tests/ui/unwrap_or.rs | 10 + tests/ui/unwrap_or.stderr | 16 +- tests/ui/use_self.rs | 10 + tests/ui/use_self.stderr | 104 +++--- tests/ui/used_underscore_binding.rs | 10 + tests/ui/used_underscore_binding.stderr | 20 +- tests/ui/useless_asref.rs | 10 + tests/ui/useless_asref.stderr | 48 +-- tests/ui/useless_attribute.rs | 10 + tests/ui/useless_attribute.stderr | 20 +- tests/ui/vec.rs | 10 + tests/ui/vec.stderr | 24 +- tests/ui/while_loop.rs | 10 + tests/ui/while_loop.stderr | 112 +++---- tests/ui/write_literal.rs | 10 + tests/ui/write_literal.stderr | 56 ++-- tests/ui/write_with_newline.rs | 10 + tests/ui/write_with_newline.stderr | 16 +- tests/ui/writeln_empty_string.rs | 10 + tests/ui/writeln_empty_string.stderr | 8 +- tests/ui/wrong_self_convention.rs | 10 + tests/ui/wrong_self_convention.stderr | 48 +-- tests/ui/zero_div_zero.rs | 10 + tests/ui/zero_div_zero.stderr | 74 ++--- tests/ui/zero_ptr.rs | 10 + tests/ui/zero_ptr.stderr | 20 +- tests/versioncheck.rs | 10 + 599 files changed, 9468 insertions(+), 5508 deletions(-) mode change 100755 => 100644 tests/ui/author/call.rs diff --git a/build.rs b/build.rs index 146a8dae745..336f0295bdf 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap()); diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 2f91c987cb1..2087a4b0740 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::default_hash_types)] diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index f45c52e2271..28f831a9b1c 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + extern crate clap; extern crate clippy_dev; extern crate regex; diff --git a/clippy_dummy/build.rs b/clippy_dummy/build.rs index 97902feff86..b4ea0772ee5 100644 --- a/clippy_dummy/build.rs +++ b/clippy_dummy/build.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + extern crate term; fn main() { diff --git a/clippy_dummy/src/main.rs b/clippy_dummy/src/main.rs index a118834f1fd..878993d5c28 100644 --- a/clippy_dummy/src/main.rs +++ b/clippy_dummy/src/main.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { panic!("This shouldn't even compile") } diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 4d921daea8a..01cb03730b8 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::span_lint; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index bdf8d237c70..4d7e921567d 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::span_lint; use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index a05a4d55010..3fbac7bc153 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; use crate::utils::{higher, sugg}; use crate::rustc::hir; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index e192c3f2093..f463ce5fa35 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! checks for attributes use crate::reexport::*; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 7151e8db9aa..6ba6a182902 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 9d6005cd612..ecc9957b88f 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index c1b4b4575ab..129b8fe9e58 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use matches::matches; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 1201b4a0c64..f12859d90c3 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 7ec556b5d78..a61e823f959 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index b0fb058116f..85fdca1d421 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for if expressions that contain only an if expression. //! //! For example, the lint would catch: diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index bb9829ad3c9..4c49aee2850 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 4e09e039100..584060aeca3 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(clippy::float_cmp)] use crate::rustc::lint::LateContext; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 26669d8c4c2..ac73dc1f5d5 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty::Ty; diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 17f32c7bb45..f4d29433cb8 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use crate::rustc::hir::{Item, ItemKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index db85a3f3fda..7971d20d83f 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! calculate cyclomatic complexity and warn about overly complex functions use crate::rustc::cfg::CFG; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 5f2b1a29dc7..66d94e00d0d 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 983f347c56f..0067629bbd0 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + macro_rules! declare_deprecated_lint { (pub $name: ident, $_reason: expr) => { declare_lint!(pub $name, Allow, "deprecated lint") diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 21365f60586..792699fc0c5 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 19f2916cc5e..9c25e79aa71 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use itertools::Itertools; use pulldown_cmark; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index c692bffaff6..e151918c1fb 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Lint on unnecessary double comparisons. Some examples: use crate::rustc::hir::*; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 3b2ef4e8bb2..ffaf93bd7a1 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 1dbca5ed9ba..cac5d0da71d 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 709cbd27754..a679a97c2e7 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index da6e860e236..26ffef9ebe4 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on if expressions with an else if, but without a final else branch use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 48c96a0ffad..7ac33fd452e 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint when there is an enum with no variants use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 965d425b43d..75c43745207 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index b49322dcaf9..8fba45de8ce 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index d594406decf..ebd28ee2796 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on `use`ing all variants of an enum use crate::rustc::hir::*; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c68439d161b..8d708f01720 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on enum variants that are prefixed or suffixed by the same characters use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, Lint}; diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 7b9f2568da9..a454ea83695 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 7e313daffa4..7bfc2ef31d0 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::consts::{constant_simple, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 8af232420b1..0491cde4fed 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::hir::intravisit as visit; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 556f76af3a7..59c7f8a36db 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 068d6fb135f..31fae2d1967 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; use crate::rustc::ty; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 0ae228d1dea..9f8224cd2f0 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 888dca97928..b5a5d7e497d 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 146e2366552..07674ef2763 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 7e2e355c251..41046a98a34 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 92950706d88..7f5715ef691 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index d73c0710ba1..d087452d16d 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use matches::matches; use crate::rustc::hir::intravisit; use crate::rustc::hir; diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 5b1bd0ada7b..e9761616696 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 836e4fafba4..3f05f21e840 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::consts::{constant_simple, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index c9fbf1b0775..4ee8d9f0ca7 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 954f8543a87..e005eb40144 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 1010b53e09a..984d725898d 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index dabc167f37d..7bbbe72f91d 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index a15ec8c14bd..9c727dccd33 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 167259b7353..3fa442a3562 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on inherent implementations use crate::rustc::hir::*; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 881bebc2f60..bbd16eaeaf8 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! checks for `#[inline]` on trait methods without bodies use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 69a19e2fb01..4349b15f100 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on blocks unnecessarily using >= with a + 1 or - 1 use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 55de8998378..fe599192053 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index a12c9c400ba..57124e5d019 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint when items are used after statements use matches::matches; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index e8982d92b56..79ff0c84bce 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint when there is a large size difference between variants on an enum use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b126b8dbb93..defb5892e51 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::def_id::DefId; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 53d13407be3..4cee4f34a63 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3779b09ecf3..e4ad9fe9ca1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern:cargo-clippy #![feature(box_syntax)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index dbd433bc909..d1cf0da876b 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::reexport::*; use matches::matches; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 188ca157423..a123415cca9 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2c05d9a198f..b807e4fb9e1 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use itertools::Itertools; use crate::reexport::*; use crate::rustc::hir::*; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index e16a8af7641..c2bfcf18280 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 40b81e6fdb8..e620a1815ce 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index c1a65e756a9..e46615f4da2 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 7a07ecbf02c..dd2a1ca50e7 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::{Expr, ExprKind}; diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index fd22e3afe80..ff57571a948 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e0d858bd270..30c82e3969f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 0a3486df8bd..86889c4c7c4 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 293d301ebb4..222247307c8 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 0fa05de2841..a83fa75de69 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::reexport::*; use matches::matches; use crate::rustc::hir::*; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index d3e1ca93784..a2fd487078e 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 685f701ef8b..20da0e7a698 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // This file incorporates work covered by the following copyright and // permission notice: // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index dea3a81e50d..2f3819a2da4 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 9c10a929d6f..dbf8cbe16c2 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! lint on multiple versions of a crate being used use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index b3607d623b3..737d8bfd92c 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir; use crate::rustc::hir::intravisit; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 1bf06b9e20a..bdf8bf80c88 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty::{self, Ty}; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index f6caddab485..8ddaf692b7e 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for uses of mutex where an atomic value could be used //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 74b6647551a..f102b49d785 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for needless boolean results of if-else expressions //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 8a676be99ea..639358a7ce7 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for needless address of operations (`&`) //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 057a097f4b7..f40fbef6d2f 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for useless borrowed references. //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 0f7ea34f18a..6a39595f62e 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for continue statements in loops that are redundant. //! //! For example, the lint would catch diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 73d59d7a33c..39f519ac586 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use matches::matches; use crate::rustc::hir::*; use crate::rustc::hir::intravisit::FnKind; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 7c452bed0a3..3388c92e0ec 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 08ad4dd43c9..7cd14b9a2d6 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index f39cfc8d122..d3b72372c2f 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index e0b54620faf..9f2d29a1b63 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::def_id::DefId; use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 5ff0979670d..289b5591edc 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::def::Def; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 3b97e9d4a17..61b57db51d5 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for uses of const which the type is not Freeze (Cell-free). //! //! This lint is **deny** by default. diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 77642b4727c..ad4f52a528f 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LintArray, LintPass, EarlyContext, EarlyLintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::source_map::Span; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index cd97e485342..9a23b05b8d9 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 9133192549f..4f647d053e3 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index bdd87ad3a25..d0805896fb7 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 404f43312e5..003c9bdf084 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 7eb0c089726..d38e02d6326 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index e77a49266ba..1c5e8fcb964 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 86cb89f2de1..187d89cdd79 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Checks for usage of `&Vec[_]` and `&String`. use std::borrow::Cow; diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 261e5cccbdd..38a9bbf6d4c 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::{declare_tool_lint, hir, lint, lint_array}; use crate::utils; use std::fmt; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index ced0fe3ef50..0ec57e0be80 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c60ed3842d4..bc3125253a2 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 38cb4578d9e..526232f7853 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 1faacc79df0..79d30612cbd 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::syntax::ast::{Expr, ExprKind, UnOp}; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 41ff8a4bc0c..7a818c41fff 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use regex_syntax; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 05cca2ac338..ca17a032526 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 9ab6b50ada6..f4360802483 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index f2cfdf82d5b..5f8789016b5 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 4a989353600..16567535c90 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::reexport::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 54fced12425..f4798842205 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 78a2c2adeb3..af7ff8d938f 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 5de2f0e54a9..77a33e9eebb 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use matches::matches; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 7cde4eb48f3..292bf9fb6a4 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::{Expr, ExprKind}; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 69422056df5..0d49f5de265 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index baa9a8c3903..61a2a9ded44 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use std::cmp; use matches::matches; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 2e660088380..24b895b23a6 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(clippy::default_hash_types)] use crate::reexport::*; diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 83f9713b59e..a140b567f01 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index e6472eb50bf..cd9d649ed0a 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 82430a794b1..1bb819a74e3 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index a67164becfb..0b2237ac22b 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f8fe1b3bdfa..f7a2d0805fa 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 3b2659a6176..d770ea120eb 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8e8d40e28a9..6650dd67b4f 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. diff --git a/clippy_lints/src/utils/camel_case.rs b/clippy_lints/src/utils/camel_case.rs index e8a8d510fe5..2b60e2c32fa 100644 --- a/clippy_lints/src/utils/camel_case.rs +++ b/clippy_lints/src/utils/camel_case.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + /// Return the index of the character after the first camel-case component of /// `s`. pub fn camel_case_until(s: &str) -> usize { diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index bd90fe1bc0a..986802107c0 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Utility functions about comparison operators. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index d79a7743e0f..faf4e2702f0 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Read configurations files. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index b63be9b86c8..42da95a12ed 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! This module contains some useful constants. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index cfedad49f31..584a6df1cc6 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! This module contains functions for retrieve the original AST from lowered //! `hir`. diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2257fbf7743..bc55c22979b 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::consts::{constant_simple, constant_context}; use crate::rustc::lint::LateContext; use crate::rustc::hir::*; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 413c71ab27b..841aaaabdfa 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(clippy::print_stdout, clippy::use_debug)] //! checks for attributes diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 058f7ee2fab..3a0d056bbb5 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::{ match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6c963cf205b..7282e5064c3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::reexport::*; use matches::matches; use if_chain::if_chain; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index f2f1a4db375..12ef2f51d8c 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! This module contains paths to types and functions Clippy needs to know //! about. diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index a28e1c7fe9d..43ab0f064ac 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use std::borrow::Cow; use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 076907e4945..fecfc0c0789 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //! Contains utility functions to generate suggestions. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 826ca78e64b..d26ffc715e8 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::lint::LateContext; use crate::rustc::hir::def::Def; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 4c6060192cf..21a33bd143f 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index a367a04b2ba..05ddbfe6f84 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::utils::{snippet, span_lint, span_lint_and_sugg}; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 5ceff6d4aa0..779a6a59e54 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use crate::consts::{constant_simple, Constant}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_workspace_tests/src/main.rs b/clippy_workspace_tests/src/main.rs index f79c691f085..7af28f80b9b 100644 --- a/clippy_workspace_tests/src/main.rs +++ b/clippy_workspace_tests/src/main.rs @@ -1,2 +1,12 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { } diff --git a/clippy_workspace_tests/subcrate/src/lib.rs b/clippy_workspace_tests/subcrate/src/lib.rs index e69de29bb2d..fd694f68ca6 100644 --- a/clippy_workspace_tests/subcrate/src/lib.rs +++ b/clippy_workspace_tests/subcrate/src/lib.rs @@ -0,0 +1,10 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 01cdc70c72a..d326dd7e679 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(proc_macro_quote, proc_macro_hygiene)] extern crate proc_macro; diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 09d80072d66..0951a0dee28 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use std::env; #[macro_export] diff --git a/src/driver.rs b/src/driver.rs index 6c442e42d95..d2ed3cb1c26 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] diff --git a/src/lib.rs b/src/lib.rs index bfa44d08703..58158f92e65 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] diff --git a/src/main.rs b/src/main.rs index cf26549774c..11c259b4d6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] diff --git a/tests/auxiliary/test_macro.rs b/tests/auxiliary/test_macro.rs index 624ca892add..497fedff15e 100644 --- a/tests/auxiliary/test_macro.rs +++ b/tests/auxiliary/test_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + pub trait A {} macro_rules! __implicit_hasher_test_macro { diff --git a/tests/compile-test.rs b/tests/compile-test.rs index da5c5bd3227..c9d4f658935 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(test)] extern crate compiletest_rs as compiletest; diff --git a/tests/dogfood.rs b/tests/dogfood.rs index ff7452c7c10..0815b146677 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[test] fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { diff --git a/tests/matches.rs b/tests/matches.rs index 3b4910315f5..99b05e50c9f 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(rustc_private)] extern crate clippy_lints; diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 2f6f5c0a81c..662ae110845 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // Tests for the various helper functions used by the needless_continue diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs index 2c5c90683cc..bc9a0b3b6d5 100644 --- a/tests/run-pass/associated-constant-ice.rs +++ b/tests/run-pass/associated-constant-ice.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + pub trait Trait { const CONSTANT: u8; } diff --git a/tests/run-pass/cc_seme.rs b/tests/run-pass/cc_seme.rs index 1539d3c61bc..215b4096b56 100644 --- a/tests/run-pass/cc_seme.rs +++ b/tests/run-pass/cc_seme.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[allow(dead_code)] enum Baz { One, diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index 6014558a184..c1e1d9645d1 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::all)] diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index fcda3814e4a..db5a6629a2b 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::all)] diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs index fcd3e7cf530..2101b4d3037 100644 --- a/tests/run-pass/ice-1782.rs +++ b/tests/run-pass/ice-1782.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 43d6bd8bfbc..0b4a0f4dfbf 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::all)] diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index c6793a78529..9716e5500c7 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs index 7cd30b6d946..8bd77e3d6f0 100644 --- a/tests/run-pass/ice-2594.rs +++ b/tests/run-pass/ice-2594.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/run-pass/ice-2727.rs b/tests/run-pass/ice-2727.rs index 79c6f1c55db..420be4c7112 100644 --- a/tests/run-pass/ice-2727.rs +++ b/tests/run-pass/ice-2727.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + pub fn f(new: fn()) { new(); } diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index 2e9c6d527c4..ad517b84c2c 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused_variables, clippy::blacklisted_name, diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index 6b14a2b5e03..6ed09a4a008 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::collections::HashSet; diff --git a/tests/run-pass/ice-2865.rs b/tests/run-pass/ice-2865.rs index 430de25a29d..1713915745a 100644 --- a/tests/run-pass/ice-2865.rs +++ b/tests/run-pass/ice-2865.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[allow(dead_code)] struct Ice { size: String diff --git a/tests/run-pass/ice-3151.rs b/tests/run-pass/ice-3151.rs index 5ee83dac7b3..8e1b7b9a178 100644 --- a/tests/run-pass/ice-3151.rs +++ b/tests/run-pass/ice-3151.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[derive(Clone)] pub struct HashMap { hash_builder: S, diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index 3992af2c280..3252381e1fd 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::all)] diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index 3d25aa50499..8a905a401e5 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::all)] diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs index b7536e25028..4f0f581063a 100644 --- a/tests/run-pass/if_same_then_else.rs +++ b/tests/run-pass/if_same_then_else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::if_same_then_else)] diff --git a/tests/run-pass/issue-2862.rs b/tests/run-pass/issue-2862.rs index b35df667f27..298ce088cea 100644 --- a/tests/run-pass/issue-2862.rs +++ b/tests/run-pass/issue-2862.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + pub trait FooMap { fn map B>(&self, f: F) -> B; } diff --git a/tests/run-pass/issue-825.rs b/tests/run-pass/issue-825.rs index 79df259eadb..576d53757cf 100644 --- a/tests/run-pass/issue-825.rs +++ b/tests/run-pass/issue-825.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(warnings)] // this should compile in a reasonable amount of time diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs index 6ecd40b99b1..c3deae9bafd 100644 --- a/tests/run-pass/issues_loop_mut_cond.rs +++ b/tests/run-pass/issues_loop_mut_cond.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(dead_code)] /// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2596 diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs index 59b939f3e01..1e36baf059b 100644 --- a/tests/run-pass/match_same_arms_const.rs +++ b/tests/run-pass/match_same_arms_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::match_same_arms)] diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index bfb9cfc7170..afc3c9eda15 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs index 204968e48d0..6a70849d9ca 100644 --- a/tests/run-pass/needless_borrow_fp.rs +++ b/tests/run-pass/needless_borrow_fp.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[deny(clippy::all)] diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index f727b2547e3..b27bb284e21 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::needless_lifetimes)] diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index 2b7ff123ea6..a9c9dd06b42 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[macro_use] extern crate clippy_mini_macro_test; diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index aa4e16d3949..a589922218d 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::blacklisted_name)] diff --git a/tests/run-pass/returns.rs b/tests/run-pass/returns.rs index 882d3aa7f32..cc7678d603b 100644 --- a/tests/run-pass/returns.rs +++ b/tests/run-pass/returns.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[deny(warnings)] fn cfg_return() -> i32 { #[cfg(unix)] return 1; diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index 379a98fc3ec..54c282451b8 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::single_match_else)] diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index 73f48a96e77..b700ab90a68 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::useless_attribute)] //issue #2910 diff --git a/tests/run-pass/whitelist/conf_whitelisted.rs b/tests/run-pass/whitelist/conf_whitelisted.rs index f328e4d9d04..168f09a095a 100644 --- a/tests/run-pass/whitelist/conf_whitelisted.rs +++ b/tests/run-pass/whitelist/conf_whitelisted.rs @@ -1 +1,11 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs index 325688ac7da..10c0f0004e4 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.rs +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern: error reading Clippy's configuration file diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs index f97f5802b13..021a839d9ef 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.rs +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs index fe533f521d0..4f0cd1659f7 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr index 4229b711b0d..dd414657c28 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -1,45 +1,45 @@ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:9:9 - | -9 | fn test(toto: ()) {} - | ^^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` + --> $DIR/conf_french_blacklisted_name.rs:19:9 + | +19 | fn test(toto: ()) {} + | ^^^^ + | + = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:12:9 + --> $DIR/conf_french_blacklisted_name.rs:22:9 | -12 | let toto = 42; +22 | let toto = 42; | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:13:9 + --> $DIR/conf_french_blacklisted_name.rs:23:9 | -13 | let tata = 42; +23 | let tata = 42; | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:14:9 + --> $DIR/conf_french_blacklisted_name.rs:24:9 | -14 | let titi = 42; +24 | let titi = 42; | ^^^^ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:20:10 + --> $DIR/conf_french_blacklisted_name.rs:30:10 | -20 | (toto, Some(tata), titi @ Some(_)) => (), +30 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:20:21 + --> $DIR/conf_french_blacklisted_name.rs:30:21 | -20 | (toto, Some(tata), titi @ Some(_)) => (), +30 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:20:28 + --> $DIR/conf_french_blacklisted_name.rs:30:28 | -20 | (toto, Some(tata), titi @ Some(_)) => (), +30 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 074ca064ab5..081dbf9b060 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::many_single_char_names)] diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index cf2f15a68e6..ad3ca831fd7 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,15 +1,15 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:13:11 + --> $DIR/test.rs:23:11 | -13 | fn bad(x: &u16, y: &Foo) { +23 | fn bad(x: &u16, y: &Foo) { | ^^^^ help: consider passing by value instead: `u16` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:13:20 + --> $DIR/test.rs:23:20 | -13 | fn bad(x: &u16, y: &Foo) { +23 | fn bad(x: &u16, y: &Foo) { | ^^^^ help: consider passing by value instead: `Foo` error: aborting due to 2 previous errors diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index bfa804558bb..60e8e4fc29a 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // error-pattern: error reading Clippy's configuration file: unknown key `foobar` diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index d08c8008ec9..a88e57a5c43 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 2e5ebec7573..6c32b309aa5 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -1,144 +1,144 @@ error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:10:5 + --> $DIR/absurd-extreme-comparisons.rs:20:5 | -10 | u <= 0; +20 | u <= 0; | ^^^^^^ | = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings` = help: because 0 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:11:5 + --> $DIR/absurd-extreme-comparisons.rs:21:5 | -11 | u <= Z; +21 | u <= Z; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == Z instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:12:5 + --> $DIR/absurd-extreme-comparisons.rs:22:5 | -12 | u < Z; +22 | u < Z; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:13:5 + --> $DIR/absurd-extreme-comparisons.rs:23:5 | -13 | Z >= u; +23 | Z >= u; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using Z == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:14:5 + --> $DIR/absurd-extreme-comparisons.rs:24:5 | -14 | Z > u; +24 | Z > u; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:15:5 + --> $DIR/absurd-extreme-comparisons.rs:25:5 | -15 | u > std::u32::MAX; +25 | u > std::u32::MAX; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:16:5 + --> $DIR/absurd-extreme-comparisons.rs:26:5 | -16 | u >= std::u32::MAX; +26 | u >= std::u32::MAX; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == std::u32::MAX instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:17:5 + --> $DIR/absurd-extreme-comparisons.rs:27:5 | -17 | std::u32::MAX < u; +27 | std::u32::MAX < u; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:18:5 + --> $DIR/absurd-extreme-comparisons.rs:28:5 | -18 | std::u32::MAX <= u; +28 | std::u32::MAX <= u; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using std::u32::MAX == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:19:5 + --> $DIR/absurd-extreme-comparisons.rs:29:5 | -19 | 1-1 > u; +29 | 1-1 > u; | ^^^^^^^ | = help: because 1-1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:20:5 + --> $DIR/absurd-extreme-comparisons.rs:30:5 | -20 | u >= !0; +30 | u >= !0; | ^^^^^^^ | = help: because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:21:5 + --> $DIR/absurd-extreme-comparisons.rs:31:5 | -21 | u <= 12 - 2*6; +31 | u <= 12 - 2*6; | ^^^^^^^^^^^^^ | = help: because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:23:5 + --> $DIR/absurd-extreme-comparisons.rs:33:5 | -23 | i < -127 - 1; +33 | i < -127 - 1; | ^^^^^^^^^^^^ | = help: because -127 - 1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:24:5 + --> $DIR/absurd-extreme-comparisons.rs:34:5 | -24 | std::i8::MAX >= i; +34 | std::i8::MAX >= i; | ^^^^^^^^^^^^^^^^^ | = help: because std::i8::MAX is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:25:5 + --> $DIR/absurd-extreme-comparisons.rs:35:5 | -25 | 3-7 < std::i32::MIN; +35 | 3-7 < std::i32::MIN; | ^^^^^^^^^^^^^^^^^^^ | = help: because std::i32::MIN is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:27:5 + --> $DIR/absurd-extreme-comparisons.rs:37:5 | -27 | b >= true; +37 | b >= true; | ^^^^^^^^^ | = help: because true is the maximum value for this type, the case where the two sides are not equal never occurs, consider using b == true instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:28:5 + --> $DIR/absurd-extreme-comparisons.rs:38:5 | -28 | false > b; +38 | false > b; | ^^^^^^^^^ | = help: because false is the minimum value for this type, this comparison is always false error: <-comparison of unit values detected. This will always be false - --> $DIR/absurd-extreme-comparisons.rs:31:5 + --> $DIR/absurd-extreme-comparisons.rs:41:5 | -31 | () < {}; +41 | () < {}; | ^^^^^^^ | = note: #[deny(clippy::unit_cmp)] on by default diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 46ca2fbfb57..ea023b8a7a2 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index 3ff016b9c40..a765ffb64de 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -1,117 +1,117 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:7:16 - | -7 | let my_e = 2.7182; - | ^^^^^^ - | - = note: `-D clippy::approx-constant` implied by `-D warnings` + --> $DIR/approx_const.rs:17:16 + | +17 | let my_e = 2.7182; + | ^^^^^^ + | + = note: `-D clippy::approx-constant` implied by `-D warnings` error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:8:20 - | -8 | let almost_e = 2.718; - | ^^^^^ + --> $DIR/approx_const.rs:18:20 + | +18 | let almost_e = 2.718; + | ^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly - --> $DIR/approx_const.rs:11:24 + --> $DIR/approx_const.rs:21:24 | -11 | let my_1_frac_pi = 0.3183; +21 | let my_1_frac_pi = 0.3183; | ^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:14:28 + --> $DIR/approx_const.rs:24:28 | -14 | let my_frac_1_sqrt_2 = 0.70710678; +24 | let my_frac_1_sqrt_2 = 0.70710678; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:15:32 + --> $DIR/approx_const.rs:25:32 | -15 | let almost_frac_1_sqrt_2 = 0.70711; +25 | let almost_frac_1_sqrt_2 = 0.70711; | ^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly - --> $DIR/approx_const.rs:18:24 + --> $DIR/approx_const.rs:28:24 | -18 | let my_frac_2_pi = 0.63661977; +28 | let my_frac_2_pi = 0.63661977; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly - --> $DIR/approx_const.rs:21:27 + --> $DIR/approx_const.rs:31:27 | -21 | let my_frac_2_sq_pi = 1.128379; +31 | let my_frac_2_sq_pi = 1.128379; | ^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly - --> $DIR/approx_const.rs:24:24 + --> $DIR/approx_const.rs:34:24 | -24 | let my_frac_pi_2 = 1.57079632679; +34 | let my_frac_pi_2 = 1.57079632679; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly - --> $DIR/approx_const.rs:27:24 + --> $DIR/approx_const.rs:37:24 | -27 | let my_frac_pi_3 = 1.04719755119; +37 | let my_frac_pi_3 = 1.04719755119; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly - --> $DIR/approx_const.rs:30:24 + --> $DIR/approx_const.rs:40:24 | -30 | let my_frac_pi_4 = 0.785398163397; +40 | let my_frac_pi_4 = 0.785398163397; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly - --> $DIR/approx_const.rs:33:24 + --> $DIR/approx_const.rs:43:24 | -33 | let my_frac_pi_6 = 0.523598775598; +43 | let my_frac_pi_6 = 0.523598775598; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly - --> $DIR/approx_const.rs:36:24 + --> $DIR/approx_const.rs:46:24 | -36 | let my_frac_pi_8 = 0.3926990816987; +46 | let my_frac_pi_8 = 0.3926990816987; | ^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly - --> $DIR/approx_const.rs:39:20 + --> $DIR/approx_const.rs:49:20 | -39 | let my_ln_10 = 2.302585092994046; +49 | let my_ln_10 = 2.302585092994046; | ^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly - --> $DIR/approx_const.rs:42:19 + --> $DIR/approx_const.rs:52:19 | -42 | let my_ln_2 = 0.6931471805599453; +52 | let my_ln_2 = 0.6931471805599453; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly - --> $DIR/approx_const.rs:45:22 + --> $DIR/approx_const.rs:55:22 | -45 | let my_log10_e = 0.4342944819032518; +55 | let my_log10_e = 0.4342944819032518; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly - --> $DIR/approx_const.rs:48:21 + --> $DIR/approx_const.rs:58:21 | -48 | let my_log2_e = 1.4426950408889634; +58 | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:51:17 + --> $DIR/approx_const.rs:61:17 | -51 | let my_pi = 3.1415; +61 | let my_pi = 3.1415; | ^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:52:21 + --> $DIR/approx_const.rs:62:21 | -52 | let almost_pi = 3.14; +62 | let almost_pi = 3.14; | ^^^^ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:55:18 + --> $DIR/approx_const.rs:65:18 | -55 | let my_sq2 = 1.4142; +65 | let my_sq2 = 1.4142; | ^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index e7aa9a18b8a..a5bf8c9280e 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index ee7a594fa15..5e6021403e9 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,72 +1,72 @@ error: integer arithmetic detected - --> $DIR/arithmetic.rs:8:5 - | -8 | 1 + i; - | ^^^^^ - | - = note: `-D clippy::integer-arithmetic` implied by `-D warnings` + --> $DIR/arithmetic.rs:18:5 + | +18 | 1 + i; + | ^^^^^ + | + = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/arithmetic.rs:9:5 - | -9 | i * 2; - | ^^^^^ + --> $DIR/arithmetic.rs:19:5 + | +19 | i * 2; + | ^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:10:5 + --> $DIR/arithmetic.rs:20:5 | -10 | / 1 % -11 | | i / 2; // no error, this is part of the expression in the preceding line +20 | / 1 % +21 | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:12:5 + --> $DIR/arithmetic.rs:22:5 | -12 | i - 2 + 2 - i; +22 | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:13:5 + --> $DIR/arithmetic.rs:23:5 | -13 | -i; +23 | -i; | ^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:23:5 + --> $DIR/arithmetic.rs:33:5 | -23 | f * 2.0; +33 | f * 2.0; | ^^^^^^^ | = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:25:5 + --> $DIR/arithmetic.rs:35:5 | -25 | 1.0 + f; +35 | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:26:5 + --> $DIR/arithmetic.rs:36:5 | -26 | f * 2.0; +36 | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:27:5 + --> $DIR/arithmetic.rs:37:5 | -27 | f / 2.0; +37 | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:28:5 + --> $DIR/arithmetic.rs:38:5 | -28 | f - 2.0 * 4.2; +38 | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:29:5 + --> $DIR/arithmetic.rs:39:5 | -29 | -f; +39 | -f; | ^^ error: aborting due to 11 previous errors diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 765dbb67990..5d791ba8f54 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[allow(dead_code, unused_assignments)] diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index fe7ccff7805..20ed51334ab 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,57 +1,57 @@ error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:7:5 - | -7 | a = a + 1; - | ^^^^^^^^^ help: replace it with: `a += 1` - | - = note: `-D clippy::assign-op-pattern` implied by `-D warnings` + --> $DIR/assign_ops.rs:17:5 + | +17 | a = a + 1; + | ^^^^^^^^^ help: replace it with: `a += 1` + | + = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:8:5 - | -8 | a = 1 + a; - | ^^^^^^^^^ help: replace it with: `a += 1` + --> $DIR/assign_ops.rs:18:5 + | +18 | a = 1 + a; + | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:9:5 - | -9 | a = a - 1; - | ^^^^^^^^^ help: replace it with: `a -= 1` + --> $DIR/assign_ops.rs:19:5 + | +19 | a = a - 1; + | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:10:5 + --> $DIR/assign_ops.rs:20:5 | -10 | a = a * 99; +20 | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:11:5 + --> $DIR/assign_ops.rs:21:5 | -11 | a = 42 * a; +21 | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:12:5 + --> $DIR/assign_ops.rs:22:5 | -12 | a = a / 2; +22 | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:13:5 + --> $DIR/assign_ops.rs:23:5 | -13 | a = a % 5; +23 | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:14:5 + --> $DIR/assign_ops.rs:24:5 | -14 | a = a & 1; +24 | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:20:5 + --> $DIR/assign_ops.rs:30:5 | -20 | s = s + "bla"; +30 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: aborting due to 9 previous errors diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index c3f5083bb1f..9eef898c9a7 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 93528e50577..8e44fc13bb7 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -1,129 +1,129 @@ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:8:5 - | -8 | a += a + 1; - | ^^^^^^^^^^ - | - = note: `-D clippy::misrefactored-assign-op` implied by `-D warnings` + --> $DIR/assign_ops2.rs:18:5 + | +18 | a += a + 1; + | ^^^^^^^^^^ + | + = note: `-D clippy::misrefactored-assign-op` implied by `-D warnings` help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with - | -8 | a += 1; - | ^^^^^^ + | +18 | a += 1; + | ^^^^^^ help: or - | -8 | a = a + a + 1; - | ^^^^^^^^^^^^^ + | +18 | a = a + a + 1; + | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:9:5 - | -9 | a += 1 + a; - | ^^^^^^^^^^ + --> $DIR/assign_ops2.rs:19:5 + | +19 | a += 1 + a; + | ^^^^^^^^^^ help: Did you mean a = a + 1 or a = a + 1 + a? Consider replacing it with - | -9 | a += 1; - | ^^^^^^ + | +19 | a += 1; + | ^^^^^^ help: or - | -9 | a = a + 1 + a; - | ^^^^^^^^^^^^^ + | +19 | a = a + 1 + a; + | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:10:5 + --> $DIR/assign_ops2.rs:20:5 | -10 | a -= a - 1; +20 | a -= a - 1; | ^^^^^^^^^^ help: Did you mean a = a - 1 or a = a - (a - 1)? Consider replacing it with | -10 | a -= 1; +20 | a -= 1; | ^^^^^^ help: or | -10 | a = a - (a - 1); +20 | a = a - (a - 1); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:11:5 + --> $DIR/assign_ops2.rs:21:5 | -11 | a *= a * 99; +21 | a *= a * 99; | ^^^^^^^^^^^ help: Did you mean a = a * 99 or a = a * a * 99? Consider replacing it with | -11 | a *= 99; +21 | a *= 99; | ^^^^^^^ help: or | -11 | a = a * a * 99; +21 | a = a * a * 99; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:12:5 + --> $DIR/assign_ops2.rs:22:5 | -12 | a *= 42 * a; +22 | a *= 42 * a; | ^^^^^^^^^^^ help: Did you mean a = a * 42 or a = a * 42 * a? Consider replacing it with | -12 | a *= 42; +22 | a *= 42; | ^^^^^^^ help: or | -12 | a = a * 42 * a; +22 | a = a * 42 * a; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:13:5 + --> $DIR/assign_ops2.rs:23:5 | -13 | a /= a / 2; +23 | a /= a / 2; | ^^^^^^^^^^ help: Did you mean a = a / 2 or a = a / (a / 2)? Consider replacing it with | -13 | a /= 2; +23 | a /= 2; | ^^^^^^ help: or | -13 | a = a / (a / 2); +23 | a = a / (a / 2); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:14:5 + --> $DIR/assign_ops2.rs:24:5 | -14 | a %= a % 5; +24 | a %= a % 5; | ^^^^^^^^^^ help: Did you mean a = a % 5 or a = a % (a % 5)? Consider replacing it with | -14 | a %= 5; +24 | a %= 5; | ^^^^^^ help: or | -14 | a = a % (a % 5); +24 | a = a % (a % 5); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:15:5 + --> $DIR/assign_ops2.rs:25:5 | -15 | a &= a & 1; +25 | a &= a & 1; | ^^^^^^^^^^ help: Did you mean a = a & 1 or a = a & a & 1? Consider replacing it with | -15 | a &= 1; +25 | a &= 1; | ^^^^^^ help: or | -15 | a = a & a & 1; +25 | a = a & a & 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:16:5 + --> $DIR/assign_ops2.rs:26:5 | -16 | a *= a * a; +26 | a *= a * a; | ^^^^^^^^^^ help: Did you mean a = a * a or a = a * a * a? Consider replacing it with | -16 | a *= a; +26 | a *= a; | ^^^^^^ help: or | -16 | a = a * a * a; +26 | a = a * a * a; | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index b1f0ca640aa..9af9c0e619a 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index 6b6ecd675b3..a361d0968f5 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,23 +1,23 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> $DIR/attrs.rs:6:1 - | -6 | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::inline-always` implied by `-D warnings` + --> $DIR/attrs.rs:16:1 + | +16 | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:27:14 + --> $DIR/attrs.rs:37:14 | -27 | #[deprecated(since = "forever")] +37 | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:30:14 + --> $DIR/attrs.rs:40:14 | -30 | #[deprecated(since = "1")] +40 | #[deprecated(since = "1")] | ^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/author.rs b/tests/ui/author.rs index e8a04bb7b13..f151d50f2f2 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs old mode 100755 new mode 100644 index c3e9846e21c..3dcf8da5c72 --- a/tests/ui/author/call.rs +++ b/tests/ui/author/call.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index b3dec876535..a27322b3205 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(stmt_expr_attributes)] fn main() { diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs index e6bf229103f..956404f3490 100644 --- a/tests/ui/author/matches.rs +++ b/tests/ui/author/matches.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_attributes)] fn main() { diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr index 46618fe4065..d78a173316b 100644 --- a/tests/ui/author/matches.stderr +++ b/tests/ui/author/matches.stderr @@ -1,15 +1,15 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/matches.rs:9:13 - | -9 | x - | ^ - | - = note: `-D clippy::let-and-return` implied by `-D warnings` + --> $DIR/matches.rs:19:13 + | +19 | x + | ^ + | + = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/matches.rs:8:21 - | -8 | let x = 3; - | ^ + --> $DIR/matches.rs:18:21 + | +18 | let x = 3; + | ^ error: aborting due to previous error diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index 4111f344b66..4110f6ced85 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index dcf3f241b4b..f0f450fc169 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -1,109 +1,109 @@ error: &-masking with zero - --> $DIR/bit_masks.rs:12:5 + --> $DIR/bit_masks.rs:22:5 | -12 | x & 0 == 0; +22 | x & 0 == 0; | ^^^^^^^^^^ | = note: `-D clippy::bad-bit-mask` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:12:5 + --> $DIR/bit_masks.rs:22:5 | -12 | x & 0 == 0; +22 | x & 0 == 0; | ^^^^^ | = note: #[deny(clippy::erasing_op)] on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:15:5 + --> $DIR/bit_masks.rs:25:5 | -15 | x & 2 == 1; +25 | x & 2 == 1; | ^^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:19:5 + --> $DIR/bit_masks.rs:29:5 | -19 | x | 3 == 2; +29 | x | 3 == 2; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 1` will never be higher than `1` - --> $DIR/bit_masks.rs:21:5 + --> $DIR/bit_masks.rs:31:5 | -21 | x & 1 > 1; +31 | x & 1 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:25:5 + --> $DIR/bit_masks.rs:35:5 | -25 | x | 2 > 1; +35 | x | 2 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ & 7` can never be equal to `8` - --> $DIR/bit_masks.rs:32:5 + --> $DIR/bit_masks.rs:42:5 | -32 | x & THREE_BITS == 8; +42 | x & THREE_BITS == 8; | ^^^^^^^^^^^^^^^^^^^ error: incompatible bit mask: `_ | 7` will never be lower than `7` - --> $DIR/bit_masks.rs:33:5 + --> $DIR/bit_masks.rs:43:5 | -33 | x | EVEN_MORE_REDIRECTION < 7; +43 | x | EVEN_MORE_REDIRECTION < 7; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &-masking with zero - --> $DIR/bit_masks.rs:35:5 + --> $DIR/bit_masks.rs:45:5 | -35 | 0 & x == 0; +45 | 0 & x == 0; | ^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:35:5 + --> $DIR/bit_masks.rs:45:5 | -35 | 0 & x == 0; +45 | 0 & x == 0; | ^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:39:5 + --> $DIR/bit_masks.rs:49:5 | -39 | 1 < 2 | x; +49 | 1 < 2 | x; | ^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:40:5 + --> $DIR/bit_masks.rs:50:5 | -40 | 2 == 3 | x; +50 | 2 == 3 | x; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:41:5 + --> $DIR/bit_masks.rs:51:5 | -41 | 1 == x & 2; +51 | 1 == x & 2; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:52:5 + --> $DIR/bit_masks.rs:62:5 | -52 | x | 1 > 3; +62 | x | 1 > 3; | ^^^^^^^^^ | = note: `-D clippy::ineffective-bit-mask` implied by `-D warnings` error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly - --> $DIR/bit_masks.rs:53:5 + --> $DIR/bit_masks.rs:63:5 | -53 | x | 1 < 4; +63 | x | 1 < 4; | ^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:54:5 + --> $DIR/bit_masks.rs:64:5 | -54 | x | 1 <= 3; +64 | x | 1 <= 3; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared directly - --> $DIR/bit_masks.rs:55:5 + --> $DIR/bit_masks.rs:65:5 | -55 | x | 1 >= 8; +65 | x | 1 >= 8; | ^^^^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index 4e2e5388c98..be58a8fb601 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 472401d5ed6..1e253eba140 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -1,87 +1,87 @@ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:7:9 - | -7 | fn test(foo: ()) {} - | ^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` + --> $DIR/blacklisted_name.rs:17:9 + | +17 | fn test(foo: ()) {} + | ^^^ + | + = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:10:9 + --> $DIR/blacklisted_name.rs:20:9 | -10 | let foo = 42; +20 | let foo = 42; | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:11:9 + --> $DIR/blacklisted_name.rs:21:9 | -11 | let bar = 42; +21 | let bar = 42; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:12:9 + --> $DIR/blacklisted_name.rs:22:9 | -12 | let baz = 42; +22 | let baz = 42; | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:18:10 + --> $DIR/blacklisted_name.rs:28:10 | -18 | (foo, Some(bar), baz @ Some(_)) => (), +28 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:18:20 + --> $DIR/blacklisted_name.rs:28:20 | -18 | (foo, Some(bar), baz @ Some(_)) => (), +28 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:18:26 + --> $DIR/blacklisted_name.rs:28:26 | -18 | (foo, Some(bar), baz @ Some(_)) => (), +28 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:23:19 + --> $DIR/blacklisted_name.rs:33:19 | -23 | fn issue_1647(mut foo: u8) { +33 | fn issue_1647(mut foo: u8) { | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:24:13 + --> $DIR/blacklisted_name.rs:34:13 | -24 | let mut bar = 0; +34 | let mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:25:21 + --> $DIR/blacklisted_name.rs:35:21 | -25 | if let Some(mut baz) = Some(42) {} +35 | if let Some(mut baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:29:13 + --> $DIR/blacklisted_name.rs:39:13 | -29 | let ref bar = 0; +39 | let ref bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:30:21 + --> $DIR/blacklisted_name.rs:40:21 | -30 | if let Some(ref baz) = Some(42) {} +40 | if let Some(ref baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:34:17 + --> $DIR/blacklisted_name.rs:44:17 | -34 | let ref mut bar = 0; +44 | let ref mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:35:25 + --> $DIR/blacklisted_name.rs:45:25 | -35 | if let Some(ref mut baz) = Some(42) {} +45 | if let Some(ref mut baz) = Some(42) {} | ^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index dd0e5503437..67bd778acaa 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index 41f1e9c1681..b0036d1ee23 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,11 +1,11 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:30:8 + --> $DIR/block_in_if_condition.rs:40:8 | -30 | if { +40 | if { | ________^ -31 | | let x = 3; -32 | | x == 3 -33 | | } { +41 | | let x = 3; +42 | | x == 3 +43 | | } { | |_____^ | = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` @@ -19,9 +19,9 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; inste } ... error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:41:8 + --> $DIR/block_in_if_condition.rs:51:8 | -41 | if { true } { +51 | if { true } { | ^^^^^^^^ | = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` @@ -31,21 +31,21 @@ error: omit braces around single expression condition } ... error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:58:49 + --> $DIR/block_in_if_condition.rs:68:49 | -58 | if v == 3 && sky == "blue" && predicate(|x| { let target = 3; x == target }, v) { +68 | if v == 3 && sky == "blue" && predicate(|x| { let target = 3; x == target }, v) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:61:22 + --> $DIR/block_in_if_condition.rs:71:22 | -61 | if predicate(|x| { let target = 3; x == target }, v) { +71 | if predicate(|x| { let target = 3; x == target }, v) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:67:8 + --> $DIR/block_in_if_condition.rs:77:8 | -67 | if true && x == 3 { +77 | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 144f9f4c631..1d9756bc39b 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2fcde94367a..f1bb50fae9e 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,27 +1,27 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:7:8 - | -7 | if x == true { "yes" } else { "no" }; - | ^^^^^^^^^ help: try simplifying it as shown: `x` - | - = note: `-D clippy::bool-comparison` implied by `-D warnings` + --> $DIR/bool_comparison.rs:17:8 + | +17 | if x == true { "yes" } else { "no" }; + | ^^^^^^^^^ help: try simplifying it as shown: `x` + | + = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:8:8 - | -8 | if x == false { "yes" } else { "no" }; - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + --> $DIR/bool_comparison.rs:18:8 + | +18 | if x == false { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:9:8 - | -9 | if true == x { "yes" } else { "no" }; - | ^^^^^^^^^ help: try simplifying it as shown: `x` + --> $DIR/bool_comparison.rs:19:8 + | +19 | if true == x { "yes" } else { "no" }; + | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:10:8 + --> $DIR/bool_comparison.rs:20:8 | -10 | if false == x { "yes" } else { "no" }; +20 | if false == x { "yes" } else { "no" }; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: aborting due to 4 previous errors diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index eaa686c9a90..556344c77a2 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::nonminimal_bool, clippy::logic_bug)] diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 45e371025ef..01f821f511f 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -1,202 +1,202 @@ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:12:13 + --> $DIR/booleans.rs:22:13 | -12 | let _ = a && b || a; +22 | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:12:18 + --> $DIR/booleans.rs:22:18 | -12 | let _ = a && b || a; +22 | let _ = a && b || a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:14:13 + --> $DIR/booleans.rs:24:13 | -14 | let _ = !true; +24 | let _ = !true; | ^^^^^ help: try: `false` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/booleans.rs:15:13 + --> $DIR/booleans.rs:25:13 | -15 | let _ = !false; +25 | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/booleans.rs:16:13 + --> $DIR/booleans.rs:26:13 | -16 | let _ = !!a; +26 | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:17:13 + --> $DIR/booleans.rs:27:13 | -17 | let _ = false && a; +27 | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:17:22 + --> $DIR/booleans.rs:27:22 | -17 | let _ = false && a; +27 | let _ = false && a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:18:13 + --> $DIR/booleans.rs:28:13 | -18 | let _ = false || a; +28 | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/booleans.rs:23:13 + --> $DIR/booleans.rs:33:13 | -23 | let _ = !(!a && b); +33 | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `!b || a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:33:13 + --> $DIR/booleans.rs:43:13 | -33 | let _ = a == b && a != b; +43 | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:33:13 + --> $DIR/booleans.rs:43:13 | -33 | let _ = a == b && a != b; +43 | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:34:13 + --> $DIR/booleans.rs:44:13 | -34 | let _ = a == b && c == 5 && a == b; +44 | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -34 | let _ = a == b && c == 5; +44 | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -34 | let _ = !(c != 5 || a != b); +44 | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:35:13 + --> $DIR/booleans.rs:45:13 | -35 | let _ = a == b && c == 5 && b == a; +45 | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -35 | let _ = a == b && c == 5; +45 | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -35 | let _ = !(c != 5 || a != b); +45 | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:36:13 + --> $DIR/booleans.rs:46:13 | -36 | let _ = a < b && a >= b; +46 | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:36:13 + --> $DIR/booleans.rs:46:13 | -36 | let _ = a < b && a >= b; +46 | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:37:13 + --> $DIR/booleans.rs:47:13 | -37 | let _ = a > b && a <= b; +47 | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:37:13 + --> $DIR/booleans.rs:47:13 | -37 | let _ = a > b && a <= b; +47 | let _ = a > b && a <= b; | ^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:39:13 + --> $DIR/booleans.rs:49:13 | -39 | let _ = a != b || !(a != b || c == d); +49 | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -39 | let _ = c != d || a != b; +49 | let _ = c != d || a != b; | ^^^^^^^^^^^^^^^^ -39 | let _ = !(a == b && c == d); +49 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:47:13 + --> $DIR/booleans.rs:57:13 | -47 | let _ = !a.is_some(); +57 | let _ = !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:49:13 + --> $DIR/booleans.rs:59:13 | -49 | let _ = !a.is_none(); +59 | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:51:13 + --> $DIR/booleans.rs:61:13 | -51 | let _ = !b.is_err(); +61 | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:53:13 + --> $DIR/booleans.rs:63:13 | -53 | let _ = !b.is_ok(); +63 | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:55:13 + --> $DIR/booleans.rs:65:13 | -55 | let _ = !(a.is_some() && !c); +65 | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:56:13 + --> $DIR/booleans.rs:66:13 | -56 | let _ = !(!c ^ c) || !a.is_some(); +66 | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:57:13 + --> $DIR/booleans.rs:67:13 | -57 | let _ = (!c ^ c) || !a.is_some(); +67 | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:58:13 + --> $DIR/booleans.rs:68:13 | -58 | let _ = !c ^ c || !a.is_some(); +68 | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:110:8 + --> $DIR/booleans.rs:120:8 | -110 | if !res.is_ok() { } +120 | if !res.is_ok() { } | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:111:8 + --> $DIR/booleans.rs:121:8 | -111 | if !res.is_err() { } +121 | if !res.is_err() { } | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:114:8 + --> $DIR/booleans.rs:124:8 | -114 | if !res.is_some() { } +124 | if !res.is_some() { } | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:115:8 + --> $DIR/booleans.rs:125:8 | -115 | if !res.is_none() { } +125 | if !res.is_none() { } | ^^^^^^^^^^^^^^ help: try: `res.is_some()` error: aborting due to 25 previous errors diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index 216dbebda67..7c668c33c83 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 1098c7785e2..7cc8eb8da40 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -1,31 +1,31 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:9:19 - | -9 | pub fn test1(foo: &mut Box) { - | ^^^^^^^^^^^^^^ help: try: `&mut bool` - | + --> $DIR/borrow_box.rs:19:19 + | +19 | pub fn test1(foo: &mut Box) { + | ^^^^^^^^^^^^^^ help: try: `&mut bool` + | note: lint level defined here - --> $DIR/borrow_box.rs:4:9 - | -4 | #![deny(clippy::borrowed_box)] - | ^^^^^^^^^^^^^^^^^^^^ + --> $DIR/borrow_box.rs:14:9 + | +14 | #![deny(clippy::borrowed_box)] + | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:14:14 + --> $DIR/borrow_box.rs:24:14 | -14 | let foo: &Box; +24 | let foo: &Box; | ^^^^^^^^^^ help: try: `&bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:18:10 + --> $DIR/borrow_box.rs:28:10 | -18 | foo: &'a Box +28 | foo: &'a Box | ^^^^^^^^^^^^^ help: try: `&'a bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:22:17 + --> $DIR/borrow_box.rs:32:17 | -22 | fn test4(a: &Box); +32 | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` error: aborting due to 4 previous errors diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index bc5e8361d8b..78174d2cd8f 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index b90bb5e2a4e..34be890b534 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -1,7 +1,7 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` - --> $DIR/box_vec.rs:17:18 + --> $DIR/box_vec.rs:27:18 | -17 | pub fn test(foo: Box>) { +27 | pub fn test(foo: Box>) { | ^^^^^^^^^^^^^^ | = note: `-D clippy::box-vec` implied by `-D warnings` diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index 56892fc9483..a6d0f82a7d6 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::builtin_type_shadow)] diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 78924ebf9cf..11253715716 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,21 +1,21 @@ error: This generic shadows the built-in type `u32` - --> $DIR/builtin-type-shadow.rs:5:8 - | -5 | fn foo(a: u32) -> u32 { - | ^^^ - | - = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` + --> $DIR/builtin-type-shadow.rs:15:8 + | +15 | fn foo(a: u32) -> u32 { + | ^^^ + | + = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types - --> $DIR/builtin-type-shadow.rs:6:5 - | -5 | fn foo(a: u32) -> u32 { - | --- expected `u32` because of return type -6 | 42 - | ^^ expected type parameter, found integral variable - | - = note: expected type `u32` - found type `{integer}` + --> $DIR/builtin-type-shadow.rs:16:5 + | +15 | fn foo(a: u32) -> u32 { + | --- expected `u32` because of return type +16 | 42 + | ^^ expected type parameter, found integral variable + | + = note: expected type `u32` + found type `{integer}` error: aborting due to 2 previous errors diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 7211284e4a0..71a6e01219e 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 0564d6a0b60..c5c0ec7eda4 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,25 +1,25 @@ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:8:13 - | -8 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` - | + --> $DIR/bytecount.rs:18:13 + | +18 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` + | note: lint level defined here - --> $DIR/bytecount.rs:4:8 - | -4 | #[deny(clippy::naive_bytecount)] - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/bytecount.rs:14:8 + | +14 | #[deny(clippy::naive_bytecount)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:10:13 + --> $DIR/bytecount.rs:20:13 | -10 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count +20 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:22:13 + --> $DIR/bytecount.rs:32:13 | -22 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count +32 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` error: aborting due to 3 previous errors diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 0668b16ff32..2fb865b12b8 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 2578c49893f..1f9ab5712f5 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,181 +1,181 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:8:5 - | -8 | 1i32 as f32; - | ^^^^^^^^^^^ - | - = note: `-D clippy::cast-precision-loss` implied by `-D warnings` + --> $DIR/cast.rs:18:5 + | +18 | 1i32 as f32; + | ^^^^^^^^^^^ + | + = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:9:5 - | -9 | 1i64 as f32; - | ^^^^^^^^^^^ + --> $DIR/cast.rs:19:5 + | +19 | 1i64 as f32; + | ^^^^^^^^^^^ error: casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:10:5 + --> $DIR/cast.rs:20:5 | -10 | 1i64 as f64; +20 | 1i64 as f64; | ^^^^^^^^^^^ error: casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:11:5 + --> $DIR/cast.rs:21:5 | -11 | 1u32 as f32; +21 | 1u32 as f32; | ^^^^^^^^^^^ error: casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:12:5 + --> $DIR/cast.rs:22:5 | -12 | 1u64 as f32; +22 | 1u64 as f32; | ^^^^^^^^^^^ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:13:5 + --> $DIR/cast.rs:23:5 | -13 | 1u64 as f64; +23 | 1u64 as f64; | ^^^^^^^^^^^ error: casting f32 to i32 may truncate the value - --> $DIR/cast.rs:15:5 + --> $DIR/cast.rs:25:5 | -15 | 1f32 as i32; +25 | 1f32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value - --> $DIR/cast.rs:16:5 + --> $DIR/cast.rs:26:5 | -16 | 1f32 as u32; +26 | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value - --> $DIR/cast.rs:16:5 + --> $DIR/cast.rs:26:5 | -16 | 1f32 as u32; +26 | 1f32 as u32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value - --> $DIR/cast.rs:17:5 + --> $DIR/cast.rs:27:5 | -17 | 1f64 as f32; +27 | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value - --> $DIR/cast.rs:18:5 + --> $DIR/cast.rs:28:5 | -18 | 1i32 as i8; +28 | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may lose the sign of the value - --> $DIR/cast.rs:19:5 + --> $DIR/cast.rs:29:5 | -19 | 1i32 as u8; +29 | 1i32 as u8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value - --> $DIR/cast.rs:19:5 + --> $DIR/cast.rs:29:5 | -19 | 1i32 as u8; +29 | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:30:5 | -20 | 1f64 as isize; +30 | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:31:5 | -21 | 1f64 as usize; +31 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:31:5 | -21 | 1f64 as usize; +31 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:33:5 | -23 | 1u8 as i8; +33 | 1u8 as i8; | ^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value - --> $DIR/cast.rs:24:5 + --> $DIR/cast.rs:34:5 | -24 | 1u16 as i16; +34 | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:35:5 | -25 | 1u32 as i32; +35 | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value - --> $DIR/cast.rs:26:5 + --> $DIR/cast.rs:36:5 | -26 | 1u64 as i64; +36 | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value - --> $DIR/cast.rs:27:5 + --> $DIR/cast.rs:37:5 | -27 | 1usize as isize; +37 | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting f32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:29:5 + --> $DIR/cast.rs:39:5 | -29 | 1.0f32 as f64; +39 | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:41:5 | -31 | (1u8 + 1u8) as u16; +41 | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:43:5 | -33 | 1i32 as u32; +43 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:34:5 + --> $DIR/cast.rs:44:5 | -34 | 1isize as usize; +44 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:47:5 | -37 | 1i32 as i32; +47 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:38:5 + --> $DIR/cast.rs:48:5 | -38 | 1f32 as f32; +48 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:39:5 + --> $DIR/cast.rs:49:5 | -39 | false as bool; +49 | false as bool; | ^^^^^^^^^^^^^ error: aborting due to 28 previous errors diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 1f7606de649..b6e01d21288 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] //! Test casts for alignment issues diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index d03d727a89c..a4dd6038cab 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,15 +1,15 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:15:5 + --> $DIR/cast_alignment.rs:25:5 | -15 | (&1u8 as *const u8) as *const u16; +25 | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:16:5 + --> $DIR/cast_alignment.rs:26:5 | -16 | (&mut 1u8 as *mut u8) as *mut u16; +26 | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index 437c4b67120..aa78a62f88b 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 9025633a141..95b9bfb0262 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,63 +1,63 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:7:5 - | -7 | 1i8 as f32; - | ^^^^^^^^^^ help: try: `f32::from(1i8)` - | - = note: `-D clippy::cast-lossless` implied by `-D warnings` + --> $DIR/cast_lossless_float.rs:17:5 + | +17 | 1i8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1i8)` + | + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:8:5 - | -8 | 1i8 as f64; - | ^^^^^^^^^^ help: try: `f64::from(1i8)` + --> $DIR/cast_lossless_float.rs:18:5 + | +18 | 1i8 as f64; + | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:9:5 - | -9 | 1u8 as f32; - | ^^^^^^^^^^ help: try: `f32::from(1u8)` + --> $DIR/cast_lossless_float.rs:19:5 + | +19 | 1u8 as f32; + | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:10:5 + --> $DIR/cast_lossless_float.rs:20:5 | -10 | 1u8 as f64; +20 | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:11:5 + --> $DIR/cast_lossless_float.rs:21:5 | -11 | 1i16 as f32; +21 | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:12:5 + --> $DIR/cast_lossless_float.rs:22:5 | -12 | 1i16 as f64; +22 | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:13:5 + --> $DIR/cast_lossless_float.rs:23:5 | -13 | 1u16 as f32; +23 | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:14:5 + --> $DIR/cast_lossless_float.rs:24:5 | -14 | 1u16 as f64; +24 | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:15:5 + --> $DIR/cast_lossless_float.rs:25:5 | -15 | 1i32 as f64; +25 | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:16:5 + --> $DIR/cast_lossless_float.rs:26:5 | -16 | 1u32 as f64; +26 | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` error: aborting due to 10 previous errors diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index e06e653c6f5..ef430d57e1e 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index 9640e1e18fa..5f9c70879b4 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,111 +1,111 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:6:5 - | -6 | 1i8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1i8)` - | - = note: `-D clippy::cast-lossless` implied by `-D warnings` + --> $DIR/cast_lossless_integer.rs:16:5 + | +16 | 1i8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1i8)` + | + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:7:5 - | -7 | 1i8 as i32; - | ^^^^^^^^^^ help: try: `i32::from(1i8)` + --> $DIR/cast_lossless_integer.rs:17:5 + | +17 | 1i8 as i32; + | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:8:5 - | -8 | 1i8 as i64; - | ^^^^^^^^^^ help: try: `i64::from(1i8)` + --> $DIR/cast_lossless_integer.rs:18:5 + | +18 | 1i8 as i64; + | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:9:5 - | -9 | 1u8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1u8)` + --> $DIR/cast_lossless_integer.rs:19:5 + | +19 | 1u8 as i16; + | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:10:5 + --> $DIR/cast_lossless_integer.rs:20:5 | -10 | 1u8 as i32; +20 | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:11:5 + --> $DIR/cast_lossless_integer.rs:21:5 | -11 | 1u8 as i64; +21 | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:12:5 + --> $DIR/cast_lossless_integer.rs:22:5 | -12 | 1u8 as u16; +22 | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:13:5 + --> $DIR/cast_lossless_integer.rs:23:5 | -13 | 1u8 as u32; +23 | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:14:5 + --> $DIR/cast_lossless_integer.rs:24:5 | -14 | 1u8 as u64; +24 | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:15:5 + --> $DIR/cast_lossless_integer.rs:25:5 | -15 | 1i16 as i32; +25 | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:26:5 | -16 | 1i16 as i64; +26 | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:27:5 | -17 | 1u16 as i32; +27 | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:28:5 | -18 | 1u16 as i64; +28 | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:29:5 | -19 | 1u16 as u32; +29 | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:30:5 | -20 | 1u16 as u64; +30 | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:31:5 | -21 | 1i32 as i64; +31 | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:32:5 | -22 | 1u32 as i64; +32 | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:33:5 | -23 | 1u32 as u64; +33 | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` error: aborting due to 18 previous errors diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index 4c72f57165c..e8b0f4a5b82 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index 1797e2e367f..c5f569db167 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,123 +1,123 @@ error: casting isize to i8 may truncate the value - --> $DIR/cast_size.rs:7:5 - | -7 | 1isize as i8; - | ^^^^^^^^^^^^ - | - = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` + --> $DIR/cast_size.rs:17:5 + | +17 | 1isize as i8; + | ^^^^^^^^^^^^ + | + = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:8:5 - | -8 | 1isize as f64; - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::cast-precision-loss` implied by `-D warnings` + --> $DIR/cast_size.rs:18:5 + | +18 | 1isize as f64; + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:9:5 - | -9 | 1usize as f64; - | ^^^^^^^^^^^^^ + --> $DIR/cast_size.rs:19:5 + | +19 | 1usize as f64; + | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:10:5 + --> $DIR/cast_size.rs:20:5 | -10 | 1isize as f32; +20 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:11:5 + --> $DIR/cast_size.rs:21:5 | -11 | 1usize as f32; +21 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:12:5 + --> $DIR/cast_size.rs:22:5 | -12 | 1isize as i32; +22 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast_size.rs:13:5 + --> $DIR/cast_size.rs:23:5 | -13 | 1isize as u32; +23 | 1isize as u32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:13:5 + --> $DIR/cast_size.rs:23:5 | -13 | 1isize as u32; +23 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:14:5 + --> $DIR/cast_size.rs:24:5 | -14 | 1usize as u32; +24 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:15:5 + --> $DIR/cast_size.rs:25:5 | -15 | 1usize as i32; +25 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:15:5 + --> $DIR/cast_size.rs:25:5 | -15 | 1usize as i32; +25 | 1usize as i32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:17:5 + --> $DIR/cast_size.rs:27:5 | -17 | 1i64 as isize; +27 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast_size.rs:18:5 + --> $DIR/cast_size.rs:28:5 | -18 | 1i64 as usize; +28 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:18:5 + --> $DIR/cast_size.rs:28:5 | -18 | 1i64 as usize; +28 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:19:5 + --> $DIR/cast_size.rs:29:5 | -19 | 1u64 as isize; +29 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:19:5 + --> $DIR/cast_size.rs:29:5 | -19 | 1u64 as isize; +29 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:20:5 + --> $DIR/cast_size.rs:30:5 | -20 | 1u64 as usize; +30 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:21:5 + --> $DIR/cast_size.rs:31:5 | -21 | 1u32 as isize; +31 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast_size.rs:24:5 + --> $DIR/cast_size.rs:34:5 | -24 | 1i32 as usize; +34 | 1i32 as usize; | ^^^^^^^^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index f9937ede351..8fda473e351 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index f6ea10d5731..38a469bfebb 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -1,12 +1,12 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them - --> $DIR/char_lit_as_u8.rs:7:13 - | -7 | let c = 'a' as u8; - | ^^^^^^^^^ - | - = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` - = help: Consider using a byte literal instead: - b'a' + --> $DIR/char_lit_as_u8.rs:17:13 + | +17 | let c = 'a' as u8; + | ^^^^^^^^^ + | + = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` + = help: Consider using a byte literal instead: + b'a' error: aborting due to previous error diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index b3979245d36..ed9651b1872 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index 4508ce442fa..f7f49360348 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,312 +1,312 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:9:9 - | -8 | if x.is_some() { - | ----------- the check is happening here -9 | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - | + --> $DIR/checked_unwrap.rs:19:9 + | +18 | if x.is_some() { + | ----------- the check is happening here +19 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + | note: lint level defined here - --> $DIR/checked_unwrap.rs:3:35 - | -3 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/checked_unwrap.rs:13:35 + | +13 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:11:9 + --> $DIR/checked_unwrap.rs:21:9 | -8 | if x.is_some() { +18 | if x.is_some() { | ----------- because of this check ... -11 | x.unwrap(); // will panic +21 | x.unwrap(); // will panic | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:3:9 + --> $DIR/checked_unwrap.rs:13:9 | -3 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +13 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:14:9 + --> $DIR/checked_unwrap.rs:24:9 | -13 | if x.is_none() { +23 | if x.is_none() { | ----------- because of this check -14 | x.unwrap(); // will panic +24 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:16:9 + --> $DIR/checked_unwrap.rs:26:9 | -13 | if x.is_none() { +23 | if x.is_none() { | ----------- the check is happening here ... -16 | x.unwrap(); // unnecessary +26 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:20:9 + --> $DIR/checked_unwrap.rs:30:9 | -19 | if x.is_ok() { +29 | if x.is_ok() { | --------- the check is happening here -20 | x.unwrap(); // unnecessary +30 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:21:9 + --> $DIR/checked_unwrap.rs:31:9 | -19 | if x.is_ok() { +29 | if x.is_ok() { | --------- because of this check -20 | x.unwrap(); // unnecessary -21 | x.unwrap_err(); // will panic +30 | x.unwrap(); // unnecessary +31 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:23:9 + --> $DIR/checked_unwrap.rs:33:9 | -19 | if x.is_ok() { +29 | if x.is_ok() { | --------- because of this check ... -23 | x.unwrap(); // will panic +33 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:24:9 + --> $DIR/checked_unwrap.rs:34:9 | -19 | if x.is_ok() { +29 | if x.is_ok() { | --------- the check is happening here ... -24 | x.unwrap_err(); // unnecessary +34 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:27:9 + --> $DIR/checked_unwrap.rs:37:9 | -26 | if x.is_err() { +36 | if x.is_err() { | ---------- because of this check -27 | x.unwrap(); // will panic +37 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:28:9 + --> $DIR/checked_unwrap.rs:38:9 | -26 | if x.is_err() { +36 | if x.is_err() { | ---------- the check is happening here -27 | x.unwrap(); // will panic -28 | x.unwrap_err(); // unnecessary +37 | x.unwrap(); // will panic +38 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:30:9 + --> $DIR/checked_unwrap.rs:40:9 | -26 | if x.is_err() { +36 | if x.is_err() { | ---------- the check is happening here ... -30 | x.unwrap(); // unnecessary +40 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:31:9 + --> $DIR/checked_unwrap.rs:41:9 | -26 | if x.is_err() { +36 | if x.is_err() { | ---------- because of this check ... -31 | x.unwrap_err(); // will panic +41 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:48:9 + --> $DIR/checked_unwrap.rs:58:9 | -47 | if x.is_ok() && y.is_err() { +57 | if x.is_ok() && y.is_err() { | --------- the check is happening here -48 | x.unwrap(); // unnecessary +58 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:49:9 + --> $DIR/checked_unwrap.rs:59:9 | -47 | if x.is_ok() && y.is_err() { +57 | if x.is_ok() && y.is_err() { | --------- because of this check -48 | x.unwrap(); // unnecessary -49 | x.unwrap_err(); // will panic +58 | x.unwrap(); // unnecessary +59 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:50:9 + --> $DIR/checked_unwrap.rs:60:9 | -47 | if x.is_ok() && y.is_err() { +57 | if x.is_ok() && y.is_err() { | ---------- because of this check ... -50 | y.unwrap(); // will panic +60 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:51:9 + --> $DIR/checked_unwrap.rs:61:9 | -47 | if x.is_ok() && y.is_err() { +57 | if x.is_ok() && y.is_err() { | ---------- the check is happening here ... -51 | y.unwrap_err(); // unnecessary +61 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:65:9 + --> $DIR/checked_unwrap.rs:75:9 | -60 | if x.is_ok() || y.is_ok() { +70 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -65 | x.unwrap(); // will panic +75 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:66:9 + --> $DIR/checked_unwrap.rs:76:9 | -60 | if x.is_ok() || y.is_ok() { +70 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -66 | x.unwrap_err(); // unnecessary +76 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:67:9 + --> $DIR/checked_unwrap.rs:77:9 | -60 | if x.is_ok() || y.is_ok() { +70 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -67 | y.unwrap(); // will panic +77 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:68:9 + --> $DIR/checked_unwrap.rs:78:9 | -60 | if x.is_ok() || y.is_ok() { +70 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -68 | y.unwrap_err(); // unnecessary +78 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:72:9 + --> $DIR/checked_unwrap.rs:82:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -72 | x.unwrap(); // unnecessary +82 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:73:9 + --> $DIR/checked_unwrap.rs:83:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check -72 | x.unwrap(); // unnecessary -73 | x.unwrap_err(); // will panic +82 | x.unwrap(); // unnecessary +83 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:74:9 + --> $DIR/checked_unwrap.rs:84:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check ... -74 | y.unwrap(); // will panic +84 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:75:9 + --> $DIR/checked_unwrap.rs:85:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here ... -75 | y.unwrap_err(); // unnecessary +85 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:76:9 + --> $DIR/checked_unwrap.rs:86:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here ... -76 | z.unwrap(); // unnecessary +86 | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:77:9 + --> $DIR/checked_unwrap.rs:87:9 | -71 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check ... -77 | z.unwrap_err(); // will panic +87 | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:85:9 + --> $DIR/checked_unwrap.rs:95:9 | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -85 | x.unwrap(); // will panic +95 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:86:9 + --> $DIR/checked_unwrap.rs:96:9 | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -86 | x.unwrap_err(); // unnecessary +96 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:87:9 + --> $DIR/checked_unwrap.rs:97:9 | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -87 | y.unwrap(); // unnecessary +97 | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:88:9 + --> $DIR/checked_unwrap.rs:98:9 | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -88 | y.unwrap_err(); // will panic +98 | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:89:9 + --> $DIR/checked_unwrap.rs:99:9 | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check ... -89 | z.unwrap(); // will panic +99 | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:90:9 - | -79 | if x.is_ok() || !(y.is_ok() && z.is_err()) { - | ---------- the check is happening here + --> $DIR/checked_unwrap.rs:100:9 + | +89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ---------- the check is happening here ... -90 | z.unwrap_err(); // unnecessary - | ^^^^^^^^^^^^^^ +100 | z.unwrap_err(); // unnecessary + | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:98:13 - | -97 | if x.is_some() { - | ----------- the check is happening here -98 | x.unwrap(); // unnecessary - | ^^^^^^^^^^ + --> $DIR/checked_unwrap.rs:108:13 + | +107 | if x.is_some() { + | ----------- the check is happening here +108 | x.unwrap(); // unnecessary + | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:100:13 + --> $DIR/checked_unwrap.rs:110:13 | -97 | if x.is_some() { +107 | if x.is_some() { | ----------- because of this check ... -100 | x.unwrap(); // will panic +110 | x.unwrap(); // will panic | ^^^^^^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index e21441640f3..a1353abd92b 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use std::marker::PhantomData; use std::fmt; diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 77dffc67670..ad37d45d36f 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] pub fn dec_read_dec(i: &mut i32) -> i32 { diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index fdebb7da18a..a2506f444f0 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 7f636e6b534..b880b821f08 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -1,75 +1,75 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:8:5 - | -8 | x == std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::cmp-nan` implied by `-D warnings` + --> $DIR/cmp_nan.rs:18:5 + | +18 | x == std::f32::NAN; + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::cmp-nan` implied by `-D warnings` error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:9:5 - | -9 | x != std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ + --> $DIR/cmp_nan.rs:19:5 + | +19 | x != std::f32::NAN; + | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:10:5 + --> $DIR/cmp_nan.rs:20:5 | -10 | x < std::f32::NAN; +20 | x < std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:11:5 + --> $DIR/cmp_nan.rs:21:5 | -11 | x > std::f32::NAN; +21 | x > std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:12:5 + --> $DIR/cmp_nan.rs:22:5 | -12 | x <= std::f32::NAN; +22 | x <= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:13:5 + --> $DIR/cmp_nan.rs:23:5 | -13 | x >= std::f32::NAN; +23 | x >= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:16:5 + --> $DIR/cmp_nan.rs:26:5 | -16 | y == std::f64::NAN; +26 | y == std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:17:5 + --> $DIR/cmp_nan.rs:27:5 | -17 | y != std::f64::NAN; +27 | y != std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:18:5 + --> $DIR/cmp_nan.rs:28:5 | -18 | y < std::f64::NAN; +28 | y < std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:19:5 + --> $DIR/cmp_nan.rs:29:5 | -19 | y > std::f64::NAN; +29 | y > std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:20:5 + --> $DIR/cmp_nan.rs:30:5 | -20 | y <= std::f64::NAN; +30 | y <= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:21:5 + --> $DIR/cmp_nan.rs:31:5 | -21 | y >= std::f64::NAN; +31 | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index e10b3e104ec..d8214876a1b 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::cmp_null)] diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 55050d2a320..1f1fdf32852 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -1,15 +1,15 @@ error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:11:8 + --> $DIR/cmp_null.rs:21:8 | -11 | if p == ptr::null() { +21 | if p == ptr::null() { | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::cmp-null` implied by `-D warnings` error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:16:8 + --> $DIR/cmp_null.rs:26:8 | -16 | if m == ptr::null_mut() { +26 | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 713975c4404..e937afc1a81 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 2691c12eab1..020ffe805cd 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -1,39 +1,39 @@ error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:8:14 - | -8 | x != "foo".to_string(); - | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` - | - = note: `-D clippy::cmp-owned` implied by `-D warnings` + --> $DIR/cmp_owned.rs:18:14 + | +18 | x != "foo".to_string(); + | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` + | + = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:10:9 + --> $DIR/cmp_owned.rs:20:9 | -10 | "foo".to_string() != x; +20 | "foo".to_string() != x; | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:17:10 + --> $DIR/cmp_owned.rs:27:10 | -17 | x != "foo".to_owned(); +27 | x != "foo".to_owned(); | ^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:19:10 + --> $DIR/cmp_owned.rs:29:10 | -19 | x != String::from("foo"); +29 | x != String::from("foo"); | ^^^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:23:5 + --> $DIR/cmp_owned.rs:33:5 | -23 | Foo.to_owned() == Foo; +33 | Foo.to_owned() == Foo; | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:30:9 + --> $DIR/cmp_owned.rs:40:9 | -30 | self.to_owned() == *other +40 | self.to_owned() == *other | ^^^^^^^^^^^^^^^ try calling implementing the comparison without allocating error: aborting due to 6 previous errors diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index d40be631933..fa80b27f590 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index a447fab7b6e..87c279cd725 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,243 +1,243 @@ error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:8:5 + --> $DIR/collapsible_if.rs:18:5 | -8 | / if x == "hello" { -9 | | if y == "world" { -10 | | println!("Hello world!"); -11 | | } -12 | | } +18 | / if x == "hello" { +19 | | if y == "world" { +20 | | println!("Hello world!"); +21 | | } +22 | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` help: try | -8 | if x == "hello" && y == "world" { -9 | println!("Hello world!"); -10 | } +18 | if x == "hello" && y == "world" { +19 | println!("Hello world!"); +20 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:14:5 + --> $DIR/collapsible_if.rs:24:5 | -14 | / if x == "hello" || x == "world" { -15 | | if y == "world" || y == "hello" { -16 | | println!("Hello world!"); -17 | | } -18 | | } +24 | / if x == "hello" || x == "world" { +25 | | if y == "world" || y == "hello" { +26 | | println!("Hello world!"); +27 | | } +28 | | } | |_____^ help: try | -14 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -15 | println!("Hello world!"); -16 | } +24 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { +25 | println!("Hello world!"); +26 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:20:5 + --> $DIR/collapsible_if.rs:30:5 | -20 | / if x == "hello" && x == "world" { -21 | | if y == "world" || y == "hello" { -22 | | println!("Hello world!"); -23 | | } -24 | | } +30 | / if x == "hello" && x == "world" { +31 | | if y == "world" || y == "hello" { +32 | | println!("Hello world!"); +33 | | } +34 | | } | |_____^ help: try | -20 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { -21 | println!("Hello world!"); -22 | } +30 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { +31 | println!("Hello world!"); +32 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:26:5 + --> $DIR/collapsible_if.rs:36:5 | -26 | / if x == "hello" || x == "world" { -27 | | if y == "world" && y == "hello" { -28 | | println!("Hello world!"); -29 | | } -30 | | } +36 | / if x == "hello" || x == "world" { +37 | | if y == "world" && y == "hello" { +38 | | println!("Hello world!"); +39 | | } +40 | | } | |_____^ help: try | -26 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { -27 | println!("Hello world!"); -28 | } +36 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { +37 | println!("Hello world!"); +38 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:32:5 + --> $DIR/collapsible_if.rs:42:5 | -32 | / if x == "hello" && x == "world" { -33 | | if y == "world" && y == "hello" { -34 | | println!("Hello world!"); -35 | | } -36 | | } +42 | / if x == "hello" && x == "world" { +43 | | if y == "world" && y == "hello" { +44 | | println!("Hello world!"); +45 | | } +46 | | } | |_____^ help: try | -32 | if x == "hello" && x == "world" && y == "world" && y == "hello" { -33 | println!("Hello world!"); -34 | } +42 | if x == "hello" && x == "world" && y == "world" && y == "hello" { +43 | println!("Hello world!"); +44 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:38:5 + --> $DIR/collapsible_if.rs:48:5 | -38 | / if 42 == 1337 { -39 | | if 'a' != 'A' { -40 | | println!("world!") -41 | | } -42 | | } +48 | / if 42 == 1337 { +49 | | if 'a' != 'A' { +50 | | println!("world!") +51 | | } +52 | | } | |_____^ help: try | -38 | if 42 == 1337 && 'a' != 'A' { -39 | println!("world!") -40 | } +48 | if 42 == 1337 && 'a' != 'A' { +49 | println!("world!") +50 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:47:12 + --> $DIR/collapsible_if.rs:57:12 | -47 | } else { +57 | } else { | ____________^ -48 | | if y == "world" { -49 | | println!("world!") -50 | | } -51 | | } +58 | | if y == "world" { +59 | | println!("world!") +60 | | } +61 | | } | |_____^ help: try | -47 | } else if y == "world" { -48 | println!("world!") -49 | } +57 | } else if y == "world" { +58 | println!("world!") +59 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:55:12 + --> $DIR/collapsible_if.rs:65:12 | -55 | } else { +65 | } else { | ____________^ -56 | | if let Some(42) = Some(42) { -57 | | println!("world!") -58 | | } -59 | | } +66 | | if let Some(42) = Some(42) { +67 | | println!("world!") +68 | | } +69 | | } | |_____^ help: try | -55 | } else if let Some(42) = Some(42) { -56 | println!("world!") -57 | } +65 | } else if let Some(42) = Some(42) { +66 | println!("world!") +67 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:63:12 + --> $DIR/collapsible_if.rs:73:12 | -63 | } else { +73 | } else { | ____________^ -64 | | if y == "world" { -65 | | println!("world") -66 | | } +74 | | if y == "world" { +75 | | println!("world") +76 | | } ... | -69 | | } -70 | | } +79 | | } +80 | | } | |_____^ help: try | -63 | } else if y == "world" { -64 | println!("world") -65 | } -66 | else { -67 | println!("!") -68 | } +73 | } else if y == "world" { +74 | println!("world") +75 | } +76 | else { +77 | println!("!") +78 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:74:12 + --> $DIR/collapsible_if.rs:84:12 | -74 | } else { +84 | } else { | ____________^ -75 | | if let Some(42) = Some(42) { -76 | | println!("world") -77 | | } +85 | | if let Some(42) = Some(42) { +86 | | println!("world") +87 | | } ... | -80 | | } -81 | | } +90 | | } +91 | | } | |_____^ help: try | -74 | } else if let Some(42) = Some(42) { -75 | println!("world") -76 | } -77 | else { -78 | println!("!") -79 | } +84 | } else if let Some(42) = Some(42) { +85 | println!("world") +86 | } +87 | else { +88 | println!("!") +89 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:85:12 - | -85 | } else { - | ____________^ -86 | | if let Some(42) = Some(42) { -87 | | println!("world") -88 | | } -... | -91 | | } -92 | | } - | |_____^ + --> $DIR/collapsible_if.rs:95:12 + | +95 | } else { + | ____________^ +96 | | if let Some(42) = Some(42) { +97 | | println!("world") +98 | | } +... | +101 | | } +102 | | } + | |_____^ help: try - | -85 | } else if let Some(42) = Some(42) { -86 | println!("world") -87 | } -88 | else { -89 | println!("!") -90 | } - | + | +95 | } else if let Some(42) = Some(42) { +96 | println!("world") +97 | } +98 | else { +99 | println!("!") +100 | } + | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:96:12 + --> $DIR/collapsible_if.rs:106:12 | -96 | } else { +106 | } else { | ____________^ -97 | | if x == "hello" { -98 | | println!("world") -99 | | } +107 | | if x == "hello" { +108 | | println!("world") +109 | | } ... | -102 | | } -103 | | } +112 | | } +113 | | } | |_____^ help: try | -96 | } else if x == "hello" { -97 | println!("world") -98 | } -99 | else { -100 | println!("!") -101 | } +106 | } else if x == "hello" { +107 | println!("world") +108 | } +109 | else { +110 | println!("!") +111 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:107:12 + --> $DIR/collapsible_if.rs:117:12 | -107 | } else { +117 | } else { | ____________^ -108 | | if let Some(42) = Some(42) { -109 | | println!("world") -110 | | } +118 | | if let Some(42) = Some(42) { +119 | | println!("world") +120 | | } ... | -113 | | } -114 | | } +123 | | } +124 | | } | |_____^ help: try | -107 | } else if let Some(42) = Some(42) { -108 | println!("world") -109 | } -110 | else { -111 | println!("!") -112 | } +117 | } else if let Some(42) = Some(42) { +118 | println!("world") +119 | } +120 | else { +121 | println!("!") +122 | } | error: aborting due to 13 previous errors diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index eac2c07c12e..5779c9da47f 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all)] diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 1c9106c0c21..f373f09951b 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -1,93 +1,93 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:9:12 - | -9 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::type-complexity` implied by `-D warnings` + --> $DIR/complex_types.rs:19:12 + | +19 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::type-complexity` implied by `-D warnings` error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:10:12 + --> $DIR/complex_types.rs:20:12 | -10 | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +20 | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:13:8 + --> $DIR/complex_types.rs:23:8 | -13 | f: Vec>>, +23 | f: Vec>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:16:11 + --> $DIR/complex_types.rs:26:11 | -16 | struct TS(Vec>>); +26 | struct TS(Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:19:11 + --> $DIR/complex_types.rs:29:11 | -19 | Tuple(Vec>>), +29 | Tuple(Vec>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:20:17 + --> $DIR/complex_types.rs:30:17 | -20 | Struct { f: Vec>> }, +30 | Struct { f: Vec>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:24:14 + --> $DIR/complex_types.rs:34:14 | -24 | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +34 | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:25:30 + --> $DIR/complex_types.rs:35:30 | -25 | fn impl_method(&self, p: Vec>>) { } +35 | fn impl_method(&self, p: Vec>>) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:29:14 + --> $DIR/complex_types.rs:39:14 | -29 | const A: Vec>>; +39 | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:30:14 + --> $DIR/complex_types.rs:40:14 | -30 | type B = Vec>>; +40 | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:31:25 + --> $DIR/complex_types.rs:41:25 | -31 | fn method(&self, p: Vec>>); +41 | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:32:29 + --> $DIR/complex_types.rs:42:29 | -32 | fn def_method(&self, p: Vec>>) { } +42 | fn def_method(&self, p: Vec>>) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:35:15 + --> $DIR/complex_types.rs:45:15 | -35 | fn test1() -> Vec>> { vec![] } +45 | fn test1() -> Vec>> { vec![] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:37:14 + --> $DIR/complex_types.rs:47:14 | -37 | fn test2(_x: Vec>>) { } +47 | fn test2(_x: Vec>>) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:40:13 + --> $DIR/complex_types.rs:50:13 | -40 | let _y: Vec>> = vec![]; +50 | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index 745821a1503..2b6a5dc249a 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[derive(Debug)] struct Foo {} diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index db6c4d9444f..908a681584d 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,81 +1,81 @@ error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:4:17 - | -4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. - | -^^^^^^^---- help: consider removing `'static`: `&str` - | - = note: `-D clippy::const-static-lifetime` implied by `-D warnings` + --> $DIR/const_static_lifetime.rs:14:17 + | +14 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. + | -^^^^^^^---- help: consider removing `'static`: `&str` + | + = note: `-D clippy::const-static-lifetime` implied by `-D warnings` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:8:21 - | -8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static - | -^^^^^^^---- help: consider removing `'static`: `&str` + --> $DIR/const_static_lifetime.rs:18:21 + | +18 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static + | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:10:32 + --> $DIR/const_static_lifetime.rs:20:32 | -10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +20 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:10:47 + --> $DIR/const_static_lifetime.rs:20:47 | -10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +20 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:12:18 + --> $DIR/const_static_lifetime.rs:22:18 | -12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +22 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:12:30 + --> $DIR/const_static_lifetime.rs:22:30 | -12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +22 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:14:17 + --> $DIR/const_static_lifetime.rs:24:17 | -14 | const VAR_SIX: &'static u8 = &5; +24 | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:16:29 + --> $DIR/const_static_lifetime.rs:26:29 | -16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +26 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:16:39 + --> $DIR/const_static_lifetime.rs:26:39 | -16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +26 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:18:20 + --> $DIR/const_static_lifetime.rs:28:20 | -18 | const VAR_HEIGHT: &'static Foo = &Foo {}; +28 | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:20:19 + --> $DIR/const_static_lifetime.rs:30:19 | -20 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +30 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:22:19 + --> $DIR/const_static_lifetime.rs:32:19 | -22 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +32 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:24:19 + --> $DIR/const_static_lifetime.rs:34:19 | -24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +34 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: aborting due to 13 previous errors diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 064c7fc1c59..2b29e76c4e0 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index febd34603c9..e5f808218fe 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,384 +1,384 @@ error: this `if` has identical blocks - --> $DIR/copies.rs:31:10 + --> $DIR/copies.rs:41:10 | -31 | else { //~ ERROR same body as `if` block +41 | else { //~ ERROR same body as `if` block | __________^ -32 | | Foo { bar: 42 }; -33 | | 0..10; -34 | | ..; +42 | | Foo { bar: 42 }; +43 | | 0..10; +44 | | ..; ... | -38 | | foo(); -39 | | } +48 | | foo(); +49 | | } | |_____^ | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:22:13 + --> $DIR/copies.rs:32:13 | -22 | if true { +32 | if true { | _____________^ -23 | | Foo { bar: 42 }; -24 | | 0..10; -25 | | ..; +33 | | Foo { bar: 42 }; +34 | | 0..10; +35 | | ..; ... | -29 | | foo(); -30 | | } +39 | | foo(); +40 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:80:14 + --> $DIR/copies.rs:90:14 | -80 | _ => { //~ ERROR match arms have same body +90 | _ => { //~ ERROR match arms have same body | ______________^ -81 | | foo(); -82 | | let mut a = 42 + [23].len() as i32; -83 | | if true { +91 | | foo(); +92 | | let mut a = 42 + [23].len() as i32; +93 | | if true { ... | -87 | | a -88 | | } +97 | | a +98 | | } | |_________^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:71:15 + --> $DIR/copies.rs:81:15 | -71 | 42 => { +81 | 42 => { | _______________^ -72 | | foo(); -73 | | let mut a = 42 + [23].len() as i32; -74 | | if true { +82 | | foo(); +83 | | let mut a = 42 + [23].len() as i32; +84 | | if true { ... | -78 | | a -79 | | } +88 | | a +89 | | } | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:71:15 + --> $DIR/copies.rs:81:15 | -71 | 42 => { +81 | 42 => { | _______________^ -72 | | foo(); -73 | | let mut a = 42 + [23].len() as i32; -74 | | if true { +82 | | foo(); +83 | | let mut a = 42 + [23].len() as i32; +84 | | if true { ... | -78 | | a -79 | | } +88 | | a +89 | | } | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:94:14 - | -94 | _ => 0, //~ ERROR match arms have same body - | ^ - | + --> $DIR/copies.rs:104:14 + | +104 | _ => 0, //~ ERROR match arms have same body + | ^ + | note: same as this - --> $DIR/copies.rs:92:19 - | -92 | Abc::A => 0, - | ^ + --> $DIR/copies.rs:102:19 + | +102 | Abc::A => 0, + | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:92:19 - | -92 | Abc::A => 0, - | ^ + --> $DIR/copies.rs:102:19 + | +102 | Abc::A => 0, + | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:104:10 + --> $DIR/copies.rs:114:10 | -104 | else { //~ ERROR same body as `if` block +114 | else { //~ ERROR same body as `if` block | __________^ -105 | | 42 -106 | | }; +115 | | 42 +116 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:101:21 + --> $DIR/copies.rs:111:21 | -101 | let _ = if true { +111 | let _ = if true { | _____________________^ -102 | | 42 -103 | | } +112 | | 42 +113 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:118:10 + --> $DIR/copies.rs:128:10 | -118 | else { //~ ERROR same body as `if` block +128 | else { //~ ERROR same body as `if` block | __________^ -119 | | for _ in &[42] { -120 | | let foo: &Option<_> = &Some::(42); -121 | | if true { +129 | | for _ in &[42] { +130 | | let foo: &Option<_> = &Some::(42); +131 | | if true { ... | -126 | | } -127 | | } +136 | | } +137 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:108:13 + --> $DIR/copies.rs:118:13 | -108 | if true { +118 | if true { | _____________^ -109 | | for _ in &[42] { -110 | | let foo: &Option<_> = &Some::(42); -111 | | if true { +119 | | for _ in &[42] { +120 | | let foo: &Option<_> = &Some::(42); +121 | | if true { ... | -116 | | } -117 | | } +126 | | } +127 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:140:10 + --> $DIR/copies.rs:150:10 | -140 | else { //~ ERROR same body as `if` block +150 | else { //~ ERROR same body as `if` block | __________^ -141 | | let bar = if true { -142 | | 42 -143 | | } +151 | | let bar = if true { +152 | | 42 +153 | | } ... | -149 | | bar + 1; -150 | | } +159 | | bar + 1; +160 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:129:13 + --> $DIR/copies.rs:139:13 | -129 | if true { +139 | if true { | _____________^ -130 | | let bar = if true { -131 | | 42 -132 | | } +140 | | let bar = if true { +141 | | 42 +142 | | } ... | -138 | | bar + 1; -139 | | } +148 | | bar + 1; +149 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:175:10 + --> $DIR/copies.rs:185:10 | -175 | else { //~ ERROR same body as `if` block +185 | else { //~ ERROR same body as `if` block | __________^ -176 | | if let Some(a) = Some(42) {} -177 | | } +186 | | if let Some(a) = Some(42) {} +187 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:172:13 + --> $DIR/copies.rs:182:13 | -172 | if true { +182 | if true { | _____________^ -173 | | if let Some(a) = Some(42) {} -174 | | } +183 | | if let Some(a) = Some(42) {} +184 | | } | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:182:10 + --> $DIR/copies.rs:192:10 | -182 | else { //~ ERROR same body as `if` block +192 | else { //~ ERROR same body as `if` block | __________^ -183 | | if let (1, .., 3) = (1, 2, 3) {} -184 | | } +193 | | if let (1, .., 3) = (1, 2, 3) {} +194 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:179:13 + --> $DIR/copies.rs:189:13 | -179 | if true { +189 | if true { | _____________^ -180 | | if let (1, .., 3) = (1, 2, 3) {} -181 | | } +190 | | if let (1, .., 3) = (1, 2, 3) {} +191 | | } | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:237:15 + --> $DIR/copies.rs:247:15 | -237 | 51 => foo(), //~ ERROR match arms have same body +247 | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:236:15 + --> $DIR/copies.rs:246:15 | -236 | 42 => foo(), +246 | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:236:15 + --> $DIR/copies.rs:246:15 | -236 | 42 => foo(), +246 | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:243:17 + --> $DIR/copies.rs:253:17 | -243 | None => 24, //~ ERROR match arms have same body +253 | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:242:20 + --> $DIR/copies.rs:252:20 | -242 | Some(_) => 24, +252 | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:242:20 + --> $DIR/copies.rs:252:20 | -242 | Some(_) => 24, +252 | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:265:28 + --> $DIR/copies.rs:275:28 | -265 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +275 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:264:28 + --> $DIR/copies.rs:274:28 | -264 | (Some(a), None) => bar(a), +274 | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:264:28 + --> $DIR/copies.rs:274:28 | -264 | (Some(a), None) => bar(a), +274 | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:271:26 + --> $DIR/copies.rs:281:26 | -271 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +281 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:270:26 + --> $DIR/copies.rs:280:26 | -270 | (Some(a), ..) => bar(a), +280 | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:270:26 + --> $DIR/copies.rs:280:26 | -270 | (Some(a), ..) => bar(a), +280 | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:277:20 + --> $DIR/copies.rs:287:20 | -277 | (.., 3) => 42, //~ ERROR match arms have same body +287 | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:276:23 + --> $DIR/copies.rs:286:23 | -276 | (1, .., 3) => 42, +286 | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:276:23 + --> $DIR/copies.rs:286:23 | -276 | (1, .., 3) => 42, +286 | (1, .., 3) => 42, | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:283:12 + --> $DIR/copies.rs:293:12 | -283 | } else { //~ ERROR same body as `if` block +293 | } else { //~ ERROR same body as `if` block | ____________^ -284 | | 0.0 -285 | | }; +294 | | 0.0 +295 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:281:21 + --> $DIR/copies.rs:291:21 | -281 | let _ = if true { +291 | let _ = if true { | _____________________^ -282 | | 0.0 -283 | | } else { //~ ERROR same body as `if` block +292 | | 0.0 +293 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:289:12 + --> $DIR/copies.rs:299:12 | -289 | } else { //~ ERROR same body as `if` block +299 | } else { //~ ERROR same body as `if` block | ____________^ -290 | | -0.0 -291 | | }; +300 | | -0.0 +301 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:287:21 + --> $DIR/copies.rs:297:21 | -287 | let _ = if true { +297 | let _ = if true { | _____________________^ -288 | | -0.0 -289 | | } else { //~ ERROR same body as `if` block +298 | | -0.0 +299 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:309:12 + --> $DIR/copies.rs:319:12 | -309 | } else { //~ ERROR same body as `if` block +319 | } else { //~ ERROR same body as `if` block | ____________^ -310 | | std::f32::NAN -311 | | }; +320 | | std::f32::NAN +321 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:307:21 + --> $DIR/copies.rs:317:21 | -307 | let _ = if true { +317 | let _ = if true { | _____________________^ -308 | | std::f32::NAN -309 | | } else { //~ ERROR same body as `if` block +318 | | std::f32::NAN +319 | | } else { //~ ERROR same body as `if` block | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:327:10 + --> $DIR/copies.rs:337:10 | -327 | else { //~ ERROR same body as `if` block +337 | else { //~ ERROR same body as `if` block | __________^ -328 | | try!(Ok("foo")); -329 | | } +338 | | try!(Ok("foo")); +339 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:324:13 + --> $DIR/copies.rs:334:13 | -324 | if true { +334 | if true { | _____________^ -325 | | try!(Ok("foo")); -326 | | } +335 | | try!(Ok("foo")); +336 | | } | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:353:13 + --> $DIR/copies.rs:363:13 | -353 | else if b { //~ ERROR ifs same condition +363 | else if b { //~ ERROR ifs same condition | ^ | = note: `-D clippy::ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:351:8 + --> $DIR/copies.rs:361:8 | -351 | if b { +361 | if b { | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:13 + --> $DIR/copies.rs:368:13 | -358 | else if a == 1 { //~ ERROR ifs same condition +368 | else if a == 1 { //~ ERROR ifs same condition | ^^^^^^ | note: same as this - --> $DIR/copies.rs:356:8 + --> $DIR/copies.rs:366:8 | -356 | if a == 1 { +366 | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:365:13 + --> $DIR/copies.rs:375:13 | -365 | else if 2*a == 1 { //~ ERROR ifs same condition +375 | else if 2*a == 1 { //~ ERROR ifs same condition | ^^^^^^^^ | note: same as this - --> $DIR/copies.rs:361:8 + --> $DIR/copies.rs:371:8 | -361 | if 2*a == 1 { +371 | if 2*a == 1 { | ^^^^^^^^ error: aborting due to 20 previous errors diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index 5ccb9910c1e..6984b612f23 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::copy_iterator)] diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr index 9a06a52d4bb..4620958f47b 100644 --- a/tests/ui/copy_iterator.stderr +++ b/tests/ui/copy_iterator.stderr @@ -1,13 +1,13 @@ error: you are implementing `Iterator` on a `Copy` type - --> $DIR/copy_iterator.rs:8:1 + --> $DIR/copy_iterator.rs:18:1 | -8 | / impl Iterator for Countdown { -9 | | type Item = u8; -10 | | -11 | | fn next(&mut self) -> Option { +18 | / impl Iterator for Countdown { +19 | | type Item = u8; +20 | | +21 | | fn next(&mut self) -> Option { ... | -16 | | } -17 | | } +26 | | } +27 | | } | |_^ | = note: `-D clippy::copy-iterator` implied by `-D warnings` diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index e68874d5409..fd5d00059a7 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] fn main() {} diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 2b2b51de6ae..74d6e864de4 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,16 +1,16 @@ error: you are getting the inner pointer of a temporary `CString` - --> $DIR/cstring.rs:9:5 - | -9 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default - = note: that pointer will be invalid outside this expression + --> $DIR/cstring.rs:19:5 + | +19 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default + = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/cstring.rs:9:5 - | -9 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/cstring.rs:19:5 + | +19 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 84e2a1b6583..3c8ab8694a6 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::all)] diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index ff93f21e3ae..ddc2f5b159f 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -1,129 +1,115 @@ error: the function has a cyclomatic complexity of 28 - --> $DIR/cyclomatic_complexity.rs:7:1 + --> $DIR/cyclomatic_complexity.rs:17:1 | -7 | / fn main() { -8 | | if true { -9 | | println!("a"); -10 | | } +17 | / fn main() { +18 | | if true { +19 | | println!("a"); +20 | | } ... | -88 | | } -89 | | } +98 | | } +99 | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 - --> $DIR/cyclomatic_complexity.rs:92:1 + --> $DIR/cyclomatic_complexity.rs:102:1 | -92 | / fn kaboom() { -93 | | let n = 0; -94 | | 'a: for i in 0..20 { -95 | | 'b: for j in i..20 { +102 | / fn kaboom() { +103 | | let n = 0; +104 | | 'a: for i in 0..20 { +105 | | 'b: for j in i..20 { ... | -110 | | } -111 | | } +120 | | } +121 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:138:1 + --> $DIR/cyclomatic_complexity.rs:148:1 | -138 | / fn lots_of_short_circuits() -> bool { -139 | | true && false && true && false && true && false && true -140 | | } +148 | / fn lots_of_short_circuits() -> bool { +149 | | true && false && true && false && true && false && true +150 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:143:1 + --> $DIR/cyclomatic_complexity.rs:153:1 | -143 | / fn lots_of_short_circuits2() -> bool { -144 | | true || false || true || false || true || false || true -145 | | } +153 | / fn lots_of_short_circuits2() -> bool { +154 | | true || false || true || false || true || false || true +155 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:148:1 + --> $DIR/cyclomatic_complexity.rs:158:1 | -148 | / fn baa() { -149 | | let x = || match 99 { -150 | | 0 => 0, -151 | | 1 => 1, +158 | / fn baa() { +159 | | let x = || match 99 { +160 | | 0 => 0, +161 | | 1 => 1, ... | -162 | | } -163 | | } +172 | | } +173 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:149:13 + --> $DIR/cyclomatic_complexity.rs:159:13 | -149 | let x = || match 99 { +159 | let x = || match 99 { | _____________^ -150 | | 0 => 0, -151 | | 1 => 1, -152 | | 2 => 2, +160 | | 0 => 0, +161 | | 1 => 1, +162 | | 2 => 2, ... | -156 | | _ => 42, -157 | | }; +166 | | _ => 42, +167 | | }; | |_____^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:166:1 - | -166 | / fn bar() { -167 | | match 99 { -168 | | 0 => println!("hi"), -169 | | _ => println!("bye"), -170 | | } -171 | | } + --> $DIR/cyclomatic_complexity.rs:176:1 + | +176 | / fn bar() { +177 | | match 99 { +178 | | 0 => println!("hi"), +179 | | _ => println!("bye"), +180 | | } +181 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:185:1 - | -185 | / fn barr() { -186 | | match 99 { -187 | | 0 => println!("hi"), -188 | | 1 => println!("bla"), -... | -191 | | } -192 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions - -error: the function has a cyclomatic complexity of 3 --> $DIR/cyclomatic_complexity.rs:195:1 | -195 | / fn barr2() { +195 | / fn barr() { 196 | | match 99 { 197 | | 0 => println!("hi"), 198 | | 1 => println!("bla"), ... | -207 | | } -208 | | } +201 | | } +202 | | } | |_^ | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:211:1 +error: the function has a cyclomatic complexity of 3 + --> $DIR/cyclomatic_complexity.rs:205:1 | -211 | / fn barrr() { -212 | | match 99 { -213 | | 0 => println!("hi"), -214 | | 1 => panic!("bla"), +205 | / fn barr2() { +206 | | match 99 { +207 | | 0 => println!("hi"), +208 | | 1 => println!("bla"), ... | 217 | | } 218 | | } @@ -131,27 +117,27 @@ error: the function has a cyclomatic complexity of 2 | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 3 +error: the function has a cyclomatic complexity of 2 --> $DIR/cyclomatic_complexity.rs:221:1 | -221 | / fn barrr2() { +221 | / fn barrr() { 222 | | match 99 { 223 | | 0 => println!("hi"), 224 | | 1 => panic!("bla"), ... | -233 | | } -234 | | } +227 | | } +228 | | } | |_^ | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:237:1 +error: the function has a cyclomatic complexity of 3 + --> $DIR/cyclomatic_complexity.rs:231:1 | -237 | / fn barrrr() { -238 | | match 99 { -239 | | 0 => println!("hi"), -240 | | 1 => println!("bla"), +231 | / fn barrr2() { +232 | | match 99 { +233 | | 0 => println!("hi"), +234 | | 1 => panic!("bla"), ... | 243 | | } 244 | | } @@ -159,55 +145,56 @@ error: the function has a cyclomatic complexity of 2 | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 3 +error: the function has a cyclomatic complexity of 2 --> $DIR/cyclomatic_complexity.rs:247:1 | -247 | / fn barrrr2() { +247 | / fn barrrr() { 248 | | match 99 { 249 | | 0 => println!("hi"), 250 | | 1 => println!("bla"), ... | -259 | | } -260 | | } +253 | | } +254 | | } | |_^ | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:263:1 +error: the function has a cyclomatic complexity of 3 + --> $DIR/cyclomatic_complexity.rs:257:1 | -263 | / fn cake() { -264 | | if 4 == 5 { -265 | | println!("yea"); -266 | | } else { +257 | / fn barrrr2() { +258 | | match 99 { +259 | | 0 => println!("hi"), +260 | | 1 => println!("bla"), ... | -269 | | println!("whee"); +269 | | } 270 | | } | |_^ | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 4 - --> $DIR/cyclomatic_complexity.rs:274:1 +error: the function has a cyclomatic complexity of 2 + --> $DIR/cyclomatic_complexity.rs:273:1 | -274 | / pub fn read_file(input_path: &str) -> String { -275 | | use std::fs::File; -276 | | use std::io::{Read, Write}; -277 | | use std::path::Path; +273 | / fn cake() { +274 | | if 4 == 5 { +275 | | println!("yea"); +276 | | } else { ... | -299 | | } -300 | | } +279 | | println!("whee"); +280 | | } | |_^ | = help: you could split it up into multiple smaller functions -error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:305:1 +error: the function has a cyclomatic complexity of 4 + --> $DIR/cyclomatic_complexity.rs:284:1 | -305 | / fn void(void: Void) { -306 | | if true { -307 | | match void { -308 | | } +284 | / pub fn read_file(input_path: &str) -> String { +285 | | use std::fs::File; +286 | | use std::io::{Read, Write}; +287 | | use std::path::Path; +... | 309 | | } 310 | | } | |_^ @@ -215,56 +202,69 @@ error: the function has a cyclomatic complexity of 1 = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:319:1 - | -319 | / fn try() -> Result { -320 | | match 5 { -321 | | 5 => Ok(5), -322 | | _ => return Err("bla"), -323 | | } -324 | | } + --> $DIR/cyclomatic_complexity.rs:315:1 + | +315 | / fn void(void: Void) { +316 | | if true { +317 | | match void { +318 | | } +319 | | } +320 | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cyclomatic complexity of 1 + --> $DIR/cyclomatic_complexity.rs:329:1 + | +329 | / fn try() -> Result { +330 | | match 5 { +331 | | 5 => Ok(5), +332 | | _ => return Err("bla"), +333 | | } +334 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:327:1 + --> $DIR/cyclomatic_complexity.rs:337:1 | -327 | / fn try_again() -> Result { -328 | | let _ = try!(Ok(42)); -329 | | let _ = try!(Ok(43)); -330 | | let _ = try!(Ok(44)); +337 | / fn try_again() -> Result { +338 | | let _ = try!(Ok(42)); +339 | | let _ = try!(Ok(43)); +340 | | let _ = try!(Ok(44)); ... | -339 | | } -340 | | } +349 | | } +350 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:343:1 + --> $DIR/cyclomatic_complexity.rs:353:1 | -343 | / fn early() -> Result { -344 | | return Ok(5); -345 | | return Ok(5); -346 | | return Ok(5); +353 | / fn early() -> Result { +354 | | return Ok(5); +355 | | return Ok(5); +356 | | return Ok(5); ... | -352 | | return Ok(5); -353 | | } +362 | | return Ok(5); +363 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 8 - --> $DIR/cyclomatic_complexity.rs:356:1 + --> $DIR/cyclomatic_complexity.rs:366:1 | -356 | / fn early_ret() -> i32 { -357 | | let a = if true { 42 } else { return 0; }; -358 | | let a = if a < 99 { 42 } else { return 0; }; -359 | | let a = if a < 99 { 42 } else { return 0; }; +366 | / fn early_ret() -> i32 { +367 | | let a = if true { 42 } else { return 0; }; +368 | | let a = if a < 99 { 42 } else { return 0; }; +369 | | let a = if a < 99 { 42 } else { return 0; }; ... | -372 | | } -373 | | } +382 | | } +383 | | } | |_^ | = help: you could split it up into multiple smaller functions diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index fd8be25e670..1699601aa50 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::cyclomatic_complexity)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index f8342f0d9e5..f066e29ce75 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -1,13 +1,13 @@ error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity_attr_used.rs:11:1 + --> $DIR/cyclomatic_complexity_attr_used.rs:21:1 | -11 | / fn kaboom() { -12 | | if 42 == 43 { -13 | | panic!(); -14 | | } else if "cake" == "lie" { -15 | | println!("what?"); -16 | | } -17 | | } +21 | / fn kaboom() { +22 | | if 42 == 43 { +23 | | panic!(); +24 | | } else if "cake" == "lie" { +25 | | println!("what?"); +26 | | } +27 | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index 472ea618571..f85ccd84722 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index 343936bb7a2..d944c49066a 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,33 +1,33 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:18:9 + --> $DIR/decimal_literal_representation.rs:28:9 | -18 | 32_773, // 0x8005 +28 | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` | = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:19:9 + --> $DIR/decimal_literal_representation.rs:29:9 | -19 | 65_280, // 0xFF00 +29 | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:20:9 + --> $DIR/decimal_literal_representation.rs:30:9 | -20 | 2_131_750_927, // 0x7F0F_F00F +30 | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:21:9 + --> $DIR/decimal_literal_representation.rs:31:9 | -21 | 2_147_483_647, // 0x7FFF_FFFF +31 | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:22:9 + --> $DIR/decimal_literal_representation.rs:32:9 | -22 | 4_042_322_160, // 0xF0F0_F0F0 +32 | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 248b4ec0066..d268746d765 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::default_trait_access)] diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index e3c263e7732..d6ae00214c0 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,51 +1,51 @@ error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:10:22 + --> $DIR/default_trait_access.rs:20:22 | -10 | let s1: String = Default::default(); +20 | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` | = note: `-D clippy::default-trait-access` implied by `-D warnings` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:14:22 + --> $DIR/default_trait_access.rs:24:22 | -14 | let s3: String = D2::default(); +24 | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:16:22 + --> $DIR/default_trait_access.rs:26:22 | -16 | let s4: String = std::default::Default::default(); +26 | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:20:22 + --> $DIR/default_trait_access.rs:30:22 | -20 | let s6: String = default::Default::default(); +30 | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling GenericDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:30:46 + --> $DIR/default_trait_access.rs:40:46 | -30 | let s11: GenericDerivedDefault = Default::default(); +40 | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: Calling TupleDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:36:36 + --> $DIR/default_trait_access.rs:46:36 | -36 | let s14: TupleDerivedDefault = Default::default(); +46 | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: Calling ArrayDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:38:36 + --> $DIR/default_trait_access.rs:48:36 | -38 | let s15: ArrayDerivedDefault = Default::default(); +48 | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: Calling TupleStructDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:42:42 + --> $DIR/default_trait_access.rs:52:42 | -42 | let s17: TupleStructDerivedDefault = Default::default(); +52 | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` error: aborting due to 8 previous errors diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index f456c417223..a7e95ad5dde 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 6bbc0aebf9c..d44528ab28f 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -1,33 +1,33 @@ error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:4:8 - | -4 | #[warn(str_to_string)] - | ^^^^^^^^^^^^^ - | - = note: `-D renamed-and-removed-lints` implied by `-D warnings` + --> $DIR/deprecated.rs:14:8 + | +14 | #[warn(str_to_string)] + | ^^^^^^^^^^^^^ + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:6:8 - | -6 | #[warn(string_to_string)] - | ^^^^^^^^^^^^^^^^ + --> $DIR/deprecated.rs:16:8 + | +16 | #[warn(string_to_string)] + | ^^^^^^^^^^^^^^^^ error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:8:8 - | -8 | #[warn(unstable_as_slice)] - | ^^^^^^^^^^^^^^^^^ + --> $DIR/deprecated.rs:18:8 + | +18 | #[warn(unstable_as_slice)] + | ^^^^^^^^^^^^^^^^^ error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:10:8 + --> $DIR/deprecated.rs:20:8 | -10 | #[warn(unstable_as_mut_slice)] +20 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` - --> $DIR/deprecated.rs:12:8 + --> $DIR/deprecated.rs:22:8 | -12 | #[warn(misaligned_transmute)] +22 | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index ae54c0290bc..c5ce42586fa 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(untagged_unions)] diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index fa706f22b90..824b5b44cba 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -1,83 +1,67 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> $DIR/derive.rs:17:10 + --> $DIR/derive.rs:27:10 | -17 | #[derive(Hash)] +27 | #[derive(Hash)] | ^^^^ | = note: #[deny(clippy::derive_hash_xor_eq)] on by default note: `PartialEq` implemented here - --> $DIR/derive.rs:20:1 + --> $DIR/derive.rs:30:1 | -20 | / impl PartialEq for Bar { -21 | | fn eq(&self, _: &Bar) -> bool { true } -22 | | } +30 | / impl PartialEq for Bar { +31 | | fn eq(&self, _: &Bar) -> bool { true } +32 | | } | |_^ error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> $DIR/derive.rs:24:10 + --> $DIR/derive.rs:34:10 | -24 | #[derive(Hash)] +34 | #[derive(Hash)] | ^^^^ | note: `PartialEq` implemented here - --> $DIR/derive.rs:27:1 + --> $DIR/derive.rs:37:1 | -27 | / impl PartialEq for Baz { -28 | | fn eq(&self, _: &Baz) -> bool { true } -29 | | } +37 | / impl PartialEq for Baz { +38 | | fn eq(&self, _: &Baz) -> bool { true } +39 | | } | |_^ error: you are implementing `Hash` explicitly but have derived `PartialEq` - --> $DIR/derive.rs:34:1 + --> $DIR/derive.rs:44:1 | -34 | / impl Hash for Bah { -35 | | fn hash(&self, _: &mut H) {} -36 | | } +44 | / impl Hash for Bah { +45 | | fn hash(&self, _: &mut H) {} +46 | | } | |_^ | note: `PartialEq` implemented here - --> $DIR/derive.rs:31:10 + --> $DIR/derive.rs:41:10 | -31 | #[derive(PartialEq)] +41 | #[derive(PartialEq)] | ^^^^^^^^^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:41:1 + --> $DIR/derive.rs:51:1 | -41 | / impl Clone for Qux { -42 | | fn clone(&self) -> Self { Qux } -43 | | } +51 | / impl Clone for Qux { +52 | | fn clone(&self) -> Self { Qux } +53 | | } | |_^ | = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:41:1 + --> $DIR/derive.rs:51:1 | -41 | / impl Clone for Qux { -42 | | fn clone(&self) -> Self { Qux } -43 | | } - | |_^ - -error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:65:1 - | -65 | / impl<'a> Clone for Lt<'a> { -66 | | fn clone(&self) -> Self { unimplemented!() } -67 | | } - | |_^ - | -note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:65:1 - | -65 | / impl<'a> Clone for Lt<'a> { -66 | | fn clone(&self) -> Self { unimplemented!() } -67 | | } +51 | / impl Clone for Qux { +52 | | fn clone(&self) -> Self { Qux } +53 | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type --> $DIR/derive.rs:75:1 | -75 | / impl Clone for BigArray { +75 | / impl<'a> Clone for Lt<'a> { 76 | | fn clone(&self) -> Self { unimplemented!() } 77 | | } | |_^ @@ -85,7 +69,7 @@ error: you are implementing `Clone` explicitly on a `Copy` type note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:75:1 | -75 | / impl Clone for BigArray { +75 | / impl<'a> Clone for Lt<'a> { 76 | | fn clone(&self) -> Self { unimplemented!() } 77 | | } | |_^ @@ -93,7 +77,7 @@ note: consider deriving `Clone` or removing `Copy` error: you are implementing `Clone` explicitly on a `Copy` type --> $DIR/derive.rs:85:1 | -85 | / impl Clone for FnPtr { +85 | / impl Clone for BigArray { 86 | | fn clone(&self) -> Self { unimplemented!() } 87 | | } | |_^ @@ -101,10 +85,26 @@ error: you are implementing `Clone` explicitly on a `Copy` type note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:85:1 | -85 | / impl Clone for FnPtr { +85 | / impl Clone for BigArray { 86 | | fn clone(&self) -> Self { unimplemented!() } 87 | | } | |_^ +error: you are implementing `Clone` explicitly on a `Copy` type + --> $DIR/derive.rs:95:1 + | +95 | / impl Clone for FnPtr { +96 | | fn clone(&self) -> Self { unimplemented!() } +97 | | } + | |_^ + | +note: consider deriving `Clone` or removing `Copy` + --> $DIR/derive.rs:95:1 + | +95 | / impl Clone for FnPtr { +96 | | fn clone(&self) -> Self { unimplemented!() } +97 | | } + | |_^ + error: aborting due to 7 previous errors diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index a8284dca326..9cf6f22fb27 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(never_type)] diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 8e86a7734dc..fea2bd1aa41 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,39 +1,39 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:20:10 + --> $DIR/diverging_sub_expression.rs:30:10 | -20 | b || diverge(); +30 | b || diverge(); | ^^^^^^^^^ | = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:21:10 + --> $DIR/diverging_sub_expression.rs:31:10 | -21 | b || A.foo(); +31 | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:30:26 + --> $DIR/diverging_sub_expression.rs:40:26 | -30 | 6 => true || return, +40 | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:31:26 + --> $DIR/diverging_sub_expression.rs:41:26 | -31 | 7 => true || continue, +41 | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:34:26 + --> $DIR/diverging_sub_expression.rs:44:26 | -34 | 3 => true || diverge(), +44 | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:39:26 + --> $DIR/diverging_sub_expression.rs:49:26 | -39 | _ => true || break, +49 | _ => true || break, | ^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 395ff217497..dbbac901b03 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(alloc)] diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index 5322075208c..b3dc6095cd8 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -1,48 +1,48 @@ error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:14:16 + --> $DIR/dlist.rs:24:16 | -14 | type Baz = LinkedList; +24 | type Baz = LinkedList; | ^^^^^^^^^^^^^^ | = note: `-D clippy::linkedlist` implied by `-D warnings` = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:15:12 + --> $DIR/dlist.rs:25:12 | -15 | fn foo(LinkedList); +25 | fn foo(LinkedList); | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:16:24 + --> $DIR/dlist.rs:26:24 | -16 | const BAR : Option>; +26 | const BAR : Option>; | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:27:15 + --> $DIR/dlist.rs:37:15 | -27 | fn foo(_: LinkedList) {} +37 | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:30:39 + --> $DIR/dlist.rs:40:39 | -30 | pub fn test(my_favourite_linked_list: LinkedList) { +40 | pub fn test(my_favourite_linked_list: LinkedList) { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:34:29 + --> $DIR/dlist.rs:44:29 | -34 | pub fn test_ret() -> Option> { +44 | pub fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index d48007a9347..85e688e0f07 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] //! This file tests for the DOC_MARKDOWN lint diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index c781f36db7a..69fa4e32cd3 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -1,183 +1,183 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation - --> $DIR/doc.rs:3:29 - | -3 | //! This file tests for the DOC_MARKDOWN lint - | ^^^^^^^^^^^^ - | - = note: `-D clippy::doc-markdown` implied by `-D warnings` + --> $DIR/doc.rs:13:29 + | +13 | //! This file tests for the DOC_MARKDOWN lint + | ^^^^^^^^^^^^ + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` error: you should put `foo_bar` between ticks in the documentation - --> $DIR/doc.rs:10:9 + --> $DIR/doc.rs:20:9 | -10 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +20 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^ error: you should put `foo::bar` between ticks in the documentation - --> $DIR/doc.rs:10:51 + --> $DIR/doc.rs:20:51 | -10 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +20 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^^ error: you should put `Foo::some_fun` between ticks in the documentation - --> $DIR/doc.rs:11:84 + --> $DIR/doc.rs:21:84 | -11 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun +21 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun | ^^^^^^^^^^^^^ error: you should put `a::global:path` between ticks in the documentation - --> $DIR/doc.rs:13:15 + --> $DIR/doc.rs:23:15 | -13 | /// Here be ::a::global:path. +23 | /// Here be ::a::global:path. | ^^^^^^^^^^^^^^ error: you should put `NotInCodeBlock` between ticks in the documentation - --> $DIR/doc.rs:14:22 + --> $DIR/doc.rs:24:22 | -14 | /// That's not code ~NotInCodeBlock~. +24 | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:15:5 + --> $DIR/doc.rs:25:5 | -15 | /// be_sure_we_got_to_the_end_of_it +25 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:29:5 + --> $DIR/doc.rs:39:5 | -29 | /// be_sure_we_got_to_the_end_of_it +39 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:36:5 + --> $DIR/doc.rs:46:5 | -36 | /// be_sure_we_got_to_the_end_of_it +46 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:50:5 + --> $DIR/doc.rs:60:5 | -50 | /// be_sure_we_got_to_the_end_of_it +60 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:54:22 + --> $DIR/doc.rs:64:22 | -54 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. +64 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:57:21 + --> $DIR/doc.rs:67:21 | -57 | /// It can also be [inline_link2]. +67 | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:67:5 + --> $DIR/doc.rs:77:5 | -67 | /// be_sure_we_got_to_the_end_of_it +77 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:75:8 + --> $DIR/doc.rs:85:8 | -75 | /// ## CamelCaseThing +85 | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:78:7 + --> $DIR/doc.rs:88:7 | -78 | /// # CamelCaseThing +88 | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:80:22 + --> $DIR/doc.rs:90:22 | -80 | /// Not a title #897 CamelCaseThing +90 | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:81:5 + --> $DIR/doc.rs:91:5 | -81 | /// be_sure_we_got_to_the_end_of_it +91 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:88:5 + --> $DIR/doc.rs:98:5 | -88 | /// be_sure_we_got_to_the_end_of_it +98 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:101:5 + --> $DIR/doc.rs:111:5 | -101 | /// be_sure_we_got_to_the_end_of_it +111 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:112:42 + --> $DIR/doc.rs:122:42 | -112 | /** E.g. serialization of an empty list: FooBar +122 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:117:5 + --> $DIR/doc.rs:127:5 | -117 | And BarQuz too. +127 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:118:1 + --> $DIR/doc.rs:128:1 | -118 | be_sure_we_got_to_the_end_of_it +128 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:123:42 + --> $DIR/doc.rs:133:42 | -123 | /** E.g. serialization of an empty list: FooBar +133 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:128:5 + --> $DIR/doc.rs:138:5 | -128 | And BarQuz too. +138 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:129:1 + --> $DIR/doc.rs:139:1 | -129 | be_sure_we_got_to_the_end_of_it +139 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:140:5 + --> $DIR/doc.rs:150:5 | -140 | /// be_sure_we_got_to_the_end_of_it +150 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:167:13 + --> $DIR/doc.rs:177:13 | -167 | /// Not ok: http://www.unicode.org +177 | /// Not ok: http://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:168:13 + --> $DIR/doc.rs:178:13 | -168 | /// Not ok: https://www.unicode.org +178 | /// Not ok: https://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:169:13 + --> $DIR/doc.rs:179:13 | -169 | /// Not ok: http://www.unicode.org/ +179 | /// Not ok: http://www.unicode.org/ | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:170:13 + --> $DIR/doc.rs:180:13 | -170 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +180 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 30 previous errors diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 2c8f116281b..555f35884f9 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { let x = 1; let y = 2; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index e6a0e976414..646b6f13fab 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,51 +1,51 @@ error: This binary expression can be simplified - --> $DIR/double_comparison.rs:4:8 - | -4 | if x == y || x < y { - | ^^^^^^^^^^^^^^^ help: try: `x <= y` - | - = note: `-D clippy::double-comparisons` implied by `-D warnings` + --> $DIR/double_comparison.rs:14:8 + | +14 | if x == y || x < y { + | ^^^^^^^^^^^^^^^ help: try: `x <= y` + | + = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:7:8 - | -7 | if x < y || x == y { - | ^^^^^^^^^^^^^^^ help: try: `x <= y` + --> $DIR/double_comparison.rs:17:8 + | +17 | if x < y || x == y { + | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:10:8 + --> $DIR/double_comparison.rs:20:8 | -10 | if x == y || x > y { +20 | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:13:8 + --> $DIR/double_comparison.rs:23:8 | -13 | if x > y || x == y { +23 | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:16:8 + --> $DIR/double_comparison.rs:26:8 | -16 | if x < y || x > y { +26 | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:19:8 + --> $DIR/double_comparison.rs:29:8 | -19 | if x > y || x < y { +29 | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:22:8 + --> $DIR/double_comparison.rs:32:8 | -22 | if x <= y && x >= y { +32 | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:25:8 + --> $DIR/double_comparison.rs:35:8 | -25 | if x >= y && x <= y { +35 | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: aborting due to 8 previous errors diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index 0ec13900f99..31e7a508fcd 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index 02202dbd63c..cf0292f7af1 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -1,10 +1,10 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op - --> $DIR/double_neg.rs:9:5 - | -9 | --x; - | ^^^ - | - = note: `-D clippy::double-neg` implied by `-D warnings` + --> $DIR/double_neg.rs:19:5 + | +19 | --x; + | ^^^ + | + = note: `-D clippy::double-neg` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index c217972fa6a..18ff140c3ca 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index 3e38db730e0..727b2c4ef42 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -1,39 +1,39 @@ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:16:5 + --> $DIR/double_parens.rs:26:5 | -16 | ((0)) +26 | ((0)) | ^^^^^ | = note: `-D clippy::double-parens` implied by `-D warnings` error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:20:14 + --> $DIR/double_parens.rs:30:14 | -20 | dummy_fn((0)); +30 | dummy_fn((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:24:20 + --> $DIR/double_parens.rs:34:20 | -24 | x.dummy_method((0)); +34 | x.dummy_method((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:28:5 + --> $DIR/double_parens.rs:38:5 | -28 | ((1, 2)) +38 | ((1, 2)) | ^^^^^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:32:5 + --> $DIR/double_parens.rs:42:5 | -32 | (()) +42 | (()) | ^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:54:16 + --> $DIR/double_parens.rs:64:16 | -54 | assert_eq!(((1, 2)), (1, 2), "Error"); +64 | assert_eq!(((1, 2)), (1, 2), "Error"); | ^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index aa70490f8ab..8b2b96a14d3 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index 043067fe8af..ef337ae6691 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -1,75 +1,75 @@ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:33:5 + --> $DIR/drop_forget_copy.rs:43:5 | -33 | drop(s1); +43 | drop(s1); | ^^^^^^^^ | = note: `-D clippy::drop-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:33:10 + --> $DIR/drop_forget_copy.rs:43:10 | -33 | drop(s1); +43 | drop(s1); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:34:5 + --> $DIR/drop_forget_copy.rs:44:5 | -34 | drop(s2); +44 | drop(s2); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:34:10 + --> $DIR/drop_forget_copy.rs:44:10 | -34 | drop(s2); +44 | drop(s2); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:36:5 + --> $DIR/drop_forget_copy.rs:46:5 | -36 | drop(s4); +46 | drop(s4); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:36:10 + --> $DIR/drop_forget_copy.rs:46:10 | -36 | drop(s4); +46 | drop(s4); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:39:5 + --> $DIR/drop_forget_copy.rs:49:5 | -39 | forget(s1); +49 | forget(s1); | ^^^^^^^^^^ | = note: `-D clippy::forget-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:39:12 + --> $DIR/drop_forget_copy.rs:49:12 | -39 | forget(s1); +49 | forget(s1); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:40:5 + --> $DIR/drop_forget_copy.rs:50:5 | -40 | forget(s2); +50 | forget(s2); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:40:12 + --> $DIR/drop_forget_copy.rs:50:12 | -40 | forget(s2); +50 | forget(s2); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:42:5 + --> $DIR/drop_forget_copy.rs:52:5 | -42 | forget(s4); +52 | forget(s4); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:42:12 + --> $DIR/drop_forget_copy.rs:52:12 | -42 | forget(s4); +52 | forget(s4); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index bb4781db71b..0f36b823e0f 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 227918f5917..15661ef1d2b 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -1,219 +1,219 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:12:5 + --> $DIR/drop_forget_ref.rs:22:5 | -12 | drop(&SomeStruct); +22 | drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::drop-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:12:10 + --> $DIR/drop_forget_ref.rs:22:10 | -12 | drop(&SomeStruct); +22 | drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:13:5 + --> $DIR/drop_forget_ref.rs:23:5 | -13 | forget(&SomeStruct); +23 | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:13:12 + --> $DIR/drop_forget_ref.rs:23:12 | -13 | forget(&SomeStruct); +23 | forget(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:16:5 + --> $DIR/drop_forget_ref.rs:26:5 | -16 | drop(&owned1); +26 | drop(&owned1); | ^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:16:10 + --> $DIR/drop_forget_ref.rs:26:10 | -16 | drop(&owned1); +26 | drop(&owned1); | ^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:17:5 + --> $DIR/drop_forget_ref.rs:27:5 | -17 | drop(&&owned1); +27 | drop(&&owned1); | ^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:17:10 + --> $DIR/drop_forget_ref.rs:27:10 | -17 | drop(&&owned1); +27 | drop(&&owned1); | ^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:18:5 + --> $DIR/drop_forget_ref.rs:28:5 | -18 | drop(&mut owned1); +28 | drop(&mut owned1); | ^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:18:10 + --> $DIR/drop_forget_ref.rs:28:10 | -18 | drop(&mut owned1); +28 | drop(&mut owned1); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:21:5 + --> $DIR/drop_forget_ref.rs:31:5 | -21 | forget(&owned2); +31 | forget(&owned2); | ^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:21:12 + --> $DIR/drop_forget_ref.rs:31:12 | -21 | forget(&owned2); +31 | forget(&owned2); | ^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:22:5 + --> $DIR/drop_forget_ref.rs:32:5 | -22 | forget(&&owned2); +32 | forget(&&owned2); | ^^^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:22:12 + --> $DIR/drop_forget_ref.rs:32:12 | -22 | forget(&&owned2); +32 | forget(&&owned2); | ^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:23:5 + --> $DIR/drop_forget_ref.rs:33:5 | -23 | forget(&mut owned2); +33 | forget(&mut owned2); | ^^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:23:12 + --> $DIR/drop_forget_ref.rs:33:12 | -23 | forget(&mut owned2); +33 | forget(&mut owned2); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:27:5 + --> $DIR/drop_forget_ref.rs:37:5 | -27 | drop(reference1); +37 | drop(reference1); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:27:10 + --> $DIR/drop_forget_ref.rs:37:10 | -27 | drop(reference1); +37 | drop(reference1); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:28:5 + --> $DIR/drop_forget_ref.rs:38:5 | -28 | forget(&*reference1); +38 | forget(&*reference1); | ^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:28:12 + --> $DIR/drop_forget_ref.rs:38:12 | -28 | forget(&*reference1); +38 | forget(&*reference1); | ^^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:31:5 + --> $DIR/drop_forget_ref.rs:41:5 | -31 | drop(reference2); +41 | drop(reference2); | ^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:31:10 + --> $DIR/drop_forget_ref.rs:41:10 | -31 | drop(reference2); +41 | drop(reference2); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:33:5 + --> $DIR/drop_forget_ref.rs:43:5 | -33 | forget(reference3); +43 | forget(reference3); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:33:12 + --> $DIR/drop_forget_ref.rs:43:12 | -33 | forget(reference3); +43 | forget(reference3); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:36:5 + --> $DIR/drop_forget_ref.rs:46:5 | -36 | drop(reference4); +46 | drop(reference4); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:36:10 + --> $DIR/drop_forget_ref.rs:46:10 | -36 | drop(reference4); +46 | drop(reference4); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:37:5 + --> $DIR/drop_forget_ref.rs:47:5 | -37 | forget(reference4); +47 | forget(reference4); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:37:12 + --> $DIR/drop_forget_ref.rs:47:12 | -37 | forget(reference4); +47 | forget(reference4); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:42:5 + --> $DIR/drop_forget_ref.rs:52:5 | -42 | drop(&val); +52 | drop(&val); | ^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:42:10 + --> $DIR/drop_forget_ref.rs:52:10 | -42 | drop(&val); +52 | drop(&val); | ^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:48:5 + --> $DIR/drop_forget_ref.rs:58:5 | -48 | forget(&val); +58 | forget(&val); | ^^^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:48:12 + --> $DIR/drop_forget_ref.rs:58:12 | -48 | forget(&val); +58 | forget(&val); | ^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:56:5 + --> $DIR/drop_forget_ref.rs:66:5 | -56 | std::mem::drop(&SomeStruct); +66 | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:56:20 + --> $DIR/drop_forget_ref.rs:66:20 | -56 | std::mem::drop(&SomeStruct); +66 | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:59:5 + --> $DIR/drop_forget_ref.rs:69:5 | -59 | std::mem::forget(&SomeStruct); +69 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:59:22 + --> $DIR/drop_forget_ref.rs:69:22 | -59 | std::mem::forget(&SomeStruct); +69 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ error: aborting due to 18 previous errors diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index e54920c1b56..25b2a0ba8b6 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index 70714534653..87b5c5e19d9 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -1,10 +1,10 @@ error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult - --> $DIR/duplicate_underscore_argument.rs:7:23 - | -7 | fn join_the_dark_side(darth: i32, _darth: i32) {} - | ^^^^^ - | - = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` + --> $DIR/duplicate_underscore_argument.rs:17:23 + | +17 | fn join_the_dark_side(darth: i32, _darth: i32) {} + | ^^^^^ + | + = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index d732a0228d5..75352ad182b 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::duration_subsec)] diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index c23b041a80a..854af9dcb51 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,33 +1,33 @@ error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:10:24 + --> $DIR/duration_subsec.rs:20:24 | -10 | let bad_millis_1 = dur.subsec_micros() / 1_000; +20 | let bad_millis_1 = dur.subsec_micros() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` | = note: `-D clippy::duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:11:24 + --> $DIR/duration_subsec.rs:21:24 | -11 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; +21 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:16:22 + --> $DIR/duration_subsec.rs:26:22 | -16 | let bad_micros = dur.subsec_nanos() / 1_000; +26 | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:21:13 + --> $DIR/duration_subsec.rs:31:13 | -21 | let _ = (&dur).subsec_nanos() / 1_000; +31 | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:25:13 + --> $DIR/duration_subsec.rs:35:13 | -25 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; +35 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: aborting due to 5 previous errors diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 3776aecf54f..56987d0d64d 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all)] diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index a352546ce9f..9eddd4ab30d 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,21 +1,21 @@ error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:41:12 + --> $DIR/else_if_without_else.rs:51:12 | -41 | } else if bla2() { //~ ERROR else if without else +51 | } else if bla2() { //~ ERROR else if without else | ____________^ -42 | | println!("else if"); -43 | | } +52 | | println!("else if"); +53 | | } | |_____^ help: add an `else` block here | = note: `-D clippy::else-if-without-else` implied by `-D warnings` error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:49:12 + --> $DIR/else_if_without_else.rs:59:12 | -49 | } else if bla3() { //~ ERROR else if without else +59 | } else if bla3() { //~ ERROR else if without else | ____________^ -50 | | println!("else if 2"); -51 | | } +60 | | println!("else if 2"); +61 | | } | |_____^ help: add an `else` block here error: aborting due to 2 previous errors diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index 3398b71eead..cd63acb9ed6 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index f198793fed4..9d6691c974d 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -1,15 +1,15 @@ error: enum with no variants - --> $DIR/empty_enum.rs:7:1 - | -7 | enum Empty {} - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::empty-enum` implied by `-D warnings` + --> $DIR/empty_enum.rs:17:1 + | +17 | enum Empty {} + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::empty-enum` implied by `-D warnings` help: consider using the uninhabited type `!` or a wrapper around it - --> $DIR/empty_enum.rs:7:1 - | -7 | enum Empty {} - | ^^^^^^^^^^^^^ + --> $DIR/empty_enum.rs:17:1 + | +17 | enum Empty {} + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index c46a0496a73..8aa2e8a1f46 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::empty_line_after_outer_attr)] diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index 7bcec54a600..e742c0b6615 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,53 +1,53 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:5:1 - | -5 | / #[crate_type = "lib"] -6 | | -7 | | /// some comment -8 | | fn with_one_newline_and_comment() { assert!(true) } - | |_ - | - = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` + --> $DIR/empty_line_after_outer_attribute.rs:15:1 + | +15 | / #[crate_type = "lib"] +16 | | +17 | | /// some comment +18 | | fn with_one_newline_and_comment() { assert!(true) } + | |_ + | + = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:17:1 + --> $DIR/empty_line_after_outer_attribute.rs:27:1 | -17 | / #[crate_type = "lib"] -18 | | -19 | | fn with_one_newline() { assert!(true) } +27 | / #[crate_type = "lib"] +28 | | +29 | | fn with_one_newline() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:22:1 + --> $DIR/empty_line_after_outer_attribute.rs:32:1 | -22 | / #[crate_type = "lib"] -23 | | -24 | | -25 | | fn with_two_newlines() { assert!(true) } +32 | / #[crate_type = "lib"] +33 | | +34 | | +35 | | fn with_two_newlines() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:29:1 + --> $DIR/empty_line_after_outer_attribute.rs:39:1 | -29 | / #[crate_type = "lib"] -30 | | -31 | | enum Baz { +39 | / #[crate_type = "lib"] +40 | | +41 | | enum Baz { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:37:1 + --> $DIR/empty_line_after_outer_attribute.rs:47:1 | -37 | / #[crate_type = "lib"] -38 | | -39 | | struct Foo { +47 | / #[crate_type = "lib"] +48 | | +49 | | struct Foo { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:45:1 + --> $DIR/empty_line_after_outer_attribute.rs:55:1 | -45 | / #[crate_type = "lib"] -46 | | -47 | | mod foo { +55 | / #[crate_type = "lib"] +56 | | +57 | | mod foo { | |_ error: aborting due to 6 previous errors diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 955b0a6e917..0bab6bf332e 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused, clippy::needless_pass_by_value)] diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index cffe8b23235..60e5ae893b6 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -1,45 +1,45 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:13:5 + --> $DIR/entry.rs:23:5 | -13 | if !m.contains_key(&k) { m.insert(k, v); } +23 | if !m.contains_key(&k) { m.insert(k, v); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k).or_insert(v)` | = note: `-D clippy::map-entry` implied by `-D warnings` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:17:5 + --> $DIR/entry.rs:27:5 | -17 | if !m.contains_key(&k) { foo(); m.insert(k, v); } +27 | if !m.contains_key(&k) { foo(); m.insert(k, v); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:21:5 + --> $DIR/entry.rs:31:5 | -21 | if !m.contains_key(&k) { m.insert(k, v) } else { None }; +31 | if !m.contains_key(&k) { m.insert(k, v) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:25:5 + --> $DIR/entry.rs:35:5 | -25 | if m.contains_key(&k) { None } else { m.insert(k, v) }; +35 | if m.contains_key(&k) { None } else { m.insert(k, v) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:29:5 + --> $DIR/entry.rs:39:5 | -29 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; +39 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:33:5 + --> $DIR/entry.rs:43:5 | -33 | if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; +43 | if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `BTreeMap` - --> $DIR/entry.rs:37:5 + --> $DIR/entry.rs:47:5 | -37 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; +47 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` error: aborting due to 7 previous errors diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 47082f8f3e6..e24e2fd8eb3 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all, clippy::pedantic)] diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index bb1d19e41b2..2dac4a2b106 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -1,15 +1,15 @@ error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:6:1 - | -6 | use std::cmp::Ordering::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::enum-glob-use` implied by `-D warnings` + --> $DIR/enum_glob_use.rs:16:1 + | +16 | use std::cmp::Ordering::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::enum-glob-use` implied by `-D warnings` error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:12:1 + --> $DIR/enum_glob_use.rs:22:1 | -12 | use self::Enum::*; +22 | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 4ddb7207a30..8a51e2f58f1 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(non_ascii_idents)] diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index bd083e7e069..7b63fab3a99 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,101 +1,101 @@ error: Variant name ends with the enum's name - --> $DIR/enum_variants.rs:16:5 + --> $DIR/enum_variants.rs:26:5 | -16 | cFoo, +26 | cFoo, | ^^^^ | = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:27:5 + --> $DIR/enum_variants.rs:37:5 | -27 | FoodGood, +37 | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:28:5 + --> $DIR/enum_variants.rs:38:5 | -28 | FoodMiddle, +38 | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:29:5 + --> $DIR/enum_variants.rs:39:5 | -29 | FoodBad, +39 | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:26:1 + --> $DIR/enum_variants.rs:36:1 | -26 | / enum Food { -27 | | FoodGood, -28 | | FoodMiddle, -29 | | FoodBad, -30 | | } +36 | / enum Food { +37 | | FoodGood, +38 | | FoodMiddle, +39 | | FoodBad, +40 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:36:1 + --> $DIR/enum_variants.rs:46:1 | -36 | / enum BadCallType { -37 | | CallTypeCall, -38 | | CallTypeCreate, -39 | | CallTypeDestroy, -40 | | } +46 | / enum BadCallType { +47 | | CallTypeCall, +48 | | CallTypeCreate, +49 | | CallTypeDestroy, +50 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:47:1 + --> $DIR/enum_variants.rs:57:1 | -47 | / enum Consts { -48 | | ConstantInt, -49 | | ConstantCake, -50 | | ConstantLie, -51 | | } +57 | / enum Consts { +58 | | ConstantInt, +59 | | ConstantCake, +60 | | ConstantLie, +61 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:80:1 + --> $DIR/enum_variants.rs:90:1 | -80 | / enum Seallll { -81 | | WithOutCake, -82 | | WithOutTea, -83 | | WithOut, -84 | | } +90 | / enum Seallll { +91 | | WithOutCake, +92 | | WithOutTea, +93 | | WithOut, +94 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:86:1 - | -86 | / enum NonCaps { -87 | | Prefix的, -88 | | PrefixTea, -89 | | PrefixCake, -90 | | } - | |_^ - | - = help: remove the prefixes and use full paths to the variants instead of glob imports + --> $DIR/enum_variants.rs:96:1 + | +96 | / enum NonCaps { +97 | | Prefix的, +98 | | PrefixTea, +99 | | PrefixCake, +100 | | } + | |_^ + | + = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:92:1 - | -92 | / pub enum PubSeall { -93 | | WithOutCake, -94 | | WithOutTea, -95 | | WithOut, -96 | | } - | |_^ - | - = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` - = help: remove the prefixes and use full paths to the variants instead of glob imports + --> $DIR/enum_variants.rs:102:1 + | +102 | / pub enum PubSeall { +103 | | WithOutCake, +104 | | WithOutTea, +105 | | WithOut, +106 | | } + | |_^ + | + = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` + = help: remove the prefixes and use full paths to the variants instead of glob imports error: aborting due to 10 previous errors diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index 8212f12b3db..17983255030 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] // ignore-x86 diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index cccf4ed030c..27b184ea3cc 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -1,51 +1,51 @@ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:12:5 + --> $DIR/enums_clike.rs:22:5 | -12 | X = 0x1_0000_0000, +22 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:19:5 + --> $DIR/enums_clike.rs:29:5 | -19 | X = 0x1_0000_0000, +29 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:22:5 + --> $DIR/enums_clike.rs:32:5 | -22 | A = 0xFFFF_FFFF, +32 | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:29:5 + --> $DIR/enums_clike.rs:39:5 | -29 | Z = 0xFFFF_FFFF, +39 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:30:5 + --> $DIR/enums_clike.rs:40:5 | -30 | A = 0x1_0000_0000, +40 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:32:5 + --> $DIR/enums_clike.rs:42:5 | -32 | C = (std::i32::MIN as isize) - 1, +42 | C = (std::i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:38:5 + --> $DIR/enums_clike.rs:48:5 | -38 | Z = 0xFFFF_FFFF, +48 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:39:5 + --> $DIR/enums_clike.rs:49:5 | -39 | A = 0x1_0000_0000, +49 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index a88866436dd..c96cd8b9af2 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index ad0c8d8ecd7..21487884d35 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,203 +1,203 @@ error: this boolean expression can be simplified - --> $DIR/eq_op.rs:37:5 + --> $DIR/eq_op.rs:47:5 | -37 | true && true; +47 | true && true; | ^^^^^^^^^^^^ help: try: `true` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:39:5 + --> $DIR/eq_op.rs:49:5 | -39 | true || true; +49 | true || true; | ^^^^^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:45:5 + --> $DIR/eq_op.rs:55:5 | -45 | a == b && b == a; +55 | a == b && b == a; | ^^^^^^^^^^^^^^^^ help: try: `a == b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:56:5 | -46 | a != b && b != a; +56 | a != b && b != a; | ^^^^^^^^^^^^^^^^ help: try: `a != b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:47:5 + --> $DIR/eq_op.rs:57:5 | -47 | a < b && b > a; +57 | a < b && b > a; | ^^^^^^^^^^^^^^ help: try: `a < b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:48:5 + --> $DIR/eq_op.rs:58:5 | -48 | a <= b && b >= a; +58 | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ help: try: `a <= b` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:10:5 + --> $DIR/eq_op.rs:20:5 | -10 | 1 == 1; +20 | 1 == 1; | ^^^^^^ | = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:11:5 + --> $DIR/eq_op.rs:21:5 | -11 | "no" == "no"; +21 | "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:13:5 + --> $DIR/eq_op.rs:23:5 | -13 | false != false; +23 | false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:14:5 + --> $DIR/eq_op.rs:24:5 | -14 | 1.5 < 1.5; +24 | 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:15:5 + --> $DIR/eq_op.rs:25:5 | -15 | 1u64 >= 1u64; +25 | 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:18:5 + --> $DIR/eq_op.rs:28:5 | -18 | (1 as u64) & (1 as u64); +28 | (1 as u64) & (1 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:19:5 + --> $DIR/eq_op.rs:29:5 | -19 | 1 ^ ((((((1)))))); +29 | 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:22:5 + --> $DIR/eq_op.rs:32:5 | -22 | (-(2) < -(2)); +32 | (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:23:5 + --> $DIR/eq_op.rs:33:5 | -23 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:23:6 + --> $DIR/eq_op.rs:33:6 | -23 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:23:27 + --> $DIR/eq_op.rs:33:27 | -23 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:24:5 + --> $DIR/eq_op.rs:34:5 | -24 | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; +34 | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:27:5 + --> $DIR/eq_op.rs:37:5 | -27 | ([1] != [1]); +37 | ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:28:5 + --> $DIR/eq_op.rs:38:5 | -28 | ((1, 2) != (1, 2)); +38 | ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:32:5 + --> $DIR/eq_op.rs:42:5 | -32 | 1 + 1 == 2; +42 | 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:33:5 + --> $DIR/eq_op.rs:43:5 | -33 | 1 - 1 == 0; +43 | 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:33:5 + --> $DIR/eq_op.rs:43:5 | -33 | 1 - 1 == 0; +43 | 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:35:5 + --> $DIR/eq_op.rs:45:5 | -35 | 1 - 1; +45 | 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:36:5 + --> $DIR/eq_op.rs:46:5 | -36 | 1 / 1; +46 | 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:37:5 + --> $DIR/eq_op.rs:47:5 | -37 | true && true; +47 | true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:39:5 + --> $DIR/eq_op.rs:49:5 | -39 | true || true; +49 | true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:45:5 + --> $DIR/eq_op.rs:55:5 | -45 | a == b && b == a; +55 | a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:56:5 | -46 | a != b && b != a; +56 | a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:47:5 + --> $DIR/eq_op.rs:57:5 | -47 | a < b && b > a; +57 | a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:48:5 + --> $DIR/eq_op.rs:58:5 | -48 | a <= b && b >= a; +58 | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:51:5 + --> $DIR/eq_op.rs:61:5 | -51 | a == a; +61 | a == a; | ^^^^^^ error: taken reference of right operand - --> $DIR/eq_op.rs:89:13 + --> $DIR/eq_op.rs:99:13 | -89 | let z = x & &y; +99 | let z = x & &y; | ^^^^-- | | | help: use the right value directly: `y` @@ -205,10 +205,10 @@ error: taken reference of right operand = note: `-D clippy::op-ref` implied by `-D warnings` error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:97:20 - | -97 | const D: u32 = A / A; - | ^^^^^ + --> $DIR/eq_op.rs:107:20 + | +107 | const D: u32 = A / A; + | ^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index 02745ac5d91..1c572b55554 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 18486ab4781..2cc3db7c268 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -1,21 +1,21 @@ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:9:5 - | -9 | x * 0; - | ^^^^^ - | - = note: `-D clippy::erasing-op` implied by `-D warnings` + --> $DIR/erasing_op.rs:19:5 + | +19 | x * 0; + | ^^^^^ + | + = note: `-D clippy::erasing-op` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:10:5 + --> $DIR/erasing_op.rs:20:5 | -10 | 0 & x; +20 | 0 & x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:11:5 + --> $DIR/erasing_op.rs:21:5 | -11 | 0 / x; +21 | 0 / x; | ^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index 7a888f01914..1f2f46b03cd 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(box_syntax)] #![allow(warnings, clippy)] diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 4dd46f20e76..a580ce0831a 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unknown_lints, unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 89543d6af0c..dcdf0699ff7 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,35 +1,35 @@ error: redundant closure found - --> $DIR/eta.rs:7:27 - | -7 | let a = Some(1u8).map(|a| foo(a)); - | ^^^^^^^^^^ help: remove closure as shown: `foo` - | - = note: `-D clippy::redundant-closure` implied by `-D warnings` + --> $DIR/eta.rs:17:27 + | +17 | let a = Some(1u8).map(|a| foo(a)); + | ^^^^^^^^^^ help: remove closure as shown: `foo` + | + = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:8:10 - | -8 | meta(|a| foo(a)); - | ^^^^^^^^^^ help: remove closure as shown: `foo` + --> $DIR/eta.rs:18:10 + | +18 | meta(|a| foo(a)); + | ^^^^^^^^^^ help: remove closure as shown: `foo` error: redundant closure found - --> $DIR/eta.rs:9:27 - | -9 | let c = Some(1u8).map(|a| {1+2; foo}(a)); - | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` + --> $DIR/eta.rs:19:27 + | +19 | let c = Some(1u8).map(|a| {1+2; foo}(a)); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/eta.rs:11:21 + --> $DIR/eta.rs:21:21 | -11 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted +21 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` | = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:18:27 + --> $DIR/eta.rs:28:27 | -18 | let e = Some(1u8).map(|a| generic(a)); +28 | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: aborting due to 5 previous errors diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index b240dde06f8..4e525b9b2b0 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index 3caba829be4..d5be92e993f 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -1,50 +1,50 @@ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:8:28 - | -8 | let a = { x = 1; 1 } + x; - | ^ - | - = note: `-D clippy::eval-order-dependence` implied by `-D warnings` + --> $DIR/eval_order_dependence.rs:18:28 + | +18 | let a = { x = 1; 1 } + x; + | ^ + | + = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:8:15 - | -8 | let a = { x = 1; 1 } + x; - | ^^^^^ + --> $DIR/eval_order_dependence.rs:18:15 + | +18 | let a = { x = 1; 1 } + x; + | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:11:5 + --> $DIR/eval_order_dependence.rs:21:5 | -11 | x += { x = 20; 2 }; +21 | x += { x = 20; 2 }; | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:11:12 + --> $DIR/eval_order_dependence.rs:21:12 | -11 | x += { x = 20; 2 }; +21 | x += { x = 20; 2 }; | ^^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:17:24 + --> $DIR/eval_order_dependence.rs:27:24 | -17 | let foo = Foo { a: x, .. { x = 6; base } }; +27 | let foo = Foo { a: x, .. { x = 6; base } }; | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:17:32 + --> $DIR/eval_order_dependence.rs:27:32 | -17 | let foo = Foo { a: x, .. { x = 6; base } }; +27 | let foo = Foo { a: x, .. { x = 6; base } }; | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:21:9 + --> $DIR/eval_order_dependence.rs:31:9 | -21 | x += { x = 20; 2 }; +31 | x += { x = 20; 2 }; | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:21:16 + --> $DIR/eval_order_dependence.rs:31:16 | -21 | x += { x = 20; 2 }; +31 | x += { x = 20; 2 }; | ^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 1b3412166d4..ab0412a16b5 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::excessive_precision)] #![allow(clippy::print_literal)] diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index bb0546cdcc6..783e41f2b50 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,111 +1,111 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:15:26 + --> $DIR/excessive_precision.rs:25:26 | -15 | const BAD32_1: f32 = 0.123_456_789_f32; +25 | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` | = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:16:26 + --> $DIR/excessive_precision.rs:26:26 | -16 | const BAD32_2: f32 = 0.123_456_789; +26 | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:17:26 + --> $DIR/excessive_precision.rs:27:26 | -17 | const BAD32_3: f32 = 0.100_000_000_000_1; +27 | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:18:29 + --> $DIR/excessive_precision.rs:28:29 | -18 | const BAD32_EDGE: f32 = 1.000_000_9; +28 | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:20:26 + --> $DIR/excessive_precision.rs:30:26 | -20 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; +30 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:21:26 + --> $DIR/excessive_precision.rs:31:26 | -21 | const BAD64_2: f64 = 0.123_456_789_012_345_67; +31 | const BAD64_2: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:22:26 + --> $DIR/excessive_precision.rs:32:26 | -22 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; +32 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:25:22 + --> $DIR/excessive_precision.rs:35:22 | -25 | println!("{:?}", 8.888_888_888_888_888_888_888); +35 | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:36:22 + --> $DIR/excessive_precision.rs:46:22 | -36 | let bad32: f32 = 1.123_456_789; +46 | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:37:26 + --> $DIR/excessive_precision.rs:47:26 | -37 | let bad32_suf: f32 = 1.123_456_789_f32; +47 | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:38:21 + --> $DIR/excessive_precision.rs:48:21 | -38 | let bad32_inf = 1.123_456_789_f32; +48 | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:40:22 + --> $DIR/excessive_precision.rs:50:22 | -40 | let bad64: f64 = 0.123_456_789_012_345_67; +50 | let bad64: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:41:26 + --> $DIR/excessive_precision.rs:51:26 | -41 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; +51 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:42:21 + --> $DIR/excessive_precision.rs:52:21 | -42 | let bad64_inf = 0.123_456_789_012_345_67; +52 | let bad64_inf = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:36 + --> $DIR/excessive_precision.rs:58:36 | -48 | let bad_vec32: Vec = vec![0.123_456_789]; +58 | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:49:36 + --> $DIR/excessive_precision.rs:59:36 | -49 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; +59 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:53:24 + --> $DIR/excessive_precision.rs:63:24 | -53 | let bad_e32: f32 = 1.123_456_788_888e-10; +63 | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:56:27 + --> $DIR/excessive_precision.rs:66:27 | -56 | let bad_bige32: f32 = 1.123_456_788_888E-10; +66 | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` error: aborting due to 18 previous errors diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 9d6d13c84c5..2a748d25724 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::explicit_write)] diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index fb14120b16d..fadc12c7594 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,39 +1,39 @@ error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:18:9 + --> $DIR/explicit_write.rs:28:9 | -18 | write!(std::io::stdout(), "test").unwrap(); +28 | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:19:9 + --> $DIR/explicit_write.rs:29:9 | -19 | write!(std::io::stderr(), "test").unwrap(); +29 | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead - --> $DIR/explicit_write.rs:20:9 + --> $DIR/explicit_write.rs:30:9 | -20 | writeln!(std::io::stdout(), "test").unwrap(); +30 | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead - --> $DIR/explicit_write.rs:21:9 + --> $DIR/explicit_write.rs:31:9 | -21 | writeln!(std::io::stderr(), "test").unwrap(); +31 | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:22:9 + --> $DIR/explicit_write.rs:32:9 | -22 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); +32 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:23:9 + --> $DIR/explicit_write.rs:33:9 | -23 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); +33 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index 5e33cca59fa..1e1e24ee954 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::fallible_impl_from)] diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 4dbc7879d31..97ece931464 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -1,91 +1,91 @@ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:7:1 + --> $DIR/fallible_impl_from.rs:17:1 | -7 | / impl From for Foo { -8 | | fn from(s: String) -> Self { -9 | | Foo(s.parse().unwrap()) -10 | | } -11 | | } +17 | / impl From for Foo { +18 | | fn from(s: String) -> Self { +19 | | Foo(s.parse().unwrap()) +20 | | } +21 | | } | |_^ | note: lint level defined here - --> $DIR/fallible_impl_from.rs:3:9 + --> $DIR/fallible_impl_from.rs:13:9 | -3 | #![deny(clippy::fallible_impl_from)] +13 | #![deny(clippy::fallible_impl_from)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:9:13 + --> $DIR/fallible_impl_from.rs:19:13 | -9 | Foo(s.parse().unwrap()) +19 | Foo(s.parse().unwrap()) | ^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:30:1 + --> $DIR/fallible_impl_from.rs:40:1 | -30 | / impl From for Invalid { -31 | | fn from(i: usize) -> Invalid { -32 | | if i != 42 { -33 | | panic!(); +40 | / impl From for Invalid { +41 | | fn from(i: usize) -> Invalid { +42 | | if i != 42 { +43 | | panic!(); ... | -36 | | } -37 | | } +46 | | } +47 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:33:13 + --> $DIR/fallible_impl_from.rs:43:13 | -33 | panic!(); +43 | panic!(); | ^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:39:1 + --> $DIR/fallible_impl_from.rs:49:1 | -39 | / impl From> for Invalid { -40 | | fn from(s: Option) -> Invalid { -41 | | let s = s.unwrap(); -42 | | if !s.is_empty() { +49 | / impl From> for Invalid { +50 | | fn from(s: Option) -> Invalid { +51 | | let s = s.unwrap(); +52 | | if !s.is_empty() { ... | -48 | | } -49 | | } +58 | | } +59 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:41:17 + --> $DIR/fallible_impl_from.rs:51:17 | -41 | let s = s.unwrap(); +51 | let s = s.unwrap(); | ^^^^^^^^^^ -42 | if !s.is_empty() { -43 | panic!(42); +52 | if !s.is_empty() { +53 | panic!(42); | ^^^^^^^^^^^ -44 | } else if s.parse::().unwrap() != 42 { +54 | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -45 | panic!("{:?}", s); +55 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:57:1 + --> $DIR/fallible_impl_from.rs:67:1 | -57 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { -58 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -59 | | if s.parse::().ok().unwrap() != 42 { -60 | | panic!("{:?}", s); +67 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +68 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +69 | | if s.parse::().ok().unwrap() != 42 { +70 | | panic!("{:?}", s); ... | -63 | | } -64 | | } +73 | | } +74 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:59:12 + --> $DIR/fallible_impl_from.rs:69:12 | -59 | if s.parse::().ok().unwrap() != 42 { +69 | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -60 | panic!("{:?}", s); +70 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index d7a50a58838..1bfc03356fb 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index 1fde70601aa..6adbec44cf9 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -1,39 +1,39 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:8:21 + --> $DIR/filter_methods.rs:18:21 | -8 | let _: Vec<_> = vec![5; 6].into_iter() +18 | let _: Vec<_> = vec![5; 6].into_iter() | _____________________^ -9 | | .filter(|&x| x == 0) -10 | | .map(|x| x * 2) +19 | | .filter(|&x| x == 0) +20 | | .map(|x| x * 2) | |_____________________________________________^ | = note: `-D clippy::filter-map` implied by `-D warnings` error: called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:13:21 + --> $DIR/filter_methods.rs:23:21 | -13 | let _: Vec<_> = vec![5_i8; 6].into_iter() +23 | let _: Vec<_> = vec![5_i8; 6].into_iter() | _____________________^ -14 | | .filter(|&x| x == 0) -15 | | .flat_map(|x| x.checked_mul(2)) +24 | | .filter(|&x| x == 0) +25 | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________________________________^ error: called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:18:21 + --> $DIR/filter_methods.rs:28:21 | -18 | let _: Vec<_> = vec![5_i8; 6].into_iter() +28 | let _: Vec<_> = vec![5_i8; 6].into_iter() | _____________________^ -19 | | .filter_map(|x| x.checked_mul(2)) -20 | | .flat_map(|x| x.checked_mul(2)) +29 | | .filter_map(|x| x.checked_mul(2)) +30 | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________________________________^ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly expressed by only calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:23:21 + --> $DIR/filter_methods.rs:33:21 | -23 | let _: Vec<_> = vec![5_i8; 6].into_iter() +33 | let _: Vec<_> = vec![5_i8; 6].into_iter() | _____________________^ -24 | | .filter_map(|x| x.checked_mul(2)) -25 | | .map(|x| x.checked_mul(2)) +34 | | .filter_map(|x| x.checked_mul(2)) +35 | | .map(|x| x.checked_mul(2)) | |__________________________________________________________^ error: aborting due to 4 previous errors diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index d5b02fb706f..cb8b7a98e39 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index 598ebf33668..52ec0e3ed78 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,38 +1,38 @@ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:49:5 + --> $DIR/float_cmp.rs:59:5 | -49 | ONE as f64 != 2.0; +59 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | = note: `-D clippy::float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:49:5 + --> $DIR/float_cmp.rs:59:5 | -49 | ONE as f64 != 2.0; +59 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:54:5 + --> $DIR/float_cmp.rs:64:5 | -54 | x == 1.0; +64 | x == 1.0; | ^^^^^^^^ help: consider comparing them within some error: `(x - 1.0).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:54:5 + --> $DIR/float_cmp.rs:64:5 | -54 | x == 1.0; +64 | x == 1.0; | ^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:57:5 + --> $DIR/float_cmp.rs:67:5 | -57 | twice(x) != twice(ONE as f64); +67 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(x) - twice(ONE as f64)).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:57:5 + --> $DIR/float_cmp.rs:67:5 | -57 | twice(x) != twice(ONE as f64); +67 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 279400604a2..27d829ed105 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index 14083979511..d9b1d268505 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -1,86 +1,86 @@ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:17:5 + --> $DIR/float_cmp_const.rs:27:5 | -17 | 1f32 == ONE; +27 | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | = note: `-D clippy::float-cmp-const` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:17:5 + --> $DIR/float_cmp_const.rs:27:5 | -17 | 1f32 == ONE; +27 | 1f32 == ONE; | ^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:18:5 + --> $DIR/float_cmp_const.rs:28:5 | -18 | TWO == ONE; +28 | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:18:5 + --> $DIR/float_cmp_const.rs:28:5 | -18 | TWO == ONE; +28 | TWO == ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:19:5 + --> $DIR/float_cmp_const.rs:29:5 | -19 | TWO != ONE; +29 | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:19:5 + --> $DIR/float_cmp_const.rs:29:5 | -19 | TWO != ONE; +29 | TWO != ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:20:5 + --> $DIR/float_cmp_const.rs:30:5 | -20 | ONE + ONE == TWO; +30 | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:20:5 + --> $DIR/float_cmp_const.rs:30:5 | -20 | ONE + ONE == TWO; +30 | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:21:5 + --> $DIR/float_cmp_const.rs:31:5 | -21 | 1 as f32 == ONE; +31 | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(1 as f32 - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:21:5 + --> $DIR/float_cmp_const.rs:31:5 | -21 | 1 as f32 == ONE; +31 | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:24:5 + --> $DIR/float_cmp_const.rs:34:5 | -24 | v == ONE; +34 | v == ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:24:5 + --> $DIR/float_cmp_const.rs:34:5 | -24 | v == ONE; +34 | v == ONE; | ^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:25:5 + --> $DIR/float_cmp_const.rs:35:5 | -25 | v != ONE; +35 | v != ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:25:5 + --> $DIR/float_cmp_const.rs:35:5 | -25 | v != ONE; +35 | v != ONE; | ^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index fc8aa19dcf0..0066b9a3587 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // only-64bit #![feature(tool_lints)] diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index 29320f0d8ed..2e186145eae 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -1,143 +1,143 @@ error: casting function pointer `foo` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:9:13 - | -9 | let _ = foo as i8; - | ^^^^^^^^^ help: try: `foo as usize` - | - = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` + --> $DIR/fn_to_numeric_cast.rs:19:13 + | +19 | let _ = foo as i8; + | ^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` error: casting function pointer `foo` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:10:13 + --> $DIR/fn_to_numeric_cast.rs:20:13 | -10 | let _ = foo as i16; +20 | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:11:13 + --> $DIR/fn_to_numeric_cast.rs:21:13 | -11 | let _ = foo as i32; +21 | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i64` - --> $DIR/fn_to_numeric_cast.rs:12:13 + --> $DIR/fn_to_numeric_cast.rs:22:13 | -12 | let _ = foo as i64; +22 | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` | = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` error: casting function pointer `foo` to `i128` - --> $DIR/fn_to_numeric_cast.rs:13:13 + --> $DIR/fn_to_numeric_cast.rs:23:13 | -13 | let _ = foo as i128; +23 | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> $DIR/fn_to_numeric_cast.rs:14:13 + --> $DIR/fn_to_numeric_cast.rs:24:13 | -14 | let _ = foo as isize; +24 | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:16:13 + --> $DIR/fn_to_numeric_cast.rs:26:13 | -16 | let _ = foo as u8; +26 | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:17:13 + --> $DIR/fn_to_numeric_cast.rs:27:13 | -17 | let _ = foo as u16; +27 | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:18:13 + --> $DIR/fn_to_numeric_cast.rs:28:13 | -18 | let _ = foo as u32; +28 | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> $DIR/fn_to_numeric_cast.rs:19:13 + --> $DIR/fn_to_numeric_cast.rs:29:13 | -19 | let _ = foo as u64; +29 | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> $DIR/fn_to_numeric_cast.rs:20:13 + --> $DIR/fn_to_numeric_cast.rs:30:13 | -20 | let _ = foo as u128; +30 | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:29:13 + --> $DIR/fn_to_numeric_cast.rs:39:13 | -29 | let _ = abc as i8; +39 | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:30:13 + --> $DIR/fn_to_numeric_cast.rs:40:13 | -30 | let _ = abc as i16; +40 | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:31:13 + --> $DIR/fn_to_numeric_cast.rs:41:13 | -31 | let _ = abc as i32; +41 | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> $DIR/fn_to_numeric_cast.rs:32:13 + --> $DIR/fn_to_numeric_cast.rs:42:13 | -32 | let _ = abc as i64; +42 | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> $DIR/fn_to_numeric_cast.rs:33:13 + --> $DIR/fn_to_numeric_cast.rs:43:13 | -33 | let _ = abc as i128; +43 | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> $DIR/fn_to_numeric_cast.rs:34:13 + --> $DIR/fn_to_numeric_cast.rs:44:13 | -34 | let _ = abc as isize; +44 | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:36:13 + --> $DIR/fn_to_numeric_cast.rs:46:13 | -36 | let _ = abc as u8; +46 | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:37:13 + --> $DIR/fn_to_numeric_cast.rs:47:13 | -37 | let _ = abc as u16; +47 | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:38:13 + --> $DIR/fn_to_numeric_cast.rs:48:13 | -38 | let _ = abc as u32; +48 | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> $DIR/fn_to_numeric_cast.rs:39:13 + --> $DIR/fn_to_numeric_cast.rs:49:13 | -39 | let _ = abc as u64; +49 | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> $DIR/fn_to_numeric_cast.rs:40:13 + --> $DIR/fn_to_numeric_cast.rs:50:13 | -40 | let _ = abc as u128; +50 | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:47:5 + --> $DIR/fn_to_numeric_cast.rs:57:5 | -47 | f as i32 +57 | f as i32 | ^^^^^^^^ help: try: `f as usize` error: aborting due to 23 previous errors diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 55060b0769d..cff7075543b 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index d829147541e..472fa148609 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,502 +1,502 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:17:14 + --> $DIR/for_loop.rs:27:14 | -17 | for x in option { +27 | for x in option { | ^^^^^^ | = note: `-D clippy::for-loop-over-option` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:22:14 + --> $DIR/for_loop.rs:32:14 | -22 | for x in result { +32 | for x in result { | ^^^^^^ | = note: `-D clippy::for-loop-over-result` implied by `-D warnings` = help: consider replacing `for x in result` with `if let Ok(x) = result` error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:26:14 + --> $DIR/for_loop.rs:36:14 | -26 | for x in option.ok_or("x not found") { +36 | for x in option.ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:32:14 + --> $DIR/for_loop.rs:42:14 | -32 | for x in v.iter().next() { +42 | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:37:14 + --> $DIR/for_loop.rs:47:14 | -37 | for x in v.iter().next().and(Some(0)) { +47 | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:41:14 + --> $DIR/for_loop.rs:51:14 | -41 | for x in v.iter().next().ok_or("x not found") { +51 | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop.rs:53:5 + --> $DIR/for_loop.rs:63:5 | -53 | / while let Some(x) = option { -54 | | println!("{}", x); -55 | | break; -56 | | } +63 | / while let Some(x) = option { +64 | | println!("{}", x); +65 | | break; +66 | | } | |_____^ | = note: `-D clippy::never-loop` implied by `-D warnings` error: this loop never actually loops - --> $DIR/for_loop.rs:59:5 + --> $DIR/for_loop.rs:69:5 | -59 | / while let Ok(x) = result { -60 | | println!("{}", x); -61 | | break; -62 | | } +69 | / while let Ok(x) = result { +70 | | println!("{}", x); +71 | | break; +72 | | } | |_____^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:86:14 + --> $DIR/for_loop.rs:96:14 | -86 | for i in 0..vec.len() { +96 | for i in 0..vec.len() { | ^^^^^^^^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -86 | for in &vec { +96 | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:95:14 - | -95 | for i in 0..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:105:14 + | +105 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -95 | for in &vec { - | ^^^^^^ ^^^^ + | +105 | for in &vec { + | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:100:14 + --> $DIR/for_loop.rs:110:14 | -100 | for j in 0..4 { +110 | for j in 0..4 { | ^^^^ help: consider using an iterator | -100 | for in STATIC.iter().take(4) { +110 | for in STATIC.iter().take(4) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `j` is only used to index `CONST`. - --> $DIR/for_loop.rs:104:14 + --> $DIR/for_loop.rs:114:14 | -104 | for j in 0..4 { +114 | for j in 0..4 { | ^^^^ help: consider using an iterator | -104 | for in CONST.iter().take(4) { +114 | for in CONST.iter().take(4) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:108:14 + --> $DIR/for_loop.rs:118:14 | -108 | for i in 0..vec.len() { +118 | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -108 | for (i, ) in vec.iter().enumerate() { +118 | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:116:14 + --> $DIR/for_loop.rs:126:14 | -116 | for i in 0..vec.len() { +126 | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -116 | for in vec2.iter().take(vec.len()) { +126 | for in vec2.iter().take(vec.len()) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:120:14 + --> $DIR/for_loop.rs:130:14 | -120 | for i in 5..vec.len() { +130 | for i in 5..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -120 | for in vec.iter().skip(5) { +130 | for in vec.iter().skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:124:14 + --> $DIR/for_loop.rs:134:14 | -124 | for i in 0..MAX_LEN { +134 | for i in 0..MAX_LEN { | ^^^^^^^^^^ help: consider using an iterator | -124 | for in vec.iter().take(MAX_LEN) { +134 | for in vec.iter().take(MAX_LEN) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:128:14 + --> $DIR/for_loop.rs:138:14 | -128 | for i in 0..=MAX_LEN { +138 | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ help: consider using an iterator | -128 | for in vec.iter().take(MAX_LEN + 1) { +138 | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:132:14 + --> $DIR/for_loop.rs:142:14 | -132 | for i in 5..10 { +142 | for i in 5..10 { | ^^^^^ help: consider using an iterator | -132 | for in vec.iter().take(10).skip(5) { +142 | for in vec.iter().take(10).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:136:14 + --> $DIR/for_loop.rs:146:14 | -136 | for i in 5..=10 { +146 | for i in 5..=10 { | ^^^^^^ help: consider using an iterator | -136 | for in vec.iter().take(10 + 1).skip(5) { +146 | for in vec.iter().take(10 + 1).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:140:14 + --> $DIR/for_loop.rs:150:14 | -140 | for i in 5..vec.len() { +150 | for i in 5..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -140 | for (i, ) in vec.iter().enumerate().skip(5) { +150 | for (i, ) in vec.iter().enumerate().skip(5) { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:144:14 + --> $DIR/for_loop.rs:154:14 | -144 | for i in 5..10 { +154 | for i in 5..10 { | ^^^^^ help: consider using an iterator | -144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { +154 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:148:14 + --> $DIR/for_loop.rs:158:14 | -148 | for i in 10..0 { +158 | for i in 10..0 { | ^^^^^ | = note: `-D clippy::reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | -148 | for i in (0..10).rev() { +158 | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:152:14 + --> $DIR/for_loop.rs:162:14 | -152 | for i in 10..=0 { +162 | for i in 10..=0 { | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -152 | for i in (0...10).rev() { +162 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:156:14 + --> $DIR/for_loop.rs:166:14 | -156 | for i in MAX_LEN..0 { +166 | for i in MAX_LEN..0 { | ^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -156 | for i in (0..MAX_LEN).rev() { +166 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:160:14 + --> $DIR/for_loop.rs:170:14 | -160 | for i in 5..5 { +170 | for i in 5..5 { | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:185:14 + --> $DIR/for_loop.rs:195:14 | -185 | for i in 10..5 + 4 { +195 | for i in 10..5 + 4 { | ^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -185 | for i in (5 + 4..10).rev() { +195 | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:189:14 + --> $DIR/for_loop.rs:199:14 | -189 | for i in (5 + 2)..(3 - 1) { +199 | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -189 | for i in ((3 - 1)..(5 + 2)).rev() { +199 | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:193:14 + --> $DIR/for_loop.rs:203:14 | -193 | for i in (5 + 2)..(8 - 1) { +203 | for i in (5 + 2)..(8 - 1) { | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:215:15 + --> $DIR/for_loop.rs:225:15 | -215 | for _v in vec.iter() {} +225 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:217:15 + --> $DIR/for_loop.rs:227:15 | -217 | for _v in vec.iter_mut() {} +227 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:220:15 + --> $DIR/for_loop.rs:230:15 | -220 | for _v in out_vec.into_iter() {} +230 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:223:15 + --> $DIR/for_loop.rs:233:15 | -223 | for _v in array.into_iter() {} +233 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:228:15 + --> $DIR/for_loop.rs:238:15 | -228 | for _v in [1, 2, 3].iter() {} +238 | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:232:15 + --> $DIR/for_loop.rs:242:15 | -232 | for _v in [0; 32].iter() {} +242 | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:237:15 + --> $DIR/for_loop.rs:247:15 | -237 | for _v in ll.iter() {} +247 | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:240:15 + --> $DIR/for_loop.rs:250:15 | -240 | for _v in vd.iter() {} +250 | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:243:15 + --> $DIR/for_loop.rs:253:15 | -243 | for _v in bh.iter() {} +253 | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:246:15 + --> $DIR/for_loop.rs:256:15 | -246 | for _v in hm.iter() {} +256 | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:249:15 + --> $DIR/for_loop.rs:259:15 | -249 | for _v in bt.iter() {} +259 | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:252:15 + --> $DIR/for_loop.rs:262:15 | -252 | for _v in hs.iter() {} +262 | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:255:15 + --> $DIR/for_loop.rs:265:15 | -255 | for _v in bs.iter() {} +265 | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:257:15 + --> $DIR/for_loop.rs:267:15 | -257 | for _v in vec.iter().next() {} +267 | for _v in vec.iter().next() {} | ^^^^^^^^^^^^^^^^^ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:264:5 + --> $DIR/for_loop.rs:274:5 | -264 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); +274 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:269:15 + --> $DIR/for_loop.rs:279:15 | -269 | for _v in &vec { +279 | for _v in &vec { | ^^^^ | = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:275:15 + --> $DIR/for_loop.rs:285:15 | -275 | for _v in &vec { +285 | for _v in &vec { | ^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:385:19 + --> $DIR/for_loop.rs:395:19 | -385 | for (_, v) in &m { +395 | for (_, v) in &m { | ^^ | = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method | -385 | for v in m.values() { +395 | for v in m.values() { | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:390:19 + --> $DIR/for_loop.rs:400:19 | -390 | for (_, v) in &*m { +400 | for (_, v) in &*m { | ^^^ help: use the corresponding method | -390 | for v in (*m).values() { +400 | for v in (*m).values() { | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:398:19 + --> $DIR/for_loop.rs:408:19 | -398 | for (_, v) in &mut m { +408 | for (_, v) in &mut m { | ^^^^^^ help: use the corresponding method | -398 | for v in m.values_mut() { +408 | for v in m.values_mut() { | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:403:19 + --> $DIR/for_loop.rs:413:19 | -403 | for (_, v) in &mut *m { +413 | for (_, v) in &mut *m { | ^^^^^^^ help: use the corresponding method | -403 | for v in (*m).values_mut() { +413 | for v in (*m).values_mut() { | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:409:24 + --> $DIR/for_loop.rs:419:24 | -409 | for (k, _value) in rm { +419 | for (k, _value) in rm { | ^^ help: use the corresponding method | -409 | for k in rm.keys() { +419 | for k in rm.keys() { | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:462:14 + --> $DIR/for_loop.rs:472:14 | -462 | for i in 0..src.len() { +472 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:467:14 + --> $DIR/for_loop.rs:477:14 | -467 | for i in 0..src.len() { +477 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 + --> $DIR/for_loop.rs:482:14 | -472 | for i in 0..src.len() { +482 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:477:14 + --> $DIR/for_loop.rs:487:14 | -477 | for i in 11..src.len() { +487 | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:482:14 + --> $DIR/for_loop.rs:492:14 | -482 | for i in 0..dst.len() { +492 | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:495:14 + --> $DIR/for_loop.rs:505:14 | -495 | for i in 10..256 { +505 | for i in 10..256 { | ^^^^^^^ help: try replacing the loop by | -495 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { +505 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +506 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:507:14 + --> $DIR/for_loop.rs:517:14 | -507 | for i in 10..LOOP_OFFSET { +517 | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:520:14 + --> $DIR/for_loop.rs:530:14 | -520 | for i in 0..src_vec.len() { +530 | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:547:14 + --> $DIR/for_loop.rs:557:14 | -547 | for i in 0..src.len() { +557 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:608:19 + --> $DIR/for_loop.rs:618:19 | -608 | for ch in text.chars() { +618 | for ch in text.chars() { | ^^^^^^^^^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:619:19 + --> $DIR/for_loop.rs:629:19 | -619 | for ch in text.chars() { +629 | for ch in text.chars() { | ^^^^^^^^^^^^ error: aborting due to 61 previous errors diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 858c9fc8de5..5679a55755c 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::print_literal)] #![warn(clippy::useless_format)] diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 520c1b79433..c4ecd1dcc00 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,71 +1,71 @@ error: useless use of `format!` - --> $DIR/format.rs:12:5 + --> $DIR/format.rs:22:5 | -12 | format!("foo"); +22 | format!("foo"); | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:14:5 + --> $DIR/format.rs:24:5 | -14 | format!("{}", "foo"); +24 | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:18:5 + --> $DIR/format.rs:28:5 | -18 | format!("{:+}", "foo"); // warn when the format makes no difference +28 | format!("{:+}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:19:5 + --> $DIR/format.rs:29:5 | -19 | format!("{:<}", "foo"); // warn when the format makes no difference +29 | format!("{:<}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:24:5 + --> $DIR/format.rs:34:5 | -24 | format!("{}", arg); +34 | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:28:5 + --> $DIR/format.rs:38:5 | -28 | format!("{:+}", arg); // warn when the format makes no difference +38 | format!("{:+}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:29:5 + --> $DIR/format.rs:39:5 | -29 | format!("{:<}", arg); // warn when the format makes no difference +39 | format!("{:<}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:56:5 + --> $DIR/format.rs:66:5 | -56 | format!("{}", 42.to_string()); +66 | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:58:5 + --> $DIR/format.rs:68:5 | -58 | format!("{}", x.display().to_string()); +68 | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 74d42f08f5a..15aff5a3bba 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index d9fee73660c..e1620b22125 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,87 +1,87 @@ error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:15:6 + --> $DIR/formatting.rs:25:6 | -15 | } if foo() { +25 | } if foo() { | ^ | = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:22:10 + --> $DIR/formatting.rs:32:10 | -22 | } if foo() { +32 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:30:10 + --> $DIR/formatting.rs:40:10 | -30 | } if foo() { +40 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:39:6 + --> $DIR/formatting.rs:49:6 | -39 | } else +49 | } else | ______^ -40 | | if foo() { // the span of the above error should continue here +50 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:44:6 + --> $DIR/formatting.rs:54:6 | -44 | } +54 | } | ______^ -45 | | else -46 | | if foo() { // the span of the above error should continue here +55 | | else +56 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:71:6 + --> $DIR/formatting.rs:81:6 | -71 | a =- 35; +81 | a =- 35; | ^^^^ | = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:72:6 + --> $DIR/formatting.rs:82:6 | -72 | a =* &191; +82 | a =* &191; | ^^^^ | = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:75:6 + --> $DIR/formatting.rs:85:6 | -75 | b =! false; +85 | b =! false; | ^^^^ | = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:84:19 + --> $DIR/formatting.rs:94:19 | -84 | -1, -2, -3 // <= no comma here +94 | -1, -2, -3 // <= no comma here | ^ | = note: `-D clippy::possible-missing-comma` implied by `-D warnings` = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:88:19 + --> $DIR/formatting.rs:98:19 | -88 | -1, -2, -3 // <= no comma here +98 | -1, -2, -3 // <= no comma here | ^ | = note: to remove this lint, add a comma or write the expr in a single line diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index ab5ce5b06d8..136adef823b 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index c2f7b76aab4..9c45eb033ea 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -1,78 +1,78 @@ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:11:1 + --> $DIR/functions.rs:21:1 | -11 | / fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { -12 | | } +21 | / fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { +22 | | } | |_^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` error: this function has too many arguments (8/7) - --> $DIR/functions.rs:19:5 + --> $DIR/functions.rs:29:5 | -19 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); +29 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:28:5 + --> $DIR/functions.rs:38:5 | -28 | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +38 | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:37:34 + --> $DIR/functions.rs:47:34 | -37 | println!("{}", unsafe { *p }); +47 | println!("{}", unsafe { *p }); | ^ | = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:38:35 + --> $DIR/functions.rs:48:35 | -38 | println!("{:?}", unsafe { p.as_ref() }); +48 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:39:33 + --> $DIR/functions.rs:49:33 | -39 | unsafe { std::ptr::read(p) }; +49 | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:50:30 + --> $DIR/functions.rs:60:30 | -50 | println!("{}", unsafe { *p }); +60 | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:51:31 + --> $DIR/functions.rs:61:31 | -51 | println!("{:?}", unsafe { p.as_ref() }); +61 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:52:29 + --> $DIR/functions.rs:62:29 | -52 | unsafe { std::ptr::read(p) }; +62 | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:61:34 + --> $DIR/functions.rs:71:34 | -61 | println!("{}", unsafe { *p }); +71 | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:62:35 + --> $DIR/functions.rs:72:35 | -62 | println!("{:?}", unsafe { p.as_ref() }); +72 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:63:33 + --> $DIR/functions.rs:73:33 | -63 | unsafe { std::ptr::read(p) }; +73 | unsafe { std::ptr::read(p) }; | ^ error: aborting due to 12 previous errors diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs index 1376b9442b6..e91cfcb9e70 100644 --- a/tests/ui/fxhash.rs +++ b/tests/ui/fxhash.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::default_hash_types)] diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index 869a315c9eb..f5f8ae7e801 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -1,39 +1,39 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:8:24 - | -8 | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ help: use: `FxHashMap` - | - = note: `-D clippy::default-hash-types` implied by `-D warnings` + --> $DIR/fxhash.rs:18:24 + | +18 | use std::collections::{HashMap, HashSet}; + | ^^^^^^^ help: use: `FxHashMap` + | + = note: `-D clippy::default-hash-types` implied by `-D warnings` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:8:33 - | -8 | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ help: use: `FxHashSet` + --> $DIR/fxhash.rs:18:33 + | +18 | use std::collections::{HashMap, HashSet}; + | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:12:15 + --> $DIR/fxhash.rs:22:15 | -12 | let _map: HashMap = HashMap::default(); +22 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:12:41 + --> $DIR/fxhash.rs:22:41 | -12 | let _map: HashMap = HashMap::default(); +22 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:13:15 + --> $DIR/fxhash.rs:23:15 | -13 | let _set: HashSet = HashSet::default(); +23 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:13:33 + --> $DIR/fxhash.rs:23:33 | -13 | let _set: HashSet = HashSet::default(); +23 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: aborting due to 6 previous errors diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 141233e0d8a..7b672c0748c 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(unused_mut)] use std::collections::BTreeMap; diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 669903da190..90b46e960f4 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,75 +1,75 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:27:17 + --> $DIR/get_unwrap.rs:37:17 | -27 | let _ = boxed_slice.get(1).unwrap(); +37 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D clippy::get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:28:17 + --> $DIR/get_unwrap.rs:38:17 | -28 | let _ = some_slice.get(0).unwrap(); +38 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:29:17 + --> $DIR/get_unwrap.rs:39:17 | -29 | let _ = some_vec.get(0).unwrap(); +39 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:30:17 + --> $DIR/get_unwrap.rs:40:17 | -30 | let _ = some_vecdeque.get(0).unwrap(); +40 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:31:17 + --> $DIR/get_unwrap.rs:41:17 | -31 | let _ = some_hashmap.get(&1).unwrap(); +41 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:32:17 + --> $DIR/get_unwrap.rs:42:17 | -32 | let _ = some_btreemap.get(&1).unwrap(); +42 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:37:10 + --> $DIR/get_unwrap.rs:47:10 | -37 | *boxed_slice.get_mut(0).unwrap() = 1; +47 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:38:10 + --> $DIR/get_unwrap.rs:48:10 | -38 | *some_slice.get_mut(0).unwrap() = 1; +48 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:39:10 + --> $DIR/get_unwrap.rs:49:10 | -39 | *some_vec.get_mut(0).unwrap() = 1; +49 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:10 + --> $DIR/get_unwrap.rs:50:10 | -40 | *some_vecdeque.get_mut(0).unwrap() = 1; +50 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:48:17 + --> $DIR/get_unwrap.rs:58:17 | -48 | let _ = some_vec.get(0..1).unwrap().to_vec(); +58 | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:49:17 + --> $DIR/get_unwrap.rs:59:17 | -49 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); +59 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: aborting due to 12 previous errors diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index b9ad8d06ad5..a4f5babecfc 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::identity_conversion)] diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index ffcd3649ad6..2ac74191931 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,61 +1,61 @@ error: identical conversion - --> $DIR/identity_conversion.rs:6:13 - | -6 | let _ = T::from(val); - | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` - | + --> $DIR/identity_conversion.rs:16:13 + | +16 | let _ = T::from(val); + | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` + | note: lint level defined here - --> $DIR/identity_conversion.rs:3:9 - | -3 | #![deny(clippy::identity_conversion)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/identity_conversion.rs:13:9 + | +13 | #![deny(clippy::identity_conversion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion - --> $DIR/identity_conversion.rs:7:5 - | -7 | val.into() - | ^^^^^^^^^^ help: consider removing `.into()`: `val` + --> $DIR/identity_conversion.rs:17:5 + | +17 | val.into() + | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion - --> $DIR/identity_conversion.rs:19:22 + --> $DIR/identity_conversion.rs:29:22 | -19 | let _: i32 = 0i32.into(); +29 | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:40:21 + --> $DIR/identity_conversion.rs:50:21 | -40 | let _: String = "foo".to_string().into(); +50 | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:41:21 + --> $DIR/identity_conversion.rs:51:21 | -41 | let _: String = From::from("foo".to_string()); +51 | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:42:13 + --> $DIR/identity_conversion.rs:52:13 | -42 | let _ = String::from("foo".to_string()); +52 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:43:13 + --> $DIR/identity_conversion.rs:53:13 | -43 | let _ = String::from(format!("A: {:04}", 123)); +53 | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion - --> $DIR/identity_conversion.rs:44:13 + --> $DIR/identity_conversion.rs:54:13 | -44 | let _ = "".lines().into_iter(); +54 | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion - --> $DIR/identity_conversion.rs:45:13 + --> $DIR/identity_conversion.rs:55:13 | -45 | let _ = vec![1, 2, 3].into_iter().into_iter(); +55 | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: aborting due to 9 previous errors diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index ae8c66faa41..35afb85109f 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index e494250c019..332350fd1d8 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,51 +1,51 @@ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:13:5 + --> $DIR/identity_op.rs:23:5 | -13 | x + 0; +23 | x + 0; | ^^^^^ | = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:14:5 + --> $DIR/identity_op.rs:24:5 | -14 | x + (1 - 1); +24 | x + (1 - 1); | ^^^^^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:16:5 + --> $DIR/identity_op.rs:26:5 | -16 | 0 + x; +26 | 0 + x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:19:5 + --> $DIR/identity_op.rs:29:5 | -19 | x | (0); +29 | x | (0); | ^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:22:5 + --> $DIR/identity_op.rs:32:5 | -22 | x * 1; +32 | x * 1; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:23:5 + --> $DIR/identity_op.rs:33:5 | -23 | 1 * x; +33 | 1 * x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:29:5 + --> $DIR/identity_op.rs:39:5 | -29 | -1 & x; +39 | -1 & x; | ^^^^^^ error: the operation is ineffective. Consider reducing it to `u` - --> $DIR/identity_op.rs:32:5 + --> $DIR/identity_op.rs:42:5 | -32 | u & 255; +42 | u & 255; | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs index 90265853f00..84f4b711f53 100644 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ b/tests/ui/if_let_redundant_pattern_matching.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index 9046625855c..00eb7885540 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -1,27 +1,27 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/if_let_redundant_pattern_matching.rs:9:12 - | -9 | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` - | - = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings` + --> $DIR/if_let_redundant_pattern_matching.rs:19:12 + | +19 | if let Ok(_) = Ok::(42) {} + | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + | + = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/if_let_redundant_pattern_matching.rs:11:12 + --> $DIR/if_let_redundant_pattern_matching.rs:21:12 | -11 | if let Err(_) = Err::(42) { +21 | if let Err(_) = Err::(42) { | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/if_let_redundant_pattern_matching.rs:14:12 + --> $DIR/if_let_redundant_pattern_matching.rs:24:12 | -14 | if let None = None::<()> { +24 | if let None = None::<()> { | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/if_let_redundant_pattern_matching.rs:17:12 + --> $DIR/if_let_redundant_pattern_matching.rs:27:12 | -17 | if let Some(_) = Some(42) { +27 | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: aborting due to 4 previous errors diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index bb16e16700b..b0744d8c600 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all)] diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index 9682f6dc18f..a054ac6223d 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -1,24 +1,24 @@ error: Unnecessary boolean `not` operation - --> $DIR/if_not_else.rs:9:5 + --> $DIR/if_not_else.rs:19:5 | -9 | / if !bla() { -10 | | println!("Bugs"); -11 | | } else { -12 | | println!("Bunny"); -13 | | } +19 | / if !bla() { +20 | | println!("Bugs"); +21 | | } else { +22 | | println!("Bunny"); +23 | | } | |_____^ | = note: `-D clippy::if-not-else` implied by `-D warnings` = help: remove the `!` and swap the blocks of the if/else error: Unnecessary `!=` operation - --> $DIR/if_not_else.rs:14:5 + --> $DIR/if_not_else.rs:24:5 | -14 | / if 4 != 5 { -15 | | println!("Bugs"); -16 | | } else { -17 | | println!("Bunny"); -18 | | } +24 | / if 4 != 5 { +25 | | println!("Bugs"); +26 | | } else { +27 | | println!("Bunny"); +28 | | } | |_____^ | = help: change to `==` and swap the blocks of the if/else diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 7da0e04e59e..6c2152220cf 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(dead_code)] diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index 13d4a76558d..c24a96e8aa7 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,34 +1,34 @@ error: Multiple implementations of this structure - --> $DIR/impl.rs:12:1 + --> $DIR/impl.rs:22:1 | -12 | / impl MyStruct { -13 | | fn second() {} -14 | | } +22 | / impl MyStruct { +23 | | fn second() {} +24 | | } | |_^ | = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` note: First implementation here - --> $DIR/impl.rs:8:1 + --> $DIR/impl.rs:18:1 | -8 | / impl MyStruct { -9 | | fn first() {} -10 | | } +18 | / impl MyStruct { +19 | | fn first() {} +20 | | } | |_^ error: Multiple implementations of this structure - --> $DIR/impl.rs:26:5 + --> $DIR/impl.rs:36:5 | -26 | / impl super::MyStruct { -27 | | fn third() {} -28 | | } +36 | / impl super::MyStruct { +37 | | fn third() {} +38 | | } | |_____^ | note: First implementation here - --> $DIR/impl.rs:8:1 + --> $DIR/impl.rs:18:1 | -8 | / impl MyStruct { -9 | | fn first() {} -10 | | } +18 | / impl MyStruct { +19 | | fn first() {} +20 | | } | |_^ error: aborting due to 2 previous errors diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index 49df39ca71b..a6be909c0cc 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![allow(unused)] use std::collections::{HashMap, HashSet}; diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 5bb6f11b2a7..c561e0a3dfb 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,136 +1,136 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:11:35 + --> $DIR/implicit_hasher.rs:21:35 | -11 | impl Foo for HashMap { +21 | impl Foo for HashMap { | ^^^^^^^^^^^^^ | = note: `-D clippy::implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -11 | impl Foo for HashMap { +21 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -17 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:20:36 + --> $DIR/implicit_hasher.rs:30:36 | -20 | impl Foo for (HashMap,) { +30 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ help: consider adding a type parameter | -20 | impl Foo for (HashMap,) { +30 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -22 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) +32 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:25:19 + --> $DIR/implicit_hasher.rs:35:19 | -25 | impl Foo for HashMap { +35 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -25 | impl Foo for HashMap { +35 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +37 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:43:32 + --> $DIR/implicit_hasher.rs:53:32 | -43 | impl Foo for HashSet { +53 | impl Foo for HashSet { | ^^^^^^^^^^ help: consider adding a type parameter | -43 | impl Foo for HashSet { +53 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ help: ...and use generic constructor | -45 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +55 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:48:19 + --> $DIR/implicit_hasher.rs:58:19 | -48 | impl Foo for HashSet { +58 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ help: consider adding a type parameter | -48 | impl Foo for HashSet { +58 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -50 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +60 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:65:23 + --> $DIR/implicit_hasher.rs:75:23 | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:65:53 + --> $DIR/implicit_hasher.rs:75:53 | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^ help: consider adding a type parameter | -65 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:70:43 + --> $DIR/implicit_hasher.rs:80:43 | -70 | impl Foo for HashMap { +80 | impl Foo for HashMap { | ^^^^^^^^^^^^^ ... -83 | gen!(impl); +93 | gen!(impl); | ----------- in this macro invocation help: consider adding a type parameter | -70 | impl Foo for HashMap { +80 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -72 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +82 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:78:33 + --> $DIR/implicit_hasher.rs:88:33 | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^ ... -84 | gen!(fn bar); +94 | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:78:63 + --> $DIR/implicit_hasher.rs:88:63 | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^ ... -84 | gen!(fn bar); +94 | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -78 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index 056d8761109..dc73952ca25 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::inconsistent_digit_grouping)] diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 51eeca2b864..a417394629e 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,34 +1,34 @@ error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:7:16 - | -7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ help: consider: `123_456` - | - = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` + --> $DIR/inconsistent_digit_grouping.rs:17:16 + | +17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + | ^^^^^^^^ help: consider: `123_456` + | + = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:7:26 - | -7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^ help: consider: `12_345_678` + --> $DIR/inconsistent_digit_grouping.rs:17:26 + | +17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:7:38 - | -7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^ help: consider: `1_234_567` + --> $DIR/inconsistent_digit_grouping.rs:17:38 + | +17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:7:48 - | -7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` + --> $DIR/inconsistent_digit_grouping.rs:17:48 + | +17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:7:64 - | -7 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); - | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` + --> $DIR/inconsistent_digit_grouping.rs:17:64 + | +17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: aborting due to 5 previous errors diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index b9f1c4a4a5d..8d3f3cee99a 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(plugin)] diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 3f09a6516e0..7d847c7a673 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,268 +1,268 @@ error: indexing may panic. - --> $DIR/indexing_slicing.rs:13:5 + --> $DIR/indexing_slicing.rs:23:5 | -13 | x[index]; +23 | x[index]; | ^^^^^^^^ | = note: `-D clippy::indexing-slicing` implied by `-D warnings` = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:14:6 + --> $DIR/indexing_slicing.rs:24:6 | -14 | &x[index..]; +24 | &x[index..]; | ^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:25:6 | -15 | &x[..index]; +25 | &x[..index]; | ^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:16:6 + --> $DIR/indexing_slicing.rs:26:6 | -16 | &x[index_from..index_to]; +26 | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:17:6 + --> $DIR/indexing_slicing.rs:27:6 | -17 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +27 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:17:6 + --> $DIR/indexing_slicing.rs:27:6 | -17 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +27 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:20:6 + --> $DIR/indexing_slicing.rs:30:6 | -20 | &x[..=4]; +30 | &x[..=4]; | ^^^^^^^ | = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds - --> $DIR/indexing_slicing.rs:21:6 + --> $DIR/indexing_slicing.rs:31:6 | -21 | &x[1..5]; +31 | &x[1..5]; | ^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:22:6 + --> $DIR/indexing_slicing.rs:32:6 | -22 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +32 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:22:6 + --> $DIR/indexing_slicing.rs:32:6 | -22 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +32 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:23:6 + --> $DIR/indexing_slicing.rs:33:6 | -23 | &x[5..]; +33 | &x[5..]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:24:6 + --> $DIR/indexing_slicing.rs:34:6 | -24 | &x[..5]; +34 | &x[..5]; | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:25:6 + --> $DIR/indexing_slicing.rs:35:6 | -25 | &x[5..].iter().map(|x| 2 * x).collect::>(); +35 | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:26:6 + --> $DIR/indexing_slicing.rs:36:6 | -26 | &x[0..=4]; +36 | &x[0..=4]; | ^^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:27:6 + --> $DIR/indexing_slicing.rs:37:6 | -27 | &x[0..][..3]; +37 | &x[0..][..3]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:28:6 + --> $DIR/indexing_slicing.rs:38:6 | -28 | &x[1..][..5]; +38 | &x[1..][..5]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:41:5 + --> $DIR/indexing_slicing.rs:51:5 | -41 | y[0]; +51 | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:42:6 + --> $DIR/indexing_slicing.rs:52:6 | -42 | &y[1..2]; +52 | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:43:6 + --> $DIR/indexing_slicing.rs:53:6 | -43 | &y[0..=4]; +53 | &y[0..=4]; | ^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:44:6 + --> $DIR/indexing_slicing.rs:54:6 | -44 | &y[..=4]; +54 | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:50:6 + --> $DIR/indexing_slicing.rs:60:6 | -50 | &empty[1..5]; +60 | &empty[1..5]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:51:6 + --> $DIR/indexing_slicing.rs:61:6 | -51 | &empty[0..=4]; +61 | &empty[0..=4]; | ^^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:52:6 + --> $DIR/indexing_slicing.rs:62:6 | -52 | &empty[..=4]; +62 | &empty[..=4]; | ^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:53:6 + --> $DIR/indexing_slicing.rs:63:6 | -53 | &empty[1..]; +63 | &empty[1..]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:54:6 + --> $DIR/indexing_slicing.rs:64:6 | -54 | &empty[..4]; +64 | &empty[..4]; | ^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:55:6 + --> $DIR/indexing_slicing.rs:65:6 | -55 | &empty[0..=0]; +65 | &empty[0..=0]; | ^^^^^^^^^^^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:56:6 + --> $DIR/indexing_slicing.rs:66:6 | -56 | &empty[..=0]; +66 | &empty[..=0]; | ^^^^^^^^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:64:5 + --> $DIR/indexing_slicing.rs:74:5 | -64 | v[0]; +74 | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:65:5 + --> $DIR/indexing_slicing.rs:75:5 | -65 | v[10]; +75 | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:66:5 + --> $DIR/indexing_slicing.rs:76:5 | -66 | v[1 << 3]; +76 | v[1 << 3]; | ^^^^^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:67:6 + --> $DIR/indexing_slicing.rs:77:6 | -67 | &v[10..100]; +77 | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:68:6 + --> $DIR/indexing_slicing.rs:78:6 | -68 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +78 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:68:6 + --> $DIR/indexing_slicing.rs:78:6 | -68 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +78 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:69:6 + --> $DIR/indexing_slicing.rs:79:6 | -69 | &v[10..]; +79 | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:70:6 + --> $DIR/indexing_slicing.rs:80:6 | -70 | &v[..100]; +80 | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:82:5 + --> $DIR/indexing_slicing.rs:92:5 | -82 | v[N]; +92 | v[N]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:83:5 + --> $DIR/indexing_slicing.rs:93:5 | -83 | v[M]; +93 | v[M]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index b3e2835d72f..bd4e4b49a4a 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(exhaustive_patterns, never_type)] diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index 6e26741fc87..bce83b91242 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,27 +1,27 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:18:5 + --> $DIR/infallible_destructuring_match.rs:28:5 | -18 | / let data = match wrapper { -19 | | SingleVariantEnum::Variant(i) => i, -20 | | }; +28 | / let data = match wrapper { +29 | | SingleVariantEnum::Variant(i) => i, +30 | | }; | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` | = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:39:5 + --> $DIR/infallible_destructuring_match.rs:49:5 | -39 | / let data = match wrapper { -40 | | TupleStruct(i) => i, -41 | | }; +49 | / let data = match wrapper { +50 | | TupleStruct(i) => i, +51 | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:60:5 + --> $DIR/infallible_destructuring_match.rs:70:5 | -60 | / let data = match wrapper { -61 | | Ok(i) => i, -62 | | }; +70 | / let data = match wrapper { +71 | | Ok(i) => i, +72 | | }; | |______^ help: try this: `let Ok(data) = wrapper;` error: aborting due to 3 previous errors diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 44fa934aa26..cf30a2e35ed 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::iter::repeat; diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index c3d67bdfde3..5b783c2b8b9 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,99 +1,99 @@ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/infinite_iter.rs:10:5 + --> $DIR/infinite_iter.rs:20:5 | -10 | repeat(0_u8).collect::>(); // infinite iter +20 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` error: infinite iteration detected - --> $DIR/infinite_iter.rs:10:5 + --> $DIR/infinite_iter.rs:20:5 | -10 | repeat(0_u8).collect::>(); // infinite iter +20 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:8:8 + --> $DIR/infinite_iter.rs:18:8 | -8 | #[deny(clippy::infinite_iter)] +18 | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:11:5 + --> $DIR/infinite_iter.rs:21:5 | -11 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter +21 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:12:5 + --> $DIR/infinite_iter.rs:22:5 | -12 | (0..8_u64).chain(0..).max(); // infinite iter +22 | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:14:5 + --> $DIR/infinite_iter.rs:24:5 | -14 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter +24 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:16:5 + --> $DIR/infinite_iter.rs:26:5 | -16 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter +26 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:17:5 + --> $DIR/infinite_iter.rs:27:5 | -17 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter +27 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:24:5 + --> $DIR/infinite_iter.rs:34:5 | -24 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter +34 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:22:8 + --> $DIR/infinite_iter.rs:32:8 | -22 | #[deny(clippy::maybe_infinite_iter)] +32 | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:25:5 + --> $DIR/infinite_iter.rs:35:5 | -25 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter +35 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:26:5 + --> $DIR/infinite_iter.rs:36:5 | -26 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter +36 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:27:5 + --> $DIR/infinite_iter.rs:37:5 | -27 | (0..).find(|x| *x == 24); // maybe infinite iter +37 | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:28:5 + --> $DIR/infinite_iter.rs:38:5 | -28 | (0..).position(|x| x == 24); // maybe infinite iter +38 | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:29:5 + --> $DIR/infinite_iter.rs:39:5 | -29 | (0..).any(|x| x == 24); // maybe infinite iter +39 | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:30:5 + --> $DIR/infinite_iter.rs:40:5 | -30 | (0..).all(|x| x == 24); // maybe infinite iter +40 | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 9449a295e3a..e837e563f18 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index edbe4937425..fdbdd13fd8f 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,57 +1,57 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:16:11 + --> $DIR/infinite_loop.rs:26:11 | -16 | while y < 10 { +26 | while y < 10 { | ^^^^^^ | = note: #[deny(clippy::while_immutable_condition)] on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:21:11 + --> $DIR/infinite_loop.rs:31:11 | -21 | while y < 10 && x < 3 { +31 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:28:11 + --> $DIR/infinite_loop.rs:38:11 | -28 | while !cond { +38 | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:72:11 + --> $DIR/infinite_loop.rs:82:11 | -72 | while i < 3 { +82 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:77:11 + --> $DIR/infinite_loop.rs:87:11 | -77 | while i < 3 && j > 0 { +87 | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:81:11 + --> $DIR/infinite_loop.rs:91:11 | -81 | while i < 3 { +91 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:96:11 - | -96 | while i < 3 { - | ^^^^^ + --> $DIR/infinite_loop.rs:106:11 + | +106 | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:101:11 + --> $DIR/infinite_loop.rs:111:11 | -101 | while i < 3 { +111 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:164:15 + --> $DIR/infinite_loop.rs:174:15 | -164 | while self.count < n { +174 | while self.count < n { | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 830da6d1124..93dff0d350f 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index a9a52b19053..112fad812e5 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,25 +1,25 @@ error: use of `#[inline]` on trait method `default_inline` which has no body - --> $DIR/inline_fn_without_body.rs:8:5 - | -8 | #[inline] - | _____-^^^^^^^^ -9 | | fn default_inline(); - | |____- help: remove - | - = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` + --> $DIR/inline_fn_without_body.rs:18:5 + | +18 | #[inline] + | _____-^^^^^^^^ +19 | | fn default_inline(); + | |____- help: remove + | + = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body - --> $DIR/inline_fn_without_body.rs:11:5 + --> $DIR/inline_fn_without_body.rs:21:5 | -11 | #[inline(always)]fn always_inline(); +21 | #[inline(always)]fn always_inline(); | ^^^^^^^^^^^^^^^^^ help: remove error: use of `#[inline]` on trait method `never_inline` which has no body - --> $DIR/inline_fn_without_body.rs:13:5 + --> $DIR/inline_fn_without_body.rs:23:5 | -13 | #[inline(never)] +23 | #[inline(never)] | _____-^^^^^^^^^^^^^^^ -14 | | fn never_inline(); +24 | | fn never_inline(); | |____- help: remove error: aborting due to 3 previous errors diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index 1eb0e49290f..df16a393824 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 12d7000dcfa..5612b203290 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,43 +1,43 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:10:5 + --> $DIR/int_plus_one.rs:20:5 | -10 | x >= y + 1; +20 | x >= y + 1; | ^^^^^^^^^^ | = note: `-D clippy::int-plus-one` implied by `-D warnings` help: change `>= y + 1` to `> y` as shown | -10 | x > y; +20 | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:11:5 + --> $DIR/int_plus_one.rs:21:5 | -11 | y + 1 <= x; +21 | y + 1 <= x; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -11 | y < x; +21 | y < x; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:13:5 + --> $DIR/int_plus_one.rs:23:5 | -13 | x - 1 >= y; +23 | x - 1 >= y; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -13 | x > y; +23 | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:14:5 + --> $DIR/int_plus_one.rs:24:5 | -14 | y <= x - 1; +24 | y <= x - 1; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -14 | y < x; +24 | y < x; | ^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs index ce2596c0c1a..9fb6c7fd4b7 100644 --- a/tests/ui/invalid_ref.rs +++ b/tests/ui/invalid_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 1ca825dd94c..52868e908ca 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,48 +1,48 @@ error: reference to zeroed memory - --> $DIR/invalid_ref.rs:27:24 + --> $DIR/invalid_ref.rs:37:24 | -27 | let ref_zero: &T = std::mem::zeroed(); // warning +37 | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | = note: #[deny(clippy::invalid_ref)] on by default = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:31:24 + --> $DIR/invalid_ref.rs:41:24 | -31 | let ref_zero: &T = core::mem::zeroed(); // warning +41 | let ref_zero: &T = core::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:35:24 + --> $DIR/invalid_ref.rs:45:24 | -35 | let ref_zero: &T = std::intrinsics::init(); // warning +45 | let ref_zero: &T = std::intrinsics::init(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:39:26 + --> $DIR/invalid_ref.rs:49:26 | -39 | let ref_uninit: &T = std::mem::uninitialized(); // warning +49 | let ref_uninit: &T = std::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:43:26 + --> $DIR/invalid_ref.rs:53:26 | -43 | let ref_uninit: &T = core::mem::uninitialized(); // warning +53 | let ref_uninit: &T = core::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:47:26 + --> $DIR/invalid_ref.rs:57:26 | -47 | let ref_uninit: &T = std::intrinsics::uninit(); // warning +57 | let ref_uninit: &T = std::intrinsics::uninit(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 0a700518f8f..5c17970d337 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index ce6d1dfa1ae..e41132dfc8b 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -1,165 +1,165 @@ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:16:5 + --> $DIR/invalid_upcast_comparisons.rs:26:5 | -16 | (u8 as u32) > 300; +26 | (u8 as u32) > 300; | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:17:5 + --> $DIR/invalid_upcast_comparisons.rs:27:5 | -17 | (u8 as i32) > 300; +27 | (u8 as i32) > 300; | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:18:5 + --> $DIR/invalid_upcast_comparisons.rs:28:5 | -18 | (u8 as u32) == 300; +28 | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:19:5 + --> $DIR/invalid_upcast_comparisons.rs:29:5 | -19 | (u8 as i32) == 300; +29 | (u8 as i32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:20:5 + --> $DIR/invalid_upcast_comparisons.rs:30:5 | -20 | 300 < (u8 as u32); +30 | 300 < (u8 as u32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:21:5 + --> $DIR/invalid_upcast_comparisons.rs:31:5 | -21 | 300 < (u8 as i32); +31 | 300 < (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:22:5 + --> $DIR/invalid_upcast_comparisons.rs:32:5 | -22 | 300 == (u8 as u32); +32 | 300 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:23:5 + --> $DIR/invalid_upcast_comparisons.rs:33:5 | -23 | 300 == (u8 as i32); +33 | 300 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:25:5 + --> $DIR/invalid_upcast_comparisons.rs:35:5 | -25 | (u8 as u32) <= 300; +35 | (u8 as u32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:26:5 + --> $DIR/invalid_upcast_comparisons.rs:36:5 | -26 | (u8 as i32) <= 300; +36 | (u8 as i32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:27:5 + --> $DIR/invalid_upcast_comparisons.rs:37:5 | -27 | (u8 as u32) != 300; +37 | (u8 as u32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:28:5 + --> $DIR/invalid_upcast_comparisons.rs:38:5 | -28 | (u8 as i32) != 300; +38 | (u8 as i32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:29:5 + --> $DIR/invalid_upcast_comparisons.rs:39:5 | -29 | 300 >= (u8 as u32); +39 | 300 >= (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:30:5 + --> $DIR/invalid_upcast_comparisons.rs:40:5 | -30 | 300 >= (u8 as i32); +40 | 300 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:31:5 + --> $DIR/invalid_upcast_comparisons.rs:41:5 | -31 | 300 != (u8 as u32); +41 | 300 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:32:5 + --> $DIR/invalid_upcast_comparisons.rs:42:5 | -32 | 300 != (u8 as i32); +42 | 300 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:35:5 + --> $DIR/invalid_upcast_comparisons.rs:45:5 | -35 | (u8 as i32) < 0; +45 | (u8 as i32) < 0; | ^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:36:5 + --> $DIR/invalid_upcast_comparisons.rs:46:5 | -36 | -5 != (u8 as i32); +46 | -5 != (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:38:5 + --> $DIR/invalid_upcast_comparisons.rs:48:5 | -38 | (u8 as i32) >= 0; +48 | (u8 as i32) >= 0; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:39:5 + --> $DIR/invalid_upcast_comparisons.rs:49:5 | -39 | -5 == (u8 as i32); +49 | -5 == (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:42:5 + --> $DIR/invalid_upcast_comparisons.rs:52:5 | -42 | 1337 == (u8 as i32); +52 | 1337 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:43:5 + --> $DIR/invalid_upcast_comparisons.rs:53:5 | -43 | 1337 == (u8 as u32); +53 | 1337 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:45:5 + --> $DIR/invalid_upcast_comparisons.rs:55:5 | -45 | 1337 != (u8 as i32); +55 | 1337 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:46:5 + --> $DIR/invalid_upcast_comparisons.rs:56:5 | -46 | 1337 != (u8 as u32); +56 | 1337 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:61:5 + --> $DIR/invalid_upcast_comparisons.rs:71:5 | -61 | (u8 as i32) > -1; +71 | (u8 as i32) > -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:62:5 + --> $DIR/invalid_upcast_comparisons.rs:72:5 | -62 | (u8 as i32) < -1; +72 | (u8 as i32) < -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:78:5 + --> $DIR/invalid_upcast_comparisons.rs:88:5 | -78 | -5 >= (u8 as i32); +88 | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: aborting due to 27 previous errors diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs index f497d5550af..74a11925a76 100644 --- a/tests/ui/issue-3145.rs +++ b/tests/ui/issue-3145.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { println!("{}" a); //~ERROR expected token: `,` } diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index e289df043a3..2086f11463f 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,8 +1,8 @@ error: expected token: `,` - --> $DIR/issue-3145.rs:2:19 - | -2 | println!("{}" a); //~ERROR expected token: `,` - | ^ + --> $DIR/issue-3145.rs:12:19 + | +12 | println!("{}" a); //~ERROR expected token: `,` + | ^ error: aborting due to previous error diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index 398e0d1d1f0..d251d51f3fc 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::while_let_on_iterator)] diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr index fe2d9d45b77..291e64bec6f 100644 --- a/tests/ui/issue_2356.stderr +++ b/tests/ui/issue_2356.stderr @@ -1,13 +1,13 @@ error: this loop could be written as a `for` loop - --> $DIR/issue_2356.rs:17:29 + --> $DIR/issue_2356.rs:27:29 | -17 | while let Some(e) = it.next() { +27 | while let Some(e) = it.next() { | ^^^^^^^^^ help: try: `for e in it { .. }` | note: lint level defined here - --> $DIR/issue_2356.rs:3:9 + --> $DIR/issue_2356.rs:13:9 | -3 | #![deny(clippy::while_let_on_iterator)] +13 | #![deny(clippy::while_let_on_iterator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index 9626a59ed02..d765adae38c 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::items_after_statements)] diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index 6d20899b5ec..15c0cc3af4c 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -1,15 +1,15 @@ error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:12:5 + --> $DIR/item_after_statement.rs:22:5 | -12 | fn foo() { println!("foo"); } +22 | fn foo() { println!("foo"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::items-after-statements` implied by `-D warnings` error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:17:5 + --> $DIR/item_after_statement.rs:27:5 | -17 | fn foo() { println!("foo"); } +27 | fn foo() { println!("foo"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index af569ea7566..7cc1f9c881d 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::large_digit_groups)] diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index b322ded9cfb..c38abb8887c 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -1,40 +1,40 @@ error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:16 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` - | - = note: `-D clippy::large-digit-groups` implied by `-D warnings` + --> $DIR/large_digit_groups.rs:17:16 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` + | + = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:31 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` + --> $DIR/large_digit_groups.rs:17:31 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:54 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^ help: consider: `123_456_f32` + --> $DIR/large_digit_groups.rs:17:54 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:67 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` + --> $DIR/large_digit_groups.rs:17:67 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:83 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` + --> $DIR/large_digit_groups.rs:17:83 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:7:102 - | -7 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` + --> $DIR/large_digit_groups.rs:17:102 + | +17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` error: aborting due to 6 previous errors diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index cd1772ad1d1..729cc8940ef 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index af42f905458..4bb25dd855a 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -1,69 +1,69 @@ error: large size difference between variants - --> $DIR/large_enum_variant.rs:10:5 + --> $DIR/large_enum_variant.rs:20:5 | -10 | B([i32; 8000]), +20 | B([i32; 8000]), | ^^^^^^^^^^^^^^ | = note: `-D clippy::large-enum-variant` implied by `-D warnings` help: consider boxing the large fields to reduce the total size of the enum | -10 | B(Box<[i32; 8000]>), +20 | B(Box<[i32; 8000]>), | ^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:21:5 + --> $DIR/large_enum_variant.rs:31:5 | -21 | C(T, [i32; 8000]), +31 | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:21:5 + --> $DIR/large_enum_variant.rs:31:5 | -21 | C(T, [i32; 8000]), +31 | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:34:5 + --> $DIR/large_enum_variant.rs:44:5 | -34 | ContainingLargeEnum(LargeEnum), +44 | ContainingLargeEnum(LargeEnum), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -34 | ContainingLargeEnum(Box), +44 | ContainingLargeEnum(Box), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:37:5 + --> $DIR/large_enum_variant.rs:47:5 | -37 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +47 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:37:5 + --> $DIR/large_enum_variant.rs:47:5 | -37 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +47 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:44:5 + --> $DIR/large_enum_variant.rs:54:5 | -44 | StructLikeLarge { x: [i32; 8000], y: i32 }, +54 | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:44:5 + --> $DIR/large_enum_variant.rs:54:5 | -44 | StructLikeLarge { x: [i32; 8000], y: i32 }, +54 | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:49:5 + --> $DIR/large_enum_variant.rs:59:5 | -49 | StructLikeLarge2 { x: [i32; 8000] }, +59 | StructLikeLarge2 { x: [i32; 8000] }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -49 | StructLikeLarge2 { x: Box<[i32; 8000]> }, +59 | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index b188db5186e..a8f1e283643 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::len_without_is_empty, clippy::len_zero)] diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 49e365e6c21..ffba33a65f8 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,139 +1,139 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:8:1 + --> $DIR/len_zero.rs:18:1 | -8 | / impl PubOne { -9 | | pub fn len(self: &Self) -> isize { -10 | | 1 -11 | | } -12 | | } +18 | / impl PubOne { +19 | | pub fn len(self: &Self) -> isize { +20 | | 1 +21 | | } +22 | | } | |_^ | = note: `-D clippy::len-without-is-empty` implied by `-D warnings` error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:57:1 + --> $DIR/len_zero.rs:67:1 | -57 | / pub trait PubTraitsToo { -58 | | fn len(self: &Self) -> isize; -59 | | } +67 | / pub trait PubTraitsToo { +68 | | fn len(self: &Self) -> isize; +69 | | } | |_^ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:91:1 - | -91 | / impl HasIsEmpty { -92 | | pub fn len(self: &Self) -> isize { -93 | | 1 -94 | | } -... | -98 | | } -99 | | } - | |_^ + --> $DIR/len_zero.rs:101:1 + | +101 | / impl HasIsEmpty { +102 | | pub fn len(self: &Self) -> isize { +103 | | 1 +104 | | } +... | +108 | | } +109 | | } + | |_^ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:120:1 + --> $DIR/len_zero.rs:130:1 | -120 | / impl HasWrongIsEmpty { -121 | | pub fn len(self: &Self) -> isize { -122 | | 1 -123 | | } +130 | / impl HasWrongIsEmpty { +131 | | pub fn len(self: &Self) -> isize { +132 | | 1 +133 | | } ... | -127 | | } -128 | | } +137 | | } +138 | | } | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:141:8 + --> $DIR/len_zero.rs:151:8 | -141 | if x.len() == 0 { +151 | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `x.is_empty()` | = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:145:8 + --> $DIR/len_zero.rs:155:8 | -145 | if "".len() == 0 {} +155 | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is more concise: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:160:8 + --> $DIR/len_zero.rs:170:8 | -160 | if has_is_empty.len() == 0 { +170 | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:163:8 + --> $DIR/len_zero.rs:173:8 | -163 | if has_is_empty.len() != 0 { +173 | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:166:8 + --> $DIR/len_zero.rs:176:8 | -166 | if has_is_empty.len() > 0 { +176 | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:169:8 + --> $DIR/len_zero.rs:179:8 | -169 | if has_is_empty.len() < 1 { +179 | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:172:8 + --> $DIR/len_zero.rs:182:8 | -172 | if has_is_empty.len() >= 1 { +182 | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:183:8 + --> $DIR/len_zero.rs:193:8 | -183 | if 0 == has_is_empty.len() { +193 | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:186:8 + --> $DIR/len_zero.rs:196:8 | -186 | if 0 != has_is_empty.len() { +196 | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:189:8 + --> $DIR/len_zero.rs:199:8 | -189 | if 0 < has_is_empty.len() { +199 | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:192:8 + --> $DIR/len_zero.rs:202:8 | -192 | if 1 <= has_is_empty.len() { +202 | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:195:8 + --> $DIR/len_zero.rs:205:8 | -195 | if 1 > has_is_empty.len() { +205 | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:209:8 + --> $DIR/len_zero.rs:219:8 | -209 | if with_is_empty.len() == 0 { +219 | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:222:8 + --> $DIR/len_zero.rs:232:8 | -222 | if b.len() != 0 {} +232 | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:228:1 + --> $DIR/len_zero.rs:238:1 | -228 | / pub trait DependsOnFoo: Foo { -229 | | fn len(&mut self) -> usize; -230 | | } +238 | / pub trait DependsOnFoo: Foo { +239 | | fn len(&mut self) -> usize; +240 | | } | |_^ error: aborting due to 19 previous errors diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 102b72f3e25..5fca759a4b3 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 7b4c78003ab..6e2ec6d4aaa 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,47 +1,47 @@ error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:57:5 + --> $DIR/let_if_seq.rs:67:5 | -57 | / let mut foo = 0; -58 | | if f() { -59 | | foo = 42; -60 | | } +67 | / let mut foo = 0; +68 | | if f() { +69 | | foo = 42; +70 | | } | |_____^ help: it is more idiomatic to write: `let foo = if f() { 42 } else { 0 };` | = note: `-D clippy::useless-let-if-seq` implied by `-D warnings` = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:62:5 + --> $DIR/let_if_seq.rs:72:5 | -62 | / let mut bar = 0; -63 | | if f() { -64 | | f(); -65 | | bar = 42; +72 | / let mut bar = 0; +73 | | if f() { +74 | | f(); +75 | | bar = 42; ... | -68 | | f(); -69 | | } +78 | | f(); +79 | | } | |_____^ help: it is more idiomatic to write: `let bar = if f() { ..; 42 } else { ..; 0 };` | = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:71:5 + --> $DIR/let_if_seq.rs:81:5 | -71 | / let quz; -72 | | if f() { -73 | | quz = 42; -74 | | } else { -75 | | quz = 0; -76 | | } +81 | / let quz; +82 | | if f() { +83 | | quz = 42; +84 | | } else { +85 | | quz = 0; +86 | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:100:5 + --> $DIR/let_if_seq.rs:110:5 | -100 | / let mut baz = 0; -101 | | if f() { -102 | | baz = 42; -103 | | } +110 | / let mut baz = 0; +111 | | if f() { +112 | | baz = 42; +113 | | } | |_____^ help: it is more idiomatic to write: `let baz = if f() { 42 } else { 0 };` | = note: you might not need `mut` at all diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index 9b584d6e293..380f775689d 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused)] diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index dad628bc912..cdd4b6bd537 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -1,26 +1,26 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:10:5 + --> $DIR/let_return.rs:20:5 | -10 | x +20 | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/let_return.rs:9:13 + --> $DIR/let_return.rs:19:13 | -9 | let x = 5; +19 | let x = 5; | ^ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:16:9 + --> $DIR/let_return.rs:26:9 | -16 | x +26 | x | ^ | note: this expression can be directly returned - --> $DIR/let_return.rs:15:17 + --> $DIR/let_return.rs:25:17 | -15 | let x = 5; +25 | let x = 5; | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 187ff9d1358..578fcb2ddde 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index f6f5d3f7dcc..e8c7bb37e73 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -1,15 +1,15 @@ error: this let-binding has unit value. Consider omitting `let _x =` - --> $DIR/let_unit.rs:14:5 + --> $DIR/let_unit.rs:24:5 | -14 | let _x = println!("x"); +24 | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::let-unit-value` implied by `-D warnings` error: this let-binding has unit value. Consider omitting `let _a =` - --> $DIR/let_unit.rs:18:9 + --> $DIR/let_unit.rs:28:9 | -18 | let _a = (); +28 | let _a = (); | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index aa5640f4e22..cae18498779 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 42fb01b7580..9e4fac1e4f2 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -1,89 +1,89 @@ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:7:1 - | -7 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::needless-lifetimes` implied by `-D warnings` + --> $DIR/lifetimes.rs:17:1 + | +17 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:9:1 - | -9 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/lifetimes.rs:19:1 + | +19 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:17:1 + --> $DIR/lifetimes.rs:27:1 | -17 | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } +27 | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:29:1 + --> $DIR/lifetimes.rs:39:1 | -29 | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } +39 | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:32:1 + --> $DIR/lifetimes.rs:42:1 | -32 | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } +42 | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:38:1 + --> $DIR/lifetimes.rs:48:1 | -38 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } +48 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:52:1 + --> $DIR/lifetimes.rs:62:1 | -52 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -53 | | where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> -54 | | { unreachable!() } +62 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +63 | | where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> +64 | | { unreachable!() } | |__________________^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:77:5 + --> $DIR/lifetimes.rs:87:5 | -77 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } +87 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:81:5 + --> $DIR/lifetimes.rs:91:5 | -81 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } +91 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:97:1 - | -97 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/lifetimes.rs:107:1 + | +107 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:117:1 + --> $DIR/lifetimes.rs:127:1 | -117 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } +127 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:121:1 + --> $DIR/lifetimes.rs:131:1 | -121 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } +131 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:132:1 + --> $DIR/lifetimes.rs:142:1 | -132 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } +142 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:136:1 + --> $DIR/lifetimes.rs:146:1 | -136 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } +146 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 7a9efaeec84..3c1dcf09af2 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::mixed_case_hex_literals)] diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index bd2d1f81831..4e26b9dd321 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,181 +1,181 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:14:17 + --> $DIR/literals.rs:24:17 | -14 | let fail1 = 0xabCD; +24 | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:15:17 + --> $DIR/literals.rs:25:17 | -15 | let fail2 = 0xabCD_u32; +25 | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:16:17 + --> $DIR/literals.rs:26:17 | -16 | let fail2 = 0xabCD_isize; +26 | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:17:27 + --> $DIR/literals.rs:27:27 | -17 | let fail_multi_zero = 000_123usize; +27 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:17:27 + --> $DIR/literals.rs:27:27 | -17 | let fail_multi_zero = 000_123usize; +27 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -17 | let fail_multi_zero = 123usize; +27 | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -17 | let fail_multi_zero = 0o123usize; +27 | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:22:17 + --> $DIR/literals.rs:32:17 | -22 | let fail3 = 1234i32; +32 | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:23:17 + --> $DIR/literals.rs:33:17 | -23 | let fail4 = 1234u32; +33 | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:24:17 + --> $DIR/literals.rs:34:17 | -24 | let fail5 = 1234isize; +34 | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:25:17 + --> $DIR/literals.rs:35:17 | -25 | let fail6 = 1234usize; +35 | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:26:17 + --> $DIR/literals.rs:36:17 | -26 | let fail7 = 1.5f32; +36 | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:30:17 + --> $DIR/literals.rs:40:17 | -30 | let fail8 = 0123; +40 | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -30 | let fail8 = 123; +40 | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -30 | let fail8 = 0o123; +40 | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:41:17 + --> $DIR/literals.rs:51:17 | -41 | let fail9 = 0xabcdef; +51 | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:42:18 + --> $DIR/literals.rs:52:18 | -42 | let fail10 = 0xBAFEBAFE; +52 | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:43:18 + --> $DIR/literals.rs:53:18 | -43 | let fail11 = 0xabcdeff; +53 | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/literals.rs:44:18 + --> $DIR/literals.rs:54:18 | -44 | let fail12 = 0xabcabcabcabcabcabc; +54 | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller - --> $DIR/literals.rs:45:18 + --> $DIR/literals.rs:55:18 | -45 | let fail13 = 0x1_23456_78901_usize; +55 | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:47:18 + --> $DIR/literals.rs:57:18 | -47 | let fail14 = 2_32; +57 | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` | = note: #[deny(clippy::mistyped_literal_suffixes)] on by default error: mistyped literal suffix - --> $DIR/literals.rs:48:18 + --> $DIR/literals.rs:58:18 | -48 | let fail15 = 4_64; +58 | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/literals.rs:49:18 + --> $DIR/literals.rs:59:18 | -49 | let fail16 = 7_8; +59 | let fail16 = 7_8; | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/literals.rs:50:18 + --> $DIR/literals.rs:60:18 | -50 | let fail17 = 23_16; +60 | let fail17 = 23_16; | ^^^^^ help: did you mean to write: `23_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:52:18 + --> $DIR/literals.rs:62:18 | -52 | let fail19 = 12_3456_21; +62 | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:53:18 + --> $DIR/literals.rs:63:18 | -53 | let fail20 = 2__8; +63 | let fail20 = 2__8; | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/literals.rs:54:18 + --> $DIR/literals.rs:64:18 | -54 | let fail21 = 4___16; +64 | let fail21 = 4___16; | ^^^^^^ help: did you mean to write: `4_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:55:18 + --> $DIR/literals.rs:65:18 | -55 | let fail22 = 3__4___23; +65 | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:56:18 + --> $DIR/literals.rs:66:18 | -56 | let fail23 = 3__16___23; +66 | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: aborting due to 25 previous errors diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 11a5316a367..8a410737f83 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index e80983cdbf7..50856f6a937 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,22 +1,22 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:6:22 - | -6 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` - | - = note: `-D clippy::map-clone` implied by `-D warnings` + --> $DIR/map_clone.rs:16:22 + | +16 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` + | + = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:7:26 - | -7 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` + --> $DIR/map_clone.rs:17:26 + | +17 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:8:23 - | -8 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` + --> $DIR/map_clone.rs:18:23 + | +18 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` error: aborting due to 3 previous errors diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index c5cf24d9bb0..b3f86d81e3f 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index d4ce44490d1..d41e6297758 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,10 +1,10 @@ error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` - --> $DIR/map_flatten.rs:6:21 - | -6 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` - | - = note: `-D clippy::map-flatten` implied by `-D warnings` + --> $DIR/map_flatten.rs:16:21 + | +16 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` + | + = note: `-D clippy::map-flatten` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs index 07efe2c6808..7548b83764d 100644 --- a/tests/ui/match_bool.rs +++ b/tests/ui/match_bool.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn match_bool() { let test: bool = true; diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 7ef6f714f3a..9bef0d823e2 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -1,73 +1,73 @@ error: this boolean expression can be simplified - --> $DIR/match_bool.rs:25:11 + --> $DIR/match_bool.rs:35:11 | -25 | match test && test { +35 | match test && test { | ^^^^^^^^^^^^ help: try: `test` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:4:5 - | -4 | / match test { -5 | | true => 0, -6 | | false => 42, -7 | | }; - | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` - | - = note: `-D clippy::match-bool` implied by `-D warnings` + --> $DIR/match_bool.rs:14:5 + | +14 | / match test { +15 | | true => 0, +16 | | false => 42, +17 | | }; + | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` + | + = note: `-D clippy::match-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:10:5 + --> $DIR/match_bool.rs:20:5 | -10 | / match option == 1 { -11 | | true => 1, -12 | | false => 0, -13 | | }; +20 | / match option == 1 { +21 | | true => 1, +22 | | false => 0, +23 | | }; | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:15:5 + --> $DIR/match_bool.rs:25:5 | -15 | / match test { -16 | | true => (), -17 | | false => { println!("Noooo!"); } -18 | | }; +25 | / match test { +26 | | true => (), +27 | | false => { println!("Noooo!"); } +28 | | }; | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:20:5 + --> $DIR/match_bool.rs:30:5 | -20 | / match test { -21 | | false => { println!("Noooo!"); } -22 | | _ => (), -23 | | }; +30 | / match test { +31 | | false => { println!("Noooo!"); } +32 | | _ => (), +33 | | }; | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:25:5 + --> $DIR/match_bool.rs:35:5 | -25 | / match test && test { -26 | | false => { println!("Noooo!"); } -27 | | _ => (), -28 | | }; +35 | / match test && test { +36 | | false => { println!("Noooo!"); } +37 | | _ => (), +38 | | }; | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` error: equal expressions as operands to `&&` - --> $DIR/match_bool.rs:25:11 + --> $DIR/match_bool.rs:35:11 | -25 | match test && test { +35 | match test && test { | ^^^^^^^^^^^^ | = note: #[deny(clippy::eq_op)] on by default error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:30:5 + --> $DIR/match_bool.rs:40:5 | -30 | / match test { -31 | | false => { println!("Noooo!"); } -32 | | true => { println!("Yes!"); } -33 | | }; +40 | / match test { +41 | | false => { println!("Noooo!"); } +42 | | true => { println!("Yes!"); } +43 | | }; | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` error: aborting due to 8 previous errors diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 92befb25a7e..e6e4154e437 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(exclusive_range_pattern)] diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 6f1a067382a..bed903faf1a 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,362 +1,362 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:21:5 + --> $DIR/matches.rs:31:5 | -21 | / match ExprNode::Butterflies { -22 | | ExprNode::ExprAddrOf => Some(&NODE), -23 | | _ => { let x = 5; None }, -24 | | } +31 | / match ExprNode::Butterflies { +32 | | ExprNode::ExprAddrOf => Some(&NODE), +33 | | _ => { let x = 5; None }, +34 | | } | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` | = note: `-D clippy::single-match-else` implied by `-D warnings` error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:30:9 + --> $DIR/matches.rs:40:9 | -30 | / match v { -31 | | &Some(v) => println!("{:?}", v), -32 | | &None => println!("none"), -33 | | } +40 | / match v { +41 | | &Some(v) => println!("{:?}", v), +42 | | &None => println!("none"), +43 | | } | |_________^ | = note: `-D clippy::match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -30 | match *v { -31 | Some(v) => println!("{:?}", v), -32 | None => println!("none"), +40 | match *v { +41 | Some(v) => println!("{:?}", v), +42 | None => println!("none"), | error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:40:5 + --> $DIR/matches.rs:50:5 | -40 | / match tup { -41 | | &(v, 1) => println!("{}", v), -42 | | _ => println!("none"), -43 | | } +50 | / match tup { +51 | | &(v, 1) => println!("{}", v), +52 | | _ => println!("none"), +53 | | } | |_____^ help: try this: `if let &(v, 1) = tup { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; } else { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; }` error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:40:5 + --> $DIR/matches.rs:50:5 | -40 | / match tup { -41 | | &(v, 1) => println!("{}", v), -42 | | _ => println!("none"), -43 | | } +50 | / match tup { +51 | | &(v, 1) => println!("{}", v), +52 | | _ => println!("none"), +53 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -40 | match *tup { -41 | (v, 1) => println!("{}", v), +50 | match *tup { +51 | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:46:5 + --> $DIR/matches.rs:56:5 | -46 | / match &w { -47 | | &Some(v) => println!("{:?}", v), -48 | | &None => println!("none"), -49 | | } +56 | / match &w { +57 | | &Some(v) => println!("{:?}", v), +58 | | &None => println!("none"), +59 | | } | |_____^ help: try | -46 | match w { -47 | Some(v) => println!("{:?}", v), -48 | None => println!("none"), +56 | match w { +57 | Some(v) => println!("{:?}", v), +58 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:57:5 + --> $DIR/matches.rs:67:5 | -57 | / if let &None = a { -58 | | println!("none"); -59 | | } +67 | / if let &None = a { +68 | | println!("none"); +69 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -57 | if let None = *a { +67 | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:62:5 + --> $DIR/matches.rs:72:5 | -62 | / if let &None = &b { -63 | | println!("none"); -64 | | } +72 | / if let &None = &b { +73 | | println!("none"); +74 | | } | |_____^ help: try | -62 | if let None = b { +72 | if let None = b { | ^^^^ ^ error: some ranges overlap - --> $DIR/matches.rs:71:9 + --> $DIR/matches.rs:81:9 | -71 | 0 ... 10 => println!("0 ... 10"), +81 | 0 ... 10 => println!("0 ... 10"), | ^^^^^^^^ | = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this - --> $DIR/matches.rs:72:9 + --> $DIR/matches.rs:82:9 | -72 | 0 ... 11 => println!("0 ... 11"), +82 | 0 ... 11 => println!("0 ... 11"), | ^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:77:9 + --> $DIR/matches.rs:87:9 | -77 | 0 ... 5 => println!("0 ... 5"), +87 | 0 ... 5 => println!("0 ... 5"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:79:9 + --> $DIR/matches.rs:89:9 | -79 | FOO ... 11 => println!("0 ... 11"), +89 | FOO ... 11 => println!("0 ... 11"), | ^^^^^^^^^^ error: some ranges overlap - --> $DIR/matches.rs:85:9 + --> $DIR/matches.rs:95:9 | -85 | 0 ... 5 => println!("0 ... 5"), +95 | 0 ... 5 => println!("0 ... 5"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:84:9 + --> $DIR/matches.rs:94:9 | -84 | 2 => println!("2"), +94 | 2 => println!("2"), | ^ error: some ranges overlap - --> $DIR/matches.rs:91:9 - | -91 | 0 ... 2 => println!("0 ... 2"), - | ^^^^^^^ - | + --> $DIR/matches.rs:101:9 + | +101 | 0 ... 2 => println!("0 ... 2"), + | ^^^^^^^ + | note: overlaps with this - --> $DIR/matches.rs:90:9 - | -90 | 2 => println!("2"), - | ^ + --> $DIR/matches.rs:100:9 + | +100 | 2 => println!("2"), + | ^ error: some ranges overlap - --> $DIR/matches.rs:114:9 + --> $DIR/matches.rs:124:9 | -114 | 0 .. 11 => println!("0 .. 11"), +124 | 0 .. 11 => println!("0 .. 11"), | ^^^^^^^ | note: overlaps with this - --> $DIR/matches.rs:115:9 + --> $DIR/matches.rs:125:9 | -115 | 0 ... 11 => println!("0 ... 11"), +125 | 0 ... 11 => println!("0 ... 11"), | ^^^^^^^^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:132:9 + --> $DIR/matches.rs:142:9 | -132 | Err(_) => panic!("err") +142 | Err(_) => panic!("err") | ^^^^^^ | = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:131:18 + --> $DIR/matches.rs:141:18 | -131 | Ok(_) => println!("ok"), +141 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:130:18 + --> $DIR/matches.rs:140:18 | -130 | Ok(3) => println!("ok"), +140 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:130:18 + --> $DIR/matches.rs:140:18 | -130 | Ok(3) => println!("ok"), +140 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:138:9 + --> $DIR/matches.rs:148:9 | -138 | Err(_) => {panic!()} +148 | Err(_) => {panic!()} | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:137:18 + --> $DIR/matches.rs:147:18 | -137 | Ok(_) => println!("ok"), +147 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:136:18 + --> $DIR/matches.rs:146:18 | -136 | Ok(3) => println!("ok"), +146 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:136:18 + --> $DIR/matches.rs:146:18 | -136 | Ok(3) => println!("ok"), +146 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:144:9 + --> $DIR/matches.rs:154:9 | -144 | Err(_) => {panic!();} +154 | Err(_) => {panic!();} | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:143:18 + --> $DIR/matches.rs:153:18 | -143 | Ok(_) => println!("ok"), +153 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:142:18 + --> $DIR/matches.rs:152:18 | -142 | Ok(3) => println!("ok"), +152 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:142:18 + --> $DIR/matches.rs:152:18 | -142 | Ok(3) => println!("ok"), +152 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:150:18 + --> $DIR/matches.rs:160:18 | -150 | Ok(_) => println!("ok"), +160 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:149:18 + --> $DIR/matches.rs:159:18 | -149 | Ok(3) => println!("ok"), +159 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:149:18 + --> $DIR/matches.rs:159:18 | -149 | Ok(3) => println!("ok"), +159 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:157:18 + --> $DIR/matches.rs:167:18 | -157 | Ok(_) => println!("ok"), +167 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:156:18 + --> $DIR/matches.rs:166:18 | -156 | Ok(3) => println!("ok"), +166 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:156:18 + --> $DIR/matches.rs:166:18 | -156 | Ok(3) => println!("ok"), +166 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:163:18 + --> $DIR/matches.rs:173:18 | -163 | Ok(_) => println!("ok"), +173 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:162:18 + --> $DIR/matches.rs:172:18 | -162 | Ok(3) => println!("ok"), +172 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:162:18 + --> $DIR/matches.rs:172:18 | -162 | Ok(3) => println!("ok"), +172 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:169:18 + --> $DIR/matches.rs:179:18 | -169 | Ok(_) => println!("ok"), +179 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:168:18 + --> $DIR/matches.rs:178:18 | -168 | Ok(3) => println!("ok"), +178 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:168:18 + --> $DIR/matches.rs:178:18 | -168 | Ok(3) => println!("ok"), +178 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:190:29 + --> $DIR/matches.rs:200:29 | -190 | (Ok(_), Some(x)) => println!("ok {}", x), +200 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:189:29 + --> $DIR/matches.rs:199:29 | -189 | (Ok(x), Some(_)) => println!("ok {}", x), +199 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:189:29 + --> $DIR/matches.rs:199:29 | -189 | (Ok(x), Some(_)) => println!("ok {}", x), +199 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:205:18 + --> $DIR/matches.rs:215:18 | -205 | Ok(_) => println!("ok"), +215 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:204:18 + --> $DIR/matches.rs:214:18 | -204 | Ok(3) => println!("ok"), +214 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:204:18 + --> $DIR/matches.rs:214:18 | -204 | Ok(3) => println!("ok"), +214 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:212:33 + --> $DIR/matches.rs:222:33 | -212 | let borrowed: Option<&()> = match owned { +222 | let borrowed: Option<&()> = match owned { | _________________________________^ -213 | | None => None, -214 | | Some(ref v) => Some(v), -215 | | }; +223 | | None => None, +224 | | Some(ref v) => Some(v), +225 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:218:39 + --> $DIR/matches.rs:228:39 | -218 | let borrow_mut: Option<&mut ()> = match mut_owned { +228 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -219 | | None => None, -220 | | Some(ref mut v) => Some(v), -221 | | }; +229 | | None => None, +230 | | Some(ref mut v) => Some(v), +231 | | }; | |_____^ help: try this: `mut_owned.as_mut()` error: aborting due to 26 previous errors diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 96d333a7170..0e7cfbffa4c 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 1f43d9f360a..06ac6a3679d 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -1,21 +1,21 @@ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:18:5 + --> $DIR/mem_forget.rs:28:5 | -18 | memstuff::forget(six); +28 | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:21:5 + --> $DIR/mem_forget.rs:31:5 | -21 | std::mem::forget(seven); +31 | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:24:5 + --> $DIR/mem_forget.rs:34:5 | -24 | forgetSomething(eight); +34 | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 62df42ef2d2..69e3ae96bad 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 8385fa3cb3c..64a1690156c 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,15 +1,15 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:8:13 - | -8 | let _ = mem::replace(&mut an_option, None); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` - | - = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` + --> $DIR/mem_replace.rs:18:13 + | +18 | let _ = mem::replace(&mut an_option, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` + | + = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:10:13 + --> $DIR/mem_replace.rs:20:13 | -10 | let _ = mem::replace(an_option, None); +20 | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: aborting due to 2 previous errors diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 7faa45b987d..5bf52c740fe 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 3189f375647..4b8c0403702 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,454 +1,454 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:21:5 + --> $DIR/methods.rs:31:5 | -21 | pub fn add(self, other: T) -> T { self } +31 | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:32:17 + --> $DIR/methods.rs:42:17 | -32 | fn into_u16(&self) -> u16 { 0 } +42 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:34:21 + --> $DIR/methods.rs:44:21 | -34 | fn to_something(self) -> u32 { 0 } +44 | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:36:12 + --> $DIR/methods.rs:46:12 | -36 | fn new(self) {} +46 | fn new(self) {} | ^^^^ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:36:5 + --> $DIR/methods.rs:46:5 | -36 | fn new(self) {} +46 | fn new(self) {} | ^^^^^^^^^^^^^^^ | = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:104:13 + --> $DIR/methods.rs:114:13 | -104 | let _ = opt.map(|x| x + 1) +114 | let _ = opt.map(|x| x + 1) | _____________^ -105 | | -106 | | .unwrap_or(0); // should lint even though this call is on a separate line +115 | | +116 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:108:13 + --> $DIR/methods.rs:118:13 | -108 | let _ = opt.map(|x| { +118 | let _ = opt.map(|x| { | _____________^ -109 | | x + 1 -110 | | } -111 | | ).unwrap_or(0); +119 | | x + 1 +120 | | } +121 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:112:13 + --> $DIR/methods.rs:122:13 | -112 | let _ = opt.map(|x| x + 1) +122 | let _ = opt.map(|x| x + 1) | _____________^ -113 | | .unwrap_or({ -114 | | 0 -115 | | }); +123 | | .unwrap_or({ +124 | | 0 +125 | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:117:13 + --> $DIR/methods.rs:127:13 | -117 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); +127 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:119:13 + --> $DIR/methods.rs:129:13 | -119 | let _ = opt.map(|x| { +129 | let _ = opt.map(|x| { | _____________^ -120 | | Some(x + 1) -121 | | } -122 | | ).unwrap_or(None); +130 | | Some(x + 1) +131 | | } +132 | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:123:13 + --> $DIR/methods.rs:133:13 | -123 | let _ = opt +133 | let _ = opt | _____________^ -124 | | .map(|x| Some(x + 1)) -125 | | .unwrap_or(None); +134 | | .map(|x| Some(x + 1)) +135 | | .unwrap_or(None); | |________________________^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:131:13 + --> $DIR/methods.rs:141:13 | -131 | let _ = opt.map(|x| x + 1) +141 | let _ = opt.map(|x| x + 1) | _____________^ -132 | | -133 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +142 | | +143 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:135:13 + --> $DIR/methods.rs:145:13 | -135 | let _ = opt.map(|x| { +145 | let _ = opt.map(|x| { | _____________^ -136 | | x + 1 -137 | | } -138 | | ).unwrap_or_else(|| 0); +146 | | x + 1 +147 | | } +148 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:139:13 + --> $DIR/methods.rs:149:13 | -139 | let _ = opt.map(|x| x + 1) +149 | let _ = opt.map(|x| x + 1) | _____________^ -140 | | .unwrap_or_else(|| -141 | | 0 -142 | | ); +150 | | .unwrap_or_else(|| +151 | | 0 +152 | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:148:13 + --> $DIR/methods.rs:158:13 | -148 | let _ = opt.map_or(None, |x| Some(x + 1)); +158 | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:150:13 + --> $DIR/methods.rs:160:13 | -150 | let _ = opt.map_or(None, |x| { +160 | let _ = opt.map_or(None, |x| { | _____________^ -151 | | Some(x + 1) -152 | | } -153 | | ); +161 | | Some(x + 1) +162 | | } +163 | | ); | |_________________^ help: try using and_then instead | -150 | let _ = opt.and_then(|x| { -151 | Some(x + 1) -152 | }); +160 | let _ = opt.and_then(|x| { +161 | Some(x + 1) +162 | }); | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:163:13 + --> $DIR/methods.rs:173:13 | -163 | let _ = res.map(|x| x + 1) +173 | let _ = res.map(|x| x + 1) | _____________^ -164 | | -165 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line +174 | | +175 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | |_____________________________________^ | = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:167:13 + --> $DIR/methods.rs:177:13 | -167 | let _ = res.map(|x| { +177 | let _ = res.map(|x| { | _____________^ -168 | | x + 1 -169 | | } -170 | | ).unwrap_or_else(|e| 0); +178 | | x + 1 +179 | | } +180 | | ).unwrap_or_else(|e| 0); | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:171:13 + --> $DIR/methods.rs:181:13 | -171 | let _ = res.map(|x| x + 1) +181 | let _ = res.map(|x| x + 1) | _____________^ -172 | | .unwrap_or_else(|e| -173 | | 0 -174 | | ); +182 | | .unwrap_or_else(|e| +183 | | 0 +184 | | ); | |_________________^ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:234:13 + --> $DIR/methods.rs:244:13 | -234 | let _ = v.iter().filter(|&x| *x < 0).next(); +244 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:237:13 + --> $DIR/methods.rs:247:13 | -237 | let _ = v.iter().filter(|&x| { +247 | let _ = v.iter().filter(|&x| { | _____________^ -238 | | *x < 0 -239 | | } -240 | | ).next(); +248 | | *x < 0 +249 | | } +250 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:252:13 + --> $DIR/methods.rs:262:13 | -252 | let _ = v.iter().find(|&x| *x < 0).is_some(); +262 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:255:13 + --> $DIR/methods.rs:265:13 | -255 | let _ = v.iter().find(|&x| { +265 | let _ = v.iter().find(|&x| { | _____________^ -256 | | *x < 0 -257 | | } -258 | | ).is_some(); +266 | | *x < 0 +267 | | } +268 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:261:13 + --> $DIR/methods.rs:271:13 | -261 | let _ = v.iter().position(|&x| x < 0).is_some(); +271 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:264:13 + --> $DIR/methods.rs:274:13 | -264 | let _ = v.iter().position(|&x| { +274 | let _ = v.iter().position(|&x| { | _____________^ -265 | | x < 0 -266 | | } -267 | | ).is_some(); +275 | | x < 0 +276 | | } +277 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:270:13 + --> $DIR/methods.rs:280:13 | -270 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +280 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:273:13 + --> $DIR/methods.rs:283:13 | -273 | let _ = v.iter().rposition(|&x| { +283 | let _ = v.iter().rposition(|&x| { | _____________^ -274 | | x < 0 -275 | | } -276 | | ).is_some(); +284 | | x < 0 +285 | | } +286 | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:308:22 + --> $DIR/methods.rs:318:22 | -308 | with_constructor.unwrap_or(make()); +318 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` | = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:311:5 + --> $DIR/methods.rs:321:5 | -311 | with_new.unwrap_or(Vec::new()); +321 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:314:21 + --> $DIR/methods.rs:324:21 | -314 | with_const_args.unwrap_or(Vec::with_capacity(12)); +324 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:317:14 + --> $DIR/methods.rs:327:14 | -317 | with_err.unwrap_or(make()); +327 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:320:19 + --> $DIR/methods.rs:330:19 | -320 | with_err_args.unwrap_or(Vec::with_capacity(12)); +330 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:323:5 + --> $DIR/methods.rs:333:5 | -323 | with_default_trait.unwrap_or(Default::default()); +333 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:326:5 + --> $DIR/methods.rs:336:5 | -326 | with_default_type.unwrap_or(u64::default()); +336 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:329:14 + --> $DIR/methods.rs:339:14 | -329 | with_vec.unwrap_or(vec![]); +339 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:334:21 + --> $DIR/methods.rs:344:21 | -334 | without_default.unwrap_or(Foo::new()); +344 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:337:19 + --> $DIR/methods.rs:347:19 | -337 | map.entry(42).or_insert(String::new()); +347 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:340:21 + --> $DIR/methods.rs:350:21 | -340 | btree.entry(42).or_insert(String::new()); +350 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:343:21 + --> $DIR/methods.rs:353:21 | -343 | let _ = stringy.unwrap_or("".to_owned()); +353 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: `error_code` is shadowed by `123_i32` - --> $DIR/methods.rs:377:9 + --> $DIR/methods.rs:387:9 | -377 | let error_code = 123_i32; +387 | let error_code = 123_i32; | ^^^^^^^^^^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here - --> $DIR/methods.rs:377:22 + --> $DIR/methods.rs:387:22 | -377 | let error_code = 123_i32; +387 | let error_code = 123_i32; | ^^^^^^^ note: previous binding is here - --> $DIR/methods.rs:364:9 + --> $DIR/methods.rs:374:9 | -364 | let error_code = 123_i32; +374 | let error_code = 123_i32; | ^^^^^^^^^^ error: use of `expect` followed by a function call - --> $DIR/methods.rs:366:26 + --> $DIR/methods.rs:376:26 | -366 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); +376 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/methods.rs:369:26 + --> $DIR/methods.rs:379:26 | -369 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +379 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:379:25 + --> $DIR/methods.rs:389:25 | -379 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); +389 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/methods.rs:382:25 + --> $DIR/methods.rs:392:25 | -382 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +392 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:406:23 + --> $DIR/methods.rs:416:23 | -406 | let bad_vec = some_vec.iter().nth(3); +416 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:407:26 + --> $DIR/methods.rs:417:26 | -407 | let bad_slice = &some_vec[..].iter().nth(3); +417 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:408:31 + --> $DIR/methods.rs:418:31 | -408 | let bad_boxed_slice = boxed_slice.iter().nth(3); +418 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:409:29 + --> $DIR/methods.rs:419:29 | -409 | let bad_vec_deque = some_vec_deque.iter().nth(3); +419 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:414:23 + --> $DIR/methods.rs:424:23 | -414 | let bad_vec = some_vec.iter_mut().nth(3); +424 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:417:26 + --> $DIR/methods.rs:427:26 | -417 | let bad_slice = &some_vec[..].iter_mut().nth(3); +427 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:420:29 + --> $DIR/methods.rs:430:29 | -420 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +430 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:432:13 + --> $DIR/methods.rs:442:13 | -432 | let _ = some_vec.iter().skip(42).next(); +442 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:433:13 + --> $DIR/methods.rs:443:13 | -433 | let _ = some_vec.iter().cycle().skip(42).next(); +443 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:434:13 + --> $DIR/methods.rs:444:13 | -434 | let _ = (1..10).skip(10).next(); +444 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:435:14 + --> $DIR/methods.rs:445:14 | -435 | let _ = &some_vec[..].iter().skip(3).next(); +445 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:444:13 + --> $DIR/methods.rs:454:13 | -444 | let _ = opt.unwrap(); +454 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 9866933f9fe..32e3863ad40 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index e89542a2ddc..3ed67ad258e 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,45 +1,45 @@ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:15:5 + --> $DIR/min_max.rs:25:5 | -15 | min(1, max(3, x)); +25 | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::min-max` implied by `-D warnings` error: this min/max combination leads to constant result - --> $DIR/min_max.rs:16:5 + --> $DIR/min_max.rs:26:5 | -16 | min(max(3, x), 1); +26 | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:17:5 + --> $DIR/min_max.rs:27:5 | -17 | max(min(x, 1), 3); +27 | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:18:5 + --> $DIR/min_max.rs:28:5 | -18 | max(3, min(x, 1)); +28 | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:20:5 + --> $DIR/min_max.rs:30:5 | -20 | my_max(3, my_min(x, 1)); +30 | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:32:5 + --> $DIR/min_max.rs:42:5 | -32 | min("Apple", max("Zoo", s)); +42 | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:33:5 + --> $DIR/min_max.rs:43:5 | -33 | max(min(s, "Apple"), "Zoo"); +43 | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index 6968adb312b..43dad8398f1 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] /* This file incorporates work covered by the following copyright and diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index ebc4c5aca43..67f50152c73 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -1,267 +1,267 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:28:1 + --> $DIR/missing-doc.rs:38:1 | -28 | type Typedef = String; +38 | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:29:1 + --> $DIR/missing-doc.rs:39:1 | -29 | pub type PubTypedef = String; +39 | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:31:1 + --> $DIR/missing-doc.rs:41:1 | -31 | / struct Foo { -32 | | a: isize, -33 | | b: isize, -34 | | } +41 | / struct Foo { +42 | | a: isize, +43 | | b: isize, +44 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:32:5 + --> $DIR/missing-doc.rs:42:5 | -32 | a: isize, +42 | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:33:5 + --> $DIR/missing-doc.rs:43:5 | -33 | b: isize, +43 | b: isize, | ^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:36:1 + --> $DIR/missing-doc.rs:46:1 | -36 | / pub struct PubFoo { -37 | | pub a: isize, -38 | | b: isize, -39 | | } +46 | / pub struct PubFoo { +47 | | pub a: isize, +48 | | b: isize, +49 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:37:5 + --> $DIR/missing-doc.rs:47:5 | -37 | pub a: isize, +47 | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:38:5 + --> $DIR/missing-doc.rs:48:5 | -38 | b: isize, +48 | b: isize, | ^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:47:1 + --> $DIR/missing-doc.rs:57:1 | -47 | mod module_no_dox {} +57 | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:48:1 + --> $DIR/missing-doc.rs:58:1 | -48 | pub mod pub_module_no_dox {} +58 | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:52:1 + --> $DIR/missing-doc.rs:62:1 | -52 | pub fn foo2() {} +62 | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:53:1 + --> $DIR/missing-doc.rs:63:1 | -53 | fn foo3() {} +63 | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for a trait - --> $DIR/missing-doc.rs:70:1 + --> $DIR/missing-doc.rs:80:1 | -70 | / pub trait C { -71 | | fn foo(&self); -72 | | fn foo_with_impl(&self) {} -73 | | } +80 | / pub trait C { +81 | | fn foo(&self); +82 | | fn foo_with_impl(&self) {} +83 | | } | |_^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:71:5 + --> $DIR/missing-doc.rs:81:5 | -71 | fn foo(&self); +81 | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:72:5 + --> $DIR/missing-doc.rs:82:5 | -72 | fn foo_with_impl(&self) {} +82 | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:82:5 + --> $DIR/missing-doc.rs:92:5 | -82 | type AssociatedType; +92 | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:83:5 + --> $DIR/missing-doc.rs:93:5 | -83 | type AssociatedTypeDef = Self; +93 | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:94:5 - | -94 | pub fn foo() {} - | ^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:104:5 + | +104 | pub fn foo() {} + | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:95:5 - | -95 | fn bar() {} - | ^^^^^^^^^^^ + --> $DIR/missing-doc.rs:105:5 + | +105 | fn bar() {} + | ^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:99:5 - | -99 | pub fn foo() {} - | ^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:109:5 + | +109 | pub fn foo() {} + | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:102:5 + --> $DIR/missing-doc.rs:112:5 | -102 | fn foo2() {} +112 | fn foo2() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:128:1 + --> $DIR/missing-doc.rs:138:1 | -128 | / enum Baz { -129 | | BazA { -130 | | a: isize, -131 | | b: isize -132 | | }, -133 | | BarB -134 | | } +138 | / enum Baz { +139 | | BazA { +140 | | a: isize, +141 | | b: isize +142 | | }, +143 | | BarB +144 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:129:5 + --> $DIR/missing-doc.rs:139:5 | -129 | / BazA { -130 | | a: isize, -131 | | b: isize -132 | | }, +139 | / BazA { +140 | | a: isize, +141 | | b: isize +142 | | }, | |_____^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:130:9 + --> $DIR/missing-doc.rs:140:9 | -130 | a: isize, +140 | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:131:9 + --> $DIR/missing-doc.rs:141:9 | -131 | b: isize +141 | b: isize | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:133:5 + --> $DIR/missing-doc.rs:143:5 | -133 | BarB +143 | BarB | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:136:1 + --> $DIR/missing-doc.rs:146:1 | -136 | / pub enum PubBaz { -137 | | PubBazA { -138 | | a: isize, -139 | | }, -140 | | } +146 | / pub enum PubBaz { +147 | | PubBazA { +148 | | a: isize, +149 | | }, +150 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:137:5 + --> $DIR/missing-doc.rs:147:5 | -137 | / PubBazA { -138 | | a: isize, -139 | | }, +147 | / PubBazA { +148 | | a: isize, +149 | | }, | |_____^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:138:9 + --> $DIR/missing-doc.rs:148:9 | -138 | a: isize, +148 | a: isize, | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:162:1 + --> $DIR/missing-doc.rs:172:1 | -162 | const FOO: u32 = 0; +172 | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:169:1 + --> $DIR/missing-doc.rs:179:1 | -169 | pub const FOO4: u32 = 0; +179 | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:172:1 + --> $DIR/missing-doc.rs:182:1 | -172 | static BAR: u32 = 0; +182 | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:179:1 + --> $DIR/missing-doc.rs:189:1 | -179 | pub static BAR4: u32 = 0; +189 | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:182:1 + --> $DIR/missing-doc.rs:192:1 | -182 | / mod internal_impl { -183 | | /// dox -184 | | pub fn documented() {} -185 | | pub fn undocumented1() {} +192 | / mod internal_impl { +193 | | /// dox +194 | | pub fn documented() {} +195 | | pub fn undocumented1() {} ... | -194 | | } -195 | | } +204 | | } +205 | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:185:5 + --> $DIR/missing-doc.rs:195:5 | -185 | pub fn undocumented1() {} +195 | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:186:5 + --> $DIR/missing-doc.rs:196:5 | -186 | pub fn undocumented2() {} +196 | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:187:5 + --> $DIR/missing-doc.rs:197:5 | -187 | fn undocumented3() {} +197 | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:192:9 + --> $DIR/missing-doc.rs:202:9 | -192 | pub fn also_undocumented1() {} +202 | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:193:9 + --> $DIR/missing-doc.rs:203:9 | -193 | fn also_undocumented2() {} +203 | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 39 previous errors diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 7fbb01c6d2b..593774da1b4 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] /* This file incorporates work covered by the following copyright and diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index 3609c9101b7..fc617ef54c9 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -1,39 +1,39 @@ error: missing `#[inline]` for a function - --> $DIR/missing_inline.rs:33:1 + --> $DIR/missing_inline.rs:43:1 | -33 | pub fn pub_foo() {} // missing #[inline] +43 | pub fn pub_foo() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` error: missing `#[inline]` for a default trait method - --> $DIR/missing_inline.rs:48:5 + --> $DIR/missing_inline.rs:58:5 | -48 | fn PubBar_b() {} // missing #[inline] +58 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:61:5 + --> $DIR/missing_inline.rs:71:5 | -61 | fn PubBar_a() {} // missing #[inline] +71 | fn PubBar_a() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:62:5 + --> $DIR/missing_inline.rs:72:5 | -62 | fn PubBar_b() {} // missing #[inline] +72 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:63:5 + --> $DIR/missing_inline.rs:73:5 | -63 | fn PubBar_c() {} // missing #[inline] +73 | fn PubBar_c() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:73:5 + --> $DIR/missing_inline.rs:83:5 | -73 | pub fn PubFooImpl() {} // missing #[inline] +83 | pub fn PubFooImpl() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index b6917020ea2..1dfc06f38af 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::module_inception)] diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index 43f9666f78d..c1e6d0a6e62 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,19 +1,19 @@ error: module has the same name as its containing module - --> $DIR/module_inception.rs:7:9 - | -7 | / mod bar { -8 | | mod foo {} -9 | | } - | |_________^ - | - = note: `-D clippy::module-inception` implied by `-D warnings` + --> $DIR/module_inception.rs:17:9 + | +17 | / mod bar { +18 | | mod foo {} +19 | | } + | |_________^ + | + = note: `-D clippy::module-inception` implied by `-D warnings` error: module has the same name as its containing module - --> $DIR/module_inception.rs:12:5 + --> $DIR/module_inception.rs:22:5 | -12 | / mod foo { -13 | | mod bar {} -14 | | } +22 | / mod foo { +23 | | mod bar {} +24 | | } | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index 7dcec04baf9..6e0cbc581dc 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::modulo_one)] diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index 5d42c3e0a29..57e2c59ee14 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -1,10 +1,10 @@ error: any number modulo 1 will be 0 - --> $DIR/modulo_one.rs:7:5 - | -7 | 10 % 1; - | ^^^^^^ - | - = note: `-D clippy::modulo-one` implied by `-D warnings` + --> $DIR/modulo_one.rs:17:5 + | +17 | 10 % 1; + | ^^^^^^ + | + = note: `-D clippy::modulo-one` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index b75fa92f098..37256efb839 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index 0f5baa2d27e..48b5abf5a6e 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -1,62 +1,62 @@ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:9:39 - | -9 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { - | ^^^^^^^^ - | - = note: `-D clippy::mut-from-ref` implied by `-D warnings` + --> $DIR/mut_from_ref.rs:19:39 + | +19 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { + | ^^^^^^^^ + | + = note: `-D clippy::mut-from-ref` implied by `-D warnings` note: immutable borrow here - --> $DIR/mut_from_ref.rs:9:29 - | -9 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { - | ^^^^^ + --> $DIR/mut_from_ref.rs:19:29 + | +19 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { + | ^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:15:25 + --> $DIR/mut_from_ref.rs:25:25 | -15 | fn ouch(x: &Foo) -> &mut Foo; +25 | fn ouch(x: &Foo) -> &mut Foo; | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:15:16 + --> $DIR/mut_from_ref.rs:25:16 | -15 | fn ouch(x: &Foo) -> &mut Foo; +25 | fn ouch(x: &Foo) -> &mut Foo; | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:24:21 + --> $DIR/mut_from_ref.rs:34:21 | -24 | fn fail(x: &u32) -> &mut u16 { +34 | fn fail(x: &u32) -> &mut u16 { | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:24:12 + --> $DIR/mut_from_ref.rs:34:12 | -24 | fn fail(x: &u32) -> &mut u16 { +34 | fn fail(x: &u32) -> &mut u16 { | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:28:50 + --> $DIR/mut_from_ref.rs:38:50 | -28 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +38 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:28:25 + --> $DIR/mut_from_ref.rs:38:25 | -28 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +38 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:32:67 + --> $DIR/mut_from_ref.rs:42:67 | -32 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +42 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:32:27 + --> $DIR/mut_from_ref.rs:42:27 | -32 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +42 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 4656d27648f..81c945beafc 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 88bd2f729af..c05c0215795 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -1,60 +1,60 @@ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:10:12 + --> $DIR/mut_mut.rs:20:12 | -10 | fn fun(x : &mut &mut u32) -> bool { +20 | fn fun(x : &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ | = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:24:17 + --> $DIR/mut_mut.rs:34:17 | -24 | let mut x = &mut &mut 1u32; +34 | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:19:20 + --> $DIR/mut_mut.rs:29:20 | -19 | ($p:expr) => { &mut $p } +29 | ($p:expr) => { &mut $p } | ^^^^^^^ ... -39 | let mut z = mut_ptr!(&mut 3u32); +49 | let mut z = mut_ptr!(&mut 3u32); | ------------------- in this macro invocation error: this expression mutably borrows a mutable reference. Consider reborrowing - --> $DIR/mut_mut.rs:26:21 + --> $DIR/mut_mut.rs:36:21 | -26 | let mut y = &mut x; +36 | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:30:33 + --> $DIR/mut_mut.rs:40:33 | -30 | let y : &mut &mut u32 = &mut &mut 2; +40 | let y : &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:30:17 + --> $DIR/mut_mut.rs:40:17 | -30 | let y : &mut &mut u32 = &mut &mut 2; +40 | let y : &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:38 + --> $DIR/mut_mut.rs:45:38 | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; +45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:17 + --> $DIR/mut_mut.rs:45:17 | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; +45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:22 + --> $DIR/mut_mut.rs:45:22 | -35 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; +45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs index 0e397c7ae8c..edc86b5d6ac 100644 --- a/tests/ui/mut_range_bound.rs +++ b/tests/ui/mut_range_bound.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index fece9610697..a476ad5d14e 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,33 +1,33 @@ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:18:21 + --> $DIR/mut_range_bound.rs:28:21 | -18 | for i in 0..m { m = 5; } // warning +28 | for i in 0..m { m = 5; } // warning | ^^^^^ | = note: `-D clippy::mut-range-bound` implied by `-D warnings` error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:23:22 + --> $DIR/mut_range_bound.rs:33:22 | -23 | for i in m..10 { m *= 2; } // warning +33 | for i in m..10 { m *= 2; } // warning | ^^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:29:21 + --> $DIR/mut_range_bound.rs:39:21 | -29 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) +39 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:29:28 + --> $DIR/mut_range_bound.rs:39:28 | -29 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) +39 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:40:22 + --> $DIR/mut_range_bound.rs:50:22 | -40 | let n = &mut m; // warning +50 | let n = &mut m; // warning | ^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index 38b0e25e07c..f42d48f0db4 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index ee62e264767..07b07580d4b 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,21 +1,21 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:22:34 + --> $DIR/mut_reference.rs:32:34 | -22 | takes_an_immutable_reference(&mut 42); +32 | takes_an_immutable_reference(&mut 42); | ^^^^^^^ | = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` error: The function/method `as_ptr` doesn't need a mutable reference - --> $DIR/mut_reference.rs:24:12 + --> $DIR/mut_reference.rs:34:12 | -24 | as_ptr(&mut 42); +34 | as_ptr(&mut 42); | ^^^^^^^ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:28:44 + --> $DIR/mut_reference.rs:38:44 | -28 | my_struct.takes_an_immutable_reference(&mut 42); +38 | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index 3eefbb97ab8..e0ce93bf698 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 2df58889a47..a317e8a6c94 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -1,47 +1,47 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:9:5 - | -9 | Mutex::new(true); - | ^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::mutex-atomic` implied by `-D warnings` + --> $DIR/mutex_atomic.rs:19:5 + | +19 | Mutex::new(true); + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::mutex-atomic` implied by `-D warnings` error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:10:5 + --> $DIR/mutex_atomic.rs:20:5 | -10 | Mutex::new(5usize); +20 | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:11:5 + --> $DIR/mutex_atomic.rs:21:5 | -11 | Mutex::new(9isize); +21 | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:13:5 + --> $DIR/mutex_atomic.rs:23:5 | -13 | Mutex::new(&x as *const u32); +23 | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:14:5 + --> $DIR/mutex_atomic.rs:24:5 | -14 | Mutex::new(&mut x as *mut u32); +24 | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:15:5 + --> $DIR/mutex_atomic.rs:25:5 | -15 | Mutex::new(0u32); +25 | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::mutex-integer` implied by `-D warnings` error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:16:5 + --> $DIR/mutex_atomic.rs:26:5 | -16 | Mutex::new(0i32); +26 | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 4e6f65ed0dd..0e8e250c95d 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::needless_bool)] diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index dd132bc671e..13af6fc3564 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,69 +1,69 @@ error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:9:5 - | -9 | if x { true } else { true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::needless-bool` implied by `-D warnings` + --> $DIR/needless_bool.rs:19:5 + | +19 | if x { true } else { true }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:10:5 + --> $DIR/needless_bool.rs:20:5 | -10 | if x { false } else { false }; +20 | if x { false } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:11:5 + --> $DIR/needless_bool.rs:21:5 | -11 | if x { true } else { false }; +21 | if x { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:12:5 + --> $DIR/needless_bool.rs:22:5 | -12 | if x { false } else { true }; +22 | if x { false } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:13:5 + --> $DIR/needless_bool.rs:23:5 | -13 | if x && y { false } else { true }; +23 | if x && y { false } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:25:5 + --> $DIR/needless_bool.rs:35:5 | -25 | if x { return true } else { return true }; +35 | if x { return true } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:30:5 + --> $DIR/needless_bool.rs:40:5 | -30 | if x { return false } else { return false }; +40 | if x { return false } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:35:5 + --> $DIR/needless_bool.rs:45:5 | -35 | if x { return true } else { return false }; +45 | if x { return true } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:40:5 + --> $DIR/needless_bool.rs:50:5 | -40 | if x && y { return true } else { return false }; +50 | if x && y { return true } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:45:5 + --> $DIR/needless_bool.rs:55:5 | -45 | if x { return false } else { return true }; +55 | if x { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:50:5 + --> $DIR/needless_bool.rs:60:5 | -50 | if x && y { return false } else { return true }; +60 | if x && y { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !(x && y)` error: aborting due to 11 previous errors diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 61384c43fa9..1cf7b40661d 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::borrow::Cow; diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index c720dff5d29..93ba61784d3 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,41 +1,41 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:15:15 + --> $DIR/needless_borrow.rs:25:15 | -15 | let c = x(&&a); +25 | let c = x(&&a); | ^^^ help: change this to: `&a` | = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:22:17 + --> $DIR/needless_borrow.rs:32:17 | -22 | if let Some(ref cake) = Some(&5) {} +32 | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:29:15 + --> $DIR/needless_borrow.rs:39:15 | -29 | 46 => &&a, +39 | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:51:34 + --> $DIR/needless_borrow.rs:61:34 | -51 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +61 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:52:30 + --> $DIR/needless_borrow.rs:62:30 | -52 | let _ = v.iter().filter(|&ref a| a.is_empty()); +62 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:52:31 + --> $DIR/needless_borrow.rs:62:31 | -52 | let _ = v.iter().filter(|&ref a| a.is_empty()); +62 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` error: aborting due to 6 previous errors diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 000ecd32da4..650b57b586c 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 3113b887b05..ef80473a9dc 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,27 +1,27 @@ error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:8:34 - | -8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - | ^^^^^^ help: try removing the `&ref` part and just keep: `a` - | - = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` + --> $DIR/needless_borrowed_ref.rs:18:34 + | +18 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + | + = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:13:17 + --> $DIR/needless_borrowed_ref.rs:23:17 | -13 | if let Some(&ref v) = thingy { +23 | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep: `v` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:42:27 + --> $DIR/needless_borrowed_ref.rs:52:27 | -42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +52 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:42:38 + --> $DIR/needless_borrowed_ref.rs:52:38 | -42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +52 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index b001f20d527..45622b33384 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::collections::{HashMap, HashSet, BTreeSet}; diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 0124db3b975..ee41a9d8dea 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,27 +1,27 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:9:28 - | -9 | let len = sample.iter().collect::>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` - | - = note: `-D clippy::needless-collect` implied by `-D warnings` + --> $DIR/needless_collect.rs:19:28 + | +19 | let len = sample.iter().collect::>().len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` + | + = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:10:21 + --> $DIR/needless_collect.rs:20:21 | -10 | if sample.iter().collect::>().is_empty() { +20 | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:13:27 + --> $DIR/needless_collect.rs:23:27 | -13 | sample.iter().cloned().collect::>().contains(&1); +23 | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:14:34 + --> $DIR/needless_collect.rs:24:34 | -14 | sample.iter().map(|x| (x, x)).collect::>().len(); +24 | sample.iter().map(|x| (x, x)).collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 4fe523e48de..4a15987ba96 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 7cfaf89d6e0..10e7062f2a6 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -1,11 +1,11 @@ error: This else block is redundant. - --> $DIR/needless_continue.rs:26:16 + --> $DIR/needless_continue.rs:36:16 | -26 | } else { +36 | } else { | ________________^ -27 | | continue; -28 | | } +37 | | continue; +38 | | } | |_________^ | = note: `-D clippy::needless-continue` implied by `-D warnings` @@ -37,14 +37,14 @@ error: This else block is redundant. error: There is no need for an explicit `else` block for this `if` expression - --> $DIR/needless_continue.rs:41:9 + --> $DIR/needless_continue.rs:51:9 | -41 | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { -42 | | continue; -43 | | } else { -44 | | println!("Blabber"); -45 | | println!("Jabber"); -46 | | } +51 | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { +52 | | continue; +53 | | } else { +54 | | println!("Blabber"); +55 | | println!("Jabber"); +56 | | } | |_________^ | = help: Consider dropping the else clause, and moving out the code in the else block, like so: diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 31ad96942d6..3e029de4755 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::needless_pass_by_value)] diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 0d4a35363fb..3685f0e9614 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,199 +1,199 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:11:23 + --> $DIR/needless_pass_by_value.rs:21:23 | -11 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { +21 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` | = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:25:11 + --> $DIR/needless_pass_by_value.rs:35:11 | -25 | fn bar(x: String, y: Wrapper) { +35 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:25:22 + --> $DIR/needless_pass_by_value.rs:35:22 | -25 | fn bar(x: String, y: Wrapper) { +35 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:31:71 + --> $DIR/needless_pass_by_value.rs:41:71 | -31 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +41 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:43:18 + --> $DIR/needless_pass_by_value.rs:53:18 | -43 | fn test_match(x: Option>, y: Option>) { +53 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -43 | fn test_match(x: &Option>, y: Option>) { -44 | match *x { +53 | fn test_match(x: &Option>, y: Option>) { +54 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:56:24 + --> $DIR/needless_pass_by_value.rs:66:24 | -56 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +66 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:56:36 + --> $DIR/needless_pass_by_value.rs:66:36 | -56 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +66 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead | -56 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -57 | let Wrapper(s) = z; // moved -58 | let Wrapper(ref t) = *y; // not moved -59 | let Wrapper(_) = *y; // still not moved +66 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +67 | let Wrapper(s) = z; // moved +68 | let Wrapper(ref t) = *y; // not moved +69 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:72:49 + --> $DIR/needless_pass_by_value.rs:82:49 | -72 | fn test_blanket_ref(_foo: T, _serializable: S) {} +82 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:74:18 + --> $DIR/needless_pass_by_value.rs:84:18 | -74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:74:29 + --> $DIR/needless_pass_by_value.rs:84:29 | -74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -74 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +84 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -76 | let _ = t.to_string(); +86 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:74:40 + --> $DIR/needless_pass_by_value.rs:84:40 | -74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:74:53 + --> $DIR/needless_pass_by_value.rs:84:53 | -74 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -74 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +84 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -78 | let _ = v.to_owned(); +88 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:86:12 + --> $DIR/needless_pass_by_value.rs:96:12 | -86 | s: String, +96 | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:12 + --> $DIR/needless_pass_by_value.rs:97:12 | -87 | t: String, +97 | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:99:13 - | -99 | _u: U, - | ^ help: consider taking a reference instead: `&U` + --> $DIR/needless_pass_by_value.rs:109:13 + | +109 | _u: U, + | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:100:13 + --> $DIR/needless_pass_by_value.rs:110:13 | -100 | _s: Self, +110 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:122:24 + --> $DIR/needless_pass_by_value.rs:132:24 | -122 | fn bar_copy(x: u32, y: CopyWrapper) { +132 | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:120:1 + --> $DIR/needless_pass_by_value.rs:130:1 | -120 | struct CopyWrapper(u32); +130 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:128:29 + --> $DIR/needless_pass_by_value.rs:138:29 | -128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:120:1 + --> $DIR/needless_pass_by_value.rs:130:1 | -120 | struct CopyWrapper(u32); +130 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:128:45 + --> $DIR/needless_pass_by_value.rs:138:45 | -128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:120:1 + --> $DIR/needless_pass_by_value.rs:130:1 | -120 | struct CopyWrapper(u32); +130 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -128 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { -129 | let CopyWrapper(s) = z; // moved -130 | let CopyWrapper(ref t) = *y; // not moved -131 | let CopyWrapper(_) = *y; // still not moved +138 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { +139 | let CopyWrapper(s) = z; // moved +140 | let CopyWrapper(ref t) = *y; // not moved +141 | let CopyWrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:128:61 + --> $DIR/needless_pass_by_value.rs:138:61 | -128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { +138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:120:1 + --> $DIR/needless_pass_by_value.rs:130:1 | -120 | struct CopyWrapper(u32); +130 | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -128 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { -129 | let CopyWrapper(s) = *z; // moved +138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { +139 | let CopyWrapper(s) = *z; // moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:140:40 + --> $DIR/needless_pass_by_value.rs:150:40 | -140 | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} +150 | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:145:20 + --> $DIR/needless_pass_by_value.rs:155:20 | -145 | fn more_fun(_item: impl Club<'static, i32>) {} +155 | fn more_fun(_item: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` error: aborting due to 22 previous errors diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 6b1305fa2d8..b1ca6d75c99 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![crate_type = "proc-macro"] diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 30613f98f2b..44515502835 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn calc_idx(i: usize) -> usize { (i + i + 20) % 4 } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 1954a8240b2..64b1f3c08f7 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,33 +1,33 @@ error: the loop variable `i` is only used to index `ns`. - --> $DIR/needless_range_loop.rs:8:14 - | -8 | for i in 3..10 { - | ^^^^^ - | - = note: `-D clippy::needless-range-loop` implied by `-D warnings` + --> $DIR/needless_range_loop.rs:18:14 + | +18 | for i in 3..10 { + | ^^^^^ + | + = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator - | -8 | for in ns.iter().take(10).skip(3) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +18 | for in ns.iter().take(10).skip(3) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:29:14 + --> $DIR/needless_range_loop.rs:39:14 | -29 | for i in 0..ms.len() { +39 | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -29 | for in &mut ms { +39 | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:35:14 + --> $DIR/needless_range_loop.rs:45:14 | -35 | for i in 0..ms.len() { +45 | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -35 | for in &mut ms { +45 | for in &mut ms { | ^^^^^^ ^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index a834563eca3..bfe86573a4d 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 094fe3642a2..742ef8d379e 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,51 +1,51 @@ error: unneeded return statement - --> $DIR/needless_return.rs:11:5 + --> $DIR/needless_return.rs:21:5 | -11 | return true; +21 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` | = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded return statement - --> $DIR/needless_return.rs:15:5 + --> $DIR/needless_return.rs:25:5 | -15 | return true +25 | return true | ^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:20:9 + --> $DIR/needless_return.rs:30:9 | -20 | return true; +30 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:22:9 + --> $DIR/needless_return.rs:32:9 | -22 | return false; +32 | return false; | ^^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:28:17 + --> $DIR/needless_return.rs:38:17 | -28 | true => return false, +38 | true => return false, | ^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:30:13 + --> $DIR/needless_return.rs:40:13 | -30 | return true; +40 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:37:9 + --> $DIR/needless_return.rs:47:9 | -37 | return true; +47 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:39:16 + --> $DIR/needless_return.rs:49:16 | -39 | let _ = || return true; +49 | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` error: aborting due to 8 previous errors diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 675c60e2477..70fe7236c24 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index acc51198497..512cec84770 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -1,7 +1,7 @@ error: struct update has no effect, all the fields in the struct have already been specified - --> $DIR/needless_update.rs:16:23 + --> $DIR/needless_update.rs:26:23 | -16 | S { a: 1, b: 1, ..base }; +26 | S { a: 1, b: 1, ..base }; | ^^^^ | = note: `-D clippy::needless-update` implied by `-D warnings` diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 3a472bf6995..c8edba32219 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] //! This test case utilizes `f64` an easy example for `PartialOrd` only types diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 5fd4ab9ba48..1bd292818b3 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,27 +1,27 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:19:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:29:21 | -19 | let _not_less = !(a_value < another_value); +29 | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:22:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:32:30 | -22 | let _not_less_or_equal = !(a_value <= another_value); +32 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:25:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:35:24 | -25 | let _not_greater = !(a_value > another_value); +35 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:28:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:38:33 | -28 | let _not_greater_or_equal = !(a_value >= another_value); +38 | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index b1a1879a3fc..2589f3b8551 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index ba59fdb8940..ed96dd519ff 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -1,15 +1,15 @@ error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:30:5 + --> $DIR/neg_multiply.rs:40:5 | -30 | x * -1; +40 | x * -1; | ^^^^^^ | = note: `-D clippy::neg-multiply` implied by `-D warnings` error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:32:5 + --> $DIR/neg_multiply.rs:42:5 | -32 | -1 * x; +42 | -1 * x; | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index bb6d76b06cd..901a98559e7 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::single_match, unused_assignments, unused_variables, clippy::while_immutable_condition)] diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 3d1235964d1..e4daa6e4350 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,93 +1,93 @@ error: this loop never actually loops - --> $DIR/never_loop.rs:7:5 + --> $DIR/never_loop.rs:17:5 | -7 | / loop { // clippy::never_loop -8 | | x += 1; -9 | | if x == 1 { -10 | | return -11 | | } -12 | | break; -13 | | } +17 | / loop { // clippy::never_loop +18 | | x += 1; +19 | | if x == 1 { +20 | | return +21 | | } +22 | | break; +23 | | } | |_____^ | = note: #[deny(clippy::never_loop)] on by default error: this loop never actually loops - --> $DIR/never_loop.rs:28:5 + --> $DIR/never_loop.rs:38:5 | -28 | / loop { // never loops -29 | | x += 1; -30 | | break -31 | | } +38 | / loop { // never loops +39 | | x += 1; +40 | | break +41 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:47:2 + --> $DIR/never_loop.rs:57:2 | -47 | loop { // never loops +57 | loop { // never loops | _____^ -48 | | while i == 0 { // never loops -49 | | break -50 | | } -51 | | return -52 | | } +58 | | while i == 0 { // never loops +59 | | break +60 | | } +61 | | return +62 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:48:9 + --> $DIR/never_loop.rs:58:9 | -48 | / while i == 0 { // never loops -49 | | break -50 | | } +58 | / while i == 0 { // never loops +59 | | break +60 | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:59:3 + --> $DIR/never_loop.rs:69:3 | -59 | loop { // never loops +69 | loop { // never loops | _________^ -60 | | if x == 5 { break } -61 | | continue 'outer -62 | | } +70 | | if x == 5 { break } +71 | | continue 'outer +72 | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:92:5 - | -92 | / while let Some(y) = x { // never loops -93 | | return -94 | | } - | |_____^ + --> $DIR/never_loop.rs:102:5 + | +102 | / while let Some(y) = x { // never loops +103 | | return +104 | | } + | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:98:5 + --> $DIR/never_loop.rs:108:5 | -98 | / for x in 0..10 { // never loops -99 | | match x { -100 | | 1 => break, -101 | | _ => return, -102 | | } -103 | | } +108 | / for x in 0..10 { // never loops +109 | | match x { +110 | | 1 => break, +111 | | _ => return, +112 | | } +113 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:144:5 + --> $DIR/never_loop.rs:154:5 | -144 | / 'outer: while a { // never loops -145 | | while a { -146 | | if a { -147 | | a = false; +154 | / 'outer: while a { // never loops +155 | | while a { +156 | | if a { +157 | | a = false; ... | -151 | | break 'outer; -152 | | } +161 | | break 'outer; +162 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:158:9 + --> $DIR/never_loop.rs:168:9 | -158 | / while false { -159 | | break 'label; -160 | | } +168 | / while false { +169 | | break 'label; +170 | | } | |_________^ error: aborting due to 9 previous errors diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index bf63e9336e5..46d2bc45f68 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(const_fn)] diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 11ece5e8708..5343428636c 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,39 +1,39 @@ error: you should consider deriving a `Default` implementation for `Foo` - --> $DIR/new_without_default.rs:12:5 + --> $DIR/new_without_default.rs:22:5 | -12 | pub fn new() -> Foo { Foo } +22 | pub fn new() -> Foo { Foo } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::new-without-default-derive` implied by `-D warnings` help: try this | -9 | #[derive(Default)] +19 | #[derive(Default)] | error: you should consider deriving a `Default` implementation for `Bar` - --> $DIR/new_without_default.rs:18:5 + --> $DIR/new_without_default.rs:28:5 | -18 | pub fn new() -> Self { Bar } +28 | pub fn new() -> Self { Bar } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this | -15 | #[derive(Default)] +25 | #[derive(Default)] | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> $DIR/new_without_default.rs:66:5 + --> $DIR/new_without_default.rs:76:5 | -66 | pub fn new() -> LtKo<'c> { unimplemented!() } +76 | pub fn new() -> LtKo<'c> { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | -65 | impl Default for LtKo<'c> { -66 | fn default() -> Self { -67 | Self::new() -68 | } -69 | } +75 | impl Default for LtKo<'c> { +76 | fn default() -> Self { +77 | Self::new() +78 | } +79 | } | error: aborting due to 3 previous errors diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 2913ecdbf59..a56327eeefa 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(box_syntax)] diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 2429d934ca1..eca47d7546e 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,275 +1,275 @@ error: statement with no effect - --> $DIR/no_effect.rs:61:5 + --> $DIR/no_effect.rs:71:5 | -61 | 0; +71 | 0; | ^^ | = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:62:5 + --> $DIR/no_effect.rs:72:5 | -62 | s2; +72 | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:63:5 + --> $DIR/no_effect.rs:73:5 | -63 | Unit; +73 | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:64:5 + --> $DIR/no_effect.rs:74:5 | -64 | Tuple(0); +74 | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:65:5 + --> $DIR/no_effect.rs:75:5 | -65 | Struct { field: 0 }; +75 | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:66:5 + --> $DIR/no_effect.rs:76:5 | -66 | Struct { ..s }; +76 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:67:5 + --> $DIR/no_effect.rs:77:5 | -67 | Union { a: 0 }; +77 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:68:5 + --> $DIR/no_effect.rs:78:5 | -68 | Enum::Tuple(0); +78 | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:69:5 + --> $DIR/no_effect.rs:79:5 | -69 | Enum::Struct { field: 0 }; +79 | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:70:5 + --> $DIR/no_effect.rs:80:5 | -70 | 5 + 6; +80 | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:81:5 | -71 | *&42; +81 | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:82:5 | -72 | &6; +82 | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:73:5 + --> $DIR/no_effect.rs:83:5 | -73 | (5, 6, 7); +83 | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:84:5 | -74 | box 42; +84 | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:85:5 | -75 | ..; +85 | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:86:5 | -76 | 5..; +86 | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:87:5 | -77 | ..5; +87 | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:88:5 | -78 | 5..6; +88 | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:90:5 | -80 | [42, 55]; +90 | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:91:5 | -81 | [42, 55][1]; +91 | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:92:5 | -82 | (42, 55).1; +92 | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:93:5 | -83 | [42; 55]; +93 | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:94:5 | -84 | [42; 55][13]; +94 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:96:5 | -86 | || x += 5; +96 | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:98:5 | -88 | FooString { s: s }; +98 | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: statement can be reduced - --> $DIR/no_effect.rs:99:5 - | -99 | Tuple(get_number()); - | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - | - = note: `-D clippy::unnecessary-operation` implied by `-D warnings` + --> $DIR/no_effect.rs:109:5 + | +109 | Tuple(get_number()); + | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + | + = note: `-D clippy::unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:110:5 | -100 | Struct { field: get_number() }; +110 | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:111:5 | -101 | Struct { ..get_struct() }; +111 | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:112:5 | -102 | Enum::Tuple(get_number()); +112 | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:113:5 | -103 | Enum::Struct { field: get_number() }; +113 | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:114:5 | -104 | 5 + get_number(); +114 | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:115:5 | -105 | *&get_number(); +115 | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:116:5 | -106 | &get_number(); +116 | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:117:5 | -107 | (5, 6, get_number()); +117 | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:118:5 | -108 | box get_number(); +118 | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:119:5 | -109 | get_number()..; +119 | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:120:5 | -110 | ..get_number(); +120 | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:121:5 | -111 | 5..get_number(); +121 | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:122:5 | -112 | [42, get_number()]; +122 | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:123:5 | -113 | [42, 55][get_number() as usize]; +123 | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:124:5 | -114 | (42, get_number()).1; +124 | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:125:5 | -115 | [get_number(); 55]; +125 | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:126:5 | -116 | [42; 55][get_number() as usize]; +126 | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/no_effect.rs:117:5 + --> $DIR/no_effect.rs:127:5 | -117 | {get_number()}; +127 | {get_number()}; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/no_effect.rs:118:5 + --> $DIR/no_effect.rs:128:5 | -118 | FooString { s: String::from("blah"), }; +128 | FooString { s: String::from("blah"), }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` error: aborting due to 45 previous errors diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index 4e086333b0c..6c57a37e2ab 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(const_string_new, const_vec_new)] diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 7f164595b59..744b5474844 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -1,7 +1,7 @@ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:12:1 + --> $DIR/non_copy_const.rs:22:1 | -12 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +22 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` @@ -9,264 +9,264 @@ error: a const item should never be interior mutable = note: #[deny(clippy::declare_interior_mutable_const)] on by default error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:13:1 + --> $DIR/non_copy_const.rs:23:1 | -13 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +23 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:14:1 + --> $DIR/non_copy_const.rs:24:1 | -14 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +24 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:18:42 + --> $DIR/non_copy_const.rs:28:42 | -18 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; +28 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; | ^^^^^^^^^^^^^^^^^^^^^^ -19 | } -20 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +29 | } +30 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:41:5 + --> $DIR/non_copy_const.rs:51:5 | -41 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +51 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:45:5 + --> $DIR/non_copy_const.rs:55:5 | -45 | const INPUT: T; +55 | const INPUT: T; | ^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:45:18 + --> $DIR/non_copy_const.rs:55:18 | -45 | const INPUT: T; +55 | const INPUT: T; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:48:5 + --> $DIR/non_copy_const.rs:58:5 | -48 | const ASSOC: Self::NonCopyType; +58 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:48:18 + --> $DIR/non_copy_const.rs:58:18 | -48 | const ASSOC: Self::NonCopyType; +58 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:52:5 + --> $DIR/non_copy_const.rs:62:5 | -52 | const AN_INPUT: T = Self::INPUT; +62 | const AN_INPUT: T = Self::INPUT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:52:21 + --> $DIR/non_copy_const.rs:62:21 | -52 | const AN_INPUT: T = Self::INPUT; +62 | const AN_INPUT: T = Self::INPUT; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:18:42 + --> $DIR/non_copy_const.rs:28:42 | -18 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; +28 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; | ^^^^^^^^^^^^^^^^^^^^^^ ... -55 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable +65 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable | ----------------------------------------------- in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:61:5 + --> $DIR/non_copy_const.rs:71:5 | -61 | const SELF_2: Self; +71 | const SELF_2: Self; | ^^^^^^^^^^^^^^^^^^^ | help: consider requiring `Self` to be `Copy` - --> $DIR/non_copy_const.rs:61:19 + --> $DIR/non_copy_const.rs:71:19 | -61 | const SELF_2: Self; +71 | const SELF_2: Self; | ^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:82:5 + --> $DIR/non_copy_const.rs:92:5 | -82 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable +92 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:85:5 + --> $DIR/non_copy_const.rs:95:5 | -85 | const U_SELF: U = U::SELF_2; +95 | const U_SELF: U = U::SELF_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `U` to be `Copy` - --> $DIR/non_copy_const.rs:85:19 + --> $DIR/non_copy_const.rs:95:19 | -85 | const U_SELF: U = U::SELF_2; +95 | const U_SELF: U = U::SELF_2; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:88:5 + --> $DIR/non_copy_const.rs:98:5 | -88 | const T_ASSOC: T::NonCopyType = T::ASSOC; +98 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:88:20 + --> $DIR/non_copy_const.rs:98:20 | -88 | const T_ASSOC: T::NonCopyType = T::ASSOC; +98 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^ error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:95:5 - | -95 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^ - | - = note: #[deny(clippy::borrow_interior_mutable_const)] on by default - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:105:5 + | +105 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^ + | + = note: #[deny(clippy::borrow_interior_mutable_const)] on by default + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:96:16 - | -96 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability - | ^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:106:16 + | +106 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + | ^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:98:5 - | -98 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:108:5 + | +108 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:99:16 - | -99 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:109:16 + | +109 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:102:22 + --> $DIR/non_copy_const.rs:112:22 | -102 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability +112 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:103:25 + --> $DIR/non_copy_const.rs:113:25 | -103 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability +113 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:104:27 + --> $DIR/non_copy_const.rs:114:27 | -104 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability +114 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:105:26 + --> $DIR/non_copy_const.rs:115:26 | -105 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability +115 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:116:14 + --> $DIR/non_copy_const.rs:126:14 | -116 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability +126 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:117:14 + --> $DIR/non_copy_const.rs:127:14 | -117 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability +127 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:118:19 + --> $DIR/non_copy_const.rs:128:19 | -118 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability +128 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:119:14 + --> $DIR/non_copy_const.rs:129:14 | -119 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +129 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:120:13 + --> $DIR/non_copy_const.rs:130:13 | -120 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability +130 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:126:13 + --> $DIR/non_copy_const.rs:136:13 | -126 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +136 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:131:5 + --> $DIR/non_copy_const.rs:141:5 | -131 | CELL.set(2); //~ ERROR interior mutability +141 | CELL.set(2); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:132:16 + --> $DIR/non_copy_const.rs:142:16 | -132 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability +142 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:145:5 + --> $DIR/non_copy_const.rs:155:5 | -145 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability +155 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:146:16 + --> $DIR/non_copy_const.rs:156:16 | -146 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability +156 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index e8b0021e301..47e4da61b51 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all,clippy::similar_names)] diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 53cb36edacb..1369cd8a4ad 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,170 +1,170 @@ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:18:9 + --> $DIR/non_expressive_names.rs:28:9 | -18 | let bpple: i32; +28 | let bpple: i32; | ^^^^^ | = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here - --> $DIR/non_expressive_names.rs:16:9 + --> $DIR/non_expressive_names.rs:26:9 | -16 | let apple: i32; +26 | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `b_pple` - --> $DIR/non_expressive_names.rs:18:9 + --> $DIR/non_expressive_names.rs:28:9 | -18 | let bpple: i32; +28 | let bpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:20:9 + --> $DIR/non_expressive_names.rs:30:9 | -20 | let cpple: i32; +30 | let cpple: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:16:9 + --> $DIR/non_expressive_names.rs:26:9 | -16 | let apple: i32; +26 | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `c_pple` - --> $DIR/non_expressive_names.rs:20:9 + --> $DIR/non_expressive_names.rs:30:9 | -20 | let cpple: i32; +30 | let cpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:45:9 + --> $DIR/non_expressive_names.rs:55:9 | -45 | let bluby: i32; +55 | let bluby: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:44:9 + --> $DIR/non_expressive_names.rs:54:9 | -44 | let blubx: i32; +54 | let blubx: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `blub_y` - --> $DIR/non_expressive_names.rs:45:9 + --> $DIR/non_expressive_names.rs:55:9 | -45 | let bluby: i32; +55 | let bluby: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:50:9 + --> $DIR/non_expressive_names.rs:60:9 | -50 | let coke: i32; +60 | let coke: i32; | ^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:48:9 + --> $DIR/non_expressive_names.rs:58:9 | -48 | let cake: i32; +58 | let cake: i32; | ^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:68:9 + --> $DIR/non_expressive_names.rs:78:9 | -68 | let xyzeabc: i32; +78 | let xyzeabc: i32; | ^^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:66:9 + --> $DIR/non_expressive_names.rs:76:9 | -66 | let xyz1abc: i32; +76 | let xyz1abc: i32; | ^^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:72:9 + --> $DIR/non_expressive_names.rs:82:9 | -72 | let parsee: i32; +82 | let parsee: i32; | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:70:9 + --> $DIR/non_expressive_names.rs:80:9 | -70 | let parser: i32; +80 | let parser: i32; | ^^^^^^ help: separate the discriminating character by an underscore like: `parse_e` - --> $DIR/non_expressive_names.rs:72:9 + --> $DIR/non_expressive_names.rs:82:9 | -72 | let parsee: i32; +82 | let parsee: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:86:16 + --> $DIR/non_expressive_names.rs:96:16 | -86 | bpple: sprang } = unimplemented!(); +96 | bpple: sprang } = unimplemented!(); | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:85:22 + --> $DIR/non_expressive_names.rs:95:22 | -85 | let Foo { apple: spring, +95 | let Foo { apple: spring, | ^^^^^^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:120:17 + --> $DIR/non_expressive_names.rs:130:17 | -120 | let e: i32; +130 | let e: i32; | ^ | = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:123:17 + --> $DIR/non_expressive_names.rs:133:17 | -123 | let e: i32; +133 | let e: i32; | ^ error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:124:17 + --> $DIR/non_expressive_names.rs:134:17 | -124 | let f: i32; +134 | let f: i32; | ^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:129:13 + --> $DIR/non_expressive_names.rs:139:13 | -129 | e => panic!(), +139 | e => panic!(), | ^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:139:9 + --> $DIR/non_expressive_names.rs:149:9 | -139 | let _1 = 1; //~ERROR Consider a more descriptive name +149 | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ | = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:140:9 + --> $DIR/non_expressive_names.rs:150:9 | -140 | let ____1 = 1; //~ERROR Consider a more descriptive name +150 | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:141:9 + --> $DIR/non_expressive_names.rs:151:9 | -141 | let __1___2 = 12; //~ERROR Consider a more descriptive name +151 | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:161:13 + --> $DIR/non_expressive_names.rs:171:13 | -161 | let _1 = 1; +171 | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:162:13 + --> $DIR/non_expressive_names.rs:172:13 | -162 | let ____1 = 1; +172 | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:163:13 + --> $DIR/non_expressive_names.rs:173:13 | -163 | let __1___2 = 12; +173 | let __1___2 = 12; | ^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index 4341e8ea70b..5d333a72cc0 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use std::io; struct MyError(()); // doesn't implement Debug diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 7c158b5207b..f4c8440a774 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,33 +1,33 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:14:5 + --> $DIR/ok_expect.rs:24:5 | -14 | res.ok().expect("disaster!"); +24 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:20:5 + --> $DIR/ok_expect.rs:30:5 | -20 | res3.ok().expect("whoof"); +30 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:22:5 + --> $DIR/ok_expect.rs:32:5 | -22 | res4.ok().expect("argh"); +32 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:24:5 + --> $DIR/ok_expect.rs:34:5 | -24 | res5.ok().expect("oops"); +34 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:26:5 + --> $DIR/ok_expect.rs:36:5 | -26 | res6.ok().expect("meh"); +36 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index 46d85bb9cd0..71b301cbc42 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index eac49032ed8..27b3ef28ff3 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -1,11 +1,11 @@ error: Matching on `Some` with `ok()` is redundant - --> $DIR/ok_if_let.rs:7:5 + --> $DIR/ok_if_let.rs:17:5 | -7 | / if let Some(y) = x.parse().ok() { -8 | | y -9 | | } else { -10 | | 0 -11 | | } +17 | / if let Some(y) = x.parse().ok() { +18 | | y +19 | | } else { +20 | | 0 +21 | | } | |_____^ | = note: `-D clippy::if-let-some-result` implied by `-D warnings` diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index a85a2c8bb51..96a208ef807 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 398e3a6e9e6..e2b7b7820f3 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -1,19 +1,19 @@ error: needlessly taken reference of both operands - --> $DIR/op_ref.rs:13:15 + --> $DIR/op_ref.rs:23:15 | -13 | let foo = &5 - &6; +23 | let foo = &5 - &6; | ^^^^^^^ | = note: `-D clippy::op-ref` implied by `-D warnings` help: use the values directly | -13 | let foo = 5 - 6; +23 | let foo = 5 - 6; | ^ ^ error: taken reference of right operand - --> $DIR/op_ref.rs:21:8 + --> $DIR/op_ref.rs:31:8 | -21 | if b < &a { +31 | if b < &a { | ^^^^-- | | | help: use the right value directly: `a` diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 38b3dd7e49d..a01f2b1ce39 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::fs::OpenOptions; diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 64ad667a4c7..2835eebfbb3 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,45 +1,45 @@ error: file opened with "truncate" and "read" - --> $DIR/open_options.rs:8:5 - | -8 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` + --> $DIR/open_options.rs:18:5 + | +18 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` error: file opened with "append" and "truncate" - --> $DIR/open_options.rs:9:5 - | -9 | OpenOptions::new().append(true).truncate(true).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/open_options.rs:19:5 + | +19 | OpenOptions::new().append(true).truncate(true).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "read" is called more than once - --> $DIR/open_options.rs:11:5 + --> $DIR/open_options.rs:21:5 | -11 | OpenOptions::new().read(true).read(false).open("foo.txt"); +21 | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "create" is called more than once - --> $DIR/open_options.rs:12:5 + --> $DIR/open_options.rs:22:5 | -12 | OpenOptions::new().create(true).create(false).open("foo.txt"); +22 | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "write" is called more than once - --> $DIR/open_options.rs:13:5 + --> $DIR/open_options.rs:23:5 | -13 | OpenOptions::new().write(true).write(false).open("foo.txt"); +23 | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "append" is called more than once - --> $DIR/open_options.rs:14:5 + --> $DIR/open_options.rs:24:5 | -14 | OpenOptions::new().append(true).append(false).open("foo.txt"); +24 | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "truncate" is called more than once - --> $DIR/open_options.rs:15:5 + --> $DIR/open_options.rs:25:5 | -15 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); +25 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index e86cc99c522..a69c41ce967 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::option_map_unit_fn)] diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 77fe24d2696..7a2dfd338a3 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:34:5 + --> $DIR/option_map_unit_fn.rs:44:5 | -34 | x.field.map(do_nothing); +44 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` @@ -9,202 +9,202 @@ error: called `map(f)` on an Option value where `f` is a unit function = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:36:5 + --> $DIR/option_map_unit_fn.rs:46:5 | -36 | x.field.map(do_nothing); +46 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:38:5 + --> $DIR/option_map_unit_fn.rs:48:5 | -38 | x.field.map(diverge); +48 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:44:5 + --> $DIR/option_map_unit_fn.rs:54:5 | -44 | x.field.map(|value| x.do_option_nothing(value + captured)); +54 | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:46:5 + --> $DIR/option_map_unit_fn.rs:56:5 | -46 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); +56 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:49:5 + --> $DIR/option_map_unit_fn.rs:59:5 | -49 | x.field.map(|value| do_nothing(value + captured)); +59 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:51:5 + --> $DIR/option_map_unit_fn.rs:61:5 | -51 | x.field.map(|value| { do_nothing(value + captured) }); +61 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:53:5 + --> $DIR/option_map_unit_fn.rs:63:5 | -53 | x.field.map(|value| { do_nothing(value + captured); }); +63 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:55:5 + --> $DIR/option_map_unit_fn.rs:65:5 | -55 | x.field.map(|value| { { do_nothing(value + captured); } }); +65 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:58:5 + --> $DIR/option_map_unit_fn.rs:68:5 | -58 | x.field.map(|value| diverge(value + captured)); +68 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:60:5 + --> $DIR/option_map_unit_fn.rs:70:5 | -60 | x.field.map(|value| { diverge(value + captured) }); +70 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:62:5 + --> $DIR/option_map_unit_fn.rs:72:5 | -62 | x.field.map(|value| { diverge(value + captured); }); +72 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:64:5 + --> $DIR/option_map_unit_fn.rs:74:5 | -64 | x.field.map(|value| { { diverge(value + captured); } }); +74 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:69:5 + --> $DIR/option_map_unit_fn.rs:79:5 | -69 | x.field.map(|value| { let y = plus_one(value + captured); }); +79 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:71:5 + --> $DIR/option_map_unit_fn.rs:81:5 | -71 | x.field.map(|value| { plus_one(value + captured); }); +81 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:73:5 + --> $DIR/option_map_unit_fn.rs:83:5 | -73 | x.field.map(|value| { { plus_one(value + captured); } }); +83 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:76:5 + --> $DIR/option_map_unit_fn.rs:86:5 | -76 | x.field.map(|ref value| { do_nothing(value + captured) }); +86 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:79:5 + --> $DIR/option_map_unit_fn.rs:89:5 | -79 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +89 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:81:5 + --> $DIR/option_map_unit_fn.rs:91:5 | -81 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +91 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:85:5 + --> $DIR/option_map_unit_fn.rs:95:5 | -85 | x.field.map(|value| { +95 | x.field.map(|value| { | _____^ | |_____| | || -86 | || do_nothing(value); -87 | || do_nothing(value) -88 | || }); +96 | || do_nothing(value); +97 | || do_nothing(value) +98 | || }); | ||______^- help: try this: `if let Some(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:89:5 + --> $DIR/option_map_unit_fn.rs:99:5 | -89 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +99 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:92:5 - | -92 | Some(42).map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(42) { diverge(...) }` + --> $DIR/option_map_unit_fn.rs:102:5 + | +102 | Some(42).map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:93:5 - | -93 | "12".parse::().ok().map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` + --> $DIR/option_map_unit_fn.rs:103:5 + | +103 | "12".parse::().ok().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:94:5 - | -94 | Some(plus_one(1)).map(do_nothing); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` + --> $DIR/option_map_unit_fn.rs:104:5 + | +104 | Some(plus_one(1)).map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:98:5 - | -98 | y.map(do_nothing); - | ^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_y) = y { do_nothing(...) }` + --> $DIR/option_map_unit_fn.rs:108:5 + | +108 | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_y) = y { do_nothing(...) }` error: aborting due to 25 previous errors diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 249745c6a45..3cb4fdc27eb 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn input(_: Option>) { } diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 4341857cce0..8a867fd4fe2 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,57 +1,57 @@ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:1:13 - | -1 | fn input(_: Option>) { - | ^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::option-option` implied by `-D warnings` + --> $DIR/option_option.rs:11:13 + | +11 | fn input(_: Option>) { + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::option-option` implied by `-D warnings` error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:4:16 - | -4 | fn output() -> Option> { - | ^^^^^^^^^^^^^^^^^^ + --> $DIR/option_option.rs:14:16 + | +14 | fn output() -> Option> { + | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:8:27 - | -8 | fn output_nested() -> Vec>> { - | ^^^^^^^^^^^^^^^^^^ + --> $DIR/option_option.rs:18:27 + | +18 | fn output_nested() -> Vec>> { + | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:13:30 + --> $DIR/option_option.rs:23:30 | -13 | fn output_nested_nested() -> Option>> { +23 | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:18:8 + --> $DIR/option_option.rs:28:8 | -18 | x: Option>, +28 | x: Option>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:22:23 + --> $DIR/option_option.rs:32:23 | -22 | fn struct_fn() -> Option> { +32 | fn struct_fn() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:28:22 + --> $DIR/option_option.rs:38:22 | -28 | fn trait_fn() -> Option>; +38 | fn trait_fn() -> Option>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:32:11 + --> $DIR/option_option.rs:42:11 | -32 | Tuple(Option>), +42 | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:33:15 + --> $DIR/option_option.rs:43:15 | -33 | Struct{x: Option>}, +43 | Struct{x: Option>}, | ^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index 5c3cc5b08a9..8aba051c65e 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 9659e352af1..0bd20210f01 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,51 +1,51 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:11:5 + --> $DIR/overflow_check_conditional.rs:21:5 | -11 | if a + b < a { +21 | if a + b < a { | ^^^^^^^^^ | = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:14:5 + --> $DIR/overflow_check_conditional.rs:24:5 | -14 | if a > a + b { +24 | if a > a + b { | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:17:5 + --> $DIR/overflow_check_conditional.rs:27:5 | -17 | if a + b < b { +27 | if a + b < b { | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:20:5 + --> $DIR/overflow_check_conditional.rs:30:5 | -20 | if b > a + b { +30 | if b > a + b { | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:23:5 + --> $DIR/overflow_check_conditional.rs:33:5 | -23 | if a - b > b { +33 | if a - b > b { | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:26:5 + --> $DIR/overflow_check_conditional.rs:36:5 | -26 | if b < a - b { +36 | if b < a - b { | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:29:5 + --> $DIR/overflow_check_conditional.rs:39:5 | -29 | if a - b > a { +39 | if a - b > a { | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:32:5 + --> $DIR/overflow_check_conditional.rs:42:5 | -32 | if a < a - b { +42 | if a < a - b { | ^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 693dc921be3..f292455dc7d 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index c5ce42f4c54..75032c1170e 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -1,33 +1,33 @@ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:8:16 - | -8 | panic!("{}"); - | ^^^^ - | - = note: `-D clippy::panic-params` implied by `-D warnings` + --> $DIR/panic_unimplemented.rs:18:16 + | +18 | panic!("{}"); + | ^^^^ + | + = note: `-D clippy::panic-params` implied by `-D warnings` error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:10:16 + --> $DIR/panic_unimplemented.rs:20:16 | -10 | panic!("{:?}"); +20 | panic!("{:?}"); | ^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:12:23 + --> $DIR/panic_unimplemented.rs:22:23 | -12 | assert!(true, "here be missing values: {}"); +22 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:15:12 + --> $DIR/panic_unimplemented.rs:25:12 | -15 | panic!("{{{this}}}"); +25 | panic!("{{{this}}}"); | ^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panic_unimplemented.rs:58:5 + --> $DIR/panic_unimplemented.rs:68:5 | -58 | unimplemented!(); +68 | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unimplemented` implied by `-D warnings` diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index 36dd4df8a6e..45aa0decd58 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index 773bed8fd8e..0ed2d0789cb 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -1,7 +1,7 @@ error: re-implementing `PartialEq::ne` is unnecessary - --> $DIR/partialeq_ne_impl.rs:10:5 + --> $DIR/partialeq_ne_impl.rs:20:5 | -10 | fn ne(&self, _: &Foo) -> bool { false } +20 | fn ne(&self, _: &Foo) -> bool { false } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 70f86afbacb..2b42aae63ea 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused)] diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index ce8aab7e627..d236da24022 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,7 +1,7 @@ error: the `y @ _` pattern can be written as just `y` - --> $DIR/patterns.rs:10:9 + --> $DIR/patterns.rs:20:9 | -10 | y @ _ => (), +20 | y @ _ => (), | ^^^^^ | = note: `-D clippy::redundant-pattern` implied by `-D warnings` diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 95476dd4f51..ccc08ddc5d7 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 5ec1732ee56..3d5553ed0c3 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,57 +1,57 @@ error: operator precedence can trip the unwary - --> $DIR/precedence.rs:18:5 + --> $DIR/precedence.rs:28:5 | -18 | 1 << 2 + 3; +28 | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` | = note: `-D clippy::precedence` implied by `-D warnings` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:19:5 + --> $DIR/precedence.rs:29:5 | -19 | 1 + 2 << 3; +29 | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:20:5 + --> $DIR/precedence.rs:30:5 | -20 | 4 >> 1 + 1; +30 | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:21:5 + --> $DIR/precedence.rs:31:5 | -21 | 1 + 3 >> 2; +31 | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:22:5 + --> $DIR/precedence.rs:32:5 | -22 | 1 ^ 1 - 1; +32 | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:23:5 + --> $DIR/precedence.rs:33:5 | -23 | 3 | 2 - 1; +33 | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:24:5 + --> $DIR/precedence.rs:34:5 | -24 | 3 & 5 - 2; +34 | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:25:5 + --> $DIR/precedence.rs:35:5 | -25 | -1i32.abs(); +35 | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:26:5 + --> $DIR/precedence.rs:36:5 | -26 | -1f32.abs(); +36 | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` error: aborting due to 9 previous errors diff --git a/tests/ui/print.rs b/tests/ui/print.rs index cee3e700036..3bb72fcb1f4 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::print_literal, clippy::write_literal)] diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 92a2f2f9627..605e527c208 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,59 +1,59 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:13:19 + --> $DIR/print.rs:23:19 | -13 | write!(f, "{:?}", 43.1415) +23 | write!(f, "{:?}", 43.1415) | ^^^^^^ | = note: `-D clippy::use-debug` implied by `-D warnings` error: use of `Debug`-based formatting - --> $DIR/print.rs:20:19 + --> $DIR/print.rs:30:19 | -20 | write!(f, "{:?}", 42.718) +30 | write!(f, "{:?}", 42.718) | ^^^^^^ error: use of `println!` - --> $DIR/print.rs:25:5 + --> $DIR/print.rs:35:5 | -25 | println!("Hello"); +35 | println!("Hello"); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::print-stdout` implied by `-D warnings` error: use of `print!` - --> $DIR/print.rs:26:5 + --> $DIR/print.rs:36:5 | -26 | print!("Hello"); +36 | print!("Hello"); | ^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:28:5 + --> $DIR/print.rs:38:5 | -28 | print!("Hello {}", "World"); +38 | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:30:5 + --> $DIR/print.rs:40:5 | -30 | print!("Hello {:?}", "World"); +40 | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:30:12 + --> $DIR/print.rs:40:12 | -30 | print!("Hello {:?}", "World"); +40 | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:32:5 + --> $DIR/print.rs:42:5 | -32 | print!("Hello {:#?}", "#orld"); +42 | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:32:12 + --> $DIR/print.rs:42:12 | -32 | print!("Hello {:#?}", "#orld"); +42 | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 46b91d40f8c..fd68751820d 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::print_literal)] diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index bd13f5d1730..9fe7fe34e6e 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,87 +1,87 @@ error: literal with an empty format string - --> $DIR/print_literal.rs:24:71 + --> $DIR/print_literal.rs:34:71 | -24 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); +34 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::print-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/print_literal.rs:25:24 + --> $DIR/print_literal.rs:35:24 | -25 | print!("Hello {}", "world"); +35 | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:26:36 + --> $DIR/print_literal.rs:36:36 | -26 | println!("Hello {} {}", world, "world"); +36 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:27:26 + --> $DIR/print_literal.rs:37:26 | -27 | println!("Hello {}", "world"); +37 | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:28:30 + --> $DIR/print_literal.rs:38:30 | -28 | println!("10 / 4 is {}", 2.5); +38 | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:29:28 + --> $DIR/print_literal.rs:39:28 | -29 | println!("2 + 1 = {}", 3); +39 | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/print_literal.rs:34:25 + --> $DIR/print_literal.rs:44:25 | -34 | println!("{0} {1}", "hello", "world"); +44 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:34:34 + --> $DIR/print_literal.rs:44:34 | -34 | println!("{0} {1}", "hello", "world"); +44 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:35:25 + --> $DIR/print_literal.rs:45:25 | -35 | println!("{1} {0}", "hello", "world"); +45 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:35:34 + --> $DIR/print_literal.rs:45:34 | -35 | println!("{1} {0}", "hello", "world"); +45 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:38:33 + --> $DIR/print_literal.rs:48:33 | -38 | println!("{foo} {bar}", foo="hello", bar="world"); +48 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:38:46 + --> $DIR/print_literal.rs:48:46 | -38 | println!("{foo} {bar}", foo="hello", bar="world"); +48 | println!("{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:39:33 + --> $DIR/print_literal.rs:49:33 | -39 | println!("{bar} {foo}", foo="hello", bar="world"); +49 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:39:46 + --> $DIR/print_literal.rs:49:46 | -39 | println!("{bar} {foo}", foo="hello", bar="world"); +49 | println!("{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index c2c79c726e8..4fc24080d46 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::print_literal)] diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 12c4ecb2f3e..4cd7a6685d4 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,27 +1,27 @@ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:7:5 - | -7 | print!("Hello/n"); - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::print-with-newline` implied by `-D warnings` + --> $DIR/print_with_newline.rs:17:5 + | +17 | print!("Hello/n"); + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::print-with-newline` implied by `-D warnings` error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:8:5 - | -8 | print!("Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/print_with_newline.rs:18:5 + | +18 | print!("Hello {}/n", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:9:5 - | -9 | print!("Hello {} {}/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/print_with_newline.rs:19:5 + | +19 | print!("Hello {} {}/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:10:5 + --> $DIR/print_with_newline.rs:20:5 | -10 | print!("{}/n", 1265); +20 | print!("{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 9df348050ad..afc37b1bec7 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { println!(); println!(""); diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 96d15838400..e06b403cfec 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,16 +1,16 @@ error: using `println!("")` - --> $DIR/println_empty_string.rs:3:5 - | -3 | println!(""); - | ^^^^^^^^^^^^ help: replace it with: `println!()` - | - = note: `-D clippy::println-empty-string` implied by `-D warnings` + --> $DIR/println_empty_string.rs:13:5 + | +13 | println!(""); + | ^^^^^^^^^^^^ help: replace it with: `println!()` + | + = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` - --> $DIR/println_empty_string.rs:6:14 - | -6 | _ => println!(""), - | ^^^^^^^^^^^^ help: replace it with: `println!()` + --> $DIR/println_empty_string.rs:16:14 + | +16 | _ => println!(""), + | ^^^^^^^^^^^^ help: replace it with: `println!()` error: aborting due to 2 previous errors diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 7cd3c9f9c72..4d5f353bb6a 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused, clippy::many_single_char_names)] diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 6c16443f524..e7aecf7c20b 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,85 +1,85 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:8:14 - | -8 | fn do_vec(x: &Vec) { - | ^^^^^^^^^ help: change this to: `&[i64]` - | - = note: `-D clippy::ptr-arg` implied by `-D warnings` + --> $DIR/ptr_arg.rs:18:14 + | +18 | fn do_vec(x: &Vec) { + | ^^^^^^^^^ help: change this to: `&[i64]` + | + = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:16:14 + --> $DIR/ptr_arg.rs:26:14 | -16 | fn do_str(x: &String) { +26 | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:29:18 + --> $DIR/ptr_arg.rs:39:18 | -29 | fn do_vec(x: &Vec); +39 | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:42:14 + --> $DIR/ptr_arg.rs:52:14 | -42 | fn cloned(x: &Vec) -> Vec { +52 | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ help: change this to | -42 | fn cloned(x: &[u8]) -> Vec { +52 | fn cloned(x: &[u8]) -> Vec { | ^^^^^ help: change `x.clone()` to | -43 | let e = x.to_owned(); +53 | let e = x.to_owned(); | ^^^^^^^^^^^^ help: change `x.clone()` to | -48 | x.to_owned() +58 | x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:51:18 + --> $DIR/ptr_arg.rs:61:18 | -51 | fn str_cloned(x: &String) -> String { +61 | fn str_cloned(x: &String) -> String { | ^^^^^^^ help: change this to | -51 | fn str_cloned(x: &str) -> String { +61 | fn str_cloned(x: &str) -> String { | ^^^^ help: change `x.clone()` to | -52 | let a = x.to_string(); +62 | let a = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -53 | let b = x.to_string(); +63 | let b = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -58 | x.to_string() +68 | x.to_string() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:61:44 + --> $DIR/ptr_arg.rs:71:44 | -61 | fn false_positive_capacity(x: &Vec, y: &String) { +71 | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ help: change this to | -61 | fn false_positive_capacity(x: &Vec, y: &str) { +71 | fn false_positive_capacity(x: &Vec, y: &str) { | ^^^^ help: change `y.clone()` to | -63 | let b = y.to_string(); +73 | let b = y.to_string(); | ^^^^^^^^^^^^^ help: change `y.as_str()` to | -64 | let c = y; +74 | let c = y; | ^ error: using a reference to `Cow` is not recommended. - --> $DIR/ptr_arg.rs:73:25 + --> $DIR/ptr_arg.rs:83:25 | -73 | fn test_cow_with_ref(c: &Cow<[i32]>) { +83 | fn test_cow_with_ref(c: &Cow<[i32]>) { | ^^^^^^^^^^^ help: change this to: `&[i32]` error: aborting due to 7 previous errors diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 4549f960ca0..a6f86a230f3 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { let vec = vec![b'a', b'b', b'c']; let ptr = vec.as_ptr(); diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index 214a39cdc11..b3df0abbaa8 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,15 +1,15 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:10:9 + --> $DIR/ptr_offset_with_cast.rs:20:9 | -10 | ptr.offset(offset_usize as isize); +20 | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` | = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:14:9 + --> $DIR/ptr_offset_with_cast.rs:24:9 | -14 | ptr.wrapping_offset(offset_usize as isize); +24 | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` error: aborting due to 2 previous errors diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 369b868a50d..a39ea00cb8b 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn some_func(a: Option) -> Option { if a.is_none() { return None diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 68c0e5e381a..7ca76e38192 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,21 +1,21 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:2:2 - | -2 | if a.is_none() { - | _____^ -3 | | return None -4 | | } - | |_____^ help: replace_it_with: `a?;` - | - = note: `-D clippy::question-mark` implied by `-D warnings` + --> $DIR/question_mark.rs:12:2 + | +12 | if a.is_none() { + | _____^ +13 | | return None +14 | | } + | |_____^ help: replace_it_with: `a?;` + | + = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:37:3 + --> $DIR/question_mark.rs:47:3 | -37 | if (self.opt).is_none() { +47 | if (self.opt).is_none() { | _________^ -38 | | return None; -39 | | } +48 | | return None; +49 | | } | |_________^ help: replace_it_with: `(self.opt)?;` error: aborting due to 2 previous errors diff --git a/tests/ui/range.rs b/tests/ui/range.rs index df3ce12689b..270b71d263f 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] struct NotARange; diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 651ff266c1a..2dc81b4f042 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,41 +1,41 @@ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:10:13 + --> $DIR/range.rs:20:13 | -10 | let _ = (0..1).step_by(0); +20 | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:14:13 + --> $DIR/range.rs:24:13 | -14 | let _ = (1..).step_by(0); +24 | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:15:13 + --> $DIR/range.rs:25:13 | -15 | let _ = (1..=2).step_by(0); +25 | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:18:13 + --> $DIR/range.rs:28:13 | -18 | let _ = x.step_by(0); +28 | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: It is more idiomatic to use v1.iter().enumerate() - --> $DIR/range.rs:26:14 + --> $DIR/range.rs:36:14 | -26 | let _x = v1.iter().zip(0..v1.len()); +36 | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::range-zip-with-len` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:30:13 + --> $DIR/range.rs:40:13 | -30 | let _ = v1.iter().step_by(2/3); +40 | let _ = v1.iter().step_by(2/3); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 1ee3637f266..15743828d8b 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] fn f() -> usize { diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 3fe4e7ca073..0cac21734dc 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,53 +1,53 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:12:14 + --> $DIR/range_plus_minus_one.rs:22:14 | -12 | for _ in 0..3+1 { } +22 | for _ in 0..3+1 { } | ^^^^^^ help: use: `0..=3` | = note: `-D clippy::range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:15:14 + --> $DIR/range_plus_minus_one.rs:25:14 | -15 | for _ in 0..1+5 { } +25 | for _ in 0..1+5 { } | ^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:18:14 + --> $DIR/range_plus_minus_one.rs:28:14 | -18 | for _ in 1..1+1 { } +28 | for _ in 1..1+1 { } | ^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:24:14 + --> $DIR/range_plus_minus_one.rs:34:14 | -24 | for _ in 0..(1+f()) { } +34 | for _ in 0..(1+f()) { } | ^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:28:13 + --> $DIR/range_plus_minus_one.rs:38:13 | -28 | let _ = ..=11-1; +38 | let _ = ..=11-1; | ^^^^^^^ help: use: `..11` | = note: `-D clippy::range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:29:13 + --> $DIR/range_plus_minus_one.rs:39:13 | -29 | let _ = ..=(11-1); +39 | let _ = ..=(11-1); | ^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:30:13 + --> $DIR/range_plus_minus_one.rs:40:13 | -30 | let _ = (1..11+1); +40 | let _ = (1..11+1); | ^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:31:13 + --> $DIR/range_plus_minus_one.rs:41:13 | -31 | let _ = (f()+1)..(f()+1); +41 | let _ = (f()+1)..(f()+1); | ^^^^^^^^^^^^^^^^ help: use: `((f()+1)..=f())` error: aborting due to 8 previous errors diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index b09ed9a3574..bf0cc550b0d 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index e4d490743ad..1563de3d74f 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,33 +1,33 @@ error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:15:2 + --> $DIR/redundant_closure_call.rs:25:2 | -15 | i = closure(); +25 | i = closure(); | ^^^^^^^^^^^^^ | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:18:2 + --> $DIR/redundant_closure_call.rs:28:2 | -18 | i = closure(3); +28 | i = closure(3); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:7:10 - | -7 | let a = (|| 42)(); - | ^^^^^^^^^ help: Try doing something like: : `42` + --> $DIR/redundant_closure_call.rs:17:10 + | +17 | let a = (|| 42)(); + | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:10:14 + --> $DIR/redundant_closure_call.rs:20:14 | -10 | let mut k = (|m| m+1)(i); +20 | let mut k = (|m| m+1)(i); | ^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:12:6 + --> $DIR/redundant_closure_call.rs:22:6 | -12 | k = (|a,b| a*b)(1,5); +22 | k = (|a,b| a*b)(1,5); | ^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index b379aa661cb..ac0d5d10535 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::redundant_field_names)] diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 457fe7d3c6c..d81ddf343f1 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,45 +1,45 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:36:9 + --> $DIR/redundant_field_names.rs:46:9 | -36 | gender: gender, +46 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:37:9 + --> $DIR/redundant_field_names.rs:47:9 | -37 | age: age, +47 | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:25 + --> $DIR/redundant_field_names.rs:68:25 | -58 | let _ = RangeFrom { start: start }; +68 | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:59:23 + --> $DIR/redundant_field_names.rs:69:23 | -59 | let _ = RangeTo { end: end }; +69 | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:21 + --> $DIR/redundant_field_names.rs:70:21 | -60 | let _ = Range { start: start, end: end }; +70 | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:35 + --> $DIR/redundant_field_names.rs:70:35 | -60 | let _ = Range { start: start, end: end }; +70 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:62:32 + --> $DIR/redundant_field_names.rs:72:32 | -62 | let _ = RangeToInclusive { end: end }; +72 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 7 previous errors diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index 97a0030a99a..9298aee2cac 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 13e0da98795..4187d55cb47 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -1,69 +1,69 @@ error: immediately dereferencing a reference - --> $DIR/reference.rs:19:13 + --> $DIR/reference.rs:29:13 | -19 | let b = *&a; +29 | let b = *&a; | ^^^ help: try this: `a` | = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference - --> $DIR/reference.rs:21:13 + --> $DIR/reference.rs:31:13 | -21 | let b = *&get_number(); +31 | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try this: `get_number()` error: immediately dereferencing a reference - --> $DIR/reference.rs:26:13 + --> $DIR/reference.rs:36:13 | -26 | let b = *&bytes[1..2][0]; +36 | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` error: immediately dereferencing a reference - --> $DIR/reference.rs:30:13 + --> $DIR/reference.rs:40:13 | -30 | let b = *&(a); +40 | let b = *&(a); | ^^^^^ help: try this: `(a)` error: immediately dereferencing a reference - --> $DIR/reference.rs:32:13 + --> $DIR/reference.rs:42:13 | -32 | let b = *(&a); +42 | let b = *(&a); | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:34:13 + --> $DIR/reference.rs:44:13 | -34 | let b = *((&a)); +44 | let b = *((&a)); | ^^^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:36:13 + --> $DIR/reference.rs:46:13 | -36 | let b = *&&a; +46 | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:38:14 + --> $DIR/reference.rs:48:14 | -38 | let b = **&aref; +48 | let b = **&aref; | ^^^^^^ help: try this: `aref` error: immediately dereferencing a reference - --> $DIR/reference.rs:42:14 + --> $DIR/reference.rs:52:14 | -42 | let b = **&&a; +52 | let b = **&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:46:17 + --> $DIR/reference.rs:56:17 | -46 | let y = *&mut x; +56 | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference - --> $DIR/reference.rs:53:18 + --> $DIR/reference.rs:63:18 | -53 | let y = **&mut &mut x; +63 | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` error: aborting due to 11 previous errors diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index e3837e104f4..6e77c589023 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index fd8fecb1139..1da859dea5c 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,168 +1,168 @@ error: trivial regex - --> $DIR/regex.rs:16:45 + --> $DIR/regex.rs:26:45 | -16 | let pipe_in_wrong_position = Regex::new("|"); +26 | let pipe_in_wrong_position = Regex::new("|"); | ^^^ | = note: `-D clippy::trivial-regex` implied by `-D warnings` = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:17:60 + --> $DIR/regex.rs:27:60 | -17 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); +27 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:18:42 + --> $DIR/regex.rs:28:42 | -18 | let wrong_char_ranice = Regex::new("[z-a]"); +28 | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ | = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:19:37 + --> $DIR/regex.rs:29:37 | -19 | let some_unicode = Regex::new("[é-è]"); +29 | let some_unicode = Regex::new("[é-è]"); | ^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:21:33 + --> $DIR/regex.rs:31:33 | -21 | let some_regex = Regex::new(OPENING_PAREN); +31 | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:23:53 + --> $DIR/regex.rs:33:53 | -23 | let binary_pipe_in_wrong_position = BRegex::new("|"); +33 | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:24:41 + --> $DIR/regex.rs:34:41 | -24 | let some_binary_regex = BRegex::new(OPENING_PAREN); +34 | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:25:56 + --> $DIR/regex.rs:35:56 | -25 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); +35 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:41:9 + --> $DIR/regex.rs:51:9 | -41 | OPENING_PAREN, +51 | OPENING_PAREN, | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:45:9 + --> $DIR/regex.rs:55:9 | -45 | OPENING_PAREN, +55 | OPENING_PAREN, | ^^^^^^^^^^^^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:49:45 + --> $DIR/regex.rs:59:45 | -49 | let raw_string_error = Regex::new(r"[...//...]"); +59 | let raw_string_error = Regex::new(r"[...//...]"); | ^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:50:46 + --> $DIR/regex.rs:60:46 | -50 | let raw_string_error = Regex::new(r#"[...//...]"#); +60 | let raw_string_error = Regex::new(r#"[...//...]"#); | ^^ error: trivial regex - --> $DIR/regex.rs:54:33 + --> $DIR/regex.rs:64:33 | -54 | let trivial_eq = Regex::new("^foobar$"); +64 | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:56:48 + --> $DIR/regex.rs:66:48 | -56 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); +66 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:58:42 + --> $DIR/regex.rs:68:42 | -58 | let trivial_starts_with = Regex::new("^foobar"); +68 | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:60:40 + --> $DIR/regex.rs:70:40 | -60 | let trivial_ends_with = Regex::new("foobar$"); +70 | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:62:39 + --> $DIR/regex.rs:72:39 | -62 | let trivial_contains = Regex::new("foobar"); +72 | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:64:39 + --> $DIR/regex.rs:74:39 | -64 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); +74 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:66:40 + --> $DIR/regex.rs:76:40 | -66 | let trivial_backslash = Regex::new("a/.b"); +76 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:69:36 + --> $DIR/regex.rs:79:36 | -69 | let trivial_empty = Regex::new(""); +79 | let trivial_empty = Regex::new(""); | ^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:71:36 + --> $DIR/regex.rs:81:36 | -71 | let trivial_empty = Regex::new("^"); +81 | let trivial_empty = Regex::new("^"); | ^^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:73:36 + --> $DIR/regex.rs:83:36 | -73 | let trivial_empty = Regex::new("^$"); +83 | let trivial_empty = Regex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:75:44 + --> $DIR/regex.rs:85:44 | -75 | let binary_trivial_empty = BRegex::new("^$"); +85 | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 8420b368d3d..2f961e86f9a 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(integer_atomics)] diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index fb9c9414c85..02100b4194d 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,217 +1,217 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:14:17 + --> $DIR/replace_consts.rs:24:17 | -14 | { let foo = ATOMIC_BOOL_INIT; }; +24 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:5:9 + --> $DIR/replace_consts.rs:15:9 | -5 | #![deny(clippy::replace_consts)] +15 | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:15:17 + --> $DIR/replace_consts.rs:25:17 | -15 | { let foo = ATOMIC_ISIZE_INIT; }; +25 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:16:17 + --> $DIR/replace_consts.rs:26:17 | -16 | { let foo = ATOMIC_I8_INIT; }; +26 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:17:17 + --> $DIR/replace_consts.rs:27:17 | -17 | { let foo = ATOMIC_I16_INIT; }; +27 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:18:17 + --> $DIR/replace_consts.rs:28:17 | -18 | { let foo = ATOMIC_I32_INIT; }; +28 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:19:17 + --> $DIR/replace_consts.rs:29:17 | -19 | { let foo = ATOMIC_I64_INIT; }; +29 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:20:17 + --> $DIR/replace_consts.rs:30:17 | -20 | { let foo = ATOMIC_USIZE_INIT; }; +30 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:21:17 + --> $DIR/replace_consts.rs:31:17 | -21 | { let foo = ATOMIC_U8_INIT; }; +31 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:22:17 + --> $DIR/replace_consts.rs:32:17 | -22 | { let foo = ATOMIC_U16_INIT; }; +32 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:33:17 | -23 | { let foo = ATOMIC_U32_INIT; }; +33 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:34:17 | -24 | { let foo = ATOMIC_U64_INIT; }; +34 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:36:17 | -26 | { let foo = std::isize::MIN; }; +36 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:37:17 | -27 | { let foo = std::i8::MIN; }; +37 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:38:17 | -28 | { let foo = std::i16::MIN; }; +38 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:39:17 | -29 | { let foo = std::i32::MIN; }; +39 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:40:17 | -30 | { let foo = std::i64::MIN; }; +40 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:41:17 | -31 | { let foo = std::i128::MIN; }; +41 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:42:17 | -32 | { let foo = std::usize::MIN; }; +42 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:43:17 | -33 | { let foo = std::u8::MIN; }; +43 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:44:17 | -34 | { let foo = std::u16::MIN; }; +44 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:45:17 | -35 | { let foo = std::u32::MIN; }; +45 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:46:17 | -36 | { let foo = std::u64::MIN; }; +46 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:47:17 | -37 | { let foo = std::u128::MIN; }; +47 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:49:17 | -39 | { let foo = std::isize::MAX; }; +49 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:50:17 | -40 | { let foo = std::i8::MAX; }; +50 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:51:17 | -41 | { let foo = std::i16::MAX; }; +51 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:52:17 | -42 | { let foo = std::i32::MAX; }; +52 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:53:17 | -43 | { let foo = std::i64::MAX; }; +53 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:54:17 | -44 | { let foo = std::i128::MAX; }; +54 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:55:17 | -45 | { let foo = std::usize::MAX; }; +55 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:56:17 | -46 | { let foo = std::u8::MAX; }; +56 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:57:17 | -47 | { let foo = std::u16::MAX; }; +57 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:58:17 | -48 | { let foo = std::u32::MAX; }; +58 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:59:17 | -49 | { let foo = std::u64::MAX; }; +59 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:60:17 | -50 | { let foo = std::u128::MAX; }; +60 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index 8cac6a9c827..4edbfdd5bf4 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(never_type)] diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 5fba1a0d7ad..04f105c78e2 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:35:5 + --> $DIR/result_map_unit_fn.rs:45:5 | -35 | x.field.map(do_nothing); +45 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -9,183 +9,183 @@ error: called `map(f)` on an Result value where `f` is a unit function = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:37:5 + --> $DIR/result_map_unit_fn.rs:47:5 | -37 | x.field.map(do_nothing); +47 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:39:5 + --> $DIR/result_map_unit_fn.rs:49:5 | -39 | x.field.map(diverge); +49 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:45:5 + --> $DIR/result_map_unit_fn.rs:55:5 | -45 | x.field.map(|value| x.do_result_nothing(value + captured)); +55 | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:47:5 + --> $DIR/result_map_unit_fn.rs:57:5 | -47 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); +57 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:50:5 + --> $DIR/result_map_unit_fn.rs:60:5 | -50 | x.field.map(|value| do_nothing(value + captured)); +60 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:52:5 + --> $DIR/result_map_unit_fn.rs:62:5 | -52 | x.field.map(|value| { do_nothing(value + captured) }); +62 | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:54:5 + --> $DIR/result_map_unit_fn.rs:64:5 | -54 | x.field.map(|value| { do_nothing(value + captured); }); +64 | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:56:5 + --> $DIR/result_map_unit_fn.rs:66:5 | -56 | x.field.map(|value| { { do_nothing(value + captured); } }); +66 | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:59:5 + --> $DIR/result_map_unit_fn.rs:69:5 | -59 | x.field.map(|value| diverge(value + captured)); +69 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:61:5 + --> $DIR/result_map_unit_fn.rs:71:5 | -61 | x.field.map(|value| { diverge(value + captured) }); +71 | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:63:5 + --> $DIR/result_map_unit_fn.rs:73:5 | -63 | x.field.map(|value| { diverge(value + captured); }); +73 | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:65:5 + --> $DIR/result_map_unit_fn.rs:75:5 | -65 | x.field.map(|value| { { diverge(value + captured); } }); +75 | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:70:5 + --> $DIR/result_map_unit_fn.rs:80:5 | -70 | x.field.map(|value| { let y = plus_one(value + captured); }); +80 | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:72:5 + --> $DIR/result_map_unit_fn.rs:82:5 | -72 | x.field.map(|value| { plus_one(value + captured); }); +82 | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:74:5 + --> $DIR/result_map_unit_fn.rs:84:5 | -74 | x.field.map(|value| { { plus_one(value + captured); } }); +84 | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:77:5 + --> $DIR/result_map_unit_fn.rs:87:5 | -77 | x.field.map(|ref value| { do_nothing(value + captured) }); +87 | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:80:5 + --> $DIR/result_map_unit_fn.rs:90:5 | -80 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +90 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:82:5 + --> $DIR/result_map_unit_fn.rs:92:5 | -82 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +92 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:86:5 + --> $DIR/result_map_unit_fn.rs:96:5 | -86 | x.field.map(|value| { +96 | x.field.map(|value| { | _____^ | |_____| | || -87 | || do_nothing(value); -88 | || do_nothing(value) -89 | || }); +97 | || do_nothing(value); +98 | || do_nothing(value) +99 | || }); | ||______^- help: try this: `if let Ok(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:90:5 - | -90 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { ... }` + --> $DIR/result_map_unit_fn.rs:100:5 + | +100 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:94:5 - | -94 | "12".parse::().map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` + --> $DIR/result_map_unit_fn.rs:104:5 + | +104 | "12".parse::().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:100:5 + --> $DIR/result_map_unit_fn.rs:110:5 | -100 | y.map(do_nothing); +110 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_y) = y { do_nothing(...) }` diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index 65c2c344da7..caa954bea44 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::serde_api_misuse)] diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index cce839a0d94..e223430e680 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -1,11 +1,11 @@ error: you should not implement `visit_string` without also implementing `visit_str` - --> $DIR/serde.rs:39:5 + --> $DIR/serde.rs:49:5 | -39 | / fn visit_string(self, _v: String) -> Result -40 | | where E: serde::de::Error, -41 | | { -42 | | unimplemented!() -43 | | } +49 | / fn visit_string(self, _v: String) -> Result +50 | | where E: serde::de::Error, +51 | | { +52 | | unimplemented!() +53 | | } | |_____^ | = note: `-D clippy::serde-api-misuse` implied by `-D warnings` diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index c73acf5c5dd..a607161a949 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 311177e25b4..adca299d382 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,137 +1,137 @@ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:13:5 + --> $DIR/shadow.rs:23:5 | -13 | let x = &mut x; +23 | let x = &mut x; | ^^^^^^^^^^^^^^^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:12:13 + --> $DIR/shadow.rs:22:13 | -12 | let mut x = 1; +22 | let mut x = 1; | ^ error: `x` is shadowed by itself in `{ x }` - --> $DIR/shadow.rs:14:5 + --> $DIR/shadow.rs:24:5 | -14 | let x = { x }; +24 | let x = { x }; | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:23:9 | -13 | let x = &mut x; +23 | let x = &mut x; | ^ error: `x` is shadowed by itself in `(&*x)` - --> $DIR/shadow.rs:15:5 + --> $DIR/shadow.rs:25:5 | -15 | let x = (&*x); +25 | let x = (&*x); | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:24:9 | -14 | let x = { x }; +24 | let x = { x }; | ^ error: `x` is shadowed by `{ *x + 1 }` which reuses the original value - --> $DIR/shadow.rs:16:9 + --> $DIR/shadow.rs:26:9 | -16 | let x = { *x + 1 }; +26 | let x = { *x + 1 }; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:16:13 + --> $DIR/shadow.rs:26:13 | -16 | let x = { *x + 1 }; +26 | let x = { *x + 1 }; | ^^^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:25:9 | -15 | let x = (&*x); +25 | let x = (&*x); | ^ error: `x` is shadowed by `id(x)` which reuses the original value - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:27:9 | -17 | let x = id(x); +27 | let x = id(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:17:13 + --> $DIR/shadow.rs:27:13 | -17 | let x = id(x); +27 | let x = id(x); | ^^^^^ note: previous binding is here - --> $DIR/shadow.rs:16:9 + --> $DIR/shadow.rs:26:9 | -16 | let x = { *x + 1 }; +26 | let x = { *x + 1 }; | ^ error: `x` is shadowed by `(1, x)` which reuses the original value - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:28:9 | -18 | let x = (1, x); +28 | let x = (1, x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:18:13 + --> $DIR/shadow.rs:28:13 | -18 | let x = (1, x); +28 | let x = (1, x); | ^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:27:9 | -17 | let x = id(x); +27 | let x = id(x); | ^ error: `x` is shadowed by `first(x)` which reuses the original value - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:29:9 | -19 | let x = first(x); +29 | let x = first(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:19:13 + --> $DIR/shadow.rs:29:13 | -19 | let x = first(x); +29 | let x = first(x); | ^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:28:9 | -18 | let x = (1, x); +28 | let x = (1, x); | ^ error: `x` is shadowed by `y` - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:31:9 | -21 | let x = y; +31 | let x = y; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:21:13 + --> $DIR/shadow.rs:31:13 | -21 | let x = y; +31 | let x = y; | ^ note: previous binding is here - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:29:9 | -19 | let x = first(x); +29 | let x = first(x); | ^ error: `x` shadows a previous declaration - --> $DIR/shadow.rs:23:5 + --> $DIR/shadow.rs:33:5 | -23 | let x; +33 | let x; | ^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:31:9 | -21 | let x = y; +31 | let x = y; | ^ error: aborting due to 9 previous errors diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index e9cb8e4ad8c..01511314c7d 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index bef497c33a0..331bdac3128 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -1,22 +1,22 @@ error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:7:5 - | -7 | f() && g(); - | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` - | - = note: `-D clippy::short-circuit-statement` implied by `-D warnings` + --> $DIR/short_circuit_statement.rs:17:5 + | +17 | f() && g(); + | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` + | + = note: `-D clippy::short-circuit-statement` implied by `-D warnings` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:8:5 - | -8 | f() || g(); - | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` + --> $DIR/short_circuit_statement.rs:18:5 + | +18 | f() || g(); + | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:9:5 - | -9 | 1 == 2 || g(); - | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` + --> $DIR/short_circuit_statement.rs:19:5 + | +19 | 1 == 2 || g(); + | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` error: aborting due to 3 previous errors diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index c4e88e9ee2b..12aaa69f34b 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 78355612717..ff657df1bf8 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,123 +1,123 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:7:13 - | -7 | x.split("x"); - | ^^^ help: try using a char instead: `'x'` - | - = note: `-D clippy::single-char-pattern` implied by `-D warnings` + --> $DIR/single_char_pattern.rs:17:13 + | +17 | x.split("x"); + | ^^^ help: try using a char instead: `'x'` + | + = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:24:16 + --> $DIR/single_char_pattern.rs:34:16 | -24 | x.contains("x"); +34 | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:25:19 + --> $DIR/single_char_pattern.rs:35:19 | -25 | x.starts_with("x"); +35 | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:26:17 + --> $DIR/single_char_pattern.rs:36:17 | -26 | x.ends_with("x"); +36 | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:27:12 + --> $DIR/single_char_pattern.rs:37:12 | -27 | x.find("x"); +37 | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:28:13 + --> $DIR/single_char_pattern.rs:38:13 | -28 | x.rfind("x"); +38 | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:29:14 + --> $DIR/single_char_pattern.rs:39:14 | -29 | x.rsplit("x"); +39 | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:30:24 + --> $DIR/single_char_pattern.rs:40:24 | -30 | x.split_terminator("x"); +40 | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:31:25 + --> $DIR/single_char_pattern.rs:41:25 | -31 | x.rsplit_terminator("x"); +41 | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:32:17 + --> $DIR/single_char_pattern.rs:42:17 | -32 | x.splitn(0, "x"); +42 | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:18 + --> $DIR/single_char_pattern.rs:43:18 | -33 | x.rsplitn(0, "x"); +43 | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:15 + --> $DIR/single_char_pattern.rs:44:15 | -34 | x.matches("x"); +44 | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:16 + --> $DIR/single_char_pattern.rs:45:16 | -35 | x.rmatches("x"); +45 | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:21 + --> $DIR/single_char_pattern.rs:46:21 | -36 | x.match_indices("x"); +46 | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:22 + --> $DIR/single_char_pattern.rs:47:22 | -37 | x.rmatch_indices("x"); +47 | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:25 + --> $DIR/single_char_pattern.rs:48:25 | -38 | x.trim_left_matches("x"); +48 | x.trim_left_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:26 + --> $DIR/single_char_pattern.rs:49:26 | -39 | x.trim_right_matches("x"); +49 | x.trim_right_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:13 + --> $DIR/single_char_pattern.rs:51:13 | -41 | x.split("/n"); +51 | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:31 + --> $DIR/single_char_pattern.rs:56:31 | -46 | x.replace(";", ",").split(","); // issue #2978 +56 | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:47:19 + --> $DIR/single_char_pattern.rs:57:19 | -47 | x.starts_with("/x03"); // issue #2996 +57 | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` error: aborting due to 20 previous errors diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index c0c82adafb5..07c1a95025a 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::single_match)] diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 20d8fed25fd..74448391ca5 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,48 +1,48 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:11:5 + --> $DIR/single_match.rs:21:5 | -11 | / match x { -12 | | Some(y) => { println!("{:?}", y); } -13 | | _ => () -14 | | }; +21 | / match x { +22 | | Some(y) => { println!("{:?}", y); } +23 | | _ => () +24 | | }; | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y); }` | = note: `-D clippy::single-match` implied by `-D warnings` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:17:5 + --> $DIR/single_match.rs:27:5 | -17 | / match z { -18 | | (2...3, 7...9) => dummy(), -19 | | _ => {} -20 | | }; +27 | / match z { +28 | | (2...3, 7...9) => dummy(), +29 | | _ => {} +30 | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:43:5 + --> $DIR/single_match.rs:53:5 | -43 | / match x { -44 | | Some(y) => dummy(), -45 | | None => () -46 | | }; +53 | / match x { +54 | | Some(y) => dummy(), +55 | | None => () +56 | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:48:5 + --> $DIR/single_match.rs:58:5 | -48 | / match y { -49 | | Ok(y) => dummy(), -50 | | Err(..) => () -51 | | }; +58 | / match y { +59 | | Ok(y) => dummy(), +60 | | Err(..) => () +61 | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:55:5 + --> $DIR/single_match.rs:65:5 | -55 | / match c { -56 | | Cow::Borrowed(..) => dummy(), -57 | | Cow::Owned(..) => (), -58 | | }; +65 | / match c { +66 | | Cow::Borrowed(..) => dummy(), +67 | | Cow::Owned(..) => (), +68 | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: aborting due to 5 previous errors diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index adea56cf9a2..180924d2c9c 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(dead_code)] diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index b3fb444b562..9921819e093 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,77 +1,77 @@ error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:9:5 - | -9 | "".chars().next() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` - | - = note: `-D clippy::chars-next-cmp` implied by `-D warnings` + --> $DIR/starts_ends_with.rs:19:5 + | +19 | "".chars().next() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` + | + = note: `-D clippy::chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:10:5 + --> $DIR/starts_ends_with.rs:20:5 | -10 | Some(' ') != "".chars().next(); +20 | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:15:8 + --> $DIR/starts_ends_with.rs:25:8 | -15 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +25 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:18:8 + --> $DIR/starts_ends_with.rs:28:8 | -18 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +28 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | = note: `-D clippy::chars-last-cmp` implied by `-D warnings` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:21:8 + --> $DIR/starts_ends_with.rs:31:8 | -21 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +31 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:24:8 + --> $DIR/starts_ends_with.rs:34:8 | -24 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +34 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:27:8 + --> $DIR/starts_ends_with.rs:37:8 | -27 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +37 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:30:8 + --> $DIR/starts_ends_with.rs:40:8 | -30 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +40 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:37:5 + --> $DIR/starts_ends_with.rs:47:5 | -37 | "".chars().last() == Some(' '); +47 | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:38:5 + --> $DIR/starts_ends_with.rs:48:5 | -38 | Some(' ') != "".chars().last(); +48 | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:39:5 + --> $DIR/starts_ends_with.rs:49:5 | -39 | "".chars().next_back() == Some(' '); +49 | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:40:5 + --> $DIR/starts_ends_with.rs:50:5 | -40 | Some(' ') != "".chars().next_back(); +50 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: aborting due to 12 previous errors diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index d99adb19f89..a0cf9c46906 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 32e3482699c..2a82972a3cd 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,21 +1,21 @@ error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:16:5 + --> $DIR/string_extend.rs:26:5 | -16 | s.extend(abc.chars()); +26 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:19:5 + --> $DIR/string_extend.rs:29:5 | -19 | s.extend("abc".chars()); +29 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:22:5 + --> $DIR/string_extend.rs:32:5 | -22 | s.extend(def.chars()); +32 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: aborting due to 3 previous errors diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 86819e3fd5c..31e6c9a059f 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index 258920e2652..bcdf91568d2 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -1,75 +1,75 @@ error: manual implementation of an assign operation - --> $DIR/strings.rs:10:9 + --> $DIR/strings.rs:20:9 | -10 | x = x + "."; +20 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:10:13 + --> $DIR/strings.rs:20:13 | -10 | x = x + "."; +20 | x = x + "."; | ^^^^^^^ | = note: `-D clippy::string-add` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:14:13 + --> $DIR/strings.rs:24:13 | -14 | let z = y + "..."; +24 | let z = y + "..."; | ^^^^^^^^^ error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:24:9 + --> $DIR/strings.rs:34:9 | -24 | x = x + "."; +34 | x = x + "."; | ^^^^^^^^^^^ | = note: `-D clippy::string-add-assign` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/strings.rs:24:9 + --> $DIR/strings.rs:34:9 | -24 | x = x + "."; +34 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:38:9 + --> $DIR/strings.rs:48:9 | -38 | x = x + "."; +48 | x = x + "."; | ^^^^^^^^^^^ error: manual implementation of an assign operation - --> $DIR/strings.rs:38:9 + --> $DIR/strings.rs:48:9 | -38 | x = x + "."; +48 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:42:13 + --> $DIR/strings.rs:52:13 | -42 | let z = y + "..."; +52 | let z = y + "..."; | ^^^^^^^^^ error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:50:14 + --> $DIR/strings.rs:60:14 | -50 | let bs = "hello there".as_bytes(); +60 | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:55:18 + --> $DIR/strings.rs:65:18 | -55 | let strify = stringify!(foobar).as_bytes(); +65 | let strify = stringify!(foobar).as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `bstringify!(foobar)` error: manual implementation of an assign operation - --> $DIR/strings.rs:65:7 + --> $DIR/strings.rs:75:7 | -65 | ; x = x + 1; +75 | ; x = x + 1; | ^^^^^^^^^ help: replace it with: `x += 1` error: aborting due to 11 previous errors diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index de67bb1aff5..148e8071ce0 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::stutter)] diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index 3cc0be39567..2ff992fccf6 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -1,33 +1,33 @@ error: item name starts with its containing module's name - --> $DIR/stutter.rs:8:5 - | -8 | pub fn foo_bar() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::stutter` implied by `-D warnings` + --> $DIR/stutter.rs:18:5 + | +18 | pub fn foo_bar() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::stutter` implied by `-D warnings` error: item name ends with its containing module's name - --> $DIR/stutter.rs:9:5 - | -9 | pub fn bar_foo() {} - | ^^^^^^^^^^^^^^^^^^^ + --> $DIR/stutter.rs:19:5 + | +19 | pub fn bar_foo() {} + | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/stutter.rs:10:5 + --> $DIR/stutter.rs:20:5 | -10 | pub struct FooCake {} +20 | pub struct FooCake {} | ^^^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name - --> $DIR/stutter.rs:11:5 + --> $DIR/stutter.rs:21:5 | -11 | pub enum CakeFoo {} +21 | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/stutter.rs:12:5 + --> $DIR/stutter.rs:22:5 | -12 | pub struct Foo7Bar; +22 | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 04e235c690b..a183576b40e 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 0f396c3a560..64070cce3a8 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,15 +1,15 @@ error: Suspicious use of binary operator in `Add` impl - --> $DIR/suspicious_arithmetic_impl.rs:14:20 + --> $DIR/suspicious_arithmetic_impl.rs:24:20 | -14 | Foo(self.0 - other.0) +24 | Foo(self.0 - other.0) | ^ | = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` error: Suspicious use of binary operator in `AddAssign` impl - --> $DIR/suspicious_arithmetic_impl.rs:20:23 + --> $DIR/suspicious_arithmetic_impl.rs:30:23 | -20 | *self = *self - other; +30 | *self = *self - other; | ^ | = note: #[deny(clippy::suspicious_op_assign_impl)] on by default diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 377319e8faa..bef2031f8a8 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 67d4fd8a14b..7a4fbdad791 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,66 +1,66 @@ error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:11:5 + --> $DIR/swap.rs:21:5 | -11 | / let temp = foo[0]; -12 | | foo[0] = foo[1]; -13 | | foo[1] = temp; +21 | / let temp = foo[0]; +22 | | foo[0] = foo[1]; +23 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` | = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:20:5 + --> $DIR/swap.rs:30:5 | -20 | / let temp = foo[0]; -21 | | foo[0] = foo[1]; -22 | | foo[1] = temp; +30 | / let temp = foo[0]; +31 | | foo[0] = foo[1]; +32 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:29:5 + --> $DIR/swap.rs:39:5 | -29 | / let temp = foo[0]; -30 | | foo[0] = foo[1]; -31 | | foo[1] = temp; +39 | / let temp = foo[0]; +40 | | foo[0] = foo[1]; +41 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:47:7 + --> $DIR/swap.rs:57:7 | -47 | ; let t = a; +57 | ; let t = a; | _______^ -48 | | a = b; -49 | | b = t; +58 | | a = b; +59 | | b = t; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:56:7 + --> $DIR/swap.rs:66:7 | -56 | ; let t = c.0; +66 | ; let t = c.0; | _______^ -57 | | c.0 = a; -58 | | a = t; +67 | | c.0 = a; +68 | | a = t; | |_________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:44:5 + --> $DIR/swap.rs:54:5 | -44 | / a = b; -45 | | b = a; +54 | / a = b; +55 | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: `-D clippy::almost-swapped` implied by `-D warnings` = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:53:5 + --> $DIR/swap.rs:63:5 | -53 | / c.0 = a; -54 | | a = c.0; +63 | / c.0 = a; +64 | | a = c.0; | |___________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 1d0cffcfc0a..cf92f9fd6c2 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 38379d8bd20..17b1ca1251a 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -1,15 +1,15 @@ error: assignment to temporary - --> $DIR/temporary_assignment.rs:29:5 + --> $DIR/temporary_assignment.rs:39:5 | -29 | Struct { field: 0 }.field = 1; +39 | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::temporary-assignment` implied by `-D warnings` error: assignment to temporary - --> $DIR/temporary_assignment.rs:30:5 + --> $DIR/temporary_assignment.rs:40:5 | -30 | (0, 0).0 = 1; +40 | (0, 0).0 = 1; | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 86eb7fa5565..9f92d706ad6 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index f3fe563f294..edde5510e2a 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,33 +1,33 @@ error: `ref` directly on a function argument is ignored. Consider using a reference type instead. - --> $DIR/toplevel_ref_arg.rs:7:15 - | -7 | fn the_answer(ref mut x: u8) { - | ^^^^^^^^^ - | - = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` + --> $DIR/toplevel_ref_arg.rs:17:15 + | +17 | fn the_answer(ref mut x: u8) { + | ^^^^^^^^^ + | + = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:18:7 + --> $DIR/toplevel_ref_arg.rs:28:7 | -18 | let ref x = 1; +28 | let ref x = 1; | ----^^^^^----- help: try: `let x = &1;` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:20:7 + --> $DIR/toplevel_ref_arg.rs:30:7 | -20 | let ref y: (&_, u8) = (&1, 2); +30 | let ref y: (&_, u8) = (&1, 2); | ----^^^^^--------------------- help: try: `let y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:22:7 + --> $DIR/toplevel_ref_arg.rs:32:7 | -22 | let ref z = 1 + 2; +32 | let ref z = 1 + 2; | ----^^^^^--------- help: try: `let z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:24:7 + --> $DIR/toplevel_ref_arg.rs:34:7 | -24 | let ref mut z = 1 + 2; +34 | let ref mut z = 1 + 2; | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` error: aborting due to 5 previous errors diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 58c04d292bc..7ed076225e2 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(stmt_expr_attributes)] #![allow(unused_parens)] diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 477f42c28f4..4dbb82b3460 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -1,16 +1,16 @@ error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:7:31 - | -7 | let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros - | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` - | - = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` + --> $DIR/trailing_zeros.rs:17:31 + | +17 | let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros + | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` + | + = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:8:13 - | -8 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros - | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` + --> $DIR/trailing_zeros.rs:18:13 + | +18 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros + | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` error: aborting due to 2 previous errors diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 34d50da11ca..4108750acf6 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 4340c16b97c..bde43da499f 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,245 +1,245 @@ error: transmute from a type (`&'a T`) to itself - --> $DIR/transmute.rs:22:20 + --> $DIR/transmute.rs:32:20 | -22 | let _: &'a T = core::intrinsics::transmute(t); +32 | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:26:23 + --> $DIR/transmute.rs:36:23 | -26 | let _: *const T = core::intrinsics::transmute(t); +36 | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:28:21 + --> $DIR/transmute.rs:38:21 | -28 | let _: *mut T = core::intrinsics::transmute(t); +38 | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:30:23 + --> $DIR/transmute.rs:40:23 | -30 | let _: *const U = core::intrinsics::transmute(t); +40 | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute.rs:35:17 + --> $DIR/transmute.rs:45:17 | -35 | let _: &T = std::mem::transmute(p); +45 | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` | = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:38:21 + --> $DIR/transmute.rs:48:21 | -38 | let _: &mut T = std::mem::transmute(m); +48 | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute.rs:41:17 + --> $DIR/transmute.rs:51:17 | -41 | let _: &T = std::mem::transmute(m); +51 | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:44:21 + --> $DIR/transmute.rs:54:21 | -44 | let _: &mut T = std::mem::transmute(p as *mut T); +54 | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute.rs:47:17 + --> $DIR/transmute.rs:57:17 | -47 | let _: &T = std::mem::transmute(o); +57 | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:50:21 + --> $DIR/transmute.rs:60:21 | -50 | let _: &mut T = std::mem::transmute(om); +60 | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute.rs:53:17 + --> $DIR/transmute.rs:63:17 | -53 | let _: &T = std::mem::transmute(om); +63 | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, u8>`) - --> $DIR/transmute.rs:64:32 + --> $DIR/transmute.rs:74:32 | -64 | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; +74 | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, &u8>`) - --> $DIR/transmute.rs:66:33 + --> $DIR/transmute.rs:76:33 | -66 | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; +76 | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute.rs:70:14 + --> $DIR/transmute.rs:80:14 | -70 | unsafe { std::mem::transmute::<_, Bar>(raw) }; +80 | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:76:27 + --> $DIR/transmute.rs:86:27 | -76 | let _: Vec = core::intrinsics::transmute(my_vec()); +86 | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:78:27 + --> $DIR/transmute.rs:88:27 | -78 | let _: Vec = core::mem::transmute(my_vec()); +88 | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:80:27 + --> $DIR/transmute.rs:90:27 | -80 | let _: Vec = std::intrinsics::transmute(my_vec()); +90 | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:82:27 + --> $DIR/transmute.rs:92:27 | -82 | let _: Vec = std::mem::transmute(my_vec()); +92 | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:84:27 + --> $DIR/transmute.rs:94:27 | -84 | let _: Vec = my_transmute(my_vec()); +94 | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:92:31 - | -92 | let _: *const usize = std::mem::transmute(5_isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` + --> $DIR/transmute.rs:102:31 + | +102 | let _: *const usize = std::mem::transmute(5_isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:96:31 - | -96 | let _: *const usize = std::mem::transmute(1+1usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1+1usize) as *const usize` + --> $DIR/transmute.rs:106:31 + | +106 | let _: *const usize = std::mem::transmute(1+1usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1+1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:111:24 + --> $DIR/transmute.rs:121:24 | -111 | let _: Usize = core::intrinsics::transmute(int_const_ptr); +121 | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:113:24 + --> $DIR/transmute.rs:123:24 | -113 | let _: Usize = core::intrinsics::transmute(int_mut_ptr); +123 | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:115:31 + --> $DIR/transmute.rs:125:31 | -115 | let _: *const Usize = core::intrinsics::transmute(my_int()); +125 | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:117:29 + --> $DIR/transmute.rs:127:29 | -117 | let _: *mut Usize = core::intrinsics::transmute(my_int()); +127 | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:123:28 + --> $DIR/transmute.rs:133:28 | -123 | let _: char = unsafe { std::mem::transmute(0_u32) }; +133 | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` | = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:124:28 + --> $DIR/transmute.rs:134:28 | -124 | let _: char = unsafe { std::mem::transmute(0_i32) }; +134 | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:129:28 + --> $DIR/transmute.rs:139:28 | -129 | let _: bool = unsafe { std::mem::transmute(0_u8) }; +139 | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` | = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:134:27 + --> $DIR/transmute.rs:144:27 | -134 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; +144 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` | = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:135:27 + --> $DIR/transmute.rs:145:27 | -135 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; +145 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:139:28 + --> $DIR/transmute.rs:149:28 | -139 | let _: &str = unsafe { std::mem::transmute(b) }; +149 | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` | = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:140:32 + --> $DIR/transmute.rs:150:32 | -140 | let _: &mut str = unsafe { std::mem::transmute(mb) }; +150 | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:172:29 + --> $DIR/transmute.rs:182:29 | -172 | let _: *const f32 = std::mem::transmute(ptr); +182 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:173:27 + --> $DIR/transmute.rs:183:27 | -173 | let _: *mut f32 = std::mem::transmute(mut_ptr); +183 | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:175:23 + --> $DIR/transmute.rs:185:23 | -175 | let _: &f32 = std::mem::transmute(&1u32); +185 | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:176:23 + --> $DIR/transmute.rs:186:23 | -176 | let _: &f64 = std::mem::transmute(&1f32); +186 | let _: &f64 = std::mem::transmute(&1f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:179:27 + --> $DIR/transmute.rs:189:27 | -179 | let _: &mut f32 = std::mem::transmute(&mut 1u32); +189 | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:180:37 + --> $DIR/transmute.rs:190:37 | -180 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); +190 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: aborting due to 38 previous errors diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index 08866c63ec6..59d3d82ccae 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + //ignore-x86_64 diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 539b403cff9..630b594eb1b 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] //ignore-x86 diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index e86908655a8..dcc6d264caf 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,15 +1,15 @@ error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:11:31 + --> $DIR/transmute_64bit.rs:21:31 | -11 | let _: *const usize = std::mem::transmute(6.0f64); +21 | let _: *const usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::wrong-transmute` implied by `-D warnings` error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:13:29 + --> $DIR/transmute_64bit.rs:23:29 | -13 | let _: *mut usize = std::mem::transmute(6.0f64); +23 | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index e3dbe510a47..716e0dc6420 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::many_single_char_names, clippy::blacklisted_name, clippy::redundant_field_names)] diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 2db627dd9b1..2026d4c00d8 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:42:11 + --> $DIR/trivially_copy_pass_by_ref.rs:52:11 | -42 | fn bad(x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:42:20 + --> $DIR/trivially_copy_pass_by_ref.rs:52:20 | -42 | fn bad(x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:42:29 + --> $DIR/trivially_copy_pass_by_ref.rs:52:29 | -42 | fn bad(x: &u32, y: &Foo, z: &Baz) { +52 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:12 + --> $DIR/trivially_copy_pass_by_ref.rs:62:12 | -52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:22 + --> $DIR/trivially_copy_pass_by_ref.rs:62:22 | -52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:31 + --> $DIR/trivially_copy_pass_by_ref.rs:62:31 | -52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:40 + --> $DIR/trivially_copy_pass_by_ref.rs:62:40 | -52 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:55:16 + --> $DIR/trivially_copy_pass_by_ref.rs:65:16 | -55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:55:25 + --> $DIR/trivially_copy_pass_by_ref.rs:65:25 | -55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:55:34 + --> $DIR/trivially_copy_pass_by_ref.rs:65:34 | -55 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:69:16 + --> $DIR/trivially_copy_pass_by_ref.rs:79:16 | -69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:69:25 + --> $DIR/trivially_copy_pass_by_ref.rs:79:25 | -69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:69:34 + --> $DIR/trivially_copy_pass_by_ref.rs:79:34 | -69 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs index 9e2753dcb18..82b5deda3ba 100644 --- a/tests/ui/ty_fn_sig.rs +++ b/tests/ui/ty_fn_sig.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // Regression test pub fn retry(f: F) { diff --git a/tests/ui/types.rs b/tests/ui/types.rs index 10d1c490ee6..03676f69ab4 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + // should not warn on lossy casting in constant types // because not supported yet const C : i32 = 42; diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index e2f75162867..0940cd53b5c 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -1,10 +1,10 @@ error: casting i32 to i64 may become silently lossy if types change - --> $DIR/types.rs:9:23 - | -9 | let c_i64 : i64 = c as i64; - | ^^^^^^^^ help: try: `i64::from(c)` - | - = note: `-D clippy::cast-lossless` implied by `-D warnings` + --> $DIR/types.rs:19:23 + | +19 | let c_i64 : i64 = c as i64; + | ^^^^^^^^ help: try: `i64::from(c)` + | + = note: `-D clippy::cast-lossless` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index b997d6d3f14..486135ddfa5 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index b0e567fc212..8de848caec3 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,17 +1,17 @@ error: zero-width space detected - --> $DIR/unicode.rs:6:12 - | -6 | print!("Here >​< is a ZWS, and ​another"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::zero-width-space` implied by `-D warnings` - = help: Consider replacing the string with: - ""Here >/u{200B}< is a ZWS, and /u{200B}another"" + --> $DIR/unicode.rs:16:12 + | +16 | print!("Here >​< is a ZWS, and ​another"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::zero-width-space` implied by `-D warnings` + = help: Consider replacing the string with: + ""Here >/u{200B}< is a ZWS, and /u{200B}another"" error: non-nfc unicode sequence detected - --> $DIR/unicode.rs:12:12 + --> $DIR/unicode.rs:22:12 | -12 | print!("̀àh?"); +22 | print!("̀àh?"); | ^^^^^ | = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` @@ -19,9 +19,9 @@ error: non-nfc unicode sequence detected ""̀àh?"" error: literal non-ASCII character detected - --> $DIR/unicode.rs:18:12 + --> $DIR/unicode.rs:28:12 | -18 | print!("Üben!"); +28 | print!("Üben!"); | ^^^^^^^ | = note: `-D clippy::non-ascii-literal` implied by `-D warnings` diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 2f743f227b8..ed70ee843b1 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::unit_arg)] diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index e1845c0c0ea..6e5cf8354bc 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,67 +1,67 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:25:9 + --> $DIR/unit_arg.rs:35:9 | -25 | foo({}); +35 | foo({}); | ^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` help: if you intended to pass a unit value, use a unit literal instead | -25 | foo(()); +35 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:26:9 + --> $DIR/unit_arg.rs:36:9 | -26 | foo({ 1; }); +36 | foo({ 1; }); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -26 | foo(()); +36 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:27:9 + --> $DIR/unit_arg.rs:37:9 | -27 | foo(foo(1)); +37 | foo(foo(1)); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -27 | foo(()); +37 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:28:9 + --> $DIR/unit_arg.rs:38:9 | -28 | foo({ +38 | foo({ | _________^ -29 | | foo(1); -30 | | foo(2); -31 | | }); +39 | | foo(1); +40 | | foo(2); +41 | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -28 | foo(()); +38 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:32:10 + --> $DIR/unit_arg.rs:42:10 | -32 | foo3({}, 2, 2); +42 | foo3({}, 2, 2); | ^^ help: if you intended to pass a unit value, use a unit literal instead | -32 | foo3((), 2, 2); +42 | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:34:11 + --> $DIR/unit_arg.rs:44:11 | -34 | b.bar({ 1; }); +44 | b.bar({ 1; }); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -34 | b.bar(()); +44 | b.bar(()); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index bd79d0f8189..e8726bf7364 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index a85eb32841f..bd9ac25a64f 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,15 +1,15 @@ error: ==-comparison of unit values detected. This will always be true - --> $DIR/unit_cmp.rs:16:8 + --> $DIR/unit_cmp.rs:26:8 | -16 | if { true; } == { false; } { +26 | if { true; } == { false; } { | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false - --> $DIR/unit_cmp.rs:19:8 + --> $DIR/unit_cmp.rs:29:8 | -19 | if { true; } > { false; } { +29 | if { true; } > { false; } { | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 7a2fc4ac1f6..82010db7a99 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::clone_on_ref_ptr)] diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index b2985f84b04..051fc1fcdf9 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,81 +1,81 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:18:5 + --> $DIR/unnecessary_clone.rs:28:5 | -18 | 42.clone(); +28 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:22:5 + --> $DIR/unnecessary_clone.rs:32:5 | -22 | (&42).clone(); +32 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:32:5 + --> $DIR/unnecessary_clone.rs:42:5 | -32 | rc.clone(); +42 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:35:5 + --> $DIR/unnecessary_clone.rs:45:5 | -35 | arc.clone(); +45 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:38:5 + --> $DIR/unnecessary_clone.rs:48:5 | -38 | rcweak.clone(); +48 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:41:5 + --> $DIR/unnecessary_clone.rs:51:5 | -41 | arc_weak.clone(); +51 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:45:29 + --> $DIR/unnecessary_clone.rs:55:29 | -45 | let _: Arc = x.clone(); +55 | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:49:5 + --> $DIR/unnecessary_clone.rs:59:5 | -49 | t.clone(); +59 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:51:5 + --> $DIR/unnecessary_clone.rs:61:5 | -51 | Some(t).clone(); +61 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:57:22 + --> $DIR/unnecessary_clone.rs:67:22 | -57 | let z: &Vec<_> = y.clone(); +67 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | = note: #[deny(clippy::clone_double_ref)] on by default help: try dereferencing it | -57 | let z: &Vec<_> = &(*y).clone(); +67 | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -57 | let z: &Vec<_> = &std::vec::Vec::clone(y); +67 | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:64:27 + --> $DIR/unnecessary_clone.rs:74:27 | -64 | let v2 : Vec = v.iter().cloned().collect(); +74 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs index dd6cdc5d39d..8b74ca3a425 100644 --- a/tests/ui/unnecessary_filter_map.rs +++ b/tests/ui/unnecessary_filter_map.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index 045802047d2..8fef6068167 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -1,32 +1,32 @@ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:2:13 - | -2 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` + --> $DIR/unnecessary_filter_map.rs:12:13 + | +12 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:3:13 - | -3 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/unnecessary_filter_map.rs:13:13 + | +13 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:4:13 - | -4 | let _ = (0..4).filter_map(|x| match x { - | _____________^ -5 | | 0 | 1 => None, -6 | | _ => Some(x), -7 | | }); - | |______^ + --> $DIR/unnecessary_filter_map.rs:14:13 + | +14 | let _ = (0..4).filter_map(|x| match x { + | _____________^ +15 | | 0 | 1 => None, +16 | | _ => Some(x), +17 | | }); + | |______^ error: this `.filter_map` can be written more simply using `.map` - --> $DIR/unnecessary_filter_map.rs:9:13 - | -9 | let _ = (0..4).filter_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/unnecessary_filter_map.rs:19:13 + | +19 | let _ = (0..4).filter_map(|x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 62198e21ef7..e8d84ecea8c 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index e72f671b67e..b2865479c43 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -1,33 +1,33 @@ error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:4:19 - | -4 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` - | - = note: `-D clippy::unnecessary-fold` implied by `-D warnings` + --> $DIR/unnecessary_fold.rs:14:19 + | +14 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` + | + = note: `-D clippy::unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:6:19 - | -6 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` + --> $DIR/unnecessary_fold.rs:16:19 + | +16 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:8:19 - | -8 | let _ = (0..3).fold(0, |acc, x| acc + x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` + --> $DIR/unnecessary_fold.rs:18:19 + | +18 | let _ = (0..3).fold(0, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:10:19 + --> $DIR/unnecessary_fold.rs:20:19 | -10 | let _ = (0..3).fold(1, |acc, x| acc * x); +20 | let _ = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:15:34 + --> $DIR/unnecessary_fold.rs:25:34 | -15 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +25 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: aborting due to 5 previous errors diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index afc920832ce..6fb2abaf19c 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![feature(tool_attributes)] diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index d27ba26f349..a3d8f5e337c 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,13 +1,13 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:13:17 + --> $DIR/unnecessary_ref.rs:23:17 | -13 | let inner = (&outer).inner; +23 | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer.inner` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:10:8 + --> $DIR/unnecessary_ref.rs:20:8 | -10 | #[deny(clippy::ref_in_deref)] +20 | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 88b91235df6..963d555ca56 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 40aa4f524fe..85982d75494 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,16 +1,16 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:17:15 + --> $DIR/unneeded_field_pattern.rs:27:15 | -17 | Foo { a: _, b: 0, .. } => {} +27 | Foo { a: _, b: 0, .. } => {} | ^^^^ | = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` = help: Try with `Foo { b: 0, .. }` error: All the struct fields are matched to a wildcard pattern, consider using `..`. - --> $DIR/unneeded_field_pattern.rs:19:9 + --> $DIR/unneeded_field_pattern.rs:29:9 | -19 | Foo { a: _, b: _, c: _ } => {} +29 | Foo { a: _, b: _, c: _ } => {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Try with `Foo { .. }` instead diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index df3539e38e8..67e04706f04 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #[warn(clippy::unreadable_literal)] diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 516b6ccc595..b5ab6937d95 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,34 +1,34 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:16 - | -7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` - | - = note: `-D clippy::unreadable-literal` implied by `-D warnings` + --> $DIR/unreadable_literal.rs:17:16 + | +17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` + | + = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:30 - | -7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` + --> $DIR/unreadable_literal.rs:17:30 + | +17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:51 - | -7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^ help: consider: `123_456_f32` + --> $DIR/unreadable_literal.rs:17:51 + | +17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:7:63 - | -7 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` + --> $DIR/unreadable_literal.rs:17:63 + | +17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:9:19 - | -9 | let bad_sci = 1.123456e1; - | ^^^^^^^^^^ help: consider: `1.123_456e1` + --> $DIR/unreadable_literal.rs:19:19 + | +19 | let bad_sci = 1.123456e1; + | ^^^^^^^^^^ help: consider: `1.123_456e1` error: aborting due to 5 previous errors diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index 41b98975d53..39aa4afdf8d 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused_imports)] diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 2b014ca5863..f4bb93735d7 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -1,21 +1,21 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell` - --> $DIR/unsafe_removed_from_name.rs:7:1 - | -7 | use std::cell::{UnsafeCell as TotallySafeCell}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` + --> $DIR/unsafe_removed_from_name.rs:17:1 + | +17 | use std::cell::{UnsafeCell as TotallySafeCell}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` - --> $DIR/unsafe_removed_from_name.rs:9:1 - | -9 | use std::cell::UnsafeCell as TotallySafeCellAgain; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/unsafe_removed_from_name.rs:19:1 + | +19 | use std::cell::UnsafeCell as TotallySafeCellAgain; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` - --> $DIR/unsafe_removed_from_name.rs:23:1 + --> $DIR/unsafe_removed_from_name.rs:33:1 | -23 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; +33 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 53bcbce9dbf..0ab89c994f4 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 48a5751579c..329dfacd43b 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,42 +1,42 @@ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:11:5 + --> $DIR/unused_io_amount.rs:21:5 | -11 | try!(s.write(b"test")); +21 | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-io-amount` implied by `-D warnings` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:13:5 + --> $DIR/unused_io_amount.rs:23:5 | -13 | try!(s.read(&mut buf)); +23 | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:18:5 + --> $DIR/unused_io_amount.rs:28:5 | -18 | s.write(b"test")?; +28 | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:20:5 + --> $DIR/unused_io_amount.rs:30:5 | -20 | s.read(&mut buf)?; +30 | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:25:5 + --> $DIR/unused_io_amount.rs:35:5 | -25 | s.write(b"test").unwrap(); +35 | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:27:5 + --> $DIR/unused_io_amount.rs:37:5 | -27 | s.read(&mut buf).unwrap(); +37 | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index b76fcad1699..ecfdab490f6 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index d35ca41a1a1..5a31ada902e 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -1,25 +1,25 @@ error: unused label `'label` - --> $DIR/unused_labels.rs:8:5 + --> $DIR/unused_labels.rs:18:5 | -8 | / 'label: for i in 1..2 { -9 | | if i > 4 { continue } -10 | | } +18 | / 'label: for i in 1..2 { +19 | | if i > 4 { continue } +20 | | } | |_____^ | = note: `-D clippy::unused-label` implied by `-D warnings` error: unused label `'a` - --> $DIR/unused_labels.rs:21:5 + --> $DIR/unused_labels.rs:31:5 | -21 | 'a: loop { break } +31 | 'a: loop { break } | ^^^^^^^^^^^^^^^^^^ error: unused label `'same_label_in_two_fns` - --> $DIR/unused_labels.rs:32:5 + --> $DIR/unused_labels.rs:42:5 | -32 | / 'same_label_in_two_fns: loop { -33 | | let _ = 1; -34 | | } +42 | / 'same_label_in_two_fns: loop { +43 | | let _ = 1; +44 | | } | |_____^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index e5c5e893504..3aea986d28d 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index 4cad611c2a1..f5b788c16a7 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -1,21 +1,21 @@ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:16:14 + --> $DIR/unused_lt.rs:26:14 | -16 | fn unused_lt<'a>(x: u8) { +26 | fn unused_lt<'a>(x: u8) { | ^^ | = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:20:25 + --> $DIR/unused_lt.rs:30:25 | -20 | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { +30 | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:50:10 + --> $DIR/unused_lt.rs:60:10 | -50 | fn x<'a>(&self) {} +60 | fn x<'a>(&self) {} | ^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index 682c42dc935..b31ccfea200 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all)] diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index 42c72090ca5..ffdeeb5307f 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,15 +1,15 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:5:47 - | -5 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` - | - = note: `-D clippy::or-fun-call` implied by `-D warnings` + --> $DIR/unwrap_or.rs:15:47 + | +15 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` + | + = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:10:10 + --> $DIR/unwrap_or.rs:20:10 | -10 | .unwrap_or("Fail".to_string()) +20 | .unwrap_or("Fail".to_string()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 8d18d848ae0..784e0c04016 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::use_self)] diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index cf673e166d8..627fc3a97cb 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,123 +1,123 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:13:21 + --> $DIR/use_self.rs:23:21 | -13 | fn new() -> Foo { +23 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:13 + --> $DIR/use_self.rs:24:13 | -14 | Foo {} +24 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:16:22 + --> $DIR/use_self.rs:26:22 | -16 | fn test() -> Foo { +26 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:17:13 + --> $DIR/use_self.rs:27:13 | -17 | Foo::new() +27 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:22:25 + --> $DIR/use_self.rs:32:25 | -22 | fn default() -> Foo { +32 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:13 + --> $DIR/use_self.rs:33:13 | -23 | Foo::new() +33 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:86:22 + --> $DIR/use_self.rs:96:22 | -86 | fn refs(p1: &Bad) -> &Bad { +96 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:86:31 + --> $DIR/use_self.rs:96:31 | -86 | fn refs(p1: &Bad) -> &Bad { +96 | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:90:37 - | -90 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:100:37 + | +100 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:90:53 - | -90 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:100:53 + | +100 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:94:30 - | -94 | fn mut_refs(p1: &mut Bad) -> &mut Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:104:30 + | +104 | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:94:43 - | -94 | fn mut_refs(p1: &mut Bad) -> &mut Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:104:43 + | +104 | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:28 - | -98 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:108:28 + | +108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:46 - | -98 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:108:46 + | +108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:101:20 + --> $DIR/use_self.rs:111:20 | -101 | fn vals(_: Bad) -> Bad { +111 | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:101:28 + --> $DIR/use_self.rs:111:28 | -101 | fn vals(_: Bad) -> Bad { +111 | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:102:13 + --> $DIR/use_self.rs:112:13 | -102 | Bad::default() +112 | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:107:23 + --> $DIR/use_self.rs:117:23 | -107 | type Output = Bad; +117 | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:109:27 + --> $DIR/use_self.rs:119:27 | -109 | fn mul(self, rhs: Bad) -> Bad { +119 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:109:35 + --> $DIR/use_self.rs:119:35 | -109 | fn mul(self, rhs: Bad) -> Bad { +119 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: aborting due to 20 previous errors diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index c1e1c9af5db..13ae1d67f15 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::all)] diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index a1bb57a50a5..8092119470e 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -1,33 +1,33 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:17:5 + --> $DIR/used_underscore_binding.rs:27:5 | -17 | _foo + 1 +27 | _foo + 1 | ^^^^ | = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:22:20 + --> $DIR/used_underscore_binding.rs:32:20 | -22 | println!("{}", _foo); +32 | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:23:16 + --> $DIR/used_underscore_binding.rs:33:16 | -23 | assert_eq!(_foo, _foo); +33 | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:23:22 + --> $DIR/used_underscore_binding.rs:33:22 | -23 | assert_eq!(_foo, _foo); +33 | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:36:5 + --> $DIR/used_underscore_binding.rs:46:5 | -36 | s._underscore_field += 1; +46 | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 52994566e09..598618365c8 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![deny(clippy::useless_asref)] diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 6247fb27a79..8e45facf587 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,73 +1,73 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:33:18 + --> $DIR/useless_asref.rs:43:18 | -33 | foo_rstr(rstr.as_ref()); +43 | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here - --> $DIR/useless_asref.rs:3:9 + --> $DIR/useless_asref.rs:13:9 | -3 | #![deny(clippy::useless_asref)] +13 | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:35:20 + --> $DIR/useless_asref.rs:45:20 | -35 | foo_rslice(rslice.as_ref()); +45 | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:39:21 + --> $DIR/useless_asref.rs:49:21 | -39 | foo_mrslice(mrslice.as_mut()); +49 | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:41:20 + --> $DIR/useless_asref.rs:51:20 | -41 | foo_rslice(mrslice.as_ref()); +51 | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:48:20 + --> $DIR/useless_asref.rs:58:20 | -48 | foo_rslice(rrrrrslice.as_ref()); +58 | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:50:18 + --> $DIR/useless_asref.rs:60:18 | -50 | foo_rstr(rrrrrstr.as_ref()); +60 | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:55:21 + --> $DIR/useless_asref.rs:65:21 | -55 | foo_mrslice(mrrrrrslice.as_mut()); +65 | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:57:20 + --> $DIR/useless_asref.rs:67:20 | -57 | foo_rslice(mrrrrrslice.as_ref()); +67 | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:60:16 + --> $DIR/useless_asref.rs:70:16 | -60 | foo_rrrrmr((&&&&MoreRef).as_ref()); +70 | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:106:13 + --> $DIR/useless_asref.rs:116:13 | -106 | foo_mrt(mrt.as_mut()); +116 | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:108:12 + --> $DIR/useless_asref.rs:118:12 | -108 | foo_rt(mrt.as_ref()); +118 | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` error: aborting due to 11 previous errors diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 80d4ebcedba..710f35da72b 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index d498fe64ebf..4a27d1148b4 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,16 +1,16 @@ error: useless lint attribute - --> $DIR/useless_attribute.rs:5:1 - | -5 | #[allow(dead_code)] - | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` - | - = note: `-D clippy::useless-attribute` implied by `-D warnings` + --> $DIR/useless_attribute.rs:15:1 + | +15 | #[allow(dead_code)] + | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` + | + = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute - --> $DIR/useless_attribute.rs:6:1 - | -6 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code))` + --> $DIR/useless_attribute.rs:16:1 + | +16 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code))` error: aborting due to 2 previous errors diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 78a49f2580a..45e51663795 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index b9541e58c77..e4649eab5ec 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,39 +1,39 @@ error: useless use of `vec!` - --> $DIR/vec.rs:24:14 + --> $DIR/vec.rs:34:14 | -24 | on_slice(&vec![]); +34 | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` | = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:27:14 + --> $DIR/vec.rs:37:14 | -27 | on_slice(&vec![1, 2]); +37 | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:30:14 + --> $DIR/vec.rs:40:14 | -30 | on_slice(&vec ![1, 2]); +40 | on_slice(&vec ![1, 2]); | ^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:33:14 + --> $DIR/vec.rs:43:14 | -33 | on_slice(&vec!(1, 2)); +43 | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:36:14 + --> $DIR/vec.rs:46:14 | -36 | on_slice(&vec![1; 2]); +46 | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:49:14 + --> $DIR/vec.rs:59:14 | -49 | for a in vec![1, 2, 3] { +59 | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: aborting due to 6 previous errors diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 0b8691d57b4..ff7a43fd693 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index cc309e37946..b166e8bacb5 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -1,114 +1,114 @@ error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:9:5 + --> $DIR/while_loop.rs:19:5 | -9 | / loop { -10 | | if let Some(_x) = y { -11 | | let _v = 1; -12 | | } else { -13 | | break -14 | | } -15 | | } +19 | / loop { +20 | | if let Some(_x) = y { +21 | | let _v = 1; +22 | | } else { +23 | | break +24 | | } +25 | | } | |_____^ help: try: `while let Some(_x) = y { .. }` | = note: `-D clippy::while-let-loop` implied by `-D warnings` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:22:5 + --> $DIR/while_loop.rs:32:5 | -22 | / loop { -23 | | match y { -24 | | Some(_x) => true, -25 | | None => break -26 | | }; -27 | | } +32 | / loop { +33 | | match y { +34 | | Some(_x) => true, +35 | | None => break +36 | | }; +37 | | } | |_____^ help: try: `while let Some(_x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:28:5 + --> $DIR/while_loop.rs:38:5 | -28 | / loop { -29 | | let x = match y { -30 | | Some(x) => x, -31 | | None => break +38 | / loop { +39 | | let x = match y { +40 | | Some(x) => x, +41 | | None => break ... | -34 | | let _str = "foo"; -35 | | } +44 | | let _str = "foo"; +45 | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:36:5 + --> $DIR/while_loop.rs:46:5 | -36 | / loop { -37 | | let x = match y { -38 | | Some(x) => x, -39 | | None => break, +46 | / loop { +47 | | let x = match y { +48 | | Some(x) => x, +49 | | None => break, ... | -42 | | { let _b = "foobar"; } -43 | | } +52 | | { let _b = "foobar"; } +53 | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:58:5 + --> $DIR/while_loop.rs:68:5 | -58 | / loop { -59 | | let (e, l) = match "".split_whitespace().next() { -60 | | Some(word) => (word.is_empty(), word.len()), -61 | | None => break +68 | / loop { +69 | | let (e, l) = match "".split_whitespace().next() { +70 | | Some(word) => (word.is_empty(), word.len()), +71 | | None => break ... | -64 | | let _ = (e, l); -65 | | } +74 | | let _ = (e, l); +75 | | } | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:68:33 + --> $DIR/while_loop.rs:78:33 | -68 | while let Option::Some(x) = iter.next() { +78 | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` | = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:73:25 + --> $DIR/while_loop.rs:83:25 | -73 | while let Some(x) = iter.next() { +83 | while let Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:78:25 + --> $DIR/while_loop.rs:88:25 | -78 | while let Some(_) = iter.next() {} +88 | while let Some(_) = iter.next() {} | ^^^^^^^^^^^ help: try: `for _ in iter { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:118:5 + --> $DIR/while_loop.rs:128:5 | -118 | / loop { -119 | | let _ = match iter.next() { -120 | | Some(ele) => ele, -121 | | None => break -122 | | }; -123 | | loop {} -124 | | } +128 | / loop { +129 | | let _ = match iter.next() { +130 | | Some(ele) => ele, +131 | | None => break +132 | | }; +133 | | loop {} +134 | | } | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` error: empty `loop {}` detected. You may want to either use `panic!()` or add `std::thread::sleep(..);` to the loop body. - --> $DIR/while_loop.rs:123:9 + --> $DIR/while_loop.rs:133:9 | -123 | loop {} +133 | loop {} | ^^^^^^^ | = note: `-D clippy::empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:183:29 + --> $DIR/while_loop.rs:193:29 | -183 | while let Some(v) = y.next() { // use a for loop here +193 | while let Some(v) = y.next() { // use a for loop here | ^^^^^^^^ help: try: `for v in y { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:210:26 + --> $DIR/while_loop.rs:220:26 | -210 | while let Some(..) = values.iter().next() { +220 | while let Some(..) = values.iter().next() { | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` error: aborting due to 12 previous errors diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 5ef4c15f409..9a27ca11dae 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused_must_use)] diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 644f6f15b42..2aa66c32049 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,87 +1,87 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:29:79 + --> $DIR/write_literal.rs:39:79 | -29 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); +39 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::write-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/write_literal.rs:30:32 + --> $DIR/write_literal.rs:40:32 | -30 | write!(&mut v, "Hello {}", "world"); +40 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:31:44 + --> $DIR/write_literal.rs:41:44 | -31 | writeln!(&mut v, "Hello {} {}", world, "world"); +41 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:32:34 + --> $DIR/write_literal.rs:42:34 | -32 | writeln!(&mut v, "Hello {}", "world"); +42 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:33:38 + --> $DIR/write_literal.rs:43:38 | -33 | writeln!(&mut v, "10 / 4 is {}", 2.5); +43 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:34:36 + --> $DIR/write_literal.rs:44:36 | -34 | writeln!(&mut v, "2 + 1 = {}", 3); +44 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/write_literal.rs:39:33 + --> $DIR/write_literal.rs:49:33 | -39 | writeln!(&mut v, "{0} {1}", "hello", "world"); +49 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:39:42 + --> $DIR/write_literal.rs:49:42 | -39 | writeln!(&mut v, "{0} {1}", "hello", "world"); +49 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:40:33 + --> $DIR/write_literal.rs:50:33 | -40 | writeln!(&mut v, "{1} {0}", "hello", "world"); +50 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:40:42 + --> $DIR/write_literal.rs:50:42 | -40 | writeln!(&mut v, "{1} {0}", "hello", "world"); +50 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:43:41 + --> $DIR/write_literal.rs:53:41 | -43 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +53 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:43:54 + --> $DIR/write_literal.rs:53:54 | -43 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); +53 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:44:41 + --> $DIR/write_literal.rs:54:41 | -44 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +54 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:44:54 + --> $DIR/write_literal.rs:54:54 | -44 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); +54 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 58e6002fa6a..f3e26ed904f 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(clippy::write_literal)] diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index c8617b4939a..dd7f223c517 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,27 +1,27 @@ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:12:5 + --> $DIR/write_with_newline.rs:22:5 | -12 | write!(&mut v, "Hello/n"); +22 | write!(&mut v, "Hello/n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::write-with-newline` implied by `-D warnings` error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:13:5 + --> $DIR/write_with_newline.rs:23:5 | -13 | write!(&mut v, "Hello {}/n", "world"); +23 | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:14:5 + --> $DIR/write_with_newline.rs:24:5 | -14 | write!(&mut v, "Hello {} {}/n", "world", "#2"); +24 | write!(&mut v, "Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:15:5 + --> $DIR/write_with_newline.rs:25:5 | -15 | write!(&mut v, "{}/n", 1265); +25 | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 81dfdcdc0d0..888e870667c 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] #![allow(unused_must_use)] diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index ef1e9b3d36e..3e6ec33623a 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,15 +1,15 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:11:5 + --> $DIR/writeln_empty_string.rs:21:5 | -11 | writeln!(&mut v, ""); +21 | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` | = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:14:5 + --> $DIR/writeln_empty_string.rs:24:5 | -14 | writeln!(&mut suggestion, ""); +24 | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` error: aborting due to 2 previous errors diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 2fb33d08619..d843af1a396 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index 4a6e5e0ab22..ee0f4f8a143 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -1,75 +1,75 @@ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:21:17 + --> $DIR/wrong_self_convention.rs:31:17 | -21 | fn from_i32(self) {} +31 | fn from_i32(self) {} | ^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:27:21 + --> $DIR/wrong_self_convention.rs:37:21 | -27 | pub fn from_i64(self) {} +37 | pub fn from_i64(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:40:15 + --> $DIR/wrong_self_convention.rs:50:15 | -40 | fn as_i32(self) {} +50 | fn as_i32(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:42:17 + --> $DIR/wrong_self_convention.rs:52:17 | -42 | fn into_i32(&self) {} +52 | fn into_i32(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:44:15 + --> $DIR/wrong_self_convention.rs:54:15 | -44 | fn is_i32(self) {} +54 | fn is_i32(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:46:15 + --> $DIR/wrong_self_convention.rs:56:15 | -46 | fn to_i32(self) {} +56 | fn to_i32(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:48:17 + --> $DIR/wrong_self_convention.rs:58:17 | -48 | fn from_i32(self) {} +58 | fn from_i32(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:50:19 + --> $DIR/wrong_self_convention.rs:60:19 | -50 | pub fn as_i64(self) {} +60 | pub fn as_i64(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:51:21 + --> $DIR/wrong_self_convention.rs:61:21 | -51 | pub fn into_i64(&self) {} +61 | pub fn into_i64(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:52:19 + --> $DIR/wrong_self_convention.rs:62:19 | -52 | pub fn is_i64(self) {} +62 | pub fn is_i64(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:53:19 + --> $DIR/wrong_self_convention.rs:63:19 | -53 | pub fn to_i64(self) {} +63 | pub fn to_i64(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:54:21 + --> $DIR/wrong_self_convention.rs:64:21 | -54 | pub fn from_i64(self) {} +64 | pub fn from_i64(self) {} | ^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index 7927e8b8ac7..c2cbd32968f 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + #![feature(tool_lints)] diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index a5e86883d25..0c24a08a634 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -1,58 +1,58 @@ error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:7:15 - | -7 | let nan = 0.0 / 0.0; - | ^^^^^^^^^ - | - = note: #[deny(clippy::eq_op)] on by default + --> $DIR/zero_div_zero.rs:17:15 + | +17 | let nan = 0.0 / 0.0; + | ^^^^^^^^^ + | + = note: #[deny(clippy::eq_op)] on by default error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:7:15 - | -7 | let nan = 0.0 / 0.0; - | ^^^^^^^^^ - | - = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + --> $DIR/zero_div_zero.rs:17:15 + | +17 | let nan = 0.0 / 0.0; + | ^^^^^^^^^ + | + = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` + = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:8:19 - | -8 | let f64_nan = 0.0 / 0.0f64; - | ^^^^^^^^^^^^ + --> $DIR/zero_div_zero.rs:18:19 + | +18 | let f64_nan = 0.0 / 0.0f64; + | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:8:19 - | -8 | let f64_nan = 0.0 / 0.0f64; - | ^^^^^^^^^^^^ - | - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + --> $DIR/zero_div_zero.rs:18:19 + | +18 | let f64_nan = 0.0 / 0.0f64; + | ^^^^^^^^^^^^ + | + = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:9:25 - | -9 | let other_f64_nan = 0.0f64 / 0.0; - | ^^^^^^^^^^^^ + --> $DIR/zero_div_zero.rs:19:25 + | +19 | let other_f64_nan = 0.0f64 / 0.0; + | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:9:25 - | -9 | let other_f64_nan = 0.0f64 / 0.0; - | ^^^^^^^^^^^^ - | - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + --> $DIR/zero_div_zero.rs:19:25 + | +19 | let other_f64_nan = 0.0f64 / 0.0; + | ^^^^^^^^^^^^ + | + = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:10:28 + --> $DIR/zero_div_zero.rs:20:28 | -10 | let one_more_f64_nan = 0.0f64/0.0f64; +20 | let one_more_f64_nan = 0.0f64/0.0f64; | ^^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:10:28 + --> $DIR/zero_div_zero.rs:20:28 | -10 | let one_more_f64_nan = 0.0f64/0.0f64; +20 | let one_more_f64_nan = 0.0f64/0.0f64; | ^^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index 4a6010f4bd0..fbe4f950da5 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index b5e279eaa3a..7a0c8e70b22 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -1,16 +1,16 @@ error: `0 as *const _` detected. Consider using `ptr::null()` - --> $DIR/zero_ptr.rs:6:13 - | -6 | let x = 0 as *const usize; - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::zero-ptr` implied by `-D warnings` + --> $DIR/zero_ptr.rs:16:13 + | +16 | let x = 0 as *const usize; + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::zero-ptr` implied by `-D warnings` error: `0 as *mut _` detected. Consider using `ptr::null_mut()` - --> $DIR/zero_ptr.rs:7:13 - | -7 | let y = 0 as *mut f64; - | ^^^^^^^^^^^^^ + --> $DIR/zero_ptr.rs:17:13 + | +17 | let y = 0 as *mut f64; + | ^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 25b0ceefae7..5b189a797b7 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -1,3 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + extern crate cargo_metadata; extern crate semver; use semver::VersionReq; -- cgit 1.4.1-3-g733a5 From 23e5e24f52c433be9636d1955e68f61e26beb9dc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 6 Oct 2018 09:23:54 -0700 Subject: Add license header to other files --- .github/deploy.sh | 12 ++++++++++++ ci/base-tests.sh | 11 +++++++++++ ci/integration-tests.sh | 10 ++++++++++ pre_publish.sh | 11 +++++++++++ util/cov.sh | 11 +++++++++++ util/export.py | 12 ++++++++++++ util/lintlib.py | 10 ++++++++++ util/update_lints.py | 12 ++++++++++++ 8 files changed, 89 insertions(+) diff --git a/.github/deploy.sh b/.github/deploy.sh index 1d206e61167..11d0b2d2a85 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -1,4 +1,16 @@ #!/bin/bash + +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + # Automatically deploy on gh-pages set -ex diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 2358c8fe2ed..ebf4a127cdc 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,3 +1,14 @@ +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + set -ex echo "Running clippy base tests" diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 18b91f6eae0..9019a6830e6 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,3 +1,13 @@ +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + set -x rm ~/.cargo/bin/cargo-clippy cargo install --force --path . diff --git a/pre_publish.sh b/pre_publish.sh index 3602f671e3d..fc7ae212fcf 100755 --- a/pre_publish.sh +++ b/pre_publish.sh @@ -1,5 +1,16 @@ #!/bin/bash +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + set -e ./util/update_lints.py diff --git a/util/cov.sh b/util/cov.sh index 3f9a6b06f72..d927a5cfcd0 100755 --- a/util/cov.sh +++ b/util/cov.sh @@ -1,5 +1,16 @@ #!/usr/bin/bash +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + # This run `kcov` on Clippy. The coverage report will be at # `./target/cov/index.html`. # `compile-test` is special. `kcov` does not work directly on it so these files diff --git a/util/export.py b/util/export.py index 5419624d48e..d8598ed8037 100755 --- a/util/export.py +++ b/util/export.py @@ -1,4 +1,16 @@ #!/usr/bin/env python + +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + # Build the gh-pages import re diff --git a/util/lintlib.py b/util/lintlib.py index c386a94b18b..61090abc138 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -1,3 +1,13 @@ +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + # Common utils for the several housekeeping scripts. import os diff --git a/util/update_lints.py b/util/update_lints.py index b34dad73f70..2e1bd98050d 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -1,4 +1,16 @@ #!/usr/bin/env python + +# Copyright 2014-2018 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + + # Generate a Markdown table of all lints, and put it in README.md. # With -n option, only print the new table to stdout. # With -c option, print a warning and set exit status to 1 if a file would be -- cgit 1.4.1-3-g733a5 From 31bc2827f80a3ea7a12bad53fc43c19c565be57d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 6 Oct 2018 10:20:48 -0700 Subject: additional people --- etc/relicense/RELICENSE_DOCUMENTATION.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/etc/relicense/RELICENSE_DOCUMENTATION.md b/etc/relicense/RELICENSE_DOCUMENTATION.md index b40f748e9d0..5abe8b694a3 100644 --- a/etc/relicense/RELICENSE_DOCUMENTATION.md +++ b/etc/relicense/RELICENSE_DOCUMENTATION.md @@ -31,3 +31,6 @@ Two of these contributors had nonminor contributions (#2184, #427) requiring a r First, I (Manishearth) removed the lints they had added. I then documented at a high level what the lints did in #3251, asking for co-maintainers who had not seen the code for the lints to rewrite them. #2814 was rewritten by @phansch, and #427 was rewritten by @oli-obk, who did not recall having previously seen the code they were rewriting. +------ + +Since this document was written, @JayKickliter and @sanmai-ML added their consent in #3230 ([archive](http://web.archive.org/web/20181006171926/https://github.com/rust-lang-nursery/rust-clippy/issues/3230)) \ No newline at end of file -- cgit 1.4.1-3-g733a5 From d129d049c6ef259630c862eb0ecd322452814d1b Mon Sep 17 00:00:00 2001 From: Dylan Maccora Date: Sun, 7 Oct 2018 11:24:09 +1100 Subject: Adding more detail to filter_map lint documentation. --- clippy_lints/src/methods/mod.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 30c82e3969f..d49a05f5186 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -706,8 +706,11 @@ declare_clippy_lint! { /// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`. +/// More specifically it checks if the closure provided is only performing one of the +/// filter or map operations and suggests the appropriate option. /// -/// **Why is this bad?** Complexity +/// **Why is this bad?** Complexity. The intent is also clearer if only a single +/// operation is being performed. /// /// **Known problems:** None /// @@ -715,10 +718,18 @@ declare_clippy_lint! { /// ```rust /// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None }); /// ``` -/// This could be written as: +/// As there is no transformation of the argument this could be written as: /// ```rust /// let _ = (0..3).filter(|&x| x > 2); /// ``` +/// +/// ```rust +/// let _ = (0..4).filter_map(i32::checked_abs); +/// ``` +/// As there is no conditional check on the argument this could be written as: +/// ```rust +/// let _ = (0..4).map(i32::checked_abs); +/// ``` declare_clippy_lint! { pub UNNECESSARY_FILTER_MAP, complexity, -- cgit 1.4.1-3-g733a5 From 492d6852e5bd04c1a8df74077a1e11d0e5baff2e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 6 Oct 2018 19:29:01 -0700 Subject: Add license to README --- COPYRIGHT | 2 +- README.md | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index a7112226318..cb9970597a2 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 2018 The Rust Project Developers +Copyright 2014-2018 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/README.md b/README.md index e429454cf28..9dd41f6513c 100644 --- a/README.md +++ b/README.md @@ -149,5 +149,10 @@ If you do not want to include your lint levels in your code, you can globally en ## License -Licensed under [MPL](https://www.mozilla.org/MPL/2.0/). -If you're having issues with the license, let me know and I'll try to change it to something more permissive. +Copyright 2014-2018 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 or the MIT license +, at your +option. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. -- cgit 1.4.1-3-g733a5 From e1d7f00e430aa253cf686d3330d1408620977443 Mon Sep 17 00:00:00 2001 From: Daniele D'Orazio Date: Sat, 6 Oct 2018 20:07:41 +0200 Subject: fix command to manually test an example --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1341ca30ebd..c4080a5fa9c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -149,8 +149,8 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running Manually testing against an example file is useful if you have added some `println!`s and test suite output becomes unreadable. To try Clippy with your -local modifications, run `cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the -working copy root. +local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` +from the working copy root. ### How Clippy works -- cgit 1.4.1-3-g733a5 From 59c4ff77f10deab8ff216f5019acf5a60ad77447 Mon Sep 17 00:00:00 2001 From: Daniele D'Orazio Date: Sun, 7 Oct 2018 12:39:54 +0200 Subject: new_without_default should not warn about unsafe new --- clippy_lints/src/new_without_default.rs | 4 ++++ tests/ui/new_without_default.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 9f2d29a1b63..865b1c987c8 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -116,6 +116,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } + if sig.header.unsafety == hir::Unsafety::Unsafe { + // can't be implemented for unsafe new + return; + } if impl_item.generics.params.iter().any(|gen| match gen.kind { hir::GenericParamKind::Type { .. } => true, _ => false diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 46d2bc45f68..7fa369354b3 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -101,4 +101,10 @@ pub trait TraitWithNew: Sized { } } +pub struct IgnoreUnsafeNew; + +impl IgnoreUnsafeNew { + pub unsafe fn new() -> Self { IgnoreUnsafeNew } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From d365742bc62f78b00275504229bdbe8b88e3db3e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 7 Oct 2018 12:18:40 +0200 Subject: Fix FP in `fn_to_numeric_cast_with_truncation` We only want this lint to check casts to numeric, as per the lint title. Rust already has a built-in check for all other casts [here][rust_check]. [rust_check]: https://github.com/rust-lang/rust/blob/5472b0718f286266ab89acdf234c3552de7e973c/src/librustc_typeck/check/cast.rs#L430-L433 --- clippy_lints/src/types.rs | 5 ++++ tests/ui/fn_to_numeric_cast.rs | 4 ++++ tests/ui/fn_to_numeric_cast.stderr | 48 +++++++++++++++++++------------------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 24b895b23a6..f43b1fe7abe 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1088,6 +1088,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { + // We only want to check casts to `ty::Uint` or `ty::Int` + match cast_to.sty { + ty::Uint(_) | ty::Int(..) => { /* continue on */ }, + _ => return + } match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { let from_snippet = snippet(cx, cast_expr.span, "x"); diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 0066b9a3587..9bd0ad7687f 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -31,6 +31,10 @@ fn test_function_to_numeric_cast() { // Casting to usize is OK and should not warn let _ = foo as usize; + + // Cast `f` (a `FnDef`) to `fn()` should not warn + fn f() {} + let _ = f as fn(); } fn test_function_var_to_numeric_cast() { diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index 2e186145eae..27eeb909154 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -69,75 +69,75 @@ error: casting function pointer `foo` to `u128` | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:39:13 + --> $DIR/fn_to_numeric_cast.rs:43:13 | -39 | let _ = abc as i8; +43 | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:40:13 + --> $DIR/fn_to_numeric_cast.rs:44:13 | -40 | let _ = abc as i16; +44 | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:41:13 + --> $DIR/fn_to_numeric_cast.rs:45:13 | -41 | let _ = abc as i32; +45 | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> $DIR/fn_to_numeric_cast.rs:42:13 + --> $DIR/fn_to_numeric_cast.rs:46:13 | -42 | let _ = abc as i64; +46 | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> $DIR/fn_to_numeric_cast.rs:43:13 + --> $DIR/fn_to_numeric_cast.rs:47:13 | -43 | let _ = abc as i128; +47 | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> $DIR/fn_to_numeric_cast.rs:44:13 + --> $DIR/fn_to_numeric_cast.rs:48:13 | -44 | let _ = abc as isize; +48 | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:46:13 + --> $DIR/fn_to_numeric_cast.rs:50:13 | -46 | let _ = abc as u8; +50 | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:47:13 + --> $DIR/fn_to_numeric_cast.rs:51:13 | -47 | let _ = abc as u16; +51 | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:48:13 + --> $DIR/fn_to_numeric_cast.rs:52:13 | -48 | let _ = abc as u32; +52 | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> $DIR/fn_to_numeric_cast.rs:49:13 + --> $DIR/fn_to_numeric_cast.rs:53:13 | -49 | let _ = abc as u64; +53 | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> $DIR/fn_to_numeric_cast.rs:50:13 + --> $DIR/fn_to_numeric_cast.rs:54:13 | -50 | let _ = abc as u128; +54 | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:57:5 + --> $DIR/fn_to_numeric_cast.rs:61:5 | -57 | f as i32 +61 | f as i32 | ^^^^^^^^ help: try: `f as usize` error: aborting due to 23 previous errors -- cgit 1.4.1-3-g733a5 From 8a77a25b8a4020577476056b5741fccb87be587e Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 7 Oct 2018 11:38:20 -0700 Subject: Fix excessive_precision false positive --- clippy_lints/src/excessive_precision.rs | 6 +++--- tests/ui/excessive_precision.rs | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 9f8224cd2f0..99668880f72 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -136,10 +136,10 @@ fn max_digits(fty: FloatTy) -> u32 { /// Counts the digits excluding leading zeros fn count_digits(s: &str) -> usize { - // Note that s does not contain the f32/64 suffix + // Note that s does not contain the f32/64 suffix, and underscores have been stripped s.chars() - .filter(|c| *c != '-' || *c != '.') - .take_while(|c| *c != 'e' || *c != 'E') + .filter(|c| *c != '-' && *c != '.') + .take_while(|c| *c != 'e' && *c != 'E') .fold(0, |count, c| { // leading zeros if c == '0' && count == 0 { diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index ab0412a16b5..abfdb0b3da1 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -67,4 +67,7 @@ fn main() { // Inferred type let good_inferred: f32 = 1f32 * 1_000_000_000.; + + // issue #2840 + let num = 0.000_000_000_01e-10f64; } -- cgit 1.4.1-3-g733a5 From 9bd4e5469e1ecb7d98602ba1d805872faa8bf2c9 Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Mon, 8 Oct 2018 06:20:32 +1100 Subject: Don't suggest cloned() for map Box deref Boxes are a bit magic in that they need to use `*` to get an owned value out of the box. They implement `Deref` but that only returns a reference. This means an easy way to convert an `Option>` to an `` is: ``` box_option.map(|b| *b) ``` However, since b36bb0a6 the `map_clone` lint is detecting this as an attempt to copy the box. Fix by excluding boxes completely from the deref part of this lint. Fixes #3274 --- clippy_lints/src/map_clone.rs | 2 +- tests/ui/map_clone.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index c2bfcf18280..b2c08e6ae8c 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint(cx, e.span, args[0].span, name, closure_expr); }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { - hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => lint(cx, e.span, args[0].span, name, inner), + hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) if !cx.tables.expr_ty(inner).is_box() => lint(cx, e.span, args[0].span, name, inner), hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { lint(cx, e.span, args[0].span, name, &obj[0]); } diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 8a410737f83..90611023f75 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -16,4 +16,5 @@ fn main() { let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); + let _: Option = Some(Box::new(16)).map(|b| *b); } -- cgit 1.4.1-3-g733a5 From 6528749083bb64a28aca6a8be2bf67458ce62147 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sun, 7 Oct 2018 17:05:28 -0700 Subject: Fix items_after_statements for `use` statements --- clippy_lints/src/consts.rs | 4 +++- clippy_lints/src/write.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 4e09e039100..3cf38440744 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -265,6 +265,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// lookup a possibly constant expression from a ExprKind::Path fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { + use crate::rustc::mir::interpret::GlobalId; + let def = self.tables.qpath_def(qpath, id); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { @@ -279,7 +281,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { instance, promoted: None, }; - use crate::rustc::mir::interpret::GlobalId; + let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; let ret = miri_to_const(self.tcx, result); if ret.is_some() { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index a367a04b2ba..06575a264b3 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -246,6 +246,7 @@ impl EarlyLintPass for Pass { } fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { + use crate::fmt_macros::*; let tts = TokenStream::from(tts.clone()); let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false); let mut expr: Option = None; @@ -264,7 +265,6 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - Ok(token) => token.0.to_string(), Err(_) => return (None, expr), }; - use crate::fmt_macros::*; let tmp = fmtstr.clone(); let mut args = vec![]; let mut fmt_parser = Parser::new(&tmp, None); -- cgit 1.4.1-3-g733a5 From be983fbf52c581bfa51e8b5dd95fb9f599a67639 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sun, 7 Oct 2018 17:07:10 -0700 Subject: Fix items_after_statements for sub-functions --- clippy_lints/src/methods/mod.rs | 40 ++++++++++++++++++++-------------------- clippy_lints/src/utils/higher.rs | 16 ++++++++-------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e0d858bd270..01cd6f25832 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1081,18 +1081,6 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: arg: &hir::Expr, span: Span, ) { - if name != "expect" { - return; - } - - let self_type = cx.tables.expr_ty(self_expr); - let known_types = &[&paths::OPTION, &paths::RESULT]; - - // if not a known type, return early - if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { - return; - } - fn is_call(node: &hir::ExprKind) -> bool { match node { hir::ExprKind::AddrOf(_, expr) => { @@ -1107,6 +1095,18 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: } } + if name != "expect" { + return; + } + + let self_type = cx.tables.expr_ty(self_expr); + let known_types = &[&paths::OPTION, &paths::RESULT]; + + // if not a known type, return early + if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { + return; + } + if !is_call(&arg.node) { return; } @@ -1338,14 +1338,6 @@ fn lint_iter_cloned_collect(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_arg } fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: &[hir::Expr]) { - // Check that this is a call to Iterator::fold rather than just some function called fold - if !match_trait_method(cx, expr, &paths::ITERATOR) { - return; - } - - assert!(fold_args.len() == 3, - "Expected fold_args to have three entries - the receiver, the initial value and the closure"); - fn check_fold_with_op( cx: &LateContext<'_, '_>, fold_args: &[hir::Expr], @@ -1402,6 +1394,14 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: } } + // Check that this is a call to Iterator::fold rather than just some function called fold + if !match_trait_method(cx, expr, &paths::ITERATOR) { + return; + } + + assert!(fold_args.len() == 3, + "Expected fold_args to have three entries - the receiver, the initial value and the closure"); + // Check if the first argument to .fold is a suitable literal match fold_args[1].node { hir::ExprKind::Lit(ref lit) => { diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index cfedad49f31..88c875c3102 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -46,6 +46,14 @@ pub struct Range<'a> { /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option> { + /// Find the field named `name` in the field. Always return `Some` for + /// convenience. + fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { + let expr = &fields.iter().find(|field| field.ident.name == name)?.expr; + + Some(expr) + } + let def_path = match cx.tables.expr_ty(expr).sty { ty::Adt(def, _) => cx.tcx.def_path(def.did), @@ -75,14 +83,6 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O return None; } - /// Find the field named `name` in the field. Always return `Some` for - /// convenience. - fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { - let expr = &fields.iter().find(|field| field.ident.name == name)?.expr; - - Some(expr) - } - // The range syntax is expanded to literal paths starting with `core` or `std` // depending on // `#[no_std]`. Testing both instead of resolving the paths. -- cgit 1.4.1-3-g733a5 From 82638e4dd42274dd1c644197b9dc821aa3409c97 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Sun, 7 Oct 2018 17:08:20 -0700 Subject: Fix items_after_statements for `const`s --- clippy_lints/src/write.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 06575a264b3..1fa7c50bb9b 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -283,13 +283,6 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL }; let mut idx = 0; loop { - if !parser.eat(&token::Comma) { - return (Some(fmtstr), expr); - } - let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { - Ok(expr) => expr, - Err(_) => return (Some(fmtstr), None), - }; const SIMPLE: FormatSpec<'_> = FormatSpec { fill: None, align: AlignUnknown, @@ -298,6 +291,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - width: CountImplied, ty: "", }; + if !parser.eat(&token::Comma) { + return (Some(fmtstr), expr); + } + let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { + Ok(expr) => expr, + Err(_) => return (Some(fmtstr), None), + }; match &token_expr.node { ExprKind::Lit(_) => { let mut all_simple = true; -- cgit 1.4.1-3-g733a5 From 1ef32e4096bb813edee300a5fa89c355959ed878 Mon Sep 17 00:00:00 2001 From: Rotem Yaari Date: Mon, 8 Oct 2018 11:43:13 +0300 Subject: Improve diagnostics in case of lifetime elision (closes #3284) --- clippy_lints/src/lifetimes.rs | 2 +- tests/ui/lifetimes.rs | 6 ++++++ tests/ui/lifetimes.stderr | 36 +++++++++++++++++++++--------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index d1cf0da876b..81d37404d77 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -152,7 +152,7 @@ fn check_fn_inner<'a, 'tcx>( cx, NEEDLESS_LIFETIMES, span, - "explicit lifetimes given in parameter types where they could be elided", + "explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)", ); } report_extra_lifetimes(cx, decl, generics); diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index cae18498779..c7ed303b43b 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -170,5 +170,11 @@ fn test<'a>(x: &'a [u8]) -> u8 { *y } +// #3284 - Give a hint regarding lifetime in return type + +struct Cow<'a> { x: &'a str, } +fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { unimplemented!() } + + fn main() { } diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 9e4fac1e4f2..46dbf6cce09 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -1,4 +1,4 @@ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:17:1 | 17 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } @@ -6,37 +6,37 @@ error: explicit lifetimes given in parameter types where they could be elided | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:19:1 | 19 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:27:1 | 27 | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:39:1 | 39 | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:42:1 | 42 | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:48:1 | 48 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:62:1 | 62 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> @@ -44,47 +44,53 @@ error: explicit lifetimes given in parameter types where they could be elided 64 | | { unreachable!() } | |__________________^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:87:5 | 87 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:91:5 | 91 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:107:1 | 107 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:127:1 | 127 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:131:1 | 131 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:142:1 | 142 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:146:1 | 146 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) + --> $DIR/lifetimes.rs:176:1 + | +176 | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors -- cgit 1.4.1-3-g733a5 From a578cb2d62d4ff1ddbf9034d2924e1a68f55723c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 28 Sep 2018 21:09:57 +0200 Subject: if_let_redundant_pattern_matching: use Span.to() instead of Span.with_hi() to fix crash. Fixes #3064 --- .../src/if_let_redundant_pattern_matching.rs | 2 +- tests/ui/if_let_redundant_pattern_matching.stderr | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 4ee8d9f0ca7..8b42eaa528e 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { arms[0].pats[0].span, &format!("redundant pattern matching, consider using `{}`", good_method), |db| { - let span = expr.span.with_hi(op.span.hi()); + let span = expr.span.to(op.span); db.span_suggestion_with_applicability( span, "try this", diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index 00eb7885540..5111de67189 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -2,27 +2,33 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/if_let_redundant_pattern_matching.rs:19:12 | 19 | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` | = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` --> $DIR/if_let_redundant_pattern_matching.rs:21:12 | -21 | if let Err(_) = Err::(42) { - | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` +21 | if let Err(_) = Err::(42) { + | _____- ^^^^^^ +22 | | } + | |_____- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_none()` --> $DIR/if_let_redundant_pattern_matching.rs:24:12 | -24 | if let None = None::<()> { - | -------^^^^------------- help: try this: `if None::<()>.is_none()` +24 | if let None = None::<()> { + | _____- ^^^^ +25 | | } + | |_____- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/if_let_redundant_pattern_matching.rs:27:12 | -27 | if let Some(_) = Some(42) { - | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` +27 | if let Some(_) = Some(42) { + | _____- ^^^^^^^ +28 | | } + | |_____- help: try this: `if Some(42).is_some()` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From ad5c29a445692c0c074ee1f019fe1ff2056da23f Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Mon, 8 Oct 2018 19:04:29 -0700 Subject: Fixes #2925 cmp_owned false positive --- clippy_lints/src/misc.rs | 26 ++++++++++++++------------ tests/ui/cmp_owned.rs | 4 ++++ tests/ui/cmp_owned.stderr | 12 +++++++++--- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a83fa75de69..4e6d5b72efc 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -334,11 +334,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; db.span_suggestion_with_applicability( - s.span, + s.span, "replace it with", format!( "if {} {{ {}; }}", - sugg, + sugg, &snippet(cx, b.span, ".."), ), Applicability::MachineApplicable, // snippet @@ -520,16 +520,17 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { None => return, }; - // *arg impls PartialEq - if !arg_ty + let deref_arg_impl_partial_eq_other = arg_ty .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])) - // arg impls PartialEq<*other> - && !other_ty + .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])); + let arg_impl_partial_eq_deref_other = other_ty .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])) - // arg impls PartialEq - && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]) + .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])); + let arg_impl_partial_eq_other = implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]); + + if !deref_arg_impl_partial_eq_other + && !arg_impl_partial_eq_deref_other + && !arg_impl_partial_eq_other { return; } @@ -559,10 +560,11 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } } } + let try_hint = if deref_arg_impl_partial_eq_other { format!("*{}", snip) } else { snip.to_string() }; db.span_suggestion_with_applicability( - expr.span, + expr.span, "try", - snip.to_string(), + try_hint, Applicability::MachineApplicable, // snippet ); }, diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index e937afc1a81..031809f5df5 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -31,6 +31,10 @@ fn main() { 42.to_string() == "42"; Foo.to_owned() == Foo; + + "abc".chars().filter(|c| c.to_owned() != 'X'); + + "abc".chars().filter(|c| *c != 'X'); } struct Foo; diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 020ffe805cd..5434b68de9f 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -31,10 +31,16 @@ error: this creates an owned instance just for comparison | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:40:9 + --> $DIR/cmp_owned.rs:35:30 | -40 | self.to_owned() == *other +35 | "abc".chars().filter(|c| c.to_owned() != 'X'); + | ^^^^^^^^^^^^ help: try: `*c` + +error: this creates an owned instance just for comparison + --> $DIR/cmp_owned.rs:44:9 + | +44 | self.to_owned() == *other | ^^^^^^^^^^^^^^^ try calling implementing the comparison without allocating -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From eef2e8948b4f0de21669231933739ef0d0f0017a Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Mon, 8 Oct 2018 21:40:21 -0700 Subject: Fix cast_possible_truncation warnings --- clippy_lints/src/consts.rs | 27 ++++++++++++++++++++------- clippy_lints/src/lib.rs | 1 + clippy_lints/src/regex.rs | 19 +++++++++++++++++-- clippy_lints/src/utils/sugg.rs | 3 ++- src/driver.rs | 4 +++- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 2422e8e8a10..b84430e6819 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -18,6 +18,7 @@ use crate::rustc::ty::{self, Ty, TyCtxt, Instance}; use crate::rustc::ty::subst::{Subst, Substs}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; +use std::convert::TryInto; use std::hash::{Hash, Hasher}; use std::mem; use std::rc::Rc; @@ -341,8 +342,12 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BinOpKind::Mul => l.checked_mul(r).map(zext), BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), - BinOpKind::Shr => l.checked_shr(r as u128 as u32).map(zext), - BinOpKind::Shl => l.checked_shl(r as u128 as u32).map(zext), + BinOpKind::Shr => l.checked_shr( + (r as u128).try_into().expect("shift too large") + ).map(zext), + BinOpKind::Shl => l.checked_shl( + (r as u128).try_into().expect("shift too large") + ).map(zext), BinOpKind::BitXor => Some(zext(l ^ r)), BinOpKind::BitOr => Some(zext(l | r)), BinOpKind::BitAnd => Some(zext(l & r)), @@ -362,8 +367,12 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BinOpKind::Mul => l.checked_mul(r).map(Constant::Int), BinOpKind::Div => l.checked_div(r).map(Constant::Int), BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), - BinOpKind::Shr => l.checked_shr(r as u32).map(Constant::Int), - BinOpKind::Shl => l.checked_shl(r as u32).map(Constant::Int), + BinOpKind::Shr => l.checked_shr( + r.try_into().expect("shift too large") + ).map(Constant::Int), + BinOpKind::Shl => l.checked_shl( + r.try_into().expect("shift too large") + ).map(Constant::Int), BinOpKind::BitXor => Some(Constant::Int(l ^ r)), BinOpKind::BitOr => Some(Constant::Int(l | r)), BinOpKind::BitAnd => Some(Constant::Int(l & r)), @@ -426,8 +435,12 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { ty::Bool => Some(Constant::Bool(b == 1)), ty::Uint(_) | ty::Int(_) => Some(Constant::Int(b)), - ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))), - ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(b as u64))), + ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( + b.try_into().expect("invalid f32 bit representation") + ))), + ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( + b.try_into().expect("invalid f64 bit representation") + ))), // FIXME: implement other conversion _ => None, }, @@ -439,7 +452,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' .alloc_map .lock() .unwrap_memory(ptr.alloc_id); - let offset = ptr.offset.bytes() as usize; + let offset = ptr.offset.bytes().try_into().expect("too-large pointer offset"); let n = n as usize; String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str) }, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e4ad9fe9ca1..af69a6284f3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -21,6 +21,7 @@ #![feature(tool_lints)] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] +#![feature(try_from)] // FIXME: switch to something more ergonomic here, once available. // (currently there is no way to opt into sysroot crates w/o `extern crate`) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 7a818c41fff..deb32e49a0d 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -18,6 +18,7 @@ use crate::syntax::ast::{LitKind, NodeId, StrStyle}; use crate::syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; use crate::consts::{constant, Constant}; +use std::convert::TryInto; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -143,8 +144,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { let offset = u32::from(offset); - let end = base.lo() + BytePos(c.end.offset as u32 + offset); - let start = base.lo() + BytePos(c.start.offset as u32 + offset); + let end = base.lo() + BytePos( + c.end + .offset + .try_into() + .ok() + .and_then(|o: u32| o.checked_add(offset)) + .expect("offset too large"), + ); + let start = base.lo() + BytePos( + c.start + .offset + .try_into() + .ok() + .and_then(|o: u32| o.checked_add(offset)) + .expect("offset too large"), + ); assert!(start <= end); Span::new(start, end, base.ctxt()) } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index fecfc0c0789..eb67838f1d1 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -16,6 +16,7 @@ use crate::rustc::hir; use crate::rustc::lint::{EarlyContext, LateContext, LintContext}; use crate::rustc_errors; use std::borrow::Cow; +use std::convert::TryInto; use std::fmt::Display; use std; use crate::syntax::source_map::{CharPos, Span}; @@ -551,7 +552,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); if let Some(non_whitespace_offset) = non_whitespace_offset { - remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset as u32)) + remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large"))) } } diff --git a/src/driver.rs b/src/driver.rs index d2ed3cb1c26..0619b3ae0d9 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] #![feature(tool_lints)] +#![feature(try_from)] #![allow(unknown_lints, clippy::missing_docs_in_private_items)] // FIXME: switch to something more ergonomic here, once available. @@ -22,6 +23,7 @@ extern crate rustc_driver; extern crate rustc_plugin; use self::rustc_driver::{driver::CompileController, Compilation}; +use std::convert::TryInto; use std::path::Path; use std::process::{exit, Command}; @@ -153,5 +155,5 @@ pub fn main() { let args = args; rustc_driver::run_compiler(&args, Box::new(controller), None, None) - }) as i32) + }).try_into().expect("exit code too large")) } -- cgit 1.4.1-3-g733a5 From 2b9abc5daa67120e9b8b711885b71a4c63399921 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Mon, 8 Oct 2018 22:34:10 -0700 Subject: Fix cast_possible_wrap and cast_sign_loss warnings --- clippy_lints/src/consts.rs | 5 +++-- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index b84430e6819..5d509ef76f3 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -230,6 +230,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } + #[allow(clippy::cast_possible_wrap)] fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option { use self::Constant::*; match *o { @@ -343,10 +344,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), BinOpKind::Shr => l.checked_shr( - (r as u128).try_into().expect("shift too large") + r.try_into().expect("invalid shift") ).map(zext), BinOpKind::Shl => l.checked_shl( - (r as u128).try_into().expect("shift too large") + r.try_into().expect("invalid shift") ).map(zext), BinOpKind::BitXor => Some(zext(l ^ r)), BinOpKind::BitOr => Some(zext(l | r)), diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 8fba45de8ce..313175aee84 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -53,7 +53,7 @@ impl LintPass for UnportableVariant { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7282e5064c3..2a9b1cb0a10 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -971,12 +971,14 @@ pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 { layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() } +#[allow(clippy::cast_possible_wrap)] /// Turn a constant int byte representation into an i128 pub fn sext(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } +#[allow(clippy::cast_sign_loss)] /// clip unused bytes pub fn unsext(tcx: TyCtxt<'_, '_, '_>, u: i128, ity: ast::IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); -- cgit 1.4.1-3-g733a5 From b0d7aea946e88e87af136fb0fe5c4a7e87b6c16e Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 9 Oct 2018 19:25:03 -0700 Subject: Fixes 3289, cmp_owned wording and false positive --- clippy_lints/src/misc.rs | 26 ++++++++++++++++++++++---- tests/ui/cmp_owned.rs | 15 +++++++++++++++ tests/ui/cmp_owned.stderr | 14 ++++++++++---- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 4e6d5b72efc..4c6a9d6bd11 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -535,10 +535,29 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { return; } + let other_gets_derefed = match other.node { + ExprKind::Unary(UnDeref, _) => true, + _ => false, + }; + + let (lint_span, try_hint) = if deref_arg_impl_partial_eq_other { + // suggest deref on the left + (expr.span, format!("*{}", snip)) + } else if other_gets_derefed { + // suggest dropping the to_owned on the left and the deref on the right + let other_snippet = snippet(cx, other.span, "..").into_owned(); + let other_without_deref = other_snippet.trim_left_matches("*"); + + (expr.span.to(other.span), format!("{} == {}", snip.to_string(), other_without_deref)) + } else { + // suggest dropping the to_owned on the left + (expr.span, snip.to_string()) + }; + span_lint_and_then( cx, CMP_OWNED, - expr.span, + lint_span, "this creates an owned instance just for comparison", |db| { // this is as good as our recursion check can get, we can't prove that the @@ -554,15 +573,14 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise // we go into // recursion - db.span_label(expr.span, "try calling implementing the comparison without allocating"); + db.span_label(lint_span, "try implementing the comparison without allocating"); return; } } } } - let try_hint = if deref_arg_impl_partial_eq_other { format!("*{}", snip) } else { snip.to_string() }; db.span_suggestion_with_applicability( - expr.span, + lint_span, "try", try_hint, Applicability::MachineApplicable, // snippet diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 031809f5df5..65351cd9b9d 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -35,6 +35,11 @@ fn main() { "abc".chars().filter(|c| c.to_owned() != 'X'); "abc".chars().filter(|c| *c != 'X'); + + let x = &Baz; + let y = &Baz; + + y.to_owned() == *x; } struct Foo; @@ -67,3 +72,13 @@ impl std::borrow::Borrow for Bar { &FOO } } + +#[derive(PartialEq)] +struct Baz; + +impl ToOwned for Baz { + type Owned = Baz; + fn to_owned(&self) -> Baz { + Baz + } +} diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 5434b68de9f..2613d3b7500 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -37,10 +37,16 @@ error: this creates an owned instance just for comparison | ^^^^^^^^^^^^ help: try: `*c` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:44:9 + --> $DIR/cmp_owned.rs:42:5 | -44 | self.to_owned() == *other - | ^^^^^^^^^^^^^^^ try calling implementing the comparison without allocating +42 | y.to_owned() == *x; + | ^^^^^^^^^^^^^^^^^^ help: try: `y == x` -error: aborting due to 7 previous errors +error: this creates an owned instance just for comparison + --> $DIR/cmp_owned.rs:49:9 + | +49 | self.to_owned() == *other + | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 88ee209a1d2596efa1582cb7f993aca4308bf1c7 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 9 Oct 2018 20:01:12 -0700 Subject: Corrected single-character string constant used as pattern found in dogfood test --- clippy_lints/src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 4c6a9d6bd11..5f8480d8282 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -546,7 +546,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } else if other_gets_derefed { // suggest dropping the to_owned on the left and the deref on the right let other_snippet = snippet(cx, other.span, "..").into_owned(); - let other_without_deref = other_snippet.trim_left_matches("*"); + let other_without_deref = other_snippet.trim_left_matches('*'); (expr.span.to(other.span), format!("{} == {}", snip.to_string(), other_without_deref)) } else { -- cgit 1.4.1-3-g733a5 From 7499cb543dbf111b1d92b808a91be730e761849f Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 10 Oct 2018 07:52:58 +0200 Subject: Fix #2937 --- clippy_lints/src/methods/mod.rs | 24 ++++++++++----- tests/ui/methods.rs | 5 +++- tests/ui/methods.stderr | 66 ++++++++++++++++++++++++----------------- 3 files changed, 59 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a5102824b1c..7c15eb677cc 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1069,12 +1069,19 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { - if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node { - if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node { - if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { - if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { - return Some(format_args); - } + let arg = match &arg.node { + hir::ExprKind::AddrOf(_, expr)=> expr, + hir::ExprKind::MethodCall(method_name, _, args) + if method_name.ident.name == "as_str" || + method_name.ident.name == "as_ref" + => &args[0], + _ => arg, + }; + + if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg.node { + if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { + if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { + return Some(format_args); } } } @@ -1111,7 +1118,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: | hir::ExprKind::MethodCall(..) // These variants are debatable or require further examination | hir::ExprKind::If(..) - | hir::ExprKind::Match(..) => true, + | hir::ExprKind::Match(..) + | hir::ExprKind::Block{ .. } => true, _ => false, } } @@ -1165,7 +1173,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: span_replace_word, &format!("use of `{}` followed by a function call", name), "try this", - format!("unwrap_or_else({} panic!({}))", closure, sugg), + format!("unwrap_or_else({} {{ let msg = {}; panic!(msg) }}))", closure, sugg), ); } diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 5bf52c740fe..e247a3d6450 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -14,7 +14,7 @@ #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] #![allow(clippy::blacklisted_name, unused, clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, clippy::new_without_default_derive, clippy::missing_docs_in_private_items, clippy::needless_pass_by_value, - clippy::default_trait_access, clippy::use_self)] + clippy::default_trait_access, clippy::use_self, clippy::useless_format)] use std::collections::BTreeMap; use std::collections::HashMap; @@ -403,6 +403,9 @@ fn expect_fun_call() { //Issue #2979 - this should not lint let msg = "bar"; Some("foo").expect(msg); + + Some("foo").expect({ &format!("error") }); + Some("foo").expect(format!("error").as_ref()); } /// Checks implementation of `ITER_NTH` lint diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 4b8c0403702..124edee6a52 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -361,7 +361,7 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:379:26 | 379 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/methods.rs:389:25 @@ -373,85 +373,97 @@ error: use of `expect` followed by a function call --> $DIR/methods.rs:392:25 | 392 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` + +error: use of `expect` followed by a function call + --> $DIR/methods.rs:407:17 + | +407 | Some("foo").expect({ &format!("error") }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` + +error: use of `expect` followed by a function call + --> $DIR/methods.rs:408:17 + | +408 | Some("foo").expect(format!("error").as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:416:23 + --> $DIR/methods.rs:419:23 | -416 | let bad_vec = some_vec.iter().nth(3); +419 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:417:26 + --> $DIR/methods.rs:420:26 | -417 | let bad_slice = &some_vec[..].iter().nth(3); +420 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:418:31 + --> $DIR/methods.rs:421:31 | -418 | let bad_boxed_slice = boxed_slice.iter().nth(3); +421 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:419:29 + --> $DIR/methods.rs:422:29 | -419 | let bad_vec_deque = some_vec_deque.iter().nth(3); +422 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:424:23 + --> $DIR/methods.rs:427:23 | -424 | let bad_vec = some_vec.iter_mut().nth(3); +427 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:427:26 + --> $DIR/methods.rs:430:26 | -427 | let bad_slice = &some_vec[..].iter_mut().nth(3); +430 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:430:29 + --> $DIR/methods.rs:433:29 | -430 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +433 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:442:13 + --> $DIR/methods.rs:445:13 | -442 | let _ = some_vec.iter().skip(42).next(); +445 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:443:13 + --> $DIR/methods.rs:446:13 | -443 | let _ = some_vec.iter().cycle().skip(42).next(); +446 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:444:13 + --> $DIR/methods.rs:447:13 | -444 | let _ = (1..10).skip(10).next(); +447 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:445:14 + --> $DIR/methods.rs:448:14 | -445 | let _ = &some_vec[..].iter().skip(3).next(); +448 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:454:13 + --> $DIR/methods.rs:457:13 | -454 | let _ = opt.unwrap(); +457 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 56 previous errors +error: aborting due to 58 previous errors -- cgit 1.4.1-3-g733a5 From 289c642d1a58c6173a1c3adbc26dbb89a7fde4ca Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Tue, 9 Oct 2018 23:35:10 -0700 Subject: Clarify code Take advantage of the fact that very large regexes are unlikely --- clippy_lints/src/regex.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index deb32e49a0d..e68468d4dfe 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -18,7 +18,7 @@ use crate::syntax::ast::{LitKind, NodeId, StrStyle}; use crate::syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; use crate::consts::{constant, Constant}; -use std::convert::TryInto; +use std::convert::TryFrom; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -142,24 +142,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } +#[allow(clippy::cast_possible_truncation)] // truncation very unlikely here fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { let offset = u32::from(offset); - let end = base.lo() + BytePos( - c.end - .offset - .try_into() - .ok() - .and_then(|o: u32| o.checked_add(offset)) - .expect("offset too large"), - ); - let start = base.lo() + BytePos( - c.start - .offset - .try_into() - .ok() - .and_then(|o: u32| o.checked_add(offset)) - .expect("offset too large"), - ); + let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset); + let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset); assert!(start <= end); Span::new(start, end, base.ctxt()) } -- cgit 1.4.1-3-g733a5 From d41615548e47f57c60ac8aed5d47a74dba048c13 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 10 Oct 2018 04:51:06 -0700 Subject: cmp_owned add test for multiple dereference --- tests/ui/cmp_owned.rs | 5 +++++ tests/ui/cmp_owned.stderr | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 65351cd9b9d..dc0880e7089 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -40,6 +40,11 @@ fn main() { let y = &Baz; y.to_owned() == *x; + + let x = &&Baz; + let y = &Baz; + + y.to_owned() == **x; } struct Foo; diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 2613d3b7500..0982467aeee 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -43,10 +43,16 @@ error: this creates an owned instance just for comparison | ^^^^^^^^^^^^^^^^^^ help: try: `y == x` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:49:9 + --> $DIR/cmp_owned.rs:47:5 | -49 | self.to_owned() == *other +47 | y.to_owned() == **x; + | ^^^^^^^^^^^^^^^^^^^ help: try: `y == x` + +error: this creates an owned instance just for comparison + --> $DIR/cmp_owned.rs:54:9 + | +54 | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From f9e4f5695dca025a868e3cdc24bea387c7c475f9 Mon Sep 17 00:00:00 2001 From: Karim SENHAJI Date: Wed, 10 Oct 2018 17:05:16 +0200 Subject: Limit commutative assign op lint to primitive types --- clippy_lints/src/assign_ops.rs | 4 +++- tests/ui/assign_ops2.rs | 15 +++++++++++++++ tests/ui/assign_ops2.stderr | 10 +++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 3fbac7bc153..803c79d42fc 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -215,7 +215,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { lint(assignee, r); } // a = b commutative_op a - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { + // Limited to primitive type as these ops are know to be commutative + if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) + && cx.tables.expr_ty(assignee).is_primitive_ty() { match op.node { hir::BinOpKind::Add | hir::BinOpKind::Mul diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 9eef898c9a7..60a9d2fb73e 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -53,3 +53,18 @@ impl MulAssign for Wrap { *self = *self * rhs } } + +fn cow_add_assign() { + use std::borrow::Cow; + let mut buf = Cow::Owned(String::from("bar")); + let cows = Cow::Borrowed("foo"); + + // this can be linted + buf = buf + cows.clone(); + + // this should not as cow Add is not commutative + buf = cows + buf; + println!("{}", buf); + +} + diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 8e44fc13bb7..bd49c3cdd80 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -126,5 +126,13 @@ help: or 26 | a = a * a * a; | ^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: manual implementation of an assign operation + --> $DIR/assign_ops2.rs:63:5 + | +63 | buf = buf + cows.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` + | + = note: `-D clippy::assign-op-pattern` implied by `-D warnings` + +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 80cf0d7f26f437acf31ce74c52bbe809fcbcb9dc Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 11 Oct 2018 07:45:26 +0200 Subject: Fix fn_to_numeric_cast_with_truncation suppression Fixes #3276 --- clippy_lints/src/types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f43b1fe7abe..035ca2b0496 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -977,7 +977,8 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, - FN_TO_NUMERIC_CAST + FN_TO_NUMERIC_CAST, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, ) } } -- cgit 1.4.1-3-g733a5 From 759ceb984039dee7cac226c656cf599712b5e038 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 11 Oct 2018 08:34:51 +0200 Subject: Use `impl Iterator` in arg position in clippy_dev Small refactoring pulled out of work on #3266. This should make the methods a bit more flexible. --- clippy_dev/src/lib.rs | 6 +++--- clippy_dev/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 2087a4b0740..0e29db9bef0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -56,8 +56,8 @@ impl Lint { } /// Returns all non-deprecated lints - pub fn active_lints(lints: &[Self]) -> impl Iterator { - lints.iter().filter(|l| l.deprecation.is_none()) + pub fn active_lints(lints: impl Iterator) -> impl Iterator { + lints.filter(|l| l.deprecation.is_none()) } /// Returns the lints in a HashMap, grouped by the different lint groups @@ -144,7 +144,7 @@ fn test_active_lints() { let expected = vec![ Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") ]; - assert_eq!(expected, Lint::active_lints(&lints).cloned().collect::>()); + assert_eq!(expected, Lint::active_lints(lints.into_iter()).collect::>()); } #[test] diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 28f831a9b1c..d1161323b02 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -51,5 +51,5 @@ fn print_lints() { } } - println!("there are {} lints", Lint::active_lints(&lint_list).count()); + println!("there are {} lints", Lint::active_lints(lint_list.into_iter()).count()); } -- cgit 1.4.1-3-g733a5 From b8654eaa6c4c4abaed9b8e448445b992c87bb41e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Oct 2018 12:16:22 +0200 Subject: Stabilize tool lints --- README.md | 9 ++++----- clippy_dev/src/lib.rs | 2 +- clippy_lints/src/lib.rs | 2 +- src/driver.rs | 2 +- src/lib.rs | 2 +- src/main.rs | 2 +- tests/run-pass/enum-glob-import-crate.rs | 2 +- tests/run-pass/ice-1588.rs | 2 +- tests/run-pass/ice-1969.rs | 2 +- tests/run-pass/ice-2499.rs | 2 +- tests/run-pass/ice-2760.rs | 2 +- tests/run-pass/ice-2774.rs | 2 +- tests/run-pass/ice-700.rs | 2 +- tests/run-pass/ice_exacte_size.rs | 2 +- tests/run-pass/if_same_then_else.rs | 2 +- tests/run-pass/match_same_arms_const.rs | 2 +- tests/run-pass/mut_mut_macro.rs | 2 +- tests/run-pass/needless_borrow_fp.rs | 2 +- tests/run-pass/needless_lifetimes_impl_trait.rs | 2 +- tests/run-pass/regressions.rs | 2 +- tests/run-pass/single-match-else.rs | 2 +- tests/run-pass/used_underscore_binding_macro.rs | 2 +- tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs | 2 +- tests/ui-toml/toml_trivially_copy/test.rs | 2 +- tests/ui/absurd-extreme-comparisons.rs | 2 +- tests/ui/approx_const.rs | 2 +- tests/ui/arithmetic.rs | 2 +- tests/ui/assign_ops.rs | 2 +- tests/ui/assign_ops2.rs | 2 +- tests/ui/attrs.rs | 2 +- tests/ui/bit_masks.rs | 2 +- tests/ui/blacklisted_name.rs | 2 +- tests/ui/block_in_if_condition.rs | 2 +- tests/ui/bool_comparison.rs | 2 +- tests/ui/booleans.rs | 2 +- tests/ui/borrow_box.rs | 2 +- tests/ui/box_vec.rs | 2 +- tests/ui/builtin-type-shadow.rs | 2 +- tests/ui/bytecount.rs | 2 +- tests/ui/cast.rs | 2 +- tests/ui/cast_alignment.rs | 2 +- tests/ui/cast_lossless_float.rs | 2 +- tests/ui/cast_lossless_integer.rs | 2 +- tests/ui/cast_size.rs | 2 +- tests/ui/char_lit_as_u8.rs | 2 +- tests/ui/checked_unwrap.rs | 2 +- tests/ui/clone_on_copy_mut.rs | 2 +- tests/ui/cmp_nan.rs | 2 +- tests/ui/cmp_null.rs | 2 +- tests/ui/cmp_owned.rs | 2 +- tests/ui/collapsible_if.rs | 2 +- tests/ui/complex_types.rs | 2 +- tests/ui/copies.rs | 2 +- tests/ui/copy_iterator.rs | 2 +- tests/ui/cstring.rs | 2 +- tests/ui/cyclomatic_complexity.rs | 2 +- tests/ui/cyclomatic_complexity_attr_used.rs | 2 +- tests/ui/decimal_literal_representation.rs | 2 +- tests/ui/default_trait_access.rs | 2 +- tests/ui/derive.rs | 2 +- tests/ui/diverging_sub_expression.rs | 2 +- tests/ui/dlist.rs | 2 +- tests/ui/doc.rs | 2 +- tests/ui/double_neg.rs | 2 +- tests/ui/double_parens.rs | 2 +- tests/ui/drop_forget_copy.rs | 2 +- tests/ui/drop_forget_ref.rs | 2 +- tests/ui/duplicate_underscore_argument.rs | 2 +- tests/ui/duration_subsec.rs | 2 +- tests/ui/else_if_without_else.rs | 2 +- tests/ui/empty_enum.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/entry.rs | 2 +- tests/ui/enum_glob_use.rs | 2 +- tests/ui/enum_variants.rs | 2 +- tests/ui/enums_clike.rs | 2 +- tests/ui/eq_op.rs | 2 +- tests/ui/erasing_op.rs | 2 +- tests/ui/eta.rs | 2 +- tests/ui/eval_order_dependence.rs | 2 +- tests/ui/excessive_precision.rs | 2 +- tests/ui/explicit_write.rs | 2 +- tests/ui/fallible_impl_from.rs | 2 +- tests/ui/filter_methods.rs | 2 +- tests/ui/float_cmp.rs | 2 +- tests/ui/float_cmp_const.rs | 2 +- tests/ui/fn_to_numeric_cast.rs | 2 +- tests/ui/for_loop.rs | 2 +- tests/ui/format.rs | 2 +- tests/ui/formatting.rs | 2 +- tests/ui/functions.rs | 2 +- tests/ui/fxhash.rs | 2 +- tests/ui/identity_conversion.rs | 2 +- tests/ui/identity_op.rs | 2 +- tests/ui/if_let_redundant_pattern_matching.rs | 2 +- tests/ui/if_not_else.rs | 2 +- tests/ui/impl.rs | 2 +- tests/ui/inconsistent_digit_grouping.rs | 2 +- tests/ui/indexing_slicing.rs | 2 +- tests/ui/infallible_destructuring_match.rs | 2 +- tests/ui/infinite_iter.rs | 2 +- tests/ui/infinite_loop.rs | 2 +- tests/ui/inline_fn_without_body.rs | 2 +- tests/ui/int_plus_one.rs | 4 ++-- tests/ui/invalid_upcast_comparisons.rs | 2 +- tests/ui/issue_2356.rs | 2 +- tests/ui/item_after_statement.rs | 2 +- tests/ui/large_digit_groups.rs | 2 +- tests/ui/large_enum_variant.rs | 2 +- tests/ui/len_zero.rs | 2 +- tests/ui/let_if_seq.rs | 2 +- tests/ui/let_return.rs | 2 +- tests/ui/let_unit.rs | 2 +- tests/ui/lifetimes.rs | 2 +- tests/ui/literals.rs | 2 +- tests/ui/map_clone.rs | 2 +- tests/ui/map_flatten.rs | 2 +- tests/ui/matches.rs | 2 +- tests/ui/mem_forget.rs | 2 +- tests/ui/mem_replace.rs | 2 +- tests/ui/methods.rs | 2 +- tests/ui/min_max.rs | 2 +- tests/ui/missing-doc.rs | 2 +- tests/ui/missing_inline.rs | 2 +- tests/ui/module_inception.rs | 2 +- tests/ui/modulo_one.rs | 2 +- tests/ui/mut_from_ref.rs | 2 +- tests/ui/mut_mut.rs | 2 +- tests/ui/mut_reference.rs | 2 +- tests/ui/mutex_atomic.rs | 2 +- tests/ui/needless_bool.rs | 2 +- tests/ui/needless_borrow.rs | 2 +- tests/ui/needless_borrowed_ref.rs | 2 +- tests/ui/needless_collect.rs | 2 +- tests/ui/needless_continue.rs | 2 +- tests/ui/needless_pass_by_value.rs | 2 +- tests/ui/needless_pass_by_value_proc_macro.rs | 2 +- tests/ui/needless_return.rs | 2 +- tests/ui/needless_update.rs | 2 +- tests/ui/neg_cmp_op_on_partial_ord.rs | 4 ++-- tests/ui/neg_multiply.rs | 2 +- tests/ui/never_loop.rs | 2 +- tests/ui/new_without_default.rs | 2 +- tests/ui/no_effect.rs | 2 +- tests/ui/non_copy_const.rs | 2 +- tests/ui/non_expressive_names.rs | 2 +- tests/ui/ok_if_let.rs | 2 +- tests/ui/op_ref.rs | 4 ++-- tests/ui/open_options.rs | 2 +- tests/ui/option_map_unit_fn.rs | 2 +- tests/ui/overflow_check_conditional.rs | 2 +- tests/ui/panic_unimplemented.rs | 2 +- tests/ui/patterns.rs | 2 +- tests/ui/precedence.rs | 2 +- tests/ui/print.rs | 2 +- tests/ui/print_literal.rs | 2 +- tests/ui/print_with_newline.rs | 2 +- tests/ui/ptr_arg.rs | 2 +- tests/ui/range.rs | 2 +- tests/ui/range_plus_minus_one.rs | 2 +- tests/ui/redundant_closure_call.rs | 2 +- tests/ui/redundant_field_names.rs | 2 +- tests/ui/reference.rs | 2 +- tests/ui/regex.rs | 2 +- tests/ui/replace_consts.rs | 2 +- tests/ui/result_map_unit_fn.rs | 2 +- tests/ui/serde.rs | 2 +- tests/ui/shadow.rs | 2 +- tests/ui/short_circuit_statement.rs | 2 +- tests/ui/single_char_pattern.rs | 2 +- tests/ui/single_match.rs | 2 +- tests/ui/starts_ends_with.rs | 2 +- tests/ui/strings.rs | 2 +- tests/ui/stutter.rs | 2 +- tests/ui/suspicious_arithmetic_impl.rs | 2 +- tests/ui/swap.rs | 2 +- tests/ui/temporary_assignment.rs | 2 +- tests/ui/toplevel_ref_arg.rs | 2 +- tests/ui/transmute.rs | 2 +- tests/ui/transmute_64bit.rs | 2 +- tests/ui/trivially_copy_pass_by_ref.rs | 2 +- tests/ui/unicode.rs | 2 +- tests/ui/unit_arg.rs | 2 +- tests/ui/unit_cmp.rs | 2 +- tests/ui/unnecessary_clone.rs | 2 +- tests/ui/unnecessary_ref.rs | 2 +- tests/ui/unneeded_field_pattern.rs | 2 +- tests/ui/unreadable_literal.rs | 2 +- tests/ui/unsafe_removed_from_name.rs | 2 +- tests/ui/unused_io_amount.rs | 2 +- tests/ui/unused_labels.rs | 2 +- tests/ui/unused_lt.rs | 2 +- tests/ui/unwrap_or.rs | 2 +- tests/ui/use_self.rs | 2 +- tests/ui/used_underscore_binding.rs | 2 +- tests/ui/useless_asref.rs | 2 +- tests/ui/useless_attribute.rs | 2 +- tests/ui/useless_attribute.stderr | 2 +- tests/ui/vec.rs | 2 +- tests/ui/while_loop.rs | 2 +- tests/ui/write_literal.rs | 2 +- tests/ui/write_with_newline.rs | 2 +- tests/ui/writeln_empty_string.rs | 2 +- tests/ui/wrong_self_convention.rs | 2 +- tests/ui/zero_div_zero.rs | 2 +- 205 files changed, 211 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index 9dd41f6513c..14a5e56cdea 100644 --- a/README.md +++ b/README.md @@ -130,16 +130,15 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: Note: `deny` produces errors instead of warnings. -Note: To use the new `clippy::lint_name` syntax, `#![feature(tool_lints)]` has to be activated -currently. If you want to compile your code with the stable toolchain you can use a `cfg_attr` to +Note: To use the new `clippy::lint_name` syntax, a recent compiler has to be used +currently. If you want to compile your code with the stable toolchain you can use a `cfg_attr` to activate the `tool_lints` feature: ```rust -#![cfg_attr(feature = "cargo-clippy", feature(tool_lints))] #![cfg_attr(feature = "cargo-clippy", allow(clippy::lint_name))] ``` -For this to work you have to use Clippy on the nightly toolchain: `cargo +nightly clippy`. If you -want to use Clippy with the stable toolchain, you can stick to the old unscoped method to +For this to work you have to use Clippy on the nightly toolchain: `cargo +nightly clippy`. If you +want to use Clippy with the stable toolchain, you can stick to the old unscoped method to enable/disable Clippy lints until `tool_lints` are stable: ```rust #![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))] diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 0e29db9bef0..eee9089e7c4 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::default_hash_types)] use itertools::Itertools; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index af69a6284f3..451374c9a47 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -18,7 +18,7 @@ #![allow(unknown_lints, clippy::shadow_reuse, clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] -#![feature(tool_lints)] + #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] #![feature(try_from)] diff --git a/src/driver.rs b/src/driver.rs index 0619b3ae0d9..6af0f0be190 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -11,7 +11,7 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] -#![feature(tool_lints)] + #![feature(try_from)] #![allow(unknown_lints, clippy::missing_docs_in_private_items)] diff --git a/src/lib.rs b/src/lib.rs index 58158f92e65..62c9da03278 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] -#![feature(tool_lints)] + #![allow(unknown_lints)] #![allow(clippy::missing_docs_in_private_items)] #![warn(rust_2018_idioms)] diff --git a/src/main.rs b/src/main.rs index 11c259b4d6b..efdcc42dea3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] -#![feature(tool_lints)] + #![allow(unknown_lints, clippy::missing_docs_in_private_items)] use rustc_tools_util::*; diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index c1e1d9645d1..df8b32cde2b 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::all)] #![allow(unused_imports)] diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index db5a6629a2b..a54c77cce73 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::all)] diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 0b4a0f4dfbf..848d9743dcd 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::all)] diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index 9716e5500c7..1a973d737ba 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index ad517b84c2c..7a83094ea76 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_variables, clippy::blacklisted_name, clippy::needless_pass_by_value, dead_code)] diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index 6ed09a4a008..67a77340d91 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::collections::HashSet; diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index 3252381e1fd..cb6ba21e72b 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::all)] diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index 8a905a401e5..74eda792e75 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::all)] diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs index 4f0f581063a..cc95262fe3c 100644 --- a/tests/run-pass/if_same_then_else.rs +++ b/tests/run-pass/if_same_then_else.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::if_same_then_else)] diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs index 1e36baf059b..bd180e9cad9 100644 --- a/tests/run-pass/match_same_arms_const.rs +++ b/tests/run-pass/match_same_arms_const.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::match_same_arms)] diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index afc3c9eda15..8859009479c 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] #![allow(dead_code)] diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs index 6a70849d9ca..ad4b04864e4 100644 --- a/tests/run-pass/needless_borrow_fp.rs +++ b/tests/run-pass/needless_borrow_fp.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[deny(clippy::all)] diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index b27bb284e21..0514d7ab008 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index a589922218d..9be3bab185c 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::blacklisted_name)] diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index 54c282451b8..cf032c65703 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::single_match_else)] diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index b700ab90a68..68bd6922062 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::useless_attribute)] //issue #2910 diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs index 4f0cd1659f7..ad81b82b2c5 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 081dbf9b060..eb09d6dfc5c 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::many_single_char_names)] #[derive(Copy, Clone)] diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index a88e57a5c43..b219cb0397b 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::absurd_extreme_comparisons)] diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index ea023b8a7a2..b2f50cc2ce3 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::approx_constant)] diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index a5bf8c9280e..ff550c9593c 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 5d791ba8f54..419e63b2c62 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[allow(dead_code, unused_assignments)] #[warn(clippy::assign_op_pattern)] diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 60a9d2fb73e..4f9fbc80aaa 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[allow(unused_assignments)] diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 9af9c0e619a..1d0c23905bd 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::inline_always, clippy::deprecated_semver)] diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index 4110f6ced85..db5a6885c9e 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + const THREE_BITS : i64 = 7; diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index be58a8fb601..285438810d9 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code, clippy::similar_names, clippy::single_match, clippy::toplevel_ref_arg, unused_mut, unused_variables)] diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index 67bd778acaa..bb87315bcc4 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::block_in_if_condition_expr)] diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 1d9756bc39b..c213414a63d 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::bool_comparison)] diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 556344c77a2..962f03dc9cd 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::nonminimal_bool, clippy::logic_bug)] diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index 7c668c33c83..dbcd42a692c 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::borrowed_box)] diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index 78174d2cd8f..bf505c85abc 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index a6d0f82a7d6..e43a2789ce1 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::builtin_type_shadow)] diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 71a6e01219e..170666d1f18 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[deny(clippy::naive_bytecount)] diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 2fb865b12b8..9976a4aa96a 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index b6e01d21288..a1a2e1c9a8f 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + //! Test casts for alignment issues diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index aa78a62f88b..468774dd88b 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index ef430d57e1e..4f7432de620 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index e8b0f4a5b82..fddf9669a8f 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index 8fda473e351..d684fcf5746 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::char_lit_as_u8)] diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index ed9651b1872..383fd82240b 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow(clippy::if_same_then_else)] diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index ad37d45d36f..81d70eb9458 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + pub fn dec_read_dec(i: &mut i32) -> i32 { *i -= 1; diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index a2506f444f0..4b62d0e53f1 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cmp_nan)] diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index d8214876a1b..03f0367a640 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::cmp_null)] #![allow(unused_mut)] diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 031809f5df5..978e919ff43 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::cmp_owned)] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index fa80b27f590..a6df9109df9 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::collapsible_if)] diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index 5779c9da47f..e735bf8e487 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value)] diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 2b29e76c4e0..8d0bc802daf 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, clippy::needless_return, clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero)] diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index 6984b612f23..b5684f183eb 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::copy_iterator)] diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index fd5d00059a7..6121166debe 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + fn main() {} diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 3c8ab8694a6..35451a99acc 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::all)] #![warn(clippy::cyclomatic_complexity)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index 1699601aa50..63d4e65a977 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index f85ccd84722..c52fcd826ca 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::decimal_literal_representation)] diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index d268746d765..331ad03f9a2 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::default_trait_access)] diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index c5ce42586fa..521a2e323fc 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(untagged_unions)] diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 9cf6f22fb27..a47c96759ac 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(never_type)] diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index dbbac901b03..cf16777b77a 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(alloc)] #![feature(associated_type_defaults)] diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 85e688e0f07..37f89de471f 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + //! This file tests for the DOC_MARKDOWN lint diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index 31e7a508fcd..3785c09060b 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::double_neg)] diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index 18ff140c3ca..be1676a7487 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::double_parens)] diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 8b2b96a14d3..44e9ae0e044 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::drop_copy, clippy::forget_copy)] diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index 0f36b823e0f..0aee38d3cbf 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::drop_ref, clippy::forget_ref)] diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index 25b2a0ba8b6..27329965f0c 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::duplicate_underscore_argument)] diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 75352ad182b..c8db599a840 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::duration_subsec)] diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 56987d0d64d..caaa024ff6b 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] #![warn(clippy::else_if_without_else)] diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index cd63acb9ed6..b60f5491a93 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 8aa2e8a1f46..43105b6e342 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::empty_line_after_outer_attr)] // This should produce a warning diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 0bab6bf332e..0ee6d799222 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused, clippy::needless_pass_by_value)] diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index e24e2fd8eb3..9b7d4518c66 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic)] #![allow(unused_imports, dead_code, clippy::missing_docs_in_private_items)] diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 8a51e2f58f1..34c69854b75 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(non_ascii_idents)] diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index 17983255030..5513a9506aa 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + // ignore-x86 diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index c96cd8b9af2..36c54b0f42e 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::eq_op)] diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index 1c572b55554..696c58f98ae 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[allow(clippy::no_effect)] diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index a580ce0831a..e516dd6910a 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unknown_lints, unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::redundant_closure, clippy::needless_borrow)] diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index 4e525b9b2b0..ee8f834fe56 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::eval_order_dependence)] diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index abfdb0b3da1..5945298da9f 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::excessive_precision)] #![allow(clippy::print_literal)] diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 2a748d25724..8c1e35daa48 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::explicit_write)] diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index 1e1e24ee954..f50d5999de6 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::fallible_impl_from)] diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index 1bfc03356fb..33441d728ca 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic)] diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index cb8b7a98e39..5619539fb5a 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::float_cmp)] diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 27d829ed105..7cca1df65ae 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::float_cmp_const)] diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 9bd0ad7687f..50796e13ef6 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -9,7 +9,7 @@ // only-64bit -#![feature(tool_lints)] + #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index cff7075543b..bdb6b56e0bb 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::collections::*; diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 5679a55755c..e314d3022da 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::print_literal)] #![warn(clippy::useless_format)] diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 15aff5a3bba..0dca8c8585b 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 136adef823b..f5ba0f791ee 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs index e91cfcb9e70..fe4b80807c0 100644 --- a/tests/ui/fxhash.rs +++ b/tests/ui/fxhash.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::default_hash_types)] #![feature(rustc_private)] diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index a4f5babecfc..9384c9eb206 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::identity_conversion)] diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 35afb85109f..07a4ef8f3eb 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + const ONE : i64 = 1; diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs index 84f4b711f53..1c0e7e79c68 100644 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ b/tests/ui/if_let_redundant_pattern_matching.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index b0744d8c600..23895c0ab52 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] #![warn(clippy::if_not_else)] diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 6c2152220cf..38c0a484091 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] #![warn(clippy::multiple_inherent_impl)] diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index dc73952ca25..941fbe5154a 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::inconsistent_digit_grouping)] #[allow(unused_variables)] diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 8d3f3cee99a..6a32eb87491 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(plugin)] #![warn(clippy::indexing_slicing)] diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index bd4e4b49a4a..62036cbc107 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(exhaustive_patterns, never_type)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index cf30a2e35ed..68c10acb2be 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::iter::repeat; #[allow(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index e837e563f18..869b34e8ade 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 93dff0d350f..8434d33f65e 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::inline_fn_without_body)] diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index df16a393824..8a0405321d0 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[allow(clippy::no_effect, clippy::unnecessary_operation)] @@ -16,7 +16,7 @@ fn main() { let x = 1i32; let y = 0i32; - + x >= y + 1; y + 1 <= x; diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 5c17970d337..3e62f11006d 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::invalid_upcast_comparisons)] diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index d251d51f3fc..070808f7b69 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::while_let_on_iterator)] diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index d765adae38c..a4cc42f0d72 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::items_after_statements)] diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 7cc1f9c881d..aad5c205041 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::large_digit_groups)] #[allow(unused_variables)] diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index 729cc8940ef..419cb0ab428 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index a8f1e283643..bc82e0bca04 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::len_without_is_empty, clippy::len_zero)] #![allow(dead_code, unused)] diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 5fca759a4b3..080fa3b24b8 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_variables, unused_assignments, clippy::similar_names, clippy::blacklisted_name)] diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index 380f775689d..317aaf42b5c 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused)] diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 578fcb2ddde..d77bc8712bf 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::let_unit_value)] diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index c7ed303b43b..77f25afe023 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::needless_lifetimes, clippy::extra_unused_lifetimes)] diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 3c1dcf09af2..4db7ce95712 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::mixed_case_hex_literals)] #![warn(clippy::unseparated_literal_suffix)] diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 90611023f75..162d8a484b4 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index b3f86d81e3f..1b5c20069d1 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index e6e4154e437..c43fead08f8 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(exclusive_range_pattern)] diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 0e7cfbffa4c..266c5c267f8 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 69e3ae96bad..2b6e6f2ce67 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] use std::mem; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index e247a3d6450..883dbf589d7 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 32e3863ad40..b4ca46231e0 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index 43dad8398f1..6e7dfbfa37a 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + /* This file incorporates work covered by the following copyright and * permission notice: diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 593774da1b4..0b86c4e5cfe 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + /* This file incorporates work covered by the following copyright and * permission notice: diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index 1dfc06f38af..333a8efec32 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::module_inception)] diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index 6e0cbc581dc..f1576447708 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::modulo_one)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 37256efb839..0a68d449d92 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::mut_from_ref)] diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 81c945beafc..bed872902af 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index f42d48f0db4..d63b854fd09 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_variables, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index e0ce93bf698..87b4ac9d8e3 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 0e8e250c95d..a9a2e3709f1 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::needless_bool)] diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 1cf7b40661d..f8a170f38d4 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::borrow::Cow; diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 650b57b586c..ca3e60bd7e7 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::needless_borrowed_reference)] diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 45622b33384..91ebd354146 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::collections::{HashMap, HashSet, BTreeSet}; diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 4a15987ba96..3d91132ea62 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + macro_rules! zero { diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 3e029de4755..5825d9e9074 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::needless_pass_by_value)] #![allow(dead_code, clippy::single_match, clippy::if_let_redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)] diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index b1ca6d75c99..f8f279ccb66 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![crate_type = "proc-macro"] #![warn(clippy::needless_pass_by_value)] diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index bfe86573a4d..9380f7c48a5 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::needless_return)] diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 70fe7236c24..974f3603fc6 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::needless_update)] diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index c8edba32219..6d26d2ec6d1 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + //! This test case utilizes `f64` an easy example for `PartialOrd` only types //! but the lint itself actually validates any expression where the left @@ -27,7 +27,7 @@ fn main() { // Not Less but potentially Greater, Equal or Uncomparable. let _not_less = !(a_value < another_value); - + // Not Less or Equal but potentially Greater or Uncomparable. let _not_less_or_equal = !(a_value <= another_value); diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 2589f3b8551..446af7bbe94 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::neg_multiply)] diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 901a98559e7..b952b1197dd 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::single_match, unused_assignments, unused_variables, clippy::while_immutable_condition)] diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 7fa369354b3..783308d264a 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(const_fn)] diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index a56327eeefa..32e1ccb7bee 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(box_syntax)] diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index 6c57a37e2ab..5cbb610fea3 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(const_string_new, const_vec_new)] #![allow(clippy::ref_in_deref, dead_code)] diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 47e4da61b51..67fded14485 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all,clippy::similar_names)] #![allow(unused, clippy::println_empty_string)] diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index 71b301cbc42..b318a90d883 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::if_let_some_result)] diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index 96a208ef807..bacf9f1057b 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_variables, clippy::blacklisted_name)] @@ -19,7 +19,7 @@ fn main() { let tracked_fds: HashSet = HashSet::new(); let new_fds = HashSet::new(); let unwanted = &tracked_fds - &new_fds; - + let foo = &5 - &6; let bar = String::new(); diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index a01f2b1ce39..6b891d72e8b 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::fs::OpenOptions; diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index a69c41ce967..b023181fcf7 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::option_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index 8aba051c65e..82fdfe14ab6 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::many_single_char_names)] diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index f292455dc7d..ede2e8f063b 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::panic_params, clippy::unimplemented)] diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 2b42aae63ea..41e9ec8ca81 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused)] #![warn(clippy::all)] diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index ccc08ddc5d7..4b404022ed4 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::precedence)] diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 3bb72fcb1f4..5fa2cfcc315 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::print_literal, clippy::write_literal)] #![warn(clippy::print_stdout, clippy::use_debug)] diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index fd68751820d..0df26f6d25f 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::print_literal)] diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 4fc24080d46..2dd08a5b88d 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::print_literal)] #![warn(clippy::print_with_newline)] diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 4d5f353bb6a..df0bde14960 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused, clippy::many_single_char_names)] #![warn(clippy::ptr_arg)] diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 270b71d263f..8b7f0673e24 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + struct NotARange; impl NotARange { diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 15743828d8b..602743d6914 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + fn f() -> usize { 42 diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index bf0cc550b0d..4912e5fc1b4 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::redundant_closure_call)] diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index ac0d5d10535..41e90bba368 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::redundant_field_names)] #![allow(unused_variables)] diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index 9298aee2cac..bd0fdd5d5ea 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + fn get_number() -> usize { diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 6e77c589023..2623438c4c4 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused)] diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 2f961e86f9a..7a2584f174d 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(integer_atomics)] #![allow(clippy::blacklisted_name)] diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index 4edbfdd5bf4..f24e52b10fd 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(never_type)] #![warn(clippy::result_map_unit_fn)] diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index caa954bea44..47be8423d7b 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::serde_api_misuse)] #![allow(dead_code)] diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index a607161a949..aa29bd1d79c 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all, clippy::pedantic, clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index 01511314c7d..67999a74e5e 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::short_circuit_statement)] diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 12aaa69f34b..5e1231f1227 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + use std::collections::HashSet; diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 07c1a95025a..5c7cae249b4 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::single_match)] diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 180924d2c9c..5c09e8f1f28 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 31e6c9a059f..7bc4e6515f6 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::string_add)] diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index 148e8071ce0..17d528d1050 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::stutter)] #![allow(dead_code)] diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index a183576b40e..5e7608565ed 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::suspicious_arithmetic_impl)] diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index bef2031f8a8..90c2aec9875 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index cf92f9fd6c2..9c4365bef40 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::temporary_assignment)] diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 9f92d706ad6..09ee79f6d8b 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 4108750acf6..285c07a9724 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 630b594eb1b..8620628fdce 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + //ignore-x86 //no-ignore-x86_64 diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 716e0dc6420..cebe15b2cc8 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::many_single_char_names, clippy::blacklisted_name, clippy::redundant_field_names)] diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 486135ddfa5..8de17fea220 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::zero_width_space)] diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index ed70ee843b1..058c6563c5a 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::unit_arg)] #![allow(clippy::no_effect)] diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index e8726bf7364..10eb0c70c54 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::unit_cmp)] diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 82010db7a99..df02570d692 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::clone_on_ref_ptr)] #![allow(unused)] diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 6fb2abaf19c..adc628fe8b6 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![feature(tool_attributes)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 963d555ca56..128a3fee429 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::unneeded_field_pattern)] diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 67e04706f04..9142b3d2911 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[warn(clippy::unreadable_literal)] #[allow(unused_variables)] diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index 39aa4afdf8d..9c1800467d3 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_imports)] #![allow(dead_code)] diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 0ab89c994f4..a47a6ccfdf6 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code)] diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index ecfdab490f6..d7d843dfc25 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(dead_code, clippy::items_after_statements, clippy::never_loop)] diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 3aea986d28d..de13864421e 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::extra_unused_lifetimes)] diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index b31ccfea200..80965635a08 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] fn main() { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 784e0c04016..6ebe8f16a90 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::use_self)] #![allow(dead_code)] diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index 13ae1d67f15..b6b055e58bc 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::all)] diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 598618365c8..a5e9caf3a67 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![deny(clippy::useless_asref)] #![allow(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 710f35da72b..9fb84866ef6 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 4a27d1148b4..6b82b105b05 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -10,7 +10,7 @@ error: useless lint attribute --> $DIR/useless_attribute.rs:16:1 | 16 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` error: aborting due to 2 previous errors diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 45e51663795..e74aded5728 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::useless_vec)] diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index ff7a43fd693..3cc7c52df5d 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)] diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 9a27ca11dae..7917479ed67 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_must_use)] #![warn(clippy::write_literal)] diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index f3e26ed904f..e9fcff0b3dd 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(clippy::write_literal)] #![warn(clippy::write_with_newline)] diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 888e870667c..e272a5af88b 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index d843af1a396..d1c7424c8d7 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #![warn(clippy::wrong_self_convention)] diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index c2cbd32968f..4e2272c8e09 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -8,7 +8,7 @@ // except according to those terms. -#![feature(tool_lints)] + #[allow(unused_variables)] -- cgit 1.4.1-3-g733a5 From 9d3373137b74a403281b293b19ab9346773af073 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Oct 2018 12:18:27 +0200 Subject: Remove now-useless `allow(unknown_lints)` --- clippy_lints/src/lib.rs | 2 +- src/driver.rs | 2 +- src/lib.rs | 1 - src/main.rs | 2 +- tests/ui/eta.rs | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 451374c9a47..c343cf364f6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -15,7 +15,7 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] -#![allow(unknown_lints, clippy::shadow_reuse, clippy::missing_docs_in_private_items)] +#![allow(clippy::shadow_reuse, clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] diff --git a/src/driver.rs b/src/driver.rs index 6af0f0be190..9abe6bd91de 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -13,7 +13,7 @@ #![feature(rustc_private)] #![feature(try_from)] -#![allow(unknown_lints, clippy::missing_docs_in_private_items)] +#![allow(clippy::missing_docs_in_private_items)] // FIXME: switch to something more ergonomic here, once available. // (currently there is no way to opt into sysroot crates w/o `extern crate`) diff --git a/src/lib.rs b/src/lib.rs index 62c9da03278..97f1f81091d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar)] #![feature(rustc_private)] -#![allow(unknown_lints)] #![allow(clippy::missing_docs_in_private_items)] #![warn(rust_2018_idioms)] diff --git a/src/main.rs b/src/main.rs index efdcc42dea3..4a1dc487cea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] -#![allow(unknown_lints, clippy::missing_docs_in_private_items)] +#![allow(clippy::missing_docs_in_private_items)] use rustc_tools_util::*; diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index e516dd6910a..dd41433d2db 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -10,7 +10,7 @@ -#![allow(unknown_lints, unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] +#![allow(unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::redundant_closure, clippy::needless_borrow)] fn main() { -- cgit 1.4.1-3-g733a5 From 0b65462ca52599162949df162239ce55de96b4b3 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Thu, 11 Oct 2018 05:03:02 -0700 Subject: cmp_owned current suggestion for multiple deref --- clippy_lints/src/misc.rs | 2 +- tests/ui/cmp_owned.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 5f8480d8282..be863cd7bc8 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -546,7 +546,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } else if other_gets_derefed { // suggest dropping the to_owned on the left and the deref on the right let other_snippet = snippet(cx, other.span, "..").into_owned(); - let other_without_deref = other_snippet.trim_left_matches('*'); + let other_without_deref = other_snippet.replacen('*', "", 1); (expr.span.to(other.span), format!("{} == {}", snip.to_string(), other_without_deref)) } else { diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 0982467aeee..1db60be54d6 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -46,7 +46,7 @@ error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:47:5 | 47 | y.to_owned() == **x; - | ^^^^^^^^^^^^^^^^^^^ help: try: `y == x` + | ^^^^^^^^^^^^^^^^^^^ help: try: `y == *x` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:54:9 -- cgit 1.4.1-3-g733a5 From 9afd8abbe345095ee8755e2872a33cc7666e7790 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 11 Oct 2018 15:18:58 -0700 Subject: Fix `similar_names` warnings Most of these are just `#![allow]`ed, because they are things like using l vs r to differentiate left vs right. These would be made less clear by taking the advice of `similar_names` --- clippy_lints/src/double_comparison.rs | 1 + clippy_lints/src/enum_clike.rs | 12 ++++++------ clippy_lints/src/enum_variants.rs | 1 + clippy_lints/src/eq_op.rs | 1 + clippy_lints/src/if_let_redundant_pattern_matching.rs | 1 + clippy_lints/src/transmute.rs | 1 + clippy_lints/src/utils/hir_utils.rs | 3 +++ clippy_lints/src/utils/inspector.rs | 2 ++ clippy_lints/src/utils/usage.rs | 1 + 9 files changed, 17 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index e151918c1fb..3710301c8ab 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -49,6 +49,7 @@ impl LintPass for DoubleComparisonPass { } impl<'a, 'tcx> DoubleComparisonPass { + #[allow(clippy::similar_names)] fn check_binop( &self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 313175aee84..315bc54cd17 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -63,16 +63,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let variant = &var.node; if let Some(ref anon_const) = variant.disr_expr { let param_env = ty::ParamEnv::empty(); - let did = cx.tcx.hir.body_owner_def_id(anon_const.body); - let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); - let instance = ty::Instance::new(did, substs); - let cid = GlobalId { + let def_id = cx.tcx.hir.body_owner_def_id(anon_const.body); + let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id); + let instance = ty::Instance::new(def_id, substs); + let c_id = GlobalId { instance, promoted: None }; - let constant = cx.tcx.const_eval(param_env.and(cid)).ok(); + let constant = cx.tcx.const_eval(param_env.and(c_id)).ok(); if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { - let mut ty = cx.tcx.type_of(did); + let mut ty = cx.tcx.type_of(def_id); if let ty::Adt(adt, _) = ty.sty { if adt.is_enum() { ty = adt.repr.discr_type().to_ty(cx.tcx); diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 8d708f01720..3454eff08a9 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -255,6 +255,7 @@ impl EarlyLintPass for EnumVariantNames { assert!(last.is_some()); } + #[allow(clippy::similar_names)] fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { let item_name = item.ident.as_str(); let item_name_chars = item_name.chars().count(); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index a454ea83695..dfe0c0180a7 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -63,6 +63,7 @@ impl LintPass for EqOp { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { + #[allow(clippy::similar_names)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Binary(op, ref left, ref right) = e.node { if in_macro(e.span) { diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 8b42eaa528e..bced0c9552d 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -56,6 +56,7 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + #[allow(clippy::similar_names)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Match(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { if arms[0].pats.len() == 1 { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 0d49f5de265..801b6db63f5 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -227,6 +227,7 @@ impl LintPass for Transmute { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { + #[allow(clippy::similar_names)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Call(ref path_expr, ref args) = e.node { if let ExprKind::Path(ref qpath) = path_expr.node { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index bc55c22979b..7a0b28d15d8 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -73,6 +73,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) } + #[allow(clippy::similar_names)] pub fn eq_expr(&mut self, left: &Expr, right: &Expr) -> bool { if self.ignore_fn && differing_macro_contexts(left.span, right.span) { return false; @@ -208,6 +209,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } + #[allow(clippy::similar_names)] fn eq_qpath(&mut self, left: &QPath, right: &QPath) -> bool { match (left, right) { (&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => { @@ -262,6 +264,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_ty_kind(&left.node, &right.node) } + #[allow(clippy::similar_names)] pub fn eq_ty_kind(&mut self, left: &TyKind, right: &TyKind) -> bool { match (left, right) { (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec), diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 841aaaabdfa..ea48aa9ab5e 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -166,6 +166,7 @@ fn print_decl(cx: &LateContext<'_, '_>, decl: &hir::Decl) { } } +#[allow(clippy::similar_names)] fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); @@ -424,6 +425,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { } } +#[allow(clippy::similar_names)] fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index d26ffc715e8..f3af698ffa2 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -54,6 +54,7 @@ struct MutVarsDelegate { } impl<'tcx> MutVarsDelegate { + #[allow(clippy::similar_names)] fn update(&mut self, cat: &'tcx Categorization<'_>) { match *cat { Categorization::Local(id) => { -- cgit 1.4.1-3-g733a5 From dcef9d07952eae2a2fbfe8f01e3885352c4ce8fb Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 11 Oct 2018 15:36:40 -0700 Subject: Fix `stutter` lints --- clippy_lints/src/double_comparison.rs | 1 + clippy_lints/src/enum_variants.rs | 12 +++++------ clippy_lints/src/question_mark.rs | 1 + clippy_lints/src/utils/camel_case.rs | 38 +++++++++++++++++------------------ clippy_lints/src/utils/mod.rs | 3 +-- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 3710301c8ab..314ca41ba21 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -40,6 +40,7 @@ declare_clippy_lint! { "unnecessary double comparisons that can be simplified" } +#[allow(clippy::stutter)] pub struct DoubleComparisonPass; impl LintPass for DoubleComparisonPass { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 3454eff08a9..16d1e40484d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -16,7 +16,7 @@ use crate::syntax::ast::*; use crate::syntax::source_map::Span; use crate::syntax::symbol::LocalInternedString; use crate::utils::{span_help_and_lint, span_lint}; -use crate::utils::{camel_case_from, camel_case_until, in_macro}; +use crate::utils::{camel_case, in_macro}; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. @@ -184,19 +184,19 @@ fn check_variant( } } let first = var2str(&def.variants[0]); - let mut pre = &first[..camel_case_until(&*first)]; - let mut post = &first[camel_case_from(&*first)..]; + let mut pre = &first[..camel_case::until(&*first)]; + let mut post = &first[camel_case::from(&*first)..]; for var in &def.variants { let name = var2str(var); let pre_match = partial_match(pre, &name); pre = &pre[..pre_match]; - let pre_camel = camel_case_until(pre); + let pre_camel = camel_case::until(pre); pre = &pre[..pre_camel]; while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { if next.is_lowercase() { let last = pre.len() - last.len_utf8(); - let last_camel = camel_case_until(&pre[..last]); + let last_camel = camel_case::until(&pre[..last]); pre = &pre[..last_camel]; } else { break; @@ -206,7 +206,7 @@ fn check_variant( let post_match = partial_rmatch(post, &name); let post_end = post.len() - post_match; post = &post[post_end..]; - let post_camel = camel_case_from(post); + let post_camel = camel_case::from(post); post = &post[post_camel..]; } let (what, value) = match (pre.is_empty(), post.is_empty()) { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 0ec57e0be80..93a40e13540 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -44,6 +44,7 @@ declare_clippy_lint!{ "checks for expressions that could be replaced by the question mark operator" } +#[allow(clippy::stutter)] #[derive(Copy, Clone)] pub struct QuestionMarkPass; diff --git a/clippy_lints/src/utils/camel_case.rs b/clippy_lints/src/utils/camel_case.rs index 2b60e2c32fa..5ce1e08d8b5 100644 --- a/clippy_lints/src/utils/camel_case.rs +++ b/clippy_lints/src/utils/camel_case.rs @@ -10,7 +10,7 @@ /// Return the index of the character after the first camel-case component of /// `s`. -pub fn camel_case_until(s: &str) -> usize { +pub fn until(s: &str) -> usize { let mut iter = s.char_indices(); if let Some((_, first)) = iter.next() { if !first.is_uppercase() { @@ -43,7 +43,7 @@ pub fn camel_case_until(s: &str) -> usize { } /// Return index of the last camel-case component of `s`. -pub fn camel_case_from(s: &str) -> usize { +pub fn from(s: &str) -> usize { let mut iter = s.char_indices().rev(); if let Some((_, first)) = iter.next() { if !first.is_lowercase() { @@ -73,52 +73,52 @@ pub fn camel_case_from(s: &str) -> usize { #[cfg(test)] mod test { - use super::{camel_case_from, camel_case_until}; + use super::{from, until}; #[test] fn from_full() { - assert_eq!(camel_case_from("AbcDef"), 0); - assert_eq!(camel_case_from("Abc"), 0); + assert_eq!(from("AbcDef"), 0); + assert_eq!(from("Abc"), 0); } #[test] fn from_partial() { - assert_eq!(camel_case_from("abcDef"), 3); - assert_eq!(camel_case_from("aDbc"), 1); + assert_eq!(from("abcDef"), 3); + assert_eq!(from("aDbc"), 1); } #[test] fn from_not() { - assert_eq!(camel_case_from("AbcDef_"), 7); - assert_eq!(camel_case_from("AbcDD"), 5); + assert_eq!(from("AbcDef_"), 7); + assert_eq!(from("AbcDD"), 5); } #[test] fn from_caps() { - assert_eq!(camel_case_from("ABCD"), 4); + assert_eq!(from("ABCD"), 4); } #[test] fn until_full() { - assert_eq!(camel_case_until("AbcDef"), 6); - assert_eq!(camel_case_until("Abc"), 3); + assert_eq!(until("AbcDef"), 6); + assert_eq!(until("Abc"), 3); } #[test] fn until_not() { - assert_eq!(camel_case_until("abcDef"), 0); - assert_eq!(camel_case_until("aDbc"), 0); + assert_eq!(until("abcDef"), 0); + assert_eq!(until("aDbc"), 0); } #[test] fn until_partial() { - assert_eq!(camel_case_until("AbcDef_"), 6); - assert_eq!(camel_case_until("CallTypeC"), 8); - assert_eq!(camel_case_until("AbcDD"), 3); + assert_eq!(until("AbcDef_"), 6); + assert_eq!(until("CallTypeC"), 8); + assert_eq!(until("AbcDD"), 3); } #[test] fn until_caps() { - assert_eq!(camel_case_until("ABCD"), 0); + assert_eq!(until("ABCD"), 0); } -} \ No newline at end of file +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2a9b1cb0a10..05356f8d385 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -33,8 +33,7 @@ use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::errors::DiagnosticBuilder; use crate::syntax::symbol::keywords; -mod camel_case; -pub use self::camel_case::{camel_case_from, camel_case_until}; +pub mod camel_case; pub mod comparisons; pub mod conf; -- cgit 1.4.1-3-g733a5 From 73ba33dd2b22c4b434a9189304c39f8dfa608f70 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 11 Oct 2018 15:43:13 -0700 Subject: Fix `doc_markdown` lints --- clippy_lints/src/excessive_precision.rs | 1 + clippy_lints/src/map_unit_fn.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 99668880f72..15a8d47337a 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -108,6 +108,7 @@ impl ExcessivePrecision { } } +#[allow(clippy::doc_markdown)] /// Should we exclude the float because it has a `.0` or `.` suffix /// Ex 1_000_000_000.0 /// Ex 1_000_000_000. diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index e620a1815ce..503a2ee7032 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -179,7 +179,7 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op None } -/// Builds a name for the let binding variable (var_arg) +/// Builds a name for the let binding variable (`var_arg`) /// /// `x.field` => `x_field` /// `y` => `_y` -- cgit 1.4.1-3-g733a5 From 9fad38dca913573c1b534addc37affdcc174de0b Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Thu, 11 Oct 2018 22:15:01 -0600 Subject: tmp progress --- clippy_lints/src/literal_representation.rs | 18 ++++++++++++++++-- tests/ui/literals.rs | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index a123415cca9..2d64a24a79b 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -173,8 +173,10 @@ impl<'a> DigitInfo<'a> { } else { d_idx }; - if float && (d == 'f' || d == 'e' || d == 'E') || - !float && (d == 'i' || d == 'u' || is_possible_suffix_index(&sans_prefix, suffix_start, len)) { + if float && ((is_possible_float_suffix_index(&sans_prefix, suffix_start, len)) || + (d == 'f' || d == 'e' || d == 'E')) || + !float && (d == 'i' || d == 'u' || + is_possible_suffix_index(&sans_prefix, suffix_start, len)) { let (digits, suffix) = sans_prefix.split_at(suffix_start); return Self { digits, @@ -248,6 +250,9 @@ impl<'a> DigitInfo<'a> { hint = format!("{:0>4}{}", &hint[..nb_digits_to_fill], &hint[nb_digits_to_fill..]); } let suffix_hint = match self.suffix { + Some(suffix) if is_mistyped_float_suffix(suffix) && self.digits.contains(".") => { + format!("_f{}", &suffix[1..]) + }, Some(suffix) if is_mistyped_suffix(suffix) => { format!("_i{}", &suffix[1..]) }, @@ -572,3 +577,12 @@ fn is_possible_suffix_index(lit: &str, idx: usize, len: usize) -> bool { ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && is_mistyped_suffix(lit.split_at(idx).1) } + +fn is_mistyped_float_suffix(suffix: &str) -> bool { + ["_32", "_64"].contains(&suffix) +} + +fn is_possible_float_suffix_index(lit: &str, idx: usize, len: usize) -> bool { + ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && + is_mistyped_float_suffix(lit.split_at(idx).1) +} diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 3c1dcf09af2..39d9f3f0e44 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -64,4 +64,7 @@ fn main() { let fail21 = 4___16; let fail22 = 3__4___23; let fail23 = 3__16___23; + + //let fail24 = 1E2_32; + let fail25 = 1.2_32; } -- cgit 1.4.1-3-g733a5 From ff9dfccadee1a724f357999fb9eb671fe04e837c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 12 Oct 2018 07:19:34 +0200 Subject: Add Travis windows build See https://blog.travis-ci.com/2018-10-11-windows-early-release --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6d44c7faa93..20c98062dd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ rust: nightly os: - linux - osx + - windows sudo: false @@ -36,6 +37,8 @@ matrix: env: BASE_TESTS=true - os: linux env: BASE_TESTS=true + - os: windows + env: BASE_TEST=true - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-lang-nursery/rand - env: INTEGRATION=rust-lang-nursery/stdsimd @@ -53,6 +56,7 @@ matrix: exclude: - os: linux - os: osx + - os: windows script: - | -- cgit 1.4.1-3-g733a5 From 024ccb4f508c184127e2522ce8ac77a9229b31e9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 12 Oct 2018 07:41:25 +0200 Subject: Move Travis Windows build to allowed failures Until the remaining issues are fixed. This also enabled `fast_finish`. It will finish even if the windows build is still running. --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 20c98062dd8..7abfe0e03dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,9 @@ matrix: - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom - env: INTEGRATION=hyperium/hyper + allow_failures: + - os: windows + env: BASE_TEST=true # prevent these jobs with default env vars exclude: - os: linux -- cgit 1.4.1-3-g733a5 From f5a38f2323006fb56cc730cc1313f9578bc84c68 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 12 Oct 2018 07:59:08 +0200 Subject: Only run markdown linter on linux Because: * There's no need to run it on more than one platform * It doesn't work on windows --- .travis.yml | 2 +- ci/base-tests.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7abfe0e03dd..5446f1ab568 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ before_install: install: - | - if [ -z ${INTEGRATION} ]; then + if [ -z ${INTEGRATION} ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then . $HOME/.nvm/nvm.sh nvm install stable nvm use stable diff --git a/ci/base-tests.sh b/ci/base-tests.sh index ebf4a127cdc..72a38ee5e58 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -14,7 +14,9 @@ set -ex echo "Running clippy base tests" PATH=$PATH:./node_modules/.bin -remark -f *.md > /dev/null +if [ "$TRAVIS_OS_NAME" == "linux" ]; then + remark -f *.md > /dev/null +fi # build clippy in debug mode and run tests cargo build --features debugging cargo test --features debugging -- cgit 1.4.1-3-g733a5 From 34fd4af503f6cf193e42cd7760c848bc45852875 Mon Sep 17 00:00:00 2001 From: sigustin Date: Fri, 12 Oct 2018 12:15:20 +0200 Subject: Specify which categories are enabled by default Closes #3293 --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 14a5e56cdea..cf3b3e1ffdd 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,15 @@ We have a bunch of lint categories to allow you to choose how much Clippy is sup More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! +Only the following of those categories are enabled by default: + +* `clippy::style` +* `clippy::correctness` +* `clippy::complexity` +* `clippy::perf` + +Other categories need to be enabled in order for their lints to be executed. + Table of contents: * [Usage instructions](#usage) -- cgit 1.4.1-3-g733a5 From 4e2062518775c7c42db48aea2678d16eaba2d72b Mon Sep 17 00:00:00 2001 From: sigustin Date: Fri, 12 Oct 2018 12:32:48 +0200 Subject: Add a comment reminding to update README if the default changes --- clippy_lints/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c343cf364f6..7cdc0f43b34 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -46,6 +46,8 @@ extern crate syntax_pos; use toml; +// Currently, categories "style", "correctness", "complexity" and "perf" are enabled by default, +// as said in the README.md of this repository. If this changes, please update README.md. macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } -- cgit 1.4.1-3-g733a5 From c9718fa589552476ee277c52a35271663383cf6a Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 12 Oct 2018 04:34:41 -0700 Subject: cmp_owned correct error message if rhs is deref --- clippy_lints/src/misc.rs | 4 ++++ tests/ui/cmp_owned.stderr | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index be863cd7bc8..0a65953313e 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -579,6 +579,10 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { } } } + if other_gets_derefed { + db.span_label(lint_span, "try implementing the comparison without allocating"); + return; + } db.span_suggestion_with_applicability( lint_span, "try", diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 1db60be54d6..a7371ab4b6c 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -40,13 +40,13 @@ error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:42:5 | 42 | y.to_owned() == *x; - | ^^^^^^^^^^^^^^^^^^ help: try: `y == x` + | ^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:47:5 | 47 | y.to_owned() == **x; - | ^^^^^^^^^^^^^^^^^^^ help: try: `y == *x` + | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:54:9 -- cgit 1.4.1-3-g733a5 From 352863065cb644a4f59fa5655601960e34bf77e7 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 12 Oct 2018 04:48:54 -0700 Subject: cmp_owned refactor --- clippy_lints/src/misc.rs | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 0a65953313e..1cf7345e8df 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -21,7 +21,7 @@ use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; -use crate::syntax::ast::{LitKind, CRATE_NODE_ID}; +use crate::syntax::ast::LitKind; use crate::consts::{constant, Constant}; use crate::rustc_errors::Applicability; @@ -540,18 +540,10 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { _ => false, }; - let (lint_span, try_hint) = if deref_arg_impl_partial_eq_other { - // suggest deref on the left - (expr.span, format!("*{}", snip)) - } else if other_gets_derefed { - // suggest dropping the to_owned on the left and the deref on the right - let other_snippet = snippet(cx, other.span, "..").into_owned(); - let other_without_deref = other_snippet.replacen('*', "", 1); - - (expr.span.to(other.span), format!("{} == {}", snip.to_string(), other_without_deref)) + let lint_span = if other_gets_derefed { + expr.span.to(other.span) } else { - // suggest dropping the to_owned on the left - (expr.span, snip.to_string()) + expr.span }; span_lint_and_then( @@ -560,29 +552,20 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { lint_span, "this creates an owned instance just for comparison", |db| { - // this is as good as our recursion check can get, we can't prove that the - // current function is - // called by - // PartialEq::eq, but we can at least ensure that this code is not part of it - let parent_fn = cx.tcx.hir.get_parent(expr.id); - let parent_impl = cx.tcx.hir.get_parent(parent_fn); - if parent_impl != CRATE_NODE_ID { - if let Node::Item(item) = cx.tcx.hir.get(parent_impl) { - if let ItemKind::Impl(.., Some(ref trait_ref), _, _) = item.node { - if trait_ref.path.def.def_id() == partial_eq_trait_id { - // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise - // we go into - // recursion - db.span_label(lint_span, "try implementing the comparison without allocating"); - return; - } - } - } - } + // this also catches PartialEq implementations that call to_owned if other_gets_derefed { db.span_label(lint_span, "try implementing the comparison without allocating"); return; } + + let try_hint = if deref_arg_impl_partial_eq_other { + // suggest deref on the left + format!("*{}", snip) + } else { + // suggest dropping the to_owned on the left + snip.to_string() + }; + db.span_suggestion_with_applicability( lint_span, "try", -- cgit 1.4.1-3-g733a5 From d3c06f7252fdca30b19aa6ff8ecf63c86675676e Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Fri, 12 Oct 2018 10:26:55 -0400 Subject: Exclude pattern guards from unnecessary_fold lint Methods like `Iterator::any` borrow the iterator mutably, which is not allowed within a pattern guard and will fail to compile. This commit prevents clippy from suggesting this type of change. Closes #3069 --- clippy_lints/src/methods/mod.rs | 18 ++++++++++++++++++ tests/ui/unnecessary_fold.rs | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 7c15eb677cc..66c94746f5a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -9,6 +9,7 @@ use crate::rustc::hir; +use crate::rustc::hir::{ExprKind, Guard, Node}; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; use crate::rustc::ty::{self, Ty}; @@ -1428,6 +1429,23 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: return; } + // `Iterator::any` cannot be used within a pattern guard + // See https://github.com/rust-lang-nursery/rust-clippy/issues/3069 + if_chain! { + if let Some(fold_parent) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(expr.id)); + if let Node::Expr(fold_parent) = fold_parent; + if let ExprKind::Match(_, ref arms, _) = fold_parent.node; + if arms.iter().any(|arm| { + if let Some(Guard::If(ref guard)) = arm.guard { + return guard.id == expr.id; + } + false + }); + then { + return; + } + } + assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index e8d84ecea8c..3b70602d4ad 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -45,6 +45,13 @@ fn unnecessary_fold_should_ignore() { let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); + + // Because `any` takes the iterator as a mutable reference, + // it cannot be used in a pattern guard, and we must use `fold`. + match 1 { + _ if (0..3).fold(false, |acc, x| acc || x > 2) => {} + _ => {} + } } fn main() {} -- cgit 1.4.1-3-g733a5 From 863c8e26fc66e856456cb05e75e1d6c821a04ec6 Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Fri, 12 Oct 2018 13:15:55 -0400 Subject: Revert "Exclude pattern guards from unnecessary_fold lint" This reverts commit d3c06f7252fdca30b19aa6ff8ecf63c86675676e. --- clippy_lints/src/methods/mod.rs | 18 ------------------ tests/ui/unnecessary_fold.rs | 7 ------- 2 files changed, 25 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 66c94746f5a..7c15eb677cc 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -9,7 +9,6 @@ use crate::rustc::hir; -use crate::rustc::hir::{ExprKind, Guard, Node}; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; use crate::rustc::ty::{self, Ty}; @@ -1429,23 +1428,6 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: return; } - // `Iterator::any` cannot be used within a pattern guard - // See https://github.com/rust-lang-nursery/rust-clippy/issues/3069 - if_chain! { - if let Some(fold_parent) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(expr.id)); - if let Node::Expr(fold_parent) = fold_parent; - if let ExprKind::Match(_, ref arms, _) = fold_parent.node; - if arms.iter().any(|arm| { - if let Some(Guard::If(ref guard)) = arm.guard { - return guard.id == expr.id; - } - false - }); - then { - return; - } - } - assert!(fold_args.len() == 3, "Expected fold_args to have three entries - the receiver, the initial value and the closure"); diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 3b70602d4ad..e8d84ecea8c 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -45,13 +45,6 @@ fn unnecessary_fold_should_ignore() { let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); - - // Because `any` takes the iterator as a mutable reference, - // it cannot be used in a pattern guard, and we must use `fold`. - match 1 { - _ if (0..3).fold(false, |acc, x| acc || x > 2) => {} - _ => {} - } } fn main() {} -- cgit 1.4.1-3-g733a5 From 0a1bae95074a682318e167bee55078dd8ccbdc51 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 12 Oct 2018 22:04:58 +0200 Subject: Install Windows SDK 10.0 on travis --- .travis.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5446f1ab568..818353e0c16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,11 +24,16 @@ before_install: install: - | - if [ -z ${INTEGRATION} ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then - . $HOME/.nvm/nvm.sh - nvm install stable - nvm use stable - npm install remark-cli remark-lint + if [ -z ${INTEGRATION} ]; then + if [ "$TRAVIS_OS_NAME" == "linux" ]; then + . $HOME/.nvm/nvm.sh + nvm install stable + nvm use stable + npm install remark-cli remark-lint + fi + if [ "$TRAVIS_OS_NAME" == "windows" ]; then + choco install windows-sdk-10.0 + fi fi matrix: -- cgit 1.4.1-3-g733a5 From e8687a6677b2352228a6edd2ba05282cbb1ddb65 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Thu, 27 Sep 2018 19:10:20 +0200 Subject: unused unit lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/returns.rs | 100 ++++++++++++++++++++++++++++++++++++++++++-- tests/ui/copies.rs | 6 +-- tests/ui/my_lint.rs | 7 ++++ tests/ui/unused_unit.rs | 52 +++++++++++++++++++++++ tests/ui/unused_unit.stderr | 52 +++++++++++++++++++++++ 8 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 tests/ui/my_lint.rs create mode 100644 tests/ui/unused_unit.rs create mode 100644 tests/ui/unused_unit.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bea1e8ef5..e6792c06894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -878,6 +878,7 @@ All notable changes to this project will be documented in this file. [`unused_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_collect [`unused_io_amount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_io_amount [`unused_label`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_label +[`unused_unit`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_unit [`use_debug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#used_underscore_binding diff --git a/README.md b/README.md index 14a5e56cdea..b07bac9b11a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 279 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 280 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c343cf364f6..3d8179e4782 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -685,6 +685,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + returns::UNUSED_UNIT, serde_api::SERDE_API_MISUSE, strings::STRING_LIT_AS_BYTES, suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, @@ -801,6 +802,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, + returns::UNUSED_UNIT, strings::STRING_LIT_AS_BYTES, types::FN_TO_NUMERIC_CAST, types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index f4360802483..d083387e852 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -14,8 +14,8 @@ use if_chain::if_chain; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax::visit::FnKind; +use crate::syntax_pos::BytePos; use crate::rustc_errors::Applicability; - use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for return statements at the end of a block. @@ -68,6 +68,25 @@ declare_clippy_lint! { the end of a block" } +/// **What it does:** Checks for unit (`()`) expressions that can be removed. +/// +/// **Why is this bad?** Such expressions add no value, but can make the code +/// less readable. Depending on formatting they can make a `break` or `return` +/// statement look like a function call. +/// +/// **Known problems:** The lint currently misses unit return types in types, +/// e.g. the `F` in `fn generic_unit ()>(f: F) { .. }`. +/// +/// **Example:** +/// ```rust +/// fn return_unit() -> () { () } +/// ``` +declare_clippy_lint! { + pub UNUSED_UNIT, + style, + "needless unit expression" +} + #[derive(Copy, Clone)] pub struct ReturnPass; @@ -162,23 +181,98 @@ impl ReturnPass { impl LintPass for ReturnPass { fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RETURN, LET_AND_RETURN) + lint_array!(NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT) } } impl EarlyLintPass for ReturnPass { - fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: &ast::FnDecl, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, decl: &ast::FnDecl, span: Span, _: ast::NodeId) { match kind { FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), FnKind::Closure(body) => self.check_final_expr(cx, body, Some(body.span)), } + if_chain! { + if let ast::FunctionRetTy::Ty(ref ty) = decl.output; + if let ast::TyKind::Tup(ref vals) = ty.node; + if vals.is_empty() && !in_macro(ty.span) && get_def(span) == get_def(ty.span); + then { + let (rspan, appl) = if let Ok(fn_source) = + cx.sess().source_map() + .span_to_snippet(span.with_hi(ty.span.hi())) { + if let Some(rpos) = fn_source.rfind("->") { + (ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable) + } else { + (ty.span, Applicability::MaybeIncorrect) + } + } else { + (ty.span, Applicability::MaybeIncorrect) + }; + span_lint_and_then(cx, UNUSED_UNIT, rspan, "unneeded unit return type", |db| { + db.span_suggestion_with_applicability( + rspan, + "remove the `-> ()`", + String::new(), + appl, + ); + }); + } + } } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { self.check_let_return(cx, block); + if_chain! { + if let Some(ref stmt) = block.stmts.last(); + if let ast::StmtKind::Expr(ref expr) = stmt.node; + if is_unit_expr(expr) && !in_macro(expr.span); + then { + let sp = expr.span; + span_lint_and_then(cx, UNUSED_UNIT, sp, "unneeded unit expression", |db| { + db.span_suggestion_with_applicability( + sp, + "remove the final `()`", + String::new(), + Applicability::MachineApplicable, + ); + }); + } + } + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + match e.node { + ast::ExprKind::Ret(Some(ref expr)) | ast::ExprKind::Break(_, Some(ref expr)) => { + if is_unit_expr(expr) && !in_macro(expr.span) { + span_lint_and_then(cx, UNUSED_UNIT, expr.span, "unneeded `()`", |db| { + db.span_suggestion_with_applicability( + expr.span, + "remove the `()`", + String::new(), + Applicability::MachineApplicable, + ); + }); + } + } + _ => () + } } } fn attr_is_cfg(attr: &ast::Attribute) -> bool { attr.meta_item_list().is_some() && attr.name() == "cfg" } + +// get the def site +fn get_def(span: Span) -> Option { + span.ctxt().outer().expn_info().and_then(|info| info.def_site) +} + +// is this expr a `()` unit? +fn is_unit_expr(expr: &ast::Expr) -> bool { + if let ast::ExprKind::Tup(ref vals) = expr.node { + vals.is_empty() + } else { + false + } +} diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 8d0bc802daf..5c4bbecf822 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, + clippy::needless_return, clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero, clippy::unused_unit)] -#![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, - clippy::needless_return, clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero)] - fn bar(_: T) {} fn foo() -> bool { unimplemented!() } @@ -28,6 +27,7 @@ pub enum Abc { #[warn(clippy::if_same_then_else)] #[warn(clippy::match_same_arms)] +#[allow(clippy::unused_unit)] fn if_same_then_else() -> Result<&'static str, ()> { if true { Foo { bar: 42 }; diff --git a/tests/ui/my_lint.rs b/tests/ui/my_lint.rs new file mode 100644 index 00000000000..c27fd5be134 --- /dev/null +++ b/tests/ui/my_lint.rs @@ -0,0 +1,7 @@ +#[clippy::author] +#[cfg(any(target_arch = "x86"))] +pub struct Foo { + x: u32, +} + +fn main() {} diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs new file mode 100644 index 00000000000..a7f08c28939 --- /dev/null +++ b/tests/ui/unused_unit.rs @@ -0,0 +1,52 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +// compile-pass + +// 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. + + +#![deny(clippy::unused_unit)] +#![allow(clippy::needless_return)] + +struct Unitter; + +impl Unitter { + // try to disorient the lint with multiple unit returns and newlines + pub fn get_unit (), G>(&self, f: F, _g: G) -> + () + where G: Fn() -> () { + let _y: &Fn() -> () = &f; + (); // this should not lint, as it's not in return type position + } +} + +impl Into<()> for Unitter { + fn into(self) -> () { + () + } +} + +fn return_unit() -> () { () } + +fn main() { + let u = Unitter; + assert_eq!(u.get_unit(|| {}, return_unit), u.into()); + return_unit(); + loop { + break(); + } + return(); +} diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr new file mode 100644 index 00000000000..b5d5bdbcbee --- /dev/null +++ b/tests/ui/unused_unit.stderr @@ -0,0 +1,52 @@ +error: unneeded unit return type + --> $DIR/unused_unit.rs:28:59 + | +28 | pub fn get_unit (), G>(&self, f: F, _g: G) -> + | ___________________________________________________________^ +29 | | () + | |__________^ help: remove the `-> ()` + | +note: lint level defined here + --> $DIR/unused_unit.rs:21:9 + | +21 | #![deny(clippy::unused_unit)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unneeded unit return type + --> $DIR/unused_unit.rs:37:19 + | +37 | fn into(self) -> () { + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit expression + --> $DIR/unused_unit.rs:38:9 + | +38 | () + | ^^ help: remove the final `()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:42:18 + | +42 | fn return_unit() -> () { () } + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit expression + --> $DIR/unused_unit.rs:42:26 + | +42 | fn return_unit() -> () { () } + | ^^ help: remove the final `()` + +error: unneeded `()` + --> $DIR/unused_unit.rs:49:14 + | +49 | break(); + | ^^ help: remove the `()` + +error: unneeded `()` + --> $DIR/unused_unit.rs:51:11 + | +51 | return(); + | ^^ help: remove the `()` + +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 335bc1e820c2fd1316e3c225189361b43f2654c3 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Fri, 12 Oct 2018 17:07:48 -0700 Subject: Fix some more `stutter` warnings --- clippy_lints/src/double_comparison.rs | 9 ++++----- clippy_lints/src/lib.rs | 4 ++-- clippy_lints/src/question_mark.rs | 9 ++++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 314ca41ba21..0171ac1e784 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -40,16 +40,15 @@ declare_clippy_lint! { "unnecessary double comparisons that can be simplified" } -#[allow(clippy::stutter)] -pub struct DoubleComparisonPass; +pub struct Pass; -impl LintPass for DoubleComparisonPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DOUBLE_COMPARISONS) } } -impl<'a, 'tcx> DoubleComparisonPass { +impl<'a, 'tcx> Pass { #[allow(clippy::similar_names)] fn check_binop( &self, @@ -89,7 +88,7 @@ impl<'a, 'tcx> DoubleComparisonPass { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisonPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.node { self.check_binop(cx, kind.node, lhs, rhs, expr.span); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c343cf364f6..9b749bdcebe 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -428,8 +428,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_late_lint_pass(box replace_consts::ReplaceConsts); reg.register_late_lint_pass(box types::UnitArg); - reg.register_late_lint_pass(box double_comparison::DoubleComparisonPass); - reg.register_late_lint_pass(box question_mark::QuestionMarkPass); + reg.register_late_lint_pass(box double_comparison::Pass); + reg.register_late_lint_pass(box question_mark::Pass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_early_lint_pass(box multiple_crate_versions::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 93a40e13540..72d33e58cd3 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -44,17 +44,16 @@ declare_clippy_lint!{ "checks for expressions that could be replaced by the question mark operator" } -#[allow(clippy::stutter)] #[derive(Copy, Clone)] -pub struct QuestionMarkPass; +pub struct Pass; -impl LintPass for QuestionMarkPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(QUESTION_MARK) } } -impl QuestionMarkPass { +impl Pass { /// Check if the given expression on the given context matches the following structure: /// /// ```ignore @@ -146,7 +145,7 @@ impl QuestionMarkPass { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMarkPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { Self::check_is_none_and_early_return_none(cx, expr); } -- cgit 1.4.1-3-g733a5 From eb854b233c353441f86c4a346a941c5965a2333a Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 2 Oct 2018 20:11:56 -0700 Subject: new_ret_no_self added positive test cases --- clippy_lints/src/methods/mod.rs | 22 +++++++------- tests/ui/new_ret_no_self.rs | 63 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 tests/ui/new_ret_no_self.rs diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 7c15eb677cc..d11dbf0e773 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -878,6 +878,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let name = implitem.ident.name; let parent = cx.tcx.hir.get_parent(implitem.id); let item = cx.tcx.hir.expect_item(parent); + let def_id = cx.tcx.hir.local_def_id(item.id); + let ty = cx.tcx.type_of(def_id); if_chain! { if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; if let Some(first_arg_ty) = sig.decl.inputs.get(0); @@ -899,8 +901,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } // check conventions w.r.t. conversion method names and predicates - let def_id = cx.tcx.hir.local_def_id(item.id); - let ty = cx.tcx.type_of(def_id); let is_copy = is_copy(cx, ty); for &(ref conv, self_kinds) in &CONVENTIONS { if conv.check(&name.as_str()) { @@ -928,17 +928,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { break; } } - - let ret_ty = return_ty(cx, implitem.id); - if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { - span_lint(cx, - NEW_RET_NO_SELF, - implitem.span, - "methods called `new` usually return `Self`"); - } } } + + let ret_ty = return_ty(cx, implitem.id); + if name == "new" && + !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { + span_lint(cx, + NEW_RET_NO_SELF, + implitem.span, + "methods called `new` usually return `Self`"); + } } } diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs new file mode 100644 index 00000000000..67933f00262 --- /dev/null +++ b/tests/ui/new_ret_no_self.rs @@ -0,0 +1,63 @@ +#![feature(tool_lints)] + +#![warn(clippy::new_ret_no_self)] +#![allow(dead_code, clippy::trivially_copy_pass_by_ref)] + +fn main(){} + +//trait R { +// type Item; +//} +// +//struct S; +// +//impl R for S { +// type Item = Self; +//} +// +//impl S { +// // should not trigger the lint +// pub fn new() -> impl R { +// S +// } +//} +// +//struct S2; +// +//impl R for S2 { +// type Item = Self; +//} +// +//impl S2 { +// // should not trigger the lint +// pub fn new(_: String) -> impl R { +// S2 +// } +//} +// +//struct T; +// +//impl T { +// // should not trigger lint +// pub fn new() -> Self { +// unimplemented!(); +// } +//} + +struct U; + +impl U { + // should trigger lint + pub fn new() -> u32 { + unimplemented!(); + } +} + +struct V; + +impl V { + // should trigger lint + pub fn new(_: String) -> u32 { + unimplemented!(); + } +} -- cgit 1.4.1-3-g733a5 From 13ce96c4bfd236ec49bcd7b63f42f9a51b0ee599 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 3 Oct 2018 03:55:31 -0700 Subject: new_ret_no_self corrected panic and added test stderr --- clippy_lints/src/methods/mod.rs | 16 +++++---- tests/ui/new_ret_no_self.rs | 76 ++++++++++++++++++++--------------------- tests/ui/new_ret_no_self.stderr | 18 ++++++++++ 3 files changed, 65 insertions(+), 45 deletions(-) create mode 100644 tests/ui/new_ret_no_self.stderr diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d11dbf0e773..81cb1cd1182 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -931,13 +931,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } - let ret_ty = return_ty(cx, implitem.id); - if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { - span_lint(cx, - NEW_RET_NO_SELF, - implitem.span, - "methods called `new` usually return `Self`"); + if let hir::ImplItemKind::Method(ref sig, id) = implitem.node { + let ret_ty = return_ty(cx, implitem.id); + if name == "new" && + !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { + span_lint(cx, + NEW_RET_NO_SELF, + implitem.span, + "methods called `new` usually return `Self`"); + } } } } diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 67933f00262..762dd582168 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -5,44 +5,44 @@ fn main(){} -//trait R { -// type Item; -//} -// -//struct S; -// -//impl R for S { -// type Item = Self; -//} -// -//impl S { -// // should not trigger the lint -// pub fn new() -> impl R { -// S -// } -//} -// -//struct S2; -// -//impl R for S2 { -// type Item = Self; -//} -// -//impl S2 { -// // should not trigger the lint -// pub fn new(_: String) -> impl R { -// S2 -// } -//} -// -//struct T; -// -//impl T { -// // should not trigger lint -// pub fn new() -> Self { -// unimplemented!(); -// } -//} +trait R { + type Item; +} + +struct S; + +impl R for S { + type Item = Self; +} + +impl S { + // should not trigger the lint + pub fn new() -> impl R { + S + } +} + +struct S2; + +impl R for S2 { + type Item = Self; +} + +impl S2 { + // should not trigger the lint + pub fn new(_: String) -> impl R { + S2 + } +} + +struct T; + +impl T { + // should not trigger lint + pub fn new() -> Self { + unimplemented!(); + } +} struct U; diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr new file mode 100644 index 00000000000..1d698892449 --- /dev/null +++ b/tests/ui/new_ret_no_self.stderr @@ -0,0 +1,18 @@ +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:51:5 + | +51 | / pub fn new() -> u32 { +52 | | unimplemented!(); +53 | | } + | |_____^ + +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:60:5 + | +60 | / pub fn new(_: String) -> u32 { +61 | | unimplemented!(); +62 | | } + | |_____^ + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 1c4fa419f33211db3fa60f3bc8d59a8f42992558 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 3 Oct 2018 04:59:14 -0700 Subject: new_ret_no_self fix false positive for impl trait return with associated type self --- clippy_lints/src/methods/mod.rs | 3 ++- tests/ui/new_ret_no_self.rs | 13 +++++++++++++ tests/ui/new_ret_no_self.stderr | 18 ++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 81cb1cd1182..7426ece5ba9 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -934,7 +934,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let hir::ImplItemKind::Method(ref sig, id) = implitem.node { let ret_ty = return_ty(cx, implitem.id); if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { + !same_tys(cx, ret_ty, ty) && + !ret_ty.is_impl_trait() { span_lint(cx, NEW_RET_NO_SELF, implitem.span, diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 762dd582168..3b7ff7780ef 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -35,6 +35,19 @@ impl S2 { } } +struct S3; + +impl R for S3 { + type Item = u32; +} + +impl S3 { + // should trigger the lint, but currently does not + pub fn new(_: String) -> impl R { + S3 + } +} + struct T; impl T { diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index 1d698892449..cab5fa55cb6 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -1,17 +1,19 @@ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:51:5 + --> $DIR/new_ret_no_self.rs:64:5 | -51 | / pub fn new() -> u32 { -52 | | unimplemented!(); -53 | | } +64 | / pub fn new() -> u32 { +65 | | unimplemented!(); +66 | | } | |_____^ + | + = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:60:5 + --> $DIR/new_ret_no_self.rs:73:5 | -60 | / pub fn new(_: String) -> u32 { -61 | | unimplemented!(); -62 | | } +73 | / pub fn new(_: String) -> u32 { +74 | | unimplemented!(); +75 | | } | |_____^ error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 2ef4af7db23c5522db2d71b60908b93127df5036 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 3 Oct 2018 05:00:43 -0700 Subject: Removed unused variables --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 7426ece5ba9..c78bb48db2a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -931,7 +931,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } - if let hir::ImplItemKind::Method(ref sig, id) = implitem.node { + if let hir::ImplItemKind::Method(_, _) = implitem.node { let ret_ty = return_ty(cx, implitem.id); if name == "new" && !same_tys(cx, ret_ty, ty) && -- cgit 1.4.1-3-g733a5 From a5e4805ecf1ff5b38f0d467ba90530e43bfd0d9c Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Thu, 4 Oct 2018 19:01:04 -0700 Subject: new_ret_no_self correctly lint impl return --- clippy_lints/src/methods/mod.rs | 26 ++++++++++++++++++++++---- tests/ui/new_ret_no_self.rs | 21 ++++++++++++++++++++- tests/ui/new_ret_no_self.stderr | 26 +++++++++++++++++--------- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c78bb48db2a..f9c010beea7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -11,7 +11,7 @@ use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Ty}; +use crate::rustc::ty::{self, Ty, TyKind, Predicate}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast; @@ -933,9 +933,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let hir::ImplItemKind::Method(_, _) = implitem.node { let ret_ty = return_ty(cx, implitem.id); - if name == "new" && - !same_tys(cx, ret_ty, ty) && - !ret_ty.is_impl_trait() { + + // if return type is impl trait + if let TyKind::Opaque(def_id, _) = ret_ty.sty { + + // then one of the associated types must be Self + for predicate in cx.tcx.predicates_of(def_id).predicates.iter() { + match predicate { + (Predicate::Projection(poly_projection_predicate), _) => { + let binder = poly_projection_predicate.ty(); + let associated_type = binder.skip_binder(); + let associated_type_is_self_type = same_tys(cx, ty, associated_type); + + // if the associated type is self, early return and do not trigger lint + if associated_type_is_self_type { return; } + }, + (_, _) => {}, + } + } + } + + if name == "new" && !same_tys(cx, ret_ty, ty) { span_lint(cx, NEW_RET_NO_SELF, implitem.span, diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 3b7ff7780ef..e9f41d34133 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -9,6 +9,11 @@ trait R { type Item; } +trait Q { + type Item; + type Item2; +} + struct S; impl R for S { @@ -42,12 +47,26 @@ impl R for S3 { } impl S3 { - // should trigger the lint, but currently does not + // should trigger the lint pub fn new(_: String) -> impl R { S3 } } +struct S4; + +impl Q for S4 { + type Item = u32; + type Item2 = Self; +} + +impl S4 { + // should not trigger the lint + pub fn new(_: String) -> impl Q { + S4 + } +} + struct T; impl T { diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index cab5fa55cb6..aa3a633c418 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -1,20 +1,28 @@ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:64:5 + --> $DIR/new_ret_no_self.rs:51:5 | -64 | / pub fn new() -> u32 { -65 | | unimplemented!(); -66 | | } +51 | / pub fn new(_: String) -> impl R { +52 | | S3 +53 | | } | |_____^ | = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:73:5 + --> $DIR/new_ret_no_self.rs:83:5 | -73 | / pub fn new(_: String) -> u32 { -74 | | unimplemented!(); -75 | | } +83 | / pub fn new() -> u32 { +84 | | unimplemented!(); +85 | | } | |_____^ -error: aborting due to 2 previous errors +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:92:5 + | +92 | / pub fn new(_: String) -> u32 { +93 | | unimplemented!(); +94 | | } + | |_____^ + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 348d18ebd8ee5182d4705aba8341fb469f936ff5 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Thu, 4 Oct 2018 21:37:28 -0700 Subject: Removed new_ret_no_self tests from method.rs --- tests/ui/methods.rs | 4 ++-- tests/ui/methods.stderr | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 883dbf589d7..ae1b1642be7 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -14,7 +14,7 @@ #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] #![allow(clippy::blacklisted_name, unused, clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, clippy::new_without_default_derive, clippy::missing_docs_in_private_items, clippy::needless_pass_by_value, - clippy::default_trait_access, clippy::use_self, clippy::useless_format)] + clippy::default_trait_access, clippy::use_self, clippy::new_ret_no_self, clippy::useless_format)] use std::collections::BTreeMap; use std::collections::HashMap; @@ -43,7 +43,7 @@ impl T { fn to_something(self) -> u32 { 0 } - fn new(self) {} + fn new(self) -> Self { unimplemented!(); } } struct Lt<'a> { diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 124edee6a52..307814824ea 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -23,17 +23,9 @@ error: methods called `to_*` usually take self by reference; consider choosing a error: methods called `new` usually take no self; consider choosing a less ambiguous name --> $DIR/methods.rs:46:12 | -46 | fn new(self) {} +46 | fn new(self) -> Self { unimplemented!(); } | ^^^^ -error: methods called `new` usually return `Self` - --> $DIR/methods.rs:46:5 - | -46 | fn new(self) {} - | ^^^^^^^^^^^^^^^ - | - = note: `-D clippy::new-ret-no-self` implied by `-D warnings` - error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead --> $DIR/methods.rs:114:13 | @@ -465,5 +457,5 @@ error: used unwrap() on an Option value. If you don't want to handle the None ca | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 58 previous errors +error: aborting due to 57 previous errors -- cgit 1.4.1-3-g733a5 From 54506705cec65652c0607cfe8af7284546e9b576 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Mon, 8 Oct 2018 19:35:37 -0700 Subject: Added new_ret_no_self exception to clippy to pass dogfood tests --- clippy_lints/src/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 035ca2b0496..59c55168232 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1920,6 +1920,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. + #[allow(clippy::new_ret_no_self)] fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node { let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()? -- cgit 1.4.1-3-g733a5 From 3f386d33f92c4bf439043cf2866f44fc0ee5b27c Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 13 Oct 2018 06:33:46 -0700 Subject: new_ret_no_self test remove tool lints cfg flag --- tests/ui/new_ret_no_self.rs | 2 -- tests/ui/new_ret_no_self.stderr | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index e9f41d34133..1a4b91cc9da 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -1,5 +1,3 @@ -#![feature(tool_lints)] - #![warn(clippy::new_ret_no_self)] #![allow(dead_code, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index aa3a633c418..ad26438d4ef 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -1,27 +1,27 @@ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:51:5 + --> $DIR/new_ret_no_self.rs:49:5 | -51 | / pub fn new(_: String) -> impl R { -52 | | S3 -53 | | } +49 | / pub fn new(_: String) -> impl R { +50 | | S3 +51 | | } | |_____^ | = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:83:5 + --> $DIR/new_ret_no_self.rs:81:5 | -83 | / pub fn new() -> u32 { -84 | | unimplemented!(); -85 | | } +81 | / pub fn new() -> u32 { +82 | | unimplemented!(); +83 | | } | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:92:5 + --> $DIR/new_ret_no_self.rs:90:5 | -92 | / pub fn new(_: String) -> u32 { -93 | | unimplemented!(); -94 | | } +90 | / pub fn new(_: String) -> u32 { +91 | | unimplemented!(); +92 | | } | |_____^ error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From c6f79c7ba0dcefaae7e96912a066ecbf4f63e8ca Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 13 Oct 2018 06:57:52 -0700 Subject: explicit_counter_loop fix #3308 false positive --- clippy_lints/src/loops.rs | 5 +---- tests/ui/for_loop.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b807e4fb9e1..064a8d5229d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1952,10 +1952,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { _ => (), } } - } else if is_loop(expr) { - walk_expr(self, expr); - return; - } else if is_conditional(expr) { + } else if is_loop(expr) || is_conditional(expr) { self.depth += 1; walk_expr(self, expr); self.depth -= 1; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index bdb6b56e0bb..89c452f44df 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -646,3 +646,38 @@ mod issue_1219 { } } } + +mod issue_3308 { + #[warn(clippy::explicit_counter_loop)] + pub fn test() { + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + let erasures = vec![]; + for i in 0..10 { + while erasures.contains(&(i + skips)) { + skips += 1; + } + println!("{}", skips); + } + + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + for i in 0..10 { + let mut j = 0; + while j < 5 { + skips += 1; + j += 1; + } + println!("{}", skips); + } + + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + for i in 0..10 { + for j in 0..5 { + skips += 1; + } + println!("{}", skips); + } + } +} -- cgit 1.4.1-3-g733a5 From 0f3345e8b2f839f1d3e0c8472537d7d954828ccd Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 13 Oct 2018 13:51:53 -0700 Subject: OUT_OF_BOUNDS_INDEXING fix #3102 false negative --- clippy_lints/src/indexing_slicing.rs | 70 ++++++++++++++++++++++++------------ tests/ui/indexing_slicing.rs | 5 +++ tests/ui/indexing_slicing.stderr | 14 +++++++- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 984d725898d..8b7a1f7882b 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -111,17 +111,43 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - // Index is a constant range. - if let Some((start, end)) = to_const_range(cx, range, size) { - if start > size || end > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - } - return; + + match to_const_range(cx, range, size) { + (None, None) => {}, + (Some(start), None) => { + if start > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + return; + } + }, + (None, Some(end)) => { + if end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + return; + } + }, + (Some(start), Some(end)) => { + if start > size || end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + } + // early return because both start and end are constant + return; + }, } } @@ -161,20 +187,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { } } -/// Returns an option containing a tuple with the start and end (exclusive) of -/// the range. +/// Returns a tuple of options with the start and end (exclusive) values of +/// the range. If the start or end is not constant, None is returned. fn to_const_range<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, range: Range<'_>, array_size: u128, -) -> Option<(u128, u128)> { +) -> (Option, Option) { let s = range .start .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let start = match s { - Some(Some(Constant::Int(x))) => x, - Some(_) => return None, - None => 0, + Some(Some(Constant::Int(x))) => Some(x), + Some(_) => None, + None => Some(0), }; let e = range @@ -182,13 +208,13 @@ fn to_const_range<'a, 'tcx>( .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let end = match e { Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { - x + 1 + Some(x + 1) } else { - x + Some(x) }, - Some(_) => return None, - None => array_size, + Some(_) => None, + None => Some(array_size), }; - Some((start, end)) + (start, end) } diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index 6a32eb87491..ff154091bb8 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -91,4 +91,9 @@ fn main() { x[M]; // Ok, should not produce stderr. v[N]; v[M]; + + // issue 3102 + let num = 1; + &x[num..10]; // should trigger out of bounds error + &x[10..num]; // should trigger out of bounds error } diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 7d847c7a673..c587269e3e5 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -267,5 +267,17 @@ error: indexing may panic. | = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: aborting due to 37 previous errors +error: range is out of bounds + --> $DIR/indexing_slicing.rs:97:6 + | +97 | &x[num..10]; // should trigger out of bounds error + | ^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/indexing_slicing.rs:98:6 + | +98 | &x[10..num]; // should trigger out of bounds error + | ^^^^^^^^^^ + +error: aborting due to 39 previous errors -- cgit 1.4.1-3-g733a5 From c4928181107314fa437cbd6cdd078d07f53caef1 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 14 Oct 2018 10:30:04 +0200 Subject: mem_forget: fix syntax error in code sample --- clippy_lints/src/mem_forget.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index dd2a1ca50e7..accd7bc220c 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -23,7 +23,7 @@ use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// /// **Example:** /// ```rust -/// mem::forget(Rc::new(55))) +/// mem::forget(Rc::new(55)) /// ``` declare_clippy_lint! { pub MEM_FORGET, -- cgit 1.4.1-3-g733a5 From 5c3928282699244f5e85a66f0cded09ea3dfbeda Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 14 Oct 2018 07:49:28 -0700 Subject: out_of_bounds_indexing refactoring --- clippy_lints/src/indexing_slicing.rs | 65 +++++++++++++++++------------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 8b7a1f7882b..9f9c25f7728 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -108,46 +108,41 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let ExprKind::Index(ref array, ref index) = &expr.node { let ty = cx.tables.expr_ty(array); if let Some(range) = higher::range(cx, index) { + // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); - match to_const_range(cx, range, size) { - (None, None) => {}, - (Some(start), None) => { - if start > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - return; - } - }, - (None, Some(end)) => { - if end > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - return; - } - }, - (Some(start), Some(end)) => { - if start > size || end > size { - utils::span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - expr.span, - "range is out of bounds", - ); - } - // early return because both start and end are constant + let const_range = to_const_range(cx, range, size); + + if let (Some(start), _) = const_range { + if start > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); + return; + } + } + + if let (_, Some(end)) = const_range { + if end > size { + utils::span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + expr.span, + "range is out of bounds", + ); return; - }, + } + } + + if let (Some(_), Some(_)) = const_range { + // early return because both start and end are constants + // and we have proven above that they are in bounds + return; } } -- cgit 1.4.1-3-g733a5 From 212a4fe4f4aaa8e592f4e7178d9c9a7bcd8c97be Mon Sep 17 00:00:00 2001 From: Oliver S̶c̶h̶n̶e̶i̶d̶e̶r Scherer Date: Sun, 14 Oct 2018 22:55:26 +0200 Subject: fix for rustc master --- clippy_lints/src/len_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index defb5892e51..1dd775051d9 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -276,7 +276,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { ty::Dynamic(ref tt, ..) => cx.tcx - .associated_items(tt.principal().expect("trait impl not found").def_id()) + .associated_items(tt.principal().def_id()) .any(|item| is_is_empty(cx, &item)), ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), -- cgit 1.4.1-3-g733a5 From 456843f1cd7d64015202338597cd3db79558dcbf Mon Sep 17 00:00:00 2001 From: Owen Sanchez Date: Sun, 14 Oct 2018 20:07:21 -0700 Subject: Swap order of methods in `needless_range_loop` suggestion in some cases --- clippy_lints/src/loops.rs | 40 +++++++++++++++++++++++++++++++------ tests/ui/author/for_loop.stderr | 0 tests/ui/needless_range_loop.rs | 14 +++++++++++++ tests/ui/needless_range_loop.stderr | 22 +++++++++++++++++++- tests/ui/ty_fn_sig.stderr | 0 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 tests/ui/author/for_loop.stderr create mode 100644 tests/ui/ty_fn_sig.stderr diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 064a8d5229d..3c4f06077d9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -27,6 +27,7 @@ use crate::rustc::ty::subst::Subst; use crate::rustc_errors::Applicability; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::iter::{once, Iterator}; +use std::mem; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax_pos::BytePos; @@ -1082,16 +1083,35 @@ fn check_for_loop_range<'a, 'tcx>( format!(".skip({})", snippet(cx, start.span, "..")) }; + let mut end_is_start_plus_val = false; + let take = if let Some(end) = *end { + let mut take_expr = end; + + if let ExprKind::Binary(ref op, ref left, ref right) = end.node { + if let BinOpKind::Add = op.node { + let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left); + let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right); + + if start_equal_left { + take_expr = right; + } else if start_equal_right { + take_expr = left; + } + + end_is_start_plus_val = start_equal_left | start_equal_right; + } + } + if is_len_call(end, indexed) { String::new() } else { match limits { ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, ""); - format!(".take({})", end + sugg::ONE) + let take_expr = sugg::Sugg::hir(cx, take_expr, ""); + format!(".take({})", take_expr + sugg::ONE) }, - ast::RangeLimits::HalfOpen => format!(".take({})", snippet(cx, end.span, "..")), + ast::RangeLimits::HalfOpen => format!(".take({})", snippet(cx, take_expr.span, "..")), } } } else { @@ -1104,6 +1124,14 @@ fn check_for_loop_range<'a, 'tcx>( ("", "iter") }; + let take_is_empty = take.is_empty(); + let mut method_1 = take; + let mut method_2 = skip; + + if end_is_start_plus_val { + mem::swap(&mut method_1, &mut method_2); + } + if visitor.nonindex { span_lint_and_then( cx, @@ -1116,16 +1144,16 @@ fn check_for_loop_range<'a, 'tcx>( "consider using an iterator".to_string(), vec![ (pat.span, format!("({}, )", ident.name)), - (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, take, skip)), + (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2)), ], ); }, ); } else { - let repl = if starts_at_zero && take.is_empty() { + let repl = if starts_at_zero && take_is_empty { format!("&{}{}", ref_mut, indexed) } else { - format!("{}.{}(){}{}", indexed, method, take, skip) + format!("{}.{}(){}{}", indexed, method, method_1, method_2) }; span_lint_and_then( diff --git a/tests/ui/author/for_loop.stderr b/tests/ui/author/for_loop.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 44515502835..3da9267d38b 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -62,4 +62,18 @@ fn main() { g[i] = g[i+1..].iter().sum(); } assert_eq!(g, vec![20, 18, 15, 11, 6, 0]); + + let x = 5; + let mut vec = vec![0; 9]; + + for i in x..x + 4 { + vec[i] += 1; + } + + let x = 5; + let mut vec = vec![0; 10]; + + for i in x..=x + 4 { + vec[i] += 1; + } } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 64b1f3c08f7..d62a0434d0b 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -30,5 +30,25 @@ help: consider using an iterator 45 | for in &mut ms { | ^^^^^^ ^^^^^^^ -error: aborting due to 3 previous errors +error: the loop variable `i` is only used to index `vec`. + --> $DIR/needless_range_loop.rs:69:14 + | +69 | for i in x..x + 4 { + | ^^^^^^^^ +help: consider using an iterator + | +69 | for in vec.iter_mut().skip(x).take(4) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the loop variable `i` is only used to index `vec`. + --> $DIR/needless_range_loop.rs:76:14 + | +76 | for i in x..=x + 4 { + | ^^^^^^^^^ +help: consider using an iterator + | +76 | for in vec.iter_mut().skip(x).take(4 + 1) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/ty_fn_sig.stderr b/tests/ui/ty_fn_sig.stderr new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From 3ad9290ea43fdf995dbb06af850ff7dbf53af620 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 14 Oct 2018 23:41:35 -0700 Subject: Restore clippy_dummy's placeholder name Fixes #3317 --- clippy_dummy/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dummy/Cargo.toml b/clippy_dummy/Cargo.toml index b53e89071ce..ed97cc45725 100644 --- a/clippy_dummy/Cargo.toml +++ b/clippy_dummy/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "clippy" # rename to clippy before publishing +name = "clippy_dummy" # rename to clippy before publishing version = "0.0.302" authors = ["Manish Goregaokar "] edition = "2018" -- cgit 1.4.1-3-g733a5 From 66d3672b2696918a074d193813af1f74d1c48be9 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Mon, 15 Oct 2018 04:44:39 -0700 Subject: out_of_bounds_indexing improved reporting of out of bounds value --- clippy_lints/src/indexing_slicing.rs | 4 +-- tests/ui/indexing_slicing.stderr | 68 ++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 9f9c25f7728..f960ab5958c 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { utils::span_lint( cx, OUT_OF_BOUNDS_INDEXING, - expr.span, + range.start.map_or(expr.span, |start| start.span), "range is out of bounds", ); return; @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { utils::span_lint( cx, OUT_OF_BOUNDS_INDEXING, - expr.span, + range.end.map_or(expr.span, |end| end.span), "range is out of bounds", ); return; diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index c587269e3e5..fafcb1bc485 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -48,18 +48,18 @@ error: slicing may panic. = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:30:6 + --> $DIR/indexing_slicing.rs:30:11 | 30 | &x[..=4]; - | ^^^^^^^ + | ^ | = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds - --> $DIR/indexing_slicing.rs:31:6 + --> $DIR/indexing_slicing.rs:31:11 | 31 | &x[1..5]; - | ^^^^^^^ + | ^ error: slicing may panic. --> $DIR/indexing_slicing.rs:32:6 @@ -70,34 +70,34 @@ error: slicing may panic. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:32:6 + --> $DIR/indexing_slicing.rs:32:8 | 32 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. - | ^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:33:6 + --> $DIR/indexing_slicing.rs:33:8 | 33 | &x[5..]; - | ^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:34:6 + --> $DIR/indexing_slicing.rs:34:10 | 34 | &x[..5]; - | ^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:35:6 + --> $DIR/indexing_slicing.rs:35:8 | 35 | &x[5..].iter().map(|x| 2 * x).collect::>(); - | ^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:36:6 + --> $DIR/indexing_slicing.rs:36:12 | 36 | &x[0..=4]; - | ^^^^^^^^ + | ^ error: slicing may panic. --> $DIR/indexing_slicing.rs:37:6 @@ -148,46 +148,46 @@ error: slicing may panic. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:60:6 + --> $DIR/indexing_slicing.rs:60:12 | 60 | &empty[1..5]; - | ^^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:61:6 + --> $DIR/indexing_slicing.rs:61:16 | 61 | &empty[0..=4]; - | ^^^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:62:6 + --> $DIR/indexing_slicing.rs:62:15 | 62 | &empty[..=4]; - | ^^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:63:6 + --> $DIR/indexing_slicing.rs:63:12 | 63 | &empty[1..]; - | ^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:64:6 + --> $DIR/indexing_slicing.rs:64:14 | 64 | &empty[..4]; - | ^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:65:6 + --> $DIR/indexing_slicing.rs:65:16 | 65 | &empty[0..=0]; - | ^^^^^^^^^^^^ + | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:66:6 + --> $DIR/indexing_slicing.rs:66:15 | 66 | &empty[..=0]; - | ^^^^^^^^^^^ + | ^ error: indexing may panic. --> $DIR/indexing_slicing.rs:74:5 @@ -230,10 +230,10 @@ error: slicing may panic. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:78:6 + --> $DIR/indexing_slicing.rs:78:8 | 78 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. - | ^^^^^^^ + | ^^ error: slicing may panic. --> $DIR/indexing_slicing.rs:79:6 @@ -268,16 +268,16 @@ error: indexing may panic. = help: Consider using `.get(n)` or `.get_mut(n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:97:6 + --> $DIR/indexing_slicing.rs:97:13 | 97 | &x[num..10]; // should trigger out of bounds error - | ^^^^^^^^^^ + | ^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:98:6 + --> $DIR/indexing_slicing.rs:98:8 | 98 | &x[10..num]; // should trigger out of bounds error - | ^^^^^^^^^^ + | ^^ error: aborting due to 39 previous errors -- cgit 1.4.1-3-g733a5 From 4c88362a9dd166388bfd7508041145dfdfb965e6 Mon Sep 17 00:00:00 2001 From: Park Juhyung Date: Mon, 15 Oct 2018 22:32:49 +0900 Subject: Website: Make lint categories linkable Fixes #2973 --- util/gh-pages/index.html | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 656a7341257..277eeaf39f4 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -167,6 +167,19 @@ }); } + function selectGroup($scope, selectedGroup) { + var groups = $scope.groups; + for (var group in groups) { + if (groups.hasOwnProperty(group)) { + if (group === selectedGroup) { + groups[group] = true; + } else { + groups[group] = false; + } + } + } + } + angular.module("clippy", []) .filter('markdown', function ($sce) { return function (text) { @@ -223,6 +236,11 @@ return result; }, {}); + var selectedGroup = getQueryVariable("sel"); + if (selectedGroup) { + selectGroup($scope, selectedGroup.toLowerCase()); + } + scrollToLintByURL($scope); }) .error(function (data) { @@ -243,6 +261,17 @@ }, false); }); })(); + + function getQueryVariable(variable) { + var query = window.location.search.substring(1); + var vars = query.split('&'); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split('='); + if (decodeURIComponent(pair[0]) == variable) { + return decodeURIComponent(pair[1]); + } + } + } -- cgit 1.4.1-3-g733a5 From 2d8b4f3d5cb771a67f119f3903dd4aca1e4c9136 Mon Sep 17 00:00:00 2001 From: Bruno Kirschner Date: Mon, 15 Oct 2018 20:20:50 +0200 Subject: Avoid linting `boxed_local` on trait implementations. --- clippy_lints/src/escape.rs | 13 ++++++++++++- tests/ui/escape_analysis.rs | 34 ++++++++++++++++++++++++++++------ tests/ui/escape_analysis.stderr | 16 ++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 0491cde4fed..b7646dd6fdf 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -65,6 +65,7 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, @@ -74,13 +75,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: Span, node_id: NodeId, ) { - let fn_def_id = cx.tcx.hir.local_def_id(node_id); + // If the method is an impl for a trait, don't warn + let parent_id = cx.tcx.hir.get_parent(node_id); + let parent_node = cx.tcx.hir.find(parent_id); + + if let Some(Node::Item(item)) = parent_node { + if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { + return; + } + } + let mut v = EscapeDelegate { cx, set: NodeSet(), too_large_for_stack: self.too_large_for_stack, }; + let fn_def_id = cx.tcx.hir.local_def_id(node_id); let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body); diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index 1f2f46b03cd..b35071546e7 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -7,12 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(box_syntax)] -#![allow(warnings, clippy)] - -#![warn(boxed_local)] +#![allow(clippy::borrowed_box, clippy::needless_pass_by_value, clippy::unused_unit)] +#![warn(clippy::boxed_local)] #[derive(Clone)] struct A; @@ -70,8 +68,7 @@ fn warn_pass() { } fn nowarn_return() -> Box { - let fx = box A; - fx // moved out, "escapes" + box A // moved out, "escapes" } fn nowarn_move() { @@ -139,3 +136,28 @@ pub struct PeekableSeekable { pub fn new(_needs_name: Box>) -> () { } + +/// Regression for #916, #1123 +/// +/// This shouldn't warn for `boxed_local`as the implementation of a trait +/// can't change much about the trait definition. +trait BoxedAction { + fn do_sth(self: Box); +} + +impl BoxedAction for u64 { + fn do_sth(self: Box) { + println!("{}", *self) + } +} + +/// Regression for #1478 +/// +/// This shouldn't warn for `boxed_local`as self itself is a box type. +trait MyTrait { + fn do_sth(self); +} + +impl MyTrait for Box { + fn do_sth(self) {} +} diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr index e69de29bb2d..25ba413b75a 100644 --- a/tests/ui/escape_analysis.stderr +++ b/tests/ui/escape_analysis.stderr @@ -0,0 +1,16 @@ +error: local variable doesn't need to be boxed here + --> $DIR/escape_analysis.rs:45:13 + | +45 | fn warn_arg(x: Box) { + | ^ + | + = note: `-D clippy::boxed-local` implied by `-D warnings` + +error: local variable doesn't need to be boxed here + --> $DIR/escape_analysis.rs:137:12 + | +137 | pub fn new(_needs_name: Box>) -> () { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 7da97a94dfe42768b38f6ba7dc5804cf8e5821fb Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 9 Oct 2018 08:08:50 +0200 Subject: Use `WalkDir` to also gather from subdirectories `fs::read_dir` does not recurse into subdirectories. --- clippy_dev/Cargo.toml | 1 + clippy_dev/src/lib.rs | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index d6057ba970c..5380ecd9814 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -9,3 +9,4 @@ clap = "~2.32" itertools = "0.7" regex = "1" lazy_static = "1.0" +walkdir = "2" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index eee9089e7c4..d312eadf89e 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -14,6 +14,7 @@ use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; +use walkdir::WalkDir; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -70,7 +71,7 @@ pub fn gather_all() -> impl Iterator { lint_files().flat_map(|f| gather_from_file(&f)) } -fn gather_from_file(dir_entry: &fs::DirEntry) -> impl Iterator { +fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); @@ -89,9 +90,9 @@ fn parse_contents(content: &str, filename: &str) -> impl Iterator { } /// Collects all .rs files in the `clippy_lints/src` directory -fn lint_files() -> impl Iterator { - fs::read_dir("../clippy_lints/src") - .unwrap() +fn lint_files() -> impl Iterator { + WalkDir::new("../clippy_lints/src") + .into_iter() .filter_map(|f| f.ok()) .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } -- cgit 1.4.1-3-g733a5 From fb830c53db356b22a2635ed50d0698fafe310321 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 15 Oct 2018 20:47:19 +0200 Subject: Some more documentation for clippy_dev --- clippy_dev/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index d312eadf89e..1bd9bffff06 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -36,6 +36,7 @@ lazy_static! { pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string(); } +/// Lint data parsed from the Clippy source code. #[derive(Clone, PartialEq, Debug)] pub struct Lint { pub name: String, @@ -67,6 +68,7 @@ impl Lint { } } +/// Gathers all files in `src/clippy_lints` and gathers all lints inside pub fn gather_all() -> impl Iterator { lint_files().flat_map(|f| gather_from_file(&f)) } -- cgit 1.4.1-3-g733a5 From b61ca63c5e91d8659af239e658bf313894aebd23 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 15 Oct 2018 21:02:38 +0200 Subject: sort_by -> sort_by_key --- clippy_dev/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index d1161323b02..9e78def78fe 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -44,7 +44,7 @@ fn print_lints() { if lint_group == "Deprecated" { continue; } println!("\n## {}", lint_group); - lints.sort_by(|a, b| a.name.cmp(&b.name)); + lints.sort_by_key(|l| l.name.clone()); for lint in lints { println!("* [{}]({}#{}) ({})", lint.name, clippy_dev::DOCS_LINK.clone(), lint.name, lint.desc); -- cgit 1.4.1-3-g733a5 From b5dd8f17d12ec6ccc96910c07f930e340fafeb3b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 15 Oct 2018 21:10:22 +0200 Subject: Add comment on WalkDir vs. fs::read_dir --- clippy_dev/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 1bd9bffff06..8477183ae56 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -93,6 +93,8 @@ fn parse_contents(content: &str, filename: &str) -> impl Iterator { /// Collects all .rs files in the `clippy_lints/src` directory fn lint_files() -> impl Iterator { + // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. + // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. WalkDir::new("../clippy_lints/src") .into_iter() .filter_map(|f| f.ok()) -- cgit 1.4.1-3-g733a5 From af441b5b072eb01c939d2e92a3496dbedf6d412b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Oct 2018 07:24:32 +0200 Subject: Rename `active_lints` to `usable_lints` Because now `usable_lints` will also exclude internal lints. --- clippy_dev/src/lib.rs | 14 ++++++++------ clippy_dev/src/main.rs | 8 +++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8477183ae56..d4b74f55717 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -57,9 +57,9 @@ impl Lint { } } - /// Returns all non-deprecated lints - pub fn active_lints(lints: impl Iterator) -> impl Iterator { - lints.filter(|l| l.deprecation.is_none()) + /// Returns all non-deprecated lints and non-internal lints + pub fn usable_lints(lints: impl Iterator) -> impl Iterator { + lints.filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) } /// Returns the lints in a HashMap, grouped by the different lint groups @@ -141,15 +141,17 @@ declare_deprecated_lint! { } #[test] -fn test_active_lints() { +fn test_usable_lints() { let lints = vec![ Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), - Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") + Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name") ]; let expected = vec![ Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") ]; - assert_eq!(expected, Lint::active_lints(lints.into_iter()).collect::>()); + assert_eq!(expected, Lint::usable_lints(lints.into_iter()).collect::>()); } #[test] diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 9e78def78fe..ff7d47366ae 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -37,8 +37,10 @@ fn main() { } fn print_lints() { - let lint_list = gather_all().collect::>(); - let grouped_by_lint_group = Lint::by_lint_group(&lint_list); + let lint_list = gather_all(); + let usable_lints: Vec = Lint::usable_lints(lint_list).collect(); + let lint_count = usable_lints.len(); + let grouped_by_lint_group = Lint::by_lint_group(&usable_lints); for (lint_group, mut lints) in grouped_by_lint_group { if lint_group == "Deprecated" { continue; } @@ -51,5 +53,5 @@ fn print_lints() { } } - println!("there are {} lints", Lint::active_lints(lint_list.into_iter()).count()); + println!("there are {} lints", lint_count); } -- cgit 1.4.1-3-g733a5 From 956987f43e3012c3487973cc0dd47f7c4eaa7942 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Oct 2018 08:00:31 +0200 Subject: RIIR update_lints: Replace lint count in README.md This allows the usage of `util/dev update_lints` which will write the new lint_count to the `README.md`. --- clippy_dev/src/lib.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ clippy_dev/src/main.rs | 20 +++++++++ 2 files changed, 139 insertions(+) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index d4b74f55717..1c303d180d2 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -101,6 +101,88 @@ fn lint_files() -> impl Iterator { .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } +/// Replace a region in a file delimited by two lines matching regexes. +/// +/// `path` is the relative path to the file on which you want to perform the replacement. +/// +/// See `replace_region_in_text` for documentation of the other options. +pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_start: bool, replacements: F) where F: Fn() -> Vec { + let mut f = fs::File::open(path).expect(&format!("File not found: {}", path)); + let mut contents = String::new(); + f.read_to_string(&mut contents).expect("Something went wrong reading the file"); + let replaced = replace_region_in_text(&contents, start, end, replace_start, replacements); + + let mut f = fs::File::create(path).expect(&format!("File not found: {}", path)); + f.write_all(replaced.as_bytes()).expect("Unable to write file"); + // Ensure we write the changes with a trailing newline so that + // the file has the proper line endings. + f.write(b"\n").expect("Unable to write file"); +} + +/// Replace a region in a text delimited by two lines matching regexes. +/// +/// * `text` is the input text on which you want to perform the replacement +/// * `start` is a `&str` that describes the delimiter line before the region you want to replace. +/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. +/// * `end` is a `&str` that describes the delimiter line until where the replacement should +/// happen. As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. +/// * If `replace_start` is true, the `start` delimiter line is replaced as well. +/// The `end` delimiter line is never replaced. +/// * `replacements` is a closure that has to return a `Vec` which contains the new text. +/// +/// If you want to perform the replacement on files instead of already parsed text, +/// use `replace_region_in_file`. +/// +/// # Example +/// +/// ``` +/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; +/// let result = clippy_dev::replace_region_in_text( +/// the_text, +/// r#"replace_start"#, +/// r#"replace_end"#, +/// false, +/// || { +/// vec!["a different".to_string(), "text".to_string()] +/// } +/// ); +/// assert_eq!("replace_start\na different\ntext\nreplace_end", result); +/// ``` +pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> String where F: Fn() -> Vec { + let lines = text.lines(); + let mut in_old_region = false; + let mut found = false; + let mut new_lines = vec![]; + let start = Regex::new(start).unwrap(); + let end = Regex::new(end).unwrap(); + + for line in lines { + if in_old_region { + if end.is_match(&line) { + in_old_region = false; + new_lines.extend(replacements()); + new_lines.push(line.to_string()); + } + } else if start.is_match(&line) { + if !replace_start { + new_lines.push(line.to_string()); + } + in_old_region = true; + found = true; + } else { + new_lines.push(line.to_string()); + } + } + + if !found { + // This happens if the provided regex in `clippy_dev/src/main.rs` is not found in the + // given text or file. Most likely this is an error on the programmer's side and the Regex + // is incorrect. + println!("regex {:?} not found. You may have to update it.", start); + } + new_lines.join("\n") +} + #[test] fn test_parse_contents() { let result: Vec = parse_contents( @@ -140,6 +222,43 @@ declare_deprecated_lint! { assert_eq!(expected, result); } +#[test] +fn test_replace_region() { + let text = r#" +abc +123 +789 +def +ghi"#; + let expected = r#" +abc +hello world +def +ghi"#; + let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { + vec!["hello world".to_string()] + }); + assert_eq!(expected, result); +} + +#[test] +fn test_replace_region_with_start() { + let text = r#" +abc +123 +789 +def +ghi"#; + let expected = r#" +hello world +def +ghi"#; + let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { + vec!["hello world".to_string()] + }); + assert_eq!(expected, result); +} + #[test] fn test_usable_lints() { let lints = vec![ diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index ff7d47366ae..7b688836a95 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -32,6 +32,8 @@ fn main() { if let Some(matches) = matches.subcommand_matches("update_lints") { if matches.is_present("print-only") { print_lints(); + } else { + update_lints(); } } } @@ -55,3 +57,21 @@ fn print_lints() { println!("there are {} lints", lint_count); } + +fn update_lints() { + let lint_list = gather_all(); + let usable_lints: Vec = Lint::usable_lints(lint_list).collect(); + let lint_count = usable_lints.len(); + + replace_region_in_file( + "../README.md", + r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#, + "", + true, + || { + vec![ + format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count) + ] + } + ); +} -- cgit 1.4.1-3-g733a5 From 33847b579eb5479f888a0caae37ebc469dd9ccd2 Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Tue, 16 Oct 2018 09:04:02 -0400 Subject: Update known problems for unnecessary_fold --- clippy_lints/src/methods/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 7c15eb677cc..6fc563a42ea 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -688,7 +688,8 @@ declare_clippy_lint! { /// /// **Why is this bad?** Readability. /// -/// **Known problems:** None. +/// **Known problems:** False positive in pattern guards. Will be resolved once +/// non-lexical lifetimes are stable. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 05ffc2d05743c0cc4ad5e551c147dc8385e67bac Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Oct 2018 20:58:00 +0200 Subject: Fix dogfood `expect_fun_call` causes a false-positive, so I disabled it for now. --- clippy_dev/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 1c303d180d2..dcb2de2b1f8 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -106,6 +106,7 @@ fn lint_files() -> impl Iterator { /// `path` is the relative path to the file on which you want to perform the replacement. /// /// See `replace_region_in_text` for documentation of the other options. +#[allow(clippy::expect_fun_call)] pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_start: bool, replacements: F) where F: Fn() -> Vec { let mut f = fs::File::open(path).expect(&format!("File not found: {}", path)); let mut contents = String::new(); @@ -116,7 +117,7 @@ pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_sta f.write_all(replaced.as_bytes()).expect("Unable to write file"); // Ensure we write the changes with a trailing newline so that // the file has the proper line endings. - f.write(b"\n").expect("Unable to write file"); + f.write_all(b"\n").expect("Unable to write file"); } /// Replace a region in a text delimited by two lines matching regexes. -- cgit 1.4.1-3-g733a5 From 8c902d1cf263c38416ccf4bf48d143d40c75f8db Mon Sep 17 00:00:00 2001 From: Owen Sanchez Date: Mon, 15 Oct 2018 21:12:59 -0700 Subject: Simplify manual_memcpy suggestion in some cases --- clippy_lints/src/loops.rs | 16 ++++++++++++++-- tests/ui/for_loop.rs | 13 +++++++++++++ tests/ui/for_loop.stderr | 26 +++++++++++++++++++------- tests/ui/for_loop.stdout | 0 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/ui/for_loop.stdout diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3c4f06077d9..4c505ababf1 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -950,8 +950,20 @@ fn detect_manual_memcpy<'a, 'tcx>( ("0", _, x, false) | (x, false, "0", false) => x.into(), ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), - (x, false, y, true) => format!("({} - {})", x, y), - (x, true, y, false) => format!("({} - {})", y, x), + (x, false, y, true) => { + if x == y { + "0".into() + } else { + format!("({} - {})", x, y) + } + }, + (x, true, y, false) => { + if x == y { + "0".into() + } else { + format!("({} - {})", y, x) + } + }, (x, true, y, true) => format!("-({} + {})", x, y), } }; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 89c452f44df..f80270d9fe8 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -550,6 +550,19 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { for i in 0..10 { dst_vec[i] = src[i]; } + + // Simplify suggestion (issue #3004) + let src = [0, 1, 2, 3, 4]; + let mut dst = [0, 0, 0, 0, 0, 0]; + let from = 1; + + for i in from..from + src.len() { + dst[i] = src[i - from]; + } + + for i in from..from + 3 { + dst[i] = src[i - from]; + } } #[warn(clippy::needless_range_loop)] diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 472fa148609..33176335783 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -482,22 +482,34 @@ error: it looks like you're manually copying between slices | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:557:14 + --> $DIR/for_loop.rs:559:14 | -557 | for i in 0..src.len() { +559 | for i in from..from + src.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:563:14 + | +563 | for i in from..from + 3 { + | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:570:14 + | +570 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:618:19 + --> $DIR/for_loop.rs:631:19 | -618 | for ch in text.chars() { +631 | for ch in text.chars() { | ^^^^^^^^^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:629:19 + --> $DIR/for_loop.rs:642:19 | -629 | for ch in text.chars() { +642 | for ch in text.chars() { | ^^^^^^^^^^^^ -error: aborting due to 61 previous errors +error: aborting due to 63 previous errors diff --git a/tests/ui/for_loop.stdout b/tests/ui/for_loop.stdout new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From aa88e68902663db1bc5e5aa93c7884e405dd6b32 Mon Sep 17 00:00:00 2001 From: Giorgio Gambino Date: Tue, 16 Oct 2018 23:23:31 +0200 Subject: Fix issue #3322: reword help message for len_zero --- clippy_lints/src/len_zero.rs | 2 +- tests/ui/len_zero.stderr | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 1dd775051d9..789a569f4cd 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -240,7 +240,7 @@ fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Ex LEN_ZERO, span, &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), - "using `is_empty` is more concise", + "using `is_empty` is clearer and more explicit", format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")), ); } diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index ffba33a65f8..1f937bafdef 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -46,7 +46,7 @@ error: length comparison to zero --> $DIR/len_zero.rs:151:8 | 151 | if x.len() == 0 { - | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `x.is_empty()` + | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` | = note: `-D clippy::len-zero` implied by `-D warnings` @@ -54,79 +54,79 @@ error: length comparison to zero --> $DIR/len_zero.rs:155:8 | 155 | if "".len() == 0 {} - | ^^^^^^^^^^^^^ help: using `is_empty` is more concise: `"".is_empty()` + | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:170:8 | 170 | if has_is_empty.len() == 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:173:8 | 173 | if has_is_empty.len() != 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:176:8 | 176 | if has_is_empty.len() > 0 { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:179:8 | 179 | if has_is_empty.len() < 1 { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:182:8 | 182 | if has_is_empty.len() >= 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:193:8 | 193 | if 0 == has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:196:8 | 196 | if 0 != has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:199:8 | 199 | if 0 < has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:202:8 | 202 | if 1 <= has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:205:8 | 205 | if 1 > has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:219:8 | 219 | if with_is_empty.len() == 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `with_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:232:8 | 232 | if b.len() != 0 {} - | ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()` + | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method --> $DIR/len_zero.rs:238:1 -- cgit 1.4.1-3-g733a5 From 3b7c88888bb9b01eb9ca8f40f59b48006462f2b5 Mon Sep 17 00:00:00 2001 From: CYBAI Date: Sun, 7 Oct 2018 21:36:42 +0800 Subject: Add lint for redundant pattern matching for explicit return boolean --- .../src/if_let_redundant_pattern_matching.rs | 192 +++++++++++++++++---- tests/ui/if_let_redundant_pattern_matching.rs | 30 ++++ tests/ui/if_let_redundant_pattern_matching.stderr | 56 +++++- 3 files changed, 241 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index bced0c9552d..6f786fc5659 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -11,6 +11,8 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; +use crate::syntax::ptr::P; +use crate::syntax::ast::LitKind; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; use crate::rustc_errors::Applicability; @@ -58,46 +60,164 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { #[allow(clippy::similar_names)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::Match(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { - if arms[0].pats.len() == 1 { - let good_method = match arms[0].pats[0].node { - PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { - if let PatKind::Wild = pats[0].node { - if match_qpath(path, &paths::RESULT_OK) { - "is_ok()" - } else if match_qpath(path, &paths::RESULT_ERR) { - "is_err()" - } else if match_qpath(path, &paths::OPTION_SOME) { - "is_some()" - } else { - return; - } - } else { - return; - } - }, + if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node { + match match_source { + MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), + MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms), + _ => return, + } + } + } +} - PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", +fn find_sugg_for_if_let<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, + op: &P, + arms: &HirVec +) { + if arms[0].pats.len() == 1 { + let good_method = match arms[0].pats[0].node { + PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { + if let PatKind::Wild = pats[0].node { + if match_qpath(path, &paths::RESULT_OK) { + "is_ok()" + } else if match_qpath(path, &paths::RESULT_ERR) { + "is_err()" + } else if match_qpath(path, &paths::OPTION_SOME) { + "is_some()" + } else { + return; + } + } else { + return; + } + }, - _ => return, - }; + PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", - span_lint_and_then( - cx, - IF_LET_REDUNDANT_PATTERN_MATCHING, - arms[0].pats[0].span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |db| { - let span = expr.span.to(op.span); - db.span_suggestion_with_applicability( - span, - "try this", - format!("if {}.{}", snippet(cx, op.span, "_"), good_method), - Applicability::MachineApplicable, // snippet - ); - }, + _ => return, + }; + + span_lint_and_then( + cx, + IF_LET_REDUNDANT_PATTERN_MATCHING, + arms[0].pats[0].span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.to(op.span); + db.span_suggestion_with_applicability( + span, + "try this", + format!("if {}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::MachineApplicable, // snippet ); - } + }, + ); + } else { + return; + } +} + +fn find_sugg_for_match<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, + op: &P, + arms: &HirVec +) { + if arms.len() == 2 { + let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node); + + let found_good_method = match node_pair { + ( + PatKind::TupleStruct(ref path_left, ref pats_left, _), + PatKind::TupleStruct(ref path_right, ref pats_right, _) + ) if pats_left.len() == 1 && pats_right.len() == 1 => { + if let (PatKind::Wild, PatKind::Wild) = (&pats_left[0].node, &pats_right[0].node) { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::RESULT_OK, + &paths::RESULT_ERR, + "is_ok()", + "is_err()" + ) + } else { + None + } + }, + ( + PatKind::TupleStruct(ref path_left, ref pats, _), + PatKind::Path(ref path_right) + ) | ( + PatKind::Path(ref path_left), + PatKind::TupleStruct(ref path_right, ref pats, _) + ) if pats.len() == 1 => { + if let PatKind::Wild = pats[0].node { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::OPTION_SOME, + &paths::OPTION_NONE, + "is_some()", + "is_none()" + ) + } else { + None + } + }, + _ => None, + }; + + if let Some(good_method) = found_good_method { + span_lint_and_then( + cx, + IF_LET_REDUNDANT_PATTERN_MATCHING, + expr.span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.to(op.span); + db.span_suggestion_with_applicability( + span, + "try this", + format!("{}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::MachineApplicable, // snippet + ); + }, + ); } + } else { + return; + } +} + +fn find_good_method_for_match<'a>( + arms: &HirVec, + path_left: &QPath, + path_right: &QPath, + expected_left: &[&str], + expected_right: &[&str], + should_be_left: &'a str, + should_be_right: &'a str +) -> Option<&'a str> { + let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { + (&(*arms[0].body).node, &(*arms[1].body).node) + } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { + (&(*arms[1].body).node, &(*arms[0].body).node) + } else { + return None; + }; + + match body_node_pair { + (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => { + match (&lit_left.node, &lit_right.node) { + (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), + (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), + _ => None, + } + }, + _ => None, } } diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs index 1c0e7e79c68..3f7d0c8e1bd 100644 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ b/tests/ui/if_let_redundant_pattern_matching.rs @@ -42,4 +42,34 @@ fn main() { if let Ok(x) = Ok::(42) { println!("{}", x); } + + match Ok::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Ok::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; } diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr index 5111de67189..93bafa7fcbd 100644 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ b/tests/ui/if_let_redundant_pattern_matching.stderr @@ -30,5 +30,59 @@ error: redundant pattern matching, consider using `is_some()` 28 | | } | |_____- help: try this: `if Some(42).is_some()` -error: aborting due to 4 previous errors +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/if_let_redundant_pattern_matching.rs:46:5 + | +46 | / match Ok::(42) { +47 | | Ok(_) => true, +48 | | Err(_) => false, +49 | | }; + | |_____^ help: try this: `Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/if_let_redundant_pattern_matching.rs:51:5 + | +51 | / match Ok::(42) { +52 | | Ok(_) => false, +53 | | Err(_) => true, +54 | | }; + | |_____^ help: try this: `Ok::(42).is_err()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/if_let_redundant_pattern_matching.rs:56:5 + | +56 | / match Err::(42) { +57 | | Ok(_) => false, +58 | | Err(_) => true, +59 | | }; + | |_____^ help: try this: `Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/if_let_redundant_pattern_matching.rs:61:5 + | +61 | / match Err::(42) { +62 | | Ok(_) => true, +63 | | Err(_) => false, +64 | | }; + | |_____^ help: try this: `Err::(42).is_ok()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/if_let_redundant_pattern_matching.rs:66:5 + | +66 | / match Some(42) { +67 | | Some(_) => true, +68 | | None => false, +69 | | }; + | |_____^ help: try this: `Some(42).is_some()` + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/if_let_redundant_pattern_matching.rs:71:5 + | +71 | / match None::<()> { +72 | | Some(_) => false, +73 | | None => true, +74 | | }; + | |_____^ help: try this: `None::<()>.is_none()` + +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 66ae3b124949d07c2a50e051b166b93029ecc4ca Mon Sep 17 00:00:00 2001 From: CYBAI Date: Wed, 10 Oct 2018 23:13:53 +0800 Subject: Rename if_let_redundant_pattern_matching to redundant_pattern_matching Also, making the old one deprecated --- CHANGELOG.md | 1 + clippy_lints/src/deprecated_lints.rs | 12 +- .../src/if_let_redundant_pattern_matching.rs | 223 -------------------- clippy_lints/src/lib.rs | 12 +- clippy_lints/src/redundant_pattern_matching.rs | 228 +++++++++++++++++++++ tests/ui/if_let_redundant_pattern_matching.rs | 75 ------- tests/ui/if_let_redundant_pattern_matching.stderr | 88 -------- tests/ui/matches.rs | 2 +- tests/ui/needless_pass_by_value.rs | 2 +- tests/ui/redundant_pattern_matching.rs | 75 +++++++ tests/ui/redundant_pattern_matching.stderr | 88 ++++++++ 11 files changed, 413 insertions(+), 393 deletions(-) delete mode 100644 clippy_lints/src/if_let_redundant_pattern_matching.rs create mode 100644 clippy_lints/src/redundant_pattern_matching.rs delete mode 100644 tests/ui/if_let_redundant_pattern_matching.rs delete mode 100644 tests/ui/if_let_redundant_pattern_matching.stderr create mode 100644 tests/ui/redundant_pattern_matching.rs create mode 100644 tests/ui/redundant_pattern_matching.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index e6792c06894..626c39457e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -816,6 +816,7 @@ All notable changes to this project will be documented in this file. [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern +[`redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern_matching [`ref_in_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ref_in_deref [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 0067629bbd0..904036fe888 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -16,7 +16,7 @@ macro_rules! declare_deprecated_lint { /// **What it does:** Nothing. This lint has been deprecated. /// -/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend +/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend /// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011. declare_deprecated_lint! { pub SHOULD_ASSERT_EQ, @@ -102,3 +102,13 @@ declare_deprecated_lint! { pub ASSIGN_OPS, "using compound assignment operators (e.g. `+=`) is harmless" } + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** The original rule will only lint for `if let`. After +/// making it support to lint `match`, naming as `if let` is not suitable for it. +/// So, this lint is deprecated. +declare_deprecated_lint! { + pub IF_LET_REDUNDANT_PATTERN_MATCHING, + "this lint has been changed to redundant_pattern_matching" +} diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs deleted file mode 100644 index 6f786fc5659..00000000000 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; -use crate::syntax::ptr::P; -use crate::syntax::ast::LitKind; -use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; -use crate::rustc_errors::Applicability; - -/// **What it does:** Lint for redundant pattern matching over `Result` or -/// `Option` -/// -/// **Why is this bad?** It's more concise and clear to just use the proper -/// utility function -/// -/// **Known problems:** None. -/// -/// **Example:** -/// -/// ```rust -/// if let Ok(_) = Ok::(42) {} -/// if let Err(_) = Err::(42) {} -/// if let None = None::<()> {} -/// if let Some(_) = Some(42) {} -/// ``` -/// -/// The more idiomatic use would be: -/// -/// ```rust -/// if Ok::(42).is_ok() {} -/// if Err::(42).is_err() {} -/// if None::<()>.is_none() {} -/// if Some(42).is_some() {} -/// ``` -/// -declare_clippy_lint! { - pub IF_LET_REDUNDANT_PATTERN_MATCHING, - style, - "use the proper utility function avoiding an `if let`" -} - -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(IF_LET_REDUNDANT_PATTERN_MATCHING) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - #[allow(clippy::similar_names)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node { - match match_source { - MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), - MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms), - _ => return, - } - } - } -} - -fn find_sugg_for_if_let<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr, - op: &P, - arms: &HirVec -) { - if arms[0].pats.len() == 1 { - let good_method = match arms[0].pats[0].node { - PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { - if let PatKind::Wild = pats[0].node { - if match_qpath(path, &paths::RESULT_OK) { - "is_ok()" - } else if match_qpath(path, &paths::RESULT_ERR) { - "is_err()" - } else if match_qpath(path, &paths::OPTION_SOME) { - "is_some()" - } else { - return; - } - } else { - return; - } - }, - - PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", - - _ => return, - }; - - span_lint_and_then( - cx, - IF_LET_REDUNDANT_PATTERN_MATCHING, - arms[0].pats[0].span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |db| { - let span = expr.span.to(op.span); - db.span_suggestion_with_applicability( - span, - "try this", - format!("if {}.{}", snippet(cx, op.span, "_"), good_method), - Applicability::MachineApplicable, // snippet - ); - }, - ); - } else { - return; - } -} - -fn find_sugg_for_match<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr, - op: &P, - arms: &HirVec -) { - if arms.len() == 2 { - let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node); - - let found_good_method = match node_pair { - ( - PatKind::TupleStruct(ref path_left, ref pats_left, _), - PatKind::TupleStruct(ref path_right, ref pats_right, _) - ) if pats_left.len() == 1 && pats_right.len() == 1 => { - if let (PatKind::Wild, PatKind::Wild) = (&pats_left[0].node, &pats_right[0].node) { - find_good_method_for_match( - arms, - path_left, - path_right, - &paths::RESULT_OK, - &paths::RESULT_ERR, - "is_ok()", - "is_err()" - ) - } else { - None - } - }, - ( - PatKind::TupleStruct(ref path_left, ref pats, _), - PatKind::Path(ref path_right) - ) | ( - PatKind::Path(ref path_left), - PatKind::TupleStruct(ref path_right, ref pats, _) - ) if pats.len() == 1 => { - if let PatKind::Wild = pats[0].node { - find_good_method_for_match( - arms, - path_left, - path_right, - &paths::OPTION_SOME, - &paths::OPTION_NONE, - "is_some()", - "is_none()" - ) - } else { - None - } - }, - _ => None, - }; - - if let Some(good_method) = found_good_method { - span_lint_and_then( - cx, - IF_LET_REDUNDANT_PATTERN_MATCHING, - expr.span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |db| { - let span = expr.span.to(op.span); - db.span_suggestion_with_applicability( - span, - "try this", - format!("{}.{}", snippet(cx, op.span, "_"), good_method), - Applicability::MachineApplicable, // snippet - ); - }, - ); - } - } else { - return; - } -} - -fn find_good_method_for_match<'a>( - arms: &HirVec, - path_left: &QPath, - path_right: &QPath, - expected_left: &[&str], - expected_right: &[&str], - should_be_left: &'a str, - should_be_right: &'a str -) -> Option<&'a str> { - let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { - (&(*arms[0].body).node, &(*arms[1].body).node) - } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { - (&(*arms[1].body).node, &(*arms[0].body).node) - } else { - return None; - }; - - match body_node_pair { - (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => { - match (&lit_left.node, &lit_right.node) { - (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), - (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), - _ => None, - } - }, - _ => None, - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 35c89e4efde..23bd71a08ab 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -126,7 +126,6 @@ pub mod formatting; pub mod functions; pub mod identity_conversion; pub mod identity_op; -pub mod if_let_redundant_pattern_matching; pub mod if_not_else; pub mod indexing_slicing; pub mod infallible_destructuring_match; @@ -180,6 +179,7 @@ pub mod ptr_offset_with_cast; pub mod question_mark; pub mod ranges; pub mod redundant_field_names; +pub mod redundant_pattern_matching; pub mod reference; pub mod regex; pub mod replace_consts; @@ -303,6 +303,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { "assign_ops", "using compound assignment operators (e.g. `+=`) is harmless", ); + store.register_removed( + "if_let_redundant_pattern_matching", + "this lint has been changed to redundant_pattern_matching", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); @@ -402,7 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box missing_doc::MissingDoc::new()); reg.register_late_lint_pass(box missing_inline::MissingInline); reg.register_late_lint_pass(box ok_if_let::Pass); - reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass); + reg.register_late_lint_pass(box redundant_pattern_matching::Pass); reg.register_late_lint_pass(box partialeq_ne_impl::Pass); reg.register_early_lint_pass(box reference::Pass); reg.register_early_lint_pass(box reference::DerefPass); @@ -565,7 +569,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { functions::TOO_MANY_ARGUMENTS, identity_conversion::IDENTITY_CONVERSION, identity_op::IDENTITY_OP, - if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, indexing_slicing::OUT_OF_BOUNDS_INDEXING, infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, infinite_iter::INFINITE_ITER, @@ -680,6 +683,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ranges::RANGE_PLUS_ONE, ranges::RANGE_ZIP_WITH_LEN, redundant_field_names::REDUNDANT_FIELD_NAMES, + redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING, reference::DEREF_ADDROF, reference::REF_IN_DEREF, regex::INVALID_REGEX, @@ -749,7 +753,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { excessive_precision::EXCESSIVE_PRECISION, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, - if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING, infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, @@ -800,6 +803,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ptr::PTR_ARG, question_mark::QUESTION_MARK, redundant_field_names::REDUNDANT_FIELD_NAMES, + redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING, regex::REGEX_MACRO, regex::TRIVIAL_REGEX, returns::LET_AND_RETURN, diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs new file mode 100644 index 00000000000..f8c5b29bad1 --- /dev/null +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -0,0 +1,228 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::hir::*; +use crate::syntax::ptr::P; +use crate::syntax::ast::LitKind; +use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; +use crate::rustc_errors::Applicability; + +/// **What it does:** Lint for redundant pattern matching over `Result` or +/// `Option` +/// +/// **Why is this bad?** It's more concise and clear to just use the proper +/// utility function +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// if let Ok(_) = Ok::(42) {} +/// if let Err(_) = Err::(42) {} +/// if let None = None::<()> {} +/// if let Some(_) = Some(42) {} +/// match Ok::(42) { +/// Ok(_) => true, +/// Err(_) => false, +/// }; +/// ``` +/// +/// The more idiomatic use would be: +/// +/// ```rust +/// if Ok::(42).is_ok() {} +/// if Err::(42).is_err() {} +/// if None::<()>.is_none() {} +/// if Some(42).is_some() {} +/// Ok::(42).is_ok(); +/// ``` +/// +declare_clippy_lint! { + pub REDUNDANT_PATTERN_MATCHING, + style, + "use the proper utility function avoiding an `if let`" +} + +#[derive(Copy, Clone)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_PATTERN_MATCHING) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + #[allow(clippy::similar_names)] + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node { + match match_source { + MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), + MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms), + _ => return, + } + } + } +} + +fn find_sugg_for_if_let<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, + op: &P, + arms: &HirVec +) { + if arms[0].pats.len() == 1 { + let good_method = match arms[0].pats[0].node { + PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { + if let PatKind::Wild = pats[0].node { + if match_qpath(path, &paths::RESULT_OK) { + "is_ok()" + } else if match_qpath(path, &paths::RESULT_ERR) { + "is_err()" + } else if match_qpath(path, &paths::OPTION_SOME) { + "is_some()" + } else { + return; + } + } else { + return; + } + }, + + PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", + + _ => return, + }; + + span_lint_and_then( + cx, + REDUNDANT_PATTERN_MATCHING, + arms[0].pats[0].span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.to(op.span); + db.span_suggestion_with_applicability( + span, + "try this", + format!("if {}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::MachineApplicable, // snippet + ); + }, + ); + } else { + return; + } +} + +fn find_sugg_for_match<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, + op: &P, + arms: &HirVec +) { + if arms.len() == 2 { + let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node); + + let found_good_method = match node_pair { + ( + PatKind::TupleStruct(ref path_left, ref pats_left, _), + PatKind::TupleStruct(ref path_right, ref pats_right, _) + ) if pats_left.len() == 1 && pats_right.len() == 1 => { + if let (PatKind::Wild, PatKind::Wild) = (&pats_left[0].node, &pats_right[0].node) { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::RESULT_OK, + &paths::RESULT_ERR, + "is_ok()", + "is_err()" + ) + } else { + None + } + }, + ( + PatKind::TupleStruct(ref path_left, ref pats, _), + PatKind::Path(ref path_right) + ) | ( + PatKind::Path(ref path_left), + PatKind::TupleStruct(ref path_right, ref pats, _) + ) if pats.len() == 1 => { + if let PatKind::Wild = pats[0].node { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::OPTION_SOME, + &paths::OPTION_NONE, + "is_some()", + "is_none()" + ) + } else { + None + } + }, + _ => None, + }; + + if let Some(good_method) = found_good_method { + span_lint_and_then( + cx, + REDUNDANT_PATTERN_MATCHING, + expr.span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.to(op.span); + db.span_suggestion_with_applicability( + span, + "try this", + format!("{}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::MachineApplicable, // snippet + ); + }, + ); + } + } else { + return; + } +} + +fn find_good_method_for_match<'a>( + arms: &HirVec, + path_left: &QPath, + path_right: &QPath, + expected_left: &[&str], + expected_right: &[&str], + should_be_left: &'a str, + should_be_right: &'a str +) -> Option<&'a str> { + let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { + (&(*arms[0].body).node, &(*arms[1].body).node) + } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { + (&(*arms[1].body).node, &(*arms[0].body).node) + } else { + return None; + }; + + match body_node_pair { + (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => { + match (&lit_left.node, &lit_right.node) { + (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), + (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), + _ => None, + } + }, + _ => None, + } +} diff --git a/tests/ui/if_let_redundant_pattern_matching.rs b/tests/ui/if_let_redundant_pattern_matching.rs deleted file mode 100644 index 3f7d0c8e1bd..00000000000 --- a/tests/ui/if_let_redundant_pattern_matching.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - - -#![warn(clippy::all)] -#![warn(clippy::if_let_redundant_pattern_matching)] - - -fn main() { - if let Ok(_) = Ok::(42) {} - - if let Err(_) = Err::(42) { - } - - if let None = None::<()> { - } - - if let Some(_) = Some(42) { - } - - if Ok::(42).is_ok() { - } - - if Err::(42).is_err() { - } - - if None::.is_none() { - } - - if Some(42).is_some() { - } - - if let Ok(x) = Ok::(42) { - println!("{}", x); - } - - match Ok::(42) { - Ok(_) => true, - Err(_) => false, - }; - - match Ok::(42) { - Ok(_) => false, - Err(_) => true, - }; - - match Err::(42) { - Ok(_) => false, - Err(_) => true, - }; - - match Err::(42) { - Ok(_) => true, - Err(_) => false, - }; - - match Some(42) { - Some(_) => true, - None => false, - }; - - match None::<()> { - Some(_) => false, - None => true, - }; -} diff --git a/tests/ui/if_let_redundant_pattern_matching.stderr b/tests/ui/if_let_redundant_pattern_matching.stderr deleted file mode 100644 index 93bafa7fcbd..00000000000 --- a/tests/ui/if_let_redundant_pattern_matching.stderr +++ /dev/null @@ -1,88 +0,0 @@ -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/if_let_redundant_pattern_matching.rs:19:12 - | -19 | if let Ok(_) = Ok::(42) {} - | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` - | - = note: `-D clippy::if-let-redundant-pattern-matching` implied by `-D warnings` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/if_let_redundant_pattern_matching.rs:21:12 - | -21 | if let Err(_) = Err::(42) { - | _____- ^^^^^^ -22 | | } - | |_____- help: try this: `if Err::(42).is_err()` - -error: redundant pattern matching, consider using `is_none()` - --> $DIR/if_let_redundant_pattern_matching.rs:24:12 - | -24 | if let None = None::<()> { - | _____- ^^^^ -25 | | } - | |_____- help: try this: `if None::<()>.is_none()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/if_let_redundant_pattern_matching.rs:27:12 - | -27 | if let Some(_) = Some(42) { - | _____- ^^^^^^^ -28 | | } - | |_____- help: try this: `if Some(42).is_some()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/if_let_redundant_pattern_matching.rs:46:5 - | -46 | / match Ok::(42) { -47 | | Ok(_) => true, -48 | | Err(_) => false, -49 | | }; - | |_____^ help: try this: `Ok::(42).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/if_let_redundant_pattern_matching.rs:51:5 - | -51 | / match Ok::(42) { -52 | | Ok(_) => false, -53 | | Err(_) => true, -54 | | }; - | |_____^ help: try this: `Ok::(42).is_err()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/if_let_redundant_pattern_matching.rs:56:5 - | -56 | / match Err::(42) { -57 | | Ok(_) => false, -58 | | Err(_) => true, -59 | | }; - | |_____^ help: try this: `Err::(42).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/if_let_redundant_pattern_matching.rs:61:5 - | -61 | / match Err::(42) { -62 | | Ok(_) => true, -63 | | Err(_) => false, -64 | | }; - | |_____^ help: try this: `Err::(42).is_ok()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/if_let_redundant_pattern_matching.rs:66:5 - | -66 | / match Some(42) { -67 | | Some(_) => true, -68 | | None => false, -69 | | }; - | |_____^ help: try this: `Some(42).is_some()` - -error: redundant pattern matching, consider using `is_none()` - --> $DIR/if_let_redundant_pattern_matching.rs:71:5 - | -71 | / match None::<()> { -72 | | Some(_) => false, -73 | | None => true, -74 | | }; - | |_____^ help: try this: `None::<()>.is_none()` - -error: aborting due to 10 previous errors - diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index c43fead08f8..d31e97c7959 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -13,7 +13,7 @@ #![warn(clippy::all)] -#![allow(unused, clippy::if_let_redundant_pattern_matching)] +#![allow(unused, clippy::redundant_pattern_matching)] #![warn(clippy::single_match_else, clippy::match_same_arms)] enum ExprNode { diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 5825d9e9074..48b7b42cc8c 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -11,7 +11,7 @@ #![warn(clippy::needless_pass_by_value)] -#![allow(dead_code, clippy::single_match, clippy::if_let_redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)] +#![allow(dead_code, clippy::single_match, clippy::redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)] use std::borrow::Borrow; use std::convert::AsRef; diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs new file mode 100644 index 00000000000..50838584f66 --- /dev/null +++ b/tests/ui/redundant_pattern_matching.rs @@ -0,0 +1,75 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + + + + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] + + +fn main() { + if let Ok(_) = Ok::(42) {} + + if let Err(_) = Err::(42) { + } + + if let None = None::<()> { + } + + if let Some(_) = Some(42) { + } + + if Ok::(42).is_ok() { + } + + if Err::(42).is_err() { + } + + if None::.is_none() { + } + + if Some(42).is_some() { + } + + if let Ok(x) = Ok::(42) { + println!("{}", x); + } + + match Ok::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Ok::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; +} diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr new file mode 100644 index 00000000000..a42ac7ba04d --- /dev/null +++ b/tests/ui/redundant_pattern_matching.stderr @@ -0,0 +1,88 @@ +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching.rs:19:12 + | +19 | if let Ok(_) = Ok::(42) {} + | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching.rs:21:12 + | +21 | if let Err(_) = Err::(42) { + | _____- ^^^^^^ +22 | | } + | |_____- help: try this: `if Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching.rs:24:12 + | +24 | if let None = None::<()> { + | _____- ^^^^ +25 | | } + | |_____- help: try this: `if None::<()>.is_none()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching.rs:27:12 + | +27 | if let Some(_) = Some(42) { + | _____- ^^^^^^^ +28 | | } + | |_____- help: try this: `if Some(42).is_some()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching.rs:46:5 + | +46 | / match Ok::(42) { +47 | | Ok(_) => true, +48 | | Err(_) => false, +49 | | }; + | |_____^ help: try this: `Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching.rs:51:5 + | +51 | / match Ok::(42) { +52 | | Ok(_) => false, +53 | | Err(_) => true, +54 | | }; + | |_____^ help: try this: `Ok::(42).is_err()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching.rs:56:5 + | +56 | / match Err::(42) { +57 | | Ok(_) => false, +58 | | Err(_) => true, +59 | | }; + | |_____^ help: try this: `Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching.rs:61:5 + | +61 | / match Err::(42) { +62 | | Ok(_) => true, +63 | | Err(_) => false, +64 | | }; + | |_____^ help: try this: `Err::(42).is_ok()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching.rs:66:5 + | +66 | / match Some(42) { +67 | | Some(_) => true, +68 | | None => false, +69 | | }; + | |_____^ help: try this: `Some(42).is_some()` + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching.rs:71:5 + | +71 | / match None::<()> { +72 | | Some(_) => false, +73 | | None => true, +74 | | }; + | |_____^ help: try this: `None::<()>.is_none()` + +error: aborting due to 10 previous errors + -- cgit 1.4.1-3-g733a5 From 9f3ac4e5a396170c6f59e0f654c65b5ba0c4e5e5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 17 Oct 2018 08:18:05 +0200 Subject: RIIR update_lints: Update changelog links This now also updates the link list at the bottom of the changelog. --- clippy_dev/src/lib.rs | 32 +++++++++++++++++++++++++++++++- clippy_dev/src/main.rs | 12 ++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index dcb2de2b1f8..77351233381 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -59,13 +59,29 @@ impl Lint { /// Returns all non-deprecated lints and non-internal lints pub fn usable_lints(lints: impl Iterator) -> impl Iterator { - lints.filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) + lints.filter(|l| l.deprecation.is_none() && !l.is_internal()) } /// Returns the lints in a HashMap, grouped by the different lint groups pub fn by_lint_group(lints: &[Self]) -> HashMap> { lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map() } + + pub fn is_internal(&self) -> bool { + self.group.starts_with("internal") + } +} + +pub fn gen_changelog_lint_list(lints: Vec) -> Vec { + let mut lint_list_sorted: Vec = lints; + lint_list_sorted.sort_by_key(|l| l.name.clone()); + lint_list_sorted + .iter() + .filter(|l| !l.is_internal()) + .map(|l| { + format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name) + }) + .collect() } /// Gathers all files in `src/clippy_lints` and gathers all lints inside @@ -291,3 +307,17 @@ fn test_by_lint_group() { ]); assert_eq!(expected, Lint::by_lint_group(&lints)); } + +#[test] +fn test_gen_changelog_lint_list() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), + Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), + ]; + let expected = vec![ + format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()), + format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()) + ]; + assert_eq!(expected, gen_changelog_lint_list(lints)); +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 7b688836a95..8769ee6b810 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -59,8 +59,8 @@ fn print_lints() { } fn update_lints() { - let lint_list = gather_all(); - let usable_lints: Vec = Lint::usable_lints(lint_list).collect(); + let lint_list: Vec = gather_all().collect(); + let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); let lint_count = usable_lints.len(); replace_region_in_file( @@ -74,4 +74,12 @@ fn update_lints() { ] } ); + + replace_region_in_file( + "../CHANGELOG.md", + "", + "", + false, + || { gen_changelog_lint_list(lint_list.clone()) } + ); } -- cgit 1.4.1-3-g733a5 From 4b68c965feec8ce0e86d0b396baca5e33c3cf0af Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Wed, 17 Oct 2018 10:43:32 -0400 Subject: Resolve ICE in needless range loop lint An ICE would occur if the needless range loop was triggered within a procedural macro, because Clippy would try to produce a code suggestion which was invalid, and caused the compiler to crash. This commit takes the same approach which Clippy currently takes to work around this type of crash in the needless pass by value lint, which is to skip the lint if Clippy is inside of a macro. --- clippy_lints/src/loops.rs | 6 +++++- mini-macro/src/lib.rs | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3c4f06077d9..950c1043802 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -31,7 +31,7 @@ use std::mem; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax_pos::BytePos; -use crate::utils::{sugg, sext}; +use crate::utils::{in_macro, sugg, sext}; use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; @@ -1030,6 +1030,10 @@ fn check_for_loop_range<'a, 'tcx>( body: &'tcx Expr, expr: &'tcx Expr, ) { + if in_macro(expr.span) { + return; + } + if let Some(higher::Range { start: Some(start), ref end, diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index d326dd7e679..b6405975862 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -17,5 +17,10 @@ use proc_macro::{TokenStream, quote}; pub fn mini_macro(_: TokenStream) -> TokenStream { quote!( #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } + #[allow(unused)] fn needless_loop(items: &[u8]) { + for i in 0..items.len() { + println!("{}", items[i]); + } + } ) } -- cgit 1.4.1-3-g733a5 From 8753e568bf0d8bdc591ca56d9c3bc442efffaede Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Tue, 16 Oct 2018 22:20:27 +0200 Subject: Check for comments in collapsible ifs --- clippy_lints/src/collapsible_if.rs | 9 ++++++++ tests/ui/collapsible_if.rs | 45 ++++++++++++++++++++++++++++++++++++++ tests/ui/collapsible_if.stderr | 18 ++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 85fdca1d421..67ef1048299 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -112,9 +112,17 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { } } +fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { + // The zeroth character in the trimmed block text is "{", which marks the beginning of the block. + // Therefore, we check if the first string after that is a comment, i.e. starts with //. + let trimmed_block_text = snippet_block(cx, expr.span, "..").trim_left().to_owned(); + trimmed_block_text[1..trimmed_block_text.len()].trim_left().starts_with("//") +} + fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { if_chain! { if let ast::ExprKind::Block(ref block, _) = else_.node; + if !block_starts_with_comment(cx, block); if let Some(else_) = expr_block(block); if !in_macro(else_.span); then { @@ -135,6 +143,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { if_chain! { + if !block_starts_with_comment(cx, then); if let Some(inner) = expr_block(then); if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node; then { diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index a6df9109df9..c186d9e577f 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -151,4 +151,49 @@ fn main() { } else { assert!(true); // assert! is just an `if` } + + + // The following tests check for the fix of https://github.com/rust-lang-nursery/rust-clippy/issues/798 + if x == "hello" {// Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { // Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { + // Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { + if y == "world" { // Collapsible + println!("Hello world!"); + } + } + + if x == "hello" { + print!("Hello "); + } else { + // Not collapsible + if y == "world" { + println!("world!") + } + } + + if x == "hello" { + print!("Hello "); + } else { + // Not collapsible + if let Some(42) = Some(42) { + println!("world!") + } + } } diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 87c279cd725..3f06dca5495 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -240,5 +240,21 @@ help: try 122 | } | -error: aborting due to 13 previous errors +error: this if statement can be collapsed + --> $DIR/collapsible_if.rs:176:5 + | +176 | / if x == "hello" { +177 | | if y == "world" { // Collapsible +178 | | println!("Hello world!"); +179 | | } +180 | | } + | |_____^ +help: try + | +176 | if x == "hello" && y == "world" { // Collapsible +177 | println!("Hello world!"); +178 | } + | + +error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 5614dcb4ead82724e5873172961a26ffbfddcd18 Mon Sep 17 00:00:00 2001 From: Lukas Stevens Date: Thu, 18 Oct 2018 18:57:16 +0200 Subject: Support multiline comments and hopefully fix panic --- clippy_lints/src/collapsible_if.rs | 8 ++++---- tests/ui/collapsible_if.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 67ef1048299..a55ca04f706 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -113,10 +113,10 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { } fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { - // The zeroth character in the trimmed block text is "{", which marks the beginning of the block. - // Therefore, we check if the first string after that is a comment, i.e. starts with //. - let trimmed_block_text = snippet_block(cx, expr.span, "..").trim_left().to_owned(); - trimmed_block_text[1..trimmed_block_text.len()].trim_left().starts_with("//") + // We trim all opening braces and whitespaces and then check if the next string is a comment. + let trimmed_block_text = + snippet_block(cx, expr.span, "..").trim_left_matches(|c: char| c.is_whitespace() || c == '{').to_owned(); + trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") } fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index c186d9e577f..1bc866010fd 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -196,4 +196,17 @@ fn main() { println!("world!") } } + + if x == "hello" { + /* Not collapsible */ + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { /* Not collapsible */ + if y == "world" { + println!("Hello world!"); + } + } } -- cgit 1.4.1-3-g733a5 From fd2f6dd3824b32af031d19830b6ccdc732dd3dfc Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 18 Oct 2018 23:31:11 +0200 Subject: new_ret_no_self: add sample from #3313 to Known Problems section. fix trivial typo on the way --- clippy_lints/src/methods/mod.rs | 3 ++- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 11ed1e70e38..6d22abf2d33 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -452,7 +452,8 @@ declare_clippy_lint! { /// **Why is this bad?** As a convention, `new` methods are used to make a new /// instance of a type. /// -/// **Known problems:** None. +/// **Known problems:** The lint fires when the return type is wrapping `Self`. +/// Example: `fn new() -> Result {}` /// /// **Example:** /// ```rust diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 38a9bbf6d4c..58afdc351d1 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -41,7 +41,7 @@ use std::fmt; declare_clippy_lint! { pub PTR_OFFSET_WITH_CAST, complexity, - "uneeded pointer offset cast" + "unneeded pointer offset cast" } #[derive(Copy, Clone, Debug)] -- cgit 1.4.1-3-g733a5 From a2be0509657c4b100ba9b81b34aa0262700da83c Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 00:03:56 -0400 Subject: Fix `clone_on_copy` not detecting derefs sometimes --- clippy_lints/src/methods/mod.rs | 3 ++- tests/ui/unnecessary_clone.rs | 4 +++ tests/ui/unnecessary_clone.stderr | 56 ++++++++++++++++++++++----------------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6d22abf2d33..a0d57e0916b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1250,7 +1250,8 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if is_copy(cx, ty) { let snip; if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - if let ty::Ref(..) = cx.tables.expr_ty(arg).sty { + // x.clone() might have dereferenced x, possibly through a Deref impl + if cx.tables.expr_ty(arg) != ty { let parent = cx.tcx.hir.get_parent_node(expr.id); match cx.tcx.hir.get(parent) { hir::Node::Expr(parent) => match parent.node { diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index df02570d692..2dd2213e138 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -13,6 +13,7 @@ #![warn(clippy::clone_on_ref_ptr)] #![allow(unused)] +use std::cell::RefCell; use std::collections::HashSet; use std::collections::VecDeque; use std::rc::{self, Rc}; @@ -30,6 +31,9 @@ fn clone_on_copy() { vec![1].clone(); // ok, not a Copy type Some(vec![1]).clone(); // ok, not a Copy type (&42).clone(); + + let rc = RefCell::new(0); + rc.borrow().clone(); } fn clone_on_ref_ptr() { diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 051fc1fcdf9..63e6f3d8bd5 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,84 +1,90 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:28:5 + --> $DIR/unnecessary_clone.rs:29:5 | -28 | 42.clone(); +29 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:32:5 + --> $DIR/unnecessary_clone.rs:33:5 | -32 | (&42).clone(); +33 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:36:5 + | +36 | rc.borrow().clone(); + | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` + error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:42:5 + --> $DIR/unnecessary_clone.rs:46:5 | -42 | rc.clone(); +46 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:45:5 + --> $DIR/unnecessary_clone.rs:49:5 | -45 | arc.clone(); +49 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:48:5 + --> $DIR/unnecessary_clone.rs:52:5 | -48 | rcweak.clone(); +52 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:51:5 + --> $DIR/unnecessary_clone.rs:55:5 | -51 | arc_weak.clone(); +55 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:55:29 + --> $DIR/unnecessary_clone.rs:59:29 | -55 | let _: Arc = x.clone(); +59 | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:59:5 + --> $DIR/unnecessary_clone.rs:63:5 | -59 | t.clone(); +63 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:61:5 + --> $DIR/unnecessary_clone.rs:65:5 | -61 | Some(t).clone(); +65 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:67:22 + --> $DIR/unnecessary_clone.rs:71:22 | -67 | let z: &Vec<_> = y.clone(); +71 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | = note: #[deny(clippy::clone_double_ref)] on by default help: try dereferencing it | -67 | let z: &Vec<_> = &(*y).clone(); +71 | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -67 | let z: &Vec<_> = &std::vec::Vec::clone(y); +71 | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:74:27 + --> $DIR/unnecessary_clone.rs:78:27 | -74 | let v2 : Vec = v.iter().cloned().collect(); +78 | let v2 : Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From 6e75050be07d5f457c8854e9392fd756ef211a06 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 19 Oct 2018 04:55:06 -0700 Subject: new_ret_no_self correct linting of tuple return types --- clippy_lints/src/methods/mod.rs | 11 +++++++++++ tests/ui/new_ret_no_self.rs | 28 ++++++++++++++++++++++++++++ tests/ui/new_ret_no_self.stderr | 8 +++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6d22abf2d33..6e015487561 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -936,6 +936,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let hir::ImplItemKind::Method(_, _) = implitem.node { let ret_ty = return_ty(cx, implitem.id); +// println!("ret_ty: {:?}", ret_ty); +// println!("ret_ty.sty {:?}", ret_ty.sty); + // if return type is impl trait if let TyKind::Opaque(def_id, _) = ret_ty.sty { @@ -955,6 +958,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } + // if return type is tuple + if let TyKind::Tuple(list) = ret_ty.sty { + // then at least one of the types in the tuple must be Self + for ret_type in list { + if same_tys(cx, ty, ret_type) { return; } + } + } + if name == "new" && !same_tys(cx, ret_ty, ty) { span_lint(cx, NEW_RET_NO_SELF, diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 1a4b91cc9da..77731149678 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -91,3 +91,31 @@ impl V { unimplemented!(); } } + +struct TupleReturnerOk; + +impl TupleReturnerOk { + // should not trigger lint + pub fn new() -> (Self, u32) { unimplemented!(); } +} + +struct TupleReturnerOk2; + +impl TupleReturnerOk2 { + // should not trigger lint (it doesn't matter which element in the tuple is Self) + pub fn new() -> (u32, Self) { unimplemented!(); } +} + +struct TupleReturnerOk3; + +impl TupleReturnerOk3 { + // should not trigger lint (tuple can contain multiple Self) + pub fn new() -> (Self, Self) { unimplemented!(); } +} + +struct TupleReturnerBad; + +impl TupleReturnerBad { + // should trigger lint + pub fn new() -> (u32, u32) { unimplemented!(); } +} diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index ad26438d4ef..6f8e2d136a7 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -24,5 +24,11 @@ error: methods called `new` usually return `Self` 92 | | } | |_____^ -error: aborting due to 3 previous errors +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:120:5 + | +120 | pub fn new() -> (u32, u32) { unimplemented!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 097df8f223e8a3d10ea8bd66ecd94ead376c4416 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 19 Oct 2018 05:20:33 -0700 Subject: new_ret_no_self correct false positive on raw pointer return types --- clippy_lints/src/methods/mod.rs | 6 ++++++ tests/ui/new_ret_no_self.rs | 21 +++++++++++++++++++++ tests/ui/new_ret_no_self.stderr | 8 +++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6e015487561..0992067636e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -966,6 +966,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } + // if return type is mutable pointer + if let TyKind::RawPtr(ty::TypeAndMut{ty: ret_type, ..}) = ret_ty.sty { + // then the pointer must point to Self + if same_tys(cx, ty, ret_type) { return; } + } + if name == "new" && !same_tys(cx, ret_ty, ty) { span_lint(cx, NEW_RET_NO_SELF, diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 77731149678..b267a3aecdf 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -119,3 +119,24 @@ impl TupleReturnerBad { // should trigger lint pub fn new() -> (u32, u32) { unimplemented!(); } } + +struct MutPointerReturnerOk; + +impl MutPointerReturnerOk { + // should not trigger lint + pub fn new() -> *mut Self { unimplemented!(); } +} + +struct MutPointerReturnerOk2; + +impl MutPointerReturnerOk2 { + // should not trigger lint + pub fn new() -> *const Self { unimplemented!(); } +} + +struct MutPointerReturnerBad; + +impl MutPointerReturnerBad { + // should trigger lint + pub fn new() -> *mut V { unimplemented!(); } +} diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index 6f8e2d136a7..20f0dbbe8a3 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -30,5 +30,11 @@ error: methods called `new` usually return `Self` 120 | pub fn new() -> (u32, u32) { unimplemented!(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:141:5 + | +141 | pub fn new() -> *mut V { unimplemented!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 2a9dec681fe8a7bd1985790fc70f671975c68da0 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 14:51:25 -0400 Subject: Fix suggestion for multiple derefs --- clippy_lints/src/methods/mod.rs | 15 +++++++++++++-- tests/ui/unnecessary_clone.rs | 32 ++++++++++++++++++++++++++++++++ tests/ui/unnecessary_clone.stderr | 8 +++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a0d57e0916b..dd44aad351c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1250,7 +1250,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if is_copy(cx, ty) { let snip; if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - // x.clone() might have dereferenced x, possibly through a Deref impl + // x.clone() might have dereferenced x, possibly through Deref impls if cx.tables.expr_ty(arg) != ty { let parent = cx.tcx.hir.get_parent_node(expr.id); match cx.tcx.hir.get(parent) { @@ -1273,7 +1273,18 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp }, _ => {}, } - snip = Some(("try dereferencing it", format!("{}", snippet.deref()))); + + let deref_count = cx.tables.expr_adjustments(arg).iter() + .filter(|adj| { + if let ty::adjustment::Adjust::Deref(_) = adj.kind { + true + } else { + false + } + }) + .count(); + let derefs: String = iter::repeat('*').take(deref_count).collect(); + snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet))); } else { snip = Some(("try removing the `clone` call", format!("{}", snippet))); } diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 2dd2213e138..28cad1d881f 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -79,3 +79,35 @@ fn iter_clone_collect() { let v3 : HashSet = v.iter().cloned().collect(); let v4 : VecDeque = v.iter().cloned().collect(); } + +mod many_derefs { + struct A; + struct B; + struct C; + struct D; + #[derive(Copy, Clone)] + struct E; + + macro_rules! impl_deref { + ($src:ident, $dst:ident) => { + impl std::ops::Deref for $src { + type Target = $dst; + fn deref(&self) -> &Self::Target { &$dst } + } + } + } + + impl_deref!(A, B); + impl_deref!(B, C); + impl_deref!(C, D); + impl std::ops::Deref for D { + type Target = &'static E; + fn deref(&self) -> &Self::Target { &&E } + } + + fn go1() { + let a = A; + let _: E = a.clone(); + let _: E = *****a; + } +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 63e6f3d8bd5..5dcd5cae463 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -86,5 +86,11 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` -error: aborting due to 12 previous errors +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:110:20 + | +110 | let _: E = a.clone(); + | ^^^^^^^^^ help: try dereferencing it: `*****a` + +error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 2e9172aea2b169e6f4ee888c4bea9d56eaf6d78e Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 16:34:16 -0400 Subject: Check for known array length in `needless_range_loop` --- clippy_lints/src/loops.rs | 38 ++++++++++++++++++++++++++++++++----- tests/ui/needless_range_loop.rs | 16 +++++++++++++++- tests/ui/needless_range_loop.stderr | 32 ++++++++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 9e45757f3f0..0d1b960cc1f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1068,7 +1068,7 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable, and indexed it directly if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 { - let (indexed, indexed_extent) = visitor + let (indexed, (indexed_extent, indexed_ty)) = visitor .indexed_directly .into_iter() .next() @@ -1119,7 +1119,7 @@ fn check_for_loop_range<'a, 'tcx>( } } - if is_len_call(end, indexed) { + if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) { String::new() } else { match limits { @@ -1207,6 +1207,28 @@ fn is_len_call(expr: &Expr, var: Name) -> bool { false } +fn is_end_eq_array_len( + cx: &LateContext<'_, '_>, + end: &Expr, + limits: ast::RangeLimits, + indexed_ty: Ty<'_>, +) -> bool { + if_chain! { + if let ExprKind::Lit(ref lit) = end.node; + if let ast::LitKind::Int(end_int, _) = lit.node; + if let ty::TyKind::Array(_, arr_len_const) = indexed_ty.sty; + if let Some(arr_len) = arr_len_const.assert_usize(cx.tcx); + then { + return match limits { + ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), + ast::RangeLimits::HalfOpen => end_int >= arr_len.into(), + }; + } + } + + false +} + fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr, expr: &'tcx Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { @@ -1678,7 +1700,7 @@ struct VarVisitor<'a, 'tcx: 'a> { indexed_indirectly: FxHashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` - indexed_directly: FxHashMap>, + indexed_directly: FxHashMap, Ty<'tcx>)>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: FxHashSet, @@ -1725,7 +1747,10 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); } if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].ident.name, Some(extent)); + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (Some(extent), self.cx.tables.node_id_to_type(seqexpr.hir_id)), + ); } return false; // no need to walk further *on the variable* } @@ -1734,7 +1759,10 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); } if index_used_directly { - self.indexed_directly.insert(seqvar.segments[0].ident.name, None); + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (None, self.cx.tables.node_id_to_type(seqexpr.hir_id)), + ); } return false; // no need to walk further *on the variable* } diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 3da9267d38b..c1992bba548 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -13,7 +13,7 @@ fn calc_idx(i: usize) -> usize { } fn main() { - let ns = [2, 3, 5, 7]; + let ns = vec![2, 3, 5, 7]; for i in 3..10 { println!("{}", ns[i]); @@ -76,4 +76,18 @@ fn main() { for i in x..=x + 4 { vec[i] += 1; } + + let arr = [1,2,3]; + + for i in 0..3 { + println!("{}", arr[i]); + } + + for i in 0..2 { + println!("{}", arr[i]); + } + + for i in 1..3 { + println!("{}", arr[i]); + } } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index d62a0434d0b..688e9fc3a2c 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -50,5 +50,35 @@ help: consider using an iterator 76 | for in vec.iter_mut().skip(x).take(4 + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: the loop variable `i` is only used to index `arr`. + --> $DIR/needless_range_loop.rs:82:14 + | +82 | for i in 0..3 { + | ^^^^ +help: consider using an iterator + | +82 | for in &arr { + | ^^^^^^ ^^^^ + +error: the loop variable `i` is only used to index `arr`. + --> $DIR/needless_range_loop.rs:86:14 + | +86 | for i in 0..2 { + | ^^^^ +help: consider using an iterator + | +86 | for in arr.iter().take(2) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^ + +error: the loop variable `i` is only used to index `arr`. + --> $DIR/needless_range_loop.rs:90:14 + | +90 | for i in 1..3 { + | ^^^^ +help: consider using an iterator + | +90 | for in arr.iter().skip(1) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 553d01d9c74477a8172581aba00d179fcd63a78f Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 17:17:13 -0400 Subject: Update `ui/for_loop` test output --- tests/ui/for_loop.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 33176335783..695209de53f 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -97,8 +97,8 @@ error: the loop variable `j` is only used to index `STATIC`. | ^^^^ help: consider using an iterator | -110 | for in STATIC.iter().take(4) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +110 | for in &STATIC { + | ^^^^^^ ^^^^^^^ error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:114:14 @@ -107,8 +107,8 @@ error: the loop variable `j` is only used to index `CONST`. | ^^^^ help: consider using an iterator | -114 | for in CONST.iter().take(4) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +114 | for in &CONST { + | ^^^^^^ ^^^^^^ error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:118:14 -- cgit 1.4.1-3-g733a5 From 079f9f45b5a44a0feaf60d56576758dd7b0c9fdd Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 19 Oct 2018 17:54:25 -0700 Subject: new_ret_no_self walk return type to check for self --- clippy_lints/src/methods/mod.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 0992067636e..f0810c906ef 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -936,13 +936,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let hir::ImplItemKind::Method(_, _) = implitem.node { let ret_ty = return_ty(cx, implitem.id); -// println!("ret_ty: {:?}", ret_ty); -// println!("ret_ty.sty {:?}", ret_ty.sty); + // walk the return type and check for Self (this does not check associated types) + for inner_type in ret_ty.walk() { + if same_tys(cx, ty, inner_type) { return; } + } - // if return type is impl trait + // if return type is impl trait, check the associated types if let TyKind::Opaque(def_id, _) = ret_ty.sty { - // then one of the associated types must be Self + // one of the associated types must be Self for predicate in cx.tcx.predicates_of(def_id).predicates.iter() { match predicate { (Predicate::Projection(poly_projection_predicate), _) => { @@ -958,20 +960,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } - // if return type is tuple - if let TyKind::Tuple(list) = ret_ty.sty { - // then at least one of the types in the tuple must be Self - for ret_type in list { - if same_tys(cx, ty, ret_type) { return; } - } - } - - // if return type is mutable pointer - if let TyKind::RawPtr(ty::TypeAndMut{ty: ret_type, ..}) = ret_ty.sty { - // then the pointer must point to Self - if same_tys(cx, ty, ret_type) { return; } - } - if name == "new" && !same_tys(cx, ret_ty, ty) { span_lint(cx, NEW_RET_NO_SELF, -- cgit 1.4.1-3-g733a5 From a6245835573760d7e2dfd6a608af40fab7ba5223 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 20 Oct 2018 06:29:17 -0700 Subject: new_ret_no_self added test cases --- clippy_lints/src/types.rs | 1 - tests/ui/new_ret_no_self.rs | 21 +++++++++++++++++++++ tests/ui/new_ret_no_self.stderr | 8 +++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 59c55168232..035ca2b0496 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1920,7 +1920,6 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. - #[allow(clippy::new_ret_no_self)] fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node { let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()? diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index b267a3aecdf..b7daf3d49bc 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -140,3 +140,24 @@ impl MutPointerReturnerBad { // should trigger lint pub fn new() -> *mut V { unimplemented!(); } } + +struct GenericReturnerOk; + +impl GenericReturnerOk { + // should not trigger lint + pub fn new() -> Option { unimplemented!(); } +} + +struct GenericReturnerBad; + +impl GenericReturnerBad { + // should trigger lint + pub fn new() -> Option { unimplemented!(); } +} + +struct NestedReturnerOk; + +impl NestedReturnerOk { + // should trigger lint + pub fn new() -> (Option, u32) { unimplemented!(); } +} diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index 20f0dbbe8a3..bab9627ca22 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -36,5 +36,11 @@ error: methods called `new` usually return `Self` 141 | pub fn new() -> *mut V { unimplemented!(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:155:5 + | +155 | pub fn new() -> Option { unimplemented!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 8fc84b1f5504ce8812b6b99e04aa30263ffd73bc Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 22 Oct 2018 13:09:48 +0200 Subject: Setup bors --- .travis.yml | 9 +++++++++ bors.toml | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 bors.toml diff --git a/.travis.yml b/.travis.yml index 818353e0c16..97cec5ee86b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,15 @@ os: sudo: false +branches: + only: + # This is where pull requests from "bors r+" are built. + - staging + # This is where pull requests from "bors try" are built. + - trying + # Also build pull requests. + - master + env: global: - RUST_BACKTRACE=1 diff --git a/bors.toml b/bors.toml new file mode 100644 index 00000000000..4e6e85f45fe --- /dev/null +++ b/bors.toml @@ -0,0 +1,4 @@ +status = [ + "continuous-integration/travis-ci/push", + "continuous-integration/appveyor/branch" +] -- cgit 1.4.1-3-g733a5 From 9086730dc43329d2bb11f92078e2eb1f6b040421 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 22 Oct 2018 17:30:01 +0200 Subject: Add branch configuration to appveyor.yml --- appveyor.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f50d1e88a24..8ab4a994476 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,16 @@ environment: #- TARGET: i686-pc-windows-msvc #- TARGET: x86_64-pc-windows-gnu - TARGET: x86_64-pc-windows-msvc - + +branches: + only: + # This is where pull requests from "bors r+" are built. + - staging + # This is where pull requests from "bors try" are built. + - trying + # Also build pull requests. + - master + install: - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly -- cgit 1.4.1-3-g733a5 From fd3651a55151086390a877d5c8773647742f51c3 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Tue, 23 Oct 2018 23:03:23 +0200 Subject: Fix inspector pass documentation When using `#[clippy_dump]`, the compiler complains about an unknown attribute. The correct one seems to be `#[clippy::dump]`. --- clippy_lints/src/utils/inspector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ea48aa9ab5e..54ca0736c52 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -19,12 +19,12 @@ use crate::rustc::hir::print; use crate::syntax::ast::Attribute; use crate::utils::get_attr; -/// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` +/// **What it does:** Dumps every ast/hir node which has the `#[clippy::dump]` /// attribute /// /// **Example:** /// ```rust -/// #[clippy_dump] +/// #[clippy::dump] /// extern crate foo; /// ``` /// -- cgit 1.4.1-3-g733a5 From 6a695ffb3db7bf656c0cf4da38af236fdebac2e0 Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Tue, 23 Oct 2018 15:54:27 -0600 Subject: added float support for mistyped literal lints --- clippy_lints/src/literal_representation.rs | 164 ++++++++++++++++------------- tests/ui/literals.rs | 11 +- tests/ui/literals.stderr | 146 +++++++++++++++---------- 3 files changed, 185 insertions(+), 136 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 2d64a24a79b..357f344919f 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::syntax::ast::*; use crate::syntax_pos; use crate::utils::{snippet_opt, span_lint_and_sugg}; +use if_chain::if_chain; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -41,9 +40,9 @@ declare_clippy_lint! { /// **Why is this bad?** This is most probably a typo /// /// **Known problems:** -/// - Recommends a signed suffix, even though the number might be too big and an unsigned +/// - Recommends a signed suffix, even though the number might be too big and an unsigned /// suffix is required -/// - Does not match on `_128` since that is a valid grouping for decimal and octal numbers +/// - Does not match on `_128` since that is a valid grouping for decimal and octal numbers /// /// **Example:** /// @@ -168,23 +167,21 @@ impl<'a> DigitInfo<'a> { let len = sans_prefix.len(); let mut last_d = '\0'; for (d_idx, d) in sans_prefix.char_indices() { - let suffix_start = if last_d == '_' { - d_idx - 1 - } else { - d_idx - }; - if float && ((is_possible_float_suffix_index(&sans_prefix, suffix_start, len)) || - (d == 'f' || d == 'e' || d == 'E')) || - !float && (d == 'i' || d == 'u' || - is_possible_suffix_index(&sans_prefix, suffix_start, len)) { - let (digits, suffix) = sans_prefix.split_at(suffix_start); - return Self { - digits, - radix, - prefix, - suffix: Some(suffix), - float, - }; + let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx }; + if float + && (d == 'f' + || is_possible_float_suffix_index(&sans_prefix, suffix_start, len) + || ((d == 'E' || d == 'e') && !has_possible_float_suffix(&sans_prefix))) + || !float && (d == 'i' || d == 'u' || is_possible_suffix_index(&sans_prefix, suffix_start, len)) + { + let (digits, suffix) = sans_prefix.split_at(suffix_start); + return Self { + digits, + radix, + prefix, + suffix: Some(suffix), + float, + }; } last_d = d } @@ -226,18 +223,44 @@ impl<'a> DigitInfo<'a> { .map(|chunk| chunk.into_iter().collect()) .collect::>() .join("_"); + let suffix_hint = match self.suffix { + Some(suffix) if is_mistyped_float_suffix(suffix) => format!("_f{}", &suffix[1..]), + Some(suffix) => suffix.to_string(), + None => String::new(), + }; + format!("{}.{}{}", int_part_hint, frac_part_hint, suffix_hint) + } else if self.float && (self.digits.contains("E") || self.digits.contains("E")) { + let which_e = if self.digits.contains("E") { "E" } else { "e" }; + let parts: Vec<&str> = self.digits.split(which_e).collect(); + let filtered_digits_vec_0 = parts[0].chars().filter(|&c| c != '_').rev().collect::>(); + let filtered_digits_vec_1 = parts[1].chars().filter(|&c| c != '_').rev().collect::>(); + let before_e_hint = filtered_digits_vec_0 + .chunks(group_size) + .map(|chunk| chunk.into_iter().rev().collect()) + .rev() + .collect::>() + .join("_"); + let after_e_hint = filtered_digits_vec_1 + .chunks(group_size) + .map(|chunk| chunk.into_iter().rev().collect()) + .rev() + .collect::>() + .join("_"); + let suffix_hint = match self.suffix { + Some(suffix) if is_mistyped_float_suffix(suffix) => format!("_f{}", &suffix[1..]), + Some(suffix) => suffix.to_string(), + None => String::new(), + }; format!( - "{}.{}{}", - int_part_hint, - frac_part_hint, - self.suffix.unwrap_or("") + "{}{}{}{}{}", + self.prefix.unwrap_or(""), + before_e_hint, + which_e, + after_e_hint, + suffix_hint ) } else { - let filtered_digits_vec = self.digits - .chars() - .filter(|&c| c != '_') - .rev() - .collect::>(); + let filtered_digits_vec = self.digits.chars().filter(|&c| c != '_').rev().collect::>(); let mut hint = filtered_digits_vec .chunks(group_size) .map(|chunk| chunk.into_iter().rev().collect()) @@ -250,21 +273,11 @@ impl<'a> DigitInfo<'a> { hint = format!("{:0>4}{}", &hint[..nb_digits_to_fill], &hint[nb_digits_to_fill..]); } let suffix_hint = match self.suffix { - Some(suffix) if is_mistyped_float_suffix(suffix) && self.digits.contains(".") => { - format!("_f{}", &suffix[1..]) - }, - Some(suffix) if is_mistyped_suffix(suffix) => { - format!("_i{}", &suffix[1..]) - }, + Some(suffix) if is_mistyped_suffix(suffix) => format!("_i{}", &suffix[1..]), Some(suffix) => suffix.to_string(), - None => String::new() + None => String::new(), }; - format!( - "{}{}{}", - self.prefix.unwrap_or(""), - hint, - suffix_hint - ) + format!("{}{}{}", self.prefix.unwrap_or(""), hint, suffix_hint) } } } @@ -274,22 +287,20 @@ enum WarningType { InconsistentDigitGrouping, LargeDigitGroups, DecimalRepresentation, - MistypedLiteralSuffix + MistypedLiteralSuffix, } impl WarningType { crate fn display(&self, grouping_hint: &str, cx: &EarlyContext<'_>, span: syntax_pos::Span) { match self { - WarningType::MistypedLiteralSuffix => { - span_lint_and_sugg( - cx, - MISTYPED_LITERAL_SUFFIXES, - span, - "mistyped literal suffix", - "did you mean to write", - grouping_hint.to_string() - ) - }, + WarningType::MistypedLiteralSuffix => span_lint_and_sugg( + cx, + MISTYPED_LITERAL_SUFFIXES, + span, + "mistyped literal suffix", + "did you mean to write", + grouping_hint.to_string(), + ), WarningType::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, @@ -331,11 +342,7 @@ pub struct LiteralDigitGrouping; impl LintPass for LiteralDigitGrouping { fn get_lints(&self) -> LintArray { - lint_array!( - UNREADABLE_LITERAL, - INCONSISTENT_DIGIT_GROUPING, - LARGE_DIGIT_GROUPS - ) + lint_array!(UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, LARGE_DIGIT_GROUPS) } } @@ -384,7 +391,7 @@ impl LiteralDigitGrouping { // Lint integral and fractional parts separately, and then check consistency of digit // groups if both pass. - let _ = Self::do_lint(parts[0], None) + let _ = Self::do_lint(parts[0], digit_info.suffix) .map(|integral_group_size| { if parts.len() > 1 { // Lint the fractional part of literal just like integral part, but reversed. @@ -395,11 +402,11 @@ impl LiteralDigitGrouping { fractional_group_size, parts[0].len(), parts[1].len()); - if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), - cx, - lit.span); - } + if !consistent { + WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), + cx, + lit.span); + } }) .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), cx, @@ -498,9 +505,7 @@ impl EarlyLintPass for LiteralRepresentation { impl LiteralRepresentation { pub fn new(threshold: u64) -> Self { - Self { - threshold, - } + Self { threshold } } fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { // Lint integral literals. @@ -533,7 +538,12 @@ impl LiteralRepresentation { fn do_lint(digits: &str) -> Result<(), WarningType> { if digits.len() == 1 { // Lint for 1 digit literals, if someone really sets the threshold that low - if digits == "1" || digits == "2" || digits == "4" || digits == "8" || digits == "3" || digits == "7" + if digits == "1" + || digits == "2" + || digits == "4" + || digits == "8" + || digits == "3" + || digits == "7" || digits == "F" { return Err(WarningType::DecimalRepresentation); @@ -542,7 +552,7 @@ impl LiteralRepresentation { // Lint for Literals with a hex-representation of 2 or 3 digits let f = &digits[0..1]; // first digit let s = &digits[1..]; // suffix - // Powers of 2 + // Powers of 2 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && s.chars().all(|c| c == '0')) // Powers of 2 minus 1 || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.chars().all(|c| c == 'F')) @@ -554,7 +564,7 @@ impl LiteralRepresentation { let f = &digits[0..1]; // first digit let m = &digits[1..digits.len() - 1]; // middle digits, except last let s = &digits[1..]; // suffix - // Powers of 2 with a margin of +15/-16 + // Powers of 2 with a margin of +15/-16 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && m.chars().all(|c| c == '0')) || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && m.chars().all(|c| c == 'F')) // Lint for representations with only 0s and Fs, while allowing 7 as the first @@ -574,8 +584,7 @@ fn is_mistyped_suffix(suffix: &str) -> bool { } fn is_possible_suffix_index(lit: &str, idx: usize, len: usize) -> bool { - ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && - is_mistyped_suffix(lit.split_at(idx).1) + ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && is_mistyped_suffix(lit.split_at(idx).1) } fn is_mistyped_float_suffix(suffix: &str) -> bool { @@ -583,6 +592,9 @@ fn is_mistyped_float_suffix(suffix: &str) -> bool { } fn is_possible_float_suffix_index(lit: &str, idx: usize, len: usize) -> bool { - ((len > 3 && idx == len - 3) || (len > 2 && idx == len - 2)) && - is_mistyped_float_suffix(lit.split_at(idx).1) + (len > 3 && idx == len - 3) && is_mistyped_float_suffix(lit.split_at(idx).1) +} + +fn has_possible_float_suffix(lit: &str) -> bool { + lit.ends_with("_32") || lit.ends_with("_64") } diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 3782679d492..c08c4b693b8 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::mixed_case_hex_literals)] #![warn(clippy::unseparated_literal_suffix)] #![warn(clippy::zero_prefixed_literal)] @@ -65,6 +62,10 @@ fn main() { let fail22 = 3__4___23; let fail23 = 3__16___23; - //let fail24 = 1E2_32; - let fail25 = 1.2_32; + let fail24 = 12.34_64; + let fail25 = 1E2_32; + let fail26 = 43E7_64; + let fail27 = 243E17_32; + let fail28 = 241251235E723_64; + let fail29 = 42279.911_32; } diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 4e26b9dd321..d2a50e2ded5 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,182 +1,218 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:24:17 + --> $DIR/literals.rs:21:17 | -24 | let fail1 = 0xabCD; +21 | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:25:17 + --> $DIR/literals.rs:22:17 | -25 | let fail2 = 0xabCD_u32; +22 | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:26:17 + --> $DIR/literals.rs:23:17 | -26 | let fail2 = 0xabCD_isize; +23 | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:27:27 + --> $DIR/literals.rs:24:27 | -27 | let fail_multi_zero = 000_123usize; +24 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:27:27 + --> $DIR/literals.rs:24:27 | -27 | let fail_multi_zero = 000_123usize; +24 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -27 | let fail_multi_zero = 123usize; +24 | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -27 | let fail_multi_zero = 0o123usize; +24 | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:32:17 + --> $DIR/literals.rs:29:17 | -32 | let fail3 = 1234i32; +29 | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:33:17 + --> $DIR/literals.rs:30:17 | -33 | let fail4 = 1234u32; +30 | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:34:17 + --> $DIR/literals.rs:31:17 | -34 | let fail5 = 1234isize; +31 | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:35:17 + --> $DIR/literals.rs:32:17 | -35 | let fail6 = 1234usize; +32 | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:36:17 + --> $DIR/literals.rs:33:17 | -36 | let fail7 = 1.5f32; +33 | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:40:17 + --> $DIR/literals.rs:37:17 | -40 | let fail8 = 0123; +37 | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -40 | let fail8 = 123; +37 | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -40 | let fail8 = 0o123; +37 | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:51:17 + --> $DIR/literals.rs:48:17 | -51 | let fail9 = 0xabcdef; +48 | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:52:18 + --> $DIR/literals.rs:49:18 | -52 | let fail10 = 0xBAFEBAFE; +49 | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:53:18 + --> $DIR/literals.rs:50:18 | -53 | let fail11 = 0xabcdeff; +50 | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/literals.rs:54:18 + --> $DIR/literals.rs:51:18 | -54 | let fail12 = 0xabcabcabcabcabcabc; +51 | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller - --> $DIR/literals.rs:55:18 + --> $DIR/literals.rs:52:18 | -55 | let fail13 = 0x1_23456_78901_usize; +52 | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:57:18 + --> $DIR/literals.rs:54:18 | -57 | let fail14 = 2_32; +54 | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` | = note: #[deny(clippy::mistyped_literal_suffixes)] on by default error: mistyped literal suffix - --> $DIR/literals.rs:58:18 + --> $DIR/literals.rs:55:18 | -58 | let fail15 = 4_64; +55 | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/literals.rs:59:18 + --> $DIR/literals.rs:56:18 | -59 | let fail16 = 7_8; +56 | let fail16 = 7_8; | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/literals.rs:60:18 + --> $DIR/literals.rs:57:18 | -60 | let fail17 = 23_16; +57 | let fail17 = 23_16; | ^^^^^ help: did you mean to write: `23_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:62:18 + --> $DIR/literals.rs:59:18 | -62 | let fail19 = 12_3456_21; +59 | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:63:18 + --> $DIR/literals.rs:60:18 | -63 | let fail20 = 2__8; +60 | let fail20 = 2__8; | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/literals.rs:64:18 + --> $DIR/literals.rs:61:18 | -64 | let fail21 = 4___16; +61 | let fail21 = 4___16; | ^^^^^^ help: did you mean to write: `4_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:65:18 + --> $DIR/literals.rs:62:18 | -65 | let fail22 = 3__4___23; +62 | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:66:18 + --> $DIR/literals.rs:63:18 | -66 | let fail23 = 3__16___23; +63 | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` -error: aborting due to 25 previous errors +error: mistyped literal suffix + --> $DIR/literals.rs:65:18 + | +65 | let fail24 = 12.34_64; + | ^^^^^^^^ help: did you mean to write: `12.34_f64` + +error: mistyped literal suffix + --> $DIR/literals.rs:66:18 + | +66 | let fail25 = 1E2_32; + | ^^^^^^ help: did you mean to write: `1E2_f32` + +error: mistyped literal suffix + --> $DIR/literals.rs:67:18 + | +67 | let fail26 = 43E7_64; + | ^^^^^^^ help: did you mean to write: `43E7_f64` + +error: mistyped literal suffix + --> $DIR/literals.rs:68:18 + | +68 | let fail27 = 243E17_32; + | ^^^^^^^^^ help: did you mean to write: `243E17_f32` + +error: mistyped literal suffix + --> $DIR/literals.rs:69:18 + | +69 | let fail28 = 241251235E723_64; + | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` + +error: mistyped literal suffix + --> $DIR/literals.rs:70:18 + | +70 | let fail29 = 42279.911_32; + | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` + +error: aborting due to 31 previous errors -- cgit 1.4.1-3-g733a5 From b1abc81a60e05bb2cf46850b977b7fa4ba34a6de Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Tue, 23 Oct 2018 16:35:09 -0600 Subject: small fix --- clippy_lints/src/literal_representation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 357f344919f..98fabcdcf51 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -229,8 +229,8 @@ impl<'a> DigitInfo<'a> { None => String::new(), }; format!("{}.{}{}", int_part_hint, frac_part_hint, suffix_hint) - } else if self.float && (self.digits.contains("E") || self.digits.contains("E")) { - let which_e = if self.digits.contains("E") { "E" } else { "e" }; + } else if self.float && (self.digits.contains('E') || self.digits.contains('e')) { + let which_e = if self.digits.contains('E') { 'E' } else { 'e' }; let parts: Vec<&str> = self.digits.split(which_e).collect(); let filtered_digits_vec_0 = parts[0].chars().filter(|&c| c != '_').rev().collect::>(); let filtered_digits_vec_1 = parts[1].chars().filter(|&c| c != '_').rev().collect::>(); -- cgit 1.4.1-3-g733a5 From 50b9e7aebc2e7b00f098736ff67f94300106f7fc Mon Sep 17 00:00:00 2001 From: Owen Sanchez Date: Sun, 21 Oct 2018 21:59:45 -0700 Subject: Don't emit `new_without_default_derive` if an impl of Default exists --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/new_without_default.rs | 37 +++++++++++++++++++++++++++++---- tests/ui/new_without_default.rs | 9 ++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 23bd71a08ab..bf37b239064 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -391,7 +391,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_early_lint_pass(box int_plus_one::IntPlusOne); reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); - reg.register_late_lint_pass(box new_without_default::NewWithoutDefault); + reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default()); reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone())); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone())); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 865b1c987c8..21b966a6bd9 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -11,6 +11,7 @@ use crate::rustc::hir::def_id::DefId; use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::util::nodemap::NodeSet; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::rustc::ty::{self, Ty}; @@ -91,8 +92,10 @@ declare_clippy_lint! { "`fn new() -> Self` without `#[derive]`able `Default` implementation" } -#[derive(Copy, Clone)] -pub struct NewWithoutDefault; +#[derive(Clone, Default)] +pub struct NewWithoutDefault { + impling_types: Option, +} impl LintPass for NewWithoutDefault { fn get_lints(&self) -> LintArray { @@ -130,13 +133,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { + let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)); let self_ty = cx.tcx - .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); + .type_of(self_did); if_chain! { if same_tys(cx, self_ty, return_ty(cx, id)); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); - if !implements_trait(cx, self_ty, default_trait_id, &[]); then { + if self.impling_types.is_none() { + let mut impls = NodeSet(); + cx.tcx.for_each_impl(default_trait_id, |d| { + if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { + if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) { + impls.insert(node_id); + } + } + }); + self.impling_types = Some(impls); + } + + // Check if a Default implementation exists for the Self type, regardless of + // generics + if_chain! { + if let Some(ref impling_types) = self.impling_types; + if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def(); + if self_def.did.is_local(); + then { + let self_id = cx.tcx.hir.local_def_id_to_node_id(self_def.did.to_local()); + if impling_types.contains(&self_id) { + return; + } + } + } + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { span_lint_and_then( cx, diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 783308d264a..16b9bd5c71b 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -107,4 +107,13 @@ impl IgnoreUnsafeNew { pub unsafe fn new() -> Self { IgnoreUnsafeNew } } +#[derive(Default)] +pub struct OptionRefWrapper<'a, T: 'a>(Option<&'a T>); + +impl<'a, T: 'a> OptionRefWrapper<'a, T> { + pub fn new() -> Self { + OptionRefWrapper(None) + } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From 0263ddde92d865a7e42dfe0d567286389d032faf Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Mon, 22 Oct 2018 22:39:51 +0900 Subject: Lint for wildcard dependencies in Cargo.toml --- clippy_lints/src/lib.rs | 3 ++ clippy_lints/src/wildcard_dependencies.rs | 70 +++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 clippy_lints/src/wildcard_dependencies.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 23bd71a08ab..b9f437a953f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -200,6 +200,7 @@ pub mod unused_label; pub mod unwrap; pub mod use_self; pub mod vec; +pub mod wildcard_dependencies; pub mod write; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -438,6 +439,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box question_mark::Pass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_early_lint_pass(box multiple_crate_versions::Pass); + reg.register_early_lint_pass(box wildcard_dependencies::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); reg.register_late_lint_pass(box infallible_destructuring_match::Pass); reg.register_late_lint_pass(box inherent_impl::Pass::default()); @@ -967,6 +969,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::cargo", Some("clippy_cargo"), vec![ multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, + wildcard_dependencies::WILDCARD_DEPENDENCIES, ]); reg.register_lint_group("clippy::nursery", Some("clippy_nursery"), vec![ diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs new file mode 100644 index 00000000000..3045130231c --- /dev/null +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -0,0 +1,70 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::ast::*; +use crate::utils::span_lint; + +use cargo_metadata; +use lazy_static::lazy_static; +use semver; + +/// **What it does:** Checks to see if wildcard dependencies are being used. +/// +/// **Why is this bad?** [As the edition guide sais](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html), +/// it is highly unlikely that you work with any possible version of your dependency, +/// and wildcard dependencies would cause unnecessary breakage in the ecosystem. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```toml +/// [dependencies] +/// regex = "*" +/// ``` +declare_clippy_lint! { + pub WILDCARD_DEPENDENCIES, + cargo, + "wildcard dependencies being used" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(WILDCARD_DEPENDENCIES) + } +} + +impl EarlyLintPass for Pass { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + let metadata = if let Ok(metadata) = cargo_metadata::metadata(None) { + metadata + } else { + span_lint(cx, WILDCARD_DEPENDENCIES, krate.span, "could not read cargo metadata"); + return; + }; + + lazy_static! { + static ref WILDCARD_VERSION_REQ: semver::VersionReq = semver::VersionReq::parse("*").unwrap(); + } + + for dep in &metadata.packages[0].dependencies { + if dep.req == *WILDCARD_VERSION_REQ { + span_lint( + cx, + WILDCARD_DEPENDENCIES, + krate.span, + &format!("wildcard dependency for `{}`", dep.name), + ); + } + } + } +} -- cgit 1.4.1-3-g733a5 From fa6c9f838cbe5a50b8e7871c146cd1d8fe8e4e00 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 11:34:36 +0900 Subject: Minor changes on clippy_lints/src/wildcard_dependencies.rs --- clippy_lints/src/wildcard_dependencies.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 3045130231c..e02501005e2 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -25,6 +25,7 @@ use semver; /// **Known problems:** None. /// /// **Example:** +/// /// ```toml /// [dependencies] /// regex = "*" @@ -53,6 +54,7 @@ impl EarlyLintPass for Pass { }; lazy_static! { + // VersionReq::any() does not work static ref WILDCARD_VERSION_REQ: semver::VersionReq = semver::VersionReq::parse("*").unwrap(); } -- cgit 1.4.1-3-g733a5 From d334fab4d0c28bd59538864e02847876a032439c Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 14:59:19 +0900 Subject: Run util/update_lints.py --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 626c39457e2..768751b2f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -893,6 +893,7 @@ All notable changes to this project will be documented in this file. [`while_immutable_condition`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_on_iterator +[`wildcard_dependencies`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wildcard_dependencies [`write_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_literal [`write_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_with_newline [`writeln_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#writeln_empty_string diff --git a/README.md b/README.md index d32f66b5957..94fb8c6c02f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 280 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 281 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 663f2cff7e08301841dd212fcf945b706ca2f224 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 20:18:19 +0900 Subject: Some fixes for wildcard_dependencies --- clippy_lints/src/wildcard_dependencies.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index e02501005e2..00533efb8e5 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -10,15 +10,15 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; +use crate::syntax::source_map::DUMMY_SP; use crate::utils::span_lint; use cargo_metadata; -use lazy_static::lazy_static; use semver; -/// **What it does:** Checks to see if wildcard dependencies are being used. +/// **What it does:** Checks for wildcard dependencies in the `Cargo.toml`. /// -/// **Why is this bad?** [As the edition guide sais](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html), +/// **Why is this bad?** [As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html), /// it is highly unlikely that you work with any possible version of your dependency, /// and wildcard dependencies would cause unnecessary breakage in the ecosystem. /// @@ -53,19 +53,17 @@ impl EarlyLintPass for Pass { return; }; - lazy_static! { - // VersionReq::any() does not work - static ref WILDCARD_VERSION_REQ: semver::VersionReq = semver::VersionReq::parse("*").unwrap(); - } - for dep in &metadata.packages[0].dependencies { - if dep.req == *WILDCARD_VERSION_REQ { - span_lint( - cx, - WILDCARD_DEPENDENCIES, - krate.span, - &format!("wildcard dependency for `{}`", dep.name), - ); + // VersionReq::any() does not work + if let Ok(wildcard_ver) = semver::VersionReq::parse("*") { + if dep.req == wildcard_ver { + span_lint( + cx, + WILDCARD_DEPENDENCIES, + DUMMY_SP, + &format!("wildcard dependency for `{}`", dep.name), + ); + } } } } -- cgit 1.4.1-3-g733a5 From 0d577c36a9e48fce3b9a0a49b7d5d59f8710af35 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 20:22:38 +0900 Subject: Use DUMMY_SP in multiple_crate_versions --- clippy_lints/src/multiple_crate_versions.rs | 12 +++--------- clippy_lints/src/wildcard_dependencies.rs | 3 +-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index dbf8cbe16c2..9507522ed10 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on multiple versions of a crate being used use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; +use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; use cargo_metadata; @@ -54,12 +53,7 @@ impl EarlyLintPass for Pass { let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { metadata } else { - span_lint( - cx, - MULTIPLE_CRATE_VERSIONS, - krate.span, - "could not read cargo metadata" - ); + span_lint(cx, MULTIPLE_CRATE_VERSIONS, krate.span, "could not read cargo metadata"); return; }; @@ -76,7 +70,7 @@ impl EarlyLintPass for Pass { span_lint( cx, MULTIPLE_CRATE_VERSIONS, - krate.span, + DUMMY_SP, &format!("multiple versions for dependency `{}`: {}", name, versions), ); } diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 00533efb8e5..8f2f1aeb27a 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -9,8 +9,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; -use crate::syntax::source_map::DUMMY_SP; +use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; use cargo_metadata; -- cgit 1.4.1-3-g733a5 From 99b78f06506c4f04399d2186b434a5dd4e16e792 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 21:15:27 +0900 Subject: Replace remaining `krate.span` with `DUMMY_SP` --- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/wildcard_dependencies.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 9507522ed10..da1ccd8fdf0 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -53,7 +53,7 @@ impl EarlyLintPass for Pass { let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { metadata } else { - span_lint(cx, MULTIPLE_CRATE_VERSIONS, krate.span, "could not read cargo metadata"); + span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata"); return; }; diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 8f2f1aeb27a..c172b38a6cb 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -48,7 +48,7 @@ impl EarlyLintPass for Pass { let metadata = if let Ok(metadata) = cargo_metadata::metadata(None) { metadata } else { - span_lint(cx, WILDCARD_DEPENDENCIES, krate.span, "could not read cargo metadata"); + span_lint(cx, WILDCARD_DEPENDENCIES, DUMMY_SP, "could not read cargo metadata"); return; }; -- cgit 1.4.1-3-g733a5 From 30ffc17ef754f6b6c7bd47809afd51b1c5632f22 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Wed, 24 Oct 2018 06:43:21 -0700 Subject: new_ret_no_self added test cases --- tests/ui/new_ret_no_self.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index b7daf3d49bc..bed43f550f2 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -158,6 +158,20 @@ impl GenericReturnerBad { struct NestedReturnerOk; impl NestedReturnerOk { - // should trigger lint + // should not trigger lint pub fn new() -> (Option, u32) { unimplemented!(); } } + +struct NestedReturnerOk2; + +impl NestedReturnerOk2 { + // should not trigger lint + pub fn new() -> ((Self, u32), u32) { unimplemented!(); } +} + +struct NestedReturnerOk3; + +impl NestedReturnerOk3 { + // should not trigger lint + pub fn new() -> Option<(Self, u32)> { unimplemented!(); } +} -- cgit 1.4.1-3-g733a5 From 57a18b65206371eafadaf16561f27025c7e33d9e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 24 Oct 2018 16:18:01 +0200 Subject: Fix warnings introduced by #3349 --- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/wildcard_dependencies.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index da1ccd8fdf0..c554c8729ce 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -49,7 +49,7 @@ impl LintPass for Pass { } impl EarlyLintPass for Pass { - fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { metadata } else { diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index c172b38a6cb..59f3cc78afe 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -44,7 +44,7 @@ impl LintPass for Pass { } impl EarlyLintPass for Pass { - fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { let metadata = if let Ok(metadata) = cargo_metadata::metadata(None) { metadata } else { -- cgit 1.4.1-3-g733a5 From 0b9e9c9e3d3a163941414d4b7632ff37fd4da224 Mon Sep 17 00:00:00 2001 From: Owen Sanchez Date: Wed, 17 Oct 2018 21:20:36 -0700 Subject: Disable arithmetic lints in constant items --- clippy_lints/src/arithmetic.rs | 55 ++++++++++++++++++++++++++++++++++++------ tests/ui/arithmetic.rs | 32 ++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 4d7e921567d..a481d46cce0 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -51,7 +51,9 @@ declare_clippy_lint! { #[derive(Copy, Clone, Default)] pub struct Arithmetic { - span: Option, + expr_span: Option, + /// This field is used to check whether expressions are constants, such as in enum discriminants and consts + const_span: Option, } impl LintPass for Arithmetic { @@ -62,9 +64,15 @@ impl LintPass for Arithmetic { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - if self.span.is_some() { + if self.expr_span.is_some() { return; } + + if let Some(span) = self.const_span { + if span.contains(expr.span) { + return; + } + } match expr.node { hir::ExprKind::Binary(ref op, ref l, ref r) => { match op.node { @@ -86,20 +94,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); if l_ty.is_integral() && r_ty.is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.span = Some(expr.span); + self.expr_span = Some(expr.span); } else if l_ty.is_floating_point() && r_ty.is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.span = Some(expr.span); + self.expr_span = Some(expr.span); } }, hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => { let ty = cx.tables.expr_ty(arg); if ty.is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.span = Some(expr.span); + self.expr_span = Some(expr.span); } else if ty.is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.span = Some(expr.span); + self.expr_span = Some(expr.span); } }, _ => (), @@ -107,8 +115,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - if Some(expr.span) == self.span { - self.span = None; + if Some(expr.span) == self.expr_span { + self.expr_span = None; + } + } + + fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) { + let body_owner = cx.tcx.hir.body_owner(body.id()); + + match cx.tcx.hir.body_owner_kind(body_owner) { + hir::BodyOwnerKind::Static(_) + | hir::BodyOwnerKind::Const => { + let body_span = cx.tcx.hir.span(body_owner); + + if let Some(span) = self.const_span { + if span.contains(body_span) { + return; + } + } + self.const_span = Some(body_span); + } + hir::BodyOwnerKind::Fn => (), + } + } + + fn check_body_post(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) { + let body_owner = cx.tcx.hir.body_owner(body.id()); + let body_span = cx.tcx.hir.span(body_owner); + + if let Some(span) = self.const_span { + if span.contains(body_span) { + return; + } } + self.const_span = None; } } diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index ff550c9593c..61a601468fb 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -37,4 +37,36 @@ fn main() { f / 2.0; f - 2.0 * 4.2; -f; + + // No errors for the following items because they are constant expressions + enum Foo { + Bar = -2, + } + struct Baz([i32; 1 + 1]); + union Qux { + field: [i32; 1 + 1], + } + type Alias = [i32; 1 + 1]; + + const FOO: i32 = -2; + static BAR: i32 = -2; + + let _: [i32; 1 + 1] = [0, 0]; + + let _: [i32; 1 + 1] = { + let a: [i32; 1 + 1] = [0, 0]; + a + }; + + trait Trait { + const ASSOC: i32 = 1 + 1; + } + + impl Trait for Foo { + const ASSOC: i32 = { + let _: [i32; 1 + 1]; + fn foo() {} + 1 + 1 + }; + } } -- cgit 1.4.1-3-g733a5 From 3db14f182c4dce4d6ace923c291456e7d1249bc9 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Wed, 24 Oct 2018 23:28:54 -0400 Subject: Check existential types in `use_self` --- clippy_lints/src/use_self.rs | 2 +- tests/ui/use_self.rs | 14 ++++++++++++++ tests/ui/use_self.stderr | 8 +++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index d770ea120eb..a8b7e820681 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -226,6 +226,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + NestedVisitorMap::All(&self.cx.tcx.hir) } } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 6ebe8f16a90..073d64d5a4b 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -205,3 +205,17 @@ mod issue2894 { } } } + +mod existential { + struct Foo; + + impl Foo { + fn bad(foos: &[Self]) -> impl Iterator { + foos.iter() + } + + fn good(foos: &[Self]) -> impl Iterator { + foos.iter() + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 627fc3a97cb..b71c7a9a4c5 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -120,5 +120,11 @@ error: unnecessary structure name repetition 119 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 20 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:213:54 + | +213 | fn bad(foos: &[Self]) -> impl Iterator { + | ^^^ help: use the applicable keyword: `Self` + +error: aborting due to 21 previous errors -- cgit 1.4.1-3-g733a5 From aabf8083bd7e3e45ca4701623ede99fb35dd0578 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Sat, 20 Oct 2018 23:46:13 -0400 Subject: Add lint for calling `mem::discriminant` on a non-enum type --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 4 ++ clippy_lints/src/mem_discriminant.rs | 93 ++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/mem_discriminant.rs | 44 +++++++++++++++++ tests/ui/mem_discriminant.stderr | 76 +++++++++++++++++++++++++++++ 7 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/mem_discriminant.rs create mode 100644 tests/ui/mem_discriminant.rs create mode 100644 tests/ui/mem_discriminant.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 768751b2f08..9ad6514ee10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -744,6 +744,7 @@ All notable changes to this project will be documented in this file. [`match_same_arms`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_same_arms [`match_wild_err_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_wild_err_arm [`maybe_infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#maybe_infinite_iter +[`mem_discriminant_non_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_forget [`mem_replace_option_with_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_replace_option_with_none [`min_max`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#min_max diff --git a/README.md b/README.md index 94fb8c6c02f..a13d8ecef66 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 281 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 282 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8b2070561d2..7a91890633a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -144,6 +144,7 @@ pub mod loops; pub mod map_clone; pub mod map_unit_fn; pub mod matches; +pub mod mem_discriminant; pub mod mem_forget; pub mod mem_replace; pub mod methods; @@ -398,6 +399,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); + reg.register_late_lint_pass(box mem_discriminant::MemDiscriminant); reg.register_late_lint_pass(box mem_forget::MemForget); reg.register_late_lint_pass(box mem_replace::MemReplace); reg.register_late_lint_pass(box arithmetic::Arithmetic::default()); @@ -612,6 +614,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { matches::MATCH_REF_PATS, matches::MATCH_WILD_ERR_ARM, matches::SINGLE_MATCH, + mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, mem_replace::MEM_REPLACE_OPTION_WITH_NONE, methods::CHARS_LAST_CMP, methods::CHARS_NEXT_CMP, @@ -924,6 +927,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::NEVER_LOOP, loops::REVERSE_RANGE_LOOP, loops::WHILE_IMMUTABLE_CONDITION, + mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, methods::CLONE_DOUBLE_REF, methods::TEMPORARY_CSTRING_AS_PTR, minmax::MIN_MAX, diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs new file mode 100644 index 00000000000..356162fd6f4 --- /dev/null +++ b/clippy_lints/src/mem_discriminant.rs @@ -0,0 +1,93 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use crate::rustc::hir::{Expr, ExprKind}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::utils::{match_def_path, opt_def_id, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; +use if_chain::if_chain; + +use std::iter; + +/// **What it does:** Checks for calls of `mem::discriminant()` on a non-enum type. +/// +/// **Why is this bad?** The value of `mem::discriminant()` on non-enum types +/// is unspecified. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// mem::discriminant(&"hello"); +/// mem::discriminant(&&Some(2)); +/// ``` +declare_clippy_lint! { + pub MEM_DISCRIMINANT_NON_ENUM, + correctness, + "calling mem::descriminant on non-enum type" +} + +pub struct MemDiscriminant; + +impl LintPass for MemDiscriminant { + fn get_lints(&self) -> LintArray { + lint_array![MEM_DISCRIMINANT_NON_ENUM] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::Call(ref func, ref func_args) = expr.node; + // is `mem::discriminant` + if let ExprKind::Path(ref func_qpath) = func.node; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(func_qpath, func.hir_id)); + if match_def_path(cx.tcx, def_id, &paths::MEM_DISCRIMINANT); + // type is non-enum + let ty_param = cx.tables.node_substs(func.hir_id).type_at(0); + if !ty_param.is_enum(); + + then { + span_lint_and_then( + cx, + MEM_DISCRIMINANT_NON_ENUM, + expr.span, + &format!("calling `mem::discriminant` on non-enum type `{}`", ty_param), + |db| { + // if this is a reference to an enum, suggest dereferencing + let (base_ty, ptr_depth) = walk_ptrs_ty_depth(ty_param); + if ptr_depth >= 1 && base_ty.is_enum() { + let param = &func_args[0]; + + // cancel out '&'s first + let mut derefs_needed = ptr_depth; + let mut cur_expr = param; + while derefs_needed > 0 { + if let ExprKind::AddrOf(_, ref inner_expr) = cur_expr.node { + derefs_needed -= 1; + cur_expr = inner_expr; + } else { + break; + } + } + + let derefs: String = iter::repeat('*').take(derefs_needed).collect(); + db.span_suggestion( + param.span, + "try dereferencing", + format!("{}{}", derefs, snippet(cx, cur_expr.span, "")), + ); + } + }, + ) + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 12ef2f51d8c..474f16679a7 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -55,6 +55,7 @@ pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; +pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"]; diff --git a/tests/ui/mem_discriminant.rs b/tests/ui/mem_discriminant.rs new file mode 100644 index 00000000000..a7176fb7985 --- /dev/null +++ b/tests/ui/mem_discriminant.rs @@ -0,0 +1,44 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![deny(clippy::mem_discriminant_non_enum)] + +use std::mem; + +enum Foo { + One(usize), + Two(u8), +} + +struct A(Foo); + +fn main() { + // bad + mem::discriminant(&"hello"); + mem::discriminant(&&Some(2)); + mem::discriminant(&&None::); + mem::discriminant(&&Foo::One(5)); + mem::discriminant(&&Foo::Two(5)); + mem::discriminant(&A(Foo::One(0))); + + let ro = &Some(3); + let rro = &ro; + mem::discriminant(&ro); + mem::discriminant(rro); + mem::discriminant(&rro); + + + // ok + mem::discriminant(&Some(2)); + mem::discriminant(&None::); + mem::discriminant(&Foo::One(5)); + mem::discriminant(&Foo::Two(5)); + mem::discriminant(ro); +} diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr new file mode 100644 index 00000000000..5255458d8f8 --- /dev/null +++ b/tests/ui/mem_discriminant.stderr @@ -0,0 +1,76 @@ +error: calling `mem::discriminant` on non-enum type `&str` + --> $DIR/mem_discriminant.rs:24:5 + | +24 | mem::discriminant(&"hello"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/mem_discriminant.rs:11:9 + | +11 | #![deny(clippy::mem_discriminant_non_enum)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: calling `mem::discriminant` on non-enum type `&std::option::Option` + --> $DIR/mem_discriminant.rs:25:5 + | +25 | mem::discriminant(&&Some(2)); + | ^^^^^^^^^^^^^^^^^^---------^ + | | + | help: try dereferencing: `&Some(2)` + +error: calling `mem::discriminant` on non-enum type `&std::option::Option` + --> $DIR/mem_discriminant.rs:26:5 + | +26 | mem::discriminant(&&None::); + | ^^^^^^^^^^^^^^^^^^------------^ + | | + | help: try dereferencing: `&None::` + +error: calling `mem::discriminant` on non-enum type `&Foo` + --> $DIR/mem_discriminant.rs:27:5 + | +27 | mem::discriminant(&&Foo::One(5)); + | ^^^^^^^^^^^^^^^^^^-------------^ + | | + | help: try dereferencing: `&Foo::One(5)` + +error: calling `mem::discriminant` on non-enum type `&Foo` + --> $DIR/mem_discriminant.rs:28:5 + | +28 | mem::discriminant(&&Foo::Two(5)); + | ^^^^^^^^^^^^^^^^^^-------------^ + | | + | help: try dereferencing: `&Foo::Two(5)` + +error: calling `mem::discriminant` on non-enum type `A` + --> $DIR/mem_discriminant.rs:29:5 + | +29 | mem::discriminant(&A(Foo::One(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: calling `mem::discriminant` on non-enum type `&std::option::Option` + --> $DIR/mem_discriminant.rs:33:5 + | +33 | mem::discriminant(&ro); + | ^^^^^^^^^^^^^^^^^^---^ + | | + | help: try dereferencing: `ro` + +error: calling `mem::discriminant` on non-enum type `&std::option::Option` + --> $DIR/mem_discriminant.rs:34:5 + | +34 | mem::discriminant(rro); + | ^^^^^^^^^^^^^^^^^^---^ + | | + | help: try dereferencing: `*rro` + +error: calling `mem::discriminant` on non-enum type `&&std::option::Option` + --> $DIR/mem_discriminant.rs:35:5 + | +35 | mem::discriminant(&rro); + | ^^^^^^^^^^^^^^^^^^----^ + | | + | help: try dereferencing: `*rro` + +error: aborting due to 9 previous errors + -- cgit 1.4.1-3-g733a5 From 5dbca1f6b11fd7ece50675f0c8f1ff7c254a30bd Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 21 Oct 2018 15:27:01 -0400 Subject: Add `Applicability` --- clippy_lints/src/mem_discriminant.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 356162fd6f4..c53c276991d 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -11,6 +11,7 @@ use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, opt_def_id, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; use if_chain::if_chain; @@ -79,10 +80,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { } let derefs: String = iter::repeat('*').take(derefs_needed).collect(); - db.span_suggestion( + db.span_suggestion_with_applicability( param.span, "try dereferencing", format!("{}{}", derefs, snippet(cx, cur_expr.span, "")), + Applicability::MachineApplicable, ); } }, -- cgit 1.4.1-3-g733a5 From 1a6bfecf383ca1e48fe9a5838261a60ade5af403 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Sun, 21 Oct 2018 15:23:51 -0400 Subject: Add test case for `mem::discriminant` inside a macro --- tests/ui/mem_discriminant.rs | 5 +++++ tests/ui/mem_discriminant.stderr | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/ui/mem_discriminant.rs b/tests/ui/mem_discriminant.rs index a7176fb7985..64d056fb2fe 100644 --- a/tests/ui/mem_discriminant.rs +++ b/tests/ui/mem_discriminant.rs @@ -34,6 +34,11 @@ fn main() { mem::discriminant(rro); mem::discriminant(&rro); + macro_rules! mem_discriminant_but_in_a_macro { + ($param:expr) => (mem::discriminant($param)) + } + + mem_discriminant_but_in_a_macro!(&rro); // ok mem::discriminant(&Some(2)); diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index 5255458d8f8..57e03013392 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -72,5 +72,17 @@ error: calling `mem::discriminant` on non-enum type `&&std::option::Option` | | | help: try dereferencing: `*rro` -error: aborting due to 9 previous errors +error: calling `mem::discriminant` on non-enum type `&&std::option::Option` + --> $DIR/mem_discriminant.rs:38:27 + | +38 | ($param:expr) => (mem::discriminant($param)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +41 | mem_discriminant_but_in_a_macro!(&rro); + | --------------------------------------- + | | | + | | help: try dereferencing: `*rro` + | in this macro invocation + +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From d53e6f87e94c83651ad1e22f294f6f59d8d1b5d1 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Wed, 24 Oct 2018 22:27:47 -0400 Subject: Add tests for more than one level of reference --- tests/ui/mem_discriminant.rs | 6 ++++++ tests/ui/mem_discriminant.stderr | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/ui/mem_discriminant.rs b/tests/ui/mem_discriminant.rs index 64d056fb2fe..5ddd90ac8b5 100644 --- a/tests/ui/mem_discriminant.rs +++ b/tests/ui/mem_discriminant.rs @@ -40,10 +40,16 @@ fn main() { mem_discriminant_but_in_a_macro!(&rro); + let rrrrro = &&&rro; + mem::discriminant(&rrrrro); + mem::discriminant(*rrrrro); + // ok mem::discriminant(&Some(2)); mem::discriminant(&None::); mem::discriminant(&Foo::One(5)); mem::discriminant(&Foo::Two(5)); mem::discriminant(ro); + mem::discriminant(*rro); + mem::discriminant(****rrrrro); } diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index 57e03013392..6414e4c96d6 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -84,5 +84,21 @@ error: calling `mem::discriminant` on non-enum type `&&std::option::Option` | | help: try dereferencing: `*rro` | in this macro invocation -error: aborting due to 10 previous errors +error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` + --> $DIR/mem_discriminant.rs:44:5 + | +44 | mem::discriminant(&rrrrro); + | ^^^^^^^^^^^^^^^^^^-------^ + | | + | help: try dereferencing: `****rrrrro` + +error: calling `mem::discriminant` on non-enum type `&&&std::option::Option` + --> $DIR/mem_discriminant.rs:45:5 + | +45 | mem::discriminant(*rrrrro); + | ^^^^^^^^^^^^^^^^^^-------^ + | | + | help: try dereferencing: `****rrrrro` + +error: aborting due to 12 previous errors -- cgit 1.4.1-3-g733a5 From b8a909901123fb326edf46e99d3e2d83ed22b15c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 25 Oct 2018 13:37:50 +0200 Subject: Revert "new_ret_no_self: add sample from #3313 to Known Problems section." This reverts commit fd2f6dd3824b32af031d19830b6ccdc732dd3dfc. Issue #3313 has been fixed. --- clippy_lints/src/methods/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f0810c906ef..01f97264d0b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -452,8 +452,7 @@ declare_clippy_lint! { /// **Why is this bad?** As a convention, `new` methods are used to make a new /// instance of a type. /// -/// **Known problems:** The lint fires when the return type is wrapping `Self`. -/// Example: `fn new() -> Result {}` +/// **Known problems:** None. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 3ca08959200b69f1736c1af3e5bc944ab43e739b Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 23 Oct 2018 16:01:45 +0900 Subject: Add redundant_clone lint --- clippy_lints/src/lib.rs | 3 + clippy_lints/src/redundant_clone.rs | 281 ++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 8 + tests/ui/redundant_clone.rs | 44 ++++++ tests/ui/redundant_clone.stderr | 111 ++++++++++++++ 5 files changed, 447 insertions(+) create mode 100644 clippy_lints/src/redundant_clone.rs create mode 100644 tests/ui/redundant_clone.rs create mode 100644 tests/ui/redundant_clone.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7a91890633a..eaff87e78f8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -179,6 +179,7 @@ pub mod ptr; pub mod ptr_offset_with_cast; pub mod question_mark; pub mod ranges; +pub mod redundant_clone; pub mod redundant_field_names; pub mod redundant_pattern_matching; pub mod reference; @@ -452,6 +453,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing); reg.register_late_lint_pass(box non_copy_const::NonCopyConst); reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); + reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -981,6 +983,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, + redundant_clone::REDUNDANT_CLONE, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs new file mode 100644 index 00000000000..fc760a3ee29 --- /dev/null +++ b/clippy_lints/src/redundant_clone.rs @@ -0,0 +1,281 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::intravisit::FnKind; +use crate::rustc::hir::{def_id, Body, FnDecl}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::mir::{ + self, traversal, + visit::{PlaceContext, Visitor}, + TerminatorKind, +}; +use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::{ + ast::NodeId, + source_map::{BytePos, Span}, +}; +use crate::utils::{ + in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint, span_lint_and_then, + walk_ptrs_ty_depth, +}; +use if_chain::if_chain; +use std::convert::TryFrom; + +/// **What it does:** Checks for a redudant `clone()` (and its relatives) which clones an owned +/// value that is going to be dropped without further use. +/// +/// **Why is this bad?** It is not always possible for the compiler to eliminate useless +/// allocations and deallocations generated by redundant `clone()`s. +/// +/// **Known problems:** +/// +/// * Suggestions made by this lint could require NLL to be enabled. +/// * False-positive if there is a borrow preventing the value from moving out. +/// +/// ```rust +/// let x = String::new(); +/// +/// let y = &x; +/// +/// foo(x.clone()); // This lint suggests to remove this `clone()` +/// ``` +/// +/// **Example:** +/// ```rust +/// { +/// let x = Foo::new(); +/// call(x.clone()); +/// call(x.clone()); // this can just pass `x` +/// } +/// +/// ["lorem", "ipsum"].join(" ").to_string() +/// +/// Path::new("/a/b").join("c").to_path_buf() +/// ``` +declare_clippy_lint! { + pub REDUNDANT_CLONE, + nursery, + "`clone()` of an owned value that is going to be dropped immediately" +} + +pub struct RedundantClone; + +impl LintPass for RedundantClone { + fn get_lints(&self) -> LintArray { + lint_array!(REDUNDANT_CLONE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl, + body: &'tcx Body, + _: Span, + _: NodeId, + ) { + let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let mir = cx.tcx.optimized_mir(def_id); + + // Looks for `call(&T)` where `T: !Copy` + let call = |kind: &mir::TerminatorKind<'tcx>| -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>)> { + if_chain! { + if let TerminatorKind::Call { func, args, .. } = kind; + if args.len() == 1; + if let mir::Operand::Move(mir::Place::Local(local)) = &args[0]; + if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty; + if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); + if !is_copy(cx, inner_ty); + then { + Some((def_id, *local, inner_ty)) + } else { + None + } + } + }; + + for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { + let terminator = if let Some(terminator) = &bbdata.terminator { + terminator + } else { + continue; + }; + + // Give up on loops + if terminator.successors().any(|s| *s == bb) { + continue; + } + + let (fn_def_id, arg, arg_ty) = if let Some(t) = call(&terminator.kind) { + t + } else { + continue; + }; + + let from_borrow = match_def_path(cx.tcx, fn_def_id, &paths::CLONE_TRAIT_METHOD) + || match_def_path(cx.tcx, fn_def_id, &paths::TO_OWNED_METHOD) + || (match_def_path(cx.tcx, fn_def_id, &paths::TO_STRING_METHOD) + && match_type(cx, arg_ty, &paths::STRING)); + + let from_deref = !from_borrow + && (match_def_path(cx.tcx, fn_def_id, &paths::PATH_TO_PATH_BUF) + || match_def_path(cx.tcx, fn_def_id, &paths::OS_STR_TO_OS_STRING)); + + if !from_borrow && !from_deref { + continue; + } + + // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } + let cloned = if let Some(referent) = bbdata + .statements + .iter() + .rev() + .filter_map(|stmt| { + if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { + if *local == arg { + if from_deref { + // `r` is already a reference. + if let mir::Rvalue::Use(mir::Operand::Copy(mir::Place::Local(r))) = **v { + return Some(r); + } + } else if let mir::Rvalue::Ref(_, _, mir::Place::Local(r)) = **v { + return Some(r); + } + } + } + + None + }) + .next() + { + referent + } else { + continue; + }; + + // _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }` + let referent = if from_deref { + let ps = mir.predecessors_for(bb); + let pred_arg = if_chain! { + if ps.len() == 1; + if let Some(pred_terminator) = &mir[ps[0]].terminator; + if let mir::TerminatorKind::Call { destination: Some((res, _)), .. } = &pred_terminator.kind; + if *res == mir::Place::Local(cloned); + if let Some((pred_fn_def_id, pred_arg, pred_arg_ty)) = call(&pred_terminator.kind); + if match_def_path(cx.tcx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); + if match_type(cx, pred_arg_ty, &paths::PATH_BUF) + || match_type(cx, pred_arg_ty, &paths::OS_STRING); + then { + pred_arg + } else { + continue; + } + }; + + if let Some(referent) = mir[ps[0]] + .statements + .iter() + .rev() + .filter_map(|stmt| { + if let mir::StatementKind::Assign(mir::Place::Local(l), v) = &stmt.kind { + if *l == pred_arg { + if let mir::Rvalue::Ref(_, _, mir::Place::Local(referent)) = **v { + return Some(referent); + } + } + } + + None + }) + .next() + { + referent + } else { + continue; + } + } else { + cloned + }; + + let used_later = traversal::ReversePostorder::new(&mir, bb).skip(1).any(|(tbb, tdata)| { + if let Some(term) = &tdata.terminator { + // Give up on loops + if term.successors().any(|s| *s == bb) { + return true; + } + } + + let mut vis = LocalUseVisitor { + local: referent, + used_other_than_drop: false, + }; + vis.visit_basic_block_data(tbb, tdata); + vis.used_other_than_drop + }); + + if !used_later { + let span = terminator.source_info.span; + if_chain! { + if !in_macro(span); + if let Some(snip) = snippet_opt(cx, span); + if let Some(dot) = snip.rfind('.'); + then { + let sugg_span = span.with_lo( + span.lo() + BytePos(u32::try_from(dot).unwrap()) + ); + + span_lint_and_then(cx, REDUNDANT_CLONE, sugg_span, "redundant clone", |db| { + db.span_suggestion_with_applicability( + sugg_span, + "remove this", + String::new(), + Applicability::MaybeIncorrect, + ); + db.span_note( + span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), + "this value is dropped without further use", + ); + }); + } else { + span_lint(cx, REDUNDANT_CLONE, span, "redundant clone"); + } + } + } + } + } +} + +struct LocalUseVisitor { + local: mir::Local, + used_other_than_drop: bool, +} + +impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { + fn visit_statement(&mut self, block: mir::BasicBlock, statement: &mir::Statement<'tcx>, location: mir::Location) { + // Once flagged, skip remaining statements + if !self.used_other_than_drop { + self.super_statement(block, statement, location); + } + } + + fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { + match ctx { + PlaceContext::Drop | PlaceContext::StorageDead => return, + _ => {}, + } + + if *local == self.local { + self.used_other_than_drop = true; + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 474f16679a7..8941d303156 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -23,6 +23,7 @@ pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeM pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"]; pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"]; +pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; @@ -31,6 +32,7 @@ pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"]; pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; +pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; @@ -67,7 +69,11 @@ pub const OPTION: [&str; 3] = ["core", "option", "Option"]; pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"]; pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; +pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"]; +pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; +pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; +pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; @@ -100,7 +106,9 @@ pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"]; pub const STRING: [&str; 3] = ["alloc", "string", "String"]; pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"]; +pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"]; pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"]; +pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"]; diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs new file mode 100644 index 00000000000..5fd7ffae71b --- /dev/null +++ b/tests/ui/redundant_clone.rs @@ -0,0 +1,44 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::redundant_clone)] + +use std::path::Path; +use std::ffi::OsString; + +fn main() { + let _ = ["lorem", "ipsum"].join(" ").to_string(); + + let s = String::from("foo"); + let _ = s.clone(); + + let s = String::from("foo"); + let _ = s.to_string(); + + let s = String::from("foo"); + let _ = s.to_owned(); + + let _ = Path::new("/a/b/").join("c").to_owned(); + + let _ = Path::new("/a/b/").join("c").to_path_buf(); + + let _ = OsString::new().to_owned(); + + let _ = OsString::new().to_os_string(); +} + +#[derive(Clone)] +struct Alpha; +fn double(a: Alpha) -> (Alpha, Alpha) { + if true { + (a.clone(), a.clone()) + } else { + (Alpha, a) + } +} diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr new file mode 100644 index 00000000000..ad84a5754b5 --- /dev/null +++ b/tests/ui/redundant_clone.stderr @@ -0,0 +1,111 @@ +error: redundant clone + --> $DIR/redundant_clone.rs:16:41 + | +16 | let _ = ["lorem", "ipsum"].join(" ").to_string(); + | ^^^^^^^^^^^^ help: remove this + | + = note: `-D clippy::redundant-clone` implied by `-D warnings` +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:16:13 + | +16 | let _ = ["lorem", "ipsum"].join(" ").to_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:19:14 + | +19 | let _ = s.clone(); + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:19:13 + | +19 | let _ = s.clone(); + | ^ + +error: redundant clone + --> $DIR/redundant_clone.rs:22:14 + | +22 | let _ = s.to_string(); + | ^^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:22:13 + | +22 | let _ = s.to_string(); + | ^ + +error: redundant clone + --> $DIR/redundant_clone.rs:25:14 + | +25 | let _ = s.to_owned(); + | ^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:25:13 + | +25 | let _ = s.to_owned(); + | ^ + +error: redundant clone + --> $DIR/redundant_clone.rs:27:41 + | +27 | let _ = Path::new("/a/b/").join("c").to_owned(); + | ^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:27:13 + | +27 | let _ = Path::new("/a/b/").join("c").to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:29:41 + | +29 | let _ = Path::new("/a/b/").join("c").to_path_buf(); + | ^^^^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:29:13 + | +29 | let _ = Path::new("/a/b/").join("c").to_path_buf(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:31:28 + | +31 | let _ = OsString::new().to_owned(); + | ^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:31:13 + | +31 | let _ = OsString::new().to_owned(); + | ^^^^^^^^^^^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:33:28 + | +33 | let _ = OsString::new().to_os_string(); + | ^^^^^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:33:13 + | +33 | let _ = OsString::new().to_os_string(); + | ^^^^^^^^^^^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:40:22 + | +40 | (a.clone(), a.clone()) + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:40:21 + | +40 | (a.clone(), a.clone()) + | ^ + +error: aborting due to 9 previous errors + -- cgit 1.4.1-3-g733a5 From 5285372f686ed5ff7a84cd0cefb287af6b9c62b7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 24 Oct 2018 22:57:31 +0900 Subject: Run update_lints --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ad6514ee10..5d9d470925f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -813,6 +813,7 @@ All notable changes to this project will be documented in this file. [`range_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_step_by_zero [`range_zip_with_len`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_zip_with_len +[`redundant_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_closure`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names diff --git a/README.md b/README.md index a13d8ecef66..b4091cdab6c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 282 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 283 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 105ae712f4f136adb7c94f1cfa35da30bd0e4952 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 25 Oct 2018 14:59:14 +0900 Subject: update_references indexing_slicing --- tests/ui/indexing_slicing.stderr | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index fafcb1bc485..14e9627e573 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,3 +1,29 @@ +error: index out of bounds: the len is 4 but the index is 4 + --> $DIR/indexing_slicing.rs:28:5 + | +28 | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + | ^^^^ + | + = note: #[deny(const_err)] on by default + +error: index out of bounds: the len is 4 but the index is 8 + --> $DIR/indexing_slicing.rs:29:5 + | +29 | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + | ^^^^^^^^^ + +error: index out of bounds: the len is 0 but the index is 0 + --> $DIR/indexing_slicing.rs:59:5 + | +59 | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + | ^^^^^^^^ + +error: index out of bounds: the len is 4 but the index is 15 + --> $DIR/indexing_slicing.rs:90:5 + | +90 | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + | ^^^^ + error: indexing may panic. --> $DIR/indexing_slicing.rs:23:5 | @@ -279,5 +305,5 @@ error: range is out of bounds 98 | &x[10..num]; // should trigger out of bounds error | ^^ -error: aborting due to 39 previous errors +error: aborting due to 43 previous errors -- cgit 1.4.1-3-g733a5 From 24d3f5b48f177379ba7b8727e5ba9b52b52da2f5 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 25 Oct 2018 20:33:40 +0900 Subject: Implement visit_basic_block_data --- clippy_lints/src/redundant_clone.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index fc760a3ee29..fa377dcca67 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -261,10 +261,31 @@ struct LocalUseVisitor { } impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { - fn visit_statement(&mut self, block: mir::BasicBlock, statement: &mir::Statement<'tcx>, location: mir::Location) { - // Once flagged, skip remaining statements - if !self.used_other_than_drop { - self.super_statement(block, statement, location); + fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) { + let mir::BasicBlockData { + statements, + terminator, + is_cleanup: _, + } = data; + + for (statement_index, statement) in statements.iter().enumerate() { + self.visit_statement(block, statement, mir::Location { block, statement_index }); + + // Once flagged, skip remaining statements + if self.used_other_than_drop { + return; + } + } + + if let Some(terminator) = terminator { + self.visit_terminator( + block, + terminator, + mir::Location { + block, + statement_index: statements.len(), + }, + ); } } -- cgit 1.4.1-3-g733a5 From 9a150b4aa123a6d67fbf8819fe67f2ef1015b726 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 25 Oct 2018 21:08:32 +0900 Subject: Use lint_root --- clippy_lints/src/redundant_clone.rs | 14 ++++++++++---- clippy_lints/src/utils/mod.rs | 17 +++++++++++++++++ tests/ui/redundant_clone.rs | 3 +++ tests/ui/redundant_clone.stderr | 8 ++++---- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index fa377dcca67..1a8a6273358 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -23,7 +23,7 @@ use crate::syntax::{ source_map::{BytePos, Span}, }; use crate::utils::{ - in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint, span_lint_and_then, + in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, span_lint_node_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let def_id = cx.tcx.hir.body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); - // Looks for `call(&T)` where `T: !Copy` + // Looks for `call(x: &T)` where `T: !Copy` let call = |kind: &mir::TerminatorKind<'tcx>| -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>)> { if_chain! { if let TerminatorKind::Call { func, args, .. } = kind; @@ -225,6 +225,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { if !used_later { let span = terminator.source_info.span; + let node = if let mir::ClearCrossCrate::Set(scope_local_data) = &mir.source_scope_local_data { + scope_local_data[terminator.source_info.scope].lint_root + } else { + unreachable!() + }; + if_chain! { if !in_macro(span); if let Some(snip) = snippet_opt(cx, span); @@ -234,7 +240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { span.lo() + BytePos(u32::try_from(dot).unwrap()) ); - span_lint_and_then(cx, REDUNDANT_CLONE, sugg_span, "redundant clone", |db| { + span_lint_node_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |db| { db.span_suggestion_with_applicability( sugg_span, "remove this", @@ -247,7 +253,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { ); }); } else { - span_lint(cx, REDUNDANT_CLONE, span, "redundant clone"); + span_lint_node(cx, REDUNDANT_CLONE, node, span, "redundant clone"); } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 05356f8d385..1a8db837f32 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -562,6 +562,23 @@ pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>( db.docs_link(lint); } +pub fn span_lint_node(cx: &LateContext<'_, '_>, lint: &'static Lint, node: NodeId, sp: Span, msg: &str) { + DiagnosticWrapper(cx.tcx.struct_span_lint_node(lint, node, sp, msg)).docs_link(lint); +} + +pub fn span_lint_node_and_then( + cx: &LateContext<'_, '_>, + lint: &'static Lint, + node: NodeId, + sp: Span, + msg: &str, + f: impl FnOnce(&mut DiagnosticBuilder<'_>), +) { + let mut db = DiagnosticWrapper(cx.tcx.struct_span_lint_node(lint, node, sp, msg)); + f(&mut db.0); + db.docs_link(lint); +} + /// Add a span lint with a suggestion on how to fix it. /// /// These suggestions can be parsed by rustfix to allow it to automatically fix your code. diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 5fd7ffae71b..deedde38231 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -31,6 +31,9 @@ fn main() { let _ = OsString::new().to_owned(); let _ = OsString::new().to_os_string(); + + // Check that lint level works + #[allow(clippy::redundant_clone)] let _ = String::new().to_string(); } #[derive(Clone)] diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index ad84a5754b5..db452822f89 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -96,15 +96,15 @@ note: this value is dropped without further use | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:40:22 + --> $DIR/redundant_clone.rs:43:22 | -40 | (a.clone(), a.clone()) +43 | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:40:21 + --> $DIR/redundant_clone.rs:43:21 | -40 | (a.clone(), a.clone()) +43 | (a.clone(), a.clone()) | ^ error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From 6d6ff885852e669a59013629193b74c2458005af Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 25 Oct 2018 22:02:46 +0900 Subject: Refactor --- clippy_lints/src/redundant_clone.rs | 146 +++++++++++++++++------------------- 1 file changed, 67 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 1a8a6273358..85f8b525677 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -29,6 +29,15 @@ use crate::utils::{ use if_chain::if_chain; use std::convert::TryFrom; +macro_rules! unwrap_or_continue { + ($x:expr) => { + match $x { + Some(x) => x, + None => continue, + } + }; +} + /// **What it does:** Checks for a redudant `clone()` (and its relatives) which clones an owned /// value that is going to be dropped without further use. /// @@ -87,40 +96,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let def_id = cx.tcx.hir.body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); - // Looks for `call(x: &T)` where `T: !Copy` - let call = |kind: &mir::TerminatorKind<'tcx>| -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>)> { - if_chain! { - if let TerminatorKind::Call { func, args, .. } = kind; - if args.len() == 1; - if let mir::Operand::Move(mir::Place::Local(local)) = &args[0]; - if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty; - if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); - if !is_copy(cx, inner_ty); - then { - Some((def_id, *local, inner_ty)) - } else { - None - } - } - }; - for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { - let terminator = if let Some(terminator) = &bbdata.terminator { - terminator - } else { - continue; - }; + let terminator = unwrap_or_continue!(&bbdata.terminator); // Give up on loops if terminator.successors().any(|s| *s == bb) { continue; } - let (fn_def_id, arg, arg_ty) = if let Some(t) = call(&terminator.kind) { - t - } else { - continue; - }; + let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); let from_borrow = match_def_path(cx.tcx, fn_def_id, &paths::CLONE_TRAIT_METHOD) || match_def_path(cx.tcx, fn_def_id, &paths::TO_OWNED_METHOD) @@ -135,43 +119,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { continue; } - // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } - let cloned = if let Some(referent) = bbdata - .statements - .iter() - .rev() - .filter_map(|stmt| { - if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { - if *local == arg { - if from_deref { - // `r` is already a reference. - if let mir::Rvalue::Use(mir::Operand::Copy(mir::Place::Local(r))) = **v { - return Some(r); - } - } else if let mir::Rvalue::Ref(_, _, mir::Place::Local(r)) = **v { - return Some(r); - } - } - } - - None - }) - .next() - { - referent - } else { - continue; - }; + // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } (from_deref) + // In case of `from_deref`, `arg` is already a reference since it is `deref`ed in the previous + // block. + let cloned = unwrap_or_continue!(find_stmt_assigns_to(arg, from_borrow, bbdata.statements.iter().rev())); // _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }` let referent = if from_deref { let ps = mir.predecessors_for(bb); + if ps.len() != 1 { + continue; + } + let pred_terminator = unwrap_or_continue!(&mir[ps[0]].terminator); + let pred_arg = if_chain! { - if ps.len() == 1; - if let Some(pred_terminator) = &mir[ps[0]].terminator; - if let mir::TerminatorKind::Call { destination: Some((res, _)), .. } = &pred_terminator.kind; + if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = + is_call_with_ref_arg(cx, mir, &pred_terminator.kind); if *res == mir::Place::Local(cloned); - if let Some((pred_fn_def_id, pred_arg, pred_arg_ty)) = call(&pred_terminator.kind); if match_def_path(cx.tcx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); if match_type(cx, pred_arg_ty, &paths::PATH_BUF) || match_type(cx, pred_arg_ty, &paths::OS_STRING); @@ -182,27 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { } }; - if let Some(referent) = mir[ps[0]] - .statements - .iter() - .rev() - .filter_map(|stmt| { - if let mir::StatementKind::Assign(mir::Place::Local(l), v) = &stmt.kind { - if *l == pred_arg { - if let mir::Rvalue::Ref(_, _, mir::Place::Local(referent)) = **v { - return Some(referent); - } - } - } - - None - }) - .next() - { - referent - } else { - continue; - } + unwrap_or_continue!(find_stmt_assigns_to(pred_arg, true, mir[ps[0]].statements.iter().rev())) } else { cloned }; @@ -261,6 +205,50 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { } } +/// If `kind` is `y = func(x: &T)` where `T: !Copy`, returns `(DefId of func, x, T, y)`. +fn is_call_with_ref_arg<'tcx>( + cx: &LateContext<'_, 'tcx>, + mir: &'tcx mir::Mir<'tcx>, + kind: &'tcx mir::TerminatorKind<'tcx>, +) -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> { + if_chain! { + if let TerminatorKind::Call { func, args, destination, .. } = kind; + if args.len() == 1; + if let mir::Operand::Move(mir::Place::Local(local)) = &args[0]; + if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty; + if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); + if !is_copy(cx, inner_ty); + then { + Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest))) + } else { + None + } + } +} + +/// Finds the first `to = (&)from`, and returns `Some(from)`. +fn find_stmt_assigns_to<'a, 'tcx: 'a>( + to: mir::Local, + by_ref: bool, + mut stmts: impl Iterator>, +) -> Option { + stmts.find_map(|stmt| { + if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { + if *local == to { + if by_ref { + if let mir::Rvalue::Ref(_, _, mir::Place::Local(r)) = **v { + return Some(r); + } + } else if let mir::Rvalue::Use(mir::Operand::Copy(mir::Place::Local(r))) = **v { + return Some(r); + } + } + } + + None + }) +} + struct LocalUseVisitor { local: mir::Local, used_other_than_drop: bool, -- cgit 1.4.1-3-g733a5 From a8286927800f2e9f050f0d8c3d6797d5f0885656 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 26 Oct 2018 01:27:28 +0900 Subject: Use BasicBlockData::terminator --- clippy_lints/src/redundant_clone.rs | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 85f8b525677..85f7bbb637c 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let mir = cx.tcx.optimized_mir(def_id); for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { - let terminator = unwrap_or_continue!(&bbdata.terminator); + let terminator = bbdata.terminator(); // Give up on loops if terminator.successors().any(|s| *s == bb) { @@ -130,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { if ps.len() != 1 { continue; } - let pred_terminator = unwrap_or_continue!(&mir[ps[0]].terminator); + let pred_terminator = mir[ps[0]].terminator(); let pred_arg = if_chain! { if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = @@ -152,11 +152,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { }; let used_later = traversal::ReversePostorder::new(&mir, bb).skip(1).any(|(tbb, tdata)| { - if let Some(term) = &tdata.terminator { - // Give up on loops - if term.successors().any(|s| *s == bb) { - return true; - } + // Give up on loops + if tdata.terminator().successors().any(|s| *s == bb) { + return true; } let mut vis = LocalUseVisitor { @@ -256,12 +254,7 @@ struct LocalUseVisitor { impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) { - let mir::BasicBlockData { - statements, - terminator, - is_cleanup: _, - } = data; - + let statements = &data.statements; for (statement_index, statement) in statements.iter().enumerate() { self.visit_statement(block, statement, mir::Location { block, statement_index }); @@ -271,16 +264,14 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { } } - if let Some(terminator) = terminator { - self.visit_terminator( + self.visit_terminator( + block, + data.terminator(), + mir::Location { block, - terminator, - mir::Location { - block, - statement_index: statements.len(), - }, - ); - } + statement_index: statements.len(), + }, + ); } fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { -- cgit 1.4.1-3-g733a5 From 9034b87a539904c96c01ece3c43878ce25887214 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 26 Oct 2018 03:07:29 +0900 Subject: Move in_macro check --- clippy_lints/src/redundant_clone.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 85f7bbb637c..8c895915921 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -99,6 +99,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { let terminator = bbdata.terminator(); + if in_macro(terminator.source_info.span) { + continue; + } + // Give up on loops if terminator.successors().any(|s| *s == bb) { continue; @@ -174,7 +178,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { }; if_chain! { - if !in_macro(span); if let Some(snip) = snippet_opt(cx, span); if let Some(dot) = snip.rfind('.'); then { -- cgit 1.4.1-3-g733a5 From 9e15791f0ae14d66c093bb4bcd25986a5661a64b Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 25 Oct 2018 20:14:39 +0200 Subject: ci: allow all branches except trying.tmp and staging.tmp to be built --- .travis.yml | 12 +++++------- appveyor.yml | 16 +++++++--------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97cec5ee86b..75b45c9db40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,11 @@ os: sudo: false branches: - only: - # This is where pull requests from "bors r+" are built. - - staging - # This is where pull requests from "bors try" are built. - - trying - # Also build pull requests. - - master + # Don't build these branches + except: + # Used by bors + - trying.tmp + - staging.tmp env: global: diff --git a/appveyor.yml b/appveyor.yml index 8ab4a994476..fb0b326c713 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,16 +6,14 @@ environment: #- TARGET: i686-pc-windows-msvc #- TARGET: x86_64-pc-windows-gnu - TARGET: x86_64-pc-windows-msvc - + branches: - only: - # This is where pull requests from "bors r+" are built. - - staging - # This is where pull requests from "bors try" are built. - - trying - # Also build pull requests. - - master - + # Don't build these branches + except: + # Used by bors + - trying.tmp + - staging.tmp + install: - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly -- cgit 1.4.1-3-g733a5 From 326270ad1221b54028f9d029881fa0b1fb742db9 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 26 Oct 2018 09:57:20 +0200 Subject: travis: work around temporary test failure due to rustc crashing on hyper. Upstream ticket: https://github.com/rust-lang/rust/issues/55376 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 97cec5ee86b..04027833e7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,8 @@ matrix: - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom - - env: INTEGRATION=hyperium/hyper +# uncomment once https://github.com/rust-lang/rust/issues/55376 is fixed +# - env: INTEGRATION=hyperium/hyper allow_failures: - os: windows env: BASE_TEST=true -- cgit 1.4.1-3-g733a5 From c209fc9349ff750dc983ecfe23d8e0bb74f002df Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 5 Oct 2018 09:06:05 -0700 Subject: Fix string_lit_as_bytes lint for macros Prior to this change, string_lit_as_bytes would trigger for constructs like `include_str!("filename").as_bytes()` and would recommend fixing it by rewriting as `binclude_str!("filename")`. This change updates the lint to act as an EarlyLintPass lint. It then differentiates between string literals and macros that have bytes yielding alternatives. Closes #3205 --- clippy_lints/src/strings.rs | 39 +++++++++++++++++++++++++++++++-------- tests/ui/strings.rs | 8 +++++--- tests/ui/strings.stderr | 12 ------------ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index f4798842205..9b6478fb9cd 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -92,7 +92,14 @@ impl LintPass for StringAdd { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) = e.node { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + ref left, + _, + ) = e.node + { if is_string(cx, left) { if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) { let parent = get_parent_expr(cx, e); @@ -132,13 +139,15 @@ fn is_string(cx: &LateContext<'_, '_>, e: &Expr) -> bool { fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool { match src.node { - ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), + ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + ref left, + _, + ) => SpanlessEq::new(cx).eq_expr(target, left), ExprKind::Block(ref block, _) => { - block.stmts.is_empty() - && block - .expr - .as_ref() - .map_or(false, |expr| is_add(cx, expr, target)) + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) }, _ => false, } @@ -162,7 +171,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { if path.ident.name == "as_bytes" { if let ExprKind::Lit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { - if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) { + let callsite = snippet(cx, args[0].span.source_callsite(), ""); + let expanded = format!("\"{}\"", lit_content.as_str()); + if callsite.starts_with("include_str!") { + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on `include_str!(..)`", + "consider using `include_bytes!(..)` instead", + snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1), + ); + } else if callsite == expanded + && lit_content.as_str().chars().all(|c| c.is_ascii()) + && !in_macro(args[0].span) + { span_lint_and_sugg( cx, STRING_LIT_AS_BYTES, diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 7bc4e6515f6..6693776a961 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -10,10 +10,10 @@ - #[warn(clippy::string_add)] #[allow(clippy::string_add_assign)] -fn add_only() { // ignores assignment distinction +fn add_only() { + // ignores assignment distinction let mut x = "".to_owned(); for _ in 1..3 { @@ -63,6 +63,8 @@ fn str_lit_as_bytes() { let ubs = "☃".as_bytes(); let strify = stringify!(foobar).as_bytes(); + + let includestr = include_str!("entry.rs").as_bytes(); } fn main() { @@ -72,6 +74,6 @@ fn main() { // the add is only caught for `String` let mut x = 1; - ; x = x + 1; +; x = x + 1; assert_eq!(2, x); } diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index bcdf91568d2..8a93733732e 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -60,17 +60,5 @@ error: calling `as_bytes()` on a string literal | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` -error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:65:18 - | -65 | let strify = stringify!(foobar).as_bytes(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `bstringify!(foobar)` - -error: manual implementation of an assign operation - --> $DIR/strings.rs:75:7 - | -75 | ; x = x + 1; - | ^^^^^^^^^ help: replace it with: `x += 1` - error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From f9020bb2dded44e97fd997ab71ab4edf6d88033b Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Wed, 24 Oct 2018 11:49:39 -0400 Subject: fix: extra semicolon, only create callsite once --- clippy_lints/src/strings.rs | 2 +- tests/ui/strings.rs | 5 ++++- tests/ui/strings.stderr | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 9b6478fb9cd..fe3d461ab43 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { if path.ident.name == "as_bytes" { if let ExprKind::Lit(ref lit) = args[0].node { if let LitKind::Str(ref lit_content, _) = lit.node { - let callsite = snippet(cx, args[0].span.source_callsite(), ""); + let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#); let expanded = format!("\"{}\"", lit_content.as_str()); if callsite.starts_with("include_str!") { span_lint_and_sugg( diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index 6693776a961..d2062b356dc 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -59,6 +59,8 @@ fn both() { fn str_lit_as_bytes() { let bs = "hello there".as_bytes(); + let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); + // no warning, because this cannot be written as a byte string literal: let ubs = "☃".as_bytes(); @@ -67,6 +69,7 @@ fn str_lit_as_bytes() { let includestr = include_str!("entry.rs").as_bytes(); } +#[allow(clippy::assign_op_pattern)] fn main() { add_only(); add_assign_only(); @@ -74,6 +77,6 @@ fn main() { // the add is only caught for `String` let mut x = 1; -; x = x + 1; + x = x + 1; assert_eq!(2, x); } diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index 8a93733732e..2496270ba0d 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -60,5 +60,3 @@ error: calling `as_bytes()` on a string literal | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` -error: aborting due to 11 previous errors - -- cgit 1.4.1-3-g733a5 From 19ac2e94c6cb12ae4f9fb410f165e2aa5309e124 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 26 Oct 2018 09:10:20 -0700 Subject: fix: correctly reconstruct raw strings --- clippy_lints/src/strings.rs | 12 ++++++++---- tests/ui/strings.stderr | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index fe3d461ab43..e07b1649a46 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -164,15 +163,20 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use crate::syntax::ast::LitKind; + use crate::syntax::ast::{LitKind, StrStyle}; use crate::utils::{in_macro, snippet}; if let ExprKind::MethodCall(ref path, _, ref args) = e.node { if path.ident.name == "as_bytes" { if let ExprKind::Lit(ref lit) = args[0].node { - if let LitKind::Str(ref lit_content, _) = lit.node { + if let LitKind::Str(ref lit_content, style) = lit.node { let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#); - let expanded = format!("\"{}\"", lit_content.as_str()); + let expanded = if let StrStyle::Raw(n) = style { + let term = (0..n).map(|_| '#').collect::(); + format!("r{0}\"{1}\"{0}", term, lit_content.as_str()) + } else { + format!("\"{}\"", lit_content.as_str()) + }; if callsite.starts_with("include_str!") { span_lint_and_sugg( cx, diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index 2496270ba0d..21115d8e97e 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -60,3 +60,17 @@ error: calling `as_bytes()` on a string literal | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` +error: calling `as_bytes()` on a string literal + --> $DIR/strings.rs:62:14 + | +62 | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###` + +error: calling `as_bytes()` on `include_str!(..)` + --> $DIR/strings.rs:69:22 + | +69 | let includestr = include_str!("entry.rs").as_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")` + +error: aborting due to 11 previous errors + -- cgit 1.4.1-3-g733a5 From d6ca12a70dad2c34b8bcb421bf5b6d9b79d06b2e Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 26 Oct 2018 19:58:50 +0200 Subject: simplify ci base-tests --- ci/base-tests.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 72a38ee5e58..6ff3c41607b 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -24,21 +24,21 @@ cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. # check that the lint lists are up-to-date ./util/update_lints.py -c -mkdir -p ~/rust/cargo/bin -cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy -cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver -rm ~/.cargo/bin/cargo-clippy + +CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... -PATH=$PATH:~/rust/cargo/bin cargo clippy --all-targets --all-features -- -D clippy::all -D clippy::internal +${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal # ... and some test directories -cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. -cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. -cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../.. -cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd ../../.. -cd clippy_dev && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. -cd rustc_tools_util/ && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy::all && cd .. +CWD_OLD=`pwd` +for dir in clippy_workspace_tests clippy_workspace_tests/src clippy_workspace_tests/subcrate clippy_workspace_tests/subcrate/src clippy_dev rustc_tools_util +do + cd ${dir} + ${CLIPPY} -- -D clippy::all + cd ${CWD_OLD} +done + # test --manifest-path -PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all -cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. +${CLIPPY} --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all +cd clippy_workspace_tests/subcrate && ${CLIPPY} --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. set +x -- cgit 1.4.1-3-g733a5 From a90084d587a4c75c9fd42773bd5395cc7e62f528 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 26 Oct 2018 20:00:49 +0200 Subject: slightly simplify integration tests --- ci/base-tests.sh | 3 +-- ci/integration-tests.sh | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 6ff3c41607b..9b73263c24a 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -29,12 +29,11 @@ CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... ${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal # ... and some test directories -CWD_OLD=`pwd` for dir in clippy_workspace_tests clippy_workspace_tests/src clippy_workspace_tests/subcrate clippy_workspace_tests/subcrate/src clippy_dev rustc_tools_util do cd ${dir} ${CLIPPY} -- -D clippy::all - cd ${CWD_OLD} + cd - done diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 9019a6830e6..75decab940e 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -28,9 +28,6 @@ function check() { } case ${INTEGRATION} in - rust-lang/cargo) - check - ;; *) check ;; -- cgit 1.4.1-3-g733a5 From aa7bcb9074f3a7235e43d1da910d80248e53357d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 27 Oct 2018 11:01:27 +0200 Subject: Don't expand macro in identity_conversion suggestion --- clippy_lints/src/identity_conversion.rs | 5 +++-- clippy_lints/src/utils/mod.rs | 6 ++++++ tests/ui/identity_conversion.rs | 1 + tests/ui/identity_conversion.stderr | 8 +++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index e9761616696..00ce58f00b0 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -12,7 +12,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; use crate::syntax::ast::NodeId; -use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then}; +use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then}; use crate::utils::{opt_def_id, paths, resolve_node}; use crate::rustc_errors::Applicability; @@ -72,7 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { - let sugg = snippet(cx, args[0].span, "").into_owned(); + let sugg = snippet_with_macro_callsite(cx, args[0].span, "").to_string(); + span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { db.span_suggestion_with_applicability( e.span, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 1a8db837f32..5ff246630e0 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -362,6 +362,12 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) } +/// Same as `snippet`, but should only be used when it's clear that the input span is +/// not a macro argument. +pub fn snippet_with_macro_callsite<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + snippet(cx, span.source_callsite(), default) +} + /// Convert a span to a code snippet. Returns `None` if not available. pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { cx.sess().source_map().span_to_snippet(span).ok() diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 9384c9eb206..b5cb92c6d5a 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -53,4 +53,5 @@ fn main() { let _ = String::from(format!("A: {:04}", 123)); let _ = "".lines().into_iter(); let _ = vec![1, 2, 3].into_iter().into_iter(); + let _: String = format!("Hello {}", "world").into(); } diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 2ac74191931..15bef8b125e 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -58,5 +58,11 @@ error: identical conversion 55 | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: aborting due to 9 previous errors +error: identical conversion + --> $DIR/identity_conversion.rs:56:21 + | +56 | let _: String = format!("Hello {}", "world").into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` + +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From af1548f58f2a9a356a7c122f2fba25c816492a91 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 27 Oct 2018 14:45:02 +0200 Subject: Don't expand macro in single_match suggestion --- clippy_lints/src/matches.rs | 3 ++- clippy_lints/src/utils/mod.rs | 5 ++++- tests/ui/matches.stderr | 2 +- tests/ui/single_match.rs | 9 ++++++++ tests/ui/single_match.stderr | 52 ++++++++++++++++++++++++++----------------- 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index e46615f4da2..4a704c3d52e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -19,7 +19,8 @@ use crate::syntax::ast::LitKind; use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, - remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; + remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, + span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; use crate::rustc_errors::Applicability; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 5ff246630e0..72a6bda26c3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -406,7 +406,10 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( ) -> Cow<'a, str> { let code = snippet_block(cx, expr.span, default); let string = option.unwrap_or_default(); - if let ExprKind::Block(_, _) = expr.node { + if in_macro(expr.span) { + Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default))) + } + else if let ExprKind::Block(_, _) = expr.node { Cow::Owned(format!("{}{}", code, string)) } else if string.is_empty() { Cow::Owned(format!("{{ {} }}", code)) diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index bed903faf1a..b5f1f2ab0e7 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -33,7 +33,7 @@ error: you seem to be trying to use match for destructuring a single pattern. Co 51 | | &(v, 1) => println!("{}", v), 52 | | _ => println!("none"), 53 | | } - | |_____^ help: try this: `if let &(v, 1) = tup { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; } else { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; }` + | |_____^ help: try this: `if let &(v, 1) = tup { println!("{}", v) } else { println!("none") }` error: you don't need to add `&` to all patterns --> $DIR/matches.rs:50:5 diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 5c7cae249b4..dca68e179e7 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -23,6 +23,15 @@ fn single_match(){ _ => () }; + let x = Some(1u8); + match x { + // Note the missing block braces. + // We suggest `if let Some(y) = x { .. }` because the macro + // is expanded before we can do anything. + Some(y) => println!("{:?}", y), + _ => () + } + let z = (1u8,1u8); match z { (2...3, 7...9) => dummy(), diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 74448391ca5..df614ad201d 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -12,38 +12,50 @@ error: you seem to be trying to use match for destructuring a single pattern. Co error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:27:5 | -27 | / match z { -28 | | (2...3, 7...9) => dummy(), -29 | | _ => {} -30 | | }; +27 | / match x { +28 | | // Note the missing block braces. +29 | | // We suggest `if let Some(y) = x { .. }` because the macro +30 | | // is expanded before we can do anything. +31 | | Some(y) => println!("{:?}", y), +32 | | _ => () +33 | | } + | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:36:5 + | +36 | / match z { +37 | | (2...3, 7...9) => dummy(), +38 | | _ => {} +39 | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:53:5 + --> $DIR/single_match.rs:62:5 | -53 | / match x { -54 | | Some(y) => dummy(), -55 | | None => () -56 | | }; +62 | / match x { +63 | | Some(y) => dummy(), +64 | | None => () +65 | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:58:5 + --> $DIR/single_match.rs:67:5 | -58 | / match y { -59 | | Ok(y) => dummy(), -60 | | Err(..) => () -61 | | }; +67 | / match y { +68 | | Ok(y) => dummy(), +69 | | Err(..) => () +70 | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:65:5 + --> $DIR/single_match.rs:74:5 | -65 | / match c { -66 | | Cow::Borrowed(..) => dummy(), -67 | | Cow::Owned(..) => (), -68 | | }; +74 | / match c { +75 | | Cow::Borrowed(..) => dummy(), +76 | | Cow::Owned(..) => (), +77 | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 840e50e97f023c2d0bfeb0222d094fa407f12f2f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 27 Oct 2018 15:37:56 +0200 Subject: Don't expand macro in or_fun_call suggestion --- clippy_lints/src/methods/mod.rs | 8 ++++---- tests/ui/methods.stderr | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 01f97264d0b..8d0cd32e23b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -21,7 +21,7 @@ use crate::utils::sugg; use crate::utils::{ get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, - match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, span_lint, + match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; use if_chain::if_chain; @@ -1062,9 +1062,9 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa } let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) { - (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(), - (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(), - (false, true) => snippet(cx, fun_span, ".."), + (true, _) => format!("|_| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(), + (false, false) => format!("|| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(), + (false, true) => snippet_with_macro_callsite(cx, fun_span, ".."), }; let span_replace_word = method_span.with_hi(span.hi()); span_lint_and_sugg( diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 307814824ea..896b15481bb 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -297,7 +297,7 @@ error: use of `unwrap_or` followed by a function call --> $DIR/methods.rs:339:14 | 339 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call --> $DIR/methods.rs:344:21 -- cgit 1.4.1-3-g733a5 From 0d899562cd805bd4335d6ee8d88e2bf1f743f000 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 28 Oct 2018 08:11:18 +0100 Subject: Disable rust master toolchain build temporarily --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09972a12f8d..d3f8c116607 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,13 +75,14 @@ matrix: - os: windows script: - - | - rm rust-toolchain - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') - travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH - rustup default master - export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + # uncomment once https://github.com/rust-lang/rust/issues/55376 is fixed + # - | + # rm rust-toolchain + # cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + # RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') + # travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH + # rustup default master + # export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh && sleep 5 -- cgit 1.4.1-3-g733a5 From 061a48321c46c4050afcdadbc57f5869cae37eeb Mon Sep 17 00:00:00 2001 From: Michael Rutter Date: Sun, 28 Oct 2018 08:12:47 +0000 Subject: added downsides to "known problems" for get_unwrap lint --- clippy_lints/src/methods/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 01f97264d0b..8e3a75f2c7b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -568,7 +568,14 @@ declare_clippy_lint! { /// **Why is this bad?** Using the Index trait (`[]`) is more clear and more /// concise. /// -/// **Known problems:** None. +/// **Known problems:** Not a replacement for error handling: Using either +/// `.unwrap()` or the Index syntax (`[]`) carries the risk of causing a `panic` +/// if the value being accessed is `None`. If the use of `.get().unwrap()` is a +/// temporary placeholder for dealing with the `Option` type, then this does +/// not mitigate the need for error handling. If there is a chance that `.get()` +/// will be `None` in your program, then it is advisable that the `None` case +/// is eventually handled in a future refactor instead of using `.unwrap()` +/// or the Index syntax. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 232a483331242a3c10097b0c182c80b1403b7a1e Mon Sep 17 00:00:00 2001 From: Michael Rutter Date: Sun, 28 Oct 2018 12:31:02 +0000 Subject: more consistent use of terminology; trait > syntax --- clippy_lints/src/methods/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 8e3a75f2c7b..10e6644b70e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -569,13 +569,13 @@ declare_clippy_lint! { /// concise. /// /// **Known problems:** Not a replacement for error handling: Using either -/// `.unwrap()` or the Index syntax (`[]`) carries the risk of causing a `panic` +/// `.unwrap()` or the Index trait (`[]`) carries the risk of causing a `panic` /// if the value being accessed is `None`. If the use of `.get().unwrap()` is a /// temporary placeholder for dealing with the `Option` type, then this does /// not mitigate the need for error handling. If there is a chance that `.get()` /// will be `None` in your program, then it is advisable that the `None` case -/// is eventually handled in a future refactor instead of using `.unwrap()` -/// or the Index syntax. +/// is handled in a future refactor instead of using `.unwrap()` or the Index +/// trait. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 6eb1f23555102cbd0619a79423a4d9bc56ee30b1 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 28 Oct 2018 12:50:32 +0100 Subject: rustup: fix build with rustc 1.31.0-nightly (cae6efc37 2018-10-27) --- clippy_lints/src/redundant_clone.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 8c895915921..2ed877d1364 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -12,7 +12,7 @@ use crate::rustc::hir::{def_id, Body, FnDecl}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::mir::{ self, traversal, - visit::{PlaceContext, Visitor}, + visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor}, TerminatorKind, }; use crate::rustc::ty; @@ -279,7 +279,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { match ctx { - PlaceContext::Drop | PlaceContext::StorageDead => return, + PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => return, _ => {}, } -- cgit 1.4.1-3-g733a5 From 7cfde9cfa95b0c466efe867e064d05fd8adea568 Mon Sep 17 00:00:00 2001 From: Giorgio Gambino Date: Sun, 28 Oct 2018 15:37:39 +0100 Subject: Fix #3335: bool_comparison triggers 3 times on same code --- clippy_lints/src/needless_bool.rs | 100 +++++++++++++++++++------------------- tests/ui/needless_bool.rs | 47 +++++++++++++++++- tests/ui/needless_bool.stderr | 72 ++++++++++++++++++--------- 3 files changed, 146 insertions(+), 73 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index f102b49d785..3afccf9f984 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -17,7 +17,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Spanned; -use crate::utils::{snippet, span_lint, span_lint_and_sugg}; +use crate::utils::{in_macro, snippet, span_lint, span_lint_and_sugg}; use crate::utils::sugg::Sugg; /// **What it does:** Checks for expressions of the form `if c { true } else { @@ -133,54 +133,56 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use self::Expression::*; - if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { - match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Bool(true), Other) => { - let hint = snippet(cx, right_side.span, "..").into_owned(); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint, - ); - }, - (Other, Bool(true)) => { - let hint = snippet(cx, left_side.span, "..").into_owned(); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint, - ); - }, - (Bool(false), Other) => { - let hint = Sugg::hir(cx, right_side, ".."); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - ); - }, - (Other, Bool(false)) => { - let hint = Sugg::hir(cx, left_side, ".."); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - ); - }, - _ => (), + if !in_macro(e.span) { + use self::Expression::*; + if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { + (Bool(true), Other) => { + let hint = snippet(cx, right_side.span, "..").into_owned(); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); + }, + (Other, Bool(true)) => { + let hint = snippet(cx, left_side.span, "..").into_owned(); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); + }, + (Bool(false), Other) => { + let hint = Sugg::hir(cx, right_side, ".."); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); + }, + (Other, Bool(false)) => { + let hint = Sugg::hir(cx, left_side, ".."); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); + }, + _ => (), + } } } } diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index a9a2e3709f1..aca4ccabf0e 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -8,9 +8,31 @@ // except according to those terms. +#![warn(clippy::needless_bool)] +use std::cell::Cell; -#![warn(clippy::needless_bool)] +macro_rules! bool_comparison_trigger { + ($($i:ident: $def:expr, $stb:expr );+ $(;)*) => ( + + #[derive(Clone)] + pub struct Trigger { + $($i: (Cell, bool, bool)),+ + } + + #[allow(dead_code)] + impl Trigger { + pub fn trigger(&self, key: &str) -> bool { + $( + if let stringify!($i) = key { + return self.$i.1 && self.$i.2 == $def; + } + )+ + false + } + } + ) +} #[allow(clippy::if_same_then_else)] fn main() { @@ -28,6 +50,9 @@ fn main() { bool_ret5(x, x); bool_ret4(x); bool_ret6(x, x); + needless_bool(x); + needless_bool2(x); + needless_bool3(x); } #[allow(clippy::if_same_then_else, clippy::needless_return)] @@ -59,3 +84,23 @@ fn bool_ret4(x: bool) -> bool { fn bool_ret6(x: bool, y: bool) -> bool { if x && y { return false } else { return true }; } + +fn needless_bool(x: bool) { + if x == true { }; +} + +fn needless_bool2(x: bool) { + if x == false { }; +} + +fn needless_bool3(x: bool) { + + bool_comparison_trigger! { + test_one: false, false; + test_three: false, false; + test_two: true, true; + } + + if x == true { }; + if x == false { }; +} \ No newline at end of file diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index 13af6fc3564..638a3f56f0f 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,70 +1,96 @@ error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:19:5 + --> $DIR/needless_bool.rs:41:5 | -19 | if x { true } else { true }; +41 | if x { true } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:20:5 + --> $DIR/needless_bool.rs:42:5 | -20 | if x { false } else { false }; +42 | if x { false } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:21:5 + --> $DIR/needless_bool.rs:43:5 | -21 | if x { true } else { false }; +43 | if x { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:22:5 + --> $DIR/needless_bool.rs:44:5 | -22 | if x { false } else { true }; +44 | if x { false } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:23:5 + --> $DIR/needless_bool.rs:45:5 | -23 | if x && y { false } else { true }; +45 | if x && y { false } else { true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:35:5 + --> $DIR/needless_bool.rs:60:5 | -35 | if x { return true } else { return true }; +60 | if x { return true } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:40:5 + --> $DIR/needless_bool.rs:65:5 | -40 | if x { return false } else { return false }; +65 | if x { return false } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:45:5 + --> $DIR/needless_bool.rs:70:5 | -45 | if x { return true } else { return false }; +70 | if x { return true } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:50:5 + --> $DIR/needless_bool.rs:75:5 | -50 | if x && y { return true } else { return false }; +75 | if x && y { return true } else { return false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:55:5 + --> $DIR/needless_bool.rs:80:5 | -55 | if x { return false } else { return true }; +80 | if x { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:60:5 + --> $DIR/needless_bool.rs:85:5 | -60 | if x && y { return false } else { return true }; +85 | if x && y { return false } else { return true }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !(x && y)` -error: aborting due to 11 previous errors +error: equality checks against true are unnecessary + --> $DIR/needless_bool.rs:89:7 + | +89 | if x == true { }; + | ^^^^^^^^^^ help: try simplifying it as shown: `x` + | + = note: `-D clippy::bool-comparison` implied by `-D warnings` + +error: equality checks against false can be replaced by a negation + --> $DIR/needless_bool.rs:93:7 + | +93 | if x == false { }; + | ^^^^^^^^^^^ help: try simplifying it as shown: `!x` + +error: equality checks against true are unnecessary + --> $DIR/needless_bool.rs:104:8 + | +104 | if x == true { }; + | ^^^^^^^^^ help: try simplifying it as shown: `x` + +error: equality checks against false can be replaced by a negation + --> $DIR/needless_bool.rs:105:8 + | +105 | if x == false { }; + | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + +error: aborting due to 15 previous errors -- cgit 1.4.1-3-g733a5 From 62f16803e8abb176279d3160f0287ad0f0575105 Mon Sep 17 00:00:00 2001 From: Giorgio Gambino Date: Sun, 28 Oct 2018 16:28:17 +0100 Subject: Fix #3335 rev1: bool_comparison triggers 3 times on same code --- tests/ui/needless_bool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index aca4ccabf0e..98c2e0767d6 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -103,4 +103,4 @@ fn needless_bool3(x: bool) { if x == true { }; if x == false { }; -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 349697531ffe4eef947d5755a6045232a8198bbf Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 28 Oct 2018 16:52:38 +0100 Subject: pin compiletest dependency to git version (12c980f47971b5ba6beb7cb2ffebf8b32f6766ea) while we are waiting for a new release --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 518c2caf671..81ca6c46817 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6" -compiletest_rs = "0.3.7" +compiletest_rs = { git = "https://github.com/laumann/compiletest-rs", rev = "12c980f47971b5ba6beb7cb2ffebf8b32f6766ea" } lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } -- cgit 1.4.1-3-g733a5 From 3f0161918871403b4e0547191a93f395b8bf5b35 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 28 Oct 2018 17:14:39 +0100 Subject: appveyor: use rustc nightly instead of master --- appveyor.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fb0b326c713..18f25e916f3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,11 +20,12 @@ install: - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}' >rustc-hash.txt - set /p RUSTC_HASH= Date: Sat, 27 Oct 2018 19:31:47 +0200 Subject: UI test cleanup: Extract unnecessary_operation tests --- tests/ui/no_effect.rs | 31 +-------- tests/ui/no_effect.stderr | 124 +--------------------------------- tests/ui/unnecessary_operation.rs | 76 +++++++++++++++++++++ tests/ui/unnecessary_operation.stderr | 124 ++++++++++++++++++++++++++++++++++ 4 files changed, 202 insertions(+), 153 deletions(-) create mode 100644 tests/ui/unnecessary_operation.rs create mode 100644 tests/ui/unnecessary_operation.stderr diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 32e1ccb7bee..bee3aeb6f7f 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -13,7 +13,7 @@ #![feature(box_syntax)] -#![warn(clippy::no_effect, clippy::unnecessary_operation)] +#![warn(clippy::no_effect)] #![allow(dead_code)] #![allow(path_statements)] #![allow(clippy::deref_addrof)] @@ -105,33 +105,4 @@ fn main() { DropTuple(0); DropEnum::Tuple(0); DropEnum::Struct { field: 0 }; - - Tuple(get_number()); - Struct { field: get_number() }; - Struct { ..get_struct() }; - Enum::Tuple(get_number()); - Enum::Struct { field: get_number() }; - 5 + get_number(); - *&get_number(); - &get_number(); - (5, 6, get_number()); - box get_number(); - get_number()..; - ..get_number(); - 5..get_number(); - [42, get_number()]; - [42, 55][get_number() as usize]; - (42, get_number()).1; - [get_number(); 55]; - [42; 55][get_number() as usize]; - {get_number()}; - FooString { s: String::from("blah"), }; - - // Do not warn - DropTuple(get_number()); - DropStruct { field: get_number() }; - DropStruct { field: get_number() }; - DropStruct { ..get_drop_struct() }; - DropEnum::Tuple(get_number()); - DropEnum::Struct { field: get_number() }; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index eca47d7546e..7f012aa2ed4 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -150,127 +150,5 @@ error: statement with no effect 98 | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ -error: statement can be reduced - --> $DIR/no_effect.rs:109:5 - | -109 | Tuple(get_number()); - | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - | - = note: `-D clippy::unnecessary-operation` implied by `-D warnings` - -error: statement can be reduced - --> $DIR/no_effect.rs:110:5 - | -110 | Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:111:5 - | -111 | Struct { ..get_struct() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` - -error: statement can be reduced - --> $DIR/no_effect.rs:112:5 - | -112 | Enum::Tuple(get_number()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:113:5 - | -113 | Enum::Struct { field: get_number() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:114:5 - | -114 | 5 + get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:115:5 - | -115 | *&get_number(); - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:116:5 - | -116 | &get_number(); - | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:117:5 - | -117 | (5, 6, get_number()); - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:118:5 - | -118 | box get_number(); - | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:119:5 - | -119 | get_number()..; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:120:5 - | -120 | ..get_number(); - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:121:5 - | -121 | 5..get_number(); - | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:122:5 - | -122 | [42, get_number()]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:123:5 - | -123 | [42, 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` - -error: statement can be reduced - --> $DIR/no_effect.rs:124:5 - | -124 | (42, get_number()).1; - | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:125:5 - | -125 | [get_number(); 55]; - | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:126:5 - | -126 | [42; 55][get_number() as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` - -error: statement can be reduced - --> $DIR/no_effect.rs:127:5 - | -127 | {get_number()}; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` - -error: statement can be reduced - --> $DIR/no_effect.rs:128:5 - | -128 | FooString { s: String::from("blah"), }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` - -error: aborting due to 45 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs new file mode 100644 index 00000000000..de44047c867 --- /dev/null +++ b/tests/ui/unnecessary_operation.rs @@ -0,0 +1,76 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![allow(clippy::deref_addrof)] +#![warn(clippy::unnecessary_operation)] + +struct Tuple(i32); +struct Struct { + field: i32 +} +enum Enum { + Tuple(i32), + Struct { field: i32 }, +} +struct DropStruct { + field: i32 +} +impl Drop for DropStruct { + fn drop(&mut self) {} +} +struct DropTuple(i32); +impl Drop for DropTuple { + fn drop(&mut self) {} +} +enum DropEnum { + Tuple(i32), + Struct { field: i32 }, +} +impl Drop for DropEnum { + fn drop(&mut self) {} +} +struct FooString { + s: String, +} + +fn get_number() -> i32 { 0 } +fn get_struct() -> Struct { Struct { field: 0 } } +fn get_drop_struct() -> DropStruct { DropStruct { field: 0 } } + +fn main() { + Tuple(get_number()); + Struct { field: get_number() }; + Struct { ..get_struct() }; + Enum::Tuple(get_number()); + Enum::Struct { field: get_number() }; + 5 + get_number(); + *&get_number(); + &get_number(); + (5, 6, get_number()); + box get_number(); + get_number()..; + ..get_number(); + 5..get_number(); + [42, get_number()]; + [42, 55][get_number() as usize]; + (42, get_number()).1; + [get_number(); 55]; + [42; 55][get_number() as usize]; + {get_number()}; + FooString { s: String::from("blah"), }; + + // Do not warn + DropTuple(get_number()); + DropStruct { field: get_number() }; + DropStruct { field: get_number() }; + DropStruct { ..get_drop_struct() }; + DropEnum::Tuple(get_number()); + DropEnum::Struct { field: get_number() }; +} diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr new file mode 100644 index 00000000000..8e5417eb13e --- /dev/null +++ b/tests/ui/unnecessary_operation.stderr @@ -0,0 +1,124 @@ +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:48:5 + | +48 | Tuple(get_number()); + | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + | + = note: `-D clippy::unnecessary-operation` implied by `-D warnings` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:49:5 + | +49 | Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:50:5 + | +50 | Struct { ..get_struct() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:51:5 + | +51 | Enum::Tuple(get_number()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:52:5 + | +52 | Enum::Struct { field: get_number() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:53:5 + | +53 | 5 + get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:54:5 + | +54 | *&get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:55:5 + | +55 | &get_number(); + | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:56:5 + | +56 | (5, 6, get_number()); + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:57:5 + | +57 | box get_number(); + | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:58:5 + | +58 | get_number()..; + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:59:5 + | +59 | ..get_number(); + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:60:5 + | +60 | 5..get_number(); + | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:61:5 + | +61 | [42, get_number()]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:62:5 + | +62 | [42, 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:63:5 + | +63 | (42, get_number()).1; + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:64:5 + | +64 | [get_number(); 55]; + | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:65:5 + | +65 | [42; 55][get_number() as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:66:5 + | +66 | {get_number()}; + | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` + +error: statement can be reduced + --> $DIR/unnecessary_operation.rs:67:5 + | +67 | FooString { s: String::from("blah"), }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` + +error: aborting due to 20 previous errors + -- cgit 1.4.1-3-g733a5 From 18b122005fa297c9c39a1ef3fb6973e955ea43c4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 27 Oct 2018 19:16:43 +0200 Subject: UI test cleanup: Extract explicit_counter_loop tests --- tests/ui/explicit_counter_loop.rs | 122 ++++++++++++++++++++++++++++++++++ tests/ui/explicit_counter_loop.stderr | 28 ++++++++ tests/ui/for_loop.rs | 112 +------------------------------ tests/ui/for_loop.stderr | 106 +++++++++++------------------ 4 files changed, 191 insertions(+), 177 deletions(-) create mode 100644 tests/ui/explicit_counter_loop.rs create mode 100644 tests/ui/explicit_counter_loop.stderr diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs new file mode 100644 index 00000000000..eaed606b89e --- /dev/null +++ b/tests/ui/explicit_counter_loop.rs @@ -0,0 +1,122 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::explicit_counter_loop)] + +fn main() { + let mut vec = vec![1, 2, 3, 4]; + let mut _index = 0; + for _v in &vec { + _index += 1 + } + + let mut _index = 1; + _index = 0; + for _v in &vec { + _index += 1 + } +} + +mod issue_1219 { + pub fn test() { + // should not trigger the lint because variable is used after the loop #473 + let vec = vec![1,2,3]; + let mut index = 0; + for _v in &vec { index += 1 } + println!("index: {}", index); + + // should not trigger the lint because the count is conditional #1219 + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + if ch == 'a' { + continue; + } + count += 1; + println!("{}", count); + } + + // should not trigger the lint because the count is conditional + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + if ch == 'a' { + count += 1; + } + println!("{}", count); + } + + // should trigger the lint because the count is not conditional + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + if ch == 'a' { + continue; + } + println!("{}", count); + } + + // should trigger the lint because the count is not conditional + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + for i in 0..2 { + let _ = 123; + } + println!("{}", count); + } + + // should not trigger the lint because the count is incremented multiple times + let text = "banana"; + let mut count = 0; + for ch in text.chars() { + count += 1; + for i in 0..2 { + count += 1; + } + println!("{}", count); + } + } +} + +mod issue_3308 { + pub fn test() { + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + let erasures = vec![]; + for i in 0..10 { + while erasures.contains(&(i + skips)) { + skips += 1; + } + println!("{}", skips); + } + + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + for i in 0..10 { + let mut j = 0; + while j < 5 { + skips += 1; + j += 1; + } + println!("{}", skips); + } + + // should not trigger the lint because the count is incremented multiple times + let mut skips = 0; + for i in 0..10 { + for j in 0..5 { + skips += 1; + } + println!("{}", skips); + } + } +} diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr new file mode 100644 index 00000000000..023f7f299a7 --- /dev/null +++ b/tests/ui/explicit_counter_loop.stderr @@ -0,0 +1,28 @@ +error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators + --> $DIR/explicit_counter_loop.rs:15:15 + | +15 | for _v in &vec { + | ^^^^ + | + = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` + +error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators + --> $DIR/explicit_counter_loop.rs:21:15 + | +21 | for _v in &vec { + | ^^^^ + +error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators + --> $DIR/explicit_counter_loop.rs:58:19 + | +58 | for ch in text.chars() { + | ^^^^^^^^^^^^ + +error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators + --> $DIR/explicit_counter_loop.rs:69:19 + | +69 | for ch in text.chars() { + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index f80270d9fe8..eefb4317276 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -84,7 +84,7 @@ impl Unrelated { } #[warn(clippy::needless_range_loop, clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, clippy::reverse_range_loop, - clippy::explicit_counter_loop, clippy::for_kv_map)] + clippy::for_kv_map)] #[warn(clippy::unused_collect)] #[allow(clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, clippy::cyclomatic_complexity, clippy::similar_names)] #[allow(clippy::many_single_char_names, unused_variables)] @@ -275,16 +275,6 @@ fn main() { let _y = vec.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine // Loop with explicit counter variable - let mut _index = 0; - for _v in &vec { - _index += 1 - } - - let mut _index = 1; - _index = 0; - for _v in &vec { - _index += 1 - } // Potential false positives let mut _index = 0; @@ -594,103 +584,3 @@ mod issue_2496 { unimplemented!() } } - -mod issue_1219 { - #[warn(clippy::explicit_counter_loop)] - pub fn test() { - // should not trigger the lint because variable is used after the loop #473 - let vec = vec![1,2,3]; - let mut index = 0; - for _v in &vec { index += 1 } - println!("index: {}", index); - - // should not trigger the lint because the count is conditional #1219 - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - if ch == 'a' { - continue; - } - count += 1; - println!("{}", count); - } - - // should not trigger the lint because the count is conditional - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - if ch == 'a' { - count += 1; - } - println!("{}", count); - } - - // should trigger the lint because the count is not conditional - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - count += 1; - if ch == 'a' { - continue; - } - println!("{}", count); - } - - // should trigger the lint because the count is not conditional - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - count += 1; - for i in 0..2 { - let _ = 123; - } - println!("{}", count); - } - - // should not trigger the lint because the count is incremented multiple times - let text = "banana"; - let mut count = 0; - for ch in text.chars() { - count += 1; - for i in 0..2 { - count += 1; - } - println!("{}", count); - } - } -} - -mod issue_3308 { - #[warn(clippy::explicit_counter_loop)] - pub fn test() { - // should not trigger the lint because the count is incremented multiple times - let mut skips = 0; - let erasures = vec![]; - for i in 0..10 { - while erasures.contains(&(i + skips)) { - skips += 1; - } - println!("{}", skips); - } - - // should not trigger the lint because the count is incremented multiple times - let mut skips = 0; - for i in 0..10 { - let mut j = 0; - while j < 5 { - skips += 1; - j += 1; - } - println!("{}", skips); - } - - // should not trigger the lint because the count is incremented multiple times - let mut skips = 0; - for i in 0..10 { - for j in 0..5 { - skips += 1; - } - println!("{}", skips); - } - } -} diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 695209de53f..0318b6694e4 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -360,156 +360,130 @@ error: you are collect()ing an iterator and throwing away the result. Consider u | = note: `-D clippy::unused-collect` implied by `-D warnings` -error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:279:15 - | -279 | for _v in &vec { - | ^^^^ - | - = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` - -error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:285:15 - | -285 | for _v in &vec { - | ^^^^ - error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:395:19 + --> $DIR/for_loop.rs:385:19 | -395 | for (_, v) in &m { +385 | for (_, v) in &m { | ^^ | = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method | -395 | for v in m.values() { +385 | for v in m.values() { | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:400:19 + --> $DIR/for_loop.rs:390:19 | -400 | for (_, v) in &*m { +390 | for (_, v) in &*m { | ^^^ help: use the corresponding method | -400 | for v in (*m).values() { +390 | for v in (*m).values() { | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:408:19 + --> $DIR/for_loop.rs:398:19 | -408 | for (_, v) in &mut m { +398 | for (_, v) in &mut m { | ^^^^^^ help: use the corresponding method | -408 | for v in m.values_mut() { +398 | for v in m.values_mut() { | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:413:19 + --> $DIR/for_loop.rs:403:19 | -413 | for (_, v) in &mut *m { +403 | for (_, v) in &mut *m { | ^^^^^^^ help: use the corresponding method | -413 | for v in (*m).values_mut() { +403 | for v in (*m).values_mut() { | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:419:24 + --> $DIR/for_loop.rs:409:24 | -419 | for (k, _value) in rm { +409 | for (k, _value) in rm { | ^^ help: use the corresponding method | -419 | for k in rm.keys() { +409 | for k in rm.keys() { | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 + --> $DIR/for_loop.rs:462:14 | -472 | for i in 0..src.len() { +462 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:477:14 + --> $DIR/for_loop.rs:467:14 | -477 | for i in 0..src.len() { +467 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:482:14 + --> $DIR/for_loop.rs:472:14 | -482 | for i in 0..src.len() { +472 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:487:14 + --> $DIR/for_loop.rs:477:14 | -487 | for i in 11..src.len() { +477 | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:492:14 + --> $DIR/for_loop.rs:482:14 | -492 | for i in 0..dst.len() { +482 | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:505:14 + --> $DIR/for_loop.rs:495:14 | -505 | for i in 10..256 { +495 | for i in 10..256 { | ^^^^^^^ help: try replacing the loop by | -505 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -506 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { +495 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:517:14 + --> $DIR/for_loop.rs:507:14 | -517 | for i in 10..LOOP_OFFSET { +507 | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:530:14 + --> $DIR/for_loop.rs:520:14 | -530 | for i in 0..src_vec.len() { +520 | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:559:14 + --> $DIR/for_loop.rs:549:14 | -559 | for i in from..from + src.len() { +549 | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:563:14 + --> $DIR/for_loop.rs:553:14 | -563 | for i in from..from + 3 { +553 | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:570:14 + --> $DIR/for_loop.rs:560:14 | -570 | for i in 0..src.len() { +560 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:631:19 - | -631 | for ch in text.chars() { - | ^^^^^^^^^^^^ - -error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/for_loop.rs:642:19 - | -642 | for ch in text.chars() { - | ^^^^^^^^^^^^ - -error: aborting due to 63 previous errors +error: aborting due to 59 previous errors -- cgit 1.4.1-3-g733a5 From 53edeacdc01bf9d9d434cc88c52e2ed587cfd118 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 29 Oct 2018 09:52:49 +0100 Subject: dependencies: bump compiletest-rs from git to 0.3.16 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 81ca6c46817..2293913f38e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6" -compiletest_rs = { git = "https://github.com/laumann/compiletest-rs", rev = "12c980f47971b5ba6beb7cb2ffebf8b32f6766ea" } +compiletest_rs = "0.3.16" lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } -- cgit 1.4.1-3-g733a5 From be7656d9928b6e07fe19eed6938f6cf5316f2de0 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 29 Oct 2018 10:27:40 +0100 Subject: compiletest: clean rmeta data (from "cargo check") before running compiletest. Fixes #2896 Fixes #2139 --- tests/compile-test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c9d4f658935..64360af641b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -75,7 +75,10 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { } fn run_mode(mode: &str, dir: PathBuf) { - compiletest::run_tests(&config(mode, dir)); + let cfg = config(mode, dir); + // clean rmeta data, otherwise "cargo check; cargo test" fails (#2896) + cfg.clean_rmeta(); + compiletest::run_tests(&cfg); } fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec) -> Result { -- cgit 1.4.1-3-g733a5 From 267d5d3433c08c6867fc212ed091a7b178d1c141 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 12 Oct 2018 08:09:04 +0200 Subject: Fix lint_without_lint_pass --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/utils/internal_lints.rs | 16 ++++++++++------ tests/ui/lint_without_lint_pass.rs | 19 +++++++++++++++++++ tests/ui/lint_without_lint_pass.stderr | 21 +++++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint_without_lint_pass.rs create mode 100644 tests/ui/lint_without_lint_pass.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index eaff87e78f8..207dc40fa1d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -48,6 +48,7 @@ use toml; // Currently, categories "style", "correctness", "complexity" and "perf" are enabled by default, // as said in the README.md of this repository. If this changes, please update README.md. +#[macro_export] macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 3a0d056bbb5..e89c2d28953 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -9,12 +9,13 @@ use crate::utils::{ - match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, + match_def_path, match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; +use crate::rustc::hir::def::Def; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -161,7 +162,8 @@ impl LintPass for LintWithoutLintPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let hir::ItemKind::Static(ref ty, MutImmutable, body_id) = item.node { - if is_lint_ref_type(ty) { + + if is_lint_ref_type(cx, ty) { self.declared_lints.insert(item.name, item.span); } else if is_lint_array_type(ty) && item.name == "ARRAY" { if let VisibilityKind::Inherited = item.vis.node { @@ -203,19 +205,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { } } -fn is_lint_ref_type(ty: &Ty) -> bool { +fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool { if let TyKind::Rptr( _, MutTy { ty: ref inner, mutbl: MutImmutable, }, - ) = ty.node - { + ) = ty.node { if let TyKind::Path(ref path) = inner.node { - return match_qpath(path, &paths::LINT); + if let Def::Struct(def_id) = cx.tables.qpath_def(path, inner.hir_id) { + return match_def_path(cx.tcx, def_id, &paths::LINT); + } } } + false } diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs new file mode 100644 index 00000000000..41e7fea1abe --- /dev/null +++ b/tests/ui/lint_without_lint_pass.rs @@ -0,0 +1,19 @@ +#![deny(clippy::internal)] + +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc; + +#[macro_use] +extern crate clippy_lints; + +declare_clippy_lint! +{ + pub TEST_LINT, + correctness, + "" +} + +fn main() { +} diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr new file mode 100644 index 00000000000..48d511ce92e --- /dev/null +++ b/tests/ui/lint_without_lint_pass.stderr @@ -0,0 +1,21 @@ +error: the lint `TEST_LINT` is not added to any `LintPass` + --> $DIR/lint_without_lint_pass.rs:11:1 + | +11 | / declare_clippy_lint! +12 | | { +13 | | pub TEST_LINT, +14 | | correctness, +15 | | "" +16 | | } + | |_^ + | +note: lint level defined here + --> $DIR/lint_without_lint_pass.rs:1:9 + | +1 | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: #[deny(clippy::lint_without_lint_pass)] implied by #[deny(clippy::internal)] + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From a7fc6799df27a6ca0ad0eabcd71f9fb30d4e10a2 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 29 Oct 2018 20:37:47 +0100 Subject: Rewrite registered lint collection --- clippy_lints/src/utils/internal_lints.rs | 23 ++++++++++------------- clippy_lints/src/utils/paths.rs | 2 +- tests/ui/lint_without_lint_pass.rs | 17 +++++++++++++++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index e89c2d28953..879157ec8a4 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -9,7 +9,7 @@ use crate::utils::{ - match_def_path, match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, + match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; use crate::rustc::hir; @@ -161,16 +161,21 @@ impl LintPass for LintWithoutLintPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let hir::ItemKind::Static(ref ty, MutImmutable, body_id) = item.node { - + if let hir::ItemKind::Static(ref ty, MutImmutable, _) = item.node { if is_lint_ref_type(cx, ty) { self.declared_lints.insert(item.name, item.span); - } else if is_lint_array_type(ty) && item.name == "ARRAY" { - if let VisibilityKind::Inherited = item.vis.node { + } + } else if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { + if_chain! { + if let hir::TraitRef{path, ..} = trait_ref; + if let Def::Trait(def_id) = path.def; + if match_def_path(cx.tcx, def_id, &paths::LINT_PASS); + then { let mut collector = LintCollector { output: &mut self.registered_lints, cx, }; + let body_id = cx.tcx.hir.body_owned_by(impl_item_refs[0].id.node_id); collector.visit_expr(&cx.tcx.hir.body(body_id).value); } } @@ -223,14 +228,6 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool { false } -fn is_lint_array_type(ty: &Ty) -> bool { - if let TyKind::Path(ref path) = ty.node { - match_qpath(path, &paths::LINT_ARRAY) - } else { - false - } -} - struct LintCollector<'a, 'tcx: 'a> { output: &'a mut FxHashSet, cx: &'a LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 8941d303156..107a8eea15d 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -56,7 +56,7 @@ pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; -pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; +pub const LINT_PASS: [&str; 3] = ["rustc", "lint", "LintPass"]; pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index 41e7fea1abe..c7e11840a37 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -4,16 +4,29 @@ #[macro_use] extern crate rustc; +use rustc::lint; #[macro_use] extern crate clippy_lints; -declare_clippy_lint! -{ +declare_clippy_lint! { pub TEST_LINT, correctness, "" } +declare_clippy_lint! { + pub TEST_LINT_REGISTERED, + correctness, + "" +} + +pub struct Pass; +impl lint::LintPass for Pass { + fn get_lints(&self) -> lint::LintArray { + lint_array!(TEST_LINT_REGISTERED) + } +} + fn main() { } -- cgit 1.4.1-3-g733a5 From 1e43c3bb9f929695514e8d4854e9471962d2dde4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 29 Oct 2018 20:54:21 +0100 Subject: Register MISTYPED_LITERAL_SUFFIXES lint --- clippy_lints/src/literal_representation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index a123415cca9..145faf0b6b6 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -329,7 +329,8 @@ impl LintPass for LiteralDigitGrouping { lint_array!( UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, - LARGE_DIGIT_GROUPS + LARGE_DIGIT_GROUPS, + MISTYPED_LITERAL_SUFFIXES, ) } } -- cgit 1.4.1-3-g733a5 From 3d84ffb5eca1b1ca5f7fee0448c197c06247714a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 29 Oct 2018 20:55:52 +0100 Subject: Update .stderr file --- tests/ui/lint_without_lint_pass.stderr | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr index 48d511ce92e..65d1283a6e3 100644 --- a/tests/ui/lint_without_lint_pass.stderr +++ b/tests/ui/lint_without_lint_pass.stderr @@ -1,8 +1,7 @@ error: the lint `TEST_LINT` is not added to any `LintPass` - --> $DIR/lint_without_lint_pass.rs:11:1 + --> $DIR/lint_without_lint_pass.rs:12:1 | -11 | / declare_clippy_lint! -12 | | { +12 | / declare_clippy_lint! { 13 | | pub TEST_LINT, 14 | | correctness, 15 | | "" -- cgit 1.4.1-3-g733a5 From c0c1f1f7fa1cd2d9d65d3b2cd4b3943c62106328 Mon Sep 17 00:00:00 2001 From: Giorgio Gambino Date: Mon, 29 Oct 2018 22:23:45 +0100 Subject: Fix #3335 rev2: bool_comparison triggers 3 times on same code --- clippy_lints/src/needless_bool.rs | 101 +++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 3afccf9f984..e13f757adb9 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -133,56 +133,57 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if !in_macro(e.span) { - use self::Expression::*; - if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { - match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Bool(true), Other) => { - let hint = snippet(cx, right_side.span, "..").into_owned(); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint, - ); - }, - (Other, Bool(true)) => { - let hint = snippet(cx, left_side.span, "..").into_owned(); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint, - ); - }, - (Bool(false), Other) => { - let hint = Sugg::hir(cx, right_side, ".."); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - ); - }, - (Other, Bool(false)) => { - let hint = Sugg::hir(cx, left_side, ".."); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - ); - }, - _ => (), - } + if in_macro(e.span) { + return; + } + use self::Expression::*; + if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { + (Bool(true), Other) => { + let hint = snippet(cx, right_side.span, "..").into_owned(); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); + }, + (Other, Bool(true)) => { + let hint = snippet(cx, left_side.span, "..").into_owned(); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against true are unnecessary", + "try simplifying it as shown", + hint, + ); + }, + (Bool(false), Other) => { + let hint = Sugg::hir(cx, right_side, ".."); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); + }, + (Other, Bool(false)) => { + let hint = Sugg::hir(cx, left_side, ".."); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "equality checks against false can be replaced by a negation", + "try simplifying it as shown", + (!hint).to_string(), + ); + }, + _ => (), } } } -- cgit 1.4.1-3-g733a5 From a06296f8363788f75b7f295463a893bfb5743cae Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 30 Oct 2018 04:06:37 +0000 Subject: Rustup to rustc 1.31.0-nightly (fb2446ad5 2018-10-30) --- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 72a6bda26c3..9d11950dd73 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -392,7 +392,7 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { let file_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); let line_no = file_map_and_line.line; - let line_start = &file_map_and_line.fm.lines[line_no]; + let line_start = &file_map_and_line.sf.lines[line_no]; Span::new(*line_start, span.hi(), span.ctxt()) } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index eb67838f1d1..90f48f0f83c 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -548,7 +548,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error let hi = cx.sess().source_map().next_point(remove_span).hi(); let fmpos = cx.sess().source_map().lookup_byte_offset(hi); - if let Some(ref src) = fmpos.fm.src { + if let Some(ref src) = fmpos.sf.src { let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); if let Some(non_whitespace_offset) = non_whitespace_offset { -- cgit 1.4.1-3-g733a5 From b421f5ad4833e93025b9180bf8e296d1eb0a81d2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 30 Oct 2018 21:25:34 +0100 Subject: UI test cleanup: Extract for_loop_over_x tests --- tests/ui/for_loop.rs | 60 ---- tests/ui/for_loop.stderr | 424 ++++++++++++---------------- tests/ui/for_loop_over_option_result.rs | 68 +++++ tests/ui/for_loop_over_option_result.stderr | 72 +++++ 4 files changed, 318 insertions(+), 306 deletions(-) create mode 100644 tests/ui/for_loop_over_option_result.rs create mode 100644 tests/ui/for_loop_over_option_result.stderr diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index eefb4317276..2a70149f246 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - use std::collections::*; use std::rc::Rc; @@ -18,60 +14,6 @@ static STATIC: [usize; 4] = [0, 1, 8, 16]; const CONST: [usize; 4] = [0, 1, 8, 16]; #[warn(clippy::all)] -fn for_loop_over_option_and_result() { - let option = Some(1); - let result = option.ok_or("x not found"); - let v = vec![0, 1, 2]; - - // check FOR_LOOP_OVER_OPTION lint - for x in option { - println!("{}", x); - } - - // check FOR_LOOP_OVER_RESULT lint - for x in result { - println!("{}", x); - } - - for x in option.ok_or("x not found") { - println!("{}", x); - } - - // make sure LOOP_OVER_NEXT lint takes clippy::precedence when next() is the last call - // in the chain - for x in v.iter().next() { - println!("{}", x); - } - - // make sure we lint when next() is not the last call in the chain - for x in v.iter().next().and(Some(0)) { - println!("{}", x); - } - - for x in v.iter().next().ok_or("x not found") { - println!("{}", x); - } - - // check for false positives - - // for loop false positive - for x in v { - println!("{}", x); - } - - // while let false positive for Option - while let Some(x) = option { - println!("{}", x); - break; - } - - // while let false positive for Result - while let Ok(x) = result { - println!("{}", x); - break; - } -} - struct Unrelated(Vec); impl Unrelated { fn next(&self) -> std::slice::Iter { @@ -379,8 +321,6 @@ fn main() { } println!("index: {}", index); - for_loop_over_option_and_result(); - let m: HashMap = HashMap::new(); for (_, v) in &m { let _v = v; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 0318b6694e4..f70a6d3b32f 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,489 +1,421 @@ -error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:27:14 - | -27 | for x in option { - | ^^^^^^ - | - = note: `-D clippy::for-loop-over-option` implied by `-D warnings` - = help: consider replacing `for x in option` with `if let Some(x) = option` - -error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:32:14 - | -32 | for x in result { - | ^^^^^^ - | - = note: `-D clippy::for-loop-over-result` implied by `-D warnings` - = help: consider replacing `for x in result` with `if let Ok(x) = result` - -error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:36:14 - | -36 | for x in option.ok_or("x not found") { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` - -error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:42:14 - | -42 | for x in v.iter().next() { - | ^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-next-loop` implied by `-D warnings` - -error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:47:14 - | -47 | for x in v.iter().next().and(Some(0)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` - -error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:51:14 - | -51 | for x in v.iter().next().ok_or("x not found") { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` - -error: this loop never actually loops - --> $DIR/for_loop.rs:63:5 - | -63 | / while let Some(x) = option { -64 | | println!("{}", x); -65 | | break; -66 | | } - | |_____^ - | - = note: `-D clippy::never-loop` implied by `-D warnings` - -error: this loop never actually loops - --> $DIR/for_loop.rs:69:5 - | -69 | / while let Ok(x) = result { -70 | | println!("{}", x); -71 | | break; -72 | | } - | |_____^ - error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:96:14 + --> $DIR/for_loop.rs:38:14 | -96 | for i in 0..vec.len() { +38 | for i in 0..vec.len() { | ^^^^^^^^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -96 | for in &vec { +38 | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:105:14 - | -105 | for i in 0..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:47:14 + | +47 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -105 | for in &vec { - | ^^^^^^ ^^^^ + | +47 | for in &vec { + | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:110:14 - | -110 | for j in 0..4 { - | ^^^^ + --> $DIR/for_loop.rs:52:14 + | +52 | for j in 0..4 { + | ^^^^ help: consider using an iterator - | -110 | for in &STATIC { - | ^^^^^^ ^^^^^^^ + | +52 | for in &STATIC { + | ^^^^^^ ^^^^^^^ error: the loop variable `j` is only used to index `CONST`. - --> $DIR/for_loop.rs:114:14 - | -114 | for j in 0..4 { - | ^^^^ + --> $DIR/for_loop.rs:56:14 + | +56 | for j in 0..4 { + | ^^^^ help: consider using an iterator - | -114 | for in &CONST { - | ^^^^^^ ^^^^^^ + | +56 | for in &CONST { + | ^^^^^^ ^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:118:14 - | -118 | for i in 0..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:60:14 + | +60 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -118 | for (i, ) in vec.iter().enumerate() { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ + | +60 | for (i, ) in vec.iter().enumerate() { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:126:14 - | -126 | for i in 0..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:68:14 + | +68 | for i in 0..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -126 | for in vec2.iter().take(vec.len()) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +68 | for in vec2.iter().take(vec.len()) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:130:14 - | -130 | for i in 5..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:72:14 + | +72 | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -130 | for in vec.iter().skip(5) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^ + | +72 | for in vec.iter().skip(5) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:134:14 - | -134 | for i in 0..MAX_LEN { - | ^^^^^^^^^^ + --> $DIR/for_loop.rs:76:14 + | +76 | for i in 0..MAX_LEN { + | ^^^^^^^^^^ help: consider using an iterator - | -134 | for in vec.iter().take(MAX_LEN) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ + | +76 | for in vec.iter().take(MAX_LEN) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:138:14 - | -138 | for i in 0..=MAX_LEN { - | ^^^^^^^^^^^ + --> $DIR/for_loop.rs:80:14 + | +80 | for i in 0..=MAX_LEN { + | ^^^^^^^^^^^ help: consider using an iterator - | -138 | for in vec.iter().take(MAX_LEN + 1) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +80 | for in vec.iter().take(MAX_LEN + 1) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:142:14 - | -142 | for i in 5..10 { - | ^^^^^ + --> $DIR/for_loop.rs:84:14 + | +84 | for i in 5..10 { + | ^^^^^ help: consider using an iterator - | -142 | for in vec.iter().take(10).skip(5) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +84 | for in vec.iter().take(10).skip(5) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:146:14 - | -146 | for i in 5..=10 { - | ^^^^^^ + --> $DIR/for_loop.rs:88:14 + | +88 | for i in 5..=10 { + | ^^^^^^ help: consider using an iterator - | -146 | for in vec.iter().take(10 + 1).skip(5) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +88 | for in vec.iter().take(10 + 1).skip(5) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:150:14 - | -150 | for i in 5..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:92:14 + | +92 | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -150 | for (i, ) in vec.iter().enumerate().skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +92 | for (i, ) in vec.iter().enumerate().skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:154:14 - | -154 | for i in 5..10 { - | ^^^^^ + --> $DIR/for_loop.rs:96:14 + | +96 | for i in 5..10 { + | ^^^^^ help: consider using an iterator - | -154 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +96 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:158:14 + --> $DIR/for_loop.rs:100:14 | -158 | for i in 10..0 { +100 | for i in 10..0 { | ^^^^^ | = note: `-D clippy::reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | -158 | for i in (0..10).rev() { +100 | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:162:14 + --> $DIR/for_loop.rs:104:14 | -162 | for i in 10..=0 { +104 | for i in 10..=0 { | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -162 | for i in (0...10).rev() { +104 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:166:14 + --> $DIR/for_loop.rs:108:14 | -166 | for i in MAX_LEN..0 { +108 | for i in MAX_LEN..0 { | ^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -166 | for i in (0..MAX_LEN).rev() { +108 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:170:14 + --> $DIR/for_loop.rs:112:14 | -170 | for i in 5..5 { +112 | for i in 5..5 { | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:195:14 + --> $DIR/for_loop.rs:137:14 | -195 | for i in 10..5 + 4 { +137 | for i in 10..5 + 4 { | ^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -195 | for i in (5 + 4..10).rev() { +137 | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:199:14 + --> $DIR/for_loop.rs:141:14 | -199 | for i in (5 + 2)..(3 - 1) { +141 | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -199 | for i in ((3 - 1)..(5 + 2)).rev() { +141 | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:203:14 + --> $DIR/for_loop.rs:145:14 | -203 | for i in (5 + 2)..(8 - 1) { +145 | for i in (5 + 2)..(8 - 1) { | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:225:15 + --> $DIR/for_loop.rs:167:15 | -225 | for _v in vec.iter() {} +167 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:227:15 + --> $DIR/for_loop.rs:169:15 | -227 | for _v in vec.iter_mut() {} +169 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:230:15 + --> $DIR/for_loop.rs:172:15 | -230 | for _v in out_vec.into_iter() {} +172 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:233:15 + --> $DIR/for_loop.rs:175:15 | -233 | for _v in array.into_iter() {} +175 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:238:15 + --> $DIR/for_loop.rs:180:15 | -238 | for _v in [1, 2, 3].iter() {} +180 | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:242:15 + --> $DIR/for_loop.rs:184:15 | -242 | for _v in [0; 32].iter() {} +184 | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:247:15 + --> $DIR/for_loop.rs:189:15 | -247 | for _v in ll.iter() {} +189 | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:250:15 + --> $DIR/for_loop.rs:192:15 | -250 | for _v in vd.iter() {} +192 | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:253:15 + --> $DIR/for_loop.rs:195:15 | -253 | for _v in bh.iter() {} +195 | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:256:15 + --> $DIR/for_loop.rs:198:15 | -256 | for _v in hm.iter() {} +198 | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:259:15 + --> $DIR/for_loop.rs:201:15 | -259 | for _v in bt.iter() {} +201 | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:262:15 + --> $DIR/for_loop.rs:204:15 | -262 | for _v in hs.iter() {} +204 | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:265:15 + --> $DIR/for_loop.rs:207:15 | -265 | for _v in bs.iter() {} +207 | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:267:15 + --> $DIR/for_loop.rs:209:15 | -267 | for _v in vec.iter().next() {} +209 | for _v in vec.iter().next() {} | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:274:5 + --> $DIR/for_loop.rs:216:5 | -274 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); +216 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:385:19 + --> $DIR/for_loop.rs:325:19 | -385 | for (_, v) in &m { +325 | for (_, v) in &m { | ^^ | = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method | -385 | for v in m.values() { +325 | for v in m.values() { | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:390:19 + --> $DIR/for_loop.rs:330:19 | -390 | for (_, v) in &*m { +330 | for (_, v) in &*m { | ^^^ help: use the corresponding method | -390 | for v in (*m).values() { +330 | for v in (*m).values() { | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:398:19 + --> $DIR/for_loop.rs:338:19 | -398 | for (_, v) in &mut m { +338 | for (_, v) in &mut m { | ^^^^^^ help: use the corresponding method | -398 | for v in m.values_mut() { +338 | for v in m.values_mut() { | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:403:19 + --> $DIR/for_loop.rs:343:19 | -403 | for (_, v) in &mut *m { +343 | for (_, v) in &mut *m { | ^^^^^^^ help: use the corresponding method | -403 | for v in (*m).values_mut() { +343 | for v in (*m).values_mut() { | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:409:24 + --> $DIR/for_loop.rs:349:24 | -409 | for (k, _value) in rm { +349 | for (k, _value) in rm { | ^^ help: use the corresponding method | -409 | for k in rm.keys() { +349 | for k in rm.keys() { | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:462:14 + --> $DIR/for_loop.rs:402:14 | -462 | for i in 0..src.len() { +402 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:467:14 + --> $DIR/for_loop.rs:407:14 | -467 | for i in 0..src.len() { +407 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 + --> $DIR/for_loop.rs:412:14 | -472 | for i in 0..src.len() { +412 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:477:14 + --> $DIR/for_loop.rs:417:14 | -477 | for i in 11..src.len() { +417 | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:482:14 + --> $DIR/for_loop.rs:422:14 | -482 | for i in 0..dst.len() { +422 | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:495:14 + --> $DIR/for_loop.rs:435:14 | -495 | for i in 10..256 { +435 | for i in 10..256 { | ^^^^^^^ help: try replacing the loop by | -495 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { +435 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +436 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:507:14 + --> $DIR/for_loop.rs:447:14 | -507 | for i in 10..LOOP_OFFSET { +447 | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:520:14 + --> $DIR/for_loop.rs:460:14 | -520 | for i in 0..src_vec.len() { +460 | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:549:14 + --> $DIR/for_loop.rs:489:14 | -549 | for i in from..from + src.len() { +489 | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:553:14 + --> $DIR/for_loop.rs:493:14 | -553 | for i in from..from + 3 { +493 | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:560:14 + --> $DIR/for_loop.rs:500:14 | -560 | for i in 0..src.len() { +500 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 59 previous errors +error: aborting due to 51 previous errors diff --git a/tests/ui/for_loop_over_option_result.rs b/tests/ui/for_loop_over_option_result.rs new file mode 100644 index 00000000000..37fd4e6d038 --- /dev/null +++ b/tests/ui/for_loop_over_option_result.rs @@ -0,0 +1,68 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::for_loop_over_option, clippy::for_loop_over_result)] + +/// Tests for_loop_over_result and for_loop_over_option + +fn for_loop_over_option_and_result() { + let option = Some(1); + let result = option.ok_or("x not found"); + let v = vec![0, 1, 2]; + + // check FOR_LOOP_OVER_OPTION lint + for x in option { + println!("{}", x); + } + + // check FOR_LOOP_OVER_RESULT lint + for x in result { + println!("{}", x); + } + + for x in option.ok_or("x not found") { + println!("{}", x); + } + + // make sure LOOP_OVER_NEXT lint takes clippy::precedence when next() is the last call + // in the chain + for x in v.iter().next() { + println!("{}", x); + } + + // make sure we lint when next() is not the last call in the chain + for x in v.iter().next().and(Some(0)) { + println!("{}", x); + } + + for x in v.iter().next().ok_or("x not found") { + println!("{}", x); + } + + // check for false positives + + // for loop false positive + for x in v { + println!("{}", x); + } + + // while let false positive for Option + while let Some(x) = option { + println!("{}", x); + break; + } + + // while let false positive for Result + while let Ok(x) = result { + println!("{}", x); + break; + } +} + +fn main() {} diff --git a/tests/ui/for_loop_over_option_result.stderr b/tests/ui/for_loop_over_option_result.stderr new file mode 100644 index 00000000000..13ad5fff846 --- /dev/null +++ b/tests/ui/for_loop_over_option_result.stderr @@ -0,0 +1,72 @@ +error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. + --> $DIR/for_loop_over_option_result.rs:20:14 + | +20 | for x in option { + | ^^^^^^ + | + = note: `-D clippy::for-loop-over-option` implied by `-D warnings` + = help: consider replacing `for x in option` with `if let Some(x) = option` + +error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. + --> $DIR/for_loop_over_option_result.rs:25:14 + | +25 | for x in result { + | ^^^^^^ + | + = note: `-D clippy::for-loop-over-result` implied by `-D warnings` + = help: consider replacing `for x in result` with `if let Ok(x) = result` + +error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. + --> $DIR/for_loop_over_option_result.rs:29:14 + | +29 | for x in option.ok_or("x not found") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` + +error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want + --> $DIR/for_loop_over_option_result.rs:35:14 + | +35 | for x in v.iter().next() { + | ^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::iter_next_loop)] on by default + +error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. + --> $DIR/for_loop_over_option_result.rs:40:14 + | +40 | for x in v.iter().next().and(Some(0)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` + +error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. + --> $DIR/for_loop_over_option_result.rs:44:14 + | +44 | for x in v.iter().next().ok_or("x not found") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` + +error: this loop never actually loops + --> $DIR/for_loop_over_option_result.rs:56:5 + | +56 | / while let Some(x) = option { +57 | | println!("{}", x); +58 | | break; +59 | | } + | |_____^ + | + = note: #[deny(clippy::never_loop)] on by default + +error: this loop never actually loops + --> $DIR/for_loop_over_option_result.rs:62:5 + | +62 | / while let Ok(x) = result { +63 | | println!("{}", x); +64 | | break; +65 | | } + | |_____^ + +error: aborting due to 8 previous errors + -- cgit 1.4.1-3-g733a5 From 650eb099810095e7b2dc31ba4fda08f3ad7aaecc Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 31 Oct 2018 01:42:17 +0100 Subject: docs: use_self: hightlight the "should be" code sample as rust code as well. --- clippy_lints/src/use_self.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index a8b7e820681..b997d76d0e7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -36,7 +36,7 @@ use crate::syntax_pos::symbol::keywords::SelfType; /// } /// ``` /// could be -/// ``` +/// ```rust /// struct Foo {} /// impl Foo { /// fn new() -> Self { -- cgit 1.4.1-3-g733a5 From 627ca6b57857de8967cb857e04283d92a28dd9ff Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 30 Oct 2018 15:41:59 +0100 Subject: Revert "Disable rust master toolchain build temporarily" This reverts commit 0d899562cd805bd4335d6ee8d88e2bf1f743f000. --- .travis.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index d3f8c116607..09972a12f8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,14 +75,13 @@ matrix: - os: windows script: - # uncomment once https://github.com/rust-lang/rust/issues/55376 is fixed - # - | - # rm rust-toolchain - # cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" - # RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') - # travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH - # rustup default master - # export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + - | + rm rust-toolchain + cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') + travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH + rustup default master + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - | if [ -z ${INTEGRATION} ]; then ./ci/base-tests.sh && sleep 5 -- cgit 1.4.1-3-g733a5 From 9b0f767b43a8f67bc22355b72799358ee79063c0 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 30 Oct 2018 15:42:15 +0100 Subject: Revert "appveyor: use rustc nightly instead of master" This reverts commit 3f0161918871403b4e0547191a93f395b8bf5b35. --- appveyor.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 18f25e916f3..fb0b326c713 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,12 +20,11 @@ install: - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}' >rustc-hash.txt - set /p RUSTC_HASH= Date: Tue, 30 Oct 2018 15:58:35 +0100 Subject: Revert "travis: work around temporary test failure due to rustc crashing on hyper." This reverts commit 326270ad1221b54028f9d029881fa0b1fb742db9. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09972a12f8d..75b45c9db40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,8 +63,7 @@ matrix: - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom -# uncomment once https://github.com/rust-lang/rust/issues/55376 is fixed -# - env: INTEGRATION=hyperium/hyper + - env: INTEGRATION=hyperium/hyper allow_failures: - os: windows env: BASE_TEST=true -- cgit 1.4.1-3-g733a5 From 4e054ad32007142b7e9a501a5f5c29013ea5d1c8 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 31 Oct 2018 06:26:29 +0200 Subject: Replace big if/else expression with match --- clippy_lints/src/methods/mod.rs | 92 ++++++++++++++++------------------------- clippy_lints/src/utils/mod.rs | 25 ++++++++++- 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 8d0cd32e23b..dacdefd2265 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -16,12 +16,13 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast; use crate::syntax::source_map::{BytePos, Span}; +use crate::syntax::symbol::LocalInternedString; use crate::utils::paths; use crate::utils::sugg; use crate::utils::{ get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, - match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint, + match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; use if_chain::if_chain; @@ -783,63 +784,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } + let (method_names, arg_lists) = method_calls(expr, 2); + let method_names: Vec = method_names.iter().map(|s| s.as_str()).collect(); + let mut method_names = method_names.iter().map(|s| s.as_ref()).chain(iter::repeat("")); + + match [method_names.next().unwrap(), method_names.next().unwrap()] { + ["unwrap", "get"] => lint_get_unwrap(cx, expr, arg_lists[1], false), + ["unwrap", "get_mut"] => lint_get_unwrap(cx, expr, arg_lists[1], true), + ["unwrap", _] => lint_unwrap(cx, expr, arg_lists[0]), + ["expect", "ok"] => lint_ok_expect(cx, expr, arg_lists[1]), + ["unwrap_or", "map"] => lint_map_unwrap_or(cx, expr, arg_lists[1], arg_lists[0]), + ["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]), + ["map_or", _] => lint_map_or_none(cx, expr, arg_lists[0]), + ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), + ["map", "filter"] => lint_filter_map(cx, expr, arg_lists[1], arg_lists[0]), + ["map", "filter_map"] => lint_filter_map_map(cx, expr, arg_lists[1], arg_lists[0]), + ["flat_map", "filter"] => lint_filter_flat_map(cx, expr, arg_lists[1], arg_lists[0]), + ["flat_map", "filter_map"] => lint_filter_map_flat_map(cx, expr, arg_lists[1], arg_lists[0]), + ["flatten", "map"] => lint_map_flatten(cx, expr, arg_lists[1]), + ["is_some", "find"] => lint_search_is_some(cx, expr, "find", arg_lists[1], arg_lists[0]), + ["is_some", "position"] => lint_search_is_some(cx, expr, "position", arg_lists[1], arg_lists[0]), + ["is_some", "rposition"] => lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0]), + ["extend", _] => lint_extend(cx, expr, arg_lists[0]), + ["as_ptr", "unwrap"] => lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]), + ["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false), + ["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true), + ["next", "skip"] => lint_iter_skip_next(cx, expr), + ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), + ["as_ref", _] => lint_asref(cx, expr, "as_ref", arg_lists[0]), + ["as_mut", _] => lint_asref(cx, expr, "as_mut", arg_lists[0]), + ["fold", _] => lint_unnecessary_fold(cx, expr, arg_lists[0]), + ["filter_map", _] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), + _ => {} + } + match expr.node { hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { - // Chain calls - // GET_UNWRAP needs to be checked before general `UNWRAP` lints - if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) { - lint_get_unwrap(cx, expr, arglists[0], false); - } else if let Some(arglists) = method_chain_args(expr, &["get_mut", "unwrap"]) { - lint_get_unwrap(cx, expr, arglists[0], true); - } else if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - lint_unwrap(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["ok", "expect"]) { - lint_ok_expect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or"]) { - lint_map_unwrap_or(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "unwrap_or_else"]) { - lint_map_unwrap_or_else(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map_or"]) { - lint_map_or_none(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "next"]) { - lint_filter_next(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "map"]) { - lint_filter_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "map"]) { - lint_filter_map_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter", "flat_map"]) { - lint_filter_flat_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map", "flat_map"]) { - lint_filter_map_flat_map(cx, expr, arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["map", "flatten"]) { - lint_map_flatten(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["find", "is_some"]) { - lint_search_is_some(cx, expr, "find", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["position", "is_some"]) { - lint_search_is_some(cx, expr, "position", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["rposition", "is_some"]) { - lint_search_is_some(cx, expr, "rposition", arglists[0], arglists[1]); - } else if let Some(arglists) = method_chain_args(expr, &["extend"]) { - lint_extend(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { - lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); - } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { - lint_iter_nth(cx, expr, arglists[0], false); - } else if let Some(arglists) = method_chain_args(expr, &["iter_mut", "nth"]) { - lint_iter_nth(cx, expr, arglists[0], true); - } else if method_chain_args(expr, &["skip", "next"]).is_some() { - lint_iter_skip_next(cx, expr); - } else if let Some(arglists) = method_chain_args(expr, &["cloned", "collect"]) { - lint_iter_cloned_collect(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["as_ref"]) { - lint_asref(cx, expr, "as_ref", arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["as_mut"]) { - lint_asref(cx, expr, "as_mut", arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["fold"]) { - lint_unnecessary_fold(cx, expr, arglists[0]); - } else if let Some(arglists) = method_chain_args(expr, &["filter_map"]) { - unnecessary_filter_map::lint(cx, expr, arglists[0]); - } lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9d11950dd73..1cd20b68421 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -31,7 +31,7 @@ use crate::syntax::ast::{self, LitKind}; use crate::syntax::attr; use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax::symbol::keywords; +use crate::syntax::symbol::{keywords, Symbol}; pub mod camel_case; @@ -274,6 +274,29 @@ pub fn resolve_node(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> def:: cx.tables.qpath_def(qpath, id) } +/// Return the method names and argument list of nested method call expressions that make up +/// `expr`. +pub fn method_calls<'a>(expr: &'a Expr, max_depth: usize) -> (Vec, Vec<&'a [Expr]>) { + let mut method_names = Vec::with_capacity(max_depth); + let mut arg_lists = Vec::with_capacity(max_depth); + + let mut current = expr; + for _ in 0..max_depth { + if let ExprKind::MethodCall(path, _, args) = ¤t.node { + if args.iter().any(|e| in_macro(e.span)) { + break; + } + method_names.push(path.ident.name); + arg_lists.push(&**args); + current = &args[0]; + } else { + break; + } + } + + (method_names, arg_lists) +} + /// Match an `Expr` against a chain of methods, and return the matched `Expr`s. /// /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -- cgit 1.4.1-3-g733a5 From 64bd658516d6a097c04295a3f90537d757c258bd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 31 Oct 2018 08:03:50 +0100 Subject: RIIR update lints: Generate deprecated lints The update script now also generates the 'register_removed' section in `clippy_lints/src/lib.rs`. Also, instead of using `let mut store ...`, I added a new identifier line so that the replacement will continue to work in case `let mut store ...` ever changes. --- clippy_dev/src/lib.rs | 33 +++++++++++++++++++++++++++++++++ clippy_dev/src/main.rs | 8 ++++++++ clippy_lints/src/lib.rs | 1 + util/update_lints.py | 2 +- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 77351233381..d2191d426ff 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -72,6 +72,7 @@ impl Lint { } } +/// Generates the list of lint links at the bottom of the README pub fn gen_changelog_lint_list(lints: Vec) -> Vec { let mut lint_list_sorted: Vec = lints; lint_list_sorted.sort_by_key(|l| l.name.clone()); @@ -84,6 +85,23 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { .collect() } +/// Generates the 'register_removed' code in `./clippy_lints/src/lib.rs`. +pub fn gen_deprecated(lints: Vec) -> Vec { + lints.iter() + .filter(|l| l.deprecation.is_some()) + .map(|l| { + format!( + r#" store.register_removed( + "{}", + "{}", + );"#, + l.name, + l.deprecation.clone().unwrap() + ) + }) + .collect() +} + /// Gathers all files in `src/clippy_lints` and gathers all lints inside pub fn gather_all() -> impl Iterator { lint_files().flat_map(|f| gather_from_file(&f)) @@ -321,3 +339,18 @@ fn test_gen_changelog_lint_list() { ]; assert_eq!(expected, gen_changelog_lint_list(lints)); } + +#[test] +fn test_gen_deprecated() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", Some("has been superseeded by should_assert_eq2"), "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name") + ]; + let expected: Vec = vec![ + r#" store.register_removed( + "should_assert_eq", + "has been superseeded by should_assert_eq2", + );"#.to_string() + ]; + assert_eq!(expected, gen_deprecated(lints)); +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 8769ee6b810..cf321dbbc02 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -82,4 +82,12 @@ fn update_lints() { false, || { gen_changelog_lint_list(lint_list.clone()) } ); + + replace_region_in_file( + "../clippy_lints/src/lib.rs", + "begin deprecated lints", + "end deprecated lints", + false, + || { gen_deprecated(lint_list.clone()) } + ); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index eaff87e78f8..f7b103e8d72 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -270,6 +270,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { #[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { let mut store = reg.sess.lint_store.borrow_mut(); + // begin deprecated lints, do not remove this comment, it’s used in `update_lints` store.register_removed( "should_assert_eq", "`assert!()` will be more flexible with RFC 2011", diff --git a/util/update_lints.py b/util/update_lints.py index 2e1bd98050d..221069d353c 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -240,7 +240,7 @@ def main(print_only=False, check=False): # same for "deprecated" lint collection changed |= replace_region( - 'clippy_lints/src/lib.rs', r'let mut store', r'end deprecated lints', + 'clippy_lints/src/lib.rs', r'begin deprecated lints', r'end deprecated lints', lambda: gen_deprecated(deprecated_lints), replace_start=False, write_back=not check) -- cgit 1.4.1-3-g733a5 From 59f4aba5b964e3d1da076b12e0e2c5575374f481 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 31 Oct 2018 11:18:20 +0100 Subject: ci: when installing rust-toolchain-installer-master, install it in debug mode to save some time in ci. the compiletime optimizations probably take longer than the speedup we get when executing the optimized binary vs debug build. --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 75b45c9db40..50967e4b906 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,7 +76,7 @@ matrix: script: - | rm rust-toolchain - cargo install rustup-toolchain-install-master || echo "rustup-toolchain-install-master already installed" + cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH rustup default master diff --git a/appveyor.yml b/appveyor.yml index fb0b326c713..c852cd8232e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,7 +21,7 @@ install: - git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}' >rustc-hash.txt - set /p RUSTC_HASH= Date: Wed, 31 Oct 2018 21:54:30 +0100 Subject: Fix dogfood and pedantic lints --- clippy_dev/src/lib.rs | 38 ++++++++++++++++++++------------------ clippy_dev/src/main.rs | 2 +- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index d2191d426ff..656a271aec9 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -78,26 +78,28 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { lint_list_sorted.sort_by_key(|l| l.name.clone()); lint_list_sorted .iter() - .filter(|l| !l.is_internal()) - .map(|l| { - format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name) - }) - .collect() + .filter_map(|l| { + if l.is_internal() { + None + } else { + Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name)) + } + }).collect() } -/// Generates the 'register_removed' code in `./clippy_lints/src/lib.rs`. -pub fn gen_deprecated(lints: Vec) -> Vec { +/// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. +pub fn gen_deprecated(lints: &[Lint]) -> Vec { lints.iter() - .filter(|l| l.deprecation.is_some()) - .map(|l| { - format!( - r#" store.register_removed( - "{}", - "{}", - );"#, - l.name, - l.deprecation.clone().unwrap() - ) + .filter_map(|l| { + l.clone().deprecation.and_then(|depr_text| { + Some( + format!( + " store.register_removed(\n \"{}\",\n \"{}\",\n );", + l.name, + depr_text + ) + ) + }) }) .collect() } @@ -352,5 +354,5 @@ fn test_gen_deprecated() { "has been superseeded by should_assert_eq2", );"#.to_string() ]; - assert_eq!(expected, gen_deprecated(lints)); + assert_eq!(expected, gen_deprecated(&lints)); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index cf321dbbc02..887a4ab9328 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -88,6 +88,6 @@ fn update_lints() { "begin deprecated lints", "end deprecated lints", false, - || { gen_deprecated(lint_list.clone()) } + || { gen_deprecated(&lint_list) } ); } -- cgit 1.4.1-3-g733a5 From 6b895b8267e72575d73055d5a64b19b7ba801a1a Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Wed, 31 Oct 2018 16:39:12 -0600 Subject: Revert "small fix" This reverts commit b1abc81a60e05bb2cf46850b977b7fa4ba34a6de. --- clippy_lints/src/literal_representation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 98fabcdcf51..357f344919f 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -229,8 +229,8 @@ impl<'a> DigitInfo<'a> { None => String::new(), }; format!("{}.{}{}", int_part_hint, frac_part_hint, suffix_hint) - } else if self.float && (self.digits.contains('E') || self.digits.contains('e')) { - let which_e = if self.digits.contains('E') { 'E' } else { 'e' }; + } else if self.float && (self.digits.contains("E") || self.digits.contains("E")) { + let which_e = if self.digits.contains("E") { "E" } else { "e" }; let parts: Vec<&str> = self.digits.split(which_e).collect(); let filtered_digits_vec_0 = parts[0].chars().filter(|&c| c != '_').rev().collect::>(); let filtered_digits_vec_1 = parts[1].chars().filter(|&c| c != '_').rev().collect::>(); -- cgit 1.4.1-3-g733a5 From f4b919cad7cf7697138b6ae94ecffd085bf47aed Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Wed, 31 Oct 2018 16:48:24 -0600 Subject: add lint to lintarray macro --- clippy_lints/src/literal_representation.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 357f344919f..d9be99042c3 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -342,7 +342,12 @@ pub struct LiteralDigitGrouping; impl LintPass for LiteralDigitGrouping { fn get_lints(&self) -> LintArray { - lint_array!(UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, LARGE_DIGIT_GROUPS) + lint_array!( + UNREADABLE_LITERAL, + INCONSISTENT_DIGIT_GROUPING, + LARGE_DIGIT_GROUPS, + MISTYPED_LITERAL_SUFFIXES, + ) } } -- cgit 1.4.1-3-g733a5 From 98ce3348d9c066bf08892bd320620cab10266ee9 Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Wed, 31 Oct 2018 18:09:56 -0600 Subject: change single char str to char --- clippy_lints/src/literal_representation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index d9be99042c3..9c319d64b32 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -229,8 +229,8 @@ impl<'a> DigitInfo<'a> { None => String::new(), }; format!("{}.{}{}", int_part_hint, frac_part_hint, suffix_hint) - } else if self.float && (self.digits.contains("E") || self.digits.contains("E")) { - let which_e = if self.digits.contains("E") { "E" } else { "e" }; + } else if self.float && (self.digits.contains('E') || self.digits.contains('E')) { + let which_e = if self.digits.contains('E') { 'E' } else { 'e' }; let parts: Vec<&str> = self.digits.split(which_e).collect(); let filtered_digits_vec_0 = parts[0].chars().filter(|&c| c != '_').rev().collect::>(); let filtered_digits_vec_1 = parts[1].chars().filter(|&c| c != '_').rev().collect::>(); -- cgit 1.4.1-3-g733a5 From 0a41dfd94630057713e0e55b28accb9455ae2183 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 1 Nov 2018 07:06:47 +0200 Subject: Use slice patterns instead of padding --- clippy_lints/src/methods/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index dacdefd2265..abf97def50f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -786,16 +786,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let (method_names, arg_lists) = method_calls(expr, 2); let method_names: Vec = method_names.iter().map(|s| s.as_str()).collect(); - let mut method_names = method_names.iter().map(|s| s.as_ref()).chain(iter::repeat("")); + let method_names: Vec<&str> = method_names.iter().map(|s| s.as_ref()).collect(); - match [method_names.next().unwrap(), method_names.next().unwrap()] { + match method_names.as_slice() { ["unwrap", "get"] => lint_get_unwrap(cx, expr, arg_lists[1], false), ["unwrap", "get_mut"] => lint_get_unwrap(cx, expr, arg_lists[1], true), - ["unwrap", _] => lint_unwrap(cx, expr, arg_lists[0]), + ["unwrap", ..] => lint_unwrap(cx, expr, arg_lists[0]), ["expect", "ok"] => lint_ok_expect(cx, expr, arg_lists[1]), ["unwrap_or", "map"] => lint_map_unwrap_or(cx, expr, arg_lists[1], arg_lists[0]), ["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]), - ["map_or", _] => lint_map_or_none(cx, expr, arg_lists[0]), + ["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]), ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), ["map", "filter"] => lint_filter_map(cx, expr, arg_lists[1], arg_lists[0]), ["map", "filter_map"] => lint_filter_map_map(cx, expr, arg_lists[1], arg_lists[0]), @@ -805,16 +805,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ["is_some", "find"] => lint_search_is_some(cx, expr, "find", arg_lists[1], arg_lists[0]), ["is_some", "position"] => lint_search_is_some(cx, expr, "position", arg_lists[1], arg_lists[0]), ["is_some", "rposition"] => lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0]), - ["extend", _] => lint_extend(cx, expr, arg_lists[0]), + ["extend", ..] => lint_extend(cx, expr, arg_lists[0]), ["as_ptr", "unwrap"] => lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]), ["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false), ["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true), ["next", "skip"] => lint_iter_skip_next(cx, expr), ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), - ["as_ref", _] => lint_asref(cx, expr, "as_ref", arg_lists[0]), - ["as_mut", _] => lint_asref(cx, expr, "as_mut", arg_lists[0]), - ["fold", _] => lint_unnecessary_fold(cx, expr, arg_lists[0]), - ["filter_map", _] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), + ["as_ref", ..] => lint_asref(cx, expr, "as_ref", arg_lists[0]), + ["as_mut", ..] => lint_asref(cx, expr, "as_mut", arg_lists[0]), + ["fold", ..] => lint_unnecessary_fold(cx, expr, arg_lists[0]), + ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), _ => {} } -- cgit 1.4.1-3-g733a5 From 02340cc89101b33c1d219aa65a3eb09096bcaffe Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Thu, 1 Nov 2018 12:35:01 -0600 Subject: fix comment spacing --- clippy_lints/src/literal_representation.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9c319d64b32..7b0c9523ef0 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -557,7 +557,8 @@ impl LiteralRepresentation { // Lint for Literals with a hex-representation of 2 or 3 digits let f = &digits[0..1]; // first digit let s = &digits[1..]; // suffix - // Powers of 2 + + // Powers of 2 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && s.chars().all(|c| c == '0')) // Powers of 2 minus 1 || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && s.chars().all(|c| c == 'F')) @@ -569,7 +570,8 @@ impl LiteralRepresentation { let f = &digits[0..1]; // first digit let m = &digits[1..digits.len() - 1]; // middle digits, except last let s = &digits[1..]; // suffix - // Powers of 2 with a margin of +15/-16 + + // Powers of 2 with a margin of +15/-16 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && m.chars().all(|c| c == '0')) || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && m.chars().all(|c| c == 'F')) // Lint for representations with only 0s and Fs, while allowing 7 as the first -- cgit 1.4.1-3-g733a5 From beb44ef6cac013f721a319bea05d50021c0d2b0d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Nov 2018 20:35:23 +0100 Subject: Fix clippy build failure on latest master --- clippy_lints/src/booleans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f12859d90c3..2d587b79357 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { improvements.push(suggestion); } } - let nonminimal_bool_lint = |suggestions| { + let nonminimal_bool_lint = |suggestions: Vec<_>| { span_lint_and_then( self.cx, NONMINIMAL_BOOL, @@ -434,7 +434,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { db.span_suggestions_with_applicability( e.span, "try", - suggestions, + suggestions.into_iter(), // nonminimal_bool can produce minimal but // not human readable expressions (#3141) Applicability::Unspecified, -- cgit 1.4.1-3-g733a5 From f33dd175f3b654b9962669948f8f98fab877d046 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Nov 2018 21:31:05 +0100 Subject: Add missing code of conduct file We are already using the Rust code of conduct, this just ticks off an additional checkbox [here][community]. This version is taken from [rustfmt][rustfmt]. [community]: https://github.com/rust-lang-nursery/rust-clippy/community [rustfmt]: https://github.com/rust-lang-nursery/rustfmt --- CODE_OF_CONDUCT.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..d70b2b52aca --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# The Rust Code of Conduct + +A version of this document [can be found online](https://www.rust-lang.org/conduct.html). + +## Conduct + +**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) + +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. +* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. +* Please be kind and courteous. There's no need to be mean or rude. +* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. +* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. +* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. + +## Moderation + + +These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team]. + +1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. +3. Moderators will first respond to such remarks with a warning. +4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. +5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. +6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. +7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. +8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. + +In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. + +And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. + +The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. + +*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).* + +[mod_team]: https://www.rust-lang.org/team.html#Moderation-team -- cgit 1.4.1-3-g733a5 From b6b97e5c1fe6000fafbc8891b8a1da8cb3415583 Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Thu, 1 Nov 2018 15:43:40 -0600 Subject: format code --- clippy_lints/src/literal_representation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 7b0c9523ef0..9f0fad96fc6 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -557,7 +557,7 @@ impl LiteralRepresentation { // Lint for Literals with a hex-representation of 2 or 3 digits let f = &digits[0..1]; // first digit let s = &digits[1..]; // suffix - + // Powers of 2 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && s.chars().all(|c| c == '0')) // Powers of 2 minus 1 @@ -570,7 +570,7 @@ impl LiteralRepresentation { let f = &digits[0..1]; // first digit let m = &digits[1..digits.len() - 1]; // middle digits, except last let s = &digits[1..]; // suffix - + // Powers of 2 with a margin of +15/-16 if ((f.eq("1") || f.eq("2") || f.eq("4") || f.eq("8")) && m.chars().all(|c| c == '0')) || ((f.eq("1") || f.eq("3") || f.eq("7") || f.eq("F")) && m.chars().all(|c| c == 'F')) -- cgit 1.4.1-3-g733a5 From 26569f3dde0d0de2f19fb8d17bf14bf969dd5ace Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 30 Oct 2018 21:21:23 +0100 Subject: UI test cleanup: Extract expect_fun_call tests Note that the new stderr file does not include a `shadow-unrelated` error, because the new UI test file does not use `#![warn(clippy::all)]` --- tests/ui/expect_fun_call.rs | 69 ++++++++++++++++++++++++++ tests/ui/expect_fun_call.stderr | 40 +++++++++++++++ tests/ui/methods.rs | 55 --------------------- tests/ui/methods.stderr | 106 ++++++++++------------------------------ 4 files changed, 134 insertions(+), 136 deletions(-) create mode 100644 tests/ui/expect_fun_call.rs create mode 100644 tests/ui/expect_fun_call.stderr diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs new file mode 100644 index 00000000000..cf764c43694 --- /dev/null +++ b/tests/ui/expect_fun_call.rs @@ -0,0 +1,69 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::expect_fun_call)] +#![allow(clippy::useless_format)] + +/// Checks implementation of the `EXPECT_FUN_CALL` lint + +fn expect_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Self { Foo } + + fn expect(&self, msg: &str) { + panic!("{}", msg) + } + } + + let with_some = Some("value"); + with_some.expect("error"); + + let with_none: Option = None; + with_none.expect("error"); + + let error_code = 123_i32; + let with_none_and_format: Option = None; + with_none_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_none_and_as_str: Option = None; + with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + let with_ok: Result<(), ()> = Ok(()); + with_ok.expect("error"); + + let with_err: Result<(), ()> = Err(()); + with_err.expect("error"); + + let error_code = 123_i32; + let with_err_and_format: Result<(), ()> = Err(()); + with_err_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_err_and_as_str: Result<(), ()> = Err(()); + with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + let with_dummy_type = Foo::new(); + with_dummy_type.expect("another test string"); + + let with_dummy_type_and_format = Foo::new(); + with_dummy_type_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_dummy_type_and_as_str = Foo::new(); + with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + //Issue #2979 - this should not lint + let msg = "bar"; + Some("foo").expect(msg); + + Some("foo").expect({ &format!("error") }); + Some("foo").expect(format!("error").as_ref()); +} + +fn main() {} diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr new file mode 100644 index 00000000000..6b1550b2195 --- /dev/null +++ b/tests/ui/expect_fun_call.stderr @@ -0,0 +1,40 @@ +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:34:26 + | +34 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` + | + = note: `-D clippy::expect-fun-call` implied by `-D warnings` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:37:26 + | +37 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:47:25 + | +47 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:50:25 + | +50 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:65:17 + | +65 | Some("foo").expect({ &format!("error") }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:66:17 + | +66 | Some("foo").expect(format!("error").as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index ae1b1642be7..03bd7e1f084 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -353,61 +353,6 @@ fn or_fun_call() { let _ = stringy.unwrap_or("".to_owned()); } -/// Checks implementation of the `EXPECT_FUN_CALL` lint -fn expect_fun_call() { - struct Foo; - - impl Foo { - fn new() -> Self { Foo } - - fn expect(&self, msg: &str) { - panic!("{}", msg) - } - } - - let with_some = Some("value"); - with_some.expect("error"); - - let with_none: Option = None; - with_none.expect("error"); - - let error_code = 123_i32; - let with_none_and_format: Option = None; - with_none_and_format.expect(&format!("Error {}: fake error", error_code)); - - let with_none_and_as_str: Option = None; - with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - - let with_ok: Result<(), ()> = Ok(()); - with_ok.expect("error"); - - let with_err: Result<(), ()> = Err(()); - with_err.expect("error"); - - let error_code = 123_i32; - let with_err_and_format: Result<(), ()> = Err(()); - with_err_and_format.expect(&format!("Error {}: fake error", error_code)); - - let with_err_and_as_str: Result<(), ()> = Err(()); - with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - - let with_dummy_type = Foo::new(); - with_dummy_type.expect("another test string"); - - let with_dummy_type_and_format = Foo::new(); - with_dummy_type_and_format.expect(&format!("Error {}: fake error", error_code)); - - let with_dummy_type_and_as_str = Foo::new(); - with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - - //Issue #2979 - this should not lint - let msg = "bar"; - Some("foo").expect(msg); - - Some("foo").expect({ &format!("error") }); - Some("foo").expect(format!("error").as_ref()); -} - /// Checks implementation of `ITER_NTH` lint fn iter_nth() { let mut some_vec = vec![0, 1, 2, 3]; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 896b15481bb..985070f3754 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -323,139 +323,83 @@ error: use of `unwrap_or` followed by a function call 353 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` -error: `error_code` is shadowed by `123_i32` - --> $DIR/methods.rs:387:9 - | -387 | let error_code = 123_i32; - | ^^^^^^^^^^ - | - = note: `-D clippy::shadow-unrelated` implied by `-D warnings` -note: initialization happens here - --> $DIR/methods.rs:387:22 - | -387 | let error_code = 123_i32; - | ^^^^^^^ -note: previous binding is here - --> $DIR/methods.rs:374:9 - | -374 | let error_code = 123_i32; - | ^^^^^^^^^^ - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:376:26 - | -376 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` - | - = note: `-D clippy::expect-fun-call` implied by `-D warnings` - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:379:26 - | -379 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:389:25 - | -389 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:392:25 - | -392 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:407:17 - | -407 | Some("foo").expect({ &format!("error") }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` - -error: use of `expect` followed by a function call - --> $DIR/methods.rs:408:17 - | -408 | Some("foo").expect(format!("error").as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` - error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:419:23 + --> $DIR/methods.rs:364:23 | -419 | let bad_vec = some_vec.iter().nth(3); +364 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:420:26 + --> $DIR/methods.rs:365:26 | -420 | let bad_slice = &some_vec[..].iter().nth(3); +365 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:421:31 + --> $DIR/methods.rs:366:31 | -421 | let bad_boxed_slice = boxed_slice.iter().nth(3); +366 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:422:29 + --> $DIR/methods.rs:367:29 | -422 | let bad_vec_deque = some_vec_deque.iter().nth(3); +367 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:427:23 + --> $DIR/methods.rs:372:23 | -427 | let bad_vec = some_vec.iter_mut().nth(3); +372 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:430:26 + --> $DIR/methods.rs:375:26 | -430 | let bad_slice = &some_vec[..].iter_mut().nth(3); +375 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:433:29 + --> $DIR/methods.rs:378:29 | -433 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +378 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:445:13 + --> $DIR/methods.rs:390:13 | -445 | let _ = some_vec.iter().skip(42).next(); +390 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:446:13 + --> $DIR/methods.rs:391:13 | -446 | let _ = some_vec.iter().cycle().skip(42).next(); +391 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:447:13 + --> $DIR/methods.rs:392:13 | -447 | let _ = (1..10).skip(10).next(); +392 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:448:14 + --> $DIR/methods.rs:393:14 | -448 | let _ = &some_vec[..].iter().skip(3).next(); +393 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:457:13 + --> $DIR/methods.rs:402:13 | -457 | let _ = opt.unwrap(); +402 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 57 previous errors +error: aborting due to 50 previous errors -- cgit 1.4.1-3-g733a5 From e5af43d4262d66a1dc850d765da99f0fc3c783d2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 30 Oct 2018 21:36:52 +0100 Subject: UI test cleanup: Extract match_overlapping_arm tests --- tests/ui/match_overlapping_arm.rs | 75 ++++++++++ tests/ui/match_overlapping_arm.stderr | 63 ++++++++ tests/ui/matches.rs | 59 -------- tests/ui/matches.stderr | 275 +++++++++++++--------------------- 4 files changed, 245 insertions(+), 227 deletions(-) create mode 100644 tests/ui/match_overlapping_arm.rs create mode 100644 tests/ui/match_overlapping_arm.stderr diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs new file mode 100644 index 00000000000..1f2c3f8a891 --- /dev/null +++ b/tests/ui/match_overlapping_arm.rs @@ -0,0 +1,75 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(exclusive_range_pattern)] +#![warn(clippy::match_overlapping_arm)] +#![allow(clippy::redundant_pattern_matching)] + +/// Tests for match_overlapping_arm + +fn overlapping() { + const FOO : u64 = 2; + + match 42 { + 0 ... 10 => println!("0 ... 10"), + 0 ... 11 => println!("0 ... 11"), + _ => (), + } + + match 42 { + 0 ... 5 => println!("0 ... 5"), + 6 ... 7 => println!("6 ... 7"), + FOO ... 11 => println!("0 ... 11"), + _ => (), + } + + match 42 { + 2 => println!("2"), + 0 ... 5 => println!("0 ... 5"), + _ => (), + } + + match 42 { + 2 => println!("2"), + 0 ... 2 => println!("0 ... 2"), + _ => (), + } + + match 42 { + 0 ... 10 => println!("0 ... 10"), + 11 ... 50 => println!("11 ... 50"), + _ => (), + } + + match 42 { + 2 => println!("2"), + 0 .. 2 => println!("0 .. 2"), + _ => (), + } + + match 42 { + 0 .. 10 => println!("0 .. 10"), + 10 .. 50 => println!("10 .. 50"), + _ => (), + } + + match 42 { + 0 .. 11 => println!("0 .. 11"), + 0 ... 11 => println!("0 ... 11"), + _ => (), + } + + if let None = Some(42) { + // nothing + } else if let None = Some(42) { + // another nothing :-) + } +} + +fn main() {} diff --git a/tests/ui/match_overlapping_arm.stderr b/tests/ui/match_overlapping_arm.stderr new file mode 100644 index 00000000000..4f9d8ac7683 --- /dev/null +++ b/tests/ui/match_overlapping_arm.stderr @@ -0,0 +1,63 @@ +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:20:9 + | +20 | 0 ... 10 => println!("0 ... 10"), + | ^^^^^^^^ + | + = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:21:9 + | +21 | 0 ... 11 => println!("0 ... 11"), + | ^^^^^^^^ + +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:26:9 + | +26 | 0 ... 5 => println!("0 ... 5"), + | ^^^^^^^ + | +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:28:9 + | +28 | FOO ... 11 => println!("0 ... 11"), + | ^^^^^^^^^^ + +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:34:9 + | +34 | 0 ... 5 => println!("0 ... 5"), + | ^^^^^^^ + | +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:33:9 + | +33 | 2 => println!("2"), + | ^ + +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:40:9 + | +40 | 0 ... 2 => println!("0 ... 2"), + | ^^^^^^^ + | +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:39:9 + | +39 | 2 => println!("2"), + | ^ + +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:63:9 + | +63 | 0 .. 11 => println!("0 .. 11"), + | ^^^^^^^ + | +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:64:9 + | +64 | 0 ... 11 => println!("0 ... 11"), + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index d31e97c7959..c7630b0533d 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -74,65 +74,6 @@ fn ref_pats() { } } -fn overlapping() { - const FOO : u64 = 2; - - match 42 { - 0 ... 10 => println!("0 ... 10"), - 0 ... 11 => println!("0 ... 11"), - _ => (), - } - - match 42 { - 0 ... 5 => println!("0 ... 5"), - 6 ... 7 => println!("6 ... 7"), - FOO ... 11 => println!("0 ... 11"), - _ => (), - } - - match 42 { - 2 => println!("2"), - 0 ... 5 => println!("0 ... 5"), - _ => (), - } - - match 42 { - 2 => println!("2"), - 0 ... 2 => println!("0 ... 2"), - _ => (), - } - - match 42 { - 0 ... 10 => println!("0 ... 10"), - 11 ... 50 => println!("11 ... 50"), - _ => (), - } - - match 42 { - 2 => println!("2"), - 0 .. 2 => println!("0 .. 2"), - _ => (), - } - - match 42 { - 0 .. 10 => println!("0 .. 10"), - 10 .. 50 => println!("10 .. 50"), - _ => (), - } - - match 42 { - 0 .. 11 => println!("0 .. 11"), - 0 ... 11 => println!("0 ... 11"), - _ => (), - } - - if let None = Some(42) { - // nothing - } else if let None = Some(42) { - // another nothing :-) - } -} - fn match_wild_err_arm() { let x: Result = Ok(3); diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index b5f1f2ab0e7..aebb166d3bc 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -88,276 +88,215 @@ help: try 72 | if let None = b { | ^^^^ ^ -error: some ranges overlap - --> $DIR/matches.rs:81:9 - | -81 | 0 ... 10 => println!("0 ... 10"), - | ^^^^^^^^ - | - = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` -note: overlaps with this - --> $DIR/matches.rs:82:9 - | -82 | 0 ... 11 => println!("0 ... 11"), - | ^^^^^^^^ - -error: some ranges overlap - --> $DIR/matches.rs:87:9 - | -87 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ +error: Err(_) will match all errors, maybe not a good idea + --> $DIR/matches.rs:83:9 | -note: overlaps with this - --> $DIR/matches.rs:89:9 +83 | Err(_) => panic!("err") + | ^^^^^^ | -89 | FOO ... 11 => println!("0 ... 11"), - | ^^^^^^^^^^ + = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` + = note: to remove this warning, match each error separately or use unreachable macro -error: some ranges overlap - --> $DIR/matches.rs:95:9 - | -95 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ +error: this `match` has identical arm bodies + --> $DIR/matches.rs:82:18 | -note: overlaps with this - --> $DIR/matches.rs:94:9 +82 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ | -94 | 2 => println!("2"), - | ^ - -error: some ranges overlap - --> $DIR/matches.rs:101:9 - | -101 | 0 ... 2 => println!("0 ... 2"), - | ^^^^^^^ - | -note: overlaps with this - --> $DIR/matches.rs:100:9 - | -100 | 2 => println!("2"), - | ^ - -error: some ranges overlap - --> $DIR/matches.rs:124:9 - | -124 | 0 .. 11 => println!("0 .. 11"), - | ^^^^^^^ - | -note: overlaps with this - --> $DIR/matches.rs:125:9 - | -125 | 0 ... 11 => println!("0 ... 11"), - | ^^^^^^^^ - -error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:142:9 - | -142 | Err(_) => panic!("err") - | ^^^^^^ - | - = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` - = note: to remove this warning, match each error separately or use unreachable macro - -error: this `match` has identical arm bodies - --> $DIR/matches.rs:141:18 - | -141 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | - = note: `-D clippy::match-same-arms` implied by `-D warnings` + = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:140:18 - | -140 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:81:18 + | +81 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:140:18 - | -140 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:81:18 + | +81 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:148:9 - | -148 | Err(_) => {panic!()} - | ^^^^^^ - | - = note: to remove this warning, match each error separately or use unreachable macro + --> $DIR/matches.rs:89:9 + | +89 | Err(_) => {panic!()} + | ^^^^^^ + | + = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:147:18 - | -147 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:88:18 + | +88 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:146:18 - | -146 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:87:18 + | +87 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:146:18 - | -146 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:87:18 + | +87 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:154:9 - | -154 | Err(_) => {panic!();} - | ^^^^^^ - | - = note: to remove this warning, match each error separately or use unreachable macro + --> $DIR/matches.rs:95:9 + | +95 | Err(_) => {panic!();} + | ^^^^^^ + | + = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:153:18 - | -153 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:94:18 + | +94 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:152:18 - | -152 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:93:18 + | +93 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:152:18 - | -152 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:93:18 + | +93 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:160:18 + --> $DIR/matches.rs:101:18 | -160 | Ok(_) => println!("ok"), +101 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:159:18 + --> $DIR/matches.rs:100:18 | -159 | Ok(3) => println!("ok"), +100 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:159:18 + --> $DIR/matches.rs:100:18 | -159 | Ok(3) => println!("ok"), +100 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:167:18 + --> $DIR/matches.rs:108:18 | -167 | Ok(_) => println!("ok"), +108 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:166:18 + --> $DIR/matches.rs:107:18 | -166 | Ok(3) => println!("ok"), +107 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:166:18 + --> $DIR/matches.rs:107:18 | -166 | Ok(3) => println!("ok"), +107 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:173:18 + --> $DIR/matches.rs:114:18 | -173 | Ok(_) => println!("ok"), +114 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:172:18 + --> $DIR/matches.rs:113:18 | -172 | Ok(3) => println!("ok"), +113 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:172:18 + --> $DIR/matches.rs:113:18 | -172 | Ok(3) => println!("ok"), +113 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:179:18 + --> $DIR/matches.rs:120:18 | -179 | Ok(_) => println!("ok"), +120 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:178:18 + --> $DIR/matches.rs:119:18 | -178 | Ok(3) => println!("ok"), +119 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:178:18 + --> $DIR/matches.rs:119:18 | -178 | Ok(3) => println!("ok"), +119 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:200:29 + --> $DIR/matches.rs:141:29 | -200 | (Ok(_), Some(x)) => println!("ok {}", x), +141 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:199:29 + --> $DIR/matches.rs:140:29 | -199 | (Ok(x), Some(_)) => println!("ok {}", x), +140 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:199:29 + --> $DIR/matches.rs:140:29 | -199 | (Ok(x), Some(_)) => println!("ok {}", x), +140 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:215:18 + --> $DIR/matches.rs:156:18 | -215 | Ok(_) => println!("ok"), +156 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:214:18 + --> $DIR/matches.rs:155:18 | -214 | Ok(3) => println!("ok"), +155 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:214:18 + --> $DIR/matches.rs:155:18 | -214 | Ok(3) => println!("ok"), +155 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:222:33 + --> $DIR/matches.rs:163:33 | -222 | let borrowed: Option<&()> = match owned { +163 | let borrowed: Option<&()> = match owned { | _________________________________^ -223 | | None => None, -224 | | Some(ref v) => Some(v), -225 | | }; +164 | | None => None, +165 | | Some(ref v) => Some(v), +166 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:228:39 + --> $DIR/matches.rs:169:39 | -228 | let borrow_mut: Option<&mut ()> = match mut_owned { +169 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -229 | | None => None, -230 | | Some(ref mut v) => Some(v), -231 | | }; +170 | | None => None, +171 | | Some(ref mut v) => Some(v), +172 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 26 previous errors +error: aborting due to 21 previous errors -- cgit 1.4.1-3-g733a5 From d4370f8b07b8aac41a94187f4d334e0903a68711 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 2 Nov 2018 15:56:47 +0900 Subject: Fix a false-positive of needless_borrow --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/needless_borrow.rs | 49 +++++++++++++++++++++---------------- tests/ui/needless_borrow.rs | 7 ++++++ 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 207dc40fa1d..c4913862642 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -365,7 +365,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box zero_div_zero::Pass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_update::Pass); - reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); + reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow::default()); reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); reg.register_late_lint_pass(box no_effect::Pass); reg.register_late_lint_pass(box temporary_assignment::Pass); diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 639358a7ce7..7892467b7f8 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -12,14 +12,15 @@ //! //! This lint is **warn** by default +use crate::rustc::hir::{BindingAnnotation, Expr, ExprKind, Item, MutImmutable, Pat, PatKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind}; use crate::rustc::ty; use crate::rustc::ty::adjustment::{Adjust, Adjustment}; -use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; +use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; +use crate::syntax::ast::NodeId; +use if_chain::if_chain; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. @@ -32,26 +33,17 @@ use crate::rustc_errors::Applicability; /// let x: &i32 = &&&&&&5; /// ``` /// -/// **Known problems:** This will cause false positives in code generated by `derive`. -/// For instance in the following snippet: -/// ```rust -/// #[derive(Debug)] -/// pub enum Error { -/// Type( -/// &'static str, -/// ), -/// } -/// ``` -/// A warning will be emitted that `&'static str` should be replaced with `&'static str`, -/// however there is nothing that can or should be done to fix this. +/// **Known problems:** None. declare_clippy_lint! { pub NEEDLESS_BORROW, nursery, "taking a reference that is going to be automatically dereferenced" } -#[derive(Copy, Clone)] -pub struct NeedlessBorrow; +#[derive(Default)] +pub struct NeedlessBorrow { + derived_item: Option, +} impl LintPass for NeedlessBorrow { fn get_lints(&self) -> LintArray { @@ -61,7 +53,7 @@ impl LintPass for NeedlessBorrow { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if in_macro(e.span) { + if in_macro(e.span) || self.derived_item.is_some() { return; } if let ExprKind::AddrOf(MutImmutable, ref inner) = e.node { @@ -87,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { |db| { if let Some(snippet) = snippet_opt(cx, inner.span) { db.span_suggestion_with_applicability( - e.span, + e.span, "change this to", snippet, Applicability::MachineApplicable, @@ -101,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } } fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { - if in_macro(pat.span) { + if in_macro(pat.span) || self.derived_item.is_some() { return; } if_chain! { @@ -131,4 +123,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } } } + + fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if item.attrs.iter().any(|a| a.check_name("automatically_derived")) { + debug_assert!(self.derived_item.is_none()); + self.derived_item = Some(item.id); + } + } + + fn check_item_post(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if let Some(id) = self.derived_item { + if item.id == id { + self.derived_item = None; + } + } + } } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index f8a170f38d4..29e6ccca94d 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -63,3 +63,10 @@ fn issue_1432() { let _ = v.iter().filter(|&a| a.is_empty()); } + +#[allow(dead_code)] +#[warn(clippy::needless_borrow)] +#[derive(Debug)] +enum Foo<'a> { + Str(&'a str), +} -- cgit 1.4.1-3-g733a5 From df7cff31dc3288d168ce307c2127edb4e3160616 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 2 Nov 2018 12:12:14 +0100 Subject: clippy: fix pedantic warnings and run clippy::pedantic lints on the codebase. Turn on pedantic lints in dogfood and base tests. needless_bool: fix clippy::items-after-statements redundant_pattern_matching: fix clippy::similar-names mods.rs: fix clippy::explicit-iter-loop returns.rs: allow clippy::cast-possible-wrap Fixes #3172 --- ci/base-tests.sh | 4 ++-- clippy_dev/src/lib.rs | 1 - clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/needless_bool.rs | 4 +++- clippy_lints/src/redundant_pattern_matching.rs | 20 ++++++++++---------- clippy_lints/src/returns.rs | 1 + tests/dogfood.rs | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 9b73263c24a..f46c558f24d 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -27,12 +27,12 @@ cd rustc_tools_util && cargo test && cd .. CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... -${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal +${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal -Dclippy::pedantic # ... and some test directories for dir in clippy_workspace_tests clippy_workspace_tests/src clippy_workspace_tests/subcrate clippy_workspace_tests/subcrate/src clippy_dev rustc_tools_util do cd ${dir} - ${CLIPPY} -- -D clippy::all + ${CLIPPY} -- -D clippy::all -D clippy::pedantic cd - done diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 656a271aec9..370b8cf630a 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -8,7 +8,6 @@ // except according to those terms. - #![allow(clippy::default_hash_types)] use itertools::Itertools; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 539d95fd076..31982706497 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -931,7 +931,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let TyKind::Opaque(def_id, _) = ret_ty.sty { // one of the associated types must be Self - for predicate in cx.tcx.predicates_of(def_id).predicates.iter() { + for predicate in &cx.tcx.predicates_of(def_id).predicates { match predicate { (Predicate::Projection(poly_projection_predicate), _) => { let binder = poly_projection_predicate.ty(); diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index e13f757adb9..0019380a34c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -133,10 +133,12 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + use self::Expression::*; + if in_macro(e.span) { return; } - use self::Expression::*; + if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index f8c5b29bad1..7c888b36503 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -83,8 +83,8 @@ fn find_sugg_for_if_let<'a, 'tcx>( ) { if arms[0].pats.len() == 1 { let good_method = match arms[0].pats[0].node { - PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => { - if let PatKind::Wild = pats[0].node { + PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { + if let PatKind::Wild = patterns[0].node { if match_qpath(path, &paths::RESULT_OK) { "is_ok()" } else if match_qpath(path, &paths::RESULT_ERR) { @@ -135,10 +135,10 @@ fn find_sugg_for_match<'a, 'tcx>( let found_good_method = match node_pair { ( - PatKind::TupleStruct(ref path_left, ref pats_left, _), - PatKind::TupleStruct(ref path_right, ref pats_right, _) - ) if pats_left.len() == 1 && pats_right.len() == 1 => { - if let (PatKind::Wild, PatKind::Wild) = (&pats_left[0].node, &pats_right[0].node) { + PatKind::TupleStruct(ref path_left, ref patterns_left, _), + PatKind::TupleStruct(ref path_right, ref patterns_right, _) + ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { + if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].node, &patterns_right[0].node) { find_good_method_for_match( arms, path_left, @@ -153,13 +153,13 @@ fn find_sugg_for_match<'a, 'tcx>( } }, ( - PatKind::TupleStruct(ref path_left, ref pats, _), + PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right) ) | ( PatKind::Path(ref path_left), - PatKind::TupleStruct(ref path_right, ref pats, _) - ) if pats.len() == 1 => { - if let PatKind::Wild = pats[0].node { + PatKind::TupleStruct(ref path_right, ref patterns, _) + ) if patterns.len() == 1 => { + if let PatKind::Wild = patterns[0].node { find_good_method_for_match( arms, path_left, diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index d083387e852..93a0353b2d1 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -200,6 +200,7 @@ impl EarlyLintPass for ReturnPass { cx.sess().source_map() .span_to_snippet(span.with_hi(ty.span.hi())) { if let Some(rpos) = fn_source.rfind("->") { + #[allow(clippy::cast_possible_truncation)] (ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), Applicability::MachineApplicable) } else { diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 0815b146677..dcbfa90e611 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -23,7 +23,7 @@ fn dogfood() { .arg("--all-features") .arg("--manifest-path") .arg(root_dir.join("Cargo.toml")) - .args(&["--", "-W clippy::internal"]) + .args(&["--", "-W clippy::internal -W clippy::pedantic"]) .env("CLIPPY_DOGFOOD", "true") .output() .unwrap(); -- cgit 1.4.1-3-g733a5 From f6d57862c789a2a62d9be175e0fb247d3cf9e0a8 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:09:15 +0200 Subject: Add new lint: unknwon_clippy_lintsg --- clippy_lints/src/attrs.rs | 92 +++++++++++++++++++++++++++++++++++++++++++---- clippy_lints/src/lib.rs | 2 ++ 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index f463ce5fa35..a6c33efd91a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -12,16 +12,20 @@ use crate::reexport::*; use crate::utils::{ - in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, - without_block_comments, + in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, + span_lint_and_then, without_block_comments, }; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; +use crate::rustc::hir::*; +use crate::rustc::lint::{ + CheckLintNameResult, LateContext, LateLintPass, LintArray, LintContext, LintPass, +}; use crate::rustc::ty::{self, TyCtxt}; +use crate::rustc::{declare_tool_lint, lint_array}; use semver::Version; -use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use crate::syntax::ast::{ + AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind, +}; use crate::syntax::source_map::Span; use crate::rustc_errors::Applicability; @@ -138,6 +142,33 @@ declare_clippy_lint! { "empty line after outer attribute" } +/// **What it does:** Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy +/// lints and if those lints exist in clippy. If there is a uppercase letter in the lint name +/// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase +/// the lint name. +/// +/// **Why is this bad?** An lint attribute with a misstyped lint name won't have an effect. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// Bad: +/// ```rust +/// #![warn(if_not_els)] +/// #![deny(clippy::All)] +/// ``` +/// +/// Good: +/// ```rust +/// #![warn(if_not_else)] +/// #![deny(clippy::all)] +/// ``` +declare_clippy_lint! { + pub UNKNOWN_CLIPPY_LINTS, + style, + "unknown_lints for scoped Clippy lints" +} + #[derive(Copy, Clone)] pub struct AttrPass; @@ -147,7 +178,8 @@ impl LintPass for AttrPass { INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, - EMPTY_LINE_AFTER_OUTER_ATTR + EMPTY_LINE_AFTER_OUTER_ATTR, + UNKNOWN_CLIPPY_LINTS, ) } } @@ -155,6 +187,12 @@ impl LintPass for AttrPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { if let Some(ref items) = attr.meta_item_list() { + match &*attr.name().as_str() { + "allow" | "warn" | "deny" | "forbid" => { + check_clippy_lint_names(cx, items); + } + _ => {} + } if items.is_empty() || attr.name() != "deprecated" { return; } @@ -247,6 +285,46 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } +fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &Vec) { + let lint_store = cx.lints(); + for lint in items { + if_chain! { + if let Some(word) = lint.word(); + if let Some(tool_name) = word.is_scoped(); + if tool_name.as_str() == "clippy"; + let name = word.name(); + if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name( + &name.as_str(), + Some(tool_name.as_str()), + ); + then { + span_lint_and_then( + cx, + UNKNOWN_CLIPPY_LINTS, + lint.span, + &format!("unknwon clippy lint: clippy::{}", name), + |db| { + if name.as_str().chars().any(|c| c.is_uppercase()) { + let name_lower = name.as_str().to_lowercase().to_string(); + match lint_store.check_lint_name( + &name_lower, + Some(tool_name.as_str()) + ) { + CheckLintNameResult::NoLint => {} + _ => { + db.span_suggestion(lint.span, + "lowercase the lint name", + name_lower); + } + } + } + } + ); + } + }; + } +} + fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool { if let ItemKind::Fn(_, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 86ecba38d59..56cd2ca3e92 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -533,6 +533,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_SEMVER, + attrs::UNKNOWN_CLIPPY_LINTS, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, @@ -749,6 +750,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::style", Some("clippy_style"), vec![ assign_ops::ASSIGN_OP_PATTERN, + attrs::UNKNOWN_CLIPPY_LINTS, bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, -- cgit 1.4.1-3-g733a5 From 8d516b36fecc62937e0237b0f33d142042741778 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:21:50 +0200 Subject: Add tests for unknwon_clippy_lints lint --- tests/ui/unknown_clippy_lints.rs | 8 ++++++++ tests/ui/unknown_clippy_lints.stderr | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/ui/unknown_clippy_lints.rs create mode 100644 tests/ui/unknown_clippy_lints.stderr diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs new file mode 100644 index 00000000000..0ea20092246 --- /dev/null +++ b/tests/ui/unknown_clippy_lints.rs @@ -0,0 +1,8 @@ + +#![allow(clippy::All)] +#![warn(clippy::pedantic)] + +#[warn(clippy::if_not_els)] +fn main() { + +} diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr new file mode 100644 index 00000000000..da1234e77d0 --- /dev/null +++ b/tests/ui/unknown_clippy_lints.stderr @@ -0,0 +1,16 @@ +error: unknwon clippy lint: clippy::if_not_els + --> $DIR/unknown_clippy_lints.rs:5:8 + | +5 | #[warn(clippy::if_not_els)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` + +error: unknwon clippy lint: clippy::All + --> $DIR/unknown_clippy_lints.rs:2:10 + | +2 | #![allow(clippy::All)] + | ^^^^^^^^^^^ help: lowercase the lint name: `all` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 6819127f1e495ab90e1ee9c1a0c5d16b2d132178 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:26:48 +0200 Subject: run update_lints script --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d9d470925f..0d5d10c7ae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -866,6 +866,7 @@ All notable changes to this project will be documented in this file. [`unimplemented`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unimplemented [`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp +[`unknown_clippy_lints`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unknown_clippy_lints [`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_fold diff --git a/README.md b/README.md index b4091cdab6c..3c056171f02 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 283 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 284 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From ea4a80f2159012f181d5b2cdce5f2200ecf32e4c Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:52:44 +0200 Subject: Fix typo and indentation --- clippy_lints/src/attrs.rs | 4 ++-- tests/ui/unknown_clippy_lints.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a6c33efd91a..4f4beb4cbfb 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -296,13 +296,13 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &Vec if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name( &name.as_str(), Some(tool_name.as_str()), - ); + ); then { span_lint_and_then( cx, UNKNOWN_CLIPPY_LINTS, lint.span, - &format!("unknwon clippy lint: clippy::{}", name), + &format!("unknown clippy lint: clippy::{}", name), |db| { if name.as_str().chars().any(|c| c.is_uppercase()) { let name_lower = name.as_str().to_lowercase().to_string(); diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index da1234e77d0..50d5a9ace37 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -1,4 +1,4 @@ -error: unknwon clippy lint: clippy::if_not_els +error: unknown clippy lint: clippy::if_not_els --> $DIR/unknown_clippy_lints.rs:5:8 | 5 | #[warn(clippy::if_not_els)] @@ -6,7 +6,7 @@ error: unknwon clippy lint: clippy::if_not_els | = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` -error: unknwon clippy lint: clippy::All +error: unknown clippy lint: clippy::All --> $DIR/unknown_clippy_lints.rs:2:10 | 2 | #![allow(clippy::All)] -- cgit 1.4.1-3-g733a5 From cf89c40e345876521864dd1ae05a874e118f1e84 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 13 Sep 2018 10:54:02 +0200 Subject: Fix dogfood error --- clippy_lints/src/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4f4beb4cbfb..a5c7c715747 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -285,7 +285,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } -fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &Vec) { +fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { let lint_store = cx.lints(); for lint in items { if_chain! { -- cgit 1.4.1-3-g733a5 From 014cf3d6e010915f80e26578be00c2859df1b870 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Nov 2018 20:37:13 +0100 Subject: Fix typos --- clippy_lints/src/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a5c7c715747..3a4322e1273 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -147,7 +147,7 @@ declare_clippy_lint! { /// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase /// the lint name. /// -/// **Why is this bad?** An lint attribute with a misstyped lint name won't have an effect. +/// **Why is this bad?** A lint attribute with a mistyped lint name won't have an effect. /// /// **Known problems:** None. /// -- cgit 1.4.1-3-g733a5 From 4e1102f56cb334ed900c124311200da0e55529f9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Nov 2018 21:02:15 +0100 Subject: Add copyright statement© MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ui/unknown_clippy_lints.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index 0ea20092246..d0b4ae9f532 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -1,3 +1,11 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. #![allow(clippy::All)] #![warn(clippy::pedantic)] -- cgit 1.4.1-3-g733a5 From faa1db33912cf000c6f9d31662e30006c41c3c59 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 2 Nov 2018 12:58:16 +0100 Subject: Update stderr --- tests/ui/unknown_clippy_lints.stderr | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index 50d5a9ace37..83ee0e9dd31 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -1,16 +1,16 @@ error: unknown clippy lint: clippy::if_not_els - --> $DIR/unknown_clippy_lints.rs:5:8 - | -5 | #[warn(clippy::if_not_els)] - | ^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` + --> $DIR/unknown_clippy_lints.rs:13:8 + | +13 | #[warn(clippy::if_not_els)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` error: unknown clippy lint: clippy::All - --> $DIR/unknown_clippy_lints.rs:2:10 - | -2 | #![allow(clippy::All)] - | ^^^^^^^^^^^ help: lowercase the lint name: `all` + --> $DIR/unknown_clippy_lints.rs:10:10 + | +10 | #![allow(clippy::All)] + | ^^^^^^^^^^^ help: lowercase the lint name: `all` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 32396f6e181da070269a093efe726fa1a4561cd6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 2 Nov 2018 14:00:46 +0100 Subject: Allow single_match_else --- clippy_lints/src/attrs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 3a4322e1273..89d676f3f4c 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -285,6 +285,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } +#[allow(clippy::single_match_else)] fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { let lint_store = cx.lints(); for lint in items { @@ -310,7 +311,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { &name_lower, Some(tool_name.as_str()) ) { - CheckLintNameResult::NoLint => {} + CheckLintNameResult::NoLint => (), _ => { db.span_suggestion(lint.span, "lowercase the lint name", -- cgit 1.4.1-3-g733a5 From 2d1c9313b0e901229c0ed69f030302917cf8fd18 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 21 Oct 2018 04:03:38 +0800 Subject: Added lints `into_iter_on_ref` and `into_iter_on_array`. Fix #1565. --- CHANGELOG.md | 2 + README.md | 2 +- clippy_lints/src/lib.rs | 4 + clippy_lints/src/methods/mod.rs | 117 ++++++++++++++++++++++++- tests/ui/for_loop.rs | 2 +- tests/ui/into_iter_on_ref.rs | 44 ++++++++++ tests/ui/into_iter_on_ref.stderr | 178 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 tests/ui/into_iter_on_ref.rs create mode 100644 tests/ui/into_iter_on_ref.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d5d10c7ae5..72183f68ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -713,6 +713,8 @@ All notable changes to this project will be documented in this file. [`inline_fn_without_body`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_fn_without_body [`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic +[`into_iter_on_array`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#into_iter_on_array +[`into_iter_on_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons diff --git a/README.md b/README.md index 3c056171f02..8af7a20f66d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 284 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 286 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 56cd2ca3e92..863c0623487 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -628,6 +628,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::EXPECT_FUN_CALL, methods::FILTER_NEXT, methods::GET_UNWRAP, + methods::INTO_ITER_ON_ARRAY, + methods::INTO_ITER_ON_REF, methods::ITER_CLONED_COLLECT, methods::ITER_NTH, methods::ITER_SKIP_NEXT, @@ -784,6 +786,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { mem_replace::MEM_REPLACE_OPTION_WITH_NONE, methods::CHARS_LAST_CMP, methods::GET_UNWRAP, + methods::INTO_ITER_ON_REF, methods::ITER_CLONED_COLLECT, methods::ITER_SKIP_NEXT, methods::NEW_RET_NO_SELF, @@ -935,6 +938,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, methods::CLONE_DOUBLE_REF, + methods::INTO_ITER_ON_ARRAY, methods::TEMPORARY_CSTRING_AS_PTR, minmax::MIN_MAX, misc::CMP_NAN, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 31982706497..4b83c6e6b11 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -745,6 +745,51 @@ declare_clippy_lint! { "using `filter_map` when a more succinct alternative exists" } +/// **What it does:** Checks for `into_iter` calls on types which should be replaced by `iter` or +/// `iter_mut`. +/// +/// **Why is this bad?** Arrays and `PathBuf` do not yet have an `into_iter` method which move out +/// their content into an iterator. Calling `into_iter` instead just forwards to `iter` or +/// `iter_mut` due to auto-referencing, of which only yield references. Furthermore, when the +/// standard library actually [implements the `into_iter` method][25725] which moves the content out +/// of the array, the original use of `into_iter` got inferred with the wrong type and the code will +/// be broken. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ```rust +/// let _ = [1, 2, 3].into_iter().map(|x| *x).collect::>(); +/// ``` +/// +/// [25725]: https://github.com/rust-lang/rust/issues/25725 +declare_clippy_lint! { + pub INTO_ITER_ON_ARRAY, + correctness, + "using `.into_iter()` on an array" +} + +/// **What it does:** Checks for `into_iter` calls on references which should be replaced by `iter` +/// or `iter_mut`. +/// +/// **Why is this bad?** Readability. Calling `into_iter` on a reference will not move out its +/// content into the resulting iterator, which is confusing. It is better just call `iter` or +/// `iter_mut` directly. +/// +/// **Known problems:** None +/// +/// **Example:** +/// +/// ```rust +/// let _ = (&vec![3, 4, 5]).into_iter(); +/// ``` +declare_clippy_lint! { + pub INTO_ITER_ON_REF, + style, + "using `.into_iter()` on a reference" +} + impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!( @@ -779,7 +824,9 @@ impl LintPass for Pass { ITER_CLONED_COLLECT, USELESS_ASREF, UNNECESSARY_FOLD, - UNNECESSARY_FILTER_MAP + UNNECESSARY_FILTER_MAP, + INTO_ITER_ON_ARRAY, + INTO_ITER_ON_REF, ) } } @@ -843,6 +890,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { lint_single_char_pattern(cx, expr, &args[pos]); } }, + ty::Ref(..) if method_call.ident.name == "into_iter" => { + lint_into_iter(cx, expr, self_ty, *method_span); + }, _ => (), } }, @@ -2084,6 +2134,71 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re } } +fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Option<(&'static Lint, &'static str, &'static str)> { + let (self_ty, mutbl) = match self_ref_ty.sty { + ty::TyKind::Ref(_, self_ty, mutbl) => (self_ty, mutbl), + _ => unreachable!(), + }; + let method_name = match mutbl { + hir::MutImmutable => "iter", + hir::MutMutable => "iter_mut", + }; + + let def_id = match self_ty.sty { + ty::TyKind::Array(..) => return Some((INTO_ITER_ON_ARRAY, "array", method_name)), + ty::TyKind::Slice(..) => return Some((INTO_ITER_ON_REF, "slice", method_name)), + ty::Adt(adt, _) => adt.did, + _ => return None, + }; + + // FIXME: instead of this hard-coded list, we should check if `::iter` + // exists and has the desired signature. Unfortunately FnCtxt is not exported + // so we can't use its `lookup_method` method. + static INTO_ITER_COLLECTIONS: [(&Lint, &[&str]); 13] = [ + (INTO_ITER_ON_REF, &paths::VEC), + (INTO_ITER_ON_REF, &paths::OPTION), + (INTO_ITER_ON_REF, &paths::RESULT), + (INTO_ITER_ON_REF, &paths::BTREESET), + (INTO_ITER_ON_REF, &paths::BTREEMAP), + (INTO_ITER_ON_REF, &paths::VEC_DEQUE), + (INTO_ITER_ON_REF, &paths::LINKED_LIST), + (INTO_ITER_ON_REF, &paths::BINARY_HEAP), + (INTO_ITER_ON_REF, &paths::HASHSET), + (INTO_ITER_ON_REF, &paths::HASHMAP), + (INTO_ITER_ON_ARRAY, &["std", "path", "PathBuf"]), + (INTO_ITER_ON_REF, &["std", "path", "Path"]), + (INTO_ITER_ON_REF, &["std", "sync", "mpsc", "Receiver"]), + ]; + + for (lint, path) in &INTO_ITER_COLLECTIONS { + if match_def_path(cx.tcx, def_id, path) { + return Some((lint, path.last().unwrap(), method_name)) + } + } + None +} + +fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::Ty<'_>, method_span: Span) { + if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) { + return; + } + if let Some((lint, kind, method_name)) = ty_has_iter_method(cx, self_ref_ty) { + span_lint_and_sugg( + cx, + lint, + method_span, + &format!( + "this .into_iter() call is equivalent to .{}() and will not move the {}", + method_name, + kind, + ), + "call directly", + method_name.to_owned(), + ); + } +} + + /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { if let ty::Adt(_, substs) = ty.sty { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 2a70149f246..513a3c0ee42 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -29,7 +29,7 @@ impl Unrelated { clippy::for_kv_map)] #[warn(clippy::unused_collect)] #[allow(clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, clippy::cyclomatic_complexity, clippy::similar_names)] -#[allow(clippy::many_single_char_names, unused_variables)] +#[allow(clippy::many_single_char_names, unused_variables, clippy::into_iter_on_array)] fn main() { const MAX_LEN: usize = 42; diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs new file mode 100644 index 00000000000..72aa6341a50 --- /dev/null +++ b/tests/ui/into_iter_on_ref.rs @@ -0,0 +1,44 @@ +#![warn(clippy::into_iter_on_ref)] +#![deny(clippy::into_iter_on_array)] + +struct X; +use std::collections::*; + +fn main() { + for _ in &[1,2,3] {} + for _ in vec![X, X] {} + for _ in &vec![X, X] {} + for _ in [1,2,3].into_iter() {} //~ ERROR equivalent to .iter() + + let _ = [1,2,3].into_iter(); //~ ERROR equivalent to .iter() + let _ = vec![1,2,3].into_iter(); + let _ = (&vec![1,2,3]).into_iter(); //~ WARN equivalent to .iter() + let _ = vec![1,2,3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() + let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + + let _ = (&&&&&&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() + let _ = (&&&&mut &&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() + let _ = (&mut &mut &mut [1,2,3]).into_iter(); //~ ERROR equivalent to .iter_mut() + + let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + + let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() + let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() + let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() +} diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr new file mode 100644 index 00000000000..39055423048 --- /dev/null +++ b/tests/ui/into_iter_on_ref.stderr @@ -0,0 +1,178 @@ +error: this .into_iter() call is equivalent to .iter() and will not move the array + --> $DIR/into_iter_on_ref.rs:11:22 + | +11 | for _ in [1,2,3].into_iter() {} //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + | +note: lint level defined here + --> $DIR/into_iter_on_ref.rs:2:9 + | +2 | #![deny(clippy::into_iter_on_array)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this .into_iter() call is equivalent to .iter() and will not move the array + --> $DIR/into_iter_on_ref.rs:13:21 + | +13 | let _ = [1,2,3].into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the Vec + --> $DIR/into_iter_on_ref.rs:15:28 + | +15 | let _ = (&vec![1,2,3]).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + | + = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` + +error: this .into_iter() call is equivalent to .iter() and will not move the slice + --> $DIR/into_iter_on_ref.rs:16:44 + | +16 | let _ = vec![1,2,3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the slice + --> $DIR/into_iter_on_ref.rs:17:41 + | +17 | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the slice + --> $DIR/into_iter_on_ref.rs:18:44 + | +18 | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the array + --> $DIR/into_iter_on_ref.rs:20:30 + | +20 | let _ = (&&&&&&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the array + --> $DIR/into_iter_on_ref.rs:21:34 + | +21 | let _ = (&&&&mut &&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the array + --> $DIR/into_iter_on_ref.rs:22:38 + | +22 | let _ = (&mut &mut &mut [1,2,3]).into_iter(); //~ ERROR equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the Option + --> $DIR/into_iter_on_ref.rs:24:24 + | +24 | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the Option + --> $DIR/into_iter_on_ref.rs:25:28 + | +25 | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the Result + --> $DIR/into_iter_on_ref.rs:26:32 + | +26 | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the Result + --> $DIR/into_iter_on_ref.rs:27:37 + | +27 | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the Vec + --> $DIR/into_iter_on_ref.rs:28:34 + | +28 | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the Vec + --> $DIR/into_iter_on_ref.rs:29:38 + | +29 | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the BTreeMap + --> $DIR/into_iter_on_ref.rs:30:44 + | +30 | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the BTreeMap + --> $DIR/into_iter_on_ref.rs:31:48 + | +31 | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the VecDeque + --> $DIR/into_iter_on_ref.rs:32:39 + | +32 | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the VecDeque + --> $DIR/into_iter_on_ref.rs:33:43 + | +33 | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the LinkedList + --> $DIR/into_iter_on_ref.rs:34:41 + | +34 | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the LinkedList + --> $DIR/into_iter_on_ref.rs:35:45 + | +35 | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the HashMap + --> $DIR/into_iter_on_ref.rs:36:43 + | +36 | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter_mut() and will not move the HashMap + --> $DIR/into_iter_on_ref.rs:37:47 + | +37 | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` + +error: this .into_iter() call is equivalent to .iter() and will not move the BTreeSet + --> $DIR/into_iter_on_ref.rs:39:39 + | +39 | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the BinaryHeap + --> $DIR/into_iter_on_ref.rs:40:41 + | +40 | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the HashSet + --> $DIR/into_iter_on_ref.rs:41:38 + | +41 | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the Path + --> $DIR/into_iter_on_ref.rs:42:43 + | +42 | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: this .into_iter() call is equivalent to .iter() and will not move the PathBuf + --> $DIR/into_iter_on_ref.rs:43:47 + | +43 | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: aborting due to 28 previous errors + -- cgit 1.4.1-3-g733a5 From 2b2acf1002f8ee516fe064b2c4b5173bcbd21342 Mon Sep 17 00:00:00 2001 From: kennytm Date: Mon, 22 Oct 2018 11:44:09 +0800 Subject: Fix dogfood error. --- clippy_lints/src/literal_representation.rs | 6 +++--- clippy_lints/src/methods/mod.rs | 34 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 145faf0b6b6..f029dd65b39 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -210,7 +210,7 @@ impl<'a> DigitInfo<'a> { .filter(|&c| c != '_') .collect::>() .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) + .map(|chunk| chunk.iter().rev().collect()) .rev() .collect::>() .join("_"); @@ -221,7 +221,7 @@ impl<'a> DigitInfo<'a> { .filter(|&c| c != '_') .collect::>() .chunks(group_size) - .map(|chunk| chunk.into_iter().collect()) + .map(|chunk| chunk.iter().collect()) .collect::>() .join("_"); format!( @@ -238,7 +238,7 @@ impl<'a> DigitInfo<'a> { .collect::>(); let mut hint = filtered_digits_vec .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) + .map(|chunk| chunk.iter().rev().collect()) .rev() .collect::>() .join("_"); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4b83c6e6b11..149e39758ca 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -575,7 +575,7 @@ declare_clippy_lint! { /// temporary placeholder for dealing with the `Option` type, then this does /// not mitigate the need for error handling. If there is a chance that `.get()` /// will be `None` in your program, then it is advisable that the `None` case -/// is handled in a future refactor instead of using `.unwrap()` or the Index +/// is handled in a future refactor instead of using `.unwrap()` or the Index /// trait. /// /// **Example:** @@ -2135,22 +2135,6 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re } fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Option<(&'static Lint, &'static str, &'static str)> { - let (self_ty, mutbl) = match self_ref_ty.sty { - ty::TyKind::Ref(_, self_ty, mutbl) => (self_ty, mutbl), - _ => unreachable!(), - }; - let method_name = match mutbl { - hir::MutImmutable => "iter", - hir::MutMutable => "iter_mut", - }; - - let def_id = match self_ty.sty { - ty::TyKind::Array(..) => return Some((INTO_ITER_ON_ARRAY, "array", method_name)), - ty::TyKind::Slice(..) => return Some((INTO_ITER_ON_REF, "slice", method_name)), - ty::Adt(adt, _) => adt.did, - _ => return None, - }; - // FIXME: instead of this hard-coded list, we should check if `::iter` // exists and has the desired signature. Unfortunately FnCtxt is not exported // so we can't use its `lookup_method` method. @@ -2170,6 +2154,22 @@ fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Opti (INTO_ITER_ON_REF, &["std", "sync", "mpsc", "Receiver"]), ]; + let (self_ty, mutbl) = match self_ref_ty.sty { + ty::TyKind::Ref(_, self_ty, mutbl) => (self_ty, mutbl), + _ => unreachable!(), + }; + let method_name = match mutbl { + hir::MutImmutable => "iter", + hir::MutMutable => "iter_mut", + }; + + let def_id = match self_ty.sty { + ty::TyKind::Array(..) => return Some((INTO_ITER_ON_ARRAY, "array", method_name)), + ty::TyKind::Slice(..) => return Some((INTO_ITER_ON_REF, "slice", method_name)), + ty::Adt(adt, _) => adt.did, + _ => return None, + }; + for (lint, path) in &INTO_ITER_COLLECTIONS { if match_def_path(cx.tcx, def_id, path) { return Some((lint, path.last().unwrap(), method_name)) -- cgit 1.4.1-3-g733a5 From 5563bd6cc366c1e1596bd65c86f04fa66649e993 Mon Sep 17 00:00:00 2001 From: kennytm Date: Wed, 24 Oct 2018 01:50:18 +0800 Subject: Addressed comments. --- clippy_lints/src/methods/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 149e39758ca..e3c704b77ad 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -749,11 +749,11 @@ declare_clippy_lint! { /// `iter_mut`. /// /// **Why is this bad?** Arrays and `PathBuf` do not yet have an `into_iter` method which move out -/// their content into an iterator. Calling `into_iter` instead just forwards to `iter` or -/// `iter_mut` due to auto-referencing, of which only yield references. Furthermore, when the -/// standard library actually [implements the `into_iter` method][25725] which moves the content out -/// of the array, the original use of `into_iter` got inferred with the wrong type and the code will -/// be broken. +/// their content into an iterator. Auto-referencing resolves the `into_iter` call to its reference +/// instead, like `<&[T; N] as IntoIterator>::into_iter`, which just iterates over item references +/// like calling `iter` would. Furthermore, when the standard library actually +/// [implements the `into_iter` method][25725] which moves the content out of the array, the +/// original use of `into_iter` got inferred with the wrong type and the code will be broken. /// /// **Known problems:** None /// -- cgit 1.4.1-3-g733a5 From e1cf160e2a2fba4cf7625dab1a52af5adfc534f5 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 3 Sep 2018 15:34:12 +0200 Subject: Add cfg_attr(rustfmt) lint --- clippy_lints/src/attrs.rs | 33 +++++++++++++++++++++++++++++++-- clippy_lints/src/lib.rs | 3 +++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 89d676f3f4c..4ea13f649d7 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -12,13 +12,13 @@ use crate::reexport::*; use crate::utils::{ - in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, + in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; use crate::rustc::hir::*; use crate::rustc::lint::{ - CheckLintNameResult, LateContext, LateLintPass, LintArray, LintContext, LintPass, + CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, }; use crate::rustc::ty::{self, TyCtxt}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -169,6 +169,35 @@ declare_clippy_lint! { "unknown_lints for scoped Clippy lints" } +/// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it +/// with `#[rustfmt::skip]`. +/// +/// **Why is this bad?** Since tool_attributes (rust-lang/rust#44690) are stable now, they should +/// be used instead of the old `cfg_attr(rustfmt)` attribute. +/// +/// **Known problems:** It currently only detects outer attributes. But since it does not really +/// makes sense to have `#![cfg_attr(rustfmt, rustfmt_skip)]` as an inner attribute, this should be +/// ok. +/// +/// **Example:** +/// +/// Bad: +/// ```rust +/// #[cfg_attr(rustfmt, rustfmt_skip)] +/// fn main() { } +/// ``` +/// +/// Good: +/// ```rust +/// #[rustfmt::skip] +/// fn main() { } +/// ``` +declare_clippy_lint! { + pub DEPRECATED_CFG_ATTR, + complexity, + "usage of `cfg_attr(rustfmt)` instead of `tool_attributes`" +} + #[derive(Copy, Clone)] pub struct AttrPass; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 863c0623487..f3fce54f910 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -220,6 +220,7 @@ pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &m store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold: conf.single_char_binding_names_threshold, }); + store.register_pre_expansion_pass(Some(session), box attrs::CfgAttrPass); } pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { @@ -532,6 +533,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { approx_const::APPROX_CONSTANT, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, + attrs::DEPRECATED_CFG_ATTR, attrs::DEPRECATED_SEMVER, attrs::UNKNOWN_CLIPPY_LINTS, attrs::USELESS_ATTRIBUTE, @@ -839,6 +841,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::complexity", Some("clippy_complexity"), vec![ assign_ops::MISREFACTORED_ASSIGN_OP, + attrs::DEPRECATED_CFG_ATTR, booleans::NONMINIMAL_BOOL, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, double_comparison::DOUBLE_COMPARISONS, -- cgit 1.4.1-3-g733a5 From 7bd8c303d34369124b6550ad6c645d2e1a149214 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 3 Sep 2018 15:34:33 +0200 Subject: Add tests --- tests/ui/cfg_attr_lint.rs | 9 +++++++++ tests/ui/cfg_attr_lint.stderr | 10 ++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/ui/cfg_attr_lint.rs create mode 100644 tests/ui/cfg_attr_lint.stderr diff --git a/tests/ui/cfg_attr_lint.rs b/tests/ui/cfg_attr_lint.rs new file mode 100644 index 00000000000..d543db06d6c --- /dev/null +++ b/tests/ui/cfg_attr_lint.rs @@ -0,0 +1,9 @@ +#![feature(tool_lints)] + +#![warn(clippy::deprecated_cfg_attr)] + +// This doesn't get linted, see known problems +#![cfg_attr(rustfmt, rustfmt_skip)] + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn main() {} diff --git a/tests/ui/cfg_attr_lint.stderr b/tests/ui/cfg_attr_lint.stderr new file mode 100644 index 00000000000..3a515f155c1 --- /dev/null +++ b/tests/ui/cfg_attr_lint.stderr @@ -0,0 +1,10 @@ +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes + --> $DIR/cfg_attr_lint.rs:8:1 + | +8 | #[cfg_attr(rustfmt, rustfmt_skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` + | + = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From a770d8edd0f5f6d1bc4b2abb0842f900f121c186 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Tue, 18 Sep 2018 11:35:53 +0200 Subject: Differ between inner and outer attributes --- clippy_lints/src/attrs.rs | 53 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4ea13f649d7..24edf6d8495 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -172,12 +172,12 @@ declare_clippy_lint! { /// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it /// with `#[rustfmt::skip]`. /// -/// **Why is this bad?** Since tool_attributes (rust-lang/rust#44690) are stable now, they should -/// be used instead of the old `cfg_attr(rustfmt)` attribute. +/// **Why is this bad?** Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690)) +/// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes. /// -/// **Known problems:** It currently only detects outer attributes. But since it does not really -/// makes sense to have `#![cfg_attr(rustfmt, rustfmt_skip)]` as an inner attribute, this should be -/// ok. +/// **Known problems:** This lint doesn't detect crate level inner attributes, because they get +/// processed before the PreExpansionPass lints get executed. See +/// [#3123](https://github.com/rust-lang-nursery/rust-clippy/pull/3123#issuecomment-422321765) /// /// **Example:** /// @@ -495,3 +495,46 @@ fn is_present_in_source(cx: &LateContext<'_, '_>, span: Span) -> bool { } true } + +#[derive(Copy, Clone)] +pub struct CfgAttrPass; + +impl LintPass for CfgAttrPass { + fn get_lints(&self) -> LintArray { + lint_array!( + DEPRECATED_CFG_ATTR, + ) + } +} + +impl EarlyLintPass for CfgAttrPass { + fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { + if_chain! { + // check cfg_attr + if attr.name() == "cfg_attr"; + if let Some(ref items) = attr.meta_item_list(); + if items.len() == 2; + // check for `rustfmt` + if let Some(feature_item) = items[0].meta_item(); + if feature_item.name() == "rustfmt"; + // check for `rustfmt_skip` + if let Some(skip_item) = &items[1].meta_item(); + if skip_item.name() == "rustfmt_skip"; + then { + let attr_style = match attr.style { + AttrStyle::Outer => "#[", + AttrStyle::Inner => "#![", + }; + span_lint_and_sugg( + cx, + DEPRECATED_CFG_ATTR, + attr.span, + "`cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes", + "use", + format!("{}rustfmt::skip]", attr_style), + ); + } + } + } +} + -- cgit 1.4.1-3-g733a5 From 352da1d33dd3f568c2c7bf6887879e3b569209bb Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Tue, 18 Sep 2018 11:36:59 +0200 Subject: Add test for non-crate-level inner attributes --- tests/ui/cfg_attr_lint.rs | 10 +++++++++- tests/ui/cfg_attr_lint.stderr | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/ui/cfg_attr_lint.rs b/tests/ui/cfg_attr_lint.rs index d543db06d6c..1005af8b9ea 100644 --- a/tests/ui/cfg_attr_lint.rs +++ b/tests/ui/cfg_attr_lint.rs @@ -6,4 +6,12 @@ #![cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)] -fn main() {} +fn main() { + foo::f(); +} + +mod foo { + #![cfg_attr(rustfmt, rustfmt_skip)] + + pub fn f() {} +} diff --git a/tests/ui/cfg_attr_lint.stderr b/tests/ui/cfg_attr_lint.stderr index 3a515f155c1..b166d4028d9 100644 --- a/tests/ui/cfg_attr_lint.stderr +++ b/tests/ui/cfg_attr_lint.stderr @@ -6,5 +6,11 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes | = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` -error: aborting due to previous error +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes + --> $DIR/cfg_attr_lint.rs:14:5 + | +14 | #![cfg_attr(rustfmt, rustfmt_skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From bb4083c412f0d7e687b3ae7ab4cc4dc57e6ea804 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 15 Oct 2018 15:18:26 +0200 Subject: Run update_lints.py script --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72183f68ee0..bdd01bfeecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -651,6 +651,7 @@ All notable changes to this project will be documented in this file. [`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation [`declare_interior_mutable_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#declare_interior_mutable_const [`default_trait_access`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#default_trait_access +[`deprecated_cfg_attr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_cfg_attr [`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof [`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq diff --git a/README.md b/README.md index 8af7a20f66d..0525788e64e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 286 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 287 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 7df7a0a86ebf290f6f2650955f2479aaaa39beef Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Nov 2018 20:06:25 +0100 Subject: Add tests from rustfmt::skip test file --- tests/ui/cfg_attr_lint.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/ui/cfg_attr_lint.rs b/tests/ui/cfg_attr_lint.rs index 1005af8b9ea..614cd3e30ec 100644 --- a/tests/ui/cfg_attr_lint.rs +++ b/tests/ui/cfg_attr_lint.rs @@ -1,10 +1,31 @@ -#![feature(tool_lints)] +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(stmt_expr_attributes)] #![warn(clippy::deprecated_cfg_attr)] // This doesn't get linted, see known problems #![cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] +trait Foo +{ +fn foo( +); +} + +fn skip_on_statements() { + #[cfg_attr(rustfmt, rustfmt::skip)] + 5+3; +} + #[cfg_attr(rustfmt, rustfmt_skip)] fn main() { foo::f(); -- cgit 1.4.1-3-g733a5 From cadb367a5cb36590c54d90c4cad5ebf67e796477 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Nov 2018 20:06:59 +0100 Subject: Also lint cfg_attr(.., rustfmt::skip) --- clippy_lints/src/attrs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 24edf6d8495..593484aa1c6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -517,9 +517,9 @@ impl EarlyLintPass for CfgAttrPass { // check for `rustfmt` if let Some(feature_item) = items[0].meta_item(); if feature_item.name() == "rustfmt"; - // check for `rustfmt_skip` + // check for `rustfmt_skip` and `rustfmt::skip` if let Some(skip_item) = &items[1].meta_item(); - if skip_item.name() == "rustfmt_skip"; + if skip_item.name() == "rustfmt_skip" || skip_item.name() == "skip"; then { let attr_style = match attr.style { AttrStyle::Outer => "#[", -- cgit 1.4.1-3-g733a5 From 5c1385249e9ca227b469f83232c771ddfde8b0e6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Nov 2018 20:17:04 +0100 Subject: Rename test files --- tests/ui/cfg_attr_lint.rs | 38 -------------------------------------- tests/ui/cfg_attr_lint.stderr | 16 ---------------- tests/ui/cfg_attr_rustfmt.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/ui/cfg_attr_rustfmt.stderr | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 tests/ui/cfg_attr_lint.rs delete mode 100644 tests/ui/cfg_attr_lint.stderr create mode 100644 tests/ui/cfg_attr_rustfmt.rs create mode 100644 tests/ui/cfg_attr_rustfmt.stderr diff --git a/tests/ui/cfg_attr_lint.rs b/tests/ui/cfg_attr_lint.rs deleted file mode 100644 index 614cd3e30ec..00000000000 --- a/tests/ui/cfg_attr_lint.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(stmt_expr_attributes)] - -#![warn(clippy::deprecated_cfg_attr)] - -// This doesn't get linted, see known problems -#![cfg_attr(rustfmt, rustfmt_skip)] - -#[rustfmt::skip] -trait Foo -{ -fn foo( -); -} - -fn skip_on_statements() { - #[cfg_attr(rustfmt, rustfmt::skip)] - 5+3; -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn main() { - foo::f(); -} - -mod foo { - #![cfg_attr(rustfmt, rustfmt_skip)] - - pub fn f() {} -} diff --git a/tests/ui/cfg_attr_lint.stderr b/tests/ui/cfg_attr_lint.stderr deleted file mode 100644 index b166d4028d9..00000000000 --- a/tests/ui/cfg_attr_lint.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_lint.rs:8:1 - | -8 | #[cfg_attr(rustfmt, rustfmt_skip)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` - | - = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` - -error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_lint.rs:14:5 - | -14 | #![cfg_attr(rustfmt, rustfmt_skip)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs new file mode 100644 index 00000000000..614cd3e30ec --- /dev/null +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -0,0 +1,38 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(stmt_expr_attributes)] + +#![warn(clippy::deprecated_cfg_attr)] + +// This doesn't get linted, see known problems +#![cfg_attr(rustfmt, rustfmt_skip)] + +#[rustfmt::skip] +trait Foo +{ +fn foo( +); +} + +fn skip_on_statements() { + #[cfg_attr(rustfmt, rustfmt::skip)] + 5+3; +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn main() { + foo::f(); +} + +mod foo { + #![cfg_attr(rustfmt, rustfmt_skip)] + + pub fn f() {} +} diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr new file mode 100644 index 00000000000..b166d4028d9 --- /dev/null +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -0,0 +1,16 @@ +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes + --> $DIR/cfg_attr_lint.rs:8:1 + | +8 | #[cfg_attr(rustfmt, rustfmt_skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` + | + = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` + +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes + --> $DIR/cfg_attr_lint.rs:14:5 + | +14 | #![cfg_attr(rustfmt, rustfmt_skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From 318f84ffcf4d919373ab4a025891d591e81070d6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 2 Nov 2018 13:43:16 +0100 Subject: Update stderr --- tests/ui/cfg_attr_rustfmt.stderr | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index b166d4028d9..a6a27bd2ee8 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -1,16 +1,22 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_lint.rs:8:1 - | -8 | #[cfg_attr(rustfmt, rustfmt_skip)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` - | - = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` + --> $DIR/cfg_attr_rustfmt.rs:25:5 + | +25 | #[cfg_attr(rustfmt, rustfmt::skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` + | + = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` + +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes + --> $DIR/cfg_attr_rustfmt.rs:29:1 + | +29 | #[cfg_attr(rustfmt, rustfmt_skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_lint.rs:14:5 + --> $DIR/cfg_attr_rustfmt.rs:35:5 | -14 | #![cfg_attr(rustfmt, rustfmt_skip)] +35 | #![cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 5fc25d30e25fa5c05c34812eab311c42b464bb17 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Nov 2018 20:16:38 +0100 Subject: RIIR update lints: Generate modules section --- clippy_dev/src/lib.rs | 38 ++++++++++++++++++++++++++++++++++++-- clippy_dev/src/main.rs | 8 ++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 656a271aec9..53b9d5e18ec 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -72,6 +72,19 @@ impl Lint { } } +/// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. +pub fn gen_modules_list(lints: Vec) -> Vec { + lints.into_iter() + .filter_map(|l| { + if l.is_internal() || l.deprecation.is_some() { None } else { Some(l.module) } + }) + .unique() + .map(|module| { + format!("pub mod {};", module) + }) + .sorted() +} + /// Generates the list of lint links at the bottom of the README pub fn gen_changelog_lint_list(lints: Vec) -> Vec { let mut lint_list_sorted: Vec = lints; @@ -113,7 +126,13 @@ fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); - parse_contents(&content, dir_entry.path().file_stem().unwrap().to_str().unwrap()) + let mut filename = dir_entry.path().file_stem().unwrap().to_str().unwrap(); + // If the lints are stored in mod.rs, we get the module name from + // the containing directory: + if filename == "mod" { + filename = dir_entry.path().parent().unwrap().file_stem().unwrap().to_str().unwrap() + } + parse_contents(&content, filename) } fn parse_contents(content: &str, filename: &str) -> impl Iterator { @@ -215,7 +234,7 @@ pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_sta // This happens if the provided regex in `clippy_dev/src/main.rs` is not found in the // given text or file. Most likely this is an error on the programmer's side and the Regex // is incorrect. - println!("regex {:?} not found. You may have to update it.", start); + eprintln!("error: regex `{:?}` not found. You may have to update it.", start); } new_lines.join("\n") } @@ -356,3 +375,18 @@ fn test_gen_deprecated() { ]; assert_eq!(expected, gen_deprecated(&lints)); } + +#[test] +fn test_gen_modules_list() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), + Lint::new("incorrect_internal", "internal_style", "abc", None, "another_module"), + Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), + ]; + let expected = vec![ + "pub mod another_module;\n".to_string(), + "pub mod module_name;\n".to_string(), + ]; + assert_eq!(expected, gen_modules_list(lints)); +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 887a4ab9328..4832b428e9c 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -90,4 +90,12 @@ fn update_lints() { false, || { gen_deprecated(&lint_list) } ); + + replace_region_in_file( + "../clippy_lints/src/lib.rs", + "begin lints modules", + "end lints modules", + false, + || { gen_modules_list(lint_list.clone()) } + ); } -- cgit 1.4.1-3-g733a5 From 6e3320c7efc9cdaa1ddb3865181ec017d9f5de26 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Nov 2018 10:58:45 +0100 Subject: Test clippy_dev on CI and fix test --- ci/base-tests.sh | 1 + clippy_dev/src/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 9b73263c24a..dc0802a941d 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -22,6 +22,7 @@ cargo build --features debugging cargo test --features debugging cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. +cd clippy_dev && cargo test && cd .. # check that the lint lists are up-to-date ./util/update_lints.py -c diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 53b9d5e18ec..28cc4600a09 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -381,12 +381,12 @@ fn test_gen_modules_list() { let lints = vec![ Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), - Lint::new("incorrect_internal", "internal_style", "abc", None, "another_module"), + Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), ]; let expected = vec![ - "pub mod another_module;\n".to_string(), - "pub mod module_name;\n".to_string(), + "pub mod another_module;".to_string(), + "pub mod module_name;".to_string(), ]; assert_eq!(expected, gen_modules_list(lints)); } -- cgit 1.4.1-3-g733a5 From 4f38538d7585caed83bb6a95ede130f407ca7d3f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Nov 2018 12:59:13 +0100 Subject: RIIR update lints: Generate lint group registrations --- clippy_dev/src/lib.rs | 28 ++++++++++++++++++++++++++++ clippy_dev/src/main.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 28cc4600a09..f16ea14a3de 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -72,6 +72,19 @@ impl Lint { } } +/// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`. +pub fn gen_lint_group_list(lints: Vec) -> Vec { + lints.into_iter() + .filter_map(|l| { + if l.is_internal() || l.deprecation.is_some() { + None + } else { + Some(format!(" {}::{},", l.module, l.name.to_uppercase())) + } + }) + .sorted() +} + /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. pub fn gen_modules_list(lints: Vec) -> Vec { lints.into_iter() @@ -390,3 +403,18 @@ fn test_gen_modules_list() { ]; assert_eq!(expected, gen_modules_list(lints)); } + +#[test] +fn test_gen_lint_group_list() { + let lints = vec![ + Lint::new("abc", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), + Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), + ]; + let expected = vec![ + " module_name::ABC,".to_string(), + " module_name::SHOULD_ASSERT_EQ,".to_string(), + ]; + assert_eq!(expected, gen_lint_group_list(lints)); +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 4832b428e9c..128feaa8aea 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -98,4 +98,34 @@ fn update_lints() { false, || { gen_modules_list(lint_list.clone()) } ); + + // Generate lists of lints in the clippy::all lint group + replace_region_in_file( + "../clippy_lints/src/lib.rs", + r#"reg.register_lint_group\("clippy::all""#, + r#"\]\);"#, + false, + || { + // clippy::all should only include the following lint groups: + let all_group_lints = usable_lints.clone().into_iter().filter(|l| { + l.group == "correctness" || + l.group == "style" || + l.group == "complexity" || + l.group == "perf" + }).collect(); + + gen_lint_group_list(all_group_lints) + } + ); + + // Generate the list of lints for all other lint groups + for (lint_group, lints) in Lint::by_lint_group(&usable_lints) { + replace_region_in_file( + "../clippy_lints/src/lib.rs", + &format!("reg.register_lint_group\\(\"clippy::{}\"", lint_group), + r#"\]\);"#, + false, + || { gen_lint_group_list(lints.clone()) } + ); + } } -- cgit 1.4.1-3-g733a5 From cca50701d9b798c821bb4c5c4a20eb02d8d5f3a8 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Nov 2018 12:59:40 +0100 Subject: Improve clippy_dev help text --- clippy_dev/src/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 128feaa8aea..807e4a1b9af 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -19,12 +19,17 @@ fn main() { let matches = App::new("Clippy developer tooling") .subcommand( SubCommand::with_name("update_lints") - .about("Update the lint list") + .about("Makes sure that:\n \ + * the lint count in README.md is correct\n \ + * the changelog contains markdown link references at the bottom\n \ + * all lints groups include the correct lints\n \ + * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ + * all lints are registered in the lint store") .arg( Arg::with_name("print-only") .long("print-only") .short("p") - .help("Print a table of lints to STDOUT. Does not modify any files."), + .help("Print a table of lints to STDOUT. This does not include deprecated and internal lints. (Does not modify any files)"), ) ) .get_matches(); -- cgit 1.4.1-3-g733a5 From facfb5a7a979054c26fdb3adf11b1c6c762fde13 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Nov 2018 18:48:39 +0100 Subject: Fix typo --- clippy_dev/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 807e4a1b9af..288fb7c58b4 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -22,7 +22,7 @@ fn main() { .about("Makes sure that:\n \ * the lint count in README.md is correct\n \ * the changelog contains markdown link references at the bottom\n \ - * all lints groups include the correct lints\n \ + * all lint groups include the correct lints\n \ * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ * all lints are registered in the lint store") .arg( -- cgit 1.4.1-3-g733a5 From b59b60c8ae2c3702069ad47c05023563636a21ef Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 3 Nov 2018 18:50:23 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/55330/ --- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 503a2ee7032..373cf1fbf38 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -106,7 +106,7 @@ fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool { let ty = cx.tables.expr_ty(expr); if let ty::FnDef(id, _) = ty.sty { - if let Some(fn_type) = cx.tcx.fn_sig(id).no_late_bound_regions() { + if let Some(fn_type) = cx.tcx.fn_sig(id).no_bound_vars() { return is_unit_type(fn_type.output()); } } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 39f519ac586..d4257fd1aa9 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .filter(|p| !p.is_global()) .filter_map(|pred| { if let ty::Predicate::Trait(poly_trait_ref) = pred { - if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_regions() { + if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars() { return None; } Some(poly_trait_ref) -- cgit 1.4.1-3-g733a5 From 0c1ffc1d1fdfd73bf326d1e7a886f59367374dc3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 4 Nov 2018 10:02:49 +0200 Subject: Fix `possible_missing_comma` false positives `possible_missing_comma` should only trigger when the binary operator has unary equivalent. Otherwise, it's not possible to insert a comma without breaking compilation. The operators identified were `+`, `&`, `*` and `-`. This fixes the specific examples given in issues #3244 and #3396 but doesn't address the conflict this lint has with the style of starting a line with a binary operator. --- clippy_lints/src/formatting.rs | 36 +++++++++++++++++++++++------------- tests/ui/formatting.rs | 12 ++++++++++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 7f5715ef691..8649834e267 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -173,24 +173,34 @@ fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { } } +fn has_unary_equivalent(bin_op: ast::BinOpKind) -> bool { + //+, &, *, - + bin_op == ast::BinOpKind::Add + || bin_op == ast::BinOpKind::And + || bin_op == ast::BinOpKind::Mul + || bin_op == ast::BinOpKind::Sub +} + /// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let ast::ExprKind::Array(ref array) = expr.node { for element in array { if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node { - if !differing_macro_contexts(lhs.span, op.span) { - let space_span = lhs.span.between(op.span); - if let Some(space_snippet) = snippet_opt(cx, space_span) { - let lint_span = lhs.span.with_lo(lhs.span.hi()); - if space_snippet.contains('\n') { - span_note_and_lint( - cx, - POSSIBLE_MISSING_COMMA, - lint_span, - "possibly missing a comma here", - lint_span, - "to remove this lint, add a comma or write the expr in a single line", - ); + if has_unary_equivalent(op.node) { + if !differing_macro_contexts(lhs.span, op.span) { + let space_span = lhs.span.between(op.span); + if let Some(space_snippet) = snippet_opt(cx, space_span) { + let lint_span = lhs.span.with_lo(lhs.span.hi()); + if space_snippet.contains('\n') { + span_note_and_lint( + cx, + POSSIBLE_MISSING_COMMA, + lint_span, + "possibly missing a comma here", + lint_span, + "to remove this lint, add a comma or write the expr in a single line", + ); + } } } } diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 0dca8c8585b..88f6e497d12 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -112,4 +112,16 @@ fn main() { 1 + 2, 3 + 4, 5 + 6, ]; + + // don't lint for bin op without unary equiv + // issue 3244 + vec![ + 1 + / 2, + ]; + // issue 3396 + vec![ + true + | false, + ]; } -- cgit 1.4.1-3-g733a5 From a3ab512576c77e08646ba731e8906a02983da2c8 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 4 Nov 2018 10:48:24 +0200 Subject: Fix `collapsible_if` error --- clippy_lints/src/formatting.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 8649834e267..69aabcb7949 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -186,21 +186,19 @@ fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let ast::ExprKind::Array(ref array) = expr.node { for element in array { if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node { - if has_unary_equivalent(op.node) { - if !differing_macro_contexts(lhs.span, op.span) { - let space_span = lhs.span.between(op.span); - if let Some(space_snippet) = snippet_opt(cx, space_span) { - let lint_span = lhs.span.with_lo(lhs.span.hi()); - if space_snippet.contains('\n') { - span_note_and_lint( - cx, - POSSIBLE_MISSING_COMMA, - lint_span, - "possibly missing a comma here", - lint_span, - "to remove this lint, add a comma or write the expr in a single line", - ); - } + if has_unary_equivalent(op.node) && !differing_macro_contexts(lhs.span, op.span) { + let space_span = lhs.span.between(op.span); + if let Some(space_snippet) = snippet_opt(cx, space_span) { + let lint_span = lhs.span.with_lo(lhs.span.hi()); + if space_snippet.contains('\n') { + span_note_and_lint( + cx, + POSSIBLE_MISSING_COMMA, + lint_span, + "possibly missing a comma here", + lint_span, + "to remove this lint, add a comma or write the expr in a single line", + ); } } } -- cgit 1.4.1-3-g733a5 From 3e0de1745d643d78dcc7e10ec81720dcae1ba4fe Mon Sep 17 00:00:00 2001 From: Maxwell Anderson Date: Sun, 4 Nov 2018 10:39:54 -0700 Subject: changed into_iter to iter and fixed a lint check --- clippy_lints/src/literal_representation.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9f0fad96fc6..574ab707595 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -229,20 +229,20 @@ impl<'a> DigitInfo<'a> { None => String::new(), }; format!("{}.{}{}", int_part_hint, frac_part_hint, suffix_hint) - } else if self.float && (self.digits.contains('E') || self.digits.contains('E')) { + } else if self.float && (self.digits.contains('E') || self.digits.contains('e')) { let which_e = if self.digits.contains('E') { 'E' } else { 'e' }; let parts: Vec<&str> = self.digits.split(which_e).collect(); let filtered_digits_vec_0 = parts[0].chars().filter(|&c| c != '_').rev().collect::>(); let filtered_digits_vec_1 = parts[1].chars().filter(|&c| c != '_').rev().collect::>(); let before_e_hint = filtered_digits_vec_0 .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) + .map(|chunk| chunk.iter().rev().collect()) .rev() .collect::>() .join("_"); let after_e_hint = filtered_digits_vec_1 .chunks(group_size) - .map(|chunk| chunk.into_iter().rev().collect()) + .map(|chunk| chunk.iter().rev().collect()) .rev() .collect::>() .join("_"); -- cgit 1.4.1-3-g733a5 From 396701613e644905fac904c28678d64a813f80a6 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 4 Nov 2018 22:47:20 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/55665 (pass contexts by reference) --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 1cd20b68421..ad91acbcbfd 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1016,7 +1016,7 @@ pub fn get_arg_name(pat: &Pat) -> Option { } pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 { - layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits() + layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits() } #[allow(clippy::cast_possible_wrap)] @@ -1035,7 +1035,7 @@ pub fn unsext(tcx: TyCtxt<'_, '_, '_>, u: i128, ity: ast::IntTy) -> u128 { /// clip unused bytes pub fn clip(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::UintTy) -> u128 { - let bits = layout::Integer::from_attr(tcx, attr::IntType::UnsignedInt(ity)).size().bits(); + let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits(); let amt = 128 - bits; (u << amt) >> amt } -- cgit 1.4.1-3-g733a5 From 90f31e21ab1e3b0b3cd3887094a705217f67bdfa Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 4 Nov 2018 09:41:28 +0100 Subject: RIIR update lints: Add check mode (update_lints.py rewrite complete) This finishes up the rewrite of `update_lints.py` in Rust. More specifically, this * adds the `--check` flag and handling to clippy_dev * tracks file changes over the different calls to `replace_region_in_file` * only writes changes to files if the `--check` flag is *not* used * runs `./util/dev update_lints --check` on CI instead of the old script * replaces usage of the `update_lints.py` script with an error `./util/dev update_lints` behaves 99% the same as the python script. The only difference that I'm aware of is an ordering change to `clippy_lints/src/lib.rs` because underscores seem to be sorted differently in Rust and in Python. :checkered_flag: --- CONTRIBUTING.md | 2 +- ci/base-tests.sh | 5 +- clippy_dev/src/lib.rs | 41 +++++--- clippy_dev/src/main.rs | 59 ++++++++---- clippy_lints/src/lib.rs | 12 +-- util/update_lints.py | 242 +----------------------------------------------- 6 files changed, 82 insertions(+), 279 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4080a5fa9c..50f61eb1e67 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -180,7 +180,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. -It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/update_lints.py` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time. +It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/dev update_lints` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time. ```rust // ./clippy_lints/src/else_if_without_else.rs diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 0ed1494be82..88cc20842e8 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -23,8 +23,9 @@ cargo test --features debugging cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. cd clippy_dev && cargo test && cd .. -# check that the lint lists are up-to-date -./util/update_lints.py -c + +# Perform various checks for lint registration +./util/dev update_lints --check CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 2ae8423381d..d1ba13bbe9d 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -168,23 +168,33 @@ fn lint_files() -> impl Iterator { .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } +/// Whether a file has had its text changed or not +#[derive(PartialEq, Debug)] +pub struct FileChange { + pub changed: bool, + pub new_lines: String, +} + /// Replace a region in a file delimited by two lines matching regexes. /// /// `path` is the relative path to the file on which you want to perform the replacement. /// /// See `replace_region_in_text` for documentation of the other options. #[allow(clippy::expect_fun_call)] -pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_start: bool, replacements: F) where F: Fn() -> Vec { +pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_start: bool, write_back: bool, replacements: F) -> FileChange where F: Fn() -> Vec { let mut f = fs::File::open(path).expect(&format!("File not found: {}", path)); let mut contents = String::new(); f.read_to_string(&mut contents).expect("Something went wrong reading the file"); - let replaced = replace_region_in_text(&contents, start, end, replace_start, replacements); - - let mut f = fs::File::create(path).expect(&format!("File not found: {}", path)); - f.write_all(replaced.as_bytes()).expect("Unable to write file"); - // Ensure we write the changes with a trailing newline so that - // the file has the proper line endings. - f.write_all(b"\n").expect("Unable to write file"); + let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); + + if write_back { + let mut f = fs::File::create(path).expect(&format!("File not found: {}", path)); + f.write_all(file_change.new_lines.as_bytes()).expect("Unable to write file"); + // Ensure we write the changes with a trailing newline so that + // the file has the proper line endings. + f.write_all(b"\n").expect("Unable to write file"); + } + file_change } /// Replace a region in a text delimited by two lines matching regexes. @@ -213,10 +223,10 @@ pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_sta /// || { /// vec!["a different".to_string(), "text".to_string()] /// } -/// ); +/// ).new_lines; /// assert_eq!("replace_start\na different\ntext\nreplace_end", result); /// ``` -pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> String where F: Fn() -> Vec { +pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange where F: Fn() -> Vec { let lines = text.lines(); let mut in_old_region = false; let mut found = false; @@ -224,7 +234,7 @@ pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_sta let start = Regex::new(start).unwrap(); let end = Regex::new(end).unwrap(); - for line in lines { + for line in lines.clone() { if in_old_region { if end.is_match(&line) { in_old_region = false; @@ -248,7 +258,10 @@ pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_sta // is incorrect. eprintln!("error: regex `{:?}` not found. You may have to update it.", start); } - new_lines.join("\n") + FileChange { + changed: lines.ne(new_lines.clone()), + new_lines: new_lines.join("\n") + } } #[test] @@ -305,7 +318,7 @@ def ghi"#; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { vec!["hello world".to_string()] - }); + }).new_lines; assert_eq!(expected, result); } @@ -323,7 +336,7 @@ def ghi"#; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { vec!["hello world".to_string()] - }); + }).new_lines; assert_eq!(expected, result); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 288fb7c58b4..c9b498f5d5a 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -15,6 +15,12 @@ extern crate regex; use clap::{App, Arg, SubCommand}; use clippy_dev::*; +#[derive(PartialEq)] +enum UpdateMode { + Check, + Change +} + fn main() { let matches = App::new("Clippy developer tooling") .subcommand( @@ -28,17 +34,23 @@ fn main() { .arg( Arg::with_name("print-only") .long("print-only") - .short("p") - .help("Print a table of lints to STDOUT. This does not include deprecated and internal lints. (Does not modify any files)"), + .help("Print a table of lints to STDOUT. This does not include deprecated and internal lints. (Does not modify any files)") + ) + .arg( + Arg::with_name("check") + .long("check") + .help("Checks that util/dev update_lints has been run. Used on CI."), ) - ) - .get_matches(); + ) + .get_matches(); if let Some(matches) = matches.subcommand_matches("update_lints") { if matches.is_present("print-only") { print_lints(); + } else if matches.is_present("check") { + update_lints(UpdateMode::Check); } else { - update_lints(); + update_lints(UpdateMode::Change); } } } @@ -63,53 +75,58 @@ fn print_lints() { println!("there are {} lints", lint_count); } -fn update_lints() { +fn update_lints(update_mode: UpdateMode) { let lint_list: Vec = gather_all().collect(); let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); let lint_count = usable_lints.len(); - replace_region_in_file( + let mut file_change = replace_region_in_file( "../README.md", r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#, "", true, + update_mode == UpdateMode::Change, || { vec![ format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count) ] } - ); + ).changed; - replace_region_in_file( + file_change |= replace_region_in_file( "../CHANGELOG.md", "", "", false, + update_mode == UpdateMode::Change, || { gen_changelog_lint_list(lint_list.clone()) } - ); + ).changed; - replace_region_in_file( + file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", "begin deprecated lints", "end deprecated lints", false, + update_mode == UpdateMode::Change, || { gen_deprecated(&lint_list) } - ); + ).changed; - replace_region_in_file( + file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", "begin lints modules", "end lints modules", false, + update_mode == UpdateMode::Change, || { gen_modules_list(lint_list.clone()) } - ); + ).changed; // Generate lists of lints in the clippy::all lint group - replace_region_in_file( + file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", r#"reg.register_lint_group\("clippy::all""#, r#"\]\);"#, false, + update_mode == UpdateMode::Change, || { // clippy::all should only include the following lint groups: let all_group_lints = usable_lints.clone().into_iter().filter(|l| { @@ -121,16 +138,22 @@ fn update_lints() { gen_lint_group_list(all_group_lints) } - ); + ).changed; // Generate the list of lints for all other lint groups for (lint_group, lints) in Lint::by_lint_group(&usable_lints) { - replace_region_in_file( + file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", &format!("reg.register_lint_group\\(\"clippy::{}\"", lint_group), r#"\]\);"#, false, + update_mode == UpdateMode::Change, || { gen_lint_group_list(lints.clone()) } - ); + ).changed; + } + + if update_mode == UpdateMode::Check && file_change { + println!("Not all lints defined properly. Please run util/dev update_lints to make sure all lints are defined properly."); + std::process::exit(1); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 06ae78a6509..c93e9d57d67 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -548,8 +548,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { bytecount::NAIVE_BYTECOUNT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, - copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, + copies::IF_SAME_THEN_ELSE, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, derive::DERIVE_HASH_XOR_EQ, double_comparison::DOUBLE_COMPARISONS, @@ -743,12 +743,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unused_io_amount::UNUSED_IO_AMOUNT, unused_label::UNUSED_LABEL, vec::USELESS_VEC, + write::PRINTLN_EMPTY_STRING, write::PRINT_LITERAL, write::PRINT_WITH_NEWLINE, - write::PRINTLN_EMPTY_STRING, + write::WRITELN_EMPTY_STRING, write::WRITE_LITERAL, write::WRITE_WITH_NEWLINE, - write::WRITELN_EMPTY_STRING, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); @@ -831,12 +831,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + write::PRINTLN_EMPTY_STRING, write::PRINT_LITERAL, write::PRINT_WITH_NEWLINE, - write::PRINTLN_EMPTY_STRING, + write::WRITELN_EMPTY_STRING, write::WRITE_LITERAL, write::WRITE_WITH_NEWLINE, - write::WRITELN_EMPTY_STRING, ]); reg.register_lint_group("clippy::complexity", Some("clippy_complexity"), vec![ @@ -916,8 +916,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { bit_mask::BAD_BIT_MASK, bit_mask::INEFFECTIVE_BIT_MASK, booleans::LOGIC_BUG, - copies::IF_SAME_THEN_ELSE, copies::IFS_SAME_COND, + copies::IF_SAME_THEN_ELSE, derive::DERIVE_HASH_XOR_EQ, drop_forget_ref::DROP_COPY, drop_forget_ref::DROP_REF, diff --git a/util/update_lints.py b/util/update_lints.py index 221069d353c..4467b5c0cf7 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -10,245 +10,11 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. - -# Generate a Markdown table of all lints, and put it in README.md. -# With -n option, only print the new table to stdout. -# With -c option, print a warning and set exit status to 1 if a file would be -# changed. - -import os -import re import sys -from subprocess import call - -declare_deprecated_lint_re = re.compile(r''' - declare_deprecated_lint! \s* [{(] \s* - pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* - " (?P(?:[^"\\]+|\\.)*) " \s* [})] -''', re.VERBOSE | re.DOTALL) - -declare_clippy_lint_re = re.compile(r''' - declare_clippy_lint! \s* [{(] \s* - pub \s+ (?P[A-Z_][A-Z_0-9]*) \s*,\s* - (?P[a-z_]+) \s*,\s* - " (?P(?:[^"\\]+|\\.)*) " \s* [})] -''', re.VERBOSE | re.DOTALL) - -nl_escape_re = re.compile(r'\\\n\s*') - -docs_link = 'https://rust-lang-nursery.github.io/rust-clippy/master/index.html' - - -def collect(deprecated_lints, clippy_lints, fn): - """Collect all lints from a file. - - Adds entries to the lints list as `(module, name, level, desc)`. - """ - with open(fn) as fp: - code = fp.read() - - for match in declare_deprecated_lint_re.finditer(code): - # remove \-newline escapes from description string - desc = nl_escape_re.sub('', match.group('desc')) - deprecated_lints.append((os.path.splitext(os.path.basename(fn))[0], - match.group('name').lower(), - desc.replace('\\"', '"'))) - - for match in declare_clippy_lint_re.finditer(code): - # remove \-newline escapes from description string - desc = nl_escape_re.sub('', match.group('desc')) - cat = match.group('cat') - if cat in ('internal', 'internal_warn'): - continue - module_name = os.path.splitext(os.path.basename(fn))[0] - if module_name == 'mod': - module_name = os.path.basename(os.path.dirname(fn)) - clippy_lints[cat].append((module_name, - match.group('name').lower(), - "allow", - desc.replace('\\"', '"'))) - - -def gen_group(lints): - """Write lint group (list of all lints in the form module::NAME).""" - for (module, name, _, _) in sorted(lints): - yield ' %s::%s,\n' % (module, name.upper()) - - -def gen_mods(lints): - """Declare modules""" - - for module in sorted(set(lint[0] for lint in lints)): - yield 'pub mod %s;\n' % module - - -def gen_deprecated(lints): - """Declare deprecated lints""" - - for lint in lints: - yield ' store.register_removed(\n' - yield ' "%s",\n' % lint[1] - yield ' "%s",\n' % lint[2] - yield ' );\n' - - -def replace_region(fn, region_start, region_end, callback, - replace_start=True, write_back=True): - """Replace a region in a file delimited by two lines matching regexes. - - A callback is called to write the new region. If `replace_start` is true, - the start delimiter line is replaced as well. The end delimiter line is - never replaced. - """ - # read current content - with open(fn) as fp: - lines = list(fp) - - found = False - - # replace old region with new region - new_lines = [] - in_old_region = False - for line in lines: - if in_old_region: - if re.search(region_end, line): - in_old_region = False - new_lines.extend(callback()) - new_lines.append(line) - elif re.search(region_start, line): - if not replace_start: - new_lines.append(line) - # old region starts here - in_old_region = True - found = True - else: - new_lines.append(line) - - if not found: - print("regex " + region_start + " not found") - - # write back to file - if write_back: - with open(fn, 'w') as fp: - fp.writelines(new_lines) - - # if something changed, return true - return lines != new_lines - - -def main(print_only=False, check=False): - deprecated_lints = [] - clippy_lints = { - "correctness": [], - "style": [], - "complexity": [], - "perf": [], - "restriction": [], - "pedantic": [], - "cargo": [], - "nursery": [], - } - - # check directory - if not os.path.isfile('clippy_lints/src/lib.rs'): - print('Error: call this script from clippy checkout directory!') - return - - # collect all lints from source files - for root, dirs, files in os.walk('clippy_lints/src'): - for fn in files: - if fn.endswith('.rs'): - collect(deprecated_lints, clippy_lints, - os.path.join(root, fn)) - - # determine version - with open('Cargo.toml') as fp: - for line in fp: - if line.startswith('version ='): - clippy_version = line.split()[2].strip('"') - break - else: - print('Error: version not found in Cargo.toml!') - return - - all_lints = [] - clippy_lint_groups = [ - "correctness", - "style", - "complexity", - "perf", - ] - clippy_lint_list = [] - for x in clippy_lint_groups: - clippy_lint_list += clippy_lints[x] - for _, value in clippy_lints.iteritems(): - all_lints += value - - if print_only: - call(["./util/dev", "update_lints", "--print-only"]) - return - - # update the lint counter in README.md - changed = replace_region( - 'README.md', - r'^\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)$', "", - lambda: ['[There are %d lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)\n' % - (len(all_lints))], - write_back=not check) - - # update the links in the CHANGELOG - changed |= replace_region( - 'CHANGELOG.md', - "", - "", - lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], docs_link) for l in - sorted(all_lints + deprecated_lints, - key=lambda l: l[1])], - replace_start=False, write_back=not check) - - # update version of clippy_lints in Cargo.toml - changed |= replace_region( - 'Cargo.toml', r'# begin automatic update', '# end automatic update', - lambda: ['clippy_lints = { version = "%s", path = "clippy_lints" }\n' % - clippy_version], - replace_start=False, write_back=not check) - - # update version of clippy_lints in Cargo.toml - changed |= replace_region( - 'clippy_lints/Cargo.toml', r'# begin automatic update', '# end automatic update', - lambda: ['version = "%s"\n' % clippy_version], - replace_start=False, write_back=not check) - - # update the `pub mod` list - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'begin lints modules', r'end lints modules', - lambda: gen_mods(all_lints), - replace_start=False, write_back=not check) - - # same for "clippy::*" lint collections - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy::all"', r'\]\);', - lambda: gen_group(clippy_lint_list), - replace_start=False, write_back=not check) - - for key, value in clippy_lints.iteritems(): - # same for "clippy::*" lint collections - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'reg.register_lint_group\("clippy::' + key + r'"', r'\]\);', - lambda: gen_group(value), - replace_start=False, write_back=not check) - - # same for "deprecated" lint collection - changed |= replace_region( - 'clippy_lints/src/lib.rs', r'begin deprecated lints', r'end deprecated lints', - lambda: gen_deprecated(deprecated_lints), - replace_start=False, - write_back=not check) - - if check and changed: - print('Please run util/update_lints.py to regenerate lints lists.') - return 1 +def main(): + print('Error: Please use `util/dev` to update lints') + return 1 if __name__ == '__main__': - sys.exit(main(print_only='-n' in sys.argv, check='-c' in sys.argv)) + sys.exit(main()) -- cgit 1.4.1-3-g733a5 From f6194f33d23a90d56dcb00634109d0fa9b92cd3f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 4 Nov 2018 22:05:12 +0100 Subject: Fix false positive in check mode caused by `gen_deprecated` `gen_deprecated` should never have created the string with linebreaks. Using a single string broke the check because the changed lines were different. --- clippy_dev/src/lib.rs | 89 +++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index d1ba13bbe9d..5e1a454195e 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -114,19 +114,22 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. pub fn gen_deprecated(lints: &[Lint]) -> Vec { - lints.iter() - .filter_map(|l| { - l.clone().deprecation.and_then(|depr_text| { - Some( - format!( - " store.register_removed(\n \"{}\",\n \"{}\",\n );", - l.name, - depr_text + itertools::flatten( + lints + .iter() + .filter_map(|l| { + l.clone().deprecation.and_then(|depr_text| { + Some( + vec![ + " store.register_removed(".to_string(), + format!(" \"{}\",", l.name), + format!(" \"{}\",", depr_text), + " );".to_string() + ] ) - ) + }) }) - }) - .collect() + ).collect() } /// Gathers all files in `src/clippy_lints` and gathers all lints inside @@ -258,6 +261,7 @@ pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_sta // is incorrect. eprintln!("error: regex `{:?}` not found. You may have to update it.", start); } + FileChange { changed: lines.ne(new_lines.clone()), new_lines: new_lines.join("\n") @@ -305,38 +309,40 @@ declare_deprecated_lint! { #[test] fn test_replace_region() { - let text = r#" -abc -123 -789 -def -ghi"#; - let expected = r#" -abc -hello world -def -ghi"#; + let text = "\nabc\n123\n789\ndef\nghi"; + let expected = FileChange { + changed: true, + new_lines: "\nabc\nhello world\ndef\nghi".to_string() + }; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { vec!["hello world".to_string()] - }).new_lines; + }); assert_eq!(expected, result); } #[test] fn test_replace_region_with_start() { - let text = r#" -abc -123 -789 -def -ghi"#; - let expected = r#" -hello world -def -ghi"#; + let text = "\nabc\n123\n789\ndef\nghi"; + let expected = FileChange { + changed: true, + new_lines: "\nhello world\ndef\nghi".to_string() + }; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { vec!["hello world".to_string()] - }).new_lines; + }); + assert_eq!(expected, result); +} + +#[test] +fn test_replace_region_no_changes() { + let text = "123\n456\n789"; + let expected = FileChange { + changed: false, + new_lines: "123\n456\n789".to_string() + }; + let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || { + vec![] + }); assert_eq!(expected, result); } @@ -390,14 +396,19 @@ fn test_gen_changelog_lint_list() { fn test_gen_deprecated() { let lints = vec![ Lint::new("should_assert_eq", "group1", "abc", Some("has been superseeded by should_assert_eq2"), "module_name"), + Lint::new("another_deprecated", "group2", "abc", Some("will be removed"), "module_name"), Lint::new("should_assert_eq2", "group2", "abc", None, "module_name") ]; let expected: Vec = vec![ - r#" store.register_removed( - "should_assert_eq", - "has been superseeded by should_assert_eq2", - );"#.to_string() - ]; + " store.register_removed(", + " \"should_assert_eq\",", + " \"has been superseeded by should_assert_eq2\",", + " );", + " store.register_removed(", + " \"another_deprecated\",", + " \"will be removed\",", + " );" + ].into_iter().map(String::from).collect(); assert_eq!(expected, gen_deprecated(&lints)); } -- cgit 1.4.1-3-g733a5 From 5b24f2302052e38c17827114c28a31205de17404 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 4 Nov 2018 22:08:18 +0100 Subject: Update println! formatting Co-Authored-By: phansch --- clippy_dev/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index c9b498f5d5a..901f59679fe 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -153,7 +153,7 @@ fn update_lints(update_mode: UpdateMode) { } if update_mode == UpdateMode::Check && file_change { - println!("Not all lints defined properly. Please run util/dev update_lints to make sure all lints are defined properly."); + println!("Not all lints defined properly. Please run `util/dev update_lints` to make sure all lints are defined properly."); std::process::exit(1); } } -- cgit 1.4.1-3-g733a5 From 745a619657943f2491a02020907c2de18163b0cd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 5 Nov 2018 07:11:25 +0100 Subject: Fix dogfood --- clippy_dev/src/main.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 901f59679fe..bfd98968c42 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -48,9 +48,9 @@ fn main() { if matches.is_present("print-only") { print_lints(); } else if matches.is_present("check") { - update_lints(UpdateMode::Check); + update_lints(&UpdateMode::Check); } else { - update_lints(UpdateMode::Change); + update_lints(&UpdateMode::Change); } } } @@ -75,7 +75,7 @@ fn print_lints() { println!("there are {} lints", lint_count); } -fn update_lints(update_mode: UpdateMode) { +fn update_lints(update_mode: &UpdateMode) { let lint_list: Vec = gather_all().collect(); let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); let lint_count = usable_lints.len(); @@ -85,7 +85,7 @@ fn update_lints(update_mode: UpdateMode) { r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#, "", true, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { vec![ format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count) @@ -98,7 +98,7 @@ fn update_lints(update_mode: UpdateMode) { "", "", false, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { gen_changelog_lint_list(lint_list.clone()) } ).changed; @@ -107,7 +107,7 @@ fn update_lints(update_mode: UpdateMode) { "begin deprecated lints", "end deprecated lints", false, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { gen_deprecated(&lint_list) } ).changed; @@ -116,7 +116,7 @@ fn update_lints(update_mode: UpdateMode) { "begin lints modules", "end lints modules", false, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { gen_modules_list(lint_list.clone()) } ).changed; @@ -126,7 +126,7 @@ fn update_lints(update_mode: UpdateMode) { r#"reg.register_lint_group\("clippy::all""#, r#"\]\);"#, false, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { // clippy::all should only include the following lint groups: let all_group_lints = usable_lints.clone().into_iter().filter(|l| { @@ -147,12 +147,12 @@ fn update_lints(update_mode: UpdateMode) { &format!("reg.register_lint_group\\(\"clippy::{}\"", lint_group), r#"\]\);"#, false, - update_mode == UpdateMode::Change, + update_mode == &UpdateMode::Change, || { gen_lint_group_list(lints.clone()) } ).changed; } - if update_mode == UpdateMode::Check && file_change { + if update_mode == &UpdateMode::Check && file_change { println!("Not all lints defined properly. Please run `util/dev update_lints` to make sure all lints are defined properly."); std::process::exit(1); } -- cgit 1.4.1-3-g733a5 From c20e17f8ee44e05067402960dc12794c377fbe03 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 6 Nov 2018 07:05:13 +0200 Subject: Remove `+` from `has_unary_equivalent` Rust doesn't has a unary + operator! --- clippy_lints/src/formatting.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 69aabcb7949..d06183cb52f 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -174,9 +174,8 @@ fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { } fn has_unary_equivalent(bin_op: ast::BinOpKind) -> bool { - //+, &, *, - - bin_op == ast::BinOpKind::Add - || bin_op == ast::BinOpKind::And + // &, *, - + bin_op == ast::BinOpKind::And || bin_op == ast::BinOpKind::Mul || bin_op == ast::BinOpKind::Sub } -- cgit 1.4.1-3-g733a5 From 460c2b317b9768593f084545f4ae812d612ccacc Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 10 Nov 2018 10:46:21 +0200 Subject: Fix `use_self` false positive This fixes the first error reported in issue #3410. --- clippy_lints/src/use_self.rs | 39 ++++++++++++++++++++++++--------------- tests/ui/use_self.rs | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b997d76d0e7..db393616ff2 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -73,7 +73,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { } struct TraitImplTyVisitor<'a, 'tcx: 'a> { - item_path: &'a Path, + item_type: ty::Ty<'tcx>, cx: &'a LateContext<'a, 'tcx>, trait_type_walker: ty::walk::TypeWalker<'tcx>, impl_type_walker: ty::walk::TypeWalker<'tcx>, @@ -85,21 +85,28 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { let impl_ty = self.impl_type_walker.next(); if let TyKind::Path(QPath::Resolved(_, path)) = &t.node { - if self.item_path.def == path.def { - let is_self_ty = if let def::Def::SelfTy(..) = path.def { - true - } else { - false - }; - if !is_self_ty && impl_ty != trait_ty { - // The implementation and trait types don't match which means that - // the concrete type was specified by the implementation but - // it didn't use `Self` - span_use_self_lint(self.cx, path); + // The implementation and trait types don't match which means that + // the concrete type was specified by the implementation + if impl_ty != trait_ty { + + if let Some(impl_ty) = impl_ty { + if self.item_type == impl_ty { + let is_self_ty = if let def::Def::SelfTy(..) = path.def { + true + } else { + false + }; + + if !is_self_ty { + span_use_self_lint(self.cx, path); + } + } } + } } + walk_ty(self, t) } @@ -110,7 +117,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { fn check_trait_method_impl_decl<'a, 'tcx: 'a>( cx: &'a LateContext<'a, 'tcx>, - item_path: &'a Path, + item_type: ty::Ty<'tcx>, impl_item: &ImplItem, impl_decl: &'tcx FnDecl, impl_trait_ref: &ty::TraitRef<'_>, @@ -151,7 +158,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( ) { let mut visitor = TraitImplTyVisitor { cx, - item_path, + item_type, trait_type_walker: trait_ty.walk(), impl_type_walker: impl_ty.walk(), }; @@ -192,7 +199,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); if let ImplItemKind::Method(MethodSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.node { - check_trait_method_impl_decl(cx, item_path, impl_item, impl_decl, &impl_trait_ref); + let item_type = cx.tcx.type_of(impl_def_id); + check_trait_method_impl_decl(cx, item_type, impl_item, impl_decl, &impl_trait_ref); + let body = cx.tcx.hir.body(*impl_body_id); visitor.visit_body(body); } else { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 073d64d5a4b..4c1ec2ad2b9 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -219,3 +219,17 @@ mod existential { } } } + +mod issue3410 { + + struct A; + struct B; + + trait Trait: Sized { + fn a(v: T); + } + + impl Trait> for Vec { + fn a(_: Vec) {} + } +} -- cgit 1.4.1-3-g733a5 From 5ade9ff44ebd466d5658a6666990c84a73dcec86 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 13 Nov 2018 06:15:33 +0200 Subject: Fix `use_self` false positive on `use` statements --- clippy_lints/src/use_self.rs | 5 +++++ tests/ui/use_self.rs | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index db393616ff2..ad4ced995ba 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -16,6 +16,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax_pos::symbol::keywords::SelfType; +use crate::syntax::ast::NodeId; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. @@ -234,6 +235,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { walk_path(self, path); } + fn visit_use(&mut self, _path: &'tcx Path, _id: NodeId, _hir_id: HirId) { + // Don't check use statements + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::All(&self.cx.tcx.hir) } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 4c1ec2ad2b9..60dc2d54d05 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -225,7 +225,7 @@ mod issue3410 { struct A; struct B; - trait Trait: Sized { + trait Trait { fn a(v: T); } @@ -233,3 +233,14 @@ mod issue3410 { fn a(_: Vec) {} } } + +mod issue3425 { + enum Enum { + A, + } + impl Enum { + fn a () { + use self::Enum::*; + } + } +} -- cgit 1.4.1-3-g733a5 From 866caabb7a1308ee263992414def2074b00db514 Mon Sep 17 00:00:00 2001 From: Yusuf Simonson Date: Tue, 13 Nov 2018 08:43:30 -0500 Subject: Check for common metadata --- CHANGELOG.md | 1 + Cargo.toml | 2 +- README.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/cargo_common_metadata.rs | 115 ++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 + 6 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/cargo_common_metadata.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index bdd01bfeecd..3237f76b4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -628,6 +628,7 @@ All notable changes to this project will be documented in this file. [`box_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#box_vec [`boxed_local`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#boxed_local [`builtin_type_shadow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#builtin_type_shadow +[`cargo_common_metadata`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cargo_common_metadata [`cast_lossless`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_lossless [`cast_possible_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_truncation [`cast_possible_wrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_wrap diff --git a/Cargo.toml b/Cargo.toml index 2293913f38e..0a1f3dabb93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } -cargo_metadata = "0.6" +cargo_metadata = "0.6.2" compiletest_rs = "0.3.16" lazy_static = "1.0" serde_derive = "1.0" diff --git a/README.md b/README.md index 0525788e64e..47db3a358e3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 287 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 288 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 8907dd3659c..fa1b22784bd 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -17,7 +17,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2018" [dependencies] -cargo_metadata = "0.6" +cargo_metadata = "0.6.2" itertools = "0.7" lazy_static = "1.0.2" matches = "0.1.7" diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs new file mode 100644 index 00000000000..1a053de27d1 --- /dev/null +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -0,0 +1,115 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! lint on missing cargo common metadata + +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::{ast::*, source_map::DUMMY_SP}; +use crate::utils::span_lint; + +use cargo_metadata; + +/// **What it does:** Checks to see if all common metadata is defined in +/// `Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata +/// +/// **Why is this bad?** It will be more difficult for users to discover the +/// purpose of the crate, and key information related to it. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```toml +/// # This `Cargo.toml` is missing an authors field: +/// [package] +/// name = "clippy" +/// version = "0.0.212" +/// description = "A bunch of helpful lints to avoid common pitfalls in Rust" +/// repository = "https://github.com/rust-lang-nursery/rust-clippy" +/// readme = "README.md" +/// license = "MIT/Apache-2.0" +/// keywords = ["clippy", "lint", "plugin"] +/// categories = ["development-tools", "development-tools::cargo-plugins"] +/// ``` +declare_clippy_lint! { + pub CARGO_COMMON_METADATA, + cargo, + "common metadata is defined in `Cargo.toml`" +} + +fn warning(cx: &EarlyContext<'_>, message: &str) { + span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, message); +} + +fn missing_warning(cx: &EarlyContext<'_>, package: &cargo_metadata::Package, field: &str) { + let message = format!("package `{}` is missing `{}` metadata", package.name, field); + warning(cx, &message); +} + +fn is_empty_str(value: &Option) -> bool { + match value { + None => true, + Some(value) if value.is_empty() => true, + _ => false + } +} + +fn is_empty_vec(value: &[String]) -> bool { + // This works because empty iterators return true + value.iter().all(|v| v.is_empty()) +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(CARGO_COMMON_METADATA) + } +} + +impl EarlyLintPass for Pass { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { + let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { + metadata + } else { + warning(cx, "could not read cargo metadata"); + return; + }; + + for package in metadata.packages { + if is_empty_vec(&package.authors) { + missing_warning(cx, &package, "package.authors"); + } + + if is_empty_str(&package.description) { + missing_warning(cx, &package, "package.description"); + } + + if is_empty_str(&package.license) { + missing_warning(cx, &package, "package.license"); + } + + if is_empty_str(&package.repository) { + missing_warning(cx, &package, "package.repository"); + } + + if is_empty_str(&package.readme) { + missing_warning(cx, &package, "package.readme"); + } + + if is_empty_vec(&package.keywords) { + missing_warning(cx, &package, "package.keywords"); + } + + if is_empty_vec(&package.categories) { + missing_warning(cx, &package, "package.categories"); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c93e9d57d67..6ebe9df6a1e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -96,6 +96,7 @@ pub mod blacklisted_name; pub mod block_in_if_condition; pub mod booleans; pub mod bytecount; +pub mod cargo_common_metadata; pub mod collapsible_if; pub mod const_static_lifetime; pub mod copies; @@ -444,6 +445,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box double_comparison::Pass); reg.register_late_lint_pass(box question_mark::Pass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); + reg.register_early_lint_pass(box cargo_common_metadata::Pass); reg.register_early_lint_pass(box multiple_crate_versions::Pass); reg.register_early_lint_pass(box wildcard_dependencies::Pass); reg.register_late_lint_pass(box map_unit_fn::Pass); @@ -985,6 +987,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ]); reg.register_lint_group("clippy::cargo", Some("clippy_cargo"), vec![ + cargo_common_metadata::CARGO_COMMON_METADATA, multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, wildcard_dependencies::WILDCARD_DEPENDENCIES, ]); -- cgit 1.4.1-3-g733a5 From e2e892b59b1f31d75a6d37302ebb9d25d67de4c3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 14 Nov 2018 08:01:39 +0200 Subject: Fix wrong suggestion for `redundant_closure_call` Fixes #1684 --- clippy_lints/src/misc_early.rs | 61 ++++++++++++++++++++++++++++---------- tests/ui/redundant_closure_call.rs | 5 ++++ 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index a2fd487078e..550d7f24210 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -15,7 +15,7 @@ use if_chain::if_chain; use std::char; use crate::syntax::ast::*; use crate::syntax::source_map::Span; -use crate::syntax::visit::FnKind; +use crate::syntax::visit::{FnKind, Visitor, walk_expr}; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; use crate::rustc_errors::Applicability; @@ -199,6 +199,31 @@ impl LintPass for MiscEarly { } } +// Used to find `return` statements or equivalents e.g. `?` +struct ReturnVisitor { + found_return: bool, +} + +impl ReturnVisitor { + fn new() -> ReturnVisitor { + ReturnVisitor { + found_return: false, + } + } +} + +impl<'ast> Visitor<'ast> for ReturnVisitor { + fn visit_expr(&mut self, ex: &'ast Expr) { + if let ExprKind::Ret(_) = ex.node { + self.found_return = true; + } else if let ExprKind::Try(_) = ex.node { + self.found_return = true; + } + + walk_expr(self, ex) + } +} + impl EarlyLintPass for MiscEarly { fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { for param in &gen.params { @@ -311,21 +336,25 @@ impl EarlyLintPass for MiscEarly { match expr.node { ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node { - span_lint_and_then( - cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| if decl.inputs.is_empty() { - let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion_with_applicability( - expr.span, - "Try doing something like: ", - hint, - Applicability::MachineApplicable, // snippet - ); - }, - ); + let mut visitor = ReturnVisitor::new(); + visitor.visit_expr(block); + if !visitor.found_return { + span_lint_and_then( + cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |db| if decl.inputs.is_empty() { + let hint = snippet(cx, block.span, "..").into_owned(); + db.span_suggestion_with_applicability( + expr.span, + "Try doing something like: ", + hint, + Applicability::MachineApplicable, // snippet + ); + }, + ); + } } }, ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node { diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index 4912e5fc1b4..e68cdc2c1d1 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -28,4 +28,9 @@ fn main() { i = closure(3); i = closure(4); + + #[allow(clippy::needless_return)] + (|| return 2)(); + (|| -> Option { None? })(); + (|| -> Result { r#try!(Err(2)) })(); } -- cgit 1.4.1-3-g733a5 From 3ba4c3a9b179be4ed7e169475914997270f13b77 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 14 Nov 2018 08:43:35 +0200 Subject: Fix `use_self` violation --- clippy_lints/src/misc_early.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 550d7f24210..8f2f36ff560 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -205,8 +205,8 @@ struct ReturnVisitor { } impl ReturnVisitor { - fn new() -> ReturnVisitor { - ReturnVisitor { + fn new() -> Self { + Self { found_return: false, } } -- cgit 1.4.1-3-g733a5 From 93324f1acfc1929b935f9fdfec5a0a319679fca5 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 14 Nov 2018 14:08:52 +0100 Subject: Fix "too" -> "foo" typo in format.rs --- clippy_lints/src/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 41046a98a34..bd9fa6f80be 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -21,7 +21,7 @@ use crate::rustc_errors::Applicability; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. /// -/// **Why is this bad?** There is no point of doing that. `format!("too")` can +/// **Why is this bad?** There is no point of doing that. `format!("foo")` can /// be replaced by `"foo".to_owned()` if you really need a `String`. The even /// worse `&format!("foo")` is often encountered in the wild. `format!("{}", /// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()` -- cgit 1.4.1-3-g733a5 From 2d0d41ff291bfb580cf1ce2d64ed32ee0b9aa37c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 15 Nov 2018 16:50:28 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/55852/ --- clippy_lints/src/misc_early.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 8f2f36ff560..4973db4a5e8 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -241,7 +241,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { + fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat, _: &mut bool) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; let type_name = npat.segments -- cgit 1.4.1-3-g733a5 From 1000fc5120b0c58649f8a09811982d4dcfebeba8 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 15 Nov 2018 17:03:17 +0100 Subject: Don't emit suggestion when inside of a macro --- clippy_lints/src/matches.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 4a704c3d52e..9e2dac8fef1 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -18,9 +18,9 @@ use std::collections::Bound; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, - remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, - span_note_and_lint, walk_ptrs_ty}; +use crate::utils::{expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type, + multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, + span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; use crate::rustc_errors::Applicability; @@ -457,7 +457,9 @@ fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: })); span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |db| { - multispan_sugg(db, msg.to_owned(), suggs); + if !in_macro(expr.span) { + multispan_sugg(db, msg.to_owned(), suggs); + } }); } } -- cgit 1.4.1-3-g733a5 From 655a2b4709136546e28961e1f6cccb45155983ff Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 15 Nov 2018 17:03:41 +0100 Subject: Add regression test --- tests/ui/ice-2636.rs | 32 ++++++++++++++++++++++++++++++++ tests/ui/ice-2636.stderr | 16 ++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/ui/ice-2636.rs create mode 100644 tests/ui/ice-2636.stderr diff --git a/tests/ui/ice-2636.rs b/tests/ui/ice-2636.rs new file mode 100644 index 00000000000..3ef9ea8f69f --- /dev/null +++ b/tests/ui/ice-2636.rs @@ -0,0 +1,32 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +enum Foo { + A, + B, + C, +} + +macro_rules! test_hash { + ($foo:expr, $($t:ident => $ord:expr),+ ) => { + use self::Foo::*; + match $foo { + $ ( & $t => $ord, + )* + }; + }; +} + +fn main() { + let a = Foo::A; + test_hash!(&a, A => 0, B => 1, C => 2); +} + diff --git a/tests/ui/ice-2636.stderr b/tests/ui/ice-2636.stderr new file mode 100644 index 00000000000..a0806af5da9 --- /dev/null +++ b/tests/ui/ice-2636.stderr @@ -0,0 +1,16 @@ +error: you don't need to add `&` to both the expression and the patterns + --> $DIR/ice-2636.rs:21:9 + | +21 | / match $foo { +22 | | $ ( & $t => $ord, +23 | | )* +24 | | }; + | |_________^ +... +30 | test_hash!(&a, A => 0, B => 1, C => 2); + | --------------------------------------- in this macro invocation + | + = note: `-D clippy::match-ref-pats` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 3a11cd428902feafdc70c279d2dbc950f580db3f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 17 Nov 2018 13:47:27 +0100 Subject: remove unused allow() attributes, NFC --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 1 - clippy_lints/src/enum_variants.rs | 2 -- clippy_lints/src/eta_reduction.rs | 1 - clippy_lints/src/lib.rs | 4 ++-- clippy_lints/src/minmax.rs | 1 - clippy_lints/src/panic_unimplemented.rs | 1 - clippy_lints/src/redundant_pattern_matching.rs | 1 - clippy_lints/src/types.rs | 4 ---- clippy_lints/src/utils/author.rs | 2 -- clippy_lints/src/utils/inspector.rs | 2 -- src/driver.rs | 1 - src/main.rs | 2 -- 13 files changed, 3 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 5d509ef76f3..67c0de93496 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -293,7 +293,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { instance, promoted: None, }; - + let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; let ret = miri_to_const(self.tcx, result); if ret.is_some() { diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index cac5d0da71d..9bead9c1d86 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -116,7 +116,6 @@ const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that imp const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements Copy. \ Forgetting a copy leaves the original intact."; -#[allow(missing_copy_implementations)] pub struct Pass; impl LintPass for Pass { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 16d1e40484d..121a33f9475 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -156,8 +156,6 @@ fn partial_rmatch(post: &str, name: &str) -> usize { .count() } -// FIXME: #600 -#[allow(clippy::while_let_on_iterator)] fn check_variant( cx: &EarlyContext<'_>, threshold: u64, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 59c7f8a36db..95191b471a8 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -15,7 +15,6 @@ use crate::rustc::hir::*; use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; use crate::rustc_errors::Applicability; -#[allow(missing_copy_implementations)] pub struct EtaPass; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ebe9df6a1e..3debe567cda 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -15,7 +15,7 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] -#![allow(clippy::shadow_reuse, clippy::missing_docs_in_private_items)] +#![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] @@ -1005,7 +1005,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { // only exists to let the dogfood integration test works. // Don't run clippy as an executable directly -#[allow(dead_code, clippy::print_stdout)] +#[allow(dead_code)] fn main() { panic!("Please use the cargo-clippy executable"); } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 222247307c8..4a3fcfc853e 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -35,7 +35,6 @@ declare_clippy_lint! { "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" } -#[allow(missing_copy_implementations)] pub struct MinMaxPass; impl LintPass for MinMaxPass { diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 003c9bdf084..68b989721af 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -52,7 +52,6 @@ declare_clippy_lint! { "`unimplemented!` should not be present in production code" } -#[allow(missing_copy_implementations)] pub struct Pass; impl LintPass for Pass { diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index 7c888b36503..130b1144329 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -63,7 +63,6 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - #[allow(clippy::similar_names)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node { match match_source { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 035ca2b0496..c9068be838f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -34,7 +34,6 @@ use crate::utils::paths; use crate::consts::{constant, Constant}; /// Handles all the linting of funky types -#[allow(missing_copy_implementations)] pub struct TypePass; /// **What it does:** Checks for use of `Box>` anywhere in the code. @@ -371,7 +370,6 @@ fn is_any_trait(t: &hir::Ty) -> bool { false } -#[allow(missing_copy_implementations)] pub struct LetPass; /// **What it does:** Checks for binding a unit value. @@ -447,7 +445,6 @@ declare_clippy_lint! { "comparing unit values" } -#[allow(missing_copy_implementations)] pub struct UnitCmp; impl LintPass for UnitCmp { @@ -1142,7 +1139,6 @@ declare_clippy_lint! { "usage of very complex types that might be better factored into `type` definitions" } -#[allow(missing_copy_implementations)] pub struct TypeComplexityPass { threshold: u64, } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 6650dd67b4f..d88a70e4e49 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -11,8 +11,6 @@ //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -#![allow(clippy::print_stdout, clippy::use_debug)] - use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 54ca0736c52..e750c1c9bce 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -8,8 +8,6 @@ // except according to those terms. -#![allow(clippy::print_stdout, clippy::use_debug)] - //! checks for attributes use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/src/driver.rs b/src/driver.rs index 9abe6bd91de..f99c37b8519 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -27,7 +27,6 @@ use std::convert::TryInto; use std::path::Path; use std::process::{exit, Command}; -#[allow(clippy::print_stdout)] fn show_version() { println!(env!("CARGO_PKG_VERSION")); } diff --git a/src/main.rs b/src/main.rs index 4a1dc487cea..be28fe12899 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,12 +41,10 @@ it to allow or deny lints from the code, eg.: #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] "#; -#[allow(clippy::print_stdout)] fn show_help() { println!("{}", CARGO_CLIPPY_HELP); } -#[allow(clippy::print_stdout)] fn show_version() { let version_info = rustc_tools_util::get_version_info!(); println!("{}", version_info); -- cgit 1.4.1-3-g733a5 From 246a77ebe8c9d640c76a82f3869c5272ba51346d Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 15 Nov 2018 16:50:28 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/55852/ --- clippy_lints/src/misc_early.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index a2fd487078e..1f5973dad16 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -216,7 +216,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { + fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat, _: &mut bool) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; let type_name = npat.segments -- cgit 1.4.1-3-g733a5 From e4be2b4e6411d1b144305adab6b8874d7d3448d9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 21 Nov 2018 01:58:27 -0800 Subject: Downgrade needless_pass_by_value to allow by default I noticed that I suppress this lint in many of my projects. https://github.com/search?q=needless_pass_by_value+user%3Adtolnay&type=Code https://github.com/search?q=needless_pass_by_value+user%3Aserde-rs&type=Code Upon further inspection, this lint has a *long* history of false positives (and several remaining). Generally I feel that this lint is the definition of pedantic and should not be linted by default. #[derive(Debug)] enum How { ThisWay, ThatWay, } // Are we really better off forcing the call sites to write f(&_)...? fn f(how: How) { println!("You want to do it {:?}", how); } fn main() { f(How::ThatWay); } --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/needless_pass_by_value.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3debe567cda..2dbe448c950 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -509,6 +509,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { misc_early::UNSEPARATED_LITERAL_SUFFIX, mut_mut::MUT_MUT, needless_continue::NEEDLESS_CONTINUE, + needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, non_expressive_names::SIMILAR_NAMES, replace_consts::REPLACE_CONSTS, shadow::SHADOW_UNRELATED, @@ -671,7 +672,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, - needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, needless_update::NEEDLESS_UPDATE, neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, neg_multiply::NEG_MULTIPLY, @@ -809,7 +809,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { misc_early::MIXED_CASE_HEX_LITERALS, misc_early::UNNEEDED_FIELD_PATTERN, mut_reference::UNNECESSARY_MUT_PASSED, - needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index d4257fd1aa9..ff8e0cc0e6e 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -54,7 +54,7 @@ use crate::rustc_errors::Applicability; /// ``` declare_clippy_lint! { pub NEEDLESS_PASS_BY_VALUE, - style, + pedantic, "functions taking arguments by value, but not consuming them in its body" } -- cgit 1.4.1-3-g733a5 From 4aae76464c75f6c8dc6e365a5076f28584782be7 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 21 Nov 2018 13:29:23 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/52591 --- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index b7646dd6fdf..11bdf2244b1 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let mut v = EscapeDelegate { cx, - set: NodeSet(), + set: NodeSet::default(), too_large_for_stack: self.too_large_for_stack, }; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 21b966a6bd9..ee990117014 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -141,7 +141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); then { if self.impling_types.is_none() { - let mut impls = NodeSet(); + let mut impls = NodeSet::default(); cx.tcx.for_each_impl(default_trait_id, |d| { if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) { -- cgit 1.4.1-3-g733a5 From 617d8610414c800f5a97b17b0d674ada2d92a4db Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 13:33:42 +0100 Subject: Enable rustup clippy to refer to the correct documentation --- clippy_lints/src/utils/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ad91acbcbfd..3a16c6a892b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -539,8 +539,11 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/v{}/index.html#{}", - env!("CARGO_PKG_VERSION"), + "for further information visit https://rust-lang-nursery.github.io/rust-clippy/{}/index.html#{}", + &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { + // extract just major + minor version and ignore patch versions + format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) + }), lint.name_lower().replacen("clippy::", "", 1) )); } -- cgit 1.4.1-3-g733a5 From 30b3bc8d80e4f2d084ea560a7a196f1a39c54660 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Wed, 21 Nov 2018 07:12:00 -0600 Subject: Document how to lint local Clippy changes with locally built Clippy --- CONTRIBUTING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50f61eb1e67..227e12e145c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -152,6 +152,18 @@ Manually testing against an example file is useful if you have added some local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. +### Running Clippy Against Clippy + +Clippy CI runs all lints defined in the version of the Clippy being tested pass +(that is, don’t report any suggestions). You can avoid prolonging the CI +feedback cycle for PRs you submit by running these lints yourself ahead of time +and addressing any issues found: + +``` +cargo build +`pwd`/target/debug/cargo-clippy clippy --all-targets --all-features -- -D clippy::all -D clippy::internal -D clippy::pedantic +``` + ### How Clippy works Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. -- cgit 1.4.1-3-g733a5 From 4450b3e47a33e13b890e7e5b41084c89148fae72 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Wed, 21 Nov 2018 07:16:03 -0600 Subject: Fix awkward wording --- CONTRIBUTING.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 227e12e145c..bb0da592851 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -152,12 +152,12 @@ Manually testing against an example file is useful if you have added some local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. -### Running Clippy Against Clippy +### Linting Clippy with your changes locally -Clippy CI runs all lints defined in the version of the Clippy being tested pass -(that is, don’t report any suggestions). You can avoid prolonging the CI -feedback cycle for PRs you submit by running these lints yourself ahead of time -and addressing any issues found: +Clippy CI only passes if all lints defined in the version of the Clippy being +tested pass (that is, don’t report any suggestions). You can avoid prolonging +the CI feedback cycle for PRs you submit by running these lints yourself ahead +of time and addressing any issues found: ``` cargo build -- cgit 1.4.1-3-g733a5 From 67c32eb2c45b30af9e0d22a2220a50fac8439f59 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Tue, 20 Nov 2018 19:57:53 -0600 Subject: Update trivially_copy_pass_by_ref with Trait examples --- tests/ui/trivially_copy_pass_by_ref.rs | 19 +++++++++++ tests/ui/trivially_copy_pass_by_ref.stderr | 52 +++++++++++++++--------------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index cebe15b2cc8..2a0dc22bfef 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -18,6 +18,11 @@ struct Foo(u32); #[derive(Copy, Clone)] struct Bar([u8; 24]); +#[derive(Copy, Clone)] +pub struct Color { + pub r: u8, pub g: u8, pub b: u8, pub a: u8, +} + struct FooRef<'a> { foo: &'a Foo, } @@ -80,6 +85,20 @@ impl Bar { } } +trait MyTrait { + fn trait_method(&self, _foo: &Foo); +} + +pub trait MyTrait2 { + fn trait_method2(&self, _color: &Color); +} + +impl MyTrait for Foo { + fn trait_method(&self, _foo: &Foo) { + unimplemented!() + } +} + fn main() { let (mut foo, bar) = (Foo(0), Bar([0; 24])); let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0); diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 2026d4c00d8..d3610c10ef8 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:11 + --> $DIR/trivially_copy_pass_by_ref.rs:57:11 | -52 | fn bad(x: &u32, y: &Foo, z: &Baz) { +57 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:20 + --> $DIR/trivially_copy_pass_by_ref.rs:57:20 | -52 | fn bad(x: &u32, y: &Foo, z: &Baz) { +57 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:52:29 + --> $DIR/trivially_copy_pass_by_ref.rs:57:29 | -52 | fn bad(x: &u32, y: &Foo, z: &Baz) { +57 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:62:12 + --> $DIR/trivially_copy_pass_by_ref.rs:67:12 | -62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:62:22 + --> $DIR/trivially_copy_pass_by_ref.rs:67:22 | -62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:62:31 + --> $DIR/trivially_copy_pass_by_ref.rs:67:31 | -62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:62:40 + --> $DIR/trivially_copy_pass_by_ref.rs:67:40 | -62 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:16 + --> $DIR/trivially_copy_pass_by_ref.rs:70:16 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:25 + --> $DIR/trivially_copy_pass_by_ref.rs:70:25 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:34 + --> $DIR/trivially_copy_pass_by_ref.rs:70:34 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:79:16 + --> $DIR/trivially_copy_pass_by_ref.rs:84:16 | -79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:79:25 + --> $DIR/trivially_copy_pass_by_ref.rs:84:25 | -79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:79:34 + --> $DIR/trivially_copy_pass_by_ref.rs:84:34 | -79 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 92f7f9061c1383d6f8f5c8fbf15baa145c653d4c Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Tue, 20 Nov 2018 18:49:15 -0600 Subject: issue#3318 run trivially_copy_pass_by_ref for traits --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 134 +++++++++++++++++-------- 1 file changed, 93 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 61a2a9ded44..3d667cb5ea3 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -18,12 +18,13 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::rustc::ty::TyKind; +use crate::rustc::ty::FnSig; use crate::rustc::session::config::Config as SessionConfig; use crate::rustc_target::spec::abi::Abi; use crate::rustc_target::abi::LayoutOf; use crate::syntax::ast::NodeId; use crate::syntax_pos::Span; -use crate::utils::{in_macro, is_copy, is_self, span_lint_and_sugg, snippet}; +use crate::utils::{in_macro, is_copy, is_self_ty, span_lint_and_sugg, snippet}; /// **What it does:** Checks for functions taking arguments by reference, where /// the argument type is `Copy` and small enough to be more efficient to always @@ -67,7 +68,7 @@ pub struct TriviallyCopyPassByRef { limit: u64, } -impl TriviallyCopyPassByRef { +impl<'a, 'tcx> TriviallyCopyPassByRef { pub fn new(limit: Option, target: &SessionConfig) -> Self { let limit = limit.unwrap_or_else(|| { let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64; @@ -80,6 +81,84 @@ impl TriviallyCopyPassByRef { }); Self { limit } } + + fn check_trait_method( + &mut self, + cx: &LateContext<'_, 'tcx>, + item: &TraitItemRef + ) { + let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id); + let method_sig = cx.tcx.fn_sig(method_def_id); + let method_sig = cx.tcx.erase_late_bound_regions(&method_sig); + + let decl = match cx.tcx.hir.fn_decl(item.id.node_id) { + Some(b) => b, + None => return, + }; + + self.check_poly_fn(cx, &decl, &method_sig, None); + } + + fn check_poly_fn( + &mut self, + cx: &LateContext<'_, 'tcx>, + decl: &FnDecl, + sig: &FnSig<'tcx>, + span: Option, + ) { + // Use lifetimes to determine if we're returning a reference to the + // argument. In that case we can't switch to pass-by-value as the + // argument will not live long enough. + let output_lts = match sig.output().sty { + TyKind::Ref(output_lt, _, _) => vec![output_lt], + TyKind::Adt(_, substs) => substs.regions().collect(), + _ => vec![], + }; + + for (input, &ty) in decl.inputs.iter().zip(sig.inputs()) { + // All spans generated from a proc-macro invocation are the same... + match span { + Some(s) if s == input.span => return, + _ => (), + } + + if_chain! { + if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty; + if !output_lts.contains(&input_lt); + if is_copy(cx, ty); + if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); + if size <= self.limit; + if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; + then { + let value_type = if is_self_ty(decl_ty) { + "self".into() + } else { + snippet(cx, decl_ty.span, "_").into() + }; + span_lint_and_sugg( + cx, + TRIVIALLY_COPY_PASS_BY_REF, + input.span, + "this argument is passed by reference, but would be more efficient if passed by value", + "consider passing by value instead", + value_type); + } + } + } + } + + fn check_trait_items( + &mut self, + cx: &LateContext<'_, '_>, + trait_items: &[TraitItemRef] + ) { + for item in trait_items { + match item.kind { + AssociatedItemKind::Method{ has_self: _ } => self.check_trait_method(cx, item), + _ => (), + } + } + } } impl LintPass for TriviallyCopyPassByRef { @@ -89,12 +168,22 @@ impl LintPass for TriviallyCopyPassByRef { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { + if in_macro(item.span) { + return; + } + match item.node { + ItemKind::Trait(_, _, _, _, ref trait_items) => self.check_trait_items(cx, trait_items), + _ => (), + } + } + fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl, - body: &'tcx Body, + _body: &'tcx Body, span: Span, node_id: NodeId, ) { @@ -131,43 +220,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); - // Use lifetimes to determine if we're returning a reference to the - // argument. In that case we can't switch to pass-by-value as the - // argument will not live long enough. - let output_lts = match fn_sig.output().sty { - TyKind::Ref(output_lt, _, _) => vec![output_lt], - TyKind::Adt(_, substs) => substs.regions().collect(), - _ => vec![], - }; - - for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { - // All spans generated from a proc-macro invocation are the same... - if span == input.span { - return; - } - - if_chain! { - if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty; - if !output_lts.contains(&input_lt); - if is_copy(cx, ty); - if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); - if size <= self.limit; - if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node; - then { - let value_type = if is_self(arg) { - "self".into() - } else { - snippet(cx, decl_ty.span, "_").into() - }; - span_lint_and_sugg( - cx, - TRIVIALLY_COPY_PASS_BY_REF, - input.span, - "this argument is passed by reference, but would be more efficient if passed by value", - "consider passing by value instead", - value_type); - } - } - } + self.check_poly_fn(cx, decl, &fn_sig, Some(span)); } } -- cgit 1.4.1-3-g733a5 From ca4803101f95455b0436cefdf0e7cfecf259ca97 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Tue, 20 Nov 2018 19:59:02 -0600 Subject: Update trivially_copy_pass_by_ref with Trait stderr output --- tests/ui/trivially_copy_pass_by_ref.stderr | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index d3610c10ef8..3fb577d3edb 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -78,5 +78,17 @@ error: this argument is passed by reference, but would be more efficient if pass 84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` -error: aborting due to 13 previous errors +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:89:34 + | +89 | fn trait_method(&self, _foo: &Foo); + | ^^^^ help: consider passing by value instead: `Foo` + +error: this argument is passed by reference, but would be more efficient if passed by value + --> $DIR/trivially_copy_pass_by_ref.rs:93:37 + | +93 | fn trait_method2(&self, _color: &Color); + | ^^^^^^ help: consider passing by value instead: `Color` + +error: aborting due to 15 previous errors -- cgit 1.4.1-3-g733a5 From cb5e327c58576feb8bcafcb59b698c65be9e4833 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Tue, 20 Nov 2018 21:21:07 -0600 Subject: Address travis CI lint failure --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 3d667cb5ea3..8d442cd1b35 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { ) { for item in trait_items { match item.kind { - AssociatedItemKind::Method{ has_self: _ } => self.check_trait_method(cx, item), + AssociatedItemKind::Method{..} => self.check_trait_method(cx, item), _ => (), } } -- cgit 1.4.1-3-g733a5 From d4a6ee4a0c8308342c60e6b597872c19a5c6704c Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Wed, 21 Nov 2018 06:08:33 -0600 Subject: Fix nit Co-Authored-By: waynr --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8d442cd1b35..d811ce4ecb9 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { for (input, &ty) in decl.inputs.iter().zip(sig.inputs()) { // All spans generated from a proc-macro invocation are the same... match span { - Some(s) if s == input.span => return, + Some(s) if s == input.span => return, _ => (), } -- cgit 1.4.1-3-g733a5 From 1fed72bad4a7740cab5b5f607018a089f6d0132a Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Wed, 21 Nov 2018 06:05:52 -0600 Subject: Address 'clippy::single-match' dogfood lint --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index d811ce4ecb9..2929752bbb2 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -153,9 +153,8 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { trait_items: &[TraitItemRef] ) { for item in trait_items { - match item.kind { - AssociatedItemKind::Method{..} => self.check_trait_method(cx, item), - _ => (), + if let AssociatedItemKind::Method{..} = item.kind { + self.check_trait_method(cx, item); } } } @@ -172,9 +171,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { if in_macro(item.span) { return; } - match item.node { - ItemKind::Trait(_, _, _, _, ref trait_items) => self.check_trait_items(cx, trait_items), - _ => (), + if let ItemKind::Trait(_, _, _, _, ref trait_items) = item.node { + self.check_trait_items(cx, trait_items); } } -- cgit 1.4.1-3-g733a5 From f5929e07977215d2c5d94ae5bda30b38dae21b86 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 22 Nov 2018 04:40:09 +0100 Subject: rust-lang-nursery/rust-clippy => rust-lang/rust-clippy --- .travis.yml | 6 +++--- CONTRIBUTING.md | 22 +++++++++++----------- Cargo.toml | 6 +++--- README.md | 8 ++++---- clippy_dev/src/lib.rs | 2 +- clippy_dev/src/main.rs | 4 ++-- clippy_dummy/Cargo.toml | 2 +- clippy_dummy/crates-readme.md | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/README.md | 2 +- clippy_lints/src/attrs.rs | 3 +-- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- mini-macro/Cargo.toml | 2 +- tests/run-pass/ice-1782.rs | 2 +- tests/run-pass/ice-2499.rs | 2 +- tests/run-pass/ice-2594.rs | 2 +- tests/run-pass/ice-2760.rs | 2 +- tests/run-pass/ice-2774.rs | 2 +- tests/run-pass/issues_loop_mut_cond.rs | 6 +++--- tests/ui/booleans.rs | 2 +- tests/ui/collapsible_if.rs | 2 +- tests/ui/doc.rs | 4 ++-- tests/ui/module_inception.rs | 2 +- tests/ui/single_char_pattern.rs | 2 +- util/gh-pages/index.html | 2 +- util/gh-pages/versions.html | 2 +- 30 files changed, 51 insertions(+), 52 deletions(-) diff --git a/.travis.yml b/.travis.yml index 50967e4b906..af209ca96d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,14 +52,14 @@ matrix: - os: windows env: BASE_TEST=true - env: INTEGRATION=rust-lang/cargo - - env: INTEGRATION=rust-lang-nursery/rand + - env: INTEGRATION=rust-random/rand - env: INTEGRATION=rust-lang-nursery/stdsimd - - env: INTEGRATION=rust-lang-nursery/rustfmt + - env: INTEGRATION=rust-lang/rustfmt - env: INTEGRATION=rust-lang-nursery/futures-rs - env: INTEGRATION=rust-lang-nursery/failure - env: INTEGRATION=rust-lang-nursery/log - env: INTEGRATION=rust-lang-nursery/chalk - - env: INTEGRATION=rust-lang-nursery/rls + - env: INTEGRATION=rust-lang/rls - env: INTEGRATION=chronotope/chrono - env: INTEGRATION=serde-rs/serde - env: INTEGRATION=Geal/nom diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bb0da592851..5bc9e99a28f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,27 +35,27 @@ High level approach: All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. -Some issues are easier than others. The [`good first issue`](https://github.com/rust-lang-nursery/rust-clippy/labels/good%20first%20issue) +Some issues are easier than others. The [`good first issue`](https://github.com/rust-lang/rust-clippy/labels/good%20first%20issue) label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! -Issues marked [`T-AST`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) involve simple +Issues marked [`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) involve simple matching of the syntax tree structure, and are generally easier than -[`T-middle`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues, which involve types +[`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues, which involve types and resolved paths. -[`T-AST`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out +[`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast). Usually the lint will end up to be a nested series of matches and ifs, -[like so](https://github.com/rust-lang-nursery/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). +[like so](https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). -[`E-medium`](https://github.com/rust-lang-nursery/rust-clippy/labels/E-medium) issues are generally +[`E-medium`](https://github.com/rust-lang/rust-clippy/labels/E-medium) issues are generally pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified as `E-medium`, since they might be somewhat involved code wise, but not difficult per-se. -[`T-middle`](https://github.com/rust-lang-nursery/rust-clippy/labels/T-middle) issues can +[`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues can be more involved and require verifying types. The [`ty`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty) module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of @@ -249,10 +249,10 @@ All code in this repository is under the [Mozilla Public License, 2.0](https://w -[main_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/src/lib.rs#L14 -[lint_crate]: https://github.com/rust-lang-nursery/rust-clippy/tree/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src -[lint_crate_entry]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/lib.rs -[else_if_without_else]: https://github.com/rust-lang-nursery/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/else_if_without_else.rs +[main_entry]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/src/lib.rs#L14 +[lint_crate]: https://github.com/rust-lang/rust-clippy/tree/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src +[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/lib.rs +[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/else_if_without_else.rs [compiler_plugin]: https://doc.rust-lang.org/unstable-book/language-features/plugin.html#lint-plugins [plugin_registry]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html [reg_early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin/registry/struct.Registry.html#method.register_early_lint_pass diff --git a/Cargo.toml b/Cargo.toml index 0a1f3dabb93..359a6e43bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Oliver Schneider " ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" -repository = "https://github.com/rust-lang-nursery/rust-clippy" +repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" license = "MIT/Apache-2.0" keywords = ["clippy", "lint", "plugin"] @@ -19,8 +19,8 @@ edition = "2018" publish = false [badges] -travis-ci = { repository = "rust-lang-nursery/rust-clippy" } -appveyor = { repository = "rust-lang-nursery/rust-clippy" } +travis-ci = { repository = "rust-lang/rust-clippy" } +appveyor = { repository = "rust-lang/rust-clippy" } [lib] name = "clippy" diff --git a/README.md b/README.md index 47db3a358e3..68bca8896de 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in # Clippy -[![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy) +[![Build Status](https://travis-ci.org/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) [![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MIT/Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 288 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 288 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: @@ -22,7 +22,7 @@ We have a bunch of lint categories to allow you to choose how much Clippy is sup * `clippy::cargo` (checks against the cargo manifest) * **`clippy::correctness`** (code that is just outright wrong or very very useless) -More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas! +More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas! Only the following of those categories are enabled by default: @@ -84,7 +84,7 @@ in your code, you can use: cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` -*[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):* +*[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):* Be sure that Clippy was compiled with the same version of rustc that cargo invokes here! ### Travis CI diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 5e1a454195e..2dd04371c9b 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -32,7 +32,7 @@ lazy_static! { "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] "#).unwrap(); static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap(); - pub static ref DOCS_LINK: String = "https://rust-lang-nursery.github.io/rust-clippy/master/index.html".to_string(); + pub static ref DOCS_LINK: String = "https://rust-lang.github.io/rust-clippy/master/index.html".to_string(); } /// Lint data parsed from the Clippy source code. diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index bfd98968c42..0e82f6e0939 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -82,13 +82,13 @@ fn update_lints(update_mode: &UpdateMode) { let mut file_change = replace_region_in_file( "../README.md", - r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#, + r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang.github.io/rust-clippy/master/index.html\)"#, "", true, update_mode == &UpdateMode::Change, || { vec![ - format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count) + format!("[There are {} lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)", lint_count) ] } ).changed; diff --git a/clippy_dummy/Cargo.toml b/clippy_dummy/Cargo.toml index ed97cc45725..f99a23d93d0 100644 --- a/clippy_dummy/Cargo.toml +++ b/clippy_dummy/Cargo.toml @@ -7,7 +7,7 @@ readme = "crates-readme.md" description = "A bunch of helpful lints to avoid common pitfalls in Rust." build = 'build.rs' -repository = "https://github.com/rust-lang-nursery/rust-clippy" +repository = "https://github.com/rust-lang/rust-clippy" license = "MIT/Apache-2.0" keywords = ["clippy", "lint", "plugin"] diff --git a/clippy_dummy/crates-readme.md b/clippy_dummy/crates-readme.md index 0035073549c..4f4f4991ed4 100644 --- a/clippy_dummy/crates-readme.md +++ b/clippy_dummy/crates-readme.md @@ -6,4 +6,4 @@ rustup component add clippy-preview on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary. -See [the homepage](https://github.com/rust-lang-nursery/rust-clippy/#clippy) for more information \ No newline at end of file +See [the homepage](https://github.com/rust-lang/rust-clippy/#clippy) for more information diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index fa1b22784bd..f8f83152386 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -10,7 +10,7 @@ authors = [ "Martin Carton " ] description = "A bunch of helpful lints to avoid common pitfalls in Rust" -repository = "https://github.com/rust-lang-nursery/rust-clippy" +repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" license = "MPL-2.0" keywords = ["clippy", "lint", "plugin"] diff --git a/clippy_lints/README.md b/clippy_lints/README.md index 2fa5b0ae3e4..2724aa6a052 100644 --- a/clippy_lints/README.md +++ b/clippy_lints/README.md @@ -1,3 +1,3 @@ This crate contains Clippy lints. For the main crate, check [*crates.io*](https://crates.io/crates/clippy) or -[GitHub](https://github.com/rust-lang-nursery/rust-clippy). +[GitHub](https://github.com/rust-lang/rust-clippy). diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 593484aa1c6..58af069f1d9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -177,7 +177,7 @@ declare_clippy_lint! { /// /// **Known problems:** This lint doesn't detect crate level inner attributes, because they get /// processed before the PreExpansionPass lints get executed. See -/// [#3123](https://github.com/rust-lang-nursery/rust-clippy/pull/3123#issuecomment-422321765) +/// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765) /// /// **Example:** /// @@ -537,4 +537,3 @@ impl EarlyLintPass for CfgAttrPass { } } } - diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 1a053de27d1..c39c05c789b 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -31,7 +31,7 @@ use cargo_metadata; /// name = "clippy" /// version = "0.0.212" /// description = "A bunch of helpful lints to avoid common pitfalls in Rust" -/// repository = "https://github.com/rust-lang-nursery/rust-clippy" +/// repository = "https://github.com/rust-lang/rust-clippy" /// readme = "README.md" /// license = "MIT/Apache-2.0" /// keywords = ["clippy", "lint", "plugin"] diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index ac73dc1f5d5..c69173ac269 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -80,7 +80,7 @@ declare_clippy_lint! { /// /// **Known problems:** False positive possible with order dependent `match` /// (see issue -/// [#860](https://github.com/rust-lang-nursery/rust-clippy/issues/860)). +/// [#860](https://github.com/rust-lang/rust-clippy/issues/860)). /// /// **Example:** /// ```rust,ignore diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 95191b471a8..644c7fb3821 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -28,7 +28,7 @@ pub struct EtaPass; /// **Known problems:** If creating the closure inside the closure has a side- /// effect then moving the closure creation out will change when that side- /// effect runs. -/// See https://github.com/rust-lang-nursery/rust-clippy/issues/1439 for more +/// See https://github.com/rust-lang/rust-clippy/issues/1439 for more /// details. /// /// **Example:** diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c9068be838f..e5e3138acf6 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1532,7 +1532,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { /// `u8`. /// /// **Known problems:** -/// https://github.com/rust-lang-nursery/rust-clippy/issues/886 +/// https://github.com/rust-lang/rust-clippy/issues/886 /// /// **Example:** /// ```rust diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ad91acbcbfd..f7fbd5edb52 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -539,7 +539,7 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/v{}/index.html#{}", + "for further information visit https://rust-lang.github.io/rust-clippy/v{}/index.html#{}", env!("CARGO_PKG_VERSION"), lint.name_lower().replacen("clippy::", "", 1) )); diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml index ac3272030ba..2cdba4c3236 100644 --- a/mini-macro/Cargo.toml +++ b/mini-macro/Cargo.toml @@ -10,7 +10,7 @@ authors = [ ] license = "MPL-2.0" description = "A macro to test clippy's procedural macro checks" -repository = "https://github.com/rust-lang-nursery/rust-clippy" +repository = "https://github.com/rust-lang/rust-clippy" [lib] name = "clippy_mini_macro_test" diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs index 2101b4d3037..446aaacb2ee 100644 --- a/tests/run-pass/ice-1782.rs +++ b/tests/run-pass/ice-1782.rs @@ -12,7 +12,7 @@ /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` /// -/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/1782 +/// Issue: https://github.com/rust-lang/rust-clippy/issues/1782 use std::{mem, ptr}; diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index 1a973d737ba..30e8fa657f2 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -14,7 +14,7 @@ /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` /// -/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2499 +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2499 fn f(s: &[u8]) -> bool { let t = s[0] as char; diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs index 8bd77e3d6f0..738636b5e40 100644 --- a/tests/run-pass/ice-2594.rs +++ b/tests/run-pass/ice-2594.rs @@ -12,7 +12,7 @@ /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` /// -/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2594 +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2594 fn spanless_hash_ice() { let txt = "something"; diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index 7a83094ea76..fe7138b7f28 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -17,7 +17,7 @@ // // error[E0277]: the trait bound `T: Foo` is not satisfied // -// See https://github.com/rust-lang-nursery/rust-clippy/issues/2760 +// See https://github.com/rust-lang/rust-clippy/issues/2760 trait Foo { type Bar; diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index 67a77340d91..9959ec46d24 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -12,7 +12,7 @@ use std::collections::HashSet; -// See https://github.com/rust-lang-nursery/rust-clippy/issues/2774 +// See https://github.com/rust-lang/rust-clippy/issues/2774 #[derive(Eq, PartialEq, Debug, Hash)] pub struct Bar { diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs index c3deae9bafd..893866a2a34 100644 --- a/tests/run-pass/issues_loop_mut_cond.rs +++ b/tests/run-pass/issues_loop_mut_cond.rs @@ -10,14 +10,14 @@ #![allow(dead_code)] -/// Issue: https://github.com/rust-lang-nursery/rust-clippy/issues/2596 +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 pub fn loop_on_block_condition(u: &mut isize) { while { *u < 0 } { *u += 1; } } -/// https://github.com/rust-lang-nursery/rust-clippy/issues/2584 +/// https://github.com/rust-lang/rust-clippy/issues/2584 fn loop_with_unsafe_condition(ptr: *const u8) { let mut len = 0; while unsafe { *ptr.offset(len) } != 0 { @@ -25,7 +25,7 @@ fn loop_with_unsafe_condition(ptr: *const u8) { } } -/// https://github.com/rust-lang-nursery/rust-clippy/issues/2710 +/// https://github.com/rust-lang/rust-clippy/issues/2710 static mut RUNNING: bool = true; fn loop_on_static_condition() { unsafe { diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 962f03dc9cd..e63b6a75e8f 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -68,7 +68,7 @@ fn methods_with_negation() { let _ = !c ^ c || !a.is_some(); } -// Simplified versions of https://github.com/rust-lang-nursery/rust-clippy/issues/2638 +// Simplified versions of https://github.com/rust-lang/rust-clippy/issues/2638 // clippy::nonminimal_bool should only check the built-in Result and Some type, not // any other types like the following. enum CustomResultOk { Ok, Err(E) } diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 1bc866010fd..a8ec13ab669 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -153,7 +153,7 @@ fn main() { } - // The following tests check for the fix of https://github.com/rust-lang-nursery/rust-clippy/issues/798 + // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 if x == "hello" {// Not collapsible if y == "world" { println!("Hello world!"); diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 37f89de471f..d87142e9367 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -62,7 +62,7 @@ fn test_units() { } /// This test has [a link_with_underscores][chunked-example] inside it. See #823. -/// See also [the issue tracker](https://github.com/rust-lang-nursery/rust-clippy/search?q=clippy::doc_markdown&type=Issues) +/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues) /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. /// It can also be [inline_link2]. /// @@ -154,7 +154,7 @@ fn four_quotes() { /// See [NIST SP 800-56A, revision 2]. /// /// [NIST SP 800-56A, revision 2]: -/// https://github.com/rust-lang-nursery/rust-clippy/issues/902#issuecomment-261919419 +/// https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419 fn issue_902_comment() {} #[cfg_attr(feature = "a", doc = " ```")] diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index 333a8efec32..0676c4c29f0 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -24,7 +24,7 @@ mod foo { } } -// No warning. See . +// No warning. See . mod bar { #[allow(clippy::module_inception)] mod bar { diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 5e1231f1227..c3d846997ec 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -25,7 +25,7 @@ fn main() { // should have done this but produced an ICE // // We may not want to suggest changing these anyway - // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 + // See: https://github.com/rust-lang/rust-clippy/issues/650#issuecomment-184328984 x.split("ß"); x.split("ℝ"); x.split("💣"); diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 277eeaf39f4..1a8495951a4 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -125,7 +125,7 @@
- + Fork me on Github diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index 5678ebec722..169d3fa16d2 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -43,7 +43,7 @@
- + -- cgit 1.4.1-3-g733a5 From d48af43cdf8962e50c8634f0260374c0ac66691c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 22 Nov 2018 04:43:33 +0100 Subject: run "util/dev update_lints" --- CHANGELOG.md | 596 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 298 insertions(+), 298 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3237f76b4ae..fa05eca89d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -613,302 +613,302 @@ All notable changes to this project will be documented in this file. [configuration file]: ./rust-clippy#configuration -[`absurd_extreme_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons -[`almost_swapped`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#almost_swapped -[`approx_constant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant -[`assign_op_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#assign_op_pattern -[`assign_ops`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#assign_ops -[`bad_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#bad_bit_mask -[`blacklisted_name`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#blacklisted_name -[`block_in_if_condition_expr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_expr -[`block_in_if_condition_stmt`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt -[`bool_comparison`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#bool_comparison -[`borrow_interior_mutable_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const -[`borrowed_box`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#borrowed_box -[`box_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#box_vec -[`boxed_local`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#boxed_local -[`builtin_type_shadow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#builtin_type_shadow -[`cargo_common_metadata`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cargo_common_metadata -[`cast_lossless`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_lossless -[`cast_possible_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_truncation -[`cast_possible_wrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_possible_wrap -[`cast_precision_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_precision_loss -[`cast_ptr_alignment`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_ptr_alignment -[`cast_sign_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_sign_loss -[`char_lit_as_u8`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#char_lit_as_u8 -[`chars_last_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_last_cmp -[`chars_next_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_next_cmp -[`clone_double_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_double_ref -[`clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_copy -[`clone_on_ref_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_ref_ptr -[`cmp_nan`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_nan -[`cmp_null`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_null -[`cmp_owned`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cmp_owned -[`collapsible_if`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#collapsible_if -[`const_static_lifetime`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#const_static_lifetime -[`copy_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#copy_iterator -[`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute -[`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity -[`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation -[`declare_interior_mutable_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#declare_interior_mutable_const -[`default_trait_access`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#default_trait_access -[`deprecated_cfg_attr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_cfg_attr -[`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver -[`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof -[`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq -[`diverging_sub_expression`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#diverging_sub_expression -[`doc_markdown`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#doc_markdown -[`double_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_comparisons -[`double_neg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_neg -[`double_parens`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#double_parens -[`drop_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_copy -[`drop_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#drop_ref -[`duplicate_underscore_argument`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duplicate_underscore_argument -[`duration_subsec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#duration_subsec -[`else_if_without_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#else_if_without_else -[`empty_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum -[`empty_line_after_outer_attr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr -[`empty_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_loop -[`enum_clike_unportable_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant -[`enum_glob_use`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_glob_use -[`enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#enum_variant_names -[`eq_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eq_op -[`erasing_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#erasing_op -[`eval_order_dependence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#eval_order_dependence -[`excessive_precision`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#excessive_precision -[`expect_fun_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expect_fun_call -[`expl_impl_clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy -[`explicit_counter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_counter_loop -[`explicit_into_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_into_iter_loop -[`explicit_iter_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_iter_loop -[`explicit_write`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#explicit_write -[`extend_from_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extend_from_slice -[`extra_unused_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#extra_unused_lifetimes -[`fallible_impl_from`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fallible_impl_from -[`filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_map -[`filter_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#filter_next -[`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic -[`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp -[`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const -[`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast -[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation -[`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map -[`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option -[`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result -[`forget_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_copy -[`forget_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#forget_ref -[`get_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#get_unwrap -[`identity_conversion`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#identity_conversion -[`identity_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#identity_op -[`if_let_redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching -[`if_let_some_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_let_some_result -[`if_not_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_not_else -[`if_same_then_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#if_same_then_else -[`ifs_same_cond`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ifs_same_cond -[`implicit_hasher`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#implicit_hasher -[`inconsistent_digit_grouping`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping -[`indexing_slicing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#indexing_slicing -[`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask -[`infallible_destructuring_match`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infallible_destructuring_match -[`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter -[`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always -[`inline_fn_without_body`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_fn_without_body -[`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one -[`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic -[`into_iter_on_array`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#into_iter_on_array -[`into_iter_on_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#into_iter_on_ref -[`invalid_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_ref -[`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex -[`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons -[`items_after_statements`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#items_after_statements -[`iter_cloned_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_cloned_collect -[`iter_next_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_next_loop -[`iter_nth`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_nth -[`iter_skip_next`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iter_skip_next -[`iterator_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#iterator_step_by_zero -[`just_underscores_and_digits`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#just_underscores_and_digits -[`large_digit_groups`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_digit_groups -[`large_enum_variant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#large_enum_variant -[`len_without_is_empty`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#len_without_is_empty -[`len_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#len_zero -[`let_and_return`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_and_return -[`let_unit_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#let_unit_value -[`linkedlist`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#linkedlist -[`logic_bug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#logic_bug -[`manual_memcpy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_memcpy -[`manual_swap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#manual_swap -[`many_single_char_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#many_single_char_names -[`map_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_clone -[`map_entry`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_entry -[`map_flatten`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#map_flatten -[`match_as_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_as_ref -[`match_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_bool -[`match_overlapping_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_overlapping_arm -[`match_ref_pats`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_ref_pats -[`match_same_arms`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_same_arms -[`match_wild_err_arm`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#match_wild_err_arm -[`maybe_infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#maybe_infinite_iter -[`mem_discriminant_non_enum`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum -[`mem_forget`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_forget -[`mem_replace_option_with_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mem_replace_option_with_none -[`min_max`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#min_max -[`misaligned_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misaligned_transmute -[`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op -[`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items -[`missing_inline_in_public_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_inline_in_public_items -[`mistyped_literal_suffixes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes -[`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals -[`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception -[`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one -[`multiple_crate_versions`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#multiple_crate_versions -[`multiple_inherent_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#multiple_inherent_impl -[`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref -[`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut -[`mut_range_bound`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_range_bound -[`mutex_atomic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_atomic -[`mutex_integer`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_integer -[`naive_bytecount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#naive_bytecount -[`needless_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_bool -[`needless_borrow`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrow -[`needless_borrowed_reference`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_borrowed_reference -[`needless_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_collect -[`needless_continue`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_continue -[`needless_lifetimes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_lifetimes -[`needless_pass_by_value`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_pass_by_value -[`needless_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_range_loop -[`needless_return`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_return -[`needless_update`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#needless_update -[`neg_cmp_op_on_partial_ord`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord -[`neg_multiply`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#neg_multiply -[`never_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#never_loop -[`new_ret_no_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_ret_no_self -[`new_without_default`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_without_default -[`new_without_default_derive`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#new_without_default_derive -[`no_effect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#no_effect -[`non_ascii_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#non_ascii_literal -[`nonminimal_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonminimal_bool -[`nonsensical_open_options`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#nonsensical_open_options -[`not_unsafe_ptr_arg_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref -[`ok_expect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ok_expect -[`op_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#op_ref -[`option_map_or_none`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_or_none -[`option_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unit_fn -[`option_map_unwrap_or`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or -[`option_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else -[`option_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_option -[`option_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#option_unwrap_used -[`or_fun_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#or_fun_call -[`out_of_bounds_indexing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#out_of_bounds_indexing -[`overflow_check_conditional`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#overflow_check_conditional -[`panic_params`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panic_params -[`panicking_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panicking_unwrap -[`partialeq_ne_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#partialeq_ne_impl -[`possible_missing_comma`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#possible_missing_comma -[`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence -[`print_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_literal -[`print_stdout`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_stdout -[`print_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#print_with_newline -[`println_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#println_empty_string -[`ptr_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_arg -[`ptr_offset_with_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ptr_offset_with_cast -[`pub_enum_variant_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#pub_enum_variant_names -[`question_mark`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#question_mark -[`range_minus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_minus_one -[`range_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_plus_one -[`range_step_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_step_by_zero -[`range_zip_with_len`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#range_zip_with_len -[`redundant_clone`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_clone -[`redundant_closure`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure -[`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call -[`redundant_field_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_field_names -[`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern -[`redundant_pattern_matching`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern_matching -[`ref_in_deref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ref_in_deref -[`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro -[`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts -[`result_map_unit_fn`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unit_fn -[`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else -[`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used -[`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop -[`search_is_some`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#search_is_some -[`serde_api_misuse`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#serde_api_misuse -[`shadow_reuse`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_reuse -[`shadow_same`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_same -[`shadow_unrelated`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#shadow_unrelated -[`short_circuit_statement`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#short_circuit_statement -[`should_assert_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#should_assert_eq -[`should_implement_trait`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#should_implement_trait -[`similar_names`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#similar_names -[`single_char_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_char_pattern -[`single_match`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_match -[`single_match_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#single_match_else -[`str_to_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#str_to_string -[`string_add`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_add -[`string_add_assign`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_add_assign -[`string_extend_chars`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_extend_chars -[`string_lit_as_bytes`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_lit_as_bytes -[`string_to_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#string_to_string -[`stutter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#stutter -[`suspicious_arithmetic_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl -[`suspicious_assignment_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting -[`suspicious_else_formatting`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_else_formatting -[`suspicious_op_assign_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl -[`temporary_assignment`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_assignment -[`temporary_cstring_as_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr -[`too_many_arguments`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#too_many_arguments -[`toplevel_ref_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#toplevel_ref_arg -[`transmute_bytes_to_str`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_bytes_to_str -[`transmute_int_to_bool`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_bool -[`transmute_int_to_char`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_char -[`transmute_int_to_float`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_int_to_float -[`transmute_ptr_to_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr -[`transmute_ptr_to_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref -[`trivial_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivial_regex -[`trivially_copy_pass_by_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref -[`type_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#type_complexity -[`unicode_not_nfc`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unicode_not_nfc -[`unimplemented`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unimplemented -[`unit_arg`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_arg -[`unit_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unit_cmp -[`unknown_clippy_lints`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unknown_clippy_lints -[`unnecessary_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_cast -[`unnecessary_filter_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_filter_map -[`unnecessary_fold`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_fold -[`unnecessary_mut_passed`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_mut_passed -[`unnecessary_operation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_operation -[`unnecessary_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unnecessary_unwrap -[`unneeded_field_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unneeded_field_pattern -[`unreadable_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unreadable_literal -[`unsafe_removed_from_name`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unsafe_removed_from_name -[`unseparated_literal_suffix`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unseparated_literal_suffix -[`unstable_as_mut_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unstable_as_mut_slice -[`unstable_as_slice`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unstable_as_slice -[`unused_collect`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_collect -[`unused_io_amount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_io_amount -[`unused_label`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_label -[`unused_unit`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#unused_unit -[`use_debug`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_debug -[`use_self`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#use_self -[`used_underscore_binding`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#used_underscore_binding -[`useless_asref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_asref -[`useless_attribute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_attribute -[`useless_format`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_format -[`useless_let_if_seq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_let_if_seq -[`useless_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_transmute -[`useless_vec`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#useless_vec -[`verbose_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#verbose_bit_mask -[`while_immutable_condition`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_immutable_condition -[`while_let_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_loop -[`while_let_on_iterator`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#while_let_on_iterator -[`wildcard_dependencies`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wildcard_dependencies -[`write_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_literal -[`write_with_newline`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#write_with_newline -[`writeln_empty_string`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#writeln_empty_string -[`wrong_pub_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_pub_self_convention -[`wrong_self_convention`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_self_convention -[`wrong_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#wrong_transmute -[`zero_divided_by_zero`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_divided_by_zero -[`zero_prefixed_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_prefixed_literal -[`zero_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_ptr -[`zero_width_space`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_width_space +[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons +[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped +[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern +[`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops +[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask +[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name +[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_expr +[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt +[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison +[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const +[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box +[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec +[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local +[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow +[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata +[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless +[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation +[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap +[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss +[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment +[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss +[`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8 +[`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp +[`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp +[`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref +[`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy +[`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr +[`cmp_nan`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_nan +[`cmp_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_null +[`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned +[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if +[`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime +[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator +[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute +[`cyclomatic_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cyclomatic_complexity +[`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation +[`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const +[`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access +[`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr +[`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver +[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof +[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq +[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown +[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons +[`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg +[`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens +[`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy +[`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref +[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument +[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec +[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else +[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum +[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr +[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop +[`enum_clike_unportable_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant +[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use +[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names +[`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op +[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op +[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence +[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision +[`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call +[`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy +[`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop +[`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop +[`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop +[`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write +[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice +[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes +[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from +[`filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map +[`filter_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_next +[`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic +[`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp +[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const +[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast +[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation +[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map +[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option +[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result +[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy +[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref +[`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap +[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion +[`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op +[`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching +[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result +[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else +[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else +[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond +[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher +[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping +[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing +[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask +[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match +[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter +[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always +[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body +[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one +[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic +[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array +[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref +[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref +[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex +[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons +[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements +[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect +[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop +[`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth +[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next +[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero +[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits +[`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups +[`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant +[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty +[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero +[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return +[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value +[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist +[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug +[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy +[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap +[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names +[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone +[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry +[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten +[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref +[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool +[`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm +[`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats +[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms +[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm +[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter +[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum +[`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget +[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none +[`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max +[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute +[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op +[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items +[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items +[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes +[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals +[`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception +[`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one +[`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions +[`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl +[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_from_ref +[`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut +[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound +[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic +[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer +[`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/master/index.html#naive_bytecount +[`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool +[`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow +[`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference +[`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect +[`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue +[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes +[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value +[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop +[`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return +[`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update +[`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord +[`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply +[`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop +[`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self +[`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default +[`new_without_default_derive`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default_derive +[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect +[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal +[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool +[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options +[`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref +[`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect +[`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref +[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none +[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn +[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or +[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else +[`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option +[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used +[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call +[`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing +[`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional +[`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params +[`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap +[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl +[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma +[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence +[`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal +[`print_stdout`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout +[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline +[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string +[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg +[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast +[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names +[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark +[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one +[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one +[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero +[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len +[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone +[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call +[`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names +[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern +[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching +[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref +[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro +[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts +[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn +[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else +[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used +[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop +[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some +[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse +[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse +[`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same +[`shadow_unrelated`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_unrelated +[`short_circuit_statement`]: https://rust-lang.github.io/rust-clippy/master/index.html#short_circuit_statement +[`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_assert_eq +[`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait +[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names +[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern +[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match +[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string +[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add +[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign +[`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars +[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes +[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string +[`stutter`]: https://rust-lang.github.io/rust-clippy/master/index.html#stutter +[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl +[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting +[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting +[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl +[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment +[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr +[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments +[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str +[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool +[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char +[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float +[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr +[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref +[`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex +[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref +[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity +[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc +[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented +[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg +[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp +[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints +[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast +[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map +[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold +[`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed +[`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation +[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap +[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern +[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal +[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name +[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix +[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice +[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice +[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect +[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount +[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label +[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit +[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug +[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self +[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding +[`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref +[`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute +[`useless_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format +[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq +[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute +[`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec +[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask +[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition +[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop +[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator +[`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies +[`write_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_literal +[`write_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_with_newline +[`writeln_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#writeln_empty_string +[`wrong_pub_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_pub_self_convention +[`wrong_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention +[`wrong_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_transmute +[`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_divided_by_zero +[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal +[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr +[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space -- cgit 1.4.1-3-g733a5 From 0b8d3233046687383fbd7bbb600377e5c37f4d45 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 22 Nov 2018 04:50:00 +0100 Subject: missed another one in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68bca8896de..f2b0da3ae71 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ blacklisted-names = ["toto", "tata", "titi"] cyclomatic-complexity-threshold = 30 ``` -See the [list of lints](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the +See the [list of lints](https://rust-lang.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the meaning of the variables. To deactivate the “for further information visit *lint-link*” message you can -- cgit 1.4.1-3-g733a5 From c4b08a5b0cb4eeac8f95b46a25819d1d09e84c28 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 22 Nov 2018 07:53:59 +0100 Subject: s/file_map/source_map --- clippy_lints/src/utils/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ad91acbcbfd..db4c3046731 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -413,9 +413,9 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' /// Returns a new Span that covers the full last line of the given Span pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { - let file_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); - let line_no = file_map_and_line.line; - let line_start = &file_map_and_line.sf.lines[line_no]; + let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); + let line_no = source_map_and_line.line; + let line_start = &source_map_and_line.sf.lines[line_no]; Span::new(*line_start, span.hi(), span.ctxt()) } -- cgit 1.4.1-3-g733a5 From 2e26fdc2a86f03771a31b8a1e1a35cf8397cb69b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 13:33:42 +0100 Subject: Enable rustup clippy to refer to the correct documentation --- clippy_lints/src/utils/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 05356f8d385..410819136bc 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -507,8 +507,11 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/v{}/index.html#{}", - env!("CARGO_PKG_VERSION"), + "for further information visit https://rust-lang-nursery.github.io/rust-clippy/{}/index.html#{}", + &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { + // extract just major + minor version and ignore patch versions + format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) + }), lint.name_lower().replacen("clippy::", "", 1) )); } -- cgit 1.4.1-3-g733a5 From 1ee0c1a029d9ac9177fc334fd324d9752b436432 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 22 Nov 2018 18:04:34 +0100 Subject: dependencies: update pulldown-cmark from 0.1 to 0.2 --- clippy_lints/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index f8f83152386..67dcffbfe1b 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -28,7 +28,7 @@ serde = "1.0" serde_derive = "1.0" toml = "0.4" unicode-normalization = "0.1" -pulldown-cmark = "0.1" +pulldown-cmark = "0.2" url = "1.7.0" if_chain = "0.1.3" smallvec = { version = "0.6.5", features = ["union"] } -- cgit 1.4.1-3-g733a5 From 311c8e29b1686ca40c25826f798c31edaecd366e Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 23 Nov 2018 10:05:51 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/54071/ --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e5e3138acf6..d7adcd17981 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1064,8 +1064,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if_chain!{ if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; - if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi()); - if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi()); + if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi); + if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi); if from_align < to_align; // with c_void, we inherently need to trust the user if ! ( -- cgit 1.4.1-3-g733a5 From ce4f3010ecf6234e99fa06d9648824ebf53f7cf5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 23 Nov 2018 21:47:02 +0100 Subject: Travis: Remove `sudo: false` --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index af209ca96d0..8730535d629 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,6 @@ os: - osx - windows -sudo: false - branches: # Don't build these branches except: -- cgit 1.4.1-3-g733a5 From e0ccc9d9afa2b7800e288a6367422b2a2389f57e Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Fri, 19 Oct 2018 01:15:48 +0200 Subject: Add slow zero-filled vector initialization lint Add lint to detect slow zero-filled vector initialization. It detects when a vector is zero-filled with extended with `repeat(0).take(len)` or `resize(len, 0)`. This zero-fillings are usually slower than simply using `vec![0; len]`. --- clippy_lints/src/lib.rs | 3 + clippy_lints/src/slow_vector_initialization.rs | 304 +++++++++++++++++++++++++ tests/ui/slow_vector_initialization.rs | 63 +++++ tests/ui/slow_vector_initialization.stderr | 101 ++++++++ tests/ui/slow_vector_initialization.stdout | 0 5 files changed, 471 insertions(+) create mode 100644 clippy_lints/src/slow_vector_initialization.rs create mode 100644 tests/ui/slow_vector_initialization.rs create mode 100644 tests/ui/slow_vector_initialization.stderr create mode 100644 tests/ui/slow_vector_initialization.stdout diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2dbe448c950..cf754d48667 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -190,6 +190,7 @@ pub mod replace_consts; pub mod returns; pub mod serde_api; pub mod shadow; +pub mod slow_vector_initialization; pub mod strings; pub mod suspicious_trait_impl; pub mod swap; @@ -459,6 +460,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box non_copy_const::NonCopyConst); reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); + reg.register_late_lint_pass(box slow_vector_initialization::Pass); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -980,6 +982,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { methods::SINGLE_CHAR_PATTERN, misc::CMP_OWNED, mutex_atomic::MUTEX_ATOMIC, + slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, types::BOX_VEC, vec::USELESS_VEC, diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs new file mode 100644 index 00000000000..52855031a5a --- /dev/null +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -0,0 +1,304 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::hir::*; +use if_chain::if_chain; +use crate::syntax_pos::symbol::Symbol; +use crate::syntax::ast::{LitKind, NodeId}; +use crate::syntax::source_map::Span; +use crate::utils::{match_qpath, span_lint_and_then, SpanlessEq}; +use crate::utils::get_enclosing_block; +use crate::rustc_errors::{Applicability}; + +/// **What it does:** Checks slow zero-filled vector initialization +/// +/// **Why is this bad?** This structures are non-idiomatic and less efficient than simply using +/// `vec![len; 0]`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let mut vec1 = Vec::with_capacity(len); +/// vec1.resize(len, 0); +/// +/// let mut vec2 = Vec::with_capacity(len); +/// vec2.extend(repeat(0).take(len)) +/// ``` +declare_clippy_lint! { + pub SLOW_VECTOR_INITIALIZATION, + perf, + "slow or unsafe vector initialization" +} + +#[derive(Copy, Clone, Default)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(SLOW_VECTOR_INITIALIZATION) + } +} + +/// VecInitialization contains data regarding a vector initialized with `with_capacity` and then +/// assigned to a variable. For example, `let mut vec = Vec::with_capacity(0)` or +/// `vec = Vec::with_capacity(0)` +struct VecInitialization<'tcx> { + /// Symbol of the local variable name + variable_name: Symbol, + + /// Reference to the expression which initializes the vector + initialization_expr: &'tcx Expr, + + /// Reference to the expression used as argument on `with_capacity` call. This is used + /// to only match slow zero-filling idioms of the same length than vector initialization. + len_expr: &'tcx Expr, +} + +/// Type of slow initialization +enum InitializationType<'tcx> { + /// Extend is a slow initialization with the form `vec.extend(repeat(0).take(..))` + Extend(&'tcx Expr), + + /// Resize is a slow initialization with the form `vec.resize(.., 0)` + Resize(&'tcx Expr), +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)` + if_chain! { + if let ExprKind::Assign(ref left, ref right) = expr.node; + + // Extract variable name + if let ExprKind::Path(QPath::Resolved(_, ref path)) = left.node; + if let Some(variable_name) = path.segments.get(0); + + // Extract len argument + if let Some(ref len_arg) = Pass::is_vec_with_capacity(right); + + then { + let vi = VecInitialization { + variable_name: variable_name.ident.name, + initialization_expr: right, + len_expr: len_arg, + }; + + Pass::search_slow_zero_filling(cx, vi, expr.id, expr.span); + } + } + } + + fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { + // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` + if_chain! { + if let StmtKind::Decl(ref decl, _) = stmt.node; + if let DeclKind::Local(ref local) = decl.node; + if let PatKind::Binding(BindingAnnotation::Mutable, _, variable_name, None) = local.pat.node; + if let Some(ref init) = local.init; + if let Some(ref len_arg) = Pass::is_vec_with_capacity(init); + + then { + let vi = VecInitialization { + variable_name: variable_name.name, + initialization_expr: init, + len_expr: len_arg, + }; + + Pass::search_slow_zero_filling(cx, vi, stmt.node.id(), stmt.span); + } + } + } +} + +impl Pass { + /// Checks if the given expression is `Vec::with_capacity(..)`. It will return the expression + /// of the first argument of `with_capacity` call if it matches or `None` if it does not. + fn is_vec_with_capacity(expr: &Expr) -> Option<&Expr> { + if_chain! { + if let ExprKind::Call(ref func, ref args) = expr.node; + if let ExprKind::Path(ref path) = func.node; + if match_qpath(path, &["Vec", "with_capacity"]); + if args.len() == 1; + + then { + return Some(&args[0]); + } + } + + None + } + + /// Search for slow zero filling vector initialization for the given vector + fn search_slow_zero_filling<'tcx>( + cx: &LateContext<'_, 'tcx>, + vec_initialization: VecInitialization<'tcx>, + parent_node: NodeId, + parent_span: Span + ) { + let enclosing_body = get_enclosing_block(cx, parent_node); + + if enclosing_body.is_none() { + return; + } + + let mut v = SlowInitializationVisitor { + cx, + vec_ini: vec_initialization, + slow_expression: None, + initialization_found: false, + }; + + v.visit_block(enclosing_body.unwrap()); + + if let Some(ref repeat_expr) = v.slow_expression { + span_lint_and_then( + cx, + SLOW_VECTOR_INITIALIZATION, + parent_span, + "detected slow zero-filling initialization", + |db| { + db.span_suggestion_with_applicability(v.vec_ini.initialization_expr.span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); + + match repeat_expr { + InitializationType::Extend(e) => { + db.span_note(e.span, "extended here with .. 0"); + }, + InitializationType::Resize(e) => { + db.span_note(e.span, "resize here with .. 0"); + } + } + } + ); + } + } +} + +/// SlowInitializationVisitor searches for slow zero filling vector initialization, for the given +/// vector. +struct SlowInitializationVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + + /// Contains the information + vec_ini: VecInitialization<'tcx>, + + /// Contains, if found, the slow initialization expression + slow_expression: Option>, + + /// true if the initialization of the vector has been found on the visited block + initialization_found: bool, +} + +impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { + /// Checks if the given expression is extending a vector with `repeat(0).take(..)` + fn search_slow_extend_filling(&mut self, expr: &'tcx Expr) { + if_chain! { + if self.initialization_found; + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + if let ExprKind::Path(ref qpath_subj) = args[0].node; + if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if path.ident.name == "extend"; + if let Some(ref extend_arg) = args.get(1); + if self.is_repeat_take(extend_arg); + + then { + self.slow_expression = Some(InitializationType::Extend(expr)); + } + } + } + + /// Checks if the given expression is resizing a vector with 0 + fn search_slow_resize_filling(&mut self, expr: &'tcx Expr) { + if_chain! { + if self.initialization_found; + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + if let ExprKind::Path(ref qpath_subj) = args[0].node; + if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if path.ident.name == "resize"; + if let (Some(ref len_arg), Some(fill_arg)) = (args.get(1), args.get(2)); + + // Check that is filled with 0 + if let ExprKind::Lit(ref lit) = fill_arg.node; + if let LitKind::Int(0, _) = lit.node; + + // Check that len expression is equals to `with_capacity` expression + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + + then { + self.slow_expression = Some(InitializationType::Resize(expr)); + } + } + } + + /// Returns `true` if give expression is `repeat(0).take(...)` + fn is_repeat_take(&self, expr: &Expr) -> bool { + if_chain! { + if let ExprKind::MethodCall(ref take_path, _, ref take_args) = expr.node; + if take_path.ident.name == "take"; + + // Check that take is applied to `repeat(0)` + if let Some(ref repeat_expr) = take_args.get(0); + if self.is_repeat_zero(repeat_expr); + + // Check that len expression is equals to `with_capacity` expression + if let Some(ref len_arg) = take_args.get(1); + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + + then { + return true; + } + } + + false + } + + /// Returns `true` if given expression is `repeat(0)` + fn is_repeat_zero(&self, expr: &Expr) -> bool { + if_chain! { + if let ExprKind::Call(ref fn_expr, ref repeat_args) = expr.node; + if let ExprKind::Path(ref qpath_repeat) = fn_expr.node; + if match_qpath(&qpath_repeat, &["repeat"]); + if let Some(ref repeat_arg) = repeat_args.get(0); + if let ExprKind::Lit(ref lit) = repeat_arg.node; + if let LitKind::Int(0, _) = lit.node; + + then { + return true + } + } + + false + } +} + +impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + // Stop the search if we already found a slow zero-filling initialization + if self.slow_expression.is_some() { + return + } + + // Skip all the expressions previous to the vector initialization + if self.vec_ini.initialization_expr.id == expr.id { + self.initialization_found = true; + } + + self.search_slow_extend_filling(expr); + self.search_slow_resize_filling(expr); + + walk_expr(self, expr); + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs new file mode 100644 index 00000000000..f79abe8327e --- /dev/null +++ b/tests/ui/slow_vector_initialization.rs @@ -0,0 +1,63 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::repeat; + +fn main() { + resize_vector(); + extend_vector(); + mixed_extend_resize_vector(); +} + +fn extend_vector() { + // Extend with constant expression + let len = 300; + let mut vec1 = Vec::with_capacity(len); + vec1.extend(repeat(0).take(len)); + + // Extend with len expression + let mut vec2 = Vec::with_capacity(len - 10); + vec2.extend(repeat(0).take(len - 10)); + + // Extend with mismatching expression should not be warned + let mut vec3 = Vec::with_capacity(24322); + vec3.extend(repeat(0).take(2)); +} + +fn mixed_extend_resize_vector() { + // Mismatching len + let mut mismatching_len = Vec::with_capacity(30); + + // Slow initialization + let mut resized_vec = Vec::with_capacity(30); + let mut extend_vec = Vec::with_capacity(30); + + resized_vec.resize(30, 0); + mismatching_len.extend(repeat(0).take(40)); + extend_vec.extend(repeat(0).take(30)); +} + +fn resize_vector() { + // Resize with constant expression + let len = 300; + let mut vec1 = Vec::with_capacity(len); + vec1.resize(len, 0); + + // Resize mismatch len + let mut vec2 = Vec::with_capacity(200); + vec2.resize(10, 0); + + // Resize with len expression + let mut vec3 = Vec::with_capacity(len - 10); + vec3.resize(len - 10, 0); + + // Reinitialization should be warned + vec1 = Vec::with_capacity(10); + vec1.resize(10, 0); +} diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr new file mode 100644 index 00000000000..4941794d541 --- /dev/null +++ b/tests/ui/slow_vector_initialization.stderr @@ -0,0 +1,101 @@ +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:21:5 + | +21 | let mut vec1 = Vec::with_capacity(len); + | ^^^^^^^^^^^^^^^-----------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | + = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` +note: extended here with .. 0 + --> $DIR/slow_vector_initialization.rs:22:5 + | +22 | vec1.extend(repeat(0).take(len)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:25:5 + | +25 | let mut vec2 = Vec::with_capacity(len - 10); + | ^^^^^^^^^^^^^^^----------------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: extended here with .. 0 + --> $DIR/slow_vector_initialization.rs:26:5 + | +26 | vec2.extend(repeat(0).take(len - 10)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:38:5 + | +38 | let mut resized_vec = Vec::with_capacity(30); + | ^^^^^^^^^^^^^^^^^^^^^^----------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: resize here with .. 0 + --> $DIR/slow_vector_initialization.rs:41:5 + | +41 | resized_vec.resize(30, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:39:5 + | +39 | let mut extend_vec = Vec::with_capacity(30); + | ^^^^^^^^^^^^^^^^^^^^^----------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: extended here with .. 0 + --> $DIR/slow_vector_initialization.rs:43:5 + | +43 | extend_vec.extend(repeat(0).take(30)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:49:5 + | +49 | let mut vec1 = Vec::with_capacity(len); + | ^^^^^^^^^^^^^^^-----------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: resize here with .. 0 + --> $DIR/slow_vector_initialization.rs:50:5 + | +50 | vec1.resize(len, 0); + | ^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:57:5 + | +57 | let mut vec3 = Vec::with_capacity(len - 10); + | ^^^^^^^^^^^^^^^----------------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: resize here with .. 0 + --> $DIR/slow_vector_initialization.rs:58:5 + | +58 | vec3.resize(len - 10, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:61:5 + | +61 | vec1 = Vec::with_capacity(10); + | ^^^^^^^---------------------- + | | + | help: consider replacing with: `vec![0; ..]` + | +note: resize here with .. 0 + --> $DIR/slow_vector_initialization.rs:62:5 + | +62 | vec1.resize(10, 0); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/slow_vector_initialization.stdout b/tests/ui/slow_vector_initialization.stdout new file mode 100644 index 00000000000..e69de29bb2d -- cgit 1.4.1-3-g733a5 From 9b4bc3b6efcb9daf8c1daf9f7f2a8bfa19973ad8 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Fri, 26 Oct 2018 22:35:16 +0200 Subject: Add unsafe set_len initialization --- clippy_lints/src/slow_vector_initialization.rs | 40 +++++++++--- tests/ui/slow_vector_initialization.rs | 9 +++ tests/ui/slow_vector_initialization.stderr | 86 +++++++++++++++----------- 3 files changed, 92 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 52855031a5a..5d0b302e06b 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -71,6 +71,9 @@ enum InitializationType<'tcx> { /// Resize is a slow initialization with the form `vec.resize(.., 0)` Resize(&'tcx Expr), + + /// UnsafeSetLen is a slow initialization with the form `vec.set_len(..)` + UnsafeSetLen(&'tcx Expr), } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { @@ -93,7 +96,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_slow_zero_filling(cx, vi, expr.id, expr.span); + Pass::search_slow_initialization(cx, vi, expr.id, expr.span); } } } @@ -114,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_slow_zero_filling(cx, vi, stmt.node.id(), stmt.span); + Pass::search_slow_initialization(cx, vi, stmt.node.id(), stmt.span); } } } @@ -138,8 +141,8 @@ impl Pass { None } - /// Search for slow zero filling vector initialization for the given vector - fn search_slow_zero_filling<'tcx>( + /// Search a slow initialization for the given vector + fn search_slow_initialization<'tcx>( cx: &LateContext<'_, 'tcx>, vec_initialization: VecInitialization<'tcx>, parent_node: NodeId, @@ -171,11 +174,14 @@ impl Pass { match repeat_expr { InitializationType::Extend(e) => { - db.span_note(e.span, "extended here with .. 0"); + db.span_note(e.span, "extended at"); }, InitializationType::Resize(e) => { - db.span_note(e.span, "resize here with .. 0"); - } + db.span_note(e.span, "resized at"); + }, + InitializationType::UnsafeSetLen(e) => { + db.span_note(e.span, "changed len at"); + }, } } ); @@ -239,6 +245,25 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { } } + /// Checks if the given expression is using `set_len` to initialize the vector + fn search_unsafe_set_len(&mut self, expr: &'tcx Expr) { + if_chain! { + if self.initialization_found; + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + if let ExprKind::Path(ref qpath_subj) = args[0].node; + if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if path.ident.name == "set_len"; + if let Some(ref len_arg) = args.get(1); + + // Check that len expression is equals to `with_capacity` expression + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + + then { + self.slow_expression = Some(InitializationType::UnsafeSetLen(expr)); + } + } + } + /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&self, expr: &Expr) -> bool { if_chain! { @@ -294,6 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> { self.search_slow_extend_filling(expr); self.search_slow_resize_filling(expr); + self.search_unsafe_set_len(expr); walk_expr(self, expr); } diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index f79abe8327e..991d850464e 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -13,6 +13,7 @@ fn main() { resize_vector(); extend_vector(); mixed_extend_resize_vector(); + unsafe_vector(); } fn extend_vector() { @@ -61,3 +62,11 @@ fn resize_vector() { vec1 = Vec::with_capacity(10); vec1.resize(10, 0); } + +fn unsafe_vector() { + let mut unsafe_vec: Vec = Vec::with_capacity(200); + + unsafe { + unsafe_vec.set_len(200); + } +} diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 4941794d541..ece6f388c84 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,101 +1,115 @@ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:21:5 + --> $DIR/slow_vector_initialization.rs:22:5 | -21 | let mut vec1 = Vec::with_capacity(len); +22 | let mut vec1 = Vec::with_capacity(len); | ^^^^^^^^^^^^^^^-----------------------^ | | | help: consider replacing with: `vec![0; ..]` | = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` -note: extended here with .. 0 - --> $DIR/slow_vector_initialization.rs:22:5 +note: extended at + --> $DIR/slow_vector_initialization.rs:23:5 | -22 | vec1.extend(repeat(0).take(len)); +23 | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:25:5 + --> $DIR/slow_vector_initialization.rs:26:5 | -25 | let mut vec2 = Vec::with_capacity(len - 10); +26 | let mut vec2 = Vec::with_capacity(len - 10); | ^^^^^^^^^^^^^^^----------------------------^ | | | help: consider replacing with: `vec![0; ..]` | -note: extended here with .. 0 - --> $DIR/slow_vector_initialization.rs:26:5 +note: extended at + --> $DIR/slow_vector_initialization.rs:27:5 | -26 | vec2.extend(repeat(0).take(len - 10)); +27 | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:38:5 + --> $DIR/slow_vector_initialization.rs:39:5 | -38 | let mut resized_vec = Vec::with_capacity(30); +39 | let mut resized_vec = Vec::with_capacity(30); | ^^^^^^^^^^^^^^^^^^^^^^----------------------^ | | | help: consider replacing with: `vec![0; ..]` | -note: resize here with .. 0 - --> $DIR/slow_vector_initialization.rs:41:5 +note: resized at + --> $DIR/slow_vector_initialization.rs:42:5 | -41 | resized_vec.resize(30, 0); +42 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:39:5 + --> $DIR/slow_vector_initialization.rs:40:5 | -39 | let mut extend_vec = Vec::with_capacity(30); +40 | let mut extend_vec = Vec::with_capacity(30); | ^^^^^^^^^^^^^^^^^^^^^----------------------^ | | | help: consider replacing with: `vec![0; ..]` | -note: extended here with .. 0 - --> $DIR/slow_vector_initialization.rs:43:5 +note: extended at + --> $DIR/slow_vector_initialization.rs:44:5 | -43 | extend_vec.extend(repeat(0).take(30)); +44 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:49:5 + --> $DIR/slow_vector_initialization.rs:50:5 | -49 | let mut vec1 = Vec::with_capacity(len); +50 | let mut vec1 = Vec::with_capacity(len); | ^^^^^^^^^^^^^^^-----------------------^ | | | help: consider replacing with: `vec![0; ..]` | -note: resize here with .. 0 - --> $DIR/slow_vector_initialization.rs:50:5 +note: resized at + --> $DIR/slow_vector_initialization.rs:51:5 | -50 | vec1.resize(len, 0); +51 | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:57:5 + --> $DIR/slow_vector_initialization.rs:58:5 | -57 | let mut vec3 = Vec::with_capacity(len - 10); +58 | let mut vec3 = Vec::with_capacity(len - 10); | ^^^^^^^^^^^^^^^----------------------------^ | | | help: consider replacing with: `vec![0; ..]` | -note: resize here with .. 0 - --> $DIR/slow_vector_initialization.rs:58:5 +note: resized at + --> $DIR/slow_vector_initialization.rs:59:5 | -58 | vec3.resize(len - 10, 0); +59 | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:61:5 + --> $DIR/slow_vector_initialization.rs:62:5 | -61 | vec1 = Vec::with_capacity(10); +62 | vec1 = Vec::with_capacity(10); | ^^^^^^^---------------------- | | | help: consider replacing with: `vec![0; ..]` | -note: resize here with .. 0 - --> $DIR/slow_vector_initialization.rs:62:5 +note: resized at + --> $DIR/slow_vector_initialization.rs:63:5 | -62 | vec1.resize(10, 0); +63 | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: detected slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:67:5 + | +67 | let mut unsafe_vec: Vec = Vec::with_capacity(200); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^ + | | + | help: consider replacing with: `vec![0; ..]` + | +note: changed len at + --> $DIR/slow_vector_initialization.rs:70:9 + | +70 | unsafe_vec.set_len(200); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 2753f1cbd4623063f19ca27caaac67308c94a536 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Tue, 30 Oct 2018 00:25:05 +0100 Subject: Split lint into slow and unsafe vector initalization --- clippy_lints/src/slow_vector_initialization.rs | 100 ++++++++++++++++++------- tests/ui/slow_vector_initialization.stderr | 90 ++++++---------------- 2 files changed, 96 insertions(+), 94 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 5d0b302e06b..090125e3694 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -37,7 +37,25 @@ use crate::rustc_errors::{Applicability}; declare_clippy_lint! { pub SLOW_VECTOR_INITIALIZATION, perf, - "slow or unsafe vector initialization" + "slow vector initialization" +} + +/// **What it does:** Checks unsafe vector initialization +/// +/// **Why is this bad?** Changing the length of a vector may expose uninitialized memory, which +/// can lead to memory safety issues +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let mut vec1 = Vec::with_capacity(len); +/// unsafe { vec1.set_len(len); } +/// ``` +declare_clippy_lint! { + pub UNSAFE_VECTOR_INITIALIZATION, + correctness, + "unsafe vector initialization" } #[derive(Copy, Clone, Default)] @@ -45,7 +63,10 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(SLOW_VECTOR_INITIALIZATION) + lint_array!( + SLOW_VECTOR_INITIALIZATION, + UNSAFE_VECTOR_INITIALIZATION, + ) } } @@ -96,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_slow_initialization(cx, vi, expr.id, expr.span); + Pass::search_slow_initialization(cx, vi, expr.id); } } } @@ -117,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_slow_initialization(cx, vi, stmt.node.id(), stmt.span); + Pass::search_slow_initialization(cx, vi, stmt.node.id()); } } } @@ -145,8 +166,7 @@ impl Pass { fn search_slow_initialization<'tcx>( cx: &LateContext<'_, 'tcx>, vec_initialization: VecInitialization<'tcx>, - parent_node: NodeId, - parent_span: Span + parent_node: NodeId ) { let enclosing_body = get_enclosing_block(cx, parent_node); @@ -163,30 +183,54 @@ impl Pass { v.visit_block(enclosing_body.unwrap()); - if let Some(ref repeat_expr) = v.slow_expression { - span_lint_and_then( - cx, - SLOW_VECTOR_INITIALIZATION, - parent_span, - "detected slow zero-filling initialization", - |db| { - db.span_suggestion_with_applicability(v.vec_ini.initialization_expr.span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); - - match repeat_expr { - InitializationType::Extend(e) => { - db.span_note(e.span, "extended at"); - }, - InitializationType::Resize(e) => { - db.span_note(e.span, "resized at"); - }, - InitializationType::UnsafeSetLen(e) => { - db.span_note(e.span, "changed len at"); - }, - } - } - ); + if let Some(ref initialization_expr) = v.slow_expression { + let alloc_span = v.vec_ini.initialization_expr.span; + Pass::lint_initialization(cx, initialization_expr, alloc_span); } } + + fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, alloc_span: Span) { + match initialization { + InitializationType::UnsafeSetLen(e) => + Pass::lint_unsafe_initialization(cx, e, alloc_span), + + InitializationType::Extend(e) | + InitializationType::Resize(e) => + Pass::lint_slow_initialization(cx, e, alloc_span), + }; + } + + fn lint_slow_initialization<'tcx>( + cx: &LateContext<'_, 'tcx>, + slow_fill: &Expr, + alloc_span: Span, + ) { + span_lint_and_then( + cx, + SLOW_VECTOR_INITIALIZATION, + slow_fill.span, + "detected slow zero-filling initialization", + |db| { + db.span_suggestion_with_applicability(alloc_span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); + } + ); + } + + fn lint_unsafe_initialization<'tcx>( + cx: &LateContext<'_, 'tcx>, + slow_fill: &Expr, + alloc_span: Span, + ) { + span_lint_and_then( + cx, + UNSAFE_VECTOR_INITIALIZATION, + slow_fill.span, + "detected unsafe vector initialization", + |db| { + db.span_suggestion_with_applicability(alloc_span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); + } + ); + } } /// SlowInitializationVisitor searches for slow zero filling vector initialization, for the given diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index ece6f388c84..74fd9be0a0b 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,115 +1,73 @@ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:22:5 - | -22 | let mut vec1 = Vec::with_capacity(len); - | ^^^^^^^^^^^^^^^-----------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | - = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` -note: extended at --> $DIR/slow_vector_initialization.rs:23:5 | +22 | let mut vec1 = Vec::with_capacity(len); + | ----------------------- help: consider replacing with: `vec![0; ..]` 23 | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:26:5 - | -26 | let mut vec2 = Vec::with_capacity(len - 10); - | ^^^^^^^^^^^^^^^----------------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: extended at --> $DIR/slow_vector_initialization.rs:27:5 | +26 | let mut vec2 = Vec::with_capacity(len - 10); + | ---------------------------- help: consider replacing with: `vec![0; ..]` 27 | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:39:5 - | -39 | let mut resized_vec = Vec::with_capacity(30); - | ^^^^^^^^^^^^^^^^^^^^^^----------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: resized at --> $DIR/slow_vector_initialization.rs:42:5 | +39 | let mut resized_vec = Vec::with_capacity(30); + | ---------------------- help: consider replacing with: `vec![0; ..]` +... 42 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:40:5 - | -40 | let mut extend_vec = Vec::with_capacity(30); - | ^^^^^^^^^^^^^^^^^^^^^----------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: extended at --> $DIR/slow_vector_initialization.rs:44:5 | +40 | let mut extend_vec = Vec::with_capacity(30); + | ---------------------- help: consider replacing with: `vec![0; ..]` +... 44 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:50:5 - | -50 | let mut vec1 = Vec::with_capacity(len); - | ^^^^^^^^^^^^^^^-----------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: resized at --> $DIR/slow_vector_initialization.rs:51:5 | +50 | let mut vec1 = Vec::with_capacity(len); + | ----------------------- help: consider replacing with: `vec![0; ..]` 51 | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:58:5 - | -58 | let mut vec3 = Vec::with_capacity(len - 10); - | ^^^^^^^^^^^^^^^----------------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: resized at --> $DIR/slow_vector_initialization.rs:59:5 | +58 | let mut vec3 = Vec::with_capacity(len - 10); + | ---------------------------- help: consider replacing with: `vec![0; ..]` 59 | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:62:5 - | -62 | vec1 = Vec::with_capacity(10); - | ^^^^^^^---------------------- - | | - | help: consider replacing with: `vec![0; ..]` - | -note: resized at --> $DIR/slow_vector_initialization.rs:63:5 | +62 | vec1 = Vec::with_capacity(10); + | ---------------------- help: consider replacing with: `vec![0; ..]` 63 | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:67:5 - | -67 | let mut unsafe_vec: Vec = Vec::with_capacity(200); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^ - | | - | help: consider replacing with: `vec![0; ..]` - | -note: changed len at +error: detected unsafe vector initialization --> $DIR/slow_vector_initialization.rs:70:9 | +67 | let mut unsafe_vec: Vec = Vec::with_capacity(200); + | ----------------------- help: consider replacing with: `vec![0; ..]` +... 70 | unsafe_vec.set_len(200); | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::unsafe_vector_initialization)] on by default error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 5b77ee95dc6c8cadfba8b5f82b427efa3e0f23c5 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Tue, 30 Oct 2018 21:47:15 +0100 Subject: Rename some symbols Renamed some symbols in order to make them a little bit more accurate. --- clippy_lints/src/slow_vector_initialization.rs | 117 +++++++++++++------------ tests/ui/slow_vector_initialization.stderr | 32 +++---- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 090125e3694..ec9c7ec60bc 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -8,15 +8,14 @@ // except according to those terms. use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, Lint}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; use if_chain::if_chain; use crate::syntax_pos::symbol::Symbol; use crate::syntax::ast::{LitKind, NodeId}; -use crate::syntax::source_map::Span; -use crate::utils::{match_qpath, span_lint_and_then, SpanlessEq}; -use crate::utils::get_enclosing_block; +use crate::utils::{match_qpath, span_lint_and_then, SpanlessEq, get_enclosing_block}; +use crate::utils::sugg::Sugg; use crate::rustc_errors::{Applicability}; /// **What it does:** Checks slow zero-filled vector initialization @@ -70,15 +69,15 @@ impl LintPass for Pass { } } -/// VecInitialization contains data regarding a vector initialized with `with_capacity` and then +/// `VecAllocation` contains data regarding a vector allocated with `with_capacity` and then /// assigned to a variable. For example, `let mut vec = Vec::with_capacity(0)` or /// `vec = Vec::with_capacity(0)` -struct VecInitialization<'tcx> { +struct VecAllocation<'tcx> { /// Symbol of the local variable name variable_name: Symbol, - /// Reference to the expression which initializes the vector - initialization_expr: &'tcx Expr, + /// Reference to the expression which allocates the vector + allocation_expr: &'tcx Expr, /// Reference to the expression used as argument on `with_capacity` call. This is used /// to only match slow zero-filling idioms of the same length than vector initialization. @@ -111,13 +110,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(ref len_arg) = Pass::is_vec_with_capacity(right); then { - let vi = VecInitialization { + let vi = VecAllocation { variable_name: variable_name.ident.name, - initialization_expr: right, + allocation_expr: right, len_expr: len_arg, }; - Pass::search_slow_initialization(cx, vi, expr.id); + Pass::search_initialization(cx, vi, expr.id); } } } @@ -132,13 +131,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(ref len_arg) = Pass::is_vec_with_capacity(init); then { - let vi = VecInitialization { + let vi = VecAllocation { variable_name: variable_name.name, - initialization_expr: init, + allocation_expr: init, len_expr: len_arg, }; - Pass::search_slow_initialization(cx, vi, stmt.node.id()); + Pass::search_initialization(cx, vi, stmt.node.id()); } } } @@ -162,10 +161,10 @@ impl Pass { None } - /// Search a slow initialization for the given vector - fn search_slow_initialization<'tcx>( + /// Search initialization for the given vector + fn search_initialization<'tcx>( cx: &LateContext<'_, 'tcx>, - vec_initialization: VecInitialization<'tcx>, + vec_alloc: VecAllocation<'tcx>, parent_node: NodeId ) { let enclosing_body = get_enclosing_block(cx, parent_node); @@ -174,72 +173,76 @@ impl Pass { return; } - let mut v = SlowInitializationVisitor { + let mut v = VectorInitializationVisitor { cx, - vec_ini: vec_initialization, + vec_alloc, slow_expression: None, initialization_found: false, }; v.visit_block(enclosing_body.unwrap()); - if let Some(ref initialization_expr) = v.slow_expression { - let alloc_span = v.vec_ini.initialization_expr.span; - Pass::lint_initialization(cx, initialization_expr, alloc_span); + if let Some(ref allocation_expr) = v.slow_expression { + Pass::lint_initialization(cx, allocation_expr, &v.vec_alloc); } } - fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, alloc_span: Span) { + fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, vec_alloc: &VecAllocation<'_>) { match initialization { InitializationType::UnsafeSetLen(e) => - Pass::lint_unsafe_initialization(cx, e, alloc_span), + Pass::emit_lint( + cx, + e, + vec_alloc, + "unsafe vector initialization", + UNSAFE_VECTOR_INITIALIZATION + ), InitializationType::Extend(e) | InitializationType::Resize(e) => - Pass::lint_slow_initialization(cx, e, alloc_span), + Pass::emit_lint( + cx, + e, + vec_alloc, + "slow zero-filling initialization", + SLOW_VECTOR_INITIALIZATION + ) }; } - fn lint_slow_initialization<'tcx>( + fn emit_lint<'tcx>( cx: &LateContext<'_, 'tcx>, slow_fill: &Expr, - alloc_span: Span, + vec_alloc: &VecAllocation<'_>, + msg: &str, + lint: &'static Lint ) { - span_lint_and_then( - cx, - SLOW_VECTOR_INITIALIZATION, - slow_fill.span, - "detected slow zero-filling initialization", - |db| { - db.span_suggestion_with_applicability(alloc_span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); - } - ); - } + let len_expr = Sugg::hir(cx, vec_alloc.len_expr, "len"); - fn lint_unsafe_initialization<'tcx>( - cx: &LateContext<'_, 'tcx>, - slow_fill: &Expr, - alloc_span: Span, - ) { span_lint_and_then( cx, - UNSAFE_VECTOR_INITIALIZATION, + lint, slow_fill.span, - "detected unsafe vector initialization", + msg, |db| { - db.span_suggestion_with_applicability(alloc_span, "consider replacing with", "vec![0; ..]".to_string(), Applicability::Unspecified); + db.span_suggestion_with_applicability( + vec_alloc.allocation_expr.span, + "consider replace allocation with", + format!("vec![0; {}]", len_expr), + Applicability::Unspecified + ); } ); } } -/// SlowInitializationVisitor searches for slow zero filling vector initialization, for the given +/// `VectorInitializationVisitor` searches for unsafe or slow vector initializations for the given /// vector. -struct SlowInitializationVisitor<'a, 'tcx: 'a> { +struct VectorInitializationVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, /// Contains the information - vec_ini: VecInitialization<'tcx>, + vec_alloc: VecAllocation<'tcx>, /// Contains, if found, the slow initialization expression slow_expression: Option>, @@ -248,14 +251,14 @@ struct SlowInitializationVisitor<'a, 'tcx: 'a> { initialization_found: bool, } -impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { +impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Checks if the given expression is extending a vector with `repeat(0).take(..)` fn search_slow_extend_filling(&mut self, expr: &'tcx Expr) { if_chain! { if self.initialization_found; if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; if let ExprKind::Path(ref qpath_subj) = args[0].node; - if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]); if path.ident.name == "extend"; if let Some(ref extend_arg) = args.get(1); if self.is_repeat_take(extend_arg); @@ -272,7 +275,7 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { if self.initialization_found; if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; if let ExprKind::Path(ref qpath_subj) = args[0].node; - if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]); if path.ident.name == "resize"; if let (Some(ref len_arg), Some(fill_arg)) = (args.get(1), args.get(2)); @@ -281,7 +284,7 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { if let LitKind::Int(0, _) = lit.node; // Check that len expression is equals to `with_capacity` expression - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); then { self.slow_expression = Some(InitializationType::Resize(expr)); @@ -295,12 +298,12 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { if self.initialization_found; if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; if let ExprKind::Path(ref qpath_subj) = args[0].node; - if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]); + if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]); if path.ident.name == "set_len"; if let Some(ref len_arg) = args.get(1); // Check that len expression is equals to `with_capacity` expression - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); then { self.slow_expression = Some(InitializationType::UnsafeSetLen(expr)); @@ -320,7 +323,7 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { // Check that len expression is equals to `with_capacity` expression if let Some(ref len_arg) = take_args.get(1); - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr); + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); then { return true; @@ -349,7 +352,7 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { // Stop the search if we already found a slow zero-filling initialization if self.slow_expression.is_some() { @@ -357,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> { } // Skip all the expressions previous to the vector initialization - if self.vec_ini.initialization_expr.id == expr.id { + if self.vec_alloc.allocation_expr.id == expr.id { self.initialization_found = true; } diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 74fd9be0a0b..c1e48d42a6c 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,68 +1,68 @@ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:23:5 | 22 | let mut vec1 = Vec::with_capacity(len); - | ----------------------- help: consider replacing with: `vec![0; ..]` + | ----------------------- help: consider replace allocation with: `vec![0; len]` 23 | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:27:5 | 26 | let mut vec2 = Vec::with_capacity(len - 10); - | ---------------------------- help: consider replacing with: `vec![0; ..]` + | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` 27 | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:42:5 | 39 | let mut resized_vec = Vec::with_capacity(30); - | ---------------------- help: consider replacing with: `vec![0; ..]` + | ---------------------- help: consider replace allocation with: `vec![0; 30]` ... 42 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:44:5 | 40 | let mut extend_vec = Vec::with_capacity(30); - | ---------------------- help: consider replacing with: `vec![0; ..]` + | ---------------------- help: consider replace allocation with: `vec![0; 30]` ... 44 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:51:5 | 50 | let mut vec1 = Vec::with_capacity(len); - | ----------------------- help: consider replacing with: `vec![0; ..]` + | ----------------------- help: consider replace allocation with: `vec![0; len]` 51 | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:59:5 | 58 | let mut vec3 = Vec::with_capacity(len - 10); - | ---------------------------- help: consider replacing with: `vec![0; ..]` + | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` 59 | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: detected slow zero-filling initialization +error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:63:5 | 62 | vec1 = Vec::with_capacity(10); - | ---------------------- help: consider replacing with: `vec![0; ..]` + | ---------------------- help: consider replace allocation with: `vec![0; 10]` 63 | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: detected unsafe vector initialization +error: unsafe vector initialization --> $DIR/slow_vector_initialization.rs:70:9 | 67 | let mut unsafe_vec: Vec = Vec::with_capacity(200); - | ----------------------- help: consider replacing with: `vec![0; ..]` + | ----------------------- help: consider replace allocation with: `vec![0; 200]` ... 70 | unsafe_vec.set_len(200); | ^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 39b02fdcd26adc95540e96c82b93beb926b6606f Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Mon, 5 Nov 2018 22:46:07 +0100 Subject: Fix some warnings related to Self --- clippy_lints/src/slow_vector_initialization.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index ec9c7ec60bc..2af657a5a6a 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(variable_name) = path.segments.get(0); // Extract len argument - if let Some(ref len_arg) = Pass::is_vec_with_capacity(right); + if let Some(ref len_arg) = Self::is_vec_with_capacity(right); then { let vi = VecAllocation { @@ -116,7 +116,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_initialization(cx, vi, expr.id); + Self::search_initialization(cx, vi, expr.id); } } } @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let DeclKind::Local(ref local) = decl.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, variable_name, None) = local.pat.node; if let Some(ref init) = local.init; - if let Some(ref len_arg) = Pass::is_vec_with_capacity(init); + if let Some(ref len_arg) = Self::is_vec_with_capacity(init); then { let vi = VecAllocation { @@ -137,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Pass::search_initialization(cx, vi, stmt.node.id()); + Self::search_initialization(cx, vi, stmt.node.id()); } } } @@ -183,14 +183,14 @@ impl Pass { v.visit_block(enclosing_body.unwrap()); if let Some(ref allocation_expr) = v.slow_expression { - Pass::lint_initialization(cx, allocation_expr, &v.vec_alloc); + Self::lint_initialization(cx, allocation_expr, &v.vec_alloc); } } fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, vec_alloc: &VecAllocation<'_>) { match initialization { InitializationType::UnsafeSetLen(e) => - Pass::emit_lint( + Self::emit_lint( cx, e, vec_alloc, @@ -200,7 +200,7 @@ impl Pass { InitializationType::Extend(e) | InitializationType::Resize(e) => - Pass::emit_lint( + Self::emit_lint( cx, e, vec_alloc, -- cgit 1.4.1-3-g733a5 From 5fa04bc3cdb3071dddbfd9cf9cf33bc099b182f0 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Sun, 18 Nov 2018 23:45:53 +0100 Subject: Lint only the first statment/expression after alloc Instead of searching for all the successive expressions after a vector allocation, check only the first expression. This is done to minimize the amount of false positives of the lint. --- clippy_lints/src/slow_vector_initialization.rs | 39 ++++++++++++++++++++------ tests/ui/slow_vector_initialization.rs | 17 +++++++++-- tests/ui/slow_vector_initialization.stderr | 10 +++---- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 2af657a5a6a..272047bc7cb 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -7,7 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::intravisit::{walk_expr, walk_stmt, walk_block, NestedVisitorMap, Visitor}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, Lint}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; @@ -353,20 +353,41 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr) { - // Stop the search if we already found a slow zero-filling initialization - if self.slow_expression.is_some() { - return + fn visit_stmt(&mut self, stmt: &'tcx Stmt) { + if self.initialization_found { + match stmt.node { + StmtKind::Expr(ref expr, _) | + StmtKind::Semi(ref expr, _) => { + self.search_slow_extend_filling(expr); + self.search_slow_resize_filling(expr); + self.search_unsafe_set_len(expr); + }, + _ => (), + } + + self.initialization_found = false; + } else { + walk_stmt(self, stmt); + } + } + + fn visit_block(&mut self, block: &'tcx Block) { + if self.initialization_found { + if let Some(ref s) = block.stmts.get(0) { + self.visit_stmt( s) + } + + self.initialization_found = false; + } else { + walk_block(self, block); } + } + fn visit_expr(&mut self, expr: &'tcx Expr) { // Skip all the expressions previous to the vector initialization if self.vec_alloc.allocation_expr.id == expr.id { self.initialization_found = true; } - - self.search_slow_extend_filling(expr); - self.search_slow_resize_filling(expr); - self.search_unsafe_set_len(expr); walk_expr(self, expr); } diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index 991d850464e..daa6b9c1376 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -34,13 +34,13 @@ fn extend_vector() { fn mixed_extend_resize_vector() { // Mismatching len let mut mismatching_len = Vec::with_capacity(30); + mismatching_len.extend(repeat(0).take(40)); // Slow initialization let mut resized_vec = Vec::with_capacity(30); - let mut extend_vec = Vec::with_capacity(30); - resized_vec.resize(30, 0); - mismatching_len.extend(repeat(0).take(40)); + + let mut extend_vec = Vec::with_capacity(30); extend_vec.extend(repeat(0).take(30)); } @@ -70,3 +70,14 @@ fn unsafe_vector() { unsafe_vec.set_len(200); } } + +fn do_stuff(vec: &mut Vec) { + +} + +fn extend_vector_with_manipulations_between() { + let len = 300; + let mut vec1:Vec = Vec::with_capacity(len); + do_stuff(&mut vec1); + vec1.extend(repeat(0).take(len)); +} diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index c1e48d42a6c..577cc82c6d5 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -17,20 +17,18 @@ error: slow zero-filling initialization | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:42:5 + --> $DIR/slow_vector_initialization.rs:41:5 | -39 | let mut resized_vec = Vec::with_capacity(30); +40 | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -... -42 | resized_vec.resize(30, 0); +41 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:44:5 | -40 | let mut extend_vec = Vec::with_capacity(30); +43 | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -... 44 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From dc35841be4dd7efad4205e6d2d9f183b5866f6f6 Mon Sep 17 00:00:00 2001 From: Guillem Nieto Date: Sun, 25 Nov 2018 14:36:04 -0800 Subject: Update lints --- CHANGELOG.md | 2 ++ README.md | 2 +- clippy_lints/src/lib.rs | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa05eca89d1..320a3511e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -842,6 +842,7 @@ All notable changes to this project will be documented in this file. [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign @@ -880,6 +881,7 @@ All notable changes to this project will be documented in this file. [`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern [`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal [`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name +[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization [`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix [`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice [`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice diff --git a/README.md b/README.md index f2b0da3ae71..9d142a2deee 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 288 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cf754d48667..35f47c1cde4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -711,6 +711,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { returns::NEEDLESS_RETURN, returns::UNUSED_UNIT, serde_api::SERDE_API_MISUSE, + slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, + slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, strings::STRING_LIT_AS_BYTES, suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, @@ -957,6 +959,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ranges::ITERATOR_STEP_BY_ZERO, regex::INVALID_REGEX, serde_api::SERDE_API_MISUSE, + slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, swap::ALMOST_SWAPPED, -- cgit 1.4.1-3-g733a5 From ae32c877a5adb87af38fce0be918a6a03f8b3540 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 26 Nov 2018 01:12:12 +0100 Subject: constants: add u128 i128 builtin types and fix outdated url --- clippy_lints/src/utils/constants.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index 42da95a12ed..2e87191d720 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -16,7 +16,7 @@ /// /// See also [the reference][reference-types] for a list of such types. /// -/// [reference-types]: https://doc.rust-lang.org/reference.html#types +/// [reference-types]: https://doc.rust-lang.org/reference/types.html pub const BUILTIN_TYPES: &[&str] = &[ "i8", "u8", @@ -26,6 +26,8 @@ pub const BUILTIN_TYPES: &[&str] = &[ "u32", "i64", "u64", + "i128", + "u128", "isize", "usize", "f32", -- cgit 1.4.1-3-g733a5 From fd05696b9d8a42e4c7c44375795c280fae57c115 Mon Sep 17 00:00:00 2001 From: Oliver S̶c̶h̶n̶e̶i̶d̶e̶r Scherer Date: Mon, 26 Nov 2018 13:39:09 +0100 Subject: Update mod.rs --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 410819136bc..b54f64dacf3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -507,7 +507,7 @@ impl<'a> DiagnosticWrapper<'a> { fn docs_link(&mut self, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { self.0.help(&format!( - "for further information visit https://rust-lang-nursery.github.io/rust-clippy/{}/index.html#{}", + "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}", &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { // extract just major + minor version and ignore patch versions format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) -- cgit 1.4.1-3-g733a5 From 2a1c8b1db6d5cb79aa77333387c9be50c0b70aa7 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 5 Nov 2018 00:12:42 +0100 Subject: readme: tell how to install clippy on travis from git if it is not shipped with a nightly. --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 9d142a2deee..0cb1481c9cf 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,18 @@ script: # etc. ``` +It might happen that clippy is not available for a certain nightly release. +In this case you can try to conditionally install clippy from the git repo. + +```yaml +language: rust +rust: + - nightly +before_script: + - rustup component add clippy-preview --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy + # etc +``` + ## Configuration Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable = value` mapping eg. -- cgit 1.4.1-3-g733a5 From fad267c3b32895999f464c640d603f923fa0eeba Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 20 Nov 2018 10:33:40 +0100 Subject: Introduce snippet_with_applicability and hir_with_applicability functions --- clippy_lints/src/utils/mod.rs | 258 +++++++++++++++++++++++------------------ clippy_lints/src/utils/sugg.rs | 9 ++ 2 files changed, 151 insertions(+), 116 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 457aa3f8500..43af5e393c8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -7,44 +7,48 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::reexport::*; -use matches::matches; -use if_chain::if_chain; use crate::rustc::hir; -use crate::rustc::hir::*; -use crate::rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use crate::rustc::hir::def::Def; +use crate::rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use crate::rustc::hir::Node; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, Level, Lint, LintContext}; use crate::rustc::session::Session; use crate::rustc::traits; -use crate::rustc::ty::{self, Binder, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; +use crate::rustc::ty::{ + self, + layout::{self, IntegerExt}, + subst::Kind, + Binder, Ty, TyCtxt, +}; use crate::rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; -use std::borrow::Cow; -use std::env; -use std::mem; -use std::str::FromStr; -use std::rc::Rc; use crate::syntax::ast::{self, LitKind}; use crate::syntax::attr; -use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::errors::DiagnosticBuilder; +use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::symbol::{keywords, Symbol}; +use if_chain::if_chain; +use matches::matches; +use std::borrow::Cow; +use std::env; +use std::mem; +use std::rc::Rc; +use std::str::FromStr; pub mod camel_case; +pub mod author; pub mod comparisons; pub mod conf; pub mod constants; mod hir_utils; -pub mod paths; -pub mod sugg; pub mod inspector; pub mod internal_lints; -pub mod author; +pub mod paths; pub mod ptr; +pub mod sugg; pub mod usage; pub use self::hir_utils::{SpanlessEq, SpanlessHash}; @@ -101,11 +105,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> tcx.push_item_path(&mut apb, def_id, false); - apb.names.len() == path.len() - && apb.names - .into_iter() - .zip(path.iter()) - .all(|(a, &b)| *a == *b) + apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) } /// Check if type is struct, enum or union type with given def path. @@ -137,12 +137,9 @@ pub fn match_var(expr: &Expr, var: Name) -> bool { false } - pub fn last_path_segment(path: &QPath) -> &PathSegment { match *path { - QPath::Resolved(_, ref path) => path.segments - .last() - .expect("A path must have at least one segment"), + QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"), QPath::TypeRelative(_, ref seg) => seg, } } @@ -166,7 +163,8 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { QPath::Resolved(_, ref path) => match_path(path, segments), QPath::TypeRelative(ref ty, ref segment) => match ty.node { TyKind::Path(ref inner_path) => { - !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) + !segments.is_empty() + && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && segment.ident.name == segments[segments.len() - 1] }, _ => false, @@ -199,9 +197,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { /// Get the definition associated to a path. pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option { let crates = cx.tcx.crates(); - let krate = crates - .iter() - .find(|&&krate| cx.tcx.crate_name(krate) == path[0]); + let krate = crates.iter().find(|&&krate| cx.tcx.crate_name(krate) == path[0]); if let Some(krate) = krate { let krate = DefId { krate: *krate, @@ -254,10 +250,17 @@ pub fn implements_trait<'a, 'tcx>( ty_params: &[Kind<'tcx>], ) -> bool { let ty = cx.tcx.erase_regions(&ty); - let obligation = - cx.tcx - .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); - cx.tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold(&obligation)) + let obligation = cx.tcx.predicate_for_trait_def( + cx.param_env, + traits::ObligationCause::dummy(), + trait_id, + 0, + ty, + ty_params, + ); + cx.tcx + .infer_ctxt() + .enter(|infcx| infcx.predicate_must_hold(&obligation)) } /// Check whether this type implements Drop. @@ -326,14 +329,14 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option, expr: &Expr) -> Option { let parent_id = cx.tcx.hir.get_parent(expr.id); match cx.tcx.hir.find(parent_id) { Some(Node::Item(&Item { ref name, .. })) => Some(*name), - Some(Node::TraitItem(&TraitItem { ident, .. })) | - Some(Node::ImplItem(&ImplItem { ident, .. })) => Some(ident.name), + Some(Node::TraitItem(&TraitItem { ident, .. })) | Some(Node::ImplItem(&ImplItem { ident, .. })) => { + Some(ident.name) + }, _ => None, } } @@ -366,15 +369,11 @@ impl<'tcx> Visitor<'tcx> for ContainsName { /// check if an `Expr` contains a certain name pub fn contains_name(name: Name, expr: &Expr) -> bool { - let mut cn = ContainsName { - name, - result: false, - }; + let mut cn = ContainsName { name, result: false }; cn.visit_expr(expr); cn.result } - /// Convert a span to a code snippet if available, otherwise use default. /// /// # Example @@ -385,6 +384,31 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) } +pub fn snippet_with_applicability<'a, 'b, T: LintContext<'b>>( + cx: &T, + span: Span, + default: &'a str, + applicability: &mut Applicability, +) -> Cow<'a, str> { + snippet_opt(cx, span).map_or_else( + || { + // If the applicability is already `HasPlaceholders` or `MaybeIncorrect` don't change it. + // Also `Unspecified` shouldn't be changed + // Only if the applicability level is originally `MachineApplicable` and the default value + // has to be used change it to `HasPlaceholders` + if *applicability == Applicability::MachineApplicable { + if in_macro(span) { + *applicability = Applicability::MaybeIncorrect; + } else { + *applicability = Applicability::HasPlaceholders; + } + } + Cow::Borrowed(default) + }, + From::from, + ) +} + /// Same as `snippet`, but should only be used when it's clear that the input span is /// not a macro argument. pub fn snippet_with_macro_callsite<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { @@ -431,8 +455,7 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>( let string = option.unwrap_or_default(); if in_macro(expr.span) { Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default))) - } - else if let ExprKind::Block(_, _) = expr.node { + } else if let ExprKind::Block(_, _) = expr.node { Cow::Owned(format!("{}{}", code, string)) } else if string.is_empty() { Cow::Owned(format!("{{ {} }}", code)) @@ -450,19 +473,15 @@ pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool) -> Cow<'_, str> { } fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_, str> { - let x = s.lines() + let x = s + .lines() .skip(ignore_first as usize) .filter_map(|l| { if l.is_empty() { None } else { // ignore empty lines - Some( - l.char_indices() - .find(|&(_, x)| x != ch) - .unwrap_or((l.len(), ch)) - .0, - ) + Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0) } }) .min() @@ -505,7 +524,8 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { let map = &cx.tcx.hir; - let enclosing_node = map.get_enclosing_scope(node) + let enclosing_node = map + .get_enclosing_scope(node) .and_then(|enclosing_id| map.find(enclosing_id)); if let Some(node) = enclosing_node { match node { @@ -513,7 +533,8 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI Node::Item(&Item { node: ItemKind::Fn(_, _, _, eid), .. - }) | Node::ImplItem(&ImplItem { + }) + | Node::ImplItem(&ImplItem { node: ImplItemKind::Method(_, eid), .. }) => match cx.tcx.hir.body(eid).value.node { @@ -617,7 +638,8 @@ pub fn span_lint_node_and_then( /// Add a span lint with a suggestion on how to fix it. /// /// These suggestions can be parsed by rustfix to allow it to automatically fix your code. -/// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > 2)"`. +/// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > +/// 2)"`. /// /// ```ignore /// error: This `.fold` can be more succinctly expressed as `.any` @@ -652,18 +674,12 @@ where I: IntoIterator, { let sugg = CodeSuggestion { - substitutions: vec![ - Substitution { - parts: sugg.into_iter() - .map(|(span, snippet)| { - SubstitutionPart { - snippet, - span, - } - }) - .collect(), - } - ], + substitutions: vec![Substitution { + parts: sugg + .into_iter() + .map(|(span, snippet)| SubstitutionPart { snippet, span }) + .collect(), + }], msg: help_msg, show_code_when_inline: true, applicability: Applicability::Unspecified, @@ -729,9 +745,7 @@ impl LimitStack { Self { stack: vec![limit] } } pub fn limit(&self) -> u64 { - *self.stack - .last() - .expect("there should always be a value in the stack") + *self.stack.last().expect("there should always be a value in the stack") } pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; @@ -744,10 +758,11 @@ impl LimitStack { } pub fn get_attr<'a>(attrs: &'a [ast::Attribute], name: &'static str) -> impl Iterator { - attrs.iter().filter(move |attr| - attr.path.segments.len() == 2 && - attr.path.segments[0].ident.to_string() == "clippy" && - attr.path.segments[1].ident.to_string() == name) + attrs.iter().filter(move |attr| { + attr.path.segments.len() == 2 + && attr.path.segments[0].ident.to_string() == "clippy" + && attr.path.segments[1].ident.to_string() == name + }) } fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { @@ -769,7 +784,8 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt() + let span_name_span = span + .ctxt() .outer() .expn_info() .map(|ei| (ei.format.name(), ei.call_site)); @@ -792,7 +808,8 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt() + let span_name_span = span + .ctxt() .outer() .expn_info() .map(|ei| (ei.format.name(), ei.call_site)); @@ -855,23 +872,23 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool { PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), - PatKind::Struct(ref qpath, ref fields, _) => if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) + PatKind::Struct(ref qpath, ref fields, _) => { + if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) + } }, - PatKind::TupleStruct(ref qpath, ref pats, _) => if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, pats.iter().map(|pat| &**pat)) + PatKind::TupleStruct(ref qpath, ref pats, _) => { + if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, pats.iter().map(|pat| &**pat)) + } + }, + PatKind::Slice(ref head, ref middle, ref tail) => { + are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)) }, - PatKind::Slice(ref head, ref middle, ref tail) => are_refutable( - cx, - head.iter() - .chain(middle) - .chain(tail.iter()) - .map(|pat| &**pat), - ), } } @@ -903,32 +920,37 @@ pub fn remove_blocks(expr: &Expr) -> &Expr { pub fn opt_def_id(def: Def) -> Option { match def { - Def::Fn(id) | - Def::Mod(id) | - Def::Static(id, _) | - Def::Variant(id) | - Def::VariantCtor(id, ..) | - Def::Enum(id) | - Def::TyAlias(id) | - Def::AssociatedTy(id) | - Def::TyParam(id) | - Def::ForeignTy(id) | - Def::Struct(id) | - Def::StructCtor(id, ..) | - Def::Union(id) | - Def::Trait(id) | - Def::TraitAlias(id) | - Def::Method(id) | - Def::Const(id) | - Def::AssociatedConst(id) | - Def::Macro(id, ..) | - Def::Existential(id) | - Def::AssociatedExistential(id) | - Def::SelfCtor(id) - => Some(id), - - Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | - Def::ToolMod | Def::NonMacroAttr{..} | Def::Err => None, + Def::Fn(id) + | Def::Mod(id) + | Def::Static(id, _) + | Def::Variant(id) + | Def::VariantCtor(id, ..) + | Def::Enum(id) + | Def::TyAlias(id) + | Def::AssociatedTy(id) + | Def::TyParam(id) + | Def::ForeignTy(id) + | Def::Struct(id) + | Def::StructCtor(id, ..) + | Def::Union(id) + | Def::Trait(id) + | Def::TraitAlias(id) + | Def::Method(id) + | Def::Const(id) + | Def::AssociatedConst(id) + | Def::Macro(id, ..) + | Def::Existential(id) + | Def::AssociatedExistential(id) + | Def::SelfCtor(id) => Some(id), + + Def::Upvar(..) + | Def::Local(_) + | Def::Label(..) + | Def::PrimTy(..) + | Def::SelfTy(..) + | Def::ToolMod + | Def::NonMacroAttr { .. } + | Def::Err => None, } } @@ -1019,7 +1041,9 @@ pub fn get_arg_name(pat: &Pat) -> Option { } pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 { - layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits() + layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)) + .size() + .bits() } #[allow(clippy::cast_possible_wrap)] @@ -1038,7 +1062,9 @@ pub fn unsext(tcx: TyCtxt<'_, '_, '_>, u: i128, ity: ast::IntTy) -> u128 { /// clip unused bytes pub fn clip(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::UintTy) -> u128 { - let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits(); + let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)) + .size() + .bits(); let amt = 128 - bits; (u << amt) >> amt } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 90f48f0f83c..5bb35474403 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -96,6 +96,15 @@ impl<'a> Sugg<'a> { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } + pub fn hir_with_applicability(cx: &LateContext<'_, '_>, expr: &hir::Expr, default: &'a str, applicability: &mut Applicability) -> Self { + Self::hir_opt(cx, expr).unwrap_or_else(|| { + if *applicability == Applicability::MachineApplicable { + *applicability = Applicability::HasPlaceholders; + } + Sugg::NonParen(Cow::Borrowed(default)) + }) + } + /// Prepare a suggestion from an expression. pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self { use crate::syntax::ast::RangeLimits; -- cgit 1.4.1-3-g733a5 From 9096269610fcfc5cdc719dbe7d817de4cbb75201 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 20 Nov 2018 14:06:29 +0100 Subject: Add Applicability::Unspecified to span_lint_and_sugg functions --- clippy_lints/src/attrs.rs | 1 + clippy_lints/src/bytecount.rs | 29 ++++++++------ clippy_lints/src/collapsible_if.rs | 15 +++++--- clippy_lints/src/default_trait_access.rs | 7 +++- clippy_lints/src/double_comparison.rs | 13 +++++-- clippy_lints/src/duration_subsec.rs | 4 +- clippy_lints/src/else_if_without_else.rs | 4 +- clippy_lints/src/excessive_precision.rs | 10 +++-- clippy_lints/src/infallible_destructuring_match.rs | 2 + clippy_lints/src/len_zero.rs | 4 +- clippy_lints/src/literal_representation.rs | 6 +++ clippy_lints/src/loops.rs | 5 +++ clippy_lints/src/map_clone.rs | 10 ++--- clippy_lints/src/matches.rs | 6 ++- clippy_lints/src/mem_replace.rs | 4 +- clippy_lints/src/methods/mod.rs | 37 ++++++++++++------ clippy_lints/src/needless_bool.rs | 10 ++++- clippy_lints/src/no_effect.rs | 6 ++- clippy_lints/src/precedence.rs | 3 ++ clippy_lints/src/ptr_offset_with_cast.rs | 11 +++++- clippy_lints/src/redundant_field_names.rs | 6 ++- clippy_lints/src/reference.rs | 9 +++-- clippy_lints/src/replace_consts.rs | 8 ++-- clippy_lints/src/strings.rs | 3 ++ clippy_lints/src/trivially_copy_pass_by_ref.rs | 16 ++++---- clippy_lints/src/types.rs | 45 +++++++++++++--------- clippy_lints/src/use_self.rs | 8 ++-- clippy_lints/src/utils/internal_lints.rs | 2 + clippy_lints/src/utils/mod.rs | 3 +- clippy_lints/src/vec.rs | 8 ++-- clippy_lints/src/write.rs | 7 +++- 31 files changed, 204 insertions(+), 98 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 58af069f1d9..19306b81e4a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -532,6 +532,7 @@ impl EarlyLintPass for CfgAttrPass { "`cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes", "use", format!("{}rustfmt::skip]", attr_style), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index a61e823f959..1e738b9afa1 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -10,12 +10,14 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::{Name, UintTy}; -use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, - walk_ptrs_ty}; +use crate::utils::{ + contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, walk_ptrs_ty, +}; +use if_chain::if_chain; /// **What it does:** Checks for naive byte counts /// @@ -89,14 +91,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { } else { &filter_args[0] }; - span_lint_and_sugg(cx, - NAIVE_BYTECOUNT, - expr.span, - "You appear to be counting bytes the naive way", - "Consider using the bytecount crate", - format!("bytecount::count({}, {})", - snippet(cx, haystack.span, ".."), - snippet(cx, needle.span, ".."))); + span_lint_and_sugg( + cx, + NAIVE_BYTECOUNT, + expr.span, + "You appear to be counting bytes the naive way", + "Consider using the bytecount crate", + format!("bytecount::count({}, {})", + snippet(cx, haystack.span, ".."), + snippet(cx, needle.span, "..")), + Applicability::Unspecified, + ); } }; } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index a55ca04f706..2699ec0e7fd 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -128,12 +128,15 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { then { match else_.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { - span_lint_and_sugg(cx, - COLLAPSIBLE_IF, - block.span, - "this `else { if .. }` block can be collapsed", - "try", - snippet_block(cx, else_.span, "..").into_owned()); + span_lint_and_sugg( + cx, + COLLAPSIBLE_IF, + block.span, + "this `else { if .. }` block can be collapsed", + "try", + snippet_block(cx, else_.span, "..").into_owned(), + Applicability::Unspecified, + ); } _ => (), } diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 66d94e00d0d..17dccf2adfb 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -10,9 +10,10 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::ty::TyKind; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use if_chain::if_chain; -use crate::rustc::ty::TyKind; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; @@ -80,7 +81,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { expr.span, &format!("Calling {} is more clear than this expression", replacement), "try", - replacement); + replacement, + Applicability::Unspecified, + ); } }, QPath::TypeRelative(..) => {}, diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 0171ac1e784..f4c340538a7 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -13,6 +13,7 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; @@ -73,9 +74,15 @@ impl<'a, 'tcx> Pass { let lhs_str = snippet(cx, llhs.span, ""); let rhs_str = snippet(cx, lrhs.span, ""); let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str); - span_lint_and_sugg(cx, DOUBLE_COMPARISONS, span, - "This binary expression can be simplified", - "try", sugg); + span_lint_and_sugg( + cx, + DOUBLE_COMPARISONS, + span, + "This binary expression can be simplified", + "try", + sugg, + Applicability::Unspecified, + ); }} } match (op, lkind, rkind) { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index a679a97c2e7..5752968c1a2 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -11,8 +11,9 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Spanned; +use if_chain::if_chain; use crate::consts::{constant, Constant}; use crate::utils::paths; @@ -67,6 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { &format!("Calling `{}()` is more concise than this calculation", suggested_fn), "try", format!("{}.{}()", snippet(cx, args[0].span, "_"), suggested_fn), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 26ffef9ebe4..99031dd2887 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -12,6 +12,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::utils::span_lint_and_sugg; @@ -72,7 +73,8 @@ impl EarlyLintPass for ElseIfWithoutElse { els.span, "if expression with an `else if`, but without a final `else`", "add an `else` block here", - String::new() + String::new(), + Applicability::Unspecified, ); } diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 15a8d47337a..5f15f81205c 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -10,15 +10,16 @@ use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::ty::TyKind; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast::*; +use crate::syntax_pos::symbol::Symbol; +use crate::utils::span_lint_and_sugg; use if_chain::if_chain; -use crate::rustc::ty::TyKind; use std::f32; use std::f64; use std::fmt; -use crate::syntax::ast::*; -use crate::syntax_pos::symbol::Symbol; -use crate::utils::span_lint_and_sugg; /// **What it does:** Checks for float literals with a precision greater /// than that supported by the underlying type @@ -68,6 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { "float has excessive precision", "consider changing the type or truncating it to", sugg, + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 7bbbe72f91d..d212cf62390 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -12,6 +12,7 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_an use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use if_chain::if_chain; /// **What it does:** Checks for matches being used to destructure a single-variant enum @@ -84,6 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { snippet(cx, local.pat.span, ".."), snippet(cx, target.span, ".."), ), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 789a569f4cd..33457bb7044 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -11,9 +11,10 @@ use crate::rustc::hir::def_id::DefId; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashSet; +use crate::rustc_errors::Applicability; use crate::syntax::ast::{Lit, LitKind, Name}; use crate::syntax::source_map::{Span, Spanned}; use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -242,6 +243,7 @@ fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Ex &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), "using `is_empty` is clearer and more explicit", format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index bd54c068486..ebcb773d6f2 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -12,6 +12,7 @@ use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax_pos; use crate::utils::{snippet_opt, span_lint_and_sugg}; @@ -300,6 +301,7 @@ impl WarningType { "mistyped literal suffix", "did you mean to write", grouping_hint.to_string(), + Applicability::Unspecified, ), WarningType::UnreadableLiteral => span_lint_and_sugg( cx, @@ -308,6 +310,7 @@ impl WarningType { "long literal lacking separators", "consider", grouping_hint.to_owned(), + Applicability::Unspecified, ), WarningType::LargeDigitGroups => span_lint_and_sugg( cx, @@ -316,6 +319,7 @@ impl WarningType { "digit groups should be smaller", "consider", grouping_hint.to_owned(), + Applicability::Unspecified, ), WarningType::InconsistentDigitGrouping => span_lint_and_sugg( cx, @@ -324,6 +328,7 @@ impl WarningType { "digits grouped inconsistently by underscores", "consider", grouping_hint.to_owned(), + Applicability::Unspecified, ), WarningType::DecimalRepresentation => span_lint_and_sugg( cx, @@ -332,6 +337,7 @@ impl WarningType { "integer literal has a better hexadecimal representation", "consider", grouping_hint.to_owned(), + Applicability::Unspecified, ), }; } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0d1b960cc1f..e04fc6ea17f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -512,6 +512,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, matchexpr.span, "..") ), + Applicability::Unspecified, ); } }, @@ -549,6 +550,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "this loop could be written as a `for` loop", "try", format!("for {} in {} {{ .. }}", loop_var, iterator), + Applicability::Unspecified, ); } } @@ -1027,6 +1029,7 @@ fn detect_manual_memcpy<'a, 'tcx>( "it looks like you're manually copying between slices", "try replacing the loop by", big_sugg, + Applicability::Unspecified, ); } } @@ -1316,6 +1319,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_ iteration methods", "to write this more concisely, try", format!("&{}{}", muta, object), + Applicability::Unspecified, ) } @@ -1354,6 +1358,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex iteration methods`", "to write this more concisely, try", object.to_string(), + Applicability::Unspecified, ); } } else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index b2c08e6ae8c..2fd5c6187c3 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -11,15 +11,12 @@ use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast::Ident; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{ - in_macro, match_trait_method, match_type, - remove_blocks, snippet, - span_lint_and_sugg, -}; +use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet, span_lint_and_sugg}; use if_chain::if_chain; -use crate::syntax::ast::Ident; #[derive(Clone)] pub struct Pass; @@ -102,6 +99,7 @@ fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: "You are using an explicit closure for cloning elements", "Consider calling the dedicated `cloned` method", format!("{}.cloned()", snippet(cx, root, "..")), + Applicability::Unspecified, ) } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 9e2dac8fef1..f96ab2f924e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -268,8 +268,9 @@ fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, ex.span, ".."), expr_block(cx, &arms[0].body, None, ".."), - els_str + els_str, ), + Applicability::Unspecified, ); } @@ -483,7 +484,8 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & expr.span, &format!("use {}() instead", suggestion), "try this", - format!("{}.{}()", snippet(cx, ex.span, "_"), suggestion) + format!("{}.{}()", snippet(cx, ex.span, "_"), suggestion), + Applicability::Unspecified, ) } } diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index ff57571a948..684f58a08ef 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -11,6 +11,7 @@ use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet, span_lint_and_sugg}; use if_chain::if_chain; @@ -85,7 +86,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { expr.span, "replacing an `Option` with `None`", "consider `Option::take()` instead", - format!("{}.take()", snippet(cx, replaced_path.span, "")) + format!("{}.take()", snippet(cx, replaced_path.span, "")), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e3c704b77ad..dcee380f455 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1042,6 +1042,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa &format!("use of `{}` followed by a call to `{}`", name, path), "try this", format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")), + Applicability::Unspecified, ); return true; } @@ -1111,6 +1112,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa &format!("use of `{}` followed by a function call", name), "try this", format!("{}_{}({})", name, suffix, sugg), + Applicability::Unspecified, ); } @@ -1224,6 +1226,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: &format!("use of `{}` followed by a function call", name), "try this", format!("unwrap_or_else({} panic!({}))", closure, sugg), + Applicability::Unspecified, ); return; @@ -1238,6 +1241,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: &format!("use of `{}` followed by a function call", name), "try this", format!("unwrap_or_else({} {{ let msg = {}; panic!(msg) }}))", closure, sugg), + Applicability::Unspecified, ); } @@ -1354,6 +1358,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir:: "using '.clone()' on a ref-counted pointer", "try this", format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), + Applicability::Unspecified, ); } } @@ -1384,6 +1389,7 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E ref_str, snippet(cx, target.span, "_") ), + Applicability::Unspecified, ); } } @@ -1482,6 +1488,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: "this `.fold` can be written more succinctly using another method", "try", sugg, + Applicability::Unspecified, ); } } @@ -1589,6 +1596,7 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: snippet(cx, get_args[0].span, "_"), get_args_str ), + Applicability::Unspecified, ); } @@ -2010,16 +2018,19 @@ fn lint_chars_cmp( return false; } - span_lint_and_sugg(cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}({})", - if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), - suggest, - snippet(cx, arg_char[0].span, "_"))); + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, + snippet(cx, args[0][0].span, "_"), + suggest, + snippet(cx, arg_char[0].span, "_")), + Applicability::Unspecified, + ); return true; } @@ -2065,7 +2076,8 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( if info.eq { "" } else { "!" }, snippet(cx, args[0][0].span, "_"), suggest, - c) + c), + Applicability::Unspecified, ); return true; @@ -2105,6 +2117,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h "single-character string constant used as pattern", "try using a char instead", hint, + Applicability::Unspecified, ); } } @@ -2129,6 +2142,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re &format!("this call to `{}` does nothing", call_name), "try this", snippet(cx, recvr.span, "_").into_owned(), + Applicability::Unspecified, ); } } @@ -2194,6 +2208,7 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::T ), "call directly", method_name.to_owned(), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 0019380a34c..8ed319c6736 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -12,13 +12,14 @@ //! //! This lint is **warn** by default +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Spanned; -use crate::utils::{in_macro, snippet, span_lint, span_lint_and_sugg}; use crate::utils::sugg::Sugg; +use crate::utils::{in_macro, snippet, span_lint, span_lint_and_sugg}; /// **What it does:** Checks for expressions of the form `if c { true } else { /// false }` @@ -89,6 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { "this if-then-else expression returns a bool literal", "you can reduce it to", hint, + Applicability::Unspecified, ); }; if let ExprKind::Block(ref then_block, _) = then_block.node { @@ -150,6 +152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against true are unnecessary", "try simplifying it as shown", hint, + Applicability::Unspecified, ); }, (Other, Bool(true)) => { @@ -161,6 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against true are unnecessary", "try simplifying it as shown", hint, + Applicability::Unspecified, ); }, (Bool(false), Other) => { @@ -172,6 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against false can be replaced by a negation", "try simplifying it as shown", (!hint).to_string(), + Applicability::Unspecified, ); }, (Other, Bool(false)) => { @@ -183,6 +188,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against false can be replaced by a negation", "try simplifying it as shown", (!hint).to_string(), + Applicability::Unspecified, ); }, _ => (), diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 289b5591edc..877cd5ab1e4 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -8,10 +8,11 @@ // except according to those terms. -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::def::Def; use crate::rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; @@ -131,6 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "statement can be reduced", "replace it with", snippet, + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 1c5e8fcb964..4376db5e9b3 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -10,6 +10,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax::source_map::Spanned; use crate::utils::{in_macro, snippet, span_lint_and_sugg}; @@ -61,6 +62,7 @@ impl EarlyLintPass for Precedence { "operator precedence can trip the unwary", "consider parenthesizing your expression", sugg, + Applicability::Unspecified, ); }; @@ -112,6 +114,7 @@ impl EarlyLintPass for Precedence { "unary minus has lower precedence than method call", "consider adding parentheses to clarify your intent", format!("-({})", snippet(cx, rhs.span, "..")), + Applicability::Unspecified, ); }, _ => (), diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 58afdc351d1..e653ae2ff75 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -9,6 +9,7 @@ use crate::rustc::{declare_tool_lint, hir, lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::utils; use std::fmt; @@ -69,7 +70,15 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { let msg = format!("use of `{}` with a `usize` casted to an `isize`", method); if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) { - utils::span_lint_and_sugg(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg, "try", sugg); + utils::span_lint_and_sugg( + cx, + PTR_OFFSET_WITH_CAST, + expr.span, + &msg, + "try", + sugg, + Applicability::Unspecified, + ); } else { utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 526232f7853..2acea17be26 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -10,6 +10,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::utils::{span_lint_and_sugg}; @@ -58,13 +59,14 @@ impl EarlyLintPass for RedundantFieldNames { } if let ExprKind::Path(None, path) = &field.expr.node { if path.segments.len() == 1 && path.segments[0].ident == field.ident { - span_lint_and_sugg ( + span_lint_and_sugg( cx, REDUNDANT_FIELD_NAMES, field.span, "redundant field names in struct initialization", "replace it with", - field.ident.to_string() + field.ident.to_string(), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 79d30612cbd..aac3d09bfd3 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -8,11 +8,12 @@ // except according to those terms. -use crate::syntax::ast::{Expr, ExprKind, UnOp}; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc_errors::Applicability; +use crate::syntax::ast::{Expr, ExprKind, UnOp}; use crate::utils::{snippet, span_lint_and_sugg}; +use if_chain::if_chain; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. /// @@ -61,6 +62,7 @@ impl EarlyLintPass for Pass { "immediately dereferencing a reference", "try this", format!("{}", snippet(cx, addrof_target.span, "_")), + Applicability::Unspecified, ); } } @@ -110,7 +112,8 @@ impl EarlyLintPass for DerefPass { "{}.{}", snippet(cx, inner.span, "_"), snippet(cx, field_name.span, "_") - ) + ), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index ca17a032526..1c204912f17 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -8,12 +8,13 @@ // except according to those terms. -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::def::Def; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, span_lint_and_sugg}; +use if_chain::if_chain; /// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and /// `uX/iX::MIN/MAX`. @@ -61,6 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { &format!("using `{}`", const_path.last().expect("empty path")), "try this", repl_snip.to_string(), + Applicability::Unspecified, ); return; } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index e07b1649a46..74d5e304b87 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -10,6 +10,7 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Spanned; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -185,6 +186,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { "calling `as_bytes()` on `include_str!(..)`", "consider using `include_bytes!(..)` instead", snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1), + Applicability::Unspecified, ); } else if callsite == expanded && lit_content.as_str().chars().all(|c| c.is_ascii()) @@ -197,6 +199,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { "calling `as_bytes()` on a string literal", "consider using a byte string literal instead", format!("b{}", snippet(cx, args[0].span, r#""foo""#)), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 2929752bbb2..467713694e1 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -10,21 +10,21 @@ use std::cmp; -use matches::matches; use crate::rustc::hir; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::FnKind; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::ty::TyKind; -use crate::rustc::ty::FnSig; use crate::rustc::session::config::Config as SessionConfig; -use crate::rustc_target::spec::abi::Abi; +use crate::rustc::ty::TyKind; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::rustc_target::abi::LayoutOf; +use crate::rustc_target::spec::abi::Abi; use crate::syntax::ast::NodeId; use crate::syntax_pos::Span; -use crate::utils::{in_macro, is_copy, is_self_ty, span_lint_and_sugg, snippet}; +use crate::utils::{in_macro, is_copy, is_self, snippet, span_lint_and_sugg}; +use if_chain::if_chain; +use matches::matches; /// **What it does:** Checks for functions taking arguments by reference, where /// the argument type is `Copy` and small enough to be more efficient to always diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d7adcd17981..4a9cb04a0ac 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -10,28 +10,31 @@ #![allow(clippy::default_hash_types)] +use crate::consts::{constant, Constant}; use crate::reexport::*; use crate::rustc::hir; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables}; +use crate::rustc::hir::*; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty::layout::LayoutOf; +use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::rustc_target::spec::abi::Abi; use crate::rustc_typeck::hir_ty_to_ty; -use std::cmp::Ordering; -use std::collections::BTreeMap; -use std::borrow::Cow; use crate::syntax::ast::{FloatTy, IntTy, UintTy}; -use crate::syntax::source_map::Span; use crate::syntax::errors::DiagnosticBuilder; -use crate::rustc_target::spec::abi::Abi; -use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_macro, last_path_segment, match_def_path, match_path, - match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; +use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::consts::{constant, Constant}; +use crate::utils::{ + clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, + match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, + span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, +}; +use if_chain::if_chain; +use std::borrow::Cow; +use std::cmp::Ordering; +use std::collections::BTreeMap; /// Handles all the linting of funky types pub struct TypePass; @@ -338,12 +341,14 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: } else { "" }; - span_lint_and_sugg(cx, + span_lint_and_sugg( + cx, BORROWED_BOX, ast_ty.span, "you seem to be trying to use `&Box`. Consider using just `&T`", "try", - format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")) + format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")), + Applicability::Unspecified, ); return; // don't recurse into the type } @@ -537,6 +542,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { "passing a unit value to a function", "if you intended to pass a unit value, use a unit literal instead", "()".to_string(), + Applicability::Unspecified, ); } } @@ -874,6 +880,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to), "try", format!("{}::from({})", cast_to, sugg), + Applicability::Unspecified, ); } @@ -1103,7 +1110,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex expr.span, &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to), "try", - format!("{} as usize", from_snippet) + format!("{} as usize", from_snippet), + Applicability::Unspecified, ); } else if cast_to.sty != ty::Uint(UintTy::Usize) { @@ -1113,7 +1121,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex expr.span, &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to), "try", - format!("{} as usize", from_snippet) + format!("{} as usize", from_snippet), + Applicability::Unspecified, ); } }, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index ad4ced995ba..ea9deb7a804 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -8,15 +8,16 @@ // except according to those terms. -use crate::utils::{in_macro, span_lint_and_sugg}; -use if_chain::if_chain; use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax_pos::symbol::keywords::SelfType; +use crate::rustc_errors::Applicability; use crate::syntax::ast::NodeId; +use crate::syntax_pos::symbol::keywords::SelfType; +use crate::utils::{in_macro, span_lint_and_sugg}; +use if_chain::if_chain; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. @@ -70,6 +71,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { "unnecessary structure name repetition", "use the applicable keyword", "Self".to_owned(), + Applicability::Unspecified, ); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 879157ec8a4..740da22ba1c 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -18,6 +18,7 @@ use crate::rustc::hir::*; use crate::rustc::hir::def::Def; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use crate::syntax::source_map::Span; @@ -281,6 +282,7 @@ impl EarlyLintPass for DefaultHashTypes { &msg, "use", replace.to_string(), + Applicability::Unspecified, ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 43af5e393c8..3c19cfe1805 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -657,9 +657,10 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( msg: &str, help: &str, sugg: String, + applicability: Applicability, ) { span_lint_and_then(cx, lint, sp, msg, |db| { - db.span_suggestion_with_applicability(sp, help, sugg, Applicability::Unspecified); + db.span_suggestion_with_applicability(sp, help, sugg, applicability); }); } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 21a33bd143f..0dd9af6db16 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -8,14 +8,15 @@ // except according to those terms. +use crate::consts::constant; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty::{self, Ty}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; -use crate::consts::constant; +use if_chain::if_chain; /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would /// be possible. @@ -100,6 +101,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA "useless use of `vec!`", "you can use a slice directly", snippet, + Applicability::Unspecified, ); } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index f84362fdbbc..c0161ecf532 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -8,13 +8,14 @@ // except according to those terms. -use crate::utils::{snippet, span_lint, span_lint_and_sugg}; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use std::borrow::Cow; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax::parse::{parser, token}; use crate::syntax::tokenstream::{ThinTokenStream, TokenStream}; +use crate::utils::{snippet, span_lint, span_lint_and_sugg}; +use std::borrow::Cow; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -199,6 +200,7 @@ impl EarlyLintPass for Pass { "using `println!(\"\")`", "replace it with", "println!()".to_string(), + Applicability::Unspecified, ); } } @@ -248,6 +250,7 @@ impl EarlyLintPass for Pass { format!("using `writeln!({}, \"\")`", suggestion).as_str(), "replace it with", format!("writeln!({})", suggestion), + Applicability::Unspecified, ); } } -- cgit 1.4.1-3-g733a5 From 3740da203b6e65f19b5075379c494616d60e5f80 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 15:11:13 +0100 Subject: Fix bugs and improve documentation Some bugs and some documentation is unrelated to the Applicability change, but these bugs were serious and the documentation was kind of required to understand what's going on. --- clippy_lints/src/else_if_without_else.rs | 7 ++----- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 31 ++++++++++++++++++++++--------- clippy_lints/src/utils/sugg.rs | 18 ++++++++++++++++-- clippy_lints/src/write.rs | 14 ++++++++++++++ 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 99031dd2887..cb75d983683 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -12,10 +12,9 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::syntax::ast::*; -use crate::utils::span_lint_and_sugg; +use crate::utils::span_help_and_lint; /// **What it does:** Checks for usage of if expressions with an `else if` branch, /// but without a final `else` branch. @@ -67,14 +66,12 @@ impl EarlyLintPass for ElseIfWithoutElse { while let ExprKind::If(_, _, Some(ref els)) = item.node { if let ExprKind::If(_, _, None) = els.node { - span_lint_and_sugg( + span_help_and_lint( cx, ELSE_IF_WITHOUT_ELSE, els.span, "if expression with an `else if`, but without a final `else`", "add an `else` block here", - String::new(), - Applicability::Unspecified, ); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index dcee380f455..82c3274d43b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2046,10 +2046,10 @@ fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn /// Checks for the `CHARS_LAST_CMP` lint. fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") { + if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { true } else { - lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_NEXT_CMP, "ends_with") + lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3c19cfe1805..0c6935d867d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -384,24 +384,25 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) } +/// Same as `snippet`, but it adapts the applicability level by following rules: +/// +/// - Applicability level `Unspecified` will never be changed. +/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. +/// - If the default value is used and the applicability level is `MachineApplicable`, change it to +/// `HasPlaceholders` pub fn snippet_with_applicability<'a, 'b, T: LintContext<'b>>( cx: &T, span: Span, default: &'a str, applicability: &mut Applicability, ) -> Cow<'a, str> { + if *applicability != Applicability::Unspecified && in_macro(span) { + *applicability = Applicability::MaybeIncorrect; + } snippet_opt(cx, span).map_or_else( || { - // If the applicability is already `HasPlaceholders` or `MaybeIncorrect` don't change it. - // Also `Unspecified` shouldn't be changed - // Only if the applicability level is originally `MachineApplicable` and the default value - // has to be used change it to `HasPlaceholders` if *applicability == Applicability::MachineApplicable { - if in_macro(span) { - *applicability = Applicability::MaybeIncorrect; - } else { - *applicability = Applicability::HasPlaceholders; - } + *applicability = Applicability::HasPlaceholders; } Cow::Borrowed(default) }, @@ -435,6 +436,18 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &' trim_multiline(snip, true) } +/// Same as `snippet_block`, but adapts the applicability level by the rules of +/// `snippet_with_applicabiliy`. +pub fn snippet_block_with_applicability<'a, 'b, T: LintContext<'b>>( + cx: &T, + span: Span, + default: &'a str, + applicability: &mut Applicability, +) -> Cow<'a, str> { + let snip = snippet_with_applicability(cx, span, default, applicability); + trim_multiline(snip, true) +} + /// Returns a new Span that covers the full last line of the given Span pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span { let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 5bb35474403..b4c9868bbd6 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -24,7 +24,7 @@ use crate::syntax::parse::token; use crate::syntax::print::pprust::token_to_string; use crate::syntax::util::parser::AssocOp; use crate::syntax::ast; -use crate::utils::{higher, snippet, snippet_opt}; +use crate::utils::{higher, in_macro, snippet, snippet_opt}; use crate::syntax_pos::{BytePos, Pos}; use crate::rustc_errors::Applicability; @@ -96,7 +96,21 @@ impl<'a> Sugg<'a> { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } - pub fn hir_with_applicability(cx: &LateContext<'_, '_>, expr: &hir::Expr, default: &'a str, applicability: &mut Applicability) -> Self { + /// Same as `hir`, but it adapts the applicability level by following rules: + /// + /// - Applicability level `Unspecified` will never be changed. + /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. + /// - If the default value is used and the applicability level is `MachineApplicable`, change it to + /// `HasPlaceholders` + pub fn hir_with_applicability( + cx: &LateContext<'_, '_>, + expr: &hir::Expr, + default: &'a str, + applicability: &mut Applicability, + ) -> Self { + if *applicability != Applicability::Unspecified && in_macro(expr.span) { + *applicability = Applicability::MaybeIncorrect; + } Self::hir_opt(cx, expr).unwrap_or_else(|| { if *applicability == Applicability::MachineApplicable { *applicability = Applicability::HasPlaceholders; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c0161ecf532..76e07a2d3b3 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -258,6 +258,20 @@ impl EarlyLintPass for Pass { } } +/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two +/// options. The first part of the tuple is format_str of the macros. The secund part of the tuple +/// is in the `write[ln]!` case the expression the format_str should be written to. +/// +/// Example: +/// +/// Calling this function on +/// ```rust,ignore +/// writeln!(buf, "string to write: {}", something) +/// ``` +/// will return +/// ```rust,ignore +/// (Some("string to write: {}"), Some(buf)) +/// ``` fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { use crate::fmt_macros::*; let tts = TokenStream::from(tts.clone()); -- cgit 1.4.1-3-g733a5 From 0c6483bf215245c190d7a47bc9f3067bbc887e63 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 15:27:34 +0100 Subject: Update stderr file --- tests/ui/else_if_without_else.stderr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 9eddd4ab30d..7c8afcf3ce1 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -5,9 +5,10 @@ error: if expression with an `else if`, but without a final `else` | ____________^ 52 | | println!("else if"); 53 | | } - | |_____^ help: add an `else` block here + | |_____^ | = note: `-D clippy::else-if-without-else` implied by `-D warnings` + = help: add an `else` block here error: if expression with an `else if`, but without a final `else` --> $DIR/else_if_without_else.rs:59:12 @@ -16,7 +17,9 @@ error: if expression with an `else if`, but without a final `else` | ____________^ 60 | | println!("else if 2"); 61 | | } - | |_____^ help: add an `else` block here + | |_____^ + | + = help: add an `else` block here error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 4e74eef6e9225973c73c555c9a324791e8be3958 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 15:13:57 +0100 Subject: Add applicability level to (nearly) every span_lint_and_sugg function --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/bytecount.rs | 8 ++- clippy_lints/src/collapsible_if.rs | 7 +- clippy_lints/src/default_trait_access.rs | 2 +- clippy_lints/src/double_comparison.rs | 9 +-- clippy_lints/src/duration_subsec.rs | 7 +- clippy_lints/src/excessive_precision.rs | 2 +- clippy_lints/src/infallible_destructuring_match.rs | 11 ++-- clippy_lints/src/len_zero.rs | 17 +++-- clippy_lints/src/literal_representation.rs | 10 +-- clippy_lints/src/loops.rs | 29 ++++---- clippy_lints/src/map_clone.rs | 7 +- clippy_lints/src/matches.rs | 9 +-- clippy_lints/src/mem_replace.rs | 7 +- clippy_lints/src/methods/mod.rs | 77 +++++++++++++--------- clippy_lints/src/needless_bool.rs | 28 ++++---- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/precedence.rs | 30 +++++---- clippy_lints/src/ptr_offset_with_cast.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/reference.rs | 14 ++-- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/strings.rs | 18 +++-- clippy_lints/src/trivially_copy_pass_by_ref.rs | 8 ++- clippy_lints/src/types.rs | 20 +++--- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/vec.rs | 13 ++-- clippy_lints/src/write.rs | 17 +++-- 29 files changed, 216 insertions(+), 148 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 19306b81e4a..88b61f07422 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -532,7 +532,7 @@ impl EarlyLintPass for CfgAttrPass { "`cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes", "use", format!("{}rustfmt::skip]", attr_style), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 1e738b9afa1..0547837795d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -15,7 +15,8 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::{Name, UintTy}; use crate::utils::{ - contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg, walk_ptrs_ty, + contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, + span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; @@ -91,6 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { } else { &filter_args[0] }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, NAIVE_BYTECOUNT, @@ -98,8 +100,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { "You appear to be counting bytes the naive way", "Consider using the bytecount crate", format!("bytecount::count({}, {})", - snippet(cx, haystack.span, ".."), - snippet(cx, needle.span, "..")), + snippet_with_applicability(cx, haystack.span, "..", &mut applicability), + snippet_with_applicability(cx, needle.span, "..", &mut applicability)), Applicability::Unspecified, ); } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 2699ec0e7fd..206403791a1 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -27,7 +27,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use crate::syntax::ast; -use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; +use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; use crate::utils::sugg::Sugg; use crate::rustc_errors::Applicability; @@ -128,14 +128,15 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { then { match else_.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, COLLAPSIBLE_IF, block.span, "this `else { if .. }` block can be collapsed", "try", - snippet_block(cx, else_.span, "..").into_owned(), - Applicability::Unspecified, + snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(), + applicability, ); } _ => (), diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 17dccf2adfb..693b47f6fff 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { &format!("Calling {} is more clear than this expression", replacement), "try", replacement, - Applicability::Unspecified, + Applicability::Unspecified, // First resolve the TODO above ); } }, diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index f4c340538a7..4d8345dadc3 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -16,7 +16,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; -use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq}; +use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; /// **What it does:** Checks for double comparions that could be simpified to a single expression. /// @@ -71,8 +71,9 @@ impl<'a, 'tcx> Pass { } macro_rules! lint_double_comparison { ($op:tt) => {{ - let lhs_str = snippet(cx, llhs.span, ""); - let rhs_str = snippet(cx, lrhs.span, ""); + let mut applicability = Applicability::MachineApplicable; + let lhs_str = snippet_with_applicability(cx, llhs.span, "", &mut applicability); + let rhs_str = snippet_with_applicability(cx, lrhs.span, "", &mut applicability); let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str); span_lint_and_sugg( cx, @@ -81,7 +82,7 @@ impl<'a, 'tcx> Pass { "This binary expression can be simplified", "try", sugg, - Applicability::Unspecified, + applicability, ); }} } diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 5752968c1a2..fe4aea572e0 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -17,7 +17,7 @@ use if_chain::if_chain; use crate::consts::{constant, Constant}; use crate::utils::paths; -use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{match_type, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for calculation of subsecond microseconds or milliseconds /// from other `Duration` methods. @@ -61,14 +61,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { ("subsec_nanos", 1_000) => "subsec_micros", _ => return, }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, DURATION_SUBSEC, expr.span, &format!("Calling `{}()` is more concise than this calculation", suggested_fn), "try", - format!("{}.{}()", snippet(cx, args[0].span, "_"), suggested_fn), - Applicability::Unspecified, + format!("{}.{}()", snippet_with_applicability(cx, args[0].span, "_", &mut applicability), suggested_fn), + applicability, ); } } diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 5f15f81205c..6043dd46ae7 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { "float has excessive precision", "consider changing the type or truncating it to", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index d212cf62390..558d101d68e 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -8,7 +8,7 @@ // except according to those terms. -use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg}; +use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -72,6 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if match_var(body, arg); then { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, INFALLIBLE_DESTRUCTURING_MATCH, @@ -81,11 +82,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "try this", format!( "let {}({}) = {};", - snippet(cx, variant_name.span, ".."), - snippet(cx, local.pat.span, ".."), - snippet(cx, target.span, ".."), + snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), + snippet_with_applicability(cx, local.pat.span, "..", &mut applicability), + snippet_with_applicability(cx, target.span, "..", &mut applicability), ), - Applicability::Unspecified, + applicability, ); } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 33457bb7044..15c21d77698 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -17,7 +17,7 @@ use crate::rustc_data_structures::fx::FxHashSet; use crate::rustc_errors::Applicability; use crate::syntax::ast::{Lit, LitKind, Name}; use crate::syntax::source_map::{Span, Spanned}; -use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for getting the length of something via `.len()` /// just to compare to zero, and suggests using `.is_empty()` where applicable. @@ -224,7 +224,15 @@ fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op } } -fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) { +fn check_len( + cx: &LateContext<'_, '_>, + span: Span, + method_name: Name, + args: &[Expr], + lit: &Lit, + op: &str, + compare_to: u32, +) { if let Spanned { node: LitKind::Int(lit, _), .. @@ -236,14 +244,15 @@ fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Ex } if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, LEN_ZERO, span, &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), "using `is_empty` is clearer and more explicit", - format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")), - Applicability::Unspecified, + format!("{}{}.is_empty()", op, snippet_with_applicability(cx, args[0].span, "_", &mut applicability)), + applicability, ); } } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index ebcb773d6f2..8d7f549da39 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -301,7 +301,7 @@ impl WarningType { "mistyped literal suffix", "did you mean to write", grouping_hint.to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, ), WarningType::UnreadableLiteral => span_lint_and_sugg( cx, @@ -310,7 +310,7 @@ impl WarningType { "long literal lacking separators", "consider", grouping_hint.to_owned(), - Applicability::Unspecified, + Applicability::MachineApplicable, ), WarningType::LargeDigitGroups => span_lint_and_sugg( cx, @@ -319,7 +319,7 @@ impl WarningType { "digit groups should be smaller", "consider", grouping_hint.to_owned(), - Applicability::Unspecified, + Applicability::MachineApplicable, ), WarningType::InconsistentDigitGrouping => span_lint_and_sugg( cx, @@ -328,7 +328,7 @@ impl WarningType { "digits grouped inconsistently by underscores", "consider", grouping_hint.to_owned(), - Applicability::Unspecified, + Applicability::MachineApplicable, ), WarningType::DecimalRepresentation => span_lint_and_sugg( cx, @@ -337,7 +337,7 @@ impl WarningType { "integer literal has a better hexadecimal representation", "consider", grouping_hint.to_owned(), - Applicability::Unspecified, + Applicability::MachineApplicable, ), }; } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e04fc6ea17f..0704246d450 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -35,10 +35,12 @@ use crate::utils::{in_macro, sugg, sext}; use crate::utils::usage::mutated_variables; use crate::consts::{constant, Constant}; -use crate::utils::{get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable, - last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, - span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq}; use crate::utils::paths; +use crate::utils::{ + get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable, last_path_segment, + match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, snippet_with_applicability, + span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq, +}; /// **What it does:** Checks for for-loops that manually copy items between /// slices that could be optimized by having a memcpy. @@ -501,6 +503,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // 1) it was ugly with big bodies; // 2) it was not indented properly; // 3) it wasn’t very smart (see #675). + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, WHILE_LET_LOOP, @@ -509,10 +512,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "try", format!( "while let {} = {} {{ .. }}", - snippet(cx, arms[0].pats[0].span, ".."), - snippet(cx, matchexpr.span, "..") + snippet_with_applicability(cx, arms[0].pats[0].span, "..", &mut applicability), + snippet_with_applicability(cx, matchexpr.span, "..", &mut applicability), ), - Applicability::Unspecified, + applicability, ); } }, @@ -550,7 +553,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "this loop could be written as a `for` loop", "try", format!("for {} in {} {{ .. }}", loop_var, iterator), - Applicability::Unspecified, + Applicability::HasPlaceholders, ); } } @@ -1006,7 +1009,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let big_sugg = manual_copies .into_iter() .map(|(dst_var, src_var)| { - let start_str = Offset::positive(snippet_opt(cx, start.span).unwrap_or_else(|| "".into())); + let start_str = Offset::positive(snippet(cx, start.span, "").to_string()); let dst_offset = print_sum(&start_str, &dst_var.offset); let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); let src_offset = print_sum(&start_str, &src_var.offset); @@ -1305,7 +1308,8 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx } fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) { - let object = snippet(cx, args[0].span, "_"); + let mut applicability = Applicability::MachineApplicable; + let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); let muta = if method_name == "iter_mut" { "mut " } else { @@ -1319,7 +1323,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_ iteration methods", "to write this more concisely, try", format!("&{}{}", muta, object), - Applicability::Unspecified, + applicability, ) } @@ -1349,7 +1353,8 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex _ => lint_iter_method(cx, args, arg, method_name), }; } else { - let object = snippet(cx, args[0].span, "_"); + let mut applicability = Applicability::MachineApplicable; + let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); span_lint_and_sugg( cx, EXPLICIT_INTO_ITER_LOOP, @@ -1358,7 +1363,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex iteration methods`", "to write this more concisely, try", object.to_string(), - Applicability::Unspecified, + applicability, ); } } else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 2fd5c6187c3..4424143160c 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -15,7 +15,7 @@ use crate::rustc_errors::Applicability; use crate::syntax::ast::Ident; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; #[derive(Clone)] @@ -92,14 +92,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) { if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node { if path.segments.len() == 1 && path.segments[0].ident == name { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, MAP_CLONE, replace, "You are using an explicit closure for cloning elements", "Consider calling the dedicated `cloned` method", - format!("{}.cloned()", snippet(cx, root, "..")), - Applicability::Unspecified, + format!("{}.cloned()", snippet_with_applicability(cx, root, "..", &mut applicability)), + applicability, ) } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index f96ab2f924e..583cdee843f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -19,7 +19,7 @@ use crate::syntax::ast::LitKind; use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type, - multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, + multispan_sugg, remove_blocks, snippet, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; use crate::consts::{constant, Constant}; @@ -270,7 +270,7 @@ fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: expr_block(cx, &arms[0].body, None, ".."), els_str, ), - Applicability::Unspecified, + Applicability::HasPlaceholders, ); } @@ -478,14 +478,15 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & }; if let Some(rb) = arm_ref { let suggestion = if rb == BindingAnnotation::Ref { "as_ref" } else { "as_mut" }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, MATCH_AS_REF, expr.span, &format!("use {}() instead", suggestion), "try this", - format!("{}.{}()", snippet(cx, ex.span, "_"), suggestion), - Applicability::Unspecified, + format!("{}.{}()", snippet_with_applicability(cx, ex.span, "_", &mut applicability), suggestion), + applicability, ) } } diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 684f58a08ef..f0310b87f69 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -12,7 +12,7 @@ use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; -use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet, span_lint_and_sugg}; +use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; /// **What it does:** Checks for `mem::replace()` on an `Option` with @@ -80,14 +80,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { _ => return, }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, MEM_REPLACE_OPTION_WITH_NONE, expr.span, "replacing an `Option` with `None`", "consider `Option::take()` instead", - format!("{}.take()", snippet(cx, replaced_path.span, "")), - Applicability::Unspecified, + format!("{}.take()", snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)), + applicability, ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 82c3274d43b..dc939ad0815 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -22,8 +22,9 @@ use crate::utils::sugg; use crate::utils::{ get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, - match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint, - span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, + match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, + snippet_with_macro_callsite, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then, + span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; use if_chain::if_chain; use matches::matches; @@ -1035,14 +1036,15 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa }; if implements_trait(cx, arg_ty, default_trait_id, &[]) { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a call to `{}`", name, path), "try this", - format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")), - Applicability::Unspecified, + format!("{}.unwrap_or_default()", snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)), + applicability, ); return true; } @@ -1112,7 +1114,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa &format!("use of `{}` followed by a function call", name), "try this", format!("{}_{}({})", name, suffix, sugg), - Applicability::Unspecified, + Applicability::HasPlaceholders, ); } @@ -1155,11 +1157,15 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: None } - fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String { + fn generate_format_arg_snippet( + cx: &LateContext<'_, '_>, + a: &hir::Expr, + applicability: &mut Applicability, + ) -> String { if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { - return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned(); + return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability).into_owned(); } } }; @@ -1210,11 +1216,12 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: let span_replace_word = method_span.with_hi(span.hi()); if let Some(format_args) = extract_format_args(arg) { + let mut applicability = Applicability::MachineApplicable; let args_len = format_args.len(); let args: Vec = format_args .into_iter() .take(args_len - 1) - .map(|a| generate_format_arg_snippet(cx, a)) + .map(|a| generate_format_arg_snippet(cx, a, &mut applicability)) .collect(); let sugg = args.join(", "); @@ -1226,13 +1233,14 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: &format!("use of `{}` followed by a function call", name), "try this", format!("unwrap_or_else({} panic!({}))", closure, sugg), - Applicability::Unspecified, + applicability, ); return; } - let sugg: Cow<'_, _> = snippet(cx, arg.span, ".."); + let mut applicability = Applicability::MachineApplicable; + let sugg: Cow<'_, _> = snippet_with_applicability(cx, arg.span, "..", &mut applicability); span_lint_and_sugg( cx, @@ -1241,7 +1249,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: &format!("use of `{}` followed by a function call", name), "try this", format!("unwrap_or_else({} {{ let msg = {}; panic!(msg) }}))", closure, sugg), - Applicability::Unspecified, + applicability, ); } @@ -1358,7 +1366,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir:: "using '.clone()' on a ref-counted pointer", "try this", format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), - Applicability::Unspecified, + Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak ); } } @@ -1377,6 +1385,7 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E return; }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, STRING_EXTEND_CHARS, @@ -1385,11 +1394,11 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E "try this", format!( "{}.push_str({}{})", - snippet(cx, args[0].span, "_"), + snippet_with_applicability(cx, args[0].span, "_", &mut applicability), ref_str, - snippet(cx, target.span, "_") + snippet_with_applicability(cx, target.span, "_", &mut applicability) ), - Applicability::Unspecified, + applicability, ); } } @@ -1466,12 +1475,13 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: let next_point = cx.sess().source_map().next_point(fold_args[0].span); let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1)); + let mut applicability = Applicability::MachineApplicable; let sugg = if replacement_has_args { format!( ".{replacement}(|{s}| {r})", replacement = replacement_method_name, s = second_arg_ident, - r = snippet(cx, right_expr.span, "EXPR"), + r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), ) } else { format!( @@ -1488,7 +1498,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: "this `.fold` can be written more succinctly using another method", "try", sugg, - Applicability::Unspecified, + applicability, ); } } @@ -1552,9 +1562,10 @@ fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::E fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) { // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap, // because they do not implement `IndexMut` + let mut applicability = Applicability::MachineApplicable; let expr_ty = cx.tables.expr_ty(&get_args[0]); let get_args_str = if get_args.len() > 1 { - snippet(cx, get_args[1].span, "_") + snippet_with_applicability(cx, get_args[1].span, "_", &mut applicability) } else { return; // not linting on a .get().unwrap() chain or variant }; @@ -1593,10 +1604,10 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: format!( "{}{}[{}]", borrow_str, - snippet(cx, get_args[0].span, "_"), + snippet_with_applicability(cx, get_args[0].span, "_", &mut applicability), get_args_str ), - Applicability::Unspecified, + applicability, ); } @@ -2012,6 +2023,7 @@ fn lint_chars_cmp( if let Some(segment) = single_segment_path(qpath); if segment.ident.name == "Some"; then { + let mut applicability = Applicability::MachineApplicable; let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0])); if self_ty.sty != ty::Str { @@ -2026,10 +2038,10 @@ fn lint_chars_cmp( "like this", format!("{}{}.{}({})", if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), + snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability), suggest, - snippet(cx, arg_char[0].span, "_")), - Applicability::Unspecified, + snippet_with_applicability(cx, arg_char[0].span, "_", &mut applicability)), + applicability, ); return true; @@ -2066,6 +2078,7 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( if let hir::ExprKind::Lit(ref lit) = info.other.node; if let ast::LitKind::Char(c) = lit.node; then { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, lint, @@ -2074,10 +2087,10 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( "like this", format!("{}{}.{}('{}')", if info.eq { "" } else { "!" }, - snippet(cx, args[0][0].span, "_"), + snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability), suggest, c), - Applicability::Unspecified, + applicability, ); return true; @@ -2108,7 +2121,8 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h if let ast::LitKind::Str(r, _) = lit.node; if r.as_str().len() == 1; then { - let snip = snippet(cx, arg.span, ".."); + let mut applicability = Applicability::MachineApplicable; + let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability); let hint = format!("'{}'", &snip[1..snip.len() - 1]); span_lint_and_sugg( cx, @@ -2117,7 +2131,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h "single-character string constant used as pattern", "try using a char instead", hint, - Applicability::Unspecified, + applicability, ); } } @@ -2135,14 +2149,15 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, USELESS_ASREF, expr.span, &format!("this call to `{}` does nothing", call_name), "try this", - snippet(cx, recvr.span, "_").into_owned(), - Applicability::Unspecified, + snippet_with_applicability(cx, recvr.span, "_", &mut applicability).to_string(), + applicability, ); } } @@ -2207,8 +2222,8 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::T kind, ), "call directly", - method_name.to_owned(), - Applicability::Unspecified, + method_name.to_string(), + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 8ed319c6736..37ccf28d572 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -19,7 +19,7 @@ use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Spanned; use crate::utils::sugg::Sugg; -use crate::utils::{in_macro, snippet, span_lint, span_lint_and_sugg}; +use crate::utils::{in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg}; /// **What it does:** Checks for expressions of the form `if c { true } else { /// false }` @@ -74,7 +74,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { use self::Expression::*; if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node { let reduce = |ret, not| { - let snip = Sugg::hir(cx, pred, ""); + let mut applicability = Applicability::MachineApplicable; + let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); let snip = if not { !snip } else { snip }; let hint = if ret { @@ -90,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { "this if-then-else expression returns a bool literal", "you can reduce it to", hint, - Applicability::Unspecified, + applicability, ); }; if let ExprKind::Block(ref then_block, _) = then_block.node { @@ -142,33 +143,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { + let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { - let hint = snippet(cx, right_side.span, "..").into_owned(); + let hint = snippet_with_applicability(cx, right_side.span, "..", &mut applicability); span_lint_and_sugg( cx, BOOL_COMPARISON, e.span, "equality checks against true are unnecessary", "try simplifying it as shown", - hint, - Applicability::Unspecified, + hint.to_string(), + applicability, ); }, (Other, Bool(true)) => { - let hint = snippet(cx, left_side.span, "..").into_owned(); + let hint = snippet_with_applicability(cx, left_side.span, "..", &mut applicability); span_lint_and_sugg( cx, BOOL_COMPARISON, e.span, "equality checks against true are unnecessary", "try simplifying it as shown", - hint, - Applicability::Unspecified, + hint.to_string(), + applicability, ); }, (Bool(false), Other) => { - let hint = Sugg::hir(cx, right_side, ".."); + let hint = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability); span_lint_and_sugg( cx, BOOL_COMPARISON, @@ -176,11 +178,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against false can be replaced by a negation", "try simplifying it as shown", (!hint).to_string(), - Applicability::Unspecified, + applicability, ); }, (Other, Bool(false)) => { - let hint = Sugg::hir(cx, left_side, ".."); + let hint = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability); span_lint_and_sugg( cx, BOOL_COMPARISON, @@ -188,7 +190,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { "equality checks against false can be replaced by a negation", "try simplifying it as shown", (!hint).to_string(), - Applicability::Unspecified, + applicability, ); }, _ => (), diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 877cd5ab1e4..72ed649c5d9 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "statement can be reduced", "replace it with", snippet, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 4376db5e9b3..d8f2645699d 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -13,7 +13,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax::source_map::Spanned; -use crate::utils::{in_macro, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: @@ -54,7 +54,7 @@ impl EarlyLintPass for Precedence { } if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node { - let span_sugg = |expr: &Expr, sugg| { + let span_sugg = |expr: &Expr, sugg, appl| { span_lint_and_sugg( cx, PRECEDENCE, @@ -62,40 +62,41 @@ impl EarlyLintPass for Precedence { "operator precedence can trip the unwary", "consider parenthesizing your expression", sugg, - Applicability::Unspecified, + appl, ); }; if !is_bit_op(op) { return; } + let mut applicability = Applicability::MachineApplicable; match (is_arith_expr(left), is_arith_expr(right)) { (true, true) => { let sugg = format!( "({}) {} ({})", - snippet(cx, left.span, ".."), + snippet_with_applicability(cx, left.span, "..", &mut applicability), op.to_string(), - snippet(cx, right.span, "..") + snippet_with_applicability(cx, right.span, "..", &mut applicability) ); - span_sugg(expr, sugg); + span_sugg(expr, sugg, applicability); }, (true, false) => { let sugg = format!( "({}) {} {}", - snippet(cx, left.span, ".."), + snippet_with_applicability(cx, left.span, "..", &mut applicability), op.to_string(), - snippet(cx, right.span, "..") + snippet_with_applicability(cx, right.span, "..", &mut applicability) ); - span_sugg(expr, sugg); + span_sugg(expr, sugg, applicability); }, (false, true) => { let sugg = format!( "{} {} ({})", - snippet(cx, left.span, ".."), + snippet_with_applicability(cx, left.span, "..", &mut applicability), op.to_string(), - snippet(cx, right.span, "..") + snippet_with_applicability(cx, right.span, "..", &mut applicability) ); - span_sugg(expr, sugg); + span_sugg(expr, sugg, applicability); }, (false, false) => (), } @@ -107,14 +108,15 @@ impl EarlyLintPass for Precedence { if let ExprKind::Lit(ref lit) = slf.node { match lit.node { LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, PRECEDENCE, expr.span, "unary minus has lower precedence than method call", "consider adding parentheses to clarify your intent", - format!("-({})", snippet(cx, rhs.span, "..")), - Applicability::Unspecified, + format!("-({})", snippet_with_applicability(cx, rhs.span, "..", &mut applicability)), + applicability, ); }, _ => (), diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index e653ae2ff75..0d37d4d4b08 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -77,7 +77,7 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { &msg, "try", sugg, - Applicability::Unspecified, + Applicability::MachineApplicable, ); } else { utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 2acea17be26..b25ea1d5d38 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -66,7 +66,7 @@ impl EarlyLintPass for RedundantFieldNames { "redundant field names in struct initialization", "replace it with", field.ident.to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index aac3d09bfd3..7651c6f0a9f 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -12,7 +12,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::{Expr, ExprKind, UnOp}; -use crate::utils::{snippet, span_lint_and_sugg}; +use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. @@ -55,14 +55,15 @@ impl EarlyLintPass for Pass { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node; if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node; then { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, DEREF_ADDROF, e.span, "immediately dereferencing a reference", "try this", - format!("{}", snippet(cx, addrof_target.span, "_")), - Applicability::Unspecified, + format!("{}", snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability)), + applicability, ); } } @@ -102,6 +103,7 @@ impl EarlyLintPass for DerefPass { if let ExprKind::Paren(ref parened) = object.node; if let ExprKind::AddrOf(_, ref inner) = parened.node; then { + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, REF_IN_DEREF, @@ -110,10 +112,10 @@ impl EarlyLintPass for DerefPass { "try this", format!( "{}.{}", - snippet(cx, inner.span, "_"), - snippet(cx, field_name.span, "_") + snippet_with_applicability(cx, inner.span, "_", &mut applicability), + snippet_with_applicability(cx, field_name.span, "_", &mut applicability) ), - Applicability::Unspecified, + applicability, ); } } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 1c204912f17..e3016b7259b 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { &format!("using `{}`", const_path.last().expect("empty path")), "try this", repl_snip.to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, ); return; } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 74d5e304b87..05d64fbcd04 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -165,7 +165,7 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use crate::syntax::ast::{LitKind, StrStyle}; - use crate::utils::{in_macro, snippet}; + use crate::utils::{in_macro, snippet, snippet_with_applicability}; if let ExprKind::MethodCall(ref path, _, ref args) = e.node { if path.ident.name == "as_bytes" { @@ -178,6 +178,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { } else { format!("\"{}\"", lit_content.as_str()) }; + let mut applicability = Applicability::MachineApplicable; if callsite.starts_with("include_str!") { span_lint_and_sugg( cx, @@ -185,8 +186,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { e.span, "calling `as_bytes()` on `include_str!(..)`", "consider using `include_bytes!(..)` instead", - snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1), - Applicability::Unspecified, + snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen( + "include_str", + "include_bytes", + 1, + ), + applicability, ); } else if callsite == expanded && lit_content.as_str().chars().all(|c| c.is_ascii()) @@ -198,8 +203,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { e.span, "calling `as_bytes()` on a string literal", "consider using a byte string literal instead", - format!("b{}", snippet(cx, args[0].span, r#""foo""#)), - Applicability::Unspecified, + format!( + "b{}", + snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability) + ), + applicability, ); } } diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 467713694e1..836f84e8966 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -15,14 +15,14 @@ use crate::rustc::hir::intravisit::FnKind; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::session::config::Config as SessionConfig; -use crate::rustc::ty::TyKind; +use crate::rustc::ty::{FnSig, TyKind}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::rustc_target::abi::LayoutOf; use crate::rustc_target::spec::abi::Abi; use crate::syntax::ast::NodeId; use crate::syntax_pos::Span; -use crate::utils::{in_macro, is_copy, is_self, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro, is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; use matches::matches; @@ -141,7 +141,9 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { input.span, "this argument is passed by reference, but would be more efficient if passed by value", "consider passing by value instead", - value_type); + value_type, + Applicability::Unspecified, + ); } } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4a9cb04a0ac..61f294e1f3c 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -29,7 +29,7 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, - span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, + snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, }; use if_chain::if_chain; use std::borrow::Cow; @@ -334,20 +334,21 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: let ltopt = if lt.is_elided() { String::new() } else { - format!("{} ", lt.name.ident().name.as_str()) + format!("{} ", lt.name.ident().as_str()) }; let mutopt = if mut_ty.mutbl == Mutability::MutMutable { "mut " } else { "" }; + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, BORROWED_BOX, ast_ty.span, "you seem to be trying to use `&Box`. Consider using just `&T`", "try", - format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, "..")), + format!("&{}{}{}", ltopt, mutopt, &snippet_with_applicability(cx, inner.span, "..", &mut applicability)), Applicability::Unspecified, ); return; // don't recurse into the type @@ -542,7 +543,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { "passing a unit value to a function", "if you intended to pass a unit value, use a unit literal instead", "()".to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } @@ -862,6 +863,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro if in_constant(cx, expr.id) { return } // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. + let mut applicability = Applicability::MachineApplicable; let opt = snippet_opt(cx, op.span); let sugg = if let Some(ref snip) = opt { if should_strip_parens(op, snip) { @@ -870,6 +872,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro snip.as_str() } } else { + applicability = Applicability::HasPlaceholders; ".." }; @@ -880,7 +883,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to), "try", format!("{}::from({})", cast_to, sugg), - Applicability::Unspecified, + applicability, ); } @@ -1100,7 +1103,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex } match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { - let from_snippet = snippet(cx, cast_expr.span, "x"); + let mut applicability = Applicability::MachineApplicable; + let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); if to_nbits < cx.tcx.data_layout.pointer_size.bits() { @@ -1111,7 +1115,7 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to), "try", format!("{} as usize", from_snippet), - Applicability::Unspecified, + applicability, ); } else if cast_to.sty != ty::Uint(UintTy::Usize) { @@ -1122,7 +1126,7 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to), "try", format!("{} as usize", from_snippet), - Applicability::Unspecified, + applicability, ); } }, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index ea9deb7a804..564bdb0bb03 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -71,7 +71,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { "unnecessary structure name repetition", "use the applicable keyword", "Self".to_owned(), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 740da22ba1c..fd232e2a366 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -282,7 +282,7 @@ impl EarlyLintPass for DefaultHashTypes { &msg, "use", replace.to_string(), - Applicability::Unspecified, + Applicability::MaybeIncorrect, // FxHashMap, ... needs another import ); } } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 0dd9af6db16..d7e7de06355 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -15,7 +15,7 @@ use crate::rustc::ty::{self, Ty}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; -use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg}; +use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would @@ -77,10 +77,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { + let mut applicability = Applicability::MachineApplicable; let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { if constant(cx, cx.tables, len).is_some() { - format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")) + format!( + "&[{}; {}]", + snippet_with_applicability(cx, elem.span, "elem", &mut applicability), + snippet_with_applicability(cx, len.span, "len", &mut applicability) + ) } else { return; } @@ -88,7 +93,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() { let span = args[0].span.to(last.span); - format!("&[{}]", snippet(cx, span, "..")) + format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) } else { "&[]".into() }, @@ -101,7 +106,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA "useless use of `vec!`", "you can use a slice directly", snippet, - Applicability::Unspecified, + applicability, ); } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 76e07a2d3b3..c746815062b 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -14,7 +14,7 @@ use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax::parse::{parser, token}; use crate::syntax::tokenstream::{ThinTokenStream, TokenStream}; -use crate::utils::{snippet, span_lint, span_lint_and_sugg}; +use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg}; use std::borrow::Cow; /// **What it does:** This lint warns when you use `println!("")` to @@ -200,7 +200,7 @@ impl EarlyLintPass for Pass { "using `println!(\"\")`", "replace it with", "println!()".to_string(), - Applicability::Unspecified, + Applicability::MachineApplicable, ); } } @@ -239,9 +239,14 @@ impl EarlyLintPass for Pass { let check_tts = check_tts(cx, &mac.node.tts, true); if let Some(fmtstr) = check_tts.0 { if fmtstr == "" { - let suggestion = check_tts - .1 - .map_or(Cow::Borrowed("v"), |expr| snippet(cx, expr.span, "v")); + let mut applicability = Applicability::MachineApplicable; + let suggestion = check_tts.1.map_or_else( + move || { + applicability = Applicability::HasPlaceholders; + Cow::Borrowed("v") + }, + move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability), + ); span_lint_and_sugg( cx, @@ -250,7 +255,7 @@ impl EarlyLintPass for Pass { format!("using `writeln!({}, \"\")`", suggestion).as_str(), "replace it with", format!("writeln!({})", suggestion), - Applicability::Unspecified, + applicability, ); } } -- cgit 1.4.1-3-g733a5 From adc638ef334a9f34a16ebaee1c3430c3be04a790 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 16:59:39 +0100 Subject: Change Applicability of MISTYPED_LITERAL_SUFFIX --- clippy_lints/src/literal_representation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 8d7f549da39..1efacc4ccec 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -301,7 +301,7 @@ impl WarningType { "mistyped literal suffix", "did you mean to write", grouping_hint.to_string(), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ), WarningType::UnreadableLiteral => span_lint_and_sugg( cx, -- cgit 1.4.1-3-g733a5 From 6eb8e6d7c59ba1dfb4f1e8d669ac8d7a5db06b68 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 16:59:52 +0100 Subject: Fix dogfood error --- clippy_lints/src/write.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c746815062b..0119560ccd8 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -264,8 +264,8 @@ impl EarlyLintPass for Pass { } /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two -/// options. The first part of the tuple is format_str of the macros. The secund part of the tuple -/// is in the `write[ln]!` case the expression the format_str should be written to. +/// options. The first part of the tuple is `format_str` of the macros. The secund part of the tuple +/// is in the `write[ln]!` case the expression the `format_str` should be written to. /// /// Example: /// -- cgit 1.4.1-3-g733a5 From 87e72a58616ab2c17877cdcf56035642cbcc536b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 17:31:17 +0100 Subject: Fix NAIVE_BYTECOUNT applicability --- clippy_lints/src/bytecount.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 0547837795d..4f02b627e51 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { format!("bytecount::count({}, {})", snippet_with_applicability(cx, haystack.span, "..", &mut applicability), snippet_with_applicability(cx, needle.span, "..", &mut applicability)), - Applicability::Unspecified, + applicability, ); } }; -- cgit 1.4.1-3-g733a5 From ccff495b62bc86e2e18ec93795c453b9e1d4cd26 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 20:46:11 +0100 Subject: Error on line overflow --- rustfmt.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rustfmt.toml b/rustfmt.toml index 6776a88294c..797eccdad99 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,3 +2,5 @@ max_width = 120 comment_width = 100 match_block_trailing_comma = true wrap_comments = true + +error_on_line_overflow = true -- cgit 1.4.1-3-g733a5 From 4e0938d349e95cf6bc8edd1d48197db65c8ecd87 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:11:05 +0100 Subject: Let travis run cargo fmt --all -- --check --- .travis.yml | 5 +++-- ci/base-tests.sh | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8730535d629..45fc5278517 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ before_install: install: - | if [ -z ${INTEGRATION} ]; then + rustup component add rustfmt-preview || cargo install --git https://github.com/rust-lang/rustfmt/ --force if [ "$TRAVIS_OS_NAME" == "linux" ]; then . $HOME/.nvm/nvm.sh nvm install stable @@ -48,7 +49,7 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: BASE_TEST=true + env: BASE_TESTS=true - env: INTEGRATION=rust-lang/cargo - env: INTEGRATION=rust-random/rand - env: INTEGRATION=rust-lang-nursery/stdsimd @@ -64,7 +65,7 @@ matrix: - env: INTEGRATION=hyperium/hyper allow_failures: - os: windows - env: BASE_TEST=true + env: BASE_TESTS=true # prevent these jobs with default env vars exclude: - os: linux diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 88cc20842e8..e46f8c4c39a 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -26,6 +26,7 @@ cd clippy_dev && cargo test && cd .. # Perform various checks for lint registration ./util/dev update_lints --check +cargo +nightly fmt --all -- --check CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... -- cgit 1.4.1-3-g733a5 From 2953ae0702c103dc9e0ca6c7509ebc8a5e89e9f0 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:11:50 +0100 Subject: Run rustfmt on the tests --- tests/compile-test.rs | 1 - tests/dogfood.rs | 1 - tests/matches.rs | 3 +-- tests/needless_continue_helpers.rs | 3 --- tests/versioncheck.rs | 1 - 5 files changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 64360af641b..5cb37b6b6fd 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(test)] extern crate compiletest_rs as compiletest; diff --git a/tests/dogfood.rs b/tests/dogfood.rs index dcbfa90e611..e8f7a080c95 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[test] fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { diff --git a/tests/matches.rs b/tests/matches.rs index 99b05e50c9f..fb5dbf5d84d 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(rustc_private)] extern crate clippy_lints; @@ -16,8 +15,8 @@ use std::collections::Bound; #[test] fn test_overlapping() { - use clippy_lints::matches::overlapping; use crate::syntax::source_map::DUMMY_SP; + use clippy_lints::matches::overlapping; let sp = |s, e| clippy_lints::matches::SpannedRange { span: DUMMY_SP, diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 662ae110845..8237ac437ba 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 5b189a797b7..cdf97f75ec6 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - extern crate cargo_metadata; extern crate semver; use semver::VersionReq; -- cgit 1.4.1-3-g733a5 From d71c871568c4febd047ab46be6370a36aefcb882 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:12:13 +0100 Subject: Run rustfmt on src --- src/driver.rs | 238 +++++++++++++++++++++++++++++----------------------------- src/lib.rs | 2 - src/main.rs | 5 +- 3 files changed, 121 insertions(+), 124 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index f99c37b8519..fd9c8693c95 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -7,11 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] - #![feature(try_from)] #![allow(clippy::missing_docs_in_private_items)] @@ -33,126 +31,128 @@ fn show_version() { pub fn main() { rustc_driver::init_rustc_env_logger(); - exit(rustc_driver::run(move || { - use std::env; - - if std::env::args().any(|a| a == "--version" || a == "-V") { - show_version(); - exit(0); - } - - let sys_root = option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); - if orig_args.len() <= 1 { - std::process::exit(1); - } - if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { - // we still want to be able to invoke it normally though - orig_args.remove(1); - } - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() - } else { - orig_args - .clone() - .into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; - - // this check ensures that dependencies are built but not linted and the final - // crate is - // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); - - if clippy_enabled { - args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); - if let Ok(extra_args) = env::var("CLIPPY_ARGS") { - args.extend( - extra_args - .split("__CLIPPY_HACKERY__") - .filter_map(|s| if s.is_empty() { + exit( + rustc_driver::run(move || { + use std::env; + + if std::env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + // this check ensures that dependencies are built but not linted and the final + // crate is + // linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") + || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); + + if clippy_enabled { + args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); + if let Ok(extra_args) = env::var("CLIPPY_ARGS") { + args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| { + if s.is_empty() { None } else { Some(s.to_string()) - }) - ); - } - } - - let mut controller = CompileController::basic(); - if clippy_enabled { - controller.after_parse.callback = Box::new(move |state| { - let mut registry = rustc_plugin::registry::Registry::new( - state.session, - state - .krate - .as_ref() - .expect( - "at this compilation stage \ - the crate must be parsed", - ) - .span, - ); - registry.args_hidden = Some(Vec::new()); - - let conf = clippy_lints::read_conf(®istry); - clippy_lints::register_plugins(&mut registry, &conf); - - let rustc_plugin::registry::Registry { - early_lint_passes, - late_lint_passes, - lint_groups, - llvm_passes, - attributes, - .. - } = registry; - let sess = &state.session; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } - - for (name, (to, deprecated_name)) in lint_groups { - ls.register_group(Some(sess), true, name, deprecated_name, to); + } + })); } - clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); - - sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); - sess.plugin_attributes.borrow_mut().extend(attributes); - }); - } - controller.compilation_done.stop = Compilation::Stop; + } - let args = args; - rustc_driver::run_compiler(&args, Box::new(controller), None, None) - }).try_into().expect("exit code too large")) + let mut controller = CompileController::basic(); + if clippy_enabled { + controller.after_parse.callback = Box::new(move |state| { + let mut registry = rustc_plugin::registry::Registry::new( + state.session, + state + .krate + .as_ref() + .expect( + "at this compilation stage \ + the crate must be parsed", + ) + .span, + ); + registry.args_hidden = Some(Vec::new()); + + let conf = clippy_lints::read_conf(®istry); + clippy_lints::register_plugins(&mut registry, &conf); + + let rustc_plugin::registry::Registry { + early_lint_passes, + late_lint_passes, + lint_groups, + llvm_passes, + attributes, + .. + } = registry; + let sess = &state.session; + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } + + for (name, (to, deprecated_name)) in lint_groups { + ls.register_group(Some(sess), true, name, deprecated_name, to); + } + clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); + + sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); + sess.plugin_attributes.borrow_mut().extend(attributes); + }); + } + controller.compilation_done.stop = Compilation::Stop; + + let args = args; + rustc_driver::run_compiler(&args, Box::new(controller), None, None) + }) + .try_into() + .expect("exit code too large"), + ) } diff --git a/src/lib.rs b/src/lib.rs index 97f1f81091d..4069472612d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] - #![allow(clippy::missing_docs_in_private_items)] #![warn(rust_2018_idioms)] diff --git a/src/main.rs b/src/main.rs index be28fe12899..6c5cfe69166 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,11 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] - #![allow(clippy::missing_docs_in_private_items)] use rustc_tools_util::*; @@ -106,7 +104,8 @@ where .into_os_string() }, ) - }).map(|p| ("CARGO_TARGET_DIR", p)); + }) + .map(|p| ("CARGO_TARGET_DIR", p)); let exit_status = std::process::Command::new("cargo") .args(&args) -- cgit 1.4.1-3-g733a5 From 3befd86967993fdb8dfb23bd8524de04b65e658d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:12:38 +0100 Subject: Run rustfmt on rustc_tools_util --- rustc_tools_util/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 0951a0dee28..d1640c758bb 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::env; #[macro_export] -- cgit 1.4.1-3-g733a5 From f9c0e2a4cba73539a3b005d293a230f6a36555a0 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:13:08 +0100 Subject: Run rustfmt on clippy_dev --- clippy_dev/src/lib.rs | 208 ++++++++++++++++++++++++++++++------------------- clippy_dev/src/main.rs | 88 ++++++++++++--------- 2 files changed, 181 insertions(+), 115 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 2dd04371c9b..626afceecff 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -7,30 +7,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(clippy::default_hash_types)] use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; -use walkdir::WalkDir; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; use std::io::prelude::*; +use walkdir::WalkDir; lazy_static! { - static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"(?x) + static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new( + r#"(?x) declare_clippy_lint!\s*[\{(]\s* pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* (?P[a-z_]+)\s*,\s* "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] - "#).unwrap(); - static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"(?x) + "# + ) + .unwrap(); + static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new( + r#"(?x) declare_deprecated_lint!\s*[{(]\s* pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] - "#).unwrap(); + "# + ) + .unwrap(); static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap(); pub static ref DOCS_LINK: String = "https://rust-lang.github.io/rust-clippy/master/index.html".to_string(); } @@ -57,13 +62,16 @@ impl Lint { } /// Returns all non-deprecated lints and non-internal lints - pub fn usable_lints(lints: impl Iterator) -> impl Iterator { + pub fn usable_lints(lints: impl Iterator) -> impl Iterator { lints.filter(|l| l.deprecation.is_none() && !l.is_internal()) } /// Returns the lints in a HashMap, grouped by the different lint groups pub fn by_lint_group(lints: &[Self]) -> HashMap> { - lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map() + lints + .iter() + .map(|lint| (lint.group.to_string(), lint.clone())) + .into_group_map() } pub fn is_internal(&self) -> bool { @@ -73,7 +81,8 @@ impl Lint { /// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`. pub fn gen_lint_group_list(lints: Vec) -> Vec { - lints.into_iter() + lints + .into_iter() .filter_map(|l| { if l.is_internal() || l.deprecation.is_some() { None @@ -86,14 +95,17 @@ pub fn gen_lint_group_list(lints: Vec) -> Vec { /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. pub fn gen_modules_list(lints: Vec) -> Vec { - lints.into_iter() + lints + .into_iter() .filter_map(|l| { - if l.is_internal() || l.deprecation.is_some() { None } else { Some(l.module) } + if l.is_internal() || l.deprecation.is_some() { + None + } else { + Some(l.module) + } }) .unique() - .map(|module| { - format!("pub mod {};", module) - }) + .map(|module| format!("pub mod {};", module)) .sorted() } @@ -109,35 +121,31 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { } else { Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name)) } - }).collect() + }) + .collect() } /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. pub fn gen_deprecated(lints: &[Lint]) -> Vec { - itertools::flatten( - lints - .iter() - .filter_map(|l| { - l.clone().deprecation.and_then(|depr_text| { - Some( - vec![ - " store.register_removed(".to_string(), - format!(" \"{}\",", l.name), - format!(" \"{}\",", depr_text), - " );".to_string() - ] - ) - }) - }) - ).collect() + itertools::flatten(lints.iter().filter_map(|l| { + l.clone().deprecation.and_then(|depr_text| { + Some(vec![ + " store.register_removed(".to_string(), + format!(" \"{}\",", l.name), + format!(" \"{}\",", depr_text), + " );".to_string(), + ]) + }) + })) + .collect() } /// Gathers all files in `src/clippy_lints` and gathers all lints inside -pub fn gather_all() -> impl Iterator { +pub fn gather_all() -> impl Iterator { lint_files().flat_map(|f| gather_from_file(&f)) } -fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { +fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { let mut file = fs::File::open(dir_entry.path()).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); @@ -145,24 +153,31 @@ fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { // If the lints are stored in mod.rs, we get the module name from // the containing directory: if filename == "mod" { - filename = dir_entry.path().parent().unwrap().file_stem().unwrap().to_str().unwrap() + filename = dir_entry + .path() + .parent() + .unwrap() + .file_stem() + .unwrap() + .to_str() + .unwrap() } parse_contents(&content, filename) } -fn parse_contents(content: &str, filename: &str) -> impl Iterator { +fn parse_contents(content: &str, filename: &str) -> impl Iterator { let lints = DEC_CLIPPY_LINT_RE .captures_iter(content) .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)); let deprecated = DEC_DEPRECATED_LINT_RE .captures_iter(content) - .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)); + .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)); // Removing the `.collect::>().into_iter()` causes some lifetime issues due to the map lints.chain(deprecated).collect::>().into_iter() } /// Collects all .rs files in the `clippy_lints/src` directory -fn lint_files() -> impl Iterator { +fn lint_files() -> impl Iterator { // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. WalkDir::new("../clippy_lints/src") @@ -184,15 +199,27 @@ pub struct FileChange { /// /// See `replace_region_in_text` for documentation of the other options. #[allow(clippy::expect_fun_call)] -pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_start: bool, write_back: bool, replacements: F) -> FileChange where F: Fn() -> Vec { +pub fn replace_region_in_file( + path: &str, + start: &str, + end: &str, + replace_start: bool, + write_back: bool, + replacements: F, +) -> FileChange +where + F: Fn() -> Vec, +{ let mut f = fs::File::open(path).expect(&format!("File not found: {}", path)); let mut contents = String::new(); - f.read_to_string(&mut contents).expect("Something went wrong reading the file"); + f.read_to_string(&mut contents) + .expect("Something went wrong reading the file"); let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); if write_back { let mut f = fs::File::create(path).expect(&format!("File not found: {}", path)); - f.write_all(file_change.new_lines.as_bytes()).expect("Unable to write file"); + f.write_all(file_change.new_lines.as_bytes()) + .expect("Unable to write file"); // Ensure we write the changes with a trailing newline so that // the file has the proper line endings. f.write_all(b"\n").expect("Unable to write file"); @@ -205,10 +232,10 @@ pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_sta /// * `text` is the input text on which you want to perform the replacement /// * `start` is a `&str` that describes the delimiter line before the region you want to replace. /// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * `end` is a `&str` that describes the delimiter line until where the replacement should -/// happen. As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * If `replace_start` is true, the `start` delimiter line is replaced as well. -/// The `end` delimiter line is never replaced. +/// * `end` is a `&str` that describes the delimiter line until where the replacement should happen. +/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. +/// * If `replace_start` is true, the `start` delimiter line is replaced as well. The `end` +/// delimiter line is never replaced. /// * `replacements` is a closure that has to return a `Vec` which contains the new text. /// /// If you want to perform the replacement on files instead of already parsed text, @@ -218,18 +245,16 @@ pub fn replace_region_in_file(path: &str, start: &str, end: &str, replace_sta /// /// ``` /// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; -/// let result = clippy_dev::replace_region_in_text( -/// the_text, -/// r#"replace_start"#, -/// r#"replace_end"#, -/// false, -/// || { -/// vec!["a different".to_string(), "text".to_string()] -/// } -/// ).new_lines; +/// let result = clippy_dev::replace_region_in_text(the_text, r#"replace_start"#, r#"replace_end"#, false, || { +/// vec!["a different".to_string(), "text".to_string()] +/// }) +/// .new_lines; /// assert_eq!("replace_start\na different\ntext\nreplace_end", result); /// ``` -pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange where F: Fn() -> Vec { +pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange +where + F: Fn() -> Vec, +{ let lines = text.lines(); let mut in_old_region = false; let mut found = false; @@ -264,7 +289,7 @@ pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_sta FileChange { changed: lines.ne(new_lines.clone()), - new_lines: new_lines.join("\n") + new_lines: new_lines.join("\n"), } } @@ -291,7 +316,9 @@ declare_deprecated_lint! { "`assert!()` will be more flexible with RFC 2011" } "#, - "module_name").collect(); + "module_name", + ) + .collect(); let expected = vec![ Lint::new("ptr_arg", "style", "really long text", None, "module_name"), @@ -301,7 +328,7 @@ declare_deprecated_lint! { "Deprecated", "`assert!()` will be more flexible with RFC 2011", Some("`assert!()` will be more flexible with RFC 2011"), - "module_name" + "module_name", ), ]; assert_eq!(expected, result); @@ -312,7 +339,7 @@ fn test_replace_region() { let text = "\nabc\n123\n789\ndef\nghi"; let expected = FileChange { changed: true, - new_lines: "\nabc\nhello world\ndef\nghi".to_string() + new_lines: "\nabc\nhello world\ndef\nghi".to_string(), }; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { vec!["hello world".to_string()] @@ -325,7 +352,7 @@ fn test_replace_region_with_start() { let text = "\nabc\n123\n789\ndef\nghi"; let expected = FileChange { changed: true, - new_lines: "\nhello world\ndef\nghi".to_string() + new_lines: "\nhello world\ndef\nghi".to_string(), }; let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { vec!["hello world".to_string()] @@ -338,11 +365,9 @@ fn test_replace_region_no_changes() { let text = "123\n456\n789"; let expected = FileChange { changed: false, - new_lines: "123\n456\n789".to_string() + new_lines: "123\n456\n789".to_string(), }; - let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || { - vec![] - }); + let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || vec![]); assert_eq!(expected, result); } @@ -352,11 +377,15 @@ fn test_usable_lints() { Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"), Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name") - ]; - let expected = vec![ - Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name") + Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"), ]; + let expected = vec![Lint::new( + "should_assert_eq2", + "Not Deprecated", + "abc", + None, + "module_name", + )]; assert_eq!(expected, Lint::usable_lints(lints.into_iter()).collect::>()); } @@ -368,13 +397,17 @@ fn test_by_lint_group() { Lint::new("incorrect_match", "group1", "abc", None, "module_name"), ]; let mut expected: HashMap> = HashMap::new(); - expected.insert("group1".to_string(), vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("incorrect_match", "group1", "abc", None, "module_name"), - ]); - expected.insert("group2".to_string(), vec![ - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name") - ]); + expected.insert( + "group1".to_string(), + vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + ], + ); + expected.insert( + "group2".to_string(), + vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")], + ); assert_eq!(expected, Lint::by_lint_group(&lints)); } @@ -387,7 +420,7 @@ fn test_gen_changelog_lint_list() { ]; let expected = vec![ format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()), - format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()) + format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()), ]; assert_eq!(expected, gen_changelog_lint_list(lints)); } @@ -395,9 +428,21 @@ fn test_gen_changelog_lint_list() { #[test] fn test_gen_deprecated() { let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", Some("has been superseeded by should_assert_eq2"), "module_name"), - Lint::new("another_deprecated", "group2", "abc", Some("will be removed"), "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name") + Lint::new( + "should_assert_eq", + "group1", + "abc", + Some("has been superseeded by should_assert_eq2"), + "module_name", + ), + Lint::new( + "another_deprecated", + "group2", + "abc", + Some("will be removed"), + "module_name", + ), + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), ]; let expected: Vec = vec![ " store.register_removed(", @@ -407,8 +452,11 @@ fn test_gen_deprecated() { " store.register_removed(", " \"another_deprecated\",", " \"will be removed\",", - " );" - ].into_iter().map(String::from).collect(); + " );", + ] + .into_iter() + .map(String::from) + .collect(); assert_eq!(expected, gen_deprecated(&lints)); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 0e82f6e0939..4ed07960010 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - extern crate clap; extern crate clippy_dev; extern crate regex; @@ -18,31 +17,33 @@ use clippy_dev::*; #[derive(PartialEq)] enum UpdateMode { Check, - Change + Change, } fn main() { let matches = App::new("Clippy developer tooling") .subcommand( SubCommand::with_name("update_lints") - .about("Makes sure that:\n \ - * the lint count in README.md is correct\n \ - * the changelog contains markdown link references at the bottom\n \ - * all lint groups include the correct lints\n \ - * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ - * all lints are registered in the lint store") - .arg( - Arg::with_name("print-only") - .long("print-only") - .help("Print a table of lints to STDOUT. This does not include deprecated and internal lints. (Does not modify any files)") + .about( + "Makes sure that:\n \ + * the lint count in README.md is correct\n \ + * the changelog contains markdown link references at the bottom\n \ + * all lint groups include the correct lints\n \ + * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ + * all lints are registered in the lint store", ) + .arg(Arg::with_name("print-only").long("print-only").help( + "Print a table of lints to STDOUT. \ + This does not include deprecated and internal lints. \ + (Does not modify any files)", + )) .arg( Arg::with_name("check") .long("check") .help("Checks that util/dev update_lints has been run. Used on CI."), - ) - ) - .get_matches(); + ), + ) + .get_matches(); if let Some(matches) = matches.subcommand_matches("update_lints") { if matches.is_present("print-only") { @@ -62,13 +63,21 @@ fn print_lints() { let grouped_by_lint_group = Lint::by_lint_group(&usable_lints); for (lint_group, mut lints) in grouped_by_lint_group { - if lint_group == "Deprecated" { continue; } + if lint_group == "Deprecated" { + continue; + } println!("\n## {}", lint_group); lints.sort_by_key(|l| l.name.clone()); for lint in lints { - println!("* [{}]({}#{}) ({})", lint.name, clippy_dev::DOCS_LINK.clone(), lint.name, lint.desc); + println!( + "* [{}]({}#{}) ({})", + lint.name, + clippy_dev::DOCS_LINK.clone(), + lint.name, + lint.desc + ); } } @@ -99,8 +108,9 @@ fn update_lints(update_mode: &UpdateMode) { "", false, update_mode == &UpdateMode::Change, - || { gen_changelog_lint_list(lint_list.clone()) } - ).changed; + || gen_changelog_lint_list(lint_list.clone()), + ) + .changed; file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", @@ -108,8 +118,9 @@ fn update_lints(update_mode: &UpdateMode) { "end deprecated lints", false, update_mode == &UpdateMode::Change, - || { gen_deprecated(&lint_list) } - ).changed; + || gen_deprecated(&lint_list), + ) + .changed; file_change |= replace_region_in_file( "../clippy_lints/src/lib.rs", @@ -117,8 +128,9 @@ fn update_lints(update_mode: &UpdateMode) { "end lints modules", false, update_mode == &UpdateMode::Change, - || { gen_modules_list(lint_list.clone()) } - ).changed; + || gen_modules_list(lint_list.clone()), + ) + .changed; // Generate lists of lints in the clippy::all lint group file_change |= replace_region_in_file( @@ -129,16 +141,18 @@ fn update_lints(update_mode: &UpdateMode) { update_mode == &UpdateMode::Change, || { // clippy::all should only include the following lint groups: - let all_group_lints = usable_lints.clone().into_iter().filter(|l| { - l.group == "correctness" || - l.group == "style" || - l.group == "complexity" || - l.group == "perf" - }).collect(); + let all_group_lints = usable_lints + .clone() + .into_iter() + .filter(|l| { + l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf" + }) + .collect(); gen_lint_group_list(all_group_lints) - } - ).changed; + }, + ) + .changed; // Generate the list of lints for all other lint groups for (lint_group, lints) in Lint::by_lint_group(&usable_lints) { @@ -148,12 +162,16 @@ fn update_lints(update_mode: &UpdateMode) { r#"\]\);"#, false, update_mode == &UpdateMode::Change, - || { gen_lint_group_list(lints.clone()) } - ).changed; + || gen_lint_group_list(lints.clone()), + ) + .changed; } if update_mode == &UpdateMode::Check && file_change { - println!("Not all lints defined properly. Please run `util/dev update_lints` to make sure all lints are defined properly."); - std::process::exit(1); + println!( + "Not all lints defined properly. \ + Please run `util/dev update_lints` to make sure all lints are defined properly." + ); + std::process::exit(1); } } -- cgit 1.4.1-3-g733a5 From 5c5e8cc942c8ef97d19f820dc8c4fb4a9397774e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:13:26 +0100 Subject: Run rustfmt on build.rs --- build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build.rs b/build.rs index 336f0295bdf..22a6910f167 100644 --- a/build.rs +++ b/build.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap()); -- cgit 1.4.1-3-g733a5 From 1751d2496d4241b2a705ed871a8ad3d4402180b5 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:14:15 +0100 Subject: Run rustfmt on clippy_lints --- clippy_lints/src/approx_const.rs | 5 +- clippy_lints/src/arithmetic.rs | 11 +- clippy_lints/src/assign_ops.rs | 12 +- clippy_lints/src/attrs.rs | 58 ++- clippy_lints/src/bit_mask.rs | 175 +++++---- clippy_lints/src/blacklisted_name.rs | 7 +- clippy_lints/src/block_in_if_condition.rs | 17 +- clippy_lints/src/booleans.rs | 67 ++-- clippy_lints/src/bytecount.rs | 11 +- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/collapsible_if.rs | 22 +- clippy_lints/src/const_static_lifetime.rs | 20 +- clippy_lints/src/consts.rs | 171 ++++---- clippy_lints/src/copies.rs | 52 ++- clippy_lints/src/copy_iterator.rs | 3 +- clippy_lints/src/cyclomatic_complexity.rs | 41 +- clippy_lints/src/default_trait_access.rs | 78 ++-- clippy_lints/src/derive.rs | 27 +- clippy_lints/src/doc.rs | 22 +- clippy_lints/src/double_comparison.rs | 30 +- clippy_lints/src/double_parens.rs | 41 +- clippy_lints/src/drop_forget_ref.rs | 15 +- clippy_lints/src/duration_subsec.rs | 7 +- clippy_lints/src/else_if_without_else.rs | 3 +- clippy_lints/src/empty_enum.rs | 11 +- clippy_lints/src/entry.rs | 26 +- clippy_lints/src/enum_clike.rs | 17 +- clippy_lints/src/enum_glob_use.rs | 10 +- clippy_lints/src/enum_variants.rs | 35 +- clippy_lints/src/eq_op.rs | 42 +- clippy_lints/src/erasing_op.rs | 5 +- clippy_lints/src/escape.rs | 18 +- clippy_lints/src/eta_reduction.rs | 14 +- clippy_lints/src/eval_order_dependence.rs | 82 ++-- clippy_lints/src/excessive_precision.rs | 19 +- clippy_lints/src/explicit_write.rs | 13 +- clippy_lints/src/fallible_impl_from.rs | 11 +- clippy_lints/src/format.rs | 36 +- clippy_lints/src/formatting.rs | 20 +- clippy_lints/src/functions.rs | 38 +- clippy_lints/src/identity_conversion.rs | 44 ++- clippy_lints/src/identity_op.rs | 5 +- clippy_lints/src/if_not_else.rs | 3 +- clippy_lints/src/indexing_slicing.rs | 38 +- clippy_lints/src/infallible_destructuring_match.rs | 1 - clippy_lints/src/infinite_iter.rs | 26 +- clippy_lints/src/inherent_impl.rs | 18 +- clippy_lints/src/inline_fn_without_body.rs | 5 +- clippy_lints/src/int_plus_one.rs | 23 +- clippy_lints/src/invalid_ref.rs | 7 +- clippy_lints/src/items_after_statements.rs | 6 +- clippy_lints/src/large_enum_variant.rs | 14 +- clippy_lints/src/len_zero.rs | 81 ++-- clippy_lints/src/let_if_seq.rs | 17 +- clippy_lints/src/lib.rs | 62 +-- clippy_lints/src/lifetimes.rs | 61 +-- clippy_lints/src/literal_representation.rs | 8 +- clippy_lints/src/loops.rs | 362 +++++++++-------- clippy_lints/src/map_clone.rs | 33 +- clippy_lints/src/map_unit_fn.rs | 77 ++-- clippy_lints/src/matches.rs | 152 +++++--- clippy_lints/src/mem_discriminant.rs | 1 - clippy_lints/src/mem_forget.rs | 3 +- clippy_lints/src/mem_replace.rs | 1 - clippy_lints/src/methods/mod.rs | 432 +++++++++++---------- clippy_lints/src/methods/unnecessary_filter_map.rs | 1 - clippy_lints/src/minmax.rs | 3 +- clippy_lints/src/misc.rs | 78 ++-- clippy_lints/src/misc_early.rs | 84 ++-- clippy_lints/src/missing_doc.rs | 51 +-- clippy_lints/src/missing_inline.rs | 67 ++-- clippy_lints/src/mut_mut.rs | 15 +- clippy_lints/src/mut_reference.rs | 59 ++- clippy_lints/src/mutex_atomic.rs | 5 +- clippy_lints/src/needless_bool.rs | 48 ++- clippy_lints/src/needless_borrow.rs | 9 +- clippy_lints/src/needless_borrowed_ref.rs | 13 +- clippy_lints/src/needless_continue.rs | 48 ++- clippy_lints/src/needless_pass_by_value.rs | 87 +++-- clippy_lints/src/needless_update.rs | 11 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 +- clippy_lints/src/neg_multiply.rs | 12 +- clippy_lints/src/new_without_default.rs | 28 +- clippy_lints/src/no_effect.rs | 112 +++--- clippy_lints/src/non_copy_const.rs | 77 ++-- clippy_lints/src/non_expressive_names.rs | 53 ++- clippy_lints/src/ok_if_let.rs | 5 +- clippy_lints/src/open_options.rs | 8 +- clippy_lints/src/overflow_check_conditional.rs | 5 +- clippy_lints/src/panic_unimplemented.rs | 5 +- clippy_lints/src/partialeq_ne_impl.rs | 5 +- clippy_lints/src/precedence.rs | 6 +- clippy_lints/src/ptr.rs | 73 ++-- clippy_lints/src/ptr_offset_with_cast.rs | 20 +- clippy_lints/src/question_mark.rs | 23 +- clippy_lints/src/ranges.rs | 56 ++- clippy_lints/src/redundant_clone.rs | 4 +- clippy_lints/src/redundant_field_names.rs | 3 +- clippy_lints/src/redundant_pattern_matching.rs | 51 +-- clippy_lints/src/reference.rs | 1 - clippy_lints/src/regex.rs | 82 ++-- clippy_lints/src/replace_consts.rs | 64 +-- clippy_lints/src/returns.rs | 47 ++- clippy_lints/src/serde_api.rs | 4 +- clippy_lints/src/shadow.rs | 99 ++--- clippy_lints/src/slow_vector_initialization.rs | 97 ++--- clippy_lints/src/suspicious_trait_impl.rs | 30 +- clippy_lints/src/swap.rs | 13 +- clippy_lints/src/temporary_assignment.rs | 3 +- clippy_lints/src/transmute.rs | 211 +++++----- clippy_lints/src/trivially_copy_pass_by_ref.rs | 23 +- clippy_lints/src/types.rs | 322 +++++++++------ clippy_lints/src/unicode.rs | 27 +- clippy_lints/src/unsafe_removed_from_name.rs | 13 +- clippy_lints/src/unused_io_amount.rs | 3 +- clippy_lints/src/unused_label.rs | 11 +- clippy_lints/src/unwrap.rs | 3 +- clippy_lints/src/use_self.rs | 4 - clippy_lints/src/utils/author.rs | 112 ++++-- clippy_lints/src/utils/camel_case.rs | 1 - clippy_lints/src/utils/comparisons.rs | 1 - clippy_lints/src/utils/conf.rs | 40 +- clippy_lints/src/utils/constants.rs | 20 +- clippy_lints/src/utils/higher.rs | 84 ++-- clippy_lints/src/utils/hir_utils.rs | 109 +++--- clippy_lints/src/utils/inspector.rs | 9 +- clippy_lints/src/utils/internal_lints.rs | 37 +- clippy_lints/src/utils/paths.rs | 1 - clippy_lints/src/utils/ptr.rs | 11 +- clippy_lints/src/utils/sugg.rs | 259 ++++++------ clippy_lints/src/utils/usage.rs | 1 - clippy_lints/src/vec.rs | 13 +- clippy_lints/src/write.rs | 17 +- clippy_lints/src/zero_div_zero.rs | 5 +- 134 files changed, 2977 insertions(+), 2703 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 01cb03730b8..bf6355c4a41 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::utils::span_lint; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use std::f64::consts as f64; use crate::syntax::ast::{FloatTy, Lit, LitKind}; use crate::syntax::symbol; +use crate::utils::span_lint; +use std::f64::consts as f64; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index a481d46cce0..2e24eb7122d 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::utils::span_lint; use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::source_map::Span; +use crate::utils::span_lint; /// **What it does:** Checks for plain integer arithmetic. /// @@ -52,7 +51,8 @@ declare_clippy_lint! { #[derive(Copy, Clone, Default)] pub struct Arithmetic { expr_span: Option, - /// This field is used to check whether expressions are constants, such as in enum discriminants and consts + /// This field is used to check whether expressions are constants, such as in enum discriminants + /// and consts const_span: Option, } @@ -124,8 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { let body_owner = cx.tcx.hir.body_owner(body.id()); match cx.tcx.hir.body_owner_kind(body_owner) { - hir::BodyOwnerKind::Static(_) - | hir::BodyOwnerKind::Const => { + hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => { let body_span = cx.tcx.hir.span(body_owner); if let Some(span) = self.const_span { @@ -134,7 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } } self.const_span = Some(body_span); - } + }, hir::BodyOwnerKind::Fn => (), } } diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 803c79d42fc..91562ece5f5 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; -use crate::utils::{higher, sugg}; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::syntax::ast; use crate::rustc_errors::Applicability; +use crate::syntax::ast; +use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; +use crate::utils::{higher, sugg}; +use if_chain::if_chain; /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` /// patterns. @@ -217,7 +216,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // a = b commutative_op a // Limited to primitive type as these ops are know to be commutative if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) - && cx.tables.expr_ty(assignee).is_primitive_ty() { + && cx.tables.expr_ty(assignee).is_primitive_ty() + { match op.node { hir::BinOpKind::Add | hir::BinOpKind::Mul diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 88b61f07422..4f9d5f2a768 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,27 +7,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! checks for attributes use crate::reexport::*; -use crate::utils::{ - in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, without_block_comments, -}; -use if_chain::if_chain; use crate::rustc::hir::*; use crate::rustc::lint::{ CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, }; use crate::rustc::ty::{self, TyCtxt}; use crate::rustc::{declare_tool_lint, lint_array}; -use semver::Version; -use crate::syntax::ast::{ - AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind, -}; -use crate::syntax::source_map::Span; use crate::rustc_errors::Applicability; +use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use crate::syntax::source_map::Span; +use crate::utils::{ + in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg, + span_lint_and_then, without_block_comments, +}; +use if_chain::if_chain; +use semver::Version; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -219,8 +216,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { match &*attr.name().as_str() { "allow" | "warn" | "deny" | "forbid" => { check_clippy_lint_names(cx, items); - } - _ => {} + }, + _ => {}, } if items.is_empty() || attr.name() != "deprecated" { return; @@ -254,19 +251,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { // and `unused_imports` for `extern crate` items with `macro_use` for lint in lint_list { match item.node { - ItemKind::Use(..) => if is_word(lint, "unused_imports") - || is_word(lint, "deprecated") { - return + ItemKind::Use(..) => { + if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { + return; + } }, ItemKind::ExternCrate(..) => { - if is_word(lint, "unused_imports") - && skip_unused_imports { - return + if is_word(lint, "unused_imports") && skip_unused_imports { + return; } if is_word(lint, "unused_extern_crates") { - return + return; } - } + }, _ => {}, } } @@ -396,14 +393,16 @@ fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block), ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e), ExprKind::Ret(None) | ExprKind::Break(_, None) => false, - ExprKind::Call(ref path_expr, _) => if let ExprKind::Path(ref qpath) = path_expr.node { - if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) { - !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + ExprKind::Call(ref path_expr, _) => { + if let ExprKind::Path(ref qpath) = path_expr.node { + if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) { + !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + } else { + true + } } else { true } - } else { - true }, _ => true, } @@ -435,7 +434,8 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib cx, EMPTY_LINE_AFTER_OUTER_ATTR, begin_of_attr_to_item, - "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?" + "Found an empty line after an outer attribute. \ + Perhaps you forgot to add a '!' to make it an inner attribute?", ); } } @@ -501,9 +501,7 @@ pub struct CfgAttrPass; impl LintPass for CfgAttrPass { fn get_lints(&self) -> LintArray { - lint_array!( - DEPRECATED_CFG_ATTR, - ) + lint_array!(DEPRECATED_CFG_ATTR,) } } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 6ba6a182902..b15ce871c32 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::consts::{constant, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Span; -use crate::utils::{span_lint, span_lint_and_then}; use crate::utils::sugg::Sugg; -use crate::consts::{constant, Constant}; -use crate::rustc_errors::Applicability; +use crate::utils::{span_lint, span_lint_and_then}; +use if_chain::if_chain; /// **What it does:** Checks for incompatible bit masks in comparisons. /// @@ -173,7 +172,6 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } } - fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node { if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { @@ -185,99 +183,112 @@ fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp } } -fn check_bit_mask(cx: &LateContext<'_, '_>, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) { +fn check_bit_mask( + cx: &LateContext<'_, '_>, + bit_op: BinOpKind, + cmp_op: BinOpKind, + mask_value: u128, + cmp_value: u128, + span: Span, +) { match cmp_op { BinOpKind::Eq | BinOpKind::Ne => match bit_op { - BinOpKind::BitAnd => if mask_value & cmp_value != cmp_value { - if cmp_value != 0 { + BinOpKind::BitAnd => { + if mask_value & cmp_value != cmp_value { + if cmp_value != 0 { + span_lint( + cx, + BAD_BIT_MASK, + span, + &format!( + "incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, cmp_value + ), + ); + } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); + } + }, + BinOpKind::BitOr => { + if mask_value | cmp_value != cmp_value { span_lint( cx, BAD_BIT_MASK, span, &format!( - "incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, - cmp_value + "incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, cmp_value ), ); } - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); - }, - BinOpKind::BitOr => if mask_value | cmp_value != cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - &format!( - "incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, - cmp_value - ), - ); }, _ => (), }, BinOpKind::Lt | BinOpKind::Ge => match bit_op { - BinOpKind::BitAnd => if mask_value < cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - &format!( - "incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); + BinOpKind::BitAnd => { + if mask_value < cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + span, + &format!( + "incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); + } }, - BinOpKind::BitOr => if mask_value >= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - &format!( - "incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_lt(cx, span, mask_value, cmp_value, "|"); + BinOpKind::BitOr => { + if mask_value >= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + span, + &format!( + "incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, cmp_value + ), + ); + } else { + check_ineffective_lt(cx, span, mask_value, cmp_value, "|"); + } }, BinOpKind::BitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"), _ => (), }, BinOpKind::Le | BinOpKind::Gt => match bit_op { - BinOpKind::BitAnd => if mask_value <= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - &format!( - "incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); + BinOpKind::BitAnd => { + if mask_value <= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + span, + &format!( + "incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); + } }, - BinOpKind::BitOr => if mask_value > cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - span, - &format!( - "incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_gt(cx, span, mask_value, cmp_value, "|"); + BinOpKind::BitOr => { + if mask_value > cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + span, + &format!( + "incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, cmp_value + ), + ); + } else { + check_ineffective_gt(cx, span, mask_value, cmp_value, "|"); + } }, BinOpKind::BitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"), _ => (), @@ -294,9 +305,7 @@ fn check_ineffective_lt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c + op, m, c ), ); } @@ -310,9 +319,7 @@ fn check_ineffective_gt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, span, &format!( "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", - op, - m, - c + op, m, c ), ); } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index ecc9957b88f..bf311b3fd56 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::utils::span_lint; /// **What it does:** Checks for usage of blacklisted names for variables, such @@ -38,9 +37,7 @@ pub struct BlackListedName { impl BlackListedName { pub fn new(blacklist: Vec) -> Self { - Self { - blacklist, - } + Self { blacklist } } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 129b8fe9e58..5597b856a8c 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use matches::matches; +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::utils::*; +use matches::matches; /// **What it does:** Checks for `if` conditions that use blocks to contain an /// expression. @@ -112,10 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { ); } } else { - let span = block - .expr - .as_ref() - .map_or_else(|| block.stmts[0].span, |e| e.span); + let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); if in_macro(span) || differing_macro_contexts(expr.span, span) { return; } @@ -134,10 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { } } } else { - let mut visitor = ExVisitor { - found_block: None, - cx, - }; + let mut visitor = ExVisitor { found_block: None, cx }; walk_expr(&mut visitor, check); if let Some(block) = visitor.found_block { span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE); diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 2d587b79357..9f58cb6582e 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -7,16 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::intravisit::*; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; -use crate::rustc::hir::intravisit::*; -use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; -use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; use crate::rustc_data_structures::thin_vec::ThinVec; -use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait}; use crate::rustc_errors::Applicability; +use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; +use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; +use crate::utils::{ + get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_then, SpanlessEq, +}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -57,10 +58,7 @@ declare_clippy_lint! { } // For each pairs, both orders are considered. -const METHODS_WITH_NEGATION: [(&str, &str); 2] = [ - ("is_some", "is_none"), - ("is_err", "is_ok"), -]; +const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")]; #[derive(Copy, Clone)] pub struct NonminimalBool; @@ -134,19 +132,16 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } let negated = match e.node { ExprKind::Binary(binop, ref lhs, ref rhs) => { - if !implements_ord(self.cx, lhs) { continue; } - let mk_expr = |op| { - Expr { - id: DUMMY_NODE_ID, - hir_id: DUMMY_HIR_ID, - span: DUMMY_SP, - attrs: ThinVec::new(), - node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()), - } + let mk_expr = |op| Expr { + id: DUMMY_NODE_ID, + hir_id: DUMMY_HIR_ID, + span: DUMMY_SP, + attrs: ThinVec::new(), + node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()), }; match binop.node { BinOpKind::Eq => mk_expr(BinOpKind::Ne), @@ -191,7 +186,6 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { fn simplify_not(&self, expr: &Expr) -> Option { match expr.node { ExprKind::Binary(binop, ref lhs, ref rhs) => { - if !implements_ord(self.cx, lhs) { return None; } @@ -204,16 +198,19 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { BinOpKind::Le => Some(" > "), BinOpKind::Ge => Some(" < "), _ => None, - }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) + } + .and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, ExprKind::MethodCall(ref path, _, ref args) if args.len() == 1 => { let type_of_receiver = self.cx.tables.expr_ty(&args[0]); - if !match_type(self.cx, type_of_receiver, &paths::OPTION) && - !match_type(self.cx, type_of_receiver, &paths::RESULT) { - return None; + if !match_type(self.cx, type_of_receiver, &paths::OPTION) + && !match_type(self.cx, type_of_receiver, &paths::RESULT) + { + return None; } METHODS_WITH_NEGATION - .iter().cloned() + .iter() + .cloned() .flat_map(|(a, b)| vec![(a, b), (b, a)]) .find(|&(a, _)| a == path.ident.as_str()) .and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method))) @@ -452,7 +449,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { improvements .into_iter() .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals).0) - .collect() + .collect(), ); } } @@ -465,11 +462,15 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { return; } match e.node { - ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => self.bool_expr(e), - ExprKind::Unary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { - self.bool_expr(e); - } else { - walk_expr(self, e); + ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => { + self.bool_expr(e) + }, + ExprKind::Unary(UnNot, ref inner) => { + if self.cx.tables.node_types()[inner.hir_id].is_bool() { + self.bool_expr(e); + } else { + walk_expr(self, e); + } }, _ => walk_expr(self, e), } @@ -479,9 +480,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } } - fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> bool { let ty = cx.tables.expr_ty(expr); - get_trait_def_id(cx, &paths::ORD) - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])) } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 4f02b627e51..31ec879d18d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty; @@ -118,10 +117,12 @@ fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool { fn get_path_name(expr: &Expr) -> Option { match expr.node { ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprKind::Block(ref b, _) => if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { - None + ExprKind::Block(ref b, _) => { + if b.stmts.is_empty() { + b.expr.as_ref().and_then(|p| get_path_name(p)) + } else { + None + } }, ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), _ => None, diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index c39c05c789b..4d15944d317 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -56,7 +56,7 @@ fn is_empty_str(value: &Option) -> bool { match value { None => true, Some(value) if value.is_empty() => true, - _ => false + _ => false, } } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 206403791a1..80f0267a981 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for if expressions that contain only an if expression. //! //! For example, the lint would catch: @@ -24,12 +23,12 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::syntax::ast; +use if_chain::if_chain; -use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; -use crate::utils::sugg::Sugg; use crate::rustc_errors::Applicability; +use crate::utils::sugg::Sugg; +use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; /// **What it does:** Checks for nested `if` statements which can be collapsed /// by `&&`-combining their conditions and for `else { if ... }` expressions @@ -100,10 +99,12 @@ impl EarlyLintPass for CollapsibleIf { fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { match expr.node { - ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ { - check_collapsible_maybe_if_let(cx, else_); - } else { - check_collapsible_no_if_let(cx, expr, check, then); + ast::ExprKind::If(ref check, ref then, ref else_) => { + if let Some(ref else_) = *else_ { + check_collapsible_maybe_if_let(cx, else_); + } else { + check_collapsible_no_if_let(cx, expr, check, then); + } }, ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => { check_collapsible_maybe_if_let(cx, else_); @@ -114,8 +115,9 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { // We trim all opening braces and whitespaces and then check if the next string is a comment. - let trimmed_block_text = - snippet_block(cx, expr.span, "..").trim_left_matches(|c: char| c.is_whitespace() || c == '{').to_owned(); + let trimmed_block_text = snippet_block(cx, expr.span, "..") + .trim_left_matches(|c: char| c.is_whitespace() || c == '{') + .to_owned(); trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 4c49aee2850..ecf3bb1f96e 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::{in_macro, snippet, span_lint_and_then}; use crate::rustc_errors::Applicability; +use crate::syntax::ast::*; +use crate::utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// @@ -52,16 +51,17 @@ impl StaticConst { TyKind::Array(ref ty, _) => { self.visit_type(&*ty, cx); }, - TyKind::Tup(ref tup) => for tup_ty in tup { - self.visit_type(&*tup_ty, cx); + TyKind::Tup(ref tup) => { + for tup_ty in tup { + self.visit_type(&*tup_ty, cx); + } }, // This is what we are looking for ! TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { match borrow_type.ty.node { - TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | - TyKind::Tup(..) => { + TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => { if lifetime.ident.name == "'static" { let snip = snippet(cx, borrow_type.ty.span, ""); let sugg = format!("&{}", snip); @@ -72,7 +72,7 @@ impl StaticConst { "Constants have by default a `'static` lifetime", |db| { db.span_suggestion_with_applicability( - ty.span, + ty.span, "consider removing `'static`", sugg, Applicability::MachineApplicable, //snippet @@ -80,8 +80,8 @@ impl StaticConst { }, ); } - } - _ => {} + }, + _ => {}, } } self.visit_type(&*borrow_type.ty, cx); diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 67c0de93496..26a92ab8b9f 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -10,21 +10,21 @@ #![allow(clippy::float_cmp)] -use crate::rustc::lint::LateContext; -use crate::rustc::{span_bug, bug}; use crate::rustc::hir::def::Def; use crate::rustc::hir::*; -use crate::rustc::ty::{self, Ty, TyCtxt, Instance}; +use crate::rustc::lint::LateContext; use crate::rustc::ty::subst::{Subst, Substs}; +use crate::rustc::ty::{self, Instance, Ty, TyCtxt}; +use crate::rustc::{bug, span_bug}; +use crate::syntax::ast::{FloatTy, LitKind}; +use crate::syntax::ptr::P; +use crate::utils::{clip, sext, unsext}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; use std::mem; use std::rc::Rc; -use crate::syntax::ast::{FloatTy, LitKind}; -use crate::syntax::ptr::P; -use crate::utils::{sext, unsext, clip}; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -71,7 +71,9 @@ impl PartialEq for Constant { unsafe { mem::transmute::(f64::from(l)) == mem::transmute::(f64::from(r)) } }, (&Constant::Bool(l), &Constant::Bool(r)) => l == r, - (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, + (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => { + l == r + }, (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, _ => false, // TODO: Are there inter-type equalities? } @@ -117,7 +119,12 @@ impl Hash for Constant { } impl Constant { - pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TyKind<'_>, left: &Self, right: &Self) -> Option { + pub fn partial_cmp( + tcx: TyCtxt<'_, '_, '_>, + cmp_type: &ty::TyKind<'_>, + left: &Self, + right: &Self, + ) -> Option { match (left, right) { (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), @@ -158,8 +165,7 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), - LitKind::Float(ref is, _) | - LitKind::FloatUnsuffixed(ref is) => match ty.sty { + LitKind::Float(ref is, _) | LitKind::FloatUnsuffixed(ref is) => match ty.sty { ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()), ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()), _ => bug!(), @@ -168,7 +174,11 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { } } -pub fn constant<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option<(Constant, bool)> { +pub fn constant<'c, 'cc>( + lcx: &LateContext<'c, 'cc>, + tables: &'c ty::TypeckTables<'cc>, + e: &Expr, +) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { tcx: lcx.tcx, tables, @@ -179,12 +189,19 @@ pub fn constant<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTable cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } -pub fn constant_simple<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option { +pub fn constant_simple<'c, 'cc>( + lcx: &LateContext<'c, 'cc>, + tables: &'c ty::TypeckTables<'cc>, + e: &Expr, +) -> Option { constant(lcx, tables, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables` -pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> { +pub fn constant_context<'c, 'cc>( + lcx: &LateContext<'c, 'cc>, + tables: &'c ty::TypeckTables<'cc>, +) -> ConstEvalLateContext<'c, 'cc> { ConstEvalLateContext { tcx: lcx.tcx, tables, @@ -270,9 +287,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part fn multi(&mut self, vec: &[Expr]) -> Option> { - vec.iter() - .map(|elem| self.expr(elem)) - .collect::>() + vec.iter().map(|elem| self.expr(elem)).collect::>() } /// lookup a possibly constant expression from a ExprKind::Path @@ -331,63 +346,51 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { - (Constant::Int(l), Some(Constant::Int(r))) => { - match self.tables.expr_ty(left).sty { - ty::Int(ity) => { - let l = sext(self.tcx, l, ity); - let r = sext(self.tcx, r, ity); - let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); - match op.node { - BinOpKind::Add => l.checked_add(r).map(zext), - BinOpKind::Sub => l.checked_sub(r).map(zext), - BinOpKind::Mul => l.checked_mul(r).map(zext), - BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), - BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), - BinOpKind::Shr => l.checked_shr( - r.try_into().expect("invalid shift") - ).map(zext), - BinOpKind::Shl => l.checked_shl( - r.try_into().expect("invalid shift") - ).map(zext), - BinOpKind::BitXor => Some(zext(l ^ r)), - BinOpKind::BitOr => Some(zext(l | r)), - BinOpKind::BitAnd => Some(zext(l & r)), - BinOpKind::Eq => Some(Constant::Bool(l == r)), - BinOpKind::Ne => Some(Constant::Bool(l != r)), - BinOpKind::Lt => Some(Constant::Bool(l < r)), - BinOpKind::Le => Some(Constant::Bool(l <= r)), - BinOpKind::Ge => Some(Constant::Bool(l >= r)), - BinOpKind::Gt => Some(Constant::Bool(l > r)), - _ => None, - } + (Constant::Int(l), Some(Constant::Int(r))) => match self.tables.expr_ty(left).sty { + ty::Int(ity) => { + let l = sext(self.tcx, l, ity); + let r = sext(self.tcx, r, ity); + let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); + match op.node { + BinOpKind::Add => l.checked_add(r).map(zext), + BinOpKind::Sub => l.checked_sub(r).map(zext), + BinOpKind::Mul => l.checked_mul(r).map(zext), + BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), + BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), + BinOpKind::Shr => l.checked_shr(r.try_into().expect("invalid shift")).map(zext), + BinOpKind::Shl => l.checked_shl(r.try_into().expect("invalid shift")).map(zext), + BinOpKind::BitXor => Some(zext(l ^ r)), + BinOpKind::BitOr => Some(zext(l | r)), + BinOpKind::BitAnd => Some(zext(l & r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), + _ => None, } - ty::Uint(_) => { - match op.node { - BinOpKind::Add => l.checked_add(r).map(Constant::Int), - BinOpKind::Sub => l.checked_sub(r).map(Constant::Int), - BinOpKind::Mul => l.checked_mul(r).map(Constant::Int), - BinOpKind::Div => l.checked_div(r).map(Constant::Int), - BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), - BinOpKind::Shr => l.checked_shr( - r.try_into().expect("shift too large") - ).map(Constant::Int), - BinOpKind::Shl => l.checked_shl( - r.try_into().expect("shift too large") - ).map(Constant::Int), - BinOpKind::BitXor => Some(Constant::Int(l ^ r)), - BinOpKind::BitOr => Some(Constant::Int(l | r)), - BinOpKind::BitAnd => Some(Constant::Int(l & r)), - BinOpKind::Eq => Some(Constant::Bool(l == r)), - BinOpKind::Ne => Some(Constant::Bool(l != r)), - BinOpKind::Lt => Some(Constant::Bool(l < r)), - BinOpKind::Le => Some(Constant::Bool(l <= r)), - BinOpKind::Ge => Some(Constant::Bool(l >= r)), - BinOpKind::Gt => Some(Constant::Bool(l > r)), - _ => None, - } - }, + }, + ty::Uint(_) => match op.node { + BinOpKind::Add => l.checked_add(r).map(Constant::Int), + BinOpKind::Sub => l.checked_sub(r).map(Constant::Int), + BinOpKind::Mul => l.checked_mul(r).map(Constant::Int), + BinOpKind::Div => l.checked_div(r).map(Constant::Int), + BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), + BinOpKind::Shr => l.checked_shr(r.try_into().expect("shift too large")).map(Constant::Int), + BinOpKind::Shl => l.checked_shl(r.try_into().expect("shift too large")).map(Constant::Int), + BinOpKind::BitXor => Some(Constant::Int(l ^ r)), + BinOpKind::BitOr => Some(Constant::Int(l | r)), + BinOpKind::BitAnd => Some(Constant::Int(l & r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, - } + }, + _ => None, }, (Constant::F32(l), Some(Constant::F32(r))) => match op.node { BinOpKind::Add => Some(Constant::F32(l + r)), @@ -420,7 +423,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (l, r) => match (op.node, l, r) { (BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => Some(r), + (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => { + Some(r) + }, (BinOpKind::BitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), (BinOpKind::BitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), (BinOpKind::BitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)), @@ -431,36 +436,34 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use crate::rustc::mir::interpret::{Scalar, ConstValue}; + use crate::rustc::mir::interpret::{ConstValue, Scalar}; match result.val { - ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty { + ConstValue::Scalar(Scalar::Bits { bits: b, .. }) => match result.ty.sty { ty::Bool => Some(Constant::Bool(b == 1)), ty::Uint(_) | ty::Int(_) => Some(Constant::Int(b)), ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( - b.try_into().expect("invalid f32 bit representation") + b.try_into().expect("invalid f32 bit representation"), ))), ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( - b.try_into().expect("invalid f64 bit representation") + b.try_into().expect("invalid f64 bit representation"), ))), // FIXME: implement other conversion _ => None, }, - ConstValue::ScalarPair(Scalar::Ptr(ptr), - Scalar::Bits { bits: n, .. }) => match result.ty.sty { + ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty { ty::Ref(_, tam, _) => match tam.sty { ty::Str => { - let alloc = tcx - .alloc_map - .lock() - .unwrap_memory(ptr.alloc_id); + let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); let offset = ptr.offset.bytes().try_into().expect("too-large pointer offset"); let n = n as usize; - String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str) + String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()) + .ok() + .map(Constant::Str) }, _ => None, }, _ => None, - } + }, // FIXME: implement other conversions _ => None, } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index c69173ac269..2f7aac99acd 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty::Ty; -use crate::rustc::hir::*; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; -use std::collections::hash_map::Entry; -use std::hash::BuildHasherDefault; use crate::syntax::symbol::LocalInternedString; -use smallvec::SmallVec; -use crate::utils::{SpanlessEq, SpanlessHash}; use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; +use crate::utils::{SpanlessEq, SpanlessHash}; +use smallvec::SmallVec; +use std::collections::hash_map::Entry; +use std::hash::BuildHasherDefault; /// **What it does:** Checks for consecutive `if`s with the same condition. /// @@ -168,7 +167,8 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) { h.finish() }; - let eq: &dyn Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; + let eq: &dyn Fn(&&Expr, &&Expr) -> bool = + &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; if let Some((i, j)) = search_same(conds, hash, eq) { span_note_and_lint( @@ -229,7 +229,10 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { // hiding all the subsequent arms, and rust won't compile db.span_note( i.body.span, - &format!("`{}` has the same arm body as the `_` wildcard, consider removing it`", lhs), + &format!( + "`{}` has the same arm body as the `_` wildcard, consider removing it`", + lhs + ), ); } else { db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs)); @@ -276,11 +279,17 @@ fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>) /// Return the list of bindings in a pattern. fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap> { - fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut FxHashMap>) { + fn bindings_impl<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + pat: &Pat, + map: &mut FxHashMap>, + ) { match pat.node { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), - PatKind::TupleStruct(_, ref pats, _) => for pat in pats { - bindings_impl(cx, pat, map); + PatKind::TupleStruct(_, ref pats, _) => { + for pat in pats { + bindings_impl(cx, pat, map); + } }, PatKind::Binding(_, _, ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.as_str()) { @@ -290,11 +299,15 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap for pat in fields { - bindings_impl(cx, &pat.node.pat, map); + PatKind::Struct(_, ref fields, _) => { + for pat in fields { + bindings_impl(cx, &pat.node.pat, map); + } }, - PatKind::Tuple(ref fields, _) => for pat in fields { - bindings_impl(cx, pat, map); + PatKind::Tuple(ref fields, _) => { + for pat in fields { + bindings_impl(cx, pat, map); + } }, PatKind::Slice(ref lhs, ref mid, ref rhs) => { for pat in lhs { @@ -316,7 +329,6 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap(exprs: &[T], eq: Eq) -> Option<(&T, &T)> where Eq: Fn(&T, &T) -> bool, @@ -345,10 +357,8 @@ where }; } - let mut map: FxHashMap<_, Vec<&_>> = FxHashMap::with_capacity_and_hasher( - exprs.len(), - BuildHasherDefault::default() - ); + let mut map: FxHashMap<_, Vec<&_>> = + FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default()); for expr in exprs { match map.entry(hash(expr)) { diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index f4d29433cb8..af6142c8a04 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use crate::rustc::hir::{Item, ItemKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; /// **What it does:** Checks for types that implement `Copy` as well as /// `Iterator`. diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 7971d20d83f..132440885f7 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! calculate cyclomatic complexity and warn about overly complex functions use crate::rustc::cfg::CFG; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::{Attribute, NodeId}; use crate::syntax::source_map::Span; @@ -138,12 +137,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { } fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit - .push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit - .pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); + self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } } @@ -197,7 +194,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { #[cfg(feature = "debugging")] #[allow(clippy::too_many_arguments)] -fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) { +fn report_cc_bug( + _: &LateContext<'_, '_>, + cc: u64, + narms: u64, + div: u64, + shorts: u64, + returns: u64, + span: Span, + _: NodeId, +) { span_bug!( span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ @@ -211,7 +217,16 @@ fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: } #[cfg(not(feature = "debugging"))] #[allow(clippy::too_many_arguments)] -fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) { +fn report_cc_bug( + cx: &LateContext<'_, '_>, + cc: u64, + narms: u64, + div: u64, + shorts: u64, + returns: u64, + span: Span, + id: NodeId, +) { if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) { cx.sess().span_note_without_error( span, @@ -220,11 +235,7 @@ fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts (hide this message with `#[allow(cyclomatic_complexity)]`): \ cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ Please file a bug report.", - cc, - narms, - div, - shorts, - returns + cc, narms, div, shorts, returns ), ); } diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 693b47f6fff..bc5643a0bed 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty::TyKind; @@ -17,7 +16,6 @@ use if_chain::if_chain; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; - /// **What it does:** Checks for literal calls to `Default::default()`. /// /// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is @@ -51,44 +49,44 @@ impl LintPass for DefaultTraitAccess { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprKind::Call(ref path, ..) = expr.node; - if !any_parent_is_automatically_derived(cx.tcx, expr.id); - if let ExprKind::Path(ref qpath) = path.node; - if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); - if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); - then { - match qpath { - QPath::Resolved(..) => { - if_chain! { - // Detect and ignore ::default() because these calls do - // explicitly name the type. - if let ExprKind::Call(ref method, ref _args) = expr.node; - if let ExprKind::Path(ref p) = method.node; - if let QPath::Resolved(Some(_ty), _path) = p; - then { - return; - } - } + if let ExprKind::Call(ref path, ..) = expr.node; + if !any_parent_is_automatically_derived(cx.tcx, expr.id); + if let ExprKind::Path(ref qpath) = path.node; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); + if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); + then { + match qpath { + QPath::Resolved(..) => { + if_chain! { + // Detect and ignore ::default() because these calls do + // explicitly name the type. + if let ExprKind::Call(ref method, ref _args) = expr.node; + if let ExprKind::Path(ref p) = method.node; + if let QPath::Resolved(Some(_ty), _path) = p; + then { + return; + } + } - // TODO: Work out a way to put "whatever the imported way of referencing - // this type in this file" rather than a fully-qualified type. - let expr_ty = cx.tables.expr_ty(expr); - if let TyKind::Adt(..) = expr_ty.sty { - let replacement = format!("{}::default()", expr_ty); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("Calling {} is more clear than this expression", replacement), - "try", - replacement, - Applicability::Unspecified, // First resolve the TODO above - ); - } - }, - QPath::TypeRelative(..) => {}, - } - } - } + // TODO: Work out a way to put "whatever the imported way of referencing + // this type in this file" rather than a fully-qualified type. + let expr_ty = cx.tables.expr_ty(expr); + if let TyKind::Adt(..) = expr_ty.sty { + let replacement = format!("{}::default()", expr_ty); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("Calling {} is more clear than this expression", replacement), + "try", + replacement, + Applicability::Unspecified, // First resolve the TODO above + ); + } + }, + QPath::TypeRelative(..) => {}, + } + } + } } } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 792699fc0c5..96621d366fa 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty::{self, Ty}; -use crate::rustc::hir::*; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; +use if_chain::if_chain; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly or vice versa. @@ -154,18 +153,20 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref ty::Adt(def, _) if def.is_union() => return, // Some types are not Clone by default but could be cloned “by hand” if necessary - ty::Adt(def, substs) => for variant in &def.variants { - for field in &variant.fields { - if let ty::FnDef(..) = field.ty(cx.tcx, substs).sty { - return; - } - } - for subst in substs { - if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { - if let ty::Param(_) = subst.sty { + ty::Adt(def, substs) => { + for variant in &def.variants { + for field in &variant.fields { + if let ty::FnDef(..) = field.ty(cx.tcx, substs).sty { return; } } + for subst in substs { + if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { + if let ty::Param(_) = subst.sty { + return; + } + } + } } }, _ => (), diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 9c25e79aa71..a3278159ef5 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use itertools::Itertools; -use pulldown_cmark; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; use crate::syntax::source_map::{BytePos, Span}; use crate::syntax_pos::Pos; use crate::utils::span_lint; +use itertools::Itertools; +use pulldown_cmark; use url::Url; /// **What it does:** Checks for the presence of `_`, `::` or camel-case words @@ -49,9 +48,7 @@ pub struct Doc { impl Doc { pub fn new(valid_idents: Vec) -> Self { - Self { - valid_idents, - } + Self { valid_idents } } } @@ -107,9 +104,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( doc.push('\n'); return ( doc.to_owned(), - vec![ - (doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32))), - ], + vec![(doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32)))], ); } } @@ -275,13 +270,10 @@ fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) { return false; } - let s = if s.ends_with('s') { - &s[..s.len() - 1] - } else { - s - }; + let s = if s.ends_with('s') { &s[..s.len() - 1] } else { s }; - s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 + s.chars().all(char::is_alphanumeric) + && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 } diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 4d8345dadc3..25ce883cac8 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Lint on unnecessary double comparisons. Some examples: use crate::rustc::hir::*; @@ -51,18 +50,11 @@ impl LintPass for Pass { impl<'a, 'tcx> Pass { #[allow(clippy::similar_names)] - fn check_binop( - &self, - cx: &LateContext<'a, 'tcx>, - op: BinOpKind, - lhs: &'tcx Expr, - rhs: &'tcx Expr, - span: Span, - ) { + fn check_binop(&self, cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) { let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) { (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) - } + }, _ => return, }; let mut spanless_eq = SpanlessEq::new(cx).ignore_fn(); @@ -84,13 +76,21 @@ impl<'a, 'tcx> Pass { sugg, applicability, ); - }} + }}; } match (op, lkind, rkind) { - (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => lint_double_comparison!(<=), - (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => lint_double_comparison!(>=), - (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => lint_double_comparison!(!=), - (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => lint_double_comparison!(==), + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => { + lint_double_comparison!(<=) + }, + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => { + lint_double_comparison!(>=) + }, + (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => { + lint_double_comparison!(!=) + }, + (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { + lint_double_comparison!(==) + }, _ => (), }; } diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index ffaf93bd7a1..d3979e660cc 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -7,13 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::syntax::ast::*; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::ast::*; use crate::utils::{in_macro, span_lint}; - /// **What it does:** Checks for unnecessary double parentheses. /// /// **Why is this bad?** This makes code harder to read and might indicate a @@ -51,20 +49,39 @@ impl EarlyLintPass for DoubleParens { match expr.node { ExprKind::Paren(ref in_paren) => match in_paren.node { ExprKind::Paren(_) | ExprKind::Tup(_) => { - span_lint(cx, DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); + span_lint( + cx, + DOUBLE_PARENS, + expr.span, + "Consider removing unnecessary double parentheses", + ); }, _ => {}, }, - ExprKind::Call(_, ref params) => if params.len() == 1 { - let param = ¶ms[0]; - if let ExprKind::Paren(_) = param.node { - span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); + ExprKind::Call(_, ref params) => { + if params.len() == 1 { + let param = ¶ms[0]; + if let ExprKind::Paren(_) = param.node { + span_lint( + cx, + DOUBLE_PARENS, + param.span, + "Consider removing unnecessary double parentheses", + ); + } } }, - ExprKind::MethodCall(_, ref params) => if params.len() == 2 { - let param = ¶ms[1]; - if let ExprKind::Paren(_) = param.node { - span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); + ExprKind::MethodCall(_, ref params) => { + if params.len() == 2 { + let param = ¶ms[1]; + if let ExprKind::Paren(_) = param.node { + span_lint( + cx, + DOUBLE_PARENS, + param.span, + "Consider removing unnecessary double parentheses", + ); + } } }, _ => {}, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 9bead9c1d86..a9741c7a2dd 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; -use crate::rustc::hir::*; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; +use if_chain::if_chain; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. @@ -70,9 +69,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let x:i32 = 42; // i32 implements Copy +/// let x: i32 = 42; // i32 implements Copy /// std::mem::drop(x) // A copy of x is passed to the function, leaving the -/// // original unaffected +/// // original unaffected /// ``` declare_clippy_lint! { pub DROP_COPY, @@ -97,9 +96,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let x:i32 = 42; // i32 implements Copy +/// let x: i32 = 42; // i32 implements Copy /// std::mem::forget(x) // A copy of x is passed to the function, leaving the -/// // original unaffected +/// // original unaffected /// ``` declare_clippy_lint! { pub FORGET_COPY, diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index fe4aea572e0..295f7532e90 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -68,7 +67,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { expr.span, &format!("Calling `{}()` is more concise than this calculation", suggested_fn), "try", - format!("{}.{}()", snippet_with_applicability(cx, args[0].span, "_", &mut applicability), suggested_fn), + format!( + "{}.{}()", + snippet_with_applicability(cx, args[0].span, "_", &mut applicability), + suggested_fn + ), applicability, ); } diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index cb75d983683..e977019fa4e 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on if expressions with an else if, but without a final else branch -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 7ac33fd452e..b9b6b17a2dd 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint when there is an enum with no variants +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::utils::span_lint_and_then; /// **What it does:** Checks for `enum`s with no variants. @@ -47,11 +46,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { let did = cx.tcx.hir.local_def_id(item.id); if let ItemKind::Enum(..) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def() - .expect("already checked whether this is an enum"); + let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); if adt.variants.is_empty() { span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| { - db.span_help(item.span, "consider using the uninhabited type `!` or a wrapper around it"); + db.span_help( + item.span, + "consider using the uninhabited type `!` or a wrapper around it", + ); }); } } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 75c43745207..fad62c6825e 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; -use crate::rustc_errors::Applicability; +use if_chain::if_chain; /// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap` /// or `BTreeMap`. @@ -26,12 +25,16 @@ use crate::rustc_errors::Applicability; /// **Known problems:** Some false negatives, eg.: /// ```rust /// let k = &key; -/// if !m.contains_key(k) { m.insert(k.clone(), v); } +/// if !m.contains_key(k) { +/// m.insert(k.clone(), v); +/// } /// ``` /// /// **Example:** /// ```rust -/// if !m.contains_key(&k) { m.insert(k, v) } +/// if !m.contains_key(&k) { +/// m.insert(k, v) +/// } /// ``` /// can be rewritten as: /// ```rust @@ -60,11 +63,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = { - else_block.is_none() && if let ExprKind::Block(ref then_block, _) = then_block.node { - (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 - } else { - true - } + else_block.is_none() + && if let ExprKind::Block(ref then_block, _) = then_block.node { + (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 + } else { + true + } }; let mut visitor = InsertVisitor { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 315bc54cd17..cf921b6b94c 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -7,20 +7,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; +use crate::consts::{miri_to_const, Constant}; use crate::rustc::hir::*; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::mir::interpret::GlobalId; use crate::rustc::ty; use crate::rustc::ty::subst::Substs; +use crate::rustc::ty::util::IntTypeExt; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::{IntTy, UintTy}; use crate::utils::span_lint; -use crate::consts::{Constant, miri_to_const}; -use crate::rustc::ty::util::IntTypeExt; -use crate::rustc::mir::interpret::GlobalId; /// **What it does:** Checks for C-like enumerations that are /// `repr(isize/usize)` and have values that don't fit into an `i32`. @@ -35,7 +34,7 @@ use crate::rustc::mir::interpret::GlobalId; /// #[repr(usize)] /// enum NonPortable { /// X = 0x1_0000_0000, -/// Y = 0 +/// Y = 0, /// } /// ``` declare_clippy_lint! { @@ -68,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let instance = ty::Instance::new(def_id, substs); let c_id = GlobalId { instance, - promoted: None + promoted: None, }; let constant = cx.tcx.const_eval(param_env.and(c_id)).ok(); if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { @@ -84,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { if val <= i128::from(i32::max_value()) && val >= i128::from(i32::min_value()) { continue; } - } + }, ty::Uint(UintTy::Usize) if val > u128::from(u32::max_value()) => {}, _ => continue, } diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index ebd28ee2796..164b0d8dbad 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on `use`ing all variants of an enum -use crate::rustc::hir::*; use crate::rustc::hir::def::Def; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::NodeId; @@ -60,12 +59,7 @@ impl EnumGlobUse { } if let ItemKind::Use(ref path, UseKind::Glob) = item.node { if let Def::Enum(_) = path.def { - span_lint( - cx, - ENUM_GLOB_USE, - item.span, - "don't use glob imports for enum variants", - ); + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 121a33f9475..ae87c4273e9 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on enum variants that are prefixed or suffixed by the same characters -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, Lint}; +use crate::rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; use crate::syntax::source_map::Span; use crate::syntax::symbol::LocalInternedString; -use crate::utils::{span_help_and_lint, span_lint}; use crate::utils::{camel_case, in_macro}; +use crate::utils::{span_help_and_lint, span_lint}; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. @@ -139,10 +138,7 @@ fn var2str(var: &Variant) -> LocalInternedString { fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next_back(); // make sure the name is never fully matched - pre.chars() - .zip(name_iter) - .take_while(|&(l, r)| l == r) - .count() + pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() } /// Returns the number of chars that match from the end @@ -171,9 +167,7 @@ fn check_variant( for var in &def.variants { let name = var2str(var); if partial_match(item_name, &name) == item_name_chars - && name.chars() - .nth(item_name_chars) - .map_or(false, |c| !c.is_lowercase()) + && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) { span_lint(cx, lint, var.span, "Variant name starts with the enum's name"); } @@ -277,19 +271,26 @@ impl EarlyLintPass for EnumVariantNames { let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); - let is_word_beginning = |c: char| { - c == '_' || c.is_uppercase() || c.is_numeric() - }; + let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric(); if matching == nchars { match item_camel.chars().nth(nchars) { - Some(c) if is_word_beginning(c) => - span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name"), - _ => () + Some(c) if is_word_beginning(c) => span_lint( + cx, + STUTTER, + item.span, + "item name starts with its containing module's name", + ), + _ => (), } } if rmatching == nchars { - span_lint(cx, STUTTER, item.span, "item name ends with its containing module's name"); + span_lint( + cx, + STUTTER, + item.span, + "item name ends with its containing module's name", + ); } } } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index dfe0c0180a7..83644786e51 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -7,12 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; use crate::rustc_errors::Applicability; +use crate::utils::{ + implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq, +}; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, @@ -92,7 +93,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false), BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false), BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true), - BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => (cx.tcx.lang_items().ord_trait(), true), + BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => { + (cx.tcx.lang_items().ord_trait(), true) + }, }; if let Some(trait_id) = trait_id { #[allow(clippy::match_same_arms)] @@ -122,7 +125,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { ); }, ) - } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { + } else if lcpy + && !rcpy + && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) + { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion_with_applicability( @@ -132,7 +138,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { Applicability::MachineApplicable, // snippet ); }) - } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { + } else if !lcpy + && rcpy + && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) + { span_lint_and_then( cx, OP_REF, @@ -154,7 +163,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { (&ExprKind::AddrOf(_, ref l), _) => { let lty = cx.tables.expr_ty(l); let lcpy = is_copy(cx, lty); - if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) { + if (requires_ref || lcpy) + && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) + { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion_with_applicability( @@ -170,7 +181,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { (_, &ExprKind::AddrOf(_, ref r)) => { let rty = cx.tables.expr_ty(r); let rcpy = is_copy(cx, rty); - if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) { + if (requires_ref || rcpy) + && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) + { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); db.span_suggestion_with_applicability( @@ -189,10 +202,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { } } - fn is_valid_operator(op: BinOp) -> bool { match op.node { - BinOpKind::Sub | BinOpKind::Div | BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge | BinOpKind::Ne | BinOpKind::And | BinOpKind::Or | BinOpKind::BitXor | BinOpKind::BitAnd | BinOpKind::BitOr => true, + BinOpKind::Sub + | BinOpKind::Div + | BinOpKind::Eq + | BinOpKind::Lt + | BinOpKind::Le + | BinOpKind::Gt + | BinOpKind::Ge + | BinOpKind::Ne + | BinOpKind::And + | BinOpKind::Or + | BinOpKind::BitXor + | BinOpKind::BitAnd + | BinOpKind::BitOr => true, _ => false, } } diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 7bfc2ef31d0..e2725cf59b0 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -25,7 +24,9 @@ use crate::utils::{in_macro, span_lint}; /// /// **Example:** /// ```rust -/// 0 / x; 0 * x; x & 0 +/// 0 / x; +/// 0 * x; +/// x & 0 /// ``` declare_clippy_lint! { pub ERASING_OP, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 11bdf2244b1..99c145b2677 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::hir::*; use crate::rustc::hir::intravisit as visit; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::middle::expr_use_visitor::*; use crate::rustc::middle::mem_categorization::{cmt_, Categorization}; -use crate::rustc::ty::{self, Ty}; use crate::rustc::ty::layout::LayoutOf; +use crate::rustc::ty::{self, Ty}; use crate::rustc::util::nodemap::NodeSet; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::NodeId; use crate::syntax::source_map::Span; use crate::utils::span_lint; @@ -65,7 +64,6 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, @@ -157,7 +155,15 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } } - fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, loan_cause: LoanCause) { + fn borrow( + &mut self, + _: NodeId, + _: Span, + cmt: &cmt_<'tcx>, + _: ty::Region<'_>, + _: ty::BorrowKind, + loan_cause: LoanCause, + ) { if let Categorization::Local(lid) = cmt.cat { match loan_cause { // x.foo() diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 644c7fb3821..1e7fee9757f 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -7,17 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; -use crate::rustc::hir::*; -use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; +use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; pub struct EtaPass; - /// **What it does:** Checks for closures which just call another function where /// the function can be called directly. `unsafe` functions or calls where types /// get adjusted are ignored. @@ -52,8 +50,10 @@ impl LintPass for EtaPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { - ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args { - check_closure(cx, arg) + ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => { + for arg in args { + check_closure(cx, arg) + } }, _ => (), } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 31fae2d1967..269a6bb6c8a 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; -use crate::rustc::ty; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::syntax::ast; use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; +use if_chain::if_chain; /// **What it does:** Checks for a read and a write to the same variable where /// whether the read occurs before or after the write depends on the evaluation @@ -30,7 +29,10 @@ use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; /// **Example:** /// ```rust /// let mut x = 0; -/// let a = {x = 1; 1} + x; +/// let a = { +/// x = 1; +/// 1 +/// } + x; /// // Unclear whether a is 1 or 2. /// ``` declare_clippy_lint! { @@ -74,17 +76,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Find a write to a local variable. match expr.node { - ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => if let ExprKind::Path(ref qpath) = lhs.node { - if let QPath::Resolved(_, ref path) = *qpath { - if path.segments.len() == 1 { - if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) { - let mut visitor = ReadVisitor { - cx, - var, - write_expr: expr, - last_expr: expr, - }; - check_for_unsequenced_reads(&mut visitor); + ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => { + if let ExprKind::Path(ref qpath) = lhs.node { + if let QPath::Resolved(_, ref path) = *qpath { + if path.segments.len() == 1 { + if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) { + let mut visitor = ReadVisitor { + cx, + var, + write_expr: expr, + last_expr: expr, + }; + check_for_unsequenced_reads(&mut visitor); + } } } } @@ -95,12 +99,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), - StmtKind::Decl(ref d, _) => if let DeclKind::Local(ref local) = d.node { - if let Local { - init: Some(ref e), .. - } = **local - { - DivergenceVisitor { cx }.visit_expr(e); + StmtKind::Decl(ref d, _) => { + if let DeclKind::Local(ref local) = d.node { + if let Local { init: Some(ref e), .. } = **local { + DivergenceVisitor { cx }.visit_expr(e); + } } }, } @@ -179,12 +182,12 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { /// This means reads for which there is a common ancestor between the read and /// the write such that /// -/// * evaluating the ancestor necessarily evaluates both the read and the write -/// (for example, `&x` and `|| x = 1` don't necessarily evaluate `x`), and +/// * evaluating the ancestor necessarily evaluates both the read and the write (for example, `&x` +/// and `|| x = 1` don't necessarily evaluate `x`), and /// -/// * which one is evaluated first depends on the order of sub-expression -/// evaluation. Blocks, `if`s, loops, `match`es, and the short-circuiting -/// logical operators are considered to have a defined evaluation order. +/// * which one is evaluated first depends on the order of sub-expression evaluation. Blocks, `if`s, +/// loops, `match`es, and the short-circuiting logical operators are considered to have a defined +/// evaluation order. /// /// When such a read is found, the lint is triggered. fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { @@ -232,14 +235,14 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St } match expr.node { - ExprKind::Array(_) | - ExprKind::Tup(_) | - ExprKind::MethodCall(..) | - ExprKind::Call(_, _) | - ExprKind::Assign(_, _) | - ExprKind::Index(_, _) | - ExprKind::Repeat(_, _) | - ExprKind::Struct(_, _, _) => { + ExprKind::Array(_) + | ExprKind::Tup(_) + | ExprKind::MethodCall(..) + | ExprKind::Call(_, _) + | ExprKind::Assign(_, _) + | ExprKind::Index(_, _) + | ExprKind::Repeat(_, _) + | ExprKind::Struct(_, _, _) => { walk_expr(vis, expr); }, ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => { @@ -253,13 +256,12 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St ExprKind::Closure(_, _, _, _, _) => { // Either // - // * `var` is defined in the closure body, in which case we've - // reached the top of the enclosing function and can stop, or + // * `var` is defined in the closure body, in which case we've reached the top of the enclosing + // function and can stop, or // - // * `var` is captured by the closure, in which case, because - // evaluating a closure does not evaluate its body, we don't - // necessarily have a write, so we need to stop to avoid - // generating false positives. + // * `var` is captured by the closure, in which case, because evaluating a closure does not evaluate + // its body, we don't necessarily have a write, so we need to stop to avoid generating false + // positives. // // This is also the only place we need to stop early (grrr). return StopEarly::Stop; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 6043dd46ae7..cd0d5941cbe 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty::TyKind; @@ -32,12 +31,12 @@ use std::fmt; /// /// ```rust /// // Bad -/// let v: f32 = 0.123_456_789_9; -/// println!("{}", v); // 0.123_456_789 +/// let v: f32 = 0.123_456_789_9; +/// println!("{}", v); // 0.123_456_789 /// /// // Good -/// let v: f64 = 0.123_456_789_9; -/// println!("{}", v); // 0.123_456_789_9 +/// let v: f64 = 0.123_456_789_9; +/// println!("{}", v); // 0.123_456_789_9 /// ``` declare_clippy_lint! { pub EXCESSIVE_PRECISION, @@ -82,7 +81,7 @@ impl ExcessivePrecision { let max = max_digits(fty); let sym_str = sym.as_str(); if dot_zero_exclusion(&sym_str) { - return None + return None; } // Try to bail out if the float is for sure fine. // If its within the 2 decimal digits of being out of precision we @@ -116,9 +115,7 @@ impl ExcessivePrecision { /// Ex 1_000_000_000. fn dot_zero_exclusion(s: &str) -> bool { if let Some(after_dec) = s.split('.').nth(1) { - let mut decpart = after_dec - .chars() - .take_while(|c| *c != 'e' || *c != 'E'); + let mut decpart = after_dec.chars().take_while(|c| *c != 'e' || *c != 'E'); match decpart.next() { Some('0') => decpart.count() == 0, @@ -169,7 +166,9 @@ impl FloatFormat { .unwrap_or(FloatFormat::Normal) } fn format(&self, f: T) -> String - where T: fmt::UpperExp + fmt::LowerExp + fmt::Display { + where + T: fmt::UpperExp + fmt::LowerExp + fmt::Display, + { match self { FloatFormat::LowerExp => format!("{:e}", f), FloatFormat::UpperExp => format!("{:E}", f), diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index b5a5d7e497d..c1f007fea0b 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; use crate::utils::opt_def_id; +use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; +use if_chain::if_chain; /// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be /// replaced with `(e)print!()` / `(e)println!()` @@ -28,10 +27,10 @@ use crate::utils::opt_def_id; /// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); /// ``` declare_clippy_lint! { - pub EXPLICIT_WRITE, - complexity, - "using the `write!()` family of functions instead of the `print!()` family \ - of functions, when using the latter would work" +pub EXPLICIT_WRITE, +complexity, +"using the `write!()` family of functions instead of the `print!()` family \ + of functions, when using the latter would work" } #[derive(Copy, Clone, Debug)] diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 07674ef2763..ec47c78e495 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::hir; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax_pos::Span; -use crate::utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of, opt_def_id}; use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; +use crate::utils::{is_expn_of, match_def_path, method_chain_args, opt_def_id, span_lint_and_then, walk_ptrs_ty}; +use if_chain::if_chain; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` /// @@ -62,8 +61,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { } fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec) { - use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; + use crate::rustc::hir::*; struct FindPanicUnwrap<'a, 'tcx: 'a> { tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index bd9fa6f80be..ac80580b148 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -7,16 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::utils::paths; -use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty}; -use crate::rustc_errors::Applicability; +use crate::utils::{ + in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, + span_lint_and_then, walk_ptrs_ty, +}; +use if_chain::if_chain; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. @@ -92,17 +94,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }, // `format!("foo")` expansion contains `match () { () => [], }` - ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node { - if tup.is_empty() { - let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); - span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { - db.span_suggestion_with_applicability( - span, - "consider using .to_string()", - sugg, - Applicability::MachineApplicable, // snippet - ); - }); + ExprKind::Match(ref matchee, _, _) => { + if let ExprKind::Tup(ref tup) = matchee.node { + if tup.is_empty() { + let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); + span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { + db.span_suggestion_with_applicability( + span, + "consider using .to_string()", + sugg, + Applicability::MachineApplicable, // snippet + ); + }); + } } }, _ => (), diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index d06183cb52f..48ee383482c 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; -use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use crate::syntax::ptr::P; +use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; /// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` /// operators. @@ -78,7 +77,6 @@ declare_clippy_lint! { "possible missing comma in array" } - #[derive(Copy, Clone)] pub struct Formatting; @@ -96,8 +94,8 @@ impl EarlyLintPass for Formatting { fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { for w in block.stmts.windows(2) { match (&w[0].node, &w[1].node) { - (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) | - (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => { + (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) + | (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => { check_consecutive_ifs(cx, first, second); }, _ => (), @@ -153,9 +151,7 @@ fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” if let Some(else_snippet) = snippet_opt(cx, else_span) { - let else_pos = else_snippet - .find("else") - .expect("there must be a `else` here"); + let else_pos = else_snippet.find("else").expect("there must be a `else` here"); if else_snippet[else_pos..].contains('\n') { span_note_and_lint( @@ -175,9 +171,7 @@ fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { fn has_unary_equivalent(bin_op: ast::BinOpKind) -> bool { // &, *, - - bin_op == ast::BinOpKind::And - || bin_op == ast::BinOpKind::Mul - || bin_op == ast::BinOpKind::Sub + bin_op == ast::BinOpKind::And || bin_op == ast::BinOpKind::Mul || bin_op == ast::BinOpKind::Sub } /// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array @@ -208,7 +202,9 @@ fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) { /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. fn check_consecutive_ifs(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) { - if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() + if !differing_macro_contexts(first.span, second.span) + && !in_macro(first.span) + && unsugar_if(first).is_some() && unsugar_if(second).is_some() { // where the else would be diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index d087452d16d..57000761922 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -7,19 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use matches::matches; -use crate::rustc::hir::intravisit; use crate::rustc::hir; +use crate::rustc::hir::def::Def; +use crate::rustc::hir::intravisit; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; -use crate::rustc::hir::def::Def; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashSet; -use crate::syntax::ast; use crate::rustc_target::spec::abi::Abi; +use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; +use matches::matches; /// **What it does:** Checks for functions with too many parameters. /// @@ -31,8 +30,9 @@ use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// /// **Example:** /// ```rust -/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: -/// f32) { .. } +/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { +/// .. +/// } /// ``` declare_clippy_lint! { pub TOO_MANY_ARGUMENTS, @@ -58,7 +58,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// pub fn foo(x: *const u8) { println!("{}", unsafe { *x }); } +/// pub fn foo(x: *const u8) { +/// println!("{}", unsafe { *x }); +/// } /// ``` declare_clippy_lint! { pub NOT_UNSAFE_PTR_ARG_DEREF, @@ -73,9 +75,7 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64) -> Self { - Self { - threshold, - } + Self { threshold } } } @@ -111,8 +111,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { if !is_impl { // don't lint extern functions decls, it's not their fault either match kind { - hir::intravisit::FnKind::Method(_, &hir::MethodSig { header: hir::FnHeader { abi: Abi::Rust, .. }, .. }, _, _) | - hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => self.check_arg_number(cx, decl, span), + hir::intravisit::FnKind::Method( + _, + &hir::MethodSig { + header: hir::FnHeader { abi: Abi::Rust, .. }, + .. + }, + _, + _, + ) + | hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => { + self.check_arg_number(cx, decl, span) + }, _ => {}, } } diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 00ce58f00b0..cea759712b8 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -7,14 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; +use crate::rustc_errors::Applicability; use crate::syntax::ast::NodeId; -use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then}; +use crate::utils::{ + in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then, +}; use crate::utils::{opt_def_id, paths, resolve_node}; -use crate::rustc_errors::Applicability; /// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions. /// @@ -101,22 +102,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { } }, - ExprKind::Call(ref path, ref args) => if let ExprKind::Path(ref qpath) = path.node { - if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) { - if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) { - let a = cx.tables.expr_ty(e); - let b = cx.tables.expr_ty(&args[0]); - if same_tys(cx, a, b) { - let sugg = snippet(cx, args[0].span.source_callsite(), "").into_owned(); - let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); - span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion_with_applicability( - e.span, - &sugg_msg, - sugg, - Applicability::MachineApplicable, // snippet - ); - }); + ExprKind::Call(ref path, ref args) => { + if let ExprKind::Path(ref qpath) = path.node { + if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) { + if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) { + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + if same_tys(cx, a, b) { + let sugg = snippet(cx, args[0].span.source_callsite(), "").into_owned(); + let sugg_msg = + format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); + span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { + db.span_suggestion_with_applicability( + e.span, + &sugg_msg, + sugg, + Applicability::MachineApplicable, // snippet + ); + }); + } } } } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 3f05f21e840..aab3c8c8336 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::source_map::Span; -use crate::utils::{in_macro, snippet, span_lint, unsext, clip}; -use crate::rustc::ty; +use crate::utils::{clip, in_macro, snippet, span_lint, unsext}; /// **What it does:** Checks for identity operations, e.g. `x + 0`. /// diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index e005eb40144..8a82b8d6c49 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index f960ab5958c..758b1352471 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; -use crate::utils; -use crate::utils::higher; -use crate::utils::higher::Range; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::RangeLimits; +use crate::utils; +use crate::utils::higher; +use crate::utils::higher::Range; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. @@ -29,7 +28,7 @@ use crate::syntax::ast::RangeLimits; /// /// **Example:** /// ```rust -/// let x = [1,2,3,4]; +/// let x = [1, 2, 3, 4]; /// /// // Bad /// x[9]; @@ -108,7 +107,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let ExprKind::Index(ref array, ref index) = &expr.node { let ty = cx.tables.expr_ty(array); if let Some(range) = higher::range(cx, index) { - // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.sty { let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); @@ -153,13 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { (None, None) => return, // [..] is ok. }; - utils::span_help_and_lint( - cx, - INDEXING_SLICING, - expr.span, - "slicing may panic.", - help_msg, - ); + utils::span_help_and_lint(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg); } else { // Catchall non-range index, i.e. [n] or [n << m] if let ty::Array(..) = ty.sty { @@ -189,23 +181,21 @@ fn to_const_range<'a, 'tcx>( range: Range<'_>, array_size: u128, ) -> (Option, Option) { - let s = range - .start - .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); + let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let start = match s { Some(Some(Constant::Int(x))) => Some(x), Some(_) => None, None => Some(0), }; - let e = range - .end - .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); + let e = range.end.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); let end = match e { - Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed { - Some(x + 1) - } else { - Some(x) + Some(Some(Constant::Int(x))) => { + if range.limits == RangeLimits::Closed { + Some(x + 1) + } else { + Some(x) + } }, Some(_) => None, None => Some(array_size), diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 558d101d68e..ddf3e8f8aaa 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 9c727dccd33..3ac68096aaa 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -160,7 +159,8 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { First => is_infinite(cx, &args[0]), Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), - }).and(cap); + }) + .and(cap); } } if method.ident.name == "flat_map" && args.len() == 2 { @@ -173,14 +173,14 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { }, ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e), - ExprKind::Call(ref path, _) => if let ExprKind::Path(ref qpath) = path.node { - match_qpath(qpath, &paths::REPEAT).into() - } else { - Finite + ExprKind::Call(ref path, _) => { + if let ExprKind::Path(ref qpath) = path.node { + match_qpath(qpath, &paths::REPEAT).into() + } else { + Finite + } }, - ExprKind::Struct(..) => higher::range(cx, expr) - .map_or(false, |r| r.end.is_none()) - .into(), + ExprKind::Struct(..) => higher::range(cx, expr).map_or(false, |r| r.end.is_none()).into(), _ => Finite, } } @@ -235,10 +235,10 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { } } }, - ExprKind::Binary(op, ref l, ref r) => if op.node.is_comparison() { - return is_infinite(cx, l) - .and(is_infinite(cx, r)) - .and(MaybeInfinite); + ExprKind::Binary(op, ref l, ref r) => { + if op.node.is_comparison() { + return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite); + } }, // TODO: ExprKind::Loop + Match _ => (), } diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 3fa442a3562..256f080fdb9 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on inherent implementations use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; -use std::default::Default; use crate::syntax_pos::Span; use crate::utils::span_lint_and_then; +use std::default::Default; /// **What it does:** Checks for multiple inherent implementations of a struct /// @@ -56,7 +55,9 @@ pub struct Pass { impl Default for Pass { fn default() -> Self { - Self { impls: FxHashMap::default() } + Self { + impls: FxHashMap::default(), + } } } @@ -88,11 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let mut impl_spans = impls .iter() .filter_map(|impl_def| self.impls.get(impl_def)) - .filter_map(|(span, generics)| if generics.params.len() == 0 { - Some(span) - } else { - None - }); + .filter_map(|(span, generics)| if generics.params.len() == 0 { Some(span) } else { None }); if let Some(initial_span) = impl_spans.nth(0) { impl_spans.for_each(|additional_span| { span_lint_and_then( @@ -101,10 +98,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { *additional_span, "Multiple implementations of this structure", |db| { - db.span_note( - *initial_span, - "First implementation here", - ); + db.span_note(*initial_span, "First implementation here"); }, ) }) diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index bbd16eaeaf8..4b651dd0e1e 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! checks for `#[inline]` on trait methods without bodies +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; +use crate::rustc_errors::Applicability; use crate::syntax::ast::{Attribute, Name}; use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; -use crate::rustc_errors::Applicability; /// **What it does:** Checks for `#[inline]` on trait methods without bodies /// diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 4349b15f100..08c8012c931 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint on blocks unnecessarily using >= with a + 1 or - 1 use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; @@ -162,14 +161,20 @@ impl IntPlusOne { } fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { - span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { - db.span_suggestion_with_applicability( - block.span, - "change `>= y + 1` to `> y` as shown", - recommendation, - Applicability::MachineApplicable, // snippet - ); - }); + span_lint_and_then( + cx, + INT_PLUS_ONE, + block.span, + "Unnecessary `>= y + 1` or `x - 1 >=`", + |db| { + db.span_suggestion_with_applicability( + block.span, + "change `>= y + 1` to `> y` as shown", + recommendation, + Applicability::MachineApplicable, // snippet + ); + }, + ); } } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index fe599192053..5eba76bb45f 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; -use crate::rustc::hir::*; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; +use if_chain::if_chain; /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. /// diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 57124e5d019..ce44b7ac97c 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint when items are used after statements -use matches::matches; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; use crate::utils::{in_macro, span_lint}; +use matches::matches; /// **What it does:** Checks for items declared after some statement in a block. /// @@ -59,7 +58,8 @@ impl EarlyLintPass for ItemsAfterStatements { } // skip initial items - let stmts = item.stmts + let stmts = item + .stmts .iter() .map(|stmt| &stmt.node) .skip_while(|s| matches!(**s, StmtKind::Item(..))); diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 79ff0c84bce..6f9ae1a9367 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! lint when there is a large size difference between variants on an enum -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::*; -use crate::utils::{snippet_opt, span_lint_and_then}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::ty::layout::LayoutOf; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; +use crate::utils::{snippet_opt, span_lint_and_then}; /// **What it does:** Checks for large size differences between variants on /// `enum`s. @@ -29,8 +28,8 @@ use crate::rustc_errors::Applicability; /// **Example:** /// ```rust /// enum Test { -/// A(i32), -/// B([i32; 8000]), +/// A(i32), +/// B([i32; 8000]), /// } /// ``` declare_clippy_lint! { @@ -63,8 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let did = cx.tcx.hir.local_def_id(item.id); if let ItemKind::Enum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def() - .expect("already checked whether this is an enum"); + let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); let mut smallest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 15c21d77698..0dc21747580 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::def_id::DefId; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -32,19 +31,27 @@ use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lin /// /// **Example:** /// ```rust -/// if x.len() == 0 { .. } -/// if y.len() != 0 { .. } +/// if x.len() == 0 { +/// .. +/// } +/// if y.len() != 0 { +/// .. +/// } /// ``` /// instead use /// ```rust -/// if x.len().is_empty() { .. } -/// if !y.len().is_empty() { .. } +/// if x.len().is_empty() { +/// .. +/// } +/// if !y.len().is_empty() { +/// .. +/// } /// ``` declare_clippy_lint! { - pub LEN_ZERO, - style, - "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ - could be used instead" +pub LEN_ZERO, +style, +"checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \ + could be used instead" } /// **What it does:** Checks for items that implement `.len()` but not @@ -61,7 +68,9 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// impl X { -/// pub fn len(&self) -> usize { .. } +/// pub fn len(&self) -> usize { +/// .. +/// } /// } /// ``` declare_clippy_lint! { @@ -125,14 +134,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool { - item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + item.ident.name == name + && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + } + } else { + false } - } else { - false - } } // fill the set with current and super traits @@ -153,7 +163,9 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items .iter() .flat_map(|&i| cx.tcx.associated_items(i)) .any(|i| { - i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.ident.name == "is_empty" + i.kind == ty::AssociatedKind::Method + && i.method_has_self_argument + && i.ident.name == "is_empty" && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); @@ -173,14 +185,15 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) { fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool { - item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + item.ident.name == name + && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 + } + } else { + false } - } else { - false - } } let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) { @@ -251,7 +264,11 @@ fn check_len( span, &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), "using `is_empty` is clearer and more explicit", - format!("{}{}.is_empty()", op, snippet_with_applicability(cx, args[0].span, "_", &mut applicability)), + format!( + "{}{}.is_empty()", + op, + snippet_with_applicability(cx, args[0].span, "_", &mut applicability) + ), applicability, ); } @@ -277,16 +294,16 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool { - cx.tcx.inherent_impls(id).iter().any(|imp| { - cx.tcx - .associated_items(*imp) - .any(|item| is_is_empty(cx, &item)) - }) + cx.tcx + .inherent_impls(id) + .iter() + .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item))) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::Dynamic(ref tt, ..) => cx.tcx + ty::Dynamic(ref tt, ..) => cx + .tcx .associated_items(tt.principal().def_id()) .any(|item| is_is_empty(cx, &item)), ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 4cee4f34a63..282c4536bca 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::hir; -use crate::rustc::hir::BindingAnnotation; use crate::rustc::hir::def::Def; +use crate::rustc::hir::BindingAnnotation; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast; use crate::utils::{snippet, span_lint_and_then}; -use crate::rustc_errors::Applicability; +use if_chain::if_chain; /// **What it does:** Checks for variable declarations immediately followed by a /// conditional affectation. @@ -207,11 +206,7 @@ fn check_assign<'a, 'tcx>( } fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: ast::NodeId, expr: &'tcx hir::Expr) -> bool { - let mut v = UsedVisitor { - cx, - id, - used: false, - }; + let mut v = UsedVisitor { cx, id, used: false }; hir::intravisit::walk_expr(&mut v, expr); v.used } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 35f47c1cde4..9eb5a94f51d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern:cargo-clippy #![feature(box_syntax)] @@ -18,7 +17,6 @@ #![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![feature(macro_at_most_once_rep)] - #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] #![feature(try_from)] @@ -216,12 +214,19 @@ mod reexport { crate use crate::syntax::ast::{Name, NodeId}; } -pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore, conf: &Conf) { +pub fn register_pre_expansion_lints( + session: &rustc::session::Session, + store: &mut rustc::lint::LintStore, + conf: &Conf, +) { store.register_pre_expansion_pass(Some(session), box write::Pass); store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); - store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold: conf.single_char_binding_names_threshold, - }); + store.register_pre_expansion_pass( + Some(session), + box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold: conf.single_char_binding_names_threshold, + }, + ); store.register_pre_expansion_pass(Some(session), box attrs::CfgAttrPass); } @@ -236,38 +241,49 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { match utils::conf::lookup_conf_file() { Ok(path) => path, Err(error) => { - reg.sess.struct_err(&format!("error finding Clippy's configuration file: {}", error)).emit(); + reg.sess + .struct_err(&format!("error finding Clippy's configuration file: {}", error)) + .emit(); None - } + }, } }; - let file_name = file_name.map(|file_name| if file_name.is_relative() { - reg.sess - .local_crate_source_file - .as_ref() - .and_then(|file| std::path::Path::new(&file).parent().map(std::path::Path::to_path_buf)) - .unwrap_or_default() - .join(file_name) - } else { - file_name + let file_name = file_name.map(|file_name| { + if file_name.is_relative() { + reg.sess + .local_crate_source_file + .as_ref() + .and_then(|file| std::path::Path::new(&file).parent().map(std::path::Path::to_path_buf)) + .unwrap_or_default() + .join(file_name) + } else { + file_name + } }); let (conf, errors) = utils::conf::read(file_name.as_ref().map(|p| p.as_ref())); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { - reg.sess.struct_err(&format!("error reading Clippy's configuration file `{}`: {}", file_name.as_ref().and_then(|p| p.to_str()).unwrap_or(""), error)).emit(); + reg.sess + .struct_err(&format!( + "error reading Clippy's configuration file `{}`: {}", + file_name.as_ref().and_then(|p| p.to_str()).unwrap_or(""), + error + )) + .emit(); } conf - } + }, Err((err, span)) => { - reg.sess.struct_span_err(span, err) - .span_note(span, "Clippy will use default configuration") - .emit(); + reg.sess + .struct_span_err(span, err) + .span_note(span, "Clippy will use default configuration") + .emit(); toml::from_str("").expect("we never error on empty config files") - } + }, } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 81d37404d77..9b5da7bfc17 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::reexport::*; -use matches::matches; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::*; +use crate::rustc::hir::*; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; use crate::syntax::source_map::Span; -use crate::utils::{last_path_segment, span_lint}; use crate::syntax::symbol::keywords; +use crate::utils::{last_path_segment, span_lint}; +use matches::matches; /// **What it does:** Checks for lifetime annotations which can be removed by /// relying on lifetime elision. @@ -32,13 +31,15 @@ use crate::syntax::symbol::keywords; /// /// **Example:** /// ```rust -/// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x } +/// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { +/// x +/// } /// ``` declare_clippy_lint! { - pub NEEDLESS_LIFETIMES, - complexity, - "using explicit lifetimes for references in function arguments when elision rules \ - would allow omitting them" +pub NEEDLESS_LIFETIMES, +complexity, +"using explicit lifetimes for references in function arguments when elision rules \ + would allow omitting them" } /// **What it does:** Checks for lifetimes in generics that are never used @@ -52,7 +53,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// fn unused_lifetime<'a>(x: u8) { .. } +/// fn unused_lifetime<'a>(x: u8) { +/// .. +/// } /// ``` declare_clippy_lint! { pub EXTRA_UNUSED_LIFETIMES, @@ -152,7 +155,8 @@ fn check_fn_inner<'a, 'tcx>( cx, NEEDLESS_LIFETIMES, span, - "explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)", + "explicit lifetimes given in parameter types where they could be elided \ + (or replaced with `'_` if needed by type declaration)", ); } report_extra_lifetimes(cx, decl, generics); @@ -220,9 +224,7 @@ fn could_use_elision<'a, 'tcx: 'a>( // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - let unnamed_and_static = input_lts - .iter() - .all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static); + let unnamed_and_static = input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static); if unnamed_and_static { return false; } @@ -320,7 +322,8 @@ impl<'v, 't> RefVisitor<'v, 't> { && !last_path_segment.args.iter().any(|arg| match arg { GenericArg::Lifetime(_) => true, GenericArg::Type(_) => false, - }) { + }) + { let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { Def::TyAlias(def_id) | Def::Struct(def_id) => { @@ -354,9 +357,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { self.record(&None); }, TyKind::Path(ref path) => { - self.collect_anonymous_lifetimes(path, ty); - } + }, TyKind::Def(item, _) => { if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(item.id).node { for bound in &exist_ty.bounds { @@ -368,7 +370,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { unreachable!() } walk_ty(self, ty); - } + }, TyKind::TraitObject(ref bounds, ref lt) => { if !lt.is_elided() { self.abort = true; @@ -410,9 +412,11 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & // and check that all lifetimes are allowed match visitor.into_vec() { None => return false, - Some(lts) => for lt in lts { - if !allowed_lts.contains(<) { - return true; + Some(lts) => { + for lt in lts { + if !allowed_lts.contains(<) { + return true; + } } }, } @@ -456,7 +460,9 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { } fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) { - let hs = generics.params.iter() + let hs = generics + .params + .iter() .filter_map(|par| match par.kind { GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), _ => None, @@ -468,7 +474,12 @@ fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx walk_fn_decl(&mut checker, func); for &v in checker.map.values() { - span_lint(cx, EXTRA_UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition"); + span_lint( + cx, + EXTRA_UNUSED_LIFETIMES, + v, + "this lifetime isn't used in the function definition", + ); } } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 1efacc4ccec..5fc97d97426 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -414,9 +414,11 @@ impl LiteralDigitGrouping { parts[0].len(), parts[1].len()); if !consistent { - WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(), - cx, - lit.span); + WarningType::InconsistentDigitGrouping.display( + &digit_info.grouping_hint(), + cx, + lit.span, + ); } }) .map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0704246d450..01b526cc630 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,33 +7,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use itertools::Itertools; use crate::reexport::*; -use crate::rustc::hir::*; use crate::rustc::hir::def::Def; use crate::rustc::hir::def_id; use crate::rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::hir::*; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use crate::rustc::middle::region; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; -use crate::rustc::middle::region; +use itertools::Itertools; // use crate::rustc::middle::region::CodeExtent; +use crate::consts::{constant, Constant}; use crate::rustc::middle::expr_use_visitor::*; -use crate::rustc::middle::mem_categorization::Categorization; use crate::rustc::middle::mem_categorization::cmt_; -use crate::rustc::ty::{self, Ty}; +use crate::rustc::middle::mem_categorization::Categorization; use crate::rustc::ty::subst::Subst; -use crate::rustc_errors::Applicability; +use crate::rustc::ty::{self, Ty}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::iter::{once, Iterator}; -use std::mem; +use crate::rustc_errors::Applicability; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax_pos::BytePos; -use crate::utils::{in_macro, sugg, sext}; use crate::utils::usage::mutated_variables; -use crate::consts::{constant, Constant}; +use crate::utils::{in_macro, sext, sugg}; +use std::iter::{once, Iterator}; +use std::mem; use crate::utils::paths; use crate::utils::{ @@ -92,11 +91,15 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// // with `y` a `Vec` or slice: -/// for x in y.iter() { .. } +/// for x in y.iter() { +/// .. +/// } /// ``` /// can be rewritten to /// ```rust -/// for x in &y { .. } +/// for x in &y { +/// .. +/// } /// ``` declare_clippy_lint! { pub EXPLICIT_ITER_LOOP, @@ -114,11 +117,15 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// // with `y` a `Vec` or slice: -/// for x in y.into_iter() { .. } +/// for x in y.into_iter() { +/// .. +/// } /// ``` /// can be rewritten to /// ```rust -/// for x in y { .. } +/// for x in y { +/// .. +/// } /// ``` declare_clippy_lint! { pub EXPLICIT_INTO_ITER_LOOP, @@ -139,7 +146,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// for x in y.next() { .. } +/// for x in y.next() { +/// .. +/// } /// ``` declare_clippy_lint! { pub ITER_NEXT_LOOP, @@ -156,12 +165,16 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// for x in option { .. } +/// for x in option { +/// .. +/// } /// ``` /// /// This should be /// ```rust -/// if let Some(x) = option { .. } +/// if let Some(x) = option { +/// .. +/// } /// ``` declare_clippy_lint! { pub FOR_LOOP_OVER_OPTION, @@ -178,12 +191,16 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// for x in result { .. } +/// for x in result { +/// .. +/// } /// ``` /// /// This should be /// ```rust -/// if let Ok(x) = result { .. } +/// if let Ok(x) = result { +/// .. +/// } /// ``` declare_clippy_lint! { pub FOR_LOOP_OVER_RESULT, @@ -232,10 +249,10 @@ declare_clippy_lint! { /// vec.iter().map(|x| /* some operation returning () */).collect::>(); /// ``` declare_clippy_lint! { - pub UNUSED_COLLECT, - perf, - "`collect()`ing an iterator without using the result; this is usually better \ - written as a for loop" +pub UNUSED_COLLECT, +perf, +"`collect()`ing an iterator without using the result; this is usually better \ + written as a for loop" } /// **What it does:** Checks for functions collecting an iterator when collect @@ -273,7 +290,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// for x in 5..10-5 { .. } // oops, stray `-` +/// for x in 5..10 - 5 { +/// .. +/// } // oops, stray `-` /// ``` declare_clippy_lint! { pub REVERSE_RANGE_LOOP, @@ -328,7 +347,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// while let Some(val) = iter() { .. } +/// while let Some(val) = iter() { +/// .. +/// } /// ``` declare_clippy_lint! { pub WHILE_LET_ON_ITERATOR, @@ -346,13 +367,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// for (k, _) in &map { .. } +/// for (k, _) in &map { +/// .. +/// } /// ``` /// /// could be replaced by /// /// ```rust -/// for k in map.keys() { .. } +/// for k in map.keys() { +/// .. +/// } /// ``` declare_clippy_lint! { pub FOR_KV_MAP, @@ -370,7 +395,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// loop { ..; break; } +/// loop { +/// ..; +/// break; +/// } /// ``` declare_clippy_lint! { pub NEVER_LOOP, @@ -412,7 +440,7 @@ declare_clippy_lint! { /// ```rust /// let i = 0; /// while i > 10 { -/// println!("let me loop forever!"); +/// println!("let me loop forever!"); /// } /// ``` declare_clippy_lint! { @@ -459,8 +487,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match expr.node { ExprKind::While(_, ref block, _) | ExprKind::Loop(ref block, _, _) => { match never_loop_block(block, expr.id) { - NeverLoopResult::AlwaysBreak => - span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), + NeverLoopResult::AlwaysBreak => { + span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops") + }, NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), } }, @@ -490,8 +519,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // ensure "if let" compatible match structure match *source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { - if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() - && arms[1].pats.len() == 1 && arms[1].guard.is_none() + if arms.len() == 2 + && arms[0].pats.len() == 1 + && arms[0].guard.is_none() + && arms[1].pats.len() == 1 + && arms[1].guard.is_none() && is_simple_break_expr(&arms[1].body) { if in_external_macro(cx.sess(), expr.span) { @@ -533,12 +565,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); - if method_path.ident.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) - && lhs_constructor.ident.name == "Some" && ( - pat_args.is_empty() + if method_path.ident.name == "next" + && match_trait_method(cx, match_expr, &paths::ITERATOR) + && lhs_constructor.ident.name == "Some" + && (pat_args.is_empty() || !is_refutable(cx, &pat_args[0]) - && !is_iterator_used_after_while_let(cx, iter_expr) - && !is_nested(cx, expr, &method_args[0])) + && !is_iterator_used_after_while_let(cx, iter_expr) + && !is_nested(cx, expr, &method_args[0])) { let iterator = snippet(cx, method_args[0].span, "_"); let loop_var = if pat_args.is_empty() { @@ -594,8 +627,7 @@ enum NeverLoopResult { fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult { match *arg { - NeverLoopResult::AlwaysBreak | - NeverLoopResult::Otherwise => NeverLoopResult::Otherwise, + NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise, NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop, } } @@ -611,24 +643,22 @@ fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResu // Combine two results where both parts are called but not necessarily in order. fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult { match (left, right) { - (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => - NeverLoopResult::MayContinueMainLoop, - (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => - NeverLoopResult::AlwaysBreak, - (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => - NeverLoopResult::Otherwise, + (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => { + NeverLoopResult::MayContinueMainLoop + }, + (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak, + (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise, } } // Combine two results where only one of the part may have been executed. fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult { match (b1, b2) { - (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => - NeverLoopResult::AlwaysBreak, - (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => - NeverLoopResult::MayContinueMainLoop, - (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => - NeverLoopResult::Otherwise, + (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak, + (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => { + NeverLoopResult::MayContinueMainLoop + }, + (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise, } } @@ -655,26 +685,28 @@ fn decl_to_expr(decl: &Decl) -> Option<&Expr> { fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { match expr.node { - ExprKind::Box(ref e) | - ExprKind::Unary(_, ref e) | - ExprKind::Cast(ref e, _) | - ExprKind::Type(ref e, _) | - ExprKind::Field(ref e, _) | - ExprKind::AddrOf(_, ref e) | - ExprKind::Struct(_, _, Some(ref e)) | - ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id), + ExprKind::Box(ref e) + | ExprKind::Unary(_, ref e) + | ExprKind::Cast(ref e, _) + | ExprKind::Type(ref e, _) + | ExprKind::Field(ref e, _) + | ExprKind::AddrOf(_, ref e) + | ExprKind::Struct(_, _, Some(ref e)) + | ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id), ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => { never_loop_expr_all(&mut es.iter(), main_loop_id) }, ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), - ExprKind::Binary(_, ref e1, ref e2) | - ExprKind::Assign(ref e1, ref e2) | - ExprKind::AssignOp(_, ref e1, ref e2) | - ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), + ExprKind::Binary(_, ref e1, ref e2) + | ExprKind::Assign(ref e1, ref e2) + | ExprKind::AssignOp(_, ref e1, ref e2) + | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), ExprKind::If(ref e, ref e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); - let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); + let e3 = e3 + .as_ref() + .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); combine_seq(e1, combine_branches(e2, e3)) }, ExprKind::Loop(ref b, _, _) => { @@ -698,7 +730,8 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { }, ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id), ExprKind::Continue(d) => { - let id = d.target_id + let id = d + .target_id .expect("target id can only be missing in the presence of compilation errors"); if id == main_loop_id { NeverLoopResult::MayContinueMainLoop @@ -706,9 +739,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { NeverLoopResult::AlwaysBreak } }, - ExprKind::Break(_, _) => { - NeverLoopResult::AlwaysBreak - }, + ExprKind::Break(_, _) => NeverLoopResult::AlwaysBreak, ExprKind::Ret(ref e) => { if let Some(ref e) = *e { combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) @@ -716,26 +747,26 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { NeverLoopResult::AlwaysBreak } }, - ExprKind::Struct(_, _, None) | - ExprKind::Yield(_) | - ExprKind::Closure(_, _, _, _, _) | - ExprKind::InlineAsm(_, _, _) | - ExprKind::Path(_) | - ExprKind::Lit(_) => NeverLoopResult::Otherwise, + ExprKind::Struct(_, _, None) + | ExprKind::Yield(_) + | ExprKind::Closure(_, _, _, _, _) + | ExprKind::InlineAsm(_, _, _) + | ExprKind::Path(_) + | ExprKind::Lit(_) => NeverLoopResult::Otherwise, } } -fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { +fn never_loop_expr_seq<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { es.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_seq) } -fn never_loop_expr_all<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { +fn never_loop_expr_all<'a, T: Iterator>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult { es.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_both) } -fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, main_loop_id: NodeId) -> NeverLoopResult { +fn never_loop_expr_branch<'a, T: Iterator>(e: &mut T, main_loop_id: NodeId) -> NeverLoopResult { e.map(|e| never_loop_expr(e, main_loop_id)) .fold(NeverLoopResult::AlwaysBreak, combine_branches) } @@ -779,10 +810,7 @@ struct Offset { impl Offset { fn negative(s: String) -> Self { - Self { - value: s, - negate: true, - } + Self { value: s, negate: true } } fn positive(s: String) -> Self { @@ -842,19 +870,19 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, }, - ExprKind::Path(..) => if same_var(cx, idx, var) { - Some(Offset::positive("0".into())) - } else { - None + ExprKind::Path(..) => { + if same_var(cx, idx, var) { + Some(Offset::positive("0".into())) + } else { + None + } }, _ => None, }; - offset.map(|o| { - FixedOffsetVar { - var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), - offset: o, - } + offset.map(|o| FixedOffsetVar { + var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), + offset: o, }) } else { None @@ -890,7 +918,10 @@ fn get_indexed_assignments<'a, 'tcx>( var: ast::NodeId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { if let ExprKind::Assign(ref lhs, ref rhs) = e.node { - match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) { + match ( + get_fixed_offset_var(cx, lhs, var), + fetch_cloned_fixed_offset_var(cx, rhs, var), + ) { (Some(offset_left), Some(offset_right)) => { // Source and destination must be different if offset_left.var_name == offset_right.var_name { @@ -908,9 +939,7 @@ fn get_indexed_assignments<'a, 'tcx>( if let ExprKind::Block(ref b, _) = body.node { let Block { - ref stmts, - ref expr, - .. + ref stmts, ref expr, .. } = **b; stmts @@ -919,11 +948,7 @@ fn get_indexed_assignments<'a, 'tcx>( StmtKind::Decl(..) => None, StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)), }) - .chain( - expr.as_ref() - .into_iter() - .map(|e| Some(get_assignment(cx, &*e, var))), - ) + .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .filter_map(|op| op) .collect::>>() .unwrap_or_else(|| vec![]) @@ -973,33 +998,35 @@ fn detect_manual_memcpy<'a, 'tcx>( } }; - let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { - if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node; - if method.ident.name == "len"; - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if snippet(cx, arg.span, "??") == var_name; - then { - return if offset.negate { - format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) - } else { - String::new() - }; + let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| { + if let Some(end) = *end { + if_chain! { + if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node; + if method.ident.name == "len"; + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if snippet(cx, arg.span, "??") == var_name; + then { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) + } else { + String::new() + }; + } } - } - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, ""); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; - print_sum(&Offset::positive(end_str), &offset) - } else { - "..".into() + print_sum(&Offset::positive(end_str), &offset) + } else { + "..".into() + } }; // The only statements in the for loops can be indexed assignments from @@ -1020,7 +1047,10 @@ fn detect_manual_memcpy<'a, 'tcx>( format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) }; - format!("{}.clone_from_slice(&{}[{}..{}])", dst, src_var.var_name, src_offset, src_limit) + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var.var_name, src_offset, src_limit + ) }) .join("\n "); @@ -1166,7 +1196,10 @@ fn check_for_loop_range<'a, 'tcx>( "consider using an iterator".to_string(), vec![ (pat.span, format!("({}, )", ident.name)), - (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2)), + ( + arg.span, + format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2), + ), ], ); }, @@ -1182,7 +1215,10 @@ fn check_for_loop_range<'a, 'tcx>( cx, NEEDLESS_RANGE_LOOP, expr.span, - &format!("the loop variable `{}` is only used to index `{}`.", ident.name, indexed), + &format!( + "the loop variable `{}` is only used to index `{}`.", + ident.name, indexed + ), |db| { multispan_sugg( db, @@ -1213,12 +1249,7 @@ fn is_len_call(expr: &Expr, var: Name) -> bool { false } -fn is_end_eq_array_len( - cx: &LateContext<'_, '_>, - end: &Expr, - limits: ast::RangeLimits, - indexed_ty: Ty<'_>, -) -> bool { +fn is_end_eq_array_len(cx: &LateContext<'_, '_>, end: &Expr, limits: ast::RangeLimits, indexed_ty: Ty<'_>) -> bool { if_chain! { if let ExprKind::Lit(ref lit) = end.node; if let ast::LitKind::Int(end_int, _) = lit.node; @@ -1252,14 +1283,14 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx // smaller value. let ty = cx.tables.expr_ty(start); let (sup, eq) = match (start_idx, end_idx) { - ( - Constant::Int(start_idx), - Constant::Int(end_idx), - ) => (match ty.sty { - ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), - ty::Uint(_) => start_idx > end_idx, - _ => false, - }, start_idx == end_idx), + (Constant::Int(start_idx), Constant::Int(end_idx)) => ( + match ty.sty { + ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), + ty::Uint(_) => start_idx > end_idx, + _ => false, + }, + start_idx == end_idx, + ), _ => (false, false), }; @@ -1310,11 +1341,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) { let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); - let muta = if method_name == "iter_mut" { - "mut " - } else { - "" - }; + let muta = if method_name == "iter_mut" { "mut " } else { "" }; span_lint_and_sugg( cx, EXPLICIT_ITER_LOOP, @@ -1439,15 +1466,12 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id) + let parent_scope = map + .get_enclosing_scope(expr.id) .and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { if let Node::Block(block) = map.get(parent_id) { - for (id, _) in visitor - .states - .iter() - .filter(|&(_, v)| *v == VarState::IncrOnce) - { + for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { cx, end_expr: expr, @@ -1586,10 +1610,7 @@ fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr, body: &Expr) .. }) = higher::range(cx, arg) { - let mut_ids = vec![ - check_for_mutability(cx, start), - check_for_mutability(cx, end), - ]; + let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; if mut_ids[0].is_some() || mut_ids[1].is_some() { let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids); mut_warn_with_span(cx, span_low); @@ -1631,7 +1652,11 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option, body: &Expr, bound_ids: &[Option]) -> (Option, Option) { +fn check_for_mutation( + cx: &LateContext<'_, '_>, + body: &Expr, + bound_ids: &[Option], +) -> (Option, Option) { let mut delegate = MutatePairDelegate { node_id_low: bound_ids[0], node_id_high: bound_ids[1], @@ -1821,8 +1846,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } let old = self.prefer_mutable; match expr.node { - ExprKind::AssignOp(_, ref lhs, ref rhs) | - ExprKind::Assign(ref lhs, ref rhs) => { + ExprKind::AssignOp(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs) => { self.prefer_mutable = true; self.visit_expr(lhs); self.prefer_mutable = false; @@ -1910,7 +1934,6 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> { } } - /// Return true if the type of expr is one that provides `IntoIterator` impls /// for `&T` and `&mut T`, such as `Vec`. #[rustfmt::skip] @@ -1998,9 +2021,9 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'a, 'tcx>, // context reference states: FxHashMap, // incremented variables - depth: u32, // depth of conditional expressions + depth: u32, // depth of conditional expressions done: bool, } @@ -2244,8 +2267,10 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => if match_var(path, self.iterator) { - self.nesting = RuledOut; + ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => { + if match_var(path, self.iterator) { + self.nesting = RuledOut; + } }, _ => walk_expr(self, expr), } @@ -2299,7 +2324,7 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e let no_cond_variable_mutated = if let Some(used_mutably) = mutated_variables(expr, cx) { used_in_condition.is_disjoint(&used_mutably) } else { - return + return; }; let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v); if no_cond_variable_mutated && !mutable_static_in_cond { @@ -2307,7 +2332,8 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e cx, WHILE_IMMUTABLE_CONDITION, cond.span, - "Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.", + "Variable in the condition are not mutated in the loop body. \ + This either leads to an infinite or to a never running loop.", ); } } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4424143160c..4ea02db1465 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -15,7 +14,9 @@ use crate::rustc_errors::Applicability; use crate::syntax::ast::Ident; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; +use crate::utils::{ + in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, +}; use if_chain::if_chain; #[derive(Clone)] @@ -72,15 +73,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let closure_expr = remove_blocks(&closure_body.value); then { match closure_body.arguments[0].pat.node { - hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) = inner.node { + hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding( + hir::BindingAnnotation::Unannotated, _, name, None + ) = inner.node { lint(cx, e.span, args[0].span, name, closure_expr); }, - hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { - hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) if !cx.tables.expr_ty(inner).is_box() => lint(cx, e.span, args[0].span, name, inner), - hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { - lint(cx, e.span, args[0].span, name, &obj[0]); + hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => { + match closure_expr.node { + hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => { + if !cx.tables.expr_ty(inner).is_box() => { + lint(cx, e.span, args[0].span, name, inner); + } + }, + hir::ExprKind::MethodCall(ref method, _, ref obj) => { + if method.ident.as_str() == "clone" + && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { + lint(cx, e.span, args[0].span, name, &obj[0]); + } + }, + _ => {}, } - _ => {}, }, _ => {}, } @@ -99,7 +111,10 @@ fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: replace, "You are using an explicit closure for cloning elements", "Consider calling the dedicated `cloned` method", - format!("{}.cloned()", snippet_with_applicability(cx, root, "..", &mut applicability)), + format!( + "{}.cloned()", + snippet_with_applicability(cx, root, "..", &mut applicability) + ), applicability, ) } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 373cf1fbf38..8fb41b25c73 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; -use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use crate::utils::paths; +use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; +use if_chain::if_chain; #[derive(Clone)] pub struct Pass; @@ -87,7 +86,6 @@ declare_clippy_lint! { "using `result.map(f)`, where f is a function or closure that returns ()" } - impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN) @@ -127,8 +125,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> } match expr.node { - hir::ExprKind::Call(_, _) | - hir::ExprKind::MethodCall(_, _, _) => { + hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => { // Calls can't be reduced any more Some(expr.span) }, @@ -155,7 +152,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> // // We do not attempt to build a suggestion for those right now. None - } + }, } }, _ => None, @@ -189,15 +186,14 @@ fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr) -> String { match &var_arg.node { hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")), - _ => "_".to_string() + _ => "_".to_string(), } } fn suggestion_msg(function_type: &str, map_type: &str) -> String { format!( "called `map(f)` on an {0} value where `f` is a unit {1}", - map_type, - function_type + map_type, function_type ) } @@ -205,39 +201,39 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr let var_arg = &map_args[0]; let fn_arg = &map_args[1]; - let (map_type, variant, lint) = - if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { - ("Option", "Some", OPTION_MAP_UNIT_FN) - } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) { - ("Result", "Ok", RESULT_MAP_UNIT_FN) - } else { - return - }; + let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + ("Option", "Some", OPTION_MAP_UNIT_FN) + } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) { + ("Result", "Ok", RESULT_MAP_UNIT_FN) + } else { + return; + }; if is_unit_function(cx, fn_arg) { let msg = suggestion_msg("function", map_type); - let suggestion = format!("if let {0}({1}) = {2} {{ {3}(...) }}", - variant, - let_binding_name(cx, var_arg), - snippet(cx, var_arg.span, "_"), - snippet(cx, fn_arg.span, "_")); + let suggestion = format!( + "if let {0}({1}) = {2} {{ {3}(...) }}", + variant, + let_binding_name(cx, var_arg), + snippet(cx, var_arg.span, "_"), + snippet(cx, fn_arg.span, "_") + ); span_lint_and_then(cx, lint, expr.span, &msg, |db| { - db.span_suggestion_with_applicability(stmt.span, - "try this", - suggestion, - Applicability::Unspecified); + db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); span_lint_and_then(cx, lint, expr.span, &msg, |db| { if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) { - let suggestion = format!("if let {0}({1}) = {2} {{ {3} }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, reduced_expr_span, "_")); + let suggestion = format!( + "if let {0}({1}) = {2} {{ {3} }}", + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_"), + snippet(cx, reduced_expr_span, "_") + ); db.span_suggestion_with_applicability( stmt.span, "try this", @@ -245,16 +241,13 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr Applicability::MachineApplicable, // snippet ); } else { - let suggestion = format!("if let {0}({1}) = {2} {{ ... }}", - variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_")); - db.span_suggestion_with_applicability( - stmt.span, - "try this", - suggestion, - Applicability::Unspecified, + let suggestion = format!( + "if let {0}({1}) = {2} {{ ... }}", + variant, + snippet(cx, binding.pat.span, "_"), + snippet(cx, var_arg.span, "_") ); + db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified); } }); } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 583cdee843f..1821a35cf59 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -7,23 +7,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::consts::{constant, Constant}; use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty::{self, Ty}; -use std::cmp::Ordering; -use std::collections::Bound; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type, - multispan_sugg, remove_blocks, snippet, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, - span_note_and_lint, walk_ptrs_ty}; use crate::utils::sugg::Sugg; -use crate::consts::{constant, Constant}; -use crate::rustc_errors::Applicability; +use crate::utils::{ + expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, + snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, +}; +use if_chain::if_chain; +use std::cmp::Ordering; +use std::collections::Bound; /// **What it does:** Checks for matches with a single arm where an `if let` /// will usually suffice. @@ -36,14 +36,14 @@ use crate::rustc_errors::Applicability; /// ```rust /// match x { /// Some(ref foo) => bar(foo), -/// _ => () +/// _ => (), /// } /// ``` declare_clippy_lint! { - pub SINGLE_MATCH, - style, - "a match statement with a single nontrivial arm (i.e. where the other arm \ - is `_ => {}`) instead of `if let`" +pub SINGLE_MATCH, +style, +"a match statement with a single nontrivial arm (i.e. where the other arm \ + is `_ => {}`) instead of `if let`" } /// **What it does:** Checks for matches with a two arms where an `if let` will @@ -61,10 +61,10 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub SINGLE_MATCH_ELSE, - pedantic, - "a match statement with a two arms where the second arm's pattern is a wildcard \ - instead of `if let`" +pub SINGLE_MATCH_ELSE, +pedantic, +"a match statement with a two arms where the second arm's pattern is a wildcard \ + instead of `if let`" } /// **What it does:** Checks for matches where all arms match a reference, @@ -131,8 +131,8 @@ declare_clippy_lint! { /// ```rust /// let x = 5; /// match x { -/// 1 ... 10 => println!("1 ... 10"), -/// 5 ... 15 => println!("5 ... 15"), +/// 1...10 => println!("1 ... 10"), +/// 5...15 => println!("5 ... 15"), /// _ => (), /// } /// ``` @@ -152,7 +152,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let x : Result(i32, &str) = Ok(3); +/// let x: Result(i32, &str) = Ok(3); /// match x { /// Ok(_) => println!("ok"), /// Err(_) => panic!("err"), @@ -175,8 +175,8 @@ declare_clippy_lint! { /// ```rust /// let x: Option<()> = None; /// let r: Option<&()> = match x { -/// None => None, -/// Some(ref v) => Some(v), +/// None => None, +/// Some(ref v) => Some(v), /// }; /// ``` declare_clippy_lint! { @@ -243,19 +243,29 @@ fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & } } -fn check_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { +fn check_single_match_single_pattern( + cx: &LateContext<'_, '_>, + ex: &Expr, + arms: &[Arm], + expr: &Expr, + els: Option<&Expr>, +) { if is_wild(&arms[1].pats[0]) { report_single_match_single_pattern(cx, ex, arms, expr, els); } } -fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) { - let lint = if els.is_some() { - SINGLE_MATCH_ELSE - } else { - SINGLE_MATCH - }; - let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, ".."))); +fn report_single_match_single_pattern( + cx: &LateContext<'_, '_>, + ex: &Expr, + arms: &[Arm], + expr: &Expr, + els: Option<&Expr>, +) { + let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; + let els_str = els.map_or(String::new(), |els| { + format!(" else {}", expr_block(cx, els, None, "..")) + }); span_lint_and_sugg( cx, lint, @@ -274,7 +284,14 @@ fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: ); } -fn check_single_match_opt_like(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty<'_>, els: Option<&Expr>) { +fn check_single_match_opt_like( + cx: &LateContext<'_, '_>, + ex: &Expr, + arms: &[Arm], + expr: &Expr, + ty: Ty<'_>, + els: Option<&Expr>, +) { // list of candidate Enums we know will never get any more members let candidates = &[ (&paths::COW, "Borrowed"), @@ -466,9 +483,12 @@ fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: } fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) { - if arms.len() == 2 && - arms[0].pats.len() == 1 && arms[0].guard.is_none() && - arms[1].pats.len() == 1 && arms[1].guard.is_none() { + if arms.len() == 2 + && arms[0].pats.len() == 1 + && arms[0].guard.is_none() + && arms[1].pats.len() == 1 + && arms[1].guard.is_none() + { let arm_ref: Option = if is_none_arm(&arms[0]) { is_ref_some_arm(&arms[1]) } else if is_none_arm(&arms[1]) { @@ -477,7 +497,11 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & None }; if let Some(rb) = arm_ref { - let suggestion = if rb == BindingAnnotation::Ref { "as_ref" } else { "as_mut" }; + let suggestion = if rb == BindingAnnotation::Ref { + "as_ref" + } else { + "as_mut" + }; let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, @@ -485,7 +509,11 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & expr.span, &format!("use {}() instead", suggestion), "try this", - format!("{}.{}()", snippet_with_applicability(cx, ex.span, "_", &mut applicability), suggestion), + format!( + "{}.{}()", + snippet_with_applicability(cx, ex.span, "_", &mut applicability), + suggestion + ), applicability, ) } @@ -493,22 +521,18 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: & } /// Get all arms that are unbounded `PatRange`s. -fn all_ranges<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - arms: &'tcx [Arm], -) -> Vec> { +fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm]) -> Vec> { arms.iter() .flat_map(|arm| { if let Arm { - ref pats, - guard: None, - .. + ref pats, guard: None, .. } = *arm { pats.iter() } else { [].iter() - }.filter_map(|pat| { + } + .filter_map(|pat| { if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node { let lhs = constant(cx, cx.tables, lhs)?.0; let rhs = constant(cx, cx.tables, rhs)?.0; @@ -516,12 +540,18 @@ fn all_ranges<'a, 'tcx>( RangeEnd::Included => Bound::Included(rhs), RangeEnd::Excluded => Bound::Excluded(rhs), }; - return Some(SpannedRange { span: pat.span, node: (lhs, rhs) }); + return Some(SpannedRange { + span: pat.span, + node: (lhs, rhs), + }); } if let PatKind::Lit(ref value) = pat.node { let value = constant(cx, cx.tables, value)?.0; - return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); + return Some(SpannedRange { + span: pat.span, + node: (value.clone(), Bound::Included(value)), + }); } None @@ -545,24 +575,15 @@ fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { - ( - Constant::Int(start), - Bound::Included(Constant::Int(end)), - ) => Some(SpannedRange { + (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange { span: range.span, node: (start, Bound::Included(end)), }), - ( - Constant::Int(start), - Bound::Excluded(Constant::Int(end)), - ) => Some(SpannedRange { + (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange { span: range.span, node: (start, Bound::Excluded(end)), }), - ( - Constant::Int(start), - Bound::Unbounded, - ) => Some(SpannedRange { + (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange { span: range.span, node: (start, Bound::Unbounded), }), @@ -608,7 +629,8 @@ fn is_ref_some_arm(arm: &Arm) -> Option { } fn has_only_ref_pats(arms: &[Arm]) -> bool { - let mapped = arms.iter() + let mapped = arms + .iter() .flat_map(|a| &a.pats) .map(|p| { match p.node { @@ -682,8 +704,10 @@ where for (a, b) in values.iter().zip(values.iter().skip(1)) { match (a, b) { - (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node { - return Some((ra, rb)); + (&Kind::Start(_, ra), &Kind::End(_, rb)) => { + if ra.node != rb.node { + return Some((ra, rb)); + } }, (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (), _ => return Some((a.range(), b.range())), diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index c53c276991d..5c58c990dc7 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index accd7bc220c..066eeb70fde 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::{Expr, ExprKind}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index f0310b87f69..91586ae152d 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index dc939ad0815..9e56213931a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Ty, TyKind, Predicate}; +use crate::rustc::ty::{self, Predicate, Ty, TyKind}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast; @@ -23,7 +22,7 @@ use crate::utils::{ get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, - snippet_with_macro_callsite, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then, + snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; use if_chain::if_chain; @@ -95,7 +94,9 @@ declare_clippy_lint! { /// ```rust /// struct X; /// impl X { -/// fn add(&self, other: &X) -> X { .. } +/// fn add(&self, other: &X) -> X { +/// .. +/// } /// } /// ``` declare_clippy_lint! { @@ -124,14 +125,16 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// impl X { -/// fn as_str(self) -> &str { .. } +/// fn as_str(self) -> &str { +/// .. +/// } /// } /// ``` declare_clippy_lint! { - pub WRONG_SELF_CONVENTION, - style, - "defining a method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" +pub WRONG_SELF_CONVENTION, +style, +"defining a method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" } /// **What it does:** This is the same as @@ -146,14 +149,16 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// impl X { -/// pub fn as_str(self) -> &str { .. } +/// pub fn as_str(self) -> &str { +/// .. +/// } /// } /// ``` declare_clippy_lint! { - pub WRONG_PUB_SELF_CONVENTION, - restriction, - "defining a public method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" +pub WRONG_PUB_SELF_CONVENTION, +restriction, +"defining a public method named with an established prefix (like \"into_\") that takes \ + `self` with the wrong convention" } /// **What it does:** Checks for usage of `ok().expect(..)`. @@ -168,10 +173,10 @@ declare_clippy_lint! { /// x.ok().expect("why did I do this again?") /// ``` declare_clippy_lint! { - pub OK_EXPECT, - style, - "using `ok().expect()`, which gives worse error messages than \ - calling `expect` directly on the Result" +pub OK_EXPECT, +style, +"using `ok().expect()`, which gives worse error messages than \ + calling `expect` directly on the Result" } /// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`. @@ -186,10 +191,10 @@ declare_clippy_lint! { /// x.map(|a| a + 1).unwrap_or(0) /// ``` declare_clippy_lint! { - pub OPTION_MAP_UNWRAP_OR, - pedantic, - "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ - `map_or(a, f)`" +pub OPTION_MAP_UNWRAP_OR, +pedantic, +"using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \ + `map_or(a, f)`" } /// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`. @@ -204,10 +209,10 @@ declare_clippy_lint! { /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` declare_clippy_lint! { - pub OPTION_MAP_UNWRAP_OR_ELSE, - pedantic, - "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`" +pub OPTION_MAP_UNWRAP_OR_ELSE, +pedantic, +"using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `map_or_else(g, f)`" } /// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. @@ -222,10 +227,10 @@ declare_clippy_lint! { /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` declare_clippy_lint! { - pub RESULT_MAP_UNWRAP_OR_ELSE, - pedantic, - "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `.ok().map_or_else(g, f)`" +pub RESULT_MAP_UNWRAP_OR_ELSE, +pedantic, +"using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ + `.ok().map_or_else(g, f)`" } /// **What it does:** Checks for usage of `_.map_or(None, _)`. @@ -240,10 +245,10 @@ declare_clippy_lint! { /// opt.map_or(None, |a| a + 1) /// ``` declare_clippy_lint! { - pub OPTION_MAP_OR_NONE, - style, - "using `Option.map_or(None, f)`, which is more succinctly expressed as \ - `and_then(f)`" +pub OPTION_MAP_OR_NONE, +style, +"using `Option.map_or(None, f)`, which is more succinctly expressed as \ + `and_then(f)`" } /// **What it does:** Checks for usage of `_.filter(_).next()`. @@ -275,10 +280,10 @@ declare_clippy_lint! { /// iter.map(|x| x.iter()).flatten() /// ``` declare_clippy_lint! { - pub MAP_FLATTEN, - pedantic, - "using combinations of `flatten` and `map` which can usually be written as a \ - single method call" +pub MAP_FLATTEN, +pedantic, +"using combinations of `flatten` and `map` which can usually be written as a \ + single method call" } /// **What it does:** Checks for usage of `_.filter(_).map(_)`, @@ -295,10 +300,10 @@ declare_clippy_lint! { /// iter.filter(|x| x == 0).map(|x| x * 2) /// ``` declare_clippy_lint! { - pub FILTER_MAP, - pedantic, - "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ - usually be written as a single method call" +pub FILTER_MAP, +pedantic, +"using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ + usually be written as a single method call" } /// **What it does:** Checks for an iterator search (such as `find()`, @@ -314,10 +319,10 @@ declare_clippy_lint! { /// iter.find(|x| x == 0).is_some() /// ``` declare_clippy_lint! { - pub SEARCH_IS_SOME, - complexity, - "using an iterator search followed by `is_some()`, which is more succinctly \ - expressed as a call to `any()`" +pub SEARCH_IS_SOME, +complexity, +"using an iterator search followed by `is_some()`, which is more succinctly \ + expressed as a call to `any()`" } /// **What it does:** Checks for usage of `.chars().next()` on a `str` to check @@ -437,10 +442,10 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// fn main() { -/// let x = vec![1]; -/// let y = &&x; -/// let z = y.clone(); -/// println!("{:p} {:p}",*y, z); // prints out the same pointer +/// let x = vec![1]; +/// let y = &&x; +/// let z = y.clone(); +/// println!("{:p} {:p}", *y, z); // prints out the same pointer /// } /// ``` declare_clippy_lint! { @@ -480,10 +485,10 @@ declare_clippy_lint! { /// **Example:** /// `_.split("x")` could be `_.split('x')` declare_clippy_lint! { - pub SINGLE_CHAR_PATTERN, - perf, - "using a single-character str where a char could be used, e.g. \ - `_.split(\"x\")`" +pub SINGLE_CHAR_PATTERN, +perf, +"using a single-character str where a char could be used, e.g. \ + `_.split(\"x\")`" } /// **What it does:** Checks for getting the inner pointer of a temporary @@ -635,13 +640,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let s = [1,2,3,4,5]; -/// let s2 : Vec = s[..].iter().cloned().collect(); +/// let s = [1, 2, 3, 4, 5]; +/// let s2: Vec = s[..].iter().cloned().collect(); /// ``` /// The better use would be: /// ```rust -/// let s = [1,2,3,4,5]; -/// let s2 : Vec = s.to_vec(); +/// let s = [1, 2, 3, 4, 5]; +/// let s2: Vec = s.to_vec(); /// ``` declare_clippy_lint! { pub ITER_CLONED_COLLECT, @@ -676,12 +681,12 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let x: &[i32] = &[1,2,3,4,5]; +/// let x: &[i32] = &[1, 2, 3, 4, 5]; /// do_stuff(x.as_ref()); /// ``` /// The correct use would be: /// ```rust -/// let x: &[i32] = &[1,2,3,4,5]; +/// let x: &[i32] = &[1, 2, 3, 4, 5]; /// do_stuff(x); /// ``` declare_clippy_lint! { @@ -690,7 +695,6 @@ declare_clippy_lint! { "using `as_ref` where the types before and after the call are the same" } - /// **What it does:** Checks for using `fold` when a more succinct alternative exists. /// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, /// `sum` or `product`. @@ -714,7 +718,6 @@ declare_clippy_lint! { "using `fold` when a more succinct alternative exists" } - /// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`. /// More specifically it checks if the closure provided is only performing one of the /// filter or map operations and suggests the appropriate option. @@ -870,12 +873,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ["as_mut", ..] => lint_asref(cx, expr, "as_mut", arg_lists[0]), ["fold", ..] => lint_unnecessary_fold(cx, expr, arg_lists[0]), ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), - _ => {} + _ => {}, } match expr.node { hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { - lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); @@ -886,9 +888,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match self_ty.sty { - ty::Ref(_, ty, _) if ty.sty == ty::Str => for &(method, pos) in &PATTERN_METHODS { - if method_call.ident.name == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); + ty::Ref(_, ty, _) if ty.sty == ty::Str => { + for &(method, pos) in &PATTERN_METHODS { + if method_call.ident.name == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); + } } }, ty::Ref(..) if method_call.ident.name == "into_iter" => { @@ -897,7 +901,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => (), } }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { + hir::ExprKind::Binary(op, ref lhs, ref rhs) + if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => + { let mut info = BinaryExprInfo { expr, chain: lhs, @@ -905,7 +911,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { eq: op.node == hir::BinOpKind::Eq, }; lint_binary_expr_with_method_call(cx, &mut info); - }, + } _ => (), } } @@ -963,7 +969,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { .join(" or "))); } - // Only check the first convention to match (CONVENTIONS should be listed from most to least specific) + // Only check the first convention to match (CONVENTIONS should be listed from most to least + // specific) break; } } @@ -975,12 +982,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // walk the return type and check for Self (this does not check associated types) for inner_type in ret_ty.walk() { - if same_tys(cx, ty, inner_type) { return; } + if same_tys(cx, ty, inner_type) { + return; + } } // if return type is impl trait, check the associated types if let TyKind::Opaque(def_id, _) = ret_ty.sty { - // one of the associated types must be Self for predicate in &cx.tcx.predicates_of(def_id).predicates { match predicate { @@ -990,7 +998,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let associated_type_is_self_type = same_tys(cx, ty, associated_type); // if the associated type is self, early return and do not trigger lint - if associated_type_is_self_type { return; } + if associated_type_is_self_type { + return; + } }, (_, _) => {}, } @@ -998,10 +1008,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if name == "new" && !same_tys(cx, ret_ty, ty) { - span_lint(cx, - NEW_RET_NO_SELF, - implitem.span, - "methods called `new` usually return `Self`"); + span_lint( + cx, + NEW_RET_NO_SELF, + implitem.span, + "methods called `new` usually return `Self`", + ); } } } @@ -1043,7 +1055,10 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa span, &format!("use of `{}` followed by a call to `{}`", name, path), "try this", - format!("{}.unwrap_or_default()", snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)), + format!( + "{}.unwrap_or_default()", + snippet_with_applicability(cx, self_expr.span, "_", &mut applicability) + ), applicability, ); return true; @@ -1123,12 +1138,28 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa hir::ExprKind::Call(ref fun, ref or_args) => { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { - check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span); + check_general_case( + cx, + name, + method_span, + fun.span, + &args[0], + &args[1], + or_has_args, + expr.span, + ); } }, - hir::ExprKind::MethodCall(_, span, ref or_args) => { - check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span) - }, + hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case( + cx, + name, + method_span, + span, + &args[0], + &args[1], + !or_args.is_empty(), + expr.span, + ), _ => {}, } } @@ -1137,12 +1168,13 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { - let arg = match &arg.node { - hir::ExprKind::AddrOf(_, expr)=> expr, + let arg = match &arg.node { + hir::ExprKind::AddrOf(_, expr) => expr, hir::ExprKind::MethodCall(method_name, _, args) - if method_name.ident.name == "as_str" || - method_name.ident.name == "as_ref" - => &args[0], + if method_name.ident.name == "as_str" || method_name.ident.name == "as_ref" => + { + &args[0] + }, _ => arg, }; @@ -1165,7 +1197,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { - return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability).into_owned(); + return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability) + .into_owned(); } } }; @@ -1212,7 +1245,11 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: return; } - let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" }; + let closure = if match_type(cx, self_type, &paths::OPTION) { + "||" + } else { + "|_|" + }; let span_replace_word = method_span.with_hi(span.hi()); if let Some(format_args) = extract_format_args(arg) { @@ -1272,28 +1309,30 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp expr.span, "using `clone` on a double-reference; \ this will copy the reference instead of cloning the inner type", - |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - let mut ty = innermost; - let mut n = 0; - while let ty::Ref(_, inner, _) = ty.sty { - ty = inner; - n += 1; + |db| { + if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { + let mut ty = innermost; + let mut n = 0; + while let ty::Ref(_, inner, _) = ty.sty { + ty = inner; + n += 1; + } + let refs: String = iter::repeat('&').take(n + 1).collect(); + let derefs: String = iter::repeat('*').take(n).collect(); + let explicit = format!("{}{}::clone({})", refs, ty, snip); + db.span_suggestion_with_applicability( + expr.span, + "try dereferencing it", + format!("{}({}{}).clone()", refs, derefs, snip.deref()), + Applicability::MaybeIncorrect, + ); + db.span_suggestion_with_applicability( + expr.span, + "or try being explicit about what type to clone", + explicit, + Applicability::MaybeIncorrect, + ); } - let refs: String = iter::repeat('&').take(n + 1).collect(); - let derefs: String = iter::repeat('*').take(n).collect(); - let explicit = format!("{}{}::clone({})", refs, ty, snip); - db.span_suggestion_with_applicability( - expr.span, - "try dereferencing it", - format!("{}({}{}).clone()", refs, derefs, snip.deref()), - Applicability::MaybeIncorrect, - ); - db.span_suggestion_with_applicability( - expr.span, - "or try being explicit about what type to clone", - explicit, - Applicability::MaybeIncorrect, - ); }, ); return; // don't report clone_on_copy @@ -1312,7 +1351,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp // (*x).func() is useless, x.clone().func() can work in case func borrows mutably hir::ExprKind::MethodCall(..) => return, _ => {}, - } + }, hir::Node::Stmt(stmt) => { if let hir::StmtKind::Decl(ref decl, _) = stmt.node { if let hir::DeclKind::Local(ref loc) = decl.node { @@ -1334,12 +1373,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp } span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { if let Some((text, snip)) = snip { - db.span_suggestion_with_applicability( - expr.span, - text, - snip, - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability(expr.span, text, snip, Applicability::Unspecified); } }); } @@ -1365,13 +1399,17 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir:: expr.span, "using '.clone()' on a ref-counted pointer", "try this", - format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")), + format!( + "{}::<{}>::clone(&{})", + caller_type, + subst.type_at(0), + snippet(cx, arg.span, "_") + ), Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak ); } } - fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) { let arg = &args[1]; if let Some(arglists) = method_chain_args(arg, &["chars"]) { @@ -1451,8 +1489,8 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: fold_args: &[hir::Expr], op: hir::BinOpKind, replacement_method_name: &str, - replacement_has_args: bool) { - + replacement_has_args: bool, + ) { if_chain! { // Extract the body of the closure passed to fold if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node; @@ -1509,29 +1547,21 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: return; } - assert!(fold_args.len() == 3, - "Expected fold_args to have three entries - the receiver, the initial value and the closure"); + assert!( + fold_args.len() == 3, + "Expected fold_args to have three entries - the receiver, the initial value and the closure" + ); // Check if the first argument to .fold is a suitable literal match fold_args[1].node { - hir::ExprKind::Lit(ref lit) => { - match lit.node { - ast::LitKind::Bool(false) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Or, "any", true - ), - ast::LitKind::Bool(true) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::And, "all", true - ), - ast::LitKind::Int(0, _) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Add, "sum", false - ), - ast::LitKind::Int(1, _) => check_fold_with_op( - cx, fold_args, hir::BinOpKind::Mul, "product", false - ), - _ => return - } - } - _ => return + hir::ExprKind::Lit(ref lit) => match lit.node { + ast::LitKind::Bool(false) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Or, "any", true), + ast::LitKind::Bool(true) => check_fold_with_op(cx, fold_args, hir::BinOpKind::And, "all", true), + ast::LitKind::Int(0, _) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Add, "sum", false), + ast::LitKind::Int(1, _) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Mul, "product", false), + _ => return, + }, + _ => return, }; } @@ -1553,8 +1583,7 @@ fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::E expr.span, &format!( "called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable", - mut_str, - caller_type + mut_str, caller_type ), ); } @@ -1590,15 +1619,20 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: }; let mut_str = if is_mut { "_mut" } else { "" }; - let borrow_str = if !needs_ref { "" } else if is_mut { "&mut " } else { "&" }; + let borrow_str = if !needs_ref { + "" + } else if is_mut { + "&mut " + } else { + "&" + }; span_lint_and_sugg( cx, GET_UNWRAP, expr.span, &format!( "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", - mut_str, - caller_type + mut_str, caller_type ), "try this", format!( @@ -1645,10 +1679,12 @@ fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Op match ty.sty { ty::Slice(_) => sugg::Sugg::hir_opt(cx, expr), ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::Ref(_, inner, _) => if may_slice(cx, inner) { - sugg::Sugg::hir_opt(cx, expr) - } else { - None + ty::Ref(_, inner, _) => { + if may_slice(cx, inner) { + sugg::Sugg::hir_opt(cx, expr) + } else { + None + } }, _ => None, } @@ -1676,8 +1712,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::E "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ using expect() to provide a better panic \ message", - kind, - none_value + kind, none_value ), ); } @@ -1711,11 +1746,7 @@ fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hi // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { - "None" - } else { - "a" - }; + let arg = if unwrap_snippet == "None" { "None" } else { "a" }; let suggest = if unwrap_snippet == "None" { "and_then(f)" } else { @@ -1724,8 +1755,7 @@ fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hi let msg = &format!( "called `map(f).unwrap_or({})` on an Option value. \ This can be done more directly by calling `{}` instead", - arg, - suggest + arg, suggest ); // lint, with note if neither arg is > 1 line and both map() and // unwrap_or() have the same span @@ -1739,9 +1769,7 @@ fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hi }; let note = format!( "replace `map({}).unwrap_or({})` with `{}`", - map_snippet, - unwrap_snippet, - suggest + map_snippet, unwrap_snippet, suggest ); span_note_and_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, ¬e); } else if same_span && multiline { @@ -1751,11 +1779,7 @@ fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hi } /// lint use of `map().flatten()` for `Iterators` -fn lint_map_flatten<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, - map_args: &'tcx [hir::Expr], -) { +fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr]) { // lint if caller of `.map().flatten()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `map(..).flatten()` on an `Iterator`. \ @@ -1971,7 +1995,10 @@ fn lint_search_is_some<'a, 'tcx>( expr.span, &msg, expr.span, - &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet), + &format!( + "replace `{0}({1}).is_some()` with `any({1})`", + search_method, search_snippet + ), ); } else { span_lint(cx, SEARCH_IS_SOME, expr.span, &msg); @@ -1998,7 +2025,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut Binary return; } } - } + }; } lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); @@ -2163,7 +2190,10 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re } } -fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Option<(&'static Lint, &'static str, &'static str)> { +fn ty_has_iter_method( + cx: &LateContext<'_, '_>, + self_ref_ty: ty::Ty<'_>, +) -> Option<(&'static Lint, &'static str, &'static str)> { // FIXME: instead of this hard-coded list, we should check if `::iter` // exists and has the desired signature. Unfortunately FnCtxt is not exported // so we can't use its `lookup_method` method. @@ -2201,7 +2231,7 @@ fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Opti for (lint, path) in &INTO_ITER_COLLECTIONS { if match_def_path(cx.tcx, def_id, path) { - return Some((lint, path.last().unwrap(), method_name)) + return Some((lint, path.last().unwrap(), method_name)); } } None @@ -2218,8 +2248,7 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::T method_span, &format!( "this .into_iter() call is equivalent to .{}() and will not move the {}", - method_name, - kind, + method_name, kind, ), "call directly", method_name.to_string(), @@ -2228,7 +2257,6 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::T } } - /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { if let ty::Adt(_, substs) = ty.sty { @@ -2321,7 +2349,6 @@ const PATTERN_METHODS: [(&str, usize); 17] = [ ("trim_right_matches", 1), ]; - #[derive(Clone, Copy, PartialEq, Debug)] enum SelfKind { Value, @@ -2397,31 +2424,36 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener single_segment_ty(ty).map_or(false, |seg| { generics.params.iter().any(|param| match param.kind { hir::GenericParamKind::Type { .. } => { - param.name.ident().name == seg.ident.name && param.bounds.iter().any(|bound| { - if let hir::GenericBound::Trait(ref ptr, ..) = *bound { - let path = &ptr.trait_ref.path; - match_path(path, name) && path.segments.last().map_or(false, |s| { - if let Some(ref params) = s.args { - if params.parenthesized { - false - } else { - // FIXME(flip1995): messy, improve if there is a better option - // in the compiler - let types: Vec<_> = params.args.iter().filter_map(|arg| match arg { - hir::GenericArg::Type(ty) => Some(ty), - _ => None, - }).collect(); - types.len() == 1 - && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty)) - } - } else { - false - } - }) - } else { - false - } - }) + param.name.ident().name == seg.ident.name + && param.bounds.iter().any(|bound| { + if let hir::GenericBound::Trait(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path(path, name) + && path.segments.last().map_or(false, |s| { + if let Some(ref params) = s.args { + if params.parenthesized { + false + } else { + // FIXME(flip1995): messy, improve if there is a better option + // in the compiler + let types: Vec<_> = params + .args + .iter() + .filter_map(|arg| match arg { + hir::GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .collect(); + types.len() == 1 && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty)) + } + } else { + false + } + }) + } else { + false + } + }) }, _ => false, }) diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 86889c4c7c4..f8988935788 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 4a3fcfc853e..bddad90d1ef 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::consts::{constant_simple, Constant}; -use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use std::cmp::Ordering; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 1cf7345e8df..7220f1726bf 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,23 +7,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::consts::{constant, Constant}; use crate::reexport::*; -use matches::matches; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::FnKind; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast::LitKind; use crate::syntax::source_map::{ExpnFormat, Span}; -use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, - iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, - span_lint_and_then, walk_ptrs_ty, SpanlessEq}; use crate::utils::sugg::Sugg; -use crate::syntax::ast::LitKind; -use crate::consts::{constant, Constant}; -use crate::rustc_errors::Applicability; +use crate::utils::{ + get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, + last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty, + SpanlessEq, +}; +use if_chain::if_chain; +use matches::matches; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -43,7 +44,9 @@ use crate::rustc_errors::Applicability; /// /// **Example:** /// ```rust -/// fn foo(ref x: u8) -> bool { .. } +/// fn foo(ref x: u8) -> bool { +/// .. +/// } /// ``` declare_clippy_lint! { pub TOPLEVEL_REF_ARG, @@ -139,7 +142,7 @@ declare_clippy_lint! { /// ```rust /// match v { /// Some(x) => (), -/// y @ _ => (), // easier written as `y`, +/// y @ _ => (), // easier written as `y`, /// } /// ``` declare_clippy_lint! { @@ -182,7 +185,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// f() && g(); // We should write `if f() { g(); }`. +/// f() && g(); // We should write `if f() { g(); }`. /// ``` declare_clippy_lint! { pub SHORT_CIRCUIT_STATEMENT, @@ -266,8 +269,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } for arg in iter_input_pats(decl, body) { match arg.pat.node { - PatKind::Binding(BindingAnnotation::Ref, _, _, _) | - PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => { + PatKind::Binding(BindingAnnotation::Ref, _, _, _) + | PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => { span_lint( cx, TOPLEVEL_REF_ARG, @@ -372,7 +375,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); - if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") + if name == "eq" + || name == "ne" + || name == "is_nan" + || name.starts_with("eq_") || name.ends_with("_eq") { return; @@ -451,7 +457,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { cx, REDUNDANT_PATTERN, pat.span, - &format!("the `{} @ _` pattern can be written as just `{}`", ident.name, ident.name), + &format!( + "the `{} @ _` pattern can be written as just `{}`", + ident.name, ident.name + ), ); } } @@ -467,7 +476,7 @@ fn check_nan(cx: &LateContext<'_, '_>, path: &Path, expr: &Expr) { CMP_NAN, expr.span, "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead", - ); + ); } } } @@ -477,7 +486,7 @@ fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> if let Some((_, res)) = constant(cx, cx.tables, expr) { res } else { - false + false } } @@ -502,14 +511,16 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { return; } }, - ExprKind::Call(ref path, ref v) if v.len() == 1 => if let ExprKind::Path(ref path) = path.node { - if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { - (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) + ExprKind::Call(ref path, ref v) if v.len() == 1 => { + if let ExprKind::Path(ref path) = path.node { + if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { + (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) + } else { + return; + } } else { return; } - } else { - return; }, _ => return, }; @@ -520,18 +531,15 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { None => return, }; - let deref_arg_impl_partial_eq_other = arg_ty - .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])); - let arg_impl_partial_eq_deref_other = other_ty - .builtin_deref(true) - .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])); + let deref_arg_impl_partial_eq_other = arg_ty.builtin_deref(true).map_or(false, |tam| { + implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()]) + }); + let arg_impl_partial_eq_deref_other = other_ty.builtin_deref(true).map_or(false, |tam| { + implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()]) + }); let arg_impl_partial_eq_other = implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]); - if !deref_arg_impl_partial_eq_other - && !arg_impl_partial_eq_deref_other - && !arg_impl_partial_eq_other - { + if !deref_arg_impl_partial_eq_other && !arg_impl_partial_eq_deref_other && !arg_impl_partial_eq_other { return; } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 4973db4a5e8..53da89dfcb0 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro}; +use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; -use if_chain::if_chain; -use std::char; +use crate::rustc_errors::Applicability; use crate::syntax::ast::*; use crate::syntax::source_map::Span; -use crate::syntax::visit::{FnKind, Visitor, walk_expr}; +use crate::syntax::visit::{walk_expr, FnKind, Visitor}; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; -use crate::rustc_errors::Applicability; +use if_chain::if_chain; +use std::char; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -206,9 +205,7 @@ struct ReturnVisitor { impl ReturnVisitor { fn new() -> Self { - Self { - found_return: false, - } + Self { found_return: false } } } @@ -244,7 +241,8 @@ impl EarlyLintPass for MiscEarly { fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat, _: &mut bool) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; - let type_name = npat.segments + let type_name = npat + .segments .last() .expect("A path must have at least one segment") .ident @@ -271,8 +269,10 @@ impl EarlyLintPass for MiscEarly { for field in pfields { match field.node.pat.node { PatKind::Wild => {}, - _ => if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { - normal.push(n); + _ => { + if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { + normal.push(n); + } }, } } @@ -334,36 +334,42 @@ impl EarlyLintPass for MiscEarly { return; } match expr.node { - ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node { - let mut visitor = ReturnVisitor::new(); - visitor.visit_expr(block); - if !visitor.found_return { - span_lint_and_then( - cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| if decl.inputs.is_empty() { - let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion_with_applicability( - expr.span, - "Try doing something like: ", - hint, - Applicability::MachineApplicable, // snippet - ); - }, - ); + ExprKind::Call(ref paren, _) => { + if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node { + let mut visitor = ReturnVisitor::new(); + visitor.visit_expr(block); + if !visitor.found_return { + span_lint_and_then( + cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |db| { + if decl.inputs.is_empty() { + let hint = snippet(cx, block.span, "..").into_owned(); + db.span_suggestion_with_applicability( + expr.span, + "Try doing something like: ", + hint, + Applicability::MachineApplicable, // snippet + ); + } + }, + ); + } } } }, - ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node { - span_lint( - cx, - DOUBLE_NEG, - expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", - ); + ExprKind::Unary(UnOp::Neg, ref inner) => { + if let ExprKind::Unary(UnOp::Neg, _) = inner.node { + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); + } }, ExprKind::Lit(ref lit) => self.check_lit(cx, lit), _ => (), diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 20da0e7a698..8eb64f7ca37 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // This file incorporates work covered by the following copyright and // permission notice: // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT @@ -29,13 +28,13 @@ // use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; use crate::syntax::attr; use crate::syntax::source_map::Span; -use crate::utils::{span_lint, in_macro}; +use crate::utils::{in_macro, span_lint}; /// **What it does:** Warns if there is missing doc for any documentable item /// (public or private). @@ -72,12 +71,16 @@ impl MissingDoc { } fn doc_hidden(&self) -> bool { - *self.doc_hidden_stack - .last() - .expect("empty doc_hidden_stack") + *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") } - fn check_missing_docs_attrs(&self, cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { + fn check_missing_docs_attrs( + &self, + cx: &LateContext<'_, '_>, + attrs: &[ast::Attribute], + sp: Span, + desc: &'static str, + ) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. if cx.sess().opts.test { @@ -93,9 +96,7 @@ impl MissingDoc { return; } - let has_doc = attrs - .iter() - .any(|a| a.is_value_str() && a.name() == "doc"); + let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc"); if !has_doc { span_lint( cx, @@ -115,12 +116,14 @@ impl LintPass for MissingDoc { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { - let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { - attr.check_name("doc") && match attr.meta_item_list() { - None => false, - Some(l) => attr::list_contains_name(&l[..], "hidden"), - } - }); + let doc_hidden = self.doc_hidden() + || attrs.iter().any(|attr| { + attr.check_name("doc") + && match attr.meta_item_list() { + None => false, + Some(l) => attr::list_contains_name(&l[..], "hidden"), + } + }); self.doc_hidden_stack.push(doc_hidden); } @@ -156,10 +159,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Ty(..) => "a type alias", hir::ItemKind::Union(..) => "a union", hir::ItemKind::Existential(..) => "an existential type", - hir::ItemKind::ExternCrate(..) | - hir::ItemKind::ForeignMod(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Use(..) => return, + hir::ItemKind::ExternCrate(..) + | hir::ItemKind::ForeignMod(..) + | hir::ItemKind::Impl(..) + | hir::ItemKind::Use(..) => return, }; self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc); @@ -180,8 +183,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let def_id = cx.tcx.hir.local_def_id(impl_item.id); match cx.tcx.associated_item(def_id).container { ty::TraitContainer(_) => return, - ty::ImplContainer(cid) => if cx.tcx.impl_trait_ref(cid).is_some() { - return; + ty::ImplContainer(cid) => { + if cx.tcx.impl_trait_ref(cid).is_some() { + return; + } }, } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 2f3819a2da4..99477821cfa 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -33,9 +32,9 @@ use crate::utils::span_lint; /// crates when that's profitable as long as any form of LTO is used. When LTO is disabled, /// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates /// might intend for most of the methods in their public API to be able to be inlined across -/// crates even when LTO is disabled. For these types of crates, enabling this lint might make sense. -/// It allows the crate to require all exported methods to be `#[inline]` by default, and then opt -/// out for specific methods where this might not make sense. +/// crates even when LTO is disabled. For these types of crates, enabling this lint might make +/// sense. It allows the crate to require all exported methods to be `#[inline]` by default, and +/// then opt out for specific methods where this might not make sense. /// /// **Known problems:** None. /// @@ -79,11 +78,8 @@ declare_clippy_lint! { pub struct MissingInline; -fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, - attrs: &[ast::Attribute], sp: Span, desc: &'static str) { - let has_inline = attrs - .iter() - .any(|a| a.name() == "inline" ); +fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { + let has_inline = attrs.iter().any(|a| a.name() == "inline"); if !has_inline { span_lint( cx, @@ -97,11 +93,9 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool { use crate::rustc::session::config::CrateType; - cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| { - match t { - CrateType::Executable => true, - _ => false, - } + cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t { + CrateType::Executable => true, + _ => false, }) } @@ -125,47 +119,44 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let desc = "a function"; check_missing_inline_attrs(cx, &it.attrs, it.span, desc); }, - hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, - ref _bounds, ref trait_items) => { + hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, ref trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for tit in trait_items { let tit_ = cx.tcx.hir.trait_item(tit.id); match tit_.node { - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(..) => {}, + hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, hir::TraitItemKind::Method(..) => { if tit.defaultness.has_value() { // trait method with default body needs inline in case // an impl is not provided let desc = "a default trait method"; let item = cx.tcx.hir.expect_trait_item(tit.id.node_id); - check_missing_inline_attrs(cx, &item.attrs, - item.span, desc); + check_missing_inline_attrs(cx, &item.attrs, item.span, desc); } }, } } - } - hir::ItemKind::Const(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Mod(..) | - hir::ItemKind::Static(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::TraitAlias(..) | - hir::ItemKind::GlobalAsm(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::ExternCrate(..) | - hir::ItemKind::ForeignMod(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Use(..) => {}, + }, + hir::ItemKind::Const(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Mod(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::TraitAlias(..) + | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::Ty(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::Existential(..) + | hir::ItemKind::ExternCrate(..) + | hir::ItemKind::ForeignMod(..) + | hir::ItemKind::Impl(..) + | hir::ItemKind::Use(..) => {}, }; } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { - use crate::rustc::ty::{TraitContainer, ImplContainer}; + use crate::rustc::ty::{ImplContainer, TraitContainer}; if is_executable(cx) { return; } @@ -177,9 +168,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let desc = match impl_item.node { hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(_) | - hir::ImplItemKind::Existential(_) => return, + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::Existential(_) => return, }; let def_id = cx.tcx.hir.local_def_id(impl_item.id); diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 737d8bfd92c..6c58f93f0d8 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::hir::intravisit; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{higher, span_lint}; /// **What it does:** Checks for instances of `mut mut` references. @@ -81,12 +80,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { expr.span, "generally you want to avoid `&mut &mut _` if possible", ); - } else if let ty::Ref( - _, - _, - hir::MutMutable, - ) = self.cx.tables.expr_ty(e).sty - { + } else if let ty::Ref(_, _, hir::MutMutable) = self.cx.tables.expr_ty(e).sty { span_lint( self.cx, MUT_MUT, @@ -109,8 +103,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { if let hir::TyKind::Rptr( _, hir::MutTy { - mutbl: hir::MutMutable, - .. + mutbl: hir::MutMutable, .. }, ) = pty.node { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index bdf8bf80c88..6729b2030a7 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::ty::{self, Ty}; use crate::rustc::ty::subst::Subst; -use crate::rustc::hir::*; +use crate::rustc::ty::{self, Ty}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint; /// **What it does:** Detects giving a mutable reference to a function that only @@ -28,13 +27,12 @@ use crate::utils::span_lint; /// my_vec.push(&mut value) /// ``` declare_clippy_lint! { - pub UNNECESSARY_MUT_PASSED, - style, - "an argument passed as a mutable reference although the callee only demands an \ - immutable reference" +pub UNNECESSARY_MUT_PASSED, +style, +"an argument passed as a mutable reference although the callee only demands an \ + immutable reference" } - #[derive(Copy, Clone)] pub struct UnnecessaryMutPassed; @@ -47,13 +45,15 @@ impl LintPass for UnnecessaryMutPassed { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { match e.node { - ExprKind::Call(ref fn_expr, ref arguments) => if let ExprKind::Path(ref path) = fn_expr.node { - check_arguments( - cx, - arguments, - cx.tables.expr_ty(fn_expr), - &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), - ); + ExprKind::Call(ref fn_expr, ref arguments) => { + if let ExprKind::Path(ref path) = fn_expr.node { + check_arguments( + cx, + arguments, + cx.tables.expr_ty(fn_expr), + &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + ); + } }, ExprKind::MethodCall(ref path, _, ref arguments) => { let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); @@ -72,21 +72,18 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - ty::Ref( - _, - _, - MutImmutable, - ) | - ty::RawPtr(ty::TypeAndMut { - mutbl: MutImmutable, - .. - }) => if let ExprKind::AddrOf(MutMutable, _) = argument.node { - span_lint( - cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method `{}` doesn't need a mutable reference", name), - ); + ty::Ref(_, _, MutImmutable) + | ty::RawPtr(ty::TypeAndMut { + mutbl: MutImmutable, .. + }) => { + if let ExprKind::AddrOf(MutMutable, _) = argument.node { + span_lint( + cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method `{}` doesn't need a mutable reference", name), + ); + } }, _ => (), } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 8ddaf692b7e..34683934eca 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for uses of mutex where an atomic value could be used //! //! This lint is **warn** by default +use crate::rustc::hir::Expr; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty::{self, Ty}; -use crate::rustc::hir::Expr; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; use crate::utils::{match_type, paths, span_lint}; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 37ccf28d572..fec8e2490da 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for needless boolean results of if-else expressions //! //! This lint is **warn** by default @@ -34,13 +33,17 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint, span_lint_an /// /// **Example:** /// ```rust -/// if x { false } else { true } +/// if x { +/// false +/// } else { +/// true +/// } /// ``` declare_clippy_lint! { - pub NEEDLESS_BOOL, - complexity, - "if-statements with plain booleans in the then- and else-clause, e.g. \ - `if p { true } else { false }`" +pub NEEDLESS_BOOL, +complexity, +"if-statements with plain booleans in the then- and else-clause, e.g. \ + `if p { true } else { false }`" } /// **What it does:** Checks for expressions of the form `x == true` (or vice @@ -52,7 +55,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// if x == true { } // could be `if x { }` +/// if x == true {} // could be `if x { }` /// ``` declare_clippy_lint! { pub BOOL_COMPARISON, @@ -142,7 +145,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { return; } - if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Eq, .. + }, + ref left_side, + ref right_side, + ) = e.node + { let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => { @@ -208,14 +218,16 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), - (&[ref e], None) => if let StmtKind::Semi(ref e, _) = e.node { - if let ExprKind::Ret(_) = e.node { - fetch_bool_expr(&**e) + (&[ref e], None) => { + if let StmtKind::Semi(ref e, _) = e.node { + if let ExprKind::Ret(_) = e.node { + fetch_bool_expr(&**e) + } else { + Expression::Other + } } else { Expression::Other } - } else { - Expression::Other }, _ => Expression::Other, } @@ -224,10 +236,12 @@ fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { ExprKind::Block(ref block, _) => fetch_bool_block(block), - ExprKind::Lit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { - Expression::Bool(value) - } else { - Expression::Other + ExprKind::Lit(ref lit_ptr) => { + if let LitKind::Bool(value) = lit_ptr.node { + Expression::Bool(value) + } else { + Expression::Other + } }, ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) { Expression::Bool(value) => Expression::RetBool(value), diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 7892467b7f8..dbee58c6a3e 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for needless address of operations (`&`) //! //! This lint is **warn** by default @@ -18,8 +17,8 @@ use crate::rustc::ty; use crate::rustc::ty::adjustment::{Adjust, Adjustment}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; -use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; use crate::syntax::ast::NodeId; +use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; use if_chain::if_chain; /// **What it does:** Checks for address of operations (`&`) that are going to @@ -60,11 +59,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if let ty::Ref(..) = cx.tables.expr_ty(inner).sty { for adj3 in cx.tables.expr_adjustments(e).windows(3) { if let [Adjustment { - kind: Adjust::Deref(_), - .. + kind: Adjust::Deref(_), .. }, Adjustment { - kind: Adjust::Deref(_), - .. + kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(_), .. diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index f40fbef6d2f..9b70d4b2e64 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for useless borrowed references. //! //! This lint is **warn** by default +use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; -use crate::utils::{in_macro, snippet, span_lint_and_then}; use crate::rustc_errors::Applicability; +use crate::utils::{in_macro, snippet, span_lint_and_then}; +use if_chain::if_chain; /// **What it does:** Checks for useless borrowed references. /// @@ -48,8 +47,8 @@ use crate::rustc_errors::Applicability; /// /// **Example:** /// ```rust -/// let mut v = Vec::::new(); -/// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +/// let mut v = Vec::::new(); +/// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); /// ``` /// This closure takes a reference on something that has been matched as a /// reference and @@ -89,7 +88,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { |db| { let hint = snippet(cx, spanned_name.span, "..").into_owned(); db.span_suggestion_with_applicability( - pat.span, + pat.span, "try removing the `&ref` part and just keep", hint, Applicability::MachineApplicable, // snippet diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 6a39595f62e..2f1b92544b4 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for continue statements in loops that are redundant. //! //! For example, the lint would catch @@ -181,7 +180,6 @@ impl EarlyLintPass for NeedlessContinue { /// - The expression is a `continue` node. /// - The expression node is a block with the first statement being a /// `continue`. -/// fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { match else_expr.node { ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block), @@ -192,10 +190,12 @@ fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { fn is_first_block_stmt_continue(block: &ast::Block) -> bool { block.stmts.get(0).map_or(false, |stmt| match stmt.node { - ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node { - true - } else { - false + ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => { + if let ast::ExprKind::Continue(_) = e.node { + true + } else { + false + } }, _ => false, }) @@ -208,10 +208,10 @@ where F: FnMut(&ast::Block), { match expr.node { - ast::ExprKind::While(_, ref loop_block, _) | - ast::ExprKind::WhileLet(_, _, ref loop_block, _) | - ast::ExprKind::ForLoop(_, _, ref loop_block, _) | - ast::ExprKind::Loop(ref loop_block, _) => func(loop_block), + ast::ExprKind::While(_, ref loop_block, _) + | ast::ExprKind::WhileLet(_, _, ref loop_block, _) + | ast::ExprKind::ForLoop(_, _, ref loop_block, _) + | ast::ExprKind::Loop(ref loop_block, _) => func(loop_block), _ => {}, } } @@ -224,7 +224,6 @@ where /// - The `if` condition expression, /// - The `then` block, and /// - The `else` expression. -/// fn with_if_expr(stmt: &ast::Stmt, mut func: F) where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr), @@ -274,7 +273,6 @@ const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause a const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \ block, like so:\n"; - fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) { // snip is the whole *help* message that appears after the warning. // message is the warning message. @@ -294,7 +292,11 @@ fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); } -fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String { +fn suggestion_snippet_for_continue_inside_if<'a>( + ctx: &EarlyContext<'_>, + data: &'a LintData<'_>, + header: &str, +) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); let if_code = format!("if {} {{\n continue;\n}}\n", cond_code); @@ -311,7 +313,11 @@ fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: & ret } -fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String { +fn suggestion_snippet_for_continue_inside_else<'a>( + ctx: &EarlyContext<'_>, + data: &'a LintData<'_>, + header: &str, +) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); let mut if_code = format!("if {} {{\n", cond_code); @@ -355,7 +361,12 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { block_stmts: &loop_block.stmts, }; if needless_continue_in_else(else_expr) { - emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock); + emit_warning( + ctx, + data, + DROP_ELSE_BLOCK_AND_MERGE_MSG, + LintType::ContinueInsideElseBlock, + ); } else if is_first_block_stmt_continue(then_block) { emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock); } @@ -369,9 +380,9 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { /// e.g., the string /// /// ``` -/// { -/// let x = 5; -/// } +/// { +/// let x = 5; +/// } /// ``` /// /// is transformed to @@ -413,7 +424,6 @@ pub fn erode_from_back(s: &str) -> String { /// inside_a_block(); /// } /// ``` -/// pub fn erode_from_front(s: &str) -> String { s.chars() .skip_while(|c| c.is_whitespace()) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ff8e0cc0e6e..251c3d73959 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -7,27 +7,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use matches::matches; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::FnKind; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::ty::{self, RegionKind, TypeFoldable}; -use crate::rustc::traits; use crate::rustc::middle::expr_use_visitor as euv; use crate::rustc::middle::mem_categorization as mc; -use crate::rustc_target::spec::abi::Abi; +use crate::rustc::traits; +use crate::rustc::ty::{self, RegionKind, TypeFoldable}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use crate::rustc_errors::Applicability; +use crate::rustc_target::spec::abi::Abi; use crate::syntax::ast::NodeId; -use crate::syntax_pos::Span; use crate::syntax::errors::DiagnosticBuilder; -use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, - snippet, snippet_opt, span_lint_and_then}; +use crate::syntax_pos::Span; use crate::utils::ptr::get_spans; +use crate::utils::{ + get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet, + snippet_opt, span_lint_and_then, +}; +use if_chain::if_chain; +use matches::matches; use std::borrow::Cow; -use crate::rustc_errors::Applicability; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its @@ -67,7 +68,13 @@ impl LintPass for NeedlessPassByValue { } macro_rules! need { - ($e: expr) => { if let Some(x) = $e { x } else { return; } }; + ($e: expr) => { + if let Some(x) = $e { + x + } else { + return; + } + }; } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { @@ -114,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { need!(cx.tcx.lang_items().fn_trait()), need!(cx.tcx.lang_items().fn_once_trait()), need!(cx.tcx.lang_items().fn_mut_trait()), - need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)) + need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)), ]; let sized_trait = need!(cx.tcx.lang_items().sized_trait()); @@ -125,7 +132,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .filter(|p| !p.is_global()) .filter_map(|pred| { if let ty::Predicate::Trait(poly_trait_ref) = pred { - if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars() { + if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars() + { return None; } Some(poly_trait_ref) @@ -152,12 +160,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); - for (idx, ((input, &ty), arg)) in decl.inputs - .iter() - .zip(fn_sig.inputs()) - .zip(&body.arguments) - .enumerate() - { + for (idx, ((input, &ty), arg)) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments).enumerate() { // All spans generated from a proc-macro invocation are the same... if span == input.span { return; @@ -172,9 +175,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } } + // // * Exclude a type that is specifically bounded by `Borrow`. - // * Exclude a type whose reference also fulfills its bound. - // (e.g. `std::convert::AsRef`, `serde::Serialize`) + // * Exclude a type whose reference also fulfills its bound. (e.g. `std::convert::AsRef`, + // `serde::Serialize`) let (implements_borrow_trait, all_borrowable_trait) = { let preds = preds .iter() @@ -183,17 +187,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| t.def_id() == borrow_trait), - !preds.is_empty() && preds.iter().all(|t| { - let ty_params = &t.skip_binder().trait_ref.substs.iter().skip(1) - .cloned() - .collect::>(); - implements_trait( - cx, - cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), - t.def_id(), - ty_params - ) - }), + !preds.is_empty() + && preds.iter().all(|t| { + let ty_params = &t + .skip_binder() + .trait_ref + .substs + .iter() + .skip(1) + .cloned() + .collect::>(); + implements_trait(cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), ty_params) + }), ) }; @@ -415,14 +420,22 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { } } - fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, _: euv::LoanCause) {} + fn borrow( + &mut self, + _: NodeId, + _: Span, + _: &mc::cmt_<'tcx>, + _: ty::Region<'_>, + _: ty::BorrowKind, + _: euv::LoanCause, + ) { + } fn mutate(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: euv::MutateMode) {} fn decl_without_init(&mut self, _: NodeId, _: Span) {} } - fn unwrap_downcast_or_interior<'a, 'tcx>(mut cmt: &'a mc::cmt_<'tcx>) -> mc::cmt_<'tcx> { loop { match cmt.cat { @@ -431,5 +444,5 @@ fn unwrap_downcast_or_interior<'a, 'tcx>(mut cmt: &'a mc::cmt_<'tcx>) -> mc::cmt }, _ => return (*cmt).clone(), } - }; + } } diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 3388c92e0ec..a15f7924678 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::ty; -use crate::rustc::hir::{Expr, ExprKind}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint; /// **What it does:** Checks for needlessly including a base struct on update @@ -24,7 +23,11 @@ use crate::utils::span_lint; /// /// **Example:** /// ```rust -/// Point { x: 1, y: 0, ..zero_point } +/// Point { +/// x: 1, +/// y: 0, +/// ..zero_point +/// } /// ``` declare_clippy_lint! { pub NEEDLESS_UPDATE, diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 7cd14b9a2d6..dd7d1478c23 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -7,9 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; @@ -61,7 +60,6 @@ impl LintPass for NoNegCompOpForPartialOrd { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index d3b72372c2f..0df21861346 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::syntax::source_map::{Span, Spanned}; +use if_chain::if_chain; use crate::consts::{self, Constant}; use crate::utils::span_lint; @@ -45,7 +44,14 @@ impl LintPass for NegMultiply { #[allow(clippy::match_same_arms)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref l, ref r) = e.node { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + ref l, + ref r, + ) = e.node + { match (&l.node, &r.node) { (&ExprKind::Unary(..), &ExprKind::Unary(..)) => (), (&ExprKind::Unary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r), diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index ee990117014..f0a7c71856d 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -7,19 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::hir::def_id::DefId; use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::hir::def_id::DefId; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use crate::rustc::ty::{self, Ty}; use crate::rustc::util::nodemap::NodeSet; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::ty::{self, Ty}; +use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; use crate::utils::paths; -use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; use crate::utils::sugg::DiagnosticBuilderExt; -use crate::rustc_errors::Applicability; +use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; +use if_chain::if_chain; /// **What it does:** Checks for types with a `fn new() -> Self` method and no /// implementation of @@ -125,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } if impl_item.generics.params.iter().any(|gen| match gen.kind { hir::GenericParamKind::Type { .. } => true, - _ => false + _ => false, }) { // when the result of `new()` depends on a type parameter we should not require // an @@ -134,8 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)); - let self_ty = cx.tcx - .type_of(self_did); + let self_ty = cx.tcx.type_of(self_did); if_chain! { if same_tys(cx, self_ty, return_ty(cx, id)); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); @@ -171,7 +169,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { cx, NEW_WITHOUT_DEFAULT_DERIVE, impl_item.span, - &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), + &format!( + "you should consider deriving a `Default` implementation for `{}`", + self_ty + ), |db| { db.suggest_item_with_attr( cx, @@ -186,7 +187,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { cx, NEW_WITHOUT_DEFAULT, impl_item.span, - &format!("you should consider adding a `Default` implementation for `{}`", self_ty), + &format!( + "you should consider adding a `Default` implementation for `{}`", + self_ty + ), |db| { db.suggest_prepend_item( cx, diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 72ed649c5d9..d39c13621ff 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::def::Def; use crate::rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -63,37 +62,42 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { has_no_effect(cx, a) && has_no_effect(cx, b) }, ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), - ExprKind::Repeat(ref inner, _) | - ExprKind::Cast(ref inner, _) | - ExprKind::Type(ref inner, _) | - ExprKind::Unary(_, ref inner) | - ExprKind::Field(ref inner, _) | - ExprKind::AddrOf(_, ref inner) | - ExprKind::Box(ref inner) => has_no_effect(cx, inner), + ExprKind::Repeat(ref inner, _) + | ExprKind::Cast(ref inner, _) + | ExprKind::Type(ref inner, _) + | ExprKind::Unary(_, ref inner) + | ExprKind::Field(ref inner, _) + | ExprKind::AddrOf(_, ref inner) + | ExprKind::Box(ref inner) => has_no_effect(cx, inner), ExprKind::Struct(_, ref fields, ref base) => { - !has_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { - Some(ref base) => has_no_effect(cx, base), - None => true, - } - }, - ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { - !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg)) - }, - _ => false, - } - } else { - false + !has_drop(cx, expr) + && fields.iter().all(|field| has_no_effect(cx, &field.expr)) + && match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } }, - ExprKind::Block(ref block, _) => { - block.stmts.is_empty() && if let Some(ref expr) = block.expr { - has_no_effect(cx, expr) + ExprKind::Call(ref callee, ref args) => { + if let ExprKind::Path(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg)) + }, + _ => false, + } } else { false } }, + ExprKind::Block(ref block, _) => { + block.stmts.is_empty() + && if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) + } else { + false + } + }, _ => false, } } @@ -139,7 +143,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } - fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option> { if in_macro(expr.span) { return None; @@ -150,37 +153,34 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option Some(v.iter().collect()), - ExprKind::Repeat(ref inner, _) | - ExprKind::Cast(ref inner, _) | - ExprKind::Type(ref inner, _) | - ExprKind::Unary(_, ref inner) | - ExprKind::Field(ref inner, _) | - ExprKind::AddrOf(_, ref inner) | - ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - ExprKind::Struct(_, ref fields, ref base) => if has_drop(cx, expr) { - None - } else { - Some( - fields - .iter() - .map(|f| &f.expr) - .chain(base) - .map(Deref::deref) - .collect(), - ) + ExprKind::Repeat(ref inner, _) + | ExprKind::Cast(ref inner, _) + | ExprKind::Type(ref inner, _) + | ExprKind::Unary(_, ref inner) + | ExprKind::Field(ref inner, _) + | ExprKind::AddrOf(_, ref inner) + | ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), + ExprKind::Struct(_, ref fields, ref base) => { + if has_drop(cx, expr) { + None + } else { + Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) + } }, - ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) - if !has_drop(cx, expr) => - { - Some(args.iter().collect()) - }, - _ => None, + ExprKind::Call(ref callee, ref args) => { + if let ExprKind::Path(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) + if !has_drop(cx, expr) => + { + Some(args.iter().collect()) + }, + _ => None, + } + } else { + None } - } else { - None }, ExprKind::Block(ref block, _) => { if block.stmts.is_empty() { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 61b57db51d5..bb44bd6bd06 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -7,22 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for uses of const which the type is not Freeze (Cell-free). //! //! This lint is **deny** by default. -use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::rustc::hir::def::Def; -use crate::rustc::ty::{self, TypeFlags}; +use crate::rustc::hir::*; +use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; use crate::rustc::ty::adjustment::Adjust; +use crate::rustc::ty::{self, TypeFlags}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::rustc_typeck::hir_ty_to_ty; -use crate::syntax_pos::{DUMMY_SP, Span}; -use std::ptr; +use crate::syntax_pos::{Span, DUMMY_SP}; use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then}; +use std::ptr; /// **What it does:** Checks for declaration of `const` items which is interior /// mutable (e.g. contains a `Cell`, `Mutex`, `AtomicXxxx` etc). @@ -42,11 +41,11 @@ use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then}; /// /// **Example:** /// ```rust -/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize}; +/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; /// /// // Bad. /// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); -/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged +/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged /// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct /// /// // Good. @@ -74,11 +73,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize}; +/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; /// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); /// /// // Bad. -/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged +/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged /// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct /// /// // Good. @@ -94,16 +93,9 @@ declare_clippy_lint! { #[derive(Copy, Clone)] enum Source { - Item { - item: Span, - }, - Assoc { - item: Span, - ty: Span, - }, - Expr { - expr: Span, - }, + Item { item: Span }, + Assoc { item: Span, ty: Span }, + Expr { expr: Span }, } impl Source { @@ -123,11 +115,7 @@ impl Source { } } -fn verify_ty_bound<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - ty: ty::Ty<'tcx>, - source: Source, -) { +fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) { if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) { // an UnsafeCell is !Copy, and an UnsafeCell is also the only type which // is !Freeze, thus if our type is Copy we can be sure it must be Freeze @@ -149,22 +137,19 @@ fn verify_ty_bound<'a, 'tcx>( "static".to_string(), Applicability::MachineApplicable, ); - } + }, Source::Assoc { ty: ty_span, .. } => { if ty.flags.contains(TypeFlags::HAS_FREE_LOCAL_NAMES) { db.span_help(ty_span, &format!("consider requiring `{}` to be `Copy`", ty)); } - } + }, Source::Expr { .. } => { - db.help( - "assign this const to a local or static variable, and use the variable here", - ); - } + db.help("assign this const to a local or static variable, and use the variable here"); + }, } }); } - pub struct NonCopyConst; impl LintPass for NonCopyConst { @@ -184,7 +169,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx TraitItem) { if let TraitItemKind::Const(hir_ty, ..) = &trait_item.node { let ty = hir_ty_to_ty(cx.tcx, hir_ty); - verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: trait_item.span }); + verify_ty_bound( + cx, + ty, + Source::Assoc { + ty: hir_ty.span, + item: trait_item.span, + }, + ); } } @@ -195,7 +187,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { // ensure the impl is an inherent impl. if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node { let ty = hir_ty_to_ty(cx.tcx, hir_ty); - verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: impl_item.span }); + verify_ty_bound( + cx, + ty, + Source::Assoc { + ty: hir_ty.span, + item: impl_item.span, + }, + ); } } } @@ -227,25 +226,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced needs_check_adjustment = false; - } + }, ExprKind::Field(..) => { dereferenced_expr = parent_expr; needs_check_adjustment = true; - } + }, ExprKind::Index(e, _) if ptr::eq(&**e, cur_expr) => { // `e[i]` => desugared to `*Index::index(&e, i)`, // meaning `e` must be referenced. // no need to go further up since a method call is involved now. needs_check_adjustment = false; break; - } + }, ExprKind::Unary(UnDeref, _) => { // `*e` => desugared to `*Deref::deref(&e)`, // meaning `e` must be referenced. // no need to go further up since a method call is involved now. needs_check_adjustment = false; break; - } + }, _ => break, } cur_expr = parent_expr; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index ad4f52a528f..ad8006e9256 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{LintArray, LintPass, EarlyContext, EarlyLintPass}; +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; use crate::syntax::ast::*; use crate::syntax::attr; +use crate::syntax::source_map::Span; +use crate::syntax::symbol::LocalInternedString; use crate::syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; use crate::utils::{span_lint, span_lint_and_then}; @@ -116,9 +115,11 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.node { PatKind::Ident(_, ident, _) => self.check_name(ident.span, ident.name), - PatKind::Struct(_, ref fields, _) => for field in fields { - if !field.node.is_shorthand { - self.visit_pat(&field.node.pat); + PatKind::Struct(_, ref fields, _) => { + for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); + } } }, _ => walk_pat(self, pat), @@ -155,7 +156,10 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { self.0.cx, MANY_SINGLE_CHAR_NAMES, span, - &format!("{}th binding whose name is just one char", self.0.single_char_names.len()), + &format!( + "{}th binding whose name is just one char", + self.0.single_char_names.len() + ), ); } } @@ -197,26 +201,19 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } else { let mut interned_chars = interned_name.chars(); let mut existing_chars = existing_name.interned.chars(); - let first_i = interned_chars - .next() - .expect("we know we have at least one char"); - let first_e = existing_chars - .next() - .expect("we know we have at least one char"); + let first_i = interned_chars.next().expect("we know we have at least one char"); + let first_e = existing_chars.next().expect("we know we have at least one char"); let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric(); if eq_or_numeric((first_i, first_e)) { - let last_i = interned_chars - .next_back() - .expect("we know we have at least two chars"); - let last_e = existing_chars - .next_back() - .expect("we know we have at least two chars"); + let last_i = interned_chars.next_back().expect("we know we have at least two chars"); + let last_e = existing_chars.next_back().expect("we know we have at least two chars"); if eq_or_numeric((last_i, last_e)) { if interned_chars .zip(existing_chars) .filter(|&ie| !eq_or_numeric(ie)) - .count() != 1 + .count() + != 1 { continue; } @@ -227,7 +224,8 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let second_last_e = existing_chars .next_back() .expect("we know we have at least three chars"); - if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' + if !eq_or_numeric((second_last_i, second_last_e)) + || second_last_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity foo_x, foo_y @@ -237,13 +235,10 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); } } else { - let second_i = interned_chars - .next() - .expect("we know we have at least two chars"); - let second_e = existing_chars - .next() - .expect("we know we have at least two chars"); - if !eq_or_numeric((second_i, second_e)) || second_i == '_' + let second_i = interned_chars.next().expect("we know we have at least two chars"); + let second_e = existing_chars.next().expect("we know we have at least two chars"); + if !eq_or_numeric((second_i, second_e)) + || second_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { // allowed similarity x_foo, y_foo diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 9a23b05b8d9..9f6b6265665 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; +use if_chain::if_chain; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 4f647d053e3..e78299bd3af 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -200,7 +199,12 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument } if read && truncate && read_arg && truncate_arg && !(write && write_arg) { - span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\""); + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with \"truncate\" and \"read\"", + ); } if append && truncate && append_arg && truncate_arg { span_lint( diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index d0805896fb7..7942e61c9f4 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; use crate::utils::{span_lint, SpanlessEq}; +use if_chain::if_chain; /// **What it does:** Detects classic underflow/overflow checks. /// diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 68b989721af..39b85b12a84 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::syntax::ast::LitKind; -use crate::syntax::ptr::P; use crate::syntax::ext::quote::rt::Span; +use crate::syntax::ptr::P; use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; +use if_chain::if_chain; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index d38e02d6326..70c93c5978b 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; use crate::utils::{is_automatically_derived, span_lint}; +use if_chain::if_chain; /// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. /// diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index d8f2645699d..4f71f36528c 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; @@ -115,7 +114,10 @@ impl EarlyLintPass for Precedence { expr.span, "unary minus has lower precedence than method call", "consider adding parentheses to clarify your intent", - format!("-({})", snippet_with_applicability(cx, rhs.span, "..", &mut applicability)), + format!( + "-({})", + snippet_with_applicability(cx, rhs.span, "..", &mut applicability) + ), applicability, ); }, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 187d89cdd79..139b87dffe7 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -7,22 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Checks for usage of `&Vec[_]` and `&String`. -use std::borrow::Cow; -use crate::rustc::hir::*; use crate::rustc::hir::QPath; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::NodeId; use crate::syntax::source_map::Span; use crate::syntax_pos::MultiSpan; -use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; use crate::utils::ptr::get_spans; -use crate::rustc_errors::Applicability; +use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; +use if_chain::if_chain; +use std::borrow::Cow; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless the references are mutable. It will also suggest you @@ -55,10 +54,10 @@ use crate::rustc_errors::Applicability; /// fn foo(&Vec) { .. } /// ``` declare_clippy_lint! { - pub PTR_ARG, - style, - "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ - instead, respectively" +pub PTR_ARG, +style, +"fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ + instead, respectively" } /// **What it does:** This lint checks for equality comparisons with `ptr::null` @@ -71,7 +70,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// if x == ptr::null { .. } +/// if x == ptr::null { +/// .. +/// } /// ``` declare_clippy_lint! { pub CMP_NULL, @@ -162,12 +163,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: let fn_ty = sig.skip_binder(); for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { - if let ty::Ref( - _, - ty, - MutImmutable - ) = ty.sty - { + if let ty::Ref(_, ty, MutImmutable) = ty.sty { if match_type(cx, ty, &paths::VEC) { let mut ty_snippet = None; if_chain! { @@ -193,19 +189,18 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: |db| { if let Some(ref snippet) = ty_snippet { db.span_suggestion_with_applicability( - arg.span, - "change this to", - format!("&[{}]", snippet), - Applicability::Unspecified, - ); + arg.span, + "change this to", + format!("&[{}]", snippet), + Applicability::Unspecified, + ); } for (clonespan, suggestion) in spans { db.span_suggestion_with_applicability( clonespan, - &snippet_opt(cx, clonespan).map_or( - "change the call to".into(), - |x| Cow::Owned(format!("change `{}` to", x)), - ), + &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { + Cow::Owned(format!("change `{}` to", x)) + }), suggestion.into(), Applicability::Unspecified, ); @@ -230,10 +225,9 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: for (clonespan, suggestion) in spans { db.span_suggestion_short_with_applicability( clonespan, - &snippet_opt(cx, clonespan).map_or( - "change the call to".into(), - |x| Cow::Owned(format!("change `{}` to", x)), - ), + &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { + Cow::Owned(format!("change `{}` to", x)) + }), suggestion.into(), Applicability::Unspecified, ); @@ -280,7 +274,8 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: if let FunctionRetTy::Return(ref ty) = decl.output { if let Some((out, MutMutable, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; - for (_, ref mutbl, ref argspan) in decl.inputs + for (_, ref mutbl, ref argspan) in decl + .inputs .iter() .filter_map(|ty| get_rptr_lm(ty)) .filter(|&(lt, _, _)| lt.name == out.name) @@ -293,10 +288,16 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: if immutables.is_empty() { return; } - span_lint_and_then(cx, MUT_FROM_REF, ty.span, "mutable borrow from immutable input(s)", |db| { - let ms = MultiSpan::from_spans(immutables); - db.span_note(ms, "immutable borrow here"); - }); + span_lint_and_then( + cx, + MUT_FROM_REF, + ty.span, + "mutable borrow from immutable input(s)", + |db| { + let ms = MultiSpan::from_spans(immutables); + db.span_note(ms, "immutable borrow here"); + }, + ); } } } diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 0d37d4d4b08..5d2714651ed 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::{declare_tool_lint, hir, lint, lint_array}; use crate::rustc_errors::Applicability; use crate::utils; @@ -27,7 +26,9 @@ use std::fmt; /// let ptr = vec.as_ptr(); /// let offset = 1_usize; /// -/// unsafe { ptr.offset(offset as isize); } +/// unsafe { +/// ptr.offset(offset as isize); +/// } /// ``` /// /// Could be written: @@ -37,7 +38,9 @@ use std::fmt; /// let ptr = vec.as_ptr(); /// let offset = 1_usize; /// -/// unsafe { ptr.add(offset); } +/// unsafe { +/// ptr.add(offset); +/// } /// ``` declare_clippy_lint! { pub PTR_OFFSET_WITH_CAST, @@ -82,7 +85,6 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { } else { utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); } - } } @@ -119,18 +121,12 @@ fn expr_as_ptr_offset_call<'a, 'tcx>( } // Is the type of the expression a usize? -fn is_expr_ty_usize<'a, 'tcx>( - cx: &lint::LateContext<'a, 'tcx>, - expr: &hir::Expr, -) -> bool { +fn is_expr_ty_usize<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool { cx.tables.expr_ty(expr) == cx.tcx.types.usize } // Is the type of the expression a raw pointer? -fn is_expr_ty_raw_ptr<'a, 'tcx>( - cx: &lint::LateContext<'a, 'tcx>, - expr: &hir::Expr, -) -> bool { +fn is_expr_ty_raw_ptr<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool { cx.tables.expr_ty(expr).is_unsafe_ptr() } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 72d33e58cd3..3a62a3a1526 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::def::Def; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; -use crate::rustc::hir::def::Def; -use crate::utils::sugg::Sugg; use crate::syntax::ptr::P; +use crate::utils::sugg::Sugg; +use if_chain::if_chain; -use crate::utils::{match_def_path, match_type, span_lint_and_then}; -use crate::utils::paths::*; use crate::rustc_errors::Applicability; +use crate::utils::paths::*; +use crate::utils::{match_def_path, match_type, span_lint_and_then}; /// **What it does:** Checks for expressions that could be replaced by the question mark operator /// @@ -38,7 +37,7 @@ use crate::rustc_errors::Applicability; /// ```rust /// option?; /// ``` -declare_clippy_lint!{ +declare_clippy_lint! { pub QUESTION_MARK, style, "checks for expressions that could be replaced by the question mark operator" @@ -108,17 +107,15 @@ impl Pass { false }, - ExprKind::Ret(Some(ref expr)) => { - Self::expression_returns_none(cx, expr) - }, + ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { - return match_def_path(cx.tcx, def_id, &OPTION_NONE); + return match_def_path(cx.tcx, def_id, &OPTION_NONE); } false }, - _ => false + _ => false, } } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index bc3125253a2..d84943f1ddc 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; +use crate::rustc_errors::Applicability; use crate::syntax::ast::RangeLimits; use crate::syntax::source_map::Spanned; -use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt}; -use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::sugg::Sugg; -use crate::rustc_errors::Applicability; +use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; +use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then}; +use if_chain::if_chain; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -29,7 +28,9 @@ use crate::rustc_errors::Applicability; /// /// **Example:** /// ```rust -/// for x in (5..5).step_by(0) { .. } +/// for x in (5..5).step_by(0) { +/// .. +/// } /// ``` declare_clippy_lint! { pub ITERATOR_STEP_BY_ZERO, @@ -98,7 +99,12 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, RANGE_MINUS_ONE) + lint_array!( + ITERATOR_STEP_BY_ZERO, + RANGE_ZIP_WITH_LEN, + RANGE_PLUS_ONE, + RANGE_MINUS_ONE + ) } } @@ -148,7 +154,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // exclusive range plus one: x..(y+1) if_chain! { - if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr); + if let Some(higher::Range { + start, + end: Some(end), + limits: RangeLimits::HalfOpen + }) = higher::range(cx, expr); if let Some(y) = y_plus_one(end); then { span_lint_and_then( @@ -217,12 +227,20 @@ fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { fn y_plus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) { - Some(rhs) - } else if is_integer_literal(rhs, 1) { - Some(lhs) - } else { - None + ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + ref lhs, + ref rhs, + ) => { + if is_integer_literal(lhs, 1) { + Some(rhs) + } else if is_integer_literal(rhs, 1) { + Some(lhs) + } else { + None + } }, _ => None, } @@ -230,7 +248,13 @@ fn y_plus_one(expr: &Expr) -> Option<&Expr> { fn y_minus_one(expr: &Expr) -> Option<&Expr> { match expr.node { - ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs), + ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, .. + }, + ref lhs, + ref rhs, + ) if is_integer_literal(rhs, 1) => Some(lhs), _ => None, } } diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 2ed877d1364..77f8d7578d8 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -279,7 +279,9 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { match ctx { - PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => return, + PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => { + return + }, _ => {}, } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index b25ea1d5d38..308f0066b69 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::*; -use crate::utils::{span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index 130b1144329..4de98eb5525 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; -use crate::syntax::ptr::P; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; +use crate::syntax::ptr::P; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; -use crate::rustc_errors::Applicability; /// **What it does:** Lint for redundant pattern matching over `Result` or /// `Option` @@ -46,7 +45,6 @@ use crate::rustc_errors::Applicability; /// if Some(42).is_some() {} /// Ok::(42).is_ok(); /// ``` -/// declare_clippy_lint! { pub REDUNDANT_PATTERN_MATCHING, style, @@ -74,12 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn find_sugg_for_if_let<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr, - op: &P, - arms: &HirVec -) { +fn find_sugg_for_if_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, op: &P, arms: &HirVec) { if arms[0].pats.len() == 1 { let good_method = match arms[0].pats[0].node { PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { @@ -123,19 +116,14 @@ fn find_sugg_for_if_let<'a, 'tcx>( } } -fn find_sugg_for_match<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr, - op: &P, - arms: &HirVec -) { +fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, op: &P, arms: &HirVec) { if arms.len() == 2 { let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node); let found_good_method = match node_pair { ( PatKind::TupleStruct(ref path_left, ref patterns_left, _), - PatKind::TupleStruct(ref path_right, ref patterns_right, _) + PatKind::TupleStruct(ref path_right, ref patterns_right, _), ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].node, &patterns_right[0].node) { find_good_method_for_match( @@ -145,19 +133,16 @@ fn find_sugg_for_match<'a, 'tcx>( &paths::RESULT_OK, &paths::RESULT_ERR, "is_ok()", - "is_err()" + "is_err()", ) } else { None } }, - ( - PatKind::TupleStruct(ref path_left, ref patterns, _), - PatKind::Path(ref path_right) - ) | ( - PatKind::Path(ref path_left), - PatKind::TupleStruct(ref path_right, ref patterns, _) - ) if patterns.len() == 1 => { + (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right)) + | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _)) + if patterns.len() == 1 => + { if let PatKind::Wild = patterns[0].node { find_good_method_for_match( arms, @@ -166,7 +151,7 @@ fn find_sugg_for_match<'a, 'tcx>( &paths::OPTION_SOME, &paths::OPTION_NONE, "is_some()", - "is_none()" + "is_none()", ) } else { None @@ -204,7 +189,7 @@ fn find_good_method_for_match<'a>( expected_left: &[&str], expected_right: &[&str], should_be_left: &'a str, - should_be_right: &'a str + should_be_right: &'a str, ) -> Option<&'a str> { let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { (&(*arms[0].body).node, &(*arms[1].body).node) @@ -215,12 +200,10 @@ fn find_good_method_for_match<'a>( }; match body_node_pair { - (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => { - match (&lit_left.node, &lit_right.node) { - (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), - (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), - _ => None, - } + (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) { + (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), + (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), + _ => None, }, _ => None, } diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 7651c6f0a9f..2e35719d466 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index e68468d4dfe..749d6068fe1 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use regex_syntax; +use crate::consts::{constant, Constant}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashSet; -use if_chain::if_chain; use crate::syntax::ast::{LitKind, NodeId, StrStyle}; use crate::syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; -use crate::consts::{constant, Constant}; +use if_chain::if_chain; +use regex_syntax; use std::convert::TryFrom; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation @@ -159,28 +158,37 @@ fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option Option<&'static str> { - use regex_syntax::hir::HirKind::*; use regex_syntax::hir::Anchor::*; + use regex_syntax::hir::HirKind::*; - let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| match *e.kind() { - Literal(_) => true, - _ => false, - }); + let is_literal = |e: &[regex_syntax::hir::Hir]| { + e.iter().all(|e| match *e.kind() { + Literal(_) => true, + _ => false, + }) + }; match *s.kind() { - Empty | - Anchor(_) => Some("the regex is unlikely to be useful as it is"), + Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"), Literal(_) => Some("consider using `str::contains`"), - Alternation(ref exprs) => if exprs.iter().all(|e| e.kind().is_empty()) { - Some("the regex is unlikely to be useful as it is") - } else { - None + Alternation(ref exprs) => { + if exprs.iter().all(|e| e.kind().is_empty()) { + Some("the regex is unlikely to be useful as it is") + } else { + None + } }, Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) { - (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => Some("consider using `str::is_empty`"), - (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `==` on `str`s"), + (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => { + Some("consider using `str::is_empty`") + }, + (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => { + Some("consider using `==` on `str`s") + }, (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"), - (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `str::ends_with`"), + (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => { + Some("consider using `str::ends_with`") + }, _ if is_literal(exprs) => Some("consider using `str::contains`"), _ => None, }, @@ -211,14 +219,10 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo let r = &r.as_str(); let offset = if let StrStyle::Raw(n) = style { 2 + n } else { 1 }; match parser.parse(r) { - Ok(r) => if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - repl, - ); + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, "trivial regex", repl); + } }, Err(regex_syntax::Error::Parse(e)) => { span_lint( @@ -237,25 +241,16 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo ); }, Err(e) => { - span_lint( - cx, - INVALID_REGEX, - expr.span, - &format!("regex syntax error: {}", e), - ); + span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e)); }, } } } else if let Some(r) = const_str(cx, expr) { match parser.parse(&r) { - Ok(r) => if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - repl, - ); + Ok(r) => { + if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, "trivial regex", repl); + } }, Err(regex_syntax::Error::Parse(e)) => { span_lint( @@ -274,12 +269,7 @@ fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, utf8: boo ); }, Err(e) => { - span_lint( - cx, - INVALID_REGEX, - expr.span, - &format!("regex syntax error: {}", e), - ); + span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e)); }, } } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index e3016b7259b..0da44bc37a1 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -74,43 +73,46 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { const REPLACEMENTS: &[(&[&str], &str)] = &[ // Once - (&["core", "sync", "ONCE_INIT"], "Once::new()"), + (&["core", "sync", "ONCE_INIT"], "Once::new()"), // Atomic - (&["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], "AtomicBool::new(false)"), + ( + &["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], + "AtomicBool::new(false)", + ), (&["core", "sync", "atomic", "ATOMIC_ISIZE_INIT"], "AtomicIsize::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"), (&["core", "sync", "atomic", "ATOMIC_USIZE_INIT"], "AtomicUsize::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"), + (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"), // Min (&["core", "isize", "MIN"], "isize::min_value()"), - (&["core", "i8", "MIN"], "i8::min_value()"), - (&["core", "i16", "MIN"], "i16::min_value()"), - (&["core", "i32", "MIN"], "i32::min_value()"), - (&["core", "i64", "MIN"], "i64::min_value()"), - (&["core", "i128", "MIN"], "i128::min_value()"), + (&["core", "i8", "MIN"], "i8::min_value()"), + (&["core", "i16", "MIN"], "i16::min_value()"), + (&["core", "i32", "MIN"], "i32::min_value()"), + (&["core", "i64", "MIN"], "i64::min_value()"), + (&["core", "i128", "MIN"], "i128::min_value()"), (&["core", "usize", "MIN"], "usize::min_value()"), - (&["core", "u8", "MIN"], "u8::min_value()"), - (&["core", "u16", "MIN"], "u16::min_value()"), - (&["core", "u32", "MIN"], "u32::min_value()"), - (&["core", "u64", "MIN"], "u64::min_value()"), - (&["core", "u128", "MIN"], "u128::min_value()"), + (&["core", "u8", "MIN"], "u8::min_value()"), + (&["core", "u16", "MIN"], "u16::min_value()"), + (&["core", "u32", "MIN"], "u32::min_value()"), + (&["core", "u64", "MIN"], "u64::min_value()"), + (&["core", "u128", "MIN"], "u128::min_value()"), // Max (&["core", "isize", "MAX"], "isize::max_value()"), - (&["core", "i8", "MAX"], "i8::max_value()"), - (&["core", "i16", "MAX"], "i16::max_value()"), - (&["core", "i32", "MAX"], "i32::max_value()"), - (&["core", "i64", "MAX"], "i64::max_value()"), - (&["core", "i128", "MAX"], "i128::max_value()"), + (&["core", "i8", "MAX"], "i8::max_value()"), + (&["core", "i16", "MAX"], "i16::max_value()"), + (&["core", "i32", "MAX"], "i32::max_value()"), + (&["core", "i64", "MAX"], "i64::max_value()"), + (&["core", "i128", "MAX"], "i128::max_value()"), (&["core", "usize", "MAX"], "usize::max_value()"), - (&["core", "u8", "MAX"], "u8::max_value()"), - (&["core", "u16", "MAX"], "u16::max_value()"), - (&["core", "u32", "MAX"], "u32::max_value()"), - (&["core", "u64", "MAX"], "u64::max_value()"), - (&["core", "u128", "MAX"], "u128::max_value()"), + (&["core", "u8", "MAX"], "u8::max_value()"), + (&["core", "u16", "MAX"], "u16::max_value()"), + (&["core", "u32", "MAX"], "u32::max_value()"), + (&["core", "u64", "MAX"], "u64::max_value()"), + (&["core", "u128", "MAX"], "u128::max_value()"), ]; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 93a0353b2d1..892f9e57752 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext}; +use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; +use crate::rustc_errors::Applicability; use crate::syntax::ast; use crate::syntax::source_map::Span; use crate::syntax::visit::FnKind; use crate::syntax_pos::BytePos; -use crate::rustc_errors::Applicability; use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; +use if_chain::if_chain; /// **What it does:** Checks for return statements at the end of a block. /// @@ -28,11 +27,15 @@ use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, sp /// /// **Example:** /// ```rust -/// fn foo(x: usize) { return x; } +/// fn foo(x: usize) { +/// return x; +/// } /// ``` /// simplify to /// ```rust -/// fn foo(x: usize) { x } +/// fn foo(x: usize) { +/// x +/// } /// ``` declare_clippy_lint! { pub NEEDLESS_RETURN, @@ -51,21 +54,21 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// fn foo() -> String { -/// let x = String::new(); -/// x -///} +/// let x = String::new(); +/// x +/// } /// ``` /// instead, use /// ``` /// fn foo() -> String { -/// String::new() -///} +/// String::new() +/// } /// ``` declare_clippy_lint! { - pub LET_AND_RETURN, - style, - "creating a let-binding and then immediately returning it like `let x = expr; x` at \ - the end of a block" +pub LET_AND_RETURN, +style, +"creating a let-binding and then immediately returning it like `let x = expr; x` at \ + the end of a block" } /// **What it does:** Checks for unit (`()`) expressions that can be removed. @@ -79,7 +82,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// fn return_unit() -> () { () } +/// fn return_unit() -> () { +/// () +/// } /// ``` declare_clippy_lint! { pub UNUSED_UNIT, @@ -125,8 +130,10 @@ impl ReturnPass { self.check_final_expr(cx, elsexpr, None); }, // a match expr, check all arms - ast::ExprKind::Match(_, ref arms) => for arm in arms { - self.check_final_expr(cx, &arm.body, Some(arm.body.span)); + ast::ExprKind::Match(_, ref arms) => { + for arm in arms { + self.check_final_expr(cx, &arm.body, Some(arm.body.span)); + } }, _ => (), } @@ -254,8 +261,8 @@ impl EarlyLintPass for ReturnPass { ); }); } - } - _ => () + }, + _ => (), } } } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 5f8789016b5..a99f1398a26 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::utils::{get_trait_def_id, paths, span_lint}; /// **What it does:** Checks for mis-uses of the serde API. @@ -28,7 +27,6 @@ declare_clippy_lint! { "various things that will negatively affect your serde experience" } - #[derive(Copy, Clone)] pub struct Serde; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 16567535c90..caeccf0cba2 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::reexport::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::FnKind; +use crate::rustc::hir::*; +use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use crate::rustc::ty; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::source_map::Span; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; @@ -57,10 +56,10 @@ declare_clippy_lint! { /// let y = x + 1; /// ``` declare_clippy_lint! { - pub SHADOW_REUSE, - restriction, - "rebinding a name to an expression that re-uses the original value, e.g. \ - `let x = x + 1`" +pub SHADOW_REUSE, +restriction, +"rebinding a name to an expression that re-uses the original value, e.g. \ + `let x = x + 1`" } /// **What it does:** Checks for bindings that shadow other bindings already in @@ -77,7 +76,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// let x = y; let x = z; // shadows the earlier binding +/// let x = y; +/// let x = z; // shadows the earlier binding /// ``` declare_clippy_lint! { pub SHADOW_UNRELATED, @@ -199,49 +199,52 @@ fn check_pat<'a, 'tcx>( check_pat(cx, p, init, span, bindings); } }, - PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init { - if let ExprKind::Struct(_, ref efields, _) = init_struct.node { - for field in pfields { - let name = field.node.ident.name; - let efield = efields - .iter() - .find(|f| f.ident.name == name) - .map(|f| &*f.expr); - check_pat(cx, &field.node.pat, efield, span, bindings); + PatKind::Struct(_, ref pfields, _) => { + if let Some(init_struct) = init { + if let ExprKind::Struct(_, ref efields, _) = init_struct.node { + for field in pfields { + let name = field.node.ident.name; + let efield = efields.iter().find(|f| f.ident.name == name).map(|f| &*f.expr); + check_pat(cx, &field.node.pat, efield, span, bindings); + } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, init, span, bindings); + } } } else { for field in pfields { - check_pat(cx, &field.node.pat, init, span, bindings); + check_pat(cx, &field.node.pat, None, span, bindings); } } - } else { - for field in pfields { - check_pat(cx, &field.node.pat, None, span, bindings); - } }, - PatKind::Tuple(ref inner, _) => if let Some(init_tup) = init { - if let ExprKind::Tup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, Some(&tup[i]), p.span, bindings); + PatKind::Tuple(ref inner, _) => { + if let Some(init_tup) = init { + if let ExprKind::Tup(ref tup) = init_tup.node { + for (i, p) in inner.iter().enumerate() { + check_pat(cx, p, Some(&tup[i]), p.span, bindings); + } + } else { + for p in inner { + check_pat(cx, p, init, span, bindings); + } } } else { for p in inner { - check_pat(cx, p, init, span, bindings); + check_pat(cx, p, None, span, bindings); } } - } else { - for p in inner { - check_pat(cx, p, None, span, bindings); - } }, - PatKind::Box(ref inner) => if let Some(initp) = init { - if let ExprKind::Box(ref inner_init) = initp.node { - check_pat(cx, inner, Some(&**inner_init), span, bindings); + PatKind::Box(ref inner) => { + if let Some(initp) = init { + if let ExprKind::Box(ref inner_init) = initp.node { + check_pat(cx, inner, Some(&**inner_init), span, bindings); + } else { + check_pat(cx, inner, init, span, bindings); + } } else { check_pat(cx, inner, init, span, bindings); } - } else { - check_pat(cx, inner, init, span, bindings); }, PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), // PatVec(Vec>, Option>, Vec>), @@ -327,8 +330,10 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings), // ExprKind::Call // ExprKind::MethodCall - ExprKind::Array(ref v) | ExprKind::Tup(ref v) => for e in v { - check_expr(cx, e, bindings) + ExprKind::Array(ref v) | ExprKind::Tup(ref v) => { + for e in v { + check_expr(cx, e, bindings) + } }, ExprKind::If(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); @@ -369,9 +374,13 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V check_ty(cx, fty, bindings); check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings); }, - TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyKind::Tup(ref tup) => for t in tup { - check_ty(cx, t, bindings) + TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => { + check_ty(cx, mty, bindings) + }, + TyKind::Tup(ref tup) => { + for t in tup { + check_ty(cx, t, bindings) + } }, TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings), _ => (), @@ -382,11 +391,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { ExprKind::Box(ref inner) | ExprKind::AddrOf(_, ref inner) => is_self_shadow(name, inner), ExprKind::Block(ref block, _) => { - block.stmts.is_empty() - && block - .expr - .as_ref() - .map_or(false, |e| is_self_shadow(name, e)) + block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) }, ExprKind::Unary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path), diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 272047bc7cb..7bf0fea4277 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, walk_stmt, walk_block, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, Lint}; -use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; -use if_chain::if_chain; -use crate::syntax_pos::symbol::Symbol; +use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::{LitKind, NodeId}; -use crate::utils::{match_qpath, span_lint_and_then, SpanlessEq, get_enclosing_block}; +use crate::syntax_pos::symbol::Symbol; use crate::utils::sugg::Sugg; -use crate::rustc_errors::{Applicability}; +use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; +use if_chain::if_chain; /// **What it does:** Checks slow zero-filled vector initialization /// @@ -49,7 +49,9 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let mut vec1 = Vec::with_capacity(len); -/// unsafe { vec1.set_len(len); } +/// unsafe { +/// vec1.set_len(len); +/// } /// ``` declare_clippy_lint! { pub UNSAFE_VECTOR_INITIALIZATION, @@ -62,10 +64,7 @@ pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!( - SLOW_VECTOR_INITIALIZATION, - UNSAFE_VECTOR_INITIALIZATION, - ) + lint_array!(SLOW_VECTOR_INITIALIZATION, UNSAFE_VECTOR_INITIALIZATION,) } } @@ -162,11 +161,7 @@ impl Pass { } /// Search initialization for the given vector - fn search_initialization<'tcx>( - cx: &LateContext<'_, 'tcx>, - vec_alloc: VecAllocation<'tcx>, - parent_node: NodeId - ) { + fn search_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, vec_alloc: VecAllocation<'tcx>, parent_node: NodeId) { let enclosing_body = get_enclosing_block(cx, parent_node); if enclosing_body.is_none() { @@ -187,26 +182,27 @@ impl Pass { } } - fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, vec_alloc: &VecAllocation<'_>) { + fn lint_initialization<'tcx>( + cx: &LateContext<'_, 'tcx>, + initialization: &InitializationType<'tcx>, + vec_alloc: &VecAllocation<'_>, + ) { match initialization { - InitializationType::UnsafeSetLen(e) => - Self::emit_lint( - cx, - e, - vec_alloc, - "unsafe vector initialization", - UNSAFE_VECTOR_INITIALIZATION - ), - - InitializationType::Extend(e) | - InitializationType::Resize(e) => - Self::emit_lint( - cx, - e, - vec_alloc, - "slow zero-filling initialization", - SLOW_VECTOR_INITIALIZATION - ) + InitializationType::UnsafeSetLen(e) => Self::emit_lint( + cx, + e, + vec_alloc, + "unsafe vector initialization", + UNSAFE_VECTOR_INITIALIZATION, + ), + + InitializationType::Extend(e) | InitializationType::Resize(e) => Self::emit_lint( + cx, + e, + vec_alloc, + "slow zero-filling initialization", + SLOW_VECTOR_INITIALIZATION, + ), }; } @@ -215,24 +211,18 @@ impl Pass { slow_fill: &Expr, vec_alloc: &VecAllocation<'_>, msg: &str, - lint: &'static Lint + lint: &'static Lint, ) { let len_expr = Sugg::hir(cx, vec_alloc.len_expr, "len"); - span_lint_and_then( - cx, - lint, - slow_fill.span, - msg, - |db| { - db.span_suggestion_with_applicability( - vec_alloc.allocation_expr.span, - "consider replace allocation with", - format!("vec![0; {}]", len_expr), - Applicability::Unspecified - ); - } - ); + span_lint_and_then(cx, lint, slow_fill.span, msg, |db| { + db.span_suggestion_with_applicability( + vec_alloc.allocation_expr.span, + "consider replace allocation with", + format!("vec![0; {}]", len_expr), + Applicability::Unspecified, + ); + }); } } @@ -356,8 +346,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt) { if self.initialization_found { match stmt.node { - StmtKind::Expr(ref expr, _) | - StmtKind::Semi(ref expr, _) => { + StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => { self.search_slow_extend_filling(expr); self.search_slow_resize_filling(expr); self.search_unsafe_set_len(expr); @@ -374,7 +363,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_block(&mut self, block: &'tcx Block) { if self.initialization_found { if let Some(ref s) = block.stmts.get(0) { - self.visit_stmt( s) + self.visit_stmt(s) } self.initialization_found = false; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index af7ff8d938f..ff37488c839 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast; use crate::utils::{get_trait_def_id, span_lint}; +use if_chain::if_chain; /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g. /// subtracting elements in an Add impl. @@ -73,13 +72,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if let hir::ExprKind::Binary(binop, _, _) = expr.node { match binop.node { - | hir::BinOpKind::Eq + hir::BinOpKind::Eq | hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Ne | hir::BinOpKind::Ge - | hir::BinOpKind::Gt - => return, + | hir::BinOpKind::Gt => return, _ => {}, } // Check if the binary expression is part of another bi/unary expression @@ -97,9 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { parent_expr = cx.tcx.hir.get_parent_node(parent_expr); } // as a parent node - let mut visitor = BinaryExprVisitor { - in_binary_expr: false, - }; + let mut visitor = BinaryExprVisitor { in_binary_expr: false }; walk_expr(&mut visitor, expr); if visitor.in_binary_expr { @@ -122,10 +118,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { cx, SUSPICIOUS_ARITHMETIC_IMPL, binop.span, - &format!( - r#"Suspicious use of binary operator in `{}` impl"#, - impl_trait - ), + &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait), ); } @@ -162,10 +155,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { cx, SUSPICIOUS_OP_ASSIGN_IMPL, binop.span, - &format!( - r#"Suspicious use of binary operator in `{}` impl"#, - impl_trait - ), + &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait), ); } } @@ -218,9 +208,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for BinaryExprVisitor { match expr.node { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot, _) - | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => { - self.in_binary_expr = true - }, + | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => self.in_binary_expr = true, _ => {}, } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 77a33e9eebb..a93ff124052 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -7,16 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use matches::matches; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty; -use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq}; -use crate::utils::sugg::Sugg; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; +use crate::utils::sugg::Sugg; +use crate::utils::{ + differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq, +}; +use if_chain::if_chain; +use matches::matches; /// **What it does:** Checks for manual swapping. /// diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 292bf9fb6a4..c25b0cf7661 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::{Expr, ExprKind}; use crate::utils::is_adjusted; use crate::utils::span_lint; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 801b6db63f5..65d8e33ce7b 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; use crate::rustc::ty::{self, Ty}; -use crate::rustc::hir::*; -use std::borrow::Cow; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast; use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use crate::utils::{opt_def_id, sugg}; -use crate::rustc_errors::Applicability; +use if_chain::if_chain; +use std::borrow::Cow; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. @@ -65,7 +64,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// core::intrinsics::transmute(t) // where the result type is the same as -/// // `*t` or `&t`'s +/// // `*t` or `&t`'s /// ``` declare_clippy_lint! { pub CROSSPOINTER_TRANSMUTE, @@ -82,7 +81,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: &T = std::mem::transmute(p); // where p: *const T -/// // can be written: +/// // can be written: /// let _: &T = &*p; /// ``` declare_clippy_lint! { @@ -109,7 +108,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: char = std::mem::transmute(x); // where x: u32 -/// // should be: +/// // should be: /// let _ = std::char::from_u32(x).unwrap(); /// ``` declare_clippy_lint! { @@ -136,7 +135,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: &str = std::mem::transmute(b); // where b: &[u8] -/// // should be: +/// // should be: /// let _ = std::str::from_utf8(b).unwrap(); /// ``` declare_clippy_lint! { @@ -154,7 +153,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: bool = std::mem::transmute(x); // where x: u8 -/// // should be: +/// // should be: /// let _: bool = x != 0; /// ``` declare_clippy_lint! { @@ -172,7 +171,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: f32 = std::mem::transmute(x); // where x: u32 -/// // should be: +/// // should be: /// let _: f32 = f32::from_bits(x); /// ``` declare_clippy_lint! { @@ -248,43 +247,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { USELESS_TRANSMUTE, e.span, "transmute from a reference to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let rty_and_mut = ty::TypeAndMut { ty: rty, mutbl: rty_mutbl }; + |db| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let rty_and_mut = ty::TypeAndMut { + ty: rty, + mutbl: rty_mutbl, + }; - let sugg = if ptr_ty == rty_and_mut { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) - }; + let sugg = if ptr_ty == rty_and_mut { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) + }; - db.span_suggestion_with_applicability( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); + } }, ), - (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { db.span_suggestion_with_applicability( e.span, "try", arg.as_ty(&to_ty.to_string()).to_string(), Applicability::Unspecified, ); - }, - ) - }, - (&ty::Float(_), &ty::Ref(..)) | - (&ty::Float(_), &ty::RawPtr(_)) | - (&ty::Char, &ty::Ref(..)) | - (&ty::Char, &ty::RawPtr(_)) => span_lint( + } + }, + ), + (&ty::Float(_), &ty::Ref(..)) + | (&ty::Float(_), &ty::RawPtr(_)) + | (&ty::Char, &ty::Ref(..)) + | (&ty::Char, &ty::RawPtr(_)) => span_lint( cx, WRONG_TRANSMUTE, e.span, @@ -296,8 +300,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!( "transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty + from_ty, to_ty ), ), (_, &ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( @@ -306,8 +309,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!( "transmute from a type (`{}`) to a pointer to that type (`{}`)", - from_ty, - to_ty + from_ty, to_ty ), ), (&ty::RawPtr(from_pty), &ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( @@ -317,8 +319,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { &format!( "transmute from a pointer type (`{}`) to a reference type \ (`{}`)", - from_ty, - to_ty + from_ty, to_ty ), |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); @@ -342,27 +343,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::Int(ast::IntTy::I32), &ty::Char) | - (&ty::Uint(ast::UintTy::U32), &ty::Char) => span_lint_and_then( - cx, - TRANSMUTE_INT_TO_CHAR, - e.span, - &format!("transmute from a `{}` to a `char`", from_ty), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::Int(_) = from_ty.sty { - arg.as_ty(ty::Uint(ast::UintTy::U32)) - } else { - arg - }; - db.span_suggestion_with_applicability( - e.span, - "consider using", - format!("std::char::from_u32({}).unwrap()", arg.to_string()), - Applicability::Unspecified, - ); - }, - ), + (&ty::Int(ast::IntTy::I32), &ty::Char) | (&ty::Uint(ast::UintTy::U32), &ty::Char) => { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_CHAR, + e.span, + &format!("transmute from a `{}` to a `char`", from_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::Int(_) = from_ty.sty { + arg.as_ty(ty::Uint(ast::UintTy::U32)) + } else { + arg + }; + db.span_suggestion_with_applicability( + e.span, + "consider using", + format!("std::char::from_u32({}).unwrap()", arg.to_string()), + Applicability::Unspecified, + ); + }, + ) + }, (&ty::Ref(_, ty_from, from_mutbl), &ty::Ref(_, ty_to, to_mutbl)) => { if_chain! { if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.sty, &ty_to.sty); @@ -401,9 +403,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, "transmute from a reference to a reference", |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, mutbl: from_mutbl }; + let ty_from_and_mut = ty::TypeAndMut { + ty: ty_from, + mutbl: from_mutbl + }; let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl }; - let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(ty_from_and_mut)).as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + let sugg_paren = arg + .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) + .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); let sugg = if to_mutbl == Mutability::MutMutable { sugg_paren.mut_addr_deref() } else { @@ -426,14 +433,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { TRANSMUTE_PTR_TO_PTR, e.span, "transmute from a pointer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); - db.span_suggestion_with_applicability( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + |db| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); + db.span_suggestion_with_applicability( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); + } }, ), (&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => { @@ -454,33 +463,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }, ) }, - (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => { - span_lint_and_then( - cx, - TRANSMUTE_INT_TO_FLOAT, - e.span, - &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::Int(int_ty) = from_ty.sty { - arg.as_ty(format!( - "u{}", - int_ty - .bit_width() - .map_or_else(|| "size".to_string(), |v| v.to_string()) - )) - } else { - arg - }; - db.span_suggestion_with_applicability( - e.span, - "consider using", - format!("{}::from_bits({})", to_ty, arg.to_string()), - Applicability::Unspecified, - ); - }, - ) - }, + (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => span_lint_and_then( + cx, + TRANSMUTE_INT_TO_FLOAT, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::Int(int_ty) = from_ty.sty { + arg.as_ty(format!( + "u{}", + int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string()) + )) + } else { + arg + }; + db.span_suggestion_with_applicability( + e.span, + "consider using", + format!("{}::from_bits({})", to_ty, arg.to_string()), + Applicability::Unspecified, + ); + }, + ), _ => return, }; } diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 836f84e8966..587b9b731c3 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::cmp; use crate::rustc::hir; @@ -82,11 +81,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { Self { limit } } - fn check_trait_method( - &mut self, - cx: &LateContext<'_, 'tcx>, - item: &TraitItemRef - ) { + fn check_trait_method(&mut self, cx: &LateContext<'_, 'tcx>, item: &TraitItemRef) { let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id); let method_sig = cx.tcx.fn_sig(method_def_id); let method_sig = cx.tcx.erase_late_bound_regions(&method_sig); @@ -99,13 +94,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { self.check_poly_fn(cx, &decl, &method_sig, None); } - fn check_poly_fn( - &mut self, - cx: &LateContext<'_, 'tcx>, - decl: &FnDecl, - sig: &FnSig<'tcx>, - span: Option, - ) { + fn check_poly_fn(&mut self, cx: &LateContext<'_, 'tcx>, decl: &FnDecl, sig: &FnSig<'tcx>, span: Option) { // Use lifetimes to determine if we're returning a reference to the // argument. In that case we can't switch to pass-by-value as the // argument will not live long enough. @@ -149,13 +138,9 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { } } - fn check_trait_items( - &mut self, - cx: &LateContext<'_, '_>, - trait_items: &[TraitItemRef] - ) { + fn check_trait_items(&mut self, cx: &LateContext<'_, '_>, trait_items: &[TraitItemRef]) { for item in trait_items { - if let AssociatedItemKind::Method{..} = item.kind { + if let AssociatedItemKind::Method { .. } = item.kind { self.check_trait_method(cx, item); } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 61f294e1f3c..6d5dbfe0713 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -117,10 +117,10 @@ declare_clippy_lint! { /// let x = LinkedList::new(); /// ``` declare_clippy_lint! { - pub LINKEDLIST, - pedantic, - "usage of LinkedList, usually a vector is faster, or a more specialized data \ - structure like a VecDeque" +pub LINKEDLIST, +pedantic, +"usage of LinkedList, usually a vector is faster, or a more specialized data \ + structure like a VecDeque" } /// **What it does:** Checks for use of `&Box` anywhere in the code. @@ -245,7 +245,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { OPTION_OPTION, ast_ty.span, "consider using `Option` instead of `Option>` or a custom \ - enum if you need to distinguish all 3 cases", + enum if you need to distinguish all 3 cases", ); return; // don't recurse into the type } @@ -275,16 +275,18 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { check_ty(cx, ty, is_local); } }, - QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| { - seg.args - .as_ref() - .map_or_else(|| [].iter(), |params| params.args.iter()) - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - GenericArg::Lifetime(_) => None, - }) - }) { - check_ty(cx, ty, is_local); + QPath::Resolved(None, ref p) => { + for ty in p.segments.iter().flat_map(|seg| { + seg.args + .as_ref() + .map_or_else(|| [].iter(), |params| params.args.iter()) + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }) + }) { + check_ty(cx, ty, is_local); + } }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); @@ -301,9 +303,13 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { }, TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty), // recurse - TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), - TyKind::Tup(ref tys) => for ty in tys { - check_ty(cx, ty, is_local); + TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => { + check_ty(cx, ty, is_local) + }, + TyKind::Tup(ref tys) => { + for ty in tys { + check_ty(cx, ty, is_local); + } }, _ => {}, } @@ -348,7 +354,12 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: ast_ty.span, "you seem to be trying to use `&Box`. Consider using just `&T`", "try", - format!("&{}{}{}", ltopt, mutopt, &snippet_with_applicability(cx, inner.span, "..", &mut applicability)), + format!( + "&{}{}{}", + ltopt, + mutopt, + &snippet_with_applicability(cx, inner.span, "..", &mut applicability) + ), Applicability::Unspecified, ); return; // don't recurse into the type @@ -387,7 +398,9 @@ pub struct LetPass; /// /// **Example:** /// ```rust -/// let x = { 1; }; +/// let x = { +/// 1; +/// }; /// ``` declare_clippy_lint! { pub LET_UNIT_VALUE, @@ -439,11 +452,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass { /// /// **Example:** /// ```rust -/// if { foo(); } == { bar(); } { baz(); } +/// if { +/// foo(); +/// } == { +/// bar(); +/// } { +/// baz(); +/// } /// ``` /// is equal to /// ```rust -/// { foo(); bar(); baz(); } +/// { +/// foo(); +/// bar(); +/// baz(); +/// } /// ``` declare_clippy_lint! { pub UNIT_CMP, @@ -486,7 +509,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { } } -/// **What it does:** Checks for passing a unit value as an argument to a function without using a unit literal (`()`). +/// **What it does:** Checks for passing a unit value as an argument to a function without using a +/// unit literal (`()`). /// /// **Why is this bad?** This is likely the result of an accidental semicolon. /// @@ -495,8 +519,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { /// **Example:** /// ```rust /// foo({ -/// let a = bar(); -/// baz(a); +/// let a = bar(); +/// baz(a); /// }) /// ``` declare_clippy_lint! { @@ -528,7 +552,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { // only the calls to `Try::from_error` is marked as desugared, // so we need to check both the current Expr and its parent. if !is_questionmark_desugar_marked_call(expr) { - if_chain!{ + if_chain! { let opt_parent_node = map.find(map.get_parent_node(expr.id)); if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; if is_questionmark_desugar_marked_call(parent_expr); @@ -597,7 +621,8 @@ pub struct CastPass; /// /// **Example:** /// ```rust -/// let x = u64::MAX; x as f64 +/// let x = u64::MAX; +/// x as f64 /// ``` declare_clippy_lint! { pub CAST_PRECISION_LOSS, @@ -618,7 +643,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let y: i8 = -1; -/// y as u128 // will return 18446744073709551615 +/// y as u128 // will return 18446744073709551615 /// ``` declare_clippy_lint! { pub CAST_SIGN_LOSS, @@ -638,13 +663,15 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// fn as_u8(x: u64) -> u8 { x as u8 } +/// fn as_u8(x: u64) -> u8 { +/// x as u8 +/// } /// ``` declare_clippy_lint! { - pub CAST_POSSIBLE_TRUNCATION, - pedantic, - "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, \ - or `x as i32` where `x: f32`" +pub CAST_POSSIBLE_TRUNCATION, +pedantic, +"casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, \ + or `x as i32` where `x: f32`" } /// **What it does:** Checks for casts from an unsigned type to a signed type of @@ -662,13 +689,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// u32::MAX as i32 // will yield a value of `-1` +/// u32::MAX as i32 // will yield a value of `-1` /// ``` declare_clippy_lint! { - pub CAST_POSSIBLE_WRAP, - pedantic, - "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` \ - and `x > i32::MAX`" +pub CAST_POSSIBLE_WRAP, +pedantic, +"casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` \ + and `x > i32::MAX`" } /// **What it does:** Checks for on casts between numerical types that may @@ -685,13 +712,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust -/// fn as_u64(x: u8) -> u64 { x as u64 } +/// fn as_u64(x: u8) -> u64 { +/// x as u64 +/// } /// ``` /// /// Using `::from` would look like this: /// /// ```rust -/// fn as_u64(x: u8) -> u64 { u64::from(x) } +/// fn as_u64(x: u8) -> u64 { +/// u64::from(x) +/// } /// ``` declare_clippy_lint! { pub CAST_LOSSLESS, @@ -773,11 +804,15 @@ declare_clippy_lint! { /// /// ```rust /// // Bad -/// fn fn1() -> i16 { 1 }; +/// fn fn1() -> i16 { +/// 1 +/// }; /// let _ = fn1 as i32; /// /// // Better: Cast to usize first, then comment with the reason for the truncation -/// fn fn2() -> i16 { 1 }; +/// fn fn2() -> i16 { +/// 1 +/// }; /// let fn_ptr = fn2 as usize; /// let fn_ptr_truncated = fn_ptr as i32; /// ``` @@ -838,11 +873,7 @@ fn span_precision_loss_lint(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty is only {4} bits wide)", cast_from, if cast_to_f64 { "f64" } else { "f32" }, - if arch_dependent { - arch_dependent_str - } else { - "" - }, + if arch_dependent { arch_dependent_str } else { "" }, from_nbits_str, mantissa_nbits ), @@ -860,7 +891,9 @@ fn should_strip_parens(op: &Expr, snip: &str) -> bool { fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { // Do not suggest using From in consts/statics until it is valid to do so (see #2267). - if in_constant(cx, expr.id) { return } + if in_constant(cx, expr.id) { + return; + } // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. let mut applicability = Applicability::MachineApplicable; @@ -880,7 +913,10 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro cx, CAST_LOSSLESS, expr.span, - &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to), + &format!( + "casting {} to {} may become silently lossy if types change", + cast_from, cast_to + ), "try", format!("{}::from({})", cast_to, sugg), applicability, @@ -999,13 +1035,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { use crate::syntax::ast::{LitIntType, LitKind}; match lit.node { LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, - _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) { - span_lint( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), - ); + _ => { + if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) { + span_lint( + cx, + UNNECESSARY_CAST, + expr.span, + &format!( + "casting to the same type is unnecessary (`{}` -> `{}`)", + cast_from, cast_to + ), + ); + } }, } } @@ -1054,8 +1095,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { check_lossless(cx, expr, ex, cast_from, cast_to); }, (false, false) => { - if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) - { + if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { span_lint( cx, CAST_POSSIBLE_TRUNCATION, @@ -1063,15 +1103,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { "casting f64 to f32 may truncate the value", ); } - if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) - { + if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) { span_lossless_lint(cx, expr, ex, cast_from, cast_to); } }, } } - if_chain!{ + if_chain! { if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi); @@ -1095,11 +1134,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } } -fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn lint_fn_to_numeric_cast( + cx: &LateContext<'_, '_>, + expr: &Expr, + cast_expr: &Expr, + cast_from: Ty<'_>, + cast_to: Ty<'_>, +) { // We only want to check casts to `ty::Uint` or `ty::Int` match cast_to.sty { ty::Uint(_) | ty::Int(..) => { /* continue on */ }, - _ => return + _ => return, } match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { @@ -1112,12 +1157,14 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex cx, FN_TO_NUMERIC_CAST_WITH_TRUNCATION, expr.span, - &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to), + &format!( + "casting function pointer `{}` to `{}`, which truncates the value", + from_snippet, cast_to + ), "try", format!("{} as usize", from_snippet), applicability, ); - } else if cast_to.sty != ty::Uint(UintTy::Usize) { span_lint_and_sugg( cx, @@ -1130,7 +1177,7 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex ); } }, - _ => {} + _ => {}, } } @@ -1144,7 +1191,9 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex /// /// **Example:** /// ```rust -/// struct Foo { inner: Rc>>> } +/// struct Foo { +/// inner: Rc>>>, +/// } /// ``` declare_clippy_lint! { pub TYPE_COMPLEXITY, @@ -1158,9 +1207,7 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { - Self { - threshold, - } + Self { threshold } } } @@ -1272,12 +1319,12 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), TyKind::TraitObject(ref param_bounds, _) => { - let has_lifetime_parameters = param_bounds - .iter() - .any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind { + let has_lifetime_parameters = param_bounds.iter().any(|bound| { + bound.bound_generic_params.iter().any(|gen| match gen.kind { GenericParamKind::Lifetime { .. } => true, _ => false, - })); + }) + }); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) @@ -1345,7 +1392,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { let msg = "casting character literal to u8. `char`s \ are 4 bytes wide in rust, so casting to u8 \ truncates them"; - let help = format!("Consider using a byte literal instead:\nb{}", snippet(cx, e.span, "'x'")); + let help = format!( + "Consider using a byte literal instead:\nb{}", + snippet(cx, e.span, "'x'") + ); span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help); } } @@ -1405,17 +1455,12 @@ enum AbsurdComparisonResult { InequalityImpossible, } - -fn is_cast_between_fixed_and_target<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr -) -> bool { - +fn is_cast_between_fixed_and_target<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { if let ExprKind::Cast(ref cast_exp, _) = expr.node { let precast_ty = cx.tables.expr_ty(cast_exp); let cast_ty = cx.tables.expr_ty(expr); - return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty) + return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty); } false @@ -1427,8 +1472,8 @@ fn detect_absurd_comparison<'a, 'tcx>( lhs: &'tcx Expr, rhs: &'tcx Expr, ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { - use crate::types::ExtremeType::*; use crate::types::AbsurdComparisonResult::*; + use crate::types::ExtremeType::*; use crate::utils::comparisons::*; // absurd comparison only makes sense on primitive types @@ -1481,26 +1526,30 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) - let cv = constant(cx, cx.tables, expr)?.0; let which = match (&ty.sty, cv) { - (&ty::Bool, Constant::Bool(false)) | - (&ty::Uint(_), Constant::Int(0)) => Minimum, - (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum, + (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum, + (&ty::Int(ity), Constant::Int(i)) + if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => + { + Minimum + }, (&ty::Bool, Constant::Bool(true)) => Maximum, - (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum, + (&ty::Int(ity), Constant::Int(i)) + if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => + { + Maximum + }, (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum, _ => return None, }; - Some(ExtremeExpr { - which, - expr, - }) + Some(ExtremeExpr { which, expr }) } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - use crate::types::ExtremeType::*; use crate::types::AbsurdComparisonResult::*; + use crate::types::ExtremeType::*; if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node { if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { @@ -1586,8 +1635,7 @@ impl FullInt { impl PartialEq for FullInt { fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other) - .expect("partial_cmp only returns Some(_)") == Ordering::Equal + self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal } } @@ -1608,7 +1656,6 @@ impl Ord for FullInt { } } - fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> { use crate::syntax::ast::{IntTy, UintTy}; use std::*; @@ -1622,7 +1669,10 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> } match pre_cast_ty.sty { ty::Int(int_ty) => Some(match int_ty { - IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), + IntTy::I8 => ( + FullInt::S(i128::from(i8::min_value())), + FullInt::S(i128::from(i8::max_value())), + ), IntTy::I16 => ( FullInt::S(i128::from(i16::min_value())), FullInt::S(i128::from(i16::max_value())), @@ -1636,10 +1686,16 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> FullInt::S(i128::from(i64::max_value())), ), IntTy::I128 => (FullInt::S(i128::min_value()), FullInt::S(i128::max_value())), - IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), + IntTy::Isize => ( + FullInt::S(isize::min_value() as i128), + FullInt::S(isize::max_value() as i128), + ), }), ty::Uint(uint_ty) => Some(match uint_ty { - UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), + UintTy::U8 => ( + FullInt::U(u128::from(u8::min_value())), + FullInt::U(u128::from(u8::max_value())), + ), UintTy::U16 => ( FullInt::U(u128::from(u16::min_value())), FullInt::U(u128::from(u16::max_value())), @@ -1653,7 +1709,10 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> FullInt::U(u128::from(u64::max_value())), ), UintTy::U128 => (FullInt::U(u128::min_value()), FullInt::U(u128::max_value())), - UintTy::Usize => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), + UintTy::Usize => ( + FullInt::U(usize::min_value() as u128), + FullInt::U(usize::max_value() as u128), + ), }), _ => None, } @@ -1708,29 +1767,37 @@ fn upcast_comparison_bounds_err<'a, 'tcx>( err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } }, - Rel::Le => if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } }, Rel::Eq | Rel::Ne => unreachable!(), } { err_upcast_comparison(cx, span, lhs, true) } else if match rel { - Rel::Lt => if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } }, - Rel::Le => if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } }, Rel::Eq | Rel::Ne => unreachable!(), } { @@ -1874,7 +1941,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { cx, IMPLICIT_HASHER, target.span(), - &format!("impl for `{}` should be generalized over different hashers", target.type_name()), + &format!( + "impl for `{}` should be generalized over different hashers", + target.type_name() + ), move |db| { suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis); }, @@ -1931,11 +2001,19 @@ impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a BuildHasher. fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option { if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node { - let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()? - .args.iter().filter_map(|arg| match arg { + let params: Vec<_> = path + .segments + .last() + .as_ref()? + .args + .as_ref()? + .args + .iter() + .filter_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), GenericArg::Lifetime(_) => None, - }).collect(); + }) + .collect(); let params_len = params.len(); let ty = hir_ty_to_ty(cx.tcx, hir_ty); @@ -1948,7 +2026,11 @@ impl<'tcx> ImplicitHasherType<'tcx> { snippet(cx, params[1].span, "V"), )) } else if match_path(path, &paths::HASHSET) && params_len == 1 { - Some(ImplicitHasherType::HashSet(hir_ty.span, ty, snippet(cx, params[0].span, "T"))) + Some(ImplicitHasherType::HashSet( + hir_ty.span, + ty, + snippet(cx, params[0].span, "T"), + )) } else { None } diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index a140b567f01..bb384891926 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; use crate::syntax::ast::{LitKind, NodeId}; use crate::syntax::source_map::Span; -use unicode_normalization::UnicodeNormalization; use crate::utils::{is_allowed, snippet, span_help_and_lint}; +use unicode_normalization::UnicodeNormalization; /// **What it does:** Checks for the Unicode zero-width space in the code. /// @@ -46,10 +45,10 @@ declare_clippy_lint! { /// let x = "Hä?" /// ``` declare_clippy_lint! { - pub NON_ASCII_LITERAL, - pedantic, - "using any literal non-ASCII chars in a string literal instead of \ - using the `\\u` escape" +pub NON_ASCII_LITERAL, +pedantic, +"using any literal non-ASCII chars in a string literal instead of \ + using the `\\u` escape" } /// **What it does:** Checks for string literals that contain Unicode in a form @@ -64,13 +63,12 @@ declare_clippy_lint! { /// **Example:** You may not see it, but “à” and “à” aren't the same string. The /// former when escaped is actually `"a\u{300}"` while the latter is `"\u{e0}"`. declare_clippy_lint! { - pub UNICODE_NOT_NFC, - pedantic, - "using a unicode literal not in NFC normal form (see \ - [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" +pub UNICODE_NOT_NFC, +pedantic, +"using a unicode literal not in NFC normal form (see \ + [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } - #[derive(Copy, Clone)] pub struct Unicode; @@ -140,7 +138,10 @@ fn check_str(cx: &LateContext<'_, '_>, span: Span, id: NodeId) { UNICODE_NOT_NFC, span, "non-nfc unicode sequence detected", - &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::()), + &format!( + "Consider replacing the string with:\n\"{}\"", + string.nfc().collect::() + ), ); } } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index cd9d649ed0a..ce07e48eaf0 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::*; @@ -62,14 +61,13 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) { .expect("use paths cannot be empty") .ident; unsafe_to_safe_check(old_name, new_name, cx, span); - } - UseTreeKind::Simple(None, ..) | - UseTreeKind::Glob => {}, + }, + UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {}, UseTreeKind::Nested(ref nested_use_tree) => { for &(ref use_tree, _) in nested_use_tree { check_use_tree(use_tree, cx, span); } - } + }, } } @@ -81,7 +79,10 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, cx, UNSAFE_REMOVED_FROM_NAME, span, - &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str), + &format!( + "removed \"unsafe\" from the name of `{}` in use as `{}`", + old_str, new_str + ), ); } } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1bb819a74e3..af2d742b2db 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir; use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; /// **What it does:** Checks for unused written/read amount. diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 0b2237ac22b..ed4a9578440 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -7,11 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; use crate::syntax::ast; use crate::syntax::source_map::Span; @@ -80,8 +79,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprKind::Break(destination, _) | hir::ExprKind::Continue(destination) => if let Some(label) = destination.label { - self.labels.remove(&label.ident.as_str()); + hir::ExprKind::Break(destination, _) | hir::ExprKind::Continue(destination) => { + if let Some(label) = destination.label { + self.labels.remove(&label.ident.as_str()); + } }, hir::ExprKind::Loop(_, Some(label), _) | hir::ExprKind::While(_, _, Some(label)) => { self.labels.insert(label.ident.as_str(), expr.span); diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f7a2d0805fa..6e9b70f3003 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; -use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use crate::rustc::hir::intravisit::*; use crate::rustc::hir::*; use crate::syntax::ast::NodeId; use crate::syntax::source_map::Span; +use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; /// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail. /// diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 564bdb0bb03..3a71a6d04af 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -88,11 +87,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { let impl_ty = self.impl_type_walker.next(); if let TyKind::Path(QPath::Resolved(_, path)) = &t.node { - // The implementation and trait types don't match which means that // the concrete type was specified by the implementation if impl_ty != trait_ty { - if let Some(impl_ty) = impl_ty { if self.item_type == impl_ty { let is_self_ty = if let def::Def::SelfTy(..) = path.def { @@ -106,7 +103,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { } } } - } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index d88a70e4e49..7e09eae1e93 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -7,15 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; -use crate::rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt}; use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use crate::rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::FxHashMap; use crate::syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; use crate::utils::get_attr; @@ -40,7 +39,7 @@ use crate::utils::get_attr; /// /// ```rust /// // ./tests/ui/new_lint.stdout -/// if_chain!{ +/// if_chain! { /// if let ExprKind::If(ref cond, ref then, None) = item.node, /// if let ExprKind::Binary(BinOp::Eq, ref left, ref right) = cond.node, /// if let ExprKind::Path(ref path) = left.node, @@ -248,7 +247,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let op_pat = self.next("op"); let left_pat = self.next("left"); let right_pat = self.next("right"); - println!("Binary(ref {}, ref {}, ref {}) = {};", op_pat, left_pat, right_pat, current); + println!( + "Binary(ref {}, ref {}, ref {}) = {};", + op_pat, left_pat, right_pat, current + ); println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat); self.current = left_pat; self.visit_expr(left); @@ -311,7 +313,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let then_pat = self.next("then"); if let Some(ref else_) = *opt_else { let else_pat = self.next("else_"); - println!("If(ref {}, ref {}, Some(ref {})) = {};", cond_pat, then_pat, else_pat, current); + println!( + "If(ref {}, ref {}, Some(ref {})) = {};", + cond_pat, then_pat, else_pat, current + ); self.current = else_pat; self.visit_expr(else_); } else { @@ -326,7 +331,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let cond_pat = self.next("cond"); let body_pat = self.next("body"); let label_pat = self.next("label"); - println!("While(ref {}, ref {}, ref {}) = {};", cond_pat, body_pat, label_pat, current); + println!( + "While(ref {}, ref {}, ref {}) = {};", + cond_pat, body_pat, label_pat, current + ); self.current = cond_pat; self.visit_expr(cond); self.current = body_pat; @@ -360,7 +368,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat); self.current = if_expr_pat; self.visit_expr(if_expr); - } + }, } } println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len()); @@ -399,7 +407,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let op_pat = self.next("op"); let target_pat = self.next("target"); let value_pat = self.next("value"); - println!("AssignOp(ref {}, ref {}, ref {}) = {};", op_pat, target_pat, value_pat, current); + println!( + "AssignOp(ref {}, ref {}, ref {}) = {};", + op_pat, target_pat, value_pat, current + ); println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat); self.current = target_pat; self.visit_expr(target); @@ -452,13 +463,15 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Again(ref {}) = {};", destination_pat, current); // FIXME: implement label printing }, - ExprKind::Ret(ref opt_value) => if let Some(ref value) = *opt_value { - let value_pat = self.next("value"); - println!("Ret(Some(ref {})) = {};", value_pat, current); - self.current = value_pat; - self.visit_expr(value); - } else { - println!("Ret(None) = {};", current); + ExprKind::Ret(ref opt_value) => { + if let Some(ref value) = *opt_value { + let value_pat = self.next("value"); + println!("Ret(Some(ref {})) = {};", value_pat, current); + self.current = value_pat; + self.visit_expr(value); + } else { + println!("Ret(None) = {};", current); + } }, ExprKind::InlineAsm(_, ref _input, ref _output) => { println!("InlineAsm(_, ref input, ref output) = {};", current); @@ -471,10 +484,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let base_pat = self.next("base"); println!( "Struct(ref {}, ref {}, Some(ref {})) = {};", - path_pat, - fields_pat, - base_pat, - current + path_pat, fields_pat, base_pat, current ); self.current = base_pat; self.visit_expr(base); @@ -512,27 +522,36 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let name_pat = self.next("name"); if let Some(ref sub) = *sub { let sub_pat = self.next("sub"); - println!("Binding({}, _, {}, Some(ref {})) = {};", anno_pat, name_pat, sub_pat, current); + println!( + "Binding({}, _, {}, Some(ref {})) = {};", + anno_pat, name_pat, sub_pat, current + ); self.current = sub_pat; self.visit_pat(sub); } else { println!("Binding({}, _, {}, None) = {};", anno_pat, name_pat, current); } println!(" if {}.node.as_str() == \"{}\";", name_pat, ident.as_str()); - } + }, PatKind::Struct(ref path, ref fields, ignore) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); - println!("Struct(ref {}, ref {}, {}) = {};", path_pat, fields_pat, ignore, current); + println!( + "Struct(ref {}, ref {}, {}) = {};", + path_pat, fields_pat, ignore, current + ); self.current = path_pat; self.print_qpath(path); println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); - } + }, PatKind::TupleStruct(ref path, ref fields, skip_pos) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); - println!("TupleStruct(ref {}, ref {}, {:?}) = {};", path_pat, fields_pat, skip_pos, current); + println!( + "TupleStruct(ref {}, ref {}, {:?}) = {};", + path_pat, fields_pat, skip_pos, current + ); self.current = path_pat; self.print_qpath(path); println!(" if {}.len() == {};", fields_pat, fields.len()); @@ -543,13 +562,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Path(ref {}) = {};", path_pat, current); self.current = path_pat; self.print_qpath(path); - } + }, PatKind::Tuple(ref fields, skip_pos) => { let fields_pat = self.next("fields"); println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current); println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); - } + }, PatKind::Box(ref pat) => { let pat_pat = self.next("pat"); println!("Box(ref {}) = {};", pat_pat, current); @@ -567,22 +586,28 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Lit(ref {}) = {}", lit_expr_pat, current); self.current = lit_expr_pat; self.visit_expr(lit_expr); - } + }, PatKind::Range(ref start, ref end, end_kind) => { let start_pat = self.next("start"); let end_pat = self.next("end"); - println!("Range(ref {}, ref {}, RangeEnd::{:?}) = {};", start_pat, end_pat, end_kind, current); + println!( + "Range(ref {}, ref {}, RangeEnd::{:?}) = {};", + start_pat, end_pat, end_kind, current + ); self.current = start_pat; self.visit_expr(start); self.current = end_pat; self.visit_expr(end); - } + }, PatKind::Slice(ref start, ref middle, ref end) => { let start_pat = self.next("start"); let end_pat = self.next("end"); if let Some(ref middle) = middle { let middle_pat = self.next("middle"); - println!("Slice(ref {}, Some(ref {}), ref {}) = {};", start_pat, middle_pat, end_pat, current); + println!( + "Slice(ref {}, Some(ref {}), ref {}) = {};", + start_pat, middle_pat, end_pat, current + ); self.current = middle_pat; self.visit_pat(middle); } else { @@ -598,7 +623,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = format!("{}[{}]", end_pat, i); self.visit_pat(pat); } - } + }, } } @@ -631,7 +656,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Item(item_id) = {};", current); }, } - } + }, // Expr without trailing semi-colon (must have unit type): StmtKind::Expr(ref e, _) => { @@ -666,7 +691,10 @@ fn desugaring_name(des: hir::MatchSource) -> String { hir::MatchSource::TryDesugar => "MatchSource::TryDesugar".to_string(), hir::MatchSource::WhileLetDesugar => "MatchSource::WhileLetDesugar".to_string(), hir::MatchSource::Normal => "MatchSource::Normal".to_string(), - hir::MatchSource::IfLetDesugar { contains_else_clause } => format!("MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", contains_else_clause), + hir::MatchSource::IfLetDesugar { contains_else_clause } => format!( + "MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", + contains_else_clause + ), } } @@ -680,13 +708,15 @@ fn loop_desugaring_name(des: hir::LoopSource) -> &'static str { fn print_path(path: &QPath, first: &mut bool) { match *path { - QPath::Resolved(_, ref path) => for segment in &path.segments { - if *first { - *first = false; - } else { - print!(", "); + QPath::Resolved(_, ref path) => { + for segment in &path.segments { + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.ident.as_str()); } - print!("{:?}", segment.ident.as_str()); }, QPath::TypeRelative(ref ty, ref segment) => match ty.node { hir::TyKind::Path(ref inner_path) => { diff --git a/clippy_lints/src/utils/camel_case.rs b/clippy_lints/src/utils/camel_case.rs index 5ce1e08d8b5..f58f3e3b98a 100644 --- a/clippy_lints/src/utils/camel_case.rs +++ b/clippy_lints/src/utils/camel_case.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - /// Return the index of the character after the first camel-case component of /// `s`. pub fn until(s: &str) -> usize { diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index 986802107c0..05636e3234b 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Utility functions about comparison operators. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index faf4e2702f0..aa302500abf 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Read configurations files. #![deny(clippy::missing_docs_in_private_items)] +use crate::syntax::{ast, source_map}; use lazy_static::lazy_static; use std::default::Default; -use std::{env, fmt, fs, io, path}; use std::io::Read; -use crate::syntax::{ast, source_map}; -use toml; use std::sync::Mutex; +use std::{env, fmt, fs, io, path}; +use toml; /// Get the configuration file from arguments. pub fn file_from_args( @@ -30,10 +29,12 @@ pub fn file_from_args( ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { Err(("`conf_file` must be a named value", arg.span)) }, - ast::MetaItemKind::NameValue(ref value) => if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.to_string().into())) - } else { - Err(("`conf_file` value must be a string", value.span)) + ast::MetaItemKind::NameValue(ref value) => { + if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.to_string().into())) + } else { + Err(("`conf_file` value must be a string", value.span)) + } }, }; } @@ -179,8 +180,10 @@ pub fn lookup_conf_file() -> io::Result> { Ok(ref md) if md.is_file() => return Ok(Some(config_file)), // Return the error if it's something other than `NotFound`; otherwise we didn't // find the project file yet, and continue searching. - Err(e) => if e.kind() != io::ErrorKind::NotFound { - return Err(e); + Err(e) => { + if e.kind() != io::ErrorKind::NotFound { + return Err(e); + } }, _ => (), } @@ -223,25 +226,14 @@ pub fn read(path: Option<&path::Path>) -> (Conf, Vec) { Err(err) => return default(vec![err.into()]), }; - assert!( - ERRORS - .lock() - .expect("no threading -> mutex always safe") - .is_empty() - ); + assert!(ERRORS.lock().expect("no threading -> mutex always safe").is_empty()); match toml::from_str(&file) { Ok(toml) => ( toml, - ERRORS - .lock() - .expect("no threading -> mutex always safe") - .split_off(0), + ERRORS.lock().expect("no threading -> mutex always safe").split_off(0), ), Err(e) => { - let mut errors = ERRORS - .lock() - .expect("no threading -> mutex always safe") - .split_off(0); + let mut errors = ERRORS.lock().expect("no threading -> mutex always safe").split_off(0); errors.push(Error::Toml(e.to_string())); default(errors) }, diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index 2e87191d720..dde70d8e2cc 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! This module contains some useful constants. #![deny(clippy::missing_docs_in_private_items)] @@ -18,21 +17,6 @@ /// /// [reference-types]: https://doc.rust-lang.org/reference/types.html pub const BUILTIN_TYPES: &[&str] = &[ - "i8", - "u8", - "i16", - "u16", - "i32", - "u32", - "i64", - "u64", - "i128", - "u128", - "isize", - "usize", - "f32", - "f64", - "bool", - "str", - "char", + "i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "i128", "u128", "isize", "usize", "f32", "f64", "bool", + "str", "char", ]; diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 29c7260f491..992a3321c70 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! This module contains functions for retrieve the original AST from lowered //! `hir`. #![deny(clippy::missing_docs_in_private_items)] -use if_chain::if_chain; -use crate::rustc::{hir, ty}; use crate::rustc::lint::LateContext; +use crate::rustc::{hir, ty}; use crate::syntax::ast; use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; +use if_chain::if_chain; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind { @@ -64,7 +63,6 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O Some(expr) } - let def_path = match cx.tables.expr_ty(expr).sty { ty::Adt(def, _) => cx.tcx.def_path(def.did), _ => return None, @@ -109,47 +107,51 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O None } }, - hir::ExprKind::Call(ref path, ref args) => if let hir::ExprKind::Path(ref path) = path.node { - if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) { + hir::ExprKind::Call(ref path, ref args) => { + if let hir::ExprKind::Path(ref path) = path.node { + if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) + { + Some(Range { + start: Some(&args[0]), + end: Some(&args[1]), + limits: ast::RangeLimits::Closed, + }) + } else { + None + } + } else { + None + } + }, + hir::ExprKind::Struct(ref path, ref fields, None) => { + if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { + Some(Range { + start: Some(get_field("start", fields)?), + end: None, + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { + Some(Range { + start: Some(get_field("start", fields)?), + end: Some(get_field("end", fields)?), + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) + { Some(Range { - start: Some(&args[0]), - end: Some(&args[1]), + start: None, + end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, }) + } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { + Some(Range { + start: None, + end: Some(get_field("end", fields)?), + limits: ast::RangeLimits::HalfOpen, + }) } else { None } - } else { - None - }, - hir::ExprKind::Struct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) - || match_qpath(path, &paths::RANGE_FROM) - { - Some(Range { - start: Some(get_field("start", fields)?), - end: None, - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { - Some(Range { - start: Some(get_field("start", fields)?), - end: Some(get_field("end", fields)?), - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { - Some(Range { - start: None, - end: Some(get_field("end", fields)?), - limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { - Some(Range { - start: None, - end: Some(get_field("end", fields)?), - limits: ast::RangeLimits::HalfOpen, - }) - } else { - None }, _ => None, } @@ -161,7 +163,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // // ``` // for x in some_vec { - // // do stuff + // // do stuff // } // ``` if_chain! { @@ -178,7 +180,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // // ``` // for _ in vec![()] { - // // anything + // // anything // } // ``` if_chain! { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 7a0b28d15d8..27f49e72b33 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -7,16 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::consts::{constant_simple, constant_context}; -use crate::rustc::lint::LateContext; +use crate::consts::{constant_context, constant_simple}; use crate::rustc::hir::*; -use crate::rustc::ty::{TypeckTables}; -use std::hash::{Hash, Hasher}; -use std::collections::hash_map::DefaultHasher; +use crate::rustc::lint::LateContext; +use crate::rustc::ty::TypeckTables; use crate::syntax::ast::Name; use crate::syntax::ptr::P; use crate::utils::differing_macro_contexts; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; /// Type used to check whether two ast are the same. This is different from the /// operator @@ -60,9 +59,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { false } }, - (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _)) | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => { - self.eq_expr(l, r) - }, + (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _)) + | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => self.eq_expr(l, r), _ => false, } } @@ -79,18 +77,25 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { return false; } - if let (Some(l), Some(r)) = (constant_simple(self.cx, self.tables, left), constant_simple(self.cx, self.tables, right)) { + if let (Some(l), Some(r)) = ( + constant_simple(self.cx, self.tables, left), + constant_simple(self.cx, self.tables, right), + ) { if l == r { return true; } } match (&left.node, &right.node) { - (&ExprKind::AddrOf(l_mut, ref le), &ExprKind::AddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), + (&ExprKind::AddrOf(l_mut, ref le), &ExprKind::AddrOf(r_mut, ref re)) => { + l_mut == r_mut && self.eq_expr(le, re) + }, (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) }, - (&ExprKind::Assign(ref ll, ref lr), &ExprKind::Assign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), + (&ExprKind::Assign(ref ll, ref lr), &ExprKind::Assign(ref rl, ref rr)) => { + self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }, (&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, @@ -109,12 +114,16 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprKind::Call(ref l_fun, ref l_args), &ExprKind::Call(ref r_fun, ref r_args)) => { !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) | - (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt), + (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) + | (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => { + self.eq_expr(lx, rx) && self.eq_ty(lt, rt) + }, (&ExprKind::Field(ref l_f_exp, ref l_f_ident), &ExprKind::Field(ref r_f_exp, ref r_f_ident)) => { l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, - (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), + (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => { + self.eq_expr(la, ra) && self.eq_expr(li, ri) + }, (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => { self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r)) }, @@ -123,10 +132,13 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => { - ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r)) - && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) + ls == rs + && self.eq_expr(le, re) + && over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) + && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r)) + && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) }, (&ExprKind::MethodCall(ref l_path, _, ref l_args), &ExprKind::MethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) @@ -142,14 +154,17 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r), (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => { - self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) + self.eq_qpath(l_path, r_path) + && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_field(l, r)) }, (&ExprKind::Tup(ref l_tup), &ExprKind::Tup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), (&ExprKind::Array(ref l), &ExprKind::Array(ref r)) => self.eq_exprs(l, r), (&ExprKind::While(ref lc, ref lb, ref ll), &ExprKind::While(ref rc, ref rb, ref rl)) => { - self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) + self.eq_expr(lc, rc) + && self.eq_block(lb, rb) + && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str()) }, _ => false, } @@ -201,7 +216,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), (&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => { - over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) + over(ls, rs, |l, r| self.eq_pat(l, r)) + && over(le, re, |l, r| self.eq_pat(l, r)) && both(li, ri, |l, r| self.eq_pat(l, r)) }, (&PatKind::Wild, &PatKind::Wild) => true, @@ -233,11 +249,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) } else if left.parenthesized && right.parenthesized { over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) - && both( - &Some(&left.bindings[0].ty), - &Some(&right.bindings[0].ty), - |l, r| self.eq_ty(l, r), - ) + && both(&Some(&left.bindings[0].ty), &Some(&right.bindings[0].ty), |l, r| { + self.eq_ty(l, r) + }) } else { false } @@ -283,7 +297,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.tables = full_table; eq_ty && ll == rl }, - (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), + (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => { + l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty) + }, (&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) }, @@ -301,24 +317,24 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn swap_binop<'a>(binop: BinOpKind, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOpKind, &'a Expr, &'a Expr)> { match binop { - BinOpKind::Add | - BinOpKind::Mul | - BinOpKind::Eq | - BinOpKind::Ne | - BinOpKind::BitAnd | - BinOpKind::BitXor | - BinOpKind::BitOr => Some((binop, rhs, lhs)), + BinOpKind::Add + | BinOpKind::Mul + | BinOpKind::Eq + | BinOpKind::Ne + | BinOpKind::BitAnd + | BinOpKind::BitXor + | BinOpKind::BitOr => Some((binop, rhs, lhs)), BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Shl | - BinOpKind::Shr | - BinOpKind::Rem | - BinOpKind::Sub | - BinOpKind::Div | - BinOpKind::And | - BinOpKind::Or => None, + BinOpKind::Shl + | BinOpKind::Shr + | BinOpKind::Rem + | BinOpKind::Sub + | BinOpKind::Div + | BinOpKind::And + | BinOpKind::Or => None, } } @@ -340,7 +356,6 @@ where left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } - /// Type used to hash an ast element. This is different from the `Hash` trait /// on ast types as this /// trait would consider IDs and spans. @@ -380,7 +395,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { BlockCheckMode::UnsafeBlock(_) => 1, BlockCheckMode::PushUnsafeBlock(_) => 2, BlockCheckMode::PopUnsafeBlock(_) => 3, - }.hash(&mut self.s); + } + .hash(&mut self.s); } #[allow(clippy::many_single_char_names)] @@ -466,7 +482,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { match cap { CaptureClause::CaptureByValue => 0, CaptureClause::CaptureByRef => 1, - }.hash(&mut self.s); + } + .hash(&mut self.s); self.hash_expr(&self.cx.tcx.hir.body(eid).value); }, ExprKind::Field(ref e, ref f) => { @@ -661,7 +678,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = Guard::If; c.hash(&mut self.s); self.hash_expr(expr); - } + }, } } } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index e750c1c9bce..7297db4283b 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! checks for attributes -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc::hir; use crate::rustc::hir::print; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::Attribute; use crate::utils::get_attr; @@ -413,7 +412,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { }, hir::ItemKind::TraitAlias(..) => { println!("trait alias"); - } + }, hir::ItemKind::Impl(_, _, _, _, Some(ref _trait_ref), _, _) => { println!("trait impl"); }, @@ -533,6 +532,6 @@ fn print_guard(cx: &LateContext<'_, '_>, guard: &hir::Guard, indent: usize) { hir::Guard::If(expr) => { println!("{}If", ind); print_expr(cx, expr, indent + 1); - } + }, } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index fd232e2a366..5855ef672c2 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -7,22 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use crate::utils::{ - match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, -}; -use if_chain::if_chain; use crate::rustc::hir; +use crate::rustc::hir::def::Def; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; -use crate::rustc::hir::def::Def; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use crate::syntax::source_map::Span; use crate::syntax::symbol::LocalInternedString; +use crate::utils::{ + match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, +}; +use if_chain::if_chain; /// **What it does:** Checks for various things we like to keep tidy in clippy. /// @@ -112,18 +111,9 @@ impl LintPass for Clippy { impl EarlyLintPass for Clippy { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) { - if let Some(utils) = krate - .module - .items - .iter() - .find(|item| item.ident.name == "utils") - { + if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == "utils") { if let ItemKind::Mod(ref utils_mod) = utils.node { - if let Some(paths) = utils_mod - .items - .iter() - .find(|item| item.ident.name == "paths") - { + if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name == "paths") { if let ItemKind::Mod(ref paths_mod) = paths.node { let mut last_name: Option = None; for item in &paths_mod.items { @@ -218,7 +208,8 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool { ty: ref inner, mutbl: MutImmutable, }, - ) = ty.node { + ) = ty.node + { if let TyKind::Path(ref path) = inner.node { if let Def::Struct(def_id) = cx.tables.qpath_def(path, inner.hir_id) { return match_def_path(cx.tcx, def_id, &paths::LINT); @@ -272,9 +263,11 @@ impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { let ident_string = ident.to_string(); if let Some(replace) = self.map.get(&ident_string) { - let msg = format!("Prefer {} over {}, it has better performance \ - and we don't need any collision prevention in clippy", - replace, ident_string); + let msg = format!( + "Prefer {} over {}, it has better performance \ + and we don't need any collision prevention in clippy", + replace, ident_string + ); span_lint_and_sugg( cx, DEFAULT_HASH_TYPES, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 107a8eea15d..69a2500a1e1 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! This module contains paths to types and functions Clippy needs to know //! about. diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 43ab0f064ac..c9595ca5f50 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use std::borrow::Cow; -use crate::rustc::hir::*; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::*; use crate::rustc::lint::LateContext; use crate::syntax::ast::Name; use crate::syntax::source_map::Span; use crate::utils::{get_pat_name, match_var, snippet}; +use std::borrow::Cow; pub fn get_spans( cx: &LateContext<'_, '_>, @@ -23,8 +22,10 @@ pub fn get_spans( replacements: &'static [(&'static str, &'static str)], ) -> Option)>> { if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { - get_binding_name(&body.arguments[idx]) - .map_or_else(|| Some(vec![]), |name| extract_clone_suggestions(cx, name, replacements, body)) + get_binding_name(&body.arguments[idx]).map_or_else( + || Some(vec![]), + |name| extract_clone_suggestions(cx, name, replacements, body), + ) } else { Some(vec![]) } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index b4c9868bbd6..c5f4a61fe8c 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -7,26 +7,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Contains utility functions to generate suggestions. #![deny(clippy::missing_docs_in_private_items)] -use matches::matches; use crate::rustc::hir; use crate::rustc::lint::{EarlyContext, LateContext, LintContext}; use crate::rustc_errors; -use std::borrow::Cow; -use std::convert::TryInto; -use std::fmt::Display; -use std; -use crate::syntax::source_map::{CharPos, Span}; +use crate::rustc_errors::Applicability; +use crate::syntax::ast; use crate::syntax::parse::token; use crate::syntax::print::pprust::token_to_string; +use crate::syntax::source_map::{CharPos, Span}; use crate::syntax::util::parser::AssocOp; -use crate::syntax::ast; -use crate::utils::{higher, in_macro, snippet, snippet_opt}; use crate::syntax_pos::{BytePos, Pos}; -use crate::rustc_errors::Applicability; +use crate::utils::{higher, in_macro, snippet, snippet_opt}; +use matches::matches; +use std; +use std::borrow::Cow; +use std::convert::TryInto; +use std::fmt::Display; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -57,30 +56,30 @@ impl<'a> Sugg<'a> { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); match expr.node { - hir::ExprKind::AddrOf(..) | - hir::ExprKind::Box(..) | - hir::ExprKind::Closure(.., _) | - hir::ExprKind::If(..) | - hir::ExprKind::Unary(..) | - hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet), - hir::ExprKind::Continue(..) | - hir::ExprKind::Yield(..) | - hir::ExprKind::Array(..) | - hir::ExprKind::Block(..) | - hir::ExprKind::Break(..) | - hir::ExprKind::Call(..) | - hir::ExprKind::Field(..) | - hir::ExprKind::Index(..) | - hir::ExprKind::InlineAsm(..) | - hir::ExprKind::Lit(..) | - hir::ExprKind::Loop(..) | - hir::ExprKind::MethodCall(..) | - hir::ExprKind::Path(..) | - hir::ExprKind::Repeat(..) | - hir::ExprKind::Ret(..) | - hir::ExprKind::Struct(..) | - hir::ExprKind::Tup(..) | - hir::ExprKind::While(..) => Sugg::NonParen(snippet), + hir::ExprKind::AddrOf(..) + | hir::ExprKind::Box(..) + | hir::ExprKind::Closure(.., _) + | hir::ExprKind::If(..) + | hir::ExprKind::Unary(..) + | hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet), + hir::ExprKind::Continue(..) + | hir::ExprKind::Yield(..) + | hir::ExprKind::Array(..) + | hir::ExprKind::Block(..) + | hir::ExprKind::Break(..) + | hir::ExprKind::Call(..) + | hir::ExprKind::Field(..) + | hir::ExprKind::Index(..) + | hir::ExprKind::InlineAsm(..) + | hir::ExprKind::Lit(..) + | hir::ExprKind::Loop(..) + | hir::ExprKind::MethodCall(..) + | hir::ExprKind::Path(..) + | hir::ExprKind::Repeat(..) + | hir::ExprKind::Ret(..) + | hir::ExprKind::Struct(..) + | hir::ExprKind::Tup(..) + | hir::ExprKind::While(..) => Sugg::NonParen(snippet), hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), @@ -100,7 +99,8 @@ impl<'a> Sugg<'a> { /// /// - Applicability level `Unspecified` will never be changed. /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. - /// - If the default value is used and the applicability level is `MachineApplicable`, change it to + /// - If the default value is used and the applicability level is `MachineApplicable`, change it + /// to /// `HasPlaceholders` pub fn hir_with_applicability( cx: &LateContext<'_, '_>, @@ -126,39 +126,39 @@ impl<'a> Sugg<'a> { let snippet = snippet(cx, expr.span, default); match expr.node { - ast::ExprKind::AddrOf(..) | - ast::ExprKind::Box(..) | - ast::ExprKind::Closure(..) | - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::ObsoleteInPlace(..) | - ast::ExprKind::Unary(..) | - ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), - ast::ExprKind::Async(..) | - ast::ExprKind::Block(..) | - ast::ExprKind::Break(..) | - ast::ExprKind::Call(..) | - ast::ExprKind::Continue(..) | - ast::ExprKind::Yield(..) | - ast::ExprKind::Field(..) | - ast::ExprKind::ForLoop(..) | - ast::ExprKind::Index(..) | - ast::ExprKind::InlineAsm(..) | - ast::ExprKind::Lit(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::Mac(..) | - ast::ExprKind::MethodCall(..) | - ast::ExprKind::Paren(..) | - ast::ExprKind::Path(..) | - ast::ExprKind::Repeat(..) | - ast::ExprKind::Ret(..) | - ast::ExprKind::Struct(..) | - ast::ExprKind::Try(..) | - ast::ExprKind::TryBlock(..) | - ast::ExprKind::Tup(..) | - ast::ExprKind::Array(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), + ast::ExprKind::AddrOf(..) + | ast::ExprKind::Box(..) + | ast::ExprKind::Closure(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ObsoleteInPlace(..) + | ast::ExprKind::Unary(..) + | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet), + ast::ExprKind::Async(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Break(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::Continue(..) + | ast::ExprKind::Yield(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Index(..) + | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::Lit(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Paren(..) + | ast::ExprKind::Path(..) + | ast::ExprKind::Repeat(..) + | ast::ExprKind::Ret(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Try(..) + | ast::ExprKind::TryBlock(..) + | ast::ExprKind::Tup(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet), ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotEq, snippet), ast::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), @@ -225,10 +225,12 @@ impl<'a> Sugg<'a> { match self { Sugg::NonParen(..) => self, // (x) and (x).y() both don't need additional parens - Sugg::MaybeParen(sugg) => if sugg.starts_with('(') && sugg.ends_with(')') { - Sugg::MaybeParen(sugg) - } else { - Sugg::NonParen(format!("({})", sugg).into()) + Sugg::MaybeParen(sugg) => { + if sugg.starts_with('(') && sugg.ends_with(')') { + Sugg::MaybeParen(sugg) + } else { + Sugg::NonParen(format!("({})", sugg).into()) + } }, Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()), } @@ -267,10 +269,7 @@ struct ParenHelper { impl ParenHelper { /// Build a `ParenHelper`. fn new(paren: bool, wrapped: T) -> Self { - Self { - paren, - wrapped, - } + Self { paren, wrapped } } } @@ -320,7 +319,8 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> || (other.precedence() == op.precedence() && ((op != other && associativity(op) != dir) || (op == other && associativity(op) != Associativity::Both))) - || is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) + || is_shift(op) && is_arith(other) + || is_shift(other) && is_arith(op) } let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs { @@ -338,24 +338,29 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> let lhs = ParenHelper::new(lhs_paren, lhs); let rhs = ParenHelper::new(rhs_paren, rhs); let sugg = match op { - AssocOp::Add | - AssocOp::BitAnd | - AssocOp::BitOr | - AssocOp::BitXor | - AssocOp::Divide | - AssocOp::Equal | - AssocOp::Greater | - AssocOp::GreaterEqual | - AssocOp::LAnd | - AssocOp::LOr | - AssocOp::Less | - AssocOp::LessEqual | - AssocOp::Modulus | - AssocOp::Multiply | - AssocOp::NotEqual | - AssocOp::ShiftLeft | - AssocOp::ShiftRight | - AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), + AssocOp::Add + | AssocOp::BitAnd + | AssocOp::BitOr + | AssocOp::BitXor + | AssocOp::Divide + | AssocOp::Equal + | AssocOp::Greater + | AssocOp::GreaterEqual + | AssocOp::LAnd + | AssocOp::LOr + | AssocOp::Less + | AssocOp::LessEqual + | AssocOp::Modulus + | AssocOp::Multiply + | AssocOp::NotEqual + | AssocOp::ShiftLeft + | AssocOp::ShiftRight + | AssocOp::Subtract => format!( + "{} {} {}", + lhs, + op.to_ast_binop().expect("Those are AST ops").to_string(), + rhs + ), AssocOp::Assign => format!("{} = {}", lhs, rhs), AssocOp::ObsoleteInPlace => format!("in ({}) {}", lhs, rhs), AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), @@ -400,17 +405,8 @@ fn associativity(op: &AssocOp) -> Associativity { match *op { ObsoleteInPlace | Assign | AssignOp(_) => Associativity::Right, Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, - Divide | - Equal | - Greater | - GreaterEqual | - Less | - LessEqual | - Modulus | - NotEqual | - ShiftLeft | - ShiftRight | - Subtract => Associativity::Left, + Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight + | Subtract => Associativity::Left, DotDot | DotDotEq => Associativity::None, } } @@ -431,15 +427,14 @@ fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { hir::BinOpKind::Shr => Shr, hir::BinOpKind::Sub => Minus, - | hir::BinOpKind::And + hir::BinOpKind::And | hir::BinOpKind::Eq | hir::BinOpKind::Ge | hir::BinOpKind::Gt | hir::BinOpKind::Le | hir::BinOpKind::Lt | hir::BinOpKind::Ne - | hir::BinOpKind::Or - => panic!("This operator does not exist"), + | hir::BinOpKind::Or => panic!("This operator does not exist"), }) } @@ -467,9 +462,7 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { let lo = cx.sess().source_map().lookup_char_pos(span.lo()); - if let Some(line) = lo.file - .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) - { + if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { // we can mix char and byte positions here because we only consider `[ \t]` if lo.col == CharPos(pos) { @@ -496,7 +489,14 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { /// ```rust,ignore /// db.suggest_item_with_attr(cx, item, "#[derive(Default)]"); /// ``` - fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability); + fn suggest_item_with_attr( + &mut self, + cx: &T, + item: Span, + msg: &str, + attr: &D, + applicability: Applicability, + ); /// Suggest to add an item before another. /// @@ -527,16 +527,18 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> { } impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { - fn suggest_item_with_attr(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability) { + fn suggest_item_with_attr( + &mut self, + cx: &T, + item: Span, + msg: &str, + attr: &D, + applicability: Applicability, + ) { if let Some(indent) = indentation(cx, item) { let span = item.with_hi(item.lo()); - self.span_suggestion_with_applicability( - span, - msg, - format!("{}\n{}", attr, indent), - applicability, - ); + self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", attr, indent), applicability); } } @@ -557,12 +559,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error }) .collect::(); - self.span_suggestion_with_applicability( - span, - msg, - format!("{}\n{}", new_item, indent), - applicability, - ); + self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", new_item, indent), applicability); } } @@ -575,15 +572,11 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n'); if let Some(non_whitespace_offset) = non_whitespace_offset { - remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large"))) + remove_span = remove_span + .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large"))) } } - self.span_suggestion_with_applicability( - remove_span, - msg, - String::new(), - applicability, - ); + self.span_suggestion_with_applicability(remove_span, msg, String::new(), applicability); } } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index f3af698ffa2..31aa4b6fb5a 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::LateContext; use crate::rustc::hir::def::Def; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index d7e7de06355..7d09c20db27 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::consts::constant; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -90,12 +89,14 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA return; } }, - higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() { - let span = args[0].span.to(last.span); + higher::VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + let span = args[0].span.to(last.span); - format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) - } else { - "&[]".into() + format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + } else { + "&[]".into() + } }, }; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0119560ccd8..440ab7433cc 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; @@ -336,9 +335,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - let mut seen = false; for arg in &args { match arg.position { - ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx { - all_simple &= arg.format == SIMPLE; - seen = true; + ArgumentImplicitlyIs(n) | ArgumentIs(n) => { + if n == idx { + all_simple &= arg.format == SIMPLE; + seen = true; + } }, ArgumentNamed(_) => {}, } @@ -356,9 +357,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - for arg in &args { match arg.position { ArgumentImplicitlyIs(_) | ArgumentIs(_) => {}, - ArgumentNamed(name) => if *p == name { - seen = true; - all_simple &= arg.format == SIMPLE; + ArgumentNamed(name) => { + if *p == name { + seen = true; + all_simple &= arg.format == SIMPLE; + } }, } } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 779a6a59e54..20a92012520 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use crate::consts::{constant_simple, Constant}; +use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; use crate::utils::span_help_and_lint; +use if_chain::if_chain; /// **What it does:** Checks for `0.0 / 0.0`. /// -- cgit 1.4.1-3-g733a5 From 63fa5d24e15be79c2a5dfcc8b0200c1d3eb7ffb4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 21:49:09 +0100 Subject: Fix some formatting issues --- clippy_lints/src/default_trait_access.rs | 74 ++++++++++++++++---------------- clippy_lints/src/explicit_write.rs | 7 ++- clippy_lints/src/loops.rs | 7 ++- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/matches.rs | 14 +++--- clippy_lints/src/methods/mod.rs | 70 +++++++++++++----------------- clippy_lints/src/mut_reference.rs | 7 ++- clippy_lints/src/needless_bool.rs | 7 ++- clippy_lints/src/ptr.rs | 7 ++- clippy_lints/src/returns.rs | 7 ++- clippy_lints/src/shadow.rs | 7 ++- clippy_lints/src/transmute.rs | 15 ++++--- clippy_lints/src/types.rs | 21 ++++----- clippy_lints/src/unicode.rs | 14 +++--- 14 files changed, 120 insertions(+), 139 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index bc5643a0bed..7719e35902b 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -49,44 +49,44 @@ impl LintPass for DefaultTraitAccess { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { - if let ExprKind::Call(ref path, ..) = expr.node; - if !any_parent_is_automatically_derived(cx.tcx, expr.id); - if let ExprKind::Path(ref qpath) = path.node; - if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); - if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); - then { - match qpath { - QPath::Resolved(..) => { - if_chain! { - // Detect and ignore ::default() because these calls do - // explicitly name the type. - if let ExprKind::Call(ref method, ref _args) = expr.node; - if let ExprKind::Path(ref p) = method.node; - if let QPath::Resolved(Some(_ty), _path) = p; - then { - return; - } - } - - // TODO: Work out a way to put "whatever the imported way of referencing - // this type in this file" rather than a fully-qualified type. - let expr_ty = cx.tables.expr_ty(expr); - if let TyKind::Adt(..) = expr_ty.sty { - let replacement = format!("{}::default()", expr_ty); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("Calling {} is more clear than this expression", replacement), - "try", - replacement, - Applicability::Unspecified, // First resolve the TODO above - ); + if let ExprKind::Call(ref path, ..) = expr.node; + if !any_parent_is_automatically_derived(cx.tcx, expr.id); + if let ExprKind::Path(ref qpath) = path.node; + if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); + if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); + then { + match qpath { + QPath::Resolved(..) => { + if_chain! { + // Detect and ignore ::default() because these calls do + // explicitly name the type. + if let ExprKind::Call(ref method, ref _args) = expr.node; + if let ExprKind::Path(ref p) = method.node; + if let QPath::Resolved(Some(_ty), _path) = p; + then { + return; + } } - }, - QPath::TypeRelative(..) => {}, - } - } + + // TODO: Work out a way to put "whatever the imported way of referencing + // this type in this file" rather than a fully-qualified type. + let expr_ty = cx.tables.expr_ty(expr); + if let TyKind::Adt(..) = expr_ty.sty { + let replacement = format!("{}::default()", expr_ty); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("Calling {} is more clear than this expression", replacement), + "try", + replacement, + Applicability::Unspecified, // First resolve the TODO above + ); + } + }, + QPath::TypeRelative(..) => {}, + } + } } } } diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index c1f007fea0b..94bd0ab209c 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -27,10 +27,9 @@ use if_chain::if_chain; /// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); /// ``` declare_clippy_lint! { -pub EXPLICIT_WRITE, -complexity, -"using the `write!()` family of functions instead of the `print!()` family \ - of functions, when using the latter would work" + pub EXPLICIT_WRITE, + complexity, + "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work" } #[derive(Copy, Clone, Debug)] diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 01b526cc630..08ae3a55a2c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -249,10 +249,9 @@ declare_clippy_lint! { /// vec.iter().map(|x| /* some operation returning () */).collect::>(); /// ``` declare_clippy_lint! { -pub UNUSED_COLLECT, -perf, -"`collect()`ing an iterator without using the result; this is usually better \ - written as a for loop" + pub UNUSED_COLLECT, + perf, + "`collect()`ing an iterator without using the result; this is usually better written as a for loop" } /// **What it does:** Checks for functions collecting an iterator when collect diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4ea02db1465..af85a279ca3 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -81,7 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => { match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => { - if !cx.tables.expr_ty(inner).is_box() => { + if !cx.tables.expr_ty(inner).is_box() { lint(cx, e.span, args[0].span, name, inner); } }, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 1821a35cf59..dedf9a16b35 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -40,10 +40,9 @@ use std::collections::Bound; /// } /// ``` declare_clippy_lint! { -pub SINGLE_MATCH, -style, -"a match statement with a single nontrivial arm (i.e. where the other arm \ - is `_ => {}`) instead of `if let`" + pub SINGLE_MATCH, + style, + "a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let`" } /// **What it does:** Checks for matches with a two arms where an `if let` will @@ -61,10 +60,9 @@ style, /// } /// ``` declare_clippy_lint! { -pub SINGLE_MATCH_ELSE, -pedantic, -"a match statement with a two arms where the second arm's pattern is a wildcard \ - instead of `if let`" + pub SINGLE_MATCH_ELSE, + pedantic, + "a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let`" } /// **What it does:** Checks for matches where all arms match a reference, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9e56213931a..0df166a0796 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -131,10 +131,9 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { -pub WRONG_SELF_CONVENTION, -style, -"defining a method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" + pub WRONG_SELF_CONVENTION, + style, + "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention" } /// **What it does:** This is the same as @@ -155,10 +154,9 @@ style, /// } /// ``` declare_clippy_lint! { -pub WRONG_PUB_SELF_CONVENTION, -restriction, -"defining a public method named with an established prefix (like \"into_\") that takes \ - `self` with the wrong convention" + pub WRONG_PUB_SELF_CONVENTION, + restriction, + "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention" } /// **What it does:** Checks for usage of `ok().expect(..)`. @@ -173,10 +171,9 @@ restriction, /// x.ok().expect("why did I do this again?") /// ``` declare_clippy_lint! { -pub OK_EXPECT, -style, -"using `ok().expect()`, which gives worse error messages than \ - calling `expect` directly on the Result" + pub OK_EXPECT, + style, + "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result" } /// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`. @@ -209,10 +206,9 @@ pedantic, /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` declare_clippy_lint! { -pub OPTION_MAP_UNWRAP_OR_ELSE, -pedantic, -"using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `map_or_else(g, f)`" + pub OPTION_MAP_UNWRAP_OR_ELSE, + pedantic, + "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`" } /// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. @@ -227,10 +223,9 @@ pedantic, /// x.map(|a| a + 1).unwrap_or_else(some_function) /// ``` declare_clippy_lint! { -pub RESULT_MAP_UNWRAP_OR_ELSE, -pedantic, -"using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \ - `.ok().map_or_else(g, f)`" + pub RESULT_MAP_UNWRAP_OR_ELSE, + pedantic, + "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.ok().map_or_else(g, f)`" } /// **What it does:** Checks for usage of `_.map_or(None, _)`. @@ -245,10 +240,9 @@ pedantic, /// opt.map_or(None, |a| a + 1) /// ``` declare_clippy_lint! { -pub OPTION_MAP_OR_NONE, -style, -"using `Option.map_or(None, f)`, which is more succinctly expressed as \ - `and_then(f)`" + pub OPTION_MAP_OR_NONE, + style, + "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`" } /// **What it does:** Checks for usage of `_.filter(_).next()`. @@ -280,10 +274,9 @@ declare_clippy_lint! { /// iter.map(|x| x.iter()).flatten() /// ``` declare_clippy_lint! { -pub MAP_FLATTEN, -pedantic, -"using combinations of `flatten` and `map` which can usually be written as a \ - single method call" + pub MAP_FLATTEN, + pedantic, + "using combinations of `flatten` and `map` which can usually be written as a single method call" } /// **What it does:** Checks for usage of `_.filter(_).map(_)`, @@ -300,10 +293,9 @@ pedantic, /// iter.filter(|x| x == 0).map(|x| x * 2) /// ``` declare_clippy_lint! { -pub FILTER_MAP, -pedantic, -"using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \ - usually be written as a single method call" + pub FILTER_MAP, + pedantic, + "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call" } /// **What it does:** Checks for an iterator search (such as `find()`, @@ -319,10 +311,9 @@ pedantic, /// iter.find(|x| x == 0).is_some() /// ``` declare_clippy_lint! { -pub SEARCH_IS_SOME, -complexity, -"using an iterator search followed by `is_some()`, which is more succinctly \ - expressed as a call to `any()`" + pub SEARCH_IS_SOME, + complexity, + "using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()`" } /// **What it does:** Checks for usage of `.chars().next()` on a `str` to check @@ -485,10 +476,9 @@ declare_clippy_lint! { /// **Example:** /// `_.split("x")` could be `_.split('x')` declare_clippy_lint! { -pub SINGLE_CHAR_PATTERN, -perf, -"using a single-character str where a char could be used, e.g. \ - `_.split(\"x\")`" + pub SINGLE_CHAR_PATTERN, + perf, + "using a single-character str where a char could be used, e.g. `_.split(\"x\")`" } /// **What it does:** Checks for getting the inner pointer of a temporary diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 6729b2030a7..b92b3358cea 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -27,10 +27,9 @@ use crate::utils::span_lint; /// my_vec.push(&mut value) /// ``` declare_clippy_lint! { -pub UNNECESSARY_MUT_PASSED, -style, -"an argument passed as a mutable reference although the callee only demands an \ - immutable reference" + pub UNNECESSARY_MUT_PASSED, + style, + "an argument passed as a mutable reference although the callee only demands an immutable reference" } #[derive(Copy, Clone)] diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index fec8e2490da..e3db1f79ed7 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -40,10 +40,9 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint, span_lint_an /// } /// ``` declare_clippy_lint! { -pub NEEDLESS_BOOL, -complexity, -"if-statements with plain booleans in the then- and else-clause, e.g. \ - `if p { true } else { false }`" + pub NEEDLESS_BOOL, + complexity, + "if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`" } /// **What it does:** Checks for expressions of the form `x == true` (or vice diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 139b87dffe7..82e69889395 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -54,10 +54,9 @@ use std::borrow::Cow; /// fn foo(&Vec) { .. } /// ``` declare_clippy_lint! { -pub PTR_ARG, -style, -"fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \ - instead, respectively" + pub PTR_ARG, + style, + "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively" } /// **What it does:** This lint checks for equality comparisons with `ptr::null` diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 892f9e57752..c7dc6e1cde7 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -65,10 +65,9 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { -pub LET_AND_RETURN, -style, -"creating a let-binding and then immediately returning it like `let x = expr; x` at \ - the end of a block" + pub LET_AND_RETURN, + style, + "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block" } /// **What it does:** Checks for unit (`()`) expressions that can be removed. diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index caeccf0cba2..472596beaf7 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -56,10 +56,9 @@ declare_clippy_lint! { /// let y = x + 1; /// ``` declare_clippy_lint! { -pub SHADOW_REUSE, -restriction, -"rebinding a name to an expression that re-uses the original value, e.g. \ - `let x = x + 1`" + pub SHADOW_REUSE, + restriction, + "rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1`" } /// **What it does:** Checks for bindings that shadow other bindings already in diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 65d8e33ce7b..ec6439aef95 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -81,7 +81,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: &T = std::mem::transmute(p); // where p: *const T -/// // can be written: +/// +/// // can be written: /// let _: &T = &*p; /// ``` declare_clippy_lint! { @@ -108,7 +109,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: char = std::mem::transmute(x); // where x: u32 -/// // should be: +/// +/// // should be: /// let _ = std::char::from_u32(x).unwrap(); /// ``` declare_clippy_lint! { @@ -135,7 +137,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: &str = std::mem::transmute(b); // where b: &[u8] -/// // should be: +/// +/// // should be: /// let _ = std::str::from_utf8(b).unwrap(); /// ``` declare_clippy_lint! { @@ -153,7 +156,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: bool = std::mem::transmute(x); // where x: u8 -/// // should be: +/// +/// // should be: /// let _: bool = x != 0; /// ``` declare_clippy_lint! { @@ -171,7 +175,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _: f32 = std::mem::transmute(x); // where x: u32 -/// // should be: +/// +/// // should be: /// let _: f32 = f32::from_bits(x); /// ``` declare_clippy_lint! { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6d5dbfe0713..1b98a89f868 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -117,10 +117,9 @@ declare_clippy_lint! { /// let x = LinkedList::new(); /// ``` declare_clippy_lint! { -pub LINKEDLIST, -pedantic, -"usage of LinkedList, usually a vector is faster, or a more specialized data \ - structure like a VecDeque" + pub LINKEDLIST, + pedantic, + "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque" } /// **What it does:** Checks for use of `&Box` anywhere in the code. @@ -668,10 +667,9 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { -pub CAST_POSSIBLE_TRUNCATION, -pedantic, -"casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, \ - or `x as i32` where `x: f32`" + pub CAST_POSSIBLE_TRUNCATION, + pedantic, + "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32`" } /// **What it does:** Checks for casts from an unsigned type to a signed type of @@ -692,10 +690,9 @@ pedantic, /// u32::MAX as i32 // will yield a value of `-1` /// ``` declare_clippy_lint! { -pub CAST_POSSIBLE_WRAP, -pedantic, -"casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` \ - and `x > i32::MAX`" + pub CAST_POSSIBLE_WRAP, + pedantic, + "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX`" } /// **What it does:** Checks for on casts between numerical types that may diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index bb384891926..723565b3a9b 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -45,10 +45,9 @@ declare_clippy_lint! { /// let x = "Hä?" /// ``` declare_clippy_lint! { -pub NON_ASCII_LITERAL, -pedantic, -"using any literal non-ASCII chars in a string literal instead of \ - using the `\\u` escape" + pub NON_ASCII_LITERAL, + pedantic, + "using any literal non-ASCII chars in a string literal instead of using the `\\u` escape" } /// **What it does:** Checks for string literals that contain Unicode in a form @@ -63,10 +62,9 @@ pedantic, /// **Example:** You may not see it, but “à” and “à” aren't the same string. The /// former when escaped is actually `"a\u{300}"` while the latter is `"\u{e0}"`. declare_clippy_lint! { -pub UNICODE_NOT_NFC, -pedantic, -"using a unicode literal not in NFC normal form (see \ - [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" + pub UNICODE_NOT_NFC, + pedantic, + "using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } #[derive(Copy, Clone)] -- cgit 1.4.1-3-g733a5 From 27a69bd66c4d15608d093b75c4647fc10d88882b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 22:01:22 +0100 Subject: Don't run integration tests in forks --- .travis.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8730535d629..5338c7622e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,9 @@ install: fi fi +# disabling the integration tests in forks should be done with +# if: fork = false +# but this is currently buggy travis-ci/travis-ci#9118 matrix: include: - os: osx # run base tests on both platforms @@ -48,23 +51,36 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: BASE_TEST=true + env: BASE_TESTS=true - env: INTEGRATION=rust-lang/cargo + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-random/rand + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang-nursery/stdsimd + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang/rustfmt + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang-nursery/futures-rs + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang-nursery/failure + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang-nursery/log + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang-nursery/chalk + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-lang/rls + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=chronotope/chrono + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=serde-rs/serde + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=Geal/nom + if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=hyperium/hyper + if: repo =~ /^rust-lang\/rust-clippy$/ allow_failures: - os: windows - env: BASE_TEST=true + env: BASE_TESTS=true # prevent these jobs with default env vars exclude: - os: linux -- cgit 1.4.1-3-g733a5 From 14d1e8d17436b22b27c451619ec563494f0e5ec4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 27 Nov 2018 22:36:25 +0100 Subject: Document how to run rustfmt in CONTRIBUTING.md --- CONTRIBUTING.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5bc9e99a28f..26efa9a58c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,9 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Author lint](#author-lint) * [Documentation](#documentation) * [Running test suite](#running-test-suite) + * [Running rustfmt](#running-rustfmt) * [Testing manually](#testing-manually) + * [Linting Clippy with your local changes](#linting-clippy-with-your-local-changes) * [How Clippy works](#how-clippy-works) * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) * [Contributions](#contributions) @@ -145,6 +147,18 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running `cargo test`) and check whether the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +### Running rustfmt + +[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according +to style guidelines. The code has to be formatted by `rustfmt` before a PR will be merged. + +It can be installed via `rustup`: +```bash +rustup component add rustfmt-preview +``` + +Use `cargo fmt --all` to format the whole codebase. + ### Testing manually Manually testing against an example file is useful if you have added some @@ -152,7 +166,7 @@ Manually testing against an example file is useful if you have added some local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. -### Linting Clippy with your changes locally +### Linting Clippy with your local changes Clippy CI only passes if all lints defined in the version of the Clippy being tested pass (that is, don’t report any suggestions). You can avoid prolonging @@ -245,7 +259,8 @@ Contributions to Clippy should be made in the form of GitHub pull requests. Each be reviewed by a core contributor (someone with permission to land patches) and either landed in the main tree or given feedback for changes that would be required. -All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/) +All code in this repository is under the [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0>) +or the [MIT](http://opensource.org/licenses/MIT) license. -- cgit 1.4.1-3-g733a5 From 93e8c9efc9470fb17fb52b0a4fa17565ad22ee83 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 28 Nov 2018 08:11:28 +0100 Subject: Update docs in regards to the merged RFC --- CONTRIBUTING.md | 10 +++++++--- README.md | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5bc9e99a28f..cad6b93caf2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,14 +63,15 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us ## Writing code -Compiling Clippy from scratch can take almost a minute or more depending on your machine. -However, since Rust 1.24.0 incremental compilation is enabled by default and compile times for small changes should be quick. - [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of `LintPass` with one or more of its default methods overridden. See the existing lints for examples of this. +If want to add a new lint or change existing ones apart from bugfixing, it's +also a good idea to give the [stability guaratees][rfc_stability] and +[lint categories][rfc_lint_cats] sections of the [Clippy 1.0 RFC][clippy_rfc] a +quick read. ### Author lint @@ -263,3 +264,6 @@ All code in this repository is under the [Mozilla Public License, 2.0](https://w [toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/6ce0459f6bfa7c528ae1886492a3e0b5ef0ee547 [rtim]: https://github.com/kennytm/rustup-toolchain-install-master [rustup_component_history]: https://mexus.github.io/rustup-components-history +[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md +[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees +[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories diff --git a/README.md b/README.md index 0cb1481c9cf..92bb4586688 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in Clippy. Please leave your thoughts on the RFC PR. - # Clippy [![Build Status](https://travis-ci.org/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang/rust-clippy) -- cgit 1.4.1-3-g733a5 From 33c1e3c08c52eb32fa2eb80843fb42dddb9a1a06 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Wed, 28 Nov 2018 14:39:25 +0100 Subject: Add missing word Co-Authored-By: phansch --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cad6b93caf2..daaf1b37d09 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ to lint-writing, though it does get into advanced stuff. Most lints consist of a `LintPass` with one or more of its default methods overridden. See the existing lints for examples of this. -If want to add a new lint or change existing ones apart from bugfixing, it's +If you want to add a new lint or change existing ones apart from bugfixing, it's also a good idea to give the [stability guaratees][rfc_stability] and [lint categories][rfc_lint_cats] sections of the [Clippy 1.0 RFC][clippy_rfc] a quick read. -- cgit 1.4.1-3-g733a5 From c38bac89e976e7dfe731e68ef56fd8661be1a93f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 30 Nov 2018 09:14:18 +0100 Subject: remove macro_at_most_once_rep feature attribute since it's stable Warning was: warning: the feature `macro_at_most_once_rep` has been stable since 1.32.0 and no longer requires an attribute to enable --> clippy_lints/src/lib.rs:19:12 | 19 | #![feature(macro_at_most_once_rep)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(stable_features)] on by default --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9eb5a94f51d..1b970b2f376 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -16,7 +16,6 @@ #![feature(range_contains)] #![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] -#![feature(macro_at_most_once_rep)] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] #![feature(try_from)] -- cgit 1.4.1-3-g733a5 From 8b1f69a485d394f4439336f958451054c0e89184 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Dec 2018 16:20:58 -0800 Subject: Downgrade unsafe_vector_initialization to restriction This lint looks for: let mut vec = Vec::with_capacity(len); vec.set_len(len); The suggested replacement is `vec![0; len]`. This is far too opinionated to be a deny-by-default lint because the performance characteristics of the suggested replacement are totally different. I am not convinced that this lint has value beyond what deny(unsafe_code) gives you. Unsafe code is unsafe but please don't deny-by-default lint it if that's the only reason. --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/slow_vector_initialization.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1b970b2f376..c2e625f3d52 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -495,6 +495,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, + slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, strings::STRING_ADD, write::PRINT_STDOUT, write::USE_DEBUG, @@ -727,7 +728,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { returns::UNUSED_UNIT, serde_api::SERDE_API_MISUSE, slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, strings::STRING_LIT_AS_BYTES, suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, @@ -974,7 +974,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ranges::ITERATOR_STEP_BY_ZERO, regex::INVALID_REGEX, serde_api::SERDE_API_MISUSE, - slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, swap::ALMOST_SWAPPED, diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 7bf0fea4277..2964bb6fac7 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -55,7 +55,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub UNSAFE_VECTOR_INITIALIZATION, - correctness, + restriction, "unsafe vector initialization" } -- cgit 1.4.1-3-g733a5 From c00dcd03d77333cbdf24fb2b79f62e4ab29603a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Dec 2018 16:46:03 -0800 Subject: Downgrade large_digit_groups to pedantic I believe if the user already decided to put underscores in their literal, Clippy should be willing to believe that they put a number of underscores that they felt was readable. --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/literal_representation.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1b970b2f376..9d8ebcde427 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -514,6 +514,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, + literal_representation::LARGE_DIGIT_GROUPS, loops::EXPLICIT_INTO_ITER_LOOP, loops::EXPLICIT_ITER_LOOP, matches::SINGLE_MATCH_ELSE, @@ -613,7 +614,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { lifetimes::EXTRA_UNUSED_LIFETIMES, lifetimes::NEEDLESS_LIFETIMES, literal_representation::INCONSISTENT_DIGIT_GROUPING, - literal_representation::LARGE_DIGIT_GROUPS, literal_representation::MISTYPED_LITERAL_SUFFIXES, literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, @@ -794,7 +794,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, literal_representation::INCONSISTENT_DIGIT_GROUPING, - literal_representation::LARGE_DIGIT_GROUPS, literal_representation::UNREADABLE_LITERAL, loops::EMPTY_LOOP, loops::FOR_KV_MAP, diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 5fc97d97426..470ed369564 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -90,7 +90,7 @@ declare_clippy_lint! { /// ``` declare_clippy_lint! { pub LARGE_DIGIT_GROUPS, - style, + pedantic, "grouping digits into groups that are too large" } -- cgit 1.4.1-3-g733a5 From 67f9d24c1b32ddc44765e55a0daf8d038426acba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Dec 2018 17:19:39 -0800 Subject: Keep testing unsafe_vector_initialization as ui test --- tests/ui/slow_vector_initialization.rs | 2 ++ tests/ui/slow_vector_initialization.stderr | 50 +++++++++++++++--------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index daa6b9c1376..aa80fc87aa2 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(clippy::unsafe_vector_initialization)] + use std::iter::repeat; fn main() { diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 577cc82c6d5..bc05dd6e1e5 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,71 +1,71 @@ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:23:5 + --> $DIR/slow_vector_initialization.rs:25:5 | -22 | let mut vec1 = Vec::with_capacity(len); +24 | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -23 | vec1.extend(repeat(0).take(len)); +25 | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:27:5 + --> $DIR/slow_vector_initialization.rs:29:5 | -26 | let mut vec2 = Vec::with_capacity(len - 10); +28 | let mut vec2 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -27 | vec2.extend(repeat(0).take(len - 10)); +29 | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:41:5 + --> $DIR/slow_vector_initialization.rs:43:5 | -40 | let mut resized_vec = Vec::with_capacity(30); +42 | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -41 | resized_vec.resize(30, 0); +43 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:44:5 + --> $DIR/slow_vector_initialization.rs:46:5 | -43 | let mut extend_vec = Vec::with_capacity(30); +45 | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -44 | extend_vec.extend(repeat(0).take(30)); +46 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:51:5 + --> $DIR/slow_vector_initialization.rs:53:5 | -50 | let mut vec1 = Vec::with_capacity(len); +52 | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -51 | vec1.resize(len, 0); +53 | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:59:5 + --> $DIR/slow_vector_initialization.rs:61:5 | -58 | let mut vec3 = Vec::with_capacity(len - 10); +60 | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -59 | vec3.resize(len - 10, 0); +61 | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:63:5 + --> $DIR/slow_vector_initialization.rs:65:5 | -62 | vec1 = Vec::with_capacity(10); +64 | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replace allocation with: `vec![0; 10]` -63 | vec1.resize(10, 0); +65 | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ error: unsafe vector initialization - --> $DIR/slow_vector_initialization.rs:70:9 + --> $DIR/slow_vector_initialization.rs:72:9 | -67 | let mut unsafe_vec: Vec = Vec::with_capacity(200); +69 | let mut unsafe_vec: Vec = Vec::with_capacity(200); | ----------------------- help: consider replace allocation with: `vec![0; 200]` ... -70 | unsafe_vec.set_len(200); +72 | unsafe_vec.set_len(200); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[deny(clippy::unsafe_vector_initialization)] on by default + = note: `-D clippy::unsafe-vector-initialization` implied by `-D warnings` error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 1a14cb36436602419c374acd69f46f6490de80c7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Dec 2018 17:23:53 -0800 Subject: Keep testing large_digit_groups as ui test --- tests/ui/literals.rs | 1 + tests/ui/literals.stderr | 132 +++++++++++++++++++++++------------------------ 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index c08c4b693b8..90e9a69a994 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -7,6 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(clippy::large_digit_groups)] #![warn(clippy::mixed_case_hex_literals)] #![warn(clippy::unseparated_literal_suffix)] #![warn(clippy::zero_prefixed_literal)] diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index d2a50e2ded5..a9d49ff394e 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,217 +1,217 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:21:17 + --> $DIR/literals.rs:22:17 | -21 | let fail1 = 0xabCD; +22 | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:22:17 + --> $DIR/literals.rs:23:17 | -22 | let fail2 = 0xabCD_u32; +23 | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:23:17 + --> $DIR/literals.rs:24:17 | -23 | let fail2 = 0xabCD_isize; +24 | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:24:27 + --> $DIR/literals.rs:25:27 | -24 | let fail_multi_zero = 000_123usize; +25 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:24:27 + --> $DIR/literals.rs:25:27 | -24 | let fail_multi_zero = 000_123usize; +25 | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -24 | let fail_multi_zero = 123usize; +25 | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -24 | let fail_multi_zero = 0o123usize; +25 | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:29:17 + --> $DIR/literals.rs:30:17 | -29 | let fail3 = 1234i32; +30 | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:30:17 + --> $DIR/literals.rs:31:17 | -30 | let fail4 = 1234u32; +31 | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:31:17 + --> $DIR/literals.rs:32:17 | -31 | let fail5 = 1234isize; +32 | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:32:17 + --> $DIR/literals.rs:33:17 | -32 | let fail6 = 1234usize; +33 | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:33:17 + --> $DIR/literals.rs:34:17 | -33 | let fail7 = 1.5f32; +34 | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:37:17 + --> $DIR/literals.rs:38:17 | -37 | let fail8 = 0123; +38 | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -37 | let fail8 = 123; +38 | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -37 | let fail8 = 0o123; +38 | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:48:17 + --> $DIR/literals.rs:49:17 | -48 | let fail9 = 0xabcdef; +49 | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:49:18 + --> $DIR/literals.rs:50:18 | -49 | let fail10 = 0xBAFEBAFE; +50 | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:50:18 + --> $DIR/literals.rs:51:18 | -50 | let fail11 = 0xabcdeff; +51 | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/literals.rs:51:18 + --> $DIR/literals.rs:52:18 | -51 | let fail12 = 0xabcabcabcabcabcabc; +52 | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller - --> $DIR/literals.rs:52:18 + --> $DIR/literals.rs:53:18 | -52 | let fail13 = 0x1_23456_78901_usize; +53 | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:54:18 + --> $DIR/literals.rs:55:18 | -54 | let fail14 = 2_32; +55 | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` | = note: #[deny(clippy::mistyped_literal_suffixes)] on by default error: mistyped literal suffix - --> $DIR/literals.rs:55:18 + --> $DIR/literals.rs:56:18 | -55 | let fail15 = 4_64; +56 | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/literals.rs:56:18 + --> $DIR/literals.rs:57:18 | -56 | let fail16 = 7_8; +57 | let fail16 = 7_8; | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/literals.rs:57:18 + --> $DIR/literals.rs:58:18 | -57 | let fail17 = 23_16; +58 | let fail17 = 23_16; | ^^^^^ help: did you mean to write: `23_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:59:18 + --> $DIR/literals.rs:60:18 | -59 | let fail19 = 12_3456_21; +60 | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:60:18 + --> $DIR/literals.rs:61:18 | -60 | let fail20 = 2__8; +61 | let fail20 = 2__8; | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/literals.rs:61:18 + --> $DIR/literals.rs:62:18 | -61 | let fail21 = 4___16; +62 | let fail21 = 4___16; | ^^^^^^ help: did you mean to write: `4_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:62:18 + --> $DIR/literals.rs:63:18 | -62 | let fail22 = 3__4___23; +63 | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:63:18 + --> $DIR/literals.rs:64:18 | -63 | let fail23 = 3__16___23; +64 | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: mistyped literal suffix - --> $DIR/literals.rs:65:18 + --> $DIR/literals.rs:66:18 | -65 | let fail24 = 12.34_64; +66 | let fail24 = 12.34_64; | ^^^^^^^^ help: did you mean to write: `12.34_f64` error: mistyped literal suffix - --> $DIR/literals.rs:66:18 + --> $DIR/literals.rs:67:18 | -66 | let fail25 = 1E2_32; +67 | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> $DIR/literals.rs:67:18 + --> $DIR/literals.rs:68:18 | -67 | let fail26 = 43E7_64; +68 | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> $DIR/literals.rs:68:18 + --> $DIR/literals.rs:69:18 | -68 | let fail27 = 243E17_32; +69 | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix - --> $DIR/literals.rs:69:18 + --> $DIR/literals.rs:70:18 | -69 | let fail28 = 241251235E723_64; +70 | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix - --> $DIR/literals.rs:70:18 + --> $DIR/literals.rs:71:18 | -70 | let fail29 = 42279.911_32; +71 | let fail29 = 42279.911_32; | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` error: aborting due to 31 previous errors -- cgit 1.4.1-3-g733a5 From 40d58f9195c7dbee117ad3a918768a489b51dc74 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Dec 2018 09:33:23 +0100 Subject: Mention triage procedure in contributing.md --- CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76b9cc166c7..fffa8784961 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,6 +22,7 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Linting Clippy with your local changes](#linting-clippy-with-your-local-changes) * [How Clippy works](#how-clippy-works) * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) +* [Issue and PR Triage](#issue-and-pr-triage) * [Contributions](#contributions) ## Getting started @@ -254,6 +255,20 @@ rustup override set master cargo test ``` +## Issue and PR triage + +Clippy is following the [Rust triage procedure][triage] for issues and pull +requests. + +However, we are a smaller project with all contributors being volunteers +currently. Between writing new lints, fixing issues, reviewing pull requests and +responding to issues there may not always be enough time to stay on top of it +all. + +Our highest priority is fixing [crashes][l-crash] and [bugs][l-bug]. We don't +want Clippy to crash on your code and we want it to be as reliable as the +suggestions from Rust compiler errors. + ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will @@ -282,3 +297,6 @@ or the [MIT](http://opensource.org/licenses/MIT) license. [clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories +[triage]: https://forge.rust-lang.org/triage-procedure.html +[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A +[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A -- cgit 1.4.1-3-g733a5 From 3a7da8b4fa66d08d4da613170ff34bf05bd02e00 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Dec 2018 10:57:56 +0100 Subject: Enforce LF lineendings for everything Someone on discord reported issues with UI tests. This should make sure that git never automatically converts lineendings for text files to `CRLF`. They should always be `LF` now. Probably this means that we can stop using dos2unix for #3306, too. Taken from [Rust's .gitattributes file](https://github.com/rust-lang/rust/blob/master/.gitattributes). --- .gitattributes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..45bca848f8f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 + +* text=auto eol=lf +*.rs rust -- cgit 1.4.1-3-g733a5 From 451085ca8dab5a14b6831fe35684618dcfbf0c97 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Dec 2018 11:45:05 +0100 Subject: Fix some nursery links --- CONTRIBUTING.md | 2 +- etc/relicense/RELICENSE_DOCUMENTATION.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76b9cc166c7..26e599c9ebb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -130,7 +130,7 @@ Please document your lint with a doc comment akin to the following: /// ``` ``` -Once your lint is merged it will show up in the [lint list](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +Once your lint is merged it will show up in the [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) ### Running test suite diff --git a/etc/relicense/RELICENSE_DOCUMENTATION.md b/etc/relicense/RELICENSE_DOCUMENTATION.md index 5abe8b694a3..847e66e65e3 100644 --- a/etc/relicense/RELICENSE_DOCUMENTATION.md +++ b/etc/relicense/RELICENSE_DOCUMENTATION.md @@ -17,13 +17,13 @@ The usernames of commenters on these issues can be found in relicense_comments.t There are a couple people in relicense_comments.txt who are not found in contributors.txt: - - @EpocSquadron has [made minor text contributions to the README](https://github.com/rust-lang-nursery/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and doesn't count - - @JayKickliter [agreed to the relicense on their pull request](https://github.com/rust-lang-nursery/rust-clippy/pull/3195#issuecomment-423781016) ([archive](https://web.archive.org/web/20181005190730/https://github.com/rust-lang-nursery/rust-clippy/pull/3195), [screenshot](https://user-images.githubusercontent.com/1617736/46573514-5cb69580-c94b-11e8-8ffb-05a5bd02e2cc.png) + - @EpocSquadron has [made minor text contributions to the README](https://github.com/rust-lang/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and doesn't count + - @JayKickliter [agreed to the relicense on their pull request](https://github.com/rust-lang/rust-clippy/pull/3195#issuecomment-423781016) ([archive](https://web.archive.org/web/20181005190730/https://github.com/rust-lang/rust-clippy/pull/3195), [screenshot](https://user-images.githubusercontent.com/1617736/46573514-5cb69580-c94b-11e8-8ffb-05a5bd02e2cc.png) ) - - @sanmai-NL's [contribution](https://github.com/rust-lang-nursery/rust-clippy/commits?author=sanmai-NL) is a minor one-word addition which doesn't count for copyright assignment - - @zmt00's [contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=zmt00) are minor typo fixes and don't count - - @VKlayd has [nonminor contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=VKlayd) which we rewrote (see below) - - @wartman4404 has [nonminor contributions](https://github.com/rust-lang-nursery/rust-clippy/commits?author=wartman4404) which we rewrote (see below) + - @sanmai-NL's [contribution](https://github.com/rust-lang/rust-clippy/commits?author=sanmai-NL) is a minor one-word addition which doesn't count for copyright assignment + - @zmt00's [contributions](https://github.com/rust-lang/rust-clippy/commits?author=zmt00) are minor typo fixes and don't count + - @VKlayd has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=VKlayd) which we rewrote (see below) + - @wartman4404 has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=wartman4404) which we rewrote (see below) Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251 ([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251), [screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png) @@ -33,4 +33,4 @@ First, I (Manishearth) removed the lints they had added. I then documented at a ------ -Since this document was written, @JayKickliter and @sanmai-ML added their consent in #3230 ([archive](http://web.archive.org/web/20181006171926/https://github.com/rust-lang-nursery/rust-clippy/issues/3230)) \ No newline at end of file +Since this document was written, @JayKickliter and @sanmai-ML added their consent in #3230 ([archive](http://web.archive.org/web/20181006171926/https://github.com/rust-lang-nursery/rust-clippy/issues/3230)) -- cgit 1.4.1-3-g733a5 From d8166bf141f8e245569430eed98f4ba38a5957bc Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Dec 2018 14:33:19 +0100 Subject: Travis: Add rustc sysroot bin to PATH for windows build --- ci/base-tests.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index e46f8c4c39a..a046d21c4be 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -28,6 +28,9 @@ cd clippy_dev && cargo test && cd .. ./util/dev update_lints --check cargo +nightly fmt --all -- --check +# Add bin to PATH for windows +PATH=$PATH:$(rustc --print sysroot)/bin + CLIPPY="`pwd`/target/debug/cargo-clippy clippy" # run clippy on its own codebase... ${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal -Dclippy::pedantic -- cgit 1.4.1-3-g733a5 From 39f179da450e8879341ed662e69ee95e6fcff9e3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 2 Dec 2018 15:08:11 +0100 Subject: Disable incremental build for windows Testing if this speeds up compilation time for the Windows CI build. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a2db0033e2f..b3331c8a26d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,7 +52,7 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: BASE_TESTS=true + env: CARGO_INCREMENTAL=0 BASE_TESTS=true - env: INTEGRATION=rust-lang/cargo if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=rust-random/rand @@ -81,7 +81,7 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ allow_failures: - os: windows - env: BASE_TESTS=true + env: CARGO_INCREMENTAL=0 BASE_TESTS=true # prevent these jobs with default env vars exclude: - os: linux -- cgit 1.4.1-3-g733a5 From ebd508e0acc39b6170d8e374c7bfa75d121c7e58 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 3 Dec 2018 07:13:00 +0100 Subject: Fix rustfmt format --- clippy_lints/src/redundant_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 77f8d7578d8..eece07d006a 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -280,7 +280,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { match ctx { PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => { - return + return; }, _ => {}, } -- cgit 1.4.1-3-g733a5 From ef64c762d24d763886d79d11f0e4d76446858ee5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 3 Dec 2018 08:12:35 +0100 Subject: Fix wildcard_dependencies false positive This now only checks for wildcard_dependencies if the source is a non-git source. I tried adding a compiletest suite for the cargo lints, but I was unable to override the `Cargo.toml` of the original executable. I tested this manually by modifying the main `Cargo.toml`. Fixes #3458 --- clippy_lints/src/wildcard_dependencies.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 59f3cc78afe..d7178f1f11a 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -12,6 +12,7 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; +use if_chain::if_chain; use cargo_metadata; use semver; @@ -54,8 +55,12 @@ impl EarlyLintPass for Pass { for dep in &metadata.packages[0].dependencies { // VersionReq::any() does not work - if let Ok(wildcard_ver) = semver::VersionReq::parse("*") { - if dep.req == wildcard_ver { + if_chain! { + if let Ok(wildcard_ver) = semver::VersionReq::parse("*"); + if let Some(ref source) = dep.source; + if !source.starts_with("git"); + if dep.req == wildcard_ver; + then { span_lint( cx, WILDCARD_DEPENDENCIES, -- cgit 1.4.1-3-g733a5 From e632a1946e1f5f943c46719692f6127fe2877747 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Dec 2018 02:43:01 -0800 Subject: Remove unsafe_vector_initialization lint --- README.md | 2 +- clippy_lints/src/deprecated_lints.rs | 11 ++++++ clippy_lints/src/lib.rs | 5 ++- clippy_lints/src/slow_vector_initialization.rs | 53 +------------------------ tests/ui/slow_vector_initialization.rs | 11 ------ tests/ui/slow_vector_initialization.stderr | 55 +++++++++++--------------- 6 files changed, 39 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 92bb4586688..0d83224e3f6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 289 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 904036fe888..17bef09164b 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -112,3 +112,14 @@ declare_deprecated_lint! { pub IF_LET_REDUNDANT_PATTERN_MATCHING, "this lint has been changed to redundant_pattern_matching" } + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This lint used to suggest replacing `let mut vec = +/// Vec::with_capacity(n); vec.set_len(n);` with `let vec = vec![0; n];`. The +/// replacement has very different performance characteristics so the lint is +/// deprecated. +declare_deprecated_lint! { + pub UNSAFE_VECTOR_INITIALIZATION, + "the replacement suggested by this lint had substantially different behavior" +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c2e625f3d52..f08294c8397 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -330,6 +330,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { "if_let_redundant_pattern_matching", "this lint has been changed to redundant_pattern_matching", ); + store.register_removed( + "unsafe_vector_initialization", + "the replacement suggested by this lint had substantially different behavior", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` reg.register_late_lint_pass(box serde_api::Serde); @@ -495,7 +499,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, - slow_vector_initialization::UNSAFE_VECTOR_INITIALIZATION, strings::STRING_ADD, write::PRINT_STDOUT, write::USE_DEBUG, diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 2964bb6fac7..0ec6fc0d0d1 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -39,32 +39,12 @@ declare_clippy_lint! { "slow vector initialization" } -/// **What it does:** Checks unsafe vector initialization -/// -/// **Why is this bad?** Changing the length of a vector may expose uninitialized memory, which -/// can lead to memory safety issues -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// let mut vec1 = Vec::with_capacity(len); -/// unsafe { -/// vec1.set_len(len); -/// } -/// ``` -declare_clippy_lint! { - pub UNSAFE_VECTOR_INITIALIZATION, - restriction, - "unsafe vector initialization" -} - #[derive(Copy, Clone, Default)] pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(SLOW_VECTOR_INITIALIZATION, UNSAFE_VECTOR_INITIALIZATION,) + lint_array!(SLOW_VECTOR_INITIALIZATION,) } } @@ -90,9 +70,6 @@ enum InitializationType<'tcx> { /// Resize is a slow initialization with the form `vec.resize(.., 0)` Resize(&'tcx Expr), - - /// UnsafeSetLen is a slow initialization with the form `vec.set_len(..)` - UnsafeSetLen(&'tcx Expr), } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { @@ -188,14 +165,6 @@ impl Pass { vec_alloc: &VecAllocation<'_>, ) { match initialization { - InitializationType::UnsafeSetLen(e) => Self::emit_lint( - cx, - e, - vec_alloc, - "unsafe vector initialization", - UNSAFE_VECTOR_INITIALIZATION, - ), - InitializationType::Extend(e) | InitializationType::Resize(e) => Self::emit_lint( cx, e, @@ -282,25 +251,6 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { } } - /// Checks if the given expression is using `set_len` to initialize the vector - fn search_unsafe_set_len(&mut self, expr: &'tcx Expr) { - if_chain! { - if self.initialization_found; - if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; - if let ExprKind::Path(ref qpath_subj) = args[0].node; - if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]); - if path.ident.name == "set_len"; - if let Some(ref len_arg) = args.get(1); - - // Check that len expression is equals to `with_capacity` expression - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); - - then { - self.slow_expression = Some(InitializationType::UnsafeSetLen(expr)); - } - } - } - /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&self, expr: &Expr) -> bool { if_chain! { @@ -349,7 +299,6 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => { self.search_slow_extend_filling(expr); self.search_slow_resize_filling(expr); - self.search_unsafe_set_len(expr); }, _ => (), } diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index aa80fc87aa2..5364bf70ff0 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -7,15 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![warn(clippy::unsafe_vector_initialization)] - use std::iter::repeat; fn main() { resize_vector(); extend_vector(); mixed_extend_resize_vector(); - unsafe_vector(); } fn extend_vector() { @@ -65,14 +62,6 @@ fn resize_vector() { vec1.resize(10, 0); } -fn unsafe_vector() { - let mut unsafe_vec: Vec = Vec::with_capacity(200); - - unsafe { - unsafe_vec.set_len(200); - } -} - fn do_stuff(vec: &mut Vec) { } diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index bc05dd6e1e5..f45c3b48b1b 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,71 +1,60 @@ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:25:5 + --> $DIR/slow_vector_initialization.rs:22:5 | -24 | let mut vec1 = Vec::with_capacity(len); +21 | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -25 | vec1.extend(repeat(0).take(len)); +22 | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:29:5 + --> $DIR/slow_vector_initialization.rs:26:5 | -28 | let mut vec2 = Vec::with_capacity(len - 10); +25 | let mut vec2 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -29 | vec2.extend(repeat(0).take(len - 10)); +26 | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:43:5 + --> $DIR/slow_vector_initialization.rs:40:5 | -42 | let mut resized_vec = Vec::with_capacity(30); +39 | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -43 | resized_vec.resize(30, 0); +40 | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:46:5 + --> $DIR/slow_vector_initialization.rs:43:5 | -45 | let mut extend_vec = Vec::with_capacity(30); +42 | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -46 | extend_vec.extend(repeat(0).take(30)); +43 | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:53:5 + --> $DIR/slow_vector_initialization.rs:50:5 | -52 | let mut vec1 = Vec::with_capacity(len); +49 | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -53 | vec1.resize(len, 0); +50 | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:61:5 + --> $DIR/slow_vector_initialization.rs:58:5 | -60 | let mut vec3 = Vec::with_capacity(len - 10); +57 | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -61 | vec3.resize(len - 10, 0); +58 | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:65:5 + --> $DIR/slow_vector_initialization.rs:62:5 | -64 | vec1 = Vec::with_capacity(10); +61 | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replace allocation with: `vec![0; 10]` -65 | vec1.resize(10, 0); +62 | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: unsafe vector initialization - --> $DIR/slow_vector_initialization.rs:72:9 - | -69 | let mut unsafe_vec: Vec = Vec::with_capacity(200); - | ----------------------- help: consider replace allocation with: `vec![0; 200]` -... -72 | unsafe_vec.set_len(200); - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unsafe-vector-initialization` implied by `-D warnings` - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 393014805986a1360d9b2ec4fd54137839777dbe Mon Sep 17 00:00:00 2001 From: Lucas Lois Date: Fri, 30 Nov 2018 10:21:11 -0300 Subject: Adds inequality cases to bool comparison lint The lint now checks cases like `y != true` --- clippy_lints/src/needless_bool.rs | 130 +++++++++++++++++++------------------- tests/ui/bool_comparison.rs | 4 ++ tests/ui/bool_comparison.stderr | 26 +++++++- 3 files changed, 95 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index e3db1f79ed7..3bb87fbf5e9 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -18,7 +18,7 @@ use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::syntax::source_map::Spanned; use crate::utils::sugg::Sugg; -use crate::utils::{in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg}; +use crate::utils::{in_macro, span_lint, span_lint_and_sugg}; /// **What it does:** Checks for expressions of the form `if c { true } else { /// false }` @@ -45,8 +45,8 @@ declare_clippy_lint! { "if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`" } -/// **What it does:** Checks for expressions of the form `x == true` (or vice -/// versa) and suggest using the variable directly. +/// **What it does:** Checks for expressions of the form `x == true` and +/// `x != true` (or vice versa) and suggest using the variable directly. /// /// **Why is this bad?** Unnecessary code. /// @@ -59,7 +59,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub BOOL_COMPARISON, complexity, - "comparing a variable to a boolean, e.g. `if x == true`" + "comparing a variable to a boolean, e.g. `if x == true` or `if x != true`" } #[derive(Copy, Clone)] @@ -138,76 +138,78 @@ impl LintPass for BoolComparison { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use self::Expression::*; - if in_macro(e.span) { return; } - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Eq, .. - }, - ref left_side, - ref right_side, - ) = e.node - { - let mut applicability = Applicability::MachineApplicable; - match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Bool(true), Other) => { - let hint = snippet_with_applicability(cx, right_side.span, "..", &mut applicability); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint.to_string(), - applicability, - ); - }, - (Other, Bool(true)) => { - let hint = snippet_with_applicability(cx, left_side.span, "..", &mut applicability); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against true are unnecessary", - "try simplifying it as shown", - hint.to_string(), - applicability, - ); - }, - (Bool(false), Other) => { - let hint = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - applicability, - ); - }, - (Other, Bool(false)) => { - let hint = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability); - span_lint_and_sugg( - cx, - BOOL_COMPARISON, - e.span, - "equality checks against false can be replaced by a negation", - "try simplifying it as shown", - (!hint).to_string(), - applicability, - ); - }, + if let ExprKind::Binary(Spanned { node, .. }, ..) = e.node { + match node { + BinOpKind::Eq => check_comparison( + cx, + e, + "equality checks against true are unnecessary", + "equality checks against false can be replaced by a negation", + |h| h, + |h| !h, + ), + BinOpKind::Ne => check_comparison( + cx, + e, + "inequality checks against true can be replaced by a negation", + "inequality checks against false are unnecessary", + |h| !h, + |h| h, + ), _ => (), } } } } +fn check_comparison<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + e: &'tcx Expr, + true_message: &str, + false_message: &str, + true_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, + false_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, +) { + use self::Expression::*; + + if let ExprKind::Binary(_, ref left_side, ref right_side) = e.node { + let applicability = Applicability::MachineApplicable; + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { + (Bool(true), Other) => suggest_bool_comparison(cx, e, right_side, applicability, true_message, true_hint), + (Other, Bool(true)) => suggest_bool_comparison(cx, e, left_side, applicability, true_message, true_hint), + (Bool(false), Other) => { + suggest_bool_comparison(cx, e, right_side, applicability, false_message, false_hint) + }, + (Other, Bool(false)) => suggest_bool_comparison(cx, e, left_side, applicability, false_message, false_hint), + _ => (), + } + } +} + +fn suggest_bool_comparison<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + e: &'tcx Expr, + expr: &Expr, + mut applicability: Applicability, + message: &str, + conv_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, +) { + let hint = Sugg::hir_with_applicability(cx, expr, "..", &mut applicability); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + message, + "try simplifying it as shown", + conv_hint(hint).to_string(), + applicability, + ); +} + enum Expression { Bool(bool), RetBool(bool), diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index c213414a63d..8ab8b3f9281 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -18,4 +18,8 @@ fn main() { if x == false { "yes" } else { "no" }; if true == x { "yes" } else { "no" }; if false == x { "yes" } else { "no" }; + if x != true { "yes" } else { "no" }; + if x != false { "yes" } else { "no" }; + if true != x { "yes" } else { "no" }; + if false != x { "yes" } else { "no" }; } diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index f1bb50fae9e..b4a1545b49e 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -24,5 +24,29 @@ error: equality checks against false can be replaced by a negation 20 | if false == x { "yes" } else { "no" }; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` -error: aborting due to 4 previous errors +error: inequality checks against true can be replaced by a negation + --> $DIR/bool_comparison.rs:21:8 + | +21 | if x != true { "yes" } else { "no" }; + | ^^^^^^^^^ help: try simplifying it as shown: `!x` + +error: inequality checks against false are unnecessary + --> $DIR/bool_comparison.rs:22:8 + | +22 | if x != false { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try simplifying it as shown: `x` + +error: inequality checks against true can be replaced by a negation + --> $DIR/bool_comparison.rs:23:8 + | +23 | if true != x { "yes" } else { "no" }; + | ^^^^^^^^^ help: try simplifying it as shown: `!x` + +error: inequality checks against false are unnecessary + --> $DIR/bool_comparison.rs:24:8 + | +24 | if false != x { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try simplifying it as shown: `x` + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 46ee676139006c74d7d7594a755d84290a5f1eee Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 4 Dec 2018 06:47:41 +0100 Subject: cargo fmt --- clippy_lints/src/wildcard_dependencies.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index d7178f1f11a..6de391d882f 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -12,8 +12,8 @@ use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; -use if_chain::if_chain; use cargo_metadata; +use if_chain::if_chain; use semver; /// **What it does:** Checks for wildcard dependencies in the `Cargo.toml`. -- cgit 1.4.1-3-g733a5 From 3f72d4d63084b82dcced7ec0d18e60da688c857f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 4 Dec 2018 07:17:53 +0100 Subject: Extract single_match_else UI test There's only one test currently. I also updated the lint doc with a 'good' example and changed the lint help text a bit. cc #2038 --- clippy_lints/src/matches.rs | 17 ++- tests/ui/matches.rs | 16 +-- tests/ui/matches.stderr | 260 ++++++++++++++++++-------------------- tests/ui/single_match_else.rs | 27 ++++ tests/ui/single_match_else.stderr | 13 ++ 5 files changed, 176 insertions(+), 157 deletions(-) create mode 100644 tests/ui/single_match_else.rs create mode 100644 tests/ui/single_match_else.stderr diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index dedf9a16b35..3ef8d534861 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -45,7 +45,7 @@ declare_clippy_lint! { "a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let`" } -/// **What it does:** Checks for matches with a two arms where an `if let` will +/// **What it does:** Checks for matches with a two arms where an `if let else` will /// usually suffice. /// /// **Why is this bad?** Just readability – `if let` nests less than a `match`. @@ -53,16 +53,29 @@ declare_clippy_lint! { /// **Known problems:** Personal style preferences may differ. /// /// **Example:** +/// +/// Using `match`: +/// /// ```rust /// match x { /// Some(ref foo) => bar(foo), /// _ => bar(other_ref), /// } /// ``` +/// +/// Using `if let` with `else`: +/// +/// ```rust +/// if let Some(ref foo) = x { +/// bar(foo); +/// } else { +/// bar(other_ref); +/// } +/// ``` declare_clippy_lint! { pub SINGLE_MATCH_ELSE, pedantic, - "a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let`" + "a match statement with a two arms where the second arm's pattern is a placeholder instead of a specific match pattern" } /// **What it does:** Checks for matches where all arms match a reference, diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index c7630b0533d..e5b8f6f4c1c 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -14,26 +14,12 @@ #![warn(clippy::all)] #![allow(unused, clippy::redundant_pattern_matching)] -#![warn(clippy::single_match_else, clippy::match_same_arms)] +#![warn(clippy::match_same_arms)] -enum ExprNode { - ExprAddrOf, - Butterflies, - Unicorns, -} - -static NODE: ExprNode = ExprNode::Unicorns; fn dummy() { } -fn unwrap_addr() -> Option<&'static ExprNode> { - match ExprNode::Butterflies { - ExprNode::ExprAddrOf => Some(&NODE), - _ => { let x = 5; None }, - } -} - fn ref_pats() { { let v = &Some(0); diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index aebb166d3bc..53e61efa83a 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,302 +1,282 @@ -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:31:5 - | -31 | / match ExprNode::Butterflies { -32 | | ExprNode::ExprAddrOf => Some(&NODE), -33 | | _ => { let x = 5; None }, -34 | | } - | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` - | - = note: `-D clippy::single-match-else` implied by `-D warnings` - error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:40:9 + --> $DIR/matches.rs:26:9 | -40 | / match v { -41 | | &Some(v) => println!("{:?}", v), -42 | | &None => println!("none"), -43 | | } +26 | / match v { +27 | | &Some(v) => println!("{:?}", v), +28 | | &None => println!("none"), +29 | | } | |_________^ | = note: `-D clippy::match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -40 | match *v { -41 | Some(v) => println!("{:?}", v), -42 | None => println!("none"), +26 | match *v { +27 | Some(v) => println!("{:?}", v), +28 | None => println!("none"), | -error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/matches.rs:50:5 - | -50 | / match tup { -51 | | &(v, 1) => println!("{}", v), -52 | | _ => println!("none"), -53 | | } - | |_____^ help: try this: `if let &(v, 1) = tup { println!("{}", v) } else { println!("none") }` - error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:50:5 + --> $DIR/matches.rs:36:5 | -50 | / match tup { -51 | | &(v, 1) => println!("{}", v), -52 | | _ => println!("none"), -53 | | } +36 | / match tup { +37 | | &(v, 1) => println!("{}", v), +38 | | _ => println!("none"), +39 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -50 | match *tup { -51 | (v, 1) => println!("{}", v), +36 | match *tup { +37 | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:56:5 + --> $DIR/matches.rs:42:5 | -56 | / match &w { -57 | | &Some(v) => println!("{:?}", v), -58 | | &None => println!("none"), -59 | | } +42 | / match &w { +43 | | &Some(v) => println!("{:?}", v), +44 | | &None => println!("none"), +45 | | } | |_____^ help: try | -56 | match w { -57 | Some(v) => println!("{:?}", v), -58 | None => println!("none"), +42 | match w { +43 | Some(v) => println!("{:?}", v), +44 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:67:5 + --> $DIR/matches.rs:53:5 | -67 | / if let &None = a { -68 | | println!("none"); -69 | | } +53 | / if let &None = a { +54 | | println!("none"); +55 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -67 | if let None = *a { +53 | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:72:5 + --> $DIR/matches.rs:58:5 | -72 | / if let &None = &b { -73 | | println!("none"); -74 | | } +58 | / if let &None = &b { +59 | | println!("none"); +60 | | } | |_____^ help: try | -72 | if let None = b { +58 | if let None = b { | ^^^^ ^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:83:9 + --> $DIR/matches.rs:69:9 | -83 | Err(_) => panic!("err") +69 | Err(_) => panic!("err") | ^^^^^^ | = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:82:18 + --> $DIR/matches.rs:68:18 | -82 | Ok(_) => println!("ok"), +68 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:81:18 + --> $DIR/matches.rs:67:18 | -81 | Ok(3) => println!("ok"), +67 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:81:18 + --> $DIR/matches.rs:67:18 | -81 | Ok(3) => println!("ok"), +67 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:89:9 + --> $DIR/matches.rs:75:9 | -89 | Err(_) => {panic!()} +75 | Err(_) => {panic!()} | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:88:18 + --> $DIR/matches.rs:74:18 | -88 | Ok(_) => println!("ok"), +74 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:73:18 | -87 | Ok(3) => println!("ok"), +73 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:73:18 | -87 | Ok(3) => println!("ok"), +73 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:95:9 + --> $DIR/matches.rs:81:9 | -95 | Err(_) => {panic!();} +81 | Err(_) => {panic!();} | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:94:18 + --> $DIR/matches.rs:80:18 | -94 | Ok(_) => println!("ok"), +80 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:79:18 | -93 | Ok(3) => println!("ok"), +79 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:79:18 | -93 | Ok(3) => println!("ok"), +79 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:101:18 - | -101 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:87:18 + | +87 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:100:18 - | -100 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:86:18 + | +86 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:100:18 - | -100 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:86:18 + | +86 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:108:18 - | -108 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:94:18 + | +94 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:107:18 - | -107 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:93:18 + | +93 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:107:18 - | -107 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:93:18 + | +93 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:114:18 + --> $DIR/matches.rs:100:18 | -114 | Ok(_) => println!("ok"), +100 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:113:18 + --> $DIR/matches.rs:99:18 | -113 | Ok(3) => println!("ok"), +99 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:113:18 + --> $DIR/matches.rs:99:18 | -113 | Ok(3) => println!("ok"), +99 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:120:18 + --> $DIR/matches.rs:106:18 | -120 | Ok(_) => println!("ok"), +106 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:119:18 + --> $DIR/matches.rs:105:18 | -119 | Ok(3) => println!("ok"), +105 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:119:18 + --> $DIR/matches.rs:105:18 | -119 | Ok(3) => println!("ok"), +105 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:141:29 + --> $DIR/matches.rs:127:29 | -141 | (Ok(_), Some(x)) => println!("ok {}", x), +127 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:140:29 + --> $DIR/matches.rs:126:29 | -140 | (Ok(x), Some(_)) => println!("ok {}", x), +126 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:140:29 + --> $DIR/matches.rs:126:29 | -140 | (Ok(x), Some(_)) => println!("ok {}", x), +126 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:156:18 + --> $DIR/matches.rs:142:18 | -156 | Ok(_) => println!("ok"), +142 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:155:18 + --> $DIR/matches.rs:141:18 | -155 | Ok(3) => println!("ok"), +141 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:155:18 + --> $DIR/matches.rs:141:18 | -155 | Ok(3) => println!("ok"), +141 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:163:33 + --> $DIR/matches.rs:149:33 | -163 | let borrowed: Option<&()> = match owned { +149 | let borrowed: Option<&()> = match owned { | _________________________________^ -164 | | None => None, -165 | | Some(ref v) => Some(v), -166 | | }; +150 | | None => None, +151 | | Some(ref v) => Some(v), +152 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:169:39 + --> $DIR/matches.rs:155:39 | -169 | let borrow_mut: Option<&mut ()> = match mut_owned { +155 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -170 | | None => None, -171 | | Some(ref mut v) => Some(v), -172 | | }; +156 | | None => None, +157 | | Some(ref mut v) => Some(v), +158 | | }; | |_____^ help: try this: `mut_owned.as_mut()` -error: aborting due to 21 previous errors +error: aborting due to 19 previous errors diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs new file mode 100644 index 00000000000..a7c28c578a4 --- /dev/null +++ b/tests/ui/single_match_else.rs @@ -0,0 +1,27 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::single_match_else)] + +enum ExprNode { + ExprAddrOf, + Butterflies, + Unicorns, +} + +static NODE: ExprNode = ExprNode::Unicorns; + +fn unwrap_addr() -> Option<&'static ExprNode> { + match ExprNode::Butterflies { + ExprNode::ExprAddrOf => Some(&NODE), + _ => { let x = 5; None }, + } +} + +fn main() {} diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr new file mode 100644 index 00000000000..0b488b2fcf4 --- /dev/null +++ b/tests/ui/single_match_else.stderr @@ -0,0 +1,13 @@ +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:21:5 + | +21 | / match ExprNode::Butterflies { +22 | | ExprNode::ExprAddrOf => Some(&NODE), +23 | | _ => { let x = 5; None }, +24 | | } + | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` + | + = note: `-D clippy::single-match-else` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From d5d669228867259277ce2724bb2fa510d16f0b47 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 5 Dec 2018 01:59:09 +0100 Subject: Added `FORCED_RETURN` lint. --- README.md | 2 +- clippy_lints/src/forced_return.rs | 106 ++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 3 ++ tests/ui/forced_return.rs | 55 ++++++++++++++++++++ tests/ui/forced_return.stderr | 46 +++++++++++++++++ 5 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/forced_return.rs create mode 100644 tests/ui/forced_return.rs create mode 100644 tests/ui/forced_return.stderr diff --git a/README.md b/README.md index 0d83224e3f6..92bb4586688 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 289 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/forced_return.rs b/clippy_lints/src/forced_return.rs new file mode 100644 index 00000000000..ee30bd0ab1e --- /dev/null +++ b/clippy_lints/src/forced_return.rs @@ -0,0 +1,106 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::{ast::NodeId, source_map::Span}; +use crate::utils::{snippet_opt, span_lint_and_then}; + +/// **What it does:** Checks for missing return statements at the end of a block. +/// +/// **Why is this bad?** Actually it is idiomatic Rust code. Programmers coming +/// from other languages might prefer the expressiveness of `return`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn foo(x: usize) { +/// x +/// } +/// ``` +/// add return +/// ```rust +/// fn foo(x: usize) { +/// return x; +/// } +/// ``` +declare_clippy_lint! { + pub FORCED_RETURN, + restriction, + "use a return statement like `return expr` instead of an expression" +} + +pub struct ForcedReturnPass; + +impl ForcedReturnPass { + fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) { + span_lint_and_then(cx, FORCED_RETURN, span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, span) { + db.span_suggestion_with_applicability( + span, + "add `return` as shown", + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }); + } + + fn expr_match(cx: &LateContext<'_, '_>, kind: &ExprKind) { + match kind { + ExprKind::Block(ref block, ..) => { + if let Some(ref expr) = block.expr { + Self::expr_match(cx, &expr.node); + } + }, + ExprKind::If(.., if_expr, else_expr) => { + Self::expr_match(cx, &if_expr.node); + + if let Some(else_expr) = else_expr { + Self::expr_match(cx, &else_expr.node); + } + }, + ExprKind::Match(_, arms, ..) => { + for arm in arms { + Self::expr_match(cx, &arm.body.node); + } + }, + ExprKind::Lit(lit) => Self::show_suggestion(cx, lit.span), + _ => (), + } + } +} + +impl LintPass for ForcedReturnPass { + fn get_lints(&self) -> LintArray { + lint_array!(FORCED_RETURN) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ForcedReturnPass { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl, + body: &'tcx Body, + _: Span, + _: NodeId, + ) { + let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let mir = cx.tcx.optimized_mir(def_id); + + if !mir.return_ty().is_unit() { + Self::expr_match(cx, &body.value.node); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 326bf884e33..729e3a20c2c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -185,6 +185,7 @@ pub mod reference; pub mod regex; pub mod replace_consts; pub mod returns; +pub mod forced_return; pub mod serde_api; pub mod shadow; pub mod slow_vector_initialization; @@ -371,6 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); + reg.register_late_lint_pass(box forced_return::ForcedReturnPass); reg.register_late_lint_pass(box methods::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); @@ -502,6 +504,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { strings::STRING_ADD, write::PRINT_STDOUT, write::USE_DEBUG, + forced_return::FORCED_RETURN, ]); reg.register_lint_group("clippy::pedantic", Some("clippy_pedantic"), vec![ diff --git a/tests/ui/forced_return.rs b/tests/ui/forced_return.rs new file mode 100644 index 00000000000..5f07d99528e --- /dev/null +++ b/tests/ui/forced_return.rs @@ -0,0 +1,55 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + + + + +#![warn(clippy::forced_return)] + +fn test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + true +} + +#[allow(clippy::needless_bool)] +fn test_if_block() -> bool { + if true { + true + } else { + false + } +} + +#[allow(clippy::match_bool)] +fn test_match(x: bool) -> bool { + match x { + true => false, + false => { + true + } + } +} + +fn test_closure() { + let _ = || { + true + }; + let _ = || true; +} + +fn main() { + let _ = test_end_of_fn(); + let _ = test_if_block(); + let _ = test_match(true); + test_closure(); +} diff --git a/tests/ui/forced_return.stderr b/tests/ui/forced_return.stderr new file mode 100644 index 00000000000..0b1dcc4ce33 --- /dev/null +++ b/tests/ui/forced_return.stderr @@ -0,0 +1,46 @@ +error: missing return statement + --> $DIR/forced_return.rs:21:5 + | +21 | true + | ^^^^ help: add `return` as shown: `return true` + | + = note: `-D clippy::forced-return` implied by `-D warnings` + +error: missing return statement + --> $DIR/forced_return.rs:27:9 + | +27 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/forced_return.rs:29:9 + | +29 | false + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/forced_return.rs:36:17 + | +36 | true => false, + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/forced_return.rs:38:13 + | +38 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/forced_return.rs:45:9 + | +45 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/forced_return.rs:47:16 + | +47 | let _ = || true; + | ^^^^ help: add `return` as shown: `return true` + +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 978f8c65ee44b43243a83a047be6cdacb6df1320 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 5 Dec 2018 10:54:21 +0100 Subject: Renamed `forced_return` to `missing_returns`. Better clarification in the docs. Ran `update_lints`. --- CHANGELOG.md | 1 + clippy_lints/src/forced_return.rs | 106 ------------------------------------ clippy_lints/src/lib.rs | 6 +- clippy_lints/src/missing_returns.rs | 106 ++++++++++++++++++++++++++++++++++++ tests/ui/forced_return.rs | 55 ------------------- tests/ui/forced_return.stderr | 46 ---------------- tests/ui/missing_returns.rs | 55 +++++++++++++++++++ tests/ui/missing_returns.stderr | 46 ++++++++++++++++ 8 files changed, 211 insertions(+), 210 deletions(-) delete mode 100644 clippy_lints/src/forced_return.rs create mode 100644 clippy_lints/src/missing_returns.rs delete mode 100644 tests/ui/forced_return.rs delete mode 100644 tests/ui/forced_return.stderr create mode 100644 tests/ui/missing_returns.rs create mode 100644 tests/ui/missing_returns.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 320a3511e5c..ed5057daf29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -756,6 +756,7 @@ All notable changes to this project will be documented in this file. [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items +[`missing_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_returns [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception diff --git a/clippy_lints/src/forced_return.rs b/clippy_lints/src/forced_return.rs deleted file mode 100644 index ee30bd0ab1e..00000000000 --- a/clippy_lints/src/forced_return.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::{ast::NodeId, source_map::Span}; -use crate::utils::{snippet_opt, span_lint_and_then}; - -/// **What it does:** Checks for missing return statements at the end of a block. -/// -/// **Why is this bad?** Actually it is idiomatic Rust code. Programmers coming -/// from other languages might prefer the expressiveness of `return`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn foo(x: usize) { -/// x -/// } -/// ``` -/// add return -/// ```rust -/// fn foo(x: usize) { -/// return x; -/// } -/// ``` -declare_clippy_lint! { - pub FORCED_RETURN, - restriction, - "use a return statement like `return expr` instead of an expression" -} - -pub struct ForcedReturnPass; - -impl ForcedReturnPass { - fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) { - span_lint_and_then(cx, FORCED_RETURN, span, "missing return statement", |db| { - if let Some(snippet) = snippet_opt(cx, span) { - db.span_suggestion_with_applicability( - span, - "add `return` as shown", - format!("return {}", snippet), - Applicability::MachineApplicable, - ); - } - }); - } - - fn expr_match(cx: &LateContext<'_, '_>, kind: &ExprKind) { - match kind { - ExprKind::Block(ref block, ..) => { - if let Some(ref expr) = block.expr { - Self::expr_match(cx, &expr.node); - } - }, - ExprKind::If(.., if_expr, else_expr) => { - Self::expr_match(cx, &if_expr.node); - - if let Some(else_expr) = else_expr { - Self::expr_match(cx, &else_expr.node); - } - }, - ExprKind::Match(_, arms, ..) => { - for arm in arms { - Self::expr_match(cx, &arm.body.node); - } - }, - ExprKind::Lit(lit) => Self::show_suggestion(cx, lit.span), - _ => (), - } - } -} - -impl LintPass for ForcedReturnPass { - fn get_lints(&self) -> LintArray { - lint_array!(FORCED_RETURN) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ForcedReturnPass { - fn check_fn( - &mut self, - cx: &LateContext<'a, 'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl, - body: &'tcx Body, - _: Span, - _: NodeId, - ) { - let def_id = cx.tcx.hir.body_owner_def_id(body.id()); - let mir = cx.tcx.optimized_mir(def_id); - - if !mir.return_ty().is_unit() { - Self::expr_match(cx, &body.value.node); - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 729e3a20c2c..87dbe8708b9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -152,6 +152,7 @@ pub mod misc; pub mod misc_early; pub mod missing_doc; pub mod missing_inline; +pub mod missing_returns; pub mod multiple_crate_versions; pub mod mut_mut; pub mod mut_reference; @@ -185,7 +186,6 @@ pub mod reference; pub mod regex; pub mod replace_consts; pub mod returns; -pub mod forced_return; pub mod serde_api; pub mod shadow; pub mod slow_vector_initialization; @@ -372,7 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box forced_return::ForcedReturnPass); + reg.register_late_lint_pass(box missing_returns::MissingReturnsPass); reg.register_late_lint_pass(box methods::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); @@ -498,13 +498,13 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, + missing_returns::MISSING_RETURNS, panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, strings::STRING_ADD, write::PRINT_STDOUT, write::USE_DEBUG, - forced_return::FORCED_RETURN, ]); reg.register_lint_group("clippy::pedantic", Some("clippy_pedantic"), vec![ diff --git a/clippy_lints/src/missing_returns.rs b/clippy_lints/src/missing_returns.rs new file mode 100644 index 00000000000..8a4d37a98ac --- /dev/null +++ b/clippy_lints/src/missing_returns.rs @@ -0,0 +1,106 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::{ast::NodeId, source_map::Span}; +use crate::utils::{snippet_opt, span_lint_and_then}; + +/// **What it does:** Checks for missing return statements at the end of a block. +/// +/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers +/// coming from other languages might prefer the expressiveness of `return`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn foo(x: usize) { +/// x +/// } +/// ``` +/// add return +/// ```rust +/// fn foo(x: usize) { +/// return x; +/// } +/// ``` +declare_clippy_lint! { + pub MISSING_RETURNS, + restriction, + "use a return statement like `return expr` instead of an expression" +} + +pub struct MissingReturnsPass; + +impl MissingReturnsPass { + fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) { + span_lint_and_then(cx, MISSING_RETURNS, span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, span) { + db.span_suggestion_with_applicability( + span, + "add `return` as shown", + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }); + } + + fn expr_match(cx: &LateContext<'_, '_>, kind: &ExprKind) { + match kind { + ExprKind::Block(ref block, ..) => { + if let Some(ref expr) = block.expr { + Self::expr_match(cx, &expr.node); + } + }, + ExprKind::If(.., if_expr, else_expr) => { + Self::expr_match(cx, &if_expr.node); + + if let Some(else_expr) = else_expr { + Self::expr_match(cx, &else_expr.node); + } + }, + ExprKind::Match(_, arms, ..) => { + for arm in arms { + Self::expr_match(cx, &arm.body.node); + } + }, + ExprKind::Lit(lit) => Self::show_suggestion(cx, lit.span), + _ => (), + } + } +} + +impl LintPass for MissingReturnsPass { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_RETURNS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingReturnsPass { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl, + body: &'tcx Body, + _: Span, + _: NodeId, + ) { + let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let mir = cx.tcx.optimized_mir(def_id); + + if !mir.return_ty().is_unit() { + Self::expr_match(cx, &body.value.node); + } + } +} diff --git a/tests/ui/forced_return.rs b/tests/ui/forced_return.rs deleted file mode 100644 index 5f07d99528e..00000000000 --- a/tests/ui/forced_return.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - - -#![warn(clippy::forced_return)] - -fn test_end_of_fn() -> bool { - if true { - // no error! - return true; - } - true -} - -#[allow(clippy::needless_bool)] -fn test_if_block() -> bool { - if true { - true - } else { - false - } -} - -#[allow(clippy::match_bool)] -fn test_match(x: bool) -> bool { - match x { - true => false, - false => { - true - } - } -} - -fn test_closure() { - let _ = || { - true - }; - let _ = || true; -} - -fn main() { - let _ = test_end_of_fn(); - let _ = test_if_block(); - let _ = test_match(true); - test_closure(); -} diff --git a/tests/ui/forced_return.stderr b/tests/ui/forced_return.stderr deleted file mode 100644 index 0b1dcc4ce33..00000000000 --- a/tests/ui/forced_return.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: missing return statement - --> $DIR/forced_return.rs:21:5 - | -21 | true - | ^^^^ help: add `return` as shown: `return true` - | - = note: `-D clippy::forced-return` implied by `-D warnings` - -error: missing return statement - --> $DIR/forced_return.rs:27:9 - | -27 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/forced_return.rs:29:9 - | -29 | false - | ^^^^^ help: add `return` as shown: `return false` - -error: missing return statement - --> $DIR/forced_return.rs:36:17 - | -36 | true => false, - | ^^^^^ help: add `return` as shown: `return false` - -error: missing return statement - --> $DIR/forced_return.rs:38:13 - | -38 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/forced_return.rs:45:9 - | -45 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/forced_return.rs:47:16 - | -47 | let _ = || true; - | ^^^^ help: add `return` as shown: `return true` - -error: aborting due to 7 previous errors - diff --git a/tests/ui/missing_returns.rs b/tests/ui/missing_returns.rs new file mode 100644 index 00000000000..96935eb6b53 --- /dev/null +++ b/tests/ui/missing_returns.rs @@ -0,0 +1,55 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + + + + +#![warn(clippy::missing_returns)] + +fn test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + true +} + +#[allow(clippy::needless_bool)] +fn test_if_block() -> bool { + if true { + true + } else { + false + } +} + +#[allow(clippy::match_bool)] +fn test_match(x: bool) -> bool { + match x { + true => false, + false => { + true + } + } +} + +fn test_closure() { + let _ = || { + true + }; + let _ = || true; +} + +fn main() { + let _ = test_end_of_fn(); + let _ = test_if_block(); + let _ = test_match(true); + test_closure(); +} diff --git a/tests/ui/missing_returns.stderr b/tests/ui/missing_returns.stderr new file mode 100644 index 00000000000..874bec9e109 --- /dev/null +++ b/tests/ui/missing_returns.stderr @@ -0,0 +1,46 @@ +error: missing return statement + --> $DIR/missing_returns.rs:21:5 + | +21 | true + | ^^^^ help: add `return` as shown: `return true` + | + = note: `-D clippy::missing-returns` implied by `-D warnings` + +error: missing return statement + --> $DIR/missing_returns.rs:27:9 + | +27 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/missing_returns.rs:29:9 + | +29 | false + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/missing_returns.rs:36:17 + | +36 | true => false, + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/missing_returns.rs:38:13 + | +38 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/missing_returns.rs:45:9 + | +45 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/missing_returns.rs:47:16 + | +47 | let _ = || true; + | ^^^^ help: add `return` as shown: `return true` + +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 19db2f1a325d5030c05d6b3a64cab165c7e15d09 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 5 Dec 2018 11:26:40 +0100 Subject: Appeasing the Test Gods. Seems I'm not smart enough to run the tests locally before committing. --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/missing_returns.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 87dbe8708b9..cb0535a03ac 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -372,7 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box missing_returns::MissingReturnsPass); + reg.register_late_lint_pass(box missing_returns::Pass); reg.register_late_lint_pass(box methods::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); diff --git a/clippy_lints/src/missing_returns.rs b/clippy_lints/src/missing_returns.rs index 8a4d37a98ac..71dc71d563b 100644 --- a/clippy_lints/src/missing_returns.rs +++ b/clippy_lints/src/missing_returns.rs @@ -39,9 +39,9 @@ declare_clippy_lint! { "use a return statement like `return expr` instead of an expression" } -pub struct MissingReturnsPass; +pub struct Pass; -impl MissingReturnsPass { +impl Pass { fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) { span_lint_and_then(cx, MISSING_RETURNS, span, "missing return statement", |db| { if let Some(snippet) = snippet_opt(cx, span) { @@ -80,13 +80,13 @@ impl MissingReturnsPass { } } -impl LintPass for MissingReturnsPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MISSING_RETURNS) } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingReturnsPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, -- cgit 1.4.1-3-g733a5 From 20a07f6d800c40a4ae978c4d814b793027edb99c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Dec 2018 23:19:42 +0100 Subject: Fix TyKind:: usage in codebase --- clippy_lints/src/default_trait_access.rs | 4 ++-- clippy_lints/src/excessive_precision.rs | 4 ++-- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/methods/mod.rs | 10 +++++----- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 7719e35902b..134950b267f 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -9,7 +9,7 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::TyKind; +use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use if_chain::if_chain; @@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. let expr_ty = cx.tables.expr_ty(expr); - if let TyKind::Adt(..) = expr_ty.sty { + if let ty::Adt(..) = expr_ty.sty { let replacement = format!("{}::default()", expr_ty); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index cd0d5941cbe..ff678925d8f 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -9,7 +9,7 @@ use crate::rustc::hir; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::TyKind; +use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::*; @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if_chain! { let ty = cx.tables.expr_ty(expr); - if let TyKind::Float(fty) = ty.sty; + if let ty::Float(fty) = ty.sty; if let hir::ExprKind::Lit(ref lit) = expr.node; if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node; if let Some(sugg) = self.check(sym, fty); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 08ae3a55a2c..67c3fee464a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1252,7 +1252,7 @@ fn is_end_eq_array_len(cx: &LateContext<'_, '_>, end: &Expr, limits: ast::RangeL if_chain! { if let ExprKind::Lit(ref lit) = end.node; if let ast::LitKind::Int(end_int, _) = lit.node; - if let ty::TyKind::Array(_, arr_len_const) = indexed_ty.sty; + if let ty::Array(_, arr_len_const) = indexed_ty.sty; if let Some(arr_len) = arr_len_const.assert_usize(cx.tcx); then { return match limits { @@ -1375,7 +1375,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex match cx.tables.expr_ty(&args[0]).sty { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. - ty::TyKind::Array(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), + ty::Array(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), _ => lint_iter_method(cx, args, arg, method_name), }; } else { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 0df166a0796..648f1ec501e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -10,7 +10,7 @@ use crate::rustc::hir; use crate::rustc::hir::def::Def; use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Predicate, Ty, TyKind}; +use crate::rustc::ty::{self, Predicate, Ty}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast; @@ -978,7 +978,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } // if return type is impl trait, check the associated types - if let TyKind::Opaque(def_id, _) = ret_ty.sty { + if let ty::Opaque(def_id, _) = ret_ty.sty { // one of the associated types must be Self for predicate in &cx.tcx.predicates_of(def_id).predicates { match predicate { @@ -2204,7 +2204,7 @@ fn ty_has_iter_method( ]; let (self_ty, mutbl) = match self_ref_ty.sty { - ty::TyKind::Ref(_, self_ty, mutbl) => (self_ty, mutbl), + ty::Ref(_, self_ty, mutbl) => (self_ty, mutbl), _ => unreachable!(), }; let method_name = match mutbl { @@ -2213,8 +2213,8 @@ fn ty_has_iter_method( }; let def_id = match self_ty.sty { - ty::TyKind::Array(..) => return Some((INTO_ITER_ON_ARRAY, "array", method_name)), - ty::TyKind::Slice(..) => return Some((INTO_ITER_ON_REF, "slice", method_name)), + ty::Array(..) => return Some((INTO_ITER_ON_ARRAY, "array", method_name)), + ty::Slice(..) => return Some((INTO_ITER_ON_REF, "slice", method_name)), ty::Adt(adt, _) => adt.did, _ => return None, }; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 251c3d73959..f1b31a3e0a7 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -219,7 +219,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder<'_>| { - if let ty::TyKind::Adt(def, ..) = ty.sty { + if let ty::Adt(def, ..) = ty.sty { if let Some(span) = cx.tcx.hir.span_if_local(def.did) { if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { db.span_help(span, "consider marking this type as Copy"); diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 587b9b731c3..070d591fcf0 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -14,7 +14,7 @@ use crate::rustc::hir::intravisit::FnKind; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::session::config::Config as SessionConfig; -use crate::rustc::ty::{FnSig, TyKind}; +use crate::rustc::ty::{self, FnSig}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::rustc_target::abi::LayoutOf; @@ -99,8 +99,8 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { // argument. In that case we can't switch to pass-by-value as the // argument will not live long enough. let output_lts = match sig.output().sty { - TyKind::Ref(output_lt, _, _) => vec![output_lt], - TyKind::Adt(_, substs) => substs.regions().collect(), + ty::Ref(output_lt, _, _) => vec![output_lt], + ty::Adt(_, substs) => substs.regions().collect(), _ => vec![], }; @@ -112,7 +112,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { } if_chain! { - if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty; + if let ty::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty; if !output_lts.contains(&input_lt); if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); -- cgit 1.4.1-3-g733a5 From 36ee92780df09e77aaf4db5899c1af94bd49d3c3 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 5 Dec 2018 00:14:44 +0100 Subject: Fix ty::TyKind usage --- clippy_lints/src/consts.rs | 9 ++------- clippy_lints/src/minmax.rs | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 26a92ab8b9f..761630da376 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -119,17 +119,12 @@ impl Hash for Constant { } impl Constant { - pub fn partial_cmp( - tcx: TyCtxt<'_, '_, '_>, - cmp_type: &ty::TyKind<'_>, - left: &Self, - right: &Self, - ) -> Option { + pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: ty::Ty<'_>, left: &Self, right: &Self) -> Option { match (left, right) { (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), (&Constant::Int(l), &Constant::Int(r)) => { - if let ty::Int(int_ty) = *cmp_type { + if let ty::Int(int_ty) = cmp_type.sty { Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))) } else { Some(l.cmp(&r)) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index bddad90d1ef..dd3aa85e600 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { } match ( outer_max, - Constant::partial_cmp(cx.tcx, &cx.tables.expr_ty(ie).sty, &outer_c, &inner_c), + Constant::partial_cmp(cx.tcx, cx.tables.expr_ty(ie), &outer_c, &inner_c), ) { (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { -- cgit 1.4.1-3-g733a5 From aed2b986e6d596f6ed154625030b8c83a67066fe Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 5 Dec 2018 14:39:09 +0100 Subject: Renamed to `implicit_return`. Covered all other kinds besides `ExprKind::Lit`. Added check for replacing `break` with `return`. --- CHANGELOG.md | 2 +- clippy_lints/src/implicit_return.rs | 131 ++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 6 +- clippy_lints/src/missing_returns.rs | 106 ----------------------------- tests/ui/implicit_return.rs | 63 +++++++++++++++++ tests/ui/implicit_return.stderr | 46 +++++++++++++ tests/ui/missing_returns.rs | 55 --------------- tests/ui/missing_returns.stderr | 46 ------------- 8 files changed, 244 insertions(+), 211 deletions(-) create mode 100644 clippy_lints/src/implicit_return.rs delete mode 100644 clippy_lints/src/missing_returns.rs create mode 100644 tests/ui/implicit_return.rs create mode 100644 tests/ui/implicit_return.stderr delete mode 100644 tests/ui/missing_returns.rs delete mode 100644 tests/ui/missing_returns.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5057daf29..e691ec9412f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -706,6 +706,7 @@ All notable changes to this project will be documented in this file. [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher +[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask @@ -756,7 +757,6 @@ All notable changes to this project will be documented in this file. [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items -[`missing_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_returns [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs new file mode 100644 index 00000000000..de783aabefe --- /dev/null +++ b/clippy_lints/src/implicit_return.rs @@ -0,0 +1,131 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; +use crate::syntax::{ast::NodeId, source_map::Span}; +use crate::utils::{snippet_opt, span_lint_and_then}; + +/// **What it does:** Checks for missing return statements at the end of a block. +/// +/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers +/// coming from other languages might prefer the expressiveness of `return`. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn foo(x: usize) { +/// x +/// } +/// ``` +/// add return +/// ```rust +/// fn foo(x: usize) { +/// return x; +/// } +/// ``` +declare_clippy_lint! { + pub IMPLICIT_RETURN, + restriction, + "use a return statement like `return expr` instead of an expression" +} + +pub struct Pass; + +impl Pass { + fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) { + match &expr.node { + ExprKind::Block(block, ..) => { + if let Some(expr) = &block.expr { + Self::expr_match(cx, expr); + } + // only needed in the case of `break` with `;` at the end + else if let Some(stmt) = block.stmts.last() { + if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node { + Self::expr_match(cx, expr); + } + } + }, + // use `return` instead of `break` + ExprKind::Break(.., break_expr) => { + if let Some(break_expr) = break_expr { + span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, break_expr.span) { + db.span_suggestion_with_applicability( + expr.span, + "change `break` to `return` as shown", + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }); + } + }, + ExprKind::If(.., if_expr, else_expr) => { + Self::expr_match(cx, if_expr); + + if let Some(else_expr) = else_expr { + Self::expr_match(cx, else_expr); + } + }, + ExprKind::Match(_, arms, ..) => { + for arm in arms { + Self::expr_match(cx, &arm.body); + } + }, + // loops could be using `break` instead of `return` + ExprKind::Loop(block, ..) => { + if let Some(expr) = &block.expr { + Self::expr_match(cx, expr); + } + }, + // skip if it already has a return statement + ExprKind::Ret(..) => (), + // everything else is missing `return` + _ => span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, expr.span) { + db.span_suggestion_with_applicability( + expr.span, + "add `return` as shown", + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }), + } + } +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(IMPLICIT_RETURN) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl, + body: &'tcx Body, + _: Span, + _: NodeId, + ) { + let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let mir = cx.tcx.optimized_mir(def_id); + + if !mir.return_ty().is_unit() { + Self::expr_match(cx, &body.value); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cb0535a03ac..ee41c632077 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -126,6 +126,7 @@ pub mod functions; pub mod identity_conversion; pub mod identity_op; pub mod if_not_else; +pub mod implicit_return; pub mod indexing_slicing; pub mod infallible_destructuring_match; pub mod infinite_iter; @@ -152,7 +153,6 @@ pub mod misc; pub mod misc_early; pub mod missing_doc; pub mod missing_inline; -pub mod missing_returns; pub mod multiple_crate_versions; pub mod mut_mut; pub mod mut_reference; @@ -372,7 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box missing_returns::Pass); + reg.register_late_lint_pass(box implicit_return::Pass); reg.register_late_lint_pass(box methods::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); @@ -487,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, + implicit_return::IMPLICIT_RETURN, indexing_slicing::INDEXING_SLICING, inherent_impl::MULTIPLE_INHERENT_IMPL, literal_representation::DECIMAL_LITERAL_REPRESENTATION, @@ -498,7 +499,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { misc::FLOAT_CMP_CONST, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, - missing_returns::MISSING_RETURNS, panic_unimplemented::UNIMPLEMENTED, shadow::SHADOW_REUSE, shadow::SHADOW_SAME, diff --git a/clippy_lints/src/missing_returns.rs b/clippy_lints/src/missing_returns.rs deleted file mode 100644 index 71dc71d563b..00000000000 --- a/clippy_lints/src/missing_returns.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::{ast::NodeId, source_map::Span}; -use crate::utils::{snippet_opt, span_lint_and_then}; - -/// **What it does:** Checks for missing return statements at the end of a block. -/// -/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers -/// coming from other languages might prefer the expressiveness of `return`. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn foo(x: usize) { -/// x -/// } -/// ``` -/// add return -/// ```rust -/// fn foo(x: usize) { -/// return x; -/// } -/// ``` -declare_clippy_lint! { - pub MISSING_RETURNS, - restriction, - "use a return statement like `return expr` instead of an expression" -} - -pub struct Pass; - -impl Pass { - fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) { - span_lint_and_then(cx, MISSING_RETURNS, span, "missing return statement", |db| { - if let Some(snippet) = snippet_opt(cx, span) { - db.span_suggestion_with_applicability( - span, - "add `return` as shown", - format!("return {}", snippet), - Applicability::MachineApplicable, - ); - } - }); - } - - fn expr_match(cx: &LateContext<'_, '_>, kind: &ExprKind) { - match kind { - ExprKind::Block(ref block, ..) => { - if let Some(ref expr) = block.expr { - Self::expr_match(cx, &expr.node); - } - }, - ExprKind::If(.., if_expr, else_expr) => { - Self::expr_match(cx, &if_expr.node); - - if let Some(else_expr) = else_expr { - Self::expr_match(cx, &else_expr.node); - } - }, - ExprKind::Match(_, arms, ..) => { - for arm in arms { - Self::expr_match(cx, &arm.body.node); - } - }, - ExprKind::Lit(lit) => Self::show_suggestion(cx, lit.span), - _ => (), - } - } -} - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MISSING_RETURNS) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_fn( - &mut self, - cx: &LateContext<'a, 'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl, - body: &'tcx Body, - _: Span, - _: NodeId, - ) { - let def_id = cx.tcx.hir.body_owner_def_id(body.id()); - let mir = cx.tcx.optimized_mir(def_id); - - if !mir.return_ty().is_unit() { - Self::expr_match(cx, &body.value.node); - } - } -} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs new file mode 100644 index 00000000000..73cf2908833 --- /dev/null +++ b/tests/ui/implicit_return.rs @@ -0,0 +1,63 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + + + + +#![warn(clippy::implicit_return)] + +fn test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + true +} + +#[allow(clippy::needless_bool)] +fn test_if_block() -> bool { + if true { + true + } else { + false + } +} + +#[allow(clippy::match_bool)] +fn test_match(x: bool) -> bool { + match x { + true => false, + false => { + true + } + } +} + +#[allow(clippy::never_loop)] +fn test_loop() -> bool { + loop { + break true; + } +} + +fn test_closure() { + let _ = || { + true + }; + let _ = || true; +} + +fn main() { + let _ = test_end_of_fn(); + let _ = test_if_block(); + let _ = test_match(true); + let _ = test_loop(); + test_closure(); +} diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr new file mode 100644 index 00000000000..bba8d942e27 --- /dev/null +++ b/tests/ui/implicit_return.stderr @@ -0,0 +1,46 @@ +error: missing return statement + --> $DIR/implicit_return.rs:21:5 + | +21 | true + | ^^^^ help: add `return` as shown: `return true` + | + = note: `-D clippy::implicit-return` implied by `-D warnings` + +error: missing return statement + --> $DIR/implicit_return.rs:27:9 + | +27 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/implicit_return.rs:29:9 + | +29 | false + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/implicit_return.rs:36:17 + | +36 | true => false, + | ^^^^^ help: add `return` as shown: `return false` + +error: missing return statement + --> $DIR/implicit_return.rs:38:13 + | +38 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/implicit_return.rs:52:9 + | +52 | true + | ^^^^ help: add `return` as shown: `return true` + +error: missing return statement + --> $DIR/implicit_return.rs:54:16 + | +54 | let _ = || true; + | ^^^^ help: add `return` as shown: `return true` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/missing_returns.rs b/tests/ui/missing_returns.rs deleted file mode 100644 index 96935eb6b53..00000000000 --- a/tests/ui/missing_returns.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - - -#![warn(clippy::missing_returns)] - -fn test_end_of_fn() -> bool { - if true { - // no error! - return true; - } - true -} - -#[allow(clippy::needless_bool)] -fn test_if_block() -> bool { - if true { - true - } else { - false - } -} - -#[allow(clippy::match_bool)] -fn test_match(x: bool) -> bool { - match x { - true => false, - false => { - true - } - } -} - -fn test_closure() { - let _ = || { - true - }; - let _ = || true; -} - -fn main() { - let _ = test_end_of_fn(); - let _ = test_if_block(); - let _ = test_match(true); - test_closure(); -} diff --git a/tests/ui/missing_returns.stderr b/tests/ui/missing_returns.stderr deleted file mode 100644 index 874bec9e109..00000000000 --- a/tests/ui/missing_returns.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: missing return statement - --> $DIR/missing_returns.rs:21:5 - | -21 | true - | ^^^^ help: add `return` as shown: `return true` - | - = note: `-D clippy::missing-returns` implied by `-D warnings` - -error: missing return statement - --> $DIR/missing_returns.rs:27:9 - | -27 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/missing_returns.rs:29:9 - | -29 | false - | ^^^^^ help: add `return` as shown: `return false` - -error: missing return statement - --> $DIR/missing_returns.rs:36:17 - | -36 | true => false, - | ^^^^^ help: add `return` as shown: `return false` - -error: missing return statement - --> $DIR/missing_returns.rs:38:13 - | -38 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/missing_returns.rs:45:9 - | -45 | true - | ^^^^ help: add `return` as shown: `return true` - -error: missing return statement - --> $DIR/missing_returns.rs:47:16 - | -47 | let _ = || true; - | ^^^^ help: add `return` as shown: `return true` - -error: aborting due to 7 previous errors - -- cgit 1.4.1-3-g733a5 From b0f3ed2b808d0696d0a97173d65d368b01c0c9a7 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 5 Dec 2018 15:01:19 +0100 Subject: Added additional reasoning to `Why is this bad?`. Added comment to explain usage of MIR. --- clippy_lints/src/implicit_return.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index de783aabefe..664f182c533 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -17,7 +17,10 @@ use crate::utils::{snippet_opt, span_lint_and_then}; /// **What it does:** Checks for missing return statements at the end of a block. /// /// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers -/// coming from other languages might prefer the expressiveness of `return`. +/// coming from other languages might prefer the expressiveness of `return`. It's possible to miss +/// the last returning statement because the only difference is a missing `;`. Especially in bigger +/// code with multiple return paths having a `return` keyword makes it easier to find the +/// corresponding statements. /// /// **Known problems:** None. /// @@ -124,6 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let def_id = cx.tcx.hir.body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); + // checking return type through MIR, HIR is not able to determine inferred closure return types if !mir.return_ty().is_unit() { Self::expr_match(cx, &body.value); } -- cgit 1.4.1-3-g733a5 From 72247d8e2e6e14fd428d2334b67298dc889340e4 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Wed, 21 Nov 2018 09:14:42 -0600 Subject: Fix dogfood tests. --- ci/base-tests.sh | 20 -------------------- tests/dogfood.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index a046d21c4be..2537f157ad9 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -27,23 +27,3 @@ cd clippy_dev && cargo test && cd .. # Perform various checks for lint registration ./util/dev update_lints --check cargo +nightly fmt --all -- --check - -# Add bin to PATH for windows -PATH=$PATH:$(rustc --print sysroot)/bin - -CLIPPY="`pwd`/target/debug/cargo-clippy clippy" -# run clippy on its own codebase... -${CLIPPY} --all-targets --all-features -- -D clippy::all -D clippy::internal -Dclippy::pedantic -# ... and some test directories -for dir in clippy_workspace_tests clippy_workspace_tests/src clippy_workspace_tests/subcrate clippy_workspace_tests/subcrate/src clippy_dev rustc_tools_util -do - cd ${dir} - ${CLIPPY} -- -D clippy::all -D clippy::pedantic - cd - -done - - -# test --manifest-path -${CLIPPY} --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy::all -cd clippy_workspace_tests/subcrate && ${CLIPPY} --manifest-path=../Cargo.toml -- -D clippy::all && cd ../.. -set +x diff --git a/tests/dogfood.rs b/tests/dogfood.rs index e8f7a080c95..2f2b0cf50ac 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -12,18 +12,50 @@ fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; } - let root_dir = std::env::current_dir().unwrap(); - for d in &[".", "clippy_lints", "rustc_tools_util", "clippy_dev"] { + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let clippy_cmd = std::path::Path::new(&root_dir).join("target/debug/cargo-clippy"); + + println!("{:?}", clippy_cmd); + let output = std::process::Command::new(clippy_cmd) + .arg("clippy") + .arg("--all-targets") + .arg("--all-features") + .arg("--") + .args(&["-D", "clippy::all"]) + .args(&["-D", "clippy::internal"]) + .args(&["-D", "clippy::pedantic"]) + .output() + .unwrap(); + println!("status: {}", output.status); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + + assert!(output.status.success()); +} + +#[test] +fn dogfood_tests() { + if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { + return; + } + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + for d in &[ + "clippy_workspace_tests", + "clippy_workspace_tests/src", + "clippy_workspace_tests/subcrate", + "clippy_workspace_tests/subcrate/src", + "clippy_dev", + "rustc_tools_util", + ] { + let clippy_cmd = std::path::Path::new(&root_dir) + .join("target/debug/cargo-clippy"); std::env::set_current_dir(root_dir.join(d)).unwrap(); - let output = std::process::Command::new("cargo") - .arg("run") - .arg("--bin") - .arg("cargo-clippy") - .arg("--all-features") - .arg("--manifest-path") - .arg(root_dir.join("Cargo.toml")) - .args(&["--", "-W clippy::internal -W clippy::pedantic"]) - .env("CLIPPY_DOGFOOD", "true") + let output = std::process::Command::new(clippy_cmd) + .arg("clippy") + .arg("--") + .args(&["-D", "clippy::all"]) + .args(&["-D", "clippy::pedantic"]) .output() .unwrap(); println!("status: {}", output.status); @@ -32,4 +64,5 @@ fn dogfood() { assert!(output.status.success()); } + std::env::set_current_dir(root_dir).unwrap(); } -- cgit 1.4.1-3-g733a5 From 1db535a88766136c1e2dae7255c3904003761063 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Wed, 21 Nov 2018 09:15:32 -0600 Subject: Remove unnecessary documentation --- CONTRIBUTING.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7ee74448a09..bff456203db 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -168,18 +168,6 @@ Manually testing against an example file is useful if you have added some local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. -### Linting Clippy with your local changes - -Clippy CI only passes if all lints defined in the version of the Clippy being -tested pass (that is, don’t report any suggestions). You can avoid prolonging -the CI feedback cycle for PRs you submit by running these lints yourself ahead -of time and addressing any issues found: - -``` -cargo build -`pwd`/target/debug/cargo-clippy clippy --all-targets --all-features -- -D clippy::all -D clippy::internal -D clippy::pedantic -``` - ### How Clippy works Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. -- cgit 1.4.1-3-g733a5 From 66251c3ecec42af22410a7290f3a82a60e97bf29 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Sat, 24 Nov 2018 15:22:23 -0600 Subject: Use dogfood_runner for deterministic test ordering --- tests/dogfood.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 2f2b0cf50ac..5ef2d8fc26a 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -8,6 +8,11 @@ // except according to those terms. #[test] +fn dogfood_runner() { + dogfood(); + dogfood_tests(); +} + fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; @@ -15,7 +20,7 @@ fn dogfood() { let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); let clippy_cmd = std::path::Path::new(&root_dir).join("target/debug/cargo-clippy"); - println!("{:?}", clippy_cmd); + std::env::set_current_dir(root_dir).unwrap(); let output = std::process::Command::new(clippy_cmd) .arg("clippy") .arg("--all-targets") @@ -33,7 +38,6 @@ fn dogfood() { assert!(output.status.success()); } -#[test] fn dogfood_tests() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; @@ -64,5 +68,4 @@ fn dogfood_tests() { assert!(output.status.success()); } - std::env::set_current_dir(root_dir).unwrap(); } -- cgit 1.4.1-3-g733a5 From 87d517df5db7597ab03a7cf0b8083f55a3cee8b7 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Sat, 24 Nov 2018 15:24:13 -0600 Subject: Use cargo's "PROFILE" envvar and set CLIPPY_DOGFOOD --- tests/dogfood.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 5ef2d8fc26a..286af42fd91 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -18,10 +18,14 @@ fn dogfood() { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let clippy_cmd = std::path::Path::new(&root_dir).join("target/debug/cargo-clippy"); + let clippy_cmd = std::path::Path::new(&root_dir) + .join("target") + .join(env!("PROFILE")) + .join("cargo-clippy"); std::env::set_current_dir(root_dir).unwrap(); let output = std::process::Command::new(clippy_cmd) + .env("CLIPPY_DOGFOOD", "1") .arg("clippy") .arg("--all-targets") .arg("--all-features") @@ -43,6 +47,10 @@ fn dogfood_tests() { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let clippy_cmd = std::path::Path::new(&root_dir) + .join("target") + .join(env!("PROFILE")) + .join("cargo-clippy"); for d in &[ "clippy_workspace_tests", @@ -52,10 +60,9 @@ fn dogfood_tests() { "clippy_dev", "rustc_tools_util", ] { - let clippy_cmd = std::path::Path::new(&root_dir) - .join("target/debug/cargo-clippy"); std::env::set_current_dir(root_dir.join(d)).unwrap(); - let output = std::process::Command::new(clippy_cmd) + let output = std::process::Command::new(&clippy_cmd) + .env("CLIPPY_DOGFOOD", "1") .arg("clippy") .arg("--") .args(&["-D", "clippy::all"]) -- cgit 1.4.1-3-g733a5 From 0442bb9ce0b1f9851442fcc6f8f9dcb3ef88e3ca Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Fri, 30 Nov 2018 12:54:47 -0600 Subject: Don't change current working directory of cargo tests --- tests/dogfood.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 286af42fd91..c1f02b9fcef 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -8,11 +8,6 @@ // except according to those terms. #[test] -fn dogfood_runner() { - dogfood(); - dogfood_tests(); -} - fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; @@ -23,8 +18,8 @@ fn dogfood() { .join(env!("PROFILE")) .join("cargo-clippy"); - std::env::set_current_dir(root_dir).unwrap(); let output = std::process::Command::new(clippy_cmd) + .current_dir(root_dir) .env("CLIPPY_DOGFOOD", "1") .arg("clippy") .arg("--all-targets") @@ -42,6 +37,7 @@ fn dogfood() { assert!(output.status.success()); } +#[test] fn dogfood_tests() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; @@ -60,8 +56,8 @@ fn dogfood_tests() { "clippy_dev", "rustc_tools_util", ] { - std::env::set_current_dir(root_dir.join(d)).unwrap(); let output = std::process::Command::new(&clippy_cmd) + .current_dir(root_dir.join(d)) .env("CLIPPY_DOGFOOD", "1") .arg("clippy") .arg("--") -- cgit 1.4.1-3-g733a5 From 69813d6faf2c9caaf2e8131e6218bd056366da53 Mon Sep 17 00:00:00 2001 From: O01eg Date: Thu, 4 Oct 2018 10:58:09 +0300 Subject: Don't try to determine sysroot. rustc_driver will use default value. --- src/driver.rs | 44 ++++++-------------------------------------- 1 file changed, 6 insertions(+), 38 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index fd9c8693c95..6b327d08207 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -23,7 +23,7 @@ use self::rustc_driver::{driver::CompileController, Compilation}; use std::convert::TryInto; use std::path::Path; -use std::process::{exit, Command}; +use std::process::exit; fn show_version() { println!(env!("CARGO_PKG_VERSION")); @@ -40,54 +40,22 @@ pub fn main() { exit(0); } - let sys_root = option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); - if orig_args.len() <= 1 { + let mut args: Vec = env::args().collect(); + if args.len() <= 1 { std::process::exit(1); } - if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + if Path::new(&args[1]).file_stem() == Some("rustc".as_ref()) { // we still want to be able to invoke it normally though - orig_args.remove(1); + args.remove(1); } - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() - } else { - orig_args - .clone() - .into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; // this check ensures that dependencies are built but not linted and the final // crate is // linted but not built let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); + || args.iter().any(|s| s == "--emit=dep-info,metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); -- cgit 1.4.1-3-g733a5 From 571d4cc7bf4c073dcb90298902188fef1721ef9b Mon Sep 17 00:00:00 2001 From: O01eg Date: Thu, 22 Nov 2018 15:40:29 +0300 Subject: Add sysroot getting code to tests. --- tests/compile-test.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5cb37b6b6fd..115b40c21b3 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -17,6 +17,7 @@ use std::ffi::OsStr; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use std::process::Command; fn clippy_driver_path() -> PathBuf { if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { @@ -42,6 +43,28 @@ fn rustc_lib_path() -> PathBuf { option_env!("RUSTC_LIB_PATH").unwrap().into() } +fn rustc_sysroot_path() -> PathBuf { + option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") + .into() +} + fn config(mode: &str, dir: PathBuf) -> compiletest::Config { let mut config = compiletest::Config::default(); @@ -55,7 +78,7 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); + config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings --sysroot {1}", host_libs().display(), rustc_sysroot_path().display())); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { -- cgit 1.4.1-3-g733a5 From a8a0b236b5768ab30a0439872368c1dc2e199860 Mon Sep 17 00:00:00 2001 From: Felix Kohlgrüber Date: Thu, 6 Dec 2018 11:07:10 +0100 Subject: fix #3482 and add ui test for it --- clippy_lints/src/block_in_if_condition.rs | 2 +- tests/ui/block_in_if_condition.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 5597b856a8c..f90e7669dd0 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { if let ExprKind::Closure(_, _, eid, _, _) = expr.node { let body = self.cx.tcx.hir.body(eid); let ex = &body.value; - if matches!(ex.node, ExprKind::Block(_, _)) { + if matches!(ex.node, ExprKind::Block(_, _)) && !in_macro(body.value.span) { self.found_block = Some(ex); return; } diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index bb87315bcc4..94611811841 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -98,3 +98,11 @@ fn condition_is_unsafe_block() { fn main() { } + +fn macro_in_closure() { + let option = Some(true); + + if option.unwrap_or_else(|| unimplemented!()) { + unimplemented!() + } +} -- cgit 1.4.1-3-g733a5 From 5113de90d1f986232b589c03f29c8af90fd07ed0 Mon Sep 17 00:00:00 2001 From: O01eg Date: Thu, 6 Dec 2018 13:21:45 +0300 Subject: Add sysroot gettinh code to dogfood tests. --- tests/dogfood.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index c1f02b9fcef..69f4f9901b7 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -7,6 +7,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::path::PathBuf; +use std::process::Command; + +fn rustc_sysroot_path() -> PathBuf { + option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") + .into() +} + #[test] fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { @@ -21,6 +46,7 @@ fn dogfood() { let output = std::process::Command::new(clippy_cmd) .current_dir(root_dir) .env("CLIPPY_DOGFOOD", "1") + .env("RUSTFLAGS", format!("--sysroot {}", rustc_sysroot_path().display())) .arg("clippy") .arg("--all-targets") .arg("--all-features") @@ -59,6 +85,7 @@ fn dogfood_tests() { let output = std::process::Command::new(&clippy_cmd) .current_dir(root_dir.join(d)) .env("CLIPPY_DOGFOOD", "1") + .env("RUSTFLAGS", format!("--sysroot {}", rustc_sysroot_path().display())) .arg("clippy") .arg("--") .args(&["-D", "clippy::all"]) -- cgit 1.4.1-3-g733a5 From 278b94e6db8e233536c27259371d22f6ec5ebe50 Mon Sep 17 00:00:00 2001 From: O01eg Date: Thu, 6 Dec 2018 13:46:23 +0300 Subject: Fix format. --- tests/compile-test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 115b40c21b3..62fa17d388a 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -78,7 +78,11 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings --sysroot {1}", host_libs().display(), rustc_sysroot_path().display())); + config.target_rustcflags = Some(format!( + "-L {0} -L {0}/deps -Dwarnings --sysroot {1}", + host_libs().display(), + rustc_sysroot_path().display() + )); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { -- cgit 1.4.1-3-g733a5 From 973d676cd105b3ec87e4edb99fc0fb63b374e213 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 6 Dec 2018 12:22:54 +0100 Subject: Fix bug in `implicit_return`. Bug was already covered by test, but test was not checked for. --- clippy_lints/src/implicit_return.rs | 6 ++++++ tests/ui/implicit_return.stderr | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 664f182c533..d29b508ba37 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -90,6 +90,12 @@ impl Pass { if let Some(expr) = &block.expr { Self::expr_match(cx, expr); } + // only needed in the case of `break` with `;` at the end + else if let Some(stmt) = block.stmts.last() { + if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node { + Self::expr_match(cx, expr); + } + } }, // skip if it already has a return statement ExprKind::Ret(..) => (), diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index bba8d942e27..6f4fe12757a 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -30,6 +30,12 @@ error: missing return statement 38 | true | ^^^^ help: add `return` as shown: `return true` +error: missing return statement + --> $DIR/implicit_return.rs:46:9 + | +46 | break true; + | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` + error: missing return statement --> $DIR/implicit_return.rs:52:9 | @@ -42,5 +48,5 @@ error: missing return statement 54 | let _ = || true; | ^^^^ help: add `return` as shown: `return true` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From d048e15835e19841211ae7725511dc946bdde5e2 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 6 Dec 2018 13:21:04 +0100 Subject: Improved code noted by clippy. --- clippy_lints/src/implicit_return.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index d29b508ba37..543948e39a7 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -7,6 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![warn(clippy::match_same_arms)] use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -47,7 +48,8 @@ pub struct Pass; impl Pass { fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) { match &expr.node { - ExprKind::Block(block, ..) => { + // loops could be using `break` instead of `return` + ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => { if let Some(expr) = &block.expr { Self::expr_match(cx, expr); } @@ -85,18 +87,6 @@ impl Pass { Self::expr_match(cx, &arm.body); } }, - // loops could be using `break` instead of `return` - ExprKind::Loop(block, ..) => { - if let Some(expr) = &block.expr { - Self::expr_match(cx, expr); - } - // only needed in the case of `break` with `;` at the end - else if let Some(stmt) = block.stmts.last() { - if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node { - Self::expr_match(cx, expr); - } - } - }, // skip if it already has a return statement ExprKind::Ret(..) => (), // everything else is missing `return` -- cgit 1.4.1-3-g733a5 From a4ec7be06fc3406bca536340a4073a9159d36e45 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 6 Dec 2018 13:23:42 +0100 Subject: Forgot to remove some debugging code ... --- clippy_lints/src/implicit_return.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 543948e39a7..07a849469fd 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![warn(clippy::match_same_arms)] use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -- cgit 1.4.1-3-g733a5 From 45cbdf471d896abd3f2c11cbdffbaf8379951917 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Dec 2018 16:38:32 +0100 Subject: rustup clippy build with latest rustc (breakage due to https://github.com/rust-lang/rust/commit/08f8faedd0e30f45762afbb8d4873f7041e7462c ) Fixes #3500 --- clippy_lints/src/use_self.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 3a71a6d04af..27ca01b8141 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -14,7 +14,7 @@ use crate::rustc::ty; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::ast::NodeId; -use crate::syntax_pos::symbol::keywords::SelfType; +use crate::syntax_pos::symbol::keywords::SelfUpper; use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; @@ -226,7 +226,7 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { - if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfType.name() { + if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { span_use_self_lint(self.cx, path); } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 0c6935d867d..316fee6b0e1 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -970,7 +970,7 @@ pub fn opt_def_id(def: Def) -> Option { pub fn is_self(slf: &Arg) -> bool { if let PatKind::Binding(_, _, name, _) = slf.pat.node { - name.name == keywords::SelfValue.name() + name.name == keywords::SelfLower.name() } else { false } -- cgit 1.4.1-3-g733a5 From 7220185560d7f748c342199f2b1c4ac570e2e58c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 6 Dec 2018 11:11:50 -0500 Subject: Remove -preview suffix from README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 92bb4586688..49c0a1f1546 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ rustup update Once you have rustup and the latest stable release (at least Rust 1.29) installed, run the following command: ```terminal -rustup component add clippy-preview +rustup component add clippy ``` Now you can run Clippy by invoking `cargo clippy`. @@ -95,7 +95,7 @@ rust: - stable - beta before_script: - - rustup component add clippy-preview + - rustup component add clippy script: - cargo clippy # if you want the build job to fail when encountering warnings, use @@ -114,7 +114,7 @@ language: rust rust: - nightly before_script: - - rustup component add clippy-preview --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy + - rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy # etc ``` -- cgit 1.4.1-3-g733a5 From 2fed8d9f1d268009c4e630626d8558c26e9175c7 Mon Sep 17 00:00:00 2001 From: Philipp A Date: Fri, 7 Dec 2018 12:24:59 +0100 Subject: typo: emum → enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index aa302500abf..63e2db7506c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -148,7 +148,7 @@ define_Conf! { (too_large_for_stack, "too_large_for_stack", 200 => u64), /// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger (enum_variant_name_threshold, "enum_variant_name_threshold", 3 => u64), - /// Lint: LARGE_ENUM_VARIANT. The maximum size of a emum's variant to avoid box suggestion + /// Lint: LARGE_ENUM_VARIANT. The maximum size of a enum's variant to avoid box suggestion (enum_variant_size_threshold, "enum_variant_size_threshold", 200 => u64), /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (verbose_bit_mask_threshold, "verbose_bit_mask_threshold", 1 => u64), -- cgit 1.4.1-3-g733a5 From a73d05122786b40ce97bc513d23a00b3ad095a55 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 7 Dec 2018 22:47:12 +0100 Subject: Remove allow(doc_markdown) in excessive_precision.rs --- clippy_lints/src/excessive_precision.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index ff678925d8f..7d72f417b2a 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -109,10 +109,9 @@ impl ExcessivePrecision { } } -#[allow(clippy::doc_markdown)] /// Should we exclude the float because it has a `.0` or `.` suffix -/// Ex 1_000_000_000.0 -/// Ex 1_000_000_000. +/// Ex `1_000_000_000.0` +/// Ex `1_000_000_000.` fn dot_zero_exclusion(s: &str) -> bool { if let Some(after_dec) = s.split('.').nth(1) { let mut decpart = after_dec.chars().take_while(|c| *c != 'e' || *c != 'E'); -- cgit 1.4.1-3-g733a5 From f13d23de41ef41da424dbd514f3012cd0e5dcd85 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 8 Dec 2018 01:56:03 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/56502 ( .hir -> .hir() ) --- clippy_lints/src/arithmetic.rs | 10 +++++----- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/attrs.rs | 6 +++--- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/copy_iterator.rs | 2 +- clippy_lints/src/cyclomatic_complexity.rs | 2 +- clippy_lints/src/derive.rs | 6 +++--- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/escape.rs | 10 +++++----- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/fallible_impl_from.rs | 8 ++++---- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/implicit_return.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/len_zero.rs | 8 ++++---- clippy_lints/src/lifetimes.rs | 6 +++--- clippy_lints/src/loops.rs | 20 ++++++++++---------- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 2 +- clippy_lints/src/methods/mod.rs | 16 ++++++++-------- clippy_lints/src/methods/unnecessary_filter_map.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/missing_doc.rs | 6 +++--- clippy_lints/src/missing_inline.rs | 8 ++++---- clippy_lints/src/needless_pass_by_value.rs | 10 +++++----- clippy_lints/src/new_without_default.rs | 8 ++++---- clippy_lints/src/non_copy_const.rs | 8 ++++---- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/redundant_clone.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/suspicious_trait_impl.rs | 12 ++++++------ clippy_lints/src/trivially_copy_pass_by_ref.rs | 8 ++++---- clippy_lints/src/types.rs | 16 ++++++++-------- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/use_self.rs | 12 ++++++------ clippy_lints/src/utils/hir_utils.rs | 12 ++++++------ clippy_lints/src/utils/inspector.rs | 8 ++++---- clippy_lints/src/utils/internal_lints.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 18 +++++++++--------- clippy_lints/src/utils/ptr.rs | 2 +- 46 files changed, 140 insertions(+), 140 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 2e24eb7122d..0b2c00b9b58 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -121,11 +121,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) { - let body_owner = cx.tcx.hir.body_owner(body.id()); + let body_owner = cx.tcx.hir().body_owner(body.id()); - match cx.tcx.hir.body_owner_kind(body_owner) { + match cx.tcx.hir().body_owner_kind(body_owner) { hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => { - let body_span = cx.tcx.hir.span(body_owner); + let body_span = cx.tcx.hir().span(body_owner); if let Some(span) = self.const_span { if span.contains(body_span) { @@ -139,8 +139,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } fn check_body_post(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) { - let body_owner = cx.tcx.hir.body_owner(body.id()); - let body_span = cx.tcx.hir.span(body_owner); + let body_owner = cx.tcx.hir().body_owner(body.id()); + let body_span = cx.tcx.hir().span(body_owner); if let Some(span) = self.const_span { if span.contains(body_span) { diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 91562ece5f5..f69c66a3d35 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -144,12 +144,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { return; // useless if the trait doesn't exist }; // check that we are not inside an `impl AssignOp` of this exact operation - let parent_fn = cx.tcx.hir.get_parent(e.id); - let parent_impl = cx.tcx.hir.get_parent(parent_fn); + let parent_fn = cx.tcx.hir().get_parent(e.id); + let parent_impl = cx.tcx.hir().get_parent(parent_fn); // the crate node is the only one that is not in the map if_chain! { if parent_impl != ast::CRATE_NODE_ID; - if let hir::Node::Item(item) = cx.tcx.hir.get(parent_impl); + if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl); if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if trait_ref.path.def.def_id() == trait_id; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4f9d5f2a768..9f8cc76c5aa 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -354,7 +354,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool { if let ItemKind::Fn(_, _, _, eid) = item.node { - is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) + is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value) } else { true } @@ -362,7 +362,7 @@ fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool { fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool { match item.node { - ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value), + ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value), _ => false, } } @@ -371,7 +371,7 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool { match item.node { TraitItemKind::Method(_, TraitMethod::Required(_)) => true, TraitItemKind::Method(_, TraitMethod::Provided(eid)) => { - is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) + is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value) }, _ => false, } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index f90e7669dd0..825bf789a69 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -68,7 +68,7 @@ struct ExVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { if let ExprKind::Closure(_, _, eid, _, _) = expr.node { - let body = self.cx.tcx.hir.body(eid); + let body = self.cx.tcx.hir().body(eid); let ex = &body.value; if matches!(ex.node, ExprKind::Block(_, _)) && !in_macro(body.value.span) { self.found_block = Some(ex); diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 31ec879d18d..5d81e51422d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { if filter_args.len() == 2; if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node; then { - let body = cx.tcx.hir.body(body_id); + let body = cx.tcx.hir().body(body_id); if_chain! { if body.arguments.len() == 1; if let Some(argname) = get_pat_name(&body.arguments[0].pat); diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index af6142c8a04..e5bbe9eb38a 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -49,7 +49,7 @@ impl LintPass for CopyIterator { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node { - let ty = cx.tcx.type_of(cx.tcx.hir.local_def_id(item.id)); + let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.id)); if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) { span_note_and_lint( diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 132440885f7..e2f98dce471 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { span: Span, node_id: NodeId, ) { - let def_id = cx.tcx.hir.local_def_id(node_id); + let def_id = cx.tcx.hir().local_def_id(node_id); if !cx.tcx.has_attr(def_id, "test") { self.check(cx, body, span); } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 96621d366fa..02eda701817 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -82,7 +82,7 @@ impl LintPass for Derive { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node { - let ty = cx.tcx.type_of(cx.tcx.hir.local_def_id(item.id)); + let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.id)); let is_automatically_derived = is_automatically_derived(&*item.attrs); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); @@ -129,9 +129,9 @@ fn check_hash_peq<'a, 'tcx>( cx, DERIVE_HASH_XOR_EQ, span, mess, |db| { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(impl_id) { + if let Some(node_id) = cx.tcx.hir().as_local_node_id(impl_id) { db.span_note( - cx.tcx.hir.span(node_id), + cx.tcx.hir().span(node_id), "`PartialEq` implemented here" ); } diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index b9b6b17a2dd..045551d38dc 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -43,7 +43,7 @@ impl LintPass for EmptyEnum { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { - let did = cx.tcx.hir.local_def_id(item.id); + let did = cx.tcx.hir().local_def_id(item.id); if let ItemKind::Enum(..) = item.node { let ty = cx.tcx.type_of(did); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index cf921b6b94c..bd3d3d13bb3 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let variant = &var.node; if let Some(ref anon_const) = variant.disr_expr { let param_env = ty::ParamEnv::empty(); - let def_id = cx.tcx.hir.body_owner_def_id(anon_const.body); + let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id); let instance = ty::Instance::new(def_id, substs); let c_id = GlobalId { diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 164b0d8dbad..3a98c784fe2 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) { // only check top level `use` statements for item in &m.item_ids { - self.lint_item(cx, cx.tcx.hir.expect_item(item.id)); + self.lint_item(cx, cx.tcx.hir().expect_item(item.id)); } } } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 99c145b2677..4b4a6bd9d5c 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -74,8 +74,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { node_id: NodeId, ) { // If the method is an impl for a trait, don't warn - let parent_id = cx.tcx.hir.get_parent(node_id); - let parent_node = cx.tcx.hir.find(parent_id); + let parent_id = cx.tcx.hir().get_parent(node_id); + let parent_node = cx.tcx.hir().find(parent_id); if let Some(Node::Item(item)) = parent_node { if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { @@ -89,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { too_large_for_stack: self.too_large_for_stack, }; - let fn_def_id = cx.tcx.hir.local_def_id(node_id); + let fn_def_id = cx.tcx.hir().local_def_id(node_id); let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body); @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { span_lint( cx, BOXED_LOCAL, - cx.tcx.hir.span(node), + cx.tcx.hir().span(node), "local variable doesn't need to be boxed here", ); } @@ -115,7 +115,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) { - let map = &self.cx.tcx.hir; + let map = &self.cx.tcx.hir(); if map.is_argument(consume_pat.id) { // Skip closure arguments if let Some(Node::Expr(..)) = map.find(map.get_parent_node(consume_pat.id)) { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 1e7fee9757f..e06f4d260d4 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node { - let body = cx.tcx.hir.body(eid); + let body = cx.tcx.hir().body(eid); let ex = &body.value; if let ExprKind::Call(ref caller, ref args) = ex.node { if args.len() != decl.inputs.len() { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 269a6bb6c8a..69d3b09a8ae 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -191,7 +191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { /// /// When such a read is found, the lint is triggered. fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { - let map = &vis.cx.tcx.hir; + let map = &vis.cx.tcx.hir(); let mut cur_id = vis.write_expr.id; loop { let parent_id = map.get_parent_node(cur_id); diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index ec47c78e495..0f1c1f7ef1d 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -48,7 +48,7 @@ impl LintPass for FallibleImplFrom { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { // check for `impl From for ..` - let impl_def_id = cx.tcx.hir.local_def_id(item.id); + let impl_def_id = cx.tcx.hir().local_def_id(item.id); if_chain! { if let hir::ItemKind::Impl(.., ref impl_items) = item.node; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); @@ -106,11 +106,11 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it if_chain! { if impl_item.ident.name == "from"; if let ImplItemKind::Method(_, body_id) = - cx.tcx.hir.impl_item(impl_item.id).node; + cx.tcx.hir().impl_item(impl_item.id).node; then { // check the body for `begin_panic` or `unwrap` - let body = cx.tcx.hir.body(body_id); - let impl_item_def_id = cx.tcx.hir.local_def_id(impl_item.id.node_id); + let body = cx.tcx.hir().body(body_id); + let impl_item_def_id = cx.tcx.hir().local_def_id(impl_item.id.node_id); let mut fpu = FindPanicUnwrap { tcx: cx.tcx, tables: cx.tcx.typeck_tables_of(impl_item_def_id), diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 57000761922..e3c43c1c090 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { span: Span, nodeid: ast::NodeId, ) { - let is_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { + let is_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(nodeid)) { matches!(item.node, hir::ItemKind::Impl(_, _, _, _, Some(_), _, _)) } else { false @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } if let hir::TraitMethod::Provided(eid) = *eid { - let body = cx.tcx.hir.body(eid); + let body = cx.tcx.hir().body(eid); self.check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.id); } } diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 07a849469fd..75c66d22647 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: Span, _: NodeId, ) { - let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); // checking return type through MIR, HIR is not able to determine inferred closure return types diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 3ac68096aaa..625eca86d87 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -165,7 +165,7 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { } if method.ident.name == "flat_map" && args.len() == 2 { if let ExprKind::Closure(_, _, body_id, _, _) = args[1].node { - let body = cx.tcx.hir.body(body_id); + let body = cx.tcx.hir().body(body_id); return is_infinite(cx, &body.value); } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 6f9ae1a9367..8c8fc5dbeda 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -59,7 +59,7 @@ impl LintPass for LargeEnumVariant { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { - let did = cx.tcx.hir.local_def_id(item.id); + let did = cx.tcx.hir().local_def_id(item.id); if let ItemKind::Enum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 0dc21747580..47b0fb55934 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -137,7 +137,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { - let did = cx.tcx.hir.local_def_id(item.id.node_id); + let did = cx.tcx.hir().local_def_id(item.id.node_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } } else { @@ -156,7 +156,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items if cx.access_levels.is_exported(visited_trait.id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { let mut current_and_super_traits = FxHashSet::default(); - let visited_trait_def_id = cx.tcx.hir.local_def_id(visited_trait.id); + let visited_trait_def_id = cx.tcx.hir().local_def_id(visited_trait.id); fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx); let is_empty_method_found = current_and_super_traits @@ -188,7 +188,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { has_self && { - let did = cx.tcx.hir.local_def_id(item.id.node_id); + let did = cx.tcx.hir().local_def_id(item.id.node_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } } else { @@ -208,7 +208,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) { if cx.access_levels.is_exported(i.id.node_id) { - let def_id = cx.tcx.hir.local_def_id(item.id); + let def_id = cx.tcx.hir().local_def_id(item.id); let ty = cx.tcx.type_of(def_id); span_lint( diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 9b5da7bfc17..9dcbf576375 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -204,7 +204,7 @@ fn could_use_elision<'a, 'tcx: 'a>( let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false, }; - checker.visit_expr(&cx.tcx.hir.body(body_id).value); + checker.visit_expr(&cx.tcx.hir().body(body_id).value); if checker.lifetimes_used_in_body { return false; } @@ -324,7 +324,7 @@ impl<'v, 't> RefVisitor<'v, 't> { GenericArg::Type(_) => false, }) { - let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + let hir_id = self.cx.tcx.hir().node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { Def::TyAlias(def_id) | Def::Struct(def_id) => { let generics = self.cx.tcx.generics_of(def_id); @@ -360,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { self.collect_anonymous_lifetimes(path, ty); }, TyKind::Def(item, _) => { - if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(item.id).node { + if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir().expect_item(item.id).node { for bound in &exist_ty.bounds { if let GenericBound::Outlives(_) = *bound { self.record(&None); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 67c3fee464a..7ff43bd2da2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1111,8 +1111,8 @@ fn check_for_loop_range<'a, 'tcx>( // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { - let parent_id = cx.tcx.hir.get_parent(expr.id); - let parent_def_id = cx.tcx.hir.local_def_id(parent_id); + let parent_id = cx.tcx.hir().get_parent(expr.id); + let parent_def_id = cx.tcx.hir().local_def_id(parent_id); let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id); if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { @@ -1464,7 +1464,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. - let map = &cx.tcx.hir; + let map = &cx.tcx.hir(); let parent_scope = map .get_enclosing_scope(expr.id) .and_then(|id| map.get_enclosing_scope(id)); @@ -1636,7 +1636,7 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option VarVisitor<'a, 'tcx> { let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); match def { Def::Local(node_id) | Def::Upvar(node_id, ..) => { - let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); + let hir_id = self.cx.tcx.hir().node_to_hir_id(node_id); - let parent_id = self.cx.tcx.hir.get_parent(expr.id); - let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); + let parent_id = self.cx.tcx.hir().get_parent(expr.id); + let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); if indexed_indirectly { self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); @@ -2186,7 +2186,7 @@ fn is_conditional(expr: &Expr) -> bool { fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr, iter_expr: &Expr) -> bool { if_chain! { if let Some(loop_block) = get_enclosing_block(cx, match_expr.id); - if let Some(Node::Expr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id)); + if let Some(Node::Expr(loop_expr)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(loop_block.id)); then { return is_loop_nested(cx, loop_expr, iter_expr) } @@ -2202,11 +2202,11 @@ fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr, iter_expr: &Expr) return true; }; loop { - let parent = cx.tcx.hir.get_parent_node(id); + let parent = cx.tcx.hir().get_parent_node(id); if parent == id { return false; } - match cx.tcx.hir.find(parent) { + match cx.tcx.hir().find(parent) { Some(Node::Expr(expr)) => match expr.node { ExprKind::Loop(..) | ExprKind::While(..) => { return true; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index af85a279ca3..8ca1fbb2759 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let ty = cx.tables.expr_ty(&args[0]); if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node; - let closure_body = cx.tcx.hir.body(body_id); + let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); then { match closure_body.arguments[0].pat.node { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 8fb41b25c73..39450deb84c 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -161,7 +161,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> { if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.node { - let body = cx.tcx.hir.body(inner_expr_id); + let body = cx.tcx.hir().body(inner_expr_id); let body_expr = &body.value; if_chain! { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b5c31bf5dbd..57eb5c539bc 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -911,14 +911,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } let name = implitem.ident.name; - let parent = cx.tcx.hir.get_parent(implitem.id); - let item = cx.tcx.hir.expect_item(parent); - let def_id = cx.tcx.hir.local_def_id(item.id); + let parent = cx.tcx.hir().get_parent(implitem.id); + let item = cx.tcx.hir().expect_item(parent); + let def_id = cx.tcx.hir().local_def_id(item.id); let ty = cx.tcx.type_of(def_id); if_chain! { if let hir::ImplItemKind::Method(ref sig, id) = implitem.node; if let Some(first_arg_ty) = sig.decl.inputs.get(0); - if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next(); + if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node; then { if cx.access_levels.is_exported(implitem.id) { @@ -1086,7 +1086,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa } // don't lint for constant values - let owner_def = cx.tcx.hir.get_parent_did(arg.id); + let owner_def = cx.tcx.hir().get_parent_did(arg.id); let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); if promotable { return; @@ -1334,8 +1334,8 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { // x.clone() might have dereferenced x, possibly through Deref impls if cx.tables.expr_ty(arg) != ty { - let parent = cx.tcx.hir.get_parent_node(expr.id); - match cx.tcx.hir.get(parent) { + let parent = cx.tcx.hir().get_parent_node(expr.id); + match cx.tcx.hir().get(parent) { hir::Node::Expr(parent) => match parent.node { // &*x is a nop, &x.clone() is not hir::ExprKind::AddrOf(..) | @@ -1496,7 +1496,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: if_chain! { // Extract the body of the closure passed to fold if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node; - let closure_body = cx.tcx.hir.body(body_id); + let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); // Check if the closure body is of the form `acc some_expr(x)` diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index f8988935788..3ffe802201f 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -26,7 +26,7 @@ pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr } if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].node { - let body = cx.tcx.hir.body(body_id); + let body = cx.tcx.hir().body(body_id); let arg_id = body.arguments[0].pat.id; let mutates_arg = match mutated_variables(&body.value, cx) { Some(used_mutably) => used_mutably.contains(&arg_id), diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 7220f1726bf..bc3e19064db 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -612,7 +612,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool { /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext<'_, '_>, def: &def::Def) -> bool { match *def { - def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir.span(id)), + def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir().span(id)), _ => false, } } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 8eb64f7ca37..6a2db0bb098 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -142,8 +142,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Fn(..) => { // ignore main() if it.name == "main" { - let def_id = cx.tcx.hir.local_def_id(it.id); - let def_key = cx.tcx.hir.def_key(def_id); + let def_id = cx.tcx.hir().local_def_id(it.id); + let def_key = cx.tcx.hir().def_key(def_id); if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { return; } @@ -180,7 +180,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { // If the method is an impl for a trait, don't doc. - let def_id = cx.tcx.hir.local_def_id(impl_item.id); + let def_id = cx.tcx.hir().local_def_id(impl_item.id); match cx.tcx.associated_item(def_id).container { ty::TraitContainer(_) => return, ty::ImplContainer(cid) => { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 99477821cfa..b76d6316600 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for tit in trait_items { - let tit_ = cx.tcx.hir.trait_item(tit.id); + let tit_ = cx.tcx.hir().trait_item(tit.id); match tit_.node { hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, hir::TraitItemKind::Method(..) => { @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { // trait method with default body needs inline in case // an impl is not provided let desc = "a default trait method"; - let item = cx.tcx.hir.expect_trait_item(tit.id.node_id); + let item = cx.tcx.hir().expect_trait_item(tit.id.node_id); check_missing_inline_attrs(cx, &item.attrs, item.span, desc); } }, @@ -171,14 +171,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::Existential(_) => return, }; - let def_id = cx.tcx.hir.local_def_id(impl_item.id); + let def_id = cx.tcx.hir().local_def_id(impl_item.id); let trait_def_id = match cx.tcx.associated_item(def_id).container { TraitContainer(cid) => Some(cid), ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id), }; if let Some(trait_def_id) = trait_def_id { - if let Some(n) = cx.tcx.hir.as_local_node_id(trait_def_id) { + if let Some(n) = cx.tcx.hir().as_local_node_id(trait_def_id) { if !cx.access_levels.is_exported(n) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f1b31a3e0a7..26bd56c2e7b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(node_id)) { if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | ItemKind::Trait(..)) { @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let sized_trait = need!(cx.tcx.lang_items().sized_trait()); - let fn_def_id = cx.tcx.hir.local_def_id(node_id); + let fn_def_id = cx.tcx.hir().local_def_id(node_id); let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) .filter(|p| !p.is_global()) @@ -220,7 +220,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Dereference suggestion let sugg = |db: &mut DiagnosticBuilder<'_>| { if let ty::Adt(def, ..) = ty.sty { - if let Some(span) = cx.tcx.hir.span_if_local(def.did) { + if let Some(span) = cx.tcx.hir().span_if_local(def.did) { if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { db.span_help(span, "consider marking this type as Copy"); } @@ -355,14 +355,14 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { if let mc::Categorization::Local(vid) = cmt.cat { let mut id = matched_pat.id; loop { - let parent = self.cx.tcx.hir.get_parent_node(id); + let parent = self.cx.tcx.hir().get_parent_node(id); if id == parent { // no parent return; } id = parent; - if let Some(node) = self.cx.tcx.hir.find(id) { + if let Some(node) = self.cx.tcx.hir().find(id) { match node { Node::Expr(e) => { // `match` and `if let` diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index f0a7c71856d..7b838fdee95 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let hir::ItemKind::Impl(_, _, _, _, None, _, ref items) = item.node { for assoc_item in items { if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind { - let impl_item = cx.tcx.hir.impl_item(assoc_item.id); + let impl_item = cx.tcx.hir().impl_item(assoc_item.id); if in_external_macro(cx.sess(), impl_item.span) { return; } @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { - let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)); + let self_did = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent(id)); let self_ty = cx.tcx.type_of(self_did); if_chain! { if same_tys(cx, self_ty, return_ty(cx, id)); @@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { let mut impls = NodeSet::default(); cx.tcx.for_each_impl(default_trait_id, |d| { if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { - if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) { + if let Some(node_id) = cx.tcx.hir().as_local_node_id(ty_def.did) { impls.insert(node_id); } } @@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def(); if self_def.did.is_local(); then { - let self_id = cx.tcx.hir.local_def_id_to_node_id(self_def.did.to_local()); + let self_id = cx.tcx.hir().local_def_id_to_node_id(self_def.did.to_local()); if impling_types.contains(&self_id) { return; } diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index bb44bd6bd06..b699a53176e 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -182,8 +182,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem) { if let ImplItemKind::Const(hir_ty, ..) = &impl_item.node { - let item_node_id = cx.tcx.hir.get_parent_node(impl_item.id); - let item = cx.tcx.hir.expect_item(item_node_id); + let item_node_id = cx.tcx.hir().get_parent_node(impl_item.id); + let item = cx.tcx.hir().expect_item(item_node_id); // ensure the impl is an inherent impl. if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node { let ty = hir_ty_to_ty(cx.tcx, hir_ty); @@ -217,11 +217,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { let mut dereferenced_expr = expr; let mut needs_check_adjustment = true; loop { - let parent_id = cx.tcx.hir.get_parent_node(cur_expr.id); + let parent_id = cx.tcx.hir().get_parent_node(cur_expr.id); if parent_id == cur_expr.id { break; } - if let Some(Node::Expr(parent_expr)) = cx.tcx.hir.find(parent_id) { + if let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find(parent_id) { match &parent_expr.node { ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 82e69889395..b2039c26300 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { if let ImplItemKind::Method(ref sig, body_id) = item.node { - if let Some(Node::Item(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) { + if let Some(Node::Item(it)) = cx.tcx.hir().find(cx.tcx.hir().get_parent(item.id)) { if let ItemKind::Impl(_, _, _, _, Some(_), _, _) = it.node { return; // ignore trait impls } @@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option) { - let fn_def_id = cx.tcx.hir.local_def_id(fn_id); + let fn_def_id = cx.tcx.hir().local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); let fn_ty = sig.skip_binder(); diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index eece07d006a..c61608e1c1b 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { _: Span, _: NodeId, ) { - let def_id = cx.tcx.hir.body_owner_def_id(body.id()); + let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 472596beaf7..21c4e9d30de 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -371,7 +371,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V TyKind::Slice(ref sty) => check_ty(cx, sty, bindings), TyKind::Array(ref fty, ref anon_const) => { check_ty(cx, fty, bindings); - check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings); + check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings); }, TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => { check_ty(cx, mty, bindings) @@ -381,7 +381,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V check_ty(cx, t, bindings) } }, - TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings), + TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings), _ => (), } } diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index ff37488c839..c54d89da705 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -82,9 +82,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { } // Check if the binary expression is part of another bi/unary expression // as a child node - let mut parent_expr = cx.tcx.hir.get_parent_node(expr.id); + let mut parent_expr = cx.tcx.hir().get_parent_node(expr.id); while parent_expr != ast::CRATE_NODE_ID { - if let hir::Node::Expr(e) = cx.tcx.hir.get(parent_expr) { + if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) { match e.node { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot, _) @@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { _ => {}, } } - parent_expr = cx.tcx.hir.get_parent_node(parent_expr); + parent_expr = cx.tcx.hir().get_parent_node(parent_expr); } // as a parent node let mut visitor = BinaryExprVisitor { in_binary_expr: false }; @@ -182,12 +182,12 @@ fn check_binop<'a>( } // Get the actually implemented trait - let parent_fn = cx.tcx.hir.get_parent(expr.id); - let parent_impl = cx.tcx.hir.get_parent(parent_fn); + let parent_fn = cx.tcx.hir().get_parent(expr.id); + let parent_impl = cx.tcx.hir().get_parent(parent_fn); if_chain! { if parent_impl != ast::CRATE_NODE_ID; - if let hir::Node::Item(item) = cx.tcx.hir.get(parent_impl); + if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl); if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node; if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.def.def_id()); if binop != expected_ops[idx]; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 070d591fcf0..9a7a5958b62 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -82,11 +82,11 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { } fn check_trait_method(&mut self, cx: &LateContext<'_, 'tcx>, item: &TraitItemRef) { - let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id); + let method_def_id = cx.tcx.hir().local_def_id(item.id.node_id); let method_sig = cx.tcx.fn_sig(method_def_id); let method_sig = cx.tcx.erase_late_bound_regions(&method_sig); - let decl = match cx.tcx.hir.fn_decl(item.id.node_id) { + let decl = match cx.tcx.hir().fn_decl(item.id.node_id) { Some(b) => b, None => return, }; @@ -192,7 +192,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(node_id)) { if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) | ItemKind::Trait(..)) { @@ -200,7 +200,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } } - let fn_def_id = cx.tcx.hir.local_def_id(node_id); + let fn_def_id = cx.tcx.hir().local_def_id(node_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 1b98a89f868..fc5f1509931 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -154,7 +154,7 @@ impl LintPass for TypePass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { // skip trait implementations, see #605 - if let Some(hir::Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) { + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent(id)) { if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { return; } @@ -203,7 +203,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) GenericArg::Lifetime(_) => None, }); if let TyKind::Path(ref qpath) = ty.node; - if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id))); + if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir().node_to_hir_id(ty.id))); if match_def_path(cx.tcx, did, path); then { return true; @@ -223,7 +223,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { } match ast_ty.node { TyKind::Path(ref qpath) if !is_local => { - let hir_id = cx.tcx.hir.node_to_hir_id(ast_ty.id); + let hir_id = cx.tcx.hir().node_to_hir_id(ast_ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { if Some(def_id) == cx.tcx.lang_items().owned_box() { @@ -317,7 +317,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { match mut_ty.ty.node { TyKind::Path(ref qpath) => { - let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id); + let hir_id = cx.tcx.hir().node_to_hir_id(mut_ty.ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if_chain! { if let Some(def_id) = opt_def_id(def); @@ -545,7 +545,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => { for arg in args { if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { - let map = &cx.tcx.hir; + let map = &cx.tcx.hir(); // apparently stuff in the desugaring of `?` can trigger this // so check for that here // only the calls to `Try::from_error` is marked as desugared, @@ -1930,7 +1930,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { }); let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); - for item in items.iter().map(|item| cx.tcx.hir.impl_item(item.id)) { + for item in items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) { ctr_vis.visit_impl_item(item); } @@ -1949,7 +1949,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { } }, ItemKind::Fn(ref decl, .., ref generics, body_id) => { - let body = cx.tcx.hir.body(body_id); + let body = cx.tcx.hir().body(body_id); for ty in &decl.inputs { let mut vis = ImplicitHasherTypeVisitor::new(cx); @@ -2157,6 +2157,6 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index ed4a9578440..bebbce8e73e 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -93,6 +93,6 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { walk_expr(self, expr); } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.cx.tcx.hir) + NestedVisitorMap::All(&self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6e9b70f3003..c65406a1954 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -185,7 +185,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir) + NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 27ca01b8141..d4e03c097f7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -135,7 +135,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); let trait_method_sig = cx.tcx.erase_late_bound_regions(&trait_method_sig); - let impl_method_def_id = cx.tcx.hir.local_def_id(impl_item.id); + let impl_method_def_id = cx.tcx.hir().local_def_id(impl_item.id); let impl_method_sig = cx.tcx.fn_sig(impl_method_def_id); let impl_method_sig = cx.tcx.erase_late_bound_regions(&impl_method_sig); @@ -190,18 +190,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { item_path, cx, }; - let impl_def_id = cx.tcx.hir.local_def_id(item.id); + let impl_def_id = cx.tcx.hir().local_def_id(item.id); let impl_trait_ref = cx.tcx.impl_trait_ref(impl_def_id); if let Some(impl_trait_ref) = impl_trait_ref { for impl_item_ref in refs { - let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); if let ImplItemKind::Method(MethodSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.node { let item_type = cx.tcx.type_of(impl_def_id); check_trait_method_impl_decl(cx, item_type, impl_item, impl_decl, &impl_trait_ref); - let body = cx.tcx.hir.body(*impl_body_id); + let body = cx.tcx.hir().body(*impl_body_id); visitor.visit_body(body); } else { visitor.visit_impl_item(impl_item); @@ -209,7 +209,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { } } else { for impl_item_ref in refs { - let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id); + let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); visitor.visit_impl_item(impl_item); } } @@ -238,6 +238,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.cx.tcx.hir) + NestedVisitorMap::All(&self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 27f49e72b33..73169414a02 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -145,9 +145,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }, (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => { let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); - let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id.body).value); + let ll = celcx.expr(&self.cx.tcx.hir().body(ll_id.body).value); let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); - let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id.body).value); + let rl = celcx.expr(&self.cx.tcx.hir().body(rl_id.body).value); self.eq_expr(le, re) && ll == rl }, @@ -287,11 +287,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); self.tables = self.cx.tcx.body_tables(ll_id.body); - let ll = celcx.expr(&self.cx.tcx.hir.body(ll_id.body).value); + let ll = celcx.expr(&self.cx.tcx.hir().body(ll_id.body).value); let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); self.tables = self.cx.tcx.body_tables(rl_id.body); - let rl = celcx.expr(&self.cx.tcx.hir.body(rl_id.body).value); + let rl = celcx.expr(&self.cx.tcx.hir().body(rl_id.body).value); let eq_ty = self.eq_ty(lt, rt); self.tables = full_table; @@ -484,7 +484,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { CaptureClause::CaptureByRef => 1, } .hash(&mut self.s); - self.hash_expr(&self.cx.tcx.hir.body(eid).value); + self.hash_expr(&self.cx.tcx.hir().body(eid).value); }, ExprKind::Field(ref e, ref f) => { let c: fn(_, _) -> _ = ExprKind::Field; @@ -551,7 +551,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); let full_table = self.tables; self.tables = self.cx.tcx.body_tables(l_id.body); - self.hash_expr(&self.cx.tcx.hir.body(l_id.body).value); + self.hash_expr(&self.cx.tcx.hir().body(l_id.body).value); self.tables = full_table; }, ExprKind::Ret(ref e) => { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 7297db4283b..93a5845ad45 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match item.node { hir::ImplItemKind::Const(_, body_id) => { println!("associated constant"); - print_expr(cx, &cx.tcx.hir.body(body_id).value, 1); + print_expr(cx, &cx.tcx.hir().body(body_id).value, 1); }, hir::ImplItemKind::Method(..) => println!("method"), hir::ImplItemKind::Type(_) => println!("associated type"), @@ -345,13 +345,13 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { println!("{}value:", ind); print_expr(cx, val, indent + 1); println!("{}repeat count:", ind); - print_expr(cx, &cx.tcx.hir.body(anon_const.body).value, indent + 1); + print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1); }, } } fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { - let did = cx.tcx.hir.local_def_id(item.id); + let did = cx.tcx.hir().local_def_id(item.id); println!("item `{}`", item.name); match item.vis.node { hir::VisibilityKind::Public => println!("public"), @@ -364,7 +364,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { } match item.node { hir::ItemKind::ExternCrate(ref _renamed_from) => { - let def_id = cx.tcx.hir.local_def_id(item.id); + let def_id = cx.tcx.hir().local_def_id(item.id); if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(def_id) { let source = cx.tcx.used_crate_source(crate_id); if let Some(ref src) = source.dylib { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 5855ef672c2..144e2693b47 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -166,8 +166,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { output: &mut self.registered_lints, cx, }; - let body_id = cx.tcx.hir.body_owned_by(impl_item_refs[0].id.node_id); - collector.visit_expr(&cx.tcx.hir.body(body_id).value); + let body_id = cx.tcx.hir().body_owned_by(impl_item_refs[0].id.node_id); + collector.visit_expr(&cx.tcx.hir().body(body_id).value); } } } @@ -236,7 +236,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { } } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.cx.tcx.hir) + NestedVisitorMap::All(&self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 316fee6b0e1..b9a95f340a7 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -62,8 +62,8 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { } pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { - let parent_id = cx.tcx.hir.get_parent(id); - match cx.tcx.hir.body_owner_kind(parent_id) { + let parent_id = cx.tcx.hir().get_parent(id); + match cx.tcx.hir().body_owner_kind(parent_id) { hir::BodyOwnerKind::Fn => false, hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(..) => true, } @@ -331,8 +331,8 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option, expr: &Expr) -> Option { - let parent_id = cx.tcx.hir.get_parent(expr.id); - match cx.tcx.hir.find(parent_id) { + let parent_id = cx.tcx.hir().get_parent(expr.id); + match cx.tcx.hir().find(parent_id) { Some(Node::Item(&Item { ref name, .. })) => Some(*name), Some(Node::TraitItem(&TraitItem { ident, .. })) | Some(Node::ImplItem(&ImplItem { ident, .. })) => { Some(ident.name) @@ -520,7 +520,7 @@ fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_ /// Get a parent expressions if any – this is useful to constrain a lint. pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c Expr> { - let map = &cx.tcx.hir; + let map = &cx.tcx.hir(); let node_id: NodeId = e.id; let parent_id: NodeId = map.get_parent_node(node_id); if node_id == parent_id { @@ -536,7 +536,7 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c } pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { - let map = &cx.tcx.hir; + let map = &cx.tcx.hir(); let enclosing_node = map .get_enclosing_scope(node) .and_then(|enclosing_id| map.find(enclosing_id)); @@ -550,7 +550,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI | Node::ImplItem(&ImplItem { node: ImplItemKind::Method(_, eid), .. - }) => match cx.tcx.hir.body(eid).value.node { + }) => match cx.tcx.hir().body(eid).value.node { ExprKind::Block(ref block, _) => Some(block), _ => None, }, @@ -836,7 +836,7 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { /// Convenience function to get the return type of a function pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'tcx> { - let fn_def_id = cx.tcx.hir.local_def_id(fn_item); + let fn_def_id = cx.tcx.hir().local_def_id(fn_item); let ret_ty = cx.tcx.fn_sig(fn_def_id).output(); cx.tcx.erase_late_bound_regions(&ret_ty) } @@ -1117,7 +1117,7 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { } pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: NodeId) -> bool { - let map = &tcx.hir; + let map = &tcx.hir(); let mut prev_enclosing_node = None; let mut enclosing_node = node; while Some(enclosing_node) != prev_enclosing_node { diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index c9595ca5f50..854da37f4d2 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -21,7 +21,7 @@ pub fn get_spans( idx: usize, replacements: &'static [(&'static str, &'static str)], ) -> Option)>> { - if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) { + if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) { get_binding_name(&body.arguments[idx]).map_or_else( || Some(vec![]), |name| extract_clone_suggestions(cx, name, replacements, body), -- cgit 1.4.1-3-g733a5 From d90cad24a19190fd51c7a90203a29c5c91780711 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 8 Dec 2018 11:57:25 +0100 Subject: Fix c_void false positive caused by libc refactoring The path of `libc::c_void` has changes in https://github.com/rust-lang/libc/commit/5c1a6b8a6d558882927a0816d91c01b9c2a88018 The DefId path is now always platform specific like `libc::windows::c_void`. This fixes our c_void detection to only check the first and last elements. --- clippy_lints/src/types.rs | 23 ++++++++++++++++++----- clippy_lints/src/utils/mod.rs | 38 ++++++++++++++++++++------------------ clippy_lints/src/utils/paths.rs | 2 -- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index fc5f1509931..f9a0d611429 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -28,8 +28,9 @@ use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, - match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, + match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, + AbsolutePathBuffer }; use if_chain::if_chain; use std::borrow::Cow; @@ -1023,6 +1024,21 @@ impl LintPass for CastPass { } } +// Check if the given type is either `core::ffi::c_void` or +// one of the platform specific `libc::::c_void` of libc. +fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { + if let ty::Adt(adt, _) = ty.sty { + let mut apb = AbsolutePathBuffer { names: vec![] }; + tcx.push_item_path(&mut apb, adt.did, false); + + if apb.names.is_empty() { return false } + if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" { + return true + } + } + false +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Cast(ref ex, _) = expr.node { @@ -1114,10 +1130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi); if from_align < to_align; // with c_void, we inherently need to trust the user - if ! ( - match_type(cx, from_ptr_ty.ty, &paths::C_VOID) - || match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC) - ); + if !is_c_void(cx.tcx, from_ptr_ty.ty); then { span_lint( cx, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b9a95f340a7..68357b08d6c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -29,6 +29,7 @@ use crate::syntax::attr; use crate::syntax::errors::DiagnosticBuilder; use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::symbol::{keywords, Symbol}; +use crate::syntax::symbol; use if_chain::if_chain; use matches::matches; use std::borrow::Cow; @@ -74,6 +75,25 @@ pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().is_some() } +/// Used to store the absolute path to a type. +/// +/// See `match_def_path` for usage. +#[derive(Debug)] +pub struct AbsolutePathBuffer { + pub names: Vec, +} + +impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { + fn root_mode(&self) -> &ty::item_path::RootMode { + const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; + ABSOLUTE + } + + fn push(&mut self, text: &str) { + self.names.push(symbol::Symbol::intern(text).as_str()); + } +} + /// Check if a `DefId`'s path matches the given absolute type path usage. /// /// # Examples @@ -83,24 +103,6 @@ pub fn in_macro(span: Span) -> bool { /// /// See also the `paths` module. pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool { - use crate::syntax::symbol; - - #[derive(Debug)] - struct AbsolutePathBuffer { - names: Vec, - } - - impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { - fn root_mode(&self) -> &ty::item_path::RootMode { - const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; - ABSOLUTE - } - - fn push(&mut self, text: &str) { - self.names.push(symbol::Symbol::intern(text).as_str()); - } - } - let mut apb = AbsolutePathBuffer { names: vec![] }; tcx.push_item_path(&mut apb, def_id, false); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 69a2500a1e1..0779d77936f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -27,8 +27,6 @@ pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; -pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"]; -pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; -- cgit 1.4.1-3-g733a5 From fe3519e0ddc277032659c6a1b5e38ead326dd9e4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 8 Dec 2018 12:09:32 +0100 Subject: Swap if branches --- clippy_lints/src/methods/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 57eb5c539bc..d311f76074c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1333,7 +1333,9 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp let snip; if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { // x.clone() might have dereferenced x, possibly through Deref impls - if cx.tables.expr_ty(arg) != ty { + if cx.tables.expr_ty(arg) == ty { + snip = Some(("try removing the `clone` call", format!("{}", snippet))); + } else { let parent = cx.tcx.hir().get_parent_node(expr.id); match cx.tcx.hir().get(parent) { hir::Node::Expr(parent) => match parent.node { @@ -1367,8 +1369,6 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp .count(); let derefs: String = iter::repeat('*').take(deref_count).collect(); snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet))); - } else { - snip = Some(("try removing the `clone` call", format!("{}", snippet))); } } else { snip = None; -- cgit 1.4.1-3-g733a5 From d93ea1ec99261cf1f0b0d68f8760077d7d332f34 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 8 Dec 2018 12:41:04 +0100 Subject: s/rustfmt-preview/rustfmt/ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b3331c8a26d..e3819448877 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_install: install: - | if [ -z ${INTEGRATION} ]; then - rustup component add rustfmt-preview || cargo install --git https://github.com/rust-lang/rustfmt/ --force + rustup component add rustfmt || cargo install --git https://github.com/rust-lang/rustfmt/ --force if [ "$TRAVIS_OS_NAME" == "linux" ]; then . $HOME/.nvm/nvm.sh nvm install stable -- cgit 1.4.1-3-g733a5 From 790e611c9ce9478c94e5103afb0506ab5c9fcd5d Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 9 Dec 2018 19:18:35 +0900 Subject: Cleanup --- clippy_lints/src/redundant_clone.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index c61608e1c1b..843f1cbd36e 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -12,7 +12,7 @@ use crate::rustc::hir::{def_id, Body, FnDecl}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::mir::{ self, traversal, - visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor}, + visit::{MutatingUseContext, PlaceContext, Visitor}, TerminatorKind, }; use crate::rustc::ty; @@ -279,10 +279,8 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { match ctx { - PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => { - return; - }, - _ => {}, + PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return, + _ => {} } if *local == self.local { -- cgit 1.4.1-3-g733a5 From 273dc828721204408a43607164816d250622f5db Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Dec 2018 12:03:10 +0100 Subject: run rustfmt --- clippy_lints/src/methods/mod.rs | 5 ++++- clippy_lints/src/types.rs | 8 +++++--- clippy_lints/src/utils/mod.rs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d311f76074c..384e027db27 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1358,7 +1358,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp _ => {}, } - let deref_count = cx.tables.expr_adjustments(arg).iter() + let deref_count = cx + .tables + .expr_adjustments(arg) + .iter() .filter(|adj| { if let ty::adjustment::Adjust::Deref(_) = adj.kind { true diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f9a0d611429..820f2fdf32d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -30,7 +30,7 @@ use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, - AbsolutePathBuffer + AbsolutePathBuffer, }; use if_chain::if_chain; use std::borrow::Cow; @@ -1031,9 +1031,11 @@ fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { let mut apb = AbsolutePathBuffer { names: vec![] }; tcx.push_item_path(&mut apb, adt.did, false); - if apb.names.is_empty() { return false } + if apb.names.is_empty() { + return false; + } if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" { - return true + return true; } } false diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 68357b08d6c..6b556b43888 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -28,8 +28,8 @@ use crate::syntax::ast::{self, LitKind}; use crate::syntax::attr; use crate::syntax::errors::DiagnosticBuilder; use crate::syntax::source_map::{Span, DUMMY_SP}; -use crate::syntax::symbol::{keywords, Symbol}; use crate::syntax::symbol; +use crate::syntax::symbol::{keywords, Symbol}; use if_chain::if_chain; use matches::matches; use std::borrow::Cow; -- cgit 1.4.1-3-g733a5 From 43542f8d89e178a81976d324b23efd5800071dfe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 15:16:36 +0100 Subject: Remove a run-rustfix annotation (for now) Starting to work on #2376, this annotation got in the way. Going to remove it for now. --- tests/ui/unused_unit.rs | 1 - tests/ui/unused_unit.stderr | 34 +++++++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index a7f08c28939..3930eecf1b7 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// run-rustfix // compile-pass // The output for humans should just highlight the whole span without showing diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index b5d5bdbcbee..92d0095c0b5 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -1,51 +1,51 @@ error: unneeded unit return type - --> $DIR/unused_unit.rs:28:59 + --> $DIR/unused_unit.rs:27:59 | -28 | pub fn get_unit (), G>(&self, f: F, _g: G) -> +27 | pub fn get_unit (), G>(&self, f: F, _g: G) -> | ___________________________________________________________^ -29 | | () +28 | | () | |__________^ help: remove the `-> ()` | note: lint level defined here - --> $DIR/unused_unit.rs:21:9 + --> $DIR/unused_unit.rs:20:9 | -21 | #![deny(clippy::unused_unit)] +20 | #![deny(clippy::unused_unit)] | ^^^^^^^^^^^^^^^^^^^ error: unneeded unit return type - --> $DIR/unused_unit.rs:37:19 + --> $DIR/unused_unit.rs:36:19 | -37 | fn into(self) -> () { +36 | fn into(self) -> () { | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:38:9 + --> $DIR/unused_unit.rs:37:9 | -38 | () +37 | () | ^^ help: remove the final `()` error: unneeded unit return type - --> $DIR/unused_unit.rs:42:18 + --> $DIR/unused_unit.rs:41:18 | -42 | fn return_unit() -> () { () } +41 | fn return_unit() -> () { () } | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:42:26 + --> $DIR/unused_unit.rs:41:26 | -42 | fn return_unit() -> () { () } +41 | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` - --> $DIR/unused_unit.rs:49:14 + --> $DIR/unused_unit.rs:48:14 | -49 | break(); +48 | break(); | ^^ help: remove the `()` error: unneeded `()` - --> $DIR/unused_unit.rs:51:11 + --> $DIR/unused_unit.rs:50:11 | -51 | return(); +50 | return(); | ^^ help: remove the `()` error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 72d2de680760a7bc1b57f2376eb9af79b5def58b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 15:42:52 +0100 Subject: Add `fast_finish` to travis matrix This means we don't have to wait for `allowed_failures` builds to complete. It should save us ~10 minutes until we remove the windows build from `allowed_failures`. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e3819448877..5014a66a79c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ install: # if: fork = false # but this is currently buggy travis-ci/travis-ci#9118 matrix: + fast_finish: true include: - os: osx # run base tests on both platforms env: BASE_TESTS=true -- cgit 1.4.1-3-g733a5 From a4fe5676022d66ad157b4b4238d035d6035dc31e Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 9 Dec 2018 19:18:44 +0900 Subject: Fix test `if true` is recognized by MIR optimization. --- tests/ui/redundant_clone.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index deedde38231..e5c5528e4fa 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -38,8 +38,8 @@ fn main() { #[derive(Clone)] struct Alpha; -fn double(a: Alpha) -> (Alpha, Alpha) { - if true { +fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { + if b { (a.clone(), a.clone()) } else { (Alpha, a) -- cgit 1.4.1-3-g733a5 From 4583d781562a1cff374992f64f85e9113391acd3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 8 Dec 2018 18:56:59 +0100 Subject: add rustfmt::skip attributes to some tests --- tests/ui/absurd-extreme-comparisons.rs | 5 +---- tests/ui/arithmetic.rs | 5 ++--- tests/ui/collapsible_if.rs | 4 +--- tests/ui/cyclomatic_complexity.rs | 4 ++-- tests/ui/doc.rs | 5 ----- tests/ui/double_parens.rs | 5 ----- tests/ui/empty_line_after_outer_attribute.rs | 2 -- tests/ui/eq_op.rs | 6 ++---- tests/ui/format.rs | 1 - tests/ui/methods.rs | 21 ++++++++++++++------- tests/ui/replace_consts.rs | 4 ++-- tests/ui/unused_unit.rs | 3 +-- 12 files changed, 25 insertions(+), 40 deletions(-) diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index b219cb0397b..a93027162e5 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -7,13 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::absurd_extreme_comparisons)] #![allow(unused, clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::needless_pass_by_value)] +#[rustfmt::skip] fn main() { const Z: u32 = 0; let u: u32 = 42; diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 61a601468fb..39aef5a4a56 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -8,11 +8,10 @@ // except according to those terms. - - - #![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] #![allow(unused, clippy::shadow_reuse, clippy::shadow_unrelated, clippy::no_effect, clippy::unnecessary_operation)] + +#[rustfmt::skip] fn main() { let i = 1i32; 1 + i; diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index a8ec13ab669..bd6e0c07946 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -8,9 +8,7 @@ // except according to those terms. - - - +#[rustfmt::skip] #[warn(clippy::collapsible_if)] fn main() { let x = "hello"; diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index 35451a99acc..a9a2391f150 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -8,12 +8,11 @@ // except according to those terms. - - #![allow(clippy::all)] #![warn(clippy::cyclomatic_complexity)] #![allow(unused)] +#[rustfmt::skip] fn main() { if true { println!("a"); @@ -362,6 +361,7 @@ fn early() -> Result { return Ok(5); } +#[rustfmt::skip] #[clippy::cyclomatic_complexity = "0"] fn early_ret() -> i32 { let a = if true { 42 } else { return 0; }; diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index d87142e9367..dde1a471e6e 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -7,13 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - //! This file tests for the DOC_MARKDOWN lint - - #![allow(dead_code)] #![warn(clippy::doc_markdown)] diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index be1676a7487..773179b2d46 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -7,13 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::double_parens)] #![allow(dead_code)] - fn dummy_fn(_: T) {} struct DummyStruct; diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 43105b6e342..ede1244df7e 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::empty_line_after_outer_attr)] // This should produce a warning diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 36c54b0f42e..020c7d795a4 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -7,10 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - +#[rustfmt::skip] #[warn(clippy::eq_op)] #[allow(clippy::identity_op, clippy::double_parens, clippy::many_single_char_names)] #[allow(clippy::no_effect, unused_variables, clippy::unnecessary_operation, clippy::short_circuit_statement)] @@ -107,6 +104,7 @@ fn main() { const D: u32 = A / A; } +#[rustfmt::skip] macro_rules! check_if_named_foo { ($expression:expr) => ( if stringify!($expression) == "foo" { diff --git a/tests/ui/format.rs b/tests/ui/format.rs index e314d3022da..6b1577e24ca 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -8,7 +8,6 @@ // except according to those terms. - #![allow(clippy::print_literal)] #![warn(clippy::useless_format)] diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 03bd7e1f084..877026d4bb1 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -7,14 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] -#![allow(clippy::blacklisted_name, unused, clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, - clippy::new_without_default_derive, clippy::missing_docs_in_private_items, clippy::needless_pass_by_value, - clippy::default_trait_access, clippy::use_self, clippy::new_ret_no_self, clippy::useless_format)] +#![allow( + clippy::blacklisted_name, + unused, + clippy::print_stdout, + clippy::non_ascii_literal, + clippy::new_without_default, + clippy::new_without_default_derive, + clippy::missing_docs_in_private_items, + clippy::needless_pass_by_value, + clippy::default_trait_access, + clippy::use_self, + clippy::new_ret_no_self, + clippy::useless_format +)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 7a2584f174d..7da1f212a75 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -8,8 +8,6 @@ // except according to those terms. - - #![feature(integer_atomics)] #![allow(clippy::blacklisted_name)] #![deny(clippy::replace_consts)] @@ -17,6 +15,7 @@ use std::sync::atomic::*; use std::sync::{ONCE_INIT, Once}; +#[rustfmt::skip] fn bad() { // Once { let foo = ONCE_INIT; }; @@ -60,6 +59,7 @@ fn bad() { { let foo = std::u128::MAX; }; } +#[rustfmt::skip] fn good() { // Once { let foo = Once::new(); }; diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index 3930eecf1b7..88f0b9687be 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -16,12 +16,10 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. - #![deny(clippy::unused_unit)] #![allow(clippy::needless_return)] struct Unitter; - impl Unitter { // try to disorient the lint with multiple unit returns and newlines pub fn get_unit (), G>(&self, f: F, _g: G) -> @@ -33,6 +31,7 @@ impl Unitter { } impl Into<()> for Unitter { + #[rustfmt::skip] fn into(self) -> () { () } -- cgit 1.4.1-3-g733a5 From 9b839cd4b58b2b780c1b05a1e2e9983dba632fda Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Dec 2018 17:17:58 +0100 Subject: update line numbers of tests --- tests/ui/absurd-extreme-comparisons.stderr | 72 +++--- tests/ui/arithmetic.stderr | 46 ++-- tests/ui/collapsible_if.stderr | 292 +++++++++++----------- tests/ui/cyclomatic_complexity.stderr | 256 ++++++++++---------- tests/ui/doc.stderr | 120 ++++----- tests/ui/double_parens.stderr | 24 +- tests/ui/empty_line_after_outer_attribute.stderr | 52 ++-- tests/ui/eq_op.stderr | 136 +++++------ tests/ui/format.stderr | 36 +-- tests/ui/methods.stderr | 294 +++++++++++------------ tests/ui/replace_consts.stderr | 144 +++++------ tests/ui/unused_unit.stderr | 34 +-- 12 files changed, 753 insertions(+), 753 deletions(-) diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 6c32b309aa5..895794da71a 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -1,144 +1,144 @@ error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:20:5 + --> $DIR/absurd-extreme-comparisons.rs:17:5 | -20 | u <= 0; +17 | u <= 0; | ^^^^^^ | = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings` = help: because 0 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:21:5 + --> $DIR/absurd-extreme-comparisons.rs:18:5 | -21 | u <= Z; +18 | u <= Z; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == Z instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:22:5 + --> $DIR/absurd-extreme-comparisons.rs:19:5 | -22 | u < Z; +19 | u < Z; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:23:5 + --> $DIR/absurd-extreme-comparisons.rs:20:5 | -23 | Z >= u; +20 | Z >= u; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using Z == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:24:5 + --> $DIR/absurd-extreme-comparisons.rs:21:5 | -24 | Z > u; +21 | Z > u; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:25:5 + --> $DIR/absurd-extreme-comparisons.rs:22:5 | -25 | u > std::u32::MAX; +22 | u > std::u32::MAX; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:26:5 + --> $DIR/absurd-extreme-comparisons.rs:23:5 | -26 | u >= std::u32::MAX; +23 | u >= std::u32::MAX; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == std::u32::MAX instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:27:5 + --> $DIR/absurd-extreme-comparisons.rs:24:5 | -27 | std::u32::MAX < u; +24 | std::u32::MAX < u; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:28:5 + --> $DIR/absurd-extreme-comparisons.rs:25:5 | -28 | std::u32::MAX <= u; +25 | std::u32::MAX <= u; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using std::u32::MAX == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:29:5 + --> $DIR/absurd-extreme-comparisons.rs:26:5 | -29 | 1-1 > u; +26 | 1-1 > u; | ^^^^^^^ | = help: because 1-1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:30:5 + --> $DIR/absurd-extreme-comparisons.rs:27:5 | -30 | u >= !0; +27 | u >= !0; | ^^^^^^^ | = help: because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:31:5 + --> $DIR/absurd-extreme-comparisons.rs:28:5 | -31 | u <= 12 - 2*6; +28 | u <= 12 - 2*6; | ^^^^^^^^^^^^^ | = help: because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:33:5 + --> $DIR/absurd-extreme-comparisons.rs:30:5 | -33 | i < -127 - 1; +30 | i < -127 - 1; | ^^^^^^^^^^^^ | = help: because -127 - 1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:34:5 + --> $DIR/absurd-extreme-comparisons.rs:31:5 | -34 | std::i8::MAX >= i; +31 | std::i8::MAX >= i; | ^^^^^^^^^^^^^^^^^ | = help: because std::i8::MAX is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:35:5 + --> $DIR/absurd-extreme-comparisons.rs:32:5 | -35 | 3-7 < std::i32::MIN; +32 | 3-7 < std::i32::MIN; | ^^^^^^^^^^^^^^^^^^^ | = help: because std::i32::MIN is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:37:5 + --> $DIR/absurd-extreme-comparisons.rs:34:5 | -37 | b >= true; +34 | b >= true; | ^^^^^^^^^ | = help: because true is the maximum value for this type, the case where the two sides are not equal never occurs, consider using b == true instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:38:5 + --> $DIR/absurd-extreme-comparisons.rs:35:5 | -38 | false > b; +35 | false > b; | ^^^^^^^^^ | = help: because false is the minimum value for this type, this comparison is always false error: <-comparison of unit values detected. This will always be false - --> $DIR/absurd-extreme-comparisons.rs:41:5 + --> $DIR/absurd-extreme-comparisons.rs:38:5 | -41 | () < {}; +38 | () < {}; | ^^^^^^^ | = note: #[deny(clippy::unit_cmp)] on by default diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index 5e6021403e9..f3a1db16b48 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,72 +1,72 @@ error: integer arithmetic detected - --> $DIR/arithmetic.rs:18:5 + --> $DIR/arithmetic.rs:17:5 | -18 | 1 + i; +17 | 1 + i; | ^^^^^ | = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/arithmetic.rs:19:5 + --> $DIR/arithmetic.rs:18:5 | -19 | i * 2; +18 | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:20:5 + --> $DIR/arithmetic.rs:19:5 | -20 | / 1 % -21 | | i / 2; // no error, this is part of the expression in the preceding line +19 | / 1 % +20 | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:22:5 + --> $DIR/arithmetic.rs:21:5 | -22 | i - 2 + 2 - i; +21 | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:23:5 + --> $DIR/arithmetic.rs:22:5 | -23 | -i; +22 | -i; | ^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:33:5 + --> $DIR/arithmetic.rs:32:5 | -33 | f * 2.0; +32 | f * 2.0; | ^^^^^^^ | = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:35:5 + --> $DIR/arithmetic.rs:34:5 | -35 | 1.0 + f; +34 | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:36:5 + --> $DIR/arithmetic.rs:35:5 | -36 | f * 2.0; +35 | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:37:5 + --> $DIR/arithmetic.rs:36:5 | -37 | f / 2.0; +36 | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:38:5 + --> $DIR/arithmetic.rs:37:5 | -38 | f - 2.0 * 4.2; +37 | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:39:5 + --> $DIR/arithmetic.rs:38:5 | -39 | -f; +38 | -f; | ^^ error: aborting due to 11 previous errors diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 3f06dca5495..697dec336fa 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,259 +1,259 @@ error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:18:5 + --> $DIR/collapsible_if.rs:16:5 | -18 | / if x == "hello" { -19 | | if y == "world" { -20 | | println!("Hello world!"); -21 | | } -22 | | } +16 | / if x == "hello" { +17 | | if y == "world" { +18 | | println!("Hello world!"); +19 | | } +20 | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` help: try | -18 | if x == "hello" && y == "world" { -19 | println!("Hello world!"); -20 | } +16 | if x == "hello" && y == "world" { +17 | println!("Hello world!"); +18 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:24:5 + --> $DIR/collapsible_if.rs:22:5 | -24 | / if x == "hello" || x == "world" { -25 | | if y == "world" || y == "hello" { -26 | | println!("Hello world!"); -27 | | } -28 | | } +22 | / if x == "hello" || x == "world" { +23 | | if y == "world" || y == "hello" { +24 | | println!("Hello world!"); +25 | | } +26 | | } | |_____^ help: try | -24 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -25 | println!("Hello world!"); -26 | } +22 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { +23 | println!("Hello world!"); +24 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:30:5 + --> $DIR/collapsible_if.rs:28:5 | -30 | / if x == "hello" && x == "world" { -31 | | if y == "world" || y == "hello" { -32 | | println!("Hello world!"); -33 | | } -34 | | } +28 | / if x == "hello" && x == "world" { +29 | | if y == "world" || y == "hello" { +30 | | println!("Hello world!"); +31 | | } +32 | | } | |_____^ help: try | -30 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { -31 | println!("Hello world!"); -32 | } +28 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { +29 | println!("Hello world!"); +30 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:36:5 + --> $DIR/collapsible_if.rs:34:5 | -36 | / if x == "hello" || x == "world" { -37 | | if y == "world" && y == "hello" { -38 | | println!("Hello world!"); -39 | | } -40 | | } +34 | / if x == "hello" || x == "world" { +35 | | if y == "world" && y == "hello" { +36 | | println!("Hello world!"); +37 | | } +38 | | } | |_____^ help: try | -36 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { -37 | println!("Hello world!"); -38 | } +34 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { +35 | println!("Hello world!"); +36 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:42:5 + --> $DIR/collapsible_if.rs:40:5 | -42 | / if x == "hello" && x == "world" { -43 | | if y == "world" && y == "hello" { -44 | | println!("Hello world!"); -45 | | } -46 | | } +40 | / if x == "hello" && x == "world" { +41 | | if y == "world" && y == "hello" { +42 | | println!("Hello world!"); +43 | | } +44 | | } | |_____^ help: try | -42 | if x == "hello" && x == "world" && y == "world" && y == "hello" { -43 | println!("Hello world!"); -44 | } +40 | if x == "hello" && x == "world" && y == "world" && y == "hello" { +41 | println!("Hello world!"); +42 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:48:5 + --> $DIR/collapsible_if.rs:46:5 | -48 | / if 42 == 1337 { -49 | | if 'a' != 'A' { -50 | | println!("world!") -51 | | } -52 | | } +46 | / if 42 == 1337 { +47 | | if 'a' != 'A' { +48 | | println!("world!") +49 | | } +50 | | } | |_____^ help: try | -48 | if 42 == 1337 && 'a' != 'A' { -49 | println!("world!") -50 | } +46 | if 42 == 1337 && 'a' != 'A' { +47 | println!("world!") +48 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:57:12 + --> $DIR/collapsible_if.rs:55:12 | -57 | } else { +55 | } else { | ____________^ -58 | | if y == "world" { -59 | | println!("world!") -60 | | } -61 | | } +56 | | if y == "world" { +57 | | println!("world!") +58 | | } +59 | | } | |_____^ help: try | -57 | } else if y == "world" { -58 | println!("world!") -59 | } +55 | } else if y == "world" { +56 | println!("world!") +57 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:65:12 + --> $DIR/collapsible_if.rs:63:12 | -65 | } else { +63 | } else { | ____________^ -66 | | if let Some(42) = Some(42) { -67 | | println!("world!") -68 | | } -69 | | } +64 | | if let Some(42) = Some(42) { +65 | | println!("world!") +66 | | } +67 | | } | |_____^ help: try | -65 | } else if let Some(42) = Some(42) { -66 | println!("world!") -67 | } +63 | } else if let Some(42) = Some(42) { +64 | println!("world!") +65 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:73:12 + --> $DIR/collapsible_if.rs:71:12 | -73 | } else { +71 | } else { | ____________^ -74 | | if y == "world" { -75 | | println!("world") -76 | | } +72 | | if y == "world" { +73 | | println!("world") +74 | | } ... | -79 | | } -80 | | } +77 | | } +78 | | } | |_____^ help: try | -73 | } else if y == "world" { -74 | println!("world") -75 | } -76 | else { -77 | println!("!") -78 | } +71 | } else if y == "world" { +72 | println!("world") +73 | } +74 | else { +75 | println!("!") +76 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:84:12 + --> $DIR/collapsible_if.rs:82:12 | -84 | } else { +82 | } else { | ____________^ -85 | | if let Some(42) = Some(42) { -86 | | println!("world") -87 | | } +83 | | if let Some(42) = Some(42) { +84 | | println!("world") +85 | | } ... | -90 | | } -91 | | } +88 | | } +89 | | } | |_____^ help: try | -84 | } else if let Some(42) = Some(42) { -85 | println!("world") -86 | } -87 | else { -88 | println!("!") -89 | } +82 | } else if let Some(42) = Some(42) { +83 | println!("world") +84 | } +85 | else { +86 | println!("!") +87 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:95:12 + --> $DIR/collapsible_if.rs:93:12 | -95 | } else { +93 | } else { | ____________^ -96 | | if let Some(42) = Some(42) { -97 | | println!("world") -98 | | } +94 | | if let Some(42) = Some(42) { +95 | | println!("world") +96 | | } ... | -101 | | } -102 | | } +99 | | } +100 | | } | |_____^ help: try | -95 | } else if let Some(42) = Some(42) { -96 | println!("world") -97 | } -98 | else { -99 | println!("!") -100 | } +93 | } else if let Some(42) = Some(42) { +94 | println!("world") +95 | } +96 | else { +97 | println!("!") +98 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:106:12 + --> $DIR/collapsible_if.rs:104:12 | -106 | } else { +104 | } else { | ____________^ -107 | | if x == "hello" { -108 | | println!("world") -109 | | } +105 | | if x == "hello" { +106 | | println!("world") +107 | | } ... | -112 | | } -113 | | } +110 | | } +111 | | } | |_____^ help: try | -106 | } else if x == "hello" { -107 | println!("world") -108 | } -109 | else { -110 | println!("!") -111 | } +104 | } else if x == "hello" { +105 | println!("world") +106 | } +107 | else { +108 | println!("!") +109 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:117:12 + --> $DIR/collapsible_if.rs:115:12 | -117 | } else { +115 | } else { | ____________^ -118 | | if let Some(42) = Some(42) { -119 | | println!("world") -120 | | } +116 | | if let Some(42) = Some(42) { +117 | | println!("world") +118 | | } ... | -123 | | } -124 | | } +121 | | } +122 | | } | |_____^ help: try | -117 | } else if let Some(42) = Some(42) { -118 | println!("world") -119 | } -120 | else { -121 | println!("!") -122 | } +115 | } else if let Some(42) = Some(42) { +116 | println!("world") +117 | } +118 | else { +119 | println!("!") +120 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:176:5 + --> $DIR/collapsible_if.rs:174:5 | -176 | / if x == "hello" { -177 | | if y == "world" { // Collapsible -178 | | println!("Hello world!"); -179 | | } -180 | | } +174 | / if x == "hello" { +175 | | if y == "world" { // Collapsible +176 | | println!("Hello world!"); +177 | | } +178 | | } | |_____^ help: try | -176 | if x == "hello" && y == "world" { // Collapsible -177 | println!("Hello world!"); -178 | } +174 | if x == "hello" && y == "world" { // Collapsible +175 | println!("Hello world!"); +176 | } | error: aborting due to 14 previous errors diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index ddc2f5b159f..390df2f5a5b 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -1,256 +1,256 @@ error: the function has a cyclomatic complexity of 28 - --> $DIR/cyclomatic_complexity.rs:17:1 + --> $DIR/cyclomatic_complexity.rs:16:1 | -17 | / fn main() { -18 | | if true { -19 | | println!("a"); -20 | | } +16 | / fn main() { +17 | | if true { +18 | | println!("a"); +19 | | } ... | -98 | | } -99 | | } +97 | | } +98 | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 - --> $DIR/cyclomatic_complexity.rs:102:1 + --> $DIR/cyclomatic_complexity.rs:101:1 | -102 | / fn kaboom() { -103 | | let n = 0; -104 | | 'a: for i in 0..20 { -105 | | 'b: for j in i..20 { +101 | / fn kaboom() { +102 | | let n = 0; +103 | | 'a: for i in 0..20 { +104 | | 'b: for j in i..20 { ... | -120 | | } -121 | | } +119 | | } +120 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:148:1 + --> $DIR/cyclomatic_complexity.rs:147:1 | -148 | / fn lots_of_short_circuits() -> bool { -149 | | true && false && true && false && true && false && true -150 | | } +147 | / fn lots_of_short_circuits() -> bool { +148 | | true && false && true && false && true && false && true +149 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:153:1 + --> $DIR/cyclomatic_complexity.rs:152:1 | -153 | / fn lots_of_short_circuits2() -> bool { -154 | | true || false || true || false || true || false || true -155 | | } +152 | / fn lots_of_short_circuits2() -> bool { +153 | | true || false || true || false || true || false || true +154 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:158:1 + --> $DIR/cyclomatic_complexity.rs:157:1 | -158 | / fn baa() { -159 | | let x = || match 99 { -160 | | 0 => 0, -161 | | 1 => 1, +157 | / fn baa() { +158 | | let x = || match 99 { +159 | | 0 => 0, +160 | | 1 => 1, ... | -172 | | } -173 | | } +171 | | } +172 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:159:13 + --> $DIR/cyclomatic_complexity.rs:158:13 | -159 | let x = || match 99 { +158 | let x = || match 99 { | _____________^ -160 | | 0 => 0, -161 | | 1 => 1, -162 | | 2 => 2, +159 | | 0 => 0, +160 | | 1 => 1, +161 | | 2 => 2, ... | -166 | | _ => 42, -167 | | }; +165 | | _ => 42, +166 | | }; | |_____^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:176:1 - | -176 | / fn bar() { -177 | | match 99 { -178 | | 0 => println!("hi"), -179 | | _ => println!("bye"), -180 | | } -181 | | } + --> $DIR/cyclomatic_complexity.rs:175:1 + | +175 | / fn bar() { +176 | | match 99 { +177 | | 0 => println!("hi"), +178 | | _ => println!("bye"), +179 | | } +180 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:195:1 + --> $DIR/cyclomatic_complexity.rs:194:1 | -195 | / fn barr() { -196 | | match 99 { -197 | | 0 => println!("hi"), -198 | | 1 => println!("bla"), +194 | / fn barr() { +195 | | match 99 { +196 | | 0 => println!("hi"), +197 | | 1 => println!("bla"), ... | -201 | | } -202 | | } +200 | | } +201 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:205:1 + --> $DIR/cyclomatic_complexity.rs:204:1 | -205 | / fn barr2() { -206 | | match 99 { -207 | | 0 => println!("hi"), -208 | | 1 => println!("bla"), +204 | / fn barr2() { +205 | | match 99 { +206 | | 0 => println!("hi"), +207 | | 1 => println!("bla"), ... | -217 | | } -218 | | } +216 | | } +217 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:221:1 + --> $DIR/cyclomatic_complexity.rs:220:1 | -221 | / fn barrr() { -222 | | match 99 { -223 | | 0 => println!("hi"), -224 | | 1 => panic!("bla"), +220 | / fn barrr() { +221 | | match 99 { +222 | | 0 => println!("hi"), +223 | | 1 => panic!("bla"), ... | -227 | | } -228 | | } +226 | | } +227 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:231:1 + --> $DIR/cyclomatic_complexity.rs:230:1 | -231 | / fn barrr2() { -232 | | match 99 { -233 | | 0 => println!("hi"), -234 | | 1 => panic!("bla"), +230 | / fn barrr2() { +231 | | match 99 { +232 | | 0 => println!("hi"), +233 | | 1 => panic!("bla"), ... | -243 | | } -244 | | } +242 | | } +243 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:247:1 + --> $DIR/cyclomatic_complexity.rs:246:1 | -247 | / fn barrrr() { -248 | | match 99 { -249 | | 0 => println!("hi"), -250 | | 1 => println!("bla"), +246 | / fn barrrr() { +247 | | match 99 { +248 | | 0 => println!("hi"), +249 | | 1 => println!("bla"), ... | -253 | | } -254 | | } +252 | | } +253 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:257:1 + --> $DIR/cyclomatic_complexity.rs:256:1 | -257 | / fn barrrr2() { -258 | | match 99 { -259 | | 0 => println!("hi"), -260 | | 1 => println!("bla"), +256 | / fn barrrr2() { +257 | | match 99 { +258 | | 0 => println!("hi"), +259 | | 1 => println!("bla"), ... | -269 | | } -270 | | } +268 | | } +269 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:273:1 + --> $DIR/cyclomatic_complexity.rs:272:1 | -273 | / fn cake() { -274 | | if 4 == 5 { -275 | | println!("yea"); -276 | | } else { +272 | / fn cake() { +273 | | if 4 == 5 { +274 | | println!("yea"); +275 | | } else { ... | -279 | | println!("whee"); -280 | | } +278 | | println!("whee"); +279 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 4 - --> $DIR/cyclomatic_complexity.rs:284:1 + --> $DIR/cyclomatic_complexity.rs:283:1 | -284 | / pub fn read_file(input_path: &str) -> String { -285 | | use std::fs::File; -286 | | use std::io::{Read, Write}; -287 | | use std::path::Path; +283 | / pub fn read_file(input_path: &str) -> String { +284 | | use std::fs::File; +285 | | use std::io::{Read, Write}; +286 | | use std::path::Path; ... | -309 | | } -310 | | } +308 | | } +309 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:315:1 - | -315 | / fn void(void: Void) { -316 | | if true { -317 | | match void { -318 | | } -319 | | } -320 | | } + --> $DIR/cyclomatic_complexity.rs:314:1 + | +314 | / fn void(void: Void) { +315 | | if true { +316 | | match void { +317 | | } +318 | | } +319 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:329:1 - | -329 | / fn try() -> Result { -330 | | match 5 { -331 | | 5 => Ok(5), -332 | | _ => return Err("bla"), -333 | | } -334 | | } + --> $DIR/cyclomatic_complexity.rs:328:1 + | +328 | / fn try() -> Result { +329 | | match 5 { +330 | | 5 => Ok(5), +331 | | _ => return Err("bla"), +332 | | } +333 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:337:1 + --> $DIR/cyclomatic_complexity.rs:336:1 | -337 | / fn try_again() -> Result { -338 | | let _ = try!(Ok(42)); -339 | | let _ = try!(Ok(43)); -340 | | let _ = try!(Ok(44)); +336 | / fn try_again() -> Result { +337 | | let _ = try!(Ok(42)); +338 | | let _ = try!(Ok(43)); +339 | | let _ = try!(Ok(44)); ... | -349 | | } -350 | | } +348 | | } +349 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:353:1 + --> $DIR/cyclomatic_complexity.rs:352:1 | -353 | / fn early() -> Result { +352 | / fn early() -> Result { +353 | | return Ok(5); 354 | | return Ok(5); 355 | | return Ok(5); -356 | | return Ok(5); ... | -362 | | return Ok(5); -363 | | } +361 | | return Ok(5); +362 | | } | |_^ | = help: you could split it up into multiple smaller functions diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index 69fa4e32cd3..85c0fd898c7 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -1,183 +1,183 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation - --> $DIR/doc.rs:13:29 + --> $DIR/doc.rs:10:29 | -13 | //! This file tests for the DOC_MARKDOWN lint +10 | //! This file tests for the DOC_MARKDOWN lint | ^^^^^^^^^^^^ | = note: `-D clippy::doc-markdown` implied by `-D warnings` error: you should put `foo_bar` between ticks in the documentation - --> $DIR/doc.rs:20:9 + --> $DIR/doc.rs:15:9 | -20 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +15 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^ error: you should put `foo::bar` between ticks in the documentation - --> $DIR/doc.rs:20:51 + --> $DIR/doc.rs:15:51 | -20 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +15 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^^ error: you should put `Foo::some_fun` between ticks in the documentation - --> $DIR/doc.rs:21:84 + --> $DIR/doc.rs:16:84 | -21 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun +16 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun | ^^^^^^^^^^^^^ error: you should put `a::global:path` between ticks in the documentation - --> $DIR/doc.rs:23:15 + --> $DIR/doc.rs:18:15 | -23 | /// Here be ::a::global:path. +18 | /// Here be ::a::global:path. | ^^^^^^^^^^^^^^ error: you should put `NotInCodeBlock` between ticks in the documentation - --> $DIR/doc.rs:24:22 + --> $DIR/doc.rs:19:22 | -24 | /// That's not code ~NotInCodeBlock~. +19 | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:25:5 + --> $DIR/doc.rs:20:5 | -25 | /// be_sure_we_got_to_the_end_of_it +20 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:39:5 + --> $DIR/doc.rs:34:5 | -39 | /// be_sure_we_got_to_the_end_of_it +34 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:46:5 + --> $DIR/doc.rs:41:5 | -46 | /// be_sure_we_got_to_the_end_of_it +41 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:60:5 + --> $DIR/doc.rs:55:5 | -60 | /// be_sure_we_got_to_the_end_of_it +55 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:64:22 + --> $DIR/doc.rs:59:22 | -64 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. +59 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:67:21 + --> $DIR/doc.rs:62:21 | -67 | /// It can also be [inline_link2]. +62 | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:77:5 + --> $DIR/doc.rs:72:5 | -77 | /// be_sure_we_got_to_the_end_of_it +72 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:85:8 + --> $DIR/doc.rs:80:8 | -85 | /// ## CamelCaseThing +80 | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:88:7 + --> $DIR/doc.rs:83:7 | -88 | /// # CamelCaseThing +83 | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:90:22 + --> $DIR/doc.rs:85:22 | -90 | /// Not a title #897 CamelCaseThing +85 | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:91:5 + --> $DIR/doc.rs:86:5 | -91 | /// be_sure_we_got_to_the_end_of_it +86 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:98:5 + --> $DIR/doc.rs:93:5 | -98 | /// be_sure_we_got_to_the_end_of_it +93 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:111:5 + --> $DIR/doc.rs:106:5 | -111 | /// be_sure_we_got_to_the_end_of_it +106 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:122:42 + --> $DIR/doc.rs:117:42 | -122 | /** E.g. serialization of an empty list: FooBar +117 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:127:5 + --> $DIR/doc.rs:122:5 | -127 | And BarQuz too. +122 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:128:1 + --> $DIR/doc.rs:123:1 | -128 | be_sure_we_got_to_the_end_of_it +123 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:133:42 + --> $DIR/doc.rs:128:42 | -133 | /** E.g. serialization of an empty list: FooBar +128 | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:138:5 + --> $DIR/doc.rs:133:5 | -138 | And BarQuz too. +133 | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:139:1 + --> $DIR/doc.rs:134:1 | -139 | be_sure_we_got_to_the_end_of_it +134 | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:150:5 + --> $DIR/doc.rs:145:5 | -150 | /// be_sure_we_got_to_the_end_of_it +145 | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:177:13 + --> $DIR/doc.rs:172:13 | -177 | /// Not ok: http://www.unicode.org +172 | /// Not ok: http://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:178:13 + --> $DIR/doc.rs:173:13 | -178 | /// Not ok: https://www.unicode.org +173 | /// Not ok: https://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:179:13 + --> $DIR/doc.rs:174:13 | -179 | /// Not ok: http://www.unicode.org/ +174 | /// Not ok: http://www.unicode.org/ | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:180:13 + --> $DIR/doc.rs:175:13 | -180 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +175 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 30 previous errors diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index 727b2c4ef42..d736d72c143 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -1,39 +1,39 @@ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:26:5 + --> $DIR/double_parens.rs:21:5 | -26 | ((0)) +21 | ((0)) | ^^^^^ | = note: `-D clippy::double-parens` implied by `-D warnings` error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:30:14 + --> $DIR/double_parens.rs:25:14 | -30 | dummy_fn((0)); +25 | dummy_fn((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:34:20 + --> $DIR/double_parens.rs:29:20 | -34 | x.dummy_method((0)); +29 | x.dummy_method((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:38:5 + --> $DIR/double_parens.rs:33:5 | -38 | ((1, 2)) +33 | ((1, 2)) | ^^^^^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:42:5 + --> $DIR/double_parens.rs:37:5 | -42 | (()) +37 | (()) | ^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:64:16 + --> $DIR/double_parens.rs:59:16 | -64 | assert_eq!(((1, 2)), (1, 2), "Error"); +59 | assert_eq!(((1, 2)), (1, 2), "Error"); | ^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index e742c0b6615..ec3ee6d018c 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,53 +1,53 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:15:1 + --> $DIR/empty_line_after_outer_attribute.rs:13:1 | -15 | / #[crate_type = "lib"] -16 | | -17 | | /// some comment -18 | | fn with_one_newline_and_comment() { assert!(true) } +13 | / #[crate_type = "lib"] +14 | | +15 | | /// some comment +16 | | fn with_one_newline_and_comment() { assert!(true) } | |_ | = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:27:1 + --> $DIR/empty_line_after_outer_attribute.rs:25:1 | -27 | / #[crate_type = "lib"] -28 | | -29 | | fn with_one_newline() { assert!(true) } +25 | / #[crate_type = "lib"] +26 | | +27 | | fn with_one_newline() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:32:1 + --> $DIR/empty_line_after_outer_attribute.rs:30:1 | -32 | / #[crate_type = "lib"] -33 | | -34 | | -35 | | fn with_two_newlines() { assert!(true) } +30 | / #[crate_type = "lib"] +31 | | +32 | | +33 | | fn with_two_newlines() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:39:1 + --> $DIR/empty_line_after_outer_attribute.rs:37:1 | -39 | / #[crate_type = "lib"] -40 | | -41 | | enum Baz { +37 | / #[crate_type = "lib"] +38 | | +39 | | enum Baz { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:47:1 + --> $DIR/empty_line_after_outer_attribute.rs:45:1 | -47 | / #[crate_type = "lib"] -48 | | -49 | | struct Foo { +45 | / #[crate_type = "lib"] +46 | | +47 | | struct Foo { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:55:1 + --> $DIR/empty_line_after_outer_attribute.rs:53:1 | -55 | / #[crate_type = "lib"] -56 | | -57 | | mod foo { +53 | / #[crate_type = "lib"] +54 | | +55 | | mod foo { | |_ error: aborting due to 6 previous errors diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 21487884d35..abd351b65a4 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,203 +1,203 @@ error: this boolean expression can be simplified - --> $DIR/eq_op.rs:47:5 + --> $DIR/eq_op.rs:44:5 | -47 | true && true; +44 | true && true; | ^^^^^^^^^^^^ help: try: `true` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:49:5 + --> $DIR/eq_op.rs:46:5 | -49 | true || true; +46 | true || true; | ^^^^^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:55:5 + --> $DIR/eq_op.rs:52:5 | -55 | a == b && b == a; +52 | a == b && b == a; | ^^^^^^^^^^^^^^^^ help: try: `a == b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:56:5 + --> $DIR/eq_op.rs:53:5 | -56 | a != b && b != a; +53 | a != b && b != a; | ^^^^^^^^^^^^^^^^ help: try: `a != b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:57:5 + --> $DIR/eq_op.rs:54:5 | -57 | a < b && b > a; +54 | a < b && b > a; | ^^^^^^^^^^^^^^ help: try: `a < b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:58:5 + --> $DIR/eq_op.rs:55:5 | -58 | a <= b && b >= a; +55 | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ help: try: `a <= b` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:20:5 + --> $DIR/eq_op.rs:17:5 | -20 | 1 == 1; +17 | 1 == 1; | ^^^^^^ | = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:21:5 + --> $DIR/eq_op.rs:18:5 | -21 | "no" == "no"; +18 | "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:23:5 + --> $DIR/eq_op.rs:20:5 | -23 | false != false; +20 | false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:24:5 + --> $DIR/eq_op.rs:21:5 | -24 | 1.5 < 1.5; +21 | 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:25:5 + --> $DIR/eq_op.rs:22:5 | -25 | 1u64 >= 1u64; +22 | 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:28:5 + --> $DIR/eq_op.rs:25:5 | -28 | (1 as u64) & (1 as u64); +25 | (1 as u64) & (1 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:29:5 + --> $DIR/eq_op.rs:26:5 | -29 | 1 ^ ((((((1)))))); +26 | 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:32:5 + --> $DIR/eq_op.rs:29:5 | -32 | (-(2) < -(2)); +29 | (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:33:5 + --> $DIR/eq_op.rs:30:5 | -33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:33:6 + --> $DIR/eq_op.rs:30:6 | -33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:33:27 + --> $DIR/eq_op.rs:30:27 | -33 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:34:5 + --> $DIR/eq_op.rs:31:5 | -34 | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; +31 | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:37:5 + --> $DIR/eq_op.rs:34:5 | -37 | ([1] != [1]); +34 | ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:38:5 + --> $DIR/eq_op.rs:35:5 | -38 | ((1, 2) != (1, 2)); +35 | ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:42:5 + --> $DIR/eq_op.rs:39:5 | -42 | 1 + 1 == 2; +39 | 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:43:5 + --> $DIR/eq_op.rs:40:5 | -43 | 1 - 1 == 0; +40 | 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:43:5 + --> $DIR/eq_op.rs:40:5 | -43 | 1 - 1 == 0; +40 | 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:45:5 + --> $DIR/eq_op.rs:42:5 | -45 | 1 - 1; +42 | 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:43:5 | -46 | 1 / 1; +43 | 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:47:5 + --> $DIR/eq_op.rs:44:5 | -47 | true && true; +44 | true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:49:5 + --> $DIR/eq_op.rs:46:5 | -49 | true || true; +46 | true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:55:5 + --> $DIR/eq_op.rs:52:5 | -55 | a == b && b == a; +52 | a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:56:5 + --> $DIR/eq_op.rs:53:5 | -56 | a != b && b != a; +53 | a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:57:5 + --> $DIR/eq_op.rs:54:5 | -57 | a < b && b > a; +54 | a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:58:5 + --> $DIR/eq_op.rs:55:5 | -58 | a <= b && b >= a; +55 | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:61:5 + --> $DIR/eq_op.rs:58:5 | -61 | a == a; +58 | a == a; | ^^^^^^ error: taken reference of right operand - --> $DIR/eq_op.rs:99:13 + --> $DIR/eq_op.rs:96:13 | -99 | let z = x & &y; +96 | let z = x & &y; | ^^^^-- | | | help: use the right value directly: `y` @@ -205,9 +205,9 @@ error: taken reference of right operand = note: `-D clippy::op-ref` implied by `-D warnings` error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:107:20 + --> $DIR/eq_op.rs:104:20 | -107 | const D: u32 = A / A; +104 | const D: u32 = A / A; | ^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index c4ecd1dcc00..62933f31e18 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,71 +1,71 @@ error: useless use of `format!` - --> $DIR/format.rs:22:5 + --> $DIR/format.rs:21:5 | -22 | format!("foo"); +21 | format!("foo"); | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:24:5 + --> $DIR/format.rs:23:5 | -24 | format!("{}", "foo"); +23 | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:28:5 + --> $DIR/format.rs:27:5 | -28 | format!("{:+}", "foo"); // warn when the format makes no difference +27 | format!("{:+}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:29:5 + --> $DIR/format.rs:28:5 | -29 | format!("{:<}", "foo"); // warn when the format makes no difference +28 | format!("{:<}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:34:5 + --> $DIR/format.rs:33:5 | -34 | format!("{}", arg); +33 | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:38:5 + --> $DIR/format.rs:37:5 | -38 | format!("{:+}", arg); // warn when the format makes no difference +37 | format!("{:+}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:39:5 + --> $DIR/format.rs:38:5 | -39 | format!("{:<}", arg); // warn when the format makes no difference +38 | format!("{:<}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:66:5 + --> $DIR/format.rs:65:5 | -66 | format!("{}", 42.to_string()); +65 | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:68:5 + --> $DIR/format.rs:67:5 | -68 | format!("{}", x.display().to_string()); +67 | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 985070f3754..950c49003b6 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,402 +1,402 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:31:5 + --> $DIR/methods.rs:38:5 | -31 | pub fn add(self, other: T) -> T { self } +38 | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:42:17 + --> $DIR/methods.rs:49:17 | -42 | fn into_u16(&self) -> u16 { 0 } +49 | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:44:21 + --> $DIR/methods.rs:51:21 | -44 | fn to_something(self) -> u32 { 0 } +51 | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:46:12 + --> $DIR/methods.rs:53:12 | -46 | fn new(self) -> Self { unimplemented!(); } +53 | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:114:13 + --> $DIR/methods.rs:121:13 | -114 | let _ = opt.map(|x| x + 1) +121 | let _ = opt.map(|x| x + 1) | _____________^ -115 | | -116 | | .unwrap_or(0); // should lint even though this call is on a separate line +122 | | +123 | | .unwrap_or(0); // should lint even though this call is on a separate line | |____________________________^ | = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:118:13 + --> $DIR/methods.rs:125:13 | -118 | let _ = opt.map(|x| { +125 | let _ = opt.map(|x| { | _____________^ -119 | | x + 1 -120 | | } -121 | | ).unwrap_or(0); +126 | | x + 1 +127 | | } +128 | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:122:13 + --> $DIR/methods.rs:129:13 | -122 | let _ = opt.map(|x| x + 1) +129 | let _ = opt.map(|x| x + 1) | _____________^ -123 | | .unwrap_or({ -124 | | 0 -125 | | }); +130 | | .unwrap_or({ +131 | | 0 +132 | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:127:13 + --> $DIR/methods.rs:134:13 | -127 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); +134 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:129:13 + --> $DIR/methods.rs:136:13 | -129 | let _ = opt.map(|x| { +136 | let _ = opt.map(|x| { | _____________^ -130 | | Some(x + 1) -131 | | } -132 | | ).unwrap_or(None); +137 | | Some(x + 1) +138 | | } +139 | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:133:13 + --> $DIR/methods.rs:140:13 | -133 | let _ = opt +140 | let _ = opt | _____________^ -134 | | .map(|x| Some(x + 1)) -135 | | .unwrap_or(None); +141 | | .map(|x| Some(x + 1)) +142 | | .unwrap_or(None); | |________________________^ | = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:141:13 + --> $DIR/methods.rs:148:13 | -141 | let _ = opt.map(|x| x + 1) +148 | let _ = opt.map(|x| x + 1) | _____________^ -142 | | -143 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line +149 | | +150 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line | |____________________________________^ | = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:145:13 + --> $DIR/methods.rs:152:13 | -145 | let _ = opt.map(|x| { +152 | let _ = opt.map(|x| { | _____________^ -146 | | x + 1 -147 | | } -148 | | ).unwrap_or_else(|| 0); +153 | | x + 1 +154 | | } +155 | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:149:13 + --> $DIR/methods.rs:156:13 | -149 | let _ = opt.map(|x| x + 1) +156 | let _ = opt.map(|x| x + 1) | _____________^ -150 | | .unwrap_or_else(|| -151 | | 0 -152 | | ); +157 | | .unwrap_or_else(|| +158 | | 0 +159 | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:158:13 + --> $DIR/methods.rs:165:13 | -158 | let _ = opt.map_or(None, |x| Some(x + 1)); +165 | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` | = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:160:13 + --> $DIR/methods.rs:167:13 | -160 | let _ = opt.map_or(None, |x| { +167 | let _ = opt.map_or(None, |x| { | _____________^ -161 | | Some(x + 1) -162 | | } -163 | | ); +168 | | Some(x + 1) +169 | | } +170 | | ); | |_________________^ help: try using and_then instead | -160 | let _ = opt.and_then(|x| { -161 | Some(x + 1) -162 | }); +167 | let _ = opt.and_then(|x| { +168 | Some(x + 1) +169 | }); | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:173:13 + --> $DIR/methods.rs:180:13 | -173 | let _ = res.map(|x| x + 1) +180 | let _ = res.map(|x| x + 1) | _____________^ -174 | | -175 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line +181 | | +182 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | |_____________________________________^ | = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:177:13 + --> $DIR/methods.rs:184:13 | -177 | let _ = res.map(|x| { +184 | let _ = res.map(|x| { | _____________^ -178 | | x + 1 -179 | | } -180 | | ).unwrap_or_else(|e| 0); +185 | | x + 1 +186 | | } +187 | | ).unwrap_or_else(|e| 0); | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:181:13 + --> $DIR/methods.rs:188:13 | -181 | let _ = res.map(|x| x + 1) +188 | let _ = res.map(|x| x + 1) | _____________^ -182 | | .unwrap_or_else(|e| -183 | | 0 -184 | | ); +189 | | .unwrap_or_else(|e| +190 | | 0 +191 | | ); | |_________________^ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:244:13 + --> $DIR/methods.rs:251:13 | -244 | let _ = v.iter().filter(|&x| *x < 0).next(); +251 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::filter-next` implied by `-D warnings` = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:247:13 + --> $DIR/methods.rs:254:13 | -247 | let _ = v.iter().filter(|&x| { +254 | let _ = v.iter().filter(|&x| { | _____________^ -248 | | *x < 0 -249 | | } -250 | | ).next(); +255 | | *x < 0 +256 | | } +257 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:262:13 + --> $DIR/methods.rs:269:13 | -262 | let _ = v.iter().find(|&x| *x < 0).is_some(); +269 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:265:13 + --> $DIR/methods.rs:272:13 | -265 | let _ = v.iter().find(|&x| { +272 | let _ = v.iter().find(|&x| { | _____________^ -266 | | *x < 0 -267 | | } -268 | | ).is_some(); +273 | | *x < 0 +274 | | } +275 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:271:13 + --> $DIR/methods.rs:278:13 | -271 | let _ = v.iter().position(|&x| x < 0).is_some(); +278 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:274:13 + --> $DIR/methods.rs:281:13 | -274 | let _ = v.iter().position(|&x| { +281 | let _ = v.iter().position(|&x| { | _____________^ -275 | | x < 0 -276 | | } -277 | | ).is_some(); +282 | | x < 0 +283 | | } +284 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:280:13 + --> $DIR/methods.rs:287:13 | -280 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +287 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:283:13 + --> $DIR/methods.rs:290:13 | -283 | let _ = v.iter().rposition(|&x| { +290 | let _ = v.iter().rposition(|&x| { | _____________^ -284 | | x < 0 -285 | | } -286 | | ).is_some(); +291 | | x < 0 +292 | | } +293 | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:318:22 + --> $DIR/methods.rs:325:22 | -318 | with_constructor.unwrap_or(make()); +325 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` | = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:321:5 + --> $DIR/methods.rs:328:5 | -321 | with_new.unwrap_or(Vec::new()); +328 | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:324:21 + --> $DIR/methods.rs:331:21 | -324 | with_const_args.unwrap_or(Vec::with_capacity(12)); +331 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:327:14 + --> $DIR/methods.rs:334:14 | -327 | with_err.unwrap_or(make()); +334 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:330:19 + --> $DIR/methods.rs:337:19 | -330 | with_err_args.unwrap_or(Vec::with_capacity(12)); +337 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:333:5 + --> $DIR/methods.rs:340:5 | -333 | with_default_trait.unwrap_or(Default::default()); +340 | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:336:5 + --> $DIR/methods.rs:343:5 | -336 | with_default_type.unwrap_or(u64::default()); +343 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:339:14 + --> $DIR/methods.rs:346:14 | -339 | with_vec.unwrap_or(vec![]); +346 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:344:21 + --> $DIR/methods.rs:351:21 | -344 | without_default.unwrap_or(Foo::new()); +351 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:347:19 + --> $DIR/methods.rs:354:19 | -347 | map.entry(42).or_insert(String::new()); +354 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:350:21 + --> $DIR/methods.rs:357:21 | -350 | btree.entry(42).or_insert(String::new()); +357 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:353:21 + --> $DIR/methods.rs:360:21 | -353 | let _ = stringy.unwrap_or("".to_owned()); +360 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:364:23 + --> $DIR/methods.rs:371:23 | -364 | let bad_vec = some_vec.iter().nth(3); +371 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:365:26 + --> $DIR/methods.rs:372:26 | -365 | let bad_slice = &some_vec[..].iter().nth(3); +372 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:366:31 + --> $DIR/methods.rs:373:31 | -366 | let bad_boxed_slice = boxed_slice.iter().nth(3); +373 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:367:29 + --> $DIR/methods.rs:374:29 | -367 | let bad_vec_deque = some_vec_deque.iter().nth(3); +374 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:372:23 + --> $DIR/methods.rs:379:23 | -372 | let bad_vec = some_vec.iter_mut().nth(3); +379 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:375:26 + --> $DIR/methods.rs:382:26 | -375 | let bad_slice = &some_vec[..].iter_mut().nth(3); +382 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:378:29 + --> $DIR/methods.rs:385:29 | -378 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +385 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:390:13 + --> $DIR/methods.rs:397:13 | -390 | let _ = some_vec.iter().skip(42).next(); +397 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:391:13 + --> $DIR/methods.rs:398:13 | -391 | let _ = some_vec.iter().cycle().skip(42).next(); +398 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:392:13 + --> $DIR/methods.rs:399:13 | -392 | let _ = (1..10).skip(10).next(); +399 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:393:14 + --> $DIR/methods.rs:400:14 | -393 | let _ = &some_vec[..].iter().skip(3).next(); +400 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:402:13 + --> $DIR/methods.rs:409:13 | -402 | let _ = opt.unwrap(); +409 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 02100b4194d..5b8451e046c 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,217 +1,217 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:23:17 | -24 | { let foo = ATOMIC_BOOL_INIT; }; +23 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:15:9 + --> $DIR/replace_consts.rs:13:9 | -15 | #![deny(clippy::replace_consts)] +13 | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:24:17 | -25 | { let foo = ATOMIC_ISIZE_INIT; }; +24 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:25:17 | -26 | { let foo = ATOMIC_I8_INIT; }; +25 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:26:17 | -27 | { let foo = ATOMIC_I16_INIT; }; +26 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:27:17 | -28 | { let foo = ATOMIC_I32_INIT; }; +27 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:28:17 | -29 | { let foo = ATOMIC_I64_INIT; }; +28 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:29:17 | -30 | { let foo = ATOMIC_USIZE_INIT; }; +29 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:30:17 | -31 | { let foo = ATOMIC_U8_INIT; }; +30 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:31:17 | -32 | { let foo = ATOMIC_U16_INIT; }; +31 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:32:17 | -33 | { let foo = ATOMIC_U32_INIT; }; +32 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:33:17 | -34 | { let foo = ATOMIC_U64_INIT; }; +33 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:35:17 | -36 | { let foo = std::isize::MIN; }; +35 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:36:17 | -37 | { let foo = std::i8::MIN; }; +36 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:37:17 | -38 | { let foo = std::i16::MIN; }; +37 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:38:17 | -39 | { let foo = std::i32::MIN; }; +38 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:39:17 | -40 | { let foo = std::i64::MIN; }; +39 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:40:17 | -41 | { let foo = std::i128::MIN; }; +40 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:41:17 | -42 | { let foo = std::usize::MIN; }; +41 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:42:17 | -43 | { let foo = std::u8::MIN; }; +42 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:43:17 | -44 | { let foo = std::u16::MIN; }; +43 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:44:17 | -45 | { let foo = std::u32::MIN; }; +44 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:45:17 | -46 | { let foo = std::u64::MIN; }; +45 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:46:17 | -47 | { let foo = std::u128::MIN; }; +46 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:48:17 | -49 | { let foo = std::isize::MAX; }; +48 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:49:17 | -50 | { let foo = std::i8::MAX; }; +49 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:51:17 + --> $DIR/replace_consts.rs:50:17 | -51 | { let foo = std::i16::MAX; }; +50 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:52:17 + --> $DIR/replace_consts.rs:51:17 | -52 | { let foo = std::i32::MAX; }; +51 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:53:17 + --> $DIR/replace_consts.rs:52:17 | -53 | { let foo = std::i64::MAX; }; +52 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:54:17 + --> $DIR/replace_consts.rs:53:17 | -54 | { let foo = std::i128::MAX; }; +53 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:55:17 + --> $DIR/replace_consts.rs:54:17 | -55 | { let foo = std::usize::MAX; }; +54 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:56:17 + --> $DIR/replace_consts.rs:55:17 | -56 | { let foo = std::u8::MAX; }; +55 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:57:17 + --> $DIR/replace_consts.rs:56:17 | -57 | { let foo = std::u16::MAX; }; +56 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:58:17 + --> $DIR/replace_consts.rs:57:17 | -58 | { let foo = std::u32::MAX; }; +57 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:59:17 + --> $DIR/replace_consts.rs:58:17 | -59 | { let foo = std::u64::MAX; }; +58 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:60:17 + --> $DIR/replace_consts.rs:59:17 | -60 | { let foo = std::u128::MAX; }; +59 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index 92d0095c0b5..aac092b9f7f 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -1,51 +1,51 @@ error: unneeded unit return type - --> $DIR/unused_unit.rs:27:59 + --> $DIR/unused_unit.rs:25:59 | -27 | pub fn get_unit (), G>(&self, f: F, _g: G) -> +25 | pub fn get_unit (), G>(&self, f: F, _g: G) -> | ___________________________________________________________^ -28 | | () +26 | | () | |__________^ help: remove the `-> ()` | note: lint level defined here - --> $DIR/unused_unit.rs:20:9 + --> $DIR/unused_unit.rs:19:9 | -20 | #![deny(clippy::unused_unit)] +19 | #![deny(clippy::unused_unit)] | ^^^^^^^^^^^^^^^^^^^ error: unneeded unit return type - --> $DIR/unused_unit.rs:36:19 + --> $DIR/unused_unit.rs:35:19 | -36 | fn into(self) -> () { +35 | fn into(self) -> () { | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:37:9 + --> $DIR/unused_unit.rs:36:9 | -37 | () +36 | () | ^^ help: remove the final `()` error: unneeded unit return type - --> $DIR/unused_unit.rs:41:18 + --> $DIR/unused_unit.rs:40:18 | -41 | fn return_unit() -> () { () } +40 | fn return_unit() -> () { () } | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:41:26 + --> $DIR/unused_unit.rs:40:26 | -41 | fn return_unit() -> () { () } +40 | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` - --> $DIR/unused_unit.rs:48:14 + --> $DIR/unused_unit.rs:47:14 | -48 | break(); +47 | break(); | ^^ help: remove the `()` error: unneeded `()` - --> $DIR/unused_unit.rs:50:11 + --> $DIR/unused_unit.rs:49:11 | -50 | return(); +49 | return(); | ^^ help: remove the `()` error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 1218145bc9490ca156cc7a26e922c86c2afe67f0 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Dec 2018 22:06:29 +0100 Subject: base tests: assert that tests are properly formatted. --- ci/base-tests.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 2537f157ad9..6eeab6671cb 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -27,3 +27,16 @@ cd clippy_dev && cargo test && cd .. # Perform various checks for lint registration ./util/dev update_lints --check cargo +nightly fmt --all -- --check + +# make sure tests are formatted + +# some lints are sensitive to formatting, exclude some files +needs_formatting=false +for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do +rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true +done + +if $needs_reformatting + "Tests need reformatting!" + exit 2 +fi -- cgit 1.4.1-3-g733a5 From 31d3bd92be7fd073beaece348193a78d4964b3e2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Dec 2018 22:47:22 +0100 Subject: travis: base-tests: share CARGO_TARGET_DIR between check runs of subcrates to avoid unneccessarily recompiling deps. --- ci/base-tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 2537f157ad9..da87134f59f 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -20,6 +20,8 @@ fi # build clippy in debug mode and run tests cargo build --features debugging cargo test --features debugging +# for faster build, share target dir between subcrates +export CARGO_TARGET_DIR=`pwd`/target/ cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. cd clippy_dev && cargo test && cd .. -- cgit 1.4.1-3-g733a5 From 435299be3062c67dc3c61b36c5e30bbfa876ee1e Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 9 Dec 2018 23:26:16 +0100 Subject: rustfmt tests --- tests/auxiliary/test_macro.rs | 1 - tests/run-pass/associated-constant-ice.rs | 1 - tests/run-pass/cc_seme.rs | 8 +- tests/run-pass/enum-glob-import-crate.rs | 5 +- tests/run-pass/ice-1588.rs | 9 +- tests/run-pass/ice-1782.rs | 16 +- tests/run-pass/ice-1969.rs | 5 +- tests/run-pass/ice-2499.rs | 17 +- tests/run-pass/ice-2594.rs | 3 +- tests/run-pass/ice-2727.rs | 1 - tests/run-pass/ice-2760.rs | 11 +- tests/run-pass/ice-2774.rs | 11 +- tests/run-pass/ice-2865.rs | 3 +- tests/run-pass/ice-3151.rs | 5 +- tests/run-pass/ice-700.rs | 3 - tests/run-pass/ice_exacte_size.rs | 3 - tests/run-pass/if_same_then_else.rs | 3 - tests/run-pass/issue-2862.rs | 1 - tests/run-pass/issue-825.rs | 17 +- tests/run-pass/issues_loop_mut_cond.rs | 1 - tests/run-pass/match_same_arms_const.rs | 5 +- tests/run-pass/mut_mut_macro.rs | 3 - tests/run-pass/needless_borrow_fp.rs | 8 +- tests/run-pass/needless_lifetimes_impl_trait.rs | 3 - tests/run-pass/procedural_macro.rs | 4 +- tests/run-pass/regressions.rs | 3 - tests/run-pass/returns.rs | 7 +- tests/run-pass/single-match-else.rs | 3 - tests/run-pass/used_underscore_binding_macro.rs | 3 - tests/run-pass/whitelist/conf_whitelisted.rs | 1 - tests/ui-toml/bad_toml/conf_bad_toml.rs | 4 - tests/ui-toml/bad_toml_type/conf_bad_type.rs | 7 +- .../toml_blacklist/conf_french_blacklisted_name.rs | 4 - tests/ui-toml/toml_trivially_copy/test.rs | 8 +- tests/ui-toml/toml_unknown_key/conf_unknown_key.rs | 4 - tests/ui/absurd-extreme-comparisons.rs | 8 +- tests/ui/approx_const.rs | 4 - tests/ui/arithmetic.rs | 9 +- tests/ui/assign_ops.rs | 3 - tests/ui/assign_ops2.rs | 6 - tests/ui/attrs.rs | 23 +-- tests/ui/author.rs | 4 - tests/ui/author/call.rs | 3 - tests/ui/author/for_loop.rs | 1 - tests/ui/author/matches.rs | 1 - tests/ui/bit_masks.rs | 15 +- tests/ui/blacklisted_name.rs | 13 +- tests/ui/block_in_if_condition.rs | 49 +++--- tests/ui/bool_comparison.rs | 52 ++++-- tests/ui/booleans.rs | 55 ++++--- tests/ui/borrow_box.rs | 12 +- tests/ui/box_vec.rs | 11 +- tests/ui/builtin-type-shadow.rs | 6 +- tests/ui/bytecount.rs | 4 - tests/ui/cast.rs | 14 +- tests/ui/cast_alignment.rs | 3 - tests/ui/cast_lossless_float.rs | 3 - tests/ui/cast_lossless_integer.rs | 2 - tests/ui/cast_size.rs | 11 +- tests/ui/char_lit_as_u8.rs | 4 - tests/ui/checked_unwrap.rs | 7 +- tests/ui/clone_on_copy_impl.rs | 3 +- tests/ui/clone_on_copy_mut.rs | 3 - tests/ui/cmp_nan.rs | 4 - tests/ui/cmp_null.rs | 7 +- tests/ui/cmp_owned.rs | 6 +- tests/ui/collapsible_if.rs | 1 - tests/ui/complex_types.rs | 16 +- tests/ui/const_static_lifetime.rs | 1 - tests/ui/copies.rs | 181 ++++++++++----------- tests/ui/copy_iterator.rs | 3 - tests/ui/cstring.rs | 3 - tests/ui/cyclomatic_complexity.rs | 15 +- tests/ui/cyclomatic_complexity_attr_used.rs | 3 - tests/ui/decimal_literal_representation.rs | 26 ++- tests/ui/default_trait_access.rs | 5 +- tests/ui/deprecated.rs | 8 - tests/ui/derive.rs | 40 +++-- tests/ui/diverging_sub_expression.rs | 12 +- tests/ui/dlist.rs | 11 +- tests/ui/double_comparison.rs | 1 - tests/ui/double_neg.rs | 4 - tests/ui/drop_forget_copy.rs | 23 +-- tests/ui/drop_forget_ref.rs | 4 - tests/ui/duplicate_underscore_argument.rs | 4 - tests/ui/duration_subsec.rs | 3 - tests/ui/else_if_without_else.rs | 21 ++- tests/ui/empty_enum.rs | 7 +- tests/ui/entry.rs | 53 ++++-- tests/ui/enum_glob_use.rs | 6 +- tests/ui/enum_variants.rs | 16 +- tests/ui/enums_clike.rs | 8 +- tests/ui/erasing_op.rs | 4 - tests/ui/escape_analysis.rs | 24 ++- tests/ui/eta.rs | 31 ++-- tests/ui/eval_order_dependence.rs | 98 ++++++++--- tests/ui/excessive_precision.rs | 2 - tests/ui/expect_fun_call.rs | 4 +- tests/ui/explicit_counter_loop.rs | 6 +- tests/ui/explicit_write.rs | 4 - tests/ui/fallible_impl_from.rs | 5 - tests/ui/filter_methods.rs | 42 +++-- tests/ui/float_cmp.rs | 34 ++-- tests/ui/float_cmp_const.rs | 10 +- tests/ui/fn_to_numeric_cast.rs | 6 +- tests/ui/for_loop.rs | 18 +- tests/ui/formatting.rs | 97 +++++------ tests/ui/functions.rs | 19 ++- tests/ui/fxhash.rs | 5 +- tests/ui/get_unwrap.rs | 18 +- tests/ui/ice-2636.rs | 1 - tests/ui/identity_conversion.rs | 3 - tests/ui/identity_op.rs | 31 ++-- tests/ui/if_not_else.rs | 7 +- tests/ui/impl.rs | 3 - tests/ui/implicit_hasher.rs | 19 +-- tests/ui/implicit_return.rs | 12 +- tests/ui/inconsistent_digit_grouping.rs | 13 +- tests/ui/indexing_slicing.rs | 3 - tests/ui/infallible_destructuring_match.rs | 3 - tests/ui/infinite_iter.rs | 27 ++- tests/ui/infinite_loop.rs | 31 ++-- tests/ui/inline_fn_without_body.rs | 13 +- tests/ui/int_plus_one.rs | 4 - tests/ui/into_iter_on_ref.rs | 18 +- tests/ui/invalid_ref.rs | 28 ++-- tests/ui/invalid_upcast_comparisons.rs | 19 ++- tests/ui/issue-3145.rs | 1 - tests/ui/issue_2356.rs | 3 - tests/ui/item_after_statement.rs | 19 ++- tests/ui/large_digit_groups.rs | 23 ++- tests/ui/large_enum_variant.rs | 4 - tests/ui/len_zero.rs | 3 - tests/ui/let_if_seq.rs | 22 ++- tests/ui/let_return.rs | 7 +- tests/ui/let_unit.rs | 10 +- tests/ui/lifetimes.rs | 171 +++++++++++++------ tests/ui/lint_without_lint_pass.rs | 4 +- tests/ui/map_clone.rs | 2 - tests/ui/map_flatten.rs | 2 - tests/ui/match_bool.rs | 28 ++-- tests/ui/match_overlapping_arm.rs | 30 ++-- tests/ui/matches.rs | 51 +++--- tests/ui/mem_discriminant.rs | 5 +- tests/ui/mem_forget.rs | 9 +- tests/ui/mem_replace.rs | 2 - tests/ui/min_max.rs | 10 +- tests/ui/missing-doc.rs | 36 ++-- tests/ui/missing_inline.rs | 15 +- tests/ui/module_inception.rs | 6 +- tests/ui/modulo_one.rs | 3 - tests/ui/mut_from_ref.rs | 3 - tests/ui/mut_mut.rs | 21 +-- tests/ui/mut_range_bound.rs | 30 ++-- tests/ui/mut_reference.rs | 11 +- tests/ui/mutex_atomic.rs | 4 - tests/ui/needless_bool.rs | 84 +++++++--- tests/ui/needless_borrow.rs | 5 +- tests/ui/needless_borrowed_ref.rs | 8 +- tests/ui/needless_collect.rs | 5 +- tests/ui/needless_continue.rs | 16 +- tests/ui/needless_pass_by_value.rs | 28 ++-- tests/ui/needless_pass_by_value_proc_macro.rs | 7 +- tests/ui/needless_range_loop.rs | 7 +- tests/ui/needless_return.rs | 8 +- tests/ui/needless_update.rs | 4 - tests/ui/neg_cmp_op_on_partial_ord.rs | 11 +- tests/ui/neg_multiply.rs | 4 - tests/ui/never_loop.rs | 70 ++++---- tests/ui/new_ret_no_self.rs | 50 ++++-- tests/ui/new_without_default.rs | 61 ++++--- tests/ui/no_effect.rs | 25 +-- tests/ui/non_copy_const.rs | 15 +- tests/ui/non_expressive_names.rs | 26 ++- tests/ui/ok_expect.rs | 5 +- tests/ui/ok_if_let.rs | 4 - tests/ui/op_ref.rs | 4 - tests/ui/open_options.rs | 3 - tests/ui/option_map_unit_fn.rs | 79 +++++---- tests/ui/option_option.rs | 8 +- tests/ui/overflow_check_conditional.rs | 78 +++------ tests/ui/panic_unimplemented.rs | 6 +- tests/ui/partialeq_ne_impl.rs | 12 +- tests/ui/patterns.rs | 9 +- tests/ui/precedence.rs | 16 +- tests/ui/print.rs | 3 - tests/ui/print_literal.rs | 17 +- tests/ui/print_with_newline.rs | 3 - tests/ui/println_empty_string.rs | 1 - tests/ui/ptr_arg.rs | 27 ++- tests/ui/ptr_offset_with_cast.rs | 1 - tests/ui/question_mark.rs | 33 ++-- tests/ui/range.rs | 9 +- tests/ui/range_plus_minus_one.rs | 37 ++--- tests/ui/redundant_clone.rs | 5 +- tests/ui/redundant_closure_call.rs | 22 +-- tests/ui/redundant_field_names.rs | 9 +- tests/ui/redundant_pattern_matching.rs | 28 +--- tests/ui/reference.rs | 10 +- tests/ui/regex.rs | 23 +-- tests/ui/replace_consts.rs | 3 +- tests/ui/result_map_unit_fn.rs | 80 +++++---- tests/ui/serde.rs | 15 +- tests/ui/shadow.rs | 24 ++- tests/ui/short_circuit_statement.rs | 4 - tests/ui/single_char_pattern.rs | 3 - tests/ui/single_match.rs | 37 +++-- tests/ui/single_match_else.rs | 5 +- tests/ui/slow_vector_initialization.rs | 6 +- tests/ui/starts_ends_with.rs | 21 ++- tests/ui/string_extend.rs | 1 - tests/ui/strings.rs | 3 - tests/ui/stutter.rs | 3 - tests/ui/suspicious_arithmetic_impl.rs | 6 +- tests/ui/swap.rs | 8 +- tests/ui/temporary_assignment.rs | 16 +- tests/ui/toplevel_ref_arg.rs | 28 ++-- tests/ui/trailing_zeros.rs | 5 +- tests/ui/transmute.rs | 16 +- tests/ui/transmute_32bit.rs | 3 - tests/ui/transmute_64bit.rs | 5 - tests/ui/trivially_copy_pass_by_ref.rs | 46 +++--- tests/ui/ty_fn_sig.rs | 1 - tests/ui/types.rs | 9 +- tests/ui/unicode.rs | 4 - tests/ui/unit_arg.rs | 11 +- tests/ui/unit_cmp.rs | 23 +-- tests/ui/unknown_clippy_lints.rs | 4 +- tests/ui/unnecessary_clone.rs | 23 +-- tests/ui/unnecessary_filter_map.rs | 8 +- tests/ui/unnecessary_fold.rs | 1 - tests/ui/unnecessary_operation.rs | 24 ++- tests/ui/unnecessary_ref.rs | 3 - tests/ui/unneeded_field_pattern.rs | 13 +- tests/ui/unreadable_literal.rs | 15 +- tests/ui/unsafe_removed_from_name.rs | 13 +- tests/ui/unused_io_amount.rs | 7 +- tests/ui/unused_labels.rs | 13 +- tests/ui/unused_lt.rs | 49 +++--- tests/ui/unwrap_or.rs | 6 +- tests/ui/use_self.rs | 29 ++-- tests/ui/used_underscore_binding.rs | 8 +- tests/ui/useless_asref.rs | 37 +++-- tests/ui/useless_attribute.rs | 11 +- tests/ui/vec.rs | 8 +- tests/ui/while_loop.rs | 65 ++++---- tests/ui/write_literal.rs | 17 +- tests/ui/write_with_newline.rs | 3 - tests/ui/writeln_empty_string.rs | 4 - tests/ui/wrong_self_convention.rs | 10 +- tests/ui/zero_div_zero.rs | 10 +- tests/ui/zero_ptr.rs | 4 - 252 files changed, 1882 insertions(+), 1984 deletions(-) diff --git a/tests/auxiliary/test_macro.rs b/tests/auxiliary/test_macro.rs index 497fedff15e..d5fef588971 100644 --- a/tests/auxiliary/test_macro.rs +++ b/tests/auxiliary/test_macro.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - pub trait A {} macro_rules! __implicit_hasher_test_macro { diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs index bc9a0b3b6d5..df84009c889 100644 --- a/tests/run-pass/associated-constant-ice.rs +++ b/tests/run-pass/associated-constant-ice.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - pub trait Trait { const CONSTANT: u8; } diff --git a/tests/run-pass/cc_seme.rs b/tests/run-pass/cc_seme.rs index 215b4096b56..7e1f13d4460 100644 --- a/tests/run-pass/cc_seme.rs +++ b/tests/run-pass/cc_seme.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[allow(dead_code)] enum Baz { One, @@ -19,7 +18,7 @@ struct Test { b: Baz, } -fn main() { } +fn main() {} pub fn foo() { use Baz::*; @@ -27,10 +26,7 @@ pub fn foo() { match x { Test { t: Some(_), b: One } => unreachable!(), - Test { - t: Some(42), - b: Two, - } => unreachable!(), + Test { t: Some(42), b: Two } => unreachable!(), Test { t: None, .. } => unreachable!(), Test { .. } => unreachable!(), } diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index df8b32cde2b..6e64f174e4c 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -7,12 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::all)] #![allow(unused_imports)] use std::*; -fn main() { } +fn main() {} diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index a54c77cce73..87f2afaa602 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -7,17 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::all)] fn main() { match 1 { - 1 => {} + 1 => {}, 2 => { [0; 1]; - } - _ => {} + }, + _ => {}, } } diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs index 446aaacb2ee..ddb4367c914 100644 --- a/tests/run-pass/ice-1782.rs +++ b/tests/run-pass/ice-1782.rs @@ -7,20 +7,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` /// /// Issue: https://github.com/rust-lang/rust-clippy/issues/1782 - use std::{mem, ptr}; fn spanless_eq_ice() { let txt = "something"; match txt { - "something" => unsafe { ptr::write(ptr::null_mut() as *mut u32, mem::transmute::<[u8; 4], _>([0, 0, 0, 255])) }, - _ => unsafe { ptr::write(ptr::null_mut() as *mut u32, mem::transmute::<[u8; 4], _>([13, 246, 24, 255])) }, + "something" => unsafe { + ptr::write( + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ) + }, + _ => unsafe { + ptr::write( + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([13, 246, 24, 255]), + ) + }, } } diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 848d9743dcd..2a0cdb19fce 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -7,12 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::all)] -fn main() { } +fn main() {} pub trait Convert { type Action: From<*const f64>; diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index 30e8fa657f2..804f416800c 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` @@ -20,15 +17,17 @@ fn f(s: &[u8]) -> bool { let t = s[0] as char; match t { - 'E' | 'W' => {} - 'T' => if s[0..4] != ['0' as u8; 4] { - return false; - } else { - return true; + 'E' | 'W' => {}, + 'T' => { + if s[0..4] != ['0' as u8; 4] { + return false; + } else { + return true; + } }, _ => { return false; - } + }, } true } diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs index 738636b5e40..e91b71b3a1c 100644 --- a/tests/run-pass/ice-2594.rs +++ b/tests/run-pass/ice-2594.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` @@ -21,7 +20,7 @@ fn spanless_hash_ice() { match txt { "something" => { let mut headers = [empty_header; 1]; - } + }, "" => (), _ => (), } diff --git a/tests/run-pass/ice-2727.rs b/tests/run-pass/ice-2727.rs index 420be4c7112..9d00f2bacd0 100644 --- a/tests/run-pass/ice-2727.rs +++ b/tests/run-pass/ice-2727.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - pub fn f(new: fn()) { new(); } diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index fe7138b7f28..533cc3b952a 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -7,11 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![allow(unused_variables, clippy::blacklisted_name, - clippy::needless_pass_by_value, dead_code)] +#![allow( + unused_variables, + clippy::blacklisted_name, + clippy::needless_pass_by_value, + dead_code +)] // This should not compile-fail with: // diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index 9959ec46d24..ae51f036207 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - use std::collections::HashSet; // See https://github.com/rust-lang/rust-clippy/issues/2774 @@ -26,18 +23,14 @@ pub struct Foo {} // This should not cause a 'cannot relate bound region' ICE pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { let mut foos = HashSet::new(); - foos.extend( - bars.iter().map(|b| &b.foo) - ); + foos.extend(bars.iter().map(|b| &b.foo)); } #[allow(clippy::implicit_hasher)] // Also this should not cause a 'cannot relate bound region' ICE pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { let mut foos = HashSet::new(); - foos.extend( - bars.iter().map(|b| &b.foo) - ); + foos.extend(bars.iter().map(|b| &b.foo)); } fn main() {} diff --git a/tests/run-pass/ice-2865.rs b/tests/run-pass/ice-2865.rs index 1713915745a..970ac5bd3a8 100644 --- a/tests/run-pass/ice-2865.rs +++ b/tests/run-pass/ice-2865.rs @@ -7,10 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[allow(dead_code)] struct Ice { - size: String + size: String, } impl<'a> From for Ice { diff --git a/tests/run-pass/ice-3151.rs b/tests/run-pass/ice-3151.rs index 8e1b7b9a178..7a26f4c3925 100644 --- a/tests/run-pass/ice-3151.rs +++ b/tests/run-pass/ice-3151.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[derive(Clone)] pub struct HashMap { hash_builder: S, @@ -17,7 +16,7 @@ pub struct HashMap { #[derive(Clone)] pub struct RawTable { size: usize, - val: V + val: V, } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index cb6ba21e72b..b839ac2a214 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::all)] fn core() {} diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index 74eda792e75..b2b331bd342 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::all)] #[allow(dead_code)] diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs index cc95262fe3c..0241d2adcf7 100644 --- a/tests/run-pass/if_same_then_else.rs +++ b/tests/run-pass/if_same_then_else.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::if_same_then_else)] fn main() {} diff --git a/tests/run-pass/issue-2862.rs b/tests/run-pass/issue-2862.rs index 298ce088cea..a5342492045 100644 --- a/tests/run-pass/issue-2862.rs +++ b/tests/run-pass/issue-2862.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - pub trait FooMap { fn map B>(&self, f: F) -> B; } diff --git a/tests/run-pass/issue-825.rs b/tests/run-pass/issue-825.rs index 576d53757cf..9f1195a4ac0 100644 --- a/tests/run-pass/issue-825.rs +++ b/tests/run-pass/issue-825.rs @@ -7,14 +7,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(warnings)] // this should compile in a reasonable amount of time fn rust_type_id(name: &str) { - if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] - || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] - || "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + if "bool" == &name[..] + || "uint" == &name[..] + || "u8" == &name[..] + || "u16" == &name[..] + || "u32" == &name[..] + || "f32" == &name[..] + || "f64" == &name[..] + || "i8" == &name[..] + || "i16" == &name[..] + || "i32" == &name[..] + || "i64" == &name[..] + || "Self" == &name[..] + || "str" == &name[..] { unreachable!(); } diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs index 893866a2a34..a81f8f55dc8 100644 --- a/tests/run-pass/issues_loop_mut_cond.rs +++ b/tests/run-pass/issues_loop_mut_cond.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(dead_code)] /// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs index bd180e9cad9..661f2ac1dc7 100644 --- a/tests/run-pass/match_same_arms_const.rs +++ b/tests/run-pass/match_same_arms_const.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::match_same_arms)] const PRICE_OF_SWEETS: u32 = 5; @@ -21,7 +18,7 @@ pub fn price(thing: &str) -> u32 { "rolo" => PRICE_OF_SWEETS, "advice" => PRICE_OF_KINDNESS, "juice" => PRICE_OF_DRINKS, - _ => panic!() + _ => panic!(), } } diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index 8859009479c..f1a2cad3ae7 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] #![allow(dead_code)] diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs index ad4b04864e4..81b77855711 100644 --- a/tests/run-pass/needless_borrow_fp.rs +++ b/tests/run-pass/needless_borrow_fp.rs @@ -7,16 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[deny(clippy::all)] - #[derive(Debug)] pub enum Error { - Type( - &'static str, - ), + Type(&'static str), } fn main() {} diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 0514d7ab008..9648f530c2a 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index a9c9dd06b42..9ac47599ea0 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[macro_use] extern crate clippy_mini_macro_test; @@ -17,6 +16,5 @@ fn main() { println!("{:?}", x); } - #[derive(ClippyMiniMacroTest, Debug)] -struct Foo; \ No newline at end of file +struct Foo; diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index 9be3bab185c..b109eecf624 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::blacklisted_name)] pub fn foo(bar: *const u8) { diff --git a/tests/run-pass/returns.rs b/tests/run-pass/returns.rs index cc7678d603b..045cf001eb2 100644 --- a/tests/run-pass/returns.rs +++ b/tests/run-pass/returns.rs @@ -7,11 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[deny(warnings)] fn cfg_return() -> i32 { - #[cfg(unix)] return 1; - #[cfg(not(unix))] return 2; + #[cfg(unix)] + return 1; + #[cfg(not(unix))] + return 2; } #[deny(warnings)] diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index cf032c65703..80fc88f30df 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::single_match_else)] fn main() { diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index 68bd6922062..8b6c6557b49 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::useless_attribute)] //issue #2910 #[macro_use] diff --git a/tests/run-pass/whitelist/conf_whitelisted.rs b/tests/run-pass/whitelist/conf_whitelisted.rs index 168f09a095a..e7f5ddb561f 100644 --- a/tests/run-pass/whitelist/conf_whitelisted.rs +++ b/tests/run-pass/whitelist/conf_whitelisted.rs @@ -7,5 +7,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs index 10c0f0004e4..31781277ae8 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.rs +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern: error reading Clippy's configuration file - - - fn main() {} diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs index 021a839d9ef..2307bfff21c 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.rs +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -7,10 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a `Vec < String >` but is a `integer` - - - +// error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a +// `Vec < String >` but is a `integer` fn main() {} diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs index ad81b82b2c5..b00a21b3f2f 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] #![allow(clippy::single_match)] #![allow(unused_variables)] diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index eb09d6dfc5c..39de0de0dc7 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![allow(clippy::many_single_char_names)] #[derive(Copy, Clone)] @@ -17,11 +15,9 @@ struct Foo(u8); #[derive(Copy, Clone)] struct Bar(u32); -fn good(a: &mut u32, b: u32, c: &Bar, d: &u32) { -} +fn good(a: &mut u32, b: u32, c: &Bar, d: &u32) {} -fn bad(x: &u16, y: &Foo) { -} +fn bad(x: &u16, y: &Foo) {} fn main() { let (mut a, b, c, d, x, y) = (0, 0, Bar(0), 0, 0, Foo(0)); diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index 60e8e4fc29a..c8e6268e95d 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // error-pattern: error reading Clippy's configuration file: unknown key `foobar` - - - fn main() {} diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index a93027162e5..666c4325706 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -8,7 +8,13 @@ // except according to those terms. #![warn(clippy::absurd_extreme_comparisons)] -#![allow(unused, clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::needless_pass_by_value)] +#![allow( + unused, + clippy::eq_op, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::needless_pass_by_value +)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index b2f50cc2ce3..8eefb6af01d 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::approx_constant)] #[allow(unused, clippy::shadow_unrelated, clippy::similar_names, clippy::unreadable_literal)] fn main() { diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 39aef5a4a56..00de38039a7 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -7,9 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] -#![allow(unused, clippy::shadow_reuse, clippy::shadow_unrelated, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + unused, + clippy::shadow_reuse, + clippy::shadow_unrelated, + clippy::no_effect, + clippy::unnecessary_operation +)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 419e63b2c62..75cd7543823 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[allow(dead_code, unused_assignments)] #[warn(clippy::assign_op_pattern)] fn main() { diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 4f9fbc80aaa..24d0d77a20d 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[allow(unused_assignments)] #[warn(clippy::misrefactored_assign_op, clippy::assign_op_pattern)] fn main() { @@ -65,6 +61,4 @@ fn cow_add_assign() { // this should not as cow Add is not commutative buf = cows + buf; println!("{}", buf); - } - diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 1d0c23905bd..413c30a1945 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::inline_always, clippy::deprecated_semver)] #[inline(always)] @@ -30,22 +26,27 @@ fn false_positive_stmt() { #[inline(always)] fn empty_and_false_positive_stmt() { - ; unreachable!(); } #[deprecated(since = "forever")] -pub const SOME_CONST : u8 = 42; +pub const SOME_CONST: u8 = 42; #[deprecated(since = "1")] -pub const ANOTHER_CONST : u8 = 23; +pub const ANOTHER_CONST: u8 = 23; #[deprecated(since = "0.1.1")] -pub const YET_ANOTHER_CONST : u8 = 0; +pub const YET_ANOTHER_CONST: u8 = 0; fn main() { test_attr_lint(); - if false { false_positive_expr() } - if false { false_positive_stmt() } - if false { empty_and_false_positive_stmt() } + if false { + false_positive_expr() + } + if false { + false_positive_stmt() + } + if false { + empty_and_false_positive_stmt() + } } diff --git a/tests/ui/author.rs b/tests/ui/author.rs index f151d50f2f2..4b7729e23b1 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - fn main() { - #[clippy::author] let x: char = 0x45 as char; } diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs index 3dcf8da5c72..40cc0d7a919 100644 --- a/tests/ui/author/call.rs +++ b/tests/ui/author/call.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - fn main() { #[clippy::author] let _ = ::std::cmp::min(3, 4); diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index a27322b3205..4acd0b452bb 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(stmt_expr_attributes)] fn main() { diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs index 956404f3490..4c220dded8a 100644 --- a/tests/ui/author/matches.rs +++ b/tests/ui/author/matches.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(tool_attributes)] fn main() { diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index db5a6885c9e..bda952db723 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -7,15 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -const THREE_BITS : i64 = 7; -const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; +const THREE_BITS: i64 = 7; +const EVEN_MORE_REDIRECTION: i64 = THREE_BITS; #[warn(clippy::bad_bit_mask)] -#[allow(clippy::ineffective_bit_mask, clippy::identity_op, clippy::no_effect, clippy::unnecessary_operation)] +#[allow( + clippy::ineffective_bit_mask, + clippy::identity_op, + clippy::no_effect, + clippy::unnecessary_operation +)] fn main() { let x = 5; diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index 285438810d9..fef73e9d84f 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -7,11 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -#![allow(dead_code, clippy::similar_names, clippy::single_match, clippy::toplevel_ref_arg, unused_mut, unused_variables)] +#![allow( + dead_code, + clippy::similar_names, + clippy::single_match, + clippy::toplevel_ref_arg, + unused_mut, + unused_variables +)] #![warn(clippy::blacklisted_name)] fn test(foo: ()) {} diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index 94611811841..eaaf5e050bf 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -7,33 +7,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] - macro_rules! blocky { - () => {{true}} + () => {{ + true + }}; } macro_rules! blocky_too { () => {{ let r = true; r - }} + }}; } fn macro_if() { - if blocky!() { - } + if blocky!() {} - if blocky_too!() { - } + if blocky_too!() {} } fn condition_has_block() -> i32 { @@ -55,7 +50,7 @@ fn condition_has_block_with_single_expression() -> i32 { } } -fn predicate bool, T>(pfn: F, val:T) -> bool { +fn predicate bool, T>(pfn: F, val: T) -> bool { pfn(val) } @@ -65,11 +60,24 @@ fn pred_test() { // this is a sneaky case, where the block isn't directly in the condition, but is actually // inside a closure that the condition is using. same principle applies. add some extra // expressions to make sure linter isn't confused by them. - if v == 3 && sky == "blue" && predicate(|x| { let target = 3; x == target }, v) { - } - - if predicate(|x| { let target = 3; x == target }, v) { - } + if v == 3 + && sky == "blue" + && predicate( + |x| { + let target = 3; + x == target + }, + v, + ) + {} + + if predicate( + |x| { + let target = 3; + x == target + }, + v, + ) {} } fn condition_is_normal() -> i32 { @@ -82,9 +90,7 @@ fn condition_is_normal() -> i32 { } fn closure_without_block() { - if predicate(|x| x == 3, 6) { - - } + if predicate(|x| x == 3, 6) {} } fn condition_is_unsafe_block() { @@ -96,8 +102,7 @@ fn condition_is_unsafe_block() { } } -fn main() { -} +fn main() {} fn macro_in_closure() { let option = Some(true); diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 8ab8b3f9281..30b5acf2d97 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -7,19 +7,47 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::bool_comparison)] fn main() { let x = true; - if x == true { "yes" } else { "no" }; - if x == false { "yes" } else { "no" }; - if true == x { "yes" } else { "no" }; - if false == x { "yes" } else { "no" }; - if x != true { "yes" } else { "no" }; - if x != false { "yes" } else { "no" }; - if true != x { "yes" } else { "no" }; - if false != x { "yes" } else { "no" }; + if x == true { + "yes" + } else { + "no" + }; + if x == false { + "yes" + } else { + "no" + }; + if true == x { + "yes" + } else { + "no" + }; + if false == x { + "yes" + } else { + "no" + }; + if x != true { + "yes" + } else { + "no" + }; + if x != false { + "yes" + } else { + "no" + }; + if true != x { + "yes" + } else { + "no" + }; + if false != x { + "yes" + } else { + "no" + }; } diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index e63b6a75e8f..8eb1b52577c 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::nonminimal_bool, clippy::logic_bug)] #[allow(unused, clippy::many_single_char_names)] @@ -71,58 +68,78 @@ fn methods_with_negation() { // Simplified versions of https://github.com/rust-lang/rust-clippy/issues/2638 // clippy::nonminimal_bool should only check the built-in Result and Some type, not // any other types like the following. -enum CustomResultOk { Ok, Err(E) } -enum CustomResultErr { Ok, Err(E) } -enum CustomSomeSome { Some(T), None } -enum CustomSomeNone { Some(T), None } +enum CustomResultOk { + Ok, + Err(E), +} +enum CustomResultErr { + Ok, + Err(E), +} +enum CustomSomeSome { + Some(T), + None, +} +enum CustomSomeNone { + Some(T), + None, +} impl CustomResultOk { - pub fn is_ok(&self) -> bool { true } + pub fn is_ok(&self) -> bool { + true + } } impl CustomResultErr { - pub fn is_err(&self) -> bool { true } + pub fn is_err(&self) -> bool { + true + } } impl CustomSomeSome { - pub fn is_some(&self) -> bool { true } + pub fn is_some(&self) -> bool { + true + } } impl CustomSomeNone { - pub fn is_none(&self) -> bool { true } + pub fn is_none(&self) -> bool { + true + } } fn dont_warn_for_custom_methods_with_negation() { let res = CustomResultOk::Err("Error"); // Should not warn and suggest 'is_err()' because the type does not // implement is_err(). - if !res.is_ok() { } + if !res.is_ok() {} let res = CustomResultErr::Err("Error"); // Should not warn and suggest 'is_ok()' because the type does not // implement is_ok(). - if !res.is_err() { } + if !res.is_err() {} let res = CustomSomeSome::Some("thing"); // Should not warn and suggest 'is_none()' because the type does not // implement is_none(). - if !res.is_some() { } + if !res.is_some() {} let res = CustomSomeNone::Some("thing"); // Should not warn and suggest 'is_some()' because the type does not // implement is_some(). - if !res.is_none() { } + if !res.is_none() {} } // Only Built-in Result and Some types should suggest the negated alternative fn warn_for_built_in_methods_with_negation() { let res: Result = Ok(1); - if !res.is_ok() { } - if !res.is_err() { } + if !res.is_ok() {} + if !res.is_err() {} let res = Some(1); - if !res.is_some() { } - if !res.is_none() { } + if !res.is_some() {} + if !res.is_none() {} } #[allow(clippy::neg_cmp_op_on_partial_ord)] diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index dbcd42a692c..cf204150f8b 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![deny(clippy::borrowed_box)] #![allow(clippy::blacklisted_name)] #![allow(unused_variables)] @@ -25,7 +21,7 @@ pub fn test2() { } struct Test3<'a> { - foo: &'a Box + foo: &'a Box, } trait Test4 { @@ -49,7 +45,7 @@ pub fn test6() { } struct Test7<'a> { - foo: &'a Box + foo: &'a Box, } trait Test8 { @@ -71,7 +67,7 @@ pub fn test10() { } struct Test11<'a> { - foo: &'a Box + foo: &'a Box, } trait Test12 { @@ -84,7 +80,7 @@ impl<'a> Test12 for Test11<'a> { } } -fn main(){ +fn main() { test1(&mut Box::new(false)); test2(); test5(&mut (Box::new(false) as Box)); diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index bf505c85abc..48523054097 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] #![allow(clippy::blacklisted_name)] @@ -18,7 +14,7 @@ macro_rules! boxit { ($init:expr, $x:ty) => { let _: Box<$x> = Box::new($init); - } + }; } fn test_macro() { @@ -28,7 +24,8 @@ pub fn test(foo: Box>) { println!("{:?}", foo.get(0)) } -pub fn test2(foo: Box)>) { // pass if #31 is fixed +pub fn test2(foo: Box)>) { + // pass if #31 is fixed foo(vec![1, 2, 3]) } @@ -36,7 +33,7 @@ pub fn test_local_not_linted() { let _: Box>; } -fn main(){ +fn main() { test(Box::new(Vec::new())); test2(Box::new(|v| println!("{:?}", v))); test_macro(); diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index e43a2789ce1..66a7e318f8a 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::builtin_type_shadow)] fn foo(a: u32) -> u32 { @@ -17,5 +14,4 @@ fn foo(a: u32) -> u32 { // ^ rustc's type error } -fn main() { -} +fn main() {} diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 170666d1f18..6bc9b5ddecd 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[deny(clippy::naive_bytecount)] fn main() { let x = vec![0_u8; 16]; diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 9976a4aa96a..45e878e9d80 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -7,11 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -#[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] +#[warn( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::cast_lossless +)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { // Test clippy::cast_precision_loss @@ -49,7 +51,7 @@ fn main() { false as bool; &1i32 as &i32; // Should not trigger - let v = vec!(1); + let v = vec![1]; &v as &[i32]; 1.0 as f64; 1 as u64; diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index a1a2e1c9a8f..efc56ea2bbc 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - //! Test casts for alignment issues #![feature(libc)] diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index 468774dd88b..e52a756c003 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 4f7432de620..593ffdd2766 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index fddf9669a8f..8f691104c51 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -7,10 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#[warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap, clippy::cast_lossless)] +#[warn( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::cast_lossless +)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { // Casting from *size diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index d684fcf5746..663962afeae 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::char_lit_as_u8)] #![allow(unused_variables)] fn main() { diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index 383fd82240b..4d250a80e90 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow(clippy::if_same_then_else)] @@ -43,11 +40,11 @@ fn main() { if x.is_ok() { x = Err(()); x.unwrap(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). } else { x = Ok(()); x.unwrap_err(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). } } diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index a1353abd92b..058cbf7a16c 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -7,9 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use std::marker::PhantomData; use std::fmt; +use std::marker::PhantomData; pub struct Key { #[doc(hidden)] diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 81d70eb9458..82f411d5c9d 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - pub fn dec_read_dec(i: &mut i32) -> i32 { *i -= 1; let ret = *i; diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index 4b62d0e53f1..d6bdb5894d5 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::cmp_nan)] #[allow(clippy::float_cmp, clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 03f0367a640..37615c9e113 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::cmp_null)] #![allow(unused_mut)] @@ -17,12 +14,12 @@ use std::ptr; fn main() { let x = 0; - let p : *const usize = &x; + let p: *const usize = &x; if p == ptr::null() { println!("This is surprising!"); } let mut y = 0; - let mut m : *mut usize = &mut y; + let mut m: *mut usize = &mut y; if m == ptr::null_mut() { println!("This is surprising, too!"); } diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index dc3d62ddfa6..53de5136105 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -7,14 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::cmp_owned)] #[allow(clippy::unnecessary_operation)] fn main() { - fn with_to_string(x : &str) { + fn with_to_string(x: &str) { x != "foo".to_string(); "foo".to_string() != x; diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index bd6e0c07946..6828743abf3 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[rustfmt::skip] #[warn(clippy::collapsible_if)] fn main() { diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index e735bf8e487..9d75de62d74 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value)] #![feature(associated_type_defaults)] @@ -32,19 +29,21 @@ enum E { impl S { const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); - fn impl_method(&self, p: Vec>>) { } + fn impl_method(&self, p: Vec>>) {} } trait T { const A: Vec>>; type B = Vec>>; fn method(&self, p: Vec>>); - fn def_method(&self, p: Vec>>) { } + fn def_method(&self, p: Vec>>) {} } -fn test1() -> Vec>> { vec![] } +fn test1() -> Vec>> { + vec![] +} -fn test2(_x: Vec>>) { } +fn test2(_x: Vec>>) {} fn test3() { let _y: Vec>> = vec![]; @@ -67,5 +66,4 @@ struct D { ), } -fn main() { -} +fn main() {} diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index 2b6a5dc249a..3e1aa94f969 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[derive(Debug)] struct Foo {} diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 5c4bbecf822..00e1d726207 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -7,13 +7,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(clippy::blacklisted_name, clippy::collapsible_if, clippy::cyclomatic_complexity, clippy::eq_op, clippy::needless_continue, - clippy::needless_return, clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero, clippy::unused_unit)] - - +#![allow( + clippy::blacklisted_name, + clippy::collapsible_if, + clippy::cyclomatic_complexity, + clippy::eq_op, + clippy::needless_continue, + clippy::needless_return, + clippy::never_loop, + clippy::no_effect, + clippy::zero_divided_by_zero, + clippy::unused_unit +)] fn bar(_: T) {} -fn foo() -> bool { unimplemented!() } +fn foo() -> bool { + unimplemented!() +} struct Foo { bar: u8, @@ -37,8 +47,8 @@ fn if_same_then_else() -> Result<&'static str, ()> { ..10; 0..=10; foo(); - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block Foo { bar: 42 }; 0..10; ..; @@ -50,30 +60,26 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { Foo { bar: 42 }; - } - else { + } else { Foo { bar: 43 }; } if true { (); - } - else { + } else { () } if true { 0..10; - } - else { + } else { 0..=10; } if true { foo(); foo(); - } - else { + } else { foo(); } @@ -84,18 +90,19 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { a += 7; } - a = -31-a; + a = -31 - a; a - } - _ => { //~ ERROR match arms have same body + }, + _ => { + //~ ERROR match arms have same body foo(); let mut a = 42 + [23].len() as i32; if true { a += 7; } - a = -31-a; + a = -31 - a; a - } + }, }; let _ = match Abc::A { @@ -110,8 +117,8 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = if true { 42 - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block 42 }; @@ -124,8 +131,8 @@ fn if_same_then_else() -> Result<&'static str, ()> { continue; } } - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block for _ in &[42] { let foo: &Option<_> = &Some::(42); if true { @@ -137,25 +144,19 @@ fn if_same_then_else() -> Result<&'static str, ()> { } if true { - let bar = if true { - 42 - } - else { - 43 - }; + let bar = if true { 42 } else { 43 }; - while foo() { break; } - bar + 1; - } - else { //~ ERROR same body as `if` block - let bar = if true { - 42 + while foo() { + break; } - else { - 43 - }; + bar + 1; + } else { + //~ ERROR same body as `if` block + let bar = if true { 42 } else { 43 }; - while foo() { break; } + while foo() { + break; + } bar + 1; } @@ -166,11 +167,9 @@ fn if_same_then_else() -> Result<&'static str, ()> { 10..=15 => 3, _ => 4, }; - } - else if false { + } else if false { foo(); - } - else if foo() { + } else if foo() { let _ = match 42 { 42 => 1, a if a > 0 => 2, @@ -181,64 +180,57 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { if let Some(a) = Some(42) {} - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block if let Some(a) = Some(42) {} } if true { if let (1, .., 3) = (1, 2, 3) {} - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block if let (1, .., 3) = (1, 2, 3) {} } if true { if let (1, .., 3) = (1, 2, 3) {} - } - else { + } else { if let (.., 3) = (1, 2, 3) {} } if true { if let (1, .., 3) = (1, 2, 3) {} - } - else { + } else { if let (.., 4) = (1, 2, 3) {} } if true { if let (1, .., 3) = (1, 2, 3) {} - } - else { + } else { if let (.., 1, 3) = (1, 2, 3) {} } if true { if let Some(42) = None {} - } - else { + } else { if let Option::Some(42) = None {} } if true { if let Some(42) = None:: {} - } - else { + } else { if let Some(42) = None {} } if true { if let Some(42) = None:: {} - } - else { + } else { if let Some(42) = None:: {} } if true { if let Some(a) = Some(42) {} - } - else { + } else { if let Some(a) = Some(43) {} } @@ -290,39 +282,34 @@ fn if_same_then_else() -> Result<&'static str, ()> { let _ = if true { 0.0 - } else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block 0.0 }; let _ = if true { -0.0 - } else { //~ ERROR same body as `if` block - -0.0 - }; - - let _ = if true { - 0.0 } else { + //~ ERROR same body as `if` block -0.0 }; + let _ = if true { 0.0 } else { -0.0 }; + // Different NaNs - let _ = if true { - 0.0 / 0.0 - } else { - std::f32::NAN - }; + let _ = if true { 0.0 / 0.0 } else { std::f32::NAN }; // Same NaNs let _ = if true { std::f32::NAN - } else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block std::f32::NAN }; let _ = match Some(()) { Some(()) => 0.0, - None => -0.0 + None => -0.0, }; match (Some(42), Some("")) { @@ -333,20 +320,18 @@ fn if_same_then_else() -> Result<&'static str, ()> { if true { try!(Ok("foo")); - } - else { //~ ERROR same body as `if` block + } else { + //~ ERROR same body as `if` block try!(Ok("foo")); } if true { let foo = ""; return Ok(&foo[0..]); - } - else if false { + } else if false { let foo = "bar"; return Ok(&foo[0..]); - } - else { + } else { let foo = ""; return Ok(&foo[0..]); } @@ -359,22 +344,20 @@ fn ifs_same_cond() { let b = false; if b { - } - else if b { //~ ERROR ifs same condition + } else if b { + //~ ERROR ifs same condition } if a == 1 { - } - else if a == 1 { //~ ERROR ifs same condition + } else if a == 1 { + //~ ERROR ifs same condition } - if 2*a == 1 { - } - else if 2*a == 2 { - } - else if 2*a == 1 { //~ ERROR ifs same condition - } - else if a == 1 { + if 2 * a == 1 { + } else if 2 * a == 2 { + } else if 2 * a == 1 { + //~ ERROR ifs same condition + } else if a == 1 { } // See #659 @@ -387,14 +370,14 @@ fn ifs_same_cond() { }; let mut v = vec![1]; - if v.pop() == None { // ok, functions - } - else if v.pop() == None { + if v.pop() == None { + // ok, functions + } else if v.pop() == None { } - if v.len() == 42 { // ok, functions - } - else if v.len() == 42 { + if v.len() == 42 { + // ok, functions + } else if v.len() == 42 { } } diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index b5684f183eb..22d3e138898 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::copy_iterator)] #[derive(Copy, Clone)] diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index 6121166debe..5fe915a8368 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - fn main() {} #[allow(clippy::result_unwrap_used)] diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index a9a2391f150..fff67762924 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(clippy::all)] #![warn(clippy::cyclomatic_complexity)] #![allow(unused)] @@ -181,8 +180,8 @@ fn bar() { #[test] #[clippy::cyclomatic_complexity = "0"] -/// Tests are usually complex but simple at the same time. `clippy::cyclomatic_complexity` used to give -/// lots of false-positives in tests. +/// Tests are usually complex but simple at the same time. `clippy::cyclomatic_complexity` used to +/// give lots of false-positives in tests. fn dont_warn_on_tests() { match 99 { 0 => println!("hi"), @@ -278,7 +277,6 @@ fn cake() { println!("whee"); } - #[clippy::cyclomatic_complexity = "0"] pub fn read_file(input_path: &str) -> String { use std::fs::File; @@ -288,7 +286,7 @@ pub fn read_file(input_path: &str) -> String { Ok(f) => f, Err(err) => { panic!("Can't open {}: {}", input_path, err); - } + }, }; let mut bytes = Vec::new(); @@ -297,14 +295,14 @@ pub fn read_file(input_path: &str) -> String { Ok(..) => {}, Err(_) => { panic!("Can't read {}", input_path); - } + }, }; match String::from_utf8(bytes) { Ok(contents) => contents, Err(_) => { panic!("{} is not UTF-8 encoded", input_path); - } + }, } } @@ -313,8 +311,7 @@ enum Void {} #[clippy::cyclomatic_complexity = "0"] fn void(void: Void) { if true { - match void { - } + match void {} } } diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index 63d4e65a977..b1da9649f90 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index c52fcd826ca..c196b27a3a6 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -7,24 +7,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] fn main() { - let good = ( // Hex: - 127, // 0x7F - 256, // 0x100 - 511, // 0x1FF - 2048, // 0x800 - 4090, // 0xFFA - 16_371, // 0x3FF3 - 61_683, // 0xF0F3 - 2_131_750_925, // 0x7F0F_F00D + let good = ( + // Hex: + 127, // 0x7F + 256, // 0x100 + 511, // 0x1FF + 2048, // 0x800 + 4090, // 0xFFA + 16_371, // 0x3FF3 + 61_683, // 0xF0F3 + 2_131_750_925, // 0x7F0F_F00D ); - let bad = ( // Hex: + let bad = ( + // Hex: 32_773, // 0x8005 65_280, // 0xFF00 2_131_750_927, // 0x7F0F_F00F diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 331ad03f9a2..eaa367b0cb3 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -7,14 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::default_trait_access)] +use std::default; use std::default::Default as D2; use std::string; -use std::default; fn main() { let s1: String = Default::default(); diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index a7e95ad5dde..7a1657424ed 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -7,18 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(str_to_string)] - #[warn(string_to_string)] - #[warn(unstable_as_slice)] - #[warn(unstable_as_mut_slice)] - #[warn(misaligned_transmute)] fn main() {} diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 521a2e323fc..a6020b61337 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(untagged_unions)] - #![allow(dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] @@ -21,21 +17,27 @@ use std::hash::{Hash, Hasher}; struct Foo; impl PartialEq for Foo { - fn eq(&self, _: &u64) -> bool { true } + fn eq(&self, _: &u64) -> bool { + true + } } #[derive(Hash)] struct Bar; impl PartialEq for Bar { - fn eq(&self, _: &Bar) -> bool { true } + fn eq(&self, _: &Bar) -> bool { + true + } } #[derive(Hash)] struct Baz; impl PartialEq for Baz { - fn eq(&self, _: &Baz) -> bool { true } + fn eq(&self, _: &Baz) -> bool { + true + } } #[derive(PartialEq)] @@ -49,7 +51,9 @@ impl Hash for Bah { struct Qux; impl Clone for Qux { - fn clone(&self) -> Self { Qux } + fn clone(&self) -> Self { + Qux + } } // looks like unions don't support deriving Clone for now @@ -60,9 +64,7 @@ union Union { impl Clone for Union { fn clone(&self) -> Self { - Union { - a: 42, - } + Union { a: 42 } } } @@ -73,7 +75,9 @@ struct Lt<'a> { } impl<'a> Clone for Lt<'a> { - fn clone(&self) -> Self { unimplemented!() } + fn clone(&self) -> Self { + unimplemented!() + } } // Ok, `Clone` cannot be derived because of the big array @@ -83,7 +87,9 @@ struct BigArray { } impl Clone for BigArray { - fn clone(&self) -> Self { unimplemented!() } + fn clone(&self) -> Self { + unimplemented!() + } } // Ok, function pointers are not always Clone @@ -93,7 +99,9 @@ struct FnPtr { } impl Clone for FnPtr { - fn clone(&self) -> Self { unimplemented!() } + fn clone(&self) -> Self { + unimplemented!() + } } // Ok, generics @@ -103,7 +111,9 @@ struct Generic { } impl Clone for Generic { - fn clone(&self) -> Self { unimplemented!() } + fn clone(&self) -> Self { + unimplemented!() + } } fn main() {} diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index a47c96759ac..3399dba7189 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -7,21 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(never_type)] - #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::logic_bug)] #[allow(clippy::empty_loop)] -fn diverge() -> ! { loop {} } +fn diverge() -> ! { + loop {} +} struct A; impl A { - fn foo(&self) -> ! { diverge() } + fn foo(&self) -> ! { + diverge() + } } #[allow(unused_variables, clippy::unnecessary_operation, clippy::short_circuit_statement)] diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index cf16777b77a..dfc8be24a8b 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -7,13 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(alloc)] #![feature(associated_type_defaults)] - - #![warn(clippy::linkedlist)] #![allow(dead_code, clippy::needless_pass_by_value)] @@ -23,13 +18,13 @@ use alloc::collections::linked_list::LinkedList; trait Foo { type Baz = LinkedList; fn foo(LinkedList); - const BAR : Option>; + const BAR: Option>; } // ok, we don’t want to warn for implementations, see #605 impl Foo for LinkedList { fn foo(_: LinkedList) {} - const BAR : Option> = None; + const BAR: Option> = None; } struct Bar; @@ -49,7 +44,7 @@ pub fn test_local_not_linted() { let _: LinkedList; } -fn main(){ +fn main() { test(LinkedList::new()); test_local_not_linted(); } diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 555f35884f9..70b837a75b6 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { let x = 1; let y = 2; diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index 3785c09060b..7d65122cb5e 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::double_neg)] fn main() { let x = 1; diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 44e9ae0e044..2ea8954ff59 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::drop_copy, clippy::forget_copy)] #![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)] @@ -18,18 +14,21 @@ use std::mem::{drop, forget}; use std::vec::Vec; #[derive(Copy, Clone)] -struct SomeStruct { -} +struct SomeStruct {} struct AnotherStruct { x: u8, y: u8, - z: Vec + z: Vec, } impl Clone for AnotherStruct { - fn clone(& self) -> AnotherStruct { - AnotherStruct{x: self.x, y: self.y, z: self.z.clone()} + fn clone(&self) -> AnotherStruct { + AnotherStruct { + x: self.x, + y: self.y, + z: self.z.clone(), + } } } @@ -52,7 +51,11 @@ fn main() { forget(s4); forget(s5); - let a1 = AnotherStruct {x: 255, y: 0, z: vec![1, 2, 3]}; + let a1 = AnotherStruct { + x: 255, + y: 0, + z: vec![1, 2, 3], + }; let a2 = &a1; let mut a3 = a1.clone(); let ref a4 = a1; diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index 0aee38d3cbf..6821d403322 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::drop_ref, clippy::forget_ref)] #![allow(clippy::toplevel_ref_arg, clippy::similar_names, clippy::needless_pass_by_value)] diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index 27329965f0c..da4e2a6dc8a 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::duplicate_underscore_argument)] #[allow(dead_code, unused)] diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index c8db599a840..8c2dade34c0 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index caaa024ff6b..0776eae310c 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -7,15 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::all)] #![warn(clippy::else_if_without_else)] -fn bla1() -> bool { unimplemented!() } -fn bla2() -> bool { unimplemented!() } -fn bla3() -> bool { unimplemented!() } +fn bla1() -> bool { + unimplemented!() +} +fn bla2() -> bool { + unimplemented!() +} +fn bla3() -> bool { + unimplemented!() +} fn main() { if bla1() { @@ -48,7 +51,8 @@ fn main() { if bla1() { println!("if"); - } else if bla2() { //~ ERROR else if without else + } else if bla2() { + //~ ERROR else if without else println!("else if"); } @@ -56,7 +60,8 @@ fn main() { println!("if"); } else if bla2() { println!("else if 1"); - } else if bla3() { //~ ERROR else if without else + } else if bla3() { + //~ ERROR else if without else println!("else if 2"); } } diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index b60f5491a93..b47afc822f8 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -7,14 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] #![warn(clippy::empty_enum)] enum Empty {} -fn main() { -} +fn main() {} diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 0ee6d799222..6c826716650 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused, clippy::needless_pass_by_value)] - #![warn(clippy::map_entry)] use std::collections::{BTreeMap, HashMap}; @@ -20,36 +16,65 @@ use std::hash::Hash; fn foo() {} fn insert_if_absent0(m: &mut HashMap, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v); } + if !m.contains_key(&k) { + m.insert(k, v); + } } fn insert_if_absent1(m: &mut HashMap, k: K, v: V) { - if !m.contains_key(&k) { foo(); m.insert(k, v); } + if !m.contains_key(&k) { + foo(); + m.insert(k, v); + } } fn insert_if_absent2(m: &mut HashMap, k: K, v: V) { - if !m.contains_key(&k) { m.insert(k, v) } else { None }; + if !m.contains_key(&k) { + m.insert(k, v) + } else { + None + }; } fn insert_if_present2(m: &mut HashMap, k: K, v: V) { - if m.contains_key(&k) { None } else { m.insert(k, v) }; + if m.contains_key(&k) { + None + } else { + m.insert(k, v) + }; } fn insert_if_absent3(m: &mut HashMap, k: K, v: V) { - if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; + if !m.contains_key(&k) { + foo(); + m.insert(k, v) + } else { + None + }; } fn insert_if_present3(m: &mut HashMap, k: K, v: V) { - if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; + if m.contains_key(&k) { + None + } else { + foo(); + m.insert(k, v) + }; } fn insert_in_btreemap(m: &mut BTreeMap, k: K, v: V) { - if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; + if !m.contains_key(&k) { + foo(); + m.insert(k, v) + } else { + None + }; } fn insert_other_if_absent(m: &mut HashMap, k: K, o: K, v: V) { - if !m.contains_key(&k) { m.insert(o, v); } + if !m.contains_key(&k) { + m.insert(o, v); + } } -fn main() { -} +fn main() {} diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 9b7d4518c66..dde2896e415 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::all, clippy::pedantic)] #![allow(unused_imports, dead_code, clippy::missing_docs_in_private_items)] @@ -34,8 +31,7 @@ mod tests { } #[allow(non_snake_case)] -mod CamelCaseName { -} +mod CamelCaseName {} use CamelCaseName::*; diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 34c69854b75..0c8f3a36a3d 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -7,19 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(non_ascii_idents)] - #![warn(clippy::all, clippy::pub_enum_variant_names)] enum FakeCallType { - CALL, CREATE + CALL, + CREATE, } enum FakeCallType2 { - CALL, CREATELL + CALL, + CREATELL, } enum Foo { @@ -49,7 +47,8 @@ enum BadCallType { CallTypeDestroy, } -enum TwoCallType { // no error +enum TwoCallType { + // no error CallTypeCall, CallTypeCreate, } @@ -60,7 +59,8 @@ enum Consts { ConstantLie, } -enum Two { // no error here +enum Two { + // no error here ConstantInt, ConstantInfer, } diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index 5513a9506aa..9c1cf8e8614 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -7,14 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - // ignore-x86 - #![warn(clippy::all)] - #![allow(unused)] #[repr(usize)] @@ -62,5 +57,4 @@ trait Trait { } */ -fn main() { -} +fn main() {} diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index 696c58f98ae..d7166213194 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[allow(clippy::no_effect)] #[warn(clippy::erasing_op)] fn main() { diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index b35071546e7..cc65c6e6306 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -8,7 +8,6 @@ // except according to those terms. #![feature(box_syntax)] - #![allow(clippy::borrowed_box, clippy::needless_pass_by_value, clippy::unused_unit)] #![warn(clippy::boxed_local)] @@ -16,7 +15,7 @@ struct A; impl A { - fn foo(&self){} + fn foo(&self) {} } trait Z { @@ -29,8 +28,7 @@ impl Z for A { } } -fn main() { -} +fn main() {} fn ok_box_trait(boxed_trait: &Box) { let boxed_local = boxed_trait; @@ -85,11 +83,9 @@ fn nowarn_pass() { take_box(&bx); // fn needs &Box } - fn take_box(x: &Box) {} fn take_ref(x: &A) {} - fn nowarn_ref_take() { // false positive, should actually warn let x = box A; @@ -100,14 +96,15 @@ fn nowarn_ref_take() { fn nowarn_match() { let x = box A; // moved into a match match x { - y => drop(y) + y => drop(y), } } fn warn_match() { let x = box A; - match &x { // not moved - ref y => () + match &x { + // not moved + ref y => (), } } @@ -115,12 +112,12 @@ fn nowarn_large_array() { // should not warn, is large array // and should not be on stack let x = box [1; 10000]; - match &x { // not moved - ref y => () + match &x { + // not moved + ref y => (), } } - /// ICE regression test pub trait Foo { type Item; @@ -134,8 +131,7 @@ pub struct PeekableSeekable { _peeked: I::Item, } -pub fn new(_needs_name: Box>) -> () { -} +pub fn new(_needs_name: Box>) -> () {} /// Regression for #916, #1123 /// diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index dd41433d2db..7b39d1c4054 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -7,10 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![allow(unused, clippy::no_effect, clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, clippy::trivially_copy_pass_by_ref)] +#![allow( + unused, + clippy::no_effect, + clippy::redundant_closure_call, + clippy::many_single_char_names, + clippy::needless_pass_by_value, + clippy::option_map_unit_fn, + clippy::trivially_copy_pass_by_ref +)] #![warn(clippy::redundant_closure, clippy::needless_borrow)] fn main() { @@ -32,25 +37,31 @@ fn main() { Some(vec![1i32, 2]).map(|v| -> Box<::std::ops::Deref> { Box::new(v) }); } -fn meta(f: F) where F: Fn(u8) { +fn meta(f: F) +where + F: Fn(u8), +{ f(1u8) } -fn foo(_: u8) { -} +fn foo(_: u8) {} fn foo2(_: u8) -> u8 { 1u8 } fn all(x: &[X], y: &X, f: F) -> bool -where F: Fn(&X, &X) -> bool { +where + F: Fn(&X, &X) -> bool, +{ x.iter().all(|e| f(e, y)) } -fn below(x: &u8, y: &u8) -> bool { x < y } +fn below(x: &u8, y: &u8) -> bool { + x < y +} -unsafe fn unsafe_fn(_: u8) { } +unsafe fn unsafe_fn(_: u8) {} fn divergent(_: u8) -> ! { unimplemented!() diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index ee8f834fe56..82110d5e4f3 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -7,52 +7,112 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::eval_order_dependence)] -#[allow(unused_assignments, unused_variables, clippy::many_single_char_names, clippy::no_effect, dead_code, clippy::blacklisted_name)] +#[allow( + unused_assignments, + unused_variables, + clippy::many_single_char_names, + clippy::no_effect, + dead_code, + clippy::blacklisted_name +)] fn main() { let mut x = 0; - let a = { x = 1; 1 } + x; + let a = { + x = 1; + 1 + } + x; // Example from iss#277 - x += { x = 20; 2 }; + x += { + x = 20; + 2 + }; // Does it work in weird places? // ...in the base for a struct expression? - struct Foo { a: i32, b: i32 }; + struct Foo { + a: i32, + b: i32, + }; let base = Foo { a: 4, b: 5 }; - let foo = Foo { a: x, .. { x = 6; base } }; + let foo = Foo { + a: x, + ..{ + x = 6; + base + } + }; // ...inside a closure? let closure = || { let mut x = 0; - x += { x = 20; 2 }; + x += { + x = 20; + 2 + }; }; // ...not across a closure? let mut y = 0; - let b = (y, || { y = 1 }); + let b = (y, || y = 1); // && and || evaluate left-to-right. - let a = { x = 1; true } && (x == 3); - let a = { x = 1; true } || (x == 3); + let a = { + x = 1; + true + } && (x == 3); + let a = { + x = 1; + true + } || (x == 3); // Make sure we don't get confused by alpha conversion. - let a = { let mut x = 1; x = 2; 1 } + x; + let a = { + let mut x = 1; + x = 2; + 1 + } + x; // No warning if we don't read the variable... - x = { x = 20; 2 }; + x = { + x = 20; + 2 + }; // ...if the assignment is in a closure... - let b = { || { x = 1; }; 1 } + x; + let b = { + || { + x = 1; + }; + 1 + } + x; // ... or the access is under an address. - let b = ({ let p = &x; 1 }, { x = 1; x }); + let b = ( + { + let p = &x; + 1 + }, + { + x = 1; + x + }, + ); // Limitation: l-values other than simple variables don't trigger // the warning. let mut tup = (0, 0); - let c = { tup.0 = 1; 1 } + tup.0; + let c = { + tup.0 = 1; + 1 + } + tup.0; // Limitation: you can get away with a read under address-of. let mut z = 0; - let b = (&{ z = x; x }, { x = 3; x }); + let b = ( + &{ + z = x; + x + }, + { + x = 3; + x + }, + ); } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 5945298da9f..59b252a3a80 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::excessive_precision)] #![allow(clippy::print_literal)] diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index cf764c43694..8afffa4d843 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -16,7 +16,9 @@ fn expect_fun_call() { struct Foo; impl Foo { - fn new() -> Self { Foo } + fn new() -> Self { + Foo + } fn expect(&self, msg: &str) { panic!("{}", msg) diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index eaed606b89e..75d905659d9 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -26,9 +26,11 @@ fn main() { mod issue_1219 { pub fn test() { // should not trigger the lint because variable is used after the loop #473 - let vec = vec![1,2,3]; + let vec = vec![1, 2, 3]; let mut index = 0; - for _v in &vec { index += 1 } + for _v in &vec { + index += 1 + } println!("index: {}", index); // should not trigger the lint because the count is conditional #1219 diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 8c1e35daa48..10a4bca9f49 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -7,12 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::explicit_write)] - fn stdout() -> String { String::new() } diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index f50d5999de6..0d8c369660b 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::fallible_impl_from)] // docs example @@ -20,7 +17,6 @@ impl From for Foo { } } - struct Valid(Vec); impl<'a> From<&'a str> for Valid { @@ -34,7 +30,6 @@ impl From for Valid { } } - struct Invalid; impl From for Invalid { diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index 33441d728ca..7ca74fd4b99 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -7,31 +7,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] fn main() { - let _: Vec<_> = vec![5; 6].into_iter() - .filter(|&x| x == 0) - .map(|x| x * 2) - .collect(); - - let _: Vec<_> = vec![5_i8; 6].into_iter() - .filter(|&x| x == 0) - .flat_map(|x| x.checked_mul(2)) - .collect(); - - let _: Vec<_> = vec![5_i8; 6].into_iter() - .filter_map(|x| x.checked_mul(2)) - .flat_map(|x| x.checked_mul(2)) - .collect(); - - let _: Vec<_> = vec![5_i8; 6].into_iter() - .filter_map(|x| x.checked_mul(2)) - .map(|x| x.checked_mul(2)) - .collect(); + let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); + + let _: Vec<_> = vec![5_i8; 6] + .into_iter() + .filter(|&x| x == 0) + .flat_map(|x| x.checked_mul(2)) + .collect(); + + let _: Vec<_> = vec![5_i8; 6] + .into_iter() + .filter_map(|x| x.checked_mul(2)) + .flat_map(|x| x.checked_mul(2)) + .collect(); + + let _: Vec<_> = vec![5_i8; 6] + .into_iter() + .filter_map(|x| x.checked_mul(2)) + .map(|x| x.checked_mul(2)) + .collect(); } diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 5619539fb5a..2d55e30a2d3 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -7,31 +7,41 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::float_cmp)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] use std::ops::Add; -const ZERO : f32 = 0.0; -const ONE : f32 = ZERO + 1.0; +const ZERO: f32 = 0.0; +const ONE: f32 = ZERO + 1.0; -fn twice(x : T) -> T where T : Add, T : Copy { +fn twice(x: T) -> T +where + T: Add, + T: Copy, +{ x + x } fn eq_fl(x: f32, y: f32) -> bool { - if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn + if x.is_nan() { + y.is_nan() + } else { + x == y + } // no error, inside "eq" fn } fn fl_eq(x: f32, y: f32) -> bool { - if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn + if x.is_nan() { + y.is_nan() + } else { + x == y + } // no error, inside "eq" fn } -struct X { val: f32 } +struct X { + val: f32, +} impl PartialEq for X { fn eq(&self, o: &X) -> bool { @@ -59,7 +69,7 @@ fn main() { ONE as f64 != 2.0; ONE as f64 != 0.0; // no error, comparison with zero is ok - let x : f64 = 1.0; + let x: f64 = 1.0; x == 1.0; x != 0f64; // no error, comparison with zero is ok @@ -71,7 +81,7 @@ fn main() { x <= 0.0; x >= 0.0; - let xs : [f32; 1] = [0.0]; + let xs: [f32; 1] = [0.0]; let a: *const f32 = xs.as_ptr(); let b: *const f32 = xs.as_ptr(); diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 7cca1df65ae..e02671e0dcc 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::float_cmp_const)] #![allow(clippy::float_cmp)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] @@ -19,7 +15,11 @@ const ONE: f32 = 1.0; const TWO: f32 = 2.0; fn eq_one(x: f32) -> bool { - if x.is_nan() { false } else { x == ONE } // no error, inside "eq" fn + if x.is_nan() { + false + } else { + x == ONE + } // no error, inside "eq" fn } fn main() { diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 50796e13ef6..9b48a965cb3 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // only-64bit - #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] -fn foo() -> String { String::new() } +fn foo() -> String { + String::new() +} fn test_function_to_numeric_cast() { let _ = foo as i8; diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 513a3c0ee42..4747269bccd 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -25,10 +25,22 @@ impl Unrelated { } } -#[warn(clippy::needless_range_loop, clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, clippy::reverse_range_loop, - clippy::for_kv_map)] +#[warn( + clippy::needless_range_loop, + clippy::explicit_iter_loop, + clippy::explicit_into_iter_loop, + clippy::iter_next_loop, + clippy::reverse_range_loop, + clippy::for_kv_map +)] #[warn(clippy::unused_collect)] -#[allow(clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, clippy::cyclomatic_complexity, clippy::similar_names)] +#[allow( + clippy::linkedlist, + clippy::shadow_unrelated, + clippy::unnecessary_mut_passed, + clippy::cyclomatic_complexity, + clippy::similar_names +)] #[allow(clippy::many_single_char_names, unused_variables, clippy::into_iter_on_array)] fn main() { const MAX_LEN: usize = 42; diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 88f6e497d12..875a74d2508 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -7,82 +7,74 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(clippy::if_same_then_else)] #![allow(clippy::deref_addrof)] -fn foo() -> bool { true } +fn foo() -> bool { + true +} fn main() { // weird `else if` formatting: - if foo() { - } if foo() { - } + if foo() {} + if foo() {} - let _ = { // if as the last expression + let _ = { + // if as the last expression let _ = 0; + if foo() {} if foo() { - } if foo() { - } - else { + } else { } }; - let _ = { // if in the middle of a block + let _ = { + // if in the middle of a block + if foo() {} if foo() { - } if foo() { - } - else { + } else { } let _ = 0; }; if foo() { - } else - if foo() { // the span of the above error should continue here + } else if foo() { + // the span of the above error should continue here } if foo() { - } - else - if foo() { // the span of the above error should continue here + } else if foo() { + // the span of the above error should continue here } // those are ok: - if foo() { - } - if foo() { - } + if foo() {} + if foo() {} if foo() { } else if foo() { } if foo() { - } - else if foo() { + } else if foo() { } if foo() { + } else if foo() { } - else if - foo() {} // weird op_eq formatting: let mut a = 42; - a =- 35; - a =* &191; + a = -35; + a = *&191; let mut b = true; - b =! false; + b = !false; // those are ok: a = -35; @@ -91,37 +83,30 @@ fn main() { // possible missing comma in an array let _ = &[ - -1, -2, -3 // <= no comma here - -4, -5, -6 + -1, + -2, + -3 // <= no comma here + -4, + -5, + -6, ]; let _ = &[ - -1, -2, -3 // <= no comma here - *4, -5, -6 + -1, + -2, + -3 // <= no comma here + *4, + -5, + -6, ]; // those are ok: - let _ = &[ - -1, -2, -3, - -4, -5, -6 - ]; - let _ = &[ - -1, -2, -3, - -4, -5, -6, - ]; - let _ = &[ - 1 + 2, 3 + - 4, 5 + 6, - ]; + let _ = &[-1, -2, -3, -4, -5, -6]; + let _ = &[-1, -2, -3, -4, -5, -6]; + let _ = &[1 + 2, 3 + 4, 5 + 6]; // don't lint for bin op without unary equiv // issue 3244 - vec![ - 1 - / 2, - ]; + vec![1 / 2]; // issue 3396 - vec![ - true - | false, - ]; + vec![true | false]; } diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index f5ba0f791ee..41963294815 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(dead_code)] #![allow(unused_unsafe)] @@ -18,11 +14,20 @@ // TOO_MANY_ARGUMENTS fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} -fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { -} +fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} // don't lint extern fns -extern fn extern_fn(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +extern "C" fn extern_fn( + _one: u32, + _two: u32, + _three: &str, + _four: bool, + _five: f32, + _six: f32, + _seven: bool, + _eight: (), +) { +} pub trait Foo { fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool); diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs index fe4b80807c0..2299714132f 100644 --- a/tests/ui/fxhash.rs +++ b/tests/ui/fxhash.rs @@ -7,16 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::default_hash_types)] #![feature(rustc_private)] extern crate rustc_data_structures; -use std::collections::{HashMap, HashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use std::collections::{HashMap, HashSet}; fn main() { let _map: HashMap = HashMap::default(); diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 7b672c0748c..e8789db6fc1 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(unused_mut)] use std::collections::BTreeMap; @@ -20,8 +19,12 @@ struct GetFalsePositive { } impl GetFalsePositive { - fn get(&self, pos: usize) -> Option<&u32> { self.arr.get(pos) } - fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { self.arr.get_mut(pos) } + fn get(&self, pos: usize) -> Option<&u32> { + self.arr.get(pos) + } + fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { + self.arr.get_mut(pos) + } } fn main() { @@ -33,7 +36,8 @@ fn main() { let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; - { // Test `get().unwrap()` + { + // Test `get().unwrap()` let _ = boxed_slice.get(1).unwrap(); let _ = some_slice.get(0).unwrap(); let _ = some_vec.get(0).unwrap(); @@ -43,7 +47,8 @@ fn main() { let _ = false_positive.get(0).unwrap(); } - { // Test `get_mut().unwrap()` + { + // Test `get_mut().unwrap()` *boxed_slice.get_mut(0).unwrap() = 1; *some_slice.get_mut(0).unwrap() = 1; *some_vec.get_mut(0).unwrap() = 1; @@ -54,7 +59,8 @@ fn main() { *false_positive.get_mut(0).unwrap() = 1; } - { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` + { + // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` let _ = some_vec.get(0..1).unwrap().to_vec(); let _ = some_vec.get_mut(0..1).unwrap().to_vec(); } diff --git a/tests/ui/ice-2636.rs b/tests/ui/ice-2636.rs index 3ef9ea8f69f..caf8c89390d 100644 --- a/tests/ui/ice-2636.rs +++ b/tests/ui/ice-2636.rs @@ -29,4 +29,3 @@ fn main() { let a = Foo::A; test_hash!(&a, A => 0, B => 1, C => 2); } - diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index b5cb92c6d5a..6ba191b0b84 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::identity_conversion)] fn test_generic(val: T) -> T { diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 07a4ef8f3eb..c8874250a04 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -7,15 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -const ONE : i64 = 1; -const NEG_ONE : i64 = -1; -const ZERO : i64 = 0; - -#[allow(clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::double_parens)] +const ONE: i64 = 1; +const NEG_ONE: i64 = -1; +const ZERO: i64 = 0; + +#[allow( + clippy::eq_op, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::double_parens +)] #[warn(clippy::identity_op)] fn main() { let x = 0; @@ -25,19 +26,19 @@ fn main() { x + 1; 0 + x; 1 + x; - x - ZERO; //no error, as we skip lookups (for now) + x - ZERO; //no error, as we skip lookups (for now) x | (0); - ((ZERO)) | x; //no error, as we skip lookups (for now) + (ZERO) | x; //no error, as we skip lookups (for now) x * 1; 1 * x; - x / ONE; //no error, as we skip lookups (for now) + x / ONE; //no error, as we skip lookups (for now) - x / 2; //no false positive + x / 2; //no false positive - x & NEG_ONE; //no error, as we skip lookups (for now) + x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; - let u : u8 = 0; + let u: u8 = 0; u & 255; } diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index 23895c0ab52..0179381fdc3 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::all)] #![warn(clippy::if_not_else)] -fn bla() -> bool { unimplemented!() } +fn bla() -> bool { + unimplemented!() +} fn main() { if !bla() { diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 38c0a484091..398a8ccce44 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(dead_code)] #![warn(clippy::multiple_inherent_impl)] diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index a6be909c0cc..ddcd8bcd755 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(unused)] -use std::collections::{HashMap, HashSet}; use std::cmp::Eq; -use std::hash::{Hash, BuildHasher}; +use std::collections::{HashMap, HashSet}; +use std::hash::{BuildHasher, Hash}; pub trait Foo: Sized { fn make() -> (Self, Self); @@ -49,7 +48,6 @@ impl Foo for HashMap { } } - impl Foo for HashSet { fn make() -> (Self, Self) { (HashSet::new(), HashSet::with_capacity(10)) @@ -72,8 +70,7 @@ impl Foo for HashSet { } } -pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { -} +pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} macro_rules! gen { (impl) => { @@ -85,19 +82,19 @@ macro_rules! gen { }; (fn $name:ident) => { - pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { - } - } + pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} + }; } -gen!(impl); +gen!(impl ); gen!(fn bar); // When the macro is in a different file, the suggestion spans can't be combined properly // and should not cause an ICE // See #2707 #[macro_use] -#[path = "../auxiliary/test_macro.rs"] pub mod test_macro; +#[path = "../auxiliary/test_macro.rs"] +pub mod test_macro; __implicit_hasher_test_macro!(impl for HashMap where V: test_macro::A); fn main() {} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 73cf2908833..3bff92cf492 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::implicit_return)] fn test_end_of_fn() -> bool { @@ -34,9 +30,7 @@ fn test_if_block() -> bool { fn test_match(x: bool) -> bool { match x { true => false, - false => { - true - } + false => true, } } @@ -48,9 +42,7 @@ fn test_loop() -> bool { } fn test_closure() { - let _ = || { - true - }; + let _ = || true; let _ = || true; } diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index 941fbe5154a..31e34135bfc 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -7,12 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[warn(clippy::inconsistent_digit_grouping)] #[allow(unused_variables)] fn main() { - let good = (123, 1_234, 1_2345_6789, 123_f32, 1_234.12_f32, 1_234.123_4_f32, 1.123_456_7_f32); + let good = ( + 123, + 1_234, + 1_2345_6789, + 123_f32, + 1_234.12_f32, + 1_234.123_4_f32, + 1.123_456_7_f32, + ); let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); } diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index ff154091bb8..a9e697e519f 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(plugin)] #![warn(clippy::indexing_slicing)] #![warn(clippy::out_of_bounds_indexing)] diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 62036cbc107..37ae19497d1 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(exhaustive_patterns, never_type)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 68c10acb2be..8f41e3ae98d 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -7,12 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - use std::iter::repeat; #[allow(clippy::trivially_copy_pass_by_ref)] -fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } +fn square_is_lower_64(x: &u32) -> bool { + x * x < 64 +} #[allow(clippy::maybe_infinite_iter)] #[deny(clippy::infinite_iter)] @@ -20,10 +19,17 @@ fn infinite_iters() { repeat(0_u8).collect::>(); // infinite iter (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter (0..8_u64).chain(0..).max(); // infinite iter - (0_usize..).chain([0usize, 1, 2].iter().cloned()).skip_while(|x| *x != 42).min(); // infinite iter - (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter + (0_usize..) + .chain([0usize, 1, 2].iter().cloned()) + .skip_while(|x| *x != 42) + .min(); // infinite iter + (0..8_u32) + .rev() + .cycle() + .map(|x| x + 1_u32) + .for_each(|x| println!("{}", x)); // infinite iter (0..3_u32).flat_map(|x| x..).sum::(); // infinite iter - (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter + (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter (0..42_u64).by_ref().last(); // not an infinite, because ranges are double-ended (0..).next(); // iterator is not exhausted @@ -33,7 +39,12 @@ fn infinite_iters() { fn potential_infinite_iters() { (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter - (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter + (1..) + .scan(0, |state, x| { + *state += x; + Some(*state) + }) + .min(); // maybe infinite iter (0..).find(|x| *x == 24); // maybe infinite iter (0..).position(|x| x == 24); // maybe infinite iter (0..).any(|x| x == 24); // maybe infinite iter diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 869b34e8ade..f9310321593 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -7,17 +7,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::trivially_copy_pass_by_ref)] - -fn fn_val(i: i32) -> i32 { unimplemented!() } -fn fn_constref(i: &i32) -> i32 { unimplemented!() } -fn fn_mutref(i: &mut i32) { unimplemented!() } -fn fooi() -> i32 { unimplemented!() } -fn foob() -> bool { unimplemented!() } +fn fn_val(i: i32) -> i32 { + unimplemented!() +} +fn fn_constref(i: &i32) -> i32 { + unimplemented!() +} +fn fn_mutref(i: &mut i32) { + unimplemented!() +} +fn fooi() -> i32 { + unimplemented!() +} +fn foob() -> bool { + unimplemented!() +} #[allow(clippy::many_single_char_names)] fn immutable_condition() { @@ -143,12 +149,15 @@ fn consts() { use std::cell::Cell; -fn maybe_i_mutate(i: &Cell) { unimplemented!() } +fn maybe_i_mutate(i: &Cell) { + unimplemented!() +} fn internally_mutable() { let b = Cell::new(true); - while b.get() { // b cannot be silently coerced to `bool` + while b.get() { + // b cannot be silently coerced to `bool` maybe_i_mutate(&b); println!("OK - Method call within condition"); } diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 8434d33f65e..d97e6d69941 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::inline_fn_without_body)] #![allow(clippy::inline_always)] @@ -18,15 +14,14 @@ trait Foo { #[inline] fn default_inline(); - #[inline(always)]fn always_inline(); + #[inline(always)] + fn always_inline(); #[inline(never)] fn never_inline(); #[inline] - fn has_body() { - } + fn has_body() {} } -fn main() { -} +fn main() {} diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index 8a0405321d0..ce6cd7888ee 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[allow(clippy::no_effect, clippy::unnecessary_operation)] #[warn(clippy::int_plus_one)] fn main() { diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 72aa6341a50..212234f0346 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -5,21 +5,21 @@ struct X; use std::collections::*; fn main() { - for _ in &[1,2,3] {} + for _ in &[1, 2, 3] {} for _ in vec![X, X] {} for _ in &vec![X, X] {} - for _ in [1,2,3].into_iter() {} //~ ERROR equivalent to .iter() + for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() - let _ = [1,2,3].into_iter(); //~ ERROR equivalent to .iter() - let _ = vec![1,2,3].into_iter(); - let _ = (&vec![1,2,3]).into_iter(); //~ WARN equivalent to .iter() - let _ = vec![1,2,3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() + let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() + let _ = vec![1, 2, 3].into_iter(); + let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() + let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() - let _ = (&&&&&&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&&&&mut &&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&mut &mut &mut [1,2,3]).into_iter(); //~ ERROR equivalent to .iter_mut() + let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() + let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() + let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs index 9fb6c7fd4b7..0ec356280b6 100644 --- a/tests/ui/invalid_ref.rs +++ b/tests/ui/invalid_ref.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused)] #![feature(core_intrinsics)] @@ -18,8 +14,8 @@ extern crate core; use std::intrinsics::{init, uninit}; fn main() { - let x = 1; - unsafe { + let x = 1; + unsafe { ref_to_zeroed_std(&x); ref_to_zeroed_core(&x); ref_to_zeroed_intr(&x); @@ -34,43 +30,41 @@ fn main() { } unsafe fn ref_to_zeroed_std(t: &T) { - let ref_zero: &T = std::mem::zeroed(); // warning + let ref_zero: &T = std::mem::zeroed(); // warning } unsafe fn ref_to_zeroed_core(t: &T) { - let ref_zero: &T = core::mem::zeroed(); // warning + let ref_zero: &T = core::mem::zeroed(); // warning } unsafe fn ref_to_zeroed_intr(t: &T) { - let ref_zero: &T = std::intrinsics::init(); // warning + let ref_zero: &T = std::intrinsics::init(); // warning } unsafe fn ref_to_uninit_std(t: &T) { - let ref_uninit: &T = std::mem::uninitialized(); // warning + let ref_uninit: &T = std::mem::uninitialized(); // warning } unsafe fn ref_to_uninit_core(t: &T) { - let ref_uninit: &T = core::mem::uninitialized(); // warning + let ref_uninit: &T = core::mem::uninitialized(); // warning } unsafe fn ref_to_uninit_intr(t: &T) { - let ref_uninit: &T = std::intrinsics::uninit(); // warning + let ref_uninit: &T = std::intrinsics::uninit(); // warning } fn some_ref() { - let some_ref = &1; + let some_ref = &1; } unsafe fn std_zeroed_no_ref() { - let mem_zero: usize = std::mem::zeroed(); // no warning + let mem_zero: usize = std::mem::zeroed(); // no warning } unsafe fn core_zeroed_no_ref() { - let mem_zero: usize = core::mem::zeroed(); // no warning + let mem_zero: usize = core::mem::zeroed(); // no warning } unsafe fn intr_init_no_ref() { let mem_zero: usize = std::intrinsics::init(); // no warning } - - diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 3e62f11006d..60f877b1ebe 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -7,14 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::invalid_upcast_comparisons)] -#![allow(unused, clippy::eq_op, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] - -fn mk_value() -> T { unimplemented!() } +#![allow( + unused, + clippy::eq_op, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::cast_lossless +)] + +fn mk_value() -> T { + unimplemented!() +} fn main() { let u32: u32 = mk_value(); @@ -55,7 +59,6 @@ fn main() { 1337 != (u8 as i32); 1337 != (u8 as u32); - // Those are Ok: (u8 as u32) > 20; 42 == (u8 as i32); diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs index 74a11925a76..5c6392811b9 100644 --- a/tests/ui/issue-3145.rs +++ b/tests/ui/issue-3145.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { println!("{}" a); //~ERROR expected token: `,` } diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index 070808f7b69..a54da0b6a96 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::while_let_on_iterator)] use std::iter::Iterator; diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index a4cc42f0d72..fca19350558 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -7,24 +7,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::items_after_statements)] fn ok() { - fn foo() { println!("foo"); } + fn foo() { + println!("foo"); + } foo(); } fn last() { foo(); - fn foo() { println!("foo"); } + fn foo() { + println!("foo"); + } } fn main() { foo(); - fn foo() { println!("foo"); } + fn foo() { + println!("foo"); + } foo(); } @@ -33,7 +36,9 @@ fn mac() { println!("{}", a); // do not lint this, because it needs to be after `a` macro_rules! b { - () => {{ a = 6 }} + () => {{ + a = 6 + }}; } b!(); println!("{}", a); diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index aad5c205041..80153efcb93 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -7,12 +7,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[warn(clippy::large_digit_groups)] #[allow(unused_variables)] fn main() { - let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); - let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); + let good = ( + 0b1011_i64, + 0o1_234_u32, + 0x1_234_567, + 1_2345_6789, + 1234_f32, + 1_234.12_f32, + 1_234.123_f32, + 1.123_4_f32, + ); + let bad = ( + 0b1_10110_i64, + 0x1_23456_78901_usize, + 1_23456_f32, + 1_23456.12_f32, + 1_23456.12345_f32, + 1_23456.12345_6_f32, + ); } diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index 419cb0ab428..29a73e68d43 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] #![allow(unused_variables)] #![warn(clippy::large_enum_variant)] diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index bc82e0bca04..7f4ba4f1523 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::len_without_is_empty, clippy::len_zero)] #![allow(dead_code, unused)] diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 080fa3b24b8..26fdc46ac17 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -7,15 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -#![allow(unused_variables, unused_assignments, clippy::similar_names, clippy::blacklisted_name)] +#![allow( + unused_variables, + unused_assignments, + clippy::similar_names, + clippy::blacklisted_name +)] #![warn(clippy::useless_let_if_seq)] -fn f() -> bool { true } -fn g(x: i32) -> i32 { x + 1 } +fn f() -> bool { + true +} +fn g(x: i32) -> i32 { + x + 1 +} fn issue985() -> i32 { let mut x = 42; @@ -73,8 +78,7 @@ fn main() { if f() { f(); bar = 42; - } - else { + } else { f(); } diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index 317aaf42b5c..eb012133376 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused)] - #![warn(clippy::let_and_return)] fn test() -> i32 { @@ -52,5 +48,4 @@ fn test_nowarn_4() -> i32 { x } -fn main() { -} +fn main() {} diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index d77bc8712bf..89cb190cc96 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -7,23 +7,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::let_unit_value)] #![allow(unused_variables)] macro_rules! let_and_return { ($n:expr) => {{ let ret = $n; - }} + }}; } fn main() { let _x = println!("x"); - let _y = 1; // this is fine - let _z = ((), 1); // this as well + let _y = 1; // this is fine + let _z = ((), 1); // this as well if true { let _a = (); } diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 77f25afe023..110868404bd 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -7,63 +7,89 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::needless_lifetimes, clippy::extra_unused_lifetimes)] #![allow(dead_code, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] -fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } +fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} -fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } +fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} -fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same lifetime on two params +fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {} // no error, same lifetime on two params -fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved +fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {} // no error, static involved -fn mut_and_static_input(_x: &mut u8, _y: &'static str) { } +fn mut_and_static_input(_x: &mut u8, _y: &'static str) {} -fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } +fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { + x +} -fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { x } // no error, multiple input refs +fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { + x +} // no error, multiple input refs -fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { x } // no error, multiple input refs +fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { + x +} // no error, multiple input refs -fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { x } // no error, static involved +fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { + x +} // no error, static involved -fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { Ok(x) } // no error +fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { + Ok(x) +} // no error -fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // no error, two input refs +fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { + x.unwrap() +} // no error, two input refs -fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } +fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { + Ok(x) +} // where clause, but without lifetimes -fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } +fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> +where + T: Copy, +{ + Ok(x) +} type Ref<'r> = &'r u8; -fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { } // no error, same lifetime on two params +fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} // no error, same lifetime on two params -fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } +fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} -fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounded lifetime +fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} // no error, bounded lifetime -fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) where 'b: 'a { } // no error, bounded lifetime +fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) +where + 'b: 'a, +{ +} // no error, bounded lifetime struct Lt<'a, I: 'static> { - x: &'a I + x: &'a I, } fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> - where F: Fn(Lt<'a, I>) -> Lt<'a, I> // no error, fn bound references 'a -{ unreachable!() } +where + F: Fn(Lt<'a, I>) -> Lt<'a, I>, // no error, fn bound references 'a +{ + unreachable!() +} fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> - where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> -{ unreachable!() } +where + for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, +{ + unreachable!() +} -fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { // no error, see below +fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { + // no error, see below f(x); } @@ -76,7 +102,11 @@ fn fn_bound_3_cannot_elide() { // no error, multiple input refs fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () { - if cond { x } else { f() } + if cond { + x + } else { + f() + } } struct X { @@ -84,13 +114,17 @@ struct X { } impl X { - fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } + fn self_and_out<'s>(&'s self) -> &'s u8 { + &self.x + } - fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { &self.x } // no error, multiple input refs + fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { + &self.x + } // no error, multiple input refs - fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } + fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} - fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params + fn self_and_same_in<'s>(&'s self, _x: &'s u8) {} // no error, same lifetimes on two params } struct Foo<'a>(&'a u8); @@ -104,50 +138,80 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { unimplemented!() } -fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } +fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes (named on the reference, anonymous on Foo) -fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { unimplemented!() } +fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes (anonymous on the reference, named on Foo) -fn struct_with_lt3<'a>(_foo: &Foo<'a> ) -> &'a str { unimplemented!() } +fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes -fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b> ) -> &'a str { unimplemented!() } +fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { + unimplemented!() +} trait WithLifetime<'a> {} type WithLifetimeAlias<'a> = WithLifetime<'a>; // should not warn because it won't build without the lifetime -fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str { unimplemented!() } +fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str { + unimplemented!() +} // this should warn because there is no lifetime on Drop, so this would be // unambiguous if we elided the lifetime -fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } +fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { + unimplemented!() +} type FooAlias<'a> = Foo<'a>; -fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } +fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes (named on the reference, anonymous on Foo) -fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { unimplemented!() } +fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes (anonymous on the reference, named on Foo) -fn alias_with_lt3<'a>(_foo: &FooAlias<'a> ) -> &'a str { unimplemented!() } +fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { + unimplemented!() +} // no warning, two input lifetimes -fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b> ) -> &'a str { unimplemented!() } +fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { + unimplemented!() +} -fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } +fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + unimplemented!() +} -fn elided_input_named_output<'a>(_arg: &str) -> &'a str { unimplemented!() } +fn elided_input_named_output<'a>(_arg: &str) -> &'a str { + unimplemented!() +} -fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } -fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { unimplemented!() } +fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { + unimplemented!() +} +fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { + unimplemented!() +} // don't warn on these, see #292 -fn trait_bound_bug<'a, T: WithLifetime<'a>>() { unimplemented!() } +fn trait_bound_bug<'a, T: WithLifetime<'a>>() { + unimplemented!() +} // #740 struct Test { @@ -160,7 +224,6 @@ impl Test { } } - trait LintContext<'a> {} fn f<'a, T: LintContext<'a>>(_: &T) {} @@ -172,9 +235,11 @@ fn test<'a>(x: &'a [u8]) -> u8 { // #3284 - Give a hint regarding lifetime in return type -struct Cow<'a> { x: &'a str, } -fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { unimplemented!() } - - -fn main() { +struct Cow<'a> { + x: &'a str, } +fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index c7e11840a37..1f2fcd8faf6 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -1,5 +1,4 @@ #![deny(clippy::internal)] - #![feature(rustc_private)] #[macro_use] @@ -28,5 +27,4 @@ impl lint::LintPass for Pass { } } -fn main() { -} +fn main() {} diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 162d8a484b4..e6fb37f8120 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 1b5c20069d1..99b90a0df79 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs index 7548b83764d..fe5e94cf458 100644 --- a/tests/ui/match_bool.rs +++ b/tests/ui/match_bool.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn match_bool() { let test: bool = true; @@ -24,31 +23,40 @@ fn match_bool() { match test { true => (), - false => { println!("Noooo!"); } + false => { + println!("Noooo!"); + }, }; match test { - false => { println!("Noooo!"); } + false => { + println!("Noooo!"); + }, _ => (), }; match test && test { - false => { println!("Noooo!"); } + false => { + println!("Noooo!"); + }, _ => (), }; match test { - false => { println!("Noooo!"); } - true => { println!("Yes!"); } + false => { + println!("Noooo!"); + }, + true => { + println!("Yes!"); + }, }; // Not linted match option { - 1 ... 10 => 1, - 11 ... 20 => 2, + 1...10 => 1, + 11...20 => 2, _ => 3, }; } -fn main() { -} +fn main() {} diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs index 1f2c3f8a891..5350f933ae5 100644 --- a/tests/ui/match_overlapping_arm.rs +++ b/tests/ui/match_overlapping_arm.rs @@ -14,54 +14,54 @@ /// Tests for match_overlapping_arm fn overlapping() { - const FOO : u64 = 2; + const FOO: u64 = 2; match 42 { - 0 ... 10 => println!("0 ... 10"), - 0 ... 11 => println!("0 ... 11"), + 0...10 => println!("0 ... 10"), + 0...11 => println!("0 ... 11"), _ => (), } match 42 { - 0 ... 5 => println!("0 ... 5"), - 6 ... 7 => println!("6 ... 7"), - FOO ... 11 => println!("0 ... 11"), + 0...5 => println!("0 ... 5"), + 6...7 => println!("6 ... 7"), + FOO...11 => println!("0 ... 11"), _ => (), } match 42 { 2 => println!("2"), - 0 ... 5 => println!("0 ... 5"), + 0...5 => println!("0 ... 5"), _ => (), } match 42 { 2 => println!("2"), - 0 ... 2 => println!("0 ... 2"), + 0...2 => println!("0 ... 2"), _ => (), } match 42 { - 0 ... 10 => println!("0 ... 10"), - 11 ... 50 => println!("11 ... 50"), + 0...10 => println!("0 ... 10"), + 11...50 => println!("11 ... 50"), _ => (), } match 42 { 2 => println!("2"), - 0 .. 2 => println!("0 .. 2"), + 0..2 => println!("0 .. 2"), _ => (), } match 42 { - 0 .. 10 => println!("0 .. 10"), - 10 .. 50 => println!("10 .. 50"), + 0..10 => println!("0 .. 10"), + 10..50 => println!("10 .. 50"), _ => (), } match 42 { - 0 .. 11 => println!("0 .. 11"), - 0 ... 11 => println!("0 ... 11"), + 0..11 => println!("0 .. 11"), + 0...11 => println!("0 ... 11"), _ => (), } diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index e5b8f6f4c1c..8038433c564 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -7,18 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![feature(exclusive_range_pattern)] - - #![warn(clippy::all)] #![allow(unused, clippy::redundant_pattern_matching)] #![warn(clippy::match_same_arms)] - -fn dummy() { -} +fn dummy() {} fn ref_pats() { { @@ -27,12 +21,13 @@ fn ref_pats() { &Some(v) => println!("{:?}", v), &None => println!("none"), } - match v { // this doesn't trigger, we have a different pattern + match v { + // this doesn't trigger, we have a different pattern &Some(v) => println!("some"), other => println!("other"), } } - let tup =& (1, 2); + let tup = &(1, 2); match tup { &(v, 1) => println!("{}", v), _ => println!("none"), @@ -66,73 +61,77 @@ fn match_wild_err_arm() { match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => panic!("err") + Err(_) => panic!("err"), } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => {panic!()} + Err(_) => panic!(), } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => {panic!();} + Err(_) => { + panic!(); + }, } // allowed when not with `panic!` block match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => println!("err") + Err(_) => println!("err"), } // allowed when used with `unreachable!` match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => {unreachable!()} + Err(_) => unreachable!(), } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => unreachable!() + Err(_) => unreachable!(), } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => {unreachable!();} + Err(_) => { + unreachable!(); + }, } // no warning because of the guard match x { - Ok(x) if x*x == 64 => println!("ok"), + Ok(x) if x * x == 64 => println!("ok"), Ok(_) => println!("ok"), - Err(_) => println!("err") + Err(_) => println!("err"), } // this used to be a false positive, see #1996 match x { Ok(3) => println!("ok"), - Ok(x) if x*x == 64 => println!("ok 64"), + Ok(x) if x * x == 64 => println!("ok 64"), Ok(_) => println!("ok"), - Err(_) => println!("err") + Err(_) => println!("err"), } match (x, Some(1i32)) { (Ok(x), Some(_)) => println!("ok {}", x), (Ok(_), Some(x)) => println!("ok {}", x), - _ => println!("err") + _ => println!("err"), } // no warning because of the different types for x match (x, Some(1.0f64)) { (Ok(x), Some(_)) => println!("ok {}", x), (Ok(_), Some(x)) => println!("ok {}", x), - _ => println!("err") + _ => println!("err"), } // because of a bug, no warning was generated for this case before #2251 @@ -140,7 +139,9 @@ fn match_wild_err_arm() { Ok(_tmp) => println!("ok"), Ok(3) => println!("ok"), Ok(_) => println!("ok"), - Err(_) => {unreachable!();} + Err(_) => { + unreachable!(); + }, } } @@ -156,8 +157,6 @@ fn match_as_ref() { None => None, Some(ref mut v) => Some(v), }; - } -fn main() { -} +fn main() {} diff --git a/tests/ui/mem_discriminant.rs b/tests/ui/mem_discriminant.rs index 5ddd90ac8b5..9d2d6f9503a 100644 --- a/tests/ui/mem_discriminant.rs +++ b/tests/ui/mem_discriminant.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![deny(clippy::mem_discriminant_non_enum)] use std::mem; @@ -35,7 +34,9 @@ fn main() { mem::discriminant(&rro); macro_rules! mem_discriminant_but_in_a_macro { - ($param:expr) => (mem::discriminant($param)) + ($param:expr) => { + mem::discriminant($param) + }; } mem_discriminant_but_in_a_macro!(&rro); diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 266c5c267f8..b46f7007cd0 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -7,16 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - - -use std::sync::Arc; use std::rc::Rc; +use std::sync::Arc; -use std::mem::forget as forgetSomething; use std::mem as memstuff; +use std::mem::forget as forgetSomething; #[warn(clippy::mem_forget)] #[allow(clippy::forget_copy)] diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 2b6e6f2ce67..edd3c031857 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] use std::mem; diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index b4ca46231e0..cf68bb61100 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -7,17 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] -use std::cmp::{min, max}; -use std::cmp::min as my_min; use std::cmp::max as my_max; +use std::cmp::min as my_min; +use std::cmp::{max, min}; -const LARGE : usize = 3; +const LARGE: usize = 3; fn main() { let x; diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index 6e7dfbfa37a..5de2ada5a41 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - /* This file incorporates work covered by the following copyright and * permission notice: * Copyright 2013 The Rust Project Developers. See the COPYRIGHT @@ -23,17 +20,14 @@ * except according to those terms. */ - - #![warn(clippy::missing_docs_in_private_items)] - // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. #![allow(dead_code)] #![feature(associated_type_defaults)] //! Some garbage docs for the crate here -#![doc="More garbage"] +#![doc = "More garbage"] type Typedef = String; pub type PubTypedef = String; @@ -61,7 +55,8 @@ pub mod pub_module_no_dox {} pub fn foo() {} pub fn foo2() {} fn foo3() {} -#[allow(clippy::missing_docs_in_private_items)] pub fn foo4() {} +#[allow(clippy::missing_docs_in_private_items)] +pub fn foo4() {} /// dox pub trait A { @@ -84,7 +79,7 @@ pub trait C { #[allow(clippy::missing_docs_in_private_items)] pub trait D { - fn dummy(&self) { } + fn dummy(&self) {} } /// dox @@ -110,7 +105,8 @@ impl PubFoo { /// dox pub fn foo1() {} fn foo2() {} - #[allow(clippy::missing_docs_in_private_items)] pub fn foo3() {} + #[allow(clippy::missing_docs_in_private_items)] + pub fn foo3() {} } #[allow(clippy::missing_docs_in_private_items)] @@ -136,17 +132,12 @@ mod a { } enum Baz { - BazA { - a: isize, - b: isize - }, - BarB + BazA { a: isize, b: isize }, + BarB, } pub enum PubBaz { - PubBazA { - a: isize, - }, + PubBazA { a: isize }, } /// dox @@ -160,15 +151,12 @@ pub enum PubBaz2 { #[allow(clippy::missing_docs_in_private_items)] pub enum PubBaz3 { - PubBaz3A { - b: isize - }, + PubBaz3A { b: isize }, } #[doc(hidden)] pub fn baz() {} - const FOO: u32 = 0; /// dox pub const FOO1: u32 = 0; @@ -178,7 +166,6 @@ pub const FOO2: u32 = 0; pub const FOO3: u32 = 0; pub const FOO4: u32 = 0; - static BAR: u32 = 0; /// dox pub static BAR1: u32 = 0; @@ -188,7 +175,6 @@ pub static BAR2: u32 = 0; pub static BAR3: u32 = 0; pub static BAR4: u32 = 0; - mod internal_impl { /// dox pub fn documented() {} @@ -206,9 +192,9 @@ mod internal_impl { /// dox pub mod public_interface { pub use internal_impl::documented as foo; + pub use internal_impl::globbed::*; pub use internal_impl::undocumented1 as bar; pub use internal_impl::{documented, undocumented2}; - pub use internal_impl::globbed::*; } fn main() {} diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 0b86c4e5cfe..c9e946e14e6 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - /* This file incorporates work covered by the following copyright and * permission notice: * Copyright 2013 The Rust Project Developers. See the COPYRIGHT @@ -32,7 +29,7 @@ type Typedef = String; pub type PubTypedef = String; struct Foo {} // ok -pub struct PubFoo { } // ok +pub struct PubFoo {} // ok enum FooE {} // ok pub enum PubFooE {} // ok @@ -41,8 +38,10 @@ pub mod pub_module {} // ok fn foo() {} pub fn pub_foo() {} // missing #[inline] -#[inline] pub fn pub_foo_inline() {} // ok -#[inline(always)] pub fn pub_foo_inline_always() {} // ok +#[inline] +pub fn pub_foo_inline() {} // ok +#[inline(always)] +pub fn pub_foo_inline_always() {} // ok #[allow(clippy::missing_inline_in_public_items)] pub fn pub_foo_no_inline() {} @@ -52,11 +51,11 @@ trait Bar { fn Bar_b() {} // ok } - pub trait PubBar { fn PubBar_a(); // ok fn PubBar_b() {} // missing #[inline] - #[inline] fn PubBar_c() {} // ok + #[inline] + fn PubBar_c() {} // ok } // none of these need inline because Foo is not exported diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index 0676c4c29f0..730055931c4 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::module_inception)] mod foo { @@ -27,8 +24,7 @@ mod foo { // No warning. See . mod bar { #[allow(clippy::module_inception)] - mod bar { - } + mod bar {} } fn main() {} diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index f1576447708..f7c0c16abad 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::modulo_one)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 0a68d449d92..8a9da42083d 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::mut_from_ref)] diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index bed872902af..e8239007cb3 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -7,26 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::mut_mut)] - - - -fn fun(x : &mut &mut u32) -> bool { +fn fun(x: &mut &mut u32) -> bool { **x > 0 } -fn less_fun(x : *mut *mut u32) { - let y = x; +fn less_fun(x: *mut *mut u32) { + let y = x; } macro_rules! mut_ptr { - ($p:expr) => { &mut $p } + ($p:expr) => { + &mut $p + }; } #[allow(unused_mut, unused_variables)] @@ -37,12 +32,12 @@ fn main() { } if fun(x) { - let y : &mut &mut u32 = &mut &mut 2; + let y: &mut &mut u32 = &mut &mut 2; **y + **x; } if fun(x) { - let y : &mut &mut &mut u32 = &mut &mut &mut 2; + let y: &mut &mut &mut u32 = &mut &mut &mut 2; ***y + **x; } diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs index edc86b5d6ac..23dddcdd158 100644 --- a/tests/ui/mut_range_bound.rs +++ b/tests/ui/mut_range_bound.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused)] fn main() { @@ -25,29 +21,38 @@ fn main() { fn mut_range_bound_upper() { let mut m = 4; - for i in 0..m { m = 5; } // warning + for i in 0..m { + m = 5; + } // warning } fn mut_range_bound_lower() { let mut m = 4; - for i in m..10 { m *= 2; } // warning + for i in m..10 { + m *= 2; + } // warning } fn mut_range_bound_both() { let mut m = 4; let mut n = 6; - for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) + for i in m..n { + m = 5; + n = 7; + } // warning (1 for each mutated bound) } fn mut_range_bound_no_mutation() { let mut m = 4; - for i in 0..m { continue; } // no warning + for i in 0..m { + continue; + } // no warning } fn mut_borrow_range_bound() { let mut m = 4; for i in 0..m { - let n = &mut m; // warning + let n = &mut m; // warning *n += 1; } } @@ -55,12 +60,13 @@ fn mut_borrow_range_bound() { fn immut_borrow_range_bound() { let mut m = 4; for i in 0..m { - let n = &m; // should be no warning? + let n = &m; // should be no warning? } } - fn immut_range_bound() { let m = 4; - for i in 0..m { continue; } // no warning + for i in 0..m { + continue; + } // no warning } diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index d63b854fd09..882ed7e1dd3 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused_variables, clippy::trivially_copy_pass_by_ref)] fn takes_an_immutable_reference(a: &i32) {} @@ -19,11 +15,9 @@ fn takes_a_mutable_reference(a: &mut i32) {} struct MyStruct; impl MyStruct { - fn takes_an_immutable_reference(&self, a: &i32) { - } + fn takes_an_immutable_reference(&self, a: &i32) {} - fn takes_a_mutable_reference(&self, a: &mut i32) { - } + fn takes_a_mutable_reference(&self, a: &mut i32) {} } #[warn(clippy::unnecessary_mut_passed)] @@ -37,7 +31,6 @@ fn main() { let my_struct = MyStruct; my_struct.takes_an_immutable_reference(&mut 42); - // No error // Functions diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index 87b4ac9d8e3..5c4e180408c 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![warn(clippy::mutex_integer)] diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 98c2e0767d6..c82f102c294 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![warn(clippy::needless_bool)] use std::cell::Cell; @@ -38,12 +37,36 @@ macro_rules! bool_comparison_trigger { fn main() { let x = true; let y = false; - if x { true } else { true }; - if x { false } else { false }; - if x { true } else { false }; - if x { false } else { true }; - if x && y { false } else { true }; - if x { x } else { false }; // would also be questionable, but we don't catch this yet + if x { + true + } else { + true + }; + if x { + false + } else { + false + }; + if x { + true + } else { + false + }; + if x { + false + } else { + true + }; + if x && y { + false + } else { + true + }; + if x { + x + } else { + false + }; // would also be questionable, but we don't catch this yet bool_ret(x); bool_ret2(x); bool_ret3(x); @@ -57,50 +80,73 @@ fn main() { #[allow(clippy::if_same_then_else, clippy::needless_return)] fn bool_ret(x: bool) -> bool { - if x { return true } else { return true }; + if x { + return true; + } else { + return true; + }; } #[allow(clippy::if_same_then_else, clippy::needless_return)] fn bool_ret2(x: bool) -> bool { - if x { return false } else { return false }; + if x { + return false; + } else { + return false; + }; } #[allow(clippy::needless_return)] fn bool_ret3(x: bool) -> bool { - if x { return true } else { return false }; + if x { + return true; + } else { + return false; + }; } #[allow(clippy::needless_return)] fn bool_ret5(x: bool, y: bool) -> bool { - if x && y { return true } else { return false }; + if x && y { + return true; + } else { + return false; + }; } #[allow(clippy::needless_return)] fn bool_ret4(x: bool) -> bool { - if x { return false } else { return true }; + if x { + return false; + } else { + return true; + }; } #[allow(clippy::needless_return)] fn bool_ret6(x: bool, y: bool) -> bool { - if x && y { return false } else { return true }; + if x && y { + return false; + } else { + return true; + }; } fn needless_bool(x: bool) { - if x == true { }; + if x == true {}; } fn needless_bool2(x: bool) { - if x == false { }; + if x == false {}; } fn needless_bool3(x: bool) { - bool_comparison_trigger! { test_one: false, false; test_three: false, false; test_two: true, true; } - - if x == true { }; - if x == false { }; + + if x == true {}; + if x == false {}; } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 29e6ccca94d..bfc6e82cb55 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - use std::borrow::Cow; #[allow(clippy::trivially_copy_pass_by_ref)] @@ -41,7 +38,7 @@ fn main() { }; } -fn f(y: &T) -> T { +fn f(y: &T) -> T { *y } diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index ca3e60bd7e7..3897c86f53a 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::needless_borrowed_reference)] #[allow(unused_variables)] fn main() { @@ -51,8 +47,6 @@ fn foo(a: &Animal, b: &Animal) { match (a, b) { (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' // ^ and ^ should *not* be linted - (&Animal::Dog(ref a), &Animal::Dog(_)) => () - // ^ should *not* be linted + (&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should *not* be linted } } - diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 91ebd354146..df449e3184f 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -7,10 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -use std::collections::{HashMap, HashSet, BTreeSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] #[allow(unused_variables, clippy::iter_cloned_collect)] diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 3d91132ea62..6d9b9499dce 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - macro_rules! zero { - ($x:expr) => ($x == 0); + ($x:expr) => { + $x == 0 + }; } macro_rules! nonzero { - ($x:expr) => (!zero!($x)); + ($x:expr) => { + !zero!($x) + }; } #[warn(clippy::needless_continue)] @@ -27,9 +27,9 @@ fn main() { if i % 2 == 0 && i % 3 == 0 { println!("{}", i); - println!("{}", i+1); + println!("{}", i + 1); if i % 5 == 0 { - println!("{}", i+2); + println!("{}", i + 2); } let i = 0; println!("bar {} ", i); diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 48b7b42cc8c..ec9df9fb3d3 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -7,11 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::needless_pass_by_value)] -#![allow(dead_code, clippy::single_match, clippy::redundant_pattern_matching, clippy::many_single_char_names, clippy::option_option)] +#![allow( + dead_code, + clippy::single_match, + clippy::redundant_pattern_matching, + clippy::many_single_char_names, + clippy::option_option +)] use std::borrow::Borrow; use std::convert::AsRef; @@ -92,24 +95,19 @@ struct S(T, U); impl S { fn foo( - self, // taking `self` by value is always allowed + self, + // taking `self` by value is always allowed s: String, t: String, ) -> usize { s.len() + t.capacity() } - fn bar( - _t: T, // Ok, since `&T: Serialize` too + fn bar(_t: T // Ok, since `&T: Serialize` too ) { } - fn baz( - &self, - _u: U, - _s: Self, - ) { - } + fn baz(&self, _u: U, _s: Self) {} } trait FalsePositive { @@ -120,7 +118,9 @@ trait FalsePositive { } // shouldn't warn on extern funcs -extern "C" fn ext(x: String) -> usize { x.len() } +extern "C" fn ext(x: String) -> usize { + x.len() +} // whitelist RangeArgument fn range>(range: T) { diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index f8f279ccb66..28f71d98fe7 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![crate_type = "proc-macro"] #![warn(clippy::needless_pass_by_value)] @@ -18,4 +15,6 @@ extern crate proc_macro; use proc_macro::TokenStream; #[proc_macro_derive(Foo)] -pub fn foo(_input: TokenStream) -> TokenStream { unimplemented!() } +pub fn foo(_input: TokenStream) -> TokenStream { + unimplemented!() +} diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index c1992bba548..f3d47eede48 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn calc_idx(i: usize) -> usize { (i + i + 20) % 4 } @@ -51,7 +50,7 @@ fn main() { let g = vec![1, 2, 3, 4, 5, 6]; let glen = g.len(); for i in 0..glen { - let x: u32 = g[i+1..].iter().sum(); + let x: u32 = g[i + 1..].iter().sum(); println!("{}", g[i] + x); } assert_eq!(g, vec![20, 18, 15, 11, 6, 0]); @@ -59,7 +58,7 @@ fn main() { let mut g = vec![1, 2, 3, 4, 5, 6]; let glen = g.len(); for i in 0..glen { - g[i] = g[i+1..].iter().sum(); + g[i] = g[i + 1..].iter().sum(); } assert_eq!(g, vec![20, 18, 15, 11, 6, 0]); @@ -77,7 +76,7 @@ fn main() { vec[i] += 1; } - let arr = [1,2,3]; + let arr = [1, 2, 3]; for i in 0..3 { println!("{}", arr[i]); diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 9380f7c48a5..101be5946f4 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::needless_return)] fn test_end_of_fn() -> bool { @@ -22,7 +18,7 @@ fn test_end_of_fn() -> bool { } fn test_no_semicolon() -> bool { - return true + return true; } fn test_if_block() -> bool { @@ -38,7 +34,7 @@ fn test_match(x: bool) -> bool { true => return false, false => { return true; - } + }, } } diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 974f3603fc6..891c446b0ea 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::needless_update)] #![allow(clippy::no_effect)] diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 6d26d2ec6d1..6c132f85f0a 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - //! This test case utilizes `f64` an easy example for `PartialOrd` only types //! but the lint itself actually validates any expression where the left //! operand implements `PartialOrd` but not `Ord`. @@ -18,13 +15,11 @@ use std::cmp::Ordering; #[warn(clippy::neg_cmp_op_on_partial_ord)] fn main() { - let a_value = 1.0; let another_value = 7.0; // --- Bad --- - // Not Less but potentially Greater, Equal or Uncomparable. let _not_less = !(a_value < another_value); @@ -37,12 +32,10 @@ fn main() { // Not Greater or Equal but potentially Less or Uncomparable. let _not_greater_or_equal = !(a_value >= another_value); - // --- Good --- - let _not_less = match a_value.partial_cmp(&another_value) { - None | Some(Ordering::Greater) | Some(Ordering::Equal) => true, + None | Some(Ordering::Greater) | Some(Ordering::Equal) => true, _ => false, }; let _not_less_or_equal = match a_value.partial_cmp(&another_value) { @@ -58,10 +51,8 @@ fn main() { _ => false, }; - // --- Should not trigger --- - let _ = a_value < another_value; let _ = a_value <= another_value; let _ = a_value > another_value; diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 446af7bbe94..f5f7525922c 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::neg_multiply)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index b952b1197dd..d5a108b0b27 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -7,17 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![allow(clippy::single_match, unused_assignments, unused_variables, clippy::while_immutable_condition)] +#![allow( + clippy::single_match, + unused_assignments, + unused_variables, + clippy::while_immutable_condition +)] fn test1() { let mut x = 0; - loop { // clippy::never_loop + loop { + // clippy::never_loop x += 1; if x == 1 { - return + return; } break; } @@ -28,16 +31,17 @@ fn test2() { loop { x += 1; if x == 1 { - break + break; } } } fn test3() { let mut x = 0; - loop { // never loops + loop { + // never loops x += 1; - break + break; } } @@ -54,24 +58,29 @@ fn test4() { fn test5() { let i = 0; - loop { // never loops - while i == 0 { // never loops - break + loop { + // never loops + while i == 0 { + // never loops + break; } - return - } + return; + } } fn test6() { let mut x = 0; 'outer: loop { x += 1; - loop { // never loops - if x == 5 { break } - continue 'outer - } - return - } + loop { + // never loops + if x == 5 { + break; + } + continue 'outer; + } + return; + } } fn test7() { @@ -82,7 +91,7 @@ fn test7() { 1 => continue, _ => (), } - return + return; } } @@ -99,13 +108,15 @@ fn test8() { fn test9() { let x = Some(1); - while let Some(y) = x { // never loops - return + while let Some(y) = x { + // never loops + return; } } fn test10() { - for x in 0..10 { // never loops + for x in 0..10 { + // never loops match x { 1 => break, _ => return, @@ -118,7 +129,7 @@ fn test11 i32>(mut f: F) { return match f() { 1 => continue, _ => (), - } + }; } } @@ -138,7 +149,8 @@ pub fn test12(a: bool, b: bool) { pub fn test13() { let mut a = true; - loop { // infinite loop + loop { + // infinite loop while a { if true { a = false; @@ -151,11 +163,12 @@ pub fn test13() { pub fn test14() { let mut a = true; - 'outer: while a { // never loops + 'outer: while a { + // never loops while a { if a { a = false; - continue + continue; } } break 'outer; @@ -187,4 +200,3 @@ fn main() { test13(); test14(); } - diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index bed43f550f2..a31f046c084 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -1,7 +1,7 @@ #![warn(clippy::new_ret_no_self)] #![allow(dead_code, clippy::trivially_copy_pass_by_ref)] -fn main(){} +fn main() {} trait R { type Item; @@ -96,82 +96,106 @@ struct TupleReturnerOk; impl TupleReturnerOk { // should not trigger lint - pub fn new() -> (Self, u32) { unimplemented!(); } + pub fn new() -> (Self, u32) { + unimplemented!(); + } } struct TupleReturnerOk2; impl TupleReturnerOk2 { // should not trigger lint (it doesn't matter which element in the tuple is Self) - pub fn new() -> (u32, Self) { unimplemented!(); } + pub fn new() -> (u32, Self) { + unimplemented!(); + } } struct TupleReturnerOk3; impl TupleReturnerOk3 { // should not trigger lint (tuple can contain multiple Self) - pub fn new() -> (Self, Self) { unimplemented!(); } + pub fn new() -> (Self, Self) { + unimplemented!(); + } } struct TupleReturnerBad; impl TupleReturnerBad { // should trigger lint - pub fn new() -> (u32, u32) { unimplemented!(); } + pub fn new() -> (u32, u32) { + unimplemented!(); + } } struct MutPointerReturnerOk; impl MutPointerReturnerOk { // should not trigger lint - pub fn new() -> *mut Self { unimplemented!(); } + pub fn new() -> *mut Self { + unimplemented!(); + } } struct MutPointerReturnerOk2; impl MutPointerReturnerOk2 { // should not trigger lint - pub fn new() -> *const Self { unimplemented!(); } + pub fn new() -> *const Self { + unimplemented!(); + } } struct MutPointerReturnerBad; impl MutPointerReturnerBad { // should trigger lint - pub fn new() -> *mut V { unimplemented!(); } + pub fn new() -> *mut V { + unimplemented!(); + } } struct GenericReturnerOk; impl GenericReturnerOk { // should not trigger lint - pub fn new() -> Option { unimplemented!(); } + pub fn new() -> Option { + unimplemented!(); + } } struct GenericReturnerBad; impl GenericReturnerBad { // should trigger lint - pub fn new() -> Option { unimplemented!(); } + pub fn new() -> Option { + unimplemented!(); + } } struct NestedReturnerOk; impl NestedReturnerOk { // should not trigger lint - pub fn new() -> (Option, u32) { unimplemented!(); } + pub fn new() -> (Option, u32) { + unimplemented!(); + } } struct NestedReturnerOk2; impl NestedReturnerOk2 { // should not trigger lint - pub fn new() -> ((Self, u32), u32) { unimplemented!(); } + pub fn new() -> ((Self, u32), u32) { + unimplemented!(); + } } struct NestedReturnerOk3; impl NestedReturnerOk3 { // should not trigger lint - pub fn new() -> Option<(Self, u32)> { unimplemented!(); } + pub fn new() -> Option<(Self, u32)> { + unimplemented!(); + } } diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 16b9bd5c71b..a1818e037a7 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -7,41 +7,46 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(const_fn)] - - #![allow(dead_code)] #![warn(clippy::new_without_default, clippy::new_without_default_derive)] pub struct Foo; impl Foo { - pub fn new() -> Foo { Foo } + pub fn new() -> Foo { + Foo + } } pub struct Bar; impl Bar { - pub fn new() -> Self { Bar } + pub fn new() -> Self { + Bar + } } pub struct Ok; impl Ok { - pub fn new() -> Self { Ok } + pub fn new() -> Self { + Ok + } } impl Default for Ok { - fn default() -> Self { Ok } + fn default() -> Self { + Ok + } } pub struct Params; impl Params { - pub fn new(_: u32) -> Self { Params } + pub fn new(_: u32) -> Self { + Params + } } pub struct GenericsOk { @@ -49,11 +54,15 @@ pub struct GenericsOk { } impl Default for GenericsOk { - fn default() -> Self { unimplemented!(); } + fn default() -> Self { + unimplemented!(); + } } impl<'c, V> GenericsOk { - pub fn new() -> GenericsOk { unimplemented!() } + pub fn new() -> GenericsOk { + unimplemented!() + } } pub struct LtOk<'a> { @@ -61,11 +70,15 @@ pub struct LtOk<'a> { } impl<'b> Default for LtOk<'b> { - fn default() -> Self { unimplemented!(); } + fn default() -> Self { + unimplemented!(); + } } impl<'c> LtOk<'c> { - pub fn new() -> LtOk<'c> { unimplemented!() } + pub fn new() -> LtOk<'c> { + unimplemented!() + } } pub struct LtKo<'a> { @@ -73,26 +86,34 @@ pub struct LtKo<'a> { } impl<'c> LtKo<'c> { - pub fn new() -> LtKo<'c> { unimplemented!() } + pub fn new() -> LtKo<'c> { + unimplemented!() + } // FIXME: that suggestion is missing lifetimes } struct Private; impl Private { - fn new() -> Private { unimplemented!() } // We don't lint private items + fn new() -> Private { + unimplemented!() + } // We don't lint private items } struct Const; impl Const { - pub const fn new() -> Const { Const } // const fns can't be implemented via Default + pub const fn new() -> Const { + Const + } // const fns can't be implemented via Default } pub struct IgnoreGenericNew; impl IgnoreGenericNew { - pub fn new() -> Self { IgnoreGenericNew } // the derived Default does not make sense here as the result depends on T + pub fn new() -> Self { + IgnoreGenericNew + } // the derived Default does not make sense here as the result depends on T } pub trait TraitWithNew: Sized { @@ -104,7 +125,9 @@ pub trait TraitWithNew: Sized { pub struct IgnoreUnsafeNew; impl IgnoreUnsafeNew { - pub unsafe fn new() -> Self { IgnoreUnsafeNew } + pub unsafe fn new() -> Self { + IgnoreUnsafeNew + } } #[derive(Default)] diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index bee3aeb6f7f..6b51c50dcde 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -7,12 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(box_syntax)] - - #![warn(clippy::no_effect)] #![allow(dead_code)] #![allow(path_statements)] @@ -23,7 +18,7 @@ struct Unit; struct Tuple(i32); struct Struct { - field: i32 + field: i32, } enum Enum { Tuple(i32), @@ -34,7 +29,7 @@ impl Drop for DropUnit { fn drop(&mut self) {} } struct DropStruct { - field: i32 + field: i32, } impl Drop for DropStruct { fn drop(&mut self) {} @@ -58,11 +53,19 @@ union Union { b: f64, } -fn get_number() -> i32 { 0 } -fn get_struct() -> Struct { Struct { field: 0 } } -fn get_drop_struct() -> DropStruct { DropStruct { field: 0 } } +fn get_number() -> i32 { + 0 +} +fn get_struct() -> Struct { + Struct { field: 0 } +} +fn get_drop_struct() -> DropStruct { + DropStruct { field: 0 } +} -unsafe fn unsafe_fn() -> i32 { 0 } +unsafe fn unsafe_fn() -> i32 { + 0 +} fn main() { let s = get_struct(); diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index 5cbb610fea3..591e1994ee3 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -7,17 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(const_string_new, const_vec_new)] #![allow(clippy::ref_in_deref, dead_code)] -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; -use std::cell::Cell; -use std::sync::Once; use std::borrow::Cow; +use std::cell::Cell; use std::fmt::Display; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; +use std::sync::Once; const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable const CELL: Cell = Cell::new(6); //~ ERROR interior mutable @@ -25,7 +22,9 @@ const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::n //~^ ERROR interior mutable macro_rules! declare_const { - ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; + ($name:ident: $ty:ty = $e:expr) => { + const $name: $ty = $e; + }; } declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable @@ -136,7 +135,7 @@ fn main() { let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability let _ = ATOMIC_TUPLE.1.into_iter(); let _ = ATOMIC_TUPLE.2; - let _ = &{ATOMIC_TUPLE}; + let _ = &{ ATOMIC_TUPLE }; CELL.set(2); //~ ERROR interior mutability assert_eq!(CELL.get(), 6); //~ ERROR interior mutability diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 67fded14485..86c9edc821d 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -7,13 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![warn(clippy::all,clippy::similar_names)] +#![warn(clippy::all, clippy::similar_names)] #![allow(unused, clippy::println_empty_string)] - struct Foo { apple: i32, bpple: i32, @@ -29,7 +25,6 @@ fn main() { let cpple: i32; - let a_bar: i32; let b_bar: i32; let c_bar: i32; @@ -54,7 +49,6 @@ fn main() { let blubx: i32; let bluby: i32; - let cake: i32; let cakes: i32; let coke: i32; @@ -81,7 +75,6 @@ fn main() { let parsed: i32; let parsee: i32; - let setter: i32; let getter: i32; let tx1: i32; @@ -92,8 +85,10 @@ fn main() { fn foo() { let Foo { apple, bpple } = unimplemented!(); - let Foo { apple: spring, - bpple: sprang } = unimplemented!(); + let Foo { + apple: spring, + bpple: sprang, + } = unimplemented!(); } #[derive(Clone, Debug)] @@ -132,7 +127,6 @@ fn bla() { { let e: i32; let f: i32; - } match 5 { 1 => println!(""), @@ -149,18 +143,18 @@ fn underscores_and_numbers() { let _1 = 1; //~ERROR Consider a more descriptive name let ____1 = 1; //~ERROR Consider a more descriptive name let __1___2 = 12; //~ERROR Consider a more descriptive name - let _1_ok= 1; + let _1_ok = 1; } fn issue2927() { - let args = 1; - format!("{:?}", 2); + let args = 1; + format!("{:?}", 2); } fn issue3078() { match "a" { stringify!(a) => {}, - _ => {} + _ => {}, } } @@ -171,7 +165,7 @@ impl Bar { let _1 = 1; let ____1 = 1; let __1___2 = 12; - let _1_ok= 1; + let _1_ok = 1; } } diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index 5d333a72cc0..b121aae788c 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::io; struct MyError(()); // doesn't implement Debug #[derive(Debug)] struct MyErrorWithParam { - x: T + x: T, } fn main() { @@ -26,7 +25,7 @@ fn main() { // the error type implements `Debug` let res2: Result = Ok(0); res2.ok().expect("oh noes!"); - let res3: Result>= Ok(0); + let res3: Result> = Ok(0); res3.ok().expect("whoof"); let res4: Result = Ok(0); res4.ok().expect("argh"); diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index b318a90d883..3ede64ce3aa 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::if_let_some_result)] fn str_to_int(x: &str) -> i32 { diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index bacf9f1057b..1112b6794cf 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused_variables, clippy::blacklisted_name)] use std::collections::HashSet; diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 6b891d72e8b..f4d0af94b3f 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - use std::fs::OpenOptions; #[allow(unused_must_use)] diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index b023181fcf7..5200ff694a0 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::option_map_unit_fn)] #![allow(unused)] @@ -39,7 +36,7 @@ fn option_map_unit_fn() { let x = HasOption { field: Some(10) }; x.field.map(plus_one); - let _ : Option<()> = x.field.map(do_nothing); + let _: Option<()> = x.field.map(do_nothing); x.field.map(do_nothing); @@ -48,47 +45,68 @@ fn option_map_unit_fn() { x.field.map(diverge); let captured = 10; - if let Some(value) = x.field { do_nothing(value + captured) }; - let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); + if let Some(value) = x.field { + do_nothing(value + captured) + }; + let _: Option<()> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_option_nothing(value + captured)); - x.field.map(|value| { x.do_option_plus_one(value + captured); }); - + x.field.map(|value| { + x.do_option_plus_one(value + captured); + }); x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { do_nothing(value + captured) }); - - x.field.map(|value| { do_nothing(value + captured); }); + x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { { do_nothing(value + captured); } }); + x.field.map(|value| { + do_nothing(value + captured); + }); + x.field.map(|value| { + do_nothing(value + captured); + }); x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { diverge(value + captured) }); - - x.field.map(|value| { diverge(value + captured); }); + x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { { diverge(value + captured); } }); + x.field.map(|value| { + diverge(value + captured); + }); + x.field.map(|value| { + diverge(value + captured); + }); x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| { plus_one(value + captured) }); - x.field.map(|value| { let y = plus_one(value + captured); }); - - x.field.map(|value| { plus_one(value + captured); }); - - x.field.map(|value| { { plus_one(value + captured); } }); + x.field.map(|value| plus_one(value + captured)); + x.field.map(|value| { + let y = plus_one(value + captured); + }); + x.field.map(|value| { + plus_one(value + captured); + }); - x.field.map(|ref value| { do_nothing(value + captured) }); + x.field.map(|value| { + plus_one(value + captured); + }); + x.field.map(|ref value| do_nothing(value + captured)); - x.field.map(|value| { do_nothing(value); do_nothing(value) }); + x.field.map(|value| { + do_nothing(value); + do_nothing(value) + }); - x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + x.field.map(|value| { + if value > 0 { + do_nothing(value); + do_nothing(value) + } + }); // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases @@ -96,9 +114,13 @@ fn option_map_unit_fn() { do_nothing(value); do_nothing(value) }); - x.field.map(|value| { do_nothing(value); do_nothing(value); }); + x.field.map(|value| { + do_nothing(value); + do_nothing(value); + }); - // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let variable name for them + // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let + // variable name for them Some(42).map(diverge); "12".parse::().ok().map(diverge); Some(plus_one(1)).map(do_nothing); @@ -108,5 +130,4 @@ fn option_map_unit_fn() { y.map(do_nothing); } -fn main() { -} +fn main() {} diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 3cb4fdc27eb..fcfd4e6ea56 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -7,9 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -fn input(_: Option>) { -} +fn input(_: Option>) {} fn output() -> Option> { None @@ -40,7 +38,7 @@ trait Trait { enum Enum { Tuple(Option>), - Struct{x: Option>}, + Struct { x: Option> }, } // The lint allows this @@ -69,5 +67,3 @@ fn main() { // The lint allows this let expr = Some(Some(true)); } - - diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index 82fdfe14ab6..a5cff3df9d7 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -7,65 +7,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(clippy::many_single_char_names)] #![warn(clippy::overflow_check_conditional)] fn main() { - let a: u32 = 1; - let b: u32 = 2; - let c: u32 = 3; - if a + b < a { - - } - if a > a + b { - - } - if a + b < b { - - } - if b > a + b { - - } - if a - b > b { - - } - if b < a - b { - - } - if a - b > a { - - } - if a < a - b { - - } - if a + b < c { - - } - if c > a + b { - - } - if a - b < c { - - } - if c > a - b { - - } - let i = 1.1; - let j = 2.2; - if i + j < i { - - } - if i - j < i { - - } - if i > i + j { - - } - if i - j < i { - - } + let a: u32 = 1; + let b: u32 = 2; + let c: u32 = 3; + if a + b < a {} + if a > a + b {} + if a + b < b {} + if b > a + b {} + if a - b > b {} + if b < a - b {} + if a - b > a {} + if a < a - b {} + if a + b < c {} + if c > a + b {} + if a - b < c {} + if c > a - b {} + let i = 1.1; + let j = 2.2; + if i + j < i {} + if i - j < i {} + if i > i + j {} + if i - j < i {} } diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index ede2e8f063b..93dec197ff5 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::panic_params, clippy::unimplemented)] fn missing() { @@ -46,7 +42,7 @@ fn ok_bracket() { } } -const ONE : u32= 1; +const ONE: u32 = 1; fn ok_nomsg() { assert!({ 1 == ONE }); diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index 45aa0decd58..3f9f91c81b1 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] struct Foo; impl PartialEq for Foo { - fn eq(&self, _: &Foo) -> bool { true } - fn ne(&self, _: &Foo) -> bool { false } + fn eq(&self, _: &Foo) -> bool { + true + } + fn ne(&self, _: &Foo) -> bool { + false + } } fn main() {} diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 41e9ec8ca81..e10afdb86b8 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused)] #![warn(clippy::all)] @@ -17,10 +14,10 @@ fn main() { let v = Some(true); match v { Some(x) => (), - y @ _ => (), + y @ _ => (), } match v { - Some(x) => (), - y @ None => (), // no error + Some(x) => (), + y @ None => (), // no error } } diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 4b404022ed4..82009cd3873 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -7,21 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::precedence)] #[allow(clippy::identity_op)] #[allow(clippy::eq_op)] macro_rules! trip { - ($a:expr) => { - match $a & 0b1111_1111i8 { - 0 => println!("a is zero ({})", $a), - _ => println!("a is {}", $a), - } - }; + ($a:expr) => { + match $a & 0b1111_1111i8 { + 0 => println!("a is zero ({})", $a), + _ => println!("a is {}", $a), + } + }; } fn main() { diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 5fa2cfcc315..a43482cba62 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::print_literal, clippy::write_literal)] #![warn(clippy::print_stdout, clippy::use_debug)] diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 0df26f6d25f..74756384067 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::print_literal)] fn main() { @@ -18,17 +15,17 @@ fn main() { println!("Hello"); let world = "world"; println!("Hello {}", world); - println!("Hello {world}", world=world); + println!("Hello {world}", world = world); println!("3 in hex is {:X}", 3); println!("2 + 1 = {:.4}", 3); println!("2 + 1 = {:5.4}", 3); println!("Debug test {:?}", "hello, world"); println!("{0:8} {1:>8}", "hello", "world"); println!("{1:8} {0:>8}", "hello", "world"); - println!("{foo:8} {bar:>8}", foo="hello", bar="world"); - println!("{bar:8} {foo:>8}", foo="hello", bar="world"); - println!("{number:>width$}", number=1, width=6); - println!("{number:>0width$}", number=1, width=6); + println!("{foo:8} {bar:>8}", foo = "hello", bar = "world"); + println!("{bar:8} {foo:>8}", foo = "hello", bar = "world"); + println!("{number:>width$}", number = 1, width = 6); + println!("{number:>0width$}", number = 1, width = 6); // these should throw warnings println!("{} of {:b} people know binary, the other half doesn't", 1, 2); @@ -45,6 +42,6 @@ fn main() { println!("{1} {0}", "hello", "world"); // named args shouldn't change anything either - println!("{foo} {bar}", foo="hello", bar="world"); - println!("{bar} {foo}", foo="hello", bar="world"); + println!("{foo} {bar}", foo = "hello", bar = "world"); + println!("{bar} {foo}", foo = "hello", bar = "world"); } diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 2dd08a5b88d..351fd60bc36 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::print_literal)] #![warn(clippy::print_with_newline)] diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index afc37b1bec7..19a0389762a 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { println!(); println!(""); diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index df0bde14960..0d7a829888e 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused, clippy::many_single_char_names)] #![warn(clippy::ptr_arg)] @@ -19,7 +16,8 @@ fn do_vec(x: &Vec) { //Nothing here } -fn do_vec_mut(x: &mut Vec) { // no error here +fn do_vec_mut(x: &mut Vec) { + // no error here //Nothing here } @@ -27,12 +25,12 @@ fn do_str(x: &String) { //Nothing here either } -fn do_str_mut(x: &mut String) { // no error here +fn do_str_mut(x: &mut String) { + // no error here //Nothing here either } -fn main() { -} +fn main() {} trait Foo { type Item; @@ -62,9 +60,7 @@ fn str_cloned(x: &String) -> String { let a = x.clone(); let b = x.clone(); let c = b.clone(); - let d = a.clone() - .clone() - .clone(); + let d = a.clone().clone().clone(); x.clone() } @@ -75,13 +71,14 @@ fn false_positive_capacity(x: &Vec, y: &String) { } fn false_positive_capacity_too(x: &String) -> String { - if x.capacity() > 1024 { panic!("Too large!"); } + if x.capacity() > 1024 { + panic!("Too large!"); + } x.clone() } #[allow(dead_code)] -fn test_cow_with_ref(c: &Cow<[i32]>) { -} +fn test_cow_with_ref(c: &Cow<[i32]>) {} #[allow(dead_code)] fn test_cow(c: Cow<[i32]>) { @@ -93,4 +90,6 @@ trait Foo2 { } // no error for &self references where self is of type String (#2293) -impl Foo2 for String { fn do_string(&self) {} } +impl Foo2 for String { + fn do_string(&self) {} +} diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index a6f86a230f3..2c9e47d3f32 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { let vec = vec![b'a', b'b', b'c']; let ptr = vec.as_ptr(); diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index a39ea00cb8b..7f1d06fbd29 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -7,18 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn some_func(a: Option) -> Option { - if a.is_none() { - return None - } + if a.is_none() { + return None; + } - a + a } pub enum SeemsOption { Some(T), - None + None, } impl SeemsOption { @@ -39,25 +38,25 @@ fn returns_something_similar_to_option(a: SeemsOption) -> SeemsOption } pub struct SomeStruct { - pub opt: Option, + pub opt: Option, } impl SomeStruct { - pub fn func(&self) -> Option { - if (self.opt).is_none() { - return None; - } + pub fn func(&self) -> Option { + if (self.opt).is_none() { + return None; + } - self.opt - } + self.opt + } } fn main() { - some_func(Some(42)); - some_func(None); + some_func(Some(42)); + some_func(None); - let some_struct = SomeStruct { opt: Some(54) }; - some_struct.func(); + let some_struct = SomeStruct { opt: Some(54) }; + some_struct.func(); let so = SeemsOption::Some(45); returns_something_similar_to_option(so); diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 8b7f0673e24..1eab67e20d0 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - struct NotARange; impl NotARange { fn step_by(&self, _: u32) {} @@ -31,13 +28,13 @@ fn main() { let y = NotARange; y.step_by(0); - let v1 = vec![1,2,3]; - let v2 = vec![4,5]; + let v1 = vec![1, 2, 3]; + let v2 = vec![4, 5]; let _x = v1.iter().zip(0..v1.len()); let _y = v1.iter().zip(0..v2.len()); // No error // check const eval - let _ = v1.iter().step_by(2/3); + let _ = v1.iter().step_by(2 / 3); } #[allow(unused)] diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 602743d6914..d8c955ba73f 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -7,38 +7,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - fn f() -> usize { 42 } #[warn(clippy::range_plus_one)] fn main() { - for _ in 0..2 { } - for _ in 0..=2 { } + for _ in 0..2 {} + for _ in 0..=2 {} - for _ in 0..3+1 { } - for _ in 0..=3+1 { } + for _ in 0..3 + 1 {} + for _ in 0..=3 + 1 {} - for _ in 0..1+5 { } - for _ in 0..=1+5 { } + for _ in 0..1 + 5 {} + for _ in 0..=1 + 5 {} - for _ in 1..1+1 { } - for _ in 1..=1+1 { } + for _ in 1..1 + 1 {} + for _ in 1..=1 + 1 {} - for _ in 0..13+13 { } - for _ in 0..=13-7 { } + for _ in 0..13 + 13 {} + for _ in 0..=13 - 7 {} - for _ in 0..(1+f()) { } - for _ in 0..=(1+f()) { } + for _ in 0..(1 + f()) {} + for _ in 0..=(1 + f()) {} - let _ = ..11-1; - let _ = ..=11-1; - let _ = ..=(11-1); - let _ = (1..11+1); - let _ = (f()+1)..(f()+1); + let _ = ..11 - 1; + let _ = ..=11 - 1; + let _ = ..=(11 - 1); + let _ = (1..11 + 1); + let _ = (f() + 1)..(f() + 1); let mut vec: Vec<()> = std::vec::Vec::new(); vec.drain(..); diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index deedde38231..d55898748be 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -9,8 +9,8 @@ #![warn(clippy::redundant_clone)] -use std::path::Path; use std::ffi::OsString; +use std::path::Path; fn main() { let _ = ["lorem", "ipsum"].join(" ").to_string(); @@ -33,7 +33,8 @@ fn main() { let _ = OsString::new().to_os_string(); // Check that lint level works - #[allow(clippy::redundant_clone)] let _ = String::new().to_string(); + #[allow(clippy::redundant_clone)] + let _ = String::new().to_string(); } #[derive(Clone)] diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index e68cdc2c1d1..46c56922974 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -7,27 +7,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::redundant_closure_call)] fn main() { - let a = (|| 42)(); + let a = (|| 42)(); - let mut i = 1; - let mut k = (|m| m+1)(i); + let mut i = 1; + let mut k = (|m| m + 1)(i); - k = (|a,b| a*b)(1,5); + k = (|a, b| a * b)(1, 5); - let closure = || 32; - i = closure(); + let closure = || 32; + i = closure(); - let closure = |i| i+1; - i = closure(3); + let closure = |i| i + 1; + i = closure(3); - i = closure(4); + i = closure(4); #[allow(clippy::needless_return)] (|| return 2)(); diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 41e90bba368..68adba92f8a 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::redundant_field_names)] #![allow(unused_variables)] #![feature(inclusive_range, inclusive_range_fields, inclusive_range_methods)] @@ -17,7 +14,7 @@ #[macro_use] extern crate derive_new; -use std::ops::{Range, RangeFrom, RangeTo, RangeInclusive, RangeToInclusive}; +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; mod foo { pub const BAR: u8 = 0; @@ -46,8 +43,8 @@ fn main() { gender: gender, age: age, - name, //should be ok - buzz: fizz, //should be ok + name, //should be ok + buzz: fizz, //should be ok foo: foo::BAR, //should be ok }; diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index 50838584f66..3744695a535 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -7,39 +7,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] - fn main() { if let Ok(_) = Ok::(42) {} - if let Err(_) = Err::(42) { - } + if let Err(_) = Err::(42) {} - if let None = None::<()> { - } + if let None = None::<()> {} - if let Some(_) = Some(42) { - } + if let Some(_) = Some(42) {} - if Ok::(42).is_ok() { - } + if Ok::(42).is_ok() {} - if Err::(42).is_err() { - } + if Err::(42).is_err() {} - if None::.is_none() { - } + if None::.is_none() {} - if Some(42).is_some() { - } + if Some(42).is_some() {} - if let Ok(x) = Ok::(42) { + if let Ok(x) = Ok::(42) { println!("{}", x); } diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index bd0fdd5d5ea..583829aae41 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -7,15 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - fn get_number() -> usize { 10 } -fn get_reference(n : &usize) -> &usize { +fn get_reference(n: &usize) -> &usize { n } @@ -32,7 +28,7 @@ fn main() { let b = *get_reference(&a); - let bytes : Vec = vec![1, 2, 3, 4]; + let bytes: Vec = vec![1, 2, 3, 4]; let b = *&bytes[1..2][0]; //This produces a suggestion of 'let b = (a);' which @@ -41,7 +37,7 @@ fn main() { let b = *(&a); - let b = *((&a)); + let b = *(&a); let b = *&&a; diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 2623438c4c4..2d9c3482850 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -7,17 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(unused)] #![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_macro)] extern crate regex; -use regex::{Regex, RegexSet, RegexBuilder}; -use regex::bytes::{Regex as BRegex, RegexSet as BRegexSet, RegexBuilder as BRegexBuilder}; +use regex::bytes::{Regex as BRegex, RegexBuilder as BRegexBuilder, RegexSet as BRegexSet}; +use regex::{Regex, RegexBuilder, RegexSet}; const OPENING_PAREN: &str = "("; const NOT_A_REAL_REGEX: &str = "foobar"; @@ -37,24 +33,15 @@ fn syntax_error() { let closing_paren = ")"; let not_linted = Regex::new(closing_paren); - let set = RegexSet::new(&[ - r"[a-z]+@[a-z]+\.(com|org|net)", - r"[a-z]+\.(com|org|net)", - ]); + let set = RegexSet::new(&[r"[a-z]+@[a-z]+\.(com|org|net)", r"[a-z]+\.(com|org|net)"]); let bset = BRegexSet::new(&[ r"[a-z]+@[a-z]+\.(com|org|net)", r"[a-z]+\.(com|org|net)", r".", // regression test ]); - let set_error = RegexSet::new(&[ - OPENING_PAREN, - r"[a-z]+\.(com|org|net)", - ]); - let bset_error = BRegexSet::new(&[ - OPENING_PAREN, - r"[a-z]+\.(com|org|net)", - ]); + let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); + let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); let raw_string_error = Regex::new(r"[...\/...]"); let raw_string_error = Regex::new(r#"[...\/...]"#); diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 7da1f212a75..ca3d3b13edc 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -7,13 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(integer_atomics)] #![allow(clippy::blacklisted_name)] #![deny(clippy::replace_consts)] use std::sync::atomic::*; -use std::sync::{ONCE_INIT, Once}; +use std::sync::{Once, ONCE_INIT}; #[rustfmt::skip] fn bad() { diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index f24e52b10fd..043b3efd45e 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(never_type)] #![warn(clippy::result_map_unit_fn)] #![allow(unused)] @@ -40,7 +37,7 @@ fn result_map_unit_fn() { let x = HasResult { field: Ok(10) }; x.field.map(plus_one); - let _ : Result<(), usize> = x.field.map(do_nothing); + let _: Result<(), usize> = x.field.map(do_nothing); x.field.map(do_nothing); @@ -49,47 +46,68 @@ fn result_map_unit_fn() { x.field.map(diverge); let captured = 10; - if let Ok(value) = x.field { do_nothing(value + captured) }; - let _ : Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); + if let Ok(value) = x.field { + do_nothing(value + captured) + }; + let _: Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_result_nothing(value + captured)); - x.field.map(|value| { x.do_result_plus_one(value + captured); }); - + x.field.map(|value| { + x.do_result_plus_one(value + captured); + }); x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { do_nothing(value + captured) }); - - x.field.map(|value| { do_nothing(value + captured); }); + x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { { do_nothing(value + captured); } }); + x.field.map(|value| { + do_nothing(value + captured); + }); + x.field.map(|value| { + do_nothing(value + captured); + }); x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { diverge(value + captured) }); - - x.field.map(|value| { diverge(value + captured); }); + x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { { diverge(value + captured); } }); + x.field.map(|value| { + diverge(value + captured); + }); + x.field.map(|value| { + diverge(value + captured); + }); x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| { plus_one(value + captured) }); - x.field.map(|value| { let y = plus_one(value + captured); }); - - x.field.map(|value| { plus_one(value + captured); }); - - x.field.map(|value| { { plus_one(value + captured); } }); + x.field.map(|value| plus_one(value + captured)); + x.field.map(|value| { + let y = plus_one(value + captured); + }); + x.field.map(|value| { + plus_one(value + captured); + }); - x.field.map(|ref value| { do_nothing(value + captured) }); + x.field.map(|value| { + plus_one(value + captured); + }); + x.field.map(|ref value| do_nothing(value + captured)); - x.field.map(|value| { do_nothing(value); do_nothing(value) }); + x.field.map(|value| { + do_nothing(value); + do_nothing(value) + }); - x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + x.field.map(|value| { + if value > 0 { + do_nothing(value); + do_nothing(value) + } + }); // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases @@ -97,9 +115,13 @@ fn result_map_unit_fn() { do_nothing(value); do_nothing(value) }); - x.field.map(|value| { do_nothing(value); do_nothing(value); }); + x.field.map(|value| { + do_nothing(value); + do_nothing(value); + }); - // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let variable name for them + // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let + // variable name for them let res: Result = Ok(42).map(diverge); "12".parse::().map(diverge); @@ -110,6 +132,4 @@ fn result_map_unit_fn() { y.map(do_nothing); } -fn main() { -} - +fn main() {} diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index 47be8423d7b..c52fd065dbe 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::serde_api_misuse)] #![allow(dead_code)] @@ -25,13 +22,15 @@ impl<'de> serde::de::Visitor<'de> for A { } fn visit_str(self, _v: &str) -> Result - where E: serde::de::Error, + where + E: serde::de::Error, { unimplemented!() } fn visit_string(self, _v: String) -> Result - where E: serde::de::Error, + where + E: serde::de::Error, { unimplemented!() } @@ -47,11 +46,11 @@ impl<'de> serde::de::Visitor<'de> for B { } fn visit_string(self, _v: String) -> Result - where E: serde::de::Error, + where + E: serde::de::Error, { unimplemented!() } } -fn main() { -} +fn main() {} diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index aa29bd1d79c..e960a6252be 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -7,16 +7,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - -#![warn(clippy::all, clippy::pedantic, clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] +#![warn( + clippy::all, + clippy::pedantic, + clippy::shadow_same, + clippy::shadow_reuse, + clippy::shadow_unrelated +)] #![allow(unused_parens, unused_variables, clippy::missing_docs_in_private_items)] -fn id(x: T) -> T { x } +fn id(x: T) -> T { + x +} -fn first(x: (isize, isize)) -> isize { x.0 } +fn first(x: (isize, isize)) -> isize { + x.0 +} fn main() { let mut x = 1; @@ -35,7 +41,9 @@ fn main() { let o = Some(1_u8); - if let Some(p) = o { assert_eq!(1, p); } + if let Some(p) = o { + assert_eq!(1, p); + } match o { Some(p) => p, // no error, because the p above is in its own scope None => 0, diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index 67999a74e5e..efe9920dd88 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::short_circuit_statement)] fn main() { diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index c3d846997ec..5277841fe32 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - use std::collections::HashSet; fn main() { diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index dca68e179e7..5a1bde3de32 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -7,20 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::single_match)] -fn dummy() { -} +fn dummy() {} -fn single_match(){ +fn single_match() { let x = Some(1u8); match x { - Some(y) => { println!("{:?}", y); } - _ => () + Some(y) => { + println!("{:?}", y); + }, + _ => (), }; let x = Some(1u8); @@ -29,19 +27,19 @@ fn single_match(){ // We suggest `if let Some(y) = x { .. }` because the macro // is expanded before we can do anything. Some(y) => println!("{:?}", y), - _ => () + _ => (), } - let z = (1u8,1u8); + let z = (1u8, 1u8); match z { (2...3, 7...9) => dummy(), - _ => {} + _ => {}, }; // Not linted (pattern guards used) match x { Some(y) if y == 0 => println!("{:?}", y), - _ => () + _ => (), } // Not linted (no block with statements in the single arm) @@ -51,22 +49,25 @@ fn single_match(){ } } -enum Foo { Bar, Baz(u8) } -use Foo::*; +enum Foo { + Bar, + Baz(u8), +} use std::borrow::Cow; +use Foo::*; fn single_match_know_enum() { let x = Some(1u8); - let y : Result<_, i8> = Ok(1i8); + let y: Result<_, i8> = Ok(1i8); match x { Some(y) => dummy(), - None => () + None => (), }; match y { Ok(y) => dummy(), - Err(..) => () + Err(..) => (), }; let c = Cow::Borrowed(""); @@ -89,4 +90,4 @@ fn single_match_know_enum() { } } -fn main() { } +fn main() {} diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index a7c28c578a4..18c26f7fc26 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -20,7 +20,10 @@ static NODE: ExprNode = ExprNode::Unicorns; fn unwrap_addr() -> Option<&'static ExprNode> { match ExprNode::Butterflies { ExprNode::ExprAddrOf => Some(&NODE), - _ => { let x = 5; None }, + _ => { + let x = 5; + None + }, } } diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index 5364bf70ff0..cf11384467c 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -62,13 +62,11 @@ fn resize_vector() { vec1.resize(10, 0); } -fn do_stuff(vec: &mut Vec) { - -} +fn do_stuff(vec: &mut Vec) {} fn extend_vector_with_manipulations_between() { let len = 300; - let mut vec1:Vec = Vec::with_capacity(len); + let mut vec1: Vec = Vec::with_capacity(len); do_stuff(&mut vec1); vec1.extend(repeat(0).take(len)); } diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 5c09e8f1f28..529c2487f54 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(dead_code)] fn main() {} @@ -22,22 +19,28 @@ fn starts_with() { fn chars_cmp_with_unwrap() { let s = String::from("foo"); - if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + if s.chars().next().unwrap() == 'f' { + // s.starts_with('f') // Nothing here } - if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + if s.chars().next_back().unwrap() == 'o' { + // s.ends_with('o') // Nothing here } - if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + if s.chars().last().unwrap() == 'o' { + // s.ends_with('o') // Nothing here } - if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + if s.chars().next().unwrap() != 'f' { + // !s.starts_with('f') // Nothing here } - if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + if s.chars().next_back().unwrap() != 'o' { + // !s.ends_with('o') // Nothing here } - if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + if s.chars().last().unwrap() != 'o' { + // !s.ends_with('o') // Nothing here } } diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index a0cf9c46906..56b466ede20 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index d2062b356dc..e15e80c1928 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[warn(clippy::string_add)] #[allow(clippy::string_add_assign)] fn add_only() { diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs index 17d528d1050..922487d671d 100644 --- a/tests/ui/stutter.rs +++ b/tests/ui/stutter.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::stutter)] #![allow(dead_code)] diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 5e7608565ed..ed845b7647a 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -7,12 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::suspicious_arithmetic_impl)] -use std::ops::{Add, AddAssign, Mul, Sub, Div}; +use std::ops::{Add, AddAssign, Div, Mul, Sub}; #[derive(Copy, Clone)] struct Foo(u32); diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 90c2aec9875..e9f227d47a0 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(clippy::blacklisted_name, unused_assignments)] @@ -54,7 +50,7 @@ fn main() { a = b; b = a; - ; let t = a; +; let t = a; a = b; b = t; @@ -63,7 +59,7 @@ fn main() { c.0 = a; a = c.0; - ; let t = c.0; +; let t = c.0; c.0 = a; a = t; } diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 9c4365bef40..79c090f0572 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -7,29 +7,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::temporary_assignment)] use std::ops::{Deref, DerefMut}; struct Struct { - field: i32 + field: i32, } struct Wrapper<'a> { - inner: &'a mut Struct + inner: &'a mut Struct, } impl<'a> Deref for Wrapper<'a> { type Target = Struct; - fn deref(&self) -> &Struct { self.inner } + fn deref(&self) -> &Struct { + self.inner + } } impl<'a> DerefMut for Wrapper<'a> { - fn deref_mut(&mut self) -> &mut Struct { self.inner } + fn deref_mut(&mut self) -> &mut Struct { + self.inner + } } fn main() { diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 09ee79f6d8b..b051746bbd4 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -7,32 +7,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(unused)] fn the_answer(ref mut x: u8) { - *x = 42; + *x = 42; } fn main() { - let mut x = 0; - the_answer(x); - // Closures should not warn - let y = |ref x| { println!("{:?}", x) }; - y(1u8); + let mut x = 0; + the_answer(x); + // Closures should not warn + let y = |ref x| println!("{:?}", x); + y(1u8); - let ref x = 1; + let ref x = 1; - let ref y: (&_, u8) = (&1, 2); + let ref y: (&_, u8) = (&1, 2); - let ref z = 1 + 2; + let ref z = 1 + 2; - let ref mut z = 1 + 2; + let ref mut z = 1 + 2; - let (ref x, _) = (1,2); // okay, not top level - println!("The answer is {}.", x); + let (ref x, _) = (1, 2); // okay, not top level + println!("The answer is {}.", x); } diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 7ed076225e2..9afb3399c59 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(stmt_expr_attributes)] - #![allow(unused_parens)] fn main() { let x: i32 = 42; - let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros + let _ = #[clippy::author] + (x & 0b1111 == 0); // suggest trailing_zeros let _ = x & 0b1_1111 == 0; // suggest trailing_zeros let _ = x & 0b1_1010 == 0; // do not lint let _ = x & 1 == 0; // do not lint diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 285c07a9724..b27014201cd 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] extern crate core; @@ -101,11 +97,11 @@ fn useless() { let _: *const usize = std::mem::transmute(5_isize); - let _ = 5_isize as *const usize; + let _ = 5_isize as *const usize; - let _: *const usize = std::mem::transmute(1+1usize); + let _: *const usize = std::mem::transmute(1 + 1usize); - let _ = (1+1_usize) as *const usize; + let _ = (1 + 1_usize) as *const usize; } } @@ -201,9 +197,7 @@ fn transmute_ptr_to_ptr() { let s = "hello world".to_owned(); let lp = LifetimeParam { s: &s }; let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) }; - let _: &GenericParam<&LifetimeParam<'static>> = unsafe { - std::mem::transmute(&GenericParam { t: &lp}) - }; + let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) }; } -fn main() { } +fn main() {} diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index 59d3d82ccae..dd96e2dabe1 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -7,11 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //ignore-x86_64 - - #[warn(wrong_transmute)] fn main() { unsafe { diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 8620628fdce..fbc298e3a06 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -7,14 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - //ignore-x86 //no-ignore-x86_64 - - #[warn(clippy::wrong_transmute)] fn main() { unsafe { diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 2a0dc22bfef..94e0113e56c 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -7,10 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![allow(clippy::many_single_char_names, clippy::blacklisted_name, clippy::redundant_field_names)] +#![allow( + clippy::many_single_char_names, + clippy::blacklisted_name, + clippy::redundant_field_names +)] #[derive(Copy, Clone)] struct Foo(u32); @@ -20,7 +21,10 @@ struct Bar([u8; 24]); #[derive(Copy, Clone)] pub struct Color { - pub r: u8, pub g: u8, pub b: u8, pub a: u8, + pub r: u8, + pub g: u8, + pub b: u8, + pub a: u8, } struct FooRef<'a> { @@ -29,8 +33,7 @@ struct FooRef<'a> { type Baz = u32; -fn good(a: &mut u32, b: u32, c: &Bar) { -} +fn good(a: &mut u32, b: u32, c: &Bar) {} fn good_return_implicit_lt_ref(foo: &Foo) -> &u32 { &foo.0 @@ -42,33 +45,24 @@ fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { } fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { - FooRef { - foo, - } + FooRef { foo } } #[allow(clippy::needless_lifetimes)] fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> { - FooRef { - foo, - } + FooRef { foo } } -fn bad(x: &u32, y: &Foo, z: &Baz) { -} +fn bad(x: &u32, y: &Foo, z: &Baz) {} impl Foo { - fn good(self, a: &mut u32, b: u32, c: &Bar) { - } + fn good(self, a: &mut u32, b: u32, c: &Bar) {} - fn good2(&mut self) { - } + fn good2(&mut self) {} - fn bad(&self, x: &u32, y: &Foo, z: &Baz) { - } + fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} - fn bad2(x: &u32, y: &Foo, z: &Baz) { - } + fn bad2(x: &u32, y: &Foo, z: &Baz) {} } impl AsRef for Foo { @@ -78,11 +72,9 @@ impl AsRef for Foo { } impl Bar { - fn good(&self, a: &mut u32, b: u32, c: &Bar) { - } + fn good(&self, a: &mut u32, b: u32, c: &Bar) {} - fn bad2(x: &u32, y: &Foo, z: &Baz) { - } + fn bad2(x: &u32, y: &Foo, z: &Baz) {} } trait MyTrait { diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs index 82b5deda3ba..17027306367 100644 --- a/tests/ui/ty_fn_sig.rs +++ b/tests/ui/ty_fn_sig.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // Regression test pub fn retry(f: F) { diff --git a/tests/ui/types.rs b/tests/ui/types.rs index 03676f69ab4..f0ede2fd48c 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -7,14 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // should not warn on lossy casting in constant types // because not supported yet -const C : i32 = 42; -const C_I64 : i64 = C as i64; +const C: i32 = 42; +const C_I64: i64 = C as i64; fn main() { // should suggest i64::from(c) - let c : i32 = 42; - let c_i64 : i64 = c as i64; + let c: i32 = 42; + let c_i64: i64 = c as i64; } diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 8de17fea220..0e1200db227 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[warn(clippy::zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 058c6563c5a..571882ced0f 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::unit_arg)] #![allow(clippy::no_effect)] @@ -33,7 +30,9 @@ impl Bar { fn bad() { foo({}); - foo({ 1; }); + foo({ + 1; + }); foo(foo(1)); foo({ foo(1); @@ -41,7 +40,9 @@ fn bad() { }); foo3({}, 2, 2); let b = Bar; - b.bar({ 1; }); + b.bar({ + 1; + }); } fn ok() { diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index 10eb0c70c54..0bc87f43c15 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::unit_cmp)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] @@ -19,13 +15,18 @@ pub struct ContainsUnit(()); // should be fine fn main() { // this is fine - if true == false { - } + if true == false {} // this warns - if { true; } == { false; } { - } - - if { true; } > { false; } { - } + if { + true; + } == { + false; + } {} + + if { + true; + } > { + false; + } {} } diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index d0b4ae9f532..e583614a93c 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -11,6 +11,4 @@ #![warn(clippy::pedantic)] #[warn(clippy::if_not_els)] -fn main() { - -} +fn main() {} diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 28cad1d881f..40c4b4961e9 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::clone_on_ref_ptr)] #![allow(unused)] @@ -70,14 +67,14 @@ fn clone_on_double_ref() { let y = &&x; let z: &Vec<_> = y.clone(); - println!("{:p} {:p}",*y, z); + println!("{:p} {:p}", *y, z); } fn iter_clone_collect() { - let v = [1,2,3,4,5]; - let v2 : Vec = v.iter().cloned().collect(); - let v3 : HashSet = v.iter().cloned().collect(); - let v4 : VecDeque = v.iter().cloned().collect(); + let v = [1, 2, 3, 4, 5]; + let v2: Vec = v.iter().cloned().collect(); + let v3: HashSet = v.iter().cloned().collect(); + let v4: VecDeque = v.iter().cloned().collect(); } mod many_derefs { @@ -92,9 +89,11 @@ mod many_derefs { ($src:ident, $dst:ident) => { impl std::ops::Deref for $src { type Target = $dst; - fn deref(&self) -> &Self::Target { &$dst } + fn deref(&self) -> &Self::Target { + &$dst + } } - } + }; } impl_deref!(A, B); @@ -102,7 +101,9 @@ mod many_derefs { impl_deref!(C, D); impl std::ops::Deref for D { type Target = &'static E; - fn deref(&self) -> &Self::Target { &&E } + fn deref(&self) -> &Self::Target { + &&E + } } fn go1() { diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs index 8b74ca3a425..a0c183a58cc 100644 --- a/tests/ui/unnecessary_filter_map.rs +++ b/tests/ui/unnecessary_filter_map.rs @@ -7,10 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); + let _ = (0..4).filter_map(|x| { + if x > 1 { + return Some(x); + }; + None + }); let _ = (0..4).filter_map(|x| match x { 0 | 1 => None, _ => Some(x), diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index e8d84ecea8c..4b4a6ee044c 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index de44047c867..34e1112f006 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -13,14 +13,14 @@ struct Tuple(i32); struct Struct { - field: i32 + field: i32, } enum Enum { Tuple(i32), Struct { field: i32 }, } struct DropStruct { - field: i32 + field: i32, } impl Drop for DropStruct { fn drop(&mut self) {} @@ -40,9 +40,15 @@ struct FooString { s: String, } -fn get_number() -> i32 { 0 } -fn get_struct() -> Struct { Struct { field: 0 } } -fn get_drop_struct() -> DropStruct { DropStruct { field: 0 } } +fn get_number() -> i32 { + 0 +} +fn get_struct() -> Struct { + Struct { field: 0 } +} +fn get_drop_struct() -> DropStruct { + DropStruct { field: 0 } +} fn main() { Tuple(get_number()); @@ -63,8 +69,12 @@ fn main() { (42, get_number()).1; [get_number(); 55]; [42; 55][get_number() as usize]; - {get_number()}; - FooString { s: String::from("blah"), }; + { + get_number() + }; + FooString { + s: String::from("blah"), + }; // Do not warn DropTuple(get_number()); diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index adc628fe8b6..31aa367e506 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![feature(tool_attributes)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 128a3fee429..14676c1e76f 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::unneeded_field_pattern)] #[allow(dead_code, unused)] @@ -24,13 +20,12 @@ fn main() { let f = Foo { a: 0, b: 0, c: 0 }; match f { - Foo { a: _, b: 0, .. } => {} - - Foo { a: _, b: _, c: _ } => {} + Foo { a: _, b: 0, .. } => {}, + Foo { a: _, b: _, c: _ } => {}, } match f { - Foo { b: 0, .. } => {} // should be OK - Foo { .. } => {} // and the Force might be with this one + Foo { b: 0, .. } => {}, // should be OK + Foo { .. } => {}, // and the Force might be with this one } } diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 9142b3d2911..ad29fcf8fe4 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -7,13 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #[warn(clippy::unreadable_literal)] #[allow(unused_variables)] fn main() { - let good = (0b1011_i64, 0o1_234_u32, 0x1_234_567, 65536, 1_2345_6789, 1234_f32, 1_234.12_f32, 1_234.123_f32, 1.123_4_f32); + let good = ( + 0b1011_i64, + 0o1_234_u32, + 0x1_234_567, + 65536, + 1_2345_6789, + 1234_f32, + 1_234.12_f32, + 1_234.123_f32, + 1.123_4_f32, + ); let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); let good_sci = 1.1234e1; let bad_sci = 1.123456e1; diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index 9c1800467d3..bfab077375d 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -7,23 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused_imports)] #![allow(dead_code)] #![warn(clippy::unsafe_removed_from_name)] -use std::cell::{UnsafeCell as TotallySafeCell}; +use std::cell::UnsafeCell as TotallySafeCell; use std::cell::UnsafeCell as TotallySafeCellAgain; // Shouldn't error -use std::cell::{UnsafeCell as SuperDangerousUnsafeCell}; -use std::cell::{UnsafeCell as Dangerunsafe}; -use std::cell::UnsafeCell as Bombsawayunsafe; -use std::cell::{RefCell as ProbablyNotUnsafe}; +use std::cell::RefCell as ProbablyNotUnsafe; use std::cell::RefCell as RefCellThatCantBeUnsafe; +use std::cell::UnsafeCell as SuperDangerousUnsafeCell; +use std::cell::UnsafeCell as Dangerunsafe; +use std::cell::UnsafeCell as Bombsawayunsafe; mod mod_with_some_unsafe_things { pub struct Safe {} diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index a47a6ccfdf6..a125d0397af 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code)] #![warn(clippy::unused_io_amount)] @@ -37,5 +33,4 @@ fn unwrap(s: &mut T) { s.read(&mut buf).unwrap(); } -fn main() { -} +fn main() {} diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index d7d843dfc25..8db29dcf3fc 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -7,16 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![allow(dead_code, clippy::items_after_statements, clippy::never_loop)] #![warn(clippy::unused_label)] fn unused_label() { 'label: for i in 1..2 { - if i > 4 { continue } + if i > 4 { + continue; + } } } @@ -26,9 +24,10 @@ fn foo() { } } - fn bla() { - 'a: loop { break } + 'a: loop { + break; + } fn blub() {} } diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index de13864421e..99e80103f1f 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -7,25 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - -#![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] +#![allow( + unused, + dead_code, + clippy::needless_lifetimes, + clippy::needless_pass_by_value, + clippy::trivially_copy_pass_by_ref +)] #![warn(clippy::extra_unused_lifetimes)] -fn empty() { - -} - - -fn used_lt<'a>(x: &'a u8) { - -} - +fn empty() {} -fn unused_lt<'a>(x: u8) { +fn used_lt<'a>(x: &'a u8) {} -} +fn unused_lt<'a>(x: u8) {} fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { // 'a is useless here since it's not directly bound @@ -39,19 +34,14 @@ fn lt_return_only<'a>() -> &'a u8 { panic!() } -fn unused_lt_blergh<'a>(x: Option>) { - -} - +fn unused_lt_blergh<'a>(x: Option>) {} trait Foo<'a> { fn x(&self, a: &'a u8); } impl<'a> Foo<'a> for u8 { - fn x(&self, a: &'a u8) { - - } + fn x(&self, a: &'a u8) {} } struct Bar; @@ -61,20 +51,23 @@ impl Bar { } // test for #489 (used lifetimes in bounds) -pub fn parse<'a, I: Iterator>(_it: &mut I) { +pub fn parse<'a, I: Iterator>(_it: &mut I) { unimplemented!() } -pub fn parse2<'a, I>(_it: &mut I) where I: Iterator{ +pub fn parse2<'a, I>(_it: &mut I) +where + I: Iterator, +{ unimplemented!() } -struct X { x: u32 } +struct X { + x: u32, +} impl X { fn self_ref_with_lifetime<'a>(&'a self) {} fn explicit_self_with_lifetime<'a>(self: &'a Self) {} } -fn main() { - -} +fn main() {} diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index 80965635a08..8573f78d43b 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![warn(clippy::all)] fn main() { @@ -16,7 +14,5 @@ fn main() { } fn new_lines() { - let s = Some(String::from("test string")) - .unwrap_or("Fail".to_string()) - .len(); + let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 60dc2d54d05..c21df403035 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::use_self)] #![allow(dead_code)] #![allow(clippy::should_implement_trait)] @@ -57,21 +54,24 @@ mod better { //todo the lint does not handle lifetimed struct //the following module should trigger the lint on the third method only mod lifetimes { - struct Foo<'a>{foo_str: &'a str} + struct Foo<'a> { + foo_str: &'a str, + } impl<'a> Foo<'a> { - // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> Foo<'b>` + // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> + // Foo<'b>` fn foo(s: &str) -> Foo { Foo { foo_str: s } } // cannot replace with `Self`, because that's `Foo<'a>` fn bar() -> Foo<'static> { - Foo { foo_str: "foo"} + Foo { foo_str: "foo" } } // `Self` is applicable here fn clone(&self) -> Foo<'a> { - Foo {foo_str: self.foo_str} + Foo { foo_str: self.foo_str } } } } @@ -105,8 +105,7 @@ mod traits { p1 } - fn nested(_p1: Box, _p2: (&u8, &Bad)) { - } + fn nested(_p1: Box, _p2: (&u8, &Bad)) {} fn vals(_: Bad) -> Bad { Bad::default() @@ -137,8 +136,7 @@ mod traits { p1 } - fn nested(_p1: Box, _p2: (&u8, &Self)) { - } + fn nested(_p1: Box, _p2: (&u8, &Self)) {} fn vals(_: Self) -> Self { Self::default() @@ -175,8 +173,7 @@ mod traits { p1 } - fn nested(_p1: Box, _p2: (&Self, &Self)) { - } + fn nested(_p1: Box, _p2: (&Self, &Self)) {} fn vals(_: Self) -> Self { Self::default() @@ -210,11 +207,11 @@ mod existential { struct Foo; impl Foo { - fn bad(foos: &[Self]) -> impl Iterator { + fn bad(foos: &[Self]) -> impl Iterator { foos.iter() } - fn good(foos: &[Self]) -> impl Iterator { + fn good(foos: &[Self]) -> impl Iterator { foos.iter() } } @@ -239,7 +236,7 @@ mod issue3425 { A, } impl Enum { - fn a () { + fn a() { use self::Enum::*; } } diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index b6b055e58bc..bd20cc5f48a 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::all)] - #![allow(clippy::blacklisted_name)] #![warn(clippy::used_underscore_binding)] @@ -19,7 +15,7 @@ macro_rules! test_macro { () => {{ let _foo = 42; _foo + 1 - }} + }}; } /// Test that we lint if we use a binding with a single leading underscore @@ -74,7 +70,7 @@ fn _fn_test() {} struct _StructTest; enum _EnumTest { _Empty, - _Value(_StructTest) + _Value(_StructTest), } /// Test that we do not lint for non-variable bindings diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index a5e9caf3a67..34c0f5095db 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![deny(clippy::useless_asref)] #![allow(clippy::trivially_copy_pass_by_ref)] use std::fmt::Debug; @@ -18,7 +15,9 @@ struct FakeAsRef; #[allow(clippy::should_implement_trait)] impl FakeAsRef { - fn as_ref(&self) -> &Self { self } + fn as_ref(&self) -> &Self { + self + } } struct MoreRef; @@ -29,14 +28,22 @@ impl<'a, 'b, 'c> AsRef<&'a &'b &'c MoreRef> for MoreRef { } } -fn foo_rstr(x: &str) { println!("{:?}", x); } -fn foo_rslice(x: &[i32]) { println!("{:?}", x); } -fn foo_mrslice(x: &mut [i32]) { println!("{:?}", x); } -fn foo_rrrrmr(_: &&&&MoreRef) { println!("so many refs"); } +fn foo_rstr(x: &str) { + println!("{:?}", x); +} +fn foo_rslice(x: &[i32]) { + println!("{:?}", x); +} +fn foo_mrslice(x: &mut [i32]) { + println!("{:?}", x); +} +fn foo_rrrrmr(_: &&&&MoreRef) { + println!("so many refs"); +} fn not_ok() { let rstr: &str = "hello"; - let mut mrslice: &mut [i32] = &mut [1,2,3]; + let mut mrslice: &mut [i32] = &mut [1, 2, 3]; { let rslice: &[i32] = &*mrslice; @@ -75,8 +82,8 @@ fn not_ok() { fn ok() { let string = "hello".to_owned(); - let mut arr = [1,2,3]; - let mut vec = vec![1,2,3]; + let mut arr = [1, 2, 3]; + let mut vec = vec![1, 2, 3]; { foo_rstr(string.as_ref()); @@ -109,8 +116,12 @@ fn ok() { generic_ok(&mut arr); } -fn foo_mrt(t: &mut T) { println!("{:?}", t); } -fn foo_rt(t: &T) { println!("{:?}", t); } +fn foo_mrt(t: &mut T) { + println!("{:?}", t); +} +fn foo_rt(t: &T) { + println!("{:?}", t); +} fn generic_not_ok + AsRef + Debug + ?Sized>(mrt: &mut T) { foo_mrt(mrt.as_mut()); diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 9fb84866ef6..4ee6520443d 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -7,15 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![warn(clippy::useless_attribute)] #[allow(dead_code)] #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] -#[cfg_attr(feature = "cargo-clippy", - allow(dead_code))] +#[cfg_attr(feature = "cargo-clippy", allow(dead_code))] #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] @@ -26,7 +22,10 @@ extern crate clippy_lints; use std::collections; // don't lint on deprecated for `use` items -mod foo { #[deprecated] pub struct Bar; } +mod foo { + #[deprecated] + pub struct Bar; +} #[allow(deprecated)] pub use foo::Bar; diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index e74aded5728..a7ccda375bf 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::useless_vec)] #[derive(Debug)] @@ -37,10 +33,10 @@ fn main() { on_slice(&vec![1, 2]); on_slice(&[1, 2]); - on_slice(&vec ![1, 2]); + on_slice(&vec![1, 2]); on_slice(&[1, 2]); - on_slice(&vec!(1, 2)); + on_slice(&vec![1, 2]); on_slice(&[1, 2]); on_slice(&vec![1; 2]); diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 3cc7c52df5d..e4c7047df91 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)] #![allow(dead_code, clippy::never_loop, unused, clippy::cyclomatic_complexity)] @@ -20,10 +16,11 @@ fn main() { if let Some(_x) = y { let _v = 1; } else { - break + break; } } - loop { // no error, break is not in else clause + loop { + // no error, break is not in else clause if let Some(_x) = y { let _v = 1; } @@ -32,13 +29,13 @@ fn main() { loop { match y { Some(_x) => true, - None => break + None => break, }; } loop { let x = match y { Some(x) => x, - None => break + None => break, }; let _x = x; let _str = "foo"; @@ -48,19 +45,25 @@ fn main() { Some(x) => x, None => break, }; - { let _a = "bar"; }; - { let _b = "foobar"; } + { + let _a = "bar"; + }; + { + let _b = "foobar"; + } } - loop { // no error, else branch does something other than break + loop { + // no error, else branch does something other than break match y { Some(_x) => true, _ => { let _z = 1; break; - } + }, }; } - while let Some(x) = y { // no error, obviously + while let Some(x) = y { + // no error, obviously println!("{}", x); } @@ -68,7 +71,7 @@ fn main() { loop { let (e, l) = match "".split_whitespace().next() { Some(word) => (word.is_empty(), word.len()), - None => break + None => break, }; let _ = (e, l); @@ -91,7 +94,8 @@ fn main() { while let None = iter.next() {} // this is fine (if nonsensical) let mut iter = 1..20; - if let Some(x) = iter.next() { // also fine + if let Some(x) = iter.next() { + // also fine println!("{}", x) } @@ -109,7 +113,9 @@ fn main() { // or this let mut iter = 1u32..20; - while let Some(x) = iter.next() {break;} + while let Some(x) = iter.next() { + break; + } println!("Remaining iter {:?}", iter); // or this @@ -128,7 +134,7 @@ fn no_panic(slice: &[T]) { loop { let _ = match iter.next() { Some(ele) => ele, - None => break + None => break, }; loop {} } @@ -143,8 +149,8 @@ fn issue1017() { Err(_) => len = 0, Ok(length) => { len = length; - break - } + break; + }, } } } @@ -155,20 +161,17 @@ fn refutable() { let mut b = a.iter(); // consume all the 42s - while let Some(&42) = b.next() { - } + while let Some(&42) = b.next() {} let a = [(1, 2, 3)]; let mut b = a.iter(); - while let Some(&(1, 2, 3)) = b.next() { - } + while let Some(&(1, 2, 3)) = b.next() {} let a = [Some(42)]; let mut b = a.iter(); - while let Some(&None) = b.next() { - } + while let Some(&None) = b.next() {} /* This gives “refutable pattern in `for` loop binding: `&_` not covered” for &42 in b {} @@ -177,20 +180,22 @@ fn refutable() { // */ let mut y = a.iter(); - loop { // x is reused, so don't lint here - while let Some(v) = y.next() { - } + loop { + // x is reused, so don't lint here + while let Some(v) = y.next() {} } let mut y = a.iter(); for _ in 0..2 { - while let Some(v) = y.next() { // y is reused, don't lint + while let Some(v) = y.next() { + // y is reused, don't lint } } loop { let mut y = a.iter(); - while let Some(v) = y.next() { // use a for loop here + while let Some(v) = y.next() { + // use a for loop here } } diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 7917479ed67..0ba1943e6d8 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused_must_use)] #![warn(clippy::write_literal)] @@ -23,17 +20,17 @@ fn main() { writeln!(&mut v, "Hello"); let world = "world"; writeln!(&mut v, "Hello {}", world); - writeln!(&mut v, "Hello {world}", world=world); + writeln!(&mut v, "Hello {world}", world = world); writeln!(&mut v, "3 in hex is {:X}", 3); writeln!(&mut v, "2 + 1 = {:.4}", 3); writeln!(&mut v, "2 + 1 = {:5.4}", 3); writeln!(&mut v, "Debug test {:?}", "hello, world"); writeln!(&mut v, "{0:8} {1:>8}", "hello", "world"); writeln!(&mut v, "{1:8} {0:>8}", "hello", "world"); - writeln!(&mut v, "{foo:8} {bar:>8}", foo="hello", bar="world"); - writeln!(&mut v, "{bar:8} {foo:>8}", foo="hello", bar="world"); - writeln!(&mut v, "{number:>width$}", number=1, width=6); - writeln!(&mut v, "{number:>0width$}", number=1, width=6); + writeln!(&mut v, "{foo:8} {bar:>8}", foo = "hello", bar = "world"); + writeln!(&mut v, "{bar:8} {foo:>8}", foo = "hello", bar = "world"); + writeln!(&mut v, "{number:>width$}", number = 1, width = 6); + writeln!(&mut v, "{number:>0width$}", number = 1, width = 6); // these should throw warnings writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); @@ -50,6 +47,6 @@ fn main() { writeln!(&mut v, "{1} {0}", "hello", "world"); // named args shouldn't change anything either - writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); - writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); + writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); } diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index e9fcff0b3dd..dbfa02d20a1 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(clippy::write_literal)] #![warn(clippy::write_with_newline)] diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index e272a5af88b..71b5df48bfa 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -7,9 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] use std::io::Write; @@ -27,5 +24,4 @@ fn main() { writeln!(&mut v); writeln!(&mut v, " "); write!(&mut v, ""); - } diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index d1c7424c8d7..3c69c9ad03f 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_pub_self_convention)] #![allow(dead_code, clippy::trivially_copy_pass_by_ref)] @@ -21,7 +17,6 @@ fn main() {} struct Foo; impl Foo { - fn as_i32(self) {} fn as_u32(&self) {} fn into_i32(self) {} @@ -39,14 +34,13 @@ impl Foo { #[allow(clippy::wrong_self_convention)] pub fn from_cake(self) {} - fn as_x>(_: F) { } - fn as_y>(_: F) { } + fn as_x>(_: F) {} + fn as_y>(_: F) {} } struct Bar; impl Bar { - fn as_i32(self) {} fn as_u32(&self) {} fn into_i32(&self) {} diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index 4e2272c8e09..68e9437273f 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -7,20 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[allow(unused_variables)] #[warn(clippy::zero_divided_by_zero)] fn main() { let nan = 0.0 / 0.0; let f64_nan = 0.0 / 0.0f64; let other_f64_nan = 0.0f64 / 0.0; - let one_more_f64_nan = 0.0f64/0.0f64; + let one_more_f64_nan = 0.0f64 / 0.0f64; let zero = 0.0; let other_zero = 0.0; let other_nan = zero / other_zero; // fine - this lint doesn't propegate constants. - let not_nan = 2.0/0.0; // not an error: 2/0 = inf - let also_not_nan = 0.0/2.0; // not an error: 0/2 = 0 + let not_nan = 2.0 / 0.0; // not an error: 2/0 = inf + let also_not_nan = 0.0 / 2.0; // not an error: 0/2 = 0 } diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index fbe4f950da5..9930b8a4c6b 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #[allow(unused_variables)] fn main() { let x = 0 as *const usize; -- cgit 1.4.1-3-g733a5 From 109d4b1ab3ef4823b3767acde6301e609535cb70 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 9 Dec 2018 20:19:21 +0900 Subject: Lint redundant clone of projection --- clippy_lints/src/no_effect.rs | 10 +++--- clippy_lints/src/redundant_clone.rs | 71 +++++++++++++++++++++++++++++++------ clippy_lints/src/utils/mod.rs | 5 ++- tests/ui/redundant_clone.rs | 21 +++++++++++ tests/ui/redundant_clone.stderr | 22 +++++++++--- 5 files changed, 106 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index d39c13621ff..f30da9c909d 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -57,7 +57,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { } match expr.node { ExprKind::Lit(..) | ExprKind::Closure(.., _) => true, - ExprKind::Path(..) => !has_drop(cx, expr), + ExprKind::Path(..) => !has_drop(cx, cx.tables.expr_ty(expr)), ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => { has_no_effect(cx, a) && has_no_effect(cx, b) }, @@ -70,7 +70,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { | ExprKind::AddrOf(_, ref inner) | ExprKind::Box(ref inner) => has_no_effect(cx, inner), ExprKind::Struct(_, ref fields, ref base) => { - !has_drop(cx, expr) + !has_drop(cx, cx.tables.expr_ty(expr)) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { Some(ref base) => has_no_effect(cx, base), @@ -82,7 +82,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { - !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg)) + !has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg)) }, _ => false, } @@ -161,7 +161,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), ExprKind::Struct(_, ref fields, ref base) => { - if has_drop(cx, expr) { + if has_drop(cx, cx.tables.expr_ty(expr)) { None } else { Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) @@ -172,7 +172,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option + if !has_drop(cx, cx.tables.expr_ty(expr)) => { Some(args.iter().collect()) }, diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 843f1cbd36e..2c1173bf10e 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -23,10 +23,11 @@ use crate::syntax::{ source_map::{BytePos, Span}, }; use crate::utils::{ - in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, span_lint_node_and_then, - walk_ptrs_ty_depth, + has_drop, in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, + span_lint_node_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; +use matches::matches; use std::convert::TryFrom; macro_rules! unwrap_or_continue { @@ -126,7 +127,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } (from_deref) // In case of `from_deref`, `arg` is already a reference since it is `deref`ed in the previous // block. - let cloned = unwrap_or_continue!(find_stmt_assigns_to(arg, from_borrow, bbdata.statements.iter().rev())); + let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to( + cx, + mir, + arg, + from_borrow, + bbdata.statements.iter().rev() + )); + + if from_borrow && cannot_move_out { + continue; + } // _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }` let referent = if from_deref { @@ -150,7 +161,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { } }; - unwrap_or_continue!(find_stmt_assigns_to(pred_arg, true, mir[ps[0]].statements.iter().rev())) + let (local, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to( + cx, + mir, + pred_arg, + true, + mir[ps[0]].statements.iter().rev() + )); + if cannot_move_out { + continue; + } + local } else { cloned }; @@ -227,21 +248,25 @@ fn is_call_with_ref_arg<'tcx>( } } +type CannotMoveOut = bool; + /// Finds the first `to = (&)from`, and returns `Some(from)`. fn find_stmt_assigns_to<'a, 'tcx: 'a>( + cx: &LateContext<'_, 'tcx>, + mir: &mir::Mir<'tcx>, to: mir::Local, by_ref: bool, mut stmts: impl Iterator>, -) -> Option { +) -> Option<(mir::Local, CannotMoveOut)> { stmts.find_map(|stmt| { if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { if *local == to { if by_ref { - if let mir::Rvalue::Ref(_, _, mir::Place::Local(r)) = **v { - return Some(r); + if let mir::Rvalue::Ref(_, _, ref place) = **v { + return base_local(cx, mir, place); } - } else if let mir::Rvalue::Use(mir::Operand::Copy(mir::Place::Local(r))) = **v { - return Some(r); + } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v { + return base_local(cx, mir, place); } } } @@ -250,6 +275,32 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( }) } +fn base_local<'tcx>( + cx: &LateContext<'_, 'tcx>, + mir: &mir::Mir<'tcx>, + mut place: &mir::Place<'tcx>, +) -> Option<(mir::Local, CannotMoveOut)> { + use rustc::mir::Place::*; + + let mut deref = false; + // Accessing a field of an ADT that has `Drop` + let mut field = false; + + loop { + match place { + Local(local) => return Some((*local, deref || field)), + Projection(proj) => { + place = &proj.base; + deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref); + if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) { + field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).to_ty(cx.tcx)); + } + }, + _ => return None, + } + } +} + struct LocalUseVisitor { local: mir::Local, used_other_than_drop: bool, @@ -280,7 +331,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) { match ctx { PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return, - _ => {} + _ => {}, } if *local == self.local { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 68357b08d6c..aa6b3305a49 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -266,9 +266,8 @@ pub fn implements_trait<'a, 'tcx>( } /// Check whether this type implements Drop. -pub fn has_drop(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { - let struct_ty = cx.tables.expr_ty(expr); - match struct_ty.ty_adt_def() { +pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { + match ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, } diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index e5c5528e4fa..71f83e155f3 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -34,6 +34,12 @@ fn main() { // Check that lint level works #[allow(clippy::redundant_clone)] let _ = String::new().to_string(); + + let tup = (String::from("foo"),); + let _ = tup.0.clone(); + + let tup_ref = &(String::from("foo"),); + let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed } #[derive(Clone)] @@ -45,3 +51,18 @@ fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { (Alpha, a) } } + +struct TypeWithDrop { + x: String, +} + +impl Drop for TypeWithDrop { + fn drop(&mut self) {} +} + +fn cannot_move_from_type_with_drop() -> String { + let s = TypeWithDrop { + x: String::new() + }; + s.x.clone() // removing this `clone()` summons E0509 +} diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index db452822f89..4d1c7aa2600 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -96,16 +96,28 @@ note: this value is dropped without further use | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:43:22 + --> $DIR/redundant_clone.rs:39:18 | -43 | (a.clone(), a.clone()) +39 | let _ = tup.0.clone(); + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:39:13 + | +39 | let _ = tup.0.clone(); + | ^^^^^ + +error: redundant clone + --> $DIR/redundant_clone.rs:49:22 + | +49 | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:43:21 + --> $DIR/redundant_clone.rs:49:21 | -43 | (a.clone(), a.clone()) +49 | (a.clone(), a.clone()) | ^ -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 22f396a1c173d3431849f1fca8df8f570ca8248c Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 9 Dec 2018 22:02:23 +0900 Subject: Apply redundant_clone on clippy --- clippy_lints/src/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 9f8cc76c5aa..a8b03d21482 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -332,7 +332,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { &format!("unknown clippy lint: clippy::{}", name), |db| { if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase().to_string(); + let name_lower = name.as_str().to_lowercase(); match lint_store.check_lint_name( &name_lower, Some(tool_name.as_str()) -- cgit 1.4.1-3-g733a5 From fd9f5df36ca934405183ee8e7ba96b46b1f645f2 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 10 Dec 2018 15:48:34 +0900 Subject: Add comment and rename --- clippy_lints/src/redundant_clone.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 2c1173bf10e..68b79869718 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -250,7 +250,8 @@ fn is_call_with_ref_arg<'tcx>( type CannotMoveOut = bool; -/// Finds the first `to = (&)from`, and returns `Some(from)`. +/// Finds the first `to = (&)from`, and returns +/// ``Some((from, [`true` if `from` cannot be moved out]))``. fn find_stmt_assigns_to<'a, 'tcx: 'a>( cx: &LateContext<'_, 'tcx>, mir: &mir::Mir<'tcx>, @@ -263,10 +264,10 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( if *local == to { if by_ref { if let mir::Rvalue::Ref(_, _, ref place) = **v { - return base_local(cx, mir, place); + return base_local_and_movability(cx, mir, place); } } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v { - return base_local(cx, mir, place); + return base_local_and_movability(cx, mir, place); } } } @@ -275,15 +276,20 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( }) } -fn base_local<'tcx>( +/// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself +/// if it is already a `Local`. +/// +/// Also reports whether given `place` cannot be moved out. +fn base_local_and_movability<'tcx>( cx: &LateContext<'_, 'tcx>, mir: &mir::Mir<'tcx>, mut place: &mir::Place<'tcx>, ) -> Option<(mir::Local, CannotMoveOut)> { use rustc::mir::Place::*; + // Dereference. You cannot move things out from a borrowed value. let mut deref = false; - // Accessing a field of an ADT that has `Drop` + // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. let mut field = false; loop { -- cgit 1.4.1-3-g733a5 From e7d18084fb8e6646489be545d20d050623d8d45d Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 10 Dec 2018 15:59:21 +0900 Subject: Only check the assignment found at last If there are more than one such assignment, the last one may be the one supplied to `clone` method. Makes `find_stmt_assigns_to` internally reverses the iterator to make the intent to "iterate statements backward" clear. --- clippy_lints/src/redundant_clone.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 68b79869718..0d31129f30a 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { mir, arg, from_borrow, - bbdata.statements.iter().rev() + bbdata.statements.iter() )); if from_borrow && cannot_move_out { @@ -166,7 +166,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { mir, pred_arg, true, - mir[ps[0]].statements.iter().rev() + mir[ps[0]].statements.iter() )); if cannot_move_out { continue; @@ -257,23 +257,29 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( mir: &mir::Mir<'tcx>, to: mir::Local, by_ref: bool, - mut stmts: impl Iterator>, + stmts: impl DoubleEndedIterator>, ) -> Option<(mir::Local, CannotMoveOut)> { - stmts.find_map(|stmt| { - if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { - if *local == to { - if by_ref { - if let mir::Rvalue::Ref(_, _, ref place) = **v { - return base_local_and_movability(cx, mir, place); - } - } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v { - return base_local_and_movability(cx, mir, place); + stmts + .rev() + .find_map(|stmt| { + if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind { + if *local == to { + return Some(v); } } - } - None - }) + None + }) + .and_then(|v| { + if by_ref { + if let mir::Rvalue::Ref(_, _, ref place) = **v { + return base_local_and_movability(cx, mir, place); + } + } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v { + return base_local_and_movability(cx, mir, place); + } + None + }) } /// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself -- cgit 1.4.1-3-g733a5 From 2213904024b60ea68af337bf23ab4a653a4bfbc9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 7 Dec 2018 13:00:21 +0100 Subject: Small updates to CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bff456203db..59f94cca048 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,7 +156,7 @@ to style guidelines. The code has to be formatted by `rustfmt` before a PR will It can be installed via `rustup`: ```bash -rustup component add rustfmt-preview +rustup component add rustfmt ``` Use `cargo fmt --all` to format the whole codebase. @@ -220,7 +220,7 @@ That's why the `else_if_without_else` example uses the `register_early_lint_pass ### Fixing build failures caused by Rust -Clippy will sometimes break because it still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals. +Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals. In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. -- cgit 1.4.1-3-g733a5 From 740634a15481237482477de59bc48bc9be6ffd5a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 10 Dec 2018 07:33:11 +0100 Subject: Document bors/homu --- CONTRIBUTING.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 59f94cca048..ce9512a80dc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,7 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [How Clippy works](#how-clippy-works) * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) * [Issue and PR Triage](#issue-and-pr-triage) +* [Bors and Homu](#bors-and-homu) * [Contributions](#contributions) ## Getting started @@ -257,6 +258,17 @@ Our highest priority is fixing [crashes][l-crash] and [bugs][l-bug]. We don't want Clippy to crash on your code and we want it to be as reliable as the suggestions from Rust compiler errors. +## Bors and Homu + +We use a bot powered by [Homu][homu] to help automate testing and landing of pull +requests in Clippy. The bot's username is @bors. + +You can find the Clippy bors queue [here][homu_queue]. + +If you have @bors permissions, you can find an overview of the available +commands [here][homu_instructions]. + + ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will @@ -288,3 +300,6 @@ or the [MIT](http://opensource.org/licenses/MIT) license. [triage]: https://forge.rust-lang.org/triage-procedure.html [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A +[homu]: https://github.com/servo/homu +[homu_instructions]: https://buildbot2.rust-lang.org/homu/ +[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy -- cgit 1.4.1-3-g733a5 From 7bcc2cd9c8d2933d4a72e090db72f65a4cfb749e Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 10 Dec 2018 06:27:19 +0100 Subject: update test stderr --- ci/base-tests.sh | 9 +- .../conf_french_blacklisted_name.stderr | 28 +- tests/ui-toml/toml_trivially_copy/test.stderr | 8 +- tests/ui/absurd-extreme-comparisons.stderr | 72 ++-- tests/ui/approx_const.stderr | 76 ++-- tests/ui/arithmetic.stderr | 46 +-- tests/ui/assign_ops.stderr | 36 +- tests/ui/assign_ops2.stderr | 76 ++-- tests/ui/attrs.stderr | 12 +- tests/ui/author/matches.stderr | 8 +- tests/ui/bit_masks.stderr | 68 ++-- tests/ui/blacklisted_name.stderr | 56 +-- tests/ui/block_in_if_condition.stderr | 42 ++- tests/ui/bool_comparison.stderr | 30 +- tests/ui/booleans.stderr | 132 +++---- tests/ui/borrow_box.stderr | 20 +- tests/ui/box_vec.stderr | 4 +- tests/ui/builtin-type-shadow.stderr | 10 +- tests/ui/bytecount.stderr | 16 +- tests/ui/cast.stderr | 112 +++--- tests/ui/cast_alignment.stderr | 8 +- tests/ui/cast_lossless_float.stderr | 40 +-- tests/ui/cast_lossless_integer.stderr | 72 ++-- tests/ui/cast_size.stderr | 76 ++-- tests/ui/char_lit_as_u8.stderr | 4 +- tests/ui/checked_unwrap.stderr | 226 ++++++------ tests/ui/cmp_nan.stderr | 48 +-- tests/ui/cmp_null.stderr | 8 +- tests/ui/cmp_owned.stderr | 36 +- tests/ui/collapsible_if.stderr | 304 ++++++++-------- tests/ui/complex_types.stderr | 60 ++-- tests/ui/const_static_lifetime.stderr | 52 +-- tests/ui/copies.stderr | 391 +++++++++++---------- tests/ui/copy_iterator.stderr | 14 +- tests/ui/cstring.stderr | 8 +- tests/ui/cyclomatic_complexity.stderr | 273 +++++++------- tests/ui/cyclomatic_complexity_attr_used.stderr | 16 +- tests/ui/decimal_literal_representation.stderr | 20 +- tests/ui/default_trait_access.stderr | 32 +- tests/ui/deprecated.stderr | 20 +- tests/ui/derive.stderr | 120 ++++--- tests/ui/dlist.stderr | 26 +- tests/ui/double_comparison.stderr | 32 +- tests/ui/double_neg.stderr | 4 +- tests/ui/drop_forget_copy.stderr | 48 +-- tests/ui/drop_forget_ref.stderr | 144 ++++---- tests/ui/duplicate_underscore_argument.stderr | 4 +- tests/ui/duration_subsec.stderr | 20 +- tests/ui/else_if_without_else.stderr | 18 +- tests/ui/empty_enum.stderr | 8 +- tests/ui/entry.stderr | 70 ++-- tests/ui/enum_glob_use.stderr | 8 +- tests/ui/enum_variants.stderr | 52 +-- tests/ui/enums_clike.stderr | 32 +- tests/ui/erasing_op.stderr | 12 +- tests/ui/escape_analysis.stderr | 8 +- tests/ui/eta.stderr | 20 +- tests/ui/eval_order_dependence.stderr | 44 +-- tests/ui/excessive_precision.stderr | 72 ++-- tests/ui/expect_fun_call.stderr | 24 +- tests/ui/explicit_counter_loop.stderr | 8 +- tests/ui/explicit_write.stderr | 24 +- tests/ui/fallible_impl_from.stderr | 84 ++--- tests/ui/filter_methods.stderr | 42 +-- tests/ui/float_cmp.stderr | 24 +- tests/ui/for_loop.stderr | 278 +++++++-------- tests/ui/formatting.stderr | 85 +---- tests/ui/functions.stderr | 51 ++- tests/ui/fxhash.stderr | 24 +- tests/ui/get_unwrap.stderr | 48 +-- tests/ui/identity_conversion.stderr | 44 +-- tests/ui/identity_op.stderr | 32 +- tests/ui/if_not_else.stderr | 24 +- tests/ui/impl.stderr | 32 +- tests/ui/implicit_hasher.stderr | 80 ++--- tests/ui/implicit_return.stderr | 36 +- tests/ui/inconsistent_digit_grouping.stderr | 20 +- tests/ui/indexing_slicing.stderr | 172 ++++----- tests/ui/infallible_destructuring_match.stderr | 24 +- tests/ui/infinite_iter.stderr | 79 +++-- tests/ui/infinite_loop.stderr | 36 +- tests/ui/inline_fn_without_body.stderr | 20 +- tests/ui/int_plus_one.stderr | 24 +- tests/ui/into_iter_on_ref.stderr | 42 +-- tests/ui/invalid_ref.stderr | 24 +- tests/ui/invalid_upcast_comparisons.stderr | 108 +++--- tests/ui/issue-3145.stderr | 4 +- tests/ui/issue_2356.stderr | 8 +- tests/ui/item_after_statement.stderr | 16 +- tests/ui/large_digit_groups.stderr | 36 +- tests/ui/large_enum_variant.stderr | 42 +-- tests/ui/len_zero.stderr | 112 +++--- tests/ui/let_if_seq.stderr | 50 +-- tests/ui/let_return.stderr | 16 +- tests/ui/let_unit.stderr | 8 +- tests/ui/lifetimes.stderr | 124 ++++--- tests/ui/lint_without_lint_pass.stderr | 12 +- tests/ui/map_clone.stderr | 12 +- tests/ui/map_flatten.stderr | 4 +- tests/ui/match_bool.stderr | 111 ++++-- tests/ui/match_overlapping_arm.stderr | 32 +- tests/ui/matches.stderr | 222 ++++++------ tests/ui/mem_discriminant.stderr | 56 +-- tests/ui/mem_forget.stderr | 12 +- tests/ui/mem_replace.stderr | 8 +- tests/ui/min_max.stderr | 28 +- tests/ui/missing-doc.stderr | 218 ++++++------ tests/ui/missing_inline.stderr | 24 +- tests/ui/module_inception.stderr | 16 +- tests/ui/modulo_one.stderr | 4 +- tests/ui/mut_from_ref.stderr | 40 +-- tests/ui/mut_mut.stderr | 52 +-- tests/ui/mut_range_bound.stderr | 28 +- tests/ui/mut_reference.stderr | 12 +- tests/ui/mutex_atomic.stderr | 28 +- tests/ui/needless_bool.stderr | 146 +++++--- tests/ui/needless_borrow.stderr | 24 +- tests/ui/needless_borrowed_ref.stderr | 16 +- tests/ui/needless_collect.stderr | 16 +- tests/ui/needless_continue.stderr | 4 +- tests/ui/needless_pass_by_value.stderr | 96 ++--- tests/ui/needless_range_loop.stderr | 48 +-- tests/ui/needless_return.stderr | 34 +- tests/ui/needless_update.stderr | 4 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 16 +- tests/ui/neg_multiply.stderr | 8 +- tests/ui/never_loop.stderr | 112 +++--- tests/ui/new_ret_no_self.stderr | 24 +- tests/ui/new_without_default.stderr | 38 +- tests/ui/no_effect.stderr | 104 +++--- tests/ui/non_copy_const.stderr | 158 ++++----- tests/ui/non_expressive_names.stderr | 114 +++--- tests/ui/ok_expect.stderr | 20 +- tests/ui/ok_if_let.stderr | 12 +- tests/ui/op_ref.stderr | 10 +- tests/ui/open_options.stderr | 28 +- tests/ui/option_map_unit_fn.stderr | 250 ++++++++----- tests/ui/option_option.stderr | 38 +- tests/ui/overflow_check_conditional.stderr | 32 +- tests/ui/panic_unimplemented.stderr | 20 +- tests/ui/partialeq_ne_impl.stderr | 8 +- tests/ui/patterns.stderr | 4 +- tests/ui/precedence.stderr | 36 +- tests/ui/print.stderr | 36 +- tests/ui/print_literal.stderr | 64 ++-- tests/ui/print_with_newline.stderr | 16 +- tests/ui/println_empty_string.stderr | 8 +- tests/ui/ptr_arg.stderr | 48 +-- tests/ui/ptr_offset_with_cast.stderr | 8 +- tests/ui/question_mark.stderr | 18 +- tests/ui/range.stderr | 26 +- tests/ui/range_plus_minus_one.stderr | 48 +-- tests/ui/redundant_clone.stderr | 8 +- tests/ui/redundant_closure_call.stderr | 24 +- tests/ui/redundant_field_names.stderr | 28 +- tests/ui/redundant_pattern_matching.stderr | 88 +++-- tests/ui/reference.stderr | 46 +-- tests/ui/regex.stderr | 96 ++--- tests/ui/replace_consts.stderr | 144 ++++---- tests/ui/result_map_unit_fn.stderr | 246 ++++++++----- tests/ui/serde.stderr | 7 +- tests/ui/shadow.stderr | 92 ++--- tests/ui/short_circuit_statement.stderr | 12 +- tests/ui/single_char_pattern.stderr | 80 ++--- tests/ui/single_match.stderr | 78 ++-- tests/ui/single_match_else.stderr | 16 +- tests/ui/starts_ends_with.stderr | 46 +-- tests/ui/string_extend.stderr | 12 +- tests/ui/strings.stderr | 44 +-- tests/ui/stutter.stderr | 20 +- tests/ui/suspicious_arithmetic_impl.stderr | 8 +- tests/ui/swap.stderr | 56 +-- tests/ui/toplevel_ref_arg.stderr | 28 +- tests/ui/trailing_zeros.stderr | 10 +- tests/ui/transmute.stderr | 158 ++++----- tests/ui/transmute_64bit.stderr | 8 +- tests/ui/trivially_copy_pass_by_ref.stderr | 60 ++-- tests/ui/types.stderr | 6 +- tests/ui/unicode.stderr | 12 +- tests/ui/unit_arg.stderr | 52 +-- tests/ui/unit_cmp.stderr | 22 +- tests/ui/unnecessary_clone.stderr | 58 +-- tests/ui/unnecessary_filter_map.stderr | 30 +- tests/ui/unnecessary_fold.stderr | 20 +- tests/ui/unnecessary_operation.stderr | 88 ++--- tests/ui/unnecessary_ref.stderr | 8 +- tests/ui/unneeded_field_pattern.stderr | 8 +- tests/ui/unreadable_literal.stderr | 20 +- tests/ui/unsafe_removed_from_name.stderr | 14 +- tests/ui/unused_io_amount.stderr | 24 +- tests/ui/unused_labels.stderr | 26 +- tests/ui/unused_lt.stderr | 12 +- tests/ui/unwrap_or.stderr | 10 +- tests/ui/use_self.stderr | 58 +-- tests/ui/used_underscore_binding.stderr | 20 +- tests/ui/useless_asref.stderr | 48 +-- tests/ui/useless_attribute.stderr | 16 +- tests/ui/vec.stderr | 26 +- tests/ui/while_loop.stderr | 112 +++--- tests/ui/write_literal.stderr | 64 ++-- tests/ui/write_with_newline.stderr | 16 +- tests/ui/writeln_empty_string.stderr | 8 +- tests/ui/wrong_self_convention.stderr | 48 +-- tests/ui/zero_div_zero.stderr | 36 +- tests/ui/zero_ptr.stderr | 8 +- 205 files changed, 5203 insertions(+), 4909 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 6eeab6671cb..dfc5ad99e0c 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -28,6 +28,9 @@ cd clippy_dev && cargo test && cd .. ./util/dev update_lints --check cargo +nightly fmt --all -- --check + +#avoid loop spam +set +ex # make sure tests are formatted # some lints are sensitive to formatting, exclude some files @@ -36,7 +39,9 @@ for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/fo rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true done -if $needs_reformatting - "Tests need reformatting!" +if [ "${needs_reformatting}" = true] ; then + echo "Tests need reformatting!" exit 2 fi + +set -ex diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr index dd414657c28..e67cdd8f9dd 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -1,45 +1,45 @@ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:19:9 + --> $DIR/conf_french_blacklisted_name.rs:15:9 | -19 | fn test(toto: ()) {} +15 | fn test(toto: ()) {} | ^^^^ | = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:22:9 + --> $DIR/conf_french_blacklisted_name.rs:18:9 | -22 | let toto = 42; +18 | let toto = 42; | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:23:9 + --> $DIR/conf_french_blacklisted_name.rs:19:9 | -23 | let tata = 42; +19 | let tata = 42; | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:24:9 + --> $DIR/conf_french_blacklisted_name.rs:20:9 | -24 | let titi = 42; +20 | let titi = 42; | ^^^^ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:30:10 + --> $DIR/conf_french_blacklisted_name.rs:26:10 | -30 | (toto, Some(tata), titi @ Some(_)) => (), +26 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:30:21 + --> $DIR/conf_french_blacklisted_name.rs:26:21 | -30 | (toto, Some(tata), titi @ Some(_)) => (), +26 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:30:28 + --> $DIR/conf_french_blacklisted_name.rs:26:28 | -30 | (toto, Some(tata), titi @ Some(_)) => (), +26 | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index ad3ca831fd7..efa9223bde8 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,15 +1,15 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:23:11 + --> $DIR/test.rs:20:11 | -23 | fn bad(x: &u16, y: &Foo) { +20 | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:23:20 + --> $DIR/test.rs:20:20 | -23 | fn bad(x: &u16, y: &Foo) { +20 | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 895794da71a..00f7086dc55 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -1,144 +1,144 @@ error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:17:5 + --> $DIR/absurd-extreme-comparisons.rs:23:5 | -17 | u <= 0; +23 | u <= 0; | ^^^^^^ | = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings` = help: because 0 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:18:5 + --> $DIR/absurd-extreme-comparisons.rs:24:5 | -18 | u <= Z; +24 | u <= Z; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == Z instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:19:5 + --> $DIR/absurd-extreme-comparisons.rs:25:5 | -19 | u < Z; +25 | u < Z; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:20:5 + --> $DIR/absurd-extreme-comparisons.rs:26:5 | -20 | Z >= u; +26 | Z >= u; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using Z == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:21:5 + --> $DIR/absurd-extreme-comparisons.rs:27:5 | -21 | Z > u; +27 | Z > u; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:22:5 + --> $DIR/absurd-extreme-comparisons.rs:28:5 | -22 | u > std::u32::MAX; +28 | u > std::u32::MAX; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:23:5 + --> $DIR/absurd-extreme-comparisons.rs:29:5 | -23 | u >= std::u32::MAX; +29 | u >= std::u32::MAX; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == std::u32::MAX instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:24:5 + --> $DIR/absurd-extreme-comparisons.rs:30:5 | -24 | std::u32::MAX < u; +30 | std::u32::MAX < u; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:25:5 + --> $DIR/absurd-extreme-comparisons.rs:31:5 | -25 | std::u32::MAX <= u; +31 | std::u32::MAX <= u; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using std::u32::MAX == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:26:5 + --> $DIR/absurd-extreme-comparisons.rs:32:5 | -26 | 1-1 > u; +32 | 1-1 > u; | ^^^^^^^ | = help: because 1-1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:27:5 + --> $DIR/absurd-extreme-comparisons.rs:33:5 | -27 | u >= !0; +33 | u >= !0; | ^^^^^^^ | = help: because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:28:5 + --> $DIR/absurd-extreme-comparisons.rs:34:5 | -28 | u <= 12 - 2*6; +34 | u <= 12 - 2*6; | ^^^^^^^^^^^^^ | = help: because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:30:5 + --> $DIR/absurd-extreme-comparisons.rs:36:5 | -30 | i < -127 - 1; +36 | i < -127 - 1; | ^^^^^^^^^^^^ | = help: because -127 - 1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:31:5 + --> $DIR/absurd-extreme-comparisons.rs:37:5 | -31 | std::i8::MAX >= i; +37 | std::i8::MAX >= i; | ^^^^^^^^^^^^^^^^^ | = help: because std::i8::MAX is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:32:5 + --> $DIR/absurd-extreme-comparisons.rs:38:5 | -32 | 3-7 < std::i32::MIN; +38 | 3-7 < std::i32::MIN; | ^^^^^^^^^^^^^^^^^^^ | = help: because std::i32::MIN is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:34:5 + --> $DIR/absurd-extreme-comparisons.rs:40:5 | -34 | b >= true; +40 | b >= true; | ^^^^^^^^^ | = help: because true is the maximum value for this type, the case where the two sides are not equal never occurs, consider using b == true instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:35:5 + --> $DIR/absurd-extreme-comparisons.rs:41:5 | -35 | false > b; +41 | false > b; | ^^^^^^^^^ | = help: because false is the minimum value for this type, this comparison is always false error: <-comparison of unit values detected. This will always be false - --> $DIR/absurd-extreme-comparisons.rs:38:5 + --> $DIR/absurd-extreme-comparisons.rs:44:5 | -38 | () < {}; +44 | () < {}; | ^^^^^^^ | = note: #[deny(clippy::unit_cmp)] on by default diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index a765ffb64de..cee7fe6919a 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -1,117 +1,117 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:17:16 + --> $DIR/approx_const.rs:13:16 | -17 | let my_e = 2.7182; +13 | let my_e = 2.7182; | ^^^^^^ | = note: `-D clippy::approx-constant` implied by `-D warnings` error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:18:20 + --> $DIR/approx_const.rs:14:20 | -18 | let almost_e = 2.718; +14 | let almost_e = 2.718; | ^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly - --> $DIR/approx_const.rs:21:24 + --> $DIR/approx_const.rs:17:24 | -21 | let my_1_frac_pi = 0.3183; +17 | let my_1_frac_pi = 0.3183; | ^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:24:28 + --> $DIR/approx_const.rs:20:28 | -24 | let my_frac_1_sqrt_2 = 0.70710678; +20 | let my_frac_1_sqrt_2 = 0.70710678; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:25:32 + --> $DIR/approx_const.rs:21:32 | -25 | let almost_frac_1_sqrt_2 = 0.70711; +21 | let almost_frac_1_sqrt_2 = 0.70711; | ^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly - --> $DIR/approx_const.rs:28:24 + --> $DIR/approx_const.rs:24:24 | -28 | let my_frac_2_pi = 0.63661977; +24 | let my_frac_2_pi = 0.63661977; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly - --> $DIR/approx_const.rs:31:27 + --> $DIR/approx_const.rs:27:27 | -31 | let my_frac_2_sq_pi = 1.128379; +27 | let my_frac_2_sq_pi = 1.128379; | ^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly - --> $DIR/approx_const.rs:34:24 + --> $DIR/approx_const.rs:30:24 | -34 | let my_frac_pi_2 = 1.57079632679; +30 | let my_frac_pi_2 = 1.57079632679; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly - --> $DIR/approx_const.rs:37:24 + --> $DIR/approx_const.rs:33:24 | -37 | let my_frac_pi_3 = 1.04719755119; +33 | let my_frac_pi_3 = 1.04719755119; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly - --> $DIR/approx_const.rs:40:24 + --> $DIR/approx_const.rs:36:24 | -40 | let my_frac_pi_4 = 0.785398163397; +36 | let my_frac_pi_4 = 0.785398163397; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly - --> $DIR/approx_const.rs:43:24 + --> $DIR/approx_const.rs:39:24 | -43 | let my_frac_pi_6 = 0.523598775598; +39 | let my_frac_pi_6 = 0.523598775598; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly - --> $DIR/approx_const.rs:46:24 + --> $DIR/approx_const.rs:42:24 | -46 | let my_frac_pi_8 = 0.3926990816987; +42 | let my_frac_pi_8 = 0.3926990816987; | ^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly - --> $DIR/approx_const.rs:49:20 + --> $DIR/approx_const.rs:45:20 | -49 | let my_ln_10 = 2.302585092994046; +45 | let my_ln_10 = 2.302585092994046; | ^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly - --> $DIR/approx_const.rs:52:19 + --> $DIR/approx_const.rs:48:19 | -52 | let my_ln_2 = 0.6931471805599453; +48 | let my_ln_2 = 0.6931471805599453; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly - --> $DIR/approx_const.rs:55:22 + --> $DIR/approx_const.rs:51:22 | -55 | let my_log10_e = 0.4342944819032518; +51 | let my_log10_e = 0.4342944819032518; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly - --> $DIR/approx_const.rs:58:21 + --> $DIR/approx_const.rs:54:21 | -58 | let my_log2_e = 1.4426950408889634; +54 | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:61:17 + --> $DIR/approx_const.rs:57:17 | -61 | let my_pi = 3.1415; +57 | let my_pi = 3.1415; | ^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:62:21 + --> $DIR/approx_const.rs:58:21 | -62 | let almost_pi = 3.14; +58 | let almost_pi = 3.14; | ^^^^ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:65:18 + --> $DIR/approx_const.rs:61:18 | -65 | let my_sq2 = 1.4142; +61 | let my_sq2 = 1.4142; | ^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index f3a1db16b48..1dff9941bb2 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,72 +1,72 @@ error: integer arithmetic detected - --> $DIR/arithmetic.rs:17:5 + --> $DIR/arithmetic.rs:22:5 | -17 | 1 + i; +22 | 1 + i; | ^^^^^ | = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/arithmetic.rs:18:5 + --> $DIR/arithmetic.rs:23:5 | -18 | i * 2; +23 | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:19:5 + --> $DIR/arithmetic.rs:24:5 | -19 | / 1 % -20 | | i / 2; // no error, this is part of the expression in the preceding line +24 | / 1 % +25 | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:21:5 + --> $DIR/arithmetic.rs:26:5 | -21 | i - 2 + 2 - i; +26 | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:22:5 + --> $DIR/arithmetic.rs:27:5 | -22 | -i; +27 | -i; | ^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:32:5 + --> $DIR/arithmetic.rs:37:5 | -32 | f * 2.0; +37 | f * 2.0; | ^^^^^^^ | = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:34:5 + --> $DIR/arithmetic.rs:39:5 | -34 | 1.0 + f; +39 | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:35:5 + --> $DIR/arithmetic.rs:40:5 | -35 | f * 2.0; +40 | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:36:5 + --> $DIR/arithmetic.rs:41:5 | -36 | f / 2.0; +41 | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:37:5 + --> $DIR/arithmetic.rs:42:5 | -37 | f - 2.0 * 4.2; +42 | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:38:5 + --> $DIR/arithmetic.rs:43:5 | -38 | -f; +43 | -f; | ^^ error: aborting due to 11 previous errors diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 20ed51334ab..7acbdc89984 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,57 +1,57 @@ error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:17:5 + --> $DIR/assign_ops.rs:14:5 | -17 | a = a + 1; +14 | a = a + 1; | ^^^^^^^^^ help: replace it with: `a += 1` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:18:5 + --> $DIR/assign_ops.rs:15:5 | -18 | a = 1 + a; +15 | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:19:5 + --> $DIR/assign_ops.rs:16:5 | -19 | a = a - 1; +16 | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:20:5 + --> $DIR/assign_ops.rs:17:5 | -20 | a = a * 99; +17 | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:21:5 + --> $DIR/assign_ops.rs:18:5 | -21 | a = 42 * a; +18 | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:22:5 + --> $DIR/assign_ops.rs:19:5 | -22 | a = a / 2; +19 | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:23:5 + --> $DIR/assign_ops.rs:20:5 | -23 | a = a % 5; +20 | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:24:5 + --> $DIR/assign_ops.rs:21:5 | -24 | a = a & 1; +21 | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:30:5 + --> $DIR/assign_ops.rs:27:5 | -30 | s = s + "bla"; +27 | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: aborting due to 9 previous errors diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index bd49c3cdd80..26ff079ad62 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -1,135 +1,135 @@ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:18:5 + --> $DIR/assign_ops2.rs:14:5 | -18 | a += a + 1; +14 | a += a + 1; | ^^^^^^^^^^ | = note: `-D clippy::misrefactored-assign-op` implied by `-D warnings` help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with | -18 | a += 1; +14 | a += 1; | ^^^^^^ help: or | -18 | a = a + a + 1; +14 | a = a + a + 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:19:5 + --> $DIR/assign_ops2.rs:15:5 | -19 | a += 1 + a; +15 | a += 1 + a; | ^^^^^^^^^^ help: Did you mean a = a + 1 or a = a + 1 + a? Consider replacing it with | -19 | a += 1; +15 | a += 1; | ^^^^^^ help: or | -19 | a = a + 1 + a; +15 | a = a + 1 + a; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:20:5 + --> $DIR/assign_ops2.rs:16:5 | -20 | a -= a - 1; +16 | a -= a - 1; | ^^^^^^^^^^ help: Did you mean a = a - 1 or a = a - (a - 1)? Consider replacing it with | -20 | a -= 1; +16 | a -= 1; | ^^^^^^ help: or | -20 | a = a - (a - 1); +16 | a = a - (a - 1); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:21:5 + --> $DIR/assign_ops2.rs:17:5 | -21 | a *= a * 99; +17 | a *= a * 99; | ^^^^^^^^^^^ help: Did you mean a = a * 99 or a = a * a * 99? Consider replacing it with | -21 | a *= 99; +17 | a *= 99; | ^^^^^^^ help: or | -21 | a = a * a * 99; +17 | a = a * a * 99; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:22:5 + --> $DIR/assign_ops2.rs:18:5 | -22 | a *= 42 * a; +18 | a *= 42 * a; | ^^^^^^^^^^^ help: Did you mean a = a * 42 or a = a * 42 * a? Consider replacing it with | -22 | a *= 42; +18 | a *= 42; | ^^^^^^^ help: or | -22 | a = a * 42 * a; +18 | a = a * 42 * a; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:23:5 + --> $DIR/assign_ops2.rs:19:5 | -23 | a /= a / 2; +19 | a /= a / 2; | ^^^^^^^^^^ help: Did you mean a = a / 2 or a = a / (a / 2)? Consider replacing it with | -23 | a /= 2; +19 | a /= 2; | ^^^^^^ help: or | -23 | a = a / (a / 2); +19 | a = a / (a / 2); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:24:5 + --> $DIR/assign_ops2.rs:20:5 | -24 | a %= a % 5; +20 | a %= a % 5; | ^^^^^^^^^^ help: Did you mean a = a % 5 or a = a % (a % 5)? Consider replacing it with | -24 | a %= 5; +20 | a %= 5; | ^^^^^^ help: or | -24 | a = a % (a % 5); +20 | a = a % (a % 5); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:25:5 + --> $DIR/assign_ops2.rs:21:5 | -25 | a &= a & 1; +21 | a &= a & 1; | ^^^^^^^^^^ help: Did you mean a = a & 1 or a = a & a & 1? Consider replacing it with | -25 | a &= 1; +21 | a &= 1; | ^^^^^^ help: or | -25 | a = a & a & 1; +21 | a = a & a & 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:26:5 + --> $DIR/assign_ops2.rs:22:5 | -26 | a *= a * a; +22 | a *= a * a; | ^^^^^^^^^^ help: Did you mean a = a * a or a = a * a * a? Consider replacing it with | -26 | a *= a; +22 | a *= a; | ^^^^^^ help: or | -26 | a = a * a * a; +22 | a = a * a * a; | ^^^^^^^^^^^^^ error: manual implementation of an assign operation - --> $DIR/assign_ops2.rs:63:5 + --> $DIR/assign_ops2.rs:59:5 | -63 | buf = buf + cows.clone(); +59 | buf = buf + cows.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index a361d0968f5..1331fa2912c 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,23 +1,23 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> $DIR/attrs.rs:16:1 + --> $DIR/attrs.rs:12:1 | -16 | #[inline(always)] +12 | #[inline(always)] | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:37:14 + --> $DIR/attrs.rs:32:14 | -37 | #[deprecated(since = "forever")] +32 | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:40:14 + --> $DIR/attrs.rs:35:14 | -40 | #[deprecated(since = "1")] +35 | #[deprecated(since = "1")] | ^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr index d78a173316b..4b895b0b8e3 100644 --- a/tests/ui/author/matches.stderr +++ b/tests/ui/author/matches.stderr @@ -1,14 +1,14 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/matches.rs:19:13 + --> $DIR/matches.rs:18:13 | -19 | x +18 | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/matches.rs:18:21 + --> $DIR/matches.rs:17:21 | -18 | let x = 3; +17 | let x = 3; | ^ error: aborting due to previous error diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index f0f450fc169..853f5a992f3 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -1,109 +1,109 @@ error: &-masking with zero - --> $DIR/bit_masks.rs:22:5 + --> $DIR/bit_masks.rs:23:5 | -22 | x & 0 == 0; +23 | x & 0 == 0; | ^^^^^^^^^^ | = note: `-D clippy::bad-bit-mask` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:22:5 + --> $DIR/bit_masks.rs:23:5 | -22 | x & 0 == 0; +23 | x & 0 == 0; | ^^^^^ | = note: #[deny(clippy::erasing_op)] on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:25:5 + --> $DIR/bit_masks.rs:26:5 | -25 | x & 2 == 1; +26 | x & 2 == 1; | ^^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:29:5 + --> $DIR/bit_masks.rs:30:5 | -29 | x | 3 == 2; +30 | x | 3 == 2; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 1` will never be higher than `1` - --> $DIR/bit_masks.rs:31:5 + --> $DIR/bit_masks.rs:32:5 | -31 | x & 1 > 1; +32 | x & 1 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:35:5 + --> $DIR/bit_masks.rs:36:5 | -35 | x | 2 > 1; +36 | x | 2 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ & 7` can never be equal to `8` - --> $DIR/bit_masks.rs:42:5 + --> $DIR/bit_masks.rs:43:5 | -42 | x & THREE_BITS == 8; +43 | x & THREE_BITS == 8; | ^^^^^^^^^^^^^^^^^^^ error: incompatible bit mask: `_ | 7` will never be lower than `7` - --> $DIR/bit_masks.rs:43:5 + --> $DIR/bit_masks.rs:44:5 | -43 | x | EVEN_MORE_REDIRECTION < 7; +44 | x | EVEN_MORE_REDIRECTION < 7; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &-masking with zero - --> $DIR/bit_masks.rs:45:5 + --> $DIR/bit_masks.rs:46:5 | -45 | 0 & x == 0; +46 | 0 & x == 0; | ^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:45:5 + --> $DIR/bit_masks.rs:46:5 | -45 | 0 & x == 0; +46 | 0 & x == 0; | ^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:49:5 + --> $DIR/bit_masks.rs:50:5 | -49 | 1 < 2 | x; +50 | 1 < 2 | x; | ^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:50:5 + --> $DIR/bit_masks.rs:51:5 | -50 | 2 == 3 | x; +51 | 2 == 3 | x; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:51:5 + --> $DIR/bit_masks.rs:52:5 | -51 | 1 == x & 2; +52 | 1 == x & 2; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:62:5 + --> $DIR/bit_masks.rs:63:5 | -62 | x | 1 > 3; +63 | x | 1 > 3; | ^^^^^^^^^ | = note: `-D clippy::ineffective-bit-mask` implied by `-D warnings` error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly - --> $DIR/bit_masks.rs:63:5 + --> $DIR/bit_masks.rs:64:5 | -63 | x | 1 < 4; +64 | x | 1 < 4; | ^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:64:5 + --> $DIR/bit_masks.rs:65:5 | -64 | x | 1 <= 3; +65 | x | 1 <= 3; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared directly - --> $DIR/bit_masks.rs:65:5 + --> $DIR/bit_masks.rs:66:5 | -65 | x | 1 >= 8; +66 | x | 1 >= 8; | ^^^^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 1e253eba140..707d36b24b2 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -1,87 +1,87 @@ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:17:9 + --> $DIR/blacklisted_name.rs:20:9 | -17 | fn test(foo: ()) {} +20 | fn test(foo: ()) {} | ^^^ | = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:20:9 + --> $DIR/blacklisted_name.rs:23:9 | -20 | let foo = 42; +23 | let foo = 42; | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:21:9 + --> $DIR/blacklisted_name.rs:24:9 | -21 | let bar = 42; +24 | let bar = 42; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:22:9 + --> $DIR/blacklisted_name.rs:25:9 | -22 | let baz = 42; +25 | let baz = 42; | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:28:10 + --> $DIR/blacklisted_name.rs:31:10 | -28 | (foo, Some(bar), baz @ Some(_)) => (), +31 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:28:20 + --> $DIR/blacklisted_name.rs:31:20 | -28 | (foo, Some(bar), baz @ Some(_)) => (), +31 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:28:26 + --> $DIR/blacklisted_name.rs:31:26 | -28 | (foo, Some(bar), baz @ Some(_)) => (), +31 | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:33:19 + --> $DIR/blacklisted_name.rs:36:19 | -33 | fn issue_1647(mut foo: u8) { +36 | fn issue_1647(mut foo: u8) { | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:34:13 + --> $DIR/blacklisted_name.rs:37:13 | -34 | let mut bar = 0; +37 | let mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:35:21 + --> $DIR/blacklisted_name.rs:38:21 | -35 | if let Some(mut baz) = Some(42) {} +38 | if let Some(mut baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:39:13 + --> $DIR/blacklisted_name.rs:42:13 | -39 | let ref bar = 0; +42 | let ref bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:40:21 + --> $DIR/blacklisted_name.rs:43:21 | -40 | if let Some(ref baz) = Some(42) {} +43 | if let Some(ref baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:44:17 + --> $DIR/blacklisted_name.rs:47:17 | -44 | let ref mut bar = 0; +47 | let ref mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:45:25 + --> $DIR/blacklisted_name.rs:48:25 | -45 | if let Some(ref mut baz) = Some(42) {} +48 | if let Some(ref mut baz) = Some(42) {} | ^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index b0036d1ee23..d83cef26a8b 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,11 +1,11 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:40:8 + --> $DIR/block_in_if_condition.rs:35:8 | -40 | if { +35 | if { | ________^ -41 | | let x = 3; -42 | | x == 3 -43 | | } { +36 | | let x = 3; +37 | | x == 3 +38 | | } { | |_____^ | = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` @@ -19,9 +19,9 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; inste } ... error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:51:8 + --> $DIR/block_in_if_condition.rs:46:8 | -51 | if { true } { +46 | if { true } { | ^^^^^^^^ | = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` @@ -31,21 +31,29 @@ error: omit braces around single expression condition } ... error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:68:49 - | -68 | if v == 3 && sky == "blue" && predicate(|x| { let target = 3; x == target }, v) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/block_in_if_condition.rs:66:17 + | +66 | |x| { + | _________________^ +67 | | let target = 3; +68 | | x == target +69 | | }, + | |_____________^ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:71:22 - | -71 | if predicate(|x| { let target = 3; x == target }, v) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/block_in_if_condition.rs:75:13 + | +75 | |x| { + | _____________^ +76 | | let target = 3; +77 | | x == target +78 | | }, + | |_________^ error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:77:8 + --> $DIR/block_in_if_condition.rs:85:8 | -77 | if true && x == 3 { +85 | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index b4a1545b49e..d136bc656b6 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,7 +1,7 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:17:8 + --> $DIR/bool_comparison.rs:13:8 | -17 | if x == true { "yes" } else { "no" }; +13 | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` | = note: `-D clippy::bool-comparison` implied by `-D warnings` @@ -9,43 +9,43 @@ error: equality checks against true are unnecessary error: equality checks against false can be replaced by a negation --> $DIR/bool_comparison.rs:18:8 | -18 | if x == false { "yes" } else { "no" }; +18 | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:19:8 + --> $DIR/bool_comparison.rs:23:8 | -19 | if true == x { "yes" } else { "no" }; +23 | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:20:8 + --> $DIR/bool_comparison.rs:28:8 | -20 | if false == x { "yes" } else { "no" }; +28 | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:21:8 + --> $DIR/bool_comparison.rs:33:8 | -21 | if x != true { "yes" } else { "no" }; +33 | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:22:8 + --> $DIR/bool_comparison.rs:38:8 | -22 | if x != false { "yes" } else { "no" }; +38 | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:23:8 + --> $DIR/bool_comparison.rs:43:8 | -23 | if true != x { "yes" } else { "no" }; +43 | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:24:8 + --> $DIR/bool_comparison.rs:48:8 | -24 | if false != x { "yes" } else { "no" }; +48 | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: aborting due to 8 previous errors diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 01f821f511f..45205b978ef 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -1,202 +1,202 @@ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:22:13 + --> $DIR/booleans.rs:19:13 | -22 | let _ = a && b || a; +19 | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:22:18 + --> $DIR/booleans.rs:19:18 | -22 | let _ = a && b || a; +19 | let _ = a && b || a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:24:13 + --> $DIR/booleans.rs:21:13 | -24 | let _ = !true; +21 | let _ = !true; | ^^^^^ help: try: `false` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/booleans.rs:25:13 + --> $DIR/booleans.rs:22:13 | -25 | let _ = !false; +22 | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/booleans.rs:26:13 + --> $DIR/booleans.rs:23:13 | -26 | let _ = !!a; +23 | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:27:13 + --> $DIR/booleans.rs:24:13 | -27 | let _ = false && a; +24 | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:27:22 + --> $DIR/booleans.rs:24:22 | -27 | let _ = false && a; +24 | let _ = false && a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:28:13 + --> $DIR/booleans.rs:25:13 | -28 | let _ = false || a; +25 | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/booleans.rs:33:13 + --> $DIR/booleans.rs:30:13 | -33 | let _ = !(!a && b); +30 | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `!b || a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:43:13 + --> $DIR/booleans.rs:40:13 | -43 | let _ = a == b && a != b; +40 | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:43:13 + --> $DIR/booleans.rs:40:13 | -43 | let _ = a == b && a != b; +40 | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:44:13 + --> $DIR/booleans.rs:41:13 | -44 | let _ = a == b && c == 5 && a == b; +41 | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -44 | let _ = a == b && c == 5; +41 | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -44 | let _ = !(c != 5 || a != b); +41 | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:45:13 + --> $DIR/booleans.rs:42:13 | -45 | let _ = a == b && c == 5 && b == a; +42 | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -45 | let _ = a == b && c == 5; +42 | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -45 | let _ = !(c != 5 || a != b); +42 | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:46:13 + --> $DIR/booleans.rs:43:13 | -46 | let _ = a < b && a >= b; +43 | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:46:13 + --> $DIR/booleans.rs:43:13 | -46 | let _ = a < b && a >= b; +43 | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:47:13 + --> $DIR/booleans.rs:44:13 | -47 | let _ = a > b && a <= b; +44 | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:47:13 + --> $DIR/booleans.rs:44:13 | -47 | let _ = a > b && a <= b; +44 | let _ = a > b && a <= b; | ^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:49:13 + --> $DIR/booleans.rs:46:13 | -49 | let _ = a != b || !(a != b || c == d); +46 | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -49 | let _ = c != d || a != b; +46 | let _ = c != d || a != b; | ^^^^^^^^^^^^^^^^ -49 | let _ = !(a == b && c == d); +46 | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:57:13 + --> $DIR/booleans.rs:54:13 | -57 | let _ = !a.is_some(); +54 | let _ = !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:59:13 + --> $DIR/booleans.rs:56:13 | -59 | let _ = !a.is_none(); +56 | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:61:13 + --> $DIR/booleans.rs:58:13 | -61 | let _ = !b.is_err(); +58 | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:63:13 + --> $DIR/booleans.rs:60:13 | -63 | let _ = !b.is_ok(); +60 | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:65:13 + --> $DIR/booleans.rs:62:13 | -65 | let _ = !(a.is_some() && !c); +62 | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:66:13 + --> $DIR/booleans.rs:63:13 | -66 | let _ = !(!c ^ c) || !a.is_some(); +63 | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:67:13 + --> $DIR/booleans.rs:64:13 | -67 | let _ = (!c ^ c) || !a.is_some(); +64 | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:68:13 + --> $DIR/booleans.rs:65:13 | -68 | let _ = !c ^ c || !a.is_some(); +65 | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:120:8 + --> $DIR/booleans.rs:137:8 | -120 | if !res.is_ok() { } +137 | if !res.is_ok() {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:121:8 + --> $DIR/booleans.rs:138:8 | -121 | if !res.is_err() { } +138 | if !res.is_err() {} | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:124:8 + --> $DIR/booleans.rs:141:8 | -124 | if !res.is_some() { } +141 | if !res.is_some() {} | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:125:8 + --> $DIR/booleans.rs:142:8 | -125 | if !res.is_none() { } +142 | if !res.is_none() {} | ^^^^^^^^^^^^^^ help: try: `res.is_some()` error: aborting due to 25 previous errors diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 7cc8eb8da40..0e42fe177ba 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -1,31 +1,31 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:19:19 + --> $DIR/borrow_box.rs:15:19 | -19 | pub fn test1(foo: &mut Box) { +15 | pub fn test1(foo: &mut Box) { | ^^^^^^^^^^^^^^ help: try: `&mut bool` | note: lint level defined here - --> $DIR/borrow_box.rs:14:9 + --> $DIR/borrow_box.rs:10:9 | -14 | #![deny(clippy::borrowed_box)] +10 | #![deny(clippy::borrowed_box)] | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:24:14 + --> $DIR/borrow_box.rs:20:14 | -24 | let foo: &Box; +20 | let foo: &Box; | ^^^^^^^^^^ help: try: `&bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:28:10 + --> $DIR/borrow_box.rs:24:10 | -28 | foo: &'a Box +24 | foo: &'a Box, | ^^^^^^^^^^^^^ help: try: `&'a bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:32:17 + --> $DIR/borrow_box.rs:28:17 | -32 | fn test4(a: &Box); +28 | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` error: aborting due to 4 previous errors diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index 34be890b534..84c0b6c36e3 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -1,7 +1,7 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` - --> $DIR/box_vec.rs:27:18 + --> $DIR/box_vec.rs:23:18 | -27 | pub fn test(foo: Box>) { +23 | pub fn test(foo: Box>) { | ^^^^^^^^^^^^^^ | = note: `-D clippy::box-vec` implied by `-D warnings` diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 11253715716..540d9f4f458 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,17 +1,17 @@ error: This generic shadows the built-in type `u32` - --> $DIR/builtin-type-shadow.rs:15:8 + --> $DIR/builtin-type-shadow.rs:12:8 | -15 | fn foo(a: u32) -> u32 { +12 | fn foo(a: u32) -> u32 { | ^^^ | = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types - --> $DIR/builtin-type-shadow.rs:16:5 + --> $DIR/builtin-type-shadow.rs:13:5 | -15 | fn foo(a: u32) -> u32 { +12 | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type -16 | 42 +13 | 42 | ^^ expected type parameter, found integral variable | = note: expected type `u32` diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index c5c0ec7eda4..605cf287419 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,25 +1,25 @@ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:18:13 + --> $DIR/bytecount.rs:14:13 | -18 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count +14 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` | note: lint level defined here - --> $DIR/bytecount.rs:14:8 + --> $DIR/bytecount.rs:10:8 | -14 | #[deny(clippy::naive_bytecount)] +10 | #[deny(clippy::naive_bytecount)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:20:13 + --> $DIR/bytecount.rs:16:13 | -20 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count +16 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:32:13 + --> $DIR/bytecount.rs:28:13 | -32 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count +28 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` error: aborting due to 3 previous errors diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 1f9ab5712f5..1b6b1e6319c 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,181 +1,181 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:18:5 + --> $DIR/cast.rs:20:5 | -18 | 1i32 as f32; +20 | 1i32 as f32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:19:5 + --> $DIR/cast.rs:21:5 | -19 | 1i64 as f32; +21 | 1i64 as f32; | ^^^^^^^^^^^ error: casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:22:5 | -20 | 1i64 as f64; +22 | 1i64 as f64; | ^^^^^^^^^^^ error: casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:23:5 | -21 | 1u32 as f32; +23 | 1u32 as f32; | ^^^^^^^^^^^ error: casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:22:5 + --> $DIR/cast.rs:24:5 | -22 | 1u64 as f32; +24 | 1u64 as f32; | ^^^^^^^^^^^ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:25:5 | -23 | 1u64 as f64; +25 | 1u64 as f64; | ^^^^^^^^^^^ error: casting f32 to i32 may truncate the value - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:27:5 | -25 | 1f32 as i32; +27 | 1f32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value - --> $DIR/cast.rs:26:5 + --> $DIR/cast.rs:28:5 | -26 | 1f32 as u32; +28 | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value - --> $DIR/cast.rs:26:5 + --> $DIR/cast.rs:28:5 | -26 | 1f32 as u32; +28 | 1f32 as u32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value - --> $DIR/cast.rs:27:5 + --> $DIR/cast.rs:29:5 | -27 | 1f64 as f32; +29 | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:30:5 | -28 | 1i32 as i8; +30 | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may lose the sign of the value - --> $DIR/cast.rs:29:5 + --> $DIR/cast.rs:31:5 | -29 | 1i32 as u8; +31 | 1i32 as u8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value - --> $DIR/cast.rs:29:5 + --> $DIR/cast.rs:31:5 | -29 | 1i32 as u8; +31 | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value - --> $DIR/cast.rs:30:5 + --> $DIR/cast.rs:32:5 | -30 | 1f64 as isize; +32 | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:33:5 | -31 | 1f64 as usize; +33 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:33:5 | -31 | 1f64 as usize; +33 | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:35:5 | -33 | 1u8 as i8; +35 | 1u8 as i8; | ^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value - --> $DIR/cast.rs:34:5 + --> $DIR/cast.rs:36:5 | -34 | 1u16 as i16; +36 | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:37:5 | -35 | 1u32 as i32; +37 | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value - --> $DIR/cast.rs:36:5 + --> $DIR/cast.rs:38:5 | -36 | 1u64 as i64; +38 | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:39:5 | -37 | 1usize as isize; +39 | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting f32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:39:5 + --> $DIR/cast.rs:41:5 | -39 | 1.0f32 as f64; +41 | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:43:5 | -41 | (1u8 + 1u8) as u16; +43 | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:45:5 | -43 | 1i32 as u32; +45 | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:44:5 + --> $DIR/cast.rs:46:5 | -44 | 1isize as usize; +46 | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:47:5 + --> $DIR/cast.rs:49:5 | -47 | 1i32 as i32; +49 | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:48:5 + --> $DIR/cast.rs:50:5 | -48 | 1f32 as f32; +50 | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:49:5 + --> $DIR/cast.rs:51:5 | -49 | false as bool; +51 | false as bool; | ^^^^^^^^^^^^^ error: aborting due to 28 previous errors diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index a4dd6038cab..1c7d53c3ce7 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,15 +1,15 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:25:5 + --> $DIR/cast_alignment.rs:22:5 | -25 | (&1u8 as *const u8) as *const u16; +22 | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:26:5 + --> $DIR/cast_alignment.rs:23:5 | -26 | (&mut 1u8 as *mut u8) as *mut u16; +23 | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 95b9bfb0262..8380c7c84e2 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,63 +1,63 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:17:5 + --> $DIR/cast_lossless_float.rs:14:5 | -17 | 1i8 as f32; +14 | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:18:5 + --> $DIR/cast_lossless_float.rs:15:5 | -18 | 1i8 as f64; +15 | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:19:5 + --> $DIR/cast_lossless_float.rs:16:5 | -19 | 1u8 as f32; +16 | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:20:5 + --> $DIR/cast_lossless_float.rs:17:5 | -20 | 1u8 as f64; +17 | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:21:5 + --> $DIR/cast_lossless_float.rs:18:5 | -21 | 1i16 as f32; +18 | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:22:5 + --> $DIR/cast_lossless_float.rs:19:5 | -22 | 1i16 as f64; +19 | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:23:5 + --> $DIR/cast_lossless_float.rs:20:5 | -23 | 1u16 as f32; +20 | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:24:5 + --> $DIR/cast_lossless_float.rs:21:5 | -24 | 1u16 as f64; +21 | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:25:5 + --> $DIR/cast_lossless_float.rs:22:5 | -25 | 1i32 as f64; +22 | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:26:5 + --> $DIR/cast_lossless_float.rs:23:5 | -26 | 1u32 as f64; +23 | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` error: aborting due to 10 previous errors diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index 5f9c70879b4..e5558b66681 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,111 +1,111 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:14:5 | -16 | 1i8 as i16; +14 | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:15:5 | -17 | 1i8 as i32; +15 | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:16:5 | -18 | 1i8 as i64; +16 | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:17:5 | -19 | 1u8 as i16; +17 | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:18:5 | -20 | 1u8 as i32; +18 | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:19:5 | -21 | 1u8 as i64; +19 | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:20:5 | -22 | 1u8 as u16; +20 | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:21:5 | -23 | 1u8 as u32; +21 | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:24:5 + --> $DIR/cast_lossless_integer.rs:22:5 | -24 | 1u8 as u64; +22 | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:25:5 + --> $DIR/cast_lossless_integer.rs:23:5 | -25 | 1i16 as i32; +23 | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:26:5 + --> $DIR/cast_lossless_integer.rs:24:5 | -26 | 1i16 as i64; +24 | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:27:5 + --> $DIR/cast_lossless_integer.rs:25:5 | -27 | 1u16 as i32; +25 | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:28:5 + --> $DIR/cast_lossless_integer.rs:26:5 | -28 | 1u16 as i64; +26 | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:29:5 + --> $DIR/cast_lossless_integer.rs:27:5 | -29 | 1u16 as u32; +27 | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:30:5 + --> $DIR/cast_lossless_integer.rs:28:5 | -30 | 1u16 as u64; +28 | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:31:5 + --> $DIR/cast_lossless_integer.rs:29:5 | -31 | 1i32 as i64; +29 | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:32:5 + --> $DIR/cast_lossless_integer.rs:30:5 | -32 | 1u32 as i64; +30 | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:33:5 + --> $DIR/cast_lossless_integer.rs:31:5 | -33 | 1u32 as u64; +31 | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` error: aborting due to 18 previous errors diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index c5f569db167..9f658d40523 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,123 +1,123 @@ error: casting isize to i8 may truncate the value - --> $DIR/cast_size.rs:17:5 + --> $DIR/cast_size.rs:20:5 | -17 | 1isize as i8; +20 | 1isize as i8; | ^^^^^^^^^^^^ | = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:18:5 + --> $DIR/cast_size.rs:21:5 | -18 | 1isize as f64; +21 | 1isize as f64; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:19:5 + --> $DIR/cast_size.rs:22:5 | -19 | 1usize as f64; +22 | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:20:5 + --> $DIR/cast_size.rs:23:5 | -20 | 1isize as f32; +23 | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:21:5 + --> $DIR/cast_size.rs:24:5 | -21 | 1usize as f32; +24 | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:22:5 + --> $DIR/cast_size.rs:25:5 | -22 | 1isize as i32; +25 | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast_size.rs:23:5 + --> $DIR/cast_size.rs:26:5 | -23 | 1isize as u32; +26 | 1isize as u32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:23:5 + --> $DIR/cast_size.rs:26:5 | -23 | 1isize as u32; +26 | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:24:5 + --> $DIR/cast_size.rs:27:5 | -24 | 1usize as u32; +27 | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:25:5 + --> $DIR/cast_size.rs:28:5 | -25 | 1usize as i32; +28 | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:25:5 + --> $DIR/cast_size.rs:28:5 | -25 | 1usize as i32; +28 | 1usize as i32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:27:5 + --> $DIR/cast_size.rs:30:5 | -27 | 1i64 as isize; +30 | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast_size.rs:28:5 + --> $DIR/cast_size.rs:31:5 | -28 | 1i64 as usize; +31 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:28:5 + --> $DIR/cast_size.rs:31:5 | -28 | 1i64 as usize; +31 | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:29:5 + --> $DIR/cast_size.rs:32:5 | -29 | 1u64 as isize; +32 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:29:5 + --> $DIR/cast_size.rs:32:5 | -29 | 1u64 as isize; +32 | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:30:5 + --> $DIR/cast_size.rs:33:5 | -30 | 1u64 as usize; +33 | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:31:5 + --> $DIR/cast_size.rs:34:5 | -31 | 1u32 as isize; +34 | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast_size.rs:34:5 + --> $DIR/cast_size.rs:37:5 | -34 | 1i32 as usize; +37 | 1i32 as usize; | ^^^^^^^^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index 38a469bfebb..cee27df2a7d 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -1,7 +1,7 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them - --> $DIR/char_lit_as_u8.rs:17:13 + --> $DIR/char_lit_as_u8.rs:13:13 | -17 | let c = 'a' as u8; +13 | let c = 'a' as u8; | ^^^^^^^^^ | = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index f7f49360348..bce37d50226 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,312 +1,312 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:19:9 + --> $DIR/checked_unwrap.rs:16:9 | -18 | if x.is_some() { +15 | if x.is_some() { | ----------- the check is happening here -19 | x.unwrap(); // unnecessary +16 | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:13:35 + --> $DIR/checked_unwrap.rs:10:35 | -13 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +10 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:21:9 + --> $DIR/checked_unwrap.rs:18:9 | -18 | if x.is_some() { +15 | if x.is_some() { | ----------- because of this check ... -21 | x.unwrap(); // will panic +18 | x.unwrap(); // will panic | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:13:9 + --> $DIR/checked_unwrap.rs:10:9 | -13 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +10 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:24:9 + --> $DIR/checked_unwrap.rs:21:9 | -23 | if x.is_none() { +20 | if x.is_none() { | ----------- because of this check -24 | x.unwrap(); // will panic +21 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:26:9 + --> $DIR/checked_unwrap.rs:23:9 | -23 | if x.is_none() { +20 | if x.is_none() { | ----------- the check is happening here ... -26 | x.unwrap(); // unnecessary +23 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:30:9 + --> $DIR/checked_unwrap.rs:27:9 | -29 | if x.is_ok() { +26 | if x.is_ok() { | --------- the check is happening here -30 | x.unwrap(); // unnecessary +27 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:31:9 + --> $DIR/checked_unwrap.rs:28:9 | -29 | if x.is_ok() { +26 | if x.is_ok() { | --------- because of this check -30 | x.unwrap(); // unnecessary -31 | x.unwrap_err(); // will panic +27 | x.unwrap(); // unnecessary +28 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:33:9 + --> $DIR/checked_unwrap.rs:30:9 | -29 | if x.is_ok() { +26 | if x.is_ok() { | --------- because of this check ... -33 | x.unwrap(); // will panic +30 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:34:9 + --> $DIR/checked_unwrap.rs:31:9 | -29 | if x.is_ok() { +26 | if x.is_ok() { | --------- the check is happening here ... -34 | x.unwrap_err(); // unnecessary +31 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:37:9 + --> $DIR/checked_unwrap.rs:34:9 | -36 | if x.is_err() { +33 | if x.is_err() { | ---------- because of this check -37 | x.unwrap(); // will panic +34 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:38:9 + --> $DIR/checked_unwrap.rs:35:9 | -36 | if x.is_err() { +33 | if x.is_err() { | ---------- the check is happening here -37 | x.unwrap(); // will panic -38 | x.unwrap_err(); // unnecessary +34 | x.unwrap(); // will panic +35 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:40:9 + --> $DIR/checked_unwrap.rs:37:9 | -36 | if x.is_err() { +33 | if x.is_err() { | ---------- the check is happening here ... -40 | x.unwrap(); // unnecessary +37 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:41:9 + --> $DIR/checked_unwrap.rs:38:9 | -36 | if x.is_err() { +33 | if x.is_err() { | ---------- because of this check ... -41 | x.unwrap_err(); // will panic +38 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:58:9 + --> $DIR/checked_unwrap.rs:55:9 | -57 | if x.is_ok() && y.is_err() { +54 | if x.is_ok() && y.is_err() { | --------- the check is happening here -58 | x.unwrap(); // unnecessary +55 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:59:9 + --> $DIR/checked_unwrap.rs:56:9 | -57 | if x.is_ok() && y.is_err() { +54 | if x.is_ok() && y.is_err() { | --------- because of this check -58 | x.unwrap(); // unnecessary -59 | x.unwrap_err(); // will panic +55 | x.unwrap(); // unnecessary +56 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:60:9 + --> $DIR/checked_unwrap.rs:57:9 | -57 | if x.is_ok() && y.is_err() { +54 | if x.is_ok() && y.is_err() { | ---------- because of this check ... -60 | y.unwrap(); // will panic +57 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:61:9 + --> $DIR/checked_unwrap.rs:58:9 | -57 | if x.is_ok() && y.is_err() { +54 | if x.is_ok() && y.is_err() { | ---------- the check is happening here ... -61 | y.unwrap_err(); // unnecessary +58 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:75:9 + --> $DIR/checked_unwrap.rs:72:9 | -70 | if x.is_ok() || y.is_ok() { +67 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -75 | x.unwrap(); // will panic +72 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:76:9 + --> $DIR/checked_unwrap.rs:73:9 | -70 | if x.is_ok() || y.is_ok() { +67 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -76 | x.unwrap_err(); // unnecessary +73 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:77:9 + --> $DIR/checked_unwrap.rs:74:9 | -70 | if x.is_ok() || y.is_ok() { +67 | if x.is_ok() || y.is_ok() { | --------- because of this check ... -77 | y.unwrap(); // will panic +74 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:78:9 + --> $DIR/checked_unwrap.rs:75:9 | -70 | if x.is_ok() || y.is_ok() { +67 | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -78 | y.unwrap_err(); // unnecessary +75 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:82:9 + --> $DIR/checked_unwrap.rs:79:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -82 | x.unwrap(); // unnecessary +79 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:83:9 + --> $DIR/checked_unwrap.rs:80:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check -82 | x.unwrap(); // unnecessary -83 | x.unwrap_err(); // will panic +79 | x.unwrap(); // unnecessary +80 | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:84:9 + --> $DIR/checked_unwrap.rs:81:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check ... -84 | y.unwrap(); // will panic +81 | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:85:9 + --> $DIR/checked_unwrap.rs:82:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here ... -85 | y.unwrap_err(); // unnecessary +82 | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:86:9 + --> $DIR/checked_unwrap.rs:83:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here ... -86 | z.unwrap(); // unnecessary +83 | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:87:9 + --> $DIR/checked_unwrap.rs:84:9 | -81 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check ... -87 | z.unwrap_err(); // will panic +84 | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:95:9 + --> $DIR/checked_unwrap.rs:92:9 | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -95 | x.unwrap(); // will panic +92 | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:96:9 + --> $DIR/checked_unwrap.rs:93:9 | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -96 | x.unwrap_err(); // unnecessary +93 | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:97:9 + --> $DIR/checked_unwrap.rs:94:9 | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -97 | y.unwrap(); // unnecessary +94 | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:98:9 + --> $DIR/checked_unwrap.rs:95:9 | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -98 | y.unwrap_err(); // will panic +95 | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:99:9 + --> $DIR/checked_unwrap.rs:96:9 | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check ... -99 | z.unwrap(); // will panic +96 | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:100:9 - | -89 | if x.is_ok() || !(y.is_ok() && z.is_err()) { - | ---------- the check is happening here + --> $DIR/checked_unwrap.rs:97:9 + | +86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { + | ---------- the check is happening here ... -100 | z.unwrap_err(); // unnecessary - | ^^^^^^^^^^^^^^ +97 | z.unwrap_err(); // unnecessary + | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:108:13 + --> $DIR/checked_unwrap.rs:105:13 | -107 | if x.is_some() { +104 | if x.is_some() { | ----------- the check is happening here -108 | x.unwrap(); // unnecessary +105 | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:110:13 + --> $DIR/checked_unwrap.rs:107:13 | -107 | if x.is_some() { +104 | if x.is_some() { | ----------- because of this check ... -110 | x.unwrap(); // will panic +107 | x.unwrap(); // will panic | ^^^^^^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index b880b821f08..6838e6ad7ae 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -1,75 +1,75 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:18:5 + --> $DIR/cmp_nan.rs:14:5 | -18 | x == std::f32::NAN; +14 | x == std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cmp-nan` implied by `-D warnings` error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:19:5 + --> $DIR/cmp_nan.rs:15:5 | -19 | x != std::f32::NAN; +15 | x != std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:20:5 + --> $DIR/cmp_nan.rs:16:5 | -20 | x < std::f32::NAN; +16 | x < std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:21:5 + --> $DIR/cmp_nan.rs:17:5 | -21 | x > std::f32::NAN; +17 | x > std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:22:5 + --> $DIR/cmp_nan.rs:18:5 | -22 | x <= std::f32::NAN; +18 | x <= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:23:5 + --> $DIR/cmp_nan.rs:19:5 | -23 | x >= std::f32::NAN; +19 | x >= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:26:5 + --> $DIR/cmp_nan.rs:22:5 | -26 | y == std::f64::NAN; +22 | y == std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:27:5 + --> $DIR/cmp_nan.rs:23:5 | -27 | y != std::f64::NAN; +23 | y != std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:28:5 + --> $DIR/cmp_nan.rs:24:5 | -28 | y < std::f64::NAN; +24 | y < std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:29:5 + --> $DIR/cmp_nan.rs:25:5 | -29 | y > std::f64::NAN; +25 | y > std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:30:5 + --> $DIR/cmp_nan.rs:26:5 | -30 | y <= std::f64::NAN; +26 | y <= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:31:5 + --> $DIR/cmp_nan.rs:27:5 | -31 | y >= std::f64::NAN; +27 | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 1f1fdf32852..5038298d9c4 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -1,15 +1,15 @@ error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:21:8 + --> $DIR/cmp_null.rs:18:8 | -21 | if p == ptr::null() { +18 | if p == ptr::null() { | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::cmp-null` implied by `-D warnings` error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:26:8 + --> $DIR/cmp_null.rs:23:8 | -26 | if m == ptr::null_mut() { +23 | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index a7371ab4b6c..2d06f736967 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -1,57 +1,57 @@ error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:18:14 + --> $DIR/cmp_owned.rs:14:14 | -18 | x != "foo".to_string(); +14 | x != "foo".to_string(); | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` | = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:20:9 + --> $DIR/cmp_owned.rs:16:9 | -20 | "foo".to_string() != x; +16 | "foo".to_string() != x; | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:27:10 + --> $DIR/cmp_owned.rs:23:10 | -27 | x != "foo".to_owned(); +23 | x != "foo".to_owned(); | ^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:29:10 + --> $DIR/cmp_owned.rs:25:10 | -29 | x != String::from("foo"); +25 | x != String::from("foo"); | ^^^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:33:5 + --> $DIR/cmp_owned.rs:29:5 | -33 | Foo.to_owned() == Foo; +29 | Foo.to_owned() == Foo; | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:35:30 + --> $DIR/cmp_owned.rs:31:30 | -35 | "abc".chars().filter(|c| c.to_owned() != 'X'); +31 | "abc".chars().filter(|c| c.to_owned() != 'X'); | ^^^^^^^^^^^^ help: try: `*c` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:42:5 + --> $DIR/cmp_owned.rs:38:5 | -42 | y.to_owned() == *x; +38 | y.to_owned() == *x; | ^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:47:5 + --> $DIR/cmp_owned.rs:43:5 | -47 | y.to_owned() == **x; +43 | y.to_owned() == **x; | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:54:9 + --> $DIR/cmp_owned.rs:50:9 | -54 | self.to_owned() == *other +50 | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: aborting due to 9 previous errors diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 697dec336fa..1884045a2db 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,259 +1,259 @@ error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:16:5 + --> $DIR/collapsible_if.rs:15:5 | -16 | / if x == "hello" { -17 | | if y == "world" { -18 | | println!("Hello world!"); -19 | | } -20 | | } +15 | / if x == "hello" { +16 | | if y == "world" { +17 | | println!("Hello world!"); +18 | | } +19 | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` help: try | -16 | if x == "hello" && y == "world" { -17 | println!("Hello world!"); -18 | } +15 | if x == "hello" && y == "world" { +16 | println!("Hello world!"); +17 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:22:5 + --> $DIR/collapsible_if.rs:21:5 | -22 | / if x == "hello" || x == "world" { -23 | | if y == "world" || y == "hello" { -24 | | println!("Hello world!"); -25 | | } -26 | | } +21 | / if x == "hello" || x == "world" { +22 | | if y == "world" || y == "hello" { +23 | | println!("Hello world!"); +24 | | } +25 | | } | |_____^ help: try | -22 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -23 | println!("Hello world!"); -24 | } +21 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { +22 | println!("Hello world!"); +23 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:28:5 + --> $DIR/collapsible_if.rs:27:5 | -28 | / if x == "hello" && x == "world" { -29 | | if y == "world" || y == "hello" { -30 | | println!("Hello world!"); -31 | | } -32 | | } +27 | / if x == "hello" && x == "world" { +28 | | if y == "world" || y == "hello" { +29 | | println!("Hello world!"); +30 | | } +31 | | } | |_____^ help: try | -28 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { -29 | println!("Hello world!"); -30 | } +27 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { +28 | println!("Hello world!"); +29 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:34:5 + --> $DIR/collapsible_if.rs:33:5 | -34 | / if x == "hello" || x == "world" { -35 | | if y == "world" && y == "hello" { -36 | | println!("Hello world!"); -37 | | } -38 | | } +33 | / if x == "hello" || x == "world" { +34 | | if y == "world" && y == "hello" { +35 | | println!("Hello world!"); +36 | | } +37 | | } | |_____^ help: try | -34 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { -35 | println!("Hello world!"); -36 | } +33 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { +34 | println!("Hello world!"); +35 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:40:5 + --> $DIR/collapsible_if.rs:39:5 | -40 | / if x == "hello" && x == "world" { -41 | | if y == "world" && y == "hello" { -42 | | println!("Hello world!"); -43 | | } -44 | | } +39 | / if x == "hello" && x == "world" { +40 | | if y == "world" && y == "hello" { +41 | | println!("Hello world!"); +42 | | } +43 | | } | |_____^ help: try | -40 | if x == "hello" && x == "world" && y == "world" && y == "hello" { -41 | println!("Hello world!"); -42 | } +39 | if x == "hello" && x == "world" && y == "world" && y == "hello" { +40 | println!("Hello world!"); +41 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:46:5 + --> $DIR/collapsible_if.rs:45:5 | -46 | / if 42 == 1337 { -47 | | if 'a' != 'A' { -48 | | println!("world!") -49 | | } -50 | | } +45 | / if 42 == 1337 { +46 | | if 'a' != 'A' { +47 | | println!("world!") +48 | | } +49 | | } | |_____^ help: try | -46 | if 42 == 1337 && 'a' != 'A' { -47 | println!("world!") -48 | } +45 | if 42 == 1337 && 'a' != 'A' { +46 | println!("world!") +47 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:55:12 + --> $DIR/collapsible_if.rs:54:12 | -55 | } else { +54 | } else { | ____________^ -56 | | if y == "world" { -57 | | println!("world!") -58 | | } -59 | | } +55 | | if y == "world" { +56 | | println!("world!") +57 | | } +58 | | } | |_____^ help: try | -55 | } else if y == "world" { -56 | println!("world!") -57 | } +54 | } else if y == "world" { +55 | println!("world!") +56 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:63:12 + --> $DIR/collapsible_if.rs:62:12 | -63 | } else { +62 | } else { | ____________^ -64 | | if let Some(42) = Some(42) { -65 | | println!("world!") -66 | | } -67 | | } +63 | | if let Some(42) = Some(42) { +64 | | println!("world!") +65 | | } +66 | | } | |_____^ help: try | -63 | } else if let Some(42) = Some(42) { -64 | println!("world!") -65 | } +62 | } else if let Some(42) = Some(42) { +63 | println!("world!") +64 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:71:12 + --> $DIR/collapsible_if.rs:70:12 | -71 | } else { +70 | } else { | ____________^ -72 | | if y == "world" { -73 | | println!("world") -74 | | } +71 | | if y == "world" { +72 | | println!("world") +73 | | } ... | -77 | | } -78 | | } +76 | | } +77 | | } | |_____^ help: try | -71 | } else if y == "world" { -72 | println!("world") -73 | } -74 | else { -75 | println!("!") -76 | } +70 | } else if y == "world" { +71 | println!("world") +72 | } +73 | else { +74 | println!("!") +75 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:82:12 + --> $DIR/collapsible_if.rs:81:12 | -82 | } else { +81 | } else { | ____________^ -83 | | if let Some(42) = Some(42) { -84 | | println!("world") -85 | | } +82 | | if let Some(42) = Some(42) { +83 | | println!("world") +84 | | } ... | -88 | | } -89 | | } +87 | | } +88 | | } | |_____^ help: try | -82 | } else if let Some(42) = Some(42) { -83 | println!("world") -84 | } -85 | else { -86 | println!("!") -87 | } +81 | } else if let Some(42) = Some(42) { +82 | println!("world") +83 | } +84 | else { +85 | println!("!") +86 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:93:12 - | -93 | } else { - | ____________^ -94 | | if let Some(42) = Some(42) { -95 | | println!("world") -96 | | } -... | -99 | | } -100 | | } - | |_____^ + --> $DIR/collapsible_if.rs:92:12 + | +92 | } else { + | ____________^ +93 | | if let Some(42) = Some(42) { +94 | | println!("world") +95 | | } +... | +98 | | } +99 | | } + | |_____^ help: try - | -93 | } else if let Some(42) = Some(42) { -94 | println!("world") -95 | } -96 | else { -97 | println!("!") -98 | } - | + | +92 | } else if let Some(42) = Some(42) { +93 | println!("world") +94 | } +95 | else { +96 | println!("!") +97 | } + | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:104:12 + --> $DIR/collapsible_if.rs:103:12 | -104 | } else { +103 | } else { | ____________^ -105 | | if x == "hello" { -106 | | println!("world") -107 | | } +104 | | if x == "hello" { +105 | | println!("world") +106 | | } ... | -110 | | } -111 | | } +109 | | } +110 | | } | |_____^ help: try | -104 | } else if x == "hello" { -105 | println!("world") -106 | } -107 | else { -108 | println!("!") -109 | } +103 | } else if x == "hello" { +104 | println!("world") +105 | } +106 | else { +107 | println!("!") +108 | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:115:12 + --> $DIR/collapsible_if.rs:114:12 | -115 | } else { +114 | } else { | ____________^ -116 | | if let Some(42) = Some(42) { -117 | | println!("world") -118 | | } +115 | | if let Some(42) = Some(42) { +116 | | println!("world") +117 | | } ... | -121 | | } -122 | | } +120 | | } +121 | | } | |_____^ help: try | -115 | } else if let Some(42) = Some(42) { -116 | println!("world") -117 | } -118 | else { -119 | println!("!") -120 | } +114 | } else if let Some(42) = Some(42) { +115 | println!("world") +116 | } +117 | else { +118 | println!("!") +119 | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:174:5 + --> $DIR/collapsible_if.rs:173:5 | -174 | / if x == "hello" { -175 | | if y == "world" { // Collapsible -176 | | println!("Hello world!"); -177 | | } -178 | | } +173 | / if x == "hello" { +174 | | if y == "world" { // Collapsible +175 | | println!("Hello world!"); +176 | | } +177 | | } | |_____^ help: try | -174 | if x == "hello" && y == "world" { // Collapsible -175 | println!("Hello world!"); -176 | } +173 | if x == "hello" && y == "world" { // Collapsible +174 | println!("Hello world!"); +175 | } | error: aborting due to 14 previous errors diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index f373f09951b..80f133fd1ce 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -1,93 +1,93 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:19:12 + --> $DIR/complex_types.rs:16:12 | -19 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +16 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::type-complexity` implied by `-D warnings` error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:20:12 + --> $DIR/complex_types.rs:17:12 | -20 | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +17 | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:23:8 + --> $DIR/complex_types.rs:20:8 | -23 | f: Vec>>, +20 | f: Vec>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:26:11 + --> $DIR/complex_types.rs:23:11 | -26 | struct TS(Vec>>); +23 | struct TS(Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:29:11 + --> $DIR/complex_types.rs:26:11 | -29 | Tuple(Vec>>), +26 | Tuple(Vec>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:30:17 + --> $DIR/complex_types.rs:27:17 | -30 | Struct { f: Vec>> }, +27 | Struct { f: Vec>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:34:14 + --> $DIR/complex_types.rs:31:14 | -34 | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +31 | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:35:30 + --> $DIR/complex_types.rs:32:30 | -35 | fn impl_method(&self, p: Vec>>) { } +32 | fn impl_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:39:14 + --> $DIR/complex_types.rs:36:14 | -39 | const A: Vec>>; +36 | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:40:14 + --> $DIR/complex_types.rs:37:14 | -40 | type B = Vec>>; +37 | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:41:25 + --> $DIR/complex_types.rs:38:25 | -41 | fn method(&self, p: Vec>>); +38 | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:42:29 + --> $DIR/complex_types.rs:39:29 | -42 | fn def_method(&self, p: Vec>>) { } +39 | fn def_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:45:15 + --> $DIR/complex_types.rs:42:15 | -45 | fn test1() -> Vec>> { vec![] } +42 | fn test1() -> Vec>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:47:14 + --> $DIR/complex_types.rs:46:14 | -47 | fn test2(_x: Vec>>) { } +46 | fn test2(_x: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:50:13 + --> $DIR/complex_types.rs:49:13 | -50 | let _y: Vec>> = vec![]; +49 | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index 908a681584d..ba53d0718fc 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,81 +1,81 @@ error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:14:17 + --> $DIR/const_static_lifetime.rs:13:17 | -14 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +13 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` | = note: `-D clippy::const-static-lifetime` implied by `-D warnings` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:18:21 + --> $DIR/const_static_lifetime.rs:17:21 | -18 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +17 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:20:32 + --> $DIR/const_static_lifetime.rs:19:32 | -20 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +19 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:20:47 + --> $DIR/const_static_lifetime.rs:19:47 | -20 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +19 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:22:18 + --> $DIR/const_static_lifetime.rs:21:18 | -22 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +21 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:22:30 + --> $DIR/const_static_lifetime.rs:21:30 | -22 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +21 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:24:17 + --> $DIR/const_static_lifetime.rs:23:17 | -24 | const VAR_SIX: &'static u8 = &5; +23 | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:26:29 + --> $DIR/const_static_lifetime.rs:25:29 | -26 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +25 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:26:39 + --> $DIR/const_static_lifetime.rs:25:39 | -26 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +25 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:28:20 + --> $DIR/const_static_lifetime.rs:27:20 | -28 | const VAR_HEIGHT: &'static Foo = &Foo {}; +27 | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:30:19 + --> $DIR/const_static_lifetime.rs:29:19 | -30 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +29 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:32:19 + --> $DIR/const_static_lifetime.rs:31:19 | -32 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +31 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:34:19 + --> $DIR/const_static_lifetime.rs:33:19 | -34 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +33 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: aborting due to 13 previous errors diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index e5f808218fe..e41fac0f686 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,385 +1,392 @@ error: this `if` has identical blocks - --> $DIR/copies.rs:41:10 + --> $DIR/copies.rs:50:12 | -41 | else { //~ ERROR same body as `if` block - | __________^ -42 | | Foo { bar: 42 }; -43 | | 0..10; -44 | | ..; +50 | } else { + | ____________^ +51 | | //~ ERROR same body as `if` block +52 | | Foo { bar: 42 }; +53 | | 0..10; ... | -48 | | foo(); -49 | | } +58 | | foo(); +59 | | } | |_____^ | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:32:13 + --> $DIR/copies.rs:42:13 | -32 | if true { +42 | if true { | _____________^ -33 | | Foo { bar: 42 }; -34 | | 0..10; -35 | | ..; +43 | | Foo { bar: 42 }; +44 | | 0..10; +45 | | ..; ... | -39 | | foo(); -40 | | } +49 | | foo(); +50 | | } else { | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:90:14 - | -90 | _ => { //~ ERROR match arms have same body - | ______________^ -91 | | foo(); -92 | | let mut a = 42 + [23].len() as i32; -93 | | if true { -... | -97 | | a -98 | | } - | |_________^ - | - = note: `-D clippy::match-same-arms` implied by `-D warnings` + --> $DIR/copies.rs:96:14 + | +96 | _ => { + | ______________^ +97 | | //~ ERROR match arms have same body +98 | | foo(); +99 | | let mut a = 42 + [23].len() as i32; +... | +104 | | a +105 | | }, + | |_________^ + | + = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:81:15 - | -81 | 42 => { - | _______________^ -82 | | foo(); -83 | | let mut a = 42 + [23].len() as i32; -84 | | if true { -... | -88 | | a -89 | | } - | |_________^ + --> $DIR/copies.rs:87:15 + | +87 | 42 => { + | _______________^ +88 | | foo(); +89 | | let mut a = 42 + [23].len() as i32; +90 | | if true { +... | +94 | | a +95 | | }, + | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:81:15 - | -81 | 42 => { - | _______________^ -82 | | foo(); -83 | | let mut a = 42 + [23].len() as i32; -84 | | if true { -... | -88 | | a -89 | | } - | |_________^ + --> $DIR/copies.rs:87:15 + | +87 | 42 => { + | _______________^ +88 | | foo(); +89 | | let mut a = 42 + [23].len() as i32; +90 | | if true { +... | +94 | | a +95 | | }, + | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:104:14 + --> $DIR/copies.rs:111:14 | -104 | _ => 0, //~ ERROR match arms have same body +111 | _ => 0, //~ ERROR match arms have same body | ^ | note: same as this - --> $DIR/copies.rs:102:19 + --> $DIR/copies.rs:109:19 | -102 | Abc::A => 0, +109 | Abc::A => 0, | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:102:19 + --> $DIR/copies.rs:109:19 | -102 | Abc::A => 0, +109 | Abc::A => 0, | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:114:10 + --> $DIR/copies.rs:120:12 | -114 | else { //~ ERROR same body as `if` block - | __________^ -115 | | 42 -116 | | }; +120 | } else { + | ____________^ +121 | | //~ ERROR same body as `if` block +122 | | 42 +123 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:111:21 + --> $DIR/copies.rs:118:21 | -111 | let _ = if true { +118 | let _ = if true { | _____________________^ -112 | | 42 -113 | | } +119 | | 42 +120 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:128:10 + --> $DIR/copies.rs:134:12 | -128 | else { //~ ERROR same body as `if` block - | __________^ -129 | | for _ in &[42] { -130 | | let foo: &Option<_> = &Some::(42); -131 | | if true { +134 | } else { + | ____________^ +135 | | //~ ERROR same body as `if` block +136 | | for _ in &[42] { +137 | | let foo: &Option<_> = &Some::(42); ... | -136 | | } -137 | | } +143 | | } +144 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:118:13 + --> $DIR/copies.rs:125:13 | -118 | if true { +125 | if true { | _____________^ -119 | | for _ in &[42] { -120 | | let foo: &Option<_> = &Some::(42); -121 | | if true { +126 | | for _ in &[42] { +127 | | let foo: &Option<_> = &Some::(42); +128 | | if true { ... | -126 | | } -127 | | } +133 | | } +134 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:150:10 + --> $DIR/copies.rs:153:12 | -150 | else { //~ ERROR same body as `if` block - | __________^ -151 | | let bar = if true { -152 | | 42 -153 | | } +153 | } else { + | ____________^ +154 | | //~ ERROR same body as `if` block +155 | | let bar = if true { 42 } else { 43 }; +156 | | ... | -159 | | bar + 1; -160 | | } +160 | | bar + 1; +161 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:139:13 + --> $DIR/copies.rs:146:13 | -139 | if true { +146 | if true { | _____________^ -140 | | let bar = if true { -141 | | 42 -142 | | } +147 | | let bar = if true { 42 } else { 43 }; +148 | | +149 | | while foo() { ... | -148 | | bar + 1; -149 | | } +152 | | bar + 1; +153 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:185:10 + --> $DIR/copies.rs:183:12 | -185 | else { //~ ERROR same body as `if` block - | __________^ -186 | | if let Some(a) = Some(42) {} -187 | | } +183 | } else { + | ____________^ +184 | | //~ ERROR same body as `if` block +185 | | if let Some(a) = Some(42) {} +186 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:182:13 + --> $DIR/copies.rs:181:13 | -182 | if true { +181 | if true { | _____________^ -183 | | if let Some(a) = Some(42) {} -184 | | } +182 | | if let Some(a) = Some(42) {} +183 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:192:10 + --> $DIR/copies.rs:190:12 | -192 | else { //~ ERROR same body as `if` block - | __________^ -193 | | if let (1, .., 3) = (1, 2, 3) {} -194 | | } +190 | } else { + | ____________^ +191 | | //~ ERROR same body as `if` block +192 | | if let (1, .., 3) = (1, 2, 3) {} +193 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:189:13 + --> $DIR/copies.rs:188:13 | -189 | if true { +188 | if true { | _____________^ -190 | | if let (1, .., 3) = (1, 2, 3) {} -191 | | } +189 | | if let (1, .., 3) = (1, 2, 3) {} +190 | | } else { | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:247:15 + --> $DIR/copies.rs:239:15 | -247 | 51 => foo(), //~ ERROR match arms have same body +239 | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:246:15 + --> $DIR/copies.rs:238:15 | -246 | 42 => foo(), +238 | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:246:15 + --> $DIR/copies.rs:238:15 | -246 | 42 => foo(), +238 | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:253:17 + --> $DIR/copies.rs:245:17 | -253 | None => 24, //~ ERROR match arms have same body +245 | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:252:20 + --> $DIR/copies.rs:244:20 | -252 | Some(_) => 24, +244 | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:252:20 + --> $DIR/copies.rs:244:20 | -252 | Some(_) => 24, +244 | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:275:28 + --> $DIR/copies.rs:267:28 | -275 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +267 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:274:28 + --> $DIR/copies.rs:266:28 | -274 | (Some(a), None) => bar(a), +266 | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:274:28 + --> $DIR/copies.rs:266:28 | -274 | (Some(a), None) => bar(a), +266 | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:281:26 + --> $DIR/copies.rs:273:26 | -281 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +273 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:280:26 + --> $DIR/copies.rs:272:26 | -280 | (Some(a), ..) => bar(a), +272 | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:280:26 + --> $DIR/copies.rs:272:26 | -280 | (Some(a), ..) => bar(a), +272 | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:287:20 + --> $DIR/copies.rs:279:20 | -287 | (.., 3) => 42, //~ ERROR match arms have same body +279 | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:286:23 + --> $DIR/copies.rs:278:23 | -286 | (1, .., 3) => 42, +278 | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:286:23 + --> $DIR/copies.rs:278:23 | -286 | (1, .., 3) => 42, +278 | (1, .., 3) => 42, | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:293:12 + --> $DIR/copies.rs:285:12 | -293 | } else { //~ ERROR same body as `if` block +285 | } else { | ____________^ -294 | | 0.0 -295 | | }; +286 | | //~ ERROR same body as `if` block +287 | | 0.0 +288 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:291:21 + --> $DIR/copies.rs:283:21 | -291 | let _ = if true { +283 | let _ = if true { | _____________________^ -292 | | 0.0 -293 | | } else { //~ ERROR same body as `if` block +284 | | 0.0 +285 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:299:12 + --> $DIR/copies.rs:292:12 | -299 | } else { //~ ERROR same body as `if` block +292 | } else { | ____________^ -300 | | -0.0 -301 | | }; +293 | | //~ ERROR same body as `if` block +294 | | -0.0 +295 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:297:21 + --> $DIR/copies.rs:290:21 | -297 | let _ = if true { +290 | let _ = if true { | _____________________^ -298 | | -0.0 -299 | | } else { //~ ERROR same body as `if` block +291 | | -0.0 +292 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:319:12 + --> $DIR/copies.rs:305:12 | -319 | } else { //~ ERROR same body as `if` block +305 | } else { | ____________^ -320 | | std::f32::NAN -321 | | }; +306 | | //~ ERROR same body as `if` block +307 | | std::f32::NAN +308 | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:317:21 + --> $DIR/copies.rs:303:21 | -317 | let _ = if true { +303 | let _ = if true { | _____________________^ -318 | | std::f32::NAN -319 | | } else { //~ ERROR same body as `if` block +304 | | std::f32::NAN +305 | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:337:10 + --> $DIR/copies.rs:323:12 | -337 | else { //~ ERROR same body as `if` block - | __________^ -338 | | try!(Ok("foo")); -339 | | } +323 | } else { + | ____________^ +324 | | //~ ERROR same body as `if` block +325 | | try!(Ok("foo")); +326 | | } | |_____^ | note: same as this - --> $DIR/copies.rs:334:13 + --> $DIR/copies.rs:321:13 | -334 | if true { +321 | if true { | _____________^ -335 | | try!(Ok("foo")); -336 | | } +322 | | try!(Ok("foo")); +323 | | } else { | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:363:13 + --> $DIR/copies.rs:347:15 | -363 | else if b { //~ ERROR ifs same condition - | ^ +347 | } else if b { + | ^ | = note: `-D clippy::ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:361:8 + --> $DIR/copies.rs:346:8 | -361 | if b { +346 | if b { | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:368:13 + --> $DIR/copies.rs:352:15 | -368 | else if a == 1 { //~ ERROR ifs same condition - | ^^^^^^ +352 | } else if a == 1 { + | ^^^^^^ | note: same as this - --> $DIR/copies.rs:366:8 + --> $DIR/copies.rs:351:8 | -366 | if a == 1 { +351 | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:375:13 + --> $DIR/copies.rs:358:15 | -375 | else if 2*a == 1 { //~ ERROR ifs same condition - | ^^^^^^^^ +358 | } else if 2 * a == 1 { + | ^^^^^^^^^^ | note: same as this - --> $DIR/copies.rs:371:8 + --> $DIR/copies.rs:356:8 | -371 | if 2*a == 1 { - | ^^^^^^^^ +356 | if 2 * a == 1 { + | ^^^^^^^^^^ error: aborting due to 20 previous errors diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr index 4620958f47b..ced9293d1dc 100644 --- a/tests/ui/copy_iterator.stderr +++ b/tests/ui/copy_iterator.stderr @@ -1,13 +1,13 @@ error: you are implementing `Iterator` on a `Copy` type - --> $DIR/copy_iterator.rs:18:1 + --> $DIR/copy_iterator.rs:15:1 | -18 | / impl Iterator for Countdown { -19 | | type Item = u8; -20 | | -21 | | fn next(&mut self) -> Option { +15 | / impl Iterator for Countdown { +16 | | type Item = u8; +17 | | +18 | | fn next(&mut self) -> Option { ... | -26 | | } -27 | | } +23 | | } +24 | | } | |_^ | = note: `-D clippy::copy-iterator` implied by `-D warnings` diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 74d6e864de4..490a655ca26 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,15 +1,15 @@ error: you are getting the inner pointer of a temporary `CString` - --> $DIR/cstring.rs:19:5 + --> $DIR/cstring.rs:16:5 | -19 | CString::new("foo").unwrap().as_ptr(); +16 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/cstring.rs:19:5 + --> $DIR/cstring.rs:16:5 | -19 | CString::new("foo").unwrap().as_ptr(); +16 | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index 390df2f5a5b..de9e5c77f1b 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -1,270 +1,269 @@ error: the function has a cyclomatic complexity of 28 - --> $DIR/cyclomatic_complexity.rs:16:1 + --> $DIR/cyclomatic_complexity.rs:15:1 | -16 | / fn main() { -17 | | if true { -18 | | println!("a"); -19 | | } +15 | / fn main() { +16 | | if true { +17 | | println!("a"); +18 | | } ... | -97 | | } -98 | | } +96 | | } +97 | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 - --> $DIR/cyclomatic_complexity.rs:101:1 + --> $DIR/cyclomatic_complexity.rs:100:1 | -101 | / fn kaboom() { -102 | | let n = 0; -103 | | 'a: for i in 0..20 { -104 | | 'b: for j in i..20 { +100 | / fn kaboom() { +101 | | let n = 0; +102 | | 'a: for i in 0..20 { +103 | | 'b: for j in i..20 { ... | -119 | | } -120 | | } +118 | | } +119 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:147:1 + --> $DIR/cyclomatic_complexity.rs:146:1 | -147 | / fn lots_of_short_circuits() -> bool { -148 | | true && false && true && false && true && false && true -149 | | } +146 | / fn lots_of_short_circuits() -> bool { +147 | | true && false && true && false && true && false && true +148 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:152:1 + --> $DIR/cyclomatic_complexity.rs:151:1 | -152 | / fn lots_of_short_circuits2() -> bool { -153 | | true || false || true || false || true || false || true -154 | | } +151 | / fn lots_of_short_circuits2() -> bool { +152 | | true || false || true || false || true || false || true +153 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:157:1 + --> $DIR/cyclomatic_complexity.rs:156:1 | -157 | / fn baa() { -158 | | let x = || match 99 { -159 | | 0 => 0, -160 | | 1 => 1, +156 | / fn baa() { +157 | | let x = || match 99 { +158 | | 0 => 0, +159 | | 1 => 1, ... | -171 | | } -172 | | } +170 | | } +171 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:158:13 + --> $DIR/cyclomatic_complexity.rs:157:13 | -158 | let x = || match 99 { +157 | let x = || match 99 { | _____________^ -159 | | 0 => 0, -160 | | 1 => 1, -161 | | 2 => 2, +158 | | 0 => 0, +159 | | 1 => 1, +160 | | 2 => 2, ... | -165 | | _ => 42, -166 | | }; +164 | | _ => 42, +165 | | }; | |_____^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:175:1 - | -175 | / fn bar() { -176 | | match 99 { -177 | | 0 => println!("hi"), -178 | | _ => println!("bye"), -179 | | } -180 | | } + --> $DIR/cyclomatic_complexity.rs:174:1 + | +174 | / fn bar() { +175 | | match 99 { +176 | | 0 => println!("hi"), +177 | | _ => println!("bye"), +178 | | } +179 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:194:1 + --> $DIR/cyclomatic_complexity.rs:193:1 | -194 | / fn barr() { -195 | | match 99 { -196 | | 0 => println!("hi"), -197 | | 1 => println!("bla"), +193 | / fn barr() { +194 | | match 99 { +195 | | 0 => println!("hi"), +196 | | 1 => println!("bla"), ... | -200 | | } -201 | | } +199 | | } +200 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:204:1 + --> $DIR/cyclomatic_complexity.rs:203:1 | -204 | / fn barr2() { -205 | | match 99 { -206 | | 0 => println!("hi"), -207 | | 1 => println!("bla"), +203 | / fn barr2() { +204 | | match 99 { +205 | | 0 => println!("hi"), +206 | | 1 => println!("bla"), ... | -216 | | } -217 | | } +215 | | } +216 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:220:1 + --> $DIR/cyclomatic_complexity.rs:219:1 | -220 | / fn barrr() { -221 | | match 99 { -222 | | 0 => println!("hi"), -223 | | 1 => panic!("bla"), +219 | / fn barrr() { +220 | | match 99 { +221 | | 0 => println!("hi"), +222 | | 1 => panic!("bla"), ... | -226 | | } -227 | | } +225 | | } +226 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:230:1 + --> $DIR/cyclomatic_complexity.rs:229:1 | -230 | / fn barrr2() { -231 | | match 99 { -232 | | 0 => println!("hi"), -233 | | 1 => panic!("bla"), +229 | / fn barrr2() { +230 | | match 99 { +231 | | 0 => println!("hi"), +232 | | 1 => panic!("bla"), ... | -242 | | } -243 | | } +241 | | } +242 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:246:1 + --> $DIR/cyclomatic_complexity.rs:245:1 | -246 | / fn barrrr() { -247 | | match 99 { -248 | | 0 => println!("hi"), -249 | | 1 => println!("bla"), +245 | / fn barrrr() { +246 | | match 99 { +247 | | 0 => println!("hi"), +248 | | 1 => println!("bla"), ... | -252 | | } -253 | | } +251 | | } +252 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:256:1 + --> $DIR/cyclomatic_complexity.rs:255:1 | -256 | / fn barrrr2() { -257 | | match 99 { -258 | | 0 => println!("hi"), -259 | | 1 => println!("bla"), +255 | / fn barrrr2() { +256 | | match 99 { +257 | | 0 => println!("hi"), +258 | | 1 => println!("bla"), ... | -268 | | } -269 | | } +267 | | } +268 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:272:1 + --> $DIR/cyclomatic_complexity.rs:271:1 | -272 | / fn cake() { -273 | | if 4 == 5 { -274 | | println!("yea"); -275 | | } else { +271 | / fn cake() { +272 | | if 4 == 5 { +273 | | println!("yea"); +274 | | } else { ... | -278 | | println!("whee"); -279 | | } +277 | | println!("whee"); +278 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 4 - --> $DIR/cyclomatic_complexity.rs:283:1 + --> $DIR/cyclomatic_complexity.rs:281:1 | -283 | / pub fn read_file(input_path: &str) -> String { -284 | | use std::fs::File; -285 | | use std::io::{Read, Write}; -286 | | use std::path::Path; +281 | / pub fn read_file(input_path: &str) -> String { +282 | | use std::fs::File; +283 | | use std::io::{Read, Write}; +284 | | use std::path::Path; ... | -308 | | } -309 | | } +306 | | } +307 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:314:1 - | -314 | / fn void(void: Void) { -315 | | if true { -316 | | match void { -317 | | } -318 | | } -319 | | } + --> $DIR/cyclomatic_complexity.rs:312:1 + | +312 | / fn void(void: Void) { +313 | | if true { +314 | | match void {} +315 | | } +316 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:328:1 - | -328 | / fn try() -> Result { -329 | | match 5 { -330 | | 5 => Ok(5), -331 | | _ => return Err("bla"), -332 | | } -333 | | } + --> $DIR/cyclomatic_complexity.rs:325:1 + | +325 | / fn try() -> Result { +326 | | match 5 { +327 | | 5 => Ok(5), +328 | | _ => return Err("bla"), +329 | | } +330 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:336:1 + --> $DIR/cyclomatic_complexity.rs:333:1 | -336 | / fn try_again() -> Result { -337 | | let _ = try!(Ok(42)); -338 | | let _ = try!(Ok(43)); -339 | | let _ = try!(Ok(44)); +333 | / fn try_again() -> Result { +334 | | let _ = try!(Ok(42)); +335 | | let _ = try!(Ok(43)); +336 | | let _ = try!(Ok(44)); ... | -348 | | } -349 | | } +345 | | } +346 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:352:1 + --> $DIR/cyclomatic_complexity.rs:349:1 | -352 | / fn early() -> Result { -353 | | return Ok(5); -354 | | return Ok(5); -355 | | return Ok(5); +349 | / fn early() -> Result { +350 | | return Ok(5); +351 | | return Ok(5); +352 | | return Ok(5); ... | -361 | | return Ok(5); -362 | | } +358 | | return Ok(5); +359 | | } | |_^ | = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 8 - --> $DIR/cyclomatic_complexity.rs:366:1 + --> $DIR/cyclomatic_complexity.rs:363:1 | -366 | / fn early_ret() -> i32 { -367 | | let a = if true { 42 } else { return 0; }; -368 | | let a = if a < 99 { 42 } else { return 0; }; -369 | | let a = if a < 99 { 42 } else { return 0; }; +363 | / fn early_ret() -> i32 { +364 | | let a = if true { 42 } else { return 0; }; +365 | | let a = if a < 99 { 42 } else { return 0; }; +366 | | let a = if a < 99 { 42 } else { return 0; }; ... | -382 | | } -383 | | } +379 | | } +380 | | } | |_^ | = help: you could split it up into multiple smaller functions diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index f066e29ce75..3493c0d9ea5 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -1,13 +1,13 @@ error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity_attr_used.rs:21:1 + --> $DIR/cyclomatic_complexity_attr_used.rs:18:1 | -21 | / fn kaboom() { -22 | | if 42 == 43 { -23 | | panic!(); -24 | | } else if "cake" == "lie" { -25 | | println!("what?"); -26 | | } -27 | | } +18 | / fn kaboom() { +19 | | if 42 == 43 { +20 | | panic!(); +21 | | } else if "cake" == "lie" { +22 | | println!("what?"); +23 | | } +24 | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index d944c49066a..42f8a6e3bc5 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,33 +1,33 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:28:9 + --> $DIR/decimal_literal_representation.rs:26:9 | -28 | 32_773, // 0x8005 +26 | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` | = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:29:9 + --> $DIR/decimal_literal_representation.rs:27:9 | -29 | 65_280, // 0xFF00 +27 | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:30:9 + --> $DIR/decimal_literal_representation.rs:28:9 | -30 | 2_131_750_927, // 0x7F0F_F00F +28 | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:31:9 + --> $DIR/decimal_literal_representation.rs:29:9 | -31 | 2_147_483_647, // 0x7FFF_FFFF +29 | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:32:9 + --> $DIR/decimal_literal_representation.rs:30:9 | -32 | 4_042_322_160, // 0xF0F0_F0F0 +30 | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index d6ae00214c0..b838f6a3bf4 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,51 +1,51 @@ error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:20:22 + --> $DIR/default_trait_access.rs:17:22 | -20 | let s1: String = Default::default(); +17 | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` | = note: `-D clippy::default-trait-access` implied by `-D warnings` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:24:22 + --> $DIR/default_trait_access.rs:21:22 | -24 | let s3: String = D2::default(); +21 | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:26:22 + --> $DIR/default_trait_access.rs:23:22 | -26 | let s4: String = std::default::Default::default(); +23 | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:30:22 + --> $DIR/default_trait_access.rs:27:22 | -30 | let s6: String = default::Default::default(); +27 | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling GenericDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:40:46 + --> $DIR/default_trait_access.rs:37:46 | -40 | let s11: GenericDerivedDefault = Default::default(); +37 | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: Calling TupleDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:46:36 + --> $DIR/default_trait_access.rs:43:36 | -46 | let s14: TupleDerivedDefault = Default::default(); +43 | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: Calling ArrayDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:48:36 + --> $DIR/default_trait_access.rs:45:36 | -48 | let s15: ArrayDerivedDefault = Default::default(); +45 | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: Calling TupleStructDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:52:42 + --> $DIR/default_trait_access.rs:49:42 | -52 | let s17: TupleStructDerivedDefault = Default::default(); +49 | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` error: aborting due to 8 previous errors diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index d44528ab28f..335f6451e59 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -1,33 +1,33 @@ error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:14:8 + --> $DIR/deprecated.rs:10:8 | -14 | #[warn(str_to_string)] +10 | #[warn(str_to_string)] | ^^^^^^^^^^^^^ | = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:16:8 + --> $DIR/deprecated.rs:11:8 | -16 | #[warn(string_to_string)] +11 | #[warn(string_to_string)] | ^^^^^^^^^^^^^^^^ error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:18:8 + --> $DIR/deprecated.rs:12:8 | -18 | #[warn(unstable_as_slice)] +12 | #[warn(unstable_as_slice)] | ^^^^^^^^^^^^^^^^^ error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:20:8 + --> $DIR/deprecated.rs:13:8 | -20 | #[warn(unstable_as_mut_slice)] +13 | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` - --> $DIR/deprecated.rs:22:8 + --> $DIR/deprecated.rs:14:8 | -22 | #[warn(misaligned_transmute)] +14 | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index 824b5b44cba..dd36f773337 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -1,15 +1,17 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> $DIR/derive.rs:27:10 + --> $DIR/derive.rs:25:10 | -27 | #[derive(Hash)] +25 | #[derive(Hash)] | ^^^^ | = note: #[deny(clippy::derive_hash_xor_eq)] on by default note: `PartialEq` implemented here - --> $DIR/derive.rs:30:1 + --> $DIR/derive.rs:28:1 | -30 | / impl PartialEq for Bar { -31 | | fn eq(&self, _: &Bar) -> bool { true } +28 | / impl PartialEq for Bar { +29 | | fn eq(&self, _: &Bar) -> bool { +30 | | true +31 | | } 32 | | } | |_^ @@ -23,88 +25,106 @@ note: `PartialEq` implemented here --> $DIR/derive.rs:37:1 | 37 | / impl PartialEq for Baz { -38 | | fn eq(&self, _: &Baz) -> bool { true } -39 | | } +38 | | fn eq(&self, _: &Baz) -> bool { +39 | | true +40 | | } +41 | | } | |_^ error: you are implementing `Hash` explicitly but have derived `PartialEq` - --> $DIR/derive.rs:44:1 + --> $DIR/derive.rs:46:1 | -44 | / impl Hash for Bah { -45 | | fn hash(&self, _: &mut H) {} -46 | | } +46 | / impl Hash for Bah { +47 | | fn hash(&self, _: &mut H) {} +48 | | } | |_^ | note: `PartialEq` implemented here - --> $DIR/derive.rs:41:10 + --> $DIR/derive.rs:43:10 | -41 | #[derive(PartialEq)] +43 | #[derive(PartialEq)] | ^^^^^^^^^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:51:1 + --> $DIR/derive.rs:53:1 | -51 | / impl Clone for Qux { -52 | | fn clone(&self) -> Self { Qux } -53 | | } +53 | / impl Clone for Qux { +54 | | fn clone(&self) -> Self { +55 | | Qux +56 | | } +57 | | } | |_^ | = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:51:1 + --> $DIR/derive.rs:53:1 | -51 | / impl Clone for Qux { -52 | | fn clone(&self) -> Self { Qux } -53 | | } +53 | / impl Clone for Qux { +54 | | fn clone(&self) -> Self { +55 | | Qux +56 | | } +57 | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:75:1 + --> $DIR/derive.rs:77:1 | -75 | / impl<'a> Clone for Lt<'a> { -76 | | fn clone(&self) -> Self { unimplemented!() } -77 | | } +77 | / impl<'a> Clone for Lt<'a> { +78 | | fn clone(&self) -> Self { +79 | | unimplemented!() +80 | | } +81 | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:75:1 + --> $DIR/derive.rs:77:1 | -75 | / impl<'a> Clone for Lt<'a> { -76 | | fn clone(&self) -> Self { unimplemented!() } -77 | | } +77 | / impl<'a> Clone for Lt<'a> { +78 | | fn clone(&self) -> Self { +79 | | unimplemented!() +80 | | } +81 | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:85:1 + --> $DIR/derive.rs:89:1 | -85 | / impl Clone for BigArray { -86 | | fn clone(&self) -> Self { unimplemented!() } -87 | | } +89 | / impl Clone for BigArray { +90 | | fn clone(&self) -> Self { +91 | | unimplemented!() +92 | | } +93 | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:85:1 + --> $DIR/derive.rs:89:1 | -85 | / impl Clone for BigArray { -86 | | fn clone(&self) -> Self { unimplemented!() } -87 | | } +89 | / impl Clone for BigArray { +90 | | fn clone(&self) -> Self { +91 | | unimplemented!() +92 | | } +93 | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:95:1 - | -95 | / impl Clone for FnPtr { -96 | | fn clone(&self) -> Self { unimplemented!() } -97 | | } - | |_^ - | + --> $DIR/derive.rs:101:1 + | +101 | / impl Clone for FnPtr { +102 | | fn clone(&self) -> Self { +103 | | unimplemented!() +104 | | } +105 | | } + | |_^ + | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:95:1 - | -95 | / impl Clone for FnPtr { -96 | | fn clone(&self) -> Self { unimplemented!() } -97 | | } - | |_^ + --> $DIR/derive.rs:101:1 + | +101 | / impl Clone for FnPtr { +102 | | fn clone(&self) -> Self { +103 | | unimplemented!() +104 | | } +105 | | } + | |_^ error: aborting due to 7 previous errors diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index b3dc6095cd8..f2ca4dab997 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -1,48 +1,48 @@ error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:24:16 + --> $DIR/dlist.rs:19:16 | -24 | type Baz = LinkedList; +19 | type Baz = LinkedList; | ^^^^^^^^^^^^^^ | = note: `-D clippy::linkedlist` implied by `-D warnings` = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:25:12 + --> $DIR/dlist.rs:20:12 | -25 | fn foo(LinkedList); +20 | fn foo(LinkedList); | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:26:24 + --> $DIR/dlist.rs:21:23 | -26 | const BAR : Option>; - | ^^^^^^^^^^^^^^ +21 | const BAR: Option>; + | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:37:15 + --> $DIR/dlist.rs:32:15 | -37 | fn foo(_: LinkedList) {} +32 | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:40:39 + --> $DIR/dlist.rs:35:39 | -40 | pub fn test(my_favourite_linked_list: LinkedList) { +35 | pub fn test(my_favourite_linked_list: LinkedList) { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:44:29 + --> $DIR/dlist.rs:39:29 | -44 | pub fn test_ret() -> Option> { +39 | pub fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 646b6f13fab..a06f278efc0 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,51 +1,51 @@ error: This binary expression can be simplified - --> $DIR/double_comparison.rs:14:8 + --> $DIR/double_comparison.rs:13:8 | -14 | if x == y || x < y { +13 | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` | = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:17:8 + --> $DIR/double_comparison.rs:16:8 | -17 | if x < y || x == y { +16 | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:20:8 + --> $DIR/double_comparison.rs:19:8 | -20 | if x == y || x > y { +19 | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:23:8 + --> $DIR/double_comparison.rs:22:8 | -23 | if x > y || x == y { +22 | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:26:8 + --> $DIR/double_comparison.rs:25:8 | -26 | if x < y || x > y { +25 | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:29:8 + --> $DIR/double_comparison.rs:28:8 | -29 | if x > y || x < y { +28 | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:32:8 + --> $DIR/double_comparison.rs:31:8 | -32 | if x <= y && x >= y { +31 | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:35:8 + --> $DIR/double_comparison.rs:34:8 | -35 | if x >= y && x <= y { +34 | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: aborting due to 8 previous errors diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index cf0292f7af1..11ad5601286 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -1,7 +1,7 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op - --> $DIR/double_neg.rs:19:5 + --> $DIR/double_neg.rs:15:5 | -19 | --x; +15 | --x; | ^^^ | = note: `-D clippy::double-neg` implied by `-D warnings` diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index ef337ae6691..3b950eaebe3 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -1,75 +1,75 @@ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:43:5 + --> $DIR/drop_forget_copy.rs:42:5 | -43 | drop(s1); +42 | drop(s1); | ^^^^^^^^ | = note: `-D clippy::drop-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:43:10 + --> $DIR/drop_forget_copy.rs:42:10 | -43 | drop(s1); +42 | drop(s1); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:44:5 + --> $DIR/drop_forget_copy.rs:43:5 | -44 | drop(s2); +43 | drop(s2); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:44:10 + --> $DIR/drop_forget_copy.rs:43:10 | -44 | drop(s2); +43 | drop(s2); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:46:5 + --> $DIR/drop_forget_copy.rs:45:5 | -46 | drop(s4); +45 | drop(s4); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:46:10 + --> $DIR/drop_forget_copy.rs:45:10 | -46 | drop(s4); +45 | drop(s4); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:49:5 + --> $DIR/drop_forget_copy.rs:48:5 | -49 | forget(s1); +48 | forget(s1); | ^^^^^^^^^^ | = note: `-D clippy::forget-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:49:12 + --> $DIR/drop_forget_copy.rs:48:12 | -49 | forget(s1); +48 | forget(s1); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:50:5 + --> $DIR/drop_forget_copy.rs:49:5 | -50 | forget(s2); +49 | forget(s2); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:50:12 + --> $DIR/drop_forget_copy.rs:49:12 | -50 | forget(s2); +49 | forget(s2); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:52:5 + --> $DIR/drop_forget_copy.rs:51:5 | -52 | forget(s4); +51 | forget(s4); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:52:12 + --> $DIR/drop_forget_copy.rs:51:12 | -52 | forget(s4); +51 | forget(s4); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 15661ef1d2b..972ab298c4c 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -1,219 +1,219 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:22:5 + --> $DIR/drop_forget_ref.rs:18:5 | -22 | drop(&SomeStruct); +18 | drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::drop-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:22:10 + --> $DIR/drop_forget_ref.rs:18:10 | -22 | drop(&SomeStruct); +18 | drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:23:5 + --> $DIR/drop_forget_ref.rs:19:5 | -23 | forget(&SomeStruct); +19 | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:23:12 + --> $DIR/drop_forget_ref.rs:19:12 | -23 | forget(&SomeStruct); +19 | forget(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:26:5 + --> $DIR/drop_forget_ref.rs:22:5 | -26 | drop(&owned1); +22 | drop(&owned1); | ^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:26:10 + --> $DIR/drop_forget_ref.rs:22:10 | -26 | drop(&owned1); +22 | drop(&owned1); | ^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:27:5 + --> $DIR/drop_forget_ref.rs:23:5 | -27 | drop(&&owned1); +23 | drop(&&owned1); | ^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:27:10 + --> $DIR/drop_forget_ref.rs:23:10 | -27 | drop(&&owned1); +23 | drop(&&owned1); | ^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:28:5 + --> $DIR/drop_forget_ref.rs:24:5 | -28 | drop(&mut owned1); +24 | drop(&mut owned1); | ^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:28:10 + --> $DIR/drop_forget_ref.rs:24:10 | -28 | drop(&mut owned1); +24 | drop(&mut owned1); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:31:5 + --> $DIR/drop_forget_ref.rs:27:5 | -31 | forget(&owned2); +27 | forget(&owned2); | ^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:31:12 + --> $DIR/drop_forget_ref.rs:27:12 | -31 | forget(&owned2); +27 | forget(&owned2); | ^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:32:5 + --> $DIR/drop_forget_ref.rs:28:5 | -32 | forget(&&owned2); +28 | forget(&&owned2); | ^^^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:32:12 + --> $DIR/drop_forget_ref.rs:28:12 | -32 | forget(&&owned2); +28 | forget(&&owned2); | ^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:33:5 + --> $DIR/drop_forget_ref.rs:29:5 | -33 | forget(&mut owned2); +29 | forget(&mut owned2); | ^^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:33:12 + --> $DIR/drop_forget_ref.rs:29:12 | -33 | forget(&mut owned2); +29 | forget(&mut owned2); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:37:5 + --> $DIR/drop_forget_ref.rs:33:5 | -37 | drop(reference1); +33 | drop(reference1); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:37:10 + --> $DIR/drop_forget_ref.rs:33:10 | -37 | drop(reference1); +33 | drop(reference1); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:38:5 + --> $DIR/drop_forget_ref.rs:34:5 | -38 | forget(&*reference1); +34 | forget(&*reference1); | ^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:38:12 + --> $DIR/drop_forget_ref.rs:34:12 | -38 | forget(&*reference1); +34 | forget(&*reference1); | ^^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:41:5 + --> $DIR/drop_forget_ref.rs:37:5 | -41 | drop(reference2); +37 | drop(reference2); | ^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:41:10 + --> $DIR/drop_forget_ref.rs:37:10 | -41 | drop(reference2); +37 | drop(reference2); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:43:5 + --> $DIR/drop_forget_ref.rs:39:5 | -43 | forget(reference3); +39 | forget(reference3); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:43:12 + --> $DIR/drop_forget_ref.rs:39:12 | -43 | forget(reference3); +39 | forget(reference3); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:46:5 + --> $DIR/drop_forget_ref.rs:42:5 | -46 | drop(reference4); +42 | drop(reference4); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:46:10 + --> $DIR/drop_forget_ref.rs:42:10 | -46 | drop(reference4); +42 | drop(reference4); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:47:5 + --> $DIR/drop_forget_ref.rs:43:5 | -47 | forget(reference4); +43 | forget(reference4); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:47:12 + --> $DIR/drop_forget_ref.rs:43:12 | -47 | forget(reference4); +43 | forget(reference4); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:52:5 + --> $DIR/drop_forget_ref.rs:48:5 | -52 | drop(&val); +48 | drop(&val); | ^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:52:10 + --> $DIR/drop_forget_ref.rs:48:10 | -52 | drop(&val); +48 | drop(&val); | ^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:58:5 + --> $DIR/drop_forget_ref.rs:54:5 | -58 | forget(&val); +54 | forget(&val); | ^^^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:58:12 + --> $DIR/drop_forget_ref.rs:54:12 | -58 | forget(&val); +54 | forget(&val); | ^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:66:5 + --> $DIR/drop_forget_ref.rs:62:5 | -66 | std::mem::drop(&SomeStruct); +62 | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:66:20 + --> $DIR/drop_forget_ref.rs:62:20 | -66 | std::mem::drop(&SomeStruct); +62 | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:69:5 + --> $DIR/drop_forget_ref.rs:65:5 | -69 | std::mem::forget(&SomeStruct); +65 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:69:22 + --> $DIR/drop_forget_ref.rs:65:22 | -69 | std::mem::forget(&SomeStruct); +65 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ error: aborting due to 18 previous errors diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index 87b5c5e19d9..ba1b5b1ded7 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -1,7 +1,7 @@ error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult - --> $DIR/duplicate_underscore_argument.rs:17:23 + --> $DIR/duplicate_underscore_argument.rs:13:23 | -17 | fn join_the_dark_side(darth: i32, _darth: i32) {} +13 | fn join_the_dark_side(darth: i32, _darth: i32) {} | ^^^^^ | = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index 854af9dcb51..1310ac12340 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,33 +1,33 @@ error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:20:24 + --> $DIR/duration_subsec.rs:17:24 | -20 | let bad_millis_1 = dur.subsec_micros() / 1_000; +17 | let bad_millis_1 = dur.subsec_micros() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` | = note: `-D clippy::duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:21:24 + --> $DIR/duration_subsec.rs:18:24 | -21 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; +18 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:26:22 + --> $DIR/duration_subsec.rs:23:22 | -26 | let bad_micros = dur.subsec_nanos() / 1_000; +23 | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:31:13 + --> $DIR/duration_subsec.rs:28:13 | -31 | let _ = (&dur).subsec_nanos() / 1_000; +28 | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:35:13 + --> $DIR/duration_subsec.rs:32:13 | -35 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; +32 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: aborting due to 5 previous errors diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 7c8afcf3ce1..8771df87297 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,22 +1,24 @@ error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:51:12 + --> $DIR/else_if_without_else.rs:54:12 | -51 | } else if bla2() { //~ ERROR else if without else +54 | } else if bla2() { | ____________^ -52 | | println!("else if"); -53 | | } +55 | | //~ ERROR else if without else +56 | | println!("else if"); +57 | | } | |_____^ | = note: `-D clippy::else-if-without-else` implied by `-D warnings` = help: add an `else` block here error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:59:12 + --> $DIR/else_if_without_else.rs:63:12 | -59 | } else if bla3() { //~ ERROR else if without else +63 | } else if bla3() { | ____________^ -60 | | println!("else if 2"); -61 | | } +64 | | //~ ERROR else if without else +65 | | println!("else if 2"); +66 | | } | |_____^ | = help: add an `else` block here diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index 9d6691c974d..fd981f2210f 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -1,14 +1,14 @@ error: enum with no variants - --> $DIR/empty_enum.rs:17:1 + --> $DIR/empty_enum.rs:13:1 | -17 | enum Empty {} +13 | enum Empty {} | ^^^^^^^^^^^^^ | = note: `-D clippy::empty-enum` implied by `-D warnings` help: consider using the uninhabited type `!` or a wrapper around it - --> $DIR/empty_enum.rs:17:1 + --> $DIR/empty_enum.rs:13:1 | -17 | enum Empty {} +13 | enum Empty {} | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 60e5ae893b6..9a4e0ba31ee 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -1,46 +1,74 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:23:5 + --> $DIR/entry.rs:19:5 | -23 | if !m.contains_key(&k) { m.insert(k, v); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k).or_insert(v)` +19 | / if !m.contains_key(&k) { +20 | | m.insert(k, v); +21 | | } + | |_____^ help: consider using: `m.entry(k).or_insert(v)` | = note: `-D clippy::map-entry` implied by `-D warnings` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:27:5 + --> $DIR/entry.rs:25:5 | -27 | if !m.contains_key(&k) { foo(); m.insert(k, v); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +25 | / if !m.contains_key(&k) { +26 | | foo(); +27 | | m.insert(k, v); +28 | | } + | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:31:5 + --> $DIR/entry.rs:32:5 | -31 | if !m.contains_key(&k) { m.insert(k, v) } else { None }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +32 | / if !m.contains_key(&k) { +33 | | m.insert(k, v) +34 | | } else { +35 | | None +36 | | }; + | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:35:5 + --> $DIR/entry.rs:40:5 | -35 | if m.contains_key(&k) { None } else { m.insert(k, v) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +40 | / if m.contains_key(&k) { +41 | | None +42 | | } else { +43 | | m.insert(k, v) +44 | | }; + | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:39:5 + --> $DIR/entry.rs:48:5 | -39 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +48 | / if !m.contains_key(&k) { +49 | | foo(); +50 | | m.insert(k, v) +51 | | } else { +52 | | None +53 | | }; + | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:43:5 + --> $DIR/entry.rs:57:5 | -43 | if m.contains_key(&k) { None } else { foo(); m.insert(k, v) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +57 | / if m.contains_key(&k) { +58 | | None +59 | | } else { +60 | | foo(); +61 | | m.insert(k, v) +62 | | }; + | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `BTreeMap` - --> $DIR/entry.rs:47:5 + --> $DIR/entry.rs:66:5 | -47 | if !m.contains_key(&k) { foo(); m.insert(k, v) } else { None }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `m.entry(k)` +66 | / if !m.contains_key(&k) { +67 | | foo(); +68 | | m.insert(k, v) +69 | | } else { +70 | | None +71 | | }; + | |_____^ help: consider using: `m.entry(k)` error: aborting due to 7 previous errors diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 2dac4a2b106..58c6f4d3301 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -1,15 +1,15 @@ error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:16:1 + --> $DIR/enum_glob_use.rs:13:1 | -16 | use std::cmp::Ordering::*; +13 | use std::cmp::Ordering::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::enum-glob-use` implied by `-D warnings` error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:22:1 + --> $DIR/enum_glob_use.rs:19:1 | -22 | use self::Enum::*; +19 | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 7b63fab3a99..ff8f9b82ae6 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,61 +1,61 @@ error: Variant name ends with the enum's name - --> $DIR/enum_variants.rs:26:5 + --> $DIR/enum_variants.rs:24:5 | -26 | cFoo, +24 | cFoo, | ^^^^ | = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:37:5 + --> $DIR/enum_variants.rs:35:5 | -37 | FoodGood, +35 | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:38:5 + --> $DIR/enum_variants.rs:36:5 | -38 | FoodMiddle, +36 | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:39:5 + --> $DIR/enum_variants.rs:37:5 | -39 | FoodBad, +37 | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:36:1 + --> $DIR/enum_variants.rs:34:1 | -36 | / enum Food { -37 | | FoodGood, -38 | | FoodMiddle, -39 | | FoodBad, -40 | | } +34 | / enum Food { +35 | | FoodGood, +36 | | FoodMiddle, +37 | | FoodBad, +38 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:46:1 + --> $DIR/enum_variants.rs:44:1 | -46 | / enum BadCallType { -47 | | CallTypeCall, -48 | | CallTypeCreate, -49 | | CallTypeDestroy, -50 | | } +44 | / enum BadCallType { +45 | | CallTypeCall, +46 | | CallTypeCreate, +47 | | CallTypeDestroy, +48 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:57:1 + --> $DIR/enum_variants.rs:56:1 | -57 | / enum Consts { -58 | | ConstantInt, -59 | | ConstantCake, -60 | | ConstantLie, -61 | | } +56 | / enum Consts { +57 | | ConstantInt, +58 | | ConstantCake, +59 | | ConstantLie, +60 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index 27b184ea3cc..0756b9a80d4 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -1,51 +1,51 @@ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:22:5 + --> $DIR/enums_clike.rs:17:5 | -22 | X = 0x1_0000_0000, +17 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:29:5 + --> $DIR/enums_clike.rs:24:5 | -29 | X = 0x1_0000_0000, +24 | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:32:5 + --> $DIR/enums_clike.rs:27:5 | -32 | A = 0xFFFF_FFFF, +27 | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:39:5 + --> $DIR/enums_clike.rs:34:5 | -39 | Z = 0xFFFF_FFFF, +34 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:40:5 + --> $DIR/enums_clike.rs:35:5 | -40 | A = 0x1_0000_0000, +35 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:42:5 + --> $DIR/enums_clike.rs:37:5 | -42 | C = (std::i32::MIN as isize) - 1, +37 | C = (std::i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:48:5 + --> $DIR/enums_clike.rs:43:5 | -48 | Z = 0xFFFF_FFFF, +43 | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:49:5 + --> $DIR/enums_clike.rs:44:5 | -49 | A = 0x1_0000_0000, +44 | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 2cc3db7c268..a500a132af7 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -1,21 +1,21 @@ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:19:5 + --> $DIR/erasing_op.rs:15:5 | -19 | x * 0; +15 | x * 0; | ^^^^^ | = note: `-D clippy::erasing-op` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:20:5 + --> $DIR/erasing_op.rs:16:5 | -20 | 0 & x; +16 | 0 & x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:21:5 + --> $DIR/erasing_op.rs:17:5 | -21 | 0 / x; +17 | 0 / x; | ^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr index 25ba413b75a..ec9b7317eed 100644 --- a/tests/ui/escape_analysis.stderr +++ b/tests/ui/escape_analysis.stderr @@ -1,15 +1,15 @@ error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:45:13 + --> $DIR/escape_analysis.rs:43:13 | -45 | fn warn_arg(x: Box) { +43 | fn warn_arg(x: Box) { | ^ | = note: `-D clippy::boxed-local` implied by `-D warnings` error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:137:12 + --> $DIR/escape_analysis.rs:134:12 | -137 | pub fn new(_needs_name: Box>) -> () { +134 | pub fn new(_needs_name: Box>) -> () {} | ^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index dcdf0699ff7..cd14855c49d 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,35 +1,35 @@ error: redundant closure found - --> $DIR/eta.rs:17:27 + --> $DIR/eta.rs:22:27 | -17 | let a = Some(1u8).map(|a| foo(a)); +22 | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` | = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:18:10 + --> $DIR/eta.rs:23:10 | -18 | meta(|a| foo(a)); +23 | meta(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` error: redundant closure found - --> $DIR/eta.rs:19:27 + --> $DIR/eta.rs:24:27 | -19 | let c = Some(1u8).map(|a| {1+2; foo}(a)); +24 | let c = Some(1u8).map(|a| {1+2; foo}(a)); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/eta.rs:21:21 + --> $DIR/eta.rs:26:21 | -21 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted +26 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` | = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:28:27 + --> $DIR/eta.rs:33:27 | -28 | let e = Some(1u8).map(|a| generic(a)); +33 | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: aborting due to 5 previous errors diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index d5be92e993f..38317376fc4 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -1,51 +1,51 @@ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:18:28 + --> $DIR/eval_order_dependence.rs:24:9 | -18 | let a = { x = 1; 1 } + x; - | ^ +24 | } + x; + | ^ | = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:18:15 + --> $DIR/eval_order_dependence.rs:22:9 | -18 | let a = { x = 1; 1 } + x; - | ^^^^^ +22 | x = 1; + | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:21:5 + --> $DIR/eval_order_dependence.rs:27:5 | -21 | x += { x = 20; 2 }; +27 | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:21:12 + --> $DIR/eval_order_dependence.rs:28:9 | -21 | x += { x = 20; 2 }; - | ^^^^^^ +28 | x = 20; + | ^^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:27:24 + --> $DIR/eval_order_dependence.rs:40:12 | -27 | let foo = Foo { a: x, .. { x = 6; base } }; - | ^ +40 | a: x, + | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:27:32 + --> $DIR/eval_order_dependence.rs:42:13 | -27 | let foo = Foo { a: x, .. { x = 6; base } }; - | ^^^^^ +42 | x = 6; + | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:31:9 + --> $DIR/eval_order_dependence.rs:49:9 | -31 | x += { x = 20; 2 }; +49 | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:31:16 + --> $DIR/eval_order_dependence.rs:50:13 | -31 | x += { x = 20; 2 }; - | ^^^^^^ +50 | x = 20; + | ^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 783e41f2b50..a69652373d5 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,111 +1,111 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:25:26 + --> $DIR/excessive_precision.rs:23:26 | -25 | const BAD32_1: f32 = 0.123_456_789_f32; +23 | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` | = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:26:26 + --> $DIR/excessive_precision.rs:24:26 | -26 | const BAD32_2: f32 = 0.123_456_789; +24 | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:27:26 + --> $DIR/excessive_precision.rs:25:26 | -27 | const BAD32_3: f32 = 0.100_000_000_000_1; +25 | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:28:29 + --> $DIR/excessive_precision.rs:26:29 | -28 | const BAD32_EDGE: f32 = 1.000_000_9; +26 | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:30:26 + --> $DIR/excessive_precision.rs:28:26 | -30 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; +28 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:31:26 + --> $DIR/excessive_precision.rs:29:26 | -31 | const BAD64_2: f64 = 0.123_456_789_012_345_67; +29 | const BAD64_2: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:32:26 + --> $DIR/excessive_precision.rs:30:26 | -32 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; +30 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:35:22 + --> $DIR/excessive_precision.rs:33:22 | -35 | println!("{:?}", 8.888_888_888_888_888_888_888); +33 | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:46:22 + --> $DIR/excessive_precision.rs:44:22 | -46 | let bad32: f32 = 1.123_456_789; +44 | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:47:26 + --> $DIR/excessive_precision.rs:45:26 | -47 | let bad32_suf: f32 = 1.123_456_789_f32; +45 | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:21 + --> $DIR/excessive_precision.rs:46:21 | -48 | let bad32_inf = 1.123_456_789_f32; +46 | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:50:22 + --> $DIR/excessive_precision.rs:48:22 | -50 | let bad64: f64 = 0.123_456_789_012_345_67; +48 | let bad64: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:51:26 + --> $DIR/excessive_precision.rs:49:26 | -51 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; +49 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:52:21 + --> $DIR/excessive_precision.rs:50:21 | -52 | let bad64_inf = 0.123_456_789_012_345_67; +50 | let bad64_inf = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:58:36 + --> $DIR/excessive_precision.rs:56:36 | -58 | let bad_vec32: Vec = vec![0.123_456_789]; +56 | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:59:36 + --> $DIR/excessive_precision.rs:57:36 | -59 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; +57 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:63:24 + --> $DIR/excessive_precision.rs:61:24 | -63 | let bad_e32: f32 = 1.123_456_788_888e-10; +61 | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:66:27 + --> $DIR/excessive_precision.rs:64:27 | -66 | let bad_bige32: f32 = 1.123_456_788_888E-10; +64 | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` error: aborting due to 18 previous errors diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 6b1550b2195..ad8fe14e9a0 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,39 +1,39 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:34:26 + --> $DIR/expect_fun_call.rs:36:26 | -34 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); +36 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:37:26 + --> $DIR/expect_fun_call.rs:39:26 | -37 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +39 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:47:25 + --> $DIR/expect_fun_call.rs:49:25 | -47 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); +49 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:50:25 + --> $DIR/expect_fun_call.rs:52:25 | -50 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +52 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:65:17 + --> $DIR/expect_fun_call.rs:67:17 | -65 | Some("foo").expect({ &format!("error") }); +67 | Some("foo").expect({ &format!("error") }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:66:17 + --> $DIR/expect_fun_call.rs:68:17 | -66 | Some("foo").expect(format!("error").as_ref()); +68 | Some("foo").expect(format!("error").as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` error: aborting due to 6 previous errors diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index 023f7f299a7..caafd2375f0 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -13,15 +13,15 @@ error: the variable `_index` is used as a loop counter. Consider using `for (_in | ^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:58:19 + --> $DIR/explicit_counter_loop.rs:60:19 | -58 | for ch in text.chars() { +60 | for ch in text.chars() { | ^^^^^^^^^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:69:19 + --> $DIR/explicit_counter_loop.rs:71:19 | -69 | for ch in text.chars() { +71 | for ch in text.chars() { | ^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index fadc12c7594..171bf312a9b 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,39 +1,39 @@ error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:28:9 + --> $DIR/explicit_write.rs:24:9 | -28 | write!(std::io::stdout(), "test").unwrap(); +24 | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:29:9 + --> $DIR/explicit_write.rs:25:9 | -29 | write!(std::io::stderr(), "test").unwrap(); +25 | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead - --> $DIR/explicit_write.rs:30:9 + --> $DIR/explicit_write.rs:26:9 | -30 | writeln!(std::io::stdout(), "test").unwrap(); +26 | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead - --> $DIR/explicit_write.rs:31:9 + --> $DIR/explicit_write.rs:27:9 | -31 | writeln!(std::io::stderr(), "test").unwrap(); +27 | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:32:9 + --> $DIR/explicit_write.rs:28:9 | -32 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); +28 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:33:9 + --> $DIR/explicit_write.rs:29:9 | -33 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); +29 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 97ece931464..8af5933a9f8 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -1,91 +1,91 @@ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:17:1 + --> $DIR/fallible_impl_from.rs:14:1 | -17 | / impl From for Foo { -18 | | fn from(s: String) -> Self { -19 | | Foo(s.parse().unwrap()) -20 | | } -21 | | } +14 | / impl From for Foo { +15 | | fn from(s: String) -> Self { +16 | | Foo(s.parse().unwrap()) +17 | | } +18 | | } | |_^ | note: lint level defined here - --> $DIR/fallible_impl_from.rs:13:9 + --> $DIR/fallible_impl_from.rs:10:9 | -13 | #![deny(clippy::fallible_impl_from)] +10 | #![deny(clippy::fallible_impl_from)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:19:13 + --> $DIR/fallible_impl_from.rs:16:13 | -19 | Foo(s.parse().unwrap()) +16 | Foo(s.parse().unwrap()) | ^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:40:1 + --> $DIR/fallible_impl_from.rs:35:1 | -40 | / impl From for Invalid { -41 | | fn from(i: usize) -> Invalid { -42 | | if i != 42 { -43 | | panic!(); +35 | / impl From for Invalid { +36 | | fn from(i: usize) -> Invalid { +37 | | if i != 42 { +38 | | panic!(); ... | -46 | | } -47 | | } +41 | | } +42 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:43:13 + --> $DIR/fallible_impl_from.rs:38:13 | -43 | panic!(); +38 | panic!(); | ^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:49:1 + --> $DIR/fallible_impl_from.rs:44:1 | -49 | / impl From> for Invalid { -50 | | fn from(s: Option) -> Invalid { -51 | | let s = s.unwrap(); -52 | | if !s.is_empty() { +44 | / impl From> for Invalid { +45 | | fn from(s: Option) -> Invalid { +46 | | let s = s.unwrap(); +47 | | if !s.is_empty() { ... | -58 | | } -59 | | } +53 | | } +54 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:51:17 + --> $DIR/fallible_impl_from.rs:46:17 | -51 | let s = s.unwrap(); +46 | let s = s.unwrap(); | ^^^^^^^^^^ -52 | if !s.is_empty() { -53 | panic!(42); +47 | if !s.is_empty() { +48 | panic!(42); | ^^^^^^^^^^^ -54 | } else if s.parse::().unwrap() != 42 { +49 | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -55 | panic!("{:?}", s); +50 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:67:1 + --> $DIR/fallible_impl_from.rs:62:1 | -67 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { -68 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -69 | | if s.parse::().ok().unwrap() != 42 { -70 | | panic!("{:?}", s); +62 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +63 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +64 | | if s.parse::().ok().unwrap() != 42 { +65 | | panic!("{:?}", s); ... | -73 | | } -74 | | } +68 | | } +69 | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:69:12 + --> $DIR/fallible_impl_from.rs:64:12 | -69 | if s.parse::().ok().unwrap() != 42 { +64 | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -70 | panic!("{:?}", s); +65 | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index 6adbec44cf9..8fde78ca5a7 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -1,40 +1,40 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:18:21 + --> $DIR/filter_methods.rs:14:21 | -18 | let _: Vec<_> = vec![5; 6].into_iter() - | _____________________^ -19 | | .filter(|&x| x == 0) -20 | | .map(|x| x * 2) - | |_____________________________________________^ +14 | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::filter-map` implied by `-D warnings` error: called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:23:21 + --> $DIR/filter_methods.rs:16:21 | -23 | let _: Vec<_> = vec![5_i8; 6].into_iter() +16 | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -24 | | .filter(|&x| x == 0) -25 | | .flat_map(|x| x.checked_mul(2)) - | |_______________________________________________________________^ +17 | | .into_iter() +18 | | .filter(|&x| x == 0) +19 | | .flat_map(|x| x.checked_mul(2)) + | |_______________________________________^ error: called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:28:21 + --> $DIR/filter_methods.rs:22:21 | -28 | let _: Vec<_> = vec![5_i8; 6].into_iter() +22 | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -29 | | .filter_map(|x| x.checked_mul(2)) -30 | | .flat_map(|x| x.checked_mul(2)) - | |_______________________________________________________________^ +23 | | .into_iter() +24 | | .filter_map(|x| x.checked_mul(2)) +25 | | .flat_map(|x| x.checked_mul(2)) + | |_______________________________________^ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly expressed by only calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:33:21 + --> $DIR/filter_methods.rs:28:21 | -33 | let _: Vec<_> = vec![5_i8; 6].into_iter() +28 | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -34 | | .filter_map(|x| x.checked_mul(2)) -35 | | .map(|x| x.checked_mul(2)) - | |__________________________________________________________^ +29 | | .into_iter() +30 | | .filter_map(|x| x.checked_mul(2)) +31 | | .map(|x| x.checked_mul(2)) + | |__________________________________^ error: aborting due to 4 previous errors diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index 52ec0e3ed78..3acd71eb99b 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,38 +1,38 @@ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:59:5 + --> $DIR/float_cmp.rs:69:5 | -59 | ONE as f64 != 2.0; +69 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | = note: `-D clippy::float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:59:5 + --> $DIR/float_cmp.rs:69:5 | -59 | ONE as f64 != 2.0; +69 | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:64:5 + --> $DIR/float_cmp.rs:74:5 | -64 | x == 1.0; +74 | x == 1.0; | ^^^^^^^^ help: consider comparing them within some error: `(x - 1.0).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:64:5 + --> $DIR/float_cmp.rs:74:5 | -64 | x == 1.0; +74 | x == 1.0; | ^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:67:5 + --> $DIR/float_cmp.rs:77:5 | -67 | twice(x) != twice(ONE as f64); +77 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(x) - twice(ONE as f64)).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:67:5 + --> $DIR/float_cmp.rs:77:5 | -67 | twice(x) != twice(ONE as f64); +77 | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index f70a6d3b32f..640cee1bc2f 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,420 +1,420 @@ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:38:14 + --> $DIR/for_loop.rs:50:14 | -38 | for i in 0..vec.len() { +50 | for i in 0..vec.len() { | ^^^^^^^^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -38 | for in &vec { +50 | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:47:14 + --> $DIR/for_loop.rs:59:14 | -47 | for i in 0..vec.len() { +59 | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -47 | for in &vec { +59 | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:52:14 + --> $DIR/for_loop.rs:64:14 | -52 | for j in 0..4 { +64 | for j in 0..4 { | ^^^^ help: consider using an iterator | -52 | for in &STATIC { +64 | for in &STATIC { | ^^^^^^ ^^^^^^^ error: the loop variable `j` is only used to index `CONST`. - --> $DIR/for_loop.rs:56:14 + --> $DIR/for_loop.rs:68:14 | -56 | for j in 0..4 { +68 | for j in 0..4 { | ^^^^ help: consider using an iterator | -56 | for in &CONST { +68 | for in &CONST { | ^^^^^^ ^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:60:14 + --> $DIR/for_loop.rs:72:14 | -60 | for i in 0..vec.len() { +72 | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -60 | for (i, ) in vec.iter().enumerate() { +72 | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:68:14 + --> $DIR/for_loop.rs:80:14 | -68 | for i in 0..vec.len() { +80 | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -68 | for in vec2.iter().take(vec.len()) { +80 | for in vec2.iter().take(vec.len()) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:72:14 + --> $DIR/for_loop.rs:84:14 | -72 | for i in 5..vec.len() { +84 | for i in 5..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -72 | for in vec.iter().skip(5) { +84 | for in vec.iter().skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:76:14 + --> $DIR/for_loop.rs:88:14 | -76 | for i in 0..MAX_LEN { +88 | for i in 0..MAX_LEN { | ^^^^^^^^^^ help: consider using an iterator | -76 | for in vec.iter().take(MAX_LEN) { +88 | for in vec.iter().take(MAX_LEN) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:80:14 + --> $DIR/for_loop.rs:92:14 | -80 | for i in 0..=MAX_LEN { +92 | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ help: consider using an iterator | -80 | for in vec.iter().take(MAX_LEN + 1) { +92 | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:84:14 + --> $DIR/for_loop.rs:96:14 | -84 | for i in 5..10 { +96 | for i in 5..10 { | ^^^^^ help: consider using an iterator | -84 | for in vec.iter().take(10).skip(5) { +96 | for in vec.iter().take(10).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:88:14 - | -88 | for i in 5..=10 { - | ^^^^^^ + --> $DIR/for_loop.rs:100:14 + | +100 | for i in 5..=10 { + | ^^^^^^ help: consider using an iterator - | -88 | for in vec.iter().take(10 + 1).skip(5) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +100 | for in vec.iter().take(10 + 1).skip(5) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:92:14 - | -92 | for i in 5..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:104:14 + | +104 | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -92 | for (i, ) in vec.iter().enumerate().skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +104 | for (i, ) in vec.iter().enumerate().skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:96:14 - | -96 | for i in 5..10 { - | ^^^^^ + --> $DIR/for_loop.rs:108:14 + | +108 | for i in 5..10 { + | ^^^^^ help: consider using an iterator - | -96 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +108 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:100:14 + --> $DIR/for_loop.rs:112:14 | -100 | for i in 10..0 { +112 | for i in 10..0 { | ^^^^^ | = note: `-D clippy::reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | -100 | for i in (0..10).rev() { +112 | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:104:14 + --> $DIR/for_loop.rs:116:14 | -104 | for i in 10..=0 { +116 | for i in 10..=0 { | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -104 | for i in (0...10).rev() { +116 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:108:14 + --> $DIR/for_loop.rs:120:14 | -108 | for i in MAX_LEN..0 { +120 | for i in MAX_LEN..0 { | ^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -108 | for i in (0..MAX_LEN).rev() { +120 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:112:14 + --> $DIR/for_loop.rs:124:14 | -112 | for i in 5..5 { +124 | for i in 5..5 { | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:137:14 + --> $DIR/for_loop.rs:149:14 | -137 | for i in 10..5 + 4 { +149 | for i in 10..5 + 4 { | ^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -137 | for i in (5 + 4..10).rev() { +149 | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:141:14 + --> $DIR/for_loop.rs:153:14 | -141 | for i in (5 + 2)..(3 - 1) { +153 | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -141 | for i in ((3 - 1)..(5 + 2)).rev() { +153 | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:145:14 + --> $DIR/for_loop.rs:157:14 | -145 | for i in (5 + 2)..(8 - 1) { +157 | for i in (5 + 2)..(8 - 1) { | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:167:15 + --> $DIR/for_loop.rs:179:15 | -167 | for _v in vec.iter() {} +179 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:169:15 + --> $DIR/for_loop.rs:181:15 | -169 | for _v in vec.iter_mut() {} +181 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:172:15 + --> $DIR/for_loop.rs:184:15 | -172 | for _v in out_vec.into_iter() {} +184 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:175:15 + --> $DIR/for_loop.rs:187:15 | -175 | for _v in array.into_iter() {} +187 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:180:15 + --> $DIR/for_loop.rs:192:15 | -180 | for _v in [1, 2, 3].iter() {} +192 | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:184:15 + --> $DIR/for_loop.rs:196:15 | -184 | for _v in [0; 32].iter() {} +196 | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:189:15 + --> $DIR/for_loop.rs:201:15 | -189 | for _v in ll.iter() {} +201 | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:192:15 + --> $DIR/for_loop.rs:204:15 | -192 | for _v in vd.iter() {} +204 | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:195:15 + --> $DIR/for_loop.rs:207:15 | -195 | for _v in bh.iter() {} +207 | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:198:15 + --> $DIR/for_loop.rs:210:15 | -198 | for _v in hm.iter() {} +210 | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:201:15 + --> $DIR/for_loop.rs:213:15 | -201 | for _v in bt.iter() {} +213 | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:204:15 + --> $DIR/for_loop.rs:216:15 | -204 | for _v in hs.iter() {} +216 | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:207:15 + --> $DIR/for_loop.rs:219:15 | -207 | for _v in bs.iter() {} +219 | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:209:15 + --> $DIR/for_loop.rs:221:15 | -209 | for _v in vec.iter().next() {} +221 | for _v in vec.iter().next() {} | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:216:5 + --> $DIR/for_loop.rs:228:5 | -216 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); +228 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:325:19 + --> $DIR/for_loop.rs:337:19 | -325 | for (_, v) in &m { +337 | for (_, v) in &m { | ^^ | = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method | -325 | for v in m.values() { +337 | for v in m.values() { | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:330:19 + --> $DIR/for_loop.rs:342:19 | -330 | for (_, v) in &*m { +342 | for (_, v) in &*m { | ^^^ help: use the corresponding method | -330 | for v in (*m).values() { +342 | for v in (*m).values() { | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:338:19 + --> $DIR/for_loop.rs:350:19 | -338 | for (_, v) in &mut m { +350 | for (_, v) in &mut m { | ^^^^^^ help: use the corresponding method | -338 | for v in m.values_mut() { +350 | for v in m.values_mut() { | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:343:19 + --> $DIR/for_loop.rs:355:19 | -343 | for (_, v) in &mut *m { +355 | for (_, v) in &mut *m { | ^^^^^^^ help: use the corresponding method | -343 | for v in (*m).values_mut() { +355 | for v in (*m).values_mut() { | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:349:24 + --> $DIR/for_loop.rs:361:24 | -349 | for (k, _value) in rm { +361 | for (k, _value) in rm { | ^^ help: use the corresponding method | -349 | for k in rm.keys() { +361 | for k in rm.keys() { | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:402:14 + --> $DIR/for_loop.rs:414:14 | -402 | for i in 0..src.len() { +414 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` | = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:407:14 + --> $DIR/for_loop.rs:419:14 | -407 | for i in 0..src.len() { +419 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:412:14 + --> $DIR/for_loop.rs:424:14 | -412 | for i in 0..src.len() { +424 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:417:14 + --> $DIR/for_loop.rs:429:14 | -417 | for i in 11..src.len() { +429 | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:422:14 + --> $DIR/for_loop.rs:434:14 | -422 | for i in 0..dst.len() { +434 | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:435:14 + --> $DIR/for_loop.rs:447:14 | -435 | for i in 10..256 { +447 | for i in 10..256 { | ^^^^^^^ help: try replacing the loop by | -435 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -436 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { +447 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +448 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:447:14 + --> $DIR/for_loop.rs:459:14 | -447 | for i in 10..LOOP_OFFSET { +459 | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:460:14 + --> $DIR/for_loop.rs:472:14 | -460 | for i in 0..src_vec.len() { +472 | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:489:14 + --> $DIR/for_loop.rs:501:14 | -489 | for i in from..from + src.len() { +501 | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:493:14 + --> $DIR/for_loop.rs:505:14 | -493 | for i in from..from + 3 { +505 | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:500:14 + --> $DIR/for_loop.rs:512:14 | -500 | for i in 0..src.len() { +512 | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` error: aborting due to 51 previous errors diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index e1620b22125..84749b6caac 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,90 +1,19 @@ -error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:25:6 - | -25 | } if foo() { - | ^ - | - = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` - = note: to remove this lint, add the missing `else` or add a new line before the second `if` - -error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:32:10 - | -32 | } if foo() { - | ^ - | - = note: to remove this lint, add the missing `else` or add a new line before the second `if` - -error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:40:10 - | -40 | } if foo() { - | ^ - | - = note: to remove this lint, add the missing `else` or add a new line before the second `if` - -error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:49:6 - | -49 | } else - | ______^ -50 | | if foo() { // the span of the above error should continue here - | |____^ - | - = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` - -error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:54:6 - | -54 | } - | ______^ -55 | | else -56 | | if foo() { // the span of the above error should continue here - | |____^ - | - = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` - -error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:81:6 - | -81 | a =- 35; - | ^^^^ - | - = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` - = note: to remove this lint, use either `-=` or `= -` - -error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:82:6 - | -82 | a =* &191; - | ^^^^ - | - = note: to remove this lint, use either `*=` or `= *` - -error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:85:6 - | -85 | b =! false; - | ^^^^ - | - = note: to remove this lint, use either `!=` or `= !` - error: possibly missing a comma here - --> $DIR/formatting.rs:94:19 + --> $DIR/formatting.rs:88:11 | -94 | -1, -2, -3 // <= no comma here - | ^ +88 | -3 // <= no comma here + | ^ | = note: `-D clippy::possible-missing-comma` implied by `-D warnings` = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:98:19 + --> $DIR/formatting.rs:96:11 | -98 | -1, -2, -3 // <= no comma here - | ^ +96 | -3 // <= no comma here + | ^ | = note: to remove this lint, add a comma or write the expr in a single line -error: aborting due to 10 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 9c45eb033ea..206d04d6a39 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -1,78 +1,77 @@ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:21:1 + --> $DIR/functions.rs:17:1 | -21 | / fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) { -22 | | } - | |_^ +17 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` error: this function has too many arguments (8/7) - --> $DIR/functions.rs:29:5 + --> $DIR/functions.rs:34:5 | -29 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); +34 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:38:5 + --> $DIR/functions.rs:43:5 | -38 | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +43 | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:47:34 + --> $DIR/functions.rs:52:34 | -47 | println!("{}", unsafe { *p }); +52 | println!("{}", unsafe { *p }); | ^ | = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:48:35 + --> $DIR/functions.rs:53:35 | -48 | println!("{:?}", unsafe { p.as_ref() }); +53 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:49:33 + --> $DIR/functions.rs:54:33 | -49 | unsafe { std::ptr::read(p) }; +54 | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:60:30 + --> $DIR/functions.rs:65:30 | -60 | println!("{}", unsafe { *p }); +65 | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:61:31 + --> $DIR/functions.rs:66:31 | -61 | println!("{:?}", unsafe { p.as_ref() }); +66 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:62:29 + --> $DIR/functions.rs:67:29 | -62 | unsafe { std::ptr::read(p) }; +67 | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:71:34 + --> $DIR/functions.rs:76:34 | -71 | println!("{}", unsafe { *p }); +76 | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:72:35 + --> $DIR/functions.rs:77:35 | -72 | println!("{:?}", unsafe { p.as_ref() }); +77 | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:73:33 + --> $DIR/functions.rs:78:33 | -73 | unsafe { std::ptr::read(p) }; +78 | unsafe { std::ptr::read(p) }; | ^ error: aborting due to 12 previous errors diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index f5f8ae7e801..a1e50401b46 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -1,39 +1,39 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:18:24 + --> $DIR/fxhash.rs:16:24 | -18 | use std::collections::{HashMap, HashSet}; +16 | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashMap` | = note: `-D clippy::default-hash-types` implied by `-D warnings` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:18:33 + --> $DIR/fxhash.rs:16:33 | -18 | use std::collections::{HashMap, HashSet}; +16 | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:22:15 + --> $DIR/fxhash.rs:19:15 | -22 | let _map: HashMap = HashMap::default(); +19 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:22:41 + --> $DIR/fxhash.rs:19:41 | -22 | let _map: HashMap = HashMap::default(); +19 | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:23:15 + --> $DIR/fxhash.rs:20:15 | -23 | let _set: HashSet = HashSet::default(); +20 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:23:33 + --> $DIR/fxhash.rs:20:33 | -23 | let _set: HashSet = HashSet::default(); +20 | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: aborting due to 6 previous errors diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 90b46e960f4..8b07e740a9a 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,75 +1,75 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:41:17 | -37 | let _ = boxed_slice.get(1).unwrap(); +41 | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D clippy::get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:42:17 | -38 | let _ = some_slice.get(0).unwrap(); +42 | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:43:17 | -39 | let _ = some_vec.get(0).unwrap(); +43 | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:44:17 | -40 | let _ = some_vecdeque.get(0).unwrap(); +44 | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:45:17 | -41 | let _ = some_hashmap.get(&1).unwrap(); +45 | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:42:17 + --> $DIR/get_unwrap.rs:46:17 | -42 | let _ = some_btreemap.get(&1).unwrap(); +46 | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:47:10 + --> $DIR/get_unwrap.rs:52:10 | -47 | *boxed_slice.get_mut(0).unwrap() = 1; +52 | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:48:10 + --> $DIR/get_unwrap.rs:53:10 | -48 | *some_slice.get_mut(0).unwrap() = 1; +53 | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:49:10 + --> $DIR/get_unwrap.rs:54:10 | -49 | *some_vec.get_mut(0).unwrap() = 1; +54 | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:50:10 + --> $DIR/get_unwrap.rs:55:10 | -50 | *some_vecdeque.get_mut(0).unwrap() = 1; +55 | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:58:17 + --> $DIR/get_unwrap.rs:64:17 | -58 | let _ = some_vec.get(0..1).unwrap().to_vec(); +64 | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:59:17 + --> $DIR/get_unwrap.rs:65:17 | -59 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); +65 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: aborting due to 12 previous errors diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 15bef8b125e..aab6bf7f218 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,67 +1,67 @@ error: identical conversion - --> $DIR/identity_conversion.rs:16:13 + --> $DIR/identity_conversion.rs:13:13 | -16 | let _ = T::from(val); +13 | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: lint level defined here - --> $DIR/identity_conversion.rs:13:9 + --> $DIR/identity_conversion.rs:10:9 | -13 | #![deny(clippy::identity_conversion)] +10 | #![deny(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion - --> $DIR/identity_conversion.rs:17:5 + --> $DIR/identity_conversion.rs:14:5 | -17 | val.into() +14 | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion - --> $DIR/identity_conversion.rs:29:22 + --> $DIR/identity_conversion.rs:26:22 | -29 | let _: i32 = 0i32.into(); +26 | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:50:21 + --> $DIR/identity_conversion.rs:47:21 | -50 | let _: String = "foo".to_string().into(); +47 | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:51:21 + --> $DIR/identity_conversion.rs:48:21 | -51 | let _: String = From::from("foo".to_string()); +48 | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:52:13 + --> $DIR/identity_conversion.rs:49:13 | -52 | let _ = String::from("foo".to_string()); +49 | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:53:13 + --> $DIR/identity_conversion.rs:50:13 | -53 | let _ = String::from(format!("A: {:04}", 123)); +50 | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion - --> $DIR/identity_conversion.rs:54:13 + --> $DIR/identity_conversion.rs:51:13 | -54 | let _ = "".lines().into_iter(); +51 | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion - --> $DIR/identity_conversion.rs:55:13 + --> $DIR/identity_conversion.rs:52:13 | -55 | let _ = vec![1, 2, 3].into_iter().into_iter(); +52 | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: identical conversion - --> $DIR/identity_conversion.rs:56:21 + --> $DIR/identity_conversion.rs:53:21 | -56 | let _: String = format!("Hello {}", "world").into(); +53 | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: aborting due to 10 previous errors diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 332350fd1d8..e2b6efa7dbe 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,51 +1,51 @@ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:23:5 + --> $DIR/identity_op.rs:24:5 | -23 | x + 0; +24 | x + 0; | ^^^^^ | = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:24:5 + --> $DIR/identity_op.rs:25:5 | -24 | x + (1 - 1); +25 | x + (1 - 1); | ^^^^^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:26:5 + --> $DIR/identity_op.rs:27:5 | -26 | 0 + x; +27 | 0 + x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:29:5 + --> $DIR/identity_op.rs:30:5 | -29 | x | (0); +30 | x | (0); | ^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:32:5 + --> $DIR/identity_op.rs:33:5 | -32 | x * 1; +33 | x * 1; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:33:5 + --> $DIR/identity_op.rs:34:5 | -33 | 1 * x; +34 | 1 * x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:39:5 + --> $DIR/identity_op.rs:40:5 | -39 | -1 & x; +40 | -1 & x; | ^^^^^^ error: the operation is ineffective. Consider reducing it to `u` - --> $DIR/identity_op.rs:42:5 + --> $DIR/identity_op.rs:43:5 | -42 | u & 255; +43 | u & 255; | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index a054ac6223d..0393e49a2ee 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -1,24 +1,24 @@ error: Unnecessary boolean `not` operation - --> $DIR/if_not_else.rs:19:5 + --> $DIR/if_not_else.rs:18:5 | -19 | / if !bla() { -20 | | println!("Bugs"); -21 | | } else { -22 | | println!("Bunny"); -23 | | } +18 | / if !bla() { +19 | | println!("Bugs"); +20 | | } else { +21 | | println!("Bunny"); +22 | | } | |_____^ | = note: `-D clippy::if-not-else` implied by `-D warnings` = help: remove the `!` and swap the blocks of the if/else error: Unnecessary `!=` operation - --> $DIR/if_not_else.rs:24:5 + --> $DIR/if_not_else.rs:23:5 | -24 | / if 4 != 5 { -25 | | println!("Bugs"); -26 | | } else { -27 | | println!("Bunny"); -28 | | } +23 | / if 4 != 5 { +24 | | println!("Bugs"); +25 | | } else { +26 | | println!("Bunny"); +27 | | } | |_____^ | = help: change to `==` and swap the blocks of the if/else diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index c24a96e8aa7..adad754bffe 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,34 +1,34 @@ error: Multiple implementations of this structure - --> $DIR/impl.rs:22:1 + --> $DIR/impl.rs:19:1 | -22 | / impl MyStruct { -23 | | fn second() {} -24 | | } +19 | / impl MyStruct { +20 | | fn second() {} +21 | | } | |_^ | = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` note: First implementation here - --> $DIR/impl.rs:18:1 + --> $DIR/impl.rs:15:1 | -18 | / impl MyStruct { -19 | | fn first() {} -20 | | } +15 | / impl MyStruct { +16 | | fn first() {} +17 | | } | |_^ error: Multiple implementations of this structure - --> $DIR/impl.rs:36:5 + --> $DIR/impl.rs:33:5 | -36 | / impl super::MyStruct { -37 | | fn third() {} -38 | | } +33 | / impl super::MyStruct { +34 | | fn third() {} +35 | | } | |_____^ | note: First implementation here - --> $DIR/impl.rs:18:1 + --> $DIR/impl.rs:15:1 | -18 | / impl MyStruct { -19 | | fn first() {} -20 | | } +15 | / impl MyStruct { +16 | | fn first() {} +17 | | } | |_^ error: aborting due to 2 previous errors diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index c561e0a3dfb..58b823e6ca1 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,136 +1,136 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:21:35 + --> $DIR/implicit_hasher.rs:20:35 | -21 | impl Foo for HashMap { +20 | impl Foo for HashMap { | ^^^^^^^^^^^^^ | = note: `-D clippy::implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -21 | impl Foo for HashMap { +20 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -27 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +26 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:30:36 + --> $DIR/implicit_hasher.rs:29:36 | -30 | impl Foo for (HashMap,) { +29 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ help: consider adding a type parameter | -30 | impl Foo for (HashMap,) { +29 | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -32 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) +31 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:35:19 + --> $DIR/implicit_hasher.rs:34:19 | -35 | impl Foo for HashMap { +34 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -35 | impl Foo for HashMap { +34 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -37 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +36 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:53:32 + --> $DIR/implicit_hasher.rs:51:32 | -53 | impl Foo for HashSet { +51 | impl Foo for HashSet { | ^^^^^^^^^^ help: consider adding a type parameter | -53 | impl Foo for HashSet { +51 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ help: ...and use generic constructor | -55 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +53 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:58:19 + --> $DIR/implicit_hasher.rs:56:19 | -58 | impl Foo for HashSet { +56 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ help: consider adding a type parameter | -58 | impl Foo for HashSet { +56 | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -60 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +58 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:75:23 + --> $DIR/implicit_hasher.rs:73:23 | -75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:75:53 + --> $DIR/implicit_hasher.rs:73:53 | -75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ help: consider adding a type parameter | -75 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) { +73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:80:43 + --> $DIR/implicit_hasher.rs:77:43 | -80 | impl Foo for HashMap { +77 | impl Foo for HashMap { | ^^^^^^^^^^^^^ ... -93 | gen!(impl); - | ----------- in this macro invocation +89 | gen!(impl ); + | ------------ in this macro invocation help: consider adding a type parameter | -80 | impl Foo for HashMap { +77 | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -82 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +79 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:88:33 + --> $DIR/implicit_hasher.rs:85:33 | -88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ ... -94 | gen!(fn bar); +90 | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:88:63 + --> $DIR/implicit_hasher.rs:85:63 | -88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ ... -94 | gen!(fn bar); +90 | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -88 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) { +85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 6f4fe12757a..26474aab4b8 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,51 +1,51 @@ error: missing return statement - --> $DIR/implicit_return.rs:21:5 + --> $DIR/implicit_return.rs:17:5 | -21 | true +17 | true | ^^^^ help: add `return` as shown: `return true` | = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing return statement - --> $DIR/implicit_return.rs:27:9 + --> $DIR/implicit_return.rs:23:9 | -27 | true +23 | true | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:29:9 + --> $DIR/implicit_return.rs:25:9 | -29 | false +25 | false | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:36:17 + --> $DIR/implicit_return.rs:32:17 | -36 | true => false, +32 | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:38:13 + --> $DIR/implicit_return.rs:33:18 | -38 | true - | ^^^^ help: add `return` as shown: `return true` +33 | false => true, + | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:46:9 + --> $DIR/implicit_return.rs:40:9 | -46 | break true; +40 | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:52:9 + --> $DIR/implicit_return.rs:45:16 | -52 | true - | ^^^^ help: add `return` as shown: `return true` +45 | let _ = || true; + | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:54:16 + --> $DIR/implicit_return.rs:46:16 | -54 | let _ = || true; +46 | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: aborting due to 8 previous errors diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index a417394629e..77e2f3bd41b 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,33 +1,33 @@ error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:17:16 + --> $DIR/inconsistent_digit_grouping.rs:22:16 | -17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:17:26 + --> $DIR/inconsistent_digit_grouping.rs:22:26 | -17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:17:38 + --> $DIR/inconsistent_digit_grouping.rs:22:38 | -17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:17:48 + --> $DIR/inconsistent_digit_grouping.rs:22:48 | -17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:17:64 + --> $DIR/inconsistent_digit_grouping.rs:22:64 | -17 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: aborting due to 5 previous errors diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 14e9627e573..c9a45bc4084 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,308 +1,308 @@ error: index out of bounds: the len is 4 but the index is 4 - --> $DIR/indexing_slicing.rs:28:5 + --> $DIR/indexing_slicing.rs:25:5 | -28 | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +25 | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ | = note: #[deny(const_err)] on by default error: index out of bounds: the len is 4 but the index is 8 - --> $DIR/indexing_slicing.rs:29:5 + --> $DIR/indexing_slicing.rs:26:5 | -29 | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +26 | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^^ error: index out of bounds: the len is 0 but the index is 0 - --> $DIR/indexing_slicing.rs:59:5 + --> $DIR/indexing_slicing.rs:56:5 | -59 | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +56 | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^ error: index out of bounds: the len is 4 but the index is 15 - --> $DIR/indexing_slicing.rs:90:5 + --> $DIR/indexing_slicing.rs:87:5 | -90 | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +87 | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:23:5 + --> $DIR/indexing_slicing.rs:20:5 | -23 | x[index]; +20 | x[index]; | ^^^^^^^^ | = note: `-D clippy::indexing-slicing` implied by `-D warnings` = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:24:6 + --> $DIR/indexing_slicing.rs:21:6 | -24 | &x[index..]; +21 | &x[index..]; | ^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:25:6 + --> $DIR/indexing_slicing.rs:22:6 | -25 | &x[..index]; +22 | &x[..index]; | ^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:26:6 + --> $DIR/indexing_slicing.rs:23:6 | -26 | &x[index_from..index_to]; +23 | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:27:6 + --> $DIR/indexing_slicing.rs:24:6 | -27 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +24 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:27:6 + --> $DIR/indexing_slicing.rs:24:6 | -27 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +24 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:30:11 + --> $DIR/indexing_slicing.rs:27:11 | -30 | &x[..=4]; +27 | &x[..=4]; | ^ | = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds - --> $DIR/indexing_slicing.rs:31:11 + --> $DIR/indexing_slicing.rs:28:11 | -31 | &x[1..5]; +28 | &x[1..5]; | ^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:32:6 + --> $DIR/indexing_slicing.rs:29:6 | -32 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +29 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:32:8 + --> $DIR/indexing_slicing.rs:29:8 | -32 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +29 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:33:8 + --> $DIR/indexing_slicing.rs:30:8 | -33 | &x[5..]; +30 | &x[5..]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:34:10 + --> $DIR/indexing_slicing.rs:31:10 | -34 | &x[..5]; +31 | &x[..5]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:35:8 + --> $DIR/indexing_slicing.rs:32:8 | -35 | &x[5..].iter().map(|x| 2 * x).collect::>(); +32 | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:36:12 + --> $DIR/indexing_slicing.rs:33:12 | -36 | &x[0..=4]; +33 | &x[0..=4]; | ^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:37:6 + --> $DIR/indexing_slicing.rs:34:6 | -37 | &x[0..][..3]; +34 | &x[0..][..3]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:38:6 + --> $DIR/indexing_slicing.rs:35:6 | -38 | &x[1..][..5]; +35 | &x[1..][..5]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:51:5 + --> $DIR/indexing_slicing.rs:48:5 | -51 | y[0]; +48 | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:52:6 + --> $DIR/indexing_slicing.rs:49:6 | -52 | &y[1..2]; +49 | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:53:6 + --> $DIR/indexing_slicing.rs:50:6 | -53 | &y[0..=4]; +50 | &y[0..=4]; | ^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:54:6 + --> $DIR/indexing_slicing.rs:51:6 | -54 | &y[..=4]; +51 | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:60:12 + --> $DIR/indexing_slicing.rs:57:12 | -60 | &empty[1..5]; +57 | &empty[1..5]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:61:16 + --> $DIR/indexing_slicing.rs:58:16 | -61 | &empty[0..=4]; +58 | &empty[0..=4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:62:15 + --> $DIR/indexing_slicing.rs:59:15 | -62 | &empty[..=4]; +59 | &empty[..=4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:63:12 + --> $DIR/indexing_slicing.rs:60:12 | -63 | &empty[1..]; +60 | &empty[1..]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:64:14 + --> $DIR/indexing_slicing.rs:61:14 | -64 | &empty[..4]; +61 | &empty[..4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:65:16 + --> $DIR/indexing_slicing.rs:62:16 | -65 | &empty[0..=0]; +62 | &empty[0..=0]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:66:15 + --> $DIR/indexing_slicing.rs:63:15 | -66 | &empty[..=0]; +63 | &empty[..=0]; | ^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:74:5 + --> $DIR/indexing_slicing.rs:71:5 | -74 | v[0]; +71 | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:75:5 + --> $DIR/indexing_slicing.rs:72:5 | -75 | v[10]; +72 | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:76:5 + --> $DIR/indexing_slicing.rs:73:5 | -76 | v[1 << 3]; +73 | v[1 << 3]; | ^^^^^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:77:6 + --> $DIR/indexing_slicing.rs:74:6 | -77 | &v[10..100]; +74 | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:78:6 + --> $DIR/indexing_slicing.rs:75:6 | -78 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +75 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:78:8 + --> $DIR/indexing_slicing.rs:75:8 | -78 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +75 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:79:6 + --> $DIR/indexing_slicing.rs:76:6 | -79 | &v[10..]; +76 | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:80:6 + --> $DIR/indexing_slicing.rs:77:6 | -80 | &v[..100]; +77 | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:92:5 + --> $DIR/indexing_slicing.rs:89:5 | -92 | v[N]; +89 | v[N]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:93:5 + --> $DIR/indexing_slicing.rs:90:5 | -93 | v[M]; +90 | v[M]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:97:13 + --> $DIR/indexing_slicing.rs:94:13 | -97 | &x[num..10]; // should trigger out of bounds error +94 | &x[num..10]; // should trigger out of bounds error | ^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:98:8 + --> $DIR/indexing_slicing.rs:95:8 | -98 | &x[10..num]; // should trigger out of bounds error +95 | &x[10..num]; // should trigger out of bounds error | ^^ error: aborting due to 43 previous errors diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index bce83b91242..62588a2ad7c 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,27 +1,27 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:28:5 + --> $DIR/infallible_destructuring_match.rs:25:5 | -28 | / let data = match wrapper { -29 | | SingleVariantEnum::Variant(i) => i, -30 | | }; +25 | / let data = match wrapper { +26 | | SingleVariantEnum::Variant(i) => i, +27 | | }; | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` | = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:49:5 + --> $DIR/infallible_destructuring_match.rs:46:5 | -49 | / let data = match wrapper { -50 | | TupleStruct(i) => i, -51 | | }; +46 | / let data = match wrapper { +47 | | TupleStruct(i) => i, +48 | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:70:5 + --> $DIR/infallible_destructuring_match.rs:67:5 | -70 | / let data = match wrapper { -71 | | Ok(i) => i, -72 | | }; +67 | / let data = match wrapper { +68 | | Ok(i) => i, +69 | | }; | |______^ help: try this: `let Ok(data) = wrapper;` error: aborting due to 3 previous errors diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 5b783c2b8b9..2c3b05aaff3 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,99 +1,108 @@ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/infinite_iter.rs:20:5 + --> $DIR/infinite_iter.rs:19:5 | -20 | repeat(0_u8).collect::>(); // infinite iter +19 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` error: infinite iteration detected - --> $DIR/infinite_iter.rs:20:5 + --> $DIR/infinite_iter.rs:19:5 | -20 | repeat(0_u8).collect::>(); // infinite iter +19 | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:18:8 + --> $DIR/infinite_iter.rs:17:8 | -18 | #[deny(clippy::infinite_iter)] +17 | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:21:5 + --> $DIR/infinite_iter.rs:20:5 | -21 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter +20 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:22:5 + --> $DIR/infinite_iter.rs:21:5 | -22 | (0..8_u64).chain(0..).max(); // infinite iter +21 | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:24:5 + --> $DIR/infinite_iter.rs:26:5 | -24 | (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +26 | / (0..8_u32) +27 | | .rev() +28 | | .cycle() +29 | | .map(|x| x + 1_u32) +30 | | .for_each(|x| println!("{}", x)); // infinite iter + | |________________________________________^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:26:5 + --> $DIR/infinite_iter.rs:32:5 | -26 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter +32 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:27:5 + --> $DIR/infinite_iter.rs:33:5 | -27 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter +33 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:34:5 + --> $DIR/infinite_iter.rs:40:5 | -34 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter +40 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:32:8 + --> $DIR/infinite_iter.rs:38:8 | -32 | #[deny(clippy::maybe_infinite_iter)] +38 | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:35:5 + --> $DIR/infinite_iter.rs:41:5 | -35 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter +41 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:36:5 - | -36 | (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/infinite_iter.rs:42:5 + | +42 | / (1..) +43 | | .scan(0, |state, x| { +44 | | *state += x; +45 | | Some(*state) +46 | | }) +47 | | .min(); // maybe infinite iter + | |______________^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:37:5 + --> $DIR/infinite_iter.rs:48:5 | -37 | (0..).find(|x| *x == 24); // maybe infinite iter +48 | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:38:5 + --> $DIR/infinite_iter.rs:49:5 | -38 | (0..).position(|x| x == 24); // maybe infinite iter +49 | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:39:5 + --> $DIR/infinite_iter.rs:50:5 | -39 | (0..).any(|x| x == 24); // maybe infinite iter +50 | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:40:5 + --> $DIR/infinite_iter.rs:51:5 | -40 | (0..).all(|x| x == 24); // maybe infinite iter +51 | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index fdbdd13fd8f..de7851519ec 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,57 +1,57 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:26:11 + --> $DIR/infinite_loop.rs:32:11 | -26 | while y < 10 { +32 | while y < 10 { | ^^^^^^ | = note: #[deny(clippy::while_immutable_condition)] on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:31:11 + --> $DIR/infinite_loop.rs:37:11 | -31 | while y < 10 && x < 3 { +37 | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:38:11 + --> $DIR/infinite_loop.rs:44:11 | -38 | while !cond { +44 | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:82:11 + --> $DIR/infinite_loop.rs:88:11 | -82 | while i < 3 { +88 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:87:11 + --> $DIR/infinite_loop.rs:93:11 | -87 | while i < 3 && j > 0 { +93 | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:91:11 + --> $DIR/infinite_loop.rs:97:11 | -91 | while i < 3 { +97 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:106:11 + --> $DIR/infinite_loop.rs:112:11 | -106 | while i < 3 { +112 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:111:11 + --> $DIR/infinite_loop.rs:117:11 | -111 | while i < 3 { +117 | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:174:15 + --> $DIR/infinite_loop.rs:183:15 | -174 | while self.count < n { +183 | while self.count < n { | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 112fad812e5..0eaee7c7b25 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,25 +1,27 @@ error: use of `#[inline]` on trait method `default_inline` which has no body - --> $DIR/inline_fn_without_body.rs:18:5 + --> $DIR/inline_fn_without_body.rs:14:5 | -18 | #[inline] +14 | #[inline] | _____-^^^^^^^^ -19 | | fn default_inline(); +15 | | fn default_inline(); | |____- help: remove | = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body - --> $DIR/inline_fn_without_body.rs:21:5 + --> $DIR/inline_fn_without_body.rs:17:5 | -21 | #[inline(always)]fn always_inline(); - | ^^^^^^^^^^^^^^^^^ help: remove +17 | #[inline(always)] + | _____-^^^^^^^^^^^^^^^^ +18 | | fn always_inline(); + | |____- help: remove error: use of `#[inline]` on trait method `never_inline` which has no body - --> $DIR/inline_fn_without_body.rs:23:5 + --> $DIR/inline_fn_without_body.rs:20:5 | -23 | #[inline(never)] +20 | #[inline(never)] | _____-^^^^^^^^^^^^^^^ -24 | | fn never_inline(); +21 | | fn never_inline(); | |____- help: remove error: aborting due to 3 previous errors diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 5612b203290..4a81e911157 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,43 +1,43 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:20:5 + --> $DIR/int_plus_one.rs:16:5 | -20 | x >= y + 1; +16 | x >= y + 1; | ^^^^^^^^^^ | = note: `-D clippy::int-plus-one` implied by `-D warnings` help: change `>= y + 1` to `> y` as shown | -20 | x > y; +16 | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:21:5 + --> $DIR/int_plus_one.rs:17:5 | -21 | y + 1 <= x; +17 | y + 1 <= x; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -21 | y < x; +17 | y < x; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:23:5 + --> $DIR/int_plus_one.rs:19:5 | -23 | x - 1 >= y; +19 | x - 1 >= y; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -23 | x > y; +19 | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:24:5 + --> $DIR/int_plus_one.rs:20:5 | -24 | y <= x - 1; +20 | y <= x - 1; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -24 | y < x; +20 | y < x; | ^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 39055423048..f6d6fe35d7f 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,8 +1,8 @@ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:11:22 + --> $DIR/into_iter_on_ref.rs:11:24 | -11 | for _ in [1,2,3].into_iter() {} //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +11 | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` | note: lint level defined here --> $DIR/into_iter_on_ref.rs:2:9 @@ -11,24 +11,24 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:13:21 + --> $DIR/into_iter_on_ref.rs:13:23 | -13 | let _ = [1,2,3].into_iter(); //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +13 | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the Vec - --> $DIR/into_iter_on_ref.rs:15:28 + --> $DIR/into_iter_on_ref.rs:15:30 | -15 | let _ = (&vec![1,2,3]).into_iter(); //~ WARN equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +15 | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` | = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` error: this .into_iter() call is equivalent to .iter() and will not move the slice - --> $DIR/into_iter_on_ref.rs:16:44 + --> $DIR/into_iter_on_ref.rs:16:46 | -16 | let _ = vec![1,2,3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +16 | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the slice --> $DIR/into_iter_on_ref.rs:17:41 @@ -43,22 +43,22 @@ error: this .into_iter() call is equivalent to .iter() and will not move the sli | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:20:30 + --> $DIR/into_iter_on_ref.rs:20:32 | -20 | let _ = (&&&&&&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +20 | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:21:34 + --> $DIR/into_iter_on_ref.rs:21:36 | -21 | let _ = (&&&&mut &&&[1,2,3]).into_iter(); //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +21 | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the array - --> $DIR/into_iter_on_ref.rs:22:38 + --> $DIR/into_iter_on_ref.rs:22:40 | -22 | let _ = (&mut &mut &mut [1,2,3]).into_iter(); //~ ERROR equivalent to .iter_mut() - | ^^^^^^^^^ help: call directly: `iter_mut` +22 | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() + | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Option --> $DIR/into_iter_on_ref.rs:24:24 diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 52868e908ca..a5142596aeb 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,48 +1,48 @@ error: reference to zeroed memory - --> $DIR/invalid_ref.rs:37:24 + --> $DIR/invalid_ref.rs:33:24 | -37 | let ref_zero: &T = std::mem::zeroed(); // warning +33 | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | = note: #[deny(clippy::invalid_ref)] on by default = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:41:24 + --> $DIR/invalid_ref.rs:37:24 | -41 | let ref_zero: &T = core::mem::zeroed(); // warning +37 | let ref_zero: &T = core::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:45:24 + --> $DIR/invalid_ref.rs:41:24 | -45 | let ref_zero: &T = std::intrinsics::init(); // warning +41 | let ref_zero: &T = std::intrinsics::init(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:49:26 + --> $DIR/invalid_ref.rs:45:26 | -49 | let ref_uninit: &T = std::mem::uninitialized(); // warning +45 | let ref_uninit: &T = std::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:53:26 + --> $DIR/invalid_ref.rs:49:26 | -53 | let ref_uninit: &T = core::mem::uninitialized(); // warning +49 | let ref_uninit: &T = core::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:57:26 + --> $DIR/invalid_ref.rs:53:26 | -57 | let ref_uninit: &T = std::intrinsics::uninit(); // warning +53 | let ref_uninit: &T = std::intrinsics::uninit(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index e41132dfc8b..2ac4a48b862 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -1,165 +1,165 @@ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:26:5 + --> $DIR/invalid_upcast_comparisons.rs:30:5 | -26 | (u8 as u32) > 300; +30 | (u8 as u32) > 300; | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:27:5 + --> $DIR/invalid_upcast_comparisons.rs:31:5 | -27 | (u8 as i32) > 300; +31 | (u8 as i32) > 300; | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:28:5 + --> $DIR/invalid_upcast_comparisons.rs:32:5 | -28 | (u8 as u32) == 300; +32 | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:29:5 + --> $DIR/invalid_upcast_comparisons.rs:33:5 | -29 | (u8 as i32) == 300; +33 | (u8 as i32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:30:5 + --> $DIR/invalid_upcast_comparisons.rs:34:5 | -30 | 300 < (u8 as u32); +34 | 300 < (u8 as u32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:31:5 + --> $DIR/invalid_upcast_comparisons.rs:35:5 | -31 | 300 < (u8 as i32); +35 | 300 < (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:32:5 + --> $DIR/invalid_upcast_comparisons.rs:36:5 | -32 | 300 == (u8 as u32); +36 | 300 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:33:5 + --> $DIR/invalid_upcast_comparisons.rs:37:5 | -33 | 300 == (u8 as i32); +37 | 300 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:35:5 + --> $DIR/invalid_upcast_comparisons.rs:39:5 | -35 | (u8 as u32) <= 300; +39 | (u8 as u32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:36:5 + --> $DIR/invalid_upcast_comparisons.rs:40:5 | -36 | (u8 as i32) <= 300; +40 | (u8 as i32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:37:5 + --> $DIR/invalid_upcast_comparisons.rs:41:5 | -37 | (u8 as u32) != 300; +41 | (u8 as u32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:38:5 + --> $DIR/invalid_upcast_comparisons.rs:42:5 | -38 | (u8 as i32) != 300; +42 | (u8 as i32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:39:5 + --> $DIR/invalid_upcast_comparisons.rs:43:5 | -39 | 300 >= (u8 as u32); +43 | 300 >= (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:40:5 + --> $DIR/invalid_upcast_comparisons.rs:44:5 | -40 | 300 >= (u8 as i32); +44 | 300 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:41:5 + --> $DIR/invalid_upcast_comparisons.rs:45:5 | -41 | 300 != (u8 as u32); +45 | 300 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:42:5 + --> $DIR/invalid_upcast_comparisons.rs:46:5 | -42 | 300 != (u8 as i32); +46 | 300 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:45:5 + --> $DIR/invalid_upcast_comparisons.rs:49:5 | -45 | (u8 as i32) < 0; +49 | (u8 as i32) < 0; | ^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:46:5 + --> $DIR/invalid_upcast_comparisons.rs:50:5 | -46 | -5 != (u8 as i32); +50 | -5 != (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:48:5 + --> $DIR/invalid_upcast_comparisons.rs:52:5 | -48 | (u8 as i32) >= 0; +52 | (u8 as i32) >= 0; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:49:5 + --> $DIR/invalid_upcast_comparisons.rs:53:5 | -49 | -5 == (u8 as i32); +53 | -5 == (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:52:5 + --> $DIR/invalid_upcast_comparisons.rs:56:5 | -52 | 1337 == (u8 as i32); +56 | 1337 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:53:5 + --> $DIR/invalid_upcast_comparisons.rs:57:5 | -53 | 1337 == (u8 as u32); +57 | 1337 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:55:5 + --> $DIR/invalid_upcast_comparisons.rs:59:5 | -55 | 1337 != (u8 as i32); +59 | 1337 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:56:5 + --> $DIR/invalid_upcast_comparisons.rs:60:5 | -56 | 1337 != (u8 as u32); +60 | 1337 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:71:5 + --> $DIR/invalid_upcast_comparisons.rs:74:5 | -71 | (u8 as i32) > -1; +74 | (u8 as i32) > -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:72:5 + --> $DIR/invalid_upcast_comparisons.rs:75:5 | -72 | (u8 as i32) < -1; +75 | (u8 as i32) < -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:88:5 + --> $DIR/invalid_upcast_comparisons.rs:91:5 | -88 | -5 >= (u8 as i32); +91 | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: aborting due to 27 previous errors diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index 2086f11463f..6f9f88a8d67 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,7 +1,7 @@ error: expected token: `,` - --> $DIR/issue-3145.rs:12:19 + --> $DIR/issue-3145.rs:11:19 | -12 | println!("{}" a); //~ERROR expected token: `,` +11 | println!("{}" a); //~ERROR expected token: `,` | ^ error: aborting due to previous error diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr index 291e64bec6f..28b67cbc9fa 100644 --- a/tests/ui/issue_2356.stderr +++ b/tests/ui/issue_2356.stderr @@ -1,13 +1,13 @@ error: this loop could be written as a `for` loop - --> $DIR/issue_2356.rs:27:29 + --> $DIR/issue_2356.rs:24:29 | -27 | while let Some(e) = it.next() { +24 | while let Some(e) = it.next() { | ^^^^^^^^^ help: try: `for e in it { .. }` | note: lint level defined here - --> $DIR/issue_2356.rs:13:9 + --> $DIR/issue_2356.rs:10:9 | -13 | #![deny(clippy::while_let_on_iterator)] +10 | #![deny(clippy::while_let_on_iterator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index 15c0cc3af4c..c988fca3827 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -1,16 +1,20 @@ error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:22:5 + --> $DIR/item_after_statement.rs:21:5 | -22 | fn foo() { println!("foo"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +21 | / fn foo() { +22 | | println!("foo"); +23 | | } + | |_____^ | = note: `-D clippy::items-after-statements` implied by `-D warnings` error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:27:5 + --> $DIR/item_after_statement.rs:28:5 | -27 | fn foo() { println!("foo"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +28 | / fn foo() { +29 | | println!("foo"); +30 | | } + | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index c38abb8887c..47587f5423a 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -1,40 +1,40 @@ error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:16 + --> $DIR/large_digit_groups.rs:24:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` +24 | 0b1_10110_i64, + | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:31 + --> $DIR/large_digit_groups.rs:25:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` +25 | 0x1_23456_78901_usize, + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:54 + --> $DIR/large_digit_groups.rs:26:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^ help: consider: `123_456_f32` +26 | 1_23456_f32, + | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:67 + --> $DIR/large_digit_groups.rs:27:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` +27 | 1_23456.12_f32, + | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:83 + --> $DIR/large_digit_groups.rs:28:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` +28 | 1_23456.12345_f32, + | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:102 + --> $DIR/large_digit_groups.rs:29:9 | -17 | let bad = (0b1_10110_i64, 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f32, 1_23456.12345_6_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` +29 | 1_23456.12345_6_f32, + | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` error: aborting due to 6 previous errors diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 4bb25dd855a..c9c46ced5e2 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -1,69 +1,69 @@ error: large size difference between variants - --> $DIR/large_enum_variant.rs:20:5 + --> $DIR/large_enum_variant.rs:16:5 | -20 | B([i32; 8000]), +16 | B([i32; 8000]), | ^^^^^^^^^^^^^^ | = note: `-D clippy::large-enum-variant` implied by `-D warnings` help: consider boxing the large fields to reduce the total size of the enum | -20 | B(Box<[i32; 8000]>), +16 | B(Box<[i32; 8000]>), | ^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:31:5 + --> $DIR/large_enum_variant.rs:27:5 | -31 | C(T, [i32; 8000]), +27 | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:31:5 + --> $DIR/large_enum_variant.rs:27:5 | -31 | C(T, [i32; 8000]), +27 | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:44:5 + --> $DIR/large_enum_variant.rs:40:5 | -44 | ContainingLargeEnum(LargeEnum), +40 | ContainingLargeEnum(LargeEnum), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -44 | ContainingLargeEnum(Box), +40 | ContainingLargeEnum(Box), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:47:5 + --> $DIR/large_enum_variant.rs:43:5 | -47 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +43 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:47:5 + --> $DIR/large_enum_variant.rs:43:5 | -47 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +43 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:54:5 + --> $DIR/large_enum_variant.rs:50:5 | -54 | StructLikeLarge { x: [i32; 8000], y: i32 }, +50 | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:54:5 + --> $DIR/large_enum_variant.rs:50:5 | -54 | StructLikeLarge { x: [i32; 8000], y: i32 }, +50 | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:59:5 + --> $DIR/large_enum_variant.rs:55:5 | -59 | StructLikeLarge2 { x: [i32; 8000] }, +55 | StructLikeLarge2 { x: [i32; 8000] }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -59 | StructLikeLarge2 { x: Box<[i32; 8000]> }, +55 | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 1f937bafdef..bc5cd0e595b 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,139 +1,139 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:18:1 + --> $DIR/len_zero.rs:15:1 | -18 | / impl PubOne { -19 | | pub fn len(self: &Self) -> isize { -20 | | 1 -21 | | } -22 | | } +15 | / impl PubOne { +16 | | pub fn len(self: &Self) -> isize { +17 | | 1 +18 | | } +19 | | } | |_^ | = note: `-D clippy::len-without-is-empty` implied by `-D warnings` error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:67:1 + --> $DIR/len_zero.rs:64:1 | -67 | / pub trait PubTraitsToo { -68 | | fn len(self: &Self) -> isize; -69 | | } +64 | / pub trait PubTraitsToo { +65 | | fn len(self: &Self) -> isize; +66 | | } | |_^ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:101:1 + --> $DIR/len_zero.rs:98:1 | -101 | / impl HasIsEmpty { -102 | | pub fn len(self: &Self) -> isize { -103 | | 1 -104 | | } +98 | / impl HasIsEmpty { +99 | | pub fn len(self: &Self) -> isize { +100 | | 1 +101 | | } ... | -108 | | } -109 | | } +105 | | } +106 | | } | |_^ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:130:1 + --> $DIR/len_zero.rs:127:1 | -130 | / impl HasWrongIsEmpty { -131 | | pub fn len(self: &Self) -> isize { -132 | | 1 -133 | | } +127 | / impl HasWrongIsEmpty { +128 | | pub fn len(self: &Self) -> isize { +129 | | 1 +130 | | } ... | -137 | | } -138 | | } +134 | | } +135 | | } | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:151:8 + --> $DIR/len_zero.rs:148:8 | -151 | if x.len() == 0 { +148 | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` | = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:155:8 + --> $DIR/len_zero.rs:152:8 | -155 | if "".len() == 0 {} +152 | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:170:8 + --> $DIR/len_zero.rs:167:8 | -170 | if has_is_empty.len() == 0 { +167 | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:173:8 + --> $DIR/len_zero.rs:170:8 | -173 | if has_is_empty.len() != 0 { +170 | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:176:8 + --> $DIR/len_zero.rs:173:8 | -176 | if has_is_empty.len() > 0 { +173 | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:179:8 + --> $DIR/len_zero.rs:176:8 | -179 | if has_is_empty.len() < 1 { +176 | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:182:8 + --> $DIR/len_zero.rs:179:8 | -182 | if has_is_empty.len() >= 1 { +179 | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:193:8 + --> $DIR/len_zero.rs:190:8 | -193 | if 0 == has_is_empty.len() { +190 | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:196:8 + --> $DIR/len_zero.rs:193:8 | -196 | if 0 != has_is_empty.len() { +193 | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:199:8 + --> $DIR/len_zero.rs:196:8 | -199 | if 0 < has_is_empty.len() { +196 | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:202:8 + --> $DIR/len_zero.rs:199:8 | -202 | if 1 <= has_is_empty.len() { +199 | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:205:8 + --> $DIR/len_zero.rs:202:8 | -205 | if 1 > has_is_empty.len() { +202 | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:219:8 + --> $DIR/len_zero.rs:216:8 | -219 | if with_is_empty.len() == 0 { +216 | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:232:8 + --> $DIR/len_zero.rs:229:8 | -232 | if b.len() != 0 {} +229 | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:238:1 + --> $DIR/len_zero.rs:235:1 | -238 | / pub trait DependsOnFoo: Foo { -239 | | fn len(&mut self) -> usize; -240 | | } +235 | / pub trait DependsOnFoo: Foo { +236 | | fn len(&mut self) -> usize; +237 | | } | |_^ error: aborting due to 19 previous errors diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 6e2ec6d4aaa..91acf6dcb30 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,47 +1,47 @@ error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:67:5 + --> $DIR/let_if_seq.rs:72:5 | -67 | / let mut foo = 0; -68 | | if f() { -69 | | foo = 42; -70 | | } +72 | / let mut foo = 0; +73 | | if f() { +74 | | foo = 42; +75 | | } | |_____^ help: it is more idiomatic to write: `let foo = if f() { 42 } else { 0 };` | = note: `-D clippy::useless-let-if-seq` implied by `-D warnings` = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:72:5 + --> $DIR/let_if_seq.rs:77:5 | -72 | / let mut bar = 0; -73 | | if f() { -74 | | f(); -75 | | bar = 42; -... | -78 | | f(); -79 | | } +77 | / let mut bar = 0; +78 | | if f() { +79 | | f(); +80 | | bar = 42; +81 | | } else { +82 | | f(); +83 | | } | |_____^ help: it is more idiomatic to write: `let bar = if f() { ..; 42 } else { ..; 0 };` | = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:81:5 + --> $DIR/let_if_seq.rs:85:5 | -81 | / let quz; -82 | | if f() { -83 | | quz = 42; -84 | | } else { -85 | | quz = 0; -86 | | } +85 | / let quz; +86 | | if f() { +87 | | quz = 42; +88 | | } else { +89 | | quz = 0; +90 | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:110:5 + --> $DIR/let_if_seq.rs:114:5 | -110 | / let mut baz = 0; -111 | | if f() { -112 | | baz = 42; -113 | | } +114 | / let mut baz = 0; +115 | | if f() { +116 | | baz = 42; +117 | | } | |_____^ help: it is more idiomatic to write: `let baz = if f() { 42 } else { 0 };` | = note: you might not need `mut` at all diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index cdd4b6bd537..894c15c2d6d 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -1,26 +1,26 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:20:5 + --> $DIR/let_return.rs:16:5 | -20 | x +16 | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/let_return.rs:19:13 + --> $DIR/let_return.rs:15:13 | -19 | let x = 5; +15 | let x = 5; | ^ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:26:9 + --> $DIR/let_return.rs:22:9 | -26 | x +22 | x | ^ | note: this expression can be directly returned - --> $DIR/let_return.rs:25:17 + --> $DIR/let_return.rs:21:17 | -25 | let x = 5; +21 | let x = 5; | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index e8c7bb37e73..a8771dd5f47 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -1,15 +1,15 @@ error: this let-binding has unit value. Consider omitting `let _x =` - --> $DIR/let_unit.rs:24:5 + --> $DIR/let_unit.rs:20:5 | -24 | let _x = println!("x"); +20 | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::let-unit-value` implied by `-D warnings` error: this let-binding has unit value. Consider omitting `let _a =` - --> $DIR/let_unit.rs:28:9 + --> $DIR/let_unit.rs:24:9 | -28 | let _a = (); +24 | let _a = (); | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 46dbf6cce09..5bddf5aa746 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -1,96 +1,122 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:17:1 + --> $DIR/lifetimes.rs:13:1 | -17 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +13 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:19:1 + --> $DIR/lifetimes.rs:15:1 | -19 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +15 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:27:1 + --> $DIR/lifetimes.rs:23:1 | -27 | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +23 | / fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { +24 | | x +25 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:39:1 + --> $DIR/lifetimes.rs:47:1 | -39 | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +47 | / fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { +48 | | Ok(x) +49 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:42:1 + --> $DIR/lifetimes.rs:52:1 | -42 | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> where T: Copy { Ok(x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +52 | / fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> +53 | | where +54 | | T: Copy, +55 | | { +56 | | Ok(x) +57 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:48:1 + --> $DIR/lifetimes.rs:63:1 | -48 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +63 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:62:1 + --> $DIR/lifetimes.rs:84:1 | -62 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -63 | | where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I> -64 | | { unreachable!() } - | |__________________^ +84 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +85 | | where +86 | | for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, +87 | | { +88 | | unreachable!() +89 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:87:5 - | -87 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/lifetimes.rs:117:5 + | +117 | / fn self_and_out<'s>(&'s self) -> &'s u8 { +118 | | &self.x +119 | | } + | |_____^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:91:5 - | -91 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/lifetimes.rs:125:5 + | +125 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:107:1 + --> $DIR/lifetimes.rs:141:1 | -107 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +141 | / fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { +142 | | unimplemented!() +143 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:127:1 + --> $DIR/lifetimes.rs:171:1 | -127 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +171 | / fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { +172 | | unimplemented!() +173 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:131:1 + --> $DIR/lifetimes.rs:177:1 | -131 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +177 | / fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { +178 | | unimplemented!() +179 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:142:1 + --> $DIR/lifetimes.rs:196:1 | -142 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +196 | / fn named_input_elided_output<'a>(_arg: &'a str) -> &str { +197 | | unimplemented!() +198 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:146:1 + --> $DIR/lifetimes.rs:204:1 | -146 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +204 | / fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { +205 | | unimplemented!() +206 | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:176:1 + --> $DIR/lifetimes.rs:241:1 | -176 | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +241 | / fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { +242 | | unimplemented!() +243 | | } + | |_^ error: aborting due to 15 previous errors diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr index 65d1283a6e3..d0d65df21f0 100644 --- a/tests/ui/lint_without_lint_pass.stderr +++ b/tests/ui/lint_without_lint_pass.stderr @@ -1,11 +1,11 @@ error: the lint `TEST_LINT` is not added to any `LintPass` - --> $DIR/lint_without_lint_pass.rs:12:1 + --> $DIR/lint_without_lint_pass.rs:11:1 | -12 | / declare_clippy_lint! { -13 | | pub TEST_LINT, -14 | | correctness, -15 | | "" -16 | | } +11 | / declare_clippy_lint! { +12 | | pub TEST_LINT, +13 | | correctness, +14 | | "" +15 | | } | |_^ | note: lint level defined here diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 50856f6a937..603819de16e 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,21 +1,21 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:16:22 + --> $DIR/map_clone.rs:14:22 | -16 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); +14 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` | = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:17:26 + --> $DIR/map_clone.rs:15:26 | -17 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); +15 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:18:23 + --> $DIR/map_clone.rs:16:23 | -18 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); +16 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` error: aborting due to 3 previous errors diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index d41e6297758..488797173f6 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,7 +1,7 @@ error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` - --> $DIR/map_flatten.rs:16:21 + --> $DIR/map_flatten.rs:14:21 | -16 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); +14 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` | = note: `-D clippy::map-flatten` implied by `-D warnings` diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 9bef0d823e2..a073f995498 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -1,74 +1,109 @@ error: this boolean expression can be simplified - --> $DIR/match_bool.rs:35:11 + --> $DIR/match_bool.rs:38:11 | -35 | match test && test { +38 | match test && test { | ^^^^^^^^^^^^ help: try: `test` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:14:5 + --> $DIR/match_bool.rs:13:5 | -14 | / match test { -15 | | true => 0, -16 | | false => 42, -17 | | }; +13 | / match test { +14 | | true => 0, +15 | | false => 42, +16 | | }; | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` | = note: `-D clippy::match-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:20:5 + --> $DIR/match_bool.rs:19:5 | -20 | / match option == 1 { -21 | | true => 1, -22 | | false => 0, -23 | | }; +19 | / match option == 1 { +20 | | true => 1, +21 | | false => 0, +22 | | }; | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:25:5 + --> $DIR/match_bool.rs:24:5 + | +24 | / match test { +25 | | true => (), +26 | | false => { +27 | | println!("Noooo!"); +28 | | }, +29 | | }; + | |_____^ +help: consider using an if/else expression + | +24 | if !test { +25 | println!("Noooo!"); +26 | }; | -25 | / match test { -26 | | true => (), -27 | | false => { println!("Noooo!"); } -28 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:30:5 + --> $DIR/match_bool.rs:31:5 + | +31 | / match test { +32 | | false => { +33 | | println!("Noooo!"); +34 | | }, +35 | | _ => (), +36 | | }; + | |_____^ +help: consider using an if/else expression + | +31 | if !test { +32 | println!("Noooo!"); +33 | }; | -30 | / match test { -31 | | false => { println!("Noooo!"); } -32 | | _ => (), -33 | | }; - | |_____^ help: consider using an if/else expression: `if !test { println!("Noooo!"); }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:35:5 + --> $DIR/match_bool.rs:38:5 + | +38 | / match test && test { +39 | | false => { +40 | | println!("Noooo!"); +41 | | }, +42 | | _ => (), +43 | | }; + | |_____^ +help: consider using an if/else expression + | +38 | if !(test && test) { +39 | println!("Noooo!"); +40 | }; | -35 | / match test && test { -36 | | false => { println!("Noooo!"); } -37 | | _ => (), -38 | | }; - | |_____^ help: consider using an if/else expression: `if !(test && test) { println!("Noooo!"); }` error: equal expressions as operands to `&&` - --> $DIR/match_bool.rs:35:11 + --> $DIR/match_bool.rs:38:11 | -35 | match test && test { +38 | match test && test { | ^^^^^^^^^^^^ | = note: #[deny(clippy::eq_op)] on by default error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:40:5 + --> $DIR/match_bool.rs:45:5 + | +45 | / match test { +46 | | false => { +47 | | println!("Noooo!"); +48 | | }, +... | +51 | | }, +52 | | }; + | |_____^ +help: consider using an if/else expression + | +45 | if test { +46 | println!("Yes!"); +47 | } else { +48 | println!("Noooo!"); +49 | }; | -40 | / match test { -41 | | false => { println!("Noooo!"); } -42 | | true => { println!("Yes!"); } -43 | | }; - | |_____^ help: consider using an if/else expression: `if test { println!("Yes!"); } else { println!("Noooo!"); }` error: aborting due to 8 previous errors diff --git a/tests/ui/match_overlapping_arm.stderr b/tests/ui/match_overlapping_arm.stderr index 4f9d8ac7683..ef8fc08f95b 100644 --- a/tests/ui/match_overlapping_arm.stderr +++ b/tests/ui/match_overlapping_arm.stderr @@ -1,33 +1,33 @@ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:20:9 | -20 | 0 ... 10 => println!("0 ... 10"), - | ^^^^^^^^ +20 | 0...10 => println!("0 ... 10"), + | ^^^^^^ | = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this --> $DIR/match_overlapping_arm.rs:21:9 | -21 | 0 ... 11 => println!("0 ... 11"), - | ^^^^^^^^ +21 | 0...11 => println!("0 ... 11"), + | ^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:26:9 | -26 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ +26 | 0...5 => println!("0 ... 5"), + | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:28:9 | -28 | FOO ... 11 => println!("0 ... 11"), - | ^^^^^^^^^^ +28 | FOO...11 => println!("0 ... 11"), + | ^^^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:34:9 | -34 | 0 ... 5 => println!("0 ... 5"), - | ^^^^^^^ +34 | 0...5 => println!("0 ... 5"), + | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:33:9 @@ -38,8 +38,8 @@ note: overlaps with this error: some ranges overlap --> $DIR/match_overlapping_arm.rs:40:9 | -40 | 0 ... 2 => println!("0 ... 2"), - | ^^^^^^^ +40 | 0...2 => println!("0 ... 2"), + | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:39:9 @@ -50,14 +50,14 @@ note: overlaps with this error: some ranges overlap --> $DIR/match_overlapping_arm.rs:63:9 | -63 | 0 .. 11 => println!("0 .. 11"), - | ^^^^^^^ +63 | 0..11 => println!("0 .. 11"), + | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:64:9 | -64 | 0 ... 11 => println!("0 ... 11"), - | ^^^^^^^^ +64 | 0...11 => println!("0 ... 11"), + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 53e61efa83a..3ed70168c6e 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,281 +1,281 @@ error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:26:9 + --> $DIR/matches.rs:20:9 | -26 | / match v { -27 | | &Some(v) => println!("{:?}", v), -28 | | &None => println!("none"), -29 | | } +20 | / match v { +21 | | &Some(v) => println!("{:?}", v), +22 | | &None => println!("none"), +23 | | } | |_________^ | = note: `-D clippy::match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -26 | match *v { -27 | Some(v) => println!("{:?}", v), -28 | None => println!("none"), +20 | match *v { +21 | Some(v) => println!("{:?}", v), +22 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:36:5 + --> $DIR/matches.rs:31:5 | -36 | / match tup { -37 | | &(v, 1) => println!("{}", v), -38 | | _ => println!("none"), -39 | | } +31 | / match tup { +32 | | &(v, 1) => println!("{}", v), +33 | | _ => println!("none"), +34 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -36 | match *tup { -37 | (v, 1) => println!("{}", v), +31 | match *tup { +32 | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:42:5 + --> $DIR/matches.rs:37:5 | -42 | / match &w { -43 | | &Some(v) => println!("{:?}", v), -44 | | &None => println!("none"), -45 | | } +37 | / match &w { +38 | | &Some(v) => println!("{:?}", v), +39 | | &None => println!("none"), +40 | | } | |_____^ help: try | -42 | match w { -43 | Some(v) => println!("{:?}", v), -44 | None => println!("none"), +37 | match w { +38 | Some(v) => println!("{:?}", v), +39 | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:53:5 + --> $DIR/matches.rs:48:5 | -53 | / if let &None = a { -54 | | println!("none"); -55 | | } +48 | / if let &None = a { +49 | | println!("none"); +50 | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -53 | if let None = *a { +48 | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:58:5 + --> $DIR/matches.rs:53:5 | -58 | / if let &None = &b { -59 | | println!("none"); -60 | | } +53 | / if let &None = &b { +54 | | println!("none"); +55 | | } | |_____^ help: try | -58 | if let None = b { +53 | if let None = b { | ^^^^ ^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:69:9 + --> $DIR/matches.rs:64:9 | -69 | Err(_) => panic!("err") +64 | Err(_) => panic!("err"), | ^^^^^^ | = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:68:18 + --> $DIR/matches.rs:63:18 | -68 | Ok(_) => println!("ok"), +63 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:67:18 + --> $DIR/matches.rs:62:18 | -67 | Ok(3) => println!("ok"), +62 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:67:18 + --> $DIR/matches.rs:62:18 | -67 | Ok(3) => println!("ok"), +62 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:75:9 + --> $DIR/matches.rs:70:9 | -75 | Err(_) => {panic!()} +70 | Err(_) => panic!(), | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:69:18 | -74 | Ok(_) => println!("ok"), +69 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:73:18 + --> $DIR/matches.rs:68:18 | -73 | Ok(3) => println!("ok"), +68 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:73:18 + --> $DIR/matches.rs:68:18 | -73 | Ok(3) => println!("ok"), +68 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:81:9 + --> $DIR/matches.rs:76:9 | -81 | Err(_) => {panic!();} +76 | Err(_) => { | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:80:18 + --> $DIR/matches.rs:75:18 | -80 | Ok(_) => println!("ok"), +75 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:79:18 + --> $DIR/matches.rs:74:18 | -79 | Ok(3) => println!("ok"), +74 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:79:18 + --> $DIR/matches.rs:74:18 | -79 | Ok(3) => println!("ok"), +74 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:84:18 | -87 | Ok(_) => println!("ok"), +84 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:86:18 + --> $DIR/matches.rs:83:18 | -86 | Ok(3) => println!("ok"), +83 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:86:18 + --> $DIR/matches.rs:83:18 | -86 | Ok(3) => println!("ok"), +83 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:94:18 + --> $DIR/matches.rs:91:18 | -94 | Ok(_) => println!("ok"), +91 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:90:18 | -93 | Ok(3) => println!("ok"), +90 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:90:18 | -93 | Ok(3) => println!("ok"), +90 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:100:18 - | -100 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:97:18 + | +97 | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:99:18 - | -99 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:96:18 + | +96 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:99:18 - | -99 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:96:18 + | +96 | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:106:18 + --> $DIR/matches.rs:103:18 | -106 | Ok(_) => println!("ok"), +103 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:105:18 + --> $DIR/matches.rs:102:18 | -105 | Ok(3) => println!("ok"), +102 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:105:18 + --> $DIR/matches.rs:102:18 | -105 | Ok(3) => println!("ok"), +102 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:127:29 + --> $DIR/matches.rs:126:29 | -127 | (Ok(_), Some(x)) => println!("ok {}", x), +126 | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:126:29 + --> $DIR/matches.rs:125:29 | -126 | (Ok(x), Some(_)) => println!("ok {}", x), +125 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:126:29 + --> $DIR/matches.rs:125:29 | -126 | (Ok(x), Some(_)) => println!("ok {}", x), +125 | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:142:18 + --> $DIR/matches.rs:141:18 | -142 | Ok(_) => println!("ok"), +141 | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:141:18 + --> $DIR/matches.rs:140:18 | -141 | Ok(3) => println!("ok"), +140 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:141:18 + --> $DIR/matches.rs:140:18 | -141 | Ok(3) => println!("ok"), +140 | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:149:33 + --> $DIR/matches.rs:150:33 | -149 | let borrowed: Option<&()> = match owned { +150 | let borrowed: Option<&()> = match owned { | _________________________________^ -150 | | None => None, -151 | | Some(ref v) => Some(v), -152 | | }; +151 | | None => None, +152 | | Some(ref v) => Some(v), +153 | | }; | |_____^ help: try this: `owned.as_ref()` | = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:155:39 + --> $DIR/matches.rs:156:39 | -155 | let borrow_mut: Option<&mut ()> = match mut_owned { +156 | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ -156 | | None => None, -157 | | Some(ref mut v) => Some(v), -158 | | }; +157 | | None => None, +158 | | Some(ref mut v) => Some(v), +159 | | }; | |_____^ help: try this: `mut_owned.as_mut()` error: aborting due to 19 previous errors diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index 6414e4c96d6..a00f7ab30e1 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -1,101 +1,101 @@ error: calling `mem::discriminant` on non-enum type `&str` - --> $DIR/mem_discriminant.rs:24:5 + --> $DIR/mem_discriminant.rs:23:5 | -24 | mem::discriminant(&"hello"); +23 | mem::discriminant(&"hello"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/mem_discriminant.rs:11:9 + --> $DIR/mem_discriminant.rs:10:9 | -11 | #![deny(clippy::mem_discriminant_non_enum)] +10 | #![deny(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:25:5 + --> $DIR/mem_discriminant.rs:24:5 | -25 | mem::discriminant(&&Some(2)); +24 | mem::discriminant(&&Some(2)); | ^^^^^^^^^^^^^^^^^^---------^ | | | help: try dereferencing: `&Some(2)` error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:26:5 + --> $DIR/mem_discriminant.rs:25:5 | -26 | mem::discriminant(&&None::); +25 | mem::discriminant(&&None::); | ^^^^^^^^^^^^^^^^^^------------^ | | | help: try dereferencing: `&None::` error: calling `mem::discriminant` on non-enum type `&Foo` - --> $DIR/mem_discriminant.rs:27:5 + --> $DIR/mem_discriminant.rs:26:5 | -27 | mem::discriminant(&&Foo::One(5)); +26 | mem::discriminant(&&Foo::One(5)); | ^^^^^^^^^^^^^^^^^^-------------^ | | | help: try dereferencing: `&Foo::One(5)` error: calling `mem::discriminant` on non-enum type `&Foo` - --> $DIR/mem_discriminant.rs:28:5 + --> $DIR/mem_discriminant.rs:27:5 | -28 | mem::discriminant(&&Foo::Two(5)); +27 | mem::discriminant(&&Foo::Two(5)); | ^^^^^^^^^^^^^^^^^^-------------^ | | | help: try dereferencing: `&Foo::Two(5)` error: calling `mem::discriminant` on non-enum type `A` - --> $DIR/mem_discriminant.rs:29:5 + --> $DIR/mem_discriminant.rs:28:5 | -29 | mem::discriminant(&A(Foo::One(0))); +28 | mem::discriminant(&A(Foo::One(0))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:33:5 + --> $DIR/mem_discriminant.rs:32:5 | -33 | mem::discriminant(&ro); +32 | mem::discriminant(&ro); | ^^^^^^^^^^^^^^^^^^---^ | | | help: try dereferencing: `ro` error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:34:5 + --> $DIR/mem_discriminant.rs:33:5 | -34 | mem::discriminant(rro); +33 | mem::discriminant(rro); | ^^^^^^^^^^^^^^^^^^---^ | | | help: try dereferencing: `*rro` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` - --> $DIR/mem_discriminant.rs:35:5 + --> $DIR/mem_discriminant.rs:34:5 | -35 | mem::discriminant(&rro); +34 | mem::discriminant(&rro); | ^^^^^^^^^^^^^^^^^^----^ | | | help: try dereferencing: `*rro` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` - --> $DIR/mem_discriminant.rs:38:27 + --> $DIR/mem_discriminant.rs:38:13 | -38 | ($param:expr) => (mem::discriminant($param)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +38 | mem::discriminant($param) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... -41 | mem_discriminant_but_in_a_macro!(&rro); +42 | mem_discriminant_but_in_a_macro!(&rro); | --------------------------------------- | | | | | help: try dereferencing: `*rro` | in this macro invocation error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` - --> $DIR/mem_discriminant.rs:44:5 + --> $DIR/mem_discriminant.rs:45:5 | -44 | mem::discriminant(&rrrrro); +45 | mem::discriminant(&rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ | | | help: try dereferencing: `****rrrrro` error: calling `mem::discriminant` on non-enum type `&&&std::option::Option` - --> $DIR/mem_discriminant.rs:45:5 + --> $DIR/mem_discriminant.rs:46:5 | -45 | mem::discriminant(*rrrrro); +46 | mem::discriminant(*rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ | | | help: try dereferencing: `****rrrrro` diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 06ac6a3679d..479cd4934ab 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -1,21 +1,21 @@ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:28:5 + --> $DIR/mem_forget.rs:23:5 | -28 | memstuff::forget(six); +23 | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:31:5 + --> $DIR/mem_forget.rs:26:5 | -31 | std::mem::forget(seven); +26 | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:34:5 + --> $DIR/mem_forget.rs:29:5 | -34 | forgetSomething(eight); +29 | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 64a1690156c..06d8f5f74c0 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,15 +1,15 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:18:13 + --> $DIR/mem_replace.rs:16:13 | -18 | let _ = mem::replace(&mut an_option, None); +16 | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` | = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:20:13 + --> $DIR/mem_replace.rs:18:13 | -20 | let _ = mem::replace(an_option, None); +18 | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: aborting due to 2 previous errors diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index 3ed67ad258e..74a93e350de 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,45 +1,45 @@ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:25:5 + --> $DIR/min_max.rs:21:5 | -25 | min(1, max(3, x)); +21 | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::min-max` implied by `-D warnings` error: this min/max combination leads to constant result - --> $DIR/min_max.rs:26:5 + --> $DIR/min_max.rs:22:5 | -26 | min(max(3, x), 1); +22 | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:27:5 + --> $DIR/min_max.rs:23:5 | -27 | max(min(x, 1), 3); +23 | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:28:5 + --> $DIR/min_max.rs:24:5 | -28 | max(3, min(x, 1)); +24 | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:30:5 + --> $DIR/min_max.rs:26:5 | -30 | my_max(3, my_min(x, 1)); +26 | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:42:5 + --> $DIR/min_max.rs:38:5 | -42 | min("Apple", max("Zoo", s)); +38 | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:43:5 + --> $DIR/min_max.rs:39:5 | -43 | max(min(s, "Apple"), "Zoo"); +39 | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index 67f50152c73..b50305ab9ee 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -1,267 +1,257 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:38:1 + --> $DIR/missing-doc.rs:32:1 | -38 | type Typedef = String; +32 | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:39:1 + --> $DIR/missing-doc.rs:33:1 | -39 | pub type PubTypedef = String; +33 | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:41:1 + --> $DIR/missing-doc.rs:35:1 | -41 | / struct Foo { -42 | | a: isize, -43 | | b: isize, -44 | | } +35 | / struct Foo { +36 | | a: isize, +37 | | b: isize, +38 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:42:5 + --> $DIR/missing-doc.rs:36:5 | -42 | a: isize, +36 | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:43:5 + --> $DIR/missing-doc.rs:37:5 | -43 | b: isize, +37 | b: isize, | ^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:46:1 + --> $DIR/missing-doc.rs:40:1 | -46 | / pub struct PubFoo { -47 | | pub a: isize, -48 | | b: isize, -49 | | } +40 | / pub struct PubFoo { +41 | | pub a: isize, +42 | | b: isize, +43 | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:47:5 + --> $DIR/missing-doc.rs:41:5 | -47 | pub a: isize, +41 | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:48:5 + --> $DIR/missing-doc.rs:42:5 | -48 | b: isize, +42 | b: isize, | ^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:57:1 + --> $DIR/missing-doc.rs:51:1 | -57 | mod module_no_dox {} +51 | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:58:1 + --> $DIR/missing-doc.rs:52:1 | -58 | pub mod pub_module_no_dox {} +52 | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:62:1 + --> $DIR/missing-doc.rs:56:1 | -62 | pub fn foo2() {} +56 | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:63:1 + --> $DIR/missing-doc.rs:57:1 | -63 | fn foo3() {} +57 | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for a trait - --> $DIR/missing-doc.rs:80:1 + --> $DIR/missing-doc.rs:75:1 | -80 | / pub trait C { -81 | | fn foo(&self); -82 | | fn foo_with_impl(&self) {} -83 | | } +75 | / pub trait C { +76 | | fn foo(&self); +77 | | fn foo_with_impl(&self) {} +78 | | } | |_^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:81:5 + --> $DIR/missing-doc.rs:76:5 | -81 | fn foo(&self); +76 | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:82:5 + --> $DIR/missing-doc.rs:77:5 | -82 | fn foo_with_impl(&self) {} +77 | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:92:5 + --> $DIR/missing-doc.rs:87:5 | -92 | type AssociatedType; +87 | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:93:5 + --> $DIR/missing-doc.rs:88:5 | -93 | type AssociatedTypeDef = Self; +88 | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:104:5 - | -104 | pub fn foo() {} - | ^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:99:5 + | +99 | pub fn foo() {} + | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:105:5 + --> $DIR/missing-doc.rs:100:5 | -105 | fn bar() {} +100 | fn bar() {} | ^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:109:5 + --> $DIR/missing-doc.rs:104:5 | -109 | pub fn foo() {} +104 | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:112:5 + --> $DIR/missing-doc.rs:107:5 | -112 | fn foo2() {} +107 | fn foo2() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:138:1 + --> $DIR/missing-doc.rs:134:1 | -138 | / enum Baz { -139 | | BazA { -140 | | a: isize, -141 | | b: isize -142 | | }, -143 | | BarB -144 | | } +134 | / enum Baz { +135 | | BazA { a: isize, b: isize }, +136 | | BarB, +137 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:139:5 + --> $DIR/missing-doc.rs:135:5 | -139 | / BazA { -140 | | a: isize, -141 | | b: isize -142 | | }, - | |_____^ +135 | BazA { a: isize, b: isize }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:140:9 + --> $DIR/missing-doc.rs:135:12 | -140 | a: isize, - | ^^^^^^^^ +135 | BazA { a: isize, b: isize }, + | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:141:9 + --> $DIR/missing-doc.rs:135:22 | -141 | b: isize - | ^^^^^^^^ +135 | BazA { a: isize, b: isize }, + | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:143:5 + --> $DIR/missing-doc.rs:136:5 | -143 | BarB +136 | BarB, | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:146:1 + --> $DIR/missing-doc.rs:139:1 | -146 | / pub enum PubBaz { -147 | | PubBazA { -148 | | a: isize, -149 | | }, -150 | | } +139 | / pub enum PubBaz { +140 | | PubBazA { a: isize }, +141 | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:147:5 + --> $DIR/missing-doc.rs:140:5 | -147 | / PubBazA { -148 | | a: isize, -149 | | }, - | |_____^ +140 | PubBazA { a: isize }, + | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:148:9 + --> $DIR/missing-doc.rs:140:15 | -148 | a: isize, - | ^^^^^^^^ +140 | PubBazA { a: isize }, + | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:172:1 + --> $DIR/missing-doc.rs:160:1 | -172 | const FOO: u32 = 0; +160 | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:179:1 + --> $DIR/missing-doc.rs:167:1 | -179 | pub const FOO4: u32 = 0; +167 | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:182:1 + --> $DIR/missing-doc.rs:169:1 | -182 | static BAR: u32 = 0; +169 | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:189:1 + --> $DIR/missing-doc.rs:176:1 | -189 | pub static BAR4: u32 = 0; +176 | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:192:1 + --> $DIR/missing-doc.rs:178:1 | -192 | / mod internal_impl { -193 | | /// dox -194 | | pub fn documented() {} -195 | | pub fn undocumented1() {} +178 | / mod internal_impl { +179 | | /// dox +180 | | pub fn documented() {} +181 | | pub fn undocumented1() {} ... | -204 | | } -205 | | } +190 | | } +191 | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:195:5 + --> $DIR/missing-doc.rs:181:5 | -195 | pub fn undocumented1() {} +181 | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:196:5 + --> $DIR/missing-doc.rs:182:5 | -196 | pub fn undocumented2() {} +182 | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:197:5 + --> $DIR/missing-doc.rs:183:5 | -197 | fn undocumented3() {} +183 | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:202:9 + --> $DIR/missing-doc.rs:188:9 | -202 | pub fn also_undocumented1() {} +188 | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:203:9 + --> $DIR/missing-doc.rs:189:9 | -203 | fn also_undocumented2() {} +189 | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 39 previous errors diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index fc617ef54c9..132285a1eaa 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -1,39 +1,39 @@ error: missing `#[inline]` for a function - --> $DIR/missing_inline.rs:43:1 + --> $DIR/missing_inline.rs:40:1 | -43 | pub fn pub_foo() {} // missing #[inline] +40 | pub fn pub_foo() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` error: missing `#[inline]` for a default trait method - --> $DIR/missing_inline.rs:58:5 + --> $DIR/missing_inline.rs:56:5 | -58 | fn PubBar_b() {} // missing #[inline] +56 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:71:5 + --> $DIR/missing_inline.rs:70:5 | -71 | fn PubBar_a() {} // missing #[inline] +70 | fn PubBar_a() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:72:5 + --> $DIR/missing_inline.rs:71:5 | -72 | fn PubBar_b() {} // missing #[inline] +71 | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:73:5 + --> $DIR/missing_inline.rs:72:5 | -73 | fn PubBar_c() {} // missing #[inline] +72 | fn PubBar_c() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:83:5 + --> $DIR/missing_inline.rs:82:5 | -83 | pub fn PubFooImpl() {} // missing #[inline] +82 | pub fn PubFooImpl() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index c1e6d0a6e62..bf891aa4578 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,19 +1,19 @@ error: module has the same name as its containing module - --> $DIR/module_inception.rs:17:9 + --> $DIR/module_inception.rs:14:9 | -17 | / mod bar { -18 | | mod foo {} -19 | | } +14 | / mod bar { +15 | | mod foo {} +16 | | } | |_________^ | = note: `-D clippy::module-inception` implied by `-D warnings` error: module has the same name as its containing module - --> $DIR/module_inception.rs:22:5 + --> $DIR/module_inception.rs:19:5 | -22 | / mod foo { -23 | | mod bar {} -24 | | } +19 | / mod foo { +20 | | mod bar {} +21 | | } | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index 57e2c59ee14..e4d20c5c63c 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -1,7 +1,7 @@ error: any number modulo 1 will be 0 - --> $DIR/modulo_one.rs:17:5 + --> $DIR/modulo_one.rs:14:5 | -17 | 10 % 1; +14 | 10 % 1; | ^^^^^^ | = note: `-D clippy::modulo-one` implied by `-D warnings` diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index 48b5abf5a6e..db0f05a7fa7 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -1,62 +1,62 @@ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:19:39 + --> $DIR/mut_from_ref.rs:16:39 | -19 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { +16 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^^^^ | = note: `-D clippy::mut-from-ref` implied by `-D warnings` note: immutable borrow here - --> $DIR/mut_from_ref.rs:19:29 + --> $DIR/mut_from_ref.rs:16:29 | -19 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { +16 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:25:25 + --> $DIR/mut_from_ref.rs:22:25 | -25 | fn ouch(x: &Foo) -> &mut Foo; +22 | fn ouch(x: &Foo) -> &mut Foo; | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:25:16 + --> $DIR/mut_from_ref.rs:22:16 | -25 | fn ouch(x: &Foo) -> &mut Foo; +22 | fn ouch(x: &Foo) -> &mut Foo; | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:34:21 + --> $DIR/mut_from_ref.rs:31:21 | -34 | fn fail(x: &u32) -> &mut u16 { +31 | fn fail(x: &u32) -> &mut u16 { | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:34:12 + --> $DIR/mut_from_ref.rs:31:12 | -34 | fn fail(x: &u32) -> &mut u16 { +31 | fn fail(x: &u32) -> &mut u16 { | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:38:50 + --> $DIR/mut_from_ref.rs:35:50 | -38 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +35 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:38:25 + --> $DIR/mut_from_ref.rs:35:25 | -38 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +35 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:42:67 + --> $DIR/mut_from_ref.rs:39:67 | -42 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +39 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:42:27 + --> $DIR/mut_from_ref.rs:39:27 | -42 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +39 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index c05c0215795..626a309a6a9 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -1,61 +1,61 @@ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:20:12 + --> $DIR/mut_mut.rs:13:11 | -20 | fn fun(x : &mut &mut u32) -> bool { - | ^^^^^^^^^^^^^ +13 | fn fun(x: &mut &mut u32) -> bool { + | ^^^^^^^^^^^^^ | = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:34:17 + --> $DIR/mut_mut.rs:29:17 | -34 | let mut x = &mut &mut 1u32; +29 | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:29:20 + --> $DIR/mut_mut.rs:23:9 | -29 | ($p:expr) => { &mut $p } - | ^^^^^^^ +23 | &mut $p + | ^^^^^^^ ... -49 | let mut z = mut_ptr!(&mut 3u32); +44 | let mut z = mut_ptr!(&mut 3u32); | ------------------- in this macro invocation error: this expression mutably borrows a mutable reference. Consider reborrowing - --> $DIR/mut_mut.rs:36:21 + --> $DIR/mut_mut.rs:31:21 | -36 | let mut y = &mut x; +31 | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:40:33 + --> $DIR/mut_mut.rs:35:32 | -40 | let y : &mut &mut u32 = &mut &mut 2; - | ^^^^^^^^^^^ +35 | let y: &mut &mut u32 = &mut &mut 2; + | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:40:17 + --> $DIR/mut_mut.rs:35:16 | -40 | let y : &mut &mut u32 = &mut &mut 2; - | ^^^^^^^^^^^^^ +35 | let y: &mut &mut u32 = &mut &mut 2; + | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:45:38 + --> $DIR/mut_mut.rs:40:37 | -45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^^^^ +40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; + | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:45:17 + --> $DIR/mut_mut.rs:40:16 | -45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^^^^^^ +40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; + | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:45:22 + --> $DIR/mut_mut.rs:40:21 | -45 | let y : &mut &mut &mut u32 = &mut &mut &mut 2; - | ^^^^^^^^^^^^^ +40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; + | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index a476ad5d14e..87537d77f44 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,33 +1,33 @@ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:28:21 + --> $DIR/mut_range_bound.rs:25:9 | -28 | for i in 0..m { m = 5; } // warning - | ^^^^^ +25 | m = 5; + | ^^^^^ | = note: `-D clippy::mut-range-bound` implied by `-D warnings` error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:33:22 + --> $DIR/mut_range_bound.rs:32:9 | -33 | for i in m..10 { m *= 2; } // warning - | ^^^^^^ +32 | m *= 2; + | ^^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:39:21 + --> $DIR/mut_range_bound.rs:40:9 | -39 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) - | ^^^^^ +40 | m = 5; + | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:39:28 + --> $DIR/mut_range_bound.rs:41:9 | -39 | for i in m..n { m = 5; n = 7; } // warning (1 for each mutated bound) - | ^^^^^ +41 | n = 7; + | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:50:22 + --> $DIR/mut_range_bound.rs:55:22 | -50 | let n = &mut m; // warning +55 | let n = &mut m; // warning | ^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 07b07580d4b..1664c1dffed 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,21 +1,21 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:32:34 + --> $DIR/mut_reference.rs:26:34 | -32 | takes_an_immutable_reference(&mut 42); +26 | takes_an_immutable_reference(&mut 42); | ^^^^^^^ | = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` error: The function/method `as_ptr` doesn't need a mutable reference - --> $DIR/mut_reference.rs:34:12 + --> $DIR/mut_reference.rs:28:12 | -34 | as_ptr(&mut 42); +28 | as_ptr(&mut 42); | ^^^^^^^ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:38:44 + --> $DIR/mut_reference.rs:32:44 | -38 | my_struct.takes_an_immutable_reference(&mut 42); +32 | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index a317e8a6c94..d6f4f03c323 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -1,47 +1,47 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:19:5 + --> $DIR/mutex_atomic.rs:15:5 | -19 | Mutex::new(true); +15 | Mutex::new(true); | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::mutex-atomic` implied by `-D warnings` error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:20:5 + --> $DIR/mutex_atomic.rs:16:5 | -20 | Mutex::new(5usize); +16 | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:21:5 + --> $DIR/mutex_atomic.rs:17:5 | -21 | Mutex::new(9isize); +17 | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:23:5 + --> $DIR/mutex_atomic.rs:19:5 | -23 | Mutex::new(&x as *const u32); +19 | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:24:5 + --> $DIR/mutex_atomic.rs:20:5 | -24 | Mutex::new(&mut x as *mut u32); +20 | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:25:5 + --> $DIR/mutex_atomic.rs:21:5 | -25 | Mutex::new(0u32); +21 | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::mutex-integer` implied by `-D warnings` error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:26:5 + --> $DIR/mutex_atomic.rs:22:5 | -26 | Mutex::new(0i32); +22 | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index 638a3f56f0f..df2f80ffd11 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,95 +1,139 @@ error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:41:5 + --> $DIR/needless_bool.rs:40:5 | -41 | if x { true } else { true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +40 | / if x { +41 | | true +42 | | } else { +43 | | true +44 | | }; + | |_____^ | = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:42:5 + --> $DIR/needless_bool.rs:45:5 | -42 | if x { false } else { false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +45 | / if x { +46 | | false +47 | | } else { +48 | | false +49 | | }; + | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:43:5 + --> $DIR/needless_bool.rs:50:5 | -43 | if x { true } else { false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `x` +50 | / if x { +51 | | true +52 | | } else { +53 | | false +54 | | }; + | |_____^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:44:5 + --> $DIR/needless_bool.rs:55:5 | -44 | if x { false } else { true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!x` +55 | / if x { +56 | | false +57 | | } else { +58 | | true +59 | | }; + | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:45:5 + --> $DIR/needless_bool.rs:60:5 | -45 | if x && y { false } else { true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `!(x && y)` +60 | / if x && y { +61 | | false +62 | | } else { +63 | | true +64 | | }; + | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:60:5 + --> $DIR/needless_bool.rs:83:5 | -60 | if x { return true } else { return true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +83 | / if x { +84 | | return true; +85 | | } else { +86 | | return true; +87 | | }; + | |_____^ error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:65:5 + --> $DIR/needless_bool.rs:92:5 | -65 | if x { return false } else { return false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +92 | / if x { +93 | | return false; +94 | | } else { +95 | | return false; +96 | | }; + | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:70:5 - | -70 | if x { return true } else { return false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x` + --> $DIR/needless_bool.rs:101:5 + | +101 | / if x { +102 | | return true; +103 | | } else { +104 | | return false; +105 | | }; + | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:75:5 - | -75 | if x && y { return true } else { return false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return x && y` + --> $DIR/needless_bool.rs:110:5 + | +110 | / if x && y { +111 | | return true; +112 | | } else { +113 | | return false; +114 | | }; + | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:80:5 - | -80 | if x { return false } else { return true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !x` + --> $DIR/needless_bool.rs:119:5 + | +119 | / if x { +120 | | return false; +121 | | } else { +122 | | return true; +123 | | }; + | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:85:5 - | -85 | if x && y { return false } else { return true }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `return !(x && y)` + --> $DIR/needless_bool.rs:128:5 + | +128 | / if x && y { +129 | | return false; +130 | | } else { +131 | | return true; +132 | | }; + | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:89:7 - | -89 | if x == true { }; - | ^^^^^^^^^^ help: try simplifying it as shown: `x` - | - = note: `-D clippy::bool-comparison` implied by `-D warnings` + --> $DIR/needless_bool.rs:136:8 + | +136 | if x == true {}; + | ^^^^^^^^^ help: try simplifying it as shown: `x` + | + = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:93:7 - | -93 | if x == false { }; - | ^^^^^^^^^^^ help: try simplifying it as shown: `!x` + --> $DIR/needless_bool.rs:140:8 + | +140 | if x == false {}; + | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:104:8 + --> $DIR/needless_bool.rs:150:8 | -104 | if x == true { }; +150 | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:105:8 + --> $DIR/needless_bool.rs:151:8 | -105 | if x == false { }; +151 | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: aborting due to 15 previous errors diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 93ba61784d3..42deedfa869 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,41 +1,41 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:25:15 + --> $DIR/needless_borrow.rs:22:15 | -25 | let c = x(&&a); +22 | let c = x(&&a); | ^^^ help: change this to: `&a` | = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:32:17 + --> $DIR/needless_borrow.rs:29:17 | -32 | if let Some(ref cake) = Some(&5) {} +29 | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:39:15 + --> $DIR/needless_borrow.rs:36:15 | -39 | 46 => &&a, +36 | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:61:34 + --> $DIR/needless_borrow.rs:58:34 | -61 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +58 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:62:30 + --> $DIR/needless_borrow.rs:59:30 | -62 | let _ = v.iter().filter(|&ref a| a.is_empty()); +59 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:62:31 + --> $DIR/needless_borrow.rs:59:31 | -62 | let _ = v.iter().filter(|&ref a| a.is_empty()); +59 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` error: aborting due to 6 previous errors diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index ef80473a9dc..5ec7b9e4f3e 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,27 +1,27 @@ error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:18:34 + --> $DIR/needless_borrowed_ref.rs:14:34 | -18 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +14 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:23:17 + --> $DIR/needless_borrowed_ref.rs:19:17 | -23 | if let Some(&ref v) = thingy { +19 | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep: `v` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:52:27 + --> $DIR/needless_borrowed_ref.rs:48:27 | -52 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +48 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:52:38 + --> $DIR/needless_borrowed_ref.rs:48:38 | -52 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +48 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index ee41a9d8dea..39b3aa5470b 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,27 +1,27 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:19:28 + --> $DIR/needless_collect.rs:16:28 | -19 | let len = sample.iter().collect::>().len(); +16 | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` | = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:20:21 + --> $DIR/needless_collect.rs:17:21 | -20 | if sample.iter().collect::>().is_empty() { +17 | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:23:27 + --> $DIR/needless_collect.rs:20:27 | -23 | sample.iter().cloned().collect::>().contains(&1); +20 | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:24:34 + --> $DIR/needless_collect.rs:21:34 | -24 | sample.iter().map(|x| (x, x)).collect::>().len(); +21 | sample.iter().map(|x| (x, x)).collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 10e7062f2a6..06f63ee496e 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -12,9 +12,9 @@ error: This else block is redundant. = help: Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so: if i % 2 == 0 && i % 3 == 0 { println!("{}", i); - println!("{}", i+1); + println!("{}", i + 1); if i % 5 == 0 { - println!("{}", i+2); + println!("{}", i + 2); } let i = 0; println!("bar {} ", i); diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 3685f0e9614..e11aa73db2a 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,128 +1,128 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:21:23 + --> $DIR/needless_pass_by_value.rs:24:23 | -21 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { +24 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` | = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:35:11 + --> $DIR/needless_pass_by_value.rs:38:11 | -35 | fn bar(x: String, y: Wrapper) { +38 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:35:22 + --> $DIR/needless_pass_by_value.rs:38:22 | -35 | fn bar(x: String, y: Wrapper) { +38 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:41:71 + --> $DIR/needless_pass_by_value.rs:44:71 | -41 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +44 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:53:18 + --> $DIR/needless_pass_by_value.rs:56:18 | -53 | fn test_match(x: Option>, y: Option>) { +56 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -53 | fn test_match(x: &Option>, y: Option>) { -54 | match *x { +56 | fn test_match(x: &Option>, y: Option>) { +57 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:66:24 + --> $DIR/needless_pass_by_value.rs:69:24 | -66 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +69 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:66:36 + --> $DIR/needless_pass_by_value.rs:69:36 | -66 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +69 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead | -66 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -67 | let Wrapper(s) = z; // moved -68 | let Wrapper(ref t) = *y; // not moved -69 | let Wrapper(_) = *y; // still not moved +69 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +70 | let Wrapper(s) = z; // moved +71 | let Wrapper(ref t) = *y; // not moved +72 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:82:49 + --> $DIR/needless_pass_by_value.rs:85:49 | -82 | fn test_blanket_ref(_foo: T, _serializable: S) {} +85 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:84:18 + --> $DIR/needless_pass_by_value.rs:87:18 | -84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:84:29 + --> $DIR/needless_pass_by_value.rs:87:29 | -84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -84 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +87 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -86 | let _ = t.to_string(); +89 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:84:40 + --> $DIR/needless_pass_by_value.rs:87:40 | -84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:84:53 + --> $DIR/needless_pass_by_value.rs:87:53 | -84 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -84 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +87 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -88 | let _ = v.to_owned(); +91 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:96:12 - | -96 | s: String, - | ^^^^^^ help: consider changing the type to: `&str` + --> $DIR/needless_pass_by_value.rs:100:12 + | +100 | s: String, + | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:97:12 - | -97 | t: String, - | ^^^^^^ help: consider taking a reference instead: `&String` + --> $DIR/needless_pass_by_value.rs:101:12 + | +101 | t: String, + | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:109:13 + --> $DIR/needless_pass_by_value.rs:110:23 | -109 | _u: U, - | ^ help: consider taking a reference instead: `&U` +110 | fn baz(&self, _u: U, _s: Self) {} + | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:110:13 + --> $DIR/needless_pass_by_value.rs:110:30 | -110 | _s: Self, - | ^^^^ help: consider taking a reference instead: `&Self` +110 | fn baz(&self, _u: U, _s: Self) {} + | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:132:24 diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 688e9fc3a2c..03a469dfa72 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,83 +1,83 @@ error: the loop variable `i` is only used to index `ns`. - --> $DIR/needless_range_loop.rs:18:14 + --> $DIR/needless_range_loop.rs:17:14 | -18 | for i in 3..10 { +17 | for i in 3..10 { | ^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -18 | for in ns.iter().take(10).skip(3) { +17 | for in ns.iter().take(10).skip(3) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:39:14 + --> $DIR/needless_range_loop.rs:38:14 | -39 | for i in 0..ms.len() { +38 | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -39 | for in &mut ms { +38 | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:45:14 + --> $DIR/needless_range_loop.rs:44:14 | -45 | for i in 0..ms.len() { +44 | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -45 | for in &mut ms { +44 | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/needless_range_loop.rs:69:14 + --> $DIR/needless_range_loop.rs:68:14 | -69 | for i in x..x + 4 { +68 | for i in x..x + 4 { | ^^^^^^^^ help: consider using an iterator | -69 | for in vec.iter_mut().skip(x).take(4) { +68 | for in vec.iter_mut().skip(x).take(4) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/needless_range_loop.rs:76:14 + --> $DIR/needless_range_loop.rs:75:14 | -76 | for i in x..=x + 4 { +75 | for i in x..=x + 4 { | ^^^^^^^^^ help: consider using an iterator | -76 | for in vec.iter_mut().skip(x).take(4 + 1) { +75 | for in vec.iter_mut().skip(x).take(4 + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:82:14 + --> $DIR/needless_range_loop.rs:81:14 | -82 | for i in 0..3 { +81 | for i in 0..3 { | ^^^^ help: consider using an iterator | -82 | for in &arr { +81 | for in &arr { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:86:14 + --> $DIR/needless_range_loop.rs:85:14 | -86 | for i in 0..2 { +85 | for i in 0..2 { | ^^^^ help: consider using an iterator | -86 | for in arr.iter().take(2) { +85 | for in arr.iter().take(2) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:90:14 + --> $DIR/needless_range_loop.rs:89:14 | -90 | for i in 1..3 { +89 | for i in 1..3 { | ^^^^ help: consider using an iterator | -90 | for in arr.iter().skip(1) { +89 | for in arr.iter().skip(1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 742ef8d379e..07d29c19be3 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,51 +1,51 @@ error: unneeded return statement - --> $DIR/needless_return.rs:21:5 + --> $DIR/needless_return.rs:17:5 | -21 | return true; +17 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` | = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded return statement - --> $DIR/needless_return.rs:25:5 + --> $DIR/needless_return.rs:21:5 | -25 | return true - | ^^^^^^^^^^^ help: remove `return` as shown: `true` +21 | return true; + | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:30:9 + --> $DIR/needless_return.rs:26:9 | -30 | return true; +26 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:32:9 + --> $DIR/needless_return.rs:28:9 | -32 | return false; +28 | return false; | ^^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:38:17 + --> $DIR/needless_return.rs:34:17 | -38 | true => return false, +34 | true => return false, | ^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:40:13 + --> $DIR/needless_return.rs:36:13 | -40 | return true; +36 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:47:9 + --> $DIR/needless_return.rs:43:9 | -47 | return true; +43 | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:49:16 + --> $DIR/needless_return.rs:45:16 | -49 | let _ = || return true; +45 | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` error: aborting due to 8 previous errors diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index 512cec84770..d5cd0e7889a 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -1,7 +1,7 @@ error: struct update has no effect, all the fields in the struct have already been specified - --> $DIR/needless_update.rs:26:23 + --> $DIR/needless_update.rs:22:23 | -26 | S { a: 1, b: 1, ..base }; +22 | S { a: 1, b: 1, ..base }; | ^^^^ | = note: `-D clippy::needless-update` implied by `-D warnings` diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 1bd292818b3..ee0f9af6f95 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,27 +1,27 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:29:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:24:21 | -29 | let _not_less = !(a_value < another_value); +24 | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:32:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:27:30 | -32 | let _not_less_or_equal = !(a_value <= another_value); +27 | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:35:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:30:24 | -35 | let _not_greater = !(a_value > another_value); +30 | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:38:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:33:33 | -38 | let _not_greater_or_equal = !(a_value >= another_value); +33 | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index ed96dd519ff..5e5d1afaafe 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -1,15 +1,15 @@ error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:40:5 + --> $DIR/neg_multiply.rs:36:5 | -40 | x * -1; +36 | x * -1; | ^^^^^^ | = note: `-D clippy::neg-multiply` implied by `-D warnings` error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:42:5 + --> $DIR/neg_multiply.rs:38:5 | -42 | -1 * x; +38 | -1 * x; | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index e4daa6e4350..6ef26234d9d 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,93 +1,99 @@ error: this loop never actually loops - --> $DIR/never_loop.rs:17:5 + --> $DIR/never_loop.rs:19:5 | -17 | / loop { // clippy::never_loop -18 | | x += 1; -19 | | if x == 1 { -20 | | return -21 | | } -22 | | break; -23 | | } +19 | / loop { +20 | | // clippy::never_loop +21 | | x += 1; +22 | | if x == 1 { +... | +25 | | break; +26 | | } | |_____^ | = note: #[deny(clippy::never_loop)] on by default error: this loop never actually loops - --> $DIR/never_loop.rs:38:5 + --> $DIR/never_loop.rs:41:5 | -38 | / loop { // never loops -39 | | x += 1; -40 | | break -41 | | } +41 | / loop { +42 | | // never loops +43 | | x += 1; +44 | | break; +45 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:57:2 + --> $DIR/never_loop.rs:61:5 | -57 | loop { // never loops - | _____^ -58 | | while i == 0 { // never loops -59 | | break -60 | | } -61 | | return -62 | | } +61 | / loop { +62 | | // never loops +63 | | while i == 0 { +64 | | // never loops +... | +67 | | return; +68 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:58:9 + --> $DIR/never_loop.rs:63:9 | -58 | / while i == 0 { // never loops -59 | | break -60 | | } +63 | / while i == 0 { +64 | | // never loops +65 | | break; +66 | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:69:3 + --> $DIR/never_loop.rs:75:9 | -69 | loop { // never loops - | _________^ -70 | | if x == 5 { break } -71 | | continue 'outer -72 | | } +75 | / loop { +76 | | // never loops +77 | | if x == 5 { +78 | | break; +79 | | } +80 | | continue 'outer; +81 | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:102:5 + --> $DIR/never_loop.rs:111:5 | -102 | / while let Some(y) = x { // never loops -103 | | return -104 | | } +111 | / while let Some(y) = x { +112 | | // never loops +113 | | return; +114 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:108:5 + --> $DIR/never_loop.rs:118:5 | -108 | / for x in 0..10 { // never loops -109 | | match x { -110 | | 1 => break, -111 | | _ => return, -112 | | } -113 | | } +118 | / for x in 0..10 { +119 | | // never loops +120 | | match x { +121 | | 1 => break, +122 | | _ => return, +123 | | } +124 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:154:5 + --> $DIR/never_loop.rs:166:5 | -154 | / 'outer: while a { // never loops -155 | | while a { -156 | | if a { -157 | | a = false; +166 | / 'outer: while a { +167 | | // never loops +168 | | while a { +169 | | if a { ... | -161 | | break 'outer; -162 | | } +174 | | break 'outer; +175 | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:168:9 + --> $DIR/never_loop.rs:181:9 | -168 | / while false { -169 | | break 'label; -170 | | } +181 | / while false { +182 | | break 'label; +183 | | } | |_________^ error: aborting due to 9 previous errors diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index bab9627ca22..e5911b3d72e 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -25,22 +25,28 @@ error: methods called `new` usually return `Self` | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:120:5 + --> $DIR/new_ret_no_self.rs:126:5 | -120 | pub fn new() -> (u32, u32) { unimplemented!(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +126 | / pub fn new() -> (u32, u32) { +127 | | unimplemented!(); +128 | | } + | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:141:5 + --> $DIR/new_ret_no_self.rs:153:5 | -141 | pub fn new() -> *mut V { unimplemented!(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +153 | / pub fn new() -> *mut V { +154 | | unimplemented!(); +155 | | } + | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:155:5 + --> $DIR/new_ret_no_self.rs:171:5 | -155 | pub fn new() -> Option { unimplemented!(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +171 | / pub fn new() -> Option { +172 | | unimplemented!(); +173 | | } + | |_____^ error: aborting due to 6 previous errors diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 5343428636c..b37c1e14424 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,39 +1,45 @@ error: you should consider deriving a `Default` implementation for `Foo` - --> $DIR/new_without_default.rs:22:5 + --> $DIR/new_without_default.rs:17:5 | -22 | pub fn new() -> Foo { Foo } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +17 | / pub fn new() -> Foo { +18 | | Foo +19 | | } + | |_____^ | = note: `-D clippy::new-without-default-derive` implied by `-D warnings` help: try this | -19 | #[derive(Default)] +14 | #[derive(Default)] | error: you should consider deriving a `Default` implementation for `Bar` - --> $DIR/new_without_default.rs:28:5 + --> $DIR/new_without_default.rs:25:5 | -28 | pub fn new() -> Self { Bar } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +25 | / pub fn new() -> Self { +26 | | Bar +27 | | } + | |_____^ help: try this | -25 | #[derive(Default)] +22 | #[derive(Default)] | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> $DIR/new_without_default.rs:76:5 + --> $DIR/new_without_default.rs:89:5 | -76 | pub fn new() -> LtKo<'c> { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +89 | / pub fn new() -> LtKo<'c> { +90 | | unimplemented!() +91 | | } + | |_____^ | = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | -75 | impl Default for LtKo<'c> { -76 | fn default() -> Self { -77 | Self::new() -78 | } -79 | } +88 | impl Default for LtKo<'c> { +89 | fn default() -> Self { +90 | Self::new() +91 | } +92 | } | error: aborting due to 3 previous errors diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 7f012aa2ed4..e8a88307c97 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,154 +1,154 @@ error: statement with no effect - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:74:5 | -71 | 0; +74 | 0; | ^^ | = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:75:5 | -72 | s2; +75 | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:73:5 + --> $DIR/no_effect.rs:76:5 | -73 | Unit; +76 | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:77:5 | -74 | Tuple(0); +77 | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:78:5 | -75 | Struct { field: 0 }; +78 | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:79:5 | -76 | Struct { ..s }; +79 | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:80:5 | -77 | Union { a: 0 }; +80 | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:81:5 | -78 | Enum::Tuple(0); +81 | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:82:5 | -79 | Enum::Struct { field: 0 }; +82 | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:83:5 | -80 | 5 + 6; +83 | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:84:5 | -81 | *&42; +84 | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:85:5 | -82 | &6; +85 | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:86:5 | -83 | (5, 6, 7); +86 | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:87:5 | -84 | box 42; +87 | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:88:5 | -85 | ..; +88 | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:89:5 | -86 | 5..; +89 | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:87:5 + --> $DIR/no_effect.rs:90:5 | -87 | ..5; +90 | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:91:5 | -88 | 5..6; +91 | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:93:5 | -90 | [42, 55]; +93 | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:94:5 | -91 | [42, 55][1]; +94 | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:95:5 | -92 | (42, 55).1; +95 | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:96:5 | -93 | [42; 55]; +96 | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:97:5 | -94 | [42; 55][13]; +97 | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:99:5 | -96 | || x += 5; +99 | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:98:5 - | -98 | FooString { s: s }; - | ^^^^^^^^^^^^^^^^^^^ + --> $DIR/no_effect.rs:101:5 + | +101 | FooString { s: s }; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 25 previous errors diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 744b5474844..6d65f4dca50 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -1,7 +1,7 @@ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:22:1 + --> $DIR/non_copy_const.rs:19:1 | -22 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +19 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` @@ -9,264 +9,264 @@ error: a const item should never be interior mutable = note: #[deny(clippy::declare_interior_mutable_const)] on by default error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:23:1 + --> $DIR/non_copy_const.rs:20:1 | -23 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +20 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:24:1 + --> $DIR/non_copy_const.rs:21:1 | -24 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +21 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:28:42 + --> $DIR/non_copy_const.rs:26:9 | -28 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; - | ^^^^^^^^^^^^^^^^^^^^^^ -29 | } -30 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +26 | const $name: $ty = $e; + | ^^^^^^^^^^^^^^^^^^^^^^ +... +29 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:51:5 + --> $DIR/non_copy_const.rs:50:5 | -51 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +50 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:55:5 + --> $DIR/non_copy_const.rs:54:5 | -55 | const INPUT: T; +54 | const INPUT: T; | ^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:55:18 + --> $DIR/non_copy_const.rs:54:18 | -55 | const INPUT: T; +54 | const INPUT: T; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:58:5 + --> $DIR/non_copy_const.rs:57:5 | -58 | const ASSOC: Self::NonCopyType; +57 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:58:18 + --> $DIR/non_copy_const.rs:57:18 | -58 | const ASSOC: Self::NonCopyType; +57 | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:62:5 + --> $DIR/non_copy_const.rs:61:5 | -62 | const AN_INPUT: T = Self::INPUT; +61 | const AN_INPUT: T = Self::INPUT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:62:21 + --> $DIR/non_copy_const.rs:61:21 | -62 | const AN_INPUT: T = Self::INPUT; +61 | const AN_INPUT: T = Self::INPUT; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:28:42 + --> $DIR/non_copy_const.rs:26:9 | -28 | ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; - | ^^^^^^^^^^^^^^^^^^^^^^ +26 | const $name: $ty = $e; + | ^^^^^^^^^^^^^^^^^^^^^^ ... -65 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable +64 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable | ----------------------------------------------- in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:71:5 + --> $DIR/non_copy_const.rs:70:5 | -71 | const SELF_2: Self; +70 | const SELF_2: Self; | ^^^^^^^^^^^^^^^^^^^ | help: consider requiring `Self` to be `Copy` - --> $DIR/non_copy_const.rs:71:19 + --> $DIR/non_copy_const.rs:70:19 | -71 | const SELF_2: Self; +70 | const SELF_2: Self; | ^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:92:5 + --> $DIR/non_copy_const.rs:91:5 | -92 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable +91 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:95:5 + --> $DIR/non_copy_const.rs:94:5 | -95 | const U_SELF: U = U::SELF_2; +94 | const U_SELF: U = U::SELF_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `U` to be `Copy` - --> $DIR/non_copy_const.rs:95:19 + --> $DIR/non_copy_const.rs:94:19 | -95 | const U_SELF: U = U::SELF_2; +94 | const U_SELF: U = U::SELF_2; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:98:5 + --> $DIR/non_copy_const.rs:97:5 | -98 | const T_ASSOC: T::NonCopyType = T::ASSOC; +97 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:98:20 + --> $DIR/non_copy_const.rs:97:20 | -98 | const T_ASSOC: T::NonCopyType = T::ASSOC; +97 | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^ error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:105:5 + --> $DIR/non_copy_const.rs:104:5 | -105 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability +104 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ | = note: #[deny(clippy::borrow_interior_mutable_const)] on by default = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:106:16 + --> $DIR/non_copy_const.rs:105:16 | -106 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability +105 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:108:5 + --> $DIR/non_copy_const.rs:107:5 | -108 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability +107 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:109:16 + --> $DIR/non_copy_const.rs:108:16 | -109 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability +108 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:112:22 + --> $DIR/non_copy_const.rs:111:22 | -112 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability +111 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:113:25 + --> $DIR/non_copy_const.rs:112:25 | -113 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability +112 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:114:27 + --> $DIR/non_copy_const.rs:113:27 | -114 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability +113 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:115:26 + --> $DIR/non_copy_const.rs:114:26 | -115 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability +114 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:126:14 + --> $DIR/non_copy_const.rs:125:14 | -126 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability +125 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:127:14 + --> $DIR/non_copy_const.rs:126:14 | -127 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability +126 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:128:19 + --> $DIR/non_copy_const.rs:127:19 | -128 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability +127 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:129:14 + --> $DIR/non_copy_const.rs:128:14 | -129 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +128 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:130:13 + --> $DIR/non_copy_const.rs:129:13 | -130 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability +129 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:136:13 + --> $DIR/non_copy_const.rs:135:13 | -136 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +135 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:141:5 + --> $DIR/non_copy_const.rs:140:5 | -141 | CELL.set(2); //~ ERROR interior mutability +140 | CELL.set(2); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:142:16 + --> $DIR/non_copy_const.rs:141:16 | -142 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability +141 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:155:5 + --> $DIR/non_copy_const.rs:154:5 | -155 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability +154 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:156:16 + --> $DIR/non_copy_const.rs:155:16 | -156 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability +155 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 1369cd8a4ad..568ae721588 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,170 +1,170 @@ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:28:9 + --> $DIR/non_expressive_names.rs:24:9 | -28 | let bpple: i32; +24 | let bpple: i32; | ^^^^^ | = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here - --> $DIR/non_expressive_names.rs:26:9 + --> $DIR/non_expressive_names.rs:22:9 | -26 | let apple: i32; +22 | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `b_pple` - --> $DIR/non_expressive_names.rs:28:9 + --> $DIR/non_expressive_names.rs:24:9 | -28 | let bpple: i32; +24 | let bpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:30:9 + --> $DIR/non_expressive_names.rs:26:9 | -30 | let cpple: i32; +26 | let cpple: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:26:9 + --> $DIR/non_expressive_names.rs:22:9 | -26 | let apple: i32; +22 | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `c_pple` - --> $DIR/non_expressive_names.rs:30:9 + --> $DIR/non_expressive_names.rs:26:9 | -30 | let cpple: i32; +26 | let cpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:55:9 + --> $DIR/non_expressive_names.rs:50:9 | -55 | let bluby: i32; +50 | let bluby: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:54:9 + --> $DIR/non_expressive_names.rs:49:9 | -54 | let blubx: i32; +49 | let blubx: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `blub_y` - --> $DIR/non_expressive_names.rs:55:9 + --> $DIR/non_expressive_names.rs:50:9 | -55 | let bluby: i32; +50 | let bluby: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:60:9 + --> $DIR/non_expressive_names.rs:54:9 | -60 | let coke: i32; +54 | let coke: i32; | ^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:58:9 + --> $DIR/non_expressive_names.rs:52:9 | -58 | let cake: i32; +52 | let cake: i32; | ^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:78:9 + --> $DIR/non_expressive_names.rs:72:9 | -78 | let xyzeabc: i32; +72 | let xyzeabc: i32; | ^^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:76:9 + --> $DIR/non_expressive_names.rs:70:9 | -76 | let xyz1abc: i32; +70 | let xyz1abc: i32; | ^^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:82:9 + --> $DIR/non_expressive_names.rs:76:9 | -82 | let parsee: i32; +76 | let parsee: i32; | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:80:9 + --> $DIR/non_expressive_names.rs:74:9 | -80 | let parser: i32; +74 | let parser: i32; | ^^^^^^ help: separate the discriminating character by an underscore like: `parse_e` - --> $DIR/non_expressive_names.rs:82:9 + --> $DIR/non_expressive_names.rs:76:9 | -82 | let parsee: i32; +76 | let parsee: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:96:16 + --> $DIR/non_expressive_names.rs:90:16 | -96 | bpple: sprang } = unimplemented!(); +90 | bpple: sprang, | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:95:22 + --> $DIR/non_expressive_names.rs:89:16 | -95 | let Foo { apple: spring, - | ^^^^^^ +89 | apple: spring, + | ^^^^^^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:130:17 + --> $DIR/non_expressive_names.rs:125:17 | -130 | let e: i32; +125 | let e: i32; | ^ | = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:133:17 + --> $DIR/non_expressive_names.rs:128:17 | -133 | let e: i32; +128 | let e: i32; | ^ error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:134:17 + --> $DIR/non_expressive_names.rs:129:17 | -134 | let f: i32; +129 | let f: i32; | ^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:139:13 + --> $DIR/non_expressive_names.rs:133:13 | -139 | e => panic!(), +133 | e => panic!(), | ^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:149:9 + --> $DIR/non_expressive_names.rs:143:9 | -149 | let _1 = 1; //~ERROR Consider a more descriptive name +143 | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ | = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:150:9 + --> $DIR/non_expressive_names.rs:144:9 | -150 | let ____1 = 1; //~ERROR Consider a more descriptive name +144 | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:151:9 + --> $DIR/non_expressive_names.rs:145:9 | -151 | let __1___2 = 12; //~ERROR Consider a more descriptive name +145 | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:171:13 + --> $DIR/non_expressive_names.rs:165:13 | -171 | let _1 = 1; +165 | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:172:13 + --> $DIR/non_expressive_names.rs:166:13 | -172 | let ____1 = 1; +166 | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:173:13 + --> $DIR/non_expressive_names.rs:167:13 | -173 | let __1___2 = 12; +167 | let __1___2 = 12; | ^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index f4c8440a774..be013cba459 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,33 +1,33 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:24:5 + --> $DIR/ok_expect.rs:23:5 | -24 | res.ok().expect("disaster!"); +23 | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:30:5 + --> $DIR/ok_expect.rs:29:5 | -30 | res3.ok().expect("whoof"); +29 | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:32:5 + --> $DIR/ok_expect.rs:31:5 | -32 | res4.ok().expect("argh"); +31 | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:34:5 + --> $DIR/ok_expect.rs:33:5 | -34 | res5.ok().expect("oops"); +33 | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:36:5 + --> $DIR/ok_expect.rs:35:5 | -36 | res6.ok().expect("meh"); +35 | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index 27b3ef28ff3..5dd8ea37f6f 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -1,11 +1,11 @@ error: Matching on `Some` with `ok()` is redundant - --> $DIR/ok_if_let.rs:17:5 + --> $DIR/ok_if_let.rs:13:5 | -17 | / if let Some(y) = x.parse().ok() { -18 | | y -19 | | } else { -20 | | 0 -21 | | } +13 | / if let Some(y) = x.parse().ok() { +14 | | y +15 | | } else { +16 | | 0 +17 | | } | |_____^ | = note: `-D clippy::if-let-some-result` implied by `-D warnings` diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index e2b7b7820f3..abe7348622f 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -1,19 +1,19 @@ error: needlessly taken reference of both operands - --> $DIR/op_ref.rs:23:15 + --> $DIR/op_ref.rs:19:15 | -23 | let foo = &5 - &6; +19 | let foo = &5 - &6; | ^^^^^^^ | = note: `-D clippy::op-ref` implied by `-D warnings` help: use the values directly | -23 | let foo = 5 - 6; +19 | let foo = 5 - 6; | ^ ^ error: taken reference of right operand - --> $DIR/op_ref.rs:31:8 + --> $DIR/op_ref.rs:27:8 | -31 | if b < &a { +27 | if b < &a { | ^^^^-- | | | help: use the right value directly: `a` diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 2835eebfbb3..10691d65a29 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,45 +1,45 @@ error: file opened with "truncate" and "read" - --> $DIR/open_options.rs:18:5 + --> $DIR/open_options.rs:15:5 | -18 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); +15 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` error: file opened with "append" and "truncate" - --> $DIR/open_options.rs:19:5 + --> $DIR/open_options.rs:16:5 | -19 | OpenOptions::new().append(true).truncate(true).open("foo.txt"); +16 | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "read" is called more than once - --> $DIR/open_options.rs:21:5 + --> $DIR/open_options.rs:18:5 | -21 | OpenOptions::new().read(true).read(false).open("foo.txt"); +18 | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "create" is called more than once - --> $DIR/open_options.rs:22:5 + --> $DIR/open_options.rs:19:5 | -22 | OpenOptions::new().create(true).create(false).open("foo.txt"); +19 | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "write" is called more than once - --> $DIR/open_options.rs:23:5 + --> $DIR/open_options.rs:20:5 | -23 | OpenOptions::new().write(true).write(false).open("foo.txt"); +20 | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "append" is called more than once - --> $DIR/open_options.rs:24:5 + --> $DIR/open_options.rs:21:5 | -24 | OpenOptions::new().append(true).append(false).open("foo.txt"); +21 | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "truncate" is called more than once - --> $DIR/open_options.rs:25:5 + --> $DIR/open_options.rs:22:5 | -25 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); +22 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 7a2dfd338a3..86fb9e75d8f 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:44:5 + --> $DIR/option_map_unit_fn.rs:41:5 | -44 | x.field.map(do_nothing); +41 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` @@ -9,36 +9,41 @@ error: called `map(f)` on an Option value where `f` is a unit function = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:46:5 + --> $DIR/option_map_unit_fn.rs:43:5 | -46 | x.field.map(do_nothing); +43 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:48:5 + --> $DIR/option_map_unit_fn.rs:45:5 | -48 | x.field.map(diverge); +45 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:54:5 + --> $DIR/option_map_unit_fn.rs:53:5 | -54 | x.field.map(|value| x.do_option_nothing(value + captured)); +53 | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:56:5 + --> $DIR/option_map_unit_fn.rs:55:5 | -56 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` +55 | x.field.map(|value| { + | _____^ + | |_____| + | || +56 | || x.do_option_plus_one(value + captured); +57 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:59:5 @@ -51,157 +56,212 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:61:5 | -61 | x.field.map(|value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +61 | x.field.map(|value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:63:5 | -63 | x.field.map(|value| { do_nothing(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` +63 | x.field.map(|value| { + | _____^ + | |_____| + | || +64 | || do_nothing(value + captured); +65 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:65:5 + --> $DIR/option_map_unit_fn.rs:67:5 | -65 | x.field.map(|value| { { do_nothing(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` +67 | x.field.map(|value| { + | _____^ + | |_____| + | || +68 | || do_nothing(value + captured); +69 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:68:5 + --> $DIR/option_map_unit_fn.rs:71:5 | -68 | x.field.map(|value| diverge(value + captured)); +71 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:70:5 + --> $DIR/option_map_unit_fn.rs:73:5 | -70 | x.field.map(|value| { diverge(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +73 | x.field.map(|value| diverge(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:72:5 + --> $DIR/option_map_unit_fn.rs:75:5 | -72 | x.field.map(|value| { diverge(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` +75 | x.field.map(|value| { + | _____^ + | |_____| + | || +76 | || diverge(value + captured); +77 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:74:5 + --> $DIR/option_map_unit_fn.rs:79:5 | -74 | x.field.map(|value| { { diverge(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` +79 | x.field.map(|value| { + | _____^ + | |_____| + | || +80 | || diverge(value + captured); +81 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:79:5 + --> $DIR/option_map_unit_fn.rs:85:5 | -79 | x.field.map(|value| { let y = plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` +85 | x.field.map(|value| { + | _____^ + | |_____| + | || +86 | || let y = plus_one(value + captured); +87 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:81:5 + --> $DIR/option_map_unit_fn.rs:89:5 | -81 | x.field.map(|value| { plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` +89 | x.field.map(|value| { + | _____^ + | |_____| + | || +90 | || plus_one(value + captured); +91 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:83:5 + --> $DIR/option_map_unit_fn.rs:93:5 | -83 | x.field.map(|value| { { plus_one(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` +93 | x.field.map(|value| { + | _____^ + | |_____| + | || +94 | || plus_one(value + captured); +95 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:86:5 + --> $DIR/option_map_unit_fn.rs:97:5 | -86 | x.field.map(|ref value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +97 | x.field.map(|ref value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:89:5 - | -89 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` + --> $DIR/option_map_unit_fn.rs:99:5 + | +99 | x.field.map(|value| { + | _____^ + | |_____| + | || +100 | || do_nothing(value); +101 | || do_nothing(value) +102 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:91:5 - | -91 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` + --> $DIR/option_map_unit_fn.rs:104:5 + | +104 | x.field.map(|value| { + | _____^ + | |_____| + | || +105 | || if value > 0 { +106 | || do_nothing(value); +107 | || do_nothing(value) +108 | || } +109 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:95:5 - | -95 | x.field.map(|value| { - | _____^ - | |_____| - | || -96 | || do_nothing(value); -97 | || do_nothing(value) -98 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | + --> $DIR/option_map_unit_fn.rs:113:5 + | +113 | x.field.map(|value| { + | _____^ + | |_____| + | || +114 | || do_nothing(value); +115 | || do_nothing(value) +116 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:99:5 - | -99 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` + --> $DIR/option_map_unit_fn.rs:117:5 + | +117 | x.field.map(|value| { + | _____^ + | |_____| + | || +118 | || do_nothing(value); +119 | || do_nothing(value); +120 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:102:5 + --> $DIR/option_map_unit_fn.rs:124:5 | -102 | Some(42).map(diverge); +124 | Some(42).map(diverge); | ^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:103:5 + --> $DIR/option_map_unit_fn.rs:125:5 | -103 | "12".parse::().ok().map(diverge); +125 | "12".parse::().ok().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:104:5 + --> $DIR/option_map_unit_fn.rs:126:5 | -104 | Some(plus_one(1)).map(do_nothing); +126 | Some(plus_one(1)).map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:108:5 + --> $DIR/option_map_unit_fn.rs:130:5 | -108 | y.map(do_nothing); +130 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_y) = y { do_nothing(...) }` diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 8a867fd4fe2..0689a10231b 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,58 +1,58 @@ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:11:13 + --> $DIR/option_option.rs:10:13 | -11 | fn input(_: Option>) { +10 | fn input(_: Option>) {} | ^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::option-option` implied by `-D warnings` error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:14:16 + --> $DIR/option_option.rs:12:16 | -14 | fn output() -> Option> { +12 | fn output() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:18:27 + --> $DIR/option_option.rs:16:27 | -18 | fn output_nested() -> Vec>> { +16 | fn output_nested() -> Vec>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:23:30 + --> $DIR/option_option.rs:21:30 | -23 | fn output_nested_nested() -> Option>> { +21 | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:28:8 + --> $DIR/option_option.rs:26:8 | -28 | x: Option>, +26 | x: Option>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:32:23 + --> $DIR/option_option.rs:30:23 | -32 | fn struct_fn() -> Option> { +30 | fn struct_fn() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:38:22 + --> $DIR/option_option.rs:36:22 | -38 | fn trait_fn() -> Option>; +36 | fn trait_fn() -> Option>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:42:11 + --> $DIR/option_option.rs:40:11 | -42 | Tuple(Option>), +40 | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:43:15 + --> $DIR/option_option.rs:41:17 | -43 | Struct{x: Option>}, - | ^^^^^^^^^^^^^^^^^^ +41 | Struct { x: Option> }, + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 0bd20210f01..1c15eeaf67b 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,51 +1,51 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:21:5 + --> $DIR/overflow_check_conditional.rs:17:8 | -21 | if a + b < a { +17 | if a + b < a {} | ^^^^^^^^^ | = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:24:5 + --> $DIR/overflow_check_conditional.rs:18:8 | -24 | if a > a + b { +18 | if a > a + b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:27:5 + --> $DIR/overflow_check_conditional.rs:19:8 | -27 | if a + b < b { +19 | if a + b < b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:30:5 + --> $DIR/overflow_check_conditional.rs:20:8 | -30 | if b > a + b { +20 | if b > a + b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:33:5 + --> $DIR/overflow_check_conditional.rs:21:8 | -33 | if a - b > b { +21 | if a - b > b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:36:5 + --> $DIR/overflow_check_conditional.rs:22:8 | -36 | if b < a - b { +22 | if b < a - b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:39:5 + --> $DIR/overflow_check_conditional.rs:23:8 | -39 | if a - b > a { +23 | if a - b > a {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:42:5 + --> $DIR/overflow_check_conditional.rs:24:8 | -42 | if a < a - b { +24 | if a < a - b {} | ^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index 75032c1170e..e357050b739 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -1,33 +1,33 @@ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:18:16 + --> $DIR/panic_unimplemented.rs:14:16 | -18 | panic!("{}"); +14 | panic!("{}"); | ^^^^ | = note: `-D clippy::panic-params` implied by `-D warnings` error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:20:16 + --> $DIR/panic_unimplemented.rs:16:16 | -20 | panic!("{:?}"); +16 | panic!("{:?}"); | ^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:22:23 + --> $DIR/panic_unimplemented.rs:18:23 | -22 | assert!(true, "here be missing values: {}"); +18 | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:25:12 + --> $DIR/panic_unimplemented.rs:21:12 | -25 | panic!("{{{this}}}"); +21 | panic!("{{{this}}}"); | ^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panic_unimplemented.rs:68:5 + --> $DIR/panic_unimplemented.rs:64:5 | -68 | unimplemented!(); +64 | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unimplemented` implied by `-D warnings` diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index 0ed2d0789cb..d429fba5db0 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -1,8 +1,10 @@ error: re-implementing `PartialEq::ne` is unnecessary - --> $DIR/partialeq_ne_impl.rs:20:5 + --> $DIR/partialeq_ne_impl.rs:18:5 | -20 | fn ne(&self, _: &Foo) -> bool { false } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +18 | / fn ne(&self, _: &Foo) -> bool { +19 | | false +20 | | } + | |_____^ | = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index d236da24022..b97709d2ae9 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,7 +1,7 @@ error: the `y @ _` pattern can be written as just `y` - --> $DIR/patterns.rs:20:9 + --> $DIR/patterns.rs:17:9 | -20 | y @ _ => (), +17 | y @ _ => (), | ^^^^^ | = note: `-D clippy::redundant-pattern` implied by `-D warnings` diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 3d5553ed0c3..8601f828ef3 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,57 +1,57 @@ error: operator precedence can trip the unwary - --> $DIR/precedence.rs:28:5 + --> $DIR/precedence.rs:24:5 | -28 | 1 << 2 + 3; +24 | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` | = note: `-D clippy::precedence` implied by `-D warnings` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:29:5 + --> $DIR/precedence.rs:25:5 | -29 | 1 + 2 << 3; +25 | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:30:5 + --> $DIR/precedence.rs:26:5 | -30 | 4 >> 1 + 1; +26 | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:31:5 + --> $DIR/precedence.rs:27:5 | -31 | 1 + 3 >> 2; +27 | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:32:5 + --> $DIR/precedence.rs:28:5 | -32 | 1 ^ 1 - 1; +28 | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:33:5 + --> $DIR/precedence.rs:29:5 | -33 | 3 | 2 - 1; +29 | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:34:5 + --> $DIR/precedence.rs:30:5 | -34 | 3 & 5 - 2; +30 | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:35:5 + --> $DIR/precedence.rs:31:5 | -35 | -1i32.abs(); +31 | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:36:5 + --> $DIR/precedence.rs:32:5 | -36 | -1f32.abs(); +32 | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` error: aborting due to 9 previous errors diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 605e527c208..199f76568f0 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,59 +1,59 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:23:19 + --> $DIR/print.rs:20:19 | -23 | write!(f, "{:?}", 43.1415) +20 | write!(f, "{:?}", 43.1415) | ^^^^^^ | = note: `-D clippy::use-debug` implied by `-D warnings` error: use of `Debug`-based formatting - --> $DIR/print.rs:30:19 + --> $DIR/print.rs:27:19 | -30 | write!(f, "{:?}", 42.718) +27 | write!(f, "{:?}", 42.718) | ^^^^^^ error: use of `println!` - --> $DIR/print.rs:35:5 + --> $DIR/print.rs:32:5 | -35 | println!("Hello"); +32 | println!("Hello"); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::print-stdout` implied by `-D warnings` error: use of `print!` - --> $DIR/print.rs:36:5 + --> $DIR/print.rs:33:5 | -36 | print!("Hello"); +33 | print!("Hello"); | ^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:38:5 + --> $DIR/print.rs:35:5 | -38 | print!("Hello {}", "World"); +35 | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:40:5 + --> $DIR/print.rs:37:5 | -40 | print!("Hello {:?}", "World"); +37 | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:40:12 + --> $DIR/print.rs:37:12 | -40 | print!("Hello {:?}", "World"); +37 | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:42:5 + --> $DIR/print.rs:39:5 | -42 | print!("Hello {:#?}", "#orld"); +39 | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:42:12 + --> $DIR/print.rs:39:12 | -42 | print!("Hello {:#?}", "#orld"); +39 | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 9fe7fe34e6e..cba5cc19eac 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,88 +1,88 @@ error: literal with an empty format string - --> $DIR/print_literal.rs:34:71 + --> $DIR/print_literal.rs:31:71 | -34 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); +31 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::print-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/print_literal.rs:35:24 + --> $DIR/print_literal.rs:32:24 | -35 | print!("Hello {}", "world"); +32 | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:36:36 + --> $DIR/print_literal.rs:33:36 | -36 | println!("Hello {} {}", world, "world"); +33 | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:37:26 + --> $DIR/print_literal.rs:34:26 | -37 | println!("Hello {}", "world"); +34 | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:38:30 + --> $DIR/print_literal.rs:35:30 | -38 | println!("10 / 4 is {}", 2.5); +35 | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:39:28 + --> $DIR/print_literal.rs:36:28 | -39 | println!("2 + 1 = {}", 3); +36 | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/print_literal.rs:44:25 + --> $DIR/print_literal.rs:41:25 | -44 | println!("{0} {1}", "hello", "world"); +41 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:44:34 + --> $DIR/print_literal.rs:41:34 | -44 | println!("{0} {1}", "hello", "world"); +41 | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:45:25 + --> $DIR/print_literal.rs:42:25 | -45 | println!("{1} {0}", "hello", "world"); +42 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:45:34 + --> $DIR/print_literal.rs:42:34 | -45 | println!("{1} {0}", "hello", "world"); +42 | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:48:33 + --> $DIR/print_literal.rs:45:35 | -48 | println!("{foo} {bar}", foo="hello", bar="world"); - | ^^^^^^^ +45 | println!("{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:48:46 + --> $DIR/print_literal.rs:45:50 | -48 | println!("{foo} {bar}", foo="hello", bar="world"); - | ^^^^^^^ +45 | println!("{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:49:33 + --> $DIR/print_literal.rs:46:35 | -49 | println!("{bar} {foo}", foo="hello", bar="world"); - | ^^^^^^^ +46 | println!("{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:49:46 + --> $DIR/print_literal.rs:46:50 | -49 | println!("{bar} {foo}", foo="hello", bar="world"); - | ^^^^^^^ +46 | println!("{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 4cd7a6685d4..639a4271110 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,27 +1,27 @@ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:17:5 + --> $DIR/print_with_newline.rs:14:5 | -17 | print!("Hello/n"); +14 | print!("Hello/n"); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::print-with-newline` implied by `-D warnings` error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:18:5 + --> $DIR/print_with_newline.rs:15:5 | -18 | print!("Hello {}/n", "world"); +15 | print!("Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:19:5 + --> $DIR/print_with_newline.rs:16:5 | -19 | print!("Hello {} {}/n", "world", "#2"); +16 | print!("Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:20:5 + --> $DIR/print_with_newline.rs:17:5 | -20 | print!("{}/n", 1265); +17 | print!("{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index e06b403cfec..9a08150d627 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,15 +1,15 @@ error: using `println!("")` - --> $DIR/println_empty_string.rs:13:5 + --> $DIR/println_empty_string.rs:12:5 | -13 | println!(""); +12 | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` | = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` - --> $DIR/println_empty_string.rs:16:14 + --> $DIR/println_empty_string.rs:15:14 | -16 | _ => println!(""), +15 | _ => println!(""), | ^^^^^^^^^^^^ help: replace it with: `println!()` error: aborting due to 2 previous errors diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index e7aecf7c20b..c9e8292795f 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,85 +1,85 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:18:14 + --> $DIR/ptr_arg.rs:15:14 | -18 | fn do_vec(x: &Vec) { +15 | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` | = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:26:14 + --> $DIR/ptr_arg.rs:24:14 | -26 | fn do_str(x: &String) { +24 | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:39:18 + --> $DIR/ptr_arg.rs:37:18 | -39 | fn do_vec(x: &Vec); +37 | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:52:14 + --> $DIR/ptr_arg.rs:50:14 | -52 | fn cloned(x: &Vec) -> Vec { +50 | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ help: change this to | -52 | fn cloned(x: &[u8]) -> Vec { +50 | fn cloned(x: &[u8]) -> Vec { | ^^^^^ help: change `x.clone()` to | -53 | let e = x.to_owned(); +51 | let e = x.to_owned(); | ^^^^^^^^^^^^ help: change `x.clone()` to | -58 | x.to_owned() +56 | x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:61:18 + --> $DIR/ptr_arg.rs:59:18 | -61 | fn str_cloned(x: &String) -> String { +59 | fn str_cloned(x: &String) -> String { | ^^^^^^^ help: change this to | -61 | fn str_cloned(x: &str) -> String { +59 | fn str_cloned(x: &str) -> String { | ^^^^ help: change `x.clone()` to | -62 | let a = x.to_string(); +60 | let a = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -63 | let b = x.to_string(); +61 | let b = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -68 | x.to_string() +64 | x.to_string() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:71:44 + --> $DIR/ptr_arg.rs:67:44 | -71 | fn false_positive_capacity(x: &Vec, y: &String) { +67 | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ help: change this to | -71 | fn false_positive_capacity(x: &Vec, y: &str) { +67 | fn false_positive_capacity(x: &Vec, y: &str) { | ^^^^ help: change `y.clone()` to | -73 | let b = y.to_string(); +69 | let b = y.to_string(); | ^^^^^^^^^^^^^ help: change `y.as_str()` to | -74 | let c = y; +70 | let c = y; | ^ error: using a reference to `Cow` is not recommended. - --> $DIR/ptr_arg.rs:83:25 + --> $DIR/ptr_arg.rs:81:25 | -83 | fn test_cow_with_ref(c: &Cow<[i32]>) { +81 | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: aborting due to 7 previous errors diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index b3df0abbaa8..c9bd4d79460 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,15 +1,15 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:20:9 + --> $DIR/ptr_offset_with_cast.rs:19:9 | -20 | ptr.offset(offset_usize as isize); +19 | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` | = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:24:9 + --> $DIR/ptr_offset_with_cast.rs:23:9 | -24 | ptr.wrapping_offset(offset_usize as isize); +23 | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` error: aborting due to 2 previous errors diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 7ca76e38192..d3daaaa9270 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,21 +1,19 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:12:2 + --> $DIR/question_mark.rs:11:5 | -12 | if a.is_none() { - | _____^ -13 | | return None -14 | | } +11 | / if a.is_none() { +12 | | return None; +13 | | } | |_____^ help: replace_it_with: `a?;` | = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:47:3 + --> $DIR/question_mark.rs:46:9 | -47 | if (self.opt).is_none() { - | _________^ -48 | | return None; -49 | | } +46 | / if (self.opt).is_none() { +47 | | return None; +48 | | } | |_________^ help: replace_it_with: `(self.opt)?;` error: aborting due to 2 previous errors diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 2dc81b4f042..7b3c5ebc3e1 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,42 +1,42 @@ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:20:13 + --> $DIR/range.rs:17:13 | -20 | let _ = (0..1).step_by(0); +17 | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:24:13 + --> $DIR/range.rs:21:13 | -24 | let _ = (1..).step_by(0); +21 | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:25:13 + --> $DIR/range.rs:22:13 | -25 | let _ = (1..=2).step_by(0); +22 | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:28:13 + --> $DIR/range.rs:25:13 | -28 | let _ = x.step_by(0); +25 | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: It is more idiomatic to use v1.iter().enumerate() - --> $DIR/range.rs:36:14 + --> $DIR/range.rs:33:14 | -36 | let _x = v1.iter().zip(0..v1.len()); +33 | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::range-zip-with-len` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:40:13 + --> $DIR/range.rs:37:13 | -40 | let _ = v1.iter().step_by(2/3); - | ^^^^^^^^^^^^^^^^^^^^^^ +37 | let _ = v1.iter().step_by(2 / 3); + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 0cac21734dc..dc49420ecb9 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,54 +1,54 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:22:14 + --> $DIR/range_plus_minus_one.rs:19:14 | -22 | for _ in 0..3+1 { } - | ^^^^^^ help: use: `0..=3` +19 | for _ in 0..3 + 1 {} + | ^^^^^^^^ help: use: `0..=3` | = note: `-D clippy::range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:25:14 + --> $DIR/range_plus_minus_one.rs:22:14 | -25 | for _ in 0..1+5 { } - | ^^^^^^ help: use: `0..=5` +22 | for _ in 0..1 + 5 {} + | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:28:14 + --> $DIR/range_plus_minus_one.rs:25:14 | -28 | for _ in 1..1+1 { } - | ^^^^^^ help: use: `1..=1` +25 | for _ in 1..1 + 1 {} + | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:34:14 + --> $DIR/range_plus_minus_one.rs:31:14 | -34 | for _ in 0..(1+f()) { } - | ^^^^^^^^^^ help: use: `0..=f()` +31 | for _ in 0..(1 + f()) {} + | ^^^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:38:13 + --> $DIR/range_plus_minus_one.rs:35:13 | -38 | let _ = ..=11-1; - | ^^^^^^^ help: use: `..11` +35 | let _ = ..=11 - 1; + | ^^^^^^^^^ help: use: `..11` | = note: `-D clippy::range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:39:13 + --> $DIR/range_plus_minus_one.rs:36:13 | -39 | let _ = ..=(11-1); - | ^^^^^^^^^ help: use: `..11` +36 | let _ = ..=(11 - 1); + | ^^^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:40:13 + --> $DIR/range_plus_minus_one.rs:37:13 | -40 | let _ = (1..11+1); - | ^^^^^^^^^ help: use: `(1..=11)` +37 | let _ = (1..11 + 1); + | ^^^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:41:13 + --> $DIR/range_plus_minus_one.rs:38:13 | -41 | let _ = (f()+1)..(f()+1); - | ^^^^^^^^^^^^^^^^ help: use: `((f()+1)..=f())` +38 | let _ = (f() + 1)..(f() + 1); + | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` error: aborting due to 8 previous errors diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index db452822f89..2130d2a6fe1 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -96,15 +96,15 @@ note: this value is dropped without further use | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:43:22 + --> $DIR/redundant_clone.rs:44:22 | -43 | (a.clone(), a.clone()) +44 | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:43:21 + --> $DIR/redundant_clone.rs:44:21 | -43 | (a.clone(), a.clone()) +44 | (a.clone(), a.clone()) | ^ error: aborting due to 9 previous errors diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 1563de3d74f..0d49f1a4066 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,34 +1,34 @@ error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:25:2 + --> $DIR/redundant_closure_call.rs:21:5 | -25 | i = closure(); +21 | i = closure(); | ^^^^^^^^^^^^^ | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:28:2 + --> $DIR/redundant_closure_call.rs:24:5 | -28 | i = closure(3); +24 | i = closure(3); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:17:10 + --> $DIR/redundant_closure_call.rs:13:13 | -17 | let a = (|| 42)(); +13 | let a = (|| 42)(); | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:20:14 + --> $DIR/redundant_closure_call.rs:16:17 | -20 | let mut k = (|m| m+1)(i); - | ^^^^^^^^^^^^ +16 | let mut k = (|m| m + 1)(i); + | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:22:6 + --> $DIR/redundant_closure_call.rs:18:9 | -22 | k = (|a,b| a*b)(1,5); - | ^^^^^^^^^^^^^^^^ +18 | k = (|a, b| a * b)(1, 5); + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index d81ddf343f1..7febaa61b71 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,45 +1,45 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:46:9 + --> $DIR/redundant_field_names.rs:43:9 | -46 | gender: gender, +43 | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:47:9 + --> $DIR/redundant_field_names.rs:44:9 | -47 | age: age, +44 | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:68:25 + --> $DIR/redundant_field_names.rs:65:25 | -68 | let _ = RangeFrom { start: start }; +65 | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:69:23 + --> $DIR/redundant_field_names.rs:66:23 | -69 | let _ = RangeTo { end: end }; +66 | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:70:21 + --> $DIR/redundant_field_names.rs:67:21 | -70 | let _ = Range { start: start, end: end }; +67 | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:70:35 + --> $DIR/redundant_field_names.rs:67:35 | -70 | let _ = Range { start: start, end: end }; +67 | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:72:32 + --> $DIR/redundant_field_names.rs:69:32 | -72 | let _ = RangeToInclusive { end: end }; +69 | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 7 previous errors diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index a42ac7ba04d..2d2aa88d76d 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,87 +1,81 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:19:12 + --> $DIR/redundant_pattern_matching.rs:14:12 | -19 | if let Ok(_) = Ok::(42) {} +14 | if let Ok(_) = Ok::(42) {} | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:21:12 + --> $DIR/redundant_pattern_matching.rs:16:12 | -21 | if let Err(_) = Err::(42) { - | _____- ^^^^^^ -22 | | } - | |_____- help: try this: `if Err::(42).is_err()` +16 | if let Err(_) = Err::(42) {} + | -------^^^^^^------------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:24:12 + --> $DIR/redundant_pattern_matching.rs:18:12 | -24 | if let None = None::<()> { - | _____- ^^^^ -25 | | } - | |_____- help: try this: `if None::<()>.is_none()` +18 | if let None = None::<()> {} + | -------^^^^---------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:27:12 + --> $DIR/redundant_pattern_matching.rs:20:12 | -27 | if let Some(_) = Some(42) { - | _____- ^^^^^^^ -28 | | } - | |_____- help: try this: `if Some(42).is_some()` +20 | if let Some(_) = Some(42) {} + | -------^^^^^^^-------------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:46:5 + --> $DIR/redundant_pattern_matching.rs:34:5 | -46 | / match Ok::(42) { -47 | | Ok(_) => true, -48 | | Err(_) => false, -49 | | }; +34 | / match Ok::(42) { +35 | | Ok(_) => true, +36 | | Err(_) => false, +37 | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:51:5 + --> $DIR/redundant_pattern_matching.rs:39:5 | -51 | / match Ok::(42) { -52 | | Ok(_) => false, -53 | | Err(_) => true, -54 | | }; +39 | / match Ok::(42) { +40 | | Ok(_) => false, +41 | | Err(_) => true, +42 | | }; | |_____^ help: try this: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:56:5 + --> $DIR/redundant_pattern_matching.rs:44:5 | -56 | / match Err::(42) { -57 | | Ok(_) => false, -58 | | Err(_) => true, -59 | | }; +44 | / match Err::(42) { +45 | | Ok(_) => false, +46 | | Err(_) => true, +47 | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:61:5 + --> $DIR/redundant_pattern_matching.rs:49:5 | -61 | / match Err::(42) { -62 | | Ok(_) => true, -63 | | Err(_) => false, -64 | | }; +49 | / match Err::(42) { +50 | | Ok(_) => true, +51 | | Err(_) => false, +52 | | }; | |_____^ help: try this: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:66:5 + --> $DIR/redundant_pattern_matching.rs:54:5 | -66 | / match Some(42) { -67 | | Some(_) => true, -68 | | None => false, -69 | | }; +54 | / match Some(42) { +55 | | Some(_) => true, +56 | | None => false, +57 | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:71:5 + --> $DIR/redundant_pattern_matching.rs:59:5 | -71 | / match None::<()> { -72 | | Some(_) => false, -73 | | None => true, -74 | | }; +59 | / match None::<()> { +60 | | Some(_) => false, +61 | | None => true, +62 | | }; | |_____^ help: try this: `None::<()>.is_none()` error: aborting due to 10 previous errors diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 4187d55cb47..c09a31e2d8a 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -1,69 +1,69 @@ error: immediately dereferencing a reference - --> $DIR/reference.rs:29:13 + --> $DIR/reference.rs:25:13 | -29 | let b = *&a; +25 | let b = *&a; | ^^^ help: try this: `a` | = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference - --> $DIR/reference.rs:31:13 + --> $DIR/reference.rs:27:13 | -31 | let b = *&get_number(); +27 | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try this: `get_number()` error: immediately dereferencing a reference - --> $DIR/reference.rs:36:13 + --> $DIR/reference.rs:32:13 | -36 | let b = *&bytes[1..2][0]; +32 | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` error: immediately dereferencing a reference - --> $DIR/reference.rs:40:13 + --> $DIR/reference.rs:36:13 | -40 | let b = *&(a); +36 | let b = *&(a); | ^^^^^ help: try this: `(a)` error: immediately dereferencing a reference - --> $DIR/reference.rs:42:13 + --> $DIR/reference.rs:38:13 | -42 | let b = *(&a); +38 | let b = *(&a); | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:44:13 + --> $DIR/reference.rs:40:13 | -44 | let b = *((&a)); - | ^^^^^^^ help: try this: `a` +40 | let b = *(&a); + | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:46:13 + --> $DIR/reference.rs:42:13 | -46 | let b = *&&a; +42 | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:48:14 + --> $DIR/reference.rs:44:14 | -48 | let b = **&aref; +44 | let b = **&aref; | ^^^^^^ help: try this: `aref` error: immediately dereferencing a reference - --> $DIR/reference.rs:52:14 + --> $DIR/reference.rs:48:14 | -52 | let b = **&&a; +48 | let b = **&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:56:17 + --> $DIR/reference.rs:52:17 | -56 | let y = *&mut x; +52 | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference - --> $DIR/reference.rs:63:18 + --> $DIR/reference.rs:59:18 | -63 | let y = **&mut &mut x; +59 | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` error: aborting due to 11 previous errors diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1da859dea5c..680cc5146e5 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,168 +1,168 @@ error: trivial regex - --> $DIR/regex.rs:26:45 + --> $DIR/regex.rs:22:45 | -26 | let pipe_in_wrong_position = Regex::new("|"); +22 | let pipe_in_wrong_position = Regex::new("|"); | ^^^ | = note: `-D clippy::trivial-regex` implied by `-D warnings` = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:27:60 + --> $DIR/regex.rs:23:60 | -27 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); +23 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:28:42 + --> $DIR/regex.rs:24:42 | -28 | let wrong_char_ranice = Regex::new("[z-a]"); +24 | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ | = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:29:37 + --> $DIR/regex.rs:25:37 | -29 | let some_unicode = Regex::new("[é-è]"); +25 | let some_unicode = Regex::new("[é-è]"); | ^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:31:33 + --> $DIR/regex.rs:27:33 | -31 | let some_regex = Regex::new(OPENING_PAREN); +27 | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:33:53 + --> $DIR/regex.rs:29:53 | -33 | let binary_pipe_in_wrong_position = BRegex::new("|"); +29 | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:34:41 + --> $DIR/regex.rs:30:41 | -34 | let some_binary_regex = BRegex::new(OPENING_PAREN); +30 | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:35:56 + --> $DIR/regex.rs:31:56 | -35 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); +31 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:51:9 + --> $DIR/regex.rs:43:37 | -51 | OPENING_PAREN, - | ^^^^^^^^^^^^^ +43 | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); + | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:55:9 + --> $DIR/regex.rs:44:39 | -55 | OPENING_PAREN, - | ^^^^^^^^^^^^^ +44 | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); + | ^^^^^^^^^^^^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:59:45 + --> $DIR/regex.rs:46:45 | -59 | let raw_string_error = Regex::new(r"[...//...]"); +46 | let raw_string_error = Regex::new(r"[...//...]"); | ^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:60:46 + --> $DIR/regex.rs:47:46 | -60 | let raw_string_error = Regex::new(r#"[...//...]"#); +47 | let raw_string_error = Regex::new(r#"[...//...]"#); | ^^ error: trivial regex - --> $DIR/regex.rs:64:33 + --> $DIR/regex.rs:51:33 | -64 | let trivial_eq = Regex::new("^foobar$"); +51 | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:66:48 + --> $DIR/regex.rs:53:48 | -66 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); +53 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:68:42 + --> $DIR/regex.rs:55:42 | -68 | let trivial_starts_with = Regex::new("^foobar"); +55 | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:70:40 + --> $DIR/regex.rs:57:40 | -70 | let trivial_ends_with = Regex::new("foobar$"); +57 | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:72:39 + --> $DIR/regex.rs:59:39 | -72 | let trivial_contains = Regex::new("foobar"); +59 | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:74:39 + --> $DIR/regex.rs:61:39 | -74 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); +61 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:76:40 + --> $DIR/regex.rs:63:40 | -76 | let trivial_backslash = Regex::new("a/.b"); +63 | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:79:36 + --> $DIR/regex.rs:66:36 | -79 | let trivial_empty = Regex::new(""); +66 | let trivial_empty = Regex::new(""); | ^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:81:36 + --> $DIR/regex.rs:68:36 | -81 | let trivial_empty = Regex::new("^"); +68 | let trivial_empty = Regex::new("^"); | ^^^ | = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:83:36 + --> $DIR/regex.rs:70:36 | -83 | let trivial_empty = Regex::new("^$"); +70 | let trivial_empty = Regex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:85:44 + --> $DIR/regex.rs:72:44 | -85 | let binary_trivial_empty = BRegex::new("^$"); +72 | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 5b8451e046c..401e3a527a6 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,217 +1,217 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:22:17 | -23 | { let foo = ATOMIC_BOOL_INIT; }; +22 | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:13:9 + --> $DIR/replace_consts.rs:12:9 | -13 | #![deny(clippy::replace_consts)] +12 | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:23:17 | -24 | { let foo = ATOMIC_ISIZE_INIT; }; +23 | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:24:17 | -25 | { let foo = ATOMIC_I8_INIT; }; +24 | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:25:17 | -26 | { let foo = ATOMIC_I16_INIT; }; +25 | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:26:17 | -27 | { let foo = ATOMIC_I32_INIT; }; +26 | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:27:17 | -28 | { let foo = ATOMIC_I64_INIT; }; +27 | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:28:17 | -29 | { let foo = ATOMIC_USIZE_INIT; }; +28 | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:29:17 | -30 | { let foo = ATOMIC_U8_INIT; }; +29 | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:30:17 | -31 | { let foo = ATOMIC_U16_INIT; }; +30 | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:31:17 | -32 | { let foo = ATOMIC_U32_INIT; }; +31 | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:32:17 | -33 | { let foo = ATOMIC_U64_INIT; }; +32 | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:34:17 | -35 | { let foo = std::isize::MIN; }; +34 | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:35:17 | -36 | { let foo = std::i8::MIN; }; +35 | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:36:17 | -37 | { let foo = std::i16::MIN; }; +36 | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:37:17 | -38 | { let foo = std::i32::MIN; }; +37 | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:38:17 | -39 | { let foo = std::i64::MIN; }; +38 | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:39:17 | -40 | { let foo = std::i128::MIN; }; +39 | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:40:17 | -41 | { let foo = std::usize::MIN; }; +40 | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:41:17 | -42 | { let foo = std::u8::MIN; }; +41 | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:42:17 | -43 | { let foo = std::u16::MIN; }; +42 | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:43:17 | -44 | { let foo = std::u32::MIN; }; +43 | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:44:17 | -45 | { let foo = std::u64::MIN; }; +44 | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:45:17 | -46 | { let foo = std::u128::MIN; }; +45 | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:47:17 | -48 | { let foo = std::isize::MAX; }; +47 | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:48:17 | -49 | { let foo = std::i8::MAX; }; +48 | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:49:17 | -50 | { let foo = std::i16::MAX; }; +49 | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:51:17 + --> $DIR/replace_consts.rs:50:17 | -51 | { let foo = std::i32::MAX; }; +50 | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:52:17 + --> $DIR/replace_consts.rs:51:17 | -52 | { let foo = std::i64::MAX; }; +51 | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:53:17 + --> $DIR/replace_consts.rs:52:17 | -53 | { let foo = std::i128::MAX; }; +52 | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:54:17 + --> $DIR/replace_consts.rs:53:17 | -54 | { let foo = std::usize::MAX; }; +53 | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:55:17 + --> $DIR/replace_consts.rs:54:17 | -55 | { let foo = std::u8::MAX; }; +54 | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:56:17 + --> $DIR/replace_consts.rs:55:17 | -56 | { let foo = std::u16::MAX; }; +55 | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:57:17 + --> $DIR/replace_consts.rs:56:17 | -57 | { let foo = std::u32::MAX; }; +56 | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:58:17 + --> $DIR/replace_consts.rs:57:17 | -58 | { let foo = std::u64::MAX; }; +57 | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:59:17 + --> $DIR/replace_consts.rs:58:17 | -59 | { let foo = std::u128::MAX; }; +58 | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 04f105c78e2..1ef107a5000 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:45:5 + --> $DIR/result_map_unit_fn.rs:42:5 | -45 | x.field.map(do_nothing); +42 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -9,36 +9,41 @@ error: called `map(f)` on an Result value where `f` is a unit function = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:47:5 + --> $DIR/result_map_unit_fn.rs:44:5 | -47 | x.field.map(do_nothing); +44 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:49:5 + --> $DIR/result_map_unit_fn.rs:46:5 | -49 | x.field.map(diverge); +46 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:55:5 + --> $DIR/result_map_unit_fn.rs:54:5 | -55 | x.field.map(|value| x.do_result_nothing(value + captured)); +54 | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:57:5 + --> $DIR/result_map_unit_fn.rs:56:5 | -57 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` +56 | x.field.map(|value| { + | _____^ + | |_____| + | || +57 | || x.do_result_plus_one(value + captured); +58 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:60:5 @@ -51,141 +56,196 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:62:5 | -62 | x.field.map(|value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +62 | x.field.map(|value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:64:5 | -64 | x.field.map(|value| { do_nothing(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` +64 | x.field.map(|value| { + | _____^ + | |_____| + | || +65 | || do_nothing(value + captured); +66 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:66:5 + --> $DIR/result_map_unit_fn.rs:68:5 | -66 | x.field.map(|value| { { do_nothing(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` +68 | x.field.map(|value| { + | _____^ + | |_____| + | || +69 | || do_nothing(value + captured); +70 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:69:5 + --> $DIR/result_map_unit_fn.rs:72:5 | -69 | x.field.map(|value| diverge(value + captured)); +72 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:71:5 + --> $DIR/result_map_unit_fn.rs:74:5 | -71 | x.field.map(|value| { diverge(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +74 | x.field.map(|value| diverge(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:73:5 + --> $DIR/result_map_unit_fn.rs:76:5 | -73 | x.field.map(|value| { diverge(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:75:5 - | -75 | x.field.map(|value| { { diverge(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` +76 | x.field.map(|value| { + | _____^ + | |_____| + | || +77 | || diverge(value + captured); +78 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:80:5 | -80 | x.field.map(|value| { let y = plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:82:5 - | -82 | x.field.map(|value| { plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:84:5 - | -84 | x.field.map(|value| { { plus_one(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` +80 | x.field.map(|value| { + | _____^ + | |_____| + | || +81 | || diverge(value + captured); +82 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:87:5 + --> $DIR/result_map_unit_fn.rs:86:5 | -87 | x.field.map(|ref value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` +86 | x.field.map(|value| { + | _____^ + | |_____| + | || +87 | || let y = plus_one(value + captured); +88 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:90:5 | -90 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { ... }` - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:92:5 - | -92 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { ... }` +90 | x.field.map(|value| { + | _____^ + | |_____| + | || +91 | || plus_one(value + captured); +92 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:96:5 + --> $DIR/result_map_unit_fn.rs:94:5 | -96 | x.field.map(|value| { +94 | x.field.map(|value| { | _____^ | |_____| | || -97 | || do_nothing(value); -98 | || do_nothing(value) -99 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` +95 | || plus_one(value + captured); +96 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` | |_______| | +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:98:5 + | +98 | x.field.map(|ref value| do_nothing(value + captured)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` + error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:100:5 | -100 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(value) = x.field { ... }` +100 | x.field.map(|value| { + | _____^ + | |_____| + | || +101 | || do_nothing(value); +102 | || do_nothing(value) +103 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:105:5 + | +105 | x.field.map(|value| { + | _____^ + | |_____| + | || +106 | || if value > 0 { +107 | || do_nothing(value); +108 | || do_nothing(value) +109 | || } +110 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:114:5 + | +114 | x.field.map(|value| { + | _____^ + | |_____| + | || +115 | || do_nothing(value); +116 | || do_nothing(value) +117 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:118:5 + | +118 | x.field.map(|value| { + | _____^ + | |_____| + | || +119 | || do_nothing(value); +120 | || do_nothing(value); +121 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:104:5 + --> $DIR/result_map_unit_fn.rs:126:5 | -104 | "12".parse::().map(diverge); +126 | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:110:5 + --> $DIR/result_map_unit_fn.rs:132:5 | -110 | y.map(do_nothing); +132 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_y) = y { do_nothing(...) }` diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index e223430e680..23f10f69435 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -1,8 +1,9 @@ error: you should not implement `visit_string` without also implementing `visit_str` - --> $DIR/serde.rs:49:5 + --> $DIR/serde.rs:48:5 | -49 | / fn visit_string(self, _v: String) -> Result -50 | | where E: serde::de::Error, +48 | / fn visit_string(self, _v: String) -> Result +49 | | where +50 | | E: serde::de::Error, 51 | | { 52 | | unimplemented!() 53 | | } diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index adca299d382..196f17ac653 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,137 +1,137 @@ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:23:5 + --> $DIR/shadow.rs:29:5 | -23 | let x = &mut x; +29 | let x = &mut x; | ^^^^^^^^^^^^^^^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:22:13 + --> $DIR/shadow.rs:28:13 | -22 | let mut x = 1; +28 | let mut x = 1; | ^ error: `x` is shadowed by itself in `{ x }` - --> $DIR/shadow.rs:24:5 + --> $DIR/shadow.rs:30:5 | -24 | let x = { x }; +30 | let x = { x }; | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:23:9 + --> $DIR/shadow.rs:29:9 | -23 | let x = &mut x; +29 | let x = &mut x; | ^ error: `x` is shadowed by itself in `(&*x)` - --> $DIR/shadow.rs:25:5 + --> $DIR/shadow.rs:31:5 | -25 | let x = (&*x); +31 | let x = (&*x); | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:24:9 + --> $DIR/shadow.rs:30:9 | -24 | let x = { x }; +30 | let x = { x }; | ^ error: `x` is shadowed by `{ *x + 1 }` which reuses the original value - --> $DIR/shadow.rs:26:9 + --> $DIR/shadow.rs:32:9 | -26 | let x = { *x + 1 }; +32 | let x = { *x + 1 }; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:26:13 + --> $DIR/shadow.rs:32:13 | -26 | let x = { *x + 1 }; +32 | let x = { *x + 1 }; | ^^^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:25:9 + --> $DIR/shadow.rs:31:9 | -25 | let x = (&*x); +31 | let x = (&*x); | ^ error: `x` is shadowed by `id(x)` which reuses the original value - --> $DIR/shadow.rs:27:9 + --> $DIR/shadow.rs:33:9 | -27 | let x = id(x); +33 | let x = id(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:27:13 + --> $DIR/shadow.rs:33:13 | -27 | let x = id(x); +33 | let x = id(x); | ^^^^^ note: previous binding is here - --> $DIR/shadow.rs:26:9 + --> $DIR/shadow.rs:32:9 | -26 | let x = { *x + 1 }; +32 | let x = { *x + 1 }; | ^ error: `x` is shadowed by `(1, x)` which reuses the original value - --> $DIR/shadow.rs:28:9 + --> $DIR/shadow.rs:34:9 | -28 | let x = (1, x); +34 | let x = (1, x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:28:13 + --> $DIR/shadow.rs:34:13 | -28 | let x = (1, x); +34 | let x = (1, x); | ^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:27:9 + --> $DIR/shadow.rs:33:9 | -27 | let x = id(x); +33 | let x = id(x); | ^ error: `x` is shadowed by `first(x)` which reuses the original value - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:35:9 | -29 | let x = first(x); +35 | let x = first(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:29:13 + --> $DIR/shadow.rs:35:13 | -29 | let x = first(x); +35 | let x = first(x); | ^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:28:9 + --> $DIR/shadow.rs:34:9 | -28 | let x = (1, x); +34 | let x = (1, x); | ^ error: `x` is shadowed by `y` - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:37:9 | -31 | let x = y; +37 | let x = y; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:31:13 + --> $DIR/shadow.rs:37:13 | -31 | let x = y; +37 | let x = y; | ^ note: previous binding is here - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:35:9 | -29 | let x = first(x); +35 | let x = first(x); | ^ error: `x` shadows a previous declaration - --> $DIR/shadow.rs:33:5 + --> $DIR/shadow.rs:39:5 | -33 | let x; +39 | let x; | ^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:37:9 | -31 | let x = y; +37 | let x = y; | ^ error: aborting due to 9 previous errors diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index 331bdac3128..7b5c843d072 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -1,21 +1,21 @@ error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:17:5 + --> $DIR/short_circuit_statement.rs:13:5 | -17 | f() && g(); +13 | f() && g(); | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` | = note: `-D clippy::short-circuit-statement` implied by `-D warnings` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:18:5 + --> $DIR/short_circuit_statement.rs:14:5 | -18 | f() || g(); +14 | f() || g(); | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:19:5 + --> $DIR/short_circuit_statement.rs:15:5 | -19 | 1 == 2 || g(); +15 | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` error: aborting due to 3 previous errors diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index ff657df1bf8..273bf779640 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,123 +1,123 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:17:13 + --> $DIR/single_char_pattern.rs:14:13 | -17 | x.split("x"); +14 | x.split("x"); | ^^^ help: try using a char instead: `'x'` | = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:16 + --> $DIR/single_char_pattern.rs:31:16 | -34 | x.contains("x"); +31 | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:19 + --> $DIR/single_char_pattern.rs:32:19 | -35 | x.starts_with("x"); +32 | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:17 + --> $DIR/single_char_pattern.rs:33:17 | -36 | x.ends_with("x"); +33 | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:12 + --> $DIR/single_char_pattern.rs:34:12 | -37 | x.find("x"); +34 | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:13 + --> $DIR/single_char_pattern.rs:35:13 | -38 | x.rfind("x"); +35 | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:14 + --> $DIR/single_char_pattern.rs:36:14 | -39 | x.rsplit("x"); +36 | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:40:24 + --> $DIR/single_char_pattern.rs:37:24 | -40 | x.split_terminator("x"); +37 | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:25 + --> $DIR/single_char_pattern.rs:38:25 | -41 | x.rsplit_terminator("x"); +38 | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:42:17 + --> $DIR/single_char_pattern.rs:39:17 | -42 | x.splitn(0, "x"); +39 | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:43:18 + --> $DIR/single_char_pattern.rs:40:18 | -43 | x.rsplitn(0, "x"); +40 | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:44:15 + --> $DIR/single_char_pattern.rs:41:15 | -44 | x.matches("x"); +41 | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:16 + --> $DIR/single_char_pattern.rs:42:16 | -45 | x.rmatches("x"); +42 | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:21 + --> $DIR/single_char_pattern.rs:43:21 | -46 | x.match_indices("x"); +43 | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:47:22 + --> $DIR/single_char_pattern.rs:44:22 | -47 | x.rmatch_indices("x"); +44 | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:48:25 + --> $DIR/single_char_pattern.rs:45:25 | -48 | x.trim_left_matches("x"); +45 | x.trim_left_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:49:26 + --> $DIR/single_char_pattern.rs:46:26 | -49 | x.trim_right_matches("x"); +46 | x.trim_right_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:51:13 + --> $DIR/single_char_pattern.rs:48:13 | -51 | x.split("/n"); +48 | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:56:31 + --> $DIR/single_char_pattern.rs:53:31 | -56 | x.replace(";", ",").split(","); // issue #2978 +53 | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:57:19 + --> $DIR/single_char_pattern.rs:54:19 | -57 | x.starts_with("/x03"); // issue #2996 +54 | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` error: aborting due to 20 previous errors diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index df614ad201d..45fcbce0047 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,60 +1,68 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:21:5 + --> $DIR/single_match.rs:17:5 | -21 | / match x { -22 | | Some(y) => { println!("{:?}", y); } -23 | | _ => () -24 | | }; - | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y); }` +17 | / match x { +18 | | Some(y) => { +19 | | println!("{:?}", y); +20 | | }, +21 | | _ => (), +22 | | }; + | |_____^ | = note: `-D clippy::single-match` implied by `-D warnings` +help: try this + | +17 | if let Some(y) = x { +18 | println!("{:?}", y); +19 | }; + | error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:27:5 - | -27 | / match x { -28 | | // Note the missing block braces. -29 | | // We suggest `if let Some(y) = x { .. }` because the macro -30 | | // is expanded before we can do anything. -31 | | Some(y) => println!("{:?}", y), -32 | | _ => () -33 | | } + --> $DIR/single_match.rs:25:5 + | +25 | / match x { +26 | | // Note the missing block braces. +27 | | // We suggest `if let Some(y) = x { .. }` because the macro +28 | | // is expanded before we can do anything. +29 | | Some(y) => println!("{:?}", y), +30 | | _ => (), +31 | | } | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:36:5 + --> $DIR/single_match.rs:34:5 | -36 | / match z { -37 | | (2...3, 7...9) => dummy(), -38 | | _ => {} -39 | | }; +34 | / match z { +35 | | (2...3, 7...9) => dummy(), +36 | | _ => {}, +37 | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:62:5 + --> $DIR/single_match.rs:63:5 | -62 | / match x { -63 | | Some(y) => dummy(), -64 | | None => () -65 | | }; +63 | / match x { +64 | | Some(y) => dummy(), +65 | | None => (), +66 | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:67:5 + --> $DIR/single_match.rs:68:5 | -67 | / match y { -68 | | Ok(y) => dummy(), -69 | | Err(..) => () -70 | | }; +68 | / match y { +69 | | Ok(y) => dummy(), +70 | | Err(..) => (), +71 | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:74:5 + --> $DIR/single_match.rs:75:5 | -74 | / match c { -75 | | Cow::Borrowed(..) => dummy(), -76 | | Cow::Owned(..) => (), -77 | | }; +75 | / match c { +76 | | Cow::Borrowed(..) => dummy(), +77 | | Cow::Owned(..) => (), +78 | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: aborting due to 6 previous errors diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 0b488b2fcf4..6ae9dd1a818 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -3,11 +3,21 @@ error: you seem to be trying to use match for destructuring a single pattern. Co | 21 | / match ExprNode::Butterflies { 22 | | ExprNode::ExprAddrOf => Some(&NODE), -23 | | _ => { let x = 5; None }, -24 | | } - | |_____^ help: try this: `if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { let x = 5; None }` +23 | | _ => { +24 | | let x = 5; +25 | | None +26 | | }, +27 | | } + | |_____^ | = note: `-D clippy::single-match-else` implied by `-D warnings` +help: try this + | +21 | if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { +22 | let x = 5; +23 | None +24 | } + | error: aborting due to previous error diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index 9921819e093..0b1b7c020d9 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,77 +1,77 @@ error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:19:5 + --> $DIR/starts_ends_with.rs:16:5 | -19 | "".chars().next() == Some(' '); +16 | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | = note: `-D clippy::chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:20:5 + --> $DIR/starts_ends_with.rs:17:5 | -20 | Some(' ') != "".chars().next(); +17 | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:25:8 + --> $DIR/starts_ends_with.rs:22:8 | -25 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') +22 | if s.chars().next().unwrap() == 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:28:8 + --> $DIR/starts_ends_with.rs:26:8 | -28 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') +26 | if s.chars().next_back().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | = note: `-D clippy::chars-last-cmp` implied by `-D warnings` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:31:8 + --> $DIR/starts_ends_with.rs:30:8 | -31 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') +30 | if s.chars().last().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method --> $DIR/starts_ends_with.rs:34:8 | -34 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') +34 | if s.chars().next().unwrap() != 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:37:8 + --> $DIR/starts_ends_with.rs:38:8 | -37 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') +38 | if s.chars().next_back().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:40:8 + --> $DIR/starts_ends_with.rs:42:8 | -40 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') +42 | if s.chars().last().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:47:5 + --> $DIR/starts_ends_with.rs:50:5 | -47 | "".chars().last() == Some(' '); +50 | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:48:5 + --> $DIR/starts_ends_with.rs:51:5 | -48 | Some(' ') != "".chars().last(); +51 | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:49:5 + --> $DIR/starts_ends_with.rs:52:5 | -49 | "".chars().next_back() == Some(' '); +52 | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:50:5 + --> $DIR/starts_ends_with.rs:53:5 | -50 | Some(' ') != "".chars().next_back(); +53 | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: aborting due to 12 previous errors diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 2a82972a3cd..36af80b8665 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,21 +1,21 @@ error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:26:5 + --> $DIR/string_extend.rs:25:5 | -26 | s.extend(abc.chars()); +25 | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:29:5 + --> $DIR/string_extend.rs:28:5 | -29 | s.extend("abc".chars()); +28 | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:32:5 + --> $DIR/string_extend.rs:31:5 | -32 | s.extend(def.chars()); +31 | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: aborting due to 3 previous errors diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index 21115d8e97e..fe491d29b78 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -1,75 +1,75 @@ error: manual implementation of an assign operation - --> $DIR/strings.rs:20:9 + --> $DIR/strings.rs:17:9 | -20 | x = x + "."; +17 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:20:13 + --> $DIR/strings.rs:17:13 | -20 | x = x + "."; +17 | x = x + "."; | ^^^^^^^ | = note: `-D clippy::string-add` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:24:13 + --> $DIR/strings.rs:21:13 | -24 | let z = y + "..."; +21 | let z = y + "..."; | ^^^^^^^^^ error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:34:9 + --> $DIR/strings.rs:31:9 | -34 | x = x + "."; +31 | x = x + "."; | ^^^^^^^^^^^ | = note: `-D clippy::string-add-assign` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/strings.rs:34:9 + --> $DIR/strings.rs:31:9 | -34 | x = x + "."; +31 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:48:9 + --> $DIR/strings.rs:45:9 | -48 | x = x + "."; +45 | x = x + "."; | ^^^^^^^^^^^ error: manual implementation of an assign operation - --> $DIR/strings.rs:48:9 + --> $DIR/strings.rs:45:9 | -48 | x = x + "."; +45 | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:52:13 + --> $DIR/strings.rs:49:13 | -52 | let z = y + "..."; +49 | let z = y + "..."; | ^^^^^^^^^ error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:60:14 + --> $DIR/strings.rs:57:14 | -60 | let bs = "hello there".as_bytes(); +57 | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:62:14 + --> $DIR/strings.rs:59:14 | -62 | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); +59 | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###` error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/strings.rs:69:22 + --> $DIR/strings.rs:66:22 | -69 | let includestr = include_str!("entry.rs").as_bytes(); +66 | let includestr = include_str!("entry.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")` error: aborting due to 11 previous errors diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr index 2ff992fccf6..8c2d1d43281 100644 --- a/tests/ui/stutter.stderr +++ b/tests/ui/stutter.stderr @@ -1,33 +1,33 @@ error: item name starts with its containing module's name - --> $DIR/stutter.rs:18:5 + --> $DIR/stutter.rs:15:5 | -18 | pub fn foo_bar() {} +15 | pub fn foo_bar() {} | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::stutter` implied by `-D warnings` error: item name ends with its containing module's name - --> $DIR/stutter.rs:19:5 + --> $DIR/stutter.rs:16:5 | -19 | pub fn bar_foo() {} +16 | pub fn bar_foo() {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/stutter.rs:20:5 + --> $DIR/stutter.rs:17:5 | -20 | pub struct FooCake {} +17 | pub struct FooCake {} | ^^^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name - --> $DIR/stutter.rs:21:5 + --> $DIR/stutter.rs:18:5 | -21 | pub enum CakeFoo {} +18 | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/stutter.rs:22:5 + --> $DIR/stutter.rs:19:5 | -22 | pub struct Foo7Bar; +19 | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 64070cce3a8..5e27dd1d44f 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,15 +1,15 @@ error: Suspicious use of binary operator in `Add` impl - --> $DIR/suspicious_arithmetic_impl.rs:24:20 + --> $DIR/suspicious_arithmetic_impl.rs:20:20 | -24 | Foo(self.0 - other.0) +20 | Foo(self.0 - other.0) | ^ | = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` error: Suspicious use of binary operator in `AddAssign` impl - --> $DIR/suspicious_arithmetic_impl.rs:30:23 + --> $DIR/suspicious_arithmetic_impl.rs:26:23 | -30 | *self = *self - other; +26 | *self = *self - other; | ^ | = note: #[deny(clippy::suspicious_op_assign_impl)] on by default diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 7a4fbdad791..12d012442ad 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,66 +1,66 @@ error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:21:5 + --> $DIR/swap.rs:17:5 | -21 | / let temp = foo[0]; -22 | | foo[0] = foo[1]; -23 | | foo[1] = temp; +17 | / let temp = foo[0]; +18 | | foo[0] = foo[1]; +19 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` | = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:30:5 + --> $DIR/swap.rs:26:5 | -30 | / let temp = foo[0]; -31 | | foo[0] = foo[1]; -32 | | foo[1] = temp; +26 | / let temp = foo[0]; +27 | | foo[0] = foo[1]; +28 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:39:5 + --> $DIR/swap.rs:35:5 | -39 | / let temp = foo[0]; -40 | | foo[0] = foo[1]; -41 | | foo[1] = temp; +35 | / let temp = foo[0]; +36 | | foo[0] = foo[1]; +37 | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:57:7 + --> $DIR/swap.rs:53:6 | -57 | ; let t = a; - | _______^ -58 | | a = b; -59 | | b = t; +53 | ; let t = a; + | ______^ +54 | | a = b; +55 | | b = t; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:66:7 + --> $DIR/swap.rs:62:6 | -66 | ; let t = c.0; - | _______^ -67 | | c.0 = a; -68 | | a = t; +62 | ; let t = c.0; + | ______^ +63 | | c.0 = a; +64 | | a = t; | |_________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:54:5 + --> $DIR/swap.rs:50:5 | -54 | / a = b; -55 | | b = a; +50 | / a = b; +51 | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: `-D clippy::almost-swapped` implied by `-D warnings` = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:63:5 + --> $DIR/swap.rs:59:5 | -63 | / c.0 = a; -64 | | a = c.0; +59 | / c.0 = a; +60 | | a = c.0; | |___________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index edde5510e2a..2807539604d 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,34 +1,34 @@ error: `ref` directly on a function argument is ignored. Consider using a reference type instead. - --> $DIR/toplevel_ref_arg.rs:17:15 + --> $DIR/toplevel_ref_arg.rs:13:15 | -17 | fn the_answer(ref mut x: u8) { +13 | fn the_answer(ref mut x: u8) { | ^^^^^^^^^ | = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:28:7 + --> $DIR/toplevel_ref_arg.rs:24:9 | -28 | let ref x = 1; - | ----^^^^^----- help: try: `let x = &1;` +24 | let ref x = 1; + | ----^^^^^----- help: try: `let x = &1;` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:30:7 + --> $DIR/toplevel_ref_arg.rs:26:9 | -30 | let ref y: (&_, u8) = (&1, 2); - | ----^^^^^--------------------- help: try: `let y: &(&_, u8) = &(&1, 2);` +26 | let ref y: (&_, u8) = (&1, 2); + | ----^^^^^--------------------- help: try: `let y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:32:7 + --> $DIR/toplevel_ref_arg.rs:28:9 | -32 | let ref z = 1 + 2; - | ----^^^^^--------- help: try: `let z = &(1 + 2);` +28 | let ref z = 1 + 2; + | ----^^^^^--------- help: try: `let z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:34:7 + --> $DIR/toplevel_ref_arg.rs:30:9 | -34 | let ref mut z = 1 + 2; - | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` +30 | let ref mut z = 1 + 2; + | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` error: aborting due to 5 previous errors diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 4dbb82b3460..0bd3580a7dd 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -1,15 +1,15 @@ error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:17:31 + --> $DIR/trailing_zeros.rs:16:5 | -17 | let _ = #[clippy::author] (x & 0b1111 == 0); // suggest trailing_zeros - | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` +16 | (x & 0b1111 == 0); // suggest trailing_zeros + | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` | = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:18:13 + --> $DIR/trailing_zeros.rs:17:13 | -18 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros +17 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` error: aborting due to 2 previous errors diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index bde43da499f..6e4fe32a4a6 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,245 +1,245 @@ error: transmute from a type (`&'a T`) to itself - --> $DIR/transmute.rs:32:20 + --> $DIR/transmute.rs:28:20 | -32 | let _: &'a T = core::intrinsics::transmute(t); +28 | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:36:23 + --> $DIR/transmute.rs:32:23 | -36 | let _: *const T = core::intrinsics::transmute(t); +32 | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:38:21 + --> $DIR/transmute.rs:34:21 | -38 | let _: *mut T = core::intrinsics::transmute(t); +34 | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:40:23 + --> $DIR/transmute.rs:36:23 | -40 | let _: *const U = core::intrinsics::transmute(t); +36 | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute.rs:45:17 + --> $DIR/transmute.rs:41:17 | -45 | let _: &T = std::mem::transmute(p); +41 | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` | = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:48:21 + --> $DIR/transmute.rs:44:21 | -48 | let _: &mut T = std::mem::transmute(m); +44 | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute.rs:51:17 + --> $DIR/transmute.rs:47:17 | -51 | let _: &T = std::mem::transmute(m); +47 | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:54:21 + --> $DIR/transmute.rs:50:21 | -54 | let _: &mut T = std::mem::transmute(p as *mut T); +50 | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute.rs:57:17 + --> $DIR/transmute.rs:53:17 | -57 | let _: &T = std::mem::transmute(o); +53 | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:60:21 + --> $DIR/transmute.rs:56:21 | -60 | let _: &mut T = std::mem::transmute(om); +56 | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute.rs:63:17 + --> $DIR/transmute.rs:59:17 | -63 | let _: &T = std::mem::transmute(om); +59 | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, u8>`) - --> $DIR/transmute.rs:74:32 + --> $DIR/transmute.rs:70:32 | -74 | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; +70 | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, &u8>`) - --> $DIR/transmute.rs:76:33 + --> $DIR/transmute.rs:72:33 | -76 | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; +72 | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute.rs:80:14 + --> $DIR/transmute.rs:76:14 | -80 | unsafe { std::mem::transmute::<_, Bar>(raw) }; +76 | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:86:27 + --> $DIR/transmute.rs:82:27 | -86 | let _: Vec = core::intrinsics::transmute(my_vec()); +82 | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:88:27 + --> $DIR/transmute.rs:84:27 | -88 | let _: Vec = core::mem::transmute(my_vec()); +84 | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:90:27 + --> $DIR/transmute.rs:86:27 | -90 | let _: Vec = std::intrinsics::transmute(my_vec()); +86 | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:92:27 + --> $DIR/transmute.rs:88:27 | -92 | let _: Vec = std::mem::transmute(my_vec()); +88 | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:94:27 + --> $DIR/transmute.rs:90:27 | -94 | let _: Vec = my_transmute(my_vec()); +90 | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:102:31 - | -102 | let _: *const usize = std::mem::transmute(5_isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` + --> $DIR/transmute.rs:98:31 + | +98 | let _: *const usize = std::mem::transmute(5_isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:106:31 + --> $DIR/transmute.rs:102:31 | -106 | let _: *const usize = std::mem::transmute(1+1usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1+1usize) as *const usize` +102 | let _: *const usize = std::mem::transmute(1 + 1usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:121:24 + --> $DIR/transmute.rs:117:24 | -121 | let _: Usize = core::intrinsics::transmute(int_const_ptr); +117 | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:123:24 + --> $DIR/transmute.rs:119:24 | -123 | let _: Usize = core::intrinsics::transmute(int_mut_ptr); +119 | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:125:31 + --> $DIR/transmute.rs:121:31 | -125 | let _: *const Usize = core::intrinsics::transmute(my_int()); +121 | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:127:29 + --> $DIR/transmute.rs:123:29 | -127 | let _: *mut Usize = core::intrinsics::transmute(my_int()); +123 | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:133:28 + --> $DIR/transmute.rs:129:28 | -133 | let _: char = unsafe { std::mem::transmute(0_u32) }; +129 | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` | = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:134:28 + --> $DIR/transmute.rs:130:28 | -134 | let _: char = unsafe { std::mem::transmute(0_i32) }; +130 | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:139:28 + --> $DIR/transmute.rs:135:28 | -139 | let _: bool = unsafe { std::mem::transmute(0_u8) }; +135 | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` | = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:144:27 + --> $DIR/transmute.rs:140:27 | -144 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; +140 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` | = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:145:27 + --> $DIR/transmute.rs:141:27 | -145 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; +141 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:149:28 + --> $DIR/transmute.rs:145:28 | -149 | let _: &str = unsafe { std::mem::transmute(b) }; +145 | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` | = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:150:32 + --> $DIR/transmute.rs:146:32 | -150 | let _: &mut str = unsafe { std::mem::transmute(mb) }; +146 | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:182:29 + --> $DIR/transmute.rs:178:29 | -182 | let _: *const f32 = std::mem::transmute(ptr); +178 | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` | = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:183:27 + --> $DIR/transmute.rs:179:27 | -183 | let _: *mut f32 = std::mem::transmute(mut_ptr); +179 | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:185:23 + --> $DIR/transmute.rs:181:23 | -185 | let _: &f32 = std::mem::transmute(&1u32); +181 | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:186:23 + --> $DIR/transmute.rs:182:23 | -186 | let _: &f64 = std::mem::transmute(&1f32); +182 | let _: &f64 = std::mem::transmute(&1f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:189:27 + --> $DIR/transmute.rs:185:27 | -189 | let _: &mut f32 = std::mem::transmute(&mut 1u32); +185 | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:190:37 + --> $DIR/transmute.rs:186:37 | -190 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); +186 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: aborting due to 38 previous errors diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index dcc6d264caf..320bbeb7d29 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,15 +1,15 @@ error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:21:31 + --> $DIR/transmute_64bit.rs:16:31 | -21 | let _: *const usize = std::mem::transmute(6.0f64); +16 | let _: *const usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::wrong-transmute` implied by `-D warnings` error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:23:29 + --> $DIR/transmute_64bit.rs:18:29 | -23 | let _: *mut usize = std::mem::transmute(6.0f64); +18 | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 3fb577d3edb..41aa52ecd14 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,93 +1,93 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:57:11 + --> $DIR/trivially_copy_pass_by_ref.rs:56:11 | -57 | fn bad(x: &u32, y: &Foo, z: &Baz) { +56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:57:20 + --> $DIR/trivially_copy_pass_by_ref.rs:56:20 | -57 | fn bad(x: &u32, y: &Foo, z: &Baz) { +56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:57:29 + --> $DIR/trivially_copy_pass_by_ref.rs:56:29 | -57 | fn bad(x: &u32, y: &Foo, z: &Baz) { +56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:12 + --> $DIR/trivially_copy_pass_by_ref.rs:63:12 | -67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:22 + --> $DIR/trivially_copy_pass_by_ref.rs:63:22 | -67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:31 + --> $DIR/trivially_copy_pass_by_ref.rs:63:31 | -67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:67:40 + --> $DIR/trivially_copy_pass_by_ref.rs:63:40 | -67 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:70:16 + --> $DIR/trivially_copy_pass_by_ref.rs:65:16 | -70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:70:25 + --> $DIR/trivially_copy_pass_by_ref.rs:65:25 | -70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:70:34 + --> $DIR/trivially_copy_pass_by_ref.rs:65:34 | -70 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:84:16 + --> $DIR/trivially_copy_pass_by_ref.rs:77:16 | -84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:84:25 + --> $DIR/trivially_copy_pass_by_ref.rs:77:25 | -84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:84:34 + --> $DIR/trivially_copy_pass_by_ref.rs:77:34 | -84 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:89:34 + --> $DIR/trivially_copy_pass_by_ref.rs:81:34 | -89 | fn trait_method(&self, _foo: &Foo); +81 | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:93:37 + --> $DIR/trivially_copy_pass_by_ref.rs:85:37 | -93 | fn trait_method2(&self, _color: &Color); +85 | fn trait_method2(&self, _color: &Color); | ^^^^^^ help: consider passing by value instead: `Color` error: aborting due to 15 previous errors diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index 0940cd53b5c..e8770490abb 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -1,8 +1,8 @@ error: casting i32 to i64 may become silently lossy if types change - --> $DIR/types.rs:19:23 + --> $DIR/types.rs:18:22 | -19 | let c_i64 : i64 = c as i64; - | ^^^^^^^^ help: try: `i64::from(c)` +18 | let c_i64: i64 = c as i64; + | ^^^^^^^^ help: try: `i64::from(c)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 8de848caec3..e27b5866372 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,7 +1,7 @@ error: zero-width space detected - --> $DIR/unicode.rs:16:12 + --> $DIR/unicode.rs:12:12 | -16 | print!("Here >​< is a ZWS, and ​another"); +12 | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::zero-width-space` implied by `-D warnings` @@ -9,9 +9,9 @@ error: zero-width space detected ""Here >/u{200B}< is a ZWS, and /u{200B}another"" error: non-nfc unicode sequence detected - --> $DIR/unicode.rs:22:12 + --> $DIR/unicode.rs:18:12 | -22 | print!("̀àh?"); +18 | print!("̀àh?"); | ^^^^^ | = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` @@ -19,9 +19,9 @@ error: non-nfc unicode sequence detected ""̀àh?"" error: literal non-ASCII character detected - --> $DIR/unicode.rs:28:12 + --> $DIR/unicode.rs:24:12 | -28 | print!("Üben!"); +24 | print!("Üben!"); | ^^^^^^^ | = note: `-D clippy::non-ascii-literal` implied by `-D warnings` diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 6e5cf8354bc..ed8d4cdfd3d 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,67 +1,73 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:35:9 + --> $DIR/unit_arg.rs:32:9 | -35 | foo({}); +32 | foo({}); | ^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` help: if you intended to pass a unit value, use a unit literal instead | -35 | foo(()); +32 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:36:9 + --> $DIR/unit_arg.rs:33:9 | -36 | foo({ 1; }); - | ^^^^^^ +33 | foo({ + | _________^ +34 | | 1; +35 | | }); + | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -36 | foo(()); +33 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:37:9 + --> $DIR/unit_arg.rs:36:9 | -37 | foo(foo(1)); +36 | foo(foo(1)); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -37 | foo(()); +36 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:38:9 + --> $DIR/unit_arg.rs:37:9 | -38 | foo({ +37 | foo({ | _________^ -39 | | foo(1); -40 | | foo(2); -41 | | }); +38 | | foo(1); +39 | | foo(2); +40 | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -38 | foo(()); +37 | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:42:10 + --> $DIR/unit_arg.rs:41:10 | -42 | foo3({}, 2, 2); +41 | foo3({}, 2, 2); | ^^ help: if you intended to pass a unit value, use a unit literal instead | -42 | foo3((), 2, 2); +41 | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:44:11 + --> $DIR/unit_arg.rs:43:11 | -44 | b.bar({ 1; }); - | ^^^^^^ +43 | b.bar({ + | ___________^ +44 | | 1; +45 | | }); + | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -44 | b.bar(()); +43 | b.bar(()); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index bd9ac25a64f..7c76945fe3e 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,16 +1,26 @@ error: ==-comparison of unit values detected. This will always be true - --> $DIR/unit_cmp.rs:26:8 + --> $DIR/unit_cmp.rs:21:8 | -26 | if { true; } == { false; } { - | ^^^^^^^^^^^^^^^^^^^^^^^ +21 | if { + | ________^ +22 | | true; +23 | | } == { +24 | | false; +25 | | } {} + | |_____^ | = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false - --> $DIR/unit_cmp.rs:29:8 + --> $DIR/unit_cmp.rs:27:8 | -29 | if { true; } > { false; } { - | ^^^^^^^^^^^^^^^^^^^^^^ +27 | if { + | ________^ +28 | | true; +29 | | } > { +30 | | false; +31 | | } {} + | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 5dcd5cae463..8a0bf9d55b5 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,95 +1,95 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:29:5 + --> $DIR/unnecessary_clone.rs:26:5 | -29 | 42.clone(); +26 | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:33:5 + --> $DIR/unnecessary_clone.rs:30:5 | -33 | (&42).clone(); +30 | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:36:5 + --> $DIR/unnecessary_clone.rs:33:5 | -36 | rc.borrow().clone(); +33 | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:46:5 + --> $DIR/unnecessary_clone.rs:43:5 | -46 | rc.clone(); +43 | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:49:5 + --> $DIR/unnecessary_clone.rs:46:5 | -49 | arc.clone(); +46 | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:52:5 + --> $DIR/unnecessary_clone.rs:49:5 | -52 | rcweak.clone(); +49 | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:55:5 + --> $DIR/unnecessary_clone.rs:52:5 | -55 | arc_weak.clone(); +52 | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:59:29 + --> $DIR/unnecessary_clone.rs:56:29 | -59 | let _: Arc = x.clone(); +56 | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:63:5 + --> $DIR/unnecessary_clone.rs:60:5 | -63 | t.clone(); +60 | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:65:5 + --> $DIR/unnecessary_clone.rs:62:5 | -65 | Some(t).clone(); +62 | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:71:22 + --> $DIR/unnecessary_clone.rs:68:22 | -71 | let z: &Vec<_> = y.clone(); +68 | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | = note: #[deny(clippy::clone_double_ref)] on by default help: try dereferencing it | -71 | let z: &Vec<_> = &(*y).clone(); +68 | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -71 | let z: &Vec<_> = &std::vec::Vec::clone(y); +68 | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:78:27 + --> $DIR/unnecessary_clone.rs:75:26 | -78 | let v2 : Vec = v.iter().cloned().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +75 | let v2: Vec = v.iter().cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:110:20 + --> $DIR/unnecessary_clone.rs:111:20 | -110 | let _: E = a.clone(); +111 | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` error: aborting due to 13 previous errors diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index 8fef6068167..53311b3d275 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -1,31 +1,37 @@ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:12:13 + --> $DIR/unnecessary_filter_map.rs:11:13 | -12 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); +11 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:13:13 + --> $DIR/unnecessary_filter_map.rs:12:13 | -13 | let _ = (0..4).filter_map(|x| { if x > 1 { return Some(x); }; None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +12 | let _ = (0..4).filter_map(|x| { + | _____________^ +13 | | if x > 1 { +14 | | return Some(x); +15 | | }; +16 | | None +17 | | }); + | |______^ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:14:13 + --> $DIR/unnecessary_filter_map.rs:18:13 | -14 | let _ = (0..4).filter_map(|x| match x { +18 | let _ = (0..4).filter_map(|x| match x { | _____________^ -15 | | 0 | 1 => None, -16 | | _ => Some(x), -17 | | }); +19 | | 0 | 1 => None, +20 | | _ => Some(x), +21 | | }); | |______^ error: this `.filter_map` can be written more simply using `.map` - --> $DIR/unnecessary_filter_map.rs:19:13 + --> $DIR/unnecessary_filter_map.rs:23:13 | -19 | let _ = (0..4).filter_map(|x| Some(x + 1)); +23 | let _ = (0..4).filter_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index b2865479c43..e0bd744265c 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -1,33 +1,33 @@ error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:14:19 + --> $DIR/unnecessary_fold.rs:13:19 | -14 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); +13 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | = note: `-D clippy::unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:16:19 + --> $DIR/unnecessary_fold.rs:15:19 | -16 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); +15 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:18:19 + --> $DIR/unnecessary_fold.rs:17:19 | -18 | let _ = (0..3).fold(0, |acc, x| acc + x); +17 | let _ = (0..3).fold(0, |acc, x| acc + x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:20:19 + --> $DIR/unnecessary_fold.rs:19:19 | -20 | let _ = (0..3).fold(1, |acc, x| acc * x); +19 | let _ = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:25:34 + --> $DIR/unnecessary_fold.rs:24:34 | -25 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +24 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: aborting due to 5 previous errors diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index 8e5417eb13e..8b576bef648 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -1,124 +1,128 @@ error: statement can be reduced - --> $DIR/unnecessary_operation.rs:48:5 + --> $DIR/unnecessary_operation.rs:54:5 | -48 | Tuple(get_number()); +54 | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | = note: `-D clippy::unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:49:5 + --> $DIR/unnecessary_operation.rs:55:5 | -49 | Struct { field: get_number() }; +55 | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:50:5 + --> $DIR/unnecessary_operation.rs:56:5 | -50 | Struct { ..get_struct() }; +56 | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:51:5 + --> $DIR/unnecessary_operation.rs:57:5 | -51 | Enum::Tuple(get_number()); +57 | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:52:5 + --> $DIR/unnecessary_operation.rs:58:5 | -52 | Enum::Struct { field: get_number() }; +58 | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:53:5 + --> $DIR/unnecessary_operation.rs:59:5 | -53 | 5 + get_number(); +59 | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:54:5 + --> $DIR/unnecessary_operation.rs:60:5 | -54 | *&get_number(); +60 | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:55:5 + --> $DIR/unnecessary_operation.rs:61:5 | -55 | &get_number(); +61 | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:56:5 + --> $DIR/unnecessary_operation.rs:62:5 | -56 | (5, 6, get_number()); +62 | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:57:5 + --> $DIR/unnecessary_operation.rs:63:5 | -57 | box get_number(); +63 | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:58:5 + --> $DIR/unnecessary_operation.rs:64:5 | -58 | get_number()..; +64 | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:59:5 + --> $DIR/unnecessary_operation.rs:65:5 | -59 | ..get_number(); +65 | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:60:5 + --> $DIR/unnecessary_operation.rs:66:5 | -60 | 5..get_number(); +66 | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:61:5 + --> $DIR/unnecessary_operation.rs:67:5 | -61 | [42, get_number()]; +67 | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:62:5 + --> $DIR/unnecessary_operation.rs:68:5 | -62 | [42, 55][get_number() as usize]; +68 | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:63:5 + --> $DIR/unnecessary_operation.rs:69:5 | -63 | (42, get_number()).1; +69 | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:64:5 + --> $DIR/unnecessary_operation.rs:70:5 | -64 | [get_number(); 55]; +70 | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:65:5 + --> $DIR/unnecessary_operation.rs:71:5 | -65 | [42; 55][get_number() as usize]; +71 | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:66:5 + --> $DIR/unnecessary_operation.rs:72:5 | -66 | {get_number()}; - | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` +72 | / { +73 | | get_number() +74 | | }; + | |______^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:67:5 + --> $DIR/unnecessary_operation.rs:75:5 | -67 | FooString { s: String::from("blah"), }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `String::from("blah");` +75 | / FooString { +76 | | s: String::from("blah"), +77 | | }; + | |______^ help: replace it with: `String::from("blah");` error: aborting due to 20 previous errors diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index a3d8f5e337c..f048df6e39b 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,13 +1,13 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:23:17 + --> $DIR/unnecessary_ref.rs:20:17 | -23 | let inner = (&outer).inner; +20 | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer.inner` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:20:8 + --> $DIR/unnecessary_ref.rs:17:8 | -20 | #[deny(clippy::ref_in_deref)] +17 | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 85982d75494..a1e43e493b7 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,16 +1,16 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:27:15 + --> $DIR/unneeded_field_pattern.rs:23:15 | -27 | Foo { a: _, b: 0, .. } => {} +23 | Foo { a: _, b: 0, .. } => {}, | ^^^^ | = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` = help: Try with `Foo { b: 0, .. }` error: All the struct fields are matched to a wildcard pattern, consider using `..`. - --> $DIR/unneeded_field_pattern.rs:29:9 + --> $DIR/unneeded_field_pattern.rs:25:9 | -29 | Foo { a: _, b: _, c: _ } => {} +25 | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Try with `Foo { .. }` instead diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index b5ab6937d95..83372a2a5a7 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,33 +1,33 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:17:16 + --> $DIR/unreadable_literal.rs:24:16 | -17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:17:30 + --> $DIR/unreadable_literal.rs:24:30 | -17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:17:51 + --> $DIR/unreadable_literal.rs:24:51 | -17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:17:63 + --> $DIR/unreadable_literal.rs:24:63 | -17 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:19:19 + --> $DIR/unreadable_literal.rs:26:19 | -19 | let bad_sci = 1.123456e1; +26 | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` error: aborting due to 5 previous errors diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index f4bb93735d7..3b285208978 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -1,21 +1,21 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell` - --> $DIR/unsafe_removed_from_name.rs:17:1 + --> $DIR/unsafe_removed_from_name.rs:14:1 | -17 | use std::cell::{UnsafeCell as TotallySafeCell}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +14 | use std::cell::UnsafeCell as TotallySafeCell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` - --> $DIR/unsafe_removed_from_name.rs:19:1 + --> $DIR/unsafe_removed_from_name.rs:16:1 | -19 | use std::cell::UnsafeCell as TotallySafeCellAgain; +16 | use std::cell::UnsafeCell as TotallySafeCellAgain; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` - --> $DIR/unsafe_removed_from_name.rs:33:1 + --> $DIR/unsafe_removed_from_name.rs:30:1 | -33 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; +30 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 329dfacd43b..f7b9b361502 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,42 +1,42 @@ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:21:5 + --> $DIR/unused_io_amount.rs:17:5 | -21 | try!(s.write(b"test")); +17 | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-io-amount` implied by `-D warnings` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:23:5 + --> $DIR/unused_io_amount.rs:19:5 | -23 | try!(s.read(&mut buf)); +19 | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:28:5 + --> $DIR/unused_io_amount.rs:24:5 | -28 | s.write(b"test")?; +24 | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:30:5 + --> $DIR/unused_io_amount.rs:26:5 | -30 | s.read(&mut buf)?; +26 | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:35:5 + --> $DIR/unused_io_amount.rs:31:5 | -35 | s.write(b"test").unwrap(); +31 | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:37:5 + --> $DIR/unused_io_amount.rs:33:5 | -37 | s.read(&mut buf).unwrap(); +33 | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index 5a31ada902e..cbade54c157 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -1,25 +1,29 @@ error: unused label `'label` - --> $DIR/unused_labels.rs:18:5 + --> $DIR/unused_labels.rs:14:5 | -18 | / 'label: for i in 1..2 { -19 | | if i > 4 { continue } -20 | | } +14 | / 'label: for i in 1..2 { +15 | | if i > 4 { +16 | | continue; +17 | | } +18 | | } | |_____^ | = note: `-D clippy::unused-label` implied by `-D warnings` error: unused label `'a` - --> $DIR/unused_labels.rs:31:5 + --> $DIR/unused_labels.rs:28:5 | -31 | 'a: loop { break } - | ^^^^^^^^^^^^^^^^^^ +28 | / 'a: loop { +29 | | break; +30 | | } + | |_____^ error: unused label `'same_label_in_two_fns` - --> $DIR/unused_labels.rs:42:5 + --> $DIR/unused_labels.rs:41:5 | -42 | / 'same_label_in_two_fns: loop { -43 | | let _ = 1; -44 | | } +41 | / 'same_label_in_two_fns: loop { +42 | | let _ = 1; +43 | | } | |_____^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index f5b788c16a7..e590cfc91aa 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -1,21 +1,21 @@ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:26:14 + --> $DIR/unused_lt.rs:23:14 | -26 | fn unused_lt<'a>(x: u8) { +23 | fn unused_lt<'a>(x: u8) {} | ^^ | = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:30:25 + --> $DIR/unused_lt.rs:25:25 | -30 | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { +25 | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:60:10 + --> $DIR/unused_lt.rs:50:10 | -60 | fn x<'a>(&self) {} +50 | fn x<'a>(&self) {} | ^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index ffdeeb5307f..2432b7970f6 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,16 +1,16 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:15:47 + --> $DIR/unwrap_or.rs:13:47 | -15 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); +13 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` | = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:20:10 + --> $DIR/unwrap_or.rs:17:47 | -20 | .unwrap_or("Fail".to_string()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` +17 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index b71c7a9a4c5..0904db2e942 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,39 +1,39 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:21 + --> $DIR/use_self.rs:20:21 | -23 | fn new() -> Foo { +20 | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:13 + --> $DIR/use_self.rs:21:13 | -24 | Foo {} +21 | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:26:22 + --> $DIR/use_self.rs:23:22 | -26 | fn test() -> Foo { +23 | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:27:13 + --> $DIR/use_self.rs:24:13 | -27 | Foo::new() +24 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:32:25 + --> $DIR/use_self.rs:29:25 | -32 | fn default() -> Foo { +29 | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:33:13 + --> $DIR/use_self.rs:30:13 | -33 | Foo::new() +30 | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition @@ -75,56 +75,56 @@ error: unnecessary structure name repetition error: unnecessary structure name repetition --> $DIR/use_self.rs:108:28 | -108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:108:46 | -108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) { +108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:111:20 + --> $DIR/use_self.rs:110:20 | -111 | fn vals(_: Bad) -> Bad { +110 | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:111:28 + --> $DIR/use_self.rs:110:28 | -111 | fn vals(_: Bad) -> Bad { +110 | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:112:13 + --> $DIR/use_self.rs:111:13 | -112 | Bad::default() +111 | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:117:23 + --> $DIR/use_self.rs:116:23 | -117 | type Output = Bad; +116 | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:119:27 + --> $DIR/use_self.rs:118:27 | -119 | fn mul(self, rhs: Bad) -> Bad { +118 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:119:35 + --> $DIR/use_self.rs:118:35 | -119 | fn mul(self, rhs: Bad) -> Bad { +118 | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:213:54 + --> $DIR/use_self.rs:210:56 | -213 | fn bad(foos: &[Self]) -> impl Iterator { - | ^^^ help: use the applicable keyword: `Self` +210 | fn bad(foos: &[Self]) -> impl Iterator { + | ^^^ help: use the applicable keyword: `Self` error: aborting due to 21 previous errors diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 8092119470e..c844a8cd75b 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -1,33 +1,33 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:27:5 + --> $DIR/used_underscore_binding.rs:23:5 | -27 | _foo + 1 +23 | _foo + 1 | ^^^^ | = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:32:20 + --> $DIR/used_underscore_binding.rs:28:20 | -32 | println!("{}", _foo); +28 | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:33:16 + --> $DIR/used_underscore_binding.rs:29:16 | -33 | assert_eq!(_foo, _foo); +29 | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:33:22 + --> $DIR/used_underscore_binding.rs:29:22 | -33 | assert_eq!(_foo, _foo); +29 | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:46:5 + --> $DIR/used_underscore_binding.rs:42:5 | -46 | s._underscore_field += 1; +42 | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 8e45facf587..397ec7108d4 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,73 +1,73 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:43:18 + --> $DIR/useless_asref.rs:50:18 | -43 | foo_rstr(rstr.as_ref()); +50 | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here - --> $DIR/useless_asref.rs:13:9 + --> $DIR/useless_asref.rs:10:9 | -13 | #![deny(clippy::useless_asref)] +10 | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:45:20 + --> $DIR/useless_asref.rs:52:20 | -45 | foo_rslice(rslice.as_ref()); +52 | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:49:21 + --> $DIR/useless_asref.rs:56:21 | -49 | foo_mrslice(mrslice.as_mut()); +56 | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:51:20 + --> $DIR/useless_asref.rs:58:20 | -51 | foo_rslice(mrslice.as_ref()); +58 | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:58:20 + --> $DIR/useless_asref.rs:65:20 | -58 | foo_rslice(rrrrrslice.as_ref()); +65 | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:60:18 + --> $DIR/useless_asref.rs:67:18 | -60 | foo_rstr(rrrrrstr.as_ref()); +67 | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:65:21 + --> $DIR/useless_asref.rs:72:21 | -65 | foo_mrslice(mrrrrrslice.as_mut()); +72 | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:67:20 + --> $DIR/useless_asref.rs:74:20 | -67 | foo_rslice(mrrrrrslice.as_ref()); +74 | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:70:16 + --> $DIR/useless_asref.rs:77:16 | -70 | foo_rrrrmr((&&&&MoreRef).as_ref()); +77 | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:116:13 + --> $DIR/useless_asref.rs:127:13 | -116 | foo_mrt(mrt.as_mut()); +127 | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:118:12 + --> $DIR/useless_asref.rs:129:12 | -118 | foo_rt(mrt.as_ref()); +129 | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` error: aborting due to 11 previous errors diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 6b82b105b05..54d18fbf2e1 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,16 +1,22 @@ error: useless lint attribute - --> $DIR/useless_attribute.rs:15:1 + --> $DIR/useless_attribute.rs:12:1 | -15 | #[allow(dead_code)] +12 | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` | = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute - --> $DIR/useless_attribute.rs:16:1 + --> $DIR/useless_attribute.rs:13:1 | -16 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] +13 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` -error: aborting due to 2 previous errors +error: useless lint attribute + --> $DIR/useless_attribute.rs:14:1 + | +14 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` + +error: aborting due to 3 previous errors diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index e4649eab5ec..94e9bcdd2a7 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,39 +1,39 @@ error: useless use of `vec!` - --> $DIR/vec.rs:34:14 + --> $DIR/vec.rs:30:14 | -34 | on_slice(&vec![]); +30 | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` | = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:37:14 + --> $DIR/vec.rs:33:14 | -37 | on_slice(&vec![1, 2]); +33 | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:40:14 + --> $DIR/vec.rs:36:14 | -40 | on_slice(&vec ![1, 2]); - | ^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` +36 | on_slice(&vec![1, 2]); + | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:43:14 + --> $DIR/vec.rs:39:14 | -43 | on_slice(&vec!(1, 2)); +39 | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:46:14 + --> $DIR/vec.rs:42:14 | -46 | on_slice(&vec![1; 2]); +42 | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:59:14 + --> $DIR/vec.rs:55:14 | -59 | for a in vec![1, 2, 3] { +55 | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: aborting due to 6 previous errors diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index b166e8bacb5..57cfa14a392 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -1,114 +1,114 @@ error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:19:5 + --> $DIR/while_loop.rs:15:5 | -19 | / loop { -20 | | if let Some(_x) = y { -21 | | let _v = 1; -22 | | } else { -23 | | break -24 | | } -25 | | } +15 | / loop { +16 | | if let Some(_x) = y { +17 | | let _v = 1; +18 | | } else { +19 | | break; +20 | | } +21 | | } | |_____^ help: try: `while let Some(_x) = y { .. }` | = note: `-D clippy::while-let-loop` implied by `-D warnings` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:32:5 + --> $DIR/while_loop.rs:29:5 | -32 | / loop { -33 | | match y { -34 | | Some(_x) => true, -35 | | None => break -36 | | }; -37 | | } +29 | / loop { +30 | | match y { +31 | | Some(_x) => true, +32 | | None => break, +33 | | }; +34 | | } | |_____^ help: try: `while let Some(_x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:38:5 + --> $DIR/while_loop.rs:35:5 | -38 | / loop { -39 | | let x = match y { -40 | | Some(x) => x, -41 | | None => break +35 | / loop { +36 | | let x = match y { +37 | | Some(x) => x, +38 | | None => break, ... | -44 | | let _str = "foo"; -45 | | } +41 | | let _str = "foo"; +42 | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:46:5 + --> $DIR/while_loop.rs:43:5 | -46 | / loop { -47 | | let x = match y { -48 | | Some(x) => x, -49 | | None => break, +43 | / loop { +44 | | let x = match y { +45 | | Some(x) => x, +46 | | None => break, ... | -52 | | { let _b = "foobar"; } -53 | | } +53 | | } +54 | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:68:5 + --> $DIR/while_loop.rs:71:5 | -68 | / loop { -69 | | let (e, l) = match "".split_whitespace().next() { -70 | | Some(word) => (word.is_empty(), word.len()), -71 | | None => break +71 | / loop { +72 | | let (e, l) = match "".split_whitespace().next() { +73 | | Some(word) => (word.is_empty(), word.len()), +74 | | None => break, ... | -74 | | let _ = (e, l); -75 | | } +77 | | let _ = (e, l); +78 | | } | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:78:33 + --> $DIR/while_loop.rs:81:33 | -78 | while let Option::Some(x) = iter.next() { +81 | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` | = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:83:25 + --> $DIR/while_loop.rs:86:25 | -83 | while let Some(x) = iter.next() { +86 | while let Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:88:25 + --> $DIR/while_loop.rs:91:25 | -88 | while let Some(_) = iter.next() {} +91 | while let Some(_) = iter.next() {} | ^^^^^^^^^^^ help: try: `for _ in iter { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:128:5 + --> $DIR/while_loop.rs:134:5 | -128 | / loop { -129 | | let _ = match iter.next() { -130 | | Some(ele) => ele, -131 | | None => break -132 | | }; -133 | | loop {} -134 | | } +134 | / loop { +135 | | let _ = match iter.next() { +136 | | Some(ele) => ele, +137 | | None => break, +138 | | }; +139 | | loop {} +140 | | } | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` error: empty `loop {}` detected. You may want to either use `panic!()` or add `std::thread::sleep(..);` to the loop body. - --> $DIR/while_loop.rs:133:9 + --> $DIR/while_loop.rs:139:9 | -133 | loop {} +139 | loop {} | ^^^^^^^ | = note: `-D clippy::empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:193:29 + --> $DIR/while_loop.rs:197:29 | -193 | while let Some(v) = y.next() { // use a for loop here +197 | while let Some(v) = y.next() { | ^^^^^^^^ help: try: `for v in y { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:220:26 + --> $DIR/while_loop.rs:225:26 | -220 | while let Some(..) = values.iter().next() { +225 | while let Some(..) = values.iter().next() { | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` error: aborting due to 12 previous errors diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 2aa66c32049..40c21902bf2 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,88 +1,88 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:39:79 + --> $DIR/write_literal.rs:36:79 | -39 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); +36 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::write-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/write_literal.rs:40:32 + --> $DIR/write_literal.rs:37:32 | -40 | write!(&mut v, "Hello {}", "world"); +37 | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:44 + --> $DIR/write_literal.rs:38:44 | -41 | writeln!(&mut v, "Hello {} {}", world, "world"); +38 | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:42:34 + --> $DIR/write_literal.rs:39:34 | -42 | writeln!(&mut v, "Hello {}", "world"); +39 | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:43:38 + --> $DIR/write_literal.rs:40:38 | -43 | writeln!(&mut v, "10 / 4 is {}", 2.5); +40 | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:44:36 + --> $DIR/write_literal.rs:41:36 | -44 | writeln!(&mut v, "2 + 1 = {}", 3); +41 | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/write_literal.rs:49:33 + --> $DIR/write_literal.rs:46:33 | -49 | writeln!(&mut v, "{0} {1}", "hello", "world"); +46 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:49:42 + --> $DIR/write_literal.rs:46:42 | -49 | writeln!(&mut v, "{0} {1}", "hello", "world"); +46 | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:50:33 + --> $DIR/write_literal.rs:47:33 | -50 | writeln!(&mut v, "{1} {0}", "hello", "world"); +47 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:50:42 + --> $DIR/write_literal.rs:47:42 | -50 | writeln!(&mut v, "{1} {0}", "hello", "world"); +47 | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:53:41 + --> $DIR/write_literal.rs:50:43 | -53 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); - | ^^^^^^^ +50 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:53:54 + --> $DIR/write_literal.rs:50:58 | -53 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world"); - | ^^^^^^^ +50 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:54:41 + --> $DIR/write_literal.rs:51:43 | -54 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); - | ^^^^^^^ +51 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:54:54 + --> $DIR/write_literal.rs:51:58 | -54 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world"); - | ^^^^^^^ +51 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index dd7f223c517..8d2ad1b4d97 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,27 +1,27 @@ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:22:5 + --> $DIR/write_with_newline.rs:19:5 | -22 | write!(&mut v, "Hello/n"); +19 | write!(&mut v, "Hello/n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::write-with-newline` implied by `-D warnings` error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:23:5 + --> $DIR/write_with_newline.rs:20:5 | -23 | write!(&mut v, "Hello {}/n", "world"); +20 | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:24:5 + --> $DIR/write_with_newline.rs:21:5 | -24 | write!(&mut v, "Hello {} {}/n", "world", "#2"); +21 | write!(&mut v, "Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:25:5 + --> $DIR/write_with_newline.rs:22:5 | -25 | write!(&mut v, "{}/n", 1265); +22 | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 3e6ec33623a..5943dfa09b1 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,15 +1,15 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:21:5 + --> $DIR/writeln_empty_string.rs:18:5 | -21 | writeln!(&mut v, ""); +18 | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` | = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:24:5 + --> $DIR/writeln_empty_string.rs:21:5 | -24 | writeln!(&mut suggestion, ""); +21 | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` error: aborting due to 2 previous errors diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index ee0f4f8a143..fa97713ed78 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -1,75 +1,75 @@ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:31:17 + --> $DIR/wrong_self_convention.rs:26:17 | -31 | fn from_i32(self) {} +26 | fn from_i32(self) {} | ^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:37:21 + --> $DIR/wrong_self_convention.rs:32:21 | -37 | pub fn from_i64(self) {} +32 | pub fn from_i64(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:50:15 + --> $DIR/wrong_self_convention.rs:44:15 | -50 | fn as_i32(self) {} +44 | fn as_i32(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:52:17 + --> $DIR/wrong_self_convention.rs:46:17 | -52 | fn into_i32(&self) {} +46 | fn into_i32(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:54:15 + --> $DIR/wrong_self_convention.rs:48:15 | -54 | fn is_i32(self) {} +48 | fn is_i32(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:56:15 + --> $DIR/wrong_self_convention.rs:50:15 | -56 | fn to_i32(self) {} +50 | fn to_i32(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:58:17 + --> $DIR/wrong_self_convention.rs:52:17 | -58 | fn from_i32(self) {} +52 | fn from_i32(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:60:19 + --> $DIR/wrong_self_convention.rs:54:19 | -60 | pub fn as_i64(self) {} +54 | pub fn as_i64(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:61:21 + --> $DIR/wrong_self_convention.rs:55:21 | -61 | pub fn into_i64(&self) {} +55 | pub fn into_i64(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:62:19 + --> $DIR/wrong_self_convention.rs:56:19 | -62 | pub fn is_i64(self) {} +56 | pub fn is_i64(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:63:19 + --> $DIR/wrong_self_convention.rs:57:19 | -63 | pub fn to_i64(self) {} +57 | pub fn to_i64(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:64:21 + --> $DIR/wrong_self_convention.rs:58:21 | -64 | pub fn from_i64(self) {} +58 | pub fn from_i64(self) {} | ^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 0c24a08a634..312392050c5 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -1,59 +1,59 @@ error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:17:15 + --> $DIR/zero_div_zero.rs:13:15 | -17 | let nan = 0.0 / 0.0; +13 | let nan = 0.0 / 0.0; | ^^^^^^^^^ | = note: #[deny(clippy::eq_op)] on by default error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:17:15 + --> $DIR/zero_div_zero.rs:13:15 | -17 | let nan = 0.0 / 0.0; +13 | let nan = 0.0 / 0.0; | ^^^^^^^^^ | = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:18:19 + --> $DIR/zero_div_zero.rs:14:19 | -18 | let f64_nan = 0.0 / 0.0f64; +14 | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:18:19 + --> $DIR/zero_div_zero.rs:14:19 | -18 | let f64_nan = 0.0 / 0.0f64; +14 | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:19:25 + --> $DIR/zero_div_zero.rs:15:25 | -19 | let other_f64_nan = 0.0f64 / 0.0; +15 | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:19:25 + --> $DIR/zero_div_zero.rs:15:25 | -19 | let other_f64_nan = 0.0f64 / 0.0; +15 | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:20:28 + --> $DIR/zero_div_zero.rs:16:28 | -20 | let one_more_f64_nan = 0.0f64/0.0f64; - | ^^^^^^^^^^^^^ +16 | let one_more_f64_nan = 0.0f64 / 0.0f64; + | ^^^^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:20:28 + --> $DIR/zero_div_zero.rs:16:28 | -20 | let one_more_f64_nan = 0.0f64/0.0f64; - | ^^^^^^^^^^^^^ +16 | let one_more_f64_nan = 0.0f64 / 0.0f64; + | ^^^^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 7a0c8e70b22..15b27c7c0ad 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -1,15 +1,15 @@ error: `0 as *const _` detected. Consider using `ptr::null()` - --> $DIR/zero_ptr.rs:16:13 + --> $DIR/zero_ptr.rs:12:13 | -16 | let x = 0 as *const usize; +12 | let x = 0 as *const usize; | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::zero-ptr` implied by `-D warnings` error: `0 as *mut _` detected. Consider using `ptr::null_mut()` - --> $DIR/zero_ptr.rs:17:13 + --> $DIR/zero_ptr.rs:13:13 | -17 | let y = 0 as *mut f64; +13 | let y = 0 as *mut f64; | ^^^^^^^^^^^^^ error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 0a6e568f07ef11ab24fd47cdaaa1719f910952e8 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 10 Dec 2018 15:46:01 +0100 Subject: test formatting: don't format tests/ui/formatting.rs --- ci/base-tests.sh | 2 +- tests/ui/formatting.rs | 97 ++++++++++++++++++++++++++-------------------- tests/ui/formatting.stderr | 85 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 135 insertions(+), 49 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index dfc5ad99e0c..a60e36f2981 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -35,7 +35,7 @@ set +ex # some lints are sensitive to formatting, exclude some files needs_formatting=false -for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do +for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/formatting.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true done diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 875a74d2508..88f6e497d12 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -7,74 +7,82 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + + + + #![warn(clippy::all)] #![allow(unused_variables)] #![allow(unused_assignments)] #![allow(clippy::if_same_then_else)] #![allow(clippy::deref_addrof)] -fn foo() -> bool { - true -} +fn foo() -> bool { true } fn main() { // weird `else if` formatting: - if foo() {} - if foo() {} + if foo() { + } if foo() { + } - let _ = { - // if as the last expression + let _ = { // if as the last expression let _ = 0; - if foo() {} if foo() { - } else { + } if foo() { + } + else { } }; - let _ = { - // if in the middle of a block - if foo() {} + let _ = { // if in the middle of a block if foo() { - } else { + } if foo() { + } + else { } let _ = 0; }; if foo() { - } else if foo() { - // the span of the above error should continue here + } else + if foo() { // the span of the above error should continue here } if foo() { - } else if foo() { - // the span of the above error should continue here + } + else + if foo() { // the span of the above error should continue here } // those are ok: - if foo() {} - if foo() {} + if foo() { + } + if foo() { + } if foo() { } else if foo() { } if foo() { - } else if foo() { + } + else if foo() { } if foo() { - } else if foo() { } + else if + foo() {} // weird op_eq formatting: let mut a = 42; - a = -35; - a = *&191; + a =- 35; + a =* &191; let mut b = true; - b = !false; + b =! false; // those are ok: a = -35; @@ -83,30 +91,37 @@ fn main() { // possible missing comma in an array let _ = &[ - -1, - -2, - -3 // <= no comma here - -4, - -5, - -6, + -1, -2, -3 // <= no comma here + -4, -5, -6 ]; let _ = &[ - -1, - -2, - -3 // <= no comma here - *4, - -5, - -6, + -1, -2, -3 // <= no comma here + *4, -5, -6 ]; // those are ok: - let _ = &[-1, -2, -3, -4, -5, -6]; - let _ = &[-1, -2, -3, -4, -5, -6]; - let _ = &[1 + 2, 3 + 4, 5 + 6]; + let _ = &[ + -1, -2, -3, + -4, -5, -6 + ]; + let _ = &[ + -1, -2, -3, + -4, -5, -6, + ]; + let _ = &[ + 1 + 2, 3 + + 4, 5 + 6, + ]; // don't lint for bin op without unary equiv // issue 3244 - vec![1 / 2]; + vec![ + 1 + / 2, + ]; // issue 3396 - vec![true | false]; + vec![ + true + | false, + ]; } diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 84749b6caac..e1620b22125 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,19 +1,90 @@ +error: this looks like an `else if` but the `else` is missing + --> $DIR/formatting.rs:25:6 + | +25 | } if foo() { + | ^ + | + = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` + = note: to remove this lint, add the missing `else` or add a new line before the second `if` + +error: this looks like an `else if` but the `else` is missing + --> $DIR/formatting.rs:32:10 + | +32 | } if foo() { + | ^ + | + = note: to remove this lint, add the missing `else` or add a new line before the second `if` + +error: this looks like an `else if` but the `else` is missing + --> $DIR/formatting.rs:40:10 + | +40 | } if foo() { + | ^ + | + = note: to remove this lint, add the missing `else` or add a new line before the second `if` + +error: this is an `else if` but the formatting might hide it + --> $DIR/formatting.rs:49:6 + | +49 | } else + | ______^ +50 | | if foo() { // the span of the above error should continue here + | |____^ + | + = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` + +error: this is an `else if` but the formatting might hide it + --> $DIR/formatting.rs:54:6 + | +54 | } + | ______^ +55 | | else +56 | | if foo() { // the span of the above error should continue here + | |____^ + | + = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` + +error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` + --> $DIR/formatting.rs:81:6 + | +81 | a =- 35; + | ^^^^ + | + = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` + = note: to remove this lint, use either `-=` or `= -` + +error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` + --> $DIR/formatting.rs:82:6 + | +82 | a =* &191; + | ^^^^ + | + = note: to remove this lint, use either `*=` or `= *` + +error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` + --> $DIR/formatting.rs:85:6 + | +85 | b =! false; + | ^^^^ + | + = note: to remove this lint, use either `!=` or `= !` + error: possibly missing a comma here - --> $DIR/formatting.rs:88:11 + --> $DIR/formatting.rs:94:19 | -88 | -3 // <= no comma here - | ^ +94 | -1, -2, -3 // <= no comma here + | ^ | = note: `-D clippy::possible-missing-comma` implied by `-D warnings` = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:96:11 + --> $DIR/formatting.rs:98:19 | -96 | -3 // <= no comma here - | ^ +98 | -1, -2, -3 // <= no comma here + | ^ | = note: to remove this lint, add a comma or write the expr in a single line -error: aborting due to 2 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 04e251f623b7880fe2c0bd1ae247c52bc69b597a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 10 Dec 2018 22:04:27 +0100 Subject: readme: tool lints are stable now --- README.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/README.md b/README.md index 49c0a1f1546..928c961c017 100644 --- a/README.md +++ b/README.md @@ -149,21 +149,7 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: Note: `deny` produces errors instead of warnings. -Note: To use the new `clippy::lint_name` syntax, a recent compiler has to be used -currently. If you want to compile your code with the stable toolchain you can use a `cfg_attr` to -activate the `tool_lints` feature: -```rust -#![cfg_attr(feature = "cargo-clippy", allow(clippy::lint_name))] -``` - -For this to work you have to use Clippy on the nightly toolchain: `cargo +nightly clippy`. If you -want to use Clippy with the stable toolchain, you can stick to the old unscoped method to -enable/disable Clippy lints until `tool_lints` are stable: -```rust -#![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))] -``` - -If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W lint_name` will run it with that enabled. On newer compilers you may need to use `clippy::lint_name` instead. +If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A clippy::lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. ## License -- cgit 1.4.1-3-g733a5 From d4da776ea77618a8b50f25b40224678065e27510 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 10 Dec 2018 22:22:57 +0100 Subject: Also add note about using -W clippy::lint_group --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 928c961c017..3e35f092559 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: Note: `deny` produces errors instead of warnings. -If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A clippy::lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. +If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A clippy::lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` ## License -- cgit 1.4.1-3-g733a5 From 0c93e4cdb2f6f41fdfd484f5b529454707850570 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 10 Dec 2018 22:30:16 +0100 Subject: s/clippy/Clippy in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e35f092559..f42771709fb 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ script: # etc. ``` -It might happen that clippy is not available for a certain nightly release. -In this case you can try to conditionally install clippy from the git repo. +It might happen that Clippy is not available for a certain nightly release. +In this case you can try to conditionally install Clippy from the git repo. ```yaml language: rust @@ -149,7 +149,7 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: Note: `deny` produces errors instead of warnings. -If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A clippy::lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` +If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` ## License -- cgit 1.4.1-3-g733a5 From f1d5194e3d9c07279811fc4f6a704b5185c8c9f4 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 11 Dec 2018 00:59:59 +0100 Subject: tests: revert some changs and add further rustfmt::skip attributes. --- tests/ui/cast.rs | 3 ++- tests/ui/identity_op.rs | 3 ++- tests/ui/identity_op.stderr | 32 ++++++++++++++++---------------- tests/ui/implicit_return.rs | 6 ++++-- tests/ui/implicit_return.stderr | 24 ++++++++++++------------ tests/ui/reference.rs | 3 ++- tests/ui/reference.stderr | 26 +++++++++++++------------- tests/ui/useless_attribute.rs | 4 +++- tests/ui/useless_attribute.stderr | 8 +------- tests/ui/vec.rs | 4 ++-- tests/ui/vec.stderr | 2 +- 11 files changed, 58 insertions(+), 57 deletions(-) diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 45e878e9d80..51e41b70172 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -51,7 +51,8 @@ fn main() { false as bool; &1i32 as &i32; // Should not trigger - let v = vec![1]; + #[rustfmt::skip] + let v = vec!(1); &v as &[i32]; 1.0 as f64; 1 as u64; diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index c8874250a04..299cd2a6786 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -18,6 +18,7 @@ const ZERO: i64 = 0; clippy::double_parens )] #[warn(clippy::identity_op)] +#[rustfmt::skip] fn main() { let x = 0; @@ -28,7 +29,7 @@ fn main() { 1 + x; x - ZERO; //no error, as we skip lookups (for now) x | (0); - (ZERO) | x; //no error, as we skip lookups (for now) + ((ZERO)) | x; //no error, as we skip lookups (for now) x * 1; 1 * x; diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index e2b6efa7dbe..19846b5ecdf 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,51 +1,51 @@ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:24:5 + --> $DIR/identity_op.rs:25:5 | -24 | x + 0; +25 | x + 0; | ^^^^^ | = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:25:5 + --> $DIR/identity_op.rs:26:5 | -25 | x + (1 - 1); +26 | x + (1 - 1); | ^^^^^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:27:5 + --> $DIR/identity_op.rs:28:5 | -27 | 0 + x; +28 | 0 + x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:30:5 + --> $DIR/identity_op.rs:31:5 | -30 | x | (0); +31 | x | (0); | ^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:33:5 + --> $DIR/identity_op.rs:34:5 | -33 | x * 1; +34 | x * 1; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:34:5 + --> $DIR/identity_op.rs:35:5 | -34 | 1 * x; +35 | 1 * x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:40:5 + --> $DIR/identity_op.rs:41:5 | -40 | -1 & x; +41 | -1 & x; | ^^^^^^ error: the operation is ineffective. Consider reducing it to `u` - --> $DIR/identity_op.rs:43:5 + --> $DIR/identity_op.rs:44:5 | -43 | u & 255; +44 | u & 255; | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 3bff92cf492..6188835e555 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -27,10 +27,11 @@ fn test_if_block() -> bool { } #[allow(clippy::match_bool)] +#[rustfmt::skip] fn test_match(x: bool) -> bool { match x { true => false, - false => true, + false => { true }, } } @@ -42,7 +43,8 @@ fn test_loop() -> bool { } fn test_closure() { - let _ = || true; + #[rustfmt::skip] + let _ = || { true }; let _ = || true; } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 26474aab4b8..b2feec3f57a 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -19,33 +19,33 @@ error: missing return statement | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:32:17 + --> $DIR/implicit_return.rs:33:17 | -32 | true => false, +33 | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:33:18 + --> $DIR/implicit_return.rs:34:20 | -33 | false => true, - | ^^^^ help: add `return` as shown: `return true` +34 | false => { true }, + | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:40:9 + --> $DIR/implicit_return.rs:41:9 | -40 | break true; +41 | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:45:16 + --> $DIR/implicit_return.rs:47:18 | -45 | let _ = || true; - | ^^^^ help: add `return` as shown: `return true` +47 | let _ = || { true }; + | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:46:16 + --> $DIR/implicit_return.rs:48:16 | -46 | let _ = || true; +48 | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: aborting due to 8 previous errors diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index 583829aae41..bab0c21ffd9 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -37,7 +37,8 @@ fn main() { let b = *(&a); - let b = *(&a); + #[rustfmt::skip] + let b = *((&a)); let b = *&&a; diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index c09a31e2d8a..7665e0d1932 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -31,39 +31,39 @@ error: immediately dereferencing a reference | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:40:13 + --> $DIR/reference.rs:41:13 | -40 | let b = *(&a); - | ^^^^^ help: try this: `a` +41 | let b = *((&a)); + | ^^^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:42:13 + --> $DIR/reference.rs:43:13 | -42 | let b = *&&a; +43 | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:44:14 + --> $DIR/reference.rs:45:14 | -44 | let b = **&aref; +45 | let b = **&aref; | ^^^^^^ help: try this: `aref` error: immediately dereferencing a reference - --> $DIR/reference.rs:48:14 + --> $DIR/reference.rs:49:14 | -48 | let b = **&&a; +49 | let b = **&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:52:17 + --> $DIR/reference.rs:53:17 | -52 | let y = *&mut x; +53 | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference - --> $DIR/reference.rs:59:18 + --> $DIR/reference.rs:60:18 | -59 | let y = **&mut &mut x; +60 | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` error: aborting due to 11 previous errors diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 4ee6520443d..2d7a9ae04d1 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -11,7 +11,9 @@ #[allow(dead_code)] #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] -#[cfg_attr(feature = "cargo-clippy", allow(dead_code))] +#[rustfmt::skip] +#[cfg_attr(feature = "cargo-clippy", + allow(dead_code))] #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 54d18fbf2e1..2dde3fd7eac 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -12,11 +12,5 @@ error: useless lint attribute 13 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` -error: useless lint attribute - --> $DIR/useless_attribute.rs:14:1 - | -14 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index a7ccda375bf..f795c11ec5b 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -35,8 +35,8 @@ fn main() { on_slice(&vec![1, 2]); on_slice(&[1, 2]); - - on_slice(&vec![1, 2]); + #[rustfmt::skip] + on_slice(&vec!(1, 2)); on_slice(&[1, 2]); on_slice(&vec![1; 2]); diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 94e9bcdd2a7..ccd6a7d25c7 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -21,7 +21,7 @@ error: useless use of `vec!` error: useless use of `vec!` --> $DIR/vec.rs:39:14 | -39 | on_slice(&vec![1, 2]); +39 | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` -- cgit 1.4.1-3-g733a5 From 625ca772b59da2355589d634f402725c495ab5ab Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 11 Dec 2018 01:31:04 +0100 Subject: tests: fix more cases where rustfmt would have hurt the tests --- tests/ui/formatting.rs | 4 - tests/ui/formatting.stderr | 46 +++---- tests/ui/option_map_unit_fn.rs | 75 ++++------- tests/ui/option_map_unit_fn.stderr | 254 ++++++++++++++----------------------- tests/ui/result_map_unit_fn.rs | 70 ++++------ tests/ui/result_map_unit_fn.stderr | 248 ++++++++++++++---------------------- 6 files changed, 262 insertions(+), 435 deletions(-) diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 88f6e497d12..3bea98acf2f 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -7,10 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - - #![warn(clippy::all)] #![allow(unused_variables)] #![allow(unused_assignments)] diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index e1620b22125..7399a0d4549 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,87 +1,87 @@ error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:25:6 + --> $DIR/formatting.rs:21:6 | -25 | } if foo() { +21 | } if foo() { | ^ | = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:32:10 + --> $DIR/formatting.rs:28:10 | -32 | } if foo() { +28 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:40:10 + --> $DIR/formatting.rs:36:10 | -40 | } if foo() { +36 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:49:6 + --> $DIR/formatting.rs:45:6 | -49 | } else +45 | } else | ______^ -50 | | if foo() { // the span of the above error should continue here +46 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:54:6 + --> $DIR/formatting.rs:50:6 | -54 | } +50 | } | ______^ -55 | | else -56 | | if foo() { // the span of the above error should continue here +51 | | else +52 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:81:6 + --> $DIR/formatting.rs:77:6 | -81 | a =- 35; +77 | a =- 35; | ^^^^ | = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:82:6 + --> $DIR/formatting.rs:78:6 | -82 | a =* &191; +78 | a =* &191; | ^^^^ | = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:85:6 + --> $DIR/formatting.rs:81:6 | -85 | b =! false; +81 | b =! false; | ^^^^ | = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:94:19 + --> $DIR/formatting.rs:90:19 | -94 | -1, -2, -3 // <= no comma here +90 | -1, -2, -3 // <= no comma here | ^ | = note: `-D clippy::possible-missing-comma` implied by `-D warnings` = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:98:19 + --> $DIR/formatting.rs:94:19 | -98 | -1, -2, -3 // <= no comma here +94 | -1, -2, -3 // <= no comma here | ^ | = note: to remove this lint, add a comma or write the expr in a single line diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index 5200ff694a0..db473f9b41e 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -31,12 +31,12 @@ impl HasOption { value + 1 } } - +#[rustfmt::skip] fn option_map_unit_fn() { let x = HasOption { field: Some(10) }; x.field.map(plus_one); - let _: Option<()> = x.field.map(do_nothing); + let _ : Option<()> = x.field.map(do_nothing); x.field.map(do_nothing); @@ -45,68 +45,47 @@ fn option_map_unit_fn() { x.field.map(diverge); let captured = 10; - if let Some(value) = x.field { - do_nothing(value + captured) - }; - let _: Option<()> = x.field.map(|value| do_nothing(value + captured)); + if let Some(value) = x.field { do_nothing(value + captured) }; + let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_option_nothing(value + captured)); - x.field.map(|value| { - x.do_option_plus_one(value + captured); - }); + x.field.map(|value| { x.do_option_plus_one(value + captured); }); - x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { - do_nothing(value + captured); - }); + x.field.map(|value| { do_nothing(value + captured) }); - x.field.map(|value| { - do_nothing(value + captured); - }); + x.field.map(|value| { do_nothing(value + captured); }); + + x.field.map(|value| { { do_nothing(value + captured); } }); - x.field.map(|value| diverge(value + captured)); x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { - diverge(value + captured); - }); + x.field.map(|value| { diverge(value + captured) }); + + x.field.map(|value| { diverge(value + captured); }); + + x.field.map(|value| { { diverge(value + captured); } }); - x.field.map(|value| { - diverge(value + captured); - }); x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| { - let y = plus_one(value + captured); - }); + x.field.map(|value| { plus_one(value + captured) }); + x.field.map(|value| { let y = plus_one(value + captured); }); - x.field.map(|value| { - plus_one(value + captured); - }); + x.field.map(|value| { plus_one(value + captured); }); - x.field.map(|value| { - plus_one(value + captured); - }); + x.field.map(|value| { { plus_one(value + captured); } }); - x.field.map(|ref value| do_nothing(value + captured)); - x.field.map(|value| { - do_nothing(value); - do_nothing(value) - }); + x.field.map(|ref value| { do_nothing(value + captured) }); - x.field.map(|value| { - if value > 0 { - do_nothing(value); - do_nothing(value) - } - }); + + x.field.map(|value| { do_nothing(value); do_nothing(value) }); + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases @@ -114,13 +93,9 @@ fn option_map_unit_fn() { do_nothing(value); do_nothing(value) }); - x.field.map(|value| { - do_nothing(value); - do_nothing(value); - }); + x.field.map(|value| { do_nothing(value); do_nothing(value); }); - // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let - // variable name for them + // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let variable name for them Some(42).map(diverge); "12".parse::().ok().map(diverge); Some(plus_one(1)).map(do_nothing); diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 86fb9e75d8f..5df5ae7d918 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -25,243 +25,183 @@ error: called `map(f)` on an Option value where `f` is a unit function | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:53:5 + --> $DIR/option_map_unit_fn.rs:51:5 | -53 | x.field.map(|value| x.do_option_nothing(value + captured)); +51 | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:55:5 + --> $DIR/option_map_unit_fn.rs:53:5 | -55 | x.field.map(|value| { - | _____^ - | |_____| - | || -56 | || x.do_option_plus_one(value + captured); -57 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` - | |_______| - | +53 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:59:5 + --> $DIR/option_map_unit_fn.rs:56:5 | -59 | x.field.map(|value| do_nothing(value + captured)); +56 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:61:5 + --> $DIR/option_map_unit_fn.rs:58:5 | -61 | x.field.map(|value| do_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +58 | x.field.map(|value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:63:5 + --> $DIR/option_map_unit_fn.rs:60:5 | -63 | x.field.map(|value| { - | _____^ - | |_____| - | || -64 | || do_nothing(value + captured); -65 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` - | |_______| - | +60 | x.field.map(|value| { do_nothing(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:67:5 + --> $DIR/option_map_unit_fn.rs:62:5 | -67 | x.field.map(|value| { - | _____^ - | |_____| - | || -68 | || do_nothing(value + captured); -69 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` - | |_______| - | +62 | x.field.map(|value| { { do_nothing(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:71:5 + --> $DIR/option_map_unit_fn.rs:65:5 | -71 | x.field.map(|value| diverge(value + captured)); +65 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:73:5 + --> $DIR/option_map_unit_fn.rs:67:5 | -73 | x.field.map(|value| diverge(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +67 | x.field.map(|value| { diverge(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:75:5 + --> $DIR/option_map_unit_fn.rs:69:5 | -75 | x.field.map(|value| { - | _____^ - | |_____| - | || -76 | || diverge(value + captured); -77 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { diverge(value + captured); }` - | |_______| - | +69 | x.field.map(|value| { diverge(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:79:5 + --> $DIR/option_map_unit_fn.rs:71:5 | -79 | x.field.map(|value| { - | _____^ - | |_____| - | || -80 | || diverge(value + captured); -81 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { diverge(value + captured); }` - | |_______| - | +71 | x.field.map(|value| { { diverge(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:85:5 + --> $DIR/option_map_unit_fn.rs:76:5 | -85 | x.field.map(|value| { - | _____^ - | |_____| - | || -86 | || let y = plus_one(value + captured); -87 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` - | |_______| - | +76 | x.field.map(|value| { let y = plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:89:5 + --> $DIR/option_map_unit_fn.rs:78:5 | -89 | x.field.map(|value| { - | _____^ - | |_____| - | || -90 | || plus_one(value + captured); -91 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` - | |_______| - | +78 | x.field.map(|value| { plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:93:5 + --> $DIR/option_map_unit_fn.rs:80:5 | -93 | x.field.map(|value| { - | _____^ - | |_____| - | || -94 | || plus_one(value + captured); -95 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` - | |_______| - | +80 | x.field.map(|value| { { plus_one(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:97:5 + --> $DIR/option_map_unit_fn.rs:83:5 | -97 | x.field.map(|ref value| do_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +83 | x.field.map(|ref value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:99:5 - | -99 | x.field.map(|value| { - | _____^ - | |_____| - | || -100 | || do_nothing(value); -101 | || do_nothing(value) -102 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | + --> $DIR/option_map_unit_fn.rs:86:5 + | +86 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:104:5 - | -104 | x.field.map(|value| { - | _____^ - | |_____| - | || -105 | || if value > 0 { -106 | || do_nothing(value); -107 | || do_nothing(value) -108 | || } -109 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | + --> $DIR/option_map_unit_fn.rs:88:5 + | +88 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:113:5 - | -113 | x.field.map(|value| { - | _____^ - | |_____| - | || -114 | || do_nothing(value); -115 | || do_nothing(value) -116 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | + --> $DIR/option_map_unit_fn.rs:92:5 + | +92 | x.field.map(|value| { + | _____^ + | |_____| + | || +93 | || do_nothing(value); +94 | || do_nothing(value) +95 | || }); + | ||______^- help: try this: `if let Some(value) = x.field { ... }` + | |_______| + | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:117:5 - | -117 | x.field.map(|value| { - | _____^ - | |_____| - | || -118 | || do_nothing(value); -119 | || do_nothing(value); -120 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | + --> $DIR/option_map_unit_fn.rs:96:5 + | +96 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:124:5 - | -124 | Some(42).map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(42) { diverge(...) }` + --> $DIR/option_map_unit_fn.rs:99:5 + | +99 | Some(42).map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:125:5 + --> $DIR/option_map_unit_fn.rs:100:5 | -125 | "12".parse::().ok().map(diverge); +100 | "12".parse::().ok().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:126:5 + --> $DIR/option_map_unit_fn.rs:101:5 | -126 | Some(plus_one(1)).map(do_nothing); +101 | Some(plus_one(1)).map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:130:5 + --> $DIR/option_map_unit_fn.rs:105:5 | -130 | y.map(do_nothing); +105 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_y) = y { do_nothing(...) }` diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index 043b3efd45e..3d731c9b350 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -33,6 +33,7 @@ impl HasResult { } } +#[rustfmt::skip] fn result_map_unit_fn() { let x = HasResult { field: Ok(10) }; @@ -46,68 +47,47 @@ fn result_map_unit_fn() { x.field.map(diverge); let captured = 10; - if let Ok(value) = x.field { - do_nothing(value + captured) - }; + if let Ok(value) = x.field { do_nothing(value + captured) }; let _: Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_result_nothing(value + captured)); - x.field.map(|value| { - x.do_result_plus_one(value + captured); - }); + x.field.map(|value| { x.do_result_plus_one(value + captured); }); - x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| do_nothing(value + captured)); - x.field.map(|value| { - do_nothing(value + captured); - }); + x.field.map(|value| { do_nothing(value + captured) }); - x.field.map(|value| { - do_nothing(value + captured); - }); + x.field.map(|value| { do_nothing(value + captured); }); + + x.field.map(|value| { { do_nothing(value + captured); } }); - x.field.map(|value| diverge(value + captured)); x.field.map(|value| diverge(value + captured)); - x.field.map(|value| { - diverge(value + captured); - }); + x.field.map(|value| { diverge(value + captured) }); + + x.field.map(|value| { diverge(value + captured); }); + + x.field.map(|value| { { diverge(value + captured); } }); - x.field.map(|value| { - diverge(value + captured); - }); x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| plus_one(value + captured)); - x.field.map(|value| { - let y = plus_one(value + captured); - }); + x.field.map(|value| { plus_one(value + captured) }); + x.field.map(|value| { let y = plus_one(value + captured); }); - x.field.map(|value| { - plus_one(value + captured); - }); + x.field.map(|value| { plus_one(value + captured); }); - x.field.map(|value| { - plus_one(value + captured); - }); + x.field.map(|value| { { plus_one(value + captured); } }); - x.field.map(|ref value| do_nothing(value + captured)); - x.field.map(|value| { - do_nothing(value); - do_nothing(value) - }); + x.field.map(|ref value| { do_nothing(value + captured) }); - x.field.map(|value| { - if value > 0 { - do_nothing(value); - do_nothing(value) - } - }); + + x.field.map(|value| { do_nothing(value); do_nothing(value) }); + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases @@ -115,13 +95,9 @@ fn result_map_unit_fn() { do_nothing(value); do_nothing(value) }); - x.field.map(|value| { - do_nothing(value); - do_nothing(value); - }); + x.field.map(|value| { do_nothing(value); do_nothing(value); }); - // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let - // variable name for them + // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let variable name for them let res: Result = Ok(42).map(diverge); "12".parse::().map(diverge); diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 1ef107a5000..3f5231dcc06 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:42:5 + --> $DIR/result_map_unit_fn.rs:43:5 | -42 | x.field.map(do_nothing); +43 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -9,151 +9,148 @@ error: called `map(f)` on an Result value where `f` is a unit function = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:44:5 + --> $DIR/result_map_unit_fn.rs:45:5 | -44 | x.field.map(do_nothing); +45 | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:46:5 + --> $DIR/result_map_unit_fn.rs:47:5 | -46 | x.field.map(diverge); +47 | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:54:5 + --> $DIR/result_map_unit_fn.rs:53:5 | -54 | x.field.map(|value| x.do_result_nothing(value + captured)); +53 | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:56:5 + --> $DIR/result_map_unit_fn.rs:55:5 | -56 | x.field.map(|value| { - | _____^ - | |_____| - | || -57 | || x.do_result_plus_one(value + captured); -58 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` - | |_______| - | +55 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:60:5 + --> $DIR/result_map_unit_fn.rs:58:5 | -60 | x.field.map(|value| do_nothing(value + captured)); +58 | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:62:5 + --> $DIR/result_map_unit_fn.rs:60:5 | -62 | x.field.map(|value| do_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +60 | x.field.map(|value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:64:5 + --> $DIR/result_map_unit_fn.rs:62:5 | -64 | x.field.map(|value| { - | _____^ - | |_____| - | || -65 | || do_nothing(value + captured); -66 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` - | |_______| - | +62 | x.field.map(|value| { do_nothing(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:68:5 + --> $DIR/result_map_unit_fn.rs:64:5 | -68 | x.field.map(|value| { - | _____^ - | |_____| - | || -69 | || do_nothing(value + captured); -70 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` - | |_______| - | +64 | x.field.map(|value| { { do_nothing(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:72:5 + --> $DIR/result_map_unit_fn.rs:67:5 | -72 | x.field.map(|value| diverge(value + captured)); +67 | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:74:5 + --> $DIR/result_map_unit_fn.rs:69:5 | -74 | x.field.map(|value| diverge(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +69 | x.field.map(|value| { diverge(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:76:5 + --> $DIR/result_map_unit_fn.rs:71:5 | -76 | x.field.map(|value| { - | _____^ - | |_____| - | || -77 | || diverge(value + captured); -78 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` - | |_______| - | +71 | x.field.map(|value| { diverge(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:73:5 + | +73 | x.field.map(|value| { { diverge(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:78:5 + | +78 | x.field.map(|value| { let y = plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:80:5 | -80 | x.field.map(|value| { - | _____^ - | |_____| - | || -81 | || diverge(value + captured); -82 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` - | |_______| - | +80 | x.field.map(|value| { plus_one(value + captured); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:86:5 + --> $DIR/result_map_unit_fn.rs:82:5 | -86 | x.field.map(|value| { - | _____^ - | |_____| - | || -87 | || let y = plus_one(value + captured); -88 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` - | |_______| - | +82 | x.field.map(|value| { { plus_one(value + captured); } }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:85:5 + | +85 | x.field.map(|ref value| { do_nothing(value + captured) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` + +error: called `map(f)` on an Result value where `f` is a unit closure + --> $DIR/result_map_unit_fn.rs:88:5 + | +88 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:90:5 | -90 | x.field.map(|value| { - | _____^ - | |_____| - | || -91 | || plus_one(value + captured); -92 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` - | |_______| - | +90 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:94:5 @@ -162,90 +159,33 @@ error: called `map(f)` on an Result value where `f` is a unit closure | _____^ | |_____| | || -95 | || plus_one(value + captured); -96 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` +95 | || do_nothing(value); +96 | || do_nothing(value) +97 | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` | |_______| | error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:98:5 | -98 | x.field.map(|ref value| do_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- +98 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:100:5 - | -100 | x.field.map(|value| { - | _____^ - | |_____| - | || -101 | || do_nothing(value); -102 | || do_nothing(value) -103 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` - | |_______| - | - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:105:5 - | -105 | x.field.map(|value| { - | _____^ - | |_____| - | || -106 | || if value > 0 { -107 | || do_nothing(value); -108 | || do_nothing(value) -109 | || } -110 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` - | |_______| - | - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:114:5 - | -114 | x.field.map(|value| { - | _____^ - | |_____| - | || -115 | || do_nothing(value); -116 | || do_nothing(value) -117 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` - | |_______| - | - -error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:118:5 - | -118 | x.field.map(|value| { - | _____^ - | |_____| - | || -119 | || do_nothing(value); -120 | || do_nothing(value); -121 | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` - | |_______| - | + | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:126:5 + --> $DIR/result_map_unit_fn.rs:102:5 | -126 | "12".parse::().map(diverge); +102 | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:132:5 + --> $DIR/result_map_unit_fn.rs:108:5 | -132 | y.map(do_nothing); +108 | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(_y) = y { do_nothing(...) }` -- cgit 1.4.1-3-g733a5 From c6505aa1604e0b5378305b95e8d89f99d0da0031 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 11 Dec 2018 08:28:25 +0200 Subject: Fix write_with_newline escaping false positive Fixes #3514 --- clippy_lints/src/write.rs | 36 ++++++++++++++++++++++++++++-------- tests/ui/write_with_newline.rs | 5 +++++ tests/ui/write_with_newline.stderr | 8 +++++++- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 440ab7433cc..416ba4ca18d 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -206,10 +206,7 @@ impl EarlyLintPass for Pass { } else if mac.node.path == "print" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 { - if fmtstr.ends_with("\\n") && - // don't warn about strings with several `\n`s (#3126) - fmtstr.matches("\\n").count() == 1 - { + if check_newlines(&fmtstr) { span_lint( cx, PRINT_WITH_NEWLINE, @@ -221,10 +218,7 @@ impl EarlyLintPass for Pass { } } else if mac.node.path == "write" { if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 { - if fmtstr.ends_with("\\n") && - // don't warn about strings with several `\n`s (#3126) - fmtstr.matches("\\n").count() == 1 - { + if check_newlines(&fmtstr) { span_lint( cx, WRITE_WITH_NEWLINE, @@ -375,3 +369,29 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - } } } + +// Checks if `s` constains a single newline that terminates it +fn check_newlines(s: &str) -> bool { + if s.len() < 2 { + return false; + } + + let bytes = s.as_bytes(); + if bytes[bytes.len() - 2] != b'\\' || bytes[bytes.len() - 1] != b'n' { + return false; + } + + let mut escaping = false; + for (index, &byte) in bytes.iter().enumerate() { + if escaping { + if byte == b'n' { + return index == bytes.len() - 1; + } + escaping = false; + } else if byte == b'\\' { + escaping = true; + } + } + + false +} diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index e9fcff0b3dd..e8bea5f7675 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -38,4 +38,9 @@ fn main() { write!(&mut v, "Hello {} {}\n\n", "world", "#2"); writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 writeln!(&mut v, "\nbla\n\n"); // #3126 + + // Escaping + write!(&mut v, "\\n"); // #3514 + write!(&mut v, "\\\n"); + write!(&mut v, "\\\\n"); } diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index dd7f223c517..30ca5e30b85 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -24,5 +24,11 @@ error: using `write!()` with a format string that ends in a single newline, cons 25 | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead + --> $DIR/write_with_newline.rs:44:5 + | +44 | write!(&mut v, "//n"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 804729cdaa109e55746ec509a253891cb64648e4 Mon Sep 17 00:00:00 2001 From: Maxence Frenette Date: Tue, 11 Dec 2018 05:10:41 -0500 Subject: Remove dead link in CONTRIBUTING.md --- CONTRIBUTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ce9512a80dc..b5548bdd732 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,6 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Running test suite](#running-test-suite) * [Running rustfmt](#running-rustfmt) * [Testing manually](#testing-manually) - * [Linting Clippy with your local changes](#linting-clippy-with-your-local-changes) * [How Clippy works](#how-clippy-works) * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) * [Issue and PR Triage](#issue-and-pr-triage) -- cgit 1.4.1-3-g733a5 From ee2abc36a33bbbb6d84f823cb5e09b4603af1f32 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 11 Dec 2018 19:37:43 +0100 Subject: Add 'CamelCase' to doc_valid_idents --- clippy_lints/src/utils/conf.rs | 1 + tests/ui/doc.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 63e2db7506c..35fcc08b518 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -137,6 +137,7 @@ define_Conf! { "iOS", "macOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", + "CamelCase", ] => Vec), /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have (too_many_arguments_threshold, "too_many_arguments_threshold", 7 => u64), diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index dde1a471e6e..8935e3f01d5 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -174,3 +174,6 @@ fn issue_1920() {} /// Not ok: http://www.unicode.org/ /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels fn issue_1832() {} + +/// Ok: CamelCase (It should not be surrounded by backticks) +fn issue_2395() {} -- cgit 1.4.1-3-g733a5 From 36266b3e6cd3d58716cd1fcd21f05148d322d204 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 11 Dec 2018 20:50:55 +0100 Subject: test reformatting: revert more questionable changes done by rustfmt and add #[rustfmt::skip] --- tests/ui/decimal_literal_representation.rs | 7 +++--- tests/ui/decimal_literal_representation.stderr | 20 ++++++++-------- tests/ui/implicit_hasher.rs | 4 ++-- tests/ui/implicit_hasher.stderr | 4 ++-- tests/ui/swap.rs | 5 ++-- tests/ui/swap.stderr | 32 +++++++++++++------------- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index c196b27a3a6..d7823b0b819 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -9,9 +9,9 @@ #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] +#[rustfmt::skip] fn main() { - let good = ( - // Hex: + let good = ( // Hex: 127, // 0x7F 256, // 0x100 511, // 0x1FF @@ -21,8 +21,7 @@ fn main() { 61_683, // 0xF0F3 2_131_750_925, // 0x7F0F_F00D ); - let bad = ( - // Hex: + let bad = ( // Hex: 32_773, // 0x8005 65_280, // 0xFF00 2_131_750_927, // 0x7F0F_F00F diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index 42f8a6e3bc5..c68a25f3dc3 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,33 +1,33 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:26:9 + --> $DIR/decimal_literal_representation.rs:25:9 | -26 | 32_773, // 0x8005 +25 | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` | = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:27:9 + --> $DIR/decimal_literal_representation.rs:26:9 | -27 | 65_280, // 0xFF00 +26 | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:28:9 + --> $DIR/decimal_literal_representation.rs:27:9 | -28 | 2_131_750_927, // 0x7F0F_F00F +27 | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:29:9 + --> $DIR/decimal_literal_representation.rs:28:9 | -29 | 2_147_483_647, // 0x7FFF_FFFF +28 | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:30:9 + --> $DIR/decimal_literal_representation.rs:29:9 | -30 | 4_042_322_160, // 0xF0F0_F0F0 +29 | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index ddcd8bcd755..acd5a52ff38 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -85,8 +85,8 @@ macro_rules! gen { pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} }; } - -gen!(impl ); +#[rustfmt::skip] +gen!(impl); gen!(fn bar); // When the macro is in a different file, the suggestion spans can't be combined properly diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 58b823e6ca1..35306e77aec 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -96,8 +96,8 @@ error: impl for `HashMap` should be generalized over different hashers 77 | impl Foo for HashMap { | ^^^^^^^^^^^^^ ... -89 | gen!(impl ); - | ------------ in this macro invocation +89 | gen!(impl); + | ----------- in this macro invocation help: consider adding a type parameter | 77 | impl Foo for HashMap { diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index e9f227d47a0..20fa9c87574 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -39,6 +39,7 @@ fn vec() { foo.swap(0, 1); } +#[rustfmt::skip] fn main() { array(); slice(); @@ -50,7 +51,7 @@ fn main() { a = b; b = a; -; let t = a; + ; let t = a; a = b; b = t; @@ -59,7 +60,7 @@ fn main() { c.0 = a; a = c.0; -; let t = c.0; + ; let t = c.0; c.0 = a; a = t; } diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 12d012442ad..c8e803c4afd 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -25,42 +25,42 @@ error: this looks like you are swapping elements of `foo` manually | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:53:6 + --> $DIR/swap.rs:54:7 | -53 | ; let t = a; - | ______^ -54 | | a = b; -55 | | b = t; +54 | ; let t = a; + | _______^ +55 | | a = b; +56 | | b = t; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:62:6 + --> $DIR/swap.rs:63:7 | -62 | ; let t = c.0; - | ______^ -63 | | c.0 = a; -64 | | a = t; +63 | ; let t = c.0; + | _______^ +64 | | c.0 = a; +65 | | a = t; | |_________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:50:5 + --> $DIR/swap.rs:51:5 | -50 | / a = b; -51 | | b = a; +51 | / a = b; +52 | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: `-D clippy::almost-swapped` implied by `-D warnings` = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:59:5 + --> $DIR/swap.rs:60:5 | -59 | / c.0 = a; -60 | | a = c.0; +60 | / c.0 = a; +61 | | a = c.0; | |___________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? -- cgit 1.4.1-3-g733a5 From c4c9d9fc62eb244c0f219cfbf23f19b9240c2827 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 23 Nov 2018 08:18:23 +0100 Subject: Add suggestion for explicit_write lint --- clippy_lints/src/explicit_write.rs | 40 +++++++++++++++--------- clippy_lints/src/lib.rs | 1 + tests/ui/explicit_write.rs | 4 +++ tests/ui/explicit_write.stderr | 62 +++++++++++++++++++++++--------------- 4 files changed, 68 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 94bd0ab209c..65fa6aeec0b 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -10,8 +10,8 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::opt_def_id; -use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint}; +use crate::syntax::ast::LitKind; +use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; /// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be @@ -51,6 +51,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if unwrap_args.len() > 0; if let ExprKind::MethodCall(ref write_fun, _, ref write_args) = unwrap_args[0].node; + // Obtain the string that should be printed + if let ExprKind::Call(_, ref output_args) = write_args[1].node; + if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node; + if let ExprKind::Array(ref string_exprs) = output_string_expr.node; + if let ExprKind::Lit(ref lit) = string_exprs[0].node; + if let LitKind::Str(ref write_output, _) = lit.node; if write_fun.ident.name == "write_fmt"; // match calls to std::io::stdout() / std::io::stderr () if write_args.len() > 0; @@ -81,29 +87,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } else { "" }; + + // We need to remove the last trailing newline from the string because the + // underlying `fmt::write` function doesn't know wether `println!` or `print!` was + // used. + let mut write_output: String = write_output.to_string(); + if write_output.ends_with('\n') { + write_output.truncate(write_output.len() - 1) + } if let Some(macro_name) = calling_macro { - span_lint( + span_lint_and_sugg( cx, EXPLICIT_WRITE, expr.span, &format!( - "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", + "use of `{}!({}(), ...).unwrap()`", macro_name, - dest_name, - prefix, - macro_name.replace("write", "print") - ) + dest_name + ), + "try this", + format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()) ); } else { - span_lint( + span_lint_and_sugg( cx, EXPLICIT_WRITE, expr.span, - &format!( - "use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", - dest_name, - prefix, - ) + &format!("use of `{}().write_fmt(...).unwrap()`", dest_name), + "try this", + format!("{}print!(\"{}\")", prefix, write_output.escape_default()) ); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ee41c632077..a862d774174 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -14,6 +14,7 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] +#![feature(str_escape)] #![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 10a4bca9f49..01a63b3a95f 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -27,6 +27,10 @@ fn main() { writeln!(std::io::stderr(), "test").unwrap(); std::io::stdout().write_fmt(format_args!("test")).unwrap(); std::io::stderr().write_fmt(format_args!("test")).unwrap(); + + // including newlines + writeln!(std::io::stdout(), "test\ntest").unwrap(); + writeln!(std::io::stderr(), "test\ntest").unwrap(); } // these should not warn, different destination { diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 171bf312a9b..6d318d09e58 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,40 +1,52 @@ -error: use of `write!(stdout(), ...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:24:9 +error: use of `write!(stdout(), ...).unwrap()` + --> $DIR/explicit_write.rs:28:9 | -24 | write!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +28 | write!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` | = note: `-D clippy::explicit-write` implied by `-D warnings` -error: use of `write!(stderr(), ...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:25:9 +error: use of `write!(stderr(), ...).unwrap()` + --> $DIR/explicit_write.rs:29:9 | -25 | write!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +29 | write!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` -error: use of `writeln!(stdout(), ...).unwrap()`. Consider using `println!` instead - --> $DIR/explicit_write.rs:26:9 +error: use of `writeln!(stdout(), ...).unwrap()` + --> $DIR/explicit_write.rs:30:9 | -26 | writeln!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +30 | writeln!(std::io::stdout(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` -error: use of `writeln!(stderr(), ...).unwrap()`. Consider using `eprintln!` instead - --> $DIR/explicit_write.rs:27:9 +error: use of `writeln!(stderr(), ...).unwrap()` + --> $DIR/explicit_write.rs:31:9 | -27 | writeln!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +31 | writeln!(std::io::stderr(), "test").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` -error: use of `stdout().write_fmt(...).unwrap()`. Consider using `print!` instead - --> $DIR/explicit_write.rs:28:9 +error: use of `stdout().write_fmt(...).unwrap()` + --> $DIR/explicit_write.rs:32:9 | -28 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +32 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` -error: use of `stderr().write_fmt(...).unwrap()`. Consider using `eprint!` instead - --> $DIR/explicit_write.rs:29:9 +error: use of `stderr().write_fmt(...).unwrap()` + --> $DIR/explicit_write.rs:33:9 + | +33 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` + +error: use of `writeln!(stdout(), ...).unwrap()` + --> $DIR/explicit_write.rs:36:9 + | +36 | writeln!(std::io::stdout(), "test/ntest").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` + +error: use of `writeln!(stderr(), ...).unwrap()` + --> $DIR/explicit_write.rs:37:9 | -29 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +37 | writeln!(std::io::stderr(), "test/ntest").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From 7e7a33c72695bae3316bf8b211e4bfb698ed7686 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 23 Nov 2018 21:29:27 +0100 Subject: Check array lengths to prevent OOB access --- clippy_lints/src/explicit_write.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 65fa6aeec0b..e2b643c4de6 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -52,9 +52,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprKind::MethodCall(ref write_fun, _, ref write_args) = unwrap_args[0].node; // Obtain the string that should be printed + if write_args.len() > 1; if let ExprKind::Call(_, ref output_args) = write_args[1].node; + if output_args.len() > 0; if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node; if let ExprKind::Array(ref string_exprs) = output_string_expr.node; + if string_exprs.len() > 0; if let ExprKind::Lit(ref lit) = string_exprs[0].node; if let LitKind::Str(ref write_output, _) = lit.node; if write_fun.ident.name == "write_fmt"; -- cgit 1.4.1-3-g733a5 From 5f007a88b4d650068525d4300aa9d773a572de11 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 24 Nov 2018 12:17:43 +0100 Subject: Extract method --- clippy_lints/src/explicit_write.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index e2b643c4de6..996dc126ec1 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -51,15 +51,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if unwrap_args.len() > 0; if let ExprKind::MethodCall(ref write_fun, _, ref write_args) = unwrap_args[0].node; - // Obtain the string that should be printed - if write_args.len() > 1; - if let ExprKind::Call(_, ref output_args) = write_args[1].node; - if output_args.len() > 0; - if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node; - if let ExprKind::Array(ref string_exprs) = output_string_expr.node; - if string_exprs.len() > 0; - if let ExprKind::Lit(ref lit) = string_exprs[0].node; - if let LitKind::Str(ref write_output, _) = lit.node; if write_fun.ident.name == "write_fmt"; // match calls to std::io::stdout() / std::io::stderr () if write_args.len() > 0; @@ -94,7 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // We need to remove the last trailing newline from the string because the // underlying `fmt::write` function doesn't know wether `println!` or `print!` was // used. - let mut write_output: String = write_output.to_string(); + let mut write_output: String = write_output_string(write_args).unwrap(); if write_output.ends_with('\n') { write_output.truncate(write_output.len() - 1) } @@ -125,3 +116,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } } + +// Extract the output string from the given `write_args`. +fn write_output_string(write_args: &HirVec) -> Option { + if_chain! { + // Obtain the string that should be printed + if write_args.len() > 1; + if let ExprKind::Call(_, ref output_args) = write_args[1].node; + if output_args.len() > 0; + if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node; + if let ExprKind::Array(ref string_exprs) = output_string_expr.node; + if string_exprs.len() > 0; + if let ExprKind::Lit(ref lit) = string_exprs[0].node; + if let LitKind::Str(ref write_output, _) = lit.node; + then { + return Some(write_output.to_string()) + } + } + None +} -- cgit 1.4.1-3-g733a5 From 9a6216ed05e353825a712c265923993b8b19d887 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 29 Nov 2018 08:15:44 +0100 Subject: Address review feedback * Fix typo * Handle None value instead of using `unwrap()` * `pop()` instead of `x.truncate(x.len() - 1)` --- clippy_lints/src/explicit_write.rs | 78 +++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 996dc126ec1..79c4c5f0530 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -83,35 +83,61 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }; // We need to remove the last trailing newline from the string because the - // underlying `fmt::write` function doesn't know wether `println!` or `print!` was + // underlying `fmt::write` function doesn't know whether `println!` or `print!` was // used. - let mut write_output: String = write_output_string(write_args).unwrap(); - if write_output.ends_with('\n') { - write_output.truncate(write_output.len() - 1) - } - if let Some(macro_name) = calling_macro { - span_lint_and_sugg( - cx, - EXPLICIT_WRITE, - expr.span, - &format!( - "use of `{}!({}(), ...).unwrap()`", - macro_name, - dest_name - ), - "try this", - format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()) - ); + if let Some(mut write_output) = write_output_string(write_args) { + if write_output.ends_with('\n') { + write_output.pop(); + } + + if let Some(macro_name) = calling_macro { + span_lint_and_sugg( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}!({}(), ...).unwrap()`", + macro_name, + dest_name + ), + "try this", + format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()) + ); + } else { + span_lint_and_sugg( + cx, + EXPLICIT_WRITE, + expr.span, + &format!("use of `{}().write_fmt(...).unwrap()`", dest_name), + "try this", + format!("{}print!(\"{}\")", prefix, write_output.escape_default()) + ); + } } else { - span_lint_and_sugg( - cx, - EXPLICIT_WRITE, - expr.span, - &format!("use of `{}().write_fmt(...).unwrap()`", dest_name), - "try this", - format!("{}print!(\"{}\")", prefix, write_output.escape_default()) - ); + // We don't have a proper suggestion + if let Some(macro_name) = calling_macro { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!( + "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead", + macro_name, + dest_name, + prefix, + macro_name.replace("write", "print") + ) + ); + } else { + span_lint( + cx, + EXPLICIT_WRITE, + expr.span, + &format!("use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix), + ); + } } + } } } -- cgit 1.4.1-3-g733a5 From 752724546a664e0fe3c2315161336d99da41c2a9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 29 Nov 2018 22:17:40 +0100 Subject: Make suggestion Applicability::MachineApplicable --- clippy_lints/src/explicit_write.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 79c4c5f0530..8c3c8461504 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -7,6 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use crate::rustc_errors::Applicability; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; @@ -101,7 +102,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { dest_name ), "try this", - format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()) + format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()), + Applicability::MachineApplicable ); } else { span_lint_and_sugg( @@ -110,7 +112,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, &format!("use of `{}().write_fmt(...).unwrap()`", dest_name), "try this", - format!("{}print!(\"{}\")", prefix, write_output.escape_default()) + format!("{}print!(\"{}\")", prefix, write_output.escape_default()), + Applicability::MachineApplicable ); } } else { -- cgit 1.4.1-3-g733a5 From 499aad1e04d4388a059b636093f836117bdba5df Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 30 Nov 2018 07:25:55 +0100 Subject: cargo fmt and remove stabilized feature --- clippy_lints/src/explicit_write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 8c3c8461504..a0db3ae8df3 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc_errors::Applicability; use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; +use crate::rustc_errors::Applicability; use crate::syntax::ast::LitKind; use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; -- cgit 1.4.1-3-g733a5 From 194acaf8e725619ed350ced85c480909003111d6 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 12 Dec 2018 07:33:23 +0100 Subject: Update .stderr after rebase --- tests/ui/explicit_write.stderr | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 6d318d09e58..1a11dbc169b 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,51 +1,51 @@ error: use of `write!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:28:9 + --> $DIR/explicit_write.rs:24:9 | -28 | write!(std::io::stdout(), "test").unwrap(); +24 | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` | = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:29:9 + --> $DIR/explicit_write.rs:25:9 | -29 | write!(std::io::stderr(), "test").unwrap(); +25 | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:30:9 + --> $DIR/explicit_write.rs:26:9 | -30 | writeln!(std::io::stdout(), "test").unwrap(); +26 | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:31:9 + --> $DIR/explicit_write.rs:27:9 | -31 | writeln!(std::io::stderr(), "test").unwrap(); +27 | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:32:9 + --> $DIR/explicit_write.rs:28:9 | -32 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); +28 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:33:9 + --> $DIR/explicit_write.rs:29:9 | -33 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); +29 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:36:9 + --> $DIR/explicit_write.rs:32:9 | -36 | writeln!(std::io::stdout(), "test/ntest").unwrap(); +32 | writeln!(std::io::stdout(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:37:9 + --> $DIR/explicit_write.rs:33:9 | -37 | writeln!(std::io::stderr(), "test/ntest").unwrap(); +33 | writeln!(std::io::stderr(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From bcbbb4d09b2f474614134730e84afad04d2d8e48 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 11 Dec 2018 15:06:41 +0900 Subject: new_without_default, partialeq_ne_impl: Use span_lint_node Fixes #2892, fixes #3199 --- clippy_lints/src/new_without_default.rs | 8 +++++--- clippy_lints/src/partialeq_ne_impl.rs | 13 ++++++++----- tests/ui/new_without_default.rs | 14 ++++++++++++++ tests/ui/partialeq_ne_impl.rs | 8 ++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 7b838fdee95..86c345b025c 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -17,7 +17,7 @@ use crate::rustc_errors::Applicability; use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; -use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then}; +use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_node_and_then}; use if_chain::if_chain; /// **What it does:** Checks for types with a `fn new() -> Self` method and no @@ -165,9 +165,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then( + span_lint_node_and_then( cx, NEW_WITHOUT_DEFAULT_DERIVE, + id, impl_item.span, &format!( "you should consider deriving a `Default` implementation for `{}`", @@ -183,9 +184,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { ); }); } else { - span_lint_and_then( + span_lint_node_and_then( cx, NEW_WITHOUT_DEFAULT, + id, impl_item.span, &format!( "you should consider adding a `Default` implementation for `{}`", diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 70c93c5978b..02935cf773d 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -10,7 +10,7 @@ use crate::rustc::hir::*; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; -use crate::utils::{is_automatically_derived, span_lint}; +use crate::utils::{is_automatically_derived, span_lint_node}; use if_chain::if_chain; /// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. @@ -56,10 +56,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { then { for impl_item in impl_items { if impl_item.ident.name == "ne" { - span_lint(cx, - PARTIALEQ_NE_IMPL, - impl_item.span, - "re-implementing `PartialEq::ne` is unnecessary") + span_lint_node( + cx, + PARTIALEQ_NE_IMPL, + impl_item.id.node_id, + impl_item.span, + "re-implementing `PartialEq::ne` is unnecessary", + ); } } } diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index a1818e037a7..2e715a6f8ba 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -139,4 +139,18 @@ impl<'a, T: 'a> OptionRefWrapper<'a, T> { } } +pub struct Allow(Foo); + +impl Allow { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { unimplemented!() } +} + +pub struct AllowDerive; + +impl AllowDerive { + #[allow(clippy::new_without_default_derive)] + pub fn new() -> Self { unimplemented!() } +} + fn main() {} diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index 3f9f91c81b1..fabeee24b30 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -20,4 +20,12 @@ impl PartialEq for Foo { } } +struct Bar; + +impl PartialEq for Bar { + fn eq(&self, _: &Bar) -> bool { true } + #[allow(clippy::partialeq_ne_impl)] + fn ne(&self, _: &Bar) -> bool { false } +} + fn main() {} -- cgit 1.4.1-3-g733a5 From d2e5a8ccf517f19d0c3b2d0274dc50aeddd4a1fa Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 11 Dec 2018 17:31:22 +0900 Subject: Remove obsolete comment --- tests/ui/unused_io_amount.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index a125d0397af..0ec8ce57ad7 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -12,7 +12,7 @@ use std::io; -// FIXME: compiletest doesn't understand errors from macro invocation span + fn try_macro(s: &mut T) -> io::Result<()> { try!(s.write(b"test")); let mut buf = [0u8; 4]; -- cgit 1.4.1-3-g733a5 From 1cfbadb0298f8acf2162b97177f54c654ac6b945 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 7 Dec 2018 11:48:06 +0100 Subject: Fix doc_markdown off by one issue --- clippy_lints/src/doc.rs | 2 +- tests/ui/doc.rs | 4 ++++ tests/ui/doc.stderr | 8 +++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index a3278159ef5..d6c96fa62a9 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -238,7 +238,7 @@ fn check_doc<'a, Events: Iterator)>>( } fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) { - for word in text.split_whitespace() { + for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ // Or even as in `_foo bar_` which is emphasized. diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 8935e3f01d5..c09cacd6be0 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -177,3 +177,7 @@ fn issue_1832() {} /// Ok: CamelCase (It should not be surrounded by backticks) fn issue_2395() {} + +/// An iterator over mycrate::Collection's values. +/// It should not lint a `'static` lifetime in ticks. +fn issue_2210() {} diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index 85c0fd898c7..26ac8103558 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -180,5 +180,11 @@ error: you should put bare URLs between `<`/`>` or make a proper Markdown link 175 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 30 previous errors +error: you should put `mycrate::Collection` between ticks in the documentation + --> $DIR/doc.rs:181:22 + | +181 | /// An iterator over mycrate::Collection's values. + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 31 previous errors -- cgit 1.4.1-3-g733a5 From 7fe39c9c6ec03fd0133d3a9a94572a65ad4e76d9 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 12 Dec 2018 09:17:43 +0100 Subject: fix typo in script --- ci/base-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 56db616cf5b..b523fd3ba31 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -41,7 +41,7 @@ for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/fo rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true done -if [ "${needs_reformatting}" = true] ; then +if [ "${needs_reformatting}" = true ] ; then echo "Tests need reformatting!" exit 2 fi -- cgit 1.4.1-3-g733a5 From 05d07155b72d39d447bff1f5c1e8fb13a1eecd31 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 11 Dec 2018 23:05:43 +0900 Subject: question_mark: Fix applicability --- clippy_lints/src/question_mark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 3a62a3a1526..21f22f151dd 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -84,7 +84,7 @@ impl Pass { expr.span, "replace_it_with", format!("{}?;", receiver_str), - Applicability::MachineApplicable, // snippet + Applicability::MaybeIncorrect, // snippet ); } ) -- cgit 1.4.1-3-g733a5 From 28635ff04be246a0e2d5bcec25b229f17b4f5974 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 11 Dec 2018 23:21:25 +0900 Subject: question_mark: Lint only early returns --- clippy_lints/src/question_mark.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 21f22f151dd..61178ccdd56 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -133,9 +133,13 @@ impl Pass { } } - // Check if the block has an implicit return expression - if let Some(ref ret_expr) = block.expr { - return Some(ret_expr.clone()); + // Check for `return` without a semicolon. + if_chain! { + if block.stmts.len() == 0; + if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.node); + then { + return Some(ret_expr.clone()); + } } None -- cgit 1.4.1-3-g733a5 From eb54c1a9a0e89017bf71a7a78990ff8ab155a4f7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 11 Dec 2018 23:33:23 +0900 Subject: redundant_field_names: Do not trigger on path with type params Fixes #3476 --- clippy_lints/src/redundant_field_names.rs | 5 ++++- tests/ui/redundant_field_names.rs | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 308f0066b69..d8d80f2d128 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -57,7 +57,10 @@ impl EarlyLintPass for RedundantFieldNames { continue; } if let ExprKind::Path(None, path) = &field.expr.node { - if path.segments.len() == 1 && path.segments[0].ident == field.ident { + if path.segments.len() == 1 + && path.segments[0].ident == field.ident + && path.segments[0].args.is_none() + { span_lint_and_sugg( cx, REDUNDANT_FIELD_NAMES, diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 68adba92f8a..3d727ee6e6a 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -68,3 +68,14 @@ fn main() { let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end: end }; } + +fn issue_3476() { + fn foo() { + } + + struct S { + foo: fn(), + } + + S { foo: foo:: }; +} -- cgit 1.4.1-3-g733a5 From eba44e1c67cd08148c7e67ce6255889b7c581b98 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 12 Dec 2018 17:46:52 +0900 Subject: question_mark: Suggest Some(opt?) for if-else --- clippy_lints/src/question_mark.rs | 32 +++++++++++++++++++++++++++++--- tests/ui/question_mark.rs | 11 +++++++++++ tests/ui/question_mark.stderr | 29 ++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 61178ccdd56..057b4850e4f 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -17,7 +17,7 @@ use if_chain::if_chain; use crate::rustc_errors::Applicability; use crate::utils::paths::*; -use crate::utils::{match_def_path, match_type, span_lint_and_then}; +use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for expressions that could be replaced by the question mark operator /// @@ -64,14 +64,40 @@ impl Pass { /// If it matches, it will suggest to use the question mark operator instead fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr) { if_chain! { - if let ExprKind::If(ref if_expr, ref body, _) = expr.node; - if let ExprKind::MethodCall(ref segment, _, ref args) = if_expr.node; + if let ExprKind::If(if_expr, body, else_) = &expr.node; + if let ExprKind::MethodCall(segment, _, args) = &if_expr.node; if segment.ident.name == "is_none"; if Self::expression_returns_none(cx, body); if let Some(subject) = args.get(0); if Self::is_option(cx, subject); then { + if let Some(else_) = else_ { + if_chain! { + if let ExprKind::Block(block, None) = &else_.node; + if block.stmts.len() == 0; + if let Some(block_expr) = &block.expr; + if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr); + then { + span_lint_and_then( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + |db| { + db.span_suggestion_with_applicability( + expr.span, + "replace_it_with", + format!("Some({}?)", Sugg::hir(cx, subject, "..")), + Applicability::MaybeIncorrect, // snippet + ); + } + ) + } + } + return; + } + span_lint_and_then( cx, QUESTION_MARK, diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 7f1d06fbd29..b1edec32eee 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -42,11 +42,22 @@ pub struct SomeStruct { } impl SomeStruct { + #[rustfmt::skip] pub fn func(&self) -> Option { if (self.opt).is_none() { return None; } + if self.opt.is_none() { + return None + } + + let _ = if self.opt.is_none() { + return None; + } else { + self.opt + }; + self.opt } } diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index d3daaaa9270..c9d5538f36f 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -9,12 +9,31 @@ error: this block may be rewritten with the `?` operator = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:46:9 + --> $DIR/question_mark.rs:47:9 | -46 | / if (self.opt).is_none() { -47 | | return None; -48 | | } +47 | / if (self.opt).is_none() { +48 | | return None; +49 | | } | |_________^ help: replace_it_with: `(self.opt)?;` -error: aborting due to 2 previous errors +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:51:9 + | +51 | / if self.opt.is_none() { +52 | | return None +53 | | } + | |_________^ help: replace_it_with: `self.opt?;` + +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:55:17 + | +55 | let _ = if self.opt.is_none() { + | _________________^ +56 | | return None; +57 | | } else { +58 | | self.opt +59 | | }; + | |_________^ help: replace_it_with: `Some(self.opt?)` + +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 591738c35a3ae55ccc6a997aa7d91fc92b641e30 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 12 Dec 2018 10:27:13 +0100 Subject: base-tests: don't print all commands to stdout during the loop --- ci/base-tests.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 56db616cf5b..c05de3a3ea8 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -32,7 +32,7 @@ cargo +nightly fmt --all -- --check #avoid loop spam -set +ex +set +x # make sure tests are formatted # some lints are sensitive to formatting, exclude some files @@ -45,5 +45,4 @@ if [ "${needs_reformatting}" = true] ; then echo "Tests need reformatting!" exit 2 fi - -set -ex +set -x -- cgit 1.4.1-3-g733a5 From 5527edd9569ffcf49236ea031626e39cbb75c52c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Dec 2018 15:37:31 +0100 Subject: Fix rvm/gpg bug in travis osx build --- .travis.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5014a66a79c..eb66112213b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,15 +18,6 @@ env: global: - RUST_BACKTRACE=1 -before_install: - - | - # work-around for issue https://github.com/travis-ci/travis-ci/issues/6307 - # might not be necessary in the future - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - command curl -sSL https://rvm.io/mpapis.asc | gpg --import - - rvm get stable - fi - install: - | if [ -z ${INTEGRATION} ]; then -- cgit 1.4.1-3-g733a5 From 016c996e1610eaed2f47fd9a9396498b8adce047 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 12 Dec 2018 17:17:01 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/56092 fix ui test cast_alignment failure by adding #![feature(rustc_private)] --- tests/ui/cast_alignment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index efc56ea2bbc..77f50b3add2 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -9,8 +9,8 @@ //! Test casts for alignment issues -#![feature(libc)] +#![feature(rustc_private)] extern crate libc; #[warn(clippy::cast_ptr_alignment)] -- cgit 1.4.1-3-g733a5 From 778723630c8237f60299afb98411cdc6129b1e76 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 7 Dec 2018 22:38:45 +0100 Subject: Fix doc_markdown mixed case false positive --- clippy_lints/src/doc.rs | 9 +++++++++ tests/ui/doc.rs | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index d6c96fa62a9..030c56cb81b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -281,6 +281,10 @@ fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) { s != "_" && !s.contains("\\_") && s.contains('_') } + fn has_hyphen(s: &str) -> bool { + s != "-" && s.contains('-') + } + if let Ok(url) = Url::parse(word) { // try to get around the fact that `foo::bar` parses as a valid URL if !url.cannot_be_a_base() { @@ -295,6 +299,11 @@ fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) { } } + // We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343) + if has_underscore(word) && has_hyphen(word) { + return; + } + if has_underscore(word) || word.contains("::") || is_camel_case(word) { span_lint( cx, diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index c09cacd6be0..d4ba83a86f3 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -181,3 +181,7 @@ fn issue_2395() {} /// An iterator over mycrate::Collection's values. /// It should not lint a `'static` lifetime in ticks. fn issue_2210() {} + +/// This should not cause the lint to trigger: +/// #REQ-data-family.lint_partof_exists +fn issue_2343() {} -- cgit 1.4.1-3-g733a5 From ab070508be3fbf02619f5f109ece829243a751e8 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 07:43:13 -0800 Subject: Lint for Vec> - Closes #3530 --- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/types.rs | 65 +++++++++++++++++++++++++++++++++++++++++-- tests/ui/vec_box_sized.rs | 17 +++++++++++ tests/ui/vec_box_sized.stderr | 11 ++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/ui/vec_box_sized.rs create mode 100644 tests/ui/vec_box_sized.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a862d774174..9e3f0a6505d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -766,6 +766,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::UNIT_ARG, types::UNIT_CMP, types::UNNECESSARY_CAST, + types::VEC_BOX_SIZED, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, unused_io_amount::UNUSED_IO_AMOUNT, @@ -931,6 +932,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::TYPE_COMPLEXITY, types::UNIT_ARG, types::UNNECESSARY_CAST, + types::VEC_BOX_SIZED, unused_label::UNUSED_LABEL, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 820f2fdf32d..b85f21ce970 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -24,7 +24,7 @@ use crate::rustc_target::spec::abi::Abi; use crate::rustc_typeck::hir_ty_to_ty; use crate::syntax::ast::{FloatTy, IntTy, UintTy}; use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax::source_map::Span; +use crate::syntax::source_map::{DUMMY_SP, Span}; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, @@ -68,6 +68,33 @@ declare_clippy_lint! { "usage of `Box>`, vector elements are already on the heap" } +/// **What it does:** Checks for use of `Vec>` where T: Sized anywhere in the code. +/// +/// **Why is this bad?** `Vec` already keeps its contents in a separate area on +/// the heap. So if you `Box` its contents, you just add another level of indirection. +/// +/// **Known problems:** Vec> makes sense if T is a large type (see #3530, 1st comment). +/// +/// **Example:** +/// ```rust +/// struct X { +/// values: Vec>, +/// } +/// ``` +/// +/// Better: +/// +/// ```rust +/// struct X { +/// values: Vec, +/// } +/// ``` +declare_clippy_lint! { + pub VEC_BOX_SIZED, + complexity, + "usage of `Vec>` where T: Sized, vector elements are already on the heap" +} + /// **What it does:** Checks for use of `Option>` in function signatures and type /// definitions /// @@ -148,7 +175,7 @@ declare_clippy_lint! { impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) + lint_array!(BOX_VEC, VEC_BOX_SIZED, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) } } @@ -238,6 +265,40 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { ); return; // don't recurse into the type } + } else if match_def_path(cx.tcx, def_id, &paths::VEC) { + if_chain! { + // Get the _ part of Vec<_> + if let Some(ref last) = last_path_segment(qpath).args; + if let Some(ty) = last.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }); + // ty is now _ at this point + if let TyKind::Path(ref ty_qpath) = ty.node; + let def = cx.tables.qpath_def(ty_qpath, ty.hir_id); + if let Some(def_id) = opt_def_id(def); + if Some(def_id) == cx.tcx.lang_items().owned_box(); + // At this point, we know ty is Box, now get T + if let Some(ref last) = last_path_segment(ty_qpath).args; + if let Some(ty) = last.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + GenericArg::Lifetime(_) => None, + }); + if let TyKind::Path(ref ty_qpath) = ty.node; + let def = cx.tables.qpath_def(ty_qpath, ty.hir_id); + if let Some(def_id) = opt_def_id(def); + let boxed_type = cx.tcx.type_of(def_id); + if boxed_type.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env); + then { + span_help_and_lint( + cx, + VEC_BOX_SIZED, + ast_ty.span, + "you seem to be trying to use `Vec>`, but T is Sized. Consider using just `Vec`", + "`Vec` is already on the heap, `Vec>` makes an extra allocation.", + ) + } + } } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { if match_type_parameter(cx, qpath, &paths::OPTION) { span_lint( diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs new file mode 100644 index 00000000000..d740f95edfe --- /dev/null +++ b/tests/ui/vec_box_sized.rs @@ -0,0 +1,17 @@ +struct SizedStruct { + _a: i32, +} + +struct UnsizedStruct { + _a: [i32], +} + +struct StructWithVecBox { + sized_type: Vec>, +} + +struct StructWithVecBoxButItsUnsized { + unsized_type: Vec>, +} + +fn main() {} diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr new file mode 100644 index 00000000000..80f54b51a40 --- /dev/null +++ b/tests/ui/vec_box_sized.stderr @@ -0,0 +1,11 @@ +error: you seem to be trying to use `Vec>`, but T is Sized. Consider using just `Vec` + --> $DIR/vec_box_sized.rs:10:14 + | +10 | sized_type: Vec>, + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::vec-box-sized` implied by `-D warnings` + = help: `Vec` is already on the heap, `Vec>` makes an extra allocation. + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From e5ea5395b971930d12e8be36ef124fa7f115f296 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 09:14:01 -0800 Subject: Update lint definitions --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e691ec9412f..977a4d4a514 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -899,6 +899,7 @@ All notable changes to this project will be documented in this file. [`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq [`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute [`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec +[`vec_box_sized`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box_sized [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop diff --git a/README.md b/README.md index f42771709fb..5c5d32e4a89 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 616395f40b54d4340348f6b811d5fe2497761f30 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 09:34:16 -0800 Subject: Add suggestion for replacement --- clippy_lints/src/types.rs | 8 +++++--- tests/ui/vec_box_sized.stderr | 5 ++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b85f21ce970..5b652985b3d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -290,12 +290,14 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { let boxed_type = cx.tcx.type_of(def_id); if boxed_type.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env); then { - span_help_and_lint( + span_lint_and_sugg( cx, VEC_BOX_SIZED, ast_ty.span, - "you seem to be trying to use `Vec>`, but T is Sized. Consider using just `Vec`", - "`Vec` is already on the heap, `Vec>` makes an extra allocation.", + "you seem to be trying to use `Vec>`, but T is Sized. `Vec` is already on the heap, `Vec>` makes an extra allocation.", + "try", + format!("Vec<{}>", boxed_type), + Applicability::MachineApplicable ) } } diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index 80f54b51a40..ae7171fdb31 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -1,11 +1,10 @@ -error: you seem to be trying to use `Vec>`, but T is Sized. Consider using just `Vec` +error: you seem to be trying to use `Vec>`, but T is Sized. `Vec` is already on the heap, `Vec>` makes an extra allocation. --> $DIR/vec_box_sized.rs:10:14 | 10 | sized_type: Vec>, - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` | = note: `-D clippy::vec-box-sized` implied by `-D warnings` - = help: `Vec` is already on the heap, `Vec>` makes an extra allocation. error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 9fc914cf4d6c508d1d07a2ff94ee23d1840eb5e5 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 09:37:00 -0800 Subject: Remove DUMMY_SP --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5b652985b3d..fdaa21f6c55 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -24,7 +24,7 @@ use crate::rustc_target::spec::abi::Abi; use crate::rustc_typeck::hir_ty_to_ty; use crate::syntax::ast::{FloatTy, IntTy, UintTy}; use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax::source_map::{DUMMY_SP, Span}; +use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, @@ -288,7 +288,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { let def = cx.tables.qpath_def(ty_qpath, ty.hir_id); if let Some(def_id) = opt_def_id(def); let boxed_type = cx.tcx.type_of(def_id); - if boxed_type.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env); + if boxed_type.is_sized(cx.tcx.at(ty.span), cx.param_env); then { span_lint_and_sugg( cx, -- cgit 1.4.1-3-g733a5 From db00c3320f8f0235f2ae022de7ecac65bfd80ff8 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 10:15:56 -0800 Subject: Remove references to sized for end users --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 4 ++-- clippy_lints/src/types.rs | 13 +++++++------ tests/ui/vec_box_sized.stderr | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 977a4d4a514..1713fda031f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -899,7 +899,7 @@ All notable changes to this project will be documented in this file. [`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq [`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute [`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec -[`vec_box_sized`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box_sized +[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9e3f0a6505d..f4b5edee84c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -766,7 +766,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::UNIT_ARG, types::UNIT_CMP, types::UNNECESSARY_CAST, - types::VEC_BOX_SIZED, + types::VEC_BOX, unicode::ZERO_WIDTH_SPACE, unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, unused_io_amount::UNUSED_IO_AMOUNT, @@ -932,7 +932,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::TYPE_COMPLEXITY, types::UNIT_ARG, types::UNNECESSARY_CAST, - types::VEC_BOX_SIZED, + types::VEC_BOX, unused_label::UNUSED_LABEL, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index fdaa21f6c55..62e99b92d35 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -90,7 +90,7 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub VEC_BOX_SIZED, + pub VEC_BOX, complexity, "usage of `Vec>` where T: Sized, vector elements are already on the heap" } @@ -175,7 +175,7 @@ declare_clippy_lint! { impl LintPass for TypePass { fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, VEC_BOX_SIZED, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) + lint_array!(BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) } } @@ -292,13 +292,14 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { then { span_lint_and_sugg( cx, - VEC_BOX_SIZED, + VEC_BOX, ast_ty.span, - "you seem to be trying to use `Vec>`, but T is Sized. `Vec` is already on the heap, `Vec>` makes an extra allocation.", + "`Vec` is already on the heap, the boxing is unnecessary.", "try", format!("Vec<{}>", boxed_type), - Applicability::MachineApplicable - ) + Applicability::MaybeIncorrect, + ); + return; // don't recurse into the type } } } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index ae7171fdb31..7f4bdfb5aed 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -1,10 +1,10 @@ -error: you seem to be trying to use `Vec>`, but T is Sized. `Vec` is already on the heap, `Vec>` makes an extra allocation. +error: `Vec` is already on the heap, the boxing is unnecessary. --> $DIR/vec_box_sized.rs:10:14 | 10 | sized_type: Vec>, | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` | - = note: `-D clippy::vec-box-sized` implied by `-D warnings` + = note: `-D clippy::vec-box` implied by `-D warnings` error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 985eba08a558bae9a9042b65df59340d227d7673 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Thu, 13 Dec 2018 10:46:21 -0800 Subject: Line length fix --- clippy_lints/src/types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 62e99b92d35..dfa4cfdcf94 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -73,7 +73,8 @@ declare_clippy_lint! { /// **Why is this bad?** `Vec` already keeps its contents in a separate area on /// the heap. So if you `Box` its contents, you just add another level of indirection. /// -/// **Known problems:** Vec> makes sense if T is a large type (see #3530, 1st comment). +/// **Known problems:** Vec> makes sense if T is a large type (see #3530, +/// 1st comment). /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From be40d82fea5010707290f8347ff3953a2e15639e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 14 Dec 2018 07:24:02 +0200 Subject: Fix test --- tests/ui/write_with_newline.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 426afe6cf49..ead6b5d08a0 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -25,9 +25,9 @@ error: using `write!()` with a format string that ends in a single newline, cons | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:44:5 + --> $DIR/write_with_newline.rs:41:5 | -44 | write!(&mut v, "//n"); +41 | write!(&mut v, "//n"); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From d866f31678d1c8c31a1b5763fbcbe7d8abe4460c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 14 Dec 2018 12:35:44 +0100 Subject: rustup rust-lang/rust#52994 s/trim_left/trim_start/ s/trim_right/trim_end/ --- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/misc_early.rs | 4 ++-- tests/ui/single_char_pattern.rs | 4 ++-- tests/ui/single_char_pattern.stderr | 12 ++++++------ 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 80f0267a981..a4d834da13f 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -116,7 +116,7 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { // We trim all opening braces and whitespaces and then check if the next string is a comment. let trimmed_block_text = snippet_block(cx, expr.span, "..") - .trim_left_matches(|c: char| c.is_whitespace() || c == '{') + .trim_start_matches(|c: char| c.is_whitespace() || c == '{') .to_owned(); trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 030c56cb81b..f8e31a4b2e7 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -116,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( for line in doc.lines() { let offset = line.as_ptr() as usize - comment.as_ptr() as usize; debug_assert_eq!(offset as u32 as usize, offset); - contains_initial_stars |= line.trim_left().starts_with('*'); + contains_initial_stars |= line.trim_start().starts_with('*'); // +1 for the newline sizes.push((line.len() + 1, span.with_lo(span.lo() + BytePos(offset as u32)))); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 384e027db27..06d2f2cb5fc 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2350,8 +2350,8 @@ const PATTERN_METHODS: [(&str, usize); 17] = [ ("rmatches", 1), ("match_indices", 1), ("rmatch_indices", 1), - ("trim_left_matches", 1), - ("trim_right_matches", 1), + ("trim_start_matches", 1), + ("trim_end_matches", 1), ]; #[derive(Clone, Copy, PartialEq, Debug)] diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 53da89dfcb0..9319ada13f4 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -446,13 +446,13 @@ impl MiscEarly { db.span_suggestion_with_applicability( lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion", - src.trim_left_matches(|c| c == '_' || c == '0').to_string(), + src.trim_start_matches(|c| c == '_' || c == '0').to_string(), Applicability::MaybeIncorrect, ); db.span_suggestion_with_applicability( lit.span, "if you mean to use an octal constant, use `0o`", - format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')), + format!("0o{}", src.trim_start_matches(|c| c == '_' || c == '0')), Applicability::MaybeIncorrect, ); }); diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 5277841fe32..eeee953ab84 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -42,8 +42,8 @@ fn main() { x.rmatches("x"); x.match_indices("x"); x.rmatch_indices("x"); - x.trim_left_matches("x"); - x.trim_right_matches("x"); + x.trim_start_matches("x"); + x.trim_end_matches("x"); // Make sure we escape characters correctly. x.split("\n"); diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 273bf779640..353796b3928 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -91,16 +91,16 @@ error: single-character string constant used as pattern | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:25 + --> $DIR/single_char_pattern.rs:45:26 | -45 | x.trim_left_matches("x"); - | ^^^ help: try using a char instead: `'x'` +45 | x.trim_start_matches("x"); + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:26 + --> $DIR/single_char_pattern.rs:46:24 | -46 | x.trim_right_matches("x"); - | ^^^ help: try using a char instead: `'x'` +46 | x.trim_end_matches("x"); + | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:48:13 -- cgit 1.4.1-3-g733a5 From a9509eb5984c1bb14fbba687cba7117a4aee8b02 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 14 Dec 2018 10:15:56 +0100 Subject: Revert "Merge pull request #3257 from o01eg/remove-sysroot" This reverts commit 041c49c1ed11b016d6ab9379643bb1da2adf5bfe, reversing changes made to 1df5766cbb559aab0ad5c2296d8b768182b5186c. --- src/driver.rs | 44 ++++++++++++++++++++++++++++++++++++++------ tests/compile-test.rs | 29 +---------------------------- tests/dogfood.rs | 27 --------------------------- 3 files changed, 39 insertions(+), 61 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 6b327d08207..fd9c8693c95 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -23,7 +23,7 @@ use self::rustc_driver::{driver::CompileController, Compilation}; use std::convert::TryInto; use std::path::Path; -use std::process::exit; +use std::process::{exit, Command}; fn show_version() { println!(env!("CARGO_PKG_VERSION")); @@ -40,22 +40,54 @@ pub fn main() { exit(0); } + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programmatically, so we ignore this/ - let mut args: Vec = env::args().collect(); - if args.len() <= 1 { + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { std::process::exit(1); } - if Path::new(&args[1]).file_stem() == Some("rustc".as_ref()) { + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { // we still want to be able to invoke it normally though - args.remove(1); + orig_args.remove(1); } + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; // this check ensures that dependencies are built but not linted and the final // crate is // linted but not built let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || args.iter().any(|s| s == "--emit=dep-info,metadata"); + || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 62fa17d388a..5cb37b6b6fd 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -17,7 +17,6 @@ use std::ffi::OsStr; use std::fs; use std::io; use std::path::{Path, PathBuf}; -use std::process::Command; fn clippy_driver_path() -> PathBuf { if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { @@ -43,28 +42,6 @@ fn rustc_lib_path() -> PathBuf { option_env!("RUSTC_LIB_PATH").unwrap().into() } -fn rustc_sysroot_path() -> PathBuf { - option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") - .into() -} - fn config(mode: &str, dir: PathBuf) -> compiletest::Config { let mut config = compiletest::Config::default(); @@ -78,11 +55,7 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!( - "-L {0} -L {0}/deps -Dwarnings --sysroot {1}", - host_libs().display(), - rustc_sysroot_path().display() - )); + config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 69f4f9901b7..c1f02b9fcef 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -7,31 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::path::PathBuf; -use std::process::Command; - -fn rustc_sysroot_path() -> PathBuf { - option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust") - .into() -} - #[test] fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { @@ -46,7 +21,6 @@ fn dogfood() { let output = std::process::Command::new(clippy_cmd) .current_dir(root_dir) .env("CLIPPY_DOGFOOD", "1") - .env("RUSTFLAGS", format!("--sysroot {}", rustc_sysroot_path().display())) .arg("clippy") .arg("--all-targets") .arg("--all-features") @@ -85,7 +59,6 @@ fn dogfood_tests() { let output = std::process::Command::new(&clippy_cmd) .current_dir(root_dir.join(d)) .env("CLIPPY_DOGFOOD", "1") - .env("RUSTFLAGS", format!("--sysroot {}", rustc_sysroot_path().display())) .arg("clippy") .arg("--") .args(&["-D", "clippy::all"]) -- cgit 1.4.1-3-g733a5 From 9fb80220267ae329bbcc8785e532dc69829d78e5 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 14 Dec 2018 21:43:40 +0100 Subject: base tests: make sure cargo-clippy binary can be called directly --- ci/base-tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 85b86fe0588..537f7e124d4 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -26,6 +26,11 @@ cd clippy_lints && cargo test && cd .. cd rustc_tools_util && cargo test && cd .. cd clippy_dev && cargo test && cd .. +# make sure clippy can be called via ./path/to/cargo-clippy +cd clippy_workspace_tests +../target/debug/cargo-clippy +cd .. + # Perform various checks for lint registration ./util/dev update_lints --check cargo +nightly fmt --all -- --check -- cgit 1.4.1-3-g733a5 From abab181984e81e89a1924d2736ecbdc86d765d7c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 14 Dec 2018 21:47:02 +0100 Subject: Make integration tests fail on 'E0463' --- ci/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index 75decab940e..bf43d5b6811 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -21,7 +21,7 @@ function check() { # run clippy on a project, try to be verbose and trigger as many warnings as possible for greater coverage RUST_BACKTRACE=full cargo clippy --all-targets --all-features -- --cap-lints warn -W clippy::pedantic -W clippy::nursery &> clippy_output cat clippy_output - ! cat clippy_output | grep -q "internal compiler error\|query stack during panic" + ! cat clippy_output | grep -q "internal compiler error\|query stack during panic\|E0463" if [[ $? != 0 ]]; then return 1 fi -- cgit 1.4.1-3-g733a5 From 15b9e9f23a3e10ca9cf2364f47ae8e1910df6eff Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 16 Dec 2018 14:10:53 +0100 Subject: chore(moduel_name_repeat): Rename stutter lint to module_name_repeat to avoid ableist language --- clippy_lints/src/enum_variants.rs | 8 ++++---- clippy_lints/src/lib.rs | 2 +- tests/ui/module_name_repeat.rs | 25 +++++++++++++++++++++++++ tests/ui/module_name_repeat.stderr | 34 ++++++++++++++++++++++++++++++++++ tests/ui/stutter.rs | 25 ------------------------- tests/ui/stutter.stderr | 34 ---------------------------------- 6 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 tests/ui/module_name_repeat.rs create mode 100644 tests/ui/module_name_repeat.stderr delete mode 100644 tests/ui/stutter.rs delete mode 100644 tests/ui/stutter.stderr diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index ae87c4273e9..861e1177296 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -75,7 +75,7 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub STUTTER, + pub MODULE_NAME_REPEAT, pedantic, "type names prefixed/postfixed with their containing module's name" } @@ -126,7 +126,7 @@ impl EnumVariantNames { impl LintPass for EnumVariantNames { fn get_lints(&self) -> LintArray { - lint_array!(ENUM_VARIANT_NAMES, PUB_ENUM_VARIANT_NAMES, STUTTER, MODULE_INCEPTION) + lint_array!(ENUM_VARIANT_NAMES, PUB_ENUM_VARIANT_NAMES, MODULE_NAME_REPEAT, MODULE_INCEPTION) } } @@ -277,7 +277,7 @@ impl EarlyLintPass for EnumVariantNames { match item_camel.chars().nth(nchars) { Some(c) if is_word_beginning(c) => span_lint( cx, - STUTTER, + MODULE_NAME_REPEAT, item.span, "item name starts with its containing module's name", ), @@ -287,7 +287,7 @@ impl EarlyLintPass for EnumVariantNames { if rmatching == nchars { span_lint( cx, - STUTTER, + MODULE_NAME_REPEAT, item.span, "item name ends with its containing module's name", ); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f4b5edee84c..1abca1751e8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -518,7 +518,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, enum_variants::PUB_ENUM_VARIANT_NAMES, - enum_variants::STUTTER, + enum_variants::MODULE_NAME_REPEAT, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, diff --git a/tests/ui/module_name_repeat.rs b/tests/ui/module_name_repeat.rs new file mode 100644 index 00000000000..a302eaacccf --- /dev/null +++ b/tests/ui/module_name_repeat.rs @@ -0,0 +1,25 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::module_name_repeat)] +#![allow(dead_code)] + +mod foo { + pub fn foo() {} + pub fn foo_bar() {} + pub fn bar_foo() {} + pub struct FooCake {} + pub enum CakeFoo {} + pub struct Foo7Bar; + + // Should not warn + pub struct Foobar; +} + +fn main() {} diff --git a/tests/ui/module_name_repeat.stderr b/tests/ui/module_name_repeat.stderr new file mode 100644 index 00000000000..9547fa9fdd6 --- /dev/null +++ b/tests/ui/module_name_repeat.stderr @@ -0,0 +1,34 @@ +error: item name starts with its containing module's name + --> $DIR/module_name_repeat.rs:15:5 + | +15 | pub fn foo_bar() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::module-name-repeat` implied by `-D warnings` + +error: item name ends with its containing module's name + --> $DIR/module_name_repeat.rs:16:5 + | +16 | pub fn bar_foo() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: item name starts with its containing module's name + --> $DIR/module_name_repeat.rs:17:5 + | +17 | pub struct FooCake {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: item name ends with its containing module's name + --> $DIR/module_name_repeat.rs:18:5 + | +18 | pub enum CakeFoo {} + | ^^^^^^^^^^^^^^^^^^^ + +error: item name starts with its containing module's name + --> $DIR/module_name_repeat.rs:19:5 + | +19 | pub struct Foo7Bar; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/stutter.rs b/tests/ui/stutter.rs deleted file mode 100644 index 922487d671d..00000000000 --- a/tests/ui/stutter.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![warn(clippy::stutter)] -#![allow(dead_code)] - -mod foo { - pub fn foo() {} - pub fn foo_bar() {} - pub fn bar_foo() {} - pub struct FooCake {} - pub enum CakeFoo {} - pub struct Foo7Bar; - - // Should not warn - pub struct Foobar; -} - -fn main() {} diff --git a/tests/ui/stutter.stderr b/tests/ui/stutter.stderr deleted file mode 100644 index 8c2d1d43281..00000000000 --- a/tests/ui/stutter.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: item name starts with its containing module's name - --> $DIR/stutter.rs:15:5 - | -15 | pub fn foo_bar() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::stutter` implied by `-D warnings` - -error: item name ends with its containing module's name - --> $DIR/stutter.rs:16:5 - | -16 | pub fn bar_foo() {} - | ^^^^^^^^^^^^^^^^^^^ - -error: item name starts with its containing module's name - --> $DIR/stutter.rs:17:5 - | -17 | pub struct FooCake {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: item name ends with its containing module's name - --> $DIR/stutter.rs:18:5 - | -18 | pub enum CakeFoo {} - | ^^^^^^^^^^^^^^^^^^^ - -error: item name starts with its containing module's name - --> $DIR/stutter.rs:19:5 - | -19 | pub struct Foo7Bar; - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - -- cgit 1.4.1-3-g733a5 From 35058287ce7cadd20eebf3fc77a34ca59c8a5eac Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 16 Dec 2018 15:42:02 +0100 Subject: Fix `implicit_return` false positives. --- clippy_lints/src/implicit_return.rs | 42 ++++++++++++++++++------------------- tests/ui/implicit_return.rs | 23 ++++++++++++++++++++ tests/ui/implicit_return.stderr | 22 ++++++++++++++----- 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 75c66d22647..96022db56aa 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -45,6 +45,19 @@ declare_clippy_lint! { pub struct Pass; impl Pass { + fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) { + span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + db.span_suggestion_with_applicability( + outer_span, + msg, + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }); + } + fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) { match &expr.node { // loops could be using `break` instead of `return` @@ -55,23 +68,19 @@ impl Pass { // only needed in the case of `break` with `;` at the end else if let Some(stmt) = block.stmts.last() { if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node { - Self::expr_match(cx, expr); + // make sure it's a break, otherwise we want to skip + if let ExprKind::Break(.., break_expr) = &expr.node { + if let Some(break_expr) = break_expr { + Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + } + } } } }, // use `return` instead of `break` ExprKind::Break(.., break_expr) => { if let Some(break_expr) = break_expr { - span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| { - if let Some(snippet) = snippet_opt(cx, break_expr.span) { - db.span_suggestion_with_applicability( - expr.span, - "change `break` to `return` as shown", - format!("return {}", snippet), - Applicability::MachineApplicable, - ); - } - }); + Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); } }, ExprKind::If(.., if_expr, else_expr) => { @@ -89,16 +98,7 @@ impl Pass { // skip if it already has a return statement ExprKind::Ret(..) => (), // everything else is missing `return` - _ => span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| { - if let Some(snippet) = snippet_opt(cx, expr.span) { - db.span_suggestion_with_applicability( - expr.span, - "add `return` as shown", - format!("return {}", snippet), - Applicability::MachineApplicable, - ); - } - }), + _ => Self::lint(cx, expr.span, expr.span, "add `return` as shown"), } } } diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 6188835e555..61cb35e1209 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -42,6 +42,27 @@ fn test_loop() -> bool { } } +#[allow(clippy::never_loop)] +fn test_loop_with_block() -> bool { + loop { + { + break true; + } + } +} + +#[allow(clippy::never_loop)] +fn test_loop_with_nests() -> bool { + loop { + if true { + let _ = true; + } + else { + break true; + } + } +} + fn test_closure() { #[rustfmt::skip] let _ = || { true }; @@ -53,5 +74,7 @@ fn main() { let _ = test_if_block(); let _ = test_match(true); let _ = test_loop(); + let _ = test_loop_with_block(); + let _ = test_loop_with_nests(); test_closure(); } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index b2feec3f57a..6d0761554cd 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -37,16 +37,28 @@ error: missing return statement | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:47:18 + --> $DIR/implicit_return.rs:49:13 | -47 | let _ = || { true }; +49 | break true; + | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` + +error: missing return statement + --> $DIR/implicit_return.rs:61:13 + | +61 | break true; + | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` + +error: missing return statement + --> $DIR/implicit_return.rs:68:18 + | +68 | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:48:16 + --> $DIR/implicit_return.rs:69:16 | -48 | let _ = || true; +69 | let _ = || true; | ^^^^ help: add `return` as shown: `return true` -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 6870638c3fb66c2abb20633bf40cc09ccc760047 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 16 Dec 2018 22:20:05 +0100 Subject: Fix an endless loop in the tests. --- tests/ui/implicit_return.rs | 4 ++-- tests/ui/implicit_return.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 61cb35e1209..9fb30135231 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -55,10 +55,10 @@ fn test_loop_with_block() -> bool { fn test_loop_with_nests() -> bool { loop { if true { - let _ = true; + break true; } else { - break true; + let _ = true; } } } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 6d0761554cd..b3562b67034 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -43,9 +43,9 @@ error: missing return statement | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:61:13 + --> $DIR/implicit_return.rs:58:13 | -61 | break true; +58 | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement -- cgit 1.4.1-3-g733a5 From 355018d0860c5aba29045c305adb2b02003e9942 Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 16 Dec 2018 22:49:46 +0100 Subject: fix(module_name_repeat): Try to register renamed lint, not valid yet --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1713fda031f..d773238597e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -760,6 +760,7 @@ All notable changes to this project will be documented in this file. [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception +[`module_name_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repeat [`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one [`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions [`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl @@ -850,7 +851,6 @@ All notable changes to this project will be documented in this file. [`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string -[`stutter`]: https://rust-lang.github.io/rust-clippy/master/index.html#stutter [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1abca1751e8..8f528ea83e3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -517,8 +517,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { doc::DOC_MARKDOWN, empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, - enum_variants::PUB_ENUM_VARIANT_NAMES, enum_variants::MODULE_NAME_REPEAT, + enum_variants::PUB_ENUM_VARIANT_NAMES, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, @@ -1028,6 +1028,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); + + store.register_renamed("stutter", "module_name_repeat"); } // only exists to let the dogfood integration test works. -- cgit 1.4.1-3-g733a5 From bc48890b47d13d1d820864e3c695ff6bf7038eac Mon Sep 17 00:00:00 2001 From: Lucas Lois Date: Thu, 6 Dec 2018 21:50:16 -0300 Subject: Implements lint for order comparisons against bool --- clippy_lints/src/needless_bool.rs | 104 +++++++++++++++++++++++++++++--------- tests/ui/bool_comparison.rs | 31 ++++++++++++ tests/ui/bool_comparison.stderr | 38 +++++++++++++- 3 files changed, 148 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 3bb87fbf5e9..dbd61935cc4 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -45,8 +45,9 @@ declare_clippy_lint! { "if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`" } -/// **What it does:** Checks for expressions of the form `x == true` and -/// `x != true` (or vice versa) and suggest using the variable directly. +/// **What it does:** Checks for expressions of the form `x == true`, +/// `x != true` and order comparisons such as `x < true` (or vice versa) and +/// suggest using the variable directly. /// /// **Why is this bad?** Unnecessary code. /// @@ -143,22 +144,54 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } if let ExprKind::Binary(Spanned { node, .. }, ..) = e.node { + let ignore_case = None::<(fn(_) -> _, &str)>; + let ignore_no_literal = None::<(fn(_, _) -> _, &str)>; match node { - BinOpKind::Eq => check_comparison( + BinOpKind::Eq => { + let true_case = Some((|h| h, "equality checks against true are unnecessary")); + let false_case = Some(( + |h: Sugg<'_>| !h, + "equality checks against false can be replaced by a negation", + )); + check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal) + }, + BinOpKind::Ne => { + let true_case = Some(( + |h: Sugg<'_>| !h, + "inequality checks against true can be replaced by a negation", + )); + let false_case = Some((|h| h, "inequality checks against false are unnecessary")); + check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal) + }, + BinOpKind::Lt => check_comparison( cx, e, - "equality checks against true are unnecessary", - "equality checks against false can be replaced by a negation", - |h| h, - |h| !h, + ignore_case, + Some((|h| h, "greater than checks against false are unnecessary")), + Some(( + |h: Sugg<'_>| !h, + "less than comparison against true can be replaced by a negation", + )), + ignore_case, + Some(( + |l: Sugg<'_>, r: Sugg<'_>| (!l).and(&r), + "order comparisons between booleans can be simplified", + )), ), - BinOpKind::Ne => check_comparison( + BinOpKind::Gt => check_comparison( cx, e, - "inequality checks against true can be replaced by a negation", - "inequality checks against false are unnecessary", - |h| !h, - |h| h, + Some(( + |h: Sugg<'_>| !h, + "less than comparison against true can be replaced by a negation", + )), + ignore_case, + ignore_case, + Some((|h| h, "greater than checks against false are unnecessary")), + Some(( + |l: Sugg<'_>, r: Sugg<'_>| l.and(&(!r)), + "order comparisons between booleans can be simplified", + )), ), _ => (), } @@ -169,22 +202,45 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx Expr, - true_message: &str, - false_message: &str, - true_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, - false_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, + left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, + left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, + right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, + right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, + no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>, ) { use self::Expression::*; if let ExprKind::Binary(_, ref left_side, ref right_side) = e.node { - let applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { - (Bool(true), Other) => suggest_bool_comparison(cx, e, right_side, applicability, true_message, true_hint), - (Other, Bool(true)) => suggest_bool_comparison(cx, e, left_side, applicability, true_message, true_hint), - (Bool(false), Other) => { - suggest_bool_comparison(cx, e, right_side, applicability, false_message, false_hint) - }, - (Other, Bool(false)) => suggest_bool_comparison(cx, e, left_side, applicability, false_message, false_hint), + (Bool(true), Other) => left_true.map_or((), |(h, m)| { + suggest_bool_comparison(cx, e, right_side, applicability, m, h) + }), + (Other, Bool(true)) => right_true.map_or((), |(h, m)| { + suggest_bool_comparison(cx, e, left_side, applicability, m, h) + }), + (Bool(false), Other) => left_false.map_or((), |(h, m)| { + suggest_bool_comparison(cx, e, right_side, applicability, m, h) + }), + (Other, Bool(false)) => right_false.map_or((), |(h, m)| { + suggest_bool_comparison(cx, e, left_side, applicability, m, h) + }), + (Other, Other) => no_literal.map_or((), |(h, m)| { + let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); + if l_ty.is_bool() && r_ty.is_bool() { + let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability); + let right_side = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability); + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + m, + "try simplifying it as shown", + h(left_side, right_side).to_string(), + applicability, + ) + } + }), _ => (), } } @@ -196,7 +252,7 @@ fn suggest_bool_comparison<'a, 'tcx>( expr: &Expr, mut applicability: Applicability, message: &str, - conv_hint: impl FnOnce(Sugg<'_>) -> Sugg<'_>, + conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>, ) { let hint = Sugg::hir_with_applicability(cx, expr, "..", &mut applicability); span_lint_and_sugg( diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 30b5acf2d97..2a28d0af1b2 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -50,4 +50,35 @@ fn main() { } else { "no" }; + if x < true { + "yes" + } else { + "no" + }; + if false < x { + "yes" + } else { + "no" + }; + if x > false { + "yes" + } else { + "no" + }; + if true > x { + "yes" + } else { + "no" + }; + let y = true; + if x < y { + "yes" + } else { + "no" + }; + if x > y { + "yes" + } else { + "no" + }; } diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index d136bc656b6..d28052676eb 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -48,5 +48,41 @@ error: inequality checks against false are unnecessary 48 | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` -error: aborting due to 8 previous errors +error: less than comparison against true can be replaced by a negation + --> $DIR/bool_comparison.rs:53:8 + | +53 | if x < true { + | ^^^^^^^^ help: try simplifying it as shown: `!x` + +error: greater than checks against false are unnecessary + --> $DIR/bool_comparison.rs:58:8 + | +58 | if false < x { + | ^^^^^^^^^ help: try simplifying it as shown: `x` + +error: greater than checks against false are unnecessary + --> $DIR/bool_comparison.rs:63:8 + | +63 | if x > false { + | ^^^^^^^^^ help: try simplifying it as shown: `x` + +error: less than comparison against true can be replaced by a negation + --> $DIR/bool_comparison.rs:68:8 + | +68 | if true > x { + | ^^^^^^^^ help: try simplifying it as shown: `!x` + +error: order comparisons between booleans can be simplified + --> $DIR/bool_comparison.rs:74:8 + | +74 | if x < y { + | ^^^^^ help: try simplifying it as shown: `!x && y` + +error: order comparisons between booleans can be simplified + --> $DIR/bool_comparison.rs:79:8 + | +79 | if x > y { + | ^^^^^ help: try simplifying it as shown: `x && !y` + +error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 0516c2e04a620493fe92b82c4cdecf32dae2f96a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 17 Dec 2018 13:58:41 +0100 Subject: Move renaming to the right place --- clippy_lints/src/lib.rs | 4 +++- src/driver.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8f528ea83e3..5c1469536f5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1028,8 +1028,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); +} - store.register_renamed("stutter", "module_name_repeat"); +pub fn register_renamed(ls: &mut rustc::lint::LintStore) { + ls.register_renamed("clippy::stutter", "clippy::module_name_repeat"); } // only exists to let the dogfood integration test works. diff --git a/src/driver.rs b/src/driver.rs index 6b327d08207..0df2d898860 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -110,6 +110,7 @@ pub fn main() { ls.register_group(Some(sess), true, name, deprecated_name, to); } clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf); + clippy_lints::register_renamed(&mut ls); sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes); sess.plugin_attributes.borrow_mut().extend(attributes); -- cgit 1.4.1-3-g733a5 From 60cc6b931996b65a053699973bb08487e31bf9f0 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 17 Dec 2018 13:59:09 +0100 Subject: Add renaming tests --- tests/ui/rename.rs | 13 +++++++++++++ tests/ui/rename.stderr | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/ui/rename.rs create mode 100644 tests/ui/rename.stderr diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs new file mode 100644 index 00000000000..8d76a2d4586 --- /dev/null +++ b/tests/ui/rename.rs @@ -0,0 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(stutter)] + +#[warn(clippy::stutter)] +fn main() {} diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr new file mode 100644 index 00000000000..9aa22eb6c45 --- /dev/null +++ b/tests/ui/rename.stderr @@ -0,0 +1,18 @@ +error: unknown lint: `stutter` + --> $DIR/rename.rs:10:10 + | +10 | #![allow(stutter)] + | ^^^^^^^ + | + = note: `-D unknown-lints` implied by `-D warnings` + +error: lint `clippy::stutter` has been renamed to `clippy::module_name_repeat` + --> $DIR/rename.rs:12:8 + | +12 | #[warn(clippy::stutter)] + | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repeat` + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From a44adaa5edd793da13665734a6de2d46d584e733 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 17 Dec 2018 14:29:19 +0100 Subject: Rename lint to MODULE_NAME_REPETITIONS --- clippy_lints/src/enum_variants.rs | 13 +++++++++---- clippy_lints/src/lib.rs | 4 ++-- tests/ui/module_name_repeat.rs | 25 ------------------------ tests/ui/module_name_repeat.stderr | 34 --------------------------------- tests/ui/module_name_repetitions.rs | 25 ++++++++++++++++++++++++ tests/ui/module_name_repetitions.stderr | 34 +++++++++++++++++++++++++++++++++ tests/ui/rename.stderr | 4 ++-- 7 files changed, 72 insertions(+), 67 deletions(-) delete mode 100644 tests/ui/module_name_repeat.rs delete mode 100644 tests/ui/module_name_repeat.stderr create mode 100644 tests/ui/module_name_repetitions.rs create mode 100644 tests/ui/module_name_repetitions.stderr diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 861e1177296..c6142a16854 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -75,7 +75,7 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub MODULE_NAME_REPEAT, + pub MODULE_NAME_REPETITIONS, pedantic, "type names prefixed/postfixed with their containing module's name" } @@ -126,7 +126,12 @@ impl EnumVariantNames { impl LintPass for EnumVariantNames { fn get_lints(&self) -> LintArray { - lint_array!(ENUM_VARIANT_NAMES, PUB_ENUM_VARIANT_NAMES, MODULE_NAME_REPEAT, MODULE_INCEPTION) + lint_array!( + ENUM_VARIANT_NAMES, + PUB_ENUM_VARIANT_NAMES, + MODULE_NAME_REPETITIONS, + MODULE_INCEPTION + ) } } @@ -277,7 +282,7 @@ impl EarlyLintPass for EnumVariantNames { match item_camel.chars().nth(nchars) { Some(c) if is_word_beginning(c) => span_lint( cx, - MODULE_NAME_REPEAT, + MODULE_NAME_REPETITIONS, item.span, "item name starts with its containing module's name", ), @@ -287,7 +292,7 @@ impl EarlyLintPass for EnumVariantNames { if rmatching == nchars { span_lint( cx, - MODULE_NAME_REPEAT, + MODULE_NAME_REPETITIONS, item.span, "item name ends with its containing module's name", ); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5c1469536f5..8ce5861a939 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -517,7 +517,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { doc::DOC_MARKDOWN, empty_enum::EMPTY_ENUM, enum_glob_use::ENUM_GLOB_USE, - enum_variants::MODULE_NAME_REPEAT, + enum_variants::MODULE_NAME_REPETITIONS, enum_variants::PUB_ENUM_VARIANT_NAMES, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, @@ -1031,7 +1031,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { } pub fn register_renamed(ls: &mut rustc::lint::LintStore) { - ls.register_renamed("clippy::stutter", "clippy::module_name_repeat"); + ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions"); } // only exists to let the dogfood integration test works. diff --git a/tests/ui/module_name_repeat.rs b/tests/ui/module_name_repeat.rs deleted file mode 100644 index a302eaacccf..00000000000 --- a/tests/ui/module_name_repeat.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![warn(clippy::module_name_repeat)] -#![allow(dead_code)] - -mod foo { - pub fn foo() {} - pub fn foo_bar() {} - pub fn bar_foo() {} - pub struct FooCake {} - pub enum CakeFoo {} - pub struct Foo7Bar; - - // Should not warn - pub struct Foobar; -} - -fn main() {} diff --git a/tests/ui/module_name_repeat.stderr b/tests/ui/module_name_repeat.stderr deleted file mode 100644 index 9547fa9fdd6..00000000000 --- a/tests/ui/module_name_repeat.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: item name starts with its containing module's name - --> $DIR/module_name_repeat.rs:15:5 - | -15 | pub fn foo_bar() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::module-name-repeat` implied by `-D warnings` - -error: item name ends with its containing module's name - --> $DIR/module_name_repeat.rs:16:5 - | -16 | pub fn bar_foo() {} - | ^^^^^^^^^^^^^^^^^^^ - -error: item name starts with its containing module's name - --> $DIR/module_name_repeat.rs:17:5 - | -17 | pub struct FooCake {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: item name ends with its containing module's name - --> $DIR/module_name_repeat.rs:18:5 - | -18 | pub enum CakeFoo {} - | ^^^^^^^^^^^^^^^^^^^ - -error: item name starts with its containing module's name - --> $DIR/module_name_repeat.rs:19:5 - | -19 | pub struct Foo7Bar; - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs new file mode 100644 index 00000000000..4db4f56de46 --- /dev/null +++ b/tests/ui/module_name_repetitions.rs @@ -0,0 +1,25 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::module_name_repetitions)] +#![allow(dead_code)] + +mod foo { + pub fn foo() {} + pub fn foo_bar() {} + pub fn bar_foo() {} + pub struct FooCake {} + pub enum CakeFoo {} + pub struct Foo7Bar; + + // Should not warn + pub struct Foobar; +} + +fn main() {} diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr new file mode 100644 index 00000000000..e2eca64ba42 --- /dev/null +++ b/tests/ui/module_name_repetitions.stderr @@ -0,0 +1,34 @@ +error: item name starts with its containing module's name + --> $DIR/module_name_repetitions.rs:15:5 + | +15 | pub fn foo_bar() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::module-name-repetitions` implied by `-D warnings` + +error: item name ends with its containing module's name + --> $DIR/module_name_repetitions.rs:16:5 + | +16 | pub fn bar_foo() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: item name starts with its containing module's name + --> $DIR/module_name_repetitions.rs:17:5 + | +17 | pub struct FooCake {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: item name ends with its containing module's name + --> $DIR/module_name_repetitions.rs:18:5 + | +18 | pub enum CakeFoo {} + | ^^^^^^^^^^^^^^^^^^^ + +error: item name starts with its containing module's name + --> $DIR/module_name_repetitions.rs:19:5 + | +19 | pub struct Foo7Bar; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 9aa22eb6c45..7ad8228fb35 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -6,11 +6,11 @@ error: unknown lint: `stutter` | = note: `-D unknown-lints` implied by `-D warnings` -error: lint `clippy::stutter` has been renamed to `clippy::module_name_repeat` +error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` --> $DIR/rename.rs:12:8 | 12 | #[warn(clippy::stutter)] - | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repeat` + | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` | = note: `-D renamed-and-removed-lints` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From d74288efce836ad67825b2d25f6c8889b06c7d7a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 17 Dec 2018 14:33:05 +0100 Subject: Run update_lints after renaming --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d773238597e..606f16061ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -760,7 +760,7 @@ All notable changes to this project will be documented in this file. [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception -[`module_name_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repeat +[`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions [`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one [`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions [`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl -- cgit 1.4.1-3-g733a5 From de42dfbab7ce008c0a15cf4b8896f51fa90ea7ed Mon Sep 17 00:00:00 2001 From: Lucas Lois Date: Mon, 17 Dec 2018 15:32:24 -0300 Subject: Changes lint sugg to bitwise and operator `&` --- clippy_lints/src/needless_bool.rs | 4 ++-- clippy_lints/src/utils/sugg.rs | 5 +++++ tests/ui/bool_comparison.stderr | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index dbd61935cc4..1ad7f4c5540 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -174,7 +174,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { )), ignore_case, Some(( - |l: Sugg<'_>, r: Sugg<'_>| (!l).and(&r), + |l: Sugg<'_>, r: Sugg<'_>| (!l).bit_and(&r), "order comparisons between booleans can be simplified", )), ), @@ -189,7 +189,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { ignore_case, Some((|h| h, "greater than checks against false are unnecessary")), Some(( - |l: Sugg<'_>, r: Sugg<'_>| l.and(&(!r)), + |l: Sugg<'_>, r: Sugg<'_>| l.bit_and(&(!r)), "order comparisons between booleans can be simplified", )), ), diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index c5f4a61fe8c..66f18b51f21 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -174,6 +174,11 @@ impl<'a> Sugg<'a> { make_binop(ast::BinOpKind::And, &self, rhs) } + /// Convenience method to create the ` & ` suggestion. + pub fn bit_and(self, rhs: &Self) -> Sugg<'static> { + make_binop(ast::BinOpKind::BitAnd, &self, rhs) + } + /// Convenience method to create the ` as ` suggestion. pub fn as_ty(self, rhs: R) -> Sugg<'static> { make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into())) diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index d28052676eb..9a12a8f089a 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -76,13 +76,13 @@ error: order comparisons between booleans can be simplified --> $DIR/bool_comparison.rs:74:8 | 74 | if x < y { - | ^^^^^ help: try simplifying it as shown: `!x && y` + | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified --> $DIR/bool_comparison.rs:79:8 | 79 | if x > y { - | ^^^^^ help: try simplifying it as shown: `x && !y` + | ^^^^^ help: try simplifying it as shown: `x & !y` error: aborting due to 14 previous errors -- cgit 1.4.1-3-g733a5 From 24ef8db4022b31bda31f4a360c0bb2b6e3616270 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Mon, 17 Dec 2018 21:33:50 +0100 Subject: Do not mark as_ref as useless if it's followed by a method call --- clippy_lints/src/methods/mod.rs | 24 +++++++++++++++++------- tests/ui/useful_asref.rs | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 tests/ui/useful_asref.rs diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 06d2f2cb5fc..9763392bfdf 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -19,11 +19,11 @@ use crate::syntax::symbol::LocalInternedString; use crate::utils::paths; use crate::utils::sugg; use crate::utils::{ - get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty, - iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type, - match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, - snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then, - span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, + get_arg_name, get_parent_expr, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, + is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, + match_type, match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, + snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, + span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; use if_chain::if_chain; use matches::matches; @@ -859,8 +859,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true), ["next", "skip"] => lint_iter_skip_next(cx, expr), ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), - ["as_ref", ..] => lint_asref(cx, expr, "as_ref", arg_lists[0]), - ["as_mut", ..] => lint_asref(cx, expr, "as_mut", arg_lists[0]), + ["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]), + ["as_mut"] => lint_asref(cx, expr, "as_mut", arg_lists[0]), ["fold", ..] => lint_unnecessary_fold(cx, expr, arg_lists[0]), ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), _ => {}, @@ -2181,6 +2181,16 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { + // allow the `as_ref` or `as_mut` if it is followed by another method call + if_chain! { + if let Some(parent) = get_parent_expr(cx, expr); + if let hir::ExprKind::MethodCall(_, ref span, _) = parent.node; + if span != &expr.span; + then { + return; + } + } + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, diff --git a/tests/ui/useful_asref.rs b/tests/ui/useful_asref.rs new file mode 100644 index 00000000000..d7e56af2590 --- /dev/null +++ b/tests/ui/useful_asref.rs @@ -0,0 +1,22 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(clippy::useless_asref)] + +trait Trait { + fn as_ptr(&self); +} + +impl<'a> Trait for &'a [u8] { + fn as_ptr(&self) { + self.as_ref().as_ptr(); + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 8b0ea2288590b7e0cf7f276467ed1851208902fe Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Tue, 18 Dec 2018 11:25:13 +0100 Subject: Deduplicate some code? --- clippy_lints/src/question_mark.rs | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 057b4850e4f..95f79219105 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -72,6 +72,8 @@ impl Pass { if Self::is_option(cx, subject); then { + let receiver_str = &Sugg::hir(cx, subject, ".."); + let mut replacement_str = String::new(); if let Some(else_) = else_ { if_chain! { if let ExprKind::Block(block, None) = &else_.node; @@ -79,37 +81,22 @@ impl Pass { if let Some(block_expr) = &block.expr; if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr); then { - span_lint_and_then( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - |db| { - db.span_suggestion_with_applicability( - expr.span, - "replace_it_with", - format!("Some({}?)", Sugg::hir(cx, subject, "..")), - Applicability::MaybeIncorrect, // snippet - ); - } - ) + replacement_str = format!("Some({}?)", receiver_str); } } - return; + } else { + replacement_str = format!("{}?;", receiver_str); } - span_lint_and_then( cx, QUESTION_MARK, expr.span, "this block may be rewritten with the `?` operator", |db| { - let receiver_str = &Sugg::hir(cx, subject, ".."); - db.span_suggestion_with_applicability( expr.span, "replace_it_with", - format!("{}?;", receiver_str), + replacement_str, Applicability::MaybeIncorrect, // snippet ); } @@ -132,7 +119,7 @@ impl Pass { } false - }, + } ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { @@ -140,7 +127,7 @@ impl Pass { } false - }, + } _ => false, } } -- cgit 1.4.1-3-g733a5 From ee0856cbeb4ec600399b01fcca58e1804478c3a1 Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Tue, 18 Dec 2018 13:55:04 +0100 Subject: Recomend `.as_ref()?` in certain situations --- clippy_lints/src/question_mark.rs | 8 +++++++ tests/ui/question_mark.rs | 45 +++++++++++++++++++++++++++++++++++---- tests/ui/question_mark.stderr | 26 +++++++++++++++++++++- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 95f79219105..c7501ccf2d7 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -84,6 +84,8 @@ impl Pass { replacement_str = format!("Some({}?)", receiver_str); } } + } else if Self::moves_by_default(cx, subject) { + replacement_str = format!("{}.as_ref()?;", receiver_str); } else { replacement_str = format!("{}?;", receiver_str); } @@ -105,6 +107,12 @@ impl Pass { } } + fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { + let expr_ty = cx.tables.expr_ty(expression); + + expr_ty.moves_by_default(cx.tcx, cx.param_env, expression.span) + } + fn is_option(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { let expr_ty = cx.tables.expr_ty(expression); diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index b1edec32eee..c6726ee567c 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -37,11 +37,11 @@ fn returns_something_similar_to_option(a: SeemsOption) -> SeemsOption a } -pub struct SomeStruct { +pub struct CopyStruct { pub opt: Option, } -impl SomeStruct { +impl CopyStruct { #[rustfmt::skip] pub fn func(&self) -> Option { if (self.opt).is_none() { @@ -62,12 +62,49 @@ impl SomeStruct { } } +#[derive(Clone)] +pub struct MoveStruct { + pub opt: Option>, +} + +impl MoveStruct { + pub fn ref_func(&self) -> Option> { + if self.opt.is_none() { + return None; + } + + self.opt.clone() + } + + pub fn mov_func_reuse(self) -> Option> { + if self.opt.is_none() { + return None; + } + + self.opt + } + + pub fn mov_func_no_use(self) -> Option> { + if self.opt.is_none() { + return None; + } + Some(Vec::new()) + } +} + fn main() { some_func(Some(42)); some_func(None); - let some_struct = SomeStruct { opt: Some(54) }; - some_struct.func(); + let copy_struct = CopyStruct { opt: Some(54) }; + copy_struct.func(); + + let move_struct = MoveStruct { + opt: Some(vec![42, 1337]), + }; + move_struct.ref_func(); + move_struct.clone().mov_func_reuse(); + move_struct.clone().mov_func_no_use(); let so = SeemsOption::Some(45); returns_something_similar_to_option(so); diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index c9d5538f36f..4f3b2c65de5 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -35,5 +35,29 @@ error: this block may be rewritten with the `?` operator 59 | | }; | |_________^ help: replace_it_with: `Some(self.opt?)` -error: aborting due to 4 previous errors +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:72:9 + | +72 | / if self.opt.is_none() { +73 | | return None; +74 | | } + | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:80:9 + | +80 | / if self.opt.is_none() { +81 | | return None; +82 | | } + | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:88:9 + | +88 | / if self.opt.is_none() { +89 | | return None; +90 | | } + | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 987f260543aecd0d2645ba7e1adba77d5b7a72e6 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 19 Dec 2018 06:13:43 +0200 Subject: Update README local run command to specify syspath --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c5d32e4a89..13fb8225e59 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ To have cargo compile your crate with Clippy without Clippy installation in your code, you can use: ```terminal -cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml +RUSTFLAGS=--sysroot=`rustc --print sysroot` cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` *[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):* -- cgit 1.4.1-3-g733a5 From e722b1338e22c46bbe74a8e7a82bc29916570105 Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Wed, 19 Dec 2018 20:31:08 +0100 Subject: Reinserted commata --- clippy_lints/src/question_mark.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index c7501ccf2d7..98aeb3a8e10 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -127,7 +127,7 @@ impl Pass { } false - } + }, ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { @@ -135,7 +135,7 @@ impl Pass { } false - } + }, _ => false, } } -- cgit 1.4.1-3-g733a5 From 18584698eebfe1f0e51349de352a53179735cf52 Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Wed, 19 Dec 2018 20:46:12 +0100 Subject: Add failing test --- tests/ui/question_mark.rs | 9 ++++++++ tests/ui/question_mark.stderr | 52 +++++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index c6726ee567c..880c163e833 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -15,6 +15,15 @@ fn some_func(a: Option) -> Option { a } +fn some_other_func(a: Option) -> Option { + if a.is_none() { + return None; + } else { + return Some(0); + } + unreachable!() +} + pub enum SeemsOption { Some(T), None, diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 4f3b2c65de5..f55a83d43c8 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -9,54 +9,54 @@ error: this block may be rewritten with the `?` operator = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:47:9 + --> $DIR/question_mark.rs:56:9 | -47 | / if (self.opt).is_none() { -48 | | return None; -49 | | } +56 | / if (self.opt).is_none() { +57 | | return None; +58 | | } | |_________^ help: replace_it_with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:51:9 + --> $DIR/question_mark.rs:60:9 | -51 | / if self.opt.is_none() { -52 | | return None -53 | | } +60 | / if self.opt.is_none() { +61 | | return None +62 | | } | |_________^ help: replace_it_with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:55:17 + --> $DIR/question_mark.rs:64:17 | -55 | let _ = if self.opt.is_none() { +64 | let _ = if self.opt.is_none() { | _________________^ -56 | | return None; -57 | | } else { -58 | | self.opt -59 | | }; +65 | | return None; +66 | | } else { +67 | | self.opt +68 | | }; | |_________^ help: replace_it_with: `Some(self.opt?)` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:72:9 + --> $DIR/question_mark.rs:81:9 | -72 | / if self.opt.is_none() { -73 | | return None; -74 | | } +81 | / if self.opt.is_none() { +82 | | return None; +83 | | } | |_________^ help: replace_it_with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:80:9 + --> $DIR/question_mark.rs:89:9 | -80 | / if self.opt.is_none() { -81 | | return None; -82 | | } +89 | / if self.opt.is_none() { +90 | | return None; +91 | | } | |_________^ help: replace_it_with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:88:9 + --> $DIR/question_mark.rs:97:9 | -88 | / if self.opt.is_none() { -89 | | return None; -90 | | } +97 | / if self.opt.is_none() { +98 | | return None; +99 | | } | |_________^ help: replace_it_with: `self.opt.as_ref()?;` error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 65c35333a4269a987350272339f3a078fd64f2b7 Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Wed, 19 Dec 2018 20:55:01 +0100 Subject: Only print out question_mark lint when it actually triggered --- clippy_lints/src/question_mark.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 98aeb3a8e10..76fb6350681 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -73,7 +73,7 @@ impl Pass { then { let receiver_str = &Sugg::hir(cx, subject, ".."); - let mut replacement_str = String::new(); + let mut replacement: Option = None; if let Some(else_) = else_ { if_chain! { if let ExprKind::Block(block, None) = &else_.node; @@ -81,28 +81,31 @@ impl Pass { if let Some(block_expr) = &block.expr; if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr); then { - replacement_str = format!("Some({}?)", receiver_str); + replacement = Some(format!("Some({}?)", receiver_str)); } } } else if Self::moves_by_default(cx, subject) { - replacement_str = format!("{}.as_ref()?;", receiver_str); + replacement = Some(format!("{}.as_ref()?;", receiver_str)); } else { - replacement_str = format!("{}?;", receiver_str); + replacement = Some(format!("{}?;", receiver_str)); } - span_lint_and_then( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - |db| { - db.span_suggestion_with_applicability( - expr.span, - "replace_it_with", - replacement_str, - Applicability::MaybeIncorrect, // snippet - ); - } - ) + + if let Some(replacement_str) = replacement { + span_lint_and_then( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + |db| { + db.span_suggestion_with_applicability( + expr.span, + "replace_it_with", + replacement_str, + Applicability::MaybeIncorrect, // snippet + ); + } + ) + } } } } -- cgit 1.4.1-3-g733a5 From 5875ba3364392eb633a3d10ec8faecf706eb46de Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Wed, 19 Dec 2018 20:47:50 +0000 Subject: mutex_atomic: Correct location of AtomicBool and friends The AtomicBool, AtomicUsize, and friends, types live in the `std::sync::atomic` module, rather than `std::atomic` as the lint help text used to say. --- clippy_lints/src/mutex_atomic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 34683934eca..fb467d886b5 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -22,7 +22,7 @@ use crate::utils::{match_type, paths, span_lint}; /// /// **Why is this bad?** Using a mutex just to make access to a plain bool or /// reference sequential is shooting flies with cannons. -/// `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and +/// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and /// faster. /// /// **Known problems:** This lint cannot detect if the mutex is actually used @@ -43,7 +43,7 @@ declare_clippy_lint! { /// /// **Why is this bad?** Using a mutex just to make access to a plain integer /// sequential is -/// shooting flies with cannons. `std::atomic::usize` is leaner and faster. +/// shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster. /// /// **Known problems:** This lint cannot detect if the mutex is actually used /// for waiting before a critical section. -- cgit 1.4.1-3-g733a5 From b5f6eb6e75b983b33f4f37a11300f5679443e9c1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 19 Dec 2018 11:41:27 -0800 Subject: Link to `rustc_driver` crate in plugin This is in anticipation for rust-lang/rust#56987 where the `rustc_driver` crate being linked in will be required to link correctly against the compiler. In the meantime it should be harmless otherwise! --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 4069472612d..ef6f4cd7b3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ // FIXME: switch to something more ergonomic here, once available. // (currently there is no way to opt into sysroot crates w/o `extern crate`) #[allow(unused_extern_crates)] +extern crate rustc_driver; +#[allow(unused_extern_crates)] extern crate rustc_plugin; use self::rustc_plugin::Registry; -- cgit 1.4.1-3-g733a5 From 88564b743ed5bd5a9c2b7d6ed7954f5bba9b1c69 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 18:04:15 -0400 Subject: Teach `suspicious_else_formatting` about `if .. {..} {..}` --- clippy_lints/src/formatting.rs | 67 +++++++++++++++++------ tests/ui/formatting.rs | 31 ++++++++++- tests/ui/formatting.stderr | 121 +++++++++++++++++++++++++---------------- 3 files changed, 155 insertions(+), 64 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 48ee383482c..1fae0974d95 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -31,8 +31,8 @@ declare_clippy_lint! { "suspicious formatting of `*=`, `-=` or `!=`" } -/// **What it does:** Checks for formatting of `else if`. It lints if the `else` -/// and `if` are not on the same line or the `else` seems to be missing. +/// **What it does:** Checks for formatting of `else`. It lints if the `else` +/// is followed immediately by a newline or the `else` seems to be missing. /// /// **Why is this bad?** This is probably some refactoring remnant, even if the /// code is correct, it might look confusing. @@ -42,19 +42,29 @@ declare_clippy_lint! { /// **Example:** /// ```rust,ignore /// if foo { +/// } { // looks like an `else` is missing here +/// } +/// +/// if foo { /// } if bar { // looks like an `else` is missing here /// } /// /// if foo { /// } else /// +/// { // this is the `else` block of the previous `if`, but should it be? +/// } +/// +/// if foo { +/// } else +/// /// if bar { // this is the `else` block of the previous `if`, but should it be? /// } /// ``` declare_clippy_lint! { pub SUSPICIOUS_ELSE_FORMATTING, style, - "suspicious formatting of `else if`" + "suspicious formatting of `else`" } /// **What it does:** Checks for possible missing comma in an array. It lints if @@ -96,7 +106,7 @@ impl EarlyLintPass for Formatting { match (&w[0].node, &w[1].node) { (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) | (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => { - check_consecutive_ifs(cx, first, second); + check_missing_else(cx, first, second); }, _ => (), } @@ -105,7 +115,7 @@ impl EarlyLintPass for Formatting { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { check_assign(cx, expr); - check_else_if(cx, expr); + check_else(cx, expr); check_array(cx, expr); } } @@ -139,10 +149,13 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &ast::Expr) { } } -/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`. -fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { +/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else`. +fn check_else(cx: &EarlyContext<'_>, expr: &ast::Expr) { if let Some((then, &Some(ref else_))) = unsugar_if(expr) { - if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) { + if (is_block(else_) || unsugar_if(else_).is_some()) + && !differing_macro_contexts(then.span, else_.span) + && !in_macro(then.span) + { // this will be a span from the closing ‘}’ of the “then” block (excluding) to // the // “if” of the “else if” block (excluding) @@ -154,14 +167,19 @@ fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { let else_pos = else_snippet.find("else").expect("there must be a `else` here"); if else_snippet[else_pos..].contains('\n') { + let else_desc = if unsugar_if(else_).is_some() { "if" } else { "{..}" }; + span_note_and_lint( cx, SUSPICIOUS_ELSE_FORMATTING, else_span, - "this is an `else if` but the formatting might hide it", + &format!("this is an `else {}` but the formatting might hide it", else_desc), else_span, - "to remove this lint, remove the `else` or remove the new line between `else` \ - and `if`", + &format!( + "to remove this lint, remove the `else` or remove the new line between \ + `else` and `{}`", + else_desc, + ), ); } } @@ -200,32 +218,47 @@ fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) { } } -/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs. -fn check_consecutive_ifs(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) { +fn check_missing_else(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) { if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some() - && unsugar_if(second).is_some() + && (is_block(second) || unsugar_if(second).is_some()) { // where the else would be let else_span = first.span.between(second.span); if let Some(else_snippet) = snippet_opt(cx, else_span) { if !else_snippet.contains('\n') { + let (looks_like, next_thing) = if unsugar_if(second).is_some() { + ("an `else if`", "the second `if`") + } else { + ("an `else {..}`", "the next block") + }; + span_note_and_lint( cx, SUSPICIOUS_ELSE_FORMATTING, else_span, - "this looks like an `else if` but the `else` is missing", + &format!("this looks like {} but the `else` is missing", looks_like), else_span, - "to remove this lint, add the missing `else` or add a new line before the second \ - `if`", + &format!( + "to remove this lint, add the missing `else` or add a new line before {}", + next_thing, + ), ); } } } } +fn is_block(expr: &ast::Expr) -> bool { + if let ast::ExprKind::Block(..) = expr.node { + true + } else { + false + } +} + /// Match `if` or `if let` expressions and return the `then` and `else` block. fn unsugar_if(expr: &ast::Expr) -> Option<(&P, &Option>)> { match expr.node { diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 3bea98acf2f..b74f778b129 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -16,7 +16,11 @@ fn foo() -> bool { true } fn main() { - // weird `else if` formatting: + // weird `else` formatting: + if foo() { + } { + } + if foo() { } if foo() { } @@ -41,6 +45,17 @@ fn main() { let _ = 0; }; + if foo() { + } else + { + } + + if foo() { + } + else + { + } + if foo() { } else if foo() { // the span of the above error should continue here @@ -53,6 +68,20 @@ fn main() { } // those are ok: + if foo() { + } + { + } + + if foo() { + } else { + } + + if foo() { + } + else { + } + if foo() { } if foo() { diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 7399a0d4549..9f00a51bc1f 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,90 +1,119 @@ -error: this looks like an `else if` but the `else` is missing +error: this looks like an `else {..}` but the `else` is missing --> $DIR/formatting.rs:21:6 | -21 | } if foo() { +21 | } { | ^ | = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` + = note: to remove this lint, add the missing `else` or add a new line before the next block + +error: this looks like an `else if` but the `else` is missing + --> $DIR/formatting.rs:25:6 + | +25 | } if foo() { + | ^ + | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:28:10 + --> $DIR/formatting.rs:32:10 | -28 | } if foo() { +32 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:36:10 + --> $DIR/formatting.rs:40:10 | -36 | } if foo() { +40 | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` +error: this is an `else {..}` but the formatting might hide it + --> $DIR/formatting.rs:49:6 + | +49 | } else + | ______^ +50 | | { + | |____^ + | + = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` + +error: this is an `else {..}` but the formatting might hide it + --> $DIR/formatting.rs:54:6 + | +54 | } + | ______^ +55 | | else +56 | | { + | |____^ + | + = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` + error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:45:6 + --> $DIR/formatting.rs:60:6 | -45 | } else +60 | } else | ______^ -46 | | if foo() { // the span of the above error should continue here +61 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:50:6 + --> $DIR/formatting.rs:65:6 | -50 | } +65 | } | ______^ -51 | | else -52 | | if foo() { // the span of the above error should continue here +66 | | else +67 | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:77:6 - | -77 | a =- 35; - | ^^^^ - | - = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` - = note: to remove this lint, use either `-=` or `= -` + --> $DIR/formatting.rs:106:6 + | +106 | a =- 35; + | ^^^^ + | + = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` + = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:78:6 - | -78 | a =* &191; - | ^^^^ - | - = note: to remove this lint, use either `*=` or `= *` + --> $DIR/formatting.rs:107:6 + | +107 | a =* &191; + | ^^^^ + | + = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:81:6 - | -81 | b =! false; - | ^^^^ - | - = note: to remove this lint, use either `!=` or `= !` + --> $DIR/formatting.rs:110:6 + | +110 | b =! false; + | ^^^^ + | + = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:90:19 - | -90 | -1, -2, -3 // <= no comma here - | ^ - | - = note: `-D clippy::possible-missing-comma` implied by `-D warnings` - = note: to remove this lint, add a comma or write the expr in a single line + --> $DIR/formatting.rs:119:19 + | +119 | -1, -2, -3 // <= no comma here + | ^ + | + = note: `-D clippy::possible-missing-comma` implied by `-D warnings` + = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:94:19 - | -94 | -1, -2, -3 // <= no comma here - | ^ - | - = note: to remove this lint, add a comma or write the expr in a single line + --> $DIR/formatting.rs:123:19 + | +123 | -1, -2, -3 // <= no comma here + | ^ + | + = note: to remove this lint, add a comma or write the expr in a single line -error: aborting due to 10 previous errors +error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 05ae391e2cd1cd356e5db437f79ce1b6137dfa64 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Thu, 25 Oct 2018 21:16:46 -0400 Subject: Workaround rust-lang/rust#43081 --- clippy_lints/src/formatting.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 1fae0974d95..cc3801423c8 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -156,6 +156,11 @@ fn check_else(cx: &EarlyContext<'_>, expr: &ast::Expr) { && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) { + // workaround for rust-lang/rust#43081 + if expr.span.lo().0 == 0 && expr.span.hi().0 == 0 { + return; + } + // this will be a span from the closing ‘}’ of the “then” block (excluding) to // the // “if” of the “else if” block (excluding) -- cgit 1.4.1-3-g733a5 From ff634e235013e4fcb07a4266b3fe96c0db469b63 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 21 Dec 2018 08:11:06 +0100 Subject: Change contrib.md hierarchy, link to it from readme 'How Clippy works' and 'How to fix nightly failures' are not exactly part of 'Writing code'. --- CONTRIBUTING.md | 8 ++++---- README.md | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b5548bdd732..3d489b2e39a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,8 +19,8 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Running test suite](#running-test-suite) * [Running rustfmt](#running-rustfmt) * [Testing manually](#testing-manually) - * [How Clippy works](#how-clippy-works) - * [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) +* [How Clippy works](#how-clippy-works) +* [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) * [Issue and PR Triage](#issue-and-pr-triage) * [Bors and Homu](#bors-and-homu) * [Contributions](#contributions) @@ -168,7 +168,7 @@ Manually testing against an example file is useful if you have added some local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the working copy root. -### How Clippy works +## How Clippy works Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. @@ -218,7 +218,7 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. -### Fixing build failures caused by Rust +## Fixing build failures caused by Rust Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals. diff --git a/README.md b/README.md index 5c5d32e4a89..a5d5ed30e24 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,8 @@ Note: `deny` produces errors instead of warnings. If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` +## [Contributing](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md) + ## License Copyright 2014-2018 The Rust Project Developers -- cgit 1.4.1-3-g733a5 From c6031221e034ea3c41ffd129798c305cea439c01 Mon Sep 17 00:00:00 2001 From: Mark Nieweglowski Date: Sat, 22 Dec 2018 00:58:07 -0500 Subject: panic at map_unit_fn.rs:202 for map() without args --- clippy_lints/src/map_unit_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 39450deb84c..e5c17beb404 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -199,7 +199,6 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) { let var_arg = &map_args[0]; - let fn_arg = &map_args[1]; let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { ("Option", "Some", OPTION_MAP_UNIT_FN) @@ -208,6 +207,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr } else { return; }; + let fn_arg = &map_args[1]; if is_unit_function(cx, fn_arg) { let msg = suggestion_msg("function", map_type); -- cgit 1.4.1-3-g733a5 From a24853709a44c4e4f4e811c315ace8ef082a4ec0 Mon Sep 17 00:00:00 2001 From: Mark Nieweglowski Date: Sat, 22 Dec 2018 01:04:03 -0500 Subject: rm unused file map_unit_fn.stderr There is no map_unit_fn.rs whose output would be diffed with map_unit_fn.stderr map_unit_fn.stderr was renamed 8 months ago from option_map_unit_fn.stderr but option_map_unit_fn.{stderr,rs} both remain and are in use. --- tests/ui/map_unit_fn.stderr | 210 -------------------------------------------- 1 file changed, 210 deletions(-) delete mode 100644 tests/ui/map_unit_fn.stderr diff --git a/tests/ui/map_unit_fn.stderr b/tests/ui/map_unit_fn.stderr deleted file mode 100644 index c4ee0ce9238..00000000000 --- a/tests/ui/map_unit_fn.stderr +++ /dev/null @@ -1,210 +0,0 @@ -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:33:5 - | -33 | x.field.map(do_nothing); - | ^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` - | - = note: `-D option-map-unit-fn` implied by `-D warnings` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:35:5 - | -35 | x.field.map(do_nothing); - | ^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:37:5 - | -37 | x.field.map(diverge); - | ^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(x_field) = x.field { diverge(...) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:43:5 - | -43 | x.field.map(|value| x.do_option_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:45:5 - | -45 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:48:5 - | -48 | x.field.map(|value| do_nothing(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:50:5 - | -50 | x.field.map(|value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:52:5 - | -52 | x.field.map(|value| { do_nothing(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:54:5 - | -54 | x.field.map(|value| { { do_nothing(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:57:5 - | -57 | x.field.map(|value| diverge(value + captured)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:59:5 - | -59 | x.field.map(|value| { diverge(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:61:5 - | -61 | x.field.map(|value| { diverge(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:63:5 - | -63 | x.field.map(|value| { { diverge(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:68:5 - | -68 | x.field.map(|value| { let y = plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:70:5 - | -70 | x.field.map(|value| { plus_one(value + captured); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:72:5 - | -72 | x.field.map(|value| { { plus_one(value + captured); } }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:75:5 - | -75 | x.field.map(|ref value| { do_nothing(value + captured) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:78:5 - | -78 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:80:5 - | -80 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:84:5 - | -84 | x.field.map(|value| { - | _____^ - | |_____| - | || -85 | || do_nothing(value); -86 | || do_nothing(value) -87 | || }); - | ||______^- help: try this: `if let Some(value) = x.field { ... }` - | |_______| - | - -error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/map_unit_fn.rs:88:5 - | -88 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(value) = x.field { ... }` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:91:5 - | -91 | Some(42).map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(42) { diverge(...) }` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:92:5 - | -92 | "12".parse::().ok().map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:93:5 - | -93 | Some(plus_one(1)).map(do_nothing); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` - -error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/map_unit_fn.rs:97:5 - | -97 | y.map(do_nothing); - | ^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_y) = y { do_nothing(...) }` - -error: aborting due to 25 previous errors - -- cgit 1.4.1-3-g733a5 From d395d45ca753099c2ff952604169a1602eae898a Mon Sep 17 00:00:00 2001 From: Mark Nieweglowski Date: Sat, 22 Dec 2018 01:06:02 -0500 Subject: test: panic at map_unit_fn.rs:202 for map() without args --- tests/ui/map_unit_fn.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/ui/map_unit_fn.rs diff --git a/tests/ui/map_unit_fn.rs b/tests/ui/map_unit_fn.rs new file mode 100644 index 00000000000..1d203a147ba --- /dev/null +++ b/tests/ui/map_unit_fn.rs @@ -0,0 +1,20 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused)] +struct Mappable {} + +impl Mappable { + pub fn map(&self) {} +} + +fn main() { + let m = Mappable {}; + m.map(); +} -- cgit 1.4.1-3-g733a5 From cef8f57082a30bf3ead0f81ae81bd3a0b5969fab Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 22 Dec 2018 10:16:52 +0100 Subject: Remove header link --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a5d5ed30e24..8ca10da416d 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,9 @@ Note: `deny` produces errors instead of warnings. If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` -## [Contributing](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md) +## Contributing + +If you want to contribute to Clippy, you can find more information in [CONTRIBUTING.md](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md). ## License -- cgit 1.4.1-3-g733a5 From d2c069de1e85cf6d236d040a5be4021092bfdb57 Mon Sep 17 00:00:00 2001 From: Vlad-Shcherbina Date: Wed, 17 Jan 2018 21:40:47 +0300 Subject: Document map_clone known problems #498 (cherry picked from commit ada0d2c54831a904a53ff4106e0ebb6a0f06a687) --- clippy_lints/src/map_clone.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 8ca1fbb2759..d45fcc7e860 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -27,7 +27,9 @@ pub struct Pass; /// /// **Why is this bad?** Readability, this can be written more concisely /// -/// **Known problems:** None. +/// **Known problems:** Sometimes `.cloned()` requires stricter trait +/// bound than `.map(|e| e.clone())` (which works because of the coercion). +/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498). /// /// **Example:** /// -- cgit 1.4.1-3-g733a5 From ce3e69da1c3fd3bcb04c5260cbaab4bb521f2589 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 23 Dec 2018 10:42:06 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/56992 --- clippy_lints/src/attrs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a8b03d21482..8d4a2a84aab 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -337,7 +337,9 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { &name_lower, Some(tool_name.as_str()) ) { - CheckLintNameResult::NoLint => (), + // @TODO: can we suggest similar lint names here? + // https://github.com/rust-lang/rust/pull/56992 + CheckLintNameResult::NoLint(None) => (), _ => { db.span_suggestion(lint.span, "lowercase the lint name", -- cgit 1.4.1-3-g733a5 From 6db409fc0c34e8acbb47d24bdb39d701acf759f6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 23 Dec 2018 13:29:37 +0100 Subject: FIXME > TODO --- clippy_lints/src/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 8d4a2a84aab..7310e35116f 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -337,7 +337,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { &name_lower, Some(tool_name.as_str()) ) { - // @TODO: can we suggest similar lint names here? + // FIXME: can we suggest similar lint names here? // https://github.com/rust-lang/rust/pull/56992 CheckLintNameResult::NoLint(None) => (), _ => { -- cgit 1.4.1-3-g733a5 From b5587a894f34e77b103947d37594c91ce124a2c0 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 24 Dec 2018 22:06:08 +0100 Subject: Fix lint detection on macro expansion. --- clippy_lints/src/implicit_return.rs | 5 +++-- clippy_lints/src/loops.rs | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 96022db56aa..ee64c01b385 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -116,14 +116,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: FnKind<'tcx>, _: &'tcx FnDecl, body: &'tcx Body, - _: Span, + span: Span, _: NodeId, ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); // checking return type through MIR, HIR is not able to determine inferred closure return types - if !mir.return_ty().is_unit() { + // make sure it's not a macro + if !mir.return_ty().is_unit() && span.macro_backtrace().is_empty() { Self::expr_match(cx, &body.value); } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7ff43bd2da2..66a54ad2443 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -478,6 +478,11 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + // we don't want to check expanded macros + if !expr.span.macro_backtrace().is_empty() { + return; + } + if let Some((pat, arg, body)) = higher::for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); } -- cgit 1.4.1-3-g733a5 From a77bcadaa55801cc870ef740ca0d9fa4ca45df42 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 25 Dec 2018 12:48:54 +0100 Subject: Changed `macro_backtrace()` to `in_macro()`. --- clippy_lints/src/implicit_return.rs | 4 ++-- clippy_lints/src/loops.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index ee64c01b385..912ed43aab3 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -12,7 +12,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::{ast::NodeId, source_map::Span}; -use crate::utils::{snippet_opt, span_lint_and_then}; +use crate::utils::{snippet_opt, span_lint_and_then, in_macro}; /// **What it does:** Checks for missing return statements at the end of a block. /// @@ -124,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // checking return type through MIR, HIR is not able to determine inferred closure return types // make sure it's not a macro - if !mir.return_ty().is_unit() && span.macro_backtrace().is_empty() { + if !mir.return_ty().is_unit() && !in_macro(span) { Self::expr_match(cx, &body.value); } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 66a54ad2443..66f85e88398 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -479,7 +479,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // we don't want to check expanded macros - if !expr.span.macro_backtrace().is_empty() { + if !in_macro(expr.span) { return; } -- cgit 1.4.1-3-g733a5 From 197914439ac0354f48c35a8eb2b6c43a6999f7fc Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 25 Dec 2018 12:57:16 +0100 Subject: Fix macro detection in `empty_loop`. Co-Authored-By: daxpedda <1645124+daxpedda@users.noreply.github.com> --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 66f85e88398..8664061fb7a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -479,7 +479,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // we don't want to check expanded macros - if !in_macro(expr.span) { + if in_macro(expr.span) { return; } -- cgit 1.4.1-3-g733a5 From 6f5c0d2e0aa7dd8904f4105727819f711282eca2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 25 Dec 2018 16:44:44 +0100 Subject: rustc_tool_utils: expand Cargo.toml with a few keywords in preparation for crates.io release --- rustc_tools_util/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 020de6c3393..b73d7ca5606 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -2,5 +2,11 @@ name = "rustc_tools_util" version = "0.1.0" authors = ["Matthias Krüger "] +description = "small helper to generate version information for git packages" +repository = "https://github.com/rust-lang/rust-clippy" +readme = "README.md" +license = "MIT/Apache-2.0" +keywords = ["rustc", "tool", "git", "version", "hash"] +categories = ["development-tools"] edition = "2018" [dependencies] -- cgit 1.4.1-3-g733a5 From 345fe6d6c6f3598d008e20a80d4df982e99ccf45 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 25 Dec 2018 17:03:36 +0100 Subject: rustc_tools_util: add readme --- rustc_tools_util/README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 rustc_tools_util/README.md diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md new file mode 100644 index 00000000000..b101f55e509 --- /dev/null +++ b/rustc_tools_util/README.md @@ -0,0 +1,58 @@ +# rustc_tools_util + +A small tool to help you generate version information +for packages installed from a git repo + +## Usage + +Add a `build.rs` file to your repo and list it in `Cargo.toml` +```` +build = "build.rs" +```` + +List rustc_tools_util as regular AND build dependency. +```` +[dependencies] +rustc_tools_util = "0.1" + +[build-dependencies] +rustc_tools_util = "0.1" +```` + +In `build.rs`, generate the data in your `main()` +````rust +fn main() { + println!( + "cargo:rustc-env=GIT_HASH={}", + rustc_tools_util::get_commit_hash().unwrap_or_default() + ); + println!( + "cargo:rustc-env=COMMIT_DATE={}", + rustc_tools_util::get_commit_date().unwrap_or_default() + ); +} + +```` + +Use the version information in your main.rs +````rust +use rustc_tools_util::*; + +fn show_version() { + let version_info = rustc_tools_util::get_version_info!(); + println!("{}", version_info); +} +```` +This gives the following output in clippy: +`clippy 0.0.212 (a416c5e 2018-12-14)` + + +## License + +Copyright 2014-2018 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 or the MIT license +, at your +option. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. -- cgit 1.4.1-3-g733a5 From 5f0617b92fef67dc24c48f19bc9ade4314ca9015 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 25 Dec 2018 17:11:57 +0100 Subject: update CARGO_CLIPPY_HELP string to suggest tool lints. --- src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6c5cfe69166..369528f1954 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,10 +33,9 @@ with: -D --deny OPT Set lint denied -F --forbid OPT Set lint forbidden -The feature `cargo-clippy` is automatically defined for convenience. You can use -it to allow or deny lints from the code, eg.: +You can use tool lints to allow or deny lints from your code, eg.: - #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] + #[allow(clippy::needless_lifetimes)] "#; fn show_help() { -- cgit 1.4.1-3-g733a5 From 7f5e17f3f115664c0334ed5798edbcdb554e2ab0 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 25 Dec 2018 18:22:34 +0100 Subject: fix a couple of ftrivial typos (NFC). --- clippy_dev/src/lib.rs | 4 ++-- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/write.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 626afceecff..60f1a3df522 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -432,7 +432,7 @@ fn test_gen_deprecated() { "should_assert_eq", "group1", "abc", - Some("has been superseeded by should_assert_eq2"), + Some("has been superseded by should_assert_eq2"), "module_name", ), Lint::new( @@ -447,7 +447,7 @@ fn test_gen_deprecated() { let expected: Vec = vec![ " store.register_removed(", " \"should_assert_eq\",", - " \"has been superseeded by should_assert_eq2\",", + " \"has been superseded by should_assert_eq2\",", " );", " store.register_removed(", " \"another_deprecated\",", diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 25ce883cac8..89440845e5c 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -17,7 +17,7 @@ use crate::syntax::source_map::Span; use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; -/// **What it does:** Checks for double comparions that could be simpified to a single expression. +/// **What it does:** Checks for double comparions that could be simplified to a single expression. /// /// /// **Why is this bad?** Readability. diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 416ba4ca18d..20970632975 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -257,7 +257,7 @@ impl EarlyLintPass for Pass { } /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two -/// options. The first part of the tuple is `format_str` of the macros. The secund part of the tuple +/// options. The first part of the tuple is `format_str` of the macros. The second part of the tuple /// is in the `write[ln]!` case the expression the `format_str` should be written to. /// /// Example: -- cgit 1.4.1-3-g733a5 From cd602c8b18d79f197ce9d1e351748f733aa9051a Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Tue, 25 Dec 2018 16:11:28 -0500 Subject: fix breakage from rust-lang/rust#57088 --- tests/ui/builtin-type-shadow.rs | 1 + tests/ui/builtin-type-shadow.stderr | 10 ++--- tests/ui/enum_variants.rs | 1 + tests/ui/enum_variants.stderr | 88 ++++++++++++++++++------------------- 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index 66a7e318f8a..e9df0992c5e 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -8,6 +8,7 @@ // except according to those terms. #![warn(clippy::builtin_type_shadow)] +#![allow(non_camel_case_types)] fn foo(a: u32) -> u32 { 42 diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 540d9f4f458..f6ee513820e 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,17 +1,17 @@ error: This generic shadows the built-in type `u32` - --> $DIR/builtin-type-shadow.rs:12:8 + --> $DIR/builtin-type-shadow.rs:13:8 | -12 | fn foo(a: u32) -> u32 { +13 | fn foo(a: u32) -> u32 { | ^^^ | = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types - --> $DIR/builtin-type-shadow.rs:13:5 + --> $DIR/builtin-type-shadow.rs:14:5 | -12 | fn foo(a: u32) -> u32 { +13 | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type -13 | 42 +14 | 42 | ^^ expected type parameter, found integral variable | = note: expected type `u32` diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 0c8f3a36a3d..33472a7f83c 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -9,6 +9,7 @@ #![feature(non_ascii_idents)] #![warn(clippy::all, clippy::pub_enum_variant_names)] +#![allow(non_camel_case_types)] enum FakeCallType { CALL, diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index ff8f9b82ae6..1f554e2c33a 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,97 +1,97 @@ error: Variant name ends with the enum's name - --> $DIR/enum_variants.rs:24:5 + --> $DIR/enum_variants.rs:25:5 | -24 | cFoo, +25 | cFoo, | ^^^^ | = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:35:5 + --> $DIR/enum_variants.rs:36:5 | -35 | FoodGood, +36 | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:36:5 + --> $DIR/enum_variants.rs:37:5 | -36 | FoodMiddle, +37 | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:37:5 + --> $DIR/enum_variants.rs:38:5 | -37 | FoodBad, +38 | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:34:1 + --> $DIR/enum_variants.rs:35:1 | -34 | / enum Food { -35 | | FoodGood, -36 | | FoodMiddle, -37 | | FoodBad, -38 | | } +35 | / enum Food { +36 | | FoodGood, +37 | | FoodMiddle, +38 | | FoodBad, +39 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:44:1 + --> $DIR/enum_variants.rs:45:1 | -44 | / enum BadCallType { -45 | | CallTypeCall, -46 | | CallTypeCreate, -47 | | CallTypeDestroy, -48 | | } +45 | / enum BadCallType { +46 | | CallTypeCall, +47 | | CallTypeCreate, +48 | | CallTypeDestroy, +49 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:56:1 + --> $DIR/enum_variants.rs:57:1 | -56 | / enum Consts { -57 | | ConstantInt, -58 | | ConstantCake, -59 | | ConstantLie, -60 | | } +57 | / enum Consts { +58 | | ConstantInt, +59 | | ConstantCake, +60 | | ConstantLie, +61 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:90:1 + --> $DIR/enum_variants.rs:91:1 | -90 | / enum Seallll { -91 | | WithOutCake, -92 | | WithOutTea, -93 | | WithOut, -94 | | } +91 | / enum Seallll { +92 | | WithOutCake, +93 | | WithOutTea, +94 | | WithOut, +95 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:96:1 + --> $DIR/enum_variants.rs:97:1 | -96 | / enum NonCaps { -97 | | Prefix的, -98 | | PrefixTea, -99 | | PrefixCake, -100 | | } +97 | / enum NonCaps { +98 | | Prefix的, +99 | | PrefixTea, +100 | | PrefixCake, +101 | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:102:1 + --> $DIR/enum_variants.rs:103:1 | -102 | / pub enum PubSeall { -103 | | WithOutCake, -104 | | WithOutTea, -105 | | WithOut, -106 | | } +103 | / pub enum PubSeall { +104 | | WithOutCake, +105 | | WithOutTea, +106 | | WithOut, +107 | | } | |_^ | = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` -- cgit 1.4.1-3-g733a5 From 2d96ef1315ebf933be79533c6c39ec2e3d7d1b85 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 26 Dec 2018 18:13:33 +0100 Subject: Rustfmt. --- clippy_lints/src/implicit_return.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 912ed43aab3..dc1869ae04e 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -12,7 +12,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_errors::Applicability; use crate::syntax::{ast::NodeId, source_map::Span}; -use crate::utils::{snippet_opt, span_lint_and_then, in_macro}; +use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; /// **What it does:** Checks for missing return statements at the end of a block. /// -- cgit 1.4.1-3-g733a5 From 99454bc9a1d5d2325301286ff16b6fb032373447 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 27 Dec 2018 11:19:20 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/57069 --- clippy_lints/src/write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 20970632975..d226c6559c3 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -292,7 +292,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) - }; let tmp = fmtstr.clone(); let mut args = vec![]; - let mut fmt_parser = Parser::new(&tmp, None); + let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false); while let Some(piece) = fmt_parser.next() { if !fmt_parser.errors.is_empty() { return (None, expr); -- cgit 1.4.1-3-g733a5 From bcc309f27d8c619877bb9083031627b3fde29349 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 27 Dec 2018 12:16:08 +0100 Subject: base tests: switch to nightly toolchain before checking formatting of tests with rustfmt this errored because rustfmt is not available on the master toolchain --- ci/base-tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 537f7e124d4..d4da158a35f 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -42,9 +42,13 @@ set +x # some lints are sensitive to formatting, exclude some files needs_formatting=false +# switch to nightly +rustup default nightly for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/formatting.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true done +# switch back to master +rustup default master if [ "${needs_reformatting}" = true ] ; then echo "Tests need reformatting!" -- cgit 1.4.1-3-g733a5 From 84ee884cc4146f60c5a66a3d670b0f6cc0c0aab9 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 27 Dec 2018 12:40:07 +0100 Subject: base tests: make sure to fail CI if tests need formatting --- ci/base-tests.sh | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index d4da158a35f..377f6957746 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -36,22 +36,31 @@ cd .. cargo +nightly fmt --all -- --check -#avoid loop spam -set +x + + # make sure tests are formatted # some lints are sensitive to formatting, exclude some files -needs_formatting=false +tests_need_reformatting=false # switch to nightly rustup default nightly +# avoid loop spam and allow cmds with exit status != 0 +set +ex + for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/formatting.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do -rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true + rustfmt ${file} --check + if [ $? -ne 0 ]; then + echo "${file} needs reformatting!" + tests_need_reformatting=true + fi done -# switch back to master -rustup default master -if [ "${needs_reformatting}" = true ] ; then +set -ex # reset + +if [ ${tests_need_reformatting} ] ; then echo "Tests need reformatting!" exit 2 fi -set -x + +# switch back to master +rustup default master -- cgit 1.4.1-3-g733a5 From 38fabcbdf28854e9538cdbcd8031e1feaccb9c50 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 27 Dec 2018 16:17:45 +0100 Subject: tests: fix formatting and update test output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix script one last time™ --- ci/base-tests.sh | 9 +++------ tests/ui/cast_alignment.rs | 1 - tests/ui/cast_alignment.stderr | 8 ++++---- tests/ui/implicit_return.rs | 3 +-- tests/ui/implicit_return.stderr | 8 ++++---- tests/ui/new_without_default.rs | 8 ++++++-- tests/ui/partialeq_ne_impl.rs | 8 ++++++-- tests/ui/redundant_field_names.rs | 3 +-- tests/ui/unused_io_amount.rs | 1 - tests/ui/unused_io_amount.stderr | 24 ++++++++++++------------ tests/ui/vec_box_sized.rs | 8 ++++---- tests/ui/vec_box_sized.stderr | 2 +- 12 files changed, 42 insertions(+), 41 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 377f6957746..b69e86ad3ac 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -35,13 +35,10 @@ cd .. ./util/dev update_lints --check cargo +nightly fmt --all -- --check - - - # make sure tests are formatted # some lints are sensitive to formatting, exclude some files -tests_need_reformatting=false +tests_need_reformatting="false" # switch to nightly rustup default nightly # avoid loop spam and allow cmds with exit status != 0 @@ -51,13 +48,13 @@ for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/fo rustfmt ${file} --check if [ $? -ne 0 ]; then echo "${file} needs reformatting!" - tests_need_reformatting=true + tests_need_reformatting="true" fi done set -ex # reset -if [ ${tests_need_reformatting} ] ; then +if [ "${tests_need_reformatting}" == "true" ] ; then echo "Tests need reformatting!" exit 2 fi diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 77f50b3add2..dba19dfd023 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -9,7 +9,6 @@ //! Test casts for alignment issues - #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 1c7d53c3ce7..1db26c19725 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,15 +1,15 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:22:5 + --> $DIR/cast_alignment.rs:21:5 | -22 | (&1u8 as *const u8) as *const u16; +21 | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:23:5 + --> $DIR/cast_alignment.rs:22:5 | -23 | (&mut 1u8 as *mut u8) as *mut u16; +22 | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 9fb30135231..46ead9bf0c5 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -56,8 +56,7 @@ fn test_loop_with_nests() -> bool { loop { if true { break true; - } - else { + } else { let _ = true; } } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index b3562b67034..3c124eb3357 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -49,15 +49,15 @@ error: missing return statement | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:68:18 + --> $DIR/implicit_return.rs:67:18 | -68 | let _ = || { true }; +67 | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:69:16 + --> $DIR/implicit_return.rs:68:16 | -69 | let _ = || true; +68 | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: aborting due to 10 previous errors diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 2e715a6f8ba..efb8904dc97 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -143,14 +143,18 @@ pub struct Allow(Foo); impl Allow { #[allow(clippy::new_without_default)] - pub fn new() -> Self { unimplemented!() } + pub fn new() -> Self { + unimplemented!() + } } pub struct AllowDerive; impl AllowDerive { #[allow(clippy::new_without_default_derive)] - pub fn new() -> Self { unimplemented!() } + pub fn new() -> Self { + unimplemented!() + } } fn main() {} diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index fabeee24b30..e1e0413fcea 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -23,9 +23,13 @@ impl PartialEq for Foo { struct Bar; impl PartialEq for Bar { - fn eq(&self, _: &Bar) -> bool { true } + fn eq(&self, _: &Bar) -> bool { + true + } #[allow(clippy::partialeq_ne_impl)] - fn ne(&self, _: &Bar) -> bool { false } + fn ne(&self, _: &Bar) -> bool { + false + } } fn main() {} diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 3d727ee6e6a..60569372e5d 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -70,8 +70,7 @@ fn main() { } fn issue_3476() { - fn foo() { - } + fn foo() {} struct S { foo: fn(), diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 0ec8ce57ad7..4e721527249 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -12,7 +12,6 @@ use std::io; - fn try_macro(s: &mut T) -> io::Result<()> { try!(s.write(b"test")); let mut buf = [0u8; 4]; diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index f7b9b361502..200e441025e 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,42 +1,42 @@ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:17:5 + --> $DIR/unused_io_amount.rs:16:5 | -17 | try!(s.write(b"test")); +16 | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-io-amount` implied by `-D warnings` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:19:5 + --> $DIR/unused_io_amount.rs:18:5 | -19 | try!(s.read(&mut buf)); +18 | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:24:5 + --> $DIR/unused_io_amount.rs:23:5 | -24 | s.write(b"test")?; +23 | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:26:5 + --> $DIR/unused_io_amount.rs:25:5 | -26 | s.read(&mut buf)?; +25 | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:31:5 + --> $DIR/unused_io_amount.rs:30:5 | -31 | s.write(b"test").unwrap(); +30 | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:33:5 + --> $DIR/unused_io_amount.rs:32:5 | -33 | s.read(&mut buf).unwrap(); +32 | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs index d740f95edfe..884761675fc 100644 --- a/tests/ui/vec_box_sized.rs +++ b/tests/ui/vec_box_sized.rs @@ -1,17 +1,17 @@ struct SizedStruct { - _a: i32, + _a: i32, } struct UnsizedStruct { - _a: [i32], + _a: [i32], } struct StructWithVecBox { - sized_type: Vec>, + sized_type: Vec>, } struct StructWithVecBoxButItsUnsized { - unsized_type: Vec>, + unsized_type: Vec>, } fn main() {} diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index 7f4bdfb5aed..f085fdad429 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -1,5 +1,5 @@ error: `Vec` is already on the heap, the boxing is unnecessary. - --> $DIR/vec_box_sized.rs:10:14 + --> $DIR/vec_box_sized.rs:10:17 | 10 | sized_type: Vec>, | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` -- cgit 1.4.1-3-g733a5 From b5e545afc2623400a0ef5af272979724b3f83bc1 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 27 Dec 2018 17:34:17 +0100 Subject: Mention S-inactive-closed PRs in the CONTRIBUTING.md --- CONTRIBUTING.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d489b2e39a..94120a3771a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,6 +42,13 @@ Some issues are easier than others. The [`good first issue`](https://github.com/ label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! +There are also some abandoned PRs, marked with +[`S-inactive-closed`](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Aclosed+label%3AS-inactive-closed). +Pretty often these PRs are nearly completed and just need some extra steps +(formatting, addressing review comments, ...) to be merged. If you want to +complete such a PR, please leave a comment in the PR and open a new one based +on it. + Issues marked [`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) involve simple matching of the syntax tree structure, and are generally easier than [`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues, which involve types -- cgit 1.4.1-3-g733a5 From 9fddb2afceaf67a6656d88f7360626b10f48f636 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 27 Dec 2018 16:57:23 +0100 Subject: Use -Zui-testing flag --- tests/compile-test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5cb37b6b6fd..8b8ffe86f19 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -55,7 +55,10 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } - config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display())); + config.target_rustcflags = Some(format!( + "-L {0} -L {0}/deps -Dwarnings -Zui-testing", + host_libs().display() + )); config.mode = cfg_mode; config.build_base = if rustc_test_suite().is_some() { -- cgit 1.4.1-3-g733a5 From d2dbd0b8a56e46baf2a33b6c30b1ca31e02e963f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 27 Dec 2018 16:57:55 +0100 Subject: Update *.stderr files --- .../conf_french_blacklisted_name.stderr | 14 +- tests/ui-toml/toml_trivially_copy/test.stderr | 4 +- tests/ui/absurd-extreme-comparisons.stderr | 36 +- tests/ui/approx_const.stderr | 38 +- tests/ui/arithmetic.stderr | 24 +- tests/ui/assign_ops.stderr | 18 +- tests/ui/assign_ops2.stderr | 56 +- tests/ui/attrs.stderr | 6 +- tests/ui/author/matches.stderr | 4 +- tests/ui/bit_masks.stderr | 34 +- tests/ui/blacklisted_name.stderr | 28 +- tests/ui/block_in_if_condition.stderr | 28 +- tests/ui/bool_comparison.stderr | 28 +- tests/ui/booleans.stderr | 96 ++-- tests/ui/borrow_box.stderr | 10 +- tests/ui/box_vec.stderr | 2 +- tests/ui/builtin-type-shadow.stderr | 6 +- tests/ui/bytecount.stderr | 8 +- tests/ui/cast.stderr | 56 +- tests/ui/cast_alignment.stderr | 4 +- tests/ui/cast_lossless_float.stderr | 20 +- tests/ui/cast_lossless_integer.stderr | 36 +- tests/ui/cast_size.stderr | 38 +- tests/ui/cfg_attr_rustfmt.stderr | 6 +- tests/ui/char_lit_as_u8.stderr | 2 +- tests/ui/checked_unwrap.stderr | 164 +++--- tests/ui/cmp_nan.stderr | 24 +- tests/ui/cmp_null.stderr | 4 +- tests/ui/cmp_owned.stderr | 18 +- tests/ui/collapsible_if.stderr | 302 +++++----- tests/ui/complex_types.stderr | 30 +- tests/ui/const_static_lifetime.stderr | 26 +- tests/ui/copies.stderr | 622 ++++++++++----------- tests/ui/copy_iterator.stderr | 12 +- tests/ui/cstring.stderr | 4 +- tests/ui/cyclomatic_complexity.stderr | 446 +++++++-------- tests/ui/cyclomatic_complexity_attr_used.stderr | 14 +- tests/ui/decimal_literal_representation.stderr | 10 +- tests/ui/default_trait_access.stderr | 16 +- tests/ui/deprecated.stderr | 10 +- tests/ui/derive.stderr | 126 ++--- tests/ui/diverging_sub_expression.stderr | 12 +- tests/ui/dlist.stderr | 12 +- tests/ui/doc.stderr | 140 ++--- tests/ui/double_comparison.stderr | 16 +- tests/ui/double_neg.stderr | 2 +- tests/ui/double_parens.stderr | 12 +- tests/ui/drop_forget_copy.stderr | 24 +- tests/ui/drop_forget_ref.stderr | 72 +-- tests/ui/duplicate_underscore_argument.stderr | 2 +- tests/ui/duration_subsec.stderr | 10 +- tests/ui/else_if_without_else.stderr | 16 +- tests/ui/empty_enum.stderr | 4 +- tests/ui/empty_line_after_outer_attribute.stderr | 40 +- tests/ui/entry.stderr | 70 +-- tests/ui/enum_glob_use.stderr | 4 +- tests/ui/enum_variants.stderr | 90 +-- tests/ui/enums_clike.stderr | 16 +- tests/ui/eq_op.stderr | 74 +-- tests/ui/erasing_op.stderr | 6 +- tests/ui/escape_analysis.stderr | 10 +- tests/ui/eta.stderr | 10 +- tests/ui/eval_order_dependence.stderr | 16 +- tests/ui/excessive_precision.stderr | 36 +- tests/ui/expect_fun_call.stderr | 12 +- tests/ui/explicit_counter_loop.stderr | 8 +- tests/ui/explicit_write.stderr | 16 +- tests/ui/fallible_impl_from.stderr | 66 +-- tests/ui/filter_methods.stderr | 26 +- tests/ui/float_cmp.stderr | 12 +- tests/ui/float_cmp_const.stderr | 28 +- tests/ui/fn_to_numeric_cast.stderr | 46 +- tests/ui/for_loop.stderr | 482 ++++++++-------- tests/ui/for_loop_over_option_result.stderr | 28 +- tests/ui/format.stderr | 18 +- tests/ui/formatting.stderr | 92 +-- tests/ui/functions.stderr | 24 +- tests/ui/fxhash.stderr | 12 +- tests/ui/get_unwrap.stderr | 24 +- tests/ui/ice-2636.stderr | 10 +- tests/ui/identity_conversion.stderr | 22 +- tests/ui/identity_op.stderr | 16 +- tests/ui/if_not_else.stderr | 20 +- tests/ui/impl.stderr | 24 +- tests/ui/implicit_hasher.stderr | 58 +- tests/ui/implicit_return.stderr | 20 +- tests/ui/inconsistent_digit_grouping.stderr | 10 +- tests/ui/indexing_slicing.stderr | 86 +-- tests/ui/infallible_destructuring_match.stderr | 18 +- tests/ui/infinite_iter.stderr | 50 +- tests/ui/infinite_loop.stderr | 36 +- tests/ui/inline_fn_without_body.stderr | 12 +- tests/ui/int_plus_one.stderr | 16 +- tests/ui/into_iter_on_ref.stderr | 58 +- tests/ui/invalid_ref.stderr | 12 +- tests/ui/invalid_upcast_comparisons.stderr | 54 +- tests/ui/issue-3145.stderr | 2 +- tests/ui/issue_2356.stderr | 4 +- tests/ui/item_after_statement.stderr | 12 +- tests/ui/large_digit_groups.stderr | 12 +- tests/ui/large_enum_variant.stderr | 24 +- tests/ui/len_zero.stderr | 184 +++--- tests/ui/let_if_seq.stderr | 52 +- tests/ui/let_return.stderr | 8 +- tests/ui/let_unit.stderr | 4 +- tests/ui/lifetimes.stderr | 134 ++--- tests/ui/lint_without_lint_pass.stderr | 12 +- tests/ui/literals.stderr | 70 +-- tests/ui/map_clone.stderr | 6 +- tests/ui/map_flatten.stderr | 2 +- tests/ui/match_bool.stderr | 96 ++-- tests/ui/match_overlapping_arm.stderr | 20 +- tests/ui/matches.stderr | 218 ++++---- tests/ui/mem_discriminant.stderr | 28 +- tests/ui/mem_forget.stderr | 6 +- tests/ui/mem_replace.stderr | 4 +- tests/ui/methods.stderr | 572 +++++++++---------- tests/ui/min_max.stderr | 14 +- tests/ui/missing-doc.stderr | 244 ++++---- tests/ui/missing_inline.stderr | 12 +- tests/ui/module_inception.stderr | 12 +- tests/ui/module_name_repetitions.stderr | 10 +- tests/ui/modulo_one.stderr | 2 +- tests/ui/mut_from_ref.stderr | 20 +- tests/ui/mut_mut.stderr | 20 +- tests/ui/mut_range_bound.stderr | 10 +- tests/ui/mut_reference.stderr | 6 +- tests/ui/mutex_atomic.stderr | 14 +- tests/ui/needless_bool.stderr | 170 +++--- tests/ui/needless_borrow.stderr | 12 +- tests/ui/needless_borrowed_ref.stderr | 8 +- tests/ui/needless_collect.stderr | 8 +- tests/ui/needless_continue.stderr | 18 +- tests/ui/needless_pass_by_value.stderr | 188 +++---- tests/ui/needless_range_loop.stderr | 32 +- tests/ui/needless_return.stderr | 16 +- tests/ui/needless_update.stderr | 2 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 +- tests/ui/neg_multiply.stderr | 4 +- tests/ui/never_loop.stderr | 122 ++-- tests/ui/new_ret_no_self.stderr | 54 +- tests/ui/new_without_default.stderr | 32 +- tests/ui/no_effect.stderr | 56 +- tests/ui/non_copy_const.stderr | 260 ++++----- tests/ui/non_expressive_names.stderr | 124 ++-- tests/ui/ok_expect.stderr | 10 +- tests/ui/ok_if_let.stderr | 10 +- tests/ui/op_ref.stderr | 6 +- tests/ui/open_options.stderr | 14 +- tests/ui/option_map_unit_fn.stderr | 86 +-- tests/ui/option_option.stderr | 18 +- tests/ui/overflow_check_conditional.stderr | 16 +- tests/ui/panic_unimplemented.stderr | 10 +- tests/ui/partialeq_ne_impl.stderr | 6 +- tests/ui/patterns.stderr | 2 +- tests/ui/precedence.stderr | 18 +- tests/ui/print.stderr | 18 +- tests/ui/print_literal.stderr | 28 +- tests/ui/print_with_newline.stderr | 8 +- tests/ui/println_empty_string.stderr | 4 +- tests/ui/ptr_arg.stderr | 34 +- tests/ui/ptr_offset_with_cast.stderr | 4 +- tests/ui/question_mark.stderr | 28 +- tests/ui/range.stderr | 12 +- tests/ui/range_plus_minus_one.stderr | 16 +- tests/ui/redundant_clone.stderr | 40 +- tests/ui/redundant_closure_call.stderr | 10 +- tests/ui/redundant_field_names.stderr | 14 +- tests/ui/redundant_pattern_matching.stderr | 56 +- tests/ui/reference.stderr | 22 +- tests/ui/regex.stderr | 46 +- tests/ui/rename.stderr | 4 +- tests/ui/replace_consts.stderr | 72 +-- tests/ui/result_map_unit_fn.stderr | 72 +-- tests/ui/serde.stderr | 12 +- tests/ui/shadow.stderr | 46 +- tests/ui/short_circuit_statement.stderr | 6 +- tests/ui/single_char_pattern.stderr | 40 +- tests/ui/single_match.stderr | 64 +-- tests/ui/single_match_else.stderr | 22 +- tests/ui/slow_vector_initialization.stderr | 28 +- tests/ui/starts_ends_with.stderr | 24 +- tests/ui/string_extend.stderr | 6 +- tests/ui/strings.stderr | 22 +- tests/ui/suspicious_arithmetic_impl.stderr | 4 +- tests/ui/swap.stderr | 38 +- tests/ui/temporary_assignment.stderr | 4 +- tests/ui/toplevel_ref_arg.stderr | 10 +- tests/ui/trailing_zeros.stderr | 4 +- tests/ui/transmute.stderr | 208 +++---- tests/ui/transmute_64bit.stderr | 4 +- tests/ui/trivially_copy_pass_by_ref.stderr | 30 +- tests/ui/types.stderr | 2 +- tests/ui/unicode.stderr | 6 +- tests/ui/unit_arg.stderr | 38 +- tests/ui/unit_cmp.stderr | 20 +- tests/ui/unknown_clippy_lints.stderr | 4 +- tests/ui/unnecessary_clone.stderr | 36 +- tests/ui/unnecessary_filter_map.stderr | 24 +- tests/ui/unnecessary_fold.stderr | 10 +- tests/ui/unnecessary_operation.stderr | 48 +- tests/ui/unnecessary_ref.stderr | 4 +- tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unreadable_literal.stderr | 10 +- tests/ui/unsafe_removed_from_name.stderr | 6 +- tests/ui/unused_io_amount.stderr | 12 +- tests/ui/unused_labels.stderr | 22 +- tests/ui/unused_lt.stderr | 6 +- tests/ui/unused_unit.stderr | 18 +- tests/ui/unwrap_or.stderr | 4 +- tests/ui/use_self.stderr | 120 ++-- tests/ui/used_underscore_binding.stderr | 10 +- tests/ui/useless_asref.stderr | 36 +- tests/ui/useless_attribute.stderr | 4 +- tests/ui/vec.stderr | 12 +- tests/ui/vec_box_sized.stderr | 2 +- tests/ui/while_loop.stderr | 116 ++-- tests/ui/write_literal.stderr | 28 +- tests/ui/write_with_newline.stderr | 10 +- tests/ui/writeln_empty_string.stderr | 4 +- tests/ui/wrong_self_convention.stderr | 24 +- tests/ui/zero_div_zero.stderr | 16 +- tests/ui/zero_ptr.stderr | 4 +- 223 files changed, 4702 insertions(+), 4702 deletions(-) diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr index e67cdd8f9dd..9f35b1751ac 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -1,7 +1,7 @@ error: use of a blacklisted/placeholder name `toto` --> $DIR/conf_french_blacklisted_name.rs:15:9 | -15 | fn test(toto: ()) {} +LL | fn test(toto: ()) {} | ^^^^ | = note: `-D clippy::blacklisted-name` implied by `-D warnings` @@ -9,37 +9,37 @@ error: use of a blacklisted/placeholder name `toto` error: use of a blacklisted/placeholder name `toto` --> $DIR/conf_french_blacklisted_name.rs:18:9 | -18 | let toto = 42; +LL | let toto = 42; | ^^^^ error: use of a blacklisted/placeholder name `tata` --> $DIR/conf_french_blacklisted_name.rs:19:9 | -19 | let tata = 42; +LL | let tata = 42; | ^^^^ error: use of a blacklisted/placeholder name `titi` --> $DIR/conf_french_blacklisted_name.rs:20:9 | -20 | let titi = 42; +LL | let titi = 42; | ^^^^ error: use of a blacklisted/placeholder name `toto` --> $DIR/conf_french_blacklisted_name.rs:26:10 | -26 | (toto, Some(tata), titi @ Some(_)) => (), +LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `tata` --> $DIR/conf_french_blacklisted_name.rs:26:21 | -26 | (toto, Some(tata), titi @ Some(_)) => (), +LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `titi` --> $DIR/conf_french_blacklisted_name.rs:26:28 | -26 | (toto, Some(tata), titi @ Some(_)) => (), +LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index efa9223bde8..49cbc0691bc 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,7 +1,7 @@ error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/test.rs:20:11 | -20 | fn bad(x: &u16, y: &Foo) {} +LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` @@ -9,7 +9,7 @@ error: this argument is passed by reference, but would be more efficient if pass error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/test.rs:20:20 | -20 | fn bad(x: &u16, y: &Foo) {} +LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 00f7086dc55..5c8d537b21c 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -1,7 +1,7 @@ error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:23:5 | -23 | u <= 0; +LL | u <= 0; | ^^^^^^ | = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings` @@ -10,7 +10,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:24:5 | -24 | u <= Z; +LL | u <= Z; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == Z instead @@ -18,7 +18,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:25:5 | -25 | u < Z; +LL | u < Z; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false @@ -26,7 +26,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:26:5 | -26 | Z >= u; +LL | Z >= u; | ^^^^^^ | = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using Z == u instead @@ -34,7 +34,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:27:5 | -27 | Z > u; +LL | Z > u; | ^^^^^ | = help: because Z is the minimum value for this type, this comparison is always false @@ -42,7 +42,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:28:5 | -28 | u > std::u32::MAX; +LL | u > std::u32::MAX; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false @@ -50,7 +50,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:29:5 | -29 | u >= std::u32::MAX; +LL | u >= std::u32::MAX; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == std::u32::MAX instead @@ -58,7 +58,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:30:5 | -30 | std::u32::MAX < u; +LL | std::u32::MAX < u; | ^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, this comparison is always false @@ -66,7 +66,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:31:5 | -31 | std::u32::MAX <= u; +LL | std::u32::MAX <= u; | ^^^^^^^^^^^^^^^^^^ | = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using std::u32::MAX == u instead @@ -74,7 +74,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:32:5 | -32 | 1-1 > u; +LL | 1-1 > u; | ^^^^^^^ | = help: because 1-1 is the minimum value for this type, this comparison is always false @@ -82,7 +82,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:33:5 | -33 | u >= !0; +LL | u >= !0; | ^^^^^^^ | = help: because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead @@ -90,7 +90,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:34:5 | -34 | u <= 12 - 2*6; +LL | u <= 12 - 2*6; | ^^^^^^^^^^^^^ | = help: because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead @@ -98,7 +98,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:36:5 | -36 | i < -127 - 1; +LL | i < -127 - 1; | ^^^^^^^^^^^^ | = help: because -127 - 1 is the minimum value for this type, this comparison is always false @@ -106,7 +106,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:37:5 | -37 | std::i8::MAX >= i; +LL | std::i8::MAX >= i; | ^^^^^^^^^^^^^^^^^ | = help: because std::i8::MAX is the maximum value for this type, this comparison is always true @@ -114,7 +114,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:38:5 | -38 | 3-7 < std::i32::MIN; +LL | 3-7 < std::i32::MIN; | ^^^^^^^^^^^^^^^^^^^ | = help: because std::i32::MIN is the minimum value for this type, this comparison is always false @@ -122,7 +122,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:40:5 | -40 | b >= true; +LL | b >= true; | ^^^^^^^^^ | = help: because true is the maximum value for this type, the case where the two sides are not equal never occurs, consider using b == true instead @@ -130,7 +130,7 @@ error: this comparison involving the minimum or maximum element for this type co error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:41:5 | -41 | false > b; +LL | false > b; | ^^^^^^^^^ | = help: because false is the minimum value for this type, this comparison is always false @@ -138,7 +138,7 @@ error: this comparison involving the minimum or maximum element for this type co error: <-comparison of unit values detected. This will always be false --> $DIR/absurd-extreme-comparisons.rs:44:5 | -44 | () < {}; +LL | () < {}; | ^^^^^^^ | = note: #[deny(clippy::unit_cmp)] on by default diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index cee7fe6919a..c29ea3d467a 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -1,7 +1,7 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly --> $DIR/approx_const.rs:13:16 | -13 | let my_e = 2.7182; +LL | let my_e = 2.7182; | ^^^^^^ | = note: `-D clippy::approx-constant` implied by `-D warnings` @@ -9,109 +9,109 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it dire error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly --> $DIR/approx_const.rs:14:20 | -14 | let almost_e = 2.718; +LL | let almost_e = 2.718; | ^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly --> $DIR/approx_const.rs:17:24 | -17 | let my_1_frac_pi = 0.3183; +LL | let my_1_frac_pi = 0.3183; | ^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly --> $DIR/approx_const.rs:20:28 | -20 | let my_frac_1_sqrt_2 = 0.70710678; +LL | let my_frac_1_sqrt_2 = 0.70710678; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly --> $DIR/approx_const.rs:21:32 | -21 | let almost_frac_1_sqrt_2 = 0.70711; +LL | let almost_frac_1_sqrt_2 = 0.70711; | ^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly --> $DIR/approx_const.rs:24:24 | -24 | let my_frac_2_pi = 0.63661977; +LL | let my_frac_2_pi = 0.63661977; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly --> $DIR/approx_const.rs:27:27 | -27 | let my_frac_2_sq_pi = 1.128379; +LL | let my_frac_2_sq_pi = 1.128379; | ^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly --> $DIR/approx_const.rs:30:24 | -30 | let my_frac_pi_2 = 1.57079632679; +LL | let my_frac_pi_2 = 1.57079632679; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly --> $DIR/approx_const.rs:33:24 | -33 | let my_frac_pi_3 = 1.04719755119; +LL | let my_frac_pi_3 = 1.04719755119; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly --> $DIR/approx_const.rs:36:24 | -36 | let my_frac_pi_4 = 0.785398163397; +LL | let my_frac_pi_4 = 0.785398163397; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly --> $DIR/approx_const.rs:39:24 | -39 | let my_frac_pi_6 = 0.523598775598; +LL | let my_frac_pi_6 = 0.523598775598; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly --> $DIR/approx_const.rs:42:24 | -42 | let my_frac_pi_8 = 0.3926990816987; +LL | let my_frac_pi_8 = 0.3926990816987; | ^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly --> $DIR/approx_const.rs:45:20 | -45 | let my_ln_10 = 2.302585092994046; +LL | let my_ln_10 = 2.302585092994046; | ^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly --> $DIR/approx_const.rs:48:19 | -48 | let my_ln_2 = 0.6931471805599453; +LL | let my_ln_2 = 0.6931471805599453; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly --> $DIR/approx_const.rs:51:22 | -51 | let my_log10_e = 0.4342944819032518; +LL | let my_log10_e = 0.4342944819032518; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly --> $DIR/approx_const.rs:54:21 | -54 | let my_log2_e = 1.4426950408889634; +LL | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly --> $DIR/approx_const.rs:57:17 | -57 | let my_pi = 3.1415; +LL | let my_pi = 3.1415; | ^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly --> $DIR/approx_const.rs:58:21 | -58 | let almost_pi = 3.14; +LL | let almost_pi = 3.14; | ^^^^ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly --> $DIR/approx_const.rs:61:18 | -61 | let my_sq2 = 1.4142; +LL | let my_sq2 = 1.4142; | ^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index 1dff9941bb2..cea9676c2b8 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,7 +1,7 @@ error: integer arithmetic detected --> $DIR/arithmetic.rs:22:5 | -22 | 1 + i; +LL | 1 + i; | ^^^^^ | = note: `-D clippy::integer-arithmetic` implied by `-D warnings` @@ -9,32 +9,32 @@ error: integer arithmetic detected error: integer arithmetic detected --> $DIR/arithmetic.rs:23:5 | -23 | i * 2; +LL | i * 2; | ^^^^^ error: integer arithmetic detected --> $DIR/arithmetic.rs:24:5 | -24 | / 1 % -25 | | i / 2; // no error, this is part of the expression in the preceding line +LL | / 1 % +LL | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected --> $DIR/arithmetic.rs:26:5 | -26 | i - 2 + 2 - i; +LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected --> $DIR/arithmetic.rs:27:5 | -27 | -i; +LL | -i; | ^^ error: floating-point arithmetic detected --> $DIR/arithmetic.rs:37:5 | -37 | f * 2.0; +LL | f * 2.0; | ^^^^^^^ | = note: `-D clippy::float-arithmetic` implied by `-D warnings` @@ -42,31 +42,31 @@ error: floating-point arithmetic detected error: floating-point arithmetic detected --> $DIR/arithmetic.rs:39:5 | -39 | 1.0 + f; +LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected --> $DIR/arithmetic.rs:40:5 | -40 | f * 2.0; +LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected --> $DIR/arithmetic.rs:41:5 | -41 | f / 2.0; +LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected --> $DIR/arithmetic.rs:42:5 | -42 | f - 2.0 * 4.2; +LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected --> $DIR/arithmetic.rs:43:5 | -43 | -f; +LL | -f; | ^^ error: aborting due to 11 previous errors diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 7acbdc89984..194033981e1 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,7 +1,7 @@ error: manual implementation of an assign operation --> $DIR/assign_ops.rs:14:5 | -14 | a = a + 1; +LL | a = a + 1; | ^^^^^^^^^ help: replace it with: `a += 1` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` @@ -9,49 +9,49 @@ error: manual implementation of an assign operation error: manual implementation of an assign operation --> $DIR/assign_ops.rs:15:5 | -15 | a = 1 + a; +LL | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:16:5 | -16 | a = a - 1; +LL | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:17:5 | -17 | a = a * 99; +LL | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:18:5 | -18 | a = 42 * a; +LL | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:19:5 | -19 | a = a / 2; +LL | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:20:5 | -20 | a = a % 5; +LL | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:21:5 | -21 | a = a & 1; +LL | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation --> $DIR/assign_ops.rs:27:5 | -27 | s = s + "bla"; +LL | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: aborting due to 9 previous errors diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 26ff079ad62..99983c0d054 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -1,135 +1,135 @@ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:14:5 | -14 | a += a + 1; +LL | a += a + 1; | ^^^^^^^^^^ | = note: `-D clippy::misrefactored-assign-op` implied by `-D warnings` help: Did you mean a = a + 1 or a = a + a + 1? Consider replacing it with | -14 | a += 1; +LL | a += 1; | ^^^^^^ help: or | -14 | a = a + a + 1; +LL | a = a + a + 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:15:5 | -15 | a += 1 + a; +LL | a += 1 + a; | ^^^^^^^^^^ help: Did you mean a = a + 1 or a = a + 1 + a? Consider replacing it with | -15 | a += 1; +LL | a += 1; | ^^^^^^ help: or | -15 | a = a + 1 + a; +LL | a = a + 1 + a; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:16:5 | -16 | a -= a - 1; +LL | a -= a - 1; | ^^^^^^^^^^ help: Did you mean a = a - 1 or a = a - (a - 1)? Consider replacing it with | -16 | a -= 1; +LL | a -= 1; | ^^^^^^ help: or | -16 | a = a - (a - 1); +LL | a = a - (a - 1); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:17:5 | -17 | a *= a * 99; +LL | a *= a * 99; | ^^^^^^^^^^^ help: Did you mean a = a * 99 or a = a * a * 99? Consider replacing it with | -17 | a *= 99; +LL | a *= 99; | ^^^^^^^ help: or | -17 | a = a * a * 99; +LL | a = a * a * 99; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:18:5 | -18 | a *= 42 * a; +LL | a *= 42 * a; | ^^^^^^^^^^^ help: Did you mean a = a * 42 or a = a * 42 * a? Consider replacing it with | -18 | a *= 42; +LL | a *= 42; | ^^^^^^^ help: or | -18 | a = a * 42 * a; +LL | a = a * 42 * a; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:19:5 | -19 | a /= a / 2; +LL | a /= a / 2; | ^^^^^^^^^^ help: Did you mean a = a / 2 or a = a / (a / 2)? Consider replacing it with | -19 | a /= 2; +LL | a /= 2; | ^^^^^^ help: or | -19 | a = a / (a / 2); +LL | a = a / (a / 2); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:20:5 | -20 | a %= a % 5; +LL | a %= a % 5; | ^^^^^^^^^^ help: Did you mean a = a % 5 or a = a % (a % 5)? Consider replacing it with | -20 | a %= 5; +LL | a %= 5; | ^^^^^^ help: or | -20 | a = a % (a % 5); +LL | a = a % (a % 5); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:21:5 | -21 | a &= a & 1; +LL | a &= a & 1; | ^^^^^^^^^^ help: Did you mean a = a & 1 or a = a & a & 1? Consider replacing it with | -21 | a &= 1; +LL | a &= 1; | ^^^^^^ help: or | -21 | a = a & a & 1; +LL | a = a & a & 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation --> $DIR/assign_ops2.rs:22:5 | -22 | a *= a * a; +LL | a *= a * a; | ^^^^^^^^^^ help: Did you mean a = a * a or a = a * a * a? Consider replacing it with | -22 | a *= a; +LL | a *= a; | ^^^^^^ help: or | -22 | a = a * a * a; +LL | a = a * a * a; | ^^^^^^^^^^^^^ error: manual implementation of an assign operation --> $DIR/assign_ops2.rs:59:5 | -59 | buf = buf + cows.clone(); +LL | buf = buf + cows.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index 1331fa2912c..bc40cb8c86d 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,7 +1,7 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea --> $DIR/attrs.rs:12:1 | -12 | #[inline(always)] +LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::inline-always` implied by `-D warnings` @@ -9,7 +9,7 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usuall error: the since field must contain a semver-compliant version --> $DIR/attrs.rs:32:14 | -32 | #[deprecated(since = "forever")] +LL | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::deprecated-semver` implied by `-D warnings` @@ -17,7 +17,7 @@ error: the since field must contain a semver-compliant version error: the since field must contain a semver-compliant version --> $DIR/attrs.rs:35:14 | -35 | #[deprecated(since = "1")] +LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr index 4b895b0b8e3..5fb2a01f1b2 100644 --- a/tests/ui/author/matches.stderr +++ b/tests/ui/author/matches.stderr @@ -1,14 +1,14 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. --> $DIR/matches.rs:18:13 | -18 | x +LL | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned --> $DIR/matches.rs:17:21 | -17 | let x = 3; +LL | let x = 3; | ^ error: aborting due to previous error diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 853f5a992f3..da883dcbfc4 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -1,7 +1,7 @@ error: &-masking with zero --> $DIR/bit_masks.rs:23:5 | -23 | x & 0 == 0; +LL | x & 0 == 0; | ^^^^^^^^^^ | = note: `-D clippy::bad-bit-mask` implied by `-D warnings` @@ -9,7 +9,7 @@ error: &-masking with zero error: this operation will always return zero. This is likely not the intended outcome --> $DIR/bit_masks.rs:23:5 | -23 | x & 0 == 0; +LL | x & 0 == 0; | ^^^^^ | = note: #[deny(clippy::erasing_op)] on by default @@ -17,73 +17,73 @@ error: this operation will always return zero. This is likely not the intended o error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:26:5 | -26 | x & 2 == 1; +LL | x & 2 == 1; | ^^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` --> $DIR/bit_masks.rs:30:5 | -30 | x | 3 == 2; +LL | x | 3 == 2; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 1` will never be higher than `1` --> $DIR/bit_masks.rs:32:5 | -32 | x & 1 > 1; +LL | x & 1 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` --> $DIR/bit_masks.rs:36:5 | -36 | x | 2 > 1; +LL | x | 2 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ & 7` can never be equal to `8` --> $DIR/bit_masks.rs:43:5 | -43 | x & THREE_BITS == 8; +LL | x & THREE_BITS == 8; | ^^^^^^^^^^^^^^^^^^^ error: incompatible bit mask: `_ | 7` will never be lower than `7` --> $DIR/bit_masks.rs:44:5 | -44 | x | EVEN_MORE_REDIRECTION < 7; +LL | x | EVEN_MORE_REDIRECTION < 7; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &-masking with zero --> $DIR/bit_masks.rs:46:5 | -46 | 0 & x == 0; +LL | 0 & x == 0; | ^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome --> $DIR/bit_masks.rs:46:5 | -46 | 0 & x == 0; +LL | 0 & x == 0; | ^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` --> $DIR/bit_masks.rs:50:5 | -50 | 1 < 2 | x; +LL | 1 < 2 | x; | ^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` --> $DIR/bit_masks.rs:51:5 | -51 | 2 == 3 | x; +LL | 2 == 3 | x; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:52:5 | -52 | 1 == x & 2; +LL | 1 == x & 2; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly --> $DIR/bit_masks.rs:63:5 | -63 | x | 1 > 3; +LL | x | 1 > 3; | ^^^^^^^^^ | = note: `-D clippy::ineffective-bit-mask` implied by `-D warnings` @@ -91,19 +91,19 @@ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly --> $DIR/bit_masks.rs:64:5 | -64 | x | 1 < 4; +LL | x | 1 < 4; | ^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly --> $DIR/bit_masks.rs:65:5 | -65 | x | 1 <= 3; +LL | x | 1 <= 3; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared directly --> $DIR/bit_masks.rs:66:5 | -66 | x | 1 >= 8; +LL | x | 1 >= 8; | ^^^^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 707d36b24b2..5b65d4ed13f 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -1,7 +1,7 @@ error: use of a blacklisted/placeholder name `foo` --> $DIR/blacklisted_name.rs:20:9 | -20 | fn test(foo: ()) {} +LL | fn test(foo: ()) {} | ^^^ | = note: `-D clippy::blacklisted-name` implied by `-D warnings` @@ -9,79 +9,79 @@ error: use of a blacklisted/placeholder name `foo` error: use of a blacklisted/placeholder name `foo` --> $DIR/blacklisted_name.rs:23:9 | -23 | let foo = 42; +LL | let foo = 42; | ^^^ error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:24:9 | -24 | let bar = 42; +LL | let bar = 42; | ^^^ error: use of a blacklisted/placeholder name `baz` --> $DIR/blacklisted_name.rs:25:9 | -25 | let baz = 42; +LL | let baz = 42; | ^^^ error: use of a blacklisted/placeholder name `foo` --> $DIR/blacklisted_name.rs:31:10 | -31 | (foo, Some(bar), baz @ Some(_)) => (), +LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:31:20 | -31 | (foo, Some(bar), baz @ Some(_)) => (), +LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `baz` --> $DIR/blacklisted_name.rs:31:26 | -31 | (foo, Some(bar), baz @ Some(_)) => (), +LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `foo` --> $DIR/blacklisted_name.rs:36:19 | -36 | fn issue_1647(mut foo: u8) { +LL | fn issue_1647(mut foo: u8) { | ^^^ error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:37:13 | -37 | let mut bar = 0; +LL | let mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` --> $DIR/blacklisted_name.rs:38:21 | -38 | if let Some(mut baz) = Some(42) {} +LL | if let Some(mut baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:42:13 | -42 | let ref bar = 0; +LL | let ref bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` --> $DIR/blacklisted_name.rs:43:21 | -43 | if let Some(ref baz) = Some(42) {} +LL | if let Some(ref baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:47:17 | -47 | let ref mut bar = 0; +LL | let ref mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` --> $DIR/blacklisted_name.rs:48:25 | -48 | if let Some(ref mut baz) = Some(42) {} +LL | if let Some(ref mut baz) = Some(42) {} | ^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index d83cef26a8b..522c7dc779e 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,11 +1,11 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' --> $DIR/block_in_if_condition.rs:35:8 | -35 | if { +LL | if { | ________^ -36 | | let x = 3; -37 | | x == 3 -38 | | } { +LL | | let x = 3; +LL | | x == 3 +LL | | } { | |_____^ | = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` @@ -21,7 +21,7 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; inste error: omit braces around single expression condition --> $DIR/block_in_if_condition.rs:46:8 | -46 | if { true } { +LL | if { true } { | ^^^^^^^^ | = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` @@ -33,27 +33,27 @@ error: omit braces around single expression condition error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' --> $DIR/block_in_if_condition.rs:66:17 | -66 | |x| { +LL | |x| { | _________________^ -67 | | let target = 3; -68 | | x == target -69 | | }, +LL | | let target = 3; +LL | | x == target +LL | | }, | |_____________^ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' --> $DIR/block_in_if_condition.rs:75:13 | -75 | |x| { +LL | |x| { | _____________^ -76 | | let target = 3; -77 | | x == target -78 | | }, +LL | | let target = 3; +LL | | x == target +LL | | }, | |_________^ error: this boolean expression can be simplified --> $DIR/block_in_if_condition.rs:85:8 | -85 | if true && x == 3 { +LL | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 9a12a8f089a..7bd48f2e3dc 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,7 +1,7 @@ error: equality checks against true are unnecessary --> $DIR/bool_comparison.rs:13:8 | -13 | if x == true { +LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` | = note: `-D clippy::bool-comparison` implied by `-D warnings` @@ -9,79 +9,79 @@ error: equality checks against true are unnecessary error: equality checks against false can be replaced by a negation --> $DIR/bool_comparison.rs:18:8 | -18 | if x == false { +LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary --> $DIR/bool_comparison.rs:23:8 | -23 | if true == x { +LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation --> $DIR/bool_comparison.rs:28:8 | -28 | if false == x { +LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation --> $DIR/bool_comparison.rs:33:8 | -33 | if x != true { +LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary --> $DIR/bool_comparison.rs:38:8 | -38 | if x != false { +LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation --> $DIR/bool_comparison.rs:43:8 | -43 | if true != x { +LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary --> $DIR/bool_comparison.rs:48:8 | -48 | if false != x { +LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation --> $DIR/bool_comparison.rs:53:8 | -53 | if x < true { +LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary --> $DIR/bool_comparison.rs:58:8 | -58 | if false < x { +LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary --> $DIR/bool_comparison.rs:63:8 | -63 | if x > false { +LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation --> $DIR/bool_comparison.rs:68:8 | -68 | if true > x { +LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified --> $DIR/bool_comparison.rs:74:8 | -74 | if x < y { +LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified --> $DIR/bool_comparison.rs:79:8 | -79 | if x > y { +LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` error: aborting due to 14 previous errors diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index 45205b978ef..c9446f5e4bc 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -1,20 +1,20 @@ error: this boolean expression contains a logic bug --> $DIR/booleans.rs:19:13 | -19 | let _ = a && b || a; +LL | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:19:18 | -19 | let _ = a && b || a; +LL | let _ = a && b || a; | ^ error: this boolean expression can be simplified --> $DIR/booleans.rs:21:13 | -21 | let _ = !true; +LL | let _ = !true; | ^^^^^ help: try: `false` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` @@ -22,182 +22,182 @@ error: this boolean expression can be simplified error: this boolean expression can be simplified --> $DIR/booleans.rs:22:13 | -22 | let _ = !false; +LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified --> $DIR/booleans.rs:23:13 | -23 | let _ = !!a; +LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression contains a logic bug --> $DIR/booleans.rs:24:13 | -24 | let _ = false && a; +LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:24:22 | -24 | let _ = false && a; +LL | let _ = false && a; | ^ error: this boolean expression can be simplified --> $DIR/booleans.rs:25:13 | -25 | let _ = false || a; +LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified --> $DIR/booleans.rs:30:13 | -30 | let _ = !(!a && b); +LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `!b || a` error: this boolean expression contains a logic bug --> $DIR/booleans.rs:40:13 | -40 | let _ = a == b && a != b; +LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:40:13 | -40 | let _ = a == b && a != b; +LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression can be simplified --> $DIR/booleans.rs:41:13 | -41 | let _ = a == b && c == 5 && a == b; +LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -41 | let _ = a == b && c == 5; +LL | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -41 | let _ = !(c != 5 || a != b); +LL | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified --> $DIR/booleans.rs:42:13 | -42 | let _ = a == b && c == 5 && b == a; +LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -42 | let _ = a == b && c == 5; +LL | let _ = a == b && c == 5; | ^^^^^^^^^^^^^^^^ -42 | let _ = !(c != 5 || a != b); +LL | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression contains a logic bug --> $DIR/booleans.rs:43:13 | -43 | let _ = a < b && a >= b; +LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:43:13 | -43 | let _ = a < b && a >= b; +LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug --> $DIR/booleans.rs:44:13 | -44 | let _ = a > b && a <= b; +LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression --> $DIR/booleans.rs:44:13 | -44 | let _ = a > b && a <= b; +LL | let _ = a > b && a <= b; | ^^^^^ error: this boolean expression can be simplified --> $DIR/booleans.rs:46:13 | -46 | let _ = a != b || !(a != b || c == d); +LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try | -46 | let _ = c != d || a != b; +LL | let _ = c != d || a != b; | ^^^^^^^^^^^^^^^^ -46 | let _ = !(a == b && c == d); +LL | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified --> $DIR/booleans.rs:54:13 | -54 | let _ = !a.is_some(); +LL | let _ = !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified --> $DIR/booleans.rs:56:13 | -56 | let _ = !a.is_none(); +LL | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified --> $DIR/booleans.rs:58:13 | -58 | let _ = !b.is_err(); +LL | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified --> $DIR/booleans.rs:60:13 | -60 | let _ = !b.is_ok(); +LL | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified --> $DIR/booleans.rs:62:13 | -62 | let _ = !(a.is_some() && !c); +LL | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` error: this boolean expression can be simplified --> $DIR/booleans.rs:63:13 | -63 | let _ = !(!c ^ c) || !a.is_some(); +LL | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` error: this boolean expression can be simplified --> $DIR/booleans.rs:64:13 | -64 | let _ = (!c ^ c) || !a.is_some(); +LL | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()` error: this boolean expression can be simplified --> $DIR/booleans.rs:65:13 | -65 | let _ = !c ^ c || !a.is_some(); +LL | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:137:8 - | -137 | if !res.is_ok() {} - | ^^^^^^^^^^^^ help: try: `res.is_err()` + --> $DIR/booleans.rs:137:8 + | +LL | if !res.is_ok() {} + | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:138:8 - | -138 | if !res.is_err() {} - | ^^^^^^^^^^^^^ help: try: `res.is_ok()` + --> $DIR/booleans.rs:138:8 + | +LL | if !res.is_err() {} + | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:141:8 - | -141 | if !res.is_some() {} - | ^^^^^^^^^^^^^^ help: try: `res.is_none()` + --> $DIR/booleans.rs:141:8 + | +LL | if !res.is_some() {} + | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:142:8 - | -142 | if !res.is_none() {} - | ^^^^^^^^^^^^^^ help: try: `res.is_some()` + --> $DIR/booleans.rs:142:8 + | +LL | if !res.is_none() {} + | ^^^^^^^^^^^^^^ help: try: `res.is_some()` error: aborting due to 25 previous errors diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 0e42fe177ba..33bd50286a5 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -1,31 +1,31 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` --> $DIR/borrow_box.rs:15:19 | -15 | pub fn test1(foo: &mut Box) { +LL | pub fn test1(foo: &mut Box) { | ^^^^^^^^^^^^^^ help: try: `&mut bool` | note: lint level defined here --> $DIR/borrow_box.rs:10:9 | -10 | #![deny(clippy::borrowed_box)] +LL | #![deny(clippy::borrowed_box)] | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` --> $DIR/borrow_box.rs:20:14 | -20 | let foo: &Box; +LL | let foo: &Box; | ^^^^^^^^^^ help: try: `&bool` error: you seem to be trying to use `&Box`. Consider using just `&T` --> $DIR/borrow_box.rs:24:10 | -24 | foo: &'a Box, +LL | foo: &'a Box, | ^^^^^^^^^^^^^ help: try: `&'a bool` error: you seem to be trying to use `&Box`. Consider using just `&T` --> $DIR/borrow_box.rs:28:17 | -28 | fn test4(a: &Box); +LL | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` error: aborting due to 4 previous errors diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index 84c0b6c36e3..8b5fc24a371 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -1,7 +1,7 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` --> $DIR/box_vec.rs:23:18 | -23 | pub fn test(foo: Box>) { +LL | pub fn test(foo: Box>) { | ^^^^^^^^^^^^^^ | = note: `-D clippy::box-vec` implied by `-D warnings` diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index f6ee513820e..9bfed9dbba8 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,7 +1,7 @@ error: This generic shadows the built-in type `u32` --> $DIR/builtin-type-shadow.rs:13:8 | -13 | fn foo(a: u32) -> u32 { +LL | fn foo(a: u32) -> u32 { | ^^^ | = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` @@ -9,9 +9,9 @@ error: This generic shadows the built-in type `u32` error[E0308]: mismatched types --> $DIR/builtin-type-shadow.rs:14:5 | -13 | fn foo(a: u32) -> u32 { +LL | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type -14 | 42 +LL | 42 | ^^ expected type parameter, found integral variable | = note: expected type `u32` diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 605cf287419..a2890fe5a6d 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,25 +1,25 @@ error: You appear to be counting bytes the naive way --> $DIR/bytecount.rs:14:13 | -14 | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count +LL | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` | note: lint level defined here --> $DIR/bytecount.rs:10:8 | -10 | #[deny(clippy::naive_bytecount)] +LL | #[deny(clippy::naive_bytecount)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way --> $DIR/bytecount.rs:16:13 | -16 | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count +LL | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` error: You appear to be counting bytes the naive way --> $DIR/bytecount.rs:28:13 | -28 | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count +LL | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` error: aborting due to 3 previous errors diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 1b6b1e6319c..78631ffa8c8 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,7 +1,7 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast.rs:20:5 | -20 | 1i32 as f32; +LL | 1i32 as f32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-precision-loss` implied by `-D warnings` @@ -9,37 +9,37 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast.rs:21:5 | -21 | 1i64 as f32; +LL | 1i64 as f32; | ^^^^^^^^^^^ error: casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) --> $DIR/cast.rs:22:5 | -22 | 1i64 as f64; +LL | 1i64 as f64; | ^^^^^^^^^^^ error: casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast.rs:23:5 | -23 | 1u32 as f32; +LL | 1u32 as f32; | ^^^^^^^^^^^ error: casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast.rs:24:5 | -24 | 1u64 as f32; +LL | 1u64 as f32; | ^^^^^^^^^^^ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) --> $DIR/cast.rs:25:5 | -25 | 1u64 as f64; +LL | 1u64 as f64; | ^^^^^^^^^^^ error: casting f32 to i32 may truncate the value --> $DIR/cast.rs:27:5 | -27 | 1f32 as i32; +LL | 1f32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` @@ -47,13 +47,13 @@ error: casting f32 to i32 may truncate the value error: casting f32 to u32 may truncate the value --> $DIR/cast.rs:28:5 | -28 | 1f32 as u32; +LL | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value --> $DIR/cast.rs:28:5 | -28 | 1f32 as u32; +LL | 1f32 as u32; | ^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` @@ -61,49 +61,49 @@ error: casting f32 to u32 may lose the sign of the value error: casting f64 to f32 may truncate the value --> $DIR/cast.rs:29:5 | -29 | 1f64 as f32; +LL | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value --> $DIR/cast.rs:30:5 | -30 | 1i32 as i8; +LL | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may lose the sign of the value --> $DIR/cast.rs:31:5 | -31 | 1i32 as u8; +LL | 1i32 as u8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value --> $DIR/cast.rs:31:5 | -31 | 1i32 as u8; +LL | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value --> $DIR/cast.rs:32:5 | -32 | 1f64 as isize; +LL | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value --> $DIR/cast.rs:33:5 | -33 | 1f64 as usize; +LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value --> $DIR/cast.rs:33:5 | -33 | 1f64 as usize; +LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value --> $DIR/cast.rs:35:5 | -35 | 1u8 as i8; +LL | 1u8 as i8; | ^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` @@ -111,31 +111,31 @@ error: casting u8 to i8 may wrap around the value error: casting u16 to i16 may wrap around the value --> $DIR/cast.rs:36:5 | -36 | 1u16 as i16; +LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value --> $DIR/cast.rs:37:5 | -37 | 1u32 as i32; +LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value --> $DIR/cast.rs:38:5 | -38 | 1u64 as i64; +LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value --> $DIR/cast.rs:39:5 | -39 | 1usize as isize; +LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting f32 to f64 may become silently lossy if types change --> $DIR/cast.rs:41:5 | -41 | 1.0f32 as f64; +LL | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` @@ -143,25 +143,25 @@ error: casting f32 to f64 may become silently lossy if types change error: casting u8 to u16 may become silently lossy if types change --> $DIR/cast.rs:43:5 | -43 | (1u8 + 1u8) as u16; +LL | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value --> $DIR/cast.rs:45:5 | -45 | 1i32 as u32; +LL | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value --> $DIR/cast.rs:46:5 | -46 | 1isize as usize; +LL | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) --> $DIR/cast.rs:49:5 | -49 | 1i32 as i32; +LL | 1i32 as i32; | ^^^^^^^^^^^ | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` @@ -169,13 +169,13 @@ error: casting to the same type is unnecessary (`i32` -> `i32`) error: casting to the same type is unnecessary (`f32` -> `f32`) --> $DIR/cast.rs:50:5 | -50 | 1f32 as f32; +LL | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) --> $DIR/cast.rs:51:5 | -51 | false as bool; +LL | false as bool; | ^^^^^^^^^^^^^ error: aborting due to 28 previous errors diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 1db26c19725..261bce613bf 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,7 +1,7 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) --> $DIR/cast_alignment.rs:21:5 | -21 | (&1u8 as *const u8) as *const u16; +LL | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` @@ -9,7 +9,7 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) --> $DIR/cast_alignment.rs:22:5 | -22 | (&mut 1u8 as *mut u8) as *mut u16; +LL | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 8380c7c84e2..2164315c35e 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,7 +1,7 @@ error: casting i8 to f32 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:14:5 | -14 | 1i8 as f32; +LL | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` @@ -9,55 +9,55 @@ error: casting i8 to f32 may become silently lossy if types change error: casting i8 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:15:5 | -15 | 1i8 as f64; +LL | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:16:5 | -16 | 1u8 as f32; +LL | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:17:5 | -17 | 1u8 as f64; +LL | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:18:5 | -18 | 1i16 as f32; +LL | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:19:5 | -19 | 1i16 as f64; +LL | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:20:5 | -20 | 1u16 as f32; +LL | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:21:5 | -21 | 1u16 as f64; +LL | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:22:5 | -22 | 1i32 as f64; +LL | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change --> $DIR/cast_lossless_float.rs:23:5 | -23 | 1u32 as f64; +LL | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` error: aborting due to 10 previous errors diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index e5558b66681..d9eb1be57f7 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,7 +1,7 @@ error: casting i8 to i16 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:14:5 | -14 | 1i8 as i16; +LL | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` @@ -9,103 +9,103 @@ error: casting i8 to i16 may become silently lossy if types change error: casting i8 to i32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:15:5 | -15 | 1i8 as i32; +LL | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:16:5 | -16 | 1i8 as i64; +LL | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:17:5 | -17 | 1u8 as i16; +LL | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:18:5 | -18 | 1u8 as i32; +LL | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:19:5 | -19 | 1u8 as i64; +LL | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:20:5 | -20 | 1u8 as u16; +LL | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:21:5 | -21 | 1u8 as u32; +LL | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:22:5 | -22 | 1u8 as u64; +LL | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:23:5 | -23 | 1i16 as i32; +LL | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:24:5 | -24 | 1i16 as i64; +LL | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:25:5 | -25 | 1u16 as i32; +LL | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:26:5 | -26 | 1u16 as i64; +LL | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:27:5 | -27 | 1u16 as u32; +LL | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:28:5 | -28 | 1u16 as u64; +LL | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:29:5 | -29 | 1i32 as i64; +LL | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:30:5 | -30 | 1u32 as i64; +LL | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change --> $DIR/cast_lossless_integer.rs:31:5 | -31 | 1u32 as u64; +LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` error: aborting due to 18 previous errors diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index 9f658d40523..eab1014128a 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,7 +1,7 @@ error: casting isize to i8 may truncate the value --> $DIR/cast_size.rs:20:5 | -20 | 1isize as i8; +LL | 1isize as i8; | ^^^^^^^^^^^^ | = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` @@ -9,7 +9,7 @@ error: casting isize to i8 may truncate the value error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) --> $DIR/cast_size.rs:21:5 | -21 | 1isize as f64; +LL | 1isize as f64; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-precision-loss` implied by `-D warnings` @@ -17,31 +17,31 @@ error: casting isize to f64 causes a loss of precision on targets with 64-bit wi error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) --> $DIR/cast_size.rs:22:5 | -22 | 1usize as f64; +LL | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast_size.rs:23:5 | -23 | 1isize as f32; +LL | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) --> $DIR/cast_size.rs:24:5 | -24 | 1usize as f32; +LL | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:25:5 | -25 | 1isize as i32; +LL | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value --> $DIR/cast_size.rs:26:5 | -26 | 1isize as u32; +LL | 1isize as u32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-sign-loss` implied by `-D warnings` @@ -49,25 +49,25 @@ error: casting isize to u32 may lose the sign of the value error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:26:5 | -26 | 1isize as u32; +LL | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:27:5 | -27 | 1usize as u32; +LL | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:28:5 | -28 | 1usize as i32; +LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:28:5 | -28 | 1usize as i32; +LL | 1usize as i32; | ^^^^^^^^^^^^^ | = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` @@ -75,49 +75,49 @@ error: casting usize to i32 may wrap around the value on targets with 32-bit wid error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:30:5 | -30 | 1i64 as isize; +LL | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value --> $DIR/cast_size.rs:31:5 | -31 | 1i64 as usize; +LL | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:31:5 | -31 | 1i64 as usize; +LL | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:32:5 | -32 | 1u64 as isize; +LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:32:5 | -32 | 1u64 as isize; +LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:33:5 | -33 | 1u64 as usize; +LL | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:34:5 | -34 | 1u32 as isize; +LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value --> $DIR/cast_size.rs:37:5 | -37 | 1i32 as usize; +LL | 1i32 as usize; | ^^^^^^^^^^^^^ error: aborting due to 19 previous errors diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index a6a27bd2ee8..233aafc3c79 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -1,7 +1,7 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes --> $DIR/cfg_attr_rustfmt.rs:25:5 | -25 | #[cfg_attr(rustfmt, rustfmt::skip)] +LL | #[cfg_attr(rustfmt, rustfmt::skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` | = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` @@ -9,13 +9,13 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes --> $DIR/cfg_attr_rustfmt.rs:29:1 | -29 | #[cfg_attr(rustfmt, rustfmt_skip)] +LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes --> $DIR/cfg_attr_rustfmt.rs:35:5 | -35 | #![cfg_attr(rustfmt, rustfmt_skip)] +LL | #![cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` error: aborting due to 3 previous errors diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index cee27df2a7d..a577c55d261 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -1,7 +1,7 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them --> $DIR/char_lit_as_u8.rs:13:13 | -13 | let c = 'a' as u8; +LL | let c = 'a' as u8; | ^^^^^^^^^ | = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index bce37d50226..7e6a487ad1e 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,313 +1,313 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:16:9 | -15 | if x.is_some() { +LL | if x.is_some() { | ----------- the check is happening here -16 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here --> $DIR/checked_unwrap.rs:10:35 | -10 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:18:9 | -15 | if x.is_some() { +LL | if x.is_some() { | ----------- because of this check ... -18 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ | note: lint level defined here --> $DIR/checked_unwrap.rs:10:9 | -10 | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:21:9 | -20 | if x.is_none() { +LL | if x.is_none() { | ----------- because of this check -21 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:23:9 | -20 | if x.is_none() { +LL | if x.is_none() { | ----------- the check is happening here ... -23 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:27:9 | -26 | if x.is_ok() { +LL | if x.is_ok() { | --------- the check is happening here -27 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:28:9 | -26 | if x.is_ok() { +LL | if x.is_ok() { | --------- because of this check -27 | x.unwrap(); // unnecessary -28 | x.unwrap_err(); // will panic +LL | x.unwrap(); // unnecessary +LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:30:9 | -26 | if x.is_ok() { +LL | if x.is_ok() { | --------- because of this check ... -30 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:31:9 | -26 | if x.is_ok() { +LL | if x.is_ok() { | --------- the check is happening here ... -31 | x.unwrap_err(); // unnecessary +LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:34:9 | -33 | if x.is_err() { +LL | if x.is_err() { | ---------- because of this check -34 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:35:9 | -33 | if x.is_err() { +LL | if x.is_err() { | ---------- the check is happening here -34 | x.unwrap(); // will panic -35 | x.unwrap_err(); // unnecessary +LL | x.unwrap(); // will panic +LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:37:9 | -33 | if x.is_err() { +LL | if x.is_err() { | ---------- the check is happening here ... -37 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:38:9 | -33 | if x.is_err() { +LL | if x.is_err() { | ---------- because of this check ... -38 | x.unwrap_err(); // will panic +LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:55:9 | -54 | if x.is_ok() && y.is_err() { +LL | if x.is_ok() && y.is_err() { | --------- the check is happening here -55 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:56:9 | -54 | if x.is_ok() && y.is_err() { +LL | if x.is_ok() && y.is_err() { | --------- because of this check -55 | x.unwrap(); // unnecessary -56 | x.unwrap_err(); // will panic +LL | x.unwrap(); // unnecessary +LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:57:9 | -54 | if x.is_ok() && y.is_err() { +LL | if x.is_ok() && y.is_err() { | ---------- because of this check ... -57 | y.unwrap(); // will panic +LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:58:9 | -54 | if x.is_ok() && y.is_err() { +LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here ... -58 | y.unwrap_err(); // unnecessary +LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:72:9 | -67 | if x.is_ok() || y.is_ok() { +LL | if x.is_ok() || y.is_ok() { | --------- because of this check ... -72 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:73:9 | -67 | if x.is_ok() || y.is_ok() { +LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -73 | x.unwrap_err(); // unnecessary +LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:74:9 | -67 | if x.is_ok() || y.is_ok() { +LL | if x.is_ok() || y.is_ok() { | --------- because of this check ... -74 | y.unwrap(); // will panic +LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:75:9 | -67 | if x.is_ok() || y.is_ok() { +LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here ... -75 | y.unwrap_err(); // unnecessary +LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:79:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here -79 | x.unwrap(); // unnecessary +LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:80:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check -79 | x.unwrap(); // unnecessary -80 | x.unwrap_err(); // will panic +LL | x.unwrap(); // unnecessary +LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:81:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check ... -81 | y.unwrap(); // will panic +LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:82:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here ... -82 | y.unwrap_err(); // unnecessary +LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:83:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here ... -83 | z.unwrap(); // unnecessary +LL | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:84:9 | -78 | if x.is_ok() && !(y.is_ok() || z.is_err()) { +LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check ... -84 | z.unwrap_err(); // will panic +LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:92:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -92 | x.unwrap(); // will panic +LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:93:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -93 | x.unwrap_err(); // unnecessary +LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:94:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here ... -94 | y.unwrap(); // unnecessary +LL | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. --> $DIR/checked_unwrap.rs:95:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check ... -95 | y.unwrap_err(); // will panic +LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. --> $DIR/checked_unwrap.rs:96:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check ... -96 | z.unwrap(); // will panic +LL | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/checked_unwrap.rs:97:9 | -86 | if x.is_ok() || !(y.is_ok() && z.is_err()) { +LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here ... -97 | z.unwrap_err(); // unnecessary +LL | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:105:13 - | -104 | if x.is_some() { - | ----------- the check is happening here -105 | x.unwrap(); // unnecessary - | ^^^^^^^^^^ + --> $DIR/checked_unwrap.rs:105:13 + | +LL | if x.is_some() { + | ----------- the check is happening here +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:107:13 - | -104 | if x.is_some() { - | ----------- because of this check + --> $DIR/checked_unwrap.rs:107:13 + | +LL | if x.is_some() { + | ----------- because of this check ... -107 | x.unwrap(); // will panic - | ^^^^^^^^^^ +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 6838e6ad7ae..2a7772308b8 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -1,7 +1,7 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:14:5 | -14 | x == std::f32::NAN; +LL | x == std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cmp-nan` implied by `-D warnings` @@ -9,67 +9,67 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:15:5 | -15 | x != std::f32::NAN; +LL | x != std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:16:5 | -16 | x < std::f32::NAN; +LL | x < std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:17:5 | -17 | x > std::f32::NAN; +LL | x > std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:18:5 | -18 | x <= std::f32::NAN; +LL | x <= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:19:5 | -19 | x >= std::f32::NAN; +LL | x >= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:22:5 | -22 | y == std::f64::NAN; +LL | y == std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:23:5 | -23 | y != std::f64::NAN; +LL | y != std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:24:5 | -24 | y < std::f64::NAN; +LL | y < std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:25:5 | -25 | y > std::f64::NAN; +LL | y > std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:26:5 | -26 | y <= std::f64::NAN; +LL | y <= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:27:5 | -27 | y >= std::f64::NAN; +LL | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 5038298d9c4..68789b5b635 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -1,7 +1,7 @@ error: Comparing with null is better expressed by the .is_null() method --> $DIR/cmp_null.rs:18:8 | -18 | if p == ptr::null() { +LL | if p == ptr::null() { | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::cmp-null` implied by `-D warnings` @@ -9,7 +9,7 @@ error: Comparing with null is better expressed by the .is_null() method error: Comparing with null is better expressed by the .is_null() method --> $DIR/cmp_null.rs:23:8 | -23 | if m == ptr::null_mut() { +LL | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 2d06f736967..9177c6bd73e 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -1,7 +1,7 @@ error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:14:14 | -14 | x != "foo".to_string(); +LL | x != "foo".to_string(); | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` | = note: `-D clippy::cmp-owned` implied by `-D warnings` @@ -9,49 +9,49 @@ error: this creates an owned instance just for comparison error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:16:9 | -16 | "foo".to_string() != x; +LL | "foo".to_string() != x; | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:23:10 | -23 | x != "foo".to_owned(); +LL | x != "foo".to_owned(); | ^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:25:10 | -25 | x != String::from("foo"); +LL | x != String::from("foo"); | ^^^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:29:5 | -29 | Foo.to_owned() == Foo; +LL | Foo.to_owned() == Foo; | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:31:30 | -31 | "abc".chars().filter(|c| c.to_owned() != 'X'); +LL | "abc".chars().filter(|c| c.to_owned() != 'X'); | ^^^^^^^^^^^^ help: try: `*c` error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:38:5 | -38 | y.to_owned() == *x; +LL | y.to_owned() == *x; | ^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:43:5 | -43 | y.to_owned() == **x; +LL | y.to_owned() == **x; | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison --> $DIR/cmp_owned.rs:50:9 | -50 | self.to_owned() == *other +LL | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: aborting due to 9 previous errors diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 1884045a2db..2c60234eb5d 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,260 +1,260 @@ error: this if statement can be collapsed --> $DIR/collapsible_if.rs:15:5 | -15 | / if x == "hello" { -16 | | if y == "world" { -17 | | println!("Hello world!"); -18 | | } -19 | | } +LL | / if x == "hello" { +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` help: try | -15 | if x == "hello" && y == "world" { -16 | println!("Hello world!"); -17 | } +LL | if x == "hello" && y == "world" { +LL | println!("Hello world!"); +LL | } | error: this if statement can be collapsed --> $DIR/collapsible_if.rs:21:5 | -21 | / if x == "hello" || x == "world" { -22 | | if y == "world" || y == "hello" { -23 | | println!("Hello world!"); -24 | | } -25 | | } +LL | / if x == "hello" || x == "world" { +LL | | if y == "world" || y == "hello" { +LL | | println!("Hello world!"); +LL | | } +LL | | } | |_____^ help: try | -21 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -22 | println!("Hello world!"); -23 | } +LL | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { +LL | println!("Hello world!"); +LL | } | error: this if statement can be collapsed --> $DIR/collapsible_if.rs:27:5 | -27 | / if x == "hello" && x == "world" { -28 | | if y == "world" || y == "hello" { -29 | | println!("Hello world!"); -30 | | } -31 | | } +LL | / if x == "hello" && x == "world" { +LL | | if y == "world" || y == "hello" { +LL | | println!("Hello world!"); +LL | | } +LL | | } | |_____^ help: try | -27 | if x == "hello" && x == "world" && (y == "world" || y == "hello") { -28 | println!("Hello world!"); -29 | } +LL | if x == "hello" && x == "world" && (y == "world" || y == "hello") { +LL | println!("Hello world!"); +LL | } | error: this if statement can be collapsed --> $DIR/collapsible_if.rs:33:5 | -33 | / if x == "hello" || x == "world" { -34 | | if y == "world" && y == "hello" { -35 | | println!("Hello world!"); -36 | | } -37 | | } +LL | / if x == "hello" || x == "world" { +LL | | if y == "world" && y == "hello" { +LL | | println!("Hello world!"); +LL | | } +LL | | } | |_____^ help: try | -33 | if (x == "hello" || x == "world") && y == "world" && y == "hello" { -34 | println!("Hello world!"); -35 | } +LL | if (x == "hello" || x == "world") && y == "world" && y == "hello" { +LL | println!("Hello world!"); +LL | } | error: this if statement can be collapsed --> $DIR/collapsible_if.rs:39:5 | -39 | / if x == "hello" && x == "world" { -40 | | if y == "world" && y == "hello" { -41 | | println!("Hello world!"); -42 | | } -43 | | } +LL | / if x == "hello" && x == "world" { +LL | | if y == "world" && y == "hello" { +LL | | println!("Hello world!"); +LL | | } +LL | | } | |_____^ help: try | -39 | if x == "hello" && x == "world" && y == "world" && y == "hello" { -40 | println!("Hello world!"); -41 | } +LL | if x == "hello" && x == "world" && y == "world" && y == "hello" { +LL | println!("Hello world!"); +LL | } | error: this if statement can be collapsed --> $DIR/collapsible_if.rs:45:5 | -45 | / if 42 == 1337 { -46 | | if 'a' != 'A' { -47 | | println!("world!") -48 | | } -49 | | } +LL | / if 42 == 1337 { +LL | | if 'a' != 'A' { +LL | | println!("world!") +LL | | } +LL | | } | |_____^ help: try | -45 | if 42 == 1337 && 'a' != 'A' { -46 | println!("world!") -47 | } +LL | if 42 == 1337 && 'a' != 'A' { +LL | println!("world!") +LL | } | error: this `else { if .. }` block can be collapsed --> $DIR/collapsible_if.rs:54:12 | -54 | } else { +LL | } else { | ____________^ -55 | | if y == "world" { -56 | | println!("world!") -57 | | } -58 | | } +LL | | if y == "world" { +LL | | println!("world!") +LL | | } +LL | | } | |_____^ help: try | -54 | } else if y == "world" { -55 | println!("world!") -56 | } +LL | } else if y == "world" { +LL | println!("world!") +LL | } | error: this `else { if .. }` block can be collapsed --> $DIR/collapsible_if.rs:62:12 | -62 | } else { +LL | } else { | ____________^ -63 | | if let Some(42) = Some(42) { -64 | | println!("world!") -65 | | } -66 | | } +LL | | if let Some(42) = Some(42) { +LL | | println!("world!") +LL | | } +LL | | } | |_____^ help: try | -62 | } else if let Some(42) = Some(42) { -63 | println!("world!") -64 | } +LL | } else if let Some(42) = Some(42) { +LL | println!("world!") +LL | } | error: this `else { if .. }` block can be collapsed --> $DIR/collapsible_if.rs:70:12 | -70 | } else { +LL | } else { | ____________^ -71 | | if y == "world" { -72 | | println!("world") -73 | | } +LL | | if y == "world" { +LL | | println!("world") +LL | | } ... | -76 | | } -77 | | } +LL | | } +LL | | } | |_____^ help: try | -70 | } else if y == "world" { -71 | println!("world") -72 | } -73 | else { -74 | println!("!") -75 | } +LL | } else if y == "world" { +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed --> $DIR/collapsible_if.rs:81:12 | -81 | } else { +LL | } else { | ____________^ -82 | | if let Some(42) = Some(42) { -83 | | println!("world") -84 | | } +LL | | if let Some(42) = Some(42) { +LL | | println!("world") +LL | | } ... | -87 | | } -88 | | } +LL | | } +LL | | } | |_____^ help: try | -81 | } else if let Some(42) = Some(42) { -82 | println!("world") -83 | } -84 | else { -85 | println!("!") -86 | } +LL | } else if let Some(42) = Some(42) { +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed --> $DIR/collapsible_if.rs:92:12 | -92 | } else { +LL | } else { | ____________^ -93 | | if let Some(42) = Some(42) { -94 | | println!("world") -95 | | } +LL | | if let Some(42) = Some(42) { +LL | | println!("world") +LL | | } ... | -98 | | } -99 | | } +LL | | } +LL | | } | |_____^ help: try | -92 | } else if let Some(42) = Some(42) { -93 | println!("world") -94 | } -95 | else { -96 | println!("!") -97 | } +LL | } else if let Some(42) = Some(42) { +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:103:12 - | -103 | } else { - | ____________^ -104 | | if x == "hello" { -105 | | println!("world") -106 | | } -... | -109 | | } -110 | | } - | |_____^ + --> $DIR/collapsible_if.rs:103:12 + | +LL | } else { + | ____________^ +LL | | if x == "hello" { +LL | | println!("world") +LL | | } +... | +LL | | } +LL | | } + | |_____^ help: try - | -103 | } else if x == "hello" { -104 | println!("world") -105 | } -106 | else { -107 | println!("!") -108 | } - | + | +LL | } else if x == "hello" { +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } + | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:114:12 - | -114 | } else { - | ____________^ -115 | | if let Some(42) = Some(42) { -116 | | println!("world") -117 | | } -... | -120 | | } -121 | | } - | |_____^ + --> $DIR/collapsible_if.rs:114:12 + | +LL | } else { + | ____________^ +LL | | if let Some(42) = Some(42) { +LL | | println!("world") +LL | | } +... | +LL | | } +LL | | } + | |_____^ help: try - | -114 | } else if let Some(42) = Some(42) { -115 | println!("world") -116 | } -117 | else { -118 | println!("!") -119 | } - | + | +LL | } else if let Some(42) = Some(42) { +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } + | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:173:5 - | -173 | / if x == "hello" { -174 | | if y == "world" { // Collapsible -175 | | println!("Hello world!"); -176 | | } -177 | | } - | |_____^ + --> $DIR/collapsible_if.rs:173:5 + | +LL | / if x == "hello" { +LL | | if y == "world" { // Collapsible +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ help: try - | -173 | if x == "hello" && y == "world" { // Collapsible -174 | println!("Hello world!"); -175 | } - | + | +LL | if x == "hello" && y == "world" { // Collapsible +LL | println!("Hello world!"); +LL | } + | error: aborting due to 14 previous errors diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 80f133fd1ce..8f46d38921d 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -1,7 +1,7 @@ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:16:12 | -16 | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::type-complexity` implied by `-D warnings` @@ -9,85 +9,85 @@ error: very complex type used. Consider factoring parts into `type` definitions error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:17:12 | -17 | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:20:8 | -20 | f: Vec>>, +LL | f: Vec>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:23:11 | -23 | struct TS(Vec>>); +LL | struct TS(Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:26:11 | -26 | Tuple(Vec>>), +LL | Tuple(Vec>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:27:17 | -27 | Struct { f: Vec>> }, +LL | Struct { f: Vec>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:31:14 | -31 | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); +LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:32:30 | -32 | fn impl_method(&self, p: Vec>>) {} +LL | fn impl_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:36:14 | -36 | const A: Vec>>; +LL | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:37:14 | -37 | type B = Vec>>; +LL | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:38:25 | -38 | fn method(&self, p: Vec>>); +LL | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:39:29 | -39 | fn def_method(&self, p: Vec>>) {} +LL | fn def_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:42:15 | -42 | fn test1() -> Vec>> { +LL | fn test1() -> Vec>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:46:14 | -46 | fn test2(_x: Vec>>) {} +LL | fn test2(_x: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions --> $DIR/complex_types.rs:49:13 | -49 | let _y: Vec>> = vec![]; +LL | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index ba53d0718fc..b3fabb3522f 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,7 +1,7 @@ error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:13:17 | -13 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` | = note: `-D clippy::const-static-lifetime` implied by `-D warnings` @@ -9,73 +9,73 @@ error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:17:21 | -17 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:19:32 | -19 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:19:47 | -19 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:21:18 | -21 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:21:30 | -21 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:23:17 | -23 | const VAR_SIX: &'static u8 = &5; +LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:25:29 | -25 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:25:39 | -25 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; +LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:27:20 | -27 | const VAR_HEIGHT: &'static Foo = &Foo {}; +LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:29:19 | -29 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:31:19 | -31 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: Constants have by default a `'static` lifetime --> $DIR/const_static_lifetime.rs:33:19 | -33 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: aborting due to 13 previous errors diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index e41fac0f686..659abf6fa7e 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,392 +1,392 @@ error: this `if` has identical blocks --> $DIR/copies.rs:50:12 | -50 | } else { +LL | } else { | ____________^ -51 | | //~ ERROR same body as `if` block -52 | | Foo { bar: 42 }; -53 | | 0..10; +LL | | //~ ERROR same body as `if` block +LL | | Foo { bar: 42 }; +LL | | 0..10; ... | -58 | | foo(); -59 | | } +LL | | foo(); +LL | | } | |_____^ | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this --> $DIR/copies.rs:42:13 | -42 | if true { +LL | if true { | _____________^ -43 | | Foo { bar: 42 }; -44 | | 0..10; -45 | | ..; +LL | | Foo { bar: 42 }; +LL | | 0..10; +LL | | ..; ... | -49 | | foo(); -50 | | } else { +LL | | foo(); +LL | | } else { | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:96:14 - | -96 | _ => { - | ______________^ -97 | | //~ ERROR match arms have same body -98 | | foo(); -99 | | let mut a = 42 + [23].len() as i32; -... | -104 | | a -105 | | }, - | |_________^ - | - = note: `-D clippy::match-same-arms` implied by `-D warnings` + --> $DIR/copies.rs:96:14 + | +LL | _ => { + | ______________^ +LL | | //~ ERROR match arms have same body +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +... | +LL | | a +LL | | }, + | |_________^ + | + = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:87:15 - | -87 | 42 => { - | _______________^ -88 | | foo(); -89 | | let mut a = 42 + [23].len() as i32; -90 | | if true { -... | -94 | | a -95 | | }, - | |_________^ + --> $DIR/copies.rs:87:15 + | +LL | 42 => { + | _______________^ +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { +... | +LL | | a +LL | | }, + | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:87:15 - | -87 | 42 => { - | _______________^ -88 | | foo(); -89 | | let mut a = 42 + [23].len() as i32; -90 | | if true { -... | -94 | | a -95 | | }, - | |_________^ + --> $DIR/copies.rs:87:15 + | +LL | 42 => { + | _______________^ +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { +... | +LL | | a +LL | | }, + | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:111:14 - | -111 | _ => 0, //~ ERROR match arms have same body - | ^ - | + --> $DIR/copies.rs:111:14 + | +LL | _ => 0, //~ ERROR match arms have same body + | ^ + | note: same as this - --> $DIR/copies.rs:109:19 - | -109 | Abc::A => 0, - | ^ + --> $DIR/copies.rs:109:19 + | +LL | Abc::A => 0, + | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:109:19 - | -109 | Abc::A => 0, - | ^ + --> $DIR/copies.rs:109:19 + | +LL | Abc::A => 0, + | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:120:12 - | -120 | } else { - | ____________^ -121 | | //~ ERROR same body as `if` block -122 | | 42 -123 | | }; - | |_____^ - | + --> $DIR/copies.rs:120:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | 42 +LL | | }; + | |_____^ + | note: same as this - --> $DIR/copies.rs:118:21 - | -118 | let _ = if true { - | _____________________^ -119 | | 42 -120 | | } else { - | |_____^ + --> $DIR/copies.rs:118:21 + | +LL | let _ = if true { + | _____________________^ +LL | | 42 +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:134:12 - | -134 | } else { - | ____________^ -135 | | //~ ERROR same body as `if` block -136 | | for _ in &[42] { -137 | | let foo: &Option<_> = &Some::(42); -... | -143 | | } -144 | | } - | |_____^ - | + --> $DIR/copies.rs:134:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | for _ in &[42] { +LL | | let foo: &Option<_> = &Some::(42); +... | +LL | | } +LL | | } + | |_____^ + | note: same as this - --> $DIR/copies.rs:125:13 - | -125 | if true { - | _____________^ -126 | | for _ in &[42] { -127 | | let foo: &Option<_> = &Some::(42); -128 | | if true { -... | -133 | | } -134 | | } else { - | |_____^ + --> $DIR/copies.rs:125:13 + | +LL | if true { + | _____________^ +LL | | for _ in &[42] { +LL | | let foo: &Option<_> = &Some::(42); +LL | | if true { +... | +LL | | } +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:153:12 - | -153 | } else { - | ____________^ -154 | | //~ ERROR same body as `if` block -155 | | let bar = if true { 42 } else { 43 }; -156 | | -... | -160 | | bar + 1; -161 | | } - | |_____^ - | + --> $DIR/copies.rs:153:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | let bar = if true { 42 } else { 43 }; +LL | | +... | +LL | | bar + 1; +LL | | } + | |_____^ + | note: same as this - --> $DIR/copies.rs:146:13 - | -146 | if true { - | _____________^ -147 | | let bar = if true { 42 } else { 43 }; -148 | | -149 | | while foo() { -... | -152 | | bar + 1; -153 | | } else { - | |_____^ + --> $DIR/copies.rs:146:13 + | +LL | if true { + | _____________^ +LL | | let bar = if true { 42 } else { 43 }; +LL | | +LL | | while foo() { +... | +LL | | bar + 1; +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:183:12 - | -183 | } else { - | ____________^ -184 | | //~ ERROR same body as `if` block -185 | | if let Some(a) = Some(42) {} -186 | | } - | |_____^ - | + --> $DIR/copies.rs:183:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | if let Some(a) = Some(42) {} +LL | | } + | |_____^ + | note: same as this - --> $DIR/copies.rs:181:13 - | -181 | if true { - | _____________^ -182 | | if let Some(a) = Some(42) {} -183 | | } else { - | |_____^ + --> $DIR/copies.rs:181:13 + | +LL | if true { + | _____________^ +LL | | if let Some(a) = Some(42) {} +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:190:12 - | -190 | } else { - | ____________^ -191 | | //~ ERROR same body as `if` block -192 | | if let (1, .., 3) = (1, 2, 3) {} -193 | | } - | |_____^ - | + --> $DIR/copies.rs:190:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | } + | |_____^ + | note: same as this - --> $DIR/copies.rs:188:13 - | -188 | if true { - | _____________^ -189 | | if let (1, .., 3) = (1, 2, 3) {} -190 | | } else { - | |_____^ + --> $DIR/copies.rs:188:13 + | +LL | if true { + | _____________^ +LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | } else { + | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:239:15 - | -239 | 51 => foo(), //~ ERROR match arms have same body - | ^^^^^ - | + --> $DIR/copies.rs:239:15 + | +LL | 51 => foo(), //~ ERROR match arms have same body + | ^^^^^ + | note: same as this - --> $DIR/copies.rs:238:15 - | -238 | 42 => foo(), - | ^^^^^ + --> $DIR/copies.rs:238:15 + | +LL | 42 => foo(), + | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:238:15 - | -238 | 42 => foo(), - | ^^^^^ + --> $DIR/copies.rs:238:15 + | +LL | 42 => foo(), + | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:245:17 - | -245 | None => 24, //~ ERROR match arms have same body - | ^^ - | + --> $DIR/copies.rs:245:17 + | +LL | None => 24, //~ ERROR match arms have same body + | ^^ + | note: same as this - --> $DIR/copies.rs:244:20 - | -244 | Some(_) => 24, - | ^^ + --> $DIR/copies.rs:244:20 + | +LL | Some(_) => 24, + | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:244:20 - | -244 | Some(_) => 24, - | ^^ + --> $DIR/copies.rs:244:20 + | +LL | Some(_) => 24, + | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:267:28 - | -267 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body - | ^^^^^^ - | + --> $DIR/copies.rs:267:28 + | +LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | note: same as this - --> $DIR/copies.rs:266:28 - | -266 | (Some(a), None) => bar(a), - | ^^^^^^ + --> $DIR/copies.rs:266:28 + | +LL | (Some(a), None) => bar(a), + | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:266:28 - | -266 | (Some(a), None) => bar(a), - | ^^^^^^ + --> $DIR/copies.rs:266:28 + | +LL | (Some(a), None) => bar(a), + | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:273:26 - | -273 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body - | ^^^^^^ - | + --> $DIR/copies.rs:273:26 + | +LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | note: same as this - --> $DIR/copies.rs:272:26 - | -272 | (Some(a), ..) => bar(a), - | ^^^^^^ + --> $DIR/copies.rs:272:26 + | +LL | (Some(a), ..) => bar(a), + | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:272:26 - | -272 | (Some(a), ..) => bar(a), - | ^^^^^^ + --> $DIR/copies.rs:272:26 + | +LL | (Some(a), ..) => bar(a), + | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:279:20 - | -279 | (.., 3) => 42, //~ ERROR match arms have same body - | ^^ - | + --> $DIR/copies.rs:279:20 + | +LL | (.., 3) => 42, //~ ERROR match arms have same body + | ^^ + | note: same as this - --> $DIR/copies.rs:278:23 - | -278 | (1, .., 3) => 42, - | ^^ + --> $DIR/copies.rs:278:23 + | +LL | (1, .., 3) => 42, + | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:278:23 - | -278 | (1, .., 3) => 42, - | ^^ + --> $DIR/copies.rs:278:23 + | +LL | (1, .., 3) => 42, + | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:285:12 - | -285 | } else { - | ____________^ -286 | | //~ ERROR same body as `if` block -287 | | 0.0 -288 | | }; - | |_____^ - | + --> $DIR/copies.rs:285:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | 0.0 +LL | | }; + | |_____^ + | note: same as this - --> $DIR/copies.rs:283:21 - | -283 | let _ = if true { - | _____________________^ -284 | | 0.0 -285 | | } else { - | |_____^ + --> $DIR/copies.rs:283:21 + | +LL | let _ = if true { + | _____________________^ +LL | | 0.0 +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:292:12 - | -292 | } else { - | ____________^ -293 | | //~ ERROR same body as `if` block -294 | | -0.0 -295 | | }; - | |_____^ - | + --> $DIR/copies.rs:292:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | -0.0 +LL | | }; + | |_____^ + | note: same as this - --> $DIR/copies.rs:290:21 - | -290 | let _ = if true { - | _____________________^ -291 | | -0.0 -292 | | } else { - | |_____^ + --> $DIR/copies.rs:290:21 + | +LL | let _ = if true { + | _____________________^ +LL | | -0.0 +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:305:12 - | -305 | } else { - | ____________^ -306 | | //~ ERROR same body as `if` block -307 | | std::f32::NAN -308 | | }; - | |_____^ - | + --> $DIR/copies.rs:305:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | std::f32::NAN +LL | | }; + | |_____^ + | note: same as this - --> $DIR/copies.rs:303:21 - | -303 | let _ = if true { - | _____________________^ -304 | | std::f32::NAN -305 | | } else { - | |_____^ + --> $DIR/copies.rs:303:21 + | +LL | let _ = if true { + | _____________________^ +LL | | std::f32::NAN +LL | | } else { + | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:323:12 - | -323 | } else { - | ____________^ -324 | | //~ ERROR same body as `if` block -325 | | try!(Ok("foo")); -326 | | } - | |_____^ - | + --> $DIR/copies.rs:323:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | try!(Ok("foo")); +LL | | } + | |_____^ + | note: same as this - --> $DIR/copies.rs:321:13 - | -321 | if true { - | _____________^ -322 | | try!(Ok("foo")); -323 | | } else { - | |_____^ + --> $DIR/copies.rs:321:13 + | +LL | if true { + | _____________^ +LL | | try!(Ok("foo")); +LL | | } else { + | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:347:15 - | -347 | } else if b { - | ^ - | - = note: `-D clippy::ifs-same-cond` implied by `-D warnings` + --> $DIR/copies.rs:347:15 + | +LL | } else if b { + | ^ + | + = note: `-D clippy::ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:346:8 - | -346 | if b { - | ^ + --> $DIR/copies.rs:346:8 + | +LL | if b { + | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:352:15 - | -352 | } else if a == 1 { - | ^^^^^^ - | + --> $DIR/copies.rs:352:15 + | +LL | } else if a == 1 { + | ^^^^^^ + | note: same as this - --> $DIR/copies.rs:351:8 - | -351 | if a == 1 { - | ^^^^^^ + --> $DIR/copies.rs:351:8 + | +LL | if a == 1 { + | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:15 - | -358 | } else if 2 * a == 1 { - | ^^^^^^^^^^ - | + --> $DIR/copies.rs:358:15 + | +LL | } else if 2 * a == 1 { + | ^^^^^^^^^^ + | note: same as this - --> $DIR/copies.rs:356:8 - | -356 | if 2 * a == 1 { - | ^^^^^^^^^^ + --> $DIR/copies.rs:356:8 + | +LL | if 2 * a == 1 { + | ^^^^^^^^^^ error: aborting due to 20 previous errors diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr index ced9293d1dc..34606df8595 100644 --- a/tests/ui/copy_iterator.stderr +++ b/tests/ui/copy_iterator.stderr @@ -1,13 +1,13 @@ error: you are implementing `Iterator` on a `Copy` type --> $DIR/copy_iterator.rs:15:1 | -15 | / impl Iterator for Countdown { -16 | | type Item = u8; -17 | | -18 | | fn next(&mut self) -> Option { +LL | / impl Iterator for Countdown { +LL | | type Item = u8; +LL | | +LL | | fn next(&mut self) -> Option { ... | -23 | | } -24 | | } +LL | | } +LL | | } | |_^ | = note: `-D clippy::copy-iterator` implied by `-D warnings` diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 490a655ca26..d2968eb9d18 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,7 +1,7 @@ error: you are getting the inner pointer of a temporary `CString` --> $DIR/cstring.rs:16:5 | -16 | CString::new("foo").unwrap().as_ptr(); +LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default @@ -9,7 +9,7 @@ error: you are getting the inner pointer of a temporary `CString` help: assign the `CString` to a variable to extend its lifetime --> $DIR/cstring.rs:16:5 | -16 | CString::new("foo").unwrap().as_ptr(); +LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index de9e5c77f1b..f8e3a54debd 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -1,272 +1,272 @@ error: the function has a cyclomatic complexity of 28 --> $DIR/cyclomatic_complexity.rs:15:1 | -15 | / fn main() { -16 | | if true { -17 | | println!("a"); -18 | | } +LL | / fn main() { +LL | | if true { +LL | | println!("a"); +LL | | } ... | -96 | | } -97 | | } +LL | | } +LL | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 - --> $DIR/cyclomatic_complexity.rs:100:1 - | -100 | / fn kaboom() { -101 | | let n = 0; -102 | | 'a: for i in 0..20 { -103 | | 'b: for j in i..20 { -... | -118 | | } -119 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:100:1 + | +LL | / fn kaboom() { +LL | | let n = 0; +LL | | 'a: for i in 0..20 { +LL | | 'b: for j in i..20 { +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:146:1 - | -146 | / fn lots_of_short_circuits() -> bool { -147 | | true && false && true && false && true && false && true -148 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:146:1 + | +LL | / fn lots_of_short_circuits() -> bool { +LL | | true && false && true && false && true && false && true +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:151:1 - | -151 | / fn lots_of_short_circuits2() -> bool { -152 | | true || false || true || false || true || false || true -153 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:151:1 + | +LL | / fn lots_of_short_circuits2() -> bool { +LL | | true || false || true || false || true || false || true +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:156:1 - | -156 | / fn baa() { -157 | | let x = || match 99 { -158 | | 0 => 0, -159 | | 1 => 1, -... | -170 | | } -171 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:156:1 + | +LL | / fn baa() { +LL | | let x = || match 99 { +LL | | 0 => 0, +LL | | 1 => 1, +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:157:13 - | -157 | let x = || match 99 { - | _____________^ -158 | | 0 => 0, -159 | | 1 => 1, -160 | | 2 => 2, -... | -164 | | _ => 42, -165 | | }; - | |_____^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:157:13 + | +LL | let x = || match 99 { + | _____________^ +LL | | 0 => 0, +LL | | 1 => 1, +LL | | 2 => 2, +... | +LL | | _ => 42, +LL | | }; + | |_____^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:174:1 - | -174 | / fn bar() { -175 | | match 99 { -176 | | 0 => println!("hi"), -177 | | _ => println!("bye"), -178 | | } -179 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:174:1 + | +LL | / fn bar() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | _ => println!("bye"), +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:193:1 - | -193 | / fn barr() { -194 | | match 99 { -195 | | 0 => println!("hi"), -196 | | 1 => println!("bla"), -... | -199 | | } -200 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:193:1 + | +LL | / fn barr() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => println!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:203:1 - | -203 | / fn barr2() { -204 | | match 99 { -205 | | 0 => println!("hi"), -206 | | 1 => println!("bla"), -... | -215 | | } -216 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:203:1 + | +LL | / fn barr2() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => println!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:219:1 - | -219 | / fn barrr() { -220 | | match 99 { -221 | | 0 => println!("hi"), -222 | | 1 => panic!("bla"), -... | -225 | | } -226 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:219:1 + | +LL | / fn barrr() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => panic!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:229:1 - | -229 | / fn barrr2() { -230 | | match 99 { -231 | | 0 => println!("hi"), -232 | | 1 => panic!("bla"), -... | -241 | | } -242 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:229:1 + | +LL | / fn barrr2() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => panic!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:245:1 - | -245 | / fn barrrr() { -246 | | match 99 { -247 | | 0 => println!("hi"), -248 | | 1 => println!("bla"), -... | -251 | | } -252 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:245:1 + | +LL | / fn barrrr() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => println!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:255:1 - | -255 | / fn barrrr2() { -256 | | match 99 { -257 | | 0 => println!("hi"), -258 | | 1 => println!("bla"), -... | -267 | | } -268 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:255:1 + | +LL | / fn barrrr2() { +LL | | match 99 { +LL | | 0 => println!("hi"), +LL | | 1 => println!("bla"), +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:271:1 - | -271 | / fn cake() { -272 | | if 4 == 5 { -273 | | println!("yea"); -274 | | } else { -... | -277 | | println!("whee"); -278 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:271:1 + | +LL | / fn cake() { +LL | | if 4 == 5 { +LL | | println!("yea"); +LL | | } else { +... | +LL | | println!("whee"); +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 4 - --> $DIR/cyclomatic_complexity.rs:281:1 - | -281 | / pub fn read_file(input_path: &str) -> String { -282 | | use std::fs::File; -283 | | use std::io::{Read, Write}; -284 | | use std::path::Path; -... | -306 | | } -307 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:281:1 + | +LL | / pub fn read_file(input_path: &str) -> String { +LL | | use std::fs::File; +LL | | use std::io::{Read, Write}; +LL | | use std::path::Path; +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:312:1 - | -312 | / fn void(void: Void) { -313 | | if true { -314 | | match void {} -315 | | } -316 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:312:1 + | +LL | / fn void(void: Void) { +LL | | if true { +LL | | match void {} +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:325:1 - | -325 | / fn try() -> Result { -326 | | match 5 { -327 | | 5 => Ok(5), -328 | | _ => return Err("bla"), -329 | | } -330 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:325:1 + | +LL | / fn try() -> Result { +LL | | match 5 { +LL | | 5 => Ok(5), +LL | | _ => return Err("bla"), +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:333:1 - | -333 | / fn try_again() -> Result { -334 | | let _ = try!(Ok(42)); -335 | | let _ = try!(Ok(43)); -336 | | let _ = try!(Ok(44)); -... | -345 | | } -346 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:333:1 + | +LL | / fn try_again() -> Result { +LL | | let _ = try!(Ok(42)); +LL | | let _ = try!(Ok(43)); +LL | | let _ = try!(Ok(44)); +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:349:1 - | -349 | / fn early() -> Result { -350 | | return Ok(5); -351 | | return Ok(5); -352 | | return Ok(5); -... | -358 | | return Ok(5); -359 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:349:1 + | +LL | / fn early() -> Result { +LL | | return Ok(5); +LL | | return Ok(5); +LL | | return Ok(5); +... | +LL | | return Ok(5); +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 8 - --> $DIR/cyclomatic_complexity.rs:363:1 - | -363 | / fn early_ret() -> i32 { -364 | | let a = if true { 42 } else { return 0; }; -365 | | let a = if a < 99 { 42 } else { return 0; }; -366 | | let a = if a < 99 { 42 } else { return 0; }; -... | -379 | | } -380 | | } - | |_^ - | - = help: you could split it up into multiple smaller functions + --> $DIR/cyclomatic_complexity.rs:363:1 + | +LL | / fn early_ret() -> i32 { +LL | | let a = if true { 42 } else { return 0; }; +LL | | let a = if a < 99 { 42 } else { return 0; }; +LL | | let a = if a < 99 { 42 } else { return 0; }; +... | +LL | | } +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions error: aborting due to 20 previous errors diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index 3493c0d9ea5..dde803880ca 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -1,13 +1,13 @@ error: the function has a cyclomatic complexity of 3 --> $DIR/cyclomatic_complexity_attr_used.rs:18:1 | -18 | / fn kaboom() { -19 | | if 42 == 43 { -20 | | panic!(); -21 | | } else if "cake" == "lie" { -22 | | println!("what?"); -23 | | } -24 | | } +LL | / fn kaboom() { +LL | | if 42 == 43 { +LL | | panic!(); +LL | | } else if "cake" == "lie" { +LL | | println!("what?"); +LL | | } +LL | | } | |_^ | = note: `-D clippy::cyclomatic-complexity` implied by `-D warnings` diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index c68a25f3dc3..cc908ca11f3 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,7 +1,7 @@ error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:25:9 | -25 | 32_773, // 0x8005 +LL | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` | = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` @@ -9,25 +9,25 @@ error: integer literal has a better hexadecimal representation error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:26:9 | -26 | 65_280, // 0xFF00 +LL | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:27:9 | -27 | 2_131_750_927, // 0x7F0F_F00F +LL | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:28:9 | -28 | 2_147_483_647, // 0x7FFF_FFFF +LL | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation --> $DIR/decimal_literal_representation.rs:29:9 | -29 | 4_042_322_160, // 0xF0F0_F0F0 +LL | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: aborting due to 5 previous errors diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index b838f6a3bf4..9fcf359b72f 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,7 +1,7 @@ error: Calling std::string::String::default() is more clear than this expression --> $DIR/default_trait_access.rs:17:22 | -17 | let s1: String = Default::default(); +LL | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` | = note: `-D clippy::default-trait-access` implied by `-D warnings` @@ -9,43 +9,43 @@ error: Calling std::string::String::default() is more clear than this expression error: Calling std::string::String::default() is more clear than this expression --> $DIR/default_trait_access.rs:21:22 | -21 | let s3: String = D2::default(); +LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression --> $DIR/default_trait_access.rs:23:22 | -23 | let s4: String = std::default::Default::default(); +LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression --> $DIR/default_trait_access.rs:27:22 | -27 | let s6: String = default::Default::default(); +LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling GenericDerivedDefault::default() is more clear than this expression --> $DIR/default_trait_access.rs:37:46 | -37 | let s11: GenericDerivedDefault = Default::default(); +LL | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: Calling TupleDerivedDefault::default() is more clear than this expression --> $DIR/default_trait_access.rs:43:36 | -43 | let s14: TupleDerivedDefault = Default::default(); +LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: Calling ArrayDerivedDefault::default() is more clear than this expression --> $DIR/default_trait_access.rs:45:36 | -45 | let s15: ArrayDerivedDefault = Default::default(); +LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: Calling TupleStructDerivedDefault::default() is more clear than this expression --> $DIR/default_trait_access.rs:49:42 | -49 | let s17: TupleStructDerivedDefault = Default::default(); +LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` error: aborting due to 8 previous errors diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 335f6451e59..3d1f016b9b9 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -1,7 +1,7 @@ error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:10:8 | -10 | #[warn(str_to_string)] +LL | #[warn(str_to_string)] | ^^^^^^^^^^^^^ | = note: `-D renamed-and-removed-lints` implied by `-D warnings` @@ -9,25 +9,25 @@ error: lint `str_to_string` has been removed: `using `str::to_string` is common error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:11:8 | -11 | #[warn(string_to_string)] +LL | #[warn(string_to_string)] | ^^^^^^^^^^^^^^^^ error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` --> $DIR/deprecated.rs:12:8 | -12 | #[warn(unstable_as_slice)] +LL | #[warn(unstable_as_slice)] | ^^^^^^^^^^^^^^^^^ error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` --> $DIR/deprecated.rs:13:8 | -13 | #[warn(unstable_as_mut_slice)] +LL | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` --> $DIR/deprecated.rs:14:8 | -14 | #[warn(misaligned_transmute)] +LL | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index dd36f773337..b9629005597 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -1,130 +1,130 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly --> $DIR/derive.rs:25:10 | -25 | #[derive(Hash)] +LL | #[derive(Hash)] | ^^^^ | = note: #[deny(clippy::derive_hash_xor_eq)] on by default note: `PartialEq` implemented here --> $DIR/derive.rs:28:1 | -28 | / impl PartialEq for Bar { -29 | | fn eq(&self, _: &Bar) -> bool { -30 | | true -31 | | } -32 | | } +LL | / impl PartialEq for Bar { +LL | | fn eq(&self, _: &Bar) -> bool { +LL | | true +LL | | } +LL | | } | |_^ error: you are deriving `Hash` but have implemented `PartialEq` explicitly --> $DIR/derive.rs:34:10 | -34 | #[derive(Hash)] +LL | #[derive(Hash)] | ^^^^ | note: `PartialEq` implemented here --> $DIR/derive.rs:37:1 | -37 | / impl PartialEq for Baz { -38 | | fn eq(&self, _: &Baz) -> bool { -39 | | true -40 | | } -41 | | } +LL | / impl PartialEq for Baz { +LL | | fn eq(&self, _: &Baz) -> bool { +LL | | true +LL | | } +LL | | } | |_^ error: you are implementing `Hash` explicitly but have derived `PartialEq` --> $DIR/derive.rs:46:1 | -46 | / impl Hash for Bah { -47 | | fn hash(&self, _: &mut H) {} -48 | | } +LL | / impl Hash for Bah { +LL | | fn hash(&self, _: &mut H) {} +LL | | } | |_^ | note: `PartialEq` implemented here --> $DIR/derive.rs:43:10 | -43 | #[derive(PartialEq)] +LL | #[derive(PartialEq)] | ^^^^^^^^^ error: you are implementing `Clone` explicitly on a `Copy` type --> $DIR/derive.rs:53:1 | -53 | / impl Clone for Qux { -54 | | fn clone(&self) -> Self { -55 | | Qux -56 | | } -57 | | } +LL | / impl Clone for Qux { +LL | | fn clone(&self) -> Self { +LL | | Qux +LL | | } +LL | | } | |_^ | = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:53:1 | -53 | / impl Clone for Qux { -54 | | fn clone(&self) -> Self { -55 | | Qux -56 | | } -57 | | } +LL | / impl Clone for Qux { +LL | | fn clone(&self) -> Self { +LL | | Qux +LL | | } +LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type --> $DIR/derive.rs:77:1 | -77 | / impl<'a> Clone for Lt<'a> { -78 | | fn clone(&self) -> Self { -79 | | unimplemented!() -80 | | } -81 | | } +LL | / impl<'a> Clone for Lt<'a> { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:77:1 | -77 | / impl<'a> Clone for Lt<'a> { -78 | | fn clone(&self) -> Self { -79 | | unimplemented!() -80 | | } -81 | | } +LL | / impl<'a> Clone for Lt<'a> { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type --> $DIR/derive.rs:89:1 | -89 | / impl Clone for BigArray { -90 | | fn clone(&self) -> Self { -91 | | unimplemented!() -92 | | } -93 | | } +LL | / impl Clone for BigArray { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` --> $DIR/derive.rs:89:1 | -89 | / impl Clone for BigArray { -90 | | fn clone(&self) -> Self { -91 | | unimplemented!() -92 | | } -93 | | } +LL | / impl Clone for BigArray { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:101:1 - | -101 | / impl Clone for FnPtr { -102 | | fn clone(&self) -> Self { -103 | | unimplemented!() -104 | | } -105 | | } - | |_^ - | + --> $DIR/derive.rs:101:1 + | +LL | / impl Clone for FnPtr { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } + | |_^ + | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:101:1 - | -101 | / impl Clone for FnPtr { -102 | | fn clone(&self) -> Self { -103 | | unimplemented!() -104 | | } -105 | | } - | |_^ + --> $DIR/derive.rs:101:1 + | +LL | / impl Clone for FnPtr { +LL | | fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } +LL | | } + | |_^ error: aborting due to 7 previous errors diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index fea2bd1aa41..1cfec07c560 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,7 +1,7 @@ error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:30:10 | -30 | b || diverge(); +LL | b || diverge(); | ^^^^^^^^^ | = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` @@ -9,31 +9,31 @@ error: sub-expression diverges error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:31:10 | -31 | b || A.foo(); +LL | b || A.foo(); | ^^^^^^^ error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:40:26 | -40 | 6 => true || return, +LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:41:26 | -41 | 7 => true || continue, +LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:44:26 | -44 | 3 => true || diverge(), +LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:49:26 | -49 | _ => true || break, +LL | _ => true || break, | ^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index f2ca4dab997..6b0413fdf23 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -1,7 +1,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:19:16 | -19 | type Baz = LinkedList; +LL | type Baz = LinkedList; | ^^^^^^^^^^^^^^ | = note: `-D clippy::linkedlist` implied by `-D warnings` @@ -10,7 +10,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:20:12 | -20 | fn foo(LinkedList); +LL | fn foo(LinkedList); | ^^^^^^^^^^^^^^ | = help: a VecDeque might work @@ -18,7 +18,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:21:23 | -21 | const BAR: Option>; +LL | const BAR: Option>; | ^^^^^^^^^^^^^^ | = help: a VecDeque might work @@ -26,7 +26,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:32:15 | -32 | fn foo(_: LinkedList) {} +LL | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ | = help: a VecDeque might work @@ -34,7 +34,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:35:39 | -35 | pub fn test(my_favourite_linked_list: LinkedList) { +LL | pub fn test(my_favourite_linked_list: LinkedList) { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work @@ -42,7 +42,7 @@ error: I see you're using a LinkedList! Perhaps you meant some other data struct error: I see you're using a LinkedList! Perhaps you meant some other data structure? --> $DIR/dlist.rs:39:29 | -39 | pub fn test_ret() -> Option> { +LL | pub fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ | = help: a VecDeque might work diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index 26ac8103558..964e351348a 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -1,7 +1,7 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation --> $DIR/doc.rs:10:29 | -10 | //! This file tests for the DOC_MARKDOWN lint +LL | //! This file tests for the DOC_MARKDOWN lint | ^^^^^^^^^^^^ | = note: `-D clippy::doc-markdown` implied by `-D warnings` @@ -9,182 +9,182 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation error: you should put `foo_bar` between ticks in the documentation --> $DIR/doc.rs:15:9 | -15 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^ error: you should put `foo::bar` between ticks in the documentation --> $DIR/doc.rs:15:51 | -15 | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^^ error: you should put `Foo::some_fun` between ticks in the documentation --> $DIR/doc.rs:16:84 | -16 | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun +LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun | ^^^^^^^^^^^^^ error: you should put `a::global:path` between ticks in the documentation --> $DIR/doc.rs:18:15 | -18 | /// Here be ::a::global:path. +LL | /// Here be ::a::global:path. | ^^^^^^^^^^^^^^ error: you should put `NotInCodeBlock` between ticks in the documentation --> $DIR/doc.rs:19:22 | -19 | /// That's not code ~NotInCodeBlock~. +LL | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:20:5 | -20 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:34:5 | -34 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:41:5 | -41 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:55:5 | -55 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `link_with_underscores` between ticks in the documentation --> $DIR/doc.rs:59:22 | -59 | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. +LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation --> $DIR/doc.rs:62:21 | -62 | /// It can also be [inline_link2]. +LL | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:72:5 | -72 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation --> $DIR/doc.rs:80:8 | -80 | /// ## CamelCaseThing +LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation --> $DIR/doc.rs:83:7 | -83 | /// # CamelCaseThing +LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation --> $DIR/doc.rs:85:22 | -85 | /// Not a title #897 CamelCaseThing +LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:86:5 | -86 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation --> $DIR/doc.rs:93:5 | -93 | /// be_sure_we_got_to_the_end_of_it +LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:106:5 - | -106 | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:106:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:117:42 - | -117 | /** E.g. serialization of an empty list: FooBar - | ^^^^^^ + --> $DIR/doc.rs:117:42 + | +LL | /** E.g. serialization of an empty list: FooBar + | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:122:5 - | -122 | And BarQuz too. - | ^^^^^^ + --> $DIR/doc.rs:122:5 + | +LL | And BarQuz too. + | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:123:1 - | -123 | be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:123:1 + | +LL | be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:128:42 - | -128 | /** E.g. serialization of an empty list: FooBar - | ^^^^^^ + --> $DIR/doc.rs:128:42 + | +LL | /** E.g. serialization of an empty list: FooBar + | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:133:5 - | -133 | And BarQuz too. - | ^^^^^^ + --> $DIR/doc.rs:133:5 + | +LL | And BarQuz too. + | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:134:1 - | -134 | be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:134:1 + | +LL | be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:145:5 - | -145 | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:145:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:172:13 - | -172 | /// Not ok: http://www.unicode.org - | ^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:172:13 + | +LL | /// Not ok: http://www.unicode.org + | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:173:13 - | -173 | /// Not ok: https://www.unicode.org - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:173:13 + | +LL | /// Not ok: https://www.unicode.org + | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:174:13 - | -174 | /// Not ok: http://www.unicode.org/ - | ^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:174:13 + | +LL | /// Not ok: http://www.unicode.org/ + | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:175:13 - | -175 | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:175:13 + | +LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `mycrate::Collection` between ticks in the documentation - --> $DIR/doc.rs:181:22 - | -181 | /// An iterator over mycrate::Collection's values. - | ^^^^^^^^^^^^^^^^^^^ + --> $DIR/doc.rs:181:22 + | +LL | /// An iterator over mycrate::Collection's values. + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 31 previous errors diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index a06f278efc0..f4ec229fbfd 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,7 +1,7 @@ error: This binary expression can be simplified --> $DIR/double_comparison.rs:13:8 | -13 | if x == y || x < y { +LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` | = note: `-D clippy::double-comparisons` implied by `-D warnings` @@ -9,43 +9,43 @@ error: This binary expression can be simplified error: This binary expression can be simplified --> $DIR/double_comparison.rs:16:8 | -16 | if x < y || x == y { +LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:19:8 | -19 | if x == y || x > y { +LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:22:8 | -22 | if x > y || x == y { +LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:25:8 | -25 | if x < y || x > y { +LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:28:8 | -28 | if x > y || x < y { +LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:31:8 | -31 | if x <= y && x >= y { +LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified --> $DIR/double_comparison.rs:34:8 | -34 | if x >= y && x <= y { +LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: aborting due to 8 previous errors diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index 11ad5601286..6ff18e5504d 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -1,7 +1,7 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op --> $DIR/double_neg.rs:15:5 | -15 | --x; +LL | --x; | ^^^ | = note: `-D clippy::double-neg` implied by `-D warnings` diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index d736d72c143..0e7f62ca3e3 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -1,7 +1,7 @@ error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:21:5 | -21 | ((0)) +LL | ((0)) | ^^^^^ | = note: `-D clippy::double-parens` implied by `-D warnings` @@ -9,31 +9,31 @@ error: Consider removing unnecessary double parentheses error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:25:14 | -25 | dummy_fn((0)); +LL | dummy_fn((0)); | ^^^ error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:29:20 | -29 | x.dummy_method((0)); +LL | x.dummy_method((0)); | ^^^ error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:33:5 | -33 | ((1, 2)) +LL | ((1, 2)) | ^^^^^^^^ error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:37:5 | -37 | (()) +LL | (()) | ^^^^ error: Consider removing unnecessary double parentheses --> $DIR/double_parens.rs:59:16 | -59 | assert_eq!(((1, 2)), (1, 2), "Error"); +LL | assert_eq!(((1, 2)), (1, 2), "Error"); | ^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index 3b950eaebe3..6fc69c4bcda 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -1,75 +1,75 @@ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:42:5 | -42 | drop(s1); +LL | drop(s1); | ^^^^^^^^ | = note: `-D clippy::drop-copy` implied by `-D warnings` note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:42:10 | -42 | drop(s1); +LL | drop(s1); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:43:5 | -43 | drop(s2); +LL | drop(s2); | ^^^^^^^^ | note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:43:10 | -43 | drop(s2); +LL | drop(s2); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:45:5 | -45 | drop(s4); +LL | drop(s4); | ^^^^^^^^ | note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:45:10 | -45 | drop(s4); +LL | drop(s4); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:48:5 | -48 | forget(s1); +LL | forget(s1); | ^^^^^^^^^^ | = note: `-D clippy::forget-copy` implied by `-D warnings` note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:48:12 | -48 | forget(s1); +LL | forget(s1); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:49:5 | -49 | forget(s2); +LL | forget(s2); | ^^^^^^^^^^ | note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:49:12 | -49 | forget(s2); +LL | forget(s2); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. --> $DIR/drop_forget_copy.rs:51:5 | -51 | forget(s4); +LL | forget(s4); | ^^^^^^^^^^ | note: argument has type SomeStruct --> $DIR/drop_forget_copy.rs:51:12 | -51 | forget(s4); +LL | forget(s4); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 972ab298c4c..005adceca50 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -1,219 +1,219 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:18:5 | -18 | drop(&SomeStruct); +LL | drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::drop-ref` implied by `-D warnings` note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:18:10 | -18 | drop(&SomeStruct); +LL | drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:19:5 | -19 | forget(&SomeStruct); +LL | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:19:12 | -19 | forget(&SomeStruct); +LL | forget(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:22:5 | -22 | drop(&owned1); +LL | drop(&owned1); | ^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:22:10 | -22 | drop(&owned1); +LL | drop(&owned1); | ^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:23:5 | -23 | drop(&&owned1); +LL | drop(&&owned1); | ^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct --> $DIR/drop_forget_ref.rs:23:10 | -23 | drop(&&owned1); +LL | drop(&&owned1); | ^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:24:5 | -24 | drop(&mut owned1); +LL | drop(&mut owned1); | ^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct --> $DIR/drop_forget_ref.rs:24:10 | -24 | drop(&mut owned1); +LL | drop(&mut owned1); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:27:5 | -27 | forget(&owned2); +LL | forget(&owned2); | ^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:27:12 | -27 | forget(&owned2); +LL | forget(&owned2); | ^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:28:5 | -28 | forget(&&owned2); +LL | forget(&&owned2); | ^^^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct --> $DIR/drop_forget_ref.rs:28:12 | -28 | forget(&&owned2); +LL | forget(&&owned2); | ^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:29:5 | -29 | forget(&mut owned2); +LL | forget(&mut owned2); | ^^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct --> $DIR/drop_forget_ref.rs:29:12 | -29 | forget(&mut owned2); +LL | forget(&mut owned2); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:33:5 | -33 | drop(reference1); +LL | drop(reference1); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:33:10 | -33 | drop(reference1); +LL | drop(reference1); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:34:5 | -34 | forget(&*reference1); +LL | forget(&*reference1); | ^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:34:12 | -34 | forget(&*reference1); +LL | forget(&*reference1); | ^^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:37:5 | -37 | drop(reference2); +LL | drop(reference2); | ^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct --> $DIR/drop_forget_ref.rs:37:10 | -37 | drop(reference2); +LL | drop(reference2); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:39:5 | -39 | forget(reference3); +LL | forget(reference3); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct --> $DIR/drop_forget_ref.rs:39:12 | -39 | forget(reference3); +LL | forget(reference3); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:42:5 | -42 | drop(reference4); +LL | drop(reference4); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:42:10 | -42 | drop(reference4); +LL | drop(reference4); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:43:5 | -43 | forget(reference4); +LL | forget(reference4); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:43:12 | -43 | forget(reference4); +LL | forget(reference4); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:48:5 | -48 | drop(&val); +LL | drop(&val); | ^^^^^^^^^^ | note: argument has type &T --> $DIR/drop_forget_ref.rs:48:10 | -48 | drop(&val); +LL | drop(&val); | ^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:54:5 | -54 | forget(&val); +LL | forget(&val); | ^^^^^^^^^^^^ | note: argument has type &T --> $DIR/drop_forget_ref.rs:54:12 | -54 | forget(&val); +LL | forget(&val); | ^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. --> $DIR/drop_forget_ref.rs:62:5 | -62 | std::mem::drop(&SomeStruct); +LL | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:62:20 | -62 | std::mem::drop(&SomeStruct); +LL | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. --> $DIR/drop_forget_ref.rs:65:5 | -65 | std::mem::forget(&SomeStruct); +LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct --> $DIR/drop_forget_ref.rs:65:22 | -65 | std::mem::forget(&SomeStruct); +LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ error: aborting due to 18 previous errors diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index ba1b5b1ded7..e4bdd3f96b2 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -1,7 +1,7 @@ error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult --> $DIR/duplicate_underscore_argument.rs:13:23 | -13 | fn join_the_dark_side(darth: i32, _darth: i32) {} +LL | fn join_the_dark_side(darth: i32, _darth: i32) {} | ^^^^^ | = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index 1310ac12340..e87c9839b33 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,7 +1,7 @@ error: Calling `subsec_millis()` is more concise than this calculation --> $DIR/duration_subsec.rs:17:24 | -17 | let bad_millis_1 = dur.subsec_micros() / 1_000; +LL | let bad_millis_1 = dur.subsec_micros() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` | = note: `-D clippy::duration-subsec` implied by `-D warnings` @@ -9,25 +9,25 @@ error: Calling `subsec_millis()` is more concise than this calculation error: Calling `subsec_millis()` is more concise than this calculation --> $DIR/duration_subsec.rs:18:24 | -18 | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; +LL | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:23:22 | -23 | let bad_micros = dur.subsec_nanos() / 1_000; +LL | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:28:13 | -28 | let _ = (&dur).subsec_nanos() / 1_000; +LL | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:32:13 | -32 | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; +LL | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: aborting due to 5 previous errors diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 8771df87297..2c1ecbfdb86 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,11 +1,11 @@ error: if expression with an `else if`, but without a final `else` --> $DIR/else_if_without_else.rs:54:12 | -54 | } else if bla2() { +LL | } else if bla2() { | ____________^ -55 | | //~ ERROR else if without else -56 | | println!("else if"); -57 | | } +LL | | //~ ERROR else if without else +LL | | println!("else if"); +LL | | } | |_____^ | = note: `-D clippy::else-if-without-else` implied by `-D warnings` @@ -14,11 +14,11 @@ error: if expression with an `else if`, but without a final `else` error: if expression with an `else if`, but without a final `else` --> $DIR/else_if_without_else.rs:63:12 | -63 | } else if bla3() { +LL | } else if bla3() { | ____________^ -64 | | //~ ERROR else if without else -65 | | println!("else if 2"); -66 | | } +LL | | //~ ERROR else if without else +LL | | println!("else if 2"); +LL | | } | |_____^ | = help: add an `else` block here diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index fd981f2210f..d2e3688eb4d 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -1,14 +1,14 @@ error: enum with no variants --> $DIR/empty_enum.rs:13:1 | -13 | enum Empty {} +LL | enum Empty {} | ^^^^^^^^^^^^^ | = note: `-D clippy::empty-enum` implied by `-D warnings` help: consider using the uninhabited type `!` or a wrapper around it --> $DIR/empty_enum.rs:13:1 | -13 | enum Empty {} +LL | enum Empty {} | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index ec3ee6d018c..59939ea2858 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,10 +1,10 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:13:1 | -13 | / #[crate_type = "lib"] -14 | | -15 | | /// some comment -16 | | fn with_one_newline_and_comment() { assert!(true) } +LL | / #[crate_type = "lib"] +LL | | +LL | | /// some comment +LL | | fn with_one_newline_and_comment() { assert!(true) } | |_ | = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` @@ -12,42 +12,42 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:25:1 | -25 | / #[crate_type = "lib"] -26 | | -27 | | fn with_one_newline() { assert!(true) } +LL | / #[crate_type = "lib"] +LL | | +LL | | fn with_one_newline() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:30:1 | -30 | / #[crate_type = "lib"] -31 | | -32 | | -33 | | fn with_two_newlines() { assert!(true) } +LL | / #[crate_type = "lib"] +LL | | +LL | | +LL | | fn with_two_newlines() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:37:1 | -37 | / #[crate_type = "lib"] -38 | | -39 | | enum Baz { +LL | / #[crate_type = "lib"] +LL | | +LL | | enum Baz { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:45:1 | -45 | / #[crate_type = "lib"] -46 | | -47 | | struct Foo { +LL | / #[crate_type = "lib"] +LL | | +LL | | struct Foo { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:53:1 | -53 | / #[crate_type = "lib"] -54 | | -55 | | mod foo { +LL | / #[crate_type = "lib"] +LL | | +LL | | mod foo { | |_ error: aborting due to 6 previous errors diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 9a4e0ba31ee..78a179d07ef 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -1,9 +1,9 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:19:5 | -19 | / if !m.contains_key(&k) { -20 | | m.insert(k, v); -21 | | } +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } | |_____^ help: consider using: `m.entry(k).or_insert(v)` | = note: `-D clippy::map-entry` implied by `-D warnings` @@ -11,63 +11,63 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:25:5 | -25 | / if !m.contains_key(&k) { -26 | | foo(); -27 | | m.insert(k, v); -28 | | } +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | m.insert(k, v); +LL | | } | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:32:5 | -32 | / if !m.contains_key(&k) { -33 | | m.insert(k, v) -34 | | } else { -35 | | None -36 | | }; +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v) +LL | | } else { +LL | | None +LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:40:5 | -40 | / if m.contains_key(&k) { -41 | | None -42 | | } else { -43 | | m.insert(k, v) -44 | | }; +LL | / if m.contains_key(&k) { +LL | | None +LL | | } else { +LL | | m.insert(k, v) +LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:48:5 | -48 | / if !m.contains_key(&k) { -49 | | foo(); -50 | | m.insert(k, v) -51 | | } else { -52 | | None -53 | | }; +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | m.insert(k, v) +LL | | } else { +LL | | None +LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:57:5 | -57 | / if m.contains_key(&k) { -58 | | None -59 | | } else { -60 | | foo(); -61 | | m.insert(k, v) -62 | | }; +LL | / if m.contains_key(&k) { +LL | | None +LL | | } else { +LL | | foo(); +LL | | m.insert(k, v) +LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `BTreeMap` --> $DIR/entry.rs:66:5 | -66 | / if !m.contains_key(&k) { -67 | | foo(); -68 | | m.insert(k, v) -69 | | } else { -70 | | None -71 | | }; +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | m.insert(k, v) +LL | | } else { +LL | | None +LL | | }; | |_____^ help: consider using: `m.entry(k)` error: aborting due to 7 previous errors diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 58c6f4d3301..8b89856d4a4 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -1,7 +1,7 @@ error: don't use glob imports for enum variants --> $DIR/enum_glob_use.rs:13:1 | -13 | use std::cmp::Ordering::*; +LL | use std::cmp::Ordering::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::enum-glob-use` implied by `-D warnings` @@ -9,7 +9,7 @@ error: don't use glob imports for enum variants error: don't use glob imports for enum variants --> $DIR/enum_glob_use.rs:19:1 | -19 | use self::Enum::*; +LL | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 1f554e2c33a..4555e1d0649 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,7 +1,7 @@ error: Variant name ends with the enum's name --> $DIR/enum_variants.rs:25:5 | -25 | cFoo, +LL | cFoo, | ^^^^ | = note: `-D clippy::enum-variant-names` implied by `-D warnings` @@ -9,29 +9,29 @@ error: Variant name ends with the enum's name error: Variant name starts with the enum's name --> $DIR/enum_variants.rs:36:5 | -36 | FoodGood, +LL | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name --> $DIR/enum_variants.rs:37:5 | -37 | FoodMiddle, +LL | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name --> $DIR/enum_variants.rs:38:5 | -38 | FoodBad, +LL | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` --> $DIR/enum_variants.rs:35:1 | -35 | / enum Food { -36 | | FoodGood, -37 | | FoodMiddle, -38 | | FoodBad, -39 | | } +LL | / enum Food { +LL | | FoodGood, +LL | | FoodMiddle, +LL | | FoodBad, +LL | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports @@ -39,11 +39,11 @@ error: All variants have the same prefix: `Food` error: All variants have the same prefix: `CallType` --> $DIR/enum_variants.rs:45:1 | -45 | / enum BadCallType { -46 | | CallTypeCall, -47 | | CallTypeCreate, -48 | | CallTypeDestroy, -49 | | } +LL | / enum BadCallType { +LL | | CallTypeCall, +LL | | CallTypeCreate, +LL | | CallTypeDestroy, +LL | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports @@ -51,11 +51,11 @@ error: All variants have the same prefix: `CallType` error: All variants have the same prefix: `Constant` --> $DIR/enum_variants.rs:57:1 | -57 | / enum Consts { -58 | | ConstantInt, -59 | | ConstantCake, -60 | | ConstantLie, -61 | | } +LL | / enum Consts { +LL | | ConstantInt, +LL | | ConstantCake, +LL | | ConstantLie, +LL | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports @@ -63,39 +63,39 @@ error: All variants have the same prefix: `Constant` error: All variants have the same prefix: `With` --> $DIR/enum_variants.rs:91:1 | -91 | / enum Seallll { -92 | | WithOutCake, -93 | | WithOutTea, -94 | | WithOut, -95 | | } +LL | / enum Seallll { +LL | | WithOutCake, +LL | | WithOutTea, +LL | | WithOut, +LL | | } | |_^ | = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:97:1 - | -97 | / enum NonCaps { -98 | | Prefix的, -99 | | PrefixTea, -100 | | PrefixCake, -101 | | } - | |_^ - | - = help: remove the prefixes and use full paths to the variants instead of glob imports + --> $DIR/enum_variants.rs:97:1 + | +LL | / enum NonCaps { +LL | | Prefix的, +LL | | PrefixTea, +LL | | PrefixCake, +LL | | } + | |_^ + | + = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:103:1 - | -103 | / pub enum PubSeall { -104 | | WithOutCake, -105 | | WithOutTea, -106 | | WithOut, -107 | | } - | |_^ - | - = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` - = help: remove the prefixes and use full paths to the variants instead of glob imports + --> $DIR/enum_variants.rs:103:1 + | +LL | / pub enum PubSeall { +LL | | WithOutCake, +LL | | WithOutTea, +LL | | WithOut, +LL | | } + | |_^ + | + = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` + = help: remove the prefixes and use full paths to the variants instead of glob imports error: aborting due to 10 previous errors diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index 0756b9a80d4..f883529b996 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -1,7 +1,7 @@ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:17:5 | -17 | X = 0x1_0000_0000, +LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` @@ -9,43 +9,43 @@ error: Clike enum variant discriminant is not portable to 32-bit targets error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:24:5 | -24 | X = 0x1_0000_0000, +LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:27:5 | -27 | A = 0xFFFF_FFFF, +LL | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:34:5 | -34 | Z = 0xFFFF_FFFF, +LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:35:5 | -35 | A = 0x1_0000_0000, +LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:37:5 | -37 | C = (std::i32::MIN as isize) - 1, +LL | C = (std::i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:43:5 | -43 | Z = 0xFFFF_FFFF, +LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enums_clike.rs:44:5 | -44 | A = 0x1_0000_0000, +LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index abd351b65a4..a1a257095c2 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,7 +1,7 @@ error: this boolean expression can be simplified --> $DIR/eq_op.rs:44:5 | -44 | true && true; +LL | true && true; | ^^^^^^^^^^^^ help: try: `true` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` @@ -9,37 +9,37 @@ error: this boolean expression can be simplified error: this boolean expression can be simplified --> $DIR/eq_op.rs:46:5 | -46 | true || true; +LL | true || true; | ^^^^^^^^^^^^ help: try: `true` error: this boolean expression can be simplified --> $DIR/eq_op.rs:52:5 | -52 | a == b && b == a; +LL | a == b && b == a; | ^^^^^^^^^^^^^^^^ help: try: `a == b` error: this boolean expression can be simplified --> $DIR/eq_op.rs:53:5 | -53 | a != b && b != a; +LL | a != b && b != a; | ^^^^^^^^^^^^^^^^ help: try: `a != b` error: this boolean expression can be simplified --> $DIR/eq_op.rs:54:5 | -54 | a < b && b > a; +LL | a < b && b > a; | ^^^^^^^^^^^^^^ help: try: `a < b` error: this boolean expression can be simplified --> $DIR/eq_op.rs:55:5 | -55 | a <= b && b >= a; +LL | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ help: try: `a <= b` error: equal expressions as operands to `==` --> $DIR/eq_op.rs:17:5 | -17 | 1 == 1; +LL | 1 == 1; | ^^^^^^ | = note: `-D clippy::eq-op` implied by `-D warnings` @@ -47,157 +47,157 @@ error: equal expressions as operands to `==` error: equal expressions as operands to `==` --> $DIR/eq_op.rs:18:5 | -18 | "no" == "no"; +LL | "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` --> $DIR/eq_op.rs:20:5 | -20 | false != false; +LL | false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` --> $DIR/eq_op.rs:21:5 | -21 | 1.5 < 1.5; +LL | 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` --> $DIR/eq_op.rs:22:5 | -22 | 1u64 >= 1u64; +LL | 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` --> $DIR/eq_op.rs:25:5 | -25 | (1 as u64) & (1 as u64); +LL | (1 as u64) & (1 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` --> $DIR/eq_op.rs:26:5 | -26 | 1 ^ ((((((1)))))); +LL | 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` --> $DIR/eq_op.rs:29:5 | -29 | (-(2) < -(2)); +LL | (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` --> $DIR/eq_op.rs:30:5 | -30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` --> $DIR/eq_op.rs:30:6 | -30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` --> $DIR/eq_op.rs:30:27 | -30 | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); +LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` --> $DIR/eq_op.rs:31:5 | -31 | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; +LL | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` --> $DIR/eq_op.rs:34:5 | -34 | ([1] != [1]); +LL | ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` --> $DIR/eq_op.rs:35:5 | -35 | ((1, 2) != (1, 2)); +LL | ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` --> $DIR/eq_op.rs:39:5 | -39 | 1 + 1 == 2; +LL | 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` --> $DIR/eq_op.rs:40:5 | -40 | 1 - 1 == 0; +LL | 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` --> $DIR/eq_op.rs:40:5 | -40 | 1 - 1 == 0; +LL | 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` --> $DIR/eq_op.rs:42:5 | -42 | 1 - 1; +LL | 1 - 1; | ^^^^^ error: equal expressions as operands to `/` --> $DIR/eq_op.rs:43:5 | -43 | 1 / 1; +LL | 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` --> $DIR/eq_op.rs:44:5 | -44 | true && true; +LL | true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` --> $DIR/eq_op.rs:46:5 | -46 | true || true; +LL | true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` --> $DIR/eq_op.rs:52:5 | -52 | a == b && b == a; +LL | a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` --> $DIR/eq_op.rs:53:5 | -53 | a != b && b != a; +LL | a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` --> $DIR/eq_op.rs:54:5 | -54 | a < b && b > a; +LL | a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` --> $DIR/eq_op.rs:55:5 | -55 | a <= b && b >= a; +LL | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` --> $DIR/eq_op.rs:58:5 | -58 | a == a; +LL | a == a; | ^^^^^^ error: taken reference of right operand --> $DIR/eq_op.rs:96:13 | -96 | let z = x & &y; +LL | let z = x & &y; | ^^^^-- | | | help: use the right value directly: `y` @@ -205,10 +205,10 @@ error: taken reference of right operand = note: `-D clippy::op-ref` implied by `-D warnings` error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:104:20 - | -104 | const D: u32 = A / A; - | ^^^^^ + --> $DIR/eq_op.rs:104:20 + | +LL | const D: u32 = A / A; + | ^^^^^ error: aborting due to 34 previous errors diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index a500a132af7..85548eefba7 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -1,7 +1,7 @@ error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:15:5 | -15 | x * 0; +LL | x * 0; | ^^^^^ | = note: `-D clippy::erasing-op` implied by `-D warnings` @@ -9,13 +9,13 @@ error: this operation will always return zero. This is likely not the intended o error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:16:5 | -16 | 0 & x; +LL | 0 & x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome --> $DIR/erasing_op.rs:17:5 | -17 | 0 / x; +LL | 0 / x; | ^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr index ec9b7317eed..ed7819ed429 100644 --- a/tests/ui/escape_analysis.stderr +++ b/tests/ui/escape_analysis.stderr @@ -1,16 +1,16 @@ error: local variable doesn't need to be boxed here --> $DIR/escape_analysis.rs:43:13 | -43 | fn warn_arg(x: Box) { +LL | fn warn_arg(x: Box) { | ^ | = note: `-D clippy::boxed-local` implied by `-D warnings` error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:134:12 - | -134 | pub fn new(_needs_name: Box>) -> () {} - | ^^^^^^^^^^^ + --> $DIR/escape_analysis.rs:134:12 + | +LL | pub fn new(_needs_name: Box>) -> () {} + | ^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index cd14855c49d..fb7daba1578 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,7 +1,7 @@ error: redundant closure found --> $DIR/eta.rs:22:27 | -22 | let a = Some(1u8).map(|a| foo(a)); +LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` | = note: `-D clippy::redundant-closure` implied by `-D warnings` @@ -9,19 +9,19 @@ error: redundant closure found error: redundant closure found --> $DIR/eta.rs:23:10 | -23 | meta(|a| foo(a)); +LL | meta(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` error: redundant closure found --> $DIR/eta.rs:24:27 | -24 | let c = Some(1u8).map(|a| {1+2; foo}(a)); +LL | let c = Some(1u8).map(|a| {1+2; foo}(a)); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` error: this expression borrows a reference that is immediately dereferenced by the compiler --> $DIR/eta.rs:26:21 | -26 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted +LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` | = note: `-D clippy::needless-borrow` implied by `-D warnings` @@ -29,7 +29,7 @@ error: this expression borrows a reference that is immediately dereferenced by t error: redundant closure found --> $DIR/eta.rs:33:27 | -33 | let e = Some(1u8).map(|a| generic(a)); +LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: aborting due to 5 previous errors diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index 38317376fc4..929650a7da8 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -1,50 +1,50 @@ error: unsequenced read of a variable --> $DIR/eval_order_dependence.rs:24:9 | -24 | } + x; +LL | } + x; | ^ | = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order --> $DIR/eval_order_dependence.rs:22:9 | -22 | x = 1; +LL | x = 1; | ^^^^^ error: unsequenced read of a variable --> $DIR/eval_order_dependence.rs:27:5 | -27 | x += { +LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order --> $DIR/eval_order_dependence.rs:28:9 | -28 | x = 20; +LL | x = 20; | ^^^^^^ error: unsequenced read of a variable --> $DIR/eval_order_dependence.rs:40:12 | -40 | a: x, +LL | a: x, | ^ | note: whether read occurs before this write depends on evaluation order --> $DIR/eval_order_dependence.rs:42:13 | -42 | x = 6; +LL | x = 6; | ^^^^^ error: unsequenced read of a variable --> $DIR/eval_order_dependence.rs:49:9 | -49 | x += { +LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order --> $DIR/eval_order_dependence.rs:50:13 | -50 | x = 20; +LL | x = 20; | ^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index a69652373d5..57c33c4719b 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,7 +1,7 @@ error: float has excessive precision --> $DIR/excessive_precision.rs:23:26 | -23 | const BAD32_1: f32 = 0.123_456_789_f32; +LL | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` | = note: `-D clippy::excessive-precision` implied by `-D warnings` @@ -9,103 +9,103 @@ error: float has excessive precision error: float has excessive precision --> $DIR/excessive_precision.rs:24:26 | -24 | const BAD32_2: f32 = 0.123_456_789; +LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision --> $DIR/excessive_precision.rs:25:26 | -25 | const BAD32_3: f32 = 0.100_000_000_000_1; +LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision --> $DIR/excessive_precision.rs:26:29 | -26 | const BAD32_EDGE: f32 = 1.000_000_9; +LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision --> $DIR/excessive_precision.rs:28:26 | -28 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; +LL | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision --> $DIR/excessive_precision.rs:29:26 | -29 | const BAD64_2: f64 = 0.123_456_789_012_345_67; +LL | const BAD64_2: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision --> $DIR/excessive_precision.rs:30:26 | -30 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; +LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision --> $DIR/excessive_precision.rs:33:22 | -33 | println!("{:?}", 8.888_888_888_888_888_888_888); +LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision --> $DIR/excessive_precision.rs:44:22 | -44 | let bad32: f32 = 1.123_456_789; +LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision --> $DIR/excessive_precision.rs:45:26 | -45 | let bad32_suf: f32 = 1.123_456_789_f32; +LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision --> $DIR/excessive_precision.rs:46:21 | -46 | let bad32_inf = 1.123_456_789_f32; +LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision --> $DIR/excessive_precision.rs:48:22 | -48 | let bad64: f64 = 0.123_456_789_012_345_67; +LL | let bad64: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision --> $DIR/excessive_precision.rs:49:26 | -49 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; +LL | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision --> $DIR/excessive_precision.rs:50:21 | -50 | let bad64_inf = 0.123_456_789_012_345_67; +LL | let bad64_inf = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision --> $DIR/excessive_precision.rs:56:36 | -56 | let bad_vec32: Vec = vec![0.123_456_789]; +LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision --> $DIR/excessive_precision.rs:57:36 | -57 | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; +LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision --> $DIR/excessive_precision.rs:61:24 | -61 | let bad_e32: f32 = 1.123_456_788_888e-10; +LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision --> $DIR/excessive_precision.rs:64:27 | -64 | let bad_bige32: f32 = 1.123_456_788_888E-10; +LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` error: aborting due to 18 previous errors diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index ad8fe14e9a0..72a6995c1ce 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,7 +1,7 @@ error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:36:26 | -36 | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); +LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D clippy::expect-fun-call` implied by `-D warnings` @@ -9,31 +9,31 @@ error: use of `expect` followed by a function call error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:39:26 | -39 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:49:25 | -49 | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); +LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:52:25 | -52 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); +LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:67:17 | -67 | Some("foo").expect({ &format!("error") }); +LL | Some("foo").expect({ &format!("error") }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:68:17 | -68 | Some("foo").expect(format!("error").as_ref()); +LL | Some("foo").expect(format!("error").as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` error: aborting due to 6 previous errors diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index caafd2375f0..caccaee84b9 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -1,7 +1,7 @@ error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators --> $DIR/explicit_counter_loop.rs:15:15 | -15 | for _v in &vec { +LL | for _v in &vec { | ^^^^ | = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` @@ -9,19 +9,19 @@ error: the variable `_index` is used as a loop counter. Consider using `for (_in error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators --> $DIR/explicit_counter_loop.rs:21:15 | -21 | for _v in &vec { +LL | for _v in &vec { | ^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators --> $DIR/explicit_counter_loop.rs:60:19 | -60 | for ch in text.chars() { +LL | for ch in text.chars() { | ^^^^^^^^^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators --> $DIR/explicit_counter_loop.rs:71:19 | -71 | for ch in text.chars() { +LL | for ch in text.chars() { | ^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 1a11dbc169b..1072d9bd0d2 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,7 +1,7 @@ error: use of `write!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:24:9 | -24 | write!(std::io::stdout(), "test").unwrap(); +LL | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` | = note: `-D clippy::explicit-write` implied by `-D warnings` @@ -9,43 +9,43 @@ error: use of `write!(stdout(), ...).unwrap()` error: use of `write!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:25:9 | -25 | write!(std::io::stderr(), "test").unwrap(); +LL | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:26:9 | -26 | writeln!(std::io::stdout(), "test").unwrap(); +LL | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:27:9 | -27 | writeln!(std::io::stderr(), "test").unwrap(); +LL | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` --> $DIR/explicit_write.rs:28:9 | -28 | std::io::stdout().write_fmt(format_args!("test")).unwrap(); +LL | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` --> $DIR/explicit_write.rs:29:9 | -29 | std::io::stderr().write_fmt(format_args!("test")).unwrap(); +LL | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:32:9 | -32 | writeln!(std::io::stdout(), "test/ntest").unwrap(); +LL | writeln!(std::io::stdout(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:33:9 | -33 | writeln!(std::io::stderr(), "test/ntest").unwrap(); +LL | writeln!(std::io::stderr(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` error: aborting due to 8 previous errors diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 8af5933a9f8..55efac7951a 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -1,91 +1,91 @@ error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:14:1 | -14 | / impl From for Foo { -15 | | fn from(s: String) -> Self { -16 | | Foo(s.parse().unwrap()) -17 | | } -18 | | } +LL | / impl From for Foo { +LL | | fn from(s: String) -> Self { +LL | | Foo(s.parse().unwrap()) +LL | | } +LL | | } | |_^ | note: lint level defined here --> $DIR/fallible_impl_from.rs:10:9 | -10 | #![deny(clippy::fallible_impl_from)] +LL | #![deny(clippy::fallible_impl_from)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) --> $DIR/fallible_impl_from.rs:16:13 | -16 | Foo(s.parse().unwrap()) +LL | Foo(s.parse().unwrap()) | ^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:35:1 | -35 | / impl From for Invalid { -36 | | fn from(i: usize) -> Invalid { -37 | | if i != 42 { -38 | | panic!(); +LL | / impl From for Invalid { +LL | | fn from(i: usize) -> Invalid { +LL | | if i != 42 { +LL | | panic!(); ... | -41 | | } -42 | | } +LL | | } +LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) --> $DIR/fallible_impl_from.rs:38:13 | -38 | panic!(); +LL | panic!(); | ^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:44:1 | -44 | / impl From> for Invalid { -45 | | fn from(s: Option) -> Invalid { -46 | | let s = s.unwrap(); -47 | | if !s.is_empty() { +LL | / impl From> for Invalid { +LL | | fn from(s: Option) -> Invalid { +LL | | let s = s.unwrap(); +LL | | if !s.is_empty() { ... | -53 | | } -54 | | } +LL | | } +LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) --> $DIR/fallible_impl_from.rs:46:17 | -46 | let s = s.unwrap(); +LL | let s = s.unwrap(); | ^^^^^^^^^^ -47 | if !s.is_empty() { -48 | panic!(42); +LL | if !s.is_empty() { +LL | panic!(42); | ^^^^^^^^^^^ -49 | } else if s.parse::().unwrap() != 42 { +LL | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -50 | panic!("{:?}", s); +LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:62:1 | -62 | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { -63 | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -64 | | if s.parse::().ok().unwrap() != 42 { -65 | | panic!("{:?}", s); +LL | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { +LL | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { +LL | | if s.parse::().ok().unwrap() != 42 { +LL | | panic!("{:?}", s); ... | -68 | | } -69 | | } +LL | | } +LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) --> $DIR/fallible_impl_from.rs:64:12 | -64 | if s.parse::().ok().unwrap() != 42 { +LL | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -65 | panic!("{:?}", s); +LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index 8fde78ca5a7..c10d673148a 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -1,7 +1,7 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead. --> $DIR/filter_methods.rs:14:21 | -14 | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); +LL | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::filter-map` implied by `-D warnings` @@ -9,31 +9,31 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expre error: called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. --> $DIR/filter_methods.rs:16:21 | -16 | let _: Vec<_> = vec![5_i8; 6] +LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -17 | | .into_iter() -18 | | .filter(|&x| x == 0) -19 | | .flat_map(|x| x.checked_mul(2)) +LL | | .into_iter() +LL | | .filter(|&x| x == 0) +LL | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________^ error: called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. --> $DIR/filter_methods.rs:22:21 | -22 | let _: Vec<_> = vec![5_i8; 6] +LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -23 | | .into_iter() -24 | | .filter_map(|x| x.checked_mul(2)) -25 | | .flat_map(|x| x.checked_mul(2)) +LL | | .into_iter() +LL | | .filter_map(|x| x.checked_mul(2)) +LL | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________^ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly expressed by only calling `.filter_map(..)` instead. --> $DIR/filter_methods.rs:28:21 | -28 | let _: Vec<_> = vec![5_i8; 6] +LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ -29 | | .into_iter() -30 | | .filter_map(|x| x.checked_mul(2)) -31 | | .map(|x| x.checked_mul(2)) +LL | | .into_iter() +LL | | .filter_map(|x| x.checked_mul(2)) +LL | | .map(|x| x.checked_mul(2)) | |__________________________________^ error: aborting due to 4 previous errors diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index 3acd71eb99b..bdbbccee714 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,38 +1,38 @@ error: strict comparison of f32 or f64 --> $DIR/float_cmp.rs:69:5 | -69 | ONE as f64 != 2.0; +LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | = note: `-D clippy::float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp.rs:69:5 | -69 | ONE as f64 != 2.0; +LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 --> $DIR/float_cmp.rs:74:5 | -74 | x == 1.0; +LL | x == 1.0; | ^^^^^^^^ help: consider comparing them within some error: `(x - 1.0).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp.rs:74:5 | -74 | x == 1.0; +LL | x == 1.0; | ^^^^^^^^ error: strict comparison of f32 or f64 --> $DIR/float_cmp.rs:77:5 | -77 | twice(x) != twice(ONE as f64); +LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(x) - twice(ONE as f64)).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp.rs:77:5 | -77 | twice(x) != twice(ONE as f64); +LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index d9b1d268505..2b434f31814 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -1,86 +1,86 @@ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:27:5 | -27 | 1f32 == ONE; +LL | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | = note: `-D clippy::float-cmp-const` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:27:5 | -27 | 1f32 == ONE; +LL | 1f32 == ONE; | ^^^^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:28:5 | -28 | TWO == ONE; +LL | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:28:5 | -28 | TWO == ONE; +LL | TWO == ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:29:5 | -29 | TWO != ONE; +LL | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:29:5 | -29 | TWO != ONE; +LL | TWO != ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:30:5 | -30 | ONE + ONE == TWO; +LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:30:5 | -30 | ONE + ONE == TWO; +LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:31:5 | -31 | 1 as f32 == ONE; +LL | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(1 as f32 - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:31:5 | -31 | 1 as f32 == ONE; +LL | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:34:5 | -34 | v == ONE; +LL | v == ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:34:5 | -34 | v == ONE; +LL | v == ONE; | ^^^^^^^^ error: strict comparison of f32 or f64 constant --> $DIR/float_cmp_const.rs:35:5 | -35 | v != ONE; +LL | v != ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. --> $DIR/float_cmp_const.rs:35:5 | -35 | v != ONE; +LL | v != ONE; | ^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index 27eeb909154..16605fd344a 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -1,7 +1,7 @@ error: casting function pointer `foo` to `i8`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:19:13 | -19 | let _ = foo as i8; +LL | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` | = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` @@ -9,19 +9,19 @@ error: casting function pointer `foo` to `i8`, which truncates the value error: casting function pointer `foo` to `i16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:20:13 | -20 | let _ = foo as i16; +LL | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:21:13 | -21 | let _ = foo as i32; +LL | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i64` --> $DIR/fn_to_numeric_cast.rs:22:13 | -22 | let _ = foo as i64; +LL | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` | = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` @@ -29,115 +29,115 @@ error: casting function pointer `foo` to `i64` error: casting function pointer `foo` to `i128` --> $DIR/fn_to_numeric_cast.rs:23:13 | -23 | let _ = foo as i128; +LL | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` --> $DIR/fn_to_numeric_cast.rs:24:13 | -24 | let _ = foo as isize; +LL | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:26:13 | -26 | let _ = foo as u8; +LL | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:27:13 | -27 | let _ = foo as u16; +LL | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:28:13 | -28 | let _ = foo as u32; +LL | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` --> $DIR/fn_to_numeric_cast.rs:29:13 | -29 | let _ = foo as u64; +LL | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` --> $DIR/fn_to_numeric_cast.rs:30:13 | -30 | let _ = foo as u128; +LL | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:43:13 | -43 | let _ = abc as i8; +LL | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:44:13 | -44 | let _ = abc as i16; +LL | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:45:13 | -45 | let _ = abc as i32; +LL | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` --> $DIR/fn_to_numeric_cast.rs:46:13 | -46 | let _ = abc as i64; +LL | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` --> $DIR/fn_to_numeric_cast.rs:47:13 | -47 | let _ = abc as i128; +LL | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` --> $DIR/fn_to_numeric_cast.rs:48:13 | -48 | let _ = abc as isize; +LL | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:50:13 | -50 | let _ = abc as u8; +LL | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:51:13 | -51 | let _ = abc as u16; +LL | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:52:13 | -52 | let _ = abc as u32; +LL | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` --> $DIR/fn_to_numeric_cast.rs:53:13 | -53 | let _ = abc as u64; +LL | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` --> $DIR/fn_to_numeric_cast.rs:54:13 | -54 | let _ = abc as u128; +LL | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:61:5 | -61 | f as i32 +LL | f as i32 | ^^^^^^^^ help: try: `f as usize` error: aborting due to 23 previous errors diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 640cee1bc2f..937bef9f8a6 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,421 +1,421 @@ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:50:14 | -50 | for i in 0..vec.len() { +LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -50 | for in &vec { +LL | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:59:14 | -59 | for i in 0..vec.len() { +LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -59 | for in &vec { +LL | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. --> $DIR/for_loop.rs:64:14 | -64 | for j in 0..4 { +LL | for j in 0..4 { | ^^^^ help: consider using an iterator | -64 | for in &STATIC { +LL | for in &STATIC { | ^^^^^^ ^^^^^^^ error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:68:14 | -68 | for j in 0..4 { +LL | for j in 0..4 { | ^^^^ help: consider using an iterator | -68 | for in &CONST { +LL | for in &CONST { | ^^^^^^ ^^^^^^ error: the loop variable `i` is used to index `vec` --> $DIR/for_loop.rs:72:14 | -72 | for i in 0..vec.len() { +LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -72 | for (i, ) in vec.iter().enumerate() { +LL | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. --> $DIR/for_loop.rs:80:14 | -80 | for i in 0..vec.len() { +LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -80 | for in vec2.iter().take(vec.len()) { +LL | for in vec2.iter().take(vec.len()) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:84:14 | -84 | for i in 5..vec.len() { +LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ help: consider using an iterator | -84 | for in vec.iter().skip(5) { +LL | for in vec.iter().skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:88:14 | -88 | for i in 0..MAX_LEN { +LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ help: consider using an iterator | -88 | for in vec.iter().take(MAX_LEN) { +LL | for in vec.iter().take(MAX_LEN) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:92:14 | -92 | for i in 0..=MAX_LEN { +LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ help: consider using an iterator | -92 | for in vec.iter().take(MAX_LEN + 1) { +LL | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/for_loop.rs:96:14 | -96 | for i in 5..10 { +LL | for i in 5..10 { | ^^^^^ help: consider using an iterator | -96 | for in vec.iter().take(10).skip(5) { +LL | for in vec.iter().take(10).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:100:14 - | -100 | for i in 5..=10 { - | ^^^^^^ + --> $DIR/for_loop.rs:100:14 + | +LL | for i in 5..=10 { + | ^^^^^^ help: consider using an iterator - | -100 | for in vec.iter().take(10 + 1).skip(5) { - | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +LL | for in vec.iter().take(10 + 1).skip(5) { + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:104:14 - | -104 | for i in 5..vec.len() { - | ^^^^^^^^^^^^ + --> $DIR/for_loop.rs:104:14 + | +LL | for i in 5..vec.len() { + | ^^^^^^^^^^^^ help: consider using an iterator - | -104 | for (i, ) in vec.iter().enumerate().skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +LL | for (i, ) in vec.iter().enumerate().skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:108:14 - | -108 | for i in 5..10 { - | ^^^^^ + --> $DIR/for_loop.rs:108:14 + | +LL | for i in 5..10 { + | ^^^^^ help: consider using an iterator - | -108 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { - | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +LL | for (i, ) in vec.iter().enumerate().take(10).skip(5) { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:112:14 - | -112 | for i in 10..0 { - | ^^^^^ - | - = note: `-D clippy::reverse-range-loop` implied by `-D warnings` + --> $DIR/for_loop.rs:112:14 + | +LL | for i in 10..0 { + | ^^^^^ + | + = note: `-D clippy::reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse - | -112 | for i in (0..10).rev() { - | ^^^^^^^^^^^^^ + | +LL | for i in (0..10).rev() { + | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:116:14 - | -116 | for i in 10..=0 { - | ^^^^^^ + --> $DIR/for_loop.rs:116:14 + | +LL | for i in 10..=0 { + | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse - | -116 | for i in (0...10).rev() { - | ^^^^^^^^^^^^^^ + | +LL | for i in (0...10).rev() { + | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:120:14 - | -120 | for i in MAX_LEN..0 { - | ^^^^^^^^^^ + --> $DIR/for_loop.rs:120:14 + | +LL | for i in MAX_LEN..0 { + | ^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse - | -120 | for i in (0..MAX_LEN).rev() { - | ^^^^^^^^^^^^^^^^^^ + | +LL | for i in (0..MAX_LEN).rev() { + | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:124:14 - | -124 | for i in 5..5 { - | ^^^^ + --> $DIR/for_loop.rs:124:14 + | +LL | for i in 5..5 { + | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:149:14 - | -149 | for i in 10..5 + 4 { - | ^^^^^^^^^ + --> $DIR/for_loop.rs:149:14 + | +LL | for i in 10..5 + 4 { + | ^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse - | -149 | for i in (5 + 4..10).rev() { - | ^^^^^^^^^^^^^^^^^ + | +LL | for i in (5 + 4..10).rev() { + | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:153:14 - | -153 | for i in (5 + 2)..(3 - 1) { - | ^^^^^^^^^^^^^^^^ + --> $DIR/for_loop.rs:153:14 + | +LL | for i in (5 + 2)..(3 - 1) { + | ^^^^^^^^^^^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse - | -153 | for i in ((3 - 1)..(5 + 2)).rev() { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +LL | for i in ((3 - 1)..(5 + 2)).rev() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:157:14 - | -157 | for i in (5 + 2)..(8 - 1) { - | ^^^^^^^^^^^^^^^^ + --> $DIR/for_loop.rs:157:14 + | +LL | for i in (5 + 2)..(8 - 1) { + | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:179:15 - | -179 | for _v in vec.iter() {} - | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` - | - = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` + --> $DIR/for_loop.rs:179:15 + | +LL | for _v in vec.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` + | + = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:181:15 - | -181 | for _v in vec.iter_mut() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` + --> $DIR/for_loop.rs:181:15 + | +LL | for _v in vec.iter_mut() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:184:15 - | -184 | for _v in out_vec.into_iter() {} - | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` - | - = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` + --> $DIR/for_loop.rs:184:15 + | +LL | for _v in out_vec.into_iter() {} + | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` + | + = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:187:15 - | -187 | for _v in array.into_iter() {} - | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` + --> $DIR/for_loop.rs:187:15 + | +LL | for _v in array.into_iter() {} + | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:192:15 - | -192 | for _v in [1, 2, 3].iter() {} - | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` + --> $DIR/for_loop.rs:192:15 + | +LL | for _v in [1, 2, 3].iter() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:196:15 - | -196 | for _v in [0; 32].iter() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` + --> $DIR/for_loop.rs:196:15 + | +LL | for _v in [0; 32].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:201:15 - | -201 | for _v in ll.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&ll` + --> $DIR/for_loop.rs:201:15 + | +LL | for _v in ll.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:204:15 - | -204 | for _v in vd.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&vd` + --> $DIR/for_loop.rs:204:15 + | +LL | for _v in vd.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:207:15 - | -207 | for _v in bh.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bh` + --> $DIR/for_loop.rs:207:15 + | +LL | for _v in bh.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:210:15 - | -210 | for _v in hm.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hm` + --> $DIR/for_loop.rs:210:15 + | +LL | for _v in hm.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:213:15 - | -213 | for _v in bt.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bt` + --> $DIR/for_loop.rs:213:15 + | +LL | for _v in bt.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:216:15 - | -216 | for _v in hs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hs` + --> $DIR/for_loop.rs:216:15 + | +LL | for _v in hs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:219:15 - | -219 | for _v in bs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bs` + --> $DIR/for_loop.rs:219:15 + | +LL | for _v in bs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:221:15 - | -221 | for _v in vec.iter().next() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-next-loop` implied by `-D warnings` + --> $DIR/for_loop.rs:221:15 + | +LL | for _v in vec.iter().next() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:228:5 - | -228 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unused-collect` implied by `-D warnings` + --> $DIR/for_loop.rs:228:5 + | +LL | vec.iter().cloned().map(|x| out.push(x)).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unused-collect` implied by `-D warnings` error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:337:19 - | -337 | for (_, v) in &m { - | ^^ - | - = note: `-D clippy::for-kv-map` implied by `-D warnings` + --> $DIR/for_loop.rs:337:19 + | +LL | for (_, v) in &m { + | ^^ + | + = note: `-D clippy::for-kv-map` implied by `-D warnings` help: use the corresponding method - | -337 | for v in m.values() { - | ^ ^^^^^^^^^^ + | +LL | for v in m.values() { + | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:342:19 - | -342 | for (_, v) in &*m { - | ^^^ + --> $DIR/for_loop.rs:342:19 + | +LL | for (_, v) in &*m { + | ^^^ help: use the corresponding method - | -342 | for v in (*m).values() { - | ^ ^^^^^^^^^^^^^ + | +LL | for v in (*m).values() { + | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:350:19 - | -350 | for (_, v) in &mut m { - | ^^^^^^ + --> $DIR/for_loop.rs:350:19 + | +LL | for (_, v) in &mut m { + | ^^^^^^ help: use the corresponding method - | -350 | for v in m.values_mut() { - | ^ ^^^^^^^^^^^^^^ + | +LL | for v in m.values_mut() { + | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:355:19 - | -355 | for (_, v) in &mut *m { - | ^^^^^^^ + --> $DIR/for_loop.rs:355:19 + | +LL | for (_, v) in &mut *m { + | ^^^^^^^ help: use the corresponding method - | -355 | for v in (*m).values_mut() { - | ^ ^^^^^^^^^^^^^^^^^ + | +LL | for v in (*m).values_mut() { + | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:361:24 - | -361 | for (k, _value) in rm { - | ^^ + --> $DIR/for_loop.rs:361:24 + | +LL | for (k, _value) in rm { + | ^^ help: use the corresponding method - | -361 | for k in rm.keys() { - | ^ ^^^^^^^^^ + | +LL | for k in rm.keys() { + | ^ ^^^^^^^^^ error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:414:14 - | -414 | for i in 0..src.len() { - | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` - | - = note: `-D clippy::manual-memcpy` implied by `-D warnings` + --> $DIR/for_loop.rs:414:14 + | +LL | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` + | + = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:419:14 - | -419 | for i in 0..src.len() { - | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` + --> $DIR/for_loop.rs:419:14 + | +LL | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:424:14 - | -424 | for i in 0..src.len() { - | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` + --> $DIR/for_loop.rs:424:14 + | +LL | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:429:14 - | -429 | for i in 11..src.len() { - | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` + --> $DIR/for_loop.rs:429:14 + | +LL | for i in 11..src.len() { + | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:434:14 - | -434 | for i in 0..dst.len() { - | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` + --> $DIR/for_loop.rs:434:14 + | +LL | for i in 0..dst.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:447:14 - | -447 | for i in 10..256 { - | ^^^^^^^ + --> $DIR/for_loop.rs:447:14 + | +LL | for i in 10..256 { + | ^^^^^^^ help: try replacing the loop by - | -447 | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) -448 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { - | + | +LL | for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +LL | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { + | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:459:14 - | -459 | for i in 10..LOOP_OFFSET { - | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` + --> $DIR/for_loop.rs:459:14 + | +LL | for i in 10..LOOP_OFFSET { + | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 - | -472 | for i in 0..src_vec.len() { - | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` + --> $DIR/for_loop.rs:472:14 + | +LL | for i in 0..src_vec.len() { + | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:501:14 - | -501 | for i in from..from + src.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` + --> $DIR/for_loop.rs:501:14 + | +LL | for i in from..from + src.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:505:14 - | -505 | for i in from..from + 3 { - | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` + --> $DIR/for_loop.rs:505:14 + | +LL | for i in from..from + 3 { + | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:512:14 - | -512 | for i in 0..src.len() { - | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` + --> $DIR/for_loop.rs:512:14 + | +LL | for i in 0..src.len() { + | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` error: aborting due to 51 previous errors diff --git a/tests/ui/for_loop_over_option_result.stderr b/tests/ui/for_loop_over_option_result.stderr index 13ad5fff846..f8a4212b253 100644 --- a/tests/ui/for_loop_over_option_result.stderr +++ b/tests/ui/for_loop_over_option_result.stderr @@ -1,7 +1,7 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:20:14 | -20 | for x in option { +LL | for x in option { | ^^^^^^ | = note: `-D clippy::for-loop-over-option` implied by `-D warnings` @@ -10,7 +10,7 @@ error: for loop over `option`, which is an `Option`. This is more readably writt error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:25:14 | -25 | for x in result { +LL | for x in result { | ^^^^^^ | = note: `-D clippy::for-loop-over-result` implied by `-D warnings` @@ -19,7 +19,7 @@ error: for loop over `result`, which is a `Result`. This is more readably writte error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:29:14 | -29 | for x in option.ok_or("x not found") { +LL | for x in option.ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` @@ -27,7 +27,7 @@ error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want --> $DIR/for_loop_over_option_result.rs:35:14 | -35 | for x in v.iter().next() { +LL | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ | = note: #[deny(clippy::iter_next_loop)] on by default @@ -35,7 +35,7 @@ error: you are iterating over `Iterator::next()` which is an Option; this will c error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:40:14 | -40 | for x in v.iter().next().and(Some(0)) { +LL | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` @@ -43,7 +43,7 @@ error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:44:14 | -44 | for x in v.iter().next().ok_or("x not found") { +LL | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` @@ -51,10 +51,10 @@ error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result` error: this loop never actually loops --> $DIR/for_loop_over_option_result.rs:56:5 | -56 | / while let Some(x) = option { -57 | | println!("{}", x); -58 | | break; -59 | | } +LL | / while let Some(x) = option { +LL | | println!("{}", x); +LL | | break; +LL | | } | |_____^ | = note: #[deny(clippy::never_loop)] on by default @@ -62,10 +62,10 @@ error: this loop never actually loops error: this loop never actually loops --> $DIR/for_loop_over_option_result.rs:62:5 | -62 | / while let Ok(x) = result { -63 | | println!("{}", x); -64 | | break; -65 | | } +LL | / while let Ok(x) = result { +LL | | println!("{}", x); +LL | | break; +LL | | } | |_____^ error: aborting due to 8 previous errors diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 62933f31e18..871fc8fba3e 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,7 +1,7 @@ error: useless use of `format!` --> $DIR/format.rs:21:5 | -21 | format!("foo"); +LL | format!("foo"); | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: `-D clippy::useless-format` implied by `-D warnings` @@ -9,7 +9,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:23:5 | -23 | format!("{}", "foo"); +LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -17,7 +17,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:27:5 | -27 | format!("{:+}", "foo"); // warn when the format makes no difference +LL | format!("{:+}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -25,7 +25,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:28:5 | -28 | format!("{:<}", "foo"); // warn when the format makes no difference +LL | format!("{:<}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -33,7 +33,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:33:5 | -33 | format!("{}", arg); +LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -41,7 +41,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:37:5 | -37 | format!("{:+}", arg); // warn when the format makes no difference +LL | format!("{:+}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -49,7 +49,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:38:5 | -38 | format!("{:<}", arg); // warn when the format makes no difference +LL | format!("{:<}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -57,7 +57,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:65:5 | -65 | format!("{}", 42.to_string()); +LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -65,7 +65,7 @@ error: useless use of `format!` error: useless use of `format!` --> $DIR/format.rs:67:5 | -67 | format!("{}", x.display().to_string()); +LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 9f00a51bc1f..061540b9aa5 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,7 +1,7 @@ error: this looks like an `else {..}` but the `else` is missing --> $DIR/formatting.rs:21:6 | -21 | } { +LL | } { | ^ | = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` @@ -10,7 +10,7 @@ error: this looks like an `else {..}` but the `else` is missing error: this looks like an `else if` but the `else` is missing --> $DIR/formatting.rs:25:6 | -25 | } if foo() { +LL | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` @@ -18,7 +18,7 @@ error: this looks like an `else if` but the `else` is missing error: this looks like an `else if` but the `else` is missing --> $DIR/formatting.rs:32:10 | -32 | } if foo() { +LL | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` @@ -26,7 +26,7 @@ error: this looks like an `else if` but the `else` is missing error: this looks like an `else if` but the `else` is missing --> $DIR/formatting.rs:40:10 | -40 | } if foo() { +LL | } if foo() { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the second `if` @@ -34,9 +34,9 @@ error: this looks like an `else if` but the `else` is missing error: this is an `else {..}` but the formatting might hide it --> $DIR/formatting.rs:49:6 | -49 | } else +LL | } else | ______^ -50 | | { +LL | | { | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` @@ -44,10 +44,10 @@ error: this is an `else {..}` but the formatting might hide it error: this is an `else {..}` but the formatting might hide it --> $DIR/formatting.rs:54:6 | -54 | } +LL | } | ______^ -55 | | else -56 | | { +LL | | else +LL | | { | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` @@ -55,9 +55,9 @@ error: this is an `else {..}` but the formatting might hide it error: this is an `else if` but the formatting might hide it --> $DIR/formatting.rs:60:6 | -60 | } else +LL | } else | ______^ -61 | | if foo() { // the span of the above error should continue here +LL | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` @@ -65,55 +65,55 @@ error: this is an `else if` but the formatting might hide it error: this is an `else if` but the formatting might hide it --> $DIR/formatting.rs:65:6 | -65 | } +LL | } | ______^ -66 | | else -67 | | if foo() { // the span of the above error should continue here +LL | | else +LL | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:106:6 - | -106 | a =- 35; - | ^^^^ - | - = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` - = note: to remove this lint, use either `-=` or `= -` + --> $DIR/formatting.rs:106:6 + | +LL | a =- 35; + | ^^^^ + | + = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings` + = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:107:6 - | -107 | a =* &191; - | ^^^^ - | - = note: to remove this lint, use either `*=` or `= *` + --> $DIR/formatting.rs:107:6 + | +LL | a =* &191; + | ^^^^ + | + = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:110:6 - | -110 | b =! false; - | ^^^^ - | - = note: to remove this lint, use either `!=` or `= !` + --> $DIR/formatting.rs:110:6 + | +LL | b =! false; + | ^^^^ + | + = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:119:19 - | -119 | -1, -2, -3 // <= no comma here - | ^ - | - = note: `-D clippy::possible-missing-comma` implied by `-D warnings` - = note: to remove this lint, add a comma or write the expr in a single line + --> $DIR/formatting.rs:119:19 + | +LL | -1, -2, -3 // <= no comma here + | ^ + | + = note: `-D clippy::possible-missing-comma` implied by `-D warnings` + = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:123:19 - | -123 | -1, -2, -3 // <= no comma here - | ^ - | - = note: to remove this lint, add a comma or write the expr in a single line + --> $DIR/formatting.rs:123:19 + | +LL | -1, -2, -3 // <= no comma here + | ^ + | + = note: to remove this lint, add a comma or write the expr in a single line error: aborting due to 13 previous errors diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 206d04d6a39..b23d09309bb 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -1,7 +1,7 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:17:1 | -17 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` @@ -9,19 +9,19 @@ error: this function has too many arguments (8/7) error: this function has too many arguments (8/7) --> $DIR/functions.rs:34:5 | -34 | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); +LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many arguments (8/7) --> $DIR/functions.rs:43:5 | -43 | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:52:34 | -52 | println!("{}", unsafe { *p }); +LL | println!("{}", unsafe { *p }); | ^ | = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` @@ -29,49 +29,49 @@ error: this public function dereferences a raw pointer but is not marked `unsafe error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:53:35 | -53 | println!("{:?}", unsafe { p.as_ref() }); +LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:54:33 | -54 | unsafe { std::ptr::read(p) }; +LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:65:30 | -65 | println!("{}", unsafe { *p }); +LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:66:31 | -66 | println!("{:?}", unsafe { p.as_ref() }); +LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:67:29 | -67 | unsafe { std::ptr::read(p) }; +LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:76:34 | -76 | println!("{}", unsafe { *p }); +LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:77:35 | -77 | println!("{:?}", unsafe { p.as_ref() }); +LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:78:33 | -78 | unsafe { std::ptr::read(p) }; +LL | unsafe { std::ptr::read(p) }; | ^ error: aborting due to 12 previous errors diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index a1e50401b46..14fc4a8090b 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -1,7 +1,7 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:16:24 | -16 | use std::collections::{HashMap, HashSet}; +LL | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashMap` | = note: `-D clippy::default-hash-types` implied by `-D warnings` @@ -9,31 +9,31 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't nee error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:16:33 | -16 | use std::collections::{HashMap, HashSet}; +LL | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:19:15 | -19 | let _map: HashMap = HashMap::default(); +LL | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:19:41 | -19 | let _map: HashMap = HashMap::default(); +LL | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:20:15 | -20 | let _set: HashSet = HashSet::default(); +LL | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy --> $DIR/fxhash.rs:20:33 | -20 | let _set: HashSet = HashSet::default(); +LL | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: aborting due to 6 previous errors diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 8b07e740a9a..1f45c26048a 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,7 +1,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:41:17 | -41 | let _ = boxed_slice.get(1).unwrap(); +LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | = note: `-D clippy::get-unwrap` implied by `-D warnings` @@ -9,67 +9,67 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:42:17 | -42 | let _ = some_slice.get(0).unwrap(); +LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:43:17 | -43 | let _ = some_vec.get(0).unwrap(); +LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:44:17 | -44 | let _ = some_vecdeque.get(0).unwrap(); +LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:45:17 | -45 | let _ = some_hashmap.get(&1).unwrap(); +LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:46:17 | -46 | let _ = some_btreemap.get(&1).unwrap(); +LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:52:10 | -52 | *boxed_slice.get_mut(0).unwrap() = 1; +LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:53:10 | -53 | *some_slice.get_mut(0).unwrap() = 1; +LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:54:10 | -54 | *some_vec.get_mut(0).unwrap() = 1; +LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:55:10 | -55 | *some_vecdeque.get_mut(0).unwrap() = 1; +LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:64:17 | -64 | let _ = some_vec.get(0..1).unwrap().to_vec(); +LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:65:17 | -65 | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); +LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: aborting due to 12 previous errors diff --git a/tests/ui/ice-2636.stderr b/tests/ui/ice-2636.stderr index a0806af5da9..a6b150f9b90 100644 --- a/tests/ui/ice-2636.stderr +++ b/tests/ui/ice-2636.stderr @@ -1,13 +1,13 @@ error: you don't need to add `&` to both the expression and the patterns --> $DIR/ice-2636.rs:21:9 | -21 | / match $foo { -22 | | $ ( & $t => $ord, -23 | | )* -24 | | }; +LL | / match $foo { +LL | | $ ( & $t => $ord, +LL | | )* +LL | | }; | |_________^ ... -30 | test_hash!(&a, A => 0, B => 1, C => 2); +LL | test_hash!(&a, A => 0, B => 1, C => 2); | --------------------------------------- in this macro invocation | = note: `-D clippy::match-ref-pats` implied by `-D warnings` diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index aab6bf7f218..4b0b958e285 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,67 +1,67 @@ error: identical conversion --> $DIR/identity_conversion.rs:13:13 | -13 | let _ = T::from(val); +LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: lint level defined here --> $DIR/identity_conversion.rs:10:9 | -10 | #![deny(clippy::identity_conversion)] +LL | #![deny(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion --> $DIR/identity_conversion.rs:14:5 | -14 | val.into() +LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion --> $DIR/identity_conversion.rs:26:22 | -26 | let _: i32 = 0i32.into(); +LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion --> $DIR/identity_conversion.rs:47:21 | -47 | let _: String = "foo".to_string().into(); +LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion --> $DIR/identity_conversion.rs:48:21 | -48 | let _: String = From::from("foo".to_string()); +LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion --> $DIR/identity_conversion.rs:49:13 | -49 | let _ = String::from("foo".to_string()); +LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion --> $DIR/identity_conversion.rs:50:13 | -50 | let _ = String::from(format!("A: {:04}", 123)); +LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion --> $DIR/identity_conversion.rs:51:13 | -51 | let _ = "".lines().into_iter(); +LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion --> $DIR/identity_conversion.rs:52:13 | -52 | let _ = vec![1, 2, 3].into_iter().into_iter(); +LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: identical conversion --> $DIR/identity_conversion.rs:53:21 | -53 | let _: String = format!("Hello {}", "world").into(); +LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: aborting due to 10 previous errors diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 19846b5ecdf..8b42cfbf1ce 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,7 +1,7 @@ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:25:5 | -25 | x + 0; +LL | x + 0; | ^^^^^ | = note: `-D clippy::identity-op` implied by `-D warnings` @@ -9,43 +9,43 @@ error: the operation is ineffective. Consider reducing it to `x` error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:26:5 | -26 | x + (1 - 1); +LL | x + (1 - 1); | ^^^^^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:28:5 | -28 | 0 + x; +LL | 0 + x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:31:5 | -31 | x | (0); +LL | x | (0); | ^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:34:5 | -34 | x * 1; +LL | x * 1; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:35:5 | -35 | 1 * x; +LL | 1 * x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` --> $DIR/identity_op.rs:41:5 | -41 | -1 & x; +LL | -1 & x; | ^^^^^^ error: the operation is ineffective. Consider reducing it to `u` --> $DIR/identity_op.rs:44:5 | -44 | u & 255; +LL | u & 255; | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index 0393e49a2ee..acdf543cc75 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -1,11 +1,11 @@ error: Unnecessary boolean `not` operation --> $DIR/if_not_else.rs:18:5 | -18 | / if !bla() { -19 | | println!("Bugs"); -20 | | } else { -21 | | println!("Bunny"); -22 | | } +LL | / if !bla() { +LL | | println!("Bugs"); +LL | | } else { +LL | | println!("Bunny"); +LL | | } | |_____^ | = note: `-D clippy::if-not-else` implied by `-D warnings` @@ -14,11 +14,11 @@ error: Unnecessary boolean `not` operation error: Unnecessary `!=` operation --> $DIR/if_not_else.rs:23:5 | -23 | / if 4 != 5 { -24 | | println!("Bugs"); -25 | | } else { -26 | | println!("Bunny"); -27 | | } +LL | / if 4 != 5 { +LL | | println!("Bugs"); +LL | | } else { +LL | | println!("Bunny"); +LL | | } | |_____^ | = help: change to `==` and swap the blocks of the if/else diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index adad754bffe..8bddd400f70 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,34 +1,34 @@ error: Multiple implementations of this structure --> $DIR/impl.rs:19:1 | -19 | / impl MyStruct { -20 | | fn second() {} -21 | | } +LL | / impl MyStruct { +LL | | fn second() {} +LL | | } | |_^ | = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` note: First implementation here --> $DIR/impl.rs:15:1 | -15 | / impl MyStruct { -16 | | fn first() {} -17 | | } +LL | / impl MyStruct { +LL | | fn first() {} +LL | | } | |_^ error: Multiple implementations of this structure --> $DIR/impl.rs:33:5 | -33 | / impl super::MyStruct { -34 | | fn third() {} -35 | | } +LL | / impl super::MyStruct { +LL | | fn third() {} +LL | | } | |_____^ | note: First implementation here --> $DIR/impl.rs:15:1 | -15 | / impl MyStruct { -16 | | fn first() {} -17 | | } +LL | / impl MyStruct { +LL | | fn first() {} +LL | | } | |_^ error: aborting due to 2 previous errors diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 35306e77aec..0c61dbc4c64 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,136 +1,136 @@ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:20:35 | -20 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ | = note: `-D clippy::implicit-hasher` implied by `-D warnings` help: consider adding a type parameter | -20 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -26 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:29:36 | -29 | impl Foo for (HashMap,) { +LL | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ help: consider adding a type parameter | -29 | impl Foo for (HashMap,) { +LL | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -31 | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) +LL | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:34:19 | -34 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -34 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -36 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:51:32 | -51 | impl Foo for HashSet { +LL | impl Foo for HashSet { | ^^^^^^^^^^ help: consider adding a type parameter | -51 | impl Foo for HashSet { +LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ help: ...and use generic constructor | -53 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:56:19 | -56 | impl Foo for HashSet { +LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ help: consider adding a type parameter | -56 | impl Foo for HashSet { +LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -58 | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) +LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:73:23 | -73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | -73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:73:53 | -73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ help: consider adding a type parameter | -73 | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:77:43 | -77 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ ... -89 | gen!(impl); +LL | gen!(impl); | ----------- in this macro invocation help: consider adding a type parameter | -77 | impl Foo for HashMap { +LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ help: ...and use generic constructor | -79 | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) +LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers --> $DIR/implicit_hasher.rs:85:33 | -85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ ... -90 | gen!(fn bar); +LL | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers --> $DIR/implicit_hasher.rs:85:63 | -85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ ... -90 | gen!(fn bar); +LL | gen!(fn bar); | ------------- in this macro invocation help: consider adding a type parameter | -85 | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} +LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 3c124eb3357..4c62a7d65c6 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,7 +1,7 @@ error: missing return statement --> $DIR/implicit_return.rs:17:5 | -17 | true +LL | true | ^^^^ help: add `return` as shown: `return true` | = note: `-D clippy::implicit-return` implied by `-D warnings` @@ -9,55 +9,55 @@ error: missing return statement error: missing return statement --> $DIR/implicit_return.rs:23:9 | -23 | true +LL | true | ^^^^ help: add `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:25:9 | -25 | false +LL | false | ^^^^^ help: add `return` as shown: `return false` error: missing return statement --> $DIR/implicit_return.rs:33:17 | -33 | true => false, +LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement --> $DIR/implicit_return.rs:34:20 | -34 | false => { true }, +LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:41:9 | -41 | break true; +LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:49:13 | -49 | break true; +LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:58:13 | -58 | break true; +LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:67:18 | -67 | let _ = || { true }; +LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement --> $DIR/implicit_return.rs:68:16 | -68 | let _ = || true; +LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: aborting due to 10 previous errors diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 77e2f3bd41b..ba909b94480 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,7 +1,7 @@ error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:22:16 | -22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` @@ -9,25 +9,25 @@ error: digits grouped inconsistently by underscores error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:22:26 | -22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:22:38 | -22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:22:48 | -22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores --> $DIR/inconsistent_digit_grouping.rs:22:64 | -22 | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); +LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: aborting due to 5 previous errors diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index c9a45bc4084..2e7bff3e0d5 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,7 +1,7 @@ error: index out of bounds: the len is 4 but the index is 4 --> $DIR/indexing_slicing.rs:25:5 | -25 | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ | = note: #[deny(const_err)] on by default @@ -9,25 +9,25 @@ error: index out of bounds: the len is 4 but the index is 4 error: index out of bounds: the len is 4 but the index is 8 --> $DIR/indexing_slicing.rs:26:5 | -26 | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +LL | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^^ error: index out of bounds: the len is 0 but the index is 0 --> $DIR/indexing_slicing.rs:56:5 | -56 | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +LL | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^ error: index out of bounds: the len is 4 but the index is 15 --> $DIR/indexing_slicing.rs:87:5 | -87 | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +LL | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ error: indexing may panic. --> $DIR/indexing_slicing.rs:20:5 | -20 | x[index]; +LL | x[index]; | ^^^^^^^^ | = note: `-D clippy::indexing-slicing` implied by `-D warnings` @@ -36,7 +36,7 @@ error: indexing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:21:6 | -21 | &x[index..]; +LL | &x[index..]; | ^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead @@ -44,7 +44,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:22:6 | -22 | &x[..index]; +LL | &x[..index]; | ^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -52,7 +52,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:23:6 | -23 | &x[index_from..index_to]; +LL | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead @@ -60,7 +60,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:24:6 | -24 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -68,7 +68,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:24:6 | -24 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. +LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead @@ -76,7 +76,7 @@ error: slicing may panic. error: range is out of bounds --> $DIR/indexing_slicing.rs:27:11 | -27 | &x[..=4]; +LL | &x[..=4]; | ^ | = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` @@ -84,13 +84,13 @@ error: range is out of bounds error: range is out of bounds --> $DIR/indexing_slicing.rs:28:11 | -28 | &x[1..5]; +LL | &x[1..5]; | ^ error: slicing may panic. --> $DIR/indexing_slicing.rs:29:6 | -29 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -98,37 +98,37 @@ error: slicing may panic. error: range is out of bounds --> $DIR/indexing_slicing.rs:29:8 | -29 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:30:8 | -30 | &x[5..]; +LL | &x[5..]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:31:10 | -31 | &x[..5]; +LL | &x[..5]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:32:8 | -32 | &x[5..].iter().map(|x| 2 * x).collect::>(); +LL | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:33:12 | -33 | &x[0..=4]; +LL | &x[0..=4]; | ^ error: slicing may panic. --> $DIR/indexing_slicing.rs:34:6 | -34 | &x[0..][..3]; +LL | &x[0..][..3]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -136,7 +136,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:35:6 | -35 | &x[1..][..5]; +LL | &x[1..][..5]; | ^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -144,7 +144,7 @@ error: slicing may panic. error: indexing may panic. --> $DIR/indexing_slicing.rs:48:5 | -48 | y[0]; +LL | y[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -152,7 +152,7 @@ error: indexing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:49:6 | -49 | &y[1..2]; +LL | &y[1..2]; | ^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead @@ -160,7 +160,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:50:6 | -50 | &y[0..=4]; +LL | &y[0..=4]; | ^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead @@ -168,7 +168,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:51:6 | -51 | &y[..=4]; +LL | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -176,49 +176,49 @@ error: slicing may panic. error: range is out of bounds --> $DIR/indexing_slicing.rs:57:12 | -57 | &empty[1..5]; +LL | &empty[1..5]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:58:16 | -58 | &empty[0..=4]; +LL | &empty[0..=4]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:59:15 | -59 | &empty[..=4]; +LL | &empty[..=4]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:60:12 | -60 | &empty[1..]; +LL | &empty[1..]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:61:14 | -61 | &empty[..4]; +LL | &empty[..4]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:62:16 | -62 | &empty[0..=0]; +LL | &empty[0..=0]; | ^ error: range is out of bounds --> $DIR/indexing_slicing.rs:63:15 | -63 | &empty[..=0]; +LL | &empty[..=0]; | ^ error: indexing may panic. --> $DIR/indexing_slicing.rs:71:5 | -71 | v[0]; +LL | v[0]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -226,7 +226,7 @@ error: indexing may panic. error: indexing may panic. --> $DIR/indexing_slicing.rs:72:5 | -72 | v[10]; +LL | v[10]; | ^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -234,7 +234,7 @@ error: indexing may panic. error: indexing may panic. --> $DIR/indexing_slicing.rs:73:5 | -73 | v[1 << 3]; +LL | v[1 << 3]; | ^^^^^^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -242,7 +242,7 @@ error: indexing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:74:6 | -74 | &v[10..100]; +LL | &v[10..100]; | ^^^^^^^^^^ | = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead @@ -250,7 +250,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:75:6 | -75 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -258,13 +258,13 @@ error: slicing may panic. error: range is out of bounds --> $DIR/indexing_slicing.rs:75:8 | -75 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. +LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^ error: slicing may panic. --> $DIR/indexing_slicing.rs:76:6 | -76 | &v[10..]; +LL | &v[10..]; | ^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead @@ -272,7 +272,7 @@ error: slicing may panic. error: slicing may panic. --> $DIR/indexing_slicing.rs:77:6 | -77 | &v[..100]; +LL | &v[..100]; | ^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead @@ -280,7 +280,7 @@ error: slicing may panic. error: indexing may panic. --> $DIR/indexing_slicing.rs:89:5 | -89 | v[N]; +LL | v[N]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -288,7 +288,7 @@ error: indexing may panic. error: indexing may panic. --> $DIR/indexing_slicing.rs:90:5 | -90 | v[M]; +LL | v[M]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead @@ -296,13 +296,13 @@ error: indexing may panic. error: range is out of bounds --> $DIR/indexing_slicing.rs:94:13 | -94 | &x[num..10]; // should trigger out of bounds error +LL | &x[num..10]; // should trigger out of bounds error | ^^ error: range is out of bounds --> $DIR/indexing_slicing.rs:95:8 | -95 | &x[10..num]; // should trigger out of bounds error +LL | &x[10..num]; // should trigger out of bounds error | ^^ error: aborting due to 43 previous errors diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index 62588a2ad7c..976957d35d7 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,9 +1,9 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` --> $DIR/infallible_destructuring_match.rs:25:5 | -25 | / let data = match wrapper { -26 | | SingleVariantEnum::Variant(i) => i, -27 | | }; +LL | / let data = match wrapper { +LL | | SingleVariantEnum::Variant(i) => i, +LL | | }; | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` | = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` @@ -11,17 +11,17 @@ error: you seem to be trying to use match to destructure a single infallible pat error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` --> $DIR/infallible_destructuring_match.rs:46:5 | -46 | / let data = match wrapper { -47 | | TupleStruct(i) => i, -48 | | }; +LL | / let data = match wrapper { +LL | | TupleStruct(i) => i, +LL | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` --> $DIR/infallible_destructuring_match.rs:67:5 | -67 | / let data = match wrapper { -68 | | Ok(i) => i, -69 | | }; +LL | / let data = match wrapper { +LL | | Ok(i) => i, +LL | | }; | |______^ help: try this: `let Ok(data) = wrapper;` error: aborting due to 3 previous errors diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 2c3b05aaff3..c64b3918db4 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,7 +1,7 @@ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator --> $DIR/infinite_iter.rs:19:5 | -19 | repeat(0_u8).collect::>(); // infinite iter +LL | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-collect` implied by `-D warnings` @@ -9,100 +9,100 @@ error: you are collect()ing an iterator and throwing away the result. Consider u error: infinite iteration detected --> $DIR/infinite_iter.rs:19:5 | -19 | repeat(0_u8).collect::>(); // infinite iter +LL | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/infinite_iter.rs:17:8 | -17 | #[deny(clippy::infinite_iter)] +LL | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected --> $DIR/infinite_iter.rs:20:5 | -20 | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter +LL | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected --> $DIR/infinite_iter.rs:21:5 | -21 | (0..8_u64).chain(0..).max(); // infinite iter +LL | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected --> $DIR/infinite_iter.rs:26:5 | -26 | / (0..8_u32) -27 | | .rev() -28 | | .cycle() -29 | | .map(|x| x + 1_u32) -30 | | .for_each(|x| println!("{}", x)); // infinite iter +LL | / (0..8_u32) +LL | | .rev() +LL | | .cycle() +LL | | .map(|x| x + 1_u32) +LL | | .for_each(|x| println!("{}", x)); // infinite iter | |________________________________________^ error: infinite iteration detected --> $DIR/infinite_iter.rs:32:5 | -32 | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter +LL | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected --> $DIR/infinite_iter.rs:33:5 | -33 | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter +LL | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:40:5 | -40 | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter +LL | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/infinite_iter.rs:38:8 | -38 | #[deny(clippy::maybe_infinite_iter)] +LL | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:41:5 | -41 | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter +LL | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:42:5 | -42 | / (1..) -43 | | .scan(0, |state, x| { -44 | | *state += x; -45 | | Some(*state) -46 | | }) -47 | | .min(); // maybe infinite iter +LL | / (1..) +LL | | .scan(0, |state, x| { +LL | | *state += x; +LL | | Some(*state) +LL | | }) +LL | | .min(); // maybe infinite iter | |______________^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:48:5 | -48 | (0..).find(|x| *x == 24); // maybe infinite iter +LL | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:49:5 | -49 | (0..).position(|x| x == 24); // maybe infinite iter +LL | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:50:5 | -50 | (0..).any(|x| x == 24); // maybe infinite iter +LL | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> $DIR/infinite_iter.rs:51:5 | -51 | (0..).all(|x| x == 24); // maybe infinite iter +LL | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index de7851519ec..79efb18a83e 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,7 +1,7 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:32:11 | -32 | while y < 10 { +LL | while y < 10 { | ^^^^^^ | = note: #[deny(clippy::while_immutable_condition)] on by default @@ -9,50 +9,50 @@ error: Variable in the condition are not mutated in the loop body. This either l error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:37:11 | -37 | while y < 10 && x < 3 { +LL | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:44:11 | -44 | while !cond { +LL | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:88:11 | -88 | while i < 3 { +LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:93:11 | -93 | while i < 3 && j > 0 { +LL | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:97:11 | -97 | while i < 3 { +LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:112:11 - | -112 | while i < 3 { - | ^^^^^ + --> $DIR/infinite_loop.rs:112:11 + | +LL | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:117:11 - | -117 | while i < 3 { - | ^^^^^ + --> $DIR/infinite_loop.rs:117:11 + | +LL | while i < 3 { + | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:183:15 - | -183 | while self.count < n { - | ^^^^^^^^^^^^^^ + --> $DIR/infinite_loop.rs:183:15 + | +LL | while self.count < n { + | ^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 0eaee7c7b25..3c2b086968e 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,9 +1,9 @@ error: use of `#[inline]` on trait method `default_inline` which has no body --> $DIR/inline_fn_without_body.rs:14:5 | -14 | #[inline] +LL | #[inline] | _____-^^^^^^^^ -15 | | fn default_inline(); +LL | | fn default_inline(); | |____- help: remove | = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` @@ -11,17 +11,17 @@ error: use of `#[inline]` on trait method `default_inline` which has no body error: use of `#[inline]` on trait method `always_inline` which has no body --> $DIR/inline_fn_without_body.rs:17:5 | -17 | #[inline(always)] +LL | #[inline(always)] | _____-^^^^^^^^^^^^^^^^ -18 | | fn always_inline(); +LL | | fn always_inline(); | |____- help: remove error: use of `#[inline]` on trait method `never_inline` which has no body --> $DIR/inline_fn_without_body.rs:20:5 | -20 | #[inline(never)] +LL | #[inline(never)] | _____-^^^^^^^^^^^^^^^ -21 | | fn never_inline(); +LL | | fn never_inline(); | |____- help: remove error: aborting due to 3 previous errors diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 4a81e911157..30bc2966619 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,43 +1,43 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:16:5 | -16 | x >= y + 1; +LL | x >= y + 1; | ^^^^^^^^^^ | = note: `-D clippy::int-plus-one` implied by `-D warnings` help: change `>= y + 1` to `> y` as shown | -16 | x > y; +LL | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:17:5 | -17 | y + 1 <= x; +LL | y + 1 <= x; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -17 | y < x; +LL | y < x; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:19:5 | -19 | x - 1 >= y; +LL | x - 1 >= y; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -19 | x > y; +LL | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:20:5 | -20 | y <= x - 1; +LL | y <= x - 1; | ^^^^^^^^^^ help: change `>= y + 1` to `> y` as shown | -20 | y < x; +LL | y < x; | ^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index f6d6fe35d7f..e7f2a21d7a4 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,25 +1,25 @@ error: this .into_iter() call is equivalent to .iter() and will not move the array --> $DIR/into_iter_on_ref.rs:11:24 | -11 | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() +LL | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` | note: lint level defined here --> $DIR/into_iter_on_ref.rs:2:9 | -2 | #![deny(clippy::into_iter_on_array)] +LL | #![deny(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this .into_iter() call is equivalent to .iter() and will not move the array --> $DIR/into_iter_on_ref.rs:13:23 | -13 | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the Vec --> $DIR/into_iter_on_ref.rs:15:30 | -15 | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` | = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` @@ -27,151 +27,151 @@ error: this .into_iter() call is equivalent to .iter() and will not move the Vec error: this .into_iter() call is equivalent to .iter() and will not move the slice --> $DIR/into_iter_on_ref.rs:16:46 | -16 | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() +LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the slice --> $DIR/into_iter_on_ref.rs:17:41 | -17 | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the slice --> $DIR/into_iter_on_ref.rs:18:44 | -18 | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array --> $DIR/into_iter_on_ref.rs:20:32 | -20 | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array --> $DIR/into_iter_on_ref.rs:21:36 | -21 | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the array --> $DIR/into_iter_on_ref.rs:22:40 | -22 | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() +LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Option --> $DIR/into_iter_on_ref.rs:24:24 | -24 | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Option --> $DIR/into_iter_on_ref.rs:25:28 | -25 | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Result --> $DIR/into_iter_on_ref.rs:26:32 | -26 | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Result --> $DIR/into_iter_on_ref.rs:27:37 | -27 | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Vec --> $DIR/into_iter_on_ref.rs:28:34 | -28 | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Vec --> $DIR/into_iter_on_ref.rs:29:38 | -29 | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the BTreeMap --> $DIR/into_iter_on_ref.rs:30:44 | -30 | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the BTreeMap --> $DIR/into_iter_on_ref.rs:31:48 | -31 | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the VecDeque --> $DIR/into_iter_on_ref.rs:32:39 | -32 | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the VecDeque --> $DIR/into_iter_on_ref.rs:33:43 | -33 | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the LinkedList --> $DIR/into_iter_on_ref.rs:34:41 | -34 | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the LinkedList --> $DIR/into_iter_on_ref.rs:35:45 | -35 | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the HashMap --> $DIR/into_iter_on_ref.rs:36:43 | -36 | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the HashMap --> $DIR/into_iter_on_ref.rs:37:47 | -37 | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the BTreeSet --> $DIR/into_iter_on_ref.rs:39:39 | -39 | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the BinaryHeap --> $DIR/into_iter_on_ref.rs:40:41 | -40 | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the HashSet --> $DIR/into_iter_on_ref.rs:41:38 | -41 | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the Path --> $DIR/into_iter_on_ref.rs:42:43 | -42 | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the PathBuf --> $DIR/into_iter_on_ref.rs:43:47 | -43 | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: aborting due to 28 previous errors diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index a5142596aeb..f4386362099 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,7 +1,7 @@ error: reference to zeroed memory --> $DIR/invalid_ref.rs:33:24 | -33 | let ref_zero: &T = std::mem::zeroed(); // warning +LL | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | = note: #[deny(clippy::invalid_ref)] on by default @@ -10,7 +10,7 @@ error: reference to zeroed memory error: reference to zeroed memory --> $DIR/invalid_ref.rs:37:24 | -37 | let ref_zero: &T = core::mem::zeroed(); // warning +LL | let ref_zero: &T = core::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -18,7 +18,7 @@ error: reference to zeroed memory error: reference to zeroed memory --> $DIR/invalid_ref.rs:41:24 | -41 | let ref_zero: &T = std::intrinsics::init(); // warning +LL | let ref_zero: &T = std::intrinsics::init(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -26,7 +26,7 @@ error: reference to zeroed memory error: reference to uninitialized memory --> $DIR/invalid_ref.rs:45:26 | -45 | let ref_uninit: &T = std::mem::uninitialized(); // warning +LL | let ref_uninit: &T = std::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -34,7 +34,7 @@ error: reference to uninitialized memory error: reference to uninitialized memory --> $DIR/invalid_ref.rs:49:26 | -49 | let ref_uninit: &T = core::mem::uninitialized(); // warning +LL | let ref_uninit: &T = core::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -42,7 +42,7 @@ error: reference to uninitialized memory error: reference to uninitialized memory --> $DIR/invalid_ref.rs:53:26 | -53 | let ref_uninit: &T = std::intrinsics::uninit(); // warning +LL | let ref_uninit: &T = std::intrinsics::uninit(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index 2ac4a48b862..4bf92088337 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -1,7 +1,7 @@ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:30:5 | -30 | (u8 as u32) > 300; +LL | (u8 as u32) > 300; | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` @@ -9,157 +9,157 @@ error: because of the numeric bounds on `u8` prior to casting, this expression i error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:31:5 | -31 | (u8 as i32) > 300; +LL | (u8 as i32) > 300; | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:32:5 | -32 | (u8 as u32) == 300; +LL | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:33:5 | -33 | (u8 as i32) == 300; +LL | (u8 as i32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:34:5 | -34 | 300 < (u8 as u32); +LL | 300 < (u8 as u32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:35:5 | -35 | 300 < (u8 as i32); +LL | 300 < (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:36:5 | -36 | 300 == (u8 as u32); +LL | 300 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:37:5 | -37 | 300 == (u8 as i32); +LL | 300 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:39:5 | -39 | (u8 as u32) <= 300; +LL | (u8 as u32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:40:5 | -40 | (u8 as i32) <= 300; +LL | (u8 as i32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:41:5 | -41 | (u8 as u32) != 300; +LL | (u8 as u32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:42:5 | -42 | (u8 as i32) != 300; +LL | (u8 as i32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:43:5 | -43 | 300 >= (u8 as u32); +LL | 300 >= (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:44:5 | -44 | 300 >= (u8 as i32); +LL | 300 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:45:5 | -45 | 300 != (u8 as u32); +LL | 300 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:46:5 | -46 | 300 != (u8 as i32); +LL | 300 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:49:5 | -49 | (u8 as i32) < 0; +LL | (u8 as i32) < 0; | ^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:50:5 | -50 | -5 != (u8 as i32); +LL | -5 != (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:52:5 | -52 | (u8 as i32) >= 0; +LL | (u8 as i32) >= 0; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:53:5 | -53 | -5 == (u8 as i32); +LL | -5 == (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:56:5 | -56 | 1337 == (u8 as i32); +LL | 1337 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:57:5 | -57 | 1337 == (u8 as u32); +LL | 1337 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:59:5 | -59 | 1337 != (u8 as i32); +LL | 1337 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:60:5 | -60 | 1337 != (u8 as u32); +LL | 1337 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:74:5 | -74 | (u8 as i32) > -1; +LL | (u8 as i32) > -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:75:5 | -75 | (u8 as i32) < -1; +LL | (u8 as i32) < -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:91:5 | -91 | -5 >= (u8 as i32); +LL | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: aborting due to 27 previous errors diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index 6f9f88a8d67..c7a995c61d6 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,7 +1,7 @@ error: expected token: `,` --> $DIR/issue-3145.rs:11:19 | -11 | println!("{}" a); //~ERROR expected token: `,` +LL | println!("{}" a); //~ERROR expected token: `,` | ^ error: aborting due to previous error diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr index 28b67cbc9fa..37599900312 100644 --- a/tests/ui/issue_2356.stderr +++ b/tests/ui/issue_2356.stderr @@ -1,13 +1,13 @@ error: this loop could be written as a `for` loop --> $DIR/issue_2356.rs:24:29 | -24 | while let Some(e) = it.next() { +LL | while let Some(e) = it.next() { | ^^^^^^^^^ help: try: `for e in it { .. }` | note: lint level defined here --> $DIR/issue_2356.rs:10:9 | -10 | #![deny(clippy::while_let_on_iterator)] +LL | #![deny(clippy::while_let_on_iterator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index c988fca3827..3024431244c 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -1,9 +1,9 @@ error: adding items after statements is confusing, since items exist from the start of the scope --> $DIR/item_after_statement.rs:21:5 | -21 | / fn foo() { -22 | | println!("foo"); -23 | | } +LL | / fn foo() { +LL | | println!("foo"); +LL | | } | |_____^ | = note: `-D clippy::items-after-statements` implied by `-D warnings` @@ -11,9 +11,9 @@ error: adding items after statements is confusing, since items exist from the st error: adding items after statements is confusing, since items exist from the start of the scope --> $DIR/item_after_statement.rs:28:5 | -28 | / fn foo() { -29 | | println!("foo"); -30 | | } +LL | / fn foo() { +LL | | println!("foo"); +LL | | } | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 47587f5423a..3f88aefda33 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -1,7 +1,7 @@ error: digit groups should be smaller --> $DIR/large_digit_groups.rs:24:9 | -24 | 0b1_10110_i64, +LL | 0b1_10110_i64, | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` @@ -9,31 +9,31 @@ error: digit groups should be smaller error: digit groups should be smaller --> $DIR/large_digit_groups.rs:25:9 | -25 | 0x1_23456_78901_usize, +LL | 0x1_23456_78901_usize, | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:26:9 | -26 | 1_23456_f32, +LL | 1_23456_f32, | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:27:9 | -27 | 1_23456.12_f32, +LL | 1_23456.12_f32, | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:28:9 | -28 | 1_23456.12345_f32, +LL | 1_23456.12345_f32, | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:29:9 | -29 | 1_23456.12345_6_f32, +LL | 1_23456.12345_6_f32, | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` error: aborting due to 6 previous errors diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index c9c46ced5e2..839d16bd9a2 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -1,69 +1,69 @@ error: large size difference between variants --> $DIR/large_enum_variant.rs:16:5 | -16 | B([i32; 8000]), +LL | B([i32; 8000]), | ^^^^^^^^^^^^^^ | = note: `-D clippy::large-enum-variant` implied by `-D warnings` help: consider boxing the large fields to reduce the total size of the enum | -16 | B(Box<[i32; 8000]>), +LL | B(Box<[i32; 8000]>), | ^^^^^^^^^^^^^^^^ error: large size difference between variants --> $DIR/large_enum_variant.rs:27:5 | -27 | C(T, [i32; 8000]), +LL | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum --> $DIR/large_enum_variant.rs:27:5 | -27 | C(T, [i32; 8000]), +LL | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ error: large size difference between variants --> $DIR/large_enum_variant.rs:40:5 | -40 | ContainingLargeEnum(LargeEnum), +LL | ContainingLargeEnum(LargeEnum), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -40 | ContainingLargeEnum(Box), +LL | ContainingLargeEnum(Box), | ^^^^^^^^^^^^^^ error: large size difference between variants --> $DIR/large_enum_variant.rs:43:5 | -43 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum --> $DIR/large_enum_variant.rs:43:5 | -43 | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants --> $DIR/large_enum_variant.rs:50:5 | -50 | StructLikeLarge { x: [i32; 8000], y: i32 }, +LL | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum --> $DIR/large_enum_variant.rs:50:5 | -50 | StructLikeLarge { x: [i32; 8000], y: i32 }, +LL | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants --> $DIR/large_enum_variant.rs:55:5 | -55 | StructLikeLarge2 { x: [i32; 8000] }, +LL | StructLikeLarge2 { x: [i32; 8000] }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum | -55 | StructLikeLarge2 { x: Box<[i32; 8000]> }, +LL | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index bc5cd0e595b..f5f19e128b7 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,11 +1,11 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method --> $DIR/len_zero.rs:15:1 | -15 | / impl PubOne { -16 | | pub fn len(self: &Self) -> isize { -17 | | 1 -18 | | } -19 | | } +LL | / impl PubOne { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +LL | | } | |_^ | = note: `-D clippy::len-without-is-empty` implied by `-D warnings` @@ -13,128 +13,128 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` m error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method --> $DIR/len_zero.rs:64:1 | -64 | / pub trait PubTraitsToo { -65 | | fn len(self: &Self) -> isize; -66 | | } +LL | / pub trait PubTraitsToo { +LL | | fn len(self: &Self) -> isize; +LL | | } | |_^ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:98:1 - | -98 | / impl HasIsEmpty { -99 | | pub fn len(self: &Self) -> isize { -100 | | 1 -101 | | } -... | -105 | | } -106 | | } - | |_^ + --> $DIR/len_zero.rs:98:1 + | +LL | / impl HasIsEmpty { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +... | +LL | | } +LL | | } + | |_^ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:127:1 - | -127 | / impl HasWrongIsEmpty { -128 | | pub fn len(self: &Self) -> isize { -129 | | 1 -130 | | } -... | -134 | | } -135 | | } - | |_^ + --> $DIR/len_zero.rs:127:1 + | +LL | / impl HasWrongIsEmpty { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +... | +LL | | } +LL | | } + | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:148:8 - | -148 | if x.len() == 0 { - | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` - | - = note: `-D clippy::len-zero` implied by `-D warnings` + --> $DIR/len_zero.rs:148:8 + | +LL | if x.len() == 0 { + | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` + | + = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:152:8 - | -152 | if "".len() == 0 {} - | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` + --> $DIR/len_zero.rs:152:8 + | +LL | if "".len() == 0 {} + | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:167:8 - | -167 | if has_is_empty.len() == 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + --> $DIR/len_zero.rs:167:8 + | +LL | if has_is_empty.len() == 0 { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:170:8 - | -170 | if has_is_empty.len() != 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:170:8 + | +LL | if has_is_empty.len() != 0 { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:173:8 - | -173 | if has_is_empty.len() > 0 { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:173:8 + | +LL | if has_is_empty.len() > 0 { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:176:8 - | -176 | if has_is_empty.len() < 1 { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + --> $DIR/len_zero.rs:176:8 + | +LL | if has_is_empty.len() < 1 { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:179:8 - | -179 | if has_is_empty.len() >= 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:179:8 + | +LL | if has_is_empty.len() >= 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:190:8 - | -190 | if 0 == has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + --> $DIR/len_zero.rs:190:8 + | +LL | if 0 == has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:193:8 - | -193 | if 0 != has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:193:8 + | +LL | if 0 != has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:196:8 - | -196 | if 0 < has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:196:8 + | +LL | if 0 < has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:199:8 - | -199 | if 1 <= has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + --> $DIR/len_zero.rs:199:8 + | +LL | if 1 <= has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:202:8 - | -202 | if 1 > has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + --> $DIR/len_zero.rs:202:8 + | +LL | if 1 > has_is_empty.len() { + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:216:8 - | -216 | if with_is_empty.len() == 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` + --> $DIR/len_zero.rs:216:8 + | +LL | if with_is_empty.len() == 0 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:229:8 - | -229 | if b.len() != 0 {} - | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` + --> $DIR/len_zero.rs:229:8 + | +LL | if b.len() != 0 {} + | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:235:1 - | -235 | / pub trait DependsOnFoo: Foo { -236 | | fn len(&mut self) -> usize; -237 | | } - | |_^ + --> $DIR/len_zero.rs:235:1 + | +LL | / pub trait DependsOnFoo: Foo { +LL | | fn len(&mut self) -> usize; +LL | | } + | |_^ error: aborting due to 19 previous errors diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 91acf6dcb30..7883a713c05 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,10 +1,10 @@ error: `if _ { .. } else { .. }` is an expression --> $DIR/let_if_seq.rs:72:5 | -72 | / let mut foo = 0; -73 | | if f() { -74 | | foo = 42; -75 | | } +LL | / let mut foo = 0; +LL | | if f() { +LL | | foo = 42; +LL | | } | |_____^ help: it is more idiomatic to write: `let foo = if f() { 42 } else { 0 };` | = note: `-D clippy::useless-let-if-seq` implied by `-D warnings` @@ -13,13 +13,13 @@ error: `if _ { .. } else { .. }` is an expression error: `if _ { .. } else { .. }` is an expression --> $DIR/let_if_seq.rs:77:5 | -77 | / let mut bar = 0; -78 | | if f() { -79 | | f(); -80 | | bar = 42; -81 | | } else { -82 | | f(); -83 | | } +LL | / let mut bar = 0; +LL | | if f() { +LL | | f(); +LL | | bar = 42; +LL | | } else { +LL | | f(); +LL | | } | |_____^ help: it is more idiomatic to write: `let bar = if f() { ..; 42 } else { ..; 0 };` | = note: you might not need `mut` at all @@ -27,24 +27,24 @@ error: `if _ { .. } else { .. }` is an expression error: `if _ { .. } else { .. }` is an expression --> $DIR/let_if_seq.rs:85:5 | -85 | / let quz; -86 | | if f() { -87 | | quz = 42; -88 | | } else { -89 | | quz = 0; -90 | | } +LL | / let quz; +LL | | if f() { +LL | | quz = 42; +LL | | } else { +LL | | quz = 0; +LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:114:5 - | -114 | / let mut baz = 0; -115 | | if f() { -116 | | baz = 42; -117 | | } - | |_____^ help: it is more idiomatic to write: `let baz = if f() { 42 } else { 0 };` - | - = note: you might not need `mut` at all + --> $DIR/let_if_seq.rs:114:5 + | +LL | / let mut baz = 0; +LL | | if f() { +LL | | baz = 42; +LL | | } + | |_____^ help: it is more idiomatic to write: `let baz = if f() { 42 } else { 0 };` + | + = note: you might not need `mut` at all error: aborting due to 4 previous errors diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index 894c15c2d6d..c53d5cfb886 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -1,26 +1,26 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. --> $DIR/let_return.rs:16:5 | -16 | x +LL | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned --> $DIR/let_return.rs:15:13 | -15 | let x = 5; +LL | let x = 5; | ^ error: returning the result of a let binding from a block. Consider returning the expression directly. --> $DIR/let_return.rs:22:9 | -22 | x +LL | x | ^ | note: this expression can be directly returned --> $DIR/let_return.rs:21:17 | -21 | let x = 5; +LL | let x = 5; | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index a8771dd5f47..8929844180a 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -1,7 +1,7 @@ error: this let-binding has unit value. Consider omitting `let _x =` --> $DIR/let_unit.rs:20:5 | -20 | let _x = println!("x"); +LL | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::let-unit-value` implied by `-D warnings` @@ -9,7 +9,7 @@ error: this let-binding has unit value. Consider omitting `let _x =` error: this let-binding has unit value. Consider omitting `let _a =` --> $DIR/let_unit.rs:24:9 | -24 | let _a = (); +LL | let _a = (); | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 5bddf5aa746..abd11907b6d 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -1,7 +1,7 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:13:1 | -13 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} +LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` @@ -9,114 +9,114 @@ error: explicit lifetimes given in parameter types where they could be elided (o error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:15:1 | -15 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} +LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:23:1 | -23 | / fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { -24 | | x -25 | | } +LL | / fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { +LL | | x +LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:47:1 | -47 | / fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { -48 | | Ok(x) -49 | | } +LL | / fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { +LL | | Ok(x) +LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:52:1 | -52 | / fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> -53 | | where -54 | | T: Copy, -55 | | { -56 | | Ok(x) -57 | | } +LL | / fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> +LL | | where +LL | | T: Copy, +LL | | { +LL | | Ok(x) +LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:63:1 | -63 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} +LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/lifetimes.rs:84:1 | -84 | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -85 | | where -86 | | for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, -87 | | { -88 | | unreachable!() -89 | | } +LL | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +LL | | where +LL | | for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, +LL | | { +LL | | unreachable!() +LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:117:5 - | -117 | / fn self_and_out<'s>(&'s self) -> &'s u8 { -118 | | &self.x -119 | | } - | |_____^ + --> $DIR/lifetimes.rs:117:5 + | +LL | / fn self_and_out<'s>(&'s self) -> &'s u8 { +LL | | &self.x +LL | | } + | |_____^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:125:5 - | -125 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/lifetimes.rs:125:5 + | +LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:141:1 - | -141 | / fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { -142 | | unimplemented!() -143 | | } - | |_^ + --> $DIR/lifetimes.rs:141:1 + | +LL | / fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { +LL | | unimplemented!() +LL | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:171:1 - | -171 | / fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { -172 | | unimplemented!() -173 | | } - | |_^ + --> $DIR/lifetimes.rs:171:1 + | +LL | / fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { +LL | | unimplemented!() +LL | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:177:1 - | -177 | / fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { -178 | | unimplemented!() -179 | | } - | |_^ + --> $DIR/lifetimes.rs:177:1 + | +LL | / fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { +LL | | unimplemented!() +LL | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:196:1 - | -196 | / fn named_input_elided_output<'a>(_arg: &'a str) -> &str { -197 | | unimplemented!() -198 | | } - | |_^ + --> $DIR/lifetimes.rs:196:1 + | +LL | / fn named_input_elided_output<'a>(_arg: &'a str) -> &str { +LL | | unimplemented!() +LL | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:204:1 - | -204 | / fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { -205 | | unimplemented!() -206 | | } - | |_^ + --> $DIR/lifetimes.rs:204:1 + | +LL | / fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { +LL | | unimplemented!() +LL | | } + | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:241:1 - | -241 | / fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { -242 | | unimplemented!() -243 | | } - | |_^ + --> $DIR/lifetimes.rs:241:1 + | +LL | / fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { +LL | | unimplemented!() +LL | | } + | |_^ error: aborting due to 15 previous errors diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr index d0d65df21f0..9d0b0d62789 100644 --- a/tests/ui/lint_without_lint_pass.stderr +++ b/tests/ui/lint_without_lint_pass.stderr @@ -1,17 +1,17 @@ error: the lint `TEST_LINT` is not added to any `LintPass` --> $DIR/lint_without_lint_pass.rs:11:1 | -11 | / declare_clippy_lint! { -12 | | pub TEST_LINT, -13 | | correctness, -14 | | "" -15 | | } +LL | / declare_clippy_lint! { +LL | | pub TEST_LINT, +LL | | correctness, +LL | | "" +LL | | } | |_^ | note: lint level defined here --> $DIR/lint_without_lint_pass.rs:1:9 | -1 | #![deny(clippy::internal)] +LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: #[deny(clippy::lint_without_lint_pass)] implied by #[deny(clippy::internal)] = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index a9d49ff394e..6ceb25fd612 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,7 +1,7 @@ error: inconsistent casing in hexadecimal literal --> $DIR/literals.rs:22:17 | -22 | let fail1 = 0xabCD; +LL | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` @@ -9,19 +9,19 @@ error: inconsistent casing in hexadecimal literal error: inconsistent casing in hexadecimal literal --> $DIR/literals.rs:23:17 | -23 | let fail2 = 0xabCD_u32; +LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal --> $DIR/literals.rs:24:17 | -24 | let fail2 = 0xabCD_isize; +LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore --> $DIR/literals.rs:25:27 | -25 | let fail_multi_zero = 000_123usize; +LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` @@ -29,67 +29,67 @@ error: integer type suffix should be separated by an underscore error: this is a decimal constant --> $DIR/literals.rs:25:27 | -25 | let fail_multi_zero = 000_123usize; +LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ | = note: `-D clippy::zero-prefixed-literal` implied by `-D warnings` help: if you mean to use a decimal constant, remove the `0` to remove confusion | -25 | let fail_multi_zero = 123usize; +LL | let fail_multi_zero = 123usize; | ^^^^^^^^ help: if you mean to use an octal constant, use `0o` | -25 | let fail_multi_zero = 0o123usize; +LL | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore --> $DIR/literals.rs:30:17 | -30 | let fail3 = 1234i32; +LL | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore --> $DIR/literals.rs:31:17 | -31 | let fail4 = 1234u32; +LL | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore --> $DIR/literals.rs:32:17 | -32 | let fail5 = 1234isize; +LL | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore --> $DIR/literals.rs:33:17 | -33 | let fail6 = 1234usize; +LL | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore --> $DIR/literals.rs:34:17 | -34 | let fail7 = 1.5f32; +LL | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant --> $DIR/literals.rs:38:17 | -38 | let fail8 = 0123; +LL | let fail8 = 0123; | ^^^^ help: if you mean to use a decimal constant, remove the `0` to remove confusion | -38 | let fail8 = 123; +LL | let fail8 = 123; | ^^^ help: if you mean to use an octal constant, use `0o` | -38 | let fail8 = 0o123; +LL | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators --> $DIR/literals.rs:49:17 | -49 | let fail9 = 0xabcdef; +LL | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` @@ -97,25 +97,25 @@ error: long literal lacking separators error: long literal lacking separators --> $DIR/literals.rs:50:18 | -50 | let fail10 = 0xBAFEBAFE; +LL | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators --> $DIR/literals.rs:51:18 | -51 | let fail11 = 0xabcdeff; +LL | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators --> $DIR/literals.rs:52:18 | -52 | let fail12 = 0xabcabcabcabcabcabc; +LL | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller --> $DIR/literals.rs:53:18 | -53 | let fail13 = 0x1_23456_78901_usize; +LL | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` @@ -123,7 +123,7 @@ error: digit groups should be smaller error: mistyped literal suffix --> $DIR/literals.rs:55:18 | -55 | let fail14 = 2_32; +LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` | = note: #[deny(clippy::mistyped_literal_suffixes)] on by default @@ -131,25 +131,25 @@ error: mistyped literal suffix error: mistyped literal suffix --> $DIR/literals.rs:56:18 | -56 | let fail15 = 4_64; +LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix --> $DIR/literals.rs:57:18 | -57 | let fail16 = 7_8; +LL | let fail16 = 7_8; | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix --> $DIR/literals.rs:58:18 | -58 | let fail17 = 23_16; +LL | let fail17 = 23_16; | ^^^^^ help: did you mean to write: `23_i16` error: digits grouped inconsistently by underscores --> $DIR/literals.rs:60:18 | -60 | let fail19 = 12_3456_21; +LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` @@ -157,61 +157,61 @@ error: digits grouped inconsistently by underscores error: mistyped literal suffix --> $DIR/literals.rs:61:18 | -61 | let fail20 = 2__8; +LL | let fail20 = 2__8; | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix --> $DIR/literals.rs:62:18 | -62 | let fail21 = 4___16; +LL | let fail21 = 4___16; | ^^^^^^ help: did you mean to write: `4_i16` error: digits grouped inconsistently by underscores --> $DIR/literals.rs:63:18 | -63 | let fail22 = 3__4___23; +LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores --> $DIR/literals.rs:64:18 | -64 | let fail23 = 3__16___23; +LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: mistyped literal suffix --> $DIR/literals.rs:66:18 | -66 | let fail24 = 12.34_64; +LL | let fail24 = 12.34_64; | ^^^^^^^^ help: did you mean to write: `12.34_f64` error: mistyped literal suffix --> $DIR/literals.rs:67:18 | -67 | let fail25 = 1E2_32; +LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix --> $DIR/literals.rs:68:18 | -68 | let fail26 = 43E7_64; +LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix --> $DIR/literals.rs:69:18 | -69 | let fail27 = 243E17_32; +LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix --> $DIR/literals.rs:70:18 | -70 | let fail28 = 241251235E723_64; +LL | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix --> $DIR/literals.rs:71:18 | -71 | let fail29 = 42279.911_32; +LL | let fail29 = 42279.911_32; | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` error: aborting due to 31 previous errors diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 603819de16e..6253ae2150c 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,7 +1,7 @@ error: You are using an explicit closure for cloning elements --> $DIR/map_clone.rs:14:22 | -14 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); +LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` | = note: `-D clippy::map-clone` implied by `-D warnings` @@ -9,13 +9,13 @@ error: You are using an explicit closure for cloning elements error: You are using an explicit closure for cloning elements --> $DIR/map_clone.rs:15:26 | -15 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); +LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements --> $DIR/map_clone.rs:16:23 | -16 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); +LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` error: aborting due to 3 previous errors diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index 488797173f6..931ef9b6248 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,7 +1,7 @@ error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` --> $DIR/map_flatten.rs:14:21 | -14 | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` | = note: `-D clippy::map-flatten` implied by `-D warnings` diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index a073f995498..78711c4ba4b 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -1,7 +1,7 @@ error: this boolean expression can be simplified --> $DIR/match_bool.rs:38:11 | -38 | match test && test { +LL | match test && test { | ^^^^^^^^^^^^ help: try: `test` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` @@ -9,10 +9,10 @@ error: this boolean expression can be simplified error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:13:5 | -13 | / match test { -14 | | true => 0, -15 | | false => 42, -16 | | }; +LL | / match test { +LL | | true => 0, +LL | | false => 42, +LL | | }; | |_____^ help: consider using an if/else expression: `if test { 0 } else { 42 }` | = note: `-D clippy::match-bool` implied by `-D warnings` @@ -20,67 +20,67 @@ error: you seem to be trying to match on a boolean expression error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:19:5 | -19 | / match option == 1 { -20 | | true => 1, -21 | | false => 0, -22 | | }; +LL | / match option == 1 { +LL | | true => 1, +LL | | false => 0, +LL | | }; | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:24:5 | -24 | / match test { -25 | | true => (), -26 | | false => { -27 | | println!("Noooo!"); -28 | | }, -29 | | }; +LL | / match test { +LL | | true => (), +LL | | false => { +LL | | println!("Noooo!"); +LL | | }, +LL | | }; | |_____^ help: consider using an if/else expression | -24 | if !test { -25 | println!("Noooo!"); -26 | }; +LL | if !test { +LL | println!("Noooo!"); +LL | }; | error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:31:5 | -31 | / match test { -32 | | false => { -33 | | println!("Noooo!"); -34 | | }, -35 | | _ => (), -36 | | }; +LL | / match test { +LL | | false => { +LL | | println!("Noooo!"); +LL | | }, +LL | | _ => (), +LL | | }; | |_____^ help: consider using an if/else expression | -31 | if !test { -32 | println!("Noooo!"); -33 | }; +LL | if !test { +LL | println!("Noooo!"); +LL | }; | error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:38:5 | -38 | / match test && test { -39 | | false => { -40 | | println!("Noooo!"); -41 | | }, -42 | | _ => (), -43 | | }; +LL | / match test && test { +LL | | false => { +LL | | println!("Noooo!"); +LL | | }, +LL | | _ => (), +LL | | }; | |_____^ help: consider using an if/else expression | -38 | if !(test && test) { -39 | println!("Noooo!"); -40 | }; +LL | if !(test && test) { +LL | println!("Noooo!"); +LL | }; | error: equal expressions as operands to `&&` --> $DIR/match_bool.rs:38:11 | -38 | match test && test { +LL | match test && test { | ^^^^^^^^^^^^ | = note: #[deny(clippy::eq_op)] on by default @@ -88,21 +88,21 @@ error: equal expressions as operands to `&&` error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:45:5 | -45 | / match test { -46 | | false => { -47 | | println!("Noooo!"); -48 | | }, +LL | / match test { +LL | | false => { +LL | | println!("Noooo!"); +LL | | }, ... | -51 | | }, -52 | | }; +LL | | }, +LL | | }; | |_____^ help: consider using an if/else expression | -45 | if test { -46 | println!("Yes!"); -47 | } else { -48 | println!("Noooo!"); -49 | }; +LL | if test { +LL | println!("Yes!"); +LL | } else { +LL | println!("Noooo!"); +LL | }; | error: aborting due to 8 previous errors diff --git a/tests/ui/match_overlapping_arm.stderr b/tests/ui/match_overlapping_arm.stderr index ef8fc08f95b..3e978df842e 100644 --- a/tests/ui/match_overlapping_arm.stderr +++ b/tests/ui/match_overlapping_arm.stderr @@ -1,62 +1,62 @@ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:20:9 | -20 | 0...10 => println!("0 ... 10"), +LL | 0...10 => println!("0 ... 10"), | ^^^^^^ | = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this --> $DIR/match_overlapping_arm.rs:21:9 | -21 | 0...11 => println!("0 ... 11"), +LL | 0...11 => println!("0 ... 11"), | ^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:26:9 | -26 | 0...5 => println!("0 ... 5"), +LL | 0...5 => println!("0 ... 5"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:28:9 | -28 | FOO...11 => println!("0 ... 11"), +LL | FOO...11 => println!("0 ... 11"), | ^^^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:34:9 | -34 | 0...5 => println!("0 ... 5"), +LL | 0...5 => println!("0 ... 5"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:33:9 | -33 | 2 => println!("2"), +LL | 2 => println!("2"), | ^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:40:9 | -40 | 0...2 => println!("0 ... 2"), +LL | 0...2 => println!("0 ... 2"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:39:9 | -39 | 2 => println!("2"), +LL | 2 => println!("2"), | ^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:63:9 | -63 | 0..11 => println!("0 .. 11"), +LL | 0..11 => println!("0 .. 11"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:64:9 | -64 | 0...11 => println!("0 ... 11"), +LL | 0...11 => println!("0 ... 11"), | ^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 3ed70168c6e..06ba6224855 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,77 +1,77 @@ error: you don't need to add `&` to all patterns --> $DIR/matches.rs:20:9 | -20 | / match v { -21 | | &Some(v) => println!("{:?}", v), -22 | | &None => println!("none"), -23 | | } +LL | / match v { +LL | | &Some(v) => println!("{:?}", v), +LL | | &None => println!("none"), +LL | | } | |_________^ | = note: `-D clippy::match-ref-pats` implied by `-D warnings` help: instead of prefixing all patterns with `&`, you can dereference the expression | -20 | match *v { -21 | Some(v) => println!("{:?}", v), -22 | None => println!("none"), +LL | match *v { +LL | Some(v) => println!("{:?}", v), +LL | None => println!("none"), | error: you don't need to add `&` to all patterns --> $DIR/matches.rs:31:5 | -31 | / match tup { -32 | | &(v, 1) => println!("{}", v), -33 | | _ => println!("none"), -34 | | } +LL | / match tup { +LL | | &(v, 1) => println!("{}", v), +LL | | _ => println!("none"), +LL | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -31 | match *tup { -32 | (v, 1) => println!("{}", v), +LL | match *tup { +LL | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns --> $DIR/matches.rs:37:5 | -37 | / match &w { -38 | | &Some(v) => println!("{:?}", v), -39 | | &None => println!("none"), -40 | | } +LL | / match &w { +LL | | &Some(v) => println!("{:?}", v), +LL | | &None => println!("none"), +LL | | } | |_____^ help: try | -37 | match w { -38 | Some(v) => println!("{:?}", v), -39 | None => println!("none"), +LL | match w { +LL | Some(v) => println!("{:?}", v), +LL | None => println!("none"), | error: you don't need to add `&` to all patterns --> $DIR/matches.rs:48:5 | -48 | / if let &None = a { -49 | | println!("none"); -50 | | } +LL | / if let &None = a { +LL | | println!("none"); +LL | | } | |_____^ help: instead of prefixing all patterns with `&`, you can dereference the expression | -48 | if let None = *a { +LL | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns --> $DIR/matches.rs:53:5 | -53 | / if let &None = &b { -54 | | println!("none"); -55 | | } +LL | / if let &None = &b { +LL | | println!("none"); +LL | | } | |_____^ help: try | -53 | if let None = b { +LL | if let None = b { | ^^^^ ^ error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:64:9 | -64 | Err(_) => panic!("err"), +LL | Err(_) => panic!("err"), | ^^^^^^ | = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` @@ -80,26 +80,26 @@ error: Err(_) will match all errors, maybe not a good idea error: this `match` has identical arm bodies --> $DIR/matches.rs:63:18 | -63 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this --> $DIR/matches.rs:62:18 | -62 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:62:18 | -62 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:70:9 | -70 | Err(_) => panic!(), +LL | Err(_) => panic!(), | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro @@ -107,25 +107,25 @@ error: Err(_) will match all errors, maybe not a good idea error: this `match` has identical arm bodies --> $DIR/matches.rs:69:18 | -69 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this --> $DIR/matches.rs:68:18 | -68 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:68:18 | -68 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea --> $DIR/matches.rs:76:9 | -76 | Err(_) => { +LL | Err(_) => { | ^^^^^^ | = note: to remove this warning, match each error separately or use unreachable macro @@ -133,150 +133,150 @@ error: Err(_) will match all errors, maybe not a good idea error: this `match` has identical arm bodies --> $DIR/matches.rs:75:18 | -75 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this --> $DIR/matches.rs:74:18 | -74 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:74:18 | -74 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:84:18 | -84 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this --> $DIR/matches.rs:83:18 | -83 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:83:18 | -83 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:91:18 | -91 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this --> $DIR/matches.rs:90:18 | -90 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:90:18 | -90 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/matches.rs:97:18 | -97 | Ok(_) => println!("ok"), +LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this --> $DIR/matches.rs:96:18 | -96 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` --> $DIR/matches.rs:96:18 | -96 | Ok(3) => println!("ok"), +LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:103:18 - | -103 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:103:18 + | +LL | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:102:18 - | -102 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:102:18 + | +LL | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:102:18 - | -102 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:102:18 + | +LL | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:126:29 - | -126 | (Ok(_), Some(x)) => println!("ok {}", x), - | ^^^^^^^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:126:29 + | +LL | (Ok(_), Some(x)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:125:29 - | -125 | (Ok(x), Some(_)) => println!("ok {}", x), - | ^^^^^^^^^^^^^^^^^^^^ + --> $DIR/matches.rs:125:29 + | +LL | (Ok(x), Some(_)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:125:29 - | -125 | (Ok(x), Some(_)) => println!("ok {}", x), - | ^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:125:29 + | +LL | (Ok(x), Some(_)) => println!("ok {}", x), + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:141:18 - | -141 | Ok(_) => println!("ok"), - | ^^^^^^^^^^^^^^ - | + --> $DIR/matches.rs:141:18 + | +LL | Ok(_) => println!("ok"), + | ^^^^^^^^^^^^^^ + | note: same as this - --> $DIR/matches.rs:140:18 - | -140 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ + --> $DIR/matches.rs:140:18 + | +LL | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:140:18 - | -140 | Ok(3) => println!("ok"), - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/matches.rs:140:18 + | +LL | Ok(3) => println!("ok"), + | ^^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:150:33 - | -150 | let borrowed: Option<&()> = match owned { - | _________________________________^ -151 | | None => None, -152 | | Some(ref v) => Some(v), -153 | | }; - | |_____^ help: try this: `owned.as_ref()` - | - = note: `-D clippy::match-as-ref` implied by `-D warnings` + --> $DIR/matches.rs:150:33 + | +LL | let borrowed: Option<&()> = match owned { + | _________________________________^ +LL | | None => None, +LL | | Some(ref v) => Some(v), +LL | | }; + | |_____^ help: try this: `owned.as_ref()` + | + = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:156:39 - | -156 | let borrow_mut: Option<&mut ()> = match mut_owned { - | _______________________________________^ -157 | | None => None, -158 | | Some(ref mut v) => Some(v), -159 | | }; - | |_____^ help: try this: `mut_owned.as_mut()` + --> $DIR/matches.rs:156:39 + | +LL | let borrow_mut: Option<&mut ()> = match mut_owned { + | _______________________________________^ +LL | | None => None, +LL | | Some(ref mut v) => Some(v), +LL | | }; + | |_____^ help: try this: `mut_owned.as_mut()` error: aborting due to 19 previous errors diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index a00f7ab30e1..c445b96a90f 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -1,19 +1,19 @@ error: calling `mem::discriminant` on non-enum type `&str` --> $DIR/mem_discriminant.rs:23:5 | -23 | mem::discriminant(&"hello"); +LL | mem::discriminant(&"hello"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/mem_discriminant.rs:10:9 | -10 | #![deny(clippy::mem_discriminant_non_enum)] +LL | #![deny(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` --> $DIR/mem_discriminant.rs:24:5 | -24 | mem::discriminant(&&Some(2)); +LL | mem::discriminant(&&Some(2)); | ^^^^^^^^^^^^^^^^^^---------^ | | | help: try dereferencing: `&Some(2)` @@ -21,7 +21,7 @@ error: calling `mem::discriminant` on non-enum type `&std::option::Option` error: calling `mem::discriminant` on non-enum type `&std::option::Option` --> $DIR/mem_discriminant.rs:25:5 | -25 | mem::discriminant(&&None::); +LL | mem::discriminant(&&None::); | ^^^^^^^^^^^^^^^^^^------------^ | | | help: try dereferencing: `&None::` @@ -29,7 +29,7 @@ error: calling `mem::discriminant` on non-enum type `&std::option::Option` error: calling `mem::discriminant` on non-enum type `&Foo` --> $DIR/mem_discriminant.rs:26:5 | -26 | mem::discriminant(&&Foo::One(5)); +LL | mem::discriminant(&&Foo::One(5)); | ^^^^^^^^^^^^^^^^^^-------------^ | | | help: try dereferencing: `&Foo::One(5)` @@ -37,7 +37,7 @@ error: calling `mem::discriminant` on non-enum type `&Foo` error: calling `mem::discriminant` on non-enum type `&Foo` --> $DIR/mem_discriminant.rs:27:5 | -27 | mem::discriminant(&&Foo::Two(5)); +LL | mem::discriminant(&&Foo::Two(5)); | ^^^^^^^^^^^^^^^^^^-------------^ | | | help: try dereferencing: `&Foo::Two(5)` @@ -45,13 +45,13 @@ error: calling `mem::discriminant` on non-enum type `&Foo` error: calling `mem::discriminant` on non-enum type `A` --> $DIR/mem_discriminant.rs:28:5 | -28 | mem::discriminant(&A(Foo::One(0))); +LL | mem::discriminant(&A(Foo::One(0))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` --> $DIR/mem_discriminant.rs:32:5 | -32 | mem::discriminant(&ro); +LL | mem::discriminant(&ro); | ^^^^^^^^^^^^^^^^^^---^ | | | help: try dereferencing: `ro` @@ -59,7 +59,7 @@ error: calling `mem::discriminant` on non-enum type `&std::option::Option` error: calling `mem::discriminant` on non-enum type `&std::option::Option` --> $DIR/mem_discriminant.rs:33:5 | -33 | mem::discriminant(rro); +LL | mem::discriminant(rro); | ^^^^^^^^^^^^^^^^^^---^ | | | help: try dereferencing: `*rro` @@ -67,7 +67,7 @@ error: calling `mem::discriminant` on non-enum type `&std::option::Option` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` --> $DIR/mem_discriminant.rs:34:5 | -34 | mem::discriminant(&rro); +LL | mem::discriminant(&rro); | ^^^^^^^^^^^^^^^^^^----^ | | | help: try dereferencing: `*rro` @@ -75,10 +75,10 @@ error: calling `mem::discriminant` on non-enum type `&&std::option::Option` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` --> $DIR/mem_discriminant.rs:38:13 | -38 | mem::discriminant($param) +LL | mem::discriminant($param) | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... -42 | mem_discriminant_but_in_a_macro!(&rro); +LL | mem_discriminant_but_in_a_macro!(&rro); | --------------------------------------- | | | | | help: try dereferencing: `*rro` @@ -87,7 +87,7 @@ error: calling `mem::discriminant` on non-enum type `&&std::option::Option` error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` --> $DIR/mem_discriminant.rs:45:5 | -45 | mem::discriminant(&rrrrro); +LL | mem::discriminant(&rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ | | | help: try dereferencing: `****rrrrro` @@ -95,7 +95,7 @@ error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` --> $DIR/mem_discriminant.rs:46:5 | -46 | mem::discriminant(*rrrrro); +LL | mem::discriminant(*rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ | | | help: try dereferencing: `****rrrrro` diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 479cd4934ab..292437d0019 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -1,7 +1,7 @@ error: usage of mem::forget on Drop type --> $DIR/mem_forget.rs:23:5 | -23 | memstuff::forget(six); +LL | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::mem-forget` implied by `-D warnings` @@ -9,13 +9,13 @@ error: usage of mem::forget on Drop type error: usage of mem::forget on Drop type --> $DIR/mem_forget.rs:26:5 | -26 | std::mem::forget(seven); +LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of mem::forget on Drop type --> $DIR/mem_forget.rs:29:5 | -29 | forgetSomething(eight); +LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 06d8f5f74c0..9092fa2ea14 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,7 +1,7 @@ error: replacing an `Option` with `None` --> $DIR/mem_replace.rs:16:13 | -16 | let _ = mem::replace(&mut an_option, None); +LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` | = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` @@ -9,7 +9,7 @@ error: replacing an `Option` with `None` error: replacing an `Option` with `None` --> $DIR/mem_replace.rs:18:13 | -18 | let _ = mem::replace(an_option, None); +LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: aborting due to 2 previous errors diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 950c49003b6..4f445c924d2 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,7 +1,7 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name --> $DIR/methods.rs:38:5 | -38 | pub fn add(self, other: T) -> T { self } +LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::should-implement-trait` implied by `-D warnings` @@ -9,7 +9,7 @@ error: defining a method called `add` on this type; consider implementing the `s error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/methods.rs:49:17 | -49 | fn into_u16(&self) -> u16 { 0 } +LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` @@ -17,389 +17,389 @@ error: methods called `into_*` usually take self by value; consider choosing a l error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name --> $DIR/methods.rs:51:21 | -51 | fn to_something(self) -> u32 { 0 } +LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name --> $DIR/methods.rs:53:12 | -53 | fn new(self) -> Self { unimplemented!(); } +LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:121:13 - | -121 | let _ = opt.map(|x| x + 1) - | _____________^ -122 | | -123 | | .unwrap_or(0); // should lint even though this call is on a separate line - | |____________________________^ - | - = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` + --> $DIR/methods.rs:121:13 + | +LL | let _ = opt.map(|x| x + 1) + | _____________^ +LL | | +LL | | .unwrap_or(0); // should lint even though this call is on a separate line + | |____________________________^ + | + = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:125:13 - | -125 | let _ = opt.map(|x| { - | _____________^ -126 | | x + 1 -127 | | } -128 | | ).unwrap_or(0); - | |____________________________^ + --> $DIR/methods.rs:125:13 + | +LL | let _ = opt.map(|x| { + | _____________^ +LL | | x + 1 +LL | | } +LL | | ).unwrap_or(0); + | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:129:13 - | -129 | let _ = opt.map(|x| x + 1) - | _____________^ -130 | | .unwrap_or({ -131 | | 0 -132 | | }); - | |__________________^ + --> $DIR/methods.rs:129:13 + | +LL | let _ = opt.map(|x| x + 1) + | _____________^ +LL | | .unwrap_or({ +LL | | 0 +LL | | }); + | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:134:13 - | -134 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` + --> $DIR/methods.rs:134:13 + | +LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:136:13 - | -136 | let _ = opt.map(|x| { - | _____________^ -137 | | Some(x + 1) -138 | | } -139 | | ).unwrap_or(None); - | |_____________________^ + --> $DIR/methods.rs:136:13 + | +LL | let _ = opt.map(|x| { + | _____________^ +LL | | Some(x + 1) +LL | | } +LL | | ).unwrap_or(None); + | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:140:13 - | -140 | let _ = opt - | _____________^ -141 | | .map(|x| Some(x + 1)) -142 | | .unwrap_or(None); - | |________________________^ - | - = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` + --> $DIR/methods.rs:140:13 + | +LL | let _ = opt + | _____________^ +LL | | .map(|x| Some(x + 1)) +LL | | .unwrap_or(None); + | |________________________^ + | + = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:148:13 - | -148 | let _ = opt.map(|x| x + 1) - | _____________^ -149 | | -150 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line - | |____________________________________^ - | - = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` + --> $DIR/methods.rs:148:13 + | +LL | let _ = opt.map(|x| x + 1) + | _____________^ +LL | | +LL | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line + | |____________________________________^ + | + = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:152:13 - | -152 | let _ = opt.map(|x| { - | _____________^ -153 | | x + 1 -154 | | } -155 | | ).unwrap_or_else(|| 0); - | |____________________________________^ + --> $DIR/methods.rs:152:13 + | +LL | let _ = opt.map(|x| { + | _____________^ +LL | | x + 1 +LL | | } +LL | | ).unwrap_or_else(|| 0); + | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:156:13 - | -156 | let _ = opt.map(|x| x + 1) - | _____________^ -157 | | .unwrap_or_else(|| -158 | | 0 -159 | | ); - | |_________________^ + --> $DIR/methods.rs:156:13 + | +LL | let _ = opt.map(|x| x + 1) + | _____________^ +LL | | .unwrap_or_else(|| +LL | | 0 +LL | | ); + | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:165:13 - | -165 | let _ = opt.map_or(None, |x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` - | - = note: `-D clippy::option-map-or-none` implied by `-D warnings` + --> $DIR/methods.rs:165:13 + | +LL | let _ = opt.map_or(None, |x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` + | + = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:167:13 - | -167 | let _ = opt.map_or(None, |x| { - | _____________^ -168 | | Some(x + 1) -169 | | } -170 | | ); - | |_________________^ + --> $DIR/methods.rs:167:13 + | +LL | let _ = opt.map_or(None, |x| { + | _____________^ +LL | | Some(x + 1) +LL | | } +LL | | ); + | |_________________^ help: try using and_then instead - | -167 | let _ = opt.and_then(|x| { -168 | Some(x + 1) -169 | }); - | + | +LL | let _ = opt.and_then(|x| { +LL | Some(x + 1) +LL | }); + | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:180:13 - | -180 | let _ = res.map(|x| x + 1) - | _____________^ -181 | | -182 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - | |_____________________________________^ - | - = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + --> $DIR/methods.rs:180:13 + | +LL | let _ = res.map(|x| x + 1) + | _____________^ +LL | | +LL | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | |_____________________________________^ + | + = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:184:13 - | -184 | let _ = res.map(|x| { - | _____________^ -185 | | x + 1 -186 | | } -187 | | ).unwrap_or_else(|e| 0); - | |_____________________________________^ + --> $DIR/methods.rs:184:13 + | +LL | let _ = res.map(|x| { + | _____________^ +LL | | x + 1 +LL | | } +LL | | ).unwrap_or_else(|e| 0); + | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:188:13 - | -188 | let _ = res.map(|x| x + 1) - | _____________^ -189 | | .unwrap_or_else(|e| -190 | | 0 -191 | | ); - | |_________________^ + --> $DIR/methods.rs:188:13 + | +LL | let _ = res.map(|x| x + 1) + | _____________^ +LL | | .unwrap_or_else(|e| +LL | | 0 +LL | | ); + | |_________________^ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:251:13 - | -251 | let _ = v.iter().filter(|&x| *x < 0).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::filter-next` implied by `-D warnings` - = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` + --> $DIR/methods.rs:251:13 + | +LL | let _ = v.iter().filter(|&x| *x < 0).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::filter-next` implied by `-D warnings` + = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:254:13 - | -254 | let _ = v.iter().filter(|&x| { - | _____________^ -255 | | *x < 0 -256 | | } -257 | | ).next(); - | |___________________________^ + --> $DIR/methods.rs:254:13 + | +LL | let _ = v.iter().filter(|&x| { + | _____________^ +LL | | *x < 0 +LL | | } +LL | | ).next(); + | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:269:13 - | -269 | let _ = v.iter().find(|&x| *x < 0).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::search-is-some` implied by `-D warnings` - = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` + --> $DIR/methods.rs:269:13 + | +LL | let _ = v.iter().find(|&x| *x < 0).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::search-is-some` implied by `-D warnings` + = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:272:13 - | -272 | let _ = v.iter().find(|&x| { - | _____________^ -273 | | *x < 0 -274 | | } -275 | | ).is_some(); - | |______________________________^ + --> $DIR/methods.rs:272:13 + | +LL | let _ = v.iter().find(|&x| { + | _____________^ +LL | | *x < 0 +LL | | } +LL | | ).is_some(); + | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:278:13 - | -278 | let _ = v.iter().position(|&x| x < 0).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` + --> $DIR/methods.rs:278:13 + | +LL | let _ = v.iter().position(|&x| x < 0).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:281:13 - | -281 | let _ = v.iter().position(|&x| { - | _____________^ -282 | | x < 0 -283 | | } -284 | | ).is_some(); - | |______________________________^ + --> $DIR/methods.rs:281:13 + | +LL | let _ = v.iter().position(|&x| { + | _____________^ +LL | | x < 0 +LL | | } +LL | | ).is_some(); + | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:287:13 - | -287 | let _ = v.iter().rposition(|&x| x < 0).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` + --> $DIR/methods.rs:287:13 + | +LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:290:13 - | -290 | let _ = v.iter().rposition(|&x| { - | _____________^ -291 | | x < 0 -292 | | } -293 | | ).is_some(); - | |______________________________^ + --> $DIR/methods.rs:290:13 + | +LL | let _ = v.iter().rposition(|&x| { + | _____________^ +LL | | x < 0 +LL | | } +LL | | ).is_some(); + | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:325:22 - | -325 | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` - | - = note: `-D clippy::or-fun-call` implied by `-D warnings` + --> $DIR/methods.rs:325:22 + | +LL | with_constructor.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` + | + = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:328:5 - | -328 | with_new.unwrap_or(Vec::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` + --> $DIR/methods.rs:328:5 + | +LL | with_new.unwrap_or(Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:331:21 - | -331 | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` + --> $DIR/methods.rs:331:21 + | +LL | with_const_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:334:14 - | -334 | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` + --> $DIR/methods.rs:334:14 + | +LL | with_err.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:337:19 - | -337 | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` + --> $DIR/methods.rs:337:19 + | +LL | with_err_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:340:5 - | -340 | with_default_trait.unwrap_or(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` + --> $DIR/methods.rs:340:5 + | +LL | with_default_trait.unwrap_or(Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:343:5 - | -343 | with_default_type.unwrap_or(u64::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` + --> $DIR/methods.rs:343:5 + | +LL | with_default_type.unwrap_or(u64::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:346:14 - | -346 | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` + --> $DIR/methods.rs:346:14 + | +LL | with_vec.unwrap_or(vec![]); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:351:21 - | -351 | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` + --> $DIR/methods.rs:351:21 + | +LL | without_default.unwrap_or(Foo::new()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:354:19 - | -354 | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + --> $DIR/methods.rs:354:19 + | +LL | map.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:357:21 - | -357 | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + --> $DIR/methods.rs:357:21 + | +LL | btree.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:360:21 - | -360 | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` + --> $DIR/methods.rs:360:21 + | +LL | let _ = stringy.unwrap_or("".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:371:23 - | -371 | let bad_vec = some_vec.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-nth` implied by `-D warnings` + --> $DIR/methods.rs:371:23 + | +LL | let bad_vec = some_vec.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:372:26 - | -372 | let bad_slice = &some_vec[..].iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:372:26 + | +LL | let bad_slice = &some_vec[..].iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:373:31 - | -373 | let bad_boxed_slice = boxed_slice.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:373:31 + | +LL | let bad_boxed_slice = boxed_slice.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:374:29 - | -374 | let bad_vec_deque = some_vec_deque.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:374:29 + | +LL | let bad_vec_deque = some_vec_deque.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:379:23 - | -379 | let bad_vec = some_vec.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:379:23 + | +LL | let bad_vec = some_vec.iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:382:26 - | -382 | let bad_slice = &some_vec[..].iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:382:26 + | +LL | let bad_slice = &some_vec[..].iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:385:29 - | -385 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:385:29 + | +LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:397:13 - | -397 | let _ = some_vec.iter().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-skip-next` implied by `-D warnings` + --> $DIR/methods.rs:397:13 + | +LL | let _ = some_vec.iter().skip(42).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:398:13 - | -398 | let _ = some_vec.iter().cycle().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:398:13 + | +LL | let _ = some_vec.iter().cycle().skip(42).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:399:13 - | -399 | let _ = (1..10).skip(10).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:399:13 + | +LL | let _ = (1..10).skip(10).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:400:14 - | -400 | let _ = &some_vec[..].iter().skip(3).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/methods.rs:400:14 + | +LL | let _ = &some_vec[..].iter().skip(3).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:409:13 - | -409 | let _ = opt.unwrap(); - | ^^^^^^^^^^^^ - | - = note: `-D clippy::option-unwrap-used` implied by `-D warnings` + --> $DIR/methods.rs:409:13 + | +LL | let _ = opt.unwrap(); + | ^^^^^^^^^^^^ + | + = note: `-D clippy::option-unwrap-used` implied by `-D warnings` error: aborting due to 50 previous errors diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index 74a93e350de..a6ad34f02b8 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,7 +1,7 @@ error: this min/max combination leads to constant result --> $DIR/min_max.rs:21:5 | -21 | min(1, max(3, x)); +LL | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::min-max` implied by `-D warnings` @@ -9,37 +9,37 @@ error: this min/max combination leads to constant result error: this min/max combination leads to constant result --> $DIR/min_max.rs:22:5 | -22 | min(max(3, x), 1); +LL | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result --> $DIR/min_max.rs:23:5 | -23 | max(min(x, 1), 3); +LL | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result --> $DIR/min_max.rs:24:5 | -24 | max(3, min(x, 1)); +LL | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result --> $DIR/min_max.rs:26:5 | -26 | my_max(3, my_min(x, 1)); +LL | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result --> $DIR/min_max.rs:38:5 | -38 | min("Apple", max("Zoo", s)); +LL | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result --> $DIR/min_max.rs:39:5 | -39 | max(min(s, "Apple"), "Zoo"); +LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index b50305ab9ee..35c12786284 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -1,7 +1,7 @@ error: missing documentation for a type alias --> $DIR/missing-doc.rs:32:1 | -32 | type Typedef = String; +LL | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` @@ -9,250 +9,250 @@ error: missing documentation for a type alias error: missing documentation for a type alias --> $DIR/missing-doc.rs:33:1 | -33 | pub type PubTypedef = String; +LL | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct --> $DIR/missing-doc.rs:35:1 | -35 | / struct Foo { -36 | | a: isize, -37 | | b: isize, -38 | | } +LL | / struct Foo { +LL | | a: isize, +LL | | b: isize, +LL | | } | |_^ error: missing documentation for a struct field --> $DIR/missing-doc.rs:36:5 | -36 | a: isize, +LL | a: isize, | ^^^^^^^^ error: missing documentation for a struct field --> $DIR/missing-doc.rs:37:5 | -37 | b: isize, +LL | b: isize, | ^^^^^^^^ error: missing documentation for a struct --> $DIR/missing-doc.rs:40:1 | -40 | / pub struct PubFoo { -41 | | pub a: isize, -42 | | b: isize, -43 | | } +LL | / pub struct PubFoo { +LL | | pub a: isize, +LL | | b: isize, +LL | | } | |_^ error: missing documentation for a struct field --> $DIR/missing-doc.rs:41:5 | -41 | pub a: isize, +LL | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field --> $DIR/missing-doc.rs:42:5 | -42 | b: isize, +LL | b: isize, | ^^^^^^^^ error: missing documentation for a module --> $DIR/missing-doc.rs:51:1 | -51 | mod module_no_dox {} +LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module --> $DIR/missing-doc.rs:52:1 | -52 | pub mod pub_module_no_dox {} +LL | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function --> $DIR/missing-doc.rs:56:1 | -56 | pub fn foo2() {} +LL | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function --> $DIR/missing-doc.rs:57:1 | -57 | fn foo3() {} +LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for a trait --> $DIR/missing-doc.rs:75:1 | -75 | / pub trait C { -76 | | fn foo(&self); -77 | | fn foo_with_impl(&self) {} -78 | | } +LL | / pub trait C { +LL | | fn foo(&self); +LL | | fn foo_with_impl(&self) {} +LL | | } | |_^ error: missing documentation for a trait method --> $DIR/missing-doc.rs:76:5 | -76 | fn foo(&self); +LL | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for a trait method --> $DIR/missing-doc.rs:77:5 | -77 | fn foo_with_impl(&self) {} +LL | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type --> $DIR/missing-doc.rs:87:5 | -87 | type AssociatedType; +LL | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type --> $DIR/missing-doc.rs:88:5 | -88 | type AssociatedTypeDef = Self; +LL | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a method --> $DIR/missing-doc.rs:99:5 | -99 | pub fn foo() {} +LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:100:5 - | -100 | fn bar() {} - | ^^^^^^^^^^^ + --> $DIR/missing-doc.rs:100:5 + | +LL | fn bar() {} + | ^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:104:5 - | -104 | pub fn foo() {} - | ^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:104:5 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:107:5 - | -107 | fn foo2() {} - | ^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:107:5 + | +LL | fn foo2() {} + | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:134:1 - | -134 | / enum Baz { -135 | | BazA { a: isize, b: isize }, -136 | | BarB, -137 | | } - | |_^ + --> $DIR/missing-doc.rs:134:1 + | +LL | / enum Baz { +LL | | BazA { a: isize, b: isize }, +LL | | BarB, +LL | | } + | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:135:5 - | -135 | BazA { a: isize, b: isize }, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:135:5 + | +LL | BazA { a: isize, b: isize }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:135:12 - | -135 | BazA { a: isize, b: isize }, - | ^^^^^^^^ + --> $DIR/missing-doc.rs:135:12 + | +LL | BazA { a: isize, b: isize }, + | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:135:22 - | -135 | BazA { a: isize, b: isize }, - | ^^^^^^^^ + --> $DIR/missing-doc.rs:135:22 + | +LL | BazA { a: isize, b: isize }, + | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:136:5 - | -136 | BarB, - | ^^^^ + --> $DIR/missing-doc.rs:136:5 + | +LL | BarB, + | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:139:1 - | -139 | / pub enum PubBaz { -140 | | PubBazA { a: isize }, -141 | | } - | |_^ + --> $DIR/missing-doc.rs:139:1 + | +LL | / pub enum PubBaz { +LL | | PubBazA { a: isize }, +LL | | } + | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:140:5 - | -140 | PubBazA { a: isize }, - | ^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:140:5 + | +LL | PubBazA { a: isize }, + | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:140:15 - | -140 | PubBazA { a: isize }, - | ^^^^^^^^ + --> $DIR/missing-doc.rs:140:15 + | +LL | PubBazA { a: isize }, + | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:160:1 - | -160 | const FOO: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:160:1 + | +LL | const FOO: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:167:1 - | -167 | pub const FOO4: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:167:1 + | +LL | pub const FOO4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:169:1 - | -169 | static BAR: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:169:1 + | +LL | static BAR: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:176:1 - | -176 | pub static BAR4: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:176:1 + | +LL | pub static BAR4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:178:1 - | -178 | / mod internal_impl { -179 | | /// dox -180 | | pub fn documented() {} -181 | | pub fn undocumented1() {} -... | -190 | | } -191 | | } - | |_^ + --> $DIR/missing-doc.rs:178:1 + | +LL | / mod internal_impl { +LL | | /// dox +LL | | pub fn documented() {} +LL | | pub fn undocumented1() {} +... | +LL | | } +LL | | } + | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:181:5 - | -181 | pub fn undocumented1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:181:5 + | +LL | pub fn undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:182:5 - | -182 | pub fn undocumented2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:182:5 + | +LL | pub fn undocumented2() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:183:5 - | -183 | fn undocumented3() {} - | ^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:183:5 + | +LL | fn undocumented3() {} + | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:188:9 - | -188 | pub fn also_undocumented1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:188:9 + | +LL | pub fn also_undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:189:9 - | -189 | fn also_undocumented2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/missing-doc.rs:189:9 + | +LL | fn also_undocumented2() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 39 previous errors diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index 132285a1eaa..efe9a3b1399 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -1,7 +1,7 @@ error: missing `#[inline]` for a function --> $DIR/missing_inline.rs:40:1 | -40 | pub fn pub_foo() {} // missing #[inline] +LL | pub fn pub_foo() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` @@ -9,31 +9,31 @@ error: missing `#[inline]` for a function error: missing `#[inline]` for a default trait method --> $DIR/missing_inline.rs:56:5 | -56 | fn PubBar_b() {} // missing #[inline] +LL | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method --> $DIR/missing_inline.rs:70:5 | -70 | fn PubBar_a() {} // missing #[inline] +LL | fn PubBar_a() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method --> $DIR/missing_inline.rs:71:5 | -71 | fn PubBar_b() {} // missing #[inline] +LL | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method --> $DIR/missing_inline.rs:72:5 | -72 | fn PubBar_c() {} // missing #[inline] +LL | fn PubBar_c() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method --> $DIR/missing_inline.rs:82:5 | -82 | pub fn PubFooImpl() {} // missing #[inline] +LL | pub fn PubFooImpl() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index bf891aa4578..f4d4692e259 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,9 +1,9 @@ error: module has the same name as its containing module --> $DIR/module_inception.rs:14:9 | -14 | / mod bar { -15 | | mod foo {} -16 | | } +LL | / mod bar { +LL | | mod foo {} +LL | | } | |_________^ | = note: `-D clippy::module-inception` implied by `-D warnings` @@ -11,9 +11,9 @@ error: module has the same name as its containing module error: module has the same name as its containing module --> $DIR/module_inception.rs:19:5 | -19 | / mod foo { -20 | | mod bar {} -21 | | } +LL | / mod foo { +LL | | mod bar {} +LL | | } | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr index e2eca64ba42..866156e3b74 100644 --- a/tests/ui/module_name_repetitions.stderr +++ b/tests/ui/module_name_repetitions.stderr @@ -1,7 +1,7 @@ error: item name starts with its containing module's name --> $DIR/module_name_repetitions.rs:15:5 | -15 | pub fn foo_bar() {} +LL | pub fn foo_bar() {} | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::module-name-repetitions` implied by `-D warnings` @@ -9,25 +9,25 @@ error: item name starts with its containing module's name error: item name ends with its containing module's name --> $DIR/module_name_repetitions.rs:16:5 | -16 | pub fn bar_foo() {} +LL | pub fn bar_foo() {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name --> $DIR/module_name_repetitions.rs:17:5 | -17 | pub struct FooCake {} +LL | pub struct FooCake {} | ^^^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name --> $DIR/module_name_repetitions.rs:18:5 | -18 | pub enum CakeFoo {} +LL | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name --> $DIR/module_name_repetitions.rs:19:5 | -19 | pub struct Foo7Bar; +LL | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index e4d20c5c63c..36f06c74077 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -1,7 +1,7 @@ error: any number modulo 1 will be 0 --> $DIR/modulo_one.rs:14:5 | -14 | 10 % 1; +LL | 10 % 1; | ^^^^^^ | = note: `-D clippy::modulo-one` implied by `-D warnings` diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index db0f05a7fa7..544d1aa5f14 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -1,62 +1,62 @@ error: mutable borrow from immutable input(s) --> $DIR/mut_from_ref.rs:16:39 | -16 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { +LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^^^^ | = note: `-D clippy::mut-from-ref` implied by `-D warnings` note: immutable borrow here --> $DIR/mut_from_ref.rs:16:29 | -16 | fn this_wont_hurt_a_bit(&self) -> &mut Foo { +LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^ error: mutable borrow from immutable input(s) --> $DIR/mut_from_ref.rs:22:25 | -22 | fn ouch(x: &Foo) -> &mut Foo; +LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^^^^^ | note: immutable borrow here --> $DIR/mut_from_ref.rs:22:16 | -22 | fn ouch(x: &Foo) -> &mut Foo; +LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^ error: mutable borrow from immutable input(s) --> $DIR/mut_from_ref.rs:31:21 | -31 | fn fail(x: &u32) -> &mut u16 { +LL | fn fail(x: &u32) -> &mut u16 { | ^^^^^^^^ | note: immutable borrow here --> $DIR/mut_from_ref.rs:31:12 | -31 | fn fail(x: &u32) -> &mut u16 { +LL | fn fail(x: &u32) -> &mut u16 { | ^^^^ error: mutable borrow from immutable input(s) --> $DIR/mut_from_ref.rs:35:50 | -35 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here --> $DIR/mut_from_ref.rs:35:25 | -35 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { +LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^ error: mutable borrow from immutable input(s) --> $DIR/mut_from_ref.rs:39:67 | -39 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here --> $DIR/mut_from_ref.rs:39:27 | -39 | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { +LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 626a309a6a9..ed926637563 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -1,7 +1,7 @@ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:13:11 | -13 | fn fun(x: &mut &mut u32) -> bool { +LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ | = note: `-D clippy::mut-mut` implied by `-D warnings` @@ -9,52 +9,52 @@ error: generally you want to avoid `&mut &mut _` if possible error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:29:17 | -29 | let mut x = &mut &mut 1u32; +LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:23:9 | -23 | &mut $p +LL | &mut $p | ^^^^^^^ ... -44 | let mut z = mut_ptr!(&mut 3u32); +LL | let mut z = mut_ptr!(&mut 3u32); | ------------------- in this macro invocation error: this expression mutably borrows a mutable reference. Consider reborrowing --> $DIR/mut_mut.rs:31:21 | -31 | let mut y = &mut x; +LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:35:32 | -35 | let y: &mut &mut u32 = &mut &mut 2; +LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:35:16 | -35 | let y: &mut &mut u32 = &mut &mut 2; +LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:40:37 | -40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; +LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:40:16 | -40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; +LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible --> $DIR/mut_mut.rs:40:21 | -40 | let y: &mut &mut &mut u32 = &mut &mut &mut 2; +LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index 87537d77f44..ce3ae6cb2a5 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,7 +1,7 @@ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:25:9 | -25 | m = 5; +LL | m = 5; | ^^^^^ | = note: `-D clippy::mut-range-bound` implied by `-D warnings` @@ -9,25 +9,25 @@ error: attempt to mutate range bound within loop; note that the range of the loo error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:32:9 | -32 | m *= 2; +LL | m *= 2; | ^^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:40:9 | -40 | m = 5; +LL | m = 5; | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:41:9 | -41 | n = 7; +LL | n = 7; | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged --> $DIR/mut_range_bound.rs:55:22 | -55 | let n = &mut m; // warning +LL | let n = &mut m; // warning | ^ error: aborting due to 5 previous errors diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 1664c1dffed..1fe31e26f6e 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,7 +1,7 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference --> $DIR/mut_reference.rs:26:34 | -26 | takes_an_immutable_reference(&mut 42); +LL | takes_an_immutable_reference(&mut 42); | ^^^^^^^ | = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` @@ -9,13 +9,13 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable error: The function/method `as_ptr` doesn't need a mutable reference --> $DIR/mut_reference.rs:28:12 | -28 | as_ptr(&mut 42); +LL | as_ptr(&mut 42); | ^^^^^^^ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference --> $DIR/mut_reference.rs:32:44 | -32 | my_struct.takes_an_immutable_reference(&mut 42); +LL | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index d6f4f03c323..77a05ca13f4 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -1,7 +1,7 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:15:5 | -15 | Mutex::new(true); +LL | Mutex::new(true); | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::mutex-atomic` implied by `-D warnings` @@ -9,31 +9,31 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want th error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:16:5 | -16 | Mutex::new(5usize); +LL | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:17:5 | -17 | Mutex::new(9isize); +LL | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:19:5 | -19 | Mutex::new(&x as *const u32); +LL | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:20:5 | -20 | Mutex::new(&mut x as *mut u32); +LL | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:21:5 | -21 | Mutex::new(0u32); +LL | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::mutex-integer` implied by `-D warnings` @@ -41,7 +41,7 @@ error: Consider using an AtomicUsize instead of a Mutex here. If you just want t error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. --> $DIR/mutex_atomic.rs:22:5 | -22 | Mutex::new(0i32); +LL | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index df2f80ffd11..a0c4ae9561d 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,11 +1,11 @@ error: this if-then-else expression will always return true --> $DIR/needless_bool.rs:40:5 | -40 | / if x { -41 | | true -42 | | } else { -43 | | true -44 | | }; +LL | / if x { +LL | | true +LL | | } else { +LL | | true +LL | | }; | |_____^ | = note: `-D clippy::needless-bool` implied by `-D warnings` @@ -13,128 +13,128 @@ error: this if-then-else expression will always return true error: this if-then-else expression will always return false --> $DIR/needless_bool.rs:45:5 | -45 | / if x { -46 | | false -47 | | } else { -48 | | false -49 | | }; +LL | / if x { +LL | | false +LL | | } else { +LL | | false +LL | | }; | |_____^ error: this if-then-else expression returns a bool literal --> $DIR/needless_bool.rs:50:5 | -50 | / if x { -51 | | true -52 | | } else { -53 | | false -54 | | }; +LL | / if x { +LL | | true +LL | | } else { +LL | | false +LL | | }; | |_____^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal --> $DIR/needless_bool.rs:55:5 | -55 | / if x { -56 | | false -57 | | } else { -58 | | true -59 | | }; +LL | / if x { +LL | | false +LL | | } else { +LL | | true +LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal --> $DIR/needless_bool.rs:60:5 | -60 | / if x && y { -61 | | false -62 | | } else { -63 | | true -64 | | }; +LL | / if x && y { +LL | | false +LL | | } else { +LL | | true +LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true --> $DIR/needless_bool.rs:83:5 | -83 | / if x { -84 | | return true; -85 | | } else { -86 | | return true; -87 | | }; +LL | / if x { +LL | | return true; +LL | | } else { +LL | | return true; +LL | | }; | |_____^ error: this if-then-else expression will always return false --> $DIR/needless_bool.rs:92:5 | -92 | / if x { -93 | | return false; -94 | | } else { -95 | | return false; -96 | | }; +LL | / if x { +LL | | return false; +LL | | } else { +LL | | return false; +LL | | }; | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:101:5 - | -101 | / if x { -102 | | return true; -103 | | } else { -104 | | return false; -105 | | }; - | |_____^ help: you can reduce it to: `return x` + --> $DIR/needless_bool.rs:101:5 + | +LL | / if x { +LL | | return true; +LL | | } else { +LL | | return false; +LL | | }; + | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:110:5 - | -110 | / if x && y { -111 | | return true; -112 | | } else { -113 | | return false; -114 | | }; - | |_____^ help: you can reduce it to: `return x && y` + --> $DIR/needless_bool.rs:110:5 + | +LL | / if x && y { +LL | | return true; +LL | | } else { +LL | | return false; +LL | | }; + | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:119:5 - | -119 | / if x { -120 | | return false; -121 | | } else { -122 | | return true; -123 | | }; - | |_____^ help: you can reduce it to: `return !x` + --> $DIR/needless_bool.rs:119:5 + | +LL | / if x { +LL | | return false; +LL | | } else { +LL | | return true; +LL | | }; + | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:128:5 - | -128 | / if x && y { -129 | | return false; -130 | | } else { -131 | | return true; -132 | | }; - | |_____^ help: you can reduce it to: `return !(x && y)` + --> $DIR/needless_bool.rs:128:5 + | +LL | / if x && y { +LL | | return false; +LL | | } else { +LL | | return true; +LL | | }; + | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:136:8 - | -136 | if x == true {}; - | ^^^^^^^^^ help: try simplifying it as shown: `x` - | - = note: `-D clippy::bool-comparison` implied by `-D warnings` + --> $DIR/needless_bool.rs:136:8 + | +LL | if x == true {}; + | ^^^^^^^^^ help: try simplifying it as shown: `x` + | + = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:140:8 - | -140 | if x == false {}; - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + --> $DIR/needless_bool.rs:140:8 + | +LL | if x == false {}; + | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:150:8 - | -150 | if x == true {}; - | ^^^^^^^^^ help: try simplifying it as shown: `x` + --> $DIR/needless_bool.rs:150:8 + | +LL | if x == true {}; + | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:151:8 - | -151 | if x == false {}; - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + --> $DIR/needless_bool.rs:151:8 + | +LL | if x == false {}; + | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: aborting due to 15 previous errors diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 42deedfa869..ace40665c0c 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,7 +1,7 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:22:15 | -22 | let c = x(&&a); +LL | let c = x(&&a); | ^^^ help: change this to: `&a` | = note: `-D clippy::needless-borrow` implied by `-D warnings` @@ -9,19 +9,19 @@ error: this expression borrows a reference that is immediately dereferenced by t error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:29:17 | -29 | if let Some(ref cake) = Some(&5) {} +LL | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:36:15 | -36 | 46 => &&a, +LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrow.rs:58:34 | -58 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` @@ -29,13 +29,13 @@ error: this pattern takes a reference on something that is being de-referenced error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrow.rs:59:30 | -59 | let _ = v.iter().filter(|&ref a| a.is_empty()); +LL | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:59:31 | -59 | let _ = v.iter().filter(|&ref a| a.is_empty()); +LL | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` error: aborting due to 6 previous errors diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 5ec7b9e4f3e..b7ea9499f38 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,7 +1,7 @@ error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrowed_ref.rs:14:34 | -14 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` | = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` @@ -9,19 +9,19 @@ error: this pattern takes a reference on something that is being de-referenced error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrowed_ref.rs:19:17 | -19 | if let Some(&ref v) = thingy { +LL | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep: `v` error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrowed_ref.rs:48:27 | -48 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +LL | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: this pattern takes a reference on something that is being de-referenced --> $DIR/needless_borrowed_ref.rs:48:38 | -48 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' +LL | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 39b3aa5470b..c4cb187c34e 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,7 +1,7 @@ error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:16:28 | -16 | let len = sample.iter().collect::>().len(); +LL | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` | = note: `-D clippy::needless-collect` implied by `-D warnings` @@ -9,19 +9,19 @@ error: avoid using `collect()` when not needed error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:17:21 | -17 | if sample.iter().collect::>().is_empty() { +LL | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:20:27 | -20 | sample.iter().cloned().collect::>().contains(&1); +LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:21:34 | -21 | sample.iter().map(|x| (x, x)).collect::>().len(); +LL | sample.iter().map(|x| (x, x)).collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` error: aborting due to 4 previous errors diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 06f63ee496e..60c853c18ad 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -2,10 +2,10 @@ error: This else block is redundant. --> $DIR/needless_continue.rs:36:16 | -36 | } else { +LL | } else { | ________________^ -37 | | continue; -38 | | } +LL | | continue; +LL | | } | |_________^ | = note: `-D clippy::needless-continue` implied by `-D warnings` @@ -39,12 +39,12 @@ error: There is no need for an explicit `else` block for this `if` expression --> $DIR/needless_continue.rs:51:9 | -51 | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { -52 | | continue; -53 | | } else { -54 | | println!("Blabber"); -55 | | println!("Jabber"); -56 | | } +LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { +LL | | continue; +LL | | } else { +LL | | println!("Blabber"); +LL | | println!("Jabber"); +LL | | } | |_________^ | = help: Consider dropping the else clause, and moving out the code in the else block, like so: diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index e11aa73db2a..d9ce5909172 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,7 +1,7 @@ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:24:23 | -24 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { +LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` | = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` @@ -9,192 +9,192 @@ error: this argument is passed by value, but not consumed in the function body error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:38:11 | -38 | fn bar(x: String, y: Wrapper) { +LL | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:38:22 | -38 | fn bar(x: String, y: Wrapper) { +LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:44:71 | -44 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:56:18 | -56 | fn test_match(x: Option>, y: Option>) { +LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -56 | fn test_match(x: &Option>, y: Option>) { -57 | match *x { +LL | fn test_match(x: &Option>, y: Option>) { +LL | match *x { | error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:69:24 | -69 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:69:36 | -69 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead | -69 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -70 | let Wrapper(s) = z; // moved -71 | let Wrapper(ref t) = *y; // not moved -72 | let Wrapper(_) = *y; // still not moved +LL | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +LL | let Wrapper(s) = z; // moved +LL | let Wrapper(ref t) = *y; // not moved +LL | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:85:49 | -85 | fn test_blanket_ref(_foo: T, _serializable: S) {} +LL | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:87:18 | -87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:87:29 | -87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -87 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +LL | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -89 | let _ = t.to_string(); +LL | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:87:40 | -87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:87:53 | -87 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -87 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +LL | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -91 | let _ = v.to_owned(); +LL | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:100:12 - | -100 | s: String, - | ^^^^^^ help: consider changing the type to: `&str` + --> $DIR/needless_pass_by_value.rs:100:12 + | +LL | s: String, + | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:12 - | -101 | t: String, - | ^^^^^^ help: consider taking a reference instead: `&String` + --> $DIR/needless_pass_by_value.rs:101:12 + | +LL | t: String, + | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:110:23 - | -110 | fn baz(&self, _u: U, _s: Self) {} - | ^ help: consider taking a reference instead: `&U` + --> $DIR/needless_pass_by_value.rs:110:23 + | +LL | fn baz(&self, _u: U, _s: Self) {} + | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:110:30 - | -110 | fn baz(&self, _u: U, _s: Self) {} - | ^^^^ help: consider taking a reference instead: `&Self` + --> $DIR/needless_pass_by_value.rs:110:30 + | +LL | fn baz(&self, _u: U, _s: Self) {} + | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:132:24 - | -132 | fn bar_copy(x: u32, y: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` - | + --> $DIR/needless_pass_by_value.rs:132:24 + | +LL | fn bar_copy(x: u32, y: CopyWrapper) { + | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 - | -130 | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/needless_pass_by_value.rs:130:1 + | +LL | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:29 - | -138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` - | + --> $DIR/needless_pass_by_value.rs:138:29 + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 - | -130 | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/needless_pass_by_value.rs:130:1 + | +LL | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:45 - | -138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ - | + --> $DIR/needless_pass_by_value.rs:138:45 + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ + | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 - | -130 | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/needless_pass_by_value.rs:130:1 + | +LL | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead - | -138 | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { -139 | let CopyWrapper(s) = z; // moved -140 | let CopyWrapper(ref t) = *y; // not moved -141 | let CopyWrapper(_) = *y; // still not moved - | - -error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:61 - | -138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ - | + | +LL | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { +LL | let CopyWrapper(s) = z; // moved +LL | let CopyWrapper(ref t) = *y; // not moved +LL | let CopyWrapper(_) = *y; // still not moved + | + +error: this argument is passed by value, but not consumed in the function body + --> $DIR/needless_pass_by_value.rs:138:61 + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | ^^^^^^^^^^^ + | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 - | -130 | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/needless_pass_by_value.rs:130:1 + | +LL | struct CopyWrapper(u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead - | -138 | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { -139 | let CopyWrapper(s) = *z; // moved - | + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { +LL | let CopyWrapper(s) = *z; // moved + | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:150:40 - | -150 | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} - | ^ help: consider taking a reference instead: `&S` + --> $DIR/needless_pass_by_value.rs:150:40 + | +LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} + | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:155:20 - | -155 | fn more_fun(_item: impl Club<'static, i32>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` + --> $DIR/needless_pass_by_value.rs:155:20 + | +LL | fn more_fun(_item: impl Club<'static, i32>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` error: aborting due to 22 previous errors diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 03a469dfa72..73b1d9841eb 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,83 +1,83 @@ error: the loop variable `i` is only used to index `ns`. --> $DIR/needless_range_loop.rs:17:14 | -17 | for i in 3..10 { +LL | for i in 3..10 { | ^^^^^ | = note: `-D clippy::needless-range-loop` implied by `-D warnings` help: consider using an iterator | -17 | for in ns.iter().take(10).skip(3) { +LL | for in ns.iter().take(10).skip(3) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `ms`. --> $DIR/needless_range_loop.rs:38:14 | -38 | for i in 0..ms.len() { +LL | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -38 | for in &mut ms { +LL | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `ms`. --> $DIR/needless_range_loop.rs:44:14 | -44 | for i in 0..ms.len() { +LL | for i in 0..ms.len() { | ^^^^^^^^^^^ help: consider using an iterator | -44 | for in &mut ms { +LL | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/needless_range_loop.rs:68:14 | -68 | for i in x..x + 4 { +LL | for i in x..x + 4 { | ^^^^^^^^ help: consider using an iterator | -68 | for in vec.iter_mut().skip(x).take(4) { +LL | for in vec.iter_mut().skip(x).take(4) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. --> $DIR/needless_range_loop.rs:75:14 | -75 | for i in x..=x + 4 { +LL | for i in x..=x + 4 { | ^^^^^^^^^ help: consider using an iterator | -75 | for in vec.iter_mut().skip(x).take(4 + 1) { +LL | for in vec.iter_mut().skip(x).take(4 + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. --> $DIR/needless_range_loop.rs:81:14 | -81 | for i in 0..3 { +LL | for i in 0..3 { | ^^^^ help: consider using an iterator | -81 | for in &arr { +LL | for in &arr { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `arr`. --> $DIR/needless_range_loop.rs:85:14 | -85 | for i in 0..2 { +LL | for i in 0..2 { | ^^^^ help: consider using an iterator | -85 | for in arr.iter().take(2) { +LL | for in arr.iter().take(2) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. --> $DIR/needless_range_loop.rs:89:14 | -89 | for i in 1..3 { +LL | for i in 1..3 { | ^^^^ help: consider using an iterator | -89 | for in arr.iter().skip(1) { +LL | for in arr.iter().skip(1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 07d29c19be3..bf1083862ed 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,7 +1,7 @@ error: unneeded return statement --> $DIR/needless_return.rs:17:5 | -17 | return true; +LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` | = note: `-D clippy::needless-return` implied by `-D warnings` @@ -9,43 +9,43 @@ error: unneeded return statement error: unneeded return statement --> $DIR/needless_return.rs:21:5 | -21 | return true; +LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement --> $DIR/needless_return.rs:26:9 | -26 | return true; +LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement --> $DIR/needless_return.rs:28:9 | -28 | return false; +LL | return false; | ^^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement --> $DIR/needless_return.rs:34:17 | -34 | true => return false, +LL | true => return false, | ^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement --> $DIR/needless_return.rs:36:13 | -36 | return true; +LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement --> $DIR/needless_return.rs:43:9 | -43 | return true; +LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement --> $DIR/needless_return.rs:45:16 | -45 | let _ = || return true; +LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` error: aborting due to 8 previous errors diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index d5cd0e7889a..6c4ea68771b 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -1,7 +1,7 @@ error: struct update has no effect, all the fields in the struct have already been specified --> $DIR/needless_update.rs:22:23 | -22 | S { a: 1, b: 1, ..base }; +LL | S { a: 1, b: 1, ..base }; | ^^^^ | = note: `-D clippy::needless-update` implied by `-D warnings` diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index ee0f9af6f95..f1df2b1d98a 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,7 +1,7 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:24:21 | -24 | let _not_less = !(a_value < another_value); +LL | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` @@ -9,19 +9,19 @@ error: The use of negated comparison operators on partially ordered types produc error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:27:30 | -27 | let _not_less_or_equal = !(a_value <= another_value); +LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:30:24 | -30 | let _not_greater = !(a_value > another_value); +LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:33:33 | -33 | let _not_greater_or_equal = !(a_value >= another_value); +LL | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 5e5d1afaafe..4c6d8e8d5dd 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -1,7 +1,7 @@ error: Negation by multiplying with -1 --> $DIR/neg_multiply.rs:36:5 | -36 | x * -1; +LL | x * -1; | ^^^^^^ | = note: `-D clippy::neg-multiply` implied by `-D warnings` @@ -9,7 +9,7 @@ error: Negation by multiplying with -1 error: Negation by multiplying with -1 --> $DIR/neg_multiply.rs:38:5 | -38 | -1 * x; +LL | -1 * x; | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 6ef26234d9d..95b1a04e783 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,13 +1,13 @@ error: this loop never actually loops --> $DIR/never_loop.rs:19:5 | -19 | / loop { -20 | | // clippy::never_loop -21 | | x += 1; -22 | | if x == 1 { +LL | / loop { +LL | | // clippy::never_loop +LL | | x += 1; +LL | | if x == 1 { ... | -25 | | break; -26 | | } +LL | | break; +LL | | } | |_____^ | = note: #[deny(clippy::never_loop)] on by default @@ -15,86 +15,86 @@ error: this loop never actually loops error: this loop never actually loops --> $DIR/never_loop.rs:41:5 | -41 | / loop { -42 | | // never loops -43 | | x += 1; -44 | | break; -45 | | } +LL | / loop { +LL | | // never loops +LL | | x += 1; +LL | | break; +LL | | } | |_____^ error: this loop never actually loops --> $DIR/never_loop.rs:61:5 | -61 | / loop { -62 | | // never loops -63 | | while i == 0 { -64 | | // never loops +LL | / loop { +LL | | // never loops +LL | | while i == 0 { +LL | | // never loops ... | -67 | | return; -68 | | } +LL | | return; +LL | | } | |_____^ error: this loop never actually loops --> $DIR/never_loop.rs:63:9 | -63 | / while i == 0 { -64 | | // never loops -65 | | break; -66 | | } +LL | / while i == 0 { +LL | | // never loops +LL | | break; +LL | | } | |_________^ error: this loop never actually loops --> $DIR/never_loop.rs:75:9 | -75 | / loop { -76 | | // never loops -77 | | if x == 5 { -78 | | break; -79 | | } -80 | | continue 'outer; -81 | | } +LL | / loop { +LL | | // never loops +LL | | if x == 5 { +LL | | break; +LL | | } +LL | | continue 'outer; +LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:111:5 - | -111 | / while let Some(y) = x { -112 | | // never loops -113 | | return; -114 | | } - | |_____^ + --> $DIR/never_loop.rs:111:5 + | +LL | / while let Some(y) = x { +LL | | // never loops +LL | | return; +LL | | } + | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:118:5 - | -118 | / for x in 0..10 { -119 | | // never loops -120 | | match x { -121 | | 1 => break, -122 | | _ => return, -123 | | } -124 | | } - | |_____^ + --> $DIR/never_loop.rs:118:5 + | +LL | / for x in 0..10 { +LL | | // never loops +LL | | match x { +LL | | 1 => break, +LL | | _ => return, +LL | | } +LL | | } + | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:166:5 - | -166 | / 'outer: while a { -167 | | // never loops -168 | | while a { -169 | | if a { -... | -174 | | break 'outer; -175 | | } - | |_____^ + --> $DIR/never_loop.rs:166:5 + | +LL | / 'outer: while a { +LL | | // never loops +LL | | while a { +LL | | if a { +... | +LL | | break 'outer; +LL | | } + | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:181:9 - | -181 | / while false { -182 | | break 'label; -183 | | } - | |_________^ + --> $DIR/never_loop.rs:181:9 + | +LL | / while false { +LL | | break 'label; +LL | | } + | |_________^ error: aborting due to 9 previous errors diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index e5911b3d72e..dd5a24bcbe7 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -1,9 +1,9 @@ error: methods called `new` usually return `Self` --> $DIR/new_ret_no_self.rs:49:5 | -49 | / pub fn new(_: String) -> impl R { -50 | | S3 -51 | | } +LL | / pub fn new(_: String) -> impl R { +LL | | S3 +LL | | } | |_____^ | = note: `-D clippy::new-ret-no-self` implied by `-D warnings` @@ -11,42 +11,42 @@ error: methods called `new` usually return `Self` error: methods called `new` usually return `Self` --> $DIR/new_ret_no_self.rs:81:5 | -81 | / pub fn new() -> u32 { -82 | | unimplemented!(); -83 | | } +LL | / pub fn new() -> u32 { +LL | | unimplemented!(); +LL | | } | |_____^ error: methods called `new` usually return `Self` --> $DIR/new_ret_no_self.rs:90:5 | -90 | / pub fn new(_: String) -> u32 { -91 | | unimplemented!(); -92 | | } +LL | / pub fn new(_: String) -> u32 { +LL | | unimplemented!(); +LL | | } | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:126:5 - | -126 | / pub fn new() -> (u32, u32) { -127 | | unimplemented!(); -128 | | } - | |_____^ + --> $DIR/new_ret_no_self.rs:126:5 + | +LL | / pub fn new() -> (u32, u32) { +LL | | unimplemented!(); +LL | | } + | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:153:5 - | -153 | / pub fn new() -> *mut V { -154 | | unimplemented!(); -155 | | } - | |_____^ + --> $DIR/new_ret_no_self.rs:153:5 + | +LL | / pub fn new() -> *mut V { +LL | | unimplemented!(); +LL | | } + | |_____^ error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:171:5 - | -171 | / pub fn new() -> Option { -172 | | unimplemented!(); -173 | | } - | |_____^ + --> $DIR/new_ret_no_self.rs:171:5 + | +LL | / pub fn new() -> Option { +LL | | unimplemented!(); +LL | | } + | |_____^ error: aborting due to 6 previous errors diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index b37c1e14424..1b35b72a82e 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,45 +1,45 @@ error: you should consider deriving a `Default` implementation for `Foo` --> $DIR/new_without_default.rs:17:5 | -17 | / pub fn new() -> Foo { -18 | | Foo -19 | | } +LL | / pub fn new() -> Foo { +LL | | Foo +LL | | } | |_____^ | = note: `-D clippy::new-without-default-derive` implied by `-D warnings` help: try this | -14 | #[derive(Default)] +LL | #[derive(Default)] | error: you should consider deriving a `Default` implementation for `Bar` --> $DIR/new_without_default.rs:25:5 | -25 | / pub fn new() -> Self { -26 | | Bar -27 | | } +LL | / pub fn new() -> Self { +LL | | Bar +LL | | } | |_____^ help: try this | -22 | #[derive(Default)] +LL | #[derive(Default)] | error: you should consider adding a `Default` implementation for `LtKo<'c>` --> $DIR/new_without_default.rs:89:5 | -89 | / pub fn new() -> LtKo<'c> { -90 | | unimplemented!() -91 | | } +LL | / pub fn new() -> LtKo<'c> { +LL | | unimplemented!() +LL | | } | |_____^ | = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | -88 | impl Default for LtKo<'c> { -89 | fn default() -> Self { -90 | Self::new() -91 | } -92 | } +LL | impl Default for LtKo<'c> { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } | error: aborting due to 3 previous errors diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index e8a88307c97..cc3b069f0b5 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,7 +1,7 @@ error: statement with no effect --> $DIR/no_effect.rs:74:5 | -74 | 0; +LL | 0; | ^^ | = note: `-D clippy::no-effect` implied by `-D warnings` @@ -9,146 +9,146 @@ error: statement with no effect error: statement with no effect --> $DIR/no_effect.rs:75:5 | -75 | s2; +LL | s2; | ^^^ error: statement with no effect --> $DIR/no_effect.rs:76:5 | -76 | Unit; +LL | Unit; | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:77:5 | -77 | Tuple(0); +LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:78:5 | -78 | Struct { field: 0 }; +LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:79:5 | -79 | Struct { ..s }; +LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:80:5 | -80 | Union { a: 0 }; +LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:81:5 | -81 | Enum::Tuple(0); +LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:82:5 | -82 | Enum::Struct { field: 0 }; +LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:83:5 | -83 | 5 + 6; +LL | 5 + 6; | ^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:84:5 | -84 | *&42; +LL | *&42; | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:85:5 | -85 | &6; +LL | &6; | ^^^ error: statement with no effect --> $DIR/no_effect.rs:86:5 | -86 | (5, 6, 7); +LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:87:5 | -87 | box 42; +LL | box 42; | ^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:88:5 | -88 | ..; +LL | ..; | ^^^ error: statement with no effect --> $DIR/no_effect.rs:89:5 | -89 | 5..; +LL | 5..; | ^^^^ error: statement with no effect --> $DIR/no_effect.rs:90:5 | -90 | ..5; +LL | ..5; | ^^^^ error: statement with no effect --> $DIR/no_effect.rs:91:5 | -91 | 5..6; +LL | 5..6; | ^^^^^ error: statement with no effect --> $DIR/no_effect.rs:93:5 | -93 | [42, 55]; +LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:94:5 | -94 | [42, 55][1]; +LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:95:5 | -95 | (42, 55).1; +LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:96:5 | -96 | [42; 55]; +LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:97:5 | -97 | [42; 55][13]; +LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect --> $DIR/no_effect.rs:99:5 | -99 | || x += 5; +LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 - | -101 | FooString { s: s }; - | ^^^^^^^^^^^^^^^^^^^ + --> $DIR/no_effect.rs:101:5 + | +LL | FooString { s: s }; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 25 previous errors diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 6d65f4dca50..6b592b681c9 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -1,7 +1,7 @@ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:19:1 | -19 | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` @@ -11,7 +11,7 @@ error: a const item should never be interior mutable error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:20:1 | -20 | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +LL | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` @@ -19,7 +19,7 @@ error: a const item should never be interior mutable error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:21:1 | -21 | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` @@ -27,249 +27,249 @@ error: a const item should never be interior mutable error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:26:9 | -26 | const $name: $ty = $e; +LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -29 | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:50:5 | -50 | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize; //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:54:5 | -54 | const INPUT: T; +LL | const INPUT: T; | ^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` --> $DIR/non_copy_const.rs:54:18 | -54 | const INPUT: T; +LL | const INPUT: T; | ^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:57:5 | -57 | const ASSOC: Self::NonCopyType; +LL | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` --> $DIR/non_copy_const.rs:57:18 | -57 | const ASSOC: Self::NonCopyType; +LL | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:61:5 | -61 | const AN_INPUT: T = Self::INPUT; +LL | const AN_INPUT: T = Self::INPUT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` --> $DIR/non_copy_const.rs:61:21 | -61 | const AN_INPUT: T = Self::INPUT; +LL | const AN_INPUT: T = Self::INPUT; | ^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:26:9 | -26 | const $name: $ty = $e; +LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -64 | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable +LL | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable | ----------------------------------------------- in this macro invocation error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:70:5 | -70 | const SELF_2: Self; +LL | const SELF_2: Self; | ^^^^^^^^^^^^^^^^^^^ | help: consider requiring `Self` to be `Copy` --> $DIR/non_copy_const.rs:70:19 | -70 | const SELF_2: Self; +LL | const SELF_2: Self; | ^^^^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:91:5 | -91 | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable +LL | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:94:5 | -94 | const U_SELF: U = U::SELF_2; +LL | const U_SELF: U = U::SELF_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `U` to be `Copy` --> $DIR/non_copy_const.rs:94:19 | -94 | const U_SELF: U = U::SELF_2; +LL | const U_SELF: U = U::SELF_2; | ^ error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:97:5 | -97 | const T_ASSOC: T::NonCopyType = T::ASSOC; +LL | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` --> $DIR/non_copy_const.rs:97:20 | -97 | const T_ASSOC: T::NonCopyType = T::ASSOC; +LL | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^ error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:104:5 - | -104 | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^ - | - = note: #[deny(clippy::borrow_interior_mutable_const)] on by default - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:104:5 + | +LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^ + | + = note: #[deny(clippy::borrow_interior_mutable_const)] on by default + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:105:16 - | -105 | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability - | ^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:105:16 + | +LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + | ^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:107:5 - | -107 | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:107:5 + | +LL | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:108:16 - | -108 | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:108:16 + | +LL | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability + | ^^^^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:111:22 - | -111 | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability - | ^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:111:22 + | +LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:112:25 - | -112 | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability - | ^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:112:25 + | +LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:113:27 - | -113 | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability - | ^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:113:27 + | +LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:114:26 - | -114 | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability - | ^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:114:26 + | +LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability + | ^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:125:14 - | -125 | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:125:14 + | +LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:126:14 - | -126 | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:126:14 + | +LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:127:19 - | -127 | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:127:19 + | +LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:128:14 - | -128 | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:128:14 + | +LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:129:13 - | -129 | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:129:13 + | +LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:135:13 - | -135 | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:135:13 + | +LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:140:5 - | -140 | CELL.set(2); //~ ERROR interior mutability - | ^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:140:5 + | +LL | CELL.set(2); //~ ERROR interior mutability + | ^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:141:16 - | -141 | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability - | ^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:141:16 + | +LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability + | ^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:154:5 - | -154 | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:154:5 + | +LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability + | ^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:155:16 - | -155 | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability - | ^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here + --> $DIR/non_copy_const.rs:155:16 + | +LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability + | ^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here error: aborting due to 31 previous errors diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 568ae721588..8729db18dff 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,171 +1,171 @@ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:24:9 | -24 | let bpple: i32; +LL | let bpple: i32; | ^^^^^ | = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here --> $DIR/non_expressive_names.rs:22:9 | -22 | let apple: i32; +LL | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `b_pple` --> $DIR/non_expressive_names.rs:24:9 | -24 | let bpple: i32; +LL | let bpple: i32; | ^^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:26:9 | -26 | let cpple: i32; +LL | let cpple: i32; | ^^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:22:9 | -22 | let apple: i32; +LL | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `c_pple` --> $DIR/non_expressive_names.rs:26:9 | -26 | let cpple: i32; +LL | let cpple: i32; | ^^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:50:9 | -50 | let bluby: i32; +LL | let bluby: i32; | ^^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:49:9 | -49 | let blubx: i32; +LL | let blubx: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `blub_y` --> $DIR/non_expressive_names.rs:50:9 | -50 | let bluby: i32; +LL | let bluby: i32; | ^^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:54:9 | -54 | let coke: i32; +LL | let coke: i32; | ^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:52:9 | -52 | let cake: i32; +LL | let cake: i32; | ^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:72:9 | -72 | let xyzeabc: i32; +LL | let xyzeabc: i32; | ^^^^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:70:9 | -70 | let xyz1abc: i32; +LL | let xyz1abc: i32; | ^^^^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:76:9 | -76 | let parsee: i32; +LL | let parsee: i32; | ^^^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:74:9 | -74 | let parser: i32; +LL | let parser: i32; | ^^^^^^ help: separate the discriminating character by an underscore like: `parse_e` --> $DIR/non_expressive_names.rs:76:9 | -76 | let parsee: i32; +LL | let parsee: i32; | ^^^^^^ error: binding's name is too similar to existing binding --> $DIR/non_expressive_names.rs:90:16 | -90 | bpple: sprang, +LL | bpple: sprang, | ^^^^^^ | note: existing binding defined here --> $DIR/non_expressive_names.rs:89:16 | -89 | apple: spring, +LL | apple: spring, | ^^^^^^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:125:17 - | -125 | let e: i32; - | ^ - | - = note: `-D clippy::many-single-char-names` implied by `-D warnings` + --> $DIR/non_expressive_names.rs:125:17 + | +LL | let e: i32; + | ^ + | + = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:128:17 - | -128 | let e: i32; - | ^ + --> $DIR/non_expressive_names.rs:128:17 + | +LL | let e: i32; + | ^ error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:129:17 - | -129 | let f: i32; - | ^ + --> $DIR/non_expressive_names.rs:129:17 + | +LL | let f: i32; + | ^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:133:13 - | -133 | e => panic!(), - | ^ + --> $DIR/non_expressive_names.rs:133:13 + | +LL | e => panic!(), + | ^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:143:9 - | -143 | let _1 = 1; //~ERROR Consider a more descriptive name - | ^^ - | - = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` + --> $DIR/non_expressive_names.rs:143:9 + | +LL | let _1 = 1; //~ERROR Consider a more descriptive name + | ^^ + | + = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:144:9 - | -144 | let ____1 = 1; //~ERROR Consider a more descriptive name - | ^^^^^ + --> $DIR/non_expressive_names.rs:144:9 + | +LL | let ____1 = 1; //~ERROR Consider a more descriptive name + | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:145:9 - | -145 | let __1___2 = 12; //~ERROR Consider a more descriptive name - | ^^^^^^^ + --> $DIR/non_expressive_names.rs:145:9 + | +LL | let __1___2 = 12; //~ERROR Consider a more descriptive name + | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:165:13 - | -165 | let _1 = 1; - | ^^ + --> $DIR/non_expressive_names.rs:165:13 + | +LL | let _1 = 1; + | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:166:13 - | -166 | let ____1 = 1; - | ^^^^^ + --> $DIR/non_expressive_names.rs:166:13 + | +LL | let ____1 = 1; + | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:167:13 - | -167 | let __1___2 = 12; - | ^^^^^^^ + --> $DIR/non_expressive_names.rs:167:13 + | +LL | let __1___2 = 12; + | ^^^^^^^ error: aborting due to 17 previous errors diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index be013cba459..4ccca10a463 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,7 +1,7 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:23:5 | -23 | res.ok().expect("disaster!"); +LL | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::ok-expect` implied by `-D warnings` @@ -9,25 +9,25 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:29:5 | -29 | res3.ok().expect("whoof"); +LL | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:31:5 | -31 | res4.ok().expect("argh"); +LL | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:33:5 | -33 | res5.ok().expect("oops"); +LL | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` --> $DIR/ok_expect.rs:35:5 | -35 | res6.ok().expect("meh"); +LL | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index 5dd8ea37f6f..4567493a7c2 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -1,11 +1,11 @@ error: Matching on `Some` with `ok()` is redundant --> $DIR/ok_if_let.rs:13:5 | -13 | / if let Some(y) = x.parse().ok() { -14 | | y -15 | | } else { -16 | | 0 -17 | | } +LL | / if let Some(y) = x.parse().ok() { +LL | | y +LL | | } else { +LL | | 0 +LL | | } | |_____^ | = note: `-D clippy::if-let-some-result` implied by `-D warnings` diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index abe7348622f..956e2ee754c 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -1,19 +1,19 @@ error: needlessly taken reference of both operands --> $DIR/op_ref.rs:19:15 | -19 | let foo = &5 - &6; +LL | let foo = &5 - &6; | ^^^^^^^ | = note: `-D clippy::op-ref` implied by `-D warnings` help: use the values directly | -19 | let foo = 5 - 6; +LL | let foo = 5 - 6; | ^ ^ error: taken reference of right operand --> $DIR/op_ref.rs:27:8 | -27 | if b < &a { +LL | if b < &a { | ^^^^-- | | | help: use the right value directly: `a` diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 10691d65a29..55c0429800b 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,7 +1,7 @@ error: file opened with "truncate" and "read" --> $DIR/open_options.rs:15:5 | -15 | OpenOptions::new().read(true).truncate(true).open("foo.txt"); +LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` @@ -9,37 +9,37 @@ error: file opened with "truncate" and "read" error: file opened with "append" and "truncate" --> $DIR/open_options.rs:16:5 | -16 | OpenOptions::new().append(true).truncate(true).open("foo.txt"); +LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "read" is called more than once --> $DIR/open_options.rs:18:5 | -18 | OpenOptions::new().read(true).read(false).open("foo.txt"); +LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "create" is called more than once --> $DIR/open_options.rs:19:5 | -19 | OpenOptions::new().create(true).create(false).open("foo.txt"); +LL | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "write" is called more than once --> $DIR/open_options.rs:20:5 | -20 | OpenOptions::new().write(true).write(false).open("foo.txt"); +LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "append" is called more than once --> $DIR/open_options.rs:21:5 | -21 | OpenOptions::new().append(true).append(false).open("foo.txt"); +LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "truncate" is called more than once --> $DIR/open_options.rs:22:5 | -22 | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); +LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 5df5ae7d918..18ddcec5edd 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Option value where `f` is a unit function --> $DIR/option_map_unit_fn.rs:41:5 | -41 | x.field.map(do_nothing); +LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` @@ -11,7 +11,7 @@ error: called `map(f)` on an Option value where `f` is a unit function error: called `map(f)` on an Option value where `f` is a unit function --> $DIR/option_map_unit_fn.rs:43:5 | -43 | x.field.map(do_nothing); +LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` @@ -19,7 +19,7 @@ error: called `map(f)` on an Option value where `f` is a unit function error: called `map(f)` on an Option value where `f` is a unit function --> $DIR/option_map_unit_fn.rs:45:5 | -45 | x.field.map(diverge); +LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(x_field) = x.field { diverge(...) }` @@ -27,7 +27,7 @@ error: called `map(f)` on an Option value where `f` is a unit function error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:51:5 | -51 | x.field.map(|value| x.do_option_nothing(value + captured)); +LL | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` @@ -35,7 +35,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:53:5 | -53 | x.field.map(|value| { x.do_option_plus_one(value + captured); }); +LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` @@ -43,7 +43,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:56:5 | -56 | x.field.map(|value| do_nothing(value + captured)); +LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` @@ -51,7 +51,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:58:5 | -58 | x.field.map(|value| { do_nothing(value + captured) }); +LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` @@ -59,7 +59,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:60:5 | -60 | x.field.map(|value| { do_nothing(value + captured); }); +LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` @@ -67,7 +67,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:62:5 | -62 | x.field.map(|value| { { do_nothing(value + captured); } }); +LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` @@ -75,7 +75,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:65:5 | -65 | x.field.map(|value| diverge(value + captured)); +LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` @@ -83,7 +83,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:67:5 | -67 | x.field.map(|value| { diverge(value + captured) }); +LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` @@ -91,7 +91,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:69:5 | -69 | x.field.map(|value| { diverge(value + captured); }); +LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` @@ -99,7 +99,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:71:5 | -71 | x.field.map(|value| { { diverge(value + captured); } }); +LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` @@ -107,7 +107,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:76:5 | -76 | x.field.map(|value| { let y = plus_one(value + captured); }); +LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` @@ -115,7 +115,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:78:5 | -78 | x.field.map(|value| { plus_one(value + captured); }); +LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` @@ -123,7 +123,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:80:5 | -80 | x.field.map(|value| { { plus_one(value + captured); } }); +LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` @@ -131,7 +131,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:83:5 | -83 | x.field.map(|ref value| { do_nothing(value + captured) }); +LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` @@ -139,7 +139,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:86:5 | -86 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` @@ -147,7 +147,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:88:5 | -88 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` @@ -155,13 +155,13 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:92:5 | -92 | x.field.map(|value| { +LL | x.field.map(|value| { | _____^ | |_____| | || -93 | || do_nothing(value); -94 | || do_nothing(value) -95 | || }); +LL | || do_nothing(value); +LL | || do_nothing(value) +LL | || }); | ||______^- help: try this: `if let Some(value) = x.field { ... }` | |_______| | @@ -169,7 +169,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit closure --> $DIR/option_map_unit_fn.rs:96:5 | -96 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(value) = x.field { ... }` @@ -177,34 +177,34 @@ error: called `map(f)` on an Option value where `f` is a unit closure error: called `map(f)` on an Option value where `f` is a unit function --> $DIR/option_map_unit_fn.rs:99:5 | -99 | Some(42).map(diverge); +LL | Some(42).map(diverge); | ^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:100:5 - | -100 | "12".parse::().ok().map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` + --> $DIR/option_map_unit_fn.rs:100:5 + | +LL | "12".parse::().ok().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:101:5 - | -101 | Some(plus_one(1)).map(do_nothing); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` + --> $DIR/option_map_unit_fn.rs:101:5 + | +LL | Some(plus_one(1)).map(do_nothing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:105:5 - | -105 | y.map(do_nothing); - | ^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Some(_y) = y { do_nothing(...) }` + --> $DIR/option_map_unit_fn.rs:105:5 + | +LL | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(_y) = y { do_nothing(...) }` error: aborting due to 25 previous errors diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 0689a10231b..992f14c825f 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,7 +1,7 @@ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:10:13 | -10 | fn input(_: Option>) {} +LL | fn input(_: Option>) {} | ^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::option-option` implied by `-D warnings` @@ -9,49 +9,49 @@ error: consider using `Option` instead of `Option>` or a custom enu error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:12:16 | -12 | fn output() -> Option> { +LL | fn output() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:16:27 | -16 | fn output_nested() -> Vec>> { +LL | fn output_nested() -> Vec>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:21:30 | -21 | fn output_nested_nested() -> Option>> { +LL | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:26:8 | -26 | x: Option>, +LL | x: Option>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:30:23 | -30 | fn struct_fn() -> Option> { +LL | fn struct_fn() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:36:22 | -36 | fn trait_fn() -> Option>; +LL | fn trait_fn() -> Option>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:40:11 | -40 | Tuple(Option>), +LL | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases --> $DIR/option_option.rs:41:17 | -41 | Struct { x: Option> }, +LL | Struct { x: Option> }, | ^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 1c15eeaf67b..078a1a5941c 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,7 +1,7 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:17:8 | -17 | if a + b < a {} +LL | if a + b < a {} | ^^^^^^^^^ | = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` @@ -9,43 +9,43 @@ error: You are trying to use classic C overflow conditions that will fail in Rus error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:18:8 | -18 | if a > a + b {} +LL | if a > a + b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:19:8 | -19 | if a + b < b {} +LL | if a + b < b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:20:8 | -20 | if b > a + b {} +LL | if b > a + b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:21:8 | -21 | if a - b > b {} +LL | if a - b > b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:22:8 | -22 | if b < a - b {} +LL | if b < a - b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:23:8 | -23 | if a - b > a {} +LL | if a - b > a {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. --> $DIR/overflow_check_conditional.rs:24:8 | -24 | if a < a - b {} +LL | if a < a - b {} | ^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index e357050b739..7bc83a287c1 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -1,7 +1,7 @@ error: you probably are missing some parameter in your format string --> $DIR/panic_unimplemented.rs:14:16 | -14 | panic!("{}"); +LL | panic!("{}"); | ^^^^ | = note: `-D clippy::panic-params` implied by `-D warnings` @@ -9,25 +9,25 @@ error: you probably are missing some parameter in your format string error: you probably are missing some parameter in your format string --> $DIR/panic_unimplemented.rs:16:16 | -16 | panic!("{:?}"); +LL | panic!("{:?}"); | ^^^^^^ error: you probably are missing some parameter in your format string --> $DIR/panic_unimplemented.rs:18:23 | -18 | assert!(true, "here be missing values: {}"); +LL | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you probably are missing some parameter in your format string --> $DIR/panic_unimplemented.rs:21:12 | -21 | panic!("{{{this}}}"); +LL | panic!("{{{this}}}"); | ^^^^^^^^^^^^ error: `unimplemented` should not be present in production code --> $DIR/panic_unimplemented.rs:64:5 | -64 | unimplemented!(); +LL | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unimplemented` implied by `-D warnings` diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index d429fba5db0..ac040acc306 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -1,9 +1,9 @@ error: re-implementing `PartialEq::ne` is unnecessary --> $DIR/partialeq_ne_impl.rs:18:5 | -18 | / fn ne(&self, _: &Foo) -> bool { -19 | | false -20 | | } +LL | / fn ne(&self, _: &Foo) -> bool { +LL | | false +LL | | } | |_____^ | = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index b97709d2ae9..74e8b9ae776 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,7 +1,7 @@ error: the `y @ _` pattern can be written as just `y` --> $DIR/patterns.rs:17:9 | -17 | y @ _ => (), +LL | y @ _ => (), | ^^^^^ | = note: `-D clippy::redundant-pattern` implied by `-D warnings` diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 8601f828ef3..2d917b3cbdb 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,7 +1,7 @@ error: operator precedence can trip the unwary --> $DIR/precedence.rs:24:5 | -24 | 1 << 2 + 3; +LL | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` | = note: `-D clippy::precedence` implied by `-D warnings` @@ -9,49 +9,49 @@ error: operator precedence can trip the unwary error: operator precedence can trip the unwary --> $DIR/precedence.rs:25:5 | -25 | 1 + 2 << 3; +LL | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary --> $DIR/precedence.rs:26:5 | -26 | 4 >> 1 + 1; +LL | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary --> $DIR/precedence.rs:27:5 | -27 | 1 + 3 >> 2; +LL | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary --> $DIR/precedence.rs:28:5 | -28 | 1 ^ 1 - 1; +LL | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary --> $DIR/precedence.rs:29:5 | -29 | 3 | 2 - 1; +LL | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary --> $DIR/precedence.rs:30:5 | -30 | 3 & 5 - 2; +LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call --> $DIR/precedence.rs:31:5 | -31 | -1i32.abs(); +LL | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call --> $DIR/precedence.rs:32:5 | -32 | -1f32.abs(); +LL | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` error: aborting due to 9 previous errors diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 199f76568f0..9635011b906 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,7 +1,7 @@ error: use of `Debug`-based formatting --> $DIR/print.rs:20:19 | -20 | write!(f, "{:?}", 43.1415) +LL | write!(f, "{:?}", 43.1415) | ^^^^^^ | = note: `-D clippy::use-debug` implied by `-D warnings` @@ -9,13 +9,13 @@ error: use of `Debug`-based formatting error: use of `Debug`-based formatting --> $DIR/print.rs:27:19 | -27 | write!(f, "{:?}", 42.718) +LL | write!(f, "{:?}", 42.718) | ^^^^^^ error: use of `println!` --> $DIR/print.rs:32:5 | -32 | println!("Hello"); +LL | println!("Hello"); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::print-stdout` implied by `-D warnings` @@ -23,37 +23,37 @@ error: use of `println!` error: use of `print!` --> $DIR/print.rs:33:5 | -33 | print!("Hello"); +LL | print!("Hello"); | ^^^^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:35:5 | -35 | print!("Hello {}", "World"); +LL | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:37:5 | -37 | print!("Hello {:?}", "World"); +LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting --> $DIR/print.rs:37:12 | -37 | print!("Hello {:?}", "World"); +LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^ error: use of `print!` --> $DIR/print.rs:39:5 | -39 | print!("Hello {:#?}", "#orld"); +LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting --> $DIR/print.rs:39:12 | -39 | print!("Hello {:#?}", "#orld"); +LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index cba5cc19eac..be55795d1ac 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,7 +1,7 @@ error: literal with an empty format string --> $DIR/print_literal.rs:31:71 | -31 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); +LL | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::print-literal` implied by `-D warnings` @@ -9,79 +9,79 @@ error: literal with an empty format string error: literal with an empty format string --> $DIR/print_literal.rs:32:24 | -32 | print!("Hello {}", "world"); +LL | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:33:36 | -33 | println!("Hello {} {}", world, "world"); +LL | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:34:26 | -34 | println!("Hello {}", "world"); +LL | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:35:30 | -35 | println!("10 / 4 is {}", 2.5); +LL | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string --> $DIR/print_literal.rs:36:28 | -36 | println!("2 + 1 = {}", 3); +LL | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string --> $DIR/print_literal.rs:41:25 | -41 | println!("{0} {1}", "hello", "world"); +LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:41:34 | -41 | println!("{0} {1}", "hello", "world"); +LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:42:25 | -42 | println!("{1} {0}", "hello", "world"); +LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:42:34 | -42 | println!("{1} {0}", "hello", "world"); +LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:45:35 | -45 | println!("{foo} {bar}", foo = "hello", bar = "world"); +LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:45:50 | -45 | println!("{foo} {bar}", foo = "hello", bar = "world"); +LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:46:35 | -46 | println!("{bar} {foo}", foo = "hello", bar = "world"); +LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/print_literal.rs:46:50 | -46 | println!("{bar} {foo}", foo = "hello", bar = "world"); +LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 639a4271110..2d76e447145 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,7 +1,7 @@ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:14:5 | -14 | print!("Hello/n"); +LL | print!("Hello/n"); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::print-with-newline` implied by `-D warnings` @@ -9,19 +9,19 @@ error: using `print!()` with a format string that ends in a single newline, cons error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:15:5 | -15 | print!("Hello {}/n", "world"); +LL | print!("Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:16:5 | -16 | print!("Hello {} {}/n", "world", "#2"); +LL | print!("Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead --> $DIR/print_with_newline.rs:17:5 | -17 | print!("{}/n", 1265); +LL | print!("{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 9a08150d627..89447040a33 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,7 +1,7 @@ error: using `println!("")` --> $DIR/println_empty_string.rs:12:5 | -12 | println!(""); +LL | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` | = note: `-D clippy::println-empty-string` implied by `-D warnings` @@ -9,7 +9,7 @@ error: using `println!("")` error: using `println!("")` --> $DIR/println_empty_string.rs:15:14 | -15 | _ => println!(""), +LL | _ => println!(""), | ^^^^^^^^^^^^ help: replace it with: `println!()` error: aborting due to 2 previous errors diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index c9e8292795f..af5003c9b95 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,7 +1,7 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:15:14 | -15 | fn do_vec(x: &Vec) { +LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` | = note: `-D clippy::ptr-arg` implied by `-D warnings` @@ -9,77 +9,77 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and canno error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:24:14 | -24 | fn do_str(x: &String) { +LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:37:18 | -37 | fn do_vec(x: &Vec); +LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:50:14 | -50 | fn cloned(x: &Vec) -> Vec { +LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ help: change this to | -50 | fn cloned(x: &[u8]) -> Vec { +LL | fn cloned(x: &[u8]) -> Vec { | ^^^^^ help: change `x.clone()` to | -51 | let e = x.to_owned(); +LL | let e = x.to_owned(); | ^^^^^^^^^^^^ help: change `x.clone()` to | -56 | x.to_owned() +LL | x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:59:18 | -59 | fn str_cloned(x: &String) -> String { +LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ help: change this to | -59 | fn str_cloned(x: &str) -> String { +LL | fn str_cloned(x: &str) -> String { | ^^^^ help: change `x.clone()` to | -60 | let a = x.to_string(); +LL | let a = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -61 | let b = x.to_string(); +LL | let b = x.to_string(); | ^^^^^^^^^^^^^ help: change `x.clone()` to | -64 | x.to_string() +LL | x.to_string() | error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:67:44 | -67 | fn false_positive_capacity(x: &Vec, y: &String) { +LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ help: change this to | -67 | fn false_positive_capacity(x: &Vec, y: &str) { +LL | fn false_positive_capacity(x: &Vec, y: &str) { | ^^^^ help: change `y.clone()` to | -69 | let b = y.to_string(); +LL | let b = y.to_string(); | ^^^^^^^^^^^^^ help: change `y.as_str()` to | -70 | let c = y; +LL | let c = y; | ^ error: using a reference to `Cow` is not recommended. --> $DIR/ptr_arg.rs:81:25 | -81 | fn test_cow_with_ref(c: &Cow<[i32]>) {} +LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: aborting due to 7 previous errors diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index c9bd4d79460..d1795f439b2 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,7 +1,7 @@ error: use of `offset` with a `usize` casted to an `isize` --> $DIR/ptr_offset_with_cast.rs:19:9 | -19 | ptr.offset(offset_usize as isize); +LL | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` | = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` @@ -9,7 +9,7 @@ error: use of `offset` with a `usize` casted to an `isize` error: use of `wrapping_offset` with a `usize` casted to an `isize` --> $DIR/ptr_offset_with_cast.rs:23:9 | -23 | ptr.wrapping_offset(offset_usize as isize); +LL | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` error: aborting due to 2 previous errors diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index c9d5538f36f..341f45eef78 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,9 +1,9 @@ error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:11:5 | -11 | / if a.is_none() { -12 | | return None; -13 | | } +LL | / if a.is_none() { +LL | | return None; +LL | | } | |_____^ help: replace_it_with: `a?;` | = note: `-D clippy::question-mark` implied by `-D warnings` @@ -11,28 +11,28 @@ error: this block may be rewritten with the `?` operator error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:47:9 | -47 | / if (self.opt).is_none() { -48 | | return None; -49 | | } +LL | / if (self.opt).is_none() { +LL | | return None; +LL | | } | |_________^ help: replace_it_with: `(self.opt)?;` error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:51:9 | -51 | / if self.opt.is_none() { -52 | | return None -53 | | } +LL | / if self.opt.is_none() { +LL | | return None +LL | | } | |_________^ help: replace_it_with: `self.opt?;` error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:55:17 | -55 | let _ = if self.opt.is_none() { +LL | let _ = if self.opt.is_none() { | _________________^ -56 | | return None; -57 | | } else { -58 | | self.opt -59 | | }; +LL | | return None; +LL | | } else { +LL | | self.opt +LL | | }; | |_________^ help: replace_it_with: `Some(self.opt?)` error: aborting due to 4 previous errors diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 7b3c5ebc3e1..b9a0a10c207 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,7 +1,7 @@ error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:17:13 | -17 | let _ = (0..1).step_by(0); +LL | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` @@ -9,25 +9,25 @@ error: Iterator::step_by(0) will panic at runtime error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:21:13 | -21 | let _ = (1..).step_by(0); +LL | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:22:13 | -22 | let _ = (1..=2).step_by(0); +LL | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:25:13 | -25 | let _ = x.step_by(0); +LL | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: It is more idiomatic to use v1.iter().enumerate() --> $DIR/range.rs:33:14 | -33 | let _x = v1.iter().zip(0..v1.len()); +LL | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::range-zip-with-len` implied by `-D warnings` @@ -35,7 +35,7 @@ error: It is more idiomatic to use v1.iter().enumerate() error: Iterator::step_by(0) will panic at runtime --> $DIR/range.rs:37:13 | -37 | let _ = v1.iter().step_by(2 / 3); +LL | let _ = v1.iter().step_by(2 / 3); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index dc49420ecb9..b1c93933ccc 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,7 +1,7 @@ error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:19:14 | -19 | for _ in 0..3 + 1 {} +LL | for _ in 0..3 + 1 {} | ^^^^^^^^ help: use: `0..=3` | = note: `-D clippy::range-plus-one` implied by `-D warnings` @@ -9,25 +9,25 @@ error: an inclusive range would be more readable error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:22:14 | -22 | for _ in 0..1 + 5 {} +LL | for _ in 0..1 + 5 {} | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:25:14 | -25 | for _ in 1..1 + 1 {} +LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:31:14 | -31 | for _ in 0..(1 + f()) {} +LL | for _ in 0..(1 + f()) {} | ^^^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable --> $DIR/range_plus_minus_one.rs:35:13 | -35 | let _ = ..=11 - 1; +LL | let _ = ..=11 - 1; | ^^^^^^^^^ help: use: `..11` | = note: `-D clippy::range-minus-one` implied by `-D warnings` @@ -35,19 +35,19 @@ error: an exclusive range would be more readable error: an exclusive range would be more readable --> $DIR/range_plus_minus_one.rs:36:13 | -36 | let _ = ..=(11 - 1); +LL | let _ = ..=(11 - 1); | ^^^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:37:13 | -37 | let _ = (1..11 + 1); +LL | let _ = (1..11 + 1); | ^^^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable --> $DIR/range_plus_minus_one.rs:38:13 | -38 | let _ = (f() + 1)..(f() + 1); +LL | let _ = (f() + 1)..(f() + 1); | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` error: aborting due to 8 previous errors diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 07cba0181fd..aef6b9b3d2f 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,122 +1,122 @@ error: redundant clone --> $DIR/redundant_clone.rs:16:41 | -16 | let _ = ["lorem", "ipsum"].join(" ").to_string(); +LL | let _ = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | = note: `-D clippy::redundant-clone` implied by `-D warnings` note: this value is dropped without further use --> $DIR/redundant_clone.rs:16:13 | -16 | let _ = ["lorem", "ipsum"].join(" ").to_string(); +LL | let _ = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:19:14 | -19 | let _ = s.clone(); +LL | let _ = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:19:13 | -19 | let _ = s.clone(); +LL | let _ = s.clone(); | ^ error: redundant clone --> $DIR/redundant_clone.rs:22:14 | -22 | let _ = s.to_string(); +LL | let _ = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:22:13 | -22 | let _ = s.to_string(); +LL | let _ = s.to_string(); | ^ error: redundant clone --> $DIR/redundant_clone.rs:25:14 | -25 | let _ = s.to_owned(); +LL | let _ = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:25:13 | -25 | let _ = s.to_owned(); +LL | let _ = s.to_owned(); | ^ error: redundant clone --> $DIR/redundant_clone.rs:27:41 | -27 | let _ = Path::new("/a/b/").join("c").to_owned(); +LL | let _ = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:27:13 | -27 | let _ = Path::new("/a/b/").join("c").to_owned(); +LL | let _ = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:29:41 | -29 | let _ = Path::new("/a/b/").join("c").to_path_buf(); +LL | let _ = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:29:13 | -29 | let _ = Path::new("/a/b/").join("c").to_path_buf(); +LL | let _ = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:31:28 | -31 | let _ = OsString::new().to_owned(); +LL | let _ = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:31:13 | -31 | let _ = OsString::new().to_owned(); +LL | let _ = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:33:28 | -33 | let _ = OsString::new().to_os_string(); +LL | let _ = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:33:13 | -33 | let _ = OsString::new().to_os_string(); +LL | let _ = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:40:18 | -40 | let _ = tup.0.clone(); +LL | let _ = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:40:13 | -40 | let _ = tup.0.clone(); +LL | let _ = tup.0.clone(); | ^^^^^ error: redundant clone --> $DIR/redundant_clone.rs:50:22 | -50 | (a.clone(), a.clone()) +LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:50:21 | -50 | (a.clone(), a.clone()) +LL | (a.clone(), a.clone()) | ^ error: aborting due to 10 previous errors diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 0d49f1a4066..6a41a07bd95 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,7 +1,7 @@ error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:21:5 | -21 | i = closure(); +LL | i = closure(); | ^^^^^^^^^^^^^ | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` @@ -9,25 +9,25 @@ error: Closure called just once immediately after it was declared error: Closure called just once immediately after it was declared --> $DIR/redundant_closure_call.rs:24:5 | -24 | i = closure(3); +LL | i = closure(3); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:13:13 | -13 | let a = (|| 42)(); +LL | let a = (|| 42)(); | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:16:17 | -16 | let mut k = (|m| m + 1)(i); +LL | let mut k = (|m| m + 1)(i); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:18:9 | -18 | k = (|a, b| a * b)(1, 5); +LL | k = (|a, b| a * b)(1, 5); | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 7febaa61b71..5675f8beb7a 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,7 +1,7 @@ error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:43:9 | -43 | gender: gender, +LL | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` | = note: `-D clippy::redundant-field-names` implied by `-D warnings` @@ -9,37 +9,37 @@ error: redundant field names in struct initialization error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:44:9 | -44 | age: age, +LL | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:65:25 | -65 | let _ = RangeFrom { start: start }; +LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:66:23 | -66 | let _ = RangeTo { end: end }; +LL | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:67:21 | -67 | let _ = Range { start: start, end: end }; +LL | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:67:35 | -67 | let _ = Range { start: start, end: end }; +LL | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization --> $DIR/redundant_field_names.rs:69:32 | -69 | let _ = RangeToInclusive { end: end }; +LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: aborting due to 7 previous errors diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index 2d2aa88d76d..0511fbc7e09 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,7 +1,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching.rs:14:12 | -14 | if let Ok(_) = Ok::(42) {} +LL | if let Ok(_) = Ok::(42) {} | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -9,73 +9,73 @@ error: redundant pattern matching, consider using `is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching.rs:16:12 | -16 | if let Err(_) = Err::(42) {} +LL | if let Err(_) = Err::(42) {} | -------^^^^^^------------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching.rs:18:12 | -18 | if let None = None::<()> {} +LL | if let None = None::<()> {} | -------^^^^---------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching.rs:20:12 | -20 | if let Some(_) = Some(42) {} +LL | if let Some(_) = Some(42) {} | -------^^^^^^^-------------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching.rs:34:5 | -34 | / match Ok::(42) { -35 | | Ok(_) => true, -36 | | Err(_) => false, -37 | | }; +LL | / match Ok::(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching.rs:39:5 | -39 | / match Ok::(42) { -40 | | Ok(_) => false, -41 | | Err(_) => true, -42 | | }; +LL | / match Ok::(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; | |_____^ help: try this: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching.rs:44:5 | -44 | / match Err::(42) { -45 | | Ok(_) => false, -46 | | Err(_) => true, -47 | | }; +LL | / match Err::(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching.rs:49:5 | -49 | / match Err::(42) { -50 | | Ok(_) => true, -51 | | Err(_) => false, -52 | | }; +LL | / match Err::(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; | |_____^ help: try this: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching.rs:54:5 | -54 | / match Some(42) { -55 | | Some(_) => true, -56 | | None => false, -57 | | }; +LL | / match Some(42) { +LL | | Some(_) => true, +LL | | None => false, +LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching.rs:59:5 | -59 | / match None::<()> { -60 | | Some(_) => false, -61 | | None => true, -62 | | }; +LL | / match None::<()> { +LL | | Some(_) => false, +LL | | None => true, +LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: aborting due to 10 previous errors diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index 7665e0d1932..eaaacc7bcbe 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -1,7 +1,7 @@ error: immediately dereferencing a reference --> $DIR/reference.rs:25:13 | -25 | let b = *&a; +LL | let b = *&a; | ^^^ help: try this: `a` | = note: `-D clippy::deref-addrof` implied by `-D warnings` @@ -9,61 +9,61 @@ error: immediately dereferencing a reference error: immediately dereferencing a reference --> $DIR/reference.rs:27:13 | -27 | let b = *&get_number(); +LL | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try this: `get_number()` error: immediately dereferencing a reference --> $DIR/reference.rs:32:13 | -32 | let b = *&bytes[1..2][0]; +LL | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` error: immediately dereferencing a reference --> $DIR/reference.rs:36:13 | -36 | let b = *&(a); +LL | let b = *&(a); | ^^^^^ help: try this: `(a)` error: immediately dereferencing a reference --> $DIR/reference.rs:38:13 | -38 | let b = *(&a); +LL | let b = *(&a); | ^^^^^ help: try this: `a` error: immediately dereferencing a reference --> $DIR/reference.rs:41:13 | -41 | let b = *((&a)); +LL | let b = *((&a)); | ^^^^^^^ help: try this: `a` error: immediately dereferencing a reference --> $DIR/reference.rs:43:13 | -43 | let b = *&&a; +LL | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference --> $DIR/reference.rs:45:14 | -45 | let b = **&aref; +LL | let b = **&aref; | ^^^^^^ help: try this: `aref` error: immediately dereferencing a reference --> $DIR/reference.rs:49:14 | -49 | let b = **&&a; +LL | let b = **&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference --> $DIR/reference.rs:53:17 | -53 | let y = *&mut x; +LL | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference --> $DIR/reference.rs:60:18 | -60 | let y = **&mut &mut x; +LL | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` error: aborting due to 11 previous errors diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 680cc5146e5..b6a4f6eb2af 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,7 +1,7 @@ error: trivial regex --> $DIR/regex.rs:22:45 | -22 | let pipe_in_wrong_position = Regex::new("|"); +LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ | = note: `-D clippy::trivial-regex` implied by `-D warnings` @@ -10,7 +10,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:23:60 | -23 | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); +LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is @@ -18,7 +18,7 @@ error: trivial regex error: regex syntax error: invalid character class range, the start must be <= the end --> $DIR/regex.rs:24:42 | -24 | let wrong_char_ranice = Regex::new("[z-a]"); +LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ | = note: `-D clippy::invalid-regex` implied by `-D warnings` @@ -26,19 +26,19 @@ error: regex syntax error: invalid character class range, the start must be <= t error: regex syntax error: invalid character class range, the start must be <= the end --> $DIR/regex.rs:25:37 | -25 | let some_unicode = Regex::new("[é-è]"); +LL | let some_unicode = Regex::new("[é-è]"); | ^^^ error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:27:33 | -27 | let some_regex = Regex::new(OPENING_PAREN); +LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex --> $DIR/regex.rs:29:53 | -29 | let binary_pipe_in_wrong_position = BRegex::new("|"); +LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ | = help: the regex is unlikely to be useful as it is @@ -46,43 +46,43 @@ error: trivial regex error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:30:41 | -30 | let some_binary_regex = BRegex::new(OPENING_PAREN); +LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:31:56 | -31 | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); +LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:43:37 | -43 | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); +LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group --> $DIR/regex.rs:44:39 | -44 | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); +LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ error: regex syntax error: unrecognized escape sequence --> $DIR/regex.rs:46:45 | -46 | let raw_string_error = Regex::new(r"[...//...]"); +LL | let raw_string_error = Regex::new(r"[...//...]"); | ^^ error: regex syntax error: unrecognized escape sequence --> $DIR/regex.rs:47:46 | -47 | let raw_string_error = Regex::new(r#"[...//...]"#); +LL | let raw_string_error = Regex::new(r#"[...//...]"#); | ^^ error: trivial regex --> $DIR/regex.rs:51:33 | -51 | let trivial_eq = Regex::new("^foobar$"); +LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s @@ -90,7 +90,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:53:48 | -53 | let trivial_eq_builder = RegexBuilder::new("^foobar$"); +LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ | = help: consider using `==` on `str`s @@ -98,7 +98,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:55:42 | -55 | let trivial_starts_with = Regex::new("^foobar"); +LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ | = help: consider using `str::starts_with` @@ -106,7 +106,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:57:40 | -57 | let trivial_ends_with = Regex::new("foobar$"); +LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ | = help: consider using `str::ends_with` @@ -114,7 +114,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:59:39 | -59 | let trivial_contains = Regex::new("foobar"); +LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ | = help: consider using `str::contains` @@ -122,7 +122,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:61:39 | -61 | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); +LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ | = help: consider using `str::contains` @@ -130,7 +130,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:63:40 | -63 | let trivial_backslash = Regex::new("a/.b"); +LL | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ | = help: consider using `str::contains` @@ -138,7 +138,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:66:36 | -66 | let trivial_empty = Regex::new(""); +LL | let trivial_empty = Regex::new(""); | ^^ | = help: the regex is unlikely to be useful as it is @@ -146,7 +146,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:68:36 | -68 | let trivial_empty = Regex::new("^"); +LL | let trivial_empty = Regex::new("^"); | ^^^ | = help: the regex is unlikely to be useful as it is @@ -154,7 +154,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:70:36 | -70 | let trivial_empty = Regex::new("^$"); +LL | let trivial_empty = Regex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` @@ -162,7 +162,7 @@ error: trivial regex error: trivial regex --> $DIR/regex.rs:72:44 | -72 | let binary_trivial_empty = BRegex::new("^$"); +LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 7ad8228fb35..1efc66d442f 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,7 +1,7 @@ error: unknown lint: `stutter` --> $DIR/rename.rs:10:10 | -10 | #![allow(stutter)] +LL | #![allow(stutter)] | ^^^^^^^ | = note: `-D unknown-lints` implied by `-D warnings` @@ -9,7 +9,7 @@ error: unknown lint: `stutter` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` --> $DIR/rename.rs:12:8 | -12 | #[warn(clippy::stutter)] +LL | #[warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` | = note: `-D renamed-and-removed-lints` implied by `-D warnings` diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 401e3a527a6..e45f490463c 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,217 +1,217 @@ error: using `ATOMIC_BOOL_INIT` --> $DIR/replace_consts.rs:22:17 | -22 | { let foo = ATOMIC_BOOL_INIT; }; +LL | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here --> $DIR/replace_consts.rs:12:9 | -12 | #![deny(clippy::replace_consts)] +LL | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` --> $DIR/replace_consts.rs:23:17 | -23 | { let foo = ATOMIC_ISIZE_INIT; }; +LL | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` --> $DIR/replace_consts.rs:24:17 | -24 | { let foo = ATOMIC_I8_INIT; }; +LL | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` --> $DIR/replace_consts.rs:25:17 | -25 | { let foo = ATOMIC_I16_INIT; }; +LL | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` --> $DIR/replace_consts.rs:26:17 | -26 | { let foo = ATOMIC_I32_INIT; }; +LL | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` --> $DIR/replace_consts.rs:27:17 | -27 | { let foo = ATOMIC_I64_INIT; }; +LL | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` --> $DIR/replace_consts.rs:28:17 | -28 | { let foo = ATOMIC_USIZE_INIT; }; +LL | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` --> $DIR/replace_consts.rs:29:17 | -29 | { let foo = ATOMIC_U8_INIT; }; +LL | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` --> $DIR/replace_consts.rs:30:17 | -30 | { let foo = ATOMIC_U16_INIT; }; +LL | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` --> $DIR/replace_consts.rs:31:17 | -31 | { let foo = ATOMIC_U32_INIT; }; +LL | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` --> $DIR/replace_consts.rs:32:17 | -32 | { let foo = ATOMIC_U64_INIT; }; +LL | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` --> $DIR/replace_consts.rs:34:17 | -34 | { let foo = std::isize::MIN; }; +LL | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:35:17 | -35 | { let foo = std::i8::MIN; }; +LL | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:36:17 | -36 | { let foo = std::i16::MIN; }; +LL | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:37:17 | -37 | { let foo = std::i32::MIN; }; +LL | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:38:17 | -38 | { let foo = std::i64::MIN; }; +LL | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:39:17 | -39 | { let foo = std::i128::MIN; }; +LL | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:40:17 | -40 | { let foo = std::usize::MIN; }; +LL | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:41:17 | -41 | { let foo = std::u8::MIN; }; +LL | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:42:17 | -42 | { let foo = std::u16::MIN; }; +LL | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:43:17 | -43 | { let foo = std::u32::MIN; }; +LL | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:44:17 | -44 | { let foo = std::u64::MIN; }; +LL | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` --> $DIR/replace_consts.rs:45:17 | -45 | { let foo = std::u128::MIN; }; +LL | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` --> $DIR/replace_consts.rs:47:17 | -47 | { let foo = std::isize::MAX; }; +LL | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:48:17 | -48 | { let foo = std::i8::MAX; }; +LL | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:49:17 | -49 | { let foo = std::i16::MAX; }; +LL | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:50:17 | -50 | { let foo = std::i32::MAX; }; +LL | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:51:17 | -51 | { let foo = std::i64::MAX; }; +LL | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:52:17 | -52 | { let foo = std::i128::MAX; }; +LL | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:53:17 | -53 | { let foo = std::usize::MAX; }; +LL | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:54:17 | -54 | { let foo = std::u8::MAX; }; +LL | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:55:17 | -55 | { let foo = std::u16::MAX; }; +LL | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:56:17 | -56 | { let foo = std::u32::MAX; }; +LL | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:57:17 | -57 | { let foo = std::u64::MAX; }; +LL | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` --> $DIR/replace_consts.rs:58:17 | -58 | { let foo = std::u128::MAX; }; +LL | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` error: aborting due to 35 previous errors diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index 3f5231dcc06..e462a07ad51 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,7 +1,7 @@ error: called `map(f)` on an Result value where `f` is a unit function --> $DIR/result_map_unit_fn.rs:43:5 | -43 | x.field.map(do_nothing); +LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -11,7 +11,7 @@ error: called `map(f)` on an Result value where `f` is a unit function error: called `map(f)` on an Result value where `f` is a unit function --> $DIR/result_map_unit_fn.rs:45:5 | -45 | x.field.map(do_nothing); +LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` @@ -19,7 +19,7 @@ error: called `map(f)` on an Result value where `f` is a unit function error: called `map(f)` on an Result value where `f` is a unit function --> $DIR/result_map_unit_fn.rs:47:5 | -47 | x.field.map(diverge); +LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` @@ -27,7 +27,7 @@ error: called `map(f)` on an Result value where `f` is a unit function error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:53:5 | -53 | x.field.map(|value| x.do_result_nothing(value + captured)); +LL | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` @@ -35,7 +35,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:55:5 | -55 | x.field.map(|value| { x.do_result_plus_one(value + captured); }); +LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` @@ -43,7 +43,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:58:5 | -58 | x.field.map(|value| do_nothing(value + captured)); +LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` @@ -51,7 +51,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:60:5 | -60 | x.field.map(|value| { do_nothing(value + captured) }); +LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` @@ -59,7 +59,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:62:5 | -62 | x.field.map(|value| { do_nothing(value + captured); }); +LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` @@ -67,7 +67,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:64:5 | -64 | x.field.map(|value| { { do_nothing(value + captured); } }); +LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` @@ -75,7 +75,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:67:5 | -67 | x.field.map(|value| diverge(value + captured)); +LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` @@ -83,7 +83,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:69:5 | -69 | x.field.map(|value| { diverge(value + captured) }); +LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` @@ -91,7 +91,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:71:5 | -71 | x.field.map(|value| { diverge(value + captured); }); +LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` @@ -99,7 +99,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:73:5 | -73 | x.field.map(|value| { { diverge(value + captured); } }); +LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` @@ -107,7 +107,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:78:5 | -78 | x.field.map(|value| { let y = plus_one(value + captured); }); +LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` @@ -115,7 +115,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:80:5 | -80 | x.field.map(|value| { plus_one(value + captured); }); +LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` @@ -123,7 +123,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:82:5 | -82 | x.field.map(|value| { { plus_one(value + captured); } }); +LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` @@ -131,7 +131,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:85:5 | -85 | x.field.map(|ref value| { do_nothing(value + captured) }); +LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` @@ -139,7 +139,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:88:5 | -88 | x.field.map(|value| { do_nothing(value); do_nothing(value) }); +LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` @@ -147,7 +147,7 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:90:5 | -90 | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); +LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` @@ -155,13 +155,13 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:94:5 | -94 | x.field.map(|value| { +LL | x.field.map(|value| { | _____^ | |_____| | || -95 | || do_nothing(value); -96 | || do_nothing(value) -97 | || }); +LL | || do_nothing(value); +LL | || do_nothing(value) +LL | || }); | ||______^- help: try this: `if let Ok(value) = x.field { ... }` | |_______| | @@ -169,26 +169,26 @@ error: called `map(f)` on an Result value where `f` is a unit closure error: called `map(f)` on an Result value where `f` is a unit closure --> $DIR/result_map_unit_fn.rs:98:5 | -98 | x.field.map(|value| { do_nothing(value); do_nothing(value); }); +LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:102:5 - | -102 | "12".parse::().map(diverge); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` + --> $DIR/result_map_unit_fn.rs:102:5 + | +LL | "12".parse::().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:108:5 - | -108 | y.map(do_nothing); - | ^^^^^^^^^^^^^^^^^- - | | - | help: try this: `if let Ok(_y) = y { do_nothing(...) }` + --> $DIR/result_map_unit_fn.rs:108:5 + | +LL | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_y) = y { do_nothing(...) }` error: aborting due to 23 previous errors diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index 23f10f69435..61e54d53468 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -1,12 +1,12 @@ error: you should not implement `visit_string` without also implementing `visit_str` --> $DIR/serde.rs:48:5 | -48 | / fn visit_string(self, _v: String) -> Result -49 | | where -50 | | E: serde::de::Error, -51 | | { -52 | | unimplemented!() -53 | | } +LL | / fn visit_string(self, _v: String) -> Result +LL | | where +LL | | E: serde::de::Error, +LL | | { +LL | | unimplemented!() +LL | | } | |_____^ | = note: `-D clippy::serde-api-misuse` implied by `-D warnings` diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 196f17ac653..158933e9672 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,137 +1,137 @@ error: `x` is shadowed by itself in `&mut x` --> $DIR/shadow.rs:29:5 | -29 | let x = &mut x; +LL | let x = &mut x; | ^^^^^^^^^^^^^^^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here --> $DIR/shadow.rs:28:13 | -28 | let mut x = 1; +LL | let mut x = 1; | ^ error: `x` is shadowed by itself in `{ x }` --> $DIR/shadow.rs:30:5 | -30 | let x = { x }; +LL | let x = { x }; | ^^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:29:9 | -29 | let x = &mut x; +LL | let x = &mut x; | ^ error: `x` is shadowed by itself in `(&*x)` --> $DIR/shadow.rs:31:5 | -31 | let x = (&*x); +LL | let x = (&*x); | ^^^^^^^^^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:30:9 | -30 | let x = { x }; +LL | let x = { x }; | ^ error: `x` is shadowed by `{ *x + 1 }` which reuses the original value --> $DIR/shadow.rs:32:9 | -32 | let x = { *x + 1 }; +LL | let x = { *x + 1 }; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: initialization happens here --> $DIR/shadow.rs:32:13 | -32 | let x = { *x + 1 }; +LL | let x = { *x + 1 }; | ^^^^^^^^^^ note: previous binding is here --> $DIR/shadow.rs:31:9 | -31 | let x = (&*x); +LL | let x = (&*x); | ^ error: `x` is shadowed by `id(x)` which reuses the original value --> $DIR/shadow.rs:33:9 | -33 | let x = id(x); +LL | let x = id(x); | ^ | note: initialization happens here --> $DIR/shadow.rs:33:13 | -33 | let x = id(x); +LL | let x = id(x); | ^^^^^ note: previous binding is here --> $DIR/shadow.rs:32:9 | -32 | let x = { *x + 1 }; +LL | let x = { *x + 1 }; | ^ error: `x` is shadowed by `(1, x)` which reuses the original value --> $DIR/shadow.rs:34:9 | -34 | let x = (1, x); +LL | let x = (1, x); | ^ | note: initialization happens here --> $DIR/shadow.rs:34:13 | -34 | let x = (1, x); +LL | let x = (1, x); | ^^^^^^ note: previous binding is here --> $DIR/shadow.rs:33:9 | -33 | let x = id(x); +LL | let x = id(x); | ^ error: `x` is shadowed by `first(x)` which reuses the original value --> $DIR/shadow.rs:35:9 | -35 | let x = first(x); +LL | let x = first(x); | ^ | note: initialization happens here --> $DIR/shadow.rs:35:13 | -35 | let x = first(x); +LL | let x = first(x); | ^^^^^^^^ note: previous binding is here --> $DIR/shadow.rs:34:9 | -34 | let x = (1, x); +LL | let x = (1, x); | ^ error: `x` is shadowed by `y` --> $DIR/shadow.rs:37:9 | -37 | let x = y; +LL | let x = y; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here --> $DIR/shadow.rs:37:13 | -37 | let x = y; +LL | let x = y; | ^ note: previous binding is here --> $DIR/shadow.rs:35:9 | -35 | let x = first(x); +LL | let x = first(x); | ^ error: `x` shadows a previous declaration --> $DIR/shadow.rs:39:5 | -39 | let x; +LL | let x; | ^^^^^^ | note: previous binding is here --> $DIR/shadow.rs:37:9 | -37 | let x = y; +LL | let x = y; | ^ error: aborting due to 9 previous errors diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index 7b5c843d072..4141a003fc4 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -1,7 +1,7 @@ error: boolean short circuit operator in statement may be clearer using an explicit test --> $DIR/short_circuit_statement.rs:13:5 | -13 | f() && g(); +LL | f() && g(); | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` | = note: `-D clippy::short-circuit-statement` implied by `-D warnings` @@ -9,13 +9,13 @@ error: boolean short circuit operator in statement may be clearer using an expli error: boolean short circuit operator in statement may be clearer using an explicit test --> $DIR/short_circuit_statement.rs:14:5 | -14 | f() || g(); +LL | f() || g(); | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test --> $DIR/short_circuit_statement.rs:15:5 | -15 | 1 == 2 || g(); +LL | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` error: aborting due to 3 previous errors diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 353796b3928..7fa3211ab72 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,7 +1,7 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:14:13 | -14 | x.split("x"); +LL | x.split("x"); | ^^^ help: try using a char instead: `'x'` | = note: `-D clippy::single-char-pattern` implied by `-D warnings` @@ -9,115 +9,115 @@ error: single-character string constant used as pattern error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:31:16 | -31 | x.contains("x"); +LL | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:32:19 | -32 | x.starts_with("x"); +LL | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:33:17 | -33 | x.ends_with("x"); +LL | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:34:12 | -34 | x.find("x"); +LL | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:35:13 | -35 | x.rfind("x"); +LL | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:36:14 | -36 | x.rsplit("x"); +LL | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:37:24 | -37 | x.split_terminator("x"); +LL | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:38:25 | -38 | x.rsplit_terminator("x"); +LL | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:39:17 | -39 | x.splitn(0, "x"); +LL | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:40:18 | -40 | x.rsplitn(0, "x"); +LL | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:41:15 | -41 | x.matches("x"); +LL | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:42:16 | -42 | x.rmatches("x"); +LL | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:43:21 | -43 | x.match_indices("x"); +LL | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:44:22 | -44 | x.rmatch_indices("x"); +LL | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:45:26 | -45 | x.trim_start_matches("x"); +LL | x.trim_start_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:46:24 | -46 | x.trim_end_matches("x"); +LL | x.trim_end_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:48:13 | -48 | x.split("/n"); +LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:53:31 | -53 | x.replace(";", ",").split(","); // issue #2978 +LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:54:19 | -54 | x.starts_with("/x03"); // issue #2996 +LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` error: aborting due to 20 previous errors diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 45fcbce0047..41776030800 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,68 +1,68 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:17:5 | -17 | / match x { -18 | | Some(y) => { -19 | | println!("{:?}", y); -20 | | }, -21 | | _ => (), -22 | | }; +LL | / match x { +LL | | Some(y) => { +LL | | println!("{:?}", y); +LL | | }, +LL | | _ => (), +LL | | }; | |_____^ | = note: `-D clippy::single-match` implied by `-D warnings` help: try this | -17 | if let Some(y) = x { -18 | println!("{:?}", y); -19 | }; +LL | if let Some(y) = x { +LL | println!("{:?}", y); +LL | }; | error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:25:5 | -25 | / match x { -26 | | // Note the missing block braces. -27 | | // We suggest `if let Some(y) = x { .. }` because the macro -28 | | // is expanded before we can do anything. -29 | | Some(y) => println!("{:?}", y), -30 | | _ => (), -31 | | } +LL | / match x { +LL | | // Note the missing block braces. +LL | | // We suggest `if let Some(y) = x { .. }` because the macro +LL | | // is expanded before we can do anything. +LL | | Some(y) => println!("{:?}", y), +LL | | _ => (), +LL | | } | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:34:5 | -34 | / match z { -35 | | (2...3, 7...9) => dummy(), -36 | | _ => {}, -37 | | }; +LL | / match z { +LL | | (2...3, 7...9) => dummy(), +LL | | _ => {}, +LL | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:63:5 | -63 | / match x { -64 | | Some(y) => dummy(), -65 | | None => (), -66 | | }; +LL | / match x { +LL | | Some(y) => dummy(), +LL | | None => (), +LL | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:68:5 | -68 | / match y { -69 | | Ok(y) => dummy(), -70 | | Err(..) => (), -71 | | }; +LL | / match y { +LL | | Ok(y) => dummy(), +LL | | Err(..) => (), +LL | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:75:5 | -75 | / match c { -76 | | Cow::Borrowed(..) => dummy(), -77 | | Cow::Owned(..) => (), -78 | | }; +LL | / match c { +LL | | Cow::Borrowed(..) => dummy(), +LL | | Cow::Owned(..) => (), +LL | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: aborting due to 6 previous errors diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 6ae9dd1a818..ff780ad9667 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -1,22 +1,22 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` --> $DIR/single_match_else.rs:21:5 | -21 | / match ExprNode::Butterflies { -22 | | ExprNode::ExprAddrOf => Some(&NODE), -23 | | _ => { -24 | | let x = 5; -25 | | None -26 | | }, -27 | | } +LL | / match ExprNode::Butterflies { +LL | | ExprNode::ExprAddrOf => Some(&NODE), +LL | | _ => { +LL | | let x = 5; +LL | | None +LL | | }, +LL | | } | |_____^ | = note: `-D clippy::single-match-else` implied by `-D warnings` help: try this | -21 | if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { -22 | let x = 5; -23 | None -24 | } +LL | if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { +LL | let x = 5; +LL | None +LL | } | error: aborting due to previous error diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index f45c3b48b1b..319234386ac 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,9 +1,9 @@ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:22:5 | -21 | let mut vec1 = Vec::with_capacity(len); +LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -22 | vec1.extend(repeat(0).take(len)); +LL | vec1.extend(repeat(0).take(len)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` @@ -11,49 +11,49 @@ error: slow zero-filling initialization error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:26:5 | -25 | let mut vec2 = Vec::with_capacity(len - 10); +LL | let mut vec2 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -26 | vec2.extend(repeat(0).take(len - 10)); +LL | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:40:5 | -39 | let mut resized_vec = Vec::with_capacity(30); +LL | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -40 | resized_vec.resize(30, 0); +LL | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:43:5 | -42 | let mut extend_vec = Vec::with_capacity(30); +LL | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` -43 | extend_vec.extend(repeat(0).take(30)); +LL | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:50:5 | -49 | let mut vec1 = Vec::with_capacity(len); +LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` -50 | vec1.resize(len, 0); +LL | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:58:5 | -57 | let mut vec3 = Vec::with_capacity(len - 10); +LL | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` -58 | vec3.resize(len - 10, 0); +LL | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization --> $DIR/slow_vector_initialization.rs:62:5 | -61 | vec1 = Vec::with_capacity(10); +LL | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replace allocation with: `vec![0; 10]` -62 | vec1.resize(10, 0); +LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index 0b1b7c020d9..ed1ccad9814 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,7 +1,7 @@ error: you should use the `starts_with` method --> $DIR/starts_ends_with.rs:16:5 | -16 | "".chars().next() == Some(' '); +LL | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` | = note: `-D clippy::chars-next-cmp` implied by `-D warnings` @@ -9,19 +9,19 @@ error: you should use the `starts_with` method error: you should use the `starts_with` method --> $DIR/starts_ends_with.rs:17:5 | -17 | Some(' ') != "".chars().next(); +LL | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method --> $DIR/starts_ends_with.rs:22:8 | -22 | if s.chars().next().unwrap() == 'f' { +LL | if s.chars().next().unwrap() == 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:26:8 | -26 | if s.chars().next_back().unwrap() == 'o' { +LL | if s.chars().next_back().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` | = note: `-D clippy::chars-last-cmp` implied by `-D warnings` @@ -29,49 +29,49 @@ error: you should use the `ends_with` method error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:30:8 | -30 | if s.chars().last().unwrap() == 'o' { +LL | if s.chars().last().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method --> $DIR/starts_ends_with.rs:34:8 | -34 | if s.chars().next().unwrap() != 'f' { +LL | if s.chars().next().unwrap() != 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:38:8 | -38 | if s.chars().next_back().unwrap() != 'o' { +LL | if s.chars().next_back().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:42:8 | -42 | if s.chars().last().unwrap() != 'o' { +LL | if s.chars().last().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:50:5 | -50 | "".chars().last() == Some(' '); +LL | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:51:5 | -51 | Some(' ') != "".chars().last(); +LL | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:52:5 | -52 | "".chars().next_back() == Some(' '); +LL | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method --> $DIR/starts_ends_with.rs:53:5 | -53 | Some(' ') != "".chars().next_back(); +LL | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: aborting due to 12 previous errors diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 36af80b8665..80a490b7884 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,7 +1,7 @@ error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:25:5 | -25 | s.extend(abc.chars()); +LL | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` | = note: `-D clippy::string-extend-chars` implied by `-D warnings` @@ -9,13 +9,13 @@ error: calling `.extend(_.chars())` error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:28:5 | -28 | s.extend("abc".chars()); +LL | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:31:5 | -31 | s.extend(def.chars()); +LL | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` error: aborting due to 3 previous errors diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index fe491d29b78..a8c80939b55 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -1,7 +1,7 @@ error: manual implementation of an assign operation --> $DIR/strings.rs:17:9 | -17 | x = x + "."; +LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` | = note: `-D clippy::assign-op-pattern` implied by `-D warnings` @@ -9,7 +9,7 @@ error: manual implementation of an assign operation error: you added something to a string. Consider using `String::push_str()` instead --> $DIR/strings.rs:17:13 | -17 | x = x + "."; +LL | x = x + "."; | ^^^^^^^ | = note: `-D clippy::string-add` implied by `-D warnings` @@ -17,13 +17,13 @@ error: you added something to a string. Consider using `String::push_str()` inst error: you added something to a string. Consider using `String::push_str()` instead --> $DIR/strings.rs:21:13 | -21 | let z = y + "..."; +LL | let z = y + "..."; | ^^^^^^^^^ error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead --> $DIR/strings.rs:31:9 | -31 | x = x + "."; +LL | x = x + "."; | ^^^^^^^^^^^ | = note: `-D clippy::string-add-assign` implied by `-D warnings` @@ -31,31 +31,31 @@ error: you assigned the result of adding something to this string. Consider usin error: manual implementation of an assign operation --> $DIR/strings.rs:31:9 | -31 | x = x + "."; +LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead --> $DIR/strings.rs:45:9 | -45 | x = x + "."; +LL | x = x + "."; | ^^^^^^^^^^^ error: manual implementation of an assign operation --> $DIR/strings.rs:45:9 | -45 | x = x + "."; +LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you added something to a string. Consider using `String::push_str()` instead --> $DIR/strings.rs:49:13 | -49 | let z = y + "..."; +LL | let z = y + "..."; | ^^^^^^^^^ error: calling `as_bytes()` on a string literal --> $DIR/strings.rs:57:14 | -57 | let bs = "hello there".as_bytes(); +LL | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` | = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` @@ -63,13 +63,13 @@ error: calling `as_bytes()` on a string literal error: calling `as_bytes()` on a string literal --> $DIR/strings.rs:59:14 | -59 | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); +LL | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###` error: calling `as_bytes()` on `include_str!(..)` --> $DIR/strings.rs:66:22 | -66 | let includestr = include_str!("entry.rs").as_bytes(); +LL | let includestr = include_str!("entry.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")` error: aborting due to 11 previous errors diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 5e27dd1d44f..71cb08c77d7 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,7 +1,7 @@ error: Suspicious use of binary operator in `Add` impl --> $DIR/suspicious_arithmetic_impl.rs:20:20 | -20 | Foo(self.0 - other.0) +LL | Foo(self.0 - other.0) | ^ | = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` @@ -9,7 +9,7 @@ error: Suspicious use of binary operator in `Add` impl error: Suspicious use of binary operator in `AddAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:26:23 | -26 | *self = *self - other; +LL | *self = *self - other; | ^ | = note: #[deny(clippy::suspicious_op_assign_impl)] on by default diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index c8e803c4afd..25afaccd754 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,9 +1,9 @@ error: this looks like you are swapping elements of `foo` manually --> $DIR/swap.rs:17:5 | -17 | / let temp = foo[0]; -18 | | foo[0] = foo[1]; -19 | | foo[1] = temp; +LL | / let temp = foo[0]; +LL | | foo[0] = foo[1]; +LL | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` | = note: `-D clippy::manual-swap` implied by `-D warnings` @@ -11,26 +11,26 @@ error: this looks like you are swapping elements of `foo` manually error: this looks like you are swapping elements of `foo` manually --> $DIR/swap.rs:26:5 | -26 | / let temp = foo[0]; -27 | | foo[0] = foo[1]; -28 | | foo[1] = temp; +LL | / let temp = foo[0]; +LL | | foo[0] = foo[1]; +LL | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping elements of `foo` manually --> $DIR/swap.rs:35:5 | -35 | / let temp = foo[0]; -36 | | foo[0] = foo[1]; -37 | | foo[1] = temp; +LL | / let temp = foo[0]; +LL | | foo[0] = foo[1]; +LL | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping `a` and `b` manually --> $DIR/swap.rs:54:7 | -54 | ; let t = a; +LL | ; let t = a; | _______^ -55 | | a = b; -56 | | b = t; +LL | | a = b; +LL | | b = t; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? @@ -38,10 +38,10 @@ error: this looks like you are swapping `a` and `b` manually error: this looks like you are swapping `c.0` and `a` manually --> $DIR/swap.rs:63:7 | -63 | ; let t = c.0; +LL | ; let t = c.0; | _______^ -64 | | c.0 = a; -65 | | a = t; +LL | | c.0 = a; +LL | | a = t; | |_________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? @@ -49,8 +49,8 @@ error: this looks like you are swapping `c.0` and `a` manually error: this looks like you are trying to swap `a` and `b` --> $DIR/swap.rs:51:5 | -51 | / a = b; -52 | | b = a; +LL | / a = b; +LL | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: `-D clippy::almost-swapped` implied by `-D warnings` @@ -59,8 +59,8 @@ error: this looks like you are trying to swap `a` and `b` error: this looks like you are trying to swap `c.0` and `a` --> $DIR/swap.rs:60:5 | -60 | / c.0 = a; -61 | | a = c.0; +LL | / c.0 = a; +LL | | a = c.0; | |___________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 17b1ca1251a..a9736385048 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -1,7 +1,7 @@ error: assignment to temporary --> $DIR/temporary_assignment.rs:39:5 | -39 | Struct { field: 0 }.field = 1; +LL | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::temporary-assignment` implied by `-D warnings` @@ -9,7 +9,7 @@ error: assignment to temporary error: assignment to temporary --> $DIR/temporary_assignment.rs:40:5 | -40 | (0, 0).0 = 1; +LL | (0, 0).0 = 1; | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index 2807539604d..7b7a46d9f8e 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,7 +1,7 @@ error: `ref` directly on a function argument is ignored. Consider using a reference type instead. --> $DIR/toplevel_ref_arg.rs:13:15 | -13 | fn the_answer(ref mut x: u8) { +LL | fn the_answer(ref mut x: u8) { | ^^^^^^^^^ | = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` @@ -9,25 +9,25 @@ error: `ref` directly on a function argument is ignored. Consider using a refere error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead --> $DIR/toplevel_ref_arg.rs:24:9 | -24 | let ref x = 1; +LL | let ref x = 1; | ----^^^^^----- help: try: `let x = &1;` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead --> $DIR/toplevel_ref_arg.rs:26:9 | -26 | let ref y: (&_, u8) = (&1, 2); +LL | let ref y: (&_, u8) = (&1, 2); | ----^^^^^--------------------- help: try: `let y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead --> $DIR/toplevel_ref_arg.rs:28:9 | -28 | let ref z = 1 + 2; +LL | let ref z = 1 + 2; | ----^^^^^--------- help: try: `let z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead --> $DIR/toplevel_ref_arg.rs:30:9 | -30 | let ref mut z = 1 + 2; +LL | let ref mut z = 1 + 2; | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` error: aborting due to 5 previous errors diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 0bd3580a7dd..1675eb44efd 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -1,7 +1,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:16:5 | -16 | (x & 0b1111 == 0); // suggest trailing_zeros +LL | (x & 0b1111 == 0); // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` | = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` @@ -9,7 +9,7 @@ error: bit mask could be simplified with a call to `trailing_zeros` error: bit mask could be simplified with a call to `trailing_zeros` --> $DIR/trailing_zeros.rs:17:13 | -17 | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros +LL | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` error: aborting due to 2 previous errors diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 6e4fe32a4a6..a6e87a72104 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,7 +1,7 @@ error: transmute from a type (`&'a T`) to itself --> $DIR/transmute.rs:28:20 | -28 | let _: &'a T = core::intrinsics::transmute(t); +LL | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::useless-transmute` implied by `-D warnings` @@ -9,25 +9,25 @@ error: transmute from a type (`&'a T`) to itself error: transmute from a reference to a pointer --> $DIR/transmute.rs:32:23 | -32 | let _: *const T = core::intrinsics::transmute(t); +LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer --> $DIR/transmute.rs:34:21 | -34 | let _: *mut T = core::intrinsics::transmute(t); +LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer --> $DIR/transmute.rs:36:23 | -36 | let _: *const U = core::intrinsics::transmute(t); +LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a pointer type (`*const T`) to a reference type (`&T`) --> $DIR/transmute.rs:41:17 | -41 | let _: &T = std::mem::transmute(p); +LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` | = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` @@ -35,212 +35,212 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) --> $DIR/transmute.rs:44:21 | -44 | let _: &mut T = std::mem::transmute(m); +LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) --> $DIR/transmute.rs:47:17 | -47 | let _: &T = std::mem::transmute(m); +LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) --> $DIR/transmute.rs:50:21 | -50 | let _: &mut T = std::mem::transmute(p as *mut T); +LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) --> $DIR/transmute.rs:53:17 | -53 | let _: &T = std::mem::transmute(o); +LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) --> $DIR/transmute.rs:56:21 | -56 | let _: &mut T = std::mem::transmute(om); +LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) --> $DIR/transmute.rs:59:17 | -59 | let _: &T = std::mem::transmute(om); +LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, u8>`) --> $DIR/transmute.rs:70:32 | -70 | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; +LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, &u8>`) --> $DIR/transmute.rs:72:33 | -72 | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; +LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) --> $DIR/transmute.rs:76:14 | -76 | unsafe { std::mem::transmute::<_, Bar>(raw) }; +LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a type (`std::vec::Vec`) to itself --> $DIR/transmute.rs:82:27 | -82 | let _: Vec = core::intrinsics::transmute(my_vec()); +LL | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself --> $DIR/transmute.rs:84:27 | -84 | let _: Vec = core::mem::transmute(my_vec()); +LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself --> $DIR/transmute.rs:86:27 | -86 | let _: Vec = std::intrinsics::transmute(my_vec()); +LL | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself --> $DIR/transmute.rs:88:27 | -88 | let _: Vec = std::mem::transmute(my_vec()); +LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself --> $DIR/transmute.rs:90:27 | -90 | let _: Vec = my_transmute(my_vec()); +LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer --> $DIR/transmute.rs:98:31 | -98 | let _: *const usize = std::mem::transmute(5_isize); +LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:102:31 - | -102 | let _: *const usize = std::mem::transmute(1 + 1usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` + --> $DIR/transmute.rs:102:31 + | +LL | let _: *const usize = std::mem::transmute(1 + 1usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:117:24 - | -117 | let _: Usize = core::intrinsics::transmute(int_const_ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` + --> $DIR/transmute.rs:117:24 + | +LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:119:24 - | -119 | let _: Usize = core::intrinsics::transmute(int_mut_ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/transmute.rs:119:24 + | +LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:121:31 - | -121 | let _: *const Usize = core::intrinsics::transmute(my_int()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/transmute.rs:121:31 + | +LL | let _: *const Usize = core::intrinsics::transmute(my_int()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:123:29 - | -123 | let _: *mut Usize = core::intrinsics::transmute(my_int()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/transmute.rs:123:29 + | +LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:129:28 - | -129 | let _: char = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` - | - = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` + --> $DIR/transmute.rs:129:28 + | +LL | let _: char = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` + | + = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:130:28 - | -130 | let _: char = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` + --> $DIR/transmute.rs:130:28 + | +LL | let _: char = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:135:28 - | -135 | let _: bool = unsafe { std::mem::transmute(0_u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` - | - = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` + --> $DIR/transmute.rs:135:28 + | +LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` + | + = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:140:27 - | -140 | let _: f32 = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` - | - = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` + --> $DIR/transmute.rs:140:27 + | +LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` + | + = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:141:27 - | -141 | let _: f32 = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` + --> $DIR/transmute.rs:141:27 + | +LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:145:28 - | -145 | let _: &str = unsafe { std::mem::transmute(b) }; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` - | - = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` + --> $DIR/transmute.rs:145:28 + | +LL | let _: &str = unsafe { std::mem::transmute(b) }; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` + | + = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:146:32 - | -146 | let _: &mut str = unsafe { std::mem::transmute(mb) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` + --> $DIR/transmute.rs:146:32 + | +LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:178:29 - | -178 | let _: *const f32 = std::mem::transmute(ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` - | - = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` + --> $DIR/transmute.rs:178:29 + | +LL | let _: *const f32 = std::mem::transmute(ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` + | + = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:179:27 - | -179 | let _: *mut f32 = std::mem::transmute(mut_ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` + --> $DIR/transmute.rs:179:27 + | +LL | let _: *mut f32 = std::mem::transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:181:23 - | -181 | let _: &f32 = std::mem::transmute(&1u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` + --> $DIR/transmute.rs:181:23 + | +LL | let _: &f32 = std::mem::transmute(&1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:182:23 - | -182 | let _: &f64 = std::mem::transmute(&1f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` + --> $DIR/transmute.rs:182:23 + | +LL | let _: &f64 = std::mem::transmute(&1f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:185:27 - | -185 | let _: &mut f32 = std::mem::transmute(&mut 1u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` + --> $DIR/transmute.rs:185:27 + | +LL | let _: &mut f32 = std::mem::transmute(&mut 1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:186:37 - | -186 | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` + --> $DIR/transmute.rs:186:37 + | +LL | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: aborting due to 38 previous errors diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index 320bbeb7d29..bbca3bc0b36 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,7 +1,7 @@ error: transmute from a `f64` to a pointer --> $DIR/transmute_64bit.rs:16:31 | -16 | let _: *const usize = std::mem::transmute(6.0f64); +LL | let _: *const usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::wrong-transmute` implied by `-D warnings` @@ -9,7 +9,7 @@ error: transmute from a `f64` to a pointer error: transmute from a `f64` to a pointer --> $DIR/transmute_64bit.rs:18:29 | -18 | let _: *mut usize = std::mem::transmute(6.0f64); +LL | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 41aa52ecd14..6f2967bc392 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,7 +1,7 @@ error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:56:11 | -56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` | = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` @@ -9,85 +9,85 @@ error: this argument is passed by reference, but would be more efficient if pass error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:56:20 | -56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:56:29 | -56 | fn bad(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:63:12 | -63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:63:22 | -63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:63:31 | -63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:63:40 | -63 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:65:16 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:65:25 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:65:34 | -65 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:77:16 | -77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:77:25 | -77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:77:34 | -77 | fn bad2(x: &u32, y: &Foo, z: &Baz) {} +LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:81:34 | -81 | fn trait_method(&self, _foo: &Foo); +LL | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value --> $DIR/trivially_copy_pass_by_ref.rs:85:37 | -85 | fn trait_method2(&self, _color: &Color); +LL | fn trait_method2(&self, _color: &Color); | ^^^^^^ help: consider passing by value instead: `Color` error: aborting due to 15 previous errors diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index e8770490abb..76dc07aef31 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -1,7 +1,7 @@ error: casting i32 to i64 may become silently lossy if types change --> $DIR/types.rs:18:22 | -18 | let c_i64: i64 = c as i64; +LL | let c_i64: i64 = c as i64; | ^^^^^^^^ help: try: `i64::from(c)` | = note: `-D clippy::cast-lossless` implied by `-D warnings` diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index e27b5866372..9b78271e1fa 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,7 +1,7 @@ error: zero-width space detected --> $DIR/unicode.rs:12:12 | -12 | print!("Here >​< is a ZWS, and ​another"); +LL | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::zero-width-space` implied by `-D warnings` @@ -11,7 +11,7 @@ error: zero-width space detected error: non-nfc unicode sequence detected --> $DIR/unicode.rs:18:12 | -18 | print!("̀àh?"); +LL | print!("̀àh?"); | ^^^^^ | = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` @@ -21,7 +21,7 @@ error: non-nfc unicode sequence detected error: literal non-ASCII character detected --> $DIR/unicode.rs:24:12 | -24 | print!("Üben!"); +LL | print!("Üben!"); | ^^^^^^^ | = note: `-D clippy::non-ascii-literal` implied by `-D warnings` diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index ed8d4cdfd3d..013016574ff 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,73 +1,73 @@ error: passing a unit value to a function --> $DIR/unit_arg.rs:32:9 | -32 | foo({}); +LL | foo({}); | ^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` help: if you intended to pass a unit value, use a unit literal instead | -32 | foo(()); +LL | foo(()); | ^^ error: passing a unit value to a function --> $DIR/unit_arg.rs:33:9 | -33 | foo({ +LL | foo({ | _________^ -34 | | 1; -35 | | }); +LL | | 1; +LL | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -33 | foo(()); +LL | foo(()); | ^^ error: passing a unit value to a function --> $DIR/unit_arg.rs:36:9 | -36 | foo(foo(1)); +LL | foo(foo(1)); | ^^^^^^ help: if you intended to pass a unit value, use a unit literal instead | -36 | foo(()); +LL | foo(()); | ^^ error: passing a unit value to a function --> $DIR/unit_arg.rs:37:9 | -37 | foo({ +LL | foo({ | _________^ -38 | | foo(1); -39 | | foo(2); -40 | | }); +LL | | foo(1); +LL | | foo(2); +LL | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -37 | foo(()); +LL | foo(()); | ^^ error: passing a unit value to a function --> $DIR/unit_arg.rs:41:10 | -41 | foo3({}, 2, 2); +LL | foo3({}, 2, 2); | ^^ help: if you intended to pass a unit value, use a unit literal instead | -41 | foo3((), 2, 2); +LL | foo3((), 2, 2); | ^^ error: passing a unit value to a function --> $DIR/unit_arg.rs:43:11 | -43 | b.bar({ +LL | b.bar({ | ___________^ -44 | | 1; -45 | | }); +LL | | 1; +LL | | }); | |_____^ help: if you intended to pass a unit value, use a unit literal instead | -43 | b.bar(()); +LL | b.bar(()); | ^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 7c76945fe3e..481891b99b0 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,12 +1,12 @@ error: ==-comparison of unit values detected. This will always be true --> $DIR/unit_cmp.rs:21:8 | -21 | if { +LL | if { | ________^ -22 | | true; -23 | | } == { -24 | | false; -25 | | } {} +LL | | true; +LL | | } == { +LL | | false; +LL | | } {} | |_____^ | = note: `-D clippy::unit-cmp` implied by `-D warnings` @@ -14,12 +14,12 @@ error: ==-comparison of unit values detected. This will always be true error: >-comparison of unit values detected. This will always be false --> $DIR/unit_cmp.rs:27:8 | -27 | if { +LL | if { | ________^ -28 | | true; -29 | | } > { -30 | | false; -31 | | } {} +LL | | true; +LL | | } > { +LL | | false; +LL | | } {} | |_____^ error: aborting due to 2 previous errors diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index 83ee0e9dd31..f83a51728e7 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -1,7 +1,7 @@ error: unknown clippy lint: clippy::if_not_els --> $DIR/unknown_clippy_lints.rs:13:8 | -13 | #[warn(clippy::if_not_els)] +LL | #[warn(clippy::if_not_els)] | ^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` @@ -9,7 +9,7 @@ error: unknown clippy lint: clippy::if_not_els error: unknown clippy lint: clippy::All --> $DIR/unknown_clippy_lints.rs:10:10 | -10 | #![allow(clippy::All)] +LL | #![allow(clippy::All)] | ^^^^^^^^^^^ help: lowercase the lint name: `all` error: aborting due to 2 previous errors diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 8a0bf9d55b5..604902e5d6d 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,7 +1,7 @@ error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:26:5 | -26 | 42.clone(); +LL | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` | = note: `-D clippy::clone-on-copy` implied by `-D warnings` @@ -9,19 +9,19 @@ error: using `clone` on a `Copy` type error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:30:5 | -30 | (&42).clone(); +LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:33:5 | -33 | rc.borrow().clone(); +LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:43:5 | -43 | rc.clone(); +LL | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` | = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` @@ -29,68 +29,68 @@ error: using '.clone()' on a ref-counted pointer error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:46:5 | -46 | arc.clone(); +LL | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:49:5 | -49 | rcweak.clone(); +LL | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:52:5 | -52 | arc_weak.clone(); +LL | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer --> $DIR/unnecessary_clone.rs:56:29 | -56 | let _: Arc = x.clone(); +LL | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:60:5 | -60 | t.clone(); +LL | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type --> $DIR/unnecessary_clone.rs:62:5 | -62 | Some(t).clone(); +LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type --> $DIR/unnecessary_clone.rs:68:22 | -68 | let z: &Vec<_> = y.clone(); +LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | = note: #[deny(clippy::clone_double_ref)] on by default help: try dereferencing it | -68 | let z: &Vec<_> = &(*y).clone(); +LL | let z: &Vec<_> = &(*y).clone(); | ^^^^^^^^^^^^^ help: or try being explicit about what type to clone | -68 | let z: &Vec<_> = &std::vec::Vec::clone(y); +LL | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable --> $DIR/unnecessary_clone.rs:75:26 | -75 | let v2: Vec = v.iter().cloned().collect(); +LL | let v2: Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:111:20 - | -111 | let _: E = a.clone(); - | ^^^^^^^^^ help: try dereferencing it: `*****a` + --> $DIR/unnecessary_clone.rs:111:20 + | +LL | let _: E = a.clone(); + | ^^^^^^^^^ help: try dereferencing it: `*****a` error: aborting due to 13 previous errors diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index 53311b3d275..09f8973708f 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -1,7 +1,7 @@ error: this `.filter_map` can be written more simply using `.filter` --> $DIR/unnecessary_filter_map.rs:11:13 | -11 | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); +LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` @@ -9,29 +9,29 @@ error: this `.filter_map` can be written more simply using `.filter` error: this `.filter_map` can be written more simply using `.filter` --> $DIR/unnecessary_filter_map.rs:12:13 | -12 | let _ = (0..4).filter_map(|x| { +LL | let _ = (0..4).filter_map(|x| { | _____________^ -13 | | if x > 1 { -14 | | return Some(x); -15 | | }; -16 | | None -17 | | }); +LL | | if x > 1 { +LL | | return Some(x); +LL | | }; +LL | | None +LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.filter` --> $DIR/unnecessary_filter_map.rs:18:13 | -18 | let _ = (0..4).filter_map(|x| match x { +LL | let _ = (0..4).filter_map(|x| match x { | _____________^ -19 | | 0 | 1 => None, -20 | | _ => Some(x), -21 | | }); +LL | | 0 | 1 => None, +LL | | _ => Some(x), +LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.map` --> $DIR/unnecessary_filter_map.rs:23:13 | -23 | let _ = (0..4).filter_map(|x| Some(x + 1)); +LL | let _ = (0..4).filter_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index e0bd744265c..2c2349bd3bc 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -1,7 +1,7 @@ error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:13:19 | -13 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); +LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` | = note: `-D clippy::unnecessary-fold` implied by `-D warnings` @@ -9,25 +9,25 @@ error: this `.fold` can be written more succinctly using another method error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:15:19 | -15 | let _ = (0..3).fold(true, |acc, x| acc && x > 2); +LL | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:17:19 | -17 | let _ = (0..3).fold(0, |acc, x| acc + x); +LL | let _ = (0..3).fold(0, |acc, x| acc + x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:19:19 | -19 | let _ = (0..3).fold(1, |acc, x| acc * x); +LL | let _ = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method --> $DIR/unnecessary_fold.rs:24:34 | -24 | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); +LL | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: aborting due to 5 previous errors diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index 8b576bef648..e46002dd97b 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -1,7 +1,7 @@ error: statement can be reduced --> $DIR/unnecessary_operation.rs:54:5 | -54 | Tuple(get_number()); +LL | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` | = note: `-D clippy::unnecessary-operation` implied by `-D warnings` @@ -9,119 +9,119 @@ error: statement can be reduced error: statement can be reduced --> $DIR/unnecessary_operation.rs:55:5 | -55 | Struct { field: get_number() }; +LL | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:56:5 | -56 | Struct { ..get_struct() }; +LL | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:57:5 | -57 | Enum::Tuple(get_number()); +LL | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:58:5 | -58 | Enum::Struct { field: get_number() }; +LL | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:59:5 | -59 | 5 + get_number(); +LL | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:60:5 | -60 | *&get_number(); +LL | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:61:5 | -61 | &get_number(); +LL | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:62:5 | -62 | (5, 6, get_number()); +LL | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:63:5 | -63 | box get_number(); +LL | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:64:5 | -64 | get_number()..; +LL | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:65:5 | -65 | ..get_number(); +LL | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:66:5 | -66 | 5..get_number(); +LL | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:67:5 | -67 | [42, get_number()]; +LL | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:68:5 | -68 | [42, 55][get_number() as usize]; +LL | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced --> $DIR/unnecessary_operation.rs:69:5 | -69 | (42, get_number()).1; +LL | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:70:5 | -70 | [get_number(); 55]; +LL | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:71:5 | -71 | [42; 55][get_number() as usize]; +LL | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced --> $DIR/unnecessary_operation.rs:72:5 | -72 | / { -73 | | get_number() -74 | | }; +LL | / { +LL | | get_number() +LL | | }; | |______^ help: replace it with: `get_number();` error: statement can be reduced --> $DIR/unnecessary_operation.rs:75:5 | -75 | / FooString { -76 | | s: String::from("blah"), -77 | | }; +LL | / FooString { +LL | | s: String::from("blah"), +LL | | }; | |______^ help: replace it with: `String::from("blah");` error: aborting due to 20 previous errors diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index f048df6e39b..77503026bde 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,13 +1,13 @@ error: Creating a reference that is immediately dereferenced. --> $DIR/unnecessary_ref.rs:20:17 | -20 | let inner = (&outer).inner; +LL | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer.inner` | note: lint level defined here --> $DIR/unnecessary_ref.rs:17:8 | -17 | #[deny(clippy::ref_in_deref)] +LL | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index a1e43e493b7..23e35923f83 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,7 +1,7 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead --> $DIR/unneeded_field_pattern.rs:23:15 | -23 | Foo { a: _, b: 0, .. } => {}, +LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ | = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` @@ -10,7 +10,7 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead error: All the struct fields are matched to a wildcard pattern, consider using `..`. --> $DIR/unneeded_field_pattern.rs:25:9 | -25 | Foo { a: _, b: _, c: _ } => {}, +LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Try with `Foo { .. }` instead diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 83372a2a5a7..6696f155fb8 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,7 +1,7 @@ error: long literal lacking separators --> $DIR/unreadable_literal.rs:24:16 | -24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` @@ -9,25 +9,25 @@ error: long literal lacking separators error: long literal lacking separators --> $DIR/unreadable_literal.rs:24:30 | -24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators --> $DIR/unreadable_literal.rs:24:51 | -24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators --> $DIR/unreadable_literal.rs:24:63 | -24 | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); +LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators --> $DIR/unreadable_literal.rs:26:19 | -26 | let bad_sci = 1.123456e1; +LL | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` error: aborting due to 5 previous errors diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 3b285208978..cdc2b907ec5 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -1,7 +1,7 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell` --> $DIR/unsafe_removed_from_name.rs:14:1 | -14 | use std::cell::UnsafeCell as TotallySafeCell; +LL | use std::cell::UnsafeCell as TotallySafeCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` @@ -9,13 +9,13 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` --> $DIR/unsafe_removed_from_name.rs:16:1 | -16 | use std::cell::UnsafeCell as TotallySafeCellAgain; +LL | use std::cell::UnsafeCell as TotallySafeCellAgain; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` --> $DIR/unsafe_removed_from_name.rs:30:1 | -30 | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; +LL | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 200e441025e..528d35ebdef 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,7 +1,7 @@ error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:16:5 | -16 | try!(s.write(b"test")); +LL | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-io-amount` implied by `-D warnings` @@ -10,7 +10,7 @@ error: handle written amount returned or use `Write::write_all` instead error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:18:5 | -18 | try!(s.read(&mut buf)); +LL | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -18,25 +18,25 @@ error: handle read amount returned or use `Read::read_exact` instead error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:23:5 | -23 | s.write(b"test")?; +LL | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:25:5 | -25 | s.read(&mut buf)?; +LL | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:30:5 | -30 | s.write(b"test").unwrap(); +LL | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:32:5 | -32 | s.read(&mut buf).unwrap(); +LL | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index cbade54c157..07ff5083ed2 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -1,11 +1,11 @@ error: unused label `'label` --> $DIR/unused_labels.rs:14:5 | -14 | / 'label: for i in 1..2 { -15 | | if i > 4 { -16 | | continue; -17 | | } -18 | | } +LL | / 'label: for i in 1..2 { +LL | | if i > 4 { +LL | | continue; +LL | | } +LL | | } | |_____^ | = note: `-D clippy::unused-label` implied by `-D warnings` @@ -13,17 +13,17 @@ error: unused label `'label` error: unused label `'a` --> $DIR/unused_labels.rs:28:5 | -28 | / 'a: loop { -29 | | break; -30 | | } +LL | / 'a: loop { +LL | | break; +LL | | } | |_____^ error: unused label `'same_label_in_two_fns` --> $DIR/unused_labels.rs:41:5 | -41 | / 'same_label_in_two_fns: loop { -42 | | let _ = 1; -43 | | } +LL | / 'same_label_in_two_fns: loop { +LL | | let _ = 1; +LL | | } | |_____^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index e590cfc91aa..30ce7b68578 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -1,7 +1,7 @@ error: this lifetime isn't used in the function definition --> $DIR/unused_lt.rs:23:14 | -23 | fn unused_lt<'a>(x: u8) {} +LL | fn unused_lt<'a>(x: u8) {} | ^^ | = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` @@ -9,13 +9,13 @@ error: this lifetime isn't used in the function definition error: this lifetime isn't used in the function definition --> $DIR/unused_lt.rs:25:25 | -25 | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { +LL | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition --> $DIR/unused_lt.rs:50:10 | -50 | fn x<'a>(&self) {} +LL | fn x<'a>(&self) {} | ^^ error: aborting due to 3 previous errors diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index aac092b9f7f..ac76d75b176 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -1,51 +1,51 @@ error: unneeded unit return type --> $DIR/unused_unit.rs:25:59 | -25 | pub fn get_unit (), G>(&self, f: F, _g: G) -> +LL | pub fn get_unit (), G>(&self, f: F, _g: G) -> | ___________________________________________________________^ -26 | | () +LL | | () | |__________^ help: remove the `-> ()` | note: lint level defined here --> $DIR/unused_unit.rs:19:9 | -19 | #![deny(clippy::unused_unit)] +LL | #![deny(clippy::unused_unit)] | ^^^^^^^^^^^^^^^^^^^ error: unneeded unit return type --> $DIR/unused_unit.rs:35:19 | -35 | fn into(self) -> () { +LL | fn into(self) -> () { | ^^^^^ help: remove the `-> ()` error: unneeded unit expression --> $DIR/unused_unit.rs:36:9 | -36 | () +LL | () | ^^ help: remove the final `()` error: unneeded unit return type --> $DIR/unused_unit.rs:40:18 | -40 | fn return_unit() -> () { () } +LL | fn return_unit() -> () { () } | ^^^^^ help: remove the `-> ()` error: unneeded unit expression --> $DIR/unused_unit.rs:40:26 | -40 | fn return_unit() -> () { () } +LL | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` --> $DIR/unused_unit.rs:47:14 | -47 | break(); +LL | break(); | ^^ help: remove the `()` error: unneeded `()` --> $DIR/unused_unit.rs:49:11 | -49 | return(); +LL | return(); | ^^ help: remove the `()` error: aborting due to 7 previous errors diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index 2432b7970f6..3970b68de7a 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,7 +1,7 @@ error: use of `unwrap_or` followed by a function call --> $DIR/unwrap_or.rs:13:47 | -13 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); +LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` | = note: `-D clippy::or-fun-call` implied by `-D warnings` @@ -9,7 +9,7 @@ error: use of `unwrap_or` followed by a function call error: use of `unwrap_or` followed by a function call --> $DIR/unwrap_or.rs:17:47 | -17 | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); +LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 0904db2e942..82b44d424df 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,7 +1,7 @@ error: unnecessary structure name repetition --> $DIR/use_self.rs:20:21 | -20 | fn new() -> Foo { +LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` | = note: `-D clippy::use-self` implied by `-D warnings` @@ -9,122 +9,122 @@ error: unnecessary structure name repetition error: unnecessary structure name repetition --> $DIR/use_self.rs:21:13 | -21 | Foo {} +LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:23:22 | -23 | fn test() -> Foo { +LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:24:13 | -24 | Foo::new() +LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:29:25 | -29 | fn default() -> Foo { +LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:30:13 | -30 | Foo::new() +LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:96:22 | -96 | fn refs(p1: &Bad) -> &Bad { +LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:96:31 | -96 | fn refs(p1: &Bad) -> &Bad { +LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:37 - | -100 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:100:37 + | +LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:53 - | -100 | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:100:53 + | +LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:30 - | -104 | fn mut_refs(p1: &mut Bad) -> &mut Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:104:30 + | +LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:43 - | -104 | fn mut_refs(p1: &mut Bad) -> &mut Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:104:43 + | +LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:28 - | -108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:108:28 + | +LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:46 - | -108 | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:108:46 + | +LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:20 - | -110 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:110:20 + | +LL | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:28 - | -110 | fn vals(_: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:110:28 + | +LL | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:111:13 - | -111 | Bad::default() - | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:111:13 + | +LL | Bad::default() + | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:116:23 - | -116 | type Output = Bad; - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:116:23 + | +LL | type Output = Bad; + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:27 - | -118 | fn mul(self, rhs: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:118:27 + | +LL | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:35 - | -118 | fn mul(self, rhs: Bad) -> Bad { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:118:35 + | +LL | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:210:56 - | -210 | fn bad(foos: &[Self]) -> impl Iterator { - | ^^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:210:56 + | +LL | fn bad(foos: &[Self]) -> impl Iterator { + | ^^^ help: use the applicable keyword: `Self` error: aborting due to 21 previous errors diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index c844a8cd75b..798dde2ea0e 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -1,7 +1,7 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:23:5 | -23 | _foo + 1 +LL | _foo + 1 | ^^^^ | = note: `-D clippy::used-underscore-binding` implied by `-D warnings` @@ -9,25 +9,25 @@ error: used binding `_foo` which is prefixed with an underscore. A leading under error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:28:20 | -28 | println!("{}", _foo); +LL | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:29:16 | -29 | assert_eq!(_foo, _foo); +LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:29:22 | -29 | assert_eq!(_foo, _foo); +LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. --> $DIR/used_underscore_binding.rs:42:5 | -42 | s._underscore_field += 1; +LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 397ec7108d4..2e4a7f80444 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,74 +1,74 @@ error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:50:18 | -50 | foo_rstr(rstr.as_ref()); +LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here --> $DIR/useless_asref.rs:10:9 | -10 | #![deny(clippy::useless_asref)] +LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:52:20 | -52 | foo_rslice(rslice.as_ref()); +LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing --> $DIR/useless_asref.rs:56:21 | -56 | foo_mrslice(mrslice.as_mut()); +LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:58:20 | -58 | foo_rslice(mrslice.as_ref()); +LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:65:20 | -65 | foo_rslice(rrrrrslice.as_ref()); +LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:67:18 | -67 | foo_rstr(rrrrrstr.as_ref()); +LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing --> $DIR/useless_asref.rs:72:21 | -72 | foo_mrslice(mrrrrrslice.as_mut()); +LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:74:20 | -74 | foo_rslice(mrrrrrslice.as_ref()); +LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:77:16 | -77 | foo_rrrrmr((&&&&MoreRef).as_ref()); +LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:127:13 - | -127 | foo_mrt(mrt.as_mut()); - | ^^^^^^^^^^^^ help: try this: `mrt` + --> $DIR/useless_asref.rs:127:13 + | +LL | foo_mrt(mrt.as_mut()); + | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:129:12 - | -129 | foo_rt(mrt.as_ref()); - | ^^^^^^^^^^^^ help: try this: `mrt` + --> $DIR/useless_asref.rs:129:12 + | +LL | foo_rt(mrt.as_ref()); + | ^^^^^^^^^^^^ help: try this: `mrt` error: aborting due to 11 previous errors diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 2dde3fd7eac..b9340ce8c02 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,7 +1,7 @@ error: useless lint attribute --> $DIR/useless_attribute.rs:12:1 | -12 | #[allow(dead_code)] +LL | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` | = note: `-D clippy::useless-attribute` implied by `-D warnings` @@ -9,7 +9,7 @@ error: useless lint attribute error: useless lint attribute --> $DIR/useless_attribute.rs:13:1 | -13 | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] +LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` error: aborting due to 2 previous errors diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index ccd6a7d25c7..0afb95629d9 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,7 +1,7 @@ error: useless use of `vec!` --> $DIR/vec.rs:30:14 | -30 | on_slice(&vec![]); +LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` | = note: `-D clippy::useless-vec` implied by `-D warnings` @@ -9,31 +9,31 @@ error: useless use of `vec!` error: useless use of `vec!` --> $DIR/vec.rs:33:14 | -33 | on_slice(&vec![1, 2]); +LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` --> $DIR/vec.rs:36:14 | -36 | on_slice(&vec![1, 2]); +LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` --> $DIR/vec.rs:39:14 | -39 | on_slice(&vec!(1, 2)); +LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` --> $DIR/vec.rs:42:14 | -42 | on_slice(&vec![1; 2]); +LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` --> $DIR/vec.rs:55:14 | -55 | for a in vec![1, 2, 3] { +LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: aborting due to 6 previous errors diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index f085fdad429..21b515fa486 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -1,7 +1,7 @@ error: `Vec` is already on the heap, the boxing is unnecessary. --> $DIR/vec_box_sized.rs:10:17 | -10 | sized_type: Vec>, +LL | sized_type: Vec>, | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` | = note: `-D clippy::vec-box` implied by `-D warnings` diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index 57cfa14a392..0e6c97e48d4 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -1,13 +1,13 @@ error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:15:5 | -15 | / loop { -16 | | if let Some(_x) = y { -17 | | let _v = 1; -18 | | } else { -19 | | break; -20 | | } -21 | | } +LL | / loop { +LL | | if let Some(_x) = y { +LL | | let _v = 1; +LL | | } else { +LL | | break; +LL | | } +LL | | } | |_____^ help: try: `while let Some(_x) = y { .. }` | = note: `-D clippy::while-let-loop` implied by `-D warnings` @@ -15,54 +15,54 @@ error: this loop could be written as a `while let` loop error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:29:5 | -29 | / loop { -30 | | match y { -31 | | Some(_x) => true, -32 | | None => break, -33 | | }; -34 | | } +LL | / loop { +LL | | match y { +LL | | Some(_x) => true, +LL | | None => break, +LL | | }; +LL | | } | |_____^ help: try: `while let Some(_x) = y { .. }` error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:35:5 | -35 | / loop { -36 | | let x = match y { -37 | | Some(x) => x, -38 | | None => break, +LL | / loop { +LL | | let x = match y { +LL | | Some(x) => x, +LL | | None => break, ... | -41 | | let _str = "foo"; -42 | | } +LL | | let _str = "foo"; +LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:43:5 | -43 | / loop { -44 | | let x = match y { -45 | | Some(x) => x, -46 | | None => break, +LL | / loop { +LL | | let x = match y { +LL | | Some(x) => x, +LL | | None => break, ... | -53 | | } -54 | | } +LL | | } +LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop --> $DIR/while_loop.rs:71:5 | -71 | / loop { -72 | | let (e, l) = match "".split_whitespace().next() { -73 | | Some(word) => (word.is_empty(), word.len()), -74 | | None => break, +LL | / loop { +LL | | let (e, l) = match "".split_whitespace().next() { +LL | | Some(word) => (word.is_empty(), word.len()), +LL | | None => break, ... | -77 | | let _ = (e, l); -78 | | } +LL | | let _ = (e, l); +LL | | } | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }` error: this loop could be written as a `for` loop --> $DIR/while_loop.rs:81:33 | -81 | while let Option::Some(x) = iter.next() { +LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` | = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` @@ -70,46 +70,46 @@ error: this loop could be written as a `for` loop error: this loop could be written as a `for` loop --> $DIR/while_loop.rs:86:25 | -86 | while let Some(x) = iter.next() { +LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` error: this loop could be written as a `for` loop --> $DIR/while_loop.rs:91:25 | -91 | while let Some(_) = iter.next() {} +LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^ help: try: `for _ in iter { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:134:5 - | -134 | / loop { -135 | | let _ = match iter.next() { -136 | | Some(ele) => ele, -137 | | None => break, -138 | | }; -139 | | loop {} -140 | | } - | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` + --> $DIR/while_loop.rs:134:5 + | +LL | / loop { +LL | | let _ = match iter.next() { +LL | | Some(ele) => ele, +LL | | None => break, +LL | | }; +LL | | loop {} +LL | | } + | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` error: empty `loop {}` detected. You may want to either use `panic!()` or add `std::thread::sleep(..);` to the loop body. - --> $DIR/while_loop.rs:139:9 - | -139 | loop {} - | ^^^^^^^ - | - = note: `-D clippy::empty-loop` implied by `-D warnings` + --> $DIR/while_loop.rs:139:9 + | +LL | loop {} + | ^^^^^^^ + | + = note: `-D clippy::empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:197:29 - | -197 | while let Some(v) = y.next() { - | ^^^^^^^^ help: try: `for v in y { .. }` + --> $DIR/while_loop.rs:197:29 + | +LL | while let Some(v) = y.next() { + | ^^^^^^^^ help: try: `for v in y { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:225:26 - | -225 | while let Some(..) = values.iter().next() { - | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` + --> $DIR/while_loop.rs:225:26 + | +LL | while let Some(..) = values.iter().next() { + | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` error: aborting due to 12 previous errors diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 40c21902bf2..7daf52a4445 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,7 +1,7 @@ error: literal with an empty format string --> $DIR/write_literal.rs:36:79 | -36 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); +LL | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ | = note: `-D clippy::write-literal` implied by `-D warnings` @@ -9,79 +9,79 @@ error: literal with an empty format string error: literal with an empty format string --> $DIR/write_literal.rs:37:32 | -37 | write!(&mut v, "Hello {}", "world"); +LL | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:38:44 | -38 | writeln!(&mut v, "Hello {} {}", world, "world"); +LL | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:39:34 | -39 | writeln!(&mut v, "Hello {}", "world"); +LL | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:40:38 | -40 | writeln!(&mut v, "10 / 4 is {}", 2.5); +LL | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string --> $DIR/write_literal.rs:41:36 | -41 | writeln!(&mut v, "2 + 1 = {}", 3); +LL | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string --> $DIR/write_literal.rs:46:33 | -46 | writeln!(&mut v, "{0} {1}", "hello", "world"); +LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:46:42 | -46 | writeln!(&mut v, "{0} {1}", "hello", "world"); +LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:47:33 | -47 | writeln!(&mut v, "{1} {0}", "hello", "world"); +LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:47:42 | -47 | writeln!(&mut v, "{1} {0}", "hello", "world"); +LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:50:43 | -50 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); +LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:50:58 | -50 | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); +LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:51:43 | -51 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); +LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string --> $DIR/write_literal.rs:51:58 | -51 | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); +LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: aborting due to 14 previous errors diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index ead6b5d08a0..c18ec184876 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,7 +1,7 @@ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:19:5 | -19 | write!(&mut v, "Hello/n"); +LL | write!(&mut v, "Hello/n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::write-with-newline` implied by `-D warnings` @@ -9,25 +9,25 @@ error: using `write!()` with a format string that ends in a single newline, cons error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:20:5 | -20 | write!(&mut v, "Hello {}/n", "world"); +LL | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:21:5 | -21 | write!(&mut v, "Hello {} {}/n", "world", "#2"); +LL | write!(&mut v, "Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:22:5 | -22 | write!(&mut v, "{}/n", 1265); +LL | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead --> $DIR/write_with_newline.rs:41:5 | -41 | write!(&mut v, "//n"); +LL | write!(&mut v, "//n"); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 5943dfa09b1..9b4061f0fe4 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,7 +1,7 @@ error: using `writeln!(&mut v, "")` --> $DIR/writeln_empty_string.rs:18:5 | -18 | writeln!(&mut v, ""); +LL | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` | = note: `-D clippy::writeln-empty-string` implied by `-D warnings` @@ -9,7 +9,7 @@ error: using `writeln!(&mut v, "")` error: using `writeln!(&mut suggestion, "")` --> $DIR/writeln_empty_string.rs:21:5 | -21 | writeln!(&mut suggestion, ""); +LL | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` error: aborting due to 2 previous errors diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index fa97713ed78..f9d20cb3d47 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -1,7 +1,7 @@ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:26:17 | -26 | fn from_i32(self) {} +LL | fn from_i32(self) {} | ^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` @@ -9,67 +9,67 @@ error: methods called `from_*` usually take no self; consider choosing a less am error: methods called `from_*` usually take no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:32:21 | -32 | pub fn from_i64(self) {} +LL | pub fn from_i64(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:44:15 | -44 | fn as_i32(self) {} +LL | fn as_i32(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:46:17 | -46 | fn into_i32(&self) {} +LL | fn into_i32(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:48:15 | -48 | fn is_i32(self) {} +LL | fn is_i32(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:50:15 | -50 | fn to_i32(self) {} +LL | fn to_i32(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:52:17 | -52 | fn from_i32(self) {} +LL | fn from_i32(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:54:19 | -54 | pub fn as_i64(self) {} +LL | pub fn as_i64(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:55:21 | -55 | pub fn into_i64(&self) {} +LL | pub fn into_i64(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:56:19 | -56 | pub fn is_i64(self) {} +LL | pub fn is_i64(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:57:19 | -57 | pub fn to_i64(self) {} +LL | pub fn to_i64(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name --> $DIR/wrong_self_convention.rs:58:21 | -58 | pub fn from_i64(self) {} +LL | pub fn from_i64(self) {} | ^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 312392050c5..653a76c6978 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -1,7 +1,7 @@ error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:13:15 | -13 | let nan = 0.0 / 0.0; +LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ | = note: #[deny(clippy::eq_op)] on by default @@ -9,7 +9,7 @@ error: equal expressions as operands to `/` error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:13:15 | -13 | let nan = 0.0 / 0.0; +LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ | = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` @@ -18,13 +18,13 @@ error: constant division of 0.0 with 0.0 will always result in NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:14:19 | -14 | let f64_nan = 0.0 / 0.0f64; +LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:14:19 | -14 | let f64_nan = 0.0 / 0.0f64; +LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN @@ -32,13 +32,13 @@ error: constant division of 0.0 with 0.0 will always result in NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:15:25 | -15 | let other_f64_nan = 0.0f64 / 0.0; +LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:15:25 | -15 | let other_f64_nan = 0.0f64 / 0.0; +LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN @@ -46,13 +46,13 @@ error: constant division of 0.0 with 0.0 will always result in NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:16:28 | -16 | let one_more_f64_nan = 0.0f64 / 0.0f64; +LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:16:28 | -16 | let one_more_f64_nan = 0.0f64 / 0.0f64; +LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ | = help: Consider using `std::f64::NAN` if you would like a constant representing NaN diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 15b27c7c0ad..5aa5e275ee6 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -1,7 +1,7 @@ error: `0 as *const _` detected. Consider using `ptr::null()` --> $DIR/zero_ptr.rs:12:13 | -12 | let x = 0 as *const usize; +LL | let x = 0 as *const usize; | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::zero-ptr` implied by `-D warnings` @@ -9,7 +9,7 @@ error: `0 as *const _` detected. Consider using `ptr::null()` error: `0 as *mut _` detected. Consider using `ptr::null_mut()` --> $DIR/zero_ptr.rs:13:13 | -13 | let y = 0 as *mut f64; +LL | let y = 0 as *mut f64; | ^^^^^^^^^^^^^ error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 909bfd3cd843a8a9fea1db1ddf52fc34744b14ac Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 28 Dec 2018 12:29:34 +0100 Subject: Match on ast/hir::ExprKind::Err --- clippy_lints/src/loops.rs | 3 ++- clippy_lints/src/utils/author.rs | 3 +++ clippy_lints/src/utils/hir_utils.rs | 1 + clippy_lints/src/utils/inspector.rs | 3 +++ clippy_lints/src/utils/sugg.rs | 6 ++++-- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8664061fb7a..8bf509844ac 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -756,7 +756,8 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult { | ExprKind::Closure(_, _, _, _, _) | ExprKind::InlineAsm(_, _, _) | ExprKind::Path(_) - | ExprKind::Lit(_) => NeverLoopResult::Otherwise, + | ExprKind::Lit(_) + | ExprKind::Err => NeverLoopResult::Otherwise, } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 7e09eae1e93..9eb543db6d4 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -504,6 +504,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, + ExprKind::Err => { + println!("Err = {}", current); + }, } } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 73169414a02..d7a57945658 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -615,6 +615,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_name(l.ident.name); } }, + ExprKind::Err => {}, } } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 93a5845ad45..b9a58c51706 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -347,6 +347,9 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { println!("{}repeat count:", ind); print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1); }, + hir::ExprKind::Err => { + println!("{}Err", ind); + }, } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 66f18b51f21..f087b73bef4 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -79,7 +79,8 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Ret(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Tup(..) - | hir::ExprKind::While(..) => Sugg::NonParen(snippet), + | hir::ExprKind::While(..) + | hir::ExprKind::Err => Sugg::NonParen(snippet), hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet), hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet), @@ -158,7 +159,8 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Tup(..) | ast::ExprKind::Array(..) | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet), + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Err => Sugg::NonParen(snippet), ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet), ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotEq, snippet), ast::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet), -- cgit 1.4.1-3-g733a5 From d127aed737e6efdf10e6f925f4a82db4dd30c399 Mon Sep 17 00:00:00 2001 From: Russell Greene Date: Mon, 17 Dec 2018 16:25:49 -0700 Subject: Merge new_without_default_derive into new_without_default --- CHANGELOG.md | 1 - README.md | 2 +- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/new_without_default.rs | 44 +++++++------- tests/ui/methods.rs | 1 - tests/ui/methods.stderr | 100 ++++++++++++++++---------------- tests/ui/new_without_default.rs | 4 +- tests/ui/new_without_default.stderr | 4 +- tests/ui/rename.rs | 9 +++ tests/ui/rename.stderr | 8 ++- 10 files changed, 94 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 606f16061ac..efa637b185c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -785,7 +785,6 @@ All notable changes to this project will be documented in this file. [`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop [`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self [`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default -[`new_without_default_derive`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default_derive [`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool diff --git a/README.md b/README.md index be24f1be827..626b589b5f3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8ce5861a939..5139e167cc0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -701,7 +701,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, - new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, no_effect::NO_EFFECT, no_effect::UNNECESSARY_OPERATION, non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, @@ -837,7 +836,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { mut_reference::UNNECESSARY_MUT_PASSED, neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, - new_without_default::NEW_WITHOUT_DEFAULT_DERIVE, non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, non_expressive_names::MANY_SINGLE_CHAR_NAMES, ok_if_let::IF_LET_SOME_RESULT, @@ -1032,6 +1030,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { pub fn register_renamed(ls: &mut rustc::lint::LintStore) { ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions"); + ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); } // only exists to let the dogfood integration test works. diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 86c345b025c..bb8e0b878a2 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -24,6 +24,11 @@ use if_chain::if_chain; /// implementation of /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html). /// +/// It detects both the case when a manual +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// implementation is required and also when it can be created with +/// `#[derive(Default)] +/// /// **Why is this bad?** The user might expect to be able to use /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the /// type can be constructed without arguments. @@ -54,27 +59,24 @@ use if_chain::if_chain; /// } /// ``` /// -/// You can also have `new()` call `Default::default()`. -declare_clippy_lint! { - pub NEW_WITHOUT_DEFAULT, - style, - "`fn new() -> Self` method without `Default` implementation" -} - -/// **What it does:** Checks for types with a `fn new() -> Self` method -/// and no implementation of -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html), -/// where the `Default` can be derived by `#[derive(Default)]`. +/// Or, if +/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) +/// can be derived by `#[derive(Default)]`: /// -/// **Why is this bad?** The user might expect to be able to use -/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the -/// type can be constructed without arguments. +/// ```rust +/// struct Foo; /// -/// **Known problems:** Hopefully none. +/// impl Foo { +/// fn new() -> Self { +/// Foo +/// } +/// } +/// ``` /// -/// **Example:** +/// Instead, use: /// /// ```rust +/// #[derive(Default)] /// struct Foo; /// /// impl Foo { @@ -84,11 +86,11 @@ declare_clippy_lint! { /// } /// ``` /// -/// Just prepend `#[derive(Default)]` before the `struct` definition. +/// You can also have `new()` call `Default::default()`. declare_clippy_lint! { - pub NEW_WITHOUT_DEFAULT_DERIVE, + pub NEW_WITHOUT_DEFAULT, style, - "`fn new() -> Self` without `#[derive]`able `Default` implementation" + "`fn new() -> Self` method without `Default` implementation" } #[derive(Clone, Default)] @@ -98,7 +100,7 @@ pub struct NewWithoutDefault { impl LintPass for NewWithoutDefault { fn get_lints(&self) -> LintArray { - lint_array!(NEW_WITHOUT_DEFAULT, NEW_WITHOUT_DEFAULT_DERIVE) + lint_array!(NEW_WITHOUT_DEFAULT) } } @@ -167,7 +169,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { span_lint_node_and_then( cx, - NEW_WITHOUT_DEFAULT_DERIVE, + NEW_WITHOUT_DEFAULT, id, impl_item.span, &format!( diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 877026d4bb1..ebf71f67a00 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -14,7 +14,6 @@ clippy::print_stdout, clippy::non_ascii_literal, clippy::new_without_default, - clippy::new_without_default_derive, clippy::missing_docs_in_private_items, clippy::needless_pass_by_value, clippy::default_trait_access, diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 4f445c924d2..b0b693f3e16 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:38:5 + --> $DIR/methods.rs:37:5 | LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn add(self, other: T) -> T { self } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:49:17 + --> $DIR/methods.rs:48:17 | LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ @@ -15,19 +15,19 @@ LL | fn into_u16(&self) -> u16 { 0 } = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:51:21 + --> $DIR/methods.rs:50:21 | LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:53:12 + --> $DIR/methods.rs:52:12 | LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:121:13 + --> $DIR/methods.rs:120:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -39,7 +39,7 @@ LL | | .unwrap_or(0); // should lint even though this call is on = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:125:13 + --> $DIR/methods.rs:124:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -49,7 +49,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:129:13 + --> $DIR/methods.rs:128:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -59,7 +59,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:134:13 + --> $DIR/methods.rs:133:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:136:13 + --> $DIR/methods.rs:135:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -77,7 +77,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:140:13 + --> $DIR/methods.rs:139:13 | LL | let _ = opt | _____________^ @@ -88,7 +88,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:148:13 + --> $DIR/methods.rs:147:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -100,7 +100,7 @@ LL | | .unwrap_or_else(|| 0); // should lint even though this cal = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:152:13 + --> $DIR/methods.rs:151:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -110,7 +110,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:156:13 + --> $DIR/methods.rs:155:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -120,7 +120,7 @@ LL | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:165:13 + --> $DIR/methods.rs:164:13 | LL | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` @@ -128,7 +128,7 @@ LL | let _ = opt.map_or(None, |x| Some(x + 1)); = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:167:13 + --> $DIR/methods.rs:166:13 | LL | let _ = opt.map_or(None, |x| { | _____________^ @@ -144,7 +144,7 @@ LL | }); | error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:180:13 + --> $DIR/methods.rs:179:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -156,7 +156,7 @@ LL | | .unwrap_or_else(|e| 0); // should lint even though this ca = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:184:13 + --> $DIR/methods.rs:183:13 | LL | let _ = res.map(|x| { | _____________^ @@ -166,7 +166,7 @@ LL | | ).unwrap_or_else(|e| 0); | |_____________________________________^ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:188:13 + --> $DIR/methods.rs:187:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -176,7 +176,7 @@ LL | | ); | |_________________^ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:251:13 + --> $DIR/methods.rs:250:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:254:13 + --> $DIR/methods.rs:253:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -195,7 +195,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:269:13 + --> $DIR/methods.rs:268:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:272:13 + --> $DIR/methods.rs:271:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -214,7 +214,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:278:13 + --> $DIR/methods.rs:277:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:281:13 + --> $DIR/methods.rs:280:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -232,7 +232,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:287:13 + --> $DIR/methods.rs:286:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:290:13 + --> $DIR/methods.rs:289:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -250,7 +250,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:325:22 + --> $DIR/methods.rs:324:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -258,73 +258,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:328:5 + --> $DIR/methods.rs:327:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:331:21 + --> $DIR/methods.rs:330:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:334:14 + --> $DIR/methods.rs:333:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:337:19 + --> $DIR/methods.rs:336:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:340:5 + --> $DIR/methods.rs:339:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:343:5 + --> $DIR/methods.rs:342:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:346:14 + --> $DIR/methods.rs:345:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:351:21 + --> $DIR/methods.rs:350:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:354:19 + --> $DIR/methods.rs:353:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:357:21 + --> $DIR/methods.rs:356:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:360:21 + --> $DIR/methods.rs:359:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:371:23 + --> $DIR/methods.rs:370:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -332,43 +332,43 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:372:26 + --> $DIR/methods.rs:371:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:373:31 + --> $DIR/methods.rs:372:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:374:29 + --> $DIR/methods.rs:373:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:379:23 + --> $DIR/methods.rs:378:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:382:26 + --> $DIR/methods.rs:381:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:385:29 + --> $DIR/methods.rs:384:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:397:13 + --> $DIR/methods.rs:396:13 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,25 +376,25 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:398:13 + --> $DIR/methods.rs:397:13 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:399:13 + --> $DIR/methods.rs:398:13 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:400:14 + --> $DIR/methods.rs:399:14 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:409:13 + --> $DIR/methods.rs:408:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index efb8904dc97..07d0a6bb05e 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -9,7 +9,7 @@ #![feature(const_fn)] #![allow(dead_code)] -#![warn(clippy::new_without_default, clippy::new_without_default_derive)] +#![warn(clippy::new_without_default)] pub struct Foo; @@ -151,7 +151,7 @@ impl Allow { pub struct AllowDerive; impl AllowDerive { - #[allow(clippy::new_without_default_derive)] + #[allow(clippy::new_without_default)] pub fn new() -> Self { unimplemented!() } diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 1b35b72a82e..9157f60a7e4 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -6,7 +6,7 @@ LL | | Foo LL | | } | |_____^ | - = note: `-D clippy::new-without-default-derive` implied by `-D warnings` + = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | LL | #[derive(Default)] @@ -31,8 +31,6 @@ LL | / pub fn new() -> LtKo<'c> { LL | | unimplemented!() LL | | } | |_____^ - | - = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | LL | impl Default for LtKo<'c> { diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 8d76a2d4586..eb08f1de63d 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -11,3 +11,12 @@ #[warn(clippy::stutter)] fn main() {} + +#[warn(clippy::new_without_default_derive)] +struct Foo; + +impl Foo { + fn new() -> Self { + Foo + } +} diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 1efc66d442f..074e3527e8a 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -14,5 +14,11 @@ LL | #[warn(clippy::stutter)] | = note: `-D renamed-and-removed-lints` implied by `-D warnings` -error: aborting due to 2 previous errors +error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` + --> $DIR/rename.rs:15:8 + | +LL | #[warn(clippy::new_without_default_derive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 8be7050b740c0e48a921e01446d5ec0e9a35881d Mon Sep 17 00:00:00 2001 From: Peter Fürstenau Date: Fri, 28 Dec 2018 20:52:46 +0100 Subject: Fix formatting --- tests/ui/question_mark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 880c163e833..7e749d164ca 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -19,7 +19,7 @@ fn some_other_func(a: Option) -> Option { if a.is_none() { return None; } else { - return Some(0); + return Some(0); } unreachable!() } -- cgit 1.4.1-3-g733a5 From bd74fdce2288746b2a4db678830447385e3319d2 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 16:26:03 +0100 Subject: Use WIP branch for compiletest_rs --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 359a6e43bdb..13d081e92cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6.2" -compiletest_rs = "0.3.16" +compiletest_rs = { git = "https://github.com/phansch/compiletest-rs.git", branch = "add_rustfix_support" } lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } -- cgit 1.4.1-3-g733a5 From 2ccfd52f5dd0774cf17d6c5459460cc9fcea6907 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 16:18:16 +0100 Subject: Run rustfix on first UI test --- tests/ui/unnecessary_ref.fixed | 23 +++++++++++++++++++++++ tests/ui/unnecessary_ref.rs | 3 ++- tests/ui/unnecessary_ref.stderr | 4 ++-- 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/ui/unnecessary_ref.fixed diff --git a/tests/ui/unnecessary_ref.fixed b/tests/ui/unnecessary_ref.fixed new file mode 100644 index 00000000000..32ad6d72054 --- /dev/null +++ b/tests/ui/unnecessary_ref.fixed @@ -0,0 +1,23 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + + +#![feature(stmt_expr_attributes)] + +struct Outer { + inner: u32, +} + +#[deny(clippy::ref_in_deref)] +fn main() { + let outer = Outer { inner: 0 }; + let inner = outer.inner.inner; +} diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 31aa367e506..4ed47cf8b5d 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -7,7 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_attributes)] +// run-rustfix + #![feature(stmt_expr_attributes)] struct Outer { diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index 77503026bde..dc221f9921e 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,11 +1,11 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:20:17 + --> $DIR/unnecessary_ref.rs:21:17 | LL | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer.inner` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:17:8 + --> $DIR/unnecessary_ref.rs:18:8 | LL | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 7d9bf99df14e04ab2d1158e3f06ecc3291145bf0 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 16:57:06 +0100 Subject: Update .fixed files via update-references.sh --- tests/ui/update-references.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ui/update-references.sh b/tests/ui/update-references.sh index aa99d35f7aa..d6995985a3b 100755 --- a/tests/ui/update-references.sh +++ b/tests/ui/update-references.sh @@ -34,6 +34,7 @@ shift while [[ "$1" != "" ]]; do STDERR_NAME="${1/%.rs/.stderr}" STDOUT_NAME="${1/%.rs/.stdout}" + FIXED_NAME="${1/%.rs/.fixed}" shift if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then @@ -45,6 +46,11 @@ while [[ "$1" != "" ]]; do echo updating $MYDIR/$STDERR_NAME cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME fi + if [ -f $BUILD_DIR/$FIXED_NAME ] && \ + ! (diff $BUILD_DIR/$FIXED_NAME $MYDIR/$FIXED_NAME >& /dev/null); then + echo updating $MYDIR/$FIXED_NAME + cp $BUILD_DIR/$FIXED_NAME $MYDIR/$FIXED_NAME + fi done -- cgit 1.4.1-3-g733a5 From 3f978afe8d2260e29dbc593fa294ccaa39b0df32 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 17:01:51 +0100 Subject: Update CONTRIBUTING.md for rustfix tests --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94120a3771a..df216a8fbc9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,6 +156,15 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running `cargo test`) and check whether the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +If the lint you are working on is making use of structured suggestions, the +test file should include a `// run-rustfix` comment at the top. This will +additionally run [rustfix](https://github.com/rust-lang-nursery/rustfix) for +that test. Rustfix will apply the suggestions from the lint to the code of the +test file and compare that to the contents of a `.fixed` file. + +Use `tests/ui/update-all-references.sh` to automatically generate the +`.fixed` file after running `cargo test`. + ### Running rustfmt [Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according -- cgit 1.4.1-3-g733a5 From 298aedf2f874ed86a68966c7b722918b1e2bde0a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 9 Dec 2018 17:25:45 +0100 Subject: Fix suggestion for unnecessary_ref lint --- clippy_lints/src/reference.rs | 8 ++------ tests/ui/unnecessary_ref.fixed | 4 ++-- tests/ui/unnecessary_ref.rs | 1 + tests/ui/unnecessary_ref.stderr | 6 +++--- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 2e35719d466..d76fa0c38b9 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -98,7 +98,7 @@ impl LintPass for DerefPass { impl EarlyLintPass for DerefPass { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { - if let ExprKind::Field(ref object, ref field_name) = e.node; + if let ExprKind::Field(ref object, _) = e.node; if let ExprKind::Paren(ref parened) = object.node; if let ExprKind::AddrOf(_, ref inner) = parened.node; then { @@ -109,11 +109,7 @@ impl EarlyLintPass for DerefPass { object.span, "Creating a reference that is immediately dereferenced.", "try this", - format!( - "{}.{}", - snippet_with_applicability(cx, inner.span, "_", &mut applicability), - snippet_with_applicability(cx, field_name.span, "_", &mut applicability) - ), + snippet_with_applicability(cx, inner.span, "_", &mut applicability).to_string(), applicability, ); } diff --git a/tests/ui/unnecessary_ref.fixed b/tests/ui/unnecessary_ref.fixed index 32ad6d72054..3617641a116 100644 --- a/tests/ui/unnecessary_ref.fixed +++ b/tests/ui/unnecessary_ref.fixed @@ -9,8 +9,8 @@ // run-rustfix - #![feature(stmt_expr_attributes)] +#![allow(unused_variables)] struct Outer { inner: u32, @@ -19,5 +19,5 @@ struct Outer { #[deny(clippy::ref_in_deref)] fn main() { let outer = Outer { inner: 0 }; - let inner = outer.inner.inner; + let inner = outer.inner; } diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 4ed47cf8b5d..48101c87a54 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -10,6 +10,7 @@ // run-rustfix #![feature(stmt_expr_attributes)] +#![allow(unused_variables)] struct Outer { inner: u32, diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index dc221f9921e..863a6389e7f 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,11 +1,11 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:21:17 + --> $DIR/unnecessary_ref.rs:22:17 | LL | let inner = (&outer).inner; - | ^^^^^^^^ help: try this: `outer.inner` + | ^^^^^^^^ help: try this: `outer` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:18:8 + --> $DIR/unnecessary_ref.rs:19:8 | LL | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 44bf8e0c3d992c21a29c9e8be358dc9eb17cd031 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 00:40:48 +0100 Subject: Remove unsafe from consts clippy lints --- clippy_lints/src/consts.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 761630da376..04109cb63df 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -23,7 +23,6 @@ use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::mem; use std::rc::Rc; /// A `LitKind`-like enum to fold constant `Expr`s into. @@ -61,14 +60,14 @@ impl PartialEq for Constant { (&Constant::F64(l), &Constant::F64(r)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them - // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs - unsafe { mem::transmute::(l) == mem::transmute::(r) } + // to_bits is required to catch non-matching 0.0, -0.0, and NaNs + l.to_bits() == r.to_bits() }, (&Constant::F32(l), &Constant::F32(r)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them - // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs - unsafe { mem::transmute::(f64::from(l)) == mem::transmute::(f64::from(r)) } + // to_bits is required to catch non-matching 0.0, -0.0, and NaNs + f64::from(l).to_bits() == f64::from(r).to_bits() }, (&Constant::Bool(l), &Constant::Bool(r)) => l == r, (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => { @@ -99,10 +98,10 @@ impl Hash for Constant { i.hash(state); }, Constant::F32(f) => { - unsafe { mem::transmute::(f64::from(f)) }.hash(state); + f64::from(f).to_bits().hash(state); }, Constant::F64(f) => { - unsafe { mem::transmute::(f) }.hash(state); + f.to_bits().hash(state); }, Constant::Bool(b) => { b.hash(state); -- cgit 1.4.1-3-g733a5 From f4cf82ce7d05f5eccb616a3dbb060939e9b0fe8d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 29 Dec 2018 07:59:33 +0200 Subject: Update README local run command to remove syspath Since #3257 was reverted, including the sysroot in RUSTFLAGS gives the error `Option 'sysroot' given more than once` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be24f1be827..8ca10da416d 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ To have cargo compile your crate with Clippy without Clippy installation in your code, you can use: ```terminal -RUSTFLAGS=--sysroot=`rustc --print sysroot` cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml +cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` *[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):* -- cgit 1.4.1-3-g733a5 From 847898f18f67e3009db0715d1bb3f083974c7b27 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 15:14:04 +0100 Subject: Mark writes to constants as side-effect-less --- clippy_lints/src/no_effect.rs | 14 +++++++++ tests/ui/no_effect.rs | 20 +++++++++++++ tests/ui/no_effect.stderr | 70 +++++++++++++++++++++++++++---------------- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index f30da9c909d..3dd5c10c939 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -98,6 +98,20 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { false } }, + ExprKind::Assign(ref left, ref right) => { + if has_no_effect(cx, left) { + let mut left = left; + while let ExprKind::Field(f, _) = &left.node { + left = f; + } + if let ExprKind::Path(qpath) = &left.node { + if let Def::Const(..) = cx.tables.qpath_def(qpath, left.hir_id) { + return has_no_effect(cx, right); + } + } + } + false + }, _ => false, } } diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 6b51c50dcde..9af51dcf6f4 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -67,6 +67,17 @@ unsafe fn unsafe_fn() -> i32 { 0 } +struct A(i32); +struct B { + field: i32, +} +struct C { + b: B, +} +const A_CONST: A = A(1); +const B: B = B { field: 1 }; +const C: C = C { b: B { field: 1 } }; + fn main() { let s = get_struct(); let s2 = get_struct(); @@ -99,6 +110,9 @@ fn main() { || x += 5; let s: String = "foo".into(); FooString { s: s }; + A_CONST.0 = 2; + B.field = 2; + C.b.field = 2; // Do not warn get_number(); @@ -108,4 +122,10 @@ fn main() { DropTuple(0); DropEnum::Tuple(0); DropEnum::Struct { field: 0 }; + let mut a_mut = A(1); + a_mut.0 = 2; + let mut b_mut = B { field: 1 }; + b_mut.field = 2; + let mut c_mut = C { b: B { field: 1 } }; + c_mut.b.field = 2; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index cc3b069f0b5..6ddc891ec28 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:85:5 | LL | 0; | ^^ @@ -7,148 +7,166 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:86:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:87:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:88:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:89:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:90:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:91:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:92:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:93:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:94:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:95:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:96:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:97:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:87:5 + --> $DIR/no_effect.rs:98:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:99:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:89:5 + --> $DIR/no_effect.rs:100:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:101:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:102:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:104:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:105:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:106:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:107:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:108:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:110:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:112:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 25 previous errors +error: statement with no effect + --> $DIR/no_effect.rs:113:5 + | +LL | A_CONST.0 = 2; + | ^^^^^^^^^^^^^^ + +error: statement with no effect + --> $DIR/no_effect.rs:114:5 + | +LL | B.field = 2; + | ^^^^^^^^^^^^ + +error: statement with no effect + --> $DIR/no_effect.rs:115:5 + | +LL | C.b.field = 2; + | ^^^^^^^^^^^^^^ + +error: aborting due to 28 previous errors -- cgit 1.4.1-3-g733a5 From 9fe8a3e52ef42ecf488f86c5fabc6af54708d216 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 15:34:15 +0100 Subject: Support array indexing expressions in unused write to a constant --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/no_effect.rs | 2 +- tests/ui/no_effect.rs | 7 +++++ tests/ui/no_effect.stderr | 64 +++++++++++++++++++++++-------------------- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8ce5861a939..560b1f61850 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -20,6 +20,7 @@ #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] #![feature(try_from)] +#![feature(if_while_or_patterns)] // FIXME: switch to something more ergonomic here, once available. // (currently there is no way to opt into sysroot crates w/o `extern crate`) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 3dd5c10c939..cab60509a78 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -101,7 +101,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { ExprKind::Assign(ref left, ref right) => { if has_no_effect(cx, left) { let mut left = left; - while let ExprKind::Field(f, _) = &left.node { + while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &left.node { left = f; } if let ExprKind::Path(qpath) = &left.node { diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 9af51dcf6f4..8431f00e445 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -74,9 +74,13 @@ struct B { struct C { b: B, } +struct D { + arr: [i32; 1], +} const A_CONST: A = A(1); const B: B = B { field: 1 }; const C: C = C { b: B { field: 1 } }; +const D: D = D { arr: [1] }; fn main() { let s = get_struct(); @@ -113,6 +117,7 @@ fn main() { A_CONST.0 = 2; B.field = 2; C.b.field = 2; + D.arr[0] = 2; // Do not warn get_number(); @@ -128,4 +133,6 @@ fn main() { b_mut.field = 2; let mut c_mut = C { b: B { field: 1 } }; c_mut.b.field = 2; + let mut d_mut = D { arr: [1] }; + d_mut.arr[0] = 2; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 6ddc891ec28..b6aab53e50f 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:89:5 | LL | 0; | ^^ @@ -7,166 +7,172 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:90:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:87:5 + --> $DIR/no_effect.rs:91:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:92:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:89:5 + --> $DIR/no_effect.rs:93:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:94:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:95:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:96:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:97:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:98:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:99:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:100:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:101:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:102:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:103:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:104:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:105:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:106:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:108:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:109:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:110:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:111:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:112:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:114:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:116:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:117:5 | LL | A_CONST.0 = 2; | ^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:118:5 | LL | B.field = 2; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:119:5 | LL | C.b.field = 2; | ^^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: statement with no effect + --> $DIR/no_effect.rs:120:5 + | +LL | D.arr[0] = 2; + | ^^^^^^^^^^^^^ + +error: aborting due to 29 previous errors -- cgit 1.4.1-3-g733a5 From 3f62fc3a7e2539e6bfeccbf1cce36ed83e8ab18a Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 16:04:45 +0100 Subject: Remove crate:: prefixes from crate paths This is somewhat misleading, as those are actually external crates, and don't need a crate:: prefix. --- clippy_lints/src/approx_const.rs | 10 +++--- clippy_lints/src/arithmetic.rs | 8 ++--- clippy_lints/src/assign_ops.rs | 14 ++++---- clippy_lints/src/attrs.rs | 18 +++++----- clippy_lints/src/bit_mask.rs | 12 +++---- clippy_lints/src/blacklisted_name.rs | 6 ++-- clippy_lints/src/block_in_if_condition.rs | 8 ++--- clippy_lints/src/booleans.rs | 16 ++++----- clippy_lints/src/bytecount.rs | 12 +++---- clippy_lints/src/cargo_common_metadata.rs | 6 ++-- clippy_lints/src/collapsible_if.rs | 8 ++--- clippy_lints/src/const_static_lifetime.rs | 8 ++--- clippy_lints/src/consts.rs | 22 ++++++------- clippy_lints/src/copies.rs | 12 +++---- clippy_lints/src/copy_iterator.rs | 6 ++-- clippy_lints/src/cyclomatic_complexity.rs | 16 ++++----- clippy_lints/src/default_trait_access.rs | 10 +++--- clippy_lints/src/derive.rs | 10 +++--- clippy_lints/src/doc.rs | 10 +++--- clippy_lints/src/double_comparison.rs | 10 +++--- clippy_lints/src/double_parens.rs | 6 ++-- clippy_lints/src/drop_forget_ref.rs | 8 ++--- clippy_lints/src/duration_subsec.rs | 10 +++--- clippy_lints/src/else_if_without_else.rs | 6 ++-- clippy_lints/src/empty_enum.rs | 6 ++-- clippy_lints/src/entry.rs | 12 +++---- clippy_lints/src/enum_clike.rs | 16 ++++----- clippy_lints/src/enum_glob_use.rs | 12 +++---- clippy_lints/src/enum_variants.rs | 10 +++--- clippy_lints/src/eq_op.rs | 8 ++--- clippy_lints/src/erasing_op.rs | 8 ++--- clippy_lints/src/escape.rs | 22 ++++++------- clippy_lints/src/eta_reduction.rs | 10 +++--- clippy_lints/src/eval_order_dependence.rs | 12 +++---- clippy_lints/src/excessive_precision.rs | 14 ++++---- clippy_lints/src/explicit_write.rs | 10 +++--- clippy_lints/src/fallible_impl_from.rs | 14 ++++---- clippy_lints/src/format.rs | 12 +++---- clippy_lints/src/formatting.rs | 8 ++--- clippy_lints/src/functions.rs | 20 ++++++------ clippy_lints/src/identity_conversion.rs | 10 +++--- clippy_lints/src/identity_op.rs | 10 +++--- clippy_lints/src/if_not_else.rs | 6 ++-- clippy_lints/src/implicit_return.rs | 10 +++--- clippy_lints/src/indexing_slicing.rs | 10 +++--- clippy_lints/src/infallible_destructuring_match.rs | 8 ++--- clippy_lints/src/infinite_iter.rs | 6 ++-- clippy_lints/src/inherent_impl.rs | 10 +++--- clippy_lints/src/inline_fn_without_body.rs | 10 +++--- clippy_lints/src/int_plus_one.rs | 8 ++--- clippy_lints/src/invalid_ref.rs | 8 ++--- clippy_lints/src/items_after_statements.rs | 6 ++-- clippy_lints/src/large_enum_variant.rs | 10 +++--- clippy_lints/src/len_zero.rs | 20 ++++++------ clippy_lints/src/let_if_seq.rs | 14 ++++---- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/lifetimes.rs | 16 ++++----- clippy_lints/src/literal_representation.rs | 10 +++--- clippy_lints/src/loops.rs | 36 ++++++++++---------- clippy_lints/src/map_clone.rs | 12 +++---- clippy_lints/src/map_unit_fn.rs | 12 +++---- clippy_lints/src/matches.rs | 14 ++++---- clippy_lints/src/mem_discriminant.rs | 8 ++--- clippy_lints/src/mem_forget.rs | 6 ++-- clippy_lints/src/mem_replace.rs | 8 ++--- clippy_lints/src/methods/mod.rs | 18 +++++----- clippy_lints/src/methods/unnecessary_filter_map.rs | 10 +++--- clippy_lints/src/minmax.rs | 6 ++-- clippy_lints/src/misc.rs | 16 ++++----- clippy_lints/src/misc_early.rs | 14 ++++---- clippy_lints/src/missing_doc.rs | 14 ++++---- clippy_lints/src/missing_inline.rs | 14 ++++---- clippy_lints/src/multiple_crate_versions.rs | 6 ++-- clippy_lints/src/mut_mut.rs | 12 +++---- clippy_lints/src/mut_reference.rs | 10 +++--- clippy_lints/src/mutex_atomic.rs | 10 +++--- clippy_lints/src/needless_bool.rs | 12 +++---- clippy_lints/src/needless_borrow.rs | 14 ++++---- clippy_lints/src/needless_borrowed_ref.rs | 8 ++--- clippy_lints/src/needless_continue.rs | 8 ++--- clippy_lints/src/needless_pass_by_value.rs | 28 ++++++++-------- clippy_lints/src/needless_update.rs | 8 ++--- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 6 ++-- clippy_lints/src/neg_multiply.rs | 8 ++--- clippy_lints/src/new_without_default.rs | 16 ++++----- clippy_lints/src/no_effect.rs | 10 +++--- clippy_lints/src/non_copy_const.rs | 18 +++++----- clippy_lints/src/non_expressive_names.rs | 14 ++++---- clippy_lints/src/ok_if_let.rs | 6 ++-- clippy_lints/src/open_options.rs | 10 +++--- clippy_lints/src/overflow_check_conditional.rs | 6 ++-- clippy_lints/src/panic_unimplemented.rs | 12 +++---- clippy_lints/src/partialeq_ne_impl.rs | 6 ++-- clippy_lints/src/precedence.rs | 14 ++++---- clippy_lints/src/ptr.rs | 18 +++++----- clippy_lints/src/ptr_offset_with_cast.rs | 4 +-- clippy_lints/src/question_mark.rs | 12 +++---- clippy_lints/src/ranges.rs | 12 +++---- clippy_lints/src/redundant_clone.rs | 30 ++++++++--------- clippy_lints/src/redundant_field_names.rs | 8 ++--- clippy_lints/src/redundant_pattern_matching.rs | 12 +++---- clippy_lints/src/reference.rs | 8 ++--- clippy_lints/src/regex.rs | 12 +++---- clippy_lints/src/replace_consts.rs | 10 +++--- clippy_lints/src/returns.rs | 14 ++++---- clippy_lints/src/serde_api.rs | 6 ++-- clippy_lints/src/shadow.rs | 12 +++---- clippy_lints/src/slow_vector_initialization.rs | 14 ++++---- clippy_lints/src/strings.rs | 12 +++---- clippy_lints/src/suspicious_trait_impl.rs | 10 +++--- clippy_lints/src/swap.rs | 10 +++--- clippy_lints/src/temporary_assignment.rs | 6 ++-- clippy_lints/src/transmute.rs | 12 +++---- clippy_lints/src/trivially_copy_pass_by_ref.rs | 24 +++++++------- clippy_lints/src/types.rs | 36 ++++++++++---------- clippy_lints/src/unicode.rs | 10 +++--- clippy_lints/src/unsafe_removed_from_name.rs | 10 +++--- clippy_lints/src/unused_io_amount.rs | 6 ++-- clippy_lints/src/unused_label.rs | 16 ++++----- clippy_lints/src/unwrap.rs | 12 +++---- clippy_lints/src/use_self.rs | 16 ++++----- clippy_lints/src/utils/author.rs | 14 ++++---- clippy_lints/src/utils/comparisons.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/higher.rs | 6 ++-- clippy_lints/src/utils/hir_utils.rs | 10 +++--- clippy_lints/src/utils/inspector.rs | 10 +++--- clippy_lints/src/utils/internal_lints.rs | 22 ++++++------- clippy_lints/src/utils/mod.rs | 38 +++++++++++----------- clippy_lints/src/utils/ptr.rs | 10 +++--- clippy_lints/src/utils/sugg.rs | 30 ++++++++--------- clippy_lints/src/utils/usage.rs | 20 ++++++------ clippy_lints/src/vec.rs | 12 +++---- clippy_lints/src/wildcard_dependencies.rs | 6 ++-- clippy_lints/src/write.rs | 14 ++++---- clippy_lints/src/zero_div_zero.rs | 6 ++-- tests/matches.rs | 2 +- 137 files changed, 803 insertions(+), 803 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index bf6355c4a41..4d502a6d093 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::{FloatTy, Lit, LitKind}; -use crate::syntax::symbol; use crate::utils::span_lint; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; use std::f64::consts as f64; +use syntax::ast::{FloatTy, Lit, LitKind}; +use syntax::symbol; /// **What it does:** Checks for floating point literals that approximate /// constants which are defined in diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 0b2c00b9b58..51d17b38882 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; use crate::utils::span_lint; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::Span; /// **What it does:** Checks for plain integer arithmetic. /// diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index f69c66a3d35..a595050d0c0 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; use crate::utils::{higher, sugg}; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast; /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` /// patterns. @@ -240,7 +240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } fn is_commutative(op: hir::BinOpKind) -> bool { - use crate::rustc::hir::BinOpKind::*; + use rustc::hir::BinOpKind::*; match op { Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 7310e35116f..08333994fa6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -10,21 +10,21 @@ //! checks for attributes use crate::reexport::*; -use crate::rustc::hir::*; -use crate::rustc::lint::{ - CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, -}; -use crate::rustc::ty::{self, TyCtxt}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; -use crate::syntax::source_map::Span; use crate::utils::{ in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{ + CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, +}; +use rustc::ty::{self, TyCtxt}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use semver::Version; +use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use syntax::source_map::Span; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index b15ce871c32..abdd624146c 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -8,15 +8,15 @@ // except according to those terms. use crate::consts::{constant, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; -use crate::syntax::source_map::Span; use crate::utils::sugg::Sugg; use crate::utils::{span_lint, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; +use syntax::source_map::Span; /// **What it does:** Checks for incompatible bit masks in comparisons. /// diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index bf311b3fd56..ce7da419497 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for usage of blacklisted names for variables, such /// as `foo`. diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 825bf789a69..b68b43354f7 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::*; use matches::matches; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for `if` conditions that use blocks to contain an /// expression. diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 9f58cb6582e..844f9fb8865 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::*; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::thin_vec::ThinVec; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; -use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; use crate::utils::{ get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_then, SpanlessEq, }; +use rustc::hir::intravisit::*; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::thin_vec::ThinVec; +use rustc_errors::Applicability; +use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; +use syntax::source_map::{dummy_spanned, Span, DUMMY_SP}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 5d81e51422d..0f2062d9e0f 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{Name, UintTy}; use crate::utils::{ contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::{Name, UintTy}; /// **What it does:** Checks for naive byte counts /// diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 4d15944d317..9f396b61330 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -9,10 +9,10 @@ //! lint on missing cargo common metadata -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index a4d834da13f..ae613d70240 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -21,14 +21,14 @@ //! //! This lint is **warn** by default -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; use if_chain::if_chain; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; -use crate::rustc_errors::Applicability; use crate::utils::sugg::Sugg; use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; +use rustc_errors::Applicability; /// **What it does:** Checks for nested `if` statements which can be collapsed /// by `&&`-combining their conditions and for `else { if ... }` expressions diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index ecf3bb1f96e..a7509dae3d5 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; use crate::utils::{in_macro, snippet, span_lint_and_then}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::*; /// **What it does:** Checks for constants with an explicit `'static` lifetime. /// diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 04109cb63df..a1fe13e4962 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -10,20 +10,20 @@ #![allow(clippy::float_cmp)] -use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; -use crate::rustc::lint::LateContext; -use crate::rustc::ty::subst::{Subst, Substs}; -use crate::rustc::ty::{self, Instance, Ty, TyCtxt}; -use crate::rustc::{bug, span_bug}; -use crate::syntax::ast::{FloatTy, LitKind}; -use crate::syntax::ptr::P; use crate::utils::{clip, sext, unsext}; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::lint::LateContext; +use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::{self, Instance, Ty, TyCtxt}; +use rustc::{bug, span_bug}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; use std::rc::Rc; +use syntax::ast::{FloatTy, LitKind}; +use syntax::ptr::P; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -151,7 +151,7 @@ impl Constant { /// parse a `LitKind` to a `Constant` pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { - use crate::syntax::ast::*; + use syntax::ast::*; match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), @@ -286,7 +286,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// lookup a possibly constant expression from a ExprKind::Path fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { - use crate::rustc::mir::interpret::GlobalId; + use rustc::mir::interpret::GlobalId; let def = self.tables.qpath_def(qpath, id); match def { @@ -430,7 +430,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option { - use crate::rustc::mir::interpret::{ConstValue, Scalar}; + use rustc::mir::interpret::{ConstValue, Scalar}; match result.val { ConstValue::Scalar(Scalar::Bits { bits: b, .. }) => match result.ty.sty { ty::Bool => Some(Constant::Bool(b == 1)), diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 2f7aac99acd..01398380075 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::Ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashMap; -use crate::syntax::symbol::LocalInternedString; use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; use crate::utils::{SpanlessEq, SpanlessHash}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::Ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; use smallvec::SmallVec; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; +use syntax::symbol::LocalInternedString; /// **What it does:** Checks for consecutive `if`s with the same condition. /// diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index e5bbe9eb38a..f45d8eea5e1 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Item, ItemKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; +use rustc::hir::{Item, ItemKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for types that implement `Copy` as well as /// `Iterator`. diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index e2f98dce471..695e4329dfd 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -9,14 +9,14 @@ //! calculate cyclomatic complexity and warn about overly complex functions -use crate::rustc::cfg::CFG; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::{Attribute, NodeId}; -use crate::syntax::source_map::Span; +use rustc::cfg::CFG; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::{Attribute, NodeId}; +use syntax::source_map::Span; use crate::utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 134950b267f..9dc404efd7e 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 02eda701817..b4556ebaff9 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::Span; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly or vice versa. diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index f8e31a4b2e7..024907185e9 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; -use crate::syntax::source_map::{BytePos, Span}; -use crate::syntax_pos::Pos; use crate::utils::span_lint; use itertools::Itertools; use pulldown_cmark; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; +use syntax::source_map::{BytePos, Span}; +use syntax_pos::Pos; use url::Url; /// **What it does:** Checks for the presence of `_`, `::` or camel-case words diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 89440845e5c..34f4a56bef9 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -9,11 +9,11 @@ //! Lint on unnecessary double comparisons. Some examples: -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Span; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Span; use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index d3979e660cc..3b476b81707 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; use crate::utils::{in_macro, span_lint}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; /// **What it does:** Checks for unnecessary double parentheses. /// diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index a9741c7a2dd..f0f91c9ab69 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 295f7532e90..aebb378ee9b 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Spanned; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Spanned; use crate::consts::{constant, Constant}; use crate::utils::paths; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index e977019fa4e..ff8345290b2 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -9,9 +9,9 @@ //! lint on if expressions with an else if, but without a final else branch -use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; use crate::utils::span_help_and_lint; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 045551d38dc..af2a54069fc 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -9,10 +9,10 @@ //! lint when there is an enum with no variants -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint_and_then; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for `enum`s with no variants. /// diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index fad62c6825e..c59bfd1ad92 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Span; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Span; /// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap` /// or `BTreeMap`. diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index bd3d3d13bb3..29038cda869 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -11,15 +11,15 @@ //! don't fit into an `i32` use crate::consts::{miri_to_const, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::mir::interpret::GlobalId; -use crate::rustc::ty; -use crate::rustc::ty::subst::Substs; -use crate::rustc::ty::util::IntTypeExt; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::{IntTy, UintTy}; use crate::utils::span_lint; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::mir::interpret::GlobalId; +use rustc::ty; +use rustc::ty::subst::Substs; +use rustc::ty::util::IntTypeExt; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::{IntTy, UintTy}; /// **What it does:** Checks for C-like enumerations that are /// `repr(isize/usize)` and have values that don't fit into an `i32`. diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 3a98c784fe2..aa1ee038c59 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -9,13 +9,13 @@ //! lint on `use`ing all variants of an enum -use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::NodeId; -use crate::syntax::source_map::Span; use crate::utils::span_lint; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::NodeId; +use syntax::source_map::Span; /// **What it does:** Checks for `use Enum::*`. /// diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c6142a16854..c5d7094dcc1 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -9,13 +9,13 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use crate::rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; use crate::utils::{camel_case, in_macro}; use crate::utils::{span_help_and_lint, span_lint}; +use rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; +use syntax::source_map::Span; +use syntax::symbol::LocalInternedString; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 83644786e51..af9de9fe7e4 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{ implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq, }; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index e2725cf59b0..43f16c74eb1 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -8,11 +8,11 @@ // except according to those terms. use crate::consts::{constant_simple, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; use crate::utils::{in_macro, span_lint}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::Span; /// **What it does:** Checks for erasing operations, e.g. `x * 0`. /// diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 4b4a6bd9d5c..445aeb3377b 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -7,18 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit as visit; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::middle::expr_use_visitor::*; -use crate::rustc::middle::mem_categorization::{cmt_, Categorization}; -use crate::rustc::ty::layout::LayoutOf; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::util::nodemap::NodeSet; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::NodeId; -use crate::syntax::source_map::Span; use crate::utils::span_lint; +use rustc::hir::intravisit as visit; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::{cmt_, Categorization}; +use rustc::ty::layout::LayoutOf; +use rustc::ty::{self, Ty}; +use rustc::util::nodemap::NodeSet; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::NodeId; +use syntax::source_map::Span; pub struct Pass { pub too_large_for_stack: u64, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index e06f4d260d4..dd80afbc4ae 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; pub struct EtaPass; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 69d3b09a8ae..50944eb5e7e 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; use if_chain::if_chain; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; /// **What it does:** Checks for a read and a write to the same variable where /// whether the read occurs before or after the write depends on the evaluation diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 7d72f417b2a..b3cf9131cce 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -7,18 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; -use crate::syntax_pos::symbol::Symbol; use crate::utils::span_lint_and_sugg; use if_chain::if_chain; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::f32; use std::f64; use std::fmt; +use syntax::ast::*; +use syntax_pos::symbol::Symbol; /// **What it does:** Checks for float literals with a precision greater /// than that supported by the underlying type diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index a0db3ae8df3..f56e3225d0a 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; /// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be /// replaced with `(e)print!()` / `(e)println!()` diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 0f1c1f7ef1d..65790b1b42e 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax_pos::Span; use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; use crate::utils::{is_expn_of, match_def_path, method_chain_args, opt_def_id, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax_pos::Span; /// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()` /// @@ -61,8 +61,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { } fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec) { - use crate::rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; - use crate::rustc::hir::*; + use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; + use rustc::hir::*; struct FindPanicUnwrap<'a, 'tcx: 'a> { tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index ac80580b148..1db52079d3f 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -7,18 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; use crate::utils::paths; use crate::utils::{ in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty, }; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; /// **What it does:** Checks for the use of `format!("string literal with no /// argument")` and `format!("{}", foo)` where `foo` is a string. diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index cc3801423c8..ce51f1433f9 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; -use crate::syntax::ptr::P; use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; +use syntax::ptr::P; /// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` /// operators. diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index e3c43c1c090..19adf2d1dc4 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -7,18 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::intravisit; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashSet; -use crate::rustc_target::spec::abi::Abi; -use crate::syntax::ast; -use crate::syntax::source_map::Span; use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; use matches::matches; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::intravisit; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; +use rustc_target::spec::abi::Abi; +use syntax::ast; +use syntax::source_map::Span; /// **What it does:** Checks for functions with too many parameters. /// diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index cea759712b8..b18d63a94b6 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::NodeId; use crate::utils::{ in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then, }; use crate::utils::{opt_def_id, paths, resolve_node}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::NodeId; /// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions. /// diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index aab3c8c8336..5f1101461bd 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -8,12 +8,12 @@ // except according to those terms. use crate::consts::{constant_simple, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; use crate::utils::{clip, in_macro, snippet, span_lint, unsext}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::Span; /// **What it does:** Checks for identity operations, e.g. `x + 0`. /// diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 8a82b8d6c49..c40fb540da6 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -10,9 +10,9 @@ //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition -use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; use crate::utils::span_help_and_lint; diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index dc1869ae04e..674667c4b5b 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::{ast::NodeId, source_map::Span}; use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; +use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::{ast::NodeId, source_map::Span}; /// **What it does:** Checks for missing return statements at the end of a block. /// diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 758b1352471..cf971b63052 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -10,14 +10,14 @@ //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::RangeLimits; use crate::utils; use crate::utils::higher; use crate::utils::higher::Range; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::RangeLimits; /// **What it does:** Checks for out of bounds array indexing with a constant /// index. diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index ddf3e8f8aaa..e3d03c0e697 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -8,11 +8,11 @@ // except according to those terms. use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for matches being used to destructure a single-variant enum /// or tuple struct where a `let` will suffice. diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 625eca86d87..2f7c5895af8 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 256f080fdb9..5224b5fb867 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -9,13 +9,13 @@ //! lint on inherent implementations -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashMap; -use crate::syntax_pos::Span; use crate::utils::span_lint_and_then; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; use std::default::Default; +use syntax_pos::Span; /// **What it does:** Checks for multiple inherent implementations of a struct /// diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 4b651dd0e1e..afa8f234023 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -9,13 +9,13 @@ //! checks for `#[inline]` on trait methods without bodies -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{Attribute, Name}; use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::{Attribute, Name}; /// **What it does:** Checks for `#[inline]` on trait methods without bodies /// diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 08c8012c931..3498c1e8114 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -9,10 +9,10 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::*; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 5eba76bb45f..c0dcda6349b 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. /// diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index ce44b7ac97c..2d8f284ea6d 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -9,11 +9,11 @@ //! lint when items are used after statements -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; use crate::utils::{in_macro, span_lint}; use matches::matches; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; /// **What it does:** Checks for items declared after some statement in a block. /// diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 8c8fc5dbeda..052504cc57c 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -9,12 +9,12 @@ //! lint when there is a large size difference between variants on an enum -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::layout::LayoutOf; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{snippet_opt, span_lint_and_then}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::layout::LayoutOf; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for large size differences between variants on /// `enum`s. diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 47b0fb55934..0a5d273141d 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::def_id::DefId; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashSet; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{Lit, LitKind, Name}; -use crate::syntax::source_map::{Span, Spanned}; use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use rustc::hir::def_id::DefId; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use syntax::ast::{Lit, LitKind, Name}; +use syntax::source_map::{Span, Spanned}; /// **What it does:** Checks for getting the length of something via `.len()` /// just to compare to zero, and suggests using `.is_empty()` where applicable. @@ -148,7 +148,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items // fill the set with current and super traits fn fill_trait_set(traitt: DefId, set: &mut FxHashSet, cx: &LateContext<'_, '_>) { if set.insert(traitt) { - for supertrait in crate::rustc::traits::supertrait_def_ids(cx.tcx, traitt) { + for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 282c4536bca..7e9f1b41d27 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::BindingAnnotation; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; use crate::utils::{snippet, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::BindingAnnotation; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast; /// **What it does:** Checks for variable declarations immediately followed by a /// conditional affectation. diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8ce5861a939..f52fa340fb2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -212,7 +212,7 @@ pub mod zero_div_zero; pub use crate::utils::conf::Conf; mod reexport { - crate use crate::syntax::ast::{Name, NodeId}; + crate use syntax::ast::{Name, NodeId}; } pub fn register_pre_expansion_lints( diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 9dcbf576375..32170c9a7c6 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -8,16 +8,16 @@ // except according to those terms. use crate::reexport::*; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::intravisit::*; -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::keywords; use crate::utils::{last_path_segment, span_lint}; use matches::matches; +use rustc::hir::def::Def; +use rustc::hir::intravisit::*; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use syntax::source_map::Span; +use syntax::symbol::keywords; /// **What it does:** Checks for lifetime annotations which can be removed by /// relying on lifetime elision. diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 470ed369564..72bd6b09fea 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -10,13 +10,13 @@ //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. -use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; -use crate::syntax_pos; use crate::utils::{snippet_opt, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::*; +use syntax_pos; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8bf509844ac..d8d95cf9a23 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -8,31 +8,31 @@ // except according to those terms. use crate::reexport::*; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::def_id; -use crate::rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::middle::region; -use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; use itertools::Itertools; -// use crate::rustc::middle::region::CodeExtent; +use rustc::hir::def::Def; +use rustc::hir::def_id; +use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::middle::region; +use rustc::{declare_tool_lint, lint_array}; +// use rustc::middle::region::CodeExtent; use crate::consts::{constant, Constant}; -use crate::rustc::middle::expr_use_visitor::*; -use crate::rustc::middle::mem_categorization::cmt_; -use crate::rustc::middle::mem_categorization::Categorization; -use crate::rustc::ty::subst::Subst; -use crate::rustc::ty::{self, Ty}; -use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; -use crate::syntax::source_map::Span; -use crate::syntax_pos::BytePos; use crate::utils::usage::mutated_variables; use crate::utils::{in_macro, sext, sugg}; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::cmt_; +use rustc::middle::mem_categorization::Categorization; +use rustc::ty::subst::Subst; +use rustc::ty::{self, Ty}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::Applicability; use std::iter::{once, Iterator}; use std::mem; +use syntax::ast; +use syntax::source_map::Span; +use syntax_pos::BytePos; use crate::utils::paths; use crate::utils::{ diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index d45fcc7e860..2a7177d1fb9 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::Ident; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{ in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, }; use if_chain::if_chain; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::Ident; +use syntax::source_map::Span; #[derive(Clone)] pub struct Pass; diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index e5c17beb404..eca35422de2 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Span; #[derive(Clone)] pub struct Pass; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 3ef8d534861..00292eb9603 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -8,13 +8,6 @@ // except according to those terms. use crate::consts::{constant, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::{ @@ -22,8 +15,15 @@ use crate::utils::{ snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, }; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::cmp::Ordering; use std::collections::Bound; +use syntax::ast::LitKind; +use syntax::source_map::Span; /// **What it does:** Checks for matches with a single arm where an `if let` /// will usually suffice. diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 5c58c990dc7..0f8ccc7dedb 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, opt_def_id, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; use if_chain::if_chain; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::iter; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 066eeb70fde..d231d054610 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is /// `Drop`. diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 91586ae152d..0a77b7d2044 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::{Expr, ExprKind, MutMutable, QPath}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for `mem::replace()` on an `Option` with /// `None`. diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9763392bfdf..dcd9e3ee153 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -7,15 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Predicate, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; -use crate::syntax::source_map::{BytePos, Span}; -use crate::syntax::symbol::LocalInternedString; use crate::utils::paths; use crate::utils::sugg; use crate::utils::{ @@ -27,9 +18,18 @@ use crate::utils::{ }; use if_chain::if_chain; use matches::matches; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass}; +use rustc::ty::{self, Predicate, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::borrow::Cow; use std::fmt; use std::iter; +use syntax::ast; +use syntax::source_map::{BytePos, Span}; +use syntax::symbol::LocalInternedString; mod unnecessary_filter_map; diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 3ffe802201f..c5a22961db9 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::LateContext; -use crate::syntax::ast; use crate::utils::paths; use crate::utils::usage::mutated_variables; use crate::utils::{match_qpath, match_trait_method, span_lint}; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::lint::LateContext; +use syntax::ast; use if_chain::if_chain; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index dd3aa85e600..087aa94a7ec 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -8,10 +8,10 @@ // except according to those terms. use crate::consts::{constant_simple, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; use std::cmp::Ordering; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index bc3e19064db..e96261bbe28 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -9,14 +9,6 @@ use crate::consts::{constant, Constant}; use crate::reexport::*; -use crate::rustc::hir::intravisit::FnKind; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; -use crate::syntax::source_map::{ExpnFormat, Span}; use crate::utils::sugg::Sugg; use crate::utils::{ get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats, @@ -25,6 +17,14 @@ use crate::utils::{ }; use if_chain::if_chain; use matches::matches; +use rustc::hir::intravisit::FnKind; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; +use syntax::source_map::{ExpnFormat, Span}; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 9319ada13f4..6b9b90e17a5 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashMap; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; -use crate::syntax::source_map::Span; -use crate::syntax::visit::{walk_expr, FnKind, Visitor}; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; use if_chain::if_chain; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::Applicability; use std::char; +use syntax::ast::*; +use syntax::source_map::Span; +use syntax::visit::{walk_expr, FnKind, Visitor}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 6a2db0bb098..d65db03a4da 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -27,14 +27,14 @@ // [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246 // -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; -use crate::syntax::attr; -use crate::syntax::source_map::Span; use crate::utils::{in_macro, span_lint}; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; +use syntax::attr; +use syntax::source_map::Span; /// **What it does:** Warns if there is missing doc for any documentable item /// (public or private). diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index b76d6316600..8fb677c7cdf 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -18,12 +18,12 @@ // except according to those terms. // -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; -use crate::syntax::source_map::Span; use crate::utils::span_lint; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; +use syntax::source_map::Span; /// **What it does:** it lints if an exported function, method, trait method with default impl, /// or trait method impl is not `#[inline]`. @@ -91,7 +91,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute] } fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool { - use crate::rustc::session::config::CrateType; + use rustc::session::config::CrateType; cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t { CrateType::Executable => true, @@ -156,7 +156,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { - use crate::rustc::ty::{ImplContainer, TraitContainer}; + use rustc::ty::{ImplContainer, TraitContainer}; if is_executable(cx) { return; } diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index c554c8729ce..c6374afb4de 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -9,10 +9,10 @@ //! lint on multiple versions of a crate being used -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; use itertools::Itertools; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 6c58f93f0d8..e1702cc373b 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::intravisit; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{higher, span_lint}; +use rustc::hir; +use rustc::hir::intravisit; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for instances of `mut mut` references. /// @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { } fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty) { - use crate::rustc::hir::intravisit::Visitor; + use rustc::hir::intravisit::Visitor; MutVisitor { cx }.visit_ty(ty); } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index b92b3358cea..ddb8bd30137 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::subst::Subst; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::subst::Subst; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Detects giving a mutable reference to a function that only /// requires an immutable reference. diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index fb467d886b5..a114e691228 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -11,12 +11,12 @@ //! //! This lint is **warn** by default -use crate::rustc::hir::Expr; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; use crate::utils::{match_type, paths, span_lint}; +use rustc::hir::Expr; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; /// **What it does:** Checks for usages of `Mutex` where an atomic will do. /// diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 1ad7f4c5540..08408c4475c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -11,14 +11,14 @@ //! //! This lint is **warn** by default -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; -use crate::syntax::source_map::Spanned; use crate::utils::sugg::Sugg; use crate::utils::{in_macro, span_lint, span_lint_and_sugg}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; +use syntax::source_map::Spanned; /// **What it does:** Checks for expressions of the form `if c { true } else { /// false }` diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index dbee58c6a3e..80c9fc549d9 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -11,15 +11,15 @@ //! //! This lint is **warn** by default -use crate::rustc::hir::{BindingAnnotation, Expr, ExprKind, Item, MutImmutable, Pat, PatKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::ty::adjustment::{Adjust, Adjustment}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::NodeId; use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir::{BindingAnnotation, Expr, ExprKind, Item, MutImmutable, Pat, PatKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::ty::adjustment::{Adjust, Adjustment}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::NodeId; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 9b70d4b2e64..e2801a2e1e0 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -11,12 +11,12 @@ //! //! This lint is **warn** by default -use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{in_macro, snippet, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for useless borrowed references. /// diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 2f1b92544b4..9044245c5a6 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -36,11 +36,11 @@ //! ``` //! //! This lint is **warn** by default. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; -use crate::syntax::source_map::{original_sp, DUMMY_SP}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; use std::borrow::Cow; +use syntax::ast; +use syntax::source_map::{original_sp, DUMMY_SP}; use crate::utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 26bd56c2e7b..9184a486374 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -7,20 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::FnKind; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::middle::expr_use_visitor as euv; -use crate::rustc::middle::mem_categorization as mc; -use crate::rustc::traits; -use crate::rustc::ty::{self, RegionKind, TypeFoldable}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::rustc_errors::Applicability; -use crate::rustc_target::spec::abi::Abi; -use crate::syntax::ast::NodeId; -use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax_pos::Span; use crate::utils::ptr::get_spans; use crate::utils::{ get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet, @@ -28,7 +14,21 @@ use crate::utils::{ }; use if_chain::if_chain; use matches::matches; +use rustc::hir::intravisit::FnKind; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::middle::expr_use_visitor as euv; +use rustc::middle::mem_categorization as mc; +use rustc::traits; +use rustc::ty::{self, RegionKind, TypeFoldable}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::Applicability; +use rustc_target::spec::abi::Abi; use std::borrow::Cow; +use syntax::ast::NodeId; +use syntax::errors::DiagnosticBuilder; +use syntax_pos::Span; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index a15f7924678..993aa73f6f7 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_lint; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for needlessly including a base struct on update /// when all fields are changed anyway. diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index dd7d1478c23..6642f674da8 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; use crate::utils::{self, paths, span_lint}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 0df21861346..55edca6cece 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::{Span, Spanned}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::{Span, Spanned}; use crate::consts::{self, Constant}; use crate::utils::span_lint; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 86c345b025c..9e4821e7031 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -7,18 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def_id::DefId; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::util::nodemap::NodeSet; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_node_and_then}; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::def_id::DefId; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::util::nodemap::NodeSet; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Span; /// **What it does:** Checks for types with a `fn new() -> Self` method and no /// implementation of diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index f30da9c909d..c2cffadf6c1 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::def::Def; -use crate::rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; +use rustc::hir::def::Def; +use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index b699a53176e..57482ff4179 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -11,17 +11,17 @@ //! //! This lint is **deny** by default. -use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; -use crate::rustc::ty::adjustment::Adjust; -use crate::rustc::ty::{self, TypeFlags}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::rustc_typeck::hir_ty_to_ty; -use crate::syntax_pos::{Span, DUMMY_SP}; use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then}; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; +use rustc::ty::adjustment::Adjust; +use rustc::ty::{self, TypeFlags}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use rustc_typeck::hir_ty_to_ty; use std::ptr; +use syntax_pos::{Span, DUMMY_SP}; /// **What it does:** Checks for declaration of `const` items which is interior /// mutable (e.g. contains a `Cell`, `Mutex`, `AtomicXxxx` etc). diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index ad8006e9256..2ab7d7e62f3 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; -use crate::syntax::attr; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; -use crate::syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; use crate::utils::{span_lint, span_lint_and_then}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; +use syntax::attr; +use syntax::source_map::Span; +use syntax::symbol::LocalInternedString; +use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; /// **What it does:** Checks for names that are very similar and thus confusing. /// diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 9f6b6265665..e060220d56b 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index e78299bd3af..f6773dcb158 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::LitKind; -use crate::syntax::source_map::{Span, Spanned}; use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::LitKind; +use syntax::source_map::{Span, Spanned}; /// **What it does:** Checks for duplicate open options as well as combinations /// that make no sense. diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 7942e61c9f4..8df3ba4197f 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{span_lint, SpanlessEq}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Detects classic underflow/overflow checks. /// diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 39b85b12a84..822361175d6 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::LitKind; -use crate::syntax::ext::quote::rt::Span; -use crate::syntax::ptr::P; use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::LitKind; +use syntax::ext::quote::rt::Span; +use syntax::ptr::P; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 02935cf773d..c33367e7a3f 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{is_automatically_derived, span_lint_node}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. /// diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 4f71f36528c..20a797937de 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; -use crate::syntax::source_map::Spanned; use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::*; +use syntax::source_map::Spanned; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: @@ -138,7 +138,7 @@ fn is_arith_expr(expr: &Expr) -> bool { } fn is_bit_op(op: BinOpKind) -> bool { - use crate::syntax::ast::BinOpKind::*; + use syntax::ast::BinOpKind::*; match op { BitXor | BitAnd | BitOr | Shl | Shr => true, _ => false, @@ -146,7 +146,7 @@ fn is_bit_op(op: BinOpKind) -> bool { } fn is_arith_op(op: BinOpKind) -> bool { - use crate::syntax::ast::BinOpKind::*; + use syntax::ast::BinOpKind::*; match op { Add | Sub | Mul | Div | Rem => true, _ => false, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index b2039c26300..f45bb54d191 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -9,19 +9,19 @@ //! Checks for usage of `&Vec[_]` and `&String`. -use crate::rustc::hir::QPath; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::NodeId; -use crate::syntax::source_map::Span; -use crate::syntax_pos::MultiSpan; use crate::utils::ptr::get_spans; use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty}; use if_chain::if_chain; +use rustc::hir::QPath; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::borrow::Cow; +use syntax::ast::NodeId; +use syntax::source_map::Span; +use syntax_pos::MultiSpan; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless the references are mutable. It will also suggest you diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 5d2714651ed..8d6bca8b689 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -7,9 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::{declare_tool_lint, hir, lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils; +use rustc::{declare_tool_lint, hir, lint, lint_array}; +use rustc_errors::Applicability; use std::fmt; /// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 76fb6350681..63a3a831304 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ptr::P; use crate::utils::sugg::Sugg; use if_chain::if_chain; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ptr::P; -use crate::rustc_errors::Applicability; use crate::utils::paths::*; use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq}; +use rustc_errors::Applicability; /// **What it does:** Checks for expressions that could be replaced by the question mark operator /// diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index d84943f1ddc..a0870ea72d0 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::RangeLimits; -use crate::syntax::source_map::Spanned; use crate::utils::sugg::Sugg; use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::RangeLimits; +use syntax::source_map::Spanned; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 0d31129f30a..1983cb6cbc4 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -7,28 +7,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::FnKind; -use crate::rustc::hir::{def_id, Body, FnDecl}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::mir::{ - self, traversal, - visit::{MutatingUseContext, PlaceContext, Visitor}, - TerminatorKind, -}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::{ - ast::NodeId, - source_map::{BytePos, Span}, -}; use crate::utils::{ has_drop, in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, span_lint_node_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; use matches::matches; +use rustc::hir::intravisit::FnKind; +use rustc::hir::{def_id, Body, FnDecl}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::mir::{ + self, traversal, + visit::{MutatingUseContext, PlaceContext, Visitor}, + TerminatorKind, +}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::convert::TryFrom; +use syntax::{ + ast::NodeId, + source_map::{BytePos, Span}, +}; macro_rules! unwrap_or_continue { ($x:expr) => { diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index d8d80f2d128..a53df6a292a 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; use crate::utils::span_lint_and_sugg; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::*; /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index 4de98eb5525..bd194dd7bc3 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::LitKind; -use crate::syntax::ptr::P; use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::LitKind; +use syntax::ptr::P; /// **What it does:** Lint for redundant pattern matching over `Result` or /// `Option` diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 2e35719d466..d4145a2dd39 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{Expr, ExprKind, UnOp}; use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::{Expr, ExprKind, UnOp}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. /// diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 749d6068fe1..021237d38c0 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -8,16 +8,16 @@ // except according to those terms. use crate::consts::{constant, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashSet; -use crate::syntax::ast::{LitKind, NodeId, StrStyle}; -use crate::syntax::source_map::{BytePos, Span}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; use if_chain::if_chain; use regex_syntax; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; use std::convert::TryFrom; +use syntax::ast::{LitKind, NodeId, StrStyle}; +use syntax::source_map::{BytePos, Span}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 0da44bc37a1..d905d3dbdf4 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::{match_def_path, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and /// `uX/iX::MIN/MAX`. diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index c7dc6e1cde7..1ef03a77bd7 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; -use crate::syntax::source_map::Span; -use crate::syntax::visit::FnKind; -use crate::syntax_pos::BytePos; use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; use if_chain::if_chain; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast; +use syntax::source_map::Span; +use syntax::visit::FnKind; +use syntax_pos::BytePos; /// **What it does:** Checks for return statements at the end of a block. /// diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index a99f1398a26..d381f8c4419 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{get_trait_def_id, paths, span_lint}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for mis-uses of the serde API. /// diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 21c4e9d30de..329e83e100b 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -8,13 +8,13 @@ // except according to those terms. use crate::reexport::*; -use crate::rustc::hir::intravisit::FnKind; -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::source_map::Span; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; +use rustc::hir::intravisit::FnKind; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use syntax::source_map::Span; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 0ec6fc0d0d1..fde679b6ed2 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{LitKind, NodeId}; -use crate::syntax_pos::symbol::Symbol; use crate::utils::sugg::Sugg; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use if_chain::if_chain; +use rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::{LitKind, NodeId}; +use syntax_pos::symbol::Symbol; /// **What it does:** Checks slow zero-filled vector initialization /// diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 05d64fbcd04..5414a1ac0de 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Spanned; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Spanned; /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -164,8 +164,8 @@ impl LintPass for StringLitAsBytes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - use crate::syntax::ast::{LitKind, StrStyle}; use crate::utils::{in_macro, snippet, snippet_with_applicability}; + use syntax::ast::{LitKind, StrStyle}; if let ExprKind::MethodCall(ref path, _, ref args) = e.node { if path.ident.name == "as_bytes" { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index c54d89da705..04f8e4993f0 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast; use crate::utils::{get_trait_def_id, span_lint}; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast; /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g. /// subtracting elements in an Add impl. diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index a93ff124052..4c4fda26253 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; use crate::utils::sugg::Sugg; use crate::utils::{ differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq, }; use if_chain::if_chain; use matches::matches; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; /// **What it does:** Checks for manual swapping. /// diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index c25b0cf7661..a454b6fd997 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::is_adjusted; use crate::utils::span_lint; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for construction of a structure or tuple just to /// assign a value in it. diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index ec6439aef95..be3475f6703 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use crate::utils::{opt_def_id, sugg}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::borrow::Cow; +use syntax::ast; /// **What it does:** Checks for transmutes that can't ever be correct on any /// architecture. diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 9a7a5958b62..efa6c0486eb 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -9,21 +9,21 @@ use std::cmp; -use crate::rustc::hir; -use crate::rustc::hir::intravisit::FnKind; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::session::config::Config as SessionConfig; -use crate::rustc::ty::{self, FnSig}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::rustc_target::abi::LayoutOf; -use crate::rustc_target::spec::abi::Abi; -use crate::syntax::ast::NodeId; -use crate::syntax_pos::Span; use crate::utils::{in_macro, is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; use matches::matches; +use rustc::hir; +use rustc::hir::intravisit::FnKind; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::session::config::Config as SessionConfig; +use rustc::ty::{self, FnSig}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use rustc_target::abi::LayoutOf; +use rustc_target::spec::abi::Abi; +use syntax::ast::NodeId; +use syntax_pos::Span; /// **What it does:** Checks for functions taking arguments by reference, where /// the argument type is `Copy` and small enough to be more efficient to always diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index dfa4cfdcf94..f4ca8209d67 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -12,19 +12,6 @@ use crate::consts::{constant, Constant}; use crate::reexport::*; -use crate::rustc::hir; -use crate::rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use crate::rustc::ty::layout::LayoutOf; -use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::rustc_target::spec::abi::Abi; -use crate::rustc_typeck::hir_ty_to_ty; -use crate::syntax::ast::{FloatTy, IntTy, UintTy}; -use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax::source_map::Span; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, @@ -33,9 +20,22 @@ use crate::utils::{ AbsolutePathBuffer, }; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::ty::layout::LayoutOf; +use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use rustc_target::spec::abi::Abi; +use rustc_typeck::hir_ty_to_ty; use std::borrow::Cow; use std::cmp::Ordering; use std::collections::BTreeMap; +use syntax::ast::{FloatTy, IntTy, UintTy}; +use syntax::errors::DiagnosticBuilder; +use syntax::source_map::Span; /// Handles all the linting of funky types pub struct TypePass; @@ -646,7 +646,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { } fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { - use crate::syntax_pos::hygiene::CompilerDesugaringKind; + use syntax_pos::hygiene::CompilerDesugaringKind; if let ExprKind::Call(ref callee, _) = expr.node { callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark) } else { @@ -1112,7 +1112,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to); if let ExprKind::Lit(ref lit) = ex.node { - use crate::syntax::ast::{LitIntType, LitKind}; + use syntax::ast::{LitIntType, LitKind}; match lit.node { LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, _ => { @@ -1460,7 +1460,7 @@ impl LintPass for CharLitAsU8 { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - use crate::syntax::ast::{LitKind, UintTy}; + use syntax::ast::{LitKind, UintTy}; if let ExprKind::Cast(ref e, _) = expr.node { if let ExprKind::Lit(ref l) = e.node { @@ -1734,8 +1734,8 @@ impl Ord for FullInt { } fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> { - use crate::syntax::ast::{IntTy, UintTy}; use std::*; + use syntax::ast::{IntTy, UintTy}; if let ExprKind::Cast(ref cast_exp, _) = expr.node { let pre_cast_ty = cx.tables.expr_ty(cast_exp); @@ -1937,7 +1937,7 @@ impl LintPass for ImplicitHasher { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { #[allow(clippy::cast_possible_truncation)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - use crate::syntax_pos::BytePos; + use syntax_pos::BytePos; fn suggestion<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 723565b3a9b..a38fe4a5aa9 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::{LitKind, NodeId}; -use crate::syntax::source_map::Span; use crate::utils::{is_allowed, snippet, span_help_and_lint}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::{LitKind, NodeId}; +use syntax::source_map::Span; use unicode_normalization::UnicodeNormalization; /// **What it does:** Checks for the Unicode zero-width space in the code. diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index ce07e48eaf0..626b1c31013 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::*; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; use crate::utils::span_lint; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::*; +use syntax::source_map::Span; +use syntax::symbol::LocalInternedString; /// **What it does:** Checks for imports that remove "unsafe" from an item's /// name. diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index af2d742b2db..43f980c72c4 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; +use rustc::hir; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for unused written/read amount. /// diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index bebbce8e73e..766431c3687 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashMap; -use crate::syntax::ast; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; use crate::utils::{in_macro, span_lint}; +use rustc::hir; +use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; +use syntax::ast; +use syntax::source_map::Span; +use syntax::symbol::LocalInternedString; /// **What it does:** Checks for unused labels. /// diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index c65406a1954..b61b3b975f5 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use if_chain::if_chain; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::intravisit::*; -use crate::rustc::hir::*; -use crate::syntax::ast::NodeId; -use crate::syntax::source_map::Span; use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; +use rustc::hir::intravisit::*; +use rustc::hir::*; +use syntax::ast::NodeId; +use syntax::source_map::Span; /// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail. /// diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index d4e03c097f7..653b6630b3c 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,16 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::NodeId; -use crate::syntax_pos::symbol::keywords::SelfUpper; use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::ast::NodeId; +use syntax_pos::symbol::keywords::SelfUpper; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 9eb543db6d4..e13c64b5c78 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -10,14 +10,14 @@ //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -use crate::rustc::hir; -use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use crate::rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::FxHashMap; -use crate::syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; use crate::utils::get_attr; +use rustc::hir; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; +use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; /// **What it does:** Generates clippy code that detects the offending pattern /// diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index 05636e3234b..8b6a97a505c 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -11,7 +11,7 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::rustc::hir::{BinOpKind, Expr}; +use rustc::hir::{BinOpKind, Expr}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] /// Represent a normalized comparison operator. diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 35fcc08b518..da3a256a83d 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -11,12 +11,12 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::syntax::{ast, source_map}; use lazy_static::lazy_static; use std::default::Default; use std::io::Read; use std::sync::Mutex; use std::{env, fmt, fs, io, path}; +use syntax::{ast, source_map}; use toml; /// Get the configuration file from arguments. diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 992a3321c70..214b3dc10e6 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -12,11 +12,11 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::rustc::lint::LateContext; -use crate::rustc::{hir, ty}; -use crate::syntax::ast; use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node}; use if_chain::if_chain; +use rustc::lint::LateContext; +use rustc::{hir, ty}; +use syntax::ast; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index d7a57945658..79c9de13571 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -8,14 +8,14 @@ // except according to those terms. use crate::consts::{constant_context, constant_simple}; -use crate::rustc::hir::*; -use crate::rustc::lint::LateContext; -use crate::rustc::ty::TypeckTables; -use crate::syntax::ast::Name; -use crate::syntax::ptr::P; use crate::utils::differing_macro_contexts; +use rustc::hir::*; +use rustc::lint::LateContext; +use rustc::ty::TypeckTables; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; +use syntax::ast::Name; +use syntax::ptr::P; /// Type used to check whether two ast are the same. This is different from the /// operator diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index b9a58c51706..e4710b6a7a4 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -9,12 +9,12 @@ //! checks for attributes -use crate::rustc::hir; -use crate::rustc::hir::print; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::Attribute; use crate::utils::get_attr; +use rustc::hir; +use rustc::hir::print; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::Attribute; /// **What it does:** Dumps every ast/hir node which has the `#[clippy::dump]` /// attribute diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 144e2693b47..3705ab91ac2 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -7,21 +7,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; -use crate::syntax::source_map::Span; -use crate::syntax::symbol::LocalInternedString; use crate::utils::{ match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::Applicability; +use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; +use syntax::source_map::Span; +use syntax::symbol::LocalInternedString; /// **What it does:** Checks for various things we like to keep tidy in clippy. /// diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index cb4a656d1ff..2c0af12818e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,35 +8,35 @@ // except according to those terms. use crate::reexport::*; -use crate::rustc::hir; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; -use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use crate::rustc::hir::Node; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, Level, Lint, LintContext}; -use crate::rustc::session::Session; -use crate::rustc::traits; -use crate::rustc::ty::{ +use if_chain::if_chain; +use matches::matches; +use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc::hir::Node; +use rustc::hir::*; +use rustc::lint::{LateContext, Level, Lint, LintContext}; +use rustc::session::Session; +use rustc::traits; +use rustc::ty::{ self, layout::{self, IntegerExt}, subst::Kind, Binder, Ty, TyCtxt, }; -use crate::rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; -use crate::syntax::ast::{self, LitKind}; -use crate::syntax::attr; -use crate::syntax::errors::DiagnosticBuilder; -use crate::syntax::source_map::{Span, DUMMY_SP}; -use crate::syntax::symbol; -use crate::syntax::symbol::{keywords, Symbol}; -use if_chain::if_chain; -use matches::matches; +use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; use std::mem; use std::rc::Rc; use std::str::FromStr; +use syntax::ast::{self, LitKind}; +use syntax::attr; +use syntax::errors::DiagnosticBuilder; +use syntax::source_map::{Span, DUMMY_SP}; +use syntax::symbol; +use syntax::symbol::{keywords, Symbol}; pub mod camel_case; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 854da37f4d2..3f589c3b687 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -7,13 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use crate::rustc::hir::*; -use crate::rustc::lint::LateContext; -use crate::syntax::ast::Name; -use crate::syntax::source_map::Span; use crate::utils::{get_pat_name, match_var, snippet}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc::hir::*; +use rustc::lint::LateContext; use std::borrow::Cow; +use syntax::ast::Name; +use syntax::source_map::Span; pub fn get_spans( cx: &LateContext<'_, '_>, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index f087b73bef4..a8bc0f3fca1 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -10,22 +10,22 @@ //! Contains utility functions to generate suggestions. #![deny(clippy::missing_docs_in_private_items)] -use crate::rustc::hir; -use crate::rustc::lint::{EarlyContext, LateContext, LintContext}; -use crate::rustc_errors; -use crate::rustc_errors::Applicability; -use crate::syntax::ast; -use crate::syntax::parse::token; -use crate::syntax::print::pprust::token_to_string; -use crate::syntax::source_map::{CharPos, Span}; -use crate::syntax::util::parser::AssocOp; -use crate::syntax_pos::{BytePos, Pos}; use crate::utils::{higher, in_macro, snippet, snippet_opt}; use matches::matches; +use rustc::hir; +use rustc::lint::{EarlyContext, LateContext, LintContext}; +use rustc_errors; +use rustc_errors::Applicability; use std; use std::borrow::Cow; use std::convert::TryInto; use std::fmt::Display; +use syntax::ast; +use syntax::parse::token; +use syntax::print::pprust::token_to_string; +use syntax::source_map::{CharPos, Span}; +use syntax::util::parser::AssocOp; +use syntax_pos::{BytePos, Pos}; /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { @@ -122,7 +122,7 @@ impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self { - use crate::syntax::ast::RangeLimits; + use syntax::ast::RangeLimits; let snippet = snippet(cx, expr.span, default); @@ -407,7 +407,7 @@ enum Associativity { /// they are considered /// associative. fn associativity(op: &AssocOp) -> Associativity { - use crate::syntax::util::parser::AssocOp::*; + use syntax::util::parser::AssocOp::*; match *op { ObsoleteInPlace | Assign | AssignOp(_) => Associativity::Right, @@ -420,7 +420,7 @@ fn associativity(op: &AssocOp) -> Associativity { /// Convert a `hir::BinOp` to the corresponding assigning binary operator. fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use crate::syntax::parse::token::BinOpToken::*; + use syntax::parse::token::BinOpToken::*; AssocOp::AssignOp(match op.node { hir::BinOpKind::Add => Plus, @@ -447,8 +447,8 @@ fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { /// Convert an `ast::BinOp` to the corresponding assigning binary operator. fn astbinop2assignop(op: ast::BinOp) -> AssocOp { - use crate::syntax::ast::BinOpKind::*; - use crate::syntax::parse::token::BinOpToken; + use syntax::ast::BinOpKind::*; + use syntax::parse::token::BinOpToken; AssocOp::AssignOp(match op.node { Add => BinOpToken::Plus, diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 31aa4b6fb5a..e4d3fa29996 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -7,17 +7,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::LateContext; +use rustc::lint::LateContext; -use crate::rustc::hir::def::Def; -use crate::rustc::hir::*; -use crate::rustc::middle::expr_use_visitor::*; -use crate::rustc::middle::mem_categorization::cmt_; -use crate::rustc::middle::mem_categorization::Categorization; -use crate::rustc::ty; -use crate::rustc_data_structures::fx::FxHashSet; -use crate::syntax::ast::NodeId; -use crate::syntax::source_map::Span; +use rustc::hir::def::Def; +use rustc::hir::*; +use rustc::middle::expr_use_visitor::*; +use rustc::middle::mem_categorization::cmt_; +use rustc::middle::mem_categorization::Categorization; +use rustc::ty; +use rustc_data_structures::fx::FxHashSet; +use syntax::ast::NodeId; +use syntax::source_map::Span; /// Returns a set of mutated local variable ids or None if mutations could not be determined. pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 7d09c20db27..2f259bf8bca 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -8,14 +8,14 @@ // except according to those terms. use crate::consts::constant; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::ty::{self, Ty}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::source_map::Span; use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::{self, Ty}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; +use syntax::source_map::Span; /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would /// be possible. diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 6de391d882f..38bce9da932 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -7,10 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::{ast::*, source_map::DUMMY_SP}; use crate::utils::span_lint; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; use if_chain::if_chain; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d226c6559c3..6531e71a9fa 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -7,14 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc_errors::Applicability; -use crate::syntax::ast::*; -use crate::syntax::parse::{parser, token}; -use crate::syntax::tokenstream::{ThinTokenStream, TokenStream}; use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_errors::Applicability; use std::borrow::Cow; +use syntax::ast::*; +use syntax::parse::{parser, token}; +use syntax::tokenstream::{ThinTokenStream, TokenStream}; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -271,7 +271,7 @@ impl EarlyLintPass for Pass { /// (Some("string to write: {}"), Some(buf)) /// ``` fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { - use crate::fmt_macros::*; + use fmt_macros::*; let tts = TokenStream::from(tts.clone()); let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false); let mut expr: Option = None; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 20a92012520..93606e378d9 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -8,11 +8,11 @@ // except according to those terms. use crate::consts::{constant_simple, Constant}; -use crate::rustc::hir::*; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; use crate::utils::span_help_and_lint; use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; /// **What it does:** Checks for `0.0 / 0.0`. /// diff --git a/tests/matches.rs b/tests/matches.rs index fb5dbf5d84d..00e2f043cbb 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -15,8 +15,8 @@ use std::collections::Bound; #[test] fn test_overlapping() { - use crate::syntax::source_map::DUMMY_SP; use clippy_lints::matches::overlapping; + use syntax::source_map::DUMMY_SP; let sp = |s, e| clippy_lints::matches::SpannedRange { span: DUMMY_SP, -- cgit 1.4.1-3-g733a5 From 0ddb6284887facf7e0c0f6908c69e6ba52426dd0 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:25:07 +0100 Subject: Use match ergonomics for approx_const lint --- clippy_lints/src/approx_const.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index bf6355c4a41..880bec79186 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -73,7 +73,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Lit(ref lit) = e.node { + if let ExprKind::Lit(lit) = &e.node { check_lit(cx, lit, e); } } -- cgit 1.4.1-3-g733a5 From 79cd95cf35a09489da02f7948886c6a736503606 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:25:45 +0100 Subject: Use match ergonomics for artithmetic lint --- clippy_lints/src/arithmetic.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 0b2c00b9b58..a9b61d328e4 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -73,8 +73,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { return; } } - match expr.node { - hir::ExprKind::Binary(ref op, ref l, ref r) => { + match &expr.node { + hir::ExprKind::Binary(op, l, r) => { match op.node { hir::BinOpKind::And | hir::BinOpKind::Or @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { self.expr_span = Some(expr.span); } }, - hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => { + hir::ExprKind::Unary(hir::UnOp::UnNeg, arg) => { let ty = cx.tables.expr_ty(arg); if ty.is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); -- cgit 1.4.1-3-g733a5 From 3bf71a8e6286b647bef901b95c031968a9b76b68 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:27:26 +0100 Subject: Use match ergonomics for assign_ops lint --- clippy_lints/src/assign_ops.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index f69c66a3d35..c7b45edb521 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -70,9 +70,9 @@ impl LintPass for AssignOps { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { - match expr.node { - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { - if let hir::ExprKind::Binary(binop, ref l, ref r) = rhs.node { + match &expr.node { + hir::ExprKind::AssignOp(op, lhs, rhs) => { + if let hir::ExprKind::Binary(binop, l, r) = &rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| { span_lint_and_then( @@ -122,8 +122,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } } }, - hir::ExprKind::Assign(ref assignee, ref e) => { - if let hir::ExprKind::Binary(op, ref l, ref r) = e.node { + hir::ExprKind::Assign(assignee, e) => { + if let hir::ExprKind::Binary(op, l, r) = &e.node { #[allow(clippy::cyclomatic_complexity)] let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { let ty = cx.tables.expr_ty(assignee); @@ -150,8 +150,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if_chain! { if parent_impl != ast::CRATE_NODE_ID; if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl); - if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = - item.node; + if let hir::ItemKind::Impl(_, _, _, _, Some(trait_ref), _, _) = + &item.node; if trait_ref.path.def.def_id() == trait_id; then { return; } } -- cgit 1.4.1-3-g733a5 From 931e2b0026e1223f0a39bc322fd7e70d9736d09a Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:29:50 +0100 Subject: Use match ergonomics for attrs lint --- clippy_lints/src/attrs.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 7310e35116f..69e6131d26a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -212,7 +212,7 @@ impl LintPass for AttrPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { - if let Some(ref items) = attr.meta_item_list() { + if let Some(items) = &attr.meta_item_list() { match &*attr.name().as_str() { "allow" | "warn" | "deny" | "forbid" => { check_clippy_lint_names(cx, items); @@ -224,8 +224,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } for item in items { if_chain! { - if let NestedMetaItemKind::MetaItem(ref mi) = item.node; - if let MetaItemKind::NameValue(ref lit) = mi.node; + if let NestedMetaItemKind::MetaItem(mi) = &item.node; + if let MetaItemKind::NameValue(lit) = &mi.node; if mi.name() == "since"; then { check_semver(cx, item.span, lit); @@ -244,7 +244,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use"); for attr in &item.attrs { - if let Some(ref lint_list) = attr.meta_item_list() { + if let Some(lint_list) = &attr.meta_item_list() { match &*attr.name().as_str() { "allow" | "warn" | "deny" | "forbid" => { // whitelist `unused_imports` and `deprecated` for `use` items @@ -381,9 +381,9 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool { fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { - match stmt.node { + match &stmt.node { StmtKind::Decl(_, _) => true, - StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => is_relevant_expr(tcx, tables, expr), + StmtKind::Expr(expr, _) | StmtKind::Semi(expr, _) => is_relevant_expr(tcx, tables, expr), } } else { block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) @@ -391,12 +391,12 @@ fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, blo } fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool { - match expr.node { - ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block), - ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e), + match &expr.node { + ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block), + ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e), ExprKind::Ret(None) | ExprKind::Break(_, None) => false, - ExprKind::Call(ref path_expr, _) => { - if let ExprKind::Path(ref qpath) = path_expr.node { + ExprKind::Call(path_expr, _) => { + if let ExprKind::Path(qpath) = &path_expr.node { if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) { !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) } else { @@ -443,7 +443,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib } } - if let Some(ref values) = attr.meta_item_list() { + if let Some(values) = attr.meta_item_list() { if values.len() != 1 || attr.name() != "inline" { continue; } @@ -463,7 +463,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib } fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) { - if let LitKind::Str(ref is, _) = lit.node { + if let LitKind::Str(is, _) = lit.node { if Version::parse(&is.as_str()).is_ok() { return; } @@ -477,7 +477,7 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) { } fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { - if let NestedMetaItemKind::MetaItem(ref mi) = nmi.node { + if let NestedMetaItemKind::MetaItem(mi) = &nmi.node { mi.is_word() && mi.name() == expected } else { false @@ -512,7 +512,7 @@ impl EarlyLintPass for CfgAttrPass { if_chain! { // check cfg_attr if attr.name() == "cfg_attr"; - if let Some(ref items) = attr.meta_item_list(); + if let Some(items) = attr.meta_item_list(); if items.len() == 2; // check for `rustfmt` if let Some(feature_item) = items[0].meta_item(); -- cgit 1.4.1-3-g733a5 From fe151ebb9c4f50bfed11b63b7e264005ac6bbc65 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:31:32 +0100 Subject: Use match ergonomics for bit_mask lint --- clippy_lints/src/bit_mask.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index b15ce871c32..c85ab799ddc 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -121,7 +121,7 @@ impl LintPass for BitMask { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node { + if let ExprKind::Binary(cmp, left, right) = &e.node { if cmp.node.is_comparison() { if let Some(cmp_opt) = fetch_int_literal(cx, right) { check_compare(cx, left, cmp.node, cmp_opt, e.span) @@ -131,13 +131,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { } } if_chain! { - if let ExprKind::Binary(ref op, ref left, ref right) = e.node; + if let ExprKind::Binary(op, left, right) = &e.node; if BinOpKind::Eq == op.node; - if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node; + if let ExprKind::Binary(op1, left1, right1) = &left.node; if BinOpKind::BitAnd == op1.node; - if let ExprKind::Lit(ref lit) = right1.node; + if let ExprKind::Lit(lit) = &right1.node; if let LitKind::Int(n, _) = lit.node; - if let ExprKind::Lit(ref lit1) = right.node; + if let ExprKind::Lit(lit1) = &right.node; if let LitKind::Int(0, _) = lit1.node; if n.leading_zeros() == n.count_zeros(); if n > u128::from(self.verbose_bit_mask_threshold); @@ -173,7 +173,7 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) { - if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node { + if let ExprKind::Binary(op, left, right) = &bit_op.node { if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { return; } -- cgit 1.4.1-3-g733a5 From 13c857b74509a7f1cd80e69f4b7938a21e848ae3 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:32:09 +0100 Subject: Use match ergonomics for block_in_if_condition lint --- clippy_lints/src/block_in_if_condition.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 825bf789a69..d288c45639d 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -88,11 +88,11 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::If(ref check, ref then, _) = expr.node { - if let ExprKind::Block(ref block, _) = check.node { + if let ExprKind::If(check, then, _) = &expr.node { + if let ExprKind::Block(block, _) = &check.node { if block.rules == DefaultBlock { if block.stmts.is_empty() { - if let Some(ref ex) = block.expr { + if let Some(ex) = &block.expr { // don't dig into the expression here, just suggest that they remove // the block if in_macro(expr.span) || differing_macro_contexts(expr.span, ex.span) { -- cgit 1.4.1-3-g733a5 From aeabb890d694b2c791c17adbff691566f6ba6984 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:34:56 +0100 Subject: Use match ergonomics for booleans lint --- clippy_lints/src/booleans.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 9f58cb6582e..236266c1c40 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -96,7 +96,7 @@ struct Hir2Qmm<'a, 'tcx: 'a, 'v> { impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { fn extract(&mut self, op: BinOpKind, a: &[&'v Expr], mut v: Vec) -> Result, String> { for a in a { - if let ExprKind::Binary(binop, ref lhs, ref rhs) = a.node { + if let ExprKind::Binary(binop, lhs, rhs) = &a.node { if binop.node == op { v = self.extract(op, &[lhs, rhs], v)?; continue; @@ -110,14 +110,14 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { fn run(&mut self, e: &'v Expr) -> Result { // prevent folding of `cfg!` macros and the like if !in_macro(e.span) { - match e.node { - ExprKind::Unary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprKind::Binary(binop, ref lhs, ref rhs) => match binop.node { + match &e.node { + ExprKind::Unary(UnNot, inner) => return Ok(Bool::Not(box self.run(inner)?)), + ExprKind::Binary(binop, lhs, rhs) => match &binop.node { BinOpKind::Or => return Ok(Bool::Or(self.extract(BinOpKind::Or, &[lhs, rhs], Vec::new())?)), BinOpKind::And => return Ok(Bool::And(self.extract(BinOpKind::And, &[lhs, rhs], Vec::new())?)), _ => (), }, - ExprKind::Lit(ref lit) => match lit.node { + ExprKind::Lit(lit) => match lit.node { LitKind::Bool(true) => return Ok(Bool::True), LitKind::Bool(false) => return Ok(Bool::False), _ => (), @@ -130,8 +130,8 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { #[allow(clippy::cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } - let negated = match e.node { - ExprKind::Binary(binop, ref lhs, ref rhs) => { + let negated = match &e.node { + ExprKind::Binary(binop, lhs, rhs) => { if !implements_ord(self.cx, lhs) { continue; } @@ -184,8 +184,8 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } fn simplify_not(&self, expr: &Expr) -> Option { - match expr.node { - ExprKind::Binary(binop, ref lhs, ref rhs) => { + match &expr.node { + ExprKind::Binary(binop, lhs, rhs) => { if !implements_ord(self.cx, lhs) { return None; } @@ -201,7 +201,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } .and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?))) }, - ExprKind::MethodCall(ref path, _, ref args) if args.len() == 1 => { + ExprKind::MethodCall(path, _, args) if args.len() == 1 => { let type_of_receiver = self.cx.tables.expr_ty(&args[0]); if !match_type(self.cx, type_of_receiver, &paths::OPTION) && !match_type(self.cx, type_of_receiver, &paths::RESULT) @@ -221,14 +221,14 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { fn recurse(&mut self, suggestion: &Bool) -> Option<()> { use quine_mc_cluskey::Bool::*; - match *suggestion { + match suggestion { True => { self.output.push_str("true"); }, False => { self.output.push_str("false"); }, - Not(ref inner) => match **inner { + Not(inner) => match **inner { And(_) | Or(_) => { self.output.push('!'); self.output.push('('); @@ -251,7 +251,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.recurse(inner)?; }, }, - And(ref v) => { + And(v) => { for (index, inner) in v.iter().enumerate() { if index > 0 { self.output.push_str(" && "); @@ -265,7 +265,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } } }, - Or(ref v) => { + Or(v) => { for (index, inner) in v.iter().enumerate() { if index > 0 { self.output.push_str(" || "); @@ -273,7 +273,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.recurse(inner); } }, - Term(n) => { + &Term(n) => { let snip = self.snip(self.terminals[n as usize])?; self.output.push_str(&snip); }, @@ -325,22 +325,22 @@ struct Stats { fn terminal_stats(b: &Bool) -> Stats { fn recurse(b: &Bool, stats: &mut Stats) { - match *b { + match b { True | False => stats.ops += 1, - Not(ref inner) => { + Not(inner) => { match **inner { And(_) | Or(_) => stats.ops += 1, // brackets are also operations _ => stats.negations += 1, } recurse(inner, stats); }, - And(ref v) | Or(ref v) => { + And(v) | Or(v) => { stats.ops += v.len() - 1; for inner in v { recurse(inner, stats); } }, - Term(n) => stats.terminals[n as usize] += 1, + &Term(n) => stats.terminals[n as usize] += 1, } } use quine_mc_cluskey::Bool::*; @@ -461,11 +461,11 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { if in_macro(e.span) { return; } - match e.node { + match &e.node { ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => { self.bool_expr(e) }, - ExprKind::Unary(UnNot, ref inner) => { + ExprKind::Unary(UnNot, inner) => { if self.cx.tables.node_types()[inner.hir_id].is_bool() { self.bool_expr(e); } else { -- cgit 1.4.1-3-g733a5 From 0edb49792f26de7af09e0727fb178ba4240a2632 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:46:25 +0100 Subject: Apply cargo fix --edition-idioms fixes --- tests/compile-test.rs | 2 +- tests/matches.rs | 2 +- tests/needless_continue_helpers.rs | 2 +- tests/versioncheck.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 8b8ffe86f19..005c2ce33f9 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -9,7 +9,7 @@ #![feature(test)] -extern crate compiletest_rs as compiletest; +use compiletest_rs as compiletest; extern crate test; use std::env::{set_var, var}; diff --git a/tests/matches.rs b/tests/matches.rs index fb5dbf5d84d..3fdb65c6a40 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -9,7 +9,7 @@ #![feature(rustc_private)] -extern crate clippy_lints; +use clippy_lints; extern crate syntax; use std::collections::Bound; diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 8237ac437ba..68ccbc7fc03 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -10,7 +10,7 @@ // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. -extern crate clippy_lints; + use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; #[test] diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index cdf97f75ec6..294e5d7d60b 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -7,8 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate cargo_metadata; -extern crate semver; +use cargo_metadata; + use semver::VersionReq; #[test] -- cgit 1.4.1-3-g733a5 From 177c639e65b56f574d2baa1403c31551a945077c Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 17:48:00 +0100 Subject: Remove unnecessary `use` statements after `cargo fix` --- tests/matches.rs | 1 - tests/needless_continue_helpers.rs | 1 - tests/versioncheck.rs | 2 -- 3 files changed, 4 deletions(-) diff --git a/tests/matches.rs b/tests/matches.rs index 3fdb65c6a40..a445772c319 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -9,7 +9,6 @@ #![feature(rustc_private)] -use clippy_lints; extern crate syntax; use std::collections::Bound; diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index 68ccbc7fc03..e0dcd035c58 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -10,7 +10,6 @@ // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. - use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; #[test] diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 294e5d7d60b..945e35f4ebf 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -7,8 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cargo_metadata; - use semver::VersionReq; #[test] -- cgit 1.4.1-3-g733a5 From ab70e0e7422ef3f53f5357ea99a739cbcbe6caee Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 18:07:10 +0100 Subject: Use an FxHashSet for valid idents in documentation lint --- clippy_lints/src/doc.rs | 13 +++++++------ clippy_lints/src/lib.rs | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 024907185e9..a3504e7e330 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -12,6 +12,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; use syntax::ast; use syntax::source_map::{BytePos, Span}; use syntax_pos::Pos; @@ -43,11 +44,11 @@ declare_clippy_lint! { #[derive(Clone)] pub struct Doc { - valid_idents: Vec, + valid_idents: FxHashSet, } impl Doc { - pub fn new(valid_idents: Vec) -> Self { + pub fn new(valid_idents: FxHashSet) -> Self { Self { valid_idents } } } @@ -144,7 +145,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( panic!("not a doc-comment: {}", comment); } -pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'a [ast::Attribute]) { +pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet, attrs: &'a [ast::Attribute]) { let mut doc = String::new(); let mut spans = vec![]; @@ -192,7 +193,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &' fn check_doc<'a, Events: Iterator)>>( cx: &EarlyContext<'_>, - valid_idents: &[String], + valid_idents: &FxHashSet, docs: Events, spans: &[(usize, Span)], ) { @@ -237,14 +238,14 @@ fn check_doc<'a, Events: Iterator)>>( } } -fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) { +fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ // Or even as in `_foo bar_` which is emphasized. let word = word.trim_matches(|c: char| !c.is_alphanumeric()); - if valid_idents.iter().any(|i| i == word) { + if valid_idents.contains(word) { continue; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 96af1642e8a..cfa99b0b75a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -425,7 +425,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default()); reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone())); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); - reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone())); + reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_discriminant::MemDiscriminant); -- cgit 1.4.1-3-g733a5 From 815e434a1fcb3817fa81c5aebd469c30493a0e51 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 00:18:55 +0100 Subject: Move constant write checks to temporary_assignment lint They make more sense here --- clippy_lints/src/no_effect.rs | 14 ------ clippy_lints/src/temporary_assignment.rs | 24 +++++++--- tests/ui/no_effect.rs | 27 ------------ tests/ui/no_effect.stderr | 76 +++++++++++--------------------- tests/ui/temporary_assignment.rs | 38 ++++++++++++++++ tests/ui/temporary_assignment.stderr | 46 +++++++++++++++++-- 6 files changed, 124 insertions(+), 101 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 02ca5ebedfa..c2cffadf6c1 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -98,20 +98,6 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { false } }, - ExprKind::Assign(ref left, ref right) => { - if has_no_effect(cx, left) { - let mut left = left; - while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &left.node { - left = f; - } - if let ExprKind::Path(qpath) = &left.node { - if let Def::Const(..) = cx.tables.qpath_def(qpath, left.hir_id) { - return has_no_effect(cx, right); - } - } - } - false - }, _ => false, } } diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index a454b6fd997..381efd57135 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -9,6 +9,7 @@ use crate::utils::is_adjusted; use crate::utils::span_lint; +use rustc::hir::def::Def; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; @@ -31,9 +32,16 @@ declare_clippy_lint! { "assignments to temporaries" } -fn is_temporary(expr: &Expr) -> bool { - match expr.node { +fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { + match &expr.node { ExprKind::Struct(..) | ExprKind::Tup(..) => true, + ExprKind::Path(qpath) => { + if let Def::Const(..) = cx.tables.qpath_def(qpath, expr.hir_id) { + true + } else { + false + } + }, _ => false, } } @@ -49,11 +57,13 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::Assign(ref target, _) = expr.node { - if let ExprKind::Field(ref base, _) = target.node { - if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - } + if let ExprKind::Assign(target, _) = &expr.node { + let mut base = target; + while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &base.node { + base = f; + } + if is_temporary(cx, base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); } } } diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 8431f00e445..6b51c50dcde 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -67,21 +67,6 @@ unsafe fn unsafe_fn() -> i32 { 0 } -struct A(i32); -struct B { - field: i32, -} -struct C { - b: B, -} -struct D { - arr: [i32; 1], -} -const A_CONST: A = A(1); -const B: B = B { field: 1 }; -const C: C = C { b: B { field: 1 } }; -const D: D = D { arr: [1] }; - fn main() { let s = get_struct(); let s2 = get_struct(); @@ -114,10 +99,6 @@ fn main() { || x += 5; let s: String = "foo".into(); FooString { s: s }; - A_CONST.0 = 2; - B.field = 2; - C.b.field = 2; - D.arr[0] = 2; // Do not warn get_number(); @@ -127,12 +108,4 @@ fn main() { DropTuple(0); DropEnum::Tuple(0); DropEnum::Struct { field: 0 }; - let mut a_mut = A(1); - a_mut.0 = 2; - let mut b_mut = B { field: 1 }; - b_mut.field = 2; - let mut c_mut = C { b: B { field: 1 } }; - c_mut.b.field = 2; - let mut d_mut = D { arr: [1] }; - d_mut.arr[0] = 2; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index b6aab53e50f..cc3b069f0b5 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:89:5 + --> $DIR/no_effect.rs:74:5 | LL | 0; | ^^ @@ -7,172 +7,148 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:75:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:76:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:77:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:78:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:79:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:80:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:81:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:82:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:83:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:84:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:85:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:86:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:87:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:88:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:89:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:90:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:91:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:93:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:94:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:95:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:96:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:97:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:99:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:101:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ -error: statement with no effect - --> $DIR/no_effect.rs:117:5 - | -LL | A_CONST.0 = 2; - | ^^^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:118:5 - | -LL | B.field = 2; - | ^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:119:5 - | -LL | C.b.field = 2; - | ^^^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:120:5 - | -LL | D.arr[0] = 2; - | ^^^^^^^^^^^^^ - -error: aborting due to 29 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 79c090f0572..5581f5be766 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -11,10 +11,16 @@ use std::ops::{Deref, DerefMut}; +struct TupleStruct(i32); + struct Struct { field: i32, } +struct MultiStruct { + structure: Struct, +} + struct Wrapper<'a> { inner: &'a mut Struct, } @@ -32,15 +38,47 @@ impl<'a> DerefMut for Wrapper<'a> { } } +struct ArrayStruct { + array: [i32; 1], +} + +const A: TupleStruct = TupleStruct(1); +const B: Struct = Struct { field: 1 }; +const C: MultiStruct = MultiStruct { + structure: Struct { field: 1 }, +}; +const D: ArrayStruct = ArrayStruct { array: [1] }; + fn main() { let mut s = Struct { field: 0 }; let mut t = (0, 0); Struct { field: 0 }.field = 1; + MultiStruct { + structure: Struct { field: 0 }, + } + .structure + .field = 1; + ArrayStruct { array: [0] }.array[0] = 1; (0, 0).0 = 1; + A.0 = 2; + B.field = 2; + C.structure.field = 2; + D.array[0] = 2; + // no error s.field = 1; t.0 = 1; Wrapper { inner: &mut s }.field = 1; + let mut a_mut = TupleStruct(1); + a_mut.0 = 2; + let mut b_mut = Struct { field: 1 }; + b_mut.field = 2; + let mut c_mut = MultiStruct { + structure: Struct { field: 1 }, + }; + c_mut.structure.field = 2; + let mut d_mut = ArrayStruct { array: [1] }; + d_mut.array[0] = 2; } diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index a9736385048..13ece2858b9 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -1,5 +1,5 @@ error: assignment to temporary - --> $DIR/temporary_assignment.rs:39:5 + --> $DIR/temporary_assignment.rs:56:5 | LL | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,10 +7,50 @@ LL | Struct { field: 0 }.field = 1; = note: `-D clippy::temporary-assignment` implied by `-D warnings` error: assignment to temporary - --> $DIR/temporary_assignment.rs:40:5 + --> $DIR/temporary_assignment.rs:57:5 + | +LL | / MultiStruct { +LL | | structure: Struct { field: 0 }, +LL | | } +LL | | .structure +LL | | .field = 1; + | |______________^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:62:5 + | +LL | ArrayStruct { array: [0] }.array[0] = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:63:5 | LL | (0, 0).0 = 1; | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: assignment to temporary + --> $DIR/temporary_assignment.rs:65:5 + | +LL | A.0 = 2; + | ^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:66:5 + | +LL | B.field = 2; + | ^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:67:5 + | +LL | C.structure.field = 2; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:68:5 + | +LL | D.array[0] = 2; + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors -- cgit 1.4.1-3-g733a5 From e590025f61d03e1f2068abdc83435d1995a7f34a Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 30 Dec 2018 01:09:24 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/56225/ item.name -> item.ident.name --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 08333994fa6..2757593e2ee 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -237,7 +237,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if is_relevant_item(cx.tcx, item) { - check_attrs(cx, item.span, item.name, &item.attrs) + check_attrs(cx, item.span, item.ident.name, &item.attrs) } match item.node { ItemKind::ExternCrate(..) | ItemKind::Use(..) => { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 0a5d273141d..61aa228729c 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -176,7 +176,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items visited_trait.span, &format!( "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method", - visited_trait.name + visited_trait.ident.name ), ); } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index d65db03a4da..90503970823 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -141,7 +141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Enum(..) => "an enum", hir::ItemKind::Fn(..) => { // ignore main() - if it.name == "main" { + if it.ident.name == "main" { let def_id = cx.tcx.hir().local_def_id(it.id); let def_key = cx.tcx.hir().def_key(def_id); if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index e4710b6a7a4..98ddcf945d9 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -355,7 +355,7 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { let did = cx.tcx.hir().local_def_id(item.id); - println!("item `{}`", item.name); + println!("item `{}`", item.ident.name); match item.vis.node { hir::VisibilityKind::Public => println!("public"), hir::VisibilityKind::Crate(_) => println!("visible crate wide"), diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 3705ab91ac2..be412f36edd 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let hir::ItemKind::Static(ref ty, MutImmutable, _) = item.node { if is_lint_ref_type(cx, ty) { - self.declared_lints.insert(item.name, item.span); + self.declared_lints.insert(item.ident.name, item.span); } } else if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { if_chain! { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2c0af12818e..e92529dc0a2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -334,7 +334,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option, expr: &Expr) -> Option { let parent_id = cx.tcx.hir().get_parent(expr.id); match cx.tcx.hir().find(parent_id) { - Some(Node::Item(&Item { ref name, .. })) => Some(*name), + Some(Node::Item(&Item { ref ident, .. })) => Some(ident.name), Some(Node::TraitItem(&TraitItem { ident, .. })) | Some(Node::ImplItem(&ImplItem { ident, .. })) => { Some(ident.name) }, -- cgit 1.4.1-3-g733a5 From a6c4eaa93c7400450facd0eb0580e4d641f2e297 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 02:43:56 +0100 Subject: random_state lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 3 +++ clippy_lints/src/random_state.rs | 48 ++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/random_state.rs | 19 ++++++++++++++++ tests/ui/random_state.stderr | 28 +++++++++++++++++++++++ 7 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/random_state.rs create mode 100644 tests/ui/random_state.rs create mode 100644 tests/ui/random_state.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index efa637b185c..b5c8feb8ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -814,6 +814,7 @@ All notable changes to this project will be documented in this file. [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark +[`random_state`]: https://rust-lang.github.io/rust-clippy/master/index.html#random_state [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one [`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero diff --git a/README.md b/README.md index 626b589b5f3..be24f1be827 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 27905b91750..0aa9ff5985f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -180,6 +180,7 @@ pub mod precedence; pub mod ptr; pub mod ptr_offset_with_cast; pub mod question_mark; +pub mod random_state; pub mod ranges; pub mod redundant_clone; pub mod redundant_field_names; @@ -484,6 +485,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); + reg.register_late_lint_pass(box random_state::Pass); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -1023,6 +1025,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, + random_state::RANDOM_STATE, redundant_clone::REDUNDANT_CLONE, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, diff --git a/clippy_lints/src/random_state.rs b/clippy_lints/src/random_state.rs new file mode 100644 index 00000000000..02abd2e93bd --- /dev/null +++ b/clippy_lints/src/random_state.rs @@ -0,0 +1,48 @@ +use crate::utils::{match_type, paths, span_lint}; +use rustc::hir::Ty; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty::subst::UnpackedKind; +use rustc::ty::TyKind; +use rustc::{declare_tool_lint, lint_array}; + +/// **What it does:** Checks for usage of `RandomState` +/// +/// **Why is this bad?** Some applications don't need collision prevention +/// which lowers the performance. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn x() { +/// let mut map = std::collections::HashMap::new(); +/// map.insert(3, 4); +/// } +/// ``` +declare_clippy_lint! { + pub RANDOM_STATE, + nursery, + "use of RandomState" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(RANDOM_STATE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &Ty) { + if let TyKind::Adt(_, substs) = cx.tables.node_id_to_type(ty.hir_id).sty { + for subst in substs { + if let UnpackedKind::Type(build_hasher) = subst.unpack() { + if match_type(cx, build_hasher, &paths::RANDOM_STATE) { + span_lint(cx, RANDOM_STATE, ty.span, "usage of RandomState"); + } + } + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0779d77936f..0ec684e36bc 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -73,6 +73,7 @@ pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; +pub const RANDOM_STATE: [&str; 5] = ["std", "collections", "hash", "map", "RandomState"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; diff --git a/tests/ui/random_state.rs b/tests/ui/random_state.rs new file mode 100644 index 00000000000..31f4b4d49b4 --- /dev/null +++ b/tests/ui/random_state.rs @@ -0,0 +1,19 @@ +#![warn(clippy::random_state)] + +use std::collections::hash_map::RandomState; +use std::collections::hash_map::{DefaultHasher, HashMap}; +use std::hash::{BuildHasherDefault}; + +fn main() { + // Should warn + let mut map = HashMap::new(); + map.insert(3, 4); + let mut map = HashMap::with_hasher(RandomState::new()); + map.insert(true, false); + let _map: HashMap<_, _> = vec![(2, 3)].into_iter().collect(); + let _vec: Vec>; + // Shouldn't warn + let _map: HashMap> = HashMap::default(); + let mut map = HashMap::with_hasher(BuildHasherDefault::::default()); + map.insert("a", "b"); +} diff --git a/tests/ui/random_state.stderr b/tests/ui/random_state.stderr new file mode 100644 index 00000000000..df224bf0c29 --- /dev/null +++ b/tests/ui/random_state.stderr @@ -0,0 +1,28 @@ +error: usage of RandomState + --> $DIR/random_state.rs:9:19 + | +LL | let mut map = HashMap::new(); + | ^^^^^^^^^^^^ + | + = note: `-D clippy::random-state` implied by `-D warnings` + +error: usage of RandomState + --> $DIR/random_state.rs:11:19 + | +LL | let mut map = HashMap::with_hasher(RandomState::new()); + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of RandomState + --> $DIR/random_state.rs:13:15 + | +LL | let _map: HashMap<_, _> = vec![(2, 3)].into_iter().collect(); + | ^^^^^^^^^^^^^ + +error: usage of RandomState + --> $DIR/random_state.rs:14:19 + | +LL | let _vec: Vec>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 0f3dcdc3aad5527049c6cfcfae8bd3d697c26447 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Thu, 27 Dec 2018 09:54:19 +0100 Subject: Document known problems --- clippy_lints/src/use_self.rs | 8 +++++++- tests/ui/use_self.rs | 5 ++--- tests/ui/use_self.stderr | 30 +++++++++++++++--------------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 653b6630b3c..d08a8931419 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -25,7 +25,13 @@ use syntax_pos::symbol::keywords::SelfUpper; /// name /// feels inconsistent. /// -/// **Known problems:** None. +/// **Known problems:** +/// - Does not trigger within locally defined macros (#2098) +/// - False positive when using associated types (#2843) +/// - False positives in some situations when using generics (#3410) +/// - False positive when type from outer function can't be used (#3463) +/// - Does not diagnose tuple structs (#3498) +/// - Does not trigger in lifetimed struct /// /// **Example:** /// ```rust diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index c21df403035..561d2418228 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -51,8 +51,6 @@ mod better { } } -//todo the lint does not handle lifetimed struct -//the following module should trigger the lint on the third method only mod lifetimes { struct Foo<'a> { foo_str: &'a str, @@ -69,7 +67,8 @@ mod lifetimes { Foo { foo_str: "foo" } } - // `Self` is applicable here + // TODO: the lint does not handle lifetimed struct + // `Self` should be applicable here fn clone(&self) -> Foo<'a> { Foo { foo_str: self.foo_str } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 82b44d424df..bb81ad79900 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -37,91 +37,91 @@ LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:22 + --> $DIR/use_self.rs:95:22 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:31 + --> $DIR/use_self.rs:95:31 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:37 + --> $DIR/use_self.rs:99:37 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:53 + --> $DIR/use_self.rs:99:53 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:30 + --> $DIR/use_self.rs:103:30 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:43 + --> $DIR/use_self.rs:103:43 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:28 + --> $DIR/use_self.rs:107:28 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:46 + --> $DIR/use_self.rs:107:46 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:20 + --> $DIR/use_self.rs:109:20 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:28 + --> $DIR/use_self.rs:109:28 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:111:13 + --> $DIR/use_self.rs:110:13 | LL | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:116:23 + --> $DIR/use_self.rs:115:23 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:27 + --> $DIR/use_self.rs:117:27 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:35 + --> $DIR/use_self.rs:117:35 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:210:56 + --> $DIR/use_self.rs:209:56 | LL | fn bad(foos: &[Self]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` -- cgit 1.4.1-3-g733a5 From ab42ba4f54d2be62f271bad44f065d1814d17d4a Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Thu, 27 Dec 2018 17:27:42 +0100 Subject: Implement use_self for tuple structs --- clippy_lints/src/use_self.rs | 15 ++++++++++----- tests/ui/use_self.rs | 10 ++++++++++ tests/ui/use_self.stderr | 8 +++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index d08a8931419..fb71352a795 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -9,6 +9,7 @@ use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::def::{CtorKind, Def}; use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -30,8 +31,7 @@ use syntax_pos::symbol::keywords::SelfUpper; /// - False positive when using associated types (#2843) /// - False positives in some situations when using generics (#3410) /// - False positive when type from outer function can't be used (#3463) -/// - Does not diagnose tuple structs (#3498) -/// - Does not trigger in lifetimed struct +/// - Does not trigger in lifetimed structs /// /// **Example:** /// ```rust @@ -232,10 +232,15 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { - if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { - span_use_self_lint(self.cx, path); + if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { + if self.item_path.def == path.def { + span_use_self_lint(self.cx, path); + } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def { + if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) { + span_use_self_lint(self.cx, path); + } + } } - walk_path(self, path); } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 561d2418228..450278f2ed9 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -216,6 +216,16 @@ mod existential { } } +mod tuple_structs { + pub struct TS(i32); + + impl TS { + pub fn ts() -> Self { + TS(0) + } + } +} + mod issue3410 { struct A; diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index bb81ad79900..7ef4737dc69 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -126,5 +126,11 @@ error: unnecessary structure name repetition LL | fn bad(foos: &[Self]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 21 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:224:13 + | +224 | TS(0) + | ^^ help: use the applicable keyword: `Self` + +error: aborting due to 22 previous errors -- cgit 1.4.1-3-g733a5 From 1d10de66debee7396e4d7f254fcd97ef0b2b9c6b Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 28 Dec 2018 13:41:33 +0100 Subject: Remove false negatives from known problems --- clippy_lints/src/use_self.rs | 2 -- tests/ui/use_self.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index fb71352a795..b031e8b1c44 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -27,11 +27,9 @@ use syntax_pos::symbol::keywords::SelfUpper; /// feels inconsistent. /// /// **Known problems:** -/// - Does not trigger within locally defined macros (#2098) /// - False positive when using associated types (#2843) /// - False positives in some situations when using generics (#3410) /// - False positive when type from outer function can't be used (#3463) -/// - Does not trigger in lifetimed structs /// /// **Example:** /// ```rust diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 450278f2ed9..b201e160ebd 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -67,7 +67,7 @@ mod lifetimes { Foo { foo_str: "foo" } } - // TODO: the lint does not handle lifetimed struct + // FIXME: the lint does not handle lifetimed struct // `Self` should be applicable here fn clone(&self) -> Foo<'a> { Foo { foo_str: self.foo_str } -- cgit 1.4.1-3-g733a5 From 259ec2dc0eb3945855fd58b0d549135f6a81884a Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 28 Dec 2018 20:49:19 +0100 Subject: Update test output after rebase --- tests/ui/use_self.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 7ef4737dc69..d52fce76de5 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -127,10 +127,10 @@ LL | fn bad(foos: &[Self]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:224:13 - | -224 | TS(0) - | ^^ help: use the applicable keyword: `Self` + --> $DIR/use_self.rs:224:13 + | +LL | TS(0) + | ^^ help: use the applicable keyword: `Self` error: aborting due to 22 previous errors -- cgit 1.4.1-3-g733a5 From 911a7525619b1c8b283c1019f3b497264c7e0a5d Mon Sep 17 00:00:00 2001 From: Max Taldykin Date: Thu, 27 Dec 2018 20:11:25 +0300 Subject: Check pattern equality while checking declaration equality --- clippy_lints/src/utils/hir_utils.rs | 4 +++- tests/ui/copies.rs | 11 +++++++++++ tests/ui/copies.stderr | 12 ++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 79c9de13571..377e56ddcac 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -54,7 +54,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => { if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) { - both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + self.eq_pat(&l.pat, &r.pat) + && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) + && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) } else { false } diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 00e1d726207..8147edb98eb 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -335,6 +335,17 @@ fn if_same_then_else() -> Result<&'static str, ()> { let foo = ""; return Ok(&foo[0..]); } + + // false positive if_same_then_else, let(x,y) vs let(y,x), see #3559 + if true { + let foo = ""; + let (x, y) = (1, 2); + return Ok(&foo[x..y]); + } else { + let foo = ""; + let (y, x) = (1, 2); + return Ok(&foo[x..y]); + } } #[warn(clippy::ifs_same_cond)] diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 659abf6fa7e..4c0bc4b0173 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -352,38 +352,38 @@ LL | | } else { | |_____^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:347:15 + --> $DIR/copies.rs:358:15 | LL | } else if b { | ^ | = note: `-D clippy::ifs-same-cond` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:346:8 + --> $DIR/copies.rs:357:8 | LL | if b { | ^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:352:15 + --> $DIR/copies.rs:363:15 | LL | } else if a == 1 { | ^^^^^^ | note: same as this - --> $DIR/copies.rs:351:8 + --> $DIR/copies.rs:362:8 | LL | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:15 + --> $DIR/copies.rs:369:15 | LL | } else if 2 * a == 1 { | ^^^^^^^^^^ | note: same as this - --> $DIR/copies.rs:356:8 + --> $DIR/copies.rs:367:8 | LL | if 2 * a == 1 { | ^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 978e3ac2cfac8cb62147d2ed6992cbcbf37bb45f Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 13:40:27 +0100 Subject: Use node_id_to_type_opt instead of node_it_to_type in random_state --- clippy_lints/src/random_state.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/random_state.rs b/clippy_lints/src/random_state.rs index 02abd2e93bd..f95116c04b6 100644 --- a/clippy_lints/src/random_state.rs +++ b/clippy_lints/src/random_state.rs @@ -35,11 +35,13 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &Ty) { - if let TyKind::Adt(_, substs) = cx.tables.node_id_to_type(ty.hir_id).sty { - for subst in substs { - if let UnpackedKind::Type(build_hasher) = subst.unpack() { - if match_type(cx, build_hasher, &paths::RANDOM_STATE) { - span_lint(cx, RANDOM_STATE, ty.span, "usage of RandomState"); + if let Some(tys) = cx.tables.node_id_to_type_opt(ty.hir_id) { + if let TyKind::Adt(_, substs) = tys.sty { + for subst in substs { + if let UnpackedKind::Type(build_hasher) = subst.unpack() { + if match_type(cx, build_hasher, &paths::RANDOM_STATE) { + span_lint(cx, RANDOM_STATE, ty.span, "usage of RandomState"); + } } } } -- cgit 1.4.1-3-g733a5 From 8c4c458ee93e53cc304d1a839d78ae18c4525b5d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 30 Dec 2018 12:41:37 +0100 Subject: UI test cleanup: Extract iter_skip_next from methods.rs cc #2038 --- tests/ui/iter_skip_next.rs | 61 ++++++++++++++++++++++++++++++++++++++++++ tests/ui/iter_skip_next.stderr | 28 +++++++++++++++++++ tests/ui/methods.rs | 12 --------- tests/ui/methods.stderr | 30 ++------------------- 4 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 tests/ui/iter_skip_next.rs create mode 100644 tests/ui/iter_skip_next.stderr diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs new file mode 100644 index 00000000000..4628bfbf301 --- /dev/null +++ b/tests/ui/iter_skip_next.rs @@ -0,0 +1,61 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::iter_skip_next)] +#![allow(clippy::blacklisted_name)] + +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +struct IteratorFalsePositives { + foo: u32, +} + +impl IteratorFalsePositives { + fn filter(self) -> IteratorFalsePositives { + self + } + + fn next(self) -> IteratorFalsePositives { + self + } + + fn find(self) -> Option { + Some(self.foo) + } + + fn position(self) -> Option { + Some(self.foo) + } + + fn rposition(self) -> Option { + Some(self.foo) + } + + fn nth(self, n: usize) -> Option { + Some(self.foo) + } + + fn skip(self, _: usize) -> IteratorFalsePositives { + self + } +} + +/// Checks implementation of `ITER_SKIP_NEXT` lint +fn iter_skip_next() { + let mut some_vec = vec![0, 1, 2, 3]; + let _ = some_vec.iter().skip(42).next(); + let _ = some_vec.iter().cycle().skip(42).next(); + let _ = (1..10).skip(10).next(); + let _ = &some_vec[..].iter().skip(3).next(); + let foo = IteratorFalsePositives { foo: 0 }; + let _ = foo.skip(42).next(); + let _ = foo.filter().skip(42).next(); +} + +fn main() {} diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr new file mode 100644 index 00000000000..6b65c1e4a1e --- /dev/null +++ b/tests/ui/iter_skip_next.stderr @@ -0,0 +1,28 @@ +error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` + --> $DIR/iter_skip_next.rs:52:13 + | +LL | let _ = some_vec.iter().skip(42).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-skip-next` implied by `-D warnings` + +error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` + --> $DIR/iter_skip_next.rs:53:13 + | +LL | let _ = some_vec.iter().cycle().skip(42).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` + --> $DIR/iter_skip_next.rs:54:13 + | +LL | let _ = (1..10).skip(10).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` + --> $DIR/iter_skip_next.rs:55:14 + | +LL | let _ = &some_vec[..].iter().skip(3).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index ebf71f67a00..b470a12f7a3 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -390,18 +390,6 @@ fn iter_nth() { let ok_mut = false_positive.iter_mut().nth(3); } -/// Checks implementation of `ITER_SKIP_NEXT` lint -fn iter_skip_next() { - let mut some_vec = vec![0, 1, 2, 3]; - let _ = some_vec.iter().skip(42).next(); - let _ = some_vec.iter().cycle().skip(42).next(); - let _ = (1..10).skip(10).next(); - let _ = &some_vec[..].iter().skip(3).next(); - let foo = IteratorFalsePositives { foo : 0 }; - let _ = foo.skip(42).next(); - let _ = foo.filter().skip(42).next(); -} - #[allow(clippy::similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index b0b693f3e16..e87e61fbe0e 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -367,39 +367,13 @@ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both fa LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:396:13 - | -LL | let _ = some_vec.iter().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-skip-next` implied by `-D warnings` - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:397:13 - | -LL | let _ = some_vec.iter().cycle().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:398:13 - | -LL | let _ = (1..10).skip(10).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:399:14 - | -LL | let _ = &some_vec[..].iter().skip(3).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:408:13 + --> $DIR/methods.rs:396:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 50 previous errors +error: aborting due to 46 previous errors -- cgit 1.4.1-3-g733a5 From 11b957e18d36c348279295ad056a1a535d8e9780 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 14:29:43 +0100 Subject: Reformat random_state tests --- tests/ui/random_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/random_state.rs b/tests/ui/random_state.rs index 31f4b4d49b4..f4fa85997a8 100644 --- a/tests/ui/random_state.rs +++ b/tests/ui/random_state.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::RandomState; use std::collections::hash_map::{DefaultHasher, HashMap}; -use std::hash::{BuildHasherDefault}; +use std::hash::BuildHasherDefault; fn main() { // Should warn -- cgit 1.4.1-3-g733a5 From d1dfd3e96f4b4ffd928501e6f253dee3c166c2c5 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Mon, 31 Dec 2018 10:44:27 +0100 Subject: Use hashset for name blacklist --- clippy_lints/src/blacklisted_name.rs | 7 ++++--- clippy_lints/src/lib.rs | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index ce7da419497..ed7437e495b 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -11,6 +11,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; /// **What it does:** Checks for usage of blacklisted names for variables, such /// as `foo`. @@ -32,11 +33,11 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct BlackListedName { - blacklist: Vec, + blacklist: FxHashSet, } impl BlackListedName { - pub fn new(blacklist: Vec) -> Self { + pub fn new(blacklist: FxHashSet) -> Self { Self { blacklist } } } @@ -50,7 +51,7 @@ impl LintPass for BlackListedName { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(_, _, ident, _) = pat.node { - if self.blacklist.iter().any(|s| ident.name == *s) { + if self.blacklist.contains(&ident.name.to_string()) { span_lint( cx, BLACKLISTED_NAME, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fb5a29dbd34..2e515cc8aea 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -423,7 +423,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default()); - reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone())); + reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new( + conf.blacklisted_names.iter().cloned().collect() + )); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); -- cgit 1.4.1-3-g733a5 From cc76384807ab0552697cf67631197266cb2f3ef4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 31 Dec 2018 12:12:50 +0100 Subject: Some improvements to util documentation --- clippy_lints/src/utils/mod.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e92529dc0a2..647bae1ae6b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -62,6 +62,15 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { rhs.ctxt() != lhs.ctxt() } +/// Returns `true` if the given `NodeId` is inside a constant context +/// +/// # Example +/// +/// ```rust,ignore +/// if in_constant(cx, expr.id) { +/// // Do something +/// } +/// ``` pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir().get_parent(id); match cx.tcx.hir().body_owner_kind(parent_id) { @@ -377,6 +386,9 @@ pub fn contains_name(name: Name, expr: &Expr) -> bool { /// Convert a span to a code snippet if available, otherwise use default. /// +/// This is useful if you want to provide suggestions for your lint or more generally, if you want +/// to convert a given `Span` to a `str`. +/// /// # Example /// ```rust,ignore /// snippet(cx, expr.span, "..") @@ -430,7 +442,7 @@ pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option /// /// # Example /// ```rust,ignore -/// snippet(cx, expr.span, "..") +/// snippet_block(cx, expr.span, "..") /// ``` pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { let snip = snippet(cx, span, default); @@ -741,6 +753,13 @@ pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { false } +/// Returns `true` if the given `Expr` has been coerced before. +/// +/// Examples of coercions can be found in the Nomicon at +/// . +/// +/// See `rustc::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more +/// information on adjustments and coercions. pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool { cx.tables.adjustments().get(e.hir_id).is_some() } -- cgit 1.4.1-3-g733a5 From f38fb56baf2921ed006a36c54df3add3b7605593 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Mon, 31 Dec 2018 12:06:08 +0100 Subject: Limit infinite_iter collect() check to known types --- clippy_lints/src/infinite_iter.rs | 20 ++++++++++++++++++-- tests/ui/infinite_iter.rs | 19 +++++++++++++++++++ tests/ui/infinite_iter.stderr | 10 +++++++++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 2f7c5895af8..e2da8461f41 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -7,7 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; +use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; @@ -200,7 +200,6 @@ static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[ /// their iterators static COMPLETING_METHODS: &[(&str, usize)] = &[ ("count", 1), - ("collect", 1), ("fold", 3), ("for_each", 2), ("partition", 2), @@ -214,6 +213,18 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[ ("product", 1), ]; +/// the paths of types that are known to be infinitely allocating +static INFINITE_COLLECTORS: &[&[&str]] = &[ + &paths::BINARY_HEAP, + &paths::BTREEMAP, + &paths::BTREESET, + &paths::HASHMAP, + &paths::HASHSET, + &paths::LINKED_LIST, + &paths::VEC, + &paths::VEC_DEQUE, +]; + fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { match expr.node { ExprKind::MethodCall(ref method, _, ref args) => { @@ -233,6 +244,11 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { if not_double_ended { return is_infinite(cx, &args[0]); } + } else if method.ident.name == "collect" { + let ty = cx.tables.expr_ty(expr); + if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) { + return is_infinite(cx, &args[0]); + } } }, ExprKind::Binary(op, ref l, ref r) => { diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 8f41e3ae98d..bd266368dc4 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -58,3 +58,22 @@ fn main() { infinite_iters(); potential_infinite_iters(); } + +mod finite_collect { + use std::collections::HashSet; + use std::iter::FromIterator; + + struct C; + impl FromIterator for C { + fn from_iter>(iter: I) -> Self { + C + } + } + + fn check_collect() { + let _: HashSet = (0..).collect(); // Infinite iter + + // Some data structures don't collect infinitely, such as `ArrayVec` + let _: C = (0..).collect(); + } +} diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index c64b3918db4..288285d9aae 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -105,5 +105,13 @@ error: possible infinite iteration detected LL | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: infinite iteration detected + --> $DIR/infinite_iter.rs:74:31 + | +LL | let _: HashSet = (0..).collect(); // Infinite iter + | ^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::infinite_iter)] on by default + +error: aborting due to 15 previous errors -- cgit 1.4.1-3-g733a5 From 5f9a65ffd69318d0a400a2f21e72e72444f1ac4a Mon Sep 17 00:00:00 2001 From: Yuning Zhang Date: Tue, 1 Jan 2019 20:34:02 -0500 Subject: Fix test for rust-lang/rust#57250 --- tests/ui/builtin-type-shadow.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 9bfed9dbba8..940a6dc2bcc 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -12,7 +12,7 @@ error[E0308]: mismatched types LL | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type LL | 42 - | ^^ expected type parameter, found integral variable + | ^^ expected type parameter, found integer | = note: expected type `u32` found type `{integer}` -- cgit 1.4.1-3-g733a5 From eaaee238472f36d664be0e0769590a8be374cd4d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 07:23:00 +0100 Subject: UI test cleanup: Extract lint from methods.rs test --- tests/auxiliary/option_helpers.rs | 6 ++ tests/ui/methods.rs | 32 +------- tests/ui/methods.stderr | 120 +++++++++++------------------- tests/ui/result_map_unwrap_or_else.rs | 37 +++++++++ tests/ui/result_map_unwrap_or_else.stderr | 34 +++++++++ 5 files changed, 123 insertions(+), 106 deletions(-) create mode 100644 tests/auxiliary/option_helpers.rs create mode 100644 tests/ui/result_map_unwrap_or_else.rs create mode 100644 tests/ui/result_map_unwrap_or_else.stderr diff --git a/tests/auxiliary/option_helpers.rs b/tests/auxiliary/option_helpers.rs new file mode 100644 index 00000000000..f8ce6ba3160 --- /dev/null +++ b/tests/auxiliary/option_helpers.rs @@ -0,0 +1,6 @@ +/// Utility macro to test linting behavior in `option_methods()` +/// The lints included in `option_methods()` should not lint if the call to map is partially +/// within a macro +macro_rules! opt_map { + ($opt:expr, $map:expr) => {($opt).map($map)}; +} diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index b470a12f7a3..b653d941fc1 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -31,6 +31,8 @@ use std::iter::FromIterator; use std::rc::{self, Rc}; use std::sync::{self, Arc}; +include!("../auxiliary/option_helpers.rs"); + pub struct T; impl T { @@ -101,13 +103,6 @@ impl Mul for T { fn mul(self, other: T) -> T { self } // no error, obviously } -/// Utility macro to test linting behavior in `option_methods()` -/// The lints included in `option_methods()` should not lint if the call to map is partially -/// within a macro -macro_rules! opt_map { - ($opt:expr, $map:expr) => {($opt).map($map)}; -} - /// Checks implementation of the following lints: /// * `OPTION_MAP_UNWRAP_OR` /// * `OPTION_MAP_UNWRAP_OR_ELSE` @@ -169,29 +164,6 @@ fn option_methods() { ); } -/// Checks implementation of the following lints: -/// * `RESULT_MAP_UNWRAP_OR_ELSE` -fn result_methods() { - let res: Result = Ok(1); - - // Check RESULT_MAP_UNWRAP_OR_ELSE - // single line case - let _ = res.map(|x| x + 1) - - .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - // multi line cases - let _ = res.map(|x| { - x + 1 - } - ).unwrap_or_else(|e| 0); - let _ = res.map(|x| x + 1) - .unwrap_or_else(|e| - 0 - ); - // macro case - let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint -} - /// Struct to generate false positives for things with .iter() #[derive(Copy, Clone)] struct HasIter; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index e87e61fbe0e..dc446ecf135 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:37:5 + --> $DIR/methods.rs:39:5 | LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn add(self, other: T) -> T { self } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:48:17 + --> $DIR/methods.rs:50:17 | LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ @@ -15,19 +15,19 @@ LL | fn into_u16(&self) -> u16 { 0 } = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:50:21 + --> $DIR/methods.rs:52:21 | LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:52:12 + --> $DIR/methods.rs:54:12 | LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:120:13 + --> $DIR/methods.rs:115:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -39,7 +39,7 @@ LL | | .unwrap_or(0); // should lint even though this call is on = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:124:13 + --> $DIR/methods.rs:119:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -49,7 +49,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:128:13 + --> $DIR/methods.rs:123:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -59,7 +59,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:133:13 + --> $DIR/methods.rs:128:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:135:13 + --> $DIR/methods.rs:130:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -77,7 +77,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:139:13 + --> $DIR/methods.rs:134:13 | LL | let _ = opt | _____________^ @@ -88,7 +88,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:147:13 + --> $DIR/methods.rs:142:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -100,7 +100,7 @@ LL | | .unwrap_or_else(|| 0); // should lint even though this cal = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:151:13 + --> $DIR/methods.rs:146:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -110,7 +110,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:155:13 + --> $DIR/methods.rs:150:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -120,7 +120,7 @@ LL | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:164:13 + --> $DIR/methods.rs:159:13 | LL | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` @@ -128,7 +128,7 @@ LL | let _ = opt.map_or(None, |x| Some(x + 1)); = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:166:13 + --> $DIR/methods.rs:161:13 | LL | let _ = opt.map_or(None, |x| { | _____________^ @@ -143,40 +143,8 @@ LL | Some(x + 1) LL | }); | -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:179:13 - | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | -LL | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - | |_____________________________________^ - | - = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` - -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:183:13 - | -LL | let _ = res.map(|x| { - | _____________^ -LL | | x + 1 -LL | | } -LL | | ).unwrap_or_else(|e| 0); - | |_____________________________________^ - -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:187:13 - | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | .unwrap_or_else(|e| -LL | | 0 -LL | | ); - | |_________________^ - error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:250:13 + --> $DIR/methods.rs:222:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +153,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:253:13 + --> $DIR/methods.rs:225:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -195,7 +163,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:268:13 + --> $DIR/methods.rs:240:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +172,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:271:13 + --> $DIR/methods.rs:243:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -214,7 +182,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:277:13 + --> $DIR/methods.rs:249:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +190,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:280:13 + --> $DIR/methods.rs:252:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -232,7 +200,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:286:13 + --> $DIR/methods.rs:258:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +208,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:289:13 + --> $DIR/methods.rs:261:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -250,7 +218,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:324:22 + --> $DIR/methods.rs:296:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -258,73 +226,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:327:5 + --> $DIR/methods.rs:299:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:330:21 + --> $DIR/methods.rs:302:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:333:14 + --> $DIR/methods.rs:305:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:336:19 + --> $DIR/methods.rs:308:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:339:5 + --> $DIR/methods.rs:311:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:342:5 + --> $DIR/methods.rs:314:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:345:14 + --> $DIR/methods.rs:317:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:350:21 + --> $DIR/methods.rs:322:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:353:19 + --> $DIR/methods.rs:325:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:356:21 + --> $DIR/methods.rs:328:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:359:21 + --> $DIR/methods.rs:331:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:370:23 + --> $DIR/methods.rs:342:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -332,48 +300,48 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:371:26 + --> $DIR/methods.rs:343:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:372:31 + --> $DIR/methods.rs:344:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:373:29 + --> $DIR/methods.rs:345:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:378:23 + --> $DIR/methods.rs:350:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:381:26 + --> $DIR/methods.rs:353:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:384:29 + --> $DIR/methods.rs:356:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:396:13 + --> $DIR/methods.rs:368:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 46 previous errors +error: aborting due to 43 previous errors diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs new file mode 100644 index 00000000000..2995babe30c --- /dev/null +++ b/tests/ui/result_map_unwrap_or_else.rs @@ -0,0 +1,37 @@ +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Checks implementation of `RESULT_MAP_UNWRAP_OR_ELSE` + +#![warn(clippy::result_map_unwrap_or_else)] + +include!("../auxiliary/option_helpers.rs"); + +fn result_methods() { + let res: Result = Ok(1); + + // Check RESULT_MAP_UNWRAP_OR_ELSE + // single line case + let _ = res.map(|x| x + 1) + + .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = res.map(|x| { + x + 1 + } + ).unwrap_or_else(|e| 0); + let _ = res.map(|x| x + 1) + .unwrap_or_else(|e| + 0 + ); + // macro case + let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint +} + +fn main() {} diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr new file mode 100644 index 00000000000..fb1555b4f6e --- /dev/null +++ b/tests/ui/result_map_unwrap_or_else.stderr @@ -0,0 +1,34 @@ +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:21:13 + | +LL | let _ = res.map(|x| x + 1) + | _____________^ +LL | | +LL | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | |_____________________________________^ + | + = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:25:13 + | +LL | let _ = res.map(|x| { + | _____________^ +LL | | x + 1 +LL | | } +LL | | ).unwrap_or_else(|e| 0); + | |_____________________________________^ + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:29:13 + | +LL | let _ = res.map(|x| x + 1) + | _____________^ +LL | | .unwrap_or_else(|e| +LL | | 0 +LL | | ); + | |_________________^ + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From b38a2d7ce9698a85a1874ed1c92386f0070c4fc9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 07:42:04 +0100 Subject: UI test cleanup: Extract for_kv_map lint tests --- tests/ui/for_kv_map.rs | 56 ++++++++++++++++++++++++++++++++++ tests/ui/for_kv_map.stderr | 54 ++++++++++++++++++++++++++++++++ tests/ui/for_loop.rs | 42 ------------------------- tests/ui/for_loop.stderr | 76 ++++++++-------------------------------------- 4 files changed, 122 insertions(+), 106 deletions(-) create mode 100644 tests/ui/for_kv_map.rs create mode 100644 tests/ui/for_kv_map.stderr diff --git a/tests/ui/for_kv_map.rs b/tests/ui/for_kv_map.rs new file mode 100644 index 00000000000..d79ea4bebeb --- /dev/null +++ b/tests/ui/for_kv_map.rs @@ -0,0 +1,56 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::for_kv_map)] +#![allow(clippy::used_underscore_binding)] + +use std::collections::*; +use std::rc::Rc; + +fn main() { + let m: HashMap = HashMap::new(); + for (_, v) in &m { + let _v = v; + } + + let m: Rc> = Rc::new(HashMap::new()); + for (_, v) in &*m { + let _v = v; + // Here the `*` is not actually necessary, but the test tests that we don't + // suggest + // `in *m.values()` as we used to + } + + let mut m: HashMap = HashMap::new(); + for (_, v) in &mut m { + let _v = v; + } + + let m: &mut HashMap = &mut HashMap::new(); + for (_, v) in &mut *m { + let _v = v; + } + + let m: HashMap = HashMap::new(); + let rm = &m; + for (k, _value) in rm { + let _k = k; + } + test_for_kv_map(); +} + +fn test_for_kv_map() { + let m: HashMap = HashMap::new(); + + // No error, _value is actually used + for (k, _value) in &m { + let _ = _value; + let _k = k; + } +} diff --git a/tests/ui/for_kv_map.stderr b/tests/ui/for_kv_map.stderr new file mode 100644 index 00000000000..7b65c58f58d --- /dev/null +++ b/tests/ui/for_kv_map.stderr @@ -0,0 +1,54 @@ +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:18:19 + | +LL | for (_, v) in &m { + | ^^ + | + = note: `-D clippy::for-kv-map` implied by `-D warnings` +help: use the corresponding method + | +LL | for v in m.values() { + | ^ ^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:23:19 + | +LL | for (_, v) in &*m { + | ^^^ +help: use the corresponding method + | +LL | for v in (*m).values() { + | ^ ^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:31:19 + | +LL | for (_, v) in &mut m { + | ^^^^^^ +help: use the corresponding method + | +LL | for v in m.values_mut() { + | ^ ^^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:36:19 + | +LL | for (_, v) in &mut *m { + | ^^^^^^^ +help: use the corresponding method + | +LL | for v in (*m).values_mut() { + | ^ ^^^^^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's keys + --> $DIR/for_kv_map.rs:42:24 + | +LL | for (k, _value) in rm { + | ^^ +help: use the corresponding method + | +LL | for k in rm.keys() { + | ^ ^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 4747269bccd..c172b0b3b77 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -333,37 +333,6 @@ fn main() { } println!("index: {}", index); - let m: HashMap = HashMap::new(); - for (_, v) in &m { - let _v = v; - } - - let m: Rc> = Rc::new(HashMap::new()); - for (_, v) in &*m { - let _v = v; - // Here the `*` is not actually necessary, but the test tests that we don't - // suggest - // `in *m.values()` as we used to - } - - let mut m: HashMap = HashMap::new(); - for (_, v) in &mut m { - let _v = v; - } - - let m: &mut HashMap = &mut HashMap::new(); - for (_, v) in &mut *m { - let _v = v; - } - - let m: HashMap = HashMap::new(); - let rm = &m; - for (k, _value) in rm { - let _k = k; - } - - test_for_kv_map(); - fn f(_: &T, _: &T) -> bool { unimplemented!() } @@ -381,17 +350,6 @@ fn main() { } } -#[allow(clippy::used_underscore_binding)] -fn test_for_kv_map() { - let m: HashMap = HashMap::new(); - - // No error, _value is actually used - for (k, _value) in &m { - let _ = _value; - let _k = k; - } -} - #[allow(dead_code)] fn partition(v: &mut [T]) -> usize { let pivot = v.len() - 1; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 937bef9f8a6..4ded425b321 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -292,60 +292,8 @@ LL | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | = note: `-D clippy::unused-collect` implied by `-D warnings` -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:337:19 - | -LL | for (_, v) in &m { - | ^^ - | - = note: `-D clippy::for-kv-map` implied by `-D warnings` -help: use the corresponding method - | -LL | for v in m.values() { - | ^ ^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:342:19 - | -LL | for (_, v) in &*m { - | ^^^ -help: use the corresponding method - | -LL | for v in (*m).values() { - | ^ ^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:350:19 - | -LL | for (_, v) in &mut m { - | ^^^^^^ -help: use the corresponding method - | -LL | for v in m.values_mut() { - | ^ ^^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:355:19 - | -LL | for (_, v) in &mut *m { - | ^^^^^^^ -help: use the corresponding method - | -LL | for v in (*m).values_mut() { - | ^ ^^^^^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:361:24 - | -LL | for (k, _value) in rm { - | ^^ -help: use the corresponding method - | -LL | for k in rm.keys() { - | ^ ^^^^^^^^^ - error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:414:14 + --> $DIR/for_loop.rs:372:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` @@ -353,31 +301,31 @@ LL | for i in 0..src.len() { = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:419:14 + --> $DIR/for_loop.rs:377:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:424:14 + --> $DIR/for_loop.rs:382:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:429:14 + --> $DIR/for_loop.rs:387:14 | LL | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:434:14 + --> $DIR/for_loop.rs:392:14 | LL | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:447:14 + --> $DIR/for_loop.rs:405:14 | LL | for i in 10..256 { | ^^^^^^^ @@ -388,34 +336,34 @@ LL | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:459:14 + --> $DIR/for_loop.rs:417:14 | LL | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 + --> $DIR/for_loop.rs:430:14 | LL | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:501:14 + --> $DIR/for_loop.rs:459:14 | LL | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:505:14 + --> $DIR/for_loop.rs:463:14 | LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:512:14 + --> $DIR/for_loop.rs:470:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 51 previous errors +error: aborting due to 46 previous errors -- cgit 1.4.1-3-g733a5 From 0c54913afef6b5ca2e6c037bbbfb25e67f9a560a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 07:27:47 +0100 Subject: Extract IteratorFalsePositives into option_helpers.rs This was previously duplicated in #3605 --- tests/auxiliary/option_helpers.rs | 36 +++++++++++++++++++++++++ tests/ui/iter_skip_next.rs | 36 +------------------------ tests/ui/iter_skip_next.stderr | 8 +++--- tests/ui/methods.rs | 36 ------------------------- tests/ui/methods.stderr | 56 +++++++++++++++++++-------------------- 5 files changed, 69 insertions(+), 103 deletions(-) diff --git a/tests/auxiliary/option_helpers.rs b/tests/auxiliary/option_helpers.rs index f8ce6ba3160..1734acfb3a2 100644 --- a/tests/auxiliary/option_helpers.rs +++ b/tests/auxiliary/option_helpers.rs @@ -4,3 +4,39 @@ macro_rules! opt_map { ($opt:expr, $map:expr) => {($opt).map($map)}; } + +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +struct IteratorFalsePositives { + foo: u32, +} + +impl IteratorFalsePositives { + fn filter(self) -> IteratorFalsePositives { + self + } + + fn next(self) -> IteratorFalsePositives { + self + } + + fn find(self) -> Option { + Some(self.foo) + } + + fn position(self) -> Option { + Some(self.foo) + } + + fn rposition(self) -> Option { + Some(self.foo) + } + + fn nth(self, n: usize) -> Option { + Some(self.foo) + } + + fn skip(self, _: usize) -> IteratorFalsePositives { + self + } +} diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 4628bfbf301..a2ce67ce35d 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -10,41 +10,7 @@ #![warn(clippy::iter_skip_next)] #![allow(clippy::blacklisted_name)] -/// Struct to generate false positive for Iterator-based lints -#[derive(Copy, Clone)] -struct IteratorFalsePositives { - foo: u32, -} - -impl IteratorFalsePositives { - fn filter(self) -> IteratorFalsePositives { - self - } - - fn next(self) -> IteratorFalsePositives { - self - } - - fn find(self) -> Option { - Some(self.foo) - } - - fn position(self) -> Option { - Some(self.foo) - } - - fn rposition(self) -> Option { - Some(self.foo) - } - - fn nth(self, n: usize) -> Option { - Some(self.foo) - } - - fn skip(self, _: usize) -> IteratorFalsePositives { - self - } -} +include!("../auxiliary/option_helpers.rs"); /// Checks implementation of `ITER_SKIP_NEXT` lint fn iter_skip_next() { diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 6b65c1e4a1e..9daa97e7758 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:52:13 + --> $DIR/iter_skip_next.rs:18:13 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:53:13 + --> $DIR/iter_skip_next.rs:19:13 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:54:13 + --> $DIR/iter_skip_next.rs:20:13 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:55:14 + --> $DIR/iter_skip_next.rs:21:14 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index b653d941fc1..d5859b8f840 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -178,42 +178,6 @@ impl HasIter { } } -/// Struct to generate false positive for Iterator-based lints -#[derive(Copy, Clone)] -struct IteratorFalsePositives { - foo: u32, -} - -impl IteratorFalsePositives { - fn filter(self) -> IteratorFalsePositives { - self - } - - fn next(self) -> IteratorFalsePositives { - self - } - - fn find(self) -> Option { - Some(self.foo) - } - - fn position(self) -> Option { - Some(self.foo) - } - - fn rposition(self) -> Option { - Some(self.foo) - } - - fn nth(self, n: usize) -> Option { - Some(self.foo) - } - - fn skip(self, _: usize) -> IteratorFalsePositives { - self - } -} - /// Checks implementation of `FILTER_NEXT` lint fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index dc446ecf135..361a763efd3 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -144,7 +144,7 @@ LL | }); | error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:222:13 + --> $DIR/methods.rs:186:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:225:13 + --> $DIR/methods.rs:189:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -163,7 +163,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:240:13 + --> $DIR/methods.rs:204:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:243:13 + --> $DIR/methods.rs:207:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -182,7 +182,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:249:13 + --> $DIR/methods.rs:213:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:252:13 + --> $DIR/methods.rs:216:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -200,7 +200,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:258:13 + --> $DIR/methods.rs:222:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:261:13 + --> $DIR/methods.rs:225:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -218,7 +218,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:296:22 + --> $DIR/methods.rs:260:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -226,73 +226,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:299:5 + --> $DIR/methods.rs:263:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:302:21 + --> $DIR/methods.rs:266:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:305:14 + --> $DIR/methods.rs:269:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:308:19 + --> $DIR/methods.rs:272:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:311:5 + --> $DIR/methods.rs:275:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:314:5 + --> $DIR/methods.rs:278:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:317:14 + --> $DIR/methods.rs:281:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:322:21 + --> $DIR/methods.rs:286:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:325:19 + --> $DIR/methods.rs:289:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:328:21 + --> $DIR/methods.rs:292:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:331:21 + --> $DIR/methods.rs:295:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:342:23 + --> $DIR/methods.rs:306:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,43 +300,43 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:343:26 + --> $DIR/methods.rs:307:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:344:31 + --> $DIR/methods.rs:308:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:345:29 + --> $DIR/methods.rs:309:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:350:23 + --> $DIR/methods.rs:314:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:353:26 + --> $DIR/methods.rs:317:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:356:29 + --> $DIR/methods.rs:320:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:368:13 + --> $DIR/methods.rs:332:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 3b035373b2804f831df2c71e3b8862a9a94929e3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 07:59:48 +0100 Subject: UI test cleanup: Extract ifs_same_cond tests --- tests/ui/copies.rs | 44 ----------------------------------------- tests/ui/copies.stderr | 39 +----------------------------------- tests/ui/ifs_same_cond.rs | 46 +++++++++++++++++++++++++++++++++++++++++++ tests/ui/ifs_same_cond.stderr | 39 ++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 82 deletions(-) create mode 100644 tests/ui/ifs_same_cond.rs create mode 100644 tests/ui/ifs_same_cond.stderr diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 8147edb98eb..5db82006dea 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -348,50 +348,6 @@ fn if_same_then_else() -> Result<&'static str, ()> { } } -#[warn(clippy::ifs_same_cond)] -#[allow(clippy::if_same_then_else)] // all empty blocks -fn ifs_same_cond() { - let a = 0; - let b = false; - - if b { - } else if b { - //~ ERROR ifs same condition - } - - if a == 1 { - } else if a == 1 { - //~ ERROR ifs same condition - } - - if 2 * a == 1 { - } else if 2 * a == 2 { - } else if 2 * a == 1 { - //~ ERROR ifs same condition - } else if a == 1 { - } - - // See #659 - if cfg!(feature = "feature1-659") { - 1 - } else if cfg!(feature = "feature2-659") { - 2 - } else { - 3 - }; - - let mut v = vec![1]; - if v.pop() == None { - // ok, functions - } else if v.pop() == None { - } - - if v.len() == 42 { - // ok, functions - } else if v.len() == 42 { - } -} - fn main() {} // Issue #2423. This was causing an ICE diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 4c0bc4b0173..3fbc279b537 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -351,42 +351,5 @@ LL | | try!(Ok("foo")); LL | | } else { | |_____^ -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:15 - | -LL | } else if b { - | ^ - | - = note: `-D clippy::ifs-same-cond` implied by `-D warnings` -note: same as this - --> $DIR/copies.rs:357:8 - | -LL | if b { - | ^ - -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:363:15 - | -LL | } else if a == 1 { - | ^^^^^^ - | -note: same as this - --> $DIR/copies.rs:362:8 - | -LL | if a == 1 { - | ^^^^^^ - -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:369:15 - | -LL | } else if 2 * a == 1 { - | ^^^^^^^^^^ - | -note: same as this - --> $DIR/copies.rs:367:8 - | -LL | if 2 * a == 1 { - | ^^^^^^^^^^ - -error: aborting due to 20 previous errors +error: aborting due to 17 previous errors diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs new file mode 100644 index 00000000000..b67e730b937 --- /dev/null +++ b/tests/ui/ifs_same_cond.rs @@ -0,0 +1,46 @@ +#![warn(clippy::ifs_same_cond)] +#![allow(clippy::if_same_then_else)] // all empty blocks + +fn ifs_same_cond() { + let a = 0; + let b = false; + + if b { + } else if b { + //~ ERROR ifs same condition + } + + if a == 1 { + } else if a == 1 { + //~ ERROR ifs same condition + } + + if 2 * a == 1 { + } else if 2 * a == 2 { + } else if 2 * a == 1 { + //~ ERROR ifs same condition + } else if a == 1 { + } + + // See #659 + if cfg!(feature = "feature1-659") { + 1 + } else if cfg!(feature = "feature2-659") { + 2 + } else { + 3 + }; + + let mut v = vec![1]; + if v.pop() == None { + // ok, functions + } else if v.pop() == None { + } + + if v.len() == 42 { + // ok, functions + } else if v.len() == 42 { + } +} + +fn main() {} diff --git a/tests/ui/ifs_same_cond.stderr b/tests/ui/ifs_same_cond.stderr new file mode 100644 index 00000000000..0b0dd24194e --- /dev/null +++ b/tests/ui/ifs_same_cond.stderr @@ -0,0 +1,39 @@ +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:9:15 + | +LL | } else if b { + | ^ + | + = note: `-D clippy::ifs-same-cond` implied by `-D warnings` +note: same as this + --> $DIR/ifs_same_cond.rs:8:8 + | +LL | if b { + | ^ + +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:14:15 + | +LL | } else if a == 1 { + | ^^^^^^ + | +note: same as this + --> $DIR/ifs_same_cond.rs:13:8 + | +LL | if a == 1 { + | ^^^^^^ + +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:20:15 + | +LL | } else if 2 * a == 1 { + | ^^^^^^^^^^ + | +note: same as this + --> $DIR/ifs_same_cond.rs:18:8 + | +LL | if 2 * a == 1 { + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From c84a894ed7fa16c13a7e9395b85990cb2dacf71a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 08:15:32 +0100 Subject: rustfmt --- tests/auxiliary/option_helpers.rs | 4 +++- tests/ui/result_map_unwrap_or_else.rs | 16 ++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/auxiliary/option_helpers.rs b/tests/auxiliary/option_helpers.rs index 1734acfb3a2..add237d6fe0 100644 --- a/tests/auxiliary/option_helpers.rs +++ b/tests/auxiliary/option_helpers.rs @@ -2,7 +2,9 @@ /// The lints included in `option_methods()` should not lint if the call to map is partially /// within a macro macro_rules! opt_map { - ($opt:expr, $map:expr) => {($opt).map($map)}; + ($opt:expr, $map:expr) => { + ($opt).map($map) + }; } /// Struct to generate false positive for Iterator-based lints diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs index 2995babe30c..b3f83239961 100644 --- a/tests/ui/result_map_unwrap_or_else.rs +++ b/tests/ui/result_map_unwrap_or_else.rs @@ -18,18 +18,10 @@ fn result_methods() { // Check RESULT_MAP_UNWRAP_OR_ELSE // single line case - let _ = res.map(|x| x + 1) - - .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - // multi line cases - let _ = res.map(|x| { - x + 1 - } - ).unwrap_or_else(|e| 0); - let _ = res.map(|x| x + 1) - .unwrap_or_else(|e| - 0 - ); + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // macro case let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint } -- cgit 1.4.1-3-g733a5 From 31d96300ef7cfebe99bc2aa20834e514466f8b80 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 2 Jan 2019 20:12:15 +0100 Subject: rustc_tool_utils: fix failure to create proper non-repo version string when used in crates on crates.io, bump version --- rustc_tools_util/Cargo.toml | 2 +- rustc_tools_util/src/lib.rs | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index b73d7ca5606..70ff86c49af 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_tools_util" -version = "0.1.0" +version = "0.1.1" authors = ["Matthias Krüger "] description = "small helper to generate version information for git packages" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index d1640c758bb..49bfb7d8b59 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -46,16 +46,17 @@ pub struct VersionInfo { impl std::fmt::Display for VersionInfo { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.commit_hash.is_some() { + let hash = self.commit_hash.clone().unwrap_or_default(); + let hash_trimmed = hash.trim(); + + let date = self.commit_date.clone().unwrap_or_default(); + let date_trimmed = date.trim(); + + if (hash_trimmed.len() + date_trimmed.len()) > 0 { write!( f, "{} {}.{}.{} ({} {})", - self.crate_name, - self.major, - self.minor, - self.patch, - self.commit_hash.clone().unwrap_or_default().trim(), - self.commit_date.clone().unwrap_or_default().trim(), + self.crate_name, self.major, self.minor, self.patch, hash_trimmed, date_trimmed, )?; } else { write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?; @@ -121,7 +122,7 @@ mod test { let vi = get_version_info!(); assert_eq!(vi.major, 0); assert_eq!(vi.minor, 1); - assert_eq!(vi.patch, 0); + assert_eq!(vi.patch, 1); assert_eq!(vi.crate_name, "rustc_tools_util"); // hard to make positive tests for these since they will always change assert!(vi.commit_hash.is_none()); @@ -131,7 +132,7 @@ mod test { #[test] fn test_display_local() { let vi = get_version_info!(); - assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0"); + assert_eq!(vi.to_string(), "rustc_tools_util 0.1.1"); } #[test] @@ -140,7 +141,7 @@ mod test { let s = format!("{:?}", vi); assert_eq!( s, - "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }" + "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 1 }" ); } -- cgit 1.4.1-3-g733a5 From a5d3f37c5aaaaa9bc7b327ec240adf3d421ad610 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 2 Jan 2019 22:48:44 +0100 Subject: Use compiletest's aux-build header instead of include macro --- tests/auxiliary/option_helpers.rs | 44 ---------------- tests/ui/auxiliary/option_helpers.rs | 47 +++++++++++++++++ tests/ui/iter_skip_next.rs | 6 ++- tests/ui/iter_skip_next.stderr | 8 +-- tests/ui/methods.rs | 7 ++- tests/ui/methods.stderr | 86 +++++++++++++++---------------- tests/ui/result_map_unwrap_or_else.rs | 5 +- tests/ui/result_map_unwrap_or_else.stderr | 33 +++++------- 8 files changed, 122 insertions(+), 114 deletions(-) delete mode 100644 tests/auxiliary/option_helpers.rs create mode 100644 tests/ui/auxiliary/option_helpers.rs diff --git a/tests/auxiliary/option_helpers.rs b/tests/auxiliary/option_helpers.rs deleted file mode 100644 index add237d6fe0..00000000000 --- a/tests/auxiliary/option_helpers.rs +++ /dev/null @@ -1,44 +0,0 @@ -/// Utility macro to test linting behavior in `option_methods()` -/// The lints included in `option_methods()` should not lint if the call to map is partially -/// within a macro -macro_rules! opt_map { - ($opt:expr, $map:expr) => { - ($opt).map($map) - }; -} - -/// Struct to generate false positive for Iterator-based lints -#[derive(Copy, Clone)] -struct IteratorFalsePositives { - foo: u32, -} - -impl IteratorFalsePositives { - fn filter(self) -> IteratorFalsePositives { - self - } - - fn next(self) -> IteratorFalsePositives { - self - } - - fn find(self) -> Option { - Some(self.foo) - } - - fn position(self) -> Option { - Some(self.foo) - } - - fn rposition(self) -> Option { - Some(self.foo) - } - - fn nth(self, n: usize) -> Option { - Some(self.foo) - } - - fn skip(self, _: usize) -> IteratorFalsePositives { - self - } -} diff --git a/tests/ui/auxiliary/option_helpers.rs b/tests/ui/auxiliary/option_helpers.rs new file mode 100644 index 00000000000..33195211968 --- /dev/null +++ b/tests/ui/auxiliary/option_helpers.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, unused_variables)] + +/// Utility macro to test linting behavior in `option_methods()` +/// The lints included in `option_methods()` should not lint if the call to map is partially +/// within a macro +#[macro_export] +macro_rules! opt_map { + ($opt:expr, $map:expr) => { + ($opt).map($map) + }; +} + +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +pub struct IteratorFalsePositives { + pub foo: u32, +} + +impl IteratorFalsePositives { + pub fn filter(self) -> IteratorFalsePositives { + self + } + + pub fn next(self) -> IteratorFalsePositives { + self + } + + pub fn find(self) -> Option { + Some(self.foo) + } + + pub fn position(self) -> Option { + Some(self.foo) + } + + pub fn rposition(self) -> Option { + Some(self.foo) + } + + pub fn nth(self, n: usize) -> Option { + Some(self.foo) + } + + pub fn skip(self, _: usize) -> IteratorFalsePositives { + self + } +} diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index a2ce67ce35d..0b9d2c36827 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -7,10 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:option_helpers.rs + #![warn(clippy::iter_skip_next)] #![allow(clippy::blacklisted_name)] -include!("../auxiliary/option_helpers.rs"); +extern crate option_helpers; + +use option_helpers::IteratorFalsePositives; /// Checks implementation of `ITER_SKIP_NEXT` lint fn iter_skip_next() { diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 9daa97e7758..037c33fbc3d 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:18:13 + --> $DIR/iter_skip_next.rs:22:13 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:19:13 + --> $DIR/iter_skip_next.rs:23:13 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:20:13 + --> $DIR/iter_skip_next.rs:24:13 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:21:14 + --> $DIR/iter_skip_next.rs:25:14 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index d5859b8f840..fa99205d69a 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:option_helpers.rs + #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] #![allow( clippy::blacklisted_name, @@ -22,6 +24,9 @@ clippy::useless_format )] +#[macro_use] +extern crate option_helpers; + use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::HashSet; @@ -31,7 +36,7 @@ use std::iter::FromIterator; use std::rc::{self, Rc}; use std::sync::{self, Arc}; -include!("../auxiliary/option_helpers.rs"); +use option_helpers::IteratorFalsePositives; pub struct T; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 361a763efd3..ef3a4e2a423 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:39:5 + --> $DIR/methods.rs:44:5 | LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn add(self, other: T) -> T { self } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:50:17 + --> $DIR/methods.rs:55:17 | LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ @@ -15,19 +15,19 @@ LL | fn into_u16(&self) -> u16 { 0 } = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:52:21 + --> $DIR/methods.rs:57:21 | LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:54:12 + --> $DIR/methods.rs:59:12 | LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:115:13 + --> $DIR/methods.rs:120:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -39,7 +39,7 @@ LL | | .unwrap_or(0); // should lint even though this call is on = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:119:13 + --> $DIR/methods.rs:124:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -49,7 +49,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:123:13 + --> $DIR/methods.rs:128:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -59,7 +59,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:128:13 + --> $DIR/methods.rs:133:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:130:13 + --> $DIR/methods.rs:135:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -77,7 +77,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:134:13 + --> $DIR/methods.rs:139:13 | LL | let _ = opt | _____________^ @@ -88,7 +88,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:142:13 + --> $DIR/methods.rs:147:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -100,7 +100,7 @@ LL | | .unwrap_or_else(|| 0); // should lint even though this cal = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:146:13 + --> $DIR/methods.rs:151:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -110,7 +110,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:150:13 + --> $DIR/methods.rs:155:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -120,7 +120,7 @@ LL | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:159:13 + --> $DIR/methods.rs:164:13 | LL | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` @@ -128,7 +128,7 @@ LL | let _ = opt.map_or(None, |x| Some(x + 1)); = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:161:13 + --> $DIR/methods.rs:166:13 | LL | let _ = opt.map_or(None, |x| { | _____________^ @@ -144,7 +144,7 @@ LL | }); | error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:186:13 + --> $DIR/methods.rs:191:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:189:13 + --> $DIR/methods.rs:194:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -163,7 +163,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:204:13 + --> $DIR/methods.rs:209:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:207:13 + --> $DIR/methods.rs:212:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -182,7 +182,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:213:13 + --> $DIR/methods.rs:218:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:216:13 + --> $DIR/methods.rs:221:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -200,7 +200,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:222:13 + --> $DIR/methods.rs:227:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:225:13 + --> $DIR/methods.rs:230:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -218,7 +218,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:260:22 + --> $DIR/methods.rs:265:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -226,73 +226,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:263:5 + --> $DIR/methods.rs:268:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:266:21 + --> $DIR/methods.rs:271:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:269:14 + --> $DIR/methods.rs:274:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:272:19 + --> $DIR/methods.rs:277:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:275:5 + --> $DIR/methods.rs:280:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:278:5 + --> $DIR/methods.rs:283:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:281:14 + --> $DIR/methods.rs:286:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:286:21 + --> $DIR/methods.rs:291:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:289:19 + --> $DIR/methods.rs:294:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:292:21 + --> $DIR/methods.rs:297:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:295:21 + --> $DIR/methods.rs:300:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:306:23 + --> $DIR/methods.rs:311:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,43 +300,43 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:307:26 + --> $DIR/methods.rs:312:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:308:31 + --> $DIR/methods.rs:313:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:309:29 + --> $DIR/methods.rs:314:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:314:23 + --> $DIR/methods.rs:319:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:317:26 + --> $DIR/methods.rs:322:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:320:29 + --> $DIR/methods.rs:325:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:332:13 + --> $DIR/methods.rs:337:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs index b3f83239961..0481e4ec1b0 100644 --- a/tests/ui/result_map_unwrap_or_else.rs +++ b/tests/ui/result_map_unwrap_or_else.rs @@ -7,11 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:option_helpers.rs + //! Checks implementation of `RESULT_MAP_UNWRAP_OR_ELSE` #![warn(clippy::result_map_unwrap_or_else)] -include!("../auxiliary/option_helpers.rs"); +#[macro_use] +extern crate option_helpers; fn result_methods() { let res: Result = Ok(1); diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr index fb1555b4f6e..9f03de669e4 100644 --- a/tests/ui/result_map_unwrap_or_else.stderr +++ b/tests/ui/result_map_unwrap_or_else.stderr @@ -1,34 +1,27 @@ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:21:13 + --> $DIR/result_map_unwrap_or_else.rs:24:13 | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | -LL | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - | |_____________________________________^ +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:25:13 + --> $DIR/result_map_unwrap_or_else.rs:26:13 | -LL | let _ = res.map(|x| { - | _____________^ -LL | | x + 1 -LL | | } -LL | | ).unwrap_or_else(|e| 0); - | |_____________________________________^ +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:29:13 + --> $DIR/result_map_unwrap_or_else.rs:27:13 | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | .unwrap_or_else(|e| -LL | | 0 -LL | | ); - | |_________________^ +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From a49ed381bdf9c24da7cd5638e1c174cc07b3ae1c Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 3 Jan 2019 03:19:15 +0100 Subject: deps: bump rustc_tools_util version from 0.1.0 to 0.1.1 just in case... --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 359a6e43bdb..3478e496f8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" -rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } @@ -61,7 +61,7 @@ derive-new = "0.5" rustc-workspace-hack = "1.0.0" [build-dependencies] -rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [features] debugging = [] -- cgit 1.4.1-3-g733a5 From 24ff813f543e0bf24efc12ee7f305b245f012e82 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 3 Jan 2019 11:08:05 +0100 Subject: add testcase for #3462 --- tests/run-pass/ice-3462.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/run-pass/ice-3462.rs diff --git a/tests/run-pass/ice-3462.rs b/tests/run-pass/ice-3462.rs new file mode 100644 index 00000000000..8aea905cd80 --- /dev/null +++ b/tests/run-pass/ice-3462.rs @@ -0,0 +1,30 @@ +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::all)] +#![allow(clippy::blacklisted_name)] +#![allow(unused)] + +enum Foo { + Bar, + Baz, +} + +fn bar(foo: Foo) { + macro_rules! baz { + () => { + if let Foo::Bar = foo {} + }; + } + + baz!(); + baz!(); +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From ec1395aafbf4c95ad9043cc256eb66bd0d622bb5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 3 Jan 2019 15:42:59 +0100 Subject: Update to latest compiletest-rs release --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 13d081e92cf..17ddda4e8dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6.2" -compiletest_rs = { git = "https://github.com/phansch/compiletest-rs.git", branch = "add_rustfix_support" } +compiletest_rs = "0.3.18" lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } -- cgit 1.4.1-3-g733a5 From 5f0d46cd48c9281b3502d5aa2047124f3ee6b2e0 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Thu, 3 Jan 2019 19:07:21 +0100 Subject: Add ui/for_kv_map test for false positive in #1279 --- tests/ui/for_kv_map.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/ui/for_kv_map.rs b/tests/ui/for_kv_map.rs index d79ea4bebeb..549187756ab 100644 --- a/tests/ui/for_kv_map.rs +++ b/tests/ui/for_kv_map.rs @@ -42,15 +42,18 @@ fn main() { for (k, _value) in rm { let _k = k; } - test_for_kv_map(); -} -fn test_for_kv_map() { - let m: HashMap = HashMap::new(); + // The following should not produce warnings. + let m: HashMap = HashMap::new(); // No error, _value is actually used for (k, _value) in &m { let _ = _value; let _k = k; } + + let m: HashMap = Default::default(); + for (_, v) in m { + let _v = v; + } } -- cgit 1.4.1-3-g733a5 From 3af68f831a27b024a95c80cd2f9a9fe7f25eeb18 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Thu, 3 Jan 2019 18:17:43 +0100 Subject: Make clippy work with parallel rustc --- clippy_lints/src/consts.rs | 6 +++--- clippy_lints/src/enum_variants.rs | 6 +++--- clippy_lints/src/utils/mod.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index a1fe13e4962..8369f4b4470 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -17,11 +17,11 @@ use rustc::lint::LateContext; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc::{bug, span_bug}; +use rustc_data_structures::sync::Lrc; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::rc::Rc; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; @@ -31,7 +31,7 @@ pub enum Constant { /// a String "abc" Str(String), /// a Binary String b"abc" - Binary(Rc>), + Binary(Lrc>), /// a single char 'a' Char(char), /// an integer's bit representation @@ -156,7 +156,7 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), - LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), + LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, _) | LitKind::FloatUnsuffixed(ref is) => match ty.sty { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c5d7094dcc1..5466baae886 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -15,7 +15,7 @@ use rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; -use syntax::symbol::LocalInternedString; +use syntax::symbol::{InternedString, LocalInternedString}; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. @@ -111,7 +111,7 @@ declare_clippy_lint! { } pub struct EnumVariantNames { - modules: Vec<(LocalInternedString, String)>, + modules: Vec<(InternedString, String)>, threshold: u64, } @@ -308,6 +308,6 @@ impl EarlyLintPass for EnumVariantNames { }; check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint); } - self.modules.push((item_name, item_camel)); + self.modules.push((item_name.as_interned_str(), item_camel)); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 647bae1ae6b..edf8fb8d033 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -25,11 +25,11 @@ use rustc::ty::{ subst::Kind, Binder, Ty, TyCtxt, }; +use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; use std::mem; -use std::rc::Rc; use std::str::FromStr; use syntax::ast::{self, LitKind}; use syntax::attr; @@ -223,7 +223,7 @@ pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option None => return None, }; - for item in mem::replace(&mut items, Rc::new(vec![])).iter() { + for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return Some(item.def); -- cgit 1.4.1-3-g733a5 From d1fffe07c5cde9ff8c830f27c26fefe8aec363d4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 3 Jan 2019 21:54:57 +0100 Subject: rustup: https://github.com/rust-lang/rust/pull/55517 --- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/utils/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 63a3a831304..c1a76eed928 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -113,7 +113,7 @@ impl Pass { fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { let expr_ty = cx.tables.expr_ty(expression); - expr_ty.moves_by_default(cx.tcx, cx.param_env, expression.span) + !expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span) } fn is_option(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 647bae1ae6b..99d27d6fc19 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -271,7 +271,7 @@ pub fn implements_trait<'a, 'tcx>( ); cx.tcx .infer_ctxt() - .enter(|infcx| infcx.predicate_must_hold(&obligation)) + .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) } /// Check whether this type implements Drop. @@ -884,7 +884,7 @@ pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx } pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - !ty.moves_by_default(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) + ty.is_copy_modulo_regions(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) } /// Return whether a pattern is refutable. -- cgit 1.4.1-3-g733a5 From 319f18e54dc84cc413df18d110a38ea340a91c86 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 4 Jan 2019 11:22:38 +0100 Subject: Add run-rustfix where it already passes --- tests/ui/cast_lossless_float.fixed | 26 ++++++++++++++ tests/ui/cast_lossless_float.rs | 2 ++ tests/ui/cast_lossless_float.stderr | 20 +++++------ tests/ui/cast_lossless_integer.fixed | 34 +++++++++++++++++++ tests/ui/cast_lossless_integer.rs | 2 ++ tests/ui/cast_lossless_integer.stderr | 36 ++++++++++---------- tests/ui/double_comparison.fixed | 39 +++++++++++++++++++++ tests/ui/double_comparison.rs | 2 ++ tests/ui/double_comparison.stderr | 16 ++++----- tests/ui/println_empty_string.fixed | 19 +++++++++++ tests/ui/println_empty_string.rs | 2 ++ tests/ui/println_empty_string.stderr | 4 +-- tests/ui/ptr_offset_with_cast.fixed | 29 ++++++++++++++++ tests/ui/ptr_offset_with_cast.rs | 2 ++ tests/ui/ptr_offset_with_cast.stderr | 4 +-- tests/ui/single_char_pattern.fixed | 61 +++++++++++++++++++++++++++++++++ tests/ui/single_char_pattern.rs | 2 ++ tests/ui/single_char_pattern.stderr | 40 +++++++++++----------- tests/ui/string_extend.fixed | 41 ++++++++++++++++++++++ tests/ui/string_extend.rs | 2 ++ tests/ui/string_extend.stderr | 6 ++-- tests/ui/unreadable_literal.fixed | 29 ++++++++++++++++ tests/ui/unreadable_literal.rs | 2 ++ tests/ui/unreadable_literal.stderr | 10 +++--- tests/ui/vec.fixed | 64 +++++++++++++++++++++++++++++++++++ tests/ui/vec.rs | 2 ++ tests/ui/vec.stderr | 12 +++---- tests/ui/writeln_empty_string.fixed | 29 ++++++++++++++++ tests/ui/writeln_empty_string.rs | 2 ++ tests/ui/writeln_empty_string.stderr | 4 +-- 30 files changed, 467 insertions(+), 76 deletions(-) create mode 100644 tests/ui/cast_lossless_float.fixed create mode 100644 tests/ui/cast_lossless_integer.fixed create mode 100644 tests/ui/double_comparison.fixed create mode 100644 tests/ui/println_empty_string.fixed create mode 100644 tests/ui/ptr_offset_with_cast.fixed create mode 100644 tests/ui/single_char_pattern.fixed create mode 100644 tests/ui/string_extend.fixed create mode 100644 tests/ui/unreadable_literal.fixed create mode 100644 tests/ui/vec.fixed create mode 100644 tests/ui/writeln_empty_string.fixed diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed new file mode 100644 index 00000000000..5f4e54eb565 --- /dev/null +++ b/tests/ui/cast_lossless_float.fixed @@ -0,0 +1,26 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +fn main() { + // Test clippy::cast_lossless with casts to floating-point types + f32::from(1i8); + f64::from(1i8); + f32::from(1u8); + f64::from(1u8); + f32::from(1i16); + f64::from(1i16); + f32::from(1u16); + f64::from(1u16); + f64::from(1i32); + f64::from(1u32); +} diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index e52a756c003..b818010feb2 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 2164315c35e..aa48bd4d1c7 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,5 +1,5 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:14:5 + --> $DIR/cast_lossless_float.rs:16:5 | LL | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` @@ -7,55 +7,55 @@ LL | 1i8 as f32; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:15:5 + --> $DIR/cast_lossless_float.rs:17:5 | LL | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:16:5 + --> $DIR/cast_lossless_float.rs:18:5 | LL | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:17:5 + --> $DIR/cast_lossless_float.rs:19:5 | LL | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:18:5 + --> $DIR/cast_lossless_float.rs:20:5 | LL | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:19:5 + --> $DIR/cast_lossless_float.rs:21:5 | LL | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:20:5 + --> $DIR/cast_lossless_float.rs:22:5 | LL | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:21:5 + --> $DIR/cast_lossless_float.rs:23:5 | LL | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:22:5 + --> $DIR/cast_lossless_float.rs:24:5 | LL | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:23:5 + --> $DIR/cast_lossless_float.rs:25:5 | LL | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed new file mode 100644 index 00000000000..83f3e024209 --- /dev/null +++ b/tests/ui/cast_lossless_integer.fixed @@ -0,0 +1,34 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +fn main() { + // Test clippy::cast_lossless with casts to integer types + i16::from(1i8); + i32::from(1i8); + i64::from(1i8); + i16::from(1u8); + i32::from(1u8); + i64::from(1u8); + u16::from(1u8); + u32::from(1u8); + u64::from(1u8); + i32::from(1i16); + i64::from(1i16); + i32::from(1u16); + i64::from(1u16); + u32::from(1u16); + u64::from(1u16); + i64::from(1i32); + i64::from(1u32); + u64::from(1u32); +} diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 593ffdd2766..75c63957001 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index d9eb1be57f7..f49dc0d9eff 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,5 +1,5 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:14:5 + --> $DIR/cast_lossless_integer.rs:16:5 | LL | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` @@ -7,103 +7,103 @@ LL | 1i8 as i16; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:15:5 + --> $DIR/cast_lossless_integer.rs:17:5 | LL | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:18:5 | LL | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:19:5 | LL | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:20:5 | LL | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:21:5 | LL | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:22:5 | LL | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:23:5 | LL | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:24:5 | LL | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:25:5 | LL | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:24:5 + --> $DIR/cast_lossless_integer.rs:26:5 | LL | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:25:5 + --> $DIR/cast_lossless_integer.rs:27:5 | LL | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:26:5 + --> $DIR/cast_lossless_integer.rs:28:5 | LL | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:27:5 + --> $DIR/cast_lossless_integer.rs:29:5 | LL | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:28:5 + --> $DIR/cast_lossless_integer.rs:30:5 | LL | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:29:5 + --> $DIR/cast_lossless_integer.rs:31:5 | LL | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:30:5 + --> $DIR/cast_lossless_integer.rs:32:5 | LL | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:31:5 + --> $DIR/cast_lossless_integer.rs:33:5 | LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed new file mode 100644 index 00000000000..fd98edb7555 --- /dev/null +++ b/tests/ui/double_comparison.fixed @@ -0,0 +1,39 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + let x = 1; + let y = 2; + if x <= y { + // do something + } + if x <= y { + // do something + } + if x >= y { + // do something + } + if x >= y { + // do something + } + if x != y { + // do something + } + if x != y { + // do something + } + if x == y { + // do something + } + if x == y { + // do something + } +} diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 70b837a75b6..5d201a13ff2 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { let x = 1; let y = 2; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index f4ec229fbfd..31bab8f0112 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,5 +1,5 @@ error: This binary expression can be simplified - --> $DIR/double_comparison.rs:13:8 + --> $DIR/double_comparison.rs:15:8 | LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` @@ -7,43 +7,43 @@ LL | if x == y || x < y { = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:16:8 + --> $DIR/double_comparison.rs:18:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:19:8 + --> $DIR/double_comparison.rs:21:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:22:8 + --> $DIR/double_comparison.rs:24:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:25:8 + --> $DIR/double_comparison.rs:27:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:28:8 + --> $DIR/double_comparison.rs:30:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:31:8 + --> $DIR/double_comparison.rs:33:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:34:8 + --> $DIR/double_comparison.rs:36:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed new file mode 100644 index 00000000000..4ca151453fe --- /dev/null +++ b/tests/ui/println_empty_string.fixed @@ -0,0 +1,19 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + println!(); + println!(); + + match "a" { + _ => println!(), + } +} diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 19a0389762a..21f944916db 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { println!(); println!(""); diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 89447040a33..2370a3f1e28 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,5 +1,5 @@ error: using `println!("")` - --> $DIR/println_empty_string.rs:12:5 + --> $DIR/println_empty_string.rs:14:5 | LL | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` @@ -7,7 +7,7 @@ LL | println!(""); = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` - --> $DIR/println_empty_string.rs:15:14 + --> $DIR/println_empty_string.rs:17:14 | LL | _ => println!(""), | ^^^^^^^^^^^^ help: replace it with: `println!()` diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed new file mode 100644 index 00000000000..c9f58896ae1 --- /dev/null +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + let vec = vec![b'a', b'b', b'c']; + let ptr = vec.as_ptr(); + + let offset_u8 = 1_u8; + let offset_usize = 1_usize; + let offset_isize = 1_isize; + + unsafe { + ptr.add(offset_usize); + ptr.offset(offset_isize as isize); + ptr.offset(offset_u8 as isize); + + ptr.wrapping_add(offset_usize); + ptr.wrapping_offset(offset_isize as isize); + ptr.wrapping_offset(offset_u8 as isize); + } +} diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 2c9e47d3f32..23eb4c6ce8a 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { let vec = vec![b'a', b'b', b'c']; let ptr = vec.as_ptr(); diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index d1795f439b2..98e3ff92a6e 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,5 +1,5 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:19:9 + --> $DIR/ptr_offset_with_cast.rs:21:9 | LL | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` @@ -7,7 +7,7 @@ LL | ptr.offset(offset_usize as isize); = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:23:9 + --> $DIR/ptr_offset_with_cast.rs:25:9 | LL | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed new file mode 100644 index 00000000000..c3c399f0ce3 --- /dev/null +++ b/tests/ui/single_char_pattern.fixed @@ -0,0 +1,61 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +use std::collections::HashSet; + +fn main() { + let x = "foo"; + x.split('x'); + x.split("xx"); + x.split('x'); + + let y = "x"; + x.split(y); + // Not yet testing for multi-byte characters + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_clippy::single_char_pattern` + // should have done this but produced an ICE + // + // We may not want to suggest changing these anyway + // See: https://github.com/rust-lang/rust-clippy/issues/650#issuecomment-184328984 + x.split("ß"); + x.split("ℝ"); + x.split("💣"); + // Can't use this lint for unicode code points which don't fit in a char + x.split("❤️"); + x.contains('x'); + x.starts_with('x'); + x.ends_with('x'); + x.find('x'); + x.rfind('x'); + x.rsplit('x'); + x.split_terminator('x'); + x.rsplit_terminator('x'); + x.splitn(0, 'x'); + x.rsplitn(0, 'x'); + x.matches('x'); + x.rmatches('x'); + x.match_indices('x'); + x.rmatch_indices('x'); + x.trim_start_matches('x'); + x.trim_end_matches('x'); + // Make sure we escape characters correctly. + x.split('\n'); + + let h = HashSet::::new(); + h.contains("X"); // should not warn + + x.replace(";", ",").split(','); // issue #2978 + x.starts_with('\x03'); // issue #2996 + + // Issue #3204 + const S: &str = "#"; + x.find(S); +} diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index eeee953ab84..cf2fe66236a 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + use std::collections::HashSet; fn main() { diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 7fa3211ab72..7bc92a96536 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,5 +1,5 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:14:13 + --> $DIR/single_char_pattern.rs:16:13 | LL | x.split("x"); | ^^^ help: try using a char instead: `'x'` @@ -7,115 +7,115 @@ LL | x.split("x"); = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:31:16 + --> $DIR/single_char_pattern.rs:33:16 | LL | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:32:19 + --> $DIR/single_char_pattern.rs:34:19 | LL | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:17 + --> $DIR/single_char_pattern.rs:35:17 | LL | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:12 + --> $DIR/single_char_pattern.rs:36:12 | LL | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:13 + --> $DIR/single_char_pattern.rs:37:13 | LL | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:14 + --> $DIR/single_char_pattern.rs:38:14 | LL | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:24 + --> $DIR/single_char_pattern.rs:39:24 | LL | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:25 + --> $DIR/single_char_pattern.rs:40:25 | LL | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:17 + --> $DIR/single_char_pattern.rs:41:17 | LL | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:40:18 + --> $DIR/single_char_pattern.rs:42:18 | LL | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:15 + --> $DIR/single_char_pattern.rs:43:15 | LL | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:42:16 + --> $DIR/single_char_pattern.rs:44:16 | LL | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:43:21 + --> $DIR/single_char_pattern.rs:45:21 | LL | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:44:22 + --> $DIR/single_char_pattern.rs:46:22 | LL | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:26 + --> $DIR/single_char_pattern.rs:47:26 | LL | x.trim_start_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:24 + --> $DIR/single_char_pattern.rs:48:24 | LL | x.trim_end_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:48:13 + --> $DIR/single_char_pattern.rs:50:13 | LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:53:31 + --> $DIR/single_char_pattern.rs:55:31 | LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:54:19 + --> $DIR/single_char_pattern.rs:56:19 | LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed new file mode 100644 index 00000000000..7463baff2af --- /dev/null +++ b/tests/ui/string_extend.fixed @@ -0,0 +1,41 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[derive(Copy, Clone)] +struct HasChars; + +impl HasChars { + fn chars(self) -> std::str::Chars<'static> { + "HasChars".chars() + } +} + +fn main() { + let abc = "abc"; + let def = String::from("def"); + let mut s = String::new(); + + s.push_str(abc); + s.push_str(abc); + + s.push_str("abc"); + s.push_str("abc"); + + s.push_str(&def); + s.push_str(&def); + + s.extend(abc.chars().skip(1)); + s.extend("abc".chars().skip(1)); + s.extend(['a', 'b', 'c'].iter()); + + let f = HasChars; + s.extend(f.chars()); +} diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index 56b466ede20..3a2ad2695de 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 80a490b7884..5638dd87ed1 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,5 +1,5 @@ error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:25:5 + --> $DIR/string_extend.rs:27:5 | LL | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` @@ -7,13 +7,13 @@ LL | s.extend(abc.chars()); = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:28:5 + --> $DIR/string_extend.rs:30:5 | LL | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:31:5 + --> $DIR/string_extend.rs:33:5 | LL | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed new file mode 100644 index 00000000000..4c466035a04 --- /dev/null +++ b/tests/ui/unreadable_literal.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::unreadable_literal)] +#[allow(unused_variables)] +fn main() { + let good = ( + 0b1011_i64, + 0o1_234_u32, + 0x1_234_567, + 65536, + 1_2345_6789, + 1234_f32, + 1_234.12_f32, + 1_234.123_f32, + 1.123_4_f32, + ); + let bad = (0b11_0110_i64, 0x0123_4567_8901_usize, 123_456_f32, 1.234_567_f32); + let good_sci = 1.1234e1; + let bad_sci = 1.123_456e1; +} diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index ad29fcf8fe4..8ade2f6a863 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::unreadable_literal)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 6696f155fb8..68580485853 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,5 +1,5 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:16 + --> $DIR/unreadable_literal.rs:26:16 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -7,25 +7,25 @@ LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32) = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:30 + --> $DIR/unreadable_literal.rs:26:30 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:51 + --> $DIR/unreadable_literal.rs:26:51 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:63 + --> $DIR/unreadable_literal.rs:26:63 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:19 + --> $DIR/unreadable_literal.rs:28:19 | LL | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed new file mode 100644 index 00000000000..2eaba1c408a --- /dev/null +++ b/tests/ui/vec.fixed @@ -0,0 +1,64 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![warn(clippy::useless_vec)] + +#[derive(Debug)] +struct NonCopy; + +fn on_slice(_: &[u8]) {} +#[allow(clippy::ptr_arg)] +fn on_vec(_: &Vec) {} + +struct Line { + length: usize, +} + +impl Line { + fn length(&self) -> usize { + self.length + } +} + +fn main() { + on_slice(&[]); + on_slice(&[]); + + on_slice(&[1, 2]); + on_slice(&[1, 2]); + + on_slice(&[1, 2]); + on_slice(&[1, 2]); + #[rustfmt::skip] + on_slice(&[1, 2]); + on_slice(&[1, 2]); + + on_slice(&[1; 2]); + on_slice(&[1; 2]); + + on_vec(&vec![]); + on_vec(&vec![1, 2]); + on_vec(&vec![1; 2]); + + // Now with non-constant expressions + let line = Line { length: 2 }; + + on_slice(&vec![2; line.length]); + on_slice(&vec![2; line.length()]); + + for a in &[1, 2, 3] { + println!("{:?}", a); + } + + for a in vec![NonCopy, NonCopy] { + println!("{:?}", a); + } +} diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index f795c11ec5b..1648215ed35 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #![warn(clippy::useless_vec)] #[derive(Debug)] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 0afb95629d9..96dd187ccc5 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:30:14 + --> $DIR/vec.rs:32:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,31 +7,31 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:33:14 + --> $DIR/vec.rs:35:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:36:14 + --> $DIR/vec.rs:38:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:39:14 + --> $DIR/vec.rs:41:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:42:14 + --> $DIR/vec.rs:44:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:55:14 + --> $DIR/vec.rs:57:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed new file mode 100644 index 00000000000..68b8185083d --- /dev/null +++ b/tests/ui/writeln_empty_string.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(unused_must_use)] +#![warn(clippy::writeln_empty_string)] +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should fail + writeln!(&mut v); + + let mut suggestion = Vec::new(); + writeln!(&mut suggestion); + + // These should be fine + writeln!(&mut v); + writeln!(&mut v, " "); + write!(&mut v, ""); +} diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 71b5df48bfa..ba43552af23 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] use std::io::Write; diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 9b4061f0fe4..119710c0cdb 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,5 +1,5 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:18:5 + --> $DIR/writeln_empty_string.rs:20:5 | LL | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` @@ -7,7 +7,7 @@ LL | writeln!(&mut v, ""); = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:21:5 + --> $DIR/writeln_empty_string.rs:23:5 | LL | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` -- cgit 1.4.1-3-g733a5 From 407ff74dcc6223185f57a675843bc95cbc66d5a2 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 4 Jan 2019 11:31:28 +0100 Subject: Trigger `use_self` lint in local macros --- clippy_lints/src/use_self.rs | 6 +++--- tests/ui/use_self.rs | 16 ++++++++++++++++ tests/ui/use_self.stderr | 20 +++++++++++++++++++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b031e8b1c44..aa4302e12a7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::utils::{in_macro, span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir::def::{CtorKind, Def}; use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; @@ -172,7 +172,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if in_macro(item.span) { + if in_external_macro(cx.sess(), item.span) { return; } if_chain! { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index b201e160ebd..a01cb3e7021 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -226,6 +226,22 @@ mod tuple_structs { } } +mod macros { + macro_rules! use_self_expand { + () => { + fn new() -> Foo { + Foo {} + } + }; + } + + struct Foo {} + + impl Foo { + use_self_expand!(); // Should lint in local macros + } +} + mod issue3410 { struct A; diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index d52fce76de5..6c5dbf9111d 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -132,5 +132,23 @@ error: unnecessary structure name repetition LL | TS(0) | ^^ help: use the applicable keyword: `Self` -error: aborting due to 22 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:232:25 + | +LL | fn new() -> Foo { + | ^^^ help: use the applicable keyword: `Self` +... +LL | use_self_expand!(); // Should lint in local macros + | ------------------- in this macro invocation + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:233:17 + | +LL | Foo {} + | ^^^ help: use the applicable keyword: `Self` +... +LL | use_self_expand!(); // Should lint in local macros + | ------------------- in this macro invocation + +error: aborting due to 24 previous errors -- cgit 1.4.1-3-g733a5 From 2b80829fe0311fc5cdbc731fa0b67f103db4c004 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 4 Jan 2019 17:18:19 +0100 Subject: tests: used_underscore_binding_macro: disable random_state lint. Trying to work around a crash (see https://github.com/rust-lang/rust-clippy/issues/3628) in https://github.com/rust-lang/rust/pull/57303 --- tests/run-pass/used_underscore_binding_macro.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index 8b6c6557b49..e3af880524c 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -8,6 +8,7 @@ // except according to those terms. #![allow(clippy::useless_attribute)] //issue #2910 +#![allow(clippy::random_state)] // issue #3628 #[macro_use] extern crate serde_derive; -- cgit 1.4.1-3-g733a5 From f8edc39c387b82d9d90460681888b78abdcbe677 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 4 Jan 2019 18:01:44 +0100 Subject: Add itertools to integration tests --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index eb66112213b..d456497d997 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,8 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=hyperium/hyper if: repo =~ /^rust-lang\/rust-clippy$/ + - env: INTEGRATION=bluss/rust-itertools + if: repo =~ /^rust-lang\/rust-clippy$/ allow_failures: - os: windows env: CARGO_INCREMENTAL=0 BASE_TESTS=true -- cgit 1.4.1-3-g733a5 From 33ec4e5220b004e2d491cce7cc9ab95a5c140370 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 5 Jan 2019 01:12:33 +0100 Subject: rustup (don't know the exact PR unfortunately) --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 8369f4b4470..8102a416d82 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -304,7 +304,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }; let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; - let ret = miri_to_const(self.tcx, result); + let ret = miri_to_const(self.tcx, &result); if ret.is_some() { self.needed_resolution = true; } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 29038cda869..78cade1f2fb 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { promoted: None, }; let constant = cx.tcx.const_eval(param_env.and(c_id)).ok(); - if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { + if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, &c)) { let mut ty = cx.tcx.type_of(def_id); if let ty::Adt(adt, _) = ty.sty { if adt.is_enum() { -- cgit 1.4.1-3-g733a5 From a4b99c6d6881b7e2149320d86794db0a9cdaed85 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 5 Jan 2019 08:21:56 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/56837 --- clippy_lints/src/len_zero.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 61aa228729c..233bea77e03 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -302,10 +302,15 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::Dynamic(ref tt, ..) => cx - .tcx - .associated_items(tt.principal().def_id()) - .any(|item| is_is_empty(cx, &item)), + ty::Dynamic(ref tt, ..) => { + if let Some(principal) = tt.principal() { + cx.tcx + .associated_items(principal.def_id()) + .any(|item| is_is_empty(cx, &item)) + } else { + false + } + }, ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), ty::Array(..) | ty::Slice(..) | ty::Str => true, -- cgit 1.4.1-3-g733a5 From 3389a688343e528c88c0b142aa152b562fdf5421 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 5 Jan 2019 10:19:04 +0100 Subject: Revert "Auto merge of #3603 - xfix:random-state-lint, r=phansch" This reverts commit 0a6593cd1b12c06d4ff2f2ad0ccf20e77f1ec5f6, reversing changes made to 5277a1fb6c1be42ec0c57a6f60d82fc18a962259. This hopefully fixes #3628 --- CHANGELOG.md | 1 - README.md | 2 +- clippy_lints/src/lib.rs | 3 --- clippy_lints/src/random_state.rs | 50 ---------------------------------------- clippy_lints/src/utils/paths.rs | 1 - tests/ui/random_state.rs | 19 --------------- tests/ui/random_state.stderr | 28 ---------------------- 7 files changed, 1 insertion(+), 103 deletions(-) delete mode 100644 clippy_lints/src/random_state.rs delete mode 100644 tests/ui/random_state.rs delete mode 100644 tests/ui/random_state.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index b5c8feb8ac6..efa637b185c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -814,7 +814,6 @@ All notable changes to this project will be documented in this file. [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark -[`random_state`]: https://rust-lang.github.io/rust-clippy/master/index.html#random_state [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one [`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero diff --git a/README.md b/README.md index 8ca10da416d..be54424dc38 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 31cd58d2c78..2e515cc8aea 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -180,7 +180,6 @@ pub mod precedence; pub mod ptr; pub mod ptr_offset_with_cast; pub mod question_mark; -pub mod random_state; pub mod ranges; pub mod redundant_clone; pub mod redundant_field_names; @@ -487,7 +486,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); - reg.register_late_lint_pass(box random_state::Pass); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -1027,7 +1025,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { fallible_impl_from::FALLIBLE_IMPL_FROM, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, - random_state::RANDOM_STATE, redundant_clone::REDUNDANT_CLONE, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, diff --git a/clippy_lints/src/random_state.rs b/clippy_lints/src/random_state.rs deleted file mode 100644 index f95116c04b6..00000000000 --- a/clippy_lints/src/random_state.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::utils::{match_type, paths, span_lint}; -use rustc::hir::Ty; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::ty::subst::UnpackedKind; -use rustc::ty::TyKind; -use rustc::{declare_tool_lint, lint_array}; - -/// **What it does:** Checks for usage of `RandomState` -/// -/// **Why is this bad?** Some applications don't need collision prevention -/// which lowers the performance. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn x() { -/// let mut map = std::collections::HashMap::new(); -/// map.insert(3, 4); -/// } -/// ``` -declare_clippy_lint! { - pub RANDOM_STATE, - nursery, - "use of RandomState" -} - -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(RANDOM_STATE) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &Ty) { - if let Some(tys) = cx.tables.node_id_to_type_opt(ty.hir_id) { - if let TyKind::Adt(_, substs) = tys.sty { - for subst in substs { - if let UnpackedKind::Type(build_hasher) = subst.unpack() { - if match_type(cx, build_hasher, &paths::RANDOM_STATE) { - span_lint(cx, RANDOM_STATE, ty.span, "usage of RandomState"); - } - } - } - } - } - } -} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0ec684e36bc..0779d77936f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -73,7 +73,6 @@ pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; -pub const RANDOM_STATE: [&str; 5] = ["std", "collections", "hash", "map", "RandomState"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; diff --git a/tests/ui/random_state.rs b/tests/ui/random_state.rs deleted file mode 100644 index f4fa85997a8..00000000000 --- a/tests/ui/random_state.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![warn(clippy::random_state)] - -use std::collections::hash_map::RandomState; -use std::collections::hash_map::{DefaultHasher, HashMap}; -use std::hash::BuildHasherDefault; - -fn main() { - // Should warn - let mut map = HashMap::new(); - map.insert(3, 4); - let mut map = HashMap::with_hasher(RandomState::new()); - map.insert(true, false); - let _map: HashMap<_, _> = vec![(2, 3)].into_iter().collect(); - let _vec: Vec>; - // Shouldn't warn - let _map: HashMap> = HashMap::default(); - let mut map = HashMap::with_hasher(BuildHasherDefault::::default()); - map.insert("a", "b"); -} diff --git a/tests/ui/random_state.stderr b/tests/ui/random_state.stderr deleted file mode 100644 index df224bf0c29..00000000000 --- a/tests/ui/random_state.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: usage of RandomState - --> $DIR/random_state.rs:9:19 - | -LL | let mut map = HashMap::new(); - | ^^^^^^^^^^^^ - | - = note: `-D clippy::random-state` implied by `-D warnings` - -error: usage of RandomState - --> $DIR/random_state.rs:11:19 - | -LL | let mut map = HashMap::with_hasher(RandomState::new()); - | ^^^^^^^^^^^^^^^^^^^^ - -error: usage of RandomState - --> $DIR/random_state.rs:13:15 - | -LL | let _map: HashMap<_, _> = vec![(2, 3)].into_iter().collect(); - | ^^^^^^^^^^^^^ - -error: usage of RandomState - --> $DIR/random_state.rs:14:19 - | -LL | let _vec: Vec>; - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -- cgit 1.4.1-3-g733a5 From 8ff4a1f0a82be971ecadfdba0066fd448db2a8b3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 5 Jan 2019 10:20:37 +0100 Subject: Revert "tests: used_underscore_binding_macro: disable random_state lint." This reverts commit 2b80829fe0311fc5cdbc731fa0b67f103db4c004. --- tests/run-pass/used_underscore_binding_macro.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index e3af880524c..8b6c6557b49 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -8,7 +8,6 @@ // except according to those terms. #![allow(clippy::useless_attribute)] //issue #2910 -#![allow(clippy::random_state)] // issue #3628 #[macro_use] extern crate serde_derive; -- cgit 1.4.1-3-g733a5 From 4add1e23f9b487373bd02852f3eef1ec15fdafc3 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 6 Jan 2019 11:46:03 +0200 Subject: Improve `get_unwrap` suggestion Handle case where a reference is immediately dereferenced. Fixes 3625 --- clippy_lints/src/methods/mod.rs | 21 +++++++++++-- tests/ui/get_unwrap.fixed | 68 +++++++++++++++++++++++++++++++++++++++++ tests/ui/get_unwrap.rs | 1 + tests/ui/get_unwrap.stderr | 32 +++++++++---------- 4 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 tests/ui/get_unwrap.fixed diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index dcd9e3ee153..afc875593ac 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1603,7 +1603,7 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: } else { return; // not linting on a .get().unwrap() chain or variant }; - let needs_ref; + let mut needs_ref; let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { needs_ref = get_args_str.parse::().is_ok(); "slice" @@ -1623,6 +1623,22 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: return; // caller is not a type that we want to lint }; + let mut span = expr.span; + + // Handle the case where the result is immedately dereferenced + // by not requiring ref and pulling the dereference into the + // suggestion. + if needs_ref { + if let Some(parent) = get_parent_expr(cx, expr) { + if let hir::ExprKind::Unary(op, _) = parent.node { + if op == hir::UnOp::UnDeref { + needs_ref = false; + span = parent.span; + } + } + } + } + let mut_str = if is_mut { "_mut" } else { "" }; let borrow_str = if !needs_ref { "" @@ -1631,10 +1647,11 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: } else { "&" }; + span_lint_and_sugg( cx, GET_UNWRAP, - expr.span, + span, &format!( "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise", mut_str, caller_type diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed new file mode 100644 index 00000000000..4badef1b803 --- /dev/null +++ b/tests/ui/get_unwrap.fixed @@ -0,0 +1,68 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +#![allow(unused_mut)] + +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::collections::VecDeque; +use std::iter::FromIterator; + +struct GetFalsePositive { + arr: [u32; 3], +} + +impl GetFalsePositive { + fn get(&self, pos: usize) -> Option<&u32> { + self.arr.get(pos) + } + fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { + self.arr.get_mut(pos) + } +} + +fn main() { + let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); + let mut some_slice = &mut [0, 1, 2, 3]; + let mut some_vec = vec![0, 1, 2, 3]; + let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect(); + let mut some_hashmap: HashMap = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; + + { + // Test `get().unwrap()` + let _ = &boxed_slice[1]; + let _ = &some_slice[0]; + let _ = &some_vec[0]; + let _ = &some_vecdeque[0]; + let _ = &some_hashmap[&1]; + let _ = &some_btreemap[&1]; + let _ = false_positive.get(0).unwrap(); + } + + { + // Test `get_mut().unwrap()` + boxed_slice[0] = 1; + some_slice[0] = 1; + some_vec[0] = 1; + some_vecdeque[0] = 1; + // Check false positives + *some_hashmap.get_mut(&1).unwrap() = 'b'; + *some_btreemap.get_mut(&1).unwrap() = 'b'; + *false_positive.get_mut(0).unwrap() = 1; + } + + { + // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` + let _ = some_vec[0..1].to_vec(); + let _ = some_vec[0..1].to_vec(); + } +} diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index e8789db6fc1..d1a32dcbda3 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -7,6 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix #![allow(unused_mut)] use std::collections::BTreeMap; diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 1f45c26048a..c947cf87d10 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,5 +1,5 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` @@ -7,67 +7,67 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:42:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:43:17 + --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:44:17 + --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:45:17 + --> $DIR/get_unwrap.rs:46:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:46:17 + --> $DIR/get_unwrap.rs:47:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:52:10 + --> $DIR/get_unwrap.rs:53:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:53:10 + --> $DIR/get_unwrap.rs:54:9 | LL | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:54:10 + --> $DIR/get_unwrap.rs:55:9 | LL | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:55:10 + --> $DIR/get_unwrap.rs:56:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:64:17 + --> $DIR/get_unwrap.rs:65:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:66:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` -- cgit 1.4.1-3-g733a5 From ff191a808e563d36b4c8bedbd2a67aa44156faf9 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 6 Jan 2019 15:05:04 +0100 Subject: Restrict use_self on nested items --- clippy_lints/src/use_self.rs | 16 ++++++++++++---- tests/ui/use_self.rs | 33 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index aa4302e12a7..e3e175a17c7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -10,13 +10,12 @@ use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir::def::{CtorKind, Def}; -use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; +use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; -use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfUpper; /// **What it does:** Checks for unnecessary repetition of structure name when a @@ -242,8 +241,17 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { walk_path(self, path); } - fn visit_use(&mut self, _path: &'tcx Path, _id: NodeId, _hir_id: HirId) { - // Don't check use statements + fn visit_item(&mut self, item: &'tcx Item) { + match item.node { + ItemKind::Use(..) + | ItemKind::Static(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) => { + // Don't check statements that shadow `Self` or where `Self` can't be used + }, + _ => walk_item(self, item), + } } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index a01cb3e7021..f3bd4a05005 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -242,6 +242,28 @@ mod macros { } } +mod nesting { + struct Foo {} + impl Foo { + fn foo() { + use self::Foo; // Can't use Self here + struct Bar { + foo: Foo, // Foo != Self + } + } + } + + enum Enum { + A, + } + impl Enum { + fn method() { + use self::Enum::*; + static STATIC: Enum = Enum::A; // Can't use Self as type + } + } +} + mod issue3410 { struct A; @@ -255,14 +277,3 @@ mod issue3410 { fn a(_: Vec) {} } } - -mod issue3425 { - enum Enum { - A, - } - impl Enum { - fn a() { - use self::Enum::*; - } - } -} -- cgit 1.4.1-3-g733a5 From 7230768998b0574836e9a90a36175174c802e76b Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 6 Jan 2019 15:41:02 +0100 Subject: Update known problems --- clippy_lints/src/use_self.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index e3e175a17c7..17078141af1 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -28,7 +28,6 @@ use syntax_pos::symbol::keywords::SelfUpper; /// **Known problems:** /// - False positive when using associated types (#2843) /// - False positives in some situations when using generics (#3410) -/// - False positive when type from outer function can't be used (#3463) /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From d2ea6355a8432e0042060796cd1b4e9060400c2f Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 7 Jan 2019 06:22:39 +0200 Subject: Update `unwrap_get` code review suggestions --- clippy_lints/src/methods/mod.rs | 15 +++++++-------- tests/ui/get_unwrap.fixed | 2 ++ tests/ui/get_unwrap.rs | 2 ++ tests/ui/get_unwrap.stderr | 20 +++++++++++++------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index afc875593ac..4473802da3b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1628,14 +1628,13 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir:: // Handle the case where the result is immedately dereferenced // by not requiring ref and pulling the dereference into the // suggestion. - if needs_ref { - if let Some(parent) = get_parent_expr(cx, expr) { - if let hir::ExprKind::Unary(op, _) = parent.node { - if op == hir::UnOp::UnDeref { - needs_ref = false; - span = parent.span; - } - } + if_chain! { + if needs_ref; + if let Some(parent) = get_parent_expr(cx, expr); + if let hir::ExprKind::Unary(hir::UnOp::UnDeref, _) = parent.node; + then { + needs_ref = false; + span = parent.span; } } diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 4badef1b803..021c0c2ff44 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -46,6 +46,8 @@ fn main() { let _ = &some_hashmap[&1]; let _ = &some_btreemap[&1]; let _ = false_positive.get(0).unwrap(); + // Test with deref + let _: u8 = boxed_slice[1]; } { diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index d1a32dcbda3..b041ba7b7c7 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -46,6 +46,8 @@ fn main() { let _ = some_hashmap.get(&1).unwrap(); let _ = some_btreemap.get(&1).unwrap(); let _ = false_positive.get(0).unwrap(); + // Test with deref + let _: u8 = *boxed_slice.get(1).unwrap(); } { diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index c947cf87d10..d4f699f5a72 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -36,41 +36,47 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:50:21 + | +LL | let _: u8 = *boxed_slice.get(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` + error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:53:9 + --> $DIR/get_unwrap.rs:55:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:54:9 + --> $DIR/get_unwrap.rs:56:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:55:9 + --> $DIR/get_unwrap.rs:57:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:56:9 + --> $DIR/get_unwrap.rs:58:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:67:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:66:17 + --> $DIR/get_unwrap.rs:68:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors -- cgit 1.4.1-3-g733a5 From 98c5f37ad2f0b40721805b3af21d26109297ce95 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Wed, 26 Dec 2018 01:29:03 +0300 Subject: Add assert(true) and assert(false) lints --- clippy_lints/src/assert_checks.rs | 78 ++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 6 +++ tests/ui/assert_checks.rs | 13 +++++ tests/ui/assert_checks.stderr | 18 +++++++ tests/ui/attrs.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/panic_unimplemented.rs | 2 +- 7 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/assert_checks.rs create mode 100644 tests/ui/assert_checks.rs create mode 100644 tests/ui/assert_checks.stderr diff --git a/clippy_lints/src/assert_checks.rs b/clippy_lints/src/assert_checks.rs new file mode 100644 index 00000000000..ecd71952b93 --- /dev/null +++ b/clippy_lints/src/assert_checks.rs @@ -0,0 +1,78 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::{Expr, ExprKind}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::ast::LitKind; +use crate::utils::{is_direct_expn_of, span_lint}; +use if_chain::if_chain; + +/// **What it does:** Check explicit call assert!(true) +/// +/// **Why is this bad?** Will be optimized out by the compiler +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// assert!(true) +/// ``` +declare_clippy_lint! { + pub EXPLICIT_TRUE, + correctness, + "assert!(true) will be optimized out by the compiler" +} + +/// **What it does:** Check explicit call assert!(false) +/// +/// **Why is this bad?** Should probably be replaced by a panic!() +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// assert!(false) +/// ``` +declare_clippy_lint! { + pub EXPLICIT_FALSE, + correctness, + "assert!(false) should probably be replaced by a panic!()r" +} + +pub struct AssertChecks; + +impl LintPass for AssertChecks { + fn get_lints(&self) -> LintArray { + lint_array![EXPLICIT_TRUE, EXPLICIT_FALSE] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertChecks { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if_chain! { + if is_direct_expn_of(e.span, "assert").is_some(); + if let ExprKind::Unary(_, ref lit) = e.node; + if let ExprKind::Lit(ref inner) = lit.node; + then { + match inner.node { + LitKind::Bool(true) => { + span_lint(cx, EXPLICIT_TRUE, e.span, + "assert!(true) will be optimized out by the compiler"); + }, + LitKind::Bool(false) => { + span_lint(cx, EXPLICIT_FALSE, e.span, + "assert!(false) should probably be replaced by a panic!()"); + }, + _ => (), + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2e515cc8aea..1f4cb27891b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -88,6 +88,7 @@ mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; pub mod arithmetic; +pub mod assert_checks; pub mod assign_ops; pub mod attrs; pub mod bit_mask; @@ -486,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); + reg.register_late_lint_pass(box assert_checks::AssertChecks); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -563,6 +565,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::all", Some("clippy"), vec![ approx_const::APPROX_CONSTANT, + assert_checks::EXPLICIT_TRUE, + assert_checks::EXPLICIT_FALSE, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_CFG_ATTR, @@ -940,6 +944,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::correctness", Some("clippy_correctness"), vec![ approx_const::APPROX_CONSTANT, + assert_checks::EXPLICIT_TRUE, + assert_checks::EXPLICIT_FALSE, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, diff --git a/tests/ui/assert_checks.rs b/tests/ui/assert_checks.rs new file mode 100644 index 00000000000..811046d060a --- /dev/null +++ b/tests/ui/assert_checks.rs @@ -0,0 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + assert!(true); + assert!(false); +} diff --git a/tests/ui/assert_checks.stderr b/tests/ui/assert_checks.stderr new file mode 100644 index 00000000000..fd7e4e01420 --- /dev/null +++ b/tests/ui/assert_checks.stderr @@ -0,0 +1,18 @@ +error: assert!(true) will be optimized out by the compiler + --> $DIR/assert_checks.rs:11:5 + | +11 | assert!(true); + | ^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::explicit_true)] on by default + +error: assert!(false) should probably be replaced by a panic!() + --> $DIR/assert_checks.rs:12:5 + | +12 | assert!(false); + | ^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::explicit_false)] on by default + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 413c30a1945..c0ea7329718 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::inline_always, clippy::deprecated_semver)] - +#![allow(clippy::assert_checks::explicit_true)] #[inline(always)] fn test_attr_lint() { assert!(true) diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index ede1244df7e..a6e6adcac5c 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::empty_line_after_outer_attr)] - +#![allow(clippy::assert_checks::explicit_true)] // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 93dec197ff5..3c568658a6c 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::panic_params, clippy::unimplemented)] - +#![allow(clippy::assert_checks::explicit_true)] fn missing() { if true { panic!("{}"); -- cgit 1.4.1-3-g733a5 From 3d9535a1067ad2913eab4bfd44b220bab0655b47 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Thu, 27 Dec 2018 16:12:11 +0300 Subject: Add unreachable!() as option --- clippy_lints/src/assert_checks.rs | 6 +++--- tests/ui/assert_checks.stderr | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/assert_checks.rs b/clippy_lints/src/assert_checks.rs index ecd71952b93..dcc11951b26 100644 --- a/clippy_lints/src/assert_checks.rs +++ b/clippy_lints/src/assert_checks.rs @@ -32,7 +32,7 @@ declare_clippy_lint! { /// **What it does:** Check explicit call assert!(false) /// -/// **Why is this bad?** Should probably be replaced by a panic!() +/// **Why is this bad?** Should probably be replaced by a panic!() or unreachable!() /// /// **Known problems:** None /// @@ -43,7 +43,7 @@ declare_clippy_lint! { declare_clippy_lint! { pub EXPLICIT_FALSE, correctness, - "assert!(false) should probably be replaced by a panic!()r" + "assert!(false) should probably be replaced by a panic!() or unreachable!()" } pub struct AssertChecks; @@ -68,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertChecks { }, LitKind::Bool(false) => { span_lint(cx, EXPLICIT_FALSE, e.span, - "assert!(false) should probably be replaced by a panic!()"); + "assert!(false) should probably be replaced by a panic!() or unreachable!()"); }, _ => (), } diff --git a/tests/ui/assert_checks.stderr b/tests/ui/assert_checks.stderr index fd7e4e01420..e2039941650 100644 --- a/tests/ui/assert_checks.stderr +++ b/tests/ui/assert_checks.stderr @@ -6,7 +6,7 @@ error: assert!(true) will be optimized out by the compiler | = note: #[deny(clippy::explicit_true)] on by default -error: assert!(false) should probably be replaced by a panic!() +error: assert!(false) should probably be replaced by a panic!() or unreachable!() --> $DIR/assert_checks.rs:12:5 | 12 | assert!(false); -- cgit 1.4.1-3-g733a5 From 96058616e2a5d8af709da67cb03c35715437a990 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Thu, 27 Dec 2018 16:48:11 +0300 Subject: run ./util/dev update_lints --- CHANGELOG.md | 2 ++ README.md | 6 ++++++ clippy_lints/src/lib.rs | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efa637b185c..603fb0b5b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -679,8 +679,10 @@ All notable changes to this project will be documented in this file. [`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call [`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop +[`explicit_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_false [`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop +[`explicit_true`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_true [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice [`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes diff --git a/README.md b/README.md index be54424dc38..658b2a70adc 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,13 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. +<<<<<<< HEAD [There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +||||||| merged common ancestors +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +======= +[There are 293 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +>>>>>>> run ./util/dev update_lints We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1f4cb27891b..8af73a4f99b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -565,8 +565,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::all", Some("clippy"), vec![ approx_const::APPROX_CONSTANT, - assert_checks::EXPLICIT_TRUE, assert_checks::EXPLICIT_FALSE, + assert_checks::EXPLICIT_TRUE, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_CFG_ATTR, @@ -944,8 +944,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::correctness", Some("clippy_correctness"), vec![ approx_const::APPROX_CONSTANT, - assert_checks::EXPLICIT_TRUE, assert_checks::EXPLICIT_FALSE, + assert_checks::EXPLICIT_TRUE, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, -- cgit 1.4.1-3-g733a5 From 351688db78823cc53e88bc22cbe35c2342daf80a Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Mon, 7 Jan 2019 14:11:53 +0100 Subject: Improve tests and exclude nested impls --- clippy_lints/src/use_self.rs | 3 ++- tests/ui/use_self.rs | 10 +++++++++- tests/ui/use_self.stderr | 14 +++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 17078141af1..5ec809f1b76 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -246,7 +246,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { | ItemKind::Static(..) | ItemKind::Enum(..) | ItemKind::Struct(..) - | ItemKind::Union(..) => { + | ItemKind::Union(..) + | ItemKind::Impl(..) => { // Don't check statements that shadow `Self` or where `Self` can't be used }, _ => walk_item(self, item), diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index f3bd4a05005..464dd814329 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -250,6 +250,14 @@ mod nesting { struct Bar { foo: Foo, // Foo != Self } + + impl Bar { + fn bar() -> Bar { + Bar { + foo: Foo{}, + } + } + } } } @@ -258,7 +266,7 @@ mod nesting { } impl Enum { fn method() { - use self::Enum::*; + use self::Enum::*; // Issue 3425 static STATIC: Enum = Enum::A; // Can't use Self as type } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 6c5dbf9111d..a388579c9a3 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -150,5 +150,17 @@ LL | Foo {} LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation -error: aborting due to 24 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:255:29 + | +LL | fn bar() -> Bar { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:256:21 + | +LL | Bar { + | ^^^ help: use the applicable keyword: `Self` + +error: aborting due to 26 previous errors -- cgit 1.4.1-3-g733a5 From a3931229c47eca72fe04a9e574d45f0bf45c2727 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig <921462+hellow554@users.noreply.github.com> Date: Mon, 7 Jan 2019 14:32:32 +0100 Subject: Add missing ` in default lint --- clippy_lints/src/new_without_default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 917a80b81f6..832311dc027 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -27,7 +27,7 @@ use syntax::source_map::Span; /// It detects both the case when a manual /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) /// implementation is required and also when it can be created with -/// `#[derive(Default)] +/// `#[derive(Default)]` /// /// **Why is this bad?** The user might expect to be able to use /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the -- cgit 1.4.1-3-g733a5 From 34daf09aa41e24fada5bf10e4193bf85b910a3ac Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sat, 29 Dec 2018 19:25:27 +0100 Subject: cast_ref_to_mut lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/types.rs | 61 +++++++++++++++++++++++++++++++++++++++++ tests/ui/cast_ref_to_mut.rs | 31 +++++++++++++++++++++ tests/ui/cast_ref_to_mut.stderr | 22 +++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 tests/ui/cast_ref_to_mut.rs create mode 100644 tests/ui/cast_ref_to_mut.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index efa637b185c..7acf9bc1eaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -634,6 +634,7 @@ All notable changes to this project will be documented in this file. [`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap [`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss [`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment +[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ref_to_mut [`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss [`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8 [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp diff --git a/README.md b/README.md index be54424dc38..8ca10da416d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2e515cc8aea..84e20111897 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -486,6 +486,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); + reg.register_late_lint_pass(box types::RefToMut); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -1026,6 +1027,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, redundant_clone::REDUNDANT_CLONE, + types::CAST_REF_TO_MUT, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f4ca8209d67..5091662e3d9 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2240,3 +2240,64 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) } } + +/// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code. +/// +/// **Why is this bad?** It’s basically guaranteed to be undefined behaviour. +/// `UnsafeCell` is the only way to obtain aliasable data that is considered +/// mutable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// fn x(r: &i32) { +/// unsafe { +/// *(r as *const _ as *mut _) += 1; +/// } +/// } +/// ``` +/// +/// Instead consider using interior mutability types. +/// +/// ```rust +/// fn x(r: &UnsafeCell) { +/// unsafe { +/// *r.get() += 1; +/// } +/// } +/// ``` +declare_clippy_lint! { + pub CAST_REF_TO_MUT, + nursery, + "a cast of reference to a mutable pointer" +} + +pub struct RefToMut; + +impl LintPass for RefToMut { + fn get_lints(&self) -> LintArray { + lint_array!(CAST_REF_TO_MUT) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::Unary(UnOp::UnDeref, e) = &expr.node; + if let ExprKind::Cast(e, t) = &e.node; + if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node; + if let ExprKind::Cast(e, t) = &e.node; + if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; + if let ty::TyKind::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; + then { + span_lint( + cx, + CAST_REF_TO_MUT, + expr.span, + "casting immutable reference to a mutable reference" + ); + } + } + } +} diff --git a/tests/ui/cast_ref_to_mut.rs b/tests/ui/cast_ref_to_mut.rs new file mode 100644 index 00000000000..967e8e46739 --- /dev/null +++ b/tests/ui/cast_ref_to_mut.rs @@ -0,0 +1,31 @@ +#![warn(clippy::cast_ref_to_mut)] +#![allow(clippy::no_effect)] + +extern "C" { + // NB. Mutability can be easily incorrect in FFI calls, as + // in C, the default are mutable pointers. + fn ffi(c: *mut u8); + fn int_ffi(c: *mut i32); +} + +fn main() { + let s = String::from("Hello"); + let a = &s; + unsafe { + let num = &3i32; + let mut_num = &mut 3i32; + // Should be warned against + (*(a as *const _ as *mut String)).push_str(" world"); + *(a as *const _ as *mut _) = String::from("Replaced"); + *(a as *const _ as *mut String) += " world"; + // Shouldn't be warned against + println!("{}", *(num as *const _ as *const i16)); + println!("{}", *(mut_num as *mut _ as *mut i16)); + ffi(a.as_ptr() as *mut _); + int_ffi(num as *const _ as *mut _); + int_ffi(&3 as *const _ as *mut _); + let mut value = 3; + let value: *const i32 = &mut value; + *(value as *const i16 as *mut i16) = 42; + } +} diff --git a/tests/ui/cast_ref_to_mut.stderr b/tests/ui/cast_ref_to_mut.stderr new file mode 100644 index 00000000000..a3e4fc5412c --- /dev/null +++ b/tests/ui/cast_ref_to_mut.stderr @@ -0,0 +1,22 @@ +error: casting immutable reference to a mutable reference + --> $DIR/cast_ref_to_mut.rs:18:9 + | +LL | (*(a as *const _ as *mut String)).push_str(" world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::cast-ref-to-mut` implied by `-D warnings` + +error: casting immutable reference to a mutable reference + --> $DIR/cast_ref_to_mut.rs:19:9 + | +LL | *(a as *const _ as *mut _) = String::from("Replaced"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting immutable reference to a mutable reference + --> $DIR/cast_ref_to_mut.rs:20:9 + | +LL | *(a as *const _ as *mut String) += " world"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5 From fd5787410625cdea037a70bc85fc657453e2aeb3 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 13:02:58 +0100 Subject: Use ty::Ref instead of ty::TyKind::Ref --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5091662e3d9..43603c28702 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -25,7 +25,7 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty::layout::LayoutOf; -use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; +use rustc::ty::{self, Ref, Ty, TyCtxt, TypeckTables}; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; @@ -2289,7 +2289,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node; if let ExprKind::Cast(e, t) = &e.node; if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; - if let ty::TyKind::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; + if let Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; then { span_lint( cx, -- cgit 1.4.1-3-g733a5 From 1cab4d15a2e95223ad8d812e5f0932e31242f665 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 13:06:37 +0100 Subject: Add a note to cast_ref_to_mut lint --- clippy_lints/src/types.rs | 10 ++++++---- tests/ui/cast_ref_to_mut.stderr | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 43603c28702..097ff1fecc0 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -16,8 +16,8 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, - snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, - AbsolutePathBuffer, + snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, + span_note_and_lint, unsext, AbsolutePathBuffer, }; use if_chain::if_chain; use rustc::hir; @@ -2291,11 +2291,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; if let Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; then { - span_lint( + span_note_and_lint( cx, CAST_REF_TO_MUT, expr.span, - "casting immutable reference to a mutable reference" + "casting immutable reference to a mutable reference", + expr.span, + "consider implementing `UnsafeCell` instead", ); } } diff --git a/tests/ui/cast_ref_to_mut.stderr b/tests/ui/cast_ref_to_mut.stderr index a3e4fc5412c..23f03f0113d 100644 --- a/tests/ui/cast_ref_to_mut.stderr +++ b/tests/ui/cast_ref_to_mut.stderr @@ -5,18 +5,23 @@ LL | (*(a as *const _ as *mut String)).push_str(" world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ref-to-mut` implied by `-D warnings` + = note: consider implementing `UnsafeCell` instead error: casting immutable reference to a mutable reference --> $DIR/cast_ref_to_mut.rs:19:9 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider implementing `UnsafeCell` instead error: casting immutable reference to a mutable reference --> $DIR/cast_ref_to_mut.rs:20:9 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider implementing `UnsafeCell` instead error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 6faf1330aaa42f9f524b7f84a881111a536ca10d Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 13:11:53 +0100 Subject: Move a hint to an error message in cast_ref_to_mut lint This matches mem::transmute::<&T, &mut T> lint in rustc. --- clippy_lints/src/types.rs | 10 ++++------ tests/ui/cast_ref_to_mut.stderr | 11 +++-------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 097ff1fecc0..a9fb595e708 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -16,8 +16,8 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, - snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, - span_note_and_lint, unsext, AbsolutePathBuffer, + snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, + AbsolutePathBuffer, }; use if_chain::if_chain; use rustc::hir; @@ -2291,13 +2291,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; if let Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; then { - span_note_and_lint( + span_lint( cx, CAST_REF_TO_MUT, expr.span, - "casting immutable reference to a mutable reference", - expr.span, - "consider implementing `UnsafeCell` instead", + "casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell", ); } } diff --git a/tests/ui/cast_ref_to_mut.stderr b/tests/ui/cast_ref_to_mut.stderr index 23f03f0113d..448a66cfcce 100644 --- a/tests/ui/cast_ref_to_mut.stderr +++ b/tests/ui/cast_ref_to_mut.stderr @@ -1,27 +1,22 @@ -error: casting immutable reference to a mutable reference +error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell --> $DIR/cast_ref_to_mut.rs:18:9 | LL | (*(a as *const _ as *mut String)).push_str(" world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::cast-ref-to-mut` implied by `-D warnings` - = note: consider implementing `UnsafeCell` instead -error: casting immutable reference to a mutable reference +error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell --> $DIR/cast_ref_to_mut.rs:19:9 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: consider implementing `UnsafeCell` instead -error: casting immutable reference to a mutable reference +error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell --> $DIR/cast_ref_to_mut.rs:20:9 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: consider implementing `UnsafeCell` instead error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 21d30450b51adf206626aacf6fe0abf52a7b4ec5 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Sun, 30 Dec 2018 13:12:28 +0100 Subject: Don't import ty::Ref in cast_ref_to_mut lint --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index a9fb595e708..3acc82edf29 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -25,7 +25,7 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty::layout::LayoutOf; -use rustc::ty::{self, Ref, Ty, TyCtxt, TypeckTables}; +use rustc::ty::{self, Ty, TyCtxt, TypeckTables}; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; @@ -2289,7 +2289,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node; if let ExprKind::Cast(e, t) = &e.node; if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; - if let Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; + if let ty::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; then { span_lint( cx, -- cgit 1.4.1-3-g733a5 From 466cd076a2c6e1cf1775c486998a1a0b12b2fe15 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Mon, 7 Jan 2019 14:38:01 +0100 Subject: Rustftmt --- tests/ui/use_self.rs | 4 +--- tests/ui/use_self.stderr | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 464dd814329..a117ce5894b 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -253,9 +253,7 @@ mod nesting { impl Bar { fn bar() -> Bar { - Bar { - foo: Foo{}, - } + Bar { foo: Foo {} } } } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index a388579c9a3..72b60db7fd2 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -159,7 +159,7 @@ LL | fn bar() -> Bar { error: unnecessary structure name repetition --> $DIR/use_self.rs:256:21 | -LL | Bar { +LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: aborting due to 26 previous errors -- cgit 1.4.1-3-g733a5 From 27ea638a15b5d71e06a2dcc3cc996f35b4ab3bd1 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 7 Jan 2019 14:39:56 +0100 Subject: Move cast_ref_to_mut list to correctness group --- clippy_lints/src/lib.rs | 3 ++- clippy_lints/src/types.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 84e20111897..35c00fb6328 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -759,6 +759,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::BOX_VEC, types::CAST_LOSSLESS, types::CAST_PTR_ALIGNMENT, + types::CAST_REF_TO_MUT, types::CHAR_LIT_AS_U8, types::FN_TO_NUMERIC_CAST, types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, @@ -990,6 +991,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::CAST_PTR_ALIGNMENT, + types::CAST_REF_TO_MUT, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, @@ -1027,7 +1029,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, redundant_clone::REDUNDANT_CLONE, - types::CAST_REF_TO_MUT, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, ]); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3acc82edf29..f9ed38e52a0 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2269,7 +2269,7 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<' /// ``` declare_clippy_lint! { pub CAST_REF_TO_MUT, - nursery, + correctness, "a cast of reference to a mutable pointer" } -- cgit 1.4.1-3-g733a5 From 38d4ac7ceaf8ace26864e847c8280dc66410587c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 7 Jan 2019 22:33:18 +0100 Subject: Remove all copyright license headers Discussion previously happened in https://github.com/rust-lang/rust/pull/43498 --- .github/deploy.sh | 11 --- COPYRIGHT | 2 +- README.md | 2 +- build.rs | 9 --- ci/base-tests.sh | 11 --- ci/integration-tests.sh | 10 --- clippy_dev/src/lib.rs | 9 --- clippy_dev/src/main.rs | 9 --- clippy_dummy/build.rs | 12 +-- clippy_dummy/src/main.rs | 10 --- clippy_lints/src/approx_const.rs | 9 --- clippy_lints/src/arithmetic.rs | 9 --- clippy_lints/src/assign_ops.rs | 9 --- clippy_lints/src/attrs.rs | 9 --- clippy_lints/src/bit_mask.rs | 9 --- clippy_lints/src/blacklisted_name.rs | 9 --- clippy_lints/src/block_in_if_condition.rs | 9 --- clippy_lints/src/booleans.rs | 9 --- clippy_lints/src/bytecount.rs | 9 --- clippy_lints/src/cargo_common_metadata.rs | 9 --- clippy_lints/src/collapsible_if.rs | 9 --- clippy_lints/src/const_static_lifetime.rs | 9 --- clippy_lints/src/consts.rs | 10 --- clippy_lints/src/copies.rs | 9 --- clippy_lints/src/copy_iterator.rs | 9 --- clippy_lints/src/cyclomatic_complexity.rs | 9 --- clippy_lints/src/default_trait_access.rs | 9 --- clippy_lints/src/deprecated_lints.rs | 10 --- clippy_lints/src/derive.rs | 9 --- clippy_lints/src/doc.rs | 9 --- clippy_lints/src/double_comparison.rs | 9 --- clippy_lints/src/double_parens.rs | 9 --- clippy_lints/src/drop_forget_ref.rs | 9 --- clippy_lints/src/duration_subsec.rs | 9 --- clippy_lints/src/else_if_without_else.rs | 9 --- clippy_lints/src/empty_enum.rs | 9 --- clippy_lints/src/entry.rs | 9 --- clippy_lints/src/enum_clike.rs | 9 --- clippy_lints/src/enum_glob_use.rs | 9 --- clippy_lints/src/enum_variants.rs | 9 --- clippy_lints/src/eq_op.rs | 9 --- clippy_lints/src/erasing_op.rs | 9 --- clippy_lints/src/escape.rs | 9 --- clippy_lints/src/eta_reduction.rs | 9 --- clippy_lints/src/eval_order_dependence.rs | 9 --- clippy_lints/src/excessive_precision.rs | 9 --- clippy_lints/src/explicit_write.rs | 9 --- clippy_lints/src/fallible_impl_from.rs | 9 --- clippy_lints/src/format.rs | 9 --- clippy_lints/src/formatting.rs | 9 --- clippy_lints/src/functions.rs | 9 --- clippy_lints/src/identity_conversion.rs | 9 --- clippy_lints/src/identity_op.rs | 9 --- clippy_lints/src/if_not_else.rs | 9 --- clippy_lints/src/implicit_return.rs | 9 --- clippy_lints/src/indexing_slicing.rs | 9 --- clippy_lints/src/infallible_destructuring_match.rs | 9 --- clippy_lints/src/infinite_iter.rs | 9 --- clippy_lints/src/inherent_impl.rs | 9 --- clippy_lints/src/inline_fn_without_body.rs | 9 --- clippy_lints/src/int_plus_one.rs | 9 --- clippy_lints/src/invalid_ref.rs | 9 --- clippy_lints/src/items_after_statements.rs | 9 --- clippy_lints/src/large_enum_variant.rs | 9 --- clippy_lints/src/len_zero.rs | 9 --- clippy_lints/src/let_if_seq.rs | 9 --- clippy_lints/src/lib.rs | 9 --- clippy_lints/src/lifetimes.rs | 9 --- clippy_lints/src/literal_representation.rs | 9 --- clippy_lints/src/loops.rs | 9 --- clippy_lints/src/map_clone.rs | 9 --- clippy_lints/src/map_unit_fn.rs | 9 --- clippy_lints/src/matches.rs | 9 --- clippy_lints/src/mem_discriminant.rs | 9 --- clippy_lints/src/mem_forget.rs | 9 --- clippy_lints/src/mem_replace.rs | 9 --- clippy_lints/src/methods/mod.rs | 9 --- clippy_lints/src/methods/unnecessary_filter_map.rs | 9 --- clippy_lints/src/minmax.rs | 9 --- clippy_lints/src/misc.rs | 9 --- clippy_lints/src/misc_early.rs | 9 --- clippy_lints/src/missing_doc.rs | 22 ------ clippy_lints/src/missing_inline.rs | 20 ----- clippy_lints/src/multiple_crate_versions.rs | 9 --- clippy_lints/src/mut_mut.rs | 9 --- clippy_lints/src/mut_reference.rs | 9 --- clippy_lints/src/mutex_atomic.rs | 9 --- clippy_lints/src/needless_bool.rs | 9 --- clippy_lints/src/needless_borrow.rs | 9 --- clippy_lints/src/needless_borrowed_ref.rs | 9 --- clippy_lints/src/needless_continue.rs | 9 --- clippy_lints/src/needless_pass_by_value.rs | 9 --- clippy_lints/src/needless_update.rs | 9 --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 9 --- clippy_lints/src/neg_multiply.rs | 9 --- clippy_lints/src/new_without_default.rs | 9 --- clippy_lints/src/no_effect.rs | 9 --- clippy_lints/src/non_copy_const.rs | 9 --- clippy_lints/src/non_expressive_names.rs | 9 --- clippy_lints/src/ok_if_let.rs | 9 --- clippy_lints/src/open_options.rs | 9 --- clippy_lints/src/overflow_check_conditional.rs | 9 --- clippy_lints/src/panic_unimplemented.rs | 9 --- clippy_lints/src/partialeq_ne_impl.rs | 9 --- clippy_lints/src/precedence.rs | 9 --- clippy_lints/src/ptr.rs | 9 --- clippy_lints/src/ptr_offset_with_cast.rs | 9 --- clippy_lints/src/question_mark.rs | 9 --- clippy_lints/src/ranges.rs | 9 --- clippy_lints/src/redundant_clone.rs | 9 --- clippy_lints/src/redundant_field_names.rs | 9 --- clippy_lints/src/redundant_pattern_matching.rs | 9 --- clippy_lints/src/reference.rs | 9 --- clippy_lints/src/regex.rs | 9 --- clippy_lints/src/replace_consts.rs | 9 --- clippy_lints/src/returns.rs | 9 --- clippy_lints/src/serde_api.rs | 9 --- clippy_lints/src/shadow.rs | 9 --- clippy_lints/src/slow_vector_initialization.rs | 9 --- clippy_lints/src/strings.rs | 9 --- clippy_lints/src/suspicious_trait_impl.rs | 9 --- clippy_lints/src/swap.rs | 9 --- clippy_lints/src/temporary_assignment.rs | 9 --- clippy_lints/src/transmute.rs | 9 --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 9 --- clippy_lints/src/types.rs | 10 --- clippy_lints/src/unicode.rs | 9 --- clippy_lints/src/unsafe_removed_from_name.rs | 9 --- clippy_lints/src/unused_io_amount.rs | 9 --- clippy_lints/src/unused_label.rs | 9 --- clippy_lints/src/unwrap.rs | 9 --- clippy_lints/src/use_self.rs | 9 --- clippy_lints/src/utils/author.rs | 9 --- clippy_lints/src/utils/camel_case.rs | 9 --- clippy_lints/src/utils/comparisons.rs | 9 --- clippy_lints/src/utils/conf.rs | 9 --- clippy_lints/src/utils/constants.rs | 9 --- clippy_lints/src/utils/higher.rs | 9 --- clippy_lints/src/utils/hir_utils.rs | 9 --- clippy_lints/src/utils/inspector.rs | 9 --- clippy_lints/src/utils/internal_lints.rs | 9 --- clippy_lints/src/utils/mod.rs | 9 --- clippy_lints/src/utils/paths.rs | 9 --- clippy_lints/src/utils/ptr.rs | 9 --- clippy_lints/src/utils/sugg.rs | 9 --- clippy_lints/src/utils/usage.rs | 9 --- clippy_lints/src/vec.rs | 9 --- clippy_lints/src/wildcard_dependencies.rs | 9 --- clippy_lints/src/write.rs | 9 --- clippy_lints/src/zero_div_zero.rs | 9 --- clippy_workspace_tests/src/main.rs | 10 --- clippy_workspace_tests/subcrate/src/lib.rs | 10 --- mini-macro/src/lib.rs | 10 --- pre_publish.sh | 11 --- rustc_tools_util/README.md | 2 +- rustc_tools_util/src/lib.rs | 9 --- src/driver.rs | 9 --- src/lib.rs | 9 --- src/main.rs | 9 --- tests/auxiliary/test_macro.rs | 9 --- tests/compile-test.rs | 9 --- tests/dogfood.rs | 9 --- tests/matches.rs | 9 --- tests/needless_continue_helpers.rs | 9 --- tests/run-pass/associated-constant-ice.rs | 9 --- tests/run-pass/cc_seme.rs | 9 --- tests/run-pass/enum-glob-import-crate.rs | 9 --- tests/run-pass/ice-1588.rs | 9 --- tests/run-pass/ice-1782.rs | 9 --- tests/run-pass/ice-1969.rs | 9 --- tests/run-pass/ice-2499.rs | 9 --- tests/run-pass/ice-2594.rs | 9 --- tests/run-pass/ice-2727.rs | 9 --- tests/run-pass/ice-2760.rs | 9 --- tests/run-pass/ice-2774.rs | 9 --- tests/run-pass/ice-2865.rs | 9 --- tests/run-pass/ice-3151.rs | 9 --- tests/run-pass/ice-3462.rs | 9 --- tests/run-pass/ice-700.rs | 9 --- tests/run-pass/ice_exacte_size.rs | 9 --- tests/run-pass/if_same_then_else.rs | 9 --- tests/run-pass/issue-2862.rs | 9 --- tests/run-pass/issue-825.rs | 9 --- tests/run-pass/issues_loop_mut_cond.rs | 9 --- tests/run-pass/match_same_arms_const.rs | 9 --- tests/run-pass/mut_mut_macro.rs | 9 --- tests/run-pass/needless_borrow_fp.rs | 9 --- tests/run-pass/needless_lifetimes_impl_trait.rs | 9 --- tests/run-pass/procedural_macro.rs | 9 --- tests/run-pass/regressions.rs | 9 --- tests/run-pass/returns.rs | 9 --- tests/run-pass/single-match-else.rs | 9 --- tests/run-pass/used_underscore_binding_macro.rs | 9 --- tests/run-pass/whitelist/conf_whitelisted.rs | 9 --- tests/ui-toml/bad_toml/conf_bad_toml.rs | 9 --- tests/ui-toml/bad_toml_type/conf_bad_type.rs | 9 --- .../toml_blacklist/conf_french_blacklisted_name.rs | 9 --- .../conf_french_blacklisted_name.stderr | 14 ++-- tests/ui-toml/toml_trivially_copy/test.rs | 9 --- tests/ui-toml/toml_trivially_copy/test.stderr | 4 +- tests/ui-toml/toml_unknown_key/conf_unknown_key.rs | 9 --- tests/ui-toml/update-all-references.sh | 10 --- tests/ui-toml/update-references.sh | 10 --- tests/ui/absurd-extreme-comparisons.rs | 9 --- tests/ui/absurd-extreme-comparisons.stderr | 36 ++++----- tests/ui/approx_const.rs | 9 --- tests/ui/approx_const.stderr | 38 ++++----- tests/ui/arithmetic.rs | 9 --- tests/ui/arithmetic.stderr | 22 +++--- tests/ui/assign_ops.rs | 9 --- tests/ui/assign_ops.stderr | 18 ++--- tests/ui/assign_ops2.rs | 9 --- tests/ui/assign_ops2.stderr | 20 ++--- tests/ui/attrs.rs | 9 --- tests/ui/attrs.stderr | 6 +- tests/ui/author.rs | 9 --- tests/ui/author/call.rs | 9 --- tests/ui/author/for_loop.rs | 9 --- tests/ui/author/matches.rs | 9 --- tests/ui/author/matches.stderr | 4 +- tests/ui/bit_masks.rs | 9 --- tests/ui/bit_masks.stderr | 34 ++++---- tests/ui/blacklisted_name.rs | 9 --- tests/ui/blacklisted_name.stderr | 28 +++---- tests/ui/block_in_if_condition.rs | 9 --- tests/ui/block_in_if_condition.stderr | 10 +-- tests/ui/bool_comparison.rs | 9 --- tests/ui/bool_comparison.stderr | 28 +++---- tests/ui/booleans.rs | 9 --- tests/ui/booleans.stderr | 60 +++++++------- tests/ui/borrow_box.rs | 9 --- tests/ui/borrow_box.stderr | 10 +-- tests/ui/box_vec.rs | 9 --- tests/ui/box_vec.stderr | 2 +- tests/ui/builtin-type-shadow.rs | 9 --- tests/ui/builtin-type-shadow.stderr | 4 +- tests/ui/bytecount.rs | 9 --- tests/ui/bytecount.stderr | 8 +- tests/ui/cast.rs | 9 --- tests/ui/cast.stderr | 56 ++++++------- tests/ui/cast_alignment.rs | 9 --- tests/ui/cast_alignment.stderr | 4 +- tests/ui/cast_lossless_float.fixed | 9 --- tests/ui/cast_lossless_float.rs | 9 --- tests/ui/cast_lossless_float.stderr | 20 ++--- tests/ui/cast_lossless_integer.fixed | 9 --- tests/ui/cast_lossless_integer.rs | 9 --- tests/ui/cast_lossless_integer.stderr | 36 ++++----- tests/ui/cast_size.rs | 9 --- tests/ui/cast_size.stderr | 38 ++++----- tests/ui/cfg_attr_rustfmt.rs | 9 --- tests/ui/cfg_attr_rustfmt.stderr | 6 +- tests/ui/char_lit_as_u8.rs | 9 --- tests/ui/char_lit_as_u8.stderr | 2 +- tests/ui/checked_unwrap.rs | 9 --- tests/ui/checked_unwrap.stderr | 72 ++++++++--------- tests/ui/clone_on_copy_impl.rs | 9 --- tests/ui/clone_on_copy_mut.rs | 9 --- tests/ui/cmp_nan.rs | 9 --- tests/ui/cmp_nan.stderr | 24 +++--- tests/ui/cmp_null.rs | 9 --- tests/ui/cmp_null.stderr | 4 +- tests/ui/cmp_owned.rs | 9 --- tests/ui/cmp_owned.stderr | 18 ++--- tests/ui/collapsible_if.rs | 9 --- tests/ui/collapsible_if.stderr | 28 +++---- tests/ui/complex_types.rs | 9 --- tests/ui/complex_types.stderr | 30 +++---- tests/ui/const_static_lifetime.rs | 9 --- tests/ui/const_static_lifetime.stderr | 26 +++--- tests/ui/copies.rs | 9 --- tests/ui/copies.stderr | 82 +++++++++---------- tests/ui/copy_iterator.rs | 9 --- tests/ui/copy_iterator.stderr | 2 +- tests/ui/cstring.rs | 9 --- tests/ui/cstring.stderr | 4 +- tests/ui/cyclomatic_complexity.rs | 9 --- tests/ui/cyclomatic_complexity.stderr | 40 +++++----- tests/ui/cyclomatic_complexity_attr_used.rs | 9 --- tests/ui/cyclomatic_complexity_attr_used.stderr | 2 +- tests/ui/decimal_literal_representation.rs | 9 --- tests/ui/decimal_literal_representation.stderr | 10 +-- tests/ui/default_trait_access.rs | 9 --- tests/ui/default_trait_access.stderr | 16 ++-- tests/ui/deprecated.rs | 9 --- tests/ui/deprecated.stderr | 10 +-- tests/ui/derive.rs | 9 --- tests/ui/derive.stderr | 28 +++---- tests/ui/diverging_sub_expression.rs | 9 --- tests/ui/diverging_sub_expression.stderr | 12 +-- tests/ui/dlist.rs | 9 --- tests/ui/dlist.stderr | 12 +-- tests/ui/doc.rs | 9 --- tests/ui/doc.stderr | 62 +++++++-------- tests/ui/double_comparison.fixed | 9 --- tests/ui/double_comparison.rs | 9 --- tests/ui/double_comparison.stderr | 16 ++-- tests/ui/double_neg.rs | 9 --- tests/ui/double_neg.stderr | 2 +- tests/ui/double_parens.rs | 9 --- tests/ui/double_parens.stderr | 12 +-- tests/ui/drop_forget_copy.rs | 9 --- tests/ui/drop_forget_copy.stderr | 24 +++--- tests/ui/drop_forget_ref.rs | 9 --- tests/ui/drop_forget_ref.stderr | 72 ++++++++--------- tests/ui/duplicate_underscore_argument.rs | 9 --- tests/ui/duplicate_underscore_argument.stderr | 2 +- tests/ui/duration_subsec.rs | 9 --- tests/ui/duration_subsec.stderr | 10 +-- tests/ui/else_if_without_else.rs | 9 --- tests/ui/else_if_without_else.stderr | 4 +- tests/ui/empty_enum.rs | 9 --- tests/ui/empty_enum.stderr | 4 +- tests/ui/empty_line_after_outer_attribute.rs | 9 --- tests/ui/empty_line_after_outer_attribute.stderr | 12 +-- tests/ui/entry.rs | 9 --- tests/ui/entry.stderr | 14 ++-- tests/ui/enum_glob_use.rs | 9 --- tests/ui/enum_glob_use.stderr | 4 +- tests/ui/enum_variants.rs | 9 --- tests/ui/enum_variants.stderr | 20 ++--- tests/ui/enums_clike.rs | 9 --- tests/ui/enums_clike.stderr | 16 ++-- tests/ui/eq_op.rs | 9 --- tests/ui/eq_op.stderr | 68 ++++++++-------- tests/ui/erasing_op.rs | 9 --- tests/ui/erasing_op.stderr | 6 +- tests/ui/escape_analysis.rs | 9 --- tests/ui/escape_analysis.stderr | 4 +- tests/ui/eta.rs | 9 --- tests/ui/eta.stderr | 10 +-- tests/ui/eval_order_dependence.rs | 9 --- tests/ui/eval_order_dependence.stderr | 16 ++-- tests/ui/excessive_precision.rs | 9 --- tests/ui/excessive_precision.stderr | 36 ++++----- tests/ui/expect_fun_call.rs | 9 --- tests/ui/expect_fun_call.stderr | 12 +-- tests/ui/explicit_counter_loop.rs | 9 --- tests/ui/explicit_counter_loop.stderr | 8 +- tests/ui/explicit_write.rs | 9 --- tests/ui/explicit_write.stderr | 16 ++-- tests/ui/fallible_impl_from.rs | 9 --- tests/ui/fallible_impl_from.stderr | 18 ++--- tests/ui/filter_methods.rs | 9 --- tests/ui/filter_methods.stderr | 8 +- tests/ui/float_cmp.rs | 9 --- tests/ui/float_cmp.stderr | 12 +-- tests/ui/float_cmp_const.rs | 9 --- tests/ui/float_cmp_const.stderr | 28 +++---- tests/ui/fn_to_numeric_cast.rs | 9 --- tests/ui/fn_to_numeric_cast.stderr | 46 +++++------ tests/ui/for_kv_map.rs | 9 --- tests/ui/for_kv_map.stderr | 10 +-- tests/ui/for_loop.rs | 9 --- tests/ui/for_loop.stderr | 92 +++++++++++----------- tests/ui/for_loop_over_option_result.rs | 9 --- tests/ui/for_loop_over_option_result.stderr | 16 ++-- tests/ui/format.rs | 10 --- tests/ui/format.stderr | 18 ++--- tests/ui/formatting.rs | 9 --- tests/ui/formatting.stderr | 26 +++--- tests/ui/functions.rs | 9 --- tests/ui/functions.stderr | 24 +++--- tests/ui/fxhash.rs | 9 --- tests/ui/fxhash.stderr | 12 +-- tests/ui/get_unwrap.fixed | 9 --- tests/ui/get_unwrap.rs | 9 --- tests/ui/get_unwrap.stderr | 26 +++--- tests/ui/ice-2636.rs | 9 --- tests/ui/ice-2636.stderr | 2 +- tests/ui/identity_conversion.rs | 9 --- tests/ui/identity_conversion.stderr | 22 +++--- tests/ui/identity_op.rs | 9 --- tests/ui/identity_op.stderr | 16 ++-- tests/ui/if_not_else.rs | 9 --- tests/ui/if_not_else.stderr | 4 +- tests/ui/impl.rs | 9 --- tests/ui/impl.stderr | 8 +- tests/ui/implicit_hasher.rs | 9 --- tests/ui/implicit_hasher.stderr | 20 ++--- tests/ui/implicit_return.rs | 9 --- tests/ui/implicit_return.stderr | 20 ++--- tests/ui/inconsistent_digit_grouping.rs | 9 --- tests/ui/inconsistent_digit_grouping.stderr | 10 +-- tests/ui/indexing_slicing.rs | 9 --- tests/ui/indexing_slicing.stderr | 86 ++++++++++---------- tests/ui/infallible_destructuring_match.rs | 9 --- tests/ui/infallible_destructuring_match.stderr | 6 +- tests/ui/infinite_iter.rs | 9 --- tests/ui/infinite_iter.stderr | 34 ++++---- tests/ui/infinite_loop.rs | 9 --- tests/ui/infinite_loop.stderr | 18 ++--- tests/ui/inline_fn_without_body.rs | 9 --- tests/ui/inline_fn_without_body.stderr | 6 +- tests/ui/int_plus_one.rs | 9 --- tests/ui/int_plus_one.stderr | 8 +- tests/ui/invalid_ref.rs | 9 --- tests/ui/invalid_ref.stderr | 12 +-- tests/ui/invalid_upcast_comparisons.rs | 9 --- tests/ui/invalid_upcast_comparisons.stderr | 54 ++++++------- tests/ui/issue-3145.rs | 9 --- tests/ui/issue-3145.stderr | 2 +- tests/ui/issue_2356.rs | 9 --- tests/ui/issue_2356.stderr | 4 +- tests/ui/item_after_statement.rs | 9 --- tests/ui/item_after_statement.stderr | 4 +- tests/ui/iter_skip_next.rs | 9 --- tests/ui/iter_skip_next.stderr | 8 +- tests/ui/large_digit_groups.rs | 9 --- tests/ui/large_digit_groups.stderr | 12 +-- tests/ui/large_enum_variant.rs | 9 --- tests/ui/large_enum_variant.stderr | 18 ++--- tests/ui/len_zero.rs | 9 --- tests/ui/len_zero.stderr | 38 ++++----- tests/ui/let_if_seq.rs | 9 --- tests/ui/let_if_seq.stderr | 8 +- tests/ui/let_return.rs | 9 --- tests/ui/let_return.stderr | 8 +- tests/ui/let_unit.rs | 9 --- tests/ui/let_unit.stderr | 4 +- tests/ui/lifetimes.rs | 9 --- tests/ui/lifetimes.stderr | 30 +++---- tests/ui/literals.rs | 9 --- tests/ui/literals.stderr | 62 +++++++-------- tests/ui/map_clone.rs | 9 --- tests/ui/map_clone.stderr | 6 +- tests/ui/map_flatten.rs | 9 --- tests/ui/map_flatten.stderr | 2 +- tests/ui/map_unit_fn.rs | 9 --- tests/ui/match_bool.rs | 9 --- tests/ui/match_bool.stderr | 16 ++-- tests/ui/match_overlapping_arm.rs | 9 --- tests/ui/match_overlapping_arm.stderr | 20 ++--- tests/ui/matches.rs | 9 --- tests/ui/matches.stderr | 74 ++++++++--------- tests/ui/mem_discriminant.rs | 9 --- tests/ui/mem_discriminant.stderr | 26 +++--- tests/ui/mem_forget.rs | 9 --- tests/ui/mem_forget.stderr | 6 +- tests/ui/mem_replace.rs | 2 +- tests/ui/methods.rs | 9 --- tests/ui/methods.stderr | 86 ++++++++++---------- tests/ui/min_max.rs | 9 --- tests/ui/min_max.stderr | 14 ++-- tests/ui/missing-doc.rs | 22 ------ tests/ui/missing-doc.stderr | 78 +++++++++--------- tests/ui/missing_inline.rs | 21 ----- tests/ui/missing_inline.stderr | 12 +-- tests/ui/module_inception.rs | 9 --- tests/ui/module_inception.stderr | 4 +- tests/ui/module_name_repetitions.rs | 9 --- tests/ui/module_name_repetitions.stderr | 10 +-- tests/ui/modulo_one.rs | 9 --- tests/ui/modulo_one.stderr | 2 +- tests/ui/mut_from_ref.rs | 9 --- tests/ui/mut_from_ref.stderr | 20 ++--- tests/ui/mut_mut.rs | 9 --- tests/ui/mut_mut.stderr | 18 ++--- tests/ui/mut_range_bound.rs | 9 --- tests/ui/mut_range_bound.stderr | 10 +-- tests/ui/mut_reference.rs | 9 --- tests/ui/mut_reference.stderr | 6 +- tests/ui/mutex_atomic.rs | 9 --- tests/ui/mutex_atomic.stderr | 14 ++-- tests/ui/needless_bool.rs | 9 --- tests/ui/needless_bool.stderr | 30 +++---- tests/ui/needless_borrow.rs | 9 --- tests/ui/needless_borrow.stderr | 12 +-- tests/ui/needless_borrowed_ref.rs | 9 --- tests/ui/needless_borrowed_ref.stderr | 8 +- tests/ui/needless_collect.rs | 9 --- tests/ui/needless_collect.stderr | 8 +- tests/ui/needless_continue.rs | 9 --- tests/ui/needless_continue.stderr | 4 +- tests/ui/needless_pass_by_value.rs | 9 --- tests/ui/needless_pass_by_value.stderr | 52 ++++++------ tests/ui/needless_pass_by_value_proc_macro.rs | 9 --- tests/ui/needless_range_loop.rs | 9 --- tests/ui/needless_range_loop.stderr | 16 ++-- tests/ui/needless_return.rs | 9 --- tests/ui/needless_return.stderr | 16 ++-- tests/ui/needless_update.rs | 9 --- tests/ui/needless_update.stderr | 2 +- tests/ui/neg_cmp_op_on_partial_ord.rs | 9 --- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 +- tests/ui/neg_multiply.rs | 9 --- tests/ui/neg_multiply.stderr | 4 +- tests/ui/never_loop.rs | 9 --- tests/ui/never_loop.stderr | 18 ++--- tests/ui/new_without_default.rs | 9 --- tests/ui/new_without_default.stderr | 6 +- tests/ui/no_effect.rs | 9 --- tests/ui/no_effect.stderr | 50 ++++++------ tests/ui/non_copy_const.rs | 9 --- tests/ui/non_copy_const.stderr | 74 ++++++++--------- tests/ui/non_expressive_names.rs | 9 --- tests/ui/non_expressive_names.stderr | 56 ++++++------- tests/ui/ok_expect.rs | 9 --- tests/ui/ok_expect.stderr | 10 +-- tests/ui/ok_if_let.rs | 9 --- tests/ui/ok_if_let.stderr | 2 +- tests/ui/op_ref.rs | 9 --- tests/ui/op_ref.stderr | 4 +- tests/ui/open_options.rs | 9 --- tests/ui/open_options.stderr | 14 ++-- tests/ui/option_map_unit_fn.rs | 9 --- tests/ui/option_map_unit_fn.stderr | 50 ++++++------ tests/ui/option_option.rs | 9 --- tests/ui/option_option.stderr | 18 ++--- tests/ui/overflow_check_conditional.rs | 9 --- tests/ui/overflow_check_conditional.stderr | 16 ++-- tests/ui/panic_unimplemented.rs | 9 --- tests/ui/panic_unimplemented.stderr | 10 +-- tests/ui/partialeq_ne_impl.rs | 9 --- tests/ui/partialeq_ne_impl.stderr | 2 +- tests/ui/patterns.rs | 9 --- tests/ui/patterns.stderr | 2 +- tests/ui/precedence.rs | 9 --- tests/ui/precedence.stderr | 18 ++--- tests/ui/print.rs | 9 --- tests/ui/print.stderr | 18 ++--- tests/ui/print_literal.rs | 9 --- tests/ui/print_literal.stderr | 28 +++---- tests/ui/print_with_newline.rs | 9 --- tests/ui/print_with_newline.stderr | 8 +- tests/ui/println_empty_string.fixed | 9 --- tests/ui/println_empty_string.rs | 9 --- tests/ui/println_empty_string.stderr | 4 +- tests/ui/ptr_arg.rs | 9 --- tests/ui/ptr_arg.stderr | 14 ++-- tests/ui/ptr_offset_with_cast.fixed | 9 --- tests/ui/ptr_offset_with_cast.rs | 9 --- tests/ui/ptr_offset_with_cast.stderr | 4 +- tests/ui/question_mark.rs | 9 --- tests/ui/question_mark.stderr | 14 ++-- tests/ui/range.rs | 9 --- tests/ui/range.stderr | 12 +-- tests/ui/range_plus_minus_one.rs | 9 --- tests/ui/range_plus_minus_one.stderr | 16 ++-- tests/ui/redundant_clone.rs | 9 --- tests/ui/redundant_clone.stderr | 40 +++++----- tests/ui/redundant_closure_call.rs | 9 --- tests/ui/redundant_closure_call.stderr | 10 +-- tests/ui/redundant_field_names.rs | 9 --- tests/ui/redundant_field_names.stderr | 14 ++-- tests/ui/redundant_pattern_matching.rs | 9 --- tests/ui/redundant_pattern_matching.stderr | 20 ++--- tests/ui/reference.rs | 9 --- tests/ui/reference.stderr | 22 +++--- tests/ui/regex.rs | 9 --- tests/ui/regex.stderr | 46 +++++------ tests/ui/rename.rs | 9 --- tests/ui/rename.stderr | 6 +- tests/ui/replace_consts.rs | 9 --- tests/ui/replace_consts.stderr | 72 ++++++++--------- tests/ui/result_map_unit_fn.rs | 9 --- tests/ui/result_map_unit_fn.stderr | 46 +++++------ tests/ui/result_map_unwrap_or_else.rs | 9 --- tests/ui/result_map_unwrap_or_else.stderr | 6 +- tests/ui/serde.rs | 9 --- tests/ui/serde.stderr | 2 +- tests/ui/shadow.rs | 9 --- tests/ui/shadow.stderr | 46 +++++------ tests/ui/short_circuit_statement.rs | 9 --- tests/ui/short_circuit_statement.stderr | 6 +- tests/ui/single_char_pattern.fixed | 9 --- tests/ui/single_char_pattern.rs | 9 --- tests/ui/single_char_pattern.stderr | 40 +++++----- tests/ui/single_match.rs | 9 --- tests/ui/single_match.stderr | 12 +-- tests/ui/single_match_else.rs | 9 --- tests/ui/single_match_else.stderr | 2 +- tests/ui/slow_vector_initialization.rs | 9 --- tests/ui/slow_vector_initialization.stderr | 14 ++-- tests/ui/starts_ends_with.rs | 9 --- tests/ui/starts_ends_with.stderr | 24 +++--- tests/ui/string_extend.fixed | 9 --- tests/ui/string_extend.rs | 9 --- tests/ui/string_extend.stderr | 6 +- tests/ui/strings.rs | 9 --- tests/ui/strings.stderr | 22 +++--- tests/ui/suspicious_arithmetic_impl.rs | 9 --- tests/ui/suspicious_arithmetic_impl.stderr | 4 +- tests/ui/swap.rs | 9 --- tests/ui/swap.stderr | 14 ++-- tests/ui/temporary_assignment.rs | 9 --- tests/ui/temporary_assignment.stderr | 16 ++-- tests/ui/toplevel_ref_arg.rs | 9 --- tests/ui/toplevel_ref_arg.stderr | 10 +-- tests/ui/trailing_zeros.rs | 9 --- tests/ui/trailing_zeros.stderr | 4 +- tests/ui/transmute.rs | 9 --- tests/ui/transmute.stderr | 76 +++++++++--------- tests/ui/transmute_32bit.rs | 9 --- tests/ui/transmute_64bit.rs | 9 --- tests/ui/transmute_64bit.stderr | 4 +- tests/ui/trivially_copy_pass_by_ref.rs | 9 --- tests/ui/trivially_copy_pass_by_ref.stderr | 30 +++---- tests/ui/ty_fn_sig.rs | 9 --- tests/ui/types.rs | 9 --- tests/ui/types.stderr | 2 +- tests/ui/unicode.rs | 9 --- tests/ui/unicode.stderr | 6 +- tests/ui/unit_arg.rs | 9 --- tests/ui/unit_arg.stderr | 12 +-- tests/ui/unit_cmp.rs | 9 --- tests/ui/unit_cmp.stderr | 4 +- tests/ui/unknown_clippy_lints.rs | 9 --- tests/ui/unknown_clippy_lints.stderr | 4 +- tests/ui/unnecessary_clone.rs | 9 --- tests/ui/unnecessary_clone.stderr | 26 +++--- tests/ui/unnecessary_filter_map.rs | 9 --- tests/ui/unnecessary_filter_map.stderr | 8 +- tests/ui/unnecessary_fold.rs | 9 --- tests/ui/unnecessary_fold.stderr | 10 +-- tests/ui/unnecessary_operation.rs | 9 --- tests/ui/unnecessary_operation.stderr | 40 +++++----- tests/ui/unnecessary_ref.fixed | 9 --- tests/ui/unnecessary_ref.rs | 9 --- tests/ui/unnecessary_ref.stderr | 4 +- tests/ui/unneeded_field_pattern.rs | 9 --- tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unreadable_literal.fixed | 9 --- tests/ui/unreadable_literal.rs | 9 --- tests/ui/unreadable_literal.stderr | 10 +-- tests/ui/unsafe_removed_from_name.rs | 9 --- tests/ui/unsafe_removed_from_name.stderr | 6 +- tests/ui/unused_io_amount.rs | 9 --- tests/ui/unused_io_amount.stderr | 12 +-- tests/ui/unused_labels.rs | 9 --- tests/ui/unused_labels.stderr | 6 +- tests/ui/unused_lt.rs | 9 --- tests/ui/unused_lt.stderr | 6 +- tests/ui/unused_unit.rs | 10 --- tests/ui/unused_unit.stderr | 16 ++-- tests/ui/unwrap_or.rs | 9 --- tests/ui/unwrap_or.stderr | 4 +- tests/ui/update-all-references.sh | 10 --- tests/ui/update-references.sh | 10 --- tests/ui/use_self.rs | 9 --- tests/ui/use_self.stderr | 52 ++++++------ tests/ui/used_underscore_binding.rs | 9 --- tests/ui/used_underscore_binding.stderr | 10 +-- tests/ui/useful_asref.rs | 9 --- tests/ui/useless_asref.rs | 9 --- tests/ui/useless_asref.stderr | 24 +++--- tests/ui/useless_attribute.rs | 9 --- tests/ui/useless_attribute.stderr | 4 +- tests/ui/vec.fixed | 9 --- tests/ui/vec.rs | 9 --- tests/ui/vec.stderr | 12 +-- tests/ui/while_loop.rs | 9 --- tests/ui/while_loop.stderr | 24 +++--- tests/ui/write_literal.rs | 9 --- tests/ui/write_literal.stderr | 28 +++---- tests/ui/write_with_newline.rs | 9 --- tests/ui/write_with_newline.stderr | 10 +-- tests/ui/writeln_empty_string.fixed | 9 --- tests/ui/writeln_empty_string.rs | 9 --- tests/ui/writeln_empty_string.stderr | 4 +- tests/ui/wrong_self_convention.rs | 9 --- tests/ui/wrong_self_convention.stderr | 24 +++--- tests/ui/zero_div_zero.rs | 9 --- tests/ui/zero_div_zero.stderr | 16 ++-- tests/ui/zero_ptr.rs | 9 --- tests/ui/zero_ptr.stderr | 4 +- tests/versioncheck.rs | 9 --- util/cov.sh | 11 --- util/export.py | 11 --- util/lintlib.py | 10 --- util/update_lints.py | 10 --- 671 files changed, 2153 insertions(+), 6243 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index 11d0b2d2a85..a242c35c3ae 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -1,16 +1,5 @@ #!/bin/bash -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - - # Automatically deploy on gh-pages set -ex diff --git a/COPYRIGHT b/COPYRIGHT index cb9970597a2..e507fb8b9b9 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 2014-2018 The Rust Project Developers +Copyright 2014-2019 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/README.md b/README.md index 8ca10da416d..ca2ff529552 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT ## License -Copyright 2014-2018 The Rust Project Developers +Copyright 2014-2019 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/build.rs b/build.rs index 22a6910f167..146a8dae745 100644 --- a/build.rs +++ b/build.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { // Forward the profile to the main compilation println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap()); diff --git a/ci/base-tests.sh b/ci/base-tests.sh index b69e86ad3ac..6675c795b3b 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,14 +1,3 @@ -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - - set -ex echo "Running clippy base tests" diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh index bf43d5b6811..1259c5e1d37 100755 --- a/ci/integration-tests.sh +++ b/ci/integration-tests.sh @@ -1,13 +1,3 @@ -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - set -x rm ~/.cargo/bin/cargo-clippy cargo install --force --path . diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 60f1a3df522..073b3a9e97f 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::default_hash_types)] use itertools::Itertools; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 4ed07960010..1d9245d1347 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - extern crate clap; extern crate clippy_dev; extern crate regex; diff --git a/clippy_dummy/build.rs b/clippy_dummy/build.rs index b4ea0772ee5..59d32e5db43 100644 --- a/clippy_dummy/build.rs +++ b/clippy_dummy/build.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - extern crate term; fn main() { @@ -49,4 +39,4 @@ fn foo() -> Result<(), ()> { t.reset().map_err(|_| ())?; Ok(()) -} \ No newline at end of file +} diff --git a/clippy_dummy/src/main.rs b/clippy_dummy/src/main.rs index 878993d5c28..a118834f1fd 100644 --- a/clippy_dummy/src/main.rs +++ b/clippy_dummy/src/main.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - fn main() { panic!("This shouldn't even compile") } diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index afbfdd32304..8410408312f 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index c466b8cd5c9..d133a583f02 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 496b6d65993..ad77ee3a3fa 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; use crate::utils::{higher, sugg}; use if_chain::if_chain; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 41946d06293..24cc8a81dc0 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! checks for attributes use crate::reexport::*; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 9af80493af1..b08d9961d25 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant, Constant}; use crate::utils::sugg::Sugg; use crate::utils::{span_lint, span_lint_and_then}; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index ed7437e495b..64b3be8f302 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 92979dc024d..6e850931e6b 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::*; use matches::matches; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 2279d24af95..8b1a56e3b6e 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_then, SpanlessEq, }; diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 0f2062d9e0f..794b43f4db5 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty, diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 9f396b61330..70ea387515a 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on missing cargo common metadata use crate::utils::span_lint; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index ae613d70240..10cbc9e6ccd 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for if expressions that contain only an if expression. //! //! For example, the lint would catch: diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index a7509dae3d5..229a411ce06 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, snippet, span_lint_and_then}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 8102a416d82..5780b9bcfd4 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - #![allow(clippy::float_cmp)] use crate::utils::{clip, sext, unsext}; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 01398380075..3676519adc1 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; use crate::utils::{SpanlessEq, SpanlessHash}; use rustc::hir::*; diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index f45d8eea5e1..3d0df7424f1 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use rustc::hir::{Item, ItemKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 695e4329dfd..9170f1e8ecf 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! calculate cyclomatic complexity and warn about overly complex functions use rustc::cfg::CFG; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 9dc404efd7e..c4b39dc0f0a 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 17bef09164b..7cb04d7a95b 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - macro_rules! declare_deprecated_lint { (pub $name: ident, $_reason: expr) => { declare_lint!(pub $name, Allow, "deprecated lint") diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index b4556ebaff9..a2bf0098ab8 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; use if_chain::if_chain; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index a3504e7e330..e96ef9ac621 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use itertools::Itertools; use pulldown_cmark; diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 34f4a56bef9..fc4af438d44 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Lint on unnecessary double comparisons. Some examples: use rustc::hir::*; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 3b476b81707..38381b069f0 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, span_lint}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index f0f91c9ab69..4a2a38f6ea1 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index aebb378ee9b..3ac98c71644 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index ff8345290b2..f633d81764b 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on if expressions with an else if, but without a final else branch use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index af2a54069fc..71e84bf1b47 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint when there is an enum with no variants use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index c59bfd1ad92..646a2569bbe 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::SpanlessEq; use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 78cade1f2fb..ab9bc6cd0ca 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index aa1ee038c59..9402c2a5aad 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on `use`ing all variants of an enum use crate::utils::span_lint; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 5466baae886..ffaa8b2811a 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on enum variants that are prefixed or suffixed by the same characters use crate::utils::{camel_case, in_macro}; diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index af9de9fe7e4..93132534a76 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq, }; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 43f16c74eb1..fea31855543 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::utils::{in_macro, span_lint}; use rustc::hir::*; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 445aeb3377b..75020b14492 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir::intravisit as visit; use rustc::hir::*; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index dd80afbc4ae..624d215492f 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 50944eb5e7e..8bd8461b119 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_parent_expr, span_lint, span_note_and_lint}; use if_chain::if_chain; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index b3cf9131cce..f17b82ab33d 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index f56e3225d0a..0bbc85a0416 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 65790b1b42e..2d11b3bd947 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; use crate::utils::{is_expn_of, match_def_path, method_chain_args, opt_def_id, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 1db52079d3f..57c21bee722 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::{ in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index ce51f1433f9..6459e7b81c6 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 19adf2d1dc4..a2b7d31b183 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; use matches::matches; use rustc::hir; diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index b18d63a94b6..d0e1ee57748 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then, }; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 5f1101461bd..862c289fce1 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::utils::{clip, in_macro, snippet, span_lint, unsext}; use rustc::hir::*; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index c40fb540da6..19554c7e207 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 674667c4b5b..cd5db359628 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index cf971b63052..b4893c759c8 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index e3d03c0e697..5d0c5a4a79d 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index e2da8461f41..c25c4ec488f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 5224b5fb867..52aa73d7a10 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on inherent implementations use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index afa8f234023..a092f86658b 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! checks for `#[inline]` on trait methods without bodies use crate::utils::span_lint_and_then; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 3498c1e8114..547052f3429 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on blocks unnecessarily using >= with a + 1 or - 1 use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index c0dcda6349b..03b099b4393 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 2d8f284ea6d..0af8c3dd5cb 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint when items are used after statements use crate::utils::{in_macro, span_lint}; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 052504cc57c..d5bc2a8fad7 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint when there is a large size difference between variants on an enum use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 233bea77e03..40fef2df27f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use rustc::hir::def_id::DefId; use rustc::hir::*; diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 7e9f1b41d27..c3b3272dffd 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{snippet, span_lint_and_then}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 35c00fb6328..e9d8732cb35 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern:cargo-clippy #![feature(box_syntax)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 32170c9a7c6..f7512446c87 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::reexport::*; use crate::utils::{last_path_segment, span_lint}; use matches::matches; diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 72bd6b09fea..d6e6ffa61b3 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d8d95cf9a23..d6430cf291b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::reexport::*; use if_chain::if_chain; use itertools::Itertools; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 2a7177d1fb9..1546964e426 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::{ in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index eca35422de2..4b4f1ad5919 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; use if_chain::if_chain; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 00292eb9603..b003da44236 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 0f8ccc7dedb..a75959e58fa 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_def_path, opt_def_id, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; use if_chain::if_chain; use rustc::hir::{Expr, ExprKind}; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index d231d054610..f83a8b5f7fe 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 0a77b7d2044..d649895e33f 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::{Expr, ExprKind, MutMutable, QPath}; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4473802da3b..41011e8f66a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::sugg; use crate::utils::{ diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index c5a22961db9..8d90a4388fc 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::usage::mutated_variables; use crate::utils::{match_qpath, match_trait_method, span_lint}; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 087aa94a7ec..beea667dd43 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; use rustc::hir::*; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e96261bbe28..4e5910f76bb 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant, Constant}; use crate::reexport::*; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 6b9b90e17a5..2cda1accc56 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 90503970823..7b56609e493 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -1,25 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This file incorporates work covered by the following copyright and -// permission notice: -// Copyright 2012-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// - // Note: More specifically this lint is largely inspired (aka copied) from // *rustc*'s // [`missing_doc`]. diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 8fb677c7cdf..e9d0d2d77f1 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,23 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Copyright 2012-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// - use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index c6374afb4de..073d3857c55 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! lint on multiple versions of a crate being used use crate::utils::span_lint; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index e1702cc373b..9aa3cce9d4b 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{higher, span_lint}; use rustc::hir; use rustc::hir::intravisit; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index ddb8bd30137..5293c80ca2b 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index a114e691228..b85f4b8ad30 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for uses of mutex where an atomic value could be used //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 08408c4475c..1dfc3f6501e 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for needless boolean results of if-else expressions //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 80c9fc549d9..f21cbe8b9ad 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for needless address of operations (`&`) //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index e2801a2e1e0..792e38e1875 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for useless borrowed references. //! //! This lint is **warn** by default diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 9044245c5a6..0b5ea255d7f 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for continue statements in loops that are redundant. //! //! For example, the lint would catch diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 9184a486374..b02faa08006 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::ptr::get_spans; use crate::utils::{ get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet, diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 993aa73f6f7..ab22e2c19b3 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 6642f674da8..919c771ccf5 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 55edca6cece..846794d8b99 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 832311dc027..37e0446faed 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_node_and_then}; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index c2cffadf6c1..53d7575e3e0 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use rustc::hir::def::Def; use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 57482ff4179..11295c3c092 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for uses of const which the type is not Freeze (Cell-free). //! //! This lint is **deny** by default. diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 2ab7d7e62f3..f39cae46de0 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{span_lint, span_lint_and_then}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index e060220d56b..5f15662c90c 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index f6773dcb158..e21225fbd29 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 8df3ba4197f..d76a9f96eff 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{span_lint, SpanlessEq}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 822361175d6..61646613b11 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index c33367e7a3f..03d2d5d3bab 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_automatically_derived, span_lint_node}; use if_chain::if_chain; use rustc::hir::*; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 20a797937de..44e82984c54 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f45bb54d191..87cd9892893 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Checks for usage of `&Vec[_]` and `&String`. use crate::utils::ptr::get_spans; diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 8d6bca8b689..32d330ac171 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils; use rustc::{declare_tool_lint, hir, lint, lint_array}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index c1a76eed928..a4c4e66cf71 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::sugg::Sugg; use if_chain::if_chain; use rustc::hir::def::Def; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index a0870ea72d0..2e01afc2258 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::sugg::Sugg; use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq}; use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then}; diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 1983cb6cbc4..f584ef19d5a 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -1,12 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ has_drop, in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, span_lint_node_and_then, walk_ptrs_ty_depth, diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index a53df6a292a..9076d67cb14 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint_and_sugg; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index bd194dd7bc3..bc61ee8e7e3 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 54a9c0336f0..8d2543ef618 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 021237d38c0..6a58a6e73c7 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant, Constant}; use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint}; use if_chain::if_chain; diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index d905d3dbdf4..ea51e4711cd 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{match_def_path, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 1ef03a77bd7..d81d04b81d3 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index d381f8c4419..da8675b38da 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_trait_def_id, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 329e83e100b..84dd339a985 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::reexport::*; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; use rustc::hir::intravisit::FnKind; diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index fde679b6ed2..77f70fad588 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::sugg::Sugg; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use if_chain::if_chain; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 5414a1ac0de..ffec764fd5e 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use rustc::hir::*; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 04f8e4993f0..c6dd9504857 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_trait_def_id, span_lint}; use if_chain::if_chain; use rustc::hir; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 4c4fda26253..56f503afeae 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::sugg::Sugg; use crate::utils::{ differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq, diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 381efd57135..c8a01c3668c 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::is_adjusted; use crate::utils::span_lint; use rustc::hir::def::Def; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index be3475f6703..02205cfbd68 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use crate::utils::{opt_def_id, sugg}; use if_chain::if_chain; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index efa6c0486eb..5ab73758301 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::cmp; use crate::utils::{in_macro, is_copy, is_self_ty, snippet, span_lint_and_sugg}; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f9ed38e52a0..f4b75437ff6 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - #![allow(clippy::default_hash_types)] use crate::consts::{constant, Constant}; diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index a38fe4a5aa9..d9207fd2131 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_allowed, snippet, span_help_and_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 626b1c31013..6beda8ce706 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 43f980c72c4..c33b6b742fa 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 766431c3687..d53fd265d37 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{in_macro, span_lint}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index b61b3b975f5..369b33363b5 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use if_chain::if_chain; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 5ec809f1b76..b72401e1cca 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir::def::{CtorKind, Def}; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e13c64b5c78..51e7d333084 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. diff --git a/clippy_lints/src/utils/camel_case.rs b/clippy_lints/src/utils/camel_case.rs index f58f3e3b98a..b49287b30d1 100644 --- a/clippy_lints/src/utils/camel_case.rs +++ b/clippy_lints/src/utils/camel_case.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - /// Return the index of the character after the first camel-case component of /// `s`. pub fn until(s: &str) -> usize { diff --git a/clippy_lints/src/utils/comparisons.rs b/clippy_lints/src/utils/comparisons.rs index 8b6a97a505c..31e20f37e20 100644 --- a/clippy_lints/src/utils/comparisons.rs +++ b/clippy_lints/src/utils/comparisons.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Utility functions about comparison operators. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index da3a256a83d..55256a25427 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Read configurations files. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/constants.rs b/clippy_lints/src/utils/constants.rs index dde70d8e2cc..522932f054d 100644 --- a/clippy_lints/src/utils/constants.rs +++ b/clippy_lints/src/utils/constants.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This module contains some useful constants. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 214b3dc10e6..682093b08e4 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This module contains functions for retrieve the original AST from lowered //! `hir`. diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 377e56ddcac..aed9bb9afc9 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant_context, constant_simple}; use crate::utils::differing_macro_contexts; use rustc::hir::*; diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 98ddcf945d9..6ce27c18cec 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! checks for attributes use crate::utils::get_attr; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index be412f36edd..788fc434d51 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{ match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9b5e18413a2..5d94f0f3f05 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::reexport::*; use if_chain::if_chain; use matches::matches; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0779d77936f..a74e457a9fd 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This module contains paths to types and functions Clippy needs to know //! about. diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 3f589c3b687..3d221fbfb81 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{get_pat_name, match_var, snippet}; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index a8bc0f3fca1..d42af5fde3a 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Contains utility functions to generate suggestions. #![deny(clippy::missing_docs_in_private_items)] diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index e4d3fa29996..a3d3518ef98 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use rustc::lint::LateContext; use rustc::hir::def::Def; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 2f259bf8bca..407722bc66e 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::constant; use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 38bce9da932..e3c35286251 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 6531e71a9fa..bb62cdeb9ed 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 93606e378d9..962d42e631e 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant_simple, Constant}; use crate::utils::span_help_and_lint; use if_chain::if_chain; diff --git a/clippy_workspace_tests/src/main.rs b/clippy_workspace_tests/src/main.rs index 7af28f80b9b..f79c691f085 100644 --- a/clippy_workspace_tests/src/main.rs +++ b/clippy_workspace_tests/src/main.rs @@ -1,12 +1,2 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - fn main() { } diff --git a/clippy_workspace_tests/subcrate/src/lib.rs b/clippy_workspace_tests/subcrate/src/lib.rs index fd694f68ca6..e69de29bb2d 100644 --- a/clippy_workspace_tests/subcrate/src/lib.rs +++ b/clippy_workspace_tests/subcrate/src/lib.rs @@ -1,10 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index b6405975862..0a96be71b35 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - #![feature(proc_macro_quote, proc_macro_hygiene)] extern crate proc_macro; diff --git a/pre_publish.sh b/pre_publish.sh index fc7ae212fcf..3602f671e3d 100755 --- a/pre_publish.sh +++ b/pre_publish.sh @@ -1,16 +1,5 @@ #!/bin/bash -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - - set -e ./util/update_lints.py diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md index b101f55e509..a88f47e4dbc 100644 --- a/rustc_tools_util/README.md +++ b/rustc_tools_util/README.md @@ -49,7 +49,7 @@ This gives the following output in clippy: ## License -Copyright 2014-2018 The Rust Project Developers +Copyright 2014-2019 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 49bfb7d8b59..f13fa12ccca 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::env; #[macro_export] diff --git a/src/driver.rs b/src/driver.rs index 269228988f7..2faa77785bb 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] diff --git a/src/lib.rs b/src/lib.rs index ef6f4cd7b3d..be0c10c8ff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern:cargo-clippy #![feature(plugin_registrar)] #![feature(rustc_private)] diff --git a/src/main.rs b/src/main.rs index 369528f1954..eefababb96d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern:yummy #![feature(box_syntax)] #![feature(rustc_private)] diff --git a/tests/auxiliary/test_macro.rs b/tests/auxiliary/test_macro.rs index d5fef588971..624ca892add 100644 --- a/tests/auxiliary/test_macro.rs +++ b/tests/auxiliary/test_macro.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - pub trait A {} macro_rules! __implicit_hasher_test_macro { diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 005c2ce33f9..c67b6f08c9f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(test)] use compiletest_rs as compiletest; diff --git a/tests/dogfood.rs b/tests/dogfood.rs index c1f02b9fcef..87fe5887bcc 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[test] fn dogfood() { if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { diff --git a/tests/matches.rs b/tests/matches.rs index 7d099665259..15a0ea503bf 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(rustc_private)] extern crate syntax; diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index e0dcd035c58..255653b4737 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs index df84009c889..2c5c90683cc 100644 --- a/tests/run-pass/associated-constant-ice.rs +++ b/tests/run-pass/associated-constant-ice.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - pub trait Trait { const CONSTANT: u8; } diff --git a/tests/run-pass/cc_seme.rs b/tests/run-pass/cc_seme.rs index 7e1f13d4460..169403df562 100644 --- a/tests/run-pass/cc_seme.rs +++ b/tests/run-pass/cc_seme.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(dead_code)] enum Baz { One, diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs index 6e64f174e4c..dca32aa3b56 100644 --- a/tests/run-pass/enum-glob-import-crate.rs +++ b/tests/run-pass/enum-glob-import-crate.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::all)] #![allow(unused_imports)] diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs index 87f2afaa602..6a5bf429f2d 100644 --- a/tests/run-pass/ice-1588.rs +++ b/tests/run-pass/ice-1588.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::all)] fn main() { diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs index ddb4367c914..81af88962a6 100644 --- a/tests/run-pass/ice-1782.rs +++ b/tests/run-pass/ice-1782.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs index 2a0cdb19fce..eab4f338f97 100644 --- a/tests/run-pass/ice-1969.rs +++ b/tests/run-pass/ice-1969.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::all)] fn main() {} diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs index 804f416800c..45b3b1869dd 100644 --- a/tests/run-pass/ice-2499.rs +++ b/tests/run-pass/ice-2499.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs index e91b71b3a1c..3f3986b6fc6 100644 --- a/tests/run-pass/ice-2594.rs +++ b/tests/run-pass/ice-2594.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/run-pass/ice-2727.rs b/tests/run-pass/ice-2727.rs index 9d00f2bacd0..79c6f1c55db 100644 --- a/tests/run-pass/ice-2727.rs +++ b/tests/run-pass/ice-2727.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - pub fn f(new: fn()) { new(); } diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs index 533cc3b952a..949e273997c 100644 --- a/tests/run-pass/ice-2760.rs +++ b/tests/run-pass/ice-2760.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( unused_variables, clippy::blacklisted_name, diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs index ae51f036207..2cc19ae32b8 100644 --- a/tests/run-pass/ice-2774.rs +++ b/tests/run-pass/ice-2774.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::HashSet; // See https://github.com/rust-lang/rust-clippy/issues/2774 diff --git a/tests/run-pass/ice-2865.rs b/tests/run-pass/ice-2865.rs index 970ac5bd3a8..64092afd53d 100644 --- a/tests/run-pass/ice-2865.rs +++ b/tests/run-pass/ice-2865.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(dead_code)] struct Ice { size: String, diff --git a/tests/run-pass/ice-3151.rs b/tests/run-pass/ice-3151.rs index 7a26f4c3925..a03dd05e7d3 100644 --- a/tests/run-pass/ice-3151.rs +++ b/tests/run-pass/ice-3151.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[derive(Clone)] pub struct HashMap { hash_builder: S, diff --git a/tests/run-pass/ice-3462.rs b/tests/run-pass/ice-3462.rs index 8aea905cd80..d4f6f355c85 100644 --- a/tests/run-pass/ice-3462.rs +++ b/tests/run-pass/ice-3462.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(clippy::blacklisted_name)] #![allow(unused)] diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs index b839ac2a214..10546850611 100644 --- a/tests/run-pass/ice-700.rs +++ b/tests/run-pass/ice-700.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::all)] fn core() {} diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs index b2b331bd342..ac643fafabc 100644 --- a/tests/run-pass/ice_exacte_size.rs +++ b/tests/run-pass/ice_exacte_size.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::all)] #[allow(dead_code)] diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs index 0241d2adcf7..e6ab7cc9d8c 100644 --- a/tests/run-pass/if_same_then_else.rs +++ b/tests/run-pass/if_same_then_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::if_same_then_else)] fn main() {} diff --git a/tests/run-pass/issue-2862.rs b/tests/run-pass/issue-2862.rs index a5342492045..b35df667f27 100644 --- a/tests/run-pass/issue-2862.rs +++ b/tests/run-pass/issue-2862.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - pub trait FooMap { fn map B>(&self, f: F) -> B; } diff --git a/tests/run-pass/issue-825.rs b/tests/run-pass/issue-825.rs index 9f1195a4ac0..b1339212e6e 100644 --- a/tests/run-pass/issue-825.rs +++ b/tests/run-pass/issue-825.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(warnings)] // this should compile in a reasonable amount of time diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs index a81f8f55dc8..bb238c81ebc 100644 --- a/tests/run-pass/issues_loop_mut_cond.rs +++ b/tests/run-pass/issues_loop_mut_cond.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] /// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs index 661f2ac1dc7..50732475562 100644 --- a/tests/run-pass/match_same_arms_const.rs +++ b/tests/run-pass/match_same_arms_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::match_same_arms)] const PRICE_OF_SWEETS: u32 = 5; diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs index f1a2cad3ae7..af11c29d9b0 100644 --- a/tests/run-pass/mut_mut_macro.rs +++ b/tests/run-pass/mut_mut_macro.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] #![allow(dead_code)] diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs index 81b77855711..4f61c76828d 100644 --- a/tests/run-pass/needless_borrow_fp.rs +++ b/tests/run-pass/needless_borrow_fp.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[deny(clippy::all)] #[derive(Debug)] pub enum Error { diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs index 9648f530c2a..676564b2445 100644 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ b/tests/run-pass/needless_lifetimes_impl_trait.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs index 9ac47599ea0..c7468493380 100644 --- a/tests/run-pass/procedural_macro.rs +++ b/tests/run-pass/procedural_macro.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[macro_use] extern crate clippy_mini_macro_test; diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs index b109eecf624..84470addd4a 100644 --- a/tests/run-pass/regressions.rs +++ b/tests/run-pass/regressions.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::blacklisted_name)] pub fn foo(bar: *const u8) { diff --git a/tests/run-pass/returns.rs b/tests/run-pass/returns.rs index 045cf001eb2..d6b2a4ef170 100644 --- a/tests/run-pass/returns.rs +++ b/tests/run-pass/returns.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[deny(warnings)] fn cfg_return() -> i32 { #[cfg(unix)] diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs index 80fc88f30df..efcc6363eb0 100644 --- a/tests/run-pass/single-match-else.rs +++ b/tests/run-pass/single-match-else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::single_match_else)] fn main() { diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs index 8b6c6557b49..3030786aea6 100644 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ b/tests/run-pass/used_underscore_binding_macro.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::useless_attribute)] //issue #2910 #[macro_use] diff --git a/tests/run-pass/whitelist/conf_whitelisted.rs b/tests/run-pass/whitelist/conf_whitelisted.rs index e7f5ddb561f..f328e4d9d04 100644 --- a/tests/run-pass/whitelist/conf_whitelisted.rs +++ b/tests/run-pass/whitelist/conf_whitelisted.rs @@ -1,10 +1 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs index 31781277ae8..3b9458fc284 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.rs +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern: error reading Clippy's configuration file fn main() {} diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs index 2307bfff21c..8a0062423ad 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.rs +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern: error reading Clippy's configuration file: `blacklisted-names` is expected to be a // `Vec < String >` but is a `integer` diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs index b00a21b3f2f..cb35d0e8589 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] #![allow(clippy::single_match)] #![allow(unused_variables)] diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr index 9f35b1751ac..84ba77851f7 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr @@ -1,5 +1,5 @@ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:15:9 + --> $DIR/conf_french_blacklisted_name.rs:6:9 | LL | fn test(toto: ()) {} | ^^^^ @@ -7,37 +7,37 @@ LL | fn test(toto: ()) {} = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:18:9 + --> $DIR/conf_french_blacklisted_name.rs:9:9 | LL | let toto = 42; | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:19:9 + --> $DIR/conf_french_blacklisted_name.rs:10:9 | LL | let tata = 42; | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:20:9 + --> $DIR/conf_french_blacklisted_name.rs:11:9 | LL | let titi = 42; | ^^^^ error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:26:10 + --> $DIR/conf_french_blacklisted_name.rs:17:10 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:26:21 + --> $DIR/conf_french_blacklisted_name.rs:17:21 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:26:28 + --> $DIR/conf_french_blacklisted_name.rs:17:28 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 39de0de0dc7..f24fe51d30f 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::many_single_char_names)] #[derive(Copy, Clone)] diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index 49cbc0691bc..746b9ffa4af 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,5 +1,5 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:20:11 + --> $DIR/test.rs:11:11 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` @@ -7,7 +7,7 @@ LL | fn bad(x: &u16, y: &Foo) {} = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/test.rs:20:20 + --> $DIR/test.rs:11:20 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `Foo` diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index c8e6268e95d..a47569f62a3 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern: error reading Clippy's configuration file: unknown key `foobar` fn main() {} diff --git a/tests/ui-toml/update-all-references.sh b/tests/ui-toml/update-all-references.sh index acc38f15fbd..71404b68c45 100755 --- a/tests/ui-toml/update-all-references.sh +++ b/tests/ui-toml/update-all-references.sh @@ -1,15 +1,5 @@ #!/bin/bash # -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - # A script to update the references for all tests. The idea is that # you do a run, which will generate files in the build directory # containing the (normalized) actual output of the compiler. You then diff --git a/tests/ui-toml/update-references.sh b/tests/ui-toml/update-references.sh index aa99d35f7aa..2c4fef43d96 100755 --- a/tests/ui-toml/update-references.sh +++ b/tests/ui-toml/update-references.sh @@ -1,14 +1,4 @@ #!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. # A script to update the references for particular tests. The idea is # that you do a run, which will generate files in the build directory diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index 666c4325706..ae0727fe2ba 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::absurd_extreme_comparisons)] #![allow( unused, diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 5c8d537b21c..b18a943c557 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -1,5 +1,5 @@ error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:23:5 + --> $DIR/absurd-extreme-comparisons.rs:14:5 | LL | u <= 0; | ^^^^^^ @@ -8,7 +8,7 @@ LL | u <= 0; = help: because 0 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:24:5 + --> $DIR/absurd-extreme-comparisons.rs:15:5 | LL | u <= Z; | ^^^^^^ @@ -16,7 +16,7 @@ LL | u <= Z; = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == Z instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:25:5 + --> $DIR/absurd-extreme-comparisons.rs:16:5 | LL | u < Z; | ^^^^^ @@ -24,7 +24,7 @@ LL | u < Z; = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:26:5 + --> $DIR/absurd-extreme-comparisons.rs:17:5 | LL | Z >= u; | ^^^^^^ @@ -32,7 +32,7 @@ LL | Z >= u; = help: because Z is the minimum value for this type, the case where the two sides are not equal never occurs, consider using Z == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:27:5 + --> $DIR/absurd-extreme-comparisons.rs:18:5 | LL | Z > u; | ^^^^^ @@ -40,7 +40,7 @@ LL | Z > u; = help: because Z is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:28:5 + --> $DIR/absurd-extreme-comparisons.rs:19:5 | LL | u > std::u32::MAX; | ^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | u > std::u32::MAX; = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:29:5 + --> $DIR/absurd-extreme-comparisons.rs:20:5 | LL | u >= std::u32::MAX; | ^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | u >= std::u32::MAX; = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == std::u32::MAX instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:30:5 + --> $DIR/absurd-extreme-comparisons.rs:21:5 | LL | std::u32::MAX < u; | ^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | std::u32::MAX < u; = help: because std::u32::MAX is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:31:5 + --> $DIR/absurd-extreme-comparisons.rs:22:5 | LL | std::u32::MAX <= u; | ^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | std::u32::MAX <= u; = help: because std::u32::MAX is the maximum value for this type, the case where the two sides are not equal never occurs, consider using std::u32::MAX == u instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:32:5 + --> $DIR/absurd-extreme-comparisons.rs:23:5 | LL | 1-1 > u; | ^^^^^^^ @@ -80,7 +80,7 @@ LL | 1-1 > u; = help: because 1-1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:33:5 + --> $DIR/absurd-extreme-comparisons.rs:24:5 | LL | u >= !0; | ^^^^^^^ @@ -88,7 +88,7 @@ LL | u >= !0; = help: because !0 is the maximum value for this type, the case where the two sides are not equal never occurs, consider using u == !0 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:34:5 + --> $DIR/absurd-extreme-comparisons.rs:25:5 | LL | u <= 12 - 2*6; | ^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | u <= 12 - 2*6; = help: because 12 - 2*6 is the minimum value for this type, the case where the two sides are not equal never occurs, consider using u == 12 - 2*6 instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:36:5 + --> $DIR/absurd-extreme-comparisons.rs:27:5 | LL | i < -127 - 1; | ^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | i < -127 - 1; = help: because -127 - 1 is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:37:5 + --> $DIR/absurd-extreme-comparisons.rs:28:5 | LL | std::i8::MAX >= i; | ^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | std::i8::MAX >= i; = help: because std::i8::MAX is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:38:5 + --> $DIR/absurd-extreme-comparisons.rs:29:5 | LL | 3-7 < std::i32::MIN; | ^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | 3-7 < std::i32::MIN; = help: because std::i32::MIN is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:40:5 + --> $DIR/absurd-extreme-comparisons.rs:31:5 | LL | b >= true; | ^^^^^^^^^ @@ -128,7 +128,7 @@ LL | b >= true; = help: because true is the maximum value for this type, the case where the two sides are not equal never occurs, consider using b == true instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> $DIR/absurd-extreme-comparisons.rs:41:5 + --> $DIR/absurd-extreme-comparisons.rs:32:5 | LL | false > b; | ^^^^^^^^^ @@ -136,7 +136,7 @@ LL | false > b; = help: because false is the minimum value for this type, this comparison is always false error: <-comparison of unit values detected. This will always be false - --> $DIR/absurd-extreme-comparisons.rs:44:5 + --> $DIR/absurd-extreme-comparisons.rs:35:5 | LL | () < {}; | ^^^^^^^ diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 8eefb6af01d..8c295d1438a 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::approx_constant)] #[allow(unused, clippy::shadow_unrelated, clippy::similar_names, clippy::unreadable_literal)] fn main() { diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index c29ea3d467a..71c1c360e74 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -1,5 +1,5 @@ error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:13:16 + --> $DIR/approx_const.rs:4:16 | LL | let my_e = 2.7182; | ^^^^^^ @@ -7,109 +7,109 @@ LL | let my_e = 2.7182; = note: `-D clippy::approx-constant` implied by `-D warnings` error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly - --> $DIR/approx_const.rs:14:20 + --> $DIR/approx_const.rs:5:20 | LL | let almost_e = 2.718; | ^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly - --> $DIR/approx_const.rs:17:24 + --> $DIR/approx_const.rs:8:24 | LL | let my_1_frac_pi = 0.3183; | ^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:20:28 + --> $DIR/approx_const.rs:11:28 | LL | let my_frac_1_sqrt_2 = 0.70710678; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:21:32 + --> $DIR/approx_const.rs:12:32 | LL | let almost_frac_1_sqrt_2 = 0.70711; | ^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly - --> $DIR/approx_const.rs:24:24 + --> $DIR/approx_const.rs:15:24 | LL | let my_frac_2_pi = 0.63661977; | ^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly - --> $DIR/approx_const.rs:27:27 + --> $DIR/approx_const.rs:18:27 | LL | let my_frac_2_sq_pi = 1.128379; | ^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly - --> $DIR/approx_const.rs:30:24 + --> $DIR/approx_const.rs:21:24 | LL | let my_frac_pi_2 = 1.57079632679; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly - --> $DIR/approx_const.rs:33:24 + --> $DIR/approx_const.rs:24:24 | LL | let my_frac_pi_3 = 1.04719755119; | ^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly - --> $DIR/approx_const.rs:36:24 + --> $DIR/approx_const.rs:27:24 | LL | let my_frac_pi_4 = 0.785398163397; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly - --> $DIR/approx_const.rs:39:24 + --> $DIR/approx_const.rs:30:24 | LL | let my_frac_pi_6 = 0.523598775598; | ^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly - --> $DIR/approx_const.rs:42:24 + --> $DIR/approx_const.rs:33:24 | LL | let my_frac_pi_8 = 0.3926990816987; | ^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly - --> $DIR/approx_const.rs:45:20 + --> $DIR/approx_const.rs:36:20 | LL | let my_ln_10 = 2.302585092994046; | ^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly - --> $DIR/approx_const.rs:48:19 + --> $DIR/approx_const.rs:39:19 | LL | let my_ln_2 = 0.6931471805599453; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly - --> $DIR/approx_const.rs:51:22 + --> $DIR/approx_const.rs:42:22 | LL | let my_log10_e = 0.4342944819032518; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly - --> $DIR/approx_const.rs:54:21 + --> $DIR/approx_const.rs:45:21 | LL | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:57:17 + --> $DIR/approx_const.rs:48:17 | LL | let my_pi = 3.1415; | ^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:58:21 + --> $DIR/approx_const.rs:49:21 | LL | let almost_pi = 3.14; | ^^^^ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:61:18 + --> $DIR/approx_const.rs:52:18 | LL | let my_sq2 = 1.4142; | ^^^^^^ diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 00de38039a7..874604889b9 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] #![allow( unused, diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index cea9676c2b8..c9bb68f857c 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,5 +1,5 @@ error: integer arithmetic detected - --> $DIR/arithmetic.rs:22:5 + --> $DIR/arithmetic.rs:13:5 | LL | 1 + i; | ^^^^^ @@ -7,32 +7,32 @@ LL | 1 + i; = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/arithmetic.rs:23:5 + --> $DIR/arithmetic.rs:14:5 | LL | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:24:5 + --> $DIR/arithmetic.rs:15:5 | LL | / 1 % LL | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:26:5 + --> $DIR/arithmetic.rs:17:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:27:5 + --> $DIR/arithmetic.rs:18:5 | LL | -i; | ^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:37:5 + --> $DIR/arithmetic.rs:28:5 | LL | f * 2.0; | ^^^^^^^ @@ -40,31 +40,31 @@ LL | f * 2.0; = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:39:5 + --> $DIR/arithmetic.rs:30:5 | LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:40:5 + --> $DIR/arithmetic.rs:31:5 | LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:41:5 + --> $DIR/arithmetic.rs:32:5 | LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:42:5 + --> $DIR/arithmetic.rs:33:5 | LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:43:5 + --> $DIR/arithmetic.rs:34:5 | LL | -f; | ^^ diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 75cd7543823..c7b4865f5c2 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(dead_code, unused_assignments)] #[warn(clippy::assign_op_pattern)] fn main() { diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 194033981e1..646f9970122 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,5 +1,5 @@ error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:14:5 + --> $DIR/assign_ops.rs:5:5 | LL | a = a + 1; | ^^^^^^^^^ help: replace it with: `a += 1` @@ -7,49 +7,49 @@ LL | a = a + 1; = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:15:5 + --> $DIR/assign_ops.rs:6:5 | LL | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:16:5 + --> $DIR/assign_ops.rs:7:5 | LL | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:17:5 + --> $DIR/assign_ops.rs:8:5 | LL | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:18:5 + --> $DIR/assign_ops.rs:9:5 | LL | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:19:5 + --> $DIR/assign_ops.rs:10:5 | LL | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:20:5 + --> $DIR/assign_ops.rs:11:5 | LL | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:21:5 + --> $DIR/assign_ops.rs:12:5 | LL | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> $DIR/assign_ops.rs:27:5 + --> $DIR/assign_ops.rs:18:5 | LL | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index 24d0d77a20d..4703a8c7777 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(unused_assignments)] #[warn(clippy::misrefactored_assign_op, clippy::assign_op_pattern)] fn main() { diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 99983c0d054..872d6e0d734 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -1,5 +1,5 @@ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:14:5 + --> $DIR/assign_ops2.rs:5:5 | LL | a += a + 1; | ^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | a = a + a + 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:15:5 + --> $DIR/assign_ops2.rs:6:5 | LL | a += 1 + a; | ^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | a = a + 1 + a; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:16:5 + --> $DIR/assign_ops2.rs:7:5 | LL | a -= a - 1; | ^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | a = a - (a - 1); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:17:5 + --> $DIR/assign_ops2.rs:8:5 | LL | a *= a * 99; | ^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | a = a * a * 99; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:18:5 + --> $DIR/assign_ops2.rs:9:5 | LL | a *= 42 * a; | ^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | a = a * 42 * a; | ^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:19:5 + --> $DIR/assign_ops2.rs:10:5 | LL | a /= a / 2; | ^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | a = a / (a / 2); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:20:5 + --> $DIR/assign_ops2.rs:11:5 | LL | a %= a % 5; | ^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | a = a % (a % 5); | ^^^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:21:5 + --> $DIR/assign_ops2.rs:12:5 | LL | a &= a & 1; | ^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | a = a & a & 1; | ^^^^^^^^^^^^^ error: variable appears on both sides of an assignment operation - --> $DIR/assign_ops2.rs:22:5 + --> $DIR/assign_ops2.rs:13:5 | LL | a *= a * a; | ^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | a = a * a * a; | ^^^^^^^^^^^^^ error: manual implementation of an assign operation - --> $DIR/assign_ops2.rs:59:5 + --> $DIR/assign_ops2.rs:50:5 | LL | buf = buf + cows.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 413c30a1945..4dbb5c67f5d 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::inline_always, clippy::deprecated_semver)] #[inline(always)] diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index bc40cb8c86d..39ddf6f226d 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,5 +1,5 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> $DIR/attrs.rs:12:1 + --> $DIR/attrs.rs:3:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[inline(always)] = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:32:14 + --> $DIR/attrs.rs:23:14 | LL | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[deprecated(since = "forever")] = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:35:14 + --> $DIR/attrs.rs:26:14 | LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ diff --git a/tests/ui/author.rs b/tests/ui/author.rs index 4b7729e23b1..0a1be356896 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { #[clippy::author] let x: char = 0x45 as char; diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs index 40cc0d7a919..e99c3c41dc4 100644 --- a/tests/ui/author/call.rs +++ b/tests/ui/author/call.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { #[clippy::author] let _ = ::std::cmp::min(3, 4); diff --git a/tests/ui/author/for_loop.rs b/tests/ui/author/for_loop.rs index 4acd0b452bb..b3dec876535 100644 --- a/tests/ui/author/for_loop.rs +++ b/tests/ui/author/for_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(stmt_expr_attributes)] fn main() { diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs index 4c220dded8a..e6bf229103f 100644 --- a/tests/ui/author/matches.rs +++ b/tests/ui/author/matches.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(tool_attributes)] fn main() { diff --git a/tests/ui/author/matches.stderr b/tests/ui/author/matches.stderr index 5fb2a01f1b2..fa7e5cce43c 100644 --- a/tests/ui/author/matches.stderr +++ b/tests/ui/author/matches.stderr @@ -1,12 +1,12 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/matches.rs:18:13 + --> $DIR/matches.rs:9:13 | LL | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/matches.rs:17:21 + --> $DIR/matches.rs:8:21 | LL | let x = 3; | ^ diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index bda952db723..cfb493fb52a 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - const THREE_BITS: i64 = 7; const EVEN_MORE_REDIRECTION: i64 = THREE_BITS; diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index da883dcbfc4..159db0374d2 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -1,5 +1,5 @@ error: &-masking with zero - --> $DIR/bit_masks.rs:23:5 + --> $DIR/bit_masks.rs:14:5 | LL | x & 0 == 0; | ^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | x & 0 == 0; = note: `-D clippy::bad-bit-mask` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:23:5 + --> $DIR/bit_masks.rs:14:5 | LL | x & 0 == 0; | ^^^^^ @@ -15,73 +15,73 @@ LL | x & 0 == 0; = note: #[deny(clippy::erasing_op)] on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:26:5 + --> $DIR/bit_masks.rs:17:5 | LL | x & 2 == 1; | ^^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:30:5 + --> $DIR/bit_masks.rs:21:5 | LL | x | 3 == 2; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 1` will never be higher than `1` - --> $DIR/bit_masks.rs:32:5 + --> $DIR/bit_masks.rs:23:5 | LL | x & 1 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:36:5 + --> $DIR/bit_masks.rs:27:5 | LL | x | 2 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ & 7` can never be equal to `8` - --> $DIR/bit_masks.rs:43:5 + --> $DIR/bit_masks.rs:34:5 | LL | x & THREE_BITS == 8; | ^^^^^^^^^^^^^^^^^^^ error: incompatible bit mask: `_ | 7` will never be lower than `7` - --> $DIR/bit_masks.rs:44:5 + --> $DIR/bit_masks.rs:35:5 | LL | x | EVEN_MORE_REDIRECTION < 7; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &-masking with zero - --> $DIR/bit_masks.rs:46:5 + --> $DIR/bit_masks.rs:37:5 | LL | 0 & x == 0; | ^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/bit_masks.rs:46:5 + --> $DIR/bit_masks.rs:37:5 | LL | 0 & x == 0; | ^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> $DIR/bit_masks.rs:50:5 + --> $DIR/bit_masks.rs:41:5 | LL | 1 < 2 | x; | ^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> $DIR/bit_masks.rs:51:5 + --> $DIR/bit_masks.rs:42:5 | LL | 2 == 3 | x; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> $DIR/bit_masks.rs:52:5 + --> $DIR/bit_masks.rs:43:5 | LL | 1 == x & 2; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:63:5 + --> $DIR/bit_masks.rs:54:5 | LL | x | 1 > 3; | ^^^^^^^^^ @@ -89,19 +89,19 @@ LL | x | 1 > 3; = note: `-D clippy::ineffective-bit-mask` implied by `-D warnings` error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly - --> $DIR/bit_masks.rs:64:5 + --> $DIR/bit_masks.rs:55:5 | LL | x | 1 < 4; | ^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> $DIR/bit_masks.rs:65:5 + --> $DIR/bit_masks.rs:56:5 | LL | x | 1 <= 3; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared directly - --> $DIR/bit_masks.rs:66:5 + --> $DIR/bit_masks.rs:57:5 | LL | x | 1 >= 8; | ^^^^^^^^^^ diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index fef73e9d84f..ca9d8d16b78 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( dead_code, clippy::similar_names, diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 5b65d4ed13f..44123829fb0 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -1,5 +1,5 @@ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:20:9 + --> $DIR/blacklisted_name.rs:11:9 | LL | fn test(foo: ()) {} | ^^^ @@ -7,79 +7,79 @@ LL | fn test(foo: ()) {} = note: `-D clippy::blacklisted-name` implied by `-D warnings` error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:23:9 + --> $DIR/blacklisted_name.rs:14:9 | LL | let foo = 42; | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:24:9 + --> $DIR/blacklisted_name.rs:15:9 | LL | let bar = 42; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:25:9 + --> $DIR/blacklisted_name.rs:16:9 | LL | let baz = 42; | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:31:10 + --> $DIR/blacklisted_name.rs:22:10 | LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:31:20 + --> $DIR/blacklisted_name.rs:22:20 | LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:31:26 + --> $DIR/blacklisted_name.rs:22:26 | LL | (foo, Some(bar), baz @ Some(_)) => (), | ^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:36:19 + --> $DIR/blacklisted_name.rs:27:19 | LL | fn issue_1647(mut foo: u8) { | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:37:13 + --> $DIR/blacklisted_name.rs:28:13 | LL | let mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:38:21 + --> $DIR/blacklisted_name.rs:29:21 | LL | if let Some(mut baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:42:13 + --> $DIR/blacklisted_name.rs:33:13 | LL | let ref bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:43:21 + --> $DIR/blacklisted_name.rs:34:21 | LL | if let Some(ref baz) = Some(42) {} | ^^^ error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:47:17 + --> $DIR/blacklisted_name.rs:38:17 | LL | let ref mut bar = 0; | ^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:48:25 + --> $DIR/blacklisted_name.rs:39:25 | LL | if let Some(ref mut baz) = Some(42) {} | ^^^ diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index eaaf5e050bf..17ee1cd6873 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![allow(unused, clippy::let_and_return)] diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index 522c7dc779e..34c0454b782 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,5 +1,5 @@ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:35:8 + --> $DIR/block_in_if_condition.rs:26:8 | LL | if { | ________^ @@ -19,7 +19,7 @@ LL | | } { } ... error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:46:8 + --> $DIR/block_in_if_condition.rs:37:8 | LL | if { true } { | ^^^^^^^^ @@ -31,7 +31,7 @@ LL | if { true } { } ... error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:66:17 + --> $DIR/block_in_if_condition.rs:57:17 | LL | |x| { | _________________^ @@ -41,7 +41,7 @@ LL | | }, | |_____________^ error: in an 'if' condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a 'let' - --> $DIR/block_in_if_condition.rs:75:13 + --> $DIR/block_in_if_condition.rs:66:13 | LL | |x| { | _____________^ @@ -51,7 +51,7 @@ LL | | }, | |_________^ error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:85:8 + --> $DIR/block_in_if_condition.rs:76:8 | LL | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 2a28d0af1b2..48c5e9d6d0c 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::bool_comparison)] fn main() { let x = true; diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 7bd48f2e3dc..2d473d91d66 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,5 +1,5 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:13:8 + --> $DIR/bool_comparison.rs:4:8 | LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -7,79 +7,79 @@ LL | if x == true { = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:18:8 + --> $DIR/bool_comparison.rs:9:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:23:8 + --> $DIR/bool_comparison.rs:14:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:28:8 + --> $DIR/bool_comparison.rs:19:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:33:8 + --> $DIR/bool_comparison.rs:24:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:38:8 + --> $DIR/bool_comparison.rs:29:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:43:8 + --> $DIR/bool_comparison.rs:34:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:48:8 + --> $DIR/bool_comparison.rs:39:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:53:8 + --> $DIR/bool_comparison.rs:44:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:58:8 + --> $DIR/bool_comparison.rs:49:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:63:8 + --> $DIR/bool_comparison.rs:54:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:68:8 + --> $DIR/bool_comparison.rs:59:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:74:8 + --> $DIR/bool_comparison.rs:65:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:79:8 + --> $DIR/bool_comparison.rs:70:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` diff --git a/tests/ui/booleans.rs b/tests/ui/booleans.rs index 8eb1b52577c..c8e01d4b258 100644 --- a/tests/ui/booleans.rs +++ b/tests/ui/booleans.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::nonminimal_bool, clippy::logic_bug)] #[allow(unused, clippy::many_single_char_names)] diff --git a/tests/ui/booleans.stderr b/tests/ui/booleans.stderr index c9446f5e4bc..eebab8c3e25 100644 --- a/tests/ui/booleans.stderr +++ b/tests/ui/booleans.stderr @@ -1,18 +1,18 @@ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:19:13 + --> $DIR/booleans.rs:10:13 | LL | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:19:18 + --> $DIR/booleans.rs:10:18 | LL | let _ = a && b || a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:21:13 + --> $DIR/booleans.rs:12:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -20,55 +20,55 @@ LL | let _ = !true; = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/booleans.rs:22:13 + --> $DIR/booleans.rs:13:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/booleans.rs:23:13 + --> $DIR/booleans.rs:14:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:24:13 + --> $DIR/booleans.rs:15:13 | LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:24:22 + --> $DIR/booleans.rs:15:22 | LL | let _ = false && a; | ^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:25:13 + --> $DIR/booleans.rs:16:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/booleans.rs:30:13 + --> $DIR/booleans.rs:21:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `!b || a` error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:40:13 + --> $DIR/booleans.rs:31:13 | LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:40:13 + --> $DIR/booleans.rs:31:13 | LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:41:13 + --> $DIR/booleans.rs:32:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:42:13 + --> $DIR/booleans.rs:33:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,31 +92,31 @@ LL | let _ = !(c != 5 || a != b); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:43:13 + --> $DIR/booleans.rs:34:13 | LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:43:13 + --> $DIR/booleans.rs:34:13 | LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> $DIR/booleans.rs:44:13 + --> $DIR/booleans.rs:35:13 | LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/booleans.rs:44:13 + --> $DIR/booleans.rs:35:13 | LL | let _ = a > b && a <= b; | ^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:46:13 + --> $DIR/booleans.rs:37:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,73 +128,73 @@ LL | let _ = !(a == b && c == d); | ^^^^^^^^^^^^^^^^^^^ error: this boolean expression can be simplified - --> $DIR/booleans.rs:54:13 + --> $DIR/booleans.rs:45:13 | LL | let _ = !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:56:13 + --> $DIR/booleans.rs:47:13 | LL | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:58:13 + --> $DIR/booleans.rs:49:13 | LL | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:60:13 + --> $DIR/booleans.rs:51:13 | LL | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:62:13 + --> $DIR/booleans.rs:53:13 | LL | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:63:13 + --> $DIR/booleans.rs:54:13 | LL | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:64:13 + --> $DIR/booleans.rs:55:13 | LL | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:65:13 + --> $DIR/booleans.rs:56:13 | LL | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:137:8 + --> $DIR/booleans.rs:128:8 | LL | if !res.is_ok() {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:138:8 + --> $DIR/booleans.rs:129:8 | LL | if !res.is_err() {} | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:141:8 + --> $DIR/booleans.rs:132:8 | LL | if !res.is_some() {} | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> $DIR/booleans.rs:142:8 + --> $DIR/booleans.rs:133:8 | LL | if !res.is_none() {} | ^^^^^^^^^^^^^^ help: try: `res.is_some()` diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index cf204150f8b..3b53aab7e23 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::borrowed_box)] #![allow(clippy::blacklisted_name)] #![allow(unused_variables)] diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 33bd50286a5..0cb455433c4 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -1,29 +1,29 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:15:19 + --> $DIR/borrow_box.rs:6:19 | LL | pub fn test1(foo: &mut Box) { | ^^^^^^^^^^^^^^ help: try: `&mut bool` | note: lint level defined here - --> $DIR/borrow_box.rs:10:9 + --> $DIR/borrow_box.rs:1:9 | LL | #![deny(clippy::borrowed_box)] | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:20:14 + --> $DIR/borrow_box.rs:11:14 | LL | let foo: &Box; | ^^^^^^^^^^ help: try: `&bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:24:10 + --> $DIR/borrow_box.rs:15:10 | LL | foo: &'a Box, | ^^^^^^^^^^^^^ help: try: `&'a bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:28:17 + --> $DIR/borrow_box.rs:19:17 | LL | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs index 48523054097..af3ba5b4d35 100644 --- a/tests/ui/box_vec.rs +++ b/tests/ui/box_vec.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] #![allow(clippy::blacklisted_name)] diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr index 8b5fc24a371..fca12eddd57 100644 --- a/tests/ui/box_vec.stderr +++ b/tests/ui/box_vec.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `Box>`. Consider using just `Vec` - --> $DIR/box_vec.rs:23:18 + --> $DIR/box_vec.rs:14:18 | LL | pub fn test(foo: Box>) { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin-type-shadow.rs index e9df0992c5e..69b8b6a0e68 100644 --- a/tests/ui/builtin-type-shadow.rs +++ b/tests/ui/builtin-type-shadow.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::builtin_type_shadow)] #![allow(non_camel_case_types)] diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 940a6dc2bcc..5714f2094da 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,5 +1,5 @@ error: This generic shadows the built-in type `u32` - --> $DIR/builtin-type-shadow.rs:13:8 + --> $DIR/builtin-type-shadow.rs:4:8 | LL | fn foo(a: u32) -> u32 { | ^^^ @@ -7,7 +7,7 @@ LL | fn foo(a: u32) -> u32 { = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types - --> $DIR/builtin-type-shadow.rs:14:5 + --> $DIR/builtin-type-shadow.rs:5:5 | LL | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index 6bc9b5ddecd..c724ee21be3 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[deny(clippy::naive_bytecount)] fn main() { let x = vec![0_u8; 16]; diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index a2890fe5a6d..43bc4b3c61e 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,23 +1,23 @@ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:14:13 + --> $DIR/bytecount.rs:5:13 | LL | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` | note: lint level defined here - --> $DIR/bytecount.rs:10:8 + --> $DIR/bytecount.rs:1:8 | LL | #[deny(clippy::naive_bytecount)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:16:13 + --> $DIR/bytecount.rs:7:13 | LL | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` error: You appear to be counting bytes the naive way - --> $DIR/bytecount.rs:28:13 + --> $DIR/bytecount.rs:19:13 | LL | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 51e41b70172..5f4de9894c7 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 78631ffa8c8..92587312a53 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:11:5 | LL | 1i32 as f32; | ^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | 1i32 as f32; = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:21:5 + --> $DIR/cast.rs:12:5 | LL | 1i64 as f32; | ^^^^^^^^^^^ error: casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:22:5 + --> $DIR/cast.rs:13:5 | LL | 1i64 as f64; | ^^^^^^^^^^^ error: casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:14:5 | LL | 1u32 as f32; | ^^^^^^^^^^^ error: casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:24:5 + --> $DIR/cast.rs:15:5 | LL | 1u64 as f32; | ^^^^^^^^^^^ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:16:5 | LL | 1u64 as f64; | ^^^^^^^^^^^ error: casting f32 to i32 may truncate the value - --> $DIR/cast.rs:27:5 + --> $DIR/cast.rs:18:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -45,13 +45,13 @@ LL | 1f32 as i32; = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:19:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:19:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -59,49 +59,49 @@ LL | 1f32 as u32; = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value - --> $DIR/cast.rs:29:5 + --> $DIR/cast.rs:20:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value - --> $DIR/cast.rs:30:5 + --> $DIR/cast.rs:21:5 | LL | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may lose the sign of the value - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:22:5 | LL | 1i32 as u8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:22:5 | LL | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value - --> $DIR/cast.rs:32:5 + --> $DIR/cast.rs:23:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:24:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:24:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:26:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -109,31 +109,31 @@ LL | 1u8 as i8; = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value - --> $DIR/cast.rs:36:5 + --> $DIR/cast.rs:27:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:28:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value - --> $DIR/cast.rs:38:5 + --> $DIR/cast.rs:29:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value - --> $DIR/cast.rs:39:5 + --> $DIR/cast.rs:30:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting f32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:32:5 | LL | 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` @@ -141,25 +141,25 @@ LL | 1.0f32 as f64; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:34:5 | LL | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:45:5 + --> $DIR/cast.rs:36:5 | LL | 1i32 as u32; | ^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:46:5 + --> $DIR/cast.rs:37:5 | LL | 1isize as usize; | ^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:49:5 + --> $DIR/cast.rs:40:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ @@ -167,13 +167,13 @@ LL | 1i32 as i32; = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:50:5 + --> $DIR/cast.rs:41:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:51:5 + --> $DIR/cast.rs:42:5 | LL | false as bool; | ^^^^^^^^^^^^^ diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index dba19dfd023..2814fe6c03d 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Test casts for alignment issues #![feature(rustc_private)] diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 261bce613bf..0077be1b570 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,5 +1,5 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - --> $DIR/cast_alignment.rs:21:5 + --> $DIR/cast_alignment.rs:12:5 | LL | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | (&1u8 as *const u8) as *const u16; = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) - --> $DIR/cast_alignment.rs:22:5 + --> $DIR/cast_alignment.rs:13:5 | LL | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index 5f4e54eb565..22df1137922 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index b818010feb2..c86b4d05f28 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index aa48bd4d1c7..c2b01e83bbe 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,5 +1,5 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:16:5 + --> $DIR/cast_lossless_float.rs:7:5 | LL | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` @@ -7,55 +7,55 @@ LL | 1i8 as f32; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:17:5 + --> $DIR/cast_lossless_float.rs:8:5 | LL | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:18:5 + --> $DIR/cast_lossless_float.rs:9:5 | LL | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:19:5 + --> $DIR/cast_lossless_float.rs:10:5 | LL | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:20:5 + --> $DIR/cast_lossless_float.rs:11:5 | LL | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:21:5 + --> $DIR/cast_lossless_float.rs:12:5 | LL | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:22:5 + --> $DIR/cast_lossless_float.rs:13:5 | LL | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:23:5 + --> $DIR/cast_lossless_float.rs:14:5 | LL | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:24:5 + --> $DIR/cast_lossless_float.rs:15:5 | LL | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:25:5 + --> $DIR/cast_lossless_float.rs:16:5 | LL | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index 83f3e024209..e5b33d5e1b0 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 75c63957001..61170625c8a 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index f49dc0d9eff..ac385298ecb 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,5 +1,5 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:7:5 | LL | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` @@ -7,103 +7,103 @@ LL | 1i8 as i16; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:8:5 | LL | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:9:5 | LL | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:10:5 | LL | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:11:5 | LL | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:12:5 | LL | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:13:5 | LL | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:14:5 | LL | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:24:5 + --> $DIR/cast_lossless_integer.rs:15:5 | LL | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:25:5 + --> $DIR/cast_lossless_integer.rs:16:5 | LL | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:26:5 + --> $DIR/cast_lossless_integer.rs:17:5 | LL | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:27:5 + --> $DIR/cast_lossless_integer.rs:18:5 | LL | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:28:5 + --> $DIR/cast_lossless_integer.rs:19:5 | LL | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:29:5 + --> $DIR/cast_lossless_integer.rs:20:5 | LL | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:30:5 + --> $DIR/cast_lossless_integer.rs:21:5 | LL | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:31:5 + --> $DIR/cast_lossless_integer.rs:22:5 | LL | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:32:5 + --> $DIR/cast_lossless_integer.rs:23:5 | LL | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:33:5 + --> $DIR/cast_lossless_integer.rs:24:5 | LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index 8f691104c51..fde178b1874 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index eab1014128a..9346deb19ec 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,5 +1,5 @@ error: casting isize to i8 may truncate the value - --> $DIR/cast_size.rs:20:5 + --> $DIR/cast_size.rs:11:5 | LL | 1isize as i8; | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | 1isize as i8; = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:21:5 + --> $DIR/cast_size.rs:12:5 | LL | 1isize as f64; | ^^^^^^^^^^^^^ @@ -15,31 +15,31 @@ LL | 1isize as f64; = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:22:5 + --> $DIR/cast_size.rs:13:5 | LL | 1usize as f64; | ^^^^^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:23:5 + --> $DIR/cast_size.rs:14:5 | LL | 1isize as f32; | ^^^^^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:24:5 + --> $DIR/cast_size.rs:15:5 | LL | 1usize as f32; | ^^^^^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:25:5 + --> $DIR/cast_size.rs:16:5 | LL | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may lose the sign of the value - --> $DIR/cast_size.rs:26:5 + --> $DIR/cast_size.rs:17:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ @@ -47,25 +47,25 @@ LL | 1isize as u32; = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:26:5 + --> $DIR/cast_size.rs:17:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:27:5 + --> $DIR/cast_size.rs:18:5 | LL | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:28:5 + --> $DIR/cast_size.rs:19:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:28:5 + --> $DIR/cast_size.rs:19:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -73,49 +73,49 @@ LL | 1usize as i32; = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:30:5 + --> $DIR/cast_size.rs:21:5 | LL | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may lose the sign of the value - --> $DIR/cast_size.rs:31:5 + --> $DIR/cast_size.rs:22:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:31:5 + --> $DIR/cast_size.rs:22:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:32:5 + --> $DIR/cast_size.rs:23:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:32:5 + --> $DIR/cast_size.rs:23:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:33:5 + --> $DIR/cast_size.rs:24:5 | LL | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:34:5 + --> $DIR/cast_size.rs:25:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to usize may lose the sign of the value - --> $DIR/cast_size.rs:37:5 + --> $DIR/cast_size.rs:28:5 | LL | 1i32 as usize; | ^^^^^^^^^^^^^ diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index 614cd3e30ec..7f4a86ae185 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(stmt_expr_attributes)] #![warn(clippy::deprecated_cfg_attr)] diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index 233aafc3c79..e60f5f25535 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -1,5 +1,5 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:25:5 + --> $DIR/cfg_attr_rustfmt.rs:16:5 | LL | #[cfg_attr(rustfmt, rustfmt::skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` @@ -7,13 +7,13 @@ LL | #[cfg_attr(rustfmt, rustfmt::skip)] = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:29:1 + --> $DIR/cfg_attr_rustfmt.rs:20:1 | LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:35:5 + --> $DIR/cfg_attr_rustfmt.rs:26:5 | LL | #![cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index 663962afeae..211cbfe98f3 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::char_lit_as_u8)] #![allow(unused_variables)] fn main() { diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index a577c55d261..52f29a3f553 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -1,5 +1,5 @@ error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them - --> $DIR/char_lit_as_u8.rs:13:13 + --> $DIR/char_lit_as_u8.rs:4:13 | LL | let c = 'a' as u8; | ^^^^^^^^^ diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap.rs index 4d250a80e90..21f9e33201f 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow(clippy::if_same_then_else)] diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap.stderr index 7e6a487ad1e..514814b0ee0 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap.stderr @@ -1,5 +1,5 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:16:9 + --> $DIR/checked_unwrap.rs:7:9 | LL | if x.is_some() { | ----------- the check is happening here @@ -7,13 +7,13 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:10:35 + --> $DIR/checked_unwrap.rs:1:35 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:18:9 + --> $DIR/checked_unwrap.rs:9:9 | LL | if x.is_some() { | ----------- because of this check @@ -22,13 +22,13 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:10:9 + --> $DIR/checked_unwrap.rs:1:9 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:21:9 + --> $DIR/checked_unwrap.rs:12:9 | LL | if x.is_none() { | ----------- because of this check @@ -36,7 +36,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:23:9 + --> $DIR/checked_unwrap.rs:14:9 | LL | if x.is_none() { | ----------- the check is happening here @@ -45,7 +45,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:27:9 + --> $DIR/checked_unwrap.rs:18:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -53,7 +53,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:28:9 + --> $DIR/checked_unwrap.rs:19:9 | LL | if x.is_ok() { | --------- because of this check @@ -62,7 +62,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:30:9 + --> $DIR/checked_unwrap.rs:21:9 | LL | if x.is_ok() { | --------- because of this check @@ -71,7 +71,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:31:9 + --> $DIR/checked_unwrap.rs:22:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -80,7 +80,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:34:9 + --> $DIR/checked_unwrap.rs:25:9 | LL | if x.is_err() { | ---------- because of this check @@ -88,7 +88,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:35:9 + --> $DIR/checked_unwrap.rs:26:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -97,7 +97,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:37:9 + --> $DIR/checked_unwrap.rs:28:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -106,7 +106,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:38:9 + --> $DIR/checked_unwrap.rs:29:9 | LL | if x.is_err() { | ---------- because of this check @@ -115,7 +115,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:55:9 + --> $DIR/checked_unwrap.rs:46:9 | LL | if x.is_ok() && y.is_err() { | --------- the check is happening here @@ -123,7 +123,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:56:9 + --> $DIR/checked_unwrap.rs:47:9 | LL | if x.is_ok() && y.is_err() { | --------- because of this check @@ -132,7 +132,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:57:9 + --> $DIR/checked_unwrap.rs:48:9 | LL | if x.is_ok() && y.is_err() { | ---------- because of this check @@ -141,7 +141,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:58:9 + --> $DIR/checked_unwrap.rs:49:9 | LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here @@ -150,7 +150,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:72:9 + --> $DIR/checked_unwrap.rs:63:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -159,7 +159,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:73:9 + --> $DIR/checked_unwrap.rs:64:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -168,7 +168,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:74:9 + --> $DIR/checked_unwrap.rs:65:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -177,7 +177,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:75:9 + --> $DIR/checked_unwrap.rs:66:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -186,7 +186,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:79:9 + --> $DIR/checked_unwrap.rs:70:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -194,7 +194,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:80:9 + --> $DIR/checked_unwrap.rs:71:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -203,7 +203,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:81:9 + --> $DIR/checked_unwrap.rs:72:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -212,7 +212,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:82:9 + --> $DIR/checked_unwrap.rs:73:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -221,7 +221,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:83:9 + --> $DIR/checked_unwrap.rs:74:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here @@ -230,7 +230,7 @@ LL | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:84:9 + --> $DIR/checked_unwrap.rs:75:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check @@ -239,7 +239,7 @@ LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:92:9 + --> $DIR/checked_unwrap.rs:83:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -248,7 +248,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:93:9 + --> $DIR/checked_unwrap.rs:84:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -257,7 +257,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:94:9 + --> $DIR/checked_unwrap.rs:85:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -266,7 +266,7 @@ LL | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:95:9 + --> $DIR/checked_unwrap.rs:86:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -275,7 +275,7 @@ LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:96:9 + --> $DIR/checked_unwrap.rs:87:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check @@ -284,7 +284,7 @@ LL | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:97:9 + --> $DIR/checked_unwrap.rs:88:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here @@ -293,7 +293,7 @@ LL | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:105:13 + --> $DIR/checked_unwrap.rs:96:13 | LL | if x.is_some() { | ----------- the check is happening here @@ -301,7 +301,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:107:13 + --> $DIR/checked_unwrap.rs:98:13 | LL | if x.is_some() { | ----------- because of this check diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index 058cbf7a16c..8f9f2a0db8c 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::fmt; use std::marker::PhantomData; diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 82f411d5c9d..3cbbcb7c083 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - pub fn dec_read_dec(i: &mut i32) -> i32 { *i -= 1; let ret = *i; diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index d6bdb5894d5..33e039308ec 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::cmp_nan)] #[allow(clippy::float_cmp, clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 2a7772308b8..421f3451823 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -1,5 +1,5 @@ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:14:5 + --> $DIR/cmp_nan.rs:5:5 | LL | x == std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ @@ -7,67 +7,67 @@ LL | x == std::f32::NAN; = note: `-D clippy::cmp-nan` implied by `-D warnings` error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:15:5 + --> $DIR/cmp_nan.rs:6:5 | LL | x != std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:16:5 + --> $DIR/cmp_nan.rs:7:5 | LL | x < std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:17:5 + --> $DIR/cmp_nan.rs:8:5 | LL | x > std::f32::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:18:5 + --> $DIR/cmp_nan.rs:9:5 | LL | x <= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:19:5 + --> $DIR/cmp_nan.rs:10:5 | LL | x >= std::f32::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:22:5 + --> $DIR/cmp_nan.rs:13:5 | LL | y == std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:23:5 + --> $DIR/cmp_nan.rs:14:5 | LL | y != std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:24:5 + --> $DIR/cmp_nan.rs:15:5 | LL | y < std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:25:5 + --> $DIR/cmp_nan.rs:16:5 | LL | y > std::f64::NAN; | ^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:26:5 + --> $DIR/cmp_nan.rs:17:5 | LL | y <= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ error: doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:27:5 + --> $DIR/cmp_nan.rs:18:5 | LL | y >= std::f64::NAN; | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 37615c9e113..2d2d04178c3 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::cmp_null)] #![allow(unused_mut)] diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 68789b5b635..063e716676c 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -1,5 +1,5 @@ error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:18:8 + --> $DIR/cmp_null.rs:9:8 | LL | if p == ptr::null() { | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | if p == ptr::null() { = note: `-D clippy::cmp-null` implied by `-D warnings` error: Comparing with null is better expressed by the .is_null() method - --> $DIR/cmp_null.rs:23:8 + --> $DIR/cmp_null.rs:14:8 | LL | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cmp_owned.rs b/tests/ui/cmp_owned.rs index 53de5136105..a5f92b30bc2 100644 --- a/tests/ui/cmp_owned.rs +++ b/tests/ui/cmp_owned.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::cmp_owned)] #[allow(clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cmp_owned.stderr b/tests/ui/cmp_owned.stderr index 9177c6bd73e..9be749f8d04 100644 --- a/tests/ui/cmp_owned.stderr +++ b/tests/ui/cmp_owned.stderr @@ -1,5 +1,5 @@ error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:14:14 + --> $DIR/cmp_owned.rs:5:14 | LL | x != "foo".to_string(); | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` @@ -7,49 +7,49 @@ LL | x != "foo".to_string(); = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:16:9 + --> $DIR/cmp_owned.rs:7:9 | LL | "foo".to_string() != x; | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:23:10 + --> $DIR/cmp_owned.rs:14:10 | LL | x != "foo".to_owned(); | ^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:25:10 + --> $DIR/cmp_owned.rs:16:10 | LL | x != String::from("foo"); | ^^^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:29:5 + --> $DIR/cmp_owned.rs:20:5 | LL | Foo.to_owned() == Foo; | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:31:30 + --> $DIR/cmp_owned.rs:22:30 | LL | "abc".chars().filter(|c| c.to_owned() != 'X'); | ^^^^^^^^^^^^ help: try: `*c` error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:38:5 + --> $DIR/cmp_owned.rs:29:5 | LL | y.to_owned() == *x; | ^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:43:5 + --> $DIR/cmp_owned.rs:34:5 | LL | y.to_owned() == **x; | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> $DIR/cmp_owned.rs:50:9 + --> $DIR/cmp_owned.rs:41:9 | LL | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 6828743abf3..e8918ddecb5 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[rustfmt::skip] #[warn(clippy::collapsible_if)] fn main() { diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 2c60234eb5d..1b9195563e5 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,5 +1,5 @@ error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:15:5 + --> $DIR/collapsible_if.rs:6:5 | LL | / if x == "hello" { LL | | if y == "world" { @@ -17,7 +17,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:21:5 + --> $DIR/collapsible_if.rs:12:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -33,7 +33,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:27:5 + --> $DIR/collapsible_if.rs:18:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -49,7 +49,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:33:5 + --> $DIR/collapsible_if.rs:24:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -65,7 +65,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:39:5 + --> $DIR/collapsible_if.rs:30:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -81,7 +81,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:45:5 + --> $DIR/collapsible_if.rs:36:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -97,7 +97,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:54:12 + --> $DIR/collapsible_if.rs:45:12 | LL | } else { | ____________^ @@ -114,7 +114,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:62:12 + --> $DIR/collapsible_if.rs:53:12 | LL | } else { | ____________^ @@ -131,7 +131,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:70:12 + --> $DIR/collapsible_if.rs:61:12 | LL | } else { | ____________^ @@ -153,7 +153,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:81:12 + --> $DIR/collapsible_if.rs:72:12 | LL | } else { | ____________^ @@ -175,7 +175,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:92:12 + --> $DIR/collapsible_if.rs:83:12 | LL | } else { | ____________^ @@ -197,7 +197,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:103:12 + --> $DIR/collapsible_if.rs:94:12 | LL | } else { | ____________^ @@ -219,7 +219,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:114:12 + --> $DIR/collapsible_if.rs:105:12 | LL | } else { | ____________^ @@ -241,7 +241,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:173:5 + --> $DIR/collapsible_if.rs:164:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index 9d75de62d74..cfece3768ef 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value)] #![feature(associated_type_defaults)] diff --git a/tests/ui/complex_types.stderr b/tests/ui/complex_types.stderr index 8f46d38921d..8f5dbd27956 100644 --- a/tests/ui/complex_types.stderr +++ b/tests/ui/complex_types.stderr @@ -1,5 +1,5 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:16:12 + --> $DIR/complex_types.rs:7:12 | LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,85 +7,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); = note: `-D clippy::type-complexity` implied by `-D warnings` error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:17:12 + --> $DIR/complex_types.rs:8:12 | LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:20:8 + --> $DIR/complex_types.rs:11:8 | LL | f: Vec>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:23:11 + --> $DIR/complex_types.rs:14:11 | LL | struct TS(Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:26:11 + --> $DIR/complex_types.rs:17:11 | LL | Tuple(Vec>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:27:17 + --> $DIR/complex_types.rs:18:17 | LL | Struct { f: Vec>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:31:14 + --> $DIR/complex_types.rs:22:14 | LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:32:30 + --> $DIR/complex_types.rs:23:30 | LL | fn impl_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:36:14 + --> $DIR/complex_types.rs:27:14 | LL | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:37:14 + --> $DIR/complex_types.rs:28:14 | LL | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:38:25 + --> $DIR/complex_types.rs:29:25 | LL | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:39:29 + --> $DIR/complex_types.rs:30:29 | LL | fn def_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:42:15 + --> $DIR/complex_types.rs:33:15 | LL | fn test1() -> Vec>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:46:14 + --> $DIR/complex_types.rs:37:14 | LL | fn test2(_x: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:49:13 + --> $DIR/complex_types.rs:40:13 | LL | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const_static_lifetime.rs b/tests/ui/const_static_lifetime.rs index 3e1aa94f969..745821a1503 100644 --- a/tests/ui/const_static_lifetime.rs +++ b/tests/ui/const_static_lifetime.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[derive(Debug)] struct Foo {} diff --git a/tests/ui/const_static_lifetime.stderr b/tests/ui/const_static_lifetime.stderr index b3fabb3522f..c329e860558 100644 --- a/tests/ui/const_static_lifetime.stderr +++ b/tests/ui/const_static_lifetime.stderr @@ -1,5 +1,5 @@ error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:13:17 + --> $DIR/const_static_lifetime.rs:4:17 | LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` @@ -7,73 +7,73 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin = note: `-D clippy::const-static-lifetime` implied by `-D warnings` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:17:21 + --> $DIR/const_static_lifetime.rs:8:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:19:32 + --> $DIR/const_static_lifetime.rs:10:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:19:47 + --> $DIR/const_static_lifetime.rs:10:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:21:18 + --> $DIR/const_static_lifetime.rs:12:18 | LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:21:30 + --> $DIR/const_static_lifetime.rs:12:30 | LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:23:17 + --> $DIR/const_static_lifetime.rs:14:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:25:29 + --> $DIR/const_static_lifetime.rs:16:29 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:25:39 + --> $DIR/const_static_lifetime.rs:16:39 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:27:20 + --> $DIR/const_static_lifetime.rs:18:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:29:19 + --> $DIR/const_static_lifetime.rs:20:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:31:19 + --> $DIR/const_static_lifetime.rs:22:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: Constants have by default a `'static` lifetime - --> $DIR/const_static_lifetime.rs:33:19 + --> $DIR/const_static_lifetime.rs:24:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 5db82006dea..a78209bcce8 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( clippy::blacklisted_name, clippy::collapsible_if, diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 3fbc279b537..a0a5c3890ed 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> $DIR/copies.rs:50:12 + --> $DIR/copies.rs:41:12 | LL | } else { | ____________^ @@ -13,7 +13,7 @@ LL | | } | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:42:13 + --> $DIR/copies.rs:33:13 | LL | if true { | _____________^ @@ -26,7 +26,7 @@ LL | | } else { | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:96:14 + --> $DIR/copies.rs:87:14 | LL | _ => { | ______________^ @@ -40,7 +40,7 @@ LL | | }, | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:87:15 + --> $DIR/copies.rs:78:15 | LL | 42 => { | _______________^ @@ -52,7 +52,7 @@ LL | | a LL | | }, | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:87:15 + --> $DIR/copies.rs:78:15 | LL | 42 => { | _______________^ @@ -65,24 +65,24 @@ LL | | }, | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:111:14 + --> $DIR/copies.rs:102:14 | LL | _ => 0, //~ ERROR match arms have same body | ^ | note: same as this - --> $DIR/copies.rs:109:19 + --> $DIR/copies.rs:100:19 | LL | Abc::A => 0, | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:109:19 + --> $DIR/copies.rs:100:19 | LL | Abc::A => 0, | ^ error: this `if` has identical blocks - --> $DIR/copies.rs:120:12 + --> $DIR/copies.rs:111:12 | LL | } else { | ____________^ @@ -92,7 +92,7 @@ LL | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:118:21 + --> $DIR/copies.rs:109:21 | LL | let _ = if true { | _____________________^ @@ -101,7 +101,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:134:12 + --> $DIR/copies.rs:125:12 | LL | } else { | ____________^ @@ -114,7 +114,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/copies.rs:125:13 + --> $DIR/copies.rs:116:13 | LL | if true { | _____________^ @@ -127,7 +127,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:153:12 + --> $DIR/copies.rs:144:12 | LL | } else { | ____________^ @@ -140,7 +140,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/copies.rs:146:13 + --> $DIR/copies.rs:137:13 | LL | if true { | _____________^ @@ -153,7 +153,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:183:12 + --> $DIR/copies.rs:174:12 | LL | } else { | ____________^ @@ -163,7 +163,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/copies.rs:181:13 + --> $DIR/copies.rs:172:13 | LL | if true { | _____________^ @@ -172,7 +172,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:190:12 + --> $DIR/copies.rs:181:12 | LL | } else { | ____________^ @@ -182,7 +182,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/copies.rs:188:13 + --> $DIR/copies.rs:179:13 | LL | if true { | _____________^ @@ -191,92 +191,92 @@ LL | | } else { | |_____^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:239:15 + --> $DIR/copies.rs:230:15 | LL | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:238:15 + --> $DIR/copies.rs:229:15 | LL | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:238:15 + --> $DIR/copies.rs:229:15 | LL | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:245:17 + --> $DIR/copies.rs:236:17 | LL | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:244:20 + --> $DIR/copies.rs:235:20 | LL | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:244:20 + --> $DIR/copies.rs:235:20 | LL | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:267:28 + --> $DIR/copies.rs:258:28 | LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:266:28 + --> $DIR/copies.rs:257:28 | LL | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:266:28 + --> $DIR/copies.rs:257:28 | LL | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:273:26 + --> $DIR/copies.rs:264:26 | LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:272:26 + --> $DIR/copies.rs:263:26 | LL | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:272:26 + --> $DIR/copies.rs:263:26 | LL | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:279:20 + --> $DIR/copies.rs:270:20 | LL | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:278:23 + --> $DIR/copies.rs:269:23 | LL | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:278:23 + --> $DIR/copies.rs:269:23 | LL | (1, .., 3) => 42, | ^^ error: this `if` has identical blocks - --> $DIR/copies.rs:285:12 + --> $DIR/copies.rs:276:12 | LL | } else { | ____________^ @@ -286,7 +286,7 @@ LL | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:283:21 + --> $DIR/copies.rs:274:21 | LL | let _ = if true { | _____________________^ @@ -295,7 +295,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:292:12 + --> $DIR/copies.rs:283:12 | LL | } else { | ____________^ @@ -305,7 +305,7 @@ LL | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:290:21 + --> $DIR/copies.rs:281:21 | LL | let _ = if true { | _____________________^ @@ -314,7 +314,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:305:12 + --> $DIR/copies.rs:296:12 | LL | } else { | ____________^ @@ -324,7 +324,7 @@ LL | | }; | |_____^ | note: same as this - --> $DIR/copies.rs:303:21 + --> $DIR/copies.rs:294:21 | LL | let _ = if true { | _____________________^ @@ -333,7 +333,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/copies.rs:323:12 + --> $DIR/copies.rs:314:12 | LL | } else { | ____________^ @@ -343,7 +343,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/copies.rs:321:13 + --> $DIR/copies.rs:312:13 | LL | if true { | _____________^ diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index 22d3e138898..e3d5928be23 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::copy_iterator)] #[derive(Copy, Clone)] diff --git a/tests/ui/copy_iterator.stderr b/tests/ui/copy_iterator.stderr index 34606df8595..f8ce6af7961 100644 --- a/tests/ui/copy_iterator.stderr +++ b/tests/ui/copy_iterator.stderr @@ -1,5 +1,5 @@ error: you are implementing `Iterator` on a `Copy` type - --> $DIR/copy_iterator.rs:15:1 + --> $DIR/copy_iterator.rs:6:1 | LL | / impl Iterator for Countdown { LL | | type Item = u8; diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index 5fe915a8368..6cc36518e27 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() {} #[allow(clippy::result_unwrap_used)] diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index d2968eb9d18..a2fc07d4af0 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -1,5 +1,5 @@ error: you are getting the inner pointer of a temporary `CString` - --> $DIR/cstring.rs:16:5 + --> $DIR/cstring.rs:7:5 | LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | CString::new("foo").unwrap().as_ptr(); = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime - --> $DIR/cstring.rs:16:5 + --> $DIR/cstring.rs:7:5 | LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cyclomatic_complexity.rs b/tests/ui/cyclomatic_complexity.rs index fff67762924..d552ef50ff0 100644 --- a/tests/ui/cyclomatic_complexity.rs +++ b/tests/ui/cyclomatic_complexity.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::all)] #![warn(clippy::cyclomatic_complexity)] #![allow(unused)] diff --git a/tests/ui/cyclomatic_complexity.stderr b/tests/ui/cyclomatic_complexity.stderr index f8e3a54debd..944bba6e488 100644 --- a/tests/ui/cyclomatic_complexity.stderr +++ b/tests/ui/cyclomatic_complexity.stderr @@ -1,5 +1,5 @@ error: the function has a cyclomatic complexity of 28 - --> $DIR/cyclomatic_complexity.rs:15:1 + --> $DIR/cyclomatic_complexity.rs:6:1 | LL | / fn main() { LL | | if true { @@ -14,7 +14,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 7 - --> $DIR/cyclomatic_complexity.rs:100:1 + --> $DIR/cyclomatic_complexity.rs:91:1 | LL | / fn kaboom() { LL | | let n = 0; @@ -28,7 +28,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:146:1 + --> $DIR/cyclomatic_complexity.rs:137:1 | LL | / fn lots_of_short_circuits() -> bool { LL | | true && false && true && false && true && false && true @@ -38,7 +38,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:151:1 + --> $DIR/cyclomatic_complexity.rs:142:1 | LL | / fn lots_of_short_circuits2() -> bool { LL | | true || false || true || false || true || false || true @@ -48,7 +48,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:156:1 + --> $DIR/cyclomatic_complexity.rs:147:1 | LL | / fn baa() { LL | | let x = || match 99 { @@ -62,7 +62,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:157:13 + --> $DIR/cyclomatic_complexity.rs:148:13 | LL | let x = || match 99 { | _____________^ @@ -77,7 +77,7 @@ LL | | }; = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:174:1 + --> $DIR/cyclomatic_complexity.rs:165:1 | LL | / fn bar() { LL | | match 99 { @@ -90,7 +90,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:193:1 + --> $DIR/cyclomatic_complexity.rs:184:1 | LL | / fn barr() { LL | | match 99 { @@ -104,7 +104,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:203:1 + --> $DIR/cyclomatic_complexity.rs:194:1 | LL | / fn barr2() { LL | | match 99 { @@ -118,7 +118,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:219:1 + --> $DIR/cyclomatic_complexity.rs:210:1 | LL | / fn barrr() { LL | | match 99 { @@ -132,7 +132,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:229:1 + --> $DIR/cyclomatic_complexity.rs:220:1 | LL | / fn barrr2() { LL | | match 99 { @@ -146,7 +146,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:245:1 + --> $DIR/cyclomatic_complexity.rs:236:1 | LL | / fn barrrr() { LL | | match 99 { @@ -160,7 +160,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity.rs:255:1 + --> $DIR/cyclomatic_complexity.rs:246:1 | LL | / fn barrrr2() { LL | | match 99 { @@ -174,7 +174,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 2 - --> $DIR/cyclomatic_complexity.rs:271:1 + --> $DIR/cyclomatic_complexity.rs:262:1 | LL | / fn cake() { LL | | if 4 == 5 { @@ -188,7 +188,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 4 - --> $DIR/cyclomatic_complexity.rs:281:1 + --> $DIR/cyclomatic_complexity.rs:272:1 | LL | / pub fn read_file(input_path: &str) -> String { LL | | use std::fs::File; @@ -202,7 +202,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:312:1 + --> $DIR/cyclomatic_complexity.rs:303:1 | LL | / fn void(void: Void) { LL | | if true { @@ -214,7 +214,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:325:1 + --> $DIR/cyclomatic_complexity.rs:316:1 | LL | / fn try() -> Result { LL | | match 5 { @@ -227,7 +227,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:333:1 + --> $DIR/cyclomatic_complexity.rs:324:1 | LL | / fn try_again() -> Result { LL | | let _ = try!(Ok(42)); @@ -241,7 +241,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 1 - --> $DIR/cyclomatic_complexity.rs:349:1 + --> $DIR/cyclomatic_complexity.rs:340:1 | LL | / fn early() -> Result { LL | | return Ok(5); @@ -255,7 +255,7 @@ LL | | } = help: you could split it up into multiple smaller functions error: the function has a cyclomatic complexity of 8 - --> $DIR/cyclomatic_complexity.rs:363:1 + --> $DIR/cyclomatic_complexity.rs:354:1 | LL | / fn early_ret() -> i32 { LL | | let a = if true { 42 } else { return 0; }; diff --git a/tests/ui/cyclomatic_complexity_attr_used.rs b/tests/ui/cyclomatic_complexity_attr_used.rs index b1da9649f90..8b5028557d9 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.rs +++ b/tests/ui/cyclomatic_complexity_attr_used.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::cyclomatic_complexity)] #![warn(unused)] diff --git a/tests/ui/cyclomatic_complexity_attr_used.stderr b/tests/ui/cyclomatic_complexity_attr_used.stderr index dde803880ca..7b732119774 100644 --- a/tests/ui/cyclomatic_complexity_attr_used.stderr +++ b/tests/ui/cyclomatic_complexity_attr_used.stderr @@ -1,5 +1,5 @@ error: the function has a cyclomatic complexity of 3 - --> $DIR/cyclomatic_complexity_attr_used.rs:18:1 + --> $DIR/cyclomatic_complexity_attr_used.rs:9:1 | LL | / fn kaboom() { LL | | if 42 == 43 { diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index d7823b0b819..d841f16757a 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] #[rustfmt::skip] diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index cc908ca11f3..3a535def197 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,5 +1,5 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:25:9 + --> $DIR/decimal_literal_representation.rs:16:9 | LL | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` @@ -7,25 +7,25 @@ LL | 32_773, // 0x8005 = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:26:9 + --> $DIR/decimal_literal_representation.rs:17:9 | LL | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:27:9 + --> $DIR/decimal_literal_representation.rs:18:9 | LL | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:28:9 + --> $DIR/decimal_literal_representation.rs:19:9 | LL | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:29:9 + --> $DIR/decimal_literal_representation.rs:20:9 | LL | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index eaa367b0cb3..2f1490a7036 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::default_trait_access)] use std::default; diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index 9fcf359b72f..1f115aecca1 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,5 +1,5 @@ error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:17:22 + --> $DIR/default_trait_access.rs:8:22 | LL | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` @@ -7,43 +7,43 @@ LL | let s1: String = Default::default(); = note: `-D clippy::default-trait-access` implied by `-D warnings` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:21:22 + --> $DIR/default_trait_access.rs:12:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:23:22 + --> $DIR/default_trait_access.rs:14:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling std::string::String::default() is more clear than this expression - --> $DIR/default_trait_access.rs:27:22 + --> $DIR/default_trait_access.rs:18:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: Calling GenericDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:37:46 + --> $DIR/default_trait_access.rs:28:46 | LL | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: Calling TupleDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:43:36 + --> $DIR/default_trait_access.rs:34:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: Calling ArrayDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:45:36 + --> $DIR/default_trait_access.rs:36:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: Calling TupleStructDerivedDefault::default() is more clear than this expression - --> $DIR/default_trait_access.rs:49:42 + --> $DIR/default_trait_access.rs:40:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 7a1657424ed..2e5c5b7ead1 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(str_to_string)] #[warn(string_to_string)] #[warn(unstable_as_slice)] diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 3d1f016b9b9..4dbca0dea64 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -1,5 +1,5 @@ error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:10:8 + --> $DIR/deprecated.rs:1:8 | LL | #[warn(str_to_string)] | ^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | #[warn(str_to_string)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:11:8 + --> $DIR/deprecated.rs:2:8 | LL | #[warn(string_to_string)] | ^^^^^^^^^^^^^^^^ error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:12:8 + --> $DIR/deprecated.rs:3:8 | LL | #[warn(unstable_as_slice)] | ^^^^^^^^^^^^^^^^^ error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:13:8 + --> $DIR/deprecated.rs:4:8 | LL | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` - --> $DIR/deprecated.rs:14:8 + --> $DIR/deprecated.rs:5:8 | LL | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index a6020b61337..b7a672cd80a 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(untagged_unions)] #![allow(dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index b9629005597..fc87c7d1596 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -1,12 +1,12 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> $DIR/derive.rs:25:10 + --> $DIR/derive.rs:16:10 | LL | #[derive(Hash)] | ^^^^ | = note: #[deny(clippy::derive_hash_xor_eq)] on by default note: `PartialEq` implemented here - --> $DIR/derive.rs:28:1 + --> $DIR/derive.rs:19:1 | LL | / impl PartialEq for Bar { LL | | fn eq(&self, _: &Bar) -> bool { @@ -16,13 +16,13 @@ LL | | } | |_^ error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> $DIR/derive.rs:34:10 + --> $DIR/derive.rs:25:10 | LL | #[derive(Hash)] | ^^^^ | note: `PartialEq` implemented here - --> $DIR/derive.rs:37:1 + --> $DIR/derive.rs:28:1 | LL | / impl PartialEq for Baz { LL | | fn eq(&self, _: &Baz) -> bool { @@ -32,7 +32,7 @@ LL | | } | |_^ error: you are implementing `Hash` explicitly but have derived `PartialEq` - --> $DIR/derive.rs:46:1 + --> $DIR/derive.rs:37:1 | LL | / impl Hash for Bah { LL | | fn hash(&self, _: &mut H) {} @@ -40,13 +40,13 @@ LL | | } | |_^ | note: `PartialEq` implemented here - --> $DIR/derive.rs:43:10 + --> $DIR/derive.rs:34:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:53:1 + --> $DIR/derive.rs:44:1 | LL | / impl Clone for Qux { LL | | fn clone(&self) -> Self { @@ -57,7 +57,7 @@ LL | | } | = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:53:1 + --> $DIR/derive.rs:44:1 | LL | / impl Clone for Qux { LL | | fn clone(&self) -> Self { @@ -67,7 +67,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:77:1 + --> $DIR/derive.rs:68:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | fn clone(&self) -> Self { @@ -77,7 +77,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:77:1 + --> $DIR/derive.rs:68:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | fn clone(&self) -> Self { @@ -87,7 +87,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:89:1 + --> $DIR/derive.rs:80:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -97,7 +97,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:89:1 + --> $DIR/derive.rs:80:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -107,7 +107,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:101:1 + --> $DIR/derive.rs:92:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { @@ -117,7 +117,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:101:1 + --> $DIR/derive.rs:92:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 3399dba7189..746afa47503 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(never_type)] #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::logic_bug)] diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 1cfec07c560..70ff3cdd046 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,5 +1,5 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:30:10 + --> $DIR/diverging_sub_expression.rs:21:10 | LL | b || diverge(); | ^^^^^^^^^ @@ -7,31 +7,31 @@ LL | b || diverge(); = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:31:10 + --> $DIR/diverging_sub_expression.rs:22:10 | LL | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:40:26 + --> $DIR/diverging_sub_expression.rs:31:26 | LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:41:26 + --> $DIR/diverging_sub_expression.rs:32:26 | LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:44:26 + --> $DIR/diverging_sub_expression.rs:35:26 | LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:49:26 + --> $DIR/diverging_sub_expression.rs:40:26 | LL | _ => true || break, | ^^^^^ diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index dfc8be24a8b..7634341ba84 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(alloc)] #![feature(associated_type_defaults)] #![warn(clippy::linkedlist)] diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index 6b0413fdf23..cc4b8e7a3b4 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -1,5 +1,5 @@ error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:19:16 + --> $DIR/dlist.rs:10:16 | LL | type Baz = LinkedList; | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | type Baz = LinkedList; = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:20:12 + --> $DIR/dlist.rs:11:12 | LL | fn foo(LinkedList); | ^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | fn foo(LinkedList); = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:21:23 + --> $DIR/dlist.rs:12:23 | LL | const BAR: Option>; | ^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | const BAR: Option>; = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:32:15 + --> $DIR/dlist.rs:23:15 | LL | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | fn foo(_: LinkedList) {} = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:35:39 + --> $DIR/dlist.rs:26:39 | LL | pub fn test(my_favourite_linked_list: LinkedList) { | ^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | pub fn test(my_favourite_linked_list: LinkedList) { = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:39:29 + --> $DIR/dlist.rs:30:29 | LL | pub fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index d4ba83a86f3..915fb3aae89 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This file tests for the DOC_MARKDOWN lint #![allow(dead_code)] diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index 964e351348a..4a2ef448e84 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -1,5 +1,5 @@ error: you should put `DOC_MARKDOWN` between ticks in the documentation - --> $DIR/doc.rs:10:29 + --> $DIR/doc.rs:1:29 | LL | //! This file tests for the DOC_MARKDOWN lint | ^^^^^^^^^^^^ @@ -7,181 +7,181 @@ LL | //! This file tests for the DOC_MARKDOWN lint = note: `-D clippy::doc-markdown` implied by `-D warnings` error: you should put `foo_bar` between ticks in the documentation - --> $DIR/doc.rs:15:9 + --> $DIR/doc.rs:6:9 | LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^ error: you should put `foo::bar` between ticks in the documentation - --> $DIR/doc.rs:15:51 + --> $DIR/doc.rs:6:51 | LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) | ^^^^^^^^ error: you should put `Foo::some_fun` between ticks in the documentation - --> $DIR/doc.rs:16:84 + --> $DIR/doc.rs:7:84 | LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun | ^^^^^^^^^^^^^ error: you should put `a::global:path` between ticks in the documentation - --> $DIR/doc.rs:18:15 + --> $DIR/doc.rs:9:15 | LL | /// Here be ::a::global:path. | ^^^^^^^^^^^^^^ error: you should put `NotInCodeBlock` between ticks in the documentation - --> $DIR/doc.rs:19:22 + --> $DIR/doc.rs:10:22 | LL | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:20:5 + --> $DIR/doc.rs:11:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:34:5 + --> $DIR/doc.rs:25:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:41:5 + --> $DIR/doc.rs:32:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:55:5 + --> $DIR/doc.rs:46:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:59:22 + --> $DIR/doc.rs:50:22 | LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:62:21 + --> $DIR/doc.rs:53:21 | LL | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:72:5 + --> $DIR/doc.rs:63:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:80:8 + --> $DIR/doc.rs:71:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:83:7 + --> $DIR/doc.rs:74:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:85:22 + --> $DIR/doc.rs:76:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:86:5 + --> $DIR/doc.rs:77:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:93:5 + --> $DIR/doc.rs:84:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:106:5 + --> $DIR/doc.rs:97:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:117:42 + --> $DIR/doc.rs:108:42 | LL | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:122:5 + --> $DIR/doc.rs:113:5 | LL | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:123:1 + --> $DIR/doc.rs:114:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:128:42 + --> $DIR/doc.rs:119:42 | LL | /** E.g. serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:133:5 + --> $DIR/doc.rs:124:5 | LL | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:134:1 + --> $DIR/doc.rs:125:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:145:5 + --> $DIR/doc.rs:136:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:172:13 + --> $DIR/doc.rs:163:13 | LL | /// Not ok: http://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:173:13 + --> $DIR/doc.rs:164:13 | LL | /// Not ok: https://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:174:13 + --> $DIR/doc.rs:165:13 | LL | /// Not ok: http://www.unicode.org/ | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:175:13 + --> $DIR/doc.rs:166:13 | LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `mycrate::Collection` between ticks in the documentation - --> $DIR/doc.rs:181:22 + --> $DIR/doc.rs:172:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index fd98edb7555..bb6cdaa667d 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 5d201a13ff2..9a2a9068a28 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 31bab8f0112..5dcda7b3af4 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,5 +1,5 @@ error: This binary expression can be simplified - --> $DIR/double_comparison.rs:15:8 + --> $DIR/double_comparison.rs:6:8 | LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` @@ -7,43 +7,43 @@ LL | if x == y || x < y { = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:18:8 + --> $DIR/double_comparison.rs:9:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:21:8 + --> $DIR/double_comparison.rs:12:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:24:8 + --> $DIR/double_comparison.rs:15:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:27:8 + --> $DIR/double_comparison.rs:18:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:30:8 + --> $DIR/double_comparison.rs:21:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:33:8 + --> $DIR/double_comparison.rs:24:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:36:8 + --> $DIR/double_comparison.rs:27:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/double_neg.rs b/tests/ui/double_neg.rs index 7d65122cb5e..d47dfcb5ba1 100644 --- a/tests/ui/double_neg.rs +++ b/tests/ui/double_neg.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::double_neg)] fn main() { let x = 1; diff --git a/tests/ui/double_neg.stderr b/tests/ui/double_neg.stderr index 6ff18e5504d..d82ed05f054 100644 --- a/tests/ui/double_neg.stderr +++ b/tests/ui/double_neg.stderr @@ -1,5 +1,5 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op - --> $DIR/double_neg.rs:15:5 + --> $DIR/double_neg.rs:6:5 | LL | --x; | ^^^ diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index 773179b2d46..c6f9bf77e12 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::double_parens)] #![allow(dead_code)] fn dummy_fn(_: T) {} diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index 0e7f62ca3e3..6336b1c259a 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -1,5 +1,5 @@ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:21:5 + --> $DIR/double_parens.rs:12:5 | LL | ((0)) | ^^^^^ @@ -7,31 +7,31 @@ LL | ((0)) = note: `-D clippy::double-parens` implied by `-D warnings` error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:25:14 + --> $DIR/double_parens.rs:16:14 | LL | dummy_fn((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:29:20 + --> $DIR/double_parens.rs:20:20 | LL | x.dummy_method((0)); | ^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:33:5 + --> $DIR/double_parens.rs:24:5 | LL | ((1, 2)) | ^^^^^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:37:5 + --> $DIR/double_parens.rs:28:5 | LL | (()) | ^^^^ error: Consider removing unnecessary double parentheses - --> $DIR/double_parens.rs:59:16 + --> $DIR/double_parens.rs:50:16 | LL | assert_eq!(((1, 2)), (1, 2), "Error"); | ^^^^^^^^ diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs index 2ea8954ff59..9ddd6d64701 100644 --- a/tests/ui/drop_forget_copy.rs +++ b/tests/ui/drop_forget_copy.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::drop_copy, clippy::forget_copy)] #![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)] diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr index 6fc69c4bcda..55c840d3480 100644 --- a/tests/ui/drop_forget_copy.stderr +++ b/tests/ui/drop_forget_copy.stderr @@ -1,73 +1,73 @@ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:42:5 + --> $DIR/drop_forget_copy.rs:33:5 | LL | drop(s1); | ^^^^^^^^ | = note: `-D clippy::drop-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:42:10 + --> $DIR/drop_forget_copy.rs:33:10 | LL | drop(s1); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:43:5 + --> $DIR/drop_forget_copy.rs:34:5 | LL | drop(s2); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:43:10 + --> $DIR/drop_forget_copy.rs:34:10 | LL | drop(s2); | ^^ error: calls to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:45:5 + --> $DIR/drop_forget_copy.rs:36:5 | LL | drop(s4); | ^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:45:10 + --> $DIR/drop_forget_copy.rs:36:10 | LL | drop(s4); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:48:5 + --> $DIR/drop_forget_copy.rs:39:5 | LL | forget(s1); | ^^^^^^^^^^ | = note: `-D clippy::forget-copy` implied by `-D warnings` note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:48:12 + --> $DIR/drop_forget_copy.rs:39:12 | LL | forget(s1); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:49:5 + --> $DIR/drop_forget_copy.rs:40:5 | LL | forget(s2); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:49:12 + --> $DIR/drop_forget_copy.rs:40:12 | LL | forget(s2); | ^^ error: calls to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. - --> $DIR/drop_forget_copy.rs:51:5 + --> $DIR/drop_forget_copy.rs:42:5 | LL | forget(s4); | ^^^^^^^^^^ | note: argument has type SomeStruct - --> $DIR/drop_forget_copy.rs:51:12 + --> $DIR/drop_forget_copy.rs:42:12 | LL | forget(s4); | ^^ diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index 6821d403322..b3c75bc5764 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::drop_ref, clippy::forget_ref)] #![allow(clippy::toplevel_ref_arg, clippy::similar_names, clippy::needless_pass_by_value)] diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 005adceca50..8ffc369b882 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -1,217 +1,217 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:18:5 + --> $DIR/drop_forget_ref.rs:9:5 | LL | drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::drop-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:18:10 + --> $DIR/drop_forget_ref.rs:9:10 | LL | drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:19:5 + --> $DIR/drop_forget_ref.rs:10:5 | LL | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:19:12 + --> $DIR/drop_forget_ref.rs:10:12 | LL | forget(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:22:5 + --> $DIR/drop_forget_ref.rs:13:5 | LL | drop(&owned1); | ^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:22:10 + --> $DIR/drop_forget_ref.rs:13:10 | LL | drop(&owned1); | ^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:23:5 + --> $DIR/drop_forget_ref.rs:14:5 | LL | drop(&&owned1); | ^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:23:10 + --> $DIR/drop_forget_ref.rs:14:10 | LL | drop(&&owned1); | ^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:24:5 + --> $DIR/drop_forget_ref.rs:15:5 | LL | drop(&mut owned1); | ^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:24:10 + --> $DIR/drop_forget_ref.rs:15:10 | LL | drop(&mut owned1); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:27:5 + --> $DIR/drop_forget_ref.rs:18:5 | LL | forget(&owned2); | ^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:27:12 + --> $DIR/drop_forget_ref.rs:18:12 | LL | forget(&owned2); | ^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:28:5 + --> $DIR/drop_forget_ref.rs:19:5 | LL | forget(&&owned2); | ^^^^^^^^^^^^^^^^ | note: argument has type &&SomeStruct - --> $DIR/drop_forget_ref.rs:28:12 + --> $DIR/drop_forget_ref.rs:19:12 | LL | forget(&&owned2); | ^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:29:5 + --> $DIR/drop_forget_ref.rs:20:5 | LL | forget(&mut owned2); | ^^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:29:12 + --> $DIR/drop_forget_ref.rs:20:12 | LL | forget(&mut owned2); | ^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:33:5 + --> $DIR/drop_forget_ref.rs:24:5 | LL | drop(reference1); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:33:10 + --> $DIR/drop_forget_ref.rs:24:10 | LL | drop(reference1); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:34:5 + --> $DIR/drop_forget_ref.rs:25:5 | LL | forget(&*reference1); | ^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:34:12 + --> $DIR/drop_forget_ref.rs:25:12 | LL | forget(&*reference1); | ^^^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:37:5 + --> $DIR/drop_forget_ref.rs:28:5 | LL | drop(reference2); | ^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:37:10 + --> $DIR/drop_forget_ref.rs:28:10 | LL | drop(reference2); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:39:5 + --> $DIR/drop_forget_ref.rs:30:5 | LL | forget(reference3); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &mut SomeStruct - --> $DIR/drop_forget_ref.rs:39:12 + --> $DIR/drop_forget_ref.rs:30:12 | LL | forget(reference3); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:42:5 + --> $DIR/drop_forget_ref.rs:33:5 | LL | drop(reference4); | ^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:42:10 + --> $DIR/drop_forget_ref.rs:33:10 | LL | drop(reference4); | ^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:43:5 + --> $DIR/drop_forget_ref.rs:34:5 | LL | forget(reference4); | ^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:43:12 + --> $DIR/drop_forget_ref.rs:34:12 | LL | forget(reference4); | ^^^^^^^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:48:5 + --> $DIR/drop_forget_ref.rs:39:5 | LL | drop(&val); | ^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:48:10 + --> $DIR/drop_forget_ref.rs:39:10 | LL | drop(&val); | ^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:54:5 + --> $DIR/drop_forget_ref.rs:45:5 | LL | forget(&val); | ^^^^^^^^^^^^ | note: argument has type &T - --> $DIR/drop_forget_ref.rs:54:12 + --> $DIR/drop_forget_ref.rs:45:12 | LL | forget(&val); | ^^^^ error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing. - --> $DIR/drop_forget_ref.rs:62:5 + --> $DIR/drop_forget_ref.rs:53:5 | LL | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:62:20 + --> $DIR/drop_forget_ref.rs:53:20 | LL | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^ error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:65:5 + --> $DIR/drop_forget_ref.rs:56:5 | LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:65:22 + --> $DIR/drop_forget_ref.rs:56:22 | LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index da4e2a6dc8a..54d748c7ce2 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::duplicate_underscore_argument)] #[allow(dead_code, unused)] diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr index e4bdd3f96b2..f71614a5fd1 100644 --- a/tests/ui/duplicate_underscore_argument.stderr +++ b/tests/ui/duplicate_underscore_argument.stderr @@ -1,5 +1,5 @@ error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult - --> $DIR/duplicate_underscore_argument.rs:13:23 + --> $DIR/duplicate_underscore_argument.rs:4:23 | LL | fn join_the_dark_side(darth: i32, _darth: i32) {} | ^^^^^ diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 8c2dade34c0..d54d2f46eb7 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index e87c9839b33..249777e863c 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,5 +1,5 @@ error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:17:24 + --> $DIR/duration_subsec.rs:8:24 | LL | let bad_millis_1 = dur.subsec_micros() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` @@ -7,25 +7,25 @@ LL | let bad_millis_1 = dur.subsec_micros() / 1_000; = note: `-D clippy::duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:18:24 + --> $DIR/duration_subsec.rs:9:24 | LL | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:23:22 + --> $DIR/duration_subsec.rs:14:22 | LL | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:28:13 + --> $DIR/duration_subsec.rs:19:13 | LL | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:32:13 + --> $DIR/duration_subsec.rs:23:13 | LL | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 0776eae310c..879b3ac398e 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![warn(clippy::else_if_without_else)] diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 2c1ecbfdb86..27000906754 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,5 +1,5 @@ error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:54:12 + --> $DIR/else_if_without_else.rs:45:12 | LL | } else if bla2() { | ____________^ @@ -12,7 +12,7 @@ LL | | } = help: add an `else` block here error: if expression with an `else if`, but without a final `else` - --> $DIR/else_if_without_else.rs:63:12 + --> $DIR/else_if_without_else.rs:54:12 | LL | } else if bla3() { | ____________^ diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index b47afc822f8..12428f29625 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] #![warn(clippy::empty_enum)] diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index d2e3688eb4d..223a14ed877 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -1,12 +1,12 @@ error: enum with no variants - --> $DIR/empty_enum.rs:13:1 + --> $DIR/empty_enum.rs:4:1 | LL | enum Empty {} | ^^^^^^^^^^^^^ | = note: `-D clippy::empty-enum` implied by `-D warnings` help: consider using the uninhabited type `!` or a wrapper around it - --> $DIR/empty_enum.rs:13:1 + --> $DIR/empty_enum.rs:4:1 | LL | enum Empty {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index ede1244df7e..1e067a54232 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::empty_line_after_outer_attr)] // This should produce a warning diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index 59939ea2858..0fb8dd8dbb1 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,5 +1,5 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:13:1 + --> $DIR/empty_line_after_outer_attribute.rs:4:1 | LL | / #[crate_type = "lib"] LL | | @@ -10,7 +10,7 @@ LL | | fn with_one_newline_and_comment() { assert!(true) } = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:25:1 + --> $DIR/empty_line_after_outer_attribute.rs:16:1 | LL | / #[crate_type = "lib"] LL | | @@ -18,7 +18,7 @@ LL | | fn with_one_newline() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:30:1 + --> $DIR/empty_line_after_outer_attribute.rs:21:1 | LL | / #[crate_type = "lib"] LL | | @@ -27,7 +27,7 @@ LL | | fn with_two_newlines() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:37:1 + --> $DIR/empty_line_after_outer_attribute.rs:28:1 | LL | / #[crate_type = "lib"] LL | | @@ -35,7 +35,7 @@ LL | | enum Baz { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:45:1 + --> $DIR/empty_line_after_outer_attribute.rs:36:1 | LL | / #[crate_type = "lib"] LL | | @@ -43,7 +43,7 @@ LL | | struct Foo { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:53:1 + --> $DIR/empty_line_after_outer_attribute.rs:44:1 | LL | / #[crate_type = "lib"] LL | | diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 6c826716650..00d496e36f6 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused, clippy::needless_pass_by_value)] #![warn(clippy::map_entry)] diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 78a179d07ef..efacec1e777 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -1,5 +1,5 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:19:5 + --> $DIR/entry.rs:10:5 | LL | / if !m.contains_key(&k) { LL | | m.insert(k, v); @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::map-entry` implied by `-D warnings` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:25:5 + --> $DIR/entry.rs:16:5 | LL | / if !m.contains_key(&k) { LL | | foo(); @@ -18,7 +18,7 @@ LL | | } | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:32:5 + --> $DIR/entry.rs:23:5 | LL | / if !m.contains_key(&k) { LL | | m.insert(k, v) @@ -28,7 +28,7 @@ LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:40:5 + --> $DIR/entry.rs:31:5 | LL | / if m.contains_key(&k) { LL | | None @@ -38,7 +38,7 @@ LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:48:5 + --> $DIR/entry.rs:39:5 | LL | / if !m.contains_key(&k) { LL | | foo(); @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry.rs:57:5 + --> $DIR/entry.rs:48:5 | LL | / if m.contains_key(&k) { LL | | None @@ -60,7 +60,7 @@ LL | | }; | |_____^ help: consider using: `m.entry(k)` error: usage of `contains_key` followed by `insert` on a `BTreeMap` - --> $DIR/entry.rs:66:5 + --> $DIR/entry.rs:57:5 | LL | / if !m.contains_key(&k) { LL | | foo(); diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index dde2896e415..e7b2526ca50 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all, clippy::pedantic)] #![allow(unused_imports, dead_code, clippy::missing_docs_in_private_items)] diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 8b89856d4a4..a301703c298 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -1,5 +1,5 @@ error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:13:1 + --> $DIR/enum_glob_use.rs:4:1 | LL | use std::cmp::Ordering::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | use std::cmp::Ordering::*; = note: `-D clippy::enum-glob-use` implied by `-D warnings` error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:19:1 + --> $DIR/enum_glob_use.rs:10:1 | LL | use self::Enum::*; | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index 33472a7f83c..f3bbd3d9626 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(non_ascii_idents)] #![warn(clippy::all, clippy::pub_enum_variant_names)] #![allow(non_camel_case_types)] diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 4555e1d0649..2835391de7f 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,5 +1,5 @@ error: Variant name ends with the enum's name - --> $DIR/enum_variants.rs:25:5 + --> $DIR/enum_variants.rs:16:5 | LL | cFoo, | ^^^^ @@ -7,25 +7,25 @@ LL | cFoo, = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:36:5 + --> $DIR/enum_variants.rs:27:5 | LL | FoodGood, | ^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:37:5 + --> $DIR/enum_variants.rs:28:5 | LL | FoodMiddle, | ^^^^^^^^^^ error: Variant name starts with the enum's name - --> $DIR/enum_variants.rs:38:5 + --> $DIR/enum_variants.rs:29:5 | LL | FoodBad, | ^^^^^^^ error: All variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:35:1 + --> $DIR/enum_variants.rs:26:1 | LL | / enum Food { LL | | FoodGood, @@ -37,7 +37,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:45:1 + --> $DIR/enum_variants.rs:36:1 | LL | / enum BadCallType { LL | | CallTypeCall, @@ -49,7 +49,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:57:1 + --> $DIR/enum_variants.rs:48:1 | LL | / enum Consts { LL | | ConstantInt, @@ -61,7 +61,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:91:1 + --> $DIR/enum_variants.rs:82:1 | LL | / enum Seallll { LL | | WithOutCake, @@ -73,7 +73,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:97:1 + --> $DIR/enum_variants.rs:88:1 | LL | / enum NonCaps { LL | | Prefix的, @@ -85,7 +85,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: All variants have the same prefix: `With` - --> $DIR/enum_variants.rs:103:1 + --> $DIR/enum_variants.rs:94:1 | LL | / pub enum PubSeall { LL | | WithOutCake, diff --git a/tests/ui/enums_clike.rs b/tests/ui/enums_clike.rs index 9c1cf8e8614..789542b1351 100644 --- a/tests/ui/enums_clike.rs +++ b/tests/ui/enums_clike.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // ignore-x86 #![warn(clippy::all)] diff --git a/tests/ui/enums_clike.stderr b/tests/ui/enums_clike.stderr index f883529b996..c3390405094 100644 --- a/tests/ui/enums_clike.stderr +++ b/tests/ui/enums_clike.stderr @@ -1,5 +1,5 @@ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:17:5 + --> $DIR/enums_clike.rs:8:5 | LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ @@ -7,43 +7,43 @@ LL | X = 0x1_0000_0000, = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:24:5 + --> $DIR/enums_clike.rs:15:5 | LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:27:5 + --> $DIR/enums_clike.rs:18:5 | LL | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:34:5 + --> $DIR/enums_clike.rs:25:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:35:5 + --> $DIR/enums_clike.rs:26:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:37:5 + --> $DIR/enums_clike.rs:28:5 | LL | C = (std::i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:43:5 + --> $DIR/enums_clike.rs:34:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets - --> $DIR/enums_clike.rs:44:5 + --> $DIR/enums_clike.rs:35:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 020c7d795a4..cc0935ddb79 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[rustfmt::skip] #[warn(clippy::eq_op)] #[allow(clippy::identity_op, clippy::double_parens, clippy::many_single_char_names)] diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index a1a257095c2..2dabaf0d4db 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/eq_op.rs:44:5 + --> $DIR/eq_op.rs:35:5 | LL | true && true; | ^^^^^^^^^^^^ help: try: `true` @@ -7,37 +7,37 @@ LL | true && true; = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:37:5 | LL | true || true; | ^^^^^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:52:5 + --> $DIR/eq_op.rs:43:5 | LL | a == b && b == a; | ^^^^^^^^^^^^^^^^ help: try: `a == b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:53:5 + --> $DIR/eq_op.rs:44:5 | LL | a != b && b != a; | ^^^^^^^^^^^^^^^^ help: try: `a != b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:54:5 + --> $DIR/eq_op.rs:45:5 | LL | a < b && b > a; | ^^^^^^^^^^^^^^ help: try: `a < b` error: this boolean expression can be simplified - --> $DIR/eq_op.rs:55:5 + --> $DIR/eq_op.rs:46:5 | LL | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ help: try: `a <= b` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:17:5 + --> $DIR/eq_op.rs:8:5 | LL | 1 == 1; | ^^^^^^ @@ -45,157 +45,157 @@ LL | 1 == 1; = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:18:5 + --> $DIR/eq_op.rs:9:5 | LL | "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:20:5 + --> $DIR/eq_op.rs:11:5 | LL | false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:21:5 + --> $DIR/eq_op.rs:12:5 | LL | 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:22:5 + --> $DIR/eq_op.rs:13:5 | LL | 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:25:5 + --> $DIR/eq_op.rs:16:5 | LL | (1 as u64) & (1 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:26:5 + --> $DIR/eq_op.rs:17:5 | LL | 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:29:5 + --> $DIR/eq_op.rs:20:5 | LL | (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:30:5 + --> $DIR/eq_op.rs:21:5 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:30:6 + --> $DIR/eq_op.rs:21:6 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:30:27 + --> $DIR/eq_op.rs:21:27 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:31:5 + --> $DIR/eq_op.rs:22:5 | LL | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:34:5 + --> $DIR/eq_op.rs:25:5 | LL | ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:35:5 + --> $DIR/eq_op.rs:26:5 | LL | ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:39:5 + --> $DIR/eq_op.rs:30:5 | LL | 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:40:5 + --> $DIR/eq_op.rs:31:5 | LL | 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:40:5 + --> $DIR/eq_op.rs:31:5 | LL | 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:42:5 + --> $DIR/eq_op.rs:33:5 | LL | 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:43:5 + --> $DIR/eq_op.rs:34:5 | LL | 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:44:5 + --> $DIR/eq_op.rs:35:5 | LL | true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:37:5 | LL | true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:52:5 + --> $DIR/eq_op.rs:43:5 | LL | a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:53:5 + --> $DIR/eq_op.rs:44:5 | LL | a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:54:5 + --> $DIR/eq_op.rs:45:5 | LL | a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:55:5 + --> $DIR/eq_op.rs:46:5 | LL | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:58:5 + --> $DIR/eq_op.rs:49:5 | LL | a == a; | ^^^^^^ error: taken reference of right operand - --> $DIR/eq_op.rs:96:13 + --> $DIR/eq_op.rs:87:13 | LL | let z = x & &y; | ^^^^-- @@ -205,7 +205,7 @@ LL | let z = x & &y; = note: `-D clippy::op-ref` implied by `-D warnings` error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:104:20 + --> $DIR/eq_op.rs:95:20 | LL | const D: u32 = A / A; | ^^^^^ diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index d7166213194..1540062a4bc 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(clippy::no_effect)] #[warn(clippy::erasing_op)] fn main() { diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 85548eefba7..e54ce85f98e 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -1,5 +1,5 @@ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:15:5 + --> $DIR/erasing_op.rs:6:5 | LL | x * 0; | ^^^^^ @@ -7,13 +7,13 @@ LL | x * 0; = note: `-D clippy::erasing-op` implied by `-D warnings` error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:16:5 + --> $DIR/erasing_op.rs:7:5 | LL | 0 & x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> $DIR/erasing_op.rs:17:5 + --> $DIR/erasing_op.rs:8:5 | LL | 0 / x; | ^^^^^ diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs index cc65c6e6306..f582596eb56 100644 --- a/tests/ui/escape_analysis.rs +++ b/tests/ui/escape_analysis.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(box_syntax)] #![allow(clippy::borrowed_box, clippy::needless_pass_by_value, clippy::unused_unit)] #![warn(clippy::boxed_local)] diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr index ed7819ed429..8af211f8a1a 100644 --- a/tests/ui/escape_analysis.stderr +++ b/tests/ui/escape_analysis.stderr @@ -1,5 +1,5 @@ error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:43:13 + --> $DIR/escape_analysis.rs:34:13 | LL | fn warn_arg(x: Box) { | ^ @@ -7,7 +7,7 @@ LL | fn warn_arg(x: Box) { = note: `-D clippy::boxed-local` implied by `-D warnings` error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:134:12 + --> $DIR/escape_analysis.rs:125:12 | LL | pub fn new(_needs_name: Box>) -> () {} | ^^^^^^^^^^^ diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 7b39d1c4054..b39de4c15a4 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( unused, clippy::no_effect, diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index fb7daba1578..218e46b40a8 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure found - --> $DIR/eta.rs:22:27 + --> $DIR/eta.rs:13:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` @@ -7,19 +7,19 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:23:10 + --> $DIR/eta.rs:14:10 | LL | meta(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` error: redundant closure found - --> $DIR/eta.rs:24:27 + --> $DIR/eta.rs:15:27 | LL | let c = Some(1u8).map(|a| {1+2; foo}(a)); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/eta.rs:26:21 + --> $DIR/eta.rs:17:21 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` @@ -27,7 +27,7 @@ LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:33:27 + --> $DIR/eta.rs:24:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` diff --git a/tests/ui/eval_order_dependence.rs b/tests/ui/eval_order_dependence.rs index 82110d5e4f3..d806bc6d401 100644 --- a/tests/ui/eval_order_dependence.rs +++ b/tests/ui/eval_order_dependence.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::eval_order_dependence)] #[allow( unused_assignments, diff --git a/tests/ui/eval_order_dependence.stderr b/tests/ui/eval_order_dependence.stderr index 929650a7da8..8f4fa2228f7 100644 --- a/tests/ui/eval_order_dependence.stderr +++ b/tests/ui/eval_order_dependence.stderr @@ -1,48 +1,48 @@ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:24:9 + --> $DIR/eval_order_dependence.rs:15:9 | LL | } + x; | ^ | = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:22:9 + --> $DIR/eval_order_dependence.rs:13:9 | LL | x = 1; | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:27:5 + --> $DIR/eval_order_dependence.rs:18:5 | LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:28:9 + --> $DIR/eval_order_dependence.rs:19:9 | LL | x = 20; | ^^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:40:12 + --> $DIR/eval_order_dependence.rs:31:12 | LL | a: x, | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:42:13 + --> $DIR/eval_order_dependence.rs:33:13 | LL | x = 6; | ^^^^^ error: unsequenced read of a variable - --> $DIR/eval_order_dependence.rs:49:9 + --> $DIR/eval_order_dependence.rs:40:9 | LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:50:13 + --> $DIR/eval_order_dependence.rs:41:13 | LL | x = 20; | ^^^^^^ diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 59b252a3a80..d5fa903c23f 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::excessive_precision)] #![allow(clippy::print_literal)] diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 57c33c4719b..da8d9471bcc 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,5 +1,5 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:23:26 + --> $DIR/excessive_precision.rs:14:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` @@ -7,103 +7,103 @@ LL | const BAD32_1: f32 = 0.123_456_789_f32; = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:24:26 + --> $DIR/excessive_precision.rs:15:26 | LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:25:26 + --> $DIR/excessive_precision.rs:16:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:26:29 + --> $DIR/excessive_precision.rs:17:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:28:26 + --> $DIR/excessive_precision.rs:19:26 | LL | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:29:26 + --> $DIR/excessive_precision.rs:20:26 | LL | const BAD64_2: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:30:26 + --> $DIR/excessive_precision.rs:21:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:33:22 + --> $DIR/excessive_precision.rs:24:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:44:22 + --> $DIR/excessive_precision.rs:35:22 | LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:45:26 + --> $DIR/excessive_precision.rs:36:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:46:21 + --> $DIR/excessive_precision.rs:37:21 | LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:22 + --> $DIR/excessive_precision.rs:39:22 | LL | let bad64: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:49:26 + --> $DIR/excessive_precision.rs:40:26 | LL | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:50:21 + --> $DIR/excessive_precision.rs:41:21 | LL | let bad64_inf = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:56:36 + --> $DIR/excessive_precision.rs:47:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:57:36 + --> $DIR/excessive_precision.rs:48:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:61:24 + --> $DIR/excessive_precision.rs:52:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:64:27 + --> $DIR/excessive_precision.rs:55:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 8afffa4d843..0f930f6a8a2 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::expect_fun_call)] #![allow(clippy::useless_format)] diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 72a6995c1ce..09844e29911 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:36:26 + --> $DIR/expect_fun_call.rs:27:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` @@ -7,31 +7,31 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:39:26 + --> $DIR/expect_fun_call.rs:30:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:49:25 + --> $DIR/expect_fun_call.rs:40:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:52:25 + --> $DIR/expect_fun_call.rs:43:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:67:17 + --> $DIR/expect_fun_call.rs:58:17 | LL | Some("foo").expect({ &format!("error") }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:68:17 + --> $DIR/expect_fun_call.rs:59:17 | LL | Some("foo").expect(format!("error").as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 75d905659d9..5efac85cf22 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::explicit_counter_loop)] fn main() { diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index caccaee84b9..b1cfb31432f 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -1,5 +1,5 @@ error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:15:15 + --> $DIR/explicit_counter_loop.rs:6:15 | LL | for _v in &vec { | ^^^^ @@ -7,19 +7,19 @@ LL | for _v in &vec { = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:21:15 + --> $DIR/explicit_counter_loop.rs:12:15 | LL | for _v in &vec { | ^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:60:19 + --> $DIR/explicit_counter_loop.rs:51:19 | LL | for ch in text.chars() { | ^^^^^^^^^^^^ error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators - --> $DIR/explicit_counter_loop.rs:71:19 + --> $DIR/explicit_counter_loop.rs:62:19 | LL | for ch in text.chars() { | ^^^^^^^^^^^^ diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 01a63b3a95f..6231a0b0588 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::explicit_write)] fn stdout() -> String { diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 1072d9bd0d2..5fd2f8a3abf 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,5 +1,5 @@ error: use of `write!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:24:9 + --> $DIR/explicit_write.rs:15:9 | LL | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` @@ -7,43 +7,43 @@ LL | write!(std::io::stdout(), "test").unwrap(); = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:25:9 + --> $DIR/explicit_write.rs:16:9 | LL | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:26:9 + --> $DIR/explicit_write.rs:17:9 | LL | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:27:9 + --> $DIR/explicit_write.rs:18:9 | LL | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:28:9 + --> $DIR/explicit_write.rs:19:9 | LL | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:29:9 + --> $DIR/explicit_write.rs:20:9 | LL | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:32:9 + --> $DIR/explicit_write.rs:23:9 | LL | writeln!(std::io::stdout(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:33:9 + --> $DIR/explicit_write.rs:24:9 | LL | writeln!(std::io::stderr(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index 0d8c369660b..679f4a7dc35 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::fallible_impl_from)] // docs example diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 55efac7951a..8b847df65cd 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -1,5 +1,5 @@ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:14:1 + --> $DIR/fallible_impl_from.rs:5:1 | LL | / impl From for Foo { LL | | fn from(s: String) -> Self { @@ -9,19 +9,19 @@ LL | | } | |_^ | note: lint level defined here - --> $DIR/fallible_impl_from.rs:10:9 + --> $DIR/fallible_impl_from.rs:1:9 | LL | #![deny(clippy::fallible_impl_from)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:16:13 + --> $DIR/fallible_impl_from.rs:7:13 | LL | Foo(s.parse().unwrap()) | ^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:35:1 + --> $DIR/fallible_impl_from.rs:26:1 | LL | / impl From for Invalid { LL | | fn from(i: usize) -> Invalid { @@ -34,14 +34,14 @@ LL | | } | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:38:13 + --> $DIR/fallible_impl_from.rs:29:13 | LL | panic!(); | ^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:44:1 + --> $DIR/fallible_impl_from.rs:35:1 | LL | / impl From> for Invalid { LL | | fn from(s: Option) -> Invalid { @@ -54,7 +54,7 @@ LL | | } | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:46:17 + --> $DIR/fallible_impl_from.rs:37:17 | LL | let s = s.unwrap(); | ^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | panic!("{:?}", s); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> $DIR/fallible_impl_from.rs:62:1 + --> $DIR/fallible_impl_from.rs:53:1 | LL | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { LL | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { @@ -81,7 +81,7 @@ LL | | } | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail. note: potential failure(s) - --> $DIR/fallible_impl_from.rs:64:12 + --> $DIR/fallible_impl_from.rs:55:12 | LL | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/filter_methods.rs b/tests/ui/filter_methods.rs index 7ca74fd4b99..ef434245fd7 100644 --- a/tests/ui/filter_methods.rs +++ b/tests/ui/filter_methods.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr index c10d673148a..9dfd91f6d64 100644 --- a/tests/ui/filter_methods.stderr +++ b/tests/ui/filter_methods.stderr @@ -1,5 +1,5 @@ error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:14:21 + --> $DIR/filter_methods.rs:5:21 | LL | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * = note: `-D clippy::filter-map` implied by `-D warnings` error: called `filter(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:16:21 + --> $DIR/filter_methods.rs:7:21 | LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ @@ -17,7 +17,7 @@ LL | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________^ error: called `filter_map(p).flat_map(q)` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` and filtering by returning an empty Iterator. - --> $DIR/filter_methods.rs:22:21 + --> $DIR/filter_methods.rs:13:21 | LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ @@ -27,7 +27,7 @@ LL | | .flat_map(|x| x.checked_mul(2)) | |_______________________________________^ error: called `filter_map(p).map(q)` on an `Iterator`. This is more succinctly expressed by only calling `.filter_map(..)` instead. - --> $DIR/filter_methods.rs:28:21 + --> $DIR/filter_methods.rs:19:21 | LL | let _: Vec<_> = vec![5_i8; 6] | _____________________^ diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 2d55e30a2d3..92d38527bbf 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::float_cmp)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index bdbbccee714..ddaf4b82497 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,36 +1,36 @@ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:69:5 + --> $DIR/float_cmp.rs:60:5 | LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error` | = note: `-D clippy::float-cmp` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:69:5 + --> $DIR/float_cmp.rs:60:5 | LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:74:5 + --> $DIR/float_cmp.rs:65:5 | LL | x == 1.0; | ^^^^^^^^ help: consider comparing them within some error: `(x - 1.0).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:74:5 + --> $DIR/float_cmp.rs:65:5 | LL | x == 1.0; | ^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:77:5 + --> $DIR/float_cmp.rs:68:5 | LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(x) - twice(ONE as f64)).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp.rs:77:5 + --> $DIR/float_cmp.rs:68:5 | LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index e02671e0dcc..887275c5e88 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::float_cmp_const)] #![allow(clippy::float_cmp)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index 2b434f31814..9ec921e536a 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -1,84 +1,84 @@ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:27:5 + --> $DIR/float_cmp_const.rs:18:5 | LL | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | = note: `-D clippy::float-cmp-const` implied by `-D warnings` note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:27:5 + --> $DIR/float_cmp_const.rs:18:5 | LL | 1f32 == ONE; | ^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:28:5 + --> $DIR/float_cmp_const.rs:19:5 | LL | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:28:5 + --> $DIR/float_cmp_const.rs:19:5 | LL | TWO == ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:29:5 + --> $DIR/float_cmp_const.rs:20:5 | LL | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:29:5 + --> $DIR/float_cmp_const.rs:20:5 | LL | TWO != ONE; | ^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:30:5 + --> $DIR/float_cmp_const.rs:21:5 | LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:30:5 + --> $DIR/float_cmp_const.rs:21:5 | LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:31:5 + --> $DIR/float_cmp_const.rs:22:5 | LL | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(1 as f32 - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:31:5 + --> $DIR/float_cmp_const.rs:22:5 | LL | 1 as f32 == ONE; | ^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:34:5 + --> $DIR/float_cmp_const.rs:25:5 | LL | v == ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:34:5 + --> $DIR/float_cmp_const.rs:25:5 | LL | v == ONE; | ^^^^^^^^ error: strict comparison of f32 or f64 constant - --> $DIR/float_cmp_const.rs:35:5 + --> $DIR/float_cmp_const.rs:26:5 | LL | v != ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | note: std::f32::EPSILON and std::f64::EPSILON are available. - --> $DIR/float_cmp_const.rs:35:5 + --> $DIR/float_cmp_const.rs:26:5 | LL | v != ONE; | ^^^^^^^^ diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 9b48a965cb3..21573af870a 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // only-64bit #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index 16605fd344a..e9549e157cd 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -1,5 +1,5 @@ error: casting function pointer `foo` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:19:13 + --> $DIR/fn_to_numeric_cast.rs:10:13 | LL | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` @@ -7,19 +7,19 @@ LL | let _ = foo as i8; = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` error: casting function pointer `foo` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:20:13 + --> $DIR/fn_to_numeric_cast.rs:11:13 | LL | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:21:13 + --> $DIR/fn_to_numeric_cast.rs:12:13 | LL | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i64` - --> $DIR/fn_to_numeric_cast.rs:22:13 + --> $DIR/fn_to_numeric_cast.rs:13:13 | LL | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` @@ -27,115 +27,115 @@ LL | let _ = foo as i64; = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` error: casting function pointer `foo` to `i128` - --> $DIR/fn_to_numeric_cast.rs:23:13 + --> $DIR/fn_to_numeric_cast.rs:14:13 | LL | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> $DIR/fn_to_numeric_cast.rs:24:13 + --> $DIR/fn_to_numeric_cast.rs:15:13 | LL | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:26:13 + --> $DIR/fn_to_numeric_cast.rs:17:13 | LL | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:27:13 + --> $DIR/fn_to_numeric_cast.rs:18:13 | LL | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:28:13 + --> $DIR/fn_to_numeric_cast.rs:19:13 | LL | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> $DIR/fn_to_numeric_cast.rs:29:13 + --> $DIR/fn_to_numeric_cast.rs:20:13 | LL | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> $DIR/fn_to_numeric_cast.rs:30:13 + --> $DIR/fn_to_numeric_cast.rs:21:13 | LL | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:43:13 + --> $DIR/fn_to_numeric_cast.rs:34:13 | LL | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:44:13 + --> $DIR/fn_to_numeric_cast.rs:35:13 | LL | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:45:13 + --> $DIR/fn_to_numeric_cast.rs:36:13 | LL | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> $DIR/fn_to_numeric_cast.rs:46:13 + --> $DIR/fn_to_numeric_cast.rs:37:13 | LL | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> $DIR/fn_to_numeric_cast.rs:47:13 + --> $DIR/fn_to_numeric_cast.rs:38:13 | LL | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> $DIR/fn_to_numeric_cast.rs:48:13 + --> $DIR/fn_to_numeric_cast.rs:39:13 | LL | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:50:13 + --> $DIR/fn_to_numeric_cast.rs:41:13 | LL | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:51:13 + --> $DIR/fn_to_numeric_cast.rs:42:13 | LL | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:52:13 + --> $DIR/fn_to_numeric_cast.rs:43:13 | LL | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> $DIR/fn_to_numeric_cast.rs:53:13 + --> $DIR/fn_to_numeric_cast.rs:44:13 | LL | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> $DIR/fn_to_numeric_cast.rs:54:13 + --> $DIR/fn_to_numeric_cast.rs:45:13 | LL | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32`, which truncates the value - --> $DIR/fn_to_numeric_cast.rs:61:5 + --> $DIR/fn_to_numeric_cast.rs:52:5 | LL | f as i32 | ^^^^^^^^ help: try: `f as usize` diff --git a/tests/ui/for_kv_map.rs b/tests/ui/for_kv_map.rs index 549187756ab..39a8d960a7e 100644 --- a/tests/ui/for_kv_map.rs +++ b/tests/ui/for_kv_map.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::for_kv_map)] #![allow(clippy::used_underscore_binding)] diff --git a/tests/ui/for_kv_map.stderr b/tests/ui/for_kv_map.stderr index 7b65c58f58d..ebe758526ec 100644 --- a/tests/ui/for_kv_map.stderr +++ b/tests/ui/for_kv_map.stderr @@ -1,5 +1,5 @@ error: you seem to want to iterate on a map's values - --> $DIR/for_kv_map.rs:18:19 + --> $DIR/for_kv_map.rs:9:19 | LL | for (_, v) in &m { | ^^ @@ -11,7 +11,7 @@ LL | for v in m.values() { | ^ ^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_kv_map.rs:23:19 + --> $DIR/for_kv_map.rs:14:19 | LL | for (_, v) in &*m { | ^^^ @@ -21,7 +21,7 @@ LL | for v in (*m).values() { | ^ ^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_kv_map.rs:31:19 + --> $DIR/for_kv_map.rs:22:19 | LL | for (_, v) in &mut m { | ^^^^^^ @@ -31,7 +31,7 @@ LL | for v in m.values_mut() { | ^ ^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's values - --> $DIR/for_kv_map.rs:36:19 + --> $DIR/for_kv_map.rs:27:19 | LL | for (_, v) in &mut *m { | ^^^^^^^ @@ -41,7 +41,7 @@ LL | for v in (*m).values_mut() { | ^ ^^^^^^^^^^^^^^^^^ error: you seem to want to iterate on a map's keys - --> $DIR/for_kv_map.rs:42:24 + --> $DIR/for_kv_map.rs:33:24 | LL | for (k, _value) in rm { | ^^ diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index c172b0b3b77..f73bb41a9bb 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::*; use std::rc::Rc; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 4ded425b321..50f10d6187b 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:50:14 + --> $DIR/for_loop.rs:41:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:59:14 + --> $DIR/for_loop.rs:50:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | for in &vec { | ^^^^^^ ^^^^ error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:64:14 + --> $DIR/for_loop.rs:55:14 | LL | for j in 0..4 { | ^^^^ @@ -31,7 +31,7 @@ LL | for in &STATIC { | ^^^^^^ ^^^^^^^ error: the loop variable `j` is only used to index `CONST`. - --> $DIR/for_loop.rs:68:14 + --> $DIR/for_loop.rs:59:14 | LL | for j in 0..4 { | ^^^^ @@ -41,7 +41,7 @@ LL | for in &CONST { | ^^^^^^ ^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:72:14 + --> $DIR/for_loop.rs:63:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:80:14 + --> $DIR/for_loop.rs:71:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | for in vec2.iter().take(vec.len()) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:84:14 + --> $DIR/for_loop.rs:75:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | for in vec.iter().skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:88:14 + --> $DIR/for_loop.rs:79:14 | LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | for in vec.iter().take(MAX_LEN) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:92:14 + --> $DIR/for_loop.rs:83:14 | LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:96:14 + --> $DIR/for_loop.rs:87:14 | LL | for i in 5..10 { | ^^^^^ @@ -101,7 +101,7 @@ LL | for in vec.iter().take(10).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:100:14 + --> $DIR/for_loop.rs:91:14 | LL | for i in 5..=10 { | ^^^^^^ @@ -111,7 +111,7 @@ LL | for in vec.iter().take(10 + 1).skip(5) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:104:14 + --> $DIR/for_loop.rs:95:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | for (i, ) in vec.iter().enumerate().skip(5) { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:108:14 + --> $DIR/for_loop.rs:99:14 | LL | for i in 5..10 { | ^^^^^ @@ -131,7 +131,7 @@ LL | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:112:14 + --> $DIR/for_loop.rs:103:14 | LL | for i in 10..0 { | ^^^^^ @@ -143,7 +143,7 @@ LL | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:116:14 + --> $DIR/for_loop.rs:107:14 | LL | for i in 10..=0 { | ^^^^^^ @@ -153,7 +153,7 @@ LL | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:120:14 + --> $DIR/for_loop.rs:111:14 | LL | for i in MAX_LEN..0 { | ^^^^^^^^^^ @@ -163,13 +163,13 @@ LL | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:124:14 + --> $DIR/for_loop.rs:115:14 | LL | for i in 5..5 { | ^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:149:14 + --> $DIR/for_loop.rs:140:14 | LL | for i in 10..5 + 4 { | ^^^^^^^^^ @@ -179,7 +179,7 @@ LL | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:153:14 + --> $DIR/for_loop.rs:144:14 | LL | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ @@ -189,13 +189,13 @@ LL | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:157:14 + --> $DIR/for_loop.rs:148:14 | LL | for i in (5 + 2)..(8 - 1) { | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:179:15 + --> $DIR/for_loop.rs:170:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -203,13 +203,13 @@ LL | for _v in vec.iter() {} = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:181:15 + --> $DIR/for_loop.rs:172:15 | LL | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:184:15 + --> $DIR/for_loop.rs:175:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -217,67 +217,67 @@ LL | for _v in out_vec.into_iter() {} = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:187:15 + --> $DIR/for_loop.rs:178:15 | LL | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:192:15 + --> $DIR/for_loop.rs:183:15 | LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:196:15 + --> $DIR/for_loop.rs:187:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:201:15 + --> $DIR/for_loop.rs:192:15 | LL | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:204:15 + --> $DIR/for_loop.rs:195:15 | LL | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:207:15 + --> $DIR/for_loop.rs:198:15 | LL | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:210:15 + --> $DIR/for_loop.rs:201:15 | LL | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:213:15 + --> $DIR/for_loop.rs:204:15 | LL | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:216:15 + --> $DIR/for_loop.rs:207:15 | LL | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:219:15 + --> $DIR/for_loop.rs:210:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:221:15 + --> $DIR/for_loop.rs:212:15 | LL | for _v in vec.iter().next() {} | ^^^^^^^^^^^^^^^^^ @@ -285,7 +285,7 @@ LL | for _v in vec.iter().next() {} = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:228:5 + --> $DIR/for_loop.rs:219:5 | LL | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -293,7 +293,7 @@ LL | vec.iter().cloned().map(|x| out.push(x)).collect::>(); = note: `-D clippy::unused-collect` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:372:14 + --> $DIR/for_loop.rs:363:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` @@ -301,31 +301,31 @@ LL | for i in 0..src.len() { = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:377:14 + --> $DIR/for_loop.rs:368:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:382:14 + --> $DIR/for_loop.rs:373:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:387:14 + --> $DIR/for_loop.rs:378:14 | LL | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:392:14 + --> $DIR/for_loop.rs:383:14 | LL | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:405:14 + --> $DIR/for_loop.rs:396:14 | LL | for i in 10..256 { | ^^^^^^^ @@ -336,31 +336,31 @@ LL | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:417:14 + --> $DIR/for_loop.rs:408:14 | LL | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:430:14 + --> $DIR/for_loop.rs:421:14 | LL | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:459:14 + --> $DIR/for_loop.rs:450:14 | LL | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:463:14 + --> $DIR/for_loop.rs:454:14 | LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:470:14 + --> $DIR/for_loop.rs:461:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` diff --git a/tests/ui/for_loop_over_option_result.rs b/tests/ui/for_loop_over_option_result.rs index 37fd4e6d038..6b207b26b6b 100644 --- a/tests/ui/for_loop_over_option_result.rs +++ b/tests/ui/for_loop_over_option_result.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::for_loop_over_option, clippy::for_loop_over_result)] /// Tests for_loop_over_result and for_loop_over_option diff --git a/tests/ui/for_loop_over_option_result.stderr b/tests/ui/for_loop_over_option_result.stderr index f8a4212b253..5414bfcf9de 100644 --- a/tests/ui/for_loop_over_option_result.stderr +++ b/tests/ui/for_loop_over_option_result.stderr @@ -1,5 +1,5 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:20:14 + --> $DIR/for_loop_over_option_result.rs:11:14 | LL | for x in option { | ^^^^^^ @@ -8,7 +8,7 @@ LL | for x in option { = help: consider replacing `for x in option` with `if let Some(x) = option` error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:25:14 + --> $DIR/for_loop_over_option_result.rs:16:14 | LL | for x in result { | ^^^^^^ @@ -17,7 +17,7 @@ LL | for x in result { = help: consider replacing `for x in result` with `if let Ok(x) = result` error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:29:14 + --> $DIR/for_loop_over_option_result.rs:20:14 | LL | for x in option.ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | for x in option.ok_or("x not found") { = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_over_option_result.rs:35:14 + --> $DIR/for_loop_over_option_result.rs:26:14 | LL | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for x in v.iter().next() { = note: #[deny(clippy::iter_next_loop)] on by default error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:40:14 + --> $DIR/for_loop_over_option_result.rs:31:14 | LL | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | for x in v.iter().next().and(Some(0)) { = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:44:14 + --> $DIR/for_loop_over_option_result.rs:35:14 | LL | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | for x in v.iter().next().ok_or("x not found") { = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop_over_option_result.rs:56:5 + --> $DIR/for_loop_over_option_result.rs:47:5 | LL | / while let Some(x) = option { LL | | println!("{}", x); @@ -60,7 +60,7 @@ LL | | } = note: #[deny(clippy::never_loop)] on by default error: this loop never actually loops - --> $DIR/for_loop_over_option_result.rs:62:5 + --> $DIR/for_loop_over_option_result.rs:53:5 | LL | / while let Ok(x) = result { LL | | println!("{}", x); diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 6b1577e24ca..f2892c5b84a 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,13 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - #![allow(clippy::print_literal)] #![warn(clippy::useless_format)] diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 871fc8fba3e..d5f2711bb37 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,5 +1,5 @@ error: useless use of `format!` - --> $DIR/format.rs:21:5 + --> $DIR/format.rs:11:5 | LL | format!("foo"); | ^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` @@ -7,7 +7,7 @@ LL | format!("foo"); = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:23:5 + --> $DIR/format.rs:13:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` @@ -15,7 +15,7 @@ LL | format!("{}", "foo"); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:27:5 + --> $DIR/format.rs:17:5 | LL | format!("{:+}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` @@ -23,7 +23,7 @@ LL | format!("{:+}", "foo"); // warn when the format makes no difference = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:28:5 + --> $DIR/format.rs:18:5 | LL | format!("{:<}", "foo"); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()` @@ -31,7 +31,7 @@ LL | format!("{:<}", "foo"); // warn when the format makes no difference = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:33:5 + --> $DIR/format.rs:23:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` @@ -39,7 +39,7 @@ LL | format!("{}", arg); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:37:5 + --> $DIR/format.rs:27:5 | LL | format!("{:+}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` @@ -47,7 +47,7 @@ LL | format!("{:+}", arg); // warn when the format makes no difference = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:38:5 + --> $DIR/format.rs:28:5 | LL | format!("{:<}", arg); // warn when the format makes no difference | ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()` @@ -55,7 +55,7 @@ LL | format!("{:<}", arg); // warn when the format makes no difference = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:65:5 + --> $DIR/format.rs:55:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()` @@ -63,7 +63,7 @@ LL | format!("{}", 42.to_string()); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: useless use of `format!` - --> $DIR/format.rs:67:5 + --> $DIR/format.rs:57:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()` diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index b74f778b129..904c05b068c 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(unused_variables)] #![allow(unused_assignments)] diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 061540b9aa5..3d723ce71b9 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,5 +1,5 @@ error: this looks like an `else {..}` but the `else` is missing - --> $DIR/formatting.rs:21:6 + --> $DIR/formatting.rs:12:6 | LL | } { | ^ @@ -8,7 +8,7 @@ LL | } { = note: to remove this lint, add the missing `else` or add a new line before the next block error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:25:6 + --> $DIR/formatting.rs:16:6 | LL | } if foo() { | ^ @@ -16,7 +16,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:32:10 + --> $DIR/formatting.rs:23:10 | LL | } if foo() { | ^ @@ -24,7 +24,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:40:10 + --> $DIR/formatting.rs:31:10 | LL | } if foo() { | ^ @@ -32,7 +32,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/formatting.rs:49:6 + --> $DIR/formatting.rs:40:6 | LL | } else | ______^ @@ -42,7 +42,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else {..}` but the formatting might hide it - --> $DIR/formatting.rs:54:6 + --> $DIR/formatting.rs:45:6 | LL | } | ______^ @@ -53,7 +53,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:60:6 + --> $DIR/formatting.rs:51:6 | LL | } else | ______^ @@ -63,7 +63,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:65:6 + --> $DIR/formatting.rs:56:6 | LL | } | ______^ @@ -74,7 +74,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:106:6 + --> $DIR/formatting.rs:97:6 | LL | a =- 35; | ^^^^ @@ -83,7 +83,7 @@ LL | a =- 35; = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:107:6 + --> $DIR/formatting.rs:98:6 | LL | a =* &191; | ^^^^ @@ -91,7 +91,7 @@ LL | a =* &191; = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:110:6 + --> $DIR/formatting.rs:101:6 | LL | b =! false; | ^^^^ @@ -99,7 +99,7 @@ LL | b =! false; = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:119:19 + --> $DIR/formatting.rs:110:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -108,7 +108,7 @@ LL | -1, -2, -3 // <= no comma here = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:123:19 + --> $DIR/formatting.rs:114:19 | LL | -1, -2, -3 // <= no comma here | ^ diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 41963294815..500576d1dff 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(dead_code)] #![allow(unused_unsafe)] diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index b23d09309bb..150b50d9a7c 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -1,5 +1,5 @@ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:17:1 + --> $DIR/functions.rs:8:1 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f = note: `-D clippy::too-many-arguments` implied by `-D warnings` error: this function has too many arguments (8/7) - --> $DIR/functions.rs:34:5 + --> $DIR/functions.rs:25:5 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:43:5 + --> $DIR/functions.rs:34:5 | LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:52:34 + --> $DIR/functions.rs:43:34 | LL | println!("{}", unsafe { *p }); | ^ @@ -27,49 +27,49 @@ LL | println!("{}", unsafe { *p }); = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:53:35 + --> $DIR/functions.rs:44:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:54:33 + --> $DIR/functions.rs:45:33 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:65:30 + --> $DIR/functions.rs:56:30 | LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:66:31 + --> $DIR/functions.rs:57:31 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:67:29 + --> $DIR/functions.rs:58:29 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:76:34 + --> $DIR/functions.rs:67:34 | LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:77:35 + --> $DIR/functions.rs:68:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:78:33 + --> $DIR/functions.rs:69:33 | LL | unsafe { std::ptr::read(p) }; | ^ diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs index 2299714132f..7d6cb4e1179 100644 --- a/tests/ui/fxhash.rs +++ b/tests/ui/fxhash.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::default_hash_types)] #![feature(rustc_private)] diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr index 14fc4a8090b..a2dac670018 100644 --- a/tests/ui/fxhash.stderr +++ b/tests/ui/fxhash.stderr @@ -1,5 +1,5 @@ error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:16:24 + --> $DIR/fxhash.rs:7:24 | LL | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashMap` @@ -7,31 +7,31 @@ LL | use std::collections::{HashMap, HashSet}; = note: `-D clippy::default-hash-types` implied by `-D warnings` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:16:33 + --> $DIR/fxhash.rs:7:33 | LL | use std::collections::{HashMap, HashSet}; | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:19:15 + --> $DIR/fxhash.rs:10:15 | LL | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:19:41 + --> $DIR/fxhash.rs:10:41 | LL | let _map: HashMap = HashMap::default(); | ^^^^^^^ help: use: `FxHashMap` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:20:15 + --> $DIR/fxhash.rs:11:15 | LL | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:20:33 + --> $DIR/fxhash.rs:11:33 | LL | let _set: HashSet = HashSet::default(); | ^^^^^^^ help: use: `FxHashSet` diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 021c0c2ff44..f9d52286355 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![allow(unused_mut)] diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index b041ba7b7c7..244a2ef25a1 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![allow(unused_mut)] diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index d4f699f5a72..dd3a5c68e0a 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,5 +1,5 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:42:17 + --> $DIR/get_unwrap.rs:33:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` @@ -7,73 +7,73 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::get-unwrap` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:43:17 + --> $DIR/get_unwrap.rs:34:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:44:17 + --> $DIR/get_unwrap.rs:35:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:45:17 + --> $DIR/get_unwrap.rs:36:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:46:17 + --> $DIR/get_unwrap.rs:37:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:47:17 + --> $DIR/get_unwrap.rs:38:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:50:21 + --> $DIR/get_unwrap.rs:41:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:55:9 + --> $DIR/get_unwrap.rs:46:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:56:9 + --> $DIR/get_unwrap.rs:47:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:57:9 + --> $DIR/get_unwrap.rs:48:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:58:9 + --> $DIR/get_unwrap.rs:49:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:67:17 + --> $DIR/get_unwrap.rs:58:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:68:17 + --> $DIR/get_unwrap.rs:59:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` diff --git a/tests/ui/ice-2636.rs b/tests/ui/ice-2636.rs index caf8c89390d..e0b58157590 100644 --- a/tests/ui/ice-2636.rs +++ b/tests/ui/ice-2636.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] enum Foo { diff --git a/tests/ui/ice-2636.stderr b/tests/ui/ice-2636.stderr index a6b150f9b90..aba8be4adcc 100644 --- a/tests/ui/ice-2636.stderr +++ b/tests/ui/ice-2636.stderr @@ -1,5 +1,5 @@ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/ice-2636.rs:21:9 + --> $DIR/ice-2636.rs:12:9 | LL | / match $foo { LL | | $ ( & $t => $ord, diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 6ba191b0b84..6491518af6c 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::identity_conversion)] fn test_generic(val: T) -> T { diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 4b0b958e285..73a1996180b 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,65 +1,65 @@ error: identical conversion - --> $DIR/identity_conversion.rs:13:13 + --> $DIR/identity_conversion.rs:4:13 | LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: lint level defined here - --> $DIR/identity_conversion.rs:10:9 + --> $DIR/identity_conversion.rs:1:9 | LL | #![deny(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion - --> $DIR/identity_conversion.rs:14:5 + --> $DIR/identity_conversion.rs:5:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion - --> $DIR/identity_conversion.rs:26:22 + --> $DIR/identity_conversion.rs:17:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:47:21 + --> $DIR/identity_conversion.rs:38:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:48:21 + --> $DIR/identity_conversion.rs:39:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:49:13 + --> $DIR/identity_conversion.rs:40:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:50:13 + --> $DIR/identity_conversion.rs:41:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion - --> $DIR/identity_conversion.rs:51:13 + --> $DIR/identity_conversion.rs:42:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion - --> $DIR/identity_conversion.rs:52:13 + --> $DIR/identity_conversion.rs:43:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: identical conversion - --> $DIR/identity_conversion.rs:53:21 + --> $DIR/identity_conversion.rs:44:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 299cd2a6786..ae2815d345a 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - const ONE: i64 = 1; const NEG_ONE: i64 = -1; const ZERO: i64 = 0; diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 8b42cfbf1ce..4742877706a 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,5 +1,5 @@ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:25:5 + --> $DIR/identity_op.rs:16:5 | LL | x + 0; | ^^^^^ @@ -7,43 +7,43 @@ LL | x + 0; = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:26:5 + --> $DIR/identity_op.rs:17:5 | LL | x + (1 - 1); | ^^^^^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:28:5 + --> $DIR/identity_op.rs:19:5 | LL | 0 + x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:31:5 + --> $DIR/identity_op.rs:22:5 | LL | x | (0); | ^^^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:34:5 + --> $DIR/identity_op.rs:25:5 | LL | x * 1; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:35:5 + --> $DIR/identity_op.rs:26:5 | LL | 1 * x; | ^^^^^ error: the operation is ineffective. Consider reducing it to `x` - --> $DIR/identity_op.rs:41:5 + --> $DIR/identity_op.rs:32:5 | LL | -1 & x; | ^^^^^^ error: the operation is ineffective. Consider reducing it to `u` - --> $DIR/identity_op.rs:44:5 + --> $DIR/identity_op.rs:35:5 | LL | u & 255; | ^^^^^^^ diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index 0179381fdc3..dc3fb1ceac9 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![warn(clippy::if_not_else)] diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index acdf543cc75..3694f5aec53 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -1,5 +1,5 @@ error: Unnecessary boolean `not` operation - --> $DIR/if_not_else.rs:18:5 + --> $DIR/if_not_else.rs:9:5 | LL | / if !bla() { LL | | println!("Bugs"); @@ -12,7 +12,7 @@ LL | | } = help: remove the `!` and swap the blocks of the if/else error: Unnecessary `!=` operation - --> $DIR/if_not_else.rs:23:5 + --> $DIR/if_not_else.rs:14:5 | LL | / if 4 != 5 { LL | | println!("Bugs"); diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 398a8ccce44..1c46e3a5337 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] #![warn(clippy::multiple_inherent_impl)] diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index 8bddd400f70..585d32845d2 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,5 +1,5 @@ error: Multiple implementations of this structure - --> $DIR/impl.rs:19:1 + --> $DIR/impl.rs:10:1 | LL | / impl MyStruct { LL | | fn second() {} @@ -8,7 +8,7 @@ LL | | } | = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` note: First implementation here - --> $DIR/impl.rs:15:1 + --> $DIR/impl.rs:6:1 | LL | / impl MyStruct { LL | | fn first() {} @@ -16,7 +16,7 @@ LL | | } | |_^ error: Multiple implementations of this structure - --> $DIR/impl.rs:33:5 + --> $DIR/impl.rs:24:5 | LL | / impl super::MyStruct { LL | | fn third() {} @@ -24,7 +24,7 @@ LL | | } | |_____^ | note: First implementation here - --> $DIR/impl.rs:15:1 + --> $DIR/impl.rs:6:1 | LL | / impl MyStruct { LL | | fn first() {} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index acd5a52ff38..064760e73f3 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] use std::cmp::Eq; diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 0c61dbc4c64..68e305f0cb4 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,5 +1,5 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:20:35 + --> $DIR/implicit_hasher.rs:11:35 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:29:36 + --> $DIR/implicit_hasher.rs:20:36 | LL | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:34:19 + --> $DIR/implicit_hasher.rs:25:19 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:51:32 + --> $DIR/implicit_hasher.rs:42:32 | LL | impl Foo for HashSet { | ^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:56:19 + --> $DIR/implicit_hasher.rs:47:19 | LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:73:23 + --> $DIR/implicit_hasher.rs:64:23 | LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | pub fn foo(_map: &mut HashMap, _s | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:73:53 + --> $DIR/implicit_hasher.rs:64:53 | LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | pub fn foo(_map: &mut HashMap, _set: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:77:43 + --> $DIR/implicit_hasher.rs:68:43 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:85:33 + --> $DIR/implicit_hasher.rs:76:33 | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | pub fn $name(_map: &mut HashMap $DIR/implicit_hasher.rs:85:63 + --> $DIR/implicit_hasher.rs:76:63 | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 46ead9bf0c5..0fe4a283abf 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::implicit_return)] fn test_end_of_fn() -> bool { diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 4c62a7d65c6..c07fced1259 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing return statement - --> $DIR/implicit_return.rs:17:5 + --> $DIR/implicit_return.rs:8:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -7,55 +7,55 @@ LL | true = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing return statement - --> $DIR/implicit_return.rs:23:9 + --> $DIR/implicit_return.rs:14:9 | LL | true | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:25:9 + --> $DIR/implicit_return.rs:16:9 | LL | false | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:33:17 + --> $DIR/implicit_return.rs:24:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:34:20 + --> $DIR/implicit_return.rs:25:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:41:9 + --> $DIR/implicit_return.rs:32:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:49:13 + --> $DIR/implicit_return.rs:40:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:58:13 + --> $DIR/implicit_return.rs:49:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:67:18 + --> $DIR/implicit_return.rs:58:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:68:16 + --> $DIR/implicit_return.rs:59:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index 31e34135bfc..529ab042610 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::inconsistent_digit_grouping)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index ba909b94480..9b903d1764f 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,5 +1,5 @@ error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:22:16 + --> $DIR/inconsistent_digit_grouping.rs:13:16 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` @@ -7,25 +7,25 @@ LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:22:26 + --> $DIR/inconsistent_digit_grouping.rs:13:26 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:22:38 + --> $DIR/inconsistent_digit_grouping.rs:13:38 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:22:48 + --> $DIR/inconsistent_digit_grouping.rs:13:48 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:22:64 + --> $DIR/inconsistent_digit_grouping.rs:13:64 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index a9e697e519f..f0bd39c0254 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(plugin)] #![warn(clippy::indexing_slicing)] #![warn(clippy::out_of_bounds_indexing)] diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 2e7bff3e0d5..129fec0e97c 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,5 +1,5 @@ error: index out of bounds: the len is 4 but the index is 4 - --> $DIR/indexing_slicing.rs:25:5 + --> $DIR/indexing_slicing.rs:16:5 | LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ @@ -7,25 +7,25 @@ LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on ar = note: #[deny(const_err)] on by default error: index out of bounds: the len is 4 but the index is 8 - --> $DIR/indexing_slicing.rs:26:5 + --> $DIR/indexing_slicing.rs:17:5 | LL | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^^ error: index out of bounds: the len is 0 but the index is 0 - --> $DIR/indexing_slicing.rs:56:5 + --> $DIR/indexing_slicing.rs:47:5 | LL | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^ error: index out of bounds: the len is 4 but the index is 15 - --> $DIR/indexing_slicing.rs:87:5 + --> $DIR/indexing_slicing.rs:78:5 | LL | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:20:5 + --> $DIR/indexing_slicing.rs:11:5 | LL | x[index]; | ^^^^^^^^ @@ -34,7 +34,7 @@ LL | x[index]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:21:6 + --> $DIR/indexing_slicing.rs:12:6 | LL | &x[index..]; | ^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | &x[index..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:22:6 + --> $DIR/indexing_slicing.rs:13:6 | LL | &x[..index]; | ^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | &x[..index]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:23:6 + --> $DIR/indexing_slicing.rs:14:6 | LL | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | &x[index_from..index_to]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:24:6 + --> $DIR/indexing_slicing.rs:15:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:24:6 + --> $DIR/indexing_slicing.rs:15:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from. = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:27:11 + --> $DIR/indexing_slicing.rs:18:11 | LL | &x[..=4]; | ^ @@ -82,13 +82,13 @@ LL | &x[..=4]; = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: range is out of bounds - --> $DIR/indexing_slicing.rs:28:11 + --> $DIR/indexing_slicing.rs:19:11 | LL | &x[1..5]; | ^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:29:6 + --> $DIR/indexing_slicing.rs:20:6 | LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^^^^^^^^^^^^ @@ -96,37 +96,37 @@ LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10 = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:29:8 + --> $DIR/indexing_slicing.rs:20:8 | LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:30:8 + --> $DIR/indexing_slicing.rs:21:8 | LL | &x[5..]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:31:10 + --> $DIR/indexing_slicing.rs:22:10 | LL | &x[..5]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:32:8 + --> $DIR/indexing_slicing.rs:23:8 | LL | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:33:12 + --> $DIR/indexing_slicing.rs:24:12 | LL | &x[0..=4]; | ^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:34:6 + --> $DIR/indexing_slicing.rs:25:6 | LL | &x[0..][..3]; | ^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | &x[0..][..3]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:35:6 + --> $DIR/indexing_slicing.rs:26:6 | LL | &x[1..][..5]; | ^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | &x[1..][..5]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:48:5 + --> $DIR/indexing_slicing.rs:39:5 | LL | y[0]; | ^^^^ @@ -150,7 +150,7 @@ LL | y[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:49:6 + --> $DIR/indexing_slicing.rs:40:6 | LL | &y[1..2]; | ^^^^^^^ @@ -158,7 +158,7 @@ LL | &y[1..2]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:50:6 + --> $DIR/indexing_slicing.rs:41:6 | LL | &y[0..=4]; | ^^^^^^^^ @@ -166,7 +166,7 @@ LL | &y[0..=4]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:51:6 + --> $DIR/indexing_slicing.rs:42:6 | LL | &y[..=4]; | ^^^^^^^ @@ -174,49 +174,49 @@ LL | &y[..=4]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:57:12 + --> $DIR/indexing_slicing.rs:48:12 | LL | &empty[1..5]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:58:16 + --> $DIR/indexing_slicing.rs:49:16 | LL | &empty[0..=4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:59:15 + --> $DIR/indexing_slicing.rs:50:15 | LL | &empty[..=4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:60:12 + --> $DIR/indexing_slicing.rs:51:12 | LL | &empty[1..]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:61:14 + --> $DIR/indexing_slicing.rs:52:14 | LL | &empty[..4]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:62:16 + --> $DIR/indexing_slicing.rs:53:16 | LL | &empty[0..=0]; | ^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:63:15 + --> $DIR/indexing_slicing.rs:54:15 | LL | &empty[..=0]; | ^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:71:5 + --> $DIR/indexing_slicing.rs:62:5 | LL | v[0]; | ^^^^ @@ -224,7 +224,7 @@ LL | v[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:72:5 + --> $DIR/indexing_slicing.rs:63:5 | LL | v[10]; | ^^^^^ @@ -232,7 +232,7 @@ LL | v[10]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:73:5 + --> $DIR/indexing_slicing.rs:64:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -240,7 +240,7 @@ LL | v[1 << 3]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:74:6 + --> $DIR/indexing_slicing.rs:65:6 | LL | &v[10..100]; | ^^^^^^^^^^ @@ -248,7 +248,7 @@ LL | &v[10..100]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:75:6 + --> $DIR/indexing_slicing.rs:66:6 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ @@ -256,13 +256,13 @@ LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:75:8 + --> $DIR/indexing_slicing.rs:66:8 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:76:6 + --> $DIR/indexing_slicing.rs:67:6 | LL | &v[10..]; | ^^^^^^^ @@ -270,7 +270,7 @@ LL | &v[10..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:77:6 + --> $DIR/indexing_slicing.rs:68:6 | LL | &v[..100]; | ^^^^^^^^ @@ -278,7 +278,7 @@ LL | &v[..100]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:89:5 + --> $DIR/indexing_slicing.rs:80:5 | LL | v[N]; | ^^^^ @@ -286,7 +286,7 @@ LL | v[N]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:90:5 + --> $DIR/indexing_slicing.rs:81:5 | LL | v[M]; | ^^^^ @@ -294,13 +294,13 @@ LL | v[M]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:94:13 + --> $DIR/indexing_slicing.rs:85:13 | LL | &x[num..10]; // should trigger out of bounds error | ^^ error: range is out of bounds - --> $DIR/indexing_slicing.rs:95:8 + --> $DIR/indexing_slicing.rs:86:8 | LL | &x[10..num]; // should trigger out of bounds error | ^^ diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 37ae19497d1..a34b06d5642 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(exhaustive_patterns, never_type)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index 976957d35d7..b2b37b9bff7 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:25:5 + --> $DIR/infallible_destructuring_match.rs:16:5 | LL | / let data = match wrapper { LL | | SingleVariantEnum::Variant(i) => i, @@ -9,7 +9,7 @@ LL | | }; = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:46:5 + --> $DIR/infallible_destructuring_match.rs:37:5 | LL | / let data = match wrapper { LL | | TupleStruct(i) => i, @@ -17,7 +17,7 @@ LL | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:67:5 + --> $DIR/infallible_destructuring_match.rs:58:5 | LL | / let data = match wrapper { LL | | Ok(i) => i, diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index bd266368dc4..c324eb95777 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::iter::repeat; #[allow(clippy::trivially_copy_pass_by_ref)] fn square_is_lower_64(x: &u32) -> bool { diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 288285d9aae..564c2b43778 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,5 +1,5 @@ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/infinite_iter.rs:19:5 + --> $DIR/infinite_iter.rs:10:5 | LL | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,31 +7,31 @@ LL | repeat(0_u8).collect::>(); // infinite iter = note: `-D clippy::unused-collect` implied by `-D warnings` error: infinite iteration detected - --> $DIR/infinite_iter.rs:19:5 + --> $DIR/infinite_iter.rs:10:5 | LL | repeat(0_u8).collect::>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:17:8 + --> $DIR/infinite_iter.rs:8:8 | LL | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:20:5 + --> $DIR/infinite_iter.rs:11:5 | LL | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:21:5 + --> $DIR/infinite_iter.rs:12:5 | LL | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:26:5 + --> $DIR/infinite_iter.rs:17:5 | LL | / (0..8_u32) LL | | .rev() @@ -41,37 +41,37 @@ LL | | .for_each(|x| println!("{}", x)); // infinite iter | |________________________________________^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:32:5 + --> $DIR/infinite_iter.rs:23:5 | LL | (0_usize..).flat_map(|x| 0..x).product::(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:33:5 + --> $DIR/infinite_iter.rs:24:5 | LL | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:40:5 + --> $DIR/infinite_iter.rs:31:5 | LL | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/infinite_iter.rs:38:8 + --> $DIR/infinite_iter.rs:29:8 | LL | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:41:5 + --> $DIR/infinite_iter.rs:32:5 | LL | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:42:5 + --> $DIR/infinite_iter.rs:33:5 | LL | / (1..) LL | | .scan(0, |state, x| { @@ -82,31 +82,31 @@ LL | | .min(); // maybe infinite iter | |______________^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:48:5 + --> $DIR/infinite_iter.rs:39:5 | LL | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:49:5 + --> $DIR/infinite_iter.rs:40:5 | LL | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:50:5 + --> $DIR/infinite_iter.rs:41:5 | LL | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:51:5 + --> $DIR/infinite_iter.rs:42:5 | LL | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:74:31 + --> $DIR/infinite_iter.rs:65:31 | LL | let _: HashSet = (0..).collect(); // Infinite iter | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index f9310321593..4df218aa4f3 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::trivially_copy_pass_by_ref)] fn fn_val(i: i32) -> i32 { diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 79efb18a83e..a3fc591c1b1 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,5 +1,5 @@ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:32:11 + --> $DIR/infinite_loop.rs:23:11 | LL | while y < 10 { | ^^^^^^ @@ -7,49 +7,49 @@ LL | while y < 10 { = note: #[deny(clippy::while_immutable_condition)] on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:37:11 + --> $DIR/infinite_loop.rs:28:11 | LL | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:44:11 + --> $DIR/infinite_loop.rs:35:11 | LL | while !cond { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:88:11 + --> $DIR/infinite_loop.rs:79:11 | LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:93:11 + --> $DIR/infinite_loop.rs:84:11 | LL | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:97:11 + --> $DIR/infinite_loop.rs:88:11 | LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:112:11 + --> $DIR/infinite_loop.rs:103:11 | LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:117:11 + --> $DIR/infinite_loop.rs:108:11 | LL | while i < 3 { | ^^^^^ error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. - --> $DIR/infinite_loop.rs:183:15 + --> $DIR/infinite_loop.rs:174:15 | LL | while self.count < n { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index d97e6d69941..af81feaa374 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::inline_fn_without_body)] #![allow(clippy::inline_always)] diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 3c2b086968e..87d2da71280 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,5 +1,5 @@ error: use of `#[inline]` on trait method `default_inline` which has no body - --> $DIR/inline_fn_without_body.rs:14:5 + --> $DIR/inline_fn_without_body.rs:5:5 | LL | #[inline] | _____-^^^^^^^^ @@ -9,7 +9,7 @@ LL | | fn default_inline(); = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body - --> $DIR/inline_fn_without_body.rs:17:5 + --> $DIR/inline_fn_without_body.rs:8:5 | LL | #[inline(always)] | _____-^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | | fn always_inline(); | |____- help: remove error: use of `#[inline]` on trait method `never_inline` which has no body - --> $DIR/inline_fn_without_body.rs:20:5 + --> $DIR/inline_fn_without_body.rs:11:5 | LL | #[inline(never)] | _____-^^^^^^^^^^^^^^^ diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index ce6cd7888ee..42d8045244f 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(clippy::no_effect, clippy::unnecessary_operation)] #[warn(clippy::int_plus_one)] fn main() { diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 30bc2966619..4a783e50c67 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,5 +1,5 @@ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:16:5 + --> $DIR/int_plus_one.rs:7:5 | LL | x >= y + 1; | ^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:17:5 + --> $DIR/int_plus_one.rs:8:5 | LL | y + 1 <= x; | ^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | y < x; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:19:5 + --> $DIR/int_plus_one.rs:10:5 | LL | x - 1 >= y; | ^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | x > y; | ^^^^^ error: Unnecessary `>= y + 1` or `x - 1 >=` - --> $DIR/int_plus_one.rs:20:5 + --> $DIR/int_plus_one.rs:11:5 | LL | y <= x - 1; | ^^^^^^^^^^ diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs index 0ec356280b6..4f04c5467d3 100644 --- a/tests/ui/invalid_ref.rs +++ b/tests/ui/invalid_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] #![feature(core_intrinsics)] diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index f4386362099..9966c347f6e 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -1,5 +1,5 @@ error: reference to zeroed memory - --> $DIR/invalid_ref.rs:33:24 + --> $DIR/invalid_ref.rs:24:24 | LL | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let ref_zero: &T = std::mem::zeroed(); // warning = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:37:24 + --> $DIR/invalid_ref.rs:28:24 | LL | let ref_zero: &T = core::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let ref_zero: &T = core::mem::zeroed(); // warning = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory - --> $DIR/invalid_ref.rs:41:24 + --> $DIR/invalid_ref.rs:32:24 | LL | let ref_zero: &T = std::intrinsics::init(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let ref_zero: &T = std::intrinsics::init(); // warning = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:45:26 + --> $DIR/invalid_ref.rs:36:26 | LL | let ref_uninit: &T = std::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let ref_uninit: &T = std::mem::uninitialized(); // warning = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:49:26 + --> $DIR/invalid_ref.rs:40:26 | LL | let ref_uninit: &T = core::mem::uninitialized(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let ref_uninit: &T = core::mem::uninitialized(); // warning = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:53:26 + --> $DIR/invalid_ref.rs:44:26 | LL | let ref_uninit: &T = std::intrinsics::uninit(); // warning | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 60f877b1ebe..697416dcee8 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::invalid_upcast_comparisons)] #![allow( unused, diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index 4bf92088337..03c3fb80aaa 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -1,5 +1,5 @@ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:30:5 + --> $DIR/invalid_upcast_comparisons.rs:21:5 | LL | (u8 as u32) > 300; | ^^^^^^^^^^^^^^^^^ @@ -7,157 +7,157 @@ LL | (u8 as u32) > 300; = note: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:31:5 + --> $DIR/invalid_upcast_comparisons.rs:22:5 | LL | (u8 as i32) > 300; | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:32:5 + --> $DIR/invalid_upcast_comparisons.rs:23:5 | LL | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:33:5 + --> $DIR/invalid_upcast_comparisons.rs:24:5 | LL | (u8 as i32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:34:5 + --> $DIR/invalid_upcast_comparisons.rs:25:5 | LL | 300 < (u8 as u32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:35:5 + --> $DIR/invalid_upcast_comparisons.rs:26:5 | LL | 300 < (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:36:5 + --> $DIR/invalid_upcast_comparisons.rs:27:5 | LL | 300 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:37:5 + --> $DIR/invalid_upcast_comparisons.rs:28:5 | LL | 300 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:39:5 + --> $DIR/invalid_upcast_comparisons.rs:30:5 | LL | (u8 as u32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:40:5 + --> $DIR/invalid_upcast_comparisons.rs:31:5 | LL | (u8 as i32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:41:5 + --> $DIR/invalid_upcast_comparisons.rs:32:5 | LL | (u8 as u32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:42:5 + --> $DIR/invalid_upcast_comparisons.rs:33:5 | LL | (u8 as i32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:43:5 + --> $DIR/invalid_upcast_comparisons.rs:34:5 | LL | 300 >= (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:44:5 + --> $DIR/invalid_upcast_comparisons.rs:35:5 | LL | 300 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:45:5 + --> $DIR/invalid_upcast_comparisons.rs:36:5 | LL | 300 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:46:5 + --> $DIR/invalid_upcast_comparisons.rs:37:5 | LL | 300 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:49:5 + --> $DIR/invalid_upcast_comparisons.rs:40:5 | LL | (u8 as i32) < 0; | ^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:50:5 + --> $DIR/invalid_upcast_comparisons.rs:41:5 | LL | -5 != (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:52:5 + --> $DIR/invalid_upcast_comparisons.rs:43:5 | LL | (u8 as i32) >= 0; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:53:5 + --> $DIR/invalid_upcast_comparisons.rs:44:5 | LL | -5 == (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:56:5 + --> $DIR/invalid_upcast_comparisons.rs:47:5 | LL | 1337 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:57:5 + --> $DIR/invalid_upcast_comparisons.rs:48:5 | LL | 1337 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:59:5 + --> $DIR/invalid_upcast_comparisons.rs:50:5 | LL | 1337 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:60:5 + --> $DIR/invalid_upcast_comparisons.rs:51:5 | LL | 1337 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:74:5 + --> $DIR/invalid_upcast_comparisons.rs:65:5 | LL | (u8 as i32) > -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:75:5 + --> $DIR/invalid_upcast_comparisons.rs:66:5 | LL | (u8 as i32) < -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:91:5 + --> $DIR/invalid_upcast_comparisons.rs:82:5 | LL | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs index 5c6392811b9..f497d5550af 100644 --- a/tests/ui/issue-3145.rs +++ b/tests/ui/issue-3145.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { println!("{}" a); //~ERROR expected token: `,` } diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index c7a995c61d6..f3984f991a4 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,5 +1,5 @@ error: expected token: `,` - --> $DIR/issue-3145.rs:11:19 + --> $DIR/issue-3145.rs:2:19 | LL | println!("{}" a); //~ERROR expected token: `,` | ^ diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index a54da0b6a96..da580a1839a 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::while_let_on_iterator)] use std::iter::Iterator; diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr index 37599900312..d7125901335 100644 --- a/tests/ui/issue_2356.stderr +++ b/tests/ui/issue_2356.stderr @@ -1,11 +1,11 @@ error: this loop could be written as a `for` loop - --> $DIR/issue_2356.rs:24:29 + --> $DIR/issue_2356.rs:15:29 | LL | while let Some(e) = it.next() { | ^^^^^^^^^ help: try: `for e in it { .. }` | note: lint level defined here - --> $DIR/issue_2356.rs:10:9 + --> $DIR/issue_2356.rs:1:9 | LL | #![deny(clippy::while_let_on_iterator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs index fca19350558..c17a7cbc8d9 100644 --- a/tests/ui/item_after_statement.rs +++ b/tests/ui/item_after_statement.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::items_after_statements)] fn ok() { diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr index 3024431244c..f8f010b5e5c 100644 --- a/tests/ui/item_after_statement.stderr +++ b/tests/ui/item_after_statement.stderr @@ -1,5 +1,5 @@ error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:21:5 + --> $DIR/item_after_statement.rs:12:5 | LL | / fn foo() { LL | | println!("foo"); @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::items-after-statements` implied by `-D warnings` error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:28:5 + --> $DIR/item_after_statement.rs:19:5 | LL | / fn foo() { LL | | println!("foo"); diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 0b9d2c36827..a65ca3bbb13 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 037c33fbc3d..6948bd27679 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:22:13 + --> $DIR/iter_skip_next.rs:13:13 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:23:13 + --> $DIR/iter_skip_next.rs:14:13 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:24:13 + --> $DIR/iter_skip_next.rs:15:13 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:25:14 + --> $DIR/iter_skip_next.rs:16:14 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 80153efcb93..76c3414bb02 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::large_digit_groups)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 3f88aefda33..45aef91069b 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -1,5 +1,5 @@ error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:24:9 + --> $DIR/large_digit_groups.rs:15:9 | LL | 0b1_10110_i64, | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -7,31 +7,31 @@ LL | 0b1_10110_i64, = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:25:9 + --> $DIR/large_digit_groups.rs:16:9 | LL | 0x1_23456_78901_usize, | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:26:9 + --> $DIR/large_digit_groups.rs:17:9 | LL | 1_23456_f32, | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:27:9 + --> $DIR/large_digit_groups.rs:18:9 | LL | 1_23456.12_f32, | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:28:9 + --> $DIR/large_digit_groups.rs:19:9 | LL | 1_23456.12345_f32, | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:29:9 + --> $DIR/large_digit_groups.rs:20:9 | LL | 1_23456.12345_6_f32, | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index 29a73e68d43..852ef5fec0e 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] #![allow(unused_variables)] #![warn(clippy::large_enum_variant)] diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 839d16bd9a2..b13812612cb 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -1,5 +1,5 @@ error: large size difference between variants - --> $DIR/large_enum_variant.rs:16:5 + --> $DIR/large_enum_variant.rs:7:5 | LL | B([i32; 8000]), | ^^^^^^^^^^^^^^ @@ -11,19 +11,19 @@ LL | B(Box<[i32; 8000]>), | ^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:27:5 + --> $DIR/large_enum_variant.rs:18:5 | LL | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:27:5 + --> $DIR/large_enum_variant.rs:18:5 | LL | C(T, [i32; 8000]), | ^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:40:5 + --> $DIR/large_enum_variant.rs:31:5 | LL | ContainingLargeEnum(LargeEnum), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,31 +33,31 @@ LL | ContainingLargeEnum(Box), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:43:5 + --> $DIR/large_enum_variant.rs:34:5 | LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:43:5 + --> $DIR/large_enum_variant.rs:34:5 | LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:50:5 + --> $DIR/large_enum_variant.rs:41:5 | LL | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:50:5 + --> $DIR/large_enum_variant.rs:41:5 | LL | StructLikeLarge { x: [i32; 8000], y: i32 }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:55:5 + --> $DIR/large_enum_variant.rs:46:5 | LL | StructLikeLarge2 { x: [i32; 8000] }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 7f4ba4f1523..05b863f3edc 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::len_without_is_empty, clippy::len_zero)] #![allow(dead_code, unused)] diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index f5f19e128b7..a8b2e2e4097 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,5 +1,5 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:15:1 + --> $DIR/len_zero.rs:6:1 | LL | / impl PubOne { LL | | pub fn len(self: &Self) -> isize { @@ -11,7 +11,7 @@ LL | | } = note: `-D clippy::len-without-is-empty` implied by `-D warnings` error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:64:1 + --> $DIR/len_zero.rs:55:1 | LL | / pub trait PubTraitsToo { LL | | fn len(self: &Self) -> isize; @@ -19,7 +19,7 @@ LL | | } | |_^ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:98:1 + --> $DIR/len_zero.rs:89:1 | LL | / impl HasIsEmpty { LL | | pub fn len(self: &Self) -> isize { @@ -31,7 +31,7 @@ LL | | } | |_^ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:127:1 + --> $DIR/len_zero.rs:118:1 | LL | / impl HasWrongIsEmpty { LL | | pub fn len(self: &Self) -> isize { @@ -43,7 +43,7 @@ LL | | } | |_^ error: length comparison to zero - --> $DIR/len_zero.rs:148:8 + --> $DIR/len_zero.rs:139:8 | LL | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` @@ -51,85 +51,85 @@ LL | if x.len() == 0 { = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:152:8 + --> $DIR/len_zero.rs:143:8 | LL | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:167:8 + --> $DIR/len_zero.rs:158:8 | LL | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:170:8 + --> $DIR/len_zero.rs:161:8 | LL | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:173:8 + --> $DIR/len_zero.rs:164:8 | LL | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:176:8 + --> $DIR/len_zero.rs:167:8 | LL | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:179:8 + --> $DIR/len_zero.rs:170:8 | LL | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:190:8 + --> $DIR/len_zero.rs:181:8 | LL | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:193:8 + --> $DIR/len_zero.rs:184:8 | LL | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:196:8 + --> $DIR/len_zero.rs:187:8 | LL | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:199:8 + --> $DIR/len_zero.rs:190:8 | LL | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:202:8 + --> $DIR/len_zero.rs:193:8 | LL | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:216:8 + --> $DIR/len_zero.rs:207:8 | LL | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:229:8 + --> $DIR/len_zero.rs:220:8 | LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:235:1 + --> $DIR/len_zero.rs:226:1 | LL | / pub trait DependsOnFoo: Foo { LL | | fn len(&mut self) -> usize; diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 26fdc46ac17..5bfa32dd56c 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( unused_variables, unused_assignments, diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 7883a713c05..c53a63a541b 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,5 +1,5 @@ error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:72:5 + --> $DIR/let_if_seq.rs:63:5 | LL | / let mut foo = 0; LL | | if f() { @@ -11,7 +11,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:77:5 + --> $DIR/let_if_seq.rs:68:5 | LL | / let mut bar = 0; LL | | if f() { @@ -25,7 +25,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:85:5 + --> $DIR/let_if_seq.rs:76:5 | LL | / let quz; LL | | if f() { @@ -36,7 +36,7 @@ LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:114:5 + --> $DIR/let_if_seq.rs:105:5 | LL | / let mut baz = 0; LL | | if f() { diff --git a/tests/ui/let_return.rs b/tests/ui/let_return.rs index eb012133376..d2e46621f9f 100644 --- a/tests/ui/let_return.rs +++ b/tests/ui/let_return.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] #![warn(clippy::let_and_return)] diff --git a/tests/ui/let_return.stderr b/tests/ui/let_return.stderr index c53d5cfb886..69c4720c9b3 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_return.stderr @@ -1,24 +1,24 @@ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:16:5 + --> $DIR/let_return.rs:7:5 | LL | x | ^ | = note: `-D clippy::let-and-return` implied by `-D warnings` note: this expression can be directly returned - --> $DIR/let_return.rs:15:13 + --> $DIR/let_return.rs:6:13 | LL | let x = 5; | ^ error: returning the result of a let binding from a block. Consider returning the expression directly. - --> $DIR/let_return.rs:22:9 + --> $DIR/let_return.rs:13:9 | LL | x | ^ | note: this expression can be directly returned - --> $DIR/let_return.rs:21:17 + --> $DIR/let_return.rs:12:17 | LL | let x = 5; | ^ diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 89cb190cc96..dc17c98f6a8 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::let_unit_value)] #![allow(unused_variables)] diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index 8929844180a..e1773a40225 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -1,5 +1,5 @@ error: this let-binding has unit value. Consider omitting `let _x =` - --> $DIR/let_unit.rs:20:5 + --> $DIR/let_unit.rs:11:5 | LL | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _x = println!("x"); = note: `-D clippy::let-unit-value` implied by `-D warnings` error: this let-binding has unit value. Consider omitting `let _a =` - --> $DIR/let_unit.rs:24:9 + --> $DIR/let_unit.rs:15:9 | LL | let _a = (); | ^^^^^^^^^^^^ diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index 110868404bd..46c8e1740a9 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::needless_lifetimes, clippy::extra_unused_lifetimes)] #![allow(dead_code, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index abd11907b6d..18b8440089c 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -1,5 +1,5 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:13:1 + --> $DIR/lifetimes.rs:4:1 | LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:15:1 + --> $DIR/lifetimes.rs:6:1 | LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:23:1 + --> $DIR/lifetimes.rs:14:1 | LL | / fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { LL | | x @@ -21,7 +21,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:47:1 + --> $DIR/lifetimes.rs:38:1 | LL | / fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { LL | | Ok(x) @@ -29,7 +29,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:52:1 + --> $DIR/lifetimes.rs:43:1 | LL | / fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> LL | | where @@ -40,13 +40,13 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:63:1 + --> $DIR/lifetimes.rs:54:1 | LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:84:1 + --> $DIR/lifetimes.rs:75:1 | LL | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> LL | | where @@ -57,7 +57,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:117:5 + --> $DIR/lifetimes.rs:108:5 | LL | / fn self_and_out<'s>(&'s self) -> &'s u8 { LL | | &self.x @@ -65,13 +65,13 @@ LL | | } | |_____^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:125:5 + --> $DIR/lifetimes.rs:116:5 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:141:1 + --> $DIR/lifetimes.rs:132:1 | LL | / fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { LL | | unimplemented!() @@ -79,7 +79,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:171:1 + --> $DIR/lifetimes.rs:162:1 | LL | / fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { LL | | unimplemented!() @@ -87,7 +87,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:177:1 + --> $DIR/lifetimes.rs:168:1 | LL | / fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { LL | | unimplemented!() @@ -95,7 +95,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:196:1 + --> $DIR/lifetimes.rs:187:1 | LL | / fn named_input_elided_output<'a>(_arg: &'a str) -> &str { LL | | unimplemented!() @@ -103,7 +103,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:204:1 + --> $DIR/lifetimes.rs:195:1 | LL | / fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { LL | | unimplemented!() @@ -111,7 +111,7 @@ LL | | } | |_^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/lifetimes.rs:241:1 + --> $DIR/lifetimes.rs:232:1 | LL | / fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { LL | | unimplemented!() diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 90e9a69a994..ef86b5240eb 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::large_digit_groups)] #![warn(clippy::mixed_case_hex_literals)] #![warn(clippy::unseparated_literal_suffix)] diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 6ceb25fd612..2a461dba457 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -1,5 +1,5 @@ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:22:17 + --> $DIR/literals.rs:13:17 | LL | let fail1 = 0xabCD; | ^^^^^^ @@ -7,19 +7,19 @@ LL | let fail1 = 0xabCD; = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:23:17 + --> $DIR/literals.rs:14:17 | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:24:17 + --> $DIR/literals.rs:15:17 | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:25:27 + --> $DIR/literals.rs:16:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | let fail_multi_zero = 000_123usize; = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: this is a decimal constant - --> $DIR/literals.rs:25:27 + --> $DIR/literals.rs:16:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -43,37 +43,37 @@ LL | let fail_multi_zero = 0o123usize; | ^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:30:17 + --> $DIR/literals.rs:21:17 | LL | let fail3 = 1234i32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:31:17 + --> $DIR/literals.rs:22:17 | LL | let fail4 = 1234u32; | ^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:32:17 + --> $DIR/literals.rs:23:17 | LL | let fail5 = 1234isize; | ^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> $DIR/literals.rs:33:17 + --> $DIR/literals.rs:24:17 | LL | let fail6 = 1234usize; | ^^^^^^^^^ error: float type suffix should be separated by an underscore - --> $DIR/literals.rs:34:17 + --> $DIR/literals.rs:25:17 | LL | let fail7 = 1.5f32; | ^^^^^^ error: this is a decimal constant - --> $DIR/literals.rs:38:17 + --> $DIR/literals.rs:29:17 | LL | let fail8 = 0123; | ^^^^ @@ -87,7 +87,7 @@ LL | let fail8 = 0o123; | ^^^^^ error: long literal lacking separators - --> $DIR/literals.rs:49:17 + --> $DIR/literals.rs:40:17 | LL | let fail9 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` @@ -95,25 +95,25 @@ LL | let fail9 = 0xabcdef; = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/literals.rs:50:18 + --> $DIR/literals.rs:41:18 | LL | let fail10 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/literals.rs:51:18 + --> $DIR/literals.rs:42:18 | LL | let fail11 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/literals.rs:52:18 + --> $DIR/literals.rs:43:18 | LL | let fail12 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: digit groups should be smaller - --> $DIR/literals.rs:53:18 + --> $DIR/literals.rs:44:18 | LL | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` @@ -121,7 +121,7 @@ LL | let fail13 = 0x1_23456_78901_usize; = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:55:18 + --> $DIR/literals.rs:46:18 | LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` @@ -129,25 +129,25 @@ LL | let fail14 = 2_32; = note: #[deny(clippy::mistyped_literal_suffixes)] on by default error: mistyped literal suffix - --> $DIR/literals.rs:56:18 + --> $DIR/literals.rs:47:18 | LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/literals.rs:57:18 + --> $DIR/literals.rs:48:18 | LL | let fail16 = 7_8; | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/literals.rs:58:18 + --> $DIR/literals.rs:49:18 | LL | let fail17 = 23_16; | ^^^^^ help: did you mean to write: `23_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:60:18 + --> $DIR/literals.rs:51:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -155,61 +155,61 @@ LL | let fail19 = 12_3456_21; = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: mistyped literal suffix - --> $DIR/literals.rs:61:18 + --> $DIR/literals.rs:52:18 | LL | let fail20 = 2__8; | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/literals.rs:62:18 + --> $DIR/literals.rs:53:18 | LL | let fail21 = 4___16; | ^^^^^^ help: did you mean to write: `4_i16` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:63:18 + --> $DIR/literals.rs:54:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:64:18 + --> $DIR/literals.rs:55:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: mistyped literal suffix - --> $DIR/literals.rs:66:18 + --> $DIR/literals.rs:57:18 | LL | let fail24 = 12.34_64; | ^^^^^^^^ help: did you mean to write: `12.34_f64` error: mistyped literal suffix - --> $DIR/literals.rs:67:18 + --> $DIR/literals.rs:58:18 | LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> $DIR/literals.rs:68:18 + --> $DIR/literals.rs:59:18 | LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> $DIR/literals.rs:69:18 + --> $DIR/literals.rs:60:18 | LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix - --> $DIR/literals.rs:70:18 + --> $DIR/literals.rs:61:18 | LL | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix - --> $DIR/literals.rs:71:18 + --> $DIR/literals.rs:62:18 | LL | let fail29 = 42279.911_32; | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index e6fb37f8120..a70cb2f6725 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 6253ae2150c..56b1f67bac9 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:14:22 + --> $DIR/map_clone.rs:5:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` @@ -7,13 +7,13 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:15:26 + --> $DIR/map_clone.rs:6:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:16:23 + --> $DIR/map_clone.rs:7:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 99b90a0df79..d0720c419c8 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index 931ef9b6248..822d27391f6 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,5 +1,5 @@ error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` - --> $DIR/map_flatten.rs:14:21 + --> $DIR/map_flatten.rs:5:21 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using flat_map instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` diff --git a/tests/ui/map_unit_fn.rs b/tests/ui/map_unit_fn.rs index 1d203a147ba..9a74da4e3b8 100644 --- a/tests/ui/map_unit_fn.rs +++ b/tests/ui/map_unit_fn.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] struct Mappable {} diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs index fe5e94cf458..a7af8ce0108 100644 --- a/tests/ui/match_bool.rs +++ b/tests/ui/match_bool.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn match_bool() { let test: bool = true; diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 78711c4ba4b..193e6c17238 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/match_bool.rs:38:11 + --> $DIR/match_bool.rs:29:11 | LL | match test && test { | ^^^^^^^^^^^^ help: try: `test` @@ -7,7 +7,7 @@ LL | match test && test { = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:13:5 + --> $DIR/match_bool.rs:4:5 | LL | / match test { LL | | true => 0, @@ -18,7 +18,7 @@ LL | | }; = note: `-D clippy::match-bool` implied by `-D warnings` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:19:5 + --> $DIR/match_bool.rs:10:5 | LL | / match option == 1 { LL | | true => 1, @@ -27,7 +27,7 @@ LL | | }; | |_____^ help: consider using an if/else expression: `if option == 1 { 1 } else { 0 }` error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:24:5 + --> $DIR/match_bool.rs:15:5 | LL | / match test { LL | | true => (), @@ -44,7 +44,7 @@ LL | }; | error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:31:5 + --> $DIR/match_bool.rs:22:5 | LL | / match test { LL | | false => { @@ -61,7 +61,7 @@ LL | }; | error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:38:5 + --> $DIR/match_bool.rs:29:5 | LL | / match test && test { LL | | false => { @@ -78,7 +78,7 @@ LL | }; | error: equal expressions as operands to `&&` - --> $DIR/match_bool.rs:38:11 + --> $DIR/match_bool.rs:29:11 | LL | match test && test { | ^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL | match test && test { = note: #[deny(clippy::eq_op)] on by default error: you seem to be trying to match on a boolean expression - --> $DIR/match_bool.rs:45:5 + --> $DIR/match_bool.rs:36:5 | LL | / match test { LL | | false => { diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs index 5350f933ae5..978ac5195d3 100644 --- a/tests/ui/match_overlapping_arm.rs +++ b/tests/ui/match_overlapping_arm.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(exclusive_range_pattern)] #![warn(clippy::match_overlapping_arm)] #![allow(clippy::redundant_pattern_matching)] diff --git a/tests/ui/match_overlapping_arm.stderr b/tests/ui/match_overlapping_arm.stderr index 3e978df842e..14eb378141b 100644 --- a/tests/ui/match_overlapping_arm.stderr +++ b/tests/ui/match_overlapping_arm.stderr @@ -1,60 +1,60 @@ error: some ranges overlap - --> $DIR/match_overlapping_arm.rs:20:9 + --> $DIR/match_overlapping_arm.rs:11:9 | LL | 0...10 => println!("0 ... 10"), | ^^^^^^ | = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this - --> $DIR/match_overlapping_arm.rs:21:9 + --> $DIR/match_overlapping_arm.rs:12:9 | LL | 0...11 => println!("0 ... 11"), | ^^^^^^ error: some ranges overlap - --> $DIR/match_overlapping_arm.rs:26:9 + --> $DIR/match_overlapping_arm.rs:17:9 | LL | 0...5 => println!("0 ... 5"), | ^^^^^ | note: overlaps with this - --> $DIR/match_overlapping_arm.rs:28:9 + --> $DIR/match_overlapping_arm.rs:19:9 | LL | FOO...11 => println!("0 ... 11"), | ^^^^^^^^ error: some ranges overlap - --> $DIR/match_overlapping_arm.rs:34:9 + --> $DIR/match_overlapping_arm.rs:25:9 | LL | 0...5 => println!("0 ... 5"), | ^^^^^ | note: overlaps with this - --> $DIR/match_overlapping_arm.rs:33:9 + --> $DIR/match_overlapping_arm.rs:24:9 | LL | 2 => println!("2"), | ^ error: some ranges overlap - --> $DIR/match_overlapping_arm.rs:40:9 + --> $DIR/match_overlapping_arm.rs:31:9 | LL | 0...2 => println!("0 ... 2"), | ^^^^^ | note: overlaps with this - --> $DIR/match_overlapping_arm.rs:39:9 + --> $DIR/match_overlapping_arm.rs:30:9 | LL | 2 => println!("2"), | ^ error: some ranges overlap - --> $DIR/match_overlapping_arm.rs:63:9 + --> $DIR/match_overlapping_arm.rs:54:9 | LL | 0..11 => println!("0 .. 11"), | ^^^^^ | note: overlaps with this - --> $DIR/match_overlapping_arm.rs:64:9 + --> $DIR/match_overlapping_arm.rs:55:9 | LL | 0...11 => println!("0 ... 11"), | ^^^^^^ diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 8038433c564..013f12a1a0e 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(exclusive_range_pattern)] #![warn(clippy::all)] #![allow(unused, clippy::redundant_pattern_matching)] diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 06ba6224855..a3714a69e6e 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,5 +1,5 @@ error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:20:9 + --> $DIR/matches.rs:11:9 | LL | / match v { LL | | &Some(v) => println!("{:?}", v), @@ -16,7 +16,7 @@ LL | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:31:5 + --> $DIR/matches.rs:22:5 | LL | / match tup { LL | | &(v, 1) => println!("{}", v), @@ -30,7 +30,7 @@ LL | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:37:5 + --> $DIR/matches.rs:28:5 | LL | / match &w { LL | | &Some(v) => println!("{:?}", v), @@ -45,7 +45,7 @@ LL | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:48:5 + --> $DIR/matches.rs:39:5 | LL | / if let &None = a { LL | | println!("none"); @@ -57,7 +57,7 @@ LL | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:53:5 + --> $DIR/matches.rs:44:5 | LL | / if let &None = &b { LL | | println!("none"); @@ -69,7 +69,7 @@ LL | if let None = b { | ^^^^ ^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:64:9 + --> $DIR/matches.rs:55:9 | LL | Err(_) => panic!("err"), | ^^^^^^ @@ -78,26 +78,26 @@ LL | Err(_) => panic!("err"), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:63:18 + --> $DIR/matches.rs:54:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:62:18 + --> $DIR/matches.rs:53:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:62:18 + --> $DIR/matches.rs:53:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:70:9 + --> $DIR/matches.rs:61:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -105,25 +105,25 @@ LL | Err(_) => panic!(), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:69:18 + --> $DIR/matches.rs:60:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:68:18 + --> $DIR/matches.rs:59:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:68:18 + --> $DIR/matches.rs:59:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:76:9 + --> $DIR/matches.rs:67:9 | LL | Err(_) => { | ^^^^^^ @@ -131,133 +131,133 @@ LL | Err(_) => { = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:75:18 + --> $DIR/matches.rs:66:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:65:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:65:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:84:18 + --> $DIR/matches.rs:75:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:83:18 + --> $DIR/matches.rs:74:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:83:18 + --> $DIR/matches.rs:74:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:91:18 + --> $DIR/matches.rs:82:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:90:18 + --> $DIR/matches.rs:81:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:90:18 + --> $DIR/matches.rs:81:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:97:18 + --> $DIR/matches.rs:88:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:96:18 + --> $DIR/matches.rs:87:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:96:18 + --> $DIR/matches.rs:87:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:103:18 + --> $DIR/matches.rs:94:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:102:18 + --> $DIR/matches.rs:93:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:102:18 + --> $DIR/matches.rs:93:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:126:29 + --> $DIR/matches.rs:117:29 | LL | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:125:29 + --> $DIR/matches.rs:116:29 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:125:29 + --> $DIR/matches.rs:116:29 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:141:18 + --> $DIR/matches.rs:132:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:140:18 + --> $DIR/matches.rs:131:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:140:18 + --> $DIR/matches.rs:131:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: use as_ref() instead - --> $DIR/matches.rs:150:33 + --> $DIR/matches.rs:141:33 | LL | let borrowed: Option<&()> = match owned { | _________________________________^ @@ -269,7 +269,7 @@ LL | | }; = note: `-D clippy::match-as-ref` implied by `-D warnings` error: use as_mut() instead - --> $DIR/matches.rs:156:39 + --> $DIR/matches.rs:147:39 | LL | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ diff --git a/tests/ui/mem_discriminant.rs b/tests/ui/mem_discriminant.rs index 9d2d6f9503a..81f1628861e 100644 --- a/tests/ui/mem_discriminant.rs +++ b/tests/ui/mem_discriminant.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::mem_discriminant_non_enum)] use std::mem; diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index c445b96a90f..295545406ed 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -1,17 +1,17 @@ error: calling `mem::discriminant` on non-enum type `&str` - --> $DIR/mem_discriminant.rs:23:5 + --> $DIR/mem_discriminant.rs:14:5 | LL | mem::discriminant(&"hello"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/mem_discriminant.rs:10:9 + --> $DIR/mem_discriminant.rs:1:9 | LL | #![deny(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:24:5 + --> $DIR/mem_discriminant.rs:15:5 | LL | mem::discriminant(&&Some(2)); | ^^^^^^^^^^^^^^^^^^---------^ @@ -19,7 +19,7 @@ LL | mem::discriminant(&&Some(2)); | help: try dereferencing: `&Some(2)` error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:25:5 + --> $DIR/mem_discriminant.rs:16:5 | LL | mem::discriminant(&&None::); | ^^^^^^^^^^^^^^^^^^------------^ @@ -27,7 +27,7 @@ LL | mem::discriminant(&&None::); | help: try dereferencing: `&None::` error: calling `mem::discriminant` on non-enum type `&Foo` - --> $DIR/mem_discriminant.rs:26:5 + --> $DIR/mem_discriminant.rs:17:5 | LL | mem::discriminant(&&Foo::One(5)); | ^^^^^^^^^^^^^^^^^^-------------^ @@ -35,7 +35,7 @@ LL | mem::discriminant(&&Foo::One(5)); | help: try dereferencing: `&Foo::One(5)` error: calling `mem::discriminant` on non-enum type `&Foo` - --> $DIR/mem_discriminant.rs:27:5 + --> $DIR/mem_discriminant.rs:18:5 | LL | mem::discriminant(&&Foo::Two(5)); | ^^^^^^^^^^^^^^^^^^-------------^ @@ -43,13 +43,13 @@ LL | mem::discriminant(&&Foo::Two(5)); | help: try dereferencing: `&Foo::Two(5)` error: calling `mem::discriminant` on non-enum type `A` - --> $DIR/mem_discriminant.rs:28:5 + --> $DIR/mem_discriminant.rs:19:5 | LL | mem::discriminant(&A(Foo::One(0))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:32:5 + --> $DIR/mem_discriminant.rs:23:5 | LL | mem::discriminant(&ro); | ^^^^^^^^^^^^^^^^^^---^ @@ -57,7 +57,7 @@ LL | mem::discriminant(&ro); | help: try dereferencing: `ro` error: calling `mem::discriminant` on non-enum type `&std::option::Option` - --> $DIR/mem_discriminant.rs:33:5 + --> $DIR/mem_discriminant.rs:24:5 | LL | mem::discriminant(rro); | ^^^^^^^^^^^^^^^^^^---^ @@ -65,7 +65,7 @@ LL | mem::discriminant(rro); | help: try dereferencing: `*rro` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` - --> $DIR/mem_discriminant.rs:34:5 + --> $DIR/mem_discriminant.rs:25:5 | LL | mem::discriminant(&rro); | ^^^^^^^^^^^^^^^^^^----^ @@ -73,7 +73,7 @@ LL | mem::discriminant(&rro); | help: try dereferencing: `*rro` error: calling `mem::discriminant` on non-enum type `&&std::option::Option` - --> $DIR/mem_discriminant.rs:38:13 + --> $DIR/mem_discriminant.rs:29:13 | LL | mem::discriminant($param) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | mem_discriminant_but_in_a_macro!(&rro); | in this macro invocation error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` - --> $DIR/mem_discriminant.rs:45:5 + --> $DIR/mem_discriminant.rs:36:5 | LL | mem::discriminant(&rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ @@ -93,7 +93,7 @@ LL | mem::discriminant(&rrrrro); | help: try dereferencing: `****rrrrro` error: calling `mem::discriminant` on non-enum type `&&&std::option::Option` - --> $DIR/mem_discriminant.rs:46:5 + --> $DIR/mem_discriminant.rs:37:5 | LL | mem::discriminant(*rrrrro); | ^^^^^^^^^^^^^^^^^^-------^ diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index b46f7007cd0..e5b35c098a2 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::rc::Rc; use std::sync::Arc; diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 292437d0019..16b95a1038a 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -1,5 +1,5 @@ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:23:5 + --> $DIR/mem_forget.rs:14:5 | LL | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | memstuff::forget(six); = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:26:5 + --> $DIR/mem_forget.rs:17:5 | LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:29:5 + --> $DIR/mem_forget.rs:20:5 | LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index edd3c031857..a0c340bb54b 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // aux-build:option_helpers.rs #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index ef3a4e2a423..99a0c0d59d1 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:44:5 + --> $DIR/methods.rs:35:5 | LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn add(self, other: T) -> T { self } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:55:17 + --> $DIR/methods.rs:46:17 | LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ @@ -15,19 +15,19 @@ LL | fn into_u16(&self) -> u16 { 0 } = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:57:21 + --> $DIR/methods.rs:48:21 | LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:59:12 + --> $DIR/methods.rs:50:12 | LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:120:13 + --> $DIR/methods.rs:111:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -39,7 +39,7 @@ LL | | .unwrap_or(0); // should lint even though this call is on = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:124:13 + --> $DIR/methods.rs:115:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -49,7 +49,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:128:13 + --> $DIR/methods.rs:119:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -59,7 +59,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:133:13 + --> $DIR/methods.rs:124:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:135:13 + --> $DIR/methods.rs:126:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -77,7 +77,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:139:13 + --> $DIR/methods.rs:130:13 | LL | let _ = opt | _____________^ @@ -88,7 +88,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:147:13 + --> $DIR/methods.rs:138:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -100,7 +100,7 @@ LL | | .unwrap_or_else(|| 0); // should lint even though this cal = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:151:13 + --> $DIR/methods.rs:142:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -110,7 +110,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:155:13 + --> $DIR/methods.rs:146:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -120,7 +120,7 @@ LL | | ); | |_________________^ error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:164:13 + --> $DIR/methods.rs:155:13 | LL | let _ = opt.map_or(None, |x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` @@ -128,7 +128,7 @@ LL | let _ = opt.map_or(None, |x| Some(x + 1)); = note: `-D clippy::option-map-or-none` implied by `-D warnings` error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:166:13 + --> $DIR/methods.rs:157:13 | LL | let _ = opt.map_or(None, |x| { | _____________^ @@ -144,7 +144,7 @@ LL | }); | error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:191:13 + --> $DIR/methods.rs:182:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:194:13 + --> $DIR/methods.rs:185:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -163,7 +163,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:209:13 + --> $DIR/methods.rs:200:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:212:13 + --> $DIR/methods.rs:203:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -182,7 +182,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:218:13 + --> $DIR/methods.rs:209:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:221:13 + --> $DIR/methods.rs:212:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -200,7 +200,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:227:13 + --> $DIR/methods.rs:218:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:230:13 + --> $DIR/methods.rs:221:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -218,7 +218,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:265:22 + --> $DIR/methods.rs:256:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -226,73 +226,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:268:5 + --> $DIR/methods.rs:259:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:271:21 + --> $DIR/methods.rs:262:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:274:14 + --> $DIR/methods.rs:265:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:277:19 + --> $DIR/methods.rs:268:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:280:5 + --> $DIR/methods.rs:271:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:283:5 + --> $DIR/methods.rs:274:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:286:14 + --> $DIR/methods.rs:277:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:291:21 + --> $DIR/methods.rs:282:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:294:19 + --> $DIR/methods.rs:285:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:297:21 + --> $DIR/methods.rs:288:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:300:21 + --> $DIR/methods.rs:291:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:311:23 + --> $DIR/methods.rs:302:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,43 +300,43 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:312:26 + --> $DIR/methods.rs:303:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:313:31 + --> $DIR/methods.rs:304:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:314:29 + --> $DIR/methods.rs:305:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:319:23 + --> $DIR/methods.rs:310:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:322:26 + --> $DIR/methods.rs:313:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:325:29 + --> $DIR/methods.rs:316:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:337:13 + --> $DIR/methods.rs:328:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index cf68bb61100..8307d4b3019 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] use std::cmp::max as my_max; diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index a6ad34f02b8..6d68d39e8d3 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,5 +1,5 @@ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:21:5 + --> $DIR/min_max.rs:12:5 | LL | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | min(1, max(3, x)); = note: `-D clippy::min-max` implied by `-D warnings` error: this min/max combination leads to constant result - --> $DIR/min_max.rs:22:5 + --> $DIR/min_max.rs:13:5 | LL | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:23:5 + --> $DIR/min_max.rs:14:5 | LL | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:24:5 + --> $DIR/min_max.rs:15:5 | LL | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:26:5 + --> $DIR/min_max.rs:17:5 | LL | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:38:5 + --> $DIR/min_max.rs:29:5 | LL | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this min/max combination leads to constant result - --> $DIR/min_max.rs:39:5 + --> $DIR/min_max.rs:30:5 | LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index 5de2ada5a41..cb311dfb361 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -1,25 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* This file incorporates work covered by the following copyright and - * permission notice: - * Copyright 2013 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 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ - #![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing-doc.stderr index 35c12786284..a3ae62217a2 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing-doc.stderr @@ -1,5 +1,5 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:32:1 + --> $DIR/missing-doc.rs:10:1 | LL | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | type Typedef = String; = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:33:1 + --> $DIR/missing-doc.rs:11:1 | LL | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:35:1 + --> $DIR/missing-doc.rs:13:1 | LL | / struct Foo { LL | | a: isize, @@ -22,19 +22,19 @@ LL | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:36:5 + --> $DIR/missing-doc.rs:14:5 | LL | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:37:5 + --> $DIR/missing-doc.rs:15:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc.rs:40:1 + --> $DIR/missing-doc.rs:18:1 | LL | / pub struct PubFoo { LL | | pub a: isize, @@ -43,43 +43,43 @@ LL | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:41:5 + --> $DIR/missing-doc.rs:19:5 | LL | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:42:5 + --> $DIR/missing-doc.rs:20:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:51:1 + --> $DIR/missing-doc.rs:29:1 | LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:52:1 + --> $DIR/missing-doc.rs:30:1 | LL | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:56:1 + --> $DIR/missing-doc.rs:34:1 | LL | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:57:1 + --> $DIR/missing-doc.rs:35:1 | LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for a trait - --> $DIR/missing-doc.rs:75:1 + --> $DIR/missing-doc.rs:53:1 | LL | / pub trait C { LL | | fn foo(&self); @@ -88,55 +88,55 @@ LL | | } | |_^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:76:5 + --> $DIR/missing-doc.rs:54:5 | LL | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for a trait method - --> $DIR/missing-doc.rs:77:5 + --> $DIR/missing-doc.rs:55:5 | LL | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:87:5 + --> $DIR/missing-doc.rs:65:5 | LL | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc.rs:88:5 + --> $DIR/missing-doc.rs:66:5 | LL | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:99:5 + --> $DIR/missing-doc.rs:77:5 | LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:100:5 + --> $DIR/missing-doc.rs:78:5 | LL | fn bar() {} | ^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:104:5 + --> $DIR/missing-doc.rs:82:5 | LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for a method - --> $DIR/missing-doc.rs:107:5 + --> $DIR/missing-doc.rs:85:5 | LL | fn foo2() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:134:1 + --> $DIR/missing-doc.rs:112:1 | LL | / enum Baz { LL | | BazA { a: isize, b: isize }, @@ -145,31 +145,31 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:135:5 + --> $DIR/missing-doc.rs:113:5 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:135:12 + --> $DIR/missing-doc.rs:113:12 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:135:22 + --> $DIR/missing-doc.rs:113:22 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:136:5 + --> $DIR/missing-doc.rs:114:5 | LL | BarB, | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:139:1 + --> $DIR/missing-doc.rs:117:1 | LL | / pub enum PubBaz { LL | | PubBazA { a: isize }, @@ -177,43 +177,43 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:140:5 + --> $DIR/missing-doc.rs:118:5 | LL | PubBazA { a: isize }, | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:140:15 + --> $DIR/missing-doc.rs:118:15 | LL | PubBazA { a: isize }, | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:160:1 + --> $DIR/missing-doc.rs:138:1 | LL | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:167:1 + --> $DIR/missing-doc.rs:145:1 | LL | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:169:1 + --> $DIR/missing-doc.rs:147:1 | LL | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:176:1 + --> $DIR/missing-doc.rs:154:1 | LL | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:178:1 + --> $DIR/missing-doc.rs:156:1 | LL | / mod internal_impl { LL | | /// dox @@ -225,31 +225,31 @@ LL | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:181:5 + --> $DIR/missing-doc.rs:159:5 | LL | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:182:5 + --> $DIR/missing-doc.rs:160:5 | LL | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:183:5 + --> $DIR/missing-doc.rs:161:5 | LL | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:188:9 + --> $DIR/missing-doc.rs:166:9 | LL | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:189:9 + --> $DIR/missing-doc.rs:167:9 | LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index c9e946e14e6..2b2ea6c94c2 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -1,24 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* This file incorporates work covered by the following copyright and - * permission notice: - * Copyright 2013 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 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ #![warn(clippy::missing_inline_in_public_items)] #![crate_type = "dylib"] // When denying at the crate level, be sure to not get random warnings from the diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index efe9a3b1399..40b92b7647b 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -1,5 +1,5 @@ error: missing `#[inline]` for a function - --> $DIR/missing_inline.rs:40:1 + --> $DIR/missing_inline.rs:19:1 | LL | pub fn pub_foo() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^ @@ -7,31 +7,31 @@ LL | pub fn pub_foo() {} // missing #[inline] = note: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` error: missing `#[inline]` for a default trait method - --> $DIR/missing_inline.rs:56:5 + --> $DIR/missing_inline.rs:35:5 | LL | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:70:5 + --> $DIR/missing_inline.rs:49:5 | LL | fn PubBar_a() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:71:5 + --> $DIR/missing_inline.rs:50:5 | LL | fn PubBar_b() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:72:5 + --> $DIR/missing_inline.rs:51:5 | LL | fn PubBar_c() {} // missing #[inline] | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> $DIR/missing_inline.rs:82:5 + --> $DIR/missing_inline.rs:61:5 | LL | pub fn PubFooImpl() {} // missing #[inline] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index 730055931c4..a23aba9164a 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::module_inception)] mod foo { diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index f4d4692e259..77564dce9eb 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,5 +1,5 @@ error: module has the same name as its containing module - --> $DIR/module_inception.rs:14:9 + --> $DIR/module_inception.rs:5:9 | LL | / mod bar { LL | | mod foo {} @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::module-inception` implied by `-D warnings` error: module has the same name as its containing module - --> $DIR/module_inception.rs:19:5 + --> $DIR/module_inception.rs:10:5 | LL | / mod foo { LL | | mod bar {} diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index 4db4f56de46..1719845cb21 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr index 866156e3b74..5bce2c9ba60 100644 --- a/tests/ui/module_name_repetitions.stderr +++ b/tests/ui/module_name_repetitions.stderr @@ -1,5 +1,5 @@ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:15:5 + --> $DIR/module_name_repetitions.rs:6:5 | LL | pub fn foo_bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | pub fn foo_bar() {} = note: `-D clippy::module-name-repetitions` implied by `-D warnings` error: item name ends with its containing module's name - --> $DIR/module_name_repetitions.rs:16:5 + --> $DIR/module_name_repetitions.rs:7:5 | LL | pub fn bar_foo() {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:17:5 + --> $DIR/module_name_repetitions.rs:8:5 | LL | pub struct FooCake {} | ^^^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name - --> $DIR/module_name_repetitions.rs:18:5 + --> $DIR/module_name_repetitions.rs:9:5 | LL | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:19:5 + --> $DIR/module_name_repetitions.rs:10:5 | LL | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index f7c0c16abad..81603175ab4 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::modulo_one)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index 36f06c74077..a7feeb56ebc 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -1,5 +1,5 @@ error: any number modulo 1 will be 0 - --> $DIR/modulo_one.rs:14:5 + --> $DIR/modulo_one.rs:5:5 | LL | 10 % 1; | ^^^^^^ diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 8a9da42083d..8f9ed7ed637 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused, clippy::trivially_copy_pass_by_ref)] #![warn(clippy::mut_from_ref)] diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index 544d1aa5f14..4787999920b 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -1,60 +1,60 @@ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:16:39 + --> $DIR/mut_from_ref.rs:7:39 | LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^^^^ | = note: `-D clippy::mut-from-ref` implied by `-D warnings` note: immutable borrow here - --> $DIR/mut_from_ref.rs:16:29 + --> $DIR/mut_from_ref.rs:7:29 | LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo { | ^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:22:25 + --> $DIR/mut_from_ref.rs:13:25 | LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:22:16 + --> $DIR/mut_from_ref.rs:13:16 | LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:31:21 + --> $DIR/mut_from_ref.rs:22:21 | LL | fn fail(x: &u32) -> &mut u16 { | ^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:31:12 + --> $DIR/mut_from_ref.rs:22:12 | LL | fn fail(x: &u32) -> &mut u16 { | ^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:35:50 + --> $DIR/mut_from_ref.rs:26:50 | LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:35:25 + --> $DIR/mut_from_ref.rs:26:25 | LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^ error: mutable borrow from immutable input(s) - --> $DIR/mut_from_ref.rs:39:67 + --> $DIR/mut_from_ref.rs:30:67 | LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> $DIR/mut_from_ref.rs:39:27 + --> $DIR/mut_from_ref.rs:30:27 | LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index e8239007cb3..8965cef66de 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::mut_mut)] diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index ed926637563..6fa5dbfc29f 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -1,5 +1,5 @@ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:13:11 + --> $DIR/mut_mut.rs:4:11 | LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:29:17 + --> $DIR/mut_mut.rs:20:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:23:9 + --> $DIR/mut_mut.rs:14:9 | LL | &mut $p | ^^^^^^^ @@ -22,37 +22,37 @@ LL | let mut z = mut_ptr!(&mut 3u32); | ------------------- in this macro invocation error: this expression mutably borrows a mutable reference. Consider reborrowing - --> $DIR/mut_mut.rs:31:21 + --> $DIR/mut_mut.rs:22:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:32 + --> $DIR/mut_mut.rs:26:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:35:16 + --> $DIR/mut_mut.rs:26:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:40:37 + --> $DIR/mut_mut.rs:31:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:40:16 + --> $DIR/mut_mut.rs:31:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:40:21 + --> $DIR/mut_mut.rs:31:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs index 23dddcdd158..1348dd2a3d8 100644 --- a/tests/ui/mut_range_bound.rs +++ b/tests/ui/mut_range_bound.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] fn main() { diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index ce3ae6cb2a5..50e94efde53 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -1,5 +1,5 @@ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:25:9 + --> $DIR/mut_range_bound.rs:16:9 | LL | m = 5; | ^^^^^ @@ -7,25 +7,25 @@ LL | m = 5; = note: `-D clippy::mut-range-bound` implied by `-D warnings` error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:32:9 + --> $DIR/mut_range_bound.rs:23:9 | LL | m *= 2; | ^^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:40:9 + --> $DIR/mut_range_bound.rs:31:9 | LL | m = 5; | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:41:9 + --> $DIR/mut_range_bound.rs:32:9 | LL | n = 7; | ^^^^^ error: attempt to mutate range bound within loop; note that the range of the loop is unchanged - --> $DIR/mut_range_bound.rs:55:22 + --> $DIR/mut_range_bound.rs:46:22 | LL | let n = &mut m; // warning | ^ diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index 882ed7e1dd3..c4379e0ea1c 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused_variables, clippy::trivially_copy_pass_by_ref)] fn takes_an_immutable_reference(a: &i32) {} diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 1fe31e26f6e..fa8c82ae0f3 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,5 +1,5 @@ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:26:34 + --> $DIR/mut_reference.rs:17:34 | LL | takes_an_immutable_reference(&mut 42); | ^^^^^^^ @@ -7,13 +7,13 @@ LL | takes_an_immutable_reference(&mut 42); = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` error: The function/method `as_ptr` doesn't need a mutable reference - --> $DIR/mut_reference.rs:28:12 + --> $DIR/mut_reference.rs:19:12 | LL | as_ptr(&mut 42); | ^^^^^^^ error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:32:44 + --> $DIR/mut_reference.rs:23:44 | LL | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index 5c4e180408c..b9d78b7f479 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![warn(clippy::mutex_integer)] diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 77a05ca13f4..1b0f5c1571b 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -1,5 +1,5 @@ error: Consider using an AtomicBool instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:15:5 + --> $DIR/mutex_atomic.rs:6:5 | LL | Mutex::new(true); | ^^^^^^^^^^^^^^^^ @@ -7,31 +7,31 @@ LL | Mutex::new(true); = note: `-D clippy::mutex-atomic` implied by `-D warnings` error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:16:5 + --> $DIR/mutex_atomic.rs:7:5 | LL | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:17:5 + --> $DIR/mutex_atomic.rs:8:5 | LL | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:19:5 + --> $DIR/mutex_atomic.rs:10:5 | LL | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicPtr instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:20:5 + --> $DIR/mutex_atomic.rs:11:5 | LL | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Consider using an AtomicUsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:21:5 + --> $DIR/mutex_atomic.rs:12:5 | LL | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | Mutex::new(0u32); = note: `-D clippy::mutex-integer` implied by `-D warnings` error: Consider using an AtomicIsize instead of a Mutex here. If you just want the locking behaviour and not the internal type, consider using Mutex<()>. - --> $DIR/mutex_atomic.rs:22:5 + --> $DIR/mutex_atomic.rs:13:5 | LL | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index c82f102c294..87493ab8c3d 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::needless_bool)] use std::cell::Cell; diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index a0c4ae9561d..c829bf97dd2 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:40:5 + --> $DIR/needless_bool.rs:31:5 | LL | / if x { LL | | true @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:45:5 + --> $DIR/needless_bool.rs:36:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:50:5 + --> $DIR/needless_bool.rs:41:5 | LL | / if x { LL | | true @@ -31,7 +31,7 @@ LL | | }; | |_____^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:55:5 + --> $DIR/needless_bool.rs:46:5 | LL | / if x { LL | | false @@ -41,7 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:60:5 + --> $DIR/needless_bool.rs:51:5 | LL | / if x && y { LL | | false @@ -51,7 +51,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:83:5 + --> $DIR/needless_bool.rs:74:5 | LL | / if x { LL | | return true; @@ -61,7 +61,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:92:5 + --> $DIR/needless_bool.rs:83:5 | LL | / if x { LL | | return false; @@ -71,7 +71,7 @@ LL | | }; | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:101:5 + --> $DIR/needless_bool.rs:92:5 | LL | / if x { LL | | return true; @@ -81,7 +81,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:110:5 + --> $DIR/needless_bool.rs:101:5 | LL | / if x && y { LL | | return true; @@ -91,7 +91,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:119:5 + --> $DIR/needless_bool.rs:110:5 | LL | / if x { LL | | return false; @@ -101,7 +101,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:128:5 + --> $DIR/needless_bool.rs:119:5 | LL | / if x && y { LL | | return false; @@ -111,7 +111,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:136:8 + --> $DIR/needless_bool.rs:127:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -119,19 +119,19 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:140:8 + --> $DIR/needless_bool.rs:131:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:150:8 + --> $DIR/needless_bool.rs:141:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:151:8 + --> $DIR/needless_bool.rs:142:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index bfc6e82cb55..a59254625dc 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; #[allow(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index ace40665c0c..40744160f65 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:22:15 + --> $DIR/needless_borrow.rs:13:15 | LL | let c = x(&&a); | ^^^ help: change this to: `&a` @@ -7,19 +7,19 @@ LL | let c = x(&&a); = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:29:17 + --> $DIR/needless_borrow.rs:20:17 | LL | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:36:15 + --> $DIR/needless_borrow.rs:27:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:58:34 + --> $DIR/needless_borrow.rs:49:34 | LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` @@ -27,13 +27,13 @@ LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrow.rs:59:30 + --> $DIR/needless_borrow.rs:50:30 | LL | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:59:31 + --> $DIR/needless_borrow.rs:50:31 | LL | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 3897c86f53a..968a9f354bc 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::needless_borrowed_reference)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index b7ea9499f38..1b8067f1d6d 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,5 +1,5 @@ error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:14:34 + --> $DIR/needless_borrowed_ref.rs:5:34 | LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep: `a` @@ -7,19 +7,19 @@ LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); = note: `-D clippy::needless-borrowed-reference` implied by `-D warnings` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:19:17 + --> $DIR/needless_borrowed_ref.rs:10:17 | LL | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep: `v` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:48:27 + --> $DIR/needless_borrowed_ref.rs:39:27 | LL | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` error: this pattern takes a reference on something that is being de-referenced - --> $DIR/needless_borrowed_ref.rs:48:38 + --> $DIR/needless_borrowed_ref.rs:39:38 | LL | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep: `k` diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index df449e3184f..d4815f60f51 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index c4cb187c34e..684c501c5b5 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:16:28 + --> $DIR/needless_collect.rs:7:28 | LL | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` @@ -7,19 +7,19 @@ LL | let len = sample.iter().collect::>().len(); = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:17:21 + --> $DIR/needless_collect.rs:8:21 | LL | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:20:27 + --> $DIR/needless_collect.rs:11:27 | LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|&x| x == 1)` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:21:34 + --> $DIR/needless_collect.rs:12:34 | LL | sample.iter().map(|x| (x, x)).collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 6d9b9499dce..8bb1ba6edb5 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - macro_rules! zero { ($x:expr) => { $x == 0 diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 60c853c18ad..763eaf3a70e 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -1,6 +1,6 @@ error: This else block is redundant. - --> $DIR/needless_continue.rs:36:16 + --> $DIR/needless_continue.rs:27:16 | LL | } else { | ________________^ @@ -37,7 +37,7 @@ LL | | } error: There is no need for an explicit `else` block for this `if` expression - --> $DIR/needless_continue.rs:51:9 + --> $DIR/needless_continue.rs:42:9 | LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { LL | | continue; diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index ec9df9fb3d3..427bce988bd 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::needless_pass_by_value)] #![allow( dead_code, diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index d9ce5909172..31f43bf16ba 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,5 +1,5 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:24:23 + --> $DIR/needless_pass_by_value.rs:15:23 | LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` @@ -7,25 +7,25 @@ LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec $DIR/needless_pass_by_value.rs:38:11 + --> $DIR/needless_pass_by_value.rs:29:11 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:38:22 + --> $DIR/needless_pass_by_value.rs:29:22 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:44:71 + --> $DIR/needless_pass_by_value.rs:35:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:56:18 + --> $DIR/needless_pass_by_value.rs:47:18 | LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -36,13 +36,13 @@ LL | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:69:24 + --> $DIR/needless_pass_by_value.rs:60:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:69:36 + --> $DIR/needless_pass_by_value.rs:60:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ @@ -55,19 +55,19 @@ LL | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:85:49 + --> $DIR/needless_pass_by_value.rs:76:49 | LL | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:18 + --> $DIR/needless_pass_by_value.rs:78:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:29 + --> $DIR/needless_pass_by_value.rs:78:29 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ @@ -81,13 +81,13 @@ LL | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:40 + --> $DIR/needless_pass_by_value.rs:78:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:53 + --> $DIR/needless_pass_by_value.rs:78:53 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ @@ -101,61 +101,61 @@ LL | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:100:12 + --> $DIR/needless_pass_by_value.rs:91:12 | LL | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:12 + --> $DIR/needless_pass_by_value.rs:92:12 | LL | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:110:23 + --> $DIR/needless_pass_by_value.rs:101:23 | LL | fn baz(&self, _u: U, _s: Self) {} | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:110:30 + --> $DIR/needless_pass_by_value.rs:101:30 | LL | fn baz(&self, _u: U, _s: Self) {} | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:132:24 + --> $DIR/needless_pass_by_value.rs:123:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 + --> $DIR/needless_pass_by_value.rs:121:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:29 + --> $DIR/needless_pass_by_value.rs:129:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 + --> $DIR/needless_pass_by_value.rs:121:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:45 + --> $DIR/needless_pass_by_value.rs:129:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 + --> $DIR/needless_pass_by_value.rs:121:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let CopyWrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:138:61 + --> $DIR/needless_pass_by_value.rs:129:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:130:1 + --> $DIR/needless_pass_by_value.rs:121:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,13 +185,13 @@ LL | let CopyWrapper(s) = *z; // moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:150:40 + --> $DIR/needless_pass_by_value.rs:141:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:155:20 + --> $DIR/needless_pass_by_value.rs:146:20 | LL | fn more_fun(_item: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 28f71d98fe7..3142210f9bf 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![crate_type = "proc-macro"] #![warn(clippy::needless_pass_by_value)] diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index f3d47eede48..a073cc0cfa3 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn calc_idx(i: usize) -> usize { (i + i + 20) % 4 } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 73b1d9841eb..7044fc17617 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `ns`. - --> $DIR/needless_range_loop.rs:17:14 + --> $DIR/needless_range_loop.rs:8:14 | LL | for i in 3..10 { | ^^^^^ @@ -11,7 +11,7 @@ LL | for in ns.iter().take(10).skip(3) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:38:14 + --> $DIR/needless_range_loop.rs:29:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `ms`. - --> $DIR/needless_range_loop.rs:44:14 + --> $DIR/needless_range_loop.rs:35:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | for in &mut ms { | ^^^^^^ ^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/needless_range_loop.rs:68:14 + --> $DIR/needless_range_loop.rs:59:14 | LL | for i in x..x + 4 { | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | for in vec.iter_mut().skip(x).take(4) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/needless_range_loop.rs:75:14 + --> $DIR/needless_range_loop.rs:66:14 | LL | for i in x..=x + 4 { | ^^^^^^^^^ @@ -51,7 +51,7 @@ LL | for in vec.iter_mut().skip(x).take(4 + 1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:81:14 + --> $DIR/needless_range_loop.rs:72:14 | LL | for i in 0..3 { | ^^^^ @@ -61,7 +61,7 @@ LL | for in &arr { | ^^^^^^ ^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:85:14 + --> $DIR/needless_range_loop.rs:76:14 | LL | for i in 0..2 { | ^^^^ @@ -71,7 +71,7 @@ LL | for in arr.iter().take(2) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ error: the loop variable `i` is only used to index `arr`. - --> $DIR/needless_range_loop.rs:89:14 + --> $DIR/needless_range_loop.rs:80:14 | LL | for i in 1..3 { | ^^^^ diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 101be5946f4..939233dbecb 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::needless_return)] fn test_end_of_fn() -> bool { diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index bf1083862ed..d7132ce4950 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded return statement - --> $DIR/needless_return.rs:17:5 + --> $DIR/needless_return.rs:8:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` @@ -7,43 +7,43 @@ LL | return true; = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded return statement - --> $DIR/needless_return.rs:21:5 + --> $DIR/needless_return.rs:12:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:26:9 + --> $DIR/needless_return.rs:17:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:28:9 + --> $DIR/needless_return.rs:19:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:34:17 + --> $DIR/needless_return.rs:25:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return` as shown: `false` error: unneeded return statement - --> $DIR/needless_return.rs:36:13 + --> $DIR/needless_return.rs:27:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:43:9 + --> $DIR/needless_return.rs:34:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return` as shown: `true` error: unneeded return statement - --> $DIR/needless_return.rs:45:16 + --> $DIR/needless_return.rs:36:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return` as shown: `true` diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 891c446b0ea..bfa005a19f9 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::needless_update)] #![allow(clippy::no_effect)] diff --git a/tests/ui/needless_update.stderr b/tests/ui/needless_update.stderr index 6c4ea68771b..133c834880d 100644 --- a/tests/ui/needless_update.stderr +++ b/tests/ui/needless_update.stderr @@ -1,5 +1,5 @@ error: struct update has no effect, all the fields in the struct have already been specified - --> $DIR/needless_update.rs:22:23 + --> $DIR/needless_update.rs:13:23 | LL | S { a: 1, b: 1, ..base }; | ^^^^ diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 6c132f85f0a..856a430ba2b 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This test case utilizes `f64` an easy example for `PartialOrd` only types //! but the lint itself actually validates any expression where the left //! operand implements `PartialOrd` but not `Ord`. diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index f1df2b1d98a..d05fd34ce33 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,5 +1,5 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:24:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:15:21 | LL | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _not_less = !(a_value < another_value); = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:27:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:18:30 | LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:30:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:21:24 | LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:33:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:24:33 | LL | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index f5f7525922c..d4a20ce9db1 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::neg_multiply)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 4c6d8e8d5dd..05554655451 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -1,5 +1,5 @@ error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:36:5 + --> $DIR/neg_multiply.rs:27:5 | LL | x * -1; | ^^^^^^ @@ -7,7 +7,7 @@ LL | x * -1; = note: `-D clippy::neg-multiply` implied by `-D warnings` error: Negation by multiplying with -1 - --> $DIR/neg_multiply.rs:38:5 + --> $DIR/neg_multiply.rs:29:5 | LL | -1 * x; | ^^^^^^ diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index d5a108b0b27..abcec3e92f6 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( clippy::single_match, unused_assignments, diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 95b1a04e783..416e14d676e 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,5 +1,5 @@ error: this loop never actually loops - --> $DIR/never_loop.rs:19:5 + --> $DIR/never_loop.rs:10:5 | LL | / loop { LL | | // clippy::never_loop @@ -13,7 +13,7 @@ LL | | } = note: #[deny(clippy::never_loop)] on by default error: this loop never actually loops - --> $DIR/never_loop.rs:41:5 + --> $DIR/never_loop.rs:32:5 | LL | / loop { LL | | // never loops @@ -23,7 +23,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:61:5 + --> $DIR/never_loop.rs:52:5 | LL | / loop { LL | | // never loops @@ -35,7 +35,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:63:9 + --> $DIR/never_loop.rs:54:9 | LL | / while i == 0 { LL | | // never loops @@ -44,7 +44,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:75:9 + --> $DIR/never_loop.rs:66:9 | LL | / loop { LL | | // never loops @@ -56,7 +56,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:111:5 + --> $DIR/never_loop.rs:102:5 | LL | / while let Some(y) = x { LL | | // never loops @@ -65,7 +65,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:118:5 + --> $DIR/never_loop.rs:109:5 | LL | / for x in 0..10 { LL | | // never loops @@ -77,7 +77,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:166:5 + --> $DIR/never_loop.rs:157:5 | LL | / 'outer: while a { LL | | // never loops @@ -89,7 +89,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:181:9 + --> $DIR/never_loop.rs:172:9 | LL | / while false { LL | | break 'label; diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 07d0a6bb05e..82aec070b40 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(const_fn)] #![allow(dead_code)] #![warn(clippy::new_without_default)] diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 9157f60a7e4..cd8e2837f08 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,5 +1,5 @@ error: you should consider deriving a `Default` implementation for `Foo` - --> $DIR/new_without_default.rs:17:5 + --> $DIR/new_without_default.rs:8:5 | LL | / pub fn new() -> Foo { LL | | Foo @@ -13,7 +13,7 @@ LL | #[derive(Default)] | error: you should consider deriving a `Default` implementation for `Bar` - --> $DIR/new_without_default.rs:25:5 + --> $DIR/new_without_default.rs:16:5 | LL | / pub fn new() -> Self { LL | | Bar @@ -25,7 +25,7 @@ LL | #[derive(Default)] | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> $DIR/new_without_default.rs:89:5 + --> $DIR/new_without_default.rs:80:5 | LL | / pub fn new() -> LtKo<'c> { LL | | unimplemented!() diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 6b51c50dcde..8fbfcb79860 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(box_syntax)] #![warn(clippy::no_effect)] #![allow(dead_code)] diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index cc3b069f0b5..834b9056e31 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:65:5 | LL | 0; | ^^ @@ -7,145 +7,145 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:66:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:67:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:68:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:69:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:70:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:71:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:72:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:73:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:74:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:75:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:76:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:77:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:87:5 + --> $DIR/no_effect.rs:78:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:79:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:89:5 + --> $DIR/no_effect.rs:80:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:81:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:82:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:84:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:85:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:86:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:87:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:88:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:90:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:92:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index 591e1994ee3..bd8b7521d14 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(const_string_new, const_vec_new)] #![allow(clippy::ref_in_deref, dead_code)] diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 6b592b681c9..a9584ceb7ec 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -1,5 +1,5 @@ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:19:1 + --> $DIR/non_copy_const.rs:10:1 | LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable = note: #[deny(clippy::declare_interior_mutable_const)] on by default error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:20:1 + --> $DIR/non_copy_const.rs:11:1 | LL | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:21:1 + --> $DIR/non_copy_const.rs:12:1 | LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], V | help: make this a static item: `static` error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:26:9 + --> $DIR/non_copy_const.rs:17:9 | LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -34,49 +34,49 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:50:5 + --> $DIR/non_copy_const.rs:41:5 | LL | const ATOMIC: AtomicUsize; //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:54:5 + --> $DIR/non_copy_const.rs:45:5 | LL | const INPUT: T; | ^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:54:18 + --> $DIR/non_copy_const.rs:45:18 | LL | const INPUT: T; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:57:5 + --> $DIR/non_copy_const.rs:48:5 | LL | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:57:18 + --> $DIR/non_copy_const.rs:48:18 | LL | const ASSOC: Self::NonCopyType; | ^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:61:5 + --> $DIR/non_copy_const.rs:52:5 | LL | const AN_INPUT: T = Self::INPUT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `T` to be `Copy` - --> $DIR/non_copy_const.rs:61:21 + --> $DIR/non_copy_const.rs:52:21 | LL | const AN_INPUT: T = Self::INPUT; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:26:9 + --> $DIR/non_copy_const.rs:17:9 | LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -85,49 +85,49 @@ LL | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior muta | ----------------------------------------------- in this macro invocation error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:70:5 + --> $DIR/non_copy_const.rs:61:5 | LL | const SELF_2: Self; | ^^^^^^^^^^^^^^^^^^^ | help: consider requiring `Self` to be `Copy` - --> $DIR/non_copy_const.rs:70:19 + --> $DIR/non_copy_const.rs:61:19 | LL | const SELF_2: Self; | ^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:91:5 + --> $DIR/non_copy_const.rs:82:5 | LL | const ASSOC_3: AtomicUsize = AtomicUsize::new(14); //~ ERROR interior mutable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:94:5 + --> $DIR/non_copy_const.rs:85:5 | LL | const U_SELF: U = U::SELF_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `U` to be `Copy` - --> $DIR/non_copy_const.rs:94:19 + --> $DIR/non_copy_const.rs:85:19 | LL | const U_SELF: U = U::SELF_2; | ^ error: a const item should never be interior mutable - --> $DIR/non_copy_const.rs:97:5 + --> $DIR/non_copy_const.rs:88:5 | LL | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider requiring `>::NonCopyType` to be `Copy` - --> $DIR/non_copy_const.rs:97:20 + --> $DIR/non_copy_const.rs:88:20 | LL | const T_ASSOC: T::NonCopyType = T::ASSOC; | ^^^^^^^^^^^^^^ error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:104:5 + --> $DIR/non_copy_const.rs:95:5 | LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ @@ -136,7 +136,7 @@ LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:105:16 + --> $DIR/non_copy_const.rs:96:16 | LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability | ^^^^^^ @@ -144,7 +144,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:107:5 + --> $DIR/non_copy_const.rs:98:5 | LL | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ @@ -152,7 +152,7 @@ LL | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutabi = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:108:16 + --> $DIR/non_copy_const.rs:99:16 | LL | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability | ^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR inte = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:111:22 + --> $DIR/non_copy_const.rs:102:22 | LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -168,7 +168,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:112:25 + --> $DIR/non_copy_const.rs:103:25 | LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -176,7 +176,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:113:27 + --> $DIR/non_copy_const.rs:104:27 | LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -184,7 +184,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:114:26 + --> $DIR/non_copy_const.rs:105:26 | LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -192,7 +192,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:125:14 + --> $DIR/non_copy_const.rs:116:14 | LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:126:14 + --> $DIR/non_copy_const.rs:117:14 | LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:127:19 + --> $DIR/non_copy_const.rs:118:19 | LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -216,7 +216,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:128:14 + --> $DIR/non_copy_const.rs:119:14 | LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -224,7 +224,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:129:13 + --> $DIR/non_copy_const.rs:120:13 | LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:135:13 + --> $DIR/non_copy_const.rs:126:13 | LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:140:5 + --> $DIR/non_copy_const.rs:131:5 | LL | CELL.set(2); //~ ERROR interior mutability | ^^^^ @@ -248,7 +248,7 @@ LL | CELL.set(2); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:141:16 + --> $DIR/non_copy_const.rs:132:16 | LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ @@ -256,7 +256,7 @@ LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:154:5 + --> $DIR/non_copy_const.rs:145:5 | LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ @@ -264,7 +264,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:155:16 + --> $DIR/non_copy_const.rs:146:16 | LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 86c9edc821d..b1d7d8e52a8 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all, clippy::similar_names)] #![allow(unused, clippy::println_empty_string)] diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 8729db18dff..f4274b87cdc 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,110 +1,110 @@ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:24:9 + --> $DIR/non_expressive_names.rs:15:9 | LL | let bpple: i32; | ^^^^^ | = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here - --> $DIR/non_expressive_names.rs:22:9 + --> $DIR/non_expressive_names.rs:13:9 | LL | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `b_pple` - --> $DIR/non_expressive_names.rs:24:9 + --> $DIR/non_expressive_names.rs:15:9 | LL | let bpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:26:9 + --> $DIR/non_expressive_names.rs:17:9 | LL | let cpple: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:22:9 + --> $DIR/non_expressive_names.rs:13:9 | LL | let apple: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `c_pple` - --> $DIR/non_expressive_names.rs:26:9 + --> $DIR/non_expressive_names.rs:17:9 | LL | let cpple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:50:9 + --> $DIR/non_expressive_names.rs:41:9 | LL | let bluby: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:49:9 + --> $DIR/non_expressive_names.rs:40:9 | LL | let blubx: i32; | ^^^^^ help: separate the discriminating character by an underscore like: `blub_y` - --> $DIR/non_expressive_names.rs:50:9 + --> $DIR/non_expressive_names.rs:41:9 | LL | let bluby: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:54:9 + --> $DIR/non_expressive_names.rs:45:9 | LL | let coke: i32; | ^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:52:9 + --> $DIR/non_expressive_names.rs:43:9 | LL | let cake: i32; | ^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:72:9 + --> $DIR/non_expressive_names.rs:63:9 | LL | let xyzeabc: i32; | ^^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:70:9 + --> $DIR/non_expressive_names.rs:61:9 | LL | let xyz1abc: i32; | ^^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:76:9 + --> $DIR/non_expressive_names.rs:67:9 | LL | let parsee: i32; | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:74:9 + --> $DIR/non_expressive_names.rs:65:9 | LL | let parser: i32; | ^^^^^^ help: separate the discriminating character by an underscore like: `parse_e` - --> $DIR/non_expressive_names.rs:76:9 + --> $DIR/non_expressive_names.rs:67:9 | LL | let parsee: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:90:16 + --> $DIR/non_expressive_names.rs:81:16 | LL | bpple: sprang, | ^^^^^^ | note: existing binding defined here - --> $DIR/non_expressive_names.rs:89:16 + --> $DIR/non_expressive_names.rs:80:16 | LL | apple: spring, | ^^^^^^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:125:17 + --> $DIR/non_expressive_names.rs:116:17 | LL | let e: i32; | ^ @@ -112,25 +112,25 @@ LL | let e: i32; = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:128:17 + --> $DIR/non_expressive_names.rs:119:17 | LL | let e: i32; | ^ error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:129:17 + --> $DIR/non_expressive_names.rs:120:17 | LL | let f: i32; | ^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:133:13 + --> $DIR/non_expressive_names.rs:124:13 | LL | e => panic!(), | ^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:143:9 + --> $DIR/non_expressive_names.rs:134:9 | LL | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ @@ -138,31 +138,31 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:144:9 + --> $DIR/non_expressive_names.rs:135:9 | LL | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:145:9 + --> $DIR/non_expressive_names.rs:136:9 | LL | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:165:13 + --> $DIR/non_expressive_names.rs:156:13 | LL | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:166:13 + --> $DIR/non_expressive_names.rs:157:13 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:167:13 + --> $DIR/non_expressive_names.rs:158:13 | LL | let __1___2 = 12; | ^^^^^^^ diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index b121aae788c..ff68d38c73b 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::io; struct MyError(()); // doesn't implement Debug diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 4ccca10a463..99e62313183 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,5 +1,5 @@ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:23:5 + --> $DIR/ok_expect.rs:14:5 | LL | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | res.ok().expect("disaster!"); = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:29:5 + --> $DIR/ok_expect.rs:20:5 | LL | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:31:5 + --> $DIR/ok_expect.rs:22:5 | LL | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:33:5 + --> $DIR/ok_expect.rs:24:5 | LL | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/ok_expect.rs:35:5 + --> $DIR/ok_expect.rs:26:5 | LL | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/ok_if_let.rs b/tests/ui/ok_if_let.rs index 3ede64ce3aa..61db3113052 100644 --- a/tests/ui/ok_if_let.rs +++ b/tests/ui/ok_if_let.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::if_let_some_result)] fn str_to_int(x: &str) -> i32 { diff --git a/tests/ui/ok_if_let.stderr b/tests/ui/ok_if_let.stderr index 4567493a7c2..e3e6c5c4634 100644 --- a/tests/ui/ok_if_let.stderr +++ b/tests/ui/ok_if_let.stderr @@ -1,5 +1,5 @@ error: Matching on `Some` with `ok()` is redundant - --> $DIR/ok_if_let.rs:13:5 + --> $DIR/ok_if_let.rs:4:5 | LL | / if let Some(y) = x.parse().ok() { LL | | y diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index 1112b6794cf..bf43deca12c 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused_variables, clippy::blacklisted_name)] use std::collections::HashSet; diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 956e2ee754c..f5c5b970261 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -1,5 +1,5 @@ error: needlessly taken reference of both operands - --> $DIR/op_ref.rs:19:15 + --> $DIR/op_ref.rs:10:15 | LL | let foo = &5 - &6; | ^^^^^^^ @@ -11,7 +11,7 @@ LL | let foo = 5 - 6; | ^ ^ error: taken reference of right operand - --> $DIR/op_ref.rs:27:8 + --> $DIR/op_ref.rs:18:8 | LL | if b < &a { | ^^^^-- diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index f4d0af94b3f..9063fafbcd0 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::fs::OpenOptions; #[allow(unused_must_use)] diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 55c0429800b..addb0c4e1a5 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,5 +1,5 @@ error: file opened with "truncate" and "read" - --> $DIR/open_options.rs:15:5 + --> $DIR/open_options.rs:6:5 | LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); = note: `-D clippy::nonsensical-open-options` implied by `-D warnings` error: file opened with "append" and "truncate" - --> $DIR/open_options.rs:16:5 + --> $DIR/open_options.rs:7:5 | LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "read" is called more than once - --> $DIR/open_options.rs:18:5 + --> $DIR/open_options.rs:9:5 | LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "create" is called more than once - --> $DIR/open_options.rs:19:5 + --> $DIR/open_options.rs:10:5 | LL | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "write" is called more than once - --> $DIR/open_options.rs:20:5 + --> $DIR/open_options.rs:11:5 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "append" is called more than once - --> $DIR/open_options.rs:21:5 + --> $DIR/open_options.rs:12:5 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method "truncate" is called more than once - --> $DIR/open_options.rs:22:5 + --> $DIR/open_options.rs:13:5 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_map_unit_fn.rs b/tests/ui/option_map_unit_fn.rs index db473f9b41e..1d2a3a17ee0 100644 --- a/tests/ui/option_map_unit_fn.rs +++ b/tests/ui/option_map_unit_fn.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::option_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/option_map_unit_fn.stderr b/tests/ui/option_map_unit_fn.stderr index 18ddcec5edd..16e355ad0b2 100644 --- a/tests/ui/option_map_unit_fn.stderr +++ b/tests/ui/option_map_unit_fn.stderr @@ -1,5 +1,5 @@ error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:41:5 + --> $DIR/option_map_unit_fn.rs:32:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -9,7 +9,7 @@ LL | x.field.map(do_nothing); = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:43:5 + --> $DIR/option_map_unit_fn.rs:34:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | x.field.map(do_nothing); | help: try this: `if let Some(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:45:5 + --> $DIR/option_map_unit_fn.rs:36:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -25,7 +25,7 @@ LL | x.field.map(diverge); | help: try this: `if let Some(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:51:5 + --> $DIR/option_map_unit_fn.rs:42:5 | LL | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -33,7 +33,7 @@ LL | x.field.map(|value| x.do_option_nothing(value + captured)); | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:53:5 + --> $DIR/option_map_unit_fn.rs:44:5 | LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -41,7 +41,7 @@ LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:56:5 + --> $DIR/option_map_unit_fn.rs:47:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -49,7 +49,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:58:5 + --> $DIR/option_map_unit_fn.rs:49:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -57,7 +57,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:60:5 + --> $DIR/option_map_unit_fn.rs:51:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -65,7 +65,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:62:5 + --> $DIR/option_map_unit_fn.rs:53:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -73,7 +73,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:65:5 + --> $DIR/option_map_unit_fn.rs:56:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -81,7 +81,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:67:5 + --> $DIR/option_map_unit_fn.rs:58:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -89,7 +89,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:69:5 + --> $DIR/option_map_unit_fn.rs:60:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -97,7 +97,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:71:5 + --> $DIR/option_map_unit_fn.rs:62:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -105,7 +105,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:76:5 + --> $DIR/option_map_unit_fn.rs:67:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -113,7 +113,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:78:5 + --> $DIR/option_map_unit_fn.rs:69:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -121,7 +121,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:80:5 + --> $DIR/option_map_unit_fn.rs:71:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -129,7 +129,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:83:5 + --> $DIR/option_map_unit_fn.rs:74:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -137,7 +137,7 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:86:5 + --> $DIR/option_map_unit_fn.rs:77:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -145,7 +145,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:88:5 + --> $DIR/option_map_unit_fn.rs:79:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -153,7 +153,7 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:92:5 + --> $DIR/option_map_unit_fn.rs:83:5 | LL | x.field.map(|value| { | _____^ @@ -167,7 +167,7 @@ LL | || }); | error: called `map(f)` on an Option value where `f` is a unit closure - --> $DIR/option_map_unit_fn.rs:96:5 + --> $DIR/option_map_unit_fn.rs:87:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -175,7 +175,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | help: try this: `if let Some(value) = x.field { ... }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:99:5 + --> $DIR/option_map_unit_fn.rs:90:5 | LL | Some(42).map(diverge); | ^^^^^^^^^^^^^^^^^^^^^- @@ -183,7 +183,7 @@ LL | Some(42).map(diverge); | help: try this: `if let Some(_) = Some(42) { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:100:5 + --> $DIR/option_map_unit_fn.rs:91:5 | LL | "12".parse::().ok().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -191,7 +191,7 @@ LL | "12".parse::().ok().map(diverge); | help: try this: `if let Some(_) = "12".parse::().ok() { diverge(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:101:5 + --> $DIR/option_map_unit_fn.rs:92:5 | LL | Some(plus_one(1)).map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -199,7 +199,7 @@ LL | Some(plus_one(1)).map(do_nothing); | help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }` error: called `map(f)` on an Option value where `f` is a unit function - --> $DIR/option_map_unit_fn.rs:105:5 + --> $DIR/option_map_unit_fn.rs:96:5 | LL | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index fcfd4e6ea56..e2e649a8108 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn input(_: Option>) {} fn output() -> Option> { diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 992f14c825f..9e9425cf954 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,5 +1,5 @@ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:10:13 + --> $DIR/option_option.rs:1:13 | LL | fn input(_: Option>) {} | ^^^^^^^^^^^^^^^^^^ @@ -7,49 +7,49 @@ LL | fn input(_: Option>) {} = note: `-D clippy::option-option` implied by `-D warnings` error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:12:16 + --> $DIR/option_option.rs:3:16 | LL | fn output() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:16:27 + --> $DIR/option_option.rs:7:27 | LL | fn output_nested() -> Vec>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:21:30 + --> $DIR/option_option.rs:12:30 | LL | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:26:8 + --> $DIR/option_option.rs:17:8 | LL | x: Option>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:30:23 + --> $DIR/option_option.rs:21:23 | LL | fn struct_fn() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:36:22 + --> $DIR/option_option.rs:27:22 | LL | fn trait_fn() -> Option>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:40:11 + --> $DIR/option_option.rs:31:11 | LL | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:41:17 + --> $DIR/option_option.rs:32:17 | LL | Struct { x: Option> }, | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index a5cff3df9d7..84332040dba 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::many_single_char_names)] #![warn(clippy::overflow_check_conditional)] diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 078a1a5941c..ad66135d326 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,5 +1,5 @@ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:17:8 + --> $DIR/overflow_check_conditional.rs:8:8 | LL | if a + b < a {} | ^^^^^^^^^ @@ -7,43 +7,43 @@ LL | if a + b < a {} = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:18:8 + --> $DIR/overflow_check_conditional.rs:9:8 | LL | if a > a + b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:19:8 + --> $DIR/overflow_check_conditional.rs:10:8 | LL | if a + b < b {} | ^^^^^^^^^ error: You are trying to use classic C overflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:20:8 + --> $DIR/overflow_check_conditional.rs:11:8 | LL | if b > a + b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:21:8 + --> $DIR/overflow_check_conditional.rs:12:8 | LL | if a - b > b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:22:8 + --> $DIR/overflow_check_conditional.rs:13:8 | LL | if b < a - b {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:23:8 + --> $DIR/overflow_check_conditional.rs:14:8 | LL | if a - b > a {} | ^^^^^^^^^ error: You are trying to use classic C underflow conditions that will fail in Rust. - --> $DIR/overflow_check_conditional.rs:24:8 + --> $DIR/overflow_check_conditional.rs:15:8 | LL | if a < a - b {} | ^^^^^^^^^ diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 93dec197ff5..f205e07cd30 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::panic_params, clippy::unimplemented)] fn missing() { diff --git a/tests/ui/panic_unimplemented.stderr b/tests/ui/panic_unimplemented.stderr index 7bc83a287c1..588fa187b4a 100644 --- a/tests/ui/panic_unimplemented.stderr +++ b/tests/ui/panic_unimplemented.stderr @@ -1,5 +1,5 @@ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:14:16 + --> $DIR/panic_unimplemented.rs:5:16 | LL | panic!("{}"); | ^^^^ @@ -7,25 +7,25 @@ LL | panic!("{}"); = note: `-D clippy::panic-params` implied by `-D warnings` error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:16:16 + --> $DIR/panic_unimplemented.rs:7:16 | LL | panic!("{:?}"); | ^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:18:23 + --> $DIR/panic_unimplemented.rs:9:23 | LL | assert!(true, "here be missing values: {}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you probably are missing some parameter in your format string - --> $DIR/panic_unimplemented.rs:21:12 + --> $DIR/panic_unimplemented.rs:12:12 | LL | panic!("{{{this}}}"); | ^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panic_unimplemented.rs:64:5 + --> $DIR/panic_unimplemented.rs:55:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index e1e0413fcea..1338d3c74d5 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] struct Foo; diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index ac040acc306..b92da4511b4 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -1,5 +1,5 @@ error: re-implementing `PartialEq::ne` is unnecessary - --> $DIR/partialeq_ne_impl.rs:18:5 + --> $DIR/partialeq_ne_impl.rs:9:5 | LL | / fn ne(&self, _: &Foo) -> bool { LL | | false diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index e10afdb86b8..576e6c9ab92 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] #![warn(clippy::all)] diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 74e8b9ae776..39dc034a014 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,5 +1,5 @@ error: the `y @ _` pattern can be written as just `y` - --> $DIR/patterns.rs:17:9 + --> $DIR/patterns.rs:8:9 | LL | y @ _ => (), | ^^^^^ diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 82009cd3873..e4f65b46ea0 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::precedence)] #[allow(clippy::identity_op)] #[allow(clippy::eq_op)] diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 2d917b3cbdb..01c59a5b8ea 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,5 +1,5 @@ error: operator precedence can trip the unwary - --> $DIR/precedence.rs:24:5 + --> $DIR/precedence.rs:15:5 | LL | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` @@ -7,49 +7,49 @@ LL | 1 << 2 + 3; = note: `-D clippy::precedence` implied by `-D warnings` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:25:5 + --> $DIR/precedence.rs:16:5 | LL | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:26:5 + --> $DIR/precedence.rs:17:5 | LL | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:27:5 + --> $DIR/precedence.rs:18:5 | LL | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:28:5 + --> $DIR/precedence.rs:19:5 | LL | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:29:5 + --> $DIR/precedence.rs:20:5 | LL | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:30:5 + --> $DIR/precedence.rs:21:5 | LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:31:5 + --> $DIR/precedence.rs:22:5 | LL | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:32:5 + --> $DIR/precedence.rs:23:5 | LL | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` diff --git a/tests/ui/print.rs b/tests/ui/print.rs index a43482cba62..366ccc2b3bd 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::print_literal, clippy::write_literal)] #![warn(clippy::print_stdout, clippy::use_debug)] diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 9635011b906..12c5a0bdaa0 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,5 +1,5 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:20:19 + --> $DIR/print.rs:11:19 | LL | write!(f, "{:?}", 43.1415) | ^^^^^^ @@ -7,13 +7,13 @@ LL | write!(f, "{:?}", 43.1415) = note: `-D clippy::use-debug` implied by `-D warnings` error: use of `Debug`-based formatting - --> $DIR/print.rs:27:19 + --> $DIR/print.rs:18:19 | LL | write!(f, "{:?}", 42.718) | ^^^^^^ error: use of `println!` - --> $DIR/print.rs:32:5 + --> $DIR/print.rs:23:5 | LL | println!("Hello"); | ^^^^^^^^^^^^^^^^^ @@ -21,37 +21,37 @@ LL | println!("Hello"); = note: `-D clippy::print-stdout` implied by `-D warnings` error: use of `print!` - --> $DIR/print.rs:33:5 + --> $DIR/print.rs:24:5 | LL | print!("Hello"); | ^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:35:5 + --> $DIR/print.rs:26:5 | LL | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:37:5 + --> $DIR/print.rs:28:5 | LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:37:12 + --> $DIR/print.rs:28:12 | LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^ error: use of `print!` - --> $DIR/print.rs:39:5 + --> $DIR/print.rs:30:5 | LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:39:12 + --> $DIR/print.rs:30:12 | LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^ diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 74756384067..40ed18e9302 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::print_literal)] fn main() { diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index be55795d1ac..fc502e9f71d 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -1,5 +1,5 @@ error: literal with an empty format string - --> $DIR/print_literal.rs:31:71 + --> $DIR/print_literal.rs:22:71 | LL | println!("{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ @@ -7,79 +7,79 @@ LL | println!("{} of {:b} people know binary, the other half doesn't", 1, 2) = note: `-D clippy::print-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/print_literal.rs:32:24 + --> $DIR/print_literal.rs:23:24 | LL | print!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:33:36 + --> $DIR/print_literal.rs:24:36 | LL | println!("Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:34:26 + --> $DIR/print_literal.rs:25:26 | LL | println!("Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:35:30 + --> $DIR/print_literal.rs:26:30 | LL | println!("10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:36:28 + --> $DIR/print_literal.rs:27:28 | LL | println!("2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/print_literal.rs:41:25 + --> $DIR/print_literal.rs:32:25 | LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:41:34 + --> $DIR/print_literal.rs:32:34 | LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:42:25 + --> $DIR/print_literal.rs:33:25 | LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:42:34 + --> $DIR/print_literal.rs:33:34 | LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:45:35 + --> $DIR/print_literal.rs:36:35 | LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:45:50 + --> $DIR/print_literal.rs:36:50 | LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:46:35 + --> $DIR/print_literal.rs:37:35 | LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/print_literal.rs:46:50 + --> $DIR/print_literal.rs:37:50 | LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 351fd60bc36..991cd7311e5 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::print_literal)] #![warn(clippy::print_with_newline)] diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 2d76e447145..a731212be87 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -1,5 +1,5 @@ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:14:5 + --> $DIR/print_with_newline.rs:5:5 | LL | print!("Hello/n"); | ^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | print!("Hello/n"); = note: `-D clippy::print-with-newline` implied by `-D warnings` error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:15:5 + --> $DIR/print_with_newline.rs:6:5 | LL | print!("Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:16:5 + --> $DIR/print_with_newline.rs:7:5 | LL | print!("Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead - --> $DIR/print_with_newline.rs:17:5 + --> $DIR/print_with_newline.rs:8:5 | LL | print!("{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed index 4ca151453fe..4e84511d7b0 100644 --- a/tests/ui/println_empty_string.fixed +++ b/tests/ui/println_empty_string.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 21f944916db..9fdfb03a366 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 2370a3f1e28..689624a0fa0 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,5 +1,5 @@ error: using `println!("")` - --> $DIR/println_empty_string.rs:14:5 + --> $DIR/println_empty_string.rs:5:5 | LL | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` @@ -7,7 +7,7 @@ LL | println!(""); = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` - --> $DIR/println_empty_string.rs:17:14 + --> $DIR/println_empty_string.rs:8:14 | LL | _ => println!(""), | ^^^^^^^^^^^^ help: replace it with: `println!()` diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 0d7a829888e..1ce6081bf94 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused, clippy::many_single_char_names)] #![warn(clippy::ptr_arg)] diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index af5003c9b95..34516368e5e 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:15:14 + --> $DIR/ptr_arg.rs:6:14 | LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -7,19 +7,19 @@ LL | fn do_vec(x: &Vec) { = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:24:14 + --> $DIR/ptr_arg.rs:15:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:37:18 + --> $DIR/ptr_arg.rs:28:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. - --> $DIR/ptr_arg.rs:50:14 + --> $DIR/ptr_arg.rs:41:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -37,7 +37,7 @@ LL | x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:59:18 + --> $DIR/ptr_arg.rs:50:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -59,7 +59,7 @@ LL | x.to_string() | error: writing `&String` instead of `&str` involves a new object where a slice will do. - --> $DIR/ptr_arg.rs:67:44 + --> $DIR/ptr_arg.rs:58:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -77,7 +77,7 @@ LL | let c = y; | ^ error: using a reference to `Cow` is not recommended. - --> $DIR/ptr_arg.rs:81:25 + --> $DIR/ptr_arg.rs:72:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index c9f58896ae1..ebdd6c4003d 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 23eb4c6ce8a..3416c4b727a 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix fn main() { diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index 98e3ff92a6e..b5c7a03e277 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,5 +1,5 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:21:9 + --> $DIR/ptr_offset_with_cast.rs:12:9 | LL | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` @@ -7,7 +7,7 @@ LL | ptr.offset(offset_usize as isize); = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:25:9 + --> $DIR/ptr_offset_with_cast.rs:16:9 | LL | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 7e749d164ca..56ccf1d432f 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn some_func(a: Option) -> Option { if a.is_none() { return None; diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index a0b87813770..522501d58c6 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,5 +1,5 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:11:5 + --> $DIR/question_mark.rs:2:5 | LL | / if a.is_none() { LL | | return None; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:56:9 + --> $DIR/question_mark.rs:47:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace_it_with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:60:9 + --> $DIR/question_mark.rs:51:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace_it_with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:64:17 + --> $DIR/question_mark.rs:55:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace_it_with: `Some(self.opt?)` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:81:9 + --> $DIR/question_mark.rs:72:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -44,7 +44,7 @@ LL | | } | |_________^ help: replace_it_with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:89:9 + --> $DIR/question_mark.rs:80:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -52,7 +52,7 @@ LL | | } | |_________^ help: replace_it_with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:97:9 + --> $DIR/question_mark.rs:88:9 | LL | / if self.opt.is_none() { LL | | return None; diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 1eab67e20d0..d0c5cc93bd9 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - struct NotARange; impl NotARange { fn step_by(&self, _: u32) {} diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index b9a0a10c207..387d1f674cb 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,5 +1,5 @@ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:17:13 + --> $DIR/range.rs:8:13 | LL | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | let _ = (0..1).step_by(0); = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:21:13 + --> $DIR/range.rs:12:13 | LL | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:22:13 + --> $DIR/range.rs:13:13 | LL | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:25:13 + --> $DIR/range.rs:16:13 | LL | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: It is more idiomatic to use v1.iter().enumerate() - --> $DIR/range.rs:33:14 + --> $DIR/range.rs:24:14 | LL | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _x = v1.iter().zip(0..v1.len()); = note: `-D clippy::range-zip-with-len` implied by `-D warnings` error: Iterator::step_by(0) will panic at runtime - --> $DIR/range.rs:37:13 + --> $DIR/range.rs:28:13 | LL | let _ = v1.iter().step_by(2 / 3); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index d8c955ba73f..54aec853d3b 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn f() -> usize { 42 } diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index b1c93933ccc..9ebc22e1625 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,5 +1,5 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:19:14 + --> $DIR/range_plus_minus_one.rs:10:14 | LL | for _ in 0..3 + 1 {} | ^^^^^^^^ help: use: `0..=3` @@ -7,25 +7,25 @@ LL | for _ in 0..3 + 1 {} = note: `-D clippy::range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:22:14 + --> $DIR/range_plus_minus_one.rs:13:14 | LL | for _ in 0..1 + 5 {} | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:25:14 + --> $DIR/range_plus_minus_one.rs:16:14 | LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:31:14 + --> $DIR/range_plus_minus_one.rs:22:14 | LL | for _ in 0..(1 + f()) {} | ^^^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:35:13 + --> $DIR/range_plus_minus_one.rs:26:13 | LL | let _ = ..=11 - 1; | ^^^^^^^^^ help: use: `..11` @@ -33,19 +33,19 @@ LL | let _ = ..=11 - 1; = note: `-D clippy::range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:36:13 + --> $DIR/range_plus_minus_one.rs:27:13 | LL | let _ = ..=(11 - 1); | ^^^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:37:13 + --> $DIR/range_plus_minus_one.rs:28:13 | LL | let _ = (1..11 + 1); | ^^^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:38:13 + --> $DIR/range_plus_minus_one.rs:29:13 | LL | let _ = (f() + 1)..(f() + 1); | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 09d4d392725..6e9ad71e55b 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -1,12 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::redundant_clone)] use std::ffi::OsString; diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index aef6b9b3d2f..c8f6cacab2b 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,120 +1,120 @@ error: redundant clone - --> $DIR/redundant_clone.rs:16:41 + --> $DIR/redundant_clone.rs:7:41 | LL | let _ = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | = note: `-D clippy::redundant-clone` implied by `-D warnings` note: this value is dropped without further use - --> $DIR/redundant_clone.rs:16:13 + --> $DIR/redundant_clone.rs:7:13 | LL | let _ = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:19:14 + --> $DIR/redundant_clone.rs:10:14 | LL | let _ = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:19:13 + --> $DIR/redundant_clone.rs:10:13 | LL | let _ = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:22:14 + --> $DIR/redundant_clone.rs:13:14 | LL | let _ = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:22:13 + --> $DIR/redundant_clone.rs:13:13 | LL | let _ = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:25:14 + --> $DIR/redundant_clone.rs:16:14 | LL | let _ = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:25:13 + --> $DIR/redundant_clone.rs:16:13 | LL | let _ = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:27:41 + --> $DIR/redundant_clone.rs:18:41 | LL | let _ = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:27:13 + --> $DIR/redundant_clone.rs:18:13 | LL | let _ = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:29:41 + --> $DIR/redundant_clone.rs:20:41 | LL | let _ = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:29:13 + --> $DIR/redundant_clone.rs:20:13 | LL | let _ = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:31:28 + --> $DIR/redundant_clone.rs:22:28 | LL | let _ = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:31:13 + --> $DIR/redundant_clone.rs:22:13 | LL | let _ = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:33:28 + --> $DIR/redundant_clone.rs:24:28 | LL | let _ = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:33:13 + --> $DIR/redundant_clone.rs:24:13 | LL | let _ = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:40:18 + --> $DIR/redundant_clone.rs:31:18 | LL | let _ = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:40:13 + --> $DIR/redundant_clone.rs:31:13 | LL | let _ = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:50:22 + --> $DIR/redundant_clone.rs:41:22 | LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:50:21 + --> $DIR/redundant_clone.rs:41:21 | LL | (a.clone(), a.clone()) | ^ diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index 46c56922974..2304871f213 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::redundant_closure_call)] fn main() { diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 6a41a07bd95..9c827fd8f17 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,5 +1,5 @@ error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:21:5 + --> $DIR/redundant_closure_call.rs:12:5 | LL | i = closure(); | ^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | i = closure(); = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:24:5 + --> $DIR/redundant_closure_call.rs:15:5 | LL | i = closure(3); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:13:13 + --> $DIR/redundant_closure_call.rs:4:13 | LL | let a = (|| 42)(); | ^^^^^^^^^ help: Try doing something like: : `42` error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:16:17 + --> $DIR/redundant_closure_call.rs:7:17 | LL | let mut k = (|m| m + 1)(i); | ^^^^^^^^^^^^^^ error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:18:9 + --> $DIR/redundant_closure_call.rs:9:9 | LL | k = (|a, b| a * b)(1, 5); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 60569372e5d..f5c3fa66224 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::redundant_field_names)] #![allow(unused_variables)] #![feature(inclusive_range, inclusive_range_fields, inclusive_range_methods)] diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 5675f8beb7a..7976292df22 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,5 +1,5 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:43:9 + --> $DIR/redundant_field_names.rs:34:9 | LL | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` @@ -7,37 +7,37 @@ LL | gender: gender, = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:44:9 + --> $DIR/redundant_field_names.rs:35:9 | LL | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:65:25 + --> $DIR/redundant_field_names.rs:56:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:66:23 + --> $DIR/redundant_field_names.rs:57:23 | LL | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:67:21 + --> $DIR/redundant_field_names.rs:58:21 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:67:35 + --> $DIR/redundant_field_names.rs:58:35 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:69:32 + --> $DIR/redundant_field_names.rs:60:32 | LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index 3744695a535..8e8d4b59ba4 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index 0511fbc7e09..baed95d6f2e 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:14:12 + --> $DIR/redundant_pattern_matching.rs:5:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^------------------------ help: try this: `if Ok::(42).is_ok()` @@ -7,25 +7,25 @@ LL | if let Ok(_) = Ok::(42) {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:16:12 + --> $DIR/redundant_pattern_matching.rs:7:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^------------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:18:12 + --> $DIR/redundant_pattern_matching.rs:9:12 | LL | if let None = None::<()> {} | -------^^^^---------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:20:12 + --> $DIR/redundant_pattern_matching.rs:11:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^-------------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:34:5 + --> $DIR/redundant_pattern_matching.rs:25:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -34,7 +34,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:39:5 + --> $DIR/redundant_pattern_matching.rs:30:5 | LL | / match Ok::(42) { LL | | Ok(_) => false, @@ -43,7 +43,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:44:5 + --> $DIR/redundant_pattern_matching.rs:35:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:49:5 + --> $DIR/redundant_pattern_matching.rs:40:5 | LL | / match Err::(42) { LL | | Ok(_) => true, @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:54:5 + --> $DIR/redundant_pattern_matching.rs:45:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -70,7 +70,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:59:5 + --> $DIR/redundant_pattern_matching.rs:50:5 | LL | / match None::<()> { LL | | Some(_) => false, diff --git a/tests/ui/reference.rs b/tests/ui/reference.rs index bab0c21ffd9..c63997fa858 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/reference.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn get_number() -> usize { 10 } diff --git a/tests/ui/reference.stderr b/tests/ui/reference.stderr index eaaacc7bcbe..aea95a7fa9f 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/reference.stderr @@ -1,5 +1,5 @@ error: immediately dereferencing a reference - --> $DIR/reference.rs:25:13 + --> $DIR/reference.rs:16:13 | LL | let b = *&a; | ^^^ help: try this: `a` @@ -7,61 +7,61 @@ LL | let b = *&a; = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference - --> $DIR/reference.rs:27:13 + --> $DIR/reference.rs:18:13 | LL | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try this: `get_number()` error: immediately dereferencing a reference - --> $DIR/reference.rs:32:13 + --> $DIR/reference.rs:23:13 | LL | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` error: immediately dereferencing a reference - --> $DIR/reference.rs:36:13 + --> $DIR/reference.rs:27:13 | LL | let b = *&(a); | ^^^^^ help: try this: `(a)` error: immediately dereferencing a reference - --> $DIR/reference.rs:38:13 + --> $DIR/reference.rs:29:13 | LL | let b = *(&a); | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:41:13 + --> $DIR/reference.rs:32:13 | LL | let b = *((&a)); | ^^^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:43:13 + --> $DIR/reference.rs:34:13 | LL | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:45:14 + --> $DIR/reference.rs:36:14 | LL | let b = **&aref; | ^^^^^^ help: try this: `aref` error: immediately dereferencing a reference - --> $DIR/reference.rs:49:14 + --> $DIR/reference.rs:40:14 | LL | let b = **&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:53:17 + --> $DIR/reference.rs:44:17 | LL | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference - --> $DIR/reference.rs:60:18 + --> $DIR/reference.rs:51:18 | LL | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 2d9c3482850..b523fa5b711 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] #![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_macro)] diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index b6a4f6eb2af..1394a9b63bc 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,5 +1,5 @@ error: trivial regex - --> $DIR/regex.rs:22:45 + --> $DIR/regex.rs:13:45 | LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ @@ -8,7 +8,7 @@ LL | let pipe_in_wrong_position = Regex::new("|"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:23:60 + --> $DIR/regex.rs:14:60 | LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ @@ -16,7 +16,7 @@ LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:24:42 + --> $DIR/regex.rs:15:42 | LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ @@ -24,19 +24,19 @@ LL | let wrong_char_ranice = Regex::new("[z-a]"); = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:25:37 + --> $DIR/regex.rs:16:37 | LL | let some_unicode = Regex::new("[é-è]"); | ^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:27:33 + --> $DIR/regex.rs:18:33 | LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:29:53 + --> $DIR/regex.rs:20:53 | LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ @@ -44,43 +44,43 @@ LL | let binary_pipe_in_wrong_position = BRegex::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:30:41 + --> $DIR/regex.rs:21:41 | LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:31:56 + --> $DIR/regex.rs:22:56 | LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:43:37 + --> $DIR/regex.rs:34:37 | LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ error: regex syntax error on position 0: unclosed group - --> $DIR/regex.rs:44:39 + --> $DIR/regex.rs:35:39 | LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:46:45 + --> $DIR/regex.rs:37:45 | LL | let raw_string_error = Regex::new(r"[...//...]"); | ^^ error: regex syntax error: unrecognized escape sequence - --> $DIR/regex.rs:47:46 + --> $DIR/regex.rs:38:46 | LL | let raw_string_error = Regex::new(r#"[...//...]"#); | ^^ error: trivial regex - --> $DIR/regex.rs:51:33 + --> $DIR/regex.rs:42:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:53:48 + --> $DIR/regex.rs:44:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:55:42 + --> $DIR/regex.rs:46:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -104,7 +104,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:57:40 + --> $DIR/regex.rs:48:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -112,7 +112,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:59:39 + --> $DIR/regex.rs:50:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -120,7 +120,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:61:39 + --> $DIR/regex.rs:52:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -128,7 +128,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:63:40 + --> $DIR/regex.rs:54:40 | LL | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ @@ -136,7 +136,7 @@ LL | let trivial_backslash = Regex::new("a/.b"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:66:36 + --> $DIR/regex.rs:57:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -144,7 +144,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:68:36 + --> $DIR/regex.rs:59:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -152,7 +152,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:70:36 + --> $DIR/regex.rs:61:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -160,7 +160,7 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:72:44 + --> $DIR/regex.rs:63:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index eb08f1de63d..bd916fa7196 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(stutter)] #[warn(clippy::stutter)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 074e3527e8a..58d2c98f890 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: unknown lint: `stutter` - --> $DIR/rename.rs:10:10 + --> $DIR/rename.rs:1:10 | LL | #![allow(stutter)] | ^^^^^^^ @@ -7,7 +7,7 @@ LL | #![allow(stutter)] = note: `-D unknown-lints` implied by `-D warnings` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:12:8 + --> $DIR/rename.rs:3:8 | LL | #[warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` @@ -15,7 +15,7 @@ LL | #[warn(clippy::stutter)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:15:8 + --> $DIR/rename.rs:6:8 | LL | #[warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index ca3d3b13edc..225d9bcbc0f 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(integer_atomics)] #![allow(clippy::blacklisted_name)] #![deny(clippy::replace_consts)] diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index e45f490463c..a2887fd4aad 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,215 +1,215 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:22:17 + --> $DIR/replace_consts.rs:13:17 | LL | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:12:9 + --> $DIR/replace_consts.rs:3:9 | LL | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:14:17 | LL | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:24:17 + --> $DIR/replace_consts.rs:15:17 | LL | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:16:17 | LL | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:17:17 | LL | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:18:17 | LL | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:19:17 | LL | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:20:17 | LL | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:21:17 | LL | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:22:17 | LL | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:23:17 | LL | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:25:17 | LL | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:26:17 | LL | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:27:17 | LL | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:28:17 | LL | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:29:17 | LL | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:30:17 | LL | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:31:17 | LL | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:32:17 | LL | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:33:17 | LL | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:34:17 | LL | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:35:17 | LL | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:36:17 | LL | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:38:17 | LL | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:39:17 | LL | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:40:17 | LL | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:41:17 | LL | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:51:17 + --> $DIR/replace_consts.rs:42:17 | LL | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:52:17 + --> $DIR/replace_consts.rs:43:17 | LL | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:53:17 + --> $DIR/replace_consts.rs:44:17 | LL | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:54:17 + --> $DIR/replace_consts.rs:45:17 | LL | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:55:17 + --> $DIR/replace_consts.rs:46:17 | LL | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:56:17 + --> $DIR/replace_consts.rs:47:17 | LL | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:57:17 + --> $DIR/replace_consts.rs:48:17 | LL | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:58:17 + --> $DIR/replace_consts.rs:49:17 | LL | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` diff --git a/tests/ui/result_map_unit_fn.rs b/tests/ui/result_map_unit_fn.rs index 3d731c9b350..a8e891d8db0 100644 --- a/tests/ui/result_map_unit_fn.rs +++ b/tests/ui/result_map_unit_fn.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(never_type)] #![warn(clippy::result_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/result_map_unit_fn.stderr b/tests/ui/result_map_unit_fn.stderr index e462a07ad51..9f9025152e2 100644 --- a/tests/ui/result_map_unit_fn.stderr +++ b/tests/ui/result_map_unit_fn.stderr @@ -1,5 +1,5 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:43:5 + --> $DIR/result_map_unit_fn.rs:34:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -9,7 +9,7 @@ LL | x.field.map(do_nothing); = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:45:5 + --> $DIR/result_map_unit_fn.rs:36:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | x.field.map(do_nothing); | help: try this: `if let Ok(x_field) = x.field { do_nothing(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:47:5 + --> $DIR/result_map_unit_fn.rs:38:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -25,7 +25,7 @@ LL | x.field.map(diverge); | help: try this: `if let Ok(x_field) = x.field { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:53:5 + --> $DIR/result_map_unit_fn.rs:44:5 | LL | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -33,7 +33,7 @@ LL | x.field.map(|value| x.do_result_nothing(value + captured)); | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:55:5 + --> $DIR/result_map_unit_fn.rs:46:5 | LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -41,7 +41,7 @@ LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:58:5 + --> $DIR/result_map_unit_fn.rs:49:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -49,7 +49,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:60:5 + --> $DIR/result_map_unit_fn.rs:51:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -57,7 +57,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:62:5 + --> $DIR/result_map_unit_fn.rs:53:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -65,7 +65,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:64:5 + --> $DIR/result_map_unit_fn.rs:55:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -73,7 +73,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:67:5 + --> $DIR/result_map_unit_fn.rs:58:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -81,7 +81,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:69:5 + --> $DIR/result_map_unit_fn.rs:60:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -89,7 +89,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:71:5 + --> $DIR/result_map_unit_fn.rs:62:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -97,7 +97,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:73:5 + --> $DIR/result_map_unit_fn.rs:64:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -105,7 +105,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:78:5 + --> $DIR/result_map_unit_fn.rs:69:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -113,7 +113,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:80:5 + --> $DIR/result_map_unit_fn.rs:71:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -121,7 +121,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:82:5 + --> $DIR/result_map_unit_fn.rs:73:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -129,7 +129,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:85:5 + --> $DIR/result_map_unit_fn.rs:76:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -137,7 +137,7 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:88:5 + --> $DIR/result_map_unit_fn.rs:79:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -145,7 +145,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:90:5 + --> $DIR/result_map_unit_fn.rs:81:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -153,7 +153,7 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:94:5 + --> $DIR/result_map_unit_fn.rs:85:5 | LL | x.field.map(|value| { | _____^ @@ -167,7 +167,7 @@ LL | || }); | error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn.rs:98:5 + --> $DIR/result_map_unit_fn.rs:89:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -175,7 +175,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | help: try this: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:102:5 + --> $DIR/result_map_unit_fn.rs:93:5 | LL | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -183,7 +183,7 @@ LL | "12".parse::().map(diverge); | help: try this: `if let Ok(_) = "12".parse::() { diverge(...) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn.rs:108:5 + --> $DIR/result_map_unit_fn.rs:99:5 | LL | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs index 0481e4ec1b0..40751bfebe6 100644 --- a/tests/ui/result_map_unwrap_or_else.rs +++ b/tests/ui/result_map_unwrap_or_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // aux-build:option_helpers.rs //! Checks implementation of `RESULT_MAP_UNWRAP_OR_ELSE` diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr index 9f03de669e4..7674b91c128 100644 --- a/tests/ui/result_map_unwrap_or_else.stderr +++ b/tests/ui/result_map_unwrap_or_else.stderr @@ -1,5 +1,5 @@ error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:24:13 + --> $DIR/result_map_unwrap_or_else.rs:15:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even t = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:26:13 + --> $DIR/result_map_unwrap_or_else.rs:17:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:27:13 + --> $DIR/result_map_unwrap_or_else.rs:18:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index c52fd065dbe..5843344eba8 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::serde_api_misuse)] #![allow(dead_code)] diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index 61e54d53468..760c9c9908a 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -1,5 +1,5 @@ error: you should not implement `visit_string` without also implementing `visit_str` - --> $DIR/serde.rs:48:5 + --> $DIR/serde.rs:39:5 | LL | / fn visit_string(self, _v: String) -> Result LL | | where diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index e960a6252be..a9c77aca66f 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn( clippy::all, clippy::pedantic, diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 158933e9672..ada8b07d69b 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,135 +1,135 @@ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:29:5 + --> $DIR/shadow.rs:20:5 | LL | let x = &mut x; | ^^^^^^^^^^^^^^^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:28:13 + --> $DIR/shadow.rs:19:13 | LL | let mut x = 1; | ^ error: `x` is shadowed by itself in `{ x }` - --> $DIR/shadow.rs:30:5 + --> $DIR/shadow.rs:21:5 | LL | let x = { x }; | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:20:9 | LL | let x = &mut x; | ^ error: `x` is shadowed by itself in `(&*x)` - --> $DIR/shadow.rs:31:5 + --> $DIR/shadow.rs:22:5 | LL | let x = (&*x); | ^^^^^^^^^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:30:9 + --> $DIR/shadow.rs:21:9 | LL | let x = { x }; | ^ error: `x` is shadowed by `{ *x + 1 }` which reuses the original value - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:23:9 | LL | let x = { *x + 1 }; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:32:13 + --> $DIR/shadow.rs:23:13 | LL | let x = { *x + 1 }; | ^^^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:22:9 | LL | let x = (&*x); | ^ error: `x` is shadowed by `id(x)` which reuses the original value - --> $DIR/shadow.rs:33:9 + --> $DIR/shadow.rs:24:9 | LL | let x = id(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:33:13 + --> $DIR/shadow.rs:24:13 | LL | let x = id(x); | ^^^^^ note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:23:9 | LL | let x = { *x + 1 }; | ^ error: `x` is shadowed by `(1, x)` which reuses the original value - --> $DIR/shadow.rs:34:9 + --> $DIR/shadow.rs:25:9 | LL | let x = (1, x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:34:13 + --> $DIR/shadow.rs:25:13 | LL | let x = (1, x); | ^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:33:9 + --> $DIR/shadow.rs:24:9 | LL | let x = id(x); | ^ error: `x` is shadowed by `first(x)` which reuses the original value - --> $DIR/shadow.rs:35:9 + --> $DIR/shadow.rs:26:9 | LL | let x = first(x); | ^ | note: initialization happens here - --> $DIR/shadow.rs:35:13 + --> $DIR/shadow.rs:26:13 | LL | let x = first(x); | ^^^^^^^^ note: previous binding is here - --> $DIR/shadow.rs:34:9 + --> $DIR/shadow.rs:25:9 | LL | let x = (1, x); | ^ error: `x` is shadowed by `y` - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:28:9 | LL | let x = y; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: initialization happens here - --> $DIR/shadow.rs:37:13 + --> $DIR/shadow.rs:28:13 | LL | let x = y; | ^ note: previous binding is here - --> $DIR/shadow.rs:35:9 + --> $DIR/shadow.rs:26:9 | LL | let x = first(x); | ^ error: `x` shadows a previous declaration - --> $DIR/shadow.rs:39:5 + --> $DIR/shadow.rs:30:5 | LL | let x; | ^^^^^^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:28:9 | LL | let x = y; | ^ diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index efe9920dd88..84e736fe080 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::short_circuit_statement)] fn main() { diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index 4141a003fc4..a526766f698 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -1,5 +1,5 @@ error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:13:5 + --> $DIR/short_circuit_statement.rs:4:5 | LL | f() && g(); | ^^^^^^^^^^^ help: replace it with: `if f() { g(); }` @@ -7,13 +7,13 @@ LL | f() && g(); = note: `-D clippy::short-circuit-statement` implied by `-D warnings` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:14:5 + --> $DIR/short_circuit_statement.rs:5:5 | LL | f() || g(); | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> $DIR/short_circuit_statement.rs:15:5 + --> $DIR/short_circuit_statement.rs:6:5 | LL | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if !(1 == 2) { g(); }` diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index c3c399f0ce3..220b855ead5 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index cf2fe66236a..9650eb2af32 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 7bc92a96536..82ef00bfee8 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,5 +1,5 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:16:13 + --> $DIR/single_char_pattern.rs:7:13 | LL | x.split("x"); | ^^^ help: try using a char instead: `'x'` @@ -7,115 +7,115 @@ LL | x.split("x"); = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:16 + --> $DIR/single_char_pattern.rs:24:16 | LL | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:19 + --> $DIR/single_char_pattern.rs:25:19 | LL | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:17 + --> $DIR/single_char_pattern.rs:26:17 | LL | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:12 + --> $DIR/single_char_pattern.rs:27:12 | LL | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:13 + --> $DIR/single_char_pattern.rs:28:13 | LL | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:14 + --> $DIR/single_char_pattern.rs:29:14 | LL | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:24 + --> $DIR/single_char_pattern.rs:30:24 | LL | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:40:25 + --> $DIR/single_char_pattern.rs:31:25 | LL | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:17 + --> $DIR/single_char_pattern.rs:32:17 | LL | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:42:18 + --> $DIR/single_char_pattern.rs:33:18 | LL | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:43:15 + --> $DIR/single_char_pattern.rs:34:15 | LL | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:44:16 + --> $DIR/single_char_pattern.rs:35:16 | LL | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:21 + --> $DIR/single_char_pattern.rs:36:21 | LL | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:22 + --> $DIR/single_char_pattern.rs:37:22 | LL | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:47:26 + --> $DIR/single_char_pattern.rs:38:26 | LL | x.trim_start_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:48:24 + --> $DIR/single_char_pattern.rs:39:24 | LL | x.trim_end_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:50:13 + --> $DIR/single_char_pattern.rs:41:13 | LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:55:31 + --> $DIR/single_char_pattern.rs:46:31 | LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:56:19 + --> $DIR/single_char_pattern.rs:47:19 | LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 5a1bde3de32..99e88019cb8 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::single_match)] fn dummy() {} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 41776030800..445f702d0ce 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:17:5 + --> $DIR/single_match.rs:8:5 | LL | / match x { LL | | Some(y) => { @@ -18,7 +18,7 @@ LL | }; | error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:25:5 + --> $DIR/single_match.rs:16:5 | LL | / match x { LL | | // Note the missing block braces. @@ -30,7 +30,7 @@ LL | | } | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:34:5 + --> $DIR/single_match.rs:25:5 | LL | / match z { LL | | (2...3, 7...9) => dummy(), @@ -39,7 +39,7 @@ LL | | }; | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:63:5 + --> $DIR/single_match.rs:54:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -48,7 +48,7 @@ LL | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:68:5 + --> $DIR/single_match.rs:59:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -57,7 +57,7 @@ LL | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:75:5 + --> $DIR/single_match.rs:66:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 18c26f7fc26..37a99de8832 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::single_match_else)] enum ExprNode { diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index ff780ad9667..3f29f5aaf6a 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match_else.rs:21:5 + --> $DIR/single_match_else.rs:12:5 | LL | / match ExprNode::Butterflies { LL | | ExprNode::ExprAddrOf => Some(&NODE), diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index cf11384467c..c5ae3ff769b 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::iter::repeat; fn main() { diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 319234386ac..5d2788ec260 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,5 +1,5 @@ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:22:5 + --> $DIR/slow_vector_initialization.rs:13:5 | LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` @@ -9,7 +9,7 @@ LL | vec1.extend(repeat(0).take(len)); = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:26:5 + --> $DIR/slow_vector_initialization.rs:17:5 | LL | let mut vec2 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` @@ -17,7 +17,7 @@ LL | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:40:5 + --> $DIR/slow_vector_initialization.rs:31:5 | LL | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` @@ -25,7 +25,7 @@ LL | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:43:5 + --> $DIR/slow_vector_initialization.rs:34:5 | LL | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` @@ -33,7 +33,7 @@ LL | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:50:5 + --> $DIR/slow_vector_initialization.rs:41:5 | LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` @@ -41,7 +41,7 @@ LL | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:58:5 + --> $DIR/slow_vector_initialization.rs:49:5 | LL | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` @@ -49,7 +49,7 @@ LL | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:62:5 + --> $DIR/slow_vector_initialization.rs:53:5 | LL | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replace allocation with: `vec![0; 10]` diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 529c2487f54..a94c8c336df 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] fn main() {} diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index ed1ccad9814..0f95484da54 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,5 +1,5 @@ error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:16:5 + --> $DIR/starts_ends_with.rs:7:5 | LL | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` @@ -7,19 +7,19 @@ LL | "".chars().next() == Some(' '); = note: `-D clippy::chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:17:5 + --> $DIR/starts_ends_with.rs:8:5 | LL | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:22:8 + --> $DIR/starts_ends_with.rs:13:8 | LL | if s.chars().next().unwrap() == 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:26:8 + --> $DIR/starts_ends_with.rs:17:8 | LL | if s.chars().next_back().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` @@ -27,49 +27,49 @@ LL | if s.chars().next_back().unwrap() == 'o' { = note: `-D clippy::chars-last-cmp` implied by `-D warnings` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:30:8 + --> $DIR/starts_ends_with.rs:21:8 | LL | if s.chars().last().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:34:8 + --> $DIR/starts_ends_with.rs:25:8 | LL | if s.chars().next().unwrap() != 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:38:8 + --> $DIR/starts_ends_with.rs:29:8 | LL | if s.chars().next_back().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:42:8 + --> $DIR/starts_ends_with.rs:33:8 | LL | if s.chars().last().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:50:5 + --> $DIR/starts_ends_with.rs:41:5 | LL | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:51:5 + --> $DIR/starts_ends_with.rs:42:5 | LL | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:52:5 + --> $DIR/starts_ends_with.rs:43:5 | LL | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:53:5 + --> $DIR/starts_ends_with.rs:44:5 | LL | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed index 7463baff2af..1883a9f8325 100644 --- a/tests/ui/string_extend.fixed +++ b/tests/ui/string_extend.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[derive(Copy, Clone)] diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index 3a2ad2695de..07d0baa1be6 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[derive(Copy, Clone)] diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 5638dd87ed1..6af8c9e1662 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,5 +1,5 @@ error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:27:5 + --> $DIR/string_extend.rs:18:5 | LL | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` @@ -7,13 +7,13 @@ LL | s.extend(abc.chars()); = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:30:5 + --> $DIR/string_extend.rs:21:5 | LL | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:33:5 + --> $DIR/string_extend.rs:24:5 | LL | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs index e15e80c1928..f0808eca829 100644 --- a/tests/ui/strings.rs +++ b/tests/ui/strings.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::string_add)] #[allow(clippy::string_add_assign)] fn add_only() { diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr index a8c80939b55..e2e997f58e6 100644 --- a/tests/ui/strings.stderr +++ b/tests/ui/strings.stderr @@ -1,5 +1,5 @@ error: manual implementation of an assign operation - --> $DIR/strings.rs:17:9 + --> $DIR/strings.rs:8:9 | LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` @@ -7,7 +7,7 @@ LL | x = x + "."; = note: `-D clippy::assign-op-pattern` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:17:13 + --> $DIR/strings.rs:8:13 | LL | x = x + "."; | ^^^^^^^ @@ -15,13 +15,13 @@ LL | x = x + "."; = note: `-D clippy::string-add` implied by `-D warnings` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:21:13 + --> $DIR/strings.rs:12:13 | LL | let z = y + "..."; | ^^^^^^^^^ error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:31:9 + --> $DIR/strings.rs:22:9 | LL | x = x + "."; | ^^^^^^^^^^^ @@ -29,31 +29,31 @@ LL | x = x + "."; = note: `-D clippy::string-add-assign` implied by `-D warnings` error: manual implementation of an assign operation - --> $DIR/strings.rs:31:9 + --> $DIR/strings.rs:22:9 | LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:45:9 + --> $DIR/strings.rs:36:9 | LL | x = x + "."; | ^^^^^^^^^^^ error: manual implementation of an assign operation - --> $DIR/strings.rs:45:9 + --> $DIR/strings.rs:36:9 | LL | x = x + "."; | ^^^^^^^^^^^ help: replace it with: `x += "."` error: you added something to a string. Consider using `String::push_str()` instead - --> $DIR/strings.rs:49:13 + --> $DIR/strings.rs:40:13 | LL | let z = y + "..."; | ^^^^^^^^^ error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:57:14 + --> $DIR/strings.rs:48:14 | LL | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` @@ -61,13 +61,13 @@ LL | let bs = "hello there".as_bytes(); = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal - --> $DIR/strings.rs:59:14 + --> $DIR/strings.rs:50:14 | LL | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###` error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/strings.rs:66:22 + --> $DIR/strings.rs:57:22 | LL | let includestr = include_str!("entry.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")` diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index ed845b7647a..6ee924d3b2e 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::suspicious_arithmetic_impl)] use std::ops::{Add, AddAssign, Div, Mul, Sub}; diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 71cb08c77d7..f818f7b3d95 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,5 +1,5 @@ error: Suspicious use of binary operator in `Add` impl - --> $DIR/suspicious_arithmetic_impl.rs:20:20 + --> $DIR/suspicious_arithmetic_impl.rs:11:20 | LL | Foo(self.0 - other.0) | ^ @@ -7,7 +7,7 @@ LL | Foo(self.0 - other.0) = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` error: Suspicious use of binary operator in `AddAssign` impl - --> $DIR/suspicious_arithmetic_impl.rs:26:23 + --> $DIR/suspicious_arithmetic_impl.rs:17:23 | LL | *self = *self - other; | ^ diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 20fa9c87574..77cfc16ff6e 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(clippy::blacklisted_name, unused_assignments)] diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 25afaccd754..5d818cf2056 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,5 +1,5 @@ error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:17:5 + --> $DIR/swap.rs:8:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -9,7 +9,7 @@ LL | | foo[1] = temp; = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:26:5 + --> $DIR/swap.rs:17:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -17,7 +17,7 @@ LL | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:35:5 + --> $DIR/swap.rs:26:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -25,7 +25,7 @@ LL | | foo[1] = temp; | |_________________^ help: try: `foo.swap(0, 1)` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:54:7 + --> $DIR/swap.rs:45:7 | LL | ; let t = a; | _______^ @@ -36,7 +36,7 @@ LL | | b = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:63:7 + --> $DIR/swap.rs:54:7 | LL | ; let t = c.0; | _______^ @@ -47,7 +47,7 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:51:5 + --> $DIR/swap.rs:42:5 | LL | / a = b; LL | | b = a; @@ -57,7 +57,7 @@ LL | | b = a; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:60:5 + --> $DIR/swap.rs:51:5 | LL | / c.0 = a; LL | | a = c.0; diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 5581f5be766..c6c315d5fab 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::temporary_assignment)] use std::ops::{Deref, DerefMut}; diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 13ece2858b9..4efe2d4bb67 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -1,5 +1,5 @@ error: assignment to temporary - --> $DIR/temporary_assignment.rs:56:5 + --> $DIR/temporary_assignment.rs:47:5 | LL | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1; = note: `-D clippy::temporary-assignment` implied by `-D warnings` error: assignment to temporary - --> $DIR/temporary_assignment.rs:57:5 + --> $DIR/temporary_assignment.rs:48:5 | LL | / MultiStruct { LL | | structure: Struct { field: 0 }, @@ -17,37 +17,37 @@ LL | | .field = 1; | |______________^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:62:5 + --> $DIR/temporary_assignment.rs:53:5 | LL | ArrayStruct { array: [0] }.array[0] = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:63:5 + --> $DIR/temporary_assignment.rs:54:5 | LL | (0, 0).0 = 1; | ^^^^^^^^^^^^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:65:5 + --> $DIR/temporary_assignment.rs:56:5 | LL | A.0 = 2; | ^^^^^^^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:66:5 + --> $DIR/temporary_assignment.rs:57:5 | LL | B.field = 2; | ^^^^^^^^^^^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:67:5 + --> $DIR/temporary_assignment.rs:58:5 | LL | C.structure.field = 2; | ^^^^^^^^^^^^^^^^^^^^^ error: assignment to temporary - --> $DIR/temporary_assignment.rs:68:5 + --> $DIR/temporary_assignment.rs:59:5 | LL | D.array[0] = 2; | ^^^^^^^^^^^^^^ diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index b051746bbd4..711fb4f8aed 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(unused)] diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index 7b7a46d9f8e..00a753c6ac2 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,5 +1,5 @@ error: `ref` directly on a function argument is ignored. Consider using a reference type instead. - --> $DIR/toplevel_ref_arg.rs:13:15 + --> $DIR/toplevel_ref_arg.rs:4:15 | LL | fn the_answer(ref mut x: u8) { | ^^^^^^^^^ @@ -7,25 +7,25 @@ LL | fn the_answer(ref mut x: u8) { = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:24:9 + --> $DIR/toplevel_ref_arg.rs:15:9 | LL | let ref x = 1; | ----^^^^^----- help: try: `let x = &1;` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:26:9 + --> $DIR/toplevel_ref_arg.rs:17:9 | LL | let ref y: (&_, u8) = (&1, 2); | ----^^^^^--------------------- help: try: `let y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:28:9 + --> $DIR/toplevel_ref_arg.rs:19:9 | LL | let ref z = 1 + 2; | ----^^^^^--------- help: try: `let z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:30:9 + --> $DIR/toplevel_ref_arg.rs:21:9 | LL | let ref mut z = 1 + 2; | ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);` diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index 9afb3399c59..4ee5ecffb87 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(stmt_expr_attributes)] #![allow(unused_parens)] diff --git a/tests/ui/trailing_zeros.stderr b/tests/ui/trailing_zeros.stderr index 1675eb44efd..61289b24471 100644 --- a/tests/ui/trailing_zeros.stderr +++ b/tests/ui/trailing_zeros.stderr @@ -1,5 +1,5 @@ error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:16:5 + --> $DIR/trailing_zeros.rs:7:5 | LL | (x & 0b1111 == 0); // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 4` @@ -7,7 +7,7 @@ LL | (x & 0b1111 == 0); // suggest trailing_zeros = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` error: bit mask could be simplified with a call to `trailing_zeros` - --> $DIR/trailing_zeros.rs:17:13 + --> $DIR/trailing_zeros.rs:8:13 | LL | let _ = x & 0b1_1111 == 0; // suggest trailing_zeros | ^^^^^^^^^^^^^^^^^ help: try: `x.trailing_zeros() >= 5` diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index b27014201cd..86964f8480a 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] extern crate core; diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index a6e87a72104..ceee86d224d 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a type (`&'a T`) to itself - --> $DIR/transmute.rs:28:20 + --> $DIR/transmute.rs:19:20 | LL | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | let _: &'a T = core::intrinsics::transmute(t); = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:32:23 + --> $DIR/transmute.rs:23:23 | LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:34:21 + --> $DIR/transmute.rs:25:21 | LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:36:23 + --> $DIR/transmute.rs:27:23 | LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute.rs:41:17 + --> $DIR/transmute.rs:32:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -33,103 +33,103 @@ LL | let _: &T = std::mem::transmute(p); = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:44:21 + --> $DIR/transmute.rs:35:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute.rs:47:17 + --> $DIR/transmute.rs:38:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:50:21 + --> $DIR/transmute.rs:41:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute.rs:53:17 + --> $DIR/transmute.rs:44:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute.rs:56:21 + --> $DIR/transmute.rs:47:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute.rs:59:17 + --> $DIR/transmute.rs:50:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, u8>`) - --> $DIR/transmute.rs:70:32 + --> $DIR/transmute.rs:61:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, &u8>`) - --> $DIR/transmute.rs:72:33 + --> $DIR/transmute.rs:63:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute.rs:76:14 + --> $DIR/transmute.rs:67:14 | LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:82:27 + --> $DIR/transmute.rs:73:27 | LL | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:84:27 + --> $DIR/transmute.rs:75:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:86:27 + --> $DIR/transmute.rs:77:27 | LL | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:88:27 + --> $DIR/transmute.rs:79:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:90:27 + --> $DIR/transmute.rs:81:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:98:31 + --> $DIR/transmute.rs:89:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:102:31 + --> $DIR/transmute.rs:93:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:117:24 + --> $DIR/transmute.rs:108:24 | LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,25 +137,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:119:24 + --> $DIR/transmute.rs:110:24 | LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:121:31 + --> $DIR/transmute.rs:112:31 | LL | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:123:29 + --> $DIR/transmute.rs:114:29 | LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:129:28 + --> $DIR/transmute.rs:120:28 | LL | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` @@ -163,13 +163,13 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:130:28 + --> $DIR/transmute.rs:121:28 | LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:135:28 + --> $DIR/transmute.rs:126:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -177,7 +177,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:140:27 + --> $DIR/transmute.rs:131:27 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -185,13 +185,13 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:141:27 + --> $DIR/transmute.rs:132:27 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:145:28 + --> $DIR/transmute.rs:136:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -199,13 +199,13 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:146:32 + --> $DIR/transmute.rs:137:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:178:29 + --> $DIR/transmute.rs:169:29 | LL | let _: *const f32 = std::mem::transmute(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` @@ -213,31 +213,31 @@ LL | let _: *const f32 = std::mem::transmute(ptr); = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmute.rs:179:27 + --> $DIR/transmute.rs:170:27 | LL | let _: *mut f32 = std::mem::transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` error: transmute from a reference to a reference - --> $DIR/transmute.rs:181:23 + --> $DIR/transmute.rs:172:23 | LL | let _: &f32 = std::mem::transmute(&1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:182:23 + --> $DIR/transmute.rs:173:23 | LL | let _: &f64 = std::mem::transmute(&1f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:185:27 + --> $DIR/transmute.rs:176:27 | LL | let _: &mut f32 = std::mem::transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> $DIR/transmute.rs:186:37 + --> $DIR/transmute.rs:177:37 | LL | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index dd96e2dabe1..1b50133d391 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //ignore-x86_64 #[warn(wrong_transmute)] diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index fbc298e3a06..aee5152d647 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //ignore-x86 //no-ignore-x86_64 diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index bbca3bc0b36..457050ec504 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,5 +1,5 @@ error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:16:31 + --> $DIR/transmute_64bit.rs:7:31 | LL | let _: *const usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _: *const usize = std::mem::transmute(6.0f64); = note: `-D clippy::wrong-transmute` implied by `-D warnings` error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:18:29 + --> $DIR/transmute_64bit.rs:9:29 | LL | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 94e0113e56c..c12d9856501 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( clippy::many_single_char_names, clippy::blacklisted_name, diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 6f2967bc392..754069b421c 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,5 +1,5 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:56:11 + --> $DIR/trivially_copy_pass_by_ref.rs:47:11 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` @@ -7,85 +7,85 @@ LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:56:20 + --> $DIR/trivially_copy_pass_by_ref.rs:47:20 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:56:29 + --> $DIR/trivially_copy_pass_by_ref.rs:47:29 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:63:12 + --> $DIR/trivially_copy_pass_by_ref.rs:54:12 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:63:22 + --> $DIR/trivially_copy_pass_by_ref.rs:54:22 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:63:31 + --> $DIR/trivially_copy_pass_by_ref.rs:54:31 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:63:40 + --> $DIR/trivially_copy_pass_by_ref.rs:54:40 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:16 + --> $DIR/trivially_copy_pass_by_ref.rs:56:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:25 + --> $DIR/trivially_copy_pass_by_ref.rs:56:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:65:34 + --> $DIR/trivially_copy_pass_by_ref.rs:56:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:77:16 + --> $DIR/trivially_copy_pass_by_ref.rs:68:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:77:25 + --> $DIR/trivially_copy_pass_by_ref.rs:68:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:77:34 + --> $DIR/trivially_copy_pass_by_ref.rs:68:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:81:34 + --> $DIR/trivially_copy_pass_by_ref.rs:72:34 | LL | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:85:37 + --> $DIR/trivially_copy_pass_by_ref.rs:76:37 | LL | fn trait_method2(&self, _color: &Color); | ^^^^^^ help: consider passing by value instead: `Color` diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs index 17027306367..9e2753dcb18 100644 --- a/tests/ui/ty_fn_sig.rs +++ b/tests/ui/ty_fn_sig.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Regression test pub fn retry(f: F) { diff --git a/tests/ui/types.rs b/tests/ui/types.rs index f0ede2fd48c..45846d6eef8 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // should not warn on lossy casting in constant types // because not supported yet const C: i32 = 42; diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index 76dc07aef31..97cce7add03 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -1,5 +1,5 @@ error: casting i32 to i64 may become silently lossy if types change - --> $DIR/types.rs:18:22 + --> $DIR/types.rs:9:22 | LL | let c_i64: i64 = c as i64; | ^^^^^^^^ help: try: `i64::from(c)` diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 0e1200db227..deec885b85d 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[warn(clippy::zero_width_space)] fn zero() { print!("Here >​< is a ZWS, and ​another"); diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index 9b78271e1fa..c60dcdaec1d 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,5 +1,5 @@ error: zero-width space detected - --> $DIR/unicode.rs:12:12 + --> $DIR/unicode.rs:3:12 | LL | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | print!("Here >​< is a ZWS, and ​another"); ""Here >/u{200B}< is a ZWS, and /u{200B}another"" error: non-nfc unicode sequence detected - --> $DIR/unicode.rs:18:12 + --> $DIR/unicode.rs:9:12 | LL | print!("̀àh?"); | ^^^^^ @@ -19,7 +19,7 @@ LL | print!("̀àh?"); ""̀àh?"" error: literal non-ASCII character detected - --> $DIR/unicode.rs:24:12 + --> $DIR/unicode.rs:15:12 | LL | print!("Üben!"); | ^^^^^^^ diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 571882ced0f..7e421a0d605 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::unit_arg)] #![allow(clippy::no_effect)] diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 013016574ff..1da00b6f5e9 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,5 +1,5 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:32:9 + --> $DIR/unit_arg.rs:23:9 | LL | foo({}); | ^^ @@ -11,7 +11,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:33:9 + --> $DIR/unit_arg.rs:24:9 | LL | foo({ | _________^ @@ -24,7 +24,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:36:9 + --> $DIR/unit_arg.rs:27:9 | LL | foo(foo(1)); | ^^^^^^ @@ -34,7 +34,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:37:9 + --> $DIR/unit_arg.rs:28:9 | LL | foo({ | _________^ @@ -48,7 +48,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:41:10 + --> $DIR/unit_arg.rs:32:10 | LL | foo3({}, 2, 2); | ^^ @@ -58,7 +58,7 @@ LL | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:43:11 + --> $DIR/unit_arg.rs:34:11 | LL | b.bar({ | ___________^ diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index 0bc87f43c15..48c22f7f875 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::unit_cmp)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 481891b99b0..56293403043 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,5 +1,5 @@ error: ==-comparison of unit values detected. This will always be true - --> $DIR/unit_cmp.rs:21:8 + --> $DIR/unit_cmp.rs:12:8 | LL | if { | ________^ @@ -12,7 +12,7 @@ LL | | } {} = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false - --> $DIR/unit_cmp.rs:27:8 + --> $DIR/unit_cmp.rs:18:8 | LL | if { | ________^ diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index e583614a93c..0a93c814d96 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::All)] #![warn(clippy::pedantic)] diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index f83a51728e7..3c86432a972 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -1,5 +1,5 @@ error: unknown clippy lint: clippy::if_not_els - --> $DIR/unknown_clippy_lints.rs:13:8 + --> $DIR/unknown_clippy_lints.rs:4:8 | LL | #[warn(clippy::if_not_els)] | ^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[warn(clippy::if_not_els)] = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` error: unknown clippy lint: clippy::All - --> $DIR/unknown_clippy_lints.rs:10:10 + --> $DIR/unknown_clippy_lints.rs:1:10 | LL | #![allow(clippy::All)] | ^^^^^^^^^^^ help: lowercase the lint name: `all` diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 40c4b4961e9..fee6b30a97b 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::clone_on_ref_ptr)] #![allow(unused)] diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 604902e5d6d..5cd9b2d337f 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,5 +1,5 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:26:5 + --> $DIR/unnecessary_clone.rs:17:5 | LL | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` @@ -7,19 +7,19 @@ LL | 42.clone(); = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:30:5 + --> $DIR/unnecessary_clone.rs:21:5 | LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:33:5 + --> $DIR/unnecessary_clone.rs:24:5 | LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:43:5 + --> $DIR/unnecessary_clone.rs:34:5 | LL | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` @@ -27,43 +27,43 @@ LL | rc.clone(); = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:46:5 + --> $DIR/unnecessary_clone.rs:37:5 | LL | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:49:5 + --> $DIR/unnecessary_clone.rs:40:5 | LL | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:52:5 + --> $DIR/unnecessary_clone.rs:43:5 | LL | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` error: using '.clone()' on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:56:29 + --> $DIR/unnecessary_clone.rs:47:29 | LL | let _: Arc = x.clone(); | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:60:5 + --> $DIR/unnecessary_clone.rs:51:5 | LL | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:62:5 + --> $DIR/unnecessary_clone.rs:53:5 | LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:68:22 + --> $DIR/unnecessary_clone.rs:59:22 | LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ @@ -79,7 +79,7 @@ LL | let z: &Vec<_> = &std::vec::Vec::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/unnecessary_clone.rs:75:26 + --> $DIR/unnecessary_clone.rs:66:26 | LL | let v2: Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | let v2: Vec = v.iter().cloned().collect(); = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:111:20 + --> $DIR/unnecessary_clone.rs:102:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs index a0c183a58cc..af858e4abcf 100644 --- a/tests/ui/unnecessary_filter_map.rs +++ b/tests/ui/unnecessary_filter_map.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); let _ = (0..4).filter_map(|x| { diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index 09f8973708f..041829c3c78 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -1,5 +1,5 @@ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:11:13 + --> $DIR/unnecessary_filter_map.rs:2:13 | LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:12:13 + --> $DIR/unnecessary_filter_map.rs:3:13 | LL | let _ = (0..4).filter_map(|x| { | _____________^ @@ -19,7 +19,7 @@ LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.filter` - --> $DIR/unnecessary_filter_map.rs:18:13 + --> $DIR/unnecessary_filter_map.rs:9:13 | LL | let _ = (0..4).filter_map(|x| match x { | _____________^ @@ -29,7 +29,7 @@ LL | | }); | |______^ error: this `.filter_map` can be written more simply using `.map` - --> $DIR/unnecessary_filter_map.rs:23:13 + --> $DIR/unnecessary_filter_map.rs:14:13 | LL | let _ = (0..4).filter_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 4b4a6ee044c..62198e21ef7 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 2c2349bd3bc..07414b400c1 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -1,5 +1,5 @@ error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:13:19 + --> $DIR/unnecessary_fold.rs:4:19 | LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` @@ -7,25 +7,25 @@ LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); = note: `-D clippy::unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:15:19 + --> $DIR/unnecessary_fold.rs:6:19 | LL | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:17:19 + --> $DIR/unnecessary_fold.rs:8:19 | LL | let _ = (0..3).fold(0, |acc, x| acc + x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:19:19 + --> $DIR/unnecessary_fold.rs:10:19 | LL | let _ = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:24:34 + --> $DIR/unnecessary_fold.rs:15:34 | LL | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index 34e1112f006..3c6796fea7b 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(box_syntax)] #![allow(clippy::deref_addrof)] #![warn(clippy::unnecessary_operation)] diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index e46002dd97b..826bf6e2c28 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -1,5 +1,5 @@ error: statement can be reduced - --> $DIR/unnecessary_operation.rs:54:5 + --> $DIR/unnecessary_operation.rs:45:5 | LL | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` @@ -7,109 +7,109 @@ LL | Tuple(get_number()); = note: `-D clippy::unnecessary-operation` implied by `-D warnings` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:55:5 + --> $DIR/unnecessary_operation.rs:46:5 | LL | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:56:5 + --> $DIR/unnecessary_operation.rs:47:5 | LL | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:57:5 + --> $DIR/unnecessary_operation.rs:48:5 | LL | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:58:5 + --> $DIR/unnecessary_operation.rs:49:5 | LL | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:59:5 + --> $DIR/unnecessary_operation.rs:50:5 | LL | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:60:5 + --> $DIR/unnecessary_operation.rs:51:5 | LL | *&get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:61:5 + --> $DIR/unnecessary_operation.rs:52:5 | LL | &get_number(); | ^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:62:5 + --> $DIR/unnecessary_operation.rs:53:5 | LL | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:63:5 + --> $DIR/unnecessary_operation.rs:54:5 | LL | box get_number(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:64:5 + --> $DIR/unnecessary_operation.rs:55:5 | LL | get_number()..; | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:65:5 + --> $DIR/unnecessary_operation.rs:56:5 | LL | ..get_number(); | ^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:66:5 + --> $DIR/unnecessary_operation.rs:57:5 | LL | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:67:5 + --> $DIR/unnecessary_operation.rs:58:5 | LL | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:68:5 + --> $DIR/unnecessary_operation.rs:59:5 | LL | [42, 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_number() as usize;` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:69:5 + --> $DIR/unnecessary_operation.rs:60:5 | LL | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:70:5 + --> $DIR/unnecessary_operation.rs:61:5 | LL | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:71:5 + --> $DIR/unnecessary_operation.rs:62:5 | LL | [42; 55][get_number() as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_number() as usize;` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:72:5 + --> $DIR/unnecessary_operation.rs:63:5 | LL | / { LL | | get_number() @@ -117,7 +117,7 @@ LL | | }; | |______^ help: replace it with: `get_number();` error: statement can be reduced - --> $DIR/unnecessary_operation.rs:75:5 + --> $DIR/unnecessary_operation.rs:66:5 | LL | / FooString { LL | | s: String::from("blah"), diff --git a/tests/ui/unnecessary_ref.fixed b/tests/ui/unnecessary_ref.fixed index 3617641a116..f7b94118d4e 100644 --- a/tests/ui/unnecessary_ref.fixed +++ b/tests/ui/unnecessary_ref.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![feature(stmt_expr_attributes)] diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 48101c87a54..4e585b9b96b 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![feature(stmt_expr_attributes)] diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index 863a6389e7f..89adca3b1ad 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,11 +1,11 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:22:17 + --> $DIR/unnecessary_ref.rs:13:17 | LL | let inner = (&outer).inner; | ^^^^^^^^ help: try this: `outer` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:19:8 + --> $DIR/unnecessary_ref.rs:10:8 | LL | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 14676c1e76f..fa639aa70d6 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::unneeded_field_pattern)] #[allow(dead_code, unused)] diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 23e35923f83..e7b92ce1e19 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: You matched a field with a wildcard pattern. Consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:23:15 + --> $DIR/unneeded_field_pattern.rs:14:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = help: Try with `Foo { b: 0, .. }` error: All the struct fields are matched to a wildcard pattern, consider using `..`. - --> $DIR/unneeded_field_pattern.rs:25:9 + --> $DIR/unneeded_field_pattern.rs:16:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed index 4c466035a04..eede10c771c 100644 --- a/tests/ui/unreadable_literal.fixed +++ b/tests/ui/unreadable_literal.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::unreadable_literal)] diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 8ade2f6a863..6523f70186f 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #[warn(clippy::unreadable_literal)] diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 68580485853..8334139120e 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,5 +1,5 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:16 + --> $DIR/unreadable_literal.rs:17:16 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -7,25 +7,25 @@ LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32) = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:30 + --> $DIR/unreadable_literal.rs:17:30 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:51 + --> $DIR/unreadable_literal.rs:17:51 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:63 + --> $DIR/unreadable_literal.rs:17:63 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:28:19 + --> $DIR/unreadable_literal.rs:19:19 | LL | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index bfab077375d..a1f616733bd 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused_imports)] #![allow(dead_code)] #![warn(clippy::unsafe_removed_from_name)] diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index cdc2b907ec5..1b1c62430b2 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -1,5 +1,5 @@ error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCell` - --> $DIR/unsafe_removed_from_name.rs:14:1 + --> $DIR/unsafe_removed_from_name.rs:5:1 | LL | use std::cell::UnsafeCell as TotallySafeCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | use std::cell::UnsafeCell as TotallySafeCell; = note: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` error: removed "unsafe" from the name of `UnsafeCell` in use as `TotallySafeCellAgain` - --> $DIR/unsafe_removed_from_name.rs:16:1 + --> $DIR/unsafe_removed_from_name.rs:7:1 | LL | use std::cell::UnsafeCell as TotallySafeCellAgain; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed "unsafe" from the name of `Unsafe` in use as `LieAboutModSafety` - --> $DIR/unsafe_removed_from_name.rs:30:1 + --> $DIR/unsafe_removed_from_name.rs:21:1 | LL | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 4e721527249..c8a38f9fe57 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code)] #![warn(clippy::unused_io_amount)] diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 528d35ebdef..2d00338193c 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,5 +1,5 @@ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:16:5 + --> $DIR/unused_io_amount.rs:7:5 | LL | try!(s.write(b"test")); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | try!(s.write(b"test")); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:18:5 + --> $DIR/unused_io_amount.rs:9:5 | LL | try!(s.read(&mut buf)); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,25 +16,25 @@ LL | try!(s.read(&mut buf)); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:23:5 + --> $DIR/unused_io_amount.rs:14:5 | LL | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:25:5 + --> $DIR/unused_io_amount.rs:16:5 | LL | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ error: handle written amount returned or use `Write::write_all` instead - --> $DIR/unused_io_amount.rs:30:5 + --> $DIR/unused_io_amount.rs:21:5 | LL | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: handle read amount returned or use `Read::read_exact` instead - --> $DIR/unused_io_amount.rs:32:5 + --> $DIR/unused_io_amount.rs:23:5 | LL | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unused_labels.rs b/tests/ui/unused_labels.rs index 8db29dcf3fc..ae963ad6969 100644 --- a/tests/ui/unused_labels.rs +++ b/tests/ui/unused_labels.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(dead_code, clippy::items_after_statements, clippy::never_loop)] #![warn(clippy::unused_label)] diff --git a/tests/ui/unused_labels.stderr b/tests/ui/unused_labels.stderr index 07ff5083ed2..d2ca0f1b57f 100644 --- a/tests/ui/unused_labels.stderr +++ b/tests/ui/unused_labels.stderr @@ -1,5 +1,5 @@ error: unused label `'label` - --> $DIR/unused_labels.rs:14:5 + --> $DIR/unused_labels.rs:5:5 | LL | / 'label: for i in 1..2 { LL | | if i > 4 { @@ -11,7 +11,7 @@ LL | | } = note: `-D clippy::unused-label` implied by `-D warnings` error: unused label `'a` - --> $DIR/unused_labels.rs:28:5 + --> $DIR/unused_labels.rs:19:5 | LL | / 'a: loop { LL | | break; @@ -19,7 +19,7 @@ LL | | } | |_____^ error: unused label `'same_label_in_two_fns` - --> $DIR/unused_labels.rs:41:5 + --> $DIR/unused_labels.rs:32:5 | LL | / 'same_label_in_two_fns: loop { LL | | let _ = 1; diff --git a/tests/ui/unused_lt.rs b/tests/ui/unused_lt.rs index 99e80103f1f..ba7c42b3a90 100644 --- a/tests/ui/unused_lt.rs +++ b/tests/ui/unused_lt.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow( unused, dead_code, diff --git a/tests/ui/unused_lt.stderr b/tests/ui/unused_lt.stderr index 30ce7b68578..bf4aedd52a9 100644 --- a/tests/ui/unused_lt.stderr +++ b/tests/ui/unused_lt.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:23:14 + --> $DIR/unused_lt.rs:14:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -7,13 +7,13 @@ LL | fn unused_lt<'a>(x: u8) {} = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:25:25 + --> $DIR/unused_lt.rs:16:25 | LL | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/unused_lt.rs:50:10 + --> $DIR/unused_lt.rs:41:10 | LL | fn x<'a>(&self) {} | ^^ diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index 88f0b9687be..8d56d2051e2 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // compile-pass // The output for humans should just highlight the whole span without showing diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index ac76d75b176..c4cb643cb71 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -1,5 +1,5 @@ error: unneeded unit return type - --> $DIR/unused_unit.rs:25:59 + --> $DIR/unused_unit.rs:15:59 | LL | pub fn get_unit (), G>(&self, f: F, _g: G) -> | ___________________________________________________________^ @@ -7,43 +7,43 @@ LL | | () | |__________^ help: remove the `-> ()` | note: lint level defined here - --> $DIR/unused_unit.rs:19:9 + --> $DIR/unused_unit.rs:9:9 | LL | #![deny(clippy::unused_unit)] | ^^^^^^^^^^^^^^^^^^^ error: unneeded unit return type - --> $DIR/unused_unit.rs:35:19 + --> $DIR/unused_unit.rs:25:19 | LL | fn into(self) -> () { | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:36:9 + --> $DIR/unused_unit.rs:26:9 | LL | () | ^^ help: remove the final `()` error: unneeded unit return type - --> $DIR/unused_unit.rs:40:18 + --> $DIR/unused_unit.rs:30:18 | LL | fn return_unit() -> () { () } | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:40:26 + --> $DIR/unused_unit.rs:30:26 | LL | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` - --> $DIR/unused_unit.rs:47:14 + --> $DIR/unused_unit.rs:37:14 | LL | break(); | ^^ help: remove the `()` error: unneeded `()` - --> $DIR/unused_unit.rs:49:11 + --> $DIR/unused_unit.rs:39:11 | LL | return(); | ^^ help: remove the `()` diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index 8573f78d43b..bfb41e43947 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] fn main() { diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index 3970b68de7a..c3a7464fd47 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:13:47 + --> $DIR/unwrap_or.rs:4:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` @@ -7,7 +7,7 @@ LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()) = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:17:47 + --> $DIR/unwrap_or.rs:8:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` diff --git a/tests/ui/update-all-references.sh b/tests/ui/update-all-references.sh index acc38f15fbd..f438d442ca1 100755 --- a/tests/ui/update-all-references.sh +++ b/tests/ui/update-all-references.sh @@ -1,14 +1,4 @@ #!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. # A script to update the references for all tests. The idea is that # you do a run, which will generate files in the build directory diff --git a/tests/ui/update-references.sh b/tests/ui/update-references.sh index d6995985a3b..c553e4ef2e3 100755 --- a/tests/ui/update-references.sh +++ b/tests/ui/update-references.sh @@ -1,14 +1,4 @@ #!/bin/bash -# -# Copyright 2015 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. # A script to update the references for particular tests. The idea is # that you do a run, which will generate files in the build directory diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index a117ce5894b..b839aead95a 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::use_self)] #![allow(dead_code)] #![allow(clippy::should_implement_trait)] diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 72b60db7fd2..9d23433ba64 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:20:21 + --> $DIR/use_self.rs:11:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,133 +7,133 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:21:13 + --> $DIR/use_self.rs:12:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:22 + --> $DIR/use_self.rs:14:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:13 + --> $DIR/use_self.rs:15:13 | LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:29:25 + --> $DIR/use_self.rs:20:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:30:13 + --> $DIR/use_self.rs:21:13 | LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:95:22 + --> $DIR/use_self.rs:86:22 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:95:31 + --> $DIR/use_self.rs:86:31 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:37 + --> $DIR/use_self.rs:90:37 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:99:53 + --> $DIR/use_self.rs:90:53 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:103:30 + --> $DIR/use_self.rs:94:30 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:103:43 + --> $DIR/use_self.rs:94:43 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:107:28 + --> $DIR/use_self.rs:98:28 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:107:46 + --> $DIR/use_self.rs:98:46 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:109:20 + --> $DIR/use_self.rs:100:20 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:109:28 + --> $DIR/use_self.rs:100:28 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:13 + --> $DIR/use_self.rs:101:13 | LL | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:115:23 + --> $DIR/use_self.rs:106:23 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:117:27 + --> $DIR/use_self.rs:108:27 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:117:35 + --> $DIR/use_self.rs:108:35 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:209:56 + --> $DIR/use_self.rs:200:56 | LL | fn bad(foos: &[Self]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:224:13 + --> $DIR/use_self.rs:215:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:232:25 + --> $DIR/use_self.rs:223:25 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -142,7 +142,7 @@ LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation error: unnecessary structure name repetition - --> $DIR/use_self.rs:233:17 + --> $DIR/use_self.rs:224:17 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` @@ -151,13 +151,13 @@ LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation error: unnecessary structure name repetition - --> $DIR/use_self.rs:255:29 + --> $DIR/use_self.rs:246:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:256:21 + --> $DIR/use_self.rs:247:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index bd20cc5f48a..702f1793ed5 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::all)] #![allow(clippy::blacklisted_name)] #![warn(clippy::used_underscore_binding)] diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 798dde2ea0e..2e2f2056d84 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -1,5 +1,5 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:23:5 + --> $DIR/used_underscore_binding.rs:14:5 | LL | _foo + 1 | ^^^^ @@ -7,25 +7,25 @@ LL | _foo + 1 = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:28:20 + --> $DIR/used_underscore_binding.rs:19:20 | LL | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:29:16 + --> $DIR/used_underscore_binding.rs:20:16 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:29:22 + --> $DIR/used_underscore_binding.rs:20:22 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:42:5 + --> $DIR/used_underscore_binding.rs:33:5 | LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useful_asref.rs b/tests/ui/useful_asref.rs index d7e56af2590..a9f0170a79c 100644 --- a/tests/ui/useful_asref.rs +++ b/tests/ui/useful_asref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::useless_asref)] trait Trait { diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 34c0f5095db..fe3dae5fc4c 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(clippy::useless_asref)] #![allow(clippy::trivially_copy_pass_by_ref)] use std::fmt::Debug; diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 2e4a7f80444..cc594559032 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,71 +1,71 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:50:18 + --> $DIR/useless_asref.rs:41:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` | note: lint level defined here - --> $DIR/useless_asref.rs:10:9 + --> $DIR/useless_asref.rs:1:9 | LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:52:20 + --> $DIR/useless_asref.rs:43:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:56:21 + --> $DIR/useless_asref.rs:47:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:58:20 + --> $DIR/useless_asref.rs:49:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:65:20 + --> $DIR/useless_asref.rs:56:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:67:18 + --> $DIR/useless_asref.rs:58:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:72:21 + --> $DIR/useless_asref.rs:63:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:74:20 + --> $DIR/useless_asref.rs:65:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:77:16 + --> $DIR/useless_asref.rs:68:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:127:13 + --> $DIR/useless_asref.rs:118:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:129:12 + --> $DIR/useless_asref.rs:120:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 2d7a9ae04d1..7da251101f5 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::useless_attribute)] #[allow(dead_code)] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index b9340ce8c02..2f7a010fc3e 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,5 +1,5 @@ error: useless lint attribute - --> $DIR/useless_attribute.rs:12:1 + --> $DIR/useless_attribute.rs:3:1 | LL | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` @@ -7,7 +7,7 @@ LL | #[allow(dead_code)] = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute - --> $DIR/useless_attribute.rs:13:1 + --> $DIR/useless_attribute.rs:4:1 | LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 2eaba1c408a..e73a791891f 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![warn(clippy::useless_vec)] diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 1648215ed35..3eb960f53d7 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![warn(clippy::useless_vec)] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 96dd187ccc5..37e28ebddb5 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:32:14 + --> $DIR/vec.rs:23:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,31 +7,31 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:35:14 + --> $DIR/vec.rs:26:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:38:14 + --> $DIR/vec.rs:29:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:41:14 + --> $DIR/vec.rs:32:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:44:14 + --> $DIR/vec.rs:35:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:57:14 + --> $DIR/vec.rs:48:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index e4c7047df91..283a2d43c04 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)] #![allow(dead_code, clippy::never_loop, unused, clippy::cyclomatic_complexity)] diff --git a/tests/ui/while_loop.stderr b/tests/ui/while_loop.stderr index 0e6c97e48d4..dde98da46c3 100644 --- a/tests/ui/while_loop.stderr +++ b/tests/ui/while_loop.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:15:5 + --> $DIR/while_loop.rs:6:5 | LL | / loop { LL | | if let Some(_x) = y { @@ -13,7 +13,7 @@ LL | | } = note: `-D clippy::while-let-loop` implied by `-D warnings` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:29:5 + --> $DIR/while_loop.rs:20:5 | LL | / loop { LL | | match y { @@ -24,7 +24,7 @@ LL | | } | |_____^ help: try: `while let Some(_x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:35:5 + --> $DIR/while_loop.rs:26:5 | LL | / loop { LL | | let x = match y { @@ -36,7 +36,7 @@ LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:43:5 + --> $DIR/while_loop.rs:34:5 | LL | / loop { LL | | let x = match y { @@ -48,7 +48,7 @@ LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:71:5 + --> $DIR/while_loop.rs:62:5 | LL | / loop { LL | | let (e, l) = match "".split_whitespace().next() { @@ -60,7 +60,7 @@ LL | | } | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:81:33 + --> $DIR/while_loop.rs:72:33 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` @@ -68,19 +68,19 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:86:25 + --> $DIR/while_loop.rs:77:25 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^ help: try: `for x in iter { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:91:25 + --> $DIR/while_loop.rs:82:25 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^ help: try: `for _ in iter { .. }` error: this loop could be written as a `while let` loop - --> $DIR/while_loop.rs:134:5 + --> $DIR/while_loop.rs:125:5 | LL | / loop { LL | | let _ = match iter.next() { @@ -92,7 +92,7 @@ LL | | } | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` error: empty `loop {}` detected. You may want to either use `panic!()` or add `std::thread::sleep(..);` to the loop body. - --> $DIR/while_loop.rs:139:9 + --> $DIR/while_loop.rs:130:9 | LL | loop {} | ^^^^^^^ @@ -100,13 +100,13 @@ LL | loop {} = note: `-D clippy::empty-loop` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:197:29 + --> $DIR/while_loop.rs:188:29 | LL | while let Some(v) = y.next() { | ^^^^^^^^ help: try: `for v in y { .. }` error: this loop could be written as a `for` loop - --> $DIR/while_loop.rs:225:26 + --> $DIR/while_loop.rs:216:26 | LL | while let Some(..) = values.iter().next() { | ^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter() { .. }` diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 0ba1943e6d8..d8205c5eb67 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused_must_use)] #![warn(clippy::write_literal)] diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 7daf52a4445..54a787fe555 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,5 +1,5 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:36:79 + --> $DIR/write_literal.rs:27:79 | LL | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); | ^ @@ -7,79 +7,79 @@ LL | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't = note: `-D clippy::write-literal` implied by `-D warnings` error: literal with an empty format string - --> $DIR/write_literal.rs:37:32 + --> $DIR/write_literal.rs:28:32 | LL | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:38:44 + --> $DIR/write_literal.rs:29:44 | LL | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:39:34 + --> $DIR/write_literal.rs:30:34 | LL | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:40:38 + --> $DIR/write_literal.rs:31:38 | LL | writeln!(&mut v, "10 / 4 is {}", 2.5); | ^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:41:36 + --> $DIR/write_literal.rs:32:36 | LL | writeln!(&mut v, "2 + 1 = {}", 3); | ^ error: literal with an empty format string - --> $DIR/write_literal.rs:46:33 + --> $DIR/write_literal.rs:37:33 | LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:46:42 + --> $DIR/write_literal.rs:37:42 | LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:47:33 + --> $DIR/write_literal.rs:38:33 | LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:47:42 + --> $DIR/write_literal.rs:38:42 | LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:50:43 + --> $DIR/write_literal.rs:41:43 | LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:50:58 + --> $DIR/write_literal.rs:41:58 | LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:51:43 + --> $DIR/write_literal.rs:42:43 | LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ error: literal with an empty format string - --> $DIR/write_literal.rs:51:58 + --> $DIR/write_literal.rs:42:58 | LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 5d8543e578d..2f53d4561af 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(clippy::write_literal)] #![warn(clippy::write_with_newline)] diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index c18ec184876..1f4395c2621 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,5 +1,5 @@ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:19:5 + --> $DIR/write_with_newline.rs:10:5 | LL | write!(&mut v, "Hello/n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | write!(&mut v, "Hello/n"); = note: `-D clippy::write-with-newline` implied by `-D warnings` error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:20:5 + --> $DIR/write_with_newline.rs:11:5 | LL | write!(&mut v, "Hello {}/n", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:21:5 + --> $DIR/write_with_newline.rs:12:5 | LL | write!(&mut v, "Hello {} {}/n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:22:5 + --> $DIR/write_with_newline.rs:13:5 | LL | write!(&mut v, "{}/n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead - --> $DIR/write_with_newline.rs:41:5 + --> $DIR/write_with_newline.rs:32:5 | LL | write!(&mut v, "//n"); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed index 68b8185083d..c3ac15b0375 100644 --- a/tests/ui/writeln_empty_string.fixed +++ b/tests/ui/writeln_empty_string.fixed @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![allow(unused_must_use)] diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index ba43552af23..9a8894b6c0d 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // run-rustfix #![allow(unused_must_use)] diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 119710c0cdb..99635229b3e 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,5 +1,5 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:20:5 + --> $DIR/writeln_empty_string.rs:11:5 | LL | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` @@ -7,7 +7,7 @@ LL | writeln!(&mut v, ""); = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:23:5 + --> $DIR/writeln_empty_string.rs:14:5 | LL | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 3c69c9ad03f..bdffb5af87e 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_pub_self_convention)] #![allow(dead_code, clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index f9d20cb3d47..0d0eb19cd07 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:26:17 + --> $DIR/wrong_self_convention.rs:17:17 | LL | fn from_i32(self) {} | ^^^^ @@ -7,67 +7,67 @@ LL | fn from_i32(self) {} = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:32:21 + --> $DIR/wrong_self_convention.rs:23:21 | LL | pub fn from_i64(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:44:15 + --> $DIR/wrong_self_convention.rs:35:15 | LL | fn as_i32(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:46:17 + --> $DIR/wrong_self_convention.rs:37:17 | LL | fn into_i32(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:48:15 + --> $DIR/wrong_self_convention.rs:39:15 | LL | fn is_i32(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:50:15 + --> $DIR/wrong_self_convention.rs:41:15 | LL | fn to_i32(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:52:17 + --> $DIR/wrong_self_convention.rs:43:17 | LL | fn from_i32(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:54:19 + --> $DIR/wrong_self_convention.rs:45:19 | LL | pub fn as_i64(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:55:21 + --> $DIR/wrong_self_convention.rs:46:21 | LL | pub fn into_i64(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:56:19 + --> $DIR/wrong_self_convention.rs:47:19 | LL | pub fn is_i64(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:57:19 + --> $DIR/wrong_self_convention.rs:48:19 | LL | pub fn to_i64(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:58:21 + --> $DIR/wrong_self_convention.rs:49:21 | LL | pub fn from_i64(self) {} | ^^^^ diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index 68e9437273f..09db130a764 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(unused_variables)] #[warn(clippy::zero_divided_by_zero)] fn main() { diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 653a76c6978..763859f54fb 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -1,5 +1,5 @@ error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:13:15 + --> $DIR/zero_div_zero.rs:4:15 | LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let nan = 0.0 / 0.0; = note: #[deny(clippy::eq_op)] on by default error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:13:15 + --> $DIR/zero_div_zero.rs:4:15 | LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ @@ -16,13 +16,13 @@ LL | let nan = 0.0 / 0.0; = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:14:19 + --> $DIR/zero_div_zero.rs:5:19 | LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:14:19 + --> $DIR/zero_div_zero.rs:5:19 | LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ @@ -30,13 +30,13 @@ LL | let f64_nan = 0.0 / 0.0f64; = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:15:25 + --> $DIR/zero_div_zero.rs:6:25 | LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:15:25 + --> $DIR/zero_div_zero.rs:6:25 | LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ @@ -44,13 +44,13 @@ LL | let other_f64_nan = 0.0f64 / 0.0; = help: Consider using `std::f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:16:28 + --> $DIR/zero_div_zero.rs:7:28 | LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:16:28 + --> $DIR/zero_div_zero.rs:7:28 | LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index 9930b8a4c6b..2291c77d56e 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[allow(unused_variables)] fn main() { let x = 0 as *const usize; diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 5aa5e275ee6..b79c3457b9b 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -1,5 +1,5 @@ error: `0 as *const _` detected. Consider using `ptr::null()` - --> $DIR/zero_ptr.rs:12:13 + --> $DIR/zero_ptr.rs:3:13 | LL | let x = 0 as *const usize; | ^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let x = 0 as *const usize; = note: `-D clippy::zero-ptr` implied by `-D warnings` error: `0 as *mut _` detected. Consider using `ptr::null_mut()` - --> $DIR/zero_ptr.rs:13:13 + --> $DIR/zero_ptr.rs:4:13 | LL | let y = 0 as *mut f64; | ^^^^^^^^^^^^^ diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 945e35f4ebf..9e00571c9d5 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use semver::VersionReq; #[test] diff --git a/util/cov.sh b/util/cov.sh index d927a5cfcd0..3f9a6b06f72 100755 --- a/util/cov.sh +++ b/util/cov.sh @@ -1,16 +1,5 @@ #!/usr/bin/bash -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - - # This run `kcov` on Clippy. The coverage report will be at # `./target/cov/index.html`. # `compile-test` is special. `kcov` does not work directly on it so these files diff --git a/util/export.py b/util/export.py index d8598ed8037..827b1e31905 100755 --- a/util/export.py +++ b/util/export.py @@ -1,16 +1,5 @@ #!/usr/bin/env python -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - - # Build the gh-pages import re diff --git a/util/lintlib.py b/util/lintlib.py index 098fcf256a6..1c49ab770d5 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -1,13 +1,3 @@ -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - # Common utils for the several housekeeping scripts. import os diff --git a/util/update_lints.py b/util/update_lints.py index 4467b5c0cf7..1800fa05c90 100755 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -1,15 +1,5 @@ #!/usr/bin/env python -# Copyright 2014-2018 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - import sys def main(): -- cgit 1.4.1-3-g733a5 From 144f01f3810dca98b7a86df11e0bee6e70b9695b Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 9 Jan 2019 00:50:32 +0100 Subject: readme: update travis badge to reflect migration from travis-ci.org to travis-ci.com --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ca10da416d..69767a1080b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Clippy -[![Build Status](https://travis-ci.org/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang/rust-clippy) +[![Build Status](https://travis-ci.com/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.com/rust-lang/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) [![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy) [![License: MIT/Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) -- cgit 1.4.1-3-g733a5 From 906b51637ca4bfa0cf68b909160937546234a2e2 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Wed, 9 Jan 2019 13:38:38 +0300 Subject: change assert_checks to assertions_on_constants --- CHANGELOG.md | 3 +- README.md | 4 +- clippy_lints/src/assert_checks.rs | 78 ---------------------------- clippy_lints/src/assertions_on_constants.rs | 74 ++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 10 ++-- tests/ui/assert_checks.rs | 13 ----- tests/ui/assert_checks.stderr | 18 ------- tests/ui/assertions_on_constants.rs | 13 +++++ tests/ui/assertions_on_constants.stderr | 16 ++++++ tests/ui/attrs.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/panic_unimplemented.rs | 2 +- 12 files changed, 113 insertions(+), 122 deletions(-) delete mode 100644 clippy_lints/src/assert_checks.rs create mode 100644 clippy_lints/src/assertions_on_constants.rs delete mode 100644 tests/ui/assert_checks.rs delete mode 100644 tests/ui/assert_checks.stderr create mode 100644 tests/ui/assertions_on_constants.rs create mode 100644 tests/ui/assertions_on_constants.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 603fb0b5b7b..69d0350eb09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -616,6 +616,7 @@ All notable changes to this project will be documented in this file. [`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask @@ -679,10 +680,8 @@ All notable changes to this project will be documented in this file. [`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call [`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop -[`explicit_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_false [`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop -[`explicit_true`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_true [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice [`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes diff --git a/README.md b/README.md index 658b2a70adc..751f0add8eb 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. <<<<<<< HEAD -[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) ||||||| merged common ancestors [There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) ======= -[There are 293 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) >>>>>>> run ./util/dev update_lints We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/assert_checks.rs b/clippy_lints/src/assert_checks.rs deleted file mode 100644 index dcc11951b26..00000000000 --- a/clippy_lints/src/assert_checks.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::rustc::hir::{Expr, ExprKind}; -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::syntax::ast::LitKind; -use crate::utils::{is_direct_expn_of, span_lint}; -use if_chain::if_chain; - -/// **What it does:** Check explicit call assert!(true) -/// -/// **Why is this bad?** Will be optimized out by the compiler -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// assert!(true) -/// ``` -declare_clippy_lint! { - pub EXPLICIT_TRUE, - correctness, - "assert!(true) will be optimized out by the compiler" -} - -/// **What it does:** Check explicit call assert!(false) -/// -/// **Why is this bad?** Should probably be replaced by a panic!() or unreachable!() -/// -/// **Known problems:** None -/// -/// **Example:** -/// ```rust -/// assert!(false) -/// ``` -declare_clippy_lint! { - pub EXPLICIT_FALSE, - correctness, - "assert!(false) should probably be replaced by a panic!() or unreachable!()" -} - -pub struct AssertChecks; - -impl LintPass for AssertChecks { - fn get_lints(&self) -> LintArray { - lint_array![EXPLICIT_TRUE, EXPLICIT_FALSE] - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertChecks { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - if_chain! { - if is_direct_expn_of(e.span, "assert").is_some(); - if let ExprKind::Unary(_, ref lit) = e.node; - if let ExprKind::Lit(ref inner) = lit.node; - then { - match inner.node { - LitKind::Bool(true) => { - span_lint(cx, EXPLICIT_TRUE, e.span, - "assert!(true) will be optimized out by the compiler"); - }, - LitKind::Bool(false) => { - span_lint(cx, EXPLICIT_FALSE, e.span, - "assert!(false) should probably be replaced by a panic!() or unreachable!()"); - }, - _ => (), - } - } - } - } -} diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs new file mode 100644 index 00000000000..0068d6fa157 --- /dev/null +++ b/clippy_lints/src/assertions_on_constants.rs @@ -0,0 +1,74 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::rustc::hir::{Expr, ExprKind}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::ast::LitKind; +use crate::utils::{is_direct_expn_of, span_lint, span_lint_and_sugg}; +use rustc_errors::Applicability; +use if_chain::if_chain; + +/// **What it does:** Check explicit call assert!(true/false) +/// +/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a panic!() or unreachable!() +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// assert!(false) +/// // or +/// assert!(true) +/// // or +/// const B: bool = false; +/// assert!(B) +/// ``` +declare_clippy_lint! { + pub ASSERTIONS_ON_CONSTANTS, + style, + "assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()" +} + +pub struct AssertionsOnConstants; + +impl LintPass for AssertionsOnConstants { + fn get_lints(&self) -> LintArray { + lint_array![ASSERTIONS_ON_CONSTANTS] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if_chain! { + if is_direct_expn_of(e.span, "assert").is_some(); + if let ExprKind::Unary(_, ref lit) = e.node; + if let ExprKind::Lit(ref inner) = lit.node; + then { + match inner.node { + LitKind::Bool(true) => { + span_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(true) will be optimized out by the compiler"); + }, + LitKind::Bool(false) => { + span_lint_and_sugg( + cx, + ASSERTIONS_ON_CONSTANTS, + e.span, + "assert!(false) should probably be replaced", + "try", + "panic!()".to_string(), + Applicability::MachineApplicable); + }, + _ => (), + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8af73a4f99b..192c9226b69 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -88,7 +88,7 @@ mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; pub mod arithmetic; -pub mod assert_checks; +pub mod assertions_on_constants; pub mod assign_ops; pub mod attrs; pub mod bit_mask; @@ -487,7 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); - reg.register_late_lint_pass(box assert_checks::AssertChecks); + reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -565,8 +565,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::all", Some("clippy"), vec![ approx_const::APPROX_CONSTANT, - assert_checks::EXPLICIT_FALSE, - assert_checks::EXPLICIT_TRUE, + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_CFG_ATTR, @@ -788,6 +787,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ]); reg.register_lint_group("clippy::style", Some("clippy_style"), vec![ + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, assign_ops::ASSIGN_OP_PATTERN, attrs::UNKNOWN_CLIPPY_LINTS, bit_mask::VERBOSE_BIT_MASK, @@ -944,8 +944,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::correctness", Some("clippy_correctness"), vec![ approx_const::APPROX_CONSTANT, - assert_checks::EXPLICIT_FALSE, - assert_checks::EXPLICIT_TRUE, attrs::DEPRECATED_SEMVER, attrs::USELESS_ATTRIBUTE, bit_mask::BAD_BIT_MASK, diff --git a/tests/ui/assert_checks.rs b/tests/ui/assert_checks.rs deleted file mode 100644 index 811046d060a..00000000000 --- a/tests/ui/assert_checks.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - assert!(true); - assert!(false); -} diff --git a/tests/ui/assert_checks.stderr b/tests/ui/assert_checks.stderr deleted file mode 100644 index e2039941650..00000000000 --- a/tests/ui/assert_checks.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: assert!(true) will be optimized out by the compiler - --> $DIR/assert_checks.rs:11:5 - | -11 | assert!(true); - | ^^^^^^^^^^^^^^ - | - = note: #[deny(clippy::explicit_true)] on by default - -error: assert!(false) should probably be replaced by a panic!() or unreachable!() - --> $DIR/assert_checks.rs:12:5 - | -12 | assert!(false); - | ^^^^^^^^^^^^^^^ - | - = note: #[deny(clippy::explicit_false)] on by default - -error: aborting due to 2 previous errors - diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs new file mode 100644 index 00000000000..811046d060a --- /dev/null +++ b/tests/ui/assertions_on_constants.rs @@ -0,0 +1,13 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + assert!(true); + assert!(false); +} diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr new file mode 100644 index 00000000000..33104ed2066 --- /dev/null +++ b/tests/ui/assertions_on_constants.stderr @@ -0,0 +1,16 @@ +error: assert!(true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:11:5 + | +LL | assert!(true); + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::assertions-on-constants` implied by `-D warnings` + +error: assert!(false) should probably be replaced + --> $DIR/assertions_on_constants.rs:12:5 + | +LL | assert!(false); + | ^^^^^^^^^^^^^^^ help: try: `panic!()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index c0ea7329718..2c7f67d4505 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::inline_always, clippy::deprecated_semver)] -#![allow(clippy::assert_checks::explicit_true)] +#![allow(clippy::assertions_on_constants::assertions_on_constants)] #[inline(always)] fn test_attr_lint() { assert!(true) diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index a6e6adcac5c..2bb5037614d 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::empty_line_after_outer_attr)] -#![allow(clippy::assert_checks::explicit_true)] +#![allow(clippy::assertions_on_constants::assertions_on_constants)] // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index 3c568658a6c..309a22dc215 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -8,7 +8,7 @@ // except according to those terms. #![warn(clippy::panic_params, clippy::unimplemented)] -#![allow(clippy::assert_checks::explicit_true)] +#![allow(clippy::assertions_on_constants::assertions_on_constants)] fn missing() { if true { panic!("{}"); -- cgit 1.4.1-3-g733a5 From a9f8d3c8fdc18080df800e65d73a737ccfd08933 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Wed, 9 Jan 2019 21:30:47 +0300 Subject: add assert(true/false, some message) tests --- clippy_lints/src/assertions_on_constants.rs | 55 ++++++++++++++++++----------- tests/ui/assertions_on_constants.rs | 8 +++++ tests/ui/assertions_on_constants.stderr | 39 ++++++++++++++++++-- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 0068d6fa157..f88ef8e83ed 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -7,17 +7,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use crate::consts::{constant, Constant}; use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::LitKind; -use crate::utils::{is_direct_expn_of, span_lint, span_lint_and_sugg}; -use rustc_errors::Applicability; +use crate::utils::{is_direct_expn_of, span_help_and_lint}; use if_chain::if_chain; -/// **What it does:** Check explicit call assert!(true/false) +/// **What it does:** Check to call assert!(true/false) /// -/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a panic!() or unreachable!() +/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a +/// panic!() or unreachable!() /// /// **Known problems:** None /// @@ -49,24 +50,36 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { if_chain! { if is_direct_expn_of(e.span, "assert").is_some(); if let ExprKind::Unary(_, ref lit) = e.node; - if let ExprKind::Lit(ref inner) = lit.node; then { - match inner.node { - LitKind::Bool(true) => { - span_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, - "assert!(true) will be optimized out by the compiler"); - }, - LitKind::Bool(false) => { - span_lint_and_sugg( - cx, - ASSERTIONS_ON_CONSTANTS, - e.span, - "assert!(false) should probably be replaced", - "try", - "panic!()".to_string(), - Applicability::MachineApplicable); - }, - _ => (), + if let ExprKind::Lit(ref inner) = lit.node { + match inner.node { + LitKind::Bool(true) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(true) will be optimized out by the compiler", + "remove it"); + }, + LitKind::Bool(false) => { + span_help_and_lint( + cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(false) should probably be replaced", + "use panic!() or unreachable!()"); + }, + _ => (), + } + } else if let Some(bool_const) = constant(cx, cx.tables, lit) { + match bool_const.0 { + Constant::Bool(true) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(const: true) will be optimized out by the compiler", + "remove it"); + }, + Constant::Bool(false) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(const: false) should probably be replaced", + "use panic!() or unreachable!()"); + }, + _ => (), + } } } } diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs index 811046d060a..dcefe83f8c2 100644 --- a/tests/ui/assertions_on_constants.rs +++ b/tests/ui/assertions_on_constants.rs @@ -10,4 +10,12 @@ fn main() { assert!(true); assert!(false); + assert!(true, "true message"); + assert!(false, "false message"); + + const B: bool = true; + assert!(B); + + const C: bool = false; + assert!(C); } diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index 33104ed2066..1f1a80e0e77 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -5,12 +5,47 @@ LL | assert!(true); | ^^^^^^^^^^^^^^ | = note: `-D clippy::assertions-on-constants` implied by `-D warnings` + = help: remove it error: assert!(false) should probably be replaced --> $DIR/assertions_on_constants.rs:12:5 | LL | assert!(false); - | ^^^^^^^^^^^^^^^ help: try: `panic!()` + | ^^^^^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() + +error: assert!(true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:13:5 + | +LL | assert!(true, "true message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: remove it + +error: assert!(false) should probably be replaced + --> $DIR/assertions_on_constants.rs:14:5 + | +LL | assert!(false, "false message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() + +error: assert!(const: true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:17:5 + | +LL | assert!(B); + | ^^^^^^^^^^^ + | + = help: remove it + +error: assert!(const: false) should probably be replaced + --> $DIR/assertions_on_constants.rs:20:5 + | +LL | assert!(C); + | ^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 58abdb591884bcde77d53a5933a78c89e26c6752 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Wed, 9 Jan 2019 21:31:29 +0300 Subject: run ./util/dev update_lints --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ca10da416d..3a7e9a165c1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 292 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 798a419b1c57a388fab026263d3bd256bdb779f6 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Thu, 10 Jan 2019 22:48:40 +0100 Subject: Fix comments in clippy_lints/src/len_zero.rs --- clippy_lints/src/len_zero.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 40fef2df27f..b15ba5a4783 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -31,10 +31,10 @@ use syntax::source_map::{Span, Spanned}; /// ``` /// instead use /// ```rust -/// if x.len().is_empty() { +/// if x.is_empty() { /// .. /// } -/// if !y.len().is_empty() { +/// if !y.is_empty() { /// .. /// } /// ``` @@ -115,8 +115,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { check_cmp(cx, expr.span, left, right, "", 1); // len < 1 check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len }, - BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1 - BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len + BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1 + BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len _ => (), } } -- cgit 1.4.1-3-g733a5 From 079a593dabed7efd673d65ff341a74482496b8c3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 12 Jan 2019 16:11:17 +0100 Subject: rustup: the features if_while_or_patterns has been stabilized --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e9d8732cb35..608094c833d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -11,7 +11,6 @@ #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![feature(crate_visibility_modifier)] #![feature(try_from)] -#![feature(if_while_or_patterns)] // FIXME: switch to something more ergonomic here, once available. // (currently there is no way to opt into sysroot crates w/o `extern crate`) -- cgit 1.4.1-3-g733a5 From 09323d74265b716c85843f215fd16d3ea6a8879c Mon Sep 17 00:00:00 2001 From: Manas Karekar Date: Sat, 12 Jan 2019 19:42:36 -0500 Subject: Update Readme for (arguably) better readability Move final instruction to run clippy into a third step in the Readme so it's easier to spot at a quick glance. --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77ba2daad57..412ccb45b4e 100644 --- a/README.md +++ b/README.md @@ -69,9 +69,15 @@ Once you have rustup and the latest stable release (at least Rust 1.29) installe rustup component add clippy ``` -Now you can run Clippy by invoking `cargo clippy`. +#### Step 3: Run Clippy -If it says that it can't find the `clippy` subcommand, please run `rustup self update` +Now you can run Clippy by invoking the following command: + +```terminal +cargo clippy +``` + +If it says that it can't find the `clippy` subcommand, please run `rustup self update`. ### Running Clippy from the command line without installing it -- cgit 1.4.1-3-g733a5 From a8157d2de72dd6b50f46a12e5169d56b96967ba8 Mon Sep 17 00:00:00 2001 From: Manas Karekar Date: Sat, 12 Jan 2019 20:24:52 -0500 Subject: Update Readme Move instruction to the correct step for installing Clippy. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 412ccb45b4e..24a57450b85 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Once you have rustup and the latest stable release (at least Rust 1.29) installe ```terminal rustup component add clippy ``` +If it says that it can't find the `clippy` component, please run `rustup self update`. #### Step 3: Run Clippy @@ -77,8 +78,6 @@ Now you can run Clippy by invoking the following command: cargo clippy ``` -If it says that it can't find the `clippy` subcommand, please run `rustup self update`. - ### Running Clippy from the command line without installing it To have cargo compile your crate with Clippy without Clippy installation -- cgit 1.4.1-3-g733a5 From c0083e2b989152e3c24a0da6d8fdab48993b2e16 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 11:44:45 +0100 Subject: Add run-rustfix to collapsible_if test --- tests/ui/collapsible_if.fixed | 175 +++++++++++++++++++++++++++++++++++++++++ tests/ui/collapsible_if.rs | 3 + tests/ui/collapsible_if.stderr | 28 +++---- 3 files changed, 192 insertions(+), 14 deletions(-) create mode 100644 tests/ui/collapsible_if.fixed diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed new file mode 100644 index 00000000000..2c6dd95a637 --- /dev/null +++ b/tests/ui/collapsible_if.fixed @@ -0,0 +1,175 @@ +// run-rustfix +#![allow(clippy::cyclomatic_complexity)] + +#[rustfmt::skip] +#[warn(clippy::collapsible_if)] +fn main() { + let x = "hello"; + let y = "world"; + if x == "hello" && y == "world" { + println!("Hello world!"); +} + + if (x == "hello" || x == "world") && (y == "world" || y == "hello") { + println!("Hello world!"); +} + + if x == "hello" && x == "world" && (y == "world" || y == "hello") { + println!("Hello world!"); +} + + if (x == "hello" || x == "world") && y == "world" && y == "hello" { + println!("Hello world!"); +} + + if x == "hello" && x == "world" && y == "world" && y == "hello" { + println!("Hello world!"); +} + + if 42 == 1337 && 'a' != 'A' { + println!("world!") +} + + // Collapse `else { if .. }` to `else if ..` + if x == "hello" { + print!("Hello "); + } else if y == "world" { + println!("world!") +} + + if x == "hello" { + print!("Hello "); + } else if let Some(42) = Some(42) { + println!("world!") +} + + if x == "hello" { + print!("Hello "); + } else if y == "world" { + println!("world") +} +else { + println!("!") +} + + if x == "hello" { + print!("Hello "); + } else if let Some(42) = Some(42) { + println!("world") +} +else { + println!("!") +} + + if let Some(42) = Some(42) { + print!("Hello "); + } else if let Some(42) = Some(42) { + println!("world") +} +else { + println!("!") +} + + if let Some(42) = Some(42) { + print!("Hello "); + } else if x == "hello" { + println!("world") +} +else { + println!("!") +} + + if let Some(42) = Some(42) { + print!("Hello "); + } else if let Some(42) = Some(42) { + println!("world") +} +else { + println!("!") +} + + // Works because any if with an else statement cannot be collapsed. + if x == "hello" { + if y == "world" { + println!("Hello world!"); + } + } else { + println!("Not Hello world"); + } + + if x == "hello" { + if y == "world" { + println!("Hello world!"); + } else { + println!("Hello something else"); + } + } + + if x == "hello" { + print!("Hello "); + if y == "world" { + println!("world!") + } + } + + if true { + } else { + assert!(true); // assert! is just an `if` + } + + + // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 + if x == "hello" {// Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { // Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { + // Not collapsible + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" && y == "world" { // Collapsible + println!("Hello world!"); +} + + if x == "hello" { + print!("Hello "); + } else { + // Not collapsible + if y == "world" { + println!("world!") + } + } + + if x == "hello" { + print!("Hello "); + } else { + // Not collapsible + if let Some(42) = Some(42) { + println!("world!") + } + } + + if x == "hello" { + /* Not collapsible */ + if y == "world" { + println!("Hello world!"); + } + } + + if x == "hello" { /* Not collapsible */ + if y == "world" { + println!("Hello world!"); + } + } +} diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index e8918ddecb5..f482d7704de 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,3 +1,6 @@ +// run-rustfix +#![allow(clippy::cyclomatic_complexity)] + #[rustfmt::skip] #[warn(clippy::collapsible_if)] fn main() { diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 1b9195563e5..d6d0b9d5d4e 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,5 +1,5 @@ error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:6:5 + --> $DIR/collapsible_if.rs:9:5 | LL | / if x == "hello" { LL | | if y == "world" { @@ -17,7 +17,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:12:5 + --> $DIR/collapsible_if.rs:15:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -33,7 +33,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:18:5 + --> $DIR/collapsible_if.rs:21:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -49,7 +49,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:24:5 + --> $DIR/collapsible_if.rs:27:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -65,7 +65,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:30:5 + --> $DIR/collapsible_if.rs:33:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -81,7 +81,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:36:5 + --> $DIR/collapsible_if.rs:39:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -97,7 +97,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:45:12 + --> $DIR/collapsible_if.rs:48:12 | LL | } else { | ____________^ @@ -114,7 +114,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:53:12 + --> $DIR/collapsible_if.rs:56:12 | LL | } else { | ____________^ @@ -131,7 +131,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:61:12 + --> $DIR/collapsible_if.rs:64:12 | LL | } else { | ____________^ @@ -153,7 +153,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:72:12 + --> $DIR/collapsible_if.rs:75:12 | LL | } else { | ____________^ @@ -175,7 +175,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:83:12 + --> $DIR/collapsible_if.rs:86:12 | LL | } else { | ____________^ @@ -197,7 +197,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:94:12 + --> $DIR/collapsible_if.rs:97:12 | LL | } else { | ____________^ @@ -219,7 +219,7 @@ LL | } | error: this `else { if .. }` block can be collapsed - --> $DIR/collapsible_if.rs:105:12 + --> $DIR/collapsible_if.rs:108:12 | LL | } else { | ____________^ @@ -241,7 +241,7 @@ LL | } | error: this if statement can be collapsed - --> $DIR/collapsible_if.rs:164:5 + --> $DIR/collapsible_if.rs:167:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible -- cgit 1.4.1-3-g733a5 From ea7eb49b478a5f656f62f3e3664009194408ecf0 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 11:53:43 +0100 Subject: Disable deprecated_cfg_attr lint for inner attributes --- clippy_lints/src/attrs.rs | 9 ++++----- tests/ui/cfg_attr_rustfmt.fixed | 31 +++++++++++++++++++++++++++++++ tests/ui/cfg_attr_rustfmt.rs | 2 ++ tests/ui/cfg_attr_rustfmt.stderr | 12 +++--------- 4 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 tests/ui/cfg_attr_rustfmt.fixed diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 24cc8a81dc0..a3f2cc6a23b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -511,18 +511,17 @@ impl EarlyLintPass for CfgAttrPass { // check for `rustfmt_skip` and `rustfmt::skip` if let Some(skip_item) = &items[1].meta_item(); if skip_item.name() == "rustfmt_skip" || skip_item.name() == "skip"; + // Only lint outer attributes, because custom inner attributes are unstable + // Tracking issue: https://github.com/rust-lang/rust/issues/54726 + if let AttrStyle::Outer = attr.style; then { - let attr_style = match attr.style { - AttrStyle::Outer => "#[", - AttrStyle::Inner => "#![", - }; span_lint_and_sugg( cx, DEPRECATED_CFG_ATTR, attr.span, "`cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes", "use", - format!("{}rustfmt::skip]", attr_style), + "#[rustfmt::skip]".to_string(), Applicability::MachineApplicable, ); } diff --git a/tests/ui/cfg_attr_rustfmt.fixed b/tests/ui/cfg_attr_rustfmt.fixed new file mode 100644 index 00000000000..4e583a25b94 --- /dev/null +++ b/tests/ui/cfg_attr_rustfmt.fixed @@ -0,0 +1,31 @@ +// run-rustfix +#![feature(stmt_expr_attributes)] + +#![allow(unused, clippy::no_effect)] +#![warn(clippy::deprecated_cfg_attr)] + +// This doesn't get linted, see known problems +#![cfg_attr(rustfmt, rustfmt_skip)] + +#[rustfmt::skip] +trait Foo +{ +fn foo( +); +} + +fn skip_on_statements() { + #[rustfmt::skip] + 5+3; +} + +#[rustfmt::skip] +fn main() { + foo::f(); +} + +mod foo { + #![cfg_attr(rustfmt, rustfmt_skip)] + + pub fn f() {} +} diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index 7f4a86ae185..9c0fcf6fb45 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -1,5 +1,7 @@ +// run-rustfix #![feature(stmt_expr_attributes)] +#![allow(unused, clippy::no_effect)] #![warn(clippy::deprecated_cfg_attr)] // This doesn't get linted, see known problems diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index e60f5f25535..09971caceea 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -1,5 +1,5 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:16:5 + --> $DIR/cfg_attr_rustfmt.rs:18:5 | LL | #[cfg_attr(rustfmt, rustfmt::skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` @@ -7,16 +7,10 @@ LL | #[cfg_attr(rustfmt, rustfmt::skip)] = note: `-D clippy::deprecated-cfg-attr` implied by `-D warnings` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:20:1 + --> $DIR/cfg_attr_rustfmt.rs:22:1 | LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` -error: `cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes - --> $DIR/cfg_attr_rustfmt.rs:26:5 - | -LL | #![cfg_attr(rustfmt, rustfmt_skip)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#![rustfmt::skip]` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 29211be896f0560789f397033bcc79d321e44e16 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:06:28 +0100 Subject: Add run-rustfix to duration_subsec test --- tests/ui/duration_subsec.fixed | 29 +++++++++++++++++++++++++++++ tests/ui/duration_subsec.rs | 2 ++ tests/ui/duration_subsec.stderr | 10 +++++----- 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 tests/ui/duration_subsec.fixed diff --git a/tests/ui/duration_subsec.fixed b/tests/ui/duration_subsec.fixed new file mode 100644 index 00000000000..ee5c7863eff --- /dev/null +++ b/tests/ui/duration_subsec.fixed @@ -0,0 +1,29 @@ +// run-rustfix +#![allow(dead_code)] +#![warn(clippy::duration_subsec)] + +use std::time::Duration; + +fn main() { + let dur = Duration::new(5, 0); + + let bad_millis_1 = dur.subsec_millis(); + let bad_millis_2 = dur.subsec_millis(); + let good_millis = dur.subsec_millis(); + assert_eq!(bad_millis_1, good_millis); + assert_eq!(bad_millis_2, good_millis); + + let bad_micros = dur.subsec_micros(); + let good_micros = dur.subsec_micros(); + assert_eq!(bad_micros, good_micros); + + // Handle refs + let _ = (&dur).subsec_micros(); + + // Handle constants + const NANOS_IN_MICRO: u32 = 1_000; + let _ = dur.subsec_micros(); + + // Other literals aren't linted + let _ = dur.subsec_nanos() / 699; +} diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index d54d2f46eb7..3c9d2a28621 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(dead_code)] #![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index 249777e863c..bd8adc2c570 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,5 +1,5 @@ error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:8:24 + --> $DIR/duration_subsec.rs:10:24 | LL | let bad_millis_1 = dur.subsec_micros() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` @@ -7,25 +7,25 @@ LL | let bad_millis_1 = dur.subsec_micros() / 1_000; = note: `-D clippy::duration-subsec` implied by `-D warnings` error: Calling `subsec_millis()` is more concise than this calculation - --> $DIR/duration_subsec.rs:9:24 + --> $DIR/duration_subsec.rs:11:24 | LL | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:14:22 + --> $DIR/duration_subsec.rs:16:22 | LL | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:19:13 + --> $DIR/duration_subsec.rs:21:13 | LL | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: Calling `subsec_micros()` is more concise than this calculation - --> $DIR/duration_subsec.rs:23:13 + --> $DIR/duration_subsec.rs:25:13 | LL | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` -- cgit 1.4.1-3-g733a5 From 9f8fb8007c467707c5820b3b9b5789f6340c7cdc Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:09:30 +0100 Subject: Add run-rustfix to excessive_precision test --- tests/ui/excessive_precision.fixed | 63 +++++++++++++++++++++++++++++++++++++ tests/ui/excessive_precision.rs | 3 +- tests/ui/excessive_precision.stderr | 36 ++++++++++----------- 3 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 tests/ui/excessive_precision.fixed diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed new file mode 100644 index 00000000000..1646dff9064 --- /dev/null +++ b/tests/ui/excessive_precision.fixed @@ -0,0 +1,63 @@ +// run-rustfix +#![warn(clippy::excessive_precision)] +#![allow(dead_code, unused_variables, clippy::print_literal)] + +fn main() { + // Consts + const GOOD32: f32 = 0.123_456; + const GOOD32_SM: f32 = 0.000_000_000_1; + const GOOD32_DOT: f32 = 10_000_000_000.0; + const GOOD32_EDGE: f32 = 1.000_000_8; + const GOOD64: f64 = 0.123_456_789_012; + const GOOD64_SM: f32 = 0.000_000_000_000_000_1; + const GOOD64_DOT: f32 = 10_000_000_000_000_000.0; + + const BAD32_1: f32 = 0.123_456_79; + const BAD32_2: f32 = 0.123_456_79; + const BAD32_3: f32 = 0.1; + const BAD32_EDGE: f32 = 1.000_001; + + const BAD64_1: f64 = 0.123_456_789_012_345_66; + const BAD64_2: f64 = 0.123_456_789_012_345_66; + const BAD64_3: f64 = 0.1; + + // Literal as param + println!("{:?}", 8.888_888_888_888_89); + + // // TODO add inferred type tests for f32 + // Locals + let good32: f32 = 0.123_456_f32; + let good32_2: f32 = 0.123_456; + + let good64: f64 = 0.123_456_789_012; + let good64_suf: f64 = 0.123_456_789_012f64; + let good64_inf = 0.123_456_789_012; + + let bad32: f32 = 1.123_456_8; + let bad32_suf: f32 = 1.123_456_8; + let bad32_inf = 1.123_456_8; + + let bad64: f64 = 0.123_456_789_012_345_66; + let bad64_suf: f64 = 0.123_456_789_012_345_66; + let bad64_inf = 0.123_456_789_012_345_66; + + // Vectors + let good_vec32: Vec = vec![0.123_456]; + let good_vec64: Vec = vec![0.123_456_789]; + + let bad_vec32: Vec = vec![0.123_456_79]; + let bad_vec64: Vec = vec![0.123_456_789_123_456_78]; + + // Exponential float notation + let good_e32: f32 = 1e-10; + let bad_e32: f32 = 1.123_456_8e-10; + + let good_bige32: f32 = 1E-10; + let bad_bige32: f32 = 1.123_456_8E-10; + + // Inferred type + let good_inferred: f32 = 1f32 * 1_000_000_000.; + + // issue #2840 + let num = 0.000_000_000_01e-10f64; +} diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index d5fa903c23f..ce4722a90f9 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,5 +1,6 @@ +// run-rustfix #![warn(clippy::excessive_precision)] -#![allow(clippy::print_literal)] +#![allow(dead_code, unused_variables, clippy::print_literal)] fn main() { // Consts diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index da8d9471bcc..12f8a61b75c 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,5 +1,5 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:14:26 + --> $DIR/excessive_precision.rs:15:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` @@ -7,103 +7,103 @@ LL | const BAD32_1: f32 = 0.123_456_789_f32; = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:15:26 + --> $DIR/excessive_precision.rs:16:26 | LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:16:26 + --> $DIR/excessive_precision.rs:17:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:17:29 + --> $DIR/excessive_precision.rs:18:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:19:26 + --> $DIR/excessive_precision.rs:20:26 | LL | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:20:26 + --> $DIR/excessive_precision.rs:21:26 | LL | const BAD64_2: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:21:26 + --> $DIR/excessive_precision.rs:22:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:24:22 + --> $DIR/excessive_precision.rs:25:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:35:22 + --> $DIR/excessive_precision.rs:36:22 | LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:36:26 + --> $DIR/excessive_precision.rs:37:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:37:21 + --> $DIR/excessive_precision.rs:38:21 | LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:39:22 + --> $DIR/excessive_precision.rs:40:22 | LL | let bad64: f64 = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:40:26 + --> $DIR/excessive_precision.rs:41:26 | LL | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:41:21 + --> $DIR/excessive_precision.rs:42:21 | LL | let bad64_inf = 0.123_456_789_012_345_67; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` error: float has excessive precision - --> $DIR/excessive_precision.rs:47:36 + --> $DIR/excessive_precision.rs:48:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:36 + --> $DIR/excessive_precision.rs:49:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:52:24 + --> $DIR/excessive_precision.rs:53:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:55:27 + --> $DIR/excessive_precision.rs:56:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` -- cgit 1.4.1-3-g733a5 From 40d9f1d9f43c50bbaaff1126fc10614cdbdec399 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:22:59 +0100 Subject: Add run-rustfix to explicit_write test --- tests/ui/explicit_write.fixed | 51 ++++++++++++++++++++++++++++++++++++++++++ tests/ui/explicit_write.rs | 2 ++ tests/ui/explicit_write.stderr | 16 ++++++------- 3 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 tests/ui/explicit_write.fixed diff --git a/tests/ui/explicit_write.fixed b/tests/ui/explicit_write.fixed new file mode 100644 index 00000000000..692d2ca675f --- /dev/null +++ b/tests/ui/explicit_write.fixed @@ -0,0 +1,51 @@ +// run-rustfix +#![allow(unused_imports)] +#![warn(clippy::explicit_write)] + +fn stdout() -> String { + String::new() +} + +fn stderr() -> String { + String::new() +} + +fn main() { + // these should warn + { + use std::io::Write; + print!("test"); + eprint!("test"); + println!("test"); + eprintln!("test"); + print!("test"); + eprint!("test"); + + // including newlines + println!("test\ntest"); + eprintln!("test\ntest"); + } + // these should not warn, different destination + { + use std::fmt::Write; + let mut s = String::new(); + write!(s, "test").unwrap(); + write!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + writeln!(s, "test").unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + s.write_fmt(format_args!("test")).unwrap(); + write!(stdout(), "test").unwrap(); + write!(stderr(), "test").unwrap(); + writeln!(stdout(), "test").unwrap(); + writeln!(stderr(), "test").unwrap(); + stdout().write_fmt(format_args!("test")).unwrap(); + stderr().write_fmt(format_args!("test")).unwrap(); + } + // these should not warn, no unwrap + { + use std::io::Write; + std::io::stdout().write_fmt(format_args!("test")).expect("no stdout"); + std::io::stderr().write_fmt(format_args!("test")).expect("no stderr"); + } +} diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 6231a0b0588..455c5ef55d0 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(unused_imports)] #![warn(clippy::explicit_write)] fn stdout() -> String { diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 5fd2f8a3abf..9feef9c0dc8 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -1,5 +1,5 @@ error: use of `write!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:15:9 + --> $DIR/explicit_write.rs:17:9 | LL | write!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` @@ -7,43 +7,43 @@ LL | write!(std::io::stdout(), "test").unwrap(); = note: `-D clippy::explicit-write` implied by `-D warnings` error: use of `write!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:16:9 + --> $DIR/explicit_write.rs:18:9 | LL | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:17:9 + --> $DIR/explicit_write.rs:19:9 | LL | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:18:9 + --> $DIR/explicit_write.rs:20:9 | LL | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:19:9 + --> $DIR/explicit_write.rs:21:9 | LL | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` - --> $DIR/explicit_write.rs:20:9 + --> $DIR/explicit_write.rs:22:9 | LL | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> $DIR/explicit_write.rs:23:9 + --> $DIR/explicit_write.rs:25:9 | LL | writeln!(std::io::stdout(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` - --> $DIR/explicit_write.rs:24:9 + --> $DIR/explicit_write.rs:26:9 | LL | writeln!(std::io::stderr(), "test/ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` -- cgit 1.4.1-3-g733a5 From 87407c5e5f27ade439ddf5b98e5d739ddb4ef1bd Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:43:10 +0100 Subject: Add rustfix to inconsistent_digit_grouping test --- tests/ui/inconsistent_digit_grouping.fixed | 15 +++++++++++++++ tests/ui/inconsistent_digit_grouping.rs | 3 ++- tests/ui/inconsistent_digit_grouping.stderr | 10 +++++----- 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 tests/ui/inconsistent_digit_grouping.fixed diff --git a/tests/ui/inconsistent_digit_grouping.fixed b/tests/ui/inconsistent_digit_grouping.fixed new file mode 100644 index 00000000000..f25be70737b --- /dev/null +++ b/tests/ui/inconsistent_digit_grouping.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#[warn(clippy::inconsistent_digit_grouping)] +#[allow(unused_variables, clippy::excessive_precision)] +fn main() { + let good = ( + 123, + 1_234, + 1_2345_6789, + 123_f32, + 1_234.12_f32, + 1_234.123_4_f32, + 1.123_456_7_f32, + ); + let bad = (123_456, 12_345_678, 1_234_567, 1_234.567_8_f32, 1.234_567_8_f32); +} diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index 529ab042610..206fac8d3e3 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,5 +1,6 @@ +// run-rustfix #[warn(clippy::inconsistent_digit_grouping)] -#[allow(unused_variables)] +#[allow(unused_variables, clippy::excessive_precision)] fn main() { let good = ( 123, diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 9b903d1764f..9fc1f424dc6 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,5 +1,5 @@ error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:13:16 + --> $DIR/inconsistent_digit_grouping.rs:14:16 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` @@ -7,25 +7,25 @@ LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:13:26 + --> $DIR/inconsistent_digit_grouping.rs:14:26 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:13:38 + --> $DIR/inconsistent_digit_grouping.rs:14:38 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:13:48 + --> $DIR/inconsistent_digit_grouping.rs:14:48 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:13:64 + --> $DIR/inconsistent_digit_grouping.rs:14:64 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` -- cgit 1.4.1-3-g733a5 From 787f5a2c12e72af923c1b0983e0f5b97839bcd40 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:49:54 +0100 Subject: Add run-rustfix to infallible_destructuring_match --- tests/ui/infallible_destructuring_match.fixed | 79 ++++++++++++++++++++++++++ tests/ui/infallible_destructuring_match.rs | 2 + tests/ui/infallible_destructuring_match.stderr | 6 +- 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 tests/ui/infallible_destructuring_match.fixed diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed new file mode 100644 index 00000000000..f16f0fd0019 --- /dev/null +++ b/tests/ui/infallible_destructuring_match.fixed @@ -0,0 +1,79 @@ +// run-rustfix +#![feature(exhaustive_patterns, never_type)] +#![allow(dead_code, unreachable_code, unused_variables)] +#![allow(clippy::let_and_return)] + +enum SingleVariantEnum { + Variant(i32), +} + +struct TupleStruct(i32); + +enum EmptyEnum {} + +fn infallible_destructuring_match_enum() { + let wrapper = SingleVariantEnum::Variant(0); + + // This should lint! + let SingleVariantEnum::Variant(data) = wrapper; + + // This shouldn't! + let data = match wrapper { + SingleVariantEnum::Variant(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + SingleVariantEnum::Variant(i) => -1, + }; + + let SingleVariantEnum::Variant(data) = wrapper; +} + +fn infallible_destructuring_match_struct() { + let wrapper = TupleStruct(0); + + // This should lint! + let TupleStruct(data) = wrapper; + + // This shouldn't! + let data = match wrapper { + TupleStruct(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + TupleStruct(i) => -1, + }; + + let TupleStruct(data) = wrapper; +} + +fn never_enum() { + let wrapper: Result = Ok(23); + + // This should lint! + let Ok(data) = wrapper; + + // This shouldn't! + let data = match wrapper { + Ok(_) => -1, + }; + + // Neither should this! + let data = match wrapper { + Ok(i) => -1, + }; + + let Ok(data) = wrapper; +} + +impl EmptyEnum { + fn match_on(&self) -> ! { + // The lint shouldn't pick this up, as `let` won't work here! + let data = match *self {}; + data + } +} + +fn main() {} diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index a34b06d5642..a4823ad60ad 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,4 +1,6 @@ +// run-rustfix #![feature(exhaustive_patterns, never_type)] +#![allow(dead_code, unreachable_code, unused_variables)] #![allow(clippy::let_and_return)] enum SingleVariantEnum { diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index b2b37b9bff7..e3693d44e9a 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:16:5 + --> $DIR/infallible_destructuring_match.rs:18:5 | LL | / let data = match wrapper { LL | | SingleVariantEnum::Variant(i) => i, @@ -9,7 +9,7 @@ LL | | }; = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:37:5 + --> $DIR/infallible_destructuring_match.rs:39:5 | LL | / let data = match wrapper { LL | | TupleStruct(i) => i, @@ -17,7 +17,7 @@ LL | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use match to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:58:5 + --> $DIR/infallible_destructuring_match.rs:60:5 | LL | / let data = match wrapper { LL | | Ok(i) => i, -- cgit 1.4.1-3-g733a5 From 256b6419762e662c5d9e6e7e41241b6bb9110e9f Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:52:51 +0100 Subject: Add run-rustfix to into_iter_on_ref --- tests/ui/into_iter_on_ref.fixed | 46 +++++++++++++++++++++++++++++++ tests/ui/into_iter_on_ref.rs | 2 ++ tests/ui/into_iter_on_ref.stderr | 58 ++++++++++++++++++++-------------------- 3 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 tests/ui/into_iter_on_ref.fixed diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed new file mode 100644 index 00000000000..f5342be631b --- /dev/null +++ b/tests/ui/into_iter_on_ref.fixed @@ -0,0 +1,46 @@ +// run-rustfix +#![allow(clippy::useless_vec)] +#![warn(clippy::into_iter_on_ref)] +#![deny(clippy::into_iter_on_array)] + +struct X; +use std::collections::*; + +fn main() { + for _ in &[1, 2, 3] {} + for _ in vec![X, X] {} + for _ in &vec![X, X] {} + for _ in [1, 2, 3].iter() {} //~ ERROR equivalent to .iter() + + let _ = [1, 2, 3].iter(); //~ ERROR equivalent to .iter() + let _ = vec![1, 2, 3].into_iter(); + let _ = (&vec![1, 2, 3]).iter(); //~ WARN equivalent to .iter() + let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ WARN equivalent to .iter() + let _ = std::rc::Rc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() + let _ = std::sync::Arc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() + + let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() + let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() + let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR equivalent to .iter_mut() + + let _ = (&Some(4)).iter(); //~ WARN equivalent to .iter() + let _ = (&mut Some(5)).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&Ok::<_, i32>(6)).iter(); //~ WARN equivalent to .iter() + let _ = (&mut Err::(7)).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&Vec::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&mut Vec::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&BTreeMap::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&mut BTreeMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&VecDeque::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&mut VecDeque::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&LinkedList::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&mut LinkedList::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&HashMap::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&mut HashMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + + let _ = (&BTreeSet::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&BinaryHeap::::new()).iter(); //~ WARN equivalent to .iter() + let _ = (&HashSet::::new()).iter(); //~ WARN equivalent to .iter() + let _ = std::path::Path::new("12/34").iter(); //~ WARN equivalent to .iter() + let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR equivalent to .iter() +} diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 212234f0346..5ec64dcf733 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(clippy::useless_vec)] #![warn(clippy::into_iter_on_ref)] #![deny(clippy::into_iter_on_array)] diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index e7f2a21d7a4..931e4880f93 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,23 +1,23 @@ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:11:24 + --> $DIR/into_iter_on_ref.rs:13:24 | LL | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` | note: lint level defined here - --> $DIR/into_iter_on_ref.rs:2:9 + --> $DIR/into_iter_on_ref.rs:4:9 | LL | #![deny(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:13:23 + --> $DIR/into_iter_on_ref.rs:15:23 | LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the Vec - --> $DIR/into_iter_on_ref.rs:15:30 + --> $DIR/into_iter_on_ref.rs:17:30 | LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` @@ -25,151 +25,151 @@ LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` error: this .into_iter() call is equivalent to .iter() and will not move the slice - --> $DIR/into_iter_on_ref.rs:16:46 + --> $DIR/into_iter_on_ref.rs:18:46 | LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the slice - --> $DIR/into_iter_on_ref.rs:17:41 + --> $DIR/into_iter_on_ref.rs:19:41 | LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the slice - --> $DIR/into_iter_on_ref.rs:18:44 + --> $DIR/into_iter_on_ref.rs:20:44 | LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:20:32 + --> $DIR/into_iter_on_ref.rs:22:32 | LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:21:36 + --> $DIR/into_iter_on_ref.rs:23:36 | LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the array - --> $DIR/into_iter_on_ref.rs:22:40 + --> $DIR/into_iter_on_ref.rs:24:40 | LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Option - --> $DIR/into_iter_on_ref.rs:24:24 + --> $DIR/into_iter_on_ref.rs:26:24 | LL | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Option - --> $DIR/into_iter_on_ref.rs:25:28 + --> $DIR/into_iter_on_ref.rs:27:28 | LL | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Result - --> $DIR/into_iter_on_ref.rs:26:32 + --> $DIR/into_iter_on_ref.rs:28:32 | LL | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Result - --> $DIR/into_iter_on_ref.rs:27:37 + --> $DIR/into_iter_on_ref.rs:29:37 | LL | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the Vec - --> $DIR/into_iter_on_ref.rs:28:34 + --> $DIR/into_iter_on_ref.rs:30:34 | LL | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the Vec - --> $DIR/into_iter_on_ref.rs:29:38 + --> $DIR/into_iter_on_ref.rs:31:38 | LL | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the BTreeMap - --> $DIR/into_iter_on_ref.rs:30:44 + --> $DIR/into_iter_on_ref.rs:32:44 | LL | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the BTreeMap - --> $DIR/into_iter_on_ref.rs:31:48 + --> $DIR/into_iter_on_ref.rs:33:48 | LL | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the VecDeque - --> $DIR/into_iter_on_ref.rs:32:39 + --> $DIR/into_iter_on_ref.rs:34:39 | LL | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the VecDeque - --> $DIR/into_iter_on_ref.rs:33:43 + --> $DIR/into_iter_on_ref.rs:35:43 | LL | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the LinkedList - --> $DIR/into_iter_on_ref.rs:34:41 + --> $DIR/into_iter_on_ref.rs:36:41 | LL | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the LinkedList - --> $DIR/into_iter_on_ref.rs:35:45 + --> $DIR/into_iter_on_ref.rs:37:45 | LL | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the HashMap - --> $DIR/into_iter_on_ref.rs:36:43 + --> $DIR/into_iter_on_ref.rs:38:43 | LL | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter_mut() and will not move the HashMap - --> $DIR/into_iter_on_ref.rs:37:47 + --> $DIR/into_iter_on_ref.rs:39:47 | LL | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() | ^^^^^^^^^ help: call directly: `iter_mut` error: this .into_iter() call is equivalent to .iter() and will not move the BTreeSet - --> $DIR/into_iter_on_ref.rs:39:39 + --> $DIR/into_iter_on_ref.rs:41:39 | LL | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the BinaryHeap - --> $DIR/into_iter_on_ref.rs:40:41 + --> $DIR/into_iter_on_ref.rs:42:41 | LL | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the HashSet - --> $DIR/into_iter_on_ref.rs:41:38 + --> $DIR/into_iter_on_ref.rs:43:38 | LL | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the Path - --> $DIR/into_iter_on_ref.rs:42:43 + --> $DIR/into_iter_on_ref.rs:44:43 | LL | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` error: this .into_iter() call is equivalent to .iter() and will not move the PathBuf - --> $DIR/into_iter_on_ref.rs:43:47 + --> $DIR/into_iter_on_ref.rs:45:47 | LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` -- cgit 1.4.1-3-g733a5 From fb90fcb61062497a18f31799965750ddffde0443 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 12:57:13 +0100 Subject: Add run-rustfix to large_digit_groups --- tests/ui/large_digit_groups.fixed | 23 +++++++++++++++++++++++ tests/ui/large_digit_groups.rs | 5 +++-- tests/ui/large_digit_groups.stderr | 20 ++++++++++---------- 3 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 tests/ui/large_digit_groups.fixed diff --git a/tests/ui/large_digit_groups.fixed b/tests/ui/large_digit_groups.fixed new file mode 100644 index 00000000000..cf8b36a499b --- /dev/null +++ b/tests/ui/large_digit_groups.fixed @@ -0,0 +1,23 @@ +// run-rustfix +#[warn(clippy::large_digit_groups)] +#[allow(unused_variables)] +fn main() { + let good = ( + 0b1011_i64, + 0o1_234_u32, + 0x1_234_567, + 1_2345_6789, + 1234_f32, + 1_234.12_f32, + 1_234.123_f32, + 1.123_4_f32, + ); + let bad = ( + 0b11_0110_i64, + 0x0123_4567_8901_usize, + 123_456_f32, + 123_456.12_f32, + 123_456.123_45_f64, + 123_456.123_456_f64, + ); +} diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 76c3414bb02..5b9aa8c58d8 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,3 +1,4 @@ +// run-rustfix #[warn(clippy::large_digit_groups)] #[allow(unused_variables)] fn main() { @@ -16,7 +17,7 @@ fn main() { 0x1_23456_78901_usize, 1_23456_f32, 1_23456.12_f32, - 1_23456.12345_f32, - 1_23456.12345_6_f32, + 1_23456.12345_f64, + 1_23456.12345_6_f64, ); } diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index 45aef91069b..4b5d0bd1a9f 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -1,5 +1,5 @@ error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:15:9 + --> $DIR/large_digit_groups.rs:16:9 | LL | 0b1_10110_i64, | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -7,34 +7,34 @@ LL | 0b1_10110_i64, = note: `-D clippy::large-digit-groups` implied by `-D warnings` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:16:9 + --> $DIR/large_digit_groups.rs:17:9 | LL | 0x1_23456_78901_usize, | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:17:9 + --> $DIR/large_digit_groups.rs:18:9 | LL | 1_23456_f32, | ^^^^^^^^^^^ help: consider: `123_456_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:18:9 + --> $DIR/large_digit_groups.rs:19:9 | LL | 1_23456.12_f32, | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:19:9 + --> $DIR/large_digit_groups.rs:20:9 | -LL | 1_23456.12345_f32, - | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f32` +LL | 1_23456.12345_f64, + | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f64` error: digit groups should be smaller - --> $DIR/large_digit_groups.rs:20:9 + --> $DIR/large_digit_groups.rs:21:9 | -LL | 1_23456.12345_6_f32, - | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f32` +LL | 1_23456.12345_6_f64, + | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f64` error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From 9ff821a7e822cbc81d4370202bd1af08c2d18c63 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 13:10:25 +0100 Subject: Add run-rustfix to map_clone test --- tests/ui/map_clone.fixed | 11 +++++++++++ tests/ui/map_clone.rs | 2 ++ tests/ui/map_clone.stderr | 6 +++--- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 tests/ui/map_clone.fixed diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed new file mode 100644 index 00000000000..5c419488286 --- /dev/null +++ b/tests/ui/map_clone.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::iter_cloned_collect)] +#![allow(clippy::missing_docs_in_private_items)] + +fn main() { + let _: Vec = vec![5_i8; 6].iter().cloned().collect(); + let _: Vec = vec![String::new()].iter().cloned().collect(); + let _: Vec = vec![42, 43].iter().cloned().collect(); + let _: Option = Some(Box::new(16)).map(|b| *b); +} diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index a70cb2f6725..96a615ae54c 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,4 +1,6 @@ +// run-rustfix #![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::iter_cloned_collect)] #![allow(clippy::missing_docs_in_private_items)] fn main() { diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 56b1f67bac9..63889055aa0 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:5:22 + --> $DIR/map_clone.rs:7:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` @@ -7,13 +7,13 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:6:26 + --> $DIR/map_clone.rs:8:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:7:23 + --> $DIR/map_clone.rs:9:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` -- cgit 1.4.1-3-g733a5 From 95f2a9dbfcaaf8b319c2743ea641b785ff4c9d2e Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 13:55:26 +0100 Subject: Add run-rustfix to mem_replace test --- tests/ui/mem_replace.fixed | 21 +++++++++++++++++++++ tests/ui/mem_replace.rs | 2 ++ tests/ui/mem_replace.stderr | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/ui/mem_replace.fixed diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed new file mode 100644 index 00000000000..4e47ac95d82 --- /dev/null +++ b/tests/ui/mem_replace.fixed @@ -0,0 +1,21 @@ +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +#![allow(unused_imports)] +#![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] + +use std::mem; + +fn main() { + let mut an_option = Some(1); + let _ = an_option.take(); + let an_option = &mut Some(1); + let _ = an_option.take(); +} diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index a0c340bb54b..6824ab18e7f 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix +#![allow(unused_imports)] #![warn(clippy::all, clippy::style, clippy::mem_replace_option_with_none)] use std::mem; diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 9092fa2ea14..791c4d71dbf 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,5 +1,5 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:16:13 + --> $DIR/mem_replace.rs:18:13 | LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` @@ -7,7 +7,7 @@ LL | let _ = mem::replace(&mut an_option, None); = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:18:13 + --> $DIR/mem_replace.rs:20:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` -- cgit 1.4.1-3-g733a5 From 6f17635f94ebcc9e70b8355d1d26b542ec83b396 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 14:24:21 +0100 Subject: Add run-rustfix for precedence test --- tests/ui/precedence.fixed | 37 +++++++++++++++++++++++++++++++++++++ tests/ui/precedence.rs | 10 ++++++---- tests/ui/precedence.stderr | 18 +++++++++--------- 3 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 tests/ui/precedence.fixed diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed new file mode 100644 index 00000000000..0ec85bc47e7 --- /dev/null +++ b/tests/ui/precedence.fixed @@ -0,0 +1,37 @@ +// run-rustfix +#![warn(clippy::precedence)] +#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::identity_op)] +#![allow(clippy::eq_op)] + +macro_rules! trip { + ($a:expr) => { + match $a & 0b1111_1111u8 { + 0 => println!("a is zero ({})", $a), + _ => println!("a is {}", $a), + } + }; +} + +fn main() { + 1 << (2 + 3); + (1 + 2) << 3; + 4 >> (1 + 1); + (1 + 3) >> 2; + 1 ^ (1 - 1); + 3 | (2 - 1); + 3 & (5 - 2); + -(1i32.abs()); + -(1f32.abs()); + + // These should not trigger an error + let _ = (-1i32).abs(); + let _ = (-1f32).abs(); + let _ = -(1i32).abs(); + let _ = -(1f32).abs(); + let _ = -(1i32.abs()); + let _ = -(1f32.abs()); + + let b = 3; + trip!(b * 8); +} diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index e4f65b46ea0..4ef771c314f 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,10 +1,12 @@ -#[warn(clippy::precedence)] -#[allow(clippy::identity_op)] -#[allow(clippy::eq_op)] +// run-rustfix +#![warn(clippy::precedence)] +#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::identity_op)] +#![allow(clippy::eq_op)] macro_rules! trip { ($a:expr) => { - match $a & 0b1111_1111i8 { + match $a & 0b1111_1111u8 { 0 => println!("a is zero ({})", $a), _ => println!("a is {}", $a), } diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 01c59a5b8ea..a2ed5392bfc 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -1,5 +1,5 @@ error: operator precedence can trip the unwary - --> $DIR/precedence.rs:15:5 + --> $DIR/precedence.rs:17:5 | LL | 1 << 2 + 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `1 << (2 + 3)` @@ -7,49 +7,49 @@ LL | 1 << 2 + 3; = note: `-D clippy::precedence` implied by `-D warnings` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:16:5 + --> $DIR/precedence.rs:18:5 | LL | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:17:5 + --> $DIR/precedence.rs:19:5 | LL | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:18:5 + --> $DIR/precedence.rs:20:5 | LL | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:19:5 + --> $DIR/precedence.rs:21:5 | LL | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:20:5 + --> $DIR/precedence.rs:22:5 | LL | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence can trip the unwary - --> $DIR/precedence.rs:21:5 + --> $DIR/precedence.rs:23:5 | LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:22:5 + --> $DIR/precedence.rs:24:5 | LL | -1i32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` error: unary minus has lower precedence than method call - --> $DIR/precedence.rs:23:5 + --> $DIR/precedence.rs:25:5 | LL | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` -- cgit 1.4.1-3-g733a5 From 79203653d17ae9abcd6ee3af7ce97fded41d6b8d Mon Sep 17 00:00:00 2001 From: roblabla Date: Sun, 13 Jan 2019 16:09:58 +0000 Subject: Missing docs: don't require documenting Global Asm items. global_asm! items cannot be documented, the lint still gets triggered after adding documentation to the macro invocation. Furthermore, even if we could add documentation to the AST node, rustdoc doesn't render it anyways. Playground example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=5182df182f0ffbbab4c3107e43368ac3 --- clippy_lints/src/missing_doc.rs | 2 +- tests/ui/missing-doc.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 7b56609e493..22084bd12cb 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -133,12 +133,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Struct(..) => "a struct", hir::ItemKind::Trait(..) => "a trait", hir::ItemKind::TraitAlias(..) => "a trait alias", - hir::ItemKind::GlobalAsm(..) => "an assembly blob", hir::ItemKind::Ty(..) => "a type alias", hir::ItemKind::Union(..) => "a union", hir::ItemKind::Existential(..) => "an existential type", hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod(..) + | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) => return, }; diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing-doc.rs index cb311dfb361..e65bce8e783 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing-doc.rs @@ -2,7 +2,7 @@ // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. #![allow(dead_code)] -#![feature(associated_type_defaults)] +#![feature(associated_type_defaults, global_asm)] //! Some garbage docs for the crate here #![doc = "More garbage"] @@ -176,3 +176,6 @@ pub mod public_interface { } fn main() {} + +// Ensure global asm doesn't require documentation. +global_asm! { "" } -- cgit 1.4.1-3-g733a5 From aa1793e9c49733f4241d075dd08fb55e948d53e0 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 18:48:54 +0100 Subject: Add run-rustfix to redundant_field_names --- tests/ui/redundant_field_names.fixed | 71 ++++++++++++++++++++++++++++++++++++ tests/ui/redundant_field_names.rs | 4 +- 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/ui/redundant_field_names.fixed diff --git a/tests/ui/redundant_field_names.fixed b/tests/ui/redundant_field_names.fixed new file mode 100644 index 00000000000..5b4b8eeedd4 --- /dev/null +++ b/tests/ui/redundant_field_names.fixed @@ -0,0 +1,71 @@ +// run-rustfix +#![warn(clippy::redundant_field_names)] +#![allow(clippy::no_effect, dead_code, unused_variables)] + +#[macro_use] +extern crate derive_new; + +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; + +mod foo { + pub const BAR: u8 = 0; +} + +struct Person { + gender: u8, + age: u8, + name: u8, + buzz: u64, + foo: u8, +} + +#[derive(new)] +pub struct S { + v: String, +} + +fn main() { + let gender: u8 = 42; + let age = 0; + let fizz: u64 = 0; + let name: u8 = 0; + + let me = Person { + gender, + age, + + name, //should be ok + buzz: fizz, //should be ok + foo: foo::BAR, //should be ok + }; + + // Range expressions + let (start, end) = (0, 0); + + let _ = start..; + let _ = ..end; + let _ = start..end; + + let _ = ..=end; + let _ = start..=end; + + // Issue #2799 + let _: Vec<_> = (start..end).collect(); + + // hand-written Range family structs are linted + let _ = RangeFrom { start }; + let _ = RangeTo { end }; + let _ = Range { start, end }; + let _ = RangeInclusive::new(start, end); + let _ = RangeToInclusive { end }; +} + +fn issue_3476() { + fn foo() {} + + struct S { + foo: fn(), + } + + S { foo: foo:: }; +} diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index f5c3fa66224..3f97b80c568 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,6 +1,6 @@ +// run-rustfix #![warn(clippy::redundant_field_names)] -#![allow(unused_variables)] -#![feature(inclusive_range, inclusive_range_fields, inclusive_range_methods)] +#![allow(clippy::no_effect, dead_code, unused_variables)] #[macro_use] extern crate derive_new; -- cgit 1.4.1-3-g733a5 From 2d11a440ddff7922656a52af461045187251fb6d Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 19:38:43 +0100 Subject: Add run-rustfix to replace_const test --- tests/ui/replace_consts.fixed | 100 +++++++++++++++++++++++++++++++++++++++++ tests/ui/replace_consts.rs | 3 +- tests/ui/replace_consts.stderr | 72 ++++++++++++++--------------- 3 files changed, 138 insertions(+), 37 deletions(-) create mode 100644 tests/ui/replace_consts.fixed diff --git a/tests/ui/replace_consts.fixed b/tests/ui/replace_consts.fixed new file mode 100644 index 00000000000..96a1281e478 --- /dev/null +++ b/tests/ui/replace_consts.fixed @@ -0,0 +1,100 @@ +// run-rustfix +#![feature(integer_atomics)] +#![allow(unused_variables, clippy::blacklisted_name)] +#![deny(clippy::replace_consts)] + +use std::sync::atomic::*; +use std::sync::{Once, ONCE_INIT}; + +#[rustfmt::skip] +fn bad() { + // Once + { let foo = ONCE_INIT; }; + // Atomic + { let foo = AtomicBool::new(false); }; + { let foo = AtomicIsize::new(0); }; + { let foo = AtomicI8::new(0); }; + { let foo = AtomicI16::new(0); }; + { let foo = AtomicI32::new(0); }; + { let foo = AtomicI64::new(0); }; + { let foo = AtomicUsize::new(0); }; + { let foo = AtomicU8::new(0); }; + { let foo = AtomicU16::new(0); }; + { let foo = AtomicU32::new(0); }; + { let foo = AtomicU64::new(0); }; + // Min + { let foo = isize::min_value(); }; + { let foo = i8::min_value(); }; + { let foo = i16::min_value(); }; + { let foo = i32::min_value(); }; + { let foo = i64::min_value(); }; + { let foo = i128::min_value(); }; + { let foo = usize::min_value(); }; + { let foo = u8::min_value(); }; + { let foo = u16::min_value(); }; + { let foo = u32::min_value(); }; + { let foo = u64::min_value(); }; + { let foo = u128::min_value(); }; + // Max + { let foo = isize::max_value(); }; + { let foo = i8::max_value(); }; + { let foo = i16::max_value(); }; + { let foo = i32::max_value(); }; + { let foo = i64::max_value(); }; + { let foo = i128::max_value(); }; + { let foo = usize::max_value(); }; + { let foo = u8::max_value(); }; + { let foo = u16::max_value(); }; + { let foo = u32::max_value(); }; + { let foo = u64::max_value(); }; + { let foo = u128::max_value(); }; +} + +#[rustfmt::skip] +fn good() { + // Once + { let foo = Once::new(); }; + // Atomic + { let foo = AtomicBool::new(false); }; + { let foo = AtomicIsize::new(0); }; + { let foo = AtomicI8::new(0); }; + { let foo = AtomicI16::new(0); }; + { let foo = AtomicI32::new(0); }; + { let foo = AtomicI64::new(0); }; + { let foo = AtomicUsize::new(0); }; + { let foo = AtomicU8::new(0); }; + { let foo = AtomicU16::new(0); }; + { let foo = AtomicU32::new(0); }; + { let foo = AtomicU64::new(0); }; + // Min + { let foo = isize::min_value(); }; + { let foo = i8::min_value(); }; + { let foo = i16::min_value(); }; + { let foo = i32::min_value(); }; + { let foo = i64::min_value(); }; + { let foo = i128::min_value(); }; + { let foo = usize::min_value(); }; + { let foo = u8::min_value(); }; + { let foo = u16::min_value(); }; + { let foo = u32::min_value(); }; + { let foo = u64::min_value(); }; + { let foo = u128::min_value(); }; + // Max + { let foo = isize::max_value(); }; + { let foo = i8::max_value(); }; + { let foo = i16::max_value(); }; + { let foo = i32::max_value(); }; + { let foo = i64::max_value(); }; + { let foo = i128::max_value(); }; + { let foo = usize::max_value(); }; + { let foo = u8::max_value(); }; + { let foo = u16::max_value(); }; + { let foo = u32::max_value(); }; + { let foo = u64::max_value(); }; + { let foo = u128::max_value(); }; +} + +fn main() { + bad(); + good(); +} diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index 225d9bcbc0f..b61293cc6e9 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -1,5 +1,6 @@ +// run-rustfix #![feature(integer_atomics)] -#![allow(clippy::blacklisted_name)] +#![allow(unused_variables, clippy::blacklisted_name)] #![deny(clippy::replace_consts)] use std::sync::atomic::*; diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index a2887fd4aad..6f2155406cd 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,215 +1,215 @@ error: using `ATOMIC_BOOL_INIT` - --> $DIR/replace_consts.rs:13:17 + --> $DIR/replace_consts.rs:14:17 | LL | { let foo = ATOMIC_BOOL_INIT; }; | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` | note: lint level defined here - --> $DIR/replace_consts.rs:3:9 + --> $DIR/replace_consts.rs:4:9 | LL | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:14:17 + --> $DIR/replace_consts.rs:15:17 | LL | { let foo = ATOMIC_ISIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:15:17 + --> $DIR/replace_consts.rs:16:17 | LL | { let foo = ATOMIC_I8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:16:17 + --> $DIR/replace_consts.rs:17:17 | LL | { let foo = ATOMIC_I16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:17:17 + --> $DIR/replace_consts.rs:18:17 | LL | { let foo = ATOMIC_I32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:18:17 + --> $DIR/replace_consts.rs:19:17 | LL | { let foo = ATOMIC_I64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:19:17 + --> $DIR/replace_consts.rs:20:17 | LL | { let foo = ATOMIC_USIZE_INIT; }; | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:20:17 + --> $DIR/replace_consts.rs:21:17 | LL | { let foo = ATOMIC_U8_INIT; }; | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:21:17 + --> $DIR/replace_consts.rs:22:17 | LL | { let foo = ATOMIC_U16_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:22:17 + --> $DIR/replace_consts.rs:23:17 | LL | { let foo = ATOMIC_U32_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:23:17 + --> $DIR/replace_consts.rs:24:17 | LL | { let foo = ATOMIC_U64_INIT; }; | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` error: using `MIN` - --> $DIR/replace_consts.rs:25:17 + --> $DIR/replace_consts.rs:26:17 | LL | { let foo = std::isize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:26:17 + --> $DIR/replace_consts.rs:27:17 | LL | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:28:17 | LL | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:29:17 | LL | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:30:17 | LL | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:31:17 | LL | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:32:17 | LL | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:33:17 | LL | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:34:17 | LL | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:35:17 | LL | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:36:17 | LL | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:37:17 | LL | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:38:17 + --> $DIR/replace_consts.rs:39:17 | LL | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:40:17 | LL | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:41:17 | LL | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:42:17 | LL | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:43:17 | LL | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:44:17 | LL | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:45:17 | LL | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:46:17 | LL | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:47:17 | LL | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:48:17 | LL | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:49:17 | LL | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:50:17 | LL | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` -- cgit 1.4.1-3-g733a5 From d3c452265fa55fdd5b5ed492fb28e84f5a4bb8da Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 19:40:14 +0100 Subject: Add run-rustfix to starts_ends_with --- tests/ui/starts_ends_with.fixed | 46 ++++++++++++++++++++++++++++++++++++++++ tests/ui/starts_ends_with.rs | 3 ++- tests/ui/starts_ends_with.stderr | 24 ++++++++++----------- 3 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 tests/ui/starts_ends_with.fixed diff --git a/tests/ui/starts_ends_with.fixed b/tests/ui/starts_ends_with.fixed new file mode 100644 index 00000000000..7dfcf9c91e4 --- /dev/null +++ b/tests/ui/starts_ends_with.fixed @@ -0,0 +1,46 @@ +// run-rustfix +#![allow(dead_code, unused_must_use)] + +fn main() {} + +#[allow(clippy::unnecessary_operation)] +fn starts_with() { + "".starts_with(' '); + !"".starts_with(' '); +} + +fn chars_cmp_with_unwrap() { + let s = String::from("foo"); + if s.starts_with('f') { + // s.starts_with('f') + // Nothing here + } + if s.ends_with('o') { + // s.ends_with('o') + // Nothing here + } + if s.ends_with('o') { + // s.ends_with('o') + // Nothing here + } + if !s.starts_with('f') { + // !s.starts_with('f') + // Nothing here + } + if !s.ends_with('o') { + // !s.ends_with('o') + // Nothing here + } + if !s.ends_with('o') { + // !s.ends_with('o') + // Nothing here + } +} + +#[allow(clippy::unnecessary_operation)] +fn ends_with() { + "".ends_with(' '); + !"".ends_with(' '); + "".ends_with(' '); + !"".ends_with(' '); +} diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index a94c8c336df..e48a4246354 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,4 +1,5 @@ -#![allow(dead_code)] +// run-rustfix +#![allow(dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index 0f95484da54..7c726d0e010 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -1,5 +1,5 @@ error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:7:5 + --> $DIR/starts_ends_with.rs:8:5 | LL | "".chars().next() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` @@ -7,19 +7,19 @@ LL | "".chars().next() == Some(' '); = note: `-D clippy::chars-next-cmp` implied by `-D warnings` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:8:5 + --> $DIR/starts_ends_with.rs:9:5 | LL | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:13:8 + --> $DIR/starts_ends_with.rs:14:8 | LL | if s.chars().next().unwrap() == 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:17:8 + --> $DIR/starts_ends_with.rs:18:8 | LL | if s.chars().next_back().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` @@ -27,49 +27,49 @@ LL | if s.chars().next_back().unwrap() == 'o' { = note: `-D clippy::chars-last-cmp` implied by `-D warnings` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:21:8 + --> $DIR/starts_ends_with.rs:22:8 | LL | if s.chars().last().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method - --> $DIR/starts_ends_with.rs:25:8 + --> $DIR/starts_ends_with.rs:26:8 | LL | if s.chars().next().unwrap() != 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:29:8 + --> $DIR/starts_ends_with.rs:30:8 | LL | if s.chars().next_back().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:33:8 + --> $DIR/starts_ends_with.rs:34:8 | LL | if s.chars().last().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:41:5 + --> $DIR/starts_ends_with.rs:42:5 | LL | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:42:5 + --> $DIR/starts_ends_with.rs:43:5 | LL | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:43:5 + --> $DIR/starts_ends_with.rs:44:5 | LL | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> $DIR/starts_ends_with.rs:44:5 + --> $DIR/starts_ends_with.rs:45:5 | LL | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` -- cgit 1.4.1-3-g733a5 From 67be42143a1c54c0050cc441b43b66c63652dcf3 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 19:57:19 +0100 Subject: Add run-rustfix for types test --- tests/ui/types.fixed | 14 ++++++++++++++ tests/ui/types.rs | 4 ++++ tests/ui/types.stderr | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/ui/types.fixed diff --git a/tests/ui/types.fixed b/tests/ui/types.fixed new file mode 100644 index 00000000000..a71a9ec8124 --- /dev/null +++ b/tests/ui/types.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + +// should not warn on lossy casting in constant types +// because not supported yet +const C: i32 = 42; +const C_I64: i64 = C as i64; + +fn main() { + // should suggest i64::from(c) + let c: i32 = 42; + let c_i64: i64 = i64::from(c); +} diff --git a/tests/ui/types.rs b/tests/ui/types.rs index 45846d6eef8..6f48080cedd 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -1,3 +1,7 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + // should not warn on lossy casting in constant types // because not supported yet const C: i32 = 42; diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr index 97cce7add03..f85e27a24ec 100644 --- a/tests/ui/types.stderr +++ b/tests/ui/types.stderr @@ -1,5 +1,5 @@ error: casting i32 to i64 may become silently lossy if types change - --> $DIR/types.rs:9:22 + --> $DIR/types.rs:13:22 | LL | let c_i64: i64 = c as i64; | ^^^^^^^^ help: try: `i64::from(c)` -- cgit 1.4.1-3-g733a5 From c325137d086e76bbe658ad9ebe44979743b03264 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 19:59:00 +0100 Subject: Add run-rustfix to unit_arg test --- tests/ui/unit_arg.fixed | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/ui/unit_arg.rs | 3 ++- tests/ui/unit_arg.stderr | 12 +++++------ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/ui/unit_arg.fixed diff --git a/tests/ui/unit_arg.fixed b/tests/ui/unit_arg.fixed new file mode 100644 index 00000000000..d8f3e854ca9 --- /dev/null +++ b/tests/ui/unit_arg.fixed @@ -0,0 +1,53 @@ +// run-rustfix +#![warn(clippy::unit_arg)] +#![allow(clippy::no_effect, unused_must_use)] + +use std::fmt::Debug; + +fn foo(t: T) { + println!("{:?}", t); +} + +fn foo3(t1: T1, t2: T2, t3: T3) { + println!("{:?}, {:?}, {:?}", t1, t2, t3); +} + +struct Bar; + +impl Bar { + fn bar(&self, t: T) { + println!("{:?}", t); + } +} + +fn bad() { + foo(()); + foo(()); + foo(()); + foo(()); + foo3((), 2, 2); + let b = Bar; + b.bar(()); +} + +fn ok() { + foo(()); + foo(1); + foo({ 1 }); + foo3("a", 3, vec![3]); + let b = Bar; + b.bar({ 1 }); + b.bar(()); + question_mark(); +} + +fn question_mark() -> Result<(), ()> { + Ok(Ok(())?)?; + Ok(Ok(()))??; + Ok(()) +} + +fn main() { + bad(); + ok(); +} diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 7e421a0d605..1403870eacf 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,5 +1,6 @@ +// run-rustfix #![warn(clippy::unit_arg)] -#![allow(clippy::no_effect)] +#![allow(clippy::no_effect, unused_must_use)] use std::fmt::Debug; diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 1da00b6f5e9..862534b18ec 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,5 +1,5 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:23:9 + --> $DIR/unit_arg.rs:24:9 | LL | foo({}); | ^^ @@ -11,7 +11,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:24:9 + --> $DIR/unit_arg.rs:25:9 | LL | foo({ | _________^ @@ -24,7 +24,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:27:9 + --> $DIR/unit_arg.rs:28:9 | LL | foo(foo(1)); | ^^^^^^ @@ -34,7 +34,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:28:9 + --> $DIR/unit_arg.rs:29:9 | LL | foo({ | _________^ @@ -48,7 +48,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:32:10 + --> $DIR/unit_arg.rs:33:10 | LL | foo3({}, 2, 2); | ^^ @@ -58,7 +58,7 @@ LL | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:34:11 + --> $DIR/unit_arg.rs:35:11 | LL | b.bar({ | ___________^ -- cgit 1.4.1-3-g733a5 From 51c0dd427b63faf6d3a3810ebd7942aae9a62065 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 13 Jan 2019 20:03:22 +0100 Subject: Add run-rustfix to unnecessary_fold --- tests/ui/unnecessary_fold.fixed | 44 ++++++++++++++++++++++++++++++++++++++++ tests/ui/unnecessary_fold.rs | 10 ++++++--- tests/ui/unnecessary_fold.stderr | 22 ++++++++++---------- 3 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 tests/ui/unnecessary_fold.fixed diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed new file mode 100644 index 00000000000..5f12d72a76a --- /dev/null +++ b/tests/ui/unnecessary_fold.fixed @@ -0,0 +1,44 @@ +// run-rustfix + +#![allow(dead_code)] + +/// Calls which should trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold() { + // Can be replaced by .any + let _ = (0..3).any(|x| x > 2); + // Can be replaced by .all + let _ = (0..3).all(|x| x > 2); + // Can be replaced by .sum + let _: i32 = (0..3).sum(); + // Can be replaced by .product + let _: i32 = (0..3).product(); +} + +/// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` +fn unnecessary_fold_span_for_multi_element_chain() { + let _: bool = (0..3).map(|x| 2 * x).any(|x| x > 2); +} + +/// Calls which should not trigger the `UNNECESSARY_FOLD` lint +fn unnecessary_fold_should_ignore() { + let _ = (0..3).fold(true, |acc, x| acc || x > 2); + let _ = (0..3).fold(false, |acc, x| acc && x > 2); + let _ = (0..3).fold(1, |acc, x| acc + x); + let _ = (0..3).fold(0, |acc, x| acc * x); + let _ = (0..3).fold(0, |acc, x| 1 + acc + x); + + // We only match against an accumulator on the left + // hand side. We could lint for .sum and .product when + // it's on the right, but don't for now (and this wouldn't + // be valid if we extended the lint to cover arbitrary numeric + // types). + let _ = (0..3).fold(false, |acc, x| x > 2 || acc); + let _ = (0..3).fold(true, |acc, x| x > 2 && acc); + let _ = (0..3).fold(0, |acc, x| x + acc); + let _ = (0..3).fold(1, |acc, x| x * acc); + + let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); + let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); +} + +fn main() {} diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 62198e21ef7..ae667d1ac06 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -1,3 +1,7 @@ +// run-rustfix + +#![allow(dead_code)] + /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any @@ -5,14 +9,14 @@ fn unnecessary_fold() { // Can be replaced by .all let _ = (0..3).fold(true, |acc, x| acc && x > 2); // Can be replaced by .sum - let _ = (0..3).fold(0, |acc, x| acc + x); + let _: i32 = (0..3).fold(0, |acc, x| acc + x); // Can be replaced by .product - let _ = (0..3).fold(1, |acc, x| acc * x); + let _: i32 = (0..3).fold(1, |acc, x| acc * x); } /// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` fn unnecessary_fold_span_for_multi_element_chain() { - let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); + let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); } /// Calls which should not trigger the `UNNECESSARY_FOLD` lint diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 07414b400c1..f9911d4a3dc 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -1,5 +1,5 @@ error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:4:19 + --> $DIR/unnecessary_fold.rs:8:19 | LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` @@ -7,28 +7,28 @@ LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); = note: `-D clippy::unnecessary-fold` implied by `-D warnings` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:6:19 + --> $DIR/unnecessary_fold.rs:10:19 | LL | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:8:19 + --> $DIR/unnecessary_fold.rs:12:24 | -LL | let _ = (0..3).fold(0, |acc, x| acc + x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` +LL | let _: i32 = (0..3).fold(0, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:10:19 + --> $DIR/unnecessary_fold.rs:14:24 | -LL | let _ = (0..3).fold(1, |acc, x| acc * x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` +LL | let _: i32 = (0..3).fold(1, |acc, x| acc * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:15:34 + --> $DIR/unnecessary_fold.rs:19:40 | -LL | let _ = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` +LL | let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 67a9f20c91fcb7281b46514bd866e353347a4416 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 15 Jan 2019 08:09:47 +0200 Subject: Fix `map_clone` bad suggestion `cloned` requires that the elements of the iterator must be references. This change determines if that is the case by examining the type of the closure argument and suggesting `.cloned` only if it is a reference. When the closure argument is not a reference, it suggests removing the `map` call instead. A minor problem with this change is that the new check sometimes overlaps with the `clone_on_copy` lint. Fixes #498 --- clippy_lints/src/map_clone.rs | 67 +++++++++++++++++++++++++++++-------------- tests/ui/map_clone.fixed | 12 ++++++++ tests/ui/map_clone.rs | 12 ++++++++ tests/ui/map_clone.stderr | 14 ++++++--- 4 files changed, 80 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 1546964e426..0fb0d8d690f 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -5,6 +5,7 @@ use crate::utils::{ use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; use syntax::ast::Ident; @@ -69,19 +70,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, _, name, None ) = inner.node { - lint(cx, e.span, args[0].span, name, closure_expr); + if ident_eq(name, closure_expr) { + lint(cx, e.span, args[0].span); + } }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => { match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => { - if !cx.tables.expr_ty(inner).is_box() { - lint(cx, e.span, args[0].span, name, inner); + if ident_eq(name, inner) && !cx.tables.expr_ty(inner).is_box() { + lint(cx, e.span, args[0].span); } }, hir::ExprKind::MethodCall(ref method, _, ref obj) => { - if method.ident.as_str() == "clone" + if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { - lint(cx, e.span, args[0].span, name, &obj[0]); + + let obj_ty = cx.tables.expr_ty(&obj[0]); + if let ty::Ref(..) = obj_ty.sty { + lint(cx, e.span, args[0].span); + } else { + lint_needless_cloning(cx, e.span, args[0].span); + } } }, _ => {}, @@ -94,22 +103,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) { +fn ident_eq(name: Ident, path: &hir::Expr) -> bool { if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node { - if path.segments.len() == 1 && path.segments[0].ident == name { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - MAP_CLONE, - replace, - "You are using an explicit closure for cloning elements", - "Consider calling the dedicated `cloned` method", - format!( - "{}.cloned()", - snippet_with_applicability(cx, root, "..", &mut applicability) - ), - applicability, - ) - } + path.segments.len() == 1 && path.segments[0].ident == name + } else { + false } } + +fn lint_needless_cloning(cx: &LateContext<'_, '_>, root: Span, receiver: Span) { + span_lint_and_sugg( + cx, + MAP_CLONE, + root.trim_start(receiver).unwrap(), + "You are needlessly cloning iterator elements", + "Remove the map call", + String::new(), + Applicability::MachineApplicable, + ) +} + +fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span) { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MAP_CLONE, + replace, + "You are using an explicit closure for cloning elements", + "Consider calling the dedicated `cloned` method", + format!( + "{}.cloned()", + snippet_with_applicability(cx, root, "..", &mut applicability) + ), + applicability, + ) +} diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index 5c419488286..aea8924073c 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::iter_cloned_collect)] +#![allow(clippy::clone_on_copy)] #![allow(clippy::missing_docs_in_private_items)] fn main() { @@ -8,4 +9,15 @@ fn main() { let _: Vec = vec![String::new()].iter().cloned().collect(); let _: Vec = vec![42, 43].iter().cloned().collect(); let _: Option = Some(Box::new(16)).map(|b| *b); + + // Don't lint these + let v = vec![5_i8; 6]; + let a = 0; + let b = &a; + let _ = v.iter().map(|_x| *b); + let _ = v.iter().map(|_x| a.clone()); + let _ = v.iter().map(|&_x| a); + + // Issue #496 + let _ = std::env::args(); } diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 96a615ae54c..e5560b34bb0 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::iter_cloned_collect)] +#![allow(clippy::clone_on_copy)] #![allow(clippy::missing_docs_in_private_items)] fn main() { @@ -8,4 +9,15 @@ fn main() { let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); let _: Option = Some(Box::new(16)).map(|b| *b); + + // Don't lint these + let v = vec![5_i8; 6]; + let a = 0; + let b = &a; + let _ = v.iter().map(|_x| *b); + let _ = v.iter().map(|_x| a.clone()); + let _ = v.iter().map(|&_x| a); + + // Issue #496 + let _ = std::env::args().map(|v| v.clone()); } diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 63889055aa0..504f4a01a4c 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:7:22 + --> $DIR/map_clone.rs:8:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` @@ -7,16 +7,22 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:8:26 + --> $DIR/map_clone.rs:9:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:9:23 + --> $DIR/map_clone.rs:10:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` -error: aborting due to 3 previous errors +error: You are needlessly cloning iterator elements + --> $DIR/map_clone.rs:22:29 + | +LL | let _ = std::env::args().map(|v| v.clone()); + | ^^^^^^^^^^^^^^^^^^^ help: Remove the map call + +error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From f96dc2e9e270da539ebd968203524e6141983643 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 15 Jan 2019 08:15:12 +0200 Subject: Remove `map_clone` fixed known problem --- clippy_lints/src/map_clone.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 0fb0d8d690f..4db0ca759db 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -19,9 +19,7 @@ pub struct Pass; /// /// **Why is this bad?** Readability, this can be written more concisely /// -/// **Known problems:** Sometimes `.cloned()` requires stricter trait -/// bound than `.map(|e| e.clone())` (which works because of the coercion). -/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498). +/// **Known problems:** None /// /// **Example:** /// -- cgit 1.4.1-3-g733a5 From f53f12b0c3d8cd619d657a50367d0f5fddf32548 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 15 Jan 2019 08:17:55 +0200 Subject: Fix issue number in `map_clone` test --- tests/ui/map_clone.fixed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index aea8924073c..af417815ed1 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -18,6 +18,6 @@ fn main() { let _ = v.iter().map(|_x| a.clone()); let _ = v.iter().map(|&_x| a); - // Issue #496 + // Issue #498 let _ = std::env::args(); } -- cgit 1.4.1-3-g733a5 From 89de4c9766eeecd791c789ef63aab9df4b9d906c Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 15 Jan 2019 08:36:56 +0200 Subject: Really fix issue number in `map_clone` test --- tests/ui/map_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index e5560b34bb0..7dd2ce30202 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -18,6 +18,6 @@ fn main() { let _ = v.iter().map(|_x| a.clone()); let _ = v.iter().map(|&_x| a); - // Issue #496 + // Issue #498 let _ = std::env::args().map(|v| v.clone()); } -- cgit 1.4.1-3-g733a5 From 8fba46aa275247b8cd2e5fcb08ba1fe0c3de745e Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 16 Jan 2019 15:27:43 -0500 Subject: add applicability to lint name suggestion --- clippy_lints/src/attrs.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index a3f2cc6a23b..693d6d487e2 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -332,9 +332,12 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { // https://github.com/rust-lang/rust/pull/56992 CheckLintNameResult::NoLint(None) => (), _ => { - db.span_suggestion(lint.span, - "lowercase the lint name", - name_lower); + db.span_suggestion_with_applicability( + lint.span, + "lowercase the lint name", + name_lower, + Applicability::MaybeIncorrect, + ); } } } -- cgit 1.4.1-3-g733a5 From e08c0954cc810069004aebe6ec9a4a21c7f5c534 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 17 Jan 2019 18:50:24 +0100 Subject: Remove bors.toml This file was only needed for bors-ng, but now we use the default rust-lang bors fork. --- bors.toml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 bors.toml diff --git a/bors.toml b/bors.toml deleted file mode 100644 index 4e6e85f45fe..00000000000 --- a/bors.toml +++ /dev/null @@ -1,4 +0,0 @@ -status = [ - "continuous-integration/travis-ci/push", - "continuous-integration/appveyor/branch" -] -- cgit 1.4.1-3-g733a5 From 8b81208012c2d88df74e18579a8025c24305db8c Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 17 Jan 2019 23:19:51 -0500 Subject: Adding a test for checking if test files are missing. --- tests/missing-test-files.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/missing-test-files.rs diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs new file mode 100644 index 00000000000..31d2dccff71 --- /dev/null +++ b/tests/missing-test-files.rs @@ -0,0 +1,47 @@ +use std::fs::{self, DirEntry}; +use std::io; +use std::path::Path; + +#[test] +fn test_missing_tests() { + explore_directory(Path::new("./tests")).unwrap(); +} + +/* +Test for missing files. + +Since rs files are alphabetically before stderr/stdout, we can sort by the full name +and iter in that order. If we've seen the file stem for the first time and it's not +a rust file, it means the rust file has to be missing. +*/ +fn explore_directory(dir: &Path) -> io::Result<()> { + let mut current_file = String::new(); + let mut files: Vec = fs::read_dir(dir)?.filter_map(Result::ok).collect(); + files.sort_by_key(|e| e.path()); + for entry in files.iter() { + let path = entry.path(); + if path.is_dir() { + explore_directory(&path)?; + } else { + let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string(); + match path.extension() { + Some(ext) => { + match ext.to_str().unwrap() { + "rs" => current_file = file_stem.clone(), + "stderr" | "stdout" => { + assert_eq!( + file_stem, + current_file, + "{}", + format!("Didn't see a test file for {:}", path.to_str().unwrap()) + ); + }, + _ => continue, + }; + }, + None => {}, + } + } + } + Ok(()) +} -- cgit 1.4.1-3-g733a5 From a3b3a54e930dec06935af37beae340a8f6a7b4ec Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 17 Jan 2019 23:50:30 -0500 Subject: Update to collect all the files then throw the error. --- tests/missing-test-files.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index 31d2dccff71..f79abedc062 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -1,10 +1,22 @@ use std::fs::{self, DirEntry}; -use std::io; use std::path::Path; #[test] fn test_missing_tests() { - explore_directory(Path::new("./tests")).unwrap(); + let missing_files = explore_directory(Path::new("./tests")); + if missing_files.len() > 0 { + assert!( + false, + format!( + "Didn't see a test file for the following files:\n\n{}\n", + missing_files + .iter() + .map(|s| format!("\t{}", s)) + .collect::>() + .join("\n") + ) + ); + } } /* @@ -14,14 +26,15 @@ Since rs files are alphabetically before stderr/stdout, we can sort by the full and iter in that order. If we've seen the file stem for the first time and it's not a rust file, it means the rust file has to be missing. */ -fn explore_directory(dir: &Path) -> io::Result<()> { +fn explore_directory(dir: &Path) -> Vec { + let mut missing_files: Vec = Vec::new(); let mut current_file = String::new(); - let mut files: Vec = fs::read_dir(dir)?.filter_map(Result::ok).collect(); + let mut files: Vec = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect(); files.sort_by_key(|e| e.path()); for entry in files.iter() { let path = entry.path(); if path.is_dir() { - explore_directory(&path)?; + missing_files.extend(explore_directory(&path)); } else { let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string(); match path.extension() { @@ -29,12 +42,9 @@ fn explore_directory(dir: &Path) -> io::Result<()> { match ext.to_str().unwrap() { "rs" => current_file = file_stem.clone(), "stderr" | "stdout" => { - assert_eq!( - file_stem, - current_file, - "{}", - format!("Didn't see a test file for {:}", path.to_str().unwrap()) - ); + if file_stem != current_file { + missing_files.push(path.to_str().unwrap().to_string()); + } }, _ => continue, }; @@ -43,5 +53,5 @@ fn explore_directory(dir: &Path) -> io::Result<()> { } } } - Ok(()) + missing_files } -- cgit 1.4.1-3-g733a5 From 38b3a4ec6309429a6ea4acced6dc2d5e1d745622 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 18 Jan 2019 00:12:35 -0500 Subject: Fixing issues pointed out by dogfood tests. --- tests/missing-test-files.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index f79abedc062..558e001d3d1 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -4,7 +4,7 @@ use std::path::Path; #[test] fn test_missing_tests() { let missing_files = explore_directory(Path::new("./tests")); - if missing_files.len() > 0 { + if !missing_files.is_empty() { assert!( false, format!( @@ -31,25 +31,22 @@ fn explore_directory(dir: &Path) -> Vec { let mut current_file = String::new(); let mut files: Vec = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect(); files.sort_by_key(|e| e.path()); - for entry in files.iter() { + for entry in &files { let path = entry.path(); if path.is_dir() { missing_files.extend(explore_directory(&path)); } else { let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string(); - match path.extension() { - Some(ext) => { - match ext.to_str().unwrap() { - "rs" => current_file = file_stem.clone(), - "stderr" | "stdout" => { - if file_stem != current_file { - missing_files.push(path.to_str().unwrap().to_string()); - } - }, - _ => continue, - }; - }, - None => {}, + if let Some(ext) = path.extension() { + match ext.to_str().unwrap() { + "rs" => current_file = file_stem.clone(), + "stderr" | "stdout" => { + if file_stem != current_file { + missing_files.push(path.to_str().unwrap().to_string()); + } + }, + _ => continue, + }; } } } -- cgit 1.4.1-3-g733a5 From de9c09e2bd8047c204acb6786d7f6c0d79911bc3 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 19 Jan 2019 09:27:45 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/57747 --- clippy_lints/src/open_options.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index e21225fbd29..fe572d86c1b 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -72,7 +72,7 @@ fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr, options: &mut Vec if let Spanned { node: LitKind::Bool(lit), .. - } = **span + } = *span { if lit { Argument::True -- cgit 1.4.1-3-g733a5 From a773276da35afc67a2c3cb8b6ec7123f3866e8a8 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 19 Jan 2019 11:36:27 +0200 Subject: Fix bad `while_let_on_iterator` suggestion. Don't suggest a `for` loop if the iterator is used inside the `while` loop. Closes #3670 --- clippy_lints/src/loops.rs | 14 ++++++++++++++ tests/ui/while_loop.rs | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d6430cf291b..acc7b11e346 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -565,6 +565,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { && lhs_constructor.ident.name == "Some" && (pat_args.is_empty() || !is_refutable(cx, &pat_args[0]) + && !is_used_inside(cx, iter_expr, &arms[0].body) && !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0])) { @@ -1888,6 +1889,19 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } } +fn is_used_inside<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr, container: &'tcx Expr) -> bool { + let def_id = match var_def_id(cx, expr) { + Some(id) => id, + None => return false, + }; + if let Some(used_mutably) = mutated_variables(container, cx) { + if used_mutably.contains(&def_id) { + return true; + } + } + false +} + fn is_iterator_used_after_while_let<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr) -> bool { let def_id = match var_def_id(cx, iter_expr) { Some(id) => id, diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 283a2d43c04..8c3bf1cc674 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -216,4 +216,14 @@ fn refutable() { while let Some(..) = values.iter().next() { values.remove(&1); } + + // Issue 3670 + { + let array = [Some(0), None, Some(1)]; + let mut iter = array.iter(); + + while let Some(elem) = iter.next() { + let _ = elem.or_else(|| *iter.next()?); + } + } } -- cgit 1.4.1-3-g733a5 From 2ee713dc7bcc8e9bb7223b49451ec6ac9685f4c6 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sat, 19 Jan 2019 21:13:06 +0900 Subject: Catch up with `format_args` change Catches up with a change in rust-lang/rust#57537 Happened to fix a bug in `expect_fun_call`, that is the lint ignores more than one arguments to `format`. --- clippy_lints/src/format.rs | 11 ++++++++--- clippy_lints/src/methods/mod.rs | 27 +++++++++++++-------------- clippy_lints/src/utils/paths.rs | 1 + tests/ui/expect_fun_call.rs | 2 ++ tests/ui/expect_fun_call.stderr | 8 +++++++- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 57c21bee722..90e19af15d0 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -53,12 +53,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ExprKind::Call(ref fun, ref args) => { if_chain! { if let ExprKind::Path(ref qpath) = fun.node; - if args.len() == 3; if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)); - if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED); + let new_v1 = match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1); + let new_v1_fmt = match_def_path( + cx.tcx, + fun_def_id, + &paths::FMT_ARGUMENTS_NEWV1FORMATTED + ); + if new_v1 || new_v1_fmt; if check_single_piece(&args[0]); if let Some(format_arg) = get_single_string_arg(cx, &args[1]); - if check_unformatted(&args[2]); + if new_v1 || check_unformatted(&args[2]); if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node; then { let (message, sugg) = if_chain! { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 41011e8f66a..14fdd6e6225 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1148,7 +1148,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { - fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec> { + fn extract_format_args(arg: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr)> { let arg = match &arg.node { hir::ExprKind::AddrOf(_, expr) => expr, hir::ExprKind::MethodCall(method_name, _, args) @@ -1161,8 +1161,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg.node { if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { - if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node { - return Some(format_args); + if let hir::ExprKind::Call(_, format_args) = &inner_args[0].node { + return Some((&format_args[0], &format_args[1])); } } } @@ -1174,17 +1174,19 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: cx: &LateContext<'_, '_>, a: &hir::Expr, applicability: &mut Applicability, - ) -> String { + ) -> Vec { if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node { if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node { if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node { - return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability) - .into_owned(); + return format_arg_expr_tup + .iter() + .map(|a| snippet_with_applicability(cx, a.span, "..", applicability).into_owned()) + .collect(); } } }; - snippet(cx, a.span, "..").into_owned() + unreachable!() } fn check_general_case( @@ -1233,14 +1235,11 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: }; let span_replace_word = method_span.with_hi(span.hi()); - if let Some(format_args) = extract_format_args(arg) { + if let Some((fmt_spec, fmt_args)) = extract_format_args(arg) { let mut applicability = Applicability::MachineApplicable; - let args_len = format_args.len(); - let args: Vec = format_args - .into_iter() - .take(args_len - 1) - .map(|a| generate_format_arg_snippet(cx, a, &mut applicability)) - .collect(); + let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()]; + + args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability)); let sugg = args.join(", "); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index a74e457a9fd..d2dc2812575 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -26,6 +26,7 @@ pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleE pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; +pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 0f930f6a8a2..7f0ca0fe809 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -57,6 +57,8 @@ fn expect_fun_call() { Some("foo").expect({ &format!("error") }); Some("foo").expect(format!("error").as_ref()); + + Some("foo").expect(format!("{} {}", 1, 2).as_ref()); } fn main() {} diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 09844e29911..a60bd7e4ed3 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -36,5 +36,11 @@ error: use of `expect` followed by a function call LL | Some("foo").expect(format!("error").as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` -error: aborting due to 6 previous errors +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:61:17 + | +LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 77b71a1af2eb1b8370305f967f53597faf279d76 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 20 Jan 2019 10:14:23 +0200 Subject: Fix breakage due to rust-lang/rust#57755 --- clippy_lints/src/write.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index bb62cdeb9ed..c8c291c8cc8 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -5,7 +5,7 @@ use rustc_errors::Applicability; use std::borrow::Cow; use syntax::ast::*; use syntax::parse::{parser, token}; -use syntax::tokenstream::{ThinTokenStream, TokenStream}; +use syntax::tokenstream::TokenStream; /// **What it does:** This lint warns when you use `println!("")` to /// print a newline. @@ -261,9 +261,9 @@ impl EarlyLintPass for Pass { /// ```rust,ignore /// (Some("string to write: {}"), Some(buf)) /// ``` -fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option, Option) { +fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { use fmt_macros::*; - let tts = TokenStream::from(tts.clone()); + let tts = tts.clone(); let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false); let mut expr: Option = None; if is_write { -- cgit 1.4.1-3-g733a5 From f51f0178dd5ba19c905d8b323dab2c43ded83b1e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 20 Jan 2019 12:21:30 +0200 Subject: Fixed breakage due to rust-lang/rust#57489 --- clippy_lints/src/attrs.rs | 5 +-- clippy_lints/src/escape.rs | 4 +-- clippy_lints/src/eval_order_dependence.rs | 24 ++++++-------- clippy_lints/src/let_if_seq.rs | 13 ++++---- clippy_lints/src/loops.rs | 34 +++++++------------ clippy_lints/src/map_unit_fn.rs | 9 +++--- clippy_lints/src/methods/mod.rs | 4 +-- clippy_lints/src/misc.rs | 5 ++- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 3 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/shadow.rs | 15 ++++----- clippy_lints/src/slow_vector_initialization.rs | 7 ++-- clippy_lints/src/swap.rs | 11 +++---- clippy_lints/src/types.rs | 44 ++++++++++++------------- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/utils/author.rs | 45 +++++++++++--------------- clippy_lints/src/utils/higher.rs | 22 +++++-------- clippy_lints/src/utils/hir_utils.rs | 41 +++++++++++------------ clippy_lints/src/utils/inspector.rs | 28 +++++++--------- tests/ui/author.stdout | 3 +- tests/ui/author/call.stdout | 3 +- tests/ui/author/for_loop.stdout | 12 +++---- 24 files changed, 141 insertions(+), 199 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 693d6d487e2..9e4dd52c414 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -376,8 +376,9 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool { fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { match &stmt.node { - StmtKind::Decl(_, _) => true, - StmtKind::Expr(expr, _) | StmtKind::Semi(expr, _) => is_relevant_expr(tcx, tables, expr), + StmtKind::Local(_) => true, + StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(tcx, tables, expr), + _ => false, } } else { block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 75020b14492..79af6305f44 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -120,8 +120,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if let Categorization::Rvalue(..) = cmt.cat { let id = map.hir_to_node_id(cmt.hir_id); if let Some(Node::Stmt(st)) = map.find(map.get_parent_node(id)) { - if let StmtKind::Decl(ref decl, _) = st.node { - if let DeclKind::Local(ref loc) = decl.node { + if let StmtKind::Local(ref loc) = st.node { if let Some(ref ex) = loc.init { if let ExprKind::Box(..) = ex.node { if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { @@ -136,7 +135,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } } - } if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { // let y = x where x is known diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 8bd8461b119..74fe4a6589b 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -89,14 +89,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { - StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e), - StmtKind::Decl(ref d, _) => { - if let DeclKind::Local(ref local) = d.node { + StmtKind::Local(ref local) => { if let Local { init: Some(ref e), .. } = **local { DivergenceVisitor { cx }.visit_expr(e); } - } }, + StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => DivergenceVisitor { cx }.maybe_walk_expr(e), + StmtKind::Item(..) => {}, } } } @@ -269,18 +268,13 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly { match stmt.node { - StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => check_expr(vis, expr), - StmtKind::Decl(ref decl, _) => { - // If the declaration is of a local variable, check its initializer - // expression if it has one. Otherwise, keep going. - let local = match decl.node { - DeclKind::Local(ref local) => Some(local), - _ => None, - }; - local - .and_then(|local| local.init.as_ref()) - .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => check_expr(vis, expr), + // If the declaration is of a local variable, check its initializer + // expression if it has one. Otherwise, keep going. + StmtKind::Local(ref local) => { + local.init.as_ref().map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) }, + _ => StopEarly::KeepGoing, } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index c3b3272dffd..5154c6d4d08 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -68,10 +68,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { while let Some(stmt) = it.next() { if_chain! { if let Some(expr) = it.peek(); - if let hir::StmtKind::Decl(ref decl, _) = stmt.node; - if let hir::DeclKind::Local(ref decl) = decl.node; - if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node; - if let hir::StmtKind::Expr(ref if_, _) = expr.node; + if let hir::StmtKind::Local(ref local) = stmt.node; + if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.node; + if let hir::StmtKind::Expr(ref if_) = expr.node; if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); if let hir::ExprKind::Block(ref then, _) = then.node; @@ -84,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if let hir::ExprKind::Block(ref else_, _) = else_.node { if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) - } else if let Some(ref default) = decl.init { + } else if let Some(ref default) = local.init { (true, &**default) } else { continue; @@ -92,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { } else { continue; } - } else if let Some(ref default) = decl.init { + } else if let Some(ref default) = local.init { (false, &**default) } else { continue; @@ -169,7 +168,7 @@ fn check_assign<'a, 'tcx>( if_chain! { if block.expr.is_none(); if let Some(expr) = block.stmts.iter().last(); - if let hir::StmtKind::Semi(ref expr, _) = expr.node; + if let hir::StmtKind::Semi(ref expr) = expr.node; if let hir::ExprKind::Assign(ref var, ref value) = expr.node; if let hir::ExprKind::Path(ref qpath) = var.node; if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index acc7b11e346..7d8b7d363b1 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use itertools::Itertools; use rustc::hir::def::Def; use rustc::hir::def_id; -use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; +use rustc::hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::middle::region; @@ -597,7 +597,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { - if let StmtKind::Semi(ref expr, _) = stmt.node { + if let StmtKind::Semi(ref expr) = stmt.node { if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) { span_lint( @@ -668,13 +668,7 @@ fn never_loop_block(block: &Block, main_loop_id: NodeId) -> NeverLoopResult { fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> { match stmt.node { StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e), - StmtKind::Decl(ref d, ..) => decl_to_expr(d), - } -} - -fn decl_to_expr(decl: &Decl) -> Option<&Expr> { - match decl.node { - DeclKind::Local(ref local) => local.init.as_ref().map(|p| &**p), + StmtKind::Local(ref local) => local.init.as_ref().map(|p| &**p), _ => None, } } @@ -942,8 +936,8 @@ fn get_indexed_assignments<'a, 'tcx>( stmts .iter() .map(|stmt| match stmt.node { - StmtKind::Decl(..) => None, - StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + StmtKind::Local(..) | StmtKind::Item(..) => None, + StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => Some(get_assignment(cx, e, var)), }) .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .filter_map(|op| op) @@ -1976,16 +1970,12 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { if block.stmts.is_empty() { return None; } - if let StmtKind::Decl(ref decl, _) = block.stmts[0].node { - if let DeclKind::Local(ref local) = decl.node { + if let StmtKind::Local(ref local) = block.stmts[0].node { if let Some(ref expr) = local.init { Some(expr) } else { None } - } else { - None - } } else { None } @@ -1996,8 +1986,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), None if !block.stmts.is_empty() => match block.stmts[0].node { - StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => Some(expr), - StmtKind::Decl(..) => None, + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => Some(expr), + StmtKind::Local(..) | StmtKind::Item(..) => None, }, _ => None, } @@ -2095,9 +2085,9 @@ struct InitializeVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { - fn visit_decl(&mut self, decl: &'tcx Decl) { + fn visit_stmt(&mut self, stmt: &'tcx Stmt) { // Look for declarations of the variable - if let DeclKind::Local(ref local) = decl.node { + if let StmtKind::Local(ref local) = stmt.node { if local.pat.id == self.var_id { if let PatKind::Binding(_, _, ident, _) = local.pat.node { self.name = Some(ident.name); @@ -2114,7 +2104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { } } } - walk_decl(self, decl); + walk_stmt(self, stmt); } fn visit_expr(&mut self, expr: &'tcx Expr) { @@ -2261,7 +2251,7 @@ struct LoopNestVisitor { impl<'tcx> Visitor<'tcx> for LoopNestVisitor { fn visit_stmt(&mut self, stmt: &'tcx Stmt) { - if stmt.node.id() == self.id { + if stmt.id == self.id { self.nesting = LookFurther; } else if self.nesting == Unknown { walk_stmt(self, stmt); diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 4b4f1ad5919..ad5761f5f04 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -131,9 +131,10 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> // If block only contains statements, // reduce `{ X; }` to `X` or `X;` match inner_stmt.node { - hir::StmtKind::Decl(ref d, _) => Some(d.span), - hir::StmtKind::Expr(ref e, _) => Some(e.span), - hir::StmtKind::Semi(_, _) => Some(inner_stmt.span), + hir::StmtKind::Local(ref local) => Some(local.span), + hir::StmtKind::Expr(ref e) => Some(e.span), + hir::StmtKind::Semi(..) => Some(inner_stmt.span), + hir::StmtKind::Item(..) => None, } }, _ => { @@ -250,7 +251,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } - if let hir::StmtKind::Semi(ref expr, _) = stmt.node { + if let hir::StmtKind::Semi(ref expr) = stmt.node { if let Some(arglists) = method_chain_args(expr, &["map"]) { lint_map_unit_fn(cx, stmt, expr, arglists[0]); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 14fdd6e6225..5883128d72c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1336,13 +1336,11 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp _ => {}, }, hir::Node::Stmt(stmt) => { - if let hir::StmtKind::Decl(ref decl, _) = stmt.node { - if let hir::DeclKind::Local(ref loc) = decl.node { + if let hir::StmtKind::Local(ref loc) = stmt.node { if let hir::PatKind::Ref(..) = loc.pat.node { // let ref y = *x borrows x, let ref y = x.clone() does not return; } - } } }, _ => {}, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 4e5910f76bb..88a6d62ee6d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -277,8 +277,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) { if_chain! { - if let StmtKind::Decl(ref d, _) = s.node; - if let DeclKind::Local(ref l) = d.node; + if let StmtKind::Local(ref l) = s.node; if let PatKind::Binding(an, _, i, None) = l.pat.node; if let Some(ref init) = l.init; then { @@ -316,7 +315,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }; if_chain! { - if let StmtKind::Semi(ref expr, _) = s.node; + if let StmtKind::Semi(ref expr) = s.node; if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node; if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; if let Some(sugg) = Sugg::hir_opt(cx, a); diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 1dfc3f6501e..6fbb0573365 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -267,7 +267,7 @@ fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), (&[ref e], None) => { - if let StmtKind::Semi(ref e, _) = e.node { + if let StmtKind::Semi(ref e) = e.node { if let ExprKind::Ret(_) = e.node { fetch_bool_expr(&**e) } else { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index b02faa08006..cb1fe475a1e 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -368,8 +368,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { Node::Stmt(s) => { // `let = x;` if_chain! { - if let StmtKind::Decl(ref decl, _) = s.node; - if let DeclKind::Local(ref local) = decl.node; + if let StmtKind::Local(ref local) = s.node; then { self.spans_need_deref .entry(vid) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 53d7575e3e0..648c198df08 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -104,7 +104,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { - if let StmtKind::Semi(ref expr, _) = stmt.node { + if let StmtKind::Semi(ref expr) = stmt.node { if has_no_effect(cx, expr) { span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); } else if let Some(reduced) = reduce_expression(cx, expr) { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index a4c4e66cf71..03f6ea12e00 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -139,7 +139,7 @@ impl Pass { if_chain! { if block.stmts.len() == 1; if let Some(expr) = block.stmts.iter().last(); - if let StmtKind::Semi(ref expr, _) = expr.node; + if let StmtKind::Semi(ref expr) = expr.node; if let ExprKind::Ret(ref ret_expr) = expr.node; if let &Some(ref ret_expr) = ret_expr; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 84dd339a985..153324094ec 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -115,8 +115,9 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding let len = bindings.len(); for stmt in &block.stmts { match stmt.node { - StmtKind::Decl(ref decl, _) => check_decl(cx, decl, bindings), - StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => check_expr(cx, e, bindings), + StmtKind::Local(ref local) => check_local(cx, local, bindings), + StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings), + StmtKind::Item(..) => {}, } } if let Some(ref o) = block.expr { @@ -125,21 +126,20 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding bindings.truncate(len); } -fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: &mut Vec<(Name, Span)>) { - if in_external_macro(cx.sess(), decl.span) { +fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, bindings: &mut Vec<(Name, Span)>) { + if in_external_macro(cx.sess(), local.span) { return; } - if higher::is_from_for_desugar(decl) { + if higher::is_from_for_desugar(local) { return; } - if let DeclKind::Local(ref local) = decl.node { let Local { ref pat, ref ty, ref init, span, .. - } = **local; + } = *local; if let Some(ref t) = *ty { check_ty(cx, t, bindings) } @@ -149,7 +149,6 @@ fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: } else { check_pat(cx, pat, None, span, bindings); } - } } fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 77f70fad588..aea414065d8 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -91,8 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` if_chain! { - if let StmtKind::Decl(ref decl, _) = stmt.node; - if let DeclKind::Local(ref local) = decl.node; + if let StmtKind::Local(ref local) = stmt.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, variable_name, None) = local.pat.node; if let Some(ref init) = local.init; if let Some(ref len_arg) = Self::is_vec_with_capacity(init); @@ -104,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { len_expr: len_arg, }; - Self::search_initialization(cx, vi, stmt.node.id()); + Self::search_initialization(cx, vi, stmt.id); } } } @@ -287,7 +286,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt) { if self.initialization_found { match stmt.node { - StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => { + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { self.search_slow_extend_filling(expr); self.search_slow_resize_filling(expr); }, diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 56f503afeae..ddf33fcc411 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -71,17 +71,16 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { for w in block.stmts.windows(3) { if_chain! { // let t = foo(); - if let StmtKind::Decl(ref tmp, _) = w[0].node; - if let DeclKind::Local(ref tmp) = tmp.node; + if let StmtKind::Local(ref tmp) = w[0].node; if let Some(ref tmp_init) = tmp.init; if let PatKind::Binding(_, _, ident, None) = tmp.pat.node; // foo() = bar(); - if let StmtKind::Semi(ref first, _) = w[1].node; + if let StmtKind::Semi(ref first) = w[1].node; if let ExprKind::Assign(ref lhs1, ref rhs1) = first.node; // bar() = t; - if let StmtKind::Semi(ref second, _) = w[2].node; + if let StmtKind::Semi(ref second) = w[2].node; if let ExprKind::Assign(ref lhs2, ref rhs2) = second.node; if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.node; if rhs2.segments.len() == 1; @@ -160,8 +159,8 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { for w in block.stmts.windows(2) { if_chain! { - if let StmtKind::Semi(ref first, _) = w[0].node; - if let StmtKind::Semi(ref second, _) = w[1].node; + if let StmtKind::Semi(ref first) = w[0].node; + if let StmtKind::Semi(ref second) = w[1].node; if !differing_macro_contexts(first.span, second.span); if let ExprKind::Assign(ref lhs0, ref rhs0) = first.node; if let ExprKind::Assign(ref lhs1, ref rhs1) = second.node; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f4b75437ff6..898fd5a9808 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -463,28 +463,6 @@ declare_clippy_lint! { "creating a let binding to a value of unit type, which usually can't be used afterwards" } -fn check_let_unit(cx: &LateContext<'_, '_>, decl: &Decl) { - if let DeclKind::Local(ref local) = decl.node { - if is_unit(cx.tables.pat_ty(&local.pat)) { - if in_external_macro(cx.sess(), decl.span) || in_macro(local.pat.span) { - return; - } - if higher::is_from_for_desugar(decl) { - return; - } - span_lint( - cx, - LET_UNIT_VALUE, - decl.span, - &format!( - "this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, "..") - ), - ); - } - } -} - impl LintPass for LetPass { fn get_lints(&self) -> LintArray { lint_array!(LET_UNIT_VALUE) @@ -492,8 +470,26 @@ impl LintPass for LetPass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass { - fn check_decl(&mut self, cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl) { - check_let_unit(cx, decl) + fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { + if let StmtKind::Local(ref local) = stmt.node { + if is_unit(cx.tables.pat_ty(&local.pat)) { + if in_external_macro(cx.sess(), stmt.span) || in_macro(local.pat.span) { + return; + } + if higher::is_from_for_desugar(local) { + return; + } + span_lint( + cx, + LET_UNIT_VALUE, + stmt.span, + &format!( + "this let-binding has unit value. Consider omitting `let {} =`", + snippet(cx, local.pat.span, "..") + ), + ); + } + } } } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index c33b6b742fa..27deb0d9945 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -41,7 +41,7 @@ impl LintPass for UnusedIoAmount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { let expr = match s.node { - hir::StmtKind::Semi(ref expr, _) | hir::StmtKind::Expr(ref expr, _) => &**expr, + hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr, _ => return, }; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 51e7d333084..36eac00b54b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -4,7 +4,7 @@ use crate::utils::get_attr; use rustc::hir; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; +use rustc::hir::{BindingAnnotation, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_data_structures::fx::FxHashMap; @@ -625,35 +625,26 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { print!(" if let StmtKind::"); let current = format!("{}.node", self.current); match s.node { - // Could be an item or a local (let) binding: - StmtKind::Decl(ref decl, _) => { - let decl_pat = self.next("decl"); - println!("Decl(ref {}, _) = {}", decl_pat, current); - print!(" if let DeclKind::"); - let current = format!("{}.node", decl_pat); - match decl.node { - // A local (let) binding: - DeclKind::Local(ref local) => { - let local_pat = self.next("local"); - println!("Local(ref {}) = {};", local_pat, current); - if let Some(ref init) = local.init { - let init_pat = self.next("init"); - println!(" if let Some(ref {}) = {}.init", init_pat, local_pat); - self.current = init_pat; - self.visit_expr(init); - } - self.current = format!("{}.pat", local_pat); - self.visit_pat(&local.pat); - }, - // An item binding: - DeclKind::Item(_) => { - println!("Item(item_id) = {};", current); - }, + // A local (let) binding: + StmtKind::Local(ref local) => { + let local_pat = self.next("local"); + println!("Local(ref {}) = {};", local_pat, current); + if let Some(ref init) = local.init { + let init_pat = self.next("init"); + println!(" if let Some(ref {}) = {}.init", init_pat, local_pat); + self.current = init_pat; + self.visit_expr(init); } + self.current = format!("{}.pat", local_pat); + self.visit_pat(&local.pat); + }, + // An item binding: + StmtKind::Item(_) => { + println!("Item(item_id) = {};", current); }, // Expr without trailing semi-colon (must have unit type): - StmtKind::Expr(ref e, _) => { + StmtKind::Expr(ref e) => { let e_pat = self.next("e"); println!("Expr(ref {}, _) = {}", e_pat, current); self.current = e_pat; @@ -661,7 +652,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, // Expr with trailing semi-colon (may have any type): - StmtKind::Semi(ref e, _) => { + StmtKind::Semi(ref e) => { let e_pat = self.next("e"); println!("Semi(ref {}, _) = {}", e_pat, current); self.current = e_pat; diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 682093b08e4..537cdf55eb1 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -148,8 +148,8 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O } } -/// Checks if a `let` decl is from a `for` loop desugaring. -pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { +/// Checks if a `let` statement is from a `for` loop desugaring. +pub fn is_from_for_desugar(local: &hir::Local) -> bool { // This will detect plain for-loops without an actual variable binding: // // ``` @@ -158,8 +158,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // } // ``` if_chain! { - if let hir::DeclKind::Local(ref loc) = decl.node; - if let Some(ref expr) = loc.init; + if let Some(ref expr) = local.init; if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.node; then { return true; @@ -174,12 +173,8 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { // // anything // } // ``` - if_chain! { - if let hir::DeclKind::Local(ref loc) = decl.node; - if let hir::LocalSource::ForLoopDesugar = loc.source; - then { - return true; - } + if let hir::LocalSource::ForLoopDesugar = local.source { + return true; } false @@ -195,11 +190,10 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> if let hir::ExprKind::Loop(ref block, _, _) = arms[0].body.node; if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; - if let hir::StmtKind::Decl(ref decl, _) = let_stmt.node; - if let hir::DeclKind::Local(ref decl) = decl.node; - if let hir::StmtKind::Expr(ref expr, _) = body.node; + if let hir::StmtKind::Local(ref local) = let_stmt.node; + if let hir::StmtKind::Expr(ref expr) = body.node; then { - return Some((&*decl.pat, &iterargs[0], expr)); + return Some((&*local.pat, &iterargs[0], expr)); } } None diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index aed9bb9afc9..aae4eb24964 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -43,17 +43,13 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two statements are the same. pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { match (&left.node, &right.node) { - (&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => { - if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) { - self.eq_pat(&l.pat, &r.pat) - && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) - && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) - } else { - false - } - }, - (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _)) - | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => self.eq_expr(l, r), + (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => + self.eq_pat(&l.pat, &r.pat) + && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) + && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + , + (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) + | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => self.eq_expr(l, r), _ => false, } } @@ -643,23 +639,24 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { pub fn hash_stmt(&mut self, b: &Stmt) { match b.node { - StmtKind::Decl(ref decl, _) => { - let c: fn(_, _) -> _ = StmtKind::Decl; + StmtKind::Local(ref local) => { + let c: fn(_) -> _ = StmtKind::Local; c.hash(&mut self.s); - - if let DeclKind::Local(ref local) = decl.node { - if let Some(ref init) = local.init { - self.hash_expr(init); - } + if let Some(ref init) = local.init { + self.hash_expr(init); } }, - StmtKind::Expr(ref expr, _) => { - let c: fn(_, _) -> _ = StmtKind::Expr; + StmtKind::Item(..) => { + let c: fn(_) -> _ = StmtKind::Item; + c.hash(&mut self.s); + } + StmtKind::Expr(ref expr) => { + let c: fn(_) -> _ = StmtKind::Expr; c.hash(&mut self.s); self.hash_expr(expr); }, - StmtKind::Semi(ref expr, _) => { - let c: fn(_, _) -> _ = StmtKind::Semi; + StmtKind::Semi(ref expr) => { + let c: fn(_) -> _ = StmtKind::Semi; c.hash(&mut self.s); self.hash_expr(expr); }, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 6ce27c18cec..235b2adc62e 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -122,8 +122,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } match stmt.node { - hir::StmtKind::Decl(ref decl, _) => print_decl(cx, decl), - hir::StmtKind::Expr(ref e, _) | hir::StmtKind::Semi(ref e, _) => print_expr(cx, e, 0), + hir::StmtKind::Local(ref local) => { + println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); + println!("pattern:"); + print_pat(cx, &local.pat, 0); + if let Some(ref e) = local.init { + println!("init expression:"); + print_expr(cx, e, 0); + } + } + hir::StmtKind::Item(_) => println!("item decl"), + hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0), } } // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx @@ -139,21 +148,6 @@ fn has_attr(attrs: &[Attribute]) -> bool { get_attr(attrs, "dump").count() > 0 } -fn print_decl(cx: &LateContext<'_, '_>, decl: &hir::Decl) { - match decl.node { - hir::DeclKind::Local(ref local) => { - println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); - println!("pattern:"); - print_pat(cx, &local.pat, 0); - if let Some(ref e) = local.init { - println!("init expression:"); - print_expr(cx, e, 0); - } - }, - hir::DeclKind::Item(_) => println!("item decl"), - } -} - #[allow(clippy::similar_names)] fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { let ind = " ".repeat(indent); diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index b06fb1d21e3..87593fafb46 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -1,6 +1,5 @@ if_chain! { - if let StmtKind::Decl(ref decl, _) = stmt.node - if let DeclKind::Local(ref local) = decl.node; + if let StmtKind::Local(ref local) = stmt.node; if let Some(ref init) = local.init if let ExprKind::Cast(ref expr, ref cast_ty) = init.node; if let TyKind::Path(ref qp) = cast_ty.node; diff --git a/tests/ui/author/call.stdout b/tests/ui/author/call.stdout index 1c25708fb48..d9322d618bf 100644 --- a/tests/ui/author/call.stdout +++ b/tests/ui/author/call.stdout @@ -1,6 +1,5 @@ if_chain! { - if let StmtKind::Decl(ref decl, _) = stmt.node - if let DeclKind::Local(ref local) = decl.node; + if let StmtKind::Local(ref local) = stmt.node; if let Some(ref init) = local.init if let ExprKind::Call(ref func, ref args) = init.node; if let ExprKind::Path(ref path) = func.node; diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index b99e8e0ade5..1611f419e5d 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -1,7 +1,6 @@ if_chain! { if let ExprKind::Block(ref block) = expr.node; - if let StmtKind::Decl(ref decl, _) = block.node - if let DeclKind::Local(ref local) = decl.node; + if let StmtKind::Local(ref local) = block.node; if let Some(ref init) = local.init if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; if let ExprKind::Call(ref func, ref args) = expr.node; @@ -14,8 +13,7 @@ if_chain! { // unimplemented: field checks if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; - if let StmtKind::Decl(ref decl1, _) = body.node - if let DeclKind::Local(ref local1) = decl1.node; + if let StmtKind::Local(ref local1) = body.node; if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; if name.node.as_str() == "__next"; if let StmtKind::Expr(ref e, _) = local1.pat.node @@ -42,8 +40,7 @@ if_chain! { if arms1[1].pats.len() == 1; if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); - if let StmtKind::Decl(ref decl2, _) = path7.node - if let DeclKind::Local(ref local2) = decl2.node; + if let StmtKind::Local(ref local2) = path7.node; if let Some(ref init1) = local2.init if let ExprKind::Path(ref path8) = init1.node; if match_qpath(path8, &["__next"]); @@ -51,8 +48,7 @@ if_chain! { if name1.node.as_str() == "y"; if let StmtKind::Expr(ref e1, _) = local2.pat.node if let ExprKind::Block(ref block1) = e1.node; - if let StmtKind::Decl(ref decl3, _) = block1.node - if let DeclKind::Local(ref local3) = decl3.node; + if let StmtKind::Local(ref local3) = block1.node; if let Some(ref init2) = local3.init if let ExprKind::Path(ref path9) = init2.node; if match_qpath(path9, &["y"]); -- cgit 1.4.1-3-g733a5 From 8747691bea639835e66c6cef0baf66063f0aae93 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 20 Jan 2019 12:49:45 +0200 Subject: Run rustfmt --- clippy_lints/src/escape.rs | 18 ++++++++--------- clippy_lints/src/eval_order_dependence.rs | 13 +++++++------ clippy_lints/src/loops.rs | 10 +++++----- clippy_lints/src/methods/mod.rs | 8 ++++---- clippy_lints/src/shadow.rs | 32 +++++++++++++++---------------- clippy_lints/src/utils/hir_utils.rs | 11 ++++++----- clippy_lints/src/utils/inspector.rs | 2 +- 7 files changed, 48 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 79af6305f44..a7b47fd1e54 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -121,20 +121,20 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { let id = map.hir_to_node_id(cmt.hir_id); if let Some(Node::Stmt(st)) = map.find(map.get_parent_node(id)) { if let StmtKind::Local(ref loc) = st.node { - if let Some(ref ex) = loc.init { - if let ExprKind::Box(..) = ex.node { - if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { - // let x = box (...) - self.set.insert(consume_pat.id); - } - // TODO Box::new - // TODO vec![] - // TODO "foo".to_owned() and friends + if let Some(ref ex) = loc.init { + if let ExprKind::Box(..) = ex.node { + if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { + // let x = box (...) + self.set.insert(consume_pat.id); } + // TODO Box::new + // TODO vec![] + // TODO "foo".to_owned() and friends } } } } + } if let Categorization::Local(lid) = cmt.cat { if self.set.contains(&lid) { // let y = x where x is known diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 74fe4a6589b..2b4b0d40239 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -90,9 +90,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { StmtKind::Local(ref local) => { - if let Local { init: Some(ref e), .. } = **local { - DivergenceVisitor { cx }.visit_expr(e); - } + if let Local { init: Some(ref e), .. } = **local { + DivergenceVisitor { cx }.visit_expr(e); + } }, StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => DivergenceVisitor { cx }.maybe_walk_expr(e), StmtKind::Item(..) => {}, @@ -271,9 +271,10 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => check_expr(vis, expr), // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. - StmtKind::Local(ref local) => { - local.init.as_ref().map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) - }, + StmtKind::Local(ref local) => local + .init + .as_ref() + .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)), _ => StopEarly::KeepGoing, } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7d8b7d363b1..70ff86087ea 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1971,11 +1971,11 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { return None; } if let StmtKind::Local(ref local) = block.stmts[0].node { - if let Some(ref expr) = local.init { - Some(expr) - } else { - None - } + if let Some(ref expr) = local.init { + Some(expr) + } else { + None + } } else { None } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 5883128d72c..6c1befe6e53 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1337,10 +1337,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp }, hir::Node::Stmt(stmt) => { if let hir::StmtKind::Local(ref loc) = stmt.node { - if let hir::PatKind::Ref(..) = loc.pat.node { - // let ref y = *x borrows x, let ref y = x.clone() does not - return; - } + if let hir::PatKind::Ref(..) = loc.pat.node { + // let ref y = *x borrows x, let ref y = x.clone() does not + return; + } } }, _ => {}, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 153324094ec..c99b00bb98f 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -133,22 +133,22 @@ fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, binding if higher::is_from_for_desugar(local) { return; } - let Local { - ref pat, - ref ty, - ref init, - span, - .. - } = *local; - if let Some(ref t) = *ty { - check_ty(cx, t, bindings) - } - if let Some(ref o) = *init { - check_expr(cx, o, bindings); - check_pat(cx, pat, Some(o), span, bindings); - } else { - check_pat(cx, pat, None, span, bindings); - } + let Local { + ref pat, + ref ty, + ref init, + span, + .. + } = *local; + if let Some(ref t) = *ty { + check_ty(cx, t, bindings) + } + if let Some(ref o) = *init { + check_expr(cx, o, bindings); + check_pat(cx, pat, Some(o), span, bindings); + } else { + check_pat(cx, pat, None, span, bindings); + } } fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index aae4eb24964..a176830be26 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -43,13 +43,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { /// Check whether two statements are the same. pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { match (&left.node, &right.node) { - (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => + (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { self.eq_pat(&l.pat, &r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) - , - (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) - | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => self.eq_expr(l, r), + }, + (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => { + self.eq_expr(l, r) + }, _ => false, } } @@ -649,7 +650,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { StmtKind::Item(..) => { let c: fn(_) -> _ = StmtKind::Item; c.hash(&mut self.s); - } + }, StmtKind::Expr(ref expr) => { let c: fn(_) -> _ = StmtKind::Expr; c.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 235b2adc62e..4116f8ffbaf 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { println!("init expression:"); print_expr(cx, e, 0); } - } + }, hir::StmtKind::Item(_) => println!("item decl"), hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0), } -- cgit 1.4.1-3-g733a5 From 2183cfcc13c12f21571879dcc8ef40c4dfc9d8a7 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 20 Jan 2019 13:45:22 +0100 Subject: Fix `implicit_return` false positives. --- clippy_lints/src/implicit_return.rs | 28 ++++++++++++++++++++++------ tests/ui/implicit_return.rs | 19 +++++++++++++++++++ tests/ui/implicit_return.stderr | 10 +++++----- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index cd5db359628..073c37eefc5 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,5 +1,5 @@ -use crate::utils::{in_macro, snippet_opt, span_lint_and_then}; -use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl}; +use crate::utils::{in_macro, is_expn_of, snippet_opt, span_lint_and_then}; +use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, MatchSource}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; @@ -81,15 +81,31 @@ impl Pass { Self::expr_match(cx, else_expr); } }, - ExprKind::Match(_, arms, ..) => { - for arm in arms { - Self::expr_match(cx, &arm.body); + ExprKind::Match(.., arms, source) => { + let check_all_arms = match source { + MatchSource::IfLetDesugar { + contains_else_clause: has_else, + } => *has_else, + _ => true, + }; + + if check_all_arms { + for arm in arms { + Self::expr_match(cx, &arm.body); + } + } else { + Self::expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body); } }, // skip if it already has a return statement ExprKind::Ret(..) => (), // everything else is missing `return` - _ => Self::lint(cx, expr.span, expr.span, "add `return` as shown"), + _ => { + // make sure it's not just an unreachable expression + if is_expn_of(expr.span, "unreachable").is_none() { + Self::lint(cx, expr.span, expr.span, "add `return` as shown") + } + }, } } } diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 0fe4a283abf..d1c63ca1697 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -26,6 +26,14 @@ fn test_match(x: bool) -> bool { } } +#[allow(clippy::match_bool, clippy::needless_return)] +fn test_match_with_unreachable(x: bool) -> bool { + match x { + true => return false, + false => unreachable!(), + } +} + #[allow(clippy::never_loop)] fn test_loop() -> bool { loop { @@ -53,6 +61,15 @@ fn test_loop_with_nests() -> bool { } } +#[allow(clippy::redundant_pattern_matching)] +fn test_loop_with_if_let() -> bool { + loop { + if let Some(x) = Some(true) { + return x; + } + } +} + fn test_closure() { #[rustfmt::skip] let _ = || { true }; @@ -63,8 +80,10 @@ fn main() { let _ = test_end_of_fn(); let _ = test_if_block(); let _ = test_match(true); + let _ = test_match_with_unreachable(true); let _ = test_loop(); let _ = test_loop_with_block(); let _ = test_loop_with_nests(); + let _ = test_loop_with_if_let(); test_closure(); } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index c07fced1259..98b588f1a74 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -31,31 +31,31 @@ LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:32:9 + --> $DIR/implicit_return.rs:40:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:40:13 + --> $DIR/implicit_return.rs:48:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:49:13 + --> $DIR/implicit_return.rs:57:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:58:18 + --> $DIR/implicit_return.rs:75:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:59:16 + --> $DIR/implicit_return.rs:76:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` -- cgit 1.4.1-3-g733a5 From 0555ca1c2d98e74d748922c5a60d42174dab9675 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 20 Jan 2019 14:18:31 +0100 Subject: Remove negative integer literal checks. --- clippy_lints/src/arithmetic.rs | 6 +----- tests/ui/arithmetic.rs | 2 +- tests/ui/arithmetic.stderr | 8 +------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index d133a583f02..4ad2c43e083 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -92,11 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } }, hir::ExprKind::Unary(hir::UnOp::UnNeg, arg) => { - let ty = cx.tables.expr_ty(arg); - if ty.is_integral() { - span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.expr_span = Some(expr.span); - } else if ty.is_floating_point() { + if cx.tables.expr_ty(arg).is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.expr_span = Some(expr.span); } diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 874604889b9..5e9f8d41a16 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -15,7 +15,7 @@ fn main() { 1 % i / 2; // no error, this is part of the expression in the preceding line i - 2 + 2 - i; - -i; + -i; // no error, overflows are checked by `overflowing_literals` i & 1; // no wrapping i | 1; diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index c9bb68f857c..df441e4d3f8 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -25,12 +25,6 @@ error: integer arithmetic detected LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ -error: integer arithmetic detected - --> $DIR/arithmetic.rs:18:5 - | -LL | -i; - | ^^ - error: floating-point arithmetic detected --> $DIR/arithmetic.rs:28:5 | @@ -69,5 +63,5 @@ error: floating-point arithmetic detected LL | -f; | ^^ -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 13b5ea4223480265059356ed80e233e9f1b8a570 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 20 Jan 2019 14:50:26 +0100 Subject: Fix automatic suggestion on `use_self`. --- clippy_lints/src/use_self.rs | 12 ++++++------ tests/ui/use_self.stderr | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b72401e1cca..696f87854a4 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,7 +7,7 @@ use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintC use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; -use syntax_pos::symbol::keywords::SelfUpper; +use syntax_pos::{symbol::keywords::SelfUpper, Span}; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. @@ -55,11 +55,11 @@ impl LintPass for UseSelf { const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; -fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { +fn span_use_self_lint(cx: &LateContext<'_, '_>, span: Span) { span_lint_and_sugg( cx, USE_SELF, - path.span, + span, "unnecessary structure name repetition", "use the applicable keyword", "Self".to_owned(), @@ -92,7 +92,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { }; if !is_self_ty { - span_use_self_lint(self.cx, path); + span_use_self_lint(self.cx, path.span); } } } @@ -221,10 +221,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { if self.item_path.def == path.def { - span_use_self_lint(self.cx, path); + span_use_self_lint(self.cx, path.segments.first().expect(SEGMENTS_MSG).ident.span); } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def { if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) { - span_use_self_lint(self.cx, path); + span_use_self_lint(self.cx, path.span); } } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 9d23433ba64..649fcdbfff9 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -22,7 +22,7 @@ error: unnecessary structure name repetition --> $DIR/use_self.rs:15:13 | LL | Foo::new() - | ^^^^^^^^ help: use the applicable keyword: `Self` + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:20:25 @@ -34,7 +34,7 @@ error: unnecessary structure name repetition --> $DIR/use_self.rs:21:13 | LL | Foo::new() - | ^^^^^^^^ help: use the applicable keyword: `Self` + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:86:22 @@ -100,7 +100,7 @@ error: unnecessary structure name repetition --> $DIR/use_self.rs:101:13 | LL | Bad::default() - | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:106:23 -- cgit 1.4.1-3-g733a5 From adce3ef96666d0f2e142980e293fe4e14fc17faf Mon Sep 17 00:00:00 2001 From: Grzegorz Bartoszek Date: Sun, 20 Jan 2019 16:15:00 +0100 Subject: needless bool lint suggestion is wrapped in brackets if it is an "else" clause of an "if-else" statement --- clippy_lints/src/needless_bool.rs | 20 +++++++++++++++++++- tests/ui/needless_bool.rs | 13 +++++++++++++ tests/ui/needless_bool.stderr | 13 ++++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 1dfc3f6501e..38879fcda95 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -67,17 +67,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node { + let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); let snip = if not { !snip } else { snip }; - let hint = if ret { + let mut hint = if ret { format!("return {}", snip) } else { snip.to_string() }; + if parent_node_is_if_expr(&e, &cx) { + hint = format!("{{ {} }}", hint); + } + span_lint_and_sugg( cx, NEEDLESS_BOOL, @@ -119,6 +124,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { } } +fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool { + let parent_id = cx.tcx.hir().get_parent_node(expr.id); + let parent_node = cx.tcx.hir().get(parent_id); + + if let rustc::hir::Node::Expr(e) = parent_node { + if let ExprKind::If(_,_,_) = e.node { + return true; + } + } + + false +} + #[derive(Copy, Clone)] pub struct BoolComparison; diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 87493ab8c3d..75705525790 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -141,3 +141,16 @@ fn needless_bool3(x: bool) { if x == true {}; if x == false {}; } + +fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_brackets() { + let b = false; + let returns_bool = || false; + + let x = if b { + true + } else if returns_bool() { + false + } else { + true + }; +} diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index c829bf97dd2..46734ea07a5 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -136,5 +136,16 @@ error: equality checks against false can be replaced by a negation LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` -error: aborting due to 15 previous errors +error: this if-then-else expression returns a bool literal + --> $DIR/needless_bool.rs:151:12 + | +LL | } else if returns_bool() { + | ____________^ +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ help: you can reduce it to: `{ !returns_bool() }` + +error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From a747dbb04f044e37da19f82233ad2dce5d0c1bec Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 20 Jan 2019 22:54:04 +0200 Subject: Fix breakage due to rust-lang/rust#57651 --- clippy_lints/src/consts.rs | 7 +++++++ clippy_lints/src/utils/author.rs | 1 + 2 files changed, 8 insertions(+) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 5780b9bcfd4..49722e5ad71 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -14,6 +14,7 @@ use std::convert::TryInto; use std::hash::{Hash, Hasher}; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; +use syntax_pos::symbol::Symbol; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -38,6 +39,8 @@ pub enum Constant { Repeat(Box, u64), /// a tuple of constants Tuple(Vec), + /// a literal with syntax error + Err(Symbol), } impl PartialEq for Constant { @@ -103,6 +106,9 @@ impl Hash for Constant { c.hash(state); l.hash(state); }, + Constant::Err(ref s) => { + s.hash(state); + }, } } } @@ -155,6 +161,7 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { _ => bug!(), }, LitKind::Bool(b) => Constant::Bool(b), + LitKind::Err(s) => Constant::Err(s), } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 36eac00b54b..9623c6cbdad 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -260,6 +260,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { match lit.node { LitKind::Bool(val) => println!(" if let LitKind::Bool({:?}) = {}.node;", val, lit_pat), LitKind::Char(c) => println!(" if let LitKind::Char({:?}) = {}.node;", c, lit_pat), + LitKind::Err(val) => println!(" if let LitKind::Err({}) = {}.node;", val, lit_pat), LitKind::Byte(b) => println!(" if let LitKind::Byte({}) = {}.node;", b, lit_pat), // FIXME: also check int type LitKind::Int(i, _) => println!(" if let LitKind::Int({}, _) = {}.node;", i, lit_pat), -- cgit 1.4.1-3-g733a5 From d17c3d99d08a1d27d7b8a09da6357a5fba0ea17a Mon Sep 17 00:00:00 2001 From: rmcteggart-r7 Date: Sun, 20 Jan 2019 21:25:36 +0000 Subject: Fixing typo in CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df216a8fbc9..415fb7ab0d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ to lint-writing, though it does get into advanced stuff. Most lints consist of a of this. If you want to add a new lint or change existing ones apart from bugfixing, it's -also a good idea to give the [stability guaratees][rfc_stability] and +also a good idea to give the [stability guarantees][rfc_stability] and [lint categories][rfc_lint_cats] sections of the [Clippy 1.0 RFC][clippy_rfc] a quick read. -- cgit 1.4.1-3-g733a5 From 0a0792e53571540cf6de8e60099a814201c5664e Mon Sep 17 00:00:00 2001 From: Grzegorz Bartoszek Date: Mon, 21 Jan 2019 11:14:34 +0100 Subject: formatting fix --- clippy_lints/src/needless_bool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 38879fcda95..a5fe25d1cba 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -130,7 +130,7 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool if let rustc::hir::Node::Expr(e) = parent_node { if let ExprKind::If(_,_,_) = e.node { - return true; + return true; } } -- cgit 1.4.1-3-g733a5 From 4532073a29e4117ea930906e7683c45d8382e5bc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 21 Jan 2019 11:41:33 +0100 Subject: Update clippy_lints/src/needless_bool.rs Co-Authored-By: g-bartoszek --- clippy_lints/src/needless_bool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index a5fe25d1cba..e58c19eb6df 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -129,7 +129,7 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool let parent_node = cx.tcx.hir().get(parent_id); if let rustc::hir::Node::Expr(e) = parent_node { - if let ExprKind::If(_,_,_) = e.node { + if let ExprKind::If(_, _, _) = e.node { return true; } } -- cgit 1.4.1-3-g733a5 From 34785a12f46c0bd57ed98f9702d2030940756e78 Mon Sep 17 00:00:00 2001 From: Grzegorz Bartoszek Date: Mon, 21 Jan 2019 12:04:15 +0100 Subject: formatting fix --- clippy_lints/src/needless_bool.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index e58c19eb6df..5657da73a34 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -67,7 +67,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node { - let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); -- cgit 1.4.1-3-g733a5 From 2e0977f3b4061ed626fe9bfe29c703d13346abc1 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 21 Jan 2019 13:06:32 +0100 Subject: Fixed potential mistakes with nesting. Added tests. --- clippy_lints/src/use_self.rs | 16 +++++++++++----- tests/ui/use_self.rs | 20 ++++++++++++++++++++ tests/ui/use_self.stderr | 20 +++++++++++++++++++- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 696f87854a4..b57847d8f4b 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,7 +7,7 @@ use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintC use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; -use syntax_pos::{symbol::keywords::SelfUpper, Span}; +use syntax_pos::symbol::keywords::SelfUpper; /// **What it does:** Checks for unnecessary repetition of structure name when a /// replacement with `Self` is applicable. @@ -55,7 +55,13 @@ impl LintPass for UseSelf { const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; -fn span_use_self_lint(cx: &LateContext<'_, '_>, span: Span) { +fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { + // path segments only include actual path, no methods or fields + let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span; + // `to()` doesn't shorten span, so we shorten it with `until(..)` + // and then include it with `to(..)` + let span = path.span.until(last_path_span).to(last_path_span); + span_lint_and_sugg( cx, USE_SELF, @@ -92,7 +98,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { }; if !is_self_ty { - span_use_self_lint(self.cx, path.span); + span_use_self_lint(self.cx, path); } } } @@ -221,10 +227,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { if self.item_path.def == path.def { - span_use_self_lint(self.cx, path.segments.first().expect(SEGMENTS_MSG).ident.span); + span_use_self_lint(self.cx, path); } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def { if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) { - span_use_self_lint(self.cx, path.span); + span_use_self_lint(self.cx, path); } } } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index b839aead95a..0cf406b18ce 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -274,3 +274,23 @@ mod issue3410 { fn a(_: Vec) {} } } + +#[allow(clippy::no_effect)] +mod rustfix { + mod nested { + pub struct A {} + } + + impl nested::A { + const A: bool = true; + + fn fun_1() {} + + fn fun_2() { + nested::A::fun_1(); + nested::A::A; + + nested::A {}; + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 649fcdbfff9..68ce7221d03 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -162,5 +162,23 @@ error: unnecessary structure name repetition LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 26 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:290:13 + | +LL | nested::A::fun_1(); + | ^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:291:13 + | +LL | nested::A::A; + | ^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:293:13 + | +LL | nested::A {}; + | ^^^^^^^^^ help: use the applicable keyword: `Self` + +error: aborting due to 29 previous errors -- cgit 1.4.1-3-g733a5 From 87d24e1fc998269d530e0fd88ba1c89d2171fb55 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 21 Jan 2019 13:59:49 +0100 Subject: Actually check for constants. --- clippy_lints/src/arithmetic.rs | 9 ++++++++- tests/ui/arithmetic.rs | 6 +++++- tests/ui/arithmetic.stderr | 20 +++++++++++++------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 4ad2c43e083..473db1869ac 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -1,3 +1,4 @@ +use crate::consts::constant_simple; use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -92,7 +93,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } }, hir::ExprKind::Unary(hir::UnOp::UnNeg, arg) => { - if cx.tables.expr_ty(arg).is_floating_point() { + let ty = cx.tables.expr_ty(arg); + if ty.is_integral() { + if constant_simple(cx, cx.tables, expr).is_none() { + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); + self.expr_span = Some(expr.span); + } + } else if ty.is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.expr_span = Some(expr.span); } diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index 5e9f8d41a16..c3cea997606 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -15,7 +15,11 @@ fn main() { 1 % i / 2; // no error, this is part of the expression in the preceding line i - 2 + 2 - i; - -i; // no error, overflows are checked by `overflowing_literals` + -i; + + // no error, overflows are checked by `overflowing_literals` + -1; + -(-1); i & 1; // no wrapping i | 1; diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index df441e4d3f8..b21efaa849f 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -25,8 +25,14 @@ error: integer arithmetic detected LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ +error: integer arithmetic detected + --> $DIR/arithmetic.rs:18:5 + | +LL | -i; + | ^^ + error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:28:5 + --> $DIR/arithmetic.rs:32:5 | LL | f * 2.0; | ^^^^^^^ @@ -34,34 +40,34 @@ LL | f * 2.0; = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:30:5 + --> $DIR/arithmetic.rs:34:5 | LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:31:5 + --> $DIR/arithmetic.rs:35:5 | LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:32:5 + --> $DIR/arithmetic.rs:36:5 | LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:33:5 + --> $DIR/arithmetic.rs:37:5 | LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:34:5 + --> $DIR/arithmetic.rs:38:5 | LL | -f; | ^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 0f5c43a7227f830f1c083b00d89ceb2f57ccb923 Mon Sep 17 00:00:00 2001 From: Grzegorz Bartoszek Date: Tue, 22 Jan 2019 12:33:47 +0100 Subject: Added "make_return" and "blockify" convenience methods in Sugg and used them in "needless_bool". --- clippy_lints/src/needless_bool.rs | 14 ++++++-------- clippy_lints/src/utils/sugg.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index a898a740cd8..3b1fea465f5 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -70,16 +70,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); - let snip = if not { !snip } else { snip }; + let mut snip = if not { !snip } else { snip }; - let mut hint = if ret { - format!("return {}", snip) - } else { - snip.to_string() - }; + if ret { + snip = snip.make_return(); + } if parent_node_is_if_expr(&e, &cx) { - hint = format!("{{ {} }}", hint); + snip = snip.blockify() } span_lint_and_sugg( @@ -88,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { e.span, "this if-then-else expression returns a bool literal", "you can reduce it to", - hint, + snip.to_string(), applicability, ); }; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index d42af5fde3a..b95ce17ed93 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -206,6 +206,17 @@ impl<'a> Sugg<'a> { make_unop("&mut *", self) } + /// Convenience method to transform suggestion into a return call + pub fn make_return(self) -> Sugg<'static> { + Sugg::NonParen(Cow::Owned(format!("return {}", self))) + } + + /// Convenience method to transform suggestion into a block + /// where the suggestion is a trailing expression + pub fn blockify(self) -> Sugg<'static> { + Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self))) + } + /// Convenience method to create the `..` or `...` /// suggestion. #[allow(dead_code)] @@ -578,3 +589,21 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error self.span_suggestion_with_applicability(remove_span, msg, String::new(), applicability); } } + +#[cfg(test)] +mod test { + use super::Sugg; + use std::borrow::Cow; + + const SUGGESTION: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("function_call()")); + + #[test] + fn make_return_transform_sugg_into_a_return_call() { + assert_eq!("return function_call()", SUGGESTION.make_return().to_string()); + } + + #[test] + fn blockify_transforms_sugg_into_a_block() { + assert_eq!("{ function_call() }", SUGGESTION.blockify().to_string()); + } +} -- cgit 1.4.1-3-g733a5 From e70f9456fcc2cafae9a94611e0e0dd6bc2fa6cb9 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 22 Jan 2019 14:43:59 +0100 Subject: Improve span shortening. Co-Authored-By: daxpedda <1645124+daxpedda@users.noreply.github.com> --- clippy_lints/src/use_self.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b57847d8f4b..5d4d5bac4c7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -60,7 +60,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span; // `to()` doesn't shorten span, so we shorten it with `until(..)` // and then include it with `to(..)` - let span = path.span.until(last_path_span).to(last_path_span); + let span = path.span.with_hi(last_path_span.hi()); span_lint_and_sugg( cx, -- cgit 1.4.1-3-g733a5 From e6f2239bc3bfec1cf37a0e28bd83b6ba9b809520 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 22 Jan 2019 15:16:54 +0100 Subject: Added rustfix to the test. --- tests/ui/use_self.fixed | 299 +++++++++++++++++++++++++++++++++++++++++++++++ tests/ui/use_self.rs | 5 +- tests/ui/use_self.stderr | 58 ++++----- 3 files changed, 332 insertions(+), 30 deletions(-) create mode 100644 tests/ui/use_self.fixed diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed new file mode 100644 index 00000000000..5eae9a7a806 --- /dev/null +++ b/tests/ui/use_self.fixed @@ -0,0 +1,299 @@ +// run-rustfix + +#![warn(clippy::use_self)] +#![allow(dead_code)] +#![allow(clippy::should_implement_trait)] + +fn main() {} + +mod use_self { + struct Foo {} + + impl Foo { + fn new() -> Self { + Self {} + } + fn test() -> Self { + Self::new() + } + } + + impl Default for Foo { + fn default() -> Self { + Self::new() + } + } +} + +mod better { + struct Foo {} + + impl Foo { + fn new() -> Self { + Self {} + } + fn test() -> Self { + Self::new() + } + } + + impl Default for Foo { + fn default() -> Self { + Self::new() + } + } +} + +mod lifetimes { + struct Foo<'a> { + foo_str: &'a str, + } + + impl<'a> Foo<'a> { + // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> + // Foo<'b>` + fn foo(s: &str) -> Foo { + Foo { foo_str: s } + } + // cannot replace with `Self`, because that's `Foo<'a>` + fn bar() -> Foo<'static> { + Foo { foo_str: "foo" } + } + + // FIXME: the lint does not handle lifetimed struct + // `Self` should be applicable here + fn clone(&self) -> Foo<'a> { + Foo { foo_str: self.foo_str } + } + } +} + +#[allow(clippy::boxed_local)] +mod traits { + + use std::ops::Mul; + + trait SelfTrait { + fn refs(p1: &Self) -> &Self; + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self; + fn mut_refs(p1: &mut Self) -> &mut Self; + fn nested(p1: Box, p2: (&u8, &Self)); + fn vals(r: Self) -> Self; + } + + #[derive(Default)] + struct Bad; + + impl SelfTrait for Bad { + fn refs(p1: &Self) -> &Self { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + p1 + } + + fn mut_refs(p1: &mut Self) -> &mut Self { + p1 + } + + fn nested(_p1: Box, _p2: (&u8, &Self)) {} + + fn vals(_: Self) -> Self { + Self::default() + } + } + + impl Mul for Bad { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + rhs + } + } + + #[derive(Default)] + struct Good; + + impl SelfTrait for Good { + fn refs(p1: &Self) -> &Self { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + p1 + } + + fn mut_refs(p1: &mut Self) -> &mut Self { + p1 + } + + fn nested(_p1: Box, _p2: (&u8, &Self)) {} + + fn vals(_: Self) -> Self { + Self::default() + } + } + + impl Mul for Good { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + rhs + } + } + + trait NameTrait { + fn refs(p1: &u8) -> &u8; + fn ref_refs<'a>(p1: &'a &'a u8) -> &'a &'a u8; + fn mut_refs(p1: &mut u8) -> &mut u8; + fn nested(p1: Box, p2: (&u8, &u8)); + fn vals(p1: u8) -> u8; + } + + // Using `Self` instead of the type name is OK + impl NameTrait for u8 { + fn refs(p1: &Self) -> &Self { + p1 + } + + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + p1 + } + + fn mut_refs(p1: &mut Self) -> &mut Self { + p1 + } + + fn nested(_p1: Box, _p2: (&Self, &Self)) {} + + fn vals(_: Self) -> Self { + Self::default() + } + } + + // Check that self arg isn't linted + impl Clone for Good { + fn clone(&self) -> Self { + // Note: Not linted and it wouldn't be valid + // because "can't use `Self` as a constructor`" + Good + } + } +} + +mod issue2894 { + trait IntoBytes { + fn into_bytes(&self) -> Vec; + } + + // This should not be linted + impl IntoBytes for u8 { + fn into_bytes(&self) -> Vec { + vec![*self] + } + } +} + +mod existential { + struct Foo; + + impl Foo { + fn bad(foos: &[Self]) -> impl Iterator { + foos.iter() + } + + fn good(foos: &[Self]) -> impl Iterator { + foos.iter() + } + } +} + +mod tuple_structs { + pub struct TS(i32); + + impl TS { + pub fn ts() -> Self { + Self(0) + } + } +} + +mod macros { + macro_rules! use_self_expand { + () => { + fn new() -> Self { + Self {} + } + }; + } + + struct Foo {} + + impl Foo { + use_self_expand!(); // Should lint in local macros + } +} + +mod nesting { + struct Foo {} + impl Foo { + fn foo() { + use self::Foo; // Can't use Self here + struct Bar { + foo: Foo, // Foo != Self + } + + impl Bar { + fn bar() -> Self { + Self { foo: Foo {} } + } + } + } + } + + enum Enum { + A, + } + impl Enum { + fn method() { + #[allow(unused_imports)] + use self::Enum::*; // Issue 3425 + static STATIC: Enum = Enum::A; // Can't use Self as type + } + } +} + +mod issue3410 { + + struct A; + struct B; + + trait Trait { + fn a(v: T); + } + + impl Trait> for Vec { + fn a(_: Vec) {} + } +} + +#[allow(clippy::no_effect, path_statements)] +mod rustfix { + mod nested { + pub struct A {} + } + + impl nested::A { + const A: bool = true; + + fn fun_1() {} + + fn fun_2() { + Self::fun_1(); + Self::A; + + Self {}; + } + } +} diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 0cf406b18ce..8e28bbbeb9c 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![warn(clippy::use_self)] #![allow(dead_code)] #![allow(clippy::should_implement_trait)] @@ -255,6 +257,7 @@ mod nesting { } impl Enum { fn method() { + #[allow(unused_imports)] use self::Enum::*; // Issue 3425 static STATIC: Enum = Enum::A; // Can't use Self as type } @@ -275,7 +278,7 @@ mod issue3410 { } } -#[allow(clippy::no_effect)] +#[allow(clippy::no_effect, path_statements)] mod rustfix { mod nested { pub struct A {} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 68ce7221d03..af9e15edb6c 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:11:21 + --> $DIR/use_self.rs:13:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,133 +7,133 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:12:13 + --> $DIR/use_self.rs:14:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:22 + --> $DIR/use_self.rs:16:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:15:13 + --> $DIR/use_self.rs:17:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:20:25 + --> $DIR/use_self.rs:22:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:21:13 + --> $DIR/use_self.rs:23:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:86:22 + --> $DIR/use_self.rs:88:22 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:86:31 + --> $DIR/use_self.rs:88:31 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:90:37 + --> $DIR/use_self.rs:92:37 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:90:53 + --> $DIR/use_self.rs:92:53 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:94:30 + --> $DIR/use_self.rs:96:30 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:94:43 + --> $DIR/use_self.rs:96:43 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:28 + --> $DIR/use_self.rs:100:28 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:46 + --> $DIR/use_self.rs:100:46 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:20 + --> $DIR/use_self.rs:102:20 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:28 + --> $DIR/use_self.rs:102:28 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:101:13 + --> $DIR/use_self.rs:103:13 | LL | Bad::default() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:106:23 + --> $DIR/use_self.rs:108:23 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:27 + --> $DIR/use_self.rs:110:27 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:35 + --> $DIR/use_self.rs:110:35 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:200:56 + --> $DIR/use_self.rs:202:56 | LL | fn bad(foos: &[Self]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:215:13 + --> $DIR/use_self.rs:217:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:223:25 + --> $DIR/use_self.rs:225:25 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -142,7 +142,7 @@ LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation error: unnecessary structure name repetition - --> $DIR/use_self.rs:224:17 + --> $DIR/use_self.rs:226:17 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` @@ -151,31 +151,31 @@ LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation error: unnecessary structure name repetition - --> $DIR/use_self.rs:246:29 + --> $DIR/use_self.rs:248:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:247:21 + --> $DIR/use_self.rs:249:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:290:13 + --> $DIR/use_self.rs:293:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:291:13 + --> $DIR/use_self.rs:294:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:293:13 + --> $DIR/use_self.rs:296:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` -- cgit 1.4.1-3-g733a5 From 3168023cc8027c3fa53c7777d4f27be6a06bf168 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 22 Jan 2019 15:17:05 +0100 Subject: Rustup --- clippy_lints/src/arithmetic.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 473db1869ac..efa53ff94c3 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } self.const_span = Some(body_span); }, - hir::BodyOwnerKind::Fn => (), + hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (), } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 5d94f0f3f05..ab394cc47ea 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -65,7 +65,7 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir().get_parent(id); match cx.tcx.hir().body_owner_kind(parent_id) { - hir::BodyOwnerKind::Fn => false, + hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => false, hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(..) => true, } } -- cgit 1.4.1-3-g733a5 From 42d5a07f0ca4d0a3d17f2d2634862dc73bf82d2f Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 22 Jan 2019 15:23:45 +0100 Subject: Improving comments. --- clippy_lints/src/use_self.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 5d4d5bac4c7..88cf01987b5 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -58,8 +58,7 @@ const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { // path segments only include actual path, no methods or fields let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span; - // `to()` doesn't shorten span, so we shorten it with `until(..)` - // and then include it with `to(..)` + // only take path up to the end of last_path_span let span = path.span.with_hi(last_path_span.hi()); span_lint_and_sugg( -- cgit 1.4.1-3-g733a5 From 38cdf63acfd8a46ce5753a8767feab43c6382aa4 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 22 Jan 2019 15:28:51 +0100 Subject: Don't make decisions on values that don't represent the decision --- clippy_lints/src/utils/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ab394cc47ea..a7af4a52714 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -64,9 +64,14 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { /// ``` pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir().get_parent(id); - match cx.tcx.hir().body_owner_kind(parent_id) { - hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => false, - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(..) => true, + match cx.tcx.hir().get(parent_id) { + | Node::Item(&Item { node: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) + | Node::AnonConst(_) + | Node::Item(&Item { node: ItemKind::Static(..), .. }) + => true, + _ => false, } } -- cgit 1.4.1-3-g733a5 From d6c806378e6901b83d5ab8594dcd2c6347e0196a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 22 Jan 2019 16:27:42 +0100 Subject: Rustfmt all the things --- clippy_lints/src/utils/mod.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a7af4a52714..c83b0f155fc 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -65,12 +65,23 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir().get_parent(id); match cx.tcx.hir().get(parent_id) { - | Node::Item(&Item { node: ItemKind::Const(..), .. }) - | Node::TraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) - | Node::ImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) + Node::Item(&Item { + node: ItemKind::Const(..), + .. + }) + | Node::TraitItem(&TraitItem { + node: TraitItemKind::Const(..), + .. + }) + | Node::ImplItem(&ImplItem { + node: ImplItemKind::Const(..), + .. + }) | Node::AnonConst(_) - | Node::Item(&Item { node: ItemKind::Static(..), .. }) - => true, + | Node::Item(&Item { + node: ItemKind::Static(..), + .. + }) => true, _ => false, } } -- cgit 1.4.1-3-g733a5 From c771f339d73e2a02c5a61734ffa3106721407265 Mon Sep 17 00:00:00 2001 From: "A.A.Abroskin" Date: Wed, 23 Jan 2019 11:49:02 +0300 Subject: allow assertions_on_constants for collapsible_if and missing_test_files --- clippy_lints/src/assertions_on_constants.rs | 9 --------- tests/missing-test-files.rs | 2 ++ tests/ui/assertions_on_constants.rs | 9 --------- tests/ui/assertions_on_constants.stderr | 12 ++++++------ tests/ui/attrs.rs | 2 +- tests/ui/collapsible_if.fixed | 2 +- tests/ui/collapsible_if.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/panic_unimplemented.rs | 2 +- 9 files changed, 13 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index f88ef8e83ed..a148cb1c3a6 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::consts::{constant, Constant}; use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index 558e001d3d1..bd0cee75644 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -1,3 +1,5 @@ +#![allow(clippy::assertions_on_constants)] + use std::fs::{self, DirEntry}; use std::path::Path; diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs index dcefe83f8c2..daeceebd3a2 100644 --- a/tests/ui/assertions_on_constants.rs +++ b/tests/ui/assertions_on_constants.rs @@ -1,12 +1,3 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { assert!(true); assert!(false); diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index 1f1a80e0e77..e8001acceb1 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -1,5 +1,5 @@ error: assert!(true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:11:5 + --> $DIR/assertions_on_constants.rs:2:5 | LL | assert!(true); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | assert!(true); = help: remove it error: assert!(false) should probably be replaced - --> $DIR/assertions_on_constants.rs:12:5 + --> $DIR/assertions_on_constants.rs:3:5 | LL | assert!(false); | ^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | assert!(false); = help: use panic!() or unreachable!() error: assert!(true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:13:5 + --> $DIR/assertions_on_constants.rs:4:5 | LL | assert!(true, "true message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | assert!(true, "true message"); = help: remove it error: assert!(false) should probably be replaced - --> $DIR/assertions_on_constants.rs:14:5 + --> $DIR/assertions_on_constants.rs:5:5 | LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | assert!(false, "false message"); = help: use panic!() or unreachable!() error: assert!(const: true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:17:5 + --> $DIR/assertions_on_constants.rs:8:5 | LL | assert!(B); | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | assert!(B); = help: remove it error: assert!(const: false) should probably be replaced - --> $DIR/assertions_on_constants.rs:20:5 + --> $DIR/assertions_on_constants.rs:11:5 | LL | assert!(C); | ^^^^^^^^^^^ diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index df7eafc6551..91b65a43be7 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,5 +1,5 @@ #![warn(clippy::inline_always, clippy::deprecated_semver)] -#![allow(clippy::assertions_on_constants::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] #[inline(always)] fn test_attr_lint() { assert!(true) diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 2c6dd95a637..3c7de56406e 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cyclomatic_complexity)] +#![allow(clippy::cyclomatic_complexity, clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index f482d7704de..e46d7537577 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cyclomatic_complexity)] +#![allow(clippy::cyclomatic_complexity, clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 3af8e3eeac0..b43dc200825 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,5 +1,5 @@ #![warn(clippy::empty_line_after_outer_attr)] -#![allow(clippy::assertions_on_constants::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index a7c5b91fdb5..92290da8a6a 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -1,5 +1,5 @@ #![warn(clippy::panic_params, clippy::unimplemented)] -#![allow(clippy::assertions_on_constants::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] fn missing() { if true { panic!("{}"); -- cgit 1.4.1-3-g733a5 From 5284b95a064280d2ed70e6fabf6eb863689d3848 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 24 Jan 2019 06:58:53 +0200 Subject: Fix `expect_fun_call` lint suggestions This commit corrects some bad suggestions produced by the `expect_fun_call` lint and enables `rust-fix` checking on the tests. Addresses #3630 --- clippy_lints/src/methods/mod.rs | 186 ++++++++++++++++++++-------------------- tests/ui/expect_fun_call.fixed | 84 ++++++++++++++++++ tests/ui/expect_fun_call.rs | 38 ++++++-- tests/ui/expect_fun_call.stderr | 46 +++++++--- 4 files changed, 238 insertions(+), 116 deletions(-) create mode 100644 tests/ui/expect_fun_call.fixed diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6c1befe6e53..0571f1d92d7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1148,28 +1148,6 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { - fn extract_format_args(arg: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr)> { - let arg = match &arg.node { - hir::ExprKind::AddrOf(_, expr) => expr, - hir::ExprKind::MethodCall(method_name, _, args) - if method_name.ident.name == "as_str" || method_name.ident.name == "as_ref" => - { - &args[0] - }, - _ => arg, - }; - - if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg.node { - if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { - if let hir::ExprKind::Call(_, format_args) = &inner_args[0].node { - return Some((&format_args[0], &format_args[1])); - } - } - } - - None - } - fn generate_format_arg_snippet( cx: &LateContext<'_, '_>, a: &hir::Expr, @@ -1189,93 +1167,115 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: unreachable!() } - fn check_general_case( - cx: &LateContext<'_, '_>, - name: &str, - method_span: Span, - self_expr: &hir::Expr, - arg: &hir::Expr, - span: Span, - ) { - fn is_call(node: &hir::ExprKind) -> bool { - match node { - hir::ExprKind::AddrOf(_, expr) => { - is_call(&expr.node) - }, - hir::ExprKind::Call(..) - | hir::ExprKind::MethodCall(..) - // These variants are debatable or require further examination - | hir::ExprKind::If(..) - | hir::ExprKind::Match(..) - | hir::ExprKind::Block{ .. } => true, - _ => false, - } - } - - if name != "expect" { - return; + fn is_call(node: &hir::ExprKind) -> bool { + match node { + hir::ExprKind::AddrOf(_, expr) => { + is_call(&expr.node) + }, + hir::ExprKind::Call(..) + | hir::ExprKind::MethodCall(..) + // These variants are debatable or require further examination + | hir::ExprKind::If(..) + | hir::ExprKind::Match(..) + | hir::ExprKind::Block{ .. } => true, + _ => false, } + } - let self_type = cx.tables.expr_ty(self_expr); - let known_types = &[&paths::OPTION, &paths::RESULT]; - - // if not a known type, return early - if known_types.iter().all(|&k| !match_type(cx, self_type, k)) { - return; - } + if args.len() != 2 || name != "expect" || !is_call(&args[1].node) { + return; + } - if !is_call(&arg.node) { - return; - } + let receiver_type = cx.tables.expr_ty(&args[0]); + let closure_args = if match_type(cx, receiver_type, &paths::OPTION) { + "||" + } else if match_type(cx, receiver_type, &paths::RESULT) { + "|_|" + } else { + return; + }; - let closure = if match_type(cx, self_type, &paths::OPTION) { - "||" - } else { - "|_|" + // Strip off `&`, `as_ref()` and `as_str()` until we're left with either a `String` or `&str` + // which we call `arg_root`. + let mut arg_root = &args[1]; + loop { + arg_root = match &arg_root.node { + hir::ExprKind::AddrOf(_, expr) => expr, + hir::ExprKind::MethodCall(method_name, _, call_args) => { + if call_args.len() == 1 + && (method_name.ident.name == "as_str" || method_name.ident.name == "as_ref") + && { + let arg_type = cx.tables.expr_ty(&call_args[0]); + let base_type = walk_ptrs_ty(arg_type); + base_type.sty == ty::Str || match_type(cx, base_type, &paths::STRING) + } + { + &call_args[0] + } else { + break; + } + }, + _ => break, }; - let span_replace_word = method_span.with_hi(span.hi()); + } - if let Some((fmt_spec, fmt_args)) = extract_format_args(arg) { - let mut applicability = Applicability::MachineApplicable; - let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()]; + let span_replace_word = method_span.with_hi(expr.span.hi()); - args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability)); + let mut applicability = Applicability::MachineApplicable; - let sugg = args.join(", "); + //Special handling for `format!` as arg_root + if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg_root.node { + if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 { + if let hir::ExprKind::Call(_, format_args) = &inner_args[0].node { + let fmt_spec = &format_args[0]; + let fmt_args = &format_args[1]; - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("unwrap_or_else({} panic!({}))", closure, sugg), - applicability, - ); + let mut applicability = Applicability::MachineApplicable; + let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()]; - return; - } + args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability)); - let mut applicability = Applicability::MachineApplicable; - let sugg: Cow<'_, _> = snippet_with_applicability(cx, arg.span, "..", &mut applicability); + let sugg = args.join(", "); - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{}` followed by a function call", name), - "try this", - format!("unwrap_or_else({} {{ let msg = {}; panic!(msg) }}))", closure, sugg), - applicability, - ); + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} panic!({}))", closure_args, sugg), + applicability, + ); + + return; + } + } } - if args.len() == 2 { - match args[1].node { - hir::ExprKind::Lit(_) => {}, - _ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span), + // If root_arg is `&'static str` or `String` we can use it directly in the `panic!` call otherwise + // we must use `to_string` to convert it. + let mut arg_root_snippet: Cow<'_, _> = snippet_with_applicability(cx, arg_root.span, "..", &mut applicability); + let arg_root_ty = cx.tables.expr_ty(arg_root); + let mut requires_conv = !match_type(cx, arg_root_ty, &paths::STRING); + if let ty::Ref(ty::ReStatic, ty, ..) = arg_root_ty.sty { + if ty.sty == ty::Str { + requires_conv = false; } + }; + + if requires_conv { + arg_root_snippet.to_mut().push_str(".to_string()"); } + + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{}` followed by a function call", name), + "try this", + format!("unwrap_or_else({} {{ panic!({}) }})", closure_args, arg_root_snippet), + applicability, + ); } /// Checks for the `CLONE_ON_COPY` lint. diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed new file mode 100644 index 00000000000..1f74f6b8cf1 --- /dev/null +++ b/tests/ui/expect_fun_call.fixed @@ -0,0 +1,84 @@ +// run-rustfix + +#![warn(clippy::expect_fun_call)] + +/// Checks implementation of the `EXPECT_FUN_CALL` lint + +fn main() { + struct Foo; + + impl Foo { + fn new() -> Self { + Foo + } + + fn expect(&self, msg: &str) { + panic!("{}", msg) + } + } + + let with_some = Some("value"); + with_some.expect("error"); + + let with_none: Option = None; + with_none.expect("error"); + + let error_code = 123_i32; + let with_none_and_format: Option = None; + with_none_and_format.unwrap_or_else(|| panic!("Error {}: fake error", error_code)); + + let with_none_and_as_str: Option = None; + with_none_and_as_str.unwrap_or_else(|| panic!("Error {}: fake error", error_code)); + + let with_ok: Result<(), ()> = Ok(()); + with_ok.expect("error"); + + let with_err: Result<(), ()> = Err(()); + with_err.expect("error"); + + let error_code = 123_i32; + let with_err_and_format: Result<(), ()> = Err(()); + with_err_and_format.unwrap_or_else(|_| panic!("Error {}: fake error", error_code)); + + let with_err_and_as_str: Result<(), ()> = Err(()); + with_err_and_as_str.unwrap_or_else(|_| panic!("Error {}: fake error", error_code)); + + let with_dummy_type = Foo::new(); + with_dummy_type.expect("another test string"); + + let with_dummy_type_and_format = Foo::new(); + with_dummy_type_and_format.expect(&format!("Error {}: fake error", error_code)); + + let with_dummy_type_and_as_str = Foo::new(); + with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + + //Issue #2937 + Some("foo").unwrap_or_else(|| panic!("{} {}", 1, 2)); + + //Issue #2979 - this should not lint + { + let msg = "bar"; + Some("foo").expect(msg); + } + + { + fn get_string() -> String { + "foo".to_string() + } + + fn get_static_str() -> &'static str { + "foo" + } + + fn get_non_static_str(_: &u32) -> &str { + "foo" + } + + Some("foo").unwrap_or_else(|| { panic!(get_string()) }); + Some("foo").unwrap_or_else(|| { panic!(get_string()) }); + Some("foo").unwrap_or_else(|| { panic!(get_string()) }); + + Some("foo").unwrap_or_else(|| { panic!(get_static_str()) }); + Some("foo").unwrap_or_else(|| { panic!(get_non_static_str(&0).to_string()) }); + } +} diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 7f0ca0fe809..2d8b4925f35 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -1,9 +1,10 @@ +// run-rustfix + #![warn(clippy::expect_fun_call)] -#![allow(clippy::useless_format)] /// Checks implementation of the `EXPECT_FUN_CALL` lint -fn expect_fun_call() { +fn main() { struct Foo; impl Foo { @@ -51,14 +52,33 @@ fn expect_fun_call() { let with_dummy_type_and_as_str = Foo::new(); with_dummy_type_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + //Issue #2937 + Some("foo").expect(format!("{} {}", 1, 2).as_ref()); + //Issue #2979 - this should not lint - let msg = "bar"; - Some("foo").expect(msg); + { + let msg = "bar"; + Some("foo").expect(msg); + } - Some("foo").expect({ &format!("error") }); - Some("foo").expect(format!("error").as_ref()); + { + fn get_string() -> String { + "foo".to_string() + } - Some("foo").expect(format!("{} {}", 1, 2).as_ref()); -} + fn get_static_str() -> &'static str { + "foo" + } + + fn get_non_static_str(_: &u32) -> &str { + "foo" + } -fn main() {} + Some("foo").expect(&get_string()); + Some("foo").expect(get_string().as_ref()); + Some("foo").expect(get_string().as_str()); + + Some("foo").expect(get_static_str()); + Some("foo").expect(get_non_static_str(&0)); + } +} diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index a60bd7e4ed3..900e251d964 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:27:26 + --> $DIR/expect_fun_call.rs:28:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` @@ -7,40 +7,58 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:30:26 + --> $DIR/expect_fun_call.rs:31:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:40:25 + --> $DIR/expect_fun_call.rs:41:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:43:25 + --> $DIR/expect_fun_call.rs:44:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:58:17 + --> $DIR/expect_fun_call.rs:56:17 | -LL | Some("foo").expect({ &format!("error") }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { let msg = { &format!("error") }; panic!(msg) }))` +LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:59:17 + --> $DIR/expect_fun_call.rs:77:21 | -LL | Some("foo").expect(format!("error").as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))` +LL | Some("foo").expect(&get_string()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:61:17 + --> $DIR/expect_fun_call.rs:78:21 | -LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` +LL | Some("foo").expect(get_string().as_ref()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:79:21 + | +LL | Some("foo").expect(get_string().as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:81:21 + | +LL | Some("foo").expect(get_static_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_static_str()) })` + +error: use of `expect` followed by a function call + --> $DIR/expect_fun_call.rs:82:21 + | +LL | Some("foo").expect(get_non_static_str(&0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_non_static_str(&0).to_string()) })` -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors -- cgit 1.4.1-3-g733a5 From 1e4f44853c13ae3e669996a265234f95baf957fe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 24 Jan 2019 14:51:25 +0100 Subject: Update changelog with all changes since 0.0.212 --- CHANGELOG.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14c1b0e4d3f..21e91c666b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,128 @@ # Change Log + All notable changes to this project will be documented in this file. -## 0.0.212 +## Unreleased / In Rust Beta or Nightly + +[b2601be...master](https://github.com/rust-lang/rust-clippy/compare/b2601be...master) + +## Rust 1.32 (2019-01-17) + +[2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be) + +* New lints: [`slow_vector_initialization`], [`unsafe_vector_initialization`], + [`mem_discriminant_non_enum`], [`redundant_clone`], [`wildcard_dependencies`], + [`into_iter_on_ref`], [`into_iter_on_array`], [`deprecated_cfg_attr`], + [`mem_discriminant_non_enum`], [`cargo_common_metadata`] +* Add support for `u128` and `i128` to integer related lints +* Add float support to `mistyped_literal_suffixes` +* Fix false positives in `use_self` +* Fix false positives in `missing_comma` +* Fix false positives in `new_ret_no_self` +* Fix false positives in `possible_missing_comma` +* Fix false positive in `integer_arithmetic` in constant items +* Fix false positive in `needless_borrow` +* Fix false positive in `out_of_bounds_indexing` +* Fix false positive in `new_without_default_derive` +* Fix false positive in `string_lit_as_bytes` +* Fix false negative in `out_of_bounds_indexing` +* Fix false negative in `use_self`. It will now also check existential types +* Fix incorrect suggestion for `redundant_closure_call` +* Fix various suggestions that contained expanded macros +* Fix `bool_comparison` triggering 3 times on on on the same code +* Expand `trivially_copy_pass_by_ref` to work on trait methods +* Improve suggestion for `needless_range_loop` +* Move `needless_pass_by_value` from `pedantic` group to `style` + +## Rust 1.31 (2018-12-06) + +[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2) + +* Clippy has been relicensed under a dual MIT / Apache license. + See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more + information. +* With Rust 1.31, Clippy is no longer available via crates.io. The recommended + installation method is via `rustup component add clippy`. +* New lints: [`redundant_pattern_matching`], [`unnecessary_filter_map`], + [`unused_unit`], [`map_flatten`], [`mem_replace_option_with_none`] +* Fix ICE in `if_let_redundant_pattern_matching` +* Fix ICE in `needless_pass_by_value` when encountering a generic function + argument with a lifetime parameter +* Fix ICE in `needless_range_loop` +* Fix ICE in `single_char_pattern` when encountering a constant value +* Fix false positive in `assign_op_pattern` +* Fix false positive in `boxed_local` on trait implementations +* Fix false positive in `cmp_owned` +* Fix false positive in `collapsible_if` when conditionals have comments +* Fix false positive in `double_parens` +* Fix false positive in `excessive_precision` +* Fix false positive in `explicit_counter_loop` +* Fix false positive in `fn_to_numeric_cast_with_truncation` +* Fix false positive in `map_clone` +* Fix false positive in `new_ret_no_self` +* Fix false positive in `new_without_default` when `new` is unsafe +* Fix false positive in `type_complexity` when using extern types +* Fix false positive in `useless_format` +* Fix false positive in `wrong_self_convention` +* Fix incorrect suggestion for `excessive_precision` +* Fix incorrect suggestion for `expect_fun_call` +* Fix incorrect suggestion for `get_unwrap` +* Fix incorrect suggestion for `useless_format` +* `fn_to_numeric_cast_with_truncation` lint can be disabled again +* Improve suggestions for `manual_memcpy` +* Improve help message for `needless_lifetimes` + +## Rust 1.30 (2018-10-25) + +[14207503...125907ad](https://github.com/rust-lang/rust-clippy/compare/14207503...125907ad) + +* Deprecate `assign_ops` lint +* New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`], + [`needless_collect`], [`copy_iterator`] +* `cargo clippy -V` now includes the Clippy commit hash of the Rust + Clippy component +* Fix ICE in `implicit_hasher` +* Fix ICE when encountering `println!("{}" a);` +* Fix ICE when encountering a macro call in match statements +* Fix false positive in `default_trait_access` +* Fix false positive in `trivially_copy_pass_by_ref` +* Fix false positive in `similar_names` +* Fix false positive in `redundant_field_name` +* Fix false positive in `expect_fun_call` +* Fix false negative in `identity_conversion` +* Fix false negative in `explicit_counter_loop` +* Fix `range_plus_one` suggestion and false negative +* `print_with_newline` / `write_with_newline`: don't warn about string with several `\n`s in them +* Fix `useless_attribute` to also whitelist `unused_extern_crates` +* Fix incorrect suggestion for `single_char_pattern` +* Improve suggestion for `identity_conversion` lint +* Move `explicit_iter_loop` and `explicit_into_iter_loop` from `style` group to `pedantic` +* Move `range_plus_one` and `range_minus_one` from `nursery` group to `complexity` +* Move `shadow_unrelated` from `restriction` group to `pedantic` +* Move `indexing_slicing` from `pedantic` group to `restriction` + +## Rust 1.29 (2018-09-13) + +[v0.0.212...14207503](https://github.com/rust-lang/rust-clippy/compare/v0.0.212...14207503) + +* :tada: :tada: **Rust 1.29 is the first stable Rust that includes a bundled Clippy** :tada: + :tada: + You can now run `rustup component add clippy-preview` and then `cargo + clippy` to run Clippy. This should put an end to the continuous nightly + upgrades for Clippy users. +* Clippy now follows the Rust versioning scheme instead of its own +* Fix ICE when encountering a `while let (..) = x.iter()` construct +* Fix false positives in `use_self` +* Fix false positive in `trivially_copy_pass_by_ref` +* Fix false positive in `useless_attribute` lint +* Fix false positive in `print_literal` +* Fix `use_self` regressions +* Improve lint message for `neg_cmp_op_on_partial_ord` +* Improve suggestion highlight for `single_char_pattern` +* Improve suggestions for various print/write macro lints +* Improve website header + +## 0.0.212 (2018-07-10) * Rustup to *rustc 1.29.0-nightly (e06c87544 2018-07-06)* ## 0.0.211 @@ -31,7 +152,7 @@ All notable changes to this project will be documented in this file. ## 0.0.203 * Rustup to *rustc 1.28.0-nightly (a3085756e 2018-05-19)* -* clippy attributes are now of the form `clippy::cyclomatic_complexity` instead of `clippy(cyclomatic_complexity)` +* Clippy attributes are now of the form `clippy::cyclomatic_complexity` instead of `clippy(cyclomatic_complexity)` ## 0.0.202 * Rustup to *rustc 1.28.0-nightly (952f344cd 2018-05-18)* -- cgit 1.4.1-3-g733a5 From 0bac0149e7d60d1612405145c6e17f128b2675c7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 24 Jan 2019 20:32:18 +0100 Subject: Rustup Due to https://github.com/rust-lang/rust/pull/51285 --- clippy_lints/src/panic_unimplemented.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 61646613b11..f5c3a26e080 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -4,8 +4,8 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use syntax::ast::LitKind; -use syntax::ext::quote::rt::Span; use syntax::ptr::P; +use syntax_pos::Span; /// **What it does:** Checks for missing parameters in `panic!`. /// -- cgit 1.4.1-3-g733a5 From fffb2691a3d2d6bbd9521ff35d98301b2cdf4298 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 24 Jan 2019 20:39:00 +0100 Subject: gitattributes: Treat .fixed files as rust files --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 45bca848f8f..796afdbde90 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ * text=auto eol=lf *.rs rust +*.fixed linguist-language=Rust -- cgit 1.4.1-3-g733a5 From 1adc35703f22c9ee4e825ca0441961cbc832e5c8 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 25 Jan 2019 18:07:50 +0100 Subject: Add script to fetch GitHub PRs between two commits --- util/fetch_prs_between | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 util/fetch_prs_between diff --git a/util/fetch_prs_between b/util/fetch_prs_between new file mode 100755 index 00000000000..dbe73b1ba98 --- /dev/null +++ b/util/fetch_prs_between @@ -0,0 +1,20 @@ +#!/bin/sh + +# Fetches the merge commits between two git commits and prints the PR URL +# together with the full commit message +# +# If you want to use this to update the Clippy changelog, be sure to manually +# exclude the non-user facing changes like 'rustup' PRs, typo fixes, etc. + +first=$1 +last=$2 + +IFS=' +' +for pr in $(git log --oneline --grep "Merge #" --grep "Merge pull request" --grep "Auto merge of" "$first...$last" | sort -rn | uniq); do + id=$(echo $pr | rg -o '#[0-9]{3,5}' | cut -c 2-) + commit=$(echo $pr | cut -d' ' -f 1) + echo "URL: https://github.com/rust-lang/rust-clippy/pull/$id" + echo "$(git --no-pager show --pretty=medium $commit)" + echo "---------------------------------------------------------\n" +done -- cgit 1.4.1-3-g733a5 From 873fe11ca56d17de0fb52bea1adf27b02f00c018 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 25 Jan 2019 20:25:14 +0100 Subject: dependencies: update itertools from 0.7 to 0.8 --- clippy_dev/Cargo.toml | 2 +- clippy_dev/src/lib.rs | 25 +++++++++++++++---------- clippy_lints/Cargo.toml | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 5380ecd9814..3b4a11a5ee5 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] clap = "~2.32" -itertools = "0.7" +itertools = "0.8" regex = "1" lazy_static = "1.0" walkdir = "2" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 073b3a9e97f..1c7f372af6b 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -82,6 +82,7 @@ pub fn gen_lint_group_list(lints: Vec) -> Vec { } }) .sorted() + .collect::>() } /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. @@ -98,6 +99,7 @@ pub fn gen_modules_list(lints: Vec) -> Vec { .unique() .map(|module| format!("pub mod {};", module)) .sorted() + .collect::>() } /// Generates the list of lint links at the bottom of the README @@ -118,17 +120,20 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. pub fn gen_deprecated(lints: &[Lint]) -> Vec { - itertools::flatten(lints.iter().filter_map(|l| { - l.clone().deprecation.and_then(|depr_text| { - Some(vec![ - " store.register_removed(".to_string(), - format!(" \"{}\",", l.name), - format!(" \"{}\",", depr_text), - " );".to_string(), - ]) + lints + .iter() + .filter_map(|l| { + l.clone().deprecation.and_then(|depr_text| { + Some(vec![ + " store.register_removed(".to_string(), + format!(" \"{}\",", l.name), + format!(" \"{}\",", depr_text), + " );".to_string(), + ]) + }) }) - })) - .collect() + .flatten() + .collect::>() } /// Gathers all files in `src/clippy_lints` and gathers all lints inside diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 67dcffbfe1b..6c7f2d25569 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -18,7 +18,7 @@ edition = "2018" [dependencies] cargo_metadata = "0.6.2" -itertools = "0.7" +itertools = "0.8" lazy_static = "1.0.2" matches = "0.1.7" quine-mc_cluskey = "0.2.2" -- cgit 1.4.1-3-g733a5 From 1fe0cf6f071979745b4da761edff49478c081f3e Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 25 Jan 2019 20:27:07 +0100 Subject: chore(cargo/dependencies/cargo-metadata): Upgrade to 0.7.1 Closes https://github.com/rust-lang/rust-clippy/issues/3692. --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/wildcard_dependencies.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ce609bb1add..868f21c1a49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } -cargo_metadata = "0.6.2" +cargo_metadata = "0.7.1" compiletest_rs = "0.3.18" lazy_static = "1.0" serde_derive = "1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 6c7f2d25569..592ad5cde1c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -17,7 +17,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2018" [dependencies] -cargo_metadata = "0.6.2" +cargo_metadata = "0.7.1" itertools = "0.8" lazy_static = "1.0.2" matches = "0.1.7" diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 70ea387515a..c60d10cd009 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -66,7 +66,7 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { - let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { + let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { metadata } else { warning(cx, "could not read cargo metadata"); diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 073d3857c55..6a042fa8c0a 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -41,7 +41,7 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { - let metadata = if let Ok(metadata) = cargo_metadata::metadata_deps(None, true) { + let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().exec() { metadata } else { span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata"); diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index e3c35286251..fb88b1371f7 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -37,7 +37,7 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { - let metadata = if let Ok(metadata) = cargo_metadata::metadata(None) { + let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { metadata } else { span_lint(cx, WILDCARD_DEPENDENCIES, DUMMY_SP, "could not read cargo metadata"); -- cgit 1.4.1-3-g733a5 From 53ce28a96930bd6b2c3add3d4fc54bacab6c42e7 Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 25 Jan 2019 20:39:45 +0100 Subject: test(versioncheck): Fix version equality check --- tests/versioncheck.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 9e00571c9d5..fe4017ceb35 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -1,17 +1,16 @@ -use semver::VersionReq; - #[test] fn check_that_clippy_lints_has_the_same_version_as_clippy() { - let clippy_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); + let clippy_meta = cargo_metadata::MetadataCommand::new() + .exec() + .expect("could not obtain cargo metadata"); std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); - let clippy_lints_meta = cargo_metadata::metadata(None).expect("could not obtain cargo metadata"); + let clippy_lints_meta = cargo_metadata::MetadataCommand::new() + .exec() + .expect("could not obtain cargo metadata"); assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); for package in &clippy_meta.packages[0].dependencies { if package.name == "clippy_lints" { - assert_eq!( - VersionReq::parse(&clippy_lints_meta.packages[0].version).unwrap(), - package.req - ); + assert!(package.req.matches(&clippy_lints_meta.packages[0].version)); return; } } -- cgit 1.4.1-3-g733a5 From dc3bee796219534de7b4719d76c73672041ed786 Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 25 Jan 2019 21:28:09 +0100 Subject: test(versioncheck): Use .no_deps() --- tests/versioncheck.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index fe4017ceb35..f5d03c645df 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -1,10 +1,12 @@ #[test] fn check_that_clippy_lints_has_the_same_version_as_clippy() { let clippy_meta = cargo_metadata::MetadataCommand::new() + .no_deps() .exec() .expect("could not obtain cargo metadata"); std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap(); let clippy_lints_meta = cargo_metadata::MetadataCommand::new() + .no_deps() .exec() .expect("could not obtain cargo metadata"); assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version); -- cgit 1.4.1-3-g733a5 From 94a6eb0695679c46387075c70efaaffb5b73cee0 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 26 Jan 2019 11:10:13 +0200 Subject: Fix dogfood tests on Appveyor This introduces a work-around for a bug in rustup.rs when excuting cargo from a custom toolchain. Instead of trusting rustup to invoke cargo from one of the release channels we just invoke nightly cargo directly. --- src/main.rs | 6 ++++++ tests/dogfood.rs | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index eefababb96d..20466fc567d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,6 +97,12 @@ where }) .map(|p| ("CARGO_TARGET_DIR", p)); + // Run the dogfood tests directly on nightly cargo. This is required due + // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118. + if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) { + args.insert(0, "+nightly".to_string()); + } + let exit_status = std::process::Command::new("cargo") .args(&args) .env("RUSTC_WRAPPER", path) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 87fe5887bcc..27a3d84da41 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,6 +1,6 @@ #[test] fn dogfood() { - if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { + if option_env!("RUSTC_TEST_SUITE").is_some() { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -30,7 +30,7 @@ fn dogfood() { #[test] fn dogfood_tests() { - if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { + if option_env!("RUSTC_TEST_SUITE").is_some() { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); -- cgit 1.4.1-3-g733a5 From 18cacbabb43f2fd87e20706be852e62aea282257 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sat, 26 Jan 2019 11:55:54 +0200 Subject: Incorporate review suggestions --- clippy_lints/src/methods/mod.rs | 79 +++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 0571f1d92d7..4126b78e676 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1148,6 +1148,48 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa /// Checks for the `EXPECT_FUN_CALL` lint. fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { + // Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or + // `&str` + fn get_arg_root<'a>(cx: &LateContext<'_, '_>, arg: &'a hir::Expr) -> &'a hir::Expr { + let mut arg_root = arg; + loop { + arg_root = match &arg_root.node { + hir::ExprKind::AddrOf(_, expr) => expr, + hir::ExprKind::MethodCall(method_name, _, call_args) => { + if call_args.len() == 1 + && (method_name.ident.name == "as_str" || method_name.ident.name == "as_ref") + && { + let arg_type = cx.tables.expr_ty(&call_args[0]); + let base_type = walk_ptrs_ty(arg_type); + base_type.sty == ty::Str || match_type(cx, base_type, &paths::STRING) + } + { + &call_args[0] + } else { + break; + } + }, + _ => break, + }; + } + arg_root + } + + // Only `&'static str` or `String` can be used directly in the `panic!`. Other types should be + // converted to string. + fn requires_to_string(cx: &LateContext<'_, '_>, arg: &hir::Expr) -> bool { + let arg_ty = cx.tables.expr_ty(arg); + if match_type(cx, arg_ty, &paths::STRING) { + return false; + } + if let ty::Ref(ty::ReStatic, ty, ..) = arg_ty.sty { + if ty.sty == ty::Str { + return false; + } + }; + true + } + fn generate_format_arg_snippet( cx: &LateContext<'_, '_>, a: &hir::Expr, @@ -1195,29 +1237,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: return; }; - // Strip off `&`, `as_ref()` and `as_str()` until we're left with either a `String` or `&str` - // which we call `arg_root`. - let mut arg_root = &args[1]; - loop { - arg_root = match &arg_root.node { - hir::ExprKind::AddrOf(_, expr) => expr, - hir::ExprKind::MethodCall(method_name, _, call_args) => { - if call_args.len() == 1 - && (method_name.ident.name == "as_str" || method_name.ident.name == "as_ref") - && { - let arg_type = cx.tables.expr_ty(&call_args[0]); - let base_type = walk_ptrs_ty(arg_type); - base_type.sty == ty::Str || match_type(cx, base_type, &paths::STRING) - } - { - &call_args[0] - } else { - break; - } - }, - _ => break, - }; - } + let arg_root = get_arg_root(cx, &args[1]); let span_replace_word = method_span.with_hi(expr.span.hi()); @@ -1230,7 +1250,6 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: let fmt_spec = &format_args[0]; let fmt_args = &format_args[1]; - let mut applicability = Applicability::MachineApplicable; let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()]; args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability)); @@ -1252,18 +1271,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: } } - // If root_arg is `&'static str` or `String` we can use it directly in the `panic!` call otherwise - // we must use `to_string` to convert it. let mut arg_root_snippet: Cow<'_, _> = snippet_with_applicability(cx, arg_root.span, "..", &mut applicability); - let arg_root_ty = cx.tables.expr_ty(arg_root); - let mut requires_conv = !match_type(cx, arg_root_ty, &paths::STRING); - if let ty::Ref(ty::ReStatic, ty, ..) = arg_root_ty.sty { - if ty.sty == ty::Str { - requires_conv = false; - } - }; - - if requires_conv { + if requires_to_string(cx, arg_root) { arg_root_snippet.to_mut().push_str(".to_string()"); } -- cgit 1.4.1-3-g733a5 From 8c416c31975764c97812aa33eaa10c74d521d47e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 26 Jan 2019 09:49:55 +0100 Subject: Prevent incorrect cast_lossless suggestion in const_fn `::from` is not a const fn, so applying the suggestion of `cast_lossless` would fail to compile. The fix is to skip the lint if the cast is found inside a const fn. --- clippy_lints/src/utils/mod.rs | 4 ++++ tests/ui/cast_lossless_float.fixed | 12 ++++++++++-- tests/ui/cast_lossless_float.rs | 12 ++++++++++-- tests/ui/cast_lossless_float.stderr | 20 +++++++++---------- tests/ui/cast_lossless_integer.fixed | 12 ++++++++++-- tests/ui/cast_lossless_integer.rs | 12 ++++++++++-- tests/ui/cast_lossless_integer.stderr | 36 +++++++++++++++++------------------ 7 files changed, 72 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c83b0f155fc..9df0896068a 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -82,6 +82,10 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { node: ItemKind::Static(..), .. }) => true, + Node::Item(&Item { + node: ItemKind::Fn(_, header, ..), + .. + }) => header.constness == Constness::Const, _ => false, } } diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index 22df1137922..cc3b007ee5d 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -1,7 +1,8 @@ // run-rustfix -#[warn(clippy::cast_lossless)] -#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] +#![warn(clippy::cast_lossless)] + fn main() { // Test clippy::cast_lossless with casts to floating-point types f32::from(1i8); @@ -15,3 +16,10 @@ fn main() { f64::from(1i32); f64::from(1u32); } + +// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, +// so we skip the lint if the expression is in a const fn. +// See #3656 +const fn abc(input: f32) -> f64 { + input as f64 +} diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index c86b4d05f28..6684afa0ede 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,7 +1,8 @@ // run-rustfix -#[warn(clippy::cast_lossless)] -#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] +#![warn(clippy::cast_lossless)] + fn main() { // Test clippy::cast_lossless with casts to floating-point types 1i8 as f32; @@ -15,3 +16,10 @@ fn main() { 1i32 as f64; 1u32 as f64; } + +// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, +// so we skip the lint if the expression is in a const fn. +// See #3656 +const fn abc(input: f32) -> f64 { + input as f64 +} diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index c2b01e83bbe..691ce72399e 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,5 +1,5 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:7:5 + --> $DIR/cast_lossless_float.rs:8:5 | LL | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` @@ -7,55 +7,55 @@ LL | 1i8 as f32; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:8:5 + --> $DIR/cast_lossless_float.rs:9:5 | LL | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:9:5 + --> $DIR/cast_lossless_float.rs:10:5 | LL | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:10:5 + --> $DIR/cast_lossless_float.rs:11:5 | LL | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:11:5 + --> $DIR/cast_lossless_float.rs:12:5 | LL | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:12:5 + --> $DIR/cast_lossless_float.rs:13:5 | LL | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:13:5 + --> $DIR/cast_lossless_float.rs:14:5 | LL | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:14:5 + --> $DIR/cast_lossless_float.rs:15:5 | LL | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:15:5 + --> $DIR/cast_lossless_float.rs:16:5 | LL | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:16:5 + --> $DIR/cast_lossless_float.rs:17:5 | LL | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index e5b33d5e1b0..6c384e7d38c 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -1,7 +1,8 @@ // run-rustfix -#[warn(clippy::cast_lossless)] -#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] +#![warn(clippy::cast_lossless)] + fn main() { // Test clippy::cast_lossless with casts to integer types i16::from(1i8); @@ -23,3 +24,10 @@ fn main() { i64::from(1u32); u64::from(1u32); } + +// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, +// so we skip the lint if the expression is in a const fn. +// See #3656 +const fn abc(input: u16) -> u32 { + input as u32 +} diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 61170625c8a..35970bca88c 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,7 +1,8 @@ // run-rustfix -#[warn(clippy::cast_lossless)] -#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] +#![warn(clippy::cast_lossless)] + fn main() { // Test clippy::cast_lossless with casts to integer types 1i8 as i16; @@ -23,3 +24,10 @@ fn main() { 1u32 as i64; 1u32 as u64; } + +// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, +// so we skip the lint if the expression is in a const fn. +// See #3656 +const fn abc(input: u16) -> u32 { + input as u32 +} diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index ac385298ecb..ff98ec84a14 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,5 +1,5 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:7:5 + --> $DIR/cast_lossless_integer.rs:8:5 | LL | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` @@ -7,103 +7,103 @@ LL | 1i8 as i16; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:8:5 + --> $DIR/cast_lossless_integer.rs:9:5 | LL | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:9:5 + --> $DIR/cast_lossless_integer.rs:10:5 | LL | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:10:5 + --> $DIR/cast_lossless_integer.rs:11:5 | LL | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:11:5 + --> $DIR/cast_lossless_integer.rs:12:5 | LL | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:12:5 + --> $DIR/cast_lossless_integer.rs:13:5 | LL | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:13:5 + --> $DIR/cast_lossless_integer.rs:14:5 | LL | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:14:5 + --> $DIR/cast_lossless_integer.rs:15:5 | LL | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:15:5 + --> $DIR/cast_lossless_integer.rs:16:5 | LL | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:17:5 | LL | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:18:5 | LL | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:19:5 | LL | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:20:5 | LL | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:21:5 | LL | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:22:5 | LL | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:23:5 | LL | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:24:5 | LL | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:24:5 + --> $DIR/cast_lossless_integer.rs:25:5 | LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` -- cgit 1.4.1-3-g733a5 From 59e176d4af9ac2df0eb1a5572be03ec6e1108a19 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 26 Jan 2019 12:50:40 +0100 Subject: Remove unsafe_vector_initialization from added lints It was deprecated before it reached a stable release, no need to include it. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21e91c666b7..b773422b015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,8 @@ All notable changes to this project will be documented in this file. [2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be) -* New lints: [`slow_vector_initialization`], [`unsafe_vector_initialization`], - [`mem_discriminant_non_enum`], [`redundant_clone`], [`wildcard_dependencies`], +* New lints: [`slow_vector_initialization`], [`mem_discriminant_non_enum`], + [`redundant_clone`], [`wildcard_dependencies`], [`into_iter_on_ref`], [`into_iter_on_array`], [`deprecated_cfg_attr`], [`mem_discriminant_non_enum`], [`cargo_common_metadata`] * Add support for `u128` and `i128` to integer related lints -- cgit 1.4.1-3-g733a5 From e9e0a7e3bd0619626ad03db4b641a368d3555bcc Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 26 Jan 2019 20:40:55 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/57726 --- clippy_lints/src/approx_const.rs | 4 ++ clippy_lints/src/arithmetic.rs | 4 ++ clippy_lints/src/assertions_on_constants.rs | 4 ++ clippy_lints/src/assign_ops.rs | 4 ++ clippy_lints/src/attrs.rs | 8 ++++ clippy_lints/src/bit_mask.rs | 3 ++ clippy_lints/src/blacklisted_name.rs | 3 ++ clippy_lints/src/block_in_if_condition.rs | 4 ++ clippy_lints/src/booleans.rs | 4 ++ clippy_lints/src/bytecount.rs | 4 ++ clippy_lints/src/cargo_common_metadata.rs | 4 ++ clippy_lints/src/collapsible_if.rs | 4 ++ clippy_lints/src/const_static_lifetime.rs | 4 ++ clippy_lints/src/copies.rs | 4 ++ clippy_lints/src/copy_iterator.rs | 4 ++ clippy_lints/src/cyclomatic_complexity.rs | 4 ++ clippy_lints/src/default_trait_access.rs | 4 ++ clippy_lints/src/derive.rs | 4 ++ clippy_lints/src/doc.rs | 4 ++ clippy_lints/src/double_comparison.rs | 4 ++ clippy_lints/src/double_parens.rs | 4 ++ clippy_lints/src/drop_forget_ref.rs | 4 ++ clippy_lints/src/duration_subsec.rs | 4 ++ clippy_lints/src/else_if_without_else.rs | 4 ++ clippy_lints/src/empty_enum.rs | 4 ++ clippy_lints/src/entry.rs | 4 ++ clippy_lints/src/enum_clike.rs | 4 ++ clippy_lints/src/enum_glob_use.rs | 4 ++ clippy_lints/src/enum_variants.rs | 4 ++ clippy_lints/src/eq_op.rs | 4 ++ clippy_lints/src/erasing_op.rs | 4 ++ clippy_lints/src/escape.rs | 4 ++ clippy_lints/src/eta_reduction.rs | 4 ++ clippy_lints/src/eval_order_dependence.rs | 4 ++ clippy_lints/src/excessive_precision.rs | 4 ++ clippy_lints/src/explicit_write.rs | 4 ++ clippy_lints/src/fallible_impl_from.rs | 4 ++ clippy_lints/src/format.rs | 4 ++ clippy_lints/src/formatting.rs | 4 ++ clippy_lints/src/functions.rs | 4 ++ clippy_lints/src/identity_conversion.rs | 4 ++ clippy_lints/src/identity_op.rs | 4 ++ clippy_lints/src/if_not_else.rs | 4 ++ clippy_lints/src/implicit_return.rs | 4 ++ clippy_lints/src/indexing_slicing.rs | 4 ++ clippy_lints/src/infallible_destructuring_match.rs | 4 ++ clippy_lints/src/infinite_iter.rs | 4 ++ clippy_lints/src/inherent_impl.rs | 4 ++ clippy_lints/src/inline_fn_without_body.rs | 4 ++ clippy_lints/src/int_plus_one.rs | 4 ++ clippy_lints/src/invalid_ref.rs | 4 ++ clippy_lints/src/items_after_statements.rs | 4 ++ clippy_lints/src/large_enum_variant.rs | 4 ++ clippy_lints/src/len_zero.rs | 4 ++ clippy_lints/src/let_if_seq.rs | 4 ++ clippy_lints/src/lib.rs | 13 +++++-- clippy_lints/src/lifetimes.rs | 4 ++ clippy_lints/src/literal_representation.rs | 8 ++++ clippy_lints/src/loops.rs | 4 ++ clippy_lints/src/map_clone.rs | 4 ++ clippy_lints/src/map_unit_fn.rs | 4 ++ clippy_lints/src/matches.rs | 4 ++ clippy_lints/src/mem_discriminant.rs | 4 ++ clippy_lints/src/mem_forget.rs | 4 ++ clippy_lints/src/mem_replace.rs | 4 ++ clippy_lints/src/methods/mod.rs | 4 ++ clippy_lints/src/minmax.rs | 4 ++ clippy_lints/src/misc.rs | 4 ++ clippy_lints/src/misc_early.rs | 4 ++ clippy_lints/src/missing_doc.rs | 4 ++ clippy_lints/src/missing_inline.rs | 4 ++ clippy_lints/src/multiple_crate_versions.rs | 4 ++ clippy_lints/src/mut_mut.rs | 4 ++ clippy_lints/src/mut_reference.rs | 4 ++ clippy_lints/src/mutex_atomic.rs | 4 ++ clippy_lints/src/needless_bool.rs | 8 ++++ clippy_lints/src/needless_borrow.rs | 4 ++ clippy_lints/src/needless_borrowed_ref.rs | 4 ++ clippy_lints/src/needless_continue.rs | 4 ++ clippy_lints/src/needless_pass_by_value.rs | 4 ++ clippy_lints/src/needless_update.rs | 4 ++ clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 ++ clippy_lints/src/neg_multiply.rs | 4 ++ clippy_lints/src/new_without_default.rs | 4 ++ clippy_lints/src/no_effect.rs | 4 ++ clippy_lints/src/non_copy_const.rs | 4 ++ clippy_lints/src/non_expressive_names.rs | 4 ++ clippy_lints/src/ok_if_let.rs | 4 ++ clippy_lints/src/open_options.rs | 4 ++ clippy_lints/src/overflow_check_conditional.rs | 4 ++ clippy_lints/src/panic_unimplemented.rs | 4 ++ clippy_lints/src/partialeq_ne_impl.rs | 4 ++ clippy_lints/src/precedence.rs | 4 ++ clippy_lints/src/ptr.rs | 4 ++ clippy_lints/src/ptr_offset_with_cast.rs | 4 ++ clippy_lints/src/question_mark.rs | 4 ++ clippy_lints/src/ranges.rs | 4 ++ clippy_lints/src/redundant_clone.rs | 4 ++ clippy_lints/src/redundant_field_names.rs | 4 ++ clippy_lints/src/redundant_pattern_matching.rs | 4 ++ clippy_lints/src/reference.rs | 8 ++++ clippy_lints/src/regex.rs | 4 ++ clippy_lints/src/replace_consts.rs | 4 ++ clippy_lints/src/returns.rs | 4 ++ clippy_lints/src/serde_api.rs | 4 ++ clippy_lints/src/shadow.rs | 4 ++ clippy_lints/src/slow_vector_initialization.rs | 4 ++ clippy_lints/src/strings.rs | 8 ++++ clippy_lints/src/suspicious_trait_impl.rs | 4 ++ clippy_lints/src/swap.rs | 4 ++ clippy_lints/src/temporary_assignment.rs | 4 ++ clippy_lints/src/transmute.rs | 4 ++ clippy_lints/src/trivially_copy_pass_by_ref.rs | 4 ++ clippy_lints/src/types.rs | 44 ++++++++++++++++++++++ clippy_lints/src/unicode.rs | 4 ++ clippy_lints/src/unsafe_removed_from_name.rs | 4 ++ clippy_lints/src/unused_io_amount.rs | 4 ++ clippy_lints/src/unused_label.rs | 4 ++ clippy_lints/src/unwrap.rs | 4 ++ clippy_lints/src/use_self.rs | 4 ++ clippy_lints/src/utils/author.rs | 4 ++ clippy_lints/src/utils/inspector.rs | 4 ++ clippy_lints/src/utils/internal_lints.rs | 15 ++++++++ clippy_lints/src/vec.rs | 4 ++ clippy_lints/src/wildcard_dependencies.rs | 4 ++ clippy_lints/src/write.rs | 4 ++ clippy_lints/src/zero_div_zero.rs | 4 ++ src/driver.rs | 2 +- tests/ui/lint_without_lint_pass.rs | 4 ++ 129 files changed, 588 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 8410408312f..337139e1b1d 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -60,6 +60,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } + + fn name(&self) -> &'static str { + "ApproxConstant" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index efa53ff94c3..e14c79374ba 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -52,6 +52,10 @@ impl LintPass for Arithmetic { fn get_lints(&self) -> LintArray { lint_array!(INTEGER_ARITHMETIC, FLOAT_ARITHMETIC) } + + fn name(&self) -> &'static str { + "Arithmetic" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index a148cb1c3a6..d420de3a4db 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -34,6 +34,10 @@ impl LintPass for AssertionsOnConstants { fn get_lints(&self) -> LintArray { lint_array![ASSERTIONS_ON_CONSTANTS] } + + fn name(&self) -> &'static str { + "AssertionsOnConstants" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index ad77ee3a3fa..329bab5cf1c 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -57,6 +57,10 @@ impl LintPass for AssignOps { fn get_lints(&self) -> LintArray { lint_array!(ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP) } + + fn name(&self) -> &'static str { + "AssignOps" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 9e4dd52c414..4a5eb378d5a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -199,6 +199,10 @@ impl LintPass for AttrPass { UNKNOWN_CLIPPY_LINTS, ) } + + fn name(&self) -> &'static str { + "Attributes" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { @@ -500,6 +504,10 @@ impl LintPass for CfgAttrPass { fn get_lints(&self) -> LintArray { lint_array!(DEPRECATED_CFG_ATTR,) } + + fn name(&self) -> &'static str { + "DeprecatedCfgAttribute" + } } impl EarlyLintPass for CfgAttrPass { diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index b08d9961d25..ef0943875d2 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -108,6 +108,9 @@ impl LintPass for BitMask { fn get_lints(&self) -> LintArray { lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK) } + fn name(&self) -> &'static str { + "BitMask" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 64b3be8f302..9606b2eda32 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -37,6 +37,9 @@ impl LintPass for BlackListedName { fn get_lints(&self) -> LintArray { lint_array!(BLACKLISTED_NAME) } + fn name(&self) -> &'static str { + "BlacklistedName" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 6e850931e6b..8abcfb4cfd6 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -49,6 +49,10 @@ impl LintPass for BlockInIfCondition { fn get_lints(&self) -> LintArray { lint_array!(BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT) } + + fn name(&self) -> &'static str { + "BlockInIfCondition" + } } struct ExVisitor<'a, 'tcx: 'a> { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 8b1a56e3b6e..6b53dd908de 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -58,6 +58,10 @@ impl LintPass for NonminimalBool { fn get_lints(&self) -> LintArray { lint_array!(NONMINIMAL_BOOL, LOGIC_BUG) } + + fn name(&self) -> &'static str { + "NonminimalBool" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 794b43f4db5..b677ef71583 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -38,6 +38,10 @@ impl LintPass for ByteCount { fn get_lints(&self) -> LintArray { lint_array!(NAIVE_BYTECOUNT) } + + fn name(&self) -> &'static str { + "ByteCount" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index c60d10cd009..124b11cc78c 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -62,6 +62,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(CARGO_COMMON_METADATA) } + + fn name(&self) -> &'static str { + "CargoCommonMetadata" + } } impl EarlyLintPass for Pass { diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 10cbc9e6ccd..c236706f02f 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -78,6 +78,10 @@ impl LintPass for CollapsibleIf { fn get_lints(&self) -> LintArray { lint_array!(COLLAPSIBLE_IF) } + + fn name(&self) -> &'static str { + "CollapsibleIf" + } } impl EarlyLintPass for CollapsibleIf { diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 229a411ce06..7315184c8bd 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -32,6 +32,10 @@ impl LintPass for StaticConst { fn get_lints(&self) -> LintArray { lint_array!(CONST_STATIC_LIFETIME) } + + fn name(&self) -> &'static str { + "StaticConst" + } } impl StaticConst { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 3676519adc1..6bb75cf8064 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -110,6 +110,10 @@ impl LintPass for CopyAndPaste { fn get_lints(&self) -> LintArray { lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS] } + + fn name(&self) -> &'static str { + "CopyAndPaste" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 3d0df7424f1..59eef9e39dc 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -35,6 +35,10 @@ impl LintPass for CopyIterator { fn get_lints(&self) -> LintArray { lint_array![COPY_ITERATOR] } + + fn name(&self) -> &'static str { + "CopyIterator" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 9170f1e8ecf..c6358aed4bd 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -42,6 +42,10 @@ impl LintPass for CyclomaticComplexity { fn get_lints(&self) -> LintArray { lint_array!(CYCLOMATIC_COMPLEXITY) } + + fn name(&self) -> &'static str { + "CyclomaticComplexity" + } } impl CyclomaticComplexity { diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index c4b39dc0f0a..7b3899b2f49 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -35,6 +35,10 @@ impl LintPass for DefaultTraitAccess { fn get_lints(&self) -> LintArray { lint_array!(DEFAULT_TRAIT_ACCESS) } + + fn name(&self) -> &'static str { + "DefaultTraitAccess" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index a2bf0098ab8..9580fbbe4c1 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -68,6 +68,10 @@ impl LintPass for Derive { fn get_lints(&self) -> LintArray { lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ) } + + fn name(&self) -> &'static str { + "Derive" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index e96ef9ac621..87135fb88b6 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -48,6 +48,10 @@ impl LintPass for Doc { fn get_lints(&self) -> LintArray { lint_array![DOC_MARKDOWN] } + + fn name(&self) -> &'static str { + "DocMarkdown" + } } impl EarlyLintPass for Doc { diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index fc4af438d44..6c6b53b0b98 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -37,6 +37,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DOUBLE_COMPARISONS) } + + fn name(&self) -> &'static str { + "DoubleComparisons" + } } impl<'a, 'tcx> Pass { diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 38381b069f0..71b2f5f51a7 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -29,6 +29,10 @@ impl LintPass for DoubleParens { fn get_lints(&self) -> LintArray { lint_array!(DOUBLE_PARENS) } + + fn name(&self) -> &'static str { + "DoubleParens" + } } impl EarlyLintPass for DoubleParens { diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 4a2a38f6ea1..b437d603005 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -112,6 +112,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY) } + + fn name(&self) -> &'static str { + "DropForgetRef" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 3ac98c71644..3935099fdce 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -36,6 +36,10 @@ impl LintPass for DurationSubsec { fn get_lints(&self) -> LintArray { lint_array!(DURATION_SUBSEC) } + + fn name(&self) -> &'static str { + "DurationSubsec" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index f633d81764b..c01ad486484 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -46,6 +46,10 @@ impl LintPass for ElseIfWithoutElse { fn get_lints(&self) -> LintArray { lint_array!(ELSE_IF_WITHOUT_ELSE) } + + fn name(&self) -> &'static str { + "ElseIfWithoutElse" + } } impl EarlyLintPass for ElseIfWithoutElse { diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 71e84bf1b47..ab80625f685 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -30,6 +30,10 @@ impl LintPass for EmptyEnum { fn get_lints(&self) -> LintArray { lint_array!(EMPTY_ENUM) } + + fn name(&self) -> &'static str { + "EmptyEnum" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 646a2569bbe..8de881d0425 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -44,6 +44,10 @@ impl LintPass for HashMapLint { fn get_lints(&self) -> LintArray { lint_array!(MAP_ENTRY) } + + fn name(&self) -> &'static str { + "HashMap" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index ab9bc6cd0ca..46501d55497 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -40,6 +40,10 @@ impl LintPass for UnportableVariant { fn get_lints(&self) -> LintArray { lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) } + + fn name(&self) -> &'static str { + "UnportableVariant" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 9402c2a5aad..4806736682f 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -32,6 +32,10 @@ impl LintPass for EnumGlobUse { fn get_lints(&self) -> LintArray { lint_array!(ENUM_GLOB_USE) } + + fn name(&self) -> &'static str { + "EnumGlobUse" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index ffaa8b2811a..74d61c0f6a0 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -124,6 +124,10 @@ impl LintPass for EnumVariantNames { MODULE_INCEPTION ) } + + fn name(&self) -> &'static str { + "EnumVariantNames" + } } fn var2str(var: &Variant) -> LocalInternedString { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 93132534a76..38c9a05b44c 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -52,6 +52,10 @@ impl LintPass for EqOp { fn get_lints(&self) -> LintArray { lint_array!(EQ_OP, OP_REF) } + + fn name(&self) -> &'static str { + "EqOp" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index fea31855543..a1d851377eb 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -32,6 +32,10 @@ impl LintPass for ErasingOp { fn get_lints(&self) -> LintArray { lint_array!(ERASING_OP) } + + fn name(&self) -> &'static str { + "ErasingOp" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index a7b47fd1e54..a276579b1b5 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -52,6 +52,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(BOXED_LOCAL) } + + fn name(&self) -> &'static str { + "BoxedLocal" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 624d215492f..cc86aee7def 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -36,6 +36,10 @@ impl LintPass for EtaPass { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_CLOSURE) } + + fn name(&self) -> &'static str { + "EtaReduction" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 2b4b0d40239..8c933ef74d2 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -61,6 +61,10 @@ impl LintPass for EvalOrderDependence { fn get_lints(&self) -> LintArray { lint_array!(EVAL_ORDER_DEPENDENCE, DIVERGING_SUB_EXPRESSION) } + + fn name(&self) -> &'static str { + "EvalOrderDependence" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index f17b82ab33d..27e033f688d 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -41,6 +41,10 @@ impl LintPass for ExcessivePrecision { fn get_lints(&self) -> LintArray { lint_array!(EXCESSIVE_PRECISION) } + + fn name(&self) -> &'static str { + "ExcessivePrecision" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 0bbc85a0416..2be2bb058bb 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -31,6 +31,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(EXPLICIT_WRITE) } + + fn name(&self) -> &'static str { + "ExplicitWrite" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 2d11b3bd947..3669e8998a4 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -34,6 +34,10 @@ impl LintPass for FallibleImplFrom { fn get_lints(&self) -> LintArray { lint_array!(FALLIBLE_IMPL_FROM) } + + fn name(&self) -> &'static str { + "FallibleImpleFrom" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 90e19af15d0..f14c281fcc9 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -40,6 +40,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array![USELESS_FORMAT] } + + fn name(&self) -> &'static str { + "UselessFormat" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 6459e7b81c6..ecc6f9565d0 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -89,6 +89,10 @@ impl LintPass for Formatting { POSSIBLE_MISSING_COMMA ) } + + fn name(&self) -> &'static str { + "Formatting" + } } impl EarlyLintPass for Formatting { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index a2b7d31b183..cb69e96c8e4 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -74,6 +74,10 @@ impl LintPass for Functions { fn get_lints(&self) -> LintArray { lint_array!(TOO_MANY_ARGUMENTS, NOT_UNSAFE_PTR_ARG_DEREF) } + + fn name(&self) -> &'static str { + "Functions" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index d0e1ee57748..2c0e389119f 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -34,6 +34,10 @@ impl LintPass for IdentityConversion { fn get_lints(&self) -> LintArray { lint_array!(IDENTITY_CONVERSION) } + + fn name(&self) -> &'static str { + "IdentityConversion" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 862c289fce1..89d41c79629 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -30,6 +30,10 @@ impl LintPass for IdentityOp { fn get_lints(&self) -> LintArray { lint_array!(IDENTITY_OP) } + + fn name(&self) -> &'static str { + "IdentityOp" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 19554c7e207..38213141de3 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -44,6 +44,10 @@ impl LintPass for IfNotElse { fn get_lints(&self) -> LintArray { lint_array!(IF_NOT_ELSE) } + + fn name(&self) -> &'static str { + "IfNotElse" + } } impl EarlyLintPass for IfNotElse { diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 073c37eefc5..b25b3bce652 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -114,6 +114,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(IMPLICIT_RETURN) } + + fn name(&self) -> &'static str { + "ImplicitReturn" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index b4893c759c8..19e2283dc07 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -91,6 +91,10 @@ impl LintPass for IndexingSlicing { fn get_lints(&self) -> LintArray { lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) } + + fn name(&self) -> &'static str { + "IndexSlicing" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 5d0c5a4a79d..704b583f813 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -47,6 +47,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INFALLIBLE_DESTRUCTURING_MATCH) } + + fn name(&self) -> &'static str { + "InfallibleDestructingMatch" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index c25c4ec488f..9f2bcd48787 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -45,6 +45,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INFINITE_ITER, MAYBE_INFINITE_ITER) } + + fn name(&self) -> &'static str { + "InfiniteIter" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 52aa73d7a10..5585ce4cbef 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -56,6 +56,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MULTIPLE_INHERENT_IMPL) } + + fn name(&self) -> &'static str { + "MultipleInherientImpl" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index a092f86658b..bdc17ab4624 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -35,6 +35,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INLINE_FN_WITHOUT_BODY) } + + fn name(&self) -> &'static str { + "InlineFnWithoutBody" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 547052f3429..aee3b7cc542 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -36,6 +36,10 @@ impl LintPass for IntPlusOne { fn get_lints(&self) -> LintArray { lint_array!(INT_PLUS_ONE) } + + fn name(&self) -> &'static str { + "IntPlusOne" + } } // cases: diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 03b099b4393..90649535958 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -32,6 +32,10 @@ impl LintPass for InvalidRef { fn get_lints(&self) -> LintArray { lint_array!(INVALID_REF) } + + fn name(&self) -> &'static str { + "InvalidRef" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 0af8c3dd5cb..dd283d897a5 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -40,6 +40,10 @@ impl LintPass for ItemsAfterStatements { fn get_lints(&self) -> LintArray { lint_array!(ITEMS_AFTER_STATEMENTS) } + + fn name(&self) -> &'static str { + "ItemsAfterStatements" + } } impl EarlyLintPass for ItemsAfterStatements { diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index d5bc2a8fad7..0b3cf07e50a 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -46,6 +46,10 @@ impl LintPass for LargeEnumVariant { fn get_lints(&self) -> LintArray { lint_array!(LARGE_ENUM_VARIANT) } + + fn name(&self) -> &'static str { + "LargeEnumVariant" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b15ba5a4783..2764cd6ffd9 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -77,6 +77,10 @@ impl LintPass for LenZero { fn get_lints(&self) -> LintArray { lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) } + + fn name(&self) -> &'static str { + "LenZero" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 5154c6d4d08..3eb25cfb36a 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -60,6 +60,10 @@ impl LintPass for LetIfSeq { fn get_lints(&self) -> LintArray { lint_array!(USELESS_LET_IF_SEQ) } + + fn name(&self) -> &'static str { + "LetIfSeq" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9d77c3c64a2..4683d353ccf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -212,15 +212,22 @@ pub fn register_pre_expansion_lints( store: &mut rustc::lint::LintStore, conf: &Conf, ) { - store.register_pre_expansion_pass(Some(session), box write::Pass); - store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames); + store.register_pre_expansion_pass(Some(session), true, false, box write::Pass); store.register_pre_expansion_pass( Some(session), + true, + false, + box redundant_field_names::RedundantFieldNames, + ); + store.register_pre_expansion_pass( + Some(session), + true, + false, box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold: conf.single_char_binding_names_threshold, }, ); - store.register_pre_expansion_pass(Some(session), box attrs::CfgAttrPass); + store.register_pre_expansion_pass(Some(session), true, false, box attrs::CfgAttrPass); } pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index f7512446c87..5562d750dac 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -61,6 +61,10 @@ impl LintPass for LifetimePass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES) } + + fn name(&self) -> &'static str { + "LifeTimes" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index d6e6ffa61b3..801e54f055c 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -346,6 +346,10 @@ impl LintPass for LiteralDigitGrouping { MISTYPED_LITERAL_SUFFIXES, ) } + + fn name(&self) -> &'static str { + "LiteralDigitGrouping" + } } impl EarlyLintPass for LiteralDigitGrouping { @@ -493,6 +497,10 @@ impl LintPass for LiteralRepresentation { fn get_lints(&self) -> LintArray { lint_array!(DECIMAL_LITERAL_REPRESENTATION) } + + fn name(&self) -> &'static str { + "DecimalLiteralRepresentation" + } } impl EarlyLintPass for LiteralRepresentation { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 70ff86087ea..64e76c09989 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -465,6 +465,10 @@ impl LintPass for Pass { WHILE_IMMUTABLE_CONDITION, ) } + + fn name(&self) -> &'static str { + "Loops" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4db0ca759db..49bd8f650e5 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -46,6 +46,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MAP_CLONE) } + + fn name(&self) -> &'static str { + "MapClone" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index ad5761f5f04..bd4b4043824 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -81,6 +81,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN) } + + fn name(&self) -> &'static str { + "MapUnit" + } } fn is_unit_type(ty: ty::Ty<'_>) -> bool { diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b003da44236..adb8dab5c42 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -202,6 +202,10 @@ impl LintPass for MatchPass { MATCH_AS_REF ) } + + fn name(&self) -> &'static str { + "Matches" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index a75959e58fa..a40b1eab2c7 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -31,6 +31,10 @@ impl LintPass for MemDiscriminant { fn get_lints(&self) -> LintArray { lint_array![MEM_DISCRIMINANT_NON_ENUM] } + + fn name(&self) -> &'static str { + "MemDiscriminant" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index f83a8b5f7fe..0f25070318e 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -27,6 +27,10 @@ impl LintPass for MemForget { fn get_lints(&self) -> LintArray { lint_array![MEM_FORGET] } + + fn name(&self) -> &'static str { + "MemForget" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index d649895e33f..1b43794bcb7 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -36,6 +36,10 @@ impl LintPass for MemReplace { fn get_lints(&self) -> LintArray { lint_array![MEM_REPLACE_OPTION_WITH_NONE] } + + fn name(&self) -> &'static str { + "MemReplace" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4126b78e676..16c3e1fb631 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -814,6 +814,10 @@ impl LintPass for Pass { INTO_ITER_ON_REF, ) } + + fn name(&self) -> &'static str { + "Methods" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index beea667dd43..19bede8a280 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -31,6 +31,10 @@ impl LintPass for MinMaxPass { fn get_lints(&self) -> LintArray { lint_array!(MIN_MAX) } + + fn name(&self) -> &'static str { + "MinMax" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 88a6d62ee6d..01f5a633387 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -242,6 +242,10 @@ impl LintPass for Pass { FLOAT_CMP_CONST ) } + + fn name(&self) -> &'static str { + "MiscLints" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 2cda1accc56..eb35da05908 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -187,6 +187,10 @@ impl LintPass for MiscEarly { BUILTIN_TYPE_SHADOW ) } + + fn name(&self) -> &'static str { + "MiscEarlyLints" + } } // Used to find `return` statements or equivalents e.g. `?` diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 22084bd12cb..9fd67e2fcbf 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -90,6 +90,10 @@ impl LintPass for MissingDoc { fn get_lints(&self) -> LintArray { lint_array![MISSING_DOCS_IN_PRIVATE_ITEMS] } + + fn name(&self) -> &'static str { + "MissingDoc" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index e9d0d2d77f1..754215799e5 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -83,6 +83,10 @@ impl LintPass for MissingInline { fn get_lints(&self) -> LintArray { lint_array![MISSING_INLINE_IN_PUBLIC_ITEMS] } + + fn name(&self) -> &'static str { + "MissingInline" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 6a042fa8c0a..f772fa2b21c 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -37,6 +37,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MULTIPLE_CRATE_VERSIONS) } + + fn name(&self) -> &'static str { + "MultipleCrateVersions" + } } impl EarlyLintPass for Pass { diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 9aa3cce9d4b..b244c7f3031 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -30,6 +30,10 @@ impl LintPass for MutMut { fn get_lints(&self) -> LintArray { lint_array!(MUT_MUT) } + + fn name(&self) -> &'static str { + "MutMut" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 5293c80ca2b..716abbe31fe 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -30,6 +30,10 @@ impl LintPass for UnnecessaryMutPassed { fn get_lints(&self) -> LintArray { lint_array!(UNNECESSARY_MUT_PASSED) } + + fn name(&self) -> &'static str { + "UnneccessaryMutPassed" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index b85f4b8ad30..fa0e8288b30 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -53,6 +53,10 @@ impl LintPass for MutexAtomic { fn get_lints(&self) -> LintArray { lint_array!(MUTEX_ATOMIC, MUTEX_INTEGER) } + + fn name(&self) -> &'static str { + "Mutex" + } } pub struct MutexAtomic; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 3b1fea465f5..49f607f525d 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -61,6 +61,10 @@ impl LintPass for NeedlessBool { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BOOL) } + + fn name(&self) -> &'static str { + "NeedlessBool" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { @@ -141,6 +145,10 @@ impl LintPass for BoolComparison { fn get_lints(&self) -> LintArray { lint_array!(BOOL_COMPARISON) } + + fn name(&self) -> &'static str { + "BoolComparison" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index f21cbe8b9ad..a35f31a9803 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -39,6 +39,10 @@ impl LintPass for NeedlessBorrow { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BORROW) } + + fn name(&self) -> &'static str { + "NeedlessBorrow" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 792e38e1875..6a0032f91b3 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -58,6 +58,10 @@ impl LintPass for NeedlessBorrowedRef { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BORROWED_REFERENCE) } + + fn name(&self) -> &'static str { + "NeedlessBorrowedRef" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 0b5ea255d7f..19d7ab32fea 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -107,6 +107,10 @@ impl LintPass for NeedlessContinue { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_CONTINUE) } + + fn name(&self) -> &'static str { + "NeedlessContinue" + } } impl EarlyLintPass for NeedlessContinue { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index cb1fe475a1e..88eb36534b5 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -56,6 +56,10 @@ impl LintPass for NeedlessPassByValue { fn get_lints(&self) -> LintArray { lint_array![NEEDLESS_PASS_BY_VALUE] } + + fn name(&self) -> &'static str { + "NeedlessPassByValue" + } } macro_rules! need { diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index ab22e2c19b3..1d91feddcbe 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -33,6 +33,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_UPDATE) } + + fn name(&self) -> &'static str { + "NeedUpdate" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 919c771ccf5..50031dd68cf 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -48,6 +48,10 @@ impl LintPass for NoNegCompOpForPartialOrd { fn get_lints(&self) -> LintArray { lint_array!(NEG_CMP_OP_ON_PARTIAL_ORD) } + + fn name(&self) -> &'static str { + "NoNegCompOpForPartialOrd" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 846794d8b99..b207433b5ab 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -30,6 +30,10 @@ impl LintPass for NegMultiply { fn get_lints(&self) -> LintArray { lint_array!(NEG_MULTIPLY) } + + fn name(&self) -> &'static str { + "NegMultiply" + } } #[allow(clippy::match_same_arms)] diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 37e0446faed..f851ae4638e 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -93,6 +93,10 @@ impl LintPass for NewWithoutDefault { fn get_lints(&self) -> LintArray { lint_array!(NEW_WITHOUT_DEFAULT) } + + fn name(&self) -> &'static str { + "NewWithoutDefault" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 648c198df08..7799e8fecf2 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -100,6 +100,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) } + + fn name(&self) -> &'static str { + "NoEffect" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 11295c3c092..cbf6099dd7d 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -147,6 +147,10 @@ impl LintPass for NonCopyConst { fn get_lints(&self) -> LintArray { lint_array!(DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST) } + + fn name(&self) -> &'static str { + "NonCopyConst" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index f39cae46de0..3bdf2c38d23 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -71,6 +71,10 @@ impl LintPass for NonExpressiveNames { fn get_lints(&self) -> LintArray { lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS) } + + fn name(&self) -> &'static str { + "NoneExpressiveNames" + } } struct ExistingName { diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 5f15662c90c..0789df0d76b 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -41,6 +41,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(IF_LET_SOME_RESULT) } + + fn name(&self) -> &'static str { + "OkIfLet" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index fe572d86c1b..31a6caa50d6 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -30,6 +30,10 @@ impl LintPass for NonSensical { fn get_lints(&self) -> LintArray { lint_array!(NONSENSICAL_OPEN_OPTIONS) } + + fn name(&self) -> &'static str { + "OpenOptions" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical { diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index d76a9f96eff..d424e8bcaad 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -28,6 +28,10 @@ impl LintPass for OverflowCheckConditional { fn get_lints(&self) -> LintArray { lint_array!(OVERFLOW_CHECK_CONDITIONAL) } + + fn name(&self) -> &'static str { + "OverflowCheckConditional" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index f5c3a26e080..d0f7487c24a 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -48,6 +48,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PANIC_PARAMS, UNIMPLEMENTED) } + + fn name(&self) -> &'static str { + "PanicUnimplemented" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 03d2d5d3bab..b9d5102ccd6 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -35,6 +35,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PARTIALEQ_NE_IMPL) } + + fn name(&self) -> &'static str { + "PartialEqNeImpl" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 44e82984c54..ed03a8c6aa7 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -35,6 +35,10 @@ impl LintPass for Precedence { fn get_lints(&self) -> LintArray { lint_array!(PRECEDENCE) } + + fn name(&self) -> &'static str { + "Precedence" + } } impl EarlyLintPass for Precedence { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 87cd9892893..6b2528248b5 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -102,6 +102,10 @@ impl LintPass for PointerPass { fn get_lints(&self) -> LintArray { lint_array!(PTR_ARG, CMP_NULL, MUT_FROM_REF) } + + fn name(&self) -> &'static str { + "Ptr" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 32d330ac171..4ff3f7643ba 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -46,6 +46,10 @@ impl lint::LintPass for Pass { fn get_lints(&self) -> lint::LintArray { lint_array!(PTR_OFFSET_WITH_CAST) } + + fn name(&self) -> &'static str { + "PtrOffsetWithCast" + } } impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 03f6ea12e00..b30cbe4ce9a 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -41,6 +41,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(QUESTION_MARK) } + + fn name(&self) -> &'static str { + "QuestionMark" + } } impl Pass { diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 2e01afc2258..ef600184ebe 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -97,6 +97,10 @@ impl LintPass for Pass { RANGE_MINUS_ONE ) } + + fn name(&self) -> &'static str { + "Ranges" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index f584ef19d5a..59d1a4297a5 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -73,6 +73,10 @@ impl LintPass for RedundantClone { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_CLONE) } + + fn name(&self) -> &'static str { + "RedundantClone" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 9076d67cb14..aeb7bb6493c 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -38,6 +38,10 @@ impl LintPass for RedundantFieldNames { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_FIELD_NAMES) } + + fn name(&self) -> &'static str { + "RedundantFieldNames" + } } impl EarlyLintPass for RedundantFieldNames { diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index bc61ee8e7e3..1cf0838415f 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -49,6 +49,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(REDUNDANT_PATTERN_MATCHING) } + + fn name(&self) -> &'static str { + "RedundantPatternMatching" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 8d2543ef618..3a5af498017 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -30,6 +30,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DEREF_ADDROF) } + + fn name(&self) -> &'static str { + "DerefAddrOf" + } } fn without_parens(mut e: &Expr) -> &Expr { @@ -84,6 +88,10 @@ impl LintPass for DerefPass { fn get_lints(&self) -> LintArray { lint_array!(REF_IN_DEREF) } + + fn name(&self) -> &'static str { + "RefInDeref" + } } impl EarlyLintPass for DerefPass { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 6a58a6e73c7..0171c2a5283 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -76,6 +76,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) } + + fn name(&self) -> &'static str { + "Regex" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index ea51e4711cd..16c8cc3bc47 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -35,6 +35,10 @@ impl LintPass for ReplaceConsts { fn get_lints(&self) -> LintArray { lint_array!(REPLACE_CONSTS) } + + fn name(&self) -> &'static str { + "ReplaceConsts" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index d81d04b81d3..83b4d7f9112 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -180,6 +180,10 @@ impl LintPass for ReturnPass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT) } + + fn name(&self) -> &'static str { + "Return" + } } impl EarlyLintPass for ReturnPass { diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index da8675b38da..8090ed7fbcf 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -25,6 +25,10 @@ impl LintPass for Serde { fn get_lints(&self) -> LintArray { lint_array!(SERDE_API_MISUSE) } + + fn name(&self) -> &'static str { + "SerdeAPI" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c99b00bb98f..1f341bd22ee 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -82,6 +82,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } + + fn name(&self) -> &'static str { + "Shadow" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index aea414065d8..0765e4e11be 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -37,6 +37,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(SLOW_VECTOR_INITIALIZATION,) } + + fn name(&self) -> &'static str { + "SlowVectorInit" + } } /// `VecAllocation` contains data regarding a vector allocated with `with_capacity` and then diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index ffec764fd5e..71784397463 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -79,6 +79,10 @@ impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD, STRING_ADD_ASSIGN) } + + fn name(&self) -> &'static str { + "StringAdd" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { @@ -151,6 +155,10 @@ impl LintPass for StringLitAsBytes { fn get_lints(&self) -> LintArray { lint_array!(STRING_LIT_AS_BYTES) } + + fn name(&self) -> &'static str { + "StringLiteralAsBytes" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index c6dd9504857..5f0e49dd7e6 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -57,6 +57,10 @@ impl LintPass for SuspiciousImpl { fn get_lints(&self) -> LintArray { lint_array![SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL] } + + fn name(&self) -> &'static str { + "SuspiciousImpl" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index ddf33fcc411..860707c8239 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -57,6 +57,10 @@ impl LintPass for Swap { fn get_lints(&self) -> LintArray { lint_array![MANUAL_SWAP, ALMOST_SWAPPED] } + + fn name(&self) -> &'static str { + "Swap" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap { diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index c8a01c3668c..0d8cfedf414 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -44,6 +44,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEMPORARY_ASSIGNMENT) } + + fn name(&self) -> &'static str { + "TemporaryAssignment" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 02205cfbd68..88371df0dca 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -219,6 +219,10 @@ impl LintPass for Transmute { TRANSMUTE_INT_TO_FLOAT, ) } + + fn name(&self) -> &'static str { + "Transmute" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 5ab73758301..4e3bb7d329e 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -142,6 +142,10 @@ impl LintPass for TriviallyCopyPassByRef { fn get_lints(&self) -> LintArray { lint_array![TRIVIALLY_COPY_PASS_BY_REF] } + + fn name(&self) -> &'static str { + "TrivallyCopyPassByRef" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 898fd5a9808..4683ffb4c85 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -168,6 +168,10 @@ impl LintPass for TypePass { fn get_lints(&self) -> LintArray { lint_array!(BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) } + + fn name(&self) -> &'static str { + "Types" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { @@ -467,6 +471,10 @@ impl LintPass for LetPass { fn get_lints(&self) -> LintArray { lint_array!(LET_UNIT_VALUE) } + + fn name(&self) -> &'static str { + "LetUnitValue" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass { @@ -531,6 +539,10 @@ impl LintPass for UnitCmp { fn get_lints(&self) -> LintArray { lint_array!(UNIT_CMP) } + + fn name(&self) -> &'static str { + "UnicCmp" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { @@ -586,6 +598,10 @@ impl LintPass for UnitArg { fn get_lints(&self) -> LintArray { lint_array!(UNIT_ARG) } + + fn name(&self) -> &'static str { + "UnitArg" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { @@ -1073,6 +1089,10 @@ impl LintPass for CastPass { FN_TO_NUMERIC_CAST_WITH_TRUNCATION, ) } + + fn name(&self) -> &'static str { + "Casts" + } } // Check if the given type is either `core::ffi::c_void` or @@ -1278,6 +1298,10 @@ impl LintPass for TypeComplexityPass { fn get_lints(&self) -> LintArray { lint_array!(TYPE_COMPLEXITY) } + + fn name(&self) -> &'static str { + "TypeComplexityPass" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { @@ -1442,6 +1466,10 @@ impl LintPass for CharLitAsU8 { fn get_lints(&self) -> LintArray { lint_array!(CHAR_LIT_AS_U8) } + + fn name(&self) -> &'static str { + "CharLiteralAsU8" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { @@ -1500,6 +1528,10 @@ impl LintPass for AbsurdExtremeComparisons { fn get_lints(&self) -> LintArray { lint_array!(ABSURD_EXTREME_COMPARISONS) } + + fn name(&self) -> &'static str { + "AbsurdExtremeComparisons" + } } enum ExtremeType { @@ -1675,6 +1707,10 @@ impl LintPass for InvalidUpcastComparisons { fn get_lints(&self) -> LintArray { lint_array!(INVALID_UPCAST_COMPARISONS) } + + fn name(&self) -> &'static str { + "InvalidUpcastComparisons" + } } #[derive(Copy, Clone, Debug, Eq)] @@ -1918,6 +1954,10 @@ impl LintPass for ImplicitHasher { fn get_lints(&self) -> LintArray { lint_array!(IMPLICIT_HASHER) } + + fn name(&self) -> &'static str { + "ImplicitHasher" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { @@ -2265,6 +2305,10 @@ impl LintPass for RefToMut { fn get_lints(&self) -> LintArray { lint_array!(CAST_REF_TO_MUT) } + + fn name(&self) -> &'static str { + "RefToMut" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index d9207fd2131..d1f39a5e2c2 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -65,6 +65,10 @@ impl LintPass for Unicode { fn get_lints(&self) -> LintArray { lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) } + + fn name(&self) -> &'static str { + "Unicode" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unicode { diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 6beda8ce706..6cf1a582a65 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -32,6 +32,10 @@ impl LintPass for UnsafeNameRemoval { fn get_lints(&self) -> LintArray { lint_array!(UNSAFE_REMOVED_FROM_NAME) } + + fn name(&self) -> &'static str { + "UnsafeNameRemoval" + } } impl EarlyLintPass for UnsafeNameRemoval { diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 27deb0d9945..d54cd3bba03 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -36,6 +36,10 @@ impl LintPass for UnusedIoAmount { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_IO_AMOUNT) } + + fn name(&self) -> &'static str { + "UnusedIoAmount" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index d53fd265d37..29d76a05118 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -39,6 +39,10 @@ impl LintPass for UnusedLabel { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_LABEL) } + + fn name(&self) -> &'static str { + "UnusedLable" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 369b33363b5..196715f77d7 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -184,6 +184,10 @@ impl<'a> LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PANICKING_UNWRAP, UNNECESSARY_UNWRAP) } + + fn name(&self) -> &'static str { + "Unwrap" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 88cf01987b5..1f1d9ddbfec 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -51,6 +51,10 @@ impl LintPass for UseSelf { fn get_lints(&self) -> LintArray { lint_array!(USE_SELF) } + + fn name(&self) -> &'static str { + "UseSelf" + } } const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 9623c6cbdad..19c3f3ad230 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -53,6 +53,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(LINT_AUTHOR) } + + fn name(&self) -> &'static str { + "Author" + } } fn prelude() { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 4116f8ffbaf..758d1d2d365 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -35,6 +35,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DEEP_CODE_INSPECTION) } + + fn name(&self) -> &'static str { + "DeepCodeInspector" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 788fc434d51..78950493699 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -98,6 +98,10 @@ impl LintPass for Clippy { fn get_lints(&self) -> LintArray { lint_array!(CLIPPY_LINTS_INTERNAL) } + + fn name(&self) -> &'static str { + "ClippyLintsInternal" + } } impl EarlyLintPass for Clippy { @@ -139,6 +143,9 @@ impl LintPass for LintWithoutLintPass { fn get_lints(&self) -> LintArray { lint_array!(LINT_WITHOUT_LINT_PASS) } + fn name(&self) -> &'static str { + "LintWithoutLintPass" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { @@ -248,6 +255,10 @@ impl LintPass for DefaultHashTypes { fn get_lints(&self) -> LintArray { lint_array!(DEFAULT_HASH_TYPES) } + + fn name(&self) -> &'static str { + "DefaultHashType" + } } impl EarlyLintPass for DefaultHashTypes { @@ -293,6 +304,10 @@ impl LintPass for CompilerLintFunctions { fn get_lints(&self) -> LintArray { lint_array!(COMPILER_LINT_FUNCTIONS) } + + fn name(&self) -> &'static str { + "CompileLintFunctions" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 407722bc66e..a99b6ca840c 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -32,6 +32,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(USELESS_VEC) } + + fn name(&self) -> &'static str { + "UselessVec" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index fb88b1371f7..8ccf2c69cc7 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -33,6 +33,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(WILDCARD_DEPENDENCIES) } + + fn name(&self) -> &'static str { + "WildcardDependencies" + } } impl EarlyLintPass for Pass { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c8c291c8cc8..36f7fee969b 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -175,6 +175,10 @@ impl LintPass for Pass { WRITE_LITERAL ) } + + fn name(&self) -> &'static str { + "Write" + } } impl EarlyLintPass for Pass { diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 962d42e631e..a806be95432 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -28,6 +28,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(ZERO_DIVIDED_BY_ZERO) } + + fn name(&self) -> &'static str { + "ZeroDiv" + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { diff --git a/src/driver.rs b/src/driver.rs index 2faa77785bb..1ce6f6b7c49 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -123,7 +123,7 @@ pub fn main() { let sess = &state.session; let mut ls = sess.lint_store.borrow_mut(); for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, pass); + ls.register_early_pass(Some(sess), true, false, pass); } for pass in late_lint_passes { ls.register_late_pass(Some(sess), true, pass); diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index 1f2fcd8faf6..a6f10a006db 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -25,6 +25,10 @@ impl lint::LintPass for Pass { fn get_lints(&self) -> lint::LintArray { lint_array!(TEST_LINT_REGISTERED) } + + fn name(&self) -> &'static str { + "TEST_LINT" + } } fn main() {} -- cgit 1.4.1-3-g733a5 From 14e27f567a59ee31bf5250e0b839e25f3730ea5e Mon Sep 17 00:00:00 2001 From: Robert Bamler Date: Sat, 26 Jan 2019 20:26:38 -0800 Subject: Fix documentation for `slow_vector_initialization` Change the recommended solution from `vec![len; 0]` to `vec![0; len]`. Also fix grammar. --- clippy_lints/src/slow_vector_initialization.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index aea414065d8..936e62396dc 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -11,8 +11,8 @@ use syntax_pos::symbol::Symbol; /// **What it does:** Checks slow zero-filled vector initialization /// -/// **Why is this bad?** This structures are non-idiomatic and less efficient than simply using -/// `vec![len; 0]`. +/// **Why is this bad?** These structures are non-idiomatic and less efficient than simply using +/// `vec![0; len]`. /// /// **Known problems:** None. /// -- cgit 1.4.1-3-g733a5 From 3a96d6b603b0a55fa14bb91d23c080725a257c04 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 27 Jan 2019 13:33:56 +0100 Subject: rustup https://github.com/rust-lang/rust/pull/57907/ for file in `fd \.rs$` ; do sed -i s/span_suggestion_with_applicability/span_suggestion/g $file ; done for file in `fd \.rs$` ; do sed -i s/span_suggestion_short_with_applicability/span_suggestion_short/g $file ; done for file in `fd \.rs$` ; do sed -i s/span_suggestions_with_applicability/span_suggestions/g $file ; done --- clippy_lints/src/assign_ops.rs | 6 +++--- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 4 ++-- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/const_static_lifetime.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/entry.rs | 4 ++-- clippy_lints/src/eq_op.rs | 8 ++++---- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/format.rs | 4 ++-- clippy_lints/src/identity_conversion.rs | 6 +++--- clippy_lints/src/implicit_return.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/loops.rs | 8 ++++---- clippy_lints/src/map_unit_fn.rs | 6 +++--- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/mem_discriminant.rs | 2 +- clippy_lints/src/methods/mod.rs | 10 +++++----- clippy_lints/src/misc.rs | 8 ++++---- clippy_lints/src/misc_early.rs | 6 +++--- clippy_lints/src/needless_borrow.rs | 4 ++-- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 8 ++++---- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/ptr.rs | 10 +++++----- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 6 +++--- clippy_lints/src/redundant_clone.rs | 2 +- clippy_lints/src/redundant_pattern_matching.rs | 4 ++-- clippy_lints/src/returns.rs | 8 ++++---- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/swap.rs | 4 ++-- clippy_lints/src/transmute.rs | 18 +++++++++--------- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/sugg.rs | 6 +++--- 38 files changed, 88 insertions(+), 88 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 329bab5cf1c..cc44b514ea7 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let r = &sugg::Sugg::hir(cx, rhs, ".."); let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, &format!( "Did you mean {} = {} {} {} or {}? Consider replacing it with", @@ -96,7 +96,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), Applicability::MachineApplicable, ); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "or", long, @@ -183,7 +183,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "replace it with", format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4a5eb378d5a..89dbba56130 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { "useless lint attribute", |db| { sugg = sugg.replacen("#[", "#![", 1); - db.span_suggestion_with_applicability( + db.span_suggestion( line_span, "if you just forgot a `!`, use", sugg, @@ -336,7 +336,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { // https://github.com/rust-lang/rust/pull/56992 CheckLintNameResult::NoLint(None) => (), _ => { - db.span_suggestion_with_applicability( + db.span_suggestion( lint.span, "lowercase the lint name", name_lower, diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index ef0943875d2..d4e30376199 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { "bit mask could be simplified with a call to `trailing_zeros`", |db| { let sugg = Sugg::hir(cx, left1, "...").maybe_par(); - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 6b53dd908de..6433e0d640d 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -393,7 +393,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { "this expression can be optimized out by applying boolean operations to the \ outer expression", ); - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "it would look like the following", suggest(self.cx, suggestion, &h2q.terminals).0, @@ -423,7 +423,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "this boolean expression can be simplified", |db| { - db.span_suggestions_with_applicability( + db.span_suggestions( e.span, "try", suggestions.into_iter(), diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index c236706f02f..9539b4d89f9 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -154,7 +154,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| { let lhs = Sugg::ast(cx, check, ".."); let rhs = Sugg::ast(cx, check_inner, ".."); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "try", format!( diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 7315184c8bd..2684f45660e 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -66,7 +66,7 @@ impl StaticConst { lifetime.ident.span, "Constants have by default a `'static` lifetime", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( ty.span, "consider removing `'static`", sugg, diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 6bb75cf8064..c704a635425 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -207,7 +207,7 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) { |db| { db.span_note(i.body.span, "same as this"); - // Note: this does not use `span_suggestion_with_applicability` on purpose: + // Note: this does not use `span_suggestion` on purpose: // there is no clean way // to remove the other arm. Building a span and suggest to replace it to "" // makes an even more confusing error message. Also in order not to make up a diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 8de881d0425..3e0a6e11be6 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, params[1].span, ".."), snippet(self.cx, params[2].span, "..")); - db.span_suggestion_with_applicability( + db.span_suggestion( self.span, "consider using", help, @@ -161,7 +161,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { snippet(self.cx, self.map.span, "map"), snippet(self.cx, params[1].span, "..")); - db.span_suggestion_with_applicability( + db.span_suggestion( self.span, "consider using", help, diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 38c9a05b44c..57291dd24ee 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); - db.span_suggestion_with_applicability( + db.span_suggestion( left.span, "use the left value directly", lsnip, @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { "needlessly taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); - db.span_suggestion_with_applicability( + db.span_suggestion( right.span, "use the right value directly", rsnip, @@ -163,7 +163,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); - db.span_suggestion_with_applicability( + db.span_suggestion( left.span, "use the left value directly", lsnip, @@ -181,7 +181,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); - db.span_suggestion_with_applicability( + db.span_suggestion( right.span, "use the right value directly", rsnip, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index cc86aee7def..f0557154f90 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -101,7 +101,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { } span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { if let Some(snippet) = snippet_opt(cx, caller.span) { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "remove closure as shown", snippet, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index f14c281fcc9..aaef5b39aeb 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }; span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, message, sugg, @@ -99,7 +99,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if tup.is_empty() { let sugg = format!("{}.to_string()", snippet(cx, expr.span, "").into_owned()); span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "consider using .to_string()", sugg, diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 2c0e389119f..abe8a9d6856 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg = snippet_with_macro_callsite(cx, args[0].span, "").to_string(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider removing `.into()`", sugg, @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { if same_tys(cx, a, b) { let sugg = snippet(cx, args[0].span, "").into_owned(); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider removing `.into_iter()`", sugg, @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, &sugg_msg, sugg, diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index b25b3bce652..72d95a0763a 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -39,7 +39,7 @@ impl Pass { fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) { span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { - db.span_suggestion_with_applicability( + db.span_suggestion( outer_span, msg, format!("return {}", snippet), diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index aee3b7cc542..9b5938baf5f 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -162,7 +162,7 @@ impl IntPlusOne { block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( block.span, "change `>= y + 1` to `> y` as shown", recommendation, diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 0b3cf07e50a..59e036c715e 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { VariantData::Unit(_) => unreachable!(), }; if let Some(snip) = snippet_opt(cx, span) { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "consider boxing the large fields to reduce the total size of the \ enum", diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 3eb25cfb36a..f1aed79847f 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { span, "`if _ { .. } else { .. }` is an expression", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "it is more idiomatic to write", sug, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 64e76c09989..4d6cc75135e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1304,7 +1304,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx expr.span, "this range is empty so this for loop will never run", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( arg.span, "consider using the following if you are attempting to iterate over this \ range in reverse", @@ -2408,7 +2408,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> if method.ident.name == "len" { let span = shorten_needless_collect_span(expr); span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "replace with", ".count()".to_string(), @@ -2419,7 +2419,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> if method.ident.name == "is_empty" { let span = shorten_needless_collect_span(expr); span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "replace with", ".next().is_none()".to_string(), @@ -2431,7 +2431,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> let contains_arg = snippet(cx, args[1].span, "??"); let span = shorten_needless_collect_span(expr); span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "replace with", format!( diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index bd4b4043824..75e12cd9fd3 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -216,7 +216,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr ); span_lint_and_then(cx, lint, expr.span, &msg, |db| { - db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified); + db.span_suggestion(stmt.span, "try this", suggestion, Applicability::Unspecified); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); @@ -230,7 +230,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr snippet(cx, var_arg.span, "_"), snippet(cx, reduced_expr_span, "_") ); - db.span_suggestion_with_applicability( + db.span_suggestion( stmt.span, "try this", suggestion, @@ -243,7 +243,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_") ); - db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified); + db.span_suggestion(stmt.span, "try this", suggestion, Applicability::Unspecified); } }); } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index adb8dab5c42..b290980fc36 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -375,7 +375,7 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex }; if let Some(sugg) = sugg { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "consider using an if/else expression", sugg, diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index a40b1eab2c7..65e47369819 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { } let derefs: String = iter::repeat('*').take(derefs_needed).collect(); - db.span_suggestion_with_applicability( + db.span_suggestion( param.span, "try dereferencing", format!("{}{}", derefs, snippet(cx, cur_expr.span, "")), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 16c3e1fb631..20ffc1fd406 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1313,13 +1313,13 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp let refs: String = iter::repeat('&').take(n + 1).collect(); let derefs: String = iter::repeat('*').take(n).collect(); let explicit = format!("{}{}::clone({})", refs, ty, snip); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "try dereferencing it", format!("{}({}{}).clone()", refs, derefs, snip.deref()), Applicability::MaybeIncorrect, ); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "or try being explicit about what type to clone", explicit, @@ -1379,7 +1379,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp } span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| { if let Some((text, snip)) = snip { - db.span_suggestion_with_applicability(expr.span, text, snip, Applicability::Unspecified); + db.span_suggestion(expr.span, text, snip, Applicability::Unspecified); } }); } @@ -1810,7 +1810,7 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let func_snippet = snippet(cx, map_args[1].span, ".."); let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); span_lint_and_then(cx, MAP_FLATTEN, expr.span, msg, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "try using flat_map instead", hint, @@ -1897,7 +1897,7 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "try using and_then instead", hint, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 01f5a633387..c15fba76869 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -302,7 +302,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( s.span, "try", format!( @@ -330,7 +330,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { "boolean short circuit operator in statement may be clearer using an explicit test", |db| { let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; - db.span_suggestion_with_applicability( + db.span_suggestion( s.span, "replace it with", format!( @@ -387,7 +387,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let lhs = Sugg::hir(cx, left, ".."); let rhs = Sugg::hir(cx, right, ".."); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "consider comparing them within some error", format!("({}).abs() < error", lhs - rhs), @@ -568,7 +568,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) { snip.to_string() }; - db.span_suggestion_with_applicability( + db.span_suggestion( lint_span, "try", try_hint, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index eb35da05908..88acdbb168a 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -343,7 +343,7 @@ impl EarlyLintPass for MiscEarly { |db| { if decl.inputs.is_empty() { let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "Try doing something like: ", hint, @@ -438,13 +438,13 @@ impl MiscEarly { lit.span, "this is a decimal constant", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion", src.trim_start_matches(|c| c == '_' || c == '0').to_string(), Applicability::MaybeIncorrect, ); - db.span_suggestion_with_applicability( + db.span_suggestion( lit.span, "if you mean to use an octal constant, use `0o`", format!("0o{}", src.trim_start_matches(|c| c == '_' || c == '0')), diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index a35f31a9803..206a1465a46 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { by the compiler", |db| { if let Some(snippet) = snippet_opt(cx, inner.span) { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "change this to", snippet, @@ -103,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { "this pattern creates a reference to a reference", |db| { if let Some(snippet) = snippet_opt(cx, name.span) { - db.span_suggestion_with_applicability( + db.span_suggestion( pat.span, "change this to", snippet, diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 6a0032f91b3..bf2857d9288 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { "this pattern takes a reference on something that is being de-referenced", |db| { let hint = snippet(cx, spanned_name.span, "..").into_owned(); - db.span_suggestion_with_applicability( + db.span_suggestion( pat.span, "try removing the `&ref` part and just keep", hint, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 88eb36534b5..73c0ed72d3b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -237,7 +237,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { }).unwrap()); then { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); - db.span_suggestion_with_applicability( + db.span_suggestion( input.span, "consider changing the type to", slice_ty, @@ -245,7 +245,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ); for (span, suggestion) in clone_spans { - db.span_suggestion_with_applicability( + db.span_suggestion( span, &snippet_opt(cx, span) .map_or( @@ -266,7 +266,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if match_type(cx, ty, &paths::STRING) { if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { - db.span_suggestion_with_applicability( + db.span_suggestion( input.span, "consider changing the type to", "&str".to_string(), @@ -274,7 +274,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ); for (span, suggestion) in clone_spans { - db.span_suggestion_with_applicability( + db.span_suggestion( span, &snippet_opt(cx, span) .map_or( diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index cbf6099dd7d..50d8b69ffae 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -122,7 +122,7 @@ fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, sourc match source { Source::Item { .. } => { let const_kw_span = span.from_inner_byte_pos(0, 5); - db.span_suggestion_with_applicability( + db.span_suggestion( const_kw_span, "make this a static item", "static".to_string(), diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 6b2528248b5..8f4ee74258a 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -182,7 +182,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: with non-Vec-based slices.", |db| { if let Some(ref snippet) = ty_snippet { - db.span_suggestion_with_applicability( + db.span_suggestion( arg.span, "change this to", format!("&[{}]", snippet), @@ -190,7 +190,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: ); } for (clonespan, suggestion) in spans { - db.span_suggestion_with_applicability( + db.span_suggestion( clonespan, &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { Cow::Owned(format!("change `{}` to", x)) @@ -210,14 +210,14 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do.", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( arg.span, "change this to", "&str".into(), Applicability::Unspecified, ); for (clonespan, suggestion) in spans { - db.span_suggestion_short_with_applicability( + db.span_suggestion_short( clonespan, &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { Cow::Owned(format!("change `{}` to", x)) @@ -250,7 +250,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: arg.span, "using a reference to `Cow` is not recommended.", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( arg.span, "change this to", "&".to_owned() + &r, diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b30cbe4ce9a..cab133943a3 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -92,7 +92,7 @@ impl Pass { expr.span, "this block may be rewritten with the `?` operator", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "replace_it_with", replacement_str, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index ef600184ebe..acd2a3ebc65 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -166,14 +166,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let end = Sugg::hir(cx, y, "y"); if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "use", format!("({}..={})", start, end), Applicability::MaybeIncorrect, ); } else { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "use", format!("{}..={}", start, end), @@ -199,7 +199,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { |db| { let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "use", format!("{}..{}", start, end), diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 59d1a4297a5..7ac147c8ac1 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { ); span_lint_node_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( sugg_span, "remove this", String::new(), diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index 1cf0838415f..8f833a893df 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -98,7 +98,7 @@ fn find_sugg_for_if_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, &format!("redundant pattern matching, consider using `{}`", good_method), |db| { let span = expr.span.to(op.span); - db.span_suggestion_with_applicability( + db.span_suggestion( span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method), @@ -163,7 +163,7 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, o &format!("redundant pattern matching, consider using `{}`", good_method), |db| { let span = expr.span.to(op.span); - db.span_suggestion_with_applicability( + db.span_suggestion( span, "try this", format!("{}.{}", snippet(cx, op.span, "_"), good_method), diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 83b4d7f9112..71ef3e4bfa0 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -135,7 +135,7 @@ impl ReturnPass { } span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { - db.span_suggestion_with_applicability( + db.span_suggestion( ret_span, "remove `return` as shown", snippet, @@ -211,7 +211,7 @@ impl EarlyLintPass for ReturnPass { (ty.span, Applicability::MaybeIncorrect) }; span_lint_and_then(cx, UNUSED_UNIT, rspan, "unneeded unit return type", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( rspan, "remove the `-> ()`", String::new(), @@ -231,7 +231,7 @@ impl EarlyLintPass for ReturnPass { then { let sp = expr.span; span_lint_and_then(cx, UNUSED_UNIT, sp, "unneeded unit expression", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( sp, "remove the final `()`", String::new(), @@ -247,7 +247,7 @@ impl EarlyLintPass for ReturnPass { ast::ExprKind::Ret(Some(ref expr)) | ast::ExprKind::Break(_, Some(ref expr)) => { if is_unit_expr(expr) && !in_macro(expr.span) { span_lint_and_then(cx, UNUSED_UNIT, expr.span, "unneeded `()`", |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( expr.span, "remove the `()`", String::new(), diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 0765e4e11be..4ce9ce3e2ff 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -179,7 +179,7 @@ impl Pass { let len_expr = Sugg::hir(cx, vec_alloc.len_expr, "len"); span_lint_and_then(cx, lint, slow_fill.span, msg, |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( vec_alloc.allocation_expr.span, "consider replace allocation with", format!("vec![0; {}]", len_expr), diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 860707c8239..af7fd11c6e5 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -142,7 +142,7 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { &format!("this looks like you are swapping{} manually", what), |db| { if !sugg.is_empty() { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "try", sugg, @@ -191,7 +191,7 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) { &format!("this looks like you are trying to swap{}", what), |db| { if !what.is_empty() { - db.span_suggestion_with_applicability( + db.span_suggestion( span, "try", format!( diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 88371df0dca..80bc29a3553 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) }; - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", sugg.to_string(), @@ -276,7 +276,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { "transmute from an integer to a pointer", |db| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", arg.as_ty(&to_ty.to_string()).to_string(), @@ -335,7 +335,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) }; - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", sugg::make_unop(deref, arg).to_string(), @@ -356,7 +356,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string()), @@ -383,7 +383,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), |db| { - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider using", format!( @@ -416,7 +416,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { sugg_paren.addr_deref() }; - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", sugg.to_string(), @@ -436,7 +436,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |db| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "try", sugg.to_string(), @@ -454,7 +454,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |db| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); let zero = sugg::Sugg::NonParen(Cow::from("0")); - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(), @@ -478,7 +478,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } else { arg }; - db.span_suggestion_with_applicability( + db.span_suggestion( e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string()), diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index c83b0f155fc..af9b1599649 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -693,7 +693,7 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( applicability: Applicability, ) { span_lint_and_then(cx, lint, sp, msg, |db| { - db.span_suggestion_with_applicability(sp, help, sugg, applicability); + db.span_suggestion(sp, help, sugg, applicability); }); } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index b95ce17ed93..166470876c9 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -547,7 +547,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error if let Some(indent) = indentation(cx, item) { let span = item.with_hi(item.lo()); - self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", attr, indent), applicability); + self.span_suggestion(span, msg, format!("{}\n{}", attr, indent), applicability); } } @@ -568,7 +568,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error }) .collect::(); - self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", new_item, indent), applicability); + self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent), applicability); } } @@ -586,7 +586,7 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error } } - self.span_suggestion_with_applicability(remove_span, msg, String::new(), applicability); + self.span_suggestion(remove_span, msg, String::new(), applicability); } } -- cgit 1.4.1-3-g733a5 From 79b1d9adf0d09ae49df72648ab3d5c03536c0de2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 27 Jan 2019 13:34:23 +0100 Subject: run cargo fmt --- clippy_lints/src/ptr.rs | 7 +------ clippy_lints/src/transmute.rs | 14 ++------------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 8f4ee74258a..b990b7ab2bd 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -210,12 +210,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do.", |db| { - db.span_suggestion( - arg.span, - "change this to", - "&str".into(), - Applicability::Unspecified, - ); + db.span_suggestion(arg.span, "change this to", "&str".into(), Applicability::Unspecified); for (clonespan, suggestion) in spans { db.span_suggestion_short( clonespan, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 80bc29a3553..90cfcd56c3b 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -260,12 +260,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) }; - db.span_suggestion( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + db.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); } }, ), @@ -436,12 +431,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |db| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); - db.span_suggestion( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); + db.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); } }, ), -- cgit 1.4.1-3-g733a5 From 16c0a2fa6fc34380b60a54282e7e2ec1dafa2f48 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 27 Jan 2019 13:46:22 +0100 Subject: update test stderr --- tests/ui/deprecated.stderr | 8 +++++++- tests/ui/rename.stderr | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 4dbca0dea64..ea809472cb2 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -30,5 +30,11 @@ error: lint `misaligned_transmute` has been removed: `this lint has been split i LL | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` + --> $DIR/deprecated.rs:1:8 + | +LL | #[warn(str_to_string)] + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 58d2c98f890..7864e2a1fca 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -20,5 +20,17 @@ error: lint `clippy::new_without_default_derive` has been renamed to `clippy::ne LL | #[warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` -error: aborting due to 3 previous errors +error: unknown lint: `stutter` + --> $DIR/rename.rs:1:10 + | +LL | #![allow(stutter)] + | ^^^^^^^ + +error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` + --> $DIR/rename.rs:3:8 + | +LL | #[warn(clippy::stutter)] + | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From b08964b3bdc8ffad3605ecd4d1c84cf8472566e0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:09:34 +0100 Subject: Update const slice processing --- clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 49722e5ad71..ccf74bffe4b 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -441,7 +441,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' // FIXME: implement other conversion _ => None, }, - ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty { + ConstValue::Slice(Scalar::Ptr(ptr), n) => match result.ty.sty { ty::Ref(_, tam, _) => match tam.sty { ty::Str => { let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); -- cgit 1.4.1-3-g733a5 From 36245feeb059cfec84ae15dc2a3ee211d0ed4e42 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:09:45 +0100 Subject: Update changed iterator paths --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index d2dc2812575..35d99d98593 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -41,7 +41,7 @@ pub const INTO: [&str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; -pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; +pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"]; pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; -- cgit 1.4.1-3-g733a5 From dc8c7b16775be6c249555338af70d78013f01301 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:10:27 +0100 Subject: Atomics constants are now handled by the deprecation lint --- clippy_lints/src/replace_consts.rs | 15 ----- tests/ui/replace_consts.fixed | 12 ---- tests/ui/replace_consts.rs | 12 ---- tests/ui/replace_consts.stderr | 120 +++++++++---------------------------- 4 files changed, 27 insertions(+), 132 deletions(-) diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 16c8cc3bc47..47168445ad3 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -69,21 +69,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { const REPLACEMENTS: &[(&[&str], &str)] = &[ // Once (&["core", "sync", "ONCE_INIT"], "Once::new()"), - // Atomic - ( - &["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], - "AtomicBool::new(false)", - ), - (&["core", "sync", "atomic", "ATOMIC_ISIZE_INIT"], "AtomicIsize::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_USIZE_INIT"], "AtomicUsize::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"), - (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"), // Min (&["core", "isize", "MIN"], "isize::min_value()"), (&["core", "i8", "MIN"], "i8::min_value()"), diff --git a/tests/ui/replace_consts.fixed b/tests/ui/replace_consts.fixed index 96a1281e478..2c125f978d9 100644 --- a/tests/ui/replace_consts.fixed +++ b/tests/ui/replace_consts.fixed @@ -10,18 +10,6 @@ use std::sync::{Once, ONCE_INIT}; fn bad() { // Once { let foo = ONCE_INIT; }; - // Atomic - { let foo = AtomicBool::new(false); }; - { let foo = AtomicIsize::new(0); }; - { let foo = AtomicI8::new(0); }; - { let foo = AtomicI16::new(0); }; - { let foo = AtomicI32::new(0); }; - { let foo = AtomicI64::new(0); }; - { let foo = AtomicUsize::new(0); }; - { let foo = AtomicU8::new(0); }; - { let foo = AtomicU16::new(0); }; - { let foo = AtomicU32::new(0); }; - { let foo = AtomicU64::new(0); }; // Min { let foo = isize::min_value(); }; { let foo = i8::min_value(); }; diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs index b61293cc6e9..3c7d8d07ed6 100644 --- a/tests/ui/replace_consts.rs +++ b/tests/ui/replace_consts.rs @@ -10,18 +10,6 @@ use std::sync::{Once, ONCE_INIT}; fn bad() { // Once { let foo = ONCE_INIT; }; - // Atomic - { let foo = ATOMIC_BOOL_INIT; }; - { let foo = ATOMIC_ISIZE_INIT; }; - { let foo = ATOMIC_I8_INIT; }; - { let foo = ATOMIC_I16_INIT; }; - { let foo = ATOMIC_I32_INIT; }; - { let foo = ATOMIC_I64_INIT; }; - { let foo = ATOMIC_USIZE_INIT; }; - { let foo = ATOMIC_U8_INIT; }; - { let foo = ATOMIC_U16_INIT; }; - { let foo = ATOMIC_U32_INIT; }; - { let foo = ATOMIC_U64_INIT; }; // Min { let foo = std::isize::MIN; }; { let foo = std::i8::MIN; }; diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr index 6f2155406cd..be0d0072623 100644 --- a/tests/ui/replace_consts.stderr +++ b/tests/ui/replace_consts.stderr @@ -1,8 +1,8 @@ -error: using `ATOMIC_BOOL_INIT` +error: using `MIN` --> $DIR/replace_consts.rs:14:17 | -LL | { let foo = ATOMIC_BOOL_INIT; }; - | ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)` +LL | { let foo = std::isize::MIN; }; + | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` | note: lint level defined here --> $DIR/replace_consts.rs:4:9 @@ -10,209 +10,143 @@ note: lint level defined here LL | #![deny(clippy::replace_consts)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: using `ATOMIC_ISIZE_INIT` - --> $DIR/replace_consts.rs:15:17 - | -LL | { let foo = ATOMIC_ISIZE_INIT; }; - | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)` - -error: using `ATOMIC_I8_INIT` - --> $DIR/replace_consts.rs:16:17 - | -LL | { let foo = ATOMIC_I8_INIT; }; - | ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)` - -error: using `ATOMIC_I16_INIT` - --> $DIR/replace_consts.rs:17:17 - | -LL | { let foo = ATOMIC_I16_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)` - -error: using `ATOMIC_I32_INIT` - --> $DIR/replace_consts.rs:18:17 - | -LL | { let foo = ATOMIC_I32_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)` - -error: using `ATOMIC_I64_INIT` - --> $DIR/replace_consts.rs:19:17 - | -LL | { let foo = ATOMIC_I64_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)` - -error: using `ATOMIC_USIZE_INIT` - --> $DIR/replace_consts.rs:20:17 - | -LL | { let foo = ATOMIC_USIZE_INIT; }; - | ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)` - -error: using `ATOMIC_U8_INIT` - --> $DIR/replace_consts.rs:21:17 - | -LL | { let foo = ATOMIC_U8_INIT; }; - | ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)` - -error: using `ATOMIC_U16_INIT` - --> $DIR/replace_consts.rs:22:17 - | -LL | { let foo = ATOMIC_U16_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)` - -error: using `ATOMIC_U32_INIT` - --> $DIR/replace_consts.rs:23:17 - | -LL | { let foo = ATOMIC_U32_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)` - -error: using `ATOMIC_U64_INIT` - --> $DIR/replace_consts.rs:24:17 - | -LL | { let foo = ATOMIC_U64_INIT; }; - | ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)` - -error: using `MIN` - --> $DIR/replace_consts.rs:26:17 - | -LL | { let foo = std::isize::MIN; }; - | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` - error: using `MIN` - --> $DIR/replace_consts.rs:27:17 + --> $DIR/replace_consts.rs:15:17 | LL | { let foo = std::i8::MIN; }; | ^^^^^^^^^^^^ help: try this: `i8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:28:17 + --> $DIR/replace_consts.rs:16:17 | LL | { let foo = std::i16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:29:17 + --> $DIR/replace_consts.rs:17:17 | LL | { let foo = std::i32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:30:17 + --> $DIR/replace_consts.rs:18:17 | LL | { let foo = std::i64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:31:17 + --> $DIR/replace_consts.rs:19:17 | LL | { let foo = std::i128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:32:17 + --> $DIR/replace_consts.rs:20:17 | LL | { let foo = std::usize::MIN; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:33:17 + --> $DIR/replace_consts.rs:21:17 | LL | { let foo = std::u8::MIN; }; | ^^^^^^^^^^^^ help: try this: `u8::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:34:17 + --> $DIR/replace_consts.rs:22:17 | LL | { let foo = std::u16::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:35:17 + --> $DIR/replace_consts.rs:23:17 | LL | { let foo = std::u32::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:36:17 + --> $DIR/replace_consts.rs:24:17 | LL | { let foo = std::u64::MIN; }; | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` error: using `MIN` - --> $DIR/replace_consts.rs:37:17 + --> $DIR/replace_consts.rs:25:17 | LL | { let foo = std::u128::MIN; }; | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` error: using `MAX` - --> $DIR/replace_consts.rs:39:17 + --> $DIR/replace_consts.rs:27:17 | LL | { let foo = std::isize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:40:17 + --> $DIR/replace_consts.rs:28:17 | LL | { let foo = std::i8::MAX; }; | ^^^^^^^^^^^^ help: try this: `i8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:41:17 + --> $DIR/replace_consts.rs:29:17 | LL | { let foo = std::i16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:42:17 + --> $DIR/replace_consts.rs:30:17 | LL | { let foo = std::i32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:43:17 + --> $DIR/replace_consts.rs:31:17 | LL | { let foo = std::i64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:44:17 + --> $DIR/replace_consts.rs:32:17 | LL | { let foo = std::i128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:45:17 + --> $DIR/replace_consts.rs:33:17 | LL | { let foo = std::usize::MAX; }; | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:46:17 + --> $DIR/replace_consts.rs:34:17 | LL | { let foo = std::u8::MAX; }; | ^^^^^^^^^^^^ help: try this: `u8::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:47:17 + --> $DIR/replace_consts.rs:35:17 | LL | { let foo = std::u16::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:48:17 + --> $DIR/replace_consts.rs:36:17 | LL | { let foo = std::u32::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:49:17 + --> $DIR/replace_consts.rs:37:17 | LL | { let foo = std::u64::MAX; }; | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` error: using `MAX` - --> $DIR/replace_consts.rs:50:17 + --> $DIR/replace_consts.rs:38:17 | LL | { let foo = std::u128::MAX; }; | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` -error: aborting due to 35 previous errors +error: aborting due to 24 previous errors -- cgit 1.4.1-3-g733a5 From 7b90cb529a2c11f69a29427da50379722f5e332e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:16:34 +0100 Subject: Update more changed iterator paths --- clippy_lints/src/utils/paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 35d99d98593..0a1b53c32ac 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -38,7 +38,7 @@ pub const INDEX: [&str; 3] = ["core", "ops", "Index"]; pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"]; pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"]; pub const INTO: [&str; 3] = ["core", "convert", "Into"]; -pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; +pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"]; -- cgit 1.4.1-3-g733a5 From 8a417204f81476a6627d18006a2a92f4282a489c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:17:04 +0100 Subject: Remove tests for deprecated items --- tests/ui/non_copy_const.rs | 5 +---- tests/ui/non_copy_const.stderr | 46 ++++++++++++++---------------------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/tests/ui/non_copy_const.rs b/tests/ui/non_copy_const.rs index bd8b7521d14..00cbcaeacb9 100644 --- a/tests/ui/non_copy_const.rs +++ b/tests/ui/non_copy_const.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::fmt::Display; -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable @@ -95,9 +95,6 @@ fn main() { ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability - ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability - assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability - let _once = ONCE_INIT; let _once_ref = &ONCE_INIT; //~ ERROR interior mutability let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index a9584ceb7ec..1276491127a 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -144,23 +144,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:98:5 - | -LL | ATOMIC_USIZE_INIT.store(2, Ordering::SeqCst); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here - -error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:99:16 - | -LL | assert_eq!(ATOMIC_USIZE_INIT.load(Ordering::SeqCst), 0); //~ ERROR interior mutability - | ^^^^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here - -error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:102:22 + --> $DIR/non_copy_const.rs:99:22 | LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -168,7 +152,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:103:25 + --> $DIR/non_copy_const.rs:100:25 | LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -176,7 +160,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:104:27 + --> $DIR/non_copy_const.rs:101:27 | LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -184,7 +168,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:105:26 + --> $DIR/non_copy_const.rs:102:26 | LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -192,7 +176,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:116:14 + --> $DIR/non_copy_const.rs:113:14 | LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -200,7 +184,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:117:14 + --> $DIR/non_copy_const.rs:114:14 | LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -208,7 +192,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:118:19 + --> $DIR/non_copy_const.rs:115:19 | LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -216,7 +200,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:119:14 + --> $DIR/non_copy_const.rs:116:14 | LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -224,7 +208,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:120:13 + --> $DIR/non_copy_const.rs:117:13 | LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -232,7 +216,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:126:13 + --> $DIR/non_copy_const.rs:123:13 | LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -240,7 +224,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:131:5 + --> $DIR/non_copy_const.rs:128:5 | LL | CELL.set(2); //~ ERROR interior mutability | ^^^^ @@ -248,7 +232,7 @@ LL | CELL.set(2); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:132:16 + --> $DIR/non_copy_const.rs:129:16 | LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ @@ -256,7 +240,7 @@ LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:145:5 + --> $DIR/non_copy_const.rs:142:5 | LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ @@ -264,12 +248,12 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed - --> $DIR/non_copy_const.rs:146:16 + --> $DIR/non_copy_const.rs:143:16 | LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here -error: aborting due to 31 previous errors +error: aborting due to 29 previous errors -- cgit 1.4.1-3-g733a5 From c67a05166f6d08956dcb26c17de5f8792123eb9a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 10:32:34 +0100 Subject: Check hypothetically failing conversion --- clippy_lints/src/consts.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index ccf74bffe4b..1055f626e59 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -12,6 +12,7 @@ use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; +use std::convert::TryFrom; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; use syntax_pos::symbol::Symbol; @@ -446,7 +447,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' ty::Str => { let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); let offset = ptr.offset.bytes().try_into().expect("too-large pointer offset"); - let n = n as usize; + let n = usize::try_from(n).unwrap(); String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()) .ok() .map(Constant::Str) -- cgit 1.4.1-3-g733a5 From 60332941c9aab8419f9bc1dbec5071214f0d8077 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 28 Jan 2019 11:32:41 +0100 Subject: Rustfmt --- clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 1055f626e59..832fb875286 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -10,9 +10,9 @@ use rustc::{bug, span_bug}; use rustc_data_structures::sync::Lrc; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; +use std::convert::TryFrom; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::convert::TryFrom; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; use syntax_pos::symbol::Symbol; -- cgit 1.4.1-3-g733a5 From df04238d3aea4b8b105c286b49d54dd77c2b5f83 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 29 Jan 2019 07:22:08 +0200 Subject: Fix `unit_arg` false positive Ignore arguments with the question mark operator. Closes #2945 --- clippy_lints/src/types.rs | 55 ++++++++++++++++++++++++++--------------------- tests/ui/unit_arg.fixed | 11 ++++++++++ tests/ui/unit_arg.rs | 11 ++++++++++ 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4683ffb4c85..94c83ed5720 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -609,36 +609,43 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { if in_macro(expr.span) { return; } + + // apparently stuff in the desugaring of `?` can trigger this + // so check for that here + // only the calls to `Try::from_error` is marked as desugared, + // so we need to check both the current Expr and its parent. + if is_questionmark_desugar_marked_call(expr) { + return; + } + if_chain! { + let map = &cx.tcx.hir(); + let opt_parent_node = map.find(map.get_parent_node(expr.id)); + if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; + if is_questionmark_desugar_marked_call(parent_expr); + then { + return; + } + } + match expr.node { ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => { for arg in args { if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { - let map = &cx.tcx.hir(); - // apparently stuff in the desugaring of `?` can trigger this - // so check for that here - // only the calls to `Try::from_error` is marked as desugared, - // so we need to check both the current Expr and its parent. - if !is_questionmark_desugar_marked_call(expr) { - if_chain! { - let opt_parent_node = map.find(map.get_parent_node(expr.id)); - if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; - if is_questionmark_desugar_marked_call(parent_expr); - then {} - else { - // `expr` and `parent_expr` where _both_ not from - // desugaring `?`, so lint - span_lint_and_sugg( - cx, - UNIT_ARG, - arg.span, - "passing a unit value to a function", - "if you intended to pass a unit value, use a unit literal instead", - "()".to_string(), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Match(.., match_source) = &arg.node { + if *match_source == MatchSource::TryDesugar { + continue; } } + + span_lint_and_sugg( + cx, + UNIT_ARG, + arg.span, + "passing a unit value to a function", + "if you intended to pass a unit value, use a unit literal instead", + "()".to_string(), + Applicability::MachineApplicable, + ); } } }, diff --git a/tests/ui/unit_arg.fixed b/tests/ui/unit_arg.fixed index d8f3e854ca9..cf146c91f6d 100644 --- a/tests/ui/unit_arg.fixed +++ b/tests/ui/unit_arg.fixed @@ -47,6 +47,17 @@ fn question_mark() -> Result<(), ()> { Ok(()) } +#[allow(dead_code)] +mod issue_2945 { + fn unit_fn() -> Result<(), i32> { + Ok(()) + } + + fn fallible() -> Result<(), i32> { + Ok(unit_fn()?) + } +} + fn main() { bad(); ok(); diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 1403870eacf..c15b0a50045 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -54,6 +54,17 @@ fn question_mark() -> Result<(), ()> { Ok(()) } +#[allow(dead_code)] +mod issue_2945 { + fn unit_fn() -> Result<(), i32> { + Ok(()) + } + + fn fallible() -> Result<(), i32> { + Ok(unit_fn()?) + } +} + fn main() { bad(); ok(); -- cgit 1.4.1-3-g733a5 From c3980bf0bc1641717d3253f9168dec07b52e0e4f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 9 Jan 2019 20:11:37 +0100 Subject: Add initial version of const_fn lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 5 + clippy_lints/src/missing_const_for_fn.rs | 115 +++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 13 +++ tests/ui/missing_const_for_fn/cant_be_const.rs | 50 +++++++++ tests/ui/missing_const_for_fn/cant_be_const.stderr | 0 tests/ui/missing_const_for_fn/could_be_const.rs | 53 ++++++++++ .../ui/missing_const_for_fn/could_be_const.stderr | 42 ++++++++ 9 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/missing_const_for_fn.rs create mode 100644 tests/ui/missing_const_for_fn/cant_be_const.rs create mode 100644 tests/ui/missing_const_for_fn/cant_be_const.stderr create mode 100644 tests/ui/missing_const_for_fn/could_be_const.rs create mode 100644 tests/ui/missing_const_for_fn/could_be_const.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index b773422b015..c0679d280c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -878,6 +878,7 @@ All notable changes to this project will be documented in this file. [`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max [`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op +[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes diff --git a/README.md b/README.md index 6473b8efc54..dad18ef7569 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 292 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 293 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4683d353ccf..3483aae0ca3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -23,6 +23,8 @@ extern crate rustc_data_structures; #[allow(unused_extern_crates)] extern crate rustc_errors; #[allow(unused_extern_crates)] +extern crate rustc_mir; +#[allow(unused_extern_crates)] extern crate rustc_plugin; #[allow(unused_extern_crates)] extern crate rustc_target; @@ -144,6 +146,7 @@ pub mod methods; pub mod minmax; pub mod misc; pub mod misc_early; +pub mod missing_const_for_fn; pub mod missing_doc; pub mod missing_inline; pub mod multiple_crate_versions; @@ -486,6 +489,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box slow_vector_initialization::Pass); reg.register_late_lint_pass(box types::RefToMut); reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants); + reg.register_late_lint_pass(box missing_const_for_fn::MissingConstForFn); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -1027,6 +1031,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::nursery", Some("clippy_nursery"), vec![ attrs::EMPTY_LINE_AFTER_OUTER_ATTR, fallible_impl_from::FALLIBLE_IMPL_FROM, + missing_const_for_fn::MISSING_CONST_FOR_FN, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, redundant_clone::REDUNDANT_CLONE, diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs new file mode 100644 index 00000000000..4751a538ebd --- /dev/null +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -0,0 +1,115 @@ +use rustc::hir; +use rustc::hir::{Body, FnDecl, Constness}; +use rustc::hir::intravisit::FnKind; +// use rustc::mir::*; +use syntax::ast::{NodeId, Attribute}; +use syntax_pos::Span; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; +use crate::utils::{span_lint, is_entrypoint_fn}; + +/// **What it does:** +/// +/// Suggests the use of `const` in functions and methods where possible +/// +/// **Why is this bad?** +/// Not using `const` is a missed optimization. Instead of having the function execute at runtime, +/// when using `const`, it's evaluated at compiletime. +/// +/// **Known problems:** +/// +/// Const functions are currently still being worked on, with some features only being available +/// on nightly. This lint does not consider all edge cases currently and the suggestions may be +/// incorrect if you are using this lint on stable. +/// +/// Also, the lint only runs one pass over the code. Consider these two non-const functions: +/// +/// ```rust +/// fn a() -> i32 { 0 } +/// fn b() -> i32 { a() } +/// ``` +/// +/// When running Clippy, the lint will only suggest to make `a` const, because `b` at this time +/// can't be const as it calls a non-const function. Making `a` const and running Clippy again, +/// will suggest to make `b` const, too. +/// +/// **Example:** +/// +/// ```rust +/// fn new() -> Self { +/// Self { +/// random_number: 42 +/// } +/// } +/// ``` +/// +/// Could be a const fn: +/// +/// ```rust +/// const fn new() -> Self { +/// Self { +/// random_number: 42 +/// } +/// } +/// ``` +declare_clippy_lint! { + pub MISSING_CONST_FOR_FN, + nursery, + "Lint functions definitions that could be made `const fn`" +} + +#[derive(Clone)] +pub struct MissingConstForFn; + +impl LintPass for MissingConstForFn { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_CONST_FOR_FN) + } + + fn name(&self) -> &'static str { + "MissingConstForFn" + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { + fn check_fn( + &mut self, + cx: &LateContext<'_, '_>, + kind: FnKind<'_>, + _: &FnDecl, + _: &Body, + span: Span, + node_id: NodeId + ) { + let def_id = cx.tcx.hir().local_def_id(node_id); + let mir = cx.tcx.optimized_mir(def_id); + if let Ok(_) = is_min_const_fn(cx.tcx, def_id, &mir) { + match kind { + FnKind::ItemFn(name, _generics, header, _vis, attrs) => { + if !can_be_const_fn(&name.as_str(), header, attrs) { + return; + } + }, + FnKind::Method(ident, sig, _vis, attrs) => { + let header = sig.header; + let name = ident.name.as_str(); + if !can_be_const_fn(&name, header, attrs) { + return; + } + }, + _ => return + } + span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a const_fn"); + } + } +} + +fn can_be_const_fn(name: &str, header: hir::FnHeader, attrs: &[Attribute]) -> bool { + // Main and custom entrypoints can't be `const` + if is_entrypoint_fn(name, attrs) { return false } + + // We don't have to lint on something that's already `const` + if header.constness == Constness::Const { return false } + true +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2b2b3e8b2f6..f06a257b5ca 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -350,6 +350,19 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option bool { + + let is_custom_entrypoint = attrs.iter().any(|attr| { + attr.path.segments.len() == 1 + && attr.path.segments[0].ident.to_string() == "start" + }); + + is_custom_entrypoint || fn_name == "main" +} + /// Get the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { let parent_id = cx.tcx.hir().get_parent(expr.id); diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs new file mode 100644 index 00000000000..5f00035b3ad --- /dev/null +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -0,0 +1,50 @@ +//! False-positive tests to ensure we don't suggest `const` for things where it would cause a +//! compilation error. +//! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. + +#![warn(clippy::missing_const_for_fn)] +#![feature(start)] + +struct Game; + +// This should not be linted because it's already const +const fn already_const() -> i32 { 32 } + +impl Game { + // This should not be linted because it's already const + pub const fn already_const() -> i32 { 32 } +} + +// Allowing on this function, because it would lint, which we don't want in this case. +#[allow(clippy::missing_const_for_fn)] +fn random() -> u32 { 42 } + +// We should not suggest to make this function `const` because `random()` is non-const +fn random_caller() -> u32 { + random() +} + +static Y: u32 = 0; + +// We should not suggest to make this function `const` because const functions are not allowed to +// refer to a static variable +fn get_y() -> u32 { + Y + //~^ ERROR E0013 +} + +// Also main should not be suggested to be made const +fn main() { + // We should also be sure to not lint on closures + let add_one_v2 = |x: u32| -> u32 { x + 1 }; +} + +trait Foo { + // This should not be suggested to be made const + // (rustc restriction) + fn f() -> u32; +} + +// Don't lint custom entrypoints either +#[start] +fn init(num: isize, something: *const *const u8) -> isize { 1 } diff --git a/tests/ui/missing_const_for_fn/cant_be_const.stderr b/tests/ui/missing_const_for_fn/cant_be_const.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs new file mode 100644 index 00000000000..3ba39711e8d --- /dev/null +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -0,0 +1,53 @@ +#![warn(clippy::missing_const_for_fn)] +#![allow(clippy::let_and_return)] + +use std::mem::transmute; + +struct Game { + guess: i32, +} + +impl Game { + // Could be const + pub fn new() -> Self { + Self { + guess: 42, + } + } +} + +// Could be const +fn one() -> i32 { 1 } + +// Could also be const +fn two() -> i32 { + let abc = 2; + abc +} + +// TODO: Why can this be const? because it's a zero sized type? +// There is the `const_string_new` feature, but it seems that this already works in const fns? +fn string() -> String { + String::new() +} + +// Could be const +unsafe fn four() -> i32 { 4 } + +// Could also be const +fn generic(t: T) -> T { + t +} + +// FIXME: This could be const but is currently not linted +fn sub(x: u32) -> usize { + unsafe { transmute(&x) } +} + +// FIXME: This could be const but is currently not linted +fn generic_arr(t: [T; 1]) -> T { + t[0] +} + +// Should not be const +fn main() {} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr new file mode 100644 index 00000000000..09350572e99 --- /dev/null +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -0,0 +1,42 @@ +error: this could be a const_fn + --> $DIR/could_be_const.rs:12:5 + | +LL | / pub fn new() -> Self { +LL | | Self { +LL | | guess: 42, +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` + +error: this could be a const_fn + --> $DIR/could_be_const.rs:20:1 + | +LL | fn one() -> i32 { 1 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error: this could be a const_fn + --> $DIR/could_be_const.rs:30:1 + | +LL | / fn string() -> String { +LL | | String::new() +LL | | } + | |_^ + +error: this could be a const_fn + --> $DIR/could_be_const.rs:35:1 + | +LL | unsafe fn four() -> i32 { 4 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this could be a const_fn + --> $DIR/could_be_const.rs:38:1 + | +LL | / fn generic(t: T) -> T { +LL | | t +LL | | } + | |_^ + +error: aborting due to 5 previous errors + -- cgit 1.4.1-3-g733a5 From 68cc4df551ea289e542910226cd1429ff2310dfa Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 10 Jan 2019 20:33:24 +0100 Subject: Maybe fix ICE? --- clippy_lints/src/missing_const_for_fn.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 4751a538ebd..caa516acd24 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -84,7 +84,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { ) { let def_id = cx.tcx.hir().local_def_id(node_id); let mir = cx.tcx.optimized_mir(def_id); - if let Ok(_) = is_min_const_fn(cx.tcx, def_id, &mir) { + if let Err((span, err) = is_min_const_fn(cx.tcx, def_id, &mir) { + cx.tcx.sess.span_err(span, &err); + } else { match kind { FnKind::ItemFn(name, _generics, header, _vis, attrs) => { if !can_be_const_fn(&name.as_str(), header, attrs) { -- cgit 1.4.1-3-g733a5 From f9d65b6356abfc0503046232776cf6fdc43fb578 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 14 Jan 2019 16:44:10 +0100 Subject: Reorganize conditionals: Run faster checks first --- clippy_lints/src/missing_const_for_fn.rs | 40 +++++++++++++--------- tests/ui/missing_const_for_fn/cant_be_const.rs | 7 +++- .../ui/missing_const_for_fn/could_be_const.stderr | 11 +++++- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index caa516acd24..3e5c81484d5 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -82,26 +82,32 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { span: Span, node_id: NodeId ) { + // Perform some preliminary checks that rule out constness on the Clippy side. This way we + // can skip the actual const check and return early. + match kind { + FnKind::ItemFn(name, _generics, header, _vis, attrs) => { + if !can_be_const_fn(&name.as_str(), header, attrs) { + return; + } + }, + FnKind::Method(ident, sig, _vis, attrs) => { + let header = sig.header; + let name = ident.name.as_str(); + if !can_be_const_fn(&name, header, attrs) { + return; + } + }, + _ => return + } + let def_id = cx.tcx.hir().local_def_id(node_id); let mir = cx.tcx.optimized_mir(def_id); - if let Err((span, err) = is_min_const_fn(cx.tcx, def_id, &mir) { - cx.tcx.sess.span_err(span, &err); - } else { - match kind { - FnKind::ItemFn(name, _generics, header, _vis, attrs) => { - if !can_be_const_fn(&name.as_str(), header, attrs) { - return; - } - }, - FnKind::Method(ident, sig, _vis, attrs) => { - let header = sig.header; - let name = ident.name.as_str(); - if !can_be_const_fn(&name, header, attrs) { - return; - } - }, - _ => return + + if let Err((span, err)) = is_min_const_fn(cx.tcx, def_id, &mir) { + if cx.tcx.is_min_const_fn(def_id) { + cx.tcx.sess.span_err(span, &err); } + } else { span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a const_fn"); } } diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index 5f00035b3ad..cfaf01cf3c1 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -41,8 +41,13 @@ fn main() { trait Foo { // This should not be suggested to be made const - // (rustc restriction) + // (rustc doesn't allow const trait methods) fn f() -> u32; + + // This should not be suggested to be made const either + fn g() -> u32 { + 33 + } } // Don't lint custom entrypoints either diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 09350572e99..593f9cf810a 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -16,6 +16,15 @@ error: this could be a const_fn LL | fn one() -> i32 { 1 } | ^^^^^^^^^^^^^^^^^^^^^ +error: this could be a const_fn + --> $DIR/could_be_const.rs:23:1 + | +LL | / fn two() -> i32 { +LL | | let abc = 2; +LL | | abc +LL | | } + | |_^ + error: this could be a const_fn --> $DIR/could_be_const.rs:30:1 | @@ -38,5 +47,5 @@ LL | | t LL | | } | |_^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -- cgit 1.4.1-3-g733a5 From c0a02691d87559cc1f8ff577f6bdb140a619ee7f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 21 Jan 2019 07:54:05 +0100 Subject: cargo fmt --- clippy_lints/src/missing_const_for_fn.rs | 36 ++++++++++++---------- clippy_lints/src/utils/mod.rs | 8 ++--- tests/ui/missing_const_for_fn/cant_be_const.rs | 18 ++++++++--- tests/ui/missing_const_for_fn/could_be_const.rs | 12 +++++--- .../ui/missing_const_for_fn/could_be_const.stderr | 20 ++++++------ 5 files changed, 54 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 3e5c81484d5..4e85d13332c 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,13 +1,13 @@ use rustc::hir; -use rustc::hir::{Body, FnDecl, Constness}; use rustc::hir::intravisit::FnKind; +use rustc::hir::{Body, Constness, FnDecl}; // use rustc::mir::*; -use syntax::ast::{NodeId, Attribute}; -use syntax_pos::Span; +use crate::utils::{is_entrypoint_fn, span_lint}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; -use crate::utils::{span_lint, is_entrypoint_fn}; +use syntax::ast::{Attribute, NodeId}; +use syntax_pos::Span; /// **What it does:** /// @@ -26,8 +26,12 @@ use crate::utils::{span_lint, is_entrypoint_fn}; /// Also, the lint only runs one pass over the code. Consider these two non-const functions: /// /// ```rust -/// fn a() -> i32 { 0 } -/// fn b() -> i32 { a() } +/// fn a() -> i32 { +/// 0 +/// } +/// fn b() -> i32 { +/// a() +/// } /// ``` /// /// When running Clippy, the lint will only suggest to make `a` const, because `b` at this time @@ -38,9 +42,7 @@ use crate::utils::{span_lint, is_entrypoint_fn}; /// /// ```rust /// fn new() -> Self { -/// Self { -/// random_number: 42 -/// } +/// Self { random_number: 42 } /// } /// ``` /// @@ -48,9 +50,7 @@ use crate::utils::{span_lint, is_entrypoint_fn}; /// /// ```rust /// const fn new() -> Self { -/// Self { -/// random_number: 42 -/// } +/// Self { random_number: 42 } /// } /// ``` declare_clippy_lint! { @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { _: &FnDecl, _: &Body, span: Span, - node_id: NodeId + node_id: NodeId, ) { // Perform some preliminary checks that rule out constness on the Clippy side. This way we // can skip the actual const check and return early. @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { return; } }, - _ => return + _ => return, } let def_id = cx.tcx.hir().local_def_id(node_id); @@ -115,9 +115,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { fn can_be_const_fn(name: &str, header: hir::FnHeader, attrs: &[Attribute]) -> bool { // Main and custom entrypoints can't be `const` - if is_entrypoint_fn(name, attrs) { return false } + if is_entrypoint_fn(name, attrs) { + return false; + } // We don't have to lint on something that's already `const` - if header.constness == Constness::Const { return false } + if header.constness == Constness::Const { + return false; + } true } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index f06a257b5ca..32fe5e22dd5 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -354,11 +354,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option bool { - - let is_custom_entrypoint = attrs.iter().any(|attr| { - attr.path.segments.len() == 1 - && attr.path.segments[0].ident.to_string() == "start" - }); + let is_custom_entrypoint = attrs + .iter() + .any(|attr| attr.path.segments.len() == 1 && attr.path.segments[0].ident.to_string() == "start"); is_custom_entrypoint || fn_name == "main" } diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index cfaf01cf3c1..ede3724cc6b 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -8,16 +8,22 @@ struct Game; // This should not be linted because it's already const -const fn already_const() -> i32 { 32 } +const fn already_const() -> i32 { + 32 +} impl Game { // This should not be linted because it's already const - pub const fn already_const() -> i32 { 32 } + pub const fn already_const() -> i32 { + 32 + } } // Allowing on this function, because it would lint, which we don't want in this case. #[allow(clippy::missing_const_for_fn)] -fn random() -> u32 { 42 } +fn random() -> u32 { + 42 +} // We should not suggest to make this function `const` because `random()` is non-const fn random_caller() -> u32 { @@ -30,7 +36,7 @@ static Y: u32 = 0; // refer to a static variable fn get_y() -> u32 { Y - //~^ ERROR E0013 + //~^ ERROR E0013 } // Also main should not be suggested to be made const @@ -52,4 +58,6 @@ trait Foo { // Don't lint custom entrypoints either #[start] -fn init(num: isize, something: *const *const u8) -> isize { 1 } +fn init(num: isize, something: *const *const u8) -> isize { + 1 +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 3ba39711e8d..2c0a8e7a3c1 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -10,14 +10,14 @@ struct Game { impl Game { // Could be const pub fn new() -> Self { - Self { - guess: 42, - } + Self { guess: 42 } } } // Could be const -fn one() -> i32 { 1 } +fn one() -> i32 { + 1 +} // Could also be const fn two() -> i32 { @@ -32,7 +32,9 @@ fn string() -> String { } // Could be const -unsafe fn four() -> i32 { 4 } +unsafe fn four() -> i32 { + 4 +} // Could also be const fn generic(t: T) -> T { diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 593f9cf810a..22ea852905d 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -2,19 +2,19 @@ error: this could be a const_fn --> $DIR/could_be_const.rs:12:5 | LL | / pub fn new() -> Self { -LL | | Self { -LL | | guess: 42, -LL | | } +LL | | Self { guess: 42 } LL | | } | |_____^ | = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a const_fn - --> $DIR/could_be_const.rs:20:1 + --> $DIR/could_be_const.rs:18:1 | -LL | fn one() -> i32 { 1 } - | ^^^^^^^^^^^^^^^^^^^^^ +LL | / fn one() -> i32 { +LL | | 1 +LL | | } + | |_^ error: this could be a const_fn --> $DIR/could_be_const.rs:23:1 @@ -36,11 +36,13 @@ LL | | } error: this could be a const_fn --> $DIR/could_be_const.rs:35:1 | -LL | unsafe fn four() -> i32 { 4 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / unsafe fn four() -> i32 { +LL | | 4 +LL | | } + | |_^ error: this could be a const_fn - --> $DIR/could_be_const.rs:38:1 + --> $DIR/could_be_const.rs:40:1 | LL | / fn generic(t: T) -> T { LL | | t -- cgit 1.4.1-3-g733a5 From 0c6bdda562a0b703214657d92dcfa85b78537daf Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 22 Jan 2019 07:36:15 +0100 Subject: Use built-in entry_fn detection over self-built --- clippy_lints/src/missing_const_for_fn.rs | 33 +++++++++++--------------- clippy_lints/src/utils/mod.rs | 17 ++++++------- tests/ui/missing_const_for_fn/cant_be_const.rs | 14 ++++------- 3 files changed, 25 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 4e85d13332c..2afde0c9315 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -6,7 +6,7 @@ use crate::utils::{is_entrypoint_fn, span_lint}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; -use syntax::ast::{Attribute, NodeId}; +use syntax::ast::NodeId; use syntax_pos::Span; /// **What it does:** @@ -82,25 +82,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { span: Span, node_id: NodeId, ) { + let def_id = cx.tcx.hir().local_def_id(node_id); + + if is_entrypoint_fn(cx, def_id) { + return; + } + // Perform some preliminary checks that rule out constness on the Clippy side. This way we // can skip the actual const check and return early. match kind { - FnKind::ItemFn(name, _generics, header, _vis, attrs) => { - if !can_be_const_fn(&name.as_str(), header, attrs) { + FnKind::ItemFn(_, _, header, ..) => { + if already_const(header) { return; } }, - FnKind::Method(ident, sig, _vis, attrs) => { - let header = sig.header; - let name = ident.name.as_str(); - if !can_be_const_fn(&name, header, attrs) { + FnKind::Method(_, sig, ..) => { + if already_const(sig.header) { return; } }, _ => return, } - let def_id = cx.tcx.hir().local_def_id(node_id); let mir = cx.tcx.optimized_mir(def_id); if let Err((span, err)) = is_min_const_fn(cx.tcx, def_id, &mir) { @@ -113,15 +116,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { } } -fn can_be_const_fn(name: &str, header: hir::FnHeader, attrs: &[Attribute]) -> bool { - // Main and custom entrypoints can't be `const` - if is_entrypoint_fn(name, attrs) { - return false; - } - - // We don't have to lint on something that's already `const` - if header.constness == Constness::Const { - return false; - } - true +// We don't have to lint on something that's already `const` +fn already_const(header: hir::FnHeader) -> bool { + header.constness == Constness::Const } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 32fe5e22dd5..8ce28bfed1f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use matches::matches; use rustc::hir; use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::Node; use rustc::hir::*; @@ -350,15 +350,12 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option bool { - let is_custom_entrypoint = attrs - .iter() - .any(|attr| attr.path.segments.len() == 1 && attr.path.segments[0].ident.to_string() == "start"); - - is_custom_entrypoint || fn_name == "main" +/// Returns true if the provided `def_id` is an entrypoint to a program +pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { + if let Some((entry_fn_def_id, _)) = cx.tcx.entry_fn(LOCAL_CRATE) { + return def_id == entry_fn_def_id + } + false } /// Get the name of the item the expression is in, if available. diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index ede3724cc6b..36efe16b84f 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -39,10 +39,10 @@ fn get_y() -> u32 { //~^ ERROR E0013 } -// Also main should not be suggested to be made const -fn main() { - // We should also be sure to not lint on closures - let add_one_v2 = |x: u32| -> u32 { x + 1 }; +// Don't lint entrypoint functions +#[start] +fn init(num: isize, something: *const *const u8) -> isize { + 1 } trait Foo { @@ -55,9 +55,3 @@ trait Foo { 33 } } - -// Don't lint custom entrypoints either -#[start] -fn init(num: isize, something: *const *const u8) -> isize { - 1 -} -- cgit 1.4.1-3-g733a5 From aed001b8d4b318dab34882dafa27511e21bfa58a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 22 Jan 2019 07:59:09 +0100 Subject: Update various docs * `const_transmute` currently also seems to depend on the `const_fn` feature. * Only `Sized` is currently allowed as a bound, not Copy. --- clippy_lints/src/missing_const_for_fn.rs | 6 +++--- tests/ui/missing_const_for_fn/could_be_const.rs | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 2afde0c9315..9c9029a500b 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -11,11 +11,11 @@ use syntax_pos::Span; /// **What it does:** /// -/// Suggests the use of `const` in functions and methods where possible +/// Suggests the use of `const` in functions and methods where possible. /// /// **Why is this bad?** -/// Not using `const` is a missed optimization. Instead of having the function execute at runtime, -/// when using `const`, it's evaluated at compiletime. +/// +/// Not having the function const prevents callers of the function from being const as well. /// /// **Known problems:** /// diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 2c0a8e7a3c1..139e64de1ff 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -25,8 +25,8 @@ fn two() -> i32 { abc } -// TODO: Why can this be const? because it's a zero sized type? -// There is the `const_string_new` feature, but it seems that this already works in const fns? +// FIXME: This is a false positive in the `is_min_const_fn` function. +// At least until the `const_string_new` feature is stabilzed. fn string() -> String { String::new() } @@ -41,12 +41,14 @@ fn generic(t: T) -> T { t } -// FIXME: This could be const but is currently not linted +// FIXME: Depends on the `const_transmute` and `const_fn` feature gates. +// In the future Clippy should be able to suggest this as const, too. fn sub(x: u32) -> usize { unsafe { transmute(&x) } } -// FIXME: This could be const but is currently not linted +// NOTE: This is currently not yet allowed to be const +// Once implemented, Clippy should be able to suggest this as const, too. fn generic_arr(t: [T; 1]) -> T { t[0] } -- cgit 1.4.1-3-g733a5 From d0d7c5e92271c40b74e796bcf71758348a748553 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 23 Jan 2019 07:32:58 +0100 Subject: cargo fmt --- clippy_lints/src/missing_const_for_fn.rs | 3 +-- clippy_lints/src/utils/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 9c9029a500b..9228c586bbf 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,8 +1,7 @@ +use crate::utils::{is_entrypoint_fn, span_lint}; use rustc::hir; use rustc::hir::intravisit::FnKind; use rustc::hir::{Body, Constness, FnDecl}; -// use rustc::mir::*; -use crate::utils::{is_entrypoint_fn, span_lint}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8ce28bfed1f..ee3356fdc82 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use matches::matches; use rustc::hir; use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::Node; use rustc::hir::*; @@ -353,7 +353,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option, def_id: DefId) -> bool { if let Some((entry_fn_def_id, _)) = cx.tcx.entry_fn(LOCAL_CRATE) { - return def_id == entry_fn_def_id + return def_id == entry_fn_def_id; } false } -- cgit 1.4.1-3-g733a5 From 246b9e7aede03dc3a3f12f2a9585d6097e112e95 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 29 Jan 2019 20:00:45 +0100 Subject: fetch_prs_between: add .sh file ending --- util/fetch_prs_between | 20 -------------------- util/fetch_prs_between.sh | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 20 deletions(-) delete mode 100755 util/fetch_prs_between create mode 100755 util/fetch_prs_between.sh diff --git a/util/fetch_prs_between b/util/fetch_prs_between deleted file mode 100755 index dbe73b1ba98..00000000000 --- a/util/fetch_prs_between +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -# Fetches the merge commits between two git commits and prints the PR URL -# together with the full commit message -# -# If you want to use this to update the Clippy changelog, be sure to manually -# exclude the non-user facing changes like 'rustup' PRs, typo fixes, etc. - -first=$1 -last=$2 - -IFS=' -' -for pr in $(git log --oneline --grep "Merge #" --grep "Merge pull request" --grep "Auto merge of" "$first...$last" | sort -rn | uniq); do - id=$(echo $pr | rg -o '#[0-9]{3,5}' | cut -c 2-) - commit=$(echo $pr | cut -d' ' -f 1) - echo "URL: https://github.com/rust-lang/rust-clippy/pull/$id" - echo "$(git --no-pager show --pretty=medium $commit)" - echo "---------------------------------------------------------\n" -done diff --git a/util/fetch_prs_between.sh b/util/fetch_prs_between.sh new file mode 100755 index 00000000000..dbe73b1ba98 --- /dev/null +++ b/util/fetch_prs_between.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Fetches the merge commits between two git commits and prints the PR URL +# together with the full commit message +# +# If you want to use this to update the Clippy changelog, be sure to manually +# exclude the non-user facing changes like 'rustup' PRs, typo fixes, etc. + +first=$1 +last=$2 + +IFS=' +' +for pr in $(git log --oneline --grep "Merge #" --grep "Merge pull request" --grep "Auto merge of" "$first...$last" | sort -rn | uniq); do + id=$(echo $pr | rg -o '#[0-9]{3,5}' | cut -c 2-) + commit=$(echo $pr | cut -d' ' -f 1) + echo "URL: https://github.com/rust-lang/rust-clippy/pull/$id" + echo "$(git --no-pager show --pretty=medium $commit)" + echo "---------------------------------------------------------\n" +done -- cgit 1.4.1-3-g733a5 From 0da18677f733f392ef7fa8d833ade3b66bf83f9a Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Thu, 10 Jan 2019 14:56:28 -0600 Subject: Add match_wild lint (#3649). This lint prevents using a wildcard in a match. --- clippy_lints/src/matches.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b290980fc36..4be045175bb 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -187,6 +187,25 @@ declare_clippy_lint! { "a match on an Option value instead of using `as_ref()` or `as_mut`" } +/// **What it does:** Checks for wildcard matches using `_`. +/// +/// **Why is this bad?** New variants added by library updates can be missed. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// match x { +/// A => {}, +/// _ => {} +/// } +/// ``` +declare_clippy_lint! { + pub MATCH_WILD, + restriction, + "a wildcard match arm using `_`" +} + #[allow(missing_copy_implementations)] pub struct MatchPass; @@ -199,7 +218,8 @@ impl LintPass for MatchPass { SINGLE_MATCH_ELSE, MATCH_OVERLAPPING_ARM, MATCH_WILD_ERR_ARM, - MATCH_AS_REF + MATCH_AS_REF, + MATCH_WILD ) } @@ -218,6 +238,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); check_wild_err_arm(cx, ex, arms); + check_wild_arm(cx, ex, arms); check_match_as_ref(cx, ex, arms, expr); } if let ExprKind::Match(ref ex, ref arms, _) = expr.node { @@ -442,6 +463,22 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { } } +fn check_wild_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { + let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); + if match_type(cx, ex_ty, &paths::RESULT) { + for arm in arms { + if is_wild(&arm.pats[0]) { + span_note_and_lint(cx, + MATCH_WILD, + arm.pats[0].span, + "Wildcard match will miss any future added variants.", + arm.pats[0].span, + "to resolve, match each variant explicitly"); + } + } + } +} + // If the block contains only a `panic!` macro (as expression or statement) fn is_panic_block(block: &Block) -> bool { match (&block.expr, block.stmts.len(), block.stmts.first()) { -- cgit 1.4.1-3-g733a5 From 1b3c3d073af9a022b7cfb620d455d25415f7ddc4 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Sat, 12 Jan 2019 17:45:16 -0600 Subject: Change match_wild lint name to WILDCARD_MATCH_ARM. Also fix message capitalization. --- clippy_lints/src/matches.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 4be045175bb..bdade6ee19e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -201,7 +201,7 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub MATCH_WILD, + pub WILDCARD_MATCH_ARM, restriction, "a wildcard match arm using `_`" } @@ -219,7 +219,7 @@ impl LintPass for MatchPass { MATCH_OVERLAPPING_ARM, MATCH_WILD_ERR_ARM, MATCH_AS_REF, - MATCH_WILD + WILDCARD_MATCH_ARM ) } @@ -469,9 +469,9 @@ fn check_wild_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { for arm in arms { if is_wild(&arm.pats[0]) { span_note_and_lint(cx, - MATCH_WILD, + WILDCARD_MATCH_ARM, arm.pats[0].span, - "Wildcard match will miss any future added variants.", + "wildcard match will miss any future added variants.", arm.pats[0].span, "to resolve, match each variant explicitly"); } -- cgit 1.4.1-3-g733a5 From 20ba476ea85b0d01fc468c565770f1fb61132273 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Fri, 25 Jan 2019 10:39:09 -0600 Subject: wildcard_match_arm: expand lint scope. We're not only working with Results. --- clippy_lints/src/matches.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index bdade6ee19e..9d4279ad1bc 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -464,17 +464,14 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { } fn check_wild_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { - let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); - if match_type(cx, ex_ty, &paths::RESULT) { - for arm in arms { - if is_wild(&arm.pats[0]) { - span_note_and_lint(cx, - WILDCARD_MATCH_ARM, - arm.pats[0].span, - "wildcard match will miss any future added variants.", - arm.pats[0].span, - "to resolve, match each variant explicitly"); - } + for arm in arms { + if is_wild(&arm.pats[0]) { + span_note_and_lint(cx, + WILDCARD_MATCH_ARM, + arm.pats[0].span, + "wildcard match will miss any future added variants.", + arm.pats[0].span, + "to resolve, match each variant explicitly"); } } } -- cgit 1.4.1-3-g733a5 From 068924198babed20c11715bb4f4acb9f2e470a9c Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Fri, 25 Jan 2019 10:42:11 -0600 Subject: wildcard_match_arm: add simple ui test. --- tests/ui/wildcard_match_arm.rs | 36 ++++++++++++++++++++++++++++++++++++ tests/ui/wildcard_match_arm.stderr | 15 +++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/ui/wildcard_match_arm.rs create mode 100644 tests/ui/wildcard_match_arm.stderr diff --git a/tests/ui/wildcard_match_arm.rs b/tests/ui/wildcard_match_arm.rs new file mode 100644 index 00000000000..26a37c969a3 --- /dev/null +++ b/tests/ui/wildcard_match_arm.rs @@ -0,0 +1,36 @@ +#![deny(clippy::wildcard_match_arm)] + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Color { + Red, + Green, + Blue, + Rgb(u8, u8, u8), + Cyan, +} + +impl Color { + fn is_monochrome(self) -> bool { + match self { + Color::Red | Color::Green | Color::Blue => true, + Color::Rgb(r, g, b) => r | g == 0 || r | b == 0 || g | b == 0, + Color::Cyan => false, + } + } +} + +fn main() { + let color = Color::Rgb(0, 0, 127); + match color { + Color::Red => println!("Red"), + _ => eprintln!("Not red"), + }; + match color { + Color::Red => {}, + Color::Green => {}, + Color::Blue => {}, + Color::Cyan => {}, + c if c.is_monochrome() => {}, + Color::Rgb(_, _, _) => {}, + }; +} \ No newline at end of file diff --git a/tests/ui/wildcard_match_arm.stderr b/tests/ui/wildcard_match_arm.stderr new file mode 100644 index 00000000000..0d10382dc15 --- /dev/null +++ b/tests/ui/wildcard_match_arm.stderr @@ -0,0 +1,15 @@ +error: wildcard match will miss any future added variants. + --> $DIR/wildcard_match_arm.rs:26:3 + | +LL | _ => eprintln!("Not red"), + | ^ + | +note: lint level defined here + --> $DIR/wildcard_match_arm.rs:1:9 + | +LL | #![deny(clippy::wildcard_match_arm)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: to resolve, match each variant explicitly + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 23eae0909db7f7315f083fa019ee301e93195fcc Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Fri, 25 Jan 2019 10:56:00 -0600 Subject: wildcard_match_arm: rename function. We also don't need `ex` as an argument. --- clippy_lints/src/matches.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 9d4279ad1bc..024c88b368c 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -238,7 +238,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); check_wild_err_arm(cx, ex, arms); - check_wild_arm(cx, ex, arms); + check_wild_match(cx, arms); check_match_as_ref(cx, ex, arms, expr); } if let ExprKind::Match(ref ex, ref arms, _) = expr.node { @@ -463,7 +463,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { } } -fn check_wild_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { +fn check_wild_match(cx: &LateContext<'_, '_>, arms: &[Arm]) { for arm in arms { if is_wild(&arm.pats[0]) { span_note_and_lint(cx, -- cgit 1.4.1-3-g733a5 From c75dfeb29bc9e8e259382fe8af3917e43f07a9e4 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Fri, 25 Jan 2019 11:06:19 -0600 Subject: wildcard_match_arm: add lint properly. --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0679d280c2..2ac88d09a53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1028,6 +1028,7 @@ All notable changes to this project will be documented in this file. [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator [`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies +[`wildcard_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_match_arm [`write_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_literal [`write_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_with_newline [`writeln_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#writeln_empty_string diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3483aae0ca3..f4ba38496be 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -499,6 +499,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { indexing_slicing::INDEXING_SLICING, inherent_impl::MULTIPLE_INHERENT_IMPL, literal_representation::DECIMAL_LITERAL_REPRESENTATION, + matches::WILDCARD_MATCH_ARM, mem_forget::MEM_FORGET, methods::CLONE_ON_REF_PTR, methods::OPTION_UNWRAP_USED, -- cgit 1.4.1-3-g733a5 From 6bc4416b2b41a9d655cef8de0ee3ef0d5632bbb1 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Sun, 27 Jan 2019 15:41:22 -0600 Subject: wilcard_match_arm: run rustfmt. --- clippy_lints/src/matches.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 024c88b368c..0245b5a1362 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -197,7 +197,7 @@ declare_clippy_lint! { /// ```rust /// match x { /// A => {}, -/// _ => {} +/// _ => {}, /// } /// ``` declare_clippy_lint! { @@ -466,12 +466,14 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { fn check_wild_match(cx: &LateContext<'_, '_>, arms: &[Arm]) { for arm in arms { if is_wild(&arm.pats[0]) { - span_note_and_lint(cx, + span_note_and_lint( + cx, WILDCARD_MATCH_ARM, arm.pats[0].span, "wildcard match will miss any future added variants.", arm.pats[0].span, - "to resolve, match each variant explicitly"); + "to resolve, match each variant explicitly", + ); } } } -- cgit 1.4.1-3-g733a5 From c7ae44c0e2aad23e6ca74893a3e3ed1a060c0ff0 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Tue, 29 Jan 2019 12:23:11 -0600 Subject: wildcard_match_arm: format test. --- tests/ui/wildcard_match_arm.rs | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/ui/wildcard_match_arm.rs b/tests/ui/wildcard_match_arm.rs index 26a37c969a3..5d3a5ff2a75 100644 --- a/tests/ui/wildcard_match_arm.rs +++ b/tests/ui/wildcard_match_arm.rs @@ -2,35 +2,35 @@ #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Color { - Red, - Green, - Blue, - Rgb(u8, u8, u8), - Cyan, + Red, + Green, + Blue, + Rgb(u8, u8, u8), + Cyan, } impl Color { - fn is_monochrome(self) -> bool { - match self { - Color::Red | Color::Green | Color::Blue => true, - Color::Rgb(r, g, b) => r | g == 0 || r | b == 0 || g | b == 0, - Color::Cyan => false, - } - } + fn is_monochrome(self) -> bool { + match self { + Color::Red | Color::Green | Color::Blue => true, + Color::Rgb(r, g, b) => r | g == 0 || r | b == 0 || g | b == 0, + Color::Cyan => false, + } + } } fn main() { - let color = Color::Rgb(0, 0, 127); - match color { - Color::Red => println!("Red"), - _ => eprintln!("Not red"), - }; - match color { - Color::Red => {}, - Color::Green => {}, - Color::Blue => {}, - Color::Cyan => {}, - c if c.is_monochrome() => {}, - Color::Rgb(_, _, _) => {}, - }; -} \ No newline at end of file + let color = Color::Rgb(0, 0, 127); + match color { + Color::Red => println!("Red"), + _ => eprintln!("Not red"), + }; + match color { + Color::Red => {}, + Color::Green => {}, + Color::Blue => {}, + Color::Cyan => {}, + c if c.is_monochrome() => {}, + Color::Rgb(_, _, _) => {}, + }; +} -- cgit 1.4.1-3-g733a5 From c676578097eb785cc3933ce363a93affc726ff51 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Tue, 29 Jan 2019 12:39:01 -0600 Subject: wildcard_match_arm: update ui test stderr --- tests/ui/wildcard_match_arm.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/wildcard_match_arm.stderr b/tests/ui/wildcard_match_arm.stderr index 0d10382dc15..b78a82f60b5 100644 --- a/tests/ui/wildcard_match_arm.stderr +++ b/tests/ui/wildcard_match_arm.stderr @@ -1,5 +1,5 @@ error: wildcard match will miss any future added variants. - --> $DIR/wildcard_match_arm.rs:26:3 + --> $DIR/wildcard_match_arm.rs:26:9 | LL | _ => eprintln!("Not red"), | ^ -- cgit 1.4.1-3-g733a5 From efaed8e0c0bc67d46a647a0ceb94b4b095ce04db Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Tue, 29 Jan 2019 14:25:40 -0600 Subject: wildcard_match_arm: lint only enum matches. --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/matches.rs | 36 +++++++++++++++------------- tests/ui/wildcard_enum_match_arm.rs | 42 +++++++++++++++++++++++++++++++++ tests/ui/wildcard_enum_match_arm.stderr | 15 ++++++++++++ tests/ui/wildcard_match_arm.rs | 36 ---------------------------- tests/ui/wildcard_match_arm.stderr | 15 ------------ 7 files changed, 78 insertions(+), 70 deletions(-) create mode 100644 tests/ui/wildcard_enum_match_arm.rs create mode 100644 tests/ui/wildcard_enum_match_arm.stderr delete mode 100644 tests/ui/wildcard_match_arm.rs delete mode 100644 tests/ui/wildcard_match_arm.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac88d09a53..71066aadfcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1028,7 +1028,7 @@ All notable changes to this project will be documented in this file. [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator [`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies -[`wildcard_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_match_arm +[`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm [`write_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_literal [`write_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_with_newline [`writeln_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#writeln_empty_string diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f4ba38496be..52cc2a88da4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -499,7 +499,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { indexing_slicing::INDEXING_SLICING, inherent_impl::MULTIPLE_INHERENT_IMPL, literal_representation::DECIMAL_LITERAL_REPRESENTATION, - matches::WILDCARD_MATCH_ARM, + matches::WILDCARD_ENUM_MATCH_ARM, mem_forget::MEM_FORGET, methods::CLONE_ON_REF_PTR, methods::OPTION_UNWRAP_USED, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 0245b5a1362..e0094b19998 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -187,9 +187,9 @@ declare_clippy_lint! { "a match on an Option value instead of using `as_ref()` or `as_mut`" } -/// **What it does:** Checks for wildcard matches using `_`. +/// **What it does:** Checks for wildcard enum matches using `_`. /// -/// **Why is this bad?** New variants added by library updates can be missed. +/// **Why is this bad?** New enum variants added by library updates can be missed. /// /// **Known problems:** None. /// @@ -201,9 +201,9 @@ declare_clippy_lint! { /// } /// ``` declare_clippy_lint! { - pub WILDCARD_MATCH_ARM, + pub WILDCARD_ENUM_MATCH_ARM, restriction, - "a wildcard match arm using `_`" + "a wildcard enum match arm using `_`" } #[allow(missing_copy_implementations)] @@ -219,7 +219,7 @@ impl LintPass for MatchPass { MATCH_OVERLAPPING_ARM, MATCH_WILD_ERR_ARM, MATCH_AS_REF, - WILDCARD_MATCH_ARM + WILDCARD_ENUM_MATCH_ARM ) } @@ -238,7 +238,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); check_wild_err_arm(cx, ex, arms); - check_wild_match(cx, arms); + check_wild_enum_match(cx, ex, arms); check_match_as_ref(cx, ex, arms, expr); } if let ExprKind::Match(ref ex, ref arms, _) = expr.node { @@ -463,17 +463,19 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { } } -fn check_wild_match(cx: &LateContext<'_, '_>, arms: &[Arm]) { - for arm in arms { - if is_wild(&arm.pats[0]) { - span_note_and_lint( - cx, - WILDCARD_MATCH_ARM, - arm.pats[0].span, - "wildcard match will miss any future added variants.", - arm.pats[0].span, - "to resolve, match each variant explicitly", - ); +fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { + if cx.tables.expr_ty(ex).is_enum() { + for arm in arms { + if is_wild(&arm.pats[0]) { + span_note_and_lint( + cx, + WILDCARD_ENUM_MATCH_ARM, + arm.pats[0].span, + "wildcard match will miss any future added variants.", + arm.pats[0].span, + "to resolve, match each variant explicitly", + ); + } } } } diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs new file mode 100644 index 00000000000..58daabf4268 --- /dev/null +++ b/tests/ui/wildcard_enum_match_arm.rs @@ -0,0 +1,42 @@ +#![deny(clippy::wildcard_enum_match_arm)] + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Color { + Red, + Green, + Blue, + Rgb(u8, u8, u8), + Cyan, +} + +impl Color { + fn is_monochrome(self) -> bool { + match self { + Color::Red | Color::Green | Color::Blue => true, + Color::Rgb(r, g, b) => r | g == 0 || r | b == 0 || g | b == 0, + Color::Cyan => false, + } + } +} + +fn main() { + let color = Color::Rgb(0, 0, 127); + match color { + Color::Red => println!("Red"), + _ => eprintln!("Not red"), + }; + match color { + Color::Red => {}, + Color::Green => {}, + Color::Blue => {}, + Color::Cyan => {}, + c if c.is_monochrome() => {}, + Color::Rgb(_, _, _) => {}, + }; + let x: u8 = unimplemented!(); + match x { + 0 => {}, + 140 => {}, + _ => {}, + }; +} diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr new file mode 100644 index 00000000000..6319a3f3d46 --- /dev/null +++ b/tests/ui/wildcard_enum_match_arm.stderr @@ -0,0 +1,15 @@ +error: wildcard match will miss any future added variants. + --> $DIR/wildcard_enum_match_arm.rs:26:9 + | +LL | _ => eprintln!("Not red"), + | ^ + | +note: lint level defined here + --> $DIR/wildcard_enum_match_arm.rs:1:9 + | +LL | #![deny(clippy::wildcard_enum_match_arm)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: to resolve, match each variant explicitly + +error: aborting due to previous error + diff --git a/tests/ui/wildcard_match_arm.rs b/tests/ui/wildcard_match_arm.rs deleted file mode 100644 index 5d3a5ff2a75..00000000000 --- a/tests/ui/wildcard_match_arm.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![deny(clippy::wildcard_match_arm)] - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum Color { - Red, - Green, - Blue, - Rgb(u8, u8, u8), - Cyan, -} - -impl Color { - fn is_monochrome(self) -> bool { - match self { - Color::Red | Color::Green | Color::Blue => true, - Color::Rgb(r, g, b) => r | g == 0 || r | b == 0 || g | b == 0, - Color::Cyan => false, - } - } -} - -fn main() { - let color = Color::Rgb(0, 0, 127); - match color { - Color::Red => println!("Red"), - _ => eprintln!("Not red"), - }; - match color { - Color::Red => {}, - Color::Green => {}, - Color::Blue => {}, - Color::Cyan => {}, - c if c.is_monochrome() => {}, - Color::Rgb(_, _, _) => {}, - }; -} diff --git a/tests/ui/wildcard_match_arm.stderr b/tests/ui/wildcard_match_arm.stderr deleted file mode 100644 index b78a82f60b5..00000000000 --- a/tests/ui/wildcard_match_arm.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: wildcard match will miss any future added variants. - --> $DIR/wildcard_match_arm.rs:26:9 - | -LL | _ => eprintln!("Not red"), - | ^ - | -note: lint level defined here - --> $DIR/wildcard_match_arm.rs:1:9 - | -LL | #![deny(clippy::wildcard_match_arm)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: to resolve, match each variant explicitly - -error: aborting due to previous error - -- cgit 1.4.1-3-g733a5 From 587492b5d243273f7170ee9036ca18bbedbebc77 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Tue, 29 Jan 2019 14:34:04 -0600 Subject: wildcard_match_arm: add nesting issue to known. --- clippy_lints/src/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index e0094b19998..6ef07316691 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -191,7 +191,7 @@ declare_clippy_lint! { /// /// **Why is this bad?** New enum variants added by library updates can be missed. /// -/// **Known problems:** None. +/// **Known problems:** Nested wildcards a la `Foo(_)` are currently not detected. /// /// **Example:** /// ```rust -- cgit 1.4.1-3-g733a5 From 7fa50fb3fe98f3c6f837e95e6d13810c68ceaf74 Mon Sep 17 00:00:00 2001 From: Alex Hamilton Date: Tue, 29 Jan 2019 15:33:16 -0600 Subject: wildcard_match_arm: Update lint count. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dad18ef7569..c1f457a956e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 293 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 294 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From f894adce8cd93a9edf3ce0908920e514d837e0dd Mon Sep 17 00:00:00 2001 From: rhysd Date: Thu, 31 Jan 2019 02:39:38 +0900 Subject: implement dbg_macro rule (fixes #3721) --- clippy_lints/src/dbg_macro.rs | 51 +++++++++++++++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 4 ++++ tests/ui/dbg_macro.rs | 3 +++ tests/ui/dbg_macro.stderr | 10 +++++++++ 4 files changed, 68 insertions(+) create mode 100644 clippy_lints/src/dbg_macro.rs create mode 100644 tests/ui/dbg_macro.rs create mode 100644 tests/ui/dbg_macro.stderr diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs new file mode 100644 index 00000000000..fad012bf7a2 --- /dev/null +++ b/clippy_lints/src/dbg_macro.rs @@ -0,0 +1,51 @@ +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use crate::utils::span_lint; +use syntax::ast; + +/// **What it does:** Checks for usage of dbg!() macro not to have it in +/// version control. +/// +/// **Why is this bad?** `dbg!` macro is intended as a debugging tool. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust,ignore +/// // Bad +/// dbg!(true) +/// +/// // Good +/// true +/// ``` +declare_clippy_lint! { + pub DBG_MACRO, + style, + "`dbg!` macro is intended as a debugging tool" +} + +#[derive(Copy, Clone, Debug)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(DBG_MACRO) + } + + fn name(&self) -> &'static str { + "DbgMacro" + } +} + +impl EarlyLintPass for Pass { + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { + if mac.node.path == "dbg" { + span_lint( + cx, + DBG_MACRO, + mac.span, + "`dbg!` macro is intended as a debugging tool. ensure to avoid having uses of it in version control", + ); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 52cc2a88da4..9681e58914d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -94,6 +94,7 @@ pub mod const_static_lifetime; pub mod copies; pub mod copy_iterator; pub mod cyclomatic_complexity; +pub mod dbg_macro; pub mod default_trait_access; pub mod derive; pub mod doc; @@ -231,6 +232,7 @@ pub fn register_pre_expansion_lints( }, ); store.register_pre_expansion_pass(Some(session), true, false, box attrs::CfgAttrPass); + store.register_pre_expansion_pass(Some(session), true, false, box dbg_macro::Pass); } pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { @@ -589,6 +591,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { copies::IFS_SAME_COND, copies::IF_SAME_THEN_ELSE, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, + dbg_macro::DBG_MACRO, derive::DERIVE_HASH_XOR_EQ, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, @@ -800,6 +803,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, + dbg_macro::DBG_MACRO, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, eq_op::OP_REF, diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs new file mode 100644 index 00000000000..cf113050c26 --- /dev/null +++ b/tests/ui/dbg_macro.rs @@ -0,0 +1,3 @@ +fn main() { + dbg!(42); +} diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr new file mode 100644 index 00000000000..cb5389c6e76 --- /dev/null +++ b/tests/ui/dbg_macro.stderr @@ -0,0 +1,10 @@ +error: `dbg!` macro is intended as a debugging tool. ensure to avoid having uses of it in version control + --> $DIR/dbg_macro.rs:2:5 + | +LL | dbg!(42); + | ^^^^^^^^ + | + = note: `-D clippy::dbg-macro` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 3cf8c0b3b52f14bda9001855369b72eca9737c1d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 31 Jan 2019 06:20:49 +0200 Subject: Fix `cast_sign_loss` false positive This checks if the value is a non-negative constant before linting about losing the sign. Because the `constant` function doesn't handle const functions, we check if the value is from a call to a `max_value` function directly. A utility method called `get_def_path` was added to make checking for the function paths easier. Fixes #2728 --- clippy_lints/src/types.rs | 55 +++++++++++++++++++++++++++++++++++-------- clippy_lints/src/utils/mod.rs | 6 +++++ tests/ui/cast.rs | 8 +++++++ tests/ui/cast.stderr | 26 ++++++++------------ tests/ui/cast_size.stderr | 22 +---------------- 5 files changed, 70 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 94c83ed5720..3c0171ce8c6 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -4,8 +4,8 @@ use crate::consts::{constant, Constant}; use crate::reexport::*; use crate::utils::paths; use crate::utils::{ - clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, - match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, + clip, comparisons, differing_macro_contexts, get_def_path, higher, in_constant, in_macro, int_bits, + last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer, }; @@ -1001,6 +1001,48 @@ enum ArchSuffix { None, } +fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { + if !cast_from.is_signed() || cast_to.is_signed() { + return; + } + + // don't lint for positive constants + let const_val = constant(cx, &cx.tables, op); + if_chain! { + if let Some((const_val, _)) = const_val; + if let Constant::Int(n) = const_val; + if let ty::Int(ity) = cast_from.sty; + if sext(cx.tcx, n, ity) >= 0; + then { + return + } + } + + // don't lint for max_value const fns + if_chain! { + if let ExprKind::Call(callee, args) = &op.node; + if args.is_empty(); + if let ExprKind::Path(qpath) = &callee.node; + let def = cx.tables.qpath_def(qpath, callee.hir_id); + if let Some(def_id) = def.opt_def_id(); + let def_path = get_def_path(cx.tcx, def_id); + if let &["core", "num", impl_ty, "max_value"] = &def_path[..]; + then { + if let "" | "" | "" | + "" | "" = impl_ty { + return; + } + } + } + + span_lint( + cx, + CAST_SIGN_LOSS, + expr.span, + &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to), + ); +} + fn check_truncation_and_wrapping(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) { let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; @@ -1176,14 +1218,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } }, (true, true) => { - if cast_from.is_signed() && !cast_to.is_signed() { - span_lint( - cx, - CAST_SIGN_LOSS, - expr.span, - &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to), - ); - } + check_loss_of_sign(cx, expr, ex, cast_from, cast_to); check_truncation_and_wrapping(cx, expr, cast_from, cast_to); check_lossless(cx, expr, ex, cast_from, cast_to); }, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ee3356fdc82..b9cde75d51d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -130,6 +130,12 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) } +pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> { + let mut apb = AbsolutePathBuffer { names: vec![] }; + tcx.push_item_path(&mut apb, def_id, false); + apb.names.iter().map(|n| n.get()).collect() +} + /// Check if type is struct, enum or union type with given def path. pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.sty { diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 5f4de9894c7..c248b5bf598 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -34,7 +34,15 @@ fn main() { (1u8 + 1u8) as u16; // Test clippy::cast_sign_loss 1i32 as u32; + -1i32 as u32; 1isize as usize; + -1isize as usize; + 0i8 as u8; + i8::max_value() as u8; + i16::max_value() as u16; + i32::max_value() as u32; + i64::max_value() as u64; + i128::max_value() as u128; // Extra checks for *size // Test cast_unnecessary 1i32 as i32; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 92587312a53..c01393793f1 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -70,12 +70,6 @@ error: casting i32 to i8 may truncate the value LL | 1i32 as i8; | ^^^^^^^^^^ -error: casting i32 to u8 may lose the sign of the value - --> $DIR/cast.rs:22:5 - | -LL | 1i32 as u8; - | ^^^^^^^^^^ - error: casting i32 to u8 may truncate the value --> $DIR/cast.rs:22:5 | @@ -147,19 +141,19 @@ LL | (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:36:5 + --> $DIR/cast.rs:37:5 | -LL | 1i32 as u32; - | ^^^^^^^^^^^ +LL | -1i32 as u32; + | ^^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:39:5 | -LL | 1isize as usize; - | ^^^^^^^^^^^^^^^ +LL | -1isize as usize; + | ^^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:40:5 + --> $DIR/cast.rs:48:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ @@ -167,16 +161,16 @@ LL | 1i32 as i32; = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:49:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:42:5 + --> $DIR/cast.rs:50:5 | LL | false as bool; | ^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: aborting due to 27 previous errors diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index 9346deb19ec..a77aafaf11d 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -38,14 +38,6 @@ error: casting isize to i32 may truncate the value on targets with 64-bit wide p LL | 1isize as i32; | ^^^^^^^^^^^^^ -error: casting isize to u32 may lose the sign of the value - --> $DIR/cast_size.rs:17:5 - | -LL | 1isize as u32; - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::cast-sign-loss` implied by `-D warnings` - error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size.rs:17:5 | @@ -78,12 +70,6 @@ error: casting i64 to isize may truncate the value on targets with 32-bit wide p LL | 1i64 as isize; | ^^^^^^^^^^^^^ -error: casting i64 to usize may lose the sign of the value - --> $DIR/cast_size.rs:22:5 - | -LL | 1i64 as usize; - | ^^^^^^^^^^^^^ - error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size.rs:22:5 | @@ -114,11 +100,5 @@ error: casting u32 to isize may wrap around the value on targets with 32-bit wid LL | 1u32 as isize; | ^^^^^^^^^^^^^ -error: casting i32 to usize may lose the sign of the value - --> $DIR/cast_size.rs:28:5 - | -LL | 1i32 as usize; - | ^^^^^^^^^^^^^ - -error: aborting due to 19 previous errors +error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From ee7bad455b12f6c434e308d18f7128e86213163b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 31 Jan 2019 07:11:22 +0100 Subject: Some renamings: s/ast_ty/hir_ty and s/StructField/hir::StructField I think in both cases the new names make the code more understandable. For `StructField` specifically because there's one in [`syntax::ast`][ast] and one in [`rustc::hir`][hir]. [ast]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/struct.StructField.html [hir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.StructField.html --- clippy_lints/src/types.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4683ffb4c85..10be0c06d87 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { check_fn_decl(cx, decl); } - fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &StructField) { + fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField) { check_ty(cx, &field.ty, false); } @@ -240,13 +240,13 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) /// /// The parameter `is_local` distinguishes the context of the type; types from /// local bindings should only be checked for the `BORROWED_BOX` lint. -fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { - if in_macro(ast_ty.span) { +fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { + if in_macro(hir_ty.span) { return; } - match ast_ty.node { + match hir_ty.node { TyKind::Path(ref qpath) if !is_local => { - let hir_id = cx.tcx.hir().node_to_hir_id(ast_ty.id); + let hir_id = cx.tcx.hir().node_to_hir_id(hir_ty.id); let def = cx.tables.qpath_def(qpath, hir_id); if let Some(def_id) = opt_def_id(def) { if Some(def_id) == cx.tcx.lang_items().owned_box() { @@ -254,7 +254,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { span_help_and_lint( cx, BOX_VEC, - ast_ty.span, + hir_ty.span, "you seem to be trying to use `Box>`. Consider using just `Vec`", "`Vec` is already on the heap, `Box>` makes an extra allocation.", ); @@ -288,7 +288,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { span_lint_and_sugg( cx, VEC_BOX, - ast_ty.span, + hir_ty.span, "`Vec` is already on the heap, the boxing is unnecessary.", "try", format!("Vec<{}>", boxed_type), @@ -302,7 +302,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { span_lint( cx, OPTION_OPTION, - ast_ty.span, + hir_ty.span, "consider using `Option` instead of `Option>` or a custom \ enum if you need to distinguish all 3 cases", ); @@ -312,7 +312,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { span_help_and_lint( cx, LINKEDLIST, - ast_ty.span, + hir_ty.span, "I see you're using a LinkedList! Perhaps you meant some other data structure?", "a VecDeque might work", ); @@ -360,7 +360,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { }, } }, - TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty), + TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, hir_ty, is_local, lt, mut_ty), // recurse TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => { check_ty(cx, ty, is_local) @@ -374,7 +374,7 @@ fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { } } -fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { +fn check_ty_rptr(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) { match mut_ty.ty.node { TyKind::Path(ref qpath) => { let hir_id = cx.tcx.hir().node_to_hir_id(mut_ty.ty.id); @@ -410,7 +410,7 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: span_lint_and_sugg( cx, BORROWED_BOX, - ast_ty.span, + hir_ty.span, "you seem to be trying to use `&Box`. Consider using just `&T`", "try", format!( @@ -1317,7 +1317,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { self.check_fndecl(cx, decl); } - fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx StructField) { + fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField) { // enum variants are also struct fields now self.check_type(cx, &field.ty); } -- cgit 1.4.1-3-g733a5 From ec261a28f0a95bbc7010798741bc038b8b8890be Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 31 Jan 2019 08:27:04 +0100 Subject: Rustup: unused trim result --- tests/ui/single_char_pattern.fixed | 2 ++ tests/ui/single_char_pattern.rs | 2 ++ tests/ui/single_char_pattern.stderr | 40 ++++++++++++++++++------------------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index 220b855ead5..2dd21790389 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,5 +1,7 @@ // run-rustfix +#![allow(unused_must_use)] + use std::collections::HashSet; fn main() { diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 9650eb2af32..dc2f9fe4959 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,5 +1,7 @@ // run-rustfix +#![allow(unused_must_use)] + use std::collections::HashSet; fn main() { diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 82ef00bfee8..0fcb203dbc1 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,5 +1,5 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:7:13 + --> $DIR/single_char_pattern.rs:9:13 | LL | x.split("x"); | ^^^ help: try using a char instead: `'x'` @@ -7,115 +7,115 @@ LL | x.split("x"); = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:24:16 + --> $DIR/single_char_pattern.rs:26:16 | LL | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:25:19 + --> $DIR/single_char_pattern.rs:27:19 | LL | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:26:17 + --> $DIR/single_char_pattern.rs:28:17 | LL | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:27:12 + --> $DIR/single_char_pattern.rs:29:12 | LL | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:28:13 + --> $DIR/single_char_pattern.rs:30:13 | LL | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:29:14 + --> $DIR/single_char_pattern.rs:31:14 | LL | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:30:24 + --> $DIR/single_char_pattern.rs:32:24 | LL | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:31:25 + --> $DIR/single_char_pattern.rs:33:25 | LL | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:32:17 + --> $DIR/single_char_pattern.rs:34:17 | LL | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:18 + --> $DIR/single_char_pattern.rs:35:18 | LL | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:15 + --> $DIR/single_char_pattern.rs:36:15 | LL | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:16 + --> $DIR/single_char_pattern.rs:37:16 | LL | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:21 + --> $DIR/single_char_pattern.rs:38:21 | LL | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:22 + --> $DIR/single_char_pattern.rs:39:22 | LL | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:26 + --> $DIR/single_char_pattern.rs:40:26 | LL | x.trim_start_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:24 + --> $DIR/single_char_pattern.rs:41:24 | LL | x.trim_end_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:13 + --> $DIR/single_char_pattern.rs:43:13 | LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:31 + --> $DIR/single_char_pattern.rs:48:31 | LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:47:19 + --> $DIR/single_char_pattern.rs:49:19 | LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` -- cgit 1.4.1-3-g733a5 From 7ec5528e0c92f15f74c1e8b48502ce3a07a419cd Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 1 Feb 2019 09:23:40 +0900 Subject: fix category and use suggestion --- clippy_lints/src/dbg_macro.rs | 18 +++++++++++------- tests/ui/dbg_macro.rs | 2 ++ tests/ui/dbg_macro.stderr | 8 ++++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index fad012bf7a2..3dce8189b71 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,12 +1,13 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; -use crate::utils::span_lint; +use crate::utils::span_lint_and_sugg; use syntax::ast; +use rustc_errors::Applicability; -/// **What it does:** Checks for usage of dbg!() macro not to have it in -/// version control. +/// **What it does:** Checks for usage of dbg!() macro. /// -/// **Why is this bad?** `dbg!` macro is intended as a debugging tool. +/// **Why is this bad?** `dbg!` macro is intended as a debugging tool. It +/// should not be in version control. /// /// **Known problems:** None. /// @@ -20,7 +21,7 @@ use syntax::ast; /// ``` declare_clippy_lint! { pub DBG_MACRO, - style, + restriction, "`dbg!` macro is intended as a debugging tool" } @@ -40,11 +41,14 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { if mac.node.path == "dbg" { - span_lint( + span_lint_and_sugg( cx, DBG_MACRO, mac.span, - "`dbg!` macro is intended as a debugging tool. ensure to avoid having uses of it in version control", + "`dbg!` macro is intended as a debugging tool", + "ensure to avoid having uses of it in version control", + mac.node.tts.to_string(), // TODO: to string + Applicability::MaybeIncorrect, ); } } diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs index cf113050c26..dc96c7da0ac 100644 --- a/tests/ui/dbg_macro.rs +++ b/tests/ui/dbg_macro.rs @@ -1,3 +1,5 @@ +#![warn(clippy::dbg_macro)] + fn main() { dbg!(42); } diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr index cb5389c6e76..4b8501462ff 100644 --- a/tests/ui/dbg_macro.stderr +++ b/tests/ui/dbg_macro.stderr @@ -1,10 +1,14 @@ -error: `dbg!` macro is intended as a debugging tool. ensure to avoid having uses of it in version control - --> $DIR/dbg_macro.rs:2:5 +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:4:5 | LL | dbg!(42); | ^^^^^^^^ | = note: `-D clippy::dbg-macro` implied by `-D warnings` +help: ensure to avoid having uses of it in version control + | +LL | 42; + | ^^ error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 9d130a546fbf448680848809a271687c8a671c9d Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 1 Feb 2019 11:25:33 +0900 Subject: add dbg_macro rule to CHANGELOG.md and update count in README --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71066aadfcb..44616a55610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -772,6 +772,7 @@ All notable changes to this project will be documented in this file. [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator [`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute [`cyclomatic_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cyclomatic_complexity +[`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro [`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation [`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access diff --git a/README.md b/README.md index c1f457a956e..8519fe55a9f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 294 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 295 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9681e58914d..0ec872c80be 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -496,6 +496,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, arithmetic::INTEGER_ARITHMETIC, + dbg_macro::DBG_MACRO, else_if_without_else::ELSE_IF_WITHOUT_ELSE, implicit_return::IMPLICIT_RETURN, indexing_slicing::INDEXING_SLICING, @@ -591,7 +592,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { copies::IFS_SAME_COND, copies::IF_SAME_THEN_ELSE, cyclomatic_complexity::CYCLOMATIC_COMPLEXITY, - dbg_macro::DBG_MACRO, derive::DERIVE_HASH_XOR_EQ, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, @@ -803,7 +803,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, collapsible_if::COLLAPSIBLE_IF, const_static_lifetime::CONST_STATIC_LIFETIME, - dbg_macro::DBG_MACRO, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, eq_op::OP_REF, -- cgit 1.4.1-3-g733a5 From 06e4e9cf27c7aa5054068ad1aaf26a1b4ead97a1 Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 1 Feb 2019 11:39:35 +0900 Subject: remove TODO comment which was already done --- clippy_lints/src/dbg_macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 3dce8189b71..1759db1ca3a 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -47,7 +47,7 @@ impl EarlyLintPass for Pass { mac.span, "`dbg!` macro is intended as a debugging tool", "ensure to avoid having uses of it in version control", - mac.node.tts.to_string(), // TODO: to string + mac.node.tts.to_string(), Applicability::MaybeIncorrect, ); } -- cgit 1.4.1-3-g733a5 From b52a9bd9665218207015092ce574de86e3610df3 Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 1 Feb 2019 12:03:13 +0900 Subject: `cargo +nightly fmt` at clippy_lints/ --- clippy_lints/src/dbg_macro.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 1759db1ca3a..0bcca015c06 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,8 +1,8 @@ +use crate::utils::span_lint_and_sugg; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; -use crate::utils::span_lint_and_sugg; -use syntax::ast; use rustc_errors::Applicability; +use syntax::ast; /// **What it does:** Checks for usage of dbg!() macro. /// -- cgit 1.4.1-3-g733a5 From b6c3a6a09f339079aa1213226aa43b65a3fe0fe9 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 1 Feb 2019 06:32:16 +0200 Subject: Move `max_value` handling to consts module --- clippy_lints/src/consts.rs | 28 +++++++++++++++++++++++++++- clippy_lints/src/types.rs | 21 ++------------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 832fb875286..f56dc3aed69 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,6 +1,7 @@ #![allow(clippy::float_cmp)] -use crate::utils::{clip, sext, unsext}; +use crate::utils::{clip, get_def_path, sext, unsext}; +use if_chain::if_chain; use rustc::hir::def::Def; use rustc::hir::*; use rustc::lint::LateContext; @@ -234,6 +235,31 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { UnDeref => Some(o), }), ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right), + ExprKind::Call(ref callee, ref args) => { + // We only handle a few const functions for now + if_chain! { + if args.is_empty(); + if let ExprKind::Path(qpath) = &callee.node; + let def = self.tables.qpath_def(qpath, callee.hir_id); + if let Some(def_id) = def.opt_def_id(); + let def_path = get_def_path(self.tcx, def_id); + if let &["core", "num", impl_ty, "max_value"] = &def_path[..]; + then { + let value = match impl_ty { + "" => i8::max_value() as u128, + "" => i16::max_value() as u128, + "" => i32::max_value() as u128, + "" => i64::max_value() as u128, + "" => i128::max_value() as u128, + _ => return None, + }; + Some(Constant::Int(value)) + } + else { + None + } + } + }, // TODO: add other expressions _ => None, } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3c0171ce8c6..2c48e06e371 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -4,8 +4,8 @@ use crate::consts::{constant, Constant}; use crate::reexport::*; use crate::utils::paths; use crate::utils::{ - clip, comparisons, differing_macro_contexts, get_def_path, higher, in_constant, in_macro, int_bits, - last_path_segment, match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, + clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, + match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer, }; @@ -1018,23 +1018,6 @@ fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro } } - // don't lint for max_value const fns - if_chain! { - if let ExprKind::Call(callee, args) = &op.node; - if args.is_empty(); - if let ExprKind::Path(qpath) = &callee.node; - let def = cx.tables.qpath_def(qpath, callee.hir_id); - if let Some(def_id) = def.opt_def_id(); - let def_path = get_def_path(cx.tcx, def_id); - if let &["core", "num", impl_ty, "max_value"] = &def_path[..]; - then { - if let "" | "" | "" | - "" | "" = impl_ty { - return; - } - } - } - span_lint( cx, CAST_SIGN_LOSS, -- cgit 1.4.1-3-g733a5 From 4e39e65ad8ecb6419f52a2928c159660af4f611f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 07:34:36 +0100 Subject: Travis: Don't run integration tests on every PR commit This does not save Clippy any time but it makes sure that the concurrent build limit is not reached as quickly for the `rust-lang` Travis account. I can't create a permalink to the discussion somehow, so here's an excerpt from the Infra channel: ``` [11:57 PM] pietroalbini: there is a clippy build (20 jobs) and a packed_simd one (42 builders) and a rustc one which isn't scheduling atm [11:58 PM] pietroalbini: I don't think there is a way to prioritize rustc builds in the queue on travis, right? [12:22 AM] alexcrichton: pietro: I don't think so no [12:22 AM] alexcrichton: If it's a problem we should cull builds on other projects [12:22 AM] alexcrichton: The rust repo is the #1 priority ``` Since the integration tests are rarely failing these days, I think it's fine to not run them on every commit. If needed, it's also still possible to do a `try` build with `@bors try`. --- .travis.yml | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index d456497d997..3780f6ece79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,40 +39,48 @@ install: matrix: fast_finish: true include: + # Builds that are executed for every PR - os: osx # run base tests on both platforms env: BASE_TESTS=true + if: type = pull_request OR branch IN (auto, try) - os: linux env: BASE_TESTS=true + if: type = pull_request OR branch IN (auto, try) - os: windows env: CARGO_INCREMENTAL=0 BASE_TESTS=true + if: type = pull_request OR branch IN (auto, try) + + # Builds that are only executed when a PR is r+ed or a try build is started + # We don't want to run these always because they go towards + # the build limit within the Travis rust-lang account. - env: INTEGRATION=rust-lang/cargo - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-random/rand - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang-nursery/stdsimd - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang/rustfmt - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang-nursery/futures-rs - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang-nursery/failure - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang-nursery/log - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang-nursery/chalk - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang/rls - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=chronotope/chrono - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=serde-rs/serde - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=Geal/nom - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=hyperium/hyper - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=bluss/rust-itertools - if: repo =~ /^rust-lang\/rust-clippy$/ + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) allow_failures: - os: windows env: CARGO_INCREMENTAL=0 BASE_TESTS=true -- cgit 1.4.1-3-g733a5 From 4aff8711f0a047fca0f06627e94618f4da1f7e4f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 08:21:32 +0100 Subject: Fix ICE in vec_box lint and add run-rustfix `hir::Ty` doesn't seem to know anything about type bounds and `cx.tcx.type_of(def_id)` caused an ICE when it was passed a generic type with a bound: ``` src/librustc_typeck/collect.rs:1311: unexpected non-type Node::GenericParam: Type { default: None, synthetic: None } ``` Converting it to a proper `Ty` fixes the ICE and catches a few more places where the lint applies. --- clippy_lints/src/types.rs | 30 ++++++++++++++---------------- tests/ui/complex_types.rs | 2 +- tests/ui/vec_box_sized.fixed | 36 ++++++++++++++++++++++++++++++++++++ tests/ui/vec_box_sized.rs | 39 +++++++++++++++++++++++++++++---------- tests/ui/vec_box_sized.stderr | 20 ++++++++++++++++---- 5 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 tests/ui/vec_box_sized.fixed diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 939dd27c441..75e2f75ffcd 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -275,26 +275,24 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { if Some(def_id) == cx.tcx.lang_items().owned_box(); // At this point, we know ty is Box, now get T if let Some(ref last) = last_path_segment(ty_qpath).args; - if let Some(ty) = last.args.iter().find_map(|arg| match arg { + if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), GenericArg::Lifetime(_) => None, }); - if let TyKind::Path(ref ty_qpath) = ty.node; - let def = cx.tables.qpath_def(ty_qpath, ty.hir_id); - if let Some(def_id) = opt_def_id(def); - let boxed_type = cx.tcx.type_of(def_id); - if boxed_type.is_sized(cx.tcx.at(ty.span), cx.param_env); then { - span_lint_and_sugg( - cx, - VEC_BOX, - hir_ty.span, - "`Vec` is already on the heap, the boxing is unnecessary.", - "try", - format!("Vec<{}>", boxed_type), - Applicability::MaybeIncorrect, - ); - return; // don't recurse into the type + let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty); + if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env) { + span_lint_and_sugg( + cx, + VEC_BOX, + hir_ty.span, + "`Vec` is already on the heap, the boxing is unnecessary.", + "try", + format!("Vec<{}>", ty_ty), + Applicability::MaybeIncorrect, + ); + return; // don't recurse into the type + } } } } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { diff --git a/tests/ui/complex_types.rs b/tests/ui/complex_types.rs index cfece3768ef..be61fb6b9be 100644 --- a/tests/ui/complex_types.rs +++ b/tests/ui/complex_types.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(unused, clippy::needless_pass_by_value)] +#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)] #![feature(associated_type_defaults)] type Alias = Vec>>; // no warning here diff --git a/tests/ui/vec_box_sized.fixed b/tests/ui/vec_box_sized.fixed new file mode 100644 index 00000000000..a56dac8aa23 --- /dev/null +++ b/tests/ui/vec_box_sized.fixed @@ -0,0 +1,36 @@ +// run-rustfix + +#![allow(dead_code)] + +struct SizedStruct(i32); +struct UnsizedStruct([i32]); + +/// The following should trigger the lint +mod should_trigger { + use super::SizedStruct; + + struct StructWithVecBox { + sized_type: Vec, + } + + struct A(Vec); + struct B(Vec>); +} + +/// The following should not trigger the lint +mod should_not_trigger { + use super::UnsizedStruct; + + struct C(Vec>); + + struct StructWithVecBoxButItsUnsized { + unsized_type: Vec>, + } + + struct TraitVec { + // Regression test for #3720. This was causing an ICE. + inner: Vec>, + } +} + +fn main() {} diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs index 884761675fc..32d1e940f27 100644 --- a/tests/ui/vec_box_sized.rs +++ b/tests/ui/vec_box_sized.rs @@ -1,17 +1,36 @@ -struct SizedStruct { - _a: i32, -} +// run-rustfix -struct UnsizedStruct { - _a: [i32], -} +#![allow(dead_code)] + +struct SizedStruct(i32); +struct UnsizedStruct([i32]); + +/// The following should trigger the lint +mod should_trigger { + use super::SizedStruct; -struct StructWithVecBox { - sized_type: Vec>, + struct StructWithVecBox { + sized_type: Vec>, + } + + struct A(Vec>); + struct B(Vec>>); } -struct StructWithVecBoxButItsUnsized { - unsized_type: Vec>, +/// The following should not trigger the lint +mod should_not_trigger { + use super::UnsizedStruct; + + struct C(Vec>); + + struct StructWithVecBoxButItsUnsized { + unsized_type: Vec>, + } + + struct TraitVec { + // Regression test for #3720. This was causing an ICE. + inner: Vec>, + } } fn main() {} diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index 21b515fa486..b33880b46bd 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -1,10 +1,22 @@ error: `Vec` is already on the heap, the boxing is unnecessary. - --> $DIR/vec_box_sized.rs:10:17 + --> $DIR/vec_box_sized.rs:13:21 | -LL | sized_type: Vec>, - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` +LL | sized_type: Vec>, + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` | = note: `-D clippy::vec-box` implied by `-D warnings` -error: aborting due to previous error +error: `Vec` is already on the heap, the boxing is unnecessary. + --> $DIR/vec_box_sized.rs:16:14 + | +LL | struct A(Vec>); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` + +error: `Vec` is already on the heap, the boxing is unnecessary. + --> $DIR/vec_box_sized.rs:17:18 + | +LL | struct B(Vec>>); + | ^^^^^^^^^^^^^^^ help: try: `Vec` + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From 38347bad3868aee11e2b47db5ae15a39829becd7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 08:42:01 +0100 Subject: Make vec_box MachineApplicable --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 75e2f75ffcd..6ee7d10155c 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -289,7 +289,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { "`Vec` is already on the heap, the boxing is unnecessary.", "try", format!("Vec<{}>", ty_ty), - Applicability::MaybeIncorrect, + Applicability::MachineApplicable, ); return; // don't recurse into the type } -- cgit 1.4.1-3-g733a5 From 69d96c7cdf384309ad429e075ff6082c8b090667 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 18:27:09 +0100 Subject: Remove conditionals from base builds We _always_ want to execute these, also on the master branch. --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3780f6ece79..d7b26225518 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,13 +42,10 @@ matrix: # Builds that are executed for every PR - os: osx # run base tests on both platforms env: BASE_TESTS=true - if: type = pull_request OR branch IN (auto, try) - os: linux env: BASE_TESTS=true - if: type = pull_request OR branch IN (auto, try) - os: windows env: CARGO_INCREMENTAL=0 BASE_TESTS=true - if: type = pull_request OR branch IN (auto, try) # Builds that are only executed when a PR is r+ed or a try build is started # We don't want to run these always because they go towards -- cgit 1.4.1-3-g733a5 From 1169066a0b501ae508461181b76c37d7e3b8ae6a Mon Sep 17 00:00:00 2001 From: Araam Borhanian Date: Sun, 13 Jan 2019 10:19:02 -0500 Subject: Adding lint for too many lines. --- clippy_lints/src/assign_ops.rs | 1 + clippy_lints/src/bit_mask.rs | 1 + clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/functions.rs | 77 +++++++++++++- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/loops.rs | 2 + clippy_lints/src/methods/mod.rs | 2 + clippy_lints/src/needless_pass_by_value.rs | 1 + clippy_lints/src/non_expressive_names.rs | 1 + clippy_lints/src/ptr.rs | 1 + clippy_lints/src/redundant_clone.rs | 1 + clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/types.rs | 7 +- clippy_lints/src/utils/author.rs | 2 + clippy_lints/src/utils/conf.rs | 2 + clippy_lints/src/utils/hir_utils.rs | 2 +- src/driver.rs | 1 + .../toml_unknown_key/conf_unknown_key.stderr | 2 +- tests/ui/functions_maxlines.rs | 112 +++++++++++++++++++++ tests/ui/functions_maxlines.stderr | 16 +++ tests/ui/matches.rs | 2 +- 21 files changed, 228 insertions(+), 13 deletions(-) create mode 100644 tests/ui/functions_maxlines.rs create mode 100644 tests/ui/functions_maxlines.stderr diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index cc44b514ea7..2ef2a184746 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -64,6 +64,7 @@ impl LintPass for AssignOps { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { + #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { match &expr.node { hir::ExprKind::AssignOp(op, lhs, rhs) => { diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index d4e30376199..f052ad6e5ac 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -177,6 +177,7 @@ fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp } } +#[allow(clippy::too_many_lines)] fn check_bit_mask( cx: &LateContext<'_, '_>, bit_op: BinOpKind, diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 57291dd24ee..2602ad45986 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -59,7 +59,7 @@ impl LintPass for EqOp { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { - #[allow(clippy::similar_names)] + #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Binary(op, ref left, ref right) = e.node { if in_macro(e.span) { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index cb69e96c8e4..9710eba21ad 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,4 +1,4 @@ -use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function}; +use crate::utils::{iter_input_pats, snippet, span_lint, type_is_unsafe_function}; use matches::matches; use rustc::hir; use rustc::hir::def::Def; @@ -31,6 +31,22 @@ declare_clippy_lint! { "functions with too many arguments" } +/// **What it does:** Checks for functions with a large amount of lines. +/// +/// **Why is this bad?** Functions with a lot of lines are harder to understand +/// due to having to look at a larger amount of code to understand what the +/// function is doing. Consider splitting the body of the function into +/// multiple functions. +/// +/// **Known problems:** None. +/// +/// ``` +declare_clippy_lint! { + pub TOO_MANY_LINES, + pedantic, + "functions with too many lines" +} + /// **What it does:** Checks for public functions that dereferences raw pointer /// arguments but are not marked unsafe. /// @@ -62,17 +78,21 @@ declare_clippy_lint! { #[derive(Copy, Clone)] pub struct Functions { threshold: u64, + max_lines: u64 } impl Functions { - pub fn new(threshold: u64) -> Self { - Self { threshold } + pub fn new(threshold: u64, max_lines: u64) -> Self { + Self { + threshold, + max_lines + } } } impl LintPass for Functions { fn get_lints(&self) -> LintArray { - lint_array!(TOO_MANY_ARGUMENTS, NOT_UNSAFE_PTR_ARG_DEREF) + lint_array!(TOO_MANY_ARGUMENTS, TOO_MANY_LINES, NOT_UNSAFE_PTR_ARG_DEREF) } fn name(&self) -> &'static str { @@ -123,6 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } self.check_raw_ptr(cx, unsafety, decl, body, nodeid); + self.check_line_number(cx, span); } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { @@ -153,6 +174,54 @@ impl<'a, 'tcx> Functions { } } + fn check_line_number(self, cx: &LateContext, span: Span) { + let code_snippet = snippet(cx, span, ".."); + let mut line_count = 0; + let mut in_comment = false; + for mut line in code_snippet.lines() { + if in_comment { + let end_comment_loc = match line.find("*/") { + Some(i) => i, + None => continue + }; + in_comment = false; + line = &line[end_comment_loc..]; + } + line = line.trim_left(); + if line.is_empty() || line.starts_with("//") { continue; } + if line.contains("/*") { + let mut count_line: bool = !line.starts_with("/*"); + let close_counts = line.match_indices("*/").count(); + let open_counts = line.match_indices("/*").count(); + + if close_counts > 1 || open_counts > 1 { + line_count += 1; + } else if close_counts == 1 { + match line.find("*/") { + Some(i) => { + line = line[i..].trim_left(); + if !line.is_empty() && !line.starts_with("//") { + count_line = true; + } + }, + None => continue + } + } else { + in_comment = true; + } + if count_line { line_count += 1; } + } else { + // No multipart comment, no single comment, non-empty string. + line_count += 1; + } + } + + if line_count > self.max_lines { + span_lint(cx, TOO_MANY_LINES, span, + "This function has a large number of lines.") + } + } + fn check_raw_ptr( self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 52cc2a88da4..8e8657c9d02 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -290,6 +290,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { } } +#[allow(clippy::too_many_lines)] #[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { let mut store = reg.sess.lint_store.borrow_mut(); @@ -427,7 +428,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new( conf.blacklisted_names.iter().cloned().collect() )); - reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); + reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold, conf.too_many_lines_threshold)); reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); @@ -527,6 +528,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { enum_glob_use::ENUM_GLOB_USE, enum_variants::MODULE_NAME_REPETITIONS, enum_variants::PUB_ENUM_VARIANT_NAMES, + functions::TOO_MANY_LINES, if_not_else::IF_NOT_ELSE, infinite_iter::MAYBE_INFINITE_ITER, items_after_statements::ITEMS_AFTER_STATEMENTS, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 4d6cc75135e..06266257d1e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -472,6 +472,7 @@ impl LintPass for Pass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // we don't want to check expanded macros if in_macro(expr.span) { @@ -1066,6 +1067,7 @@ fn detect_manual_memcpy<'a, 'tcx>( /// Check for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. +#[allow(clippy::too_many_lines)] fn check_for_loop_range<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 20ffc1fd406..4ce2ae03b9f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1005,6 +1005,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } /// Checks for the `OR_FUN_CALL` lint. +#[allow(clippy::too_many_lines)] fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { /// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. fn check_unwrap_or_default( @@ -1151,6 +1152,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa } /// Checks for the `EXPECT_FUN_CALL` lint. +#[allow(clippy::too_many_lines)] fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { // Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or // `&str` diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 73c0ed72d3b..a8cc5eeec9f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -73,6 +73,7 @@ macro_rules! need { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { + #[allow(clippy::too_many_lines)] fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 3bdf2c38d23..fbf60db28ee 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -158,6 +158,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { ); } } + #[allow(clippy::too_many_lines)] fn check_name(&mut self, span: Span, name: Name) { let interned_name = name.as_str(); if interned_name.chars().any(char::is_uppercase) { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index b990b7ab2bd..5a54971f49e 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -151,6 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } } +#[allow(clippy::too_many_lines)] fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option) { let fn_def_id = cx.tcx.hir().local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 7ac147c8ac1..5c994d8a2bc 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -80,6 +80,7 @@ impl LintPass for RedundantClone { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { + #[allow(clippy::too_many_lines)] fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 90cfcd56c3b..56e1aa4a4e1 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -226,7 +226,7 @@ impl LintPass for Transmute { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { - #[allow(clippy::similar_names)] + #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Call(ref path_expr, ref args) = e.node { if let ExprKind::Path(ref qpath) = path_expr.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 939dd27c441..e81df4af383 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -240,8 +240,9 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) /// /// The parameter `is_local` distinguishes the context of the type; types from /// local bindings should only be checked for the `BORROWED_BOX` lint. -fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { - if in_macro(hir_ty.span) { +#[allow(clippy::too_many_lines)] +fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { + if in_macro(ast_ty.span) { return; } match hir_ty.node { @@ -1968,7 +1969,7 @@ impl LintPass for ImplicitHasher { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { - #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { use syntax_pos::BytePos; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 19c3f3ad230..5a76b965d26 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -194,6 +194,7 @@ struct PrintVisitor { } impl<'tcx> Visitor<'tcx> for PrintVisitor { + #[allow(clippy::too_many_lines)] fn visit_expr(&mut self, expr: &Expr) { print!(" if let ExprKind::"); let current = format!("{}.node", self.current); @@ -506,6 +507,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } + #[allow(clippy::too_many_lines)] fn visit_pat(&mut self, pat: &Pat) { print!(" if let PatKind::"); let current = format!("{}.node", self.current); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 55256a25427..4ab274e598f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -148,6 +148,8 @@ define_Conf! { (literal_representation_threshold, "literal_representation_threshold", 16384 => u64), /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. (trivial_copy_size_limit, "trivial_copy_size_limit", None => Option), + /// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have + (too_many_lines_threshold, "too_many_lines_threshold", 101 => u64), } impl Default for Conf { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index a176830be26..2b0b0e7121f 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -389,7 +389,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { .hash(&mut self.s); } - #[allow(clippy::many_single_char_names)] + #[allow(clippy::many_single_char_names, clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr) { if let Some(e) = constant_simple(self.cx, self.tables, e) { return e.hash(&mut self.s); diff --git a/src/driver.rs b/src/driver.rs index 1ce6f6b7c49..b41895f3c2b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -20,6 +20,7 @@ fn show_version() { println!(env!("CARGO_PKG_VERSION")); } +#[allow(clippy::too_many_lines)] pub fn main() { rustc_driver::init_rustc_env_logger(); exit( diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 05a04fb377a..ec2ac20684b 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `third-party` +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `third-party` error: aborting due to previous error diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs new file mode 100644 index 00000000000..5d8baf438df --- /dev/null +++ b/tests/ui/functions_maxlines.rs @@ -0,0 +1,112 @@ +#![warn(clippy::all, clippy::pedantic)] + +// TOO_MANY_LINES +fn good_lines() { + /* println!("This is good."); */ + // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); */ + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); +} + +fn bad_lines() { + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); +} + +fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr new file mode 100644 index 00000000000..9e1b2fe568a --- /dev/null +++ b/tests/ui/functions_maxlines.stderr @@ -0,0 +1,16 @@ +error: This function has a large number of lines. + --> $DIR/functions_maxlines.rs:59:1 + | +LL | / fn bad_lines() { +LL | | println!("This is bad."); +LL | | println!("This is bad."); +LL | | println!("This is bad."); +... | +LL | | println!("This is bad."); +LL | | } + | |_^ + | + = note: `-D clippy::too-many-lines` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 013f12a1a0e..a40b80378ef 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,6 +1,6 @@ #![feature(exclusive_range_pattern)] #![warn(clippy::all)] -#![allow(unused, clippy::redundant_pattern_matching)] +#![allow(unused, clippy::redundant_pattern_matching, clippy::too_many_lines)] #![warn(clippy::match_same_arms)] fn dummy() {} -- cgit 1.4.1-3-g733a5 From 6b86c3b1e7cce84787c6903d48392e4c5f24f6b3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 11:07:14 -0500 Subject: Updating number of lines for the failing test to be > 100. Due to updating the configuration to be 101 instead of 51 --- tests/ui/functions_maxlines.rs | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index 5d8baf438df..5f93f815340 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -107,6 +107,56 @@ fn bad_lines() { println!("This is bad."); println!("This is bad."); println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); } fn main() {} -- cgit 1.4.1-3-g733a5 From 93bf74a15885c100dc830958d457c1704640de43 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 11:42:09 -0500 Subject: Running util/dev to update README/CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71066aadfcb..192e0132619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -981,6 +981,7 @@ All notable changes to this project will be documented in this file. [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments +[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg [`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool -- cgit 1.4.1-3-g733a5 From 7fbd55c3291175229fb86ffd8a31c1e5fb544e27 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 16:26:03 -0500 Subject: Reworking function logic, and adding doc example. This should fix line count logic issues that the previous code had, with assumptions it would make. --- clippy_lints/src/functions.rs | 78 ++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 9710eba21ad..a5dbbeb3e51 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -40,6 +40,13 @@ declare_clippy_lint! { /// /// **Known problems:** None. /// +/// **Example:** +/// ``` rust +/// fn im_too_long() { +/// println!(""); +/// // ... 100 more LoC +/// println!(""); +/// } /// ``` declare_clippy_lint! { pub TOO_MANY_LINES, @@ -174,46 +181,57 @@ impl<'a, 'tcx> Functions { } } - fn check_line_number(self, cx: &LateContext, span: Span) { + fn check_line_number(self, cx: &LateContext<'_, '_>, span: Span) { let code_snippet = snippet(cx, span, ".."); - let mut line_count = 0; + let mut line_count: u64 = 0; let mut in_comment = false; - for mut line in code_snippet.lines() { - if in_comment { - let end_comment_loc = match line.find("*/") { - Some(i) => i, - None => continue - }; - in_comment = false; - line = &line[end_comment_loc..]; - } - line = line.trim_left(); - if line.is_empty() || line.starts_with("//") { continue; } - if line.contains("/*") { - let mut count_line: bool = !line.starts_with("/*"); - let close_counts = line.match_indices("*/").count(); - let open_counts = line.match_indices("/*").count(); + let mut code_in_line; - if close_counts > 1 || open_counts > 1 { - line_count += 1; - } else if close_counts == 1 { + // Skip the surrounding function decl. + let start_brace_idx = match code_snippet.find("{") { + Some(i) => i + 1, + None => 0 + }; + let end_brace_idx = match code_snippet.find("}") { + Some(i) => i, + None => code_snippet.len() + }; + let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines(); + + for mut line in function_lines { + code_in_line = false; + loop { + line = line.trim_start(); + if line.is_empty() { break; } + if in_comment { match line.find("*/") { Some(i) => { - line = line[i..].trim_left(); - if !line.is_empty() && !line.starts_with("//") { - count_line = true; - } + line = &line[i + 2..]; + in_comment = false; + continue; }, - None => continue + None => break } } else { - in_comment = true; + let multi_idx = match line.find("/*") { + Some(i) => i, + None => line.len() + }; + let single_idx = match line.find("//") { + Some(i) => i, + None => line.len() + }; + code_in_line |= multi_idx > 0 && single_idx > 0; + // Implies multi_idx is below line.len() + if multi_idx < single_idx { + line = &line[multi_idx + 2..]; + in_comment = true; + continue; + } + break; } - if count_line { line_count += 1; } - } else { - // No multipart comment, no single comment, non-empty string. - line_count += 1; } + if code_in_line { line_count += 1; } } if line_count > self.max_lines { -- cgit 1.4.1-3-g733a5 From 3a97b5fa2048211b16d362be34293912fe996113 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 16:26:20 -0500 Subject: Moving tests to ui-toml to make use of clippy.toml --- tests/ui-toml/functions_maxlines/clippy.toml | 1 + tests/ui-toml/functions_maxlines/test.rs | 44 ++++++++ tests/ui-toml/functions_maxlines/test.stderr | 23 ++++ tests/ui/functions_maxlines.rs | 162 --------------------------- tests/ui/functions_maxlines.stderr | 16 --- 5 files changed, 68 insertions(+), 178 deletions(-) create mode 100644 tests/ui-toml/functions_maxlines/clippy.toml create mode 100644 tests/ui-toml/functions_maxlines/test.rs create mode 100644 tests/ui-toml/functions_maxlines/test.stderr delete mode 100644 tests/ui/functions_maxlines.rs delete mode 100644 tests/ui/functions_maxlines.stderr diff --git a/tests/ui-toml/functions_maxlines/clippy.toml b/tests/ui-toml/functions_maxlines/clippy.toml new file mode 100644 index 00000000000..951dbb523d9 --- /dev/null +++ b/tests/ui-toml/functions_maxlines/clippy.toml @@ -0,0 +1 @@ +too-many-lines-threshold = 1 diff --git a/tests/ui-toml/functions_maxlines/test.rs b/tests/ui-toml/functions_maxlines/test.rs new file mode 100644 index 00000000000..6ee75e4dbc1 --- /dev/null +++ b/tests/ui-toml/functions_maxlines/test.rs @@ -0,0 +1,44 @@ +#![warn(clippy::too_many_lines)] + + +// This function should be considered one line. +fn many_comments_but_one_line_of_code() { + /* println!("This is good."); */ + // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* println!("This is good."); + println!("This is good."); + println!("This is good."); */ + println!("This is good."); +} + +// This should be considered two and a fail. +fn too_many_lines() { + println!("This is bad."); + println!("This is bad."); +} + +// This should be considered one line. +fn comment_starts_after_code() { + let _ = 5; /* closing comment. */ /* + this line shouldn't be counted theoretically. + */ +} + +// This should be considered one line. +fn comment_after_code() { + let _ = 5; /* this line should get counted once. */ +} + +// This should fail since it is technically two lines. +fn comment_before_code() { + let _ = "test"; + /* This comment extends to the front of + teh code but this line should still count. */ let _ = 5; +} + +// This should be considered one line. +fn main() {} diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr new file mode 100644 index 00000000000..f36c5978784 --- /dev/null +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -0,0 +1,23 @@ +error: This function has a large number of lines. + --> $DIR/test.rs:19:1 + | +LL | / fn too_many_lines() { +LL | | println!("This is bad."); +LL | | println!("This is bad."); +LL | | } + | |_^ + | + = note: `-D clippy::too-many-lines` implied by `-D warnings` + +error: This function has a large number of lines. + --> $DIR/test.rs:37:1 + | +LL | / fn comment_before_code() { +LL | | let _ = "test"; +LL | | /* This comment extends to the front of +LL | | teh code but this line should still count. */ let _ = 5; +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs deleted file mode 100644 index 5f93f815340..00000000000 --- a/tests/ui/functions_maxlines.rs +++ /dev/null @@ -1,162 +0,0 @@ -#![warn(clippy::all, clippy::pedantic)] - -// TOO_MANY_LINES -fn good_lines() { - /* println!("This is good."); */ - // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); */ - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); -} - -fn bad_lines() { - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); -} - -fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr deleted file mode 100644 index 9e1b2fe568a..00000000000 --- a/tests/ui/functions_maxlines.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: This function has a large number of lines. - --> $DIR/functions_maxlines.rs:59:1 - | -LL | / fn bad_lines() { -LL | | println!("This is bad."); -LL | | println!("This is bad."); -LL | | println!("This is bad."); -... | -LL | | println!("This is bad."); -LL | | } - | |_^ - | - = note: `-D clippy::too-many-lines` implied by `-D warnings` - -error: aborting due to previous error - -- cgit 1.4.1-3-g733a5 From e583f35b3a7f2c55bc0ef786a3c671a843b38a46 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 16:53:26 -0500 Subject: rustfmt --- clippy_lints/src/functions.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index a5dbbeb3e51..e95bf6639fc 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -85,15 +85,12 @@ declare_clippy_lint! { #[derive(Copy, Clone)] pub struct Functions { threshold: u64, - max_lines: u64 + max_lines: u64, } impl Functions { pub fn new(threshold: u64, max_lines: u64) -> Self { - Self { - threshold, - max_lines - } + Self { threshold, max_lines } } } @@ -190,11 +187,11 @@ impl<'a, 'tcx> Functions { // Skip the surrounding function decl. let start_brace_idx = match code_snippet.find("{") { Some(i) => i + 1, - None => 0 + None => 0, }; let end_brace_idx = match code_snippet.find("}") { Some(i) => i, - None => code_snippet.len() + None => code_snippet.len(), }; let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines(); @@ -202,7 +199,9 @@ impl<'a, 'tcx> Functions { code_in_line = false; loop { line = line.trim_start(); - if line.is_empty() { break; } + if line.is_empty() { + break; + } if in_comment { match line.find("*/") { Some(i) => { @@ -210,16 +209,16 @@ impl<'a, 'tcx> Functions { in_comment = false; continue; }, - None => break + None => break, } } else { let multi_idx = match line.find("/*") { Some(i) => i, - None => line.len() + None => line.len(), }; let single_idx = match line.find("//") { Some(i) => i, - None => line.len() + None => line.len(), }; code_in_line |= multi_idx > 0 && single_idx > 0; // Implies multi_idx is below line.len() @@ -231,12 +230,13 @@ impl<'a, 'tcx> Functions { break; } } - if code_in_line { line_count += 1; } + if code_in_line { + line_count += 1; + } } if line_count > self.max_lines { - span_lint(cx, TOO_MANY_LINES, span, - "This function has a large number of lines.") + span_lint(cx, TOO_MANY_LINES, span, "This function has a large number of lines.") } } -- cgit 1.4.1-3-g733a5 From c1f4e18453e18d6cae92aeaeca465f004d1463a7 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 17:53:56 -0500 Subject: Adding back tests, but also reducing threshold by 1 --- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/functions_maxlines.rs | 163 +++++++++++++++++++++++++++++++++++++ tests/ui/functions_maxlines.stderr | 16 ++++ 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 tests/ui/functions_maxlines.rs create mode 100644 tests/ui/functions_maxlines.stderr diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 4ab274e598f..09d204a562c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -149,7 +149,7 @@ define_Conf! { /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. (trivial_copy_size_limit, "trivial_copy_size_limit", None => Option), /// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have - (too_many_lines_threshold, "too_many_lines_threshold", 101 => u64), + (too_many_lines_threshold, "too_many_lines_threshold", 100 => u64), } impl Default for Conf { diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs new file mode 100644 index 00000000000..762525401b8 --- /dev/null +++ b/tests/ui/functions_maxlines.rs @@ -0,0 +1,163 @@ +#![warn(clippy::all, clippy::pedantic)] + +// TOO_MANY_LINES +fn good_lines() { + /* println!("This is good."); */ + // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); */ + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); +} + +fn bad_lines() { + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); +} + +fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr new file mode 100644 index 00000000000..9e1b2fe568a --- /dev/null +++ b/tests/ui/functions_maxlines.stderr @@ -0,0 +1,16 @@ +error: This function has a large number of lines. + --> $DIR/functions_maxlines.rs:59:1 + | +LL | / fn bad_lines() { +LL | | println!("This is bad."); +LL | | println!("This is bad."); +LL | | println!("This is bad."); +... | +LL | | println!("This is bad."); +LL | | } + | |_^ + | + = note: `-D clippy::too-many-lines` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 50c82e02707fc013f584b92beae760db34222430 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Jan 2019 21:38:15 -0500 Subject: Updating to just warn for one test. --- tests/ui/functions_maxlines.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index 762525401b8..ada35abde99 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -1,6 +1,5 @@ -#![warn(clippy::all, clippy::pedantic)] +#![warn(clippy::too_many_lines)] -// TOO_MANY_LINES fn good_lines() { /* println!("This is good."); */ // println!("This is good."); -- cgit 1.4.1-3-g733a5 From 02456208b413c5bc2854a2b54bb5691eacd82813 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Jan 2019 22:32:12 -0500 Subject: Fix test broken by removing comment. --- tests/ui/functions_maxlines.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr index 9e1b2fe568a..dfa6a1cf3c5 100644 --- a/tests/ui/functions_maxlines.stderr +++ b/tests/ui/functions_maxlines.stderr @@ -1,5 +1,5 @@ error: This function has a large number of lines. - --> $DIR/functions_maxlines.rs:59:1 + --> $DIR/functions_maxlines.rs:58:1 | LL | / fn bad_lines() { LL | | println!("This is bad."); -- cgit 1.4.1-3-g733a5 From 44c835feead3bbc0c993a7ee20a51cb9ce1e07d9 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 19 Jan 2019 17:35:32 -0500 Subject: Skipping check if in external macro. --- clippy_lints/src/functions.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index e95bf6639fc..0da7e26a1be 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -3,7 +3,7 @@ use matches::matches; use rustc::hir; use rustc::hir::def::Def; use rustc::hir::intravisit; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_data_structures::fx::FxHashSet; @@ -179,6 +179,10 @@ impl<'a, 'tcx> Functions { } fn check_line_number(self, cx: &LateContext<'_, '_>, span: Span) { + if in_external_macro(cx.sess(), span) { + return; + } + let code_snippet = snippet(cx, span, ".."); let mut line_count: u64 = 0; let mut in_comment = false; -- cgit 1.4.1-3-g733a5 From 5e10809ac31526d3e91088eaeb1ee8567e90ba2a Mon Sep 17 00:00:00 2001 From: Araam Borhanian Date: Sun, 13 Jan 2019 10:19:02 -0500 Subject: Adding lint for too many lines. --- clippy_lints/src/functions.rs | 5 ++++- tests/ui/functions_maxlines.rs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 0da7e26a1be..5b4f6f2ad17 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -90,7 +90,10 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64, max_lines: u64) -> Self { - Self { threshold, max_lines } + Self { + threshold, + max_lines + } } } diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index ada35abde99..56fcd4866d6 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -1,5 +1,6 @@ #![warn(clippy::too_many_lines)] + fn good_lines() { /* println!("This is good."); */ // println!("This is good."); @@ -106,6 +107,7 @@ fn bad_lines() { println!("This is bad."); println!("This is bad."); println!("This is bad."); +<<<<<<< HEAD println!("This is bad."); println!("This is bad."); println!("This is bad."); -- cgit 1.4.1-3-g733a5 From be514a4336ee664c46b40acd2250942299f3e15c Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 11:07:14 -0500 Subject: Updating number of lines for the failing test to be > 100. Due to updating the configuration to be 101 instead of 51 --- tests/ui/functions_maxlines.rs | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index 56fcd4866d6..33a47675ff1 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -159,6 +159,56 @@ fn bad_lines() { println!("This is bad."); println!("This is bad."); println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); } fn main() {} -- cgit 1.4.1-3-g733a5 From 65f62d04976c387c30a876e37fa6f446d99a3767 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 16:26:20 -0500 Subject: Moving tests to ui-toml to make use of clippy.toml --- tests/ui/functions_maxlines.rs | 214 ------------------------------------- tests/ui/functions_maxlines.stderr | 16 --- 2 files changed, 230 deletions(-) delete mode 100644 tests/ui/functions_maxlines.rs delete mode 100644 tests/ui/functions_maxlines.stderr diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs deleted file mode 100644 index 33a47675ff1..00000000000 --- a/tests/ui/functions_maxlines.rs +++ /dev/null @@ -1,214 +0,0 @@ -#![warn(clippy::too_many_lines)] - - -fn good_lines() { - /* println!("This is good."); */ - // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* */ // println!("This is good."); - /* println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); */ - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); - println!("This is good."); -} - -fn bad_lines() { - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); -<<<<<<< HEAD - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); - println!("This is bad."); -} - -fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr deleted file mode 100644 index dfa6a1cf3c5..00000000000 --- a/tests/ui/functions_maxlines.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: This function has a large number of lines. - --> $DIR/functions_maxlines.rs:58:1 - | -LL | / fn bad_lines() { -LL | | println!("This is bad."); -LL | | println!("This is bad."); -LL | | println!("This is bad."); -... | -LL | | println!("This is bad."); -LL | | } - | |_^ - | - = note: `-D clippy::too-many-lines` implied by `-D warnings` - -error: aborting due to previous error - -- cgit 1.4.1-3-g733a5 From 6931b0f5a16c02e314fda6d3cccc5c08c51ceb68 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 16:53:26 -0500 Subject: rustfmt --- clippy_lints/src/functions.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 5b4f6f2ad17..0da7e26a1be 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -90,10 +90,7 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64, max_lines: u64) -> Self { - Self { - threshold, - max_lines - } + Self { threshold, max_lines } } } -- cgit 1.4.1-3-g733a5 From 057037a6b91de82e8a75bcb36bd596e944ab3328 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Jan 2019 17:53:56 -0500 Subject: Adding back tests, but also reducing threshold by 1 --- tests/ui/functions_maxlines.rs | 163 +++++++++++++++++++++++++++++++++++++ tests/ui/functions_maxlines.stderr | 16 ++++ 2 files changed, 179 insertions(+) create mode 100644 tests/ui/functions_maxlines.rs create mode 100644 tests/ui/functions_maxlines.stderr diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs new file mode 100644 index 00000000000..762525401b8 --- /dev/null +++ b/tests/ui/functions_maxlines.rs @@ -0,0 +1,163 @@ +#![warn(clippy::all, clippy::pedantic)] + +// TOO_MANY_LINES +fn good_lines() { + /* println!("This is good."); */ + // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* */ // println!("This is good."); + /* println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); */ + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); + println!("This is good."); +} + +fn bad_lines() { + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); +} + +fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr new file mode 100644 index 00000000000..9e1b2fe568a --- /dev/null +++ b/tests/ui/functions_maxlines.stderr @@ -0,0 +1,16 @@ +error: This function has a large number of lines. + --> $DIR/functions_maxlines.rs:59:1 + | +LL | / fn bad_lines() { +LL | | println!("This is bad."); +LL | | println!("This is bad."); +LL | | println!("This is bad."); +... | +LL | | println!("This is bad."); +LL | | } + | |_^ + | + = note: `-D clippy::too-many-lines` implied by `-D warnings` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From ae3bcb770e94dcb5668194a99260b170edb4fcf3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Jan 2019 21:38:15 -0500 Subject: Updating to just warn for one test. --- tests/ui/functions_maxlines.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index 762525401b8..ada35abde99 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -1,6 +1,5 @@ -#![warn(clippy::all, clippy::pedantic)] +#![warn(clippy::too_many_lines)] -// TOO_MANY_LINES fn good_lines() { /* println!("This is good."); */ // println!("This is good."); -- cgit 1.4.1-3-g733a5 From 21e2b13125f50695cc4de10529019ffd1566237f Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Jan 2019 22:32:12 -0500 Subject: Fix test broken by removing comment. --- tests/ui/functions_maxlines.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr index 9e1b2fe568a..dfa6a1cf3c5 100644 --- a/tests/ui/functions_maxlines.stderr +++ b/tests/ui/functions_maxlines.stderr @@ -1,5 +1,5 @@ error: This function has a large number of lines. - --> $DIR/functions_maxlines.rs:59:1 + --> $DIR/functions_maxlines.rs:58:1 | LL | / fn bad_lines() { LL | | println!("This is bad."); -- cgit 1.4.1-3-g733a5 From 93a856e9d505db2ca3fe3be22ec28a1d97bce84e Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 31 Jan 2019 23:50:55 -0500 Subject: Changing single character string to a character match. --- clippy_lints/src/functions.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 0da7e26a1be..7c23503507a 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -189,11 +189,11 @@ impl<'a, 'tcx> Functions { let mut code_in_line; // Skip the surrounding function decl. - let start_brace_idx = match code_snippet.find("{") { + let start_brace_idx = match code_snippet.find('{') { Some(i) => i + 1, None => 0, }; - let end_brace_idx = match code_snippet.find("}") { + let end_brace_idx = match code_snippet.find('}') { Some(i) => i, None => code_snippet.len(), }; -- cgit 1.4.1-3-g733a5 From a35083f2e61315f66eedc2e46a0eaafd92f7be73 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 1 Feb 2019 00:16:08 -0500 Subject: Updated readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1f457a956e..8519fe55a9f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 294 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 295 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: -- cgit 1.4.1-3-g733a5 From 6e35b33bc3d128d18883c9a69f906a605f71bd61 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 1 Feb 2019 13:19:55 -0500 Subject: Updating code to ignore rustfmt issue. --- tests/ui-toml/functions_maxlines/test.rs | 3 ++- tests/ui-toml/functions_maxlines/test.stderr | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/ui-toml/functions_maxlines/test.rs b/tests/ui-toml/functions_maxlines/test.rs index 6ee75e4dbc1..cd0e0082586 100644 --- a/tests/ui-toml/functions_maxlines/test.rs +++ b/tests/ui-toml/functions_maxlines/test.rs @@ -1,6 +1,5 @@ #![warn(clippy::too_many_lines)] - // This function should be considered one line. fn many_comments_but_one_line_of_code() { /* println!("This is good."); */ @@ -22,6 +21,7 @@ fn too_many_lines() { } // This should be considered one line. +#[rustfmt::skip] fn comment_starts_after_code() { let _ = 5; /* closing comment. */ /* this line shouldn't be counted theoretically. @@ -34,6 +34,7 @@ fn comment_after_code() { } // This should fail since it is technically two lines. +#[rustfmt::skip] fn comment_before_code() { let _ = "test"; /* This comment extends to the front of diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr index f36c5978784..0669e99370b 100644 --- a/tests/ui-toml/functions_maxlines/test.stderr +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -1,5 +1,5 @@ error: This function has a large number of lines. - --> $DIR/test.rs:19:1 + --> $DIR/test.rs:18:1 | LL | / fn too_many_lines() { LL | | println!("This is bad."); @@ -10,7 +10,7 @@ LL | | } = note: `-D clippy::too-many-lines` implied by `-D warnings` error: This function has a large number of lines. - --> $DIR/test.rs:37:1 + --> $DIR/test.rs:38:1 | LL | / fn comment_before_code() { LL | | let _ = "test"; -- cgit 1.4.1-3-g733a5 From 268ff853263da6d518e233cf2a514bde50975f1d Mon Sep 17 00:00:00 2001 From: rhysd Date: Sat, 2 Feb 2019 04:52:21 +0900 Subject: use span_help_and_lint() instead of span_lint_and_sugg() --- clippy_lints/src/dbg_macro.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 0bcca015c06..93d2007d3a5 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_sugg; +use crate::utils::span_help_and_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; @@ -41,14 +41,12 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { if mac.node.path == "dbg" { - span_lint_and_sugg( + span_help_and_lint( cx, DBG_MACRO, mac.span, "`dbg!` macro is intended as a debugging tool", "ensure to avoid having uses of it in version control", - mac.node.tts.to_string(), - Applicability::MaybeIncorrect, ); } } -- cgit 1.4.1-3-g733a5 From a022d47a6bb005e928462820c31b84ba6c99e875 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 14:52:56 -0500 Subject: Update clippy_lints/src/types.rs Co-Authored-By: avborhanian --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e81df4af383..3574217306b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -241,7 +241,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) /// The parameter `is_local` distinguishes the context of the type; types from /// local bindings should only be checked for the `BORROWED_BOX` lint. #[allow(clippy::too_many_lines)] -fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) { +fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { if in_macro(ast_ty.span) { return; } -- cgit 1.4.1-3-g733a5 From ac9472d16e5eee8b5cdf3adaf83b8ba5fdd354cd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 1 Feb 2019 14:53:15 -0500 Subject: Update clippy_lints/src/types.rs Co-Authored-By: avborhanian --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3574217306b..1a48009655e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -242,7 +242,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) /// local bindings should only be checked for the `BORROWED_BOX` lint. #[allow(clippy::too_many_lines)] fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { - if in_macro(ast_ty.span) { + if in_macro(hir_ty.span) { return; } match hir_ty.node { -- cgit 1.4.1-3-g733a5 From 54d49af3ff1f23e8e8b580483e6b3a4f708285bd Mon Sep 17 00:00:00 2001 From: rhysd Date: Sat, 2 Feb 2019 04:54:51 +0900 Subject: add more test cases for dbg_macro rule --- clippy_lints/src/dbg_macro.rs | 1 - tests/ui/dbg_macro.rs | 18 ++++++++++++++ tests/ui/dbg_macro.stderr | 57 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 93d2007d3a5..0b8f0c3f5fc 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,7 +1,6 @@ use crate::utils::span_help_and_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; -use rustc_errors::Applicability; use syntax::ast; /// **What it does:** Checks for usage of dbg!() macro. diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs index dc96c7da0ac..d2df7fbd3e8 100644 --- a/tests/ui/dbg_macro.rs +++ b/tests/ui/dbg_macro.rs @@ -1,5 +1,23 @@ #![warn(clippy::dbg_macro)] +fn foo(n: u32) -> u32 { + if let Some(n) = dbg!(n.checked_sub(4)) { + n + } else { + n + } +} + +fn factorial(n: u32) -> u32 { + if dbg!(n <= 1) { + dbg!(1) + } else { + dbg!(n * factorial(n - 1)) + } +} + fn main() { dbg!(42); + dbg!(dbg!(dbg!(42))); + foo(3) + dbg!(factorial(4)); } diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr index 4b8501462ff..28e59f4c11b 100644 --- a/tests/ui/dbg_macro.stderr +++ b/tests/ui/dbg_macro.stderr @@ -1,14 +1,59 @@ error: `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:4:5 + --> $DIR/dbg_macro.rs:4:22 + | +LL | if let Some(n) = dbg!(n.checked_sub(4)) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::dbg-macro` implied by `-D warnings` + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:12:8 + | +LL | if dbg!(n <= 1) { + | ^^^^^^^^^^^^ + | + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:13:9 + | +LL | dbg!(1) + | ^^^^^^^ + | + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:15:9 + | +LL | dbg!(n * factorial(n - 1)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:20:5 | LL | dbg!(42); | ^^^^^^^^ | - = note: `-D clippy::dbg-macro` implied by `-D warnings` -help: ensure to avoid having uses of it in version control + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:21:5 + | +LL | dbg!(dbg!(dbg!(42))); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure to avoid having uses of it in version control + +error: `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:22:14 + | +LL | foo(3) + dbg!(factorial(4)); + | ^^^^^^^^^^^^^^^^^^ | -LL | 42; - | ^^ + = help: ensure to avoid having uses of it in version control -error: aborting due to previous error +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From b5fd0108b3a6b8a9626645ac174cf653de576135 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 15 Jan 2019 10:56:09 -0800 Subject: clippy-driver: more robust test to see if we're clippy-enabled Rather than looking for a fixed --emit arg set, just check to see if we're emitting metadata at all. This makes it more robust to being invoked by tools other than cargo (or if cargo changes its invocation). Issue #3663 --- Cargo.toml | 1 - src/driver.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 868f21c1a49..c3710485027 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ path = "src/main.rs" [[bin]] name = "clippy-driver" -test = false path = "src/driver.rs" [dependencies] diff --git a/src/driver.rs b/src/driver.rs index b41895f3c2b..d290e403a31 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -20,6 +20,46 @@ fn show_version() { println!(env!("CARGO_PKG_VERSION")); } +/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If +/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. +fn arg_value<'a>( + args: impl IntoIterator, + find_arg: &str, + pred: impl Fn(&str) -> bool, +) -> Option<&'a str> { + let mut args = args.into_iter().map(String::as_str); + + while let Some(arg) = args.next() { + let arg: Vec<_> = arg.splitn(2, '=').collect(); + if arg.get(0) != Some(&find_arg) { + continue; + } + + let value = arg.get(1).cloned().or_else(|| args.next()); + if value.as_ref().map_or(false, |p| pred(p)) { + return value; + } + } + None +} + +#[test] +fn test_arg_value() { + let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"] + .iter() + .map(|s| s.to_string()) + .collect(); + + assert_eq!(arg_value(None, "--foobar", |_| true), None); + assert_eq!(arg_value(&args, "--bar", |_| false), None); + assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar")); + assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar")); + assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None); + assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None); + assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123")); + assert_eq!(arg_value(&args, "--foo", |_| true), None); +} + #[allow(clippy::too_many_lines)] pub fn main() { rustc_driver::init_rustc_env_logger(); @@ -79,7 +119,7 @@ pub fn main() { // crate is // linted but not built let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || orig_args.iter().any(|s| s == "--emit=dep-info,metadata"); + || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some(); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); -- cgit 1.4.1-3-g733a5 From 71d03ae29b175c5e99f4e978e90bab830cfbd530 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 15 Jan 2019 11:39:23 -0800 Subject: clippy-driver: if --sysroot is specified on the command line, use that If the user explicitly sets sysroot on the command line, then use that value. Issue #3663 --- src/driver.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index d290e403a31..fbff693f887 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -72,8 +72,19 @@ pub fn main() { exit(0); } - let sys_root = option_env!("SYSROOT") - .map(String::from) + let mut orig_args: Vec = env::args().collect(); + + // Get the sysroot, looking from most specific to this invocation to the least: + // - command line + // - runtime environment + // - SYSROOT + // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN + // - sysroot from rustc in the path + // - compile-time environment + let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); + let have_sys_root_arg = sys_root_arg.is_some(); + let sys_root = sys_root_arg + .map(|s| s.to_string()) .or_else(|| std::env::var("SYSROOT").ok()) .or_else(|| { let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); @@ -89,11 +100,11 @@ pub fn main() { .and_then(|out| String::from_utf8(out.stdout).ok()) .map(|s| s.trim().to_owned()) }) + .or_else(|| option_env!("SYSROOT").map(String::from)) .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); if orig_args.len() <= 1 { std::process::exit(1); } @@ -104,7 +115,7 @@ pub fn main() { // this conditional check for the --sysroot flag is there so users can call // `clippy_driver` directly // without having to pass --sysroot or anything - let mut args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + let mut args: Vec = if have_sys_root_arg { orig_args.clone() } else { orig_args -- cgit 1.4.1-3-g733a5 From 86c513e605e7982c00587e05a33a1062ca9a5334 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 26 Jan 2019 16:11:30 -0800 Subject: Let CLIPPY_CONF_DIR be used to start search for config, and fall back to CARGO_MANIFEST_DIR if it isn't set. If CARGO_MANIFEST_DIR isn't set, fall back "." rather than panicing. Issue #3663 --- clippy_lints/src/utils/conf.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 09d204a562c..b0b4394ebb8 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -163,8 +163,13 @@ pub fn lookup_conf_file() -> io::Result> { /// Possible filename to search for. const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"]; - let mut current = path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); - + // Start looking for a config file in CLIPPY_CONF_DIR, or failing that, CARGO_MANIFEST_DIR. + // If neither of those exist, use ".". + let mut current = path::PathBuf::from( + env::var("CLIPPY_CONF_DIR") + .or_else(|_| env::var("CARGO_MANIFEST_DIR")) + .unwrap_or_else(|_| ".".to_string()), + ); loop { for config_file_name in &CONFIG_FILE_NAMES { let config_file = current.join(config_file_name); -- cgit 1.4.1-3-g733a5 From 993e8ace8e82d28fc891d9cc84fa4b06754c3b58 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 26 Jan 2019 16:44:52 -0800 Subject: Drive-by cleanups to cargo-clippy. No functional change. --- src/main.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index 20466fc567d..208262ca30f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,10 +61,8 @@ where { let mut args = vec!["check".to_owned()]; - let mut found_dashes = false; for arg in old_args.by_ref() { - found_dashes |= arg == "--"; - if found_dashes { + if arg == "--" { break; } args.push(arg); @@ -82,11 +80,7 @@ where let target_dir = std::env::var_os("CLIPPY_DOGFOOD") .map(|_| { std::env::var_os("CARGO_MANIFEST_DIR").map_or_else( - || { - let mut fallback = std::ffi::OsString::new(); - fallback.push("clippy_dogfood"); - fallback - }, + || std::ffi::OsString::from("clippy_dogfood"), |d| { std::path::PathBuf::from(d) .join("target") -- cgit 1.4.1-3-g733a5 From b07f1b097493809045c92bb3ca09b5792310e5a5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 26 Jan 2019 17:49:29 -0800 Subject: base-tests: use subshells to manage current directory It saves on having to pair `cd && think && cd ..`. --- ci/base-tests.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 6675c795b3b..17eec3a4149 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -11,14 +11,15 @@ cargo build --features debugging cargo test --features debugging # for faster build, share target dir between subcrates export CARGO_TARGET_DIR=`pwd`/target/ -cd clippy_lints && cargo test && cd .. -cd rustc_tools_util && cargo test && cd .. -cd clippy_dev && cargo test && cd .. +(cd clippy_lints && cargo test) +(cd rustc_tools_util && cargo test) +(cd clippy_dev && cargo test) # make sure clippy can be called via ./path/to/cargo-clippy -cd clippy_workspace_tests -../target/debug/cargo-clippy -cd .. +( + cd clippy_workspace_tests + ../target/debug/cargo-clippy +) # Perform various checks for lint registration ./util/dev update_lints --check -- cgit 1.4.1-3-g733a5 From f0131fbab6331eb44d88c94783be2ac9b87f8b06 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 26 Jan 2019 18:24:45 -0800 Subject: Add a CI test for cargoless use of clippy-driver --- ci/base-tests.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 17eec3a4149..9b80960211d 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -25,6 +25,31 @@ export CARGO_TARGET_DIR=`pwd`/target/ ./util/dev update_lints --check cargo +nightly fmt --all -- --check +# Check running clippy-driver without cargo +( + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + + # Check sysroot handling + sysroot=$(./target/debug/clippy-driver --print sysroot) + test $sysroot = $(rustc --print sysroot) + + sysroot=$(./target/debug/clippy-driver --sysroot /tmp --print sysroot) + test $sysroot = /tmp + + sysroot=$(SYSROOT=/tmp ./target/debug/clippy-driver --print sysroot) + test $sysroot = /tmp + + # Make sure this isn't set - clippy-driver should cope without it + unset CARGO_MANIFEST_DIR + + # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 + # XXX How to match the clippy invocation in compile-test.rs? + ! ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr + diff <(sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr) tests/ui/cstring.stderr + + # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR +) + # make sure tests are formatted # some lints are sensitive to formatting, exclude some files -- cgit 1.4.1-3-g733a5 From c02367c4e95676833d88d7371568a081db67c836 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 3 Feb 2019 09:12:07 +0200 Subject: Fix breakage due to rust-lang/rust#58079 The rustc change added HirId to a few nodes. As I understand it, the plan is to remove the NodeId from these nodes eventually. Where the NodeId was not being matched, I used `..` to try and avoid further breakage. Where it was, I used `_` to make the fix easier when NodeId is removed. --- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 4 ++-- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/loops.rs | 12 ++++++------ clippy_lints/src/map_clone.rs | 4 ++-- clippy_lints/src/matches.rs | 4 ++-- clippy_lints/src/misc.rs | 7 +++---- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/mod.rs | 8 ++++---- 20 files changed, 34 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 9606b2eda32..74d45505a4b 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -44,7 +44,7 @@ impl LintPass for BlackListedName { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { - if let PatKind::Binding(_, _, ident, _) = pat.node { + if let PatKind::Binding(.., ident, _) = pat.node { if self.blacklist.contains(&ident.name.to_string()) { span_lint( cx, diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index c704a635425..41afe5ce0d7 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -286,7 +286,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap { + PatKind::Binding(.., ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.as_str()) { v.insert(cx.tables.pat_ty(pat)); } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index f0557154f90..4dbb390cd50 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -81,7 +81,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { _ => (), } for (a1, a2) in iter_input_pats(decl, body).zip(args) { - if let PatKind::Binding(_, _, ident, _) = a1.pat.node { + if let PatKind::Binding(.., ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node { if p.segments.len() != 1 { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 7c23503507a..b6e0480d986 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> Functions { } fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option { - if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) { + if let (&hir::PatKind::Binding(_, id, _, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) { Some(id) } else { None diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 59e036c715e..a6d34f2c7a2 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -94,10 +94,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { |db| { if variant.fields.len() == 1 { let span = match def.variants[i].node.data { - VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => { + VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => { fields[0].ty.span }, - VariantData::Unit(_) => unreachable!(), + VariantData::Unit(..) => unreachable!(), }; if let Some(snip) = snippet_opt(cx, span) { db.span_suggestion( diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index f1aed79847f..a4f69e32171 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if_chain! { if let Some(expr) = it.peek(); if let hir::StmtKind::Local(ref local) = stmt.node; - if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.node; + if let hir::PatKind::Binding(mode, canonical_id, _, ident, None) = local.pat.node; if let hir::StmtKind::Expr(ref if_) = expr.node; if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; if !used_in_expr(cx, canonical_id, cond); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 06266257d1e..dcd1a4e0a61 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -969,7 +969,7 @@ fn detect_manual_memcpy<'a, 'tcx>( }) = higher::range(cx, arg) { // the var must be a single name - if let PatKind::Binding(_, canonical_id, _, _) = pat.node { + if let PatKind::Binding(_, canonical_id, _, _, _) = pat.node { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), @@ -1086,7 +1086,7 @@ fn check_for_loop_range<'a, 'tcx>( }) = higher::range(cx, arg) { // the var must be a single name - if let PatKind::Binding(_, canonical_id, ident, _) = pat.node { + if let PatKind::Binding(_, canonical_id, _, ident, _) = pat.node { let mut visitor = VarVisitor { cx, var: canonical_id, @@ -1637,7 +1637,7 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { match *pat { PatKind::Wild => true, - PatKind::Binding(_, _, ident, None) if ident.as_str().starts_with('_') => { + PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => { let mut visitor = UsedVisitor { var: ident.name, used: false, @@ -2095,7 +2095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { // Look for declarations of the variable if let StmtKind::Local(ref local) = stmt.node { if local.pat.id == self.var_id { - if let PatKind::Binding(_, _, ident, _) = local.pat.node { + if let PatKind::Binding(.., ident, _) = local.pat.node { self.name = Some(ident.name); self.state = if let Some(ref init) = local.init { @@ -2286,7 +2286,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { if self.nesting != Unknown { return; } - if let PatKind::Binding(_, _, span_name, _) = pat.node { + if let PatKind::Binding(.., span_name, _) = pat.node { if self.iterator == span_name.name { self.nesting = RuledOut; return; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 49bd8f650e5..5699870c307 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -70,13 +70,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { then { match closure_body.arguments[0].pat.node { hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding( - hir::BindingAnnotation::Unannotated, _, name, None + hir::BindingAnnotation::Unannotated, .., name, None ) = inner.node { if ident_eq(name, closure_expr) { lint(cx, e.span, args[0].span); } }, - hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => { + hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => { match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => { if ident_eq(name, inner) && !cx.tables.expr_ty(inner).is_box() { diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6ef07316691..9cb160685ca 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -338,7 +338,7 @@ fn check_single_match_opt_like( } print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) }, - PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None) => ident.to_string(), + PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => ident.to_string(), PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), _ => return, }; @@ -657,7 +657,7 @@ fn is_ref_some_arm(arm: &Arm) -> Option { if_chain! { if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pats[0].node; if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); - if let PatKind::Binding(rb, _, ident, _) = pats[0].node; + if let PatKind::Binding(rb, .., ident, _) = pats[0].node; if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).node; if let ExprKind::Path(ref some_path) = e.node; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index c15fba76869..99cdba9402f 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -264,8 +264,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } for arg in iter_input_pats(decl, body) { match arg.pat.node { - PatKind::Binding(BindingAnnotation::Ref, _, _, _) - | PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => { + PatKind::Binding(BindingAnnotation::Ref, ..) | PatKind::Binding(BindingAnnotation::RefMut, ..) => { span_lint( cx, TOPLEVEL_REF_ARG, @@ -282,7 +281,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) { if_chain! { if let StmtKind::Local(ref l) = s.node; - if let PatKind::Binding(an, _, i, None) = l.pat.node; + if let PatKind::Binding(an, .., i, None) = l.pat.node; if let Some(ref init) = l.init; then { if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut { @@ -445,7 +444,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { - if let PatKind::Binding(_, _, ident, Some(ref right)) = pat.node { + if let PatKind::Binding(.., ident, Some(ref right)) = pat.node { if let PatKind::Wild = right.node { span_lint( cx, diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 206a1465a46..777d2f683f0 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { return; } if_chain! { - if let PatKind::Binding(BindingAnnotation::Ref, _, name, _) = pat.node; + if let PatKind::Binding(BindingAnnotation::Ref, .., name, _) = pat.node; if let ty::Ref(_, tam, mutbl) = cx.tables.pat_ty(pat).sty; if mutbl == MutImmutable; if let ty::Ref(_, _, mutbl) = tam.sty; diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index bf2857d9288..eae8ed541e2 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { if let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node; // Check sub_pat got a `ref` keyword (excluding `ref mut`). - if let PatKind::Binding(BindingAnnotation::Ref, _, spanned_name, ..) = sub_pat.node; + if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.node; then { span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced", diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index a8cc5eeec9f..77a6aeba53b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Ignore `self`s. if idx == 0 { - if let PatKind::Binding(_, _, ident, ..) = arg.pat.node { + if let PatKind::Binding(.., ident, _) = arg.pat.node { if ident.as_str() == "self" { continue; } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 1f341bd22ee..722f64405c7 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tcx Body) { let mut bindings = Vec::new(); for arg in iter_input_pats(decl, body) { - if let PatKind::Binding(_, _, ident, _) = arg.pat.node { + if let PatKind::Binding(.., ident, _) = arg.pat.node { bindings.push((ident.name, ident.span)) } } @@ -172,7 +172,7 @@ fn check_pat<'a, 'tcx>( ) { // TODO: match more stuff / destructuring match pat.node { - PatKind::Binding(_, _, ident, ref inner) => { + PatKind::Binding(.., ident, ref inner) => { let name = ident.name; if is_binding(cx, pat.hir_id) { let mut new_binding = true; diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 1f9f369cfe4..b8ab32491a3 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` if_chain! { if let StmtKind::Local(ref local) = stmt.node; - if let PatKind::Binding(BindingAnnotation::Mutable, _, variable_name, None) = local.pat.node; + if let PatKind::Binding(BindingAnnotation::Mutable, .., variable_name, None) = local.pat.node; if let Some(ref init) = local.init; if let Some(ref len_arg) = Self::is_vec_with_capacity(init); diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index af7fd11c6e5..7b532cdb172 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -77,7 +77,7 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) { // let t = foo(); if let StmtKind::Local(ref tmp) = w[0].node; if let Some(ref tmp_init) = tmp.init; - if let PatKind::Binding(_, _, ident, None) = tmp.pat.node; + if let PatKind::Binding(.., ident, None) = tmp.pat.node; // foo() = bar(); if let StmtKind::Semi(ref first) = w[1].node; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 5a76b965d26..264a5463225 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -513,7 +513,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let current = format!("{}.node", self.current); match pat.node { PatKind::Wild => println!("Wild = {};", current), - PatKind::Binding(anno, _, ident, ref sub) => { + PatKind::Binding(anno, .., ident, ref sub) => { let anno_pat = match anno { BindingAnnotation::Unannotated => "BindingAnnotation::Unannotated", BindingAnnotation::Mutable => "BindingAnnotation::Mutable", diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 2b0b0e7121f..53876fef579 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs }, - (&PatKind::Binding(ref lb, _, ref li, ref lp), &PatKind::Binding(ref rb, _, ref ri, ref rp)) => { + (&PatKind::Binding(ref lb, .., ref li, ref lp), &PatKind::Binding(ref rb, .., ref ri, ref rp)) => { lb == rb && li.name.as_str() == ri.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) }, (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r), diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 758d1d2d365..508bf26bab9 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -420,7 +420,7 @@ fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) { println!("{}+", ind); match pat.node { hir::PatKind::Wild => println!("{}Wild", ind), - hir::PatKind::Binding(ref mode, _, ident, ref inner) => { + hir::PatKind::Binding(ref mode, .., ident, ref inner) => { println!("{}Binding", ind); println!("{}mode: {:?}", ind, mode); println!("{}name: {}", ind, ident.name); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ee3356fdc82..e68cefe2bc4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -373,7 +373,7 @@ pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option { /// Get the name of a `Pat`, if any pub fn get_pat_name(pat: &Pat) -> Option { match pat.node { - PatKind::Binding(_, _, ref spname, _) => Some(spname.name), + PatKind::Binding(.., ref spname, _) => Some(spname.name), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), _ => None, @@ -1008,7 +1008,7 @@ pub fn opt_def_id(def: Def) -> Option { } pub fn is_self(slf: &Arg) -> bool { - if let PatKind::Binding(_, _, name, _) = slf.pat.node { + if let PatKind::Binding(.., name, _) = slf.pat.node { name.name == keywords::SelfLower.name() } else { false @@ -1038,7 +1038,7 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { if_chain! { if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pats[0].node; if match_qpath(path, &paths::RESULT_OK[1..]); - if let PatKind::Binding(_, defid, _, None) = pat[0].node; + if let PatKind::Binding(_, defid, _, _, None) = pat[0].node; if let ExprKind::Path(QPath::Resolved(None, ref path)) = arm.body.node; if let Def::Local(lid) = path.def; if lid == defid; @@ -1087,7 +1087,7 @@ pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: NodeId) -> pub fn get_arg_name(pat: &Pat) -> Option { match pat.node { - PatKind::Binding(_, _, ident, None) => Some(ident.name), + PatKind::Binding(.., ident, None) => Some(ident.name), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), _ => None, } -- cgit 1.4.1-3-g733a5 From 3100fecb99782941a2512d58e7021fd93a57b619 Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 3 Feb 2019 18:28:42 +0900 Subject: use snippet for making a suggestion if possible --- clippy_lints/src/dbg_macro.rs | 45 +++++++++++++++++++++++++++++++++++-------- tests/ui/dbg_macro.stderr | 29 +++++++++++++++++++++------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 0b8f0c3f5fc..228d31bd554 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,7 +1,10 @@ -use crate::utils::span_help_and_lint; +use crate::utils::{span_help_and_lint, span_lint_and_sugg, snippet_opt}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use syntax::ast; +use rustc_errors::Applicability; +use syntax::tokenstream::TokenStream; +use syntax::source_map::Span; /// **What it does:** Checks for usage of dbg!() macro. /// @@ -40,13 +43,39 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { if mac.node.path == "dbg" { - span_help_and_lint( - cx, - DBG_MACRO, - mac.span, - "`dbg!` macro is intended as a debugging tool", - "ensure to avoid having uses of it in version control", - ); + match tts_span(mac.node.tts.clone()).and_then(|span| snippet_opt(cx, span)) { + Some(sugg) => { + span_lint_and_sugg( + cx, + DBG_MACRO, + mac.span, + "`dbg!` macro is intended as a debugging tool", + "ensure to avoid having uses of it in version control", + sugg, + Applicability::MaybeIncorrect, + ); + } + None => { + span_help_and_lint( + cx, + DBG_MACRO, + mac.span, + "`dbg!` macro is intended as a debugging tool", + "ensure to avoid having uses of it in version control", + ); + } + }; } } } + +// Get span enclosing entire the token stream. +fn tts_span(tts: TokenStream) -> Option { + let mut cursor = tts.into_trees(); + let first = cursor.next()?.span(); + let span = match cursor.last() { + Some(tree) => first.to(tree.span()), + None => first, + }; + Some(span) +} diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr index 28e59f4c11b..43a60180f96 100644 --- a/tests/ui/dbg_macro.stderr +++ b/tests/ui/dbg_macro.stderr @@ -5,55 +5,70 @@ LL | if let Some(n) = dbg!(n.checked_sub(4)) { | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::dbg-macro` implied by `-D warnings` - = help: ensure to avoid having uses of it in version control +help: ensure to avoid having uses of it in version control + | +LL | if let Some(n) = n.checked_sub(4) { + | ^^^^^^^^^^^^^^^^ error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:12:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ +help: ensure to avoid having uses of it in version control | - = help: ensure to avoid having uses of it in version control +LL | if n <= 1 { + | ^^^^^^ error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:13:9 | LL | dbg!(1) | ^^^^^^^ +help: ensure to avoid having uses of it in version control + | +LL | 1 | - = help: ensure to avoid having uses of it in version control error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:15:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ensure to avoid having uses of it in version control + | +LL | n * factorial(n - 1) | - = help: ensure to avoid having uses of it in version control error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:20:5 | LL | dbg!(42); | ^^^^^^^^ +help: ensure to avoid having uses of it in version control | - = help: ensure to avoid having uses of it in version control +LL | 42; + | ^^ error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:21:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ +help: ensure to avoid having uses of it in version control | - = help: ensure to avoid having uses of it in version control +LL | dbg!(dbg!(42)); + | ^^^^^^^^^^^^^^ error: `dbg!` macro is intended as a debugging tool --> $DIR/dbg_macro.rs:22:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ +help: ensure to avoid having uses of it in version control | - = help: ensure to avoid having uses of it in version control +LL | foo(3) + factorial(4); + | ^^^^^^^^^^^^ error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 60f723fba42756138f3a9386b8376e2ed3e7dda1 Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 3 Feb 2019 18:50:00 +0900 Subject: prefer `if` to `match` --- clippy_lints/src/dbg_macro.rs | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 228d31bd554..ae551a0792d 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -43,28 +43,25 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { if mac.node.path == "dbg" { - match tts_span(mac.node.tts.clone()).and_then(|span| snippet_opt(cx, span)) { - Some(sugg) => { - span_lint_and_sugg( - cx, - DBG_MACRO, - mac.span, - "`dbg!` macro is intended as a debugging tool", - "ensure to avoid having uses of it in version control", - sugg, - Applicability::MaybeIncorrect, - ); - } - None => { - span_help_and_lint( - cx, - DBG_MACRO, - mac.span, - "`dbg!` macro is intended as a debugging tool", - "ensure to avoid having uses of it in version control", - ); - } - }; + if let Some(sugg) = tts_span(mac.node.tts.clone()).and_then(|span| snippet_opt(cx, span)) { + span_lint_and_sugg( + cx, + DBG_MACRO, + mac.span, + "`dbg!` macro is intended as a debugging tool", + "ensure to avoid having uses of it in version control", + sugg, + Applicability::MaybeIncorrect, + ); + } else { + span_help_and_lint( + cx, + DBG_MACRO, + mac.span, + "`dbg!` macro is intended as a debugging tool", + "ensure to avoid having uses of it in version control", + ); + } } } } -- cgit 1.4.1-3-g733a5 From 83d620b8246094ff54c90888f53015b1ef5a2bf8 Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 3 Feb 2019 21:28:43 +0900 Subject: run `util/dev update_lints` and `cargo fmt --all` --- README.md | 2 +- clippy_lints/src/dbg_macro.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8519fe55a9f..d3d82eb0752 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 295 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 296 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index ae551a0792d..d75970ce50a 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,10 +1,10 @@ -use crate::utils::{span_help_and_lint, span_lint_and_sugg, snippet_opt}; +use crate::utils::{snippet_opt, span_help_and_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; -use syntax::ast; use rustc_errors::Applicability; -use syntax::tokenstream::TokenStream; +use syntax::ast; use syntax::source_map::Span; +use syntax::tokenstream::TokenStream; /// **What it does:** Checks for usage of dbg!() macro. /// -- cgit 1.4.1-3-g733a5 From 64ff65990fe6584d6a9e273c7487e538c9d5e245 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 3 Feb 2019 14:47:03 +0100 Subject: Transition leftover test libs to Rust 2018 --- clippy_workspace_tests/Cargo.toml | 1 + clippy_workspace_tests/src/main.rs | 2 ++ mini-macro/Cargo.toml | 1 + mini-macro/src/lib.rs | 1 + 4 files changed, 5 insertions(+) diff --git a/clippy_workspace_tests/Cargo.toml b/clippy_workspace_tests/Cargo.toml index a282378c951..7a235b215d3 100644 --- a/clippy_workspace_tests/Cargo.toml +++ b/clippy_workspace_tests/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "clippy_workspace_tests" version = "0.1.0" +edition = "2018" [workspace] members = ["subcrate"] diff --git a/clippy_workspace_tests/src/main.rs b/clippy_workspace_tests/src/main.rs index f79c691f085..0dcdf6383fd 100644 --- a/clippy_workspace_tests/src/main.rs +++ b/clippy_workspace_tests/src/main.rs @@ -1,2 +1,4 @@ +#![deny(rust_2018_idioms)] + fn main() { } diff --git a/mini-macro/Cargo.toml b/mini-macro/Cargo.toml index 2cdba4c3236..a21e7fec6d4 100644 --- a/mini-macro/Cargo.toml +++ b/mini-macro/Cargo.toml @@ -11,6 +11,7 @@ authors = [ license = "MPL-2.0" description = "A macro to test clippy's procedural macro checks" repository = "https://github.com/rust-lang/rust-clippy" +edition = "2018" [lib] name = "clippy_mini_macro_test" diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 0a96be71b35..ec489344a6f 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,4 +1,5 @@ #![feature(proc_macro_quote, proc_macro_hygiene)] +#![deny(rust_2018_idioms)] extern crate proc_macro; use proc_macro::{TokenStream, quote}; -- cgit 1.4.1-3-g733a5 From 47563a13eba19d0fc4b56f2cd0d5645fc81e7bc3 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 2 Feb 2019 11:54:18 -0800 Subject: Add setup-toolchain.sh script to configure the master version of rustc, and update CONTRIBUTING.md accordingly. --- .travis.yml | 5 +---- CONTRIBUTING.md | 4 ++++ ci/base-tests.sh | 4 ++-- setup-toolchain.sh | 9 +++++++++ 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100755 setup-toolchain.sh diff --git a/.travis.yml b/.travis.yml index d7b26225518..acb5b9ae0d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -90,10 +90,7 @@ matrix: script: - | rm rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') - travis_retry rustup-toolchain-install-master -f -n master $RUSTC_HASH - rustup default master + ./setup-toolchain.sh export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - | if [ -z ${INTEGRATION} ]; then diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 415fb7ab0d7..5619ee00f8d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,6 +73,10 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us ## Writing code +Clippy depends on the current git master version of rustc, which can change rapidly. Make sure you're +working near rust-clippy's master, and use the `setup-toolchain.sh` script to configure the appropriate +toolchain for this directory. + [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer to lint-writing, though it does get into advanced stuff. Most lints consist of an implementation of `LintPass` with one or more of its default methods overridden. See the existing lints for examples diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 6675c795b3b..3ac6bbe6725 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -29,7 +29,7 @@ cargo +nightly fmt --all -- --check # some lints are sensitive to formatting, exclude some files tests_need_reformatting="false" # switch to nightly -rustup default nightly +rustup override set nightly # avoid loop spam and allow cmds with exit status != 0 set +ex @@ -49,4 +49,4 @@ if [ "${tests_need_reformatting}" == "true" ] ; then fi # switch back to master -rustup default master +rustup override set master diff --git a/setup-toolchain.sh b/setup-toolchain.sh new file mode 100755 index 00000000000..f8d764b6132 --- /dev/null +++ b/setup-toolchain.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Set up the appropriate rustc toolchain + +cd $(dirname $0) + +cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" +RUSTC_HASH=$(git ls-remote https://github.com/rust-lang/rust.git master | awk '{print $1}') +rustup-toolchain-install-master -f -n master $RUSTC_HASH +rustup override set master -- cgit 1.4.1-3-g733a5 From f3ee53d2259299e42bff3456a99def6ae3be8f84 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 4 Feb 2019 07:29:19 +0200 Subject: Document `get_def_path` --- clippy_lints/src/utils/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b9cde75d51d..eebc2913d29 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -130,6 +130,15 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) } +/// Get the absolute path of `def_id` as a vector of `&str`. +/// +/// # Examples +/// ```rust,ignore +/// let def_path = get_def_path(tcx, def_id); +/// if let &["core", "option", "Option"] = &def_path[..] { +/// // The given `def_id` is that of an `Option` type +/// }; +/// ``` pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> { let mut apb = AbsolutePathBuffer { names: vec![] }; tcx.push_item_path(&mut apb, def_id, false); -- cgit 1.4.1-3-g733a5 From 446e2ecfb72cf91c8389a42357a168de77dd414b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 5 Feb 2019 19:05:42 +0100 Subject: Don't warn about const assertions when assert is in a macro itself --- clippy_lints/src/assertions_on_constants.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index d420de3a4db..92ee9d1bc66 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -3,7 +3,7 @@ use crate::rustc::hir::{Expr, ExprKind}; use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::syntax::ast::LitKind; -use crate::utils::{is_direct_expn_of, span_help_and_lint}; +use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint}; use if_chain::if_chain; /// **What it does:** Check to call assert!(true/false) @@ -43,7 +43,9 @@ impl LintPass for AssertionsOnConstants { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if_chain! { - if is_direct_expn_of(e.span, "assert").is_some(); + if let Some(assert_span) = is_direct_expn_of(e.span, "assert"); + if !in_macro(assert_span) + || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span)); if let ExprKind::Unary(_, ref lit) = e.node; then { if let ExprKind::Lit(ref inner) = lit.node { -- cgit 1.4.1-3-g733a5 From cb2d987ed4d4074e67ec307cbf5bfe289e876a3b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 5 Feb 2019 19:06:08 +0100 Subject: Add tests for assertion_on_constants macro check --- tests/ui/assertions_on_constants.rs | 11 +++++++++++ tests/ui/assertions_on_constants.stderr | 23 ++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs index daeceebd3a2..0d2953c7ed8 100644 --- a/tests/ui/assertions_on_constants.rs +++ b/tests/ui/assertions_on_constants.rs @@ -1,3 +1,10 @@ +macro_rules! assert_const { + ($len:expr) => { + assert!($len > 0); + debug_assert!($len < 0); + }; +} + fn main() { assert!(true); assert!(false); @@ -9,4 +16,8 @@ fn main() { const C: bool = false; assert!(C); + + debug_assert!(true); + assert_const!(3); + assert_const!(-1); } diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index e8001acceb1..adfa326abac 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -1,5 +1,5 @@ error: assert!(true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:2:5 + --> $DIR/assertions_on_constants.rs:9:5 | LL | assert!(true); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | assert!(true); = help: remove it error: assert!(false) should probably be replaced - --> $DIR/assertions_on_constants.rs:3:5 + --> $DIR/assertions_on_constants.rs:10:5 | LL | assert!(false); | ^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | assert!(false); = help: use panic!() or unreachable!() error: assert!(true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:4:5 + --> $DIR/assertions_on_constants.rs:11:5 | LL | assert!(true, "true message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | assert!(true, "true message"); = help: remove it error: assert!(false) should probably be replaced - --> $DIR/assertions_on_constants.rs:5:5 + --> $DIR/assertions_on_constants.rs:12:5 | LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | assert!(false, "false message"); = help: use panic!() or unreachable!() error: assert!(const: true) will be optimized out by the compiler - --> $DIR/assertions_on_constants.rs:8:5 + --> $DIR/assertions_on_constants.rs:15:5 | LL | assert!(B); | ^^^^^^^^^^^ @@ -40,12 +40,21 @@ LL | assert!(B); = help: remove it error: assert!(const: false) should probably be replaced - --> $DIR/assertions_on_constants.rs:11:5 + --> $DIR/assertions_on_constants.rs:18:5 | LL | assert!(C); | ^^^^^^^^^^^ | = help: use panic!() or unreachable!() -error: aborting due to 6 previous errors +error: assert!(true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:20:5 + | +LL | debug_assert!(true); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: remove it + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From a586f52a0fa14d60a9a19cfe4e530f9e31e343a4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 6 Feb 2019 07:45:57 +0100 Subject: Move run-pass tests to UI tests This should give us more UI coverage for free. It also removes the `run-pass` suite, so we now only have the `ui` suite. --- tests/compile-test.rs | 1 - tests/run-pass/associated-constant-ice.rs | 11 -------- tests/run-pass/cc_seme.rs | 24 ---------------- tests/run-pass/enum-glob-import-crate.rs | 6 ---- tests/run-pass/ice-1588.rs | 11 -------- tests/run-pass/ice-1782.rs | 26 ----------------- tests/run-pass/ice-1969.rs | 11 -------- tests/run-pass/ice-2499.rs | 26 ----------------- tests/run-pass/ice-2594.rs | 20 ------------- tests/run-pass/ice-2727.rs | 5 ---- tests/run-pass/ice-2760.rs | 24 ---------------- tests/run-pass/ice-2774.rs | 27 ------------------ tests/run-pass/ice-2865.rs | 13 --------- tests/run-pass/ice-3151.rs | 13 --------- tests/run-pass/ice-3462.rs | 21 -------------- tests/run-pass/ice-700.rs | 7 ----- tests/run-pass/ice_exacte_size.rs | 17 ------------ tests/run-pass/if_same_then_else.rs | 13 --------- tests/run-pass/issue-2862.rs | 14 ---------- tests/run-pass/issue-825.rs | 23 --------------- tests/run-pass/issues_loop_mut_cond.rs | 28 ------------------- tests/run-pass/match_same_arms_const.rs | 16 ----------- tests/run-pass/mut_mut_macro.rs | 32 --------------------- tests/run-pass/needless_borrow_fp.rs | 7 ----- tests/run-pass/needless_lifetimes_impl_trait.rs | 20 ------------- tests/run-pass/procedural_macro.rs | 11 -------- tests/run-pass/regressions.rs | 7 ----- tests/run-pass/returns.rs | 21 -------------- tests/run-pass/single-match-else.rs | 9 ------ tests/run-pass/used_underscore_binding_macro.rs | 19 ------------- tests/run-pass/whitelist/clippy.toml | 3 -- tests/run-pass/whitelist/conf_whitelisted.rs | 1 - tests/ui/crashes/associated-constant-ice.rs | 13 +++++++++ tests/ui/crashes/cc_seme.rs | 27 ++++++++++++++++++ tests/ui/crashes/enum-glob-import-crate.rs | 6 ++++ tests/ui/crashes/ice-1588.rs | 13 +++++++++ tests/ui/crashes/ice-1782.rs | 26 +++++++++++++++++ tests/ui/crashes/ice-1969.rs | 13 +++++++++ tests/ui/crashes/ice-2499.rs | 26 +++++++++++++++++ tests/ui/crashes/ice-2594.rs | 20 +++++++++++++ tests/ui/crashes/ice-2727.rs | 7 +++++ tests/ui/crashes/ice-2760.rs | 24 ++++++++++++++++ tests/ui/crashes/ice-2774.rs | 27 ++++++++++++++++++ tests/ui/crashes/ice-2865.rs | 16 +++++++++++ tests/ui/crashes/ice-3151.rs | 15 ++++++++++ tests/ui/crashes/ice-3462.rs | 23 +++++++++++++++ tests/ui/crashes/ice-700.rs | 9 ++++++ tests/ui/crashes/ice_exacte_size.rs | 19 +++++++++++++ tests/ui/crashes/if_same_then_else.rs | 15 ++++++++++ tests/ui/crashes/issue-2862.rs | 16 +++++++++++ tests/ui/crashes/issue-825.rs | 25 +++++++++++++++++ tests/ui/crashes/issues_loop_mut_cond.rs | 28 +++++++++++++++++++ tests/ui/crashes/match_same_arms_const.rs | 18 ++++++++++++ tests/ui/crashes/mut_mut_macro.rs | 34 +++++++++++++++++++++++ tests/ui/crashes/needless_borrow_fp.rs | 7 +++++ tests/ui/crashes/needless_lifetimes_impl_trait.rs | 20 +++++++++++++ tests/ui/crashes/procedural_macro.rs | 11 ++++++++ tests/ui/crashes/regressions.rs | 7 +++++ tests/ui/crashes/returns.rs | 23 +++++++++++++++ tests/ui/crashes/single-match-else.rs | 11 ++++++++ tests/ui/crashes/used_underscore_binding_macro.rs | 19 +++++++++++++ tests/ui/crashes/whitelist/clippy.toml | 3 ++ tests/ui/crashes/whitelist/conf_whitelisted.rs | 1 + 63 files changed, 522 insertions(+), 487 deletions(-) delete mode 100644 tests/run-pass/associated-constant-ice.rs delete mode 100644 tests/run-pass/cc_seme.rs delete mode 100644 tests/run-pass/enum-glob-import-crate.rs delete mode 100644 tests/run-pass/ice-1588.rs delete mode 100644 tests/run-pass/ice-1782.rs delete mode 100644 tests/run-pass/ice-1969.rs delete mode 100644 tests/run-pass/ice-2499.rs delete mode 100644 tests/run-pass/ice-2594.rs delete mode 100644 tests/run-pass/ice-2727.rs delete mode 100644 tests/run-pass/ice-2760.rs delete mode 100644 tests/run-pass/ice-2774.rs delete mode 100644 tests/run-pass/ice-2865.rs delete mode 100644 tests/run-pass/ice-3151.rs delete mode 100644 tests/run-pass/ice-3462.rs delete mode 100644 tests/run-pass/ice-700.rs delete mode 100644 tests/run-pass/ice_exacte_size.rs delete mode 100644 tests/run-pass/if_same_then_else.rs delete mode 100644 tests/run-pass/issue-2862.rs delete mode 100644 tests/run-pass/issue-825.rs delete mode 100644 tests/run-pass/issues_loop_mut_cond.rs delete mode 100644 tests/run-pass/match_same_arms_const.rs delete mode 100644 tests/run-pass/mut_mut_macro.rs delete mode 100644 tests/run-pass/needless_borrow_fp.rs delete mode 100644 tests/run-pass/needless_lifetimes_impl_trait.rs delete mode 100644 tests/run-pass/procedural_macro.rs delete mode 100644 tests/run-pass/regressions.rs delete mode 100644 tests/run-pass/returns.rs delete mode 100644 tests/run-pass/single-match-else.rs delete mode 100644 tests/run-pass/used_underscore_binding_macro.rs delete mode 100644 tests/run-pass/whitelist/clippy.toml delete mode 100644 tests/run-pass/whitelist/conf_whitelisted.rs create mode 100644 tests/ui/crashes/associated-constant-ice.rs create mode 100644 tests/ui/crashes/cc_seme.rs create mode 100644 tests/ui/crashes/enum-glob-import-crate.rs create mode 100644 tests/ui/crashes/ice-1588.rs create mode 100644 tests/ui/crashes/ice-1782.rs create mode 100644 tests/ui/crashes/ice-1969.rs create mode 100644 tests/ui/crashes/ice-2499.rs create mode 100644 tests/ui/crashes/ice-2594.rs create mode 100644 tests/ui/crashes/ice-2727.rs create mode 100644 tests/ui/crashes/ice-2760.rs create mode 100644 tests/ui/crashes/ice-2774.rs create mode 100644 tests/ui/crashes/ice-2865.rs create mode 100644 tests/ui/crashes/ice-3151.rs create mode 100644 tests/ui/crashes/ice-3462.rs create mode 100644 tests/ui/crashes/ice-700.rs create mode 100644 tests/ui/crashes/ice_exacte_size.rs create mode 100644 tests/ui/crashes/if_same_then_else.rs create mode 100644 tests/ui/crashes/issue-2862.rs create mode 100644 tests/ui/crashes/issue-825.rs create mode 100644 tests/ui/crashes/issues_loop_mut_cond.rs create mode 100644 tests/ui/crashes/match_same_arms_const.rs create mode 100644 tests/ui/crashes/mut_mut_macro.rs create mode 100644 tests/ui/crashes/needless_borrow_fp.rs create mode 100644 tests/ui/crashes/needless_lifetimes_impl_trait.rs create mode 100644 tests/ui/crashes/procedural_macro.rs create mode 100644 tests/ui/crashes/regressions.rs create mode 100644 tests/ui/crashes/returns.rs create mode 100644 tests/ui/crashes/single-match-else.rs create mode 100644 tests/ui/crashes/used_underscore_binding_macro.rs create mode 100644 tests/ui/crashes/whitelist/clippy.toml create mode 100644 tests/ui/crashes/whitelist/conf_whitelisted.rs diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c67b6f08c9f..b6a4beff046 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -133,7 +133,6 @@ fn prepare_env() { #[test] fn compile_test() { prepare_env(); - run_mode("run-pass", "tests/run-pass".into()); run_mode("ui", "tests/ui".into()); run_ui_toml(); } diff --git a/tests/run-pass/associated-constant-ice.rs b/tests/run-pass/associated-constant-ice.rs deleted file mode 100644 index 2c5c90683cc..00000000000 --- a/tests/run-pass/associated-constant-ice.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub trait Trait { - const CONSTANT: u8; -} - -impl Trait for u8 { - const CONSTANT: u8 = 2; -} - -fn main() { - println!("{}", u8::CONSTANT * 10); -} diff --git a/tests/run-pass/cc_seme.rs b/tests/run-pass/cc_seme.rs deleted file mode 100644 index 169403df562..00000000000 --- a/tests/run-pass/cc_seme.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[allow(dead_code)] -enum Baz { - One, - Two, -} - -struct Test { - t: Option, - b: Baz, -} - -fn main() {} - -pub fn foo() { - use Baz::*; - let x = Test { t: Some(0), b: One }; - - match x { - Test { t: Some(_), b: One } => unreachable!(), - Test { t: Some(42), b: Two } => unreachable!(), - Test { t: None, .. } => unreachable!(), - Test { .. } => unreachable!(), - } -} diff --git a/tests/run-pass/enum-glob-import-crate.rs b/tests/run-pass/enum-glob-import-crate.rs deleted file mode 100644 index dca32aa3b56..00000000000 --- a/tests/run-pass/enum-glob-import-crate.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![deny(clippy::all)] -#![allow(unused_imports)] - -use std::*; - -fn main() {} diff --git a/tests/run-pass/ice-1588.rs b/tests/run-pass/ice-1588.rs deleted file mode 100644 index 6a5bf429f2d..00000000000 --- a/tests/run-pass/ice-1588.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![allow(clippy::all)] - -fn main() { - match 1 { - 1 => {}, - 2 => { - [0; 1]; - }, - _ => {}, - } -} diff --git a/tests/run-pass/ice-1782.rs b/tests/run-pass/ice-1782.rs deleted file mode 100644 index 81af88962a6..00000000000 --- a/tests/run-pass/ice-1782.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![allow(dead_code, unused_variables)] - -/// Should not trigger an ICE in `SpanlessEq` / `consts::constant` -/// -/// Issue: https://github.com/rust-lang/rust-clippy/issues/1782 -use std::{mem, ptr}; - -fn spanless_eq_ice() { - let txt = "something"; - match txt { - "something" => unsafe { - ptr::write( - ptr::null_mut() as *mut u32, - mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), - ) - }, - _ => unsafe { - ptr::write( - ptr::null_mut() as *mut u32, - mem::transmute::<[u8; 4], _>([13, 246, 24, 255]), - ) - }, - } -} - -fn main() {} diff --git a/tests/run-pass/ice-1969.rs b/tests/run-pass/ice-1969.rs deleted file mode 100644 index eab4f338f97..00000000000 --- a/tests/run-pass/ice-1969.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![allow(clippy::all)] - -fn main() {} - -pub trait Convert { - type Action: From<*const f64>; - - fn convert(val: *const f64) -> Self::Action { - val.into() - } -} diff --git a/tests/run-pass/ice-2499.rs b/tests/run-pass/ice-2499.rs deleted file mode 100644 index 45b3b1869dd..00000000000 --- a/tests/run-pass/ice-2499.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] - -/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` -/// -/// Issue: https://github.com/rust-lang/rust-clippy/issues/2499 - -fn f(s: &[u8]) -> bool { - let t = s[0] as char; - - match t { - 'E' | 'W' => {}, - 'T' => { - if s[0..4] != ['0' as u8; 4] { - return false; - } else { - return true; - } - }, - _ => { - return false; - }, - } - true -} - -fn main() {} diff --git a/tests/run-pass/ice-2594.rs b/tests/run-pass/ice-2594.rs deleted file mode 100644 index 3f3986b6fc6..00000000000 --- a/tests/run-pass/ice-2594.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![allow(dead_code, unused_variables)] - -/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` -/// -/// Issue: https://github.com/rust-lang/rust-clippy/issues/2594 - -fn spanless_hash_ice() { - let txt = "something"; - let empty_header: [u8; 1] = [1; 1]; - - match txt { - "something" => { - let mut headers = [empty_header; 1]; - }, - "" => (), - _ => (), - } -} - -fn main() {} diff --git a/tests/run-pass/ice-2727.rs b/tests/run-pass/ice-2727.rs deleted file mode 100644 index 79c6f1c55db..00000000000 --- a/tests/run-pass/ice-2727.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn f(new: fn()) { - new(); -} - -fn main() {} diff --git a/tests/run-pass/ice-2760.rs b/tests/run-pass/ice-2760.rs deleted file mode 100644 index 949e273997c..00000000000 --- a/tests/run-pass/ice-2760.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![allow( - unused_variables, - clippy::blacklisted_name, - clippy::needless_pass_by_value, - dead_code -)] - -// This should not compile-fail with: -// -// error[E0277]: the trait bound `T: Foo` is not satisfied -// -// See https://github.com/rust-lang/rust-clippy/issues/2760 - -trait Foo { - type Bar; -} - -struct Baz { - bar: T::Bar, -} - -fn take(baz: Baz) {} - -fn main() {} diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs deleted file mode 100644 index 2cc19ae32b8..00000000000 --- a/tests/run-pass/ice-2774.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::collections::HashSet; - -// See https://github.com/rust-lang/rust-clippy/issues/2774 - -#[derive(Eq, PartialEq, Debug, Hash)] -pub struct Bar { - foo: Foo, -} - -#[derive(Eq, PartialEq, Debug, Hash)] -pub struct Foo {} - -#[allow(clippy::implicit_hasher)] -// This should not cause a 'cannot relate bound region' ICE -pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { - let mut foos = HashSet::new(); - foos.extend(bars.iter().map(|b| &b.foo)); -} - -#[allow(clippy::implicit_hasher)] -// Also this should not cause a 'cannot relate bound region' ICE -pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { - let mut foos = HashSet::new(); - foos.extend(bars.iter().map(|b| &b.foo)); -} - -fn main() {} diff --git a/tests/run-pass/ice-2865.rs b/tests/run-pass/ice-2865.rs deleted file mode 100644 index 64092afd53d..00000000000 --- a/tests/run-pass/ice-2865.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[allow(dead_code)] -struct Ice { - size: String, -} - -impl<'a> From for Ice { - fn from(_: String) -> Self { - let text = || "iceberg".to_string(); - Self { size: text() } - } -} - -fn main() {} diff --git a/tests/run-pass/ice-3151.rs b/tests/run-pass/ice-3151.rs deleted file mode 100644 index a03dd05e7d3..00000000000 --- a/tests/run-pass/ice-3151.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[derive(Clone)] -pub struct HashMap { - hash_builder: S, - table: RawTable, -} - -#[derive(Clone)] -pub struct RawTable { - size: usize, - val: V, -} - -fn main() {} diff --git a/tests/run-pass/ice-3462.rs b/tests/run-pass/ice-3462.rs deleted file mode 100644 index d4f6f355c85..00000000000 --- a/tests/run-pass/ice-3462.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![warn(clippy::all)] -#![allow(clippy::blacklisted_name)] -#![allow(unused)] - -enum Foo { - Bar, - Baz, -} - -fn bar(foo: Foo) { - macro_rules! baz { - () => { - if let Foo::Bar = foo {} - }; - } - - baz!(); - baz!(); -} - -fn main() {} diff --git a/tests/run-pass/ice-700.rs b/tests/run-pass/ice-700.rs deleted file mode 100644 index 10546850611..00000000000 --- a/tests/run-pass/ice-700.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![deny(clippy::all)] - -fn core() {} - -fn main() { - core(); -} diff --git a/tests/run-pass/ice_exacte_size.rs b/tests/run-pass/ice_exacte_size.rs deleted file mode 100644 index ac643fafabc..00000000000 --- a/tests/run-pass/ice_exacte_size.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![deny(clippy::all)] - -#[allow(dead_code)] -struct Foo; - -impl Iterator for Foo { - type Item = (); - - fn next(&mut self) -> Option<()> { - let _ = self.len() == 0; - unimplemented!() - } -} - -impl ExactSizeIterator for Foo {} - -fn main() {} diff --git a/tests/run-pass/if_same_then_else.rs b/tests/run-pass/if_same_then_else.rs deleted file mode 100644 index e6ab7cc9d8c..00000000000 --- a/tests/run-pass/if_same_then_else.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![deny(clippy::if_same_then_else)] - -fn main() {} - -pub fn foo(a: i32, b: i32) -> Option<&'static str> { - if a == b { - None - } else if a > b { - Some("a pfeil b") - } else { - None - } -} diff --git a/tests/run-pass/issue-2862.rs b/tests/run-pass/issue-2862.rs deleted file mode 100644 index b35df667f27..00000000000 --- a/tests/run-pass/issue-2862.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub trait FooMap { - fn map B>(&self, f: F) -> B; -} - -impl FooMap for bool { - fn map B>(&self, f: F) -> B { - f() - } -} - -fn main() { - let a = true; - a.map(|| false); -} diff --git a/tests/run-pass/issue-825.rs b/tests/run-pass/issue-825.rs deleted file mode 100644 index b1339212e6e..00000000000 --- a/tests/run-pass/issue-825.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![allow(warnings)] - -// this should compile in a reasonable amount of time -fn rust_type_id(name: &str) { - if "bool" == &name[..] - || "uint" == &name[..] - || "u8" == &name[..] - || "u16" == &name[..] - || "u32" == &name[..] - || "f32" == &name[..] - || "f64" == &name[..] - || "i8" == &name[..] - || "i16" == &name[..] - || "i32" == &name[..] - || "i64" == &name[..] - || "Self" == &name[..] - || "str" == &name[..] - { - unreachable!(); - } -} - -fn main() {} diff --git a/tests/run-pass/issues_loop_mut_cond.rs b/tests/run-pass/issues_loop_mut_cond.rs deleted file mode 100644 index bb238c81ebc..00000000000 --- a/tests/run-pass/issues_loop_mut_cond.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![allow(dead_code)] - -/// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 -pub fn loop_on_block_condition(u: &mut isize) { - while { *u < 0 } { - *u += 1; - } -} - -/// https://github.com/rust-lang/rust-clippy/issues/2584 -fn loop_with_unsafe_condition(ptr: *const u8) { - let mut len = 0; - while unsafe { *ptr.offset(len) } != 0 { - len += 1; - } -} - -/// https://github.com/rust-lang/rust-clippy/issues/2710 -static mut RUNNING: bool = true; -fn loop_on_static_condition() { - unsafe { - while RUNNING { - RUNNING = false; - } - } -} - -fn main() {} diff --git a/tests/run-pass/match_same_arms_const.rs b/tests/run-pass/match_same_arms_const.rs deleted file mode 100644 index 50732475562..00000000000 --- a/tests/run-pass/match_same_arms_const.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![deny(clippy::match_same_arms)] - -const PRICE_OF_SWEETS: u32 = 5; -const PRICE_OF_KINDNESS: u32 = 0; -const PRICE_OF_DRINKS: u32 = 5; - -pub fn price(thing: &str) -> u32 { - match thing { - "rolo" => PRICE_OF_SWEETS, - "advice" => PRICE_OF_KINDNESS, - "juice" => PRICE_OF_DRINKS, - _ => panic!(), - } -} - -fn main() {} diff --git a/tests/run-pass/mut_mut_macro.rs b/tests/run-pass/mut_mut_macro.rs deleted file mode 100644 index af11c29d9b0..00000000000 --- a/tests/run-pass/mut_mut_macro.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] -#![allow(dead_code)] - -// compiletest + extern crates doesn't work together -//#[macro_use] -//extern crate lazy_static; - -//use std::collections::HashMap; - -// ensure that we don't suggest `is_nan` and `is_null` inside constants -// FIXME: once const fn is stable, suggest these functions again in constants -const BAA: *const i32 = 0 as *const i32; -static mut BAR: *const i32 = BAA; -static mut FOO: *const i32 = 0 as *const i32; -static mut BUH: bool = 42.0 < std::f32::NAN; - -#[allow(unused_variables, unused_mut)] -fn main() { - /* - lazy_static! { - static ref MUT_MAP : HashMap = { - let mut m = HashMap::new(); - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert_eq!(*MUT_COUNT, 1); - */ - // FIXME: don't lint in array length, requires `check_body` - //let _ = [""; (42.0 < std::f32::NAN) as usize]; -} diff --git a/tests/run-pass/needless_borrow_fp.rs b/tests/run-pass/needless_borrow_fp.rs deleted file mode 100644 index 4f61c76828d..00000000000 --- a/tests/run-pass/needless_borrow_fp.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[deny(clippy::all)] -#[derive(Debug)] -pub enum Error { - Type(&'static str), -} - -fn main() {} diff --git a/tests/run-pass/needless_lifetimes_impl_trait.rs b/tests/run-pass/needless_lifetimes_impl_trait.rs deleted file mode 100644 index 676564b2445..00000000000 --- a/tests/run-pass/needless_lifetimes_impl_trait.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![deny(clippy::needless_lifetimes)] -#![allow(dead_code)] - -trait Foo {} - -struct Bar {} - -struct Baz<'a> { - bar: &'a Bar, -} - -impl<'a> Foo for Baz<'a> {} - -impl Bar { - fn baz<'a>(&'a self) -> impl Foo + 'a { - Baz { bar: self } - } -} - -fn main() {} diff --git a/tests/run-pass/procedural_macro.rs b/tests/run-pass/procedural_macro.rs deleted file mode 100644 index c7468493380..00000000000 --- a/tests/run-pass/procedural_macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[macro_use] -extern crate clippy_mini_macro_test; - -#[deny(warnings)] -fn main() { - let x = Foo; - println!("{:?}", x); -} - -#[derive(ClippyMiniMacroTest, Debug)] -struct Foo; diff --git a/tests/run-pass/regressions.rs b/tests/run-pass/regressions.rs deleted file mode 100644 index 84470addd4a..00000000000 --- a/tests/run-pass/regressions.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![allow(clippy::blacklisted_name)] - -pub fn foo(bar: *const u8) { - println!("{:#p}", bar); -} - -fn main() {} diff --git a/tests/run-pass/returns.rs b/tests/run-pass/returns.rs deleted file mode 100644 index d6b2a4ef170..00000000000 --- a/tests/run-pass/returns.rs +++ /dev/null @@ -1,21 +0,0 @@ -#[deny(warnings)] -fn cfg_return() -> i32 { - #[cfg(unix)] - return 1; - #[cfg(not(unix))] - return 2; -} - -#[deny(warnings)] -fn cfg_let_and_return() -> i32 { - #[cfg(unix)] - let x = 1; - #[cfg(not(unix))] - let x = 2; - x -} - -fn main() { - cfg_return(); - cfg_let_and_return(); -} diff --git a/tests/run-pass/single-match-else.rs b/tests/run-pass/single-match-else.rs deleted file mode 100644 index efcc6363eb0..00000000000 --- a/tests/run-pass/single-match-else.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![warn(clippy::single_match_else)] - -fn main() { - let n = match (42, 43) { - (42, n) => n, - _ => panic!("typeck error"), - }; - assert_eq!(n, 43); -} diff --git a/tests/run-pass/used_underscore_binding_macro.rs b/tests/run-pass/used_underscore_binding_macro.rs deleted file mode 100644 index 3030786aea6..00000000000 --- a/tests/run-pass/used_underscore_binding_macro.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![allow(clippy::useless_attribute)] //issue #2910 - -#[macro_use] -extern crate serde_derive; - -/// Test that we do not lint for unused underscores in a `MacroAttribute` -/// expansion -#[deny(clippy::used_underscore_binding)] -#[derive(Deserialize)] -struct MacroAttributesTest { - _foo: u32, -} - -#[test] -fn macro_attributes_test() { - let _ = MacroAttributesTest { _foo: 0 }; -} - -fn main() {} diff --git a/tests/run-pass/whitelist/clippy.toml b/tests/run-pass/whitelist/clippy.toml deleted file mode 100644 index 9f87de20baf..00000000000 --- a/tests/run-pass/whitelist/clippy.toml +++ /dev/null @@ -1,3 +0,0 @@ -# this is ignored by Clippy, but allowed for other tools like clippy-service -[third-party] -clippy-feature = "nightly" diff --git a/tests/run-pass/whitelist/conf_whitelisted.rs b/tests/run-pass/whitelist/conf_whitelisted.rs deleted file mode 100644 index f328e4d9d04..00000000000 --- a/tests/run-pass/whitelist/conf_whitelisted.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/tests/ui/crashes/associated-constant-ice.rs b/tests/ui/crashes/associated-constant-ice.rs new file mode 100644 index 00000000000..948deba3ea6 --- /dev/null +++ b/tests/ui/crashes/associated-constant-ice.rs @@ -0,0 +1,13 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/1698 + +pub trait Trait { + const CONSTANT: u8; +} + +impl Trait for u8 { + const CONSTANT: u8 = 2; +} + +fn main() { + println!("{}", u8::CONSTANT * 10); +} diff --git a/tests/ui/crashes/cc_seme.rs b/tests/ui/crashes/cc_seme.rs new file mode 100644 index 00000000000..98588be9cf8 --- /dev/null +++ b/tests/ui/crashes/cc_seme.rs @@ -0,0 +1,27 @@ +#[allow(dead_code)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/478 + +enum Baz { + One, + Two, +} + +struct Test { + t: Option, + b: Baz, +} + +fn main() {} + +pub fn foo() { + use Baz::*; + let x = Test { t: Some(0), b: One }; + + match x { + Test { t: Some(_), b: One } => unreachable!(), + Test { t: Some(42), b: Two } => unreachable!(), + Test { t: None, .. } => unreachable!(), + Test { .. } => unreachable!(), + } +} diff --git a/tests/ui/crashes/enum-glob-import-crate.rs b/tests/ui/crashes/enum-glob-import-crate.rs new file mode 100644 index 00000000000..dca32aa3b56 --- /dev/null +++ b/tests/ui/crashes/enum-glob-import-crate.rs @@ -0,0 +1,6 @@ +#![deny(clippy::all)] +#![allow(unused_imports)] + +use std::*; + +fn main() {} diff --git a/tests/ui/crashes/ice-1588.rs b/tests/ui/crashes/ice-1588.rs new file mode 100644 index 00000000000..b0a3d11bce4 --- /dev/null +++ b/tests/ui/crashes/ice-1588.rs @@ -0,0 +1,13 @@ +#![allow(clippy::all)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/1588 + +fn main() { + match 1 { + 1 => {}, + 2 => { + [0; 1]; + }, + _ => {}, + } +} diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs new file mode 100644 index 00000000000..81af88962a6 --- /dev/null +++ b/tests/ui/crashes/ice-1782.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, unused_variables)] + +/// Should not trigger an ICE in `SpanlessEq` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang/rust-clippy/issues/1782 +use std::{mem, ptr}; + +fn spanless_eq_ice() { + let txt = "something"; + match txt { + "something" => unsafe { + ptr::write( + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ) + }, + _ => unsafe { + ptr::write( + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([13, 246, 24, 255]), + ) + }, + } +} + +fn main() {} diff --git a/tests/ui/crashes/ice-1969.rs b/tests/ui/crashes/ice-1969.rs new file mode 100644 index 00000000000..96a8fe6c24d --- /dev/null +++ b/tests/ui/crashes/ice-1969.rs @@ -0,0 +1,13 @@ +#![allow(clippy::all)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/1969 + +fn main() {} + +pub trait Convert { + type Action: From<*const f64>; + + fn convert(val: *const f64) -> Self::Action { + val.into() + } +} diff --git a/tests/ui/crashes/ice-2499.rs b/tests/ui/crashes/ice-2499.rs new file mode 100644 index 00000000000..45b3b1869dd --- /dev/null +++ b/tests/ui/crashes/ice-2499.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] + +/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2499 + +fn f(s: &[u8]) -> bool { + let t = s[0] as char; + + match t { + 'E' | 'W' => {}, + 'T' => { + if s[0..4] != ['0' as u8; 4] { + return false; + } else { + return true; + } + }, + _ => { + return false; + }, + } + true +} + +fn main() {} diff --git a/tests/ui/crashes/ice-2594.rs b/tests/ui/crashes/ice-2594.rs new file mode 100644 index 00000000000..3f3986b6fc6 --- /dev/null +++ b/tests/ui/crashes/ice-2594.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, unused_variables)] + +/// Should not trigger an ICE in `SpanlessHash` / `consts::constant` +/// +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2594 + +fn spanless_hash_ice() { + let txt = "something"; + let empty_header: [u8; 1] = [1; 1]; + + match txt { + "something" => { + let mut headers = [empty_header; 1]; + }, + "" => (), + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/crashes/ice-2727.rs b/tests/ui/crashes/ice-2727.rs new file mode 100644 index 00000000000..56024abc8f5 --- /dev/null +++ b/tests/ui/crashes/ice-2727.rs @@ -0,0 +1,7 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/2727 + +pub fn f(new: fn()) { + new(); +} + +fn main() {} diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs new file mode 100644 index 00000000000..fddf8252329 --- /dev/null +++ b/tests/ui/crashes/ice-2760.rs @@ -0,0 +1,24 @@ +#![allow( + unused_variables, + clippy::blacklisted_name, + clippy::needless_pass_by_value, + dead_code +)] + +/// This should not compile-fail with: +/// +/// error[E0277]: the trait bound `T: Foo` is not satisfied +/// +/// See https://github.com/rust-lang/rust-clippy/issues/2760 + +trait Foo { + type Bar; +} + +struct Baz { + bar: T::Bar, +} + +fn take(baz: Baz) {} + +fn main() {} diff --git a/tests/ui/crashes/ice-2774.rs b/tests/ui/crashes/ice-2774.rs new file mode 100644 index 00000000000..fdc671a84e0 --- /dev/null +++ b/tests/ui/crashes/ice-2774.rs @@ -0,0 +1,27 @@ +use std::collections::HashSet; + +/// See https://github.com/rust-lang/rust-clippy/issues/2774 + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Bar { + foo: Foo, +} + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Foo {} + +#[allow(clippy::implicit_hasher)] +// This should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { + let mut foos = HashSet::new(); + foos.extend(bars.iter().map(|b| &b.foo)); +} + +#[allow(clippy::implicit_hasher)] +// Also this should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { + let mut foos = HashSet::new(); + foos.extend(bars.iter().map(|b| &b.foo)); +} + +fn main() {} diff --git a/tests/ui/crashes/ice-2865.rs b/tests/ui/crashes/ice-2865.rs new file mode 100644 index 00000000000..6b1ceb50569 --- /dev/null +++ b/tests/ui/crashes/ice-2865.rs @@ -0,0 +1,16 @@ +#[allow(dead_code)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/2865 + +struct Ice { + size: String, +} + +impl<'a> From for Ice { + fn from(_: String) -> Self { + let text = || "iceberg".to_string(); + Self { size: text() } + } +} + +fn main() {} diff --git a/tests/ui/crashes/ice-3151.rs b/tests/ui/crashes/ice-3151.rs new file mode 100644 index 00000000000..fef4d7db84d --- /dev/null +++ b/tests/ui/crashes/ice-3151.rs @@ -0,0 +1,15 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/2865 + +#[derive(Clone)] +pub struct HashMap { + hash_builder: S, + table: RawTable, +} + +#[derive(Clone)] +pub struct RawTable { + size: usize, + val: V, +} + +fn main() {} diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs new file mode 100644 index 00000000000..7d62e315da2 --- /dev/null +++ b/tests/ui/crashes/ice-3462.rs @@ -0,0 +1,23 @@ +#![warn(clippy::all)] +#![allow(clippy::blacklisted_name)] +#![allow(unused)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/3462 + +enum Foo { + Bar, + Baz, +} + +fn bar(foo: Foo) { + macro_rules! baz { + () => { + if let Foo::Bar = foo {} + }; + } + + baz!(); + baz!(); +} + +fn main() {} diff --git a/tests/ui/crashes/ice-700.rs b/tests/ui/crashes/ice-700.rs new file mode 100644 index 00000000000..0cbceedbd6b --- /dev/null +++ b/tests/ui/crashes/ice-700.rs @@ -0,0 +1,9 @@ +#![deny(clippy::all)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/700 + +fn core() {} + +fn main() { + core(); +} diff --git a/tests/ui/crashes/ice_exacte_size.rs b/tests/ui/crashes/ice_exacte_size.rs new file mode 100644 index 00000000000..30e4b11ec0b --- /dev/null +++ b/tests/ui/crashes/ice_exacte_size.rs @@ -0,0 +1,19 @@ +#![deny(clippy::all)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/1336 + +#[allow(dead_code)] +struct Foo; + +impl Iterator for Foo { + type Item = (); + + fn next(&mut self) -> Option<()> { + let _ = self.len() == 0; + unimplemented!() + } +} + +impl ExactSizeIterator for Foo {} + +fn main() {} diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs new file mode 100644 index 00000000000..7b3b881316d --- /dev/null +++ b/tests/ui/crashes/if_same_then_else.rs @@ -0,0 +1,15 @@ +#![deny(clippy::if_same_then_else)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/2426 + +fn main() {} + +pub fn foo(a: i32, b: i32) -> Option<&'static str> { + if a == b { + None + } else if a > b { + Some("a pfeil b") + } else { + None + } +} diff --git a/tests/ui/crashes/issue-2862.rs b/tests/ui/crashes/issue-2862.rs new file mode 100644 index 00000000000..38e2341e278 --- /dev/null +++ b/tests/ui/crashes/issue-2862.rs @@ -0,0 +1,16 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/2826 + +pub trait FooMap { + fn map B>(&self, f: F) -> B; +} + +impl FooMap for bool { + fn map B>(&self, f: F) -> B { + f() + } +} + +fn main() { + let a = true; + a.map(|| false); +} diff --git a/tests/ui/crashes/issue-825.rs b/tests/ui/crashes/issue-825.rs new file mode 100644 index 00000000000..05696e3d7d5 --- /dev/null +++ b/tests/ui/crashes/issue-825.rs @@ -0,0 +1,25 @@ +#![allow(warnings)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/825 + +// this should compile in a reasonable amount of time +fn rust_type_id(name: &str) { + if "bool" == &name[..] + || "uint" == &name[..] + || "u8" == &name[..] + || "u16" == &name[..] + || "u32" == &name[..] + || "f32" == &name[..] + || "f64" == &name[..] + || "i8" == &name[..] + || "i16" == &name[..] + || "i32" == &name[..] + || "i64" == &name[..] + || "Self" == &name[..] + || "str" == &name[..] + { + unreachable!(); + } +} + +fn main() {} diff --git a/tests/ui/crashes/issues_loop_mut_cond.rs b/tests/ui/crashes/issues_loop_mut_cond.rs new file mode 100644 index 00000000000..bb238c81ebc --- /dev/null +++ b/tests/ui/crashes/issues_loop_mut_cond.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] + +/// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 +pub fn loop_on_block_condition(u: &mut isize) { + while { *u < 0 } { + *u += 1; + } +} + +/// https://github.com/rust-lang/rust-clippy/issues/2584 +fn loop_with_unsafe_condition(ptr: *const u8) { + let mut len = 0; + while unsafe { *ptr.offset(len) } != 0 { + len += 1; + } +} + +/// https://github.com/rust-lang/rust-clippy/issues/2710 +static mut RUNNING: bool = true; +fn loop_on_static_condition() { + unsafe { + while RUNNING { + RUNNING = false; + } + } +} + +fn main() {} diff --git a/tests/ui/crashes/match_same_arms_const.rs b/tests/ui/crashes/match_same_arms_const.rs new file mode 100644 index 00000000000..94c939665e6 --- /dev/null +++ b/tests/ui/crashes/match_same_arms_const.rs @@ -0,0 +1,18 @@ +#![deny(clippy::match_same_arms)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/2427 + +const PRICE_OF_SWEETS: u32 = 5; +const PRICE_OF_KINDNESS: u32 = 0; +const PRICE_OF_DRINKS: u32 = 5; + +pub fn price(thing: &str) -> u32 { + match thing { + "rolo" => PRICE_OF_SWEETS, + "advice" => PRICE_OF_KINDNESS, + "juice" => PRICE_OF_DRINKS, + _ => panic!(), + } +} + +fn main() {} diff --git a/tests/ui/crashes/mut_mut_macro.rs b/tests/ui/crashes/mut_mut_macro.rs new file mode 100644 index 00000000000..6ce3b37a855 --- /dev/null +++ b/tests/ui/crashes/mut_mut_macro.rs @@ -0,0 +1,34 @@ +#![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] +#![allow(dead_code)] + +// FIXME: compiletest + extern crates doesn't work together. To make this test work, it would need +// the following three lines and the lazy_static crate. +// +// #[macro_use] +// extern crate lazy_static; +// use std::collections::HashMap; + +/// ensure that we don't suggest `is_nan` and `is_null` inside constants +/// FIXME: once const fn is stable, suggest these functions again in constants + +const BAA: *const i32 = 0 as *const i32; +static mut BAR: *const i32 = BAA; +static mut FOO: *const i32 = 0 as *const i32; +static mut BUH: bool = 42.0 < std::f32::NAN; + +#[allow(unused_variables, unused_mut)] +fn main() { + /* + lazy_static! { + static ref MUT_MAP : HashMap = { + let mut m = HashMap::new(); + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert_eq!(*MUT_COUNT, 1); + */ + // FIXME: don't lint in array length, requires `check_body` + //let _ = [""; (42.0 < std::f32::NAN) as usize]; +} diff --git a/tests/ui/crashes/needless_borrow_fp.rs b/tests/ui/crashes/needless_borrow_fp.rs new file mode 100644 index 00000000000..4f61c76828d --- /dev/null +++ b/tests/ui/crashes/needless_borrow_fp.rs @@ -0,0 +1,7 @@ +#[deny(clippy::all)] +#[derive(Debug)] +pub enum Error { + Type(&'static str), +} + +fn main() {} diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/tests/ui/crashes/needless_lifetimes_impl_trait.rs new file mode 100644 index 00000000000..676564b2445 --- /dev/null +++ b/tests/ui/crashes/needless_lifetimes_impl_trait.rs @@ -0,0 +1,20 @@ +#![deny(clippy::needless_lifetimes)] +#![allow(dead_code)] + +trait Foo {} + +struct Bar {} + +struct Baz<'a> { + bar: &'a Bar, +} + +impl<'a> Foo for Baz<'a> {} + +impl Bar { + fn baz<'a>(&'a self) -> impl Foo + 'a { + Baz { bar: self } + } +} + +fn main() {} diff --git a/tests/ui/crashes/procedural_macro.rs b/tests/ui/crashes/procedural_macro.rs new file mode 100644 index 00000000000..c7468493380 --- /dev/null +++ b/tests/ui/crashes/procedural_macro.rs @@ -0,0 +1,11 @@ +#[macro_use] +extern crate clippy_mini_macro_test; + +#[deny(warnings)] +fn main() { + let x = Foo; + println!("{:?}", x); +} + +#[derive(ClippyMiniMacroTest, Debug)] +struct Foo; diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs new file mode 100644 index 00000000000..84470addd4a --- /dev/null +++ b/tests/ui/crashes/regressions.rs @@ -0,0 +1,7 @@ +#![allow(clippy::blacklisted_name)] + +pub fn foo(bar: *const u8) { + println!("{:#p}", bar); +} + +fn main() {} diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs new file mode 100644 index 00000000000..8021ed4607d --- /dev/null +++ b/tests/ui/crashes/returns.rs @@ -0,0 +1,23 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/1346 + +#[deny(warnings)] +fn cfg_return() -> i32 { + #[cfg(unix)] + return 1; + #[cfg(not(unix))] + return 2; +} + +#[deny(warnings)] +fn cfg_let_and_return() -> i32 { + #[cfg(unix)] + let x = 1; + #[cfg(not(unix))] + let x = 2; + x +} + +fn main() { + cfg_return(); + cfg_let_and_return(); +} diff --git a/tests/ui/crashes/single-match-else.rs b/tests/ui/crashes/single-match-else.rs new file mode 100644 index 00000000000..1ba7ac08213 --- /dev/null +++ b/tests/ui/crashes/single-match-else.rs @@ -0,0 +1,11 @@ +#![warn(clippy::single_match_else)] + +//! Test for https://github.com/rust-lang/rust-clippy/issues/1588 + +fn main() { + let n = match (42, 43) { + (42, n) => n, + _ => panic!("typeck error"), + }; + assert_eq!(n, 43); +} diff --git a/tests/ui/crashes/used_underscore_binding_macro.rs b/tests/ui/crashes/used_underscore_binding_macro.rs new file mode 100644 index 00000000000..3030786aea6 --- /dev/null +++ b/tests/ui/crashes/used_underscore_binding_macro.rs @@ -0,0 +1,19 @@ +#![allow(clippy::useless_attribute)] //issue #2910 + +#[macro_use] +extern crate serde_derive; + +/// Test that we do not lint for unused underscores in a `MacroAttribute` +/// expansion +#[deny(clippy::used_underscore_binding)] +#[derive(Deserialize)] +struct MacroAttributesTest { + _foo: u32, +} + +#[test] +fn macro_attributes_test() { + let _ = MacroAttributesTest { _foo: 0 }; +} + +fn main() {} diff --git a/tests/ui/crashes/whitelist/clippy.toml b/tests/ui/crashes/whitelist/clippy.toml new file mode 100644 index 00000000000..9f87de20baf --- /dev/null +++ b/tests/ui/crashes/whitelist/clippy.toml @@ -0,0 +1,3 @@ +# this is ignored by Clippy, but allowed for other tools like clippy-service +[third-party] +clippy-feature = "nightly" diff --git a/tests/ui/crashes/whitelist/conf_whitelisted.rs b/tests/ui/crashes/whitelist/conf_whitelisted.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/ui/crashes/whitelist/conf_whitelisted.rs @@ -0,0 +1 @@ +fn main() {} -- cgit 1.4.1-3-g733a5 From f3cd81980db4fc74df110ec540da8e5c0c363872 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 6 Feb 2019 08:09:56 +0100 Subject: Fix ICE in needless_pass_by_value lint If I understand it correctly, we were first creating a type with a `RegionKind::ReErased` region and then deleted it again in `util::implements_trait` with: cx.tcx.erase_regions(&ty); causing the type query to fail. It looks like using `ReEmpty` works around that deletion. --- clippy_lints/src/needless_pass_by_value.rs | 2 +- tests/ui/needless_pass_by_value.rs | 13 +++++++- tests/ui/needless_pass_by_value.stderr | 52 +++++++++++++++--------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 77a6aeba53b..c7af5fa79f3 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .skip(1) .cloned() .collect::>(); - implements_trait(cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), ty_params) + implements_trait(cx, cx.tcx.mk_imm_ref(&RegionKind::ReEmpty, ty), t.def_id(), ty_params) }), ) }; diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 427bce988bd..0d093adf8cd 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -8,6 +8,7 @@ )] use std::borrow::Borrow; +use std::collections::HashSet; use std::convert::AsRef; // `v` should be warned @@ -145,4 +146,14 @@ trait Club<'a, A> {} impl Club<'static, T> for T {} fn more_fun(_item: impl Club<'static, i32>) {} -fn main() {} +fn is_sync(_: T) +where + T: Sync, +{ +} + +fn main() { + // This should not cause an ICE either + // https://github.com/rust-lang/rust-clippy/issues/3144 + is_sync(HashSet::::new()); +} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 31f43bf16ba..ad0e6461c22 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,5 +1,5 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:15:23 + --> $DIR/needless_pass_by_value.rs:16:23 | LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` @@ -7,25 +7,25 @@ LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec $DIR/needless_pass_by_value.rs:29:11 + --> $DIR/needless_pass_by_value.rs:30:11 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:29:22 + --> $DIR/needless_pass_by_value.rs:30:22 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:35:71 + --> $DIR/needless_pass_by_value.rs:36:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:47:18 + --> $DIR/needless_pass_by_value.rs:48:18 | LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -36,13 +36,13 @@ LL | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:60:24 + --> $DIR/needless_pass_by_value.rs:61:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:60:36 + --> $DIR/needless_pass_by_value.rs:61:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ @@ -55,19 +55,19 @@ LL | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:76:49 + --> $DIR/needless_pass_by_value.rs:77:49 | LL | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:78:18 + --> $DIR/needless_pass_by_value.rs:79:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:78:29 + --> $DIR/needless_pass_by_value.rs:79:29 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ @@ -81,13 +81,13 @@ LL | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:78:40 + --> $DIR/needless_pass_by_value.rs:79:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:78:53 + --> $DIR/needless_pass_by_value.rs:79:53 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ @@ -101,61 +101,61 @@ LL | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:91:12 + --> $DIR/needless_pass_by_value.rs:92:12 | LL | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:92:12 + --> $DIR/needless_pass_by_value.rs:93:12 | LL | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:23 + --> $DIR/needless_pass_by_value.rs:102:23 | LL | fn baz(&self, _u: U, _s: Self) {} | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:30 + --> $DIR/needless_pass_by_value.rs:102:30 | LL | fn baz(&self, _u: U, _s: Self) {} | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:123:24 + --> $DIR/needless_pass_by_value.rs:124:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:121:1 + --> $DIR/needless_pass_by_value.rs:122:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:129:29 + --> $DIR/needless_pass_by_value.rs:130:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:121:1 + --> $DIR/needless_pass_by_value.rs:122:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:129:45 + --> $DIR/needless_pass_by_value.rs:130:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:121:1 + --> $DIR/needless_pass_by_value.rs:122:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let CopyWrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:129:61 + --> $DIR/needless_pass_by_value.rs:130:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ | help: consider marking this type as Copy - --> $DIR/needless_pass_by_value.rs:121:1 + --> $DIR/needless_pass_by_value.rs:122:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,13 +185,13 @@ LL | let CopyWrapper(s) = *z; // moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:141:40 + --> $DIR/needless_pass_by_value.rs:142:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:146:20 + --> $DIR/needless_pass_by_value.rs:147:20 | LL | fn more_fun(_item: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` -- cgit 1.4.1-3-g733a5 From f934f98111591c3d43aa4698648671fed312ccc1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 8 Feb 2019 08:05:52 +0100 Subject: Add a uitest subcommand to simplify UI test invocation This allows to run `TESTNAME=xxx cargo uitest` instead of `TESTNAME=xxx cargo test --test-compile-test` --- .cargo/config | 2 ++ CONTRIBUTING.md | 4 ++-- clippy_lints/src/utils/author.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000000..7cb41d979a6 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[alias] +uitest = "test --test compile-test" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5619ee00f8d..7ae8f3936a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -101,7 +101,7 @@ fn main() { } ``` -Now you run `TESTNAME=ui/my_lint cargo test --test compile-test` to produce +Now you run `TESTNAME=ui/my_lint cargo uitest` to produce a `.stdout` file with the generated code: ```rust @@ -151,7 +151,7 @@ Use `cargo test` to run the whole testsuite. If you don't want to wait for all tests to finish, you can also execute a single test file by using `TESTNAME` to specify the test to run: ```bash -TESTNAME=ui/empty_line_after_outer_attr cargo test --test compile-test +TESTNAME=ui/empty_line_after_outer_attr cargo uitest ``` Clippy uses UI tests. UI tests check that the output of the compiler is exactly as expected. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 264a5463225..4e2d4de8518 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -25,7 +25,7 @@ use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID}; /// } /// ``` /// -/// Running `TESTNAME=ui/my_lint cargo test --test compile-test` will produce +/// Running `TESTNAME=ui/my_lint cargo uitest` will produce /// a `./tests/ui/new_lint.stdout` file with the generated code: /// /// ```rust -- cgit 1.4.1-3-g733a5 From 66f8fa320b9776c2008dcc9b3e6999c3074bea46 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 11:42:13 +0900 Subject: Add new Def type ConstParam --- clippy_lints/src/utils/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index f4b1a2450bf..40daa2d0b00 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -997,6 +997,7 @@ pub fn opt_def_id(def: Def) -> Option { | Def::TyAlias(id) | Def::AssociatedTy(id) | Def::TyParam(id) + | Def::ConstParam(id) | Def::ForeignTy(id) | Def::Struct(id) | Def::StructCtor(id, ..) -- cgit 1.4.1-3-g733a5 From 71dfbe2072193d2d2db81a54758623b8ba8eaeb7 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 13:28:21 +0900 Subject: Use Hir::Def opt_def_id --- clippy_lints/src/utils/mod.rs | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 40daa2d0b00..a8b6a756b78 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -987,40 +987,7 @@ pub fn remove_blocks(expr: &Expr) -> &Expr { } pub fn opt_def_id(def: Def) -> Option { - match def { - Def::Fn(id) - | Def::Mod(id) - | Def::Static(id, _) - | Def::Variant(id) - | Def::VariantCtor(id, ..) - | Def::Enum(id) - | Def::TyAlias(id) - | Def::AssociatedTy(id) - | Def::TyParam(id) - | Def::ConstParam(id) - | Def::ForeignTy(id) - | Def::Struct(id) - | Def::StructCtor(id, ..) - | Def::Union(id) - | Def::Trait(id) - | Def::TraitAlias(id) - | Def::Method(id) - | Def::Const(id) - | Def::AssociatedConst(id) - | Def::Macro(id, ..) - | Def::Existential(id) - | Def::AssociatedExistential(id) - | Def::SelfCtor(id) => Some(id), - - Def::Upvar(..) - | Def::Local(_) - | Def::Label(..) - | Def::PrimTy(..) - | Def::SelfTy(..) - | Def::ToolMod - | Def::NonMacroAttr { .. } - | Def::Err => None, - } + def.opt_def_id() } pub fn is_self(slf: &Arg) -> bool { -- cgit 1.4.1-3-g733a5 From 9dbabffe601cbfcc74b6f309a26fd514784f0392 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 10 Feb 2019 09:44:49 +0100 Subject: UI test cleanup: Extract similar_names tests --- tests/ui/non_expressive_names.rs | 103 +--------------------------- tests/ui/non_expressive_names.stderr | 127 +++-------------------------------- tests/ui/similar_names.rs | 103 ++++++++++++++++++++++++++++ tests/ui/similar_names.stderr | 107 +++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 217 deletions(-) create mode 100644 tests/ui/similar_names.rs create mode 100644 tests/ui/similar_names.stderr diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index b1d7d8e52a8..cd158287ff7 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -1,87 +1,6 @@ -#![warn(clippy::all, clippy::similar_names)] +#![warn(clippy::all)] #![allow(unused, clippy::println_empty_string)] -struct Foo { - apple: i32, - bpple: i32, -} - -fn main() { - let specter: i32; - let spectre: i32; - - let apple: i32; - - let bpple: i32; - - let cpple: i32; - - let a_bar: i32; - let b_bar: i32; - let c_bar: i32; - - let items = [5]; - for item in &items { - loop {} - } - - let foo_x: i32; - let foo_y: i32; - - let rhs: i32; - let lhs: i32; - - let bla_rhs: i32; - let bla_lhs: i32; - - let blubrhs: i32; - let blublhs: i32; - - let blubx: i32; - let bluby: i32; - - let cake: i32; - let cakes: i32; - let coke: i32; - - match 5 { - cheese @ 1 => {}, - rabbit => panic!(), - } - let cheese: i32; - match (42, 43) { - (cheese1, 1) => {}, - (cheese2, 2) => panic!(), - _ => println!(""), - } - let ipv4: i32; - let ipv6: i32; - let abcd1: i32; - let abdc2: i32; - let xyz1abc: i32; - let xyz2abc: i32; - let xyzeabc: i32; - - let parser: i32; - let parsed: i32; - let parsee: i32; - - let setter: i32; - let getter: i32; - let tx1: i32; - let rx1: i32; - let tx_cake: i32; - let rx_cake: i32; -} - -fn foo() { - let Foo { apple, bpple } = unimplemented!(); - let Foo { - apple: spring, - bpple: sprang, - } = unimplemented!(); -} - #[derive(Clone, Debug)] enum MaybeInst { Split, @@ -160,22 +79,4 @@ impl Bar { } } -// false positive similar_names (#3057, #2651) -// clippy claimed total_reg_src_size and total_size and -// numb_reg_src_checkouts and total_bin_size were similar -#[derive(Debug, Clone)] -pub(crate) struct DirSizes { - pub(crate) total_size: u64, - pub(crate) numb_bins: u64, - pub(crate) total_bin_size: u64, - pub(crate) total_reg_size: u64, - pub(crate) total_git_db_size: u64, - pub(crate) total_git_repos_bare_size: u64, - pub(crate) numb_git_repos_bare_repos: u64, - pub(crate) numb_git_checkouts: u64, - pub(crate) total_git_chk_size: u64, - pub(crate) total_reg_cache_size: u64, - pub(crate) total_reg_src_size: u64, - pub(crate) numb_reg_cache_entries: u64, - pub(crate) numb_reg_src_checkouts: u64, -} +fn main() {} diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index f4274b87cdc..a81ecdfe4de 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,110 +1,5 @@ -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:15:9 - | -LL | let bpple: i32; - | ^^^^^ - | - = note: `-D clippy::similar-names` implied by `-D warnings` -note: existing binding defined here - --> $DIR/non_expressive_names.rs:13:9 - | -LL | let apple: i32; - | ^^^^^ -help: separate the discriminating character by an underscore like: `b_pple` - --> $DIR/non_expressive_names.rs:15:9 - | -LL | let bpple: i32; - | ^^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:17:9 - | -LL | let cpple: i32; - | ^^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:13:9 - | -LL | let apple: i32; - | ^^^^^ -help: separate the discriminating character by an underscore like: `c_pple` - --> $DIR/non_expressive_names.rs:17:9 - | -LL | let cpple: i32; - | ^^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:41:9 - | -LL | let bluby: i32; - | ^^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:40:9 - | -LL | let blubx: i32; - | ^^^^^ -help: separate the discriminating character by an underscore like: `blub_y` - --> $DIR/non_expressive_names.rs:41:9 - | -LL | let bluby: i32; - | ^^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:45:9 - | -LL | let coke: i32; - | ^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:43:9 - | -LL | let cake: i32; - | ^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:63:9 - | -LL | let xyzeabc: i32; - | ^^^^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:61:9 - | -LL | let xyz1abc: i32; - | ^^^^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:67:9 - | -LL | let parsee: i32; - | ^^^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:65:9 - | -LL | let parser: i32; - | ^^^^^^ -help: separate the discriminating character by an underscore like: `parse_e` - --> $DIR/non_expressive_names.rs:67:9 - | -LL | let parsee: i32; - | ^^^^^^ - -error: binding's name is too similar to existing binding - --> $DIR/non_expressive_names.rs:81:16 - | -LL | bpple: sprang, - | ^^^^^^ - | -note: existing binding defined here - --> $DIR/non_expressive_names.rs:80:16 - | -LL | apple: spring, - | ^^^^^^ - error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:116:17 + --> $DIR/non_expressive_names.rs:35:17 | LL | let e: i32; | ^ @@ -112,25 +7,25 @@ LL | let e: i32; = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:119:17 + --> $DIR/non_expressive_names.rs:38:17 | LL | let e: i32; | ^ error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:120:17 + --> $DIR/non_expressive_names.rs:39:17 | LL | let f: i32; | ^ error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:124:13 + --> $DIR/non_expressive_names.rs:43:13 | LL | e => panic!(), | ^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:134:9 + --> $DIR/non_expressive_names.rs:53:9 | LL | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ @@ -138,34 +33,34 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:135:9 + --> $DIR/non_expressive_names.rs:54:9 | LL | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:136:9 + --> $DIR/non_expressive_names.rs:55:9 | LL | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:156:13 + --> $DIR/non_expressive_names.rs:75:13 | LL | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:157:13 + --> $DIR/non_expressive_names.rs:76:13 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:158:13 + --> $DIR/non_expressive_names.rs:77:13 | LL | let __1___2 = 12; | ^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/similar_names.rs b/tests/ui/similar_names.rs new file mode 100644 index 00000000000..6796b15289e --- /dev/null +++ b/tests/ui/similar_names.rs @@ -0,0 +1,103 @@ +#![warn(clippy::similar_names)] +#![allow(unused, clippy::println_empty_string)] + +struct Foo { + apple: i32, + bpple: i32, +} + +fn main() { + let specter: i32; + let spectre: i32; + + let apple: i32; + + let bpple: i32; + + let cpple: i32; + + let a_bar: i32; + let b_bar: i32; + let c_bar: i32; + + let items = [5]; + for item in &items { + loop {} + } + + let foo_x: i32; + let foo_y: i32; + + let rhs: i32; + let lhs: i32; + + let bla_rhs: i32; + let bla_lhs: i32; + + let blubrhs: i32; + let blublhs: i32; + + let blubx: i32; + let bluby: i32; + + let cake: i32; + let cakes: i32; + let coke: i32; + + match 5 { + cheese @ 1 => {}, + rabbit => panic!(), + } + let cheese: i32; + match (42, 43) { + (cheese1, 1) => {}, + (cheese2, 2) => panic!(), + _ => println!(""), + } + let ipv4: i32; + let ipv6: i32; + let abcd1: i32; + let abdc2: i32; + let xyz1abc: i32; + let xyz2abc: i32; + let xyzeabc: i32; + + let parser: i32; + let parsed: i32; + let parsee: i32; + + let setter: i32; + let getter: i32; + let tx1: i32; + let rx1: i32; + let tx_cake: i32; + let rx_cake: i32; +} + +fn foo() { + let Foo { apple, bpple } = unimplemented!(); + let Foo { + apple: spring, + bpple: sprang, + } = unimplemented!(); +} + +// false positive similar_names (#3057, #2651) +// clippy claimed total_reg_src_size and total_size and +// numb_reg_src_checkouts and total_bin_size were similar +#[derive(Debug, Clone)] +pub(crate) struct DirSizes { + pub(crate) total_size: u64, + pub(crate) numb_bins: u64, + pub(crate) total_bin_size: u64, + pub(crate) total_reg_size: u64, + pub(crate) total_git_db_size: u64, + pub(crate) total_git_repos_bare_size: u64, + pub(crate) numb_git_repos_bare_repos: u64, + pub(crate) numb_git_checkouts: u64, + pub(crate) total_git_chk_size: u64, + pub(crate) total_reg_cache_size: u64, + pub(crate) total_reg_src_size: u64, + pub(crate) numb_reg_cache_entries: u64, + pub(crate) numb_reg_src_checkouts: u64, +} diff --git a/tests/ui/similar_names.stderr b/tests/ui/similar_names.stderr new file mode 100644 index 00000000000..0256f126a94 --- /dev/null +++ b/tests/ui/similar_names.stderr @@ -0,0 +1,107 @@ +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:15:9 + | +LL | let bpple: i32; + | ^^^^^ + | + = note: `-D clippy::similar-names` implied by `-D warnings` +note: existing binding defined here + --> $DIR/similar_names.rs:13:9 + | +LL | let apple: i32; + | ^^^^^ +help: separate the discriminating character by an underscore like: `b_pple` + --> $DIR/similar_names.rs:15:9 + | +LL | let bpple: i32; + | ^^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:17:9 + | +LL | let cpple: i32; + | ^^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:13:9 + | +LL | let apple: i32; + | ^^^^^ +help: separate the discriminating character by an underscore like: `c_pple` + --> $DIR/similar_names.rs:17:9 + | +LL | let cpple: i32; + | ^^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:41:9 + | +LL | let bluby: i32; + | ^^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:40:9 + | +LL | let blubx: i32; + | ^^^^^ +help: separate the discriminating character by an underscore like: `blub_y` + --> $DIR/similar_names.rs:41:9 + | +LL | let bluby: i32; + | ^^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:45:9 + | +LL | let coke: i32; + | ^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:43:9 + | +LL | let cake: i32; + | ^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:63:9 + | +LL | let xyzeabc: i32; + | ^^^^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:61:9 + | +LL | let xyz1abc: i32; + | ^^^^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:67:9 + | +LL | let parsee: i32; + | ^^^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:65:9 + | +LL | let parser: i32; + | ^^^^^^ +help: separate the discriminating character by an underscore like: `parse_e` + --> $DIR/similar_names.rs:67:9 + | +LL | let parsee: i32; + | ^^^^^^ + +error: binding's name is too similar to existing binding + --> $DIR/similar_names.rs:81:16 + | +LL | bpple: sprang, + | ^^^^^^ + | +note: existing binding defined here + --> $DIR/similar_names.rs:80:16 + | +LL | apple: spring, + | ^^^^^^ + +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 83a87fb7b6378eb928d0fd3e38fbab3579dc520c Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 10 Feb 2019 10:19:24 +0100 Subject: UI test cleanup: Extract match_same_arms tests --- tests/ui/copies.rs | 246 +---------------------------------- tests/ui/copies.stderr | 256 ++++--------------------------------- tests/ui/if_same_then_else.rs | 262 ++++++++++++++++++++++++++++++++++++++ tests/ui/if_same_then_else.stderr | 214 +++++++++++++++++++++++++++++++ 4 files changed, 499 insertions(+), 479 deletions(-) create mode 100644 tests/ui/if_same_then_else.rs create mode 100644 tests/ui/if_same_then_else.stderr diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index a78209bcce8..a1f15c0268b 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -5,7 +5,6 @@ clippy::eq_op, clippy::needless_continue, clippy::needless_return, - clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero, clippy::unused_unit @@ -16,64 +15,15 @@ fn foo() -> bool { unimplemented!() } -struct Foo { - bar: u8, -} - pub enum Abc { A, B, C, } -#[warn(clippy::if_same_then_else)] #[warn(clippy::match_same_arms)] #[allow(clippy::unused_unit)] -fn if_same_then_else() -> Result<&'static str, ()> { - if true { - Foo { bar: 42 }; - 0..10; - ..; - 0..; - ..10; - 0..=10; - foo(); - } else { - //~ ERROR same body as `if` block - Foo { bar: 42 }; - 0..10; - ..; - 0..; - ..10; - 0..=10; - foo(); - } - - if true { - Foo { bar: 42 }; - } else { - Foo { bar: 43 }; - } - - if true { - (); - } else { - () - } - - if true { - 0..10; - } else { - 0..=10; - } - - if true { - foo(); - foo(); - } else { - foo(); - } - +fn match_same_arms() { let _ = match 42 { 42 => { foo(); @@ -102,129 +52,6 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => 0, //~ ERROR match arms have same body }; - if true { - foo(); - } - - let _ = if true { - 42 - } else { - //~ ERROR same body as `if` block - 42 - }; - - if true { - for _ in &[42] { - let foo: &Option<_> = &Some::(42); - if true { - break; - } else { - continue; - } - } - } else { - //~ ERROR same body as `if` block - for _ in &[42] { - let foo: &Option<_> = &Some::(42); - if true { - break; - } else { - continue; - } - } - } - - if true { - let bar = if true { 42 } else { 43 }; - - while foo() { - break; - } - bar + 1; - } else { - //~ ERROR same body as `if` block - let bar = if true { 42 } else { 43 }; - - while foo() { - break; - } - bar + 1; - } - - if true { - let _ = match 42 { - 42 => 1, - a if a > 0 => 2, - 10..=15 => 3, - _ => 4, - }; - } else if false { - foo(); - } else if foo() { - let _ = match 42 { - 42 => 1, - a if a > 0 => 2, - 10..=15 => 3, - _ => 4, - }; - } - - if true { - if let Some(a) = Some(42) {} - } else { - //~ ERROR same body as `if` block - if let Some(a) = Some(42) {} - } - - if true { - if let (1, .., 3) = (1, 2, 3) {} - } else { - //~ ERROR same body as `if` block - if let (1, .., 3) = (1, 2, 3) {} - } - - if true { - if let (1, .., 3) = (1, 2, 3) {} - } else { - if let (.., 3) = (1, 2, 3) {} - } - - if true { - if let (1, .., 3) = (1, 2, 3) {} - } else { - if let (.., 4) = (1, 2, 3) {} - } - - if true { - if let (1, .., 3) = (1, 2, 3) {} - } else { - if let (.., 1, 3) = (1, 2, 3) {} - } - - if true { - if let Some(42) = None {} - } else { - if let Option::Some(42) = None {} - } - - if true { - if let Some(42) = None:: {} - } else { - if let Some(42) = None {} - } - - if true { - if let Some(42) = None:: {} - } else { - if let Some(42) = None:: {} - } - - if true { - if let Some(a) = Some(42) {} - } else { - if let Some(a) = Some(43) {} - } - let _ = match 42 { 42 => foo(), 51 => foo(), //~ ERROR match arms have same body @@ -271,33 +98,6 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => 0, }; - let _ = if true { - 0.0 - } else { - //~ ERROR same body as `if` block - 0.0 - }; - - let _ = if true { - -0.0 - } else { - //~ ERROR same body as `if` block - -0.0 - }; - - let _ = if true { 0.0 } else { -0.0 }; - - // Different NaNs - let _ = if true { 0.0 / 0.0 } else { std::f32::NAN }; - - // Same NaNs - let _ = if true { - std::f32::NAN - } else { - //~ ERROR same body as `if` block - std::f32::NAN - }; - let _ = match Some(()) { Some(()) => 0.0, None => -0.0, @@ -308,50 +108,6 @@ fn if_same_then_else() -> Result<&'static str, ()> { (None, Some(a)) => bar(a), // bindings have different types _ => (), } - - if true { - try!(Ok("foo")); - } else { - //~ ERROR same body as `if` block - try!(Ok("foo")); - } - - if true { - let foo = ""; - return Ok(&foo[0..]); - } else if false { - let foo = "bar"; - return Ok(&foo[0..]); - } else { - let foo = ""; - return Ok(&foo[0..]); - } - - // false positive if_same_then_else, let(x,y) vs let(y,x), see #3559 - if true { - let foo = ""; - let (x, y) = (1, 2); - return Ok(&foo[x..y]); - } else { - let foo = ""; - let (y, x) = (1, 2); - return Ok(&foo[x..y]); - } } fn main() {} - -// Issue #2423. This was causing an ICE -fn func() { - if true { - f(&[0; 62]); - f(&[0; 4]); - f(&[0; 3]); - } else { - f(&[0; 62]); - f(&[0; 6]); - f(&[0; 6]); - } -} - -fn f(val: &[u8]) {} diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index a0a5c3890ed..f04a7706846 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -1,32 +1,5 @@ -error: this `if` has identical blocks - --> $DIR/copies.rs:41:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | Foo { bar: 42 }; -LL | | 0..10; -... | -LL | | foo(); -LL | | } - | |_____^ - | - = note: `-D clippy::if-same-then-else` implied by `-D warnings` -note: same as this - --> $DIR/copies.rs:33:13 - | -LL | if true { - | _____________^ -LL | | Foo { bar: 42 }; -LL | | 0..10; -LL | | ..; -... | -LL | | foo(); -LL | | } else { - | |_____^ - error: this `match` has identical arm bodies - --> $DIR/copies.rs:87:14 + --> $DIR/copies.rs:37:14 | LL | _ => { | ______________^ @@ -40,7 +13,7 @@ LL | | }, | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/copies.rs:78:15 + --> $DIR/copies.rs:28:15 | LL | 42 => { | _______________^ @@ -52,7 +25,7 @@ LL | | a LL | | }, | |_________^ note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:78:15 + --> $DIR/copies.rs:28:15 | LL | 42 => { | _______________^ @@ -65,291 +38,106 @@ LL | | }, | |_________^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:102:14 + --> $DIR/copies.rs:52:14 | LL | _ => 0, //~ ERROR match arms have same body | ^ | note: same as this - --> $DIR/copies.rs:100:19 + --> $DIR/copies.rs:50:19 | LL | Abc::A => 0, | ^ note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:100:19 + --> $DIR/copies.rs:50:19 | LL | Abc::A => 0, | ^ -error: this `if` has identical blocks - --> $DIR/copies.rs:111:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | 42 -LL | | }; - | |_____^ - | -note: same as this - --> $DIR/copies.rs:109:21 - | -LL | let _ = if true { - | _____________________^ -LL | | 42 -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:125:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | for _ in &[42] { -LL | | let foo: &Option<_> = &Some::(42); -... | -LL | | } -LL | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:116:13 - | -LL | if true { - | _____________^ -LL | | for _ in &[42] { -LL | | let foo: &Option<_> = &Some::(42); -LL | | if true { -... | -LL | | } -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:144:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | let bar = if true { 42 } else { 43 }; -LL | | -... | -LL | | bar + 1; -LL | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:137:13 - | -LL | if true { - | _____________^ -LL | | let bar = if true { 42 } else { 43 }; -LL | | -LL | | while foo() { -... | -LL | | bar + 1; -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:174:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | if let Some(a) = Some(42) {} -LL | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:172:13 - | -LL | if true { - | _____________^ -LL | | if let Some(a) = Some(42) {} -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:181:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | if let (1, .., 3) = (1, 2, 3) {} -LL | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:179:13 - | -LL | if true { - | _____________^ -LL | | if let (1, .., 3) = (1, 2, 3) {} -LL | | } else { - | |_____^ - error: this `match` has identical arm bodies - --> $DIR/copies.rs:230:15 + --> $DIR/copies.rs:57:15 | LL | 51 => foo(), //~ ERROR match arms have same body | ^^^^^ | note: same as this - --> $DIR/copies.rs:229:15 + --> $DIR/copies.rs:56:15 | LL | 42 => foo(), | ^^^^^ note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:229:15 + --> $DIR/copies.rs:56:15 | LL | 42 => foo(), | ^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:236:17 + --> $DIR/copies.rs:63:17 | LL | None => 24, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:235:20 + --> $DIR/copies.rs:62:20 | LL | Some(_) => 24, | ^^ note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:235:20 + --> $DIR/copies.rs:62:20 | LL | Some(_) => 24, | ^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:258:28 + --> $DIR/copies.rs:85:28 | LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:257:28 + --> $DIR/copies.rs:84:28 | LL | (Some(a), None) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:257:28 + --> $DIR/copies.rs:84:28 | LL | (Some(a), None) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:264:26 + --> $DIR/copies.rs:91:26 | LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | ^^^^^^ | note: same as this - --> $DIR/copies.rs:263:26 + --> $DIR/copies.rs:90:26 | LL | (Some(a), ..) => bar(a), | ^^^^^^ note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:263:26 + --> $DIR/copies.rs:90:26 | LL | (Some(a), ..) => bar(a), | ^^^^^^ error: this `match` has identical arm bodies - --> $DIR/copies.rs:270:20 + --> $DIR/copies.rs:97:20 | LL | (.., 3) => 42, //~ ERROR match arms have same body | ^^ | note: same as this - --> $DIR/copies.rs:269:23 + --> $DIR/copies.rs:96:23 | LL | (1, .., 3) => 42, | ^^ note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:269:23 + --> $DIR/copies.rs:96:23 | LL | (1, .., 3) => 42, | ^^ -error: this `if` has identical blocks - --> $DIR/copies.rs:276:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | 0.0 -LL | | }; - | |_____^ - | -note: same as this - --> $DIR/copies.rs:274:21 - | -LL | let _ = if true { - | _____________________^ -LL | | 0.0 -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:283:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | -0.0 -LL | | }; - | |_____^ - | -note: same as this - --> $DIR/copies.rs:281:21 - | -LL | let _ = if true { - | _____________________^ -LL | | -0.0 -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:296:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | std::f32::NAN -LL | | }; - | |_____^ - | -note: same as this - --> $DIR/copies.rs:294:21 - | -LL | let _ = if true { - | _____________________^ -LL | | std::f32::NAN -LL | | } else { - | |_____^ - -error: this `if` has identical blocks - --> $DIR/copies.rs:314:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | try!(Ok("foo")); -LL | | } - | |_____^ - | -note: same as this - --> $DIR/copies.rs:312:13 - | -LL | if true { - | _____________^ -LL | | try!(Ok("foo")); -LL | | } else { - | |_____^ - -error: aborting due to 17 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs new file mode 100644 index 00000000000..c054e39811c --- /dev/null +++ b/tests/ui/if_same_then_else.rs @@ -0,0 +1,262 @@ +#![warn(clippy::if_same_then_else)] +#![allow( + clippy::blacklisted_name, + clippy::collapsible_if, + clippy::cyclomatic_complexity, + clippy::eq_op, + clippy::needless_return, + clippy::never_loop, + clippy::no_effect, + clippy::zero_divided_by_zero, + clippy::unused_unit, +)] + +struct Foo { + bar: u8, +} + +fn foo() -> bool { + unimplemented!() +} + +fn if_same_then_else() -> Result<&'static str, ()> { + if true { + Foo { bar: 42 }; + 0..10; + ..; + 0..; + ..10; + 0..=10; + foo(); + } else { + //~ ERROR same body as `if` block + Foo { bar: 42 }; + 0..10; + ..; + 0..; + ..10; + 0..=10; + foo(); + } + + if true { + Foo { bar: 42 }; + } else { + Foo { bar: 43 }; + } + + if true { + (); + } else { + () + } + + if true { + 0..10; + } else { + 0..=10; + } + + if true { + foo(); + foo(); + } else { + foo(); + } + + let _ = if true { + 0.0 + } else { + //~ ERROR same body as `if` block + 0.0 + }; + + let _ = if true { + -0.0 + } else { + //~ ERROR same body as `if` block + -0.0 + }; + + let _ = if true { 0.0 } else { -0.0 }; + + // Different NaNs + let _ = if true { 0.0 / 0.0 } else { std::f32::NAN }; + + if true { + foo(); + } + + let _ = if true { + 42 + } else { + //~ ERROR same body as `if` block + 42 + }; + + if true { + for _ in &[42] { + let foo: &Option<_> = &Some::(42); + if true { + break; + } else { + continue; + } + } + } else { + //~ ERROR same body as `if` block + for _ in &[42] { + let foo: &Option<_> = &Some::(42); + if true { + break; + } else { + continue; + } + } + } + + if true { + let bar = if true { 42 } else { 43 }; + + while foo() { + break; + } + bar + 1; + } else { + //~ ERROR same body as `if` block + let bar = if true { 42 } else { 43 }; + + while foo() { + break; + } + bar + 1; + } + + if true { + let _ = match 42 { + 42 => 1, + a if a > 0 => 2, + 10..=15 => 3, + _ => 4, + }; + } else if false { + foo(); + } else if foo() { + let _ = match 42 { + 42 => 1, + a if a > 0 => 2, + 10..=15 => 3, + _ => 4, + }; + } + + if true { + if let Some(a) = Some(42) {} + } else { + //~ ERROR same body as `if` block + if let Some(a) = Some(42) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } else { + //~ ERROR same body as `if` block + if let (1, .., 3) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } else { + if let (.., 3) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } else { + if let (.., 4) = (1, 2, 3) {} + } + + if true { + if let (1, .., 3) = (1, 2, 3) {} + } else { + if let (.., 1, 3) = (1, 2, 3) {} + } + + if true { + if let Some(42) = None {} + } else { + if let Option::Some(42) = None {} + } + + if true { + if let Some(42) = None:: {} + } else { + if let Some(42) = None {} + } + + if true { + if let Some(42) = None:: {} + } else { + if let Some(42) = None:: {} + } + + if true { + if let Some(a) = Some(42) {} + } else { + if let Some(a) = Some(43) {} + } + + // Same NaNs + let _ = if true { + std::f32::NAN + } else { + //~ ERROR same body as `if` block + std::f32::NAN + }; + + if true { + try!(Ok("foo")); + } else { + //~ ERROR same body as `if` block + try!(Ok("foo")); + } + + if true { + let foo = ""; + return Ok(&foo[0..]); + } else if false { + let foo = "bar"; + return Ok(&foo[0..]); + } else { + let foo = ""; + return Ok(&foo[0..]); + } + + // false positive if_same_then_else, let(x,y) vs let(y,x), see #3559 + if true { + let foo = ""; + let (x, y) = (1, 2); + return Ok(&foo[x..y]); + } else { + let foo = ""; + let (y, x) = (1, 2); + return Ok(&foo[x..y]); + } +} + +// Issue #2423. This was causing an ICE +fn func() { + if true { + f(&[0; 62]); + f(&[0; 4]); + f(&[0; 3]); + } else { + f(&[0; 62]); + f(&[0; 6]); + f(&[0; 6]); + } +} + +fn f(val: &[u8]) {} + +fn main() {} diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr new file mode 100644 index 00000000000..b170db31b85 --- /dev/null +++ b/tests/ui/if_same_then_else.stderr @@ -0,0 +1,214 @@ +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:31:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | Foo { bar: 42 }; +LL | | 0..10; +... | +LL | | foo(); +LL | | } + | |_____^ + | + = note: `-D clippy::if-same-then-else` implied by `-D warnings` +note: same as this + --> $DIR/if_same_then_else.rs:23:13 + | +LL | if true { + | _____________^ +LL | | Foo { bar: 42 }; +LL | | 0..10; +LL | | ..; +... | +LL | | foo(); +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:69:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | 0.0 +LL | | }; + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:67:21 + | +LL | let _ = if true { + | _____________________^ +LL | | 0.0 +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:76:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | -0.0 +LL | | }; + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:74:21 + | +LL | let _ = if true { + | _____________________^ +LL | | -0.0 +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:92:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | 42 +LL | | }; + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:90:21 + | +LL | let _ = if true { + | _____________________^ +LL | | 42 +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:106:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | for _ in &[42] { +LL | | let foo: &Option<_> = &Some::(42); +... | +LL | | } +LL | | } + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:97:13 + | +LL | if true { + | _____________^ +LL | | for _ in &[42] { +LL | | let foo: &Option<_> = &Some::(42); +LL | | if true { +... | +LL | | } +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:125:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | let bar = if true { 42 } else { 43 }; +LL | | +... | +LL | | bar + 1; +LL | | } + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:118:13 + | +LL | if true { + | _____________^ +LL | | let bar = if true { 42 } else { 43 }; +LL | | +LL | | while foo() { +... | +LL | | bar + 1; +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:155:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | if let Some(a) = Some(42) {} +LL | | } + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:153:13 + | +LL | if true { + | _____________^ +LL | | if let Some(a) = Some(42) {} +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:162:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | } + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:160:13 + | +LL | if true { + | _____________^ +LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:212:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | std::f32::NAN +LL | | }; + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:210:21 + | +LL | let _ = if true { + | _____________________^ +LL | | std::f32::NAN +LL | | } else { + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:219:12 + | +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block +LL | | try!(Ok("foo")); +LL | | } + | |_____^ + | +note: same as this + --> $DIR/if_same_then_else.rs:217:13 + | +LL | if true { + | _____________^ +LL | | try!(Ok("foo")); +LL | | } else { + | |_____^ + +error: aborting due to 10 previous errors + -- cgit 1.4.1-3-g733a5 From 8abdfb6567a1b5d5a054cb470e88396ffc3ca4bb Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 10 Feb 2019 10:20:28 +0100 Subject: UI test cleanup: Rename copies.rs to match_same_arms.rs --- tests/ui/copies.rs | 113 ------------------------------- tests/ui/copies.stderr | 143 ---------------------------------------- tests/ui/match_same_arms.rs | 113 +++++++++++++++++++++++++++++++ tests/ui/match_same_arms.stderr | 143 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 256 deletions(-) delete mode 100644 tests/ui/copies.rs delete mode 100644 tests/ui/copies.stderr create mode 100644 tests/ui/match_same_arms.rs create mode 100644 tests/ui/match_same_arms.stderr diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs deleted file mode 100644 index a1f15c0268b..00000000000 --- a/tests/ui/copies.rs +++ /dev/null @@ -1,113 +0,0 @@ -#![allow( - clippy::blacklisted_name, - clippy::collapsible_if, - clippy::cyclomatic_complexity, - clippy::eq_op, - clippy::needless_continue, - clippy::needless_return, - clippy::no_effect, - clippy::zero_divided_by_zero, - clippy::unused_unit -)] - -fn bar(_: T) {} -fn foo() -> bool { - unimplemented!() -} - -pub enum Abc { - A, - B, - C, -} - -#[warn(clippy::match_same_arms)] -#[allow(clippy::unused_unit)] -fn match_same_arms() { - let _ = match 42 { - 42 => { - foo(); - let mut a = 42 + [23].len() as i32; - if true { - a += 7; - } - a = -31 - a; - a - }, - _ => { - //~ ERROR match arms have same body - foo(); - let mut a = 42 + [23].len() as i32; - if true { - a += 7; - } - a = -31 - a; - a - }, - }; - - let _ = match Abc::A { - Abc::A => 0, - Abc::B => 1, - _ => 0, //~ ERROR match arms have same body - }; - - let _ = match 42 { - 42 => foo(), - 51 => foo(), //~ ERROR match arms have same body - _ => true, - }; - - let _ = match Some(42) { - Some(_) => 24, - None => 24, //~ ERROR match arms have same body - }; - - let _ = match Some(42) { - Some(foo) => 24, - None => 24, - }; - - let _ = match Some(42) { - Some(42) => 24, - Some(a) => 24, // bindings are different - None => 0, - }; - - let _ = match Some(42) { - Some(a) if a > 0 => 24, - Some(a) => 24, // one arm has a guard - None => 0, - }; - - match (Some(42), Some(42)) { - (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), //~ ERROR match arms have same body - _ => (), - } - - match (Some(42), Some(42)) { - (Some(a), ..) => bar(a), - (.., Some(a)) => bar(a), //~ ERROR match arms have same body - _ => (), - } - - match (1, 2, 3) { - (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body - _ => 0, - }; - - let _ = match Some(()) { - Some(()) => 0.0, - None => -0.0, - }; - - match (Some(42), Some("")) { - (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), // bindings have different types - _ => (), - } -} - -fn main() {} diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr deleted file mode 100644 index f04a7706846..00000000000 --- a/tests/ui/copies.stderr +++ /dev/null @@ -1,143 +0,0 @@ -error: this `match` has identical arm bodies - --> $DIR/copies.rs:37:14 - | -LL | _ => { - | ______________^ -LL | | //~ ERROR match arms have same body -LL | | foo(); -LL | | let mut a = 42 + [23].len() as i32; -... | -LL | | a -LL | | }, - | |_________^ - | - = note: `-D clippy::match-same-arms` implied by `-D warnings` -note: same as this - --> $DIR/copies.rs:28:15 - | -LL | 42 => { - | _______________^ -LL | | foo(); -LL | | let mut a = 42 + [23].len() as i32; -LL | | if true { -... | -LL | | a -LL | | }, - | |_________^ -note: `42` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:28:15 - | -LL | 42 => { - | _______________^ -LL | | foo(); -LL | | let mut a = 42 + [23].len() as i32; -LL | | if true { -... | -LL | | a -LL | | }, - | |_________^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:52:14 - | -LL | _ => 0, //~ ERROR match arms have same body - | ^ - | -note: same as this - --> $DIR/copies.rs:50:19 - | -LL | Abc::A => 0, - | ^ -note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` - --> $DIR/copies.rs:50:19 - | -LL | Abc::A => 0, - | ^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:57:15 - | -LL | 51 => foo(), //~ ERROR match arms have same body - | ^^^^^ - | -note: same as this - --> $DIR/copies.rs:56:15 - | -LL | 42 => foo(), - | ^^^^^ -note: consider refactoring into `42 | 51` - --> $DIR/copies.rs:56:15 - | -LL | 42 => foo(), - | ^^^^^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:63:17 - | -LL | None => 24, //~ ERROR match arms have same body - | ^^ - | -note: same as this - --> $DIR/copies.rs:62:20 - | -LL | Some(_) => 24, - | ^^ -note: consider refactoring into `Some(_) | None` - --> $DIR/copies.rs:62:20 - | -LL | Some(_) => 24, - | ^^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:85:28 - | -LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body - | ^^^^^^ - | -note: same as this - --> $DIR/copies.rs:84:28 - | -LL | (Some(a), None) => bar(a), - | ^^^^^^ -note: consider refactoring into `(Some(a), None) | (None, Some(a))` - --> $DIR/copies.rs:84:28 - | -LL | (Some(a), None) => bar(a), - | ^^^^^^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:91:26 - | -LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body - | ^^^^^^ - | -note: same as this - --> $DIR/copies.rs:90:26 - | -LL | (Some(a), ..) => bar(a), - | ^^^^^^ -note: consider refactoring into `(Some(a), ..) | (.., Some(a))` - --> $DIR/copies.rs:90:26 - | -LL | (Some(a), ..) => bar(a), - | ^^^^^^ - -error: this `match` has identical arm bodies - --> $DIR/copies.rs:97:20 - | -LL | (.., 3) => 42, //~ ERROR match arms have same body - | ^^ - | -note: same as this - --> $DIR/copies.rs:96:23 - | -LL | (1, .., 3) => 42, - | ^^ -note: consider refactoring into `(1, .., 3) | (.., 3)` - --> $DIR/copies.rs:96:23 - | -LL | (1, .., 3) => 42, - | ^^ - -error: aborting due to 7 previous errors - diff --git a/tests/ui/match_same_arms.rs b/tests/ui/match_same_arms.rs new file mode 100644 index 00000000000..a1f15c0268b --- /dev/null +++ b/tests/ui/match_same_arms.rs @@ -0,0 +1,113 @@ +#![allow( + clippy::blacklisted_name, + clippy::collapsible_if, + clippy::cyclomatic_complexity, + clippy::eq_op, + clippy::needless_continue, + clippy::needless_return, + clippy::no_effect, + clippy::zero_divided_by_zero, + clippy::unused_unit +)] + +fn bar(_: T) {} +fn foo() -> bool { + unimplemented!() +} + +pub enum Abc { + A, + B, + C, +} + +#[warn(clippy::match_same_arms)] +#[allow(clippy::unused_unit)] +fn match_same_arms() { + let _ = match 42 { + 42 => { + foo(); + let mut a = 42 + [23].len() as i32; + if true { + a += 7; + } + a = -31 - a; + a + }, + _ => { + //~ ERROR match arms have same body + foo(); + let mut a = 42 + [23].len() as i32; + if true { + a += 7; + } + a = -31 - a; + a + }, + }; + + let _ = match Abc::A { + Abc::A => 0, + Abc::B => 1, + _ => 0, //~ ERROR match arms have same body + }; + + let _ = match 42 { + 42 => foo(), + 51 => foo(), //~ ERROR match arms have same body + _ => true, + }; + + let _ = match Some(42) { + Some(_) => 24, + None => 24, //~ ERROR match arms have same body + }; + + let _ = match Some(42) { + Some(foo) => 24, + None => 24, + }; + + let _ = match Some(42) { + Some(42) => 24, + Some(a) => 24, // bindings are different + None => 0, + }; + + let _ = match Some(42) { + Some(a) if a > 0 => 24, + Some(a) => 24, // one arm has a guard + None => 0, + }; + + match (Some(42), Some(42)) { + (Some(a), None) => bar(a), + (None, Some(a)) => bar(a), //~ ERROR match arms have same body + _ => (), + } + + match (Some(42), Some(42)) { + (Some(a), ..) => bar(a), + (.., Some(a)) => bar(a), //~ ERROR match arms have same body + _ => (), + } + + match (1, 2, 3) { + (1, .., 3) => 42, + (.., 3) => 42, //~ ERROR match arms have same body + _ => 0, + }; + + let _ = match Some(()) { + Some(()) => 0.0, + None => -0.0, + }; + + match (Some(42), Some("")) { + (Some(a), None) => bar(a), + (None, Some(a)) => bar(a), // bindings have different types + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/match_same_arms.stderr b/tests/ui/match_same_arms.stderr new file mode 100644 index 00000000000..9389e48a3e4 --- /dev/null +++ b/tests/ui/match_same_arms.stderr @@ -0,0 +1,143 @@ +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:37:14 + | +LL | _ => { + | ______________^ +LL | | //~ ERROR match arms have same body +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +... | +LL | | a +LL | | }, + | |_________^ + | + = note: `-D clippy::match-same-arms` implied by `-D warnings` +note: same as this + --> $DIR/match_same_arms.rs:28:15 + | +LL | 42 => { + | _______________^ +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { +... | +LL | | a +LL | | }, + | |_________^ +note: `42` has the same arm body as the `_` wildcard, consider removing it` + --> $DIR/match_same_arms.rs:28:15 + | +LL | 42 => { + | _______________^ +LL | | foo(); +LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { +... | +LL | | a +LL | | }, + | |_________^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:52:14 + | +LL | _ => 0, //~ ERROR match arms have same body + | ^ + | +note: same as this + --> $DIR/match_same_arms.rs:50:19 + | +LL | Abc::A => 0, + | ^ +note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it` + --> $DIR/match_same_arms.rs:50:19 + | +LL | Abc::A => 0, + | ^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:57:15 + | +LL | 51 => foo(), //~ ERROR match arms have same body + | ^^^^^ + | +note: same as this + --> $DIR/match_same_arms.rs:56:15 + | +LL | 42 => foo(), + | ^^^^^ +note: consider refactoring into `42 | 51` + --> $DIR/match_same_arms.rs:56:15 + | +LL | 42 => foo(), + | ^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:63:17 + | +LL | None => 24, //~ ERROR match arms have same body + | ^^ + | +note: same as this + --> $DIR/match_same_arms.rs:62:20 + | +LL | Some(_) => 24, + | ^^ +note: consider refactoring into `Some(_) | None` + --> $DIR/match_same_arms.rs:62:20 + | +LL | Some(_) => 24, + | ^^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:85:28 + | +LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | +note: same as this + --> $DIR/match_same_arms.rs:84:28 + | +LL | (Some(a), None) => bar(a), + | ^^^^^^ +note: consider refactoring into `(Some(a), None) | (None, Some(a))` + --> $DIR/match_same_arms.rs:84:28 + | +LL | (Some(a), None) => bar(a), + | ^^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:91:26 + | +LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body + | ^^^^^^ + | +note: same as this + --> $DIR/match_same_arms.rs:90:26 + | +LL | (Some(a), ..) => bar(a), + | ^^^^^^ +note: consider refactoring into `(Some(a), ..) | (.., Some(a))` + --> $DIR/match_same_arms.rs:90:26 + | +LL | (Some(a), ..) => bar(a), + | ^^^^^^ + +error: this `match` has identical arm bodies + --> $DIR/match_same_arms.rs:97:20 + | +LL | (.., 3) => 42, //~ ERROR match arms have same body + | ^^ + | +note: same as this + --> $DIR/match_same_arms.rs:96:23 + | +LL | (1, .., 3) => 42, + | ^^ +note: consider refactoring into `(1, .., 3) | (.., 3)` + --> $DIR/match_same_arms.rs:96:23 + | +LL | (1, .., 3) => 42, + | ^^ + +error: aborting due to 7 previous errors + -- cgit 1.4.1-3-g733a5 From 1eeda35118096ef74096f07fd6f9624313dd98b7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 10 Feb 2019 10:48:24 +0100 Subject: rustfmt --- tests/ui/if_same_then_else.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index c054e39811c..eef2ef14117 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -8,7 +8,7 @@ clippy::never_loop, clippy::no_effect, clippy::zero_divided_by_zero, - clippy::unused_unit, + clippy::unused_unit )] struct Foo { -- cgit 1.4.1-3-g733a5 From b38c587b98059d002babb3023820061d0e03c5cf Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sun, 10 Feb 2019 12:58:51 +0100 Subject: redundant closure implemented for closures containing method calls --- clippy_lints/src/eta_reduction.rs | 165 ++++++++++++++++++++++++++++---------- tests/ui/eta.rs | 54 +++++++++++++ tests/ui/eta.stderr | 48 +++++++++-- 3 files changed, 219 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 4dbb390cd50..83aca243275 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; +use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then, type_is_unsafe_function}; +use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; @@ -59,56 +60,136 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) { if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node { let body = cx.tcx.hir().body(eid); let ex = &body.value; - if let ExprKind::Call(ref caller, ref args) = ex.node { - if args.len() != decl.inputs.len() { - // Not the same number of arguments, there - // is no way the closure is the same as the function - return; - } - if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { - // Are the expression or the arguments type-adjusted? Then we need the closure - return; - } + + if_chain!( + if let ExprKind::Call(ref caller, ref args) = ex.node; + + // Not the same number of arguments, there is no way the closure is the same as the function return; + if args.len() == decl.inputs.len(); + + // Are the expression or the arguments type-adjusted? Then we need the closure + if !(is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg))); + let fn_ty = cx.tables.expr_ty(caller); - match fn_ty.sty { - // Is it an unsafe function? They don't implement the closure traits - ty::FnDef(..) | ty::FnPtr(_) => { - let sig = fn_ty.fn_sig(cx.tcx); - if sig.skip_binder().unsafety == Unsafety::Unsafe || sig.skip_binder().output().sty == ty::Never { - return; + if !type_is_unsafe_function(cx, fn_ty); + + if compare_inputs(&mut iter_input_pats(decl, body), &mut args.into_iter()); + + then { + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { + if let Some(snippet) = snippet_opt(cx, caller.span) { + db.span_suggestion( + expr.span, + "remove closure as shown", + snippet, + Applicability::MachineApplicable, + ); } - }, - _ => (), + }); } - for (a1, a2) in iter_input_pats(decl, body).zip(args) { - if let PatKind::Binding(.., ident, _) = a1.pat.node { - // XXXManishearth Should I be checking the binding mode here? - if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node { - if p.segments.len() != 1 { - // If it's a proper path, it can't be a local variable - return; - } - if p.segments[0].ident.name != ident.name { - // The two idents should be the same - return; - } - } else { - return; - } - } else { - return; - } - } - span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { - if let Some(snippet) = snippet_opt(cx, caller.span) { + ); + + if_chain!( + if let ExprKind::MethodCall(ref path, _, ref args) = ex.node; + + // Not the same number of arguments, there is no way the closure is the same as the function return; + if args.len() == decl.inputs.len(); + + // Are the expression or the arguments type-adjusted? Then we need the closure + if !(is_adjusted(cx, ex) || args.iter().skip(1).any(|arg| is_adjusted(cx, arg))); + + let method_def_id = cx.tables.type_dependent_defs()[ex.hir_id].def_id(); + if !type_is_unsafe_function(cx, cx.tcx.type_of(method_def_id)); + + if compare_inputs(&mut iter_input_pats(decl, body), &mut args.into_iter()); + + if let Some(name) = get_ufcs_type_name(cx, method_def_id, &args[0]); + + then { + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| { db.span_suggestion( expr.span, "remove closure as shown", - snippet, + format!("{}::{}", name, path.ident.name), Applicability::MachineApplicable, ); + }); + } + ); + } +} + +/// Tries to determine the type for universal function call to be used instead of the closure +fn get_ufcs_type_name( + cx: &LateContext<'_, '_>, + method_def_id: def_id::DefId, + self_arg: &Expr, +) -> std::option::Option { + let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0].sty; + let actual_type_of_self = &cx.tables.node_id_to_type(self_arg.hir_id).sty; + + if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) { + //if the method expectes &self, ufcs requires explicit borrowing so closure can't be removed + return match (expected_type_of_self, actual_type_of_self) { + (ty::Ref(_, _, _), ty::Ref(_, _, _)) => Some(cx.tcx.item_path_str(trait_id)), + (l, r) => match (l, r) { + (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _)) => None, + (_, _) => Some(cx.tcx.item_path_str(trait_id)), + }, + }; + } + + cx.tcx.impl_of_method(method_def_id).and_then(|_| { + //a type may implicitly implement other types methods (e.g. Deref) + if match_types(expected_type_of_self, actual_type_of_self) { + return Some(get_type_name(cx, &actual_type_of_self)); + } + None + }) +} + +fn match_types(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool { + match (lhs, rhs) { + (ty::Bool, ty::Bool) + | (ty::Char, ty::Char) + | (ty::Int(_), ty::Int(_)) + | (ty::Uint(_), ty::Uint(_)) + | (ty::Str, ty::Str) => true, + (ty::Ref(_, t1, _), ty::Ref(_, t2, _)) + | (ty::Array(t1, _), ty::Array(t2, _)) + | (ty::Slice(t1), ty::Slice(t2)) => match_types(&t1.sty, &t2.sty), + (ty::Adt(def1, _), ty::Adt(def2, _)) => def1 == def2, + (_, _) => false, + } +} + +fn get_type_name(cx: &LateContext<'_, '_>, kind: &ty::TyKind<'_>) -> String { + match kind { + ty::Adt(t, _) => cx.tcx.item_path_str(t.did), + ty::Ref(_, r, _) => get_type_name(cx, &r.sty), + _ => kind.to_string(), + } +} + +fn compare_inputs(closure_inputs: &mut dyn Iterator, call_args: &mut dyn Iterator) -> bool { + for (closure_input, function_arg) in closure_inputs.zip(call_args) { + if let PatKind::Binding(_, _, _, ident, _) = closure_input.pat.node { + // XXXManishearth Should I be checking the binding mode here? + if let ExprKind::Path(QPath::Resolved(None, ref p)) = function_arg.node { + if p.segments.len() != 1 { + // If it's a proper path, it can't be a local variable + return false; } - }); + if p.segments[0].ident.name != ident.name { + // The two idents should be the same + return false; + } + } else { + return false; + } + } else { + return false; } } + true } diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index b39de4c15a4..b482d37b186 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -9,6 +9,8 @@ )] #![warn(clippy::redundant_closure, clippy::needless_borrow)] +use std::path::PathBuf; + fn main() { let a = Some(1u8).map(|a| foo(a)); meta(|a| foo(a)); @@ -26,6 +28,57 @@ fn main() { // See #515 let a: Option>> = Some(vec![1i32, 2]).map(|v| -> Box<::std::ops::Deref> { Box::new(v) }); + +} + +trait TestTrait { + fn trait_foo(self) -> bool; + fn trait_foo_ref(&self) -> bool; +} + +struct TestStruct<'a> { + some_ref: &'a i32 +} + +impl<'a> TestStruct<'a> { + fn foo(self) -> bool { false } + unsafe fn foo_unsafe(self) -> bool { true } +} + +impl<'a> TestTrait for TestStruct<'a> { + fn trait_foo(self) -> bool { false } + fn trait_foo_ref(&self) -> bool { false } +} + +impl<'a> std::ops::Deref for TestStruct<'a> { + type Target = char; + fn deref(&self) -> &char { &'a' } +} + +fn test_redundant_closures_containing_method_calls() { + let i = 10; + let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo()); + let e = Some(TestStruct{some_ref: &i}).map(TestStruct::foo); + let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo()); + let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo_ref()); + let e = Some(TestStruct{some_ref: &i}).map(TestTrait::trait_foo); + let e = Some(&mut vec!(1,2,3)).map(|v| v.clear()); + let e = Some(&mut vec!(1,2,3)).map(std::vec::Vec::clear); + unsafe { + let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo_unsafe()); + } + let e = Some("str").map(|s| s.to_string()); + let e = Some("str").map(str::to_string); + let e = Some('a').map(|s| s.to_uppercase()); + let e = Some('a').map(char::to_uppercase); + let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.len_utf8()).collect(); + let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.to_ascii_uppercase()).collect(); + let e: std::vec::Vec = vec!('a','b','c').iter().map(char::to_ascii_uppercase).collect(); + let p = Some(PathBuf::new()); + let e = p.as_ref().and_then(|s| s.to_str()); + //let e = p.as_ref().and_then(std::path::Path::to_str); + let c = Some(TestStruct{some_ref: &i}).as_ref().map(|c| c.to_ascii_uppercase()); + //let c = Some(TestStruct{some_ref: &i}).as_ref().map(char::to_ascii_uppercase); } fn meta(f: F) @@ -61,3 +114,4 @@ fn divergent(_: u8) -> ! { fn generic(_: T) -> u8 { 0 } + diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 218e46b40a8..7d355f7215c 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure found - --> $DIR/eta.rs:13:27 + --> $DIR/eta.rs:15:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` @@ -7,19 +7,19 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:14:10 + --> $DIR/eta.rs:16:10 | LL | meta(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` error: redundant closure found - --> $DIR/eta.rs:15:27 + --> $DIR/eta.rs:17:27 | LL | let c = Some(1u8).map(|a| {1+2; foo}(a)); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `{1+2; foo}` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/eta.rs:17:21 + --> $DIR/eta.rs:19:21 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` @@ -27,10 +27,46 @@ LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:24:27 + --> $DIR/eta.rs:26:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` -error: aborting due to 5 previous errors +error: redundant closure found + --> $DIR/eta.rs:60:48 + | +LL | let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo()); + | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` + +error: redundant closure found + --> $DIR/eta.rs:62:48 + | +LL | let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo()); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` + +error: redundant closure found + --> $DIR/eta.rs:65:40 + | +LL | let e = Some(&mut vec!(1,2,3)).map(|v| v.clear()); + | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` + +error: redundant closure found + --> $DIR/eta.rs:70:29 + | +LL | let e = Some("str").map(|s| s.to_string()); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `std::string::ToString::to_string` + +error: redundant closure found + --> $DIR/eta.rs:72:27 + | +LL | let e = Some('a').map(|s| s.to_uppercase()); + | ^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_uppercase` + +error: redundant closure found + --> $DIR/eta.rs:75:63 + | +LL | let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.to_ascii_uppercase()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` + +error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 16881390e1f1d7cbf2737e0d78560d4eaa3bb8c1 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sun, 10 Feb 2019 13:35:44 +0100 Subject: removing redundant closures in the whole project --- clippy_dev/src/lib.rs | 4 ++-- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/mod.rs | 5 ++++- rustc_tools_util/src/lib.rs | 4 ++-- src/driver.rs | 4 ++-- tests/missing-test-files.rs | 2 +- tests/ui/map_clone.fixed | 1 + tests/ui/map_clone.rs | 1 + tests/ui/map_clone.stderr | 8 ++++---- 14 files changed, 24 insertions(+), 19 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 1c7f372af6b..7fad43029ac 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -47,7 +47,7 @@ impl Lint { name: name.to_lowercase(), group: group.to_string(), desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), - deprecation: deprecation.map(|d| d.to_string()), + deprecation: deprecation.map(std::string::ToString::to_string), module: module.to_string(), } } @@ -178,7 +178,7 @@ fn lint_files() -> impl Iterator { // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. WalkDir::new("../clippy_lints/src") .into_iter() - .filter_map(|f| f.ok()) + .filter_map(std::result::Result::ok) .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 89dbba56130..a72944bbe02 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -326,7 +326,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { lint.span, &format!("unknown clippy lint: clippy::{}", name), |db| { - if name.as_str().chars().any(|c| c.is_uppercase()) { + if name.as_str().chars().any(char::is_uppercase) { let name_lower = name.as_str().to_lowercase(); match lint_store.check_lint_name( &name_lower, diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 124b11cc78c..1d37c03ff45 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -53,7 +53,7 @@ fn is_empty_str(value: &Option) -> bool { fn is_empty_vec(value: &[String]) -> bool { // This works because empty iterators return true - value.iter().all(|v| v.is_empty()) + value.iter().all(std::string::String::is_empty) } pub struct Pass; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5a9364eddb6..759b3173978 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -267,7 +267,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { } }); - let (conf, errors) = utils::conf::read(file_name.as_ref().map(|p| p.as_ref())); + let (conf, errors) = utils::conf::read(file_name.as_ref().map(std::convert::AsRef::as_ref)); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4ce2ae03b9f..c9b27ef1615 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let (method_names, arg_lists) = method_calls(expr, 2); let method_names: Vec = method_names.iter().map(|s| s.as_str()).collect(); - let method_names: Vec<&str> = method_names.iter().map(|s| s.as_ref()).collect(); + let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect(); match method_names.as_slice() { ["unwrap", "get"] => lint_get_unwrap(cx, expr, arg_lists[1], false), @@ -1695,7 +1695,7 @@ fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Op if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.node { if path.ident.name == "iter" && may_slice(cx, cx.tables.expr_ty(&args[0])) { - sugg::Sugg::hir_opt(cx, &args[0]).map(|sugg| sugg.addr()) + sugg::Sugg::hir_opt(cx, &args[0]).map(sugg::Sugg::addr) } else { None } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index fbf60db28ee..b1cd1910f5b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -241,7 +241,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { // or too many chars differ (x_foo, y_boo) or (xfoo, yboo) continue; } - split_at = interned_name.chars().next().map(|c| c.len_utf8()); + split_at = interned_name.chars().next().map(char::len_utf8); } } span_lint_and_then( diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index b0b4394ebb8..ff802dbb3a8 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -14,7 +14,7 @@ use toml; pub fn file_from_args( args: &[source_map::Spanned], ) -> Result, (&'static str, source_map::Span)> { - for arg in args.iter().filter_map(|a| a.meta_item()) { + for arg in args.iter().filter_map(syntax::source_map::Spanned::meta_item) { if arg.name() == "conf_file" { return match arg.node { ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a8b6a756b78..b5221bca007 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -142,7 +142,10 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> { let mut apb = AbsolutePathBuffer { names: vec![] }; tcx.push_item_path(&mut apb, def_id, false); - apb.names.iter().map(|n| n.get()).collect() + apb.names + .iter() + .map(syntax_pos::symbol::LocalInternedString::get) + .collect() } /// Check if type is struct, enum or union type with given def path. diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index f13fa12ccca..19c27754839 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -9,8 +9,8 @@ macro_rules! get_version_info { let crate_name = String::from(env!("CARGO_PKG_NAME")); let host_compiler = $crate::get_channel(); - let commit_hash = option_env!("GIT_HASH").map(|s| s.to_string()); - let commit_date = option_env!("COMMIT_DATE").map(|s| s.to_string()); + let commit_hash = option_env!("GIT_HASH").map(str::to_string); + let commit_date = option_env!("COMMIT_DATE").map(str::to_string); VersionInfo { major, diff --git a/src/driver.rs b/src/driver.rs index fbff693f887..34fc6fc7f9f 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -47,7 +47,7 @@ fn arg_value<'a>( fn test_arg_value() { let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"] .iter() - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .collect(); assert_eq!(arg_value(None, "--foobar", |_| true), None); @@ -84,7 +84,7 @@ pub fn main() { let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); let have_sys_root_arg = sys_root_arg.is_some(); let sys_root = sys_root_arg - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .or_else(|| std::env::var("SYSROOT").ok()) .or_else(|| { let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index bd0cee75644..d87bb4be3c3 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -32,7 +32,7 @@ fn explore_directory(dir: &Path) -> Vec { let mut missing_files: Vec = Vec::new(); let mut current_file = String::new(); let mut files: Vec = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect(); - files.sort_by_key(|e| e.path()); + files.sort_by_key(std::fs::DirEntry::path); for entry in &files { let path = entry.path(); if path.is_dir() { diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index af417815ed1..d804e838d5a 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -3,6 +3,7 @@ #![allow(clippy::iter_cloned_collect)] #![allow(clippy::clone_on_copy)] #![allow(clippy::missing_docs_in_private_items)] +#![allow(clippy::redundant_closure)] fn main() { let _: Vec = vec![5_i8; 6].iter().cloned().collect(); diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 7dd2ce30202..d98cd939d8c 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -3,6 +3,7 @@ #![allow(clippy::iter_cloned_collect)] #![allow(clippy::clone_on_copy)] #![allow(clippy::missing_docs_in_private_items)] +#![allow(clippy::redundant_closure)] fn main() { let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 504f4a01a4c..db7fa4f52fc 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:8:22 + --> $DIR/map_clone.rs:9:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` @@ -7,19 +7,19 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:9:26 + --> $DIR/map_clone.rs:10:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: You are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:10:23 + --> $DIR/map_clone.rs:11:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` error: You are needlessly cloning iterator elements - --> $DIR/map_clone.rs:22:29 + --> $DIR/map_clone.rs:23:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: Remove the map call -- cgit 1.4.1-3-g733a5 From f7c0df9183f194f60b541965b3aac3e034a400d9 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sun, 10 Feb 2019 21:23:04 +0100 Subject: test formatting --- tests/ui/eta.rs | 52 ++++++++++++++++++++++++++++++---------------------- tests/ui/eta.stderr | 28 ++++++++++++++-------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index b482d37b186..6eeb093eae9 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -28,7 +28,6 @@ fn main() { // See #515 let a: Option>> = Some(vec![1i32, 2]).map(|v| -> Box<::std::ops::Deref> { Box::new(v) }); - } trait TestTrait { @@ -37,48 +36,58 @@ trait TestTrait { } struct TestStruct<'a> { - some_ref: &'a i32 + some_ref: &'a i32, } impl<'a> TestStruct<'a> { - fn foo(self) -> bool { false } - unsafe fn foo_unsafe(self) -> bool { true } + fn foo(self) -> bool { + false + } + unsafe fn foo_unsafe(self) -> bool { + true + } } impl<'a> TestTrait for TestStruct<'a> { - fn trait_foo(self) -> bool { false } - fn trait_foo_ref(&self) -> bool { false } + fn trait_foo(self) -> bool { + false + } + fn trait_foo_ref(&self) -> bool { + false + } } impl<'a> std::ops::Deref for TestStruct<'a> { type Target = char; - fn deref(&self) -> &char { &'a' } + fn deref(&self) -> &char { + &'a' + } } fn test_redundant_closures_containing_method_calls() { let i = 10; - let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo()); - let e = Some(TestStruct{some_ref: &i}).map(TestStruct::foo); - let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo()); - let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo_ref()); - let e = Some(TestStruct{some_ref: &i}).map(TestTrait::trait_foo); - let e = Some(&mut vec!(1,2,3)).map(|v| v.clear()); - let e = Some(&mut vec!(1,2,3)).map(std::vec::Vec::clear); + let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); + let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); + let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); + let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); + let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); + let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); + let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); unsafe { - let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo_unsafe()); + let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); } let e = Some("str").map(|s| s.to_string()); let e = Some("str").map(str::to_string); let e = Some('a').map(|s| s.to_uppercase()); let e = Some('a').map(char::to_uppercase); - let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.len_utf8()).collect(); - let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.to_ascii_uppercase()).collect(); - let e: std::vec::Vec = vec!('a','b','c').iter().map(char::to_ascii_uppercase).collect(); + let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); + let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); + let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); let p = Some(PathBuf::new()); let e = p.as_ref().and_then(|s| s.to_str()); - //let e = p.as_ref().and_then(std::path::Path::to_str); - let c = Some(TestStruct{some_ref: &i}).as_ref().map(|c| c.to_ascii_uppercase()); - //let c = Some(TestStruct{some_ref: &i}).as_ref().map(char::to_ascii_uppercase); + let c = Some(TestStruct { some_ref: &i }) + .as_ref() + .map(|c| c.to_ascii_uppercase()); } fn meta(f: F) @@ -114,4 +123,3 @@ fn divergent(_: u8) -> ! { fn generic(_: T) -> u8 { 0 } - diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 7d355f7215c..5f56cd7912a 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -33,40 +33,40 @@ LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: redundant closure found - --> $DIR/eta.rs:60:48 + --> $DIR/eta.rs:69:51 | -LL | let e = Some(TestStruct{some_ref: &i}).map(|a| a.foo()); - | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` +LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); + | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` error: redundant closure found - --> $DIR/eta.rs:62:48 + --> $DIR/eta.rs:71:51 | -LL | let e = Some(TestStruct{some_ref: &i}).map(|a| a.trait_foo()); - | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` +LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` error: redundant closure found - --> $DIR/eta.rs:65:40 + --> $DIR/eta.rs:74:42 | -LL | let e = Some(&mut vec!(1,2,3)).map(|v| v.clear()); - | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` +LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); + | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` error: redundant closure found - --> $DIR/eta.rs:70:29 + --> $DIR/eta.rs:79:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `std::string::ToString::to_string` error: redundant closure found - --> $DIR/eta.rs:72:27 + --> $DIR/eta.rs:81:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_uppercase` error: redundant closure found - --> $DIR/eta.rs:75:63 + --> $DIR/eta.rs:84:65 | -LL | let e: std::vec::Vec = vec!('a','b','c').iter().map(|c| c.to_ascii_uppercase()).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` +LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` error: aborting due to 11 previous errors -- cgit 1.4.1-3-g733a5 From 217965e85527f1caf99e86153f11f676f778a360 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 11 Feb 2019 07:03:12 +0200 Subject: Fix `needless_range_loop` bad suggestion Detect if the index variable is used inside a closure. Fixes #2542 --- clippy_lints/src/loops.rs | 30 +++++++++++++++++++++++------- tests/ui/needless_range_loop.rs | 5 +++++ tests/ui/needless_range_loop.stderr | 12 +++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index dcd1a4e0a61..99ed9fc86fd 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1830,17 +1830,29 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if let ExprKind::Path(ref qpath) = expr.node; if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; - if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id); then { - if local_id == self.var { - // we are not indexing anything, record that - self.nonindex = true; - } else { - // not the correct variable, but still a variable - self.referenced.insert(path.segments[0].ident.name); + match self.cx.tables.qpath_def(qpath, expr.hir_id) { + Def::Upvar(local_id, ..) => { + if local_id == self.var { + // we are not indexing anything, record that + self.nonindex = true; + } + } + Def::Local(local_id) => + { + + if local_id == self.var { + self.nonindex = true; + } else { + // not the correct variable, but still a variable + self.referenced.insert(path.segments[0].ident.name); + } + } + _ => {} } } } + let old = self.prefer_mutable; match expr.node { ExprKind::AssignOp(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs) => { @@ -1880,6 +1892,10 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { self.visit_expr(expr); } }, + ExprKind::Closure(_, _, body_id, ..) => { + let body = self.cx.tcx.hir().body(body_id); + self.visit_expr(&body.value); + }, _ => walk_expr(self, expr), } self.prefer_mutable = old; diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index a073cc0cfa3..5f22e2645d1 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -80,4 +80,9 @@ fn main() { for i in 1..3 { println!("{}", arr[i]); } + + // #2542 + for i in 0..vec.len() { + vec[i] = Some(1).unwrap_or_else(|| panic!("error on {}", i)); + } } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 7044fc17617..d1cc9b3ce72 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -80,5 +80,15 @@ help: consider using an iterator LL | for in arr.iter().skip(1) { | ^^^^^^ ^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: the loop variable `i` is used to index `vec` + --> $DIR/needless_range_loop.rs:85:14 + | +LL | for i in 0..vec.len() { + | ^^^^^^^^^^^^ +help: consider using an iterator + | +LL | for (i, ) in vec.iter_mut().enumerate() { + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From a27022e0dcce519963db69231d4d866ba0de7b8b Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 11 Feb 2019 07:35:28 +0100 Subject: Document `declare_clippy_lint` macro Split up from my work on updating CONTRIBUTING.md, which is slowly making progress. cc #2666 --- clippy_lints/src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5a9364eddb6..5a5f968a2cf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -37,8 +37,53 @@ extern crate syntax_pos; use toml; -// Currently, categories "style", "correctness", "complexity" and "perf" are enabled by default, -// as said in the README.md of this repository. If this changes, please update README.md. +/// Macro used to declare a Clippy lint. +/// +/// Every lint declaration consists of 4 parts: +/// +/// 1. The documentation above the lint, which is used for the website +/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions. +/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or +/// `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of. +/// 4. The `description` that contains a short explanation on what's wrong with code where the +/// lint is triggered. +/// +/// Currently the categories `style`, `correctness`, `complexity` and `perf` are enabled by default. +/// As said in the README.md of this repository, if the lint level mapping changes, please update +/// README.md. +/// +/// # Example +/// +/// ``` +/// # #![feature(rustc_private)] +/// # #[allow(unused_extern_crates)] +/// # extern crate rustc; +/// # #[macro_use] +/// # use clippy_lints::declare_clippy_lint; +/// use rustc::declare_tool_lint; +/// +/// /// **What it does:** Checks for ... (describe what the lint matches). +/// /// +/// /// **Why is this bad?** Supply the reason for linting the code. +/// /// +/// /// **Known problems:** None. (Or describe where it could go wrong.) +/// /// +/// /// **Example:** +/// /// +/// /// ```rust +/// /// // Bad +/// /// Insert a short example of code that triggers the lint +/// /// +/// /// // Good +/// /// Insert a short example of improved code that doesn't trigger the lint +/// /// ``` +/// declare_clippy_lint! { +/// pub LINT_NAME, +/// pedantic, +/// "description" +/// } +/// ``` +/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints #[macro_export] macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { -- cgit 1.4.1-3-g733a5 From 7d3983216fae04263ae244a3741e9f7bfbbbfa96 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 11 Feb 2019 07:59:57 +0100 Subject: Document some more core functions --- clippy_lints/src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5a5f968a2cf..56c994b5c26 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -256,6 +256,14 @@ mod reexport { crate use syntax::ast::{Name, NodeId}; } +/// Register all pre expansion lints +/// +/// Pre-expansion lints run before any macro expansion has happened. +/// +/// Note that due to the architechture of the compiler, currently `cfg_attr` attributes will still +/// be expanded even when using a pre-expansion pass. +/// +/// Used in `./src/driver.rs`. pub fn register_pre_expansion_lints( session: &rustc::session::Session, store: &mut rustc::lint::LintStore, @@ -280,6 +288,7 @@ pub fn register_pre_expansion_lints( store.register_pre_expansion_pass(Some(session), true, false, box dbg_macro::Pass); } +#[doc(hidden)] pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { match utils::conf::file_from_args(reg.args()) { Ok(file_name) => { @@ -337,6 +346,9 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { } } +/// Register all lints and lint groups with the rustc plugin registry +/// +/// Used in `./src/driver.rs`. #[allow(clippy::too_many_lines)] #[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { @@ -1091,6 +1103,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ]); } +/// Register renamed lints. +/// +/// Used in `./src/driver.rs`. pub fn register_renamed(ls: &mut rustc::lint::LintStore) { ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions"); ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); -- cgit 1.4.1-3-g733a5 From a14247b50086eed81916a3e78112879614abb8fa Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 11 Feb 2019 22:32:54 +0100 Subject: Update comment regarding crate level cfg_attr --- clippy_lints/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 56c994b5c26..2f114c065bb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -260,8 +260,8 @@ mod reexport { /// /// Pre-expansion lints run before any macro expansion has happened. /// -/// Note that due to the architechture of the compiler, currently `cfg_attr` attributes will still -/// be expanded even when using a pre-expansion pass. +/// Note that due to the architechture of the compiler, currently `cfg_attr` attributes on crate +/// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass. /// /// Used in `./src/driver.rs`. pub fn register_pre_expansion_lints( -- cgit 1.4.1-3-g733a5 From 5a3cd31c9ed76033319a5cb63cbd0acf3d1c43a9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 13 Feb 2019 22:06:19 +0100 Subject: Rustup cc rust-lang/rust#58137 --- clippy_lints/src/cyclomatic_complexity.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/lib.rs | 1 - clippy_lints/src/loops.rs | 6 +++--- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index c6358aed4bd..6c5c5ecbb02 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -78,7 +78,7 @@ impl CyclomaticComplexity { returns, .. } = helper; - let ret_ty = cx.tables.node_id_to_type(expr.hir_id); + let ret_ty = cx.tables.node_type(expr.hir_id); let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { returns } else { @@ -159,7 +159,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { }, ExprKind::Call(ref callee, _) => { walk_expr(self, e); - let ty = self.cx.tables.node_id_to_type(callee.hir_id); + let ty = self.cx.tables.node_type(callee.hir_id); match ty.sty { ty::FnDef(..) | ty::FnPtr(_) => { let sig = ty.fn_sig(self.cx.tcx); diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 83aca243275..87a82b2a169 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -126,7 +126,7 @@ fn get_ufcs_type_name( self_arg: &Expr, ) -> std::option::Option { let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0].sty; - let actual_type_of_self = &cx.tables.node_id_to_type(self_arg.hir_id).sty; + let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id).sty; if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) { //if the method expectes &self, ufcs requires explicit borrowing so closure can't be removed diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 88224763f0c..d0032fe78fc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -5,7 +5,6 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(range_contains)] -#![feature(str_escape)] #![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 99ed9fc86fd..058d9adcb51 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1781,7 +1781,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, - (Some(extent), self.cx.tables.node_id_to_type(seqexpr.hir_id)), + (Some(extent), self.cx.tables.node_type(seqexpr.hir_id)), ); } return false; // no need to walk further *on the variable* @@ -1793,7 +1793,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, - (None, self.cx.tables.node_id_to_type(seqexpr.hir_id)), + (None, self.cx.tables.node_type(seqexpr.hir_id)), ); } return false; // no need to walk further *on the variable* @@ -2418,7 +2418,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx> if let Some(ref generic_args) = chain_method.args; if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); then { - let ty = cx.tables.node_id_to_type(ty.hir_id); + let ty = cx.tables.node_type(ty.hir_id); if match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) || match_type(cx, ty, &paths::BTREEMAP) || diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 722f64405c7..9adac2f6d7f 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -156,7 +156,7 @@ fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, binding } fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { - let var_ty = cx.tables.node_id_to_type(pat_id); + let var_ty = cx.tables.node_type(pat_id); match var_ty.sty { ty::Adt(..) => false, _ => true, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 461bd20b80c..79e9f4f27d2 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2343,7 +2343,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node; if let ExprKind::Cast(e, t) = &e.node; if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node; - if let ty::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty; + if let ty::Ref(..) = cx.tables.node_type(e.hir_id).sty; then { span_lint( cx, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 508bf26bab9..7df1b0eb0e3 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match stmt.node { hir::StmtKind::Local(ref local) => { - println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id)); + println!("local variable of type {}", cx.tables.node_type(local.hir_id)); println!("pattern:"); print_pat(cx, &local.pat, 0); if let Some(ref e) = local.init { -- cgit 1.4.1-3-g733a5 From 533dd360d79dc06ba857e702a4362d8aa272cdd4 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 14 Feb 2019 08:55:50 +0200 Subject: Fix breakage due to rust-lang/rust#58167 --- clippy_lints/src/cyclomatic_complexity.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 6c5c5ecbb02..76b342089bc 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -94,7 +94,7 @@ impl CyclomaticComplexity { short_circuits, ret_adjust, span, - body.id().node_id, + body.id().hir_id, ); } else { let mut rust_cc = cc + divergence - match_arms - short_circuits; @@ -197,7 +197,7 @@ fn report_cc_bug( shorts: u64, returns: u64, span: Span, - _: NodeId, + _: HirId, ) { span_bug!( span, @@ -220,9 +220,10 @@ fn report_cc_bug( shorts: u64, returns: u64, span: Span, - id: NodeId, + id: HirId, ) { - if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) { + let node_id = cx.tcx.hir().hir_to_node_id(id); + if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, node_id) { cx.sess().span_note_without_error( span, &format!( -- cgit 1.4.1-3-g733a5 From 10811d5d89fc8a40c74c9d34173cccaacdf32ae2 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 14 Feb 2019 14:01:43 +0100 Subject: Fix breakage from rust-lang/rust#58296 --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b5221bca007..0816c209a42 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -17,7 +17,7 @@ use rustc::ty::{ Binder, Ty, TyCtxt, }; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; +use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart, SuggestionStyle}; use std::borrow::Cow; use std::env; use std::mem; @@ -745,7 +745,7 @@ where .collect(), }], msg: help_msg, - show_code_when_inline: true, + style: SuggestionStyle::ShowCode, applicability: Applicability::Unspecified, }; db.suggestions.push(sugg); -- cgit 1.4.1-3-g733a5 From 67f50661eb02dc9cd4a4ae6917ce10127f3316c9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 16 Feb 2019 13:16:50 -0700 Subject: Use normal HTML label semantics for filter I legitimately don't understand why you did it with ARIA instead. --- util/gh-pages/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 1a8495951a4..6cbbeea0644 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -76,8 +76,8 @@
- Filter: - + +